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