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