Coverage Report

Created: 2026-07-16 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jbig2dec/jbig2_text.c
Line
Count
Source
1
/* Copyright (C) 2001-2023 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
/*
17
    jbig2dec
18
*/
19
20
#ifdef HAVE_CONFIG_H
21
#include "config.h"
22
#endif
23
#include "os_types.h"
24
25
#include <stddef.h>
26
#include <string.h>             /* memset() */
27
28
#include "jbig2.h"
29
#include "jbig2_priv.h"
30
#include "jbig2_arith.h"
31
#include "jbig2_arith_int.h"
32
#include "jbig2_arith_iaid.h"
33
#include "jbig2_generic.h"
34
#include "jbig2_huffman.h"
35
#include "jbig2_image.h"
36
#include "jbig2_page.h"
37
#include "jbig2_refinement.h"
38
#include "jbig2_segment.h"
39
#include "jbig2_symbol_dict.h"
40
#include "jbig2_text.h"
41
42
/**
43
 * jbig2_decode_text_region: decode a text region segment
44
 *
45
 * @ctx: jbig2 decoder context
46
 * @segment: jbig2 segment (header) structure
47
 * @params: parameters from the text region header
48
 * @dicts: an array of referenced symbol dictionaries
49
 * @n_dicts: the number of referenced symbol dictionaries
50
 * @image: image structure in which to store the decoded region bitmap
51
 *
52
 * Implements the text region decoding procedure
53
 * described in section 6.4 of the JBIG2 spec.
54
 *
55
 * returns: 0 on success
56
 **/
57
int
58
jbig2_decode_text_region(Jbig2Ctx *ctx, Jbig2Segment *segment,
59
                         const Jbig2TextRegionParams *params,
60
                         const Jbig2SymbolDict *const *dicts, const uint32_t n_dicts,
61
                         Jbig2Image *image, Jbig2ArithCx *GR_stats, Jbig2ArithState *as, Jbig2WordStream *ws)
62
11.1k
{
63
    /* relevant bits of 6.4.4 */
64
11.1k
    uint32_t NINSTANCES;
65
11.1k
    uint32_t ID;
66
11.1k
    int32_t STRIPT;
67
11.1k
    int32_t FIRSTS;
68
11.1k
    int32_t DT;
69
11.1k
    int32_t DFS;
70
11.1k
    int32_t IDS;
71
11.1k
    int32_t CURS;
72
11.1k
    int32_t CURT;
73
11.1k
    int S, T;
74
11.1k
    int x, y;
75
11.1k
    bool first_symbol;
76
11.1k
    uint32_t index, SBNUMSYMS;
77
11.1k
    Jbig2Image *IB = NULL;
78
11.1k
    Jbig2Image *IBO = NULL;
79
11.1k
    Jbig2Image *refimage = NULL;
80
11.1k
    Jbig2HuffmanState *hs = NULL;
81
11.1k
    Jbig2HuffmanTable *SBSYMCODES = NULL;
82
11.1k
    int code = 0;
83
11.1k
    int RI;
84
85
11.1k
    SBNUMSYMS = 0;
86
36.1k
    for (index = 0; index < n_dicts; index++) {
87
25.0k
        SBNUMSYMS += dicts[index]->n_symbols;
88
25.0k
    }
89
11.1k
    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "symbol list contains %d glyphs in %d dictionaries", SBNUMSYMS, n_dicts);
90
91
11.1k
    if (params->SBHUFF) {
92
2.36k
        Jbig2HuffmanTable *runcodes = NULL;
93
2.36k
        Jbig2HuffmanParams runcodeparams;
94
2.36k
        Jbig2HuffmanLine runcodelengths[35];
95
2.36k
        Jbig2HuffmanLine *symcodelengths = NULL;
96
2.36k
        Jbig2HuffmanParams symcodeparams;
97
2.36k
        int err, len, range, r;
98
99
2.36k
        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "huffman coded text region");
100
2.36k
        hs = jbig2_huffman_new(ctx, ws);
101
2.36k
        if (hs == NULL)
102
1
            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region");
103
104
        /* 7.4.3.1.7 - decode symbol ID Huffman table */
105
        /* this is actually part of the segment header, but it is more
106
           convenient to handle it here */
107
108
        /* parse and build the runlength code huffman table */
109
85.2k
        for (index = 0; index < 35; index++) {
110
82.8k
            runcodelengths[index].PREFLEN = jbig2_huffman_get_bits(hs, 4, &code);
111
82.8k
            if (code < 0) {
112
0
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to read huffman runcode lengths");
113
0
                goto cleanup1;
114
0
            }
115
82.8k
            if (code > 0) {
116
0
                jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB decoding huffman runcode lengths");
117
0
                goto cleanup1;
118
0
            }
119
82.8k
            runcodelengths[index].RANGELEN = 0;
120
82.8k
            runcodelengths[index].RANGELOW = index;
121
82.8k
            jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "  read runcode%d length %d", index, runcodelengths[index].PREFLEN);
122
82.8k
        }
123
2.36k
        runcodeparams.HTOOB = 0;
124
2.36k
        runcodeparams.lines = runcodelengths;
125
2.36k
        runcodeparams.n_lines = 35;
126
2.36k
        runcodes = jbig2_build_huffman_table(ctx, &runcodeparams);
127
2.36k
        if (runcodes == NULL) {
128
14
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "error constructing symbol ID runcode table");
129
14
            goto cleanup1;
130
14
        }
131
132
        /* decode the symbol ID code lengths using the runlength table */
133
2.35k
        symcodelengths = jbig2_new(ctx, Jbig2HuffmanLine, SBNUMSYMS);
134
2.35k
        if (symcodelengths == NULL) {
135
3
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "failed to allocate memory when reading symbol ID huffman table");
136
3
            goto cleanup1;
137
3
        }
138
2.35k
        index = 0;
139
14.6M
        while (index < SBNUMSYMS) {
140
14.6M
            code = jbig2_huffman_get(hs, runcodes, &err);
141
14.6M
            if (err < 0) {
142
21
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "error reading symbol ID huffman table");
143
21
                goto cleanup1;
144
21
            }
145
14.6M
            if (err > 0) {
146
0
                code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB decoding symbol ID huffman table");
147
0
                goto cleanup1;
148
0
            }
149
14.6M
            if (code < 0 || code >= 35) {
150
0
                code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "symbol ID huffman table out of range");
151
0
                goto cleanup1;
152
0
            }
153
154
14.6M
            if (code < 32) {
155
14.3M
                len = code;
156
14.3M
                range = 1;
157
14.3M
            } else {
158
363k
                if (code == 32) {
159
92.8k
                    if (index < 1) {
160
2
                        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "error decoding symbol ID table: run length with no antecedent");
161
2
                        goto cleanup1;
162
2
                    }
163
92.8k
                    len = symcodelengths[index - 1].PREFLEN;
164
270k
                } else {
165
270k
                    len = 0;    /* code == 33 or 34 */
166
270k
                }
167
363k
                err = 0;
168
363k
                if (code == 32)
169
92.8k
                    range = jbig2_huffman_get_bits(hs, 2, &err) + 3;
170
270k
                else if (code == 33)
171
43.5k
                    range = jbig2_huffman_get_bits(hs, 3, &err) + 3;
172
227k
                else if (code == 34)
173
227k
                    range = jbig2_huffman_get_bits(hs, 7, &err) + 11;
174
363k
                if (err < 0) {
175
0
                    code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to read huffman code");
176
0
                    goto cleanup1;
177
0
                }
178
363k
                if (err > 0) {
179
0
                    code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB decoding huffman code");
180
0
                    goto cleanup1;
181
0
                }
182
363k
            }
183
14.6M
            jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "  read runcode%d at index %d (length %d range %d)", code, index, len, range);
184
14.6M
            if (index + range > SBNUMSYMS) {
185
1.81k
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
186
1.81k
                            "runlength extends %d entries beyond the end of symbol ID table", index + range - SBNUMSYMS);
187
1.81k
                range = SBNUMSYMS - index;
188
1.81k
            }
189
32.2M
            for (r = 0; r < range; r++) {
190
17.6M
                symcodelengths[index + r].PREFLEN = len;
191
17.6M
                symcodelengths[index + r].RANGELEN = 0;
192
17.6M
                symcodelengths[index + r].RANGELOW = index + r;
193
17.6M
            }
194
14.6M
            index += r;
195
14.6M
        }
196
197
2.32k
        if (index < SBNUMSYMS) {
198
0
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "runlength codes do not cover the available symbol set");
199
0
            goto cleanup1;
200
0
        }
201
202
2.32k
        symcodeparams.HTOOB = 0;
203
2.32k
        symcodeparams.lines = symcodelengths;
204
2.32k
        symcodeparams.n_lines = SBNUMSYMS;
205
206
        /* skip to byte boundary */
207
2.32k
        err = jbig2_huffman_skip(hs);
208
2.32k
        if (err < 0)
209
0
        {
210
0
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to skip to next byte when building huffman table");
211
0
            goto cleanup1;
212
0
        }
213
214
        /* finally, construct the symbol ID huffman table itself */
215
2.32k
        SBSYMCODES = jbig2_build_huffman_table(ctx, &symcodeparams);
216
217
2.36k
cleanup1:
218
2.36k
        jbig2_free(ctx->allocator, symcodelengths);
219
2.36k
        jbig2_release_huffman_table(ctx, runcodes);
220
221
2.36k
        if (SBSYMCODES == NULL) {
222
95
            jbig2_huffman_free(ctx, hs);
223
95
            return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to construct symbol ID huffman table");
224
95
        }
225
2.36k
    }
226
227
    /* 6.4.5 (1) */
228
11.0k
    jbig2_image_clear(ctx, image, params->SBDEFPIXEL);
229
230
    /* 6.4.6 */
231
11.0k
    if (params->SBHUFF) {
232
2.27k
        STRIPT = jbig2_huffman_get(hs, params->SBHUFFDT, &code);
233
8.74k
    } else {
234
8.74k
        code = jbig2_arith_int_decode(ctx, params->IADT, as, &STRIPT);
235
8.74k
    }
236
11.0k
    if (code < 0) {
237
4
        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode strip T");
238
4
        goto cleanup2;
239
4
    }
240
11.0k
    if (code > 0) {
241
3
        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding strip T");
242
3
        goto cleanup2;
243
3
    }
244
245
    /* 6.4.5 (2) */
246
11.0k
    STRIPT *= -(params->SBSTRIPS);
247
11.0k
    FIRSTS = 0;
248
11.0k
    NINSTANCES = 0;
249
250
    /* 6.4.5 (3) */
251
413k
    while (NINSTANCES < params->SBNUMINSTANCES) {
252
        /* (3b) */
253
402k
        if (params->SBHUFF) {
254
372k
            DT = jbig2_huffman_get(hs, params->SBHUFFDT, &code);
255
372k
        } else {
256
30.5k
            code = jbig2_arith_int_decode(ctx, params->IADT, as, &DT);
257
30.5k
        }
258
402k
        if (code < 0) {
259
1
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode delta T");
260
1
            goto cleanup2;
261
1
        }
262
402k
        if (code > 0) {
263
32
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding delta T");
264
32
            goto cleanup2;
265
32
        }
266
402k
        DT *= params->SBSTRIPS;
267
402k
        STRIPT += DT;
268
269
402k
        first_symbol = TRUE;
270
        /* 6.4.5 (3c) - decode symbols in strip */
271
25.6M
        for (;;) {
272
            /* (3c.i) */
273
25.6M
            if (first_symbol) {
274
                /* 6.4.7 */
275
402k
                if (params->SBHUFF) {
276
372k
                    DFS = jbig2_huffman_get(hs, params->SBHUFFFS, &code);
277
372k
                } else {
278
30.5k
                    code = jbig2_arith_int_decode(ctx, params->IAFS, as, &DFS);
279
30.5k
                }
280
402k
                if (code < 0) {
281
1
                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode strip symbol S-difference");
282
1
                    goto cleanup2;
283
1
                }
284
402k
                if (code > 0) {
285
68
                    code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding strip symbol S-difference");
286
68
                    goto cleanup2;
287
68
                }
288
402k
                FIRSTS += DFS;
289
402k
                CURS = FIRSTS;
290
402k
                first_symbol = FALSE;
291
25.2M
            } else {
292
25.2M
                if (NINSTANCES > params->SBNUMINSTANCES) {
293
8.45k
                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "too many NINSTANCES (%d) decoded", NINSTANCES);
294
8.45k
                    break;
295
8.45k
                }
296
                /* (3c.ii) / 6.4.8 */
297
25.2M
                if (params->SBHUFF) {
298
8.48M
                    IDS = jbig2_huffman_get(hs, params->SBHUFFDS, &code);
299
16.7M
                } else {
300
16.7M
                    code = jbig2_arith_int_decode(ctx, params->IADS, as, &IDS);
301
16.7M
                }
302
25.2M
                if (code < 0) {
303
107
                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode symbol instance S coordinate");
304
107
                    goto cleanup2;
305
107
                }
306
25.2M
                if (code > 0) {
307
394k
                    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "OOB obtained when decoding symbol instance S coordinate signals end of strip with T value %d", DT);
308
394k
                    break;
309
394k
                }
310
24.8M
                CURS += IDS + params->SBDSOFFSET;
311
24.8M
            }
312
313
            /* (3c.iii) / 6.4.9 */
314
25.2M
            if (params->SBSTRIPS == 1) {
315
23.2M
                CURT = 0;
316
23.2M
            } else if (params->SBHUFF) {
317
1.88M
                CURT = jbig2_huffman_get_bits(hs, params->LOGSBSTRIPS, &code);
318
1.88M
            } else {
319
158k
                code = jbig2_arith_int_decode(ctx, params->IAIT, as, &CURT);
320
158k
            }
321
25.2M
            if (code < 0) {
322
0
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode symbol instance T coordinate");
323
0
                goto cleanup2;
324
0
            }
325
25.2M
            if (code > 0) {
326
62
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "OOB obtained when decoding symbol instance T coordinate");
327
62
                goto cleanup2;
328
62
            }
329
25.2M
            T = STRIPT + CURT;
330
331
            /* (3b.iv) / 6.4.10 - decode the symbol ID */
332
25.2M
            if (params->SBHUFF) {
333
8.49M
                ID = jbig2_huffman_get(hs, SBSYMCODES, &code);
334
16.7M
            } else {
335
16.7M
                code = jbig2_arith_iaid_decode(ctx, params->IAID, as, (int *)&ID);
336
16.7M
            }
337
25.2M
            if (code < 0) {
338
36
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to obtain symbol instance symbol ID");
339
36
                goto cleanup2;
340
36
            }
341
25.2M
            if (code > 0) {
342
0
                code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding symbol instance symbol ID");
343
0
                goto cleanup2;
344
0
            }
345
25.2M
            if (ID >= SBNUMSYMS) {
346
7.68M
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "ignoring out of range symbol ID (%d/%d)", ID, SBNUMSYMS);
347
7.68M
                IB = NULL;
348
17.5M
            } else {
349
                /* (3c.v) / 6.4.11 - look up the symbol bitmap IB */
350
17.5M
                uint32_t id = ID;
351
352
17.5M
                index = 0;
353
22.1M
                while (id >= dicts[index]->n_symbols)
354
4.55M
                    id -= dicts[index++]->n_symbols;
355
17.5M
                if (dicts[index]->glyphs[id] == NULL) {
356
4.20M
                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "missing glyph (%d/%d), ignoring", index, id);
357
13.3M
                } else {
358
13.3M
                    IB = jbig2_image_reference(ctx, dicts[index]->glyphs[id]);
359
13.3M
                }
360
17.5M
            }
361
25.2M
            if (params->SBREFINE) {
362
4.55M
                if (params->SBHUFF) {
363
4.05M
                    RI = jbig2_huffman_get_bits(hs, 1, &code);
364
4.05M
                } else {
365
504k
                    code = jbig2_arith_int_decode(ctx, params->IARI, as, &RI);
366
504k
                }
367
4.55M
                if (code < 0) {
368
0
                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode symbol bitmap refinement indicator");
369
0
                    goto cleanup2;
370
0
                }
371
4.55M
                if (code > 0) {
372
17
                    code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding symbol bitmap refinement indicator");
373
17
                    goto cleanup2;
374
17
                }
375
20.7M
            } else {
376
20.7M
                RI = 0;
377
20.7M
            }
378
25.2M
            if (RI) {
379
502k
                Jbig2RefinementRegionParams rparams;
380
502k
                int32_t RDW, RDH, RDX, RDY;
381
502k
                size_t BMSIZE = 0;
382
502k
                int code1 = 0;
383
502k
                int code2 = 0;
384
502k
                int code3 = 0;
385
502k
                int code4 = 0;
386
502k
                int code5 = 0;
387
502k
                int code6 = 0;
388
389
                /* 6.4.11 (1, 2, 3, 4) */
390
502k
                if (!params->SBHUFF) {
391
492k
                    code1 = jbig2_arith_int_decode(ctx, params->IARDW, as, &RDW);
392
492k
                    code2 = jbig2_arith_int_decode(ctx, params->IARDH, as, &RDH);
393
492k
                    code3 = jbig2_arith_int_decode(ctx, params->IARDX, as, &RDX);
394
492k
                    code4 = jbig2_arith_int_decode(ctx, params->IARDY, as, &RDY);
395
492k
                } else {
396
10.6k
                    RDW = jbig2_huffman_get(hs, params->SBHUFFRDW, &code1);
397
10.6k
                    RDH = jbig2_huffman_get(hs, params->SBHUFFRDH, &code2);
398
10.6k
                    RDX = jbig2_huffman_get(hs, params->SBHUFFRDX, &code3);
399
10.6k
                    RDY = jbig2_huffman_get(hs, params->SBHUFFRDY, &code4);
400
10.6k
                    BMSIZE = jbig2_huffman_get(hs, params->SBHUFFRSIZE, &code5);
401
10.6k
                    code6 = jbig2_huffman_skip(hs);
402
10.6k
                }
403
404
502k
                if (code1 < 0 || code2 < 0 || code3 < 0 || code4 < 0 || code5 < 0 || code6 < 0) {
405
7
                    code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode data");
406
7
                    goto cleanup2;
407
7
                }
408
502k
                if (code1 > 0 || code2 > 0 || code3 > 0 || code4 > 0 || code5 > 0 || code6 > 0) {
409
44
                    code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "OOB obtained when decoding symbol instance refinement data");
410
44
                    goto cleanup2;
411
44
                }
412
413
                /* 6.4.11 (6) */
414
502k
                if (IB) {
415
99.7k
                    IBO = IB;
416
99.7k
                    IB = NULL;
417
99.7k
                    if (((int32_t) IBO->width) + RDW < 0 || ((int32_t) IBO->height) + RDH < 0) {
418
27
                        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "reference image dimensions negative");
419
27
                        goto cleanup2;
420
27
                    }
421
99.7k
                    refimage = jbig2_image_new(ctx, IBO->width + RDW, IBO->height + RDH);
422
99.7k
                    if (refimage == NULL) {
423
11
                        code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate reference image");
424
11
                        goto cleanup2;
425
11
                    }
426
99.7k
                    jbig2_image_clear(ctx, refimage, 0x00);
427
428
                    /* Table 12 */
429
99.7k
                    rparams.GRTEMPLATE = params->SBRTEMPLATE;
430
99.7k
                    rparams.GRREFERENCE = IBO;
431
99.7k
                    rparams.GRREFERENCEDX = (RDW >> 1) + RDX;
432
99.7k
                    rparams.GRREFERENCEDY = (RDH >> 1) + RDY;
433
99.7k
                    rparams.TPGRON = 0;
434
99.7k
                    memcpy(rparams.grat, params->sbrat, 4);
435
99.7k
                    code = jbig2_decode_refinement_region(ctx, segment, &rparams, as, refimage, GR_stats);
436
99.7k
                    if (code < 0) {
437
5
                        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode refinement region");
438
5
                        goto cleanup2;
439
5
                    }
440
441
99.6k
                    jbig2_image_release(ctx, IBO);
442
99.6k
                    IBO = NULL;
443
99.6k
                    IB = refimage;
444
99.6k
                    refimage = NULL;
445
99.6k
                }
446
447
                /* 6.4.11 (7) */
448
502k
                if (params->SBHUFF) {
449
10.5k
                    code = jbig2_huffman_advance(hs, BMSIZE);
450
10.5k
                    if (code < 0) {
451
0
                        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to advance after huffman decoding refinement region");
452
0
                        goto cleanup2;
453
0
                    }
454
10.5k
                }
455
502k
            }
456
457
            /* (3c.vi) */
458
25.2M
            if ((!params->TRANSPOSED) && (params->REFCORNER > 1) && IB) {
459
8.67k
                CURS += IB->width - 1;
460
25.2M
            } else if ((params->TRANSPOSED) && !(params->REFCORNER & 1) && IB) {
461
7.41k
                CURS += IB->height - 1;
462
7.41k
            }
463
464
            /* (3c.vii) */
465
25.2M
            S = CURS;
466
467
            /* (3c.viii) */
468
25.2M
            if (!params->TRANSPOSED) {
469
24.3M
                switch (params->REFCORNER) {
470
4.81M
                case JBIG2_CORNER_TOPLEFT:
471
4.81M
                    x = S;
472
4.81M
                    y = T;
473
4.81M
                    break;
474
2.43M
                case JBIG2_CORNER_TOPRIGHT:
475
2.43M
                    if (IB)
476
4.65k
                        x = S - IB->width + 1;
477
2.43M
                    else
478
2.43M
                        x = S + 1;
479
2.43M
                    y = T;
480
2.43M
                    break;
481
17.0M
                case JBIG2_CORNER_BOTTOMLEFT:
482
17.0M
                    x = S;
483
17.0M
                    if (IB)
484
12.2M
                        y = T - IB->height + 1;
485
4.84M
                    else
486
4.84M
                        y = T + 1;
487
17.0M
                    break;
488
0
                default:
489
43.9k
                case JBIG2_CORNER_BOTTOMRIGHT:
490
43.9k
                    if (IB ) {
491
4.02k
                        x = S - IB->width + 1;
492
4.02k
                        y = T - IB->height + 1;
493
39.9k
                    } else {
494
39.9k
                        x = S + 1;
495
39.9k
                        y = T + 1;
496
39.9k
                    }
497
43.9k
                    break;
498
24.3M
                }
499
24.3M
            } else {            /* TRANSPOSED */
500
895k
                switch (params->REFCORNER) {
501
736k
                case JBIG2_CORNER_TOPLEFT:
502
736k
                    x = T;
503
736k
                    y = S;
504
736k
                    break;
505
79.4k
                case JBIG2_CORNER_TOPRIGHT:
506
79.4k
                    if (IB)
507
74.8k
                        x = T - IB->width + 1;
508
4.55k
                    else
509
4.55k
                        x = T + 1;
510
79.4k
                    y = S;
511
79.4k
                    break;
512
9.86k
                case JBIG2_CORNER_BOTTOMLEFT:
513
9.86k
                    x = T;
514
9.86k
                    if (IB)
515
5.93k
                        y = S - IB->height + 1;
516
3.92k
                    else
517
3.92k
                        y = S + 1;
518
9.86k
                    break;
519
0
                default:
520
70.1k
                case JBIG2_CORNER_BOTTOMRIGHT:
521
70.1k
                    if (IB) {
522
1.47k
                        x = T - IB->width + 1;
523
1.47k
                        y = S - IB->height + 1;
524
68.6k
                    } else {
525
68.6k
                        x = T + 1;
526
68.6k
                        y = S + 1;
527
68.6k
                    }
528
70.1k
                    break;
529
895k
                }
530
895k
            }
531
532
            /* (3c.ix) */
533
#ifdef JBIG2_DEBUG
534
            jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
535
                        "composing glyph ID %d: %dx%d @ (%d,%d) symbol %d/%d", ID, IB->width, IB->height, x, y, NINSTANCES + 1, params->SBNUMINSTANCES);
536
#endif
537
25.2M
            code = jbig2_image_compose(ctx, image, IB, x, y, params->SBCOMBOP);
538
25.2M
            if (code < 0) {
539
0
                jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to compose symbol instance symbol bitmap into picture");
540
0
                goto cleanup2;
541
0
            }
542
543
            /* (3c.x) */
544
25.2M
            if (IB && (!params->TRANSPOSED) && (params->REFCORNER < 2)) {
545
12.5M
                CURS += IB->width - 1;
546
12.7M
            } else if (IB && (params->TRANSPOSED) && (params->REFCORNER & 1)) {
547
802k
                CURS += IB->height - 1;
548
802k
            }
549
550
            /* (3c.xi) */
551
25.2M
            NINSTANCES++;
552
553
25.2M
            jbig2_image_release(ctx, IB);
554
25.2M
            IB = NULL;
555
25.2M
        }
556
        /* end strip */
557
402k
    }
558
    /* 6.4.5 (4) */
559
560
11.0k
cleanup2:
561
11.0k
    jbig2_image_release(ctx, refimage);
562
11.0k
    jbig2_image_release(ctx, IBO);
563
11.0k
    jbig2_image_release(ctx, IB);
564
11.0k
    if (params->SBHUFF) {
565
2.27k
        jbig2_release_huffman_table(ctx, SBSYMCODES);
566
2.27k
    }
567
11.0k
    jbig2_huffman_free(ctx, hs);
568
569
11.0k
    return code;
570
11.0k
}
571
572
/**
573
 * jbig2_text_region: read a text region segment header
574
 **/
575
int
576
jbig2_text_region(Jbig2Ctx *ctx, Jbig2Segment *segment, const byte *segment_data)
577
3.66k
{
578
3.66k
    uint32_t offset = 0;
579
3.66k
    Jbig2RegionSegmentInfo region_info;
580
3.66k
    Jbig2TextRegionParams params;
581
3.66k
    Jbig2Image *image = NULL;
582
3.66k
    Jbig2SymbolDict **dicts = NULL;
583
3.66k
    uint32_t n_dicts = 0;
584
3.66k
    uint16_t flags = 0;
585
3.66k
    uint16_t huffman_flags = 0;
586
3.66k
    Jbig2ArithCx *GR_stats = NULL;
587
3.66k
    int code = 0;
588
3.66k
    Jbig2WordStream *ws = NULL;
589
3.66k
    Jbig2ArithState *as = NULL;
590
3.66k
    uint32_t table_index = 0;
591
3.66k
    const Jbig2HuffmanParams *huffman_params = NULL;
592
593
    /* zero params to ease cleanup later */
594
3.66k
    memset(&params, 0, sizeof(Jbig2TextRegionParams));
595
596
    /* 7.4.1 */
597
3.66k
    if (segment->data_length < 17) {
598
12
        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
599
12
        goto cleanup2;
600
12
    }
601
3.65k
    jbig2_get_region_segment_info(&region_info, segment_data);
602
3.65k
    offset += 17;
603
    /* Check for T.88 amendment 3 */
604
3.65k
    if (region_info.flags & 8)
605
5
        return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "region segment flags indicate use of colored bitmap (NYI)");
606
607
    /* 7.4.3.1.1 */
608
3.64k
    if (segment->data_length - offset < 2) {
609
3
        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
610
3
        goto cleanup2;
611
3
    }
612
3.64k
    flags = jbig2_get_uint16(segment_data + offset);
613
3.64k
    offset += 2;
614
615
3.64k
    jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "text region header flags 0x%04x", flags);
616
617
3.64k
    params.SBHUFF = flags & 0x0001;
618
3.64k
    params.SBREFINE = flags & 0x0002;
619
3.64k
    params.LOGSBSTRIPS = (flags & 0x000c) >> 2;
620
3.64k
    params.SBSTRIPS = 1 << params.LOGSBSTRIPS;
621
3.64k
    params.REFCORNER = (Jbig2RefCorner)((flags & 0x0030) >> 4);
622
3.64k
    params.TRANSPOSED = flags & 0x0040;
623
3.64k
    params.SBCOMBOP = (Jbig2ComposeOp)((flags & 0x0180) >> 7);
624
3.64k
    params.SBDEFPIXEL = flags & 0x0200;
625
    /* SBDSOFFSET is a signed 5 bit integer */
626
3.64k
    params.SBDSOFFSET = (flags & 0x7C00) >> 10;
627
3.64k
    if (params.SBDSOFFSET > 0x0f)
628
223
        params.SBDSOFFSET -= 0x20;
629
3.64k
    params.SBRTEMPLATE = flags & 0x8000;
630
631
3.64k
    if (params.SBDSOFFSET) {
632
2.61k
        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number, "text region has SBDSOFFSET %d", params.SBDSOFFSET);
633
2.61k
    }
634
635
3.64k
    if (params.SBHUFF) {        /* Huffman coding */
636
        /* 7.4.3.1.2 */
637
295
        if (segment->data_length - offset < 2) {
638
3
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
639
3
            goto cleanup2;
640
3
        }
641
292
        huffman_flags = jbig2_get_uint16(segment_data + offset);
642
292
        offset += 2;
643
644
292
        if (huffman_flags & 0x8000)
645
35
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "reserved bit 15 of text region huffman flags is not zero");
646
3.34k
    } else {                    /* arithmetic coding */
647
648
        /* 7.4.3.1.3 */
649
3.34k
        if (segment->data_length - offset < 4) {
650
2
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
651
2
            goto cleanup2;
652
2
        }
653
3.34k
        if ((params.SBREFINE) && !(params.SBRTEMPLATE)) {
654
80
            params.sbrat[0] = segment_data[offset];
655
80
            params.sbrat[1] = segment_data[offset + 1];
656
80
            params.sbrat[2] = segment_data[offset + 2];
657
80
            params.sbrat[3] = segment_data[offset + 3];
658
80
            offset += 4;
659
80
        }
660
3.34k
    }
661
662
    /* 7.4.3.1.4 */
663
3.63k
    if (segment->data_length - offset < 4) {
664
7
        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
665
7
        goto cleanup2;
666
7
    }
667
3.63k
    params.SBNUMINSTANCES = jbig2_get_uint32(segment_data + offset);
668
3.63k
    offset += 4;
669
670
3.63k
    if (params.SBHUFF) {
671
        /* 7.4.3.1.5 - Symbol ID Huffman table */
672
        /* ...this is handled in the segment body decoder */
673
674
        /* 7.4.3.1.6 - Other Huffman table selection */
675
286
        switch (huffman_flags & 0x0003) {
676
191
        case 0:                /* Table B.6 */
677
191
            params.SBHUFFFS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_F);
678
191
            break;
679
69
        case 1:                /* Table B.7 */
680
69
            params.SBHUFFFS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_G);
681
69
            break;
682
20
        case 3:                /* Custom table from referred segment */
683
20
            huffman_params = jbig2_find_table(ctx, segment, table_index);
684
20
            if (huffman_params == NULL) {
685
7
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom FS huffman table not found (%d)", table_index);
686
7
                goto cleanup1;
687
7
            }
688
13
            params.SBHUFFFS = jbig2_build_huffman_table(ctx, huffman_params);
689
13
            ++table_index;
690
13
            break;
691
6
        case 2:                /* invalid */
692
6
        default:
693
6
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "text region specified invalid FS huffman table");
694
6
            goto cleanup1;
695
0
            break;
696
286
        }
697
273
        if (params.SBHUFFFS == NULL) {
698
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified FS huffman table");
699
1
            goto cleanup1;
700
1
        }
701
702
272
        switch ((huffman_flags & 0x000c) >> 2) {
703
162
        case 0:                /* Table B.8 */
704
162
            params.SBHUFFDS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_H);
705
162
            break;
706
73
        case 1:                /* Table B.9 */
707
73
            params.SBHUFFDS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_I);
708
73
            break;
709
18
        case 2:                /* Table B.10 */
710
18
            params.SBHUFFDS = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_J);
711
18
            break;
712
19
        case 3:                /* Custom table from referred segment */
713
19
            huffman_params = jbig2_find_table(ctx, segment, table_index);
714
19
            if (huffman_params == NULL) {
715
3
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom DS huffman table not found (%d)", table_index);
716
3
                goto cleanup1;
717
3
            }
718
16
            params.SBHUFFDS = jbig2_build_huffman_table(ctx, huffman_params);
719
16
            ++table_index;
720
16
            break;
721
272
        }
722
269
        if (params.SBHUFFDS == NULL) {
723
3
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified DS huffman table");
724
3
            goto cleanup1;
725
3
        }
726
727
266
        switch ((huffman_flags & 0x0030) >> 4) {
728
49
        case 0:                /* Table B.11 */
729
49
            params.SBHUFFDT = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_K);
730
49
            break;
731
119
        case 1:                /* Table B.12 */
732
119
            params.SBHUFFDT = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_L);
733
119
            break;
734
81
        case 2:                /* Table B.13 */
735
81
            params.SBHUFFDT = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_M);
736
81
            break;
737
17
        case 3:                /* Custom table from referred segment */
738
17
            huffman_params = jbig2_find_table(ctx, segment, table_index);
739
17
            if (huffman_params == NULL) {
740
2
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom DT huffman table not found (%d)", table_index);
741
2
                goto cleanup1;
742
2
            }
743
15
            params.SBHUFFDT = jbig2_build_huffman_table(ctx, huffman_params);
744
15
            ++table_index;
745
15
            break;
746
266
        }
747
264
        if (params.SBHUFFDT == NULL) {
748
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified DT huffman table");
749
1
            goto cleanup1;
750
1
        }
751
752
263
        switch ((huffman_flags & 0x00c0) >> 6) {
753
213
        case 0:                /* Table B.14 */
754
213
            params.SBHUFFRDW = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_N);
755
213
            break;
756
18
        case 1:                /* Table B.15 */
757
18
            params.SBHUFFRDW = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);
758
18
            break;
759
31
        case 3:                /* Custom table from referred segment */
760
31
            huffman_params = jbig2_find_table(ctx, segment, table_index);
761
31
            if (huffman_params == NULL) {
762
4
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom RDW huffman table not found (%d)", table_index);
763
4
                goto cleanup1;
764
4
            }
765
27
            params.SBHUFFRDW = jbig2_build_huffman_table(ctx, huffman_params);
766
27
            ++table_index;
767
27
            break;
768
1
        case 2:                /* invalid */
769
1
        default:
770
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "text region specified invalid RDW huffman table");
771
1
            goto cleanup1;
772
0
            break;
773
263
        }
774
258
        if (params.SBHUFFRDW == NULL) {
775
2
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified RDW huffman table");
776
2
            goto cleanup1;
777
2
        }
778
779
256
        switch ((huffman_flags & 0x0300) >> 8) {
780
120
        case 0:                /* Table B.14 */
781
120
            params.SBHUFFRDH = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_N);
782
120
            break;
783
128
        case 1:                /* Table B.15 */
784
128
            params.SBHUFFRDH = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);
785
128
            break;
786
6
        case 3:                /* Custom table from referred segment */
787
6
            huffman_params = jbig2_find_table(ctx, segment, table_index);
788
6
            if (huffman_params == NULL) {
789
2
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom RDH huffman table not found (%d)", table_index);
790
2
                goto cleanup1;
791
2
            }
792
4
            params.SBHUFFRDH = jbig2_build_huffman_table(ctx, huffman_params);
793
4
            ++table_index;
794
4
            break;
795
2
        case 2:                /* invalid */
796
2
        default:
797
2
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "text region specified invalid RDH huffman table");
798
2
            goto cleanup1;
799
0
            break;
800
256
        }
801
252
        if (params.SBHUFFRDH == NULL) {
802
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified RDH huffman table");
803
1
            goto cleanup1;
804
1
        }
805
806
251
        switch ((huffman_flags & 0x0c00) >> 10) {
807
198
        case 0:                /* Table B.14 */
808
198
            params.SBHUFFRDX = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_N);
809
198
            break;
810
42
        case 1:                /* Table B.15 */
811
42
            params.SBHUFFRDX = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);
812
42
            break;
813
9
        case 3:                /* Custom table from referred segment */
814
9
            huffman_params = jbig2_find_table(ctx, segment, table_index);
815
9
            if (huffman_params == NULL) {
816
3
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom RDX huffman table not found (%d)", table_index);
817
3
                goto cleanup1;
818
3
            }
819
6
            params.SBHUFFRDX = jbig2_build_huffman_table(ctx, huffman_params);
820
6
            ++table_index;
821
6
            break;
822
2
        case 2:                /* invalid */
823
2
        default:
824
2
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "text region specified invalid RDX huffman table");
825
2
            goto cleanup1;
826
0
            break;
827
251
        }
828
246
        if (params.SBHUFFRDX == NULL) {
829
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified RDX huffman table");
830
1
            goto cleanup1;
831
1
        }
832
833
245
        switch ((huffman_flags & 0x3000) >> 12) {
834
194
        case 0:                /* Table B.14 */
835
194
            params.SBHUFFRDY = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_N);
836
194
            break;
837
40
        case 1:                /* Table B.15 */
838
40
            params.SBHUFFRDY = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_O);
839
40
            break;
840
10
        case 3:                /* Custom table from referred segment */
841
10
            huffman_params = jbig2_find_table(ctx, segment, table_index);
842
10
            if (huffman_params == NULL) {
843
3
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom RDY huffman table not found (%d)", table_index);
844
3
                goto cleanup1;
845
3
            }
846
7
            params.SBHUFFRDY = jbig2_build_huffman_table(ctx, huffman_params);
847
7
            ++table_index;
848
7
            break;
849
1
        case 2:                /* invalid */
850
1
        default:
851
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "text region specified invalid RDY huffman table");
852
1
            goto cleanup1;
853
0
            break;
854
245
        }
855
241
        if (params.SBHUFFRDY == NULL) {
856
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified RDY huffman table");
857
1
            goto cleanup1;
858
1
        }
859
860
240
        switch ((huffman_flags & 0x4000) >> 14) {
861
233
        case 0:                /* Table B.1 */
862
233
            params.SBHUFFRSIZE = jbig2_build_huffman_table(ctx, &jbig2_huffman_params_A);
863
233
            break;
864
7
        case 1:                /* Custom table from referred segment */
865
7
            huffman_params = jbig2_find_table(ctx, segment, table_index);
866
7
            if (huffman_params == NULL) {
867
2
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "custom RSIZE huffman table not found (%d)", table_index);
868
2
                goto cleanup1;
869
2
            }
870
5
            params.SBHUFFRSIZE = jbig2_build_huffman_table(ctx, huffman_params);
871
5
            ++table_index;
872
5
            break;
873
240
        }
874
238
        if (params.SBHUFFRSIZE == NULL) {
875
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region specified RSIZE huffman table");
876
1
            goto cleanup1;
877
1
        }
878
879
237
        if (huffman_flags & 0x8000) {
880
4
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "text region huffman flags bit 15 is set, contrary to spec");
881
4
        }
882
883
        /* 7.4.3.1.7 */
884
        /* For convenience this is done in the body decoder routine */
885
237
    }
886
887
3.58k
    jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
888
3.58k
                "text region: %d x %d @ (%d,%d) %d symbols", region_info.width, region_info.height, region_info.x, region_info.y, params.SBNUMINSTANCES);
889
890
    /* 7.4.3.2 (2) - compose the list of symbol dictionaries */
891
3.58k
    n_dicts = jbig2_sd_count_referred(ctx, segment);
892
3.58k
    if (n_dicts == 0) {
893
714
        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "text region refers to no symbol dictionaries");
894
2.86k
    } else {
895
2.86k
        dicts = jbig2_sd_list_referred(ctx, segment);
896
2.86k
        if (dicts == NULL) {
897
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "unable to retrieve symbol dictionaries! previous parsing error?");
898
1
            goto cleanup1;
899
2.86k
        } else {
900
2.86k
            uint32_t index;
901
902
2.86k
            if (dicts[0] == NULL) {
903
0
                code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to find first referenced symbol dictionary");
904
0
                goto cleanup1;
905
0
            }
906
10.4k
            for (index = 1; index < n_dicts; index++)
907
7.53k
                if (dicts[index] == NULL) {
908
0
                    jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to find all referenced symbol dictionaries");
909
0
                    n_dicts = index;
910
0
                }
911
2.86k
        }
912
2.86k
    }
913
914
    /* 7.4.3.2 (3) */
915
3.58k
    {
916
3.58k
        int stats_size = params.SBRTEMPLATE ? 1 << 10 : 1 << 13;
917
918
3.58k
        GR_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
919
3.58k
        if (GR_stats == NULL) {
920
1
            code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "could not allocate arithmetic decoder state");
921
1
            goto cleanup1;
922
1
        }
923
3.58k
        memset(GR_stats, 0, stats_size);
924
3.58k
    }
925
926
0
    image = jbig2_image_new(ctx, region_info.width, region_info.height);
927
3.58k
    if (image == NULL) {
928
31
        code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region image");
929
31
        goto cleanup2;
930
31
    }
931
932
3.54k
    if (offset >= segment->data_length) {
933
3
        code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, "segment too short");
934
3
        goto cleanup2;
935
3
    }
936
3.54k
    ws = jbig2_word_stream_buf_new(ctx, segment_data + offset, segment->data_length - offset);
937
3.54k
    if (ws == NULL) {
938
1
        code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate word stream when handling text region image");
939
1
        goto cleanup2;
940
1
    }
941
942
3.54k
    as = jbig2_arith_new(ctx, ws);
943
3.54k
    if (as == NULL) {
944
1
        code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate arithmetic coding context when handling text region image");
945
1
        goto cleanup3;
946
1
    }
947
948
3.54k
    if (!params.SBHUFF) {
949
3.31k
        uint8_t SBSYMCODELEN;
950
3.31k
        uint32_t index;
951
3.31k
        uint32_t SBNUMSYMS = 0;
952
953
12.8k
        for (index = 0; index < n_dicts; index++) {
954
9.50k
            SBNUMSYMS += dicts[index]->n_symbols;
955
9.50k
        }
956
957
3.31k
        params.IADT = jbig2_arith_int_ctx_new(ctx);
958
3.31k
        params.IAFS = jbig2_arith_int_ctx_new(ctx);
959
3.31k
        params.IADS = jbig2_arith_int_ctx_new(ctx);
960
3.31k
        params.IAIT = jbig2_arith_int_ctx_new(ctx);
961
3.31k
        if (params.IADT == NULL || params.IAFS == NULL || params.IADS == NULL || params.IAIT == NULL) {
962
7
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region image data");
963
7
            goto cleanup4;
964
7
        }
965
966
        /* Table 31 */
967
7.10k
        for (SBSYMCODELEN = 0; ((uint64_t) 1 << SBSYMCODELEN) < (uint64_t) SBNUMSYMS; SBSYMCODELEN++);
968
969
3.30k
        params.IAID = jbig2_arith_iaid_ctx_new(ctx, SBSYMCODELEN);
970
3.30k
        params.IARI = jbig2_arith_int_ctx_new(ctx);
971
3.30k
        params.IARDW = jbig2_arith_int_ctx_new(ctx);
972
3.30k
        params.IARDH = jbig2_arith_int_ctx_new(ctx);
973
3.30k
        params.IARDX = jbig2_arith_int_ctx_new(ctx);
974
3.30k
        params.IARDY = jbig2_arith_int_ctx_new(ctx);
975
3.30k
        if (params.IAID == NULL || params.IARI == NULL ||
976
3.30k
            params.IARDW == NULL || params.IARDH == NULL || params.IARDX == NULL || params.IARDY == NULL) {
977
10
            code = jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to allocate text region image data");
978
10
            goto cleanup5;
979
10
        }
980
3.30k
    }
981
982
3.52k
    code = jbig2_decode_text_region(ctx, segment, &params,
983
3.52k
                                    (const Jbig2SymbolDict * const *)dicts, n_dicts, image, GR_stats, as, ws);
984
3.52k
    if (code < 0) {
985
241
        jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "failed to decode text region image data");
986
241
        goto cleanup5;
987
241
    }
988
989
3.28k
    if ((segment->flags & 63) == 4) {
990
        /* we have an intermediate region here. save it for later */
991
157
        segment->result = jbig2_image_reference(ctx, image);
992
3.12k
    } else {
993
        /* otherwise composite onto the page */
994
3.12k
        jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
995
3.12k
                    "composing %dx%d decoded text region onto page at (%d, %d)", region_info.width, region_info.height, region_info.x, region_info.y);
996
3.12k
        code = jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page], image, region_info.x, region_info.y, region_info.op);
997
3.12k
        if (code < 0)
998
14
            jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number, "unable to add text region to page");
999
3.12k
    }
1000
1001
3.53k
cleanup5:
1002
3.53k
    if (!params.SBHUFF) {
1003
3.30k
        jbig2_arith_iaid_ctx_free(ctx, params.IAID);
1004
3.30k
        jbig2_arith_int_ctx_free(ctx, params.IARI);
1005
3.30k
        jbig2_arith_int_ctx_free(ctx, params.IARDW);
1006
3.30k
        jbig2_arith_int_ctx_free(ctx, params.IARDH);
1007
3.30k
        jbig2_arith_int_ctx_free(ctx, params.IARDX);
1008
3.30k
        jbig2_arith_int_ctx_free(ctx, params.IARDY);
1009
3.30k
    }
1010
1011
3.54k
cleanup4:
1012
3.54k
    if (!params.SBHUFF) {
1013
3.31k
        jbig2_arith_int_ctx_free(ctx, params.IADT);
1014
3.31k
        jbig2_arith_int_ctx_free(ctx, params.IAFS);
1015
3.31k
        jbig2_arith_int_ctx_free(ctx, params.IADS);
1016
3.31k
        jbig2_arith_int_ctx_free(ctx, params.IAIT);
1017
3.31k
    }
1018
1019
3.54k
cleanup3:
1020
3.54k
    jbig2_free(ctx->allocator, as);
1021
3.54k
    jbig2_word_stream_buf_free(ctx, ws);
1022
1023
3.60k
cleanup2:
1024
3.60k
    jbig2_free(ctx->allocator, GR_stats);
1025
3.60k
    jbig2_image_release(ctx, image);
1026
1027
3.65k
cleanup1:
1028
3.65k
    if (params.SBHUFF) {
1029
295
        jbig2_release_huffman_table(ctx, params.SBHUFFFS);
1030
295
        jbig2_release_huffman_table(ctx, params.SBHUFFDS);
1031
295
        jbig2_release_huffman_table(ctx, params.SBHUFFDT);
1032
295
        jbig2_release_huffman_table(ctx, params.SBHUFFRDX);
1033
295
        jbig2_release_huffman_table(ctx, params.SBHUFFRDY);
1034
295
        jbig2_release_huffman_table(ctx, params.SBHUFFRDW);
1035
295
        jbig2_release_huffman_table(ctx, params.SBHUFFRDH);
1036
295
        jbig2_release_huffman_table(ctx, params.SBHUFFRSIZE);
1037
295
    }
1038
3.65k
    jbig2_free(ctx->allocator, dicts);
1039
1040
3.65k
    return code;
1041
3.60k
}