File Coverage

src/pdfmake_filter.c
Criterion Covered Total %
statement 704 936 75.2
branch 424 720 58.8
condition n/a
subroutine n/a
pod n/a
total 1128 1656 68.1


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             }