]> www.fi.muni.cz Git - evince.git/blobdiff - pdf/xpdf/Stream.h
Start of content-area widget.
[evince.git] / pdf / xpdf / Stream.h
index 3eb8160b6110e9df510b00c44d0dd404cbd58561..0b70afa45c3d4e42a7c58ad3330b3534ae2302b8 100644 (file)
@@ -2,14 +2,16 @@
 //
 // Stream.h
 //
-// Copyright 1996 Derek B. Noonburg
+// Copyright 1996-2003 Glyph & Cog, LLC
 //
 //========================================================================
 
 #ifndef STREAM_H
 #define STREAM_H
 
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
 #pragma interface
 #endif
 
 #include "gtypes.h"
 #include "Object.h"
 
+#ifndef NO_DECRYPTION
+class Decrypt;
+#endif
+class BaseStream;
+
 //------------------------------------------------------------------------
 
 enum StreamKind {
@@ -28,6 +35,8 @@ enum StreamKind {
   strCCITTFax,
   strDCT,
   strFlate,
+  strJBIG2,
+  strJPX,
   strWeird                     // internal-use stream types
 };
 
@@ -54,6 +63,9 @@ public:
   // Reset stream to beginning.
   virtual void reset() = 0;
 
+  // Close down the stream.
+  virtual void close();
+
   // Get next char from stream.
   virtual int getChar() = 0;
 
@@ -70,20 +82,19 @@ public:
   // Get current position in file.
   virtual int getPos() = 0;
 
-  // Go to a position in the stream.
-  virtual void setPos(int pos1);
+  // Go to a position in the stream.  If <dir> is negative, the
+  // position is from the end of the file; otherwise the position is
+  // from the start of the file.
+  virtual void setPos(Guint pos, int dir = 0) = 0;
 
   // Get PostScript command for the filter(s).
-  virtual GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(int psLevel, char *indent);
 
   // Does this stream type potentially contain non-printable chars?
   virtual GBool isBinary(GBool last = gTrue) = 0;
 
-  // Get the base FileStream or SubStream of this stream.
-  virtual Stream *getBaseStream() = 0;
-
-  // Get the base file of this stream.
-  virtual FILE *getFile() = 0;
+  // Get the BaseStream of this stream.
+  virtual BaseStream *getBaseStream() = 0;
 
   // Get the dictionary associated with this stream.
   virtual Dict *getDict() = 0;
@@ -95,6 +106,11 @@ public:
   // Returns the new stream.
   Stream *addFilters(Object *dict);
 
+  // Tell this stream to ignore any length limitation -- this only
+  // applies to BaseStream subclasses, and is used as a hack to work
+  // around broken PDF files with incorrect stream lengths.
+  virtual void ignoreLength() {}
+
 private:
 
   Stream *makeFilter(char *name, Stream *str, Object *params);
@@ -102,6 +118,68 @@ private:
   int ref;                     // reference count
 };
 
+//------------------------------------------------------------------------
+// BaseStream
+//
+// This is the base class for all streams that read directly from a file.
+//------------------------------------------------------------------------
+
+class BaseStream: public Stream {
+public:
+
+  BaseStream(Object *dictA);
+  virtual ~BaseStream();
+  virtual Stream *makeSubStream(Guint start, GBool limited,
+                               Guint length, Object *dict) = 0;
+  virtual void setPos(Guint pos, int dir = 0) = 0;
+  virtual GBool isBinary(GBool last = gTrue) { return last; }
+  virtual BaseStream *getBaseStream() { return this; }
+  virtual Dict *getDict() { return dict.getDict(); }
+
+  // Get/set position of first byte of stream within the file.
+  virtual Guint getStart() = 0;
+  virtual void moveStart(int delta) = 0;
+
+#ifndef NO_DECRYPTION
+  // Set decryption for this stream.
+  virtual void doDecryption(Guchar *fileKey, int keyLength,
+                           int objNum, int objGen);
+#endif
+
+#ifndef NO_DECRYPTION
+protected:
+
+  Decrypt *decrypt;
+#endif
+
+private:
+
+  Object dict;
+};
+
+//------------------------------------------------------------------------
+// FilterStream
+//
+// This is the base class for all streams that filter another stream.
+//------------------------------------------------------------------------
+
+class FilterStream: public Stream {
+public:
+
+  FilterStream(Stream *strA);
+  virtual ~FilterStream();
+  virtual void close();
+  virtual int getPos() { return str->getPos(); }
+  virtual void setPos(Guint pos, int dir = 0);
+  virtual BaseStream *getBaseStream() { return str->getBaseStream(); }
+  virtual Dict *getDict() { return str->getDict(); }
+  virtual void ignoreLength() { str->ignoreLength(); }
+
+protected:
+
+  Stream *str;
+};
+
 //------------------------------------------------------------------------
 // ImageStream
 //------------------------------------------------------------------------
@@ -112,7 +190,7 @@ public:
   // Create an image stream object for an image with the specified
   // parameters.  Note that these are the actual image parameters,
   // which may be different from the predictor parameters.
-  ImageStream(Stream *str, int width, int nComps, int nBits);
+  ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA);
 
   ~ImageStream();
 
@@ -123,6 +201,10 @@ public:
   // at least nComps elements.  Returns false at end of file.
   GBool getPixel(Guchar *pix);
 
+  // Returns a pointer to the next line of pixels.  Returns NULL at
+  // end of file.
+  Guchar *getLine();
+
   // Skip an entire line from the image.
   void skipLine();
 
@@ -146,8 +228,8 @@ public:
 
   // Create a predictor object.  Note that the parameters are for the
   // predictor, and may not match the actual image parameters.
-  StreamPredictor(Stream *str, int predictor,
-                 int width, int nComps, int nBits);
+  StreamPredictor(Stream *strA, int predictorA,
+                 int widthA, int nCompsA, int nBitsA);
 
   ~StreamPredictor();
 
@@ -174,95 +256,134 @@ private:
 // FileStream
 //------------------------------------------------------------------------
 
-class FileStream: public Stream {
+#define fileStreamBufSize 256
+
+class FileStream: public BaseStream {
 public:
 
-  FileStream(FILE *f1, int start1, int length1, Object *dict1);
+  FileStream(FILE *fA, Guint startA, GBool limitedA,
+            Guint lengthA, Object *dictA);
   virtual ~FileStream();
+  virtual Stream *makeSubStream(Guint startA, GBool limitedA,
+                               Guint lengthA, Object *dictA);
   virtual StreamKind getKind() { return strFile; }
   virtual void reset();
+  virtual void close();
   virtual int getChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
   virtual int lookChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
   virtual int getPos() { return bufPos + (bufPtr - buf); }
-  virtual void setPos(int pos1);
-  virtual GBool isBinary(GBool last = gTrue) { return last; }
-  virtual Stream *getBaseStream() { return this; }
-  virtual FILE *getFile() { return f; }
-  virtual Dict *getDict() { return dict.getDict(); }
-
-  // Check for a PDF header on this stream.  Skip past some garbage
-  // if necessary.
-  GBool checkHeader();
-
-  // Get position of first byte of stream within the file.
-  int getStart() { return start; }
+  virtual void setPos(Guint pos, int dir = 0);
+  virtual void ignoreLength() { limited = gFalse; }
+  virtual Guint getStart() { return start; }
+  virtual void moveStart(int delta);
 
 private:
 
   GBool fillBuf();
 
   FILE *f;
-  int start;
-  int length;
-  char buf[256];
+  Guint start;
+  GBool limited;
+  Guint length;
+  char buf[fileStreamBufSize];
   char *bufPtr;
   char *bufEnd;
-  int bufPos;
+  Guint bufPos;
   int savePos;
-  Object dict;
+  GBool saved;
+};
+
+//------------------------------------------------------------------------
+// MemStream
+//------------------------------------------------------------------------
+
+class MemStream: public BaseStream {
+public:
+
+  MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA);
+  virtual ~MemStream();
+  virtual Stream *makeSubStream(Guint start, GBool limited,
+                               Guint lengthA, Object *dictA);
+  virtual StreamKind getKind() { return strWeird; }
+  virtual void reset();
+  virtual void close();
+  virtual int getChar()
+    { return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; }
+  virtual int lookChar()
+    { return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; }
+  virtual int getPos() { return (int)(bufPtr - buf); }
+  virtual void setPos(Guint pos, int dir = 0);
+  virtual Guint getStart() { return start; }
+  virtual void moveStart(int delta);
+#ifndef NO_DECRYPTION
+  virtual void doDecryption(Guchar *fileKey, int keyLength,
+                           int objNum, int objGen);
+#endif
+
+private:
+
+  char *buf;
+  Guint start;
+  Guint length;
+  char *bufEnd;
+  char *bufPtr;
+  GBool needFree;
 };
 
 //------------------------------------------------------------------------
-// SubStream
+// EmbedStream
+//
+// This is a special stream type used for embedded streams (inline
+// images).  It reads directly from the base stream -- after the
+// EmbedStream is deleted, reads from the base stream will proceed where
+// the BaseStream left off.  Note that this is very different behavior
+// that creating a new FileStream (using makeSubStream).
 //------------------------------------------------------------------------
 
-class SubStream: public Stream {
+class EmbedStream: public BaseStream {
 public:
 
-  SubStream(Stream *str1, Object *dict1);
-  virtual ~SubStream();
+  EmbedStream(Stream *strA, Object *dictA, GBool limitedA, Guint lengthA);
+  virtual ~EmbedStream();
+  virtual Stream *makeSubStream(Guint start, GBool limitedA,
+                               Guint lengthA, Object *dictA);
   virtual StreamKind getKind() { return str->getKind(); }
   virtual void reset() {}
-  virtual int getChar() { return str->getChar(); }
-  virtual int lookChar() { return str->lookChar(); }
+  virtual int getChar();
+  virtual int lookChar();
   virtual int getPos() { return str->getPos(); }
-  virtual GBool isBinary(GBool last = gTrue) { return last; }
-  virtual Stream *getBaseStream() { return this; }
-  virtual FILE *getFile() { return str->getFile(); }
-  virtual Dict *getDict() { return dict.getDict(); }
+  virtual void setPos(Guint pos, int dir = 0);
+  virtual Guint getStart();
+  virtual void moveStart(int delta);
 
 private:
 
   Stream *str;
-  Object dict;
+  GBool limited;
+  Guint length;
 };
 
 //------------------------------------------------------------------------
 // ASCIIHexStream
 //------------------------------------------------------------------------
 
-class ASCIIHexStream: public Stream {
+class ASCIIHexStream: public FilterStream {
 public:
 
-  ASCIIHexStream(Stream *str1);
+  ASCIIHexStream(Stream *strA);
   virtual ~ASCIIHexStream();
   virtual StreamKind getKind() { return strASCIIHex; }
   virtual void reset();
   virtual int getChar()
     { int c = lookChar(); buf = EOF; return c; }
   virtual int lookChar();
-  virtual int getPos() { return str->getPos(); }
-  virtual GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(int psLevel, char *indent);
   virtual GBool isBinary(GBool last = gTrue);
-  virtual Stream *getBaseStream() { return str->getBaseStream(); }
-  virtual FILE *getFile() { return str->getFile(); }
-  virtual Dict *getDict() { return str->getDict(); }
 
 private:
 
-  Stream *str;
   int buf;
   GBool eof;
 };
@@ -271,26 +392,21 @@ private:
 // ASCII85Stream
 //------------------------------------------------------------------------
 
-class ASCII85Stream: public Stream {
+class ASCII85Stream: public FilterStream {
 public:
 
-  ASCII85Stream(Stream *str1);
+  ASCII85Stream(Stream *strA);
   virtual ~ASCII85Stream();
   virtual StreamKind getKind() { return strASCII85; }
   virtual void reset();
   virtual int getChar()
     { int ch = lookChar(); ++index; return ch; }
   virtual int lookChar();
-  virtual int getPos() { return str->getPos(); }
-  virtual GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(int psLevel, char *indent);
   virtual GBool isBinary(GBool last = gTrue);
-  virtual Stream *getBaseStream() { return str->getBaseStream(); }
-  virtual FILE *getFile() { return str->getFile(); }
-  virtual Dict *getDict() { return str->getDict(); }
 
 private:
 
-  Stream *str;
   int c[5];
   int b[4];
   int index, n;
@@ -301,52 +417,54 @@ private:
 // LZWStream
 //------------------------------------------------------------------------
 
-class LZWStream: public Stream {
+class LZWStream: public FilterStream {
 public:
 
-  LZWStream(Stream *str1, int predictor1, int columns1, int colors1,
-           int bits1, int early1);
+  LZWStream(Stream *strA, int predictor, int columns, int colors,
+           int bits, int earlyA);
   virtual ~LZWStream();
   virtual StreamKind getKind() { return strLZW; }
   virtual void reset();
   virtual int getChar();
   virtual int lookChar();
   virtual int getRawChar();
-  virtual int getPos() { return str->getPos(); }
-  virtual GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(int psLevel, char *indent);
   virtual GBool isBinary(GBool last = gTrue);
-  virtual Stream *getBaseStream() { return str->getBaseStream(); }
-  virtual FILE *getFile() { return str->getFile(); }
-  virtual Dict *getDict() { return str->getDict(); }
 
 private:
 
-  Stream *str;                 // stream
   StreamPredictor *pred;       // predictor
   int early;                   // early parameter
-  char zCmd[256];              // uncompress command
-  FILE *zPipe;                 // uncompress pipe
-  char *zName;                 // .Z file name (in zCmd)
+  GBool eof;                   // true if at eof
   int inputBuf;                        // input buffer
   int inputBits;               // number of bits in input buffer
-  int inCodeBits;              // size of input code
-  char buf[256];               // buffer
-  char *bufPtr;                        // next char to read
-  char *bufEnd;                        // end of buffer
-
-  void dumpFile(FILE *f);
+  struct {                     // decoding table
+    int length;
+    int head;
+    Guchar tail;
+  } table[4097];
+  int nextCode;                        // next code to be used
+  int nextBits;                        // number of bits in next code word
+  int prevCode;                        // previous code used in stream
+  int newChar;                 // next char to be added to table
+  Guchar seqBuf[4097];         // buffer for current sequence
+  int seqLength;               // length of current sequence
+  int seqIndex;                        // index into current sequence
+  GBool first;                 // first code after a table clear
+
+  GBool processNextCode();
+  void clearTable();
   int getCode();
-  GBool fillBuf();
 };
 
 //------------------------------------------------------------------------
 // RunLengthStream
 //------------------------------------------------------------------------
 
-class RunLengthStream: public Stream {
+class RunLengthStream: public FilterStream {
 public:
 
-  RunLengthStream(Stream *str1);
+  RunLengthStream(Stream *strA);
   virtual ~RunLengthStream();
   virtual StreamKind getKind() { return strRunLength; }
   virtual void reset();
@@ -354,16 +472,11 @@ public:
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
   virtual int lookChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
-  virtual int getPos() { return str->getPos(); }
-  virtual GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(int psLevel, char *indent);
   virtual GBool isBinary(GBool last = gTrue);
-  virtual Stream *getBaseStream() { return str->getBaseStream(); }
-  virtual FILE *getFile() { return str->getFile(); }
-  virtual Dict *getDict() { return str->getDict(); }
 
 private:
 
-  Stream *str;
   char buf[128];               // buffer
   char *bufPtr;                        // next char to read
   char *bufEnd;                        // end of buffer
@@ -378,28 +491,23 @@ private:
 
 struct CCITTCodeTable;
 
-class CCITTFaxStream: public Stream {
+class CCITTFaxStream: public FilterStream {
 public:
 
-  CCITTFaxStream(Stream *str, int encoding, GBool endOfLine,
-                GBool byteAlign, int columns, int rows,
-                GBool endOfBlock, GBool black);
+  CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
+                GBool byteAlignA, int columnsA, int rowsA,
+                GBool endOfBlockA, GBool blackA);
   virtual ~CCITTFaxStream();
   virtual StreamKind getKind() { return strCCITTFax; }
   virtual void reset();
   virtual int getChar()
     { int c = lookChar(); buf = EOF; return c; }
   virtual int lookChar();
-  virtual int getPos() { return str->getPos(); }
-  virtual GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(int psLevel, char *indent);
   virtual GBool isBinary(GBool last = gTrue);
-  virtual Stream *getBaseStream() { return str->getBaseStream(); }
-  virtual FILE *getFile() { return str->getFile(); }
-  virtual Dict *getDict() { return str->getDict(); }
 
 private:
 
-  Stream *str;                 // stream
   int encoding;                        // 'K' parameter
   GBool endOfLine;             // 'EndOfLine' parameter
   GBool byteAlign;             // 'EncodedByteAlign' parameter
@@ -433,13 +541,21 @@ private:
 // DCT component info
 struct DCTCompInfo {
   int id;                      // component ID
-  GBool inScan;                        // is this component in the current scan?
   int hSample, vSample;                // horiz/vert sampling resolutions
   int quantTable;              // quantization table number
-  int dcHuffTable, acHuffTable;        // Huffman table numbers
   int prevDC;                  // DC coefficient accumulator
 };
 
+struct DCTScanInfo {
+  GBool comp[4];               // comp[i] is set if component i is
+                               //   included in this scan
+  int numComps;                        // number of components in the scan
+  int dcHuffTable[4];          // DC Huffman table numbers
+  int acHuffTable[4];          // AC Huffman table numbers
+  int firstCoeff, lastCoeff;   // first and last DCT coefficient
+  int ah, al;                  // successive approximation parameters
+};
+
 // DCT Huffman decoding table
 struct DCTHuffTable {
   Guchar firstSym[17];         // first symbol for this bit length
@@ -448,31 +564,31 @@ struct DCTHuffTable {
   Guchar sym[256];             // symbols
 };
 
-class DCTStream: public Stream {
+class DCTStream: public FilterStream {
 public:
 
-  DCTStream(Stream *str1);
+  DCTStream(Stream *strA);
   virtual ~DCTStream();
   virtual StreamKind getKind() { return strDCT; }
   virtual void reset();
   virtual int getChar();
   virtual int lookChar();
-  virtual int getPos() { return str->getPos(); }
-  virtual GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(int psLevel, char *indent);
   virtual GBool isBinary(GBool last = gTrue);
-  virtual Stream *getBaseStream() { return str->getBaseStream(); }
-  virtual FILE *getFile() { return str->getFile(); }
-  virtual Dict *getDict() { return str->getDict(); }
   Stream *getRawStream() { return str; }
 
 private:
 
-  Stream *str;                 // stream
+  GBool progressive;           // set if in progressive mode
+  GBool interleaved;           // set if in interleaved mode
   int width, height;           // image size
   int mcuWidth, mcuHeight;     // size of min coding unit, in data units
+  int bufWidth, bufHeight;     // frameBuf size
   DCTCompInfo compInfo[4];     // info for each component
+  DCTScanInfo scanInfo;                // info for the current scan
   int numComps;                        // number of components in image
   int colorXform;              // need YCbCr-to-RGB transform?
+  GBool gotJFIFMarker;         // set if APP0 JFIF marker was present
   GBool gotAdobeMarker;                // set if APP14 Adobe marker was present
   int restartInterval;         // restart interval, in MCUs
   Guchar quantTables[4][64];   // quantization tables
@@ -481,26 +597,38 @@ private:
   DCTHuffTable acHuffTables[4];        // AC Huffman tables
   int numDCHuffTables;         // number of DC Huffman tables
   int numACHuffTables;         // number of AC Huffman tables
-  Guchar *rowBuf[4][32];       // buffer for one MCU
+  Guchar *rowBuf[4][32];       // buffer for one MCU (non-progressive mode)
+  int *frameBuf[4];            // buffer for frame (progressive mode)
   int comp, x, y, dy;          // current position within image/MCU
   int restartCtr;              // MCUs left until restart
   int restartMarker;           // next restart marker
+  int eobRun;                  // number of EOBs left in the current run
   int inputBuf;                        // input buffer for variable length codes
   int inputBits;               // number of valid bits in input buffer
 
   void restart();
   GBool readMCURow();
-  GBool readDataUnit(DCTHuffTable *dcHuffTable, DCTHuffTable *acHuffTable,
-                    Guchar quantTable[64], int *prevDC, Guchar data[64]);
+  void readScan();
+  GBool readDataUnit(DCTHuffTable *dcHuffTable,
+                    DCTHuffTable *acHuffTable,
+                    int *prevDC, int data[64]);
+  GBool readProgressiveDataUnit(DCTHuffTable *dcHuffTable,
+                               DCTHuffTable *acHuffTable,
+                               int *prevDC, int data[64]);
+  void decodeImage();
+  void transformDataUnit(Guchar *quantTable,
+                        int dataIn[64], Guchar dataOut[64]);
   int readHuffSym(DCTHuffTable *table);
   int readAmp(int size);
   int readBit();
   GBool readHeader();
-  GBool readFrameInfo();
+  GBool readBaselineSOF();
+  GBool readProgressiveSOF();
   GBool readScanInfo();
   GBool readQuantTables();
   GBool readHuffmanTables();
   GBool readRestartInterval();
+  GBool readJFIFMarker();
   GBool readAdobeMarker();
   GBool readTrailer();
   int readMarker();
@@ -520,15 +648,13 @@ private:
 
 // Huffman code table entry
 struct FlateCode {
-  int len;                     // code length in bits
-  int code;                    // code word
-  int val;                     // value represented by this code
+  Gushort len;                 // code length, in bits
+  Gushort val;                 // value represented by this code
 };
 
-// Huffman code table
 struct FlateHuffmanTab {
-  int start[flateMaxHuffman+2];        // indexes of first code of each length
-  FlateCode *codes;            // codes, sorted by length and code word
+  FlateCode *codes;
+  int maxLen;
 };
 
 // Decoding info for length and distance code words
@@ -537,35 +663,30 @@ struct FlateDecode {
   int first;                   // first length/distance
 };
 
-class FlateStream: public Stream {
+class FlateStream: public FilterStream {
 public:
 
-  FlateStream(Stream *str1, int predictor1, int columns1,
-             int colors1, int bits1);
+  FlateStream(Stream *strA, int predictor, int columns,
+             int colors, int bits);
   virtual ~FlateStream();
   virtual StreamKind getKind() { return strFlate; }
   virtual void reset();
   virtual int getChar();
   virtual int lookChar();
   virtual int getRawChar();
-  virtual int getPos() { return str->getPos(); }
-  virtual GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(int psLevel, char *indent);
   virtual GBool isBinary(GBool last = gTrue);
-  virtual Stream *getBaseStream() { return str->getBaseStream(); }
-  virtual FILE *getFile() { return str->getFile(); }
-  virtual Dict *getDict() { return str->getDict(); }
 
 private:
 
-  Stream *str;                 // stream
   StreamPredictor *pred;       // predictor
   Guchar buf[flateWindow];     // output data buffer
   int index;                   // current index into output buffer
   int remain;                  // number valid bytes in output buffer
   int codeBuf;                 // input buffer
   int codeSize;                        // number of bits in input buffer
-  FlateCode                    // literal and distance codes
-    allCodes[flateMaxLitCodes + flateMaxDistCodes];
+  int                          // literal and distance code lengths
+    codeLengths[flateMaxLitCodes + flateMaxDistCodes];
   FlateHuffmanTab litCodeTab;  // literal code table
   FlateHuffmanTab distCodeTab; // distance code table
   GBool compressedBlock;       // set if reading a compressed block
@@ -584,7 +705,7 @@ private:
   GBool startBlock();
   void loadFixedCodes();
   GBool readDynamicCodes();
-  void compHuffmanCodes(FlateHuffmanTab *tab, int n);
+  void compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab);
   int getHuffmanCodeWord(FlateHuffmanTab *tab);
   int getCodeWord(int bits);
 };
@@ -593,63 +714,80 @@ private:
 // EOFStream
 //------------------------------------------------------------------------
 
-class EOFStream: public Stream {
+class EOFStream: public FilterStream {
 public:
 
-  EOFStream(Stream *str1);
+  EOFStream(Stream *strA);
   virtual ~EOFStream();
   virtual StreamKind getKind() { return strWeird; }
   virtual void reset() {}
   virtual int getChar() { return EOF; }
   virtual int lookChar() { return EOF; }
-  virtual int getPos() { return str->getPos(); }
-  virtual GString *getPSFilter(char *indent)  { return NULL; }
+  virtual GString *getPSFilter(int psLevel, char *indent)  { return NULL; }
   virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
-  virtual Stream *getBaseStream() { return str->getBaseStream(); }
-  virtual FILE *getFile() { return str->getFile(); }
-  virtual Dict *getDict() { return str->getDict(); }
-
-private:
-
-  Stream *str;
 };
 
 //------------------------------------------------------------------------
 // FixedLengthEncoder
 //------------------------------------------------------------------------
 
-class FixedLengthEncoder: public Stream {
+class FixedLengthEncoder: public FilterStream {
 public:
 
-  FixedLengthEncoder(Stream *str1, int length1);
+  FixedLengthEncoder(Stream *strA, int lengthA);
   ~FixedLengthEncoder();
   virtual StreamKind getKind() { return strWeird; }
   virtual void reset();
   virtual int getChar();
   virtual int lookChar();
-  virtual int getPos() { return str->getPos(); }
-  virtual GString *getPSFilter(char *indent) { return NULL; }
-  virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
-  virtual Stream *getBaseStream() { return str->getBaseStream(); }
-  virtual FILE *getFile() { return str->getFile(); }
-  virtual Dict *getDict() { return str->getDict(); }
+  virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
+  virtual GBool isBinary(GBool last = gTrue);
   virtual GBool isEncoder() { return gTrue; }
 
 private:
 
-  Stream *str;
   int length;
   int count;
 };
 
+//------------------------------------------------------------------------
+// ASCIIHexEncoder
+//------------------------------------------------------------------------
+
+class ASCIIHexEncoder: public FilterStream {
+public:
+
+  ASCIIHexEncoder(Stream *strA);
+  virtual ~ASCIIHexEncoder();
+  virtual StreamKind getKind() { return strWeird; }
+  virtual void reset();
+  virtual int getChar()
+    { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
+  virtual int lookChar()
+    { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
+  virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
+  virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+  virtual GBool isEncoder() { return gTrue; }
+
+private:
+
+  char buf[4];
+  char *bufPtr;
+  char *bufEnd;
+  int lineLen;
+  GBool eof;
+
+  GBool fillBuf();
+};
+
 //------------------------------------------------------------------------
 // ASCII85Encoder
 //------------------------------------------------------------------------
 
-class ASCII85Encoder: public Stream {
+class ASCII85Encoder: public FilterStream {
 public:
 
-  ASCII85Encoder(Stream *str1);
+  ASCII85Encoder(Stream *strA);
   virtual ~ASCII85Encoder();
   virtual StreamKind getKind() { return strWeird; }
   virtual void reset();
@@ -657,17 +795,12 @@ public:
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
   virtual int lookChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
-  virtual int getPos() { return str->getPos(); }
-  virtual GString *getPSFilter(char *indent) { return NULL; }
+  virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
   virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
-  virtual Stream *getBaseStream() { return str->getBaseStream(); }
-  virtual FILE *getFile() { return str->getFile(); }
-  virtual Dict *getDict() { return str->getDict(); }
   virtual GBool isEncoder() { return gTrue; }
 
 private:
 
-  Stream *str;
   char buf[8];
   char *bufPtr;
   char *bufEnd;
@@ -681,10 +814,10 @@ private:
 // RunLengthEncoder
 //------------------------------------------------------------------------
 
-class RunLengthEncoder: public Stream {
+class RunLengthEncoder: public FilterStream {
 public:
 
-  RunLengthEncoder(Stream *str1);
+  RunLengthEncoder(Stream *strA);
   virtual ~RunLengthEncoder();
   virtual StreamKind getKind() { return strWeird; }
   virtual void reset();
@@ -692,17 +825,12 @@ public:
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
   virtual int lookChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
-  virtual int getPos() { return str->getPos(); }
-  virtual GString *getPSFilter(char *indent) { return NULL; }
-  virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
-  virtual Stream *getBaseStream() { return str->getBaseStream(); }
-  virtual FILE *getFile() { return str->getFile(); }
-  virtual Dict *getDict() { return str->getDict(); }
+  virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
+  virtual GBool isBinary(GBool last = gTrue) { return gTrue; }
   virtual GBool isEncoder() { return gTrue; }
 
 private:
 
-  Stream *str;
   char buf[131];
   char *bufPtr;
   char *bufEnd;