1 //========================================================================
2 //
3 // Stream.h
4 //
5 // Copyright 1996-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
8 
9 //========================================================================
10 //
11 // Modified under the Poppler project - http://poppler.freedesktop.org
12 //
13 // All changes made under the Poppler project to this file are licensed
14 // under GPL version 2 or later
15 //
16 // Copyright (C) 2005 Jeff Muizelaar <jeff@infidigm.net>
17 // Copyright (C) 2008 Julien Rebetez <julien@fhtagn.net>
18 // Copyright (C) 2008, 2010, 2011, 2016-2021 Albert Astals Cid <aacid@kde.org>
19 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
20 // Copyright (C) 2009 Stefan Thomas <thomas@eload24.com>
21 // Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
22 // Copyright (C) 2011, 2012, 2016, 2020 William Bader <williambader@hotmail.com>
23 // Copyright (C) 2012, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
24 // Copyright (C) 2012, 2013 Fabio D'Urso <fabiodurso@hotmail.it>
25 // Copyright (C) 2013, 2017 Adrian Johnson <ajohnson@redneon.com>
26 // Copyright (C) 2013 Peter Breitenlohner <peb@mppmu.mpg.de>
27 // Copyright (C) 2013, 2018 Adam Reichold <adamreichold@myopera.com>
28 // Copyright (C) 2013 Pino Toscano <pino@kde.org>
29 // Copyright (C) 2019 Volker Krause <vkrause@kde.org>
30 // Copyright (C) 2019 Alexander Volkov <a.volkov@rusbitech.ru>
31 // Copyright (C) 2020, 2021 Oliver Sander <oliver.sander@tu-dresden.de>
32 // Copyright (C) 2020 Philipp Knechtges <philipp-dev@knechtges.com>
33 // Copyright (C) 2021 Hubert Figuiere <hub@figuiere.net>
34 // Copyright (C) 2021 Christian Persch <chpe@src.gnome.org>
35 // Copyright (C) 2021 Georgiy Sgibnev <georgiy@sgibnev.com>. Work sponsored by lab50.net.
36 //
37 // To see a description of the changes please see the Changelog file that
38 // came with your tarball or type make ChangeLog if you are building from git
39 //
40 //========================================================================
41 
42 #ifndef STREAM_H
43 #define STREAM_H
44 
45 #include <atomic>
46 #include <cstdio>
47 
48 #include "poppler-config.h"
49 #include "poppler_private_export.h"
50 #include "Object.h"
51 
52 class GooFile;
53 class BaseStream;
54 class CachedFile;
55 class SplashBitmap;
56 
57 //------------------------------------------------------------------------
58 
59 enum StreamKind
60 {
61     strFile,
62     strCachedFile,
63     strASCIIHex,
64     strASCII85,
65     strLZW,
66     strRunLength,
67     strCCITTFax,
68     strDCT,
69     strFlate,
70     strJBIG2,
71     strJPX,
72     strWeird, // internal-use stream types
73     strCrypt // internal-use to detect decode streams
74 };
75 
76 enum StreamColorSpaceMode
77 {
78     streamCSNone,
79     streamCSDeviceGray,
80     streamCSDeviceRGB,
81     streamCSDeviceCMYK
82 };
83 
84 //------------------------------------------------------------------------
85 
86 // This is in Stream.h instead of Decrypt.h to avoid really annoying
87 // include file dependency loops.
88 enum CryptAlgorithm
89 {
90     cryptRC4,
91     cryptAES,
92     cryptAES256,
93     cryptNone
94 };
95 
96 //------------------------------------------------------------------------
97 
98 typedef struct _ByteRange
99 {
100     unsigned int offset;
101     unsigned int length;
102 } ByteRange;
103 
104 //------------------------------------------------------------------------
105 // Stream (base class)
106 //------------------------------------------------------------------------
107 
108 class POPPLER_PRIVATE_EXPORT Stream
109 {
110 public:
111     // Constructor.
112     Stream();
113 
114     // Destructor.
115     virtual ~Stream();
116 
117     Stream(const Stream &) = delete;
118     Stream &operator=(const Stream &other) = delete;
119 
120     // Get kind of stream.
121     virtual StreamKind getKind() const = 0;
122 
123     // Reset stream to beginning.
124     virtual void reset() = 0;
125 
126     // Close down the stream.
127     virtual void close();
128 
doGetChars(int nChars,unsigned char * buffer)129     inline int doGetChars(int nChars, unsigned char *buffer)
130     {
131         if (hasGetChars()) {
132             return getChars(nChars, buffer);
133         } else {
134             for (int i = 0; i < nChars; ++i) {
135                 const int c = getChar();
136                 if (likely(c != EOF))
137                     buffer[i] = c;
138                 else
139                     return i;
140             }
141             return nChars;
142         }
143     }
144 
fillString(std::string & s)145     inline void fillString(std::string &s)
146     {
147         unsigned char readBuf[4096];
148         int readChars;
149         reset();
150         while ((readChars = doGetChars(4096, readBuf)) != 0) {
151             s.append((const char *)readBuf, readChars);
152         }
153     }
154 
fillGooString(GooString * s)155     inline void fillGooString(GooString *s) { fillString(s->toNonConstStr()); }
156 
157     inline unsigned char *toUnsignedChars(int *length, int initialSize = 4096, int sizeIncrement = 4096)
158     {
159         int readChars;
160         unsigned char *buf = (unsigned char *)gmalloc(initialSize);
161         int size = initialSize;
162         *length = 0;
163         int charsToRead = initialSize;
164         bool continueReading = true;
165         reset();
166         while (continueReading && (readChars = doGetChars(charsToRead, &buf[*length])) != 0) {
167             *length += readChars;
168             if (readChars == charsToRead) {
169                 if (lookChar() != EOF) {
170                     size += sizeIncrement;
171                     charsToRead = sizeIncrement;
172                     buf = (unsigned char *)grealloc(buf, size);
173                 } else {
174                     continueReading = false;
175                 }
176             } else {
177                 continueReading = false;
178             }
179         }
180         return buf;
181     }
182 
183     // Get next char from stream.
184     virtual int getChar() = 0;
185 
186     // Peek at next char in stream.
187     virtual int lookChar() = 0;
188 
189     // Get next char from stream without using the predictor.
190     // This is only used by StreamPredictor.
191     virtual int getRawChar();
192     virtual void getRawChars(int nChars, int *buffer);
193 
194     // Get next char directly from stream source, without filtering it
195     virtual int getUnfilteredChar() = 0;
196 
197     // Resets the stream without reading anything (even not the headers)
198     // WARNING: Reading the stream with something else than getUnfilteredChar
199     // may lead to unexcepted behaviour until you call reset ()
200     virtual void unfilteredReset() = 0;
201 
202     // Get next line from stream.
203     virtual char *getLine(char *buf, int size);
204 
205     // Discard the next <n> bytes from stream.  Returns the number of
206     // bytes discarded, which will be less than <n> only if EOF is
207     // reached.
208     virtual unsigned int discardChars(unsigned int n);
209 
210     // Get current position in file.
211     virtual Goffset getPos() = 0;
212 
213     // Go to a position in the stream.  If <dir> is negative, the
214     // position is from the end of the file; otherwise the position is
215     // from the start of the file.
216     virtual void setPos(Goffset pos, int dir = 0) = 0;
217 
218     // Get PostScript command for the filter(s).
219     virtual GooString *getPSFilter(int psLevel, const char *indent);
220 
221     // Does this stream type potentially contain non-printable chars?
222     virtual bool isBinary(bool last = true) const = 0;
223 
224     // Get the BaseStream of this stream.
225     virtual BaseStream *getBaseStream() = 0;
226 
227     // Get the stream after the last decoder (this may be a BaseStream
228     // or a DecryptStream).
229     virtual Stream *getUndecodedStream() = 0;
230 
231     // Get the dictionary associated with this stream.
232     virtual Dict *getDict() = 0;
233     virtual Object *getDictObject() = 0;
234 
235     // Is this an encoding filter?
isEncoder()236     virtual bool isEncoder() const { return false; }
237 
238     // Get image parameters which are defined by the stream contents.
getImageParams(int *,StreamColorSpaceMode *)239     virtual void getImageParams(int * /*bitsPerComponent*/, StreamColorSpaceMode * /*csMode*/) { }
240 
241     // Return the next stream in the "stack".
getNextStream()242     virtual Stream *getNextStream() const { return nullptr; }
243 
244     // Add filters to this stream according to the parameters in <dict>.
245     // Returns the new stream.
246     Stream *addFilters(Dict *dict, int recursion = 0);
247 
248     // Returns true if this stream includes a crypt filter.
249     bool isEncrypted() const;
250 
251 private:
252     friend class Object; // for incRef/decRef
253 
254     // Reference counting.
incRef()255     int incRef() { return ++ref; }
decRef()256     int decRef() { return --ref; }
257 
hasGetChars()258     virtual bool hasGetChars() { return false; }
259     virtual int getChars(int nChars, unsigned char *buffer);
260 
261     Stream *makeFilter(const char *name, Stream *str, Object *params, int recursion = 0, Dict *dict = nullptr);
262 
263     std::atomic_int ref; // reference count
264 };
265 
266 //------------------------------------------------------------------------
267 // OutStream
268 //
269 // This is the base class for all streams that output to a file
270 //------------------------------------------------------------------------
271 class POPPLER_PRIVATE_EXPORT OutStream
272 {
273 public:
274     // Constructor.
275     OutStream();
276 
277     // Desctructor.
278     virtual ~OutStream();
279 
280     OutStream(const OutStream &) = delete;
281     OutStream &operator=(const OutStream &other) = delete;
282 
283     // Close the stream
284     virtual void close() = 0;
285 
286     // Return position in stream
287     virtual Goffset getPos() = 0;
288 
289     // Put a char in the stream
290     virtual void put(char c) = 0;
291 
292     virtual void printf(const char *format, ...) GCC_PRINTF_FORMAT(2, 3) = 0;
293 };
294 
295 //------------------------------------------------------------------------
296 // FileOutStream
297 //------------------------------------------------------------------------
298 class POPPLER_PRIVATE_EXPORT FileOutStream : public OutStream
299 {
300 public:
301     FileOutStream(FILE *fa, Goffset startA);
302 
303     ~FileOutStream() override;
304 
305     void close() override;
306 
307     Goffset getPos() override;
308 
309     void put(char c) override;
310 
311     void printf(const char *format, ...) override GCC_PRINTF_FORMAT(2, 3);
312 
313 private:
314     FILE *f;
315     Goffset start;
316 };
317 
318 //------------------------------------------------------------------------
319 // BaseStream
320 //
321 // This is the base class for all streams that read directly from a file.
322 //------------------------------------------------------------------------
323 
324 class POPPLER_PRIVATE_EXPORT BaseStream : public Stream
325 {
326 public:
327     // TODO Mirar si puedo hacer que dictA sea un puntero
328     BaseStream(Object &&dictA, Goffset lengthA);
329     ~BaseStream() override;
330     virtual BaseStream *copy() = 0;
331     virtual Stream *makeSubStream(Goffset start, bool limited, Goffset length, Object &&dict) = 0;
332     void setPos(Goffset pos, int dir = 0) override = 0;
333     bool isBinary(bool last = true) const override { return last; }
getBaseStream()334     BaseStream *getBaseStream() override { return this; }
getUndecodedStream()335     Stream *getUndecodedStream() override { return this; }
getDict()336     Dict *getDict() override { return dict.getDict(); }
getDictObject()337     Object *getDictObject() override { return &dict; }
getFileName()338     virtual GooString *getFileName() { return nullptr; }
getLength()339     virtual Goffset getLength() { return length; }
340 
341     // Get/set position of first byte of stream within the file.
342     virtual Goffset getStart() = 0;
343     virtual void moveStart(Goffset delta) = 0;
344 
345 protected:
346     Goffset length;
347     Object dict;
348 };
349 
350 //------------------------------------------------------------------------
351 // BaseInputStream
352 //------------------------------------------------------------------------
353 
354 class POPPLER_PRIVATE_EXPORT BaseSeekInputStream : public BaseStream
355 {
356 public:
357     // This enum is used to tell the seek() method how it must reposition
358     // the stream offset.
359     enum SeekType
360     {
361         SeekSet, // the offset is set to offset bytes
362         SeekCur, // the offset is set to its current location plus offset bytes
363         SeekEnd // the offset is set to the size of the stream plus offset bytes
364     };
365 
366     BaseSeekInputStream(Goffset startA, bool limitedA, Goffset lengthA, Object &&dictA);
367     ~BaseSeekInputStream() override;
getKind()368     StreamKind getKind() const override { return strWeird; }
369     void reset() override;
370     void close() override;
getChar()371     int getChar() override { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
lookChar()372     int lookChar() override { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
getPos()373     Goffset getPos() override { return bufPos + (bufPtr - buf); }
374     void setPos(Goffset pos, int dir = 0) override;
getStart()375     Goffset getStart() override { return start; }
376     void moveStart(Goffset delta) override;
377 
getUnfilteredChar()378     int getUnfilteredChar() override { return getChar(); }
unfilteredReset()379     void unfilteredReset() override { reset(); }
380 
381 protected:
382     Goffset start;
383     bool limited;
384 
385 private:
386     bool fillBuf();
387 
hasGetChars()388     bool hasGetChars() override { return true; }
389     int getChars(int nChars, unsigned char *buffer) override;
390 
391     virtual Goffset currentPos() const = 0;
392     virtual void setCurrentPos(Goffset offset) = 0;
393     virtual Goffset read(char *buf, Goffset size) = 0;
394 
395     static constexpr int seekInputStreamBufSize = 1024;
396     char buf[seekInputStreamBufSize];
397     char *bufPtr;
398     char *bufEnd;
399     Goffset bufPos;
400     Goffset savePos;
401     bool saved;
402 };
403 
404 //------------------------------------------------------------------------
405 // FilterStream
406 //
407 // This is the base class for all streams that filter another stream.
408 //------------------------------------------------------------------------
409 
410 class FilterStream : public Stream
411 {
412 public:
413     explicit FilterStream(Stream *strA);
414     ~FilterStream() override;
415     void close() override;
getPos()416     Goffset getPos() override { return str->getPos(); }
417     void setPos(Goffset pos, int dir = 0) override;
getBaseStream()418     BaseStream *getBaseStream() override { return str->getBaseStream(); }
getUndecodedStream()419     Stream *getUndecodedStream() override { return str->getUndecodedStream(); }
getDict()420     Dict *getDict() override { return str->getDict(); }
getDictObject()421     Object *getDictObject() override { return str->getDictObject(); }
getNextStream()422     Stream *getNextStream() const override { return str; }
423 
getUnfilteredChar()424     int getUnfilteredChar() override { return str->getUnfilteredChar(); }
unfilteredReset()425     void unfilteredReset() override { str->unfilteredReset(); }
426 
427 protected:
428     Stream *str;
429 };
430 
431 //------------------------------------------------------------------------
432 // ImageStream
433 //------------------------------------------------------------------------
434 
435 class POPPLER_PRIVATE_EXPORT ImageStream
436 {
437 public:
438     // Create an image stream object for an image with the specified
439     // parameters.  Note that these are the actual image parameters,
440     // which may be different from the predictor parameters.
441     ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA);
442 
443     ~ImageStream();
444 
445     ImageStream(const ImageStream &) = delete;
446     ImageStream &operator=(const ImageStream &other) = delete;
447 
448     // Reset the stream.
449     void reset();
450 
451     // Close the stream previously reset
452     void close();
453 
454     // Gets the next pixel from the stream.  <pix> should be able to hold
455     // at least nComps elements.  Returns false at end of file.
456     bool getPixel(unsigned char *pix);
457 
458     // Returns a pointer to the next line of pixels.  Returns NULL at
459     // end of file.
460     unsigned char *getLine();
461 
462     // Skip an entire line from the image.
463     void skipLine();
464 
465 private:
466     Stream *str; // base stream
467     int width; // pixels per line
468     int nComps; // components per pixel
469     int nBits; // bits per component
470     int nVals; // components per line
471     int inputLineSize; // input line buffer size
472     unsigned char *inputLine; // input line buffer
473     unsigned char *imgLine; // line buffer
474     int imgIdx; // current index in imgLine
475 };
476 
477 //------------------------------------------------------------------------
478 // StreamPredictor
479 //------------------------------------------------------------------------
480 
481 class StreamPredictor
482 {
483 public:
484     // Create a predictor object.  Note that the parameters are for the
485     // predictor, and may not match the actual image parameters.
486     StreamPredictor(Stream *strA, int predictorA, int widthA, int nCompsA, int nBitsA);
487 
488     ~StreamPredictor();
489 
490     StreamPredictor(const StreamPredictor &) = delete;
491     StreamPredictor &operator=(const StreamPredictor &) = delete;
492 
isOk()493     bool isOk() { return ok; }
494 
495     int lookChar();
496     int getChar();
497     int getChars(int nChars, unsigned char *buffer);
498 
499 private:
500     bool getNextLine();
501 
502     Stream *str; // base stream
503     int predictor; // predictor
504     int width; // pixels per line
505     int nComps; // components per pixel
506     int nBits; // bits per component
507     int nVals; // components per line
508     int pixBytes; // bytes per pixel
509     int rowBytes; // bytes per line
510     unsigned char *predLine; // line buffer
511     int predIdx; // current index in predLine
512     bool ok;
513 };
514 
515 //------------------------------------------------------------------------
516 // FileStream
517 //------------------------------------------------------------------------
518 
519 #define fileStreamBufSize 256
520 
521 class POPPLER_PRIVATE_EXPORT FileStream : public BaseStream
522 {
523 public:
524     FileStream(GooFile *fileA, Goffset startA, bool limitedA, Goffset lengthA, Object &&dictA);
525     ~FileStream() override;
526     BaseStream *copy() override;
527     Stream *makeSubStream(Goffset startA, bool limitedA, Goffset lengthA, Object &&dictA) override;
getKind()528     StreamKind getKind() const override { return strFile; }
529     void reset() override;
530     void close() override;
getChar()531     int getChar() override { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
lookChar()532     int lookChar() override { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
getPos()533     Goffset getPos() override { return bufPos + (bufPtr - buf); }
534     void setPos(Goffset pos, int dir = 0) override;
getStart()535     Goffset getStart() override { return start; }
536     void moveStart(Goffset delta) override;
537 
getUnfilteredChar()538     int getUnfilteredChar() override { return getChar(); }
unfilteredReset()539     void unfilteredReset() override { reset(); }
540 
getNeedsEncryptionOnSave()541     bool getNeedsEncryptionOnSave() const { return needsEncryptionOnSave; }
setNeedsEncryptionOnSave(bool needsEncryptionOnSaveA)542     void setNeedsEncryptionOnSave(bool needsEncryptionOnSaveA) { needsEncryptionOnSave = needsEncryptionOnSaveA; }
543 
544 private:
545     bool fillBuf();
546 
hasGetChars()547     bool hasGetChars() override { return true; }
getChars(int nChars,unsigned char * buffer)548     int getChars(int nChars, unsigned char *buffer) override
549     {
550         int n, m;
551 
552         n = 0;
553         while (n < nChars) {
554             if (bufPtr >= bufEnd) {
555                 if (!fillBuf()) {
556                     break;
557                 }
558             }
559             m = (int)(bufEnd - bufPtr);
560             if (m > nChars - n) {
561                 m = nChars - n;
562             }
563             memcpy(buffer + n, bufPtr, m);
564             bufPtr += m;
565             n += m;
566         }
567         return n;
568     }
569 
570 private:
571     GooFile *file;
572     Goffset offset;
573     Goffset start;
574     bool limited;
575     char buf[fileStreamBufSize];
576     char *bufPtr;
577     char *bufEnd;
578     Goffset bufPos;
579     Goffset savePos;
580     bool saved;
581     bool needsEncryptionOnSave; // Needed for FileStreams that point to "external" files
582                                 // and thus when saving we can't do a raw copy
583 };
584 
585 //------------------------------------------------------------------------
586 // CachedFileStream
587 //------------------------------------------------------------------------
588 
589 #define cachedStreamBufSize 1024
590 
591 class POPPLER_PRIVATE_EXPORT CachedFileStream : public BaseStream
592 {
593 public:
594     CachedFileStream(CachedFile *ccA, Goffset startA, bool limitedA, Goffset lengthA, Object &&dictA);
595     ~CachedFileStream() override;
596     BaseStream *copy() override;
597     Stream *makeSubStream(Goffset startA, bool limitedA, Goffset lengthA, Object &&dictA) override;
getKind()598     StreamKind getKind() const override { return strCachedFile; }
599     void reset() override;
600     void close() override;
getChar()601     int getChar() override { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
lookChar()602     int lookChar() override { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
getPos()603     Goffset getPos() override { return bufPos + (bufPtr - buf); }
604     void setPos(Goffset pos, int dir = 0) override;
getStart()605     Goffset getStart() override { return start; }
606     void moveStart(Goffset delta) override;
607 
getUnfilteredChar()608     int getUnfilteredChar() override { return getChar(); }
unfilteredReset()609     void unfilteredReset() override { reset(); }
610 
611 private:
612     bool fillBuf();
613 
614     CachedFile *cc;
615     Goffset start;
616     bool limited;
617     char buf[cachedStreamBufSize];
618     char *bufPtr;
619     char *bufEnd;
620     unsigned int bufPos;
621     int savePos;
622     bool saved;
623 };
624 
625 //------------------------------------------------------------------------
626 // MemStream
627 //------------------------------------------------------------------------
628 
629 template<typename T>
630 class BaseMemStream : public BaseStream
631 {
632 public:
BaseMemStream(T * bufA,Goffset startA,Goffset lengthA,Object && dictA)633     BaseMemStream(T *bufA, Goffset startA, Goffset lengthA, Object &&dictA) : BaseStream(std::move(dictA), lengthA)
634     {
635         buf = bufA;
636         start = startA;
637         length = lengthA;
638         bufEnd = buf + start + length;
639         bufPtr = buf + start;
640     }
641 
copy()642     BaseStream *copy() override { return new BaseMemStream(buf, start, length, dict.copy()); }
643 
makeSubStream(Goffset startA,bool limited,Goffset lengthA,Object && dictA)644     Stream *makeSubStream(Goffset startA, bool limited, Goffset lengthA, Object &&dictA) override
645     {
646         Goffset newLength;
647 
648         if (!limited || startA + lengthA > start + length) {
649             newLength = start + length - startA;
650         } else {
651             newLength = lengthA;
652         }
653         return new BaseMemStream(buf, startA, newLength, std::move(dictA));
654     }
655 
getKind()656     StreamKind getKind() const override { return strWeird; }
657 
reset()658     void reset() override { bufPtr = buf + start; }
659 
close()660     void close() override { }
661 
getChar()662     int getChar() override { return (bufPtr < bufEnd) ? (*bufPtr++ & 0xff) : EOF; }
663 
lookChar()664     int lookChar() override { return (bufPtr < bufEnd) ? (*bufPtr & 0xff) : EOF; }
665 
getPos()666     Goffset getPos() override { return (int)(bufPtr - buf); }
667 
668     void setPos(Goffset pos, int dir = 0) override
669     {
670         unsigned int i;
671 
672         if (dir >= 0) {
673             i = pos;
674         } else {
675             i = start + length - pos;
676         }
677         if (i < start) {
678             i = start;
679         } else if (i > start + length) {
680             i = start + length;
681         }
682         bufPtr = buf + i;
683     }
684 
getStart()685     Goffset getStart() override { return start; }
686 
moveStart(Goffset delta)687     void moveStart(Goffset delta) override
688     {
689         start += delta;
690         length -= delta;
691         bufPtr = buf + start;
692     }
693 
getUnfilteredChar()694     int getUnfilteredChar() override { return getChar(); }
695 
unfilteredReset()696     void unfilteredReset() override { reset(); }
697 
698 protected:
699     T *buf;
700 
701 private:
hasGetChars()702     bool hasGetChars() override { return true; }
703 
getChars(int nChars,unsigned char * buffer)704     int getChars(int nChars, unsigned char *buffer) override
705     {
706         int n;
707 
708         if (unlikely(nChars <= 0)) {
709             return 0;
710         }
711         if (unlikely(bufPtr >= bufEnd)) {
712             return 0;
713         }
714         if (bufEnd - bufPtr < nChars) {
715             n = (int)(bufEnd - bufPtr);
716         } else {
717             n = nChars;
718         }
719         memcpy(buffer, bufPtr, n);
720         bufPtr += n;
721         return n;
722     }
723 
724     Goffset start;
725     T *bufEnd;
726     T *bufPtr;
727 };
728 
729 class POPPLER_PRIVATE_EXPORT MemStream : public BaseMemStream<const char>
730 {
731 public:
MemStream(const char * bufA,Goffset startA,Goffset lengthA,Object && dictA)732     MemStream(const char *bufA, Goffset startA, Goffset lengthA, Object &&dictA) : BaseMemStream(bufA, startA, lengthA, std::move(dictA)) { }
733     ~MemStream() override;
734 };
735 
736 class AutoFreeMemStream : public BaseMemStream<char>
737 {
738     bool filterRemovalForbidden = false;
739 
740 public:
741     // AutoFreeMemStream takes ownership over the buffer.
742     // The buffer should be created using gmalloc().
AutoFreeMemStream(char * bufA,Goffset startA,Goffset lengthA,Object && dictA)743     AutoFreeMemStream(char *bufA, Goffset startA, Goffset lengthA, Object &&dictA) : BaseMemStream(bufA, startA, lengthA, std::move(dictA)) { }
744     ~AutoFreeMemStream() override;
745 
746     // A hack to deal with the strange behaviour of PDFDoc::writeObject().
747     bool isFilterRemovalForbidden() const;
748     void setFilterRemovalForbidden(bool forbidden);
749 };
750 
751 //------------------------------------------------------------------------
752 // EmbedStream
753 //
754 // This is a special stream type used for embedded streams (inline
755 // images).  It reads directly from the base stream -- after the
756 // EmbedStream is deleted, reads from the base stream will proceed where
757 // the BaseStream left off.  Note that this is very different behavior
758 // that creating a new FileStream (using makeSubStream).
759 //------------------------------------------------------------------------
760 
761 class POPPLER_PRIVATE_EXPORT EmbedStream : public BaseStream
762 {
763 public:
764     EmbedStream(Stream *strA, Object &&dictA, bool limitedA, Goffset lengthA, bool reusableA = false);
765     ~EmbedStream() override;
766     BaseStream *copy() override;
767     Stream *makeSubStream(Goffset start, bool limitedA, Goffset lengthA, Object &&dictA) override;
getKind()768     StreamKind getKind() const override { return str->getKind(); }
769     void reset() override;
770     int getChar() override;
771     int lookChar() override;
772     Goffset getPos() override;
773     void setPos(Goffset pos, int dir = 0) override;
774     Goffset getStart() override;
775     void moveStart(Goffset delta) override;
776 
getUnfilteredChar()777     int getUnfilteredChar() override { return str->getUnfilteredChar(); }
unfilteredReset()778     void unfilteredReset() override { str->unfilteredReset(); }
779 
780     void rewind();
781     void restore();
782 
783 private:
hasGetChars()784     bool hasGetChars() override { return true; }
785     int getChars(int nChars, unsigned char *buffer) override;
786 
787     Stream *str;
788     bool limited;
789     bool reusable;
790     bool record;
791     bool replay;
792     unsigned char *bufData;
793     long bufMax;
794     long bufLen;
795     long bufPos;
796     Goffset start;
797 };
798 
799 //------------------------------------------------------------------------
800 // ASCIIHexStream
801 //------------------------------------------------------------------------
802 
803 class ASCIIHexStream : public FilterStream
804 {
805 public:
806     explicit ASCIIHexStream(Stream *strA);
807     ~ASCIIHexStream() override;
getKind()808     StreamKind getKind() const override { return strASCIIHex; }
809     void reset() override;
getChar()810     int getChar() override
811     {
812         int c = lookChar();
813         buf = EOF;
814         return c;
815     }
816     int lookChar() override;
817     GooString *getPSFilter(int psLevel, const char *indent) override;
818     bool isBinary(bool last = true) const override;
819 
820 private:
821     int buf;
822     bool eof;
823 };
824 
825 //------------------------------------------------------------------------
826 // ASCII85Stream
827 //------------------------------------------------------------------------
828 
829 class ASCII85Stream : public FilterStream
830 {
831 public:
832     explicit ASCII85Stream(Stream *strA);
833     ~ASCII85Stream() override;
getKind()834     StreamKind getKind() const override { return strASCII85; }
835     void reset() override;
getChar()836     int getChar() override
837     {
838         int ch = lookChar();
839         ++index;
840         return ch;
841     }
842     int lookChar() override;
843     GooString *getPSFilter(int psLevel, const char *indent) override;
844     bool isBinary(bool last = true) const override;
845 
846 private:
847     int c[5];
848     int b[4];
849     int index, n;
850     bool eof;
851 };
852 
853 //------------------------------------------------------------------------
854 // LZWStream
855 //------------------------------------------------------------------------
856 
857 class LZWStream : public FilterStream
858 {
859 public:
860     LZWStream(Stream *strA, int predictor, int columns, int colors, int bits, int earlyA);
861     ~LZWStream() override;
getKind()862     StreamKind getKind() const override { return strLZW; }
863     void reset() override;
864     int getChar() override;
865     int lookChar() override;
866     int getRawChar() override;
867     void getRawChars(int nChars, int *buffer) override;
868     GooString *getPSFilter(int psLevel, const char *indent) override;
869     bool isBinary(bool last = true) const override;
870 
871 private:
hasGetChars()872     bool hasGetChars() override { return true; }
873     int getChars(int nChars, unsigned char *buffer) override;
874 
doGetRawChar()875     inline int doGetRawChar()
876     {
877         if (eof) {
878             return EOF;
879         }
880         if (seqIndex >= seqLength) {
881             if (!processNextCode()) {
882                 return EOF;
883             }
884         }
885         return seqBuf[seqIndex++];
886     }
887 
888     StreamPredictor *pred; // predictor
889     int early; // early parameter
890     bool eof; // true if at eof
891     unsigned int inputBuf; // input buffer
892     int inputBits; // number of bits in input buffer
893     struct
894     { // decoding table
895         int length;
896         int head;
897         unsigned char tail;
898     } table[4097];
899     int nextCode; // next code to be used
900     int nextBits; // number of bits in next code word
901     int prevCode; // previous code used in stream
902     int newChar; // next char to be added to table
903     unsigned char seqBuf[4097]; // buffer for current sequence
904     int seqLength; // length of current sequence
905     int seqIndex; // index into current sequence
906     bool first; // first code after a table clear
907 
908     bool processNextCode();
909     void clearTable();
910     int getCode();
911 };
912 
913 //------------------------------------------------------------------------
914 // RunLengthStream
915 //------------------------------------------------------------------------
916 
917 class RunLengthStream : public FilterStream
918 {
919 public:
920     explicit RunLengthStream(Stream *strA);
921     ~RunLengthStream() override;
getKind()922     StreamKind getKind() const override { return strRunLength; }
923     void reset() override;
getChar()924     int getChar() override { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
lookChar()925     int lookChar() override { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
926     GooString *getPSFilter(int psLevel, const char *indent) override;
927     bool isBinary(bool last = true) const override;
928 
929 private:
hasGetChars()930     bool hasGetChars() override { return true; }
931     int getChars(int nChars, unsigned char *buffer) override;
932 
933     char buf[128]; // buffer
934     char *bufPtr; // next char to read
935     char *bufEnd; // end of buffer
936     bool eof;
937 
938     bool fillBuf();
939 };
940 
941 //------------------------------------------------------------------------
942 // CCITTFaxStream
943 //------------------------------------------------------------------------
944 
945 struct CCITTCodeTable;
946 
947 class CCITTFaxStream : public FilterStream
948 {
949 public:
950     CCITTFaxStream(Stream *strA, int encodingA, bool endOfLineA, bool byteAlignA, int columnsA, int rowsA, bool endOfBlockA, bool blackA, int damagedRowsBeforeErrorA);
951     ~CCITTFaxStream() override;
getKind()952     StreamKind getKind() const override { return strCCITTFax; }
953     void reset() override;
getChar()954     int getChar() override
955     {
956         int c = lookChar();
957         buf = EOF;
958         return c;
959     }
960     int lookChar() override;
961     GooString *getPSFilter(int psLevel, const char *indent) override;
962     bool isBinary(bool last = true) const override;
963 
964     void unfilteredReset() override;
965 
getEncoding()966     int getEncoding() { return encoding; }
getEndOfLine()967     bool getEndOfLine() { return endOfLine; }
getEncodedByteAlign()968     bool getEncodedByteAlign() { return byteAlign; }
getEndOfBlock()969     bool getEndOfBlock() { return endOfBlock; }
getColumns()970     int getColumns() { return columns; }
getBlackIs1()971     bool getBlackIs1() { return black; }
getDamagedRowsBeforeError()972     int getDamagedRowsBeforeError() { return damagedRowsBeforeError; }
973 
974 private:
975     void ccittReset(bool unfiltered);
976     int encoding; // 'K' parameter
977     bool endOfLine; // 'EndOfLine' parameter
978     bool byteAlign; // 'EncodedByteAlign' parameter
979     int columns; // 'Columns' parameter
980     int rows; // 'Rows' parameter
981     bool endOfBlock; // 'EndOfBlock' parameter
982     bool black; // 'BlackIs1' parameter
983     int damagedRowsBeforeError; // 'DamagedRowsBeforeError' parameter
984     bool eof; // true if at eof
985     bool nextLine2D; // true if next line uses 2D encoding
986     int row; // current row
987     unsigned int inputBuf; // input buffer
988     int inputBits; // number of bits in input buffer
989     int *codingLine; // coding line changing elements
990     int *refLine; // reference line changing elements
991     int a0i; // index into codingLine
992     bool err; // error on current line
993     int outputBits; // remaining ouput bits
994     int buf; // character buffer
995 
996     void addPixels(int a1, int blackPixels);
997     void addPixelsNeg(int a1, int blackPixels);
998     short getTwoDimCode();
999     short getWhiteCode();
1000     short getBlackCode();
1001     short lookBits(int n);
eatBits(int n)1002     void eatBits(int n)
1003     {
1004         if ((inputBits -= n) < 0)
1005             inputBits = 0;
1006     }
1007 };
1008 
1009 #ifndef ENABLE_LIBJPEG
1010 //------------------------------------------------------------------------
1011 // DCTStream
1012 //------------------------------------------------------------------------
1013 
1014 // DCT component info
1015 struct DCTCompInfo
1016 {
1017     int id; // component ID
1018     int hSample, vSample; // horiz/vert sampling resolutions
1019     int quantTable; // quantization table number
1020     int prevDC; // DC coefficient accumulator
1021 };
1022 
1023 struct DCTScanInfo
1024 {
1025     bool comp[4]; // comp[i] is set if component i is
1026                   //   included in this scan
1027     int numComps; // number of components in the scan
1028     int dcHuffTable[4]; // DC Huffman table numbers
1029     int acHuffTable[4]; // AC Huffman table numbers
1030     int firstCoeff, lastCoeff; // first and last DCT coefficient
1031     int ah, al; // successive approximation parameters
1032 };
1033 
1034 // DCT Huffman decoding table
1035 struct DCTHuffTable
1036 {
1037     unsigned char firstSym[17]; // first symbol for this bit length
1038     unsigned short firstCode[17]; // first code for this bit length
1039     unsigned short numCodes[17]; // number of codes of this bit length
1040     unsigned char sym[256]; // symbols
1041 };
1042 
1043 class DCTStream : public FilterStream
1044 {
1045 public:
1046     DCTStream(Stream *strA, int colorXformA, Dict *dict, int recursion);
1047     ~DCTStream() override;
getKind()1048     StreamKind getKind() const override { return strDCT; }
1049     void reset() override;
1050     void close() override;
1051     int getChar() override;
1052     int lookChar() override;
1053     GooString *getPSFilter(int psLevel, const char *indent) override;
1054     bool isBinary(bool last = true) const override;
1055 
1056     void unfilteredReset() override;
1057 
1058 private:
1059     void dctReset(bool unfiltered);
1060     bool progressive; // set if in progressive mode
1061     bool interleaved; // set if in interleaved mode
1062     int width, height; // image size
1063     int mcuWidth, mcuHeight; // size of min coding unit, in data units
1064     int bufWidth, bufHeight; // frameBuf size
1065     DCTCompInfo compInfo[4]; // info for each component
1066     DCTScanInfo scanInfo; // info for the current scan
1067     int numComps; // number of components in image
1068     int colorXform; // color transform: -1 = unspecified
1069                     //                   0 = none
1070                     //                   1 = YUV/YUVK -> RGB/CMYK
1071     bool gotJFIFMarker; // set if APP0 JFIF marker was present
1072     bool gotAdobeMarker; // set if APP14 Adobe marker was present
1073     int restartInterval; // restart interval, in MCUs
1074     unsigned short quantTables[4][64]; // quantization tables
1075     int numQuantTables; // number of quantization tables
1076     DCTHuffTable dcHuffTables[4]; // DC Huffman tables
1077     DCTHuffTable acHuffTables[4]; // AC Huffman tables
1078     int numDCHuffTables; // number of DC Huffman tables
1079     int numACHuffTables; // number of AC Huffman tables
1080     unsigned char *rowBuf[4][32]; // buffer for one MCU (non-progressive mode)
1081     int *frameBuf[4]; // buffer for frame (progressive mode)
1082     int comp, x, y, dy; // current position within image/MCU
1083     int restartCtr; // MCUs left until restart
1084     int restartMarker; // next restart marker
1085     int eobRun; // number of EOBs left in the current run
1086     int inputBuf; // input buffer for variable length codes
1087     int inputBits; // number of valid bits in input buffer
1088 
1089     void restart();
1090     bool readMCURow();
1091     void readScan();
1092     bool readDataUnit(DCTHuffTable *dcHuffTable, DCTHuffTable *acHuffTable, int *prevDC, int data[64]);
1093     bool readProgressiveDataUnit(DCTHuffTable *dcHuffTable, DCTHuffTable *acHuffTable, int *prevDC, int data[64]);
1094     void decodeImage();
1095     void transformDataUnit(unsigned short *quantTable, int dataIn[64], unsigned char dataOut[64]);
1096     int readHuffSym(DCTHuffTable *table);
1097     int readAmp(int size);
1098     int readBit();
1099     bool readHeader();
1100     bool readBaselineSOF();
1101     bool readProgressiveSOF();
1102     bool readScanInfo();
1103     bool readQuantTables();
1104     bool readHuffmanTables();
1105     bool readRestartInterval();
1106     bool readJFIFMarker();
1107     bool readAdobeMarker();
1108     bool readTrailer();
1109     int readMarker();
1110     int read16();
1111 };
1112 
1113 #endif
1114 
1115 #ifndef ENABLE_ZLIB_UNCOMPRESS
1116 //------------------------------------------------------------------------
1117 // FlateStream
1118 //------------------------------------------------------------------------
1119 
1120 #    define flateWindow 32768 // buffer size
1121 #    define flateMask (flateWindow - 1)
1122 #    define flateMaxHuffman 15 // max Huffman code length
1123 #    define flateMaxCodeLenCodes 19 // max # code length codes
1124 #    define flateMaxLitCodes 288 // max # literal codes
1125 #    define flateMaxDistCodes 30 // max # distance codes
1126 
1127 // Huffman code table entry
1128 struct FlateCode
1129 {
1130     unsigned short len; // code length, in bits
1131     unsigned short val; // value represented by this code
1132 };
1133 
1134 struct FlateHuffmanTab
1135 {
1136     const FlateCode *codes;
1137     int maxLen;
1138 };
1139 
1140 // Decoding info for length and distance code words
1141 struct FlateDecode
1142 {
1143     int bits; // # extra bits
1144     int first; // first length/distance
1145 };
1146 
1147 class FlateStream : public FilterStream
1148 {
1149 public:
1150     FlateStream(Stream *strA, int predictor, int columns, int colors, int bits);
1151     ~FlateStream() override;
getKind()1152     StreamKind getKind() const override { return strFlate; }
1153     void reset() override;
1154     int getChar() override;
1155     int lookChar() override;
1156     int getRawChar() override;
1157     void getRawChars(int nChars, int *buffer) override;
1158     GooString *getPSFilter(int psLevel, const char *indent) override;
1159     bool isBinary(bool last = true) const override;
1160     void unfilteredReset() override;
1161 
1162 private:
1163     void flateReset(bool unfiltered);
doGetRawChar()1164     inline int doGetRawChar()
1165     {
1166         int c;
1167 
1168         while (remain == 0) {
1169             if (endOfBlock && eof)
1170                 return EOF;
1171             readSome();
1172         }
1173         c = buf[index];
1174         index = (index + 1) & flateMask;
1175         --remain;
1176         return c;
1177     }
1178 
hasGetChars()1179     bool hasGetChars() override { return true; }
1180     int getChars(int nChars, unsigned char *buffer) override;
1181 
1182     StreamPredictor *pred; // predictor
1183     unsigned char buf[flateWindow]; // output data buffer
1184     int index; // current index into output buffer
1185     int remain; // number valid bytes in output buffer
1186     int codeBuf; // input buffer
1187     int codeSize; // number of bits in input buffer
1188     int // literal and distance code lengths
1189             codeLengths[flateMaxLitCodes + flateMaxDistCodes];
1190     FlateHuffmanTab litCodeTab; // literal code table
1191     FlateHuffmanTab distCodeTab; // distance code table
1192     bool compressedBlock; // set if reading a compressed block
1193     int blockLen; // remaining length of uncompressed block
1194     bool endOfBlock; // set when end of block is reached
1195     bool eof; // set when end of stream is reached
1196 
1197     static const int // code length code reordering
1198             codeLenCodeMap[flateMaxCodeLenCodes];
1199     static const FlateDecode // length decoding info
1200             lengthDecode[flateMaxLitCodes - 257];
1201     static const FlateDecode // distance decoding info
1202             distDecode[flateMaxDistCodes];
1203     static FlateHuffmanTab // fixed literal code table
1204             fixedLitCodeTab;
1205     static FlateHuffmanTab // fixed distance code table
1206             fixedDistCodeTab;
1207 
1208     void readSome();
1209     bool startBlock();
1210     void loadFixedCodes();
1211     bool readDynamicCodes();
1212     FlateCode *compHuffmanCodes(const int *lengths, int n, int *maxLen);
1213     int getHuffmanCodeWord(FlateHuffmanTab *tab);
1214     int getCodeWord(int bits);
1215 };
1216 #endif
1217 
1218 //------------------------------------------------------------------------
1219 // EOFStream
1220 //------------------------------------------------------------------------
1221 
1222 class EOFStream : public FilterStream
1223 {
1224 public:
1225     explicit EOFStream(Stream *strA);
1226     ~EOFStream() override;
getKind()1227     StreamKind getKind() const override { return strWeird; }
reset()1228     void reset() override { }
getChar()1229     int getChar() override { return EOF; }
lookChar()1230     int lookChar() override { return EOF; }
getPSFilter(int,const char *)1231     GooString *getPSFilter(int /*psLevel*/, const char * /*indent*/) override { return nullptr; }
isBinary(bool)1232     bool isBinary(bool /*last = true*/) const override { return false; }
1233 };
1234 
1235 //------------------------------------------------------------------------
1236 // BufStream
1237 //------------------------------------------------------------------------
1238 
1239 class BufStream : public FilterStream
1240 {
1241 public:
1242     BufStream(Stream *strA, int bufSizeA);
1243     ~BufStream() override;
getKind()1244     StreamKind getKind() const override { return strWeird; }
1245     void reset() override;
1246     int getChar() override;
1247     int lookChar() override;
getPSFilter(int psLevel,const char * indent)1248     GooString *getPSFilter(int psLevel, const char *indent) override { return nullptr; }
1249     bool isBinary(bool last = true) const override;
1250 
1251     int lookChar(int idx);
1252 
1253 private:
1254     int *buf;
1255     int bufSize;
1256 };
1257 
1258 //------------------------------------------------------------------------
1259 // FixedLengthEncoder
1260 //------------------------------------------------------------------------
1261 
1262 class FixedLengthEncoder : public FilterStream
1263 {
1264 public:
1265     FixedLengthEncoder(Stream *strA, int lengthA);
1266     ~FixedLengthEncoder() override;
getKind()1267     StreamKind getKind() const override { return strWeird; }
1268     void reset() override;
1269     int getChar() override;
1270     int lookChar() override;
getPSFilter(int,const char *)1271     GooString *getPSFilter(int /*psLevel*/, const char * /*indent*/) override { return nullptr; }
1272     bool isBinary(bool /*last = true*/) const override;
isEncoder()1273     bool isEncoder() const override { return true; }
1274 
1275 private:
1276     int length;
1277     int count;
1278 };
1279 
1280 //------------------------------------------------------------------------
1281 // ASCIIHexEncoder
1282 //------------------------------------------------------------------------
1283 
1284 class ASCIIHexEncoder : public FilterStream
1285 {
1286 public:
1287     explicit ASCIIHexEncoder(Stream *strA);
1288     ~ASCIIHexEncoder() override;
getKind()1289     StreamKind getKind() const override { return strWeird; }
1290     void reset() override;
getChar()1291     int getChar() override { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
lookChar()1292     int lookChar() override { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
getPSFilter(int,const char *)1293     GooString *getPSFilter(int /*psLevel*/, const char * /*indent*/) override { return nullptr; }
isBinary(bool)1294     bool isBinary(bool /*last = true*/) const override { return false; }
isEncoder()1295     bool isEncoder() const override { return true; }
1296 
1297 private:
1298     char buf[4];
1299     char *bufPtr;
1300     char *bufEnd;
1301     int lineLen;
1302     bool eof;
1303 
1304     bool fillBuf();
1305 };
1306 
1307 //------------------------------------------------------------------------
1308 // ASCII85Encoder
1309 //------------------------------------------------------------------------
1310 
1311 class ASCII85Encoder : public FilterStream
1312 {
1313 public:
1314     explicit ASCII85Encoder(Stream *strA);
1315     ~ASCII85Encoder() override;
getKind()1316     StreamKind getKind() const override { return strWeird; }
1317     void reset() override;
getChar()1318     int getChar() override { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
lookChar()1319     int lookChar() override { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
getPSFilter(int,const char *)1320     GooString *getPSFilter(int /*psLevel*/, const char * /*indent*/) override { return nullptr; }
isBinary(bool)1321     bool isBinary(bool /*last = true*/) const override { return false; }
isEncoder()1322     bool isEncoder() const override { return true; }
1323 
1324 private:
1325     char buf[8];
1326     char *bufPtr;
1327     char *bufEnd;
1328     int lineLen;
1329     bool eof;
1330 
1331     bool fillBuf();
1332 };
1333 
1334 //------------------------------------------------------------------------
1335 // RunLengthEncoder
1336 //------------------------------------------------------------------------
1337 
1338 class RunLengthEncoder : public FilterStream
1339 {
1340 public:
1341     explicit RunLengthEncoder(Stream *strA);
1342     ~RunLengthEncoder() override;
getKind()1343     StreamKind getKind() const override { return strWeird; }
1344     void reset() override;
getChar()1345     int getChar() override { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
lookChar()1346     int lookChar() override { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
getPSFilter(int,const char *)1347     GooString *getPSFilter(int /*psLevel*/, const char * /*indent*/) override { return nullptr; }
isBinary(bool)1348     bool isBinary(bool /*last = true*/) const override { return true; }
isEncoder()1349     bool isEncoder() const override { return true; }
1350 
1351 private:
1352     char buf[131];
1353     char *bufPtr;
1354     char *bufEnd;
1355     char *nextEnd;
1356     bool eof;
1357 
1358     bool fillBuf();
1359 };
1360 
1361 //------------------------------------------------------------------------
1362 // LZWEncoder
1363 //------------------------------------------------------------------------
1364 
1365 struct LZWEncoderNode
1366 {
1367     int byte;
1368     LZWEncoderNode *next; // next sibling
1369     LZWEncoderNode *children; // first child
1370 };
1371 
1372 class LZWEncoder : public FilterStream
1373 {
1374 public:
1375     explicit LZWEncoder(Stream *strA);
1376     ~LZWEncoder() override;
getKind()1377     StreamKind getKind() const override { return strWeird; }
1378     void reset() override;
1379     int getChar() override;
1380     int lookChar() override;
getPSFilter(int psLevel,const char * indent)1381     GooString *getPSFilter(int psLevel, const char *indent) override { return nullptr; }
1382     bool isBinary(bool last = true) const override { return true; }
isEncoder()1383     bool isEncoder() const override { return true; }
1384 
1385 private:
1386     LZWEncoderNode table[4096];
1387     int nextSeq;
1388     int codeLen;
1389     unsigned char inBuf[4096];
1390     int inBufLen;
1391     int outBuf;
1392     int outBufLen;
1393     bool needEOD;
1394 
1395     void fillBuf();
1396 };
1397 
1398 //------------------------------------------------------------------------
1399 // CMYKGrayEncoder
1400 //------------------------------------------------------------------------
1401 
1402 class CMYKGrayEncoder : public FilterStream
1403 {
1404 public:
1405     explicit CMYKGrayEncoder(Stream *strA);
1406     ~CMYKGrayEncoder() override;
getKind()1407     StreamKind getKind() const override { return strWeird; }
1408     void reset() override;
getChar()1409     int getChar() override { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
lookChar()1410     int lookChar() override { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
getPSFilter(int,const char *)1411     GooString *getPSFilter(int /*psLevel*/, const char * /*indent*/) override { return nullptr; }
isBinary(bool)1412     bool isBinary(bool /*last = true*/) const override { return false; }
isEncoder()1413     bool isEncoder() const override { return true; }
1414 
1415 private:
1416     char buf[2];
1417     char *bufPtr;
1418     char *bufEnd;
1419     bool eof;
1420 
1421     bool fillBuf();
1422 };
1423 
1424 //------------------------------------------------------------------------
1425 // RGBGrayEncoder
1426 //------------------------------------------------------------------------
1427 
1428 class RGBGrayEncoder : public FilterStream
1429 {
1430 public:
1431     explicit RGBGrayEncoder(Stream *strA);
1432     ~RGBGrayEncoder() override;
getKind()1433     StreamKind getKind() const override { return strWeird; }
1434     void reset() override;
getChar()1435     int getChar() override { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
lookChar()1436     int lookChar() override { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
getPSFilter(int,const char *)1437     GooString *getPSFilter(int /*psLevel*/, const char * /*indent*/) override { return nullptr; }
isBinary(bool)1438     bool isBinary(bool /*last = true*/) const override { return false; }
isEncoder()1439     bool isEncoder() const override { return true; }
1440 
1441 private:
1442     char buf[2];
1443     char *bufPtr;
1444     char *bufEnd;
1445     bool eof;
1446 
1447     bool fillBuf();
1448 };
1449 
1450 //------------------------------------------------------------------------
1451 // SplashBitmapCMYKEncoder
1452 //
1453 // This stream helps to condense SplashBitmaps (mostly of DeviceN8 type) into
1454 // pure CMYK colors. In particular for a DeviceN8 bitmap it redacts the spot colorants.
1455 //------------------------------------------------------------------------
1456 
1457 class SplashBitmapCMYKEncoder : public Stream
1458 {
1459 public:
1460     explicit SplashBitmapCMYKEncoder(SplashBitmap *bitmapA);
1461     ~SplashBitmapCMYKEncoder() override;
getKind()1462     StreamKind getKind() const override { return strWeird; }
1463     void reset() override;
1464     int getChar() override;
1465     int lookChar() override;
getPSFilter(int,const char *)1466     GooString *getPSFilter(int /*psLevel*/, const char * /*indent*/) override { return nullptr; }
isBinary(bool)1467     bool isBinary(bool /*last = true*/) const override { return true; }
1468 
1469     // Although we are an encoder, we return false here, since we do not want do be auto-deleted by
1470     // successive streams.
isEncoder()1471     bool isEncoder() const override { return false; }
1472 
getUnfilteredChar()1473     int getUnfilteredChar() override { return getChar(); }
unfilteredReset()1474     void unfilteredReset() override { reset(); }
1475 
getBaseStream()1476     BaseStream *getBaseStream() override { return nullptr; }
getUndecodedStream()1477     Stream *getUndecodedStream() override { return this; }
1478 
getDict()1479     Dict *getDict() override { return nullptr; }
getDictObject()1480     Object *getDictObject() override { return nullptr; }
1481 
1482     Goffset getPos() override;
1483     void setPos(Goffset pos, int dir = 0) override;
1484 
1485 private:
1486     SplashBitmap *bitmap;
1487     size_t width;
1488     int height;
1489 
1490     std::vector<unsigned char> buf;
1491     size_t bufPtr;
1492     int curLine;
1493 
1494     bool fillBuf();
1495 };
1496 
1497 #endif
1498