3319dccd109130118b85867757ab41f97ca03bc2
[swftools.git] / pdf2swf / xpdf / Stream.h
1 //========================================================================
2 //
3 // Stream.h
4 //
5 // Copyright 1996-2002 Glyph & Cog, LLC
6 //
7 //========================================================================
8
9 #ifndef STREAM_H
10 #define STREAM_H
11
12 #ifdef __GNUC__
13 #pragma interface
14 #endif
15
16 #include <stdio.h>
17 #include "gtypes.h"
18 #include "Object.h"
19
20 #ifndef NO_DECRYPTION
21 class Decrypt;
22 #endif
23 class BaseStream;
24
25 //------------------------------------------------------------------------
26
27 enum StreamKind {
28   strFile,
29   strASCIIHex,
30   strASCII85,
31   strLZW,
32   strRunLength,
33   strCCITTFax,
34   strDCT,
35   strFlate,
36   strWeird                      // internal-use stream types
37 };
38
39 //------------------------------------------------------------------------
40 // Stream (base class)
41 //------------------------------------------------------------------------
42
43 class Stream {
44 public:
45
46   // Constructor.
47   Stream();
48
49   // Destructor.
50   virtual ~Stream();
51
52   // Reference counting.
53   int incRef() { return ++ref; }
54   int decRef() { return --ref; }
55
56   // Get kind of stream.
57   virtual StreamKind getKind() = 0;
58
59   // Reset stream to beginning.
60   virtual void reset() = 0;
61
62   // Close down the stream.
63   virtual void close();
64
65   // Get next char from stream.
66   virtual int getChar() = 0;
67
68   // Peek at next char in stream.
69   virtual int lookChar() = 0;
70
71   // Get next char from stream without using the predictor.
72   // This is only used by StreamPredictor.
73   virtual int getRawChar();
74
75   // Get next line from stream.
76   virtual char *getLine(char *buf, int size);
77
78   // Get current position in file.
79   virtual int getPos() = 0;
80
81   // Go to a position in the stream.  If <dir> is negative, the
82   // position is from the end of the file; otherwise the position is
83   // from the start of the file.
84   virtual void setPos(Guint pos, int dir = 0) = 0;
85
86   // Get PostScript command for the filter(s).
87   virtual GString *getPSFilter(char *indent);
88
89   // Does this stream type potentially contain non-printable chars?
90   virtual GBool isBinary(GBool last = gTrue) = 0;
91
92   // Get the BaseStream or EmbedStream of this stream.
93   virtual BaseStream *getBaseStream() = 0;
94
95   // Get the dictionary associated with this stream.
96   virtual Dict *getDict() = 0;
97
98   // Is this an encoding filter?
99   virtual GBool isEncoder() { return gFalse; }
100
101   // Add filters to this stream according to the parameters in <dict>.
102   // Returns the new stream.
103   Stream *addFilters(Object *dict);
104
105 private:
106
107   Stream *makeFilter(char *name, Stream *str, Object *params);
108
109   int ref;                      // reference count
110 };
111
112 //------------------------------------------------------------------------
113 // BaseStream
114 //
115 // This is the base class for all streams that read directly from a file.
116 //------------------------------------------------------------------------
117
118 class BaseStream: public Stream {
119 public:
120
121   BaseStream(Object *dictA);
122   virtual ~BaseStream();
123   virtual Stream *makeSubStream(Guint start, GBool limited,
124                                 Guint length, Object *dict) = 0;
125   virtual void setPos(Guint pos, int dir = 0) = 0;
126   virtual BaseStream *getBaseStream() { return this; }
127   virtual Dict *getDict() { return dict.getDict(); }
128
129   // Get/set position of first byte of stream within the file.
130   virtual Guint getStart() = 0;
131   virtual void moveStart(int delta) = 0;
132
133 #ifndef NO_DECRYPTION
134   // Set decryption for this stream.
135   virtual void doDecryption(Guchar *fileKey, int keyLength,
136                             int objNum, int objGen);
137 #endif
138
139 #ifndef NO_DECRYPTION
140 protected:
141
142   Decrypt *decrypt;
143 #endif
144
145 private:
146
147   Object dict;
148 };
149
150 //------------------------------------------------------------------------
151 // FilterStream
152 //
153 // This is the base class for all streams that filter another stream.
154 //------------------------------------------------------------------------
155
156 class FilterStream: public Stream {
157 public:
158
159   FilterStream(Stream *strA);
160   virtual ~FilterStream();
161   virtual void close();
162   virtual int getPos() { return str->getPos(); }
163   virtual void setPos(Guint pos, int dir = 0);
164   virtual BaseStream *getBaseStream() { return str->getBaseStream(); }
165   virtual Dict *getDict() { return str->getDict(); }
166
167 protected:
168
169   Stream *str;
170 };
171
172 //------------------------------------------------------------------------
173 // ImageStream
174 //------------------------------------------------------------------------
175
176 class ImageStream {
177 public:
178
179   // Create an image stream object for an image with the specified
180   // parameters.  Note that these are the actual image parameters,
181   // which may be different from the predictor parameters.
182   ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA);
183
184   ~ImageStream();
185
186   // Reset the stream.
187   void reset();
188
189   // Gets the next pixel from the stream.  <pix> should be able to hold
190   // at least nComps elements.  Returns false at end of file.
191   GBool getPixel(Guchar *pix);
192
193   // Skip an entire line from the image.
194   void skipLine();
195
196 private:
197
198   Stream *str;                  // base stream
199   int width;                    // pixels per line
200   int nComps;                   // components per pixel
201   int nBits;                    // bits per component
202   int nVals;                    // components per line
203   Guchar *imgLine;              // line buffer
204   int imgIdx;                   // current index in imgLine
205 };
206
207 //------------------------------------------------------------------------
208 // StreamPredictor
209 //------------------------------------------------------------------------
210
211 class StreamPredictor {
212 public:
213
214   // Create a predictor object.  Note that the parameters are for the
215   // predictor, and may not match the actual image parameters.
216   StreamPredictor(Stream *strA, int predictorA,
217                   int widthA, int nCompsA, int nBitsA);
218
219   ~StreamPredictor();
220
221   int lookChar();
222   int getChar();
223
224 private:
225
226   GBool getNextLine();
227
228   Stream *str;                  // base stream
229   int predictor;                // predictor
230   int width;                    // pixels per line
231   int nComps;                   // components per pixel
232   int nBits;                    // bits per component
233   int nVals;                    // components per line
234   int pixBytes;                 // bytes per pixel
235   int rowBytes;                 // bytes per line
236   Guchar *predLine;             // line buffer
237   int predIdx;                  // current index in predLine
238 };
239
240 //------------------------------------------------------------------------
241 // FileStream
242 //------------------------------------------------------------------------
243
244 #define fileStreamBufSize 256
245
246 class FileStream: public BaseStream {
247 public:
248
249   FileStream(FILE *fA, Guint startA, GBool limitedA,
250              Guint lengthA, Object *dictA);
251   virtual ~FileStream();
252   virtual Stream *makeSubStream(Guint startA, GBool limitedA,
253                                 Guint lengthA, Object *dictA);
254   virtual StreamKind getKind() { return strFile; }
255   virtual void reset();
256   virtual void close();
257   virtual int getChar()
258     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
259   virtual int lookChar()
260     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
261   virtual int getPos() { return bufPos + (bufPtr - buf); }
262   virtual void setPos(Guint pos, int dir = 0);
263   virtual GBool isBinary(GBool last = gTrue) { return last; }
264   virtual Guint getStart() { return start; }
265   virtual void moveStart(int delta);
266
267 private:
268
269   GBool fillBuf();
270
271   FILE *f;
272   Guint start;
273   GBool limited;
274   Guint length;
275   char buf[fileStreamBufSize];
276   char *bufPtr;
277   char *bufEnd;
278   Guint bufPos;
279   int savePos;
280   GBool saved;
281 };
282
283 //------------------------------------------------------------------------
284 // MemStream
285 //------------------------------------------------------------------------
286
287 class MemStream: public BaseStream {
288 public:
289
290   MemStream(char *bufA, Guint lengthA, Object *dictA);
291   virtual ~MemStream();
292   virtual Stream *makeSubStream(Guint start, GBool limited,
293                                 Guint lengthA, Object *dictA);
294   virtual StreamKind getKind() { return strWeird; }
295   virtual void reset();
296   virtual void close();
297   virtual int getChar()
298     { return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; }
299   virtual int lookChar()
300     { return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; }
301   virtual int getPos() { return bufPtr - buf; }
302   virtual void setPos(Guint pos, int dir = 0);
303   virtual GBool isBinary(GBool last = gTrue) { return last; }
304   virtual Guint getStart() { return 0; }
305   virtual void moveStart(int delta);
306 #ifndef NO_DECRYPTION
307   virtual void doDecryption(Guchar *fileKey, int keyLength,
308                             int objNum, int objGen);
309 #endif
310
311 private:
312
313   char *buf;
314   Guint length;
315   GBool needFree;
316   char *bufEnd;
317   char *bufPtr;
318 };
319
320 //------------------------------------------------------------------------
321 // EmbedStream
322 //
323 // This is a special stream type used for embedded streams (inline
324 // images).  It reads directly from the base stream -- after the
325 // EmbedStream is deleted, reads from the base stream will proceed where
326 // the BaseStream left off.  Note that this is very different behavior
327 // that creating a new FileStream (using makeSubStream).
328 //------------------------------------------------------------------------
329
330 class EmbedStream: public BaseStream {
331 public:
332
333   EmbedStream(Stream *strA, Object *dictA);
334   virtual ~EmbedStream();
335   virtual Stream *makeSubStream(Guint start, GBool limited,
336                                 Guint length, Object *dictA);
337   virtual StreamKind getKind() { return str->getKind(); }
338   virtual void reset() {}
339   virtual int getChar() { return str->getChar(); }
340   virtual int lookChar() { return str->lookChar(); }
341   virtual int getPos() { return str->getPos(); }
342   virtual void setPos(Guint pos, int dir = 0);
343   virtual GBool isBinary(GBool last = gTrue) { return last; }
344   virtual Guint getStart();
345   virtual void moveStart(int delta);
346
347 private:
348
349   Stream *str;
350 };
351
352 //------------------------------------------------------------------------
353 // ASCIIHexStream
354 //------------------------------------------------------------------------
355
356 class ASCIIHexStream: public FilterStream {
357 public:
358
359   ASCIIHexStream(Stream *strA);
360   virtual ~ASCIIHexStream();
361   virtual StreamKind getKind() { return strASCIIHex; }
362   virtual void reset();
363   virtual int getChar()
364     { int c = lookChar(); buf = EOF; return c; }
365   virtual int lookChar();
366   virtual GString *getPSFilter(char *indent);
367   virtual GBool isBinary(GBool last = gTrue);
368
369 private:
370
371   int buf;
372   GBool eof;
373 };
374
375 //------------------------------------------------------------------------
376 // ASCII85Stream
377 //------------------------------------------------------------------------
378
379 class ASCII85Stream: public FilterStream {
380 public:
381
382   ASCII85Stream(Stream *strA);
383   virtual ~ASCII85Stream();
384   virtual StreamKind getKind() { return strASCII85; }
385   virtual void reset();
386   virtual int getChar()
387     { int ch = lookChar(); ++index; return ch; }
388   virtual int lookChar();
389   virtual GString *getPSFilter(char *indent);
390   virtual GBool isBinary(GBool last = gTrue);
391
392 private:
393
394   int c[5];
395   int b[4];
396   int index, n;
397   GBool eof;
398 };
399
400 //------------------------------------------------------------------------
401 // LZWStream
402 //------------------------------------------------------------------------
403
404 class LZWStream: public FilterStream {
405 public:
406
407   LZWStream(Stream *strA, int predictor, int columns, int colors,
408             int bits, int earlyA);
409   virtual ~LZWStream();
410   virtual StreamKind getKind() { return strLZW; }
411   virtual void reset();
412   virtual int getChar();
413   virtual int lookChar();
414   virtual int getRawChar();
415   virtual GString *getPSFilter(char *indent);
416   virtual GBool isBinary(GBool last = gTrue);
417
418 private:
419
420   StreamPredictor *pred;        // predictor
421   int early;                    // early parameter
422   FILE *zPipe;                  // uncompress pipe
423   GString *zName;               // .Z file name
424   int inputBuf;                 // input buffer
425   int inputBits;                // number of bits in input buffer
426   int inCodeBits;               // size of input code
427   char buf[256];                // buffer
428   char *bufPtr;                 // next char to read
429   char *bufEnd;                 // end of buffer
430
431   void dumpFile(FILE *f);
432   int getCode();
433   GBool fillBuf();
434 };
435
436 //------------------------------------------------------------------------
437 // RunLengthStream
438 //------------------------------------------------------------------------
439
440 class RunLengthStream: public FilterStream {
441 public:
442
443   RunLengthStream(Stream *strA);
444   virtual ~RunLengthStream();
445   virtual StreamKind getKind() { return strRunLength; }
446   virtual void reset();
447   virtual int getChar()
448     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
449   virtual int lookChar()
450     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
451   virtual GString *getPSFilter(char *indent);
452   virtual GBool isBinary(GBool last = gTrue);
453
454 private:
455
456   char buf[128];                // buffer
457   char *bufPtr;                 // next char to read
458   char *bufEnd;                 // end of buffer
459   GBool eof;
460
461   GBool fillBuf();
462 };
463
464 //------------------------------------------------------------------------
465 // CCITTFaxStream
466 //------------------------------------------------------------------------
467
468 struct CCITTCodeTable;
469
470 class CCITTFaxStream: public FilterStream {
471 public:
472
473   CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA,
474                  GBool byteAlignA, int columnsA, int rowsA,
475                  GBool endOfBlockA, GBool blackA);
476   virtual ~CCITTFaxStream();
477   virtual StreamKind getKind() { return strCCITTFax; }
478   virtual void reset();
479   virtual int getChar()
480     { int c = lookChar(); buf = EOF; return c; }
481   virtual int lookChar();
482   virtual GString *getPSFilter(char *indent);
483   virtual GBool isBinary(GBool last = gTrue);
484
485 private:
486
487   int encoding;                 // 'K' parameter
488   GBool endOfLine;              // 'EndOfLine' parameter
489   GBool byteAlign;              // 'EncodedByteAlign' parameter
490   int columns;                  // 'Columns' parameter
491   int rows;                     // 'Rows' parameter
492   GBool endOfBlock;             // 'EndOfBlock' parameter
493   GBool black;                  // 'BlackIs1' parameter
494   GBool eof;                    // true if at eof
495   GBool nextLine2D;             // true if next line uses 2D encoding
496   int row;                      // current row
497   int inputBuf;                 // input buffer
498   int inputBits;                // number of bits in input buffer
499   short *refLine;               // reference line changing elements
500   int b1;                       // index into refLine
501   short *codingLine;            // coding line changing elements
502   int a0;                       // index into codingLine
503   int outputBits;               // remaining ouput bits
504   int buf;                      // character buffer
505
506   short getTwoDimCode();
507   short getWhiteCode();
508   short getBlackCode();
509   short lookBits(int n);
510   void eatBits(int n) { inputBits -= n; }
511 };
512
513 //------------------------------------------------------------------------
514 // DCTStream
515 //------------------------------------------------------------------------
516
517 // DCT component info
518 struct DCTCompInfo {
519   int id;                       // component ID
520   GBool inScan;                 // is this component in the current scan?
521   int hSample, vSample;         // horiz/vert sampling resolutions
522   int quantTable;               // quantization table number
523   int dcHuffTable, acHuffTable; // Huffman table numbers
524   int prevDC;                   // DC coefficient accumulator
525 };
526
527 // DCT Huffman decoding table
528 struct DCTHuffTable {
529   Guchar firstSym[17];          // first symbol for this bit length
530   Gushort firstCode[17];        // first code for this bit length
531   Gushort numCodes[17];         // number of codes of this bit length
532   Guchar sym[256];              // symbols
533 };
534
535 class DCTStream: public FilterStream {
536 public:
537
538   DCTStream(Stream *strA);
539   virtual ~DCTStream();
540   virtual StreamKind getKind() { return strDCT; }
541   virtual void reset();
542   virtual int getChar();
543   virtual int lookChar();
544   virtual GString *getPSFilter(char *indent);
545   virtual GBool isBinary(GBool last = gTrue);
546   Stream *getRawStream() { return str; }
547
548 private:
549
550   int width, height;            // image size
551   int mcuWidth, mcuHeight;      // size of min coding unit, in data units
552   DCTCompInfo compInfo[4];      // info for each component
553   int numComps;                 // number of components in image
554   int colorXform;               // need YCbCr-to-RGB transform?
555   GBool gotAdobeMarker;         // set if APP14 Adobe marker was present
556   int restartInterval;          // restart interval, in MCUs
557   Guchar quantTables[4][64];    // quantization tables
558   int numQuantTables;           // number of quantization tables
559   DCTHuffTable dcHuffTables[4]; // DC Huffman tables
560   DCTHuffTable acHuffTables[4]; // AC Huffman tables
561   int numDCHuffTables;          // number of DC Huffman tables
562   int numACHuffTables;          // number of AC Huffman tables
563   Guchar *rowBuf[4][32];        // buffer for one MCU
564   int comp, x, y, dy;           // current position within image/MCU
565   int restartCtr;               // MCUs left until restart
566   int restartMarker;            // next restart marker
567   int inputBuf;                 // input buffer for variable length codes
568   int inputBits;                // number of valid bits in input buffer
569
570   void restart();
571   GBool readMCURow();
572   GBool readDataUnit(DCTHuffTable *dcHuffTable, DCTHuffTable *acHuffTable,
573                      Guchar quantTable[64], int *prevDC, Guchar data[64]);
574   int readHuffSym(DCTHuffTable *table);
575   int readAmp(int size);
576   int readBit();
577   GBool readHeader();
578   GBool readFrameInfo();
579   GBool readScanInfo();
580   GBool readQuantTables();
581   GBool readHuffmanTables();
582   GBool readRestartInterval();
583   GBool readAdobeMarker();
584   GBool readTrailer();
585   int readMarker();
586   int read16();
587 };
588
589 //------------------------------------------------------------------------
590 // FlateStream
591 //------------------------------------------------------------------------
592
593 #define flateWindow          32768    // buffer size
594 #define flateMask            (flateWindow-1)
595 #define flateMaxHuffman         15    // max Huffman code length
596 #define flateMaxCodeLenCodes    19    // max # code length codes
597 #define flateMaxLitCodes       288    // max # literal codes
598 #define flateMaxDistCodes       30    // max # distance codes
599
600 // Huffman code table entry
601 struct FlateCode {
602   int len;                      // code length in bits
603   int code;                     // code word
604   int val;                      // value represented by this code
605 };
606
607 // Huffman code table
608 struct FlateHuffmanTab {
609   int start[flateMaxHuffman+2]; // indexes of first code of each length
610   FlateCode *codes;             // codes, sorted by length and code word
611 };
612
613 // Decoding info for length and distance code words
614 struct FlateDecode {
615   int bits;                     // # extra bits
616   int first;                    // first length/distance
617 };
618
619 class FlateStream: public FilterStream {
620 public:
621
622   FlateStream(Stream *strA, int predictor, int columns,
623               int colors, int bits);
624   virtual ~FlateStream();
625   virtual StreamKind getKind() { return strFlate; }
626   virtual void reset();
627   virtual int getChar();
628   virtual int lookChar();
629   virtual int getRawChar();
630   virtual GString *getPSFilter(char *indent);
631   virtual GBool isBinary(GBool last = gTrue);
632
633 private:
634
635   StreamPredictor *pred;        // predictor
636   Guchar buf[flateWindow];      // output data buffer
637   int index;                    // current index into output buffer
638   int remain;                   // number valid bytes in output buffer
639   int codeBuf;                  // input buffer
640   int codeSize;                 // number of bits in input buffer
641   FlateCode                     // literal and distance codes
642     allCodes[flateMaxLitCodes + flateMaxDistCodes];
643   FlateHuffmanTab litCodeTab;   // literal code table
644   FlateHuffmanTab distCodeTab;  // distance code table
645   GBool compressedBlock;        // set if reading a compressed block
646   int blockLen;                 // remaining length of uncompressed block
647   GBool endOfBlock;             // set when end of block is reached
648   GBool eof;                    // set when end of stream is reached
649
650   static int                    // code length code reordering
651     codeLenCodeMap[flateMaxCodeLenCodes];
652   static FlateDecode            // length decoding info
653     lengthDecode[flateMaxLitCodes-257];
654   static FlateDecode            // distance decoding info
655     distDecode[flateMaxDistCodes];
656
657   void readSome();
658   GBool startBlock();
659   void loadFixedCodes();
660   GBool readDynamicCodes();
661   void compHuffmanCodes(FlateHuffmanTab *tab, int n);
662   int getHuffmanCodeWord(FlateHuffmanTab *tab);
663   int getCodeWord(int bits);
664 };
665
666 //------------------------------------------------------------------------
667 // EOFStream
668 //------------------------------------------------------------------------
669
670 class EOFStream: public FilterStream {
671 public:
672
673   EOFStream(Stream *strA);
674   virtual ~EOFStream();
675   virtual StreamKind getKind() { return strWeird; }
676   virtual void reset() {}
677   virtual int getChar() { return EOF; }
678   virtual int lookChar() { return EOF; }
679   virtual GString *getPSFilter(char *indent)  { return NULL; }
680   virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
681 };
682
683 //------------------------------------------------------------------------
684 // FixedLengthEncoder
685 //------------------------------------------------------------------------
686
687 class FixedLengthEncoder: public FilterStream {
688 public:
689
690   FixedLengthEncoder(Stream *strA, int lengthA);
691   ~FixedLengthEncoder();
692   virtual StreamKind getKind() { return strWeird; }
693   virtual void reset();
694   virtual void close();
695   virtual int getChar();
696   virtual int lookChar();
697   virtual GString *getPSFilter(char *indent) { return NULL; }
698   virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
699   virtual GBool isEncoder() { return gTrue; }
700
701 private:
702
703   int length;
704   int count;
705 };
706
707 //------------------------------------------------------------------------
708 // ASCIIHexEncoder
709 //------------------------------------------------------------------------
710
711 class ASCIIHexEncoder: public FilterStream {
712 public:
713
714   ASCIIHexEncoder(Stream *strA);
715   virtual ~ASCIIHexEncoder();
716   virtual StreamKind getKind() { return strWeird; }
717   virtual void reset();
718   virtual void close();
719   virtual int getChar()
720     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
721   virtual int lookChar()
722     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
723   virtual GString *getPSFilter(char *indent) { return NULL; }
724   virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
725   virtual GBool isEncoder() { return gTrue; }
726
727 private:
728
729   char buf[4];
730   char *bufPtr;
731   char *bufEnd;
732   int lineLen;
733   GBool eof;
734
735   GBool fillBuf();
736 };
737
738 //------------------------------------------------------------------------
739 // ASCII85Encoder
740 //------------------------------------------------------------------------
741
742 class ASCII85Encoder: public FilterStream {
743 public:
744
745   ASCII85Encoder(Stream *strA);
746   virtual ~ASCII85Encoder();
747   virtual StreamKind getKind() { return strWeird; }
748   virtual void reset();
749   virtual void close();
750   virtual int getChar()
751     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
752   virtual int lookChar()
753     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
754   virtual GString *getPSFilter(char *indent) { return NULL; }
755   virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
756   virtual GBool isEncoder() { return gTrue; }
757
758 private:
759
760   char buf[8];
761   char *bufPtr;
762   char *bufEnd;
763   int lineLen;
764   GBool eof;
765
766   GBool fillBuf();
767 };
768
769 //------------------------------------------------------------------------
770 // RunLengthEncoder
771 //------------------------------------------------------------------------
772
773 class RunLengthEncoder: public FilterStream {
774 public:
775
776   RunLengthEncoder(Stream *strA);
777   virtual ~RunLengthEncoder();
778   virtual StreamKind getKind() { return strWeird; }
779   virtual void reset();
780   virtual void close();
781   virtual int getChar()
782     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
783   virtual int lookChar()
784     { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
785   virtual GString *getPSFilter(char *indent) { return NULL; }
786   virtual GBool isBinary(GBool last = gTrue) { return gFalse; }
787   virtual GBool isEncoder() { return gTrue; }
788
789 private:
790
791   char buf[131];
792   char *bufPtr;
793   char *bufEnd;
794   char *nextEnd;
795   GBool eof;
796
797   GBool fillBuf();
798 };
799
800 #endif