"Fossies" - the Fresh Open Source Software Archive

Member "xpdf-4.04/xpdf/JBIG2Stream.cc" (18 Apr 2022, 109724 Bytes) of package /linux/misc/xpdf-4.04.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "JBIG2Stream.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.03_vs_4.04.

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