filters

Stream.cc

00001 //========================================================================
00002 //
00003 // Stream.cc
00004 //
00005 // Copyright 1996-2002 Glyph & Cog, LLC
00006 //
00007 //========================================================================
00008 
00009 #include <aconf.h>
00010 
00011 #ifdef USE_GCC_PRAGMAS
00012 #pragma implementation
00013 #endif
00014 
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <stddef.h>
00018 #include <limits.h>
00019 #ifndef WIN32
00020 #include <unistd.h>
00021 #endif
00022 #include <string.h>
00023 #include <ctype.h>
00024 #include "gmem.h"
00025 #include "gfile.h"
00026 #include "xpdf_config.h"
00027 #include "Error.h"
00028 #include "Object.h"
00029 #ifndef NO_DECRYPTION
00030 #include "Decrypt.h"
00031 #endif
00032 #include "Stream.h"
00033 #include "JBIG2Stream.h"
00034 #include "Stream-CCITT.h"
00035 
00036 #ifdef __DJGPP__
00037 static GBool setDJSYSFLAGS = gFalse;
00038 #endif
00039 
00040 #ifdef VMS
00041 #ifdef __GNUC__
00042 #define SEEK_SET 0
00043 #define SEEK_CUR 1
00044 #define SEEK_END 2
00045 #endif
00046 #endif
00047 
00048 //------------------------------------------------------------------------
00049 // Stream (base class)
00050 //------------------------------------------------------------------------
00051 
00052 Stream::Stream() {
00053   ref = 1;
00054 }
00055 
00056 Stream::~Stream() {
00057 }
00058 
00059 void Stream::close() {
00060 }
00061 
00062 int Stream::getRawChar() {
00063   error(-1, "Internal: called getRawChar() on non-predictor stream");
00064   return EOF;
00065 }
00066 
00067 char *Stream::getLine(char *buf, int size) {
00068   int i;
00069   int c;
00070 
00071   if (lookChar() == EOF)
00072     return NULL;
00073   for (i = 0; i < size - 1; ++i) {
00074     c = getChar();
00075     if (c == EOF || c == '\n')
00076       break;
00077     if (c == '\r') {
00078       if ((c = lookChar()) == '\n')
00079     getChar();
00080       break;
00081     }
00082     buf[i] = c;
00083   }
00084   buf[i] = '\0';
00085   return buf;
00086 }
00087 
00088 GString *Stream::getPSFilter(const char */*indent*/) {
00089   return new GString();
00090 }
00091 
00092 Stream *Stream::addFilters(Object *dict) {
00093   Object obj, obj2;
00094   Object params, params2;
00095   Stream *str;
00096   int i;
00097 
00098   str = this;
00099   dict->dictLookup("Filter", &obj);
00100   if (obj.isNull()) {
00101     obj.free();
00102     dict->dictLookup("F", &obj);
00103   }
00104   dict->dictLookup("DecodeParms", &params);
00105   if (params.isNull()) {
00106     params.free();
00107     dict->dictLookup("DP", &params);
00108   }
00109   if (obj.isName()) {
00110     str = makeFilter(obj.getName(), str, &params);
00111   } else if (obj.isArray()) {
00112     for (i = 0; i < obj.arrayGetLength(); ++i) {
00113       obj.arrayGet(i, &obj2);
00114       if (params.isArray())
00115     params.arrayGet(i, &params2);
00116       else
00117     params2.initNull();
00118       if (obj2.isName()) {
00119     str = makeFilter(obj2.getName(), str, &params2);
00120       } else {
00121     error(getPos(), "Bad filter name");
00122     str = new EOFStream(str);
00123       }
00124       obj2.free();
00125       params2.free();
00126     }
00127   } else if (!obj.isNull()) {
00128     error(getPos(), "Bad 'Filter' attribute in stream");
00129   }
00130   obj.free();
00131   params.free();
00132 
00133   return str;
00134 }
00135 
00136 Stream *Stream::makeFilter(const char *name, Stream *str, Object *params) {
00137   int pred;         // parameters
00138   int colors;
00139   int bits;
00140   int early;
00141   int encoding;
00142   GBool endOfLine, byteAlign, endOfBlock, black;
00143   int columns, rows;
00144   Object globals, obj;
00145 
00146   if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
00147     str = new ASCIIHexStream(str);
00148   } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
00149     str = new ASCII85Stream(str);
00150   } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
00151     pred = 1;
00152     columns = 1;
00153     colors = 1;
00154     bits = 8;
00155     early = 1;
00156     if (params->isDict()) {
00157       params->dictLookup("Predictor", &obj);
00158       if (obj.isInt())
00159     pred = obj.getInt();
00160       obj.free();
00161       params->dictLookup("Columns", &obj);
00162       if (obj.isInt())
00163     columns = obj.getInt();
00164       obj.free();
00165       params->dictLookup("Colors", &obj);
00166       if (obj.isInt())
00167     colors = obj.getInt();
00168       obj.free();
00169       params->dictLookup("BitsPerComponent", &obj);
00170       if (obj.isInt())
00171     bits = obj.getInt();
00172       obj.free();
00173       params->dictLookup("EarlyChange", &obj);
00174       if (obj.isInt())
00175     early = obj.getInt();
00176       obj.free();
00177     }
00178     str = new LZWStream(str, pred, columns, colors, bits, early);
00179   } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
00180     str = new RunLengthStream(str);
00181   } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
00182     encoding = 0;
00183     endOfLine = gFalse;
00184     byteAlign = gFalse;
00185     columns = 1728;
00186     rows = 0;
00187     endOfBlock = gTrue;
00188     black = gFalse;
00189     if (params->isDict()) {
00190       params->dictLookup("K", &obj);
00191       if (obj.isInt()) {
00192     encoding = obj.getInt();
00193       }
00194       obj.free();
00195       params->dictLookup("EndOfLine", &obj);
00196       if (obj.isBool()) {
00197     endOfLine = obj.getBool();
00198       }
00199       obj.free();
00200       params->dictLookup("EncodedByteAlign", &obj);
00201       if (obj.isBool()) {
00202     byteAlign = obj.getBool();
00203       }
00204       obj.free();
00205       params->dictLookup("Columns", &obj);
00206       if (obj.isInt()) {
00207     columns = obj.getInt();
00208       }
00209       obj.free();
00210       params->dictLookup("Rows", &obj);
00211       if (obj.isInt()) {
00212     rows = obj.getInt();
00213       }
00214       obj.free();
00215       params->dictLookup("EndOfBlock", &obj);
00216       if (obj.isBool()) {
00217     endOfBlock = obj.getBool();
00218       }
00219       obj.free();
00220       params->dictLookup("BlackIs1", &obj);
00221       if (obj.isBool()) {
00222     black = obj.getBool();
00223       }
00224       obj.free();
00225     }
00226     str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
00227                  columns, rows, endOfBlock, black);
00228   } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
00229     str = new DCTStream(str);
00230   } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
00231     pred = 1;
00232     columns = 1;
00233     colors = 1;
00234     bits = 8;
00235     if (params->isDict()) {
00236       params->dictLookup("Predictor", &obj);
00237       if (obj.isInt())
00238     pred = obj.getInt();
00239       obj.free();
00240       params->dictLookup("Columns", &obj);
00241       if (obj.isInt())
00242     columns = obj.getInt();
00243       obj.free();
00244       params->dictLookup("Colors", &obj);
00245       if (obj.isInt())
00246     colors = obj.getInt();
00247       obj.free();
00248       params->dictLookup("BitsPerComponent", &obj);
00249       if (obj.isInt())
00250     bits = obj.getInt();
00251       obj.free();
00252     }
00253     str = new FlateStream(str, pred, columns, colors, bits);
00254   } else if (!strcmp(name, "JBIG2Decode")) {
00255     if (params->isDict()) {
00256       params->dictLookup("JBIG2Globals", &globals);
00257     }
00258     str = new JBIG2Stream(str, &globals);
00259     globals.free();
00260   } else {
00261     error(getPos(), "Unknown filter '%s'", name);
00262     str = new EOFStream(str);
00263   }
00264   return str;
00265 }
00266 
00267 //------------------------------------------------------------------------
00268 // BaseStream
00269 //------------------------------------------------------------------------
00270 
00271 BaseStream::BaseStream(Object *dictA) {
00272   dict = *dictA;
00273 #ifndef NO_DECRYPTION
00274   decrypt = NULL;
00275 #endif
00276 }
00277 
00278 BaseStream::~BaseStream() {
00279   dict.free();
00280 #ifndef NO_DECRYPTION
00281   if (decrypt)
00282     delete decrypt;
00283 #endif
00284 }
00285 
00286 #ifndef NO_DECRYPTION
00287 void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
00288                   int objNum, int objGen) {
00289   decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
00290 }
00291 #endif
00292 
00293 //------------------------------------------------------------------------
00294 // FilterStream
00295 //------------------------------------------------------------------------
00296 
00297 FilterStream::FilterStream(Stream *strA) {
00298   str = strA;
00299 }
00300 
00301 FilterStream::~FilterStream() {
00302 }
00303 
00304 void FilterStream::close() {
00305   str->close();
00306 }
00307 
00308 void FilterStream::setPos(Guint /*pos*/, int /*dir*/) {
00309   error(-1, "Internal: called setPos() on FilterStream");
00310 }
00311 
00312 //------------------------------------------------------------------------
00313 // ImageStream
00314 //------------------------------------------------------------------------
00315 
00316 ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
00317   int imgLineSize;
00318 
00319   str = strA;
00320   width = widthA;
00321   nComps = nCompsA;
00322   nBits = nBitsA;
00323 
00324   nVals = width * nComps;
00325   if (nBits == 1) {
00326     imgLineSize = (nVals + 7) & ~7;
00327   } else {
00328     imgLineSize = nVals;
00329   }
00330   imgLine = (Guchar *)gmalloc(imgLineSize * sizeof(Guchar));
00331   imgIdx = nVals;
00332 }
00333 
00334 ImageStream::~ImageStream() {
00335   gfree(imgLine);
00336 }
00337 
00338 void ImageStream::reset() {
00339   str->reset();
00340 }
00341 
00342 GBool ImageStream::getPixel(Guchar *pix) {
00343   int i;
00344 
00345   if (imgIdx >= nVals) {
00346     getLine();
00347     imgIdx = 0;
00348   }
00349   for (i = 0; i < nComps; ++i) {
00350     pix[i] = imgLine[imgIdx++];
00351   }
00352   return gTrue;
00353 }
00354 
00355 Guchar *ImageStream::getLine() {
00356   Gulong buf, bitMask;
00357   int bits;
00358   int c;
00359   int i;
00360 
00361   if (nBits == 1) {
00362     for (i = 0; i < nVals; i += 8) {
00363       c = str->getChar();
00364       imgLine[i+0] = (Guchar)((c >> 7) & 1);
00365       imgLine[i+1] = (Guchar)((c >> 6) & 1);
00366       imgLine[i+2] = (Guchar)((c >> 5) & 1);
00367       imgLine[i+3] = (Guchar)((c >> 4) & 1);
00368       imgLine[i+4] = (Guchar)((c >> 3) & 1);
00369       imgLine[i+5] = (Guchar)((c >> 2) & 1);
00370       imgLine[i+6] = (Guchar)((c >> 1) & 1);
00371       imgLine[i+7] = (Guchar)(c & 1);
00372     }
00373   } else if (nBits == 8) {
00374     for (i = 0; i < nVals; ++i) {
00375       imgLine[i] = str->getChar();
00376     }
00377   } else {
00378     bitMask = (1 << nBits) - 1;
00379     buf = 0;
00380     bits = 0;
00381     for (i = 0; i < nVals; ++i) {
00382       if (bits < nBits) {
00383     buf = (buf << 8) | (str->getChar() & 0xff);
00384     bits += 8;
00385       }
00386       imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
00387       bits -= nBits;
00388     }
00389   }
00390   return imgLine;
00391 }
00392 
00393 void ImageStream::skipLine() {
00394   int n, i;
00395 
00396   n = (nVals * nBits + 7) >> 3;
00397   for (i = 0; i < n; ++i) {
00398     str->getChar();
00399   }
00400 }
00401 
00402 //------------------------------------------------------------------------
00403 // StreamPredictor
00404 //------------------------------------------------------------------------
00405 
00406 StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
00407                  int widthA, int nCompsA, int nBitsA) {
00408   str = strA;
00409   predictor = predictorA;
00410   width = widthA;
00411   nComps = nCompsA;
00412   nBits = nBitsA;
00413   predLine = NULL;
00414   ok = gFalse;
00415 
00416   nVals = width * nComps;
00417   if (width <= 0 || nComps <= 0 || nBits <= 0 ||
00418      nComps >= 4 || nBits > 16 ||
00419       width >= INT_MAX / nComps ||
00420       nVals >= (INT_MAX - 7) / nBits)
00421     return;
00422 
00423   pixBytes = (nComps * nBits + 7) >> 3;
00424   rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
00425   if (rowBytes < 0)
00426     return;
00427 
00428   predLine = (Guchar *)gmalloc(rowBytes);
00429   memset(predLine, 0, rowBytes);
00430   predIdx = rowBytes;
00431 
00432   ok = gTrue;
00433 }
00434 
00435 StreamPredictor::~StreamPredictor() {
00436   gfree(predLine);
00437 }
00438 
00439 int StreamPredictor::lookChar() {
00440   if (predIdx >= rowBytes) {
00441     if (!getNextLine()) {
00442       return EOF;
00443     }
00444   }
00445   return predLine[predIdx];
00446 }
00447 
00448 int StreamPredictor::getChar() {
00449   if (predIdx >= rowBytes) {
00450     if (!getNextLine()) {
00451       return EOF;
00452     }
00453   }
00454   return predLine[predIdx++];
00455 }
00456 
00457 GBool StreamPredictor::getNextLine() {
00458   int curPred;
00459   Guchar upLeftBuf[4];
00460   int left, up, upLeft, p, pa, pb, pc;
00461   int c;
00462   Gulong inBuf, outBuf, bitMask;
00463   int inBits, outBits;
00464   int i, j, k;
00465 
00466   // get PNG optimum predictor number
00467   if (predictor == 15) {
00468     if ((curPred = str->getRawChar()) == EOF) {
00469       return gFalse;
00470     }
00471     curPred += 10;
00472   } else {
00473     curPred = predictor;
00474   }
00475 
00476   // read the raw line, apply PNG (byte) predictor
00477   upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
00478   for (i = pixBytes; i < rowBytes; ++i) {
00479     upLeftBuf[3] = upLeftBuf[2];
00480     upLeftBuf[2] = upLeftBuf[1];
00481     upLeftBuf[1] = upLeftBuf[0];
00482     upLeftBuf[0] = predLine[i];
00483     if ((c = str->getRawChar()) == EOF) {
00484       break;
00485     }
00486     switch (curPred) {
00487     case 11:            // PNG sub
00488       predLine[i] = predLine[i - pixBytes] + (Guchar)c;
00489       break;
00490     case 12:            // PNG up
00491       predLine[i] = predLine[i] + (Guchar)c;
00492       break;
00493     case 13:            // PNG average
00494       predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
00495                 (Guchar)c;
00496       break;
00497     case 14:            // PNG Paeth
00498       left = predLine[i - pixBytes];
00499       up = predLine[i];
00500       upLeft = upLeftBuf[pixBytes];
00501       p = left + up - upLeft;
00502       if ((pa = p - left) < 0)
00503     pa = -pa;
00504       if ((pb = p - up) < 0)
00505     pb = -pb;
00506       if ((pc = p - upLeft) < 0)
00507     pc = -pc;
00508       if (pa <= pb && pa <= pc)
00509     predLine[i] = left + (Guchar)c;
00510       else if (pb <= pc)
00511     predLine[i] = up + (Guchar)c;
00512       else
00513     predLine[i] = upLeft + (Guchar)c;
00514       break;
00515     case 10:            // PNG none
00516     default:            // no predictor or TIFF predictor
00517       predLine[i] = (Guchar)c;
00518       break;
00519     }
00520   }
00521 
00522   // apply TIFF (component) predictor
00523   //~ this is completely untested
00524   if (predictor == 2) {
00525     if (nBits == 1) {
00526       inBuf = predLine[pixBytes - 1];
00527       for (i = pixBytes; i < rowBytes; i += 8) {
00528     // 1-bit add is just xor
00529     inBuf = (inBuf << 8) | predLine[i];
00530     predLine[i] ^= inBuf >> nComps;
00531       }
00532     } else if (nBits == 8) {
00533       for (i = pixBytes; i < rowBytes; ++i) {
00534     predLine[i] += predLine[i - nComps];
00535       }
00536     } else {
00537       upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
00538       bitMask = (1 << nBits) - 1;
00539       inBuf = outBuf = 0;
00540       inBits = outBits = 0;
00541       j = k = pixBytes;
00542       for (i = 0; i < nVals; ++i) {
00543     if (inBits < nBits) {
00544       inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
00545       inBits += 8;
00546     }
00547     upLeftBuf[3] = upLeftBuf[2];
00548     upLeftBuf[2] = upLeftBuf[1];
00549     upLeftBuf[1] = upLeftBuf[0];
00550     upLeftBuf[0] = (upLeftBuf[nComps] +
00551             (inBuf >> (inBits - nBits))) & bitMask;
00552     outBuf = (outBuf << nBits) | upLeftBuf[0];
00553     inBits -= nBits;
00554     outBits += nBits;
00555     if (outBits > 8) {
00556       predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
00557     }
00558       }
00559       if (outBits > 0) {
00560     predLine[k++] = (Guchar)(outBuf << (8 - outBits));
00561       }
00562     }
00563   }
00564 
00565   // reset to start of line
00566   predIdx = pixBytes;
00567 
00568   return gTrue;
00569 }
00570 
00571 //------------------------------------------------------------------------
00572 // FileStream
00573 //------------------------------------------------------------------------
00574 
00575 FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
00576                Guint lengthA, Object *dictA):
00577     BaseStream(dictA) {
00578   f = fA;
00579   start = startA;
00580   limited = limitedA;
00581   length = lengthA;
00582   bufPtr = bufEnd = buf;
00583   bufPos = start;
00584   savePos = 0;
00585   saved = gFalse;
00586 }
00587 
00588 FileStream::~FileStream() {
00589   close();
00590 }
00591 
00592 Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
00593                   Guint lengthA, Object *dictA) {
00594   return new FileStream(f, startA, limitedA, lengthA, dictA);
00595 }
00596 
00597 void FileStream::reset() {
00598 #ifdef HAVE_FSEEKO
00599   savePos = (Guint)ftello(f);
00600   fseeko(f, start, SEEK_SET);
00601 #elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
00602   savePos = (Guint)ftell64(f);
00603   fseek64(f, start, SEEK_SET);
00604 #else
00605   savePos = (Guint)ftell(f);
00606   fseek(f, start, SEEK_SET);
00607 #endif
00608   saved = gTrue;
00609   bufPtr = bufEnd = buf;
00610   bufPos = start;
00611 #ifndef NO_DECRYPTION
00612   if (decrypt)
00613     decrypt->reset();
00614 #endif
00615 }
00616 
00617 void FileStream::close() {
00618   if (saved) {
00619 #ifdef HAVE_FSEEKO
00620     fseeko(f, savePos, SEEK_SET);
00621 #elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
00622     fseek64(f, savePos, SEEK_SET);
00623 #else
00624     fseek(f, savePos, SEEK_SET);
00625 #endif
00626     saved = gFalse;
00627   }
00628 }
00629 
00630 GBool FileStream::fillBuf() {
00631   int n;
00632 #ifndef NO_DECRYPTION
00633   char *p;
00634 #endif
00635 
00636   bufPos += bufEnd - buf;
00637   bufPtr = bufEnd = buf;
00638   if (limited && bufPos >= start + length) {
00639     return gFalse;
00640   }
00641   if (limited && bufPos + fileStreamBufSize > start + length) {
00642     n = start + length - bufPos;
00643   } else {
00644     n = fileStreamBufSize;
00645   }
00646   n = fread(buf, 1, n, f);
00647   bufEnd = buf + n;
00648   if (bufPtr >= bufEnd) {
00649     return gFalse;
00650   }
00651 #ifndef NO_DECRYPTION
00652   if (decrypt) {
00653     for (p = buf; p < bufEnd; ++p) {
00654       *p = (char)decrypt->decryptByte((Guchar)*p);
00655     }
00656   }
00657 #endif
00658   return gTrue;
00659 }
00660 
00661 void FileStream::setPos(Guint pos, int dir) {
00662   Guint size;
00663 
00664   if (dir >= 0) {
00665 #ifdef HAVE_FSEEKO
00666     fseeko(f, pos, SEEK_SET);
00667 #elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
00668     fseek64(f, pos, SEEK_SET);
00669 #else
00670     fseek(f, pos, SEEK_SET);
00671 #endif
00672     bufPos = pos;
00673   } else {
00674 #ifdef HAVE_FSEEKO
00675     fseeko(f, 0, SEEK_END);
00676     size = (Guint)ftello(f);
00677 #elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
00678     fseek64(f, 0, SEEK_END);
00679     size = (Guint)ftell64(f);
00680 #else
00681     fseek(f, 0, SEEK_END);
00682     size = (Guint)ftell(f);
00683 #endif
00684     if (pos > size)
00685       pos = (Guint)size;
00686 #ifdef __CYGWIN32__
00687     //~ work around a bug in cygwin's implementation of fseek
00688     rewind(f);
00689 #endif
00690 #ifdef HAVE_FSEEKO
00691     fseeko(f, -(int)pos, SEEK_END);
00692     bufPos = (Guint)ftello(f);
00693 #elif defined(HAVE_FSEEK64) && defined(HAVE_FTELL64)
00694     fseek64(f, -(int)pos, SEEK_END);
00695     bufPos = (Guint)ftell64(f);
00696 #else
00697     fseek(f, -(int)pos, SEEK_END);
00698     bufPos = (Guint)ftell(f);
00699 #endif
00700   }
00701   bufPtr = bufEnd = buf;
00702 }
00703 
00704 void FileStream::moveStart(int delta) {
00705   start += delta;
00706   bufPtr = bufEnd = buf;
00707   bufPos = start;
00708 }
00709 
00710 //------------------------------------------------------------------------
00711 // MemStream
00712 //------------------------------------------------------------------------
00713 
00714 MemStream::MemStream(char *bufA, Guint lengthA, Object *dictA):
00715     BaseStream(dictA) {
00716   buf = bufA;
00717   needFree = gFalse;
00718   length = lengthA;
00719   bufEnd = buf + length;
00720   bufPtr = buf;
00721 }
00722 
00723 MemStream::~MemStream() {
00724   if (needFree) {
00725     gfree(buf);
00726   }
00727 }
00728 
00729 Stream *MemStream::makeSubStream(Guint start, GBool limited,
00730                  Guint lengthA, Object *dictA) {
00731   Guint newLength;
00732 
00733   if (!limited || start + lengthA > length) {
00734     newLength = length - start;
00735   } else {
00736     newLength = lengthA;
00737   }
00738   return new MemStream(buf + start, newLength, dictA);
00739 }
00740 
00741 void MemStream::reset() {
00742   bufPtr = buf;
00743 #ifndef NO_DECRYPTION
00744   if (decrypt) {
00745     decrypt->reset();
00746   }
00747 #endif
00748 }
00749 
00750 void MemStream::close() {
00751 }
00752 
00753 void MemStream::setPos(Guint pos, int dir) {
00754   if (dir >= 0) {
00755     if (pos > length) {
00756       bufPtr = bufEnd;
00757     } else {
00758       bufPtr = buf + pos;
00759     }
00760   } else {
00761     if (pos > length) {
00762       bufPtr = buf;
00763     } else {
00764       bufPtr = bufEnd - pos;
00765     }
00766   }
00767 }
00768 
00769 void MemStream::moveStart(int delta) {
00770   buf += delta;
00771   bufPtr = buf;
00772 }
00773 
00774 #ifndef NO_DECRYPTION
00775 void MemStream::doDecryption(Guchar *fileKey, int keyLength,
00776                  int objNum, int objGen) {
00777   char *newBuf;
00778   char *p, *q;
00779 
00780   this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
00781   if (decrypt) {
00782     newBuf = (char *)gmalloc(bufEnd - buf);
00783     for (p = buf, q = newBuf; p < bufEnd; ++p, ++q) {
00784       *q = (char)decrypt->decryptByte((Guchar)*p);
00785     }
00786     bufEnd = newBuf + (bufEnd - buf);
00787     bufPtr = newBuf + (bufPtr - buf);
00788     buf = newBuf;
00789     needFree = gTrue;
00790   }
00791 }
00792 #endif
00793 
00794 //------------------------------------------------------------------------
00795 // EmbedStream
00796 //------------------------------------------------------------------------
00797 
00798 EmbedStream::EmbedStream(Stream *strA, Object *dictA):
00799     BaseStream(dictA) {
00800   str = strA;
00801 }
00802 
00803 EmbedStream::~EmbedStream() {
00804 }
00805 
00806 Stream *EmbedStream::makeSubStream(Guint /*start*/, GBool /*limited*/,
00807                                    Guint /*length*/, Object */*dictA*/) {
00808   error(-1, "Internal: called makeSubStream() on EmbedStream");
00809   return NULL;
00810 }
00811 
00812 void EmbedStream::setPos(Guint /*pos*/, int /*dir*/) {
00813   error(-1, "Internal: called setPos() on EmbedStream");
00814 }
00815 
00816 Guint EmbedStream::getStart() {
00817   error(-1, "Internal: called getStart() on EmbedStream");
00818   return 0;
00819 }
00820 
00821 void EmbedStream::moveStart(int /*delta*/) {
00822   error(-1, "Internal: called moveStart() on EmbedStream");
00823 }
00824 
00825 //------------------------------------------------------------------------
00826 // ASCIIHexStream
00827 //------------------------------------------------------------------------
00828 
00829 ASCIIHexStream::ASCIIHexStream(Stream *strA):
00830     FilterStream(strA) {
00831   buf = EOF;
00832   eof = gFalse;
00833 }
00834 
00835 ASCIIHexStream::~ASCIIHexStream() {
00836   delete str;
00837 }
00838 
00839 void ASCIIHexStream::reset() {
00840   str->reset();
00841   buf = EOF;
00842   eof = gFalse;
00843 }
00844 
00845 int ASCIIHexStream::lookChar() {
00846   int c1, c2, x;
00847 
00848   if (buf != EOF)
00849     return buf;
00850   if (eof) {
00851     buf = EOF;
00852     return EOF;
00853   }
00854   do {
00855     c1 = str->getChar();
00856   } while (isspace(c1));
00857   if (c1 == '>') {
00858     eof = gTrue;
00859     buf = EOF;
00860     return buf;
00861   }
00862   do {
00863     c2 = str->getChar();
00864   } while (isspace(c2));
00865   if (c2 == '>') {
00866     eof = gTrue;
00867     c2 = '0';
00868   }
00869   if (c1 >= '0' && c1 <= '9') {
00870     x = (c1 - '0') << 4;
00871   } else if (c1 >= 'A' && c1 <= 'F') {
00872     x = (c1 - 'A' + 10) << 4;
00873   } else if (c1 >= 'a' && c1 <= 'f') {
00874     x = (c1 - 'a' + 10) << 4;
00875   } else if (c1 == EOF) {
00876     eof = gTrue;
00877     x = 0;
00878   } else {
00879     error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
00880     x = 0;
00881   }
00882   if (c2 >= '0' && c2 <= '9') {
00883     x += c2 - '0';
00884   } else if (c2 >= 'A' && c2 <= 'F') {
00885     x += c2 - 'A' + 10;
00886   } else if (c2 >= 'a' && c2 <= 'f') {
00887     x += c2 - 'a' + 10;
00888   } else if (c2 == EOF) {
00889     eof = gTrue;
00890     x = 0;
00891   } else {
00892     error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
00893   }
00894   buf = x & 0xff;
00895   return buf;
00896 }
00897 
00898 GString *ASCIIHexStream::getPSFilter(const char *indent) {
00899   GString *s;
00900 
00901   if (!(s = str->getPSFilter(indent))) {
00902     return NULL;
00903   }
00904   s->append(indent)->append("/ASCIIHexDecode filter\n");
00905   return s;
00906 }
00907 
00908 GBool ASCIIHexStream::isBinary(GBool /*last*/) {
00909   return str->isBinary(gFalse);
00910 }
00911 
00912 //------------------------------------------------------------------------
00913 // ASCII85Stream
00914 //------------------------------------------------------------------------
00915 
00916 ASCII85Stream::ASCII85Stream(Stream *strA):
00917     FilterStream(strA) {
00918   index = n = 0;
00919   eof = gFalse;
00920 }
00921 
00922 ASCII85Stream::~ASCII85Stream() {
00923   delete str;
00924 }
00925 
00926 void ASCII85Stream::reset() {
00927   str->reset();
00928   index = n = 0;
00929   eof = gFalse;
00930 }
00931 
00932 int ASCII85Stream::lookChar() {
00933   int k;
00934   Gulong t;
00935 
00936   if (index >= n) {
00937     if (eof)
00938       return EOF;
00939     index = 0;
00940     do {
00941       c[0] = str->getChar();
00942     } while (c[0] == '\n' || c[0] == '\r');
00943     if (c[0] == '~' || c[0] == EOF) {
00944       eof = gTrue;
00945       n = 0;
00946       return EOF;
00947     } else if (c[0] == 'z') {
00948       b[0] = b[1] = b[2] = b[3] = 0;
00949       n = 4;
00950     } else {
00951       for (k = 1; k < 5; ++k) {
00952     do {
00953       c[k] = str->getChar();
00954     } while (c[k] == '\n' || c[k] == '\r');
00955     if (c[k] == '~' || c[k] == EOF)
00956       break;
00957       }
00958       n = k - 1;
00959       if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
00960     for (++k; k < 5; ++k)
00961       c[k] = 0x21 + 84;
00962     eof = gTrue;
00963       }
00964       t = 0;
00965       for (k = 0; k < 5; ++k)
00966     t = t * 85 + (c[k] - 0x21);
00967       for (k = 3; k >= 0; --k) {
00968     b[k] = (int)(t & 0xff);
00969     t >>= 8;
00970       }
00971     }
00972   }
00973   return b[index];
00974 }
00975 
00976 GString *ASCII85Stream::getPSFilter(const char *indent) {
00977   GString *s;
00978 
00979   if (!(s = str->getPSFilter(indent))) {
00980     return NULL;
00981   }
00982   s->append(indent)->append("/ASCII85Decode filter\n");
00983   return s;
00984 }
00985 
00986 GBool ASCII85Stream::isBinary(GBool /*last*/) {
00987   return str->isBinary(gFalse);
00988 }
00989 
00990 //------------------------------------------------------------------------
00991 // LZWStream
00992 //------------------------------------------------------------------------
00993 
00994 LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
00995              int bits, int earlyA):
00996     FilterStream(strA) {
00997   if (predictor != 1) {
00998     pred = new StreamPredictor(this, predictor, columns, colors, bits);
00999     if ( !pred->isOk()) {
01000        delete pred;
01001        pred = NULL;
01002     }
01003   } else {
01004     pred = NULL;
01005   }
01006   early = earlyA;
01007   eof = gFalse;
01008   inputBits = 0;
01009   clearTable();
01010 }
01011 
01012 LZWStream::~LZWStream() {
01013   if (pred) {
01014     delete pred;
01015   }
01016   delete str;
01017 }
01018 
01019 int LZWStream::getChar() {
01020   if (pred) {
01021     return pred->getChar();
01022   }
01023   if (eof) {
01024     return EOF;
01025   }
01026   if (seqIndex >= seqLength) {
01027     if (!processNextCode()) {
01028       return EOF;
01029     }
01030   }
01031   return seqBuf[seqIndex++];
01032 }
01033 
01034 int LZWStream::lookChar() {
01035   if (pred) {
01036     return pred->lookChar();
01037   }
01038   if (eof) {
01039     return EOF;
01040   }
01041   if (seqIndex >= seqLength) {
01042     if (!processNextCode()) {
01043       return EOF;
01044     }
01045   }
01046   return seqBuf[seqIndex];
01047 }
01048 
01049 int LZWStream::getRawChar() {
01050   if (eof) {
01051     return EOF;
01052   }
01053   if (seqIndex >= seqLength) {
01054     if (!processNextCode()) {
01055       return EOF;
01056     }
01057   }
01058   return seqBuf[seqIndex++];
01059 }
01060 
01061 void LZWStream::reset() {
01062   str->reset();
01063   eof = gFalse;
01064   inputBits = 0;
01065   clearTable();
01066 }
01067 
01068 GBool LZWStream::processNextCode() {
01069   int code;
01070   int nextLength;
01071   int i, j;
01072 
01073   // check for EOF
01074   if (eof) {
01075     return gFalse;
01076   }
01077 
01078   // check for eod and clear-table codes
01079  start:
01080   code = getCode();
01081   if (code == EOF || code == 257) {
01082     eof = gTrue;
01083     return gFalse;
01084   }
01085   if (code == 256) {
01086     clearTable();
01087     goto start;
01088   }
01089   if (nextCode >= 4097) {
01090     error(getPos(), "Bad LZW stream - expected clear-table code");
01091     clearTable();
01092   }
01093 
01094   // process the next code
01095   nextLength = seqLength + 1;
01096   if (code < 256) {
01097     seqBuf[0] = code;
01098     seqLength = 1;
01099   } else if (code < nextCode) {
01100     seqLength = table[code].length;
01101     for (i = seqLength - 1, j = code; i > 0; --i) {
01102       seqBuf[i] = table[j].tail;
01103       j = table[j].head;
01104     }
01105     seqBuf[0] = j;
01106   } else if (code == nextCode) {
01107     seqBuf[seqLength] = newChar;
01108     ++seqLength;
01109   } else {
01110     error(getPos(), "Bad LZW stream - unexpected code");
01111     eof = gTrue;
01112     return gFalse;
01113   }
01114   newChar = seqBuf[0];
01115   if (first) {
01116     first = gFalse;
01117   } else {
01118     table[nextCode].length = nextLength;
01119     table[nextCode].head = prevCode;
01120     table[nextCode].tail = newChar;
01121     ++nextCode;
01122     if (nextCode + early == 512)
01123       nextBits = 10;
01124     else if (nextCode + early == 1024)
01125       nextBits = 11;
01126     else if (nextCode + early == 2048)
01127       nextBits = 12;
01128   }
01129   prevCode = code;
01130 
01131   // reset buffer
01132   seqIndex = 0;
01133 
01134   return gTrue;
01135 }
01136 
01137 void LZWStream::clearTable() {
01138   nextCode = 258;
01139   nextBits = 9;
01140   seqIndex = seqLength = 0;
01141   first = gTrue;
01142 }
01143 
01144 int LZWStream::getCode() {
01145   int c;
01146   int code;
01147 
01148   while (inputBits < nextBits) {
01149     if ((c = str->getChar()) == EOF)
01150       return EOF;
01151     inputBuf = (inputBuf << 8) | (c & 0xff);
01152     inputBits += 8;
01153   }
01154   code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1);
01155   inputBits -= nextBits;
01156   return code;
01157 }
01158 
01159 GString *LZWStream::getPSFilter(const char *indent) {
01160   GString *s;
01161 
01162   if (pred) {
01163     return NULL;
01164   }
01165   if (!(s = str->getPSFilter(indent))) {
01166     return NULL;
01167   }
01168   s->append(indent)->append("/LZWDecode filter\n");
01169   return s;
01170 }
01171 
01172 GBool LZWStream::isBinary(GBool /*last*/) {
01173   return str->isBinary(gTrue);
01174 }
01175 
01176 //------------------------------------------------------------------------
01177 // RunLengthStream
01178 //------------------------------------------------------------------------
01179 
01180 RunLengthStream::RunLengthStream(Stream *strA):
01181     FilterStream(strA) {
01182   bufPtr = bufEnd = buf;
01183   eof = gFalse;
01184 }
01185 
01186 RunLengthStream::~RunLengthStream() {
01187   delete str;
01188 }
01189 
01190 void RunLengthStream::reset() {
01191   str->reset();
01192   bufPtr = bufEnd = buf;
01193   eof = gFalse;
01194 }
01195 
01196 GString *RunLengthStream::getPSFilter(const char *indent) {
01197   GString *s;
01198 
01199   if (!(s = str->getPSFilter(indent))) {
01200     return NULL;
01201   }
01202   s->append(indent)->append("/RunLengthDecode filter\n");
01203   return s;
01204 }
01205 
01206 GBool RunLengthStream::isBinary(GBool /*last*/) {
01207   return str->isBinary(gTrue);
01208 }
01209 
01210 GBool RunLengthStream::fillBuf() {
01211   int c;
01212   int n, i;
01213 
01214   if (eof)
01215     return gFalse;
01216   c = str->getChar();
01217   if (c == 0x80 || c == EOF) {
01218     eof = gTrue;
01219     return gFalse;
01220   }
01221   if (c < 0x80) {
01222     n = c + 1;
01223     for (i = 0; i < n; ++i)
01224       buf[i] = (char)str->getChar();
01225   } else {
01226     n = 0x101 - c;
01227     c = str->getChar();
01228     for (i = 0; i < n; ++i)
01229       buf[i] = (char)c;
01230   }
01231   bufPtr = buf;
01232   bufEnd = buf + n;
01233   return gTrue;
01234 }
01235 
01236 //------------------------------------------------------------------------
01237 // CCITTFaxStream
01238 //------------------------------------------------------------------------
01239 
01240 #if 0
01241 CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
01242                    GBool byteAlignA, int columnsA, int rowsA,
01243                    GBool endOfBlockA, GBool blackA):
01244     FilterStream(strA) {
01245   encoding = encodingA;
01246   endOfLine = endOfLineA;
01247   byteAlign = byteAlignA;
01248   columns = columnsA;
01249   if (columns < 1 || columns >= INT_MAX / sizeof(short)) {
01250     error(-1, "invalid number of columns");
01251     exit(1);
01252   }
01253   rows = rowsA;
01254   endOfBlock = endOfBlockA;
01255   black = blackA;
01256   refLine = (short *)gmalloc((columns + 3) * sizeof(short));
01257   codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
01258 
01259   eof = gFalse;
01260   row = 0;
01261   nextLine2D = encoding < 0;
01262   inputBits = 0;
01263   codingLine[0] = 0;
01264   codingLine[1] = refLine[2] = columns;
01265   a0 = 1;
01266 
01267   buf = EOF;
01268 }
01269 
01270 CCITTFaxStream::~CCITTFaxStream() {
01271   delete str;
01272   gfree(refLine);
01273   gfree(codingLine);
01274 }
01275 
01276 void CCITTFaxStream::reset() {
01277   int n;
01278 
01279   str->reset();
01280   eof = gFalse;
01281   row = 0;
01282   nextLine2D = encoding < 0;
01283   inputBits = 0;
01284   codingLine[0] = 0;
01285   codingLine[1] = refLine[2] = columns;
01286   a0 = 1;
01287   buf = EOF;
01288 
01289   // get initial end-of-line marker and 2D encoding tag
01290   if (endOfBlock) {
01291     if (lookBits(12) == 0x001) {
01292       eatBits(12);
01293     }
01294   } else {
01295     for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
01296     if (n == 11 && lookBits(12) == 0x001) {
01297       eatBits(12);
01298     }
01299   }
01300   if (encoding > 0) {
01301     nextLine2D = !lookBits(1);
01302     eatBits(1);
01303   }
01304 }
01305 
01306 int CCITTFaxStream::lookChar() {
01307   short code1, code2, code3;
01308   int a0New;
01309 #if 0
01310   GBool err;
01311 #endif
01312   GBool gotEOL;
01313   int ret;
01314   int bits, i;
01315 
01316   // if at eof just return EOF
01317   if (eof && codingLine[a0] >= columns) {
01318     return EOF;
01319   }
01320 
01321   // read the next row
01322 #if 0
01323   err = gFalse;
01324 #endif
01325   if (codingLine[a0] >= columns) {
01326 
01327     // 2-D encoding
01328     if (nextLine2D) {
01329       for (i = 0; codingLine[i] < columns; ++i)
01330     refLine[i] = codingLine[i];
01331       refLine[i] = refLine[i + 1] = columns;
01332       b1 = 1;
01333       a0New = codingLine[a0 = 0] = 0;
01334       do {
01335     code1 = getTwoDimCode();
01336     switch (code1) {
01337     case twoDimPass:
01338       if (refLine[b1] < columns) {
01339         a0New = refLine[b1 + 1];
01340         b1 += 2;
01341       }
01342       break;
01343     case twoDimHoriz:
01344       if ((a0 & 1) == 0) {
01345         code1 = code2 = 0;
01346         do {
01347           code1 += code3 = getWhiteCode();
01348         } while (code3 >= 64);
01349         do {
01350           code2 += code3 = getBlackCode();
01351         } while (code3 >= 64);
01352       } else {
01353         code1 = code2 = 0;
01354         do {
01355           code1 += code3 = getBlackCode();
01356         } while (code3 >= 64);
01357         do {
01358           code2 += code3 = getWhiteCode();
01359         } while (code3 >= 64);
01360       }
01361       codingLine[a0 + 1] = a0New + code1;
01362       ++a0;
01363       a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
01364       ++a0;
01365       while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01366         b1 += 2;
01367       break;
01368     case twoDimVert0:
01369       a0New = codingLine[++a0] = refLine[b1];
01370       if (refLine[b1] < columns) {
01371         ++b1;
01372         while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01373           b1 += 2;
01374       }
01375       break;
01376     case twoDimVertR1:
01377       a0New = codingLine[++a0] = refLine[b1] + 1;
01378       if (refLine[b1] < columns) {
01379         ++b1;
01380         while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01381           b1 += 2;
01382       }
01383       break;
01384     case twoDimVertL1:
01385       a0New = codingLine[++a0] = refLine[b1] - 1;
01386       --b1;
01387       while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01388         b1 += 2;
01389       break;
01390     case twoDimVertR2:
01391       a0New = codingLine[++a0] = refLine[b1] + 2;
01392       if (refLine[b1] < columns) {
01393         ++b1;
01394         while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01395           b1 += 2;
01396       }
01397       break;
01398     case twoDimVertL2:
01399       a0New = codingLine[++a0] = refLine[b1] - 2;
01400       --b1;
01401       while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01402         b1 += 2;
01403       break;
01404     case twoDimVertR3:
01405       a0New = codingLine[++a0] = refLine[b1] + 3;
01406       if (refLine[b1] < columns) {
01407         ++b1;
01408         while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01409           b1 += 2;
01410       }
01411       break;
01412     case twoDimVertL3:
01413       a0New = codingLine[++a0] = refLine[b1] - 3;
01414       --b1;
01415       while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01416         b1 += 2;
01417       break;
01418     case EOF:
01419       eof = gTrue;
01420       codingLine[a0 = 0] = columns;
01421       return EOF;
01422     default:
01423       error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
01424 #if 0
01425       err = gTrue;
01426       break;
01427 #else
01428       eof = gTrue;
01429       return EOF;
01430 #endif
01431     }
01432       } while (codingLine[a0] < columns);
01433 
01434     // 1-D encoding
01435     } else {
01436       codingLine[a0 = 0] = 0;
01437       while (1) {
01438     code1 = 0;
01439     do {
01440       code1 += code3 = getWhiteCode();
01441     } while (code3 >= 64);
01442     codingLine[a0+1] = codingLine[a0] + code1;
01443     ++a0;
01444     if (codingLine[a0] >= columns)
01445       break;
01446     code2 = 0;
01447     do {
01448       code2 += code3 = getBlackCode();
01449     } while (code3 >= 64);
01450     codingLine[a0+1] = codingLine[a0] + code2;
01451     ++a0;
01452     if (codingLine[a0] >= columns)
01453       break;
01454       }
01455     }
01456 
01457     if (codingLine[a0] != columns) {
01458       error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
01459 #if 0
01460       err = gTrue;
01461 #endif
01462     }
01463 
01464     // byte-align the row
01465     if (byteAlign) {
01466       inputBits &= ~7;
01467     }
01468 
01469     // check for end-of-line marker, skipping over any extra zero bits
01470     gotEOL = gFalse;
01471     if (!endOfBlock && row == rows - 1) {
01472       eof = gTrue;
01473     } else {
01474       code1 = lookBits(12);
01475       while (code1 == 0) {
01476     eatBits(1);
01477     code1 = lookBits(12);
01478       }
01479       if (code1 == 0x001) {
01480     eatBits(12);
01481     gotEOL = gTrue;
01482       } else if (code1 == EOF) {
01483     eof = gTrue;
01484       }
01485     }
01486 
01487     // get 2D encoding tag
01488     if (!eof && encoding > 0) {
01489       nextLine2D = !lookBits(1);
01490       eatBits(1);
01491     }
01492 
01493     // check for end-of-block marker
01494     if (endOfBlock && gotEOL) {
01495       code1 = lookBits(12);
01496       if (code1 == 0x001) {
01497     eatBits(12);
01498     if (encoding > 0) {
01499       lookBits(1);
01500       eatBits(1);
01501     }
01502     if (encoding >= 0) {
01503       for (i = 0; i < 4; ++i) {
01504         code1 = lookBits(12);
01505         if (code1 != 0x001) {
01506           error(getPos(), "Bad RTC code in CCITTFax stream");
01507         }
01508         eatBits(12);
01509         if (encoding > 0) {
01510           lookBits(1);
01511           eatBits(1);
01512         }
01513       }
01514     }
01515     eof = gTrue;
01516       }
01517     }
01518 
01519 #if 0
01520     // This looks for an end-of-line marker after an error, however
01521     // some (most?) CCITT streams in PDF files don't use end-of-line
01522     // markers, and the just-plow-on technique works better in those
01523     // cases.
01524     else if (err) {
01525       do {
01526     if (code1 == EOF) {
01527       eof = gTrue;
01528       return EOF;
01529     }
01530     eatBits(1);
01531     code1 = look13Bits();
01532       } while ((code1 >> 1) != 0x001);
01533       eatBits(12);
01534       codingLine[++a0] = columns;
01535       if (encoding > 0) {
01536     eatBits(1);
01537     nextLine2D = !(code1 & 1);
01538       }
01539     }
01540 #endif
01541 
01542     a0 = 0;
01543     outputBits = codingLine[1] - codingLine[0];
01544     if (outputBits == 0) {
01545       a0 = 1;
01546       outputBits = codingLine[2] - codingLine[1];
01547     }
01548 
01549     ++row;
01550   }
01551 
01552   // get a byte
01553   if (outputBits >= 8) {
01554     ret = ((a0 & 1) == 0) ? 0xff : 0x00;
01555     if ((outputBits -= 8) == 0) {
01556       ++a0;
01557       if (codingLine[a0] < columns) {
01558     outputBits = codingLine[a0 + 1] - codingLine[a0];
01559       }
01560     }
01561   } else {
01562     bits = 8;
01563     ret = 0;
01564     do {
01565       if (outputBits > bits) {
01566     i = bits;
01567     bits = 0;
01568     if ((a0 & 1) == 0) {
01569       ret |= 0xff >> (8 - i);
01570     }
01571     outputBits -= i;
01572       } else {
01573     i = outputBits;
01574     bits -= outputBits;
01575     if ((a0 & 1) == 0) {
01576       ret |= (0xff >> (8 - i)) << bits;
01577     }
01578     outputBits = 0;
01579     ++a0;
01580     if (codingLine[a0] < columns) {
01581       outputBits = codingLine[a0 + 1] - codingLine[a0];
01582     }
01583       }
01584     } while (bits > 0 && codingLine[a0] < columns);
01585   }
01586   buf = black ? (ret ^ 0xff) : ret;
01587   return buf;
01588 }
01589 
01590 short CCITTFaxStream::getTwoDimCode() {
01591   short code;
01592   CCITTCode *p;
01593   int n;
01594 
01595   code = 0; // make gcc happy
01596   if (endOfBlock) {
01597     code = lookBits(7);
01598     p = &twoDimTab1[code];
01599     if (p->bits > 0) {
01600       eatBits(p->bits);
01601       return p->n;
01602     }
01603   } else {
01604     for (n = 1; n <= 7; ++n) {
01605       code = lookBits(n);
01606       if (n < 7) {
01607     code <<= 7 - n;
01608       }
01609       p = &twoDimTab1[code];
01610       if (p->bits == n) {
01611     eatBits(n);
01612     return p->n;
01613       }
01614     }
01615   }
01616   error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
01617   return EOF;
01618 }
01619 
01620 short CCITTFaxStream::getWhiteCode() {
01621   short code;
01622   CCITTCode *p;
01623   int n;
01624 
01625   code = 0; // make gcc happy
01626   if (endOfBlock) {
01627     code = lookBits(12);
01628     if ((code >> 5) == 0) {
01629       p = &whiteTab1[code];
01630     } else {
01631       p = &whiteTab2[code >> 3];
01632     }
01633     if (p->bits > 0) {
01634       eatBits(p->bits);
01635       return p->n;
01636     }
01637   } else {
01638     for (n = 1; n <= 9; ++n) {
01639       code = lookBits(n);
01640       if (n < 9) {
01641     code <<= 9 - n;
01642       }
01643       p = &whiteTab2[code];
01644       if (p->bits == n) {
01645     eatBits(n);
01646     return p->n;
01647       }
01648     }
01649     for (n = 11; n <= 12; ++n) {
01650       code = lookBits(n);
01651       if (n < 12) {
01652     code <<= 12 - n;
01653       }
01654       p = &whiteTab1[code];
01655       if (p->bits == n) {
01656     eatBits(n);
01657     return p->n;
01658       }
01659     }
01660   }
01661   error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
01662   // eat a bit and return a positive number so that the caller doesn't
01663   // go into an infinite loop
01664   eatBits(1);
01665   return 1;
01666 }
01667 
01668 short CCITTFaxStream::getBlackCode() {
01669   short code;
01670   CCITTCode *p;
01671   int n;
01672 
01673   code = 0; // make gcc happy
01674   if (endOfBlock) {
01675     code = lookBits(13);
01676     if ((code >> 7) == 0) {
01677       p = &blackTab1[code];
01678     } else if ((code >> 9) == 0) {
01679       p = &blackTab2[(code >> 1) - 64];
01680     } else {
01681       p = &blackTab3[code >> 7];
01682     }
01683     if (p->bits > 0) {
01684       eatBits(p->bits);
01685       return p->n;
01686     }
01687   } else {
01688     for (n = 2; n <= 6; ++n) {
01689       code = lookBits(n);
01690       if (n < 6) {
01691     code <<= 6 - n;
01692       }
01693       p = &blackTab3[code];
01694       if (p->bits == n) {
01695     eatBits(n);
01696     return p->n;
01697       }
01698     }
01699     for (n = 7; n <= 12; ++n) {
01700       code = lookBits(n);
01701       if (n < 12) {
01702     code <<= 12 - n;
01703       }
01704       if (code >= 64) {
01705     p = &blackTab2[code - 64];
01706     if (p->bits == n) {
01707       eatBits(n);
01708       return p->n;
01709     }
01710       }
01711     }
01712     for (n = 10; n <= 13; ++n) {
01713       code = lookBits(n);
01714       if (n < 13) {
01715     code <<= 13 - n;
01716       }
01717       p = &blackTab1[code];
01718       if (p->bits == n) {
01719     eatBits(n);
01720     return p->n;
01721       }
01722     }
01723   }
01724   error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
01725   // eat a bit and return a positive number so that the caller doesn't
01726   // go into an infinite loop
01727   eatBits(1);
01728   return 1;
01729 }
01730 
01731 short CCITTFaxStream::lookBits(int n) {
01732   int c;
01733 
01734   while (inputBits < n) {
01735     if ((c = str->getChar()) == EOF) {
01736       if (inputBits == 0) {
01737     return EOF;
01738       }
01739       // near the end of the stream, the caller may ask for more bits
01740       // than are available, but there may still be a valid code in
01741       // however many bits are available -- we need to return correct
01742       // data in this case
01743       return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
01744     }
01745     inputBuf = (inputBuf << 8) + c;
01746     inputBits += 8;
01747   }
01748   return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
01749 }
01750 #else // secfix
01751 CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
01752                    GBool byteAlignA, int columnsA, int rowsA,
01753                    GBool endOfBlockA, GBool blackA):
01754     FilterStream(strA) {
01755   encoding = encodingA;
01756   endOfLine = endOfLineA;
01757   byteAlign = byteAlignA;
01758   columns = columnsA;
01759   if (columns < 1) {
01760     columns = 1;
01761   } else if (columns > (INT_MAX - 2)/sizeof(int)) {
01762     columns = (INT_MAX - 2)/sizeof(int);
01763   }
01764   rows = rowsA;
01765   endOfBlock = endOfBlockA;
01766   black = blackA;
01767   // 0 <= codingLine[0] < codingLine[1] < ... < codingLine[n] = columns
01768   // ---> max codingLine size = columns + 1
01769   // refLine has one extra guard entry at the end
01770   // ---> max refLine size = columns + 2
01771   codingLine = (int *)gmalloc((columns + 1) * sizeof(int));
01772   refLine = (int *)gmalloc((columns + 2) * sizeof(int));
01773 
01774   eof = gFalse;
01775   row = 0;
01776   nextLine2D = encoding < 0;
01777   inputBits = 0;
01778   codingLine[0] = columns;
01779   a0i = 0;
01780   outputBits = 0;
01781 
01782   buf = EOF;
01783 }
01784 
01785 CCITTFaxStream::~CCITTFaxStream() {
01786   delete str;
01787   gfree(refLine);
01788   gfree(codingLine);
01789 }
01790 
01791 void CCITTFaxStream::reset() {
01792   short code1;
01793 
01794   str->reset();
01795   eof = gFalse;
01796   row = 0;
01797   nextLine2D = encoding < 0;
01798   inputBits = 0;
01799   codingLine[0] = columns;
01800   a0i = 0;
01801   outputBits = 0;
01802   buf = EOF;
01803 
01804   // skip any initial zero bits and end-of-line marker, and get the 2D
01805   // encoding tag
01806   while ((code1 = lookBits(12)) == 0) {
01807     eatBits(1);
01808   }
01809   if (code1 == 0x001) {
01810     eatBits(12);
01811   }
01812   if (encoding > 0) {
01813     nextLine2D = !lookBits(1);
01814     eatBits(1);
01815   }
01816 }
01817 
01818 inline void CCITTFaxStream::addPixels(int a1, int blackPixels) {
01819   if (a1 > codingLine[a0i]) {
01820     if (a1 > columns) {
01821       error(getPos(), "CCITTFax row is wrong length (%d)", a1);
01822       err = gTrue;
01823       a1 = columns;
01824     }
01825     if ((a0i & 1) ^ blackPixels) {
01826       ++a0i;
01827     }
01828     codingLine[a0i] = a1;
01829   }
01830 }
01831 
01832 inline void CCITTFaxStream::addPixelsNeg(int a1, int blackPixels) {
01833   if (a1 > codingLine[a0i]) {
01834     if (a1 > columns) {
01835       error(getPos(), "CCITTFax row is wrong length (%d)", a1);
01836       err = gTrue;
01837       a1 = columns;
01838     }
01839     if ((a0i & 1) ^ blackPixels) {
01840       ++a0i;
01841     }
01842     codingLine[a0i] = a1;
01843   } else if (a1 < codingLine[a0i]) {
01844     if (a1 < 0) {
01845       error(getPos(), "Invalid CCITTFax code");
01846       err = gTrue;
01847       a1 = 0;
01848     }
01849     while (a0i > 0 && a1 <= codingLine[a0i - 1]) {
01850       --a0i;
01851     }
01852     codingLine[a0i] = a1;
01853   }
01854 }
01855 
01856 int CCITTFaxStream::lookChar() {
01857   short code1, code2, code3;
01858   int b1i, blackPixels, i, bits;
01859   GBool gotEOL;
01860 
01861   if (buf != EOF) {
01862     return buf;
01863   }
01864 
01865   // read the next row
01866   if (outputBits == 0) {
01867 
01868     // if at eof just return EOF
01869     if (eof) {
01870       return EOF;
01871     }
01872 
01873     err = gFalse;
01874 
01875     // 2-D encoding
01876     if (nextLine2D) {
01877       for (i = 0; codingLine[i] < columns; ++i) {
01878     refLine[i] = codingLine[i];
01879       }
01880       refLine[i++] = columns;
01881       refLine[i] = columns;
01882       codingLine[0] = 0;
01883       a0i = 0;
01884       b1i = 0;
01885       blackPixels = 0;
01886       // invariant:
01887       // refLine[b1i-1] <= codingLine[a0i] < refLine[b1i] < refLine[b1i+1]
01888       //                                                             <= columns
01889       // exception at left edge:
01890       //   codingLine[a0i = 0] = refLine[b1i = 0] = 0 is possible
01891       // exception at right edge:
01892       //   refLine[b1i] = refLine[b1i+1] = columns is possible
01893       while (codingLine[a0i] < columns) {
01894     code1 = getTwoDimCode();
01895     switch (code1) {
01896     case twoDimPass:
01897       addPixels(refLine[b1i + 1], blackPixels);
01898       if (refLine[b1i + 1] < columns) {
01899         b1i += 2;
01900       }
01901       break;
01902     case twoDimHoriz:
01903       code1 = code2 = 0;
01904       if (blackPixels) {
01905         do {
01906           code1 += code3 = getBlackCode();
01907         } while (code3 >= 64);
01908         do {
01909           code2 += code3 = getWhiteCode();
01910         } while (code3 >= 64);
01911       } else {
01912         do {
01913           code1 += code3 = getWhiteCode();
01914         } while (code3 >= 64);
01915         do {
01916           code2 += code3 = getBlackCode();
01917         } while (code3 >= 64);
01918       }
01919       addPixels(codingLine[a0i] + code1, blackPixels);
01920       if (codingLine[a0i] < columns) {
01921         addPixels(codingLine[a0i] + code2, blackPixels ^ 1);
01922       }
01923       while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
01924         b1i += 2;
01925       }
01926       break;
01927     case twoDimVertR3:
01928       addPixels(refLine[b1i] + 3, blackPixels);
01929       blackPixels ^= 1;
01930       if (codingLine[a0i] < columns) {
01931         ++b1i;
01932         while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
01933           b1i += 2;
01934         }
01935       }
01936       break;
01937     case twoDimVertR2:
01938       addPixels(refLine[b1i] + 2, blackPixels);
01939       blackPixels ^= 1;
01940       if (codingLine[a0i] < columns) {
01941         ++b1i;
01942         while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
01943           b1i += 2;
01944         }
01945       }
01946       break;
01947     case twoDimVertR1:
01948       addPixels(refLine[b1i] + 1, blackPixels);
01949       blackPixels ^= 1;
01950       if (codingLine[a0i] < columns) {
01951         ++b1i;
01952         while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
01953           b1i += 2;
01954         }
01955       }
01956       break;
01957     case twoDimVert0:
01958       addPixels(refLine[b1i], blackPixels);
01959       blackPixels ^= 1;
01960       if (codingLine[a0i] < columns) {
01961         ++b1i;
01962         while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
01963           b1i += 2;
01964         }
01965       }
01966       break;
01967     case twoDimVertL3:
01968       addPixelsNeg(refLine[b1i] - 3, blackPixels);
01969       blackPixels ^= 1;
01970       if (codingLine[a0i] < columns) {
01971         if (b1i > 0) {
01972           --b1i;
01973         } else {
01974           ++b1i;
01975         }
01976         while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
01977           b1i += 2;
01978         }
01979       }
01980       break;
01981     case twoDimVertL2:
01982       addPixelsNeg(refLine[b1i] - 2, blackPixels);
01983       blackPixels ^= 1;
01984       if (codingLine[a0i] < columns) {
01985         if (b1i > 0) {
01986           --b1i;
01987         } else {
01988           ++b1i;
01989         }
01990         while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
01991           b1i += 2;
01992         }
01993       }
01994       break;
01995     case twoDimVertL1:
01996       addPixelsNeg(refLine[b1i] - 1, blackPixels);
01997       blackPixels ^= 1;
01998       if (codingLine[a0i] < columns) {
01999         if (b1i > 0) {
02000           --b1i;
02001         } else {
02002           ++b1i;
02003         }
02004         while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
02005           b1i += 2;
02006         }
02007       }
02008       break;
02009     case EOF:
02010       addPixels(columns, 0);
02011       eof = gTrue;
02012       break;
02013     default:
02014       error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
02015       addPixels(columns, 0);
02016       err = gTrue;
02017       break;
02018     }
02019       }
02020 
02021     // 1-D encoding
02022     } else {
02023       codingLine[0] = 0;
02024       a0i = 0;
02025       blackPixels = 0;
02026       while (codingLine[a0i] < columns) {
02027     code1 = 0;
02028     if (blackPixels) {
02029       do {
02030         code1 += code3 = getBlackCode();
02031       } while (code3 >= 64);
02032     } else {
02033       do {
02034         code1 += code3 = getWhiteCode();
02035       } while (code3 >= 64);
02036     }
02037     addPixels(codingLine[a0i] + code1, blackPixels);
02038     blackPixels ^= 1;
02039       }
02040     }
02041 
02042     // byte-align the row
02043     if (byteAlign) {
02044       inputBits &= ~7;
02045     }
02046 
02047     // check for end-of-line marker, skipping over any extra zero bits
02048     gotEOL = gFalse;
02049     if (!endOfBlock && row == rows - 1) {
02050       eof = gTrue;
02051     } else {
02052       code1 = lookBits(12);
02053       while (code1 == 0) {
02054     eatBits(1);
02055     code1 = lookBits(12);
02056       }
02057       if (code1 == 0x001) {
02058     eatBits(12);
02059     gotEOL = gTrue;
02060       } else if (code1 == EOF) {
02061     eof = gTrue;
02062       }
02063     }
02064 
02065     // get 2D encoding tag
02066     if (!eof && encoding > 0) {
02067       nextLine2D = !lookBits(1);
02068       eatBits(1);
02069     }
02070 
02071     // check for end-of-block marker
02072     if (endOfBlock && gotEOL) {
02073       code1 = lookBits(12);
02074       if (code1 == 0x001) {
02075     eatBits(12);
02076     if (encoding > 0) {
02077       lookBits(1);
02078       eatBits(1);
02079     }
02080     if (encoding >= 0) {
02081       for (i = 0; i < 4; ++i) {
02082         code1 = lookBits(12);
02083         if (code1 != 0x001) {
02084           error(getPos(), "Bad RTC code in CCITTFax stream");
02085         }
02086         eatBits(12);
02087         if (encoding > 0) {
02088           lookBits(1);
02089           eatBits(1);
02090         }
02091       }
02092     }
02093     eof = gTrue;
02094       }
02095 
02096     // look for an end-of-line marker after an error -- we only do
02097     // this if we know the stream contains end-of-line markers because
02098     // the "just plow on" technique tends to work better otherwise
02099     } else if (err && endOfLine) {
02100       while (1) {
02101     code1 = lookBits(13);
02102     if (code1 == EOF) {
02103       eof = gTrue;
02104       return EOF;
02105     }
02106     if ((code1 >> 1) == 0x001) {
02107       break;
02108     }
02109     eatBits(1);
02110       }
02111       eatBits(12); 
02112       if (encoding > 0) {
02113     eatBits(1);
02114     nextLine2D = !(code1 & 1);
02115       }
02116     }
02117 
02118     // set up for output
02119     if (codingLine[0] > 0) {
02120       outputBits = codingLine[a0i = 0];
02121     } else {
02122       outputBits = codingLine[a0i = 1];
02123     }
02124 
02125     ++row;
02126   }
02127 
02128   // get a byte
02129   if (outputBits >= 8) {
02130     buf = (a0i & 1) ? 0x00 : 0xff;
02131     outputBits -= 8;
02132     if (outputBits == 0 && codingLine[a0i] < columns) {
02133       ++a0i;
02134       outputBits = codingLine[a0i] - codingLine[a0i - 1];
02135     }
02136   } else {
02137     bits = 8;
02138     buf = 0;
02139     do {
02140       if (outputBits > bits) {
02141     buf <<= bits;
02142     if (!(a0i & 1)) {
02143       buf |= 0xff >> (8 - bits);
02144     }
02145     outputBits -= bits;
02146     bits = 0;
02147       } else {
02148     buf <<= outputBits;
02149     if (!(a0i & 1)) {
02150       buf |= 0xff >> (8 - outputBits);
02151     }
02152     bits -= outputBits;
02153     outputBits = 0;
02154     if (codingLine[a0i] < columns) {
02155       ++a0i;
02156       outputBits = codingLine[a0i] - codingLine[a0i - 1];
02157     } else if (bits > 0) {
02158       buf <<= bits;
02159       bits = 0;
02160     }
02161       }
02162     } while (bits);
02163   }
02164   if (black) {
02165     buf ^= 0xff;
02166   }
02167   return buf;
02168 }
02169 
02170 short CCITTFaxStream::getTwoDimCode() {
02171   short code;
02172   CCITTCode *p;
02173   int n;
02174 
02175   code = 0; // make gcc happy
02176   if (endOfBlock) {
02177     code = lookBits(7);
02178     p = &twoDimTab1[code];
02179     if (p->bits > 0) {
02180       eatBits(p->bits);
02181       return p->n;
02182     }
02183   } else {
02184     for (n = 1; n <= 7; ++n) {
02185       code = lookBits(n);
02186       if (n < 7) {
02187     code <<= 7 - n;
02188       }
02189       p = &twoDimTab1[code];
02190       if (p->bits == n) {
02191     eatBits(n);
02192     return p->n;
02193       }
02194     }
02195   }
02196   error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
02197   return EOF;
02198 }
02199 
02200 short CCITTFaxStream::getWhiteCode() {
02201   short code;
02202   CCITTCode *p;
02203   int n;
02204 
02205   code = 0; // make gcc happy
02206   if (endOfBlock) {
02207     code = lookBits(12);
02208     if (code == EOF) {
02209       return 1;
02210     }
02211     if ((code >> 5) == 0) {
02212       p = &whiteTab1[code];
02213     } else {
02214       p = &whiteTab2[code >> 3];
02215     }
02216     if (p->bits > 0) {
02217       eatBits(p->bits);
02218       return p->n;
02219     }
02220   } else {
02221     for (n = 1; n <= 9; ++n) {
02222       code = lookBits(n);
02223       if (code == EOF) {
02224     return 1;
02225       }
02226       if (n < 9) {
02227     code <<= 9 - n;
02228       }
02229       p = &whiteTab2[code];
02230       if (p->bits == n) {
02231     eatBits(n);
02232     return p->n;
02233       }
02234     }
02235     for (n = 11; n <= 12; ++n) {
02236       code = lookBits(n);
02237       if (code == EOF) {
02238     return 1;
02239       }
02240       if (n < 12) {
02241     code <<= 12 - n;
02242       }
02243       p = &whiteTab1[code];
02244       if (p->bits == n) {
02245     eatBits(n);
02246     return p->n;
02247       }
02248     }
02249   }
02250   error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
02251   // eat a bit and return a positive number so that the caller doesn't
02252   // go into an infinite loop
02253   eatBits(1);
02254   return 1;
02255 }
02256 
02257 short CCITTFaxStream::getBlackCode() {
02258   short code;
02259   CCITTCode *p;
02260   int n;
02261 
02262   code = 0; // make gcc happy
02263   if (endOfBlock) {
02264     code = lookBits(13);
02265     if (code == EOF) {
02266       return 1;
02267     }
02268     if ((code >> 7) == 0) {
02269       p = &blackTab1[code];
02270     } else if ((code >> 9) == 0 && (code >> 7) != 0) {
02271       p = &blackTab2[(code >> 1) - 64];
02272     } else {
02273       p = &blackTab3[code >> 7];
02274     }
02275     if (p->bits > 0) {
02276       eatBits(p->bits);
02277       return p->n;
02278     }
02279   } else {
02280     for (n = 2; n <= 6; ++n) {
02281       code = lookBits(n);
02282       if (code == EOF) {
02283     return 1;
02284       }
02285       if (n < 6) {
02286     code <<= 6 - n;
02287       }
02288       p = &blackTab3[code];
02289       if (p->bits == n) {
02290     eatBits(n);
02291     return p->n;
02292       }
02293     }
02294     for (n = 7; n <= 12; ++n) {
02295       code = lookBits(n);
02296       if (code == EOF) {
02297     return 1;
02298       }
02299       if (n < 12) {
02300     code <<= 12 - n;
02301       }
02302       if (code >= 64) {
02303     p = &blackTab2[code - 64];
02304     if (p->bits == n) {
02305       eatBits(n);
02306       return p->n;
02307     }
02308       }
02309     }
02310     for (n = 10; n <= 13; ++n) {
02311       code = lookBits(n);
02312       if (code == EOF) {
02313     return 1;
02314       }
02315       if (n < 13) {
02316     code <<= 13 - n;
02317       }
02318       p = &blackTab1[code];
02319       if (p->bits == n) {
02320     eatBits(n);
02321     return p->n;
02322       }
02323     }
02324   }
02325   error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
02326   // eat a bit and return a positive number so that the caller doesn't
02327   // go into an infinite loop
02328   eatBits(1);
02329   return 1;
02330 }
02331 
02332 short CCITTFaxStream::lookBits(int n) {
02333   int c;
02334 
02335   while (inputBits < n) {
02336     if ((c = str->getChar()) == EOF) {
02337       if (inputBits == 0) {
02338     return EOF;
02339       }
02340       // near the end of the stream, the caller may ask for more bits
02341       // than are available, but there may still be a valid code in
02342       // however many bits are available -- we need to return correct
02343       // data in this case
02344       return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
02345     }
02346     inputBuf = (inputBuf << 8) + c;
02347     inputBits += 8;
02348   }
02349   return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
02350 }
02351 
02352 #endif
02353 
02354 GString *CCITTFaxStream::getPSFilter(const char *indent) {
02355   GString *s;
02356   char s1[50];
02357 
02358   if (!(s = str->getPSFilter(indent))) {
02359     return NULL;
02360   }
02361   s->append(indent)->append("<< ");
02362   if (encoding != 0) {
02363     sprintf(s1, "/K %d ", encoding);
02364     s->append(s1);
02365   }
02366   if (endOfLine) {
02367     s->append("/EndOfLine true ");
02368   }
02369   if (byteAlign) {
02370     s->append("/EncodedByteAlign true ");
02371   }
02372   sprintf(s1, "/Columns %d ", columns);
02373   s->append(s1);
02374   if (rows != 0) {
02375     sprintf(s1, "/Rows %d ", rows);
02376     s->append(s1);
02377   }
02378   if (!endOfBlock) {
02379     s->append("/EndOfBlock false ");
02380   }
02381   if (black) {
02382     s->append("/BlackIs1 true ");
02383   }
02384   s->append(">> /CCITTFaxDecode filter\n");
02385   return s;
02386 }
02387 
02388 GBool CCITTFaxStream::isBinary(GBool /*last*/) {
02389   return str->isBinary(gTrue);
02390 }
02391 
02392 //------------------------------------------------------------------------
02393 // DCTStream
02394 //------------------------------------------------------------------------
02395 
02396 // IDCT constants (20.12 fixed point format)
02397 #define dctCos1    4017     // cos(pi/16)
02398 #define dctSin1     799     // sin(pi/16)
02399 #define dctCos3    3406     // cos(3*pi/16)
02400 #define dctSin3    2276     // sin(3*pi/16)
02401 #define dctCos6    1567     // cos(6*pi/16)
02402 #define dctSin6    3784     // sin(6*pi/16)
02403 #define dctSqrt2   5793     // sqrt(2)
02404 #define dctSqrt1d2 2896     // sqrt(2) / 2
02405 
02406 // color conversion parameters (16.16 fixed point format)
02407 #define dctCrToR   91881    //  1.4020
02408 #define dctCbToG  -22553    // -0.3441363
02409 #define dctCrToG  -46802    // -0.71413636
02410 #define dctCbToB  116130    //  1.772
02411 
02412 // clip [-256,511] --> [0,255]
02413 #define dctClipOffset 256
02414 static Guchar dctClip[768];
02415 static int dctClipInit = 0;
02416 
02417 // zig zag decode map
02418 static int dctZigZag[64] = {
02419    0,
02420    1,  8,
02421   16,  9,  2,
02422    3, 10, 17, 24,
02423   32, 25, 18, 11, 4,
02424    5, 12, 19, 26, 33, 40,
02425   48, 41, 34, 27, 20, 13,  6,
02426    7, 14, 21, 28, 35, 42, 49, 56,
02427   57, 50, 43, 36, 29, 22, 15,
02428   23, 30, 37, 44, 51, 58,
02429   59, 52, 45, 38, 31,
02430   39, 46, 53, 60,
02431   61, 54, 47,
02432   55, 62,
02433   63
02434 };
02435 
02436 DCTStream::DCTStream(Stream *strA):
02437     FilterStream(strA) {
02438   int i, j;
02439 
02440   progressive = interleaved = gFalse;
02441   width = height = 0;
02442   mcuWidth = mcuHeight = 0;
02443   numComps = 0;
02444   comp = 0;
02445   x = y = dy = 0;
02446   for (i = 0; i < 4; ++i) {
02447     for (j = 0; j < 32; ++j) {
02448       rowBuf[i][j] = NULL;
02449     }
02450     frameBuf[i] = NULL;
02451   }
02452 
02453   if (!dctClipInit) {
02454     for (i = -256; i < 0; ++i)
02455       dctClip[dctClipOffset + i] = 0;
02456     for (i = 0; i < 256; ++i)
02457       dctClip[dctClipOffset + i] = i;
02458     for (i = 256; i < 512; ++i)
02459       dctClip[dctClipOffset + i] = 255;
02460     dctClipInit = 1;
02461   }
02462 }
02463 
02464 DCTStream::~DCTStream() {
02465   int i, j;
02466 
02467   delete str;
02468   if (progressive || !interleaved) {
02469     for (i = 0; i < numComps; ++i) {
02470       gfree(frameBuf[i]);
02471     }
02472   } else {
02473     for (i = 0; i < numComps; ++i) {
02474       for (j = 0; j < mcuHeight; ++j) {
02475     gfree(rowBuf[i][j]);
02476       }
02477     }
02478   }
02479 }
02480 
02481 void DCTStream::reset() {
02482   int minHSample, minVSample;
02483   int i, j;
02484 
02485   str->reset();
02486 
02487   progressive = interleaved = gFalse;
02488   width = height = 0;
02489   numComps = 0;
02490   numQuantTables = 0;
02491   numDCHuffTables = 0;
02492   numACHuffTables = 0;
02493   colorXform = 0;
02494   gotAdobeMarker = gFalse;
02495   restartInterval = 0;
02496 
02497   if (!readHeader()) {
02498     y = height;
02499     return;
02500   }
02501 
02502   // compute MCU size
02503   mcuWidth = minHSample = compInfo[0].hSample;
02504   mcuHeight = minVSample = compInfo[0].vSample;
02505   for (i = 1; i < numComps; ++i) {
02506     if (compInfo[i].hSample < minHSample)
02507       minHSample = compInfo[i].hSample;
02508     if (compInfo[i].vSample < minVSample)
02509       minVSample = compInfo[i].vSample;
02510     if (compInfo[i].hSample > mcuWidth)
02511       mcuWidth = compInfo[i].hSample;
02512     if (compInfo[i].vSample > mcuHeight)
02513       mcuHeight = compInfo[i].vSample;
02514   }
02515   for (i = 0; i < numComps; ++i) {
02516     compInfo[i].hSample /= minHSample;
02517     compInfo[i].vSample /= minVSample;
02518   }
02519   mcuWidth = (mcuWidth / minHSample) * 8;
02520   mcuHeight = (mcuHeight / minVSample) * 8;
02521 
02522   // figure out color transform
02523   if (!gotAdobeMarker && numComps == 3) {
02524     if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) {
02525       colorXform = 1;
02526     }
02527   }
02528 
02529   if (progressive || !interleaved) {
02530 
02531     // allocate a buffer for the whole image
02532     bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
02533     bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
02534     if (bufWidth <= 0 || bufHeight <= 0 ||
02535     bufWidth > INT_MAX / bufWidth / (int)sizeof(int)) {
02536       error(getPos(), "Invalid image size in DCT stream");
02537       y = height;
02538       return;
02539     }
02540     for (i = 0; i < numComps; ++i) {
02541       frameBuf[i] = (int *)gmalloc(bufWidth * bufHeight * sizeof(int));
02542       memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
02543     }
02544 
02545     // read the image data
02546     do {
02547       restartMarker = 0xd0;
02548       restart();
02549       readScan();
02550     } while (readHeader());
02551 
02552     // decode
02553     decodeImage();
02554 
02555     // initialize counters
02556     comp = 0;
02557     x = 0;
02558     y = 0;
02559 
02560   } else {
02561 
02562     // allocate a buffer for one row of MCUs
02563     bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
02564     for (i = 0; i < numComps; ++i) {
02565       for (j = 0; j < mcuHeight; ++j) {
02566     rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
02567       }
02568     }
02569 
02570     // initialize counters
02571     comp = 0;
02572     x = 0;
02573     y = 0;
02574     dy = mcuHeight;
02575 
02576     restartMarker = 0xd0;
02577     restart();
02578   }
02579 }
02580 
02581 int DCTStream::getChar() {
02582   int c;
02583 
02584   if (y >= height) {
02585     return EOF;
02586   }
02587   if (progressive || !interleaved) {
02588     c = frameBuf[comp][y * bufWidth + x];
02589     if (++comp == numComps) {
02590       comp = 0;
02591       if (++x == width) {
02592     x = 0;
02593     ++y;
02594       }
02595     }
02596   } else {
02597     if (dy >= mcuHeight) {
02598       if (!readMCURow()) {
02599     y = height;
02600     return EOF;
02601       }
02602       comp = 0;
02603       x = 0;
02604       dy = 0;
02605     }
02606     c = rowBuf[comp][dy][x];
02607     if (++comp == numComps) {
02608       comp = 0;
02609       if (++x == width) {
02610     x = 0;
02611     ++y;
02612     ++dy;
02613     if (y == height) {
02614       readTrailer();
02615     }
02616       }
02617     }
02618   }
02619   return c;
02620 }
02621 
02622 int DCTStream::lookChar() {
02623   if (y >= height) {
02624     return EOF;
02625   }
02626   if (progressive || !interleaved) {
02627     return frameBuf[comp][y * bufWidth + x];
02628   } else {
02629     if (dy >= mcuHeight) {
02630       if (!readMCURow()) {
02631     y = height;
02632     return EOF;
02633       }
02634       comp = 0;
02635       x = 0;
02636       dy = 0;
02637     }
02638     return rowBuf[comp][dy][x];
02639   }
02640 }
02641 
02642 void DCTStream::restart() {
02643   int i;
02644 
02645   inputBits = 0;
02646   restartCtr = restartInterval;
02647   for (i = 0; i < numComps; ++i) {
02648     compInfo[i].prevDC = 0;
02649   }
02650   eobRun = 0;
02651 }
02652 
02653 // Read one row of MCUs from a sequential JPEG stream.
02654 GBool DCTStream::readMCURow() {
02655   int data1[64];
02656   Guchar data2[64];
02657   Guchar *p1, *p2;
02658   int pY, pCb, pCr, pR, pG, pB;
02659   int h, v, horiz, vert, hSub, vSub;
02660   int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
02661   int c;
02662 
02663   for (x1 = 0; x1 < width; x1 += mcuWidth) {
02664 
02665     // deal with restart marker
02666     if (restartInterval > 0 && restartCtr == 0) {
02667       c = readMarker();
02668       if (c != restartMarker) {
02669     error(getPos(), "Bad DCT data: incorrect restart marker");
02670     return gFalse;
02671       }
02672       if (++restartMarker == 0xd8)
02673     restartMarker = 0xd0;
02674       restart();
02675     }
02676 
02677     // read one MCU
02678     for (cc = 0; cc < numComps; ++cc) {
02679       h = compInfo[cc].hSample;
02680       v = compInfo[cc].vSample;
02681       horiz = mcuWidth / h;
02682       vert = mcuHeight / v;
02683       hSub = horiz / 8;
02684       vSub = vert / 8;
02685       for (y2 = 0; y2 < mcuHeight; y2 += vert) {
02686     for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
02687       if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
02688                 &acHuffTables[scanInfo.acHuffTable[cc]],
02689                 &compInfo[cc].prevDC,
02690                 data1)) {
02691         return gFalse;
02692       }
02693       transformDataUnit(quantTables[compInfo[cc].quantTable],
02694                 data1, data2);
02695       if (hSub == 1 && vSub == 1) {
02696         for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
02697           p1 = &rowBuf[cc][y2+y3][x1+x2];
02698           p1[0] = data2[i];
02699           p1[1] = data2[i+1];
02700           p1[2] = data2[i+2];
02701           p1[3] = data2[i+3];
02702           p1[4] = data2[i+4];
02703           p1[5] = data2[i+5];
02704           p1[6] = data2[i+6];
02705           p1[7] = data2[i+7];
02706         }
02707       } else if (hSub == 2 && vSub == 2) {
02708         for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
02709           p1 = &rowBuf[cc][y2+y3][x1+x2];
02710           p2 = &rowBuf[cc][y2+y3+1][x1+x2];
02711           p1[0] = p1[1] = p2[0] = p2[1] = data2[i];
02712           p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1];
02713           p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2];
02714           p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3];
02715           p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4];
02716           p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5];
02717           p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6];
02718           p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7];
02719         }
02720       } else {
02721         i = 0;
02722         for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
02723           for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
02724         for (y5 = 0; y5 < vSub; ++y5)
02725           for (x5 = 0; x5 < hSub; ++x5)
02726             rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i];
02727         ++i;
02728           }
02729         }
02730       }
02731     }
02732       }
02733     }
02734     --restartCtr;
02735 
02736     // color space conversion
02737     if (colorXform) {
02738       // convert YCbCr to RGB
02739       if (numComps == 3) {
02740     for (y2 = 0; y2 < mcuHeight; ++y2) {
02741       for (x2 = 0; x2 < mcuWidth; ++x2) {
02742         pY = rowBuf[0][y2][x1+x2];
02743         pCb = rowBuf[1][y2][x1+x2] - 128;
02744         pCr = rowBuf[2][y2][x1+x2] - 128;
02745         pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
02746         rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
02747         pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
02748         rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
02749         pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
02750         rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
02751       }
02752     }
02753       // convert YCbCrK to CMYK (K is passed through unchanged)
02754       } else if (numComps == 4) {
02755     for (y2 = 0; y2 < mcuHeight; ++y2) {
02756       for (x2 = 0; x2 < mcuWidth; ++x2) {
02757         pY = rowBuf[0][y2][x1+x2];
02758         pCb = rowBuf[1][y2][x1+x2] - 128;
02759         pCr = rowBuf[2][y2][x1+x2] - 128;
02760         pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
02761         rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
02762         pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
02763         rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
02764         pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
02765         rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
02766       }
02767     }
02768       }
02769     }
02770   }
02771   return gTrue;
02772 }
02773 
02774 // Read one scan from a progressive or non-interleaved JPEG stream.
02775 void DCTStream::readScan() {
02776   int data[64];
02777   int x1, y1, dy1, x2, y2, y3, cc, i;
02778   int h, v, horiz, vert, hSub, vSub;
02779   int *p1;
02780   int c;
02781 
02782   if (scanInfo.numComps == 1) {
02783     for (cc = 0; cc < numComps; ++cc) {
02784       if (scanInfo.comp[cc]) {
02785     break;
02786       }
02787     }
02788     dy1 = mcuHeight / compInfo[cc].vSample;
02789   } else {
02790     dy1 = mcuHeight;
02791   }
02792 
02793   for (y1 = 0; y1 < bufHeight; y1 += dy1) {
02794     for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
02795 
02796       // deal with restart marker
02797       if (restartInterval > 0 && restartCtr == 0) {
02798     c = readMarker();
02799     if (c != restartMarker) {
02800       error(getPos(), "Bad DCT data: incorrect restart marker");
02801       return;
02802     }
02803     if (++restartMarker == 0xd8) {
02804       restartMarker = 0xd0;
02805     }
02806     restart();
02807       }
02808 
02809       // read one MCU
02810       for (cc = 0; cc < numComps; ++cc) {
02811     if (!scanInfo.comp[cc]) {
02812       continue;
02813     }
02814 
02815     h = compInfo[cc].hSample;
02816     v = compInfo[cc].vSample;
02817     horiz = mcuWidth / h;
02818     vert = mcuHeight / v;
02819     hSub = horiz / 8;
02820     vSub = vert / 8;
02821     for (y2 = 0; y2 < dy1; y2 += vert) {
02822       for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
02823 
02824         // pull out the current values
02825         p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
02826         for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
02827           data[i] = p1[0];
02828           data[i+1] = p1[1];
02829           data[i+2] = p1[2];
02830           data[i+3] = p1[3];
02831           data[i+4] = p1[4];
02832           data[i+5] = p1[5];
02833           data[i+6] = p1[6];
02834           data[i+7] = p1[7];
02835           p1 += bufWidth * vSub;
02836         }
02837 
02838         // read one data unit
02839         if (progressive) {
02840           if (!readProgressiveDataUnit(
02841                &dcHuffTables[scanInfo.dcHuffTable[cc]],
02842                &acHuffTables[scanInfo.acHuffTable[cc]],
02843                &compInfo[cc].prevDC,
02844                data)) {
02845         return;
02846           }
02847         } else {
02848           if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]],
02849                 &acHuffTables[scanInfo.acHuffTable[cc]],
02850                 &compInfo[cc].prevDC,
02851                 data)) {
02852         return;
02853           }
02854         }
02855 
02856         // add the data unit into frameBuf
02857         p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
02858         for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
02859           p1[0] = data[i];
02860           p1[1] = data[i+1];
02861           p1[2] = data[i+2];
02862           p1[3] = data[i+3];
02863           p1[4] = data[i+4];
02864           p1[5] = data[i+5];
02865           p1[6] = data[i+6];
02866           p1[7] = data[i+7];
02867           p1 += bufWidth * vSub;
02868         }
02869       }
02870     }
02871       }
02872       --restartCtr;
02873     }
02874   }
02875 }
02876 
02877 // Read one data unit from a sequential JPEG stream.
02878 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
02879                   DCTHuffTable *acHuffTable,
02880                   int *prevDC, int data[64]) {
02881   int run, size, amp;
02882   int c;
02883   int i, j;
02884 
02885   if ((size = readHuffSym(dcHuffTable)) == 9999) {
02886     return gFalse;
02887   }
02888   if (size > 0) {
02889     if ((amp = readAmp(size)) == 9999) {
02890       return gFalse;
02891     }
02892   } else {
02893     amp = 0;
02894   }
02895   data[0] = *prevDC += amp;
02896   for (i = 1; i < 64; ++i) {
02897     data[i] = 0;
02898   }
02899   i = 1;
02900   while (i < 64) {
02901     run = 0;
02902     while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) {
02903       run += 0x10;
02904     }
02905     if (c == 9999) {
02906       return gFalse;
02907     }
02908     if (c == 0x00) {
02909       break;
02910     } else {
02911       run += (c >> 4) & 0x0f;
02912       size = c & 0x0f;
02913       amp = readAmp(size);
02914       if (amp == 9999) {
02915     return gFalse;
02916       }
02917       i += run;
02918       j = dctZigZag[i++];
02919       data[j] = amp;
02920     }
02921   }
02922   return gTrue;
02923 }
02924 
02925 // Read one data unit from a sequential JPEG stream.
02926 GBool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
02927                      DCTHuffTable *acHuffTable,
02928                      int *prevDC, int data[64]) {
02929   int run, size, amp, bit, c;
02930   int i, j, k;
02931 
02932   // get the DC coefficient
02933   i = scanInfo.firstCoeff;
02934   if (i == 0) {
02935     if (scanInfo.ah == 0) {
02936       if ((size = readHuffSym(dcHuffTable)) == 9999) {
02937     return gFalse;
02938       }
02939       if (size > 0) {
02940     if ((amp = readAmp(size)) == 9999) {
02941       return gFalse;
02942     }
02943       } else {
02944     amp = 0;
02945       }
02946       data[0] += (*prevDC += amp) << scanInfo.al;
02947     } else {
02948       if ((bit = readBit()) == 9999) {
02949     return gFalse;
02950       }
02951       data[0] += bit << scanInfo.al;
02952     }
02953     ++i;
02954   }
02955   if (scanInfo.lastCoeff == 0) {
02956     return gTrue;
02957   }
02958 
02959   // check for an EOB run
02960   if (eobRun > 0) {
02961     while (i <= scanInfo.lastCoeff) {
02962       j = dctZigZag[i++];
02963       if (data[j] != 0) {
02964     if ((bit = readBit()) == EOF) {
02965       return gFalse;
02966     }
02967     if (bit) {
02968       data[j] += 1 << scanInfo.al;
02969     }
02970       }
02971     }
02972     --eobRun;
02973     return gTrue;
02974   }
02975 
02976   // read the AC coefficients
02977   while (i <= scanInfo.lastCoeff) {
02978     if ((c = readHuffSym(acHuffTable)) == 9999) {
02979       return gFalse;
02980     }
02981 
02982     // ZRL
02983     if (c == 0xf0) {
02984       k = 0;
02985       while (k < 16) {
02986     j = dctZigZag[i++];
02987     if (data[j] == 0) {
02988       ++k;
02989     } else {
02990       if ((bit = readBit()) == EOF) {
02991         return gFalse;
02992       }
02993       if (bit) {
02994         data[j] += 1 << scanInfo.al;
02995       }
02996     }
02997       }
02998 
02999     // EOB run
03000     } else if ((c & 0x0f) == 0x00) {
03001       j = c >> 4;
03002       eobRun = 0;
03003       for (k = 0; k < j; ++k) {
03004     if ((bit = readBit()) == EOF) {
03005       return 9999;
03006     }
03007     eobRun = (eobRun << 1) | bit;
03008       }
03009       eobRun += 1 << j;
03010       while (i <= scanInfo.lastCoeff) {
03011     j = dctZigZag[i++];
03012     if (data[j] != 0) {
03013       if ((bit = readBit()) == EOF) {
03014         return gFalse;
03015       }
03016       if (bit) {
03017         data[j] += 1 << scanInfo.al;
03018       }
03019     }
03020       }
03021       --eobRun;
03022       break;
03023 
03024     // zero run and one AC coefficient
03025     } else {
03026       run = (c >> 4) & 0x0f;
03027       size = c & 0x0f;
03028       if ((amp = readAmp(size)) == 9999) {
03029     return gFalse;
03030       }
03031       k = 0;
03032       do {
03033     j = dctZigZag[i++];
03034     while (data[j] != 0) {
03035       if ((bit = readBit()) == EOF) {
03036         return gFalse;
03037       }
03038       if (bit) {
03039         data[j] += 1 << scanInfo.al;
03040       }
03041       j = dctZigZag[i++];
03042     }
03043     ++k;
03044       } while (k <= run);
03045       data[j] = amp << scanInfo.al;
03046     }
03047   }
03048 
03049   return gTrue;
03050 }
03051 
03052 // Decode a progressive JPEG image.
03053 void DCTStream::decodeImage() {
03054   int dataIn[64];
03055   Guchar dataOut[64];
03056   Guchar *quantTable;
03057   int pY, pCb, pCr, pR, pG, pB;
03058   int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
03059   int h, v, horiz, vert, hSub, vSub;
03060   int *p0, *p1, *p2;
03061 
03062   for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) {
03063     for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) {
03064       for (cc = 0; cc < numComps; ++cc) {
03065     quantTable = quantTables[compInfo[cc].quantTable];
03066     h = compInfo[cc].hSample;
03067     v = compInfo[cc].vSample;
03068     horiz = mcuWidth / h;
03069     vert = mcuHeight / v;
03070     hSub = horiz / 8;
03071     vSub = vert / 8;
03072     for (y2 = 0; y2 < mcuHeight; y2 += vert) {
03073       for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
03074 
03075         // pull out the coded data unit
03076         p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
03077         for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
03078           dataIn[i]   = p1[0];
03079           dataIn[i+1] = p1[1];
03080           dataIn[i+2] = p1[2];
03081           dataIn[i+3] = p1[3];
03082           dataIn[i+4] = p1[4];
03083           dataIn[i+5] = p1[5];
03084           dataIn[i+6] = p1[6];
03085           dataIn[i+7] = p1[7];
03086           p1 += bufWidth * vSub;
03087         }
03088 
03089         // transform
03090         transformDataUnit(quantTable, dataIn, dataOut);
03091 
03092         // store back into frameBuf, doing replication for
03093         // subsampled components
03094         p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)];
03095         if (hSub == 1 && vSub == 1) {
03096           for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
03097         p1[0] = dataOut[i] & 0xff;
03098         p1[1] = dataOut[i+1] & 0xff;
03099         p1[2] = dataOut[i+2] & 0xff;
03100         p1[3] = dataOut[i+3] & 0xff;
03101         p1[4] = dataOut[i+4] & 0xff;
03102         p1[5] = dataOut[i+5] & 0xff;
03103         p1[6] = dataOut[i+6] & 0xff;
03104         p1[7] = dataOut[i+7] & 0xff;
03105         p1 += bufWidth;
03106           }
03107         } else if (hSub == 2 && vSub == 2) {
03108           p2 = p1 + bufWidth;
03109           for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
03110         p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff;
03111         p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff;
03112         p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff;
03113         p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff;
03114         p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff;
03115         p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff;
03116         p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff;
03117         p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff;
03118         p1 += bufWidth * 2;
03119         p2 += bufWidth * 2;
03120           }
03121         } else {
03122           i = 0;
03123           for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
03124         for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
03125           p2 = p1 + x4;
03126           for (y5 = 0; y5 < vSub; ++y5) {
03127             for (x5 = 0; x5 < hSub; ++x5) {
03128               p2[x5] = dataOut[i] & 0xff;
03129             }
03130             p2 += bufWidth;
03131           }
03132           ++i;
03133         }
03134         p1 += bufWidth * vSub;
03135           }
03136         }
03137       }
03138     }
03139       }
03140 
03141       // color space conversion
03142       if (colorXform) {
03143     // convert YCbCr to RGB
03144     if (numComps == 3) {
03145       for (y2 = 0; y2 < mcuHeight; ++y2) {
03146         p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
03147         p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
03148         p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
03149         for (x2 = 0; x2 < mcuWidth; ++x2) {
03150           pY = *p0;
03151           pCb = *p1 - 128;
03152           pCr = *p2 - 128;
03153           pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
03154           *p0++ = dctClip[dctClipOffset + pR];
03155           pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
03156             32768) >> 16;
03157           *p1++ = dctClip[dctClipOffset + pG];
03158           pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
03159           *p2++ = dctClip[dctClipOffset + pB];
03160         }
03161       }
03162     // convert YCbCrK to CMYK (K is passed through unchanged)
03163     } else if (numComps == 4) {
03164       for (y2 = 0; y2 < mcuHeight; ++y2) {
03165         p0 = &frameBuf[0][(y1+y2) * bufWidth + x1];
03166         p1 = &frameBuf[1][(y1+y2) * bufWidth + x1];
03167         p2 = &frameBuf[2][(y1+y2) * bufWidth + x1];
03168         for (x2 = 0; x2 < mcuWidth; ++x2) {
03169           pY = *p0;
03170           pCb = *p1 - 128;
03171           pCr = *p2 - 128;
03172           pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
03173           *p0++ = 255 - dctClip[dctClipOffset + pR];
03174           pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr +
03175             32768) >> 16;
03176           *p1++ = 255 - dctClip[dctClipOffset + pG];
03177           pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
03178           *p2++ = 255 - dctClip[dctClipOffset + pB];
03179         }
03180       }
03181     }
03182       }
03183     }
03184   }
03185 }
03186 
03187 // Transform one data unit -- this performs the dequantization and
03188 // IDCT steps.  This IDCT algorithm is taken from:
03189 //   Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
03190 //   "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
03191 //   IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
03192 //   988-991.
03193 // The stage numbers mentioned in the comments refer to Figure 1 in this
03194 // paper.
03195 void DCTStream::transformDataUnit(Guchar *quantTable,
03196                   int dataIn[64], Guchar dataOut[64]) {
03197   int v0, v1, v2, v3, v4, v5, v6, v7, t;
03198   int *p;
03199   int i;
03200 
03201   // dequant
03202   for (i = 0; i < 64; ++i) {
03203     dataIn[i] *= quantTable[i];
03204   }
03205 
03206   // inverse DCT on rows
03207   for (i = 0; i < 64; i += 8) {
03208     p = dataIn + i;
03209 
03210     // check for all-zero AC coefficients
03211     if (p[1] == 0 && p[2] == 0 && p[3] == 0 &&
03212     p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) {
03213       t = (dctSqrt2 * p[0] + 512) >> 10;
03214       p[0] = t;
03215       p[1] = t;
03216       p[2] = t;
03217       p[3] = t;
03218       p[4] = t;
03219       p[5] = t;
03220       p[6] = t;
03221       p[7] = t;
03222       continue;
03223     }
03224 
03225     // stage 4
03226     v0 = (dctSqrt2 * p[0] + 128) >> 8;
03227     v1 = (dctSqrt2 * p[4] + 128) >> 8;
03228     v2 = p[2];
03229     v3 = p[6];
03230     v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8;
03231     v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8;
03232     v5 = p[3] << 4;
03233     v6 = p[5] << 4;
03234 
03235     // stage 3
03236     t = (v0 - v1+ 1) >> 1;
03237     v0 = (v0 + v1 + 1) >> 1;
03238     v1 = t;
03239     t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
03240     v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
03241     v3 = t;
03242     t = (v4 - v6 + 1) >> 1;
03243     v4 = (v4 + v6 + 1) >> 1;
03244     v6 = t;
03245     t = (v7 + v5 + 1) >> 1;
03246     v5 = (v7 - v5 + 1) >> 1;
03247     v7 = t;
03248 
03249     // stage 2
03250     t = (v0 - v3 + 1) >> 1;
03251     v0 = (v0 + v3 + 1) >> 1;
03252     v3 = t;
03253     t = (v1 - v2 + 1) >> 1;
03254     v1 = (v1 + v2 + 1) >> 1;
03255     v2 = t;
03256     t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
03257     v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
03258     v7 = t;
03259     t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
03260     v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
03261     v6 = t;
03262 
03263     // stage 1
03264     p[0] = v0 + v7;
03265     p[7] = v0 - v7;
03266     p[1] = v1 + v6;
03267     p[6] = v1 - v6;
03268     p[2] = v2 + v5;
03269     p[5] = v2 - v5;
03270     p[3] = v3 + v4;
03271     p[4] = v3 - v4;
03272   }
03273 
03274   // inverse DCT on columns
03275   for (i = 0; i < 8; ++i) {
03276     p = dataIn + i;
03277 
03278     // check for all-zero AC coefficients
03279     if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 &&
03280     p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) {
03281       t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
03282       p[0*8] = t;
03283       p[1*8] = t;
03284       p[2*8] = t;
03285       p[3*8] = t;
03286       p[4*8] = t;
03287       p[5*8] = t;
03288       p[6*8] = t;
03289       p[7*8] = t;
03290       continue;
03291     }
03292 
03293     // stage 4
03294     v0 = (dctSqrt2 * p[0*8] + 2048) >> 12;
03295     v1 = (dctSqrt2 * p[4*8] + 2048) >> 12;
03296     v2 = p[2*8];
03297     v3 = p[6*8];
03298     v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12;
03299     v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12;
03300     v5 = p[3*8];
03301     v6 = p[5*8];
03302 
03303     // stage 3
03304     t = (v0 - v1 + 1) >> 1;
03305     v0 = (v0 + v1 + 1) >> 1;
03306     v1 = t;
03307     t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
03308     v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
03309     v3 = t;
03310     t = (v4 - v6 + 1) >> 1;
03311     v4 = (v4 + v6 + 1) >> 1;
03312     v6 = t;
03313     t = (v7 + v5 + 1) >> 1;
03314     v5 = (v7 - v5 + 1) >> 1;
03315     v7 = t;
03316 
03317     // stage 2
03318     t = (v0 - v3 + 1) >> 1;
03319     v0 = (v0 + v3 + 1) >> 1;
03320     v3 = t;
03321     t = (v1 - v2 + 1) >> 1;
03322     v1 = (v1 + v2 + 1) >> 1;
03323     v2 = t;
03324     t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
03325     v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
03326     v7 = t;
03327     t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
03328     v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
03329     v6 = t;
03330 
03331     // stage 1
03332     p[0*8] = v0 + v7;
03333     p[7*8] = v0 - v7;
03334     p[1*8] = v1 + v6;
03335     p[6*8] = v1 - v6;
03336     p[2*8] = v2 + v5;
03337     p[5*8] = v2 - v5;
03338     p[3*8] = v3 + v4;
03339     p[4*8] = v3 - v4;
03340   }
03341 
03342   // convert to 8-bit integers
03343   for (i = 0; i < 64; ++i) {
03344     dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)];
03345   }
03346 }
03347 
03348 int DCTStream::readHuffSym(DCTHuffTable *table) {
03349   Gushort code;
03350   int bit;
03351   int codeBits;
03352 
03353   code = 0;
03354   codeBits = 0;
03355   do {
03356     // add a bit to the code
03357     if ((bit = readBit()) == EOF)
03358       return 9999;
03359     code = (code << 1) + bit;
03360     ++codeBits;
03361 
03362     // look up code
03363     if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
03364       code -= table->firstCode[codeBits];
03365       return table->sym[table->firstSym[codeBits] + code];
03366     }
03367   } while (codeBits < 16);
03368 
03369   error(getPos(), "Bad Huffman code in DCT stream");
03370   return 9999;
03371 }
03372 
03373 int DCTStream::readAmp(int size) {
03374   int amp, bit;
03375   int bits;
03376 
03377   amp = 0;
03378   for (bits = 0; bits < size; ++bits) {
03379     if ((bit = readBit()) == EOF)
03380       return 9999;
03381     amp = (amp << 1) + bit;
03382   }
03383   if (amp < (1 << (size - 1)))
03384     amp -= (1 << size) - 1;
03385   return amp;
03386 }
03387 
03388 int DCTStream::readBit() {
03389   int bit;
03390   int c, c2;
03391 
03392   if (inputBits == 0) {
03393     if ((c = str->getChar()) == EOF)
03394       return EOF;
03395     if (c == 0xff) {
03396       do {
03397     c2 = str->getChar();
03398       } while (c2 == 0xff);
03399       if (c2 != 0x00) {
03400     error(getPos(), "Bad DCT data: missing 00 after ff");
03401     return EOF;
03402       }
03403     }
03404     inputBuf = c;
03405     inputBits = 8;
03406   }
03407   bit = (inputBuf >> (inputBits - 1)) & 1;
03408   --inputBits;
03409   return bit;
03410 }
03411 
03412 GBool DCTStream::readHeader() {
03413   GBool doScan;
03414   int n;
03415   int c = 0;
03416   int i;
03417 
03418   // read headers
03419   doScan = gFalse;
03420   while (!doScan) {
03421     c = readMarker();
03422     switch (c) {
03423     case 0xc0:          // SOF0
03424       if (!readBaselineSOF()) {
03425     return gFalse;
03426       }
03427       break;
03428     case 0xc2:          // SOF2
03429       if (!readProgressiveSOF()) {
03430     return gFalse;
03431       }
03432       break;
03433     case 0xc4:          // DHT
03434       if (!readHuffmanTables()) {
03435     return gFalse;
03436       }
03437       break;
03438     case 0xd8:          // SOI
03439       break;
03440     case 0xd9:          // EOI
03441       return gFalse;
03442       break;
03443     case 0xda:          // SOS
03444       if (!readScanInfo()) {
03445     return gFalse;
03446       }
03447       doScan = gTrue;
03448       break;
03449     case 0xdb:          // DQT
03450       if (!readQuantTables()) {
03451     return gFalse;
03452       }
03453       break;
03454     case 0xdd:          // DRI
03455       if (!readRestartInterval()) {
03456     return gFalse;
03457       }
03458       break;
03459     case 0xee:          // APP14
03460       if (!readAdobeMarker()) {
03461     return gFalse;
03462       }
03463       break;
03464     case EOF:
03465       error(getPos(), "Bad DCT header");
03466       return gFalse;
03467     default:
03468       // skip APPn / COM / etc.
03469       if (c >= 0xe0) {
03470     n = read16() - 2;
03471     for (i = 0; i < n; ++i) {
03472       str->getChar();
03473     }
03474       } else {
03475     error(getPos(), "Unknown DCT marker <%02x>", c);
03476     return gFalse;
03477       }
03478       break;
03479     }
03480   }
03481 
03482   return gTrue;
03483 }
03484 
03485 GBool DCTStream::readBaselineSOF() {
03486   int length;
03487   int prec;
03488   int i;
03489   int c;
03490 
03491   length = read16();
03492   prec = str->getChar();
03493   height = read16();
03494   width = read16();
03495   numComps = str->getChar();
03496   if (numComps <= 0 || numComps > 4) {
03497      numComps = 0;
03498      error(getPos(), "Bad number of components in DCT stream");
03499      return gFalse;
03500   }
03501   if (prec != 8) {
03502     error(getPos(), "Bad DCT precision %d", prec);
03503     return gFalse;
03504   }
03505   for (i = 0; i < numComps; ++i) {
03506     compInfo[i].id = str->getChar();
03507     c = str->getChar();
03508     compInfo[i].hSample = (c >> 4) & 0x0f;
03509     compInfo[i].vSample = c & 0x0f;
03510     compInfo[i].quantTable = str->getChar();
03511   }
03512   progressive = gFalse;
03513   return gTrue;
03514 }
03515 
03516 GBool DCTStream::readProgressiveSOF() {
03517   int length;
03518   int prec;
03519   int i;
03520   int c;
03521 
03522   length = read16();
03523   prec = str->getChar();
03524   height = read16();
03525   width = read16();
03526   numComps = str->getChar();
03527   if (numComps <= 0 || numComps > 4) {
03528      numComps = 0;
03529      error(getPos(), "Bad number of components in DCT stream");
03530      return gFalse;
03531   }
03532   if (prec != 8) {
03533     error(getPos(), "Bad DCT precision %d", prec);
03534     return gFalse;
03535   }
03536   for (i = 0; i < numComps; ++i) {
03537     compInfo[i].id = str->getChar();
03538     c = str->getChar();
03539     compInfo[i].hSample = (c >> 4) & 0x0f;
03540     compInfo[i].vSample = c & 0x0f;
03541     compInfo[i].quantTable = str->getChar();
03542   }
03543   progressive = gTrue;
03544   return gTrue;
03545 }
03546 
03547 GBool DCTStream::readScanInfo() {
03548   int length;
03549   int id, c;
03550   int i, j;
03551 
03552   length = read16() - 2;
03553   scanInfo.numComps = str->getChar();
03554   if (scanInfo.numComps <= 0 || scanInfo.numComps > 4) {
03555      scanInfo.numComps = 0;
03556      error(getPos(), "Bad number of components in DCT stream");
03557      return gFalse;
03558   }
03559   --length;
03560   if (length != 2 * scanInfo.numComps + 3) {
03561     error(getPos(), "Bad DCT scan info block");
03562     return gFalse;
03563   }
03564   interleaved = scanInfo.numComps == numComps;
03565   for (j = 0; j < numComps; ++j) {
03566     scanInfo.comp[j] = gFalse;
03567   }
03568   for (i = 0; i < scanInfo.numComps; ++i) {
03569     id = str->getChar();
03570     for (j = 0; j < numComps; ++j) {
03571       if (id == compInfo[j].id) {
03572     break;
03573       }
03574     }
03575     if (j == numComps) {
03576       error(getPos(), "Bad DCT component ID in scan info block");
03577       return gFalse;
03578     }
03579     scanInfo.comp[j] = gTrue;
03580     c = str->getChar();
03581     scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f;
03582     scanInfo.acHuffTable[j] = c & 0x0f;
03583   }
03584   scanInfo.firstCoeff = str->getChar();
03585   scanInfo.lastCoeff = str->getChar();
03586   if (scanInfo.firstCoeff < 0 || scanInfo.lastCoeff > 63 ||
03587       scanInfo.firstCoeff > scanInfo.lastCoeff) {
03588     error(getPos(), "Bad DCT coefficient numbers in scan info block");
03589     return gFalse;
03590   }
03591   c = str->getChar();
03592   scanInfo.ah = (c >> 4) & 0x0f;
03593   scanInfo.al = c & 0x0f;
03594   return gTrue;
03595 }
03596 
03597 GBool DCTStream::readQuantTables() {
03598   int length;
03599   int i;
03600   int index;
03601 
03602   length = read16() - 2;
03603   while (length > 0) {
03604     index = str->getChar();
03605     if ((index & 0xf0) || index >= 4) {
03606       error(getPos(), "Bad DCT quantization table");
03607       return gFalse;
03608     }
03609     if (index == numQuantTables)
03610       numQuantTables = index + 1;
03611     for (i = 0; i < 64; ++i)
03612       quantTables[index][dctZigZag[i]] = str->getChar();
03613     length -= 65;
03614   }
03615   return gTrue;
03616 }
03617 
03618 GBool DCTStream::readHuffmanTables() {
03619   DCTHuffTable *tbl;
03620   int length;
03621   int index;
03622   Gushort code;
03623   Guchar sym;
03624   int i;
03625   int c;
03626 
03627   length = read16() - 2;
03628   while (length > 0) {
03629     index = str->getChar();
03630     --length;
03631     if ((index & ~0x10) >= 4 || (index & ~0x10) < 0) {
03632       error(getPos(), "Bad DCT Huffman table");
03633       return gFalse;
03634     }
03635     if (index & 0x10) {
03636       index &= 0x03;
03637       if (index >= numACHuffTables)
03638     numACHuffTables = index+1;
03639       tbl = &acHuffTables[index];
03640     } else {
03641       if (index >= numDCHuffTables)
03642     numDCHuffTables = index+1;
03643       tbl = &dcHuffTables[index];
03644     }
03645     sym = 0;
03646     code = 0;
03647     for (i = 1; i <= 16; ++i) {
03648       c = str->getChar();
03649       tbl->firstSym[i] = sym;
03650       tbl->firstCode[i] = code;
03651       tbl->numCodes[i] = c;
03652       sym += c;
03653       code = (code + c) << 1;
03654     }
03655     length -= 16;
03656     for (i = 0; i < sym; ++i)
03657       tbl->sym[i] = str->getChar();
03658     length -= sym;
03659   }
03660   return gTrue;
03661 }
03662 
03663 GBool DCTStream::readRestartInterval() {
03664   int length;
03665 
03666   length = read16();
03667   if (length != 4) {
03668     error(getPos(), "Bad DCT restart interval");
03669     return gFalse;
03670   }
03671   restartInterval = read16();
03672   return gTrue;
03673 }
03674 
03675 GBool DCTStream::readAdobeMarker() {
03676   int length, i;
03677   char buf[12];
03678   int c;
03679 
03680   length = read16();
03681   if (length < 14) {
03682     goto err;
03683   }
03684   for (i = 0; i < 12; ++i) {
03685     if ((c = str->getChar()) == EOF) {
03686       goto err;
03687     }
03688     buf[i] = c;
03689   }
03690   if (strncmp(buf, "Adobe", 5)) {
03691     goto err;
03692   }
03693   colorXform = buf[11];
03694   gotAdobeMarker = gTrue;
03695   for (i = 14; i < length; ++i) {
03696     if (str->getChar() == EOF) {
03697       goto err;
03698     }
03699   }
03700   return gTrue;
03701 
03702  err:
03703   error(getPos(), "Bad DCT Adobe APP14 marker");
03704   return gFalse;
03705 }
03706 
03707 GBool DCTStream::readTrailer() {
03708   int c;
03709 
03710   c = readMarker();
03711   if (c != 0xd9) {      // EOI
03712     error(getPos(), "Bad DCT trailer");
03713     return gFalse;
03714   }
03715   return gTrue;
03716 }
03717 
03718 int DCTStream::readMarker() {
03719   int c;
03720 
03721   do {
03722     do {
03723       c = str->getChar();
03724       if(c == EOF) return EOF;
03725     } while (c != 0xff);
03726     do {
03727       c = str->getChar();
03728       if(c == EOF) return EOF;
03729     } while (c == 0xff);
03730   } while (c == 0x00);
03731   return c;
03732 }
03733 
03734 int DCTStream::read16() {
03735   int c1, c2;
03736 
03737   if ((c1 = str->getChar()) == EOF)
03738     return EOF;
03739   if ((c2 = str->getChar()) == EOF)
03740     return EOF;
03741   return (c1 << 8) + c2;
03742 }
03743 
03744 GString *DCTStream::getPSFilter(const char *indent) {
03745   GString *s;
03746 
03747   if (!(s = str->getPSFilter(indent))) {
03748     return NULL;
03749   }
03750   s->append(indent)->append("<< >> /DCTDecode filter\n");
03751   return s;
03752 }
03753 
03754 GBool DCTStream::isBinary(GBool /*last*/) {
03755   return str->isBinary(gTrue);
03756 }
03757 
03758 //------------------------------------------------------------------------
03759 // FlateStream
03760 //------------------------------------------------------------------------
03761 
03762 int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
03763   16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
03764 };
03765 
03766 FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
03767   {0,   3},
03768   {0,   4},
03769   {0,   5},
03770   {0,   6},
03771   {0,   7},
03772   {0,   8},
03773   {0,   9},
03774   {0,  10},
03775   {1,  11},
03776   {1,  13},
03777   {1,  15},
03778   {1,  17},
03779   {2,  19},
03780   {2,  23},
03781   {2,  27},
03782   {2,  31},
03783   {3,  35},
03784   {3,  43},
03785   {3,  51},
03786   {3,  59},
03787   {4,  67},
03788   {4,  83},
03789   {4,  99},
03790   {4, 115},
03791   {5, 131},
03792   {5, 163},
03793   {5, 195},
03794   {5, 227},
03795   {0, 258}
03796 };
03797 
03798 FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
03799   { 0,     1},
03800   { 0,     2},
03801   { 0,     3},
03802   { 0,     4},
03803   { 1,     5},
03804   { 1,     7},
03805   { 2,     9},
03806   { 2,    13},
03807   { 3,    17},
03808   { 3,    25},
03809   { 4,    33},
03810   { 4,    49},
03811   { 5,    65},
03812   { 5,    97},
03813   { 6,   129},
03814   { 6,   193},
03815   { 7,   257},
03816   { 7,   385},
03817   { 8,   513},
03818   { 8,   769},
03819   { 9,  1025},
03820   { 9,  1537},
03821   {10,  2049},
03822   {10,  3073},
03823   {11,  4097},
03824   {11,  6145},
03825   {12,  8193},
03826   {12, 12289},
03827   {13, 16385},
03828   {13, 24577}
03829 };
03830 
03831 FlateStream::FlateStream(Stream *strA, int predictor, int columns,
03832              int colors, int bits):
03833     FilterStream(strA) {
03834   if (predictor != 1) {
03835     pred = new StreamPredictor(this, predictor, columns, colors, bits);
03836     if ( !pred->isOk()) {
03837         delete pred;
03838         pred = NULL;
03839     }
03840   } else {
03841     pred = NULL;
03842   }
03843   litCodeTab.codes = NULL;
03844   distCodeTab.codes = NULL;
03845 }
03846 
03847 FlateStream::~FlateStream() {
03848   gfree(litCodeTab.codes);
03849   gfree(distCodeTab.codes);
03850   if (pred) {
03851     delete pred;
03852   }
03853   delete str;
03854 }
03855 
03856 void FlateStream::reset() {
03857   int cmf, flg;
03858 
03859   index = 0;
03860   remain = 0;
03861   codeBuf = 0;
03862   codeSize = 0;
03863   compressedBlock = gFalse;
03864   endOfBlock = gTrue;
03865   eof = gTrue;
03866 
03867   str->reset();
03868 
03869   // read header
03870   //~ need to look at window size?
03871   endOfBlock = eof = gTrue;
03872   cmf = str->getChar();
03873   flg = str->getChar();
03874   if (cmf == EOF || flg == EOF)
03875     return;
03876   if ((cmf & 0x0f) != 0x08) {
03877     error(getPos(), "Unknown compression method in flate stream");
03878     return;
03879   }
03880   if ((((cmf << 8) + flg) % 31) != 0) {
03881     error(getPos(), "Bad FCHECK in flate stream");
03882     return;
03883   }
03884   if (flg & 0x20) {
03885     error(getPos(), "FDICT bit set in flate stream");
03886     return;
03887   }
03888 
03889   eof = gFalse;
03890 }
03891 
03892 int FlateStream::getChar() {
03893   int c;
03894 
03895   if (pred) {
03896     return pred->getChar();
03897   }
03898   while (remain == 0) {
03899     if (endOfBlock && eof)
03900       return EOF;
03901     readSome();
03902   }
03903   c = buf[index];
03904   index = (index + 1) & flateMask;
03905   --remain;
03906   return c;
03907 }
03908 
03909 int FlateStream::lookChar() {
03910   int c;
03911 
03912   if (pred) {
03913     return pred->lookChar();
03914   }
03915   while (remain == 0) {
03916     if (endOfBlock && eof)
03917       return EOF;
03918     readSome();
03919   }
03920   c = buf[index];
03921   return c;
03922 }
03923 
03924 int FlateStream::getRawChar() {
03925   int c;
03926 
03927   while (remain == 0) {
03928     if (endOfBlock && eof)
03929       return EOF;
03930     readSome();
03931   }
03932   c = buf[index];
03933   index = (index + 1) & flateMask;
03934   --remain;
03935   return c;
03936 }
03937 
03938 GString *FlateStream::getPSFilter(const char */*indent*/) {
03939   return NULL;
03940 }
03941 
03942 GBool FlateStream::isBinary(GBool /*last*/) {
03943   return str->isBinary(gTrue);
03944 }
03945 
03946 void FlateStream::readSome() {
03947   int code1, code2;
03948   int len, dist;
03949   int i, j, k;
03950   int c;
03951 
03952   if (endOfBlock) {
03953     if (!startBlock())
03954       return;
03955   }
03956 
03957   if (compressedBlock) {
03958     if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
03959       goto err;
03960     if (code1 < 256) {
03961       buf[index] = code1;
03962       remain = 1;
03963     } else if (code1 == 256) {
03964       endOfBlock = gTrue;
03965       remain = 0;
03966     } else {
03967       code1 -= 257;
03968       code2 = lengthDecode[code1].bits;
03969       if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
03970     goto err;
03971       len = lengthDecode[code1].first + code2;
03972       if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
03973     goto err;
03974       code2 = distDecode[code1].bits;
03975       if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
03976     goto err;
03977       dist = distDecode[code1].first + code2;
03978       i = index;
03979       j = (index - dist) & flateMask;
03980       for (k = 0; k < len; ++k) {
03981     buf[i] = buf[j];
03982     i = (i + 1) & flateMask;
03983     j = (j + 1) & flateMask;
03984       }
03985       remain = len;
03986     }
03987 
03988   } else {
03989     len = (blockLen < flateWindow) ? blockLen : flateWindow;
03990     for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
03991       if ((c = str->getChar()) == EOF) {
03992     endOfBlock = eof = gTrue;
03993     break;
03994       }
03995       buf[j] = c & 0xff;
03996     }
03997     remain = i;
03998     blockLen -= len;
03999     if (blockLen == 0)
04000       endOfBlock = gTrue;
04001   }
04002 
04003   return;
04004 
04005 err:
04006   error(getPos(), "Unexpected end of file in flate stream");
04007   endOfBlock = eof = gTrue;
04008   remain = 0;
04009 }
04010 
04011 GBool FlateStream::startBlock() {
04012   int blockHdr;
04013   int c;
04014   int check;
04015 
04016   // free the code tables from the previous block
04017   gfree(litCodeTab.codes);
04018   litCodeTab.codes = NULL;
04019   gfree(distCodeTab.codes);
04020   distCodeTab.codes = NULL;
04021 
04022   // read block header
04023   blockHdr = getCodeWord(3);
04024   if (blockHdr & 1)
04025     eof = gTrue;
04026   blockHdr >>= 1;
04027 
04028   // uncompressed block
04029   if (blockHdr == 0) {
04030     compressedBlock = gFalse;
04031     if ((c = str->getChar()) == EOF)
04032       goto err;
04033     blockLen = c & 0xff;
04034     if ((c = str->getChar()) == EOF)
04035       goto err;
04036     blockLen |= (c & 0xff) << 8;
04037     if ((c = str->getChar()) == EOF)
04038       goto err;
04039     check = c & 0xff;
04040     if ((c = str->getChar()) == EOF)
04041       goto err;
04042     check |= (c & 0xff) << 8;
04043     if (check != (~blockLen & 0xffff))
04044       error(getPos(), "Bad uncompressed block length in flate stream");
04045     codeBuf = 0;
04046     codeSize = 0;
04047 
04048   // compressed block with fixed codes
04049   } else if (blockHdr == 1) {
04050     compressedBlock = gTrue;
04051     loadFixedCodes();
04052 
04053   // compressed block with dynamic codes
04054   } else if (blockHdr == 2) {
04055     compressedBlock = gTrue;
04056     if (!readDynamicCodes()) {
04057       goto err;
04058     }
04059 
04060   // unknown block type
04061   } else {
04062     goto err;
04063   }
04064 
04065   endOfBlock = gFalse;
04066   return gTrue;
04067 
04068 err:
04069   error(getPos(), "Bad block header in flate stream");
04070   endOfBlock = eof = gTrue;
04071   return gFalse;
04072 }
04073 
04074 void FlateStream::loadFixedCodes() {
04075   int i;
04076 
04077   // build the literal code table
04078   for (i = 0; i <= 143; ++i) {
04079     codeLengths[i] = 8;
04080   }
04081   for (i = 144; i <= 255; ++i) {
04082     codeLengths[i] = 9;
04083   }
04084   for (i = 256; i <= 279; ++i) {
04085     codeLengths[i] = 7;
04086   }
04087   for (i = 280; i <= 287; ++i) {
04088     codeLengths[i] = 8;
04089   }
04090   compHuffmanCodes(codeLengths, flateMaxLitCodes, &litCodeTab);
04091 
04092   // build the distance code table
04093   for (i = 0; i < flateMaxDistCodes; ++i) {
04094     codeLengths[i] = 5;
04095   }
04096   compHuffmanCodes(codeLengths, flateMaxDistCodes, &distCodeTab);
04097 }
04098 
04099 GBool FlateStream::readDynamicCodes() {
04100   int numCodeLenCodes;
04101   int numLitCodes;
04102   int numDistCodes;
04103   int codeLenCodeLengths[flateMaxCodeLenCodes];
04104   FlateHuffmanTab codeLenCodeTab;
04105   int len, repeat, code;
04106   int i;
04107 
04108   // read lengths
04109   if ((numLitCodes = getCodeWord(5)) == EOF) {
04110     goto err;
04111   }
04112   numLitCodes += 257;
04113   if ((numDistCodes = getCodeWord(5)) == EOF) {
04114     goto err;
04115   }
04116   numDistCodes += 1;
04117   if ((numCodeLenCodes = getCodeWord(4)) == EOF) {
04118     goto err;
04119   }
04120   numCodeLenCodes += 4;
04121   if (numLitCodes > flateMaxLitCodes ||
04122       numDistCodes > flateMaxDistCodes ||
04123       numCodeLenCodes > flateMaxCodeLenCodes) {
04124     goto err;
04125   }
04126 
04127   // build the code length code table
04128   for (i = 0; i < flateMaxCodeLenCodes; ++i) {
04129     codeLenCodeLengths[i] = 0;
04130   }
04131   for (i = 0; i < numCodeLenCodes; ++i) {
04132     if ((codeLenCodeLengths[codeLenCodeMap[i]] = getCodeWord(3)) == -1) {
04133       goto err;
04134     }
04135   }
04136   compHuffmanCodes(codeLenCodeLengths, flateMaxCodeLenCodes, &codeLenCodeTab);
04137 
04138   // build the literal and distance code tables
04139   len = 0;
04140   repeat = 0;
04141   i = 0;
04142   while (i < numLitCodes + numDistCodes) {
04143     if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF) {
04144       goto err;
04145     }
04146     if (code == 16) {
04147       if ((repeat = getCodeWord(2)) == EOF) {
04148     goto err;
04149       }
04150       for (repeat += 3; repeat > 0; --repeat) {
04151     codeLengths[i++] = len;
04152       }
04153     } else if (code == 17) {
04154       if ((repeat = getCodeWord(3)) == EOF) {
04155     goto err;
04156       }
04157       len = 0;
04158       for (repeat += 3; repeat > 0; --repeat) {
04159     codeLengths[i++] = 0;
04160       }
04161     } else if (code == 18) {
04162       if ((repeat = getCodeWord(7)) == EOF) {
04163     goto err;
04164       }
04165       len = 0;
04166       for (repeat += 11; repeat > 0; --repeat) {
04167     codeLengths[i++] = 0;
04168       }
04169     } else {
04170       codeLengths[i++] = len = code;
04171     }
04172   }
04173   compHuffmanCodes(codeLengths, numLitCodes, &litCodeTab);
04174   compHuffmanCodes(codeLengths + numLitCodes, numDistCodes, &distCodeTab);
04175 
04176   gfree(codeLenCodeTab.codes);
04177   return gTrue;
04178 
04179 err:
04180   error(getPos(), "Bad dynamic code table in flate stream");
04181   gfree(codeLenCodeTab.codes);
04182   return gFalse;
04183 }
04184 
04185 // Convert an array <lengths> of <n> lengths, in value order, into a
04186 // Huffman code lookup table.
04187 void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) {
04188   int tabSize, len, code, code2, skip, val, i, t;
04189 
04190   // find max code length
04191   tab->maxLen = 0;
04192   for (val = 0; val < n; ++val) {
04193     if (lengths[val] > tab->maxLen) {
04194       tab->maxLen = lengths[val];
04195     }
04196   }
04197 
04198   // allocate the table
04199   tabSize = 1 << tab->maxLen;
04200   tab->codes = (FlateCode *)gmalloc(tabSize * sizeof(FlateCode));
04201 
04202   // clear the table
04203   for (i = 0; i < tabSize; ++i) {
04204     tab->codes[i].len = 0;
04205     tab->codes[i].val = 0;
04206   }
04207 
04208   // build the table
04209   for (len = 1, code = 0, skip = 2;
04210        len <= tab->maxLen;
04211        ++len, code <<= 1, skip <<= 1) {
04212     for (val = 0; val < n; ++val) {
04213       if (lengths[val] == len) {
04214 
04215     // bit-reverse the code
04216     code2 = 0;
04217     t = code;
04218     for (i = 0; i < len; ++i) {
04219       code2 = (code2 << 1) | (t & 1);
04220       t >>= 1;
04221     }
04222 
04223     // fill in the table entries
04224     for (i = code2; i < tabSize; i += skip) {
04225       tab->codes[i].len = (Gushort)len;
04226       tab->codes[i].val = (Gushort)val;
04227     }
04228 
04229     ++code;
04230       }
04231     }
04232   }
04233 }
04234 
04235 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
04236   FlateCode *code;
04237   int c;
04238 
04239   while (codeSize < tab->maxLen) {
04240     if ((c = str->getChar()) == EOF) {
04241       break;
04242     }
04243     codeBuf |= (c & 0xff) << codeSize;
04244     codeSize += 8;
04245   }
04246   code = &tab->codes[codeBuf & ((1 << tab->maxLen) - 1)];
04247   if (codeSize == 0 || codeSize < code->len || code->len == 0) {
04248     return EOF;
04249   }
04250   codeBuf >>= code->len;
04251   codeSize -= code->len;
04252   return (int)code->val;
04253 }
04254 
04255 int FlateStream::getCodeWord(int bits) {
04256   int c;
04257 
04258   while (codeSize < bits) {
04259     if ((c = str->getChar()) == EOF)
04260       return EOF;
04261     codeBuf |= (c & 0xff) << codeSize;
04262     codeSize += 8;
04263   }
04264   c = codeBuf & ((1 << bits) - 1);
04265   codeBuf >>= bits;
04266   codeSize -= bits;
04267   return c;
04268 }
04269 
04270 //------------------------------------------------------------------------
04271 // EOFStream
04272 //------------------------------------------------------------------------
04273 
04274 EOFStream::EOFStream(Stream *strA):
04275     FilterStream(strA) {
04276 }
04277 
04278 EOFStream::~EOFStream() {
04279   delete str;
04280 }
04281 
04282 //------------------------------------------------------------------------
04283 // FixedLengthEncoder
04284 //------------------------------------------------------------------------
04285 
04286 FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
04287     FilterStream(strA) {
04288   length = lengthA;
04289   count = 0;
04290 }
04291 
04292 FixedLengthEncoder::~FixedLengthEncoder() {
04293   if (str->isEncoder())
04294     delete str;
04295 }
04296 
04297 void FixedLengthEncoder::reset() {
04298   str->reset();
04299   count = 0;
04300 }
04301 
04302 void FixedLengthEncoder::close() {
04303 }
04304 
04305 int FixedLengthEncoder::getChar() {
04306   if (length >= 0 && count >= length)
04307     return EOF;
04308   ++count;
04309   return str->getChar();
04310 }
04311 
04312 int FixedLengthEncoder::lookChar() {
04313   if (length >= 0 && count >= length)
04314     return EOF;
04315   return str->getChar();
04316 }
04317 
04318 //------------------------------------------------------------------------
04319 // ASCIIHexEncoder
04320 //------------------------------------------------------------------------
04321 
04322 ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
04323     FilterStream(strA) {
04324   bufPtr = bufEnd = buf;
04325   lineLen = 0;
04326   eof = gFalse;
04327 }
04328 
04329 ASCIIHexEncoder::~ASCIIHexEncoder() {
04330   if (str->isEncoder()) {
04331     delete str;
04332   }
04333 }
04334 
04335 void ASCIIHexEncoder::reset() {
04336   str->reset();
04337   bufPtr = bufEnd = buf;
04338   lineLen = 0;
04339   eof = gFalse;
04340 }
04341 
04342 void ASCIIHexEncoder::close() {
04343 }
04344 
04345 GBool ASCIIHexEncoder::fillBuf() {
04346   static const char *hex = "0123456789abcdef";
04347   int c;
04348 
04349   if (eof) {
04350     return gFalse;
04351   }
04352   bufPtr = bufEnd = buf;
04353   if ((c = str->getChar()) == EOF) {
04354     *bufEnd++ = '>';
04355     eof = gTrue;
04356   } else {
04357     if (lineLen >= 64) {
04358       *bufEnd++ = '\n';
04359       lineLen = 0;
04360     }
04361     *bufEnd++ = hex[(c >> 4) & 0x0f];
04362     *bufEnd++ = hex[c & 0x0f];
04363     lineLen += 2;
04364   }
04365   return gTrue;
04366 }
04367 
04368 //------------------------------------------------------------------------
04369 // ASCII85Encoder
04370 //------------------------------------------------------------------------
04371 
04372 ASCII85Encoder::ASCII85Encoder(Stream *strA):
04373     FilterStream(strA) {
04374   bufPtr = bufEnd = buf;
04375   lineLen = 0;
04376   eof = gFalse;
04377 }
04378 
04379 ASCII85Encoder::~ASCII85Encoder() {
04380   if (str->isEncoder())
04381     delete str;
04382 }
04383 
04384 void ASCII85Encoder::reset() {
04385   str->reset();
04386   bufPtr = bufEnd = buf;
04387   lineLen = 0;
04388   eof = gFalse;
04389 }
04390 
04391 void ASCII85Encoder::close() {
04392 }
04393 
04394 GBool ASCII85Encoder::fillBuf() {
04395   Gulong t;
04396   char buf1[5];
04397   int c;
04398   int n, i;
04399 
04400   if (eof)
04401     return gFalse;
04402   t = 0;
04403   for (n = 0; n < 4; ++n) {
04404     if ((c = str->getChar()) == EOF)
04405       break;
04406     t = (t << 8) + c;
04407   }
04408   bufPtr = bufEnd = buf;
04409   if (n > 0) {
04410     if (n == 4 && t == 0) {
04411       *bufEnd++ = 'z';
04412       if (++lineLen == 65) {
04413     *bufEnd++ = '\n';
04414     lineLen = 0;
04415       }
04416     } else {
04417       if (n < 4)
04418     t <<= 8 * (4 - n);
04419       for (i = 4; i >= 0; --i) {
04420     buf1[i] = (char)(t % 85 + 0x21);
04421     t /= 85;
04422       }
04423       for (i = 0; i <= n; ++i) {
04424     *bufEnd++ = buf1[i];
04425     if (++lineLen == 65) {
04426       *bufEnd++ = '\n';
04427       lineLen = 0;
04428     }
04429       }
04430     }
04431   }
04432   if (n < 4) {
04433     *bufEnd++ = '~';
04434     *bufEnd++ = '>';
04435     eof = gTrue;
04436   }
04437   return bufPtr < bufEnd;
04438 }
04439 
04440 //------------------------------------------------------------------------
04441 // RunLengthEncoder
04442 //------------------------------------------------------------------------
04443 
04444 RunLengthEncoder::RunLengthEncoder(Stream *strA):
04445     FilterStream(strA) {
04446   bufPtr = bufEnd = nextEnd = buf;
04447   eof = gFalse;
04448 }
04449 
04450 RunLengthEncoder::~RunLengthEncoder() {
04451   if (str->isEncoder())
04452     delete str;
04453 }
04454 
04455 void RunLengthEncoder::reset() {
04456   str->reset();
04457   bufPtr = bufEnd = nextEnd = buf;
04458   eof = gFalse;
04459 }
04460 
04461 void RunLengthEncoder::close() {
04462 }
04463 
04464 //
04465 // When fillBuf finishes, buf[] looks like this:
04466 //   +-----+--------------+-----------------+--
04467 //   + tag | ... data ... | next 0, 1, or 2 |
04468 //   +-----+--------------+-----------------+--
04469 //    ^                    ^                 ^
04470 //    bufPtr               bufEnd            nextEnd
04471 //
04472 GBool RunLengthEncoder::fillBuf() {
04473   int c, c1, c2;
04474   int n;
04475 
04476   // already hit EOF?
04477   if (eof)
04478     return gFalse;
04479 
04480   // grab two bytes
04481   if (nextEnd < bufEnd + 1) {
04482     if ((c1 = str->getChar()) == EOF) {
04483       eof = gTrue;
04484       return gFalse;
04485     }
04486   } else {
04487     c1 = bufEnd[0] & 0xff;
04488   }
04489   if (nextEnd < bufEnd + 2) {
04490     if ((c2 = str->getChar()) == EOF) {
04491       eof = gTrue;
04492       buf[0] = 0;
04493       buf[1] = c1;
04494       bufPtr = buf;
04495       bufEnd = &buf[2];
04496       return gTrue;
04497     }
04498   } else {
04499     c2 = bufEnd[1] & 0xff;
04500   }
04501 
04502   // check for repeat
04503   c = 0; // make gcc happy
04504   if (c1 == c2) {
04505     n = 2;
04506     while (n < 128 && (c = str->getChar()) == c1)
04507       ++n;
04508     buf[0] = (char)(257 - n);
04509     buf[1] = c1;
04510     bufEnd = &buf[2];
04511     if (c == EOF) {
04512       eof = gTrue;
04513     } else if (n < 128) {
04514       buf[2] = c;
04515       nextEnd = &buf[3];
04516     } else {
04517       nextEnd = bufEnd;
04518     }
04519 
04520   // get up to 128 chars
04521   } else {
04522     buf[1] = c1;
04523     buf[2] = c2;
04524     n = 2;
04525     while (n < 128) {
04526       if ((c = str->getChar()) == EOF) {
04527     eof = gTrue;
04528     break;
04529       }
04530       ++n;
04531       buf[n] = c;
04532       if (buf[n] == buf[n-1])
04533     break;
04534     }
04535     if (buf[n] == buf[n-1]) {
04536       buf[0] = (char)(n-2-1);
04537       bufEnd = &buf[n-1];
04538       nextEnd = &buf[n+1];
04539     } else {
04540       buf[0] = (char)(n-1);
04541       bufEnd = nextEnd = &buf[n+1];
04542     }
04543   }
04544   bufPtr = buf;
04545   return gTrue;
04546 }
KDE Home | KDE Accessibility Home | Description of Access Keys