/* For general Scribus (>=1.3.2) copyright and licensing information please refer to the COPYING file provided with the program. Following this notice may exist a copyright and/or license notice that predates the release of Scribus 1.3.2 for which a new license (GPL+exception) is in place. */ /* Code inspired by cairo and adapted for Scribus by Jean Ghali */ #include "scstreamfilter_flate.h" #include #include #include #define BUFFER_SIZE 16384 struct ScFlateEncodeFilterData { z_stream zlib_stream; unsigned char input_buffer [BUFFER_SIZE]; unsigned char output_buffer[BUFFER_SIZE]; }; ScFlateEncodeFilter::ScFlateEncodeFilter(QDataStream* stream) : ScStreamFilter(stream) { m_filterData = NULL; m_openedFilter = false; } ScFlateEncodeFilter::ScFlateEncodeFilter(ScStreamFilter* filter) : ScStreamFilter(filter) { m_filterData = NULL; m_openedFilter = false; } ScFlateEncodeFilter::~ScFlateEncodeFilter() { if (m_filterData && m_openedFilter) closeFilter(); freeData(); } void ScFlateEncodeFilter::freeData(void) { if (m_filterData) free (m_filterData); m_filterData = NULL; } bool ScFlateEncodeFilter::openFilter (void) { freeData(); m_filterData = (ScFlateEncodeFilterData*) malloc(sizeof(ScFlateEncodeFilterData)); if (m_filterData == NULL) return false; m_filterData->zlib_stream.zalloc = Z_NULL; m_filterData->zlib_stream.zfree = Z_NULL; m_filterData->zlib_stream.opaque = Z_NULL; if (deflateInit (&m_filterData->zlib_stream, Z_DEFAULT_COMPRESSION) != Z_OK) { freeData(); return false; } m_filterData->zlib_stream.next_in = m_filterData->input_buffer; m_filterData->zlib_stream.avail_in = 0; m_filterData->zlib_stream.next_out = m_filterData->output_buffer; m_filterData->zlib_stream.avail_out = BUFFER_SIZE; m_openedFilter = ScStreamFilter::openFilter(); return m_openedFilter; } bool ScFlateEncodeFilter::closeFilter(void) { bool closeSucceed = writeDeflate(true); deflateEnd (&m_filterData->zlib_stream); m_openedFilter = false; closeSucceed &= ScStreamFilter::closeFilter(); return closeSucceed; } bool ScFlateEncodeFilter::writeData(const char* data, int dataLen) { bool deflateSuccess = true; unsigned int count; const unsigned char *p = (const unsigned char *) data; if (!m_filterData) return false; while (dataLen) { count = dataLen; if (count > BUFFER_SIZE - m_filterData->zlib_stream.avail_in) count = BUFFER_SIZE - m_filterData->zlib_stream.avail_in; memcpy (m_filterData->input_buffer + m_filterData->zlib_stream.avail_in, p, count); p += count; m_filterData->zlib_stream.avail_in += count; dataLen -= count; if (m_filterData->zlib_stream.avail_in == BUFFER_SIZE) deflateSuccess &= writeDeflate(false); } return deflateSuccess; } bool ScFlateEncodeFilter::writeDeflate(bool flush) { int ret; bool deflateSuccess = true; bool finished; do { ret = deflate (&m_filterData->zlib_stream, flush ? Z_FINISH : Z_NO_FLUSH); if (flush || m_filterData->zlib_stream.avail_out == 0) { deflateSuccess &= writeDataInternal((const char*) m_filterData->output_buffer, BUFFER_SIZE - m_filterData->zlib_stream.avail_out); m_filterData->zlib_stream.next_out = m_filterData->output_buffer; m_filterData->zlib_stream.avail_out = BUFFER_SIZE; } finished = TRUE; if (m_filterData->zlib_stream.avail_in != 0) finished = FALSE; if (flush && ret != Z_STREAM_END) finished = FALSE; } while (!finished); m_filterData->zlib_stream.next_in = m_filterData->input_buffer; return deflateSuccess; }