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