source: trunk/poppler/mypoppler/poppler/JBIG2Stream.cc @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 16 years ago

First import

File size: 86.2 KB
Line 
1//========================================================================
2//
3// JBIG2Stream.cc
4//
5// Copyright 2002-2003 Glyph & Cog, LLC
6//
7//========================================================================
8
9#include <config.h>
10
11#ifdef USE_GCC_PRAGMAS
12#pragma implementation
13#endif
14
15#include <stdlib.h>
16#include <limits.h>
17#include "goo/GooList.h"
18#include "Error.h"
19#include "JArithmeticDecoder.h"
20#include "JBIG2Stream.h"
21
22//~ share these tables
23#include "Stream-CCITT.h"
24
25//------------------------------------------------------------------------
26
27static int contextSize[4] = { 16, 13, 10, 10 };
28static int refContextSize[2] = { 13, 10 };
29
30//------------------------------------------------------------------------
31// JBIG2HuffmanTable
32//------------------------------------------------------------------------
33
34#define jbig2HuffmanLOW 0xfffffffd
35#define jbig2HuffmanOOB 0xfffffffe
36#define jbig2HuffmanEOT 0xffffffff
37
38struct JBIG2HuffmanTable {
39  int val;
40  Guint prefixLen;
41  Guint rangeLen;               // can also be LOW, OOB, or EOT
42  Guint prefix;
43};
44
45JBIG2HuffmanTable huffTableA[] = {
46  {     0, 1,  4,              0x000 },
47  {    16, 2,  8,              0x002 },
48  {   272, 3, 16,              0x006 },
49  { 65808, 3, 32,              0x007 },
50  {     0, 0, jbig2HuffmanEOT, 0     }
51};
52
53JBIG2HuffmanTable huffTableB[] = {
54  {     0, 1,  0,              0x000 },
55  {     1, 2,  0,              0x002 },
56  {     2, 3,  0,              0x006 },
57  {     3, 4,  3,              0x00e },
58  {    11, 5,  6,              0x01e },
59  {    75, 6, 32,              0x03e },
60  {     0, 6, jbig2HuffmanOOB, 0x03f },
61  {     0, 0, jbig2HuffmanEOT, 0     }
62};
63
64JBIG2HuffmanTable huffTableC[] = {
65  {     0, 1,  0,              0x000 },
66  {     1, 2,  0,              0x002 },
67  {     2, 3,  0,              0x006 },
68  {     3, 4,  3,              0x00e },
69  {    11, 5,  6,              0x01e },
70  {     0, 6, jbig2HuffmanOOB, 0x03e },
71  {    75, 7, 32,              0x0fe },
72  {  -256, 8,  8,              0x0fe },
73  {  -257, 8, jbig2HuffmanLOW, 0x0ff },
74  {     0, 0, jbig2HuffmanEOT, 0     }
75};
76
77JBIG2HuffmanTable huffTableD[] = {
78  {     1, 1,  0,              0x000 },
79  {     2, 2,  0,              0x002 },
80  {     3, 3,  0,              0x006 },
81  {     4, 4,  3,              0x00e },
82  {    12, 5,  6,              0x01e },
83  {    76, 5, 32,              0x01f },
84  {     0, 0, jbig2HuffmanEOT, 0     }
85};
86
87JBIG2HuffmanTable huffTableE[] = {
88  {     1, 1,  0,              0x000 },
89  {     2, 2,  0,              0x002 },
90  {     3, 3,  0,              0x006 },
91  {     4, 4,  3,              0x00e },
92  {    12, 5,  6,              0x01e },
93  {    76, 6, 32,              0x03e },
94  {  -255, 7,  8,              0x07e },
95  {  -256, 7, jbig2HuffmanLOW, 0x07f },
96  {     0, 0, jbig2HuffmanEOT, 0     }
97};
98
99JBIG2HuffmanTable huffTableF[] = {
100  {     0, 2,  7,              0x000 },
101  {   128, 3,  7,              0x002 },
102  {   256, 3,  8,              0x003 },
103  { -1024, 4,  9,              0x008 },
104  {  -512, 4,  8,              0x009 },
105  {  -256, 4,  7,              0x00a },
106  {   -32, 4,  5,              0x00b },
107  {   512, 4,  9,              0x00c },
108  {  1024, 4, 10,              0x00d },
109  { -2048, 5, 10,              0x01c },
110  {  -128, 5,  6,              0x01d },
111  {   -64, 5,  5,              0x01e },
112  { -2049, 6, jbig2HuffmanLOW, 0x03e },
113  {  2048, 6, 32,              0x03f },
114  {     0, 0, jbig2HuffmanEOT, 0     }
115};
116
117JBIG2HuffmanTable huffTableG[] = {
118  {  -512, 3,  8,              0x000 },
119  {   256, 3,  8,              0x001 },
120  {   512, 3,  9,              0x002 },
121  {  1024, 3, 10,              0x003 },
122  { -1024, 4,  9,              0x008 },
123  {  -256, 4,  7,              0x009 },
124  {   -32, 4,  5,              0x00a },
125  {     0, 4,  5,              0x00b },
126  {   128, 4,  7,              0x00c },
127  {  -128, 5,  6,              0x01a },
128  {   -64, 5,  5,              0x01b },
129  {    32, 5,  5,              0x01c },
130  {    64, 5,  6,              0x01d },
131  { -1025, 5, jbig2HuffmanLOW, 0x01e },
132  {  2048, 5, 32,              0x01f },
133  {     0, 0, jbig2HuffmanEOT, 0     }
134};
135
136JBIG2HuffmanTable huffTableH[] = {
137  {     0, 2,  1,              0x000 },
138  {     0, 2, jbig2HuffmanOOB, 0x001 },
139  {     4, 3,  4,              0x004 },
140  {    -1, 4,  0,              0x00a },
141  {    22, 4,  4,              0x00b },
142  {    38, 4,  5,              0x00c },
143  {     2, 5,  0,              0x01a },
144  {    70, 5,  6,              0x01b },
145  {   134, 5,  7,              0x01c },
146  {     3, 6,  0,              0x03a },
147  {    20, 6,  1,              0x03b },
148  {   262, 6,  7,              0x03c },
149  {   646, 6, 10,              0x03d },
150  {    -2, 7,  0,              0x07c },
151  {   390, 7,  8,              0x07d },
152  {   -15, 8,  3,              0x0fc },
153  {    -5, 8,  1,              0x0fd },
154  {    -7, 9,  1,              0x1fc },
155  {    -3, 9,  0,              0x1fd },
156  {   -16, 9, jbig2HuffmanLOW, 0x1fe },
157  {  1670, 9, 32,              0x1ff },
158  {     0, 0, jbig2HuffmanEOT, 0     }
159};
160
161JBIG2HuffmanTable huffTableI[] = {
162  {     0, 2, jbig2HuffmanOOB, 0x000 },
163  {    -1, 3,  1,              0x002 },
164  {     1, 3,  1,              0x003 },
165  {     7, 3,  5,              0x004 },
166  {    -3, 4,  1,              0x00a },
167  {    43, 4,  5,              0x00b },
168  {    75, 4,  6,              0x00c },
169  {     3, 5,  1,              0x01a },
170  {   139, 5,  7,              0x01b },
171  {   267, 5,  8,              0x01c },
172  {     5, 6,  1,              0x03a },
173  {    39, 6,  2,              0x03b },
174  {   523, 6,  8,              0x03c },
175  {  1291, 6, 11,              0x03d },
176  {    -5, 7,  1,              0x07c },
177  {   779, 7,  9,              0x07d },
178  {   -31, 8,  4,              0x0fc },
179  {   -11, 8,  2,              0x0fd },
180  {   -15, 9,  2,              0x1fc },
181  {    -7, 9,  1,              0x1fd },
182  {   -32, 9, jbig2HuffmanLOW, 0x1fe },
183  {  3339, 9, 32,              0x1ff },
184  {     0, 0, jbig2HuffmanEOT, 0     }
185};
186
187JBIG2HuffmanTable huffTableJ[] = {
188  {    -2, 2,  2,              0x000 },
189  {     6, 2,  6,              0x001 },
190  {     0, 2, jbig2HuffmanOOB, 0x002 },
191  {    -3, 5,  0,              0x018 },
192  {     2, 5,  0,              0x019 },
193  {    70, 5,  5,              0x01a },
194  {     3, 6,  0,              0x036 },
195  {   102, 6,  5,              0x037 },
196  {   134, 6,  6,              0x038 },
197  {   198, 6,  7,              0x039 },
198  {   326, 6,  8,              0x03a },
199  {   582, 6,  9,              0x03b },
200  {  1094, 6, 10,              0x03c },
201  {   -21, 7,  4,              0x07a },
202  {    -4, 7,  0,              0x07b },
203  {     4, 7,  0,              0x07c },
204  {  2118, 7, 11,              0x07d },
205  {    -5, 8,  0,              0x0fc },
206  {     5, 8,  0,              0x0fd },
207  {   -22, 8, jbig2HuffmanLOW, 0x0fe },
208  {  4166, 8, 32,              0x0ff },
209  {     0, 0, jbig2HuffmanEOT, 0     }
210};
211
212JBIG2HuffmanTable huffTableK[] = {
213  {     1, 1,  0,              0x000 },
214  {     2, 2,  1,              0x002 },
215  {     4, 4,  0,              0x00c },
216  {     5, 4,  1,              0x00d },
217  {     7, 5,  1,              0x01c },
218  {     9, 5,  2,              0x01d },
219  {    13, 6,  2,              0x03c },
220  {    17, 7,  2,              0x07a },
221  {    21, 7,  3,              0x07b },
222  {    29, 7,  4,              0x07c },
223  {    45, 7,  5,              0x07d },
224  {    77, 7,  6,              0x07e },
225  {   141, 7, 32,              0x07f },
226  {     0, 0, jbig2HuffmanEOT, 0     }
227};
228
229JBIG2HuffmanTable huffTableL[] = {
230  {     1, 1,  0,              0x000 },
231  {     2, 2,  0,              0x002 },
232  {     3, 3,  1,              0x006 },
233  {     5, 5,  0,              0x01c },
234  {     6, 5,  1,              0x01d },
235  {     8, 6,  1,              0x03c },
236  {    10, 7,  0,              0x07a },
237  {    11, 7,  1,              0x07b },
238  {    13, 7,  2,              0x07c },
239  {    17, 7,  3,              0x07d },
240  {    25, 7,  4,              0x07e },
241  {    41, 8,  5,              0x0fe },
242  {    73, 8, 32,              0x0ff },
243  {     0, 0, jbig2HuffmanEOT, 0     }
244};
245
246JBIG2HuffmanTable huffTableM[] = {
247  {     1, 1,  0,              0x000 },
248  {     2, 3,  0,              0x004 },
249  {     7, 3,  3,              0x005 },
250  {     3, 4,  0,              0x00c },
251  {     5, 4,  1,              0x00d },
252  {     4, 5,  0,              0x01c },
253  {    15, 6,  1,              0x03a },
254  {    17, 6,  2,              0x03b },
255  {    21, 6,  3,              0x03c },
256  {    29, 6,  4,              0x03d },
257  {    45, 6,  5,              0x03e },
258  {    77, 7,  6,              0x07e },
259  {   141, 7, 32,              0x07f },
260  {     0, 0, jbig2HuffmanEOT, 0     }
261};
262
263JBIG2HuffmanTable huffTableN[] = {
264  {     0, 1,  0,              0x000 },
265  {    -2, 3,  0,              0x004 },
266  {    -1, 3,  0,              0x005 },
267  {     1, 3,  0,              0x006 },
268  {     2, 3,  0,              0x007 },
269  {     0, 0, jbig2HuffmanEOT, 0     }
270};
271
272JBIG2HuffmanTable huffTableO[] = {
273  {     0, 1,  0,              0x000 },
274  {    -1, 3,  0,              0x004 },
275  {     1, 3,  0,              0x005 },
276  {    -2, 4,  0,              0x00c },
277  {     2, 4,  0,              0x00d },
278  {    -4, 5,  1,              0x01c },
279  {     3, 5,  1,              0x01d },
280  {    -8, 6,  2,              0x03c },
281  {     5, 6,  2,              0x03d },
282  {   -24, 7,  4,              0x07c },
283  {     9, 7,  4,              0x07d },
284  {   -25, 7, jbig2HuffmanLOW, 0x07e },
285  {    25, 7, 32,              0x07f },
286  {     0, 0, jbig2HuffmanEOT, 0     }
287};
288
289//------------------------------------------------------------------------
290// JBIG2HuffmanDecoder
291//------------------------------------------------------------------------
292
293class JBIG2HuffmanDecoder {
294public:
295
296  JBIG2HuffmanDecoder();
297  ~JBIG2HuffmanDecoder();
298  void setStream(Stream *strA) { str = strA; }
299
300  void reset();
301
302  // Returns false for OOB, otherwise sets *<x> and returns true.
303  GBool decodeInt(int *x, JBIG2HuffmanTable *table);
304
305  Guint readBits(Guint n);
306  Guint readBit();
307
308  // Sort the table by prefix length and assign prefix values.
309  void buildTable(JBIG2HuffmanTable *table, Guint len);
310
311private:
312
313  Stream *str;
314  Guint buf;
315  Guint bufLen;
316};
317
318JBIG2HuffmanDecoder::JBIG2HuffmanDecoder() {
319  str = NULL;
320  reset();
321}
322
323JBIG2HuffmanDecoder::~JBIG2HuffmanDecoder() {
324}
325
326void JBIG2HuffmanDecoder::reset() {
327  buf = 0;
328  bufLen = 0;
329}
330
331//~ optimize this
332GBool JBIG2HuffmanDecoder::decodeInt(int *x, JBIG2HuffmanTable *table) {
333  Guint i, len, prefix;
334
335  i = 0;
336  len = 0;
337  prefix = 0;
338  while (table[i].rangeLen != jbig2HuffmanEOT) {
339    while (len < table[i].prefixLen) {
340      prefix = (prefix << 1) | readBit();
341      ++len;
342    }
343    if (prefix == table[i].prefix) {
344      if (table[i].rangeLen == jbig2HuffmanOOB) {
345        return gFalse;
346      }
347      if (table[i].rangeLen == jbig2HuffmanLOW) {
348        *x = table[i].val - readBits(32);
349      } else if (table[i].rangeLen > 0) {
350        *x = table[i].val + readBits(table[i].rangeLen);
351      } else {
352        *x = table[i].val;
353      }
354      return gTrue;
355    }
356    ++i;
357  }
358  return gFalse;
359}
360
361Guint JBIG2HuffmanDecoder::readBits(Guint n) {
362  Guint x, mask, nLeft;
363
364  mask = (n == 32) ? 0xffffffff : ((1 << n) - 1);
365  if (bufLen >= n) {
366    x = (buf >> (bufLen - n)) & mask;
367    bufLen -= n;
368  } else {
369    x = buf & ((1 << bufLen) - 1);
370    nLeft = n - bufLen;
371    bufLen = 0;
372    while (nLeft >= 8) {
373      x = (x << 8) | (str->getChar() & 0xff);
374      nLeft -= 8;
375    }
376    if (nLeft > 0) {
377      buf = str->getChar();
378      bufLen = 8 - nLeft;
379      x = (x << nLeft) | ((buf >> bufLen) & ((1 << nLeft) - 1));
380    }
381  }
382  return x;
383}
384
385Guint JBIG2HuffmanDecoder::readBit() {
386  if (bufLen == 0) {
387    buf = str->getChar();
388    bufLen = 8;
389  }
390  --bufLen;
391  return (buf >> bufLen) & 1;
392}
393
394void JBIG2HuffmanDecoder::buildTable(JBIG2HuffmanTable *table, Guint len) {
395  Guint i, j, k, prefix;
396  JBIG2HuffmanTable tab;
397
398  // stable selection sort:
399  // - entries with prefixLen > 0, in ascending prefixLen order
400  // - entry with prefixLen = 0, rangeLen = EOT
401  // - all other entries with prefixLen = 0
402  // (on entry, table[len] has prefixLen = 0, rangeLen = EOT)
403  for (i = 0; i < len; ++i) {
404    for (j = i; j < len && table[j].prefixLen == 0; ++j) ;
405    if (j == len) {
406      break;
407    }
408    for (k = j + 1; k < len; ++k) {
409      if (table[k].prefixLen > 0 &&
410          table[k].prefixLen < table[j].prefixLen) {
411        j = k;
412      }
413    }
414    if (j != i) {
415      tab = table[j];
416      for (k = j; k > i; --k) {
417        table[k] = table[k - 1];
418      }
419      table[i] = tab;
420    }
421  }
422  table[i] = table[len];
423
424  // assign prefixes
425  i = 0;
426  prefix = 0;
427  table[i++].prefix = prefix++;
428  for (; table[i].rangeLen != jbig2HuffmanEOT; ++i) {
429    prefix <<= table[i].prefixLen - table[i-1].prefixLen;
430    table[i].prefix = prefix++;
431  }
432}
433
434//------------------------------------------------------------------------
435// JBIG2MMRDecoder
436//------------------------------------------------------------------------
437
438class JBIG2MMRDecoder {
439public:
440
441  JBIG2MMRDecoder();
442  ~JBIG2MMRDecoder();
443  void setStream(Stream *strA) { str = strA; }
444  void reset();
445  int get2DCode();
446  int getBlackCode();
447  int getWhiteCode();
448  Guint get24Bits();
449  void skipTo(Guint length);
450
451private:
452
453  Stream *str;
454  Guint buf;
455  Guint bufLen;
456  Guint nBytesRead;
457};
458
459JBIG2MMRDecoder::JBIG2MMRDecoder() {
460  str = NULL;
461  reset();
462}
463
464JBIG2MMRDecoder::~JBIG2MMRDecoder() {
465}
466
467void JBIG2MMRDecoder::reset() {
468  buf = 0;
469  bufLen = 0;
470  nBytesRead = 0;
471}
472
473int JBIG2MMRDecoder::get2DCode() {
474  CCITTCode *p;
475
476  if (bufLen == 0) {
477    buf = str->getChar() & 0xff;
478    bufLen = 8;
479    ++nBytesRead;
480    p = &twoDimTab1[(buf >> 1) & 0x7f];
481  } else if (bufLen == 8) {
482    p = &twoDimTab1[(buf >> 1) & 0x7f];
483  } else {
484    p = &twoDimTab1[(buf << (7 - bufLen)) & 0x7f];
485    if (p->bits < 0 || p->bits > (int)bufLen) {
486      buf = (buf << 8) | (str->getChar() & 0xff);
487      bufLen += 8;
488      ++nBytesRead;
489      p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f];
490    }
491  }
492  if (p->bits < 0) {
493    error(str->getPos(), "Bad two dim code in JBIG2 MMR stream");
494    return 0;
495  }
496  bufLen -= p->bits;
497  return p->n;
498}
499
500int JBIG2MMRDecoder::getWhiteCode() {
501  CCITTCode *p;
502  Guint code;
503
504  if (bufLen == 0) {
505    buf = str->getChar() & 0xff;
506    bufLen = 8;
507    ++nBytesRead;
508  }
509  while (1) {
510    if (bufLen >= 7 && ((buf >> (bufLen - 7)) & 0x7f) == 0) {
511      if (bufLen <= 12) {
512        code = buf << (12 - bufLen);
513      } else {
514        code = buf >> (bufLen - 12);
515      }
516      p = &whiteTab1[code & 0x1f];
517    } else {
518      if (bufLen <= 9) {
519        code = buf << (9 - bufLen);
520      } else {
521        code = buf >> (bufLen - 9);
522      }
523      p = &whiteTab2[code & 0x1ff];
524    }
525    if (p->bits > 0 && p->bits <= (int)bufLen) {
526      bufLen -= p->bits;
527      return p->n;
528    }
529    if (bufLen >= 12) {
530      break;
531    }
532    buf = (buf << 8) | (str->getChar() & 0xff);
533    bufLen += 8;
534    ++nBytesRead;
535  }
536  error(str->getPos(), "Bad white code in JBIG2 MMR stream");
537  // eat a bit and return a positive number so that the caller doesn't
538  // go into an infinite loop
539  --bufLen;
540  return 1;
541}
542
543int JBIG2MMRDecoder::getBlackCode() {
544  CCITTCode *p;
545  Guint code;
546
547  if (bufLen == 0) {
548    buf = str->getChar() & 0xff;
549    bufLen = 8;
550    ++nBytesRead;
551  }
552  while (1) {
553    if (bufLen >= 6 && ((buf >> (bufLen - 6)) & 0x3f) == 0) {
554      if (bufLen <= 13) {
555        code = buf << (13 - bufLen);
556      } else {
557        code = buf >> (bufLen - 13);
558      }
559      p = &blackTab1[code & 0x7f];
560    } else if (bufLen >= 4 && ((buf >> (bufLen - 4)) & 0x0f) == 0) {
561      if (bufLen <= 12) {
562        code = buf << (12 - bufLen);
563      } else {
564        code = buf >> (bufLen - 12);
565      }
566      p = &blackTab2[(code & 0xff) - 64];
567    } else {
568      if (bufLen <= 6) {
569        code = buf << (6 - bufLen);
570      } else {
571        code = buf >> (bufLen - 6);
572      }
573      p = &blackTab3[code & 0x3f];
574    }
575    if (p->bits > 0 && p->bits <= (int)bufLen) {
576      bufLen -= p->bits;
577      return p->n;
578    }
579    if (bufLen >= 13) {
580      break;
581    }
582    buf = (buf << 8) | (str->getChar() & 0xff);
583    bufLen += 8;
584    ++nBytesRead;
585  }
586  error(str->getPos(), "Bad black code in JBIG2 MMR stream");
587  // eat a bit and return a positive number so that the caller doesn't
588  // go into an infinite loop
589  --bufLen;
590  return 1;
591}
592
593Guint JBIG2MMRDecoder::get24Bits() {
594  while (bufLen < 24) {
595    buf = (buf << 8) | (str->getChar() & 0xff);
596    bufLen += 8;
597    ++nBytesRead;
598  }
599  return (buf >> (bufLen - 24)) & 0xffffff;
600}
601
602void JBIG2MMRDecoder::skipTo(Guint length) {
603  while (nBytesRead < length) {
604    str->getChar();
605    ++nBytesRead;
606  }
607}
608
609//------------------------------------------------------------------------
610// JBIG2Segment
611//------------------------------------------------------------------------
612
613enum JBIG2SegmentType {
614  jbig2SegBitmap,
615  jbig2SegSymbolDict,
616  jbig2SegPatternDict,
617  jbig2SegCodeTable
618};
619
620class JBIG2Segment {
621public:
622
623  JBIG2Segment(Guint segNumA) { segNum = segNumA; }
624  virtual ~JBIG2Segment() {}
625  void setSegNum(Guint segNumA) { segNum = segNumA; }
626  Guint getSegNum() { return segNum; }
627  virtual JBIG2SegmentType getType() = 0;
628
629private:
630
631  Guint segNum;
632};
633
634//------------------------------------------------------------------------
635// JBIG2Bitmap
636//------------------------------------------------------------------------
637
638struct JBIG2BitmapPtr {
639  Guchar *p;
640  int shift;
641  int x;
642};
643
644class JBIG2Bitmap: public JBIG2Segment {
645public:
646
647  JBIG2Bitmap(Guint segNumA, int wA, int hA);
648  virtual ~JBIG2Bitmap();
649  virtual JBIG2SegmentType getType() { return jbig2SegBitmap; }
650  JBIG2Bitmap *copy() { return new JBIG2Bitmap(0, this); }
651  JBIG2Bitmap *getSlice(Guint x, Guint y, Guint wA, Guint hA);
652  void expand(int newH, Guint pixel);
653  void clearToZero();
654  void clearToOne();
655  int getWidth() { return w; }
656  int getHeight() { return h; }
657  int getPixel(int x, int y)
658    { return (x < 0 || x >= w || y < 0 || y >= h) ? 0 :
659             (data[y * line + (x >> 3)] >> (7 - (x & 7))) & 1; }
660  void setPixel(int x, int y)
661    { data[y * line + (x >> 3)] |= 1 << (7 - (x & 7)); }
662  void clearPixel(int x, int y)
663    { data[y * line + (x >> 3)] &= 0x7f7f >> (x & 7); }
664  void getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr);
665  int nextPixel(JBIG2BitmapPtr *ptr);
666  void duplicateRow(int yDest, int ySrc);
667  void combine(JBIG2Bitmap *bitmap, int x, int y, Guint combOp);
668  Guchar *getDataPtr() { return data; }
669  int getDataSize() { return h * line; }
670
671private:
672
673  JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap);
674
675  int w, h, line;
676  Guchar *data;
677};
678
679JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, int wA, int hA):
680  JBIG2Segment(segNumA)
681{
682  w = wA;
683  h = hA;
684  line = (wA + 7) >> 3;
685
686  if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) {
687    error(-1, "invalid width/height");
688    data = NULL;
689    return;
690  }
691  // need to allocate one extra guard byte for use in combine()
692  data = (Guchar *)gmalloc(h * line + 1);
693  data[h * line] = 0;
694}
695
696JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap):
697  JBIG2Segment(segNumA)
698{
699  w = bitmap->w;
700  h = bitmap->h;
701  line = bitmap->line;
702
703  if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) {
704    error(-1, "invalid width/height");
705    data = NULL;
706    return;
707  }
708  // need to allocate one extra guard byte for use in combine()
709  data = (Guchar *)gmalloc(h * line + 1);
710  memcpy(data, bitmap->data, h * line);
711  data[h * line] = 0;
712}
713
714JBIG2Bitmap::~JBIG2Bitmap() {
715  gfree(data);
716}
717
718//~ optimize this
719JBIG2Bitmap *JBIG2Bitmap::getSlice(Guint x, Guint y, Guint wA, Guint hA) {
720  JBIG2Bitmap *slice;
721  Guint xx, yy;
722
723  slice = new JBIG2Bitmap(0, wA, hA);
724  slice->clearToZero();
725  for (yy = 0; yy < hA; ++yy) {
726    for (xx = 0; xx < wA; ++xx) {
727      if (getPixel(x + xx, y + yy)) {
728        slice->setPixel(xx, yy);
729      }
730    }
731  }
732  return slice;
733}
734
735void JBIG2Bitmap::expand(int newH, Guint pixel) {
736  if (newH <= h || line <= 0 || newH >= (INT_MAX - 1) / line) {
737    error(-1, "invalid width/height");
738    gfree(data);
739    data = NULL;
740    return;
741  }
742  // need to allocate one extra guard byte for use in combine()
743  data = (Guchar *)grealloc(data, newH * line + 1);
744  if (pixel) {
745    memset(data + h * line, 0xff, (newH - h) * line);
746  } else {
747    memset(data + h * line, 0x00, (newH - h) * line);
748  }
749  h = newH;
750  data[h * line] = 0;
751}
752
753void JBIG2Bitmap::clearToZero() {
754  memset(data, 0, h * line);
755}
756
757void JBIG2Bitmap::clearToOne() {
758  memset(data, 0xff, h * line);
759}
760
761inline void JBIG2Bitmap::getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr) {
762  if (y < 0 || y >= h || x >= w) {
763    ptr->p = NULL;
764  } else if (x < 0) {
765    ptr->p = &data[y * line];
766    ptr->shift = 7;
767    ptr->x = x;
768  } else {
769    ptr->p = &data[y * line + (x >> 3)];
770    ptr->shift = 7 - (x & 7);
771    ptr->x = x;
772  }
773}
774
775inline int JBIG2Bitmap::nextPixel(JBIG2BitmapPtr *ptr) {
776  int pix;
777
778  if (!ptr->p) {
779    pix = 0;
780  } else if (ptr->x < 0) {
781    ++ptr->x;
782    pix = 0;
783  } else {
784    pix = (*ptr->p >> ptr->shift) & 1;
785    if (++ptr->x == w) {
786      ptr->p = NULL;
787    } else if (ptr->shift == 0) {
788      ++ptr->p;
789      ptr->shift = 7;
790    } else {
791      --ptr->shift;
792    }
793  }
794  return pix;
795}
796
797void JBIG2Bitmap::duplicateRow(int yDest, int ySrc) {
798  memcpy(data + yDest * line, data + ySrc * line, line);
799}
800
801void JBIG2Bitmap::combine(JBIG2Bitmap *bitmap, int x, int y,
802                          Guint combOp) {
803  int x0, x1, y0, y1, xx, yy;
804  Guchar *srcPtr, *destPtr;
805  Guint src0, src1, src, dest, s1, s2, m1, m2, m3;
806  GBool oneByte;
807
808  if (y < 0) {
809    y0 = -y;
810  } else {
811    y0 = 0;
812  }
813  if (y + bitmap->h > h) {
814    y1 = h - y;
815  } else {
816    y1 = bitmap->h;
817  }
818  if (y0 >= y1) {
819    return;
820  }
821
822  if (x >= 0) {
823    x0 = x & ~7;
824  } else {
825    x0 = 0;
826  }
827  x1 = x + bitmap->w;
828  if (x1 > w) {
829    x1 = w;
830  }
831  if (x0 >= x1) {
832    return;
833  }
834
835  s1 = x & 7;
836  s2 = 8 - s1;
837  m1 = 0xff >> (x1 & 7);
838  m2 = 0xff << (((x1 & 7) == 0) ? 0 : 8 - (x1 & 7));
839  m3 = (0xff >> s1) & m2;
840
841  oneByte = x0 == ((x1 - 1) & ~7);
842
843  for (yy = y0; yy < y1; ++yy) {
844
845    // one byte per line -- need to mask both left and right side
846    if (oneByte) {
847      if (x >= 0) {
848        destPtr = data + (y + yy) * line + (x >> 3);
849        srcPtr = bitmap->data + yy * bitmap->line;
850        dest = *destPtr;
851        src1 = *srcPtr;
852        switch (combOp) {
853        case 0: // or
854          dest |= (src1 >> s1) & m2;
855          break;
856        case 1: // and
857          dest &= ((0xff00 | src1) >> s1) | m1;
858          break;
859        case 2: // xor
860          dest ^= (src1 >> s1) & m2;
861          break;
862        case 3: // xnor
863          dest ^= ((src1 ^ 0xff) >> s1) & m2;
864          break;
865        case 4: // replace
866          dest = (dest & ~m3) | ((src1 >> s1) & m3);
867          break;
868        }
869        *destPtr = dest;
870      } else {
871        destPtr = data + (y + yy) * line;
872        srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
873        dest = *destPtr;
874        src1 = *srcPtr;
875        switch (combOp) {
876        case 0: // or
877          dest |= src1 & m2;
878          break;
879        case 1: // and
880          dest &= src1 | m1;
881          break;
882        case 2: // xor
883          dest ^= src1 & m2;
884          break;
885        case 3: // xnor
886          dest ^= (src1 ^ 0xff) & m2;
887          break;
888        case 4: // replace
889          dest = (src1 & m2) | (dest & m1);
890          break;
891        }
892        *destPtr = dest;
893      }
894
895    // multiple bytes per line -- need to mask left side of left-most
896    // byte and right side of right-most byte
897    } else {
898
899      // left-most byte
900      if (x >= 0) {
901        destPtr = data + (y + yy) * line + (x >> 3);
902        srcPtr = bitmap->data + yy * bitmap->line;
903        src1 = *srcPtr++;
904        dest = *destPtr;
905        switch (combOp) {
906        case 0: // or
907          dest |= src1 >> s1;
908          break;
909        case 1: // and
910          dest &= (0xff00 | src1) >> s1;
911          break;
912        case 2: // xor
913          dest ^= src1 >> s1;
914          break;
915        case 3: // xnor
916          dest ^= (src1 ^ 0xff) >> s1;
917          break;
918        case 4: // replace
919          dest = (dest & (0xff << s2)) | (src1 >> s1);
920          break;
921        }
922        *destPtr++ = dest;
923        xx = x0 + 8;
924      } else {
925        destPtr = data + (y + yy) * line;
926        srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
927        src1 = *srcPtr++;
928        xx = x0;
929      }
930
931      // middle bytes
932      for (; xx < x1 - 8; xx += 8) {
933        dest = *destPtr;
934        src0 = src1;
935        src1 = *srcPtr++;
936        src = (((src0 << 8) | src1) >> s1) & 0xff;
937        switch (combOp) {
938        case 0: // or
939          dest |= src;
940          break;
941        case 1: // and
942          dest &= src;
943          break;
944        case 2: // xor
945          dest ^= src;
946          break;
947        case 3: // xnor
948          dest ^= src ^ 0xff;
949          break;
950        case 4: // replace
951          dest = src;
952          break;
953        }
954        *destPtr++ = dest;
955      }
956
957      // right-most byte
958      // note: this last byte (src1) may not actually be used, depending
959      // on the values of s1, m1, and m2 - and in fact, it may be off
960      // the edge of the source bitmap, which means we need to allocate
961      // one extra guard byte at the end of each bitmap
962      dest = *destPtr;
963      src0 = src1;
964      src1 = *srcPtr++;
965      src = (((src0 << 8) | src1) >> s1) & 0xff;
966      switch (combOp) {
967      case 0: // or
968        dest |= src & m2;
969        break;
970      case 1: // and
971        dest &= src | m1;
972        break;
973      case 2: // xor
974        dest ^= src & m2;
975        break;
976      case 3: // xnor
977        dest ^= (src ^ 0xff) & m2;
978        break;
979      case 4: // replace
980        dest = (src & m2) | (dest & m1);
981        break;
982      }
983      *destPtr = dest;
984    }
985  }
986}
987
988//------------------------------------------------------------------------
989// JBIG2SymbolDict
990//------------------------------------------------------------------------
991
992class JBIG2SymbolDict: public JBIG2Segment {
993public:
994
995  JBIG2SymbolDict(Guint segNumA, Guint sizeA);
996  virtual ~JBIG2SymbolDict();
997  virtual JBIG2SegmentType getType() { return jbig2SegSymbolDict; }
998  Guint getSize() { return size; }
999  void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
1000  JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; }
1001  void setGenericRegionStats(JArithmeticDecoderStats *stats)
1002    { genericRegionStats = stats; }
1003  void setRefinementRegionStats(JArithmeticDecoderStats *stats)
1004    { refinementRegionStats = stats; }
1005  JArithmeticDecoderStats *getGenericRegionStats()
1006    { return genericRegionStats; }
1007  JArithmeticDecoderStats *getRefinementRegionStats()
1008    { return refinementRegionStats; }
1009
1010private:
1011
1012  Guint size;
1013  JBIG2Bitmap **bitmaps;
1014  JArithmeticDecoderStats *genericRegionStats;
1015  JArithmeticDecoderStats *refinementRegionStats;
1016};
1017
1018JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA):
1019  JBIG2Segment(segNumA)
1020{
1021  size = sizeA;
1022  bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *));
1023  genericRegionStats = NULL;
1024  refinementRegionStats = NULL;
1025}
1026
1027JBIG2SymbolDict::~JBIG2SymbolDict() {
1028  Guint i;
1029
1030  for (i = 0; i < size; ++i) {
1031    delete bitmaps[i];
1032  }
1033  gfree(bitmaps);
1034  if (genericRegionStats) {
1035    delete genericRegionStats;
1036  }
1037  if (refinementRegionStats) {
1038    delete refinementRegionStats;
1039  }
1040}
1041
1042//------------------------------------------------------------------------
1043// JBIG2PatternDict
1044//------------------------------------------------------------------------
1045
1046class JBIG2PatternDict: public JBIG2Segment {
1047public:
1048
1049  JBIG2PatternDict(Guint segNumA, Guint sizeA);
1050  virtual ~JBIG2PatternDict();
1051  virtual JBIG2SegmentType getType() { return jbig2SegPatternDict; }
1052  Guint getSize() { return size; }
1053  void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
1054  JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; }
1055
1056private:
1057
1058  Guint size;
1059  JBIG2Bitmap **bitmaps;
1060};
1061
1062JBIG2PatternDict::JBIG2PatternDict(Guint segNumA, Guint sizeA):
1063  JBIG2Segment(segNumA)
1064{
1065  size = sizeA;
1066  bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *));
1067}
1068
1069JBIG2PatternDict::~JBIG2PatternDict() {
1070  Guint i;
1071
1072  for (i = 0; i < size; ++i) {
1073    delete bitmaps[i];
1074  }
1075  gfree(bitmaps);
1076}
1077
1078//------------------------------------------------------------------------
1079// JBIG2CodeTable
1080//------------------------------------------------------------------------
1081
1082class JBIG2CodeTable: public JBIG2Segment {
1083public:
1084
1085  JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA);
1086  virtual ~JBIG2CodeTable();
1087  virtual JBIG2SegmentType getType() { return jbig2SegCodeTable; }
1088  JBIG2HuffmanTable *getHuffTable() { return table; }
1089
1090private:
1091
1092  JBIG2HuffmanTable *table;
1093};
1094
1095JBIG2CodeTable::JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA):
1096  JBIG2Segment(segNumA)
1097{
1098  table = tableA;
1099}
1100
1101JBIG2CodeTable::~JBIG2CodeTable() {
1102  gfree(table);
1103}
1104
1105//------------------------------------------------------------------------
1106// JBIG2Stream
1107//------------------------------------------------------------------------
1108
1109JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStream):
1110  FilterStream(strA)
1111{
1112  pageBitmap = NULL;
1113
1114  arithDecoder = new JArithmeticDecoder();
1115  genericRegionStats = new JArithmeticDecoderStats(1 << 1);
1116  refinementRegionStats = new JArithmeticDecoderStats(1 << 1);
1117  iadhStats = new JArithmeticDecoderStats(1 << 9);
1118  iadwStats = new JArithmeticDecoderStats(1 << 9);
1119  iaexStats = new JArithmeticDecoderStats(1 << 9);
1120  iaaiStats = new JArithmeticDecoderStats(1 << 9);
1121  iadtStats = new JArithmeticDecoderStats(1 << 9);
1122  iaitStats = new JArithmeticDecoderStats(1 << 9);
1123  iafsStats = new JArithmeticDecoderStats(1 << 9);
1124  iadsStats = new JArithmeticDecoderStats(1 << 9);
1125  iardxStats = new JArithmeticDecoderStats(1 << 9);
1126  iardyStats = new JArithmeticDecoderStats(1 << 9);
1127  iardwStats = new JArithmeticDecoderStats(1 << 9);
1128  iardhStats = new JArithmeticDecoderStats(1 << 9);
1129  iariStats = new JArithmeticDecoderStats(1 << 9);
1130  iaidStats = new JArithmeticDecoderStats(1 << 1);
1131  huffDecoder = new JBIG2HuffmanDecoder();
1132  mmrDecoder = new JBIG2MMRDecoder();
1133
1134  segments = globalSegments = new GooList();
1135  if (globalsStream->isStream()) {
1136    curStr = globalsStream->getStream();
1137    curStr->reset();
1138    arithDecoder->setStream(curStr);
1139    huffDecoder->setStream(curStr);
1140    mmrDecoder->setStream(curStr);
1141    readSegments();
1142  }
1143
1144  segments = NULL;
1145  curStr = NULL;
1146  dataPtr = dataEnd = NULL;
1147}
1148
1149JBIG2Stream::~JBIG2Stream() {
1150  delete arithDecoder;
1151  delete genericRegionStats;
1152  delete refinementRegionStats;
1153  delete iadhStats;
1154  delete iadwStats;
1155  delete iaexStats;
1156  delete iaaiStats;
1157  delete iadtStats;
1158  delete iaitStats;
1159  delete iafsStats;
1160  delete iadsStats;
1161  delete iardxStats;
1162  delete iardyStats;
1163  delete iardwStats;
1164  delete iardhStats;
1165  delete iariStats;
1166  delete iaidStats;
1167  delete huffDecoder;
1168  delete mmrDecoder;
1169  if (pageBitmap) {
1170    delete pageBitmap;
1171  }
1172  if (segments) {
1173    deleteGooList(segments, JBIG2Segment);
1174  }
1175  if (globalSegments) {
1176    deleteGooList(globalSegments, JBIG2Segment);
1177  }
1178  delete str;
1179}
1180
1181void JBIG2Stream::reset() {
1182  if (pageBitmap) {
1183    delete pageBitmap;
1184    pageBitmap = NULL;
1185  }
1186  if (segments) {
1187    deleteGooList(segments, JBIG2Segment);
1188  }
1189  segments = new GooList();
1190
1191  curStr = str;
1192  curStr->reset();
1193  arithDecoder->setStream(curStr);
1194  huffDecoder->setStream(curStr);
1195  mmrDecoder->setStream(curStr);
1196  readSegments();
1197
1198  if (pageBitmap) {
1199    dataPtr = pageBitmap->getDataPtr();
1200    dataEnd = dataPtr + pageBitmap->getDataSize();
1201  } else {
1202    dataPtr = NULL;
1203  }
1204}
1205
1206int JBIG2Stream::getChar() {
1207  if (dataPtr && dataPtr < dataEnd) {
1208    return (*dataPtr++ ^ 0xff) & 0xff;
1209  }
1210  return EOF;
1211}
1212
1213int JBIG2Stream::lookChar() {
1214  if (dataPtr && dataPtr < dataEnd) {
1215    return (*dataPtr ^ 0xff) & 0xff;
1216  }
1217  return EOF;
1218}
1219
1220GooString *JBIG2Stream::getPSFilter(int psLevel, char *indent) {
1221  return NULL;
1222}
1223
1224GBool JBIG2Stream::isBinary(GBool last) {
1225  return str->isBinary(gTrue);
1226}
1227
1228void JBIG2Stream::readSegments() {
1229  Guint segNum, segFlags, segType, page, segLength;
1230  Guint refFlags, nRefSegs;
1231  Guint *refSegs;
1232  int c1, c2, c3;
1233  Guint i;
1234
1235  while (readULong(&segNum)) {
1236
1237    // segment header flags
1238    if (!readUByte(&segFlags)) {
1239      goto eofError1;
1240    }
1241    segType = segFlags & 0x3f;
1242
1243    // referred-to segment count and retention flags
1244    if (!readUByte(&refFlags)) {
1245      goto eofError1;
1246    }
1247    nRefSegs = refFlags >> 5;
1248    if (nRefSegs == 7) {
1249      if ((c1 = curStr->getChar()) == EOF ||
1250          (c2 = curStr->getChar()) == EOF ||
1251          (c3 = curStr->getChar()) == EOF) {
1252        goto eofError1;
1253      }
1254      refFlags = (refFlags << 24) | (c1 << 16) | (c2 << 8) | c3;
1255      nRefSegs = refFlags & 0x1fffffff;
1256      for (i = 0; i < (nRefSegs + 9) >> 3; ++i) {
1257        c1 = curStr->getChar();
1258      }
1259    }
1260
1261    // referred-to segment numbers
1262    refSegs = (Guint *)gmallocn(nRefSegs, sizeof(Guint));
1263    if (segNum <= 256) {
1264      for (i = 0; i < nRefSegs; ++i) {
1265        if (!readUByte(&refSegs[i])) {
1266          goto eofError2;
1267        }
1268      }
1269    } else if (segNum <= 65536) {
1270      for (i = 0; i < nRefSegs; ++i) {
1271        if (!readUWord(&refSegs[i])) {
1272          goto eofError2;
1273        }
1274      }
1275    } else {
1276      for (i = 0; i < nRefSegs; ++i) {
1277        if (!readULong(&refSegs[i])) {
1278          goto eofError2;
1279        }
1280      }
1281    }
1282
1283    // segment page association
1284    if (segFlags & 0x40) {
1285      if (!readULong(&page)) {
1286        goto eofError2;
1287      }
1288    } else {
1289      if (!readUByte(&page)) {
1290        goto eofError2;
1291      }
1292    }
1293
1294    // segment data length
1295    if (!readULong(&segLength)) {
1296      goto eofError2;
1297    }
1298
1299    // read the segment data
1300    switch (segType) {
1301    case 0:
1302      if (!readSymbolDictSeg(segNum, segLength, refSegs, nRefSegs)) {
1303        goto syntaxError;
1304      }
1305      break;
1306    case 4:
1307      readTextRegionSeg(segNum, gFalse, gFalse, segLength, refSegs, nRefSegs);
1308      break;
1309    case 6:
1310      readTextRegionSeg(segNum, gTrue, gFalse, segLength, refSegs, nRefSegs);
1311      break;
1312    case 7:
1313      readTextRegionSeg(segNum, gTrue, gTrue, segLength, refSegs, nRefSegs);
1314      break;
1315    case 16:
1316      readPatternDictSeg(segNum, segLength);
1317      break;
1318    case 20:
1319      readHalftoneRegionSeg(segNum, gFalse, gFalse, segLength,
1320                            refSegs, nRefSegs);
1321      break;
1322    case 22:
1323      readHalftoneRegionSeg(segNum, gTrue, gFalse, segLength,
1324                            refSegs, nRefSegs);
1325      break;
1326    case 23:
1327      readHalftoneRegionSeg(segNum, gTrue, gTrue, segLength,
1328                            refSegs, nRefSegs);
1329      break;
1330    case 36:
1331      readGenericRegionSeg(segNum, gFalse, gFalse, segLength);
1332      break;
1333    case 38:
1334      readGenericRegionSeg(segNum, gTrue, gFalse, segLength);
1335      break;
1336    case 39:
1337      readGenericRegionSeg(segNum, gTrue, gTrue, segLength);
1338      break;
1339    case 40:
1340      readGenericRefinementRegionSeg(segNum, gFalse, gFalse, segLength,
1341                                     refSegs, nRefSegs);
1342      break;
1343    case 42:
1344      readGenericRefinementRegionSeg(segNum, gTrue, gFalse, segLength,
1345                                     refSegs, nRefSegs);
1346      break;
1347    case 43:
1348      readGenericRefinementRegionSeg(segNum, gTrue, gTrue, segLength,
1349                                     refSegs, nRefSegs);
1350      break;
1351    case 48:
1352      readPageInfoSeg(segLength);
1353      break;
1354    case 50:
1355      readEndOfStripeSeg(segLength);
1356      break;
1357    case 52:
1358      readProfilesSeg(segLength);
1359      break;
1360    case 53:
1361      readCodeTableSeg(segNum, segLength);
1362      break;
1363    case 62:
1364      readExtensionSeg(segLength);
1365      break;
1366    default:
1367      error(getPos(), "Unknown segment type in JBIG2 stream");
1368      for (i = 0; i < segLength; ++i) {
1369        if ((c1 = curStr->getChar()) == EOF) {
1370          goto eofError2;
1371        }
1372      }
1373      break;
1374    }
1375
1376    gfree(refSegs);
1377  }
1378
1379  return;
1380
1381 syntaxError:
1382  gfree(refSegs);
1383  return;
1384
1385 eofError2:
1386  gfree(refSegs);
1387 eofError1:
1388  error(getPos(), "Unexpected EOF in JBIG2 stream");
1389}
1390
1391GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
1392                                     Guint *refSegs, Guint nRefSegs) {
1393  JBIG2SymbolDict *symbolDict;
1394  JBIG2HuffmanTable *huffDHTable, *huffDWTable;
1395  JBIG2HuffmanTable *huffBMSizeTable, *huffAggInstTable;
1396  JBIG2Segment *seg;
1397  GooList *codeTables;
1398  JBIG2SymbolDict *inputSymbolDict;
1399  Guint flags, sdTemplate, sdrTemplate, huff, refAgg;
1400  Guint huffDH, huffDW, huffBMSize, huffAggInst;
1401  Guint contextUsed, contextRetained;
1402  int sdATX[4], sdATY[4], sdrATX[2], sdrATY[2];
1403  Guint numExSyms, numNewSyms, numInputSyms, symCodeLen;
1404  JBIG2Bitmap **bitmaps;
1405  JBIG2Bitmap *collBitmap, *refBitmap;
1406  Guint *symWidths;
1407  Guint symHeight, symWidth, totalWidth, x, symID;
1408  int dh, dw, refAggNum, refDX, refDY, bmSize;
1409  GBool ex;
1410  int run, cnt;
1411  Guint i, j, k;
1412  Guchar *p;
1413
1414  // symbol dictionary flags
1415  if (!readUWord(&flags)) {
1416    goto eofError;
1417  }
1418  sdTemplate = (flags >> 10) & 3;
1419  sdrTemplate = (flags >> 12) & 1;
1420  huff = flags & 1;
1421  refAgg = (flags >> 1) & 1;
1422  huffDH = (flags >> 2) & 3;
1423  huffDW = (flags >> 4) & 3;
1424  huffBMSize = (flags >> 6) & 1;
1425  huffAggInst = (flags >> 7) & 1;
1426  contextUsed = (flags >> 8) & 1;
1427  contextRetained = (flags >> 9) & 1;
1428
1429  // symbol dictionary AT flags
1430  if (!huff) {
1431    if (sdTemplate == 0) {
1432      if (!readByte(&sdATX[0]) ||
1433          !readByte(&sdATY[0]) ||
1434          !readByte(&sdATX[1]) ||
1435          !readByte(&sdATY[1]) ||
1436          !readByte(&sdATX[2]) ||
1437          !readByte(&sdATY[2]) ||
1438          !readByte(&sdATX[3]) ||
1439          !readByte(&sdATY[3])) {
1440        goto eofError;
1441      }
1442    } else {
1443      if (!readByte(&sdATX[0]) ||
1444          !readByte(&sdATY[0])) {
1445        goto eofError;
1446      }
1447    }
1448  }
1449
1450  // symbol dictionary refinement AT flags
1451  if (refAgg && !sdrTemplate) {
1452    if (!readByte(&sdrATX[0]) ||
1453        !readByte(&sdrATY[0]) ||
1454        !readByte(&sdrATX[1]) ||
1455        !readByte(&sdrATY[1])) {
1456      goto eofError;
1457    }
1458  }
1459
1460  // SDNUMEXSYMS and SDNUMNEWSYMS
1461  if (!readULong(&numExSyms) || !readULong(&numNewSyms)) {
1462    goto eofError;
1463  }
1464
1465  // get referenced segments: input symbol dictionaries and code tables
1466  codeTables = new GooList();
1467  numInputSyms = 0;
1468  for (i = 0; i < nRefSegs; ++i) {
1469    seg = findSegment(refSegs[i]);
1470    if (seg->getType() == jbig2SegSymbolDict) {
1471      numInputSyms += ((JBIG2SymbolDict *)seg)->getSize();
1472    } else if (seg->getType() == jbig2SegCodeTable) {
1473      codeTables->append(seg);
1474    }
1475  }
1476
1477  // compute symbol code length
1478  symCodeLen = 0;
1479  i = 1;
1480  while (i < numInputSyms + numNewSyms) {
1481    ++symCodeLen;
1482    i <<= 1;
1483  }
1484
1485  // get the input symbol bitmaps
1486  bitmaps = (JBIG2Bitmap **)gmallocn(numInputSyms + numNewSyms,
1487                                     sizeof(JBIG2Bitmap *));
1488  for (i = 0; i < numInputSyms + numNewSyms; ++i) {
1489    bitmaps[i] = NULL;
1490  }
1491  k = 0;
1492  inputSymbolDict = NULL;
1493  for (i = 0; i < nRefSegs; ++i) {
1494    seg = findSegment(refSegs[i]);
1495    if (seg->getType() == jbig2SegSymbolDict) {
1496      inputSymbolDict = (JBIG2SymbolDict *)seg;
1497      for (j = 0; j < inputSymbolDict->getSize(); ++j) {
1498        bitmaps[k++] = inputSymbolDict->getBitmap(j);
1499      }
1500    }
1501  }
1502
1503  // get the Huffman tables
1504  huffDHTable = huffDWTable = NULL; // make gcc happy
1505  huffBMSizeTable = huffAggInstTable = NULL; // make gcc happy
1506  i = 0;
1507  if (huff) {
1508    if (huffDH == 0) {
1509      huffDHTable = huffTableD;
1510    } else if (huffDH == 1) {
1511      huffDHTable = huffTableE;
1512    } else {
1513      huffDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1514    }
1515    if (huffDW == 0) {
1516      huffDWTable = huffTableB;
1517    } else if (huffDW == 1) {
1518      huffDWTable = huffTableC;
1519    } else {
1520      huffDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1521    }
1522    if (huffBMSize == 0) {
1523      huffBMSizeTable = huffTableA;
1524    } else {
1525      huffBMSizeTable =
1526          ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1527    }
1528    if (huffAggInst == 0) {
1529      huffAggInstTable = huffTableA;
1530    } else {
1531      huffAggInstTable =
1532          ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1533    }
1534  }
1535  delete codeTables;
1536
1537  // set up the Huffman decoder
1538  if (huff) {
1539    huffDecoder->reset();
1540
1541  // set up the arithmetic decoder
1542  } else {
1543    if (contextUsed && inputSymbolDict) {
1544      resetGenericStats(sdTemplate, inputSymbolDict->getGenericRegionStats());
1545    } else {
1546      resetGenericStats(sdTemplate, NULL);
1547    }
1548    resetIntStats(symCodeLen);
1549    arithDecoder->start();
1550  }
1551
1552  // set up the arithmetic decoder for refinement/aggregation
1553  if (refAgg) {
1554    if (contextUsed && inputSymbolDict) {
1555      resetRefinementStats(sdrTemplate,
1556                           inputSymbolDict->getRefinementRegionStats());
1557    } else {
1558      resetRefinementStats(sdrTemplate, NULL);
1559    }
1560  }
1561
1562  // allocate symbol widths storage
1563  symWidths = NULL;
1564  if (huff && !refAgg) {
1565    symWidths = (Guint *)gmallocn(numNewSyms, sizeof(Guint));
1566  }
1567
1568  symHeight = 0;
1569  i = 0;
1570  while (i < numNewSyms) {
1571
1572    // read the height class delta height
1573    if (huff) {
1574      huffDecoder->decodeInt(&dh, huffDHTable);
1575    } else {
1576      arithDecoder->decodeInt(&dh, iadhStats);
1577    }
1578    if (dh < 0 && (Guint)-dh >= symHeight) {
1579      error(getPos(), "Bad delta-height value in JBIG2 symbol dictionary");
1580      goto syntaxError;
1581    }
1582    symHeight += dh;
1583    symWidth = 0;
1584    totalWidth = 0;
1585    j = i;
1586
1587    // read the symbols in this height class
1588    while (1) {
1589
1590      // read the delta width
1591      if (huff) {
1592        if (!huffDecoder->decodeInt(&dw, huffDWTable)) {
1593          break;
1594        }
1595      } else {
1596        if (!arithDecoder->decodeInt(&dw, iadwStats)) {
1597          break;
1598        }
1599      }
1600      if (dw < 0 && (Guint)-dw >= symWidth) {
1601        error(getPos(), "Bad delta-height value in JBIG2 symbol dictionary");
1602        goto syntaxError;
1603      }
1604      symWidth += dw;
1605
1606      // using a collective bitmap, so don't read a bitmap here
1607      if (huff && !refAgg) {
1608        symWidths[i] = symWidth;
1609        totalWidth += symWidth;
1610
1611      // refinement/aggregate coding
1612      } else if (refAgg) {
1613        if (huff) {
1614          if (!huffDecoder->decodeInt(&refAggNum, huffAggInstTable)) {
1615            break;
1616          }
1617        } else {
1618          if (!arithDecoder->decodeInt(&refAggNum, iaaiStats)) {
1619            break;
1620          }
1621        }
1622#if 0 //~ This special case was added about a year before the final draft
1623      //~ of the JBIG2 spec was released.  I have encountered some old
1624      //~ JBIG2 images that predate it.
1625        if (0) {
1626#else
1627        if (refAggNum == 1) {
1628#endif
1629          if (huff) {
1630            symID = huffDecoder->readBits(symCodeLen);
1631            huffDecoder->decodeInt(&refDX, huffTableO);
1632            huffDecoder->decodeInt(&refDY, huffTableO);
1633            huffDecoder->decodeInt(&bmSize, huffTableA);
1634            huffDecoder->reset();
1635            arithDecoder->start();
1636          } else {
1637            symID = arithDecoder->decodeIAID(symCodeLen, iaidStats);
1638            arithDecoder->decodeInt(&refDX, iardxStats);
1639            arithDecoder->decodeInt(&refDY, iardyStats);
1640          }
1641          refBitmap = bitmaps[symID];
1642          bitmaps[numInputSyms + i] =
1643              readGenericRefinementRegion(symWidth, symHeight,
1644                                          sdrTemplate, gFalse,
1645                                          refBitmap, refDX, refDY,
1646                                          sdrATX, sdrATY);
1647          //~ do we need to use the bmSize value here (in Huffman mode)?
1648        } else {
1649          bitmaps[numInputSyms + i] =
1650              readTextRegion(huff, gTrue, symWidth, symHeight,
1651                             refAggNum, 0, numInputSyms + i, NULL,
1652                             symCodeLen, bitmaps, 0, 0, 0, 1, 0,
1653                             huffTableF, huffTableH, huffTableK, huffTableO,
1654                             huffTableO, huffTableO, huffTableO, huffTableA,
1655                             sdrTemplate, sdrATX, sdrATY);
1656        }
1657
1658      // non-ref/agg coding
1659      } else {
1660        bitmaps[numInputSyms + i] =
1661            readGenericBitmap(gFalse, symWidth, symHeight,
1662                              sdTemplate, gFalse, gFalse, NULL,
1663                              sdATX, sdATY, 0);
1664      }
1665
1666      ++i;
1667    }
1668
1669    // read the collective bitmap
1670    if (huff && !refAgg) {
1671      huffDecoder->decodeInt(&bmSize, huffBMSizeTable);
1672      huffDecoder->reset();
1673      if (bmSize == 0) {
1674        collBitmap = new JBIG2Bitmap(0, totalWidth, symHeight);
1675        bmSize = symHeight * ((totalWidth + 7) >> 3);
1676        p = collBitmap->getDataPtr();
1677        for (k = 0; k < (Guint)bmSize; ++k) {
1678          *p++ = curStr->getChar();
1679        }
1680      } else {
1681        collBitmap = readGenericBitmap(gTrue, totalWidth, symHeight,
1682                                       0, gFalse, gFalse, NULL, NULL, NULL,
1683                                       bmSize);
1684      }
1685      x = 0;
1686      for (; j < i; ++j) {
1687        bitmaps[numInputSyms + j] =
1688            collBitmap->getSlice(x, 0, symWidths[j], symHeight);
1689        x += symWidths[j];
1690      }
1691      delete collBitmap;
1692    }
1693  }
1694
1695  // create the symbol dict object
1696  symbolDict = new JBIG2SymbolDict(segNum, numExSyms);
1697
1698  // exported symbol list
1699  i = j = 0;
1700  ex = gFalse;
1701  while (i < numInputSyms + numNewSyms) {
1702    if (huff) {
1703      huffDecoder->decodeInt(&run, huffTableA);
1704    } else {
1705      arithDecoder->decodeInt(&run, iaexStats);
1706    }
1707    if (ex) {
1708      for (cnt = 0; cnt < run; ++cnt) {
1709        symbolDict->setBitmap(j++, bitmaps[i++]->copy());
1710      }
1711    } else {
1712      i += run;
1713    }
1714    ex = !ex;
1715  }
1716
1717  for (i = 0; i < numNewSyms; ++i) {
1718    delete bitmaps[numInputSyms + i];
1719  }
1720  gfree(bitmaps);
1721  if (symWidths) {
1722    gfree(symWidths);
1723  }
1724
1725  // save the arithmetic decoder stats
1726  if (!huff && contextRetained) {
1727    symbolDict->setGenericRegionStats(genericRegionStats->copy());
1728    if (refAgg) {
1729      symbolDict->setRefinementRegionStats(refinementRegionStats->copy());
1730    }
1731  }
1732
1733  // store the new symbol dict
1734  segments->append(symbolDict);
1735
1736  return gTrue;
1737
1738 syntaxError:
1739  for (i = 0; i < numNewSyms; ++i) {
1740    if (bitmaps[numInputSyms + i]) {
1741      delete bitmaps[numInputSyms + i];
1742    }
1743  }
1744  gfree(bitmaps);
1745  if (symWidths) {
1746    gfree(symWidths);
1747  }
1748  return gFalse;
1749
1750 eofError:
1751  error(getPos(), "Unexpected EOF in JBIG2 stream");
1752  return gFalse;
1753}
1754
1755void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
1756                                    GBool lossless, Guint length,
1757                                    Guint *refSegs, Guint nRefSegs) {
1758  JBIG2Bitmap *bitmap;
1759  JBIG2HuffmanTable runLengthTab[36];
1760  JBIG2HuffmanTable *symCodeTab;
1761  JBIG2HuffmanTable *huffFSTable, *huffDSTable, *huffDTTable;
1762  JBIG2HuffmanTable *huffRDWTable, *huffRDHTable;
1763  JBIG2HuffmanTable *huffRDXTable, *huffRDYTable, *huffRSizeTable;
1764  JBIG2Segment *seg;
1765  GooList *codeTables;
1766  JBIG2SymbolDict *symbolDict;
1767  JBIG2Bitmap **syms;
1768  Guint w, h, x, y, segInfoFlags, extCombOp;
1769  Guint flags, huff, refine, logStrips, refCorner, transposed;
1770  Guint combOp, defPixel, templ;
1771  int sOffset;
1772  Guint huffFlags, huffFS, huffDS, huffDT;
1773  Guint huffRDW, huffRDH, huffRDX, huffRDY, huffRSize;
1774  Guint numInstances, numSyms, symCodeLen;
1775  int atx[2], aty[2];
1776  Guint i, k, kk;
1777  int j;
1778
1779  // region segment info field
1780  if (!readULong(&w) || !readULong(&h) ||
1781      !readULong(&x) || !readULong(&y) ||
1782      !readUByte(&segInfoFlags)) {
1783    goto eofError;
1784  }
1785  extCombOp = segInfoFlags & 7;
1786
1787  // rest of the text region header
1788  if (!readUWord(&flags)) {
1789    goto eofError;
1790  }
1791  huff = flags & 1;
1792  refine = (flags >> 1) & 1;
1793  logStrips = (flags >> 2) & 3;
1794  refCorner = (flags >> 4) & 3;
1795  transposed = (flags >> 6) & 1;
1796  combOp = (flags >> 7) & 3;
1797  defPixel = (flags >> 9) & 1;
1798  sOffset = (flags >> 10) & 0x1f;
1799  if (sOffset & 0x10) {
1800    sOffset |= -1 - 0x0f;
1801  }
1802  templ = (flags >> 15) & 1;
1803  huffFS = huffDS = huffDT = 0; // make gcc happy
1804  huffRDW = huffRDH = huffRDX = huffRDY = huffRSize = 0; // make gcc happy
1805  if (huff) {
1806    if (!readUWord(&huffFlags)) {
1807      goto eofError;
1808    }
1809    huffFS = huffFlags & 3;
1810    huffDS = (huffFlags >> 2) & 3;
1811    huffDT = (huffFlags >> 4) & 3;
1812    huffRDW = (huffFlags >> 6) & 3;
1813    huffRDH = (huffFlags >> 8) & 3;
1814    huffRDX = (huffFlags >> 10) & 3;
1815    huffRDY = (huffFlags >> 12) & 3;
1816    huffRSize = (huffFlags >> 14) & 1;
1817  }
1818  if (refine && templ == 0) {
1819    if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
1820        !readByte(&atx[1]) || !readByte(&aty[1])) {
1821      goto eofError;
1822    }
1823  }
1824  if (!readULong(&numInstances)) {
1825    goto eofError;
1826  }
1827
1828  // get symbol dictionaries and tables
1829  codeTables = new GooList();
1830  numSyms = 0;
1831  for (i = 0; i < nRefSegs; ++i) {
1832    if ((seg = findSegment(refSegs[i]))) {
1833      if (seg->getType() == jbig2SegSymbolDict) {
1834        numSyms += ((JBIG2SymbolDict *)seg)->getSize();
1835      } else if (seg->getType() == jbig2SegCodeTable) {
1836        codeTables->append(seg);
1837      }
1838    } else {
1839      error(getPos(), "Invalid segment reference in JBIG2 text region");
1840    }
1841  }
1842  symCodeLen = 0;
1843  i = 1;
1844  while (i < numSyms) {
1845    ++symCodeLen;
1846    i <<= 1;
1847  }
1848
1849  // get the symbol bitmaps
1850  syms = (JBIG2Bitmap **)gmallocn(numSyms, sizeof(JBIG2Bitmap *));
1851  kk = 0;
1852  for (i = 0; i < nRefSegs; ++i) {
1853    if ((seg = findSegment(refSegs[i]))) {
1854      if (seg->getType() == jbig2SegSymbolDict) {
1855        symbolDict = (JBIG2SymbolDict *)seg;
1856        for (k = 0; k < symbolDict->getSize(); ++k) {
1857          syms[kk++] = symbolDict->getBitmap(k);
1858        }
1859      }
1860    }
1861  }
1862
1863  // get the Huffman tables
1864  huffFSTable = huffDSTable = huffDTTable = NULL; // make gcc happy
1865  huffRDWTable = huffRDHTable = NULL; // make gcc happy
1866  huffRDXTable = huffRDYTable = huffRSizeTable = NULL; // make gcc happy
1867  i = 0;
1868  if (huff) {
1869    if (huffFS == 0) {
1870      huffFSTable = huffTableF;
1871    } else if (huffFS == 1) {
1872      huffFSTable = huffTableG;
1873    } else {
1874      huffFSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1875    }
1876    if (huffDS == 0) {
1877      huffDSTable = huffTableH;
1878    } else if (huffDS == 1) {
1879      huffDSTable = huffTableI;
1880    } else if (huffDS == 2) {
1881      huffDSTable = huffTableJ;
1882    } else {
1883      huffDSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1884    }
1885    if (huffDT == 0) {
1886      huffDTTable = huffTableK;
1887    } else if (huffDT == 1) {
1888      huffDTTable = huffTableL;
1889    } else if (huffDT == 2) {
1890      huffDTTable = huffTableM;
1891    } else {
1892      huffDTTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1893    }
1894    if (huffRDW == 0) {
1895      huffRDWTable = huffTableN;
1896    } else if (huffRDW == 1) {
1897      huffRDWTable = huffTableO;
1898    } else {
1899      huffRDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1900    }
1901    if (huffRDH == 0) {
1902      huffRDHTable = huffTableN;
1903    } else if (huffRDH == 1) {
1904      huffRDHTable = huffTableO;
1905    } else {
1906      huffRDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1907    }
1908    if (huffRDX == 0) {
1909      huffRDXTable = huffTableN;
1910    } else if (huffRDX == 1) {
1911      huffRDXTable = huffTableO;
1912    } else {
1913      huffRDXTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1914    }
1915    if (huffRDY == 0) {
1916      huffRDYTable = huffTableN;
1917    } else if (huffRDY == 1) {
1918      huffRDYTable = huffTableO;
1919    } else {
1920      huffRDYTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1921    }
1922    if (huffRSize == 0) {
1923      huffRSizeTable = huffTableA;
1924    } else {
1925      huffRSizeTable =
1926          ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1927    }
1928  }
1929  delete codeTables;
1930
1931  // symbol ID Huffman decoding table
1932  if (huff) {
1933    huffDecoder->reset();
1934    for (i = 0; i < 32; ++i) {
1935      runLengthTab[i].val = i;
1936      runLengthTab[i].prefixLen = huffDecoder->readBits(4);
1937      runLengthTab[i].rangeLen = 0;
1938    }
1939    runLengthTab[32].val = 0x103;
1940    runLengthTab[32].prefixLen = huffDecoder->readBits(4);
1941    runLengthTab[32].rangeLen = 2;
1942    runLengthTab[33].val = 0x203;
1943    runLengthTab[33].prefixLen = huffDecoder->readBits(4);
1944    runLengthTab[33].rangeLen = 3;
1945    runLengthTab[34].val = 0x20b;
1946    runLengthTab[34].prefixLen = huffDecoder->readBits(4);
1947    runLengthTab[34].rangeLen = 7;
1948    runLengthTab[35].prefixLen = 0;
1949    runLengthTab[35].rangeLen = jbig2HuffmanEOT;
1950    huffDecoder->buildTable(runLengthTab, 35);
1951    symCodeTab = (JBIG2HuffmanTable *)gmallocn(numSyms + 1,
1952                                               sizeof(JBIG2HuffmanTable));
1953    for (i = 0; i < numSyms; ++i) {
1954      symCodeTab[i].val = i;
1955      symCodeTab[i].rangeLen = 0;
1956    }
1957    i = 0;
1958    while (i < numSyms) {
1959      huffDecoder->decodeInt(&j, runLengthTab);
1960      if (j > 0x200) {
1961        for (j -= 0x200; j && i < numSyms; --j) {
1962          symCodeTab[i++].prefixLen = 0;
1963        }
1964      } else if (j > 0x100) {
1965        for (j -= 0x100; j && i < numSyms; --j) {
1966          symCodeTab[i].prefixLen = symCodeTab[i-1].prefixLen;
1967          ++i;
1968        }
1969      } else {
1970        symCodeTab[i++].prefixLen = j;
1971      }
1972    }
1973    symCodeTab[numSyms].prefixLen = 0;
1974    symCodeTab[numSyms].rangeLen = jbig2HuffmanEOT;
1975    huffDecoder->buildTable(symCodeTab, numSyms);
1976    huffDecoder->reset();
1977
1978  // set up the arithmetic decoder
1979  } else {
1980    symCodeTab = NULL;
1981    resetIntStats(symCodeLen);
1982    arithDecoder->start();
1983  }
1984  if (refine) {
1985    resetRefinementStats(templ, NULL);
1986  }
1987
1988  bitmap = readTextRegion(huff, refine, w, h, numInstances,
1989                          logStrips, numSyms, symCodeTab, symCodeLen, syms,
1990                          defPixel, combOp, transposed, refCorner, sOffset,
1991                          huffFSTable, huffDSTable, huffDTTable,
1992                          huffRDWTable, huffRDHTable,
1993                          huffRDXTable, huffRDYTable, huffRSizeTable,
1994                          templ, atx, aty);
1995
1996  gfree(syms);
1997
1998  // combine the region bitmap into the page bitmap
1999  if (imm) {
2000    if (pageH == 0xffffffff && y + h > curPageH) {
2001      pageBitmap->expand(y + h, pageDefPixel);
2002    }
2003    pageBitmap->combine(bitmap, x, y, extCombOp);
2004    delete bitmap;
2005
2006  // store the region bitmap
2007  } else {
2008    bitmap->setSegNum(segNum);
2009    segments->append(bitmap);
2010  }
2011
2012  // clean up the Huffman decoder
2013  if (huff) {
2014    gfree(symCodeTab);
2015  }
2016
2017  return;
2018
2019 eofError:
2020  error(getPos(), "Unexpected EOF in JBIG2 stream");
2021}
2022
2023JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine,
2024                                         int w, int h,
2025                                         Guint numInstances,
2026                                         Guint logStrips,
2027                                         int numSyms,
2028                                         JBIG2HuffmanTable *symCodeTab,
2029                                         Guint symCodeLen,
2030                                         JBIG2Bitmap **syms,
2031                                         Guint defPixel, Guint combOp,
2032                                         Guint transposed, Guint refCorner,
2033                                         int sOffset,
2034                                         JBIG2HuffmanTable *huffFSTable,
2035                                         JBIG2HuffmanTable *huffDSTable,
2036                                         JBIG2HuffmanTable *huffDTTable,
2037                                         JBIG2HuffmanTable *huffRDWTable,
2038                                         JBIG2HuffmanTable *huffRDHTable,
2039                                         JBIG2HuffmanTable *huffRDXTable,
2040                                         JBIG2HuffmanTable *huffRDYTable,
2041                                         JBIG2HuffmanTable *huffRSizeTable,
2042                                         Guint templ,
2043                                         int *atx, int *aty) {
2044  JBIG2Bitmap *bitmap;
2045  JBIG2Bitmap *symbolBitmap;
2046  Guint strips;
2047  int t, dt, tt, s, ds, sFirst, j;
2048  int rdw, rdh, rdx, rdy, ri, refDX, refDY, bmSize;
2049  Guint symID, inst, bw, bh;
2050
2051  strips = 1 << logStrips;
2052
2053  // allocate the bitmap
2054  bitmap = new JBIG2Bitmap(0, w, h);
2055  if (defPixel) {
2056    bitmap->clearToOne();
2057  } else {
2058    bitmap->clearToZero();
2059  }
2060
2061  // decode initial T value
2062  if (huff) {
2063    huffDecoder->decodeInt(&t, huffDTTable);
2064  } else {
2065    arithDecoder->decodeInt(&t, iadtStats);
2066  }
2067  t *= -(int)strips;
2068
2069  inst = 0;
2070  sFirst = 0;
2071  while (inst < numInstances) {
2072
2073    // decode delta-T
2074    if (huff) {
2075      huffDecoder->decodeInt(&dt, huffDTTable);
2076    } else {
2077      arithDecoder->decodeInt(&dt, iadtStats);
2078    }
2079    t += dt * strips;
2080
2081    // first S value
2082    if (huff) {
2083      huffDecoder->decodeInt(&ds, huffFSTable);
2084    } else {
2085      arithDecoder->decodeInt(&ds, iafsStats);
2086    }
2087    sFirst += ds;
2088    s = sFirst;
2089
2090    // read the instances
2091    while (1) {
2092
2093      // T value
2094      if (strips == 1) {
2095        dt = 0;
2096      } else if (huff) {
2097        dt = huffDecoder->readBits(logStrips);
2098      } else {
2099        arithDecoder->decodeInt(&dt, iaitStats);
2100      }
2101      tt = t + dt;
2102
2103      // symbol ID
2104      if (huff) {
2105        if (symCodeTab) {
2106          huffDecoder->decodeInt(&j, symCodeTab);
2107          symID = (Guint)j;
2108        } else {
2109          symID = huffDecoder->readBits(symCodeLen);
2110        }
2111      } else {
2112        symID = arithDecoder->decodeIAID(symCodeLen, iaidStats);
2113      }
2114
2115      if (symID >= (Guint)numSyms) {
2116        error(getPos(), "Invalid symbol number in JBIG2 text region");
2117      } else {
2118
2119        // get the symbol bitmap
2120        symbolBitmap = NULL;
2121        if (refine) {
2122          if (huff) {
2123            ri = (int)huffDecoder->readBit();
2124          } else {
2125            arithDecoder->decodeInt(&ri, iariStats);
2126          }
2127        } else {
2128          ri = 0;
2129        }
2130        if (ri) {
2131          if (huff) {
2132            huffDecoder->decodeInt(&rdw, huffRDWTable);
2133            huffDecoder->decodeInt(&rdh, huffRDHTable);
2134            huffDecoder->decodeInt(&rdx, huffRDXTable);
2135            huffDecoder->decodeInt(&rdy, huffRDYTable);
2136            huffDecoder->decodeInt(&bmSize, huffRSizeTable);
2137            huffDecoder->reset();
2138            arithDecoder->start();
2139          } else {
2140            arithDecoder->decodeInt(&rdw, iardwStats);
2141            arithDecoder->decodeInt(&rdh, iardhStats);
2142            arithDecoder->decodeInt(&rdx, iardxStats);
2143            arithDecoder->decodeInt(&rdy, iardyStats);
2144          }
2145          refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx;
2146          refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy;
2147
2148          symbolBitmap =
2149            readGenericRefinementRegion(rdw + syms[symID]->getWidth(),
2150                                        rdh + syms[symID]->getHeight(),
2151                                        templ, gFalse, syms[symID],
2152                                        refDX, refDY, atx, aty);
2153          //~ do we need to use the bmSize value here (in Huffman mode)?
2154        } else {
2155          symbolBitmap = syms[symID];
2156        }
2157
2158        // combine the symbol bitmap into the region bitmap
2159        //~ something is wrong here - refCorner shouldn't degenerate into
2160        //~   two cases
2161        bw = symbolBitmap->getWidth() - 1;
2162        bh = symbolBitmap->getHeight() - 1;
2163        if (transposed) {
2164          switch (refCorner) {
2165          case 0: // bottom left
2166            bitmap->combine(symbolBitmap, tt, s, combOp);
2167            break;
2168          case 1: // top left
2169            bitmap->combine(symbolBitmap, tt, s, combOp);
2170            break;
2171          case 2: // bottom right
2172            bitmap->combine(symbolBitmap, tt - bw, s, combOp);
2173            break;
2174          case 3: // top right
2175            bitmap->combine(symbolBitmap, tt - bw, s, combOp);
2176            break;
2177          }
2178          s += bh;
2179        } else {
2180          switch (refCorner) {
2181          case 0: // bottom left
2182            bitmap->combine(symbolBitmap, s, tt - bh, combOp);
2183            break;
2184          case 1: // top left
2185            bitmap->combine(symbolBitmap, s, tt, combOp);
2186            break;
2187          case 2: // bottom right
2188            bitmap->combine(symbolBitmap, s, tt - bh, combOp);
2189            break;
2190          case 3: // top right
2191            bitmap->combine(symbolBitmap, s, tt, combOp);
2192            break;
2193          }
2194          s += bw;
2195        }
2196        if (ri) {
2197          delete symbolBitmap;
2198        }
2199      }
2200
2201      // next instance
2202      ++inst;
2203
2204      // next S value
2205      if (huff) {
2206        if (!huffDecoder->decodeInt(&ds, huffDSTable)) {
2207          break;
2208        }
2209      } else {
2210        if (!arithDecoder->decodeInt(&ds, iadsStats)) {
2211          break;
2212        }
2213      }
2214      s += sOffset + ds;
2215    }
2216  }
2217
2218  return bitmap;
2219}
2220
2221void JBIG2Stream::readPatternDictSeg(Guint segNum, Guint length) {
2222  JBIG2PatternDict *patternDict;
2223  JBIG2Bitmap *bitmap;
2224  Guint flags, patternW, patternH, grayMax, templ, mmr;
2225  int atx[4], aty[4];
2226  Guint i, x;
2227
2228  // halftone dictionary flags, pattern width and height, max gray value
2229  if (!readUByte(&flags) ||
2230      !readUByte(&patternW) ||
2231      !readUByte(&patternH) ||
2232      !readULong(&grayMax)) {
2233    goto eofError;
2234  }
2235  templ = (flags >> 1) & 3;
2236  mmr = flags & 1;
2237
2238  // set up the arithmetic decoder
2239  if (!mmr) {
2240    resetGenericStats(templ, NULL);
2241    arithDecoder->start();
2242  }
2243
2244  // read the bitmap
2245  atx[0] = -(int)patternW; aty[0] =  0;
2246  atx[1] = -3;             aty[1] = -1;
2247  atx[2] =  2;             aty[2] = -2;
2248  atx[3] = -2;             aty[3] = -2;
2249  bitmap = readGenericBitmap(mmr, (grayMax + 1) * patternW, patternH,
2250                             templ, gFalse, gFalse, NULL,
2251                             atx, aty, length - 7);
2252
2253  // create the pattern dict object
2254  patternDict = new JBIG2PatternDict(segNum, grayMax + 1);
2255
2256  // split up the bitmap
2257  x = 0;
2258  for (i = 0; i <= grayMax; ++i) {
2259    patternDict->setBitmap(i, bitmap->getSlice(x, 0, patternW, patternH));
2260    x += patternW;
2261  }
2262
2263  // free memory
2264  delete bitmap;
2265
2266  // store the new pattern dict
2267  segments->append(patternDict);
2268
2269  return;
2270
2271 eofError:
2272  error(getPos(), "Unexpected EOF in JBIG2 stream");
2273}
2274
2275void JBIG2Stream::readHalftoneRegionSeg(Guint segNum, GBool imm,
2276                                        GBool lossless, Guint length,
2277                                        Guint *refSegs, Guint nRefSegs) {
2278  JBIG2Bitmap *bitmap;
2279  JBIG2Segment *seg;
2280  JBIG2PatternDict *patternDict;
2281  JBIG2Bitmap *skipBitmap;
2282  Guint *grayImg;
2283  JBIG2Bitmap *grayBitmap;
2284  JBIG2Bitmap *patternBitmap;
2285  Guint w, h, x, y, segInfoFlags, extCombOp;
2286  Guint flags, mmr, templ, enableSkip, combOp;
2287  Guint gridW, gridH, stepX, stepY, patW, patH;
2288  int atx[4], aty[4];
2289  int gridX, gridY, xx, yy, bit, j;
2290  Guint bpp, m, n, i;
2291
2292  // region segment info field
2293  if (!readULong(&w) || !readULong(&h) ||
2294      !readULong(&x) || !readULong(&y) ||
2295      !readUByte(&segInfoFlags)) {
2296    goto eofError;
2297  }
2298  extCombOp = segInfoFlags & 7;
2299
2300  // rest of the halftone region header
2301  if (!readUByte(&flags)) {
2302    goto eofError;
2303  }
2304  mmr = flags & 1;
2305  templ = (flags >> 1) & 3;
2306  enableSkip = (flags >> 3) & 1;
2307  combOp = (flags >> 4) & 7;
2308  if (!readULong(&gridW) || !readULong(&gridH) ||
2309      !readLong(&gridX) || !readLong(&gridY) ||
2310      !readUWord(&stepX) || !readUWord(&stepY)) {
2311    goto eofError;
2312  }
2313  if (w == 0 || h == 0 || w >= INT_MAX / h) {
2314    error(getPos(), "Bad bitmap size in JBIG2 halftone segment");
2315    return;
2316  }
2317  if (gridH == 0 || gridW >= INT_MAX / gridH) {
2318    error(getPos(), "Bad grid size in JBIG2 halftone segment");
2319    return;
2320  }
2321
2322  // get pattern dictionary
2323  if (nRefSegs != 1) {
2324    error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
2325    return;
2326  }
2327  seg = findSegment(refSegs[0]);
2328  if (seg->getType() != jbig2SegPatternDict) {
2329    error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
2330    return;
2331  }
2332  if (gridH == 0 || gridW >= INT_MAX / gridH) {
2333    error(getPos(), "Bad size in JBIG2 halftone segment");
2334    return;
2335  }
2336  if (w == 0 || h >= INT_MAX / w) {
2337     error(getPos(), "Bad size in JBIG2 bitmap segment");
2338    return;
2339  }
2340
2341  patternDict = (JBIG2PatternDict *)seg;
2342  bpp = 0;
2343  i = 1;
2344  while (i < patternDict->getSize()) {
2345    ++bpp;
2346    i <<= 1;
2347  }
2348  patW = patternDict->getBitmap(0)->getWidth();
2349  patH = patternDict->getBitmap(0)->getHeight();
2350
2351  // set up the arithmetic decoder
2352  if (!mmr) {
2353    resetGenericStats(templ, NULL);
2354    arithDecoder->start();
2355  }
2356
2357  // allocate the bitmap
2358  bitmap = new JBIG2Bitmap(segNum, w, h);
2359  if (flags & 0x80) { // HDEFPIXEL
2360    bitmap->clearToOne();
2361  } else {
2362    bitmap->clearToZero();
2363  }
2364
2365  // compute the skip bitmap
2366  skipBitmap = NULL;
2367  if (enableSkip) {
2368    skipBitmap = new JBIG2Bitmap(0, gridW, gridH);
2369    skipBitmap->clearToZero();
2370    for (m = 0; m < gridH; ++m) {
2371      xx = gridX + m * stepY;
2372      yy = gridY + m * stepX;
2373      for (n = 0; n < gridW; ++n) {
2374        if (((xx + (int)patW) >> 8) <= 0 || (xx >> 8) >= (int)w ||
2375            ((yy + (int)patH) >> 8) <= 0 || (yy >> 8) >= (int)h) {
2376          skipBitmap->setPixel(n, m);
2377        }
2378      }
2379    }
2380  }
2381
2382  // read the gray-scale image
2383  grayImg = (Guint *)gmallocn(gridW * gridH, sizeof(Guint));
2384  memset(grayImg, 0, gridW * gridH * sizeof(Guint));
2385  atx[0] = templ <= 1 ? 3 : 2;  aty[0] = -1;
2386  atx[1] = -3;                  aty[1] = -1;
2387  atx[2] =  2;                  aty[2] = -2;
2388  atx[3] = -2;                  aty[3] = -2;
2389  for (j = bpp - 1; j >= 0; --j) {
2390    grayBitmap = readGenericBitmap(mmr, gridW, gridH, templ, gFalse,
2391                                   enableSkip, skipBitmap, atx, aty, -1);
2392    i = 0;
2393    for (m = 0; m < gridH; ++m) {
2394      for (n = 0; n < gridW; ++n) {
2395        bit = grayBitmap->getPixel(n, m) ^ (grayImg[i] & 1);
2396        grayImg[i] = (grayImg[i] << 1) | bit;
2397        ++i;
2398      }
2399    }
2400    delete grayBitmap;
2401  }
2402
2403  // decode the image
2404  i = 0;
2405  for (m = 0; m < gridH; ++m) {
2406    xx = gridX + m * stepY;
2407    yy = gridY + m * stepX;
2408    for (n = 0; n < gridW; ++n) {
2409      if (!(enableSkip && skipBitmap->getPixel(n, m))) {
2410        patternBitmap = patternDict->getBitmap(grayImg[i]);
2411        bitmap->combine(patternBitmap, xx >> 8, yy >> 8, combOp);
2412      }
2413      xx += stepX;
2414      yy -= stepY;
2415      ++i;
2416    }
2417  }
2418
2419  gfree(grayImg);
2420
2421  // combine the region bitmap into the page bitmap
2422  if (imm) {
2423    if (pageH == 0xffffffff && y + h > curPageH) {
2424      pageBitmap->expand(y + h, pageDefPixel);
2425    }
2426    pageBitmap->combine(bitmap, x, y, extCombOp);
2427    delete bitmap;
2428
2429  // store the region bitmap
2430  } else {
2431    segments->append(bitmap);
2432  }
2433
2434  return;
2435
2436 eofError:
2437  error(getPos(), "Unexpected EOF in JBIG2 stream");
2438}
2439
2440void JBIG2Stream::readGenericRegionSeg(Guint segNum, GBool imm,
2441                                       GBool lossless, Guint length) {
2442  JBIG2Bitmap *bitmap;
2443  Guint w, h, x, y, segInfoFlags, extCombOp;
2444  Guint flags, mmr, templ, tpgdOn;
2445  int atx[4], aty[4];
2446
2447  // region segment info field
2448  if (!readULong(&w) || !readULong(&h) ||
2449      !readULong(&x) || !readULong(&y) ||
2450      !readUByte(&segInfoFlags)) {
2451    goto eofError;
2452  }
2453  extCombOp = segInfoFlags & 7;
2454
2455  // rest of the generic region segment header
2456  if (!readUByte(&flags)) {
2457    goto eofError;
2458  }
2459  mmr = flags & 1;
2460  templ = (flags >> 1) & 3;
2461  tpgdOn = (flags >> 3) & 1;
2462
2463  // AT flags
2464  if (!mmr) {
2465    if (templ == 0) {
2466      if (!readByte(&atx[0]) ||
2467          !readByte(&aty[0]) ||
2468          !readByte(&atx[1]) ||
2469          !readByte(&aty[1]) ||
2470          !readByte(&atx[2]) ||
2471          !readByte(&aty[2]) ||
2472          !readByte(&atx[3]) ||
2473          !readByte(&aty[3])) {
2474        goto eofError;
2475      }
2476    } else {
2477      if (!readByte(&atx[0]) ||
2478          !readByte(&aty[0])) {
2479        goto eofError;
2480      }
2481    }
2482  }
2483
2484  // set up the arithmetic decoder
2485  if (!mmr) {
2486    resetGenericStats(templ, NULL);
2487    arithDecoder->start();
2488  }
2489
2490  // read the bitmap
2491  bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse,
2492                             NULL, atx, aty, mmr ? 0 : length - 18);
2493
2494  // combine the region bitmap into the page bitmap
2495  if (imm) {
2496    if (pageH == 0xffffffff && y + h > curPageH) {
2497      pageBitmap->expand(y + h, pageDefPixel);
2498    }
2499    pageBitmap->combine(bitmap, x, y, extCombOp);
2500    delete bitmap;
2501
2502  // store the region bitmap
2503  } else {
2504    bitmap->setSegNum(segNum);
2505    segments->append(bitmap);
2506  }
2507
2508  return;
2509
2510 eofError:
2511  error(getPos(), "Unexpected EOF in JBIG2 stream");
2512}
2513
2514JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
2515                                            int templ, GBool tpgdOn,
2516                                            GBool useSkip, JBIG2Bitmap *skip,
2517                                            int *atx, int *aty,
2518                                            int mmrDataLength) {
2519  JBIG2Bitmap *bitmap;
2520  GBool ltp;
2521  Guint ltpCX, cx, cx0, cx1, cx2;
2522  JBIG2BitmapPtr cxPtr0, cxPtr1;
2523  JBIG2BitmapPtr atPtr0, atPtr1, atPtr2, atPtr3;
2524  int *refLine, *codingLine;
2525  int code1, code2, code3;
2526  int x, y, a0, pix, i, refI, codingI;
2527
2528  bitmap = new JBIG2Bitmap(0, w, h);
2529  bitmap->clearToZero();
2530
2531  //----- MMR decode
2532
2533  if (mmr) {
2534
2535    mmrDecoder->reset();
2536    refLine = (int *)gmallocn(w + 2, sizeof(int));
2537    codingLine = (int *)gmallocn(w + 2, sizeof(int));
2538    codingLine[0] = codingLine[1] = w;
2539
2540    for (y = 0; y < h; ++y) {
2541
2542      // copy coding line to ref line
2543      for (i = 0; codingLine[i] < w; ++i) {
2544        refLine[i] = codingLine[i];
2545      }
2546      refLine[i] = refLine[i + 1] = w;
2547
2548      // decode a line
2549      refI = 0;     // b1 = refLine[refI]
2550      codingI = 0;  // a1 = codingLine[codingI]
2551      a0 = 0;
2552      do {
2553        code1 = mmrDecoder->get2DCode();
2554        switch (code1) {
2555        case twoDimPass:
2556          if (refLine[refI] < w) {
2557            a0 = refLine[refI + 1];
2558            refI += 2;
2559          }
2560          break;
2561        case twoDimHoriz:
2562          if (codingI & 1) {
2563            code1 = 0;
2564            do {
2565              code1 += code3 = mmrDecoder->getBlackCode();
2566            } while (code3 >= 64);
2567            code2 = 0;
2568            do {
2569              code2 += code3 = mmrDecoder->getWhiteCode();
2570            } while (code3 >= 64);
2571          } else {
2572            code1 = 0;
2573            do {
2574              code1 += code3 = mmrDecoder->getWhiteCode();
2575            } while (code3 >= 64);
2576            code2 = 0;
2577            do {
2578              code2 += code3 = mmrDecoder->getBlackCode();
2579            } while (code3 >= 64);
2580          }
2581          if (code1 > 0 || code2 > 0) {
2582            a0 = codingLine[codingI++] = a0 + code1;
2583            a0 = codingLine[codingI++] = a0 + code2;
2584            while (refLine[refI] <= a0 && refLine[refI] < w) {
2585              refI += 2;
2586            }
2587          }
2588          break;
2589        case twoDimVert0:
2590          a0 = codingLine[codingI++] = refLine[refI];
2591          if (refLine[refI] < w) {
2592            ++refI;
2593          }
2594          break;
2595        case twoDimVertR1:
2596          a0 = codingLine[codingI++] = refLine[refI] + 1;
2597          if (refLine[refI] < w) {
2598            ++refI;
2599            while (refLine[refI] <= a0 && refLine[refI] < w) {
2600              refI += 2;
2601            }
2602          }
2603          break;
2604        case twoDimVertR2:
2605          a0 = codingLine[codingI++] = refLine[refI] + 2;
2606          if (refLine[refI] < w) {
2607            ++refI;
2608            while (refLine[refI] <= a0 && refLine[refI] < w) {
2609              refI += 2;
2610            }
2611          }
2612          break;
2613        case twoDimVertR3:
2614          a0 = codingLine[codingI++] = refLine[refI] + 3;
2615          if (refLine[refI] < w) {
2616            ++refI;
2617            while (refLine[refI] <= a0 && refLine[refI] < w) {
2618              refI += 2;
2619            }
2620          }
2621          break;
2622        case twoDimVertL1:
2623          a0 = codingLine[codingI++] = refLine[refI] - 1;
2624          if (refI > 0) {
2625            --refI;
2626          } else {
2627            ++refI;
2628          }
2629          while (refLine[refI] <= a0 && refLine[refI] < w) {
2630            refI += 2;
2631          }
2632          break;
2633        case twoDimVertL2:
2634          a0 = codingLine[codingI++] = refLine[refI] - 2;
2635          if (refI > 0) {
2636            --refI;
2637          } else {
2638            ++refI;
2639          }
2640          while (refLine[refI] <= a0 && refLine[refI] < w) {
2641            refI += 2;
2642          }
2643          break;
2644        case twoDimVertL3:
2645          a0 = codingLine[codingI++] = refLine[refI] - 3;
2646          if (refI > 0) {
2647            --refI;
2648          } else {
2649            ++refI;
2650          }
2651          while (refLine[refI] <= a0 && refLine[refI] < w) {
2652            refI += 2;
2653          }
2654          break;
2655        default:
2656          error(getPos(), "Illegal code in JBIG2 MMR bitmap data");
2657          break;
2658        }
2659      } while (a0 < w);
2660      codingLine[codingI++] = w;
2661
2662      // convert the run lengths to a bitmap line
2663      i = 0;
2664      while (codingLine[i] < w) {
2665        for (x = codingLine[i]; x < codingLine[i+1]; ++x) {
2666          bitmap->setPixel(x, y);
2667        }
2668        i += 2;
2669      }
2670    }
2671
2672    if (mmrDataLength >= 0) {
2673      mmrDecoder->skipTo(mmrDataLength);
2674    } else {
2675      if (mmrDecoder->get24Bits() != 0x001001) {
2676        error(getPos(), "Missing EOFB in JBIG2 MMR bitmap data");
2677      }
2678    }
2679
2680    gfree(refLine);
2681    gfree(codingLine);
2682
2683  //----- arithmetic decode
2684
2685  } else {
2686    // set up the typical row context
2687    ltpCX = 0; // make gcc happy
2688    if (tpgdOn) {
2689      switch (templ) {
2690      case 0:
2691        ltpCX = 0x3953; // 001 11001 0101 0011
2692        break;
2693      case 1:
2694        ltpCX = 0x079a; // 0011 11001 101 0
2695        break;
2696      case 2:
2697        ltpCX = 0x0e3; // 001 1100 01 1
2698        break;
2699      case 3:
2700        ltpCX = 0x18a; // 01100 0101 1
2701        break;
2702      }
2703    }
2704
2705    ltp = 0;
2706    cx = cx0 = cx1 = cx2 = 0; // make gcc happy
2707    for (y = 0; y < h; ++y) {
2708
2709      // check for a "typical" (duplicate) row
2710      if (tpgdOn) {
2711        if (arithDecoder->decodeBit(ltpCX, genericRegionStats)) {
2712          ltp = !ltp;
2713        }
2714        if (ltp) {
2715          bitmap->duplicateRow(y, y-1);
2716          continue;
2717        }
2718      }
2719
2720      switch (templ) {
2721      case 0:
2722
2723        // set up the context
2724        bitmap->getPixelPtr(0, y-2, &cxPtr0);
2725        cx0 = bitmap->nextPixel(&cxPtr0);
2726        cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
2727        bitmap->getPixelPtr(0, y-1, &cxPtr1);
2728        cx1 = bitmap->nextPixel(&cxPtr1);
2729        cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
2730        cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
2731        cx2 = 0;
2732        bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
2733        bitmap->getPixelPtr(atx[1], y + aty[1], &atPtr1);
2734        bitmap->getPixelPtr(atx[2], y + aty[2], &atPtr2);
2735        bitmap->getPixelPtr(atx[3], y + aty[3], &atPtr3);
2736
2737        // decode the row
2738        for (x = 0; x < w; ++x) {
2739
2740          // build the context
2741          cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) |
2742               (bitmap->nextPixel(&atPtr0) << 3) |
2743               (bitmap->nextPixel(&atPtr1) << 2) |
2744               (bitmap->nextPixel(&atPtr2) << 1) |
2745               bitmap->nextPixel(&atPtr3);
2746
2747          // check for a skipped pixel
2748          if (useSkip && skip->getPixel(x, y)) {
2749            pix = 0;
2750
2751          // decode the pixel
2752          } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
2753            bitmap->setPixel(x, y);
2754          }
2755
2756          // update the context
2757          cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07;
2758          cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
2759          cx2 = ((cx2 << 1) | pix) & 0x0f;
2760        }
2761        break;
2762
2763      case 1:
2764
2765        // set up the context
2766        bitmap->getPixelPtr(0, y-2, &cxPtr0);
2767        cx0 = bitmap->nextPixel(&cxPtr0);
2768        cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
2769        cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
2770        bitmap->getPixelPtr(0, y-1, &cxPtr1);
2771        cx1 = bitmap->nextPixel(&cxPtr1);
2772        cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
2773        cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
2774        cx2 = 0;
2775        bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
2776
2777        // decode the row
2778        for (x = 0; x < w; ++x) {
2779
2780          // build the context
2781          cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) |
2782               bitmap->nextPixel(&atPtr0);
2783
2784          // check for a skipped pixel
2785          if (useSkip && skip->getPixel(x, y)) {
2786            pix = 0;
2787
2788          // decode the pixel
2789          } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
2790            bitmap->setPixel(x, y);
2791          }
2792
2793          // update the context
2794          cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x0f;
2795          cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
2796          cx2 = ((cx2 << 1) | pix) & 0x07;
2797        }
2798        break;
2799
2800      case 2:
2801
2802        // set up the context
2803        bitmap->getPixelPtr(0, y-2, &cxPtr0);
2804        cx0 = bitmap->nextPixel(&cxPtr0);
2805        cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
2806        bitmap->getPixelPtr(0, y-1, &cxPtr1);
2807        cx1 = bitmap->nextPixel(&cxPtr1);
2808        cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
2809        cx2 = 0;
2810        bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
2811
2812        // decode the row
2813        for (x = 0; x < w; ++x) {
2814
2815          // build the context
2816          cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) |
2817               bitmap->nextPixel(&atPtr0);
2818
2819          // check for a skipped pixel
2820          if (useSkip && skip->getPixel(x, y)) {
2821            pix = 0;
2822
2823          // decode the pixel
2824          } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
2825            bitmap->setPixel(x, y);
2826          }
2827
2828          // update the context
2829          cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07;
2830          cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x0f;
2831          cx2 = ((cx2 << 1) | pix) & 0x03;
2832        }
2833        break;
2834
2835      case 3:
2836
2837        // set up the context
2838        bitmap->getPixelPtr(0, y-1, &cxPtr1);
2839        cx1 = bitmap->nextPixel(&cxPtr1);
2840        cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
2841        cx2 = 0;
2842        bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
2843
2844        // decode the row
2845        for (x = 0; x < w; ++x) {
2846
2847          // build the context
2848          cx = (cx1 << 5) | (cx2 << 1) |
2849               bitmap->nextPixel(&atPtr0);
2850
2851          // check for a skipped pixel
2852          if (useSkip && skip->getPixel(x, y)) {
2853            pix = 0;
2854
2855          // decode the pixel
2856          } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
2857            bitmap->setPixel(x, y);
2858          }
2859
2860          // update the context
2861          cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
2862          cx2 = ((cx2 << 1) | pix) & 0x0f;
2863        }
2864        break;
2865      }
2866    }
2867  }
2868
2869  return bitmap;
2870}
2871
2872void JBIG2Stream::readGenericRefinementRegionSeg(Guint segNum, GBool imm,
2873                                                 GBool lossless, Guint length,
2874                                                 Guint *refSegs,
2875                                                 Guint nRefSegs) {
2876  JBIG2Bitmap *bitmap, *refBitmap;
2877  Guint w, h, x, y, segInfoFlags, extCombOp;
2878  Guint flags, templ, tpgrOn;
2879  int atx[2], aty[2];
2880  JBIG2Segment *seg;
2881
2882  // region segment info field
2883  if (!readULong(&w) || !readULong(&h) ||
2884      !readULong(&x) || !readULong(&y) ||
2885      !readUByte(&segInfoFlags)) {
2886    goto eofError;
2887  }
2888  extCombOp = segInfoFlags & 7;
2889
2890  // rest of the generic refinement region segment header
2891  if (!readUByte(&flags)) {
2892    goto eofError;
2893  }
2894  templ = flags & 1;
2895  tpgrOn = (flags >> 1) & 1;
2896
2897  // AT flags
2898  if (!templ) {
2899    if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
2900        !readByte(&atx[1]) || !readByte(&aty[1])) {
2901      goto eofError;
2902    }
2903  }
2904
2905  // resize the page bitmap if needed
2906  if (nRefSegs == 0 || imm) {
2907    if (pageH == 0xffffffff && y + h > curPageH) {
2908      pageBitmap->expand(y + h, pageDefPixel);
2909    }
2910  }
2911
2912  // get referenced bitmap
2913  if (nRefSegs > 1) {
2914    error(getPos(), "Bad reference in JBIG2 generic refinement segment");
2915    return;
2916  }
2917  if (nRefSegs == 1) {
2918    seg = findSegment(refSegs[0]);
2919    if (seg->getType() != jbig2SegBitmap) {
2920      error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment");
2921      return;
2922    }
2923    refBitmap = (JBIG2Bitmap *)seg;
2924  } else {
2925    refBitmap = pageBitmap->getSlice(x, y, w, h);
2926  }
2927
2928  // set up the arithmetic decoder
2929  resetRefinementStats(templ, NULL);
2930  arithDecoder->start();
2931
2932  // read
2933  bitmap = readGenericRefinementRegion(w, h, templ, tpgrOn,
2934                                       refBitmap, 0, 0, atx, aty);
2935
2936  // combine the region bitmap into the page bitmap
2937  if (imm) {
2938    pageBitmap->combine(bitmap, x, y, extCombOp);
2939    delete bitmap;
2940
2941  // store the region bitmap
2942  } else {
2943    bitmap->setSegNum(segNum);
2944    segments->append(bitmap);
2945  }
2946
2947  // delete the referenced bitmap
2948  if (nRefSegs == 1) {
2949    discardSegment(refSegs[0]);
2950  } else {
2951    delete refBitmap;
2952  }
2953
2954  return;
2955
2956 eofError:
2957  error(getPos(), "Unexpected EOF in JBIG2 stream");
2958}
2959
2960JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h,
2961                                                      int templ, GBool tpgrOn,
2962                                                      JBIG2Bitmap *refBitmap,
2963                                                      int refDX, int refDY,
2964                                                      int *atx, int *aty) {
2965  JBIG2Bitmap *bitmap;
2966  GBool ltp;
2967  Guint ltpCX, cx, cx0, cx2, cx3, cx4, tpgrCX0, tpgrCX1, tpgrCX2;
2968  JBIG2BitmapPtr cxPtr0, cxPtr1, cxPtr2, cxPtr3, cxPtr4, cxPtr5, cxPtr6;
2969  JBIG2BitmapPtr tpgrCXPtr0, tpgrCXPtr1, tpgrCXPtr2;
2970  int x, y, pix;
2971
2972  if (w < 0 || h <= 0 || w >= INT_MAX / h) {
2973    error(-1, "invalid width/height");
2974    return NULL;
2975  }
2976
2977  bitmap = new JBIG2Bitmap(0, w, h);
2978  bitmap->clearToZero();
2979
2980  // set up the typical row context
2981  if (templ) {
2982    ltpCX = 0x008;
2983  } else {
2984    ltpCX = 0x0010;
2985  }
2986
2987  ltp = 0;
2988  for (y = 0; y < h; ++y) {
2989
2990    if (templ) {
2991
2992      // set up the context
2993      bitmap->getPixelPtr(0, y-1, &cxPtr0);
2994      cx0 = bitmap->nextPixel(&cxPtr0);
2995      bitmap->getPixelPtr(-1, y, &cxPtr1);
2996      refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2);
2997      refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3);
2998      cx3 = refBitmap->nextPixel(&cxPtr3);
2999      cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3);
3000      refBitmap->getPixelPtr(-refDX, y+1-refDY, &cxPtr4);
3001      cx4 = refBitmap->nextPixel(&cxPtr4);
3002
3003      // set up the typical prediction context
3004      tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
3005      if (tpgrOn) {
3006        refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0);
3007        tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0);
3008        tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
3009        tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
3010        refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1);
3011        tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1);
3012        tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
3013        tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
3014        refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2);
3015        tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2);
3016        tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
3017        tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
3018      }
3019
3020      for (x = 0; x < w; ++x) {
3021
3022        // update the context
3023        cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 7;
3024        cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7;
3025        cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 3;
3026
3027        if (tpgrOn) {
3028          // update the typical predictor context
3029          tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7;
3030          tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7;
3031          tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7;
3032
3033          // check for a "typical" pixel
3034          if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) {
3035            ltp = !ltp;
3036          }
3037          if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
3038            bitmap->clearPixel(x, y);
3039            continue;
3040          } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
3041            bitmap->setPixel(x, y);
3042            continue;
3043          }
3044        }
3045
3046        // build the context
3047        cx = (cx0 << 7) | (bitmap->nextPixel(&cxPtr1) << 6) |
3048             (refBitmap->nextPixel(&cxPtr2) << 5) |
3049             (cx3 << 2) | cx4;
3050
3051        // decode the pixel
3052        if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
3053          bitmap->setPixel(x, y);
3054        }
3055      }
3056
3057    } else {
3058
3059      // set up the context
3060      bitmap->getPixelPtr(0, y-1, &cxPtr0);
3061      cx0 = bitmap->nextPixel(&cxPtr0);
3062      bitmap->getPixelPtr(-1, y, &cxPtr1);
3063      refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2);
3064      cx2 = refBitmap->nextPixel(&cxPtr2);
3065      refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3);
3066      cx3 = refBitmap->nextPixel(&cxPtr3);
3067      cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3);
3068      refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &cxPtr4);
3069      cx4 = refBitmap->nextPixel(&cxPtr4);
3070      cx4 = (cx4 << 1) | refBitmap->nextPixel(&cxPtr4);
3071      bitmap->getPixelPtr(atx[0], y+aty[0], &cxPtr5);
3072      refBitmap->getPixelPtr(atx[1]-refDX, y+aty[1]-refDY, &cxPtr6);
3073
3074      // set up the typical prediction context
3075      tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
3076      if (tpgrOn) {
3077        refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0);
3078        tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0);
3079        tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
3080        tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
3081        refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1);
3082        tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1);
3083        tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
3084        tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
3085        refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2);
3086        tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2);
3087        tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
3088        tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
3089      }
3090
3091      for (x = 0; x < w; ++x) {
3092
3093        // update the context
3094        cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 3;
3095        cx2 = ((cx2 << 1) | refBitmap->nextPixel(&cxPtr2)) & 3;
3096        cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7;
3097        cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 7;
3098
3099        if (tpgrOn) {
3100          // update the typical predictor context
3101          tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7;
3102          tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7;
3103          tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7;
3104
3105          // check for a "typical" pixel
3106          if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) {
3107            ltp = !ltp;
3108          }
3109          if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
3110            bitmap->clearPixel(x, y);
3111            continue;
3112          } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
3113            bitmap->setPixel(x, y);
3114            continue;
3115          }
3116        }
3117
3118        // build the context
3119        cx = (cx0 << 11) | (bitmap->nextPixel(&cxPtr1) << 10) |
3120             (cx2 << 8) | (cx3 << 5) | (cx4 << 2) |
3121             (bitmap->nextPixel(&cxPtr5) << 1) |
3122             refBitmap->nextPixel(&cxPtr6);
3123
3124        // decode the pixel
3125        if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
3126          bitmap->setPixel(x, y);
3127        }
3128      }
3129    }
3130  }
3131
3132  return bitmap;
3133}
3134
3135void JBIG2Stream::readPageInfoSeg(Guint length) {
3136  Guint xRes, yRes, flags, striping;
3137
3138  if (!readULong(&pageW) || !readULong(&pageH) ||
3139      !readULong(&xRes) || !readULong(&yRes) ||
3140      !readUByte(&flags) || !readUWord(&striping)) {
3141    goto eofError;
3142  }
3143  pageDefPixel = (flags >> 2) & 1;
3144  defCombOp = (flags >> 3) & 3;
3145
3146  // allocate the page bitmap
3147  if (pageH == 0xffffffff) {
3148    curPageH = striping & 0x7fff;
3149  } else {
3150    curPageH = pageH;
3151  }
3152  pageBitmap = new JBIG2Bitmap(0, pageW, curPageH);
3153
3154  // default pixel value
3155  if (pageDefPixel) {
3156    pageBitmap->clearToOne();
3157  } else {
3158    pageBitmap->clearToZero();
3159  }
3160
3161  return;
3162
3163 eofError:
3164  error(getPos(), "Unexpected EOF in JBIG2 stream");
3165}
3166
3167void JBIG2Stream::readEndOfStripeSeg(Guint length) {
3168  Guint i;
3169
3170  // skip the segment
3171  for (i = 0; i < length; ++i) {
3172    curStr->getChar();
3173  }
3174}
3175
3176void JBIG2Stream::readProfilesSeg(Guint length) {
3177  Guint i;
3178
3179  // skip the segment
3180  for (i = 0; i < length; ++i) {
3181    curStr->getChar();
3182  }
3183}
3184
3185void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) {
3186  JBIG2HuffmanTable *huffTab;
3187  Guint flags, oob, prefixBits, rangeBits;
3188  int lowVal, highVal, val;
3189  Guint huffTabSize, i;
3190
3191  if (!readUByte(&flags) || !readLong(&lowVal) || !readLong(&highVal)) {
3192    goto eofError;
3193  }
3194  oob = flags & 1;
3195  prefixBits = ((flags >> 1) & 7) + 1;
3196  rangeBits = ((flags >> 4) & 7) + 1;
3197
3198  huffDecoder->reset();
3199  huffTabSize = 8;
3200  huffTab = (JBIG2HuffmanTable *)
3201                gmallocn(huffTabSize, sizeof(JBIG2HuffmanTable));
3202  i = 0;
3203  val = lowVal;
3204  while (val < highVal) {
3205    if (i == huffTabSize) {
3206      huffTabSize *= 2;
3207      huffTab = (JBIG2HuffmanTable *)
3208                    greallocn(huffTab, huffTabSize, sizeof(JBIG2HuffmanTable));
3209    }
3210    huffTab[i].val = val;
3211    huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
3212    huffTab[i].rangeLen = huffDecoder->readBits(rangeBits);
3213    val += 1 << huffTab[i].rangeLen;
3214    ++i;
3215  }
3216  if (i + oob + 3 > huffTabSize) {
3217    huffTabSize = i + oob + 3;
3218    huffTab = (JBIG2HuffmanTable *)
3219                  greallocn(huffTab, huffTabSize, sizeof(JBIG2HuffmanTable));
3220  }
3221  huffTab[i].val = lowVal - 1;
3222  huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
3223  huffTab[i].rangeLen = jbig2HuffmanLOW;
3224  ++i;
3225  huffTab[i].val = highVal;
3226  huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
3227  huffTab[i].rangeLen = 32;
3228  ++i;
3229  if (oob) {
3230    huffTab[i].val = 0;
3231    huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
3232    huffTab[i].rangeLen = jbig2HuffmanOOB;
3233    ++i;
3234  }
3235  huffTab[i].val = 0;
3236  huffTab[i].prefixLen = 0;
3237  huffTab[i].rangeLen = jbig2HuffmanEOT;
3238  huffDecoder->buildTable(huffTab, i);
3239
3240  // create and store the new table segment
3241  segments->append(new JBIG2CodeTable(segNum, huffTab));
3242
3243  return;
3244
3245 eofError:
3246  error(getPos(), "Unexpected EOF in JBIG2 stream");
3247}
3248
3249void JBIG2Stream::readExtensionSeg(Guint length) {
3250  Guint i;
3251
3252  // skip the segment
3253  for (i = 0; i < length; ++i) {
3254    curStr->getChar();
3255  }
3256}
3257
3258JBIG2Segment *JBIG2Stream::findSegment(Guint segNum) {
3259  JBIG2Segment *seg;
3260  int i;
3261
3262  for (i = 0; i < globalSegments->getLength(); ++i) {
3263    seg = (JBIG2Segment *)globalSegments->get(i);
3264    if (seg->getSegNum() == segNum) {
3265      return seg;
3266    }
3267  }
3268  for (i = 0; i < segments->getLength(); ++i) {
3269    seg = (JBIG2Segment *)segments->get(i);
3270    if (seg->getSegNum() == segNum) {
3271      return seg;
3272    }
3273  }
3274  return NULL;
3275}
3276
3277void JBIG2Stream::discardSegment(Guint segNum) {
3278  JBIG2Segment *seg;
3279  int i;
3280
3281  for (i = 0; i < globalSegments->getLength(); ++i) {
3282    seg = (JBIG2Segment *)globalSegments->get(i);
3283    if (seg->getSegNum() == segNum) {
3284      globalSegments->del(i);
3285      return;
3286    }
3287  }
3288  for (i = 0; i < segments->getLength(); ++i) {
3289    seg = (JBIG2Segment *)segments->get(i);
3290    if (seg->getSegNum() == segNum) {
3291      segments->del(i);
3292      return;
3293    }
3294  }
3295}
3296
3297void JBIG2Stream::resetGenericStats(Guint templ,
3298                                    JArithmeticDecoderStats *prevStats) {
3299  int size;
3300
3301  size = contextSize[templ];
3302  if (prevStats && prevStats->getContextSize() == size) {
3303    if (genericRegionStats->getContextSize() == size) {
3304      genericRegionStats->copyFrom(prevStats);
3305    } else {
3306      delete genericRegionStats;
3307      genericRegionStats = prevStats->copy();
3308    }
3309  } else {
3310    if (genericRegionStats->getContextSize() == size) {
3311      genericRegionStats->reset();
3312    } else {
3313      delete genericRegionStats;
3314      genericRegionStats = new JArithmeticDecoderStats(1 << size);
3315    }
3316  }
3317}
3318
3319void JBIG2Stream::resetRefinementStats(Guint templ,
3320                                       JArithmeticDecoderStats *prevStats) {
3321  int size;
3322
3323  size = refContextSize[templ];
3324  if (prevStats && prevStats->getContextSize() == size) {
3325    if (refinementRegionStats->getContextSize() == size) {
3326      refinementRegionStats->copyFrom(prevStats);
3327    } else {
3328      delete refinementRegionStats;
3329      refinementRegionStats = prevStats->copy();
3330    }
3331  } else {
3332    if (refinementRegionStats->getContextSize() == size) {
3333      refinementRegionStats->reset();
3334    } else {
3335      delete refinementRegionStats;
3336      refinementRegionStats = new JArithmeticDecoderStats(1 << size);
3337    }
3338  }
3339}
3340
3341void JBIG2Stream::resetIntStats(int symCodeLen) {
3342  iadhStats->reset();
3343  iadwStats->reset();
3344  iaexStats->reset();
3345  iaaiStats->reset();
3346  iadtStats->reset();
3347  iaitStats->reset();
3348  iafsStats->reset();
3349  iadsStats->reset();
3350  iardxStats->reset();
3351  iardyStats->reset();
3352  iardwStats->reset();
3353  iardhStats->reset();
3354  iariStats->reset();
3355  if (iaidStats->getContextSize() == symCodeLen + 1) {
3356    iaidStats->reset();
3357  } else {
3358    delete iaidStats;
3359    iaidStats = new JArithmeticDecoderStats(1 << (symCodeLen + 1));
3360  }
3361}
3362
3363GBool JBIG2Stream::readUByte(Guint *x) {
3364  int c0;
3365
3366  if ((c0 = curStr->getChar()) == EOF) {
3367    return gFalse;
3368  }
3369  *x = (Guint)c0;
3370  return gTrue;
3371}
3372
3373GBool JBIG2Stream::readByte(int *x) {
3374 int c0;
3375
3376  if ((c0 = curStr->getChar()) == EOF) {
3377    return gFalse;
3378  }
3379  *x = c0;
3380  if (c0 & 0x80) {
3381    *x |= -1 - 0xff;
3382  }
3383  return gTrue;
3384}
3385
3386GBool JBIG2Stream::readUWord(Guint *x) {
3387  int c0, c1;
3388
3389  if ((c0 = curStr->getChar()) == EOF ||
3390      (c1 = curStr->getChar()) == EOF) {
3391    return gFalse;
3392  }
3393  *x = (Guint)((c0 << 8) | c1);
3394  return gTrue;
3395}
3396
3397GBool JBIG2Stream::readULong(Guint *x) {
3398  int c0, c1, c2, c3;
3399
3400  if ((c0 = curStr->getChar()) == EOF ||
3401      (c1 = curStr->getChar()) == EOF ||
3402      (c2 = curStr->getChar()) == EOF ||
3403      (c3 = curStr->getChar()) == EOF) {
3404    return gFalse;
3405  }
3406  *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
3407  return gTrue;
3408}
3409
3410GBool JBIG2Stream::readLong(int *x) {
3411  int c0, c1, c2, c3;
3412
3413  if ((c0 = curStr->getChar()) == EOF ||
3414      (c1 = curStr->getChar()) == EOF ||
3415      (c2 = curStr->getChar()) == EOF ||
3416      (c3 = curStr->getChar()) == EOF) {
3417    return gFalse;
3418  }
3419  *x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
3420  if (c0 & 0x80) {
3421    *x |= -1 - (int)0xffffffff;
3422  }
3423  return gTrue;
3424}
Note: See TracBrowser for help on using the repository browser.