]> rtime.felk.cvut.cz Git - hornmich/skoda-qr-demo.git/blob - QRScanner/mobile/jni/thirdparty/jbig2dec/jbig2_segment.c
Add MuPDF native source codes
[hornmich/skoda-qr-demo.git] / QRScanner / mobile / jni / thirdparty / jbig2dec / jbig2_segment.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 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 #include "os_types.h"
25
26 #include <stddef.h> /* size_t */
27
28 #include "jbig2.h"
29 #include "jbig2_priv.h"
30 #include "jbig2_huffman.h"
31 #include "jbig2_symbol_dict.h"
32 #include "jbig2_metadata.h"
33 #include "jbig2_arith.h"
34 #include "jbig2_halftone.h"
35
36 Jbig2Segment *
37 jbig2_parse_segment_header (Jbig2Ctx *ctx, uint8_t *buf, size_t buf_size,
38                             size_t *p_header_size)
39 {
40   Jbig2Segment *result;
41   uint8_t rtscarf;
42   uint32_t rtscarf_long;
43   uint32_t *referred_to_segments;
44   int referred_to_segment_count;
45   int referred_to_segment_size;
46   int pa_size;
47   int offset;
48
49   /* minimum possible size of a jbig2 segment header */
50   if (buf_size < 11)
51     return NULL;
52
53   result = jbig2_new(ctx, Jbig2Segment, 1);
54   if (result == NULL)
55   {
56       jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
57           "failed to allocate segment in jbig2_parse_segment_header");
58       return result;
59   }
60
61   /* 7.2.2 */
62   result->number = jbig2_get_uint32(buf);
63
64   /* 7.2.3 */
65   result->flags = buf[4];
66
67   /* 7.2.4 referred-to segments */
68   rtscarf = buf[5];
69   if ((rtscarf & 0xe0) == 0xe0)
70     {
71       rtscarf_long = jbig2_get_uint32(buf + 5);
72       referred_to_segment_count = rtscarf_long & 0x1fffffff;
73       offset = 5 + 4 + (referred_to_segment_count + 1) / 8;
74     }
75   else
76     {
77       referred_to_segment_count = (rtscarf >> 5);
78       offset = 5 + 1;
79     }
80   result->referred_to_segment_count = referred_to_segment_count;
81
82   /* we now have enough information to compute the full header length */
83   referred_to_segment_size = result->number <= 256 ? 1:
84         result->number <= 65536 ? 2 : 4;  /* 7.2.5 */
85   pa_size = result->flags & 0x40 ? 4 : 1; /* 7.2.6 */
86   if (offset + referred_to_segment_count*referred_to_segment_size + pa_size + 4 > buf_size)
87     {
88       jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, result->number,
89         "jbig2_parse_segment_header() called with insufficient data", -1);
90       jbig2_free (ctx->allocator, result);
91       return NULL;
92     }
93
94   /* 7.2.5 */
95   if (referred_to_segment_count)
96     {
97       int i;
98
99       referred_to_segments = jbig2_new(ctx, uint32_t,
100         referred_to_segment_count * referred_to_segment_size);
101       if (referred_to_segments == NULL)
102       {
103           jbig2_error(ctx, JBIG2_SEVERITY_FATAL, -1,
104               "could not allocate referred_to_segments "
105               "in jbig2_parse_segment_header");
106           return NULL;
107       }
108
109       for (i = 0; i < referred_to_segment_count; i++) {
110         referred_to_segments[i] =
111           (referred_to_segment_size == 1) ? buf[offset] :
112           (referred_to_segment_size == 2) ? jbig2_get_uint16(buf+offset) :
113             jbig2_get_uint32(buf + offset);
114         offset += referred_to_segment_size;
115         jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, result->number,
116             "segment %d refers to segment %d",
117             result->number, referred_to_segments[i]);
118       }
119       result->referred_to_segments = referred_to_segments;
120     }
121   else /* no referred-to segments */
122     {
123       result->referred_to_segments = NULL;
124     }
125
126   /* 7.2.6 */
127   if (result->flags & 0x40) {
128         result->page_association = jbig2_get_uint32(buf + offset);
129         offset += 4;
130   } else {
131         result->page_association = buf[offset++];
132   }
133   jbig2_error(ctx, JBIG2_SEVERITY_DEBUG, result->number,
134         "segment %d is associated with page %d",
135         result->number, result->page_association);
136
137   /* 7.2.7 */
138   result->data_length = jbig2_get_uint32(buf + offset);
139   *p_header_size = offset + 4;
140
141   /* no body parsing results yet */
142   result->result = NULL;
143
144   return result;
145 }
146
147 void
148 jbig2_free_segment (Jbig2Ctx *ctx, Jbig2Segment *segment)
149 {
150   if (segment->referred_to_segments != NULL) {
151     jbig2_free(ctx->allocator, segment->referred_to_segments);
152   }
153   /* todo: we need either some separate fields or
154      a more complex result object rather than this
155      brittle special casing */
156     switch (segment->flags & 63) {
157         case 0:  /* symbol dictionary */
158           if (segment->result != NULL)
159             jbig2_sd_release(ctx, (Jbig2SymbolDict*)segment->result);
160           break;
161         case 4:  /* intermediate text region */
162         case 40: /* intermediate refinement region */
163           if (segment->result != NULL)
164             jbig2_image_release(ctx, (Jbig2Image*)segment->result);
165           break;
166         case 16: /* pattern dictionary */
167       if (segment->result != NULL)
168         jbig2_hd_release(ctx, (Jbig2PatternDict*)segment->result);
169       break;
170         case 53: /* user-supplied huffman table */
171           if (segment->result != NULL)
172                 jbig2_table_free(ctx, (Jbig2HuffmanParams*)segment->result);
173           break;
174         case 62:
175           if (segment->result != NULL)
176             jbig2_metadata_free(ctx, (Jbig2Metadata*)segment->result);
177           break;
178         default:
179           /* anything else is probably an undefined pointer */
180           break;
181     }
182   jbig2_free (ctx->allocator, segment);
183 }
184
185 /* find a segment by number */
186 Jbig2Segment *
187 jbig2_find_segment(Jbig2Ctx *ctx, uint32_t number)
188 {
189     int index, index_max = ctx->segment_index - 1;
190     const Jbig2Ctx *global_ctx = ctx->global_ctx;
191
192     /* FIXME: binary search would be better */
193     for (index = index_max; index >= 0; index--)
194         if (ctx->segments[index]->number == number)
195             return (ctx->segments[index]);
196
197     if (global_ctx)
198         for (index = global_ctx->segment_index - 1; index >= 0; index--)
199             if (global_ctx->segments[index]->number == number)
200                 return (global_ctx->segments[index]);
201
202     /* didn't find a match */
203     return NULL;
204 }
205
206 /* parse the generic portion of a region segment data header */
207 void
208 jbig2_get_region_segment_info(Jbig2RegionSegmentInfo *info,
209                               const uint8_t *segment_data)
210 {
211   /* 7.4.1 */
212   info->width = jbig2_get_int32(segment_data);
213   info->height = jbig2_get_int32(segment_data + 4);
214   info->x = jbig2_get_int32(segment_data + 8);
215   info->y = jbig2_get_int32(segment_data + 12);
216   info->flags = segment_data[16];
217   info->op = (Jbig2ComposeOp)(info->flags & 0x7);
218 }
219
220 /* dispatch code for extension segment parsing */
221 int jbig2_parse_extension_segment(Jbig2Ctx *ctx, Jbig2Segment *segment,
222                             const uint8_t *segment_data)
223 {
224     uint32_t type = jbig2_get_uint32(segment_data);
225     bool reserved = type & 0x20000000;
226     /* bool dependent = type & 0x40000000; (NYI) */
227     bool necessary = type & 0x80000000;
228
229     if (necessary && !reserved) {
230         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
231             "extension segment is marked 'necessary' but "
232             "not 'reservered' contrary to spec");
233     }
234
235     switch (type) {
236         case 0x20000000: return jbig2_comment_ascii(ctx, segment, segment_data);
237         case 0x20000002: return jbig2_comment_unicode(ctx, segment, segment_data);
238         default:
239             if (necessary) {
240                 return jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number,
241                     "unhandled necessary extension segment type 0x%08x", type);
242             } else {
243                 return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
244                     "unhandled extension segment");
245             }
246     }
247 }
248
249 /* general segment parsing dispatch */
250 int jbig2_parse_segment (Jbig2Ctx *ctx, Jbig2Segment *segment,
251                          const uint8_t *segment_data)
252 {
253   jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
254               "Segment %d, flags=%x, type=%d, data_length=%d",
255               segment->number, segment->flags, segment->flags & 63,
256               segment->data_length);
257   switch (segment->flags & 63)
258     {
259     case 0:
260       return jbig2_symbol_dictionary(ctx, segment, segment_data);
261     case 4: /* intermediate text region */
262     case 6: /* immediate text region */
263     case 7: /* immediate lossless text region */
264       return jbig2_text_region(ctx, segment, segment_data);
265     case 16:
266       return jbig2_pattern_dictionary(ctx, segment, segment_data);
267     case 20: /* intermediate halftone region */
268     case 22: /* immediate halftone region */
269     case 23: /* immediate lossless halftone region */
270       return jbig2_halftone_region(ctx, segment, segment_data);
271     case 36:
272       return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
273         "unhandled segment type 'intermediate generic region'");
274     case 38: /* immediate generic region */
275     case 39: /* immediate lossless generic region */
276       return jbig2_immediate_generic_region(ctx, segment, segment_data);
277     case 40: /* intermediate generic refinement region */
278     case 42: /* immediate generic refinement region */
279     case 43: /* immediate lossless generic refinement region */
280       return jbig2_refinement_region(ctx, segment, segment_data);
281     case 48:
282       return jbig2_page_info(ctx, segment, segment_data);
283     case 49:
284       return jbig2_end_of_page(ctx, segment, segment_data);
285     case 50:
286       return jbig2_end_of_stripe(ctx, segment, segment_data);
287     case 51:
288       ctx->state = JBIG2_FILE_EOF;
289       return jbig2_error(ctx, JBIG2_SEVERITY_INFO, segment->number,
290         "end of file");
291     case 52:
292       return jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
293         "unhandled segment type 'profile'");
294     case 53: /* user-supplied huffman table */
295       return jbig2_table(ctx, segment, segment_data);
296     case 62:
297       return jbig2_parse_extension_segment(ctx, segment, segment_data);
298     default:
299         jbig2_error(ctx, JBIG2_SEVERITY_WARNING, segment->number,
300           "unknown segment type %d", segment->flags & 63);
301     }
302   return 0;
303 }