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 15 bool SkFlate::HaveFlate() { return false; } 16 bool SkFlate::Deflate(SkStream*, SkWStream*) { return false; } 17 bool SkFlate::Deflate(const void*, size_t, SkWStream*) { return false; } 18 bool SkFlate::Deflate(const SkData*, SkWStream*) { return false; } 19 bool SkFlate::Inflate(SkStream*, SkWStream*) { return false; } 20 #else 21 22 // static 23 bool SkFlate::HaveFlate() { 24 return true; 25 } 26 27 namespace { 28 29 #ifdef SK_SYSTEM_ZLIB 30 #include <zlib.h> 31 #else 32 #include SK_ZLIB_INCLUDE 33 #endif 34 35 // static 36 const size_t kBufferSize = 1024; 37 38 bool 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 118 bool SkFlate::Deflate(SkStream* src, SkWStream* dst) { 119 return doFlate(true, src, dst); 120 } 121 122 bool SkFlate::Deflate(const void* ptr, size_t len, SkWStream* dst) { 123 SkMemoryStream stream(ptr, len); 124 return doFlate(true, &stream, dst); 125 } 126 127 bool 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 136 bool SkFlate::Inflate(SkStream* src, SkWStream* dst) { 137 return doFlate(false, src, dst); 138 } 139 140 #endif 141