| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
/* |
|
2
|
|
|
|
|
|
|
* pdfmake_filter.c — Stream filter implementation |
|
3
|
|
|
|
|
|
|
* |
|
4
|
|
|
|
|
|
|
* Implements FlateDecode (DEFLATE + zlib) and predictor functions. |
|
5
|
|
|
|
|
|
|
* RFC 1950 (zlib), RFC 1951 (DEFLATE), PDF §7.4.4 |
|
6
|
|
|
|
|
|
|
*/ |
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
#include "pdfmake_filter.h" |
|
9
|
|
|
|
|
|
|
#include |
|
10
|
|
|
|
|
|
|
#include |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
/*============================================================================ |
|
13
|
|
|
|
|
|
|
* Adler-32 (RFC 1950) |
|
14
|
|
|
|
|
|
|
*==========================================================================*/ |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
#define ADLER_MOD 65521 |
|
17
|
|
|
|
|
|
|
|
|
18
|
31
|
|
|
|
|
|
uint32_t pdfmake_adler32(const uint8_t *data, size_t len) |
|
19
|
|
|
|
|
|
|
{ |
|
20
|
31
|
|
|
|
|
|
return pdfmake_adler32_update(1, data, len); |
|
21
|
|
|
|
|
|
|
} |
|
22
|
|
|
|
|
|
|
|
|
23
|
31
|
|
|
|
|
|
uint32_t pdfmake_adler32_update(uint32_t adler, const uint8_t *data, size_t len) |
|
24
|
|
|
|
|
|
|
{ |
|
25
|
31
|
|
|
|
|
|
uint32_t a = adler & 0xFFFF; |
|
26
|
31
|
|
|
|
|
|
uint32_t b = (adler >> 16) & 0xFFFF; |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
/* Process in chunks to avoid overflow */ |
|
29
|
387
|
100
|
|
|
|
|
while (len > 0) { |
|
30
|
356
|
|
|
|
|
|
size_t chunk = len > 5552 ? 5552 : len; |
|
31
|
356
|
|
|
|
|
|
len -= chunk; |
|
32
|
|
|
|
|
|
|
|
|
33
|
1857364
|
100
|
|
|
|
|
while (chunk--) { |
|
34
|
1857008
|
|
|
|
|
|
a += *data++; |
|
35
|
1857008
|
|
|
|
|
|
b += a; |
|
36
|
|
|
|
|
|
|
} |
|
37
|
|
|
|
|
|
|
|
|
38
|
356
|
|
|
|
|
|
a %= ADLER_MOD; |
|
39
|
356
|
|
|
|
|
|
b %= ADLER_MOD; |
|
40
|
|
|
|
|
|
|
} |
|
41
|
|
|
|
|
|
|
|
|
42
|
31
|
|
|
|
|
|
return (b << 16) | a; |
|
43
|
|
|
|
|
|
|
} |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
/*============================================================================ |
|
46
|
|
|
|
|
|
|
* Flate params |
|
47
|
|
|
|
|
|
|
*==========================================================================*/ |
|
48
|
|
|
|
|
|
|
|
|
49
|
113
|
|
|
|
|
|
void pdfmake_flate_params_init(pdfmake_flate_params_t *params) |
|
50
|
|
|
|
|
|
|
{ |
|
51
|
113
|
50
|
|
|
|
|
if (!params) return; |
|
52
|
113
|
|
|
|
|
|
params->predictor = 1; |
|
53
|
113
|
|
|
|
|
|
params->colors = 1; |
|
54
|
113
|
|
|
|
|
|
params->bits_per_comp = 8; |
|
55
|
113
|
|
|
|
|
|
params->columns = 1; |
|
56
|
113
|
|
|
|
|
|
params->early_change = 1; |
|
57
|
|
|
|
|
|
|
} |
|
58
|
|
|
|
|
|
|
|
|
59
|
93
|
|
|
|
|
|
pdfmake_err_t pdfmake_flate_params_from_dict(pdfmake_flate_params_t *params, |
|
60
|
|
|
|
|
|
|
const pdfmake_obj_t *dict) |
|
61
|
|
|
|
|
|
|
{ |
|
62
|
93
|
|
|
|
|
|
pdfmake_flate_params_init(params); |
|
63
|
|
|
|
|
|
|
/* Dict-based params parsing deferred - requires arena for name interning. |
|
64
|
|
|
|
|
|
|
* For now we use default params. Full implementation in later phase. */ |
|
65
|
|
|
|
|
|
|
(void)dict; |
|
66
|
93
|
|
|
|
|
|
return PDFMAKE_OK; |
|
67
|
|
|
|
|
|
|
} |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
/*============================================================================ |
|
70
|
|
|
|
|
|
|
* DEFLATE bit reader |
|
71
|
|
|
|
|
|
|
*==========================================================================*/ |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
typedef struct { |
|
74
|
|
|
|
|
|
|
const uint8_t *data; |
|
75
|
|
|
|
|
|
|
size_t len; |
|
76
|
|
|
|
|
|
|
size_t pos; |
|
77
|
|
|
|
|
|
|
uint32_t bits; |
|
78
|
|
|
|
|
|
|
int nbits; |
|
79
|
|
|
|
|
|
|
} bitreader_t; |
|
80
|
|
|
|
|
|
|
|
|
81
|
121
|
|
|
|
|
|
static void bitreader_init(bitreader_t *br, const uint8_t *data, size_t len) |
|
82
|
|
|
|
|
|
|
{ |
|
83
|
121
|
|
|
|
|
|
br->data = data; |
|
84
|
121
|
|
|
|
|
|
br->len = len; |
|
85
|
121
|
|
|
|
|
|
br->pos = 0; |
|
86
|
121
|
|
|
|
|
|
br->bits = 0; |
|
87
|
121
|
|
|
|
|
|
br->nbits = 0; |
|
88
|
121
|
|
|
|
|
|
} |
|
89
|
|
|
|
|
|
|
|
|
90
|
4814800
|
|
|
|
|
|
static int bitreader_read(bitreader_t *br, int n) |
|
91
|
|
|
|
|
|
|
{ |
|
92
|
|
|
|
|
|
|
int val; |
|
93
|
5675083
|
100
|
|
|
|
|
while (br->nbits < n) { |
|
94
|
860285
|
100
|
|
|
|
|
if (br->pos >= br->len) return -1; |
|
95
|
860283
|
|
|
|
|
|
br->bits |= (uint32_t)br->data[br->pos++] << br->nbits; |
|
96
|
860283
|
|
|
|
|
|
br->nbits += 8; |
|
97
|
|
|
|
|
|
|
} |
|
98
|
|
|
|
|
|
|
|
|
99
|
4814798
|
|
|
|
|
|
val = br->bits & ((1 << n) - 1); |
|
100
|
4814798
|
|
|
|
|
|
br->bits >>= n; |
|
101
|
4814798
|
|
|
|
|
|
br->nbits -= n; |
|
102
|
4814798
|
|
|
|
|
|
return val; |
|
103
|
|
|
|
|
|
|
} |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
/* Reserved for dynamic Huffman tree decoding in future phases */ |
|
106
|
|
|
|
|
|
|
__attribute__((unused)) |
|
107
|
0
|
|
|
|
|
|
static int bitreader_read_rev(bitreader_t *br, int n) |
|
108
|
|
|
|
|
|
|
{ |
|
109
|
|
|
|
|
|
|
int val; |
|
110
|
|
|
|
|
|
|
int rev; |
|
111
|
|
|
|
|
|
|
int i; |
|
112
|
0
|
|
|
|
|
|
val = bitreader_read(br, n); |
|
113
|
0
|
0
|
|
|
|
|
if (val < 0) return -1; |
|
114
|
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
/* Reverse bits */ |
|
116
|
0
|
|
|
|
|
|
rev = 0; |
|
117
|
0
|
0
|
|
|
|
|
for (i = 0; i < n; i++) { |
|
118
|
0
|
|
|
|
|
|
rev = (rev << 1) | (val & 1); |
|
119
|
0
|
|
|
|
|
|
val >>= 1; |
|
120
|
|
|
|
|
|
|
} |
|
121
|
0
|
|
|
|
|
|
return rev; |
|
122
|
|
|
|
|
|
|
} |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
/*============================================================================ |
|
125
|
|
|
|
|
|
|
* DEFLATE Huffman tables |
|
126
|
|
|
|
|
|
|
*==========================================================================*/ |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
#define HUFFMAN_MAX_BITS 15 |
|
129
|
|
|
|
|
|
|
#define HUFFMAN_MAX_CODES 288 |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
typedef struct { |
|
132
|
|
|
|
|
|
|
uint16_t counts[HUFFMAN_MAX_BITS + 1]; |
|
133
|
|
|
|
|
|
|
uint16_t symbols[HUFFMAN_MAX_CODES]; |
|
134
|
|
|
|
|
|
|
} huffman_t; |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
/* Build Huffman table from code lengths */ |
|
137
|
1110
|
|
|
|
|
|
static int huffman_build(huffman_t *h, const uint8_t *lengths, int n) |
|
138
|
|
|
|
|
|
|
{ |
|
139
|
|
|
|
|
|
|
int i; |
|
140
|
|
|
|
|
|
|
uint16_t offsets[HUFFMAN_MAX_BITS + 1]; |
|
141
|
|
|
|
|
|
|
int total; |
|
142
|
1110
|
|
|
|
|
|
memset(h->counts, 0, sizeof(h->counts)); |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
/* Count code lengths */ |
|
145
|
122105
|
100
|
|
|
|
|
for (i = 0; i < n; i++) { |
|
146
|
120995
|
50
|
|
|
|
|
if (lengths[i] > HUFFMAN_MAX_BITS) return -1; |
|
147
|
120995
|
|
|
|
|
|
h->counts[lengths[i]]++; |
|
148
|
|
|
|
|
|
|
} |
|
149
|
1110
|
|
|
|
|
|
h->counts[0] = 0; |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
/* Compute symbol table offsets (cumulative counts) */ |
|
152
|
1110
|
|
|
|
|
|
total = 0; |
|
153
|
17760
|
100
|
|
|
|
|
for (i = 1; i <= HUFFMAN_MAX_BITS; i++) { |
|
154
|
16650
|
|
|
|
|
|
offsets[i] = total; |
|
155
|
16650
|
|
|
|
|
|
total += h->counts[i]; |
|
156
|
|
|
|
|
|
|
} |
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
/* Build symbol table - symbols sorted by code length then symbol value */ |
|
159
|
122105
|
100
|
|
|
|
|
for (i = 0; i < n; i++) { |
|
160
|
120995
|
100
|
|
|
|
|
if (lengths[i] > 0) { |
|
161
|
60642
|
|
|
|
|
|
h->symbols[offsets[lengths[i]]++] = i; |
|
162
|
|
|
|
|
|
|
} |
|
163
|
|
|
|
|
|
|
} |
|
164
|
|
|
|
|
|
|
|
|
165
|
1110
|
|
|
|
|
|
return 0; |
|
166
|
|
|
|
|
|
|
} |
|
167
|
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
/* Decode one symbol using Huffman table */ |
|
169
|
920172
|
|
|
|
|
|
static int huffman_decode(huffman_t *h, bitreader_t *br) |
|
170
|
|
|
|
|
|
|
{ |
|
171
|
920172
|
|
|
|
|
|
int code = 0; |
|
172
|
920172
|
|
|
|
|
|
int first = 0; |
|
173
|
920172
|
|
|
|
|
|
int index = 0; |
|
174
|
|
|
|
|
|
|
int len; |
|
175
|
|
|
|
|
|
|
|
|
176
|
4532412
|
50
|
|
|
|
|
for (len = 1; len <= HUFFMAN_MAX_BITS; len++) { |
|
177
|
4532412
|
|
|
|
|
|
int bit = bitreader_read(br, 1); |
|
178
|
|
|
|
|
|
|
int count; |
|
179
|
4532412
|
50
|
|
|
|
|
if (bit < 0) return -1; |
|
180
|
|
|
|
|
|
|
|
|
181
|
4532412
|
|
|
|
|
|
code = (code << 1) | bit; |
|
182
|
4532412
|
|
|
|
|
|
count = h->counts[len]; |
|
183
|
|
|
|
|
|
|
|
|
184
|
4532412
|
100
|
|
|
|
|
if (code - first < count) { |
|
185
|
920172
|
|
|
|
|
|
return h->symbols[index + (code - first)]; |
|
186
|
|
|
|
|
|
|
} |
|
187
|
|
|
|
|
|
|
|
|
188
|
3612240
|
|
|
|
|
|
index += count; |
|
189
|
3612240
|
|
|
|
|
|
first = (first + count) << 1; |
|
190
|
|
|
|
|
|
|
} |
|
191
|
|
|
|
|
|
|
|
|
192
|
0
|
|
|
|
|
|
return -1; /* Invalid code */ |
|
193
|
|
|
|
|
|
|
} |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
/*============================================================================ |
|
196
|
|
|
|
|
|
|
* DEFLATE fixed Huffman codes |
|
197
|
|
|
|
|
|
|
*==========================================================================*/ |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
static huffman_t fixed_lit_len; |
|
200
|
|
|
|
|
|
|
static huffman_t fixed_dist; |
|
201
|
|
|
|
|
|
|
static int fixed_tables_built = 0; |
|
202
|
|
|
|
|
|
|
|
|
203
|
121
|
|
|
|
|
|
static void build_fixed_tables(void) |
|
204
|
|
|
|
|
|
|
{ |
|
205
|
|
|
|
|
|
|
int i; |
|
206
|
|
|
|
|
|
|
uint8_t lit_lengths[288]; |
|
207
|
|
|
|
|
|
|
uint8_t dist_lengths[32]; |
|
208
|
121
|
100
|
|
|
|
|
if (fixed_tables_built) return; |
|
209
|
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
/* Literal/length codes: 0-143=8 bits, 144-255=9 bits, 256-279=7 bits, 280-287=8 bits */ |
|
211
|
2175
|
100
|
|
|
|
|
for (i = 0; i <= 143; i++) lit_lengths[i] = 8; |
|
212
|
1695
|
100
|
|
|
|
|
for (i = 144; i <= 255; i++) lit_lengths[i] = 9; |
|
213
|
375
|
100
|
|
|
|
|
for (i = 256; i <= 279; i++) lit_lengths[i] = 7; |
|
214
|
135
|
100
|
|
|
|
|
for (i = 280; i <= 287; i++) lit_lengths[i] = 8; |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
/* Distance codes: all 5 bits */ |
|
217
|
495
|
100
|
|
|
|
|
for (i = 0; i < 32; i++) dist_lengths[i] = 5; |
|
218
|
|
|
|
|
|
|
|
|
219
|
15
|
|
|
|
|
|
huffman_build(&fixed_lit_len, lit_lengths, 288); |
|
220
|
15
|
|
|
|
|
|
huffman_build(&fixed_dist, dist_lengths, 32); |
|
221
|
|
|
|
|
|
|
|
|
222
|
15
|
|
|
|
|
|
fixed_tables_built = 1; |
|
223
|
|
|
|
|
|
|
} |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
/*============================================================================ |
|
226
|
|
|
|
|
|
|
* DEFLATE length/distance tables (RFC 1951) |
|
227
|
|
|
|
|
|
|
*==========================================================================*/ |
|
228
|
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
static const int length_base[29] = { |
|
230
|
|
|
|
|
|
|
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, |
|
231
|
|
|
|
|
|
|
15, 17, 19, 23, 27, 31, 35, 43, 51, 59, |
|
232
|
|
|
|
|
|
|
67, 83, 99, 115, 131, 163, 195, 227, 258 |
|
233
|
|
|
|
|
|
|
}; |
|
234
|
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
static const int length_extra[29] = { |
|
236
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, |
|
237
|
|
|
|
|
|
|
1, 1, 2, 2, 2, 2, 3, 3, 3, 3, |
|
238
|
|
|
|
|
|
|
4, 4, 4, 4, 5, 5, 5, 5, 0 |
|
239
|
|
|
|
|
|
|
}; |
|
240
|
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
static const int dist_base[30] = { |
|
242
|
|
|
|
|
|
|
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, |
|
243
|
|
|
|
|
|
|
33, 49, 65, 97, 129, 193, 257, 385, 513, 769, |
|
244
|
|
|
|
|
|
|
1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 |
|
245
|
|
|
|
|
|
|
}; |
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
static const int dist_extra[30] = { |
|
248
|
|
|
|
|
|
|
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, |
|
249
|
|
|
|
|
|
|
4, 4, 5, 5, 6, 6, 7, 7, 8, 8, |
|
250
|
|
|
|
|
|
|
9, 9, 10, 10, 11, 11, 12, 12, 13, 13 |
|
251
|
|
|
|
|
|
|
}; |
|
252
|
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
/* Code length code order (for dynamic Huffman) */ |
|
254
|
|
|
|
|
|
|
static const int cl_order[19] = { |
|
255
|
|
|
|
|
|
|
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 |
|
256
|
|
|
|
|
|
|
}; |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
/*============================================================================ |
|
259
|
|
|
|
|
|
|
* DEFLATE decoder |
|
260
|
|
|
|
|
|
|
*==========================================================================*/ |
|
261
|
|
|
|
|
|
|
|
|
262
|
502
|
|
|
|
|
|
static pdfmake_err_t inflate_block(bitreader_t *br, huffman_t *hl, huffman_t *hd, |
|
263
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
264
|
|
|
|
|
|
|
{ |
|
265
|
|
|
|
|
|
|
int sym; |
|
266
|
|
|
|
|
|
|
int len; |
|
267
|
|
|
|
|
|
|
int extra; |
|
268
|
|
|
|
|
|
|
int dist_sym; |
|
269
|
|
|
|
|
|
|
int dist; |
|
270
|
|
|
|
|
|
|
int i; |
|
271
|
|
|
|
|
|
|
uint8_t byte; |
|
272
|
|
|
|
|
|
|
for (;;) { |
|
273
|
610866
|
|
|
|
|
|
sym = huffman_decode(hl, br); |
|
274
|
610866
|
50
|
|
|
|
|
if (sym < 0) return PDFMAKE_ECORRUPT; |
|
275
|
|
|
|
|
|
|
|
|
276
|
610866
|
100
|
|
|
|
|
if (sym < 256) { |
|
277
|
|
|
|
|
|
|
/* Literal byte */ |
|
278
|
355316
|
50
|
|
|
|
|
if (pdfmake_buf_append_byte(out, (uint8_t)sym) != PDFMAKE_OK) |
|
279
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
280
|
|
|
|
|
|
|
} |
|
281
|
255550
|
100
|
|
|
|
|
else if (sym == 256) { |
|
282
|
|
|
|
|
|
|
/* End of block */ |
|
283
|
502
|
|
|
|
|
|
return PDFMAKE_OK; |
|
284
|
|
|
|
|
|
|
} |
|
285
|
|
|
|
|
|
|
else { |
|
286
|
|
|
|
|
|
|
/* Length/distance pair */ |
|
287
|
255048
|
|
|
|
|
|
sym -= 257; |
|
288
|
255048
|
50
|
|
|
|
|
if (sym >= 29) return PDFMAKE_ECORRUPT; |
|
289
|
|
|
|
|
|
|
|
|
290
|
255048
|
|
|
|
|
|
len = length_base[sym]; |
|
291
|
255048
|
100
|
|
|
|
|
if (length_extra[sym] > 0) { |
|
292
|
27338
|
|
|
|
|
|
extra = bitreader_read(br, length_extra[sym]); |
|
293
|
27338
|
50
|
|
|
|
|
if (extra < 0) return PDFMAKE_ECORRUPT; |
|
294
|
27338
|
|
|
|
|
|
len += extra; |
|
295
|
|
|
|
|
|
|
} |
|
296
|
|
|
|
|
|
|
|
|
297
|
255048
|
|
|
|
|
|
dist_sym = huffman_decode(hd, br); |
|
298
|
255048
|
50
|
|
|
|
|
if (dist_sym < 0 || dist_sym >= 30) return PDFMAKE_ECORRUPT; |
|
|
|
50
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
|
|
300
|
255048
|
|
|
|
|
|
dist = dist_base[dist_sym]; |
|
301
|
255048
|
100
|
|
|
|
|
if (dist_extra[dist_sym] > 0) { |
|
302
|
245075
|
|
|
|
|
|
extra = bitreader_read(br, dist_extra[dist_sym]); |
|
303
|
245075
|
50
|
|
|
|
|
if (extra < 0) return PDFMAKE_ECORRUPT; |
|
304
|
245075
|
|
|
|
|
|
dist += extra; |
|
305
|
|
|
|
|
|
|
} |
|
306
|
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
/* Copy from back-reference */ |
|
308
|
255048
|
50
|
|
|
|
|
if ((size_t)dist > out->len) return PDFMAKE_ECORRUPT; |
|
309
|
|
|
|
|
|
|
|
|
310
|
3583624
|
100
|
|
|
|
|
for (i = 0; i < len; i++) { |
|
311
|
3328576
|
|
|
|
|
|
byte = out->data[out->len - dist]; |
|
312
|
3328576
|
50
|
|
|
|
|
if (pdfmake_buf_append_byte(out, byte) != PDFMAKE_OK) |
|
313
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
314
|
|
|
|
|
|
|
} |
|
315
|
|
|
|
|
|
|
} |
|
316
|
|
|
|
|
|
|
} |
|
317
|
|
|
|
|
|
|
} |
|
318
|
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
/* Write `count` copies of `val` into lengths[n..target), saturating at target. |
|
320
|
|
|
|
|
|
|
* Shared by the three code-length repeat symbols (16/17/18) in the dynamic |
|
321
|
|
|
|
|
|
|
* Huffman block — each differs only in how `count` and `val` are derived. */ |
|
322
|
|
|
|
|
|
|
static PDFMAKE_INLINE int |
|
323
|
2613
|
|
|
|
|
|
deflate_fill_run(uint8_t *lengths, int n, int target, int count, uint8_t val) |
|
324
|
|
|
|
|
|
|
{ |
|
325
|
60323
|
100
|
|
|
|
|
while (count-- > 0 && n < target) lengths[n++] = val; |
|
|
|
50
|
|
|
|
|
|
|
326
|
2613
|
|
|
|
|
|
return n; |
|
327
|
|
|
|
|
|
|
} |
|
328
|
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
/* btype=0: uncompressed stored block. Aligns to the next byte boundary, |
|
330
|
|
|
|
|
|
|
* reads and copies len bytes verbatim into the output. */ |
|
331
|
|
|
|
|
|
|
static pdfmake_err_t |
|
332
|
3
|
|
|
|
|
|
inflate_stored_block(bitreader_t *br, pdfmake_buf_t *out) |
|
333
|
|
|
|
|
|
|
{ |
|
334
|
|
|
|
|
|
|
uint16_t len; |
|
335
|
|
|
|
|
|
|
uint16_t nlen; |
|
336
|
3
|
|
|
|
|
|
br->bits = 0; |
|
337
|
3
|
|
|
|
|
|
br->nbits = 0; /* Align to byte boundary */ |
|
338
|
|
|
|
|
|
|
|
|
339
|
3
|
50
|
|
|
|
|
if (br->pos + 4 > br->len) return PDFMAKE_ECORRUPT; |
|
340
|
3
|
|
|
|
|
|
len = br->data[br->pos] | ((uint16_t)br->data[br->pos + 1] << 8); |
|
341
|
3
|
|
|
|
|
|
nlen = br->data[br->pos + 2] | ((uint16_t)br->data[br->pos + 3] << 8); |
|
342
|
3
|
|
|
|
|
|
br->pos += 4; |
|
343
|
|
|
|
|
|
|
|
|
344
|
3
|
50
|
|
|
|
|
if (len != (uint16_t)~nlen) return PDFMAKE_ECORRUPT; |
|
345
|
3
|
50
|
|
|
|
|
if (br->pos + len > br->len) return PDFMAKE_ECORRUPT; |
|
346
|
|
|
|
|
|
|
|
|
347
|
3
|
50
|
|
|
|
|
if (pdfmake_buf_append(out, br->data + br->pos, len) != PDFMAKE_OK) |
|
348
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
349
|
3
|
|
|
|
|
|
br->pos += len; |
|
350
|
3
|
|
|
|
|
|
return PDFMAKE_OK; |
|
351
|
|
|
|
|
|
|
} |
|
352
|
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
/* btype=2: dynamic Huffman block. Decodes the code-length alphabet first, |
|
354
|
|
|
|
|
|
|
* then uses it to decode the literal/length and distance code tables, |
|
355
|
|
|
|
|
|
|
* then inflates the block body with those tables. */ |
|
356
|
|
|
|
|
|
|
static pdfmake_err_t |
|
357
|
360
|
|
|
|
|
|
inflate_dynamic_block(bitreader_t *br, pdfmake_buf_t *out) |
|
358
|
|
|
|
|
|
|
{ |
|
359
|
|
|
|
|
|
|
int hlit; |
|
360
|
|
|
|
|
|
|
int hdist; |
|
361
|
|
|
|
|
|
|
int hclen; |
|
362
|
|
|
|
|
|
|
uint8_t cl_lengths[19]; |
|
363
|
|
|
|
|
|
|
int i; |
|
364
|
|
|
|
|
|
|
huffman_t cl_huff; |
|
365
|
|
|
|
|
|
|
uint8_t lengths[288 + 32]; |
|
366
|
|
|
|
|
|
|
int n; |
|
367
|
|
|
|
|
|
|
int sym; |
|
368
|
|
|
|
|
|
|
int extra; |
|
369
|
|
|
|
|
|
|
huffman_t dyn_lit_len, dyn_dist; |
|
370
|
360
|
|
|
|
|
|
hlit = bitreader_read(br, 5); |
|
371
|
360
|
|
|
|
|
|
hdist = bitreader_read(br, 5); |
|
372
|
360
|
|
|
|
|
|
hclen = bitreader_read(br, 4); |
|
373
|
360
|
50
|
|
|
|
|
if (hlit < 0 || hdist < 0 || hclen < 0) return PDFMAKE_ECORRUPT; |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
374
|
360
|
|
|
|
|
|
hlit += 257; |
|
375
|
360
|
|
|
|
|
|
hdist += 1; |
|
376
|
360
|
|
|
|
|
|
hclen += 4; |
|
377
|
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
/* Code-length alphabet (19 symbols, stored in cl_order[]). */ |
|
379
|
360
|
|
|
|
|
|
memset(cl_lengths, 0, sizeof(cl_lengths)); |
|
380
|
5630
|
100
|
|
|
|
|
for (i = 0; i < hclen; i++) { |
|
381
|
5270
|
|
|
|
|
|
int code_len = bitreader_read(br, 3); |
|
382
|
5270
|
50
|
|
|
|
|
if (code_len < 0) return PDFMAKE_ECORRUPT; |
|
383
|
5270
|
|
|
|
|
|
cl_lengths[cl_order[i]] = (uint8_t)code_len; |
|
384
|
|
|
|
|
|
|
} |
|
385
|
|
|
|
|
|
|
|
|
386
|
360
|
50
|
|
|
|
|
if (huffman_build(&cl_huff, cl_lengths, 19) < 0) return PDFMAKE_ECORRUPT; |
|
387
|
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
/* Literal/length + distance code lengths. */ |
|
389
|
360
|
|
|
|
|
|
n = 0; |
|
390
|
54618
|
100
|
|
|
|
|
while (n < hlit + hdist) { |
|
391
|
54258
|
|
|
|
|
|
sym = huffman_decode(&cl_huff, br); |
|
392
|
54258
|
50
|
|
|
|
|
if (sym < 0) return PDFMAKE_ECORRUPT; |
|
393
|
|
|
|
|
|
|
|
|
394
|
54258
|
100
|
|
|
|
|
if (sym < 16) { |
|
395
|
51645
|
|
|
|
|
|
lengths[n++] = (uint8_t)sym; |
|
396
|
2613
|
100
|
|
|
|
|
} else if (sym == 16) { |
|
397
|
1258
|
|
|
|
|
|
extra = bitreader_read(br, 2); |
|
398
|
1258
|
50
|
|
|
|
|
if (extra < 0 || n == 0) return PDFMAKE_ECORRUPT; |
|
|
|
50
|
|
|
|
|
|
|
399
|
1258
|
|
|
|
|
|
n = deflate_fill_run(lengths, n, hlit + hdist, |
|
400
|
1258
|
|
|
|
|
|
extra + 3, lengths[n - 1]); |
|
401
|
1355
|
100
|
|
|
|
|
} else if (sym == 17) { |
|
402
|
847
|
|
|
|
|
|
extra = bitreader_read(br, 3); |
|
403
|
847
|
50
|
|
|
|
|
if (extra < 0) return PDFMAKE_ECORRUPT; |
|
404
|
847
|
|
|
|
|
|
n = deflate_fill_run(lengths, n, hlit + hdist, extra + 3, 0); |
|
405
|
508
|
50
|
|
|
|
|
} else if (sym == 18) { |
|
406
|
508
|
|
|
|
|
|
extra = bitreader_read(br, 7); |
|
407
|
508
|
50
|
|
|
|
|
if (extra < 0) return PDFMAKE_ECORRUPT; |
|
408
|
508
|
|
|
|
|
|
n = deflate_fill_run(lengths, n, hlit + hdist, extra + 11, 0); |
|
409
|
|
|
|
|
|
|
} |
|
410
|
|
|
|
|
|
|
} |
|
411
|
|
|
|
|
|
|
|
|
412
|
360
|
50
|
|
|
|
|
if (huffman_build(&dyn_lit_len, lengths, hlit) < 0) return PDFMAKE_ECORRUPT; |
|
413
|
360
|
50
|
|
|
|
|
if (huffman_build(&dyn_dist, lengths + hlit, hdist) < 0) return PDFMAKE_ECORRUPT; |
|
414
|
|
|
|
|
|
|
|
|
415
|
360
|
|
|
|
|
|
return inflate_block(br, &dyn_lit_len, &dyn_dist, out); |
|
416
|
|
|
|
|
|
|
} |
|
417
|
|
|
|
|
|
|
|
|
418
|
121
|
|
|
|
|
|
pdfmake_err_t pdfmake_deflate_decode(const uint8_t *in, size_t in_len, |
|
419
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
420
|
|
|
|
|
|
|
{ |
|
421
|
|
|
|
|
|
|
bitreader_t br; |
|
422
|
|
|
|
|
|
|
int bfinal; |
|
423
|
|
|
|
|
|
|
int btype; |
|
424
|
|
|
|
|
|
|
pdfmake_err_t err; |
|
425
|
121
|
50
|
|
|
|
|
if (!in || !out) return PDFMAKE_EINVAL; |
|
|
|
50
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
|
|
427
|
121
|
|
|
|
|
|
bitreader_init(&br, in, in_len); |
|
428
|
121
|
|
|
|
|
|
build_fixed_tables(); |
|
429
|
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
do { |
|
431
|
506
|
|
|
|
|
|
bfinal = bitreader_read(&br, 1); |
|
432
|
506
|
|
|
|
|
|
btype = bitreader_read(&br, 2); |
|
433
|
506
|
100
|
|
|
|
|
if (bfinal < 0 || btype < 0) return PDFMAKE_ECORRUPT; |
|
|
|
50
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
|
|
435
|
505
|
|
|
|
|
|
switch (btype) { |
|
436
|
3
|
|
|
|
|
|
case 0: err = inflate_stored_block(&br, out); break; |
|
437
|
142
|
|
|
|
|
|
case 1: err = inflate_block(&br, &fixed_lit_len, &fixed_dist, out); break; |
|
438
|
360
|
|
|
|
|
|
case 2: err = inflate_dynamic_block(&br, out); break; |
|
439
|
0
|
|
|
|
|
|
default: return PDFMAKE_ECORRUPT; /* btype == 3 is reserved */ |
|
440
|
|
|
|
|
|
|
} |
|
441
|
505
|
50
|
|
|
|
|
if (err != PDFMAKE_OK) return err; |
|
442
|
505
|
100
|
|
|
|
|
} while (!bfinal); |
|
443
|
|
|
|
|
|
|
|
|
444
|
120
|
|
|
|
|
|
return PDFMAKE_OK; |
|
445
|
|
|
|
|
|
|
} |
|
446
|
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
/*============================================================================ |
|
448
|
|
|
|
|
|
|
* DEFLATE encoder (store-only for now, then static Huffman) |
|
449
|
|
|
|
|
|
|
*==========================================================================*/ |
|
450
|
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
typedef struct { |
|
452
|
|
|
|
|
|
|
pdfmake_buf_t *out; |
|
453
|
|
|
|
|
|
|
uint32_t bits; |
|
454
|
|
|
|
|
|
|
int nbits; |
|
455
|
|
|
|
|
|
|
} bitwriter_t; |
|
456
|
|
|
|
|
|
|
|
|
457
|
31
|
|
|
|
|
|
static void bitwriter_init(bitwriter_t *bw, pdfmake_buf_t *out) |
|
458
|
|
|
|
|
|
|
{ |
|
459
|
31
|
|
|
|
|
|
bw->out = out; |
|
460
|
31
|
|
|
|
|
|
bw->bits = 0; |
|
461
|
31
|
|
|
|
|
|
bw->nbits = 0; |
|
462
|
31
|
|
|
|
|
|
} |
|
463
|
|
|
|
|
|
|
|
|
464
|
886834
|
|
|
|
|
|
static pdfmake_err_t bitwriter_write(bitwriter_t *bw, int val, int n) |
|
465
|
|
|
|
|
|
|
{ |
|
466
|
886834
|
|
|
|
|
|
bw->bits |= (uint32_t)val << bw->nbits; |
|
467
|
886834
|
|
|
|
|
|
bw->nbits += n; |
|
468
|
|
|
|
|
|
|
|
|
469
|
1711101
|
100
|
|
|
|
|
while (bw->nbits >= 8) { |
|
470
|
824267
|
50
|
|
|
|
|
if (pdfmake_buf_append_byte(bw->out, bw->bits & 0xFF) != PDFMAKE_OK) |
|
471
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
472
|
824267
|
|
|
|
|
|
bw->bits >>= 8; |
|
473
|
824267
|
|
|
|
|
|
bw->nbits -= 8; |
|
474
|
|
|
|
|
|
|
} |
|
475
|
|
|
|
|
|
|
|
|
476
|
886834
|
|
|
|
|
|
return PDFMAKE_OK; |
|
477
|
|
|
|
|
|
|
} |
|
478
|
|
|
|
|
|
|
|
|
479
|
31
|
|
|
|
|
|
static pdfmake_err_t bitwriter_flush(bitwriter_t *bw) |
|
480
|
|
|
|
|
|
|
{ |
|
481
|
31
|
100
|
|
|
|
|
if (bw->nbits > 0) { |
|
482
|
14
|
50
|
|
|
|
|
if (pdfmake_buf_append_byte(bw->out, bw->bits & 0xFF) != PDFMAKE_OK) |
|
483
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
484
|
14
|
|
|
|
|
|
bw->bits = 0; |
|
485
|
14
|
|
|
|
|
|
bw->nbits = 0; |
|
486
|
|
|
|
|
|
|
} |
|
487
|
31
|
|
|
|
|
|
return PDFMAKE_OK; |
|
488
|
|
|
|
|
|
|
} |
|
489
|
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
/* Reverse bits for Huffman encoding */ |
|
491
|
2544
|
|
|
|
|
|
static uint16_t reverse_bits(uint16_t val, int n) |
|
492
|
|
|
|
|
|
|
{ |
|
493
|
2544
|
|
|
|
|
|
uint16_t rev = 0; |
|
494
|
|
|
|
|
|
|
int i; |
|
495
|
22880
|
100
|
|
|
|
|
for (i = 0; i < n; i++) { |
|
496
|
20336
|
|
|
|
|
|
rev = (rev << 1) | (val & 1); |
|
497
|
20336
|
|
|
|
|
|
val >>= 1; |
|
498
|
|
|
|
|
|
|
} |
|
499
|
2544
|
|
|
|
|
|
return rev; |
|
500
|
|
|
|
|
|
|
} |
|
501
|
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
/* Fixed Huffman code tables for encoding */ |
|
503
|
|
|
|
|
|
|
static uint16_t fixed_lit_codes[288]; |
|
504
|
|
|
|
|
|
|
static uint8_t fixed_lit_bits[288]; |
|
505
|
|
|
|
|
|
|
static uint16_t fixed_dist_codes[30]; |
|
506
|
|
|
|
|
|
|
static uint8_t fixed_dist_bits[30]; |
|
507
|
|
|
|
|
|
|
static int fixed_encode_tables_built = 0; |
|
508
|
|
|
|
|
|
|
|
|
509
|
31
|
|
|
|
|
|
static void build_fixed_encode_tables(void) |
|
510
|
|
|
|
|
|
|
{ |
|
511
|
|
|
|
|
|
|
int i; |
|
512
|
|
|
|
|
|
|
uint16_t code; |
|
513
|
31
|
100
|
|
|
|
|
if (fixed_encode_tables_built) return; |
|
514
|
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
/* Literal/length codes */ |
|
516
|
8
|
|
|
|
|
|
code = 0; |
|
517
|
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
/* 256-279: 7 bits starting at 0000000 */ |
|
519
|
200
|
100
|
|
|
|
|
for (i = 256; i <= 279; i++) { |
|
520
|
192
|
|
|
|
|
|
fixed_lit_codes[i] = reverse_bits(code++, 7); |
|
521
|
192
|
|
|
|
|
|
fixed_lit_bits[i] = 7; |
|
522
|
|
|
|
|
|
|
} |
|
523
|
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
/* 0-143: 8 bits starting at 00110000 */ |
|
525
|
8
|
|
|
|
|
|
code = 0x30; |
|
526
|
1160
|
100
|
|
|
|
|
for (i = 0; i <= 143; i++) { |
|
527
|
1152
|
|
|
|
|
|
fixed_lit_codes[i] = reverse_bits(code++, 8); |
|
528
|
1152
|
|
|
|
|
|
fixed_lit_bits[i] = 8; |
|
529
|
|
|
|
|
|
|
} |
|
530
|
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
/* 280-287: 8 bits starting at 11000000 */ |
|
532
|
8
|
|
|
|
|
|
code = 0xC0; |
|
533
|
72
|
100
|
|
|
|
|
for (i = 280; i <= 287; i++) { |
|
534
|
64
|
|
|
|
|
|
fixed_lit_codes[i] = reverse_bits(code++, 8); |
|
535
|
64
|
|
|
|
|
|
fixed_lit_bits[i] = 8; |
|
536
|
|
|
|
|
|
|
} |
|
537
|
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
/* 144-255: 9 bits starting at 110010000 */ |
|
539
|
8
|
|
|
|
|
|
code = 0x190; |
|
540
|
904
|
100
|
|
|
|
|
for (i = 144; i <= 255; i++) { |
|
541
|
896
|
|
|
|
|
|
fixed_lit_codes[i] = reverse_bits(code++, 9); |
|
542
|
896
|
|
|
|
|
|
fixed_lit_bits[i] = 9; |
|
543
|
|
|
|
|
|
|
} |
|
544
|
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
/* Distance codes: all 5 bits starting at 00000 */ |
|
546
|
248
|
100
|
|
|
|
|
for (i = 0; i < 30; i++) { |
|
547
|
240
|
|
|
|
|
|
fixed_dist_codes[i] = reverse_bits(i, 5); |
|
548
|
240
|
|
|
|
|
|
fixed_dist_bits[i] = 5; |
|
549
|
|
|
|
|
|
|
} |
|
550
|
|
|
|
|
|
|
|
|
551
|
8
|
|
|
|
|
|
fixed_encode_tables_built = 1; |
|
552
|
|
|
|
|
|
|
} |
|
553
|
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
/* Find length code for a given length (3-258) */ |
|
555
|
260274
|
|
|
|
|
|
static int find_length_code(int length) |
|
556
|
|
|
|
|
|
|
{ |
|
557
|
|
|
|
|
|
|
int i; |
|
558
|
712936
|
50
|
|
|
|
|
for (i = 0; i < 29; i++) { |
|
559
|
712936
|
|
|
|
|
|
int max_len = length_base[i] + (1 << length_extra[i]) - 1; |
|
560
|
712936
|
100
|
|
|
|
|
if (length <= max_len) return i; |
|
561
|
|
|
|
|
|
|
} |
|
562
|
0
|
|
|
|
|
|
return 28; /* Max length */ |
|
563
|
|
|
|
|
|
|
} |
|
564
|
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
/* Find distance code for a given distance (1-32768) */ |
|
566
|
260274
|
|
|
|
|
|
static int find_dist_code(int dist) |
|
567
|
|
|
|
|
|
|
{ |
|
568
|
|
|
|
|
|
|
int i; |
|
569
|
6085917
|
50
|
|
|
|
|
for (i = 0; i < 30; i++) { |
|
570
|
6085917
|
|
|
|
|
|
int max_dist = dist_base[i] + (1 << dist_extra[i]) - 1; |
|
571
|
6085917
|
100
|
|
|
|
|
if (dist <= max_dist) return i; |
|
572
|
|
|
|
|
|
|
} |
|
573
|
0
|
|
|
|
|
|
return 29; /* Max distance */ |
|
574
|
|
|
|
|
|
|
} |
|
575
|
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------- |
|
577
|
|
|
|
|
|
|
* LZ77 hash chain implementation |
|
578
|
|
|
|
|
|
|
*--------------------------------------------------------------------------*/ |
|
579
|
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
#define HASH_BITS 15 |
|
581
|
|
|
|
|
|
|
#define HASH_SIZE (1 << HASH_BITS) |
|
582
|
|
|
|
|
|
|
#define HASH_MASK (HASH_SIZE - 1) |
|
583
|
|
|
|
|
|
|
#define WINDOW_SIZE 32768 |
|
584
|
|
|
|
|
|
|
#define MIN_MATCH 3 |
|
585
|
|
|
|
|
|
|
#define MAX_MATCH 258 |
|
586
|
|
|
|
|
|
|
#define MAX_CHAIN 128 /* Max hash chain length to search */ |
|
587
|
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
typedef struct { |
|
589
|
|
|
|
|
|
|
const uint8_t *data; |
|
590
|
|
|
|
|
|
|
size_t len; |
|
591
|
|
|
|
|
|
|
int head[HASH_SIZE]; |
|
592
|
|
|
|
|
|
|
int prev[WINDOW_SIZE]; |
|
593
|
|
|
|
|
|
|
size_t pos; |
|
594
|
|
|
|
|
|
|
} lz77_t; |
|
595
|
|
|
|
|
|
|
|
|
596
|
29
|
|
|
|
|
|
static void lz77_init(lz77_t *lz, const uint8_t *data, size_t len) |
|
597
|
|
|
|
|
|
|
{ |
|
598
|
29
|
|
|
|
|
|
lz->data = data; |
|
599
|
29
|
|
|
|
|
|
lz->len = len; |
|
600
|
29
|
|
|
|
|
|
lz->pos = 0; |
|
601
|
29
|
|
|
|
|
|
memset(lz->head, -1, sizeof(lz->head)); |
|
602
|
29
|
|
|
|
|
|
memset(lz->prev, -1, sizeof(lz->prev)); |
|
603
|
29
|
|
|
|
|
|
} |
|
604
|
|
|
|
|
|
|
|
|
605
|
2215311
|
|
|
|
|
|
static int lz77_hash(const uint8_t *data) |
|
606
|
|
|
|
|
|
|
{ |
|
607
|
2215311
|
|
|
|
|
|
return ((data[0] << 10) ^ (data[1] << 5) ^ data[2]) & HASH_MASK; |
|
608
|
|
|
|
|
|
|
} |
|
609
|
|
|
|
|
|
|
|
|
610
|
1857052
|
|
|
|
|
|
static void lz77_insert(lz77_t *lz, size_t pos) |
|
611
|
|
|
|
|
|
|
{ |
|
612
|
|
|
|
|
|
|
int h; |
|
613
|
1857052
|
100
|
|
|
|
|
if (pos + 2 >= lz->len) return; |
|
614
|
|
|
|
|
|
|
|
|
615
|
1856995
|
|
|
|
|
|
h = lz77_hash(lz->data + pos); |
|
616
|
1856995
|
|
|
|
|
|
lz->prev[pos & (WINDOW_SIZE - 1)] = lz->head[h]; |
|
617
|
1856995
|
|
|
|
|
|
lz->head[h] = (int)pos; |
|
618
|
|
|
|
|
|
|
} |
|
619
|
|
|
|
|
|
|
|
|
620
|
358333
|
|
|
|
|
|
static int lz77_find_match(lz77_t *lz, size_t pos, int *match_dist, int *match_len) |
|
621
|
|
|
|
|
|
|
{ |
|
622
|
|
|
|
|
|
|
int h; |
|
623
|
|
|
|
|
|
|
int chain_len; |
|
624
|
|
|
|
|
|
|
int match_pos; |
|
625
|
|
|
|
|
|
|
int dist; |
|
626
|
|
|
|
|
|
|
const uint8_t *a; |
|
627
|
|
|
|
|
|
|
const uint8_t *b; |
|
628
|
|
|
|
|
|
|
int len; |
|
629
|
|
|
|
|
|
|
size_t max_len; |
|
630
|
358333
|
|
|
|
|
|
*match_len = 0; |
|
631
|
358333
|
|
|
|
|
|
*match_dist = 0; |
|
632
|
|
|
|
|
|
|
|
|
633
|
358333
|
100
|
|
|
|
|
if (pos + MIN_MATCH > lz->len) return 0; |
|
634
|
|
|
|
|
|
|
|
|
635
|
358316
|
|
|
|
|
|
h = lz77_hash(lz->data + pos); |
|
636
|
358316
|
|
|
|
|
|
chain_len = 0; |
|
637
|
358316
|
|
|
|
|
|
match_pos = lz->head[h]; |
|
638
|
|
|
|
|
|
|
|
|
639
|
9015036
|
100
|
|
|
|
|
while (match_pos >= 0 && chain_len < MAX_CHAIN) { |
|
|
|
100
|
|
|
|
|
|
|
640
|
8800919
|
|
|
|
|
|
dist = (int)pos - match_pos; |
|
641
|
8800919
|
100
|
|
|
|
|
if (dist > WINDOW_SIZE) break; |
|
642
|
8657414
|
50
|
|
|
|
|
if (dist <= 0) break; |
|
643
|
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
/* Check match */ |
|
645
|
8657414
|
|
|
|
|
|
a = lz->data + pos; |
|
646
|
8657414
|
|
|
|
|
|
b = lz->data + match_pos; |
|
647
|
8657414
|
|
|
|
|
|
len = 0; |
|
648
|
|
|
|
|
|
|
|
|
649
|
8657414
|
|
|
|
|
|
max_len = lz->len - pos; |
|
650
|
8657414
|
100
|
|
|
|
|
if (max_len > MAX_MATCH) max_len = MAX_MATCH; |
|
651
|
|
|
|
|
|
|
|
|
652
|
53434691
|
100
|
|
|
|
|
while ((size_t)len < max_len && a[len] == b[len]) len++; |
|
|
|
100
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
|
|
654
|
8657414
|
100
|
|
|
|
|
if (len >= MIN_MATCH && len > *match_len) { |
|
|
|
100
|
|
|
|
|
|
|
655
|
443469
|
|
|
|
|
|
*match_len = len; |
|
656
|
443469
|
|
|
|
|
|
*match_dist = dist; |
|
657
|
443469
|
100
|
|
|
|
|
if (len >= MAX_MATCH) break; |
|
658
|
|
|
|
|
|
|
} |
|
659
|
|
|
|
|
|
|
|
|
660
|
8656720
|
|
|
|
|
|
match_pos = lz->prev[match_pos & (WINDOW_SIZE - 1)]; |
|
661
|
8656720
|
|
|
|
|
|
chain_len++; |
|
662
|
|
|
|
|
|
|
} |
|
663
|
|
|
|
|
|
|
|
|
664
|
358316
|
|
|
|
|
|
return *match_len >= MIN_MATCH; |
|
665
|
|
|
|
|
|
|
} |
|
666
|
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------- |
|
668
|
|
|
|
|
|
|
* DEFLATE encoder with LZ77 |
|
669
|
|
|
|
|
|
|
*--------------------------------------------------------------------------*/ |
|
670
|
|
|
|
|
|
|
|
|
671
|
32
|
|
|
|
|
|
pdfmake_err_t pdfmake_deflate_encode(const uint8_t *in, size_t in_len, |
|
672
|
|
|
|
|
|
|
int level, |
|
673
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
674
|
|
|
|
|
|
|
{ |
|
675
|
|
|
|
|
|
|
bitwriter_t bw; |
|
676
|
|
|
|
|
|
|
size_t pos; |
|
677
|
32
|
50
|
|
|
|
|
if (!out) return PDFMAKE_EINVAL; |
|
678
|
32
|
100
|
|
|
|
|
if (in_len == 0) { |
|
679
|
|
|
|
|
|
|
/* Empty input: single empty stored block */ |
|
680
|
1
|
|
|
|
|
|
uint8_t empty[] = {0x01, 0x00, 0x00, 0xFF, 0xFF}; |
|
681
|
1
|
|
|
|
|
|
return pdfmake_buf_append(out, empty, 5); |
|
682
|
|
|
|
|
|
|
} |
|
683
|
|
|
|
|
|
|
|
|
684
|
31
|
|
|
|
|
|
build_fixed_encode_tables(); |
|
685
|
|
|
|
|
|
|
|
|
686
|
31
|
|
|
|
|
|
bitwriter_init(&bw, out); |
|
687
|
|
|
|
|
|
|
|
|
688
|
31
|
100
|
|
|
|
|
if (level == 0) { |
|
689
|
|
|
|
|
|
|
uint16_t len; |
|
690
|
|
|
|
|
|
|
uint16_t nlen; |
|
691
|
|
|
|
|
|
|
int bfinal; |
|
692
|
|
|
|
|
|
|
size_t block_len; |
|
693
|
|
|
|
|
|
|
/* Store-only: emit stored blocks */ |
|
694
|
2
|
|
|
|
|
|
pos = 0; |
|
695
|
4
|
100
|
|
|
|
|
while (pos < in_len) { |
|
696
|
2
|
|
|
|
|
|
block_len = in_len - pos; |
|
697
|
2
|
50
|
|
|
|
|
if (block_len > 65535) block_len = 65535; |
|
698
|
|
|
|
|
|
|
|
|
699
|
2
|
|
|
|
|
|
bfinal = (pos + block_len >= in_len) ? 1 : 0; |
|
700
|
2
|
|
|
|
|
|
bitwriter_write(&bw, bfinal, 1); |
|
701
|
2
|
|
|
|
|
|
bitwriter_write(&bw, 0, 2); /* btype = 0 (stored) */ |
|
702
|
2
|
|
|
|
|
|
bitwriter_flush(&bw); |
|
703
|
|
|
|
|
|
|
|
|
704
|
2
|
|
|
|
|
|
len = (uint16_t)block_len; |
|
705
|
2
|
|
|
|
|
|
nlen = ~len; |
|
706
|
2
|
|
|
|
|
|
pdfmake_buf_append_byte(out, len & 0xFF); |
|
707
|
2
|
|
|
|
|
|
pdfmake_buf_append_byte(out, (len >> 8) & 0xFF); |
|
708
|
2
|
|
|
|
|
|
pdfmake_buf_append_byte(out, nlen & 0xFF); |
|
709
|
2
|
|
|
|
|
|
pdfmake_buf_append_byte(out, (nlen >> 8) & 0xFF); |
|
710
|
2
|
|
|
|
|
|
pdfmake_buf_append(out, in + pos, block_len); |
|
711
|
|
|
|
|
|
|
|
|
712
|
2
|
|
|
|
|
|
pos += block_len; |
|
713
|
|
|
|
|
|
|
} |
|
714
|
|
|
|
|
|
|
} |
|
715
|
|
|
|
|
|
|
else { |
|
716
|
|
|
|
|
|
|
lz77_t lz; |
|
717
|
|
|
|
|
|
|
/* LZ77 + fixed Huffman (level 1-9 all use this for now) */ |
|
718
|
|
|
|
|
|
|
int match_dist, match_len; |
|
719
|
|
|
|
|
|
|
int len_code; |
|
720
|
|
|
|
|
|
|
int dist_code; |
|
721
|
|
|
|
|
|
|
int extra; |
|
722
|
|
|
|
|
|
|
int i; |
|
723
|
29
|
|
|
|
|
|
lz77_init(&lz, in, in_len); |
|
724
|
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
/* Single block with fixed Huffman */ |
|
726
|
29
|
|
|
|
|
|
bitwriter_write(&bw, 1, 1); /* bfinal = 1 */ |
|
727
|
29
|
|
|
|
|
|
bitwriter_write(&bw, 1, 2); /* btype = 1 (fixed Huffman) */ |
|
728
|
|
|
|
|
|
|
|
|
729
|
29
|
|
|
|
|
|
pos = 0; |
|
730
|
358362
|
100
|
|
|
|
|
while (pos < in_len) { |
|
731
|
358333
|
100
|
|
|
|
|
if (lz77_find_match(&lz, pos, &match_dist, &match_len)) { |
|
732
|
|
|
|
|
|
|
/* Emit length/distance pair */ |
|
733
|
260274
|
|
|
|
|
|
len_code = find_length_code(match_len); |
|
734
|
260274
|
|
|
|
|
|
bitwriter_write(&bw, fixed_lit_codes[257 + len_code], |
|
735
|
260274
|
|
|
|
|
|
fixed_lit_bits[257 + len_code]); |
|
736
|
260274
|
100
|
|
|
|
|
if (length_extra[len_code] > 0) { |
|
737
|
11934
|
|
|
|
|
|
extra = match_len - length_base[len_code]; |
|
738
|
11934
|
|
|
|
|
|
bitwriter_write(&bw, extra, length_extra[len_code]); |
|
739
|
|
|
|
|
|
|
} |
|
740
|
|
|
|
|
|
|
|
|
741
|
260274
|
|
|
|
|
|
dist_code = find_dist_code(match_dist); |
|
742
|
260274
|
|
|
|
|
|
bitwriter_write(&bw, fixed_dist_codes[dist_code], |
|
743
|
260274
|
|
|
|
|
|
fixed_dist_bits[dist_code]); |
|
744
|
260274
|
100
|
|
|
|
|
if (dist_extra[dist_code] > 0) { |
|
745
|
256202
|
|
|
|
|
|
extra = match_dist - dist_base[dist_code]; |
|
746
|
256202
|
|
|
|
|
|
bitwriter_write(&bw, extra, dist_extra[dist_code]); |
|
747
|
|
|
|
|
|
|
} |
|
748
|
|
|
|
|
|
|
|
|
749
|
|
|
|
|
|
|
/* Insert all positions in the match into hash */ |
|
750
|
2019267
|
100
|
|
|
|
|
for (i = 0; i < match_len; i++) { |
|
751
|
1758993
|
|
|
|
|
|
lz77_insert(&lz, pos + i); |
|
752
|
|
|
|
|
|
|
} |
|
753
|
260274
|
|
|
|
|
|
pos += match_len; |
|
754
|
|
|
|
|
|
|
} |
|
755
|
|
|
|
|
|
|
else { |
|
756
|
|
|
|
|
|
|
/* Emit literal */ |
|
757
|
98059
|
|
|
|
|
|
bitwriter_write(&bw, fixed_lit_codes[in[pos]], |
|
758
|
98059
|
|
|
|
|
|
fixed_lit_bits[in[pos]]); |
|
759
|
98059
|
|
|
|
|
|
lz77_insert(&lz, pos); |
|
760
|
98059
|
|
|
|
|
|
pos++; |
|
761
|
|
|
|
|
|
|
} |
|
762
|
|
|
|
|
|
|
} |
|
763
|
|
|
|
|
|
|
|
|
764
|
|
|
|
|
|
|
/* End of block */ |
|
765
|
29
|
|
|
|
|
|
bitwriter_write(&bw, fixed_lit_codes[256], fixed_lit_bits[256]); |
|
766
|
29
|
|
|
|
|
|
bitwriter_flush(&bw); |
|
767
|
|
|
|
|
|
|
} |
|
768
|
|
|
|
|
|
|
|
|
769
|
31
|
|
|
|
|
|
return PDFMAKE_OK; |
|
770
|
|
|
|
|
|
|
} |
|
771
|
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
/*============================================================================ |
|
773
|
|
|
|
|
|
|
* zlib wrapper (RFC 1950) |
|
774
|
|
|
|
|
|
|
*==========================================================================*/ |
|
775
|
|
|
|
|
|
|
|
|
776
|
116
|
|
|
|
|
|
pdfmake_err_t pdfmake_flate_decode(const uint8_t *in, size_t in_len, |
|
777
|
|
|
|
|
|
|
const pdfmake_flate_params_t *params, |
|
778
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
779
|
|
|
|
|
|
|
{ |
|
780
|
|
|
|
|
|
|
uint8_t cmf; |
|
781
|
|
|
|
|
|
|
uint8_t flg; |
|
782
|
|
|
|
|
|
|
size_t deflate_len; |
|
783
|
|
|
|
|
|
|
pdfmake_buf_t raw; |
|
784
|
|
|
|
|
|
|
pdfmake_err_t err; |
|
785
|
116
|
50
|
|
|
|
|
if (!in || !out) return PDFMAKE_EINVAL; |
|
|
|
50
|
|
|
|
|
|
|
786
|
116
|
50
|
|
|
|
|
if (in_len < 6) return PDFMAKE_ECORRUPT; /* Min: 2 header + 4 Adler-32 */ |
|
787
|
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
/* Parse zlib header (CMF + FLG) */ |
|
789
|
116
|
|
|
|
|
|
cmf = in[0]; |
|
790
|
116
|
|
|
|
|
|
flg = in[1]; |
|
791
|
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
/* Check header checksum */ |
|
793
|
116
|
50
|
|
|
|
|
if ((cmf * 256 + flg) % 31 != 0) return PDFMAKE_ECORRUPT; |
|
794
|
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
/* Check compression method (CM = 8 = deflate) */ |
|
796
|
116
|
50
|
|
|
|
|
if ((cmf & 0x0F) != 8) return PDFMAKE_EUNSUPPORTED; |
|
797
|
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
/* Window size: CINFO = (cmf >> 4), window = 2^(CINFO+8) */ |
|
799
|
|
|
|
|
|
|
/* We support all window sizes */ |
|
800
|
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
/* FDICT bit (preset dictionary): not supported */ |
|
802
|
116
|
50
|
|
|
|
|
if (flg & 0x20) return PDFMAKE_EUNSUPPORTED; |
|
803
|
|
|
|
|
|
|
|
|
804
|
|
|
|
|
|
|
/* Decompress DEFLATE data */ |
|
805
|
116
|
|
|
|
|
|
deflate_len = in_len - 6; /* Skip header (2) and trailer (4) */ |
|
806
|
116
|
50
|
|
|
|
|
if (pdfmake_buf_init(&raw) != PDFMAKE_OK) return PDFMAKE_ENOMEM; |
|
807
|
|
|
|
|
|
|
|
|
808
|
116
|
|
|
|
|
|
err = pdfmake_deflate_decode(in + 2, deflate_len, &raw); |
|
809
|
116
|
100
|
|
|
|
|
if (err != PDFMAKE_OK) { |
|
810
|
1
|
|
|
|
|
|
pdfmake_buf_free(&raw); |
|
811
|
1
|
|
|
|
|
|
return err; |
|
812
|
|
|
|
|
|
|
} |
|
813
|
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
/* Note: Adler-32 checksum verification is skipped. |
|
815
|
|
|
|
|
|
|
* PDF stream /Length values don't always align with the zlib trailer |
|
816
|
|
|
|
|
|
|
* position, and many real-world PDFs have mismatched checksums. |
|
817
|
|
|
|
|
|
|
* The DEFLATE decoder's own consistency checks are sufficient. */ |
|
818
|
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
/* Apply predictor if needed */ |
|
820
|
115
|
50
|
|
|
|
|
if (params && params->predictor > 1) { |
|
|
|
50
|
|
|
|
|
|
|
821
|
|
|
|
|
|
|
pdfmake_buf_t pred_out; |
|
822
|
0
|
0
|
|
|
|
|
if (pdfmake_buf_init(&pred_out) != PDFMAKE_OK) { |
|
823
|
0
|
|
|
|
|
|
pdfmake_buf_free(&raw); |
|
824
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
825
|
|
|
|
|
|
|
} |
|
826
|
|
|
|
|
|
|
|
|
827
|
0
|
0
|
|
|
|
|
if (params->predictor == 2) { |
|
828
|
0
|
|
|
|
|
|
err = pdfmake_tiff_predictor_decode(params->colors, |
|
829
|
0
|
|
|
|
|
|
params->bits_per_comp, |
|
830
|
0
|
|
|
|
|
|
params->columns, |
|
831
|
0
|
|
|
|
|
|
raw.data, raw.len, &pred_out); |
|
832
|
0
|
0
|
|
|
|
|
} else if (params->predictor >= 10 && params->predictor <= 15) { |
|
|
|
0
|
|
|
|
|
|
|
833
|
0
|
|
|
|
|
|
err = pdfmake_predictor_decode(params->predictor, |
|
834
|
0
|
|
|
|
|
|
params->colors, |
|
835
|
0
|
|
|
|
|
|
params->bits_per_comp, |
|
836
|
0
|
|
|
|
|
|
params->columns, |
|
837
|
0
|
|
|
|
|
|
raw.data, raw.len, &pred_out); |
|
838
|
|
|
|
|
|
|
} else { |
|
839
|
0
|
|
|
|
|
|
err = PDFMAKE_EINVAL; |
|
840
|
|
|
|
|
|
|
} |
|
841
|
|
|
|
|
|
|
|
|
842
|
0
|
|
|
|
|
|
pdfmake_buf_free(&raw); |
|
843
|
0
|
0
|
|
|
|
|
if (err != PDFMAKE_OK) { |
|
844
|
0
|
|
|
|
|
|
pdfmake_buf_free(&pred_out); |
|
845
|
0
|
|
|
|
|
|
return err; |
|
846
|
|
|
|
|
|
|
} |
|
847
|
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
/* Move predictor output to main output */ |
|
849
|
0
|
0
|
|
|
|
|
if (pdfmake_buf_append(out, pred_out.data, pred_out.len) != PDFMAKE_OK) { |
|
850
|
0
|
|
|
|
|
|
pdfmake_buf_free(&pred_out); |
|
851
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
852
|
|
|
|
|
|
|
} |
|
853
|
0
|
|
|
|
|
|
pdfmake_buf_free(&pred_out); |
|
854
|
|
|
|
|
|
|
} |
|
855
|
|
|
|
|
|
|
else { |
|
856
|
|
|
|
|
|
|
/* No predictor */ |
|
857
|
115
|
50
|
|
|
|
|
if (pdfmake_buf_append(out, raw.data, raw.len) != PDFMAKE_OK) { |
|
858
|
0
|
|
|
|
|
|
pdfmake_buf_free(&raw); |
|
859
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
860
|
|
|
|
|
|
|
} |
|
861
|
115
|
|
|
|
|
|
pdfmake_buf_free(&raw); |
|
862
|
|
|
|
|
|
|
} |
|
863
|
|
|
|
|
|
|
|
|
864
|
115
|
|
|
|
|
|
return PDFMAKE_OK; |
|
865
|
|
|
|
|
|
|
} |
|
866
|
|
|
|
|
|
|
|
|
867
|
27
|
|
|
|
|
|
pdfmake_err_t pdfmake_flate_encode(const uint8_t *in, size_t in_len, |
|
868
|
|
|
|
|
|
|
const pdfmake_flate_params_t *params, |
|
869
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
870
|
|
|
|
|
|
|
{ |
|
871
|
|
|
|
|
|
|
pdfmake_buf_t raw; |
|
872
|
|
|
|
|
|
|
pdfmake_err_t err; |
|
873
|
|
|
|
|
|
|
uint32_t adler; |
|
874
|
27
|
50
|
|
|
|
|
if (!out) return PDFMAKE_EINVAL; |
|
875
|
|
|
|
|
|
|
|
|
876
|
27
|
50
|
|
|
|
|
if (pdfmake_buf_init(&raw) != PDFMAKE_OK) return PDFMAKE_ENOMEM; |
|
877
|
|
|
|
|
|
|
|
|
878
|
|
|
|
|
|
|
/* Apply predictor if needed */ |
|
879
|
27
|
50
|
|
|
|
|
if (params && params->predictor > 1) { |
|
|
|
100
|
|
|
|
|
|
|
880
|
15
|
50
|
|
|
|
|
if (params->predictor == 2) { |
|
881
|
0
|
|
|
|
|
|
err = pdfmake_tiff_predictor_encode(params->colors, |
|
882
|
0
|
|
|
|
|
|
params->bits_per_comp, |
|
883
|
0
|
|
|
|
|
|
params->columns, |
|
884
|
|
|
|
|
|
|
in, in_len, &raw); |
|
885
|
15
|
50
|
|
|
|
|
} else if (params->predictor >= 10 && params->predictor <= 15) { |
|
|
|
50
|
|
|
|
|
|
|
886
|
15
|
|
|
|
|
|
err = pdfmake_predictor_encode(params->predictor, |
|
887
|
15
|
|
|
|
|
|
params->colors, |
|
888
|
15
|
|
|
|
|
|
params->bits_per_comp, |
|
889
|
15
|
|
|
|
|
|
params->columns, |
|
890
|
|
|
|
|
|
|
in, in_len, &raw); |
|
891
|
|
|
|
|
|
|
} else { |
|
892
|
0
|
|
|
|
|
|
pdfmake_buf_free(&raw); |
|
893
|
0
|
|
|
|
|
|
return PDFMAKE_EINVAL; |
|
894
|
|
|
|
|
|
|
} |
|
895
|
|
|
|
|
|
|
|
|
896
|
15
|
50
|
|
|
|
|
if (err != PDFMAKE_OK) { |
|
897
|
0
|
|
|
|
|
|
pdfmake_buf_free(&raw); |
|
898
|
0
|
|
|
|
|
|
return err; |
|
899
|
|
|
|
|
|
|
} |
|
900
|
|
|
|
|
|
|
} |
|
901
|
|
|
|
|
|
|
else { |
|
902
|
|
|
|
|
|
|
/* No predictor - copy input */ |
|
903
|
12
|
50
|
|
|
|
|
if (pdfmake_buf_append(&raw, in, in_len) != PDFMAKE_OK) { |
|
904
|
0
|
|
|
|
|
|
pdfmake_buf_free(&raw); |
|
905
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
906
|
|
|
|
|
|
|
} |
|
907
|
|
|
|
|
|
|
} |
|
908
|
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
/* zlib header: CMF=0x78 (deflate, 32K window), FLG=0x9C (level 6, no dict) */ |
|
910
|
|
|
|
|
|
|
/* For checksum: (0x78 * 256 + 0x9C) % 31 = 0 */ |
|
911
|
27
|
|
|
|
|
|
pdfmake_buf_append_byte(out, 0x78); |
|
912
|
27
|
|
|
|
|
|
pdfmake_buf_append_byte(out, 0x9C); |
|
913
|
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
/* DEFLATE compress */ |
|
915
|
27
|
|
|
|
|
|
err = pdfmake_deflate_encode(raw.data, raw.len, 4, out); /* Level 4 */ |
|
916
|
27
|
50
|
|
|
|
|
if (err != PDFMAKE_OK) { |
|
917
|
0
|
|
|
|
|
|
pdfmake_buf_free(&raw); |
|
918
|
0
|
|
|
|
|
|
return err; |
|
919
|
|
|
|
|
|
|
} |
|
920
|
|
|
|
|
|
|
|
|
921
|
|
|
|
|
|
|
/* Adler-32 checksum (big-endian) */ |
|
922
|
27
|
|
|
|
|
|
adler = pdfmake_adler32(raw.data, raw.len); |
|
923
|
27
|
|
|
|
|
|
pdfmake_buf_append_byte(out, (adler >> 24) & 0xFF); |
|
924
|
27
|
|
|
|
|
|
pdfmake_buf_append_byte(out, (adler >> 16) & 0xFF); |
|
925
|
27
|
|
|
|
|
|
pdfmake_buf_append_byte(out, (adler >> 8) & 0xFF); |
|
926
|
27
|
|
|
|
|
|
pdfmake_buf_append_byte(out, adler & 0xFF); |
|
927
|
|
|
|
|
|
|
|
|
928
|
27
|
|
|
|
|
|
pdfmake_buf_free(&raw); |
|
929
|
27
|
|
|
|
|
|
return PDFMAKE_OK; |
|
930
|
|
|
|
|
|
|
} |
|
931
|
|
|
|
|
|
|
|
|
932
|
|
|
|
|
|
|
/*============================================================================ |
|
933
|
|
|
|
|
|
|
* PNG predictors (§7.4.4.4) |
|
934
|
|
|
|
|
|
|
*==========================================================================*/ |
|
935
|
|
|
|
|
|
|
|
|
936
|
|
|
|
|
|
|
/* Paeth predictor function */ |
|
937
|
1978428
|
|
|
|
|
|
static int paeth(int a, int b, int c) |
|
938
|
|
|
|
|
|
|
{ |
|
939
|
1978428
|
|
|
|
|
|
int p = a + b - c; |
|
940
|
1978428
|
|
|
|
|
|
int pa = abs(p - a); |
|
941
|
1978428
|
|
|
|
|
|
int pb = abs(p - b); |
|
942
|
1978428
|
|
|
|
|
|
int pc = abs(p - c); |
|
943
|
|
|
|
|
|
|
|
|
944
|
1978428
|
100
|
|
|
|
|
if (pa <= pb && pa <= pc) return a; |
|
|
|
100
|
|
|
|
|
|
|
945
|
500031
|
100
|
|
|
|
|
if (pb <= pc) return b; |
|
946
|
40185
|
|
|
|
|
|
return c; |
|
947
|
|
|
|
|
|
|
} |
|
948
|
|
|
|
|
|
|
|
|
949
|
22
|
|
|
|
|
|
pdfmake_err_t pdfmake_predictor_decode(int predictor, |
|
950
|
|
|
|
|
|
|
int colors, int bits_per_comp, int columns, |
|
951
|
|
|
|
|
|
|
const uint8_t *in, size_t in_len, |
|
952
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
953
|
|
|
|
|
|
|
{ |
|
954
|
|
|
|
|
|
|
int bpp; |
|
955
|
|
|
|
|
|
|
int row_bytes; |
|
956
|
|
|
|
|
|
|
int in_row_size; |
|
957
|
|
|
|
|
|
|
size_t num_rows; |
|
958
|
|
|
|
|
|
|
uint8_t *prev_row; |
|
959
|
|
|
|
|
|
|
uint8_t *curr_row; |
|
960
|
|
|
|
|
|
|
size_t r; |
|
961
|
|
|
|
|
|
|
int i; |
|
962
|
22
|
50
|
|
|
|
|
if (!in || !out) return PDFMAKE_EINVAL; |
|
|
|
50
|
|
|
|
|
|
|
963
|
|
|
|
|
|
|
|
|
964
|
|
|
|
|
|
|
/* Calculate bytes per pixel (bpp) and row width */ |
|
965
|
22
|
|
|
|
|
|
bpp = (colors * bits_per_comp + 7) / 8; |
|
966
|
22
|
|
|
|
|
|
row_bytes = (columns * colors * bits_per_comp + 7) / 8; |
|
967
|
|
|
|
|
|
|
|
|
968
|
|
|
|
|
|
|
/* For PNG predictors, each row has a filter type byte prefix */ |
|
969
|
22
|
|
|
|
|
|
in_row_size = row_bytes + 1; |
|
970
|
|
|
|
|
|
|
|
|
971
|
22
|
50
|
|
|
|
|
if (in_len % in_row_size != 0) { |
|
972
|
|
|
|
|
|
|
/* If there's no filter byte, data might be raw (predictor=10, None) */ |
|
973
|
0
|
0
|
|
|
|
|
if (predictor == 10) { |
|
974
|
0
|
|
|
|
|
|
return pdfmake_buf_append(out, in, in_len); |
|
975
|
|
|
|
|
|
|
} |
|
976
|
0
|
|
|
|
|
|
return PDFMAKE_ECORRUPT; |
|
977
|
|
|
|
|
|
|
} |
|
978
|
|
|
|
|
|
|
|
|
979
|
22
|
|
|
|
|
|
num_rows = in_len / in_row_size; |
|
980
|
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
/* Allocate previous row buffer */ |
|
982
|
22
|
|
|
|
|
|
prev_row = calloc(row_bytes, 1); |
|
983
|
22
|
50
|
|
|
|
|
if (!prev_row) return PDFMAKE_ENOMEM; |
|
984
|
|
|
|
|
|
|
|
|
985
|
|
|
|
|
|
|
/* Allocate current row buffer */ |
|
986
|
22
|
|
|
|
|
|
curr_row = malloc(row_bytes); |
|
987
|
22
|
50
|
|
|
|
|
if (!curr_row) { |
|
988
|
0
|
|
|
|
|
|
free(prev_row); |
|
989
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
990
|
|
|
|
|
|
|
} |
|
991
|
|
|
|
|
|
|
|
|
992
|
5164
|
100
|
|
|
|
|
for (r = 0; r < num_rows; r++) { |
|
993
|
5142
|
|
|
|
|
|
const uint8_t *row_in = in + r * in_row_size; |
|
994
|
5142
|
|
|
|
|
|
int filter_type = row_in[0]; |
|
995
|
5142
|
|
|
|
|
|
const uint8_t *filtered = row_in + 1; |
|
996
|
|
|
|
|
|
|
|
|
997
|
|
|
|
|
|
|
/* Apply reverse filter */ |
|
998
|
1785270
|
100
|
|
|
|
|
for (i = 0; i < row_bytes; i++) { |
|
999
|
|
|
|
|
|
|
uint8_t raw; |
|
1000
|
1780128
|
100
|
|
|
|
|
uint8_t a = (i >= bpp) ? curr_row[i - bpp] : 0; |
|
1001
|
1780128
|
|
|
|
|
|
uint8_t b = prev_row[i]; |
|
1002
|
1780128
|
100
|
|
|
|
|
uint8_t c = (i >= bpp) ? prev_row[i - bpp] : 0; |
|
1003
|
|
|
|
|
|
|
|
|
1004
|
1780128
|
|
|
|
|
|
switch (filter_type) { |
|
1005
|
1780048
|
|
|
|
|
|
case 0: /* None */ |
|
1006
|
1780048
|
|
|
|
|
|
raw = filtered[i]; |
|
1007
|
1780048
|
|
|
|
|
|
break; |
|
1008
|
20
|
|
|
|
|
|
case 1: /* Sub */ |
|
1009
|
20
|
|
|
|
|
|
raw = filtered[i] + a; |
|
1010
|
20
|
|
|
|
|
|
break; |
|
1011
|
28
|
|
|
|
|
|
case 2: /* Up */ |
|
1012
|
28
|
|
|
|
|
|
raw = filtered[i] + b; |
|
1013
|
28
|
|
|
|
|
|
break; |
|
1014
|
16
|
|
|
|
|
|
case 3: /* Average */ |
|
1015
|
16
|
|
|
|
|
|
raw = filtered[i] + ((a + b) / 2); |
|
1016
|
16
|
|
|
|
|
|
break; |
|
1017
|
16
|
|
|
|
|
|
case 4: /* Paeth */ |
|
1018
|
16
|
|
|
|
|
|
raw = filtered[i] + paeth(a, b, c); |
|
1019
|
16
|
|
|
|
|
|
break; |
|
1020
|
0
|
|
|
|
|
|
default: |
|
1021
|
0
|
|
|
|
|
|
free(prev_row); |
|
1022
|
0
|
|
|
|
|
|
free(curr_row); |
|
1023
|
0
|
|
|
|
|
|
return PDFMAKE_ECORRUPT; |
|
1024
|
|
|
|
|
|
|
} |
|
1025
|
|
|
|
|
|
|
|
|
1026
|
1780128
|
|
|
|
|
|
curr_row[i] = raw; |
|
1027
|
|
|
|
|
|
|
} |
|
1028
|
|
|
|
|
|
|
|
|
1029
|
|
|
|
|
|
|
/* Output row */ |
|
1030
|
5142
|
50
|
|
|
|
|
if (pdfmake_buf_append(out, curr_row, row_bytes) != PDFMAKE_OK) { |
|
1031
|
0
|
|
|
|
|
|
free(prev_row); |
|
1032
|
0
|
|
|
|
|
|
free(curr_row); |
|
1033
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1034
|
|
|
|
|
|
|
} |
|
1035
|
|
|
|
|
|
|
|
|
1036
|
|
|
|
|
|
|
/* Current row becomes previous row */ |
|
1037
|
5142
|
|
|
|
|
|
memcpy(prev_row, curr_row, row_bytes); |
|
1038
|
|
|
|
|
|
|
} |
|
1039
|
|
|
|
|
|
|
|
|
1040
|
22
|
|
|
|
|
|
free(prev_row); |
|
1041
|
22
|
|
|
|
|
|
free(curr_row); |
|
1042
|
22
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1043
|
|
|
|
|
|
|
} |
|
1044
|
|
|
|
|
|
|
|
|
1045
|
22
|
|
|
|
|
|
pdfmake_err_t pdfmake_predictor_encode(int predictor, |
|
1046
|
|
|
|
|
|
|
int colors, int bits_per_comp, int columns, |
|
1047
|
|
|
|
|
|
|
const uint8_t *in, size_t in_len, |
|
1048
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
1049
|
|
|
|
|
|
|
{ |
|
1050
|
|
|
|
|
|
|
int bpp; |
|
1051
|
|
|
|
|
|
|
int row_bytes; |
|
1052
|
|
|
|
|
|
|
size_t num_rows; |
|
1053
|
|
|
|
|
|
|
uint8_t *prev_row; |
|
1054
|
|
|
|
|
|
|
uint8_t *filtered; |
|
1055
|
|
|
|
|
|
|
size_t r; |
|
1056
|
|
|
|
|
|
|
int i; |
|
1057
|
|
|
|
|
|
|
int f; |
|
1058
|
22
|
50
|
|
|
|
|
if (!in || !out) return PDFMAKE_EINVAL; |
|
|
|
50
|
|
|
|
|
|
|
1059
|
|
|
|
|
|
|
|
|
1060
|
22
|
|
|
|
|
|
bpp = (colors * bits_per_comp + 7) / 8; |
|
1061
|
22
|
|
|
|
|
|
row_bytes = (columns * colors * bits_per_comp + 7) / 8; |
|
1062
|
|
|
|
|
|
|
|
|
1063
|
22
|
50
|
|
|
|
|
if (in_len % row_bytes != 0) return PDFMAKE_EINVAL; |
|
1064
|
|
|
|
|
|
|
|
|
1065
|
22
|
|
|
|
|
|
num_rows = in_len / row_bytes; |
|
1066
|
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
/* Allocate previous row buffer */ |
|
1068
|
22
|
|
|
|
|
|
prev_row = calloc(row_bytes, 1); |
|
1069
|
22
|
50
|
|
|
|
|
if (!prev_row) return PDFMAKE_ENOMEM; |
|
1070
|
|
|
|
|
|
|
|
|
1071
|
|
|
|
|
|
|
/* Allocate filtered row buffer */ |
|
1072
|
22
|
|
|
|
|
|
filtered = malloc(row_bytes); |
|
1073
|
22
|
50
|
|
|
|
|
if (!filtered) { |
|
1074
|
0
|
|
|
|
|
|
free(prev_row); |
|
1075
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1076
|
|
|
|
|
|
|
} |
|
1077
|
|
|
|
|
|
|
|
|
1078
|
5164
|
100
|
|
|
|
|
for (r = 0; r < num_rows; r++) { |
|
1079
|
5142
|
|
|
|
|
|
const uint8_t *curr_row = in + r * row_bytes; |
|
1080
|
|
|
|
|
|
|
|
|
1081
|
|
|
|
|
|
|
int filter_type; |
|
1082
|
5142
|
100
|
|
|
|
|
if (predictor == 15) { |
|
1083
|
|
|
|
|
|
|
/* Optimum: try all filters and pick best (simple heuristic: sum of abs values) */ |
|
1084
|
5119
|
|
|
|
|
|
int best_filter = 0; |
|
1085
|
5119
|
|
|
|
|
|
int best_sum = INT32_MAX; |
|
1086
|
|
|
|
|
|
|
|
|
1087
|
30714
|
100
|
|
|
|
|
for (f = 0; f <= 4; f++) { |
|
1088
|
25595
|
|
|
|
|
|
int sum = 0; |
|
1089
|
8925775
|
100
|
|
|
|
|
for (i = 0; i < row_bytes; i++) { |
|
1090
|
8900180
|
100
|
|
|
|
|
uint8_t a = (i >= bpp) ? curr_row[i - bpp] : 0; |
|
1091
|
8900180
|
|
|
|
|
|
uint8_t b = prev_row[i]; |
|
1092
|
8900180
|
100
|
|
|
|
|
uint8_t c = (i >= bpp) ? prev_row[i - bpp] : 0; |
|
1093
|
|
|
|
|
|
|
int val; |
|
1094
|
|
|
|
|
|
|
|
|
1095
|
8900180
|
|
|
|
|
|
switch (f) { |
|
1096
|
1780036
|
|
|
|
|
|
case 0: val = curr_row[i]; break; |
|
1097
|
1780036
|
|
|
|
|
|
case 1: val = curr_row[i] - a; break; |
|
1098
|
1780036
|
|
|
|
|
|
case 2: val = curr_row[i] - b; break; |
|
1099
|
1780036
|
|
|
|
|
|
case 3: val = curr_row[i] - ((a + b) / 2); break; |
|
1100
|
1780036
|
|
|
|
|
|
case 4: val = curr_row[i] - paeth(a, b, c); break; |
|
1101
|
0
|
|
|
|
|
|
default: val = 0; |
|
1102
|
|
|
|
|
|
|
} |
|
1103
|
8900180
|
|
|
|
|
|
sum += abs((int8_t)val); |
|
1104
|
|
|
|
|
|
|
} |
|
1105
|
25595
|
100
|
|
|
|
|
if (sum < best_sum) { |
|
1106
|
17141
|
|
|
|
|
|
best_sum = sum; |
|
1107
|
17141
|
|
|
|
|
|
best_filter = f; |
|
1108
|
|
|
|
|
|
|
} |
|
1109
|
|
|
|
|
|
|
} |
|
1110
|
5119
|
|
|
|
|
|
filter_type = best_filter; |
|
1111
|
|
|
|
|
|
|
} |
|
1112
|
|
|
|
|
|
|
else { |
|
1113
|
23
|
|
|
|
|
|
filter_type = predictor - 10; /* 10=None, 11=Sub, 12=Up, 13=Avg, 14=Paeth */ |
|
1114
|
23
|
100
|
|
|
|
|
if (filter_type < 0 || filter_type > 4) filter_type = 0; |
|
|
|
50
|
|
|
|
|
|
|
1115
|
|
|
|
|
|
|
} |
|
1116
|
|
|
|
|
|
|
|
|
1117
|
|
|
|
|
|
|
/* Apply filter */ |
|
1118
|
1785270
|
100
|
|
|
|
|
for (i = 0; i < row_bytes; i++) { |
|
1119
|
1780128
|
100
|
|
|
|
|
uint8_t a = (i >= bpp) ? curr_row[i - bpp] : 0; |
|
1120
|
1780128
|
|
|
|
|
|
uint8_t b = prev_row[i]; |
|
1121
|
1780128
|
100
|
|
|
|
|
uint8_t c = (i >= bpp) ? prev_row[i - bpp] : 0; |
|
1122
|
|
|
|
|
|
|
|
|
1123
|
1780128
|
|
|
|
|
|
switch (filter_type) { |
|
1124
|
28
|
|
|
|
|
|
case 0: /* None */ |
|
1125
|
28
|
|
|
|
|
|
filtered[i] = curr_row[i]; |
|
1126
|
28
|
|
|
|
|
|
break; |
|
1127
|
78320
|
|
|
|
|
|
case 1: /* Sub */ |
|
1128
|
78320
|
|
|
|
|
|
filtered[i] = curr_row[i] - a; |
|
1129
|
78320
|
|
|
|
|
|
break; |
|
1130
|
913528
|
|
|
|
|
|
case 2: /* Up */ |
|
1131
|
913528
|
|
|
|
|
|
filtered[i] = curr_row[i] - b; |
|
1132
|
913528
|
|
|
|
|
|
break; |
|
1133
|
589876
|
|
|
|
|
|
case 3: /* Average */ |
|
1134
|
589876
|
|
|
|
|
|
filtered[i] = curr_row[i] - ((a + b) / 2); |
|
1135
|
589876
|
|
|
|
|
|
break; |
|
1136
|
198376
|
|
|
|
|
|
case 4: /* Paeth */ |
|
1137
|
198376
|
|
|
|
|
|
filtered[i] = curr_row[i] - paeth(a, b, c); |
|
1138
|
198376
|
|
|
|
|
|
break; |
|
1139
|
|
|
|
|
|
|
} |
|
1140
|
|
|
|
|
|
|
} |
|
1141
|
|
|
|
|
|
|
|
|
1142
|
|
|
|
|
|
|
/* Output filter type byte + filtered row */ |
|
1143
|
5142
|
|
|
|
|
|
pdfmake_buf_append_byte(out, (uint8_t)filter_type); |
|
1144
|
5142
|
50
|
|
|
|
|
if (pdfmake_buf_append(out, filtered, row_bytes) != PDFMAKE_OK) { |
|
1145
|
0
|
|
|
|
|
|
free(prev_row); |
|
1146
|
0
|
|
|
|
|
|
free(filtered); |
|
1147
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1148
|
|
|
|
|
|
|
} |
|
1149
|
|
|
|
|
|
|
|
|
1150
|
|
|
|
|
|
|
/* Current row becomes previous row */ |
|
1151
|
5142
|
|
|
|
|
|
memcpy(prev_row, curr_row, row_bytes); |
|
1152
|
|
|
|
|
|
|
} |
|
1153
|
|
|
|
|
|
|
|
|
1154
|
22
|
|
|
|
|
|
free(prev_row); |
|
1155
|
22
|
|
|
|
|
|
free(filtered); |
|
1156
|
22
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1157
|
|
|
|
|
|
|
} |
|
1158
|
|
|
|
|
|
|
|
|
1159
|
|
|
|
|
|
|
/*============================================================================ |
|
1160
|
|
|
|
|
|
|
* TIFF predictor 2 (horizontal differencing) |
|
1161
|
|
|
|
|
|
|
*==========================================================================*/ |
|
1162
|
|
|
|
|
|
|
|
|
1163
|
1
|
|
|
|
|
|
pdfmake_err_t pdfmake_tiff_predictor_decode(int colors, int bits_per_comp, int columns, |
|
1164
|
|
|
|
|
|
|
const uint8_t *in, size_t in_len, |
|
1165
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
1166
|
|
|
|
|
|
|
{ |
|
1167
|
|
|
|
|
|
|
int row_bytes; |
|
1168
|
|
|
|
|
|
|
size_t num_rows; |
|
1169
|
|
|
|
|
|
|
uint8_t *row; |
|
1170
|
|
|
|
|
|
|
size_t r; |
|
1171
|
|
|
|
|
|
|
int c; |
|
1172
|
|
|
|
|
|
|
int i; |
|
1173
|
1
|
50
|
|
|
|
|
if (!in || !out) return PDFMAKE_EINVAL; |
|
|
|
50
|
|
|
|
|
|
|
1174
|
|
|
|
|
|
|
|
|
1175
|
|
|
|
|
|
|
/* Only 8-bit samples supported for now */ |
|
1176
|
1
|
50
|
|
|
|
|
if (bits_per_comp != 8) return PDFMAKE_EUNSUPPORTED; |
|
1177
|
|
|
|
|
|
|
|
|
1178
|
1
|
|
|
|
|
|
row_bytes = columns * colors; |
|
1179
|
1
|
50
|
|
|
|
|
if (in_len % row_bytes != 0) return PDFMAKE_EINVAL; |
|
1180
|
|
|
|
|
|
|
|
|
1181
|
1
|
|
|
|
|
|
num_rows = in_len / row_bytes; |
|
1182
|
|
|
|
|
|
|
|
|
1183
|
|
|
|
|
|
|
/* Allocate row buffer */ |
|
1184
|
1
|
|
|
|
|
|
row = malloc(row_bytes); |
|
1185
|
1
|
50
|
|
|
|
|
if (!row) return PDFMAKE_ENOMEM; |
|
1186
|
|
|
|
|
|
|
|
|
1187
|
2
|
100
|
|
|
|
|
for (r = 0; r < num_rows; r++) { |
|
1188
|
1
|
|
|
|
|
|
const uint8_t *row_in = in + r * row_bytes; |
|
1189
|
|
|
|
|
|
|
|
|
1190
|
|
|
|
|
|
|
/* First pixel is as-is */ |
|
1191
|
2
|
100
|
|
|
|
|
for (c = 0; c < colors; c++) { |
|
1192
|
1
|
|
|
|
|
|
row[c] = row_in[c]; |
|
1193
|
|
|
|
|
|
|
} |
|
1194
|
|
|
|
|
|
|
|
|
1195
|
|
|
|
|
|
|
/* Remaining pixels: add previous pixel */ |
|
1196
|
6
|
100
|
|
|
|
|
for (i = colors; i < row_bytes; i++) { |
|
1197
|
5
|
|
|
|
|
|
row[i] = row_in[i] + row[i - colors]; |
|
1198
|
|
|
|
|
|
|
} |
|
1199
|
|
|
|
|
|
|
|
|
1200
|
1
|
50
|
|
|
|
|
if (pdfmake_buf_append(out, row, row_bytes) != PDFMAKE_OK) { |
|
1201
|
0
|
|
|
|
|
|
free(row); |
|
1202
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1203
|
|
|
|
|
|
|
} |
|
1204
|
|
|
|
|
|
|
} |
|
1205
|
|
|
|
|
|
|
|
|
1206
|
1
|
|
|
|
|
|
free(row); |
|
1207
|
1
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1208
|
|
|
|
|
|
|
} |
|
1209
|
|
|
|
|
|
|
|
|
1210
|
1
|
|
|
|
|
|
pdfmake_err_t pdfmake_tiff_predictor_encode(int colors, int bits_per_comp, int columns, |
|
1211
|
|
|
|
|
|
|
const uint8_t *in, size_t in_len, |
|
1212
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
1213
|
|
|
|
|
|
|
{ |
|
1214
|
|
|
|
|
|
|
int row_bytes; |
|
1215
|
|
|
|
|
|
|
size_t num_rows; |
|
1216
|
|
|
|
|
|
|
uint8_t *row; |
|
1217
|
|
|
|
|
|
|
size_t r; |
|
1218
|
|
|
|
|
|
|
int c; |
|
1219
|
|
|
|
|
|
|
int i; |
|
1220
|
1
|
50
|
|
|
|
|
if (!in || !out) return PDFMAKE_EINVAL; |
|
|
|
50
|
|
|
|
|
|
|
1221
|
|
|
|
|
|
|
|
|
1222
|
|
|
|
|
|
|
/* Only 8-bit samples supported for now */ |
|
1223
|
1
|
50
|
|
|
|
|
if (bits_per_comp != 8) return PDFMAKE_EUNSUPPORTED; |
|
1224
|
|
|
|
|
|
|
|
|
1225
|
1
|
|
|
|
|
|
row_bytes = columns * colors; |
|
1226
|
1
|
50
|
|
|
|
|
if (in_len % row_bytes != 0) return PDFMAKE_EINVAL; |
|
1227
|
|
|
|
|
|
|
|
|
1228
|
1
|
|
|
|
|
|
num_rows = in_len / row_bytes; |
|
1229
|
|
|
|
|
|
|
|
|
1230
|
|
|
|
|
|
|
/* Allocate row buffer */ |
|
1231
|
1
|
|
|
|
|
|
row = malloc(row_bytes); |
|
1232
|
1
|
50
|
|
|
|
|
if (!row) return PDFMAKE_ENOMEM; |
|
1233
|
|
|
|
|
|
|
|
|
1234
|
2
|
100
|
|
|
|
|
for (r = 0; r < num_rows; r++) { |
|
1235
|
1
|
|
|
|
|
|
const uint8_t *row_in = in + r * row_bytes; |
|
1236
|
|
|
|
|
|
|
|
|
1237
|
|
|
|
|
|
|
/* First pixel is as-is */ |
|
1238
|
2
|
100
|
|
|
|
|
for (c = 0; c < colors; c++) { |
|
1239
|
1
|
|
|
|
|
|
row[c] = row_in[c]; |
|
1240
|
|
|
|
|
|
|
} |
|
1241
|
|
|
|
|
|
|
|
|
1242
|
|
|
|
|
|
|
/* Remaining pixels: subtract previous pixel */ |
|
1243
|
6
|
100
|
|
|
|
|
for (i = colors; i < row_bytes; i++) { |
|
1244
|
5
|
|
|
|
|
|
row[i] = row_in[i] - row_in[i - colors]; |
|
1245
|
|
|
|
|
|
|
} |
|
1246
|
|
|
|
|
|
|
|
|
1247
|
1
|
50
|
|
|
|
|
if (pdfmake_buf_append(out, row, row_bytes) != PDFMAKE_OK) { |
|
1248
|
0
|
|
|
|
|
|
free(row); |
|
1249
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1250
|
|
|
|
|
|
|
} |
|
1251
|
|
|
|
|
|
|
} |
|
1252
|
|
|
|
|
|
|
|
|
1253
|
1
|
|
|
|
|
|
free(row); |
|
1254
|
1
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1255
|
|
|
|
|
|
|
} |
|
1256
|
|
|
|
|
|
|
|
|
1257
|
|
|
|
|
|
|
/*============================================================================ |
|
1258
|
|
|
|
|
|
|
* Filter dispatch |
|
1259
|
|
|
|
|
|
|
*==========================================================================*/ |
|
1260
|
|
|
|
|
|
|
|
|
1261
|
0
|
|
|
|
|
|
pdfmake_err_t pdfmake_filter_encode(const char *name, |
|
1262
|
|
|
|
|
|
|
const uint8_t *in, size_t in_len, |
|
1263
|
|
|
|
|
|
|
const pdfmake_obj_t *params, |
|
1264
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
1265
|
|
|
|
|
|
|
{ |
|
1266
|
|
|
|
|
|
|
(void)params; /* Unused by most encoders */ |
|
1267
|
|
|
|
|
|
|
|
|
1268
|
0
|
0
|
|
|
|
|
if (!name || !out) return PDFMAKE_EINVAL; |
|
|
|
0
|
|
|
|
|
|
|
1269
|
|
|
|
|
|
|
|
|
1270
|
0
|
0
|
|
|
|
|
if (strcmp(name, "FlateDecode") == 0 || strcmp(name, "Fl") == 0) { |
|
|
|
0
|
|
|
|
|
|
|
1271
|
|
|
|
|
|
|
pdfmake_flate_params_t fp; |
|
1272
|
0
|
|
|
|
|
|
pdfmake_flate_params_from_dict(&fp, params); |
|
1273
|
0
|
|
|
|
|
|
return pdfmake_flate_encode(in, in_len, &fp, out); |
|
1274
|
|
|
|
|
|
|
} |
|
1275
|
|
|
|
|
|
|
|
|
1276
|
0
|
0
|
|
|
|
|
if (strcmp(name, "ASCIIHexDecode") == 0 || strcmp(name, "AHx") == 0) { |
|
|
|
0
|
|
|
|
|
|
|
1277
|
0
|
|
|
|
|
|
return pdfmake_asciihex_encode(in, in_len, out); |
|
1278
|
|
|
|
|
|
|
} |
|
1279
|
|
|
|
|
|
|
|
|
1280
|
0
|
0
|
|
|
|
|
if (strcmp(name, "ASCII85Decode") == 0 || strcmp(name, "A85") == 0) { |
|
|
|
0
|
|
|
|
|
|
|
1281
|
0
|
|
|
|
|
|
return pdfmake_ascii85_encode(in, in_len, out); |
|
1282
|
|
|
|
|
|
|
} |
|
1283
|
|
|
|
|
|
|
|
|
1284
|
0
|
0
|
|
|
|
|
if (strcmp(name, "RunLengthDecode") == 0 || strcmp(name, "RL") == 0) { |
|
|
|
0
|
|
|
|
|
|
|
1285
|
0
|
|
|
|
|
|
return pdfmake_rle_encode(in, in_len, out); |
|
1286
|
|
|
|
|
|
|
} |
|
1287
|
|
|
|
|
|
|
|
|
1288
|
|
|
|
|
|
|
/* LZWDecode encoding not supported (patent concerns, use FlateDecode) */ |
|
1289
|
|
|
|
|
|
|
|
|
1290
|
0
|
|
|
|
|
|
return PDFMAKE_EUNSUPPORTED; |
|
1291
|
|
|
|
|
|
|
} |
|
1292
|
|
|
|
|
|
|
|
|
1293
|
93
|
|
|
|
|
|
pdfmake_err_t pdfmake_filter_decode(const char *name, |
|
1294
|
|
|
|
|
|
|
const uint8_t *in, size_t in_len, |
|
1295
|
|
|
|
|
|
|
const pdfmake_obj_t *params, |
|
1296
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
1297
|
|
|
|
|
|
|
{ |
|
1298
|
93
|
50
|
|
|
|
|
if (!name || !out) return PDFMAKE_EINVAL; |
|
|
|
50
|
|
|
|
|
|
|
1299
|
|
|
|
|
|
|
|
|
1300
|
93
|
50
|
|
|
|
|
if (strcmp(name, "FlateDecode") == 0 || strcmp(name, "Fl") == 0) { |
|
|
|
0
|
|
|
|
|
|
|
1301
|
|
|
|
|
|
|
pdfmake_flate_params_t fp; |
|
1302
|
93
|
|
|
|
|
|
pdfmake_flate_params_from_dict(&fp, params); |
|
1303
|
93
|
|
|
|
|
|
return pdfmake_flate_decode(in, in_len, &fp, out); |
|
1304
|
|
|
|
|
|
|
} |
|
1305
|
|
|
|
|
|
|
|
|
1306
|
0
|
0
|
|
|
|
|
if (strcmp(name, "ASCIIHexDecode") == 0 || strcmp(name, "AHx") == 0) { |
|
|
|
0
|
|
|
|
|
|
|
1307
|
0
|
|
|
|
|
|
return pdfmake_asciihex_decode(in, in_len, out); |
|
1308
|
|
|
|
|
|
|
} |
|
1309
|
|
|
|
|
|
|
|
|
1310
|
0
|
0
|
|
|
|
|
if (strcmp(name, "ASCII85Decode") == 0 || strcmp(name, "A85") == 0) { |
|
|
|
0
|
|
|
|
|
|
|
1311
|
0
|
|
|
|
|
|
return pdfmake_ascii85_decode(in, in_len, out); |
|
1312
|
|
|
|
|
|
|
} |
|
1313
|
|
|
|
|
|
|
|
|
1314
|
0
|
0
|
|
|
|
|
if (strcmp(name, "LZWDecode") == 0 || strcmp(name, "LZW") == 0) { |
|
|
|
0
|
|
|
|
|
|
|
1315
|
|
|
|
|
|
|
pdfmake_flate_params_t fp; |
|
1316
|
0
|
|
|
|
|
|
pdfmake_flate_params_from_dict(&fp, params); /* Reuses same params structure */ |
|
1317
|
0
|
|
|
|
|
|
return pdfmake_lzw_decode(in, in_len, &fp, out); |
|
1318
|
|
|
|
|
|
|
} |
|
1319
|
|
|
|
|
|
|
|
|
1320
|
0
|
0
|
|
|
|
|
if (strcmp(name, "RunLengthDecode") == 0 || strcmp(name, "RL") == 0) { |
|
|
|
0
|
|
|
|
|
|
|
1321
|
0
|
|
|
|
|
|
return pdfmake_rle_decode(in, in_len, out); |
|
1322
|
|
|
|
|
|
|
} |
|
1323
|
|
|
|
|
|
|
|
|
1324
|
|
|
|
|
|
|
/* Stub filters */ |
|
1325
|
0
|
0
|
|
|
|
|
if (strcmp(name, "CCITTFaxDecode") == 0 || strcmp(name, "CCF") == 0) { |
|
|
|
0
|
|
|
|
|
|
|
1326
|
0
|
|
|
|
|
|
return pdfmake_ccitt_decode(in, in_len, params, out); |
|
1327
|
|
|
|
|
|
|
} |
|
1328
|
0
|
0
|
|
|
|
|
if (strcmp(name, "JBIG2Decode") == 0) { |
|
1329
|
0
|
|
|
|
|
|
return pdfmake_jbig2_decode(in, in_len, params, out); |
|
1330
|
|
|
|
|
|
|
} |
|
1331
|
0
|
0
|
|
|
|
|
if (strcmp(name, "JPXDecode") == 0) { |
|
1332
|
0
|
|
|
|
|
|
return pdfmake_jpx_decode(in, in_len, params, out); |
|
1333
|
|
|
|
|
|
|
} |
|
1334
|
|
|
|
|
|
|
|
|
1335
|
0
|
|
|
|
|
|
return PDFMAKE_EUNSUPPORTED; |
|
1336
|
|
|
|
|
|
|
} |
|
1337
|
|
|
|
|
|
|
|
|
1338
|
93
|
|
|
|
|
|
pdfmake_err_t pdfmake_filter_chain_decode(pdfmake_arena_t *arena, |
|
1339
|
|
|
|
|
|
|
const pdfmake_obj_t *filters, |
|
1340
|
|
|
|
|
|
|
const pdfmake_obj_t *params, |
|
1341
|
|
|
|
|
|
|
const uint8_t *in, size_t in_len, |
|
1342
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
1343
|
|
|
|
|
|
|
{ |
|
1344
|
|
|
|
|
|
|
size_t n; |
|
1345
|
|
|
|
|
|
|
pdfmake_buf_t tmp1, tmp2; |
|
1346
|
|
|
|
|
|
|
const uint8_t *current_in; |
|
1347
|
|
|
|
|
|
|
size_t current_len; |
|
1348
|
|
|
|
|
|
|
pdfmake_buf_t *current_out; |
|
1349
|
|
|
|
|
|
|
size_t i; |
|
1350
|
|
|
|
|
|
|
pdfmake_err_t err; |
|
1351
|
93
|
50
|
|
|
|
|
if (!arena || !filters || !out) return PDFMAKE_EINVAL; |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
1352
|
|
|
|
|
|
|
|
|
1353
|
|
|
|
|
|
|
/* Single filter (name) */ |
|
1354
|
93
|
50
|
|
|
|
|
if (filters->kind == PDFMAKE_NAME) { |
|
1355
|
93
|
|
|
|
|
|
const char *name = (const char *)pdfmake_arena_name_bytes( |
|
1356
|
93
|
|
|
|
|
|
arena, filters->as.name.id); |
|
1357
|
93
|
|
|
|
|
|
return pdfmake_filter_decode(name, in, in_len, params, out); |
|
1358
|
|
|
|
|
|
|
} |
|
1359
|
|
|
|
|
|
|
|
|
1360
|
|
|
|
|
|
|
/* Array of filters */ |
|
1361
|
0
|
0
|
|
|
|
|
if (filters->kind != PDFMAKE_ARRAY) return PDFMAKE_EINVAL; |
|
1362
|
|
|
|
|
|
|
|
|
1363
|
0
|
|
|
|
|
|
n = pdfmake_array_len((pdfmake_obj_t *)filters); |
|
1364
|
0
|
0
|
|
|
|
|
if (n == 0) { |
|
1365
|
0
|
|
|
|
|
|
return pdfmake_buf_append(out, in, in_len); |
|
1366
|
|
|
|
|
|
|
} |
|
1367
|
|
|
|
|
|
|
|
|
1368
|
|
|
|
|
|
|
/* Apply filters in reverse order (last filter first for decoding) */ |
|
1369
|
0
|
0
|
|
|
|
|
if (pdfmake_buf_init(&tmp1) != PDFMAKE_OK) return PDFMAKE_ENOMEM; |
|
1370
|
0
|
0
|
|
|
|
|
if (pdfmake_buf_init(&tmp2) != PDFMAKE_OK) { |
|
1371
|
0
|
|
|
|
|
|
pdfmake_buf_free(&tmp1); |
|
1372
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1373
|
|
|
|
|
|
|
} |
|
1374
|
|
|
|
|
|
|
|
|
1375
|
0
|
|
|
|
|
|
current_in = in; |
|
1376
|
0
|
|
|
|
|
|
current_len = in_len; |
|
1377
|
0
|
|
|
|
|
|
current_out = &tmp1; |
|
1378
|
|
|
|
|
|
|
|
|
1379
|
0
|
0
|
|
|
|
|
for (i = n; i > 0; i--) { |
|
1380
|
|
|
|
|
|
|
const char *name; |
|
1381
|
|
|
|
|
|
|
const pdfmake_obj_t *filter_params; |
|
1382
|
0
|
|
|
|
|
|
pdfmake_obj_t *filter = pdfmake_array_get((pdfmake_obj_t *)filters, i - 1); |
|
1383
|
0
|
0
|
|
|
|
|
if (!filter || filter->kind != PDFMAKE_NAME) { |
|
|
|
0
|
|
|
|
|
|
|
1384
|
0
|
|
|
|
|
|
pdfmake_buf_free(&tmp1); |
|
1385
|
0
|
|
|
|
|
|
pdfmake_buf_free(&tmp2); |
|
1386
|
0
|
|
|
|
|
|
return PDFMAKE_EINVAL; |
|
1387
|
|
|
|
|
|
|
} |
|
1388
|
|
|
|
|
|
|
|
|
1389
|
0
|
|
|
|
|
|
name = (const char *)pdfmake_arena_name_bytes( |
|
1390
|
|
|
|
|
|
|
arena, filter->as.name.id); |
|
1391
|
|
|
|
|
|
|
|
|
1392
|
|
|
|
|
|
|
/* Get params for this filter if array */ |
|
1393
|
0
|
|
|
|
|
|
filter_params = NULL; |
|
1394
|
0
|
0
|
|
|
|
|
if (params && params->kind == PDFMAKE_ARRAY) { |
|
|
|
0
|
|
|
|
|
|
|
1395
|
0
|
|
|
|
|
|
filter_params = pdfmake_array_get((pdfmake_obj_t *)params, i - 1); |
|
1396
|
0
|
0
|
|
|
|
|
} else if (params && n == 1) { |
|
|
|
0
|
|
|
|
|
|
|
1397
|
0
|
|
|
|
|
|
filter_params = params; |
|
1398
|
|
|
|
|
|
|
} |
|
1399
|
|
|
|
|
|
|
|
|
1400
|
0
|
|
|
|
|
|
pdfmake_buf_clear(current_out); |
|
1401
|
0
|
|
|
|
|
|
err = pdfmake_filter_decode(name, current_in, current_len, |
|
1402
|
|
|
|
|
|
|
filter_params, current_out); |
|
1403
|
0
|
0
|
|
|
|
|
if (err != PDFMAKE_OK) { |
|
1404
|
0
|
|
|
|
|
|
pdfmake_buf_free(&tmp1); |
|
1405
|
0
|
|
|
|
|
|
pdfmake_buf_free(&tmp2); |
|
1406
|
0
|
|
|
|
|
|
return err; |
|
1407
|
|
|
|
|
|
|
} |
|
1408
|
|
|
|
|
|
|
|
|
1409
|
|
|
|
|
|
|
/* Swap buffers for next iteration */ |
|
1410
|
0
|
|
|
|
|
|
current_in = current_out->data; |
|
1411
|
0
|
|
|
|
|
|
current_len = current_out->len; |
|
1412
|
0
|
0
|
|
|
|
|
current_out = (current_out == &tmp1) ? &tmp2 : &tmp1; |
|
1413
|
|
|
|
|
|
|
} |
|
1414
|
|
|
|
|
|
|
|
|
1415
|
|
|
|
|
|
|
/* Copy final result to output */ |
|
1416
|
0
|
|
|
|
|
|
err = pdfmake_buf_append(out, current_in, current_len); |
|
1417
|
|
|
|
|
|
|
|
|
1418
|
0
|
|
|
|
|
|
pdfmake_buf_free(&tmp1); |
|
1419
|
0
|
|
|
|
|
|
pdfmake_buf_free(&tmp2); |
|
1420
|
0
|
|
|
|
|
|
return err; |
|
1421
|
|
|
|
|
|
|
} |
|
1422
|
|
|
|
|
|
|
|
|
1423
|
0
|
|
|
|
|
|
pdfmake_err_t pdfmake_filter_chain_encode(pdfmake_arena_t *arena, |
|
1424
|
|
|
|
|
|
|
const pdfmake_obj_t *filters, |
|
1425
|
|
|
|
|
|
|
const pdfmake_obj_t *params, |
|
1426
|
|
|
|
|
|
|
const uint8_t *in, size_t in_len, |
|
1427
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
1428
|
|
|
|
|
|
|
{ |
|
1429
|
|
|
|
|
|
|
size_t n; |
|
1430
|
|
|
|
|
|
|
pdfmake_buf_t tmp1, tmp2; |
|
1431
|
|
|
|
|
|
|
const uint8_t *current_in; |
|
1432
|
|
|
|
|
|
|
size_t current_len; |
|
1433
|
|
|
|
|
|
|
pdfmake_buf_t *current_out; |
|
1434
|
|
|
|
|
|
|
size_t i; |
|
1435
|
|
|
|
|
|
|
pdfmake_err_t err; |
|
1436
|
0
|
0
|
|
|
|
|
if (!arena || !filters || !out) return PDFMAKE_EINVAL; |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
1437
|
|
|
|
|
|
|
|
|
1438
|
|
|
|
|
|
|
/* Single filter (name) */ |
|
1439
|
0
|
0
|
|
|
|
|
if (filters->kind == PDFMAKE_NAME) { |
|
1440
|
0
|
|
|
|
|
|
const char *name = (const char *)pdfmake_arena_name_bytes( |
|
1441
|
0
|
|
|
|
|
|
arena, filters->as.name.id); |
|
1442
|
0
|
|
|
|
|
|
return pdfmake_filter_encode(name, in, in_len, params, out); |
|
1443
|
|
|
|
|
|
|
} |
|
1444
|
|
|
|
|
|
|
|
|
1445
|
|
|
|
|
|
|
/* Array of filters */ |
|
1446
|
0
|
0
|
|
|
|
|
if (filters->kind != PDFMAKE_ARRAY) return PDFMAKE_EINVAL; |
|
1447
|
|
|
|
|
|
|
|
|
1448
|
0
|
|
|
|
|
|
n = pdfmake_array_len((pdfmake_obj_t *)filters); |
|
1449
|
0
|
0
|
|
|
|
|
if (n == 0) { |
|
1450
|
0
|
|
|
|
|
|
return pdfmake_buf_append(out, in, in_len); |
|
1451
|
|
|
|
|
|
|
} |
|
1452
|
|
|
|
|
|
|
|
|
1453
|
|
|
|
|
|
|
/* Apply filters in order (first filter first for encoding) */ |
|
1454
|
0
|
0
|
|
|
|
|
if (pdfmake_buf_init(&tmp1) != PDFMAKE_OK) return PDFMAKE_ENOMEM; |
|
1455
|
0
|
0
|
|
|
|
|
if (pdfmake_buf_init(&tmp2) != PDFMAKE_OK) { |
|
1456
|
0
|
|
|
|
|
|
pdfmake_buf_free(&tmp1); |
|
1457
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1458
|
|
|
|
|
|
|
} |
|
1459
|
|
|
|
|
|
|
|
|
1460
|
0
|
|
|
|
|
|
current_in = in; |
|
1461
|
0
|
|
|
|
|
|
current_len = in_len; |
|
1462
|
0
|
|
|
|
|
|
current_out = &tmp1; |
|
1463
|
|
|
|
|
|
|
|
|
1464
|
0
|
0
|
|
|
|
|
for (i = 0; i < n; i++) { |
|
1465
|
|
|
|
|
|
|
const char *name; |
|
1466
|
|
|
|
|
|
|
const pdfmake_obj_t *filter_params; |
|
1467
|
0
|
|
|
|
|
|
pdfmake_obj_t *filter = pdfmake_array_get((pdfmake_obj_t *)filters, i); |
|
1468
|
0
|
0
|
|
|
|
|
if (!filter || filter->kind != PDFMAKE_NAME) { |
|
|
|
0
|
|
|
|
|
|
|
1469
|
0
|
|
|
|
|
|
pdfmake_buf_free(&tmp1); |
|
1470
|
0
|
|
|
|
|
|
pdfmake_buf_free(&tmp2); |
|
1471
|
0
|
|
|
|
|
|
return PDFMAKE_EINVAL; |
|
1472
|
|
|
|
|
|
|
} |
|
1473
|
|
|
|
|
|
|
|
|
1474
|
0
|
|
|
|
|
|
name = (const char *)pdfmake_arena_name_bytes( |
|
1475
|
|
|
|
|
|
|
arena, filter->as.name.id); |
|
1476
|
|
|
|
|
|
|
|
|
1477
|
|
|
|
|
|
|
/* Get params for this filter if array */ |
|
1478
|
0
|
|
|
|
|
|
filter_params = NULL; |
|
1479
|
0
|
0
|
|
|
|
|
if (params && params->kind == PDFMAKE_ARRAY) { |
|
|
|
0
|
|
|
|
|
|
|
1480
|
0
|
|
|
|
|
|
filter_params = pdfmake_array_get((pdfmake_obj_t *)params, i); |
|
1481
|
0
|
0
|
|
|
|
|
} else if (params && n == 1) { |
|
|
|
0
|
|
|
|
|
|
|
1482
|
0
|
|
|
|
|
|
filter_params = params; |
|
1483
|
|
|
|
|
|
|
} |
|
1484
|
|
|
|
|
|
|
|
|
1485
|
0
|
|
|
|
|
|
pdfmake_buf_clear(current_out); |
|
1486
|
0
|
|
|
|
|
|
err = pdfmake_filter_encode(name, current_in, current_len, |
|
1487
|
|
|
|
|
|
|
filter_params, current_out); |
|
1488
|
0
|
0
|
|
|
|
|
if (err != PDFMAKE_OK) { |
|
1489
|
0
|
|
|
|
|
|
pdfmake_buf_free(&tmp1); |
|
1490
|
0
|
|
|
|
|
|
pdfmake_buf_free(&tmp2); |
|
1491
|
0
|
|
|
|
|
|
return err; |
|
1492
|
|
|
|
|
|
|
} |
|
1493
|
|
|
|
|
|
|
|
|
1494
|
|
|
|
|
|
|
/* Swap buffers for next iteration */ |
|
1495
|
0
|
|
|
|
|
|
current_in = current_out->data; |
|
1496
|
0
|
|
|
|
|
|
current_len = current_out->len; |
|
1497
|
0
|
0
|
|
|
|
|
current_out = (current_out == &tmp1) ? &tmp2 : &tmp1; |
|
1498
|
|
|
|
|
|
|
} |
|
1499
|
|
|
|
|
|
|
|
|
1500
|
|
|
|
|
|
|
/* Copy final result to output */ |
|
1501
|
0
|
|
|
|
|
|
err = pdfmake_buf_append(out, current_in, current_len); |
|
1502
|
|
|
|
|
|
|
|
|
1503
|
0
|
|
|
|
|
|
pdfmake_buf_free(&tmp1); |
|
1504
|
0
|
|
|
|
|
|
pdfmake_buf_free(&tmp2); |
|
1505
|
0
|
|
|
|
|
|
return err; |
|
1506
|
|
|
|
|
|
|
} |
|
1507
|
|
|
|
|
|
|
|
|
1508
|
|
|
|
|
|
|
/*============================================================================ |
|
1509
|
|
|
|
|
|
|
* ASCIIHexDecode — §7.4.2 |
|
1510
|
|
|
|
|
|
|
*==========================================================================*/ |
|
1511
|
|
|
|
|
|
|
|
|
1512
|
556
|
|
|
|
|
|
static int hex_digit_value(uint8_t c) |
|
1513
|
|
|
|
|
|
|
{ |
|
1514
|
556
|
50
|
|
|
|
|
if (c >= '0' && c <= '9') return c - '0'; |
|
|
|
100
|
|
|
|
|
|
|
1515
|
204
|
50
|
|
|
|
|
if (c >= 'A' && c <= 'F') return c - 'A' + 10; |
|
|
|
100
|
|
|
|
|
|
|
1516
|
3
|
50
|
|
|
|
|
if (c >= 'a' && c <= 'f') return c - 'a' + 10; |
|
|
|
50
|
|
|
|
|
|
|
1517
|
0
|
|
|
|
|
|
return -1; |
|
1518
|
|
|
|
|
|
|
} |
|
1519
|
|
|
|
|
|
|
|
|
1520
|
8
|
|
|
|
|
|
pdfmake_err_t pdfmake_asciihex_decode(const uint8_t *in, size_t in_len, |
|
1521
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
1522
|
|
|
|
|
|
|
{ |
|
1523
|
|
|
|
|
|
|
int high; |
|
1524
|
|
|
|
|
|
|
size_t i; |
|
1525
|
|
|
|
|
|
|
uint8_t c; |
|
1526
|
|
|
|
|
|
|
int val; |
|
1527
|
|
|
|
|
|
|
uint8_t byte; |
|
1528
|
8
|
50
|
|
|
|
|
if (!out) return PDFMAKE_EINVAL; |
|
1529
|
8
|
50
|
|
|
|
|
if (!in || in_len == 0) return PDFMAKE_OK; |
|
|
|
50
|
|
|
|
|
|
|
1530
|
|
|
|
|
|
|
|
|
1531
|
8
|
|
|
|
|
|
high = -1; /* Pending high nibble, -1 = none */ |
|
1532
|
|
|
|
|
|
|
|
|
1533
|
568
|
100
|
|
|
|
|
for (i = 0; i < in_len; i++) { |
|
1534
|
567
|
|
|
|
|
|
c = in[i]; |
|
1535
|
|
|
|
|
|
|
|
|
1536
|
|
|
|
|
|
|
/* End of data marker */ |
|
1537
|
567
|
100
|
|
|
|
|
if (c == '>') break; |
|
1538
|
|
|
|
|
|
|
|
|
1539
|
|
|
|
|
|
|
/* Skip whitespace */ |
|
1540
|
560
|
100
|
|
|
|
|
if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f') { |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
1541
|
4
|
|
|
|
|
|
continue; |
|
1542
|
|
|
|
|
|
|
} |
|
1543
|
|
|
|
|
|
|
|
|
1544
|
556
|
|
|
|
|
|
val = hex_digit_value(c); |
|
1545
|
556
|
50
|
|
|
|
|
if (val < 0) return PDFMAKE_ECORRUPT; /* Invalid hex digit */ |
|
1546
|
|
|
|
|
|
|
|
|
1547
|
556
|
100
|
|
|
|
|
if (high < 0) { |
|
1548
|
279
|
|
|
|
|
|
high = val; |
|
1549
|
|
|
|
|
|
|
} else { |
|
1550
|
277
|
|
|
|
|
|
byte = (uint8_t)((high << 4) | val); |
|
1551
|
277
|
50
|
|
|
|
|
if (pdfmake_buf_append_byte(out, byte) != PDFMAKE_OK) { |
|
1552
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1553
|
|
|
|
|
|
|
} |
|
1554
|
277
|
|
|
|
|
|
high = -1; |
|
1555
|
|
|
|
|
|
|
} |
|
1556
|
|
|
|
|
|
|
} |
|
1557
|
|
|
|
|
|
|
|
|
1558
|
|
|
|
|
|
|
/* Odd final digit → pad with 0 */ |
|
1559
|
8
|
100
|
|
|
|
|
if (high >= 0) { |
|
1560
|
2
|
|
|
|
|
|
byte = (uint8_t)(high << 4); |
|
1561
|
2
|
50
|
|
|
|
|
if (pdfmake_buf_append_byte(out, byte) != PDFMAKE_OK) { |
|
1562
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1563
|
|
|
|
|
|
|
} |
|
1564
|
|
|
|
|
|
|
} |
|
1565
|
|
|
|
|
|
|
|
|
1566
|
8
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1567
|
|
|
|
|
|
|
} |
|
1568
|
|
|
|
|
|
|
|
|
1569
|
3
|
|
|
|
|
|
pdfmake_err_t pdfmake_asciihex_encode(const uint8_t *in, size_t in_len, |
|
1570
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
1571
|
|
|
|
|
|
|
{ |
|
1572
|
|
|
|
|
|
|
static const char hex_chars[] = "0123456789ABCDEF"; |
|
1573
|
|
|
|
|
|
|
size_t i; |
|
1574
|
|
|
|
|
|
|
uint8_t byte; |
|
1575
|
|
|
|
|
|
|
|
|
1576
|
3
|
50
|
|
|
|
|
if (!out) return PDFMAKE_EINVAL; |
|
1577
|
|
|
|
|
|
|
|
|
1578
|
264
|
100
|
|
|
|
|
for (i = 0; i < in_len; i++) { |
|
1579
|
261
|
|
|
|
|
|
byte = in[i]; |
|
1580
|
522
|
|
|
|
|
|
if (pdfmake_buf_append_byte(out, hex_chars[byte >> 4]) != PDFMAKE_OK || |
|
1581
|
261
|
|
|
|
|
|
pdfmake_buf_append_byte(out, hex_chars[byte & 0x0F]) != PDFMAKE_OK) { |
|
1582
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1583
|
|
|
|
|
|
|
} |
|
1584
|
|
|
|
|
|
|
} |
|
1585
|
|
|
|
|
|
|
|
|
1586
|
|
|
|
|
|
|
/* End of data marker */ |
|
1587
|
3
|
|
|
|
|
|
return pdfmake_buf_append_byte(out, '>'); |
|
1588
|
|
|
|
|
|
|
} |
|
1589
|
|
|
|
|
|
|
|
|
1590
|
|
|
|
|
|
|
/*============================================================================ |
|
1591
|
|
|
|
|
|
|
* ASCII85Decode — §7.4.3 |
|
1592
|
|
|
|
|
|
|
*==========================================================================*/ |
|
1593
|
|
|
|
|
|
|
|
|
1594
|
|
|
|
|
|
|
/* Powers of 85 for decoding: 85^4, 85^3, 85^2, 85^1, 85^0 */ |
|
1595
|
|
|
|
|
|
|
static const uint32_t pdfmake_pow85[5] = {52200625, 614125, 7225, 85, 1}; |
|
1596
|
|
|
|
|
|
|
|
|
1597
|
15
|
|
|
|
|
|
pdfmake_err_t pdfmake_ascii85_decode(const uint8_t *in, size_t in_len, |
|
1598
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
1599
|
|
|
|
|
|
|
{ |
|
1600
|
|
|
|
|
|
|
uint8_t group[5]; |
|
1601
|
|
|
|
|
|
|
int group_len; |
|
1602
|
|
|
|
|
|
|
size_t i; |
|
1603
|
|
|
|
|
|
|
uint8_t c; |
|
1604
|
|
|
|
|
|
|
uint8_t zeros[4]; |
|
1605
|
|
|
|
|
|
|
uint32_t val; |
|
1606
|
|
|
|
|
|
|
int j; |
|
1607
|
|
|
|
|
|
|
uint8_t bytes[4]; |
|
1608
|
|
|
|
|
|
|
int out_bytes; |
|
1609
|
15
|
50
|
|
|
|
|
if (!out) return PDFMAKE_EINVAL; |
|
1610
|
15
|
50
|
|
|
|
|
if (!in || in_len == 0) return PDFMAKE_OK; |
|
|
|
100
|
|
|
|
|
|
|
1611
|
|
|
|
|
|
|
|
|
1612
|
14
|
|
|
|
|
|
group_len = 0; |
|
1613
|
14
|
|
|
|
|
|
zeros[0] = 0; zeros[1] = 0; zeros[2] = 0; zeros[3] = 0; |
|
1614
|
|
|
|
|
|
|
|
|
1615
|
795
|
50
|
|
|
|
|
for (i = 0; i < in_len; i++) { |
|
1616
|
795
|
|
|
|
|
|
c = in[i]; |
|
1617
|
|
|
|
|
|
|
|
|
1618
|
|
|
|
|
|
|
/* End of data marker */ |
|
1619
|
795
|
100
|
|
|
|
|
if (c == '~') { |
|
1620
|
14
|
50
|
|
|
|
|
if (i + 1 < in_len && in[i + 1] == '>') break; |
|
|
|
50
|
|
|
|
|
|
|
1621
|
|
|
|
|
|
|
/* Lone ~ is an error, but be lenient */ |
|
1622
|
0
|
|
|
|
|
|
continue; |
|
1623
|
|
|
|
|
|
|
} |
|
1624
|
|
|
|
|
|
|
|
|
1625
|
|
|
|
|
|
|
/* Skip whitespace */ |
|
1626
|
781
|
100
|
|
|
|
|
if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f') { |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
1627
|
24
|
|
|
|
|
|
continue; |
|
1628
|
|
|
|
|
|
|
} |
|
1629
|
|
|
|
|
|
|
|
|
1630
|
|
|
|
|
|
|
/* 'z' shorthand = 4 zero bytes (only valid when group is empty) */ |
|
1631
|
757
|
100
|
|
|
|
|
if (c == 'z') { |
|
1632
|
1
|
50
|
|
|
|
|
if (group_len != 0) return PDFMAKE_ECORRUPT; |
|
1633
|
1
|
50
|
|
|
|
|
if (pdfmake_buf_append(out, zeros, 4) != PDFMAKE_OK) { |
|
1634
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1635
|
|
|
|
|
|
|
} |
|
1636
|
1
|
|
|
|
|
|
continue; |
|
1637
|
|
|
|
|
|
|
} |
|
1638
|
|
|
|
|
|
|
|
|
1639
|
|
|
|
|
|
|
/* Valid ASCII85 chars are 33 ('!') to 117 ('u') */ |
|
1640
|
756
|
50
|
|
|
|
|
if (c < 33 || c > 117) return PDFMAKE_ECORRUPT; |
|
|
|
50
|
|
|
|
|
|
|
1641
|
|
|
|
|
|
|
|
|
1642
|
756
|
|
|
|
|
|
group[group_len++] = c - 33; |
|
1643
|
|
|
|
|
|
|
|
|
1644
|
756
|
100
|
|
|
|
|
if (group_len == 5) { |
|
1645
|
|
|
|
|
|
|
/* Decode 5 chars → 4 bytes */ |
|
1646
|
145
|
|
|
|
|
|
val = 0; |
|
1647
|
870
|
100
|
|
|
|
|
for (j = 0; j < 5; j++) { |
|
1648
|
725
|
|
|
|
|
|
val += group[j] * pdfmake_pow85[j]; |
|
1649
|
|
|
|
|
|
|
} |
|
1650
|
|
|
|
|
|
|
|
|
1651
|
145
|
|
|
|
|
|
bytes[0] = (val >> 24) & 0xFF; |
|
1652
|
145
|
|
|
|
|
|
bytes[1] = (val >> 16) & 0xFF; |
|
1653
|
145
|
|
|
|
|
|
bytes[2] = (val >> 8) & 0xFF; |
|
1654
|
145
|
|
|
|
|
|
bytes[3] = val & 0xFF; |
|
1655
|
|
|
|
|
|
|
|
|
1656
|
145
|
50
|
|
|
|
|
if (pdfmake_buf_append(out, bytes, 4) != PDFMAKE_OK) { |
|
1657
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1658
|
|
|
|
|
|
|
} |
|
1659
|
145
|
|
|
|
|
|
group_len = 0; |
|
1660
|
|
|
|
|
|
|
} |
|
1661
|
|
|
|
|
|
|
} |
|
1662
|
|
|
|
|
|
|
|
|
1663
|
|
|
|
|
|
|
/* Handle final short group (2-4 chars → 1-3 bytes) */ |
|
1664
|
14
|
100
|
|
|
|
|
if (group_len > 1) { |
|
1665
|
|
|
|
|
|
|
/* Pad with 'u' (84) to make 5 chars */ |
|
1666
|
29
|
100
|
|
|
|
|
for (j = group_len; j < 5; j++) { |
|
1667
|
19
|
|
|
|
|
|
group[j] = 84; /* 'u' - 33 */ |
|
1668
|
|
|
|
|
|
|
} |
|
1669
|
|
|
|
|
|
|
|
|
1670
|
10
|
|
|
|
|
|
val = 0; |
|
1671
|
60
|
100
|
|
|
|
|
for (j = 0; j < 5; j++) { |
|
1672
|
50
|
|
|
|
|
|
val += group[j] * pdfmake_pow85[j]; |
|
1673
|
|
|
|
|
|
|
} |
|
1674
|
|
|
|
|
|
|
|
|
1675
|
10
|
|
|
|
|
|
out_bytes = group_len - 1; /* 2 chars → 1 byte, etc. */ |
|
1676
|
10
|
|
|
|
|
|
bytes[0] = (val >> 24) & 0xFF; |
|
1677
|
10
|
|
|
|
|
|
bytes[1] = (val >> 16) & 0xFF; |
|
1678
|
10
|
|
|
|
|
|
bytes[2] = (val >> 8) & 0xFF; |
|
1679
|
10
|
|
|
|
|
|
bytes[3] = val & 0xFF; |
|
1680
|
|
|
|
|
|
|
|
|
1681
|
10
|
50
|
|
|
|
|
if (pdfmake_buf_append(out, bytes, out_bytes) != PDFMAKE_OK) { |
|
1682
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1683
|
|
|
|
|
|
|
} |
|
1684
|
4
|
50
|
|
|
|
|
} else if (group_len == 1) { |
|
1685
|
|
|
|
|
|
|
/* Single trailing char is invalid */ |
|
1686
|
0
|
|
|
|
|
|
return PDFMAKE_ECORRUPT; |
|
1687
|
|
|
|
|
|
|
} |
|
1688
|
|
|
|
|
|
|
|
|
1689
|
14
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1690
|
|
|
|
|
|
|
} |
|
1691
|
|
|
|
|
|
|
|
|
1692
|
12
|
|
|
|
|
|
pdfmake_err_t pdfmake_ascii85_encode(const uint8_t *in, size_t in_len, |
|
1693
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
1694
|
|
|
|
|
|
|
{ |
|
1695
|
|
|
|
|
|
|
size_t i; |
|
1696
|
|
|
|
|
|
|
uint32_t val; |
|
1697
|
|
|
|
|
|
|
uint8_t chars[5]; |
|
1698
|
|
|
|
|
|
|
size_t remain; |
|
1699
|
|
|
|
|
|
|
size_t j; |
|
1700
|
12
|
50
|
|
|
|
|
if (!out) return PDFMAKE_EINVAL; |
|
1701
|
|
|
|
|
|
|
|
|
1702
|
12
|
|
|
|
|
|
i = 0; |
|
1703
|
154
|
100
|
|
|
|
|
while (i + 4 <= in_len) { |
|
1704
|
|
|
|
|
|
|
/* Encode 4 bytes → 5 chars */ |
|
1705
|
142
|
|
|
|
|
|
val = ((uint32_t)in[i] << 24) | |
|
1706
|
142
|
|
|
|
|
|
((uint32_t)in[i+1] << 16) | |
|
1707
|
142
|
|
|
|
|
|
((uint32_t)in[i+2] << 8) | |
|
1708
|
142
|
|
|
|
|
|
(uint32_t)in[i+3]; |
|
1709
|
|
|
|
|
|
|
|
|
1710
|
142
|
100
|
|
|
|
|
if (val == 0) { |
|
1711
|
|
|
|
|
|
|
/* Use 'z' shorthand for 4 zero bytes */ |
|
1712
|
1
|
50
|
|
|
|
|
if (pdfmake_buf_append_byte(out, 'z') != PDFMAKE_OK) { |
|
1713
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1714
|
|
|
|
|
|
|
} |
|
1715
|
|
|
|
|
|
|
} else { |
|
1716
|
141
|
|
|
|
|
|
chars[4] = (val % 85) + 33; val /= 85; |
|
1717
|
141
|
|
|
|
|
|
chars[3] = (val % 85) + 33; val /= 85; |
|
1718
|
141
|
|
|
|
|
|
chars[2] = (val % 85) + 33; val /= 85; |
|
1719
|
141
|
|
|
|
|
|
chars[1] = (val % 85) + 33; val /= 85; |
|
1720
|
141
|
|
|
|
|
|
chars[0] = (val % 85) + 33; |
|
1721
|
|
|
|
|
|
|
|
|
1722
|
141
|
50
|
|
|
|
|
if (pdfmake_buf_append(out, chars, 5) != PDFMAKE_OK) { |
|
1723
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1724
|
|
|
|
|
|
|
} |
|
1725
|
|
|
|
|
|
|
} |
|
1726
|
142
|
|
|
|
|
|
i += 4; |
|
1727
|
|
|
|
|
|
|
} |
|
1728
|
|
|
|
|
|
|
|
|
1729
|
|
|
|
|
|
|
/* Handle final short group (1-3 bytes → 2-4 chars) */ |
|
1730
|
12
|
|
|
|
|
|
remain = in_len - i; |
|
1731
|
12
|
100
|
|
|
|
|
if (remain > 0) { |
|
1732
|
9
|
|
|
|
|
|
val = 0; |
|
1733
|
27
|
100
|
|
|
|
|
for (j = 0; j < remain; j++) { |
|
1734
|
18
|
|
|
|
|
|
val |= (uint32_t)in[i + j] << (24 - j * 8); |
|
1735
|
|
|
|
|
|
|
} |
|
1736
|
|
|
|
|
|
|
|
|
1737
|
9
|
|
|
|
|
|
chars[4] = (val % 85) + 33; val /= 85; |
|
1738
|
9
|
|
|
|
|
|
chars[3] = (val % 85) + 33; val /= 85; |
|
1739
|
9
|
|
|
|
|
|
chars[2] = (val % 85) + 33; val /= 85; |
|
1740
|
9
|
|
|
|
|
|
chars[1] = (val % 85) + 33; val /= 85; |
|
1741
|
9
|
|
|
|
|
|
chars[0] = (val % 85) + 33; |
|
1742
|
|
|
|
|
|
|
|
|
1743
|
|
|
|
|
|
|
/* Output remain+1 chars for remain bytes */ |
|
1744
|
9
|
50
|
|
|
|
|
if (pdfmake_buf_append(out, chars, remain + 1) != PDFMAKE_OK) { |
|
1745
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1746
|
|
|
|
|
|
|
} |
|
1747
|
|
|
|
|
|
|
} |
|
1748
|
|
|
|
|
|
|
|
|
1749
|
|
|
|
|
|
|
/* End of data marker */ |
|
1750
|
12
|
|
|
|
|
|
return pdfmake_buf_append(out, (const uint8_t *)"~>", 2); |
|
1751
|
|
|
|
|
|
|
} |
|
1752
|
|
|
|
|
|
|
|
|
1753
|
|
|
|
|
|
|
/*============================================================================ |
|
1754
|
|
|
|
|
|
|
* LZWDecode — §7.4.4 |
|
1755
|
|
|
|
|
|
|
*==========================================================================*/ |
|
1756
|
|
|
|
|
|
|
|
|
1757
|
|
|
|
|
|
|
#define LZW_CLEAR_CODE 256 |
|
1758
|
|
|
|
|
|
|
#define LZW_EOD_CODE 257 |
|
1759
|
|
|
|
|
|
|
#define LZW_MAX_CODE 4095 /* 12-bit codes max */ |
|
1760
|
|
|
|
|
|
|
|
|
1761
|
|
|
|
|
|
|
typedef struct { |
|
1762
|
|
|
|
|
|
|
int16_t prefix; /* Index of prefix string, or -1 for single byte */ |
|
1763
|
|
|
|
|
|
|
uint8_t suffix; /* Final byte */ |
|
1764
|
|
|
|
|
|
|
uint16_t length; /* Total string length */ |
|
1765
|
|
|
|
|
|
|
} lzw_entry_t; |
|
1766
|
|
|
|
|
|
|
|
|
1767
|
4
|
|
|
|
|
|
pdfmake_err_t pdfmake_lzw_decode(const uint8_t *in, size_t in_len, |
|
1768
|
|
|
|
|
|
|
const pdfmake_flate_params_t *params, |
|
1769
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
1770
|
|
|
|
|
|
|
{ |
|
1771
|
|
|
|
|
|
|
int early_change; |
|
1772
|
|
|
|
|
|
|
int i; |
|
1773
|
|
|
|
|
|
|
int next_code; |
|
1774
|
|
|
|
|
|
|
int code_bits; |
|
1775
|
|
|
|
|
|
|
int prev_code; |
|
1776
|
|
|
|
|
|
|
size_t bit_pos; |
|
1777
|
|
|
|
|
|
|
int b; |
|
1778
|
|
|
|
|
|
|
size_t byte_idx; |
|
1779
|
|
|
|
|
|
|
int bit_idx; |
|
1780
|
|
|
|
|
|
|
uint8_t first_byte; |
|
1781
|
|
|
|
|
|
|
int c; |
|
1782
|
|
|
|
|
|
|
lzw_entry_t *table; |
|
1783
|
|
|
|
|
|
|
uint8_t *stack; |
|
1784
|
|
|
|
|
|
|
pdfmake_buf_t decoded_pred; |
|
1785
|
|
|
|
|
|
|
pdfmake_err_t err; |
|
1786
|
4
|
50
|
|
|
|
|
if (!out) return PDFMAKE_EINVAL; |
|
1787
|
4
|
50
|
|
|
|
|
if (!in || in_len == 0) return PDFMAKE_OK; |
|
|
|
50
|
|
|
|
|
|
|
1788
|
|
|
|
|
|
|
|
|
1789
|
4
|
50
|
|
|
|
|
early_change = params ? params->early_change : 1; |
|
1790
|
|
|
|
|
|
|
|
|
1791
|
|
|
|
|
|
|
/* String table: each entry is (prefix_code, suffix_byte, length) */ |
|
1792
|
4
|
|
|
|
|
|
table = malloc(sizeof(lzw_entry_t) * (LZW_MAX_CODE + 1)); |
|
1793
|
4
|
50
|
|
|
|
|
if (!table) return PDFMAKE_ENOMEM; |
|
1794
|
|
|
|
|
|
|
|
|
1795
|
|
|
|
|
|
|
/* Stack for reversing strings during output */ |
|
1796
|
4
|
|
|
|
|
|
stack = malloc(LZW_MAX_CODE + 1); |
|
1797
|
4
|
50
|
|
|
|
|
if (!stack) { |
|
1798
|
0
|
|
|
|
|
|
free(table); |
|
1799
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1800
|
|
|
|
|
|
|
} |
|
1801
|
|
|
|
|
|
|
|
|
1802
|
|
|
|
|
|
|
/* Initialize table with single-byte entries 0-255 */ |
|
1803
|
1028
|
100
|
|
|
|
|
for (i = 0; i < 256; i++) { |
|
1804
|
1024
|
|
|
|
|
|
table[i].prefix = -1; |
|
1805
|
1024
|
|
|
|
|
|
table[i].suffix = (uint8_t)i; |
|
1806
|
1024
|
|
|
|
|
|
table[i].length = 1; |
|
1807
|
|
|
|
|
|
|
} |
|
1808
|
|
|
|
|
|
|
|
|
1809
|
4
|
|
|
|
|
|
next_code = 258; /* First available code after clear/eod */ |
|
1810
|
4
|
|
|
|
|
|
code_bits = 9; /* Current code width */ |
|
1811
|
4
|
|
|
|
|
|
prev_code = -1; /* Previous code, -1 = none */ |
|
1812
|
|
|
|
|
|
|
|
|
1813
|
|
|
|
|
|
|
/* Bit reader state */ |
|
1814
|
4
|
|
|
|
|
|
bit_pos = 0; /* Current bit position in input */ |
|
1815
|
|
|
|
|
|
|
|
|
1816
|
|
|
|
|
|
|
/* Helper to read next code (MSB first, unlike DEFLATE) */ |
|
1817
|
|
|
|
|
|
|
#define READ_CODE(code) do { \ |
|
1818
|
|
|
|
|
|
|
if (bit_pos + code_bits > in_len * 8) { code = LZW_EOD_CODE; break; } \ |
|
1819
|
|
|
|
|
|
|
code = 0; \ |
|
1820
|
|
|
|
|
|
|
for (b = 0; b < code_bits; b++) { \ |
|
1821
|
|
|
|
|
|
|
byte_idx = (bit_pos + b) / 8; \ |
|
1822
|
|
|
|
|
|
|
bit_idx = 7 - ((bit_pos + b) % 8); \ |
|
1823
|
|
|
|
|
|
|
code = (code << 1) | ((in[byte_idx] >> bit_idx) & 1); \ |
|
1824
|
|
|
|
|
|
|
} \ |
|
1825
|
|
|
|
|
|
|
bit_pos += code_bits; \ |
|
1826
|
|
|
|
|
|
|
} while(0) |
|
1827
|
|
|
|
|
|
|
|
|
1828
|
|
|
|
|
|
|
/* Output string for a code (uses stack to reverse) */ |
|
1829
|
|
|
|
|
|
|
#define OUTPUT_STRING(code) do { \ |
|
1830
|
|
|
|
|
|
|
int stack_pos = 0; \ |
|
1831
|
|
|
|
|
|
|
int c = code; \ |
|
1832
|
|
|
|
|
|
|
while (c >= 0) { \ |
|
1833
|
|
|
|
|
|
|
stack[stack_pos++] = table[c].suffix; \ |
|
1834
|
|
|
|
|
|
|
c = table[c].prefix; \ |
|
1835
|
|
|
|
|
|
|
} \ |
|
1836
|
|
|
|
|
|
|
while (stack_pos > 0) { \ |
|
1837
|
|
|
|
|
|
|
if (pdfmake_buf_append_byte(out, stack[--stack_pos]) != PDFMAKE_OK) { \ |
|
1838
|
|
|
|
|
|
|
free(table); free(stack); return PDFMAKE_ENOMEM; \ |
|
1839
|
|
|
|
|
|
|
} \ |
|
1840
|
|
|
|
|
|
|
} \ |
|
1841
|
|
|
|
|
|
|
} while(0) |
|
1842
|
|
|
|
|
|
|
|
|
1843
|
17
|
|
|
|
|
|
for (;;) { |
|
1844
|
|
|
|
|
|
|
int code; |
|
1845
|
201
|
100
|
|
|
|
|
READ_CODE(code); |
|
|
|
100
|
|
|
|
|
|
|
1846
|
|
|
|
|
|
|
|
|
1847
|
21
|
100
|
|
|
|
|
if (code == LZW_EOD_CODE) break; |
|
1848
|
|
|
|
|
|
|
|
|
1849
|
17
|
100
|
|
|
|
|
if (code == LZW_CLEAR_CODE) { |
|
1850
|
|
|
|
|
|
|
/* Reset table */ |
|
1851
|
4
|
|
|
|
|
|
next_code = 258; |
|
1852
|
4
|
|
|
|
|
|
code_bits = 9; |
|
1853
|
4
|
|
|
|
|
|
prev_code = -1; |
|
1854
|
4
|
|
|
|
|
|
continue; |
|
1855
|
|
|
|
|
|
|
} |
|
1856
|
|
|
|
|
|
|
|
|
1857
|
|
|
|
|
|
|
/* First code after clear must be < 256 */ |
|
1858
|
13
|
100
|
|
|
|
|
if (prev_code < 0) { |
|
1859
|
3
|
50
|
|
|
|
|
if (code >= 256) { |
|
1860
|
0
|
|
|
|
|
|
free(table); |
|
1861
|
0
|
|
|
|
|
|
free(stack); |
|
1862
|
0
|
|
|
|
|
|
return PDFMAKE_ECORRUPT; |
|
1863
|
|
|
|
|
|
|
} |
|
1864
|
9
|
100
|
|
|
|
|
OUTPUT_STRING(code); |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
1865
|
3
|
|
|
|
|
|
prev_code = code; |
|
1866
|
3
|
|
|
|
|
|
continue; |
|
1867
|
|
|
|
|
|
|
} |
|
1868
|
|
|
|
|
|
|
|
|
1869
|
10
|
100
|
|
|
|
|
if (code < next_code) { |
|
1870
|
|
|
|
|
|
|
/* Code is in table */ |
|
1871
|
36
|
100
|
|
|
|
|
OUTPUT_STRING(code); |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
1872
|
|
|
|
|
|
|
/* Get first byte of current string */ |
|
1873
|
8
|
|
|
|
|
|
c = code; |
|
1874
|
14
|
100
|
|
|
|
|
while (table[c].prefix >= 0) c = table[c].prefix; |
|
1875
|
8
|
|
|
|
|
|
first_byte = table[c].suffix; |
|
1876
|
2
|
50
|
|
|
|
|
} else if (code == next_code) { |
|
1877
|
|
|
|
|
|
|
/* Special case: code not yet in table (KwKwK) */ |
|
1878
|
2
|
|
|
|
|
|
c = prev_code; |
|
1879
|
2
|
50
|
|
|
|
|
while (table[c].prefix >= 0) c = table[c].prefix; |
|
1880
|
2
|
|
|
|
|
|
first_byte = table[c].suffix; |
|
1881
|
|
|
|
|
|
|
/* Output prev_string + first_byte */ |
|
1882
|
6
|
100
|
|
|
|
|
OUTPUT_STRING(prev_code); |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
1883
|
2
|
50
|
|
|
|
|
if (pdfmake_buf_append_byte(out, first_byte) != PDFMAKE_OK) { |
|
1884
|
0
|
|
|
|
|
|
free(table); |
|
1885
|
0
|
|
|
|
|
|
free(stack); |
|
1886
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1887
|
|
|
|
|
|
|
} |
|
1888
|
|
|
|
|
|
|
} else { |
|
1889
|
|
|
|
|
|
|
/* Invalid code */ |
|
1890
|
0
|
|
|
|
|
|
free(table); |
|
1891
|
0
|
|
|
|
|
|
free(stack); |
|
1892
|
0
|
|
|
|
|
|
return PDFMAKE_ECORRUPT; |
|
1893
|
|
|
|
|
|
|
} |
|
1894
|
|
|
|
|
|
|
|
|
1895
|
|
|
|
|
|
|
/* Add new entry: prev_string + first_byte */ |
|
1896
|
10
|
50
|
|
|
|
|
if (next_code <= LZW_MAX_CODE) { |
|
1897
|
10
|
|
|
|
|
|
table[next_code].prefix = prev_code; |
|
1898
|
10
|
|
|
|
|
|
table[next_code].suffix = first_byte; |
|
1899
|
10
|
|
|
|
|
|
table[next_code].length = table[prev_code].length + 1; |
|
1900
|
10
|
|
|
|
|
|
next_code++; |
|
1901
|
|
|
|
|
|
|
|
|
1902
|
|
|
|
|
|
|
/* Increase code size based on EarlyChange parameter */ |
|
1903
|
10
|
50
|
|
|
|
|
if (early_change) { |
|
1904
|
|
|
|
|
|
|
/* Increase BEFORE next_code reaches limit */ |
|
1905
|
10
|
50
|
|
|
|
|
if (next_code == (1 << code_bits) && code_bits < 12) { |
|
|
|
0
|
|
|
|
|
|
|
1906
|
0
|
|
|
|
|
|
code_bits++; |
|
1907
|
|
|
|
|
|
|
} |
|
1908
|
|
|
|
|
|
|
} else { |
|
1909
|
|
|
|
|
|
|
/* Increase AFTER next_code reaches limit */ |
|
1910
|
0
|
0
|
|
|
|
|
if (next_code == (1 << code_bits) + 1 && code_bits < 12) { |
|
|
|
0
|
|
|
|
|
|
|
1911
|
0
|
|
|
|
|
|
code_bits++; |
|
1912
|
|
|
|
|
|
|
} |
|
1913
|
|
|
|
|
|
|
} |
|
1914
|
|
|
|
|
|
|
} |
|
1915
|
|
|
|
|
|
|
|
|
1916
|
10
|
|
|
|
|
|
prev_code = code; |
|
1917
|
|
|
|
|
|
|
} |
|
1918
|
|
|
|
|
|
|
|
|
1919
|
|
|
|
|
|
|
#undef READ_CODE |
|
1920
|
|
|
|
|
|
|
#undef OUTPUT_STRING |
|
1921
|
|
|
|
|
|
|
|
|
1922
|
4
|
|
|
|
|
|
free(table); |
|
1923
|
4
|
|
|
|
|
|
free(stack); |
|
1924
|
|
|
|
|
|
|
|
|
1925
|
|
|
|
|
|
|
/* Apply predictor if specified */ |
|
1926
|
4
|
50
|
|
|
|
|
if (params && params->predictor > 1) { |
|
|
|
50
|
|
|
|
|
|
|
1927
|
0
|
0
|
|
|
|
|
if (pdfmake_buf_init(&decoded_pred) != PDFMAKE_OK) { |
|
1928
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1929
|
|
|
|
|
|
|
} |
|
1930
|
|
|
|
|
|
|
|
|
1931
|
0
|
0
|
|
|
|
|
if (params->predictor == 2) { |
|
1932
|
0
|
|
|
|
|
|
err = pdfmake_tiff_predictor_decode(params->colors, params->bits_per_comp, |
|
1933
|
0
|
|
|
|
|
|
params->columns, out->data, out->len, |
|
1934
|
|
|
|
|
|
|
&decoded_pred); |
|
1935
|
0
|
0
|
|
|
|
|
} else if (params->predictor >= 10 && params->predictor <= 15) { |
|
|
|
0
|
|
|
|
|
|
|
1936
|
0
|
|
|
|
|
|
err = pdfmake_predictor_decode(params->predictor, params->colors, |
|
1937
|
0
|
|
|
|
|
|
params->bits_per_comp, params->columns, |
|
1938
|
0
|
|
|
|
|
|
out->data, out->len, &decoded_pred); |
|
1939
|
|
|
|
|
|
|
} else { |
|
1940
|
0
|
|
|
|
|
|
pdfmake_buf_free(&decoded_pred); |
|
1941
|
0
|
|
|
|
|
|
return PDFMAKE_EINVAL; |
|
1942
|
|
|
|
|
|
|
} |
|
1943
|
|
|
|
|
|
|
|
|
1944
|
0
|
0
|
|
|
|
|
if (err != PDFMAKE_OK) { |
|
1945
|
0
|
|
|
|
|
|
pdfmake_buf_free(&decoded_pred); |
|
1946
|
0
|
|
|
|
|
|
return err; |
|
1947
|
|
|
|
|
|
|
} |
|
1948
|
|
|
|
|
|
|
|
|
1949
|
|
|
|
|
|
|
/* Swap buffers */ |
|
1950
|
0
|
|
|
|
|
|
pdfmake_buf_free(out); |
|
1951
|
0
|
|
|
|
|
|
*out = decoded_pred; |
|
1952
|
|
|
|
|
|
|
} |
|
1953
|
|
|
|
|
|
|
|
|
1954
|
4
|
|
|
|
|
|
return PDFMAKE_OK; |
|
1955
|
|
|
|
|
|
|
} |
|
1956
|
|
|
|
|
|
|
|
|
1957
|
|
|
|
|
|
|
/*============================================================================ |
|
1958
|
|
|
|
|
|
|
* RunLengthDecode — §7.4.5 |
|
1959
|
|
|
|
|
|
|
*==========================================================================*/ |
|
1960
|
|
|
|
|
|
|
|
|
1961
|
13
|
|
|
|
|
|
pdfmake_err_t pdfmake_rle_decode(const uint8_t *in, size_t in_len, |
|
1962
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
1963
|
|
|
|
|
|
|
{ |
|
1964
|
|
|
|
|
|
|
size_t i; |
|
1965
|
|
|
|
|
|
|
uint8_t len_byte; |
|
1966
|
|
|
|
|
|
|
size_t count; |
|
1967
|
|
|
|
|
|
|
uint8_t byte; |
|
1968
|
|
|
|
|
|
|
size_t j; |
|
1969
|
13
|
50
|
|
|
|
|
if (!out) return PDFMAKE_EINVAL; |
|
1970
|
13
|
50
|
|
|
|
|
if (!in || in_len == 0) return PDFMAKE_OK; |
|
|
|
100
|
|
|
|
|
|
|
1971
|
|
|
|
|
|
|
|
|
1972
|
12
|
|
|
|
|
|
i = 0; |
|
1973
|
34
|
100
|
|
|
|
|
while (i < in_len) { |
|
1974
|
33
|
|
|
|
|
|
len_byte = in[i++]; |
|
1975
|
|
|
|
|
|
|
|
|
1976
|
33
|
100
|
|
|
|
|
if (len_byte == 128) { |
|
1977
|
|
|
|
|
|
|
/* EOD marker */ |
|
1978
|
11
|
|
|
|
|
|
break; |
|
1979
|
22
|
100
|
|
|
|
|
} else if (len_byte <= 127) { |
|
1980
|
|
|
|
|
|
|
/* Literal run: copy next len_byte+1 bytes */ |
|
1981
|
14
|
|
|
|
|
|
count = len_byte + 1; |
|
1982
|
14
|
50
|
|
|
|
|
if (i + count > in_len) return PDFMAKE_ECORRUPT; |
|
1983
|
14
|
50
|
|
|
|
|
if (pdfmake_buf_append(out, in + i, count) != PDFMAKE_OK) { |
|
1984
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1985
|
|
|
|
|
|
|
} |
|
1986
|
14
|
|
|
|
|
|
i += count; |
|
1987
|
|
|
|
|
|
|
} else { |
|
1988
|
|
|
|
|
|
|
/* Repeat run: repeat next byte 257-len_byte times */ |
|
1989
|
8
|
|
|
|
|
|
count = 257 - len_byte; |
|
1990
|
8
|
50
|
|
|
|
|
if (i >= in_len) return PDFMAKE_ECORRUPT; |
|
1991
|
8
|
|
|
|
|
|
byte = in[i++]; |
|
1992
|
646
|
100
|
|
|
|
|
for (j = 0; j < count; j++) { |
|
1993
|
638
|
50
|
|
|
|
|
if (pdfmake_buf_append_byte(out, byte) != PDFMAKE_OK) { |
|
1994
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
1995
|
|
|
|
|
|
|
} |
|
1996
|
|
|
|
|
|
|
} |
|
1997
|
|
|
|
|
|
|
} |
|
1998
|
|
|
|
|
|
|
} |
|
1999
|
|
|
|
|
|
|
|
|
2000
|
12
|
|
|
|
|
|
return PDFMAKE_OK; |
|
2001
|
|
|
|
|
|
|
} |
|
2002
|
|
|
|
|
|
|
|
|
2003
|
6
|
|
|
|
|
|
pdfmake_err_t pdfmake_rle_encode(const uint8_t *in, size_t in_len, |
|
2004
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
2005
|
|
|
|
|
|
|
{ |
|
2006
|
|
|
|
|
|
|
size_t i; |
|
2007
|
|
|
|
|
|
|
size_t run_len; |
|
2008
|
|
|
|
|
|
|
uint8_t len_byte; |
|
2009
|
|
|
|
|
|
|
size_t lit_start; |
|
2010
|
|
|
|
|
|
|
size_t lit_len; |
|
2011
|
6
|
50
|
|
|
|
|
if (!out) return PDFMAKE_EINVAL; |
|
2012
|
6
|
50
|
|
|
|
|
if (!in || in_len == 0) { |
|
|
|
100
|
|
|
|
|
|
|
2013
|
|
|
|
|
|
|
/* Empty input: just EOD */ |
|
2014
|
1
|
|
|
|
|
|
return pdfmake_buf_append_byte(out, 128); |
|
2015
|
|
|
|
|
|
|
} |
|
2016
|
|
|
|
|
|
|
|
|
2017
|
5
|
|
|
|
|
|
i = 0; |
|
2018
|
22
|
100
|
|
|
|
|
while (i < in_len) { |
|
2019
|
|
|
|
|
|
|
/* Look for repeat run (3+ consecutive identical bytes) */ |
|
2020
|
17
|
|
|
|
|
|
run_len = 1; |
|
2021
|
519
|
100
|
|
|
|
|
while (i + run_len < in_len && in[i + run_len] == in[i] && run_len < 128) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
2022
|
502
|
|
|
|
|
|
run_len++; |
|
2023
|
|
|
|
|
|
|
} |
|
2024
|
|
|
|
|
|
|
|
|
2025
|
17
|
100
|
|
|
|
|
if (run_len >= 3) { |
|
2026
|
|
|
|
|
|
|
/* Emit repeat run */ |
|
2027
|
6
|
|
|
|
|
|
len_byte = (uint8_t)(257 - run_len); |
|
2028
|
12
|
|
|
|
|
|
if (pdfmake_buf_append_byte(out, len_byte) != PDFMAKE_OK || |
|
2029
|
6
|
|
|
|
|
|
pdfmake_buf_append_byte(out, in[i]) != PDFMAKE_OK) { |
|
2030
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
2031
|
|
|
|
|
|
|
} |
|
2032
|
6
|
|
|
|
|
|
i += run_len; |
|
2033
|
|
|
|
|
|
|
} else { |
|
2034
|
|
|
|
|
|
|
/* Collect literal run (non-repeating bytes) */ |
|
2035
|
11
|
|
|
|
|
|
lit_start = i; |
|
2036
|
11
|
|
|
|
|
|
lit_len = 0; |
|
2037
|
|
|
|
|
|
|
|
|
2038
|
1081
|
100
|
|
|
|
|
while (i < in_len && lit_len < 128) { |
|
|
|
100
|
|
|
|
|
|
|
2039
|
|
|
|
|
|
|
/* Check if next 3+ bytes are identical (start repeat run) */ |
|
2040
|
1070
|
100
|
|
|
|
|
if (i + 2 < in_len && in[i] == in[i+1] && in[i] == in[i+2]) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
2041
|
0
|
|
|
|
|
|
break; |
|
2042
|
|
|
|
|
|
|
} |
|
2043
|
1070
|
|
|
|
|
|
i++; |
|
2044
|
1070
|
|
|
|
|
|
lit_len++; |
|
2045
|
|
|
|
|
|
|
} |
|
2046
|
|
|
|
|
|
|
|
|
2047
|
11
|
50
|
|
|
|
|
if (lit_len > 0) { |
|
2048
|
11
|
|
|
|
|
|
len_byte = (uint8_t)(lit_len - 1); |
|
2049
|
22
|
|
|
|
|
|
if (pdfmake_buf_append_byte(out, len_byte) != PDFMAKE_OK || |
|
2050
|
11
|
|
|
|
|
|
pdfmake_buf_append(out, in + lit_start, lit_len) != PDFMAKE_OK) { |
|
2051
|
0
|
|
|
|
|
|
return PDFMAKE_ENOMEM; |
|
2052
|
|
|
|
|
|
|
} |
|
2053
|
|
|
|
|
|
|
} |
|
2054
|
|
|
|
|
|
|
} |
|
2055
|
|
|
|
|
|
|
} |
|
2056
|
|
|
|
|
|
|
|
|
2057
|
|
|
|
|
|
|
/* EOD marker */ |
|
2058
|
5
|
|
|
|
|
|
return pdfmake_buf_append_byte(out, 128); |
|
2059
|
|
|
|
|
|
|
} |
|
2060
|
|
|
|
|
|
|
|
|
2061
|
|
|
|
|
|
|
/*============================================================================ |
|
2062
|
|
|
|
|
|
|
* Remaining stub filters (CCITTFaxDecode implemented in pdfmake_ccitt.c) |
|
2063
|
|
|
|
|
|
|
*==========================================================================*/ |
|
2064
|
|
|
|
|
|
|
|
|
2065
|
|
|
|
|
|
|
/* JBIG2 is complex - stub for now, requires external library */ |
|
2066
|
0
|
|
|
|
|
|
pdfmake_err_t pdfmake_jbig2_decode(const uint8_t *in, size_t in_len, |
|
2067
|
|
|
|
|
|
|
const pdfmake_obj_t *params, |
|
2068
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
2069
|
|
|
|
|
|
|
{ |
|
2070
|
|
|
|
|
|
|
(void)in; (void)in_len; (void)params; (void)out; |
|
2071
|
0
|
|
|
|
|
|
return PDFMAKE_EUNSUPPORTED; |
|
2072
|
|
|
|
|
|
|
} |
|
2073
|
|
|
|
|
|
|
|
|
2074
|
0
|
|
|
|
|
|
pdfmake_err_t pdfmake_jpx_decode(const uint8_t *in, size_t in_len, |
|
2075
|
|
|
|
|
|
|
const pdfmake_obj_t *params, |
|
2076
|
|
|
|
|
|
|
pdfmake_buf_t *out) |
|
2077
|
|
|
|
|
|
|
{ |
|
2078
|
|
|
|
|
|
|
/* JPXDecode: passthrough (JPEG 2000 data used as-is by PDF readers) */ |
|
2079
|
|
|
|
|
|
|
(void)params; |
|
2080
|
0
|
|
|
|
|
|
return pdfmake_buf_append(out, in, in_len); |
|
2081
|
|
|
|
|
|
|
} |