/src/ghostpdl/base/gxdhtserial.c
Line | Count | Source (jump to first uncovered line) |
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 | | /* Serialization and de-serialization for (traditional) halftones */ |
18 | | |
19 | | #include "memory_.h" |
20 | | #include "gx.h" |
21 | | #include "gscdefs.h" |
22 | | #include "gserrors.h" |
23 | | #include "gsstruct.h" |
24 | | #include "gsutil.h" /* for gs_next_ids */ |
25 | | #include "gzstate.h" |
26 | | #include "gxdevice.h" /* for gzht.h */ |
27 | | #include "gzht.h" |
28 | | #include "gxdhtres.h" |
29 | | #include "gsserial.h" |
30 | | #include "gxdhtserial.h" |
31 | | |
32 | | /* |
33 | | * Declare the set of procedures that return resident halftones. This |
34 | | * declares both the array of procedures and their type. It is used |
35 | | * only to check if a transmitted halftone order matches one in ROM. |
36 | | */ |
37 | | extern_gx_device_halftone_list(); |
38 | | |
39 | | /* |
40 | | * An enumeration of halftone transfer functions. These must distinguish |
41 | | * between cases in which no transfer function is present, and when one |
42 | | * is present but provides the identity transformation (an empty |
43 | | * PostScript array). |
44 | | */ |
45 | | typedef enum { |
46 | | gx_ht_tf_none = 0, |
47 | | gx_ht_tf_identity, |
48 | | gx_ht_tf_complete |
49 | | } gx_ht_tf_type_t; |
50 | | |
51 | | /* |
52 | | * Serialize a transfer function. These will occupy one byte if they are |
53 | | * not present or provide an identity mapping, |
54 | | * 1 + transfer_map_size * sizeof(frac) otherwise. |
55 | | * |
56 | | * Returns: |
57 | | * |
58 | | * 0, with *psize set the the amount of space required, if successful |
59 | | * |
60 | | * gs_error_rangecheck, with *psize set to the size required, if the |
61 | | * original *psize was not large enough |
62 | | */ |
63 | | static int |
64 | | gx_ht_write_tf( |
65 | | const gx_transfer_map * pmap, |
66 | | byte * data, |
67 | | uint * psize ) |
68 | 263k | { |
69 | 263k | int req_size = 1; /* minimum of one byte */ |
70 | | |
71 | | /* check for sufficient space */ |
72 | 263k | if ( pmap != 0 && pmap->proc != gs_identity_transfer) |
73 | 0 | req_size += sizeof(pmap->values); |
74 | 263k | if (req_size > *psize) { |
75 | 197k | *psize = req_size; |
76 | 197k | return_error(gs_error_rangecheck); |
77 | 197k | } |
78 | | |
79 | 65.9k | if (req_size == 1) |
80 | 65.9k | *data = (byte)(pmap == 0 ? gx_ht_tf_none : gx_ht_tf_identity); |
81 | 0 | else { |
82 | 0 | *data++ = (byte)gx_ht_tf_complete; |
83 | 0 | memcpy(data, pmap->values, sizeof(pmap->values)); |
84 | 0 | } |
85 | | |
86 | 65.9k | *psize = req_size; |
87 | 65.9k | return 0; |
88 | 263k | } |
89 | | |
90 | | /* |
91 | | * Reconstruct a transfer function from its serial representation. The |
92 | | * buffer provided is expected to be large enough to hold the entire |
93 | | * transfer function. |
94 | | * |
95 | | * Returns the number of bytes read, or < 0 in the event of an error. |
96 | | */ |
97 | | static int |
98 | | gx_ht_read_tf( |
99 | | gx_transfer_map ** ppmap, |
100 | | const byte * data, |
101 | | uint size, |
102 | | gs_memory_t * mem ) |
103 | 2.40M | { |
104 | 2.40M | gx_ht_tf_type_t tf_type; |
105 | 2.40M | gx_transfer_map * pmap; |
106 | | |
107 | | /* read the type byte */ |
108 | 2.40M | if (size == 0) |
109 | 0 | return_error(gs_error_rangecheck); |
110 | 2.40M | --size; |
111 | 2.40M | tf_type = (gx_ht_tf_type_t)*data++; |
112 | | |
113 | | /* If no transfer function or identity set to NULL */ |
114 | 2.40M | if (tf_type == gx_ht_tf_none || tf_type == gx_ht_tf_identity) { |
115 | 2.40M | *ppmap = NULL; |
116 | 2.40M | return 1; |
117 | 2.40M | } |
118 | | |
119 | | /* If something strange then exit. Likely clist issue */ |
120 | 0 | if (tf_type != gx_ht_tf_complete || size < sizeof(pmap->values)) |
121 | 0 | return_error(gs_error_rangecheck); |
122 | | |
123 | | /* Otherwise we have a real map. Allocate a transfer map */ |
124 | 0 | rc_alloc_struct_1( pmap, |
125 | 0 | gx_transfer_map, |
126 | 0 | &st_transfer_map, |
127 | 0 | mem, |
128 | 0 | return_error(gs_error_VMerror), |
129 | 0 | "gx_ht_read_tf" ); |
130 | 0 | pmap->id = gs_next_ids(mem, 1); |
131 | 0 | pmap->closure.proc = 0; |
132 | 0 | pmap->closure.data = 0; |
133 | 0 | memcpy(pmap->values, data, sizeof(pmap->values)); |
134 | 0 | pmap->proc = gs_mapped_transfer; |
135 | 0 | *ppmap = pmap; |
136 | 0 | return 1 + sizeof(pmap->values); |
137 | 0 | } |
138 | | |
139 | | /* |
140 | | * Serialize a halftone component. The only part that is serialized is the |
141 | | * halftone order; the other two components are only required during |
142 | | * halftone construction. |
143 | | * |
144 | | * Returns: |
145 | | * |
146 | | * 0, with *psize set the the amount of space required, if successful |
147 | | * |
148 | | * gs_error_rangecheck, with *psize set to the size required, if the |
149 | | * original *psize was not large enough |
150 | | * |
151 | | * some other error code, with *psize unchanged, in the event of an |
152 | | * error other than lack of space |
153 | | */ |
154 | | static int |
155 | | gx_ht_write_component( |
156 | | const gx_ht_order_component * pcomp, |
157 | | byte * data, |
158 | | uint * psize ) |
159 | 197k | { |
160 | 197k | const gx_ht_order * porder = &pcomp->corder; |
161 | 197k | byte * data0 = data; |
162 | 197k | int code, levels_size, bits_size; |
163 | 197k | uint tmp_size = 0; |
164 | 197k | int req_size; |
165 | | |
166 | | /* |
167 | | * There is no need to transmit the comp_number field, as this must be |
168 | | * the same as the index in the component array (see gx_ht_write). |
169 | | * |
170 | | * There is also no reason to transmit the colorant name (cname), as |
171 | | * this is only used by some high-level devices that would not be targets |
172 | | * of the command list device (and even those devices should be able to |
173 | | * get the information from their color models). |
174 | | * |
175 | | * This leaves the order itself. |
176 | | */ |
177 | | |
178 | | /* |
179 | | * The following order fields are not transmitted: |
180 | | * |
181 | | * params Only required during halftone cell construction |
182 | | * |
183 | | * raster Can be re-calculated by the renderer from the width |
184 | | * |
185 | | * orig_height, The only potential use for these parameters is in |
186 | | * orig_shift this routine; they are not useful to the renderer. |
187 | | * |
188 | | * full_height Can be re-calculated by the renderer from the |
189 | | * height, width, and shift values. |
190 | | * |
191 | | * data_memory Must be provided by the renderer. |
192 | | * |
193 | | * cache Must be provided by the renderer. |
194 | | * |
195 | | * screen_params Ony required during halftone cell construction |
196 | | * |
197 | | * In addition, the procs parameter is passed as an index into the |
198 | | * ht_order_procs_table, as the renderer may not be in the same address |
199 | | * space as the writer. |
200 | | * |
201 | | * Calculate the size required. |
202 | | */ |
203 | 197k | levels_size = porder->num_levels * sizeof(porder->levels[0]); |
204 | 197k | bits_size = porder->num_bits * porder->procs->bit_data_elt_size; |
205 | 197k | req_size = enc_u_sizew(porder->width) |
206 | 197k | + enc_u_sizew(porder->height) |
207 | 197k | + enc_u_sizew(porder->shift) |
208 | 197k | + enc_u_sizew(porder->num_levels) |
209 | 197k | + enc_u_sizew(porder->num_bits) |
210 | 197k | + 1 /* order procs, as index into table */ |
211 | 197k | + levels_size |
212 | 197k | + bits_size; |
213 | 197k | code = gx_ht_write_tf(porder->transfer, data, &tmp_size); |
214 | 197k | if (code < 0 && code != gs_error_rangecheck) |
215 | 0 | return code; |
216 | 197k | req_size += tmp_size; |
217 | 197k | if (req_size > *psize) { |
218 | 131k | *psize = req_size; |
219 | 131k | return_error(gs_error_rangecheck); |
220 | 131k | } |
221 | | |
222 | | /* write out the dimensional data */ |
223 | 197k | enc_u_putw(porder->width, data); |
224 | 65.9k | enc_u_putw(porder->height, data); |
225 | 65.9k | enc_u_putw(porder->shift, data); |
226 | 65.9k | enc_u_putw(porder->num_levels, data); |
227 | 65.9k | enc_u_putw(porder->num_bits, data); |
228 | | |
229 | | /* white out the procs index */ |
230 | 65.9k | *data++ = porder->procs - ht_order_procs_table; |
231 | | |
232 | | /* copy the levels array and whitening order array */ |
233 | 65.9k | memcpy(data, porder->levels, levels_size); |
234 | 65.9k | data += levels_size; |
235 | 65.9k | memcpy(data, porder->bit_data, bits_size); |
236 | 65.9k | data += bits_size; |
237 | | |
238 | | /* write out the transfer function */ |
239 | 65.9k | tmp_size = *psize - (data - data0); |
240 | 65.9k | if ((code = gx_ht_write_tf(porder->transfer, data, &tmp_size)) == 0) |
241 | 65.9k | *psize = tmp_size + (data - data0); |
242 | 65.9k | return code; |
243 | 197k | } |
244 | | |
245 | | /* |
246 | | * Reconstruct a halftone component from its serial representation. The |
247 | | * buffer provided is expected to be large enough to hold the entire |
248 | | * halftone component. |
249 | | * |
250 | | * Because halftone components are allocated in arrays (an unfortunate |
251 | | * arrangement, as it prevents component sharing), a pointer to an |
252 | | * already allocated component structure is passed as an operand, as |
253 | | * opposed to the more normal mechanism that would have a read routine |
254 | | * allocate the component. The memory pointer is still passed, however, |
255 | | * as the levels and bit_data arrays must be allocated. |
256 | | * |
257 | | * Returns the number of bytes read, or < 0 in the event of an error. |
258 | | */ |
259 | | static int |
260 | | gx_ht_read_component( |
261 | | gx_ht_order_component * pcomp, |
262 | | const byte * data, |
263 | | uint size, |
264 | | gs_memory_t * mem ) |
265 | 2.40M | { |
266 | 2.40M | gx_ht_order new_order; |
267 | 2.40M | const byte * data0 = data; |
268 | 2.40M | const byte * data_lim = data + size; |
269 | 2.40M | int i, code, levels_size, bits_size; |
270 | 2.40M | const gx_dht_proc * phtrp = gx_device_halftone_list; |
271 | | |
272 | | /* check the order type */ |
273 | 2.40M | if (size == 0) |
274 | 0 | return_error(gs_error_rangecheck); |
275 | | |
276 | | /* |
277 | | * For performance reasons, the number encoding macros do not |
278 | | * support full buffer size verification. The code below verifies |
279 | | * that a minimum number of bytes is available, then converts |
280 | | * blindly and does not check again until the various integers are |
281 | | * read. Obviously this can be hazardous, but should not be a |
282 | | * problem in practice, as the calling code should have verified |
283 | | * that the data provided holds the entire halftone. |
284 | | */ |
285 | 2.40M | if (size < 7) |
286 | 0 | return_error(gs_error_rangecheck); |
287 | 2.40M | enc_u_getw(new_order.width, data); |
288 | 2.40M | enc_u_getw(new_order.height, data); |
289 | 2.40M | enc_u_getw(new_order.shift, data); |
290 | 2.40M | enc_u_getw(new_order.num_levels, data); |
291 | 2.40M | enc_u_getw(new_order.num_bits, data); |
292 | 2.40M | if (data >= data_lim) |
293 | 0 | return_error(gs_error_rangecheck); |
294 | 2.40M | new_order.procs = &ht_order_procs_table[*data++]; |
295 | 2.40M | new_order.threshold_inverted = 0; |
296 | | |
297 | | /* calculate the space required for levels and bit data */ |
298 | 2.40M | levels_size = new_order.num_levels * sizeof(new_order.levels[0]); |
299 | 2.40M | bits_size = new_order.num_bits * new_order.procs->bit_data_elt_size; |
300 | | |
301 | | /* + 1 below is for the minimal transfer function */ |
302 | 2.40M | if (data + bits_size + levels_size + 1 > data_lim) |
303 | 0 | return_error(gs_error_rangecheck); |
304 | | |
305 | | /* |
306 | | * Allocate the levels and bit data structures. The gx_ht_alloc_ht_order |
307 | | * has a name that is both strange and misleading. The routine does |
308 | | * not allocate a halftone order. Rather, it initializes the order, |
309 | | * and allocates the levels and bit data arrays. In particular, it |
310 | | * sets all of the following fields: |
311 | | * |
312 | | * width = operand width |
313 | | * height = operand height |
314 | | * raster = bitmap_raster(operand width) |
315 | | * shift = operand shift |
316 | | * orig_height = operand height |
317 | | * orig_shift = operand strip_shift |
318 | | * num_levels = operand num_levels |
319 | | * num_bits = operand num_bits |
320 | | * procs = operand procs |
321 | | * levels = newly allocated array |
322 | | * bit_data = new allocated array |
323 | | * cache = 0 |
324 | | * transfer = 0 |
325 | | * |
326 | | * Since several of the list fields are already set, this call |
327 | | * effectively sets them to the values they already have. This is a |
328 | | * bit peculiar but not otherwise harmful. |
329 | | * |
330 | | * For reasons that are not known and are probably historical, the |
331 | | * procedure does not initialize the params or screen_params fields. |
332 | | * In the unlikely event that these fields are ever contain pointers, |
333 | | * we initialize them explicitly here. Wse, params, and scrren_params |
334 | | * probably should not occur in the device halftone at all; they are |
335 | | * themselves historical artifacts. |
336 | | */ |
337 | 2.40M | code = gx_ht_alloc_ht_order( &new_order, |
338 | 2.40M | new_order.width, |
339 | 2.40M | new_order.height, |
340 | 2.40M | new_order.num_levels, |
341 | 2.40M | new_order.num_bits, |
342 | 2.40M | new_order.shift, |
343 | 2.40M | new_order.procs, |
344 | 2.40M | mem ); |
345 | 2.40M | if (code < 0) |
346 | 0 | return code; |
347 | 2.40M | memset(&new_order.params, 0, sizeof(new_order.params)); |
348 | 2.40M | memset(&new_order.screen_params, 0, sizeof(new_order.screen_params)); |
349 | | |
350 | | /* fill in the levels and bit_data arrays */ |
351 | 2.40M | memcpy(new_order.levels, data, levels_size); |
352 | 2.40M | data += levels_size; |
353 | 2.40M | memcpy(new_order.bit_data, data, bits_size); |
354 | 2.40M | data += bits_size; |
355 | | |
356 | | /* process the transfer function */ |
357 | 2.40M | code = gx_ht_read_tf(&new_order.transfer, data, data_lim - data, mem); |
358 | 2.40M | if (code < 0) { |
359 | 0 | gx_ht_order_release(&new_order, mem, false); |
360 | 0 | return code; |
361 | 0 | } |
362 | 2.40M | data += code; |
363 | | |
364 | | /* |
365 | | * Check to see if the order is in ROM. Since it is possible (if not |
366 | | * particularly likely) that the command list writer and renderer do |
367 | | * not have the same set of ROM-based halftones, the full halftone |
368 | | * order is transmitted and compared against the set ROM set provided |
369 | | * by the renderer. If there is a match, the transmitted version is |
370 | | * discarded and the ROM version used. |
371 | | * |
372 | | * It is not clear which, if any or the currently used devices |
373 | | * provide a ROM-based halftone order set. |
374 | | */ |
375 | 2.40M | for (i = 0; phtrp[i] != 0; i++) { |
376 | 0 | const gx_device_halftone_resource_t *const * pphtr = phtrp[i](); |
377 | 0 | const gx_device_halftone_resource_t * phtr; |
378 | |
|
379 | 0 | while ((phtr = *pphtr++) != 0) { |
380 | | /* |
381 | | * This test does not check for strict equality of the order, |
382 | | * nor is strict equality necessary. The ROM data will replace |
383 | | * just the levels and bit_data arrays of the transmitted |
384 | | * order, so only these must be the same. We don't even care |
385 | | * if the ROM's levels and bit_data arrays are larger; we |
386 | | * will never check values beyond the range required by the |
387 | | * current order. |
388 | | */ |
389 | 0 | if ( phtr->num_levels * sizeof(phtr->levels[0]) >= levels_size && |
390 | 0 | phtr->Width * phtr->Height * phtr->elt_size >= bits_size && |
391 | 0 | memcmp(phtr->levels, new_order.levels, levels_size) == 0 && |
392 | 0 | memcmp(phtr->bit_data, new_order.bit_data, bits_size) == 0 ) { |
393 | | /* the casts below are required to discard const qualifiers */ |
394 | 0 | gs_free_object(mem, new_order.bit_data, "gx_ht_read_component"); |
395 | 0 | new_order.bit_data = (void *)phtr->bit_data; |
396 | 0 | gs_free_object(mem, new_order.levels, "gx_ht_read_component"); |
397 | 0 | new_order.levels = (uint *)phtr->levels; |
398 | 0 | goto done; |
399 | 0 | } |
400 | 0 | } |
401 | 0 | } |
402 | | |
403 | 2.40M | done: |
404 | | /* everything OK, save the order and return the # of bytes read */ |
405 | 2.40M | pcomp->corder = new_order; |
406 | 2.40M | pcomp->cname = 0; |
407 | 2.40M | return data - data0; |
408 | 2.40M | } |
409 | | |
410 | | /* |
411 | | * Serialize a halftone. The essential step is the serialization of the |
412 | | * halftone orders; beyond this only the halftone type must be |
413 | | * transmitted. |
414 | | * |
415 | | * Returns: |
416 | | * |
417 | | * 0, with *psize set the the amount of space required, if successful |
418 | | * |
419 | | * gs_error_rangecheck, with *psize set to the size required, if the |
420 | | * original *psize was not large enough |
421 | | * |
422 | | * some other error code, with *psize unchange, in the event of an |
423 | | * error other than lack of space |
424 | | */ |
425 | | int |
426 | | gx_ht_write( |
427 | | const gx_device_halftone * pdht, |
428 | | const gx_device * dev, |
429 | | byte * data, |
430 | | uint * psize ) |
431 | 52.9k | { |
432 | 52.9k | int num_dev_comps; |
433 | 52.9k | int i, code; |
434 | 52.9k | uint req_size = 2, used_size = 2; |
435 | | /* 1 for halftone type, 1 for num_dev_comps */ |
436 | | |
437 | | /* |
438 | | * With the introduction of color models, there should never be a |
439 | | * halftone that includes just one component. Enforce this |
440 | | * restriction, even though it is not present in much of the rest |
441 | | * of the code. |
442 | | * |
443 | | * NB: the pdht->order field is ignored by this code. |
444 | | */ |
445 | 52.9k | if (pdht == 0 || pdht->components == 0) |
446 | 0 | return_error(gs_error_unregistered); /* Must not happen. */ |
447 | 52.9k | num_dev_comps = pdht->num_dev_comp; |
448 | | |
449 | | /* |
450 | | * The following fields do not need to be transmitted: |
451 | | * |
452 | | * order Ignored by this code (see above). |
453 | | * |
454 | | * rc, id Recreated by the allocation code on the renderer. |
455 | | * |
456 | | * lcm_width, Can be recreated by the de-serialization code on the |
457 | | * lcm_height the renderer. Since halftones are transmitted |
458 | | * infrequently (for normal jobs), the time required |
459 | | * for re-calculation is not significant. |
460 | | * |
461 | | * Hence, the only fields that must be serialized are the type,and |
462 | | * the number of components. (The number of components for the halftone |
463 | | * may not match the device's if we are compositing with a process color |
464 | | * model which does not match the output device. |
465 | | * |
466 | | * Several halftone components may be identical, but there is |
467 | | * currently no simple way to determine this. Halftones are normally |
468 | | * transmitted only once per page, so it is not clear that use of |
469 | | * such information would significantly reduce command list size. |
470 | | */ |
471 | | |
472 | | /* calculate the required data space */ |
473 | 52.9k | for ( i = 0, code = gs_error_rangecheck; |
474 | 184k | i < num_dev_comps && code == gs_error_rangecheck; |
475 | 131k | i++) { |
476 | 131k | uint tmp_size = 0; |
477 | | |
478 | | /* sanity check */ |
479 | 131k | if (i != pdht->components[i].comp_number) |
480 | 0 | return_error(gs_error_unregistered); /* Must not happen. */ |
481 | | |
482 | 131k | code = gx_ht_write_component( &pdht->components[i], |
483 | 131k | data, |
484 | 131k | &tmp_size ); |
485 | 131k | req_size += tmp_size; |
486 | 131k | } |
487 | 52.9k | if (code < 0 && code != gs_error_rangecheck) |
488 | 0 | return code; |
489 | 52.9k | else if (*psize < req_size) { |
490 | 26.4k | *psize = req_size; |
491 | 26.4k | return 0; |
492 | 26.4k | } |
493 | 26.4k | req_size = *psize; |
494 | | |
495 | | /* the halftone type is known to fit in a byte */ |
496 | 26.4k | *data++ = (byte)pdht->type; |
497 | | /* the number of components is known to fit in a byte */ |
498 | 26.4k | *data++ = (byte)num_dev_comps; |
499 | | |
500 | | /* serialize the halftone components */ |
501 | 92.3k | for (i = 0, code = 0; i < num_dev_comps && code == 0; i++) { |
502 | 65.9k | uint tmp_size = req_size - used_size; |
503 | | |
504 | 65.9k | code = gx_ht_write_component( &pdht->components[i], |
505 | 65.9k | data, |
506 | 65.9k | &tmp_size ); |
507 | 65.9k | used_size += tmp_size; |
508 | 65.9k | data += tmp_size; |
509 | 65.9k | } |
510 | | |
511 | 26.4k | if (code < 0) { |
512 | 0 | if (code == gs_error_rangecheck) |
513 | 0 | code = gs_error_unknownerror; |
514 | 0 | return code; |
515 | 0 | } |
516 | | |
517 | 26.4k | *psize = used_size; |
518 | 26.4k | return 0; |
519 | 26.4k | } |
520 | | |
521 | | /* |
522 | | * Reconstruct a halftone from its serial representation, and install it |
523 | | * as the current halftone. The buffer provided is expected to be large |
524 | | * enough to hold the entire halftone. |
525 | | * |
526 | | * The reading and installation phases are combined in this routine so as |
527 | | * to avoid unnecessarily allocating a device halftone and its component |
528 | | * array, just to release them immediately after installation is complete. |
529 | | * There is also not much reason to reconstuct a halftone except to make |
530 | | * it the current halftone. |
531 | | * |
532 | | * Returns the number of bytes read, or <0 in the event of an error. |
533 | | */ |
534 | | int |
535 | | gx_ht_read_and_install( |
536 | | gs_gstate * pgs, |
537 | | const gx_device * dev, |
538 | | const byte * data, |
539 | | uint size, |
540 | | gs_memory_t * mem ) |
541 | 963k | { |
542 | 963k | gx_ht_order_component components[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
543 | 963k | gx_ht_order_component components_save[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
544 | 963k | const byte * data0 = data; |
545 | 963k | gx_device_halftone dht; |
546 | 963k | int num_dev_comps; |
547 | 963k | int i, code; |
548 | | |
549 | | /* fill in some fixed fields */ |
550 | 963k | memset(&dht.order, 0, sizeof(dht.order)); |
551 | 963k | memset(&dht.rc, 0, sizeof(dht.rc)); |
552 | 963k | dht.id = gs_no_id; /* updated during installation */ |
553 | 963k | dht.components = components; |
554 | 963k | dht.lcm_width = 1; /* recalculated during installation */ |
555 | 963k | dht.lcm_height = 1; |
556 | | |
557 | | /* clear pointers in the components array in case we need to abort */ |
558 | 963k | memset(components, 0, sizeof(components)); |
559 | | |
560 | | /* get the halftone type */ |
561 | 963k | if (size < 2) |
562 | 0 | return_error(gs_error_rangecheck); |
563 | 963k | dht.type = (gs_halftone_type)(*data++); |
564 | 963k | num_dev_comps = dht.num_dev_comp = dht.num_comp = *data++; |
565 | 963k | size -= 2; |
566 | | |
567 | | /* process the component orders */ |
568 | 3.37M | for (i = 0, code = 0; i < num_dev_comps && code >= 0; i++) { |
569 | 2.40M | components[i].comp_number = i; |
570 | 2.40M | code = gx_ht_read_component(&components[i], data, size, mem); |
571 | 2.40M | if (code >= 0) { |
572 | 2.40M | size -= code; |
573 | 2.40M | data += code; |
574 | 2.40M | } |
575 | 2.40M | } |
576 | | |
577 | | /* if everything is OK, install the halftone */ |
578 | 963k | if (code >= 0) { |
579 | | /* save since the 'install' copies the order, but then clears the source order */ |
580 | 3.37M | for (i = 0; i < num_dev_comps; i++) |
581 | 2.40M | components_save[i] = components[i]; |
582 | 963k | code = gx_gstate_dev_ht_install(pgs, &dht, dht.type, dev, HT_OBJTYPE_DEFAULT); |
583 | 963k | if (code >= 0) { |
584 | 3.37M | for (i = 0; i < num_dev_comps; i++) |
585 | 2.40M | gx_ht_order_release(&components_save[i].corder, mem, false); |
586 | 963k | } |
587 | 963k | } |
588 | | |
589 | | /* |
590 | | * If installation failed, discard the allocated elements. We can't |
591 | | * use the gx_device_halftone_release procedure, as the components |
592 | | * array is on the stack rather than in the heap. |
593 | | */ |
594 | 963k | if (code < 0) { |
595 | 0 | for (i = 0; i < num_dev_comps; i++) |
596 | 0 | gx_ht_order_release(&components[i].corder, mem, false); |
597 | 0 | } |
598 | | |
599 | 963k | return code < 0 ? code : data - data0; |
600 | 963k | } |