Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Stream.cc

Go to the documentation of this file.
00001 //========================================================================
00002 //
00003 // Stream.cc
00004 //
00005 // Copyright 1996-2002 Glyph & Cog, LLC
00006 //
00007 //========================================================================
00008 
00009 #ifdef __GNUC__
00010 #pragma implementation
00011 #endif
00012 
00013 #include <aconf.h>
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 #include <stddef.h>
00017 #ifndef WIN32
00018 #include <unistd.h>
00019 #endif
00020 #include <string.h>
00021 #include <ctype.h>
00022 #include "gmem.h"
00023 #include "gfile.h"
00024 #include "config.h"
00025 #include "Error.h"
00026 #include "Object.h"
00027 #ifndef NO_DECRYPTION
00028 #include "Decrypt.h"
00029 #endif
00030 #include "Stream.h"
00031 #include "Stream-CCITT.h"
00032 
00033 #ifdef __DJGPP__
00034 static GBool setDJSYSFLAGS = gFalse;
00035 #endif
00036 
00037 #ifdef VMS
00038 #if (__VMS_VER < 70000000)
00039 extern "C" int unlink(char *filename);
00040 #endif
00041 #ifdef __GNUC__
00042 #define SEEK_SET 0
00043 #define SEEK_CUR 1
00044 #define SEEK_END 2
00045 #endif
00046 #endif
00047 
00048 #ifdef MACOS
00049 #include "StuffItEngineLib.h"
00050 #endif
00051 
00052 //------------------------------------------------------------------------
00053 // Stream (base class)
00054 //------------------------------------------------------------------------
00055 
00056 Stream::Stream() {
00057   ref = 1;
00058 }
00059 
00060 Stream::~Stream() {
00061 }
00062 
00063 void Stream::close() {
00064 }
00065 
00066 int Stream::getRawChar() {
00067   error(-1, "Internal: called getRawChar() on non-predictor stream");
00068   return EOF;
00069 }
00070 
00071 char *Stream::getLine(char *buf, int size) {
00072   int i;
00073   int c;
00074 
00075   if (lookChar() == EOF)
00076     return NULL;
00077   for (i = 0; i < size - 1; ++i) {
00078     c = getChar();
00079     if (c == EOF || c == '\n')
00080       break;
00081     if (c == '\r') {
00082       if ((c = lookChar()) == '\n')
00083         getChar();
00084       break;
00085     }
00086     buf[i] = c;
00087   }
00088   buf[i] = '\0';
00089   return buf;
00090 }
00091 
00092 GString *Stream::getPSFilter(char *indent) {
00093   return new GString();
00094 }
00095 
00096 Stream *Stream::addFilters(Object *dict) {
00097   Object obj, obj2;
00098   Object params, params2;
00099   Stream *str;
00100   int i;
00101 
00102   str = this;
00103   dict->dictLookup("Filter", &obj);
00104   if (obj.isNull()) {
00105     obj.free();
00106     dict->dictLookup("F", &obj);
00107   }
00108   dict->dictLookup("DecodeParms", &params);
00109   if (params.isNull()) {
00110     params.free();
00111     dict->dictLookup("DP", &params);
00112   }
00113   if (obj.isName()) {
00114     str = makeFilter(obj.getName(), str, &params);
00115   } else if (obj.isArray()) {
00116     for (i = 0; i < obj.arrayGetLength(); ++i) {
00117       obj.arrayGet(i, &obj2);
00118       if (params.isArray())
00119         params.arrayGet(i, &params2);
00120       else
00121         params2.initNull();
00122       if (obj2.isName()) {
00123         str = makeFilter(obj2.getName(), str, &params2);
00124       } else {
00125         error(getPos(), "Bad filter name");
00126         str = new EOFStream(str);
00127       }
00128       obj2.free();
00129       params2.free();
00130     }
00131   } else if (!obj.isNull()) {
00132     error(getPos(), "Bad 'Filter' attribute in stream");
00133   }
00134   obj.free();
00135   params.free();
00136 
00137   return str;
00138 }
00139 
00140 Stream *Stream::makeFilter(char *name, Stream *str, Object *params) {
00141   int pred;                     // parameters
00142   int colors;
00143   int bits;
00144   int early;
00145   int encoding;
00146   GBool endOfLine, byteAlign, endOfBlock, black;
00147   int columns, rows;
00148   Object obj;
00149 
00150   if (!strcmp(name, "ASCIIHexDecode") || !strcmp(name, "AHx")) {
00151     str = new ASCIIHexStream(str);
00152   } else if (!strcmp(name, "ASCII85Decode") || !strcmp(name, "A85")) {
00153     str = new ASCII85Stream(str);
00154   } else if (!strcmp(name, "LZWDecode") || !strcmp(name, "LZW")) {
00155     pred = 1;
00156     columns = 1;
00157     colors = 1;
00158     bits = 8;
00159     early = 1;
00160     if (params->isDict()) {
00161       params->dictLookup("Predictor", &obj);
00162       if (obj.isInt())
00163         pred = obj.getInt();
00164       obj.free();
00165       params->dictLookup("Columns", &obj);
00166       if (obj.isInt())
00167         columns = obj.getInt();
00168       obj.free();
00169       params->dictLookup("Colors", &obj);
00170       if (obj.isInt())
00171         colors = obj.getInt();
00172       obj.free();
00173       params->dictLookup("BitsPerComponent", &obj);
00174       if (obj.isInt())
00175         bits = obj.getInt();
00176       obj.free();
00177       params->dictLookup("EarlyChange", &obj);
00178       if (obj.isInt())
00179         early = obj.getInt();
00180       obj.free();
00181     }
00182     str = new LZWStream(str, pred, columns, colors, bits, early);
00183   } else if (!strcmp(name, "RunLengthDecode") || !strcmp(name, "RL")) {
00184     str = new RunLengthStream(str);
00185   } else if (!strcmp(name, "CCITTFaxDecode") || !strcmp(name, "CCF")) {
00186     encoding = 0;
00187     endOfLine = gFalse;
00188     byteAlign = gFalse;
00189     columns = 1728;
00190     rows = 0;
00191     endOfBlock = gTrue;
00192     black = gFalse;
00193     if (params->isDict()) {
00194       params->dictLookup("K", &obj);
00195       if (obj.isInt()) {
00196         encoding = obj.getInt();
00197       }
00198       obj.free();
00199       params->dictLookup("EndOfLine", &obj);
00200       if (obj.isBool()) {
00201         endOfLine = obj.getBool();
00202       }
00203       obj.free();
00204       params->dictLookup("EncodedByteAlign", &obj);
00205       if (obj.isBool()) {
00206         byteAlign = obj.getBool();
00207       }
00208       obj.free();
00209       params->dictLookup("Columns", &obj);
00210       if (obj.isInt()) {
00211         columns = obj.getInt();
00212       }
00213       obj.free();
00214       params->dictLookup("Rows", &obj);
00215       if (obj.isInt()) {
00216         rows = obj.getInt();
00217       }
00218       obj.free();
00219       params->dictLookup("EndOfBlock", &obj);
00220       if (obj.isBool()) {
00221         endOfBlock = obj.getBool();
00222       }
00223       obj.free();
00224       params->dictLookup("BlackIs1", &obj);
00225       if (obj.isBool()) {
00226         black = obj.getBool();
00227       }
00228       obj.free();
00229     }
00230     str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign,
00231                              columns, rows, endOfBlock, black);
00232   } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
00233     str = new DCTStream(str);
00234   } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
00235     pred = 1;
00236     columns = 1;
00237     colors = 1;
00238     bits = 8;
00239     if (params->isDict()) {
00240       params->dictLookup("Predictor", &obj);
00241       if (obj.isInt())
00242         pred = obj.getInt();
00243       obj.free();
00244       params->dictLookup("Columns", &obj);
00245       if (obj.isInt())
00246         columns = obj.getInt();
00247       obj.free();
00248       params->dictLookup("Colors", &obj);
00249       if (obj.isInt())
00250         colors = obj.getInt();
00251       obj.free();
00252       params->dictLookup("BitsPerComponent", &obj);
00253       if (obj.isInt())
00254         bits = obj.getInt();
00255       obj.free();
00256     }
00257     str = new FlateStream(str, pred, columns, colors, bits);
00258   } else {
00259     error(getPos(), "Unknown filter '%s'", name);
00260     str = new EOFStream(str);
00261   }
00262   return str;
00263 }
00264 
00265 //------------------------------------------------------------------------
00266 // BaseStream
00267 //------------------------------------------------------------------------
00268 
00269 BaseStream::BaseStream(Object *dictA) {
00270   dict = *dictA;
00271 #ifndef NO_DECRYPTION
00272   decrypt = NULL;
00273 #endif
00274 }
00275 
00276 BaseStream::~BaseStream() {
00277   dict.free();
00278 #ifndef NO_DECRYPTION
00279   if (decrypt)
00280     delete decrypt;
00281 #endif
00282 }
00283 
00284 #ifndef NO_DECRYPTION
00285 void BaseStream::doDecryption(Guchar *fileKey, int keyLength,
00286                               int objNum, int objGen) {
00287   decrypt = new Decrypt(fileKey, keyLength, objNum, objGen);
00288 }
00289 #endif
00290 
00291 //------------------------------------------------------------------------
00292 // FilterStream
00293 //------------------------------------------------------------------------
00294 
00295 FilterStream::FilterStream(Stream *strA) {
00296   str = strA;
00297 }
00298 
00299 FilterStream::~FilterStream() {
00300 }
00301 
00302 void FilterStream::close() {
00303   str->close();
00304 }
00305 
00306 void FilterStream::setPos(Guint pos, int dir) {
00307   error(-1, "Internal: called setPos() on FilterStream");
00308 }
00309 
00310 //------------------------------------------------------------------------
00311 // ImageStream
00312 //------------------------------------------------------------------------
00313 
00314 ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) {
00315   int imgLineSize;
00316 
00317   str = strA;
00318   width = widthA;
00319   nComps = nCompsA;
00320   nBits = nBitsA;
00321 
00322   nVals = width * nComps;
00323   if (nBits == 1) {
00324     imgLineSize = (nVals + 7) & ~7;
00325   } else {
00326     imgLineSize = nVals;
00327   }
00328   imgLine = (Guchar *)gmalloc(imgLineSize * sizeof(Guchar));
00329   imgIdx = nVals;
00330 }
00331 
00332 ImageStream::~ImageStream() {
00333   gfree(imgLine);
00334 }
00335 
00336 void ImageStream::reset() {
00337   str->reset();
00338 }
00339 
00340 GBool ImageStream::getPixel(Guchar *pix) {
00341   Gulong buf, bitMask;
00342   int bits;
00343   int c;
00344   int i;
00345 
00346   if (imgIdx >= nVals) {
00347 
00348     // read one line of image pixels
00349     if (nBits == 1) {
00350       for (i = 0; i < nVals; i += 8) {
00351         c = str->getChar();
00352         imgLine[i+0] = (Guchar)((c >> 7) & 1);
00353         imgLine[i+1] = (Guchar)((c >> 6) & 1);
00354         imgLine[i+2] = (Guchar)((c >> 5) & 1);
00355         imgLine[i+3] = (Guchar)((c >> 4) & 1);
00356         imgLine[i+4] = (Guchar)((c >> 3) & 1);
00357         imgLine[i+5] = (Guchar)((c >> 2) & 1);
00358         imgLine[i+6] = (Guchar)((c >> 1) & 1);
00359         imgLine[i+7] = (Guchar)(c & 1);
00360       }
00361     } else if (nBits == 8) {
00362       for (i = 0; i < nVals; ++i) {
00363         imgLine[i] = str->getChar();
00364       }
00365     } else {
00366       bitMask = (1 << nBits) - 1;
00367       buf = 0;
00368       bits = 0;
00369       for (i = 0; i < nVals; ++i) {
00370         if (bits < nBits) {
00371           buf = (buf << 8) | (str->getChar() & 0xff);
00372           bits += 8;
00373         }
00374         imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask);
00375         bits -= nBits;
00376       }
00377     }
00378 
00379     // reset to start of line
00380     imgIdx = 0;
00381   }
00382 
00383   for (i = 0; i < nComps; ++i)
00384     pix[i] = imgLine[imgIdx++];
00385   return gTrue;
00386 }
00387 
00388 void ImageStream::skipLine() {
00389   int n, i;
00390 
00391   n = (nVals * nBits + 7) >> 3;
00392   for (i = 0; i < n; ++i) {
00393     str->getChar();
00394   }
00395 }
00396 
00397 //------------------------------------------------------------------------
00398 // StreamPredictor
00399 //------------------------------------------------------------------------
00400 
00401 StreamPredictor::StreamPredictor(Stream *strA, int predictorA,
00402                                  int widthA, int nCompsA, int nBitsA) {
00403   str = strA;
00404   predictor = predictorA;
00405   width = widthA;
00406   nComps = nCompsA;
00407   nBits = nBitsA;
00408 
00409   nVals = width * nComps;
00410   pixBytes = (nComps * nBits + 7) >> 3;
00411   rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
00412   predLine = (Guchar *)gmalloc(rowBytes);
00413   memset(predLine, 0, rowBytes);
00414   predIdx = rowBytes;
00415 }
00416 
00417 StreamPredictor::~StreamPredictor() {
00418   gfree(predLine);
00419 }
00420 
00421 int StreamPredictor::lookChar() {
00422   if (predIdx >= rowBytes) {
00423     if (!getNextLine()) {
00424       return EOF;
00425     }
00426   }
00427   return predLine[predIdx];
00428 }
00429 
00430 int StreamPredictor::getChar() {
00431   if (predIdx >= rowBytes) {
00432     if (!getNextLine()) {
00433       return EOF;
00434     }
00435   }
00436   return predLine[predIdx++];
00437 }
00438 
00439 GBool StreamPredictor::getNextLine() {
00440   int curPred;
00441   Guchar upLeftBuf[4];
00442   int left, up, upLeft, p, pa, pb, pc;
00443   int c;
00444   Gulong inBuf, outBuf, bitMask;
00445   int inBits, outBits;
00446   int i, j, k;
00447 
00448   // get PNG optimum predictor number
00449   if (predictor == 15) {
00450     if ((curPred = str->getRawChar()) == EOF) {
00451       return gFalse;
00452     }
00453     curPred += 10;
00454   } else {
00455     curPred = predictor;
00456   }
00457 
00458   // read the raw line, apply PNG (byte) predictor
00459   upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
00460   for (i = pixBytes; i < rowBytes; ++i) {
00461     upLeftBuf[3] = upLeftBuf[2];
00462     upLeftBuf[2] = upLeftBuf[1];
00463     upLeftBuf[1] = upLeftBuf[0];
00464     upLeftBuf[0] = predLine[i];
00465     if ((c = str->getRawChar()) == EOF) {
00466       break;
00467     }
00468     switch (curPred) {
00469     case 11:                    // PNG sub
00470       predLine[i] = predLine[i - pixBytes] + (Guchar)c;
00471       break;
00472     case 12:                    // PNG up
00473       predLine[i] = predLine[i] + (Guchar)c;
00474       break;
00475     case 13:                    // PNG average
00476       predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) +
00477                     (Guchar)c;
00478       break;
00479     case 14:                    // PNG Paeth
00480       left = predLine[i - pixBytes];
00481       up = predLine[i];
00482       upLeft = upLeftBuf[pixBytes];
00483       p = left + up - upLeft;
00484       if ((pa = p - left) < 0)
00485         pa = -pa;
00486       if ((pb = p - up) < 0)
00487         pb = -pb;
00488       if ((pc = p - upLeft) < 0)
00489         pc = -pc;
00490       if (pa <= pb && pa <= pc)
00491         predLine[i] = left + (Guchar)c;
00492       else if (pb <= pc)
00493         predLine[i] = up + (Guchar)c;
00494       else
00495         predLine[i] = upLeft + (Guchar)c;
00496       break;
00497     case 10:                    // PNG none
00498     default:                    // no predictor or TIFF predictor
00499       predLine[i] = (Guchar)c;
00500       break;
00501     }
00502   }
00503 
00504   // apply TIFF (component) predictor
00505   //~ this is completely untested
00506   if (predictor == 2) {
00507     if (nBits == 1) {
00508       inBuf = predLine[pixBytes - 1];
00509       for (i = pixBytes; i < rowBytes; i += 8) {
00510         // 1-bit add is just xor
00511         inBuf = (inBuf << 8) | predLine[i];
00512         predLine[i] ^= inBuf >> nComps;
00513       }
00514     } else if (nBits == 8) {
00515       for (i = pixBytes; i < rowBytes; ++i) {
00516         predLine[i] += predLine[i - nComps];
00517       }
00518     } else {
00519       upLeftBuf[0] = upLeftBuf[1] = upLeftBuf[2] = upLeftBuf[3] = 0;
00520       bitMask = (1 << nBits) - 1;
00521       inBuf = outBuf = 0;
00522       inBits = outBits = 0;
00523       j = k = pixBytes;
00524       for (i = 0; i < nVals; ++i) {
00525         if (inBits < nBits) {
00526           inBuf = (inBuf << 8) | (predLine[j++] & 0xff);
00527           inBits += 8;
00528         }
00529         upLeftBuf[3] = upLeftBuf[2];
00530         upLeftBuf[2] = upLeftBuf[1];
00531         upLeftBuf[1] = upLeftBuf[0];
00532         upLeftBuf[0] = (upLeftBuf[nComps] +
00533                         (inBuf >> (inBits - nBits))) & bitMask;
00534         outBuf = (outBuf << nBits) | upLeftBuf[0];
00535         inBits -= nBits;
00536         outBits += nBits;
00537         if (outBits > 8) {
00538           predLine[k++] = (Guchar)(outBuf >> (outBits - 8));
00539         }
00540       }
00541       if (outBits > 0) {
00542         predLine[k++] = (Guchar)(outBuf << (8 - outBits));
00543       }
00544     }
00545   }
00546 
00547   // reset to start of line
00548   predIdx = pixBytes;
00549 
00550   return gTrue;
00551 }
00552 
00553 //------------------------------------------------------------------------
00554 // FileStream
00555 //------------------------------------------------------------------------
00556 
00557 FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA,
00558                        Guint lengthA, Object *dictA):
00559     BaseStream(dictA) {
00560   f = fA;
00561   start = startA;
00562   limited = limitedA;
00563   length = lengthA;
00564   bufPtr = bufEnd = buf;
00565   bufPos = start;
00566   savePos = 0;
00567   saved = gFalse;
00568 }
00569 
00570 FileStream::~FileStream() {
00571   close();
00572 }
00573 
00574 Stream *FileStream::makeSubStream(Guint startA, GBool limitedA,
00575                                   Guint lengthA, Object *dictA) {
00576   return new FileStream(f, startA, limitedA, lengthA, dictA);
00577 }
00578 
00579 void FileStream::reset() {
00580 #if HAVE_FSEEK64
00581   savePos = (Guint)ftell64(f);
00582   fseek64(f, start, SEEK_SET);
00583 #else
00584   savePos = (Guint)ftell(f);
00585   fseek(f, start, SEEK_SET);
00586 #endif
00587   saved = gTrue;
00588   bufPtr = bufEnd = buf;
00589   bufPos = start;
00590 #ifndef NO_DECRYPTION
00591   if (decrypt)
00592     decrypt->reset();
00593 #endif
00594 }
00595 
00596 void FileStream::close() {
00597   if (saved) {
00598 #if HAVE_FSEEK64
00599     fseek64(f, savePos, SEEK_SET);
00600 #else
00601     fseek(f, savePos, SEEK_SET);
00602 #endif
00603     saved = gFalse;
00604   }
00605 }
00606 
00607 GBool FileStream::fillBuf() {
00608   int n;
00609 #ifndef NO_DECRYPTION
00610   char *p;
00611 #endif
00612 
00613   bufPos += bufEnd - buf;
00614   bufPtr = bufEnd = buf;
00615   if (limited && bufPos >= start + length) {
00616     return gFalse;
00617   }
00618   if (limited && bufPos + fileStreamBufSize > start + length) {
00619     n = start + length - bufPos;
00620   } else {
00621     n = fileStreamBufSize;
00622   }
00623   n = fread(buf, 1, n, f);
00624   bufEnd = buf + n;
00625   if (bufPtr >= bufEnd) {
00626     return gFalse;
00627   }
00628 #ifndef NO_DECRYPTION
00629   if (decrypt) {
00630     for (p = buf; p < bufEnd; ++p) {
00631       *p = (char)decrypt->decryptByte((Guchar)*p);
00632     }
00633   }
00634 #endif
00635   return gTrue;
00636 }
00637 
00638 void FileStream::setPos(Guint pos, int dir) {
00639   Guint size;
00640 
00641   if (dir >= 0) {
00642 #if HAVE_FSEEK64
00643     fseek64(f, pos, SEEK_SET);
00644 #else
00645     fseek(f, pos, SEEK_SET);
00646 #endif
00647     bufPos = pos;
00648   } else {
00649 #if HAVE_FSEEK64
00650     fseek64(f, 0, SEEK_END);
00651     size = (Guint)ftell64(f);
00652 #else
00653     fseek(f, 0, SEEK_END);
00654     size = (Guint)ftell(f);
00655 #endif
00656     if (pos > size)
00657       pos = (Guint)size;
00658 #ifdef __CYGWIN32__
00659     //~ work around a bug in cygwin's implementation of fseek
00660     rewind(f);
00661 #endif
00662 #if HAVE_FSEEK64
00663     fseek64(f, -(int)pos, SEEK_END);
00664     bufPos = (Guint)ftell64(f);
00665 #else
00666     fseek(f, -(int)pos, SEEK_END);
00667     bufPos = (Guint)ftell(f);
00668 #endif
00669   }
00670   bufPtr = bufEnd = buf;
00671 }
00672 
00673 void FileStream::moveStart(int delta) {
00674   start += delta;
00675   bufPtr = bufEnd = buf;
00676   bufPos = start;
00677 }
00678 
00679 //------------------------------------------------------------------------
00680 // MemStream
00681 //------------------------------------------------------------------------
00682 
00683 MemStream::MemStream(char *bufA, Guint lengthA, Object *dictA):
00684     BaseStream(dictA) {
00685   buf = bufA;
00686   needFree = gFalse;
00687   length = lengthA;
00688   bufEnd = buf + length;
00689   bufPtr = buf;
00690 }
00691 
00692 MemStream::~MemStream() {
00693   if (needFree) {
00694     gfree(buf);
00695   }
00696 }
00697 
00698 Stream *MemStream::makeSubStream(Guint start, GBool limited,
00699                                  Guint lengthA, Object *dictA) {
00700   Guint newLength;
00701 
00702   if (!limited || start + lengthA > length) {
00703     newLength = length - start;
00704   } else {
00705     newLength = lengthA;
00706   }
00707   return new MemStream(buf + start, newLength, dictA);
00708 }
00709 
00710 void MemStream::reset() {
00711   bufPtr = buf;
00712 #ifndef NO_DECRYPTION
00713   if (decrypt) {
00714     decrypt->reset();
00715   }
00716 #endif
00717 }
00718 
00719 void MemStream::close() {
00720 }
00721 
00722 void MemStream::setPos(Guint pos, int dir) {
00723   if (dir >= 0) {
00724     if (pos > length) {
00725       bufPtr = bufEnd;
00726     } else {
00727       bufPtr = buf + pos;
00728     }
00729   } else {
00730     if (pos > length) {
00731       bufPtr = buf;
00732     } else {
00733       bufPtr = bufEnd - pos;
00734     }
00735   }
00736 }
00737 
00738 void MemStream::moveStart(int delta) {
00739   buf += delta;
00740   bufPtr = buf;
00741 }
00742 
00743 #ifndef NO_DECRYPTION
00744 void MemStream::doDecryption(Guchar *fileKey, int keyLength,
00745                              int objNum, int objGen) {
00746   char *newBuf;
00747   char *p, *q;
00748 
00749   this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen);
00750   if (decrypt) {
00751     newBuf = (char *)gmalloc(bufEnd - buf);
00752     for (p = buf, q = newBuf; p < bufEnd; ++p, ++q) {
00753       *q = (char)decrypt->decryptByte((Guchar)*p);
00754     }
00755     bufEnd = newBuf + (bufEnd - buf);
00756     bufPtr = newBuf + (bufPtr - buf);
00757     buf = newBuf;
00758     needFree = gTrue;
00759   }
00760 }
00761 #endif
00762 
00763 //------------------------------------------------------------------------
00764 // EmbedStream
00765 //------------------------------------------------------------------------
00766 
00767 EmbedStream::EmbedStream(Stream *strA, Object *dictA):
00768     BaseStream(dictA) {
00769   str = strA;
00770 }
00771 
00772 EmbedStream::~EmbedStream() {
00773 }
00774 
00775 Stream *EmbedStream::makeSubStream(Guint start, GBool limited,
00776                                    Guint length, Object *dictA) {
00777   error(-1, "Internal: called makeSubStream() on EmbedStream");
00778   return NULL;
00779 }
00780 
00781 void EmbedStream::setPos(Guint pos, int dir) {
00782   error(-1, "Internal: called setPos() on EmbedStream");
00783 }
00784 
00785 Guint EmbedStream::getStart() {
00786   error(-1, "Internal: called getStart() on EmbedStream");
00787   return 0;
00788 }
00789 
00790 void EmbedStream::moveStart(int delta) {
00791   error(-1, "Internal: called moveStart() on EmbedStream");
00792 }
00793 
00794 //------------------------------------------------------------------------
00795 // ASCIIHexStream
00796 //------------------------------------------------------------------------
00797 
00798 ASCIIHexStream::ASCIIHexStream(Stream *strA):
00799     FilterStream(strA) {
00800   buf = EOF;
00801   eof = gFalse;
00802 }
00803 
00804 ASCIIHexStream::~ASCIIHexStream() {
00805   delete str;
00806 }
00807 
00808 void ASCIIHexStream::reset() {
00809   str->reset();
00810   buf = EOF;
00811   eof = gFalse;
00812 }
00813 
00814 int ASCIIHexStream::lookChar() {
00815   int c1, c2, x;
00816 
00817   if (buf != EOF)
00818     return buf;
00819   if (eof) {
00820     buf = EOF;
00821     return EOF;
00822   }
00823   do {
00824     c1 = str->getChar();
00825   } while (isspace(c1));
00826   if (c1 == '>') {
00827     eof = gTrue;
00828     buf = EOF;
00829     return buf;
00830   }
00831   do {
00832     c2 = str->getChar();
00833   } while (isspace(c2));
00834   if (c2 == '>') {
00835     eof = gTrue;
00836     c2 = '0';
00837   }
00838   if (c1 >= '0' && c1 <= '9') {
00839     x = (c1 - '0') << 4;
00840   } else if (c1 >= 'A' && c1 <= 'F') {
00841     x = (c1 - 'A' + 10) << 4;
00842   } else if (c1 >= 'a' && c1 <= 'f') {
00843     x = (c1 - 'a' + 10) << 4;
00844   } else if (c1 == EOF) {
00845     eof = gTrue;
00846     x = 0;
00847   } else {
00848     error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c1);
00849     x = 0;
00850   }
00851   if (c2 >= '0' && c2 <= '9') {
00852     x += c2 - '0';
00853   } else if (c2 >= 'A' && c2 <= 'F') {
00854     x += c2 - 'A' + 10;
00855   } else if (c2 >= 'a' && c2 <= 'f') {
00856     x += c2 - 'a' + 10;
00857   } else if (c2 == EOF) {
00858     eof = gTrue;
00859     x = 0;
00860   } else {
00861     error(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2);
00862   }
00863   buf = x & 0xff;
00864   return buf;
00865 }
00866 
00867 GString *ASCIIHexStream::getPSFilter(char *indent) {
00868   GString *s;
00869 
00870   if (!(s = str->getPSFilter(indent))) {
00871     return NULL;
00872   }
00873   s->append(indent)->append("/ASCIIHexDecode filter\n");
00874   return s;
00875 }
00876 
00877 GBool ASCIIHexStream::isBinary(GBool last) {
00878   return str->isBinary(gFalse);
00879 }
00880 
00881 //------------------------------------------------------------------------
00882 // ASCII85Stream
00883 //------------------------------------------------------------------------
00884 
00885 ASCII85Stream::ASCII85Stream(Stream *strA):
00886     FilterStream(strA) {
00887   index = n = 0;
00888   eof = gFalse;
00889 }
00890 
00891 ASCII85Stream::~ASCII85Stream() {
00892   delete str;
00893 }
00894 
00895 void ASCII85Stream::reset() {
00896   str->reset();
00897   index = n = 0;
00898   eof = gFalse;
00899 }
00900 
00901 int ASCII85Stream::lookChar() {
00902   int k;
00903   Gulong t;
00904 
00905   if (index >= n) {
00906     if (eof)
00907       return EOF;
00908     index = 0;
00909     do {
00910       c[0] = str->getChar();
00911     } while (c[0] == '\n' || c[0] == '\r');
00912     if (c[0] == '~' || c[0] == EOF) {
00913       eof = gTrue;
00914       n = 0;
00915       return EOF;
00916     } else if (c[0] == 'z') {
00917       b[0] = b[1] = b[2] = b[3] = 0;
00918       n = 4;
00919     } else {
00920       for (k = 1; k < 5; ++k) {
00921         do {
00922           c[k] = str->getChar();
00923         } while (c[k] == '\n' || c[k] == '\r');
00924         if (c[k] == '~' || c[k] == EOF)
00925           break;
00926       }
00927       n = k - 1;
00928       if (k < 5 && (c[k] == '~' || c[k] == EOF)) {
00929         for (++k; k < 5; ++k)
00930           c[k] = 0x21 + 84;
00931         eof = gTrue;
00932       }
00933       t = 0;
00934       for (k = 0; k < 5; ++k)
00935         t = t * 85 + (c[k] - 0x21);
00936       for (k = 3; k >= 0; --k) {
00937         b[k] = (int)(t & 0xff);
00938         t >>= 8;
00939       }
00940     }
00941   }
00942   return b[index];
00943 }
00944 
00945 GString *ASCII85Stream::getPSFilter(char *indent) {
00946   GString *s;
00947 
00948   if (!(s = str->getPSFilter(indent))) {
00949     return NULL;
00950   }
00951   s->append(indent)->append("/ASCII85Decode filter\n");
00952   return s;
00953 }
00954 
00955 GBool ASCII85Stream::isBinary(GBool last) {
00956   return str->isBinary(gFalse);
00957 }
00958 
00959 //------------------------------------------------------------------------
00960 // LZWStream
00961 //------------------------------------------------------------------------
00962 
00963 LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors,
00964                      int bits, int earlyA):
00965     FilterStream(strA) {
00966   if (predictor != 1) {
00967     pred = new StreamPredictor(this, predictor, columns, colors, bits);
00968   } else {
00969     pred = NULL;
00970   }
00971   early = earlyA;
00972   zPipe = NULL;
00973   bufPtr = bufEnd = buf;
00974 }
00975 
00976 LZWStream::~LZWStream() {
00977   if (zPipe) {
00978 #ifdef HAVE_POPEN
00979     pclose(zPipe);
00980 #else
00981     fclose(zPipe);
00982 #endif
00983     zPipe = NULL;
00984     unlink(zName->getCString());
00985     delete zName;
00986   }
00987   if (pred) {
00988     delete pred;
00989   }
00990   delete str;
00991 }
00992 
00993 int LZWStream::getChar() {
00994   if (pred) {
00995     return pred->getChar();
00996   }
00997   return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
00998 }
00999 
01000 int LZWStream::lookChar() {
01001   if (pred) {
01002     return pred->lookChar();
01003   }
01004   return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff);
01005 }
01006 
01007 int LZWStream::getRawChar() {
01008   return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff);
01009 }
01010 
01011 void LZWStream::reset() {
01012   FILE *f;
01013   GString *zCmd;
01014 
01015   //----- close old LZW stream
01016   if (zPipe) {
01017 #ifdef HAVE_POPEN
01018     pclose(zPipe);
01019 #else
01020     fclose(zPipe);
01021 #endif
01022     zPipe = NULL;
01023     unlink(zName->getCString());
01024     delete zName;
01025   }
01026 
01027   //----- tell Delorie runtime to spawn a new instance of COMMAND.COM
01028   //      to run gzip
01029 #if __DJGPP__
01030   if (!setDJSYSFLAGS) {
01031     setenv("DJSYSFLAGS", "0x0002", 0);
01032     setDJSYSFLAGS = gTrue;
01033   }
01034 #endif
01035 
01036   //----- create the .Z file
01037   if (!openTempFile(&zName, &f, "wb", ".Z")) {
01038     error(getPos(), "Couldn't create temporary file for LZW stream");
01039     return;
01040   }
01041   dumpFile(f);
01042   fclose(f);
01043 
01044   //----- execute uncompress / gzip
01045   zCmd = new GString(uncompressCmd);
01046   zCmd->append(' ');
01047   zCmd->append(zName);
01048 #if defined(MACOS)
01049   long magicCookie;
01050   // first we open the engine up
01051   OSErr err = OpenSITEngine(kUseExternalEngine, &magicCookie);
01052   // if we found it - let's use it!
01053   if (!err && magicCookie) {
01054     // make sure we have the correct version of the Engine
01055     if (GetSITEngineVersion(magicCookie) >= kFirstSupportedEngine) {
01056       FSSpec myFSS;
01057       Str255 pName;
01058       strcpy((char *)pName, zName->getCString());
01059       c2pstr((char *)pName);
01060       FSMakeFSSpec(0, 0, pName, &myFSS);
01061       short ftype = DetermineFileType(magicCookie, &myFSS);
01062       OSErr expandErr = ExpandFSSpec(magicCookie, ftype, &myFSS,
01063                                      NULL, NULL, kCreateFolderNever,
01064                                      kDeleteOriginal, kTextConvertSmart);
01065     }
01066   }
01067 #elif defined(HAVE_POPEN)
01068   if (!(zPipe = popen(zCmd->getCString(), POPEN_READ_MODE))) {
01069     error(getPos(), "Couldn't popen '%s'", zCmd->getCString());
01070     unlink(zName->getCString());
01071     delete zName;
01072     return;
01073   }
01074 #else // HAVE_POPEN
01075   if (!executeCommand(zCmd->getCString())) {
01076     error(getPos(), "Couldn't execute '%s'", zCmd->getCString());
01077     unlink(zName->getCString());
01078     delete zName;
01079     return;
01080   }
01081   zName->del(zName->getLength() - 2, 2);
01082   if (!(zPipe = fopen(zName->getCString(), "rb"))) {
01083     error(getPos(), "Couldn't open uncompress file '%s'", zName->getCString());
01084     unlink(zName->getCString());
01085     delete zName;
01086     return;
01087   }
01088 #endif // HAVE_POPEN
01089 
01090   //----- clean up
01091   delete zCmd;
01092 
01093   //----- initialize buffer
01094   bufPtr = bufEnd = buf;
01095 }
01096 
01097 void LZWStream::dumpFile(FILE *f) {
01098   int outCodeBits;              // size of output code
01099   int outBits;                  // max output code
01100   int outBuf[8];                // output buffer
01101   int outData;                  // temporary output buffer
01102   int inCode, outCode;          // input and output codes
01103   int nextCode;                 // next code index
01104   GBool eof;                    // set when EOF is reached
01105   GBool clear;                  // set if table needs to be cleared
01106   GBool first;                  // indicates first code word after clear
01107   int i, j;
01108 
01109   str->reset();
01110 
01111   // magic number
01112   fputc(0x1f, f);
01113   fputc(0x9d, f);
01114 
01115   // max code length, block mode flag
01116   fputc(0x8c, f);
01117 
01118   // init input side
01119   inCodeBits = 9;
01120   inputBuf = 0;
01121   inputBits = 0;
01122   eof = gFalse;
01123 
01124   // init output side
01125   outCodeBits = 9;
01126 
01127   // clear table
01128   first = gTrue;
01129   nextCode = 258;
01130 
01131   clear = gFalse;
01132   do {
01133     for (i = 0; i < 8; ++i) {
01134       // check for table overflow
01135       if (nextCode + early > 0x1001) {
01136         inCode = 256;
01137 
01138       // read input code
01139       } else {
01140         do {
01141           inCode = getCode();
01142           if (inCode == EOF) {
01143             eof = gTrue;
01144             inCode = 0;
01145           }
01146         } while (first && inCode == 256);
01147       }
01148 
01149       // compute output code
01150       if (inCode < 256) {
01151         outCode = inCode;
01152       } else if (inCode == 256) {
01153         outCode = 256;
01154         clear = gTrue;
01155       } else if (inCode == 257) {
01156         outCode = 0;
01157         eof = gTrue;
01158       } else {
01159         outCode = inCode - 1;
01160       }
01161       outBuf[i] = outCode;
01162 
01163       // next code index
01164       if (first)
01165         first = gFalse;
01166       else
01167         ++nextCode;
01168 
01169       // check input code size
01170       if (nextCode + early == 0x200)
01171         inCodeBits = 10;
01172       else if (nextCode + early == 0x400) {
01173         inCodeBits = 11;
01174       } else if (nextCode + early == 0x800) {
01175         inCodeBits = 12;
01176       }
01177 
01178       // check for eof/clear
01179       if (eof)
01180         break;
01181       if (clear) {
01182         i = 8;
01183         break;
01184       }
01185     }
01186 
01187     // write output block
01188     outData = 0;
01189     outBits = 0;
01190     j = 0;
01191     while (j < i || outBits > 0) {
01192       if (outBits < 8 && j < i) {
01193         outData = outData | (outBuf[j++] << outBits);
01194         outBits += outCodeBits;
01195       }
01196       fputc(outData & 0xff, f);
01197       outData >>= 8;
01198       outBits -= 8;
01199     }
01200 
01201     // check output code size
01202     if (nextCode - 1 == 512 ||
01203         nextCode - 1 == 1024 ||
01204         nextCode - 1 == 2048 ||
01205         nextCode - 1 == 4096) {
01206       outCodeBits = inCodeBits;
01207     }
01208 
01209     // clear table if necessary
01210     if (clear) {
01211       inCodeBits = 9;
01212       outCodeBits = 9;
01213       first = gTrue;
01214       nextCode = 258;
01215       clear = gFalse;
01216     }
01217   } while (!eof);
01218 }
01219 
01220 int LZWStream::getCode() {
01221   int c;
01222   int code;
01223 
01224   while (inputBits < inCodeBits) {
01225     if ((c = str->getChar()) == EOF)
01226       return EOF;
01227     inputBuf = (inputBuf << 8) | (c & 0xff);
01228     inputBits += 8;
01229   }
01230   code = (inputBuf >> (inputBits - inCodeBits)) & ((1 << inCodeBits) - 1);
01231   inputBits -= inCodeBits;
01232   return code;
01233 }
01234 
01235 GBool LZWStream::fillBuf() {
01236   int n;
01237 
01238   if (!zPipe)
01239     return gFalse;
01240   if ((n = fread(buf, 1, 256, zPipe)) < 256) {
01241 #ifdef HAVE_POPEN
01242     pclose(zPipe);
01243 #else
01244     fclose(zPipe);
01245 #endif
01246     zPipe = NULL;
01247     unlink(zName->getCString());
01248     delete zName;
01249   }
01250   bufPtr = buf;
01251   bufEnd = buf + n;
01252   return n > 0;
01253 }
01254 
01255 GString *LZWStream::getPSFilter(char *indent) {
01256   GString *s;
01257 
01258   if (pred) {
01259     return NULL;
01260   }
01261   if (!(s = str->getPSFilter(indent))) {
01262     return NULL;
01263   }
01264   s->append(indent)->append("/LZWDecode filter\n");
01265   return s;
01266 }
01267 
01268 GBool LZWStream::isBinary(GBool last) {
01269   return str->isBinary(gTrue);
01270 }
01271 
01272 //------------------------------------------------------------------------
01273 // RunLengthStream
01274 //------------------------------------------------------------------------
01275 
01276 RunLengthStream::RunLengthStream(Stream *strA):
01277     FilterStream(strA) {
01278   bufPtr = bufEnd = buf;
01279   eof = gFalse;
01280 }
01281 
01282 RunLengthStream::~RunLengthStream() {
01283   delete str;
01284 }
01285 
01286 void RunLengthStream::reset() {
01287   str->reset();
01288   bufPtr = bufEnd = buf;
01289   eof = gFalse;
01290 }
01291 
01292 GString *RunLengthStream::getPSFilter(char *indent) {
01293   GString *s;
01294 
01295   if (!(s = str->getPSFilter(indent))) {
01296     return NULL;
01297   }
01298   s->append(indent)->append("/RunLengthDecode filter\n");
01299   return s;
01300 }
01301 
01302 GBool RunLengthStream::isBinary(GBool last) {
01303   return str->isBinary(gTrue);
01304 }
01305 
01306 GBool RunLengthStream::fillBuf() {
01307   int c;
01308   int n, i;
01309 
01310   if (eof)
01311     return gFalse;
01312   c = str->getChar();
01313   if (c == 0x80 || c == EOF) {
01314     eof = gTrue;
01315     return gFalse;
01316   }
01317   if (c < 0x80) {
01318     n = c + 1;
01319     for (i = 0; i < n; ++i)
01320       buf[i] = (char)str->getChar();
01321   } else {
01322     n = 0x101 - c;
01323     c = str->getChar();
01324     for (i = 0; i < n; ++i)
01325       buf[i] = (char)c;
01326   }
01327   bufPtr = buf;
01328   bufEnd = buf + n;
01329   return gTrue;
01330 }
01331 
01332 //------------------------------------------------------------------------
01333 // CCITTFaxStream
01334 //------------------------------------------------------------------------
01335 
01336 CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
01337                                GBool byteAlignA, int columnsA, int rowsA,
01338                                GBool endOfBlockA, GBool blackA):
01339     FilterStream(strA) {
01340   encoding = encodingA;
01341   endOfLine = endOfLineA;
01342   byteAlign = byteAlignA;
01343   columns = columnsA;
01344   rows = rowsA;
01345   endOfBlock = endOfBlockA;
01346   black = blackA;
01347   refLine = (short *)gmalloc((columns + 3) * sizeof(short));
01348   codingLine = (short *)gmalloc((columns + 2) * sizeof(short));
01349 
01350   eof = gFalse;
01351   row = 0;
01352   nextLine2D = encoding < 0;
01353   inputBits = 0;
01354   codingLine[0] = 0;
01355   codingLine[1] = refLine[2] = columns;
01356   a0 = 1;
01357 
01358   buf = EOF;
01359 }
01360 
01361 CCITTFaxStream::~CCITTFaxStream() {
01362   delete str;
01363   gfree(refLine);
01364   gfree(codingLine);
01365 }
01366 
01367 void CCITTFaxStream::reset() {
01368   int n;
01369 
01370   str->reset();
01371   eof = gFalse;
01372   row = 0;
01373   nextLine2D = encoding < 0;
01374   inputBits = 0;
01375   codingLine[0] = 0;
01376   codingLine[1] = refLine[2] = columns;
01377   a0 = 1;
01378   buf = EOF;
01379 
01380   // get initial end-of-line marker and 2D encoding tag
01381   if (endOfBlock) {
01382     if (lookBits(12) == 0x001) {
01383       eatBits(12);
01384     }
01385   } else {
01386     for (n = 0; n < 11 && lookBits(n) == 0; ++n) ;
01387     if (n == 11 && lookBits(12) == 0x001) {
01388       eatBits(12);
01389     }
01390   }
01391   if (encoding > 0) {
01392     nextLine2D = !lookBits(1);
01393     eatBits(1);
01394   }
01395 }
01396 
01397 int CCITTFaxStream::lookChar() {
01398   short code1, code2, code3;
01399   int a0New;
01400 #if 0
01401   GBool err;
01402 #endif
01403   GBool gotEOL;
01404   int ret;
01405   int bits, i;
01406 
01407   // if at eof just return EOF
01408   if (eof && codingLine[a0] >= columns) {
01409     return EOF;
01410   }
01411 
01412   // read the next row
01413 #if 0
01414   err = gFalse;
01415 #endif
01416   if (codingLine[a0] >= columns) {
01417 
01418     // 2-D encoding
01419     if (nextLine2D) {
01420       for (i = 0; codingLine[i] < columns; ++i)
01421         refLine[i] = codingLine[i];
01422       refLine[i] = refLine[i + 1] = columns;
01423       b1 = 1;
01424       a0New = codingLine[a0 = 0] = 0;
01425       do {
01426         code1 = getTwoDimCode();
01427         switch (code1) {
01428         case twoDimPass:
01429           if (refLine[b1] < columns) {
01430             a0New = refLine[b1 + 1];
01431             b1 += 2;
01432           }
01433           break;
01434         case twoDimHoriz:
01435           if ((a0 & 1) == 0) {
01436             code1 = code2 = 0;
01437             do {
01438               code1 += code3 = getWhiteCode();
01439             } while (code3 >= 64);
01440             do {
01441               code2 += code3 = getBlackCode();
01442             } while (code3 >= 64);
01443           } else {
01444             code1 = code2 = 0;
01445             do {
01446               code1 += code3 = getBlackCode();
01447             } while (code3 >= 64);
01448             do {
01449               code2 += code3 = getWhiteCode();
01450             } while (code3 >= 64);
01451           }
01452           codingLine[a0 + 1] = a0New + code1;
01453           ++a0;
01454           a0New = codingLine[a0 + 1] = codingLine[a0] + code2;
01455           ++a0;
01456           while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01457             b1 += 2;
01458           break;
01459         case twoDimVert0:
01460           a0New = codingLine[++a0] = refLine[b1];
01461           if (refLine[b1] < columns) {
01462             ++b1;
01463             while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01464               b1 += 2;
01465           }
01466           break;
01467         case twoDimVertR1:
01468           a0New = codingLine[++a0] = refLine[b1] + 1;
01469           if (refLine[b1] < columns) {
01470             ++b1;
01471             while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01472               b1 += 2;
01473           }
01474           break;
01475         case twoDimVertL1:
01476           a0New = codingLine[++a0] = refLine[b1] - 1;
01477           --b1;
01478           while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01479             b1 += 2;
01480           break;
01481         case twoDimVertR2:
01482           a0New = codingLine[++a0] = refLine[b1] + 2;
01483           if (refLine[b1] < columns) {
01484             ++b1;
01485             while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01486               b1 += 2;
01487           }
01488           break;
01489         case twoDimVertL2:
01490           a0New = codingLine[++a0] = refLine[b1] - 2;
01491           --b1;
01492           while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01493             b1 += 2;
01494           break;
01495         case twoDimVertR3:
01496           a0New = codingLine[++a0] = refLine[b1] + 3;
01497           if (refLine[b1] < columns) {
01498             ++b1;
01499             while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01500               b1 += 2;
01501           }
01502           break;
01503         case twoDimVertL3:
01504           a0New = codingLine[++a0] = refLine[b1] - 3;
01505           --b1;
01506           while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns)
01507             b1 += 2;
01508           break;
01509         case EOF:
01510           eof = gTrue;
01511           codingLine[a0 = 0] = columns;
01512           return EOF;
01513         default:
01514           error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
01515 #if 0
01516           err = gTrue;
01517           break;
01518 #else
01519           eof = gTrue;
01520           return EOF;
01521 #endif
01522         }
01523       } while (codingLine[a0] < columns);
01524 
01525     // 1-D encoding
01526     } else {
01527       codingLine[a0 = 0] = 0;
01528       while (1) {
01529         code1 = 0;
01530         do {
01531           code1 += code3 = getWhiteCode();
01532         } while (code3 >= 64);
01533         codingLine[a0+1] = codingLine[a0] + code1;
01534         ++a0;
01535         if (codingLine[a0] >= columns)
01536           break;
01537         code2 = 0;
01538         do {
01539           code2 += code3 = getBlackCode();
01540         } while (code3 >= 64);
01541         codingLine[a0+1] = codingLine[a0] + code2;
01542         ++a0;
01543         if (codingLine[a0] >= columns)
01544           break;
01545       }
01546     }
01547 
01548     if (codingLine[a0] != columns) {
01549       error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
01550 #if 0
01551       err = gTrue;
01552 #endif
01553     }
01554 
01555     // byte-align the row
01556     if (byteAlign) {
01557       inputBits &= ~7;
01558     }
01559 
01560     // check for end-of-line marker, skipping over any extra zero bits
01561     gotEOL = gFalse;
01562     if (!endOfBlock && row == rows - 1) {
01563       eof = gTrue;
01564     } else {
01565       code1 = lookBits(12);
01566       while (code1 == 0) {
01567         eatBits(1);
01568         code1 = lookBits(12);
01569       }
01570       if (code1 == 0x001) {
01571         eatBits(12);
01572         gotEOL = gTrue;
01573       } else if (code1 == EOF) {
01574         eof = gTrue;
01575       }
01576     }
01577 
01578     // get 2D encoding tag
01579     if (!eof && encoding > 0) {
01580       nextLine2D = !lookBits(1);
01581       eatBits(1);
01582     }
01583 
01584     // check for end-of-block marker
01585     if (endOfBlock && gotEOL) {
01586       code1 = lookBits(12);
01587       if (code1 == 0x001) {
01588         eatBits(12);
01589         if (encoding > 0) {
01590           lookBits(1);
01591           eatBits(1);
01592         }
01593         if (encoding >= 0) {
01594           for (i = 0; i < 4; ++i) {
01595             code1 = lookBits(12);
01596             if (code1 != 0x001) {
01597               error(getPos(), "Bad RTC code in CCITTFax stream");
01598             }
01599             eatBits(12);
01600             if (encoding > 0) {
01601               lookBits(1);
01602               eatBits(1);
01603             }
01604           }
01605         }
01606         eof = gTrue;
01607       }
01608     }
01609 
01610 #if 0
01611     // This looks for an end-of-line marker after an error, however
01612     // some (most?) CCITT streams in PDF files don't use end-of-line
01613     // markers, and the just-plow-on technique works better in those
01614     // cases.
01615     else if (err) {
01616       do {
01617         if (code1 == EOF) {
01618           eof = gTrue;
01619           return EOF;
01620         }
01621         eatBits(1);
01622         code1 = look13Bits();
01623       } while ((code1 >> 1) != 0x001);
01624       eatBits(12); 
01625       codingLine[++a0] = columns;
01626       if (encoding > 0) {
01627         eatBits(1);
01628         nextLine2D = !(code1 & 1);
01629       }
01630     }
01631 #endif
01632 
01633     a0 = 0;
01634     outputBits = codingLine[1] - codingLine[0];
01635     if (outputBits == 0) {
01636       a0 = 1;
01637       outputBits = codingLine[2] - codingLine[1];
01638     }
01639 
01640     ++row;
01641   }
01642 
01643   // get a byte
01644   if (outputBits >= 8) {
01645     ret = ((a0 & 1) == 0) ? 0xff : 0x00;
01646     if ((outputBits -= 8) == 0) {
01647       ++a0;
01648       if (codingLine[a0] < columns) {
01649         outputBits = codingLine[a0 + 1] - codingLine[a0];
01650       }
01651     }
01652   } else {
01653     bits = 8;
01654     ret = 0;
01655     do {
01656       if (outputBits > bits) {
01657         i = bits;
01658         bits = 0;
01659         if ((a0 & 1) == 0) {
01660           ret |= 0xff >> (8 - i);
01661         }
01662         outputBits -= i;
01663       } else {
01664         i = outputBits;
01665         bits -= outputBits;
01666         if ((a0 & 1) == 0) {
01667           ret |= (0xff >> (8 - i)) << bits;
01668         }
01669         outputBits = 0;
01670         ++a0;
01671         if (codingLine[a0] < columns) {
01672           outputBits = codingLine[a0 + 1] - codingLine[a0];
01673         }
01674       }
01675     } while (bits > 0 && codingLine[a0] < columns);
01676   }
01677   buf = black ? (ret ^ 0xff) : ret;
01678   return buf;
01679 }
01680 
01681 short CCITTFaxStream::getTwoDimCode() {
01682   short code;
01683   CCITTCode *p;
01684   int n;
01685 
01686   code = 0; // make gcc happy
01687   if (endOfBlock) {
01688     code = lookBits(7);
01689     p = &twoDimTab1[code];
01690     if (p->bits > 0) {
01691       eatBits(p->bits);
01692       return p->n;
01693     }
01694   } else {
01695     for (n = 1; n <= 7; ++n) {
01696       code = lookBits(n);
01697       if (n < 7) {
01698         code <<= 7 - n;
01699       }
01700       p = &twoDimTab1[code];
01701       if (p->bits == n) {
01702         eatBits(n);
01703         return p->n;
01704       }
01705     }
01706   }
01707   error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code);
01708   return EOF;
01709 }
01710 
01711 short CCITTFaxStream::getWhiteCode() {
01712   short code;
01713   CCITTCode *p;
01714   int n;
01715 
01716   code = 0; // make gcc happy
01717   if (endOfBlock) {
01718     code = lookBits(12);
01719     if ((code >> 5) == 0) {
01720       p = &whiteTab1[code];
01721     } else {
01722       p = &whiteTab2[code >> 3];
01723     }
01724     if (p->bits > 0) {
01725       eatBits(p->bits);
01726       return p->n;
01727     }
01728   } else {
01729     for (n = 1; n <= 9; ++n) {
01730       code = lookBits(n);
01731       if (n < 9) {
01732         code <<= 9 - n;
01733       }
01734       p = &whiteTab2[code];
01735       if (p->bits == n) {
01736         eatBits(n);
01737         return p->n;
01738       }
01739     }
01740     for (n = 11; n <= 12; ++n) {
01741       code = lookBits(n);
01742       if (n < 12) {
01743         code <<= 12 - n;
01744       }
01745       p = &whiteTab1[code];
01746       if (p->bits == n) {
01747         eatBits(n);
01748         return p->n;
01749       }
01750     }
01751   }
01752   error(getPos(), "Bad white code (%04x) in CCITTFax stream", code);
01753   // eat a bit and return a positive number so that the caller doesn't
01754   // go into an infinite loop
01755   eatBits(1);
01756   return 1;
01757 }
01758 
01759 short CCITTFaxStream::getBlackCode() {
01760   short code;
01761   CCITTCode *p;
01762   int n;
01763 
01764   code = 0; // make gcc happy
01765   if (endOfBlock) {
01766     code = lookBits(13);
01767     if ((code >> 7) == 0) {
01768       p = &blackTab1[code];
01769     } else if ((code >> 9) == 0) {
01770       p = &blackTab2[(code >> 1) - 64];
01771     } else {
01772       p = &blackTab3[code >> 7];
01773     }
01774     if (p->bits > 0) {
01775       eatBits(p->bits);
01776       return p->n;
01777     }
01778   } else {
01779     for (n = 2; n <= 6; ++n) {
01780       code = lookBits(n);
01781       if (n < 6) {
01782         code <<= 6 - n;
01783       }
01784       p = &blackTab3[code];
01785       if (p->bits == n) {
01786         eatBits(n);
01787         return p->n;
01788       }
01789     }
01790     for (n = 7; n <= 12; ++n) {
01791       code = lookBits(n);
01792       if (n < 12) {
01793         code <<= 12 - n;
01794       }
01795       if (code >= 64) {
01796         p = &blackTab2[code - 64];
01797         if (p->bits == n) {
01798           eatBits(n);
01799           return p->n;
01800         }
01801       }
01802     }
01803     for (n = 10; n <= 13; ++n) {
01804       code = lookBits(n);
01805       if (n < 13) {
01806         code <<= 13 - n;
01807       }
01808       p = &blackTab1[code];
01809       if (p->bits == n) {
01810         eatBits(n);
01811         return p->n;
01812       }
01813     }
01814   }
01815   error(getPos(), "Bad black code (%04x) in CCITTFax stream", code);
01816   // eat a bit and return a positive number so that the caller doesn't
01817   // go into an infinite loop
01818   eatBits(1);
01819   return 1;
01820 }
01821 
01822 short CCITTFaxStream::lookBits(int n) {
01823   int c;
01824 
01825   while (inputBits < n) {
01826     if ((c = str->getChar()) == EOF) {
01827       if (inputBits == 0) {
01828         return EOF;
01829       }
01830       // near the end of the stream, the caller may ask for more bits
01831       // than are available, but there may still be a valid code in
01832       // however many bits are available -- we need to return correct
01833       // data in this case
01834       return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n));
01835     }
01836     inputBuf = (inputBuf << 8) + c;
01837     inputBits += 8;
01838   }
01839   return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n));
01840 }
01841 
01842 GString *CCITTFaxStream::getPSFilter(char *indent) {
01843   GString *s;
01844   char s1[50];
01845 
01846   if (!(s = str->getPSFilter(indent))) {
01847     return NULL;
01848   }
01849   s->append(indent)->append("<< ");
01850   if (encoding != 0) {
01851     sprintf(s1, "/K %d ", encoding);
01852     s->append(s1);
01853   }
01854   if (endOfLine) {
01855     s->append("/EndOfLine true ");
01856   }
01857   if (byteAlign) {
01858     s->append("/EncodedByteAlign true ");
01859   }
01860   sprintf(s1, "/Columns %d ", columns);
01861   s->append(s1);
01862   if (rows != 0) {
01863     sprintf(s1, "/Rows %d ", rows);
01864     s->append(s1);
01865   }
01866   if (!endOfBlock) {
01867     s->append("/EndOfBlock false ");
01868   }
01869   if (black) {
01870     s->append("/BlackIs1 true ");
01871   }
01872   s->append(">> /CCITTFaxDecode filter\n");
01873   return s;
01874 }
01875 
01876 GBool CCITTFaxStream::isBinary(GBool last) {
01877   return str->isBinary(gTrue);
01878 }
01879 
01880 //------------------------------------------------------------------------
01881 // DCTStream
01882 //------------------------------------------------------------------------
01883 
01884 // IDCT constants (20.12 fixed point format)
01885 #ifndef FP_IDCT
01886 #define dctCos1    4017         // cos(pi/16)
01887 #define dctSin1     799         // sin(pi/16)
01888 #define dctCos3    3406         // cos(3*pi/16)
01889 #define dctSin3    2276         // sin(3*pi/16)
01890 #define dctCos6    1567         // cos(6*pi/16)
01891 #define dctSin6    3784         // sin(6*pi/16)
01892 #define dctSqrt2   5793         // sqrt(2)
01893 #define dctSqrt1d2 2896         // sqrt(2) / 2
01894 #endif
01895 
01896 // IDCT constants
01897 #ifdef FP_IDCT
01898 #define dctCos1    0.98078528   // cos(pi/16)
01899 #define dctSin1    0.19509032   // sin(pi/16)
01900 #define dctCos3    0.83146961   // cos(3*pi/16)
01901 #define dctSin3    0.55557023   // sin(3*pi/16)
01902 #define dctCos6    0.38268343   // cos(6*pi/16)
01903 #define dctSin6    0.92387953   // sin(6*pi/16)
01904 #define dctSqrt2   1.41421356   // sqrt(2)
01905 #define dctSqrt1d2 0.70710678   // sqrt(2) / 2
01906 #endif
01907 
01908 // color conversion parameters (16.16 fixed point format)
01909 #define dctCrToR   91881        //  1.4020
01910 #define dctCbToG  -22553        // -0.3441363
01911 #define dctCrToG  -46802        // -0.71413636
01912 #define dctCbToB  116130        //  1.772
01913 
01914 // clip [-256,511] --> [0,255]
01915 #define dctClipOffset 256
01916 static Guchar dctClip[768];
01917 static int dctClipInit = 0;
01918 
01919 // zig zag decode map
01920 static int dctZigZag[64] = {
01921    0,
01922    1,  8,
01923   16,  9,  2,
01924    3, 10, 17, 24,
01925   32, 25, 18, 11, 4,
01926    5, 12, 19, 26, 33, 40,
01927   48, 41, 34, 27, 20, 13,  6,
01928    7, 14, 21, 28, 35, 42, 49, 56,
01929   57, 50, 43, 36, 29, 22, 15,
01930   23, 30, 37, 44, 51, 58,
01931   59, 52, 45, 38, 31,
01932   39, 46, 53, 60,
01933   61, 54, 47,
01934   55, 62,
01935   63
01936 };
01937 
01938 DCTStream::DCTStream(Stream *strA):
01939     FilterStream(strA) {
01940   int i, j;
01941 
01942   width = height = 0;
01943   mcuWidth = mcuHeight = 0;
01944   numComps = 0;
01945   comp = 0;
01946   x = y = dy = 0;
01947   for (i = 0; i < 4; ++i)
01948     for (j = 0; j < 32; ++j)
01949       rowBuf[i][j] = NULL;
01950 
01951   if (!dctClipInit) {
01952     for (i = -256; i < 0; ++i)
01953       dctClip[dctClipOffset + i] = 0;
01954     for (i = 0; i < 256; ++i)
01955       dctClip[dctClipOffset + i] = i;
01956     for (i = 256; i < 512; ++i)
01957       dctClip[dctClipOffset + i] = 255;
01958     dctClipInit = 1;
01959   }
01960 }
01961 
01962 DCTStream::~DCTStream() {
01963   int i, j;
01964 
01965   delete str;
01966   for (i = 0; i < numComps; ++i)
01967     for (j = 0; j < mcuHeight; ++j)
01968       gfree(rowBuf[i][j]);
01969 }
01970 
01971 void DCTStream::reset() {
01972   str->reset();
01973   if (!readHeader()) {
01974     y = height;
01975     return;
01976   }
01977   restartMarker = 0xd0;
01978   restart();
01979 }
01980 
01981 int DCTStream::getChar() {
01982   int c;
01983 
01984   c = lookChar();
01985   if (c == EOF)
01986     return EOF;
01987   if (++comp == numComps) {
01988     comp = 0;
01989     if (++x == width) {
01990       x = 0;
01991       ++y;
01992       ++dy;
01993     }
01994   }
01995   if (y == height)
01996     readTrailer();
01997   return c;
01998 }
01999 
02000 int DCTStream::lookChar() {
02001   if (y >= height)
02002     return EOF;
02003   if (dy >= mcuHeight) {
02004     if (!readMCURow()) {
02005       y = height;
02006       return EOF;
02007     }
02008     comp = 0;
02009     x = 0;
02010     dy = 0;
02011   }
02012   return rowBuf[comp][dy][x];
02013 }
02014 
02015 void DCTStream::restart() {
02016   int i;
02017 
02018   inputBits = 0;
02019   restartCtr = restartInterval;
02020   for (i = 0; i < numComps; ++i)
02021     compInfo[i].prevDC = 0;
02022 }
02023 
02024 GBool DCTStream::readMCURow() {
02025   Guchar data[64];
02026   Guchar *p1, *p2;
02027   int pY, pCb, pCr, pR, pG, pB;
02028   int h, v, horiz, vert, hSub, vSub;
02029   int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i;
02030   int c;
02031 
02032   for (x1 = 0; x1 < width; x1 += mcuWidth) {
02033 
02034     // deal with restart marker
02035     if (restartInterval > 0 && restartCtr == 0) {
02036       c = readMarker();
02037       if (c != restartMarker) {
02038         error(getPos(), "Bad DCT data: incorrect restart marker");
02039         return gFalse;
02040       }
02041       if (++restartMarker == 0xd8)
02042         restartMarker = 0xd0;
02043       restart();
02044     }
02045 
02046     // read one MCU
02047     for (cc = 0; cc < numComps; ++cc) {
02048       h = compInfo[cc].hSample;
02049       v = compInfo[cc].vSample;
02050       horiz = mcuWidth / h;
02051       vert = mcuHeight / v;
02052       hSub = horiz / 8;
02053       vSub = vert / 8;
02054       for (y2 = 0; y2 < mcuHeight; y2 += vert) {
02055         for (x2 = 0; x2 < mcuWidth; x2 += horiz) {
02056           if (!readDataUnit(&dcHuffTables[compInfo[cc].dcHuffTable],
02057                             &acHuffTables[compInfo[cc].acHuffTable],
02058                             quantTables[compInfo[cc].quantTable],
02059                             &compInfo[cc].prevDC,
02060                             data))
02061             return gFalse;
02062           if (hSub == 1 && vSub == 1) {
02063             for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) {
02064               p1 = &rowBuf[cc][y2+y3][x1+x2];
02065               p1[0] = data[i];
02066               p1[1] = data[i+1];
02067               p1[2] = data[i+2];
02068               p1[3] = data[i+3];
02069               p1[4] = data[i+4];
02070               p1[5] = data[i+5];
02071               p1[6] = data[i+6];
02072               p1[7] = data[i+7];
02073             }
02074           } else if (hSub == 2 && vSub == 2) {
02075             for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) {
02076               p1 = &rowBuf[cc][y2+y3][x1+x2];
02077               p2 = &rowBuf[cc][y2+y3+1][x1+x2];
02078               p1[0] = p1[1] = p2[0] = p2[1] = data[i];
02079               p1[2] = p1[3] = p2[2] = p2[3] = data[i+1];
02080               p1[4] = p1[5] = p2[4] = p2[5] = data[i+2];
02081               p1[6] = p1[7] = p2[6] = p2[7] = data[i+3];
02082               p1[8] = p1[9] = p2[8] = p2[9] = data[i+4];
02083               p1[10] = p1[11] = p2[10] = p2[11] = data[i+5];
02084               p1[12] = p1[13] = p2[12] = p2[13] = data[i+6];
02085               p1[14] = p1[15] = p2[14] = p2[15] = data[i+7];
02086             }
02087           } else {
02088             i = 0;
02089             for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) {
02090               for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) {
02091                 for (y5 = 0; y5 < vSub; ++y5)
02092                   for (x5 = 0; x5 < hSub; ++x5)
02093                     rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data[i];
02094                 ++i;
02095               }
02096             }
02097           }
02098         }
02099       }
02100     }
02101     --restartCtr;
02102 
02103     // color space conversion
02104     if (colorXform) {
02105       // convert YCbCr to RGB
02106       if (numComps == 3) {
02107         for (y2 = 0; y2 < mcuHeight; ++y2) {
02108           for (x2 = 0; x2 < mcuWidth; ++x2) {
02109             pY = rowBuf[0][y2][x1+x2];
02110             pCb = rowBuf[1][y2][x1+x2] - 128;
02111             pCr = rowBuf[2][y2][x1+x2] - 128;
02112             pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
02113             rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR];
02114             pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
02115             rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG];
02116             pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
02117             rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB];
02118           }
02119         }
02120       // convert YCbCrK to CMYK (K is passed through unchanged)
02121       } else if (numComps == 4) {
02122         for (y2 = 0; y2 < mcuHeight; ++y2) {
02123           for (x2 = 0; x2 < mcuWidth; ++x2) {
02124             pY = rowBuf[0][y2][x1+x2];
02125             pCb = rowBuf[1][y2][x1+x2] - 128;
02126             pCr = rowBuf[2][y2][x1+x2] - 128;
02127             pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16;
02128             rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR];
02129             pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16;
02130             rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG];
02131             pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16;
02132             rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB];
02133           }
02134         }
02135       }
02136     }
02137   }
02138   return gTrue;
02139 }
02140 
02141 // This IDCT algorithm is taken from:
02142 //   Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
02143 //   "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
02144 //   IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
02145 //   988-991.
02146 // The stage numbers mentioned in the comments refer to Figure 1 in this
02147 // paper.
02148 #ifndef FP_IDCT
02149 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
02150                               DCTHuffTable *acHuffTable,
02151                               Guchar quantTable[64], int *prevDC,
02152                               Guchar data[64]) {
02153   int tmp1[64];
02154   int v0, v1, v2, v3, v4, v5, v6, v7, t;
02155   int run, size, amp;
02156   int c;
02157   int i, j;
02158 
02159   // Huffman decode and dequantize
02160   size = readHuffSym(dcHuffTable);
02161   if (size == 9999)
02162     return gFalse;
02163   if (size > 0) {
02164     amp = readAmp(size);
02165     if (amp == 9999)
02166       return gFalse;
02167   } else {
02168     amp = 0;
02169   }
02170   tmp1[0] = (*prevDC += amp) * quantTable[0];
02171   for (i = 1; i < 64; ++i)
02172     tmp1[i] = 0;
02173   i = 1;
02174   while (i < 64) {
02175     run = 0;
02176     while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
02177       run += 0x10;
02178     if (c == 9999)
02179       return gFalse;
02180     if (c == 0x00) {
02181       break;
02182     } else {
02183       run += (c >> 4) & 0x0f;
02184       size = c & 0x0f;
02185       amp = readAmp(size);
02186       if (amp == 9999)
02187         return gFalse;
02188       i += run;
02189       j = dctZigZag[i++];
02190       tmp1[j] = amp * quantTable[j];
02191     }
02192   }
02193 
02194   // inverse DCT on rows
02195   for (i = 0; i < 64; i += 8) {
02196 
02197     // stage 4
02198     v0 = (dctSqrt2 * tmp1[i+0] + 128) >> 8;
02199     v1 = (dctSqrt2 * tmp1[i+4] + 128) >> 8;
02200     v2 = tmp1[i+2];
02201     v3 = tmp1[i+6];
02202     v4 = (dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]) + 128) >> 8;
02203     v7 = (dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]) + 128) >> 8;
02204     v5 = tmp1[i+3] << 4;
02205     v6 = tmp1[i+5] << 4;
02206 
02207     // stage 3
02208     t = (v0 - v1+ 1) >> 1;
02209     v0 = (v0 + v1 + 1) >> 1;
02210     v1 = t;
02211     t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
02212     v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
02213     v3 = t;
02214     t = (v4 - v6 + 1) >> 1;
02215     v4 = (v4 + v6 + 1) >> 1;
02216     v6 = t;
02217     t = (v7 + v5 + 1) >> 1;
02218     v5 = (v7 - v5 + 1) >> 1;
02219     v7 = t;
02220 
02221     // stage 2
02222     t = (v0 - v3 + 1) >> 1;
02223     v0 = (v0 + v3 + 1) >> 1;
02224     v3 = t;
02225     t = (v1 - v2 + 1) >> 1;
02226     v1 = (v1 + v2 + 1) >> 1;
02227     v2 = t;
02228     t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
02229     v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
02230     v7 = t;
02231     t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
02232     v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
02233     v6 = t;
02234 
02235     // stage 1
02236     tmp1[i+0] = v0 + v7;
02237     tmp1[i+7] = v0 - v7;
02238     tmp1[i+1] = v1 + v6;
02239     tmp1[i+6] = v1 - v6;
02240     tmp1[i+2] = v2 + v5;
02241     tmp1[i+5] = v2 - v5;
02242     tmp1[i+3] = v3 + v4;
02243     tmp1[i+4] = v3 - v4;
02244   }
02245 
02246   // inverse DCT on columns
02247   for (i = 0; i < 8; ++i) {
02248 
02249     // stage 4
02250     v0 = (dctSqrt2 * tmp1[0*8+i] + 2048) >> 12;
02251     v1 = (dctSqrt2 * tmp1[4*8+i] + 2048) >> 12;
02252     v2 = tmp1[2*8+i];
02253     v3 = tmp1[6*8+i];
02254     v4 = (dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]) + 2048) >> 12;
02255     v7 = (dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]) + 2048) >> 12;
02256     v5 = tmp1[3*8+i];
02257     v6 = tmp1[5*8+i];
02258 
02259     // stage 3
02260     t = (v0 - v1 + 1) >> 1;
02261     v0 = (v0 + v1 + 1) >> 1;
02262     v1 = t;
02263     t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
02264     v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
02265     v3 = t;
02266     t = (v4 - v6 + 1) >> 1;
02267     v4 = (v4 + v6 + 1) >> 1;
02268     v6 = t;
02269     t = (v7 + v5 + 1) >> 1;
02270     v5 = (v7 - v5 + 1) >> 1;
02271     v7 = t;
02272 
02273     // stage 2
02274     t = (v0 - v3 + 1) >> 1;
02275     v0 = (v0 + v3 + 1) >> 1;
02276     v3 = t;
02277     t = (v1 - v2 + 1) >> 1;
02278     v1 = (v1 + v2 + 1) >> 1;
02279     v2 = t;
02280     t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
02281     v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
02282     v7 = t;
02283     t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
02284     v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
02285     v6 = t;
02286 
02287     // stage 1
02288     tmp1[0*8+i] = v0 + v7;
02289     tmp1[7*8+i] = v0 - v7;
02290     tmp1[1*8+i] = v1 + v6;
02291     tmp1[6*8+i] = v1 - v6;
02292     tmp1[2*8+i] = v2 + v5;
02293     tmp1[5*8+i] = v2 - v5;
02294     tmp1[3*8+i] = v3 + v4;
02295     tmp1[4*8+i] = v3 - v4;
02296   }
02297 
02298   // convert to 8-bit integers
02299   for (i = 0; i < 64; ++i)
02300     data[i] = dctClip[dctClipOffset + 128 + ((tmp1[i] + 8) >> 4)];
02301 
02302   return gTrue;
02303 }
02304 #endif
02305 
02306 #ifdef FP_IDCT
02307 GBool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable,
02308                               DCTHuffTable *acHuffTable,
02309                               Guchar quantTable[64], int *prevDC,
02310                               Guchar data[64]) {
02311   fouble tmp1[64];
02312   fouble v0, v1, v2, v3, v4, v5, v6, v7, t;
02313   int run, size, amp;
02314   int c;
02315   int i, j;
02316 
02317   // Huffman decode and dequantize
02318   size = readHuffSym(dcHuffTable);
02319   if (size == 9999)
02320     return gFalse;
02321   if (size > 0) {
02322     amp = readAmp(size);
02323     if (amp == 9999)
02324       return gFalse;
02325   } else {
02326     amp = 0;
02327   }
02328   tmp1[0] = (*prevDC += amp) * quantTable[0];
02329   for (i = 1; i < 64; ++i)
02330     tmp1[i] = 0;
02331   i = 1;
02332   while (i < 64) {
02333     run = 0;
02334     while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30)
02335       run += 0x10;
02336     if (c == 9999)
02337       return gFalse;
02338     if (c == 0x00) {
02339       break;
02340     } else {
02341       run += (c >> 4) & 0x0f;
02342       size = c & 0x0f;
02343       amp = readAmp(size);
02344       if (amp == 9999)
02345         return gFalse;
02346       i += run;
02347       j = dctZigZag[i++];
02348       tmp1[j] = amp * quantTable[j];
02349     }
02350   }
02351 
02352   // inverse DCT on rows
02353   for (i = 0; i < 64; i += 8) {
02354 
02355     // stage 4
02356     v0 = dctSqrt2 * tmp1[i+0];
02357     v1 = dctSqrt2 * tmp1[i+4];
02358     v2 = tmp1[i+2];
02359     v3 = tmp1[i+6];
02360     v4 = dctSqrt1d2 * (tmp1[i+1] - tmp1[i+7]);
02361     v7 = dctSqrt1d2 * (tmp1[i+1] + tmp1[i+7]);
02362     v5 = tmp1[i+3];
02363     v6 = tmp1[i+5];
02364 
02365     // stage 3
02366     t = 0.5 * (v0 - v1);
02367     v0 = 0.5 * (v0 + v1);
02368     v1 = t;
02369     t = v2 * dctSin6 + v3 * dctCos6;
02370     v2 = v2 * dctCos6 - v3 * dctSin6;
02371     v3 = t;
02372     t = 0.5 * (v4 - v6);
02373     v4 = 0.5 * (v4 + v6);
02374     v6 = t;
02375     t = 0.5 * (v7 + v5);
02376     v5 = 0.5 * (v7 - v5);
02377     v7 = t;
02378 
02379     // stage 2
02380     t = 0.5 * (v0 - v3);
02381     v0 = 0.5 * (v0 + v3);
02382     v3 = t;
02383     t = 0.5 * (v1 - v2);
02384     v1 = 0.5 * (v1 + v2);
02385     v2 = t;
02386     t = v4 * dctSin3 + v7 * dctCos3;
02387     v4 = v4 * dctCos3 - v7 * dctSin3;
02388     v7 = t;
02389     t = v5 * dctSin1 + v6 * dctCos1;
02390     v5 = v5 * dctCos1 - v6 * dctSin1;
02391     v6 = t;
02392 
02393     // stage 1
02394     tmp1[i+0] = v0 + v7;
02395     tmp1[i+7] = v0 - v7;
02396     tmp1[i+1] = v1 + v6;
02397     tmp1[i+6] = v1 - v6;
02398     tmp1[i+2] = v2 + v5;
02399     tmp1[i+5] = v2 - v5;
02400     tmp1[i+3] = v3 + v4;
02401     tmp1[i+4] = v3 - v4;
02402   }
02403 
02404   // inverse DCT on columns
02405   for (i = 0; i < 8; ++i) {
02406 
02407     // stage 4
02408     v0 = dctSqrt2 * tmp1[0*8+i];
02409     v1 = dctSqrt2 * tmp1[4*8+i];
02410     v2 = tmp1[2*8+i];
02411     v3 = tmp1[6*8+i];
02412     v4 = dctSqrt1d2 * (tmp1[1*8+i] - tmp1[7*8+i]);
02413     v7 = dctSqrt1d2 * (tmp1[1*8+i] + tmp1[7*8+i]);
02414     v5 = tmp1[3*8+i];
02415     v6 = tmp1[5*8+i];
02416 
02417     // stage 3
02418     t = 0.5 * (v0 - v1);
02419     v0 = 0.5 * (v0 + v1);
02420     v1 = t;
02421     t = v2 * dctSin6 + v3 * dctCos6;
02422     v2 = v2 * dctCos6 - v3 * dctSin6;
02423     v3 = t;
02424     t = 0.5 * (v4 - v6);
02425     v4 = 0.5 * (v4 + v6);
02426     v6 = t;
02427     t = 0.5 * (v7 + v5);
02428     v5 = 0.5 * (v7 - v5);
02429     v7 = t;
02430 
02431     // stage 2
02432     t = 0.5 * (v0 - v3);
02433     v0 = 0.5 * (v0 + v3);
02434     v3 = t;
02435     t = 0.5 * (v1 - v2);
02436     v1 = 0.5 * (v1 + v2);
02437     v2 = t;
02438     t = v4 * dctSin3 + v7 * dctCos3;
02439     v4 = v4 * dctCos3 - v7 * dctSin3;
02440     v7 = t;
02441     t = v5 * dctSin1 + v6 * dctCos1;
02442     v5 = v5 * dctCos1 - v6 * dctSin1;
02443     v6 = t;
02444 
02445     // stage 1
02446     tmp1[0*8+i] = v0 + v7;
02447     tmp1[7*8+i] = v0 - v7;
02448     tmp1[1*8+i] = v1 + v6;
02449     tmp1[6*8+i] = v1 - v6;
02450     tmp1[2*8+i] = v2 + v5;
02451     tmp1[5*8+i] = v2 - v5;
02452     tmp1[3*8+i] = v3 + v4;
02453     tmp1[4*8+i] = v3 - v4;
02454   }
02455 
02456   // convert to 8-bit integers
02457   for (i = 0; i < 64; ++i)
02458     data[i] = dctClip[dctClipOffset + (int)(tmp1[i] + 128.5)];
02459 
02460   return gTrue;
02461 }
02462 #endif
02463 
02464 int DCTStream::readHuffSym(DCTHuffTable *table) {
02465   Gushort code;
02466   int bit;
02467   int codeBits;
02468 
02469   code = 0;
02470   codeBits = 0;
02471   do {
02472     // add a bit to the code
02473     if ((bit = readBit()) == EOF)
02474       return 9999;
02475     code = (code << 1) + bit;
02476     ++codeBits;
02477 
02478     // look up code
02479     if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) {
02480       code -= table->firstCode[codeBits];
02481       return table->sym[table->firstSym[codeBits] + code];
02482     }
02483   } while (codeBits < 16);
02484 
02485   error(getPos(), "Bad Huffman code in DCT stream");
02486   return 9999;
02487 }
02488 
02489 int DCTStream::readAmp(int size) {
02490   int amp, bit;
02491   int bits;
02492 
02493   amp = 0;
02494   for (bits = 0; bits < size; ++bits) {
02495     if ((bit = readBit()) == EOF)
02496       return 9999;
02497     amp = (amp << 1) + bit;
02498   }
02499   if (amp < (1 << (size - 1)))
02500     amp -= (1 << size) - 1;
02501   return amp;
02502 }
02503 
02504 int DCTStream::readBit() {
02505   int bit;
02506   int c, c2;
02507 
02508   if (inputBits == 0) {
02509     if ((c = str->getChar()) == EOF)
02510       return EOF;
02511     if (c == 0xff) {
02512       do {
02513         c2 = str->getChar();
02514       } while (c2 == 0xff);
02515       if (c2 != 0x00) {
02516         error(getPos(), "Bad DCT data: missing 00 after ff");
02517         return EOF;
02518       }
02519     }
02520     inputBuf = c;
02521     inputBits = 8;
02522   }
02523   bit = (inputBuf >> (inputBits - 1)) & 1;
02524   --inputBits;
02525   return bit;
02526 }
02527 
02528 GBool DCTStream::readHeader() {
02529   GBool doScan;
02530   int minHSample, minVSample;
02531   int bufWidth;
02532   int n;
02533   int c = 0;
02534   int i, j;
02535 
02536   width = height = 0;
02537   numComps = 0;
02538   numQuantTables = 0;
02539   numDCHuffTables = 0;
02540   numACHuffTables = 0;
02541   colorXform = 0;
02542   gotAdobeMarker = gFalse;
02543   restartInterval = 0;
02544 
02545   // read headers
02546   doScan = gFalse;
02547   while (!doScan) {
02548     c = readMarker();
02549     switch (c) {
02550     case 0xc0:                  // SOF0
02551       if (!readFrameInfo())
02552         return gFalse;
02553       break;
02554     case 0xc4:                  // DHT
02555       if (!readHuffmanTables())
02556         return gFalse;
02557       break;
02558     case 0xd8:                  // SOI
02559       break;
02560     case 0xda:                  // SOS
02561       if (!readScanInfo())
02562         return gFalse;
02563       doScan = gTrue;
02564       break;
02565     case 0xdb:                  // DQT
02566       if (!readQuantTables())
02567         return gFalse;
02568       break;
02569     case 0xdd:                  // DRI
02570       if (!readRestartInterval())
02571         return gFalse;
02572       break;
02573     case 0xee:                  // APP14
02574       if (!readAdobeMarker())
02575         return gFalse;
02576       break;
02577     case EOF:
02578       error(getPos(), "Bad DCT header");
02579       return gFalse;
02580     default:
02581       // skip APPn / COM / etc.
02582       if (c >= 0xe0) {
02583         n = read16() - 2;
02584         for (i = 0; i < n; ++i)
02585           str->getChar();
02586       } else {
02587         error(getPos(), "Unknown DCT marker <%02x>", c);
02588         return gFalse;
02589       }
02590       break;
02591     }
02592   }
02593 
02594   // compute MCU size
02595   mcuWidth = minHSample = compInfo[0].hSample;
02596   mcuHeight = minVSample = compInfo[0].vSample;
02597   for (i = 1; i < numComps; ++i) {
02598     if (compInfo[i].hSample < minHSample)
02599       minHSample = compInfo[i].hSample;
02600     if (compInfo[i].vSample < minVSample)
02601       minVSample = compInfo[i].vSample;
02602     if (compInfo[i].hSample > mcuWidth)
02603       mcuWidth = compInfo[i].hSample;
02604     if (compInfo[i].vSample > mcuHeight)
02605       mcuHeight = compInfo[i].vSample;
02606   }
02607   for (i = 0; i < numComps; ++i) {
02608     compInfo[i].hSample /= minHSample;
02609     compInfo[i].vSample /= minVSample;
02610   }
02611   mcuWidth = (mcuWidth / minHSample) * 8;
02612   mcuHeight = (mcuHeight / minVSample) * 8;
02613 
02614   // allocate buffers
02615   bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
02616   for (i = 0; i < numComps; ++i)
02617     for (j = 0; j < mcuHeight; ++j)
02618       rowBuf[i][j] = (Guchar *)gmalloc(bufWidth * sizeof(Guchar));
02619 
02620   // figure out color transform
02621   if (!gotAdobeMarker && numComps == 3) {
02622     if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) {
02623       colorXform = 1;
02624     }
02625   }
02626 
02627   // initialize counters
02628   comp = 0;
02629   x = 0;
02630   y = 0;
02631   dy = mcuHeight;
02632 
02633   return gTrue;
02634 }
02635 
02636 GBool DCTStream::readFrameInfo() {
02637   int length;
02638   int prec;
02639   int i;
02640   int c;
02641 
02642   length = read16() - 2;
02643   prec = str->getChar();
02644   height = read16();
02645   width = read16();
02646   numComps = str->getChar();
02647   length -= 6;
02648   if (prec != 8) {
02649     error(getPos(), "Bad DCT precision %d", prec);
02650     return gFalse;
02651   }
02652   for (i = 0; i < numComps; ++i) {
02653     compInfo[i].id = str->getChar();
02654     compInfo[i].inScan = gFalse;
02655     c = str->getChar();
02656     compInfo[i].hSample = (c >> 4) & 0x0f;
02657     compInfo[i].vSample = c & 0x0f;
02658     compInfo[i].quantTable = str->getChar();
02659     compInfo[i].dcHuffTable = 0;
02660     compInfo[i].acHuffTable = 0;
02661   }
02662   return gTrue;
02663 }
02664 
02665 GBool DCTStream::readScanInfo() {
02666   int length;
02667   int scanComps, id, c;
02668   int i, j;
02669 
02670   length = read16() - 2;
02671   scanComps = str->getChar();
02672   --length;
02673   if (length != 2 * scanComps + 3) {
02674     error(getPos(), "Bad DCT scan info block");
02675     return gFalse;
02676   }
02677   for (i = 0; i < scanComps; ++i) {
02678     id = str->getChar();
02679     for (j = 0; j < numComps; ++j) {
02680       if (id == compInfo[j].id)
02681         break;
02682     }
02683     if (j == numComps) {
02684       error(getPos(), "Bad DCT component ID in scan info block");
02685       return gFalse;
02686     }
02687     compInfo[j].inScan = gTrue;
02688     c = str->getChar();
02689     compInfo[j].dcHuffTable = (c >> 4) & 0x0f;
02690     compInfo[j].acHuffTable = c & 0x0f;
02691   }
02692   str->getChar();
02693   str->getChar();
02694   str->getChar();
02695   return gTrue;
02696 }
02697 
02698 GBool DCTStream::readQuantTables() {
02699   int length;
02700   int i;
02701   int index;
02702 
02703   length = read16() - 2;
02704   while (length > 0) {
02705     index = str->getChar();
02706     if ((index & 0xf0) || index >= 4) {
02707       error(getPos(), "Bad DCT quantization table");
02708       return gFalse;
02709     }
02710     if (index == numQuantTables)
02711       numQuantTables = index + 1;
02712     for (i = 0; i < 64; ++i)
02713       quantTables[index][dctZigZag[i]] = str->getChar();
02714     length -= 65;
02715   }
02716   return gTrue;
02717 }
02718 
02719 GBool DCTStream::readHuffmanTables() {
02720   DCTHuffTable *tbl;
02721   int length;
02722   int index;
02723   Gushort code;
02724   Guchar sym;
02725   int i;
02726   int c;
02727 
02728   length = read16() - 2;
02729   while (length > 0) {
02730     index = str->getChar();
02731     --length;
02732     if ((index & 0x0f) >= 4) {
02733       error(getPos(), "Bad DCT Huffman table");
02734       return gFalse;
02735     }
02736     if (index & 0x10) {
02737       index &= 0x0f;
02738       if (index >= numACHuffTables)
02739         numACHuffTables = index+1;
02740       tbl = &acHuffTables[index];
02741     } else {
02742       if (index >= numDCHuffTables)
02743         numDCHuffTables = index+1;
02744       tbl = &dcHuffTables[index];
02745     }
02746     sym = 0;
02747     code = 0;
02748     for (i = 1; i <= 16; ++i) {
02749       c = str->getChar();
02750       tbl->firstSym[i] = sym;
02751       tbl->firstCode[i] = code;
02752       tbl->numCodes[i] = c;
02753       sym += c;
02754       code = (code + c) << 1;
02755     }
02756     length -= 16;
02757     for (i = 0; i < sym; ++i)
02758       tbl->sym[i] = str->getChar();
02759     length -= sym;
02760   }
02761   return gTrue;
02762 }
02763 
02764 GBool DCTStream::readRestartInterval() {
02765   int length;
02766 
02767   length = read16();
02768   if (length != 4) {
02769     error(getPos(), "Bad DCT restart interval");
02770     return gFalse;
02771   }
02772   restartInterval = read16();
02773   return gTrue;
02774 }
02775 
02776 GBool DCTStream::readAdobeMarker() {
02777   int length, i;
02778   char buf[12];
02779   int c;
02780 
02781   length = read16();
02782   if (length != 14)
02783     goto err;
02784   for (i = 0; i < 12; ++i) {
02785     if ((c = str->getChar()) == EOF)
02786       goto err;
02787     buf[i] = c;
02788   }
02789   if (strncmp(buf, "Adobe", 5))
02790     goto err;
02791   colorXform = buf[11];
02792   gotAdobeMarker = gTrue;
02793   return gTrue;
02794 
02795  err:
02796   error(getPos(), "Bad DCT Adobe APP14 marker");
02797   return gFalse;
02798 }
02799 
02800 GBool DCTStream::readTrailer() {
02801   int c;
02802 
02803   c = readMarker();
02804   if (c != 0xd9) {              // EOI
02805     error(getPos(), "Bad DCT trailer");
02806     return gFalse;
02807   }
02808   return gTrue;
02809 }
02810 
02811 int DCTStream::readMarker() {
02812   int c;
02813 
02814   do {
02815     do {
02816       c = str->getChar();
02817     } while (c != 0xff);
02818     do {
02819       c = str->getChar();
02820     } while (c == 0xff);
02821   } while (c == 0x00);
02822   return c;
02823 }
02824 
02825 int DCTStream::read16() {
02826   int c1, c2;
02827 
02828   if ((c1 = str->getChar()) == EOF)
02829     return EOF;
02830   if ((c2 = str->getChar()) == EOF)
02831     return EOF;
02832   return (c1 << 8) + c2;
02833 }
02834 
02835 GString *DCTStream::getPSFilter(char *indent) {
02836   GString *s;
02837 
02838   if (!(s = str->getPSFilter(indent))) {
02839     return NULL;
02840   }
02841   s->append(indent)->append("<< >> /DCTDecode filter\n");
02842   return s;
02843 }
02844 
02845 GBool DCTStream::isBinary(GBool last) {
02846   return str->isBinary(gTrue);
02847 }
02848 
02849 //------------------------------------------------------------------------
02850 // FlateStream
02851 //------------------------------------------------------------------------
02852 
02853 int FlateStream::codeLenCodeMap[flateMaxCodeLenCodes] = {
02854   16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
02855 };
02856 
02857 FlateDecode FlateStream::lengthDecode[flateMaxLitCodes-257] = {
02858   {0,   3},
02859   {0,   4},
02860   {0,   5},
02861   {0,   6},
02862   {0,   7},
02863   {0,   8},
02864   {0,   9},
02865   {0,  10},
02866   {1,  11},
02867   {1,  13},
02868   {1,  15},
02869   {1,  17},
02870   {2,  19},
02871   {2,  23},
02872   {2,  27},
02873   {2,  31},
02874   {3,  35},
02875   {3,  43},
02876   {3,  51},
02877   {3,  59},
02878   {4,  67},
02879   {4,  83},
02880   {4,  99},
02881   {4, 115},
02882   {5, 131},
02883   {5, 163},
02884   {5, 195},
02885   {5, 227},
02886   {0, 258}
02887 };
02888 
02889 FlateDecode FlateStream::distDecode[flateMaxDistCodes] = {
02890   { 0,     1},
02891   { 0,     2},
02892   { 0,     3},
02893   { 0,     4},
02894   { 1,     5},
02895   { 1,     7},
02896   { 2,     9},
02897   { 2,    13},
02898   { 3,    17},
02899   { 3,    25},
02900   { 4,    33},
02901   { 4,    49},
02902   { 5,    65},
02903   { 5,    97},
02904   { 6,   129},
02905   { 6,   193},
02906   { 7,   257},
02907   { 7,   385},
02908   { 8,   513},
02909   { 8,   769},
02910   { 9,  1025},
02911   { 9,  1537},
02912   {10,  2049},
02913   {10,  3073},
02914   {11,  4097},
02915   {11,  6145},
02916   {12,  8193},
02917   {12, 12289},
02918   {13, 16385},
02919   {13, 24577}
02920 };
02921 
02922 FlateStream::FlateStream(Stream *strA, int predictor, int columns,
02923                          int colors, int bits):
02924     FilterStream(strA) {
02925   if (predictor != 1) {
02926     pred = new StreamPredictor(this, predictor, columns, colors, bits);
02927   } else {
02928     pred = NULL;
02929   }
02930 }
02931 
02932 FlateStream::~FlateStream() {
02933   if (pred) {
02934     delete pred;
02935   }
02936   delete str;
02937 }
02938 
02939 void FlateStream::reset() {
02940   int cmf, flg;
02941 
02942   index = 0;
02943   remain = 0;
02944   codeBuf = 0;
02945   codeSize = 0;
02946   compressedBlock = gFalse;
02947   endOfBlock = gTrue;
02948   eof = gTrue;
02949 
02950   str->reset();
02951 
02952   // read header
02953   //~ need to look at window size?
02954   endOfBlock = eof = gTrue;
02955   cmf = str->getChar();
02956   flg = str->getChar();
02957   if (cmf == EOF || flg == EOF)
02958     return;
02959   if ((cmf & 0x0f) != 0x08) {
02960     error(getPos(), "Unknown compression method in flate stream");
02961     return;
02962   }
02963   if ((((cmf << 8) + flg) % 31) != 0) {
02964     error(getPos(), "Bad FCHECK in flate stream");
02965     return;
02966   }
02967   if (flg & 0x20) {
02968     error(getPos(), "FDICT bit set in flate stream");
02969     return;
02970   }
02971 
02972   eof = gFalse;
02973 }
02974 
02975 int FlateStream::getChar() {
02976   int c;
02977 
02978   if (pred) {
02979     return pred->getChar();
02980   }
02981   while (remain == 0) {
02982     if (endOfBlock && eof)
02983       return EOF;
02984     readSome();
02985   }
02986   c = buf[index];
02987   index = (index + 1) & flateMask;
02988   --remain;
02989   return c;
02990 }
02991 
02992 int FlateStream::lookChar() {
02993   int c;
02994 
02995   if (pred) {
02996     return pred->lookChar();
02997   }
02998   while (remain == 0) {
02999     if (endOfBlock && eof)
03000       return EOF;
03001     readSome();
03002   }
03003   c = buf[index];
03004   return c;
03005 }
03006 
03007 int FlateStream::getRawChar() {
03008   int c;
03009 
03010   while (remain == 0) {
03011     if (endOfBlock && eof)
03012       return EOF;
03013     readSome();
03014   }
03015   c = buf[index];
03016   index = (index + 1) & flateMask;
03017   --remain;
03018   return c;
03019 }
03020 
03021 GString *FlateStream::getPSFilter(char *indent) {
03022   return NULL;
03023 }
03024 
03025 GBool FlateStream::isBinary(GBool last) {
03026   return str->isBinary(gTrue);
03027 }
03028 
03029 void FlateStream::readSome() {
03030   int code1, code2;
03031   int len, dist;
03032   int i, j, k;
03033   int c;
03034 
03035   if (endOfBlock) {
03036     if (!startBlock())
03037       return;
03038   }
03039 
03040   if (compressedBlock) {
03041     if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF)
03042       goto err;
03043     if (code1 < 256) {
03044       buf[index] = code1;
03045       remain = 1;
03046     } else if (code1 == 256) {
03047       endOfBlock = gTrue;
03048       remain = 0;
03049     } else {
03050       code1 -= 257;
03051       code2 = lengthDecode[code1].bits;
03052       if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
03053         goto err;
03054       len = lengthDecode[code1].first + code2;
03055       if ((code1 = getHuffmanCodeWord(&distCodeTab)) == EOF)
03056         goto err;
03057       code2 = distDecode[code1].bits;
03058       if (code2 > 0 && (code2 = getCodeWord(code2)) == EOF)
03059         goto err;
03060       dist = distDecode[code1].first + code2;
03061       i = index;
03062       j = (index - dist) & flateMask;
03063       for (k = 0; k < len; ++k) {
03064         buf[i] = buf[j];
03065         i = (i + 1) & flateMask;
03066         j = (j + 1) & flateMask;
03067       }
03068       remain = len;
03069     }
03070 
03071   } else {
03072     len = (blockLen < flateWindow) ? blockLen : flateWindow;
03073     for (i = 0, j = index; i < len; ++i, j = (j + 1) & flateMask) {
03074       if ((c = str->getChar()) == EOF) {
03075         endOfBlock = eof = gTrue;
03076         break;
03077       }
03078       buf[j] = c & 0xff;
03079     }
03080     remain = i;
03081     blockLen -= len;
03082     if (blockLen == 0)
03083       endOfBlock = gTrue;
03084   }
03085 
03086   return;
03087 
03088 err:
03089   error(getPos(), "Unexpected end of file in flate stream");
03090   endOfBlock = eof = gTrue;
03091   remain = 0;
03092 }
03093 
03094 GBool FlateStream::startBlock() {
03095   int blockHdr;
03096   int c;
03097   int check;
03098 
03099   // read block header
03100   blockHdr = getCodeWord(3);
03101   if (blockHdr & 1)
03102     eof = gTrue;
03103   blockHdr >>= 1;
03104 
03105   // uncompressed block
03106   if (blockHdr == 0) {
03107     compressedBlock = gFalse;
03108     if ((c = str->getChar()) == EOF)
03109       goto err;
03110     blockLen = c & 0xff;
03111     if ((c = str->getChar()) == EOF)
03112       goto err;
03113     blockLen |= (c & 0xff) << 8;
03114     if ((c = str->getChar()) == EOF)
03115       goto err;
03116     check = c & 0xff;
03117     if ((c = str->getChar()) == EOF)
03118       goto err;
03119     check |= (c & 0xff) << 8;
03120     if (check != (~blockLen & 0xffff))
03121       error(getPos(), "Bad uncompressed block length in flate stream");
03122     codeBuf = 0;
03123     codeSize = 0;
03124 
03125   // compressed block with fixed codes
03126   } else if (blockHdr == 1) {
03127     compressedBlock = gTrue;
03128     loadFixedCodes();
03129 
03130   // compressed block with dynamic codes
03131   } else if (blockHdr == 2) {
03132     compressedBlock = gTrue;
03133     if (!readDynamicCodes())
03134       goto err;
03135 
03136   // unknown block type
03137   } else {
03138     goto err;
03139   }
03140 
03141   endOfBlock = gFalse;
03142   return gTrue;
03143 
03144 err:
03145   error(getPos(), "Bad block header in flate stream");
03146   endOfBlock = eof = gTrue;
03147   return gFalse;
03148 }
03149 
03150 void FlateStream::loadFixedCodes() {
03151   int i;
03152 
03153   // set up code arrays
03154   litCodeTab.codes = allCodes;
03155   distCodeTab.codes = allCodes + flateMaxLitCodes;
03156 
03157   // initialize literal code table
03158   for (i = 0; i <= 143; ++i)
03159     litCodeTab.codes[i].len = 8;
03160   for (i = 144; i <= 255; ++i)
03161     litCodeTab.codes[i].len = 9;
03162   for (i = 256; i <= 279; ++i)
03163     litCodeTab.codes[i].len = 7;
03164   for (i = 280; i <= 287; ++i)
03165     litCodeTab.codes[i].len = 8;
03166   compHuffmanCodes(&litCodeTab, flateMaxLitCodes);
03167 
03168   // initialize distance code table
03169   for (i = 0; i <= 5; ++i) {
03170     distCodeTab.start[i] = 0;
03171   }
03172   for (i = 6; i <= flateMaxHuffman+1; ++i) {
03173     distCodeTab.start[i] = flateMaxDistCodes;
03174   }
03175   for (i = 0; i < flateMaxDistCodes; ++i) {
03176     distCodeTab.codes[i].len = 5;
03177     distCodeTab.codes[i].code = i;
03178     distCodeTab.codes[i].val = i;
03179   }
03180 }
03181 
03182 GBool FlateStream::readDynamicCodes() {
03183   int numCodeLenCodes;
03184   int numLitCodes;
03185   int numDistCodes;
03186   FlateCode codeLenCodes[flateMaxCodeLenCodes];
03187   FlateHuffmanTab codeLenCodeTab;
03188   int len, repeat, code;
03189   int i;
03190 
03191   // read lengths
03192   if ((numLitCodes = getCodeWord(5)) == EOF)
03193     goto err;
03194   numLitCodes += 257;
03195   if ((numDistCodes = getCodeWord(5)) == EOF)
03196     goto err;
03197   numDistCodes += 1;
03198   if ((numCodeLenCodes = getCodeWord(4)) == EOF)
03199     goto err;
03200   numCodeLenCodes += 4;
03201   if (numLitCodes > flateMaxLitCodes ||
03202       numDistCodes > flateMaxDistCodes ||
03203       numCodeLenCodes > flateMaxCodeLenCodes)
03204     goto err;
03205 
03206   // read code length code table
03207   codeLenCodeTab.codes = codeLenCodes;
03208   for (i = 0; i < flateMaxCodeLenCodes; ++i)
03209     codeLenCodes[i].len = 0;
03210   for (i = 0; i < numCodeLenCodes; ++i) {
03211     if ((codeLenCodes[codeLenCodeMap[i]].len = getCodeWord(3)) == -1)
03212       goto err;
03213   }
03214   compHuffmanCodes(&codeLenCodeTab, flateMaxCodeLenCodes);
03215 
03216   // set up code arrays
03217   litCodeTab.codes = allCodes;
03218   distCodeTab.codes = allCodes + numLitCodes;
03219 
03220   // read literal and distance code tables
03221   len = 0;
03222   repeat = 0;
03223   i = 0;
03224   while (i < numLitCodes + numDistCodes) {
03225     if ((code = getHuffmanCodeWord(&codeLenCodeTab)) == EOF)
03226       goto err;
03227     if (code == 16) {
03228       if ((repeat = getCodeWord(2)) == EOF)
03229         goto err;
03230       for (repeat += 3; repeat > 0; --repeat)
03231         allCodes[i++].len = len;
03232     } else if (code == 17) {
03233       if ((repeat = getCodeWord(3)) == EOF)
03234         goto err;
03235       len = 0;
03236       for (repeat += 3; repeat > 0; --repeat)
03237         allCodes[i++].len = 0;
03238     } else if (code == 18) {
03239       if ((repeat = getCodeWord(7)) == EOF)
03240         goto err;
03241       len = 0;
03242       for (repeat += 11; repeat > 0; --repeat)
03243         allCodes[i++].len = 0;
03244     } else {
03245       allCodes[i++].len = len = code;
03246     }
03247   }
03248   compHuffmanCodes(&litCodeTab, numLitCodes);
03249   compHuffmanCodes(&distCodeTab, numDistCodes);
03250 
03251   return gTrue;
03252 
03253 err:
03254   error(getPos(), "Bad dynamic code table in flate stream");
03255   return gFalse;
03256 }
03257 
03258 // On entry, the <tab->codes> array contains the lengths of each code,
03259 // stored in code value order.  This function computes the code words.
03260 // The result is sorted in order of (1) code length and (2) code word.
03261 // The length values are no longer valid.  The <tab->start> array is
03262 // filled with the indexes of the first code of each length.
03263 void FlateStream::compHuffmanCodes(FlateHuffmanTab *tab, int n) {
03264   int numLengths[flateMaxHuffman+1];
03265   int nextCode[flateMaxHuffman+1];
03266   int nextIndex[flateMaxHuffman+2];
03267   int code;
03268   int i, j;
03269 
03270   // count number of codes for each code length
03271   for (i = 0; i <= flateMaxHuffman; ++i)
03272     numLengths[i] = 0;
03273   for (i = 0; i < n; ++i)
03274     ++numLengths[tab->codes[i].len];
03275 
03276   // compute first index for each length
03277   tab->start[0] = nextIndex[0] = 0;
03278   for (i = 1; i <= flateMaxHuffman + 1; ++i)
03279     tab->start[i] = nextIndex[i] = tab->start[i-1] + numLengths[i-1];
03280 
03281   // compute first code for each length
03282   code = 0;
03283   numLengths[0] = 0;
03284   for (i = 1; i <= flateMaxHuffman; ++i) {
03285     code = (code + numLengths[i-1]) << 1;
03286     nextCode[i] = code;
03287   }
03288 
03289   // compute the codes -- this permutes the codes array from value
03290   // order to length/code order
03291   for (i = 0; i < n; ++i) {
03292     j = nextIndex[tab->codes[i].len]++;
03293     if (tab->codes[i].len == 0)
03294       tab->codes[j].code = 0;
03295     else
03296       tab->codes[j].code = nextCode[tab->codes[i].len]++;
03297     tab->codes[j].val = i;
03298   }
03299 }
03300 
03301 int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) {
03302   int len;
03303   int code;
03304   int c;
03305   int i, j;
03306 
03307   code = 0;
03308   for (len = 1; len <= flateMaxHuffman; ++len) {
03309 
03310     // add a bit to the code
03311     if (codeSize == 0) {
03312       if ((c = str->getChar()) == EOF)
03313         return EOF;
03314       codeBuf = c & 0xff;
03315       codeSize = 8;
03316     }
03317     code = (code << 1) | (codeBuf & 1);
03318     codeBuf >>= 1;
03319     --codeSize;
03320 
03321     // look for code
03322     i = tab->start[len];
03323     j = tab->start[len + 1];
03324     if (i < j && code >= tab->codes[i].code && code <= tab->codes[j-1].code) {
03325       i += code - tab->codes[i].code;
03326       return tab->codes[i].val;
03327     }
03328   }
03329 
03330   // not found
03331   error(getPos(), "Bad code (%04x) in flate stream", code);
03332   return EOF;
03333 }
03334 
03335 int FlateStream::getCodeWord(int bits) {
03336   int c;
03337 
03338   while (codeSize < bits) {
03339     if ((c = str->getChar()) == EOF)
03340       return EOF;
03341     codeBuf |= (c & 0xff) << codeSize;
03342     codeSize += 8;
03343   }
03344   c = codeBuf & ((1 << bits) - 1);
03345   codeBuf >>= bits;
03346   codeSize -= bits;
03347   return c;
03348 }
03349 
03350 //------------------------------------------------------------------------
03351 // EOFStream
03352 //------------------------------------------------------------------------
03353 
03354 EOFStream::EOFStream(Stream *strA):
03355     FilterStream(strA) {
03356 }
03357 
03358 EOFStream::~EOFStream() {
03359   delete str;
03360 }
03361 
03362 //------------------------------------------------------------------------
03363 // FixedLengthEncoder
03364 //------------------------------------------------------------------------
03365 
03366 FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA):
03367     FilterStream(strA) {
03368   length = lengthA;
03369   count = 0;
03370 }
03371 
03372 FixedLengthEncoder::~FixedLengthEncoder() {
03373   if (str->isEncoder())
03374     delete str;
03375 }
03376 
03377 void FixedLengthEncoder::reset() {
03378   str->reset();
03379   count = 0;
03380 }
03381 
03382 void FixedLengthEncoder::close() {
03383 }
03384 
03385 int FixedLengthEncoder::getChar() {
03386   if (length >= 0 && count >= length)
03387     return EOF;
03388   ++count;
03389   return str->getChar();
03390 }
03391 
03392 int FixedLengthEncoder::lookChar() {
03393   if (length >= 0 && count >= length)
03394     return EOF;
03395   return str->getChar();
03396 }
03397 
03398 //------------------------------------------------------------------------
03399 // ASCIIHexEncoder
03400 //------------------------------------------------------------------------
03401 
03402 ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA):
03403     FilterStream(strA) {
03404   bufPtr = bufEnd = buf;
03405   lineLen = 0;
03406   eof = gFalse;
03407 }
03408 
03409 ASCIIHexEncoder::~ASCIIHexEncoder() {
03410   if (str->isEncoder()) {
03411     delete str;
03412   }
03413 }
03414 
03415 void ASCIIHexEncoder::reset() {
03416   str->reset();
03417   bufPtr = bufEnd = buf;
03418   lineLen = 0;
03419   eof = gFalse;
03420 }
03421 
03422 void ASCIIHexEncoder::close() {
03423 }
03424 
03425 GBool ASCIIHexEncoder::fillBuf() {
03426   static char *hex = "0123456789abcdef";
03427   int c;
03428 
03429   if (eof) {
03430     return gFalse;
03431   }
03432   bufPtr = bufEnd = buf;
03433   if ((c = str->getChar()) == EOF) {
03434     *bufEnd++ = '>';
03435     eof = gTrue;
03436   } else {
03437     if (lineLen >= 64) {
03438       *bufEnd++ = '\n';
03439       lineLen = 0;
03440     }
03441     *bufEnd++ = hex[(c >> 4) & 0x0f];
03442     *bufEnd++ = hex[c & 0x0f];
03443     lineLen += 2;
03444   }
03445   return gTrue;
03446 }
03447 
03448 //------------------------------------------------------------------------
03449 // ASCII85Encoder
03450 //------------------------------------------------------------------------
03451 
03452 ASCII85Encoder::ASCII85Encoder(Stream *strA):
03453     FilterStream(strA) {
03454   bufPtr = bufEnd = buf;
03455   lineLen = 0;
03456   eof = gFalse;
03457 }
03458 
03459 ASCII85Encoder::~ASCII85Encoder() {
03460   if (str->isEncoder())
03461     delete str;
03462 }
03463 
03464 void ASCII85Encoder::reset() {
03465   str->reset();
03466   bufPtr = bufEnd = buf;
03467   lineLen = 0;
03468   eof = gFalse;
03469 }
03470 
03471 void ASCII85Encoder::close() {
03472 }
03473 
03474 GBool ASCII85Encoder::fillBuf() {
03475   Gulong t;
03476   char buf1[5];
03477   int c;
03478   int n, i;
03479 
03480   if (eof)
03481     return gFalse;
03482   t = 0;
03483   for (n = 0; n < 4; ++n) {
03484     if ((c = str->getChar()) == EOF)
03485       break;
03486     t = (t << 8) + c;
03487   }
03488   bufPtr = bufEnd = buf;
03489   if (n > 0) {
03490     if (n == 4 && t == 0) {
03491       *bufEnd++ = 'z';
03492       if (++lineLen == 65) {
03493         *bufEnd++ = '\n';
03494         lineLen = 0;
03495       }
03496     } else {
03497       if (n < 4)
03498         t <<= 8 * (4 - n);
03499       for (i = 4; i >= 0; --i) {
03500         buf1[i] = (char)(t % 85 + 0x21);
03501         t /= 85;
03502       }
03503       for (i = 0; i <= n; ++i) {
03504         *bufEnd++ = buf1[i];
03505         if (++lineLen == 65) {
03506           *bufEnd++ = '\n';
03507           lineLen = 0;
03508         }
03509       }
03510     }
03511   }
03512   if (n < 4) {
03513     *bufEnd++ = '~';
03514     *bufEnd++ = '>';
03515     eof = gTrue;
03516   }
03517   return bufPtr < bufEnd;
03518 }
03519 
03520 //------------------------------------------------------------------------
03521 // RunLengthEncoder
03522 //------------------------------------------------------------------------
03523 
03524 RunLengthEncoder::RunLengthEncoder(Stream *strA):
03525     FilterStream(strA) {
03526   bufPtr = bufEnd = nextEnd = buf;
03527   eof = gFalse;
03528 }
03529 
03530 RunLengthEncoder::~RunLengthEncoder() {
03531   if (str->isEncoder())
03532     delete str;
03533 }
03534 
03535 void RunLengthEncoder::reset() {
03536   str->reset();
03537   bufPtr = bufEnd = nextEnd = buf;
03538   eof = gFalse;
03539 }
03540 
03541 void RunLengthEncoder::close() {
03542 }
03543 
03544 //
03545 // When fillBuf finishes, buf[] looks like this:
03546 //   +-----+--------------+-----------------+--
03547 //   + tag | ... data ... | next 0, 1, or 2 |
03548 //   +-----+--------------+-----------------+--
03549 //    ^                    ^                 ^
03550 //    bufPtr               bufEnd            nextEnd
03551 //
03552 GBool RunLengthEncoder::fillBuf() {
03553   int c, c1, c2;
03554   int n;
03555 
03556   // already hit EOF?
03557   if (eof)
03558     return gFalse;
03559 
03560   // grab two bytes
03561   if (nextEnd < bufEnd + 1) {
03562     if ((c1 = str->getChar()) == EOF) {
03563       eof = gTrue;
03564       return gFalse;
03565     }
03566   } else {
03567     c1 = bufEnd[0] & 0xff;
03568   }
03569   if (nextEnd < bufEnd + 2) {
03570     if ((c2 = str->getChar()) == EOF) {
03571       eof = gTrue;
03572       buf[0] = 0;
03573       buf[1] = c1;
03574       bufPtr = buf;
03575       bufEnd = &buf[2];
03576       return gTrue;
03577     }
03578   } else {
03579     c2 = bufEnd[1] & 0xff;
03580   }
03581 
03582   // check for repeat
03583   c = 0; // make gcc happy
03584   if (c1 == c2) {
03585     n = 2;
03586     while (n < 128 && (c = str->getChar()) == c1)
03587       ++n;
03588     buf[0] = (char)(257 - n);
03589     buf[1] = c1;
03590     bufEnd = &buf[2];
03591     if (c == EOF) {
03592       eof = gTrue;
03593     } else if (n < 128) {
03594       buf[2] = c;
03595       nextEnd = &buf[3];
03596     } else {
03597       nextEnd = bufEnd;
03598     }
03599 
03600   // get up to 128 chars
03601   } else {
03602     buf[1] = c1;
03603     buf[2] = c2;
03604     n = 2;
03605     while (n < 128) {
03606       if ((c = str->getChar()) == EOF) {
03607         eof = gTrue;
03608         break;
03609       }
03610       ++n;
03611       buf[n] = c;
03612       if (buf[n] == buf[n-1])
03613         break;
03614     }
03615     if (buf[n] == buf[n-1]) {
03616       buf[0] = (char)(n-2-1);
03617       bufEnd = &buf[n-1];
03618       nextEnd = &buf[n+1];
03619     } else {
03620       buf[0] = (char)(n-1);
03621       bufEnd = nextEnd = &buf[n+1];
03622     }
03623   }
03624   bufPtr = buf;
03625   return gTrue;
03626 }

Generated on Sat Nov 5 16:18:17 2005 for OPIE by  doxygen 1.4.2