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_ZLIB_INCLUDE
     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 #include SK_ZLIB_INCLUDE
     30 
     31 // static
     32 const size_t kBufferSize = 1024;
     33 
     34 bool doFlate(bool compress, SkStream* src, SkWStream* dst) {
     35     uint8_t inputBuffer[kBufferSize];
     36     uint8_t outputBuffer[kBufferSize];
     37     z_stream flateData;
     38     flateData.zalloc = NULL;
     39     flateData.zfree = NULL;
     40     flateData.next_in = NULL;
     41     flateData.avail_in = 0;
     42     flateData.next_out = outputBuffer;
     43     flateData.avail_out = kBufferSize;
     44     int rc;
     45     if (compress)
     46         rc = deflateInit(&flateData, Z_DEFAULT_COMPRESSION);
     47     else
     48         rc = inflateInit(&flateData);
     49     if (rc != Z_OK)
     50         return false;
     51 
     52     uint8_t* input = (uint8_t*)src->getMemoryBase();
     53     size_t inputLength = src->getLength();
     54     if (input == NULL || inputLength == 0) {
     55         input = NULL;
     56         flateData.next_in = inputBuffer;
     57         flateData.avail_in = 0;
     58     } else {
     59         flateData.next_in = input;
     60         flateData.avail_in = inputLength;
     61     }
     62 
     63     rc = Z_OK;
     64     while (true) {
     65         if (flateData.avail_out < kBufferSize) {
     66             if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) {
     67                 rc = Z_BUF_ERROR;
     68                 break;
     69             }
     70             flateData.next_out = outputBuffer;
     71             flateData.avail_out = kBufferSize;
     72         }
     73         if (rc != Z_OK)
     74             break;
     75         if (flateData.avail_in == 0) {
     76             if (input != NULL)
     77                 break;
     78             size_t read = src->read(&inputBuffer, kBufferSize);
     79             if (read == 0)
     80                 break;
     81             flateData.next_in = inputBuffer;
     82             flateData.avail_in = read;
     83         }
     84         if (compress)
     85             rc = deflate(&flateData, Z_NO_FLUSH);
     86         else
     87             rc = inflate(&flateData, Z_NO_FLUSH);
     88     }
     89     while (rc == Z_OK) {
     90         if (compress)
     91             rc = deflate(&flateData, Z_FINISH);
     92         else
     93             rc = inflate(&flateData, Z_FINISH);
     94         if (flateData.avail_out < kBufferSize) {
     95             if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out))
     96                 return false;
     97             flateData.next_out = outputBuffer;
     98             flateData.avail_out = kBufferSize;
     99         }
    100     }
    101 
    102     if (compress)
    103         deflateEnd(&flateData);
    104     else
    105         inflateEnd(&flateData);
    106     if (rc == Z_STREAM_END)
    107         return true;
    108     return false;
    109 }
    110 
    111 }
    112 
    113 // static
    114 bool SkFlate::Deflate(SkStream* src, SkWStream* dst) {
    115     return doFlate(true, src, dst);
    116 }
    117 
    118 bool SkFlate::Deflate(const void* ptr, size_t len, SkWStream* dst) {
    119     SkMemoryStream stream(ptr, len);
    120     return doFlate(true, &stream, dst);
    121 }
    122 
    123 bool SkFlate::Deflate(const SkData* data, SkWStream* dst) {
    124     if (data) {
    125         SkMemoryStream stream(data->data(), data->size());
    126         return doFlate(true, &stream, dst);
    127     }
    128     return false;
    129 }
    130 
    131 // static
    132 bool SkFlate::Inflate(SkStream* src, SkWStream* dst) {
    133     return doFlate(false, src, dst);
    134 }
    135 
    136 #endif
    137 
    138