blob: 20f828db0e3078c1df3b1f5d5f92b0d1e6e576e4 [file] [log] [blame]
//========================================================================
//
// FlateStream.cc
//
// Copyright (C) 2005, Jeff Muizelaar <jeff@infidigm.net>
// Copyright (C) 2010, Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2016, William Bader <williambader@hotmail.com>
// Copyright (C) 2017, Adrian Johnson <ajohnson@redneon.com>
//
// This file is under the GPLv2 or later license
//
//========================================================================
#include <config.h>
#include "poppler-config.h"
#ifdef ENABLE_ZLIB_UNCOMPRESS
#include "FlateStream.h"
FlateStream::FlateStream(Stream *strA, int predictor, int columns, int colors, int bits) :
FilterStream(strA)
{
if (predictor != 1) {
pred = new StreamPredictor(this, predictor, columns, colors, bits);
} else {
pred = NULL;
}
out_pos = 0;
memset(&d_stream, 0, sizeof(d_stream));
inflateInit(&d_stream);
}
FlateStream::~FlateStream() {
inflateEnd(&d_stream);
delete pred;
delete str;
}
void FlateStream::reset() {
//FIXME: what are the semantics of reset?
//i.e. how much initialization has to happen in the constructor?
/* reinitialize zlib */
inflateEnd(&d_stream);
memset(&d_stream, 0, sizeof(d_stream));
inflateInit(&d_stream);
str->reset();
d_stream.avail_in = 0;
status = Z_OK;
out_pos = 0;
out_buf_len = 0;
}
int FlateStream::getRawChar() {
return doGetRawChar();
}
void FlateStream::getRawChars(int nChars, int *buffer) {
for (int i = 0; i < nChars; ++i)
buffer[i] = doGetRawChar();
}
int FlateStream::getChar() {
if (pred)
return pred->getChar();
else
return getRawChar();
}
int FlateStream::lookChar() {
if (pred)
return pred->lookChar();
if (fill_buffer())
return EOF;
return out_buf[out_pos];
}
int FlateStream::fill_buffer() {
/* only fill the buffer if it has all been used */
if (out_pos >= out_buf_len) {
/* check if the flatestream has been exhausted */
if (status == Z_STREAM_END) {
return -1;
}
/* set to the beginning of out_buf */
d_stream.avail_out = sizeof(out_buf);
d_stream.next_out = out_buf;
out_pos = 0;
while (1) {
/* buffer is empty so we need to fill it */
if (d_stream.avail_in == 0) {
int c;
/* read from the source stream */
while (d_stream.avail_in < sizeof(in_buf) && (c = str->getChar()) != EOF) {
in_buf[d_stream.avail_in++] = c;
}
d_stream.next_in = in_buf;
}
/* keep decompressing until we can't anymore */
if (d_stream.avail_out == 0 || d_stream.avail_in == 0 || (status != Z_OK && status != Z_BUF_ERROR))
break;
status = inflate(&d_stream, Z_SYNC_FLUSH);
}
out_buf_len = sizeof(out_buf) - d_stream.avail_out;
if (status != Z_OK && status != Z_STREAM_END)
return -1;
if (!out_buf_len)
return -1;
}
return 0;
}
GooString *FlateStream::getPSFilter(int psLevel, const char *indent) {
GooString *s;
if (psLevel < 3 || pred) {
return NULL;
}
if (!(s = str->getPSFilter(psLevel, indent))) {
return NULL;
}
s->append(indent)->append("<< >> /FlateDecode filter\n");
return s;
}
bool FlateStream::isBinary(bool last) {
return str->isBinary(true);
}
#endif