1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "SkFlate.h" 18 #include "SkStream.h" 19 20 #ifndef SK_ZLIB_INCLUDE 21 bool SkFlate::HaveFlate() { return false; } 22 bool SkFlate::Deflate(SkStream*, SkDynamicMemoryWStream*) { return false; } 23 bool SkFlate::Inflate(SkStream*, SkDynamicMemoryWStream*) { return false; } 24 #else 25 26 // static 27 bool SkFlate::HaveFlate() { 28 #ifdef SK_DEBUG 29 return false; 30 #else 31 return true; 32 #endif 33 } 34 35 namespace { 36 37 #include SK_ZLIB_INCLUDE 38 39 // static 40 const size_t kBufferSize = 1024; 41 42 bool doFlate(bool compress, SkStream* src, SkDynamicMemoryWStream* dst) { 43 uint8_t inputBuffer[kBufferSize]; 44 uint8_t outputBuffer[kBufferSize]; 45 z_stream flateData; 46 flateData.zalloc = NULL; 47 flateData.zfree = NULL; 48 flateData.next_in = NULL; 49 flateData.avail_in = 0; 50 flateData.next_out = outputBuffer; 51 flateData.avail_out = kBufferSize; 52 int rc; 53 if (compress) 54 rc = deflateInit(&flateData, Z_DEFAULT_COMPRESSION); 55 else 56 rc = inflateInit(&flateData); 57 if (rc != Z_OK) 58 return false; 59 60 uint8_t* input = (uint8_t*)src->getMemoryBase(); 61 size_t inputLength = src->getLength(); 62 if (input == NULL || inputLength == 0) { 63 input = NULL; 64 flateData.next_in = inputBuffer; 65 flateData.avail_in = 0; 66 } else { 67 flateData.next_in = input; 68 flateData.avail_in = inputLength; 69 } 70 71 rc = Z_OK; 72 while (true) { 73 if (flateData.avail_out < kBufferSize) { 74 if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) { 75 rc = Z_BUF_ERROR; 76 break; 77 } 78 flateData.next_out = outputBuffer; 79 flateData.avail_out = kBufferSize; 80 } 81 if (rc != Z_OK) 82 break; 83 if (flateData.avail_in == 0) { 84 if (input != NULL) 85 break; 86 size_t read = src->read(&inputBuffer, kBufferSize); 87 if (read == 0) 88 break; 89 flateData.next_in = inputBuffer; 90 flateData.avail_in = read; 91 } 92 if (compress) 93 rc = deflate(&flateData, Z_NO_FLUSH); 94 else 95 rc = inflate(&flateData, Z_NO_FLUSH); 96 } 97 while (rc == Z_OK) { 98 if (compress) 99 rc = deflate(&flateData, Z_FINISH); 100 else 101 rc = inflate(&flateData, Z_FINISH); 102 if (flateData.avail_out < kBufferSize) { 103 if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) 104 return false; 105 flateData.next_out = outputBuffer; 106 flateData.avail_out = kBufferSize; 107 } 108 } 109 110 if (compress) 111 deflateEnd(&flateData); 112 else 113 inflateEnd(&flateData); 114 if (rc == Z_STREAM_END) 115 return true; 116 return false; 117 } 118 119 } 120 121 // static 122 bool SkFlate::Deflate(SkStream* src, SkDynamicMemoryWStream* dst) { 123 return doFlate(true, src, dst); 124 } 125 126 // static 127 bool SkFlate::Inflate(SkStream* src, SkDynamicMemoryWStream* dst) { 128 return doFlate(false, src, dst); 129 } 130 131 #endif 132 133