summaryrefslogtreecommitdiff
path: root/psi/zcolor.c
diff options
context:
space:
mode:
authorKen Sharp <ken.sharp@artifex.com>2019-05-08 14:27:23 +0100
committerKen Sharp <ken.sharp@artifex.com>2019-05-08 15:27:28 +0100
commit2019db2e552653bd0c27377d500de1041c9fd0bc (patch)
treec7a6548ce721248c83e5d47ea532281bf7c5fdad /psi/zcolor.c
parent0d75869134c69963406500b536fb1bb1c97c8621 (diff)
downloadghostpdl-2019db2e552653bd0c27377d500de1041c9fd0bc.tar.gz
PostScript colour space handling
We were not catering for a /Subtype in a DeviceN attributes dictionary having a value which is a string type not a name type. I can't quite see how we are ending up with a string type here, since the PDF file has it as a name, but it does. Dealing with both resolves many errors. The second change is more far-reaching; when processing an attributes dictionary for a DeviceN colour space we may need to create colour spaces for the Process dictionary /ColorSpace and for any of the entries in the Colorants dictionary. We were doing that by calling zsetcolorspace() which mostly works well, however there is one optimisation which can cause a problem; if the target space is the same as the current *interpreter* colour space, then zsetcolorspace() simply returns. The problem is that if we are halfway through processing a DeviceN space then we haven't set the interpreter space to the new colour space array yet which can mean that we incorrectly detect one of the target spaces as being the same as the current space. This leads to us trying to use the current space in the graphics state (the DeviceN space) as the target space, with unfortunate consequences. So create a new version of zsetcolorspace which doesn't do that optimisation and use that when processing the various target spaces in the DeviceN attributes dictionary.
Diffstat (limited to 'psi/zcolor.c')
-rw-r--r--psi/zcolor.c71
1 files changed, 62 insertions, 9 deletions
diff --git a/psi/zcolor.c b/psi/zcolor.c
index c62c4bebe..c7bd28fe5 100644
--- a/psi/zcolor.c
+++ b/psi/zcolor.c
@@ -530,6 +530,56 @@ zsetcolorspace(i_ctx_t * i_ctx_p)
}
/*
+ * This is a copy of the zsetcolorspace code above, but it is for *internal* use by
+ * the PostScript interpreter colour space handlign code only. It replicates the
+ * behaviour of zsetcolorspace but does not check to see if the current 'interpreter'
+ * colour space is the same as the one we are setting. That is because this code is
+ * used when setting alternate or subsidiary colour spaces, and we absolutely do
+ * not want to break out of processing the space in this case.
+ */
+static int
+absolute_setcolorspace(i_ctx_t * i_ctx_p)
+{
+ os_ptr op = osp;
+ es_ptr ep;
+ int code, depth;
+ bool is_CIE;
+
+ /* Make sure we have an operand... */
+ check_op(1);
+ /* Check its either a name (base space) or an array */
+ if (!r_has_type(op, t_name))
+ if (!r_is_array(op))
+ return_error(gs_error_typecheck);
+
+ code = validate_spaces(i_ctx_p, op, &depth);
+ if (code < 0)
+ return code;
+
+ /* Set up for the continuation procedure which will do the work */
+ /* Make sure the exec stack has enough space */
+ check_estack(5);
+ /* Store the initial value of CIE substitution (not substituting) */
+ ep = esp += 1;
+ make_int(ep, 0);
+ /* Store the 'depth' of the space returned during checking above */
+ ep = esp += 1;
+ make_int(ep, depth);
+ /* Store the 'stage' of processing (initially 0) */
+ ep = esp += 1;
+ make_int(ep, 0);
+ /* Store a pointer to the color space stored on the operand stack
+ * as the stack may grow unpredictably making further access
+ * to the space difficult
+ */
+ ep = esp += 1;
+ *ep = *op;
+ /* Finally, the actual continuation routine */
+ push_op_estack(setcolorspace_cont);
+ return o_push_estack;
+}
+
+/*
* A special version of the setcolorspace operation above. This sets the
* CIE substitution flag to true before starting, which prevents any further
* CIE substitution taking place.
@@ -3758,7 +3808,7 @@ static int devicencolorants_cont(i_ctx_t *i_ctx_p)
make_int(pstage, 1);
*op = space[1];
- code = zsetcolorspace(i_ctx_p);
+ code = absolute_setcolorspace(i_ctx_p);
if (code == 0)
return o_push_estack;
@@ -3852,7 +3902,7 @@ static int devicenprocess_cont(i_ctx_t *i_ctx_p)
make_int(pstage, 1);
ref_assign(op, &dict);
- code = zsetcolorspace(i_ctx_p);
+ code = absolute_setcolorspace(i_ctx_p);
if (code == 0)
return o_push_estack;
@@ -3967,16 +4017,19 @@ static int setdevicenspace(i_ctx_t * i_ctx_p, ref *devicenspace, int *stage, int
devn_cs->params.device_n.subtype = gs_devicen_DeviceN;
code = dict_find_string(&sref, "Subtype", &subtype);
- if (code <= 0 && code != gs_error_undefined) {
+ if (code < 0 && code != gs_error_undefined) {
*stage = 0;
return code;
}
if (code > 0) {
- if (!r_has_type(subtype, t_name)) {
- *stage = 0;
- return gs_note_error(gs_error_typecheck);
+ if (r_has_type(subtype, t_name)) {
+ name_string_ref(imemory, subtype, subtype);
+ } else {
+ if (!r_has_type(subtype, t_string)) {
+ *stage = 0;
+ return gs_note_error(gs_error_typecheck);
+ }
}
- name_string_ref(imemory, subtype, subtype);
if (memcmp(subtype->value.bytes, "NChannel", 8) == 0)
devn_cs->params.device_n.subtype = gs_devicen_NChannel;
}
@@ -5745,7 +5798,7 @@ static int seticcspace(i_ctx_t * i_ctx_p, ref *r, int *stage, int *cont, int CIE
if (CIESubst)
return setcolorspace_nosubst(i_ctx_p);
else
- return zsetcolorspace(i_ctx_p);
+ return absolute_setcolorspace(i_ctx_p);
} else {
/* We have no /Alternate in the ICC space, use hte /N key to
* determine an 'appropriate' default space.
@@ -6442,7 +6495,7 @@ setdevicecolor_cont(i_ctx_t *i_ctx_p)
esp -= 3;
return code;
}
- code = zsetcolorspace(i_ctx_p);
+ code = absolute_setcolorspace(i_ctx_p);
if (code < 0) {
esp -= 3;
return code;