1 /* Copyright (C) 1993, 2000 artofcode LLC. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify it
4 under the terms of the GNU General Public License as published by the
5 Free Software Foundation; either version 2 of the License, or (at your
6 option) any later version.
7
8 This program is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along
14 with this program; if not, write to the Free Software Foundation, Inc.,
15 59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16
17 */
18
19 /*$Id: gsdparam.c,v 1.4.6.2.2.1 2003/01/17 00:49:02 giles Exp $ */
20 /* Default device parameters for Ghostscript library */
21 #include "memory_.h" /* for memcpy */
22 #include "string_.h" /* for strlen */
23 #include "gx.h"
24 #include "gserrors.h"
25 #include "gsdevice.h" /* for prototypes */
26 #include "gsparam.h"
27 #include "gxdevice.h"
28 #include "gxfixed.h"
29
30 /* Define whether we accept PageSize as a synonym for MediaSize. */
31 /* This is for backward compatibility only. */
32 #define PAGESIZE_IS_MEDIASIZE
33
34 /* ================ Getting parameters ================ */
35
36 /* Forward references */
37 private bool param_HWColorMap(P2(gx_device *, byte *));
38
39 /* Get the device parameters. */
40 int
gs_get_device_or_hw_params(gx_device * orig_dev,gs_param_list * plist,bool is_hardware)41 gs_get_device_or_hw_params(gx_device * orig_dev, gs_param_list * plist,
42 bool is_hardware)
43 {
44 /*
45 * We must be prepared to copy the device if it is the read-only
46 * prototype.
47 */
48 gx_device *dev;
49 int code;
50
51 if (orig_dev->memory)
52 dev = orig_dev;
53 else {
54 code = gs_copydevice(&dev, orig_dev, plist->memory);
55 if (code < 0)
56 return code;
57 }
58 gx_device_set_procs(dev);
59 fill_dev_proc(dev, get_params, gx_default_get_params);
60 fill_dev_proc(dev, get_page_device, gx_default_get_page_device);
61 fill_dev_proc(dev, get_alpha_bits, gx_default_get_alpha_bits);
62 code = (is_hardware ?
63 (*dev_proc(dev, get_hardware_params)) (dev, plist) :
64 (*dev_proc(dev, get_params)) (dev, plist));
65 if (dev != orig_dev)
66 gx_device_retain(dev, false); /* frees the copy */
67 return code;
68 }
69
70 /* Standard ProcessColorModel values. */
71 static const char *const pcmsa[] =
72 {
73 "", "DeviceGray", "", "DeviceRGB", "DeviceCMYK"
74 };
75
76 /* Get standard parameters. */
77 int
gx_default_get_params(gx_device * dev,gs_param_list * plist)78 gx_default_get_params(gx_device * dev, gs_param_list * plist)
79 {
80 int code;
81
82 /* Standard page device parameters: */
83
84 int mns = 1;
85 bool seprs = false;
86 gs_param_string dns, pcms;
87 gs_param_float_array msa, ibba, hwra, ma;
88 gs_param_string_array scna;
89
90 #define set_param_array(a, d, s)\
91 (a.data = d, a.size = s, a.persistent = false);
92
93 /* Non-standard parameters: */
94
95 int colors = dev->color_info.num_components;
96 int depth = dev->color_info.depth;
97 int GrayValues = dev->color_info.max_gray + 1;
98 int HWSize[2];
99 gs_param_int_array hwsa;
100 gs_param_float_array hwma, mhwra;
101
102 /* Fill in page device parameters. */
103
104 param_string_from_string(dns, dev->dname);
105 {
106 const char *cms = pcmsa[colors];
107
108 /* We might have an uninitialized device with */
109 /* color_info.num_components = 0.... */
110 if (*cms != 0)
111 param_string_from_string(pcms, cms);
112 else
113 pcms.data = 0;
114 }
115 set_param_array(hwra, dev->HWResolution, 2);
116 set_param_array(msa, dev->MediaSize, 2);
117 set_param_array(ibba, dev->ImagingBBox, 4);
118 set_param_array(ma, dev->Margins, 2);
119 set_param_array(scna, NULL, 0);
120
121 /* Fill in non-standard parameters. */
122
123 HWSize[0] = dev->width;
124 HWSize[1] = dev->height;
125 set_param_array(hwsa, HWSize, 2);
126 set_param_array(hwma, dev->HWMargins, 4);
127 set_param_array(mhwra, dev->MarginsHWResolution, 2);
128
129 /* Transmit the values. */
130
131 if (
132
133 /* Standard parameters */
134
135 (code = param_write_name(plist, "OutputDevice", &dns)) < 0 ||
136 #ifdef PAGESIZE_IS_MEDIASIZE
137 (code = param_write_float_array(plist, "PageSize", &msa)) < 0 ||
138 #endif
139 (code = (pcms.data == 0 ? 0 :
140 param_write_name(plist, "ProcessColorModel", &pcms))) < 0 ||
141 (code = param_write_float_array(plist, "HWResolution", &hwra)) < 0 ||
142 (code = (dev->ImagingBBox_set ?
143 param_write_float_array(plist, "ImagingBBox", &ibba) :
144 param_write_null(plist, "ImagingBBox"))) < 0 ||
145 (code = param_write_float_array(plist, "Margins", &ma)) < 0 ||
146 (code = param_write_int(plist, "MaxSeparations", &mns)) < 0 ||
147 (code = (dev->NumCopies_set < 0 ||
148 (*dev_proc(dev, get_page_device))(dev) == 0 ? 0:
149 dev->NumCopies_set ?
150 param_write_int(plist, "NumCopies", &dev->NumCopies) :
151 param_write_null(plist, "NumCopies"))) < 0 ||
152 (code = param_write_name_array(plist, "SeparationColorNames", &scna)) < 0 ||
153 (code = param_write_bool(plist, "Separations", &seprs)) < 0 ||
154 (code = param_write_bool(plist, "UseCIEColor", &dev->UseCIEColor)) < 0 ||
155
156 /* Non-standard parameters */
157
158 (code = param_write_int_array(plist, "HWSize", &hwsa)) < 0 ||
159 (code = param_write_float_array(plist, ".HWMargins", &hwma)) < 0 ||
160 (code = param_write_float_array(plist, ".MarginsHWResolution", &mhwra)) < 0 ||
161 (code = param_write_float_array(plist, ".MediaSize", &msa)) < 0 ||
162 (code = param_write_string(plist, "Name", &dns)) < 0 ||
163 (code = param_write_int(plist, "Colors", &colors)) < 0 ||
164 (code = param_write_int(plist, "BitsPerPixel", &depth)) < 0 ||
165 (code = param_write_int(plist, "GrayValues", &GrayValues)) < 0 ||
166 (code = param_write_long(plist, "PageCount", &dev->PageCount)) < 0 ||
167 (code = param_write_bool(plist, ".IgnoreNumCopies", &dev->IgnoreNumCopies)) < 0 ||
168 (code = param_write_int(plist, "TextAlphaBits",
169 &dev->color_info.anti_alias.text_bits)) < 0 ||
170 (code = param_write_int(plist, "GraphicsAlphaBits",
171 &dev->color_info.anti_alias.graphics_bits)) < 0 ||
172 (code = param_write_bool(plist, ".LockSafetyParams", &dev->LockSafetyParams)) < 0
173 )
174 return code;
175
176 /* Fill in color information. */
177
178 if (colors > 1) {
179 int RGBValues = dev->color_info.max_color + 1;
180 long ColorValues = 1L << depth;
181
182 if ((code = param_write_int(plist, "RedValues", &RGBValues)) < 0 ||
183 (code = param_write_int(plist, "GreenValues", &RGBValues)) < 0 ||
184 (code = param_write_int(plist, "BlueValues", &RGBValues)) < 0 ||
185 (code = param_write_long(plist, "ColorValues", &ColorValues)) < 0
186 )
187 return code;
188 }
189 if (param_requested(plist, "HWColorMap")) {
190 byte palette[3 << 8];
191
192 if (param_HWColorMap(dev, palette)) {
193 gs_param_string hwcms;
194
195 hwcms.data = palette, hwcms.size = colors << depth,
196 hwcms.persistent = false;
197 if ((code = param_write_string(plist, "HWColorMap", &hwcms)) < 0)
198 return code;
199 }
200 }
201
202 return 0;
203 }
204
205 /* Get the color map for a device. Return true if there is one. */
206 private bool
param_HWColorMap(gx_device * dev,byte * palette)207 param_HWColorMap(gx_device * dev, byte * palette /* 3 << 8 */ )
208 {
209 int depth = dev->color_info.depth;
210 int colors = dev->color_info.num_components;
211
212 if (depth <= 8 && colors <= 3) {
213 byte *p = palette;
214 gx_color_value rgb[3];
215 gx_color_index i;
216
217 fill_dev_proc(dev, map_color_rgb, gx_default_map_color_rgb);
218 for (i = 0; (i >> depth) == 0; i++) {
219 int j;
220
221 if ((*dev_proc(dev, map_color_rgb)) (dev, i, rgb) < 0)
222 return false;
223 for (j = 0; j < colors; j++)
224 *p++ = gx_color_value_to_byte(rgb[j]);
225 }
226 return true;
227 }
228 return false;
229 }
230
231 /* Get hardware-detected parameters. Default action is no hardware params. */
232 int
gx_default_get_hardware_params(gx_device * dev,gs_param_list * plist)233 gx_default_get_hardware_params(gx_device * dev, gs_param_list * plist)
234 {
235 return 0;
236 }
237
238 /* ---------------- Input and output media ---------------- */
239
240 /* Finish defining input or output media. */
241 private int
finish_media(gs_param_list * mlist,gs_param_name key,const char * media_type)242 finish_media(gs_param_list * mlist, gs_param_name key, const char *media_type)
243 {
244 int code = 0;
245
246 if (media_type != 0) {
247 gs_param_string as;
248
249 param_string_from_string(as, media_type);
250 code = param_write_string(mlist, key, &as);
251 }
252 return code;
253 }
254
255 /* Define input media. */
256
257 const gdev_input_media_t gdev_input_media_default =
258 {
259 gdev_input_media_default_values
260 };
261
262 int
gdev_begin_input_media(gs_param_list * mlist,gs_param_dict * pdict,int count)263 gdev_begin_input_media(gs_param_list * mlist, gs_param_dict * pdict,
264 int count)
265 {
266 pdict->size = count;
267 return param_begin_write_dict(mlist, "InputAttributes", pdict, true);
268 }
269
270 int
gdev_write_input_media(int index,gs_param_dict * pdict,const gdev_input_media_t * pim)271 gdev_write_input_media(int index, gs_param_dict * pdict,
272 const gdev_input_media_t * pim)
273 {
274 char key[25];
275 gs_param_dict mdict;
276 int code;
277 gs_param_string as;
278
279 sprintf(key, "%d", index);
280 mdict.size = 4;
281 code = param_begin_write_dict(pdict->list, key, &mdict, false);
282 if (code < 0)
283 return code;
284 if ((pim->PageSize[0] != 0 && pim->PageSize[1] != 0) ||
285 (pim->PageSize[2] != 0 && pim->PageSize[3] != 0)
286 ) {
287 gs_param_float_array psa;
288
289 psa.data = pim->PageSize;
290 psa.size =
291 (pim->PageSize[0] == pim->PageSize[2] &&
292 pim->PageSize[1] == pim->PageSize[3] ? 2 : 4);
293 psa.persistent = false;
294 code = param_write_float_array(mdict.list, "PageSize",
295 &psa);
296 if (code < 0)
297 return code;
298 }
299 if (pim->MediaColor != 0) {
300 param_string_from_string(as, pim->MediaColor);
301 code = param_write_string(mdict.list, "MediaColor",
302 &as);
303 if (code < 0)
304 return code;
305 }
306 if (pim->MediaWeight != 0) {
307 /*
308 * We do the following silly thing in order to avoid
309 * having to work around the 'const' in the arg list.
310 */
311 float weight = pim->MediaWeight;
312
313 code = param_write_float(mdict.list, "MediaWeight",
314 &weight);
315 if (code < 0)
316 return code;
317 }
318 code = finish_media(mdict.list, "MediaType", pim->MediaType);
319 if (code < 0)
320 return code;
321 return param_end_write_dict(pdict->list, key, &mdict);
322 }
323
324 int
gdev_write_input_page_size(int index,gs_param_dict * pdict,floatp width_points,floatp height_points)325 gdev_write_input_page_size(int index, gs_param_dict * pdict,
326 floatp width_points, floatp height_points)
327 {
328 gdev_input_media_t media;
329
330 media.PageSize[0] = media.PageSize[2] = width_points;
331 media.PageSize[1] = media.PageSize[3] = height_points;
332 media.MediaColor = 0;
333 media.MediaWeight = 0;
334 media.MediaType = 0;
335 return gdev_write_input_media(index, pdict, &media);
336 }
337
338 int
gdev_end_input_media(gs_param_list * mlist,gs_param_dict * pdict)339 gdev_end_input_media(gs_param_list * mlist, gs_param_dict * pdict)
340 {
341 return param_end_write_dict(mlist, "InputAttributes", pdict);
342 }
343
344 /* Define output media. */
345
346 const gdev_output_media_t gdev_output_media_default =
347 {
348 gdev_output_media_default_values
349 };
350
351 int
gdev_begin_output_media(gs_param_list * mlist,gs_param_dict * pdict,int count)352 gdev_begin_output_media(gs_param_list * mlist, gs_param_dict * pdict,
353 int count)
354 {
355 pdict->size = count;
356 return param_begin_write_dict(mlist, "OutputAttributes", pdict, true);
357 }
358
359 int
gdev_write_output_media(int index,gs_param_dict * pdict,const gdev_output_media_t * pom)360 gdev_write_output_media(int index, gs_param_dict * pdict,
361 const gdev_output_media_t * pom)
362 {
363 char key[25];
364 gs_param_dict mdict;
365 int code;
366
367 sprintf(key, "%d", index);
368 mdict.size = 4;
369 code = param_begin_write_dict(pdict->list, key, &mdict, false);
370 if (code < 0)
371 return code;
372 code = finish_media(mdict.list, "OutputType", pom->OutputType);
373 if (code < 0)
374 return code;
375 return param_end_write_dict(pdict->list, key, &mdict);
376 }
377
378 int
gdev_end_output_media(gs_param_list * mlist,gs_param_dict * pdict)379 gdev_end_output_media(gs_param_list * mlist, gs_param_dict * pdict)
380 {
381 return param_end_write_dict(mlist, "OutputAttributes", pdict);
382 }
383
384 /* ================ Putting parameters ================ */
385
386 /* Forward references */
387 private int param_anti_alias_bits(P3(gs_param_list *, gs_param_name, int *));
388 private int param_MediaSize(P4(gs_param_list *, gs_param_name,
389 const float *, gs_param_float_array *));
390
391 private int param_check_bool(P4(gs_param_list *, gs_param_name, bool, bool));
392 private int param_check_long(P4(gs_param_list *, gs_param_name, long, bool));
393
394 #define param_check_int(plist, pname, ival, defined)\
395 param_check_long(plist, pname, (long)(ival), defined)
396 private int param_check_bytes(P5(gs_param_list *, gs_param_name, const byte *, uint, bool));
397
398 #define param_check_string(plist, pname, str, defined)\
399 param_check_bytes(plist, pname, (const byte *)str, strlen(str), defined)
400
401 /* Set the device parameters. */
402 /* If the device was open and the put_params procedure closed it, */
403 /* return 1; otherwise, return 0 or an error code as usual. */
404 int
gs_putdeviceparams(gx_device * dev,gs_param_list * plist)405 gs_putdeviceparams(gx_device * dev, gs_param_list * plist)
406 {
407 bool was_open = dev->is_open;
408 int code;
409
410 gx_device_set_procs(dev);
411 fill_dev_proc(dev, put_params, gx_default_put_params);
412 fill_dev_proc(dev, get_alpha_bits, gx_default_get_alpha_bits);
413 code = (*dev_proc(dev, put_params)) (dev, plist);
414 return (code < 0 ? code : was_open && !dev->is_open ? 1 : code);
415 }
416
417 /* Set standard parameters. */
418 /* Note that setting the size or resolution closes the device. */
419 /* Window devices that don't want this to happen must temporarily */
420 /* set is_open to false before calling gx_default_put_params, */
421 /* and then taking appropriate action afterwards. */
422 int
gx_default_put_params(gx_device * dev,gs_param_list * plist)423 gx_default_put_params(gx_device * dev, gs_param_list * plist)
424 {
425 int ecode = 0;
426 int code;
427 gs_param_name param_name;
428 gs_param_float_array hwra;
429 gs_param_int_array hwsa;
430 gs_param_float_array msa;
431 gs_param_float_array ma;
432 gs_param_float_array hwma;
433 gs_param_float_array mhwra;
434 gs_param_string_array scna;
435 int nci = dev->NumCopies;
436 int ncset = dev->NumCopies_set;
437 bool ignc = dev->IgnoreNumCopies;
438 bool ucc = dev->UseCIEColor;
439 bool locksafe = dev->LockSafetyParams;
440 gs_param_float_array ibba;
441 bool ibbnull = false;
442 int colors = dev->color_info.num_components;
443 int depth = dev->color_info.depth;
444 int GrayValues = dev->color_info.max_gray + 1;
445 int RGBValues = dev->color_info.max_color + 1;
446 long ColorValues = 1L << depth;
447 int tab = dev->color_info.anti_alias.text_bits;
448 int gab = dev->color_info.anti_alias.graphics_bits;
449 gs_param_string cms;
450
451 /*
452 * Template:
453 * BEGIN_ARRAY_PARAM(param_read_xxx_array, "pname", pxxa, size, pxxe) {
454 * ... check value if desired ...
455 * if (success)
456 * break;
457 * ... set ecode ...
458 * } END_ARRAY_PARAM(pxxa, pxxe);
459 */
460
461 #define BEGIN_ARRAY_PARAM(pread, pname, pa, psize, e)\
462 BEGIN\
463 switch (code = pread(plist, (param_name = pname), &(pa))) {\
464 case 0:\
465 if ((pa).size != psize) {\
466 ecode = gs_note_error(gs_error_rangecheck);\
467 (pa).data = 0; /* mark as not filled */\
468 } else
469 #define END_ARRAY_PARAM(pa, e)\
470 goto e;\
471 default:\
472 ecode = code;\
473 e: param_signal_error(plist, param_name, ecode);\
474 case 1:\
475 (pa).data = 0; /* mark as not filled */\
476 }\
477 END
478
479 /*
480 * The HWResolution, HWSize, and MediaSize parameters interact in
481 * the following way:
482 * 1. Setting HWResolution recomputes HWSize from MediaSize.
483 * 2. Setting HWSize recomputes MediaSize from HWResolution.
484 * 3. Setting MediaSize recomputes HWSize from HWResolution.
485 * If more than one parameter is being set, we apply these rules
486 * in the order 1, 2, 3. This does the right thing in the most
487 * common case of setting more than one parameter, namely,
488 * setting both HWResolution and HWSize.
489 */
490
491 BEGIN_ARRAY_PARAM(param_read_float_array, "HWResolution", hwra, 2, hwre) {
492 if (hwra.data[0] <= 0 || hwra.data[1] <= 0)
493 ecode = gs_note_error(gs_error_rangecheck);
494 else
495 break;
496 } END_ARRAY_PARAM(hwra, hwre);
497 BEGIN_ARRAY_PARAM(param_read_int_array, "HWSize", hwsa, 2, hwsa) {
498 /* We need a special check to handle the nullpage device, */
499 /* whose size is legitimately [0 0]. */
500 if ((hwsa.data[0] <= 0 && hwsa.data[0] != dev->width) ||
501 (hwsa.data[1] <= 0 && hwsa.data[1] != dev->height)
502 )
503 ecode = gs_note_error(gs_error_rangecheck);
504 #define max_coord (max_fixed / fixed_1)
505 #if max_coord < max_int
506 else if (hwsa.data[0] > max_coord || hwsa.data[1] > max_coord)
507 ecode = gs_note_error(gs_error_limitcheck);
508 #endif
509 #undef max_coord
510 else
511 break;
512 } END_ARRAY_PARAM(hwsa, hwse);
513 {
514 const float *res = (hwra.data == 0 ? dev->HWResolution : hwra.data);
515
516 #ifdef PAGESIZE_IS_MEDIASIZE
517 const float *data;
518
519 /* .MediaSize takes precedence over PageSize, so */
520 /* we read PageSize first. */
521 code = param_MediaSize(plist, "PageSize", res, &msa);
522 if (code < 0)
523 ecode = code;
524 /* Prevent data from being set to 0 if PageSize is specified */
525 /* but .MediaSize is not. */
526 data = msa.data;
527 code = param_MediaSize(plist, ".MediaSize", res, &msa);
528 if (code < 0)
529 ecode = code;
530 else if (msa.data == 0)
531 msa.data = data;
532 #else
533 code = param_MediaSize(plist, ".MediaSize", res, &msa);
534 if (code < 0)
535 ecode = code;
536 #endif
537 }
538
539 BEGIN_ARRAY_PARAM(param_read_float_array, "Margins", ma, 2, me) {
540 break;
541 } END_ARRAY_PARAM(ma, me);
542 BEGIN_ARRAY_PARAM(param_read_float_array, ".HWMargins", hwma, 4, hwme) {
543 break;
544 } END_ARRAY_PARAM(hwma, hwme);
545 /* MarginsHWResolution cannot be changed, only checked. */
546 BEGIN_ARRAY_PARAM(param_read_float_array, ".MarginsHWResolution", mhwra, 2, mhwre) {
547 if (mhwra.data[0] != dev->MarginsHWResolution[0] ||
548 mhwra.data[1] != dev->MarginsHWResolution[1]
549 )
550 ecode = gs_note_error(gs_error_rangecheck);
551 else
552 break;
553 } END_ARRAY_PARAM(mhwra, mhwre);
554 switch (code = param_read_bool(plist, (param_name = ".IgnoreNumCopies"), &ignc)) {
555 default:
556 ecode = code;
557 param_signal_error(plist, param_name, ecode);
558 case 0:
559 case 1:
560 break;
561 }
562 if (dev->NumCopies_set >= 0 &&
563 (*dev_proc(dev, get_page_device))(dev) != 0
564 ) {
565 switch (code = param_read_int(plist, (param_name = "NumCopies"), &nci)) {
566 case 0:
567 if (nci < 0)
568 ecode = gs_error_rangecheck;
569 else {
570 ncset = 1;
571 break;
572 }
573 goto nce;
574 default:
575 if ((code = param_read_null(plist, param_name)) == 0) {
576 ncset = 0;
577 break;
578 }
579 ecode = code; /* can't be 1 */
580 nce:
581 param_signal_error(plist, param_name, ecode);
582 case 1:
583 break;
584 }
585 }
586 if ((code = param_read_bool(plist, (param_name = "UseCIEColor"), &ucc)) < 0) {
587 ecode = code;
588 param_signal_error(plist, param_name, ecode);
589 }
590 if ((code = param_anti_alias_bits(plist, "TextAlphaBits", &tab)) < 0)
591 ecode = code;
592 if ((code = param_anti_alias_bits(plist, "GraphicsAlphaBits", &gab)) < 0)
593 ecode = code;
594
595 switch (code = param_read_bool(plist, (param_name = ".LockSafetyParams"), &locksafe)) {
596 case 0:
597 if (dev->LockSafetyParams && !locksafe)
598 code = gs_note_error(gs_error_invalidaccess);
599 else
600 break;
601 default:
602 ecode = code;
603 param_signal_error(plist, param_name, ecode);
604 case 1:
605 break;
606 }
607 /* Ignore parameters that only have meaning for printers. */
608 #define IGNORE_INT_PARAM(pname)\
609 { int igni;\
610 switch ( code = param_read_int(plist, (param_name = pname), &igni) )\
611 { default:\
612 ecode = code;\
613 param_signal_error(plist, param_name, ecode);\
614 case 0:\
615 case 1:\
616 break;\
617 }\
618 }
619 IGNORE_INT_PARAM("%MediaSource")
620 IGNORE_INT_PARAM("%MediaDestination")
621 switch (code = param_read_float_array(plist, (param_name = "ImagingBBox"), &ibba)) {
622 case 0:
623 if (ibba.size != 4 ||
624 ibba.data[2] < ibba.data[0] || ibba.data[3] < ibba.data[1]
625 )
626 ecode = gs_note_error(gs_error_rangecheck);
627 else
628 break;
629 goto ibbe;
630 default:
631 if ((code = param_read_null(plist, param_name)) == 0) {
632 ibbnull = true;
633 ibba.data = 0;
634 break;
635 }
636 ecode = code; /* can't be 1 */
637 ibbe:param_signal_error(plist, param_name, ecode);
638 case 1:
639 ibba.data = 0;
640 break;
641 }
642
643 /* Now check nominally read-only parameters. */
644 if ((code = param_check_string(plist, "OutputDevice", dev->dname, true)) < 0)
645 ecode = code;
646 if ((code = param_check_string(plist, "ProcessColorModel", pcmsa[colors], colors != 0)) < 0)
647 ecode = code;
648 if ((code = param_check_int(plist, "MaxSeparations", 1, true)) < 0)
649 ecode = code;
650 if ((code = param_check_bool(plist, "Separations", false, true)) < 0)
651 ecode = code;
652 BEGIN_ARRAY_PARAM(param_read_name_array, "SeparationColorNames", scna, 0, scne) {
653 break;
654 } END_ARRAY_PARAM(scna, scne);
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, colors > 1)) < 0)
666 ecode = code;
667 if ((code = param_check_int(plist, "GreenValues", RGBValues, colors > 1)) < 0)
668 ecode = code;
669 if ((code = param_check_int(plist, "BlueValues", RGBValues, colors > 1)) < 0)
670 ecode = code;
671 if ((code = param_check_long(plist, "ColorValues", ColorValues, colors > 1)) < 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 defined)806 param_check_bool(gs_param_list * plist, gs_param_name pname, bool value,
807 bool 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 (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 defined)828 param_check_long(gs_param_list * plist, gs_param_name pname, long value,
829 bool 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 (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 defined)850 param_check_bytes(gs_param_list * plist, gs_param_name pname, const byte * str,
851 uint size, bool 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 (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