summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Sharp <ken.sharp@artifex.com>2009-07-06 08:51:30 +0000
committerKen Sharp <ken.sharp@artifex.com>2009-07-06 08:51:30 +0000
commit2dfe6de501143cefcc87bad0ce0b0225e80eb381 (patch)
treec258198597557b1227691c3e4ea75874722153b4
parent1a4290769d0c533bb66e067aa27bfab117b162d1 (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.c69
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;