X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;ds=sidebyside;f=pdf%2Fxpdf%2FStream.cc;h=9777940da3b70a4dcea3d15092a4857a189cd8f4;hb=e9705183293f22e3a45dd59ba3df42d1c5a77dd8;hp=6e52d791c5a6d0c8f1c9fe7a2091f943204bbb28;hpb=2610a3462d1ac3f20cba8f16dd07cba8a8c2fbef;p=evince.git diff --git a/pdf/xpdf/Stream.cc b/pdf/xpdf/Stream.cc index 6e52d791..9777940d 100644 --- a/pdf/xpdf/Stream.cc +++ b/pdf/xpdf/Stream.cc @@ -2,7 +2,7 @@ // // Stream.cc // -// Copyright 1996 Derek B. Noonburg +// Copyright 1996-2002 Glyph & Cog, LLC // //======================================================================== @@ -10,6 +10,7 @@ #pragma implementation #endif +#include #include #include #include @@ -19,17 +20,16 @@ #include #include #include "gmem.h" +#include "gfile.h" #include "config.h" #include "Error.h" #include "Object.h" +#ifndef NO_DECRYPTION +#include "Decrypt.h" +#endif #include "Stream.h" #include "Stream-CCITT.h" -#ifdef _MSC_VER -#define popen _popen -#define pclose _pclose -#endif - #ifdef __DJGPP__ static GBool setDJSYSFLAGS = gFalse; #endif @@ -45,10 +45,9 @@ extern "C" int unlink(char *filename); #endif #endif -//------------------------------------------------------------------------ - -#define headerSearchSize 1024 // read this many bytes at beginning of - // file to look for '%PDF' +#ifdef MACOS +#include "StuffItEngineLib.h" +#endif //------------------------------------------------------------------------ // Stream (base class) @@ -61,6 +60,9 @@ Stream::Stream() { Stream::~Stream() { } +void Stream::close() { +} + int Stream::getRawChar() { error(-1, "Internal: called getRawChar() on non-predictor stream"); return EOF; @@ -87,10 +89,6 @@ char *Stream::getLine(char *buf, int size) { return buf; } -void Stream::setPos(int pos) { - error(-1, "Internal: called setPos() on non-FileStream"); -} - GString *Stream::getPSFilter(char *indent) { return new GString(); } @@ -264,17 +262,62 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params) { return str; } +//------------------------------------------------------------------------ +// BaseStream +//------------------------------------------------------------------------ + +BaseStream::BaseStream(Object *dictA) { + dict = *dictA; +#ifndef NO_DECRYPTION + decrypt = NULL; +#endif +} + +BaseStream::~BaseStream() { + dict.free(); +#ifndef NO_DECRYPTION + if (decrypt) + delete decrypt; +#endif +} + +#ifndef NO_DECRYPTION +void BaseStream::doDecryption(Guchar *fileKey, int keyLength, + int objNum, int objGen) { + decrypt = new Decrypt(fileKey, keyLength, objNum, objGen); +} +#endif + +//------------------------------------------------------------------------ +// FilterStream +//------------------------------------------------------------------------ + +FilterStream::FilterStream(Stream *strA) { + str = strA; +} + +FilterStream::~FilterStream() { +} + +void FilterStream::close() { + str->close(); +} + +void FilterStream::setPos(Guint pos, int dir) { + error(-1, "Internal: called setPos() on FilterStream"); +} + //------------------------------------------------------------------------ // ImageStream //------------------------------------------------------------------------ -ImageStream::ImageStream(Stream *str, int width, int nComps, int nBits) { +ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) { int imgLineSize; - this->str = str; - this->width = width; - this->nComps = nComps; - this->nBits = nBits; + str = strA; + width = widthA; + nComps = nCompsA; + nBits = nBitsA; nVals = width * nComps; if (nBits == 1) { @@ -355,13 +398,13 @@ void ImageStream::skipLine() { // StreamPredictor //------------------------------------------------------------------------ -StreamPredictor::StreamPredictor(Stream *str, int predictor, - int width, int nComps, int nBits) { - this->str = str; - this->predictor = predictor; - this->width = width; - this->nComps = nComps; - this->nBits = nBits; +StreamPredictor::StreamPredictor(Stream *strA, int predictorA, + int widthA, int nCompsA, int nBitsA) { + str = strA; + predictor = predictorA; + width = widthA; + nComps = nCompsA; + nBits = nBitsA; nVals = width * nComps; pixBytes = (nComps * nBits + 7) >> 3; @@ -445,11 +488,11 @@ GBool StreamPredictor::getNextLine() { if ((pc = p - upLeft) < 0) pc = -pc; if (pa <= pb && pa <= pc) - predLine[i] = pa + (Guchar)c; + predLine[i] = left + (Guchar)c; else if (pb <= pc) - predLine[i] = pb + (Guchar)c; + predLine[i] = up + (Guchar)c; else - predLine[i] = pc + (Guchar)c; + predLine[i] = upLeft + (Guchar)c; break; case 10: // PNG none default: // no predictor or TIFF predictor @@ -511,112 +554,249 @@ GBool StreamPredictor::getNextLine() { // FileStream //------------------------------------------------------------------------ -FileStream::FileStream(BaseFile f1, int start1, int length1, Object *dict1) { - f = f1; - start = start1; - length = length1; +FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA, + Guint lengthA, Object *dictA): + BaseStream(dictA) { + f = fA; + start = startA; + limited = limitedA; + length = lengthA; bufPtr = bufEnd = buf; bufPos = start; - savePos = -1; - dict = *dict1; + savePos = 0; + saved = gFalse; } FileStream::~FileStream() { - if (savePos >= 0) - bfseek(f, savePos, SEEK_SET); - dict.free(); + close(); +} + +Stream *FileStream::makeSubStream(Guint startA, GBool limitedA, + Guint lengthA, Object *dictA) { + return new FileStream(f, startA, limitedA, lengthA, dictA); } void FileStream::reset() { - savePos = (int)bftell(f); - bfseek(f, start, SEEK_SET); +#if HAVE_FSEEK64 + savePos = (Guint)ftell64(f); + fseek64(f, start, SEEK_SET); +#else + savePos = (Guint)ftell(f); + fseek(f, start, SEEK_SET); +#endif + saved = gTrue; bufPtr = bufEnd = buf; bufPos = start; +#ifndef NO_DECRYPTION + if (decrypt) + decrypt->reset(); +#endif +} + +void FileStream::close() { + if (saved) { +#if HAVE_FSEEK64 + fseek64(f, savePos, SEEK_SET); +#else + fseek(f, savePos, SEEK_SET); +#endif + saved = gFalse; + } } GBool FileStream::fillBuf() { int n; +#ifndef NO_DECRYPTION + char *p; +#endif bufPos += bufEnd - buf; bufPtr = bufEnd = buf; - if (length >= 0 && bufPos >= start + length) + if (limited && bufPos >= start + length) { return gFalse; - if (length >= 0 && bufPos + 256 > start + length) + } + if (limited && bufPos + fileStreamBufSize > start + length) { n = start + length - bufPos; - else - n = 256; - n = bfread(buf, 1, n, f); + } else { + n = fileStreamBufSize; + } + n = fread(buf, 1, n, f); bufEnd = buf + n; - if (bufPtr >= bufEnd) + if (bufPtr >= bufEnd) { return gFalse; + } +#ifndef NO_DECRYPTION + if (decrypt) { + for (p = buf; p < bufEnd; ++p) { + *p = (char)decrypt->decryptByte((Guchar)*p); + } + } +#endif return gTrue; } -void FileStream::setPos(int pos1) { - long size; +void FileStream::setPos(Guint pos, int dir) { + Guint size; - if (pos1 >= 0) { - bfseek(f, pos1, SEEK_SET); - bufPos = pos1; + if (dir >= 0) { +#if HAVE_FSEEK64 + fseek64(f, pos, SEEK_SET); +#else + fseek(f, pos, SEEK_SET); +#endif + bufPos = pos; } else { - bfseek(f, 0, SEEK_END); - size = bftell(f); - if (pos1 < -size) - pos1 = (int)(-size); - bfseek(f, pos1, SEEK_END); - bufPos = (int)bftell(f); +#if HAVE_FSEEK64 + fseek64(f, 0, SEEK_END); + size = (Guint)ftell64(f); +#else + fseek(f, 0, SEEK_END); + size = (Guint)ftell(f); +#endif + if (pos > size) + pos = (Guint)size; +#ifdef __CYGWIN32__ + //~ work around a bug in cygwin's implementation of fseek + rewind(f); +#endif +#if HAVE_FSEEK64 + fseek64(f, -(int)pos, SEEK_END); + bufPos = (Guint)ftell64(f); +#else + fseek(f, -(int)pos, SEEK_END); + bufPos = (Guint)ftell(f); +#endif } bufPtr = bufEnd = buf; } -GBool FileStream::checkHeader() { - char hdrBuf[headerSearchSize+1]; - char *p; - double version; - int i; +void FileStream::moveStart(int delta) { + start += delta; + bufPtr = bufEnd = buf; + bufPos = start; +} - for (i = 0; i < headerSearchSize; ++i) - hdrBuf[i] = getChar(); - hdrBuf[headerSearchSize] = '\0'; - for (i = 0; i < headerSearchSize - 5; ++i) { - if (!strncmp(&hdrBuf[i], "%PDF-", 5)) - break; +//------------------------------------------------------------------------ +// MemStream +//------------------------------------------------------------------------ + +MemStream::MemStream(char *bufA, Guint lengthA, Object *dictA): + BaseStream(dictA) { + buf = bufA; + needFree = gFalse; + length = lengthA; + bufEnd = buf + length; + bufPtr = buf; +} + +MemStream::~MemStream() { + if (needFree) { + gfree(buf); } - if (i >= headerSearchSize - 5) { - error(-1, "May not be a PDF file (continuing anyway)"); - return gFalse; +} + +Stream *MemStream::makeSubStream(Guint start, GBool limited, + Guint lengthA, Object *dictA) { + Guint newLength; + + if (!limited || start + lengthA > length) { + newLength = length - start; + } else { + newLength = lengthA; } - start += i; - p = strtok(&hdrBuf[i+5], " \t\n\r"); - version = atof(p); - if (!(hdrBuf[i+5] >= '0' && hdrBuf[i+5] <= '9') || - version > pdfVersionNum + 0.0001) { - error(getPos(), "PDF version %s -- xpdf supports version %s" - " (continuing anyway)", p, pdfVersion); - return gFalse; + return new MemStream(buf + start, newLength, dictA); +} + +void MemStream::reset() { + bufPtr = buf; +#ifndef NO_DECRYPTION + if (decrypt) { + decrypt->reset(); } - return gTrue; +#endif +} + +void MemStream::close() { } +void MemStream::setPos(Guint pos, int dir) { + if (dir >= 0) { + if (pos > length) { + bufPtr = bufEnd; + } else { + bufPtr = buf + pos; + } + } else { + if (pos > length) { + bufPtr = buf; + } else { + bufPtr = bufEnd - pos; + } + } +} + +void MemStream::moveStart(int delta) { + buf += delta; + bufPtr = buf; +} + +#ifndef NO_DECRYPTION +void MemStream::doDecryption(Guchar *fileKey, int keyLength, + int objNum, int objGen) { + char *newBuf; + char *p, *q; + + this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen); + if (decrypt) { + newBuf = (char *)gmalloc(bufEnd - buf); + for (p = buf, q = newBuf; p < bufEnd; ++p, ++q) { + *q = (char)decrypt->decryptByte((Guchar)*p); + } + bufEnd = newBuf + (bufEnd - buf); + bufPtr = newBuf + (bufPtr - buf); + buf = newBuf; + needFree = gTrue; + } +} +#endif + //------------------------------------------------------------------------ -// SubStream +// EmbedStream //------------------------------------------------------------------------ -SubStream::SubStream(Stream *str1, Object *dict1) { - str = str1; - dict = *dict1; +EmbedStream::EmbedStream(Stream *strA, Object *dictA): + BaseStream(dictA) { + str = strA; } -SubStream::~SubStream() { - dict.free(); +EmbedStream::~EmbedStream() { +} + +Stream *EmbedStream::makeSubStream(Guint start, GBool limited, + Guint length, Object *dictA) { + error(-1, "Internal: called makeSubStream() on EmbedStream"); + return NULL; +} + +void EmbedStream::setPos(Guint pos, int dir) { + error(-1, "Internal: called setPos() on EmbedStream"); +} + +Guint EmbedStream::getStart() { + error(-1, "Internal: called getStart() on EmbedStream"); + return 0; +} + +void EmbedStream::moveStart(int delta) { + error(-1, "Internal: called moveStart() on EmbedStream"); } //------------------------------------------------------------------------ // ASCIIHexStream //------------------------------------------------------------------------ -ASCIIHexStream::ASCIIHexStream(Stream *str1) { - str = str1; +ASCIIHexStream::ASCIIHexStream(Stream *strA): + FilterStream(strA) { buf = EOF; eof = gFalse; } @@ -687,7 +867,9 @@ int ASCIIHexStream::lookChar() { GString *ASCIIHexStream::getPSFilter(char *indent) { GString *s; - s = str->getPSFilter(indent); + if (!(s = str->getPSFilter(indent))) { + return NULL; + } s->append(indent)->append("/ASCIIHexDecode filter\n"); return s; } @@ -700,8 +882,8 @@ GBool ASCIIHexStream::isBinary(GBool last) { // ASCII85Stream //------------------------------------------------------------------------ -ASCII85Stream::ASCII85Stream(Stream *str1) { - str = str1; +ASCII85Stream::ASCII85Stream(Stream *strA): + FilterStream(strA) { index = n = 0; eof = gFalse; } @@ -763,7 +945,9 @@ int ASCII85Stream::lookChar() { GString *ASCII85Stream::getPSFilter(char *indent) { GString *s; - s = str->getPSFilter(indent); + if (!(s = str->getPSFilter(indent))) { + return NULL; + } s->append(indent)->append("/ASCII85Decode filter\n"); return s; } @@ -776,15 +960,15 @@ GBool ASCII85Stream::isBinary(GBool last) { // LZWStream //------------------------------------------------------------------------ -LZWStream::LZWStream(Stream *str1, int predictor1, int columns1, int colors1, - int bits1, int early1) { - str = str1; - if (predictor1 != 1) { - pred = new StreamPredictor(this, predictor1, columns1, colors1, bits1); +LZWStream::LZWStream(Stream *strA, int predictor, int columns, int colors, + int bits, int earlyA): + FilterStream(strA) { + if (predictor != 1) { + pred = new StreamPredictor(this, predictor, columns, colors, bits); } else { pred = NULL; } - early = early1; + early = earlyA; zPipe = NULL; bufPtr = bufEnd = buf; } @@ -797,7 +981,8 @@ LZWStream::~LZWStream() { fclose(zPipe); #endif zPipe = NULL; - unlink(zName); + unlink(zName->getCString()); + delete zName; } if (pred) { delete pred; @@ -825,9 +1010,9 @@ int LZWStream::getRawChar() { void LZWStream::reset() { FILE *f; + GString *zCmd; - str->reset(); - bufPtr = bufEnd = buf; + //----- close old LZW stream if (zPipe) { #ifdef HAVE_POPEN pclose(zPipe); @@ -835,51 +1020,78 @@ void LZWStream::reset() { fclose(zPipe); #endif zPipe = NULL; - unlink(zName); + unlink(zName->getCString()); + delete zName; } + + //----- tell Delorie runtime to spawn a new instance of COMMAND.COM + // to run gzip #if __DJGPP__ if (!setDJSYSFLAGS) { setenv("DJSYSFLAGS", "0x0002", 0); setDJSYSFLAGS = gTrue; } #endif - strcpy(zCmd, uncompressCmd); - strcat(zCmd, " "); - zName = zCmd + strlen(zCmd); - tmpnam(zName); -#ifdef _MSC_VER - zName[strlen(zName) - 2] = '\0'; -#endif - strcat(zName, ".Z"); - if (!(f = fopen(zName, "wb"))) { - error(getPos(), "Couldn't open temporary file '%s'", zName); + + //----- create the .Z file + if (!openTempFile(&zName, &f, "wb", ".Z")) { + error(getPos(), "Couldn't create temporary file for LZW stream"); return; } dumpFile(f); fclose(f); -#ifdef HAVE_POPEN - if (!(zPipe = popen(zCmd, "r"))) { - error(getPos(), "Couldn't popen '%s'", zCmd); - unlink(zName); + + //----- execute uncompress / gzip + zCmd = new GString(uncompressCmd); + zCmd->append(' '); + zCmd->append(zName); +#if defined(MACOS) + long magicCookie; + // first we open the engine up + OSErr err = OpenSITEngine(kUseExternalEngine, &magicCookie); + // if we found it - let's use it! + if (!err && magicCookie) { + // make sure we have the correct version of the Engine + if (GetSITEngineVersion(magicCookie) >= kFirstSupportedEngine) { + FSSpec myFSS; + Str255 pName; + strcpy((char *)pName, zName->getCString()); + c2pstr((char *)pName); + FSMakeFSSpec(0, 0, pName, &myFSS); + short ftype = DetermineFileType(magicCookie, &myFSS); + OSErr expandErr = ExpandFSSpec(magicCookie, ftype, &myFSS, + NULL, NULL, kCreateFolderNever, + kDeleteOriginal, kTextConvertSmart); + } + } +#elif defined(HAVE_POPEN) + if (!(zPipe = popen(zCmd->getCString(), POPEN_READ_MODE))) { + error(getPos(), "Couldn't popen '%s'", zCmd->getCString()); + unlink(zName->getCString()); + delete zName; return; } -#else -#ifdef VMS - if (!system(zCmd)) { -#else - if (system(zCmd)) { -#endif - error(getPos(), "Couldn't execute '%s'", zCmd); - unlink(zName); +#else // HAVE_POPEN + if (!executeCommand(zCmd->getCString())) { + error(getPos(), "Couldn't execute '%s'", zCmd->getCString()); + unlink(zName->getCString()); + delete zName; return; } - zName[strlen(zName) - 2] = '\0'; - if (!(zPipe = fopen(zName, "rb"))) { - error(getPos(), "Couldn't open uncompress file '%s'", zName); - unlink(zName); + zName->del(zName->getLength() - 2, 2); + if (!(zPipe = fopen(zName->getCString(), "rb"))) { + error(getPos(), "Couldn't open uncompress file '%s'", zName->getCString()); + unlink(zName->getCString()); + delete zName; return; } -#endif +#endif // HAVE_POPEN + + //----- clean up + delete zCmd; + + //----- initialize buffer + bufPtr = bufEnd = buf; } void LZWStream::dumpFile(FILE *f) { @@ -894,6 +1106,8 @@ void LZWStream::dumpFile(FILE *f) { GBool first; // indicates first code word after clear int i, j; + str->reset(); + // magic number fputc(0x1f, f); fputc(0x9d, f); @@ -1030,7 +1244,8 @@ GBool LZWStream::fillBuf() { fclose(zPipe); #endif zPipe = NULL; - unlink(zName); + unlink(zName->getCString()); + delete zName; } bufPtr = buf; bufEnd = buf + n; @@ -1043,7 +1258,9 @@ GString *LZWStream::getPSFilter(char *indent) { if (pred) { return NULL; } - s = str->getPSFilter(indent); + if (!(s = str->getPSFilter(indent))) { + return NULL; + } s->append(indent)->append("/LZWDecode filter\n"); return s; } @@ -1056,8 +1273,8 @@ GBool LZWStream::isBinary(GBool last) { // RunLengthStream //------------------------------------------------------------------------ -RunLengthStream::RunLengthStream(Stream *str1) { - str = str1; +RunLengthStream::RunLengthStream(Stream *strA): + FilterStream(strA) { bufPtr = bufEnd = buf; eof = gFalse; } @@ -1075,7 +1292,9 @@ void RunLengthStream::reset() { GString *RunLengthStream::getPSFilter(char *indent) { GString *s; - s = str->getPSFilter(indent); + if (!(s = str->getPSFilter(indent))) { + return NULL; + } s->append(indent)->append("/RunLengthDecode filter\n"); return s; } @@ -1114,18 +1333,18 @@ GBool RunLengthStream::fillBuf() { // CCITTFaxStream //------------------------------------------------------------------------ -CCITTFaxStream::CCITTFaxStream(Stream *str, int encoding, GBool endOfLine, - GBool byteAlign, int columns, int rows, - GBool endOfBlock, GBool black) { - this->str = str; - this->encoding = encoding; - this->endOfLine = endOfLine; - this->byteAlign = byteAlign; - this->columns = columns; - this->rows = rows; - this->endOfBlock = endOfBlock; - this->black = black; - refLine = (short *)gmalloc((columns + 2) * sizeof(short)); +CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA, + GBool byteAlignA, int columnsA, int rowsA, + GBool endOfBlockA, GBool blackA): + FilterStream(strA) { + encoding = encodingA; + endOfLine = endOfLineA; + byteAlign = byteAlignA; + columns = columnsA; + rows = rowsA; + endOfBlock = endOfBlockA; + black = blackA; + refLine = (short *)gmalloc((columns + 3) * sizeof(short)); codingLine = (short *)gmalloc((columns + 2) * sizeof(short)); eof = gFalse; @@ -1178,11 +1397,12 @@ void CCITTFaxStream::reset() { int CCITTFaxStream::lookChar() { short code1, code2, code3; int a0New; -#if 0 //~ +#if 0 GBool err; #endif + GBool gotEOL; int ret; - int bits, i, n; + int bits, i; // if at eof just return EOF if (eof && codingLine[a0] >= columns) { @@ -1190,7 +1410,7 @@ int CCITTFaxStream::lookChar() { } // read the next row -#if 0 //~ +#if 0 err = gFalse; #endif if (codingLine[a0] >= columns) { @@ -1292,7 +1512,7 @@ int CCITTFaxStream::lookChar() { return EOF; default: error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1); -#if 0 //~ +#if 0 err = gTrue; break; #else @@ -1327,7 +1547,7 @@ int CCITTFaxStream::lookChar() { if (codingLine[a0] != columns) { error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]); -#if 0 //~ +#if 0 err = gTrue; #endif } @@ -1337,62 +1557,57 @@ int CCITTFaxStream::lookChar() { inputBits &= ~7; } - // check for end-of-line marker, end-of-block marker, and - // 2D encoding tag - if (endOfBlock) { + // check for end-of-line marker, skipping over any extra zero bits + gotEOL = gFalse; + if (!endOfBlock && row == rows - 1) { + eof = gTrue; + } else { code1 = lookBits(12); - if (code1 == EOF) { + while (code1 == 0) { + eatBits(1); + code1 = lookBits(12); + } + if (code1 == 0x001) { + eatBits(12); + gotEOL = gTrue; + } else if (code1 == EOF) { eof = gTrue; - } else if (code1 == 0x001) { + } + } + + // get 2D encoding tag + if (!eof && encoding > 0) { + nextLine2D = !lookBits(1); + eatBits(1); + } + + // check for end-of-block marker + if (endOfBlock && gotEOL) { + code1 = lookBits(12); + if (code1 == 0x001) { eatBits(12); if (encoding > 0) { - nextLine2D = !lookBits(1); + lookBits(1); eatBits(1); } - code1 = lookBits(12); - if (code1 == 0x001) { - eatBits(12); - if (encoding > 0) { - lookBits(1); - eatBits(1); - } - if (encoding >= 0) { - for (i = 0; i < 4; ++i) { - code1 = lookBits(12); - if (code1 != 0x001) { - error(getPos(), "Bad RTC code in CCITTFax stream"); - } - eatBits(12); - if (encoding > 0) { - lookBits(1); - eatBits(1); - } + if (encoding >= 0) { + for (i = 0; i < 4; ++i) { + code1 = lookBits(12); + if (code1 != 0x001) { + error(getPos(), "Bad RTC code in CCITTFax stream"); + } + eatBits(12); + if (encoding > 0) { + lookBits(1); + eatBits(1); } } - eof = gTrue; } - } else { - if (encoding > 0) { - nextLine2D = !lookBits(1); - eatBits(1); - } - } - } else { - if (row == rows - 1) { eof = gTrue; - } else { - for (n = 0; n < 11 && lookBits(n) == 0; ++n) ; - if (n == 11 && lookBits(12) == 0x001) { - eatBits(12); - } - if (encoding > 0) { - nextLine2D = !lookBits(1); - eatBits(1); - } } } -#if 0 //~ +#if 0 // This looks for an end-of-line marker after an error, however // some (most?) CCITT streams in PDF files don't use end-of-line // markers, and the just-plow-on technique works better in those @@ -1501,10 +1716,11 @@ short CCITTFaxStream::getWhiteCode() { code = 0; // make gcc happy if (endOfBlock) { code = lookBits(12); - if ((code >> 5) == 0) + if ((code >> 5) == 0) { p = &whiteTab1[code]; - else + } else { p = &whiteTab2[code >> 3]; + } if (p->bits > 0) { eatBits(p->bits); return p->n; @@ -1534,7 +1750,10 @@ short CCITTFaxStream::getWhiteCode() { } } error(getPos(), "Bad white code (%04x) in CCITTFax stream", code); - return EOF; + // eat a bit and return a positive number so that the caller doesn't + // go into an infinite loop + eatBits(1); + return 1; } short CCITTFaxStream::getBlackCode() { @@ -1545,12 +1764,13 @@ short CCITTFaxStream::getBlackCode() { code = 0; // make gcc happy if (endOfBlock) { code = lookBits(13); - if ((code >> 7) == 0) + if ((code >> 7) == 0) { p = &blackTab1[code]; - else if ((code >> 9) == 0) + } else if ((code >> 9) == 0) { p = &blackTab2[(code >> 1) - 64]; - else + } else { p = &blackTab3[code >> 7]; + } if (p->bits > 0) { eatBits(p->bits); return p->n; @@ -1593,7 +1813,10 @@ short CCITTFaxStream::getBlackCode() { } } error(getPos(), "Bad black code (%04x) in CCITTFax stream", code); - return EOF; + // eat a bit and return a positive number so that the caller doesn't + // go into an infinite loop + eatBits(1); + return 1; } short CCITTFaxStream::lookBits(int n) { @@ -1601,9 +1824,14 @@ short CCITTFaxStream::lookBits(int n) { while (inputBits < n) { if ((c = str->getChar()) == EOF) { - if (inputBits == 0) + if (inputBits == 0) { return EOF; - c = 0; + } + // near the end of the stream, the caller may ask for more bits + // than are available, but there may still be a valid code in + // however many bits are available -- we need to return correct + // data in this case + return (inputBuf << (n - inputBits)) & (0xffff >> (16 - n)); } inputBuf = (inputBuf << 8) + c; inputBits += 8; @@ -1615,7 +1843,9 @@ GString *CCITTFaxStream::getPSFilter(char *indent) { GString *s; char s1[50]; - s = str->getPSFilter(indent); + if (!(s = str->getPSFilter(indent))) { + return NULL; + } s->append(indent)->append("<< "); if (encoding != 0) { sprintf(s1, "/K %d ", encoding); @@ -1705,10 +1935,10 @@ static int dctZigZag[64] = { 63 }; -DCTStream::DCTStream(Stream *str1) { +DCTStream::DCTStream(Stream *strA): + FilterStream(strA) { int i, j; - str = str1; width = height = 0; mcuWidth = mcuHeight = 0; numComps = 0; @@ -1896,7 +2126,7 @@ GBool DCTStream::readMCURow() { pCr = rowBuf[2][y2][x1+x2] - 128; pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR]; - pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32678) >> 16; + pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16; rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG]; pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB]; @@ -2605,7 +2835,9 @@ int DCTStream::read16() { GString *DCTStream::getPSFilter(char *indent) { GString *s; - s = str->getPSFilter(indent); + if (!(s = str->getPSFilter(indent))) { + return NULL; + } s->append(indent)->append("<< >> /DCTDecode filter\n"); return s; } @@ -2687,11 +2919,11 @@ FlateDecode FlateStream::distDecode[flateMaxDistCodes] = { {13, 24577} }; -FlateStream::FlateStream(Stream *str1, int predictor1, int columns1, - int colors1, int bits1) { - str = str1; - if (predictor1 != 1) { - pred = new StreamPredictor(this, predictor1, columns1, colors1, bits1); +FlateStream::FlateStream(Stream *strA, int predictor, int columns, + int colors, int bits): + FilterStream(strA) { + if (predictor != 1) { + pred = new StreamPredictor(this, predictor, columns, colors, bits); } else { pred = NULL; } @@ -2707,6 +2939,14 @@ FlateStream::~FlateStream() { void FlateStream::reset() { int cmf, flg; + index = 0; + remain = 0; + codeBuf = 0; + codeSize = 0; + compressedBlock = gFalse; + endOfBlock = gTrue; + eof = gTrue; + str->reset(); // read header @@ -2729,13 +2969,6 @@ void FlateStream::reset() { return; } - // initialize - index = 0; - remain = 0; - codeBuf = 0; - codeSize = 0; - compressedBlock = gFalse; - endOfBlock = gTrue; eof = gFalse; } @@ -2933,11 +3166,12 @@ void FlateStream::loadFixedCodes() { compHuffmanCodes(&litCodeTab, flateMaxLitCodes); // initialize distance code table - for (i = 0; i < 5; ++i) + for (i = 0; i <= 5; ++i) { distCodeTab.start[i] = 0; - distCodeTab.start[5] = 0; - for (i = 6; i <= flateMaxHuffman+1; ++i) - distCodeTab.start[6] = flateMaxDistCodes; + } + for (i = 6; i <= flateMaxHuffman+1; ++i) { + distCodeTab.start[i] = flateMaxDistCodes; + } for (i = 0; i < flateMaxDistCodes; ++i) { distCodeTab.codes[i].len = 5; distCodeTab.codes[i].code = i; @@ -3117,8 +3351,8 @@ int FlateStream::getCodeWord(int bits) { // EOFStream //------------------------------------------------------------------------ -EOFStream::EOFStream(Stream *str1) { - str = str1; +EOFStream::EOFStream(Stream *strA): + FilterStream(strA) { } EOFStream::~EOFStream() { @@ -3129,9 +3363,9 @@ EOFStream::~EOFStream() { // FixedLengthEncoder //------------------------------------------------------------------------ -FixedLengthEncoder::FixedLengthEncoder(Stream *str1, int length1) { - str = str1; - length = length1; +FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA): + FilterStream(strA) { + length = lengthA; count = 0; } @@ -3145,6 +3379,9 @@ void FixedLengthEncoder::reset() { count = 0; } +void FixedLengthEncoder::close() { +} + int FixedLengthEncoder::getChar() { if (length >= 0 && count >= length) return EOF; @@ -3158,12 +3395,62 @@ int FixedLengthEncoder::lookChar() { return str->getChar(); } +//------------------------------------------------------------------------ +// ASCIIHexEncoder +//------------------------------------------------------------------------ + +ASCIIHexEncoder::ASCIIHexEncoder(Stream *strA): + FilterStream(strA) { + bufPtr = bufEnd = buf; + lineLen = 0; + eof = gFalse; +} + +ASCIIHexEncoder::~ASCIIHexEncoder() { + if (str->isEncoder()) { + delete str; + } +} + +void ASCIIHexEncoder::reset() { + str->reset(); + bufPtr = bufEnd = buf; + lineLen = 0; + eof = gFalse; +} + +void ASCIIHexEncoder::close() { +} + +GBool ASCIIHexEncoder::fillBuf() { + static char *hex = "0123456789abcdef"; + int c; + + if (eof) { + return gFalse; + } + bufPtr = bufEnd = buf; + if ((c = str->getChar()) == EOF) { + *bufEnd++ = '>'; + eof = gTrue; + } else { + if (lineLen >= 64) { + *bufEnd++ = '\n'; + lineLen = 0; + } + *bufEnd++ = hex[(c >> 4) & 0x0f]; + *bufEnd++ = hex[c & 0x0f]; + lineLen += 2; + } + return gTrue; +} + //------------------------------------------------------------------------ // ASCII85Encoder //------------------------------------------------------------------------ -ASCII85Encoder::ASCII85Encoder(Stream *str1) { - str = str1; +ASCII85Encoder::ASCII85Encoder(Stream *strA): + FilterStream(strA) { bufPtr = bufEnd = buf; lineLen = 0; eof = gFalse; @@ -3181,6 +3468,9 @@ void ASCII85Encoder::reset() { eof = gFalse; } +void ASCII85Encoder::close() { +} + GBool ASCII85Encoder::fillBuf() { Gulong t; char buf1[5]; @@ -3231,8 +3521,8 @@ GBool ASCII85Encoder::fillBuf() { // RunLengthEncoder //------------------------------------------------------------------------ -RunLengthEncoder::RunLengthEncoder(Stream *str1) { - str = str1; +RunLengthEncoder::RunLengthEncoder(Stream *strA): + FilterStream(strA) { bufPtr = bufEnd = nextEnd = buf; eof = gFalse; } @@ -3248,6 +3538,9 @@ void RunLengthEncoder::reset() { eof = gFalse; } +void RunLengthEncoder::close() { +} + // // When fillBuf finishes, buf[] looks like this: // +-----+--------------+-----------------+-- @@ -3287,6 +3580,7 @@ GBool RunLengthEncoder::fillBuf() { } // check for repeat + c = 0; // make gcc happy if (c1 == c2) { n = 2; while (n < 128 && (c = str->getChar()) == c1)