upgrade to xpdf 3.00.
[swftools.git] / pdf2swf / xpdf / Stream.h
index 50345bb..0b70afa 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
 
@@ -33,6 +35,8 @@ enum StreamKind {
   strCCITTFax,
   strDCT,
   strFlate,
+  strJBIG2,
+  strJPX,
   strWeird                     // internal-use stream types
 };
 
@@ -78,16 +82,18 @@ public:
   // Get current position in file.
   virtual int getPos() = 0;
 
-  // Go to a position in the stream.
-  virtual void setPos(int pos1) = 0;
+  // 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 BaseStream or EmbedStream of this stream.
+  // Get the BaseStream of this stream.
   virtual BaseStream *getBaseStream() = 0;
 
   // Get the dictionary associated with this stream.
@@ -100,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);
@@ -116,20 +127,23 @@ private:
 class BaseStream: public Stream {
 public:
 
-  BaseStream(Object *dict);
+  BaseStream(Object *dictA);
   virtual ~BaseStream();
-  virtual Stream *makeSubStream(int start, int length, Object *dict) = 0;
-  virtual void setPos(int pos1) = 0;
+  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 int getStart() = 0;
+  virtual Guint getStart() = 0;
   virtual void moveStart(int delta) = 0;
 
 #ifndef NO_DECRYPTION
   // Set decryption for this stream.
-  void doDecryption(Guchar *fileKey, int objNum, int objGen);
+  virtual void doDecryption(Guchar *fileKey, int keyLength,
+                           int objNum, int objGen);
 #endif
 
 #ifndef NO_DECRYPTION
@@ -152,13 +166,14 @@ private:
 class FilterStream: public Stream {
 public:
 
-  FilterStream(Stream *str);
+  FilterStream(Stream *strA);
   virtual ~FilterStream();
   virtual void close();
   virtual int getPos() { return str->getPos(); }
-  virtual void setPos(int pos);
+  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:
 
@@ -175,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();
 
@@ -186,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();
 
@@ -209,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();
 
@@ -242,9 +261,11 @@ private:
 class FileStream: public BaseStream {
 public:
 
-  FileStream(FILE *f, int start, int length, Object *dict);
+  FileStream(FILE *fA, Guint startA, GBool limitedA,
+            Guint lengthA, Object *dictA);
   virtual ~FileStream();
-  virtual Stream *makeSubStream(int start, int length, Object *dict);
+  virtual Stream *makeSubStream(Guint startA, GBool limitedA,
+                               Guint lengthA, Object *dictA);
   virtual StreamKind getKind() { return strFile; }
   virtual void reset();
   virtual void close();
@@ -253,9 +274,9 @@ public:
   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 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:
@@ -263,13 +284,52 @@ private:
   GBool fillBuf();
 
   FILE *f;
-  int start;
-  int length;
+  Guint start;
+  GBool limited;
+  Guint length;
   char buf[fileStreamBufSize];
   char *bufPtr;
   char *bufEnd;
-  int bufPos;
+  Guint bufPos;
   int savePos;
+  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;
 };
 
 //------------------------------------------------------------------------
@@ -285,22 +345,24 @@ private:
 class EmbedStream: public BaseStream {
 public:
 
-  EmbedStream(Stream *str, Object *dict);
+  EmbedStream(Stream *strA, Object *dictA, GBool limitedA, Guint lengthA);
   virtual ~EmbedStream();
-  virtual Stream *makeSubStream(int start, int length, Object *dict);
+  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 void setPos(int pos);
-  virtual GBool isBinary(GBool last = gTrue) { return last; }
-  virtual int getStart();
+  virtual void setPos(Guint pos, int dir = 0);
+  virtual Guint getStart();
   virtual void moveStart(int delta);
 
 private:
 
   Stream *str;
+  GBool limited;
+  Guint length;
 };
 
 //------------------------------------------------------------------------
@@ -310,14 +372,14 @@ private:
 class ASCIIHexStream: public FilterStream {
 public:
 
-  ASCIIHexStream(Stream *str);
+  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 GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(int psLevel, char *indent);
   virtual GBool isBinary(GBool last = gTrue);
 
 private:
@@ -333,14 +395,14 @@ private:
 class ASCII85Stream: public FilterStream {
 public:
 
-  ASCII85Stream(Stream *str);
+  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 GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(int psLevel, char *indent);
   virtual GBool isBinary(GBool last = gTrue);
 
 private:
@@ -358,33 +420,41 @@ private:
 class LZWStream: public FilterStream {
 public:
 
-  LZWStream(Stream *str, 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 GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(int psLevel, char *indent);
   virtual GBool isBinary(GBool last = gTrue);
 
 private:
 
   StreamPredictor *pred;       // predictor
   int early;                   // early parameter
-  FILE *zPipe;                 // uncompress pipe
-  GString *zName;              // .Z file name
+  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();
 };
 
 //------------------------------------------------------------------------
@@ -394,7 +464,7 @@ private:
 class RunLengthStream: public FilterStream {
 public:
 
-  RunLengthStream(Stream *str);
+  RunLengthStream(Stream *strA);
   virtual ~RunLengthStream();
   virtual StreamKind getKind() { return strRunLength; }
   virtual void reset();
@@ -402,7 +472,7 @@ public:
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
   virtual int lookChar()
     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
-  virtual GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(int psLevel, char *indent);
   virtual GBool isBinary(GBool last = gTrue);
 
 private:
@@ -424,16 +494,16 @@ struct CCITTCodeTable;
 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 GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(int psLevel, char *indent);
   virtual GBool isBinary(GBool last = gTrue);
 
 private:
@@ -471,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
@@ -489,23 +567,28 @@ struct DCTHuffTable {
 class DCTStream: public FilterStream {
 public:
 
-  DCTStream(Stream *str);
+  DCTStream(Stream *strA);
   virtual ~DCTStream();
   virtual StreamKind getKind() { return strDCT; }
   virtual void reset();
   virtual int getChar();
   virtual int lookChar();
-  virtual GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(int psLevel, char *indent);
   virtual GBool isBinary(GBool last = gTrue);
   Stream *getRawStream() { return str; }
 
 private:
 
+  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
@@ -514,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();
@@ -553,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
@@ -573,15 +666,15 @@ struct FlateDecode {
 class FlateStream: public FilterStream {
 public:
 
-  FlateStream(Stream *str, 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 GString *getPSFilter(char *indent);
+  virtual GString *getPSFilter(int psLevel, char *indent);
   virtual GBool isBinary(GBool last = gTrue);
 
 private:
@@ -592,8 +685,8 @@ private:
   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
@@ -612,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);
 };
@@ -624,13 +717,13 @@ private:
 class EOFStream: public FilterStream {
 public:
 
-  EOFStream(Stream *str);
+  EOFStream(Stream *strA);
   virtual ~EOFStream();
   virtual StreamKind getKind() { return strWeird; }
   virtual void reset() {}
   virtual int getChar() { return EOF; }
   virtual int lookChar() { return EOF; }
-  virtual GString *getPSFilter(char *indent)  { return NULL; }
+  virtual GString *getPSFilter(int psLevel, char *indent)  { return NULL; }
   virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
 };
 
@@ -641,15 +734,14 @@ public:
 class FixedLengthEncoder: public FilterStream {
 public:
 
-  FixedLengthEncoder(Stream *str, int length1);
+  FixedLengthEncoder(Stream *strA, int lengthA);
   ~FixedLengthEncoder();
   virtual StreamKind getKind() { return strWeird; }
   virtual void reset();
-  virtual void close();
   virtual int getChar();
   virtual int lookChar();
-  virtual GString *getPSFilter(char *indent) { return NULL; }
-  virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+  virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
+  virtual GBool isBinary(GBool last = gTrue);
   virtual GBool isEncoder() { return gTrue; }
 
 private:
@@ -659,22 +751,51 @@ private:
 };
 
 //------------------------------------------------------------------------
+// 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 FilterStream {
 public:
 
-  ASCII85Encoder(Stream *str);
+  ASCII85Encoder(Stream *strA);
   virtual ~ASCII85Encoder();
   virtual StreamKind getKind() { return strWeird; }
   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 GString *getPSFilter(char *indent) { return NULL; }
+  virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
   virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
   virtual GBool isEncoder() { return gTrue; }
 
@@ -696,17 +817,16 @@ private:
 class RunLengthEncoder: public FilterStream {
 public:
 
-  RunLengthEncoder(Stream *str);
+  RunLengthEncoder(Stream *strA);
   virtual ~RunLengthEncoder();
   virtual StreamKind getKind() { return strWeird; }
   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 GString *getPSFilter(char *indent) { return NULL; }
-  virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
+  virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; }
+  virtual GBool isBinary(GBool last = gTrue) { return gTrue; }
   virtual GBool isEncoder() { return gTrue; }
 
 private: