Fix for 687534 Unable to determine equivalent CMYK for spot colors that are only used with overprint

"Dan Coby" <[email protected]> Tue, 22 Jun 2004 23:47:59 -0700
Newsgroups gmane.comp.printing.ghostscript.patches
Message-ID <[email protected]>
Fix for 687534 Unable to determine equivalent CMYK for spot colors
that are only used with overprint.

DETAILS:

The given test file uses spot colors.  However the psdcmyk device
was creating output files which did not contain equivalent CMYK
colors for the spot colors.  The cause was that the previous
version of the logic was capturing the equivalent CMYK colors
when the psdcmyk device's high drawing procs were called.  However
if overprinting is enabled, then the overprint device was inserting
its own versions of these routines.  Since it only took one call
to a high level drawing handler, the previous logic would capture
the equivalent CMYK colors if there were any drawing operations
with a spot color that did not have overprinting enabled.

The fix consists of moving the capturing of the equivalent CMYK
colors to a new device proc.  This new device proc is called
update_spot_equivalent_colors.  This device proc is called whenever
a Separation or a DeviceN color space is installed.

The default version of the proc does nothing.  Thus there is only
a small amount of overhead added for the installation of Separation
and DeviceN color spaces for devices which do not need the equivalent
CMYK colors for spot colors.

Most of the change consists of the standard details of adding a
new device proc.  There are several places that have to be updated
when this is done.  The documentation in doc/Drivers.htm was updated
to include this new proc.  The high level drawing handlers in the
psdcmyk devices were removed and a new psd_update_spot_equivalent_colors
procedure was added.  Some minor changes were made in the logic in
gsequivc.c since it is no longer necessary to scan through base and
alternate color spaces looking for Separation and DeviceN color spaces.
The comments at the beginning of gsequivc.c was changed to reflect
the changes in the logic for capturing equivalent CMYK colors for
spot colors.


Dan

_______________________________________________
gs-code-review mailing list
[email protected]
http://www.ghostscript.com/mailman/listinfo/gs-code-review
687534.txt (text/plain, 24.2 KB)
Index: doc/Drivers.htm
===================================================================
RCS file: /cvs/ghostscript/gs/doc/Drivers.htm,v
retrieving revision 1.46
diff -u -r1.46 Drivers.htm
--- doc/Drivers.htm	29 May 2004 01:21:53 -0000	1.46
+++ doc/Drivers.htm	23 Jun 2004 06:09:49 -0000
@@ -702,10 +702,13 @@
 <a href="../src/gxcindex.h">gxcindex.h</a>)
 <dd>This is meant to be whatever the driver uses to represent a device
 color.  For example, it might be an index in a color map, or it might be R,
-G, and B values packed into a single integer.  Ghostscript doesn't ever do
-any computations with <b><tt>gx_color_index</tt></b> values: it gets them
-from <b><tt>encode_color</tt></b> and
-hands them back as arguments to several other procedures.
+G, and B values packed into a single integer.  The Ghostscript graphics library
+gets <b><tt>gx_color_index</tt></b> values from the device's
+<b><tt>encode_color</tt></b> and hands them back as arguments to several other
+procedures. If the <b><tt>separable_and_linear</tt></b> field in the device's
+<b><tt>color_info</tt></b> structure is not set to
+<b><tt>GX_CINFO_SEP_LIN</tt></b> then Ghostscript does not do
+any computations with <b><tt>gx_color_index</tt></b> values.
 
 <p>
 The special
@@ -1314,6 +1317,18 @@
 should never be called, and drivers should not implement it.
 </dl>
 
+<dl>
+<dt><b><tt>void (*update_spot_equivalent_colors)(gx_device&nbsp;*,
+const gs_state *)</tt></b>
+<b><em>[OPTIONAL]</em></b>
+<dd>This routine provides a method for the device to gather an equivalent
+color for spot colorants. This routine is called when a Separation or DeviceN
+color space is installed.  See comments at the start of
+<a href="../src/gsequivc.c">gsequivc.c</a>. Note: This procedure is only needed
+for devices that support spot colorants and also need to have an equivalent
+color for simulating the appearance of the spot colorants.
+</dl>
+
 <h3><a name="Pixel_level_drawing"></a>Pixel-level drawing</h3>
 
 <p>
Index: src/gdevbbox.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevbbox.c,v
retrieving revision 1.17
diff -u -r1.17 gdevbbox.c
--- src/gdevbbox.c	24 May 2004 12:21:08 -0000	1.17
+++ src/gdevbbox.c	23 Jun 2004 06:11:47 -0000
@@ -273,6 +273,8 @@
 	set_dev_proc(dev, pattern_manage, gx_forward_pattern_manage);
 	set_dev_proc(dev, fill_rectangle_hl_color, gx_forward_fill_rectangle_hl_color);
 	set_dev_proc(dev, include_color_space, gx_forward_include_color_space);
+	set_dev_proc(dev, update_spot_equivalent_colors,
+				gx_forward_update_spot_equivalent_colors);
 	gx_device_set_target((gx_device_forward *)dev, target);
     } else {
 	gx_device_fill_in_procs((gx_device *)dev);
Index: src/gdevdflt.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevdflt.c,v
retrieving revision 1.23
diff -u -r1.23 gdevdflt.c
--- src/gdevdflt.c	26 May 2004 04:10:58 -0000	1.23
+++ src/gdevdflt.c	23 Jun 2004 06:11:56 -0000
@@ -669,6 +669,7 @@
     fill_dev_proc(dev, fill_linear_color_scanline, gx_default_fill_linear_color_scanline);
     fill_dev_proc(dev, fill_linear_color_trapezoid, gx_default_fill_linear_color_trapezoid);
     fill_dev_proc(dev, fill_linear_color_triangle, gx_default_fill_linear_color_triangle);
+    fill_dev_proc(dev, update_spot_equivalent_colors, gx_default_update_spot_equivalent_colors);
 }
 
 int
@@ -837,6 +838,16 @@
     return 0;
 }
 
+/*
+ * If a device want to determine an equivalent color for its spot colors then
+ * it needs to implement this method.  See comments at the start of
+ * src/gsequivc.c.
+ */
+void
+gx_default_update_spot_equivalent_colors(gx_device *pdev, const gs_state * pgs)
+{
+}
+
 /* ---------------- Default per-instance procedures ---------------- */
 
 int
Index: src/gdevnfwd.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevnfwd.c,v
retrieving revision 1.23
diff -u -r1.23 gdevnfwd.c
--- src/gdevnfwd.c	18 Jun 2004 07:00:47 -0000	1.23
+++ src/gdevnfwd.c	23 Jun 2004 06:12:10 -0000
@@ -107,6 +107,7 @@
     fill_dev_proc(dev, fill_linear_color_scanline, gx_forward_fill_linear_color_scanline);
     fill_dev_proc(dev, fill_linear_color_trapezoid, gx_forward_fill_linear_color_trapezoid);
     fill_dev_proc(dev, fill_linear_color_triangle, gx_forward_fill_linear_color_triangle);
+    fill_dev_proc(dev, update_spot_equivalent_colors, gx_forward_update_spot_equivalent_colors);
     gx_device_fill_in_procs((gx_device *) dev);
 }
 
@@ -811,6 +812,16 @@
     return proc(tdev, fa, p0, p1, p2, c0, c1, c2);
 }
 
+void 
+gx_forward_update_spot_equivalent_colors(gx_device *dev, const gs_state * pgs)
+{
+    gx_device_forward * const fdev = (gx_device_forward *)dev;
+    gx_device *tdev = fdev->target;
+
+    if (tdev != NULL)
+	dev_proc(tdev, update_spot_equivalent_colors)(tdev, pgs);
+}
+
 
 /* ---------------- The null device(s) ---------------- */
 
Index: src/gdevprn.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevprn.c,v
retrieving revision 1.16
diff -u -r1.16 gdevprn.c
--- src/gdevprn.c	28 May 2004 23:26:28 -0000	1.16
+++ src/gdevprn.c	23 Jun 2004 06:12:43 -0000
@@ -395,6 +395,7 @@
 	COPY_PROC(fill_path);
 	COPY_PROC(stroke_path);
 	COPY_PROC(fill_rectangle_hl_color);
+	COPY_PROC(update_spot_equivalent_colors);
 #undef COPY_PROC
 	/* If using a command list, already opened the device. */
 	if (is_command_list)
Index: src/gdevpsd.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevpsd.c,v
retrieving revision 1.14
diff -u -r1.14 gdevpsd.c
--- src/gdevpsd.c	18 Jun 2004 07:00:47 -0000	1.14
+++ src/gdevpsd.c	23 Jun 2004 06:12:47 -0000
@@ -48,11 +48,7 @@
 private dev_proc_get_color_comp_index(psd_get_color_comp_index);
 private dev_proc_encode_color(psd_encode_color);
 private dev_proc_decode_color(psd_decode_color);
-private dev_proc_fill_path(psd_fill_path);
-private dev_proc_stroke_path(psd_stroke_path);
-private dev_proc_begin_image(psd_begin_image);
-private dev_proc_text_begin(psd_text_begin);
-private dev_proc_fill_rectangle_hl_color(psd_fill_rectangle_hl_color);
+private dev_proc_update_spot_equivalent_colors(psd_update_spot_equivalent_colors);
 
 /* This is redundant with color_info.cm_name. We may eliminate this
    typedef and use the latter string for everything. */
@@ -156,14 +152,14 @@
 	NULL,				/* copy_alpha */\
 	NULL,				/* get_band */\
 	NULL,				/* copy_rop */\
-	psd_fill_path,			/* fill_path */\
-	psd_stroke_path,		/* stroke_path */\
+	NULL,				/* fill_path */\
+	NULL,				/* stroke_path */\
 	NULL,				/* fill_mask */\
 	NULL,				/* fill_trapezoid */\
 	NULL,				/* fill_parallelogram */\
 	NULL,				/* fill_triangle */\
 	NULL,				/* draw_thin_line */\
-	psd_begin_image,		/* begin_image */\
+	NULL,				/* begin_image */\
 	NULL,				/* image_data */\
 	NULL,				/* end_image */\
 	NULL,				/* strip_tile_rectangle */\
@@ -174,7 +170,7 @@
 	NULL,				/* map_color_rgb_alpha */\
 	NULL,				/* create_compositor */\
 	NULL,				/* get_hardware_params */\
-	psd_text_begin,			/* text_begin */\
+	NULL,				/* text_begin */\
 	NULL,				/* finish_copydevice */\
 	NULL,				/* begin_transparency_group */\
 	NULL,				/* end_transparency_group */\
@@ -186,7 +182,12 @@
 	psd_encode_color,		/* encode_color */\
 	psd_decode_color,		/* decode_color */\
 	NULL,				/* pattern_manage */\
-	psd_fill_rectangle_hl_color	/* fill_rectangle_hl_color */\
+	NULL,				/* fill_rectangle_hl_color */\
+	NULL,				/* include_color_space */\
+	NULL,				/* fill_linear_color_scanline */\
+	NULL,				/* fill_linear_color_trapezoid */\
+	NULL,				/* fill_linear_color_triangle */\
+	psd_update_spot_equivalent_colors /* update_spot_equivalent_colors */\
 }
 
 
@@ -520,77 +521,15 @@
 }
 
 /*
- * We implement the high level routines simply so we can check to see if
- * these operations involve separation colors.  If so then we use them to
- * capture an equivalent CMYK color for the the separation.
+ *  Device proc for updating the equivalent CMYK color for spot colors.
  */
-private int
-psd_fill_path(gx_device * pdev, const gs_imager_state * pis,
-		     gx_path * ppath, const gx_fill_params * params,
-		 const gx_device_color * pdevc, const gx_clip_path * pcpath)
-{
-    psd_device * psdev = (psd_device *)pdev;
-
-    update_spot_equivalent_cmyk_colors(pdev, pis,
-		    &psdev->devn_params, &psdev->equiv_cmyk_colors);
-    return gx_default_fill_path(pdev, pis, ppath, params, pdevc, pcpath);
-}
-
-private int
-psd_stroke_path(gx_device * pdev, const gs_imager_state * pis,
-		       gx_path * ppath, const gx_stroke_params * params,
-		       const gx_drawing_color * pdcolor,
-		       const gx_clip_path * pcpath)
-{
-    psd_device * psdev = (psd_device *)pdev;
-
-    update_spot_equivalent_cmyk_colors(pdev, pis,
-		    &psdev->devn_params, &psdev->equiv_cmyk_colors);
-    return gx_default_stroke_path(pdev, pis, ppath, params, pdcolor, pcpath);
-}
-
-private int
-psd_begin_image(gx_device * pdev, const gs_imager_state * pis,
-		const gs_image_t * pim, gs_image_format_t format,
-		const gs_int_rect * prect, const gx_drawing_color * pdcolor,
-		const gx_clip_path * pcpath, gs_memory_t * memory,
-		gx_image_enum_common_t ** pinfo)
-{
-    psd_device * psdev = (psd_device *)pdev;
-
-    update_spot_equivalent_cmyk_colors(pdev, pis,
-		    &psdev->devn_params, &psdev->equiv_cmyk_colors);
-    return gx_default_begin_image(pdev, pis, pim, format, prect, pdcolor,
-		    pcpath, memory, pinfo);
-}
-
-private int
-psd_text_begin(gx_device * pdev, gs_imager_state * pis,
-		      const gs_text_params_t * text, gs_font * font,
-		      gx_path * path, const gx_device_color * pdcolor,
-		      const gx_clip_path * pcpath,
-		      gs_memory_t * mem, gs_text_enum_t ** ppte)
-{
-    psd_device * psdev = (psd_device *)pdev;
-
-    update_spot_equivalent_cmyk_colors(pdev, pis,
-		    &psdev->devn_params, &psdev->equiv_cmyk_colors);
-    return gx_default_text_begin(pdev, pis, text, font, path, pdcolor,
-		    pcpath, mem, ppte);
-}
-
-private int
-psd_fill_rectangle_hl_color(gx_device *pdev, 
-    const gs_fixed_rect *rect, 
-    const gs_imager_state *pis, const gx_drawing_color *pdcolor,
-    const gx_clip_path *pcpath)
+private void
+psd_update_spot_equivalent_colors(gx_device *pdev, const gs_state * pgs)
 {
     psd_device * psdev = (psd_device *)pdev;
 
-    update_spot_equivalent_cmyk_colors(pdev, pis,
+    update_spot_equivalent_cmyk_colors(pdev, pgs,
 		    &psdev->devn_params, &psdev->equiv_cmyk_colors);
-    return gx_default_fill_rectangle_hl_color(pdev, rect,
-		    pis, pdcolor, pcpath);
 }
 
 private int
Index: src/gdevrops.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gdevrops.c,v
retrieving revision 1.11
diff -u -r1.11 gdevrops.c
--- src/gdevrops.c	26 May 2004 04:10:58 -0000	1.11
+++ src/gdevrops.c	23 Jun 2004 06:12:56 -0000
@@ -107,7 +107,8 @@
      gx_forward_include_color_space,
      gx_forward_fill_linear_color_scanline,
      gx_forward_fill_linear_color_trapezoid,
-     gx_forward_fill_linear_color_triangle
+     gx_forward_fill_linear_color_triangle,
+     gx_forward_update_spot_equivalent_colors
     },
     0,				/* target */
     lop_default			/* log_op */
Index: src/gscdevn.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gscdevn.c,v
retrieving revision 1.17
diff -u -r1.17 gscdevn.c
--- src/gscdevn.c	18 Jun 2004 07:00:47 -0000	1.17
+++ src/gscdevn.c	23 Jun 2004 06:13:24 -0000
@@ -504,9 +504,14 @@
     pgs->color_space->params.device_n.use_alt_cspace =
 	using_alt_color_space(pgs);
     if (pgs->color_space->params.device_n.use_alt_cspace)
-        return (*pcs->params.device_n.alt_space.type->install_cspace)
+        code = (*pcs->params.device_n.alt_space.type->install_cspace)
 	((const gs_color_space *) & pcs->params.device_n.alt_space, pgs);
-    return 0;
+    /*
+     * Give the device an opportunity to capture equivalent colors for any
+     * spot colors which might be present in the color space.
+     */
+    dev_proc(pgs->device, update_spot_equivalent_colors)(pgs->device, pgs);
+    return code;
 }
 
 /* Set overprint information for a DeviceN color space */
Index: src/gscsepr.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gscsepr.c,v
retrieving revision 1.24
diff -u -r1.24 gscsepr.c
--- src/gscsepr.c	18 Jun 2004 07:00:47 -0000	1.24
+++ src/gscsepr.c	23 Jun 2004 06:13:33 -0000
@@ -136,9 +136,14 @@
     pgs->color_space->params.separation.use_alt_cspace =
 	using_alt_color_space(pgs);
     if (pgs->color_space->params.separation.use_alt_cspace)
-        return (*pcs->params.separation.alt_space.type->install_cspace)
+        code = (*pcs->params.separation.alt_space.type->install_cspace)
 	((const gs_color_space *) & pcs->params.separation.alt_space, pgs);
-    return 0;
+    /*
+     * Give the device an opportunity to capture equivalent colors for any
+     * spot colors which might be present in the color space.
+     */
+    dev_proc(pgs->device, update_spot_equivalent_colors)(pgs->device, pgs);
+    return code;
 }
 
 /* Set the overprint information appropriate to a separation color space */
@@ -503,7 +508,7 @@
 
     if (code < 0)
 	return code;
-    code = sputs(s, (byte *)&p->sep_name, sizeof(p->sep_name), &n);
+    code = sputs(s, (const byte *)&p->sep_name, sizeof(p->sep_name), &n);
     if (code < 0)
 	return code;
     code = cs_serialize((const gs_color_space *)&p->alt_space, s);
@@ -512,6 +517,6 @@
     code = gx_serialize_device_n_map(pcs, p->map, s);
     if (code < 0)
 	return code;
-    return sputs(s, (byte *)&p->sep_type, sizeof(p->sep_type), &n);
+    return sputs(s, (const byte *)&p->sep_type, sizeof(p->sep_type), &n);
     /* p->use_alt_cspace isn't a property of the space. */
 }
Index: src/gsequivc.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gsequivc.c,v
retrieving revision 1.2
diff -u -r1.2 gsequivc.c
--- src/gsequivc.c	31 May 2004 06:02:00 -0000	1.2
+++ src/gsequivc.c	23 Jun 2004 06:13:36 -0000
@@ -37,20 +37,23 @@
  * colorant is not present.  We want to be able to display the spot colors
  * on our RGB or CMYK display.  We are using the tint transform function
  * to determine a CMYK equivalent to the spot color.  Current only CMYK
- * equivalent colors are supported but the logic can be cloned for any
- * other subtractive process color model.
+ * equivalent colors are supported.  This is because the CMYK is the only
+ * standard subtractive color space.
  *
  * This process consists of the following steps:
  *
  * 1.  Whenever new spot colors are found, set status flags indicating
  * that we have one or more spot colors for which we need to determine an
- * color.  New spot colors can either be explicitly specified by the
- * SeparationColorNames device parameter or they may be detected by the
+ * equivalent color.  New spot colors can either be explicitly specified by
+ * the SeparationColorNames device parameter or they may be detected by the
  * device's get_color_comp_index routine.
  *
- * 2.  Whenever a high level drawing operation is requested, the device
- * checks if the color space contains a spot color for which we do not
- * know the equivalent.
+ * 2.  Whenever a Separation or DeviceN color space is installed, the
+ * update_spot_equivalent_colors device proc is called.  This allows the
+ * device to check if the color space contains a spot color for which the
+ * device does not know the equivalent CMYK color.  The routine
+ * update_spot_equivalent_cmyk_colors is provided for this task (and the
+ * next item).
  *
  * 3.  For each spot color for which an equivalent color is not known, we
  * do the following:
@@ -92,13 +95,10 @@
  *     put_param routines to check if any separations have been added to the
  *     device.  For examples see code fragments in psd_get_color_comp_index and
  *     psd_put_params in src/gdevpsd.c.
- * 3.  The device needs to have its own version of the five high level interface
- *     routines.  These are:  fill_path, stroke_path, begin_image, text_begin
- *     and fill_rectangle_hl_color.  Usually these routines only need to consist
- *     of a call to update_spot_equivalent_cmyk_colors and then a call to the
- *     default routine.  For examples see the definition of the device_procs
- *     macro and the psd_fill_path, psd_stroke_path, psd_begin_image,
- *     psd_text_begin, and psd_fill_rectangle_hl_color routines in src/gdevpsd.c.
+ * 3.  The device needs to have its own version of the
+ *     update_spot_equivalent_colors routine.  For examples see the definition
+ *     of the device_procs macro and the psd_update_spot_equivalent_colors
+ *     routine in src/gdevpsd.c.
  * 4.  The device then uses the saved equivalent color values when its output
  *     is created.  For example see the psd_write_header routine in
  *     src/gdevpsd.c.
@@ -212,12 +212,10 @@
 
 /* If possible, update the equivalent CMYK color for a spot color */
 void
-update_spot_equivalent_cmyk_colors(gx_device * pdev, const gs_imager_state *pis,
+update_spot_equivalent_cmyk_colors(gx_device * pdev, const gs_state * pgs,
     gs_devn_params * pdevn_params, equivalent_cmyk_color_params * pparams)
 {
-    const gs_state * pgs;
     const gs_color_space * pcs;
-    extern_st(st_gs_state);
 
     /* If all of the color_info is valid then there is nothing to do. */
     if (pparams->all_color_info_valid)
@@ -229,41 +227,24 @@
 	return;
     }
     /*
-     * We need access to the graphics state, verify the pis is really a
-     * gs_state *.  If not then there is nothing that we can do.
-     */
-    if (gs_object_type(pdev->memory, pis) != &st_gs_state)
-	return;
-    /*
-     * Scan the color space and see if it is a DeviceN or Separation color
+     * Verify that the given color space is a Separation or a DeviceN color
      * space.  If so then when check if the color space contains a separation
-     * color for which we need a CMYK equivalent.  We also have to scan the
-     * base spaces since the top level color space may be an 'indexed' space,
-     * etc.
+     * color for which we need a CMYK equivalent.
      */
-    pgs = (const gs_state *) pis;
     pcs = pgs->color_space;
-    while (pcs != NULL) {
-        const gs_color_space * last_pcs = pcs;
-
+    if (pcs != NULL) {
 	if (pcs->type->index == gs_color_space_index_Separation) {
 	    update_Separation_spot_equivalent_cmyk_colors(pdev, pgs, pcs,
 						pdevn_params, pparams);
 	    pparams->all_color_info_valid = check_all_colors_known
 		    (pdevn_params->separations.num_separations, pparams);
-	    break;
 	}
 	else if (pcs->type->index == gs_color_space_index_DeviceN) {
 	    update_DeviceN_spot_equivalent_cmyk_colors(pdev, pgs, pcs,
 						pdevn_params, pparams);
 	    pparams->all_color_info_valid = check_all_colors_known
 		    (pdevn_params->separations.num_separations, pparams);
-	    break;
 	}
-	/* Go to any base color spaces to check them */
-	pcs = pcs->type->base_space(pcs);
-	if (pcs == last_pcs)	/* Exit if the base and current pcs are same */
-	    break;
     }
 }
 
Index: src/gsequivc.h
===================================================================
RCS file: /cvs/ghostscript/gs/src/gsequivc.h,v
retrieving revision 1.1
diff -u -r1.1 gsequivc.h
--- src/gsequivc.h	28 May 2004 23:26:28 -0000	1.1
+++ src/gsequivc.h	23 Jun 2004 06:13:36 -0000
@@ -44,7 +44,7 @@
 
 /* If possible, update the equivalent CMYK color for a spot color */
 void update_spot_equivalent_cmyk_colors(gx_device * pdev,
-		const gs_imager_state *pis, gs_devn_params * pdevn_params,
+		const gs_state * pgs, gs_devn_params * pdevn_params,
 		equivalent_cmyk_color_params * pparams);
 
 #endif		/* define gsequivc_INCLUDED */
Index: src/gxclip.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gxclip.c,v
retrieving revision 1.14
diff -u -r1.14 gxclip.c
--- src/gxclip.c	6 May 2004 08:41:40 -0000	1.14
+++ src/gxclip.c	23 Jun 2004 06:14:10 -0000
@@ -103,7 +103,8 @@
   gx_forward_include_color_space,
   gx_default_fill_linear_color_scanline,
   gx_default_fill_linear_color_trapezoid,
-  gx_default_fill_linear_color_triangle
+  gx_default_fill_linear_color_triangle,
+  gx_forward_update_spot_equivalent_colors
  }
 };
 
Index: src/gxclip2.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gxclip2.c,v
retrieving revision 1.10
diff -u -r1.10 gxclip2.c
--- src/gxclip2.c	28 Apr 2004 09:39:50 -0000	1.10
+++ src/gxclip2.c	23 Jun 2004 06:14:11 -0000
@@ -95,7 +95,8 @@
   gx_forward_include_color_space,
   gx_forward_fill_linear_color_scanline,
   gx_forward_fill_linear_color_trapezoid,
-  gx_forward_fill_linear_color_triangle
+  gx_forward_fill_linear_color_triangle,
+  gx_forward_update_spot_equivalent_colors
  }
 };
 
Index: src/gxclipm.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gxclipm.c,v
retrieving revision 1.12
diff -u -r1.12 gxclipm.c
--- src/gxclipm.c	28 Apr 2004 09:39:50 -0000	1.12
+++ src/gxclipm.c	23 Jun 2004 06:14:11 -0000
@@ -94,7 +94,8 @@
   gx_forward_include_color_space,
   gx_forward_fill_linear_color_scanline,
   gx_forward_fill_linear_color_trapezoid,
-  gx_forward_fill_linear_color_triangle
+  gx_forward_fill_linear_color_triangle,
+  gx_forward_update_spot_equivalent_colors
  }
 };
 
Index: src/gxclist.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gxclist.c,v
retrieving revision 1.13
diff -u -r1.13 gxclist.c
--- src/gxclist.c	29 Apr 2004 12:38:48 -0000	1.13
+++ src/gxclist.c	23 Jun 2004 06:14:12 -0000
@@ -137,7 +137,8 @@
     gx_default_include_color_space,
     gx_default_fill_linear_color_scanline,
     gx_default_fill_linear_color_trapezoid, /* fixme : write to clist. */
-    gx_default_fill_linear_color_triangle
+    gx_default_fill_linear_color_triangle,
+    gx_forward_update_spot_equivalent_colors
 };
 
 /* ------ Define the command set and syntax ------ */
Index: src/gxdevcli.h
===================================================================
RCS file: /cvs/ghostscript/gs/src/gxdevcli.h,v
retrieving revision 1.32
diff -u -r1.32 gxdevcli.h
--- src/gxdevcli.h	26 May 2004 04:10:58 -0000	1.32
+++ src/gxdevcli.h	23 Jun 2004 06:14:23 -0000
@@ -1314,6 +1314,17 @@
 #define dev_proc_fill_linear_color_triangle(proc)\
   dev_t_proc_fill_linear_color_triangle(proc, gx_device)
 
+/*
+ * Update the equivalent colors for spot colors in a color space.  The default
+ * procedure does nothing.  However this routine provides a method for devices
+ * to determine an equivalent color for a spot color.  See comments at the
+ * start of src/gsequivc.c.
+ */
+#define dev_t_proc_update_spot_equivalent_colors(proc, dev_t)\
+  void proc(dev_t *dev, const gs_state * pgs)
+#define dev_proc_update_spot_equivalent_colors(proc)\
+  dev_t_proc_update_spot_equivalent_colors(proc, gx_device)
+
 /* Define the device procedure vector template proper. */
 
 #define gx_device_proc_struct(dev_t)\
@@ -1376,6 +1387,7 @@
 	dev_t_proc_fill_linear_color_scanline((*fill_linear_color_scanline), dev_t); \
 	dev_t_proc_fill_linear_color_trapezoid((*fill_linear_color_trapezoid), dev_t); \
 	dev_t_proc_fill_linear_color_triangle((*fill_linear_color_triangle), dev_t); \
+	dev_t_proc_update_spot_equivalent_colors((*update_spot_equivalent_colors), dev_t); \
 }
 
 
Index: src/gxdevice.h
===================================================================
RCS file: /cvs/ghostscript/gs/src/gxdevice.h,v
retrieving revision 1.17
diff -u -r1.17 gxdevice.h
--- src/gxdevice.h	6 May 2004 19:06:26 -0000	1.17
+++ src/gxdevice.h	23 Jun 2004 06:14:24 -0000
@@ -274,6 +274,7 @@
 dev_proc_fill_linear_color_scanline(gx_default_fill_linear_color_scanline);
 dev_proc_fill_linear_color_trapezoid(gx_default_fill_linear_color_trapezoid);
 dev_proc_fill_linear_color_triangle(gx_default_fill_linear_color_triangle);
+dev_proc_update_spot_equivalent_colors(gx_default_update_spot_equivalent_colors);
 /* BACKWARD COMPATIBILITY */
 #define gx_non_imaging_create_compositor gx_null_create_compositor
 
@@ -349,6 +350,7 @@
 dev_proc_fill_linear_color_scanline(gx_forward_fill_linear_color_scanline);
 dev_proc_fill_linear_color_trapezoid(gx_forward_fill_linear_color_trapezoid);
 dev_proc_fill_linear_color_triangle(gx_forward_fill_linear_color_triangle);
+dev_proc_update_spot_equivalent_colors(gx_forward_update_spot_equivalent_colors);
 
 /* ---------------- Implementation utilities ---------------- */