Coverage Report

Created: 2021-08-22 09:07

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