//
// Stream.cc
//
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2002 Glyph & Cog, LLC
//
//========================================================================
#pragma implementation
#endif
+#include <aconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <ctype.h>
#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
#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)
Stream::~Stream() {
}
+void Stream::close() {
+}
+
int Stream::getRawChar() {
error(-1, "Internal: called getRawChar() on non-predictor stream");
return EOF;
return buf;
}
-void Stream::setPos(int pos) {
- error(-1, "Internal: called setPos() on non-FileStream");
-}
-
GString *Stream::getPSFilter(char *indent) {
return new GString();
}
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) {
// 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;
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
// FileStream
//------------------------------------------------------------------------
-FileStream::FileStream(FILE *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)
- fseek(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)ftell(f);
+#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;
+ } 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) {
- fseek(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 {
+#if HAVE_FSEEK64
+ fseek64(f, 0, SEEK_END);
+ size = (Guint)ftell64(f);
+#else
fseek(f, 0, SEEK_END);
- size = ftell(f);
- if (pos1 < -size)
- pos1 = (int)(-size);
- fseek(f, pos1, SEEK_END);
- bufPos = (int)ftell(f);
+ 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();
+ }
+#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;
}
- return 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;
}
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;
}
// ASCII85Stream
//------------------------------------------------------------------------
-ASCII85Stream::ASCII85Stream(Stream *str1) {
- str = str1;
+ASCII85Stream::ASCII85Stream(Stream *strA):
+ FilterStream(strA) {
index = n = 0;
eof = gFalse;
}
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;
}
// 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;
}
fclose(zPipe);
#endif
zPipe = NULL;
- unlink(zName);
+ unlink(zName->getCString());
+ delete zName;
}
if (pred) {
delete pred;
void LZWStream::reset() {
FILE *f;
+ GString *zCmd;
- str->reset();
- bufPtr = bufEnd = buf;
+ //----- close old LZW stream
if (zPipe) {
#ifdef HAVE_POPEN
pclose(zPipe);
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) {
GBool first; // indicates first code word after clear
int i, j;
+ str->reset();
+
// magic number
fputc(0x1f, f);
fputc(0x9d, f);
fclose(zPipe);
#endif
zPipe = NULL;
- unlink(zName);
+ unlink(zName->getCString());
+ delete zName;
}
bufPtr = buf;
bufEnd = buf + n;
if (pred) {
return NULL;
}
- s = str->getPSFilter(indent);
+ if (!(s = str->getPSFilter(indent))) {
+ return NULL;
+ }
s->append(indent)->append("/LZWDecode filter\n");
return s;
}
// RunLengthStream
//------------------------------------------------------------------------
-RunLengthStream::RunLengthStream(Stream *str1) {
- str = str1;
+RunLengthStream::RunLengthStream(Stream *strA):
+ FilterStream(strA) {
bufPtr = bufEnd = buf;
eof = gFalse;
}
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;
}
// 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;
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) {
}
// read the next row
-#if 0 //~
+#if 0
err = gFalse;
#endif
if (codingLine[a0] >= columns) {
return EOF;
default:
error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
-#if 0 //~
+#if 0
err = gTrue;
break;
#else
if (codingLine[a0] != columns) {
error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
-#if 0 //~
+#if 0
err = gTrue;
#endif
}
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
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;
}
}
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() {
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;
}
}
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) {
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;
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);
63
};
-DCTStream::DCTStream(Stream *str1) {
+DCTStream::DCTStream(Stream *strA):
+ FilterStream(strA) {
int i, j;
- str = str1;
width = height = 0;
mcuWidth = mcuHeight = 0;
numComps = 0;
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];
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;
}
{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;
}
void FlateStream::reset() {
int cmf, flg;
+ index = 0;
+ remain = 0;
+ codeBuf = 0;
+ codeSize = 0;
+ compressedBlock = gFalse;
+ endOfBlock = gTrue;
+ eof = gTrue;
+
str->reset();
// read header
return;
}
- // initialize
- index = 0;
- remain = 0;
- codeBuf = 0;
- codeSize = 0;
- compressedBlock = gFalse;
- endOfBlock = gTrue;
eof = gFalse;
}
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;
// EOFStream
//------------------------------------------------------------------------
-EOFStream::EOFStream(Stream *str1) {
- str = str1;
+EOFStream::EOFStream(Stream *strA):
+ FilterStream(strA) {
}
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;
}
count = 0;
}
+void FixedLengthEncoder::close() {
+}
+
int FixedLengthEncoder::getChar() {
if (length >= 0 && count >= length)
return EOF;
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;
eof = gFalse;
}
+void ASCII85Encoder::close() {
+}
+
GBool ASCII85Encoder::fillBuf() {
Gulong t;
char buf1[5];
// RunLengthEncoder
//------------------------------------------------------------------------
-RunLengthEncoder::RunLengthEncoder(Stream *str1) {
- str = str1;
+RunLengthEncoder::RunLengthEncoder(Stream *strA):
+ FilterStream(strA) {
bufPtr = bufEnd = nextEnd = buf;
eof = gFalse;
}
eof = gFalse;
}
+void RunLengthEncoder::close() {
+}
+
//
// When fillBuf finishes, buf[] looks like this:
// +-----+--------------+-----------------+--
}
// check for repeat
+ c = 0; // make gcc happy
if (c1 == c2) {
n = 2;
while (n < 128 && (c = str->getChar()) == c1)