Back to index

tetex-bin  3.0
JBIG2Stream.cc
Go to the documentation of this file.
00001 //========================================================================
00002 //
00003 // JBIG2Stream.cc
00004 //
00005 // Copyright 2002-2003 Glyph & Cog, LLC
00006 //
00007 //========================================================================
00008 
00009 #include <aconf.h>
00010 
00011 #ifdef USE_GCC_PRAGMAS
00012 #pragma implementation
00013 #endif
00014 
00015 #include <stdlib.h>
00016 #include "GList.h"
00017 #include "Error.h"
00018 #include "JArithmeticDecoder.h"
00019 #include "JBIG2Stream.h"
00020 
00021 //~ share these tables
00022 #include "Stream-CCITT.h"
00023 
00024 //------------------------------------------------------------------------
00025 
00026 static int contextSize[4] = { 16, 13, 10, 10 };
00027 static int refContextSize[2] = { 13, 10 };
00028 
00029 //------------------------------------------------------------------------
00030 // JBIG2HuffmanTable
00031 //------------------------------------------------------------------------
00032 
00033 #define jbig2HuffmanLOW 0xfffffffd
00034 #define jbig2HuffmanOOB 0xfffffffe
00035 #define jbig2HuffmanEOT 0xffffffff
00036 
00037 struct JBIG2HuffmanTable {
00038   int val;
00039   Guint prefixLen;
00040   Guint rangeLen;           // can also be LOW, OOB, or EOT
00041   Guint prefix;
00042 };
00043 
00044 JBIG2HuffmanTable huffTableA[] = {
00045   {     0, 1,  4,              0x000 },
00046   {    16, 2,  8,              0x002 },
00047   {   272, 3, 16,              0x006 },
00048   { 65808, 3, 32,              0x007 },
00049   {     0, 0, jbig2HuffmanEOT, 0     }
00050 };
00051 
00052 JBIG2HuffmanTable huffTableB[] = {
00053   {     0, 1,  0,              0x000 },
00054   {     1, 2,  0,              0x002 },
00055   {     2, 3,  0,              0x006 },
00056   {     3, 4,  3,              0x00e },
00057   {    11, 5,  6,              0x01e },
00058   {    75, 6, 32,              0x03e },
00059   {     0, 6, jbig2HuffmanOOB, 0x03f },
00060   {     0, 0, jbig2HuffmanEOT, 0     }
00061 };
00062 
00063 JBIG2HuffmanTable huffTableC[] = {
00064   {     0, 1,  0,              0x000 },
00065   {     1, 2,  0,              0x002 },
00066   {     2, 3,  0,              0x006 },
00067   {     3, 4,  3,              0x00e },
00068   {    11, 5,  6,              0x01e },
00069   {     0, 6, jbig2HuffmanOOB, 0x03e },
00070   {    75, 7, 32,              0x0fe },
00071   {  -256, 8,  8,              0x0fe },
00072   {  -257, 8, jbig2HuffmanLOW, 0x0ff },
00073   {     0, 0, jbig2HuffmanEOT, 0     }
00074 };
00075 
00076 JBIG2HuffmanTable huffTableD[] = {
00077   {     1, 1,  0,              0x000 },
00078   {     2, 2,  0,              0x002 },
00079   {     3, 3,  0,              0x006 },
00080   {     4, 4,  3,              0x00e },
00081   {    12, 5,  6,              0x01e },
00082   {    76, 5, 32,              0x01f },
00083   {     0, 0, jbig2HuffmanEOT, 0     }
00084 };
00085 
00086 JBIG2HuffmanTable huffTableE[] = {
00087   {     1, 1,  0,              0x000 },
00088   {     2, 2,  0,              0x002 },
00089   {     3, 3,  0,              0x006 },
00090   {     4, 4,  3,              0x00e },
00091   {    12, 5,  6,              0x01e },
00092   {    76, 6, 32,              0x03e },
00093   {  -255, 7,  8,              0x07e },
00094   {  -256, 7, jbig2HuffmanLOW, 0x07f },
00095   {     0, 0, jbig2HuffmanEOT, 0     }
00096 };
00097 
00098 JBIG2HuffmanTable huffTableF[] = {
00099   {     0, 2,  7,              0x000 },
00100   {   128, 3,  7,              0x002 },
00101   {   256, 3,  8,              0x003 },
00102   { -1024, 4,  9,              0x008 },
00103   {  -512, 4,  8,              0x009 },
00104   {  -256, 4,  7,              0x00a },
00105   {   -32, 4,  5,              0x00b },
00106   {   512, 4,  9,              0x00c },
00107   {  1024, 4, 10,              0x00d },
00108   { -2048, 5, 10,              0x01c },
00109   {  -128, 5,  6,              0x01d },
00110   {   -64, 5,  5,              0x01e },
00111   { -2049, 6, jbig2HuffmanLOW, 0x03e },
00112   {  2048, 6, 32,              0x03f },
00113   {     0, 0, jbig2HuffmanEOT, 0     }
00114 };
00115 
00116 JBIG2HuffmanTable huffTableG[] = {
00117   {  -512, 3,  8,              0x000 },
00118   {   256, 3,  8,              0x001 },
00119   {   512, 3,  9,              0x002 },
00120   {  1024, 3, 10,              0x003 },
00121   { -1024, 4,  9,              0x008 },
00122   {  -256, 4,  7,              0x009 },
00123   {   -32, 4,  5,              0x00a },
00124   {     0, 4,  5,              0x00b },
00125   {   128, 4,  7,              0x00c },
00126   {  -128, 5,  6,              0x01a },
00127   {   -64, 5,  5,              0x01b },
00128   {    32, 5,  5,              0x01c },
00129   {    64, 5,  6,              0x01d },
00130   { -1025, 5, jbig2HuffmanLOW, 0x01e },
00131   {  2048, 5, 32,              0x01f },
00132   {     0, 0, jbig2HuffmanEOT, 0     }
00133 };
00134 
00135 JBIG2HuffmanTable huffTableH[] = {
00136   {     0, 2,  1,              0x000 },
00137   {     0, 2, jbig2HuffmanOOB, 0x001 },
00138   {     4, 3,  4,              0x004 },
00139   {    -1, 4,  0,              0x00a },
00140   {    22, 4,  4,              0x00b },
00141   {    38, 4,  5,              0x00c },
00142   {     2, 5,  0,              0x01a },
00143   {    70, 5,  6,              0x01b },
00144   {   134, 5,  7,              0x01c },
00145   {     3, 6,  0,              0x03a },
00146   {    20, 6,  1,              0x03b },
00147   {   262, 6,  7,              0x03c },
00148   {   646, 6, 10,              0x03d },
00149   {    -2, 7,  0,              0x07c },
00150   {   390, 7,  8,              0x07d },
00151   {   -15, 8,  3,              0x0fc },
00152   {    -5, 8,  1,              0x0fd },
00153   {    -7, 9,  1,              0x1fc },
00154   {    -3, 9,  0,              0x1fd },
00155   {   -16, 9, jbig2HuffmanLOW, 0x1fe },
00156   {  1670, 9, 32,              0x1ff },
00157   {     0, 0, jbig2HuffmanEOT, 0     }
00158 };
00159 
00160 JBIG2HuffmanTable huffTableI[] = {
00161   {     0, 2, jbig2HuffmanOOB, 0x000 },
00162   {    -1, 3,  1,              0x002 },
00163   {     1, 3,  1,              0x003 },
00164   {     7, 3,  5,              0x004 },
00165   {    -3, 4,  1,              0x00a },
00166   {    43, 4,  5,              0x00b },
00167   {    75, 4,  6,              0x00c },
00168   {     3, 5,  1,              0x01a },
00169   {   139, 5,  7,              0x01b },
00170   {   267, 5,  8,              0x01c },
00171   {     5, 6,  1,              0x03a },
00172   {    39, 6,  2,              0x03b },
00173   {   523, 6,  8,              0x03c },
00174   {  1291, 6, 11,              0x03d },
00175   {    -5, 7,  1,              0x07c },
00176   {   779, 7,  9,              0x07d },
00177   {   -31, 8,  4,              0x0fc },
00178   {   -11, 8,  2,              0x0fd },
00179   {   -15, 9,  2,              0x1fc },
00180   {    -7, 9,  1,              0x1fd },
00181   {   -32, 9, jbig2HuffmanLOW, 0x1fe },
00182   {  3339, 9, 32,              0x1ff },
00183   {     0, 0, jbig2HuffmanEOT, 0     }
00184 };
00185 
00186 JBIG2HuffmanTable huffTableJ[] = {
00187   {    -2, 2,  2,              0x000 },
00188   {     6, 2,  6,              0x001 },
00189   {     0, 2, jbig2HuffmanOOB, 0x002 },
00190   {    -3, 5,  0,              0x018 },
00191   {     2, 5,  0,              0x019 },
00192   {    70, 5,  5,              0x01a },
00193   {     3, 6,  0,              0x036 },
00194   {   102, 6,  5,              0x037 },
00195   {   134, 6,  6,              0x038 },
00196   {   198, 6,  7,              0x039 },
00197   {   326, 6,  8,              0x03a },
00198   {   582, 6,  9,              0x03b },
00199   {  1094, 6, 10,              0x03c },
00200   {   -21, 7,  4,              0x07a },
00201   {    -4, 7,  0,              0x07b },
00202   {     4, 7,  0,              0x07c },
00203   {  2118, 7, 11,              0x07d },
00204   {    -5, 8,  0,              0x0fc },
00205   {     5, 8,  0,              0x0fd },
00206   {   -22, 8, jbig2HuffmanLOW, 0x0fe },
00207   {  4166, 8, 32,              0x0ff },
00208   {     0, 0, jbig2HuffmanEOT, 0     }
00209 };
00210 
00211 JBIG2HuffmanTable huffTableK[] = {
00212   {     1, 1,  0,              0x000 },
00213   {     2, 2,  1,              0x002 },
00214   {     4, 4,  0,              0x00c },
00215   {     5, 4,  1,              0x00d },
00216   {     7, 5,  1,              0x01c },
00217   {     9, 5,  2,              0x01d },
00218   {    13, 6,  2,              0x03c },
00219   {    17, 7,  2,              0x07a },
00220   {    21, 7,  3,              0x07b },
00221   {    29, 7,  4,              0x07c },
00222   {    45, 7,  5,              0x07d },
00223   {    77, 7,  6,              0x07e },
00224   {   141, 7, 32,              0x07f },
00225   {     0, 0, jbig2HuffmanEOT, 0     }
00226 };
00227 
00228 JBIG2HuffmanTable huffTableL[] = {
00229   {     1, 1,  0,              0x000 },
00230   {     2, 2,  0,              0x002 },
00231   {     3, 3,  1,              0x006 },
00232   {     5, 5,  0,              0x01c },
00233   {     6, 5,  1,              0x01d },
00234   {     8, 6,  1,              0x03c },
00235   {    10, 7,  0,              0x07a },
00236   {    11, 7,  1,              0x07b },
00237   {    13, 7,  2,              0x07c },
00238   {    17, 7,  3,              0x07d },
00239   {    25, 7,  4,              0x07e },
00240   {    41, 8,  5,              0x0fe },
00241   {    73, 8, 32,              0x0ff },
00242   {     0, 0, jbig2HuffmanEOT, 0     }
00243 };
00244 
00245 JBIG2HuffmanTable huffTableM[] = {
00246   {     1, 1,  0,              0x000 },
00247   {     2, 3,  0,              0x004 },
00248   {     7, 3,  3,              0x005 },
00249   {     3, 4,  0,              0x00c },
00250   {     5, 4,  1,              0x00d },
00251   {     4, 5,  0,              0x01c },
00252   {    15, 6,  1,              0x03a },
00253   {    17, 6,  2,              0x03b },
00254   {    21, 6,  3,              0x03c },
00255   {    29, 6,  4,              0x03d },
00256   {    45, 6,  5,              0x03e },
00257   {    77, 7,  6,              0x07e },
00258   {   141, 7, 32,              0x07f },
00259   {     0, 0, jbig2HuffmanEOT, 0     }
00260 };
00261 
00262 JBIG2HuffmanTable huffTableN[] = {
00263   {     0, 1,  0,              0x000 },
00264   {    -2, 3,  0,              0x004 },
00265   {    -1, 3,  0,              0x005 },
00266   {     1, 3,  0,              0x006 },
00267   {     2, 3,  0,              0x007 },
00268   {     0, 0, jbig2HuffmanEOT, 0     }
00269 };
00270 
00271 JBIG2HuffmanTable huffTableO[] = {
00272   {     0, 1,  0,              0x000 },
00273   {    -1, 3,  0,              0x004 },
00274   {     1, 3,  0,              0x005 },
00275   {    -2, 4,  0,              0x00c },
00276   {     2, 4,  0,              0x00d },
00277   {    -4, 5,  1,              0x01c },
00278   {     3, 5,  1,              0x01d },
00279   {    -8, 6,  2,              0x03c },
00280   {     5, 6,  2,              0x03d },
00281   {   -24, 7,  4,              0x07c },
00282   {     9, 7,  4,              0x07d },
00283   {   -25, 7, jbig2HuffmanLOW, 0x07e },
00284   {    25, 7, 32,              0x07f },
00285   {     0, 0, jbig2HuffmanEOT, 0     }
00286 };
00287 
00288 //------------------------------------------------------------------------
00289 // JBIG2HuffmanDecoder
00290 //------------------------------------------------------------------------
00291 
00292 class JBIG2HuffmanDecoder {
00293 public:
00294 
00295   JBIG2HuffmanDecoder();
00296   ~JBIG2HuffmanDecoder();
00297   void setStream(Stream *strA) { str = strA; }
00298 
00299   void reset();
00300 
00301   // Returns false for OOB, otherwise sets *<x> and returns true.
00302   GBool decodeInt(int *x, JBIG2HuffmanTable *table);
00303 
00304   Guint readBits(Guint n);
00305   Guint readBit();
00306 
00307   // Sort the table by prefix length and assign prefix values.
00308   void buildTable(JBIG2HuffmanTable *table, Guint len);
00309 
00310 private:
00311 
00312   Stream *str;
00313   Guint buf;
00314   Guint bufLen;
00315 };
00316 
00317 JBIG2HuffmanDecoder::JBIG2HuffmanDecoder() {
00318   str = NULL;
00319   reset();
00320 }
00321 
00322 JBIG2HuffmanDecoder::~JBIG2HuffmanDecoder() {
00323 }
00324 
00325 void JBIG2HuffmanDecoder::reset() {
00326   buf = 0;
00327   bufLen = 0;
00328 }
00329 
00330 //~ optimize this
00331 GBool JBIG2HuffmanDecoder::decodeInt(int *x, JBIG2HuffmanTable *table) {
00332   Guint i, len, prefix;
00333 
00334   i = 0;
00335   len = 0;
00336   prefix = 0;
00337   while (table[i].rangeLen != jbig2HuffmanEOT) {
00338     while (len < table[i].prefixLen) {
00339       prefix = (prefix << 1) | readBit();
00340       ++len;
00341     }
00342     if (prefix == table[i].prefix) {
00343       if (table[i].rangeLen == jbig2HuffmanOOB) {
00344        return gFalse;
00345       }
00346       if (table[i].rangeLen == jbig2HuffmanLOW) {
00347        *x = table[i].val - readBits(32);
00348       } else if (table[i].rangeLen > 0) {
00349        *x = table[i].val + readBits(table[i].rangeLen);
00350       } else {
00351        *x = table[i].val;
00352       }
00353       return gTrue;
00354     }
00355     ++i;
00356   }
00357   return gFalse;
00358 }
00359 
00360 Guint JBIG2HuffmanDecoder::readBits(Guint n) {
00361   Guint x, mask, nLeft;
00362 
00363   mask = (n == 32) ? 0xffffffff : ((1 << n) - 1);
00364   if (bufLen >= n) {
00365     x = (buf >> (bufLen - n)) & mask;
00366     bufLen -= n;
00367   } else {
00368     x = buf & ((1 << bufLen) - 1);
00369     nLeft = n - bufLen;
00370     bufLen = 0;
00371     while (nLeft >= 8) {
00372       x = (x << 8) | (str->getChar() & 0xff);
00373       nLeft -= 8;
00374     }
00375     if (nLeft > 0) {
00376       buf = str->getChar();
00377       bufLen = 8 - nLeft;
00378       x = (x << nLeft) | ((buf >> bufLen) & ((1 << nLeft) - 1));
00379     }
00380   }
00381   return x;
00382 }
00383 
00384 Guint JBIG2HuffmanDecoder::readBit() {
00385   if (bufLen == 0) {
00386     buf = str->getChar();
00387     bufLen = 8;
00388   }
00389   --bufLen;
00390   return (buf >> bufLen) & 1;
00391 }
00392 
00393 void JBIG2HuffmanDecoder::buildTable(JBIG2HuffmanTable *table, Guint len) {
00394   Guint i, j, k, prefix;
00395   JBIG2HuffmanTable tab;
00396 
00397   // stable selection sort:
00398   // - entries with prefixLen > 0, in ascending prefixLen order
00399   // - entry with prefixLen = 0, rangeLen = EOT
00400   // - all other entries with prefixLen = 0
00401   // (on entry, table[len] has prefixLen = 0, rangeLen = EOT)
00402   for (i = 0; i < len; ++i) {
00403     for (j = i; j < len && table[j].prefixLen == 0; ++j) ;
00404     if (j == len) {
00405       break;
00406     }
00407     for (k = j + 1; k < len; ++k) {
00408       if (table[k].prefixLen > 0 &&
00409          table[k].prefixLen < table[j].prefixLen) {
00410        j = k;
00411       }
00412     }
00413     if (j != i) {
00414       tab = table[j];
00415       for (k = j; k > i; --k) {
00416        table[k] = table[k - 1];
00417       }
00418       table[i] = tab;
00419     }
00420   }
00421   table[i] = table[len];
00422 
00423   // assign prefixes
00424   i = 0;
00425   prefix = 0;
00426   table[i++].prefix = prefix++;
00427   for (; table[i].rangeLen != jbig2HuffmanEOT; ++i) {
00428     prefix <<= table[i].prefixLen - table[i-1].prefixLen;
00429     table[i].prefix = prefix++;
00430   }
00431 }
00432 
00433 //------------------------------------------------------------------------
00434 // JBIG2MMRDecoder
00435 //------------------------------------------------------------------------
00436 
00437 class JBIG2MMRDecoder {
00438 public:
00439 
00440   JBIG2MMRDecoder();
00441   ~JBIG2MMRDecoder();
00442   void setStream(Stream *strA) { str = strA; }
00443   void reset();
00444   int get2DCode();
00445   int getBlackCode();
00446   int getWhiteCode();
00447   Guint get24Bits();
00448   void skipTo(Guint length);
00449 
00450 private:
00451 
00452   Stream *str;
00453   Guint buf;
00454   Guint bufLen;
00455   Guint nBytesRead;
00456 };
00457 
00458 JBIG2MMRDecoder::JBIG2MMRDecoder() {
00459   str = NULL;
00460   reset();
00461 }
00462 
00463 JBIG2MMRDecoder::~JBIG2MMRDecoder() {
00464 }
00465 
00466 void JBIG2MMRDecoder::reset() {
00467   buf = 0;
00468   bufLen = 0;
00469   nBytesRead = 0;
00470 }
00471 
00472 int JBIG2MMRDecoder::get2DCode() {
00473   CCITTCode *p;
00474 
00475   if (bufLen == 0) {
00476     buf = str->getChar() & 0xff;
00477     bufLen = 8;
00478     ++nBytesRead;
00479     p = &twoDimTab1[(buf >> 1) & 0x7f];
00480   } else if (bufLen == 8) {
00481     p = &twoDimTab1[(buf >> 1) & 0x7f];
00482   } else {
00483     p = &twoDimTab1[(buf << (7 - bufLen)) & 0x7f];
00484     if (p->bits < 0 || p->bits > (int)bufLen) {
00485       buf = (buf << 8) | (str->getChar() & 0xff);
00486       bufLen += 8;
00487       ++nBytesRead;
00488       p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f];
00489     }
00490   }
00491   if (p->bits < 0) {
00492     error(str->getPos(), "Bad two dim code in JBIG2 MMR stream");
00493     return 0;
00494   }
00495   bufLen -= p->bits;
00496   return p->n;
00497 }
00498 
00499 int JBIG2MMRDecoder::getWhiteCode() {
00500   CCITTCode *p;
00501   Guint code;
00502 
00503   if (bufLen == 0) {
00504     buf = str->getChar() & 0xff;
00505     bufLen = 8;
00506     ++nBytesRead;
00507   }
00508   while (1) {
00509     if (bufLen >= 7 && ((buf >> (bufLen - 7)) & 0x7f) == 0) {
00510       if (bufLen <= 12) {
00511        code = buf << (12 - bufLen);
00512       } else {
00513        code = buf >> (bufLen - 12);
00514       }
00515       p = &whiteTab1[code & 0x1f];
00516     } else {
00517       if (bufLen <= 9) {
00518        code = buf << (9 - bufLen);
00519       } else {
00520        code = buf >> (bufLen - 9);
00521       }
00522       p = &whiteTab2[code & 0x1ff];
00523     }
00524     if (p->bits > 0 && p->bits <= (int)bufLen) {
00525       bufLen -= p->bits;
00526       return p->n;
00527     }
00528     if (bufLen >= 12) {
00529       break;
00530     }
00531     buf = (buf << 8) | (str->getChar() & 0xff);
00532     bufLen += 8;
00533     ++nBytesRead;
00534   }
00535   error(str->getPos(), "Bad white code in JBIG2 MMR stream");
00536   // eat a bit and return a positive number so that the caller doesn't
00537   // go into an infinite loop
00538   --bufLen;
00539   return 1;
00540 }
00541 
00542 int JBIG2MMRDecoder::getBlackCode() {
00543   CCITTCode *p;
00544   Guint code;
00545 
00546   if (bufLen == 0) {
00547     buf = str->getChar() & 0xff;
00548     bufLen = 8;
00549     ++nBytesRead;
00550   }
00551   while (1) {
00552     if (bufLen >= 6 && ((buf >> (bufLen - 6)) & 0x3f) == 0) {
00553       if (bufLen <= 13) {
00554        code = buf << (13 - bufLen);
00555       } else {
00556        code = buf >> (bufLen - 13);
00557       }
00558       p = &blackTab1[code & 0x7f];
00559     } else if (bufLen >= 4 && ((buf >> (bufLen - 4)) & 0x0f) == 0) {
00560       if (bufLen <= 12) {
00561        code = buf << (12 - bufLen);
00562       } else {
00563        code = buf >> (bufLen - 12);
00564       }
00565       p = &blackTab2[(code & 0xff) - 64];
00566     } else {
00567       if (bufLen <= 6) {
00568        code = buf << (6 - bufLen);
00569       } else {
00570        code = buf >> (bufLen - 6);
00571       }
00572       p = &blackTab3[code & 0x3f];
00573     }
00574     if (p->bits > 0 && p->bits <= (int)bufLen) {
00575       bufLen -= p->bits;
00576       return p->n;
00577     }
00578     if (bufLen >= 13) {
00579       break;
00580     }
00581     buf = (buf << 8) | (str->getChar() & 0xff);
00582     bufLen += 8;
00583     ++nBytesRead;
00584   }
00585   error(str->getPos(), "Bad black code in JBIG2 MMR stream");
00586   // eat a bit and return a positive number so that the caller doesn't
00587   // go into an infinite loop
00588   --bufLen;
00589   return 1;
00590 }
00591 
00592 Guint JBIG2MMRDecoder::get24Bits() {
00593   while (bufLen < 24) {
00594     buf = (buf << 8) | (str->getChar() & 0xff);
00595     bufLen += 8;
00596     ++nBytesRead;
00597   }
00598   return (buf >> (bufLen - 24)) & 0xffffff;
00599 }
00600 
00601 void JBIG2MMRDecoder::skipTo(Guint length) {
00602   while (nBytesRead < length) {
00603     str->getChar();
00604     ++nBytesRead;
00605   }
00606 }
00607 
00608 //------------------------------------------------------------------------
00609 // JBIG2Segment
00610 //------------------------------------------------------------------------
00611 
00612 enum JBIG2SegmentType {
00613   jbig2SegBitmap,
00614   jbig2SegSymbolDict,
00615   jbig2SegPatternDict,
00616   jbig2SegCodeTable
00617 };
00618 
00619 class JBIG2Segment {
00620 public:
00621 
00622   JBIG2Segment(Guint segNumA) { segNum = segNumA; }
00623   virtual ~JBIG2Segment() {}
00624   void setSegNum(Guint segNumA) { segNum = segNumA; }
00625   Guint getSegNum() { return segNum; }
00626   virtual JBIG2SegmentType getType() = 0;
00627 
00628 private:
00629 
00630   Guint segNum;
00631 };
00632 
00633 //------------------------------------------------------------------------
00634 // JBIG2Bitmap
00635 //------------------------------------------------------------------------
00636 
00637 struct JBIG2BitmapPtr {
00638   Guchar *p;
00639   int shift;
00640   int x;
00641 };
00642 
00643 class JBIG2Bitmap: public JBIG2Segment {
00644 public:
00645 
00646   JBIG2Bitmap(Guint segNumA, int wA, int hA);
00647   virtual ~JBIG2Bitmap();
00648   virtual JBIG2SegmentType getType() { return jbig2SegBitmap; }
00649   JBIG2Bitmap *copy() { return new JBIG2Bitmap(0, this); }
00650   JBIG2Bitmap *getSlice(Guint x, Guint y, Guint wA, Guint hA);
00651   void expand(int newH, Guint pixel);
00652   void clearToZero();
00653   void clearToOne();
00654   int getWidth() { return w; }
00655   int getHeight() { return h; }
00656   int getPixel(int x, int y)
00657     { return (x < 0 || x >= w || y < 0 || y >= h) ? 0 :
00658              (data[y * line + (x >> 3)] >> (7 - (x & 7))) & 1; }
00659   void setPixel(int x, int y)
00660     { data[y * line + (x >> 3)] |= 1 << (7 - (x & 7)); }
00661   void clearPixel(int x, int y)
00662     { data[y * line + (x >> 3)] &= 0x7f7f >> (x & 7); }
00663   void getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr);
00664   int nextPixel(JBIG2BitmapPtr *ptr);
00665   void duplicateRow(int yDest, int ySrc);
00666   void combine(JBIG2Bitmap *bitmap, int x, int y, Guint combOp);
00667   Guchar *getDataPtr() { return data; }
00668   int getDataSize() { return h * line; }
00669 
00670 private:
00671 
00672   JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap);
00673 
00674   int w, h, line;
00675   Guchar *data;
00676 };
00677 
00678 JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, int wA, int hA):
00679   JBIG2Segment(segNumA)
00680 {
00681   w = wA;
00682   h = hA;
00683   line = (wA + 7) >> 3;
00684   data = (Guchar *)gmalloc(h * line);
00685 }
00686 
00687 JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap):
00688   JBIG2Segment(segNumA)
00689 {
00690   w = bitmap->w;
00691   h = bitmap->h;
00692   line = bitmap->line;
00693   data = (Guchar *)gmalloc(h * line);
00694   memcpy(data, bitmap->data, h * line);
00695 }
00696 
00697 JBIG2Bitmap::~JBIG2Bitmap() {
00698   gfree(data);
00699 }
00700 
00701 //~ optimize this
00702 JBIG2Bitmap *JBIG2Bitmap::getSlice(Guint x, Guint y, Guint wA, Guint hA) {
00703   JBIG2Bitmap *slice;
00704   Guint xx, yy;
00705 
00706   slice = new JBIG2Bitmap(0, wA, hA);
00707   slice->clearToZero();
00708   for (yy = 0; yy < hA; ++yy) {
00709     for (xx = 0; xx < wA; ++xx) {
00710       if (getPixel(x + xx, y + yy)) {
00711        slice->setPixel(xx, yy);
00712       }
00713     }
00714   }
00715   return slice;
00716 }
00717 
00718 void JBIG2Bitmap::expand(int newH, Guint pixel) {
00719   if (newH <= h) {
00720     return;
00721   }
00722   data = (Guchar *)grealloc(data, newH * line);
00723   if (pixel) {
00724     memset(data + h * line, 0xff, (newH - h) * line);
00725   } else {
00726     memset(data + h * line, 0x00, (newH - h) * line);
00727   }
00728   h = newH;
00729 }
00730 
00731 void JBIG2Bitmap::clearToZero() {
00732   memset(data, 0, h * line);
00733 }
00734 
00735 void JBIG2Bitmap::clearToOne() {
00736   memset(data, 0xff, h * line);
00737 }
00738 
00739 inline void JBIG2Bitmap::getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr) {
00740   if (y < 0 || y >= h || x >= w) {
00741     ptr->p = NULL;
00742   } else if (x < 0) {
00743     ptr->p = &data[y * line];
00744     ptr->shift = 7;
00745     ptr->x = x;
00746   } else {
00747     ptr->p = &data[y * line + (x >> 3)];
00748     ptr->shift = 7 - (x & 7);
00749     ptr->x = x;
00750   }
00751 }
00752 
00753 inline int JBIG2Bitmap::nextPixel(JBIG2BitmapPtr *ptr) {
00754   int pix;
00755 
00756   if (!ptr->p) {
00757     pix = 0;
00758   } else if (ptr->x < 0) {
00759     ++ptr->x;
00760     pix = 0;
00761   } else {
00762     pix = (*ptr->p >> ptr->shift) & 1;
00763     if (++ptr->x == w) {
00764       ptr->p = NULL;
00765     } else if (ptr->shift == 0) {
00766       ++ptr->p;
00767       ptr->shift = 7;
00768     } else {
00769       --ptr->shift;
00770     }
00771   }
00772   return pix;
00773 }
00774 
00775 void JBIG2Bitmap::duplicateRow(int yDest, int ySrc) {
00776   memcpy(data + yDest * line, data + ySrc * line, line);
00777 }
00778 
00779 void JBIG2Bitmap::combine(JBIG2Bitmap *bitmap, int x, int y,
00780                        Guint combOp) {
00781   int x0, x1, y0, y1, xx, yy;
00782   Guchar *srcPtr, *destPtr;
00783   Guint src0, src1, src, dest, s1, s2, m1, m2, m3;
00784   GBool oneByte;
00785 
00786   if (y < 0) {
00787     y0 = -y;
00788   } else {
00789     y0 = 0;
00790   }
00791   if (y + bitmap->h > h) {
00792     y1 = h - y;
00793   } else {
00794     y1 = bitmap->h;
00795   }
00796   if (y0 >= y1) {
00797     return;
00798   }
00799 
00800   if (x >= 0) {
00801     x0 = x & ~7;
00802   } else {
00803     x0 = 0;
00804   }
00805   x1 = x + bitmap->w;
00806   if (x1 > w) {
00807     x1 = w;
00808   }
00809   if (x0 >= x1) {
00810     return;
00811   }
00812 
00813   s1 = x & 7;
00814   s2 = 8 - s1;
00815   m1 = 0xff >> (x1 & 7);
00816   m2 = 0xff << (((x1 & 7) == 0) ? 0 : 8 - (x1 & 7));
00817   m3 = (0xff >> s1) & m2;
00818 
00819   oneByte = x0 == ((x1 - 1) & ~7);
00820 
00821   for (yy = y0; yy < y1; ++yy) {
00822 
00823     // one byte per line -- need to mask both left and right side
00824     if (oneByte) {
00825       if (x >= 0) {
00826        destPtr = data + (y + yy) * line + (x >> 3);
00827        srcPtr = bitmap->data + yy * bitmap->line;
00828        dest = *destPtr;
00829        src1 = *srcPtr;
00830        switch (combOp) {
00831        case 0: // or
00832          dest |= (src1 >> s1) & m2;
00833          break;
00834        case 1: // and
00835          dest &= ((0xff00 | src1) >> s1) | m1;
00836          break;
00837        case 2: // xor
00838          dest ^= (src1 >> s1) & m2;
00839          break;
00840        case 3: // xnor
00841          dest ^= ((src1 ^ 0xff) >> s1) & m2;
00842          break;
00843        case 4: // replace
00844          dest = (dest & ~m3) | ((src1 >> s1) & m3);
00845          break;
00846        }
00847        *destPtr = dest;
00848       } else {
00849        destPtr = data + (y + yy) * line;
00850        srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
00851        dest = *destPtr;
00852        src1 = *srcPtr;
00853        switch (combOp) {
00854        case 0: // or
00855          dest |= src1 & m2;
00856          break;
00857        case 1: // and
00858          dest &= src1 | m1;
00859          break;
00860        case 2: // xor
00861          dest ^= src1 & m2;
00862          break;
00863        case 3: // xnor
00864          dest ^= (src1 ^ 0xff) & m2;
00865          break;
00866        case 4: // replace
00867          dest = (src1 & m2) | (dest & m1);
00868          break;
00869        }
00870        *destPtr = dest;
00871       }
00872 
00873     // multiple bytes per line -- need to mask left side of left-most
00874     // byte and right side of right-most byte
00875     } else {
00876 
00877       // left-most byte
00878       if (x >= 0) {
00879        destPtr = data + (y + yy) * line + (x >> 3);
00880        srcPtr = bitmap->data + yy * bitmap->line;
00881        src1 = *srcPtr++;
00882        dest = *destPtr;
00883        switch (combOp) {
00884        case 0: // or
00885          dest |= src1 >> s1;
00886          break;
00887        case 1: // and
00888          dest &= (0xff00 | src1) >> s1;
00889          break;
00890        case 2: // xor
00891          dest ^= src1 >> s1;
00892          break;
00893        case 3: // xnor
00894          dest ^= (src1 ^ 0xff) >> s1;
00895          break;
00896        case 4: // replace
00897          dest = (dest & (0xff << s2)) | (src1 >> s1);
00898          break;
00899        }
00900        *destPtr++ = dest;
00901        xx = x0 + 8;
00902       } else {
00903        destPtr = data + (y + yy) * line;
00904        srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
00905        src1 = *srcPtr++;
00906        xx = x0;
00907       }
00908 
00909       // middle bytes
00910       for (; xx < x1 - 8; xx += 8) {
00911        dest = *destPtr;
00912        src0 = src1;
00913        src1 = *srcPtr++;
00914        src = (((src0 << 8) | src1) >> s1) & 0xff;
00915        switch (combOp) {
00916        case 0: // or
00917          dest |= src;
00918          break;
00919        case 1: // and
00920          dest &= src;
00921          break;
00922        case 2: // xor
00923          dest ^= src;
00924          break;
00925        case 3: // xnor
00926          dest ^= src ^ 0xff;
00927          break;
00928        case 4: // replace
00929          dest = src;
00930          break;
00931        }
00932        *destPtr++ = dest;
00933       }
00934 
00935       // right-most byte
00936       dest = *destPtr;
00937       src0 = src1;
00938       src1 = *srcPtr++;
00939       src = (((src0 << 8) | src1) >> s1) & 0xff;
00940       switch (combOp) {
00941       case 0: // or
00942        dest |= src & m2;
00943        break;
00944       case 1: // and
00945        dest &= src | m1;
00946        break;
00947       case 2: // xor
00948        dest ^= src & m2;
00949        break;
00950       case 3: // xnor
00951        dest ^= (src ^ 0xff) & m2;
00952        break;
00953       case 4: // replace
00954        dest = (src & m2) | (dest & m1);
00955        break;
00956       }
00957       *destPtr = dest;
00958     }
00959   }
00960 }
00961 
00962 //------------------------------------------------------------------------
00963 // JBIG2SymbolDict
00964 //------------------------------------------------------------------------
00965 
00966 class JBIG2SymbolDict: public JBIG2Segment {
00967 public:
00968 
00969   JBIG2SymbolDict(Guint segNumA, Guint sizeA);
00970   virtual ~JBIG2SymbolDict();
00971   virtual JBIG2SegmentType getType() { return jbig2SegSymbolDict; }
00972   Guint getSize() { return size; }
00973   void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
00974   JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; }
00975   void setGenericRegionStats(JArithmeticDecoderStats *stats)
00976     { genericRegionStats = stats; }
00977   void setRefinementRegionStats(JArithmeticDecoderStats *stats)
00978     { refinementRegionStats = stats; }
00979   JArithmeticDecoderStats *getGenericRegionStats()
00980     { return genericRegionStats; }
00981   JArithmeticDecoderStats *getRefinementRegionStats()
00982     { return refinementRegionStats; }
00983 
00984 private:
00985 
00986   Guint size;
00987   JBIG2Bitmap **bitmaps;
00988   JArithmeticDecoderStats *genericRegionStats;
00989   JArithmeticDecoderStats *refinementRegionStats;
00990 };
00991 
00992 JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA):
00993   JBIG2Segment(segNumA)
00994 {
00995   size = sizeA;
00996   bitmaps = (JBIG2Bitmap **)gmalloc(size * sizeof(JBIG2Bitmap *));
00997   genericRegionStats = NULL;
00998   refinementRegionStats = NULL;
00999 }
01000 
01001 JBIG2SymbolDict::~JBIG2SymbolDict() {
01002   Guint i;
01003 
01004   for (i = 0; i < size; ++i) {
01005     delete bitmaps[i];
01006   }
01007   gfree(bitmaps);
01008   if (genericRegionStats) {
01009     delete genericRegionStats;
01010   }
01011   if (refinementRegionStats) {
01012     delete refinementRegionStats;
01013   }
01014 }
01015 
01016 //------------------------------------------------------------------------
01017 // JBIG2PatternDict
01018 //------------------------------------------------------------------------
01019 
01020 class JBIG2PatternDict: public JBIG2Segment {
01021 public:
01022 
01023   JBIG2PatternDict(Guint segNumA, Guint sizeA);
01024   virtual ~JBIG2PatternDict();
01025   virtual JBIG2SegmentType getType() { return jbig2SegPatternDict; }
01026   Guint getSize() { return size; }
01027   void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
01028   JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; }
01029 
01030 private:
01031 
01032   Guint size;
01033   JBIG2Bitmap **bitmaps;
01034 };
01035 
01036 JBIG2PatternDict::JBIG2PatternDict(Guint segNumA, Guint sizeA):
01037   JBIG2Segment(segNumA)
01038 {
01039   size = sizeA;
01040   bitmaps = (JBIG2Bitmap **)gmalloc(size * sizeof(JBIG2Bitmap *));
01041 }
01042 
01043 JBIG2PatternDict::~JBIG2PatternDict() {
01044   Guint i;
01045 
01046   for (i = 0; i < size; ++i) {
01047     delete bitmaps[i];
01048   }
01049   gfree(bitmaps);
01050 }
01051 
01052 //------------------------------------------------------------------------
01053 // JBIG2CodeTable
01054 //------------------------------------------------------------------------
01055 
01056 class JBIG2CodeTable: public JBIG2Segment {
01057 public:
01058 
01059   JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA);
01060   virtual ~JBIG2CodeTable();
01061   virtual JBIG2SegmentType getType() { return jbig2SegCodeTable; }
01062   JBIG2HuffmanTable *getHuffTable() { return table; }
01063 
01064 private:
01065 
01066   JBIG2HuffmanTable *table;
01067 };
01068 
01069 JBIG2CodeTable::JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA):
01070   JBIG2Segment(segNumA)
01071 {
01072   table = tableA;
01073 }
01074 
01075 JBIG2CodeTable::~JBIG2CodeTable() {
01076   gfree(table);
01077 }
01078 
01079 //------------------------------------------------------------------------
01080 // JBIG2Stream
01081 //------------------------------------------------------------------------
01082 
01083 JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStream):
01084   FilterStream(strA)
01085 {
01086   pageBitmap = NULL;
01087 
01088   arithDecoder = new JArithmeticDecoder();
01089   genericRegionStats = new JArithmeticDecoderStats(1 << 1);
01090   refinementRegionStats = new JArithmeticDecoderStats(1 << 1);
01091   iadhStats = new JArithmeticDecoderStats(1 << 9);
01092   iadwStats = new JArithmeticDecoderStats(1 << 9);
01093   iaexStats = new JArithmeticDecoderStats(1 << 9);
01094   iaaiStats = new JArithmeticDecoderStats(1 << 9);
01095   iadtStats = new JArithmeticDecoderStats(1 << 9);
01096   iaitStats = new JArithmeticDecoderStats(1 << 9);
01097   iafsStats = new JArithmeticDecoderStats(1 << 9);
01098   iadsStats = new JArithmeticDecoderStats(1 << 9);
01099   iardxStats = new JArithmeticDecoderStats(1 << 9);
01100   iardyStats = new JArithmeticDecoderStats(1 << 9);
01101   iardwStats = new JArithmeticDecoderStats(1 << 9);
01102   iardhStats = new JArithmeticDecoderStats(1 << 9);
01103   iariStats = new JArithmeticDecoderStats(1 << 9);
01104   iaidStats = new JArithmeticDecoderStats(1 << 1);
01105   huffDecoder = new JBIG2HuffmanDecoder();
01106   mmrDecoder = new JBIG2MMRDecoder();
01107 
01108   segments = globalSegments = new GList();
01109   if (globalsStream->isStream()) {
01110     curStr = globalsStream->getStream();
01111     curStr->reset();
01112     arithDecoder->setStream(curStr);
01113     huffDecoder->setStream(curStr);
01114     mmrDecoder->setStream(curStr);
01115     readSegments();
01116   }
01117 
01118   segments = NULL;
01119   curStr = NULL;
01120   dataPtr = dataEnd = NULL;
01121 }
01122 
01123 JBIG2Stream::~JBIG2Stream() {
01124   delete arithDecoder;
01125   delete genericRegionStats;
01126   delete refinementRegionStats;
01127   delete iadhStats;
01128   delete iadwStats;
01129   delete iaexStats;
01130   delete iaaiStats;
01131   delete iadtStats;
01132   delete iaitStats;
01133   delete iafsStats;
01134   delete iadsStats;
01135   delete iardxStats;
01136   delete iardyStats;
01137   delete iardwStats;
01138   delete iardhStats;
01139   delete iariStats;
01140   delete iaidStats;
01141   delete huffDecoder;
01142   delete mmrDecoder;
01143   if (pageBitmap) {
01144     delete pageBitmap;
01145   }
01146   if (segments) {
01147     deleteGList(segments, JBIG2Segment);
01148   }
01149   if (globalSegments) {
01150     deleteGList(globalSegments, JBIG2Segment);
01151   }
01152   delete str;
01153 }
01154 
01155 void JBIG2Stream::reset() {
01156   if (pageBitmap) {
01157     delete pageBitmap;
01158     pageBitmap = NULL;
01159   }
01160   if (segments) {
01161     deleteGList(segments, JBIG2Segment);
01162   }
01163   segments = new GList();
01164 
01165   curStr = str;
01166   curStr->reset();
01167   arithDecoder->setStream(curStr);
01168   huffDecoder->setStream(curStr);
01169   mmrDecoder->setStream(curStr);
01170   readSegments();
01171 
01172   if (pageBitmap) {
01173     dataPtr = pageBitmap->getDataPtr();
01174     dataEnd = dataPtr + pageBitmap->getDataSize();
01175   } else {
01176     dataPtr = NULL;
01177   }
01178 }
01179 
01180 int JBIG2Stream::getChar() {
01181   if (dataPtr && dataPtr < dataEnd) {
01182     return (*dataPtr++ ^ 0xff) & 0xff;
01183   }
01184   return EOF;
01185 }
01186 
01187 int JBIG2Stream::lookChar() {
01188   if (dataPtr && dataPtr < dataEnd) {
01189     return (*dataPtr ^ 0xff) & 0xff;
01190   }
01191   return EOF;
01192 }
01193 
01194 GString *JBIG2Stream::getPSFilter(int psLevel, char *indent) {
01195   return NULL;
01196 }
01197 
01198 GBool JBIG2Stream::isBinary(GBool last) {
01199   return str->isBinary(gTrue);
01200 }
01201 
01202 void JBIG2Stream::readSegments() {
01203   Guint segNum, segFlags, segType, page, segLength;
01204   Guint refFlags, nRefSegs;
01205   Guint *refSegs;
01206   int c1, c2, c3;
01207   Guint i;
01208 
01209   while (readULong(&segNum)) {
01210 
01211     // segment header flags
01212     if (!readUByte(&segFlags)) {
01213       goto eofError1;
01214     }
01215     segType = segFlags & 0x3f;
01216 
01217     // referred-to segment count and retention flags
01218     if (!readUByte(&refFlags)) {
01219       goto eofError1;
01220     }
01221     nRefSegs = refFlags >> 5;
01222     if (nRefSegs == 7) {
01223       if ((c1 = curStr->getChar()) == EOF ||
01224          (c2 = curStr->getChar()) == EOF ||
01225          (c3 = curStr->getChar()) == EOF) {
01226        goto eofError1;
01227       }
01228       refFlags = (refFlags << 24) | (c1 << 16) | (c2 << 8) | c3;
01229       nRefSegs = refFlags & 0x1fffffff;
01230       for (i = 0; i < (nRefSegs + 9) >> 3; ++i) {
01231        c1 = curStr->getChar();
01232       }
01233     }
01234 
01235     // referred-to segment numbers
01236     refSegs = (Guint *)gmalloc(nRefSegs * sizeof(Guint));
01237     if (segNum <= 256) {
01238       for (i = 0; i < nRefSegs; ++i) {
01239        if (!readUByte(&refSegs[i])) {
01240          goto eofError2;
01241        }
01242       }
01243     } else if (segNum <= 65536) {
01244       for (i = 0; i < nRefSegs; ++i) {
01245        if (!readUWord(&refSegs[i])) {
01246          goto eofError2;
01247        }
01248       }
01249     } else {
01250       for (i = 0; i < nRefSegs; ++i) {
01251        if (!readULong(&refSegs[i])) {
01252          goto eofError2;
01253        }
01254       }
01255     }
01256 
01257     // segment page association
01258     if (segFlags & 0x40) {
01259       if (!readULong(&page)) {
01260        goto eofError2;
01261       }
01262     } else {
01263       if (!readUByte(&page)) {
01264        goto eofError2;
01265       }
01266     }
01267 
01268     // segment data length
01269     if (!readULong(&segLength)) {
01270       goto eofError2;
01271     }
01272 
01273     // read the segment data
01274     switch (segType) {
01275     case 0:
01276       readSymbolDictSeg(segNum, segLength, refSegs, nRefSegs);
01277       break;
01278     case 4:
01279       readTextRegionSeg(segNum, gFalse, gFalse, segLength, refSegs, nRefSegs);
01280       break;
01281     case 6:
01282       readTextRegionSeg(segNum, gTrue, gFalse, segLength, refSegs, nRefSegs);
01283       break;
01284     case 7:
01285       readTextRegionSeg(segNum, gTrue, gTrue, segLength, refSegs, nRefSegs);
01286       break;
01287     case 16:
01288       readPatternDictSeg(segNum, segLength);
01289       break;
01290     case 20:
01291       readHalftoneRegionSeg(segNum, gFalse, gFalse, segLength,
01292                          refSegs, nRefSegs);
01293       break;
01294     case 22:
01295       readHalftoneRegionSeg(segNum, gTrue, gFalse, segLength,
01296                          refSegs, nRefSegs);
01297       break;
01298     case 23:
01299       readHalftoneRegionSeg(segNum, gTrue, gTrue, segLength,
01300                          refSegs, nRefSegs);
01301       break;
01302     case 36:
01303       readGenericRegionSeg(segNum, gFalse, gFalse, segLength);
01304       break;
01305     case 38:
01306       readGenericRegionSeg(segNum, gTrue, gFalse, segLength);
01307       break;
01308     case 39:
01309       readGenericRegionSeg(segNum, gTrue, gTrue, segLength);
01310       break;
01311     case 40:
01312       readGenericRefinementRegionSeg(segNum, gFalse, gFalse, segLength,
01313                                  refSegs, nRefSegs);
01314       break;
01315     case 42:
01316       readGenericRefinementRegionSeg(segNum, gTrue, gFalse, segLength,
01317                                  refSegs, nRefSegs);
01318       break;
01319     case 43:
01320       readGenericRefinementRegionSeg(segNum, gTrue, gTrue, segLength,
01321                                  refSegs, nRefSegs);
01322       break;
01323     case 48:
01324       readPageInfoSeg(segLength);
01325       break;
01326     case 50:
01327       readEndOfStripeSeg(segLength);
01328       break;
01329     case 52:
01330       readProfilesSeg(segLength);
01331       break;
01332     case 53:
01333       readCodeTableSeg(segNum, segLength);
01334       break;
01335     case 62:
01336       readExtensionSeg(segLength);
01337       break;
01338     default:
01339       error(getPos(), "Unknown segment type in JBIG2 stream");
01340       for (i = 0; i < segLength; ++i) {
01341        if ((c1 = curStr->getChar()) == EOF) {
01342          goto eofError2;
01343        }
01344       }
01345       break;
01346     }
01347 
01348     gfree(refSegs);
01349   }
01350 
01351   return;
01352 
01353  eofError2:
01354   gfree(refSegs);
01355  eofError1:
01356   error(getPos(), "Unexpected EOF in JBIG2 stream");
01357 }
01358 
01359 void JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
01360                                 Guint *refSegs, Guint nRefSegs) {
01361   JBIG2SymbolDict *symbolDict;
01362   JBIG2HuffmanTable *huffDHTable, *huffDWTable;
01363   JBIG2HuffmanTable *huffBMSizeTable, *huffAggInstTable;
01364   JBIG2Segment *seg;
01365   GList *codeTables;
01366   JBIG2SymbolDict *inputSymbolDict;
01367   Guint flags, sdTemplate, sdrTemplate, huff, refAgg;
01368   Guint huffDH, huffDW, huffBMSize, huffAggInst;
01369   Guint contextUsed, contextRetained;
01370   int sdATX[4], sdATY[4], sdrATX[2], sdrATY[2];
01371   Guint numExSyms, numNewSyms, numInputSyms, symCodeLen;
01372   JBIG2Bitmap **bitmaps;
01373   JBIG2Bitmap *collBitmap, *refBitmap;
01374   Guint *symWidths;
01375   Guint symHeight, symWidth, totalWidth, x, symID;
01376   int dh, dw, refAggNum, refDX, refDY, bmSize;
01377   GBool ex;
01378   int run, cnt;
01379   Guint i, j, k;
01380   Guchar *p;
01381 
01382   // symbol dictionary flags
01383   if (!readUWord(&flags)) {
01384     goto eofError;
01385   }
01386   sdTemplate = (flags >> 10) & 3;
01387   sdrTemplate = (flags >> 12) & 1;
01388   huff = flags & 1;
01389   refAgg = (flags >> 1) & 1;
01390   huffDH = (flags >> 2) & 3;
01391   huffDW = (flags >> 4) & 3;
01392   huffBMSize = (flags >> 6) & 1;
01393   huffAggInst = (flags >> 7) & 1;
01394   contextUsed = (flags >> 8) & 1;
01395   contextRetained = (flags >> 9) & 1;
01396 
01397   // symbol dictionary AT flags
01398   if (!huff) {
01399     if (sdTemplate == 0) {
01400       if (!readByte(&sdATX[0]) ||
01401          !readByte(&sdATY[0]) ||
01402          !readByte(&sdATX[1]) ||
01403          !readByte(&sdATY[1]) ||
01404          !readByte(&sdATX[2]) ||
01405          !readByte(&sdATY[2]) ||
01406          !readByte(&sdATX[3]) ||
01407          !readByte(&sdATY[3])) {
01408        goto eofError;
01409       }
01410     } else {
01411       if (!readByte(&sdATX[0]) ||
01412          !readByte(&sdATY[0])) {
01413        goto eofError;
01414       }
01415     }
01416   }
01417 
01418   // symbol dictionary refinement AT flags
01419   if (refAgg && !sdrTemplate) {
01420     if (!readByte(&sdrATX[0]) ||
01421        !readByte(&sdrATY[0]) ||
01422        !readByte(&sdrATX[1]) ||
01423        !readByte(&sdrATY[1])) {
01424       goto eofError;
01425     }
01426   }
01427 
01428   // SDNUMEXSYMS and SDNUMNEWSYMS
01429   if (!readULong(&numExSyms) || !readULong(&numNewSyms)) {
01430     goto eofError;
01431   }
01432 
01433   // get referenced segments: input symbol dictionaries and code tables
01434   codeTables = new GList();
01435   numInputSyms = 0;
01436   for (i = 0; i < nRefSegs; ++i) {
01437     seg = findSegment(refSegs[i]);
01438     if (seg->getType() == jbig2SegSymbolDict) {
01439       numInputSyms += ((JBIG2SymbolDict *)seg)->getSize();
01440     } else if (seg->getType() == jbig2SegCodeTable) {
01441       codeTables->append(seg);
01442     }
01443   }
01444 
01445   // compute symbol code length
01446   symCodeLen = 0;
01447   i = 1;
01448   while (i < numInputSyms + numNewSyms) {
01449     ++symCodeLen;
01450     i <<= 1;
01451   }
01452 
01453   // get the input symbol bitmaps
01454   bitmaps = (JBIG2Bitmap **)gmalloc((numInputSyms + numNewSyms) *
01455                                 sizeof(JBIG2Bitmap *));
01456   k = 0;
01457   inputSymbolDict = NULL;
01458   for (i = 0; i < nRefSegs; ++i) {
01459     seg = findSegment(refSegs[i]);
01460     if (seg->getType() == jbig2SegSymbolDict) {
01461       inputSymbolDict = (JBIG2SymbolDict *)seg;
01462       for (j = 0; j < inputSymbolDict->getSize(); ++j) {
01463        bitmaps[k++] = inputSymbolDict->getBitmap(j);
01464       }
01465     }
01466   }
01467 
01468   // get the Huffman tables
01469   huffDHTable = huffDWTable = NULL; // make gcc happy
01470   huffBMSizeTable = huffAggInstTable = NULL; // make gcc happy
01471   i = 0;
01472   if (huff) {
01473     if (huffDH == 0) {
01474       huffDHTable = huffTableD;
01475     } else if (huffDH == 1) {
01476       huffDHTable = huffTableE;
01477     } else {
01478       huffDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
01479     }
01480     if (huffDW == 0) {
01481       huffDWTable = huffTableB;
01482     } else if (huffDW == 1) {
01483       huffDWTable = huffTableC;
01484     } else {
01485       huffDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
01486     }
01487     if (huffBMSize == 0) {
01488       huffBMSizeTable = huffTableA;
01489     } else {
01490       huffBMSizeTable =
01491          ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
01492     }
01493     if (huffAggInst == 0) {
01494       huffAggInstTable = huffTableA;
01495     } else {
01496       huffAggInstTable =
01497          ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
01498     }
01499   }
01500   delete codeTables;
01501 
01502   // set up the Huffman decoder
01503   if (huff) {
01504     huffDecoder->reset();
01505 
01506   // set up the arithmetic decoder
01507   } else {
01508     if (contextUsed && inputSymbolDict) {
01509       resetGenericStats(sdTemplate, inputSymbolDict->getGenericRegionStats());
01510     } else {
01511       resetGenericStats(sdTemplate, NULL);
01512     }
01513     resetIntStats(symCodeLen);
01514     arithDecoder->start();
01515   }
01516 
01517   // set up the arithmetic decoder for refinement/aggregation
01518   if (refAgg) {
01519     if (contextUsed && inputSymbolDict) {
01520       resetRefinementStats(sdrTemplate,
01521                         inputSymbolDict->getRefinementRegionStats());
01522     } else {
01523       resetRefinementStats(sdrTemplate, NULL);
01524     }
01525   }
01526 
01527   // allocate symbol widths storage
01528   symWidths = NULL;
01529   if (huff && !refAgg) {
01530     symWidths = (Guint *)gmalloc(numNewSyms * sizeof(Guint));
01531   }
01532 
01533   symHeight = 0;
01534   i = 0;
01535   while (i < numNewSyms) {
01536 
01537     // read the height class delta height
01538     if (huff) {
01539       huffDecoder->decodeInt(&dh, huffDHTable);
01540     } else {
01541       arithDecoder->decodeInt(&dh, iadhStats);
01542     }
01543     symHeight += dh;
01544     symWidth = 0;
01545     totalWidth = 0;
01546     j = i;
01547 
01548     // read the symbols in this height class
01549     while (1) {
01550 
01551       // read the delta width
01552       if (huff) {
01553        if (!huffDecoder->decodeInt(&dw, huffDWTable)) {
01554          break;
01555        }
01556       } else {
01557        if (!arithDecoder->decodeInt(&dw, iadwStats)) {
01558          break;
01559        }
01560       }
01561       symWidth += dw;
01562 
01563       // using a collective bitmap, so don't read a bitmap here
01564       if (huff && !refAgg) {
01565        symWidths[i] = symWidth;
01566        totalWidth += symWidth;
01567 
01568       // refinement/aggregate coding
01569       } else if (refAgg) {
01570        if (huff) {
01571          if (!huffDecoder->decodeInt(&refAggNum, huffAggInstTable)) {
01572            break;
01573          }
01574        } else {
01575          if (!arithDecoder->decodeInt(&refAggNum, iaaiStats)) {
01576            break;
01577          }
01578        }
01579 #if 0 //~ This special case was added about a year before the final draft
01580       //~ of the JBIG2 spec was released.  I have encountered some old
01581       //~ JBIG2 images that predate it.
01582        if (0) {
01583 #else
01584        if (refAggNum == 1) {
01585 #endif
01586          if (huff) {
01587            symID = huffDecoder->readBits(symCodeLen);
01588            huffDecoder->decodeInt(&refDX, huffTableO);
01589            huffDecoder->decodeInt(&refDY, huffTableO);
01590            huffDecoder->decodeInt(&bmSize, huffTableA);
01591            huffDecoder->reset();
01592            arithDecoder->start();
01593          } else {
01594            symID = arithDecoder->decodeIAID(symCodeLen, iaidStats);
01595            arithDecoder->decodeInt(&refDX, iardxStats);
01596            arithDecoder->decodeInt(&refDY, iardyStats);
01597          }
01598          refBitmap = bitmaps[symID];
01599          bitmaps[numInputSyms + i] =
01600              readGenericRefinementRegion(symWidth, symHeight,
01601                                      sdrTemplate, gFalse,
01602                                      refBitmap, refDX, refDY,
01603                                      sdrATX, sdrATY);
01604          //~ do we need to use the bmSize value here (in Huffman mode)?
01605        } else {
01606          bitmaps[numInputSyms + i] =
01607              readTextRegion(huff, gTrue, symWidth, symHeight,
01608                           refAggNum, 0, numInputSyms + i, NULL,
01609                           symCodeLen, bitmaps, 0, 0, 0, 1, 0,
01610                           huffTableF, huffTableH, huffTableK, huffTableO,
01611                           huffTableO, huffTableO, huffTableO, huffTableA,
01612                           sdrTemplate, sdrATX, sdrATY);
01613        }
01614 
01615       // non-ref/agg coding
01616       } else {
01617        bitmaps[numInputSyms + i] =
01618            readGenericBitmap(gFalse, symWidth, symHeight,
01619                            sdTemplate, gFalse, gFalse, NULL,
01620                            sdATX, sdATY, 0);
01621       }
01622 
01623       ++i;
01624     }
01625 
01626     // read the collective bitmap
01627     if (huff && !refAgg) {
01628       huffDecoder->decodeInt(&bmSize, huffBMSizeTable);
01629       huffDecoder->reset();
01630       if (bmSize == 0) {
01631        collBitmap = new JBIG2Bitmap(0, totalWidth, symHeight);
01632        bmSize = symHeight * ((totalWidth + 7) >> 3);
01633        p = collBitmap->getDataPtr();
01634        for (k = 0; k < (Guint)bmSize; ++k) {
01635          *p++ = curStr->getChar();
01636        }
01637       } else {
01638        collBitmap = readGenericBitmap(gTrue, totalWidth, symHeight,
01639                                    0, gFalse, gFalse, NULL, NULL, NULL,
01640                                    bmSize);
01641       }
01642       x = 0;
01643       for (; j < i; ++j) {
01644        bitmaps[numInputSyms + j] =
01645            collBitmap->getSlice(x, 0, symWidths[j], symHeight);
01646        x += symWidths[j];
01647       }
01648       delete collBitmap;
01649     }
01650   }
01651 
01652   // create the symbol dict object
01653   symbolDict = new JBIG2SymbolDict(segNum, numExSyms);
01654 
01655   // exported symbol list
01656   i = j = 0;
01657   ex = gFalse;
01658   while (i < numInputSyms + numNewSyms) {
01659     if (huff) {
01660       huffDecoder->decodeInt(&run, huffTableA);
01661     } else {
01662       arithDecoder->decodeInt(&run, iaexStats);
01663     }
01664     if (ex) {
01665       for (cnt = 0; cnt < run; ++cnt) {
01666        symbolDict->setBitmap(j++, bitmaps[i++]->copy());
01667       }
01668     } else {
01669       i += run;
01670     }
01671     ex = !ex;
01672   }
01673 
01674   for (i = 0; i < numNewSyms; ++i) {
01675     delete bitmaps[numInputSyms + i];
01676   }
01677   gfree(bitmaps);
01678   if (symWidths) {
01679     gfree(symWidths);
01680   }
01681 
01682   // save the arithmetic decoder stats
01683   if (!huff && contextRetained) {
01684     symbolDict->setGenericRegionStats(genericRegionStats->copy());
01685     if (refAgg) {
01686       symbolDict->setRefinementRegionStats(refinementRegionStats->copy());
01687     }
01688   }
01689 
01690   // store the new symbol dict
01691   segments->append(symbolDict);
01692 
01693   return;
01694 
01695  eofError:
01696   error(getPos(), "Unexpected EOF in JBIG2 stream");
01697 }
01698 
01699 void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
01700                                 GBool lossless, Guint length,
01701                                 Guint *refSegs, Guint nRefSegs) {
01702   JBIG2Bitmap *bitmap;
01703   JBIG2HuffmanTable runLengthTab[36];
01704   JBIG2HuffmanTable *symCodeTab;
01705   JBIG2HuffmanTable *huffFSTable, *huffDSTable, *huffDTTable;
01706   JBIG2HuffmanTable *huffRDWTable, *huffRDHTable;
01707   JBIG2HuffmanTable *huffRDXTable, *huffRDYTable, *huffRSizeTable;
01708   JBIG2Segment *seg;
01709   GList *codeTables;
01710   JBIG2SymbolDict *symbolDict;
01711   JBIG2Bitmap **syms;
01712   Guint w, h, x, y, segInfoFlags, extCombOp;
01713   Guint flags, huff, refine, logStrips, refCorner, transposed;
01714   Guint combOp, defPixel, templ;
01715   int sOffset;
01716   Guint huffFlags, huffFS, huffDS, huffDT;
01717   Guint huffRDW, huffRDH, huffRDX, huffRDY, huffRSize;
01718   Guint numInstances, numSyms, symCodeLen;
01719   int atx[2], aty[2];
01720   Guint i, k, kk;
01721   int j;
01722 
01723   // region segment info field
01724   if (!readULong(&w) || !readULong(&h) ||
01725       !readULong(&x) || !readULong(&y) ||
01726       !readUByte(&segInfoFlags)) {
01727     goto eofError;
01728   }
01729   extCombOp = segInfoFlags & 7;
01730 
01731   // rest of the text region header
01732   if (!readUWord(&flags)) {
01733     goto eofError;
01734   }
01735   huff = flags & 1;
01736   refine = (flags >> 1) & 1;
01737   logStrips = (flags >> 2) & 3;
01738   refCorner = (flags >> 4) & 3;
01739   transposed = (flags >> 6) & 1;
01740   combOp = (flags >> 7) & 3;
01741   defPixel = (flags >> 9) & 1;
01742   sOffset = (flags >> 10) & 0x1f;
01743   if (sOffset & 0x10) {
01744     sOffset |= -1 - 0x0f;
01745   }
01746   templ = (flags >> 15) & 1;
01747   huffFS = huffDS = huffDT = 0; // make gcc happy
01748   huffRDW = huffRDH = huffRDX = huffRDY = huffRSize = 0; // make gcc happy
01749   if (huff) {
01750     if (!readUWord(&huffFlags)) {
01751       goto eofError;
01752     }
01753     huffFS = huffFlags & 3;
01754     huffDS = (huffFlags >> 2) & 3;
01755     huffDT = (huffFlags >> 4) & 3;
01756     huffRDW = (huffFlags >> 6) & 3;
01757     huffRDH = (huffFlags >> 8) & 3;
01758     huffRDX = (huffFlags >> 10) & 3;
01759     huffRDY = (huffFlags >> 12) & 3;
01760     huffRSize = (huffFlags >> 14) & 1;
01761   }
01762   if (refine && templ == 0) {
01763     if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
01764        !readByte(&atx[1]) || !readByte(&aty[1])) {
01765       goto eofError;
01766     }
01767   }
01768   if (!readULong(&numInstances)) {
01769     goto eofError;
01770   }
01771 
01772   // get symbol dictionaries and tables
01773   codeTables = new GList();
01774   numSyms = 0;
01775   for (i = 0; i < nRefSegs; ++i) {
01776     seg = findSegment(refSegs[i]);
01777     if (seg->getType() == jbig2SegSymbolDict) {
01778       numSyms += ((JBIG2SymbolDict *)seg)->getSize();
01779     } else if (seg->getType() == jbig2SegCodeTable) {
01780       codeTables->append(seg);
01781     }
01782   }
01783   symCodeLen = 0;
01784   i = 1;
01785   while (i < numSyms) {
01786     ++symCodeLen;
01787     i <<= 1;
01788   }
01789 
01790   // get the symbol bitmaps
01791   syms = (JBIG2Bitmap **)gmalloc(numSyms * sizeof(JBIG2Bitmap *));
01792   kk = 0;
01793   for (i = 0; i < nRefSegs; ++i) {
01794     seg = findSegment(refSegs[i]);
01795     if (seg->getType() == jbig2SegSymbolDict) {
01796       symbolDict = (JBIG2SymbolDict *)seg;
01797       for (k = 0; k < symbolDict->getSize(); ++k) {
01798        syms[kk++] = symbolDict->getBitmap(k);
01799       }
01800     }
01801   }
01802 
01803   // get the Huffman tables
01804   huffFSTable = huffDSTable = huffDTTable = NULL; // make gcc happy
01805   huffRDWTable = huffRDHTable = NULL; // make gcc happy
01806   huffRDXTable = huffRDYTable = huffRSizeTable = NULL; // make gcc happy
01807   i = 0;
01808   if (huff) {
01809     if (huffFS == 0) {
01810       huffFSTable = huffTableF;
01811     } else if (huffFS == 1) {
01812       huffFSTable = huffTableG;
01813     } else {
01814       huffFSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
01815     }
01816     if (huffDS == 0) {
01817       huffDSTable = huffTableH;
01818     } else if (huffDS == 1) {
01819       huffDSTable = huffTableI;
01820     } else if (huffDS == 2) {
01821       huffDSTable = huffTableJ;
01822     } else {
01823       huffDSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
01824     }
01825     if (huffDT == 0) {
01826       huffDTTable = huffTableK;
01827     } else if (huffDT == 1) {
01828       huffDTTable = huffTableL;
01829     } else if (huffDT == 2) {
01830       huffDTTable = huffTableM;
01831     } else {
01832       huffDTTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
01833     }
01834     if (huffRDW == 0) {
01835       huffRDWTable = huffTableN;
01836     } else if (huffRDW == 1) {
01837       huffRDWTable = huffTableO;
01838     } else {
01839       huffRDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
01840     }
01841     if (huffRDH == 0) {
01842       huffRDHTable = huffTableN;
01843     } else if (huffRDH == 1) {
01844       huffRDHTable = huffTableO;
01845     } else {
01846       huffRDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
01847     }
01848     if (huffRDX == 0) {
01849       huffRDXTable = huffTableN;
01850     } else if (huffRDX == 1) {
01851       huffRDXTable = huffTableO;
01852     } else {
01853       huffRDXTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
01854     }
01855     if (huffRDY == 0) {
01856       huffRDYTable = huffTableN;
01857     } else if (huffRDY == 1) {
01858       huffRDYTable = huffTableO;
01859     } else {
01860       huffRDYTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
01861     }
01862     if (huffRSize == 0) {
01863       huffRSizeTable = huffTableA;
01864     } else {
01865       huffRSizeTable =
01866          ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
01867     }
01868   }
01869   delete codeTables;
01870 
01871   // symbol ID Huffman decoding table
01872   if (huff) {
01873     huffDecoder->reset();
01874     for (i = 0; i < 32; ++i) {
01875       runLengthTab[i].val = i;
01876       runLengthTab[i].prefixLen = huffDecoder->readBits(4);
01877       runLengthTab[i].rangeLen = 0;
01878     }
01879     runLengthTab[32].val = 0x103;
01880     runLengthTab[32].prefixLen = huffDecoder->readBits(4);
01881     runLengthTab[32].rangeLen = 2;
01882     runLengthTab[33].val = 0x203;
01883     runLengthTab[33].prefixLen = huffDecoder->readBits(4);
01884     runLengthTab[33].rangeLen = 3;
01885     runLengthTab[34].val = 0x20b;
01886     runLengthTab[34].prefixLen = huffDecoder->readBits(4);
01887     runLengthTab[34].rangeLen = 7;
01888     runLengthTab[35].prefixLen = 0;
01889     runLengthTab[35].rangeLen = jbig2HuffmanEOT;
01890     huffDecoder->buildTable(runLengthTab, 35);
01891     symCodeTab = (JBIG2HuffmanTable *)gmalloc((numSyms + 1) *
01892                                          sizeof(JBIG2HuffmanTable));
01893     for (i = 0; i < numSyms; ++i) {
01894       symCodeTab[i].val = i;
01895       symCodeTab[i].rangeLen = 0;
01896     }
01897     i = 0;
01898     while (i < numSyms) {
01899       huffDecoder->decodeInt(&j, runLengthTab);
01900       if (j > 0x200) {
01901        for (j -= 0x200; j && i < numSyms; --j) {
01902          symCodeTab[i++].prefixLen = 0;
01903        }
01904       } else if (j > 0x100) {
01905        for (j -= 0x100; j && i < numSyms; --j) {
01906          symCodeTab[i].prefixLen = symCodeTab[i-1].prefixLen;
01907          ++i;
01908        }
01909       } else {
01910        symCodeTab[i++].prefixLen = j;
01911       }
01912     }
01913     symCodeTab[numSyms].prefixLen = 0;
01914     symCodeTab[numSyms].rangeLen = jbig2HuffmanEOT;
01915     huffDecoder->buildTable(symCodeTab, numSyms);
01916     huffDecoder->reset();
01917 
01918   // set up the arithmetic decoder
01919   } else {
01920     symCodeTab = NULL;
01921     resetIntStats(symCodeLen);
01922     arithDecoder->start();
01923   }
01924   if (refine) {
01925     resetRefinementStats(templ, NULL);
01926   }
01927 
01928   bitmap = readTextRegion(huff, refine, w, h, numInstances,
01929                        logStrips, numSyms, symCodeTab, symCodeLen, syms,
01930                        defPixel, combOp, transposed, refCorner, sOffset,
01931                        huffFSTable, huffDSTable, huffDTTable,
01932                        huffRDWTable, huffRDHTable,
01933                        huffRDXTable, huffRDYTable, huffRSizeTable,
01934                        templ, atx, aty);
01935 
01936   gfree(syms);
01937 
01938   // combine the region bitmap into the page bitmap
01939   if (imm) {
01940     if (pageH == 0xffffffff && y + h > curPageH) {
01941       pageBitmap->expand(y + h, pageDefPixel);
01942     }
01943     pageBitmap->combine(bitmap, x, y, extCombOp);
01944     delete bitmap;
01945 
01946   // store the region bitmap
01947   } else {
01948     bitmap->setSegNum(segNum);
01949     segments->append(bitmap);
01950   }
01951 
01952   // clean up the Huffman decoder
01953   if (huff) {
01954     gfree(symCodeTab);
01955   }
01956 
01957   return;
01958 
01959  eofError:
01960   error(getPos(), "Unexpected EOF in JBIG2 stream");
01961 }
01962 
01963 JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine,
01964                                     int w, int h,
01965                                     Guint numInstances,
01966                                     Guint logStrips,
01967                                     int numSyms,
01968                                     JBIG2HuffmanTable *symCodeTab,
01969                                     Guint symCodeLen,
01970                                     JBIG2Bitmap **syms,
01971                                     Guint defPixel, Guint combOp,
01972                                     Guint transposed, Guint refCorner,
01973                                     int sOffset,
01974                                     JBIG2HuffmanTable *huffFSTable,
01975                                     JBIG2HuffmanTable *huffDSTable,
01976                                     JBIG2HuffmanTable *huffDTTable,
01977                                     JBIG2HuffmanTable *huffRDWTable,
01978                                     JBIG2HuffmanTable *huffRDHTable,
01979                                     JBIG2HuffmanTable *huffRDXTable,
01980                                     JBIG2HuffmanTable *huffRDYTable,
01981                                     JBIG2HuffmanTable *huffRSizeTable,
01982                                     Guint templ,
01983                                     int *atx, int *aty) {
01984   JBIG2Bitmap *bitmap;
01985   JBIG2Bitmap *symbolBitmap;
01986   Guint strips;
01987   int t, dt, tt, s, ds, sFirst, j;
01988   int rdw, rdh, rdx, rdy, ri, refDX, refDY, bmSize;
01989   Guint symID, inst, bw, bh;
01990 
01991   strips = 1 << logStrips;
01992 
01993   // allocate the bitmap
01994   bitmap = new JBIG2Bitmap(0, w, h);
01995   if (defPixel) {
01996     bitmap->clearToOne();
01997   } else {
01998     bitmap->clearToZero();
01999   }
02000 
02001   // decode initial T value
02002   if (huff) {
02003     huffDecoder->decodeInt(&t, huffDTTable);
02004   } else {
02005     arithDecoder->decodeInt(&t, iadtStats);
02006   }
02007   t *= -(int)strips;
02008 
02009   inst = 0;
02010   sFirst = 0;
02011   while (inst < numInstances) {
02012 
02013     // decode delta-T
02014     if (huff) {
02015       huffDecoder->decodeInt(&dt, huffDTTable);
02016     } else {
02017       arithDecoder->decodeInt(&dt, iadtStats);
02018     }
02019     t += dt * strips;
02020 
02021     // first S value
02022     if (huff) {
02023       huffDecoder->decodeInt(&ds, huffFSTable);
02024     } else {
02025       arithDecoder->decodeInt(&ds, iafsStats);
02026     }
02027     sFirst += ds;
02028     s = sFirst;
02029 
02030     // read the instances
02031     while (1) {
02032 
02033       // T value
02034       if (strips == 1) {
02035        dt = 0;
02036       } else if (huff) {
02037        dt = huffDecoder->readBits(logStrips);
02038       } else {
02039        arithDecoder->decodeInt(&dt, iaitStats);
02040       }
02041       tt = t + dt;
02042 
02043       // symbol ID
02044       if (huff) {
02045        if (symCodeTab) {
02046          huffDecoder->decodeInt(&j, symCodeTab);
02047          symID = (Guint)j;
02048        } else {
02049          symID = huffDecoder->readBits(symCodeLen);
02050        }
02051       } else {
02052        symID = arithDecoder->decodeIAID(symCodeLen, iaidStats);
02053       }
02054 
02055       // get the symbol bitmap
02056       symbolBitmap = NULL;
02057       if (refine) {
02058        if (huff) {
02059          ri = (int)huffDecoder->readBit();
02060        } else {
02061          arithDecoder->decodeInt(&ri, iariStats);
02062        }
02063       } else {
02064        ri = 0;
02065       }
02066       if (ri) {
02067        if (huff) {
02068          huffDecoder->decodeInt(&rdw, huffRDWTable);
02069          huffDecoder->decodeInt(&rdh, huffRDHTable);
02070          huffDecoder->decodeInt(&rdx, huffRDXTable);
02071          huffDecoder->decodeInt(&rdy, huffRDYTable);
02072          huffDecoder->decodeInt(&bmSize, huffRSizeTable);
02073          huffDecoder->reset();
02074          arithDecoder->start();
02075        } else {
02076          arithDecoder->decodeInt(&rdw, iardwStats);
02077          arithDecoder->decodeInt(&rdh, iardhStats);
02078          arithDecoder->decodeInt(&rdx, iardxStats);
02079          arithDecoder->decodeInt(&rdy, iardyStats);
02080        }
02081        refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx;
02082        refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy;
02083 
02084        symbolBitmap =
02085          readGenericRefinementRegion(rdw + syms[symID]->getWidth(),
02086                                   rdh + syms[symID]->getHeight(),
02087                                   templ, gFalse, syms[symID],
02088                                   refDX, refDY, atx, aty);
02089        //~ do we need to use the bmSize value here (in Huffman mode)?
02090       } else {
02091        symbolBitmap = syms[symID];
02092       }
02093 
02094       // combine the symbol bitmap into the region bitmap
02095       //~ something is wrong here - refCorner shouldn't degenerate into
02096       //~   two cases
02097       bw = symbolBitmap->getWidth() - 1;
02098       bh = symbolBitmap->getHeight() - 1;
02099       if (transposed) {
02100        switch (refCorner) {
02101        case 0: // bottom left
02102          bitmap->combine(symbolBitmap, tt, s, combOp);
02103          break;
02104        case 1: // top left
02105          bitmap->combine(symbolBitmap, tt, s, combOp);
02106          break;
02107        case 2: // bottom right
02108          bitmap->combine(symbolBitmap, tt - bw, s, combOp);
02109          break;
02110        case 3: // top right
02111          bitmap->combine(symbolBitmap, tt - bw, s, combOp);
02112          break;
02113        }
02114        s += bh;
02115       } else {
02116        switch (refCorner) {
02117        case 0: // bottom left
02118          bitmap->combine(symbolBitmap, s, tt - bh, combOp);
02119          break;
02120        case 1: // top left
02121          bitmap->combine(symbolBitmap, s, tt, combOp);
02122          break;
02123        case 2: // bottom right
02124          bitmap->combine(symbolBitmap, s, tt - bh, combOp);
02125          break;
02126        case 3: // top right
02127          bitmap->combine(symbolBitmap, s, tt, combOp);
02128          break;
02129        }
02130        s += bw;
02131       }
02132       if (ri) {
02133        delete symbolBitmap;
02134       }
02135 
02136       // next instance
02137       ++inst;
02138 
02139       // next S value
02140       if (huff) {
02141        if (!huffDecoder->decodeInt(&ds, huffDSTable)) {
02142          break;
02143        }
02144       } else {
02145        if (!arithDecoder->decodeInt(&ds, iadsStats)) {
02146          break;
02147        }
02148       }
02149       s += sOffset + ds;
02150     }
02151   }
02152 
02153   return bitmap;
02154 }
02155 
02156 void JBIG2Stream::readPatternDictSeg(Guint segNum, Guint length) {
02157   JBIG2PatternDict *patternDict;
02158   JBIG2Bitmap *bitmap;
02159   Guint flags, patternW, patternH, grayMax, templ, mmr;
02160   int atx[4], aty[4];
02161   Guint i, x;
02162 
02163   // halftone dictionary flags, pattern width and height, max gray value
02164   if (!readUByte(&flags) ||
02165       !readUByte(&patternW) ||
02166       !readUByte(&patternH) ||
02167       !readULong(&grayMax)) {
02168     goto eofError;
02169   }
02170   templ = (flags >> 1) & 3;
02171   mmr = flags & 1;
02172 
02173   // set up the arithmetic decoder
02174   if (!mmr) {
02175     resetGenericStats(templ, NULL);
02176     arithDecoder->start();
02177   }
02178 
02179   // read the bitmap
02180   atx[0] = -(int)patternW; aty[0] =  0;
02181   atx[1] = -3;             aty[1] = -1;
02182   atx[2] =  2;             aty[2] = -2;
02183   atx[3] = -2;             aty[3] = -2;
02184   bitmap = readGenericBitmap(mmr, (grayMax + 1) * patternW, patternH,
02185                           templ, gFalse, gFalse, NULL,
02186                           atx, aty, length - 7);
02187 
02188   // create the pattern dict object
02189   patternDict = new JBIG2PatternDict(segNum, grayMax + 1);
02190 
02191   // split up the bitmap
02192   x = 0;
02193   for (i = 0; i <= grayMax; ++i) {
02194     patternDict->setBitmap(i, bitmap->getSlice(x, 0, patternW, patternH));
02195     x += patternW;
02196   }
02197 
02198   // free memory
02199   delete bitmap;
02200 
02201   // store the new pattern dict
02202   segments->append(patternDict);
02203 
02204   return;
02205 
02206  eofError:
02207   error(getPos(), "Unexpected EOF in JBIG2 stream");
02208 }
02209 
02210 void JBIG2Stream::readHalftoneRegionSeg(Guint segNum, GBool imm,
02211                                    GBool lossless, Guint length,
02212                                    Guint *refSegs, Guint nRefSegs) {
02213   JBIG2Bitmap *bitmap;
02214   JBIG2Segment *seg;
02215   JBIG2PatternDict *patternDict;
02216   JBIG2Bitmap *skipBitmap;
02217   Guint *grayImg;
02218   JBIG2Bitmap *grayBitmap;
02219   JBIG2Bitmap *patternBitmap;
02220   Guint w, h, x, y, segInfoFlags, extCombOp;
02221   Guint flags, mmr, templ, enableSkip, combOp;
02222   Guint gridW, gridH, stepX, stepY, patW, patH;
02223   int atx[4], aty[4];
02224   int gridX, gridY, xx, yy, bit, j;
02225   Guint bpp, m, n, i;
02226 
02227   // region segment info field
02228   if (!readULong(&w) || !readULong(&h) ||
02229       !readULong(&x) || !readULong(&y) ||
02230       !readUByte(&segInfoFlags)) {
02231     goto eofError;
02232   }
02233   extCombOp = segInfoFlags & 7;
02234 
02235   // rest of the halftone region header
02236   if (!readUByte(&flags)) {
02237     goto eofError;
02238   }
02239   mmr = flags & 1;
02240   templ = (flags >> 1) & 3;
02241   enableSkip = (flags >> 3) & 1;
02242   combOp = (flags >> 4) & 7;
02243   if (!readULong(&gridW) || !readULong(&gridH) ||
02244       !readLong(&gridX) || !readLong(&gridY) ||
02245       !readUWord(&stepX) || !readUWord(&stepY)) {
02246     goto eofError;
02247   }
02248 
02249   // get pattern dictionary
02250   if (nRefSegs != 1) {
02251     error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
02252     return;
02253   }
02254   seg = findSegment(refSegs[0]);
02255   if (seg->getType() != jbig2SegPatternDict) {
02256     error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
02257     return;
02258   }
02259   patternDict = (JBIG2PatternDict *)seg;
02260   bpp = 0;
02261   i = 1;
02262   while (i < patternDict->getSize()) {
02263     ++bpp;
02264     i <<= 1;
02265   }
02266   patW = patternDict->getBitmap(0)->getWidth();
02267   patH = patternDict->getBitmap(0)->getHeight();
02268 
02269   // set up the arithmetic decoder
02270   if (!mmr) {
02271     resetGenericStats(templ, NULL);
02272     arithDecoder->start();
02273   }
02274 
02275   // allocate the bitmap
02276   bitmap = new JBIG2Bitmap(segNum, w, h);
02277   if (flags & 0x80) { // HDEFPIXEL
02278     bitmap->clearToOne();
02279   } else {
02280     bitmap->clearToZero();
02281   }
02282 
02283   // compute the skip bitmap
02284   skipBitmap = NULL;
02285   if (enableSkip) {
02286     skipBitmap = new JBIG2Bitmap(0, gridW, gridH);
02287     skipBitmap->clearToZero();
02288     for (m = 0; m < gridH; ++m) {
02289       xx = gridX + m * stepY;
02290       yy = gridY + m * stepX;
02291       for (n = 0; n < gridW; ++n) {
02292        if (((xx + (int)patW) >> 8) <= 0 || (xx >> 8) >= (int)w ||
02293            ((yy + (int)patH) >> 8) <= 0 || (yy >> 8) >= (int)h) {
02294          skipBitmap->setPixel(n, m);
02295        }
02296       }
02297     }
02298   }
02299 
02300   // read the gray-scale image
02301   grayImg = (Guint *)gmalloc(gridW * gridH * sizeof(Guint));
02302   memset(grayImg, 0, gridW * gridH * sizeof(Guint));
02303   atx[0] = templ <= 1 ? 3 : 2;  aty[0] = -1;
02304   atx[1] = -3;                  aty[1] = -1;
02305   atx[2] =  2;                  aty[2] = -2;
02306   atx[3] = -2;                  aty[3] = -2;
02307   for (j = bpp - 1; j >= 0; --j) {
02308     grayBitmap = readGenericBitmap(mmr, gridW, gridH, templ, gFalse,
02309                                enableSkip, skipBitmap, atx, aty, -1);
02310     i = 0;
02311     for (m = 0; m < gridH; ++m) {
02312       for (n = 0; n < gridW; ++n) {
02313        bit = grayBitmap->getPixel(n, m) ^ (grayImg[i] & 1);
02314        grayImg[i] = (grayImg[i] << 1) | bit;
02315        ++i;
02316       }
02317     }
02318     delete grayBitmap;
02319   }
02320 
02321   // decode the image
02322   i = 0;
02323   for (m = 0; m < gridH; ++m) {
02324     xx = gridX + m * stepY;
02325     yy = gridY + m * stepX;
02326     for (n = 0; n < gridW; ++n) {
02327       if (!(enableSkip && skipBitmap->getPixel(n, m))) {
02328        patternBitmap = patternDict->getBitmap(grayImg[i]);
02329        bitmap->combine(patternBitmap, xx >> 8, yy >> 8, combOp);
02330       }
02331       xx += stepX;
02332       yy -= stepY;
02333       ++i;
02334     }
02335   }
02336 
02337   gfree(grayImg);
02338 
02339   // combine the region bitmap into the page bitmap
02340   if (imm) {
02341     if (pageH == 0xffffffff && y + h > curPageH) {
02342       pageBitmap->expand(y + h, pageDefPixel);
02343     }
02344     pageBitmap->combine(bitmap, x, y, extCombOp);
02345     delete bitmap;
02346 
02347   // store the region bitmap
02348   } else {
02349     segments->append(bitmap);
02350   }
02351 
02352   return;
02353 
02354  eofError:
02355   error(getPos(), "Unexpected EOF in JBIG2 stream");
02356 }
02357 
02358 void JBIG2Stream::readGenericRegionSeg(Guint segNum, GBool imm,
02359                                    GBool lossless, Guint length) {
02360   JBIG2Bitmap *bitmap;
02361   Guint w, h, x, y, segInfoFlags, extCombOp;
02362   Guint flags, mmr, templ, tpgdOn;
02363   int atx[4], aty[4];
02364 
02365   // region segment info field
02366   if (!readULong(&w) || !readULong(&h) ||
02367       !readULong(&x) || !readULong(&y) ||
02368       !readUByte(&segInfoFlags)) {
02369     goto eofError;
02370   }
02371   extCombOp = segInfoFlags & 7;
02372 
02373   // rest of the generic region segment header
02374   if (!readUByte(&flags)) {
02375     goto eofError;
02376   }
02377   mmr = flags & 1;
02378   templ = (flags >> 1) & 3;
02379   tpgdOn = (flags >> 3) & 1;
02380 
02381   // AT flags
02382   if (!mmr) {
02383     if (templ == 0) {
02384       if (!readByte(&atx[0]) ||
02385          !readByte(&aty[0]) ||
02386          !readByte(&atx[1]) ||
02387          !readByte(&aty[1]) ||
02388          !readByte(&atx[2]) ||
02389          !readByte(&aty[2]) ||
02390          !readByte(&atx[3]) ||
02391          !readByte(&aty[3])) {
02392        goto eofError;
02393       }
02394     } else {
02395       if (!readByte(&atx[0]) ||
02396          !readByte(&aty[0])) {
02397        goto eofError;
02398       }
02399     }
02400   }
02401 
02402   // set up the arithmetic decoder
02403   if (!mmr) {
02404     resetGenericStats(templ, NULL);
02405     arithDecoder->start();
02406   }
02407 
02408   // read the bitmap
02409   bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse,
02410                           NULL, atx, aty, mmr ? 0 : length - 18);
02411 
02412   // combine the region bitmap into the page bitmap
02413   if (imm) {
02414     if (pageH == 0xffffffff && y + h > curPageH) {
02415       pageBitmap->expand(y + h, pageDefPixel);
02416     }
02417     pageBitmap->combine(bitmap, x, y, extCombOp);
02418     delete bitmap;
02419 
02420   // store the region bitmap
02421   } else {
02422     bitmap->setSegNum(segNum);
02423     segments->append(bitmap);
02424   }
02425 
02426   return;
02427 
02428  eofError:
02429   error(getPos(), "Unexpected EOF in JBIG2 stream");
02430 }
02431 
02432 JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
02433                                        int templ, GBool tpgdOn,
02434                                        GBool useSkip, JBIG2Bitmap *skip,
02435                                        int *atx, int *aty,
02436                                        int mmrDataLength) {
02437   JBIG2Bitmap *bitmap;
02438   GBool ltp;
02439   Guint ltpCX, cx, cx0, cx1, cx2;
02440   JBIG2BitmapPtr cxPtr0, cxPtr1;
02441   JBIG2BitmapPtr atPtr0, atPtr1, atPtr2, atPtr3;
02442   int *refLine, *codingLine;
02443   int code1, code2, code3;
02444   int x, y, a0, pix, i, refI, codingI;
02445 
02446   bitmap = new JBIG2Bitmap(0, w, h);
02447   bitmap->clearToZero();
02448 
02449   //----- MMR decode
02450 
02451   if (mmr) {
02452 
02453     mmrDecoder->reset();
02454     refLine = (int *)gmalloc((w + 2) * sizeof(int));
02455     codingLine = (int *)gmalloc((w + 2) * sizeof(int));
02456     codingLine[0] = codingLine[1] = w;
02457 
02458     for (y = 0; y < h; ++y) {
02459 
02460       // copy coding line to ref line
02461       for (i = 0; codingLine[i] < w; ++i) {
02462        refLine[i] = codingLine[i];
02463       }
02464       refLine[i] = refLine[i + 1] = w;
02465 
02466       // decode a line
02467       refI = 0;     // b1 = refLine[refI]
02468       codingI = 0;  // a1 = codingLine[codingI]
02469       a0 = 0;
02470       do {
02471        code1 = mmrDecoder->get2DCode();
02472        switch (code1) {
02473        case twoDimPass:
02474          if (refLine[refI] < w) {
02475            a0 = refLine[refI + 1];
02476            refI += 2;
02477          }
02478          break;
02479        case twoDimHoriz:
02480          if (codingI & 1) {
02481            code1 = 0;
02482            do {
02483              code1 += code3 = mmrDecoder->getBlackCode();
02484            } while (code3 >= 64);
02485            code2 = 0;
02486            do {
02487              code2 += code3 = mmrDecoder->getWhiteCode();
02488            } while (code3 >= 64);
02489          } else {
02490            code1 = 0;
02491            do {
02492              code1 += code3 = mmrDecoder->getWhiteCode();
02493            } while (code3 >= 64);
02494            code2 = 0;
02495            do {
02496              code2 += code3 = mmrDecoder->getBlackCode();
02497            } while (code3 >= 64);
02498          }
02499          if (code1 > 0 || code2 > 0) {
02500            a0 = codingLine[codingI++] = a0 + code1;
02501            a0 = codingLine[codingI++] = a0 + code2;
02502            while (refLine[refI] <= a0 && refLine[refI] < w) {
02503              refI += 2;
02504            }
02505          }
02506          break;
02507        case twoDimVert0:
02508          a0 = codingLine[codingI++] = refLine[refI];
02509          if (refLine[refI] < w) {
02510            ++refI;
02511          }
02512          break;
02513        case twoDimVertR1:
02514          a0 = codingLine[codingI++] = refLine[refI] + 1;
02515          if (refLine[refI] < w) {
02516            ++refI;
02517            while (refLine[refI] <= a0 && refLine[refI] < w) {
02518              refI += 2;
02519            }
02520          }
02521          break;
02522        case twoDimVertR2:
02523          a0 = codingLine[codingI++] = refLine[refI] + 2;
02524          if (refLine[refI] < w) {
02525            ++refI;
02526            while (refLine[refI] <= a0 && refLine[refI] < w) {
02527              refI += 2;
02528            }
02529          }
02530          break;
02531        case twoDimVertR3:
02532          a0 = codingLine[codingI++] = refLine[refI] + 3;
02533          if (refLine[refI] < w) {
02534            ++refI;
02535            while (refLine[refI] <= a0 && refLine[refI] < w) {
02536              refI += 2;
02537            }
02538          }
02539          break;
02540        case twoDimVertL1:
02541          a0 = codingLine[codingI++] = refLine[refI] - 1;
02542          if (refI > 0) {
02543            --refI;
02544          } else {
02545            ++refI;
02546          }
02547          while (refLine[refI] <= a0 && refLine[refI] < w) {
02548            refI += 2;
02549          }
02550          break;
02551        case twoDimVertL2:
02552          a0 = codingLine[codingI++] = refLine[refI] - 2;
02553          if (refI > 0) {
02554            --refI;
02555          } else {
02556            ++refI;
02557          }
02558          while (refLine[refI] <= a0 && refLine[refI] < w) {
02559            refI += 2;
02560          }
02561          break;
02562        case twoDimVertL3:
02563          a0 = codingLine[codingI++] = refLine[refI] - 3;
02564          if (refI > 0) {
02565            --refI;
02566          } else {
02567            ++refI;
02568          }
02569          while (refLine[refI] <= a0 && refLine[refI] < w) {
02570            refI += 2;
02571          }
02572          break;
02573        default:
02574          error(getPos(), "Illegal code in JBIG2 MMR bitmap data");
02575          break;
02576        }
02577       } while (a0 < w);
02578       codingLine[codingI++] = w;
02579 
02580       // convert the run lengths to a bitmap line
02581       i = 0;
02582       while (codingLine[i] < w) {
02583        for (x = codingLine[i]; x < codingLine[i+1]; ++x) {
02584          bitmap->setPixel(x, y);
02585        }
02586        i += 2;
02587       }
02588     }
02589 
02590     if (mmrDataLength >= 0) {
02591       mmrDecoder->skipTo(mmrDataLength);
02592     } else {
02593       if (mmrDecoder->get24Bits() != 0x001001) {
02594        error(getPos(), "Missing EOFB in JBIG2 MMR bitmap data");
02595       }
02596     }
02597 
02598     gfree(refLine);
02599     gfree(codingLine);
02600 
02601   //----- arithmetic decode
02602 
02603   } else {
02604     // set up the typical row context
02605     ltpCX = 0; // make gcc happy
02606     if (tpgdOn) {
02607       switch (templ) {
02608       case 0:
02609        ltpCX = 0x3953; // 001 11001 0101 0011
02610        break;
02611       case 1:
02612        ltpCX = 0x079a; // 0011 11001 101 0
02613        break;
02614       case 2:
02615        ltpCX = 0x0e3; // 001 1100 01 1
02616        break;
02617       case 3:
02618        ltpCX = 0x18a; // 01100 0101 1
02619        break;
02620       }
02621     }
02622 
02623     ltp = 0;
02624     cx = cx0 = cx1 = cx2 = 0; // make gcc happy
02625     for (y = 0; y < h; ++y) {
02626 
02627       // check for a "typical" (duplicate) row
02628       if (tpgdOn) {
02629        if (arithDecoder->decodeBit(ltpCX, genericRegionStats)) {
02630          ltp = !ltp;
02631        }
02632        if (ltp) {
02633          bitmap->duplicateRow(y, y-1);
02634          continue;
02635        }
02636       }
02637 
02638       switch (templ) {
02639       case 0:
02640 
02641        // set up the context
02642        bitmap->getPixelPtr(0, y-2, &cxPtr0);
02643        cx0 = bitmap->nextPixel(&cxPtr0);
02644        cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
02645        bitmap->getPixelPtr(0, y-1, &cxPtr1);
02646        cx1 = bitmap->nextPixel(&cxPtr1);
02647        cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
02648        cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
02649        cx2 = 0;
02650        bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
02651        bitmap->getPixelPtr(atx[1], y + aty[1], &atPtr1);
02652        bitmap->getPixelPtr(atx[2], y + aty[2], &atPtr2);
02653        bitmap->getPixelPtr(atx[3], y + aty[3], &atPtr3);
02654 
02655        // decode the row
02656        for (x = 0; x < w; ++x) {
02657 
02658          // build the context
02659          cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) |
02660               (bitmap->nextPixel(&atPtr0) << 3) |
02661               (bitmap->nextPixel(&atPtr1) << 2) |
02662               (bitmap->nextPixel(&atPtr2) << 1) |
02663               bitmap->nextPixel(&atPtr3);
02664 
02665          // check for a skipped pixel
02666          if (useSkip && skip->getPixel(x, y)) {
02667            pix = 0;
02668 
02669          // decode the pixel
02670          } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
02671            bitmap->setPixel(x, y);
02672          }
02673 
02674          // update the context
02675          cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07;
02676          cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
02677          cx2 = ((cx2 << 1) | pix) & 0x0f;
02678        }
02679        break;
02680 
02681       case 1:
02682 
02683        // set up the context
02684        bitmap->getPixelPtr(0, y-2, &cxPtr0);
02685        cx0 = bitmap->nextPixel(&cxPtr0);
02686        cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
02687        cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
02688        bitmap->getPixelPtr(0, y-1, &cxPtr1);
02689        cx1 = bitmap->nextPixel(&cxPtr1);
02690        cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
02691        cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
02692        cx2 = 0;
02693        bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
02694 
02695        // decode the row
02696        for (x = 0; x < w; ++x) {
02697 
02698          // build the context
02699          cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) |
02700               bitmap->nextPixel(&atPtr0);
02701 
02702          // check for a skipped pixel
02703          if (useSkip && skip->getPixel(x, y)) {
02704            pix = 0;
02705 
02706          // decode the pixel
02707          } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
02708            bitmap->setPixel(x, y);
02709          }
02710 
02711          // update the context
02712          cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x0f;
02713          cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
02714          cx2 = ((cx2 << 1) | pix) & 0x07;
02715        }
02716        break;
02717 
02718       case 2:
02719 
02720        // set up the context
02721        bitmap->getPixelPtr(0, y-2, &cxPtr0);
02722        cx0 = bitmap->nextPixel(&cxPtr0);
02723        cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
02724        bitmap->getPixelPtr(0, y-1, &cxPtr1);
02725        cx1 = bitmap->nextPixel(&cxPtr1);
02726        cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
02727        cx2 = 0;
02728        bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
02729 
02730        // decode the row
02731        for (x = 0; x < w; ++x) {
02732 
02733          // build the context
02734          cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) |
02735               bitmap->nextPixel(&atPtr0);
02736 
02737          // check for a skipped pixel
02738          if (useSkip && skip->getPixel(x, y)) {
02739            pix = 0;
02740 
02741          // decode the pixel
02742          } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
02743            bitmap->setPixel(x, y);
02744          }
02745 
02746          // update the context
02747          cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07;
02748          cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x0f;
02749          cx2 = ((cx2 << 1) | pix) & 0x03;
02750        }
02751        break;
02752 
02753       case 3:
02754 
02755        // set up the context
02756        bitmap->getPixelPtr(0, y-1, &cxPtr1);
02757        cx1 = bitmap->nextPixel(&cxPtr1);
02758        cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
02759        cx2 = 0;
02760        bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
02761 
02762        // decode the row
02763        for (x = 0; x < w; ++x) {
02764 
02765          // build the context
02766          cx = (cx1 << 5) | (cx2 << 1) |
02767               bitmap->nextPixel(&atPtr0);
02768 
02769          // check for a skipped pixel
02770          if (useSkip && skip->getPixel(x, y)) {
02771            pix = 0;
02772 
02773          // decode the pixel
02774          } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
02775            bitmap->setPixel(x, y);
02776          }
02777 
02778          // update the context
02779          cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
02780          cx2 = ((cx2 << 1) | pix) & 0x0f;
02781        }
02782        break;
02783       }
02784     }
02785   }
02786 
02787   return bitmap;
02788 }
02789 
02790 void JBIG2Stream::readGenericRefinementRegionSeg(Guint segNum, GBool imm,
02791                                            GBool lossless, Guint length,
02792                                            Guint *refSegs,
02793                                            Guint nRefSegs) {
02794   JBIG2Bitmap *bitmap, *refBitmap;
02795   Guint w, h, x, y, segInfoFlags, extCombOp;
02796   Guint flags, templ, tpgrOn;
02797   int atx[2], aty[2];
02798   JBIG2Segment *seg;
02799 
02800   // region segment info field
02801   if (!readULong(&w) || !readULong(&h) ||
02802       !readULong(&x) || !readULong(&y) ||
02803       !readUByte(&segInfoFlags)) {
02804     goto eofError;
02805   }
02806   extCombOp = segInfoFlags & 7;
02807 
02808   // rest of the generic refinement region segment header
02809   if (!readUByte(&flags)) {
02810     goto eofError;
02811   }
02812   templ = flags & 1;
02813   tpgrOn = (flags >> 1) & 1;
02814 
02815   // AT flags
02816   if (!templ) {
02817     if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
02818        !readByte(&atx[1]) || !readByte(&aty[1])) {
02819       goto eofError;
02820     }
02821   }
02822 
02823   // resize the page bitmap if needed
02824   if (nRefSegs == 0 || imm) {
02825     if (pageH == 0xffffffff && y + h > curPageH) {
02826       pageBitmap->expand(y + h, pageDefPixel);
02827     }
02828   }
02829 
02830   // get referenced bitmap
02831   if (nRefSegs > 1) {
02832     error(getPos(), "Bad reference in JBIG2 generic refinement segment");
02833     return;
02834   }
02835   if (nRefSegs == 1) {
02836     seg = findSegment(refSegs[0]);
02837     if (seg->getType() != jbig2SegBitmap) {
02838       error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment");
02839       return;
02840     }
02841     refBitmap = (JBIG2Bitmap *)seg;
02842   } else {
02843     refBitmap = pageBitmap->getSlice(x, y, w, h);
02844   }
02845 
02846   // set up the arithmetic decoder
02847   resetRefinementStats(templ, NULL);
02848   arithDecoder->start();
02849 
02850   // read
02851   bitmap = readGenericRefinementRegion(w, h, templ, tpgrOn,
02852                                    refBitmap, 0, 0, atx, aty);
02853 
02854   // combine the region bitmap into the page bitmap
02855   if (imm) {
02856     pageBitmap->combine(bitmap, x, y, extCombOp);
02857     delete bitmap;
02858 
02859   // store the region bitmap
02860   } else {
02861     bitmap->setSegNum(segNum);
02862     segments->append(bitmap);
02863   }
02864 
02865   // delete the referenced bitmap
02866   if (nRefSegs == 1) {
02867     discardSegment(refSegs[0]);
02868   } else {
02869     delete refBitmap;
02870   }
02871 
02872   return;
02873 
02874  eofError:
02875   error(getPos(), "Unexpected EOF in JBIG2 stream");
02876 }
02877 
02878 JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h,
02879                                                 int templ, GBool tpgrOn,
02880                                                 JBIG2Bitmap *refBitmap,
02881                                                 int refDX, int refDY,
02882                                                 int *atx, int *aty) {
02883   JBIG2Bitmap *bitmap;
02884   GBool ltp;
02885   Guint ltpCX, cx, cx0, cx2, cx3, cx4, tpgrCX0, tpgrCX1, tpgrCX2;
02886   JBIG2BitmapPtr cxPtr0, cxPtr1, cxPtr2, cxPtr3, cxPtr4, cxPtr5, cxPtr6;
02887   JBIG2BitmapPtr tpgrCXPtr0, tpgrCXPtr1, tpgrCXPtr2;
02888   int x, y, pix;
02889 
02890   bitmap = new JBIG2Bitmap(0, w, h);
02891   bitmap->clearToZero();
02892 
02893   // set up the typical row context
02894   if (templ) {
02895     ltpCX = 0x008;
02896   } else {
02897     ltpCX = 0x0010;
02898   }
02899 
02900   ltp = 0;
02901   for (y = 0; y < h; ++y) {
02902 
02903     if (templ) {
02904 
02905       // set up the context
02906       bitmap->getPixelPtr(0, y-1, &cxPtr0);
02907       cx0 = bitmap->nextPixel(&cxPtr0);
02908       bitmap->getPixelPtr(-1, y, &cxPtr1);
02909       refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2);
02910       refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3);
02911       cx3 = refBitmap->nextPixel(&cxPtr3);
02912       cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3);
02913       refBitmap->getPixelPtr(-refDX, y+1-refDY, &cxPtr4);
02914       cx4 = refBitmap->nextPixel(&cxPtr4);
02915 
02916       // set up the typical prediction context
02917       tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
02918       if (tpgrOn) {
02919        refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0);
02920        tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0);
02921        tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
02922        tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
02923        refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1);
02924        tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1);
02925        tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
02926        tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
02927        refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2);
02928        tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2);
02929        tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
02930        tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
02931       }
02932 
02933       for (x = 0; x < w; ++x) {
02934 
02935        // update the context
02936        cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 7;
02937        cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7;
02938        cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 3;
02939 
02940        if (tpgrOn) {
02941          // update the typical predictor context
02942          tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7;
02943          tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7;
02944          tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7;
02945 
02946          // check for a "typical" pixel
02947          if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) {
02948            ltp = !ltp;
02949          }
02950          if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
02951            bitmap->clearPixel(x, y);
02952            continue;
02953          } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
02954            bitmap->setPixel(x, y);
02955            continue;
02956          }
02957        }
02958 
02959        // build the context
02960        cx = (cx0 << 7) | (bitmap->nextPixel(&cxPtr1) << 6) |
02961             (refBitmap->nextPixel(&cxPtr2) << 5) |
02962             (cx3 << 2) | cx4;
02963 
02964        // decode the pixel
02965        if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
02966          bitmap->setPixel(x, y);
02967        }
02968       }
02969 
02970     } else {
02971 
02972       // set up the context
02973       bitmap->getPixelPtr(0, y-1, &cxPtr0);
02974       cx0 = bitmap->nextPixel(&cxPtr0);
02975       bitmap->getPixelPtr(-1, y, &cxPtr1);
02976       refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2);
02977       cx2 = refBitmap->nextPixel(&cxPtr2);
02978       refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3);
02979       cx3 = refBitmap->nextPixel(&cxPtr3);
02980       cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3);
02981       refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &cxPtr4);
02982       cx4 = refBitmap->nextPixel(&cxPtr4);
02983       cx4 = (cx4 << 1) | refBitmap->nextPixel(&cxPtr4);
02984       bitmap->getPixelPtr(atx[0], y+aty[0], &cxPtr5);
02985       refBitmap->getPixelPtr(atx[1]-refDX, y+aty[1]-refDY, &cxPtr6);
02986 
02987       // set up the typical prediction context
02988       tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
02989       if (tpgrOn) {
02990        refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0);
02991        tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0);
02992        tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
02993        tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
02994        refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1);
02995        tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1);
02996        tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
02997        tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
02998        refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2);
02999        tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2);
03000        tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
03001        tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
03002       }
03003 
03004       for (x = 0; x < w; ++x) {
03005 
03006        // update the context
03007        cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 3;
03008        cx2 = ((cx2 << 1) | refBitmap->nextPixel(&cxPtr2)) & 3;
03009        cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7;
03010        cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 7;
03011 
03012        if (tpgrOn) {
03013          // update the typical predictor context
03014          tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7;
03015          tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7;
03016          tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7;
03017 
03018          // check for a "typical" pixel
03019          if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) {
03020            ltp = !ltp;
03021          }
03022          if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
03023            bitmap->clearPixel(x, y);
03024            continue;
03025          } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
03026            bitmap->setPixel(x, y);
03027            continue;
03028          }
03029        }
03030 
03031        // build the context
03032        cx = (cx0 << 11) | (bitmap->nextPixel(&cxPtr1) << 10) |
03033             (cx2 << 8) | (cx3 << 5) | (cx4 << 2) |
03034             (bitmap->nextPixel(&cxPtr5) << 1) |
03035             refBitmap->nextPixel(&cxPtr6);
03036 
03037        // decode the pixel
03038        if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
03039          bitmap->setPixel(x, y);
03040        }
03041       }
03042     }
03043   }
03044 
03045   return bitmap;
03046 }
03047 
03048 void JBIG2Stream::readPageInfoSeg(Guint length) {
03049   Guint xRes, yRes, flags, striping;
03050 
03051   if (!readULong(&pageW) || !readULong(&pageH) ||
03052       !readULong(&xRes) || !readULong(&yRes) ||
03053       !readUByte(&flags) || !readUWord(&striping)) {
03054     goto eofError;
03055   }
03056   pageDefPixel = (flags >> 2) & 1;
03057   defCombOp = (flags >> 3) & 3;
03058 
03059   // allocate the page bitmap
03060   if (pageH == 0xffffffff) {
03061     curPageH = striping & 0x7fff;
03062   } else {
03063     curPageH = pageH;
03064   }
03065   pageBitmap = new JBIG2Bitmap(0, pageW, curPageH);
03066 
03067   // default pixel value
03068   if (pageDefPixel) {
03069     pageBitmap->clearToOne();
03070   } else {
03071     pageBitmap->clearToZero();
03072   }
03073 
03074   return;
03075 
03076  eofError:
03077   error(getPos(), "Unexpected EOF in JBIG2 stream");
03078 }
03079 
03080 void JBIG2Stream::readEndOfStripeSeg(Guint length) {
03081   Guint i;
03082 
03083   // skip the segment
03084   for (i = 0; i < length; ++i) {
03085     curStr->getChar();
03086   }
03087 }
03088 
03089 void JBIG2Stream::readProfilesSeg(Guint length) {
03090   Guint i;
03091 
03092   // skip the segment
03093   for (i = 0; i < length; ++i) {
03094     curStr->getChar();
03095   }
03096 }
03097 
03098 void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) {
03099   JBIG2HuffmanTable *huffTab;
03100   Guint flags, oob, prefixBits, rangeBits;
03101   int lowVal, highVal, val;
03102   Guint huffTabSize, i;
03103 
03104   if (!readUByte(&flags) || !readLong(&lowVal) || !readLong(&highVal)) {
03105     goto eofError;
03106   }
03107   oob = flags & 1;
03108   prefixBits = ((flags >> 1) & 7) + 1;
03109   rangeBits = ((flags >> 4) & 7) + 1;
03110 
03111   huffDecoder->reset();
03112   huffTabSize = 8;
03113   huffTab = (JBIG2HuffmanTable *)
03114                 gmalloc(huffTabSize * sizeof(JBIG2HuffmanTable));
03115   i = 0;
03116   val = lowVal;
03117   while (val < highVal) {
03118     if (i == huffTabSize) {
03119       huffTabSize *= 2;
03120       huffTab = (JBIG2HuffmanTable *)
03121                    grealloc(huffTab, huffTabSize * sizeof(JBIG2HuffmanTable));
03122     }
03123     huffTab[i].val = val;
03124     huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
03125     huffTab[i].rangeLen = huffDecoder->readBits(rangeBits);
03126     val += 1 << huffTab[i].rangeLen;
03127     ++i;
03128   }
03129   if (i + oob + 3 > huffTabSize) {
03130     huffTabSize = i + oob + 3;
03131     huffTab = (JBIG2HuffmanTable *)
03132                   grealloc(huffTab, huffTabSize * sizeof(JBIG2HuffmanTable));
03133   }
03134   huffTab[i].val = lowVal - 1;
03135   huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
03136   huffTab[i].rangeLen = jbig2HuffmanLOW;
03137   ++i;
03138   huffTab[i].val = highVal;
03139   huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
03140   huffTab[i].rangeLen = 32;
03141   ++i;
03142   if (oob) {
03143     huffTab[i].val = 0;
03144     huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
03145     huffTab[i].rangeLen = jbig2HuffmanOOB;
03146     ++i;
03147   }
03148   huffTab[i].val = 0;
03149   huffTab[i].prefixLen = 0;
03150   huffTab[i].rangeLen = jbig2HuffmanEOT;
03151   huffDecoder->buildTable(huffTab, i);
03152 
03153   // create and store the new table segment
03154   segments->append(new JBIG2CodeTable(segNum, huffTab));
03155 
03156   return;
03157 
03158  eofError:
03159   error(getPos(), "Unexpected EOF in JBIG2 stream");
03160 }
03161 
03162 void JBIG2Stream::readExtensionSeg(Guint length) {
03163   Guint i;
03164 
03165   // skip the segment
03166   for (i = 0; i < length; ++i) {
03167     curStr->getChar();
03168   }
03169 }
03170 
03171 JBIG2Segment *JBIG2Stream::findSegment(Guint segNum) {
03172   JBIG2Segment *seg;
03173   int i;
03174 
03175   for (i = 0; i < globalSegments->getLength(); ++i) {
03176     seg = (JBIG2Segment *)globalSegments->get(i);
03177     if (seg->getSegNum() == segNum) {
03178       return seg;
03179     }
03180   }
03181   for (i = 0; i < segments->getLength(); ++i) {
03182     seg = (JBIG2Segment *)segments->get(i);
03183     if (seg->getSegNum() == segNum) {
03184       return seg;
03185     }
03186   }
03187   return NULL;
03188 }
03189 
03190 void JBIG2Stream::discardSegment(Guint segNum) {
03191   JBIG2Segment *seg;
03192   int i;
03193 
03194   for (i = 0; i < globalSegments->getLength(); ++i) {
03195     seg = (JBIG2Segment *)globalSegments->get(i);
03196     if (seg->getSegNum() == segNum) {
03197       globalSegments->del(i);
03198       return;
03199     }
03200   }
03201   for (i = 0; i < segments->getLength(); ++i) {
03202     seg = (JBIG2Segment *)segments->get(i);
03203     if (seg->getSegNum() == segNum) {
03204       segments->del(i);
03205       return;
03206     }
03207   }
03208 }
03209 
03210 void JBIG2Stream::resetGenericStats(Guint templ,
03211                                 JArithmeticDecoderStats *prevStats) {
03212   int size;
03213 
03214   size = contextSize[templ];
03215   if (prevStats && prevStats->getContextSize() == size) {
03216     if (genericRegionStats->getContextSize() == size) {
03217       genericRegionStats->copyFrom(prevStats);
03218     } else {
03219       delete genericRegionStats;
03220       genericRegionStats = prevStats->copy();
03221     }
03222   } else {
03223     if (genericRegionStats->getContextSize() == size) {
03224       genericRegionStats->reset();
03225     } else {
03226       delete genericRegionStats;
03227       genericRegionStats = new JArithmeticDecoderStats(1 << size);
03228     }
03229   }
03230 }
03231 
03232 void JBIG2Stream::resetRefinementStats(Guint templ,
03233                                    JArithmeticDecoderStats *prevStats) {
03234   int size;
03235 
03236   size = refContextSize[templ];
03237   if (prevStats && prevStats->getContextSize() == size) {
03238     if (refinementRegionStats->getContextSize() == size) {
03239       refinementRegionStats->copyFrom(prevStats);
03240     } else {
03241       delete refinementRegionStats;
03242       refinementRegionStats = prevStats->copy();
03243     }
03244   } else {
03245     if (refinementRegionStats->getContextSize() == size) {
03246       refinementRegionStats->reset();
03247     } else {
03248       delete refinementRegionStats;
03249       refinementRegionStats = new JArithmeticDecoderStats(1 << size);
03250     }
03251   }
03252 }
03253 
03254 void JBIG2Stream::resetIntStats(int symCodeLen) {
03255   iadhStats->reset();
03256   iadwStats->reset();
03257   iaexStats->reset();
03258   iaaiStats->reset();
03259   iadtStats->reset();
03260   iaitStats->reset();
03261   iafsStats->reset();
03262   iadsStats->reset();
03263   iardxStats->reset();
03264   iardyStats->reset();
03265   iardwStats->reset();
03266   iardhStats->reset();
03267   iariStats->reset();
03268   if (iaidStats->getContextSize() == symCodeLen + 1) {
03269     iaidStats->reset();
03270   } else {
03271     delete iaidStats;
03272     iaidStats = new JArithmeticDecoderStats(1 << (symCodeLen + 1));
03273   }
03274 }
03275 
03276 GBool JBIG2Stream::readUByte(Guint *x) {
03277   int c0;
03278 
03279   if ((c0 = curStr->getChar()) == EOF) {
03280     return gFalse;
03281   }
03282   *x = (Guint)c0;
03283   return gTrue;
03284 }
03285 
03286 GBool JBIG2Stream::readByte(int *x) {
03287  int c0;
03288 
03289   if ((c0 = curStr->getChar()) == EOF) {
03290     return gFalse;
03291   }
03292   *x = c0;
03293   if (c0 & 0x80) {
03294     *x |= -1 - 0xff;
03295   }
03296   return gTrue;
03297 }
03298 
03299 GBool JBIG2Stream::readUWord(Guint *x) {
03300   int c0, c1;
03301 
03302   if ((c0 = curStr->getChar()) == EOF ||
03303       (c1 = curStr->getChar()) == EOF) {
03304     return gFalse;
03305   }
03306   *x = (Guint)((c0 << 8) | c1);
03307   return gTrue;
03308 }
03309 
03310 GBool JBIG2Stream::readULong(Guint *x) {
03311   int c0, c1, c2, c3;
03312 
03313   if ((c0 = curStr->getChar()) == EOF ||
03314       (c1 = curStr->getChar()) == EOF ||
03315       (c2 = curStr->getChar()) == EOF ||
03316       (c3 = curStr->getChar()) == EOF) {
03317     return gFalse;
03318   }
03319   *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
03320   return gTrue;
03321 }
03322 
03323 GBool JBIG2Stream::readLong(int *x) {
03324   int c0, c1, c2, c3;
03325 
03326   if ((c0 = curStr->getChar()) == EOF ||
03327       (c1 = curStr->getChar()) == EOF ||
03328       (c2 = curStr->getChar()) == EOF ||
03329       (c3 = curStr->getChar()) == EOF) {
03330     return gFalse;
03331   }
03332   *x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
03333   if (c0 & 0x80) {
03334     *x |= -1 - (int)0xffffffff;
03335   }
03336   return gTrue;
03337 }