]> rtime.felk.cvut.cz Git - hornmich/skoda-qr-demo.git/blob - QRScanner/mobile/jni/thirdparty/jbig2dec/jbig2_generic.c
Add MuPDF native source codes
[hornmich/skoda-qr-demo.git] / QRScanner / mobile / jni / thirdparty / jbig2dec / jbig2_generic.c
1 /* Copyright (C) 2001-2012 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.,  7 Mt. Lassen Drive - Suite A-134, San Rafael,
13    CA  94903, U.S.A., +1(415)492-9861, for further information.
14 */
15
16 /*
17     jbig2dec
18 */
19
20
21 /**
22  * Generic region handlers.
23  **/
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28 #include "os_types.h"
29
30 #include <stddef.h>
31 #include <string.h> /* memcpy(), memset() */
32
33 #ifdef OUTPUT_PBM
34 #include <stdio.h>
35 #endif
36
37 #include "jbig2.h"
38 #include "jbig2_priv.h"
39 #include "jbig2_image.h"
40 #include "jbig2_arith.h"
41 #include "jbig2_generic.h"
42 #include "jbig2_mmr.h"
43
44 /* return the appropriate context size for the given template */
45 int
46 jbig2_generic_stats_size(Jbig2Ctx *ctx, int template)
47 {
48   int stats_size = template == 0 ? 1 << 16 :
49         template == 1 ? 1 << 1 << 13 : 1 << 10;
50   return stats_size;
51 }
52
53
54 static int
55 jbig2_decode_generic_template0(Jbig2Ctx *ctx,
56                                Jbig2Segment *segment,
57                                const Jbig2GenericRegionParams *params,
58                                Jbig2ArithState *as,
59                                Jbig2Image *image,
60                                Jbig2ArithCx *GB_stats)
61 {
62   const int GBW = image->width;
63   const int GBH = image->height;
64   const int rowstride = image->stride;
65   int x, y;
66   byte *gbreg_line = (byte *)image->data;
67
68   /* todo: currently we only handle the nominal gbat location */
69
70 #ifdef OUTPUT_PBM
71   printf("P4\n%d %d\n", GBW, GBH);
72 #endif
73
74   if (GBW <= 0)
75     return 0;
76
77   for (y = 0; y < GBH; y++)
78     {
79       uint32_t CONTEXT;
80       uint32_t line_m1;
81       uint32_t line_m2;
82       int padded_width = (GBW + 7) & -8;
83
84       line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
85       line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 6 : 0;
86       CONTEXT = (line_m1 & 0x7f0) | (line_m2 & 0xf800);
87
88       /* 6.2.5.7 3d */
89       for (x = 0; x < padded_width; x += 8)
90         {
91           byte result = 0;
92           int x_minor;
93           int minor_width = GBW - x > 8 ? 8 : GBW - x;
94
95           if (y >= 1)
96             line_m1 = (line_m1 << 8) |
97               (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0);
98
99           if (y >= 2)
100             line_m2 = (line_m2 << 8) |
101               (x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 6: 0);
102
103           /* This is the speed-critical inner loop. */
104           for (x_minor = 0; x_minor < minor_width; x_minor++)
105             {
106               bool bit;
107
108               bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
109               if (bit < 0)
110                 return -1;
111               result |= bit << (7 - x_minor);
112               CONTEXT = ((CONTEXT & 0x7bf7) << 1) | bit |
113                 ((line_m1 >> (7 - x_minor)) & 0x10) |
114                 ((line_m2 >> (7 - x_minor)) & 0x800);
115             }
116           gbreg_line[x >> 3] = result;
117         }
118 #ifdef OUTPUT_PBM
119       fwrite(gbreg_line, 1, rowstride, stdout);
120 #endif
121       gbreg_line += rowstride;
122     }
123
124   return 0;
125 }
126
127 static int
128 jbig2_decode_generic_template0_unopt(Jbig2Ctx *ctx,
129                                Jbig2Segment *segment,
130                                const Jbig2GenericRegionParams *params,
131                                Jbig2ArithState *as,
132                                Jbig2Image *image,
133                                Jbig2ArithCx *GB_stats)
134 {
135   const int GBW = image->width;
136   const int GBH = image->height;
137   uint32_t CONTEXT;
138   int x,y;
139   bool bit;
140
141   /* this version is generic and easy to understand, but very slow */
142
143   for (y = 0; y < GBH; y++) {
144     for (x = 0; x < GBW; x++) {
145       CONTEXT = 0;
146       CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0;
147       CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
148       CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
149       CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
150       CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
151         y + params->gbat[1]) << 4;
152       CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 5;
153       CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 6;
154       CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 7;
155       CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 8;
156       CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 9;
157       CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[2],
158         y + params->gbat[3]) << 10;
159       CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4],
160         y + params->gbat[5]) << 11;
161       CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 12;
162       CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 2) << 13;
163       CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 14;
164       CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6],
165         y + params->gbat[7]) << 15;
166       bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
167       if (bit < 0)
168         return -1;
169       jbig2_image_set_pixel(image, x, y, bit);
170     }
171   }
172   return 0;
173 }
174
175 static int
176 jbig2_decode_generic_template1(Jbig2Ctx *ctx,
177                                Jbig2Segment *segment,
178                                const Jbig2GenericRegionParams *params,
179                                Jbig2ArithState *as,
180                                Jbig2Image *image,
181                                Jbig2ArithCx *GB_stats)
182 {
183   const int GBW = image->width;
184   const int GBH = image->height;
185   const int rowstride = image->stride;
186   int x, y;
187   byte *gbreg_line = (byte *)image->data;
188
189   /* todo: currently we only handle the nominal gbat location */
190
191 #ifdef OUTPUT_PBM
192   printf("P4\n%d %d\n", GBW, GBH);
193 #endif
194
195   if (GBW <= 0)
196     return 0;
197
198   for (y = 0; y < GBH; y++)
199     {
200       uint32_t CONTEXT;
201       uint32_t line_m1;
202       uint32_t line_m2;
203       int padded_width = (GBW + 7) & -8;
204
205       line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
206       line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 5 : 0;
207       CONTEXT = ((line_m1 >> 1) & 0x1f8) | ((line_m2 >> 1) & 0x1e00);
208
209       /* 6.2.5.7 3d */
210       for (x = 0; x < padded_width; x += 8)
211         {
212           byte result = 0;
213           int x_minor;
214           int minor_width = GBW - x > 8 ? 8 : GBW - x;
215
216           if (y >= 1)
217             line_m1 = (line_m1 << 8) |
218               (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0);
219
220           if (y >= 2)
221             line_m2 = (line_m2 << 8) |
222               (x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 5: 0);
223
224           /* This is the speed-critical inner loop. */
225           for (x_minor = 0; x_minor < minor_width; x_minor++)
226             {
227               bool bit;
228
229               bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
230               if (bit < 0)
231                 return -1;
232               result |= bit << (7 - x_minor);
233               CONTEXT = ((CONTEXT & 0xefb) << 1) | bit |
234                 ((line_m1 >> (8 - x_minor)) & 0x8) |
235                 ((line_m2 >> (8 - x_minor)) & 0x200);
236             }
237           gbreg_line[x >> 3] = result;
238         }
239 #ifdef OUTPUT_PBM
240       fwrite(gbreg_line, 1, rowstride, stdout);
241 #endif
242       gbreg_line += rowstride;
243     }
244
245   return 0;
246 }
247
248 static int
249 jbig2_decode_generic_template2(Jbig2Ctx *ctx,
250                                Jbig2Segment *segment,
251                                const Jbig2GenericRegionParams *params,
252                                Jbig2ArithState *as,
253                                Jbig2Image *image,
254                                Jbig2ArithCx *GB_stats)
255 {
256   const int GBW = image->width;
257   const int GBH = image->height;
258   const int rowstride = image->stride;
259   int x, y;
260   byte *gbreg_line = (byte *)image->data;
261
262   /* todo: currently we only handle the nominal gbat location */
263
264 #ifdef OUTPUT_PBM
265   printf("P4\n%d %d\n", GBW, GBH);
266 #endif
267
268   if (GBW <= 0)
269     return 0;
270
271   for (y = 0; y < GBH; y++)
272     {
273       uint32_t CONTEXT;
274       uint32_t line_m1;
275       uint32_t line_m2;
276       int padded_width = (GBW + 7) & -8;
277
278       line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
279       line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 4 : 0;
280       CONTEXT = ((line_m1 >> 3) & 0x7c) | ((line_m2 >> 3) & 0x380);
281
282       /* 6.2.5.7 3d */
283       for (x = 0; x < padded_width; x += 8)
284         {
285           byte result = 0;
286           int x_minor;
287           int minor_width = GBW - x > 8 ? 8 : GBW - x;
288
289           if (y >= 1)
290             line_m1 = (line_m1 << 8) |
291               (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0);
292
293           if (y >= 2)
294             line_m2 = (line_m2 << 8) |
295               (x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 4: 0);
296
297           /* This is the speed-critical inner loop. */
298           for (x_minor = 0; x_minor < minor_width; x_minor++)
299             {
300               bool bit;
301
302               bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
303               if (bit < 0)
304                 return -1;
305               result |= bit << (7 - x_minor);
306               CONTEXT = ((CONTEXT & 0x1bd) << 1) | bit |
307                 ((line_m1 >> (10 - x_minor)) & 0x4) |
308                 ((line_m2 >> (10 - x_minor)) & 0x80);
309             }
310           gbreg_line[x >> 3] = result;
311         }
312 #ifdef OUTPUT_PBM
313       fwrite(gbreg_line, 1, rowstride, stdout);
314 #endif
315       gbreg_line += rowstride;
316     }
317
318   return 0;
319 }
320
321 static int
322 jbig2_decode_generic_template2a(Jbig2Ctx *ctx,
323                                Jbig2Segment *segment,
324                                const Jbig2GenericRegionParams *params,
325                                Jbig2ArithState *as,
326                                Jbig2Image *image,
327                                Jbig2ArithCx *GB_stats)
328 {
329   const int GBW = image->width;
330   const int GBH = image->height;
331   const int rowstride = image->stride;
332   int x, y;
333   byte *gbreg_line = (byte *)image->data;
334
335   /* This is a special case for GBATX1 = 3, GBATY1 = -1 */
336
337 #ifdef OUTPUT_PBM
338   printf("P4\n%d %d\n", GBW, GBH);
339 #endif
340
341   if (GBW <= 0)
342     return 0;
343
344   for (y = 0; y < GBH; y++)
345     {
346       uint32_t CONTEXT;
347       uint32_t line_m1;
348       uint32_t line_m2;
349       int padded_width = (GBW + 7) & -8;
350
351       line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
352       line_m2 = (y >= 2) ? gbreg_line[-(rowstride << 1)] << 4 : 0;
353       CONTEXT = ((line_m1 >> 3) & 0x78) | ((line_m1 >> 2) & 0x4) | ((line_m2 >> 3) & 0x380);
354
355       /* 6.2.5.7 3d */
356       for (x = 0; x < padded_width; x += 8)
357         {
358           byte result = 0;
359           int x_minor;
360           int minor_width = GBW - x > 8 ? 8 : GBW - x;
361
362           if (y >= 1)
363             line_m1 = (line_m1 << 8) |
364               (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0);
365
366           if (y >= 2)
367             line_m2 = (line_m2 << 8) |
368               (x + 8 < GBW ? gbreg_line[-(rowstride << 1) + (x >> 3) + 1] << 4: 0);
369
370           /* This is the speed-critical inner loop. */
371           for (x_minor = 0; x_minor < minor_width; x_minor++)
372             {
373               bool bit;
374
375               bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
376               if (bit < 0)
377                 return -1;
378               result |= bit << (7 - x_minor);
379               CONTEXT = ((CONTEXT & 0x1b9) << 1) | bit |
380                 ((line_m1 >> (10 - x_minor)) & 0x8) |
381                 ((line_m1 >> (9 - x_minor)) & 0x4) |
382                 ((line_m2 >> (10 - x_minor)) & 0x80);
383             }
384           gbreg_line[x >> 3] = result;
385         }
386 #ifdef OUTPUT_PBM
387       fwrite(gbreg_line, 1, rowstride, stdout);
388 #endif
389       gbreg_line += rowstride;
390     }
391
392   return 0;
393 }
394
395 static int
396 jbig2_decode_generic_template3(Jbig2Ctx *ctx,
397                                Jbig2Segment *segment,
398                                const Jbig2GenericRegionParams *params,
399                                Jbig2ArithState *as,
400                                Jbig2Image *image,
401                                Jbig2ArithCx *GB_stats)
402 {
403   const int GBW = image->width;
404   const int GBH = image->height;
405   const int rowstride = image->stride;
406   byte *gbreg_line = (byte *)image->data;
407   int x, y;
408
409   /* this routine only handles the nominal AT location */
410
411 #ifdef OUTPUT_PBM
412   printf("P4\n%d %d\n", GBW, GBH);
413 #endif
414
415   if (GBW <= 0)
416     return 0;
417
418   for (y = 0; y < GBH; y++)
419     {
420       uint32_t CONTEXT;
421       uint32_t line_m1;
422       int padded_width = (GBW + 7) & -8;
423
424       line_m1 = (y >= 1) ? gbreg_line[-rowstride] : 0;
425       CONTEXT = (line_m1 >> 1) & 0x3f0;
426
427       /* 6.2.5.7 3d */
428       for (x = 0; x < padded_width; x += 8)
429         {
430           byte result = 0;
431           int x_minor;
432           int minor_width = GBW - x > 8 ? 8 : GBW - x;
433
434           if (y >= 1)
435             line_m1 = (line_m1 << 8) |
436               (x + 8 < GBW ? gbreg_line[-rowstride + (x >> 3) + 1] : 0);
437
438           /* This is the speed-critical inner loop. */
439           for (x_minor = 0; x_minor < minor_width; x_minor++)
440             {
441               bool bit;
442
443               bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
444               if (bit < 0)
445                 return -1;
446               result |= bit << (7 - x_minor);
447               CONTEXT = ((CONTEXT & 0x1f7) << 1) | bit |
448                 ((line_m1 >> (10 - x_minor)) & 0x010);
449             }
450           gbreg_line[x >> 3] = result;
451         }
452 #ifdef OUTPUT_PBM
453       fwrite(gbreg_line, 1, rowstride, stdout);
454 #endif
455       gbreg_line += rowstride;
456     }
457
458   return 0;
459 }
460
461 static int
462 jbig2_decode_generic_template3_unopt(Jbig2Ctx *ctx,
463                                Jbig2Segment *segment,
464                                const Jbig2GenericRegionParams *params,
465                                Jbig2ArithState *as,
466                                Jbig2Image *image,
467                                Jbig2ArithCx *GB_stats)
468 {
469   const int GBW = image->width;
470   const int GBH = image->height;
471   uint32_t CONTEXT;
472   int x,y;
473   bool bit;
474
475   /* this version is generic and easy to understand, but very slow */
476
477   for (y = 0; y < GBH; y++) {
478     for (x = 0; x < GBW; x++) {
479       CONTEXT = 0;
480       CONTEXT |= jbig2_image_get_pixel(image, x - 1, y) << 0;
481       CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
482       CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
483       CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
484       CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
485         y + params->gbat[1]) << 4;
486       CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5;
487       CONTEXT |= jbig2_image_get_pixel(image, x + 0, y - 1) << 6;
488       CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
489       CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
490       CONTEXT |= jbig2_image_get_pixel(image, x - 3, y - 1) << 9;
491       bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
492       if (bit < 0)
493         return -1;
494       jbig2_image_set_pixel(image, x, y, bit);
495     }
496   }
497   return 0;
498 }
499
500 static void
501 copy_prev_row(Jbig2Image *image, int row)
502 {
503   if (!row) {
504     /* no previous row */
505     memset( image->data, 0, image->stride );
506   } else {
507     /* duplicate data from the previous row */
508     uint8_t *src = image->data + (row - 1) * image->stride;
509     memcpy( src + image->stride, src, image->stride );
510   }
511 }
512
513 static int
514 jbig2_decode_generic_template0_TPGDON(Jbig2Ctx *ctx,
515                                 Jbig2Segment *segment,
516                                 const Jbig2GenericRegionParams *params, 
517                                 Jbig2ArithState *as,
518                                 Jbig2Image *image,
519                                 Jbig2ArithCx *GB_stats)
520 {
521   const int GBW = image->width;
522   const int GBH = image->height;
523   uint32_t CONTEXT;
524   int x, y;
525   bool bit;
526   int LTP = 0;
527
528   for (y = 0; y < GBH; y++)
529   {
530     bit = jbig2_arith_decode(as, &GB_stats[0x9B25]);
531     if (bit < 0)
532       return -1;
533     LTP ^= bit;
534     if (!LTP) {
535       for (x = 0; x < GBW; x++) {
536         CONTEXT  = jbig2_image_get_pixel(image, x - 1, y);
537         CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
538         CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
539         CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
540         CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
541                                         y + params->gbat[1]) << 4;
542         CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 5;
543         CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 6;
544         CONTEXT |= jbig2_image_get_pixel(image, x    , y - 1) << 7;
545         CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 8;
546         CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 9;
547         CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[2],
548                                         y + params->gbat[3]) << 10;
549         CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[4],
550                                         y + params->gbat[5]) << 11;
551         CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 12;
552         CONTEXT |= jbig2_image_get_pixel(image, x    , y - 2) << 13;
553         CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 14;
554         CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[6],
555                                         y + params->gbat[7]) << 15;
556         bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
557         if (bit < 0)
558           return -1;
559         jbig2_image_set_pixel(image, x, y, bit);
560       }
561     } else {
562       copy_prev_row(image, y);
563     }
564   }
565
566   return 0;
567 }
568
569 static int
570 jbig2_decode_generic_template1_TPGDON(Jbig2Ctx *ctx, 
571                                 Jbig2Segment *segment,
572                                 const Jbig2GenericRegionParams *params, 
573                                 Jbig2ArithState *as,
574                                 Jbig2Image *image,
575                                 Jbig2ArithCx *GB_stats)
576 {
577   const int GBW = image->width;
578   const int GBH = image->height;
579   uint32_t CONTEXT;
580   int x, y;
581   bool bit;
582   int LTP = 0;
583
584   for (y = 0; y < GBH; y++) {
585     bit = jbig2_arith_decode(as, &GB_stats[0x0795]);
586     if (bit < 0)
587       return -1;
588     LTP ^= bit;
589     if (!LTP) {
590       for (x = 0; x < GBW; x++) {
591         CONTEXT  = jbig2_image_get_pixel(image, x - 1, y);
592         CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
593         CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
594         CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
595                                         y + params->gbat[1]) << 3;
596         CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 1) << 4;
597         CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5;
598         CONTEXT |= jbig2_image_get_pixel(image, x    , y - 1) << 6;
599         CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
600         CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
601         CONTEXT |= jbig2_image_get_pixel(image, x + 2, y - 2) << 9;
602         CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 10;
603         CONTEXT |= jbig2_image_get_pixel(image, x    , y - 2) << 11;
604         CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 12;
605         bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
606         if (bit < 0)
607           return -1;
608         jbig2_image_set_pixel(image, x, y, bit);
609       }
610     } else {
611       copy_prev_row(image, y);
612     }
613   }
614
615   return 0;
616 }
617
618 static int
619 jbig2_decode_generic_template2_TPGDON(Jbig2Ctx *ctx, 
620                                 Jbig2Segment *segment,
621                                 const Jbig2GenericRegionParams *params,
622                                 Jbig2ArithState *as,
623                                 Jbig2Image *image,
624                                 Jbig2ArithCx *GB_stats)
625 {
626   const int GBW = image->width;
627   const int GBH = image->height;
628   uint32_t CONTEXT;
629   int x, y;
630   bool bit;
631   int LTP = 0;
632
633   for (y = 0; y < GBH; y++) {
634     bit = jbig2_arith_decode(as, &GB_stats[0xE5]);
635     if (bit < 0)
636       return -1;
637     LTP ^= bit;
638     if (!LTP) {
639       for (x = 0; x < GBW; x++) {
640         CONTEXT  = jbig2_image_get_pixel(image, x - 1, y);
641         CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
642         CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
643                                         y + params->gbat[1]) << 2;
644         CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 3;
645         CONTEXT |= jbig2_image_get_pixel(image, x    , y - 1) << 4;
646         CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 5;
647         CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 6;
648         CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 2) << 7;
649         CONTEXT |= jbig2_image_get_pixel(image, x    , y - 2) << 8;
650         CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 2) << 9;
651         bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
652         if (bit < 0)
653           return -1;
654         jbig2_image_set_pixel(image, x, y, bit);
655       }
656     } else {
657       copy_prev_row(image, y);
658     }
659   }
660
661   return 0;
662 }
663
664 static int
665 jbig2_decode_generic_template3_TPGDON(Jbig2Ctx *ctx, 
666                                 Jbig2Segment *segment,
667                                 const Jbig2GenericRegionParams *params,
668                                 Jbig2ArithState *as,
669                                 Jbig2Image *image,
670                                 Jbig2ArithCx *GB_stats)
671 {
672   const int GBW = image->width;
673   const int GBH = image->height;
674   uint32_t CONTEXT;
675   int x, y;
676   bool bit;
677   int LTP = 0;
678
679   for (y = 0; y < GBH; y++) {
680     bit = jbig2_arith_decode(as, &GB_stats[0x0195]);
681     if (bit < 0)
682       return -1;
683     LTP ^= bit;
684     if (!LTP) {
685       for (x = 0; x < GBW; x++) {
686         CONTEXT  = jbig2_image_get_pixel(image, x - 1, y);
687         CONTEXT |= jbig2_image_get_pixel(image, x - 2, y) << 1;
688         CONTEXT |= jbig2_image_get_pixel(image, x - 3, y) << 2;
689         CONTEXT |= jbig2_image_get_pixel(image, x - 4, y) << 3;
690         CONTEXT |= jbig2_image_get_pixel(image, x + params->gbat[0],
691                                         y + params->gbat[1]) << 4;
692         CONTEXT |= jbig2_image_get_pixel(image, x + 1, y - 1) << 5;
693         CONTEXT |= jbig2_image_get_pixel(image, x    , y - 1) << 6;
694         CONTEXT |= jbig2_image_get_pixel(image, x - 1, y - 1) << 7;
695         CONTEXT |= jbig2_image_get_pixel(image, x - 2, y - 1) << 8;
696         CONTEXT |= jbig2_image_get_pixel(image, x - 3, y - 1) << 9;
697         bit = jbig2_arith_decode(as, &GB_stats[CONTEXT]);
698         if (bit < 0)
699           return -1;
700         jbig2_image_set_pixel(image, x, y, bit);
701       }
702     } else {
703       copy_prev_row(image, y);
704     }
705   }
706
707   return 0;
708 }
709
710 static int
711 jbig2_decode_generic_region_TPGDON(Jbig2Ctx *ctx,
712                                 Jbig2Segment *segment,
713                                 const Jbig2GenericRegionParams *params, 
714                                 Jbig2ArithState *as,
715                                 Jbig2Image *image,
716                                 Jbig2ArithCx *GB_stats)
717 {
718   switch (params->GBTEMPLATE) {
719     case 0:
720       return jbig2_decode_generic_template0_TPGDON(ctx, segment, 
721                         params, as, image, GB_stats);
722     case 1:
723       return jbig2_decode_generic_template1_TPGDON(ctx, segment, 
724                         params, as, image, GB_stats);
725     case 2:
726       return jbig2_decode_generic_template2_TPGDON(ctx, segment, 
727                         params, as, image, GB_stats);
728     case 3:
729       return jbig2_decode_generic_template3_TPGDON(ctx, segment, 
730                         params, as, image, GB_stats);
731   }
732
733   return -1;
734 }
735
736 /**
737  * jbig2_decode_generic_region: Decode a generic region.
738  * @ctx: The context for allocation and error reporting.
739  * @segment: A segment reference for error reporting.
740  * @params: Decoding parameter set.
741  * @as: Arithmetic decoder state.
742  * @image: Where to store the decoded data.
743  * @GB_stats: Arithmetic stats.
744  *
745  * Decodes a generic region, according to section 6.2. The caller should
746  * pass an already allocated Jbig2Image object for @image
747  *
748  * Because this API is based on an arithmetic decoding state, it is
749  * not suitable for MMR decoding.
750  *
751  * Return code: 0 on success.
752  **/
753 int
754 jbig2_decode_generic_region(Jbig2Ctx *ctx,
755                             Jbig2Segment *segment,
756                             const Jbig2GenericRegionParams *params,
757                             Jbig2ArithState *as,
758                             Jbig2Image *image,
759                             Jbig2ArithCx *GB_stats)
760 {
761   const int8_t *gbat = params->gbat;
762
763   if (image->stride * image->height > (1 << 24) && segment->data_length < image->stride * image->height / 256) {
764     return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
765                        "region is far larger than data provided (%d << %d), aborting to prevent DOS",
766                        segment->data_length, image->stride * image->height);
767   }
768
769   if (!params->MMR && params->TPGDON) 
770      return jbig2_decode_generic_region_TPGDON(ctx, segment, params, 
771                 as, image, GB_stats);
772
773   if (!params->MMR && params->GBTEMPLATE == 0) {
774     if (gbat[0] == +3 && gbat[1] == -1 &&
775         gbat[2] == -3 && gbat[3] == -1 &&
776         gbat[4] == +2 && gbat[5] == -2 &&
777         gbat[6] == -2 && gbat[7] == -2)
778       return jbig2_decode_generic_template0(ctx, segment, params,
779                                           as, image, GB_stats);
780     else
781       return jbig2_decode_generic_template0_unopt(ctx, segment, params,
782                                           as, image, GB_stats);
783   } else if (!params->MMR && params->GBTEMPLATE == 1)
784     return jbig2_decode_generic_template1(ctx, segment, params,
785                                           as, image, GB_stats);
786   else if (!params->MMR && params->GBTEMPLATE == 2)
787     {
788       if (gbat[0] == 3 && gbat[1] == -1)
789         return jbig2_decode_generic_template2a(ctx, segment, params,
790                                                as, image, GB_stats);
791       else
792         return jbig2_decode_generic_template2(ctx, segment, params,
793                                               as, image, GB_stats);
794     }
795   else if (!params->MMR && params->GBTEMPLATE == 3) {
796    if (gbat[0] == 2 && gbat[1] == -1)
797      return jbig2_decode_generic_template3_unopt(ctx, segment, params,
798                                          as, image, GB_stats);
799    else
800      return jbig2_decode_generic_template3_unopt(ctx, segment, params,
801                                          as, image, GB_stats);
802   }
803
804   {
805     int i;
806     for (i = 0; i < 8; i++)
807       jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
808         "gbat[%d] = %d", i, params->gbat[i]);
809   }
810   jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
811               "decode_generic_region: MMR=%d, GBTEMPLATE=%d NYI",
812               params->MMR, params->GBTEMPLATE);
813   return -1;
814 }
815
816 /**
817  * Handler for immediate generic region segments
818  */
819 int
820 jbig2_immediate_generic_region(Jbig2Ctx *ctx, Jbig2Segment *segment,
821                                const byte *segment_data)
822 {
823   Jbig2RegionSegmentInfo rsi;
824   byte seg_flags;
825   int8_t gbat[8];
826   int offset;
827   int gbat_bytes = 0;
828   Jbig2GenericRegionParams params;
829   int code = 0;
830   Jbig2Image *image = NULL;
831   Jbig2WordStream *ws = NULL;
832   Jbig2ArithState *as = NULL;
833   Jbig2ArithCx *GB_stats = NULL;
834
835   /* 7.4.6 */
836   if (segment->data_length < 18)
837     return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
838                        "Segment too short");
839
840   jbig2_get_region_segment_info(&rsi, segment_data);
841   jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
842               "generic region: %d x %d @ (%d, %d), flags = %02x",
843               rsi.width, rsi.height, rsi.x, rsi.y, rsi.flags);
844
845   /* 7.4.6.2 */
846   seg_flags = segment_data[17];
847   jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
848               "segment flags = %02x", seg_flags);
849   if ((seg_flags & 1) && (seg_flags & 6))
850     jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
851                 "MMR is 1, but GBTEMPLATE is not 0");
852
853   /* 7.4.6.3 */
854   if (!(seg_flags & 1))
855     {
856       gbat_bytes = (seg_flags & 6) ? 2 : 8;
857       if (18 + gbat_bytes > segment->data_length)
858         return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
859                            "Segment too short");
860       memcpy(gbat, segment_data + 18, gbat_bytes);
861       jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
862                   "gbat: %d, %d", gbat[0], gbat[1]);
863     }
864
865   offset = 18 + gbat_bytes;
866
867   /* Table 34 */
868   params.MMR = seg_flags & 1;
869   params.GBTEMPLATE = (seg_flags & 6) >> 1;
870   params.TPGDON = (seg_flags & 8) >> 3;
871   params.USESKIP = 0;
872   memcpy (params.gbat, gbat, gbat_bytes);
873
874   image = jbig2_image_new(ctx, rsi.width, rsi.height);
875   if (image == NULL)
876     return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
877              "unable to allocate generic image");
878   jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, segment->number,
879     "allocated %d x %d image buffer for region decode results",
880         rsi.width, rsi.height);
881
882   if (params.MMR)
883     {
884       code = jbig2_decode_generic_mmr(ctx, segment, &params,
885           segment_data + offset, segment->data_length - offset, image);
886     }
887   else
888     {
889       int stats_size = jbig2_generic_stats_size(ctx, params.GBTEMPLATE);
890       GB_stats = jbig2_new(ctx, Jbig2ArithCx, stats_size);
891       if (GB_stats == NULL)
892       {
893           code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
894               "unable to allocate GB_stats in jbig2_immediate_generic_region");
895           goto cleanup;
896       }
897       memset(GB_stats, 0, stats_size);
898
899       ws = jbig2_word_stream_buf_new(ctx, segment_data + offset,
900           segment->data_length - offset);
901       if (ws == NULL)
902       {
903           code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
904               "unable to allocate ws in jbig2_immediate_generic_region");
905           goto cleanup;
906       }
907       as = jbig2_arith_new(ctx, ws);
908       if (as == NULL)
909       {
910           code = jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
911               "unable to allocate as in jbig2_immediate_generic_region");
912           goto cleanup;
913       }
914       code = jbig2_decode_generic_region(ctx, segment, &params,
915                                          as, image, GB_stats);
916     }
917
918   if (code >= 0)
919     jbig2_page_add_result(ctx, &ctx->pages[ctx->current_page],
920                           image, rsi.x, rsi.y, rsi.op);
921   else
922     jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
923                 "error while decoding immediate_generic_region");
924
925 cleanup:
926   jbig2_free(ctx->allocator, as);
927   jbig2_word_stream_buf_free(ctx, ws);
928   jbig2_free(ctx->allocator, GB_stats);
929   jbig2_image_release(ctx, image);
930
931   return code;
932 }