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 (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   // get pattern dictionary
02525   if (nRefSegs != 1) {
02526     error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
02527     return;
02528   }
02529   seg = findSegment(refSegs[0]);
02530   if (seg->getType() != jbig2SegPatternDict) {
02531     error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
02532     return;
02533   }
02534   if (gridH == 0 || gridW >= INT_MAX / gridH) {
02535     error(getPos(), "Bad size in JBIG2 halftone segment");
02536     return;
02537   }
02538   if (w == 0 || h >= INT_MAX / w) {
02539      error(getPos(), "Bad size in JBIG2 bitmap segment");
02540     return;
02541   }
02542 
02543   patternDict = (JBIG2PatternDict *)seg;
02544   bpp = 0;
02545   i = 1;
02546   while (i < patternDict->getSize()) {
02547     ++bpp;
02548     i <<= 1;
02549   }
02550   patW = patternDict->getBitmap(0)->getWidth();
02551   patH = patternDict->getBitmap(0)->getHeight();
02552 
02553   // set up the arithmetic decoder
02554   if (!mmr) {
02555     resetGenericStats(templ, NULL);
02556     arithDecoder->start();
02557   }
02558 
02559   // allocate the bitmap
02560   bitmap = new JBIG2Bitmap(segNum, w, h);
02561   if (flags & 0x80) { // HDEFPIXEL
02562     bitmap->clearToOne();
02563   } else {
02564     bitmap->clearToZero();
02565   }
02566 
02567   // compute the skip bitmap
02568   skipBitmap = NULL;
02569   if (enableSkip) {
02570     skipBitmap = new JBIG2Bitmap(0, gridW, gridH);
02571     skipBitmap->clearToZero();
02572     for (m = 0; m < gridH; ++m) {
02573       xx = gridX + m * stepY;
02574       yy = gridY + m * stepX;
02575       for (n = 0; n < gridW; ++n) {
02576     if (((xx + (int)patW) >> 8) <= 0 || (xx >> 8) >= (int)w ||
02577         ((yy + (int)patH) >> 8) <= 0 || (yy >> 8) >= (int)h) {
02578       skipBitmap->setPixel(n, m);
02579     }
02580       }
02581     }
02582   }
02583 
02584   // read the gray-scale image
02585   grayImg = (Guint *)gmalloc(gridW * gridH * sizeof(Guint));
02586   memset(grayImg, 0, gridW * gridH * sizeof(Guint));
02587   atx[0] = templ <= 1 ? 3 : 2;  aty[0] = -1;
02588   atx[1] = -3;                  aty[1] = -1;
02589   atx[2] =  2;                  aty[2] = -2;
02590   atx[3] = -2;                  aty[3] = -2;
02591   for (j = bpp - 1; j >= 0; --j) {
02592     grayBitmap = readGenericBitmap(mmr, gridW, gridH, templ, gFalse,
02593                    enableSkip, skipBitmap, atx, aty, -1);
02594     i = 0;
02595     for (m = 0; m < gridH; ++m) {
02596       for (n = 0; n < gridW; ++n) {
02597     bit = grayBitmap->getPixel(n, m) ^ (grayImg[i] & 1);
02598     grayImg[i] = (grayImg[i] << 1) | bit;
02599     ++i;
02600       }
02601     }
02602     delete grayBitmap;
02603   }
02604 
02605   // decode the image
02606   i = 0;
02607   for (m = 0; m < gridH; ++m) {
02608     xx = gridX + m * stepY;
02609     yy = gridY + m * stepX;
02610     for (n = 0; n < gridW; ++n) {
02611       if (!(enableSkip && skipBitmap->getPixel(n, m))) {
02612     patternBitmap = patternDict->getBitmap(grayImg[i]);
02613     bitmap->combine(patternBitmap, xx >> 8, yy >> 8, combOp);
02614       }
02615       xx += stepX;
02616       yy -= stepY;
02617       ++i;
02618     }
02619   }
02620 
02621   gfree(grayImg);
02622 
02623   // combine the region bitmap into the page bitmap
02624   if (imm) {
02625     if (pageH == 0xffffffff && y + h > curPageH) {
02626       pageBitmap->expand(y + h, pageDefPixel);
02627     }
02628     pageBitmap->combine(bitmap, x, y, extCombOp);
02629     delete bitmap;
02630 
02631   // store the region bitmap
02632   } else {
02633     segments->append(bitmap);
02634   }
02635 
02636   return;
02637 
02638  eofError:
02639   error(getPos(), "Unexpected EOF in JBIG2 stream");
02640 }
02641 
02642 void JBIG2Stream::readGenericRegionSeg(Guint segNum, GBool imm,
02643                         GBool /*lossless*/, Guint length) {
02644   JBIG2Bitmap *bitmap;
02645   Guint w, h, x, y, segInfoFlags, extCombOp;
02646   Guint flags, mmr, templ, tpgdOn;
02647   int atx[4], aty[4];
02648 
02649   // region segment info field
02650   if (!readULong(&w) || !readULong(&h) ||
02651       !readULong(&x) || !readULong(&y) ||
02652       !readUByte(&segInfoFlags)) {
02653     goto eofError;
02654   }
02655   extCombOp = segInfoFlags & 7;
02656 
02657   // rest of the generic region segment header
02658   if (!readUByte(&flags)) {
02659     goto eofError;
02660   }
02661   mmr = flags & 1;
02662   templ = (flags >> 1) & 3;
02663   tpgdOn = (flags >> 3) & 1;
02664 
02665   // AT flags
02666   if (!mmr) {
02667     if (templ == 0) {
02668       if (!readByte(&atx[0]) ||
02669       !readByte(&aty[0]) ||
02670       !readByte(&atx[1]) ||
02671       !readByte(&aty[1]) ||
02672       !readByte(&atx[2]) ||
02673       !readByte(&aty[2]) ||
02674       !readByte(&atx[3]) ||
02675       !readByte(&aty[3])) {
02676     goto eofError;
02677       }
02678     } else {
02679       if (!readByte(&atx[0]) ||
02680       !readByte(&aty[0])) {
02681     goto eofError;
02682       }
02683     }
02684   }
02685 
02686   // set up the arithmetic decoder
02687   if (!mmr) {
02688     resetGenericStats(templ, NULL);
02689     arithDecoder->start();
02690   }
02691 
02692   // read the bitmap
02693   bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse,
02694                  NULL, atx, aty, mmr ? 0 : length - 18);
02695 
02696   // combine the region bitmap into the page bitmap
02697   if (imm) {
02698     if (pageH == 0xffffffff && y + h > curPageH) {
02699       pageBitmap->expand(y + h, pageDefPixel);
02700     }
02701     pageBitmap->combine(bitmap, x, y, extCombOp);
02702     delete bitmap;
02703 
02704   // store the region bitmap
02705   } else {
02706     bitmap->setSegNum(segNum);
02707     segments->append(bitmap);
02708   }
02709 
02710   return;
02711 
02712  eofError:
02713   error(getPos(), "Unexpected EOF in JBIG2 stream");
02714 }
02715 
02716 JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
02717                         int templ, GBool tpgdOn,
02718                         GBool useSkip, JBIG2Bitmap *skip,
02719                         int *atx, int *aty,
02720                         int mmrDataLength) {
02721   JBIG2Bitmap *bitmap;
02722   GBool ltp;
02723   Guint ltpCX, cx, cx0, cx1, cx2;
02724   int *refLine, *codingLine;
02725   int code1, code2, code3;
02726   int x, y, a0, pix, i, refI, codingI;
02727 
02728   bitmap = new JBIG2Bitmap(0, w, h);
02729   bitmap->clearToZero();
02730 
02731   //----- MMR decode
02732 
02733   if (mmr) {
02734 
02735     mmrDecoder->reset();
02736     refLine = (int *)gmalloc((w + 2) * sizeof(int));
02737     codingLine = (int *)gmalloc((w + 2) * sizeof(int));
02738     codingLine[0] = codingLine[1] = w;
02739 
02740     for (y = 0; y < h; ++y) {
02741 
02742       // copy coding line to ref line
02743       for (i = 0; codingLine[i] < w; ++i) {
02744     refLine[i] = codingLine[i];
02745       }
02746       refLine[i] = refLine[i + 1] = w;
02747 
02748       // decode a line
02749       refI = 0;     // b1 = refLine[refI]
02750       codingI = 0;  // a1 = codingLine[codingI]
02751       a0 = 0;
02752       do {
02753     code1 = mmrDecoder->get2DCode();
02754     switch (code1) {
02755     case twoDimPass:
02756       if (refLine[refI] < w) {
02757         a0 = refLine[refI + 1];
02758         refI += 2;
02759       }
02760       break;
02761     case twoDimHoriz:
02762       if (codingI & 1) {
02763         code1 = 0;
02764         do {
02765           code1 += code3 = mmrDecoder->getBlackCode();
02766         } while (code3 >= 64);
02767         code2 = 0;
02768         do {
02769           code2 += code3 = mmrDecoder->getWhiteCode();
02770         } while (code3 >= 64);
02771       } else {
02772         code1 = 0;
02773         do {
02774           code1 += code3 = mmrDecoder->getWhiteCode();
02775         } while (code3 >= 64);
02776         code2 = 0;
02777         do {
02778           code2 += code3 = mmrDecoder->getBlackCode();
02779         } while (code3 >= 64);
02780       }
02781       a0 = codingLine[codingI++] = a0 + code1;
02782       a0 = codingLine[codingI++] = a0 + code2;
02783       while (refLine[refI] <= a0 && refLine[refI] < w) {
02784         refI += 2;
02785       }
02786       break;
02787     case twoDimVert0:
02788       a0 = codingLine[codingI++] = refLine[refI];
02789       if (refLine[refI] < w) {
02790         ++refI;
02791       }
02792       break;
02793     case twoDimVertR1:
02794       a0 = codingLine[codingI++] = refLine[refI] + 1;
02795       if (refLine[refI] < w) {
02796         ++refI;
02797         while (refLine[refI] <= a0 && refLine[refI] < w) {
02798           refI += 2;
02799         }
02800       }
02801       break;
02802     case twoDimVertR2:
02803       a0 = codingLine[codingI++] = refLine[refI] + 2;
02804       if (refLine[refI] < w) {
02805         ++refI;
02806         while (refLine[refI] <= a0 && refLine[refI] < w) {
02807           refI += 2;
02808         }
02809       }
02810       break;
02811     case twoDimVertR3:
02812       a0 = codingLine[codingI++] = refLine[refI] + 3;
02813       if (refLine[refI] < w) {
02814         ++refI;
02815         while (refLine[refI] <= a0 && refLine[refI] < w) {
02816           refI += 2;
02817         }
02818       }
02819       break;
02820     case twoDimVertL1:
02821       a0 = codingLine[codingI++] = refLine[refI] - 1;
02822       if (refI > 0) {
02823         --refI;
02824       } else {
02825         ++refI;
02826       }
02827       while (refLine[refI] <= a0 && refLine[refI] < w) {
02828         refI += 2;
02829       }
02830       break;
02831     case twoDimVertL2:
02832       a0 = codingLine[codingI++] = refLine[refI] - 2;
02833       if (refI > 0) {
02834         --refI;
02835       } else {
02836         ++refI;
02837       }
02838       while (refLine[refI] <= a0 && refLine[refI] < w) {
02839         refI += 2;
02840       }
02841       break;
02842     case twoDimVertL3:
02843       a0 = codingLine[codingI++] = refLine[refI] - 3;
02844       if (refI > 0) {
02845         --refI;
02846       } else {
02847         ++refI;
02848       }
02849       while (refLine[refI] <= a0 && refLine[refI] < w) {
02850         refI += 2;
02851       }
02852       break;
02853     default:
02854       error(getPos(), "Illegal code in JBIG2 MMR bitmap data");
02855       break;
02856     }
02857       } while (a0 < w);
02858       codingLine[codingI++] = w;
02859 
02860       // convert the run lengths to a bitmap line
02861       i = 0;
02862       while (codingLine[i] < w) {
02863     for (x = codingLine[i]; x < codingLine[i+1]; ++x) {
02864       bitmap->setPixel(x, y);
02865     }
02866     i += 2;
02867       }
02868     }
02869 
02870     if (mmrDataLength >= 0) {
02871       mmrDecoder->skipTo(mmrDataLength);
02872     } else {
02873       if (mmrDecoder->get24Bits() != 0x001001) {
02874     error(getPos(), "Missing EOFB in JBIG2 MMR bitmap data");
02875       }
02876     }
02877 
02878     gfree(refLine);
02879     gfree(codingLine);
02880 
02881   //----- arithmetic decode
02882 
02883   } else {
02884     // set up the typical row context
02885     ltpCX = 0; // make gcc happy
02886     if (tpgdOn) {
02887       switch (templ) {
02888       case 0:
02889     ltpCX = 0x3953; // 001 11001 0101 0011
02890     break;
02891       case 1:
02892     ltpCX = 0x079a; // 0011 11001 101 0
02893     break;
02894       case 2:
02895     ltpCX = 0x0e3; // 001 1100 01 1
02896     break;
02897       case 3:
02898     ltpCX = 0x18a; // 01100 0101 1
02899     break;
02900       }
02901     }
02902 
02903     ltp = 0;
02904     cx = cx0 = cx1 = cx2 = 0; // make gcc happy
02905     for (y = 0; y < h; ++y) {
02906 
02907       // check for a "typical" (duplicate) row
02908       if (tpgdOn) {
02909     if (arithDecoder->decodeBit(ltpCX, genericRegionStats)) {
02910       ltp = !ltp;
02911     }
02912     if (ltp) {
02913       bitmap->duplicateRow(y, y-1);
02914       continue;
02915     }
02916       }
02917 
02918       // set up the context
02919       switch (templ) {
02920       case 0:
02921     cx0 = (bitmap->getPixel(0, y-2) << 1) |
02922           bitmap->getPixel(1, y-2);
02923     cx1 = (bitmap->getPixel(0, y-1) << 2) |
02924           (bitmap->getPixel(1, y-1) << 1) |
02925           bitmap->getPixel(2, y-1);
02926     cx2 = 0;
02927     break;
02928       case 1:
02929     cx0 = (bitmap->getPixel(0, y-2) << 2) |
02930           (bitmap->getPixel(1, y-2) << 1) |
02931           bitmap->getPixel(2, 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 2:
02938     cx0 = (bitmap->getPixel(0, y-2) << 1) |
02939           bitmap->getPixel(1, y-2);
02940     cx1 = (bitmap->getPixel(0, y-1) << 1) |
02941           bitmap->getPixel(1, y-1);
02942     cx2 = 0;
02943     break;
02944       case 3:
02945     cx1 = (bitmap->getPixel(0, y-1) << 1) |
02946           bitmap->getPixel(1, y-1);
02947     cx2 = 0;
02948     break;
02949       }
02950 
02951       // decode the row
02952       for (x = 0; x < w; ++x) {
02953 
02954     // check for a skipped pixel
02955     if (useSkip && skip->getPixel(x, y)) {
02956       pix = 0;
02957 
02958     } else {
02959 
02960       // build the context
02961       switch (templ) {
02962       case 0:
02963         cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) |
02964              (bitmap->getPixel(x + atx[0], y + aty[0]) << 3) |
02965              (bitmap->getPixel(x + atx[1], y + aty[1]) << 2) |
02966              (bitmap->getPixel(x + atx[2], y + aty[2]) << 1) |
02967              bitmap->getPixel(x + atx[3], y + aty[3]);
02968         break;
02969       case 1:
02970         cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) |
02971              bitmap->getPixel(x + atx[0], y + aty[0]);
02972         break;
02973       case 2:
02974         cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) |
02975              bitmap->getPixel(x + atx[0], y + aty[0]);
02976         break;
02977       case 3:
02978         cx = (cx1 << 5) | (cx2 << 1) |
02979              bitmap->getPixel(x + atx[0], y + aty[0]);
02980         break;
02981       }
02982 
02983       // decode the pixel
02984       if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
02985         bitmap->setPixel(x, y);
02986       }
02987     }
02988 
02989     // update the context
02990     switch (templ) {
02991       case 0:
02992         cx0 = ((cx0 << 1) | bitmap->getPixel(x+2, y-2)) & 0x07;
02993         cx1 = ((cx1 << 1) | bitmap->getPixel(x+3, y-1)) & 0x1f;
02994         cx2 = ((cx2 << 1) | pix) & 0x0f;
02995         break;
02996       case 1:
02997         cx0 = ((cx0 << 1) | bitmap->getPixel(x+3, y-2)) & 0x0f;
02998         cx1 = ((cx1 << 1) | bitmap->getPixel(x+3, y-1)) & 0x1f;
02999         cx2 = ((cx2 << 1) | pix) & 0x07;
03000         break;
03001       case 2:
03002         cx0 = ((cx0 << 1) | bitmap->getPixel(x+2, y-2)) & 0x07;
03003         cx1 = ((cx1 << 1) | bitmap->getPixel(x+2, y-1)) & 0x0f;
03004         cx2 = ((cx2 << 1) | pix) & 0x03;
03005         break;
03006       case 3:
03007         cx1 = ((cx1 << 1) | bitmap->getPixel(x+2, y-1)) & 0x1f;
03008         cx2 = ((cx2 << 1) | pix) & 0x0f;
03009         break;
03010     }
03011       }
03012     }
03013   }
03014 
03015   return bitmap;
03016 }
03017 
03018 void JBIG2Stream::readGenericRefinementRegionSeg(Guint segNum, GBool imm,
03019                          GBool /*lossless*/, Guint /*length*/,
03020                          Guint *refSegs,
03021                          Guint nRefSegs) {
03022   JBIG2Bitmap *bitmap, *refBitmap;
03023   Guint w, h, x, y, segInfoFlags, extCombOp;
03024   Guint flags, templ, tpgrOn;
03025   int atx[2], aty[2];
03026   JBIG2Segment *seg;
03027 
03028   // region segment info field
03029   if (!readULong(&w) || !readULong(&h) ||
03030       !readULong(&x) || !readULong(&y) ||
03031       !readUByte(&segInfoFlags)) {
03032     goto eofError;
03033   }
03034   extCombOp = segInfoFlags & 7;
03035 
03036   // rest of the generic refinement region segment header
03037   if (!readUByte(&flags)) {
03038     goto eofError;
03039   }
03040   templ = flags & 1;
03041   tpgrOn = (flags >> 1) & 1;
03042 
03043   // AT flags
03044   if (!templ) {
03045     if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
03046     !readByte(&atx[1]) || !readByte(&aty[1])) {
03047       goto eofError;
03048     }
03049   }
03050 
03051   // resize the page bitmap if needed
03052   if (nRefSegs == 0 || imm) {
03053     if (pageH == 0xffffffff && y + h > curPageH) {
03054       pageBitmap->expand(y + h, pageDefPixel);
03055     }
03056   }
03057 
03058   // get referenced bitmap
03059   if (nRefSegs > 1) {
03060     error(getPos(), "Bad reference in JBIG2 generic refinement segment");
03061     return;
03062   }
03063   if (nRefSegs == 1) {
03064     seg = findSegment(refSegs[0]);
03065     if (seg->getType() != jbig2SegBitmap) {
03066       error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment");
03067       return;
03068     }
03069     refBitmap = (JBIG2Bitmap *)seg;
03070   } else {
03071     refBitmap = pageBitmap->getSlice(x, y, w, h);
03072   }
03073 
03074   // set up the arithmetic decoder
03075   resetRefinementStats(templ, NULL);
03076   arithDecoder->start();
03077 
03078   // read
03079   bitmap = readGenericRefinementRegion(w, h, templ, tpgrOn,
03080                        refBitmap, 0, 0, atx, aty);
03081 
03082   // combine the region bitmap into the page bitmap
03083   if (imm) {
03084     pageBitmap->combine(bitmap, x, y, extCombOp);
03085     delete bitmap;
03086 
03087   // store the region bitmap
03088   } else {
03089     bitmap->setSegNum(segNum);
03090     segments->append(bitmap);
03091   }
03092 
03093   // delete the referenced bitmap
03094   if (nRefSegs == 1) {
03095     discardSegment(refSegs[0]);
03096   } else {
03097     delete refBitmap;
03098   }
03099 
03100   return;
03101 
03102  eofError:
03103   error(getPos(), "Unexpected EOF in JBIG2 stream");
03104 }
03105 
03106 JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h,
03107                               int templ, GBool tpgrOn,
03108                               JBIG2Bitmap *refBitmap,
03109                               int refDX, int refDY,
03110                               int *atx, int *aty) {
03111   JBIG2Bitmap *bitmap;
03112   GBool ltp;
03113   Guint ltpCX, cx, cx0, cx2, cx3, cx4, tpgrCX0, tpgrCX1, tpgrCX2;
03114   int x, y, pix;
03115 
03116   if (w < 0 || h <= 0 || w >= INT_MAX / h) {
03117     error(-1, "invalid width/height");
03118     return NULL;
03119   }
03120 
03121   bitmap = new JBIG2Bitmap(0, w, h);
03122   bitmap->clearToZero();
03123 
03124   // set up the typical row context
03125   if (templ) {
03126     ltpCX = 0x008;
03127   } else {
03128     ltpCX = 0x0010;
03129   }
03130 
03131   ltp = 0;
03132   for (y = 0; y < h; ++y) {
03133 
03134     // set up the context
03135     if (templ) {
03136       cx0 = bitmap->getPixel(0, y-1);
03137       cx2 = 0; // unused
03138       cx3 = (refBitmap->getPixel(-1-refDX, y-refDY) << 1) |
03139         refBitmap->getPixel(-refDX, y-refDY);
03140       cx4 = refBitmap->getPixel(-refDX, y+1-refDY);
03141     } else {
03142       cx0 = bitmap->getPixel(0, y-1);
03143       cx2 = refBitmap->getPixel(-refDX, y-1-refDY);
03144       cx3 = (refBitmap->getPixel(-1-refDX, y-refDY) << 1) |
03145         refBitmap->getPixel(-refDX, y-refDY);
03146       cx4 = (refBitmap->getPixel(-1-refDX, y+1-refDY) << 1) |
03147         refBitmap->getPixel(-refDX, y+1-refDY);
03148     }
03149 
03150     // set up the typical prediction context
03151     tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
03152     if (tpgrOn) {
03153       tpgrCX0 = (refBitmap->getPixel(-1-refDX, y-1-refDY) << 2) |
03154             (refBitmap->getPixel(-refDX, y-1-refDY) << 1) |
03155             refBitmap->getPixel(1-refDX, y-1-refDY);
03156       tpgrCX1 = (refBitmap->getPixel(-1-refDX, y-refDY) << 2) |
03157             (refBitmap->getPixel(-refDX, y-refDY) << 1) |
03158             refBitmap->getPixel(1-refDX, y-refDY);
03159       tpgrCX2 = (refBitmap->getPixel(-1-refDX, y+1-refDY) << 2) |
03160             (refBitmap->getPixel(-refDX, y+1-refDY) << 1) |
03161             refBitmap->getPixel(1-refDX, y+1-refDY);
03162     }
03163 
03164     for (x = 0; x < w; ++x) {
03165 
03166       // update the context
03167       if (templ) {
03168     cx0 = ((cx0 << 1) | bitmap->getPixel(x+1, y-1)) & 7;
03169     cx3 = ((cx3 << 1) | refBitmap->getPixel(x+1-refDX, y-refDY)) & 7;
03170     cx4 = ((cx4 << 1) | refBitmap->getPixel(x+1-refDX, y+1-refDY)) & 3;
03171       } else {
03172     cx0 = ((cx0 << 1) | bitmap->getPixel(x+1, y-1)) & 3;
03173     cx2 = ((cx2 << 1) | refBitmap->getPixel(x+1-refDX, y-1-refDY)) & 3;
03174     cx3 = ((cx3 << 1) | refBitmap->getPixel(x+1-refDX, y-refDY)) & 7;
03175     cx4 = ((cx4 << 1) | refBitmap->getPixel(x+1-refDX, y+1-refDY)) & 7;
03176       }
03177 
03178       if (tpgrOn) {
03179     // update the typical predictor context
03180     tpgrCX0 = ((tpgrCX0 << 1) |
03181            refBitmap->getPixel(x+1-refDX, y-1-refDY)) & 7;
03182     tpgrCX1 = ((tpgrCX1 << 1) |
03183            refBitmap->getPixel(x+1-refDX, y-refDY)) & 7;
03184     tpgrCX2 = ((tpgrCX2 << 1) |
03185            refBitmap->getPixel(x+1-refDX, y+1-refDY)) & 7;
03186 
03187     // check for a "typical" pixel
03188     if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) {
03189       ltp = !ltp;
03190     }
03191     if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
03192       bitmap->clearPixel(x, y);
03193       continue;
03194     } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
03195       bitmap->setPixel(x, y);
03196       continue;
03197     }
03198       }
03199 
03200       // build the context
03201       if (templ) {
03202     cx = (cx0 << 7) | (bitmap->getPixel(x-1, y) << 6) |
03203          (refBitmap->getPixel(x-refDX, y-1-refDY) << 5) |
03204          (cx3 << 2) | cx4;
03205       } else {
03206     cx = (cx0 << 11) | (bitmap->getPixel(x-1, y) << 10) |
03207          (cx2 << 8) | (cx3 << 5) | (cx4 << 2) |
03208          (bitmap->getPixel(x+atx[0], y+aty[0]) << 1) |
03209          refBitmap->getPixel(x+atx[1]-refDX, y+aty[1]-refDY);
03210       }
03211 
03212       // decode the pixel
03213       if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
03214     bitmap->setPixel(x, y);
03215       }
03216     }
03217   }
03218 
03219   return bitmap;
03220 }
03221 
03222 void JBIG2Stream::readPageInfoSeg(Guint /*length*/) {
03223   Guint xRes, yRes, flags, striping;
03224 
03225   if (!readULong(&pageW) || !readULong(&pageH) ||
03226       !readULong(&xRes) || !readULong(&yRes) ||
03227       !readUByte(&flags) || !readUWord(&striping)) {
03228     goto eofError;
03229   }
03230   pageDefPixel = (flags >> 2) & 1;
03231   defCombOp = (flags >> 3) & 3;
03232 
03233   // allocate the page bitmap
03234   if (pageH == 0xffffffff) {
03235     curPageH = striping & 0x7fff;
03236   } else {
03237     curPageH = pageH;
03238   }
03239   pageBitmap = new JBIG2Bitmap(0, pageW, curPageH);
03240 
03241   // default pixel value
03242   if (pageDefPixel) {
03243     pageBitmap->clearToOne();
03244   } else {
03245     pageBitmap->clearToZero();
03246   }
03247 
03248   return;
03249 
03250  eofError:
03251   error(getPos(), "Unexpected EOF in JBIG2 stream");
03252 }
03253 
03254 void JBIG2Stream::readEndOfStripeSeg(Guint length) {
03255   Guint i;
03256 
03257   // skip the segment
03258   for (i = 0; i < length; ++i) {
03259     curStr->getChar();
03260   }
03261 }
03262 
03263 void JBIG2Stream::readProfilesSeg(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::readCodeTableSeg(Guint segNum, Guint /*length*/) {
03273   JBIG2HuffmanTable *huffTab;
03274   Guint flags, oob, prefixBits, rangeBits;
03275   int lowVal, highVal, val;
03276   Guint huffTabSize, i;
03277 
03278   if (!readUByte(&flags) || !readLong(&lowVal) || !readLong(&highVal)) {
03279     goto eofError;
03280   }
03281   oob = flags & 1;
03282   prefixBits = (flags >> 1) & 7;
03283   rangeBits = (flags >> 4) & 7;
03284 
03285   huffDecoder->reset();
03286   huffTabSize = 8;
03287   huffTab = (JBIG2HuffmanTable *)
03288                 gmalloc(huffTabSize * sizeof(JBIG2HuffmanTable));
03289   i = 0;
03290   val = lowVal;
03291   while (val < highVal) {
03292     if (i == huffTabSize) {
03293       huffTabSize *= 2;
03294       huffTab = (JBIG2HuffmanTable *)
03295                 grealloc(huffTab, huffTabSize * sizeof(JBIG2HuffmanTable));
03296     }
03297     huffTab[i].val = val;
03298     huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
03299     huffTab[i].rangeLen = huffDecoder->readBits(rangeBits);
03300     val += 1 << huffTab[i].rangeLen;
03301     ++i;
03302   }
03303   if (i + oob + 3 > huffTabSize) {
03304     huffTabSize = i + oob + 3;
03305     huffTab = (JBIG2HuffmanTable *)
03306                   grealloc(huffTab, huffTabSize * sizeof(JBIG2HuffmanTable));
03307   }
03308   huffTab[i].val = lowVal - 1;
03309   huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
03310   huffTab[i].rangeLen = jbig2HuffmanLOW;
03311   ++i;
03312   huffTab[i].val = highVal;
03313   huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
03314   huffTab[i].rangeLen = 32;
03315   ++i;
03316   if (oob) {
03317     huffTab[i].val = 0;
03318     huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
03319     huffTab[i].rangeLen = jbig2HuffmanOOB;
03320     ++i;
03321   }
03322   huffTab[i].val = 0;
03323   huffTab[i].prefixLen = 0;
03324   huffTab[i].rangeLen = jbig2HuffmanEOT;
03325   ++i;
03326   huffDecoder->buildTable(huffTab, i);
03327 
03328   // create and store the new table segment
03329   segments->append(new JBIG2CodeTable(segNum, huffTab));
03330 
03331   return;
03332 
03333  eofError:
03334   error(getPos(), "Unexpected EOF in JBIG2 stream");
03335 }
03336 
03337 void JBIG2Stream::readExtensionSeg(Guint length) {
03338   Guint i;
03339 
03340   // skip the segment
03341   for (i = 0; i < length; ++i) {
03342     curStr->getChar();
03343   }
03344 }
03345 
03346 JBIG2Segment *JBIG2Stream::findSegment(Guint segNum) {
03347   JBIG2Segment *seg;
03348   int i;
03349 
03350   for (i = 0; i < globalSegments->getLength(); ++i) {
03351     seg = (JBIG2Segment *)globalSegments->get(i);
03352     if (seg->getSegNum() == segNum) {
03353       return seg;
03354     }
03355   }
03356   for (i = 0; i < segments->getLength(); ++i) {
03357     seg = (JBIG2Segment *)segments->get(i);
03358     if (seg->getSegNum() == segNum) {
03359       return seg;
03360     }
03361   }
03362   return NULL;
03363 }
03364 
03365 void JBIG2Stream::discardSegment(Guint segNum) {
03366   JBIG2Segment *seg;
03367   int i;
03368 
03369   for (i = 0; i < globalSegments->getLength(); ++i) {
03370     seg = (JBIG2Segment *)globalSegments->get(i);
03371     if (seg->getSegNum() == segNum) {
03372       globalSegments->del(i);
03373       return;
03374     }
03375   }
03376   for (i = 0; i < segments->getLength(); ++i) {
03377     seg = (JBIG2Segment *)segments->get(i);
03378     if (seg->getSegNum() == segNum) {
03379       globalSegments->del(i);
03380       return;
03381     }
03382   }
03383 }
03384 
03385 void JBIG2Stream::resetGenericStats(Guint templ,
03386                     JBIG2ArithmeticDecoderStats *prevStats) {
03387   int size;
03388 
03389   size = contextSize[templ];
03390   if (prevStats && prevStats->getContextSize() == size) {
03391     if (genericRegionStats->getContextSize() == size) {
03392       genericRegionStats->copyFrom(prevStats);
03393     } else {
03394       delete genericRegionStats;
03395       genericRegionStats = prevStats->copy();
03396     }
03397   } else {
03398     if (genericRegionStats->getContextSize() == size) {
03399       genericRegionStats->reset();
03400     } else {
03401       delete genericRegionStats;
03402       genericRegionStats = new JBIG2ArithmeticDecoderStats(size);
03403     }
03404   }
03405 }
03406 
03407 void JBIG2Stream::resetRefinementStats(
03408               Guint templ,
03409               JBIG2ArithmeticDecoderStats *prevStats) {
03410   int size;
03411 
03412   size = refContextSize[templ];
03413   if (prevStats && prevStats->getContextSize() == size) {
03414     if (refinementRegionStats->getContextSize() == size) {
03415       refinementRegionStats->copyFrom(prevStats);
03416     } else {
03417       delete refinementRegionStats;
03418       refinementRegionStats = prevStats->copy();
03419     }
03420   } else {
03421     if (refinementRegionStats->getContextSize() == size) {
03422       refinementRegionStats->reset();
03423     } else {
03424       delete refinementRegionStats;
03425       refinementRegionStats = new JBIG2ArithmeticDecoderStats(size);
03426     }
03427   }
03428 }
03429 
03430 void JBIG2Stream::resetIntStats(int symCodeLen) {
03431   iadhStats->reset();
03432   iadwStats->reset();
03433   iaexStats->reset();
03434   iaaiStats->reset();
03435   iadtStats->reset();
03436   iaitStats->reset();
03437   iafsStats->reset();
03438   iadsStats->reset();
03439   iardxStats->reset();
03440   iardyStats->reset();
03441   iardwStats->reset();
03442   iardhStats->reset();
03443   iariStats->reset();
03444   if (iaidStats->getContextSize() == symCodeLen + 1) {
03445     iaidStats->reset();
03446   } else {
03447     delete iaidStats;
03448     iaidStats = new JBIG2ArithmeticDecoderStats(symCodeLen + 1);
03449   }
03450 }
03451 
03452 GBool JBIG2Stream::readUByte(Guint *x) {
03453   int c0;
03454 
03455   if ((c0 = curStr->getChar()) == EOF) {
03456     return gFalse;
03457   }
03458   *x = (Guint)c0;
03459   return gTrue;
03460 }
03461 
03462 GBool JBIG2Stream::readByte(int *x) {
03463  int c0;
03464 
03465   if ((c0 = curStr->getChar()) == EOF) {
03466     return gFalse;
03467   }
03468   *x = c0;
03469   if (c0 & 0x80) {
03470     *x |= -1 - 0xff;
03471   }
03472   return gTrue;
03473 }
03474 
03475 GBool JBIG2Stream::readUWord(Guint *x) {
03476   int c0, c1;
03477 
03478   if ((c0 = curStr->getChar()) == EOF ||
03479       (c1 = curStr->getChar()) == EOF) {
03480     return gFalse;
03481   }
03482   *x = (Guint)((c0 << 8) | c1);
03483   return gTrue;
03484 }
03485 
03486 GBool JBIG2Stream::readULong(Guint *x) {
03487   int c0, c1, c2, c3;
03488 
03489   if ((c0 = curStr->getChar()) == EOF ||
03490       (c1 = curStr->getChar()) == EOF ||
03491       (c2 = curStr->getChar()) == EOF ||
03492       (c3 = curStr->getChar()) == EOF) {
03493     return gFalse;
03494   }
03495   *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
03496   return gTrue;
03497 }
03498 
03499 GBool JBIG2Stream::readLong(int *x) {
03500   int c0, c1, c2, c3;
03501 
03502   if ((c0 = curStr->getChar()) == EOF ||
03503       (c1 = curStr->getChar()) == EOF ||
03504       (c2 = curStr->getChar()) == EOF ||
03505       (c3 = curStr->getChar()) == EOF) {
03506     return gFalse;
03507   }
03508   *x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
03509   if (c0 & 0x80) {
03510     *x |= -1 - 0xffffffff;
03511   }
03512   return gTrue;
03513 }
KDE Home | KDE Accessibility Home | Description of Access Keys