1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2010 The Android Open Source Project 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/pdf/SkDeflate.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkData.h" 11cb93a386Sopenharmony_ci#include "include/private/SkMalloc.h" 12cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 13cb93a386Sopenharmony_ci#include "src/core/SkTraceEvent.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci#include "zlib.h" 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_ci#include <algorithm> 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_cinamespace { 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ci// Different zlib implementations use different T. 22cb93a386Sopenharmony_ci// We've seen size_t and unsigned. 23cb93a386Sopenharmony_citemplate <typename T> void* skia_alloc_func(void*, T items, T size) { 24cb93a386Sopenharmony_ci return sk_calloc_throw(SkToSizeT(items) * SkToSizeT(size)); 25cb93a386Sopenharmony_ci} 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_civoid skia_free_func(void*, void* address) { sk_free(address); } 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_ci} // namespace 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_ci#define SKDEFLATEWSTREAM_INPUT_BUFFER_SIZE 4096 32cb93a386Sopenharmony_ci#define SKDEFLATEWSTREAM_OUTPUT_BUFFER_SIZE 4224 // 4096 + 128, usually big 33cb93a386Sopenharmony_ci // enough to always do a 34cb93a386Sopenharmony_ci // single loop. 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ci// called by both write() and finalize() 37cb93a386Sopenharmony_cistatic void do_deflate(int flush, 38cb93a386Sopenharmony_ci z_stream* zStream, 39cb93a386Sopenharmony_ci SkWStream* out, 40cb93a386Sopenharmony_ci unsigned char* inBuffer, 41cb93a386Sopenharmony_ci size_t inBufferSize) { 42cb93a386Sopenharmony_ci zStream->next_in = inBuffer; 43cb93a386Sopenharmony_ci zStream->avail_in = SkToInt(inBufferSize); 44cb93a386Sopenharmony_ci unsigned char outBuffer[SKDEFLATEWSTREAM_OUTPUT_BUFFER_SIZE]; 45cb93a386Sopenharmony_ci SkDEBUGCODE(int returnValue;) 46cb93a386Sopenharmony_ci do { 47cb93a386Sopenharmony_ci zStream->next_out = outBuffer; 48cb93a386Sopenharmony_ci zStream->avail_out = sizeof(outBuffer); 49cb93a386Sopenharmony_ci SkDEBUGCODE(returnValue =) deflate(zStream, flush); 50cb93a386Sopenharmony_ci SkASSERT(!zStream->msg); 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_ci out->write(outBuffer, sizeof(outBuffer) - zStream->avail_out); 53cb93a386Sopenharmony_ci } while (zStream->avail_in || !zStream->avail_out); 54cb93a386Sopenharmony_ci SkASSERT(flush == Z_FINISH 55cb93a386Sopenharmony_ci ? returnValue == Z_STREAM_END 56cb93a386Sopenharmony_ci : returnValue == Z_OK); 57cb93a386Sopenharmony_ci} 58cb93a386Sopenharmony_ci 59cb93a386Sopenharmony_ci// Hide all zlib impl details. 60cb93a386Sopenharmony_cistruct SkDeflateWStream::Impl { 61cb93a386Sopenharmony_ci SkWStream* fOut; 62cb93a386Sopenharmony_ci unsigned char fInBuffer[SKDEFLATEWSTREAM_INPUT_BUFFER_SIZE]; 63cb93a386Sopenharmony_ci size_t fInBufferIndex; 64cb93a386Sopenharmony_ci z_stream fZStream; 65cb93a386Sopenharmony_ci}; 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ciSkDeflateWStream::SkDeflateWStream(SkWStream* out, 68cb93a386Sopenharmony_ci int compressionLevel, 69cb93a386Sopenharmony_ci bool gzip) 70cb93a386Sopenharmony_ci : fImpl(std::make_unique<SkDeflateWStream::Impl>()) { 71cb93a386Sopenharmony_ci fImpl->fOut = out; 72cb93a386Sopenharmony_ci fImpl->fInBufferIndex = 0; 73cb93a386Sopenharmony_ci if (!fImpl->fOut) { 74cb93a386Sopenharmony_ci return; 75cb93a386Sopenharmony_ci } 76cb93a386Sopenharmony_ci fImpl->fZStream.next_in = nullptr; 77cb93a386Sopenharmony_ci fImpl->fZStream.zalloc = &skia_alloc_func; 78cb93a386Sopenharmony_ci fImpl->fZStream.zfree = &skia_free_func; 79cb93a386Sopenharmony_ci fImpl->fZStream.opaque = nullptr; 80cb93a386Sopenharmony_ci SkASSERT(compressionLevel <= 9 && compressionLevel >= -1); 81cb93a386Sopenharmony_ci SkDEBUGCODE(int r =) deflateInit2(&fImpl->fZStream, compressionLevel, 82cb93a386Sopenharmony_ci Z_DEFLATED, gzip ? 0x1F : 0x0F, 83cb93a386Sopenharmony_ci 8, Z_DEFAULT_STRATEGY); 84cb93a386Sopenharmony_ci SkASSERT(Z_OK == r); 85cb93a386Sopenharmony_ci} 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_ciSkDeflateWStream::~SkDeflateWStream() { this->finalize(); } 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_civoid SkDeflateWStream::finalize() { 90cb93a386Sopenharmony_ci TRACE_EVENT0("skia", TRACE_FUNC); 91cb93a386Sopenharmony_ci if (!fImpl->fOut) { 92cb93a386Sopenharmony_ci return; 93cb93a386Sopenharmony_ci } 94cb93a386Sopenharmony_ci do_deflate(Z_FINISH, &fImpl->fZStream, fImpl->fOut, fImpl->fInBuffer, 95cb93a386Sopenharmony_ci fImpl->fInBufferIndex); 96cb93a386Sopenharmony_ci (void)deflateEnd(&fImpl->fZStream); 97cb93a386Sopenharmony_ci fImpl->fOut = nullptr; 98cb93a386Sopenharmony_ci} 99cb93a386Sopenharmony_ci 100cb93a386Sopenharmony_cibool SkDeflateWStream::write(const void* void_buffer, size_t len) { 101cb93a386Sopenharmony_ci TRACE_EVENT0("skia", TRACE_FUNC); 102cb93a386Sopenharmony_ci if (!fImpl->fOut) { 103cb93a386Sopenharmony_ci return false; 104cb93a386Sopenharmony_ci } 105cb93a386Sopenharmony_ci const char* buffer = (const char*)void_buffer; 106cb93a386Sopenharmony_ci while (len > 0) { 107cb93a386Sopenharmony_ci size_t tocopy = 108cb93a386Sopenharmony_ci std::min(len, sizeof(fImpl->fInBuffer) - fImpl->fInBufferIndex); 109cb93a386Sopenharmony_ci memcpy(fImpl->fInBuffer + fImpl->fInBufferIndex, buffer, tocopy); 110cb93a386Sopenharmony_ci len -= tocopy; 111cb93a386Sopenharmony_ci buffer += tocopy; 112cb93a386Sopenharmony_ci fImpl->fInBufferIndex += tocopy; 113cb93a386Sopenharmony_ci SkASSERT(fImpl->fInBufferIndex <= sizeof(fImpl->fInBuffer)); 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_ci // if the buffer isn't filled, don't call into zlib yet. 116cb93a386Sopenharmony_ci if (sizeof(fImpl->fInBuffer) == fImpl->fInBufferIndex) { 117cb93a386Sopenharmony_ci do_deflate(Z_NO_FLUSH, &fImpl->fZStream, fImpl->fOut, 118cb93a386Sopenharmony_ci fImpl->fInBuffer, fImpl->fInBufferIndex); 119cb93a386Sopenharmony_ci fImpl->fInBufferIndex = 0; 120cb93a386Sopenharmony_ci } 121cb93a386Sopenharmony_ci } 122cb93a386Sopenharmony_ci return true; 123cb93a386Sopenharmony_ci} 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_cisize_t SkDeflateWStream::bytesWritten() const { 126cb93a386Sopenharmony_ci return fImpl->fZStream.total_in + fImpl->fInBufferIndex; 127cb93a386Sopenharmony_ci} 128