1 //========================================================================
2 //
3 // FlateStream.cc
4 //
5 // Copyright (C) 2005, Jeff Muizelaar <jeff@infidigm.net>
6 // Copyright (C) 2010, Albert Astals Cid <aacid@kde.org>
7 //
8 // This file is under the GPLv2 or later license
9 //
10 //========================================================================
11 #include "FlateStream.h"
FlateStream(Stream * strA,int predictor,int columns,int colors,int bits)12 FlateStream::FlateStream(Stream *strA, int predictor, int columns, int colors, int bits) :
13   FilterStream(strA)
14 {
15   if (predictor != 1) {
16     pred = new StreamPredictor(this, predictor, columns, colors, bits);
17   } else {
18     pred = NULL;
19   }
20   out_pos = 0;
21   memset(&d_stream, 0, sizeof(d_stream));
22   inflateInit(&d_stream);
23 }
24 
~FlateStream()25 FlateStream::~FlateStream() {
26   inflateEnd(&d_stream);
27   delete pred;
28   delete str;
29 }
30 
reset()31 void FlateStream::reset() {
32   //FIXME: what are the semantics of reset?
33   //i.e. how much intialization has to happen in the constructor?
34 
35   /* reinitialize zlib */
36   inflateEnd(&d_stream);
37   memset(&d_stream, 0, sizeof(d_stream));
38   inflateInit(&d_stream);
39 
40   str->reset();
41   d_stream.avail_in = 0;
42   status = Z_OK;
43   out_pos = 0;
44   out_buf_len = 0;
45 }
46 
getRawChar()47 int FlateStream::getRawChar() {
48   return doGetRawChar();
49 }
50 
getRawChars(int nChars,int * buffer)51 void FlateStream::getRawChars(int nChars, int *buffer) {
52   for (int i = 0; i < nChars; ++i)
53     buffer[i] = doGetRawChar();
54 }
55 
getChar()56 int FlateStream::getChar() {
57   if (pred)
58     return pred->getChar();
59   else
60     return getRawChar();
61 }
62 
lookChar()63 int FlateStream::lookChar() {
64   if (pred)
65     return pred->lookChar();
66 
67   if (fill_buffer())
68     return EOF;
69 
70   return out_buf[out_pos];
71 }
72 
fill_buffer()73 int FlateStream::fill_buffer() {
74   /* only fill the buffer if it has all been used */
75   if (out_pos >= out_buf_len) {
76     /* check if the flatestream has been exhausted */
77     if (status == Z_STREAM_END) {
78       return -1;
79     }
80 
81     /* set to the begining of out_buf */
82     d_stream.avail_out = sizeof(out_buf);
83     d_stream.next_out = out_buf;
84     out_pos = 0;
85 
86     while (1) {
87       /* buffer is empty so we need to fill it */
88       if (d_stream.avail_in == 0) {
89 	int c;
90 	/* read from the source stream */
91 	while (d_stream.avail_in < sizeof(in_buf) && (c = str->getChar()) != EOF) {
92 	  in_buf[d_stream.avail_in++] = c;
93 	}
94 	d_stream.next_in = in_buf;
95       }
96 
97       /* keep decompressing until we can't anymore */
98       if (d_stream.avail_out == 0 || d_stream.avail_in == 0 || (status != Z_OK && status != Z_BUF_ERROR))
99 	break;
100       status = inflate(&d_stream, Z_SYNC_FLUSH);
101     }
102 
103     out_buf_len = sizeof(out_buf) - d_stream.avail_out;
104     if (status != Z_OK && status != Z_STREAM_END)
105       return -1;
106     if (!out_buf_len)
107       return -1;
108   }
109 
110   return 0;
111 }
112 
getPSFilter(int psLevel,char * indent)113 GooString *FlateStream::getPSFilter(int psLevel, char *indent) {
114   GooString *s;
115 
116   if (psLevel < 3 || pred) {
117     return NULL;
118   }
119   if (!(s = str->getPSFilter(psLevel, indent))) {
120     return NULL;
121   }
122   s->append(indent)->append("<< >> /FlateDecode filter\n");
123   return s;
124 }
125 
isBinary(GBool last)126 GBool FlateStream::isBinary(GBool last) {
127   return str->isBinary(gTrue);
128 }
129