diff options
author | Ken Sharp <ken.sharp@artifex.com> | 2009-07-06 08:51:30 +0000 |
---|---|---|
committer | Ken Sharp <ken.sharp@artifex.com> | 2009-07-06 08:51:30 +0000 |
commit | 2dfe6de501143cefcc87bad0ce0b0225e80eb381 (patch) | |
tree | c258198597557b1227691c3e4ea75874722153b4 | |
parent | 1a4290769d0c533bb66e067aa27bfab117b162d1 (diff) |
Fix (graphics library) : Conversion to base colour space of an /Indexed colour space was
not catering for spaces with a string lookup instead of a procedural lookup.
Details
Bug #690587 "setcolorspace + currentgray crashes GS 8.64"
The conversion from a colour in an indexed space to its alternate assumed a procedural
lookup and failed badly if the space had a string lookup.
Expected Differences
Since this is only used when calculating a base colour equivalent (currentgray and
friends), which are rarely used in real world jobs, no differences are expected.
git-svn-id: http://svn.ghostscript.com/ghostscript/trunk@9841 a1074d23-0009-0410-80fe-cf8c14f379e6
-rw-r--r-- | gs/psi/zcolor.c | 69 |
1 files changed, 61 insertions, 8 deletions
diff --git a/gs/psi/zcolor.c b/gs/psi/zcolor.c index 9ab7450d4..76581ffdc 100644 --- a/gs/psi/zcolor.c +++ b/gs/psi/zcolor.c @@ -4611,19 +4611,72 @@ static int indexedrange(i_ctx_t * i_ctx_p, ref *space, float *ptr) } static int indexedbasecolor(i_ctx_t * i_ctx_p, ref *space, int base, int *stage, int *cont, int *stack_depth) { - es_ptr ep = ++esp; - ref proc; int code; if (*stage == 0) { + /* Usefully /Indexed can't be the base of any other space, so we know + * the current space in the graphics state is this one. + */ + gs_color_space *pcs; + pcs = gs_currentcolorspace(igs); + + /* Update the counters */ *stage = 1; *cont = 1; - check_estack(1); - code = array_get(imemory, space, 3, &proc); - if (code < 0) - return code; - *ep = proc; /* lookup proc */ - return o_push_estack; + + /* Indexed spaces can have *either* a procedure or a string for the + * lookup. + */ + if (pcs->params.indexed.use_proc) { + es_ptr ep = ++esp; + ref proc; + + /* We have a procedure, set up the continuation to run the + * lookup procedure. (The index is already on the operand stack) + */ + check_estack(1); + code = array_get(imemory, space, 3, &proc); + if (code < 0) + return code; + *ep = proc; /* lookup proc */ + return o_push_estack; + } else { + int i, index; + os_ptr op = osp; + unsigned char *ptr = (unsigned char *)pcs->params.indexed.lookup.table.data; + + *stage = 0; + /* We have a string, start by retrieving the index from the op stack */ + /* Make sure its an integer! */ + if (!r_has_type(op, t_integer)) + return_error (e_typecheck); + index = op->value.intval; + /* And remove it from the stack. */ + pop(1); + op = osp; + + /* Make sure we have enough space on the op stack to hold + * one value for each component of the alternate space + */ + push(pcs->params.indexed.n_comps); + op -= pcs->params.indexed.n_comps - 1; + + /* Move along the lookup table, one byte for each component , the + * number of times required to get to the lookup for this index + */ + ptr += index * pcs->params.indexed.n_comps; + + /* For all the components of the alternate space, push the value + * of the component on the stack. The value is given by the byte + * from the lookup table divided by 255 to give a value between + * 0 and 1. + */ + for (i = 0; i < pcs->params.indexed.n_comps; i++, op++) { + float rval = (*ptr++) / 255.0; + make_real(op, rval); + } + return 0; + } } else { *stage = 0; *cont = 1; |