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

Last change on this file since 461 was 461, checked in by Silvan Scherrer, 11 years ago

poppler update to 0.14.2

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