Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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