"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.

    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 }