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

ray at ghostscript.com ray at ghostscript.com
Thu Aug 16 21:49:23 PDT 2007


Author: ray
Date: 2007-08-16 21:49:22 -0700 (Thu, 16 Aug 2007)
New Revision: 8192

Modified:
   trunk/gs/src/gscie.c
   trunk/gs/src/gscie.h
   trunk/gs/src/gsciemap.c
   trunk/gs/src/gscspace.c
   trunk/gs/src/gsistate.c
   trunk/gs/src/gsncdummy.c
   trunk/gs/src/gxistate.h
Log:
This set of changes is an example for users or Artifex customers
that want to intercept the color spaces and perform their own
color space conversion for the CIEBased or ICCBased color spaces,
converting all of these spaces to the PostScript color management
link space "CIE XYZ". There were changes needed to implement this
that transcended the original custom color callback scheme, but
the approach taken is intended to minimize changes to the color
space processing.

Artifex customer #330

DETAILS:

Rather than rely on the hack in gx_cie_to_xyz_alloc that sets the
pis->cie_render to ~0, we establish a separate boolean for this,
cie_to_xyz which indicates that we don't need a CRD (gxistate.h,
gsistate.c, gsciemap.c, gscie.c). Note that the gx_cie_to_xyz_alloc
function is also used in the lab_range function in gdevpdfk.c
to construct an L*a*b* ICC conversion space for the pdfwrite
device.

The 'pclient_color_space_data' is now handled in the ENUM and
RELOC procedures for the gs_color_space base structure shared
by all color spaces (gscspace.c). A side effect of this is that
the pclient_color_space_data structure MUST be allocated with
appropriate GC structure calls an with an appropriate GC type
of macro to identify the structure for the GC and establish
the ENUM and RELOC hooks. This was needed to allow a gs_imager_state
structure to be allocated for the CIE color spaces and to have
both structures to be 'known' to the GC logic.

The CIE_LOAD_CACHE_BODY macro and the gx_install_cie_abc function
are now exported in gscie.h rather than local to gscie.c so that
gsncdummy.c and other custom callback clients can use them.

Finally, the gsncdummy.c module now includes example handling
that allow the graphics library to convert colors to XYZ if
the original color space was one of the CIEBased or ICCBased
spaces. Since CIE XYZ to L*a*b* is a direct conversion, this
allows clients to work with device independent color.

The conversion from XYZ to ICC L*a*b* code exists in gdevpdfk.c
in the function xyz_to_lab() which might be useful enough to
export in the future. For the short term clients can 'clone'
this small function if needed into their own color callback
processing.

Note that -dUseCIEColor (or << /UseCIEColor true >> setpagedevice
PostScript sequence) will mean that all Device* colorspaces also
get mapped through the Default* colorspaces to XYZ (DeviceGray,
DeviceRGB and DeviceCMYK).

EXPECTED DIFFERENCES:

None.

No regression differences were found in testing and the gsncdummy.c
code is only used if the ENABLE_CUSTOM_COLOR_CALLBACK is set to 1
in src/gsnamecl.h (which is NOT enabled in the default code).



Modified: trunk/gs/src/gscie.c
===================================================================
--- trunk/gs/src/gscie.c	2007-08-14 21:28:55 UTC (rev 8191)
+++ trunk/gs/src/gscie.c	2007-08-17 04:49:22 UTC (rev 8192)
@@ -58,30 +58,6 @@
   ((uint)(itemp = (int)(v)) >= (n) ?\
    (itemp < 0 ? 0 : (n) - 1) : itemp)
 
-/* Define the template for loading a cache. */
-/* If we had parameterized types, or a more flexible type system, */
-/* this could be done with a single procedure. */
-#define CIE_LOAD_CACHE_BODY(pcache, domains, rprocs, dprocs, pcie, cname)\
-  BEGIN\
-	int j;\
-\
-	for (j = 0; j < countof(pcache); j++) {\
-	    cie_cache_floats *pcf = &(pcache)[j].floats;\
-	    int i;\
-	    gs_sample_loop_params_t lp;\
-\
-	    gs_cie_cache_init(&pcf->params, &lp, &(domains)[j], cname);\
-	    for (i = 0; i <= lp.N; ++i) {\
-		float v = SAMPLE_LOOP_VALUE(i, lp);\
-		pcf->values[i] = (*(rprocs)->procs[j])(v, pcie);\
-		if_debug5('C', "[C]%s[%d,%d] = %g => %g\n",\
-			  cname, j, i, v, pcf->values[i]);\
-	    }\
-	    pcf->params.is_identity =\
-		(rprocs)->procs[j] == (dprocs).procs[j];\
-	}\
-  END
-
 /* Define cache interpolation threshold values. */
 #ifdef CIE_CACHE_INTERPOLATE
 #  ifdef CIE_INTERPOLATE_THRESHOLD
@@ -401,7 +377,7 @@
 private bool cie_cache_mult3(gx_cie_vector_cache3_t *,
 			     const gs_matrix3 *, floatp);
 
-private int
+int
 gx_install_cie_abc(gs_cie_abc *pcie, gs_state * pgs)
 {
     if_debug_matrix3("[c]CIE MatrixABC =", &pcie->MatrixABC);
@@ -1166,7 +1142,7 @@
 
 /* If the current color space is a CIE space, or has a CIE base space, */
 /* return a pointer to the common part of the space; otherwise return 0. */
-private const gs_cie_common *
+const gs_cie_common *
 cie_cs_common_abc(const gs_color_space *pcs_orig, const gs_cie_abc **ppabc)
 {
     const gs_color_space *pcs = pcs_orig;
@@ -1468,6 +1444,7 @@
 	return_error(gs_error_VMerror);
     memset(pis, 0, sizeof(*pis));	/* mostly paranoia */
     pis->memory = mem;
+    gs_imager_state_initialize(pis, mem);
 
     pjc = gs_alloc_struct(mem, gx_cie_joint_caches, &st_joint_caches,
 			  "gx_cie_to_xyz_free(joint caches)");
@@ -1493,11 +1470,7 @@
     pjc->cspace_id = pcs->id;
     pjc->status = CIE_JC_STATUS_COMPLETED;
     pis->cie_joint_caches = pjc;
-    /*
-     * Set a non-zero CRD to pacify CIE_CHECK_RENDERING.  (It will never
-     * actually be referenced, aside from the zero test.)
-     */
-    pis->cie_render = (void *)~0;
+    pis->cie_to_xyz = true;
     *ppis = pis;
     return 0;
 }

Modified: trunk/gs/src/gscie.h
===================================================================
--- trunk/gs/src/gscie.h	2007-08-14 21:28:55 UTC (rev 8191)
+++ trunk/gs/src/gscie.h	2007-08-17 04:49:22 UTC (rev 8192)
@@ -686,13 +686,38 @@
 gx_cie_joint_caches *gx_currentciecaches(gs_state *);
 const gs_cie_common *gs_cie_cs_common(const gs_state *);
 int gs_cie_cs_complete(gs_state *, bool);
-int gs_cie_jc_complete(const gs_imager_state *, const gs_color_space *pcs);
+int gs_cie_jc_complete(const gs_imager_state *, const gs_color_space *);
 float gs_cie_cached_value(floatp, const cie_cache_floats *);
+int gx_install_cie_abc(gs_cie_abc *, gs_state *);
 
 #define CIE_CLAMP_INDEX(index)\
   index = (index < 0 ? 0 :\
 	   index >= gx_cie_cache_size ? gx_cie_cache_size - 1 : index)
 
+/* Define the template for loading a cache. */
+/* If we had parameterized types, or a more flexible type system, */
+/* this could be done with a single procedure. */
+#define CIE_LOAD_CACHE_BODY(pcache, domains, rprocs, dprocs, pcie, cname)\
+  BEGIN\
+	int j;\
+\
+	for (j = 0; j < countof(pcache); j++) {\
+	    cie_cache_floats *pcf = &(pcache)[j].floats;\
+	    int i;\
+	    gs_sample_loop_params_t lp;\
+\
+	    gs_cie_cache_init(&pcf->params, &lp, &(domains)[j], cname);\
+	    for (i = 0; i <= lp.N; ++i) {\
+		float v = SAMPLE_LOOP_VALUE(i, lp);\
+		pcf->values[i] = (*(rprocs)->procs[j])(v, pcie);\
+		if_debug5('C', "[C]%s[%d,%d] = %g => %g\n",\
+			  cname, j, i, v, pcf->values[i]);\
+	    }\
+	    pcf->params.is_identity =\
+		(rprocs)->procs[j] == (dprocs).procs[j];\
+	}\
+  END
+
 /*
  * Compute the source and destination WhitePoint and BlackPoint for
  * the TransformPQR procedure.

Modified: trunk/gs/src/gsciemap.c
===================================================================
--- trunk/gs/src/gsciemap.c	2007-08-14 21:28:55 UTC (rev 8191)
+++ trunk/gs/src/gsciemap.c	2007-08-17 04:49:22 UTC (rev 8192)
@@ -94,12 +94,12 @@
 /*
  * Test whether a CIE rendering has been defined; ensure that the joint
  * caches are loaded.  Note that the procedure may return 1 if no rendering
- * has been defined.
+ * has been defined. The 'cie_to_xyz' flag indicates that we don't need a CRD
  */
 private inline int 
 gx_cie_check_rendering_inline(const gs_color_space * pcs, frac * pconc, const gs_imager_state * pis)
 {
-    if (pis->cie_render == 0) {
+    if (pis->cie_render == 0 && !pis->cie_to_xyz) {
 	/* No rendering has been defined yet: return black. */
 	pconc[0] = pconc[1] = pconc[2] = frac_0;
 	return 1;

Modified: trunk/gs/src/gscspace.c
===================================================================
--- trunk/gs/src/gscspace.c	2007-08-14 21:28:55 UTC (rev 8191)
+++ trunk/gs/src/gscspace.c	2007-08-17 04:49:22 UTC (rev 8192)
@@ -627,13 +627,16 @@
 
     if (index == 0)
 	return ENUM_OBJ(pcs->base_space);
-    return ENUM_USING(*pcs->type->stype, vptr, size, index - 1);
+    if (index == 1)
+	return ENUM_OBJ(pcs->pclient_color_space_data);
+    return ENUM_USING(*pcs->type->stype, vptr, size, index - 2);
     ENUM_PTRS_END_PROC
 }
 private 
 RELOC_PTRS_WITH(color_space_reloc_ptrs, gs_color_space *pcs)
 {
     RELOC_VAR(pcs->base_space);
+    RELOC_VAR(pcs->pclient_color_space_data);
     RELOC_USING(*pcs->type->stype, vptr, size);
 }
 RELOC_PTRS_END

Modified: trunk/gs/src/gsistate.c
===================================================================
--- trunk/gs/src/gsistate.c	2007-08-14 21:28:55 UTC (rev 8191)
+++ trunk/gs/src/gsistate.c	2007-08-17 04:49:22 UTC (rev 8192)
@@ -109,6 +109,7 @@
     }
     pis->dev_ht = 0;
     pis->cie_render = 0;
+    pis->cie_to_xyz = false;
     pis->black_generation = 0;
     pis->undercolor_removal = 0;
     /* Allocate an initial transfer map. */

Modified: trunk/gs/src/gsncdummy.c
===================================================================
--- trunk/gs/src/gsncdummy.c	2007-08-14 21:28:55 UTC (rev 8191)
+++ trunk/gs/src/gsncdummy.c	2007-08-17 04:49:22 UTC (rev 8192)
@@ -63,6 +63,7 @@
 #include "gserrors.h"
 #include "gscdefs.h"
 #include "gscspace.h"
+#include "gxcspace.h"
 #include "gscie.h"
 #include "gsicc.h"
 #include "gxdevice.h"
@@ -120,6 +121,9 @@
     /* Use a reference count for knowing when to release the data block. */
     int ref_count;
 
+    /* the memory allocator used */
+    gs_memory_t *memory;
+
     /* A flag which indicates the client wants to process the color space. */
     bool client_is_going_to_handle_color_space;
 
@@ -128,8 +132,14 @@
      * colorant in the color space.
      */
     int color_index[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    gs_imager_state *CIEtoXYZ_pis;	/* Used to map CIE spaces to XYZ */
+					/* refer to gx_cie_to_xyz_alloc	 */
 } demo_color_space_data_t;
 
+gs_private_st_ptrs1(st_demo_color_space_data, demo_color_space_data_t,
+	    "demo_color_space_data_t", demo_color_space_enum_ptrs,
+	    demo_color_space_reloc_ptrs, CIEtoXYZ_pis);
+
 /*
  * Dummy install routine for color spaces which are not handled by the client.
  */
@@ -186,38 +196,45 @@
 	(demo_color_space_data_t *)(pcs->pclient_color_space_data);
 
     pdata->ref_count += delta;
-    if (pdata->ref_count <= 0)
-		free(pdata);
+    if (pdata->ref_count <= 0) {
+	/* Free up the CIE to XYZ imager state if it was allocated */
+	if (pdata->CIEtoXYZ_pis) {
+	    gx_cie_to_xyz_free(pdata->CIEtoXYZ_pis);
+	}
+	gs_free_object(pdata->memory, pdata, "client_adjust_cspace_count(pdata)");
+    }
 }
 
 /*
  * Allocate a data block for holding our data for the client specific
  * data for a color space.  In our demo, we are only supporting the
  * Separation and DeviceN color spaces.  We use a single data structure
- * to make the code simpler.
+ * to make the code simpler. We also provide sample hooks for a client
+ * that wants to convert ALL CIEBased color spaces to XYZ (or Lab).
  */
 private demo_color_space_data_t *
-allocate_client_data_block(int initial_ref_count)
+allocate_client_data_block(int initial_ref_count, gs_memory_t *mem)
 {
     /*
-     * Since this is an example for a client, we are using the system
-     * malloc routine instead of the GS memory management routines.
-     * As a result, the client is responsible for freeing the data
-     * block.  For this purpose, we are using a simple reference count.
+     * We allocate this with normal GC structure declarations since
+     * we need this to be able to allocate the gs_imager_state for XYZ
+     * conversion.
+     * Since this is in stable memory, we use a simple reference count.
      * See client_adjust_cspace_count.
      */
     demo_color_space_data_t * pdata =
-	(demo_color_space_data_t *)malloc(size_of(demo_color_space_data_t));
+	(demo_color_space_data_t *)gs_alloc_struct(mem, demo_color_space_data_t,
+			&st_demo_color_space_data, "allocate_client_data_block(pdata)");
 
     if (pdata != NULL) {
-		pdata->ref_count = 1;
-	
-		/*
-		 * All client color space data blocks must have a pointer to a
-		 * reference count adjust routine as their first field.
-		 */
-		pdata->client_adjust_cspace_count = client_adjust_cspace_count;
-
+	memset(pdata, 0, sizeof(demo_color_space_data_t));
+	/*
+	 * All client color space data blocks must have a pointer to a
+	 * reference count adjust routine as their first field.
+	 */
+	pdata->client_adjust_cspace_count = client_adjust_cspace_count;
+	pdata->ref_count = 1;
+	pdata->memory = mem;
     }
     
     return pdata;
@@ -233,7 +250,7 @@
 	if (pcs->pclient_color_space_data != NULL)
 		return true;
 
-	pclient_data = allocate_client_data_block(1);
+	pclient_data = allocate_client_data_block(1, pcs->rc.memory->stable_memory);
 	pcs->pclient_color_space_data = (client_color_space_data_t *) pclient_data;
 	if (pclient_data)
 	{
@@ -281,7 +298,8 @@
     }
 
     if (use_custom_color_callback) {
-        demo_color_space_data_t * pclient_data = allocate_client_data_block(1);
+        demo_color_space_data_t * pclient_data =
+		allocate_client_data_block(1, pcs->rc.memory->stable_memory);
 
 	if (pclient_data == NULL)
 		return false;
@@ -390,7 +408,8 @@
      */
     use_pantone = pantone_found && !other_separation_found;
     if (use_pantone) {
-        demo_color_space_data_t * pclient_data = allocate_client_data_block(1);
+        demo_color_space_data_t * pclient_data =
+		allocate_client_data_block(1, pcs->rc.memory->stable_memory);
 
         if (pclient_data == NULL)
 	    return false;
@@ -640,6 +659,128 @@
 		: (frac) (frac_1 * \
 			(color - range.rmin) / (range.rmax - range.rmin))
 
+client_install_CIEtoA(client_custom_color_params_t * pparams,
+	    gs_color_space * pcs, gs_state * pgs)
+{
+    /* get ready for converting to XYZ */
+    demo_color_space_data_t * pdata;
+
+    /* Exit if we have already installed this color space. */
+    if (pcs->pclient_color_space_data != NULL)
+	return true;
+
+    pdata = allocate_client_data_block(1, pcs->rc.memory->stable_memory);
+    pcs->pclient_color_space_data = (client_color_space_data_t *) pdata;
+    if (pdata)
+    {
+	int code;
+	gs_cie_a *pcie = pcs->params.a;
+	gs_sample_loop_params_t lp;
+	int i;
+
+	pdata->client_is_going_to_handle_color_space = 1;
+
+	/* Fill the caches we need in the CIE color space */
+	gs_cie_cache_init(&pcie->caches.DecodeA.floats.params, &lp,
+			  &pcie->RangeA, "DecodeA");
+	for (i = 0; i <= lp.N; ++i) {
+	    float in = SAMPLE_LOOP_VALUE(i, lp);
+
+	    pcie->caches.DecodeA.floats.values[i] = (*pcie->DecodeA)(in, pcie);
+	}
+	gx_cie_load_common_cache(&pcie->common, pgs);
+	gs_cie_a_complete(pcie);
+	if ((code=gs_cie_cs_complete(pgs, true)) >= 0) {
+	    /* Now allocate the conversion imager state in stable_memory	*/
+	    /* so that the garbage collector won't free it			*/
+	    code = gx_cie_to_xyz_alloc(&pdata->CIEtoXYZ_pis, pcs,
+					pcs->rc.memory->stable_memory);
+	}
+	if (code < 0) {
+	    client_adjust_cspace_count(pcs, -1);  /* free it up */
+	    return false;
+	}
+    }
+    return true;
+}
+
+client_install_CIEtoXYZ(client_custom_color_params_t * pparams,
+	    gs_color_space * pcs, gs_state * pgs)
+{
+    /* get ready for converting to XYZ */
+    demo_color_space_data_t * pdata;
+
+    /* Exit if we have already installed this color space. */
+    if (pcs->pclient_color_space_data != NULL)
+	return true;
+
+    pdata = allocate_client_data_block(1, pcs->rc.memory->stable_memory);
+    pcs->pclient_color_space_data = (client_color_space_data_t *) pdata;
+    if (pdata)
+    {
+	int code;
+	const gs_cie_abc *pcie;
+
+	pdata->client_is_going_to_handle_color_space = 1;
+        switch (pcs->type->index) {
+	  case gs_color_space_index_CIEDEF: {
+	    gs_cie_def *pcie_def = pcs->params.def;
+
+	    pcie = (gs_cie_abc *)pcie_def;
+	    CIE_LOAD_CACHE_BODY(pcie_def->caches_def.DecodeDEF, pcie_def->RangeDEF.ranges,
+			    &pcie_def->DecodeDEF, DecodeDEF_default, pcie_def,
+			    "DecodeDEF");
+	    break;
+	  }
+	  case gs_color_space_index_CIEDEFG: {
+	    gs_cie_defg *pcie_defg = pcs->params.defg;
+
+	    pcie = (gs_cie_abc *)pcie_defg;
+	    CIE_LOAD_CACHE_BODY(pcie_defg->caches_defg.DecodeDEFG, pcie_defg->RangeDEFG.ranges,
+			    &pcie_defg->DecodeDEFG, DecodeDEFG_default, pcie_defg,
+			    "DecodeDEFG");
+	    break;
+	  }
+	  case gs_color_space_index_CIEABC: {
+	    pcie = pcs->params.abc;
+	    break;
+	  }
+	  default:
+	    /* can't happen since we only come here for certain color spaces */
+	    return false;
+	}
+	/* Fill the caches we need in the CIE color space */
+        if ((code=gx_install_cie_abc((gs_cie_abc *)pcie, pgs)) >= 0) {
+	    /* Now allocate the conversion imager state in stable_memory	*/
+	    /* so that the garbage collector won't free it			*/
+	    code = gx_cie_to_xyz_alloc(&pdata->CIEtoXYZ_pis, pcs,
+				    pcs->rc.memory->stable_memory);
+	}
+	if (code < 0) {
+	    client_adjust_cspace_count(pcs, -1);  /* free it up */
+	    return false;
+	}
+    }
+    return true;
+}
+
+client_install_ICCtoXYZ(client_custom_color_params_t * pparams,
+	    gs_color_space * pcs, gs_state * pgs)
+{
+    int code;
+    const gs_icc_params * picc_params = (const gs_icc_params *)&pcs->params.icc;
+    gs_cie_icc *    picc_info = picc_params->picc_info;
+
+    /* update the stub information used by the joint caches */
+    gx_cie_load_common_cache(&picc_info->common, pgs);
+    gx_cie_common_complete(&picc_info->common);
+    if ((code=gs_cie_cs_complete(pgs, true)) < 0) {
+	client_adjust_cspace_count(pcs, -1);  /* free it up */
+	return false;
+    }
+    return true;
+}
+
 /*
  * Convert a CIEBasedA color into device color.
  */
@@ -649,8 +790,23 @@
     gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
     gs_color_select_t select)
 {
+    demo_color_space_data_t * pdata = 
+	(demo_color_space_data_t *)(pcs->pclient_color_space_data);
     frac gray = convert2frac(pc->paint.values[0], pcs->params.a->RangeA);
 
+
+    /*** Demonstrate method to convert to XYZ ***/
+    if (pdata->CIEtoXYZ_pis) {
+	frac xyz[3];
+
+	cs_concretize_color(pc, pcs, xyz, pdata->CIEtoXYZ_pis);
+	/* We don't really do anything with these values, but this */
+	/* is where a real client could convert to a device color  */
+	if_debug4('|', "[c]client_remap CIEA [%g] -> XYZ [%g, %g, %g]\n",
+		  pc->paint.values[0],
+		  frac2float(xyz[0]), frac2float(xyz[1]), frac2float(xyz[2]));
+
+    }
     /*
      * For demo and debug purposes, make our colors a function of the
      * intensity of the given color value and the object type.
@@ -667,9 +823,22 @@
     gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
     gs_color_select_t select)
 {
+    demo_color_space_data_t * pdata = 
+	(demo_color_space_data_t *)(pcs->pclient_color_space_data);
     frac rgb[3];
     int i;
 
+    /*** Demonstrate method to convert to XYZ ***/
+    if (pdata->CIEtoXYZ_pis) {
+	frac xyz[3];
+
+	cs_concretize_color(pc, pcs, xyz, pdata->CIEtoXYZ_pis);
+	/* We don't really do anything with these values, but this */
+	/* is where a real client could convert to a device color  */
+	if_debug6('|', "[c]client_remap CIEABC [%g, %g, %g] -> XYZ [%g, %g, %g]\n",
+		  pc->paint.values[0], pc->paint.values[1], pc->paint.values[2],
+		  frac2float(xyz[0]), frac2float(xyz[1]), frac2float(xyz[2]));
+    }
     /*
      * For demo and debug purposes, make our colors a function of the
      * intensity of the given color value and the object type.  The color
@@ -691,9 +860,22 @@
     gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
     gs_color_select_t select)
 {
+    demo_color_space_data_t * pdata = 
+	(demo_color_space_data_t *)(pcs->pclient_color_space_data);
     frac rgb[3];
     int i;
 
+    /*** Demonstrate method to convert to XYZ ***/
+    if (pdata->CIEtoXYZ_pis) {
+	frac xyz[3];
+
+	cs_concretize_color(pc, pcs, xyz, pdata->CIEtoXYZ_pis);
+	/* We don't really do anything with these values, but this */
+	/* is where a real client could convert to a device color  */
+	if_debug6('|', "[c]client_remap CIEDEF [%g, %g, %g] -> XYZ [%g, %g, %g]\n",
+		  pc->paint.values[0], pc->paint.values[1], pc->paint.values[2],
+		  frac2float(xyz[0]), frac2float(xyz[1]), frac2float(xyz[2]));
+    }
     /*
      * For demo and debug purposes, make our colors a function of the
      * intensity of the given color value and the object type.  The color
@@ -715,9 +897,23 @@
     gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
     gs_color_select_t select)
 {
+    demo_color_space_data_t * pdata = 
+	(demo_color_space_data_t *)(pcs->pclient_color_space_data);
     frac cmyk[4];
     int i;
 
+    /*** Demonstrate method to convert to XYZ ***/
+    if (pdata->CIEtoXYZ_pis) {
+	frac xyz[3];
+
+	cs_concretize_color(pc, pcs, xyz, pdata->CIEtoXYZ_pis);
+	/* We don't really do anything with these values, but this */
+	/* is where a real client could convert to a device color  */
+	if_debug7('|', "[c]client_remap CIEDEFG [%g, %g, %g] -> XYZ [%g, %g, %g]\n",
+		  pc->paint.values[0], pc->paint.values[1], pc->paint.values[2],
+		  pc->paint.values[3],
+		  frac2float(xyz[0]), frac2float(xyz[1]), frac2float(xyz[2]));
+    }
     /*
      * For demo and debug purposes, make our colors a function of the
      * intensity of the given color value and the object type.  The color
@@ -739,9 +935,22 @@
     gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
     gs_color_select_t select)
 {
+    demo_color_space_data_t * pdata = 
+	(demo_color_space_data_t *)(pcs->pclient_color_space_data);
     frac frac_color[GS_CLIENT_COLOR_MAX_COMPONENTS];
     int i, num_values = pcs->params.icc.picc_info->num_components;
 
+    /*** Demonstrate method to convert to XYZ ***/
+    if (pdata->CIEtoXYZ_pis) {
+	frac xyz[3];
+
+	cs_concretize_color(pc, pcs, xyz, pdata->CIEtoXYZ_pis);
+	/* We don't really do anything with these values, but this */
+	/* is where a real client could convert to a device color  */
+	if_debug6('|', "[c]client_remap ICCBased [%g, %g, %g] -> XYZ [%g, %g, %g]\n",
+		  pc->paint.values[0], pc->paint.values[1], pc->paint.values[2],
+		  frac2float(xyz[0]), frac2float(xyz[1]), frac2float(xyz[2]));
+    }
     /*
      * For demo and debug purposes, make our colors a function of the
      * intensity of the given color value and the object type.  The color
@@ -789,15 +998,15 @@
     client_pantone_remap_Separation,
     client_pantone_install_DeviceN,	/* DeviceN */
     client_pantone_remap_DeviceN,
-    client_install_generic,		/* CIEBasedA */
+    client_install_CIEtoA,		/* CIEBasedA */
     client_remap_CIEBasedA,
-    client_install_generic,		/* CIEBasedABC */
+    client_install_CIEtoXYZ,		/* CIEBasedABC */
     client_remap_CIEBasedABC,
-    client_install_generic,		/* CIEBasedDEF */
+    client_install_CIEtoXYZ,		/* CIEBasedDEF */
     client_remap_CIEBasedDEF,
-    client_install_generic,		/* CIEBasedDEFG */
+    client_install_CIEtoXYZ,		/* CIEBasedDEFG */
     client_remap_CIEBasedDEFG,
-    client_install_generic,		/* ICCBased */
+    client_install_ICCtoXYZ,		/* ICCBased */
     client_remap_ICCBased
 };
 #else			/* Not OBJECT_TYPE_EXAMPLE special */

Modified: trunk/gs/src/gxistate.h
===================================================================
--- trunk/gs/src/gxistate.h	2007-08-14 21:28:55 UTC (rev 8191)
+++ trunk/gs/src/gxistate.h	2007-08-17 04:49:22 UTC (rev 8192)
@@ -133,6 +133,7 @@
 		/* Color (device-dependent): */\
 \
 	struct gs_cie_render_s *cie_render;	/* (RC) may be 0 */\
+	bool cie_to_xyz;			/* flag for conversion to XYZ, no CRD req'd */\
 	gx_transfer_map *black_generation;	/* (RC) may be 0 */\
 	gx_transfer_map *undercolor_removal;	/* (RC) may be 0 */\
 		/* set_transfer holds the transfer functions specified by */\



More information about the gs-cvs mailing list