michael@0: michael@0: /* michael@0: * Copyright 2010 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #include "SkData.h" michael@0: #include "SkFlate.h" michael@0: #include "SkStream.h" michael@0: michael@0: #ifndef SK_HAS_ZLIB michael@0: bool SkFlate::HaveFlate() { return false; } michael@0: bool SkFlate::Deflate(SkStream*, SkWStream*) { return false; } michael@0: bool SkFlate::Deflate(const void*, size_t, SkWStream*) { return false; } michael@0: bool SkFlate::Deflate(const SkData*, SkWStream*) { return false; } michael@0: bool SkFlate::Inflate(SkStream*, SkWStream*) { return false; } michael@0: #else michael@0: michael@0: // static michael@0: bool SkFlate::HaveFlate() { michael@0: return true; michael@0: } michael@0: michael@0: namespace { michael@0: michael@0: #ifdef SK_SYSTEM_ZLIB michael@0: #include michael@0: #else michael@0: #include SK_ZLIB_INCLUDE michael@0: #endif michael@0: michael@0: // static michael@0: const size_t kBufferSize = 1024; michael@0: michael@0: bool doFlate(bool compress, SkStream* src, SkWStream* dst) { michael@0: uint8_t inputBuffer[kBufferSize]; michael@0: uint8_t outputBuffer[kBufferSize]; michael@0: z_stream flateData; michael@0: flateData.zalloc = NULL; michael@0: flateData.zfree = NULL; michael@0: flateData.next_in = NULL; michael@0: flateData.avail_in = 0; michael@0: flateData.next_out = outputBuffer; michael@0: flateData.avail_out = kBufferSize; michael@0: int rc; michael@0: if (compress) michael@0: rc = deflateInit(&flateData, Z_DEFAULT_COMPRESSION); michael@0: else michael@0: rc = inflateInit(&flateData); michael@0: if (rc != Z_OK) michael@0: return false; michael@0: michael@0: uint8_t* input = (uint8_t*)src->getMemoryBase(); michael@0: size_t inputLength = src->getLength(); michael@0: if (input == NULL || inputLength == 0) { michael@0: input = NULL; michael@0: flateData.next_in = inputBuffer; michael@0: flateData.avail_in = 0; michael@0: } else { michael@0: flateData.next_in = input; michael@0: flateData.avail_in = SkToUInt(inputLength); michael@0: } michael@0: michael@0: rc = Z_OK; michael@0: while (true) { michael@0: if (flateData.avail_out < kBufferSize) { michael@0: if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) { michael@0: rc = Z_BUF_ERROR; michael@0: break; michael@0: } michael@0: flateData.next_out = outputBuffer; michael@0: flateData.avail_out = kBufferSize; michael@0: } michael@0: if (rc != Z_OK) michael@0: break; michael@0: if (flateData.avail_in == 0) { michael@0: if (input != NULL) michael@0: break; michael@0: size_t read = src->read(&inputBuffer, kBufferSize); michael@0: if (read == 0) michael@0: break; michael@0: flateData.next_in = inputBuffer; michael@0: flateData.avail_in = SkToUInt(read); michael@0: } michael@0: if (compress) michael@0: rc = deflate(&flateData, Z_NO_FLUSH); michael@0: else michael@0: rc = inflate(&flateData, Z_NO_FLUSH); michael@0: } michael@0: while (rc == Z_OK) { michael@0: if (compress) michael@0: rc = deflate(&flateData, Z_FINISH); michael@0: else michael@0: rc = inflate(&flateData, Z_FINISH); michael@0: if (flateData.avail_out < kBufferSize) { michael@0: if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) michael@0: return false; michael@0: flateData.next_out = outputBuffer; michael@0: flateData.avail_out = kBufferSize; michael@0: } michael@0: } michael@0: michael@0: if (compress) michael@0: deflateEnd(&flateData); michael@0: else michael@0: inflateEnd(&flateData); michael@0: if (rc == Z_STREAM_END) michael@0: return true; michael@0: return false; michael@0: } michael@0: michael@0: } michael@0: michael@0: // static michael@0: bool SkFlate::Deflate(SkStream* src, SkWStream* dst) { michael@0: return doFlate(true, src, dst); michael@0: } michael@0: michael@0: bool SkFlate::Deflate(const void* ptr, size_t len, SkWStream* dst) { michael@0: SkMemoryStream stream(ptr, len); michael@0: return doFlate(true, &stream, dst); michael@0: } michael@0: michael@0: bool SkFlate::Deflate(const SkData* data, SkWStream* dst) { michael@0: if (data) { michael@0: SkMemoryStream stream(data->data(), data->size()); michael@0: return doFlate(true, &stream, dst); michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: // static michael@0: bool SkFlate::Inflate(SkStream* src, SkWStream* dst) { michael@0: return doFlate(false, src, dst); michael@0: } michael@0: michael@0: #endif