1 2/* 3 * Copyright 2010 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#include "SkData.h" 11#include "SkFlate.h" 12#include "SkStream.h" 13 14#ifndef SK_HAS_ZLIB 15bool SkFlate::HaveFlate() { return false; } 16bool SkFlate::Deflate(SkStream*, SkWStream*) { return false; } 17bool SkFlate::Deflate(const void*, size_t, SkWStream*) { return false; } 18bool SkFlate::Deflate(const SkData*, SkWStream*) { return false; } 19bool SkFlate::Inflate(SkStream*, SkWStream*) { return false; } 20#else 21 22// static 23bool SkFlate::HaveFlate() { 24 return true; 25} 26 27namespace { 28 29#ifdef SK_SYSTEM_ZLIB 30#include <zlib.h> 31#else 32#include SK_ZLIB_INCLUDE 33#endif 34 35// static 36const size_t kBufferSize = 1024; 37 38bool doFlate(bool compress, SkStream* src, SkWStream* dst) { 39 uint8_t inputBuffer[kBufferSize]; 40 uint8_t outputBuffer[kBufferSize]; 41 z_stream flateData; 42 flateData.zalloc = NULL; 43 flateData.zfree = NULL; 44 flateData.next_in = NULL; 45 flateData.avail_in = 0; 46 flateData.next_out = outputBuffer; 47 flateData.avail_out = kBufferSize; 48 int rc; 49 if (compress) 50 rc = deflateInit(&flateData, Z_DEFAULT_COMPRESSION); 51 else 52 rc = inflateInit(&flateData); 53 if (rc != Z_OK) 54 return false; 55 56 uint8_t* input = (uint8_t*)src->getMemoryBase(); 57 size_t inputLength = src->getLength(); 58 if (input == NULL || inputLength == 0) { 59 input = NULL; 60 flateData.next_in = inputBuffer; 61 flateData.avail_in = 0; 62 } else { 63 flateData.next_in = input; 64 flateData.avail_in = SkToUInt(inputLength); 65 } 66 67 rc = Z_OK; 68 while (true) { 69 if (flateData.avail_out < kBufferSize) { 70 if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) { 71 rc = Z_BUF_ERROR; 72 break; 73 } 74 flateData.next_out = outputBuffer; 75 flateData.avail_out = kBufferSize; 76 } 77 if (rc != Z_OK) 78 break; 79 if (flateData.avail_in == 0) { 80 if (input != NULL) 81 break; 82 size_t read = src->read(&inputBuffer, kBufferSize); 83 if (read == 0) 84 break; 85 flateData.next_in = inputBuffer; 86 flateData.avail_in = SkToUInt(read); 87 } 88 if (compress) 89 rc = deflate(&flateData, Z_NO_FLUSH); 90 else 91 rc = inflate(&flateData, Z_NO_FLUSH); 92 } 93 while (rc == Z_OK) { 94 if (compress) 95 rc = deflate(&flateData, Z_FINISH); 96 else 97 rc = inflate(&flateData, Z_FINISH); 98 if (flateData.avail_out < kBufferSize) { 99 if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) 100 return false; 101 flateData.next_out = outputBuffer; 102 flateData.avail_out = kBufferSize; 103 } 104 } 105 106 if (compress) 107 deflateEnd(&flateData); 108 else 109 inflateEnd(&flateData); 110 if (rc == Z_STREAM_END) 111 return true; 112 return false; 113} 114 115} 116 117// static 118bool SkFlate::Deflate(SkStream* src, SkWStream* dst) { 119 return doFlate(true, src, dst); 120} 121 122bool SkFlate::Deflate(const void* ptr, size_t len, SkWStream* dst) { 123 SkMemoryStream stream(ptr, len); 124 return doFlate(true, &stream, dst); 125} 126 127bool SkFlate::Deflate(const SkData* data, SkWStream* dst) { 128 if (data) { 129 SkMemoryStream stream(data->data(), data->size()); 130 return doFlate(true, &stream, dst); 131 } 132 return false; 133} 134 135// static 136bool SkFlate::Inflate(SkStream* src, SkWStream* dst) { 137 return doFlate(false, src, dst); 138} 139 140#endif 141