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

Last change on this file since 250 was 250, checked in by Eugene Romanenko, 13 years ago

PDF plugin: poppler library updated to version 0.8.3

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