blob: a9adece75e38e0e7da10a1be81071cd9aa79feca [file] [log] [blame]
vandebo@chromium.orga09ef972010-12-01 22:17:20 +00001/*
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
21bool SkFlate::HaveFlate() { return false; }
22bool SkFlate::Deflate(SkStream*, SkDynamicMemoryWStream*) { return false; }
23bool SkFlate::Inflate(SkStream*, SkDynamicMemoryWStream*) { return false; }
24#else
25
26// static
27const size_t SkFlate::kBufferSize = 1024;
28
29// static
30bool SkFlate::HaveFlate() {
31 return true;
32}
33
34namespace {
35
36#include SK_ZLIB_INCLUDE
37
38bool doFlate(bool compress, const size_t kBufferSize, SkStream* src,
39 SkDynamicMemoryWStream* dst) {
40 uint8_t inputBuffer[kBufferSize];
41 uint8_t outputBuffer[kBufferSize];
42 z_stream flateData;
43 flateData.zalloc = NULL;
44 flateData.zfree = NULL;
45 flateData.next_in = NULL;
46 flateData.avail_in = 0;
47 flateData.next_out = outputBuffer;
48 flateData.avail_out = kBufferSize;
49 int rc;
50 if (compress)
51 rc = deflateInit(&flateData, Z_DEFAULT_COMPRESSION);
52 else
53 rc = inflateInit(&flateData);
54 if (rc != Z_OK)
55 return false;
56
57 uint8_t* input = (uint8_t*)src->getMemoryBase();
58 size_t inputLength = src->getLength();
59 if (input == NULL || inputLength < 0) {
60 input = NULL;
61 flateData.next_in = inputBuffer;
62 flateData.avail_in = 0;
63 } else {
64 flateData.next_in = input;
65 flateData.avail_in = inputLength;
66 }
67
68 rc = Z_OK;
69 while (true) {
70 if (flateData.avail_out < kBufferSize) {
71 if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out)) {
72 rc = Z_BUF_ERROR;
73 break;
74 }
75 flateData.next_out = outputBuffer;
76 flateData.avail_out = kBufferSize;
77 }
78 if (flateData.avail_in == 0) {
79 if (input != NULL)
80 break;
81 size_t read = src->read(&inputBuffer, kBufferSize);
82 if (read == 0)
83 break;
84 flateData.next_in = inputBuffer;
85 flateData.avail_in = read;
86 }
87 if (compress)
88 rc = deflate(&flateData, Z_NO_FLUSH);
89 else
90 rc = inflate(&flateData, Z_NO_FLUSH);
91 if (rc != Z_OK)
92 break;
93 }
94 while (rc == Z_OK) {
95 if (compress)
96 rc = deflate(&flateData, Z_FINISH);
97 else
98 rc = inflate(&flateData, Z_FINISH);
99 if (flateData.avail_out > 0) {
100 if (!dst->write(outputBuffer, kBufferSize - flateData.avail_out))
101 return false;
102 flateData.next_out = outputBuffer;
103 flateData.avail_out = kBufferSize;
104 }
105 }
106
107 if (compress)
108 deflateEnd(&flateData);
109 else
110 inflateEnd(&flateData);
111 if (rc == Z_STREAM_END)
112 return true;
113 return false;
114}
115
116}
117
118// static
119bool SkFlate::Deflate(SkStream* src, SkDynamicMemoryWStream* dst) {
120 return doFlate(true, kBufferSize, src, dst);
121}
122
123// static
124bool SkFlate::Inflate(SkStream* src, SkDynamicMemoryWStream* dst) {
125 return doFlate(false, kBufferSize, src, dst);
126}
127
128#endif
129