diff options
author | Ken Sharp <ken.sharp@artifex.com> | 2019-05-08 14:27:23 +0100 |
---|---|---|
committer | Ken Sharp <ken.sharp@artifex.com> | 2019-05-08 15:27:28 +0100 |
commit | 2019db2e552653bd0c27377d500de1041c9fd0bc (patch) | |
tree | c7a6548ce721248c83e5d47ea532281bf7c5fdad /psi/zcolor.c | |
parent | 0d75869134c69963406500b536fb1bb1c97c8621 (diff) | |
download | ghostpdl-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.c | 71 |
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; |