1 /* Copyright (C) 1993, 2000 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: gsdparam.c,v 1.18 2005/06/20 08:59:23 igor Exp $ */
18 /* Default device parameters for Ghostscript library */
19 #include "memory_.h" /* for memcpy */
20 #include "string_.h" /* for strlen */
21 #include "gx.h"
22 #include "gserrors.h"
23 #include "gsdevice.h" /* for prototypes */
24 #include "gsparam.h"
25 #include "gxdevice.h"
26 #include "gxfixed.h"
27
28 /* Define whether we accept PageSize as a synonym for MediaSize. */
29 /* This is for backward compatibility only. */
30 #define PAGESIZE_IS_MEDIASIZE
31
32 /* ================ Getting parameters ================ */
33
34 /* Forward references */
35 private bool param_HWColorMap(gx_device *, byte *);
36
37 /* Get the device parameters. */
38 int
gs_get_device_or_hw_params(gx_device * orig_dev,gs_param_list * plist,bool is_hardware)39 gs_get_device_or_hw_params(gx_device * orig_dev, gs_param_list * plist,
40 bool is_hardware)
41 {
42 /*
43 * We must be prepared to copy the device if it is the read-only
44 * prototype.
45 */
46 gx_device *dev;
47 int code;
48
49 if (orig_dev->memory)
50 dev = orig_dev;
51 else {
52 code = gs_copydevice(&dev, orig_dev, plist->memory);
53 if (code < 0)
54 return code;
55 }
56 gx_device_set_procs(dev);
57 fill_dev_proc(dev, get_params, gx_default_get_params);
58 fill_dev_proc(dev, get_page_device, gx_default_get_page_device);
59 fill_dev_proc(dev, get_alpha_bits, gx_default_get_alpha_bits);
60 code = (is_hardware ?
61 (*dev_proc(dev, get_hardware_params)) (dev, plist) :
62 (*dev_proc(dev, get_params)) (dev, plist));
63 if (dev != orig_dev)
64 gx_device_retain(dev, false); /* frees the copy */
65 return code;
66 }
67
68 /* Get standard parameters. */
69 int
gx_default_get_params(gx_device * dev,gs_param_list * plist)70 gx_default_get_params(gx_device * dev, gs_param_list * plist)
71 {
72 int code;
73
74 /* Standard page device parameters: */
75
76 bool seprs = false;
77 gs_param_string dns, pcms;
78 gs_param_float_array msa, ibba, hwra, ma;
79 gs_param_string_array scna;
80
81 #define set_param_array(a, d, s)\
82 (a.data = d, a.size = s, a.persistent = false);
83
84 /* Non-standard parameters: */
85
86 int colors = dev->color_info.num_components;
87 int mns = colors;
88 int depth = dev->color_info.depth;
89 int GrayValues = dev->color_info.max_gray + 1;
90 int HWSize[2];
91 gs_param_int_array hwsa;
92 gs_param_float_array hwma, mhwra;
93
94 /* Fill in page device parameters. */
95
96 param_string_from_string(dns, dev->dname);
97 {
98 const char *cms = get_process_color_model_name(dev);
99
100 /* We might have an uninitialized device with */
101 /* color_info.num_components = 0.... */
102 if ((cms != NULL) && (*cms != '\0'))
103 param_string_from_string(pcms, cms);
104 else
105 pcms.data = 0;
106 }
107 set_param_array(hwra, dev->HWResolution, 2);
108 set_param_array(msa, dev->MediaSize, 2);
109 set_param_array(ibba, dev->ImagingBBox, 4);
110 set_param_array(ma, dev->Margins, 2);
111 set_param_array(scna, NULL, 0);
112
113 /* Fill in non-standard parameters. */
114
115 HWSize[0] = dev->width;
116 HWSize[1] = dev->height;
117 set_param_array(hwsa, HWSize, 2);
118 set_param_array(hwma, dev->HWMargins, 4);
119 set_param_array(mhwra, dev->MarginsHWResolution, 2);
120
121 /* Transmit the values. */
122
123 if (
124
125 /* Standard parameters */
126
127 (code = param_write_name(plist, "OutputDevice", &dns)) < 0 ||
128 #ifdef PAGESIZE_IS_MEDIASIZE
129 (code = param_write_float_array(plist, "PageSize", &msa)) < 0 ||
130 #endif
131 (code = (pcms.data == 0 ? 0 :
132 param_write_name(plist, "ProcessColorModel", &pcms))) < 0 ||
133 (code = param_write_float_array(plist, "HWResolution", &hwra)) < 0 ||
134 (code = (dev->ImagingBBox_set ?
135 param_write_float_array(plist, "ImagingBBox", &ibba) :
136 param_write_null(plist, "ImagingBBox"))) < 0 ||
137 (code = param_write_float_array(plist, "Margins", &ma)) < 0 ||
138 (code = param_write_int(plist, "MaxSeparations", &mns)) < 0 ||
139 (code = (dev->NumCopies_set < 0 ||
140 (*dev_proc(dev, get_page_device))(dev) == 0 ? 0:
141 dev->NumCopies_set ?
142 param_write_int(plist, "NumCopies", &dev->NumCopies) :
143 param_write_null(plist, "NumCopies"))) < 0 ||
144 (code = param_write_name_array(plist, "SeparationColorNames", &scna)) < 0 ||
145 (code = param_write_bool(plist, "Separations", &seprs)) < 0 ||
146 (code = param_write_bool(plist, "UseCIEColor", &dev->UseCIEColor)) < 0 ||
147
148 /* Non-standard parameters */
149
150 (code = param_write_int_array(plist, "HWSize", &hwsa)) < 0 ||
151 (code = param_write_float_array(plist, ".HWMargins", &hwma)) < 0 ||
152 (code = param_write_float_array(plist, ".MarginsHWResolution", &mhwra)) < 0 ||
153 (code = param_write_float_array(plist, ".MediaSize", &msa)) < 0 ||
154 (code = param_write_string(plist, "Name", &dns)) < 0 ||
155 (code = param_write_int(plist, "Colors", &colors)) < 0 ||
156 (code = param_write_int(plist, "BitsPerPixel", &depth)) < 0 ||
157 (code = param_write_int(plist, "GrayValues", &GrayValues)) < 0 ||
158 (code = param_write_long(plist, "PageCount", &dev->PageCount)) < 0 ||
159 (code = param_write_bool(plist, ".IgnoreNumCopies", &dev->IgnoreNumCopies)) < 0 ||
160 (code = param_write_int(plist, "TextAlphaBits",
161 &dev->color_info.anti_alias.text_bits)) < 0 ||
162 (code = param_write_int(plist, "GraphicsAlphaBits",
163 &dev->color_info.anti_alias.graphics_bits)) < 0 ||
164 (code = param_write_bool(plist, ".LockSafetyParams", &dev->LockSafetyParams)) < 0
165 )
166 return code;
167
168 /* Fill in color information. */
169
170 if (colors > 1) {
171 int RGBValues = dev->color_info.max_color + 1;
172 long ColorValues = (depth >= (8 * arch_sizeof_color_index) ? -1
173 : 1L << depth);
174
175 if ((code = param_write_int(plist, "RedValues", &RGBValues)) < 0 ||
176 (code = param_write_int(plist, "GreenValues", &RGBValues)) < 0 ||
177 (code = param_write_int(plist, "BlueValues", &RGBValues)) < 0 ||
178 (code = param_write_long(plist, "ColorValues", &ColorValues)) < 0
179 )
180 return code;
181 }
182 if (param_requested(plist, "HWColorMap")) {
183 byte palette[3 << 8];
184
185 if (param_HWColorMap(dev, palette)) {
186 gs_param_string hwcms;
187
188 hwcms.data = palette, hwcms.size = colors << depth,
189 hwcms.persistent = false;
190 if ((code = param_write_string(plist, "HWColorMap", &hwcms)) < 0)
191 return code;
192 }
193 }
194
195 return 0;
196 }
197
198 /* Get the color map for a device. Return true if there is one. */
199 private bool
param_HWColorMap(gx_device * dev,byte * palette)200 param_HWColorMap(gx_device * dev, byte * palette /* 3 << 8 */ )
201 {
202 int depth = dev->color_info.depth;
203 int colors = dev->color_info.num_components;
204
205 if (depth <= 8 && colors <= 3) {
206 byte *p = palette;
207 gx_color_value rgb[3];
208 gx_color_index i;
209
210 fill_dev_proc(dev, map_color_rgb, gx_default_map_color_rgb);
211 for (i = 0; (i >> depth) == 0; i++) {
212 int j;
213
214 if ((*dev_proc(dev, map_color_rgb)) (dev, i, rgb) < 0)
215 return false;
216 for (j = 0; j < colors; j++)
217 *p++ = gx_color_value_to_byte(rgb[j]);
218 }
219 return true;
220 }
221 return false;
222 }
223
224 /* Get hardware-detected parameters. Default action is no hardware params. */
225 int
gx_default_get_hardware_params(gx_device * dev,gs_param_list * plist)226 gx_default_get_hardware_params(gx_device * dev, gs_param_list * plist)
227 {
228 return 0;
229 }
230
231 /* ---------------- Input and output media ---------------- */
232
233 /* Finish defining input or output media. */
234 private int
finish_media(gs_param_list * mlist,gs_param_name key,const char * media_type)235 finish_media(gs_param_list * mlist, gs_param_name key, const char *media_type)
236 {
237 int code = 0;
238
239 if (media_type != 0) {
240 gs_param_string as;
241
242 param_string_from_string(as, media_type);
243 code = param_write_string(mlist, key, &as);
244 }
245 return code;
246 }
247
248 /* Define input media. */
249
250 const gdev_input_media_t gdev_input_media_default =
251 {
252 gdev_input_media_default_values
253 };
254
255 int
gdev_begin_input_media(gs_param_list * mlist,gs_param_dict * pdict,int count)256 gdev_begin_input_media(gs_param_list * mlist, gs_param_dict * pdict,
257 int count)
258 {
259 pdict->size = count;
260 return param_begin_write_dict(mlist, "InputAttributes", pdict, true);
261 }
262
263 int
gdev_write_input_media(int index,gs_param_dict * pdict,const gdev_input_media_t * pim)264 gdev_write_input_media(int index, gs_param_dict * pdict,
265 const gdev_input_media_t * pim)
266 {
267 char key[25];
268 gs_param_dict mdict;
269 int code;
270 gs_param_string as;
271
272 sprintf(key, "%d", index);
273 mdict.size = 4;
274 code = param_begin_write_dict(pdict->list, key, &mdict, false);
275 if (code < 0)
276 return code;
277 if ((pim->PageSize[0] != 0 && pim->PageSize[1] != 0) ||
278 (pim->PageSize[2] != 0 && pim->PageSize[3] != 0)
279 ) {
280 gs_param_float_array psa;
281
282 psa.data = pim->PageSize;
283 psa.size =
284 (pim->PageSize[0] == pim->PageSize[2] &&
285 pim->PageSize[1] == pim->PageSize[3] ? 2 : 4);
286 psa.persistent = false;
287 code = param_write_float_array(mdict.list, "PageSize",
288 &psa);
289 if (code < 0)
290 return code;
291 }
292 if (pim->MediaColor != 0) {
293 param_string_from_string(as, pim->MediaColor);
294 code = param_write_string(mdict.list, "MediaColor",
295 &as);
296 if (code < 0)
297 return code;
298 }
299 if (pim->MediaWeight != 0) {
300 /*
301 * We do the following silly thing in order to avoid
302 * having to work around the 'const' in the arg list.
303 */
304 float weight = pim->MediaWeight;
305
306 code = param_write_float(mdict.list, "MediaWeight",
307 &weight);
308 if (code < 0)
309 return code;
310 }
311 code = finish_media(mdict.list, "MediaType", pim->MediaType);
312 if (code < 0)
313 return code;
314 return param_end_write_dict(pdict->list, key, &mdict);
315 }
316
317 int
gdev_write_input_page_size(int index,gs_param_dict * pdict,floatp width_points,floatp height_points)318 gdev_write_input_page_size(int index, gs_param_dict * pdict,
319 floatp width_points, floatp height_points)
320 {
321 gdev_input_media_t media;
322
323 media.PageSize[0] = media.PageSize[2] = (float) width_points;
324 media.PageSize[1] = media.PageSize[3] = (float) height_points;
325 media.MediaColor = 0;
326 media.MediaWeight = 0;
327 media.MediaType = 0;
328 return gdev_write_input_media(index, pdict, &media);
329 }
330
331 int
gdev_end_input_media(gs_param_list * mlist,gs_param_dict * pdict)332 gdev_end_input_media(gs_param_list * mlist, gs_param_dict * pdict)
333 {
334 return param_end_write_dict(mlist, "InputAttributes", pdict);
335 }
336
337 /* Define output media. */
338
339 const gdev_output_media_t gdev_output_media_default =
340 {
341 gdev_output_media_default_values
342 };
343
344 int
gdev_begin_output_media(gs_param_list * mlist,gs_param_dict * pdict,int count)345 gdev_begin_output_media(gs_param_list * mlist, gs_param_dict * pdict,
346 int count)
347 {
348 pdict->size = count;
349 return param_begin_write_dict(mlist, "OutputAttributes", pdict, true);
350 }
351
352 int
gdev_write_output_media(int index,gs_param_dict * pdict,const gdev_output_media_t * pom)353 gdev_write_output_media(int index, gs_param_dict * pdict,
354 const gdev_output_media_t * pom)
355 {
356 char key[25];
357 gs_param_dict mdict;
358 int code;
359
360 sprintf(key, "%d", index);
361 mdict.size = 4;
362 code = param_begin_write_dict(pdict->list, key, &mdict, false);
363 if (code < 0)
364 return code;
365 code = finish_media(mdict.list, "OutputType", pom->OutputType);
366 if (code < 0)
367 return code;
368 return param_end_write_dict(pdict->list, key, &mdict);
369 }
370
371 int
gdev_end_output_media(gs_param_list * mlist,gs_param_dict * pdict)372 gdev_end_output_media(gs_param_list * mlist, gs_param_dict * pdict)
373 {
374 return param_end_write_dict(mlist, "OutputAttributes", pdict);
375 }
376
377 /* ================ Putting parameters ================ */
378
379 /* Forward references */
380 private int param_anti_alias_bits(gs_param_list *, gs_param_name, int *);
381 private int param_MediaSize(gs_param_list *, gs_param_name,
382 const float *, gs_param_float_array *);
383
384 private int param_check_bool(gs_param_list *, gs_param_name, bool, bool);
385 private int param_check_long(gs_param_list *, gs_param_name, long, bool);
386 #define param_check_int(plist, pname, ival, is_defined)\
387 param_check_long(plist, pname, (long)(ival), is_defined)
388 private int param_check_bytes(gs_param_list *, gs_param_name, const byte *,
389 uint, bool);
390 #define param_check_string(plist, pname, str, is_defined)\
391 param_check_bytes(plist, pname, (const byte *)(str), \
392 (is_defined) ? strlen(str) : 0, is_defined)
393
394 /* Set the device parameters. */
395 /* If the device was open and the put_params procedure closed it, */
396 /* return 1; otherwise, return 0 or an error code as usual. */
397 int
gs_putdeviceparams(gx_device * dev,gs_param_list * plist)398 gs_putdeviceparams(gx_device * dev, gs_param_list * plist)
399 {
400 bool was_open = dev->is_open;
401 int code;
402
403 gx_device_set_procs(dev);
404 fill_dev_proc(dev, put_params, gx_default_put_params);
405 fill_dev_proc(dev, get_alpha_bits, gx_default_get_alpha_bits);
406 code = (*dev_proc(dev, put_params)) (dev, plist);
407 return (code < 0 ? code : was_open && !dev->is_open ? 1 : code);
408 }
409
410 /* Set standard parameters. */
411 /* Note that setting the size or resolution closes the device. */
412 /* Window devices that don't want this to happen must temporarily */
413 /* set is_open to false before calling gx_default_put_params, */
414 /* and then taking appropriate action afterwards. */
415 int
gx_default_put_params(gx_device * dev,gs_param_list * plist)416 gx_default_put_params(gx_device * dev, gs_param_list * plist)
417 {
418 int ecode = 0;
419 int code;
420 gs_param_name param_name;
421 gs_param_float_array hwra;
422 gs_param_int_array hwsa;
423 gs_param_float_array msa;
424 gs_param_float_array ma;
425 gs_param_float_array hwma;
426 gs_param_float_array mhwra;
427 gs_param_string_array scna;
428 int nci = dev->NumCopies;
429 int ncset = dev->NumCopies_set;
430 bool ignc = dev->IgnoreNumCopies;
431 bool ucc = dev->UseCIEColor;
432 bool locksafe = dev->LockSafetyParams;
433 gs_param_float_array ibba;
434 bool ibbnull = false;
435 int colors = dev->color_info.num_components;
436 int depth = dev->color_info.depth;
437 int GrayValues = dev->color_info.max_gray + 1;
438 int RGBValues = dev->color_info.max_color + 1;
439 long ColorValues = (depth >= 32 ? -1 : 1L << depth);
440 int tab = dev->color_info.anti_alias.text_bits;
441 int gab = dev->color_info.anti_alias.graphics_bits;
442 gs_param_string cms;
443
444 /*
445 * Template:
446 * BEGIN_ARRAY_PARAM(param_read_xxx_array, "pname", pxxa, size, pxxe) {
447 * ... check value if desired ...
448 * if (success)
449 * break;
450 * ... set ecode ...
451 * } END_ARRAY_PARAM(pxxa, pxxe);
452 */
453
454 #define BEGIN_ARRAY_PARAM(pread, pname, pa, psize, e)\
455 BEGIN\
456 switch (code = pread(plist, (param_name = pname), &(pa))) {\
457 case 0:\
458 if ((pa).size != psize) {\
459 ecode = gs_note_error(gs_error_rangecheck);\
460 (pa).data = 0; /* mark as not filled */\
461 } else
462 #define END_ARRAY_PARAM(pa, e)\
463 goto e;\
464 default:\
465 ecode = code;\
466 e: param_signal_error(plist, param_name, ecode);\
467 case 1:\
468 (pa).data = 0; /* mark as not filled */\
469 }\
470 END
471
472 /*
473 * The HWResolution, HWSize, and MediaSize parameters interact in
474 * the following way:
475 * 1. Setting HWResolution recomputes HWSize from MediaSize.
476 * 2. Setting HWSize recomputes MediaSize from HWResolution.
477 * 3. Setting MediaSize recomputes HWSize from HWResolution.
478 * If more than one parameter is being set, we apply these rules
479 * in the order 1, 2, 3. This does the right thing in the most
480 * common case of setting more than one parameter, namely,
481 * setting both HWResolution and HWSize.
482 */
483
484 BEGIN_ARRAY_PARAM(param_read_float_array, "HWResolution", hwra, 2, hwre) {
485 if (hwra.data[0] <= 0 || hwra.data[1] <= 0)
486 ecode = gs_note_error(gs_error_rangecheck);
487 else
488 break;
489 } END_ARRAY_PARAM(hwra, hwre);
490 BEGIN_ARRAY_PARAM(param_read_int_array, "HWSize", hwsa, 2, hwsa) {
491 /* We need a special check to handle the nullpage device, */
492 /* whose size is legitimately [0 0]. */
493 if ((hwsa.data[0] <= 0 && hwsa.data[0] != dev->width) ||
494 (hwsa.data[1] <= 0 && hwsa.data[1] != dev->height)
495 )
496 ecode = gs_note_error(gs_error_rangecheck);
497 #define max_coord (max_fixed / fixed_1)
498 #if max_coord < max_int
499 else if (hwsa.data[0] > max_coord || hwsa.data[1] > max_coord)
500 ecode = gs_note_error(gs_error_limitcheck);
501 #endif
502 #undef max_coord
503 else
504 break;
505 } END_ARRAY_PARAM(hwsa, hwse);
506 {
507 const float *res = (hwra.data == 0 ? dev->HWResolution : hwra.data);
508
509 #ifdef PAGESIZE_IS_MEDIASIZE
510 const float *data;
511
512 /* .MediaSize takes precedence over PageSize, so */
513 /* we read PageSize first. */
514 code = param_MediaSize(plist, "PageSize", res, &msa);
515 if (code < 0)
516 ecode = code;
517 /* Prevent data from being set to 0 if PageSize is specified */
518 /* but .MediaSize is not. */
519 data = msa.data;
520 code = param_MediaSize(plist, ".MediaSize", res, &msa);
521 if (code < 0)
522 ecode = code;
523 else if (msa.data == 0)
524 msa.data = data;
525 #else
526 code = param_MediaSize(plist, ".MediaSize", res, &msa);
527 if (code < 0)
528 ecode = code;
529 #endif
530 }
531
532 BEGIN_ARRAY_PARAM(param_read_float_array, "Margins", ma, 2, me) {
533 break;
534 } END_ARRAY_PARAM(ma, me);
535 BEGIN_ARRAY_PARAM(param_read_float_array, ".HWMargins", hwma, 4, hwme) {
536 break;
537 } END_ARRAY_PARAM(hwma, hwme);
538 /* MarginsHWResolution cannot be changed, only checked. */
539 BEGIN_ARRAY_PARAM(param_read_float_array, ".MarginsHWResolution", mhwra, 2, mhwre) {
540 if (mhwra.data[0] != dev->MarginsHWResolution[0] ||
541 mhwra.data[1] != dev->MarginsHWResolution[1]
542 )
543 ecode = gs_note_error(gs_error_rangecheck);
544 else
545 break;
546 } END_ARRAY_PARAM(mhwra, mhwre);
547 switch (code = param_read_bool(plist, (param_name = ".IgnoreNumCopies"), &ignc)) {
548 default:
549 ecode = code;
550 param_signal_error(plist, param_name, ecode);
551 case 0:
552 case 1:
553 break;
554 }
555 if (dev->NumCopies_set >= 0 &&
556 (*dev_proc(dev, get_page_device))(dev) != 0
557 ) {
558 switch (code = param_read_int(plist, (param_name = "NumCopies"), &nci)) {
559 case 0:
560 if (nci < 0)
561 ecode = gs_error_rangecheck;
562 else {
563 ncset = 1;
564 break;
565 }
566 goto nce;
567 default:
568 if ((code = param_read_null(plist, param_name)) == 0) {
569 ncset = 0;
570 break;
571 }
572 ecode = code; /* can't be 1 */
573 nce:
574 param_signal_error(plist, param_name, ecode);
575 case 1:
576 break;
577 }
578 }
579 if ((code = param_read_bool(plist, (param_name = "UseCIEColor"), &ucc)) < 0) {
580 ecode = code;
581 param_signal_error(plist, param_name, ecode);
582 }
583 if ((code = param_anti_alias_bits(plist, "TextAlphaBits", &tab)) < 0)
584 ecode = code;
585 if ((code = param_anti_alias_bits(plist, "GraphicsAlphaBits", &gab)) < 0)
586 ecode = code;
587
588 switch (code = param_read_bool(plist, (param_name = ".LockSafetyParams"), &locksafe)) {
589 case 0:
590 if (dev->LockSafetyParams && !locksafe)
591 code = gs_note_error(gs_error_invalidaccess);
592 else
593 break;
594 default:
595 ecode = code;
596 param_signal_error(plist, param_name, ecode);
597 case 1:
598 break;
599 }
600 /* Ignore parameters that only have meaning for printers. */
601 #define IGNORE_INT_PARAM(pname)\
602 { int igni;\
603 switch ( code = param_read_int(plist, (param_name = pname), &igni) )\
604 { default:\
605 ecode = code;\
606 param_signal_error(plist, param_name, ecode);\
607 case 0:\
608 case 1:\
609 break;\
610 }\
611 }
612 IGNORE_INT_PARAM("%MediaSource")
613 IGNORE_INT_PARAM("%MediaDestination")
614 switch (code = param_read_float_array(plist, (param_name = "ImagingBBox"), &ibba)) {
615 case 0:
616 if (ibba.size != 4 ||
617 ibba.data[2] < ibba.data[0] || ibba.data[3] < ibba.data[1]
618 )
619 ecode = gs_note_error(gs_error_rangecheck);
620 else
621 break;
622 goto ibbe;
623 default:
624 if ((code = param_read_null(plist, param_name)) == 0) {
625 ibbnull = true;
626 ibba.data = 0;
627 break;
628 }
629 ecode = code; /* can't be 1 */
630 ibbe:param_signal_error(plist, param_name, ecode);
631 case 1:
632 ibba.data = 0;
633 break;
634 }
635
636 /* Separation, DeviceN Color, and ProcessColorModel related parameters. */
637 {
638 const char * pcms = get_process_color_model_name(dev);
639 /* the device should have set a process model name at this point */
640 if ((code = param_check_string(plist, "ProcessColorModel", pcms, (pcms != NULL))) < 0)
641 ecode = code;
642 }
643 IGNORE_INT_PARAM("MaxSeparations")
644 if ((code = param_check_bool(plist, "Separations", false, true)) < 0)
645 ecode = code;
646
647 BEGIN_ARRAY_PARAM(param_read_name_array, "SeparationColorNames", scna, scna.size, scne) {
648 break;
649 } END_ARRAY_PARAM(scna, scne);
650
651
652 /* Now check nominally read-only parameters. */
653 if ((code = param_check_string(plist, "OutputDevice", dev->dname, true)) < 0)
654 ecode = code;
655 if ((code = param_check_string(plist, "Name", dev->dname, true)) < 0)
656 ecode = code;
657 if ((code = param_check_int(plist, "Colors", colors, true)) < 0)
658 ecode = code;
659 if ((code = param_check_int(plist, "BitsPerPixel", depth, true)) < 0)
660 ecode = code;
661 if ((code = param_check_int(plist, "GrayValues", GrayValues, true)) < 0)
662 ecode = code;
663 if ((code = param_check_long(plist, "PageCount", dev->PageCount, true)) < 0)
664 ecode = code;
665 if ((code = param_check_int(plist, "RedValues", RGBValues, true)) < 0)
666 ecode = code;
667 if ((code = param_check_int(plist, "GreenValues", RGBValues, true)) < 0)
668 ecode = code;
669 if ((code = param_check_int(plist, "BlueValues", RGBValues, true)) < 0)
670 ecode = code;
671 if ((code = param_check_long(plist, "ColorValues", ColorValues, true)) < 0)
672 ecode = code;
673 if (param_read_string(plist, "HWColorMap", &cms) != 1) {
674 byte palette[3 << 8];
675
676 if (param_HWColorMap(dev, palette))
677 code = param_check_bytes(plist, "HWColorMap", palette,
678 colors << depth, true);
679 else
680 code = param_check_bytes(plist, "HWColorMap", 0, 0, false);
681 if (code < 0)
682 ecode = code;
683 }
684
685 /* We must 'commit', in order to detect unknown parameters, */
686 /* even if there were errors. */
687 code = param_commit(plist);
688 if (ecode < 0)
689 return ecode;
690 if (code < 0)
691 return code;
692
693 /* Now actually make the changes. */
694 /* Changing resolution or page size requires closing the device, */
695 /* but changing margins or ImagingBBox does not. */
696 /* In order not to close and reopen the device unnecessarily, */
697 /* we check for replacing the values with the same ones. */
698
699 if (hwra.data != 0 &&
700 (dev->HWResolution[0] != hwra.data[0] ||
701 dev->HWResolution[1] != hwra.data[1])
702 ) {
703 if (dev->is_open)
704 gs_closedevice(dev);
705 gx_device_set_resolution(dev, hwra.data[0], hwra.data[1]);
706 }
707 if (hwsa.data != 0 &&
708 (dev->width != hwsa.data[0] ||
709 dev->height != hwsa.data[1])
710 ) {
711 if (dev->is_open)
712 gs_closedevice(dev);
713 gx_device_set_width_height(dev, hwsa.data[0], hwsa.data[1]);
714 }
715 if (msa.data != 0 &&
716 (dev->MediaSize[0] != msa.data[0] ||
717 dev->MediaSize[1] != msa.data[1])
718 ) {
719 if (dev->is_open)
720 gs_closedevice(dev);
721 gx_device_set_page_size(dev, msa.data[0], msa.data[1]);
722 }
723 if (ma.data != 0) {
724 dev->Margins[0] = ma.data[0];
725 dev->Margins[1] = ma.data[1];
726 }
727 if (hwma.data != 0) {
728 dev->HWMargins[0] = hwma.data[0];
729 dev->HWMargins[1] = hwma.data[1];
730 dev->HWMargins[2] = hwma.data[2];
731 dev->HWMargins[3] = hwma.data[3];
732 }
733 dev->NumCopies = nci;
734 dev->NumCopies_set = ncset;
735 dev->IgnoreNumCopies = ignc;
736 if (ibba.data != 0) {
737 dev->ImagingBBox[0] = ibba.data[0];
738 dev->ImagingBBox[1] = ibba.data[1];
739 dev->ImagingBBox[2] = ibba.data[2];
740 dev->ImagingBBox[3] = ibba.data[3];
741 dev->ImagingBBox_set = true;
742 } else if (ibbnull) {
743 dev->ImagingBBox_set = false;
744 }
745 dev->UseCIEColor = ucc;
746 dev->color_info.anti_alias.text_bits = tab;
747 dev->color_info.anti_alias.graphics_bits = gab;
748 dev->LockSafetyParams = locksafe;
749 gx_device_decache_colors(dev);
750 return 0;
751 }
752
753 /* Read TextAlphaBits or GraphicsAlphaBits. */
754 private int
param_anti_alias_bits(gs_param_list * plist,gs_param_name param_name,int * pa)755 param_anti_alias_bits(gs_param_list * plist, gs_param_name param_name, int *pa)
756 {
757 int code = param_read_int(plist, param_name, pa);
758
759 switch (code) {
760 case 0:
761 switch (*pa) {
762 case 1: case 2: case 4:
763 return 0;
764 default:
765 code = gs_error_rangecheck;
766 }
767 default:
768 param_signal_error(plist, param_name, code);
769 case 1:
770 ;
771 }
772 return code;
773 }
774
775
776 /* Read .MediaSize or, if supported as a synonym, PageSize. */
777 private int
param_MediaSize(gs_param_list * plist,gs_param_name pname,const float * res,gs_param_float_array * pa)778 param_MediaSize(gs_param_list * plist, gs_param_name pname,
779 const float *res, gs_param_float_array * pa)
780 {
781 gs_param_name param_name;
782 int ecode = 0;
783 int code;
784
785 BEGIN_ARRAY_PARAM(param_read_float_array, pname, *pa, 2, mse) {
786 float width_new = pa->data[0] * res[0] / 72;
787 float height_new = pa->data[1] * res[1] / 72;
788
789 if (width_new < 0 || height_new < 0)
790 ecode = gs_note_error(gs_error_rangecheck);
791 #define max_coord (max_fixed / fixed_1)
792 #if max_coord < max_int
793 else if (width_new > max_coord || height_new > max_coord)
794 ecode = gs_note_error(gs_error_limitcheck);
795 #endif
796 #undef max_coord
797 else
798 break;
799 } END_ARRAY_PARAM(*pa, mse);
800 return ecode;
801 }
802
803 /* Check that a nominally read-only parameter is being set to */
804 /* its existing value. */
805 private int
param_check_bool(gs_param_list * plist,gs_param_name pname,bool value,bool is_defined)806 param_check_bool(gs_param_list * plist, gs_param_name pname, bool value,
807 bool is_defined)
808 {
809 int code;
810 bool new_value;
811
812 switch (code = param_read_bool(plist, pname, &new_value)) {
813 case 0:
814 if (is_defined && new_value == value)
815 break;
816 code = gs_note_error(gs_error_rangecheck);
817 goto e;
818 default:
819 if (param_read_null(plist, pname) == 0)
820 return 1;
821 e:param_signal_error(plist, pname, code);
822 case 1:
823 ;
824 }
825 return code;
826 }
827 private int
param_check_long(gs_param_list * plist,gs_param_name pname,long value,bool is_defined)828 param_check_long(gs_param_list * plist, gs_param_name pname, long value,
829 bool is_defined)
830 {
831 int code;
832 long new_value;
833
834 switch (code = param_read_long(plist, pname, &new_value)) {
835 case 0:
836 if (is_defined && new_value == value)
837 break;
838 code = gs_note_error(gs_error_rangecheck);
839 goto e;
840 default:
841 if (param_read_null(plist, pname) == 0)
842 return 1;
843 e:param_signal_error(plist, pname, code);
844 case 1:
845 ;
846 }
847 return code;
848 }
849 private int
param_check_bytes(gs_param_list * plist,gs_param_name pname,const byte * str,uint size,bool is_defined)850 param_check_bytes(gs_param_list * plist, gs_param_name pname, const byte * str,
851 uint size, bool is_defined)
852 {
853 int code;
854 gs_param_string new_value;
855
856 switch (code = param_read_string(plist, pname, &new_value)) {
857 case 0:
858 if (is_defined && new_value.size == size &&
859 !memcmp((const char *)str, (const char *)new_value.data,
860 size)
861 )
862 break;
863 code = gs_note_error(gs_error_rangecheck);
864 goto e;
865 default:
866 if (param_read_null(plist, pname) == 0)
867 return 1;
868 e:param_signal_error(plist, pname, code);
869 case 1:
870 ;
871 }
872 return code;
873 }
874