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 /* Default device parameters for Ghostscript library */
18 #include "memory_.h" /* for memcpy */
19 #include "string_.h" /* for strlen */
20 #include "gx.h"
21 #include "gserrors.h"
22 #include "gsdevice.h" /* for prototypes */
23 #include "gsparam.h"
24 #include "gxdevice.h"
25 #include "gxfixed.h"
26 #include "gsicc_manage.h"
27
28
29 static const char *const std_intent_keys[] = {
30 GSICC_STANDARD_INTENT_KEYS
31 };
32
33 /* Define whether we accept PageSize as a synonym for MediaSize. */
34 /* This is for backward compatibility only. */
35 #define PAGESIZE_IS_MEDIASIZE
36
37 /* ================ Getting parameters ================ */
38
39 /* Forward references */
40 static bool param_HWColorMap(gx_device *, byte *);
41
42 /* Get the device parameters. */
43 int
gs_get_device_or_hw_params(gx_device * orig_dev,gs_param_list * plist,bool is_hardware)44 gs_get_device_or_hw_params(gx_device * orig_dev, gs_param_list * plist,
45 bool is_hardware)
46 {
47 /*
48 * We must be prepared to copy the device if it is the read-only
49 * prototype.
50 */
51 gx_device *dev;
52 int code;
53
54 if (orig_dev->memory)
55 dev = orig_dev;
56 else {
57 code = gs_copydevice(&dev, orig_dev, plist->memory);
58 if (code < 0)
59 return code;
60 }
61 gx_device_set_procs(dev);
62 fill_dev_proc(dev, get_params, gx_default_get_params);
63 fill_dev_proc(dev, get_page_device, gx_default_get_page_device);
64 fill_dev_proc(dev, get_alpha_bits, gx_default_get_alpha_bits);
65 code = (is_hardware ?
66 (*dev_proc(dev, get_hardware_params)) (dev, plist) :
67 (*dev_proc(dev, get_params)) (dev, plist));
68 if (dev != orig_dev)
69 gx_device_retain(dev, false); /* frees the copy */
70 return code;
71 }
72
73 /* Get standard parameters. */
74 int
gx_default_get_params(gx_device * dev,gs_param_list * plist)75 gx_default_get_params(gx_device * dev, gs_param_list * plist)
76 {
77 int code;
78
79 /* Standard page device parameters: */
80
81 bool seprs = false;
82 gs_param_string dns, pcms, profile_array[NUM_DEVICE_PROFILES];
83 gs_param_string proof_profile, link_profile;
84 gsicc_rendering_intents_t profile_intents[NUM_DEVICE_PROFILES];
85 bool devicegraytok = true; /* Default if device profile stuct not set */
86 bool usefastcolor = false; /* set for unmanaged color */
87 int k;
88 gs_param_float_array msa, ibba, hwra, ma;
89 gs_param_string_array scna;
90 char null_str[1]={'\0'};
91
92 #define set_param_array(a, d, s)\
93 (a.data = d, a.size = s, a.persistent = false);
94
95 /* Non-standard parameters: */
96 int colors = dev->color_info.num_components;
97 int mns = colors;
98 int depth = dev->color_info.depth;
99 int GrayValues = dev->color_info.max_gray + 1;
100 int HWSize[2];
101 gs_param_int_array hwsa;
102 gs_param_float_array hwma, mhwra;
103 cmm_dev_profile_t *dev_profile;
104
105 /* Fill in page device parameters. */
106
107 param_string_from_string(dns, dev->dname);
108 {
109 const char *cms = get_process_color_model_name(dev);
110
111 /* We might have an uninitialized device with */
112 /* color_info.num_components = 0.... */
113 if ((cms != NULL) && (*cms != '\0'))
114 param_string_from_string(pcms, cms);
115 else
116 pcms.data = 0;
117 }
118
119 set_param_array(hwra, dev->HWResolution, 2);
120 set_param_array(msa, dev->MediaSize, 2);
121 set_param_array(ibba, dev->ImagingBBox, 4);
122 set_param_array(ma, dev->Margins, 2);
123 set_param_array(scna, NULL, 0);
124
125 /* Fill in non-standard parameters. */
126 HWSize[0] = dev->width;
127 HWSize[1] = dev->height;
128 set_param_array(hwsa, HWSize, 2);
129 set_param_array(hwma, dev->HWMargins, 4);
130 set_param_array(mhwra, dev->MarginsHWResolution, 2);
131 /* Check if the device profile is null. If it is, then we need to
132 go ahead and get it set up at this time. If the proc is not
133 set up yet then we are not going to do anything yet */
134 if (dev->procs.get_profile != NULL) {
135 code = dev_proc(dev, get_profile)(dev, &dev_profile);
136 if (dev_profile == NULL) {
137 code = gsicc_init_device_profile_struct(dev, NULL, 0);
138 code = dev_proc(dev, get_profile)(dev, &dev_profile);
139 }
140 /* It is possible that the current device profile name is NULL if we
141 have a pdf14 device in line with a transparency group that is in a
142 color space specified from a source defined ICC profile. Check for
143 that here to avoid any access violations. Bug 692558 */
144 for (k = 0; k < NUM_DEVICE_PROFILES; k++) {
145 if (dev_profile->device_profile[k] == NULL
146 || dev_profile->device_profile[k]->name == NULL) {
147 param_string_from_string(profile_array[k], null_str);
148 profile_intents[k] = gsPERCEPTUAL;
149 } else {
150 param_string_from_string(profile_array[k],
151 dev_profile->device_profile[k]->name);
152 profile_intents[k] = dev_profile->intent[k];
153 }
154 }
155 /* The proof and link profile */
156 if (dev_profile->proof_profile == NULL) {
157 param_string_from_string(proof_profile, null_str);
158 } else {
159 param_string_from_string(proof_profile,
160 dev_profile->proof_profile->name);
161 }
162 if (dev_profile->link_profile == NULL) {
163 param_string_from_string(link_profile, null_str);
164 } else {
165 param_string_from_string(link_profile,
166 dev_profile->link_profile->name);
167 }
168 devicegraytok = dev_profile->devicegraytok;
169 usefastcolor = dev_profile->usefastcolor;
170 } else {
171 for (k = 0; k < NUM_DEVICE_PROFILES; k++) {
172 param_string_from_string(profile_array[k], null_str);
173 profile_intents[k] = gsPERCEPTUAL;
174 }
175 param_string_from_string(proof_profile, null_str);
176 param_string_from_string(link_profile, null_str);
177 }
178 /* Transmit the values. */
179 if (
180 /* Standard parameters */
181 (code = param_write_name(plist, "OutputDevice", &dns)) < 0 ||
182 #ifdef PAGESIZE_IS_MEDIASIZE
183 (code = param_write_float_array(plist, "PageSize", &msa)) < 0 ||
184 #endif
185 (code = (pcms.data == 0 ? 0 :
186 param_write_name(plist, "ProcessColorModel", &pcms))) < 0 ||
187 (code = param_write_float_array(plist, "HWResolution", &hwra)) < 0 ||
188 (code = (dev->ImagingBBox_set ?
189 param_write_float_array(plist, "ImagingBBox", &ibba) :
190 param_write_null(plist, "ImagingBBox"))) < 0 ||
191 (code = param_write_float_array(plist, "Margins", &ma)) < 0 ||
192 (code = param_write_int(plist, "MaxSeparations", &mns)) < 0 ||
193 (code = (dev->NumCopies_set < 0 ||
194 (*dev_proc(dev, get_page_device))(dev) == 0 ? 0:
195 dev->NumCopies_set ?
196 param_write_int(plist, "NumCopies", &dev->NumCopies) :
197 param_write_null(plist, "NumCopies"))) < 0 ||
198 (code = param_write_name_array(plist, "SeparationColorNames", &scna)) < 0 ||
199 (code = param_write_bool(plist, "Separations", &seprs)) < 0 ||
200 (code = param_write_bool(plist, "UseCIEColor", &dev->UseCIEColor)) < 0 ||
201 /* Non-standard parameters */
202 /* Note: if change is made in NUM_DEVICE_PROFILES we need to name
203 that profile here for the device parameter on the command line */
204 (code = param_write_bool(plist, "DeviceGrayToK", &devicegraytok)) < 0 ||
205 (code = param_write_bool(plist, "UseFastColor", &usefastcolor)) < 0 ||
206 (code = param_write_string(plist,"OutputICCProfile", &(profile_array[0]))) < 0 ||
207 (code = param_write_string(plist,"GraphicICCProfile", &(profile_array[1]))) < 0 ||
208 (code = param_write_string(plist,"ImageICCProfile", &(profile_array[2]))) < 0 ||
209 (code = param_write_string(plist,"TextICCProfile", &(profile_array[3]))) < 0 ||
210 (code = param_write_string(plist,"ProofProfile", &(proof_profile))) < 0 ||
211 (code = param_write_string(plist,"DeviceLinkProfile", &(link_profile))) < 0 ||
212 (code = param_write_int(plist,"RenderIntent", (const int *) (&(profile_intents[0])))) < 0 ||
213 (code = param_write_int(plist,"GraphicIntent", (const int *) &(profile_intents[1]))) < 0 ||
214 (code = param_write_int(plist,"ImageIntent", (const int *) &(profile_intents[2]))) < 0 ||
215 (code = param_write_int(plist,"TextIntent", (const int *) &(profile_intents[3]))) < 0 ||
216 (code = param_write_int_array(plist, "HWSize", &hwsa)) < 0 ||
217 (code = param_write_float_array(plist, ".HWMargins", &hwma)) < 0 ||
218 (code = param_write_float_array(plist, ".MarginsHWResolution", &mhwra)) < 0 ||
219 (code = param_write_float_array(plist, ".MediaSize", &msa)) < 0 ||
220 (code = param_write_string(plist, "Name", &dns)) < 0 ||
221 (code = param_write_int(plist, "Colors", &colors)) < 0 ||
222 (code = param_write_int(plist, "BitsPerPixel", &depth)) < 0 ||
223 (code = param_write_int(plist, "GrayValues", &GrayValues)) < 0 ||
224 (code = param_write_long(plist, "PageCount", &dev->PageCount)) < 0 ||
225 (code = param_write_bool(plist, ".IgnoreNumCopies", &dev->IgnoreNumCopies)) < 0 ||
226 (code = param_write_int(plist, "TextAlphaBits",
227 &dev->color_info.anti_alias.text_bits)) < 0 ||
228 (code = param_write_int(plist, "GraphicsAlphaBits",
229 &dev->color_info.anti_alias.graphics_bits)) < 0 ||
230 (code = param_write_bool(plist, ".LockSafetyParams", &dev->LockSafetyParams)) < 0 ||
231 (code = param_write_int(plist, "MaxPatternBitmap", &dev->MaxPatternBitmap)) < 0
232 )
233 return code;
234
235 /* If LeadingEdge was set explicitly, report it here. */
236 if (dev->LeadingEdge & LEADINGEDGE_SET_MASK) {
237 int leadingedge = dev->LeadingEdge & LEADINGEDGE_MASK;
238 code = param_write_int(plist, "LeadingEdge", &leadingedge);
239 }
240 if (code < 0)
241 return code;
242
243 /* Fill in color information. */
244
245 if (colors > 1) {
246 int RGBValues = dev->color_info.max_color + 1;
247 long ColorValues = (depth >= 32 ? -1 : 1L << depth); /* value can only be 32 bits */
248
249 if ((code = param_write_int(plist, "RedValues", &RGBValues)) < 0 ||
250 (code = param_write_int(plist, "GreenValues", &RGBValues)) < 0 ||
251 (code = param_write_int(plist, "BlueValues", &RGBValues)) < 0 ||
252 (code = param_write_long(plist, "ColorValues", &ColorValues)) < 0
253 )
254 return code;
255 }
256 if (param_requested(plist, "HWColorMap")) {
257 byte palette[3 << 8];
258
259 if (param_HWColorMap(dev, palette)) {
260 gs_param_string hwcms;
261
262 hwcms.data = palette, hwcms.size = colors << depth,
263 hwcms.persistent = false;
264 if ((code = param_write_string(plist, "HWColorMap", &hwcms)) < 0)
265 return code;
266 }
267 }
268
269 return 0;
270 }
271
272 /* Get the color map for a device. Return true if there is one. */
273 static bool
param_HWColorMap(gx_device * dev,byte * palette)274 param_HWColorMap(gx_device * dev, byte * palette /* 3 << 8 */ )
275 {
276 int depth = dev->color_info.depth;
277 int colors = dev->color_info.num_components;
278
279 if (depth <= 8 && colors <= 3) {
280 byte *p = palette;
281 gx_color_value rgb[3];
282 gx_color_index i;
283
284 fill_dev_proc(dev, map_color_rgb, gx_default_map_color_rgb);
285 for (i = 0; (i >> depth) == 0; i++) {
286 int j;
287
288 if ((*dev_proc(dev, map_color_rgb)) (dev, i, rgb) < 0)
289 return false;
290 for (j = 0; j < colors; j++)
291 *p++ = gx_color_value_to_byte(rgb[j]);
292 }
293 return true;
294 }
295 return false;
296 }
297
298 /* Get hardware-detected parameters. Default action is no hardware params. */
299 int
gx_default_get_hardware_params(gx_device * dev,gs_param_list * plist)300 gx_default_get_hardware_params(gx_device * dev, gs_param_list * plist)
301 {
302 return 0;
303 }
304
305 /* ---------------- Input and output media ---------------- */
306
307 /* Finish defining input or output media. */
308 static int
finish_media(gs_param_list * mlist,gs_param_name key,const char * media_type)309 finish_media(gs_param_list * mlist, gs_param_name key, const char *media_type)
310 {
311 int code = 0;
312
313 if (media_type != 0) {
314 gs_param_string as;
315
316 param_string_from_string(as, media_type);
317 code = param_write_string(mlist, key, &as);
318 }
319 return code;
320 }
321
322 /* Define input media. */
323
324 const gdev_input_media_t gdev_input_media_default =
325 {
326 gdev_input_media_default_values
327 };
328
329 int
gdev_begin_input_media(gs_param_list * mlist,gs_param_dict * pdict,int count)330 gdev_begin_input_media(gs_param_list * mlist, gs_param_dict * pdict,
331 int count)
332 {
333 pdict->size = count;
334 return param_begin_write_dict(mlist, "InputAttributes", pdict, true);
335 }
336
337 int
gdev_write_input_media(int index,gs_param_dict * pdict,const gdev_input_media_t * pim)338 gdev_write_input_media(int index, gs_param_dict * pdict,
339 const gdev_input_media_t * pim)
340 {
341 char key[25];
342 gs_param_dict mdict;
343 int code;
344 gs_param_string as;
345
346 sprintf(key, "%d", index);
347 mdict.size = 4;
348 code = param_begin_write_dict(pdict->list, key, &mdict, false);
349 if (code < 0)
350 return code;
351 if ((pim->PageSize[0] != 0 && pim->PageSize[1] != 0) ||
352 (pim->PageSize[2] != 0 && pim->PageSize[3] != 0)
353 ) {
354 gs_param_float_array psa;
355
356 psa.data = pim->PageSize;
357 psa.size =
358 (pim->PageSize[0] == pim->PageSize[2] &&
359 pim->PageSize[1] == pim->PageSize[3] ? 2 : 4);
360 psa.persistent = false;
361 code = param_write_float_array(mdict.list, "PageSize",
362 &psa);
363 if (code < 0)
364 return code;
365 }
366 if (pim->MediaColor != 0) {
367 param_string_from_string(as, pim->MediaColor);
368 code = param_write_string(mdict.list, "MediaColor",
369 &as);
370 if (code < 0)
371 return code;
372 }
373 if (pim->MediaWeight != 0) {
374 /*
375 * We do the following silly thing in order to avoid
376 * having to work around the 'const' in the arg list.
377 */
378 float weight = pim->MediaWeight;
379
380 code = param_write_float(mdict.list, "MediaWeight",
381 &weight);
382 if (code < 0)
383 return code;
384 }
385 code = finish_media(mdict.list, "MediaType", pim->MediaType);
386 if (code < 0)
387 return code;
388 return param_end_write_dict(pdict->list, key, &mdict);
389 }
390
391 int
gdev_write_input_page_size(int index,gs_param_dict * pdict,floatp width_points,floatp height_points)392 gdev_write_input_page_size(int index, gs_param_dict * pdict,
393 floatp width_points, floatp height_points)
394 {
395 gdev_input_media_t media;
396
397 media.PageSize[0] = media.PageSize[2] = (float) width_points;
398 media.PageSize[1] = media.PageSize[3] = (float) height_points;
399 media.MediaColor = 0;
400 media.MediaWeight = 0;
401 media.MediaType = 0;
402 return gdev_write_input_media(index, pdict, &media);
403 }
404
405 int
gdev_end_input_media(gs_param_list * mlist,gs_param_dict * pdict)406 gdev_end_input_media(gs_param_list * mlist, gs_param_dict * pdict)
407 {
408 return param_end_write_dict(mlist, "InputAttributes", pdict);
409 }
410
411 /* Define output media. */
412
413 const gdev_output_media_t gdev_output_media_default =
414 {
415 gdev_output_media_default_values
416 };
417
418 int
gdev_begin_output_media(gs_param_list * mlist,gs_param_dict * pdict,int count)419 gdev_begin_output_media(gs_param_list * mlist, gs_param_dict * pdict,
420 int count)
421 {
422 pdict->size = count;
423 return param_begin_write_dict(mlist, "OutputAttributes", pdict, true);
424 }
425
426 int
gdev_write_output_media(int index,gs_param_dict * pdict,const gdev_output_media_t * pom)427 gdev_write_output_media(int index, gs_param_dict * pdict,
428 const gdev_output_media_t * pom)
429 {
430 char key[25];
431 gs_param_dict mdict;
432 int code;
433
434 sprintf(key, "%d", index);
435 mdict.size = 4;
436 code = param_begin_write_dict(pdict->list, key, &mdict, false);
437 if (code < 0)
438 return code;
439 code = finish_media(mdict.list, "OutputType", pom->OutputType);
440 if (code < 0)
441 return code;
442 return param_end_write_dict(pdict->list, key, &mdict);
443 }
444
445 int
gdev_end_output_media(gs_param_list * mlist,gs_param_dict * pdict)446 gdev_end_output_media(gs_param_list * mlist, gs_param_dict * pdict)
447 {
448 return param_end_write_dict(mlist, "OutputAttributes", pdict);
449 }
450
451 /* ================ Putting parameters ================ */
452
453 /* Forward references */
454 static int param_normalize_anti_alias_bits( uint max_gray, int bits );
455 static int param_anti_alias_bits(gs_param_list *, gs_param_name, int *);
456 static int param_MediaSize(gs_param_list *, gs_param_name,
457 const float *, gs_param_float_array *);
458
459 static int param_check_bool(gs_param_list *, gs_param_name, bool, bool);
460 static int param_check_long(gs_param_list *, gs_param_name, long, bool);
461 #define param_check_int(plist, pname, ival, is_defined)\
462 param_check_long(plist, pname, (long)(ival), is_defined)
463 static int param_check_bytes(gs_param_list *, gs_param_name, const byte *,
464 uint, bool);
465 #define param_check_string(plist, pname, str, is_defined)\
466 param_check_bytes(plist, pname, (const byte *)(str), \
467 (is_defined) ? strlen(str) : 0, is_defined)
468
469 /* Set the device parameters. */
470 /* If the device was open and the put_params procedure closed it, */
471 /* return 1; otherwise, return 0 or an error code as usual. */
472 int
gs_putdeviceparams(gx_device * dev,gs_param_list * plist)473 gs_putdeviceparams(gx_device * dev, gs_param_list * plist)
474 {
475 bool was_open = dev->is_open;
476 int code;
477
478 gx_device_set_procs(dev);
479 fill_dev_proc(dev, put_params, gx_default_put_params);
480 fill_dev_proc(dev, get_alpha_bits, gx_default_get_alpha_bits);
481 code = (*dev_proc(dev, put_params)) (dev, plist);
482 return (code < 0 ? code : was_open && !dev->is_open ? 1 : code);
483 }
484
485 static void
gx_default_put_graytok(bool graytok,gx_device * dev)486 gx_default_put_graytok(bool graytok, gx_device * dev)
487 {
488 int code;
489 cmm_dev_profile_t *profile_struct;
490
491 if (dev->procs.get_profile == NULL) {
492 /* This is an odd case where the device has not yet fully been
493 set up with its procedures yet. We want to make sure that
494 we catch this so we assume here that we are dealing with
495 the target device. For now allocate the profile structure
496 but do not intialize the profile yet as the color info
497 may not be fully set up at this time. */
498 if (dev->icc_struct == NULL) {
499 /* Allocate at this time the structure */
500 dev->icc_struct = gsicc_new_device_profile_array(dev->memory);
501 }
502 dev->icc_struct->devicegraytok = graytok;
503 } else {
504 code = dev_proc(dev, get_profile)(dev, &profile_struct);
505 if (profile_struct == NULL) {
506 /* Create now */
507 dev->icc_struct = gsicc_new_device_profile_array(dev->memory);
508 profile_struct = dev->icc_struct;
509 }
510 profile_struct->devicegraytok = graytok;
511 }
512 }
513
514 static void
gx_default_put_usefastcolor(bool fastcolor,gx_device * dev)515 gx_default_put_usefastcolor(bool fastcolor, gx_device * dev)
516 {
517 int code;
518 cmm_dev_profile_t *profile_struct;
519
520 if (dev->procs.get_profile == NULL) {
521 /* This is an odd case where the device has not yet fully been
522 set up with its procedures yet. We want to make sure that
523 we catch this so we assume here that we are dealing with
524 the target device. For now allocate the profile structure
525 but do not intialize the profile yet as the color info
526 may not be fully set up at this time. */
527 if (dev->icc_struct == NULL) {
528 /* Allocate at this time the structure */
529 dev->icc_struct = gsicc_new_device_profile_array(dev->memory);
530 }
531 dev->icc_struct->usefastcolor = fastcolor;
532 } else {
533 code = dev_proc(dev, get_profile)(dev, &profile_struct);
534 if (profile_struct == NULL) {
535 /* Create now */
536 dev->icc_struct = gsicc_new_device_profile_array(dev->memory);
537 profile_struct = dev->icc_struct;
538 }
539 profile_struct->usefastcolor = fastcolor;
540 }
541 }
542
543
544 static void
gx_default_put_intent(gsicc_profile_types_t icc_intent,gx_device * dev,gsicc_profile_types_t index)545 gx_default_put_intent(gsicc_profile_types_t icc_intent, gx_device * dev,
546 gsicc_profile_types_t index)
547 {
548 int code;
549 cmm_dev_profile_t *profile_struct;
550
551 if (dev->procs.get_profile == NULL) {
552 /* This is an odd case where the device has not yet fully been
553 set up with its procedures yet. We want to make sure that
554 we catch this so we assume here that we are dealing with
555 the target device */
556 if (dev->icc_struct == NULL) {
557 /* Intializes the device structure. Not the profile though for index */
558 dev->icc_struct = gsicc_new_device_profile_array(dev->memory);
559 }
560 code = gsicc_set_device_profile_intent(dev, icc_intent, index);
561 } else {
562 code = dev_proc(dev, get_profile)(dev, &profile_struct);
563 if (profile_struct == NULL) {
564 /* Create now */
565 dev->icc_struct = gsicc_new_device_profile_array(dev->memory);
566 }
567 code = gsicc_set_device_profile_intent(dev, icc_intent, index);
568 }
569 }
570
571 static void
gx_default_put_icc(gs_param_string * icc_pro,gx_device * dev,gsicc_profile_types_t index)572 gx_default_put_icc(gs_param_string *icc_pro, gx_device * dev,
573 gsicc_profile_types_t index)
574 {
575 char *tempstr;
576 int code;
577
578 if (icc_pro->size == 0) return;
579 /* If this has not yet been set, then set it to the default.
580 I don't like doing this here but if we are in here trying to
581 set a profile for our device and if the proc for this has not
582 yet been set, we are going to lose the chance to set the profile.
583 Much like open, this proc should be set early on. I leave that
584 exercise to the device start-up experts */
585 fill_dev_proc(dev, get_profile, gx_default_get_profile);
586 if (icc_pro->size < gp_file_name_sizeof) {
587 tempstr = (char *) gs_alloc_bytes(dev->memory, icc_pro->size+1,
588 "gx_default_put_icc");
589 memcpy(tempstr, icc_pro->data, icc_pro->size);
590 /* Set last position to NULL. */
591 tempstr[icc_pro->size] = 0;
592 code = gsicc_init_device_profile_struct(dev, tempstr, index);
593 gs_free_object(dev->memory, tempstr, "gx_default_put_icc");
594 }
595 }
596
597 /* Set standard parameters. */
598 /* Note that setting the size or resolution closes the device. */
599 /* Window devices that don't want this to happen must temporarily */
600 /* set is_open to false before calling gx_default_put_params, */
601 /* and then taking appropriate action afterwards. */
602 int
gx_default_put_params(gx_device * dev,gs_param_list * plist)603 gx_default_put_params(gx_device * dev, gs_param_list * plist)
604 {
605 int ecode = 0;
606 int code;
607 gs_param_name param_name;
608 gs_param_float_array hwra;
609 gs_param_int_array hwsa;
610 gs_param_float_array msa;
611 gs_param_float_array ma;
612 gs_param_float_array hwma;
613 gs_param_float_array mhwra;
614 gs_param_string_array scna;
615 int nci = dev->NumCopies;
616 int ncset = dev->NumCopies_set;
617 bool ignc = dev->IgnoreNumCopies;
618 bool ucc = dev->UseCIEColor;
619 gs_param_string icc_pro;
620 bool locksafe = dev->LockSafetyParams;
621 gs_param_float_array ibba;
622 bool ibbnull = false;
623 int colors = dev->color_info.num_components;
624 int depth = dev->color_info.depth;
625 int GrayValues = dev->color_info.max_gray + 1;
626 int RGBValues = dev->color_info.max_color + 1;
627 long ColorValues = (depth >= 32 ? -1 : 1L << depth);
628 int tab = dev->color_info.anti_alias.text_bits;
629 int gab = dev->color_info.anti_alias.graphics_bits;
630 int mpbm = dev->MaxPatternBitmap;
631 int rend_intent[NUM_DEVICE_PROFILES];
632 gs_param_string cms;
633 int leadingedge = dev->LeadingEdge;
634 int k;
635 bool devicegraytok = true;
636 bool usefastcolor = false;
637
638 if (dev->icc_struct != NULL) {
639 for (k = 0; k < NUM_DEVICE_PROFILES; k++) {
640 rend_intent[k] = dev->icc_struct->intent[k];
641 }
642 devicegraytok = dev->icc_struct->devicegraytok;
643 usefastcolor = dev->icc_struct->usefastcolor;
644 } else {
645 for (k = 0; k < NUM_DEVICE_PROFILES; k++) {
646 rend_intent[k] = gsPERCEPTUAL;
647 }
648 }
649
650 /*
651 * Template:
652 * BEGIN_ARRAY_PARAM(param_read_xxx_array, "pname", pxxa, size, pxxe) {
653 * ... check value if desired ...
654 * if (success)
655 * break;
656 * ... set ecode ...
657 * } END_ARRAY_PARAM(pxxa, pxxe);
658 */
659
660 #define BEGIN_ARRAY_PARAM(pread, pname, pa, psize, e)\
661 BEGIN\
662 switch (code = pread(plist, (param_name = pname), &(pa))) {\
663 case 0:\
664 if ((pa).size != psize) {\
665 ecode = gs_note_error(gs_error_rangecheck);\
666 (pa).data = 0; /* mark as not filled */\
667 } else
668 #define END_ARRAY_PARAM(pa, e)\
669 goto e;\
670 default:\
671 ecode = code;\
672 e: param_signal_error(plist, param_name, ecode);\
673 case 1:\
674 (pa).data = 0; /* mark as not filled */\
675 }\
676 END
677
678 /*
679 * The actual value of LeadingEdge must be changed inside this routine,
680 * so that we can detect that it has been changed. Thus, instead of a
681 * device setting the value itself, it signals a request, which is
682 * now executed.
683 */
684 if (leadingedge & LEADINGEDGE_REQ_BIT) {
685 leadingedge = (leadingedge & LEADINGEDGE_SET_MASK) |
686 ((leadingedge >> LEADINGEDGE_REQ_VAL_SHIFT) & LEADINGEDGE_MASK);
687 }
688
689 /*
690 * The HWResolution, HWSize, and MediaSize parameters interact in
691 * the following way:
692 * 1. Setting HWResolution recomputes HWSize from MediaSize.
693 * 2. Setting HWSize recomputes MediaSize from HWResolution.
694 * 3. Setting MediaSize recomputes HWSize from HWResolution.
695 * If more than one parameter is being set, we apply these rules
696 * in the order 1, 2, 3. This does the right thing in the most
697 * common case of setting more than one parameter, namely,
698 * setting both HWResolution and HWSize.
699 *
700 * Changing of LeadingEdge is treated exactly the same as a
701 * change in HWResolution. In typical usage, MediaSize is
702 * short-edge (MediaSize[0] < MediaSize[1]), so if LeadingEdge
703 * is 1 or 3, then HWSize will become long-edge. For nonsquare
704 * resolutions, HWResolution[0] always corresponds with width
705 * (scan length), and [1] with height (number of scans).
706 */
707
708 BEGIN_ARRAY_PARAM(param_read_float_array, "HWResolution", hwra, 2, hwre) {
709 if (hwra.data[0] <= 0 || hwra.data[1] <= 0)
710 ecode = gs_note_error(gs_error_rangecheck);
711 else
712 break;
713 } END_ARRAY_PARAM(hwra, hwre);
714 BEGIN_ARRAY_PARAM(param_read_int_array, "HWSize", hwsa, 2, hwsa) {
715 /* We need a special check to handle the nullpage device, */
716 /* whose size is legitimately [0 0]. */
717 if ((hwsa.data[0] <= 0 && hwsa.data[0] != dev->width) ||
718 (hwsa.data[1] <= 0 && hwsa.data[1] != dev->height)
719 )
720 ecode = gs_note_error(gs_error_rangecheck);
721 #define max_coord (max_fixed / fixed_1)
722 #if max_coord < max_int
723 else if (hwsa.data[0] > max_coord || hwsa.data[1] > max_coord)
724 ecode = gs_note_error(gs_error_limitcheck);
725 #endif
726 #undef max_coord
727 else
728 break;
729 } END_ARRAY_PARAM(hwsa, hwse);
730 {
731 int t;
732
733 code = param_read_int(plist, "LeadingEdge", &t);
734 if (code < 0) {
735 if (param_read_null(plist, "LeadingEdge") == 0) {
736 /* if param is null, clear explicitly-set flag */
737 leadingedge &= ~LEADINGEDGE_SET_MASK;
738 code = 0;
739 } else {
740 ecode = code;
741 }
742 } else if (code == 0) {
743 if (t < 0 || t > 3)
744 param_signal_error(plist, "LeadingEdge",
745 ecode = gs_error_rangecheck);
746 else
747 leadingedge = LEADINGEDGE_SET_MASK | t;
748 }
749 }
750 {
751 const float *res = (hwra.data == 0 ? dev->HWResolution : hwra.data);
752
753 #ifdef PAGESIZE_IS_MEDIASIZE
754 const float *data;
755
756 /* .MediaSize takes precedence over PageSize, so */
757 /* we read PageSize first. */
758 code = param_MediaSize(plist, "PageSize", res, &msa);
759 if (code < 0)
760 ecode = code;
761 /* Prevent data from being set to 0 if PageSize is specified */
762 /* but .MediaSize is not. */
763 data = msa.data;
764 code = param_MediaSize(plist, ".MediaSize", res, &msa);
765 if (code < 0)
766 ecode = code;
767 else if (msa.data == 0)
768 msa.data = data;
769 #else
770 code = param_MediaSize(plist, ".MediaSize", res, &msa);
771 if (code < 0)
772 ecode = code;
773 #endif
774 }
775
776 BEGIN_ARRAY_PARAM(param_read_float_array, "Margins", ma, 2, me) {
777 break;
778 } END_ARRAY_PARAM(ma, me);
779 BEGIN_ARRAY_PARAM(param_read_float_array, ".HWMargins", hwma, 4, hwme) {
780 break;
781 } END_ARRAY_PARAM(hwma, hwme);
782 /* MarginsHWResolution cannot be changed, only checked. */
783 BEGIN_ARRAY_PARAM(param_read_float_array, ".MarginsHWResolution", mhwra, 2, mhwre) {
784 if (mhwra.data[0] != dev->MarginsHWResolution[0] ||
785 mhwra.data[1] != dev->MarginsHWResolution[1]
786 )
787 ecode = gs_note_error(gs_error_rangecheck);
788 else
789 break;
790 } END_ARRAY_PARAM(mhwra, mhwre);
791 switch (code = param_read_bool(plist, (param_name = ".IgnoreNumCopies"), &ignc)) {
792 default:
793 ecode = code;
794 param_signal_error(plist, param_name, ecode);
795 case 0:
796 case 1:
797 break;
798 }
799 if (dev->NumCopies_set >= 0 &&
800 (*dev_proc(dev, get_page_device))(dev) != 0
801 ) {
802 switch (code = param_read_int(plist, (param_name = "NumCopies"), &nci)) {
803 case 0:
804 if (nci < 0)
805 ecode = gs_error_rangecheck;
806 else {
807 ncset = 1;
808 break;
809 }
810 goto nce;
811 default:
812 if ((code = param_read_null(plist, param_name)) == 0) {
813 ncset = 0;
814 break;
815 }
816 ecode = code; /* can't be 1 */
817 nce:
818 param_signal_error(plist, param_name, ecode);
819 case 1:
820 break;
821 }
822 }
823 /* Set the directory first */
824 if ((code = param_read_string(plist, "OutputICCProfile", &icc_pro)) != 1) {
825 gx_default_put_icc(&icc_pro, dev, gsDEFAULTPROFILE);
826 }
827 /* Note, if a change is made to NUM_DEVICE_PROFILES we need to update
828 this with the name of the profile */
829 if ((code = param_read_string(plist, "GraphicICCProfile", &icc_pro)) != 1) {
830 gx_default_put_icc(&icc_pro, dev, gsGRAPHICPROFILE);
831 }
832 if ((code = param_read_string(plist, "ImageICCProfile", &icc_pro)) != 1) {
833 gx_default_put_icc(&icc_pro, dev, gsIMAGEPROFILE);
834 }
835 if ((code = param_read_string(plist, "TextICCProfile", &icc_pro)) != 1) {
836 gx_default_put_icc(&icc_pro, dev, gsTEXTPROFILE);
837 }
838 if ((code = param_read_string(plist, "ProofProfile", &icc_pro)) != 1) {
839 gx_default_put_icc(&icc_pro, dev, gsPROOFPROFILE);
840 }
841 if ((code = param_read_string(plist, "DeviceLinkProfile", &icc_pro)) != 1) {
842 gx_default_put_icc(&icc_pro, dev, gsLINKPROFILE);
843 }
844 if ((code = param_read_int(plist, (param_name = "RenderIntent"),
845 &(rend_intent[0]))) < 0) {
846 ecode = code;
847 param_signal_error(plist, param_name, ecode);
848 }
849 if ((code = param_read_int(plist, (param_name = "GraphicIntent"),
850 &(rend_intent[1]))) < 0) {
851 ecode = code;
852 param_signal_error(plist, param_name, ecode);
853 }
854 if ((code = param_read_int(plist, (param_name = "ImageIntent"),
855 &(rend_intent[2]))) < 0) {
856 ecode = code;
857 param_signal_error(plist, param_name, ecode);
858 }
859 if ((code = param_read_int(plist, (param_name = "TextIntent"),
860 &(rend_intent[3]))) < 0) {
861 ecode = code;
862 param_signal_error(plist, param_name, ecode);
863 }
864 if ((code = param_read_bool(plist, (param_name = "DeviceGrayToK"),
865 &devicegraytok)) < 0) {
866 ecode = code;
867 param_signal_error(plist, param_name, ecode);
868 }
869 if ((code = param_read_bool(plist, (param_name = "UseFastColor"),
870 &usefastcolor)) < 0) {
871 ecode = code;
872 param_signal_error(plist, param_name, ecode);
873 }
874 if ((code = param_read_bool(plist, (param_name = "UseCIEColor"), &ucc)) < 0) {
875 ecode = code;
876 param_signal_error(plist, param_name, ecode);
877 }
878 if ((code = param_anti_alias_bits(plist, "TextAlphaBits", &tab)) < 0)
879 ecode = code;
880 if ((code = param_anti_alias_bits(plist, "GraphicsAlphaBits", &gab)) < 0)
881 ecode = code;
882 if ((code = param_read_int(plist, "MaxPatternBitmap", &mpbm)) < 0)
883 ecode = code;
884
885 switch (code = param_read_bool(plist, (param_name = ".LockSafetyParams"), &locksafe)) {
886 case 0:
887 if (dev->LockSafetyParams && !locksafe)
888 code = gs_note_error(gs_error_invalidaccess);
889 else
890 break;
891 default:
892 ecode = code;
893 param_signal_error(plist, param_name, ecode);
894 case 1:
895 break;
896 }
897 /* Ignore parameters that only have meaning for printers. */
898 #define IGNORE_INT_PARAM(pname)\
899 { int igni;\
900 switch ( code = param_read_int(plist, (param_name = pname), &igni) )\
901 { default:\
902 ecode = code;\
903 param_signal_error(plist, param_name, ecode);\
904 case 0:\
905 case 1:\
906 break;\
907 }\
908 }
909 IGNORE_INT_PARAM("%MediaSource")
910 IGNORE_INT_PARAM("%MediaDestination")
911 switch (code = param_read_float_array(plist, (param_name = "ImagingBBox"), &ibba)) {
912 case 0:
913 if (ibba.size != 4 ||
914 ibba.data[2] < ibba.data[0] || ibba.data[3] < ibba.data[1]
915 )
916 ecode = gs_note_error(gs_error_rangecheck);
917 else
918 break;
919 goto ibbe;
920 default:
921 if ((code = param_read_null(plist, param_name)) == 0) {
922 ibbnull = true;
923 ibba.data = 0;
924 break;
925 }
926 ecode = code; /* can't be 1 */
927 ibbe:param_signal_error(plist, param_name, ecode);
928 case 1:
929 ibba.data = 0;
930 break;
931 }
932
933 /* Separation, DeviceN Color, and ProcessColorModel related parameters. */
934 {
935 const char * pcms = get_process_color_model_name(dev);
936 /* the device should have set a process model name at this point */
937 if ((code = param_check_string(plist, "ProcessColorModel", pcms, (pcms != NULL))) < 0)
938 ecode = code;
939 }
940 IGNORE_INT_PARAM("MaxSeparations")
941 if ((code = param_check_bool(plist, "Separations", false, true)) < 0)
942 ecode = code;
943
944 BEGIN_ARRAY_PARAM(param_read_name_array, "SeparationColorNames", scna, scna.size, scne) {
945 break;
946 } END_ARRAY_PARAM(scna, scne);
947
948 /* Now check nominally read-only parameters. */
949 if ((code = param_check_string(plist, "OutputDevice", dev->dname, true)) < 0)
950 ecode = code;
951 if ((code = param_check_string(plist, "Name", dev->dname, true)) < 0)
952 ecode = code;
953 if ((code = param_check_int(plist, "Colors", colors, true)) < 0)
954 ecode = code;
955 if ((code = param_check_int(plist, "BitsPerPixel", depth, true)) < 0)
956 ecode = code;
957 if ((code = param_check_int(plist, "GrayValues", GrayValues, true)) < 0)
958 ecode = code;
959 if ((code = param_check_long(plist, "PageCount", dev->PageCount, true)) < 0)
960 ecode = code;
961 if ((code = param_check_int(plist, "RedValues", RGBValues, true)) < 0)
962 ecode = code;
963 if ((code = param_check_int(plist, "GreenValues", RGBValues, true)) < 0)
964 ecode = code;
965 if ((code = param_check_int(plist, "BlueValues", RGBValues, true)) < 0)
966 ecode = code;
967 if ((code = param_check_long(plist, "ColorValues", ColorValues, true)) < 0)
968 ecode = code;
969 if (param_read_string(plist, "HWColorMap", &cms) != 1) {
970 byte palette[3 << 8];
971
972 if (param_HWColorMap(dev, palette))
973 code = param_check_bytes(plist, "HWColorMap", palette,
974 colors << depth, true);
975 else
976 code = param_check_bytes(plist, "HWColorMap", 0, 0, false);
977 if (code < 0)
978 ecode = code;
979 }
980
981 /* We must 'commit', in order to detect unknown parameters, */
982 /* even if there were errors. */
983 code = param_commit(plist);
984 if (ecode < 0)
985 return ecode;
986 if (code < 0)
987 return code;
988
989 /*
990 * Now actually make the changes. Changing resolution, rotation
991 * (through LeadingEdge) or page size requires closing the device,
992 * but changing margins or ImagingBBox does not. In order not to
993 * close and reopen the device unnecessarily, we check for
994 * replacing the values with the same ones.
995 */
996
997 if (hwra.data != 0 &&
998 (dev->HWResolution[0] != hwra.data[0] ||
999 dev->HWResolution[1] != hwra.data[1])
1000 ) {
1001 if (dev->is_open)
1002 gs_closedevice(dev);
1003 gx_device_set_resolution(dev, hwra.data[0], hwra.data[1]);
1004 }
1005 if ((leadingedge & LEADINGEDGE_MASK) !=
1006 (dev->LeadingEdge & LEADINGEDGE_MASK)) {
1007 /* If the LeadingEdge_set flag changes but the value of LeadingEdge
1008 itself does not, don't close device and recompute page size. */
1009 dev->LeadingEdge = leadingedge;
1010 if (dev->is_open)
1011 gs_closedevice(dev);
1012 gx_device_set_resolution(dev, dev->HWResolution[0], dev->HWResolution[1]);
1013 }
1014 /* clear leadingedge request, preserve "set" flag */
1015 dev->LeadingEdge &= LEADINGEDGE_MASK;
1016 dev->LeadingEdge |= (leadingedge & LEADINGEDGE_SET_MASK);
1017
1018 if (hwsa.data != 0 &&
1019 (dev->width != hwsa.data[0] ||
1020 dev->height != hwsa.data[1])
1021 ) {
1022 if (dev->is_open)
1023 gs_closedevice(dev);
1024 gx_device_set_width_height(dev, hwsa.data[0], hwsa.data[1]);
1025 }
1026 if (msa.data != 0 &&
1027 (dev->MediaSize[0] != msa.data[0] ||
1028 dev->MediaSize[1] != msa.data[1])
1029 ) {
1030 if (dev->is_open)
1031 gs_closedevice(dev);
1032 gx_device_set_page_size(dev, msa.data[0], msa.data[1]);
1033 }
1034 if (ma.data != 0) {
1035 dev->Margins[0] = ma.data[0];
1036 dev->Margins[1] = ma.data[1];
1037 }
1038 if (hwma.data != 0) {
1039 dev->HWMargins[0] = hwma.data[0];
1040 dev->HWMargins[1] = hwma.data[1];
1041 dev->HWMargins[2] = hwma.data[2];
1042 dev->HWMargins[3] = hwma.data[3];
1043 }
1044 dev->NumCopies = nci;
1045 dev->NumCopies_set = ncset;
1046 dev->IgnoreNumCopies = ignc;
1047 if (ibba.data != 0) {
1048 dev->ImagingBBox[0] = ibba.data[0];
1049 dev->ImagingBBox[1] = ibba.data[1];
1050 dev->ImagingBBox[2] = ibba.data[2];
1051 dev->ImagingBBox[3] = ibba.data[3];
1052 dev->ImagingBBox_set = true;
1053 } else if (ibbnull) {
1054 dev->ImagingBBox_set = false;
1055 }
1056 dev->UseCIEColor = ucc;
1057 dev->color_info.anti_alias.text_bits =
1058 param_normalize_anti_alias_bits(max(dev->color_info.max_gray,
1059 dev->color_info.max_color), tab);
1060 dev->color_info.anti_alias.graphics_bits =
1061 param_normalize_anti_alias_bits(max(dev->color_info.max_gray,
1062 dev->color_info.max_color), gab);
1063 dev->LockSafetyParams = locksafe;
1064 dev->MaxPatternBitmap = mpbm;
1065 gx_device_decache_colors(dev);
1066
1067 /* Take care of the rendering intents */
1068 if (dev->icc_struct != NULL) {
1069 gx_default_put_intent(rend_intent[0], dev, gsDEFAULTPROFILE);
1070 gx_default_put_intent(rend_intent[1], dev, gsGRAPHICPROFILE);
1071 gx_default_put_intent(rend_intent[2], dev, gsIMAGEPROFILE);
1072 gx_default_put_intent(rend_intent[3], dev, gsTEXTPROFILE);
1073 }
1074 gx_default_put_graytok(devicegraytok, dev);
1075 gx_default_put_usefastcolor(usefastcolor, dev);
1076 return 0;
1077 }
1078
1079 void
gx_device_request_leadingedge(gx_device * dev,int le_req)1080 gx_device_request_leadingedge(gx_device *dev, int le_req)
1081 {
1082 dev->LeadingEdge = (dev->LeadingEdge & ~LEADINGEDGE_REQ_VAL) |
1083 ((le_req << LEADINGEDGE_REQ_VAL_SHIFT) & LEADINGEDGE_REQ_VAL) |
1084 LEADINGEDGE_REQ_BIT;
1085 }
1086
1087 /* Limit the anti-alias bit values to the maximum legal value for the
1088 * current color depth.
1089 */
1090 static int
param_normalize_anti_alias_bits(uint max_gray,int bits)1091 param_normalize_anti_alias_bits( uint max_gray, int bits )
1092 {
1093 int max_bits = ilog2( max_gray + 1);
1094
1095 return (bits > max_bits ? max_bits : bits);
1096 }
1097
1098 /* Read TextAlphaBits or GraphicsAlphaBits. */
1099 static int
param_anti_alias_bits(gs_param_list * plist,gs_param_name param_name,int * pa)1100 param_anti_alias_bits(gs_param_list * plist, gs_param_name param_name, int *pa)
1101 {
1102 int code = param_read_int(plist, param_name, pa);
1103
1104 switch (code) {
1105 case 0:
1106 switch (*pa) {
1107 case 1: case 2: case 4:
1108 return 0;
1109 default:
1110 code = gs_error_rangecheck;
1111 }
1112 default:
1113 param_signal_error(plist, param_name, code);
1114 case 1:
1115 ;
1116 }
1117 return code;
1118 }
1119
1120 /* Read .MediaSize or, if supported as a synonym, PageSize. */
1121 static int
param_MediaSize(gs_param_list * plist,gs_param_name pname,const float * res,gs_param_float_array * pa)1122 param_MediaSize(gs_param_list * plist, gs_param_name pname,
1123 const float *res, gs_param_float_array * pa)
1124 {
1125 gs_param_name param_name;
1126 int ecode = 0;
1127 int code;
1128
1129 BEGIN_ARRAY_PARAM(param_read_float_array, pname, *pa, 2, mse) {
1130 float width_new = pa->data[0] * res[0] / 72;
1131 float height_new = pa->data[1] * res[1] / 72;
1132
1133 if (width_new < 0 || height_new < 0)
1134 ecode = gs_note_error(gs_error_rangecheck);
1135 #define max_coord (max_fixed / fixed_1)
1136 #if max_coord < max_int
1137 else if (width_new > max_coord || height_new > max_coord)
1138 ecode = gs_note_error(gs_error_limitcheck);
1139 #endif
1140 #undef max_coord
1141 else
1142 break;
1143 } END_ARRAY_PARAM(*pa, mse);
1144 return ecode;
1145 }
1146
1147 /* Check that a nominally read-only parameter is being set to */
1148 /* its existing value. */
1149 static int
param_check_bool(gs_param_list * plist,gs_param_name pname,bool value,bool is_defined)1150 param_check_bool(gs_param_list * plist, gs_param_name pname, bool value,
1151 bool is_defined)
1152 {
1153 int code;
1154 bool new_value;
1155
1156 switch (code = param_read_bool(plist, pname, &new_value)) {
1157 case 0:
1158 if (is_defined && new_value == value)
1159 break;
1160 code = gs_note_error(gs_error_rangecheck);
1161 goto e;
1162 default:
1163 if (param_read_null(plist, pname) == 0)
1164 return 1;
1165 e:param_signal_error(plist, pname, code);
1166 case 1:
1167 ;
1168 }
1169 return code;
1170 }
1171 static int
param_check_long(gs_param_list * plist,gs_param_name pname,long value,bool is_defined)1172 param_check_long(gs_param_list * plist, gs_param_name pname, long value,
1173 bool is_defined)
1174 {
1175 int code;
1176 long new_value;
1177
1178 switch (code = param_read_long(plist, pname, &new_value)) {
1179 case 0:
1180 if (is_defined && new_value == value)
1181 break;
1182 code = gs_note_error(gs_error_rangecheck);
1183 goto e;
1184 default:
1185 if (param_read_null(plist, pname) == 0)
1186 return 1;
1187 e:param_signal_error(plist, pname, code);
1188 case 1:
1189 ;
1190 }
1191 return code;
1192 }
1193 static int
param_check_bytes(gs_param_list * plist,gs_param_name pname,const byte * str,uint size,bool is_defined)1194 param_check_bytes(gs_param_list * plist, gs_param_name pname, const byte * str,
1195 uint size, bool is_defined)
1196 {
1197 int code;
1198 gs_param_string new_value;
1199
1200 switch (code = param_read_string(plist, pname, &new_value)) {
1201 case 0:
1202 if (is_defined && new_value.size == size &&
1203 !memcmp((const char *)str, (const char *)new_value.data,
1204 size)
1205 )
1206 break;
1207 code = gs_note_error(gs_error_rangecheck);
1208 goto e;
1209 default:
1210 if (param_read_null(plist, pname) == 0)
1211 return 1;
1212 e:param_signal_error(plist, pname, code);
1213 case 1:
1214 ;
1215 }
1216 return code;
1217 }
1218