|
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 |