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