filters

JBIG2Stream.cc

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