summaryrefslogtreecommitdiff
path: root/gs/base/gsdparam.c
diff options
context:
space:
mode:
Diffstat (limited to 'gs/base/gsdparam.c')
-rw-r--r--gs/base/gsdparam.c955
1 files changed, 955 insertions, 0 deletions
diff --git a/gs/base/gsdparam.c b/gs/base/gsdparam.c
new file mode 100644
index 000000000..4ff1f2dc6
--- /dev/null
+++ b/gs/base/gsdparam.c
@@ -0,0 +1,955 @@
+/* Copyright (C) 2001-2006 Artifex Software, Inc.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+/* $Id$ */
+/* Default device parameters for Ghostscript library */
+#include "memory_.h" /* for memcpy */
+#include "string_.h" /* for strlen */
+#include "gx.h"
+#include "gserrors.h"
+#include "gsdevice.h" /* for prototypes */
+#include "gsparam.h"
+#include "gxdevice.h"
+#include "gxfixed.h"
+
+/* Define whether we accept PageSize as a synonym for MediaSize. */
+/* This is for backward compatibility only. */
+#define PAGESIZE_IS_MEDIASIZE
+
+/* ================ Getting parameters ================ */
+
+/* Forward references */
+static bool param_HWColorMap(gx_device *, byte *);
+
+/* Get the device parameters. */
+int
+gs_get_device_or_hw_params(gx_device * orig_dev, gs_param_list * plist,
+ bool is_hardware)
+{
+ /*
+ * We must be prepared to copy the device if it is the read-only
+ * prototype.
+ */
+ gx_device *dev;
+ int code;
+
+ if (orig_dev->memory)
+ dev = orig_dev;
+ else {
+ code = gs_copydevice(&dev, orig_dev, plist->memory);
+ if (code < 0)
+ return code;
+ }
+ gx_device_set_procs(dev);
+ fill_dev_proc(dev, get_params, gx_default_get_params);
+ fill_dev_proc(dev, get_page_device, gx_default_get_page_device);
+ fill_dev_proc(dev, get_alpha_bits, gx_default_get_alpha_bits);
+ code = (is_hardware ?
+ (*dev_proc(dev, get_hardware_params)) (dev, plist) :
+ (*dev_proc(dev, get_params)) (dev, plist));
+ if (dev != orig_dev)
+ gx_device_retain(dev, false); /* frees the copy */
+ return code;
+}
+
+/* Get standard parameters. */
+int
+gx_default_get_params(gx_device * dev, gs_param_list * plist)
+{
+ int code;
+
+ /* Standard page device parameters: */
+
+ bool seprs = false;
+ gs_param_string dns, pcms;
+ gs_param_float_array msa, ibba, hwra, ma;
+ gs_param_string_array scna;
+
+#define set_param_array(a, d, s)\
+ (a.data = d, a.size = s, a.persistent = false);
+
+ /* Non-standard parameters: */
+
+ int colors = dev->color_info.num_components;
+ int mns = colors;
+ int depth = dev->color_info.depth;
+ int GrayValues = dev->color_info.max_gray + 1;
+ int HWSize[2];
+ gs_param_int_array hwsa;
+ gs_param_float_array hwma, mhwra;
+
+ /* Fill in page device parameters. */
+
+ param_string_from_string(dns, dev->dname);
+ {
+ const char *cms = get_process_color_model_name(dev);
+
+ /* We might have an uninitialized device with */
+ /* color_info.num_components = 0.... */
+ if ((cms != NULL) && (*cms != '\0'))
+ param_string_from_string(pcms, cms);
+ else
+ pcms.data = 0;
+ }
+ set_param_array(hwra, dev->HWResolution, 2);
+ set_param_array(msa, dev->MediaSize, 2);
+ set_param_array(ibba, dev->ImagingBBox, 4);
+ set_param_array(ma, dev->Margins, 2);
+ set_param_array(scna, NULL, 0);
+
+ /* Fill in non-standard parameters. */
+
+ HWSize[0] = dev->width;
+ HWSize[1] = dev->height;
+ set_param_array(hwsa, HWSize, 2);
+ set_param_array(hwma, dev->HWMargins, 4);
+ set_param_array(mhwra, dev->MarginsHWResolution, 2);
+
+ /* Transmit the values. */
+
+ if (
+
+ /* Standard parameters */
+
+ (code = param_write_name(plist, "OutputDevice", &dns)) < 0 ||
+#ifdef PAGESIZE_IS_MEDIASIZE
+ (code = param_write_float_array(plist, "PageSize", &msa)) < 0 ||
+#endif
+ (code = (pcms.data == 0 ? 0 :
+ param_write_name(plist, "ProcessColorModel", &pcms))) < 0 ||
+ (code = param_write_float_array(plist, "HWResolution", &hwra)) < 0 ||
+ (code = (dev->ImagingBBox_set ?
+ param_write_float_array(plist, "ImagingBBox", &ibba) :
+ param_write_null(plist, "ImagingBBox"))) < 0 ||
+ (code = param_write_float_array(plist, "Margins", &ma)) < 0 ||
+ (code = param_write_int(plist, "MaxSeparations", &mns)) < 0 ||
+ (code = (dev->NumCopies_set < 0 ||
+ (*dev_proc(dev, get_page_device))(dev) == 0 ? 0:
+ dev->NumCopies_set ?
+ param_write_int(plist, "NumCopies", &dev->NumCopies) :
+ param_write_null(plist, "NumCopies"))) < 0 ||
+ (code = param_write_name_array(plist, "SeparationColorNames", &scna)) < 0 ||
+ (code = param_write_bool(plist, "Separations", &seprs)) < 0 ||
+ (code = param_write_bool(plist, "UseCIEColor", &dev->UseCIEColor)) < 0 ||
+
+ /* Non-standard parameters */
+
+ (code = param_write_int_array(plist, "HWSize", &hwsa)) < 0 ||
+ (code = param_write_float_array(plist, ".HWMargins", &hwma)) < 0 ||
+ (code = param_write_float_array(plist, ".MarginsHWResolution", &mhwra)) < 0 ||
+ (code = param_write_float_array(plist, ".MediaSize", &msa)) < 0 ||
+ (code = param_write_string(plist, "Name", &dns)) < 0 ||
+ (code = param_write_int(plist, "Colors", &colors)) < 0 ||
+ (code = param_write_int(plist, "BitsPerPixel", &depth)) < 0 ||
+ (code = param_write_int(plist, "GrayValues", &GrayValues)) < 0 ||
+ (code = param_write_long(plist, "PageCount", &dev->PageCount)) < 0 ||
+ (code = param_write_bool(plist, ".IgnoreNumCopies", &dev->IgnoreNumCopies)) < 0 ||
+ (code = param_write_int(plist, "TextAlphaBits",
+ &dev->color_info.anti_alias.text_bits)) < 0 ||
+ (code = param_write_int(plist, "GraphicsAlphaBits",
+ &dev->color_info.anti_alias.graphics_bits)) < 0 ||
+ (code = param_write_bool(plist, ".LockSafetyParams", &dev->LockSafetyParams)) < 0
+ )
+ return code;
+
+ /* If LeadingEdge was set explicitly, report it here. */
+ if (dev->LeadingEdge & LEADINGEDGE_SET_MASK) {
+ int leadingedge = dev->LeadingEdge & LEADINGEDGE_MASK;
+ code = param_write_int(plist, "LeadingEdge", &leadingedge);
+ }
+ if (code < 0)
+ return code;
+
+ /* Fill in color information. */
+
+ if (colors > 1) {
+ int RGBValues = dev->color_info.max_color + 1;
+ long ColorValues = (depth >= 32 ? -1 : 1L << depth); /* value can only be 32 bits */
+
+ if ((code = param_write_int(plist, "RedValues", &RGBValues)) < 0 ||
+ (code = param_write_int(plist, "GreenValues", &RGBValues)) < 0 ||
+ (code = param_write_int(plist, "BlueValues", &RGBValues)) < 0 ||
+ (code = param_write_long(plist, "ColorValues", &ColorValues)) < 0
+ )
+ return code;
+ }
+ if (param_requested(plist, "HWColorMap")) {
+ byte palette[3 << 8];
+
+ if (param_HWColorMap(dev, palette)) {
+ gs_param_string hwcms;
+
+ hwcms.data = palette, hwcms.size = colors << depth,
+ hwcms.persistent = false;
+ if ((code = param_write_string(plist, "HWColorMap", &hwcms)) < 0)
+ return code;
+ }
+ }
+
+ return 0;
+}
+
+/* Get the color map for a device. Return true if there is one. */
+static bool
+param_HWColorMap(gx_device * dev, byte * palette /* 3 << 8 */ )
+{
+ int depth = dev->color_info.depth;
+ int colors = dev->color_info.num_components;
+
+ if (depth <= 8 && colors <= 3) {
+ byte *p = palette;
+ gx_color_value rgb[3];
+ gx_color_index i;
+
+ fill_dev_proc(dev, map_color_rgb, gx_default_map_color_rgb);
+ for (i = 0; (i >> depth) == 0; i++) {
+ int j;
+
+ if ((*dev_proc(dev, map_color_rgb)) (dev, i, rgb) < 0)
+ return false;
+ for (j = 0; j < colors; j++)
+ *p++ = gx_color_value_to_byte(rgb[j]);
+ }
+ return true;
+ }
+ return false;
+}
+
+/* Get hardware-detected parameters. Default action is no hardware params. */
+int
+gx_default_get_hardware_params(gx_device * dev, gs_param_list * plist)
+{
+ return 0;
+}
+
+/* ---------------- Input and output media ---------------- */
+
+/* Finish defining input or output media. */
+static int
+finish_media(gs_param_list * mlist, gs_param_name key, const char *media_type)
+{
+ int code = 0;
+
+ if (media_type != 0) {
+ gs_param_string as;
+
+ param_string_from_string(as, media_type);
+ code = param_write_string(mlist, key, &as);
+ }
+ return code;
+}
+
+/* Define input media. */
+
+const gdev_input_media_t gdev_input_media_default =
+{
+ gdev_input_media_default_values
+};
+
+int
+gdev_begin_input_media(gs_param_list * mlist, gs_param_dict * pdict,
+ int count)
+{
+ pdict->size = count;
+ return param_begin_write_dict(mlist, "InputAttributes", pdict, true);
+}
+
+int
+gdev_write_input_media(int index, gs_param_dict * pdict,
+ const gdev_input_media_t * pim)
+{
+ char key[25];
+ gs_param_dict mdict;
+ int code;
+ gs_param_string as;
+
+ sprintf(key, "%d", index);
+ mdict.size = 4;
+ code = param_begin_write_dict(pdict->list, key, &mdict, false);
+ if (code < 0)
+ return code;
+ if ((pim->PageSize[0] != 0 && pim->PageSize[1] != 0) ||
+ (pim->PageSize[2] != 0 && pim->PageSize[3] != 0)
+ ) {
+ gs_param_float_array psa;
+
+ psa.data = pim->PageSize;
+ psa.size =
+ (pim->PageSize[0] == pim->PageSize[2] &&
+ pim->PageSize[1] == pim->PageSize[3] ? 2 : 4);
+ psa.persistent = false;
+ code = param_write_float_array(mdict.list, "PageSize",
+ &psa);
+ if (code < 0)
+ return code;
+ }
+ if (pim->MediaColor != 0) {
+ param_string_from_string(as, pim->MediaColor);
+ code = param_write_string(mdict.list, "MediaColor",
+ &as);
+ if (code < 0)
+ return code;
+ }
+ if (pim->MediaWeight != 0) {
+ /*
+ * We do the following silly thing in order to avoid
+ * having to work around the 'const' in the arg list.
+ */
+ float weight = pim->MediaWeight;
+
+ code = param_write_float(mdict.list, "MediaWeight",
+ &weight);
+ if (code < 0)
+ return code;
+ }
+ code = finish_media(mdict.list, "MediaType", pim->MediaType);
+ if (code < 0)
+ return code;
+ return param_end_write_dict(pdict->list, key, &mdict);
+}
+
+int
+gdev_write_input_page_size(int index, gs_param_dict * pdict,
+ floatp width_points, floatp height_points)
+{
+ gdev_input_media_t media;
+
+ media.PageSize[0] = media.PageSize[2] = (float) width_points;
+ media.PageSize[1] = media.PageSize[3] = (float) height_points;
+ media.MediaColor = 0;
+ media.MediaWeight = 0;
+ media.MediaType = 0;
+ return gdev_write_input_media(index, pdict, &media);
+}
+
+int
+gdev_end_input_media(gs_param_list * mlist, gs_param_dict * pdict)
+{
+ return param_end_write_dict(mlist, "InputAttributes", pdict);
+}
+
+/* Define output media. */
+
+const gdev_output_media_t gdev_output_media_default =
+{
+ gdev_output_media_default_values
+};
+
+int
+gdev_begin_output_media(gs_param_list * mlist, gs_param_dict * pdict,
+ int count)
+{
+ pdict->size = count;
+ return param_begin_write_dict(mlist, "OutputAttributes", pdict, true);
+}
+
+int
+gdev_write_output_media(int index, gs_param_dict * pdict,
+ const gdev_output_media_t * pom)
+{
+ char key[25];
+ gs_param_dict mdict;
+ int code;
+
+ sprintf(key, "%d", index);
+ mdict.size = 4;
+ code = param_begin_write_dict(pdict->list, key, &mdict, false);
+ if (code < 0)
+ return code;
+ code = finish_media(mdict.list, "OutputType", pom->OutputType);
+ if (code < 0)
+ return code;
+ return param_end_write_dict(pdict->list, key, &mdict);
+}
+
+int
+gdev_end_output_media(gs_param_list * mlist, gs_param_dict * pdict)
+{
+ return param_end_write_dict(mlist, "OutputAttributes", pdict);
+}
+
+/* ================ Putting parameters ================ */
+
+/* Forward references */
+static int param_normalize_anti_alias_bits( uint max_gray, int bits );
+static int param_anti_alias_bits(gs_param_list *, gs_param_name, int *);
+static int param_MediaSize(gs_param_list *, gs_param_name,
+ const float *, gs_param_float_array *);
+
+static int param_check_bool(gs_param_list *, gs_param_name, bool, bool);
+static int param_check_long(gs_param_list *, gs_param_name, long, bool);
+#define param_check_int(plist, pname, ival, is_defined)\
+ param_check_long(plist, pname, (long)(ival), is_defined)
+static int param_check_bytes(gs_param_list *, gs_param_name, const byte *,
+ uint, bool);
+#define param_check_string(plist, pname, str, is_defined)\
+ param_check_bytes(plist, pname, (const byte *)(str), \
+ (is_defined) ? strlen(str) : 0, is_defined)
+
+/* Set the device parameters. */
+/* If the device was open and the put_params procedure closed it, */
+/* return 1; otherwise, return 0 or an error code as usual. */
+int
+gs_putdeviceparams(gx_device * dev, gs_param_list * plist)
+{
+ bool was_open = dev->is_open;
+ int code;
+
+ gx_device_set_procs(dev);
+ fill_dev_proc(dev, put_params, gx_default_put_params);
+ fill_dev_proc(dev, get_alpha_bits, gx_default_get_alpha_bits);
+ code = (*dev_proc(dev, put_params)) (dev, plist);
+ return (code < 0 ? code : was_open && !dev->is_open ? 1 : code);
+}
+
+/* Set standard parameters. */
+/* Note that setting the size or resolution closes the device. */
+/* Window devices that don't want this to happen must temporarily */
+/* set is_open to false before calling gx_default_put_params, */
+/* and then taking appropriate action afterwards. */
+int
+gx_default_put_params(gx_device * dev, gs_param_list * plist)
+{
+ int ecode = 0;
+ int code;
+ gs_param_name param_name;
+ gs_param_float_array hwra;
+ gs_param_int_array hwsa;
+ gs_param_float_array msa;
+ gs_param_float_array ma;
+ gs_param_float_array hwma;
+ gs_param_float_array mhwra;
+ gs_param_string_array scna;
+ int nci = dev->NumCopies;
+ int ncset = dev->NumCopies_set;
+ bool ignc = dev->IgnoreNumCopies;
+ bool ucc = dev->UseCIEColor;
+ bool locksafe = dev->LockSafetyParams;
+ gs_param_float_array ibba;
+ bool ibbnull = false;
+ int colors = dev->color_info.num_components;
+ int depth = dev->color_info.depth;
+ int GrayValues = dev->color_info.max_gray + 1;
+ int RGBValues = dev->color_info.max_color + 1;
+ long ColorValues = (depth >= 32 ? -1 : 1L << depth);
+ int tab = dev->color_info.anti_alias.text_bits;
+ int gab = dev->color_info.anti_alias.graphics_bits;
+ gs_param_string cms;
+ int leadingedge = dev->LeadingEdge;
+
+ /*
+ * Template:
+ * BEGIN_ARRAY_PARAM(param_read_xxx_array, "pname", pxxa, size, pxxe) {
+ * ... check value if desired ...
+ * if (success)
+ * break;
+ * ... set ecode ...
+ * } END_ARRAY_PARAM(pxxa, pxxe);
+ */
+
+#define BEGIN_ARRAY_PARAM(pread, pname, pa, psize, e)\
+ BEGIN\
+ switch (code = pread(plist, (param_name = pname), &(pa))) {\
+ case 0:\
+ if ((pa).size != psize) {\
+ ecode = gs_note_error(gs_error_rangecheck);\
+ (pa).data = 0; /* mark as not filled */\
+ } else
+#define END_ARRAY_PARAM(pa, e)\
+ goto e;\
+ default:\
+ ecode = code;\
+e: param_signal_error(plist, param_name, ecode);\
+ case 1:\
+ (pa).data = 0; /* mark as not filled */\
+ }\
+ END
+
+ /*
+ * The actual value of LeadingEdge must be changed inside this routine,
+ * so that we can detect that it has been changed. Thus, instead of a
+ * device setting the value itself, it signals a request, which is
+ * now executed.
+ */
+ if (leadingedge & LEADINGEDGE_REQ_BIT) {
+ leadingedge = (leadingedge & LEADINGEDGE_SET_MASK) |
+ ((leadingedge >> LEADINGEDGE_REQ_VAL_SHIFT) & LEADINGEDGE_MASK);
+ }
+
+ /*
+ * The HWResolution, HWSize, and MediaSize parameters interact in
+ * the following way:
+ * 1. Setting HWResolution recomputes HWSize from MediaSize.
+ * 2. Setting HWSize recomputes MediaSize from HWResolution.
+ * 3. Setting MediaSize recomputes HWSize from HWResolution.
+ * If more than one parameter is being set, we apply these rules
+ * in the order 1, 2, 3. This does the right thing in the most
+ * common case of setting more than one parameter, namely,
+ * setting both HWResolution and HWSize.
+ *
+ * Changing of LeadingEdge is treated exactly the same as a
+ * change in HWResolution. In typical usage, MediaSize is
+ * short-edge (MediaSize[0] < MediaSize[1]), so if LeadingEdge
+ * is 1 or 3, then HWSize will become long-edge. For nonsquare
+ * resolutions, HWResolution[0] always corresponds with width
+ * (scan length), and [1] with height (number of scans).
+ */
+
+ BEGIN_ARRAY_PARAM(param_read_float_array, "HWResolution", hwra, 2, hwre) {
+ if (hwra.data[0] <= 0 || hwra.data[1] <= 0)
+ ecode = gs_note_error(gs_error_rangecheck);
+ else
+ break;
+ } END_ARRAY_PARAM(hwra, hwre);
+ BEGIN_ARRAY_PARAM(param_read_int_array, "HWSize", hwsa, 2, hwsa) {
+ /* We need a special check to handle the nullpage device, */
+ /* whose size is legitimately [0 0]. */
+ if ((hwsa.data[0] <= 0 && hwsa.data[0] != dev->width) ||
+ (hwsa.data[1] <= 0 && hwsa.data[1] != dev->height)
+ )
+ ecode = gs_note_error(gs_error_rangecheck);
+#define max_coord (max_fixed / fixed_1)
+#if max_coord < max_int
+ else if (hwsa.data[0] > max_coord || hwsa.data[1] > max_coord)
+ ecode = gs_note_error(gs_error_limitcheck);
+#endif
+#undef max_coord
+ else
+ break;
+ } END_ARRAY_PARAM(hwsa, hwse);
+ {
+ int t;
+
+ code = param_read_int(plist, "LeadingEdge", &t);
+ if (code < 0) {
+ if (param_read_null(plist, "LeadingEdge") == 0) {
+ /* if param is null, clear explicitly-set flag */
+ leadingedge &= ~LEADINGEDGE_SET_MASK;
+ code = 0;
+ } else {
+ ecode = code;
+ }
+ } else if (code == 0) {
+ if (t < 0 || t > 3)
+ param_signal_error(plist, "LeadingEdge",
+ ecode = gs_error_rangecheck);
+ else
+ leadingedge = LEADINGEDGE_SET_MASK | t;
+ }
+ }
+ {
+ const float *res = (hwra.data == 0 ? dev->HWResolution : hwra.data);
+
+#ifdef PAGESIZE_IS_MEDIASIZE
+ const float *data;
+
+ /* .MediaSize takes precedence over PageSize, so */
+ /* we read PageSize first. */
+ code = param_MediaSize(plist, "PageSize", res, &msa);
+ if (code < 0)
+ ecode = code;
+ /* Prevent data from being set to 0 if PageSize is specified */
+ /* but .MediaSize is not. */
+ data = msa.data;
+ code = param_MediaSize(plist, ".MediaSize", res, &msa);
+ if (code < 0)
+ ecode = code;
+ else if (msa.data == 0)
+ msa.data = data;
+#else
+ code = param_MediaSize(plist, ".MediaSize", res, &msa);
+ if (code < 0)
+ ecode = code;
+#endif
+ }
+
+ BEGIN_ARRAY_PARAM(param_read_float_array, "Margins", ma, 2, me) {
+ break;
+ } END_ARRAY_PARAM(ma, me);
+ BEGIN_ARRAY_PARAM(param_read_float_array, ".HWMargins", hwma, 4, hwme) {
+ break;
+ } END_ARRAY_PARAM(hwma, hwme);
+ /* MarginsHWResolution cannot be changed, only checked. */
+ BEGIN_ARRAY_PARAM(param_read_float_array, ".MarginsHWResolution", mhwra, 2, mhwre) {
+ if (mhwra.data[0] != dev->MarginsHWResolution[0] ||
+ mhwra.data[1] != dev->MarginsHWResolution[1]
+ )
+ ecode = gs_note_error(gs_error_rangecheck);
+ else
+ break;
+ } END_ARRAY_PARAM(mhwra, mhwre);
+ switch (code = param_read_bool(plist, (param_name = ".IgnoreNumCopies"), &ignc)) {
+ default:
+ ecode = code;
+ param_signal_error(plist, param_name, ecode);
+ case 0:
+ case 1:
+ break;
+ }
+ if (dev->NumCopies_set >= 0 &&
+ (*dev_proc(dev, get_page_device))(dev) != 0
+ ) {
+ switch (code = param_read_int(plist, (param_name = "NumCopies"), &nci)) {
+ case 0:
+ if (nci < 0)
+ ecode = gs_error_rangecheck;
+ else {
+ ncset = 1;
+ break;
+ }
+ goto nce;
+ default:
+ if ((code = param_read_null(plist, param_name)) == 0) {
+ ncset = 0;
+ break;
+ }
+ ecode = code; /* can't be 1 */
+nce:
+ param_signal_error(plist, param_name, ecode);
+ case 1:
+ break;
+ }
+ }
+ if ((code = param_read_bool(plist, (param_name = "UseCIEColor"), &ucc)) < 0) {
+ ecode = code;
+ param_signal_error(plist, param_name, ecode);
+ }
+ if ((code = param_anti_alias_bits(plist, "TextAlphaBits", &tab)) < 0)
+ ecode = code;
+ if ((code = param_anti_alias_bits(plist, "GraphicsAlphaBits", &gab)) < 0)
+ ecode = code;
+
+ switch (code = param_read_bool(plist, (param_name = ".LockSafetyParams"), &locksafe)) {
+ case 0:
+ if (dev->LockSafetyParams && !locksafe)
+ code = gs_note_error(gs_error_invalidaccess);
+ else
+ break;
+ default:
+ ecode = code;
+ param_signal_error(plist, param_name, ecode);
+ case 1:
+ break;
+ }
+ /* Ignore parameters that only have meaning for printers. */
+#define IGNORE_INT_PARAM(pname)\
+ { int igni;\
+ switch ( code = param_read_int(plist, (param_name = pname), &igni) )\
+ { default:\
+ ecode = code;\
+ param_signal_error(plist, param_name, ecode);\
+ case 0:\
+ case 1:\
+ break;\
+ }\
+ }
+ IGNORE_INT_PARAM("%MediaSource")
+ IGNORE_INT_PARAM("%MediaDestination")
+ switch (code = param_read_float_array(plist, (param_name = "ImagingBBox"), &ibba)) {
+ case 0:
+ if (ibba.size != 4 ||
+ ibba.data[2] < ibba.data[0] || ibba.data[3] < ibba.data[1]
+ )
+ ecode = gs_note_error(gs_error_rangecheck);
+ else
+ break;
+ goto ibbe;
+ default:
+ if ((code = param_read_null(plist, param_name)) == 0) {
+ ibbnull = true;
+ ibba.data = 0;
+ break;
+ }
+ ecode = code; /* can't be 1 */
+ ibbe:param_signal_error(plist, param_name, ecode);
+ case 1:
+ ibba.data = 0;
+ break;
+ }
+
+ /* Separation, DeviceN Color, and ProcessColorModel related parameters. */
+ {
+ const char * pcms = get_process_color_model_name(dev);
+ /* the device should have set a process model name at this point */
+ if ((code = param_check_string(plist, "ProcessColorModel", pcms, (pcms != NULL))) < 0)
+ ecode = code;
+ }
+ IGNORE_INT_PARAM("MaxSeparations")
+ if ((code = param_check_bool(plist, "Separations", false, true)) < 0)
+ ecode = code;
+
+ BEGIN_ARRAY_PARAM(param_read_name_array, "SeparationColorNames", scna, scna.size, scne) {
+ break;
+ } END_ARRAY_PARAM(scna, scne);
+
+
+ /* Now check nominally read-only parameters. */
+ if ((code = param_check_string(plist, "OutputDevice", dev->dname, true)) < 0)
+ ecode = code;
+ if ((code = param_check_string(plist, "Name", dev->dname, true)) < 0)
+ ecode = code;
+ if ((code = param_check_int(plist, "Colors", colors, true)) < 0)
+ ecode = code;
+ if ((code = param_check_int(plist, "BitsPerPixel", depth, true)) < 0)
+ ecode = code;
+ if ((code = param_check_int(plist, "GrayValues", GrayValues, true)) < 0)
+ ecode = code;
+ if ((code = param_check_long(plist, "PageCount", dev->PageCount, true)) < 0)
+ ecode = code;
+ if ((code = param_check_int(plist, "RedValues", RGBValues, true)) < 0)
+ ecode = code;
+ if ((code = param_check_int(plist, "GreenValues", RGBValues, true)) < 0)
+ ecode = code;
+ if ((code = param_check_int(plist, "BlueValues", RGBValues, true)) < 0)
+ ecode = code;
+ if ((code = param_check_long(plist, "ColorValues", ColorValues, true)) < 0)
+ ecode = code;
+ if (param_read_string(plist, "HWColorMap", &cms) != 1) {
+ byte palette[3 << 8];
+
+ if (param_HWColorMap(dev, palette))
+ code = param_check_bytes(plist, "HWColorMap", palette,
+ colors << depth, true);
+ else
+ code = param_check_bytes(plist, "HWColorMap", 0, 0, false);
+ if (code < 0)
+ ecode = code;
+ }
+
+ /* We must 'commit', in order to detect unknown parameters, */
+ /* even if there were errors. */
+ code = param_commit(plist);
+ if (ecode < 0)
+ return ecode;
+ if (code < 0)
+ return code;
+
+ /*
+ * Now actually make the changes. Changing resolution, rotation
+ * (through LeadingEdge) or page size requires closing the device,
+ * but changing margins or ImagingBBox does not. In order not to
+ * close and reopen the device unnecessarily, we check for
+ * replacing the values with the same ones.
+ */
+
+ if (hwra.data != 0 &&
+ (dev->HWResolution[0] != hwra.data[0] ||
+ dev->HWResolution[1] != hwra.data[1])
+ ) {
+ if (dev->is_open)
+ gs_closedevice(dev);
+ gx_device_set_resolution(dev, hwra.data[0], hwra.data[1]);
+ }
+ if ((leadingedge & LEADINGEDGE_MASK) !=
+ (dev->LeadingEdge & LEADINGEDGE_MASK)) {
+ /* If the LeadingEdge_set flag changes but the value of LeadingEdge
+ itself does not, don't close device and recompute page size. */
+ dev->LeadingEdge = leadingedge;
+ if (dev->is_open)
+ gs_closedevice(dev);
+ gx_device_set_resolution(dev, dev->HWResolution[0], dev->HWResolution[1]);
+ }
+ /* clear leadingedge request, preserve "set" flag */
+ dev->LeadingEdge &= LEADINGEDGE_MASK;
+ dev->LeadingEdge |= (leadingedge & LEADINGEDGE_SET_MASK);
+
+ if (hwsa.data != 0 &&
+ (dev->width != hwsa.data[0] ||
+ dev->height != hwsa.data[1])
+ ) {
+ if (dev->is_open)
+ gs_closedevice(dev);
+ gx_device_set_width_height(dev, hwsa.data[0], hwsa.data[1]);
+ }
+ if (msa.data != 0 &&
+ (dev->MediaSize[0] != msa.data[0] ||
+ dev->MediaSize[1] != msa.data[1])
+ ) {
+ if (dev->is_open)
+ gs_closedevice(dev);
+ gx_device_set_page_size(dev, msa.data[0], msa.data[1]);
+ }
+ if (ma.data != 0) {
+ dev->Margins[0] = ma.data[0];
+ dev->Margins[1] = ma.data[1];
+ }
+ if (hwma.data != 0) {
+ dev->HWMargins[0] = hwma.data[0];
+ dev->HWMargins[1] = hwma.data[1];
+ dev->HWMargins[2] = hwma.data[2];
+ dev->HWMargins[3] = hwma.data[3];
+ }
+ dev->NumCopies = nci;
+ dev->NumCopies_set = ncset;
+ dev->IgnoreNumCopies = ignc;
+ if (ibba.data != 0) {
+ dev->ImagingBBox[0] = ibba.data[0];
+ dev->ImagingBBox[1] = ibba.data[1];
+ dev->ImagingBBox[2] = ibba.data[2];
+ dev->ImagingBBox[3] = ibba.data[3];
+ dev->ImagingBBox_set = true;
+ } else if (ibbnull) {
+ dev->ImagingBBox_set = false;
+ }
+ dev->UseCIEColor = ucc;
+ dev->color_info.anti_alias.text_bits =
+ param_normalize_anti_alias_bits(max(dev->color_info.max_gray,
+ dev->color_info.max_color), tab);
+ dev->color_info.anti_alias.graphics_bits =
+ param_normalize_anti_alias_bits(max(dev->color_info.max_gray,
+ dev->color_info.max_color), gab);
+ dev->LockSafetyParams = locksafe;
+ gx_device_decache_colors(dev);
+ return 0;
+}
+
+void
+gx_device_request_leadingedge(gx_device *dev, int le_req)
+{
+ dev->LeadingEdge = (dev->LeadingEdge & ~LEADINGEDGE_REQ_VAL) |
+ ((le_req << LEADINGEDGE_REQ_VAL_SHIFT) & LEADINGEDGE_REQ_VAL) |
+ LEADINGEDGE_REQ_BIT;
+}
+
+/* Limit the anti-alias bit values to the maximum legal value for the
+ * current color depth.
+ */
+static int
+param_normalize_anti_alias_bits( uint max_gray, int bits )
+{
+ int max_bits = ilog2( max_gray + 1);
+
+ return (bits > max_bits ? max_bits : bits);
+}
+
+/* Read TextAlphaBits or GraphicsAlphaBits. */
+static int
+param_anti_alias_bits(gs_param_list * plist, gs_param_name param_name, int *pa)
+{
+ int code = param_read_int(plist, param_name, pa);
+
+ switch (code) {
+ case 0:
+ switch (*pa) {
+ case 1: case 2: case 4:
+ return 0;
+ default:
+ code = gs_error_rangecheck;
+ }
+ default:
+ param_signal_error(plist, param_name, code);
+ case 1:
+ ;
+ }
+ return code;
+}
+
+
+/* Read .MediaSize or, if supported as a synonym, PageSize. */
+static int
+param_MediaSize(gs_param_list * plist, gs_param_name pname,
+ const float *res, gs_param_float_array * pa)
+{
+ gs_param_name param_name;
+ int ecode = 0;
+ int code;
+
+ BEGIN_ARRAY_PARAM(param_read_float_array, pname, *pa, 2, mse) {
+ float width_new = pa->data[0] * res[0] / 72;
+ float height_new = pa->data[1] * res[1] / 72;
+
+ if (width_new < 0 || height_new < 0)
+ ecode = gs_note_error(gs_error_rangecheck);
+#define max_coord (max_fixed / fixed_1)
+#if max_coord < max_int
+ else if (width_new > max_coord || height_new > max_coord)
+ ecode = gs_note_error(gs_error_limitcheck);
+#endif
+#undef max_coord
+ else
+ break;
+ } END_ARRAY_PARAM(*pa, mse);
+ return ecode;
+}
+
+/* Check that a nominally read-only parameter is being set to */
+/* its existing value. */
+static int
+param_check_bool(gs_param_list * plist, gs_param_name pname, bool value,
+ bool is_defined)
+{
+ int code;
+ bool new_value;
+
+ switch (code = param_read_bool(plist, pname, &new_value)) {
+ case 0:
+ if (is_defined && new_value == value)
+ break;
+ code = gs_note_error(gs_error_rangecheck);
+ goto e;
+ default:
+ if (param_read_null(plist, pname) == 0)
+ return 1;
+ e:param_signal_error(plist, pname, code);
+ case 1:
+ ;
+ }
+ return code;
+}
+static int
+param_check_long(gs_param_list * plist, gs_param_name pname, long value,
+ bool is_defined)
+{
+ int code;
+ long new_value;
+
+ switch (code = param_read_long(plist, pname, &new_value)) {
+ case 0:
+ if (is_defined && new_value == value)
+ break;
+ code = gs_note_error(gs_error_rangecheck);
+ goto e;
+ default:
+ if (param_read_null(plist, pname) == 0)
+ return 1;
+ e:param_signal_error(plist, pname, code);
+ case 1:
+ ;
+ }
+ return code;
+}
+static int
+param_check_bytes(gs_param_list * plist, gs_param_name pname, const byte * str,
+ uint size, bool is_defined)
+{
+ int code;
+ gs_param_string new_value;
+
+ switch (code = param_read_string(plist, pname, &new_value)) {
+ case 0:
+ if (is_defined && new_value.size == size &&
+ !memcmp((const char *)str, (const char *)new_value.data,
+ size)
+ )
+ break;
+ code = gs_note_error(gs_error_rangecheck);
+ goto e;
+ default:
+ if (param_read_null(plist, pname) == 0)
+ return 1;
+ e:param_signal_error(plist, pname, code);
+ case 1:
+ ;
+ }
+ return code;
+}