[gs-cvs] rev 7908 - trunk/gs/src

leonardo at ghostscript.com leonardo at ghostscript.com
Mon May 7 14:31:45 PDT 2007


Author: leonardo
Date: 2007-05-07 14:31:43 -0700 (Mon, 07 May 2007)
New Revision: 7908

Added:
   trunk/gs/src/gscicach.c
   trunk/gs/src/gscicach.h
Modified:
   trunk/gs/src/gxshade4.h
   trunk/gs/src/gxshade6.c
   trunk/gs/src/lib.mak
Log:
Fix (shadings) : Implement a color index cache.

DETAILS : 

This partially improves performance for the test case of 
the bug 689189 "PDF fails with /unregistered in --shfill--".

This change is algorithmically equivalent.
The old code redundantly converts client colors
to device colors. This patch implements a cache for 
the conversion in the new module gscicach.h .
It works for contone devices only.

For the test case it reduces the number of color conversions 
in 20+ times. However a rocket speeding up is not obtained.

This patch is an experimental one.
We have got an alternative approach,
which is more complicated but works for any device.
The alternative is to pass converted colors through the decomposition recursion.
We commit this now mainly for archiving purpose.
To disable it replace the call to gs_color_index_cache_create with NULL.

EXPECTED DIFFERENCES :

None.


Added: trunk/gs/src/gscicach.c
===================================================================
--- trunk/gs/src/gscicach.c	2007-05-07 20:29:08 UTC (rev 7907)
+++ trunk/gs/src/gscicach.c	2007-05-07 21:31:43 UTC (rev 7908)
@@ -0,0 +1,291 @@
+/* Copyright (C) 2001-2006 artofcode LLC.
+   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: gscicach.c 7765 2007-03-05 21:09:35Z raph $ */
+/* A color index cache. */
+#include "gx.h"
+#include "gserrors.h"
+#include "gsccolor.h"
+#include "gxcspace.h"
+#include "gxdcolor.h"
+#include "gscicach.h"
+#include "memory_.h"
+
+#define COLOR_INDEX_CACHE_SIZE 256
+#define COLOR_INDEX_CACHE_CHAINS (COLOR_INDEX_CACHE_SIZE / 16)
+
+typedef struct gs_color_index_cache_elem_s gs_color_index_cache_elem_t;
+
+struct gs_color_index_cache_elem_s {
+    gx_color_index cindex;
+    uint chain;
+    uint prev, next; /* NULL for unused. */
+    uint touch_prev, touch_next;
+    bool frac_values_done;
+};
+
+struct gs_color_index_cache_s {
+    const gs_color_space *direct_space;
+    gs_imager_state *pis;
+    gx_device *dev;
+    int client_num_components;
+    int device_num_components;
+    gs_memory_t *memory;
+    int used;
+    gs_color_index_cache_elem_t *buf;
+    uint recent_touch;
+    float *paint_values;
+    frac31 *frac_values;
+    int chains[COLOR_INDEX_CACHE_CHAINS];
+    /* Note : the 0th element of buf, paint_values, frac_values is never used,
+       because we consider the index 0 as NULL
+       just for a faster initialization. */
+#   define MYNULL 0
+};
+
+
+
+gs_private_st_ptrs5(st_color_index_cache, gs_color_index_cache_t, "gs_color_index_cache_t",
+		    gs_color_index_cache_elem_ptrs, gs_color_index_cache_reloc_ptrs,
+		    direct_space, memory, buf, paint_values, frac_values);
+
+gs_color_index_cache_t *
+gs_color_index_cache_create(gs_memory_t *memory, const gs_color_space *direct_space, gx_device *dev, gs_imager_state *pis, bool need_frac)
+{
+    int client_num_components = cs_num_components(direct_space);
+    int device_num_components = dev->color_info.num_components;
+    gs_color_index_cache_elem_t *buf = ( gs_color_index_cache_elem_t *)gs_alloc_byte_array(memory, COLOR_INDEX_CACHE_SIZE, 
+		    sizeof(gs_color_index_cache_elem_t), "gs_color_index_cache_create");
+    float *paint_values = (float *)gs_alloc_byte_array(memory, COLOR_INDEX_CACHE_SIZE * client_num_components, 
+		    sizeof(float), "gs_color_index_cache_create");
+    frac31 *frac_values = (need_frac ? (frac31 *)gs_alloc_byte_array(memory, COLOR_INDEX_CACHE_SIZE * device_num_components, 
+					    sizeof(frac31), "gs_color_index_cache_create") : NULL);
+    gs_color_index_cache_t *pcic = gs_alloc_struct(memory, gs_color_index_cache_t, &st_color_index_cache, "gs_color_index_cache_create");
+
+    if (buf == NULL || paint_values == NULL || (need_frac && frac_values == NULL) || pcic == NULL) {
+	gs_free_object(memory, buf, "gs_color_index_cache_create");
+	gs_free_object(memory, paint_values, "gs_color_index_cache_create");
+	gs_free_object(memory, frac_values, "gs_color_index_cache_create");
+	gs_free_object(memory, pcic, "gs_color_index_cache_create");
+	return NULL;
+    }
+    memset(pcic, 0, sizeof(*pcic));
+    memset(buf, 0, COLOR_INDEX_CACHE_SIZE * sizeof(gs_color_index_cache_elem_t));
+    pcic->direct_space = direct_space;
+    pcic->pis = pis;
+    pcic->dev = dev;
+    pcic->device_num_components = device_num_components;
+    pcic->client_num_components = client_num_components;
+    pcic->memory = memory;
+    pcic->used = 1; /* Never use the 0th element. */
+    pcic->buf = buf;
+    pcic->recent_touch = MYNULL;
+    pcic->paint_values = paint_values;
+    pcic->frac_values = frac_values;
+    return pcic;
+}
+
+void 
+gs_color_index_cache_destroy(gs_color_index_cache_t *pcic)
+{
+    gs_free_object(pcic->memory, pcic->buf, "gs_color_index_cache_create");
+    gs_free_object(pcic->memory, pcic->paint_values, "gs_color_index_cache_create");
+    gs_free_object(pcic->memory, pcic->frac_values, "gs_color_index_cache_create");
+    pcic->buf = NULL;
+    pcic->paint_values = NULL;
+    pcic->frac_values = NULL;
+    gs_free_object(pcic->memory, pcic, "gs_color_index_cache_create");
+}
+
+private inline int 
+hash_paint_values(const gs_color_index_cache_t *this, const float *paint_values)
+{
+    int i;
+    float v = 0;
+    uint k = 0;
+    const uint a_prime = 79;
+
+    for (i = 0; i < this->client_num_components; i++) 
+	v = v * a_prime + paint_values[i];
+    /* Don't know the range of v, so hash its bytes : */
+    for(i = 0; i < sizeof(v); i++)
+	k = k * a_prime + ((byte *)&v)[i];
+    return k % COLOR_INDEX_CACHE_CHAINS;
+}
+
+private inline void
+exclude_from_chain(gs_color_index_cache_t *this, uint i)
+{
+    uint co = this->buf[i].chain;
+    uint ip = this->buf[i].prev, in = this->buf[i].next;
+
+    this->buf[ip].next = in;
+    this->buf[in].prev = ip;
+    if (this->chains[co] == i)
+	this->chains[co] = in;
+}
+
+private inline void
+include_into_chain(gs_color_index_cache_t *this, uint i, uint c)
+{
+    if (this->chains[c] != MYNULL) {
+	uint in = this->chains[c], ip = this->buf[in].prev;
+
+	this->buf[i].next = in;
+	this->buf[i].prev = ip;
+	this->buf[in].prev = i;
+	this->buf[ip].next = i;
+    } else
+	this->buf[i].prev = this->buf[i].next = i;
+    this->chains[c] = i;
+    this->buf[i].chain = c;
+}
+
+private inline void
+exclude_from_touch_list(gs_color_index_cache_t *this, uint i)
+{
+    uint ip = this->buf[i].touch_prev, in = this->buf[i].touch_next;
+
+    this->buf[ip].touch_next = in;
+    this->buf[in].touch_prev = ip;
+    if (this->recent_touch == i) {
+	if (i == in)
+	    this->recent_touch = MYNULL;
+	else
+	    this->recent_touch = in;
+    }
+}
+
+private inline void
+include_into_touch_list(gs_color_index_cache_t *this, uint i)
+{
+    if (this->recent_touch != MYNULL) {
+	uint in = this->recent_touch, ip = this->buf[in].touch_prev;
+
+	this->buf[i].touch_next = in;
+	this->buf[i].touch_prev = ip;
+	this->buf[in].touch_prev = i;
+	this->buf[ip].touch_next = i;
+    } else
+	this->buf[i].touch_prev = this->buf[i].touch_next = i;
+    this->recent_touch = i;
+}
+
+private int 
+get_color_index_cache_elem(gs_color_index_cache_t *this, const float *paint_values, uint *pi)
+{
+    int client_num_components = this->client_num_components;
+    uint c = hash_paint_values(this, paint_values);
+    uint i = this->chains[c], j;
+
+    if (i != MYNULL) {
+	uint tries = 16; /* Arbitrary. */
+
+	if (!memcmp(paint_values, this->paint_values + i * client_num_components, sizeof(*paint_values) * client_num_components)) {
+	    if (this->recent_touch != i) {
+		exclude_from_touch_list(this, i);
+		include_into_touch_list(this, i);
+	    }
+	    *pi = i;
+	    return 1;
+	}
+	for (j = this->buf[i].next; tries -- && j != i; j = this->buf[j].next) {
+	    if (!memcmp(paint_values, this->paint_values + j * client_num_components, sizeof(*paint_values) * client_num_components)) {
+		exclude_from_chain(this, j);
+		include_into_chain(this, j, c);
+		if (this->recent_touch != j) {
+		    exclude_from_touch_list(this, j);
+		    include_into_touch_list(this, j);
+		}
+		*pi = j;
+		return 1;
+	    }
+	}
+	tries+=0;
+    }
+    if (this->used < COLOR_INDEX_CACHE_SIZE) {
+	/* Use a new one */
+	i = this->used++;
+	include_into_touch_list(this, i);
+    } else {
+	i = this->recent_touch;
+	this->recent_touch = this->buf[i].touch_prev; /* Assuming the cyclic list, 
+						      just move the head pointer to the last element. */
+	exclude_from_chain(this, i);
+    }
+    include_into_chain(this, i, c);
+    *pi = i;
+    return 0;
+}
+
+private inline void
+compute_frac_values(gs_color_index_cache_t *this, uint i)
+{
+    gx_color_index c = this->buf[i].cindex;
+    const gx_device_color_info *cinfo = &this->dev->color_info;
+    int device_num_components = this->device_num_components;
+    int j;
+
+    for (j = 0; j < device_num_components; j++) {
+	    int shift = cinfo->comp_shift[j];
+	    int bits = cinfo->comp_bits[j];
+
+	    this->frac_values[i * device_num_components + j] = ((c >> shift) & ((1 << bits) - 1)) << (sizeof(frac31) * 8 - 1 - bits);
+    }
+    this->buf[i].frac_values_done = true;
+}
+
+int 
+gs_cached_color_index(gs_color_index_cache_t *this, const float *paint_values, gx_device_color *pdevc, frac31 *frac_values)
+{
+    /* Must return 2 if the color is not pure. 
+       See patch_color_to_device_color. */
+    const gs_color_space *pcs = this->direct_space;
+    int client_num_components = this->client_num_components;
+    int device_num_components = this->device_num_components;
+    uint i;
+    int code;
+
+    if (get_color_index_cache_elem(this, paint_values, &i)) {
+	if (pdevc != NULL) {
+	    pdevc->colors.pure = this->buf[i].cindex;
+	    pdevc->type = &gx_dc_type_data_pure;
+	    memcpy(pdevc->ccolor.paint.values, paint_values, sizeof(*paint_values) * client_num_components);
+	    pdevc->ccolor_valid = true;
+	}
+	if (frac_values != NULL && !this->buf[i].frac_values_done)
+	    compute_frac_values(this, i);
+    } else {
+	gx_device_color devc_local;
+	gs_client_color fcc;
+
+	if (pdevc == NULL)
+	    pdevc = &devc_local;
+	memcpy(this->paint_values + i * client_num_components, paint_values, sizeof(*paint_values) * client_num_components);
+	memcpy(fcc.paint.values, paint_values, sizeof(*paint_values) * client_num_components);
+	code = pcs->type->remap_color(&fcc, pcs, pdevc, this->pis, this->dev, gs_color_select_texture);
+	if (code < 0)
+	    return code;
+	if (pdevc->type != &gx_dc_type_data_pure)
+	    return 2;
+	this->buf[i].cindex = pdevc->colors.pure;
+	
+	if (frac_values != NULL)
+    	    compute_frac_values(this, i);
+	else
+	    this->buf[i].frac_values_done = false;
+    }
+    if (frac_values != NULL)
+	memcpy(frac_values, this->frac_values + i * device_num_components, sizeof(*frac_values) * device_num_components);
+    return 0;
+}

Added: trunk/gs/src/gscicach.h
===================================================================
--- trunk/gs/src/gscicach.h	2007-05-07 20:29:08 UTC (rev 7907)
+++ trunk/gs/src/gscicach.h	2007-05-07 21:31:43 UTC (rev 7908)
@@ -0,0 +1,33 @@
+/* Copyright (C) 2001-2006 artofcode LLC.
+   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: gscicach.h 7765 2007-03-05 21:09:35Z raph $ */
+/* A color index conversion cache. */
+
+#ifndef gscicach_INCLUDED
+#  define gscicach_INCLUDED
+
+#include "gxdevcli.h" /* For frac31. */
+
+#ifndef gs_color_index_cache_DEFINED
+#  define gs_color_index_cache_DEFINED
+typedef struct gs_color_index_cache_s gs_color_index_cache_t;
+#endif
+
+gs_color_index_cache_t *gs_color_index_cache_create(gs_memory_t *memory, 
+		const gs_color_space *direct_space, gx_device *dev, gs_imager_state *pis, bool need_frac);
+void gs_color_index_cache_destroy(gs_color_index_cache_t *this);
+
+int gs_cached_color_index(gs_color_index_cache_t *this, const float *paint_values, gx_device_color *pdevc, frac31 *frac_values);
+
+#endif /* gscicach_INCLUDED */

Modified: trunk/gs/src/gxshade4.h
===================================================================
--- trunk/gs/src/gxshade4.h	2007-05-07 20:29:08 UTC (rev 7907)
+++ trunk/gs/src/gxshade4.h	2007-05-07 21:31:43 UTC (rev 7908)
@@ -112,8 +112,11 @@
 typedef struct patch_color_s patch_color_t;
 #endif
 
+#ifndef gs_color_index_cache_DEFINED
+#  define gs_color_index_cache_DEFINED
+typedef struct gs_color_index_cache_s gs_color_index_cache_t;
+#endif
 
-
 /* Define the common state for rendering Coons and tensor patches. */
 typedef struct patch_fill_state_s {
     mesh_fill_state_common;
@@ -140,6 +143,7 @@
     byte *color_stack; /* A storage for shortened patch_color_t structures. */
     byte *color_stack_limit;
     gs_memory_t *memory; /* Where color_buffer is allocated. */
+    gs_color_index_cache_t *pcic;
 } patch_fill_state_t;
 
 /* Define a structure for mesh or patch vertex. */

Modified: trunk/gs/src/gxshade6.c
===================================================================
--- trunk/gs/src/gxshade6.c	2007-05-07 20:29:08 UTC (rev 7907)
+++ trunk/gs/src/gxshade6.c	2007-05-07 21:31:43 UTC (rev 7908)
@@ -22,6 +22,7 @@
 #include "gserrors.h"
 #include "gsmatrix.h"		/* for gscoord.h */
 #include "gscoord.h"
+#include "gscicach.h"
 #include "gxcspace.h"
 #include "gxdcolor.h"
 #include "gxistate.h"
@@ -182,6 +183,18 @@
     return 0;
 }
 
+private inline bool
+is_linear_color_applicable(const patch_fill_state_t *pfs)
+{
+    if (!USE_LINEAR_COLOR_PROCS)
+	return false;
+    if (pfs->dev->color_info.separable_and_linear != GX_CINFO_SEP_LIN)
+	return false;
+    if (gx_get_cmap_procs(pfs->pis, pfs->dev)->is_halftoned(pfs->pis, pfs->dev))
+	return false;
+    return true;
+}
+
 int
 init_patch_fill_state(patch_fill_state_t *pfs)
 {
@@ -217,13 +230,24 @@
     pfs->color_stack = NULL;
     pfs->color_stack_limit = NULL;
     pfs->memory = NULL;
+    pfs->unlinear = !is_linear_color_applicable(pfs);
 #   if LAZY_WEDGES
 	code = wedge_vertex_list_elem_buffer_alloc(pfs);
 	if (code < 0)
 	    return code;
 #   endif
     pfs->max_small_coord = 1 << ((sizeof(int64_t) * 8 - 1/*sign*/) / 3);
-    return allocate_color_stack(pfs, pfs->pis->memory);
+    code = allocate_color_stack(pfs, pfs->pis->memory);
+    if (code < 0)
+	return code;
+    if (pfs->unlinear)
+	pfs->pcic = NULL;
+    else {
+	pfs->pcic = gs_color_index_cache_create(pfs->pis->memory, pcs, pfs->dev, pfs->pis, true);
+	if (pfs->pcic == NULL)
+	    return_error(gs_error_VMerror);
+    }
+    return 0;
 }
 
 bool
@@ -235,6 +259,8 @@
 #   endif
     if (pfs->color_stack)
 	gs_free_object(pfs->memory, pfs->color_stack, "term_patch_fill_state");
+    if (pfs->pcic != NULL)
+	gs_color_index_cache_destroy(pfs->pcic);
     return b;
 }
 
@@ -865,19 +891,67 @@
     return code;
 }
 
-private int
-patch_color_to_device_color(const patch_fill_state_t *pfs, const patch_color_t *c, gx_device_color *pdevc)
+private inline void
+dc2fc(const patch_fill_state_t *pfs, gx_color_index c, 
+	    frac31 fc[GX_DEVICE_COLOR_MAX_COMPONENTS])
 {
-    /* A code fragment copied from mesh_fill_triangle. */
-    gs_client_color fcc;
-    const gs_color_space *pcs = pfs->direct_space;
+    int j;
+    const gx_device_color_info *cinfo = &pfs->dev->color_info;
 
-    memcpy(fcc.paint.values, c->cc.paint.values, 
-		sizeof(fcc.paint.values[0]) * pfs->num_components);
-    return pcs->type->remap_color(&fcc, pcs, pdevc, pfs->pis,
-			      pfs->dev, gs_color_select_texture);
+    for (j = 0; j < cinfo->num_components; j++) {
+	    int shift = cinfo->comp_shift[j];
+	    int bits = cinfo->comp_bits[j];
+
+	    fc[j] = ((c >> shift) & ((1 << bits) - 1)) << (sizeof(frac31) * 8 - 1 - bits);
+    }
 }
 
+#define DEBUG_COLOR_INDEX_CACHE 0
+
+private inline int
+patch_color_to_device_color(const patch_fill_state_t *pfs, const patch_color_t *c, gx_device_color *pdevc, frac31 *frac_values)
+{
+    /* Must return 2 if the color is not pure. 
+       See try_device_linear_color.
+     */
+    int code;
+    gx_device_color devc;
+
+    if (DEBUG_COLOR_INDEX_CACHE && pdevc == NULL)
+	pdevc = &devc;
+    if (pfs->pcic) {
+	code = gs_cached_color_index(pfs->pcic, c->cc.paint.values, pdevc, frac_values);
+	if (code < 0)
+	    return code;
+    }
+    if (DEBUG_COLOR_INDEX_CACHE || pfs->pcic == NULL) {
+#	if DEBUG_COLOR_INDEX_CACHE
+	gx_color_index cindex = pdevc->colors.pure;
+#	endif
+	gs_client_color fcc;
+	const gs_color_space *pcs = pfs->direct_space;
+
+	if (pdevc == NULL)
+	    pdevc = &devc;
+	memcpy(fcc.paint.values, c->cc.paint.values, 
+		    sizeof(fcc.paint.values[0]) * pfs->num_components);
+	code = pcs->type->remap_color(&fcc, pcs, pdevc, pfs->pis,
+				  pfs->dev, gs_color_select_texture);
+	if (code < 0)
+	    return code;
+	if (frac_values != NULL) {
+	    dc2fc(pfs, pdevc->colors.pure, frac_values);
+	    if (pdevc->type != &gx_dc_type_data_pure)
+		return 2;
+	}
+#	if DEBUG_COLOR_INDEX_CACHE
+	if (cindex != pdevc->colors.pure)
+	    return_error(gs_error_unregistered);
+#	endif
+    }
+    return 0;
+}
+
 private inline double
 color_span(const patch_fill_state_t *pfs, const patch_color_t *c0, const patch_color_t *c1)
 {
@@ -956,7 +1030,7 @@
 	/* if (dbg_nofill)
 		return 0; */
 #   endif
-    code = patch_color_to_device_color(pfs, &c1, &dc);
+    code = patch_color_to_device_color(pfs, &c1, &dc, NULL);
     if (code < 0)
 	return code;
     if (!VD_TRACE_DOWN)
@@ -967,21 +1041,6 @@
     return code;
 }
 
-private inline void
-dc2fc(const patch_fill_state_t *pfs, gx_color_index c, 
-	    frac31 fc[GX_DEVICE_COLOR_MAX_COMPONENTS])
-{
-    int j;
-    const gx_device_color_info *cinfo = &pfs->dev->color_info;
-
-    for (j = 0; j < cinfo->num_components; j++) {
-	    int shift = cinfo->comp_shift[j];
-	    int bits = cinfo->comp_bits[j];
-
-	    fc[j] = ((c >> shift) & ((1 << bits) - 1)) << (sizeof(frac31) * 8 - 1 - bits);
-    }
-}
-
 private inline float
 function_linearity(const patch_fill_state_t *pfs, const patch_color_t *c0, const patch_color_t *c1)
 {
@@ -1099,7 +1158,6 @@
 	    gx_device *pdev = pfs->dev;
 	    frac31 fc[2][GX_DEVICE_COLOR_MAX_COMPONENTS];
 	    gs_fill_attributes fa;
-	    gx_device_color dc[2];
 	    gs_fixed_rect clip;
 
 	    clip = pfs->rect;
@@ -1118,30 +1176,31 @@
 	    fa.lop = 0;
 	    fa.ystart = ybot;
 	    fa.yend = ytop;
-	    code = patch_color_to_device_color(pfs, c0, &dc[0]);
+	    code = patch_color_to_device_color(pfs, c0, NULL, fc[0]);
 	    if (code < 0)
 		goto out;
-	    if (dc[0].type == &gx_dc_type_data_pure) {
-		dc2fc(pfs, dc[0].colors.pure, fc[0]);
-		code = patch_color_to_device_color(pfs, c1, &dc[1]);
-		if (code < 0)
-		    goto out;
-		dc2fc(pfs, dc[1].colors.pure, fc[1]);
-		code = dev_proc(pdev, fill_linear_color_trapezoid)(pdev, &fa, 
-				&le->start, &le->end, &re->start, &re->end, 
-				fc[0], fc[1], NULL, NULL);
-		if (code == 1) {
-		    pfs->monotonic_color = monotonic_color_save;
-		    pfs->linear_color = linear_color_save;
-		    code = 0; /* The area is filled. */
-		    goto out;
-		}
-		if (code < 0)
-		    goto out;
-		else /* code == 0, the device requested to decompose the area. */ 
-		    code = gs_note_error(gs_error_unregistered); /* Must not happen. */
-		    goto out;
+	    if (code == 2) {
+		/* Must not happen. */
+		code=gs_note_error(gs_error_unregistered);
+		goto out;
 	    }
+	    code = patch_color_to_device_color(pfs, c1, NULL, fc[1]);
+	    if (code < 0)
+		goto out;
+	    code = dev_proc(pdev, fill_linear_color_trapezoid)(pdev, &fa, 
+			    &le->start, &le->end, &re->start, &re->end, 
+			    fc[0], fc[1], NULL, NULL);
+	    if (code == 1) {
+		pfs->monotonic_color = monotonic_color_save;
+		pfs->linear_color = linear_color_save;
+		code = 0; /* The area is filled. */
+		goto out;
+	    }
+	    if (code < 0)
+		goto out;
+	    else /* code == 0, the device requested to decompose the area. */ 
+		code = gs_note_error(gs_error_unregistered); /* Must not happen. */
+		goto out;
 	}
 	if (!pfs->unlinear || !pfs->linear_color || 
 		color_span(pfs, c0, c1) > pfs->smoothness) {
@@ -1625,22 +1684,19 @@
 	fa.ht = NULL;
 	fa.swap_axes = false;
 	fa.lop = 0;
-	code = patch_color_to_device_color(pfs, p0->c, &dc[0]);
-	if (code < 0)
+	code = patch_color_to_device_color(pfs, p0->c, &dc[0], fc[0]);
+	if (code != 0)
 	    return code;
 	if (dc[0].type != &gx_dc_type_data_pure)
 	    return 2;
-	dc2fc(pfs, dc[0].colors.pure, fc[0]);
 	if (!wedge) {
-	    code = patch_color_to_device_color(pfs, p1->c, &dc[1]);
-	    if (code < 0)
+	    code = patch_color_to_device_color(pfs, p1->c, &dc[1], fc[1]);
+	    if (code != 0)
 		return code;
-	    dc2fc(pfs, dc[1].colors.pure, fc[1]);
 	}
-	code = patch_color_to_device_color(pfs, p2->c, &dc[2]);
-	if (code < 0)
+	code = patch_color_to_device_color(pfs, p2->c, &dc[2], fc[2]);
+	if (code != 0)
 	    return code;
-	dc2fc(pfs, dc[2].colors.pure, fc[2]);
 	draw_triangle(&p0->p, &p1->p, &p2->p, RGB(255, 0, 0));
 	if (!VD_TRACE_DOWN)
 	    vd_disable;
@@ -1798,18 +1854,6 @@
     return code;
 }
 
-private inline bool
-is_linear_color_applicable(const patch_fill_state_t *pfs)
-{
-    if (!USE_LINEAR_COLOR_PROCS)
-	return false;
-    if (pfs->dev->color_info.separable_and_linear != GX_CINFO_SEP_LIN)
-	return false;
-    if (gx_get_cmap_procs(pfs->pis, pfs->dev)->is_halftoned(pfs->pis, pfs->dev))
-	return false;
-    return true;
-}
-
 int
 mesh_padding(patch_fill_state_t *pfs, const gs_fixed_point *p0, const gs_fixed_point *p1, 
 	    const patch_color_t *c0, const patch_color_t *c1)
@@ -1822,7 +1866,6 @@
     gs_fixed_edge le, re;
     const fixed adjust = INTERPATCH_PADDING;
 
-    pfs->unlinear = !is_linear_color_applicable(pfs);
     if (swap_axes) {
 	if (p0->x < p1->x) {
 	    q0.x = p0->y;
@@ -2022,7 +2065,7 @@
 #   endif
     if (!VD_TRACE_DOWN)
         vd_disable;
-    code = patch_color_to_device_color(pfs, c, &dc);
+    code = patch_color_to_device_color(pfs, c, &dc, NULL);
     if (code < 0)
 	return code;
     if (le->end.y < re->end.y) {
@@ -2108,7 +2151,7 @@
     patch_interpolate_color(c[1], p->p[0][0]->c, p->p[0][1]->c, pfs, 0.5);
     patch_interpolate_color(c[2], p->p[1][0]->c, p->p[1][1]->c, pfs, 0.5);
     patch_interpolate_color(c[0], c[1], c[2], pfs, 0.5);
-    code = patch_color_to_device_color(pfs, c[0], &dc);
+    code = patch_color_to_device_color(pfs, c[0], &dc, NULL);
     if (code < 0)
 	return code;
     {	gs_fixed_point qq[4];

Modified: trunk/gs/src/lib.mak
===================================================================
--- trunk/gs/src/lib.mak	2007-05-07 20:29:08 UTC (rev 7907)
+++ trunk/gs/src/lib.mak	2007-05-07 21:31:43 UTC (rev 7908)
@@ -400,6 +400,7 @@
  $(gsrefct_h) $(gsropt_h) $(gsstruct_h) $(gstparam_h) $(gsxfont_h)\
  $(gxbitmap_h) $(gxcindex_h) $(gxcvalue_h) $(gxfixed_h)\
  $(gxtext_h) $(gscspace_h) $(gsnamecl_h)
+gscicach_h=$(GLSRC)gscicach.h $(gxdevcli_h)
 gxdevice_h=$(GLSRC)gxdevice.h $(stdio__h)\
  $(gsfname_h) $(gsmalloc_h) $(gsparam_h) $(gxdevcli_h) $(gxstdio_h)
 gxdht_h=$(GLSRC)gxdht.h\
@@ -761,6 +762,10 @@
  $(gsdevice_h) $(gxdevcli_h) $(gzstate_h) $(stream_h)
 	$(GLCC) $(GLO_)gscspace.$(OBJ) $(C_) $(GLSRC)gscspace.c
 
+$(GLOBJ)gscicach.$(OBJ) : $(GLSRC)gscicach.c $(GXERR)\
+ $(gsccolor_h) $(gxcspace_h) $(gxdcolor_h) $(gscicach_h) $(memory__h)
+	$(GLCC) $(GLO_)gscicach.$(OBJ) $(C_) $(GLSRC)gscicach.c
+
 $(GLOBJ)gsovrc.$(OBJ) : $(GLSRC)gsovrc.c $(GXERR)\
  $(memory__h) $(gsutil_h) $(gxcomp_h) $(gxdevice_h) $(gsdevice_h) $(gxgetbit_h)\
  $(gsovrc_h) $(gxdcolor_h) $(gxoprect_h) $(gsbitops_h) $(gxistate_h)
@@ -1081,7 +1086,7 @@
 # Note: gschar.c is no longer required for a standard build;
 # we include it only for backward compatibility for library clients.
 LIB3s=$(GLOBJ)gscedata.$(OBJ) $(GLOBJ)gscencs.$(OBJ) $(GLOBJ)gschar.$(OBJ) $(GLOBJ)gscolor.$(OBJ)
-LIB4s= $(GLOBJ)gscoord.$(OBJ) $(GLOBJ)gscparam.$(OBJ) $(GLOBJ)gscspace.$(OBJ) $(GLOBJ)gsovrc.$(OBJ) $(GLOBJ)gxoprect.$(OBJ)
+LIB4s=$(GLOBJ)gscoord.$(OBJ) $(GLOBJ)gscparam.$(OBJ) $(GLOBJ)gscspace.$(OBJ)  $(GLOBJ)gscicach.$(OBJ) $(GLOBJ)gsovrc.$(OBJ) $(GLOBJ)gxoprect.$(OBJ)
 LIB5s=$(GLOBJ)gsdevice.$(OBJ) $(GLOBJ)gsdevmem.$(OBJ) $(GLOBJ)gsdparam.$(OBJ) $(GLOBJ)gsdfilt.$(OBJ)
 LIB6s=$(GLOBJ)gsfname.$(OBJ) $(GLOBJ)gsfont.$(OBJ) $(GLOBJ)gsgdata.$(OBJ) $(GLOBJ)gsgcache.$(OBJ)
 LIB7s=$(GLOBJ)gsht.$(OBJ) $(GLOBJ)gshtscr.$(OBJ) $(GLOBJ)gswts.$(OBJ)
@@ -2649,7 +2654,7 @@
 	$(GLCC) $(GLO_)gxshade4.$(OBJ) $(C_) $(GLSRC)gxshade4.c
 
 $(GLOBJ)gxshade6.$(OBJ) : $(GLSRC)gxshade6.c $(GXERR) $(memory__h)\
- $(gscoord_h) $(gsmatrix_h)\
+ $(gscoord_h) $(gscicach_h) $(gsmatrix_h)\
  $(gxcspace_h) $(gxdcolor_h) $(gxistate_h) $(gxshade_h) $(gxshade4_h) $(gxdevcli_h)\
  $(gxarith_h) $(gzpath_h) $(math__h) $(vdtrace_h)
 	$(GLCC) $(GLO_)gxshade6.$(OBJ) $(C_) $(GLSRC)gxshade6.c



More information about the gs-cvs mailing list