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