Home | History | Annotate | Download | only in core
      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