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

tim at ghostscript.com tim at ghostscript.com
Thu Apr 5 19:43:20 PDT 2007


Author: tim
Date: 2007-04-05 19:43:19 -0700 (Thu, 05 Apr 2007)
New Revision: 7824

Added:
   trunk/gs/src/gsncdummy.c
   trunk/gs/src/gsncdummy.h
   trunk/gs/src/zncdummy.c
Log:
Splitting graphics library from interpreter portion of the sample custom color callback

Added: trunk/gs/src/gsncdummy.c
===================================================================
--- trunk/gs/src/gsncdummy.c	2007-04-06 02:39:31 UTC (rev 7823)
+++ trunk/gs/src/gsncdummy.c	2007-04-06 02:43:19 UTC (rev 7824)
@@ -0,0 +1,836 @@
+/* Copyright (C) 2001-2007 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: gsncdummy.c 7795 2007-03-23 13:56:11Z tim $ */
+/* Sample implementation for client custom processing of color spaces. */
+
+/*
+ * If this flag is 1 then we also do custom processing for the DeviceGray,
+ * DeviceRGB, and DeviceCMYK color spaces.  For these color spaces, we
+ * convert all text to shades of red, all images to shades of green and
+ * all lines and fills to shades of blue.  if the flag is 0 then our example
+ * only handles PANTONE colors (see comment below).
+ */
+#define OBJECT_TYPE_EXAMPLE 1		/* 0 --> disabled, 1 --> enabled */
+
+/*
+ * This module has been created to demonstrate how to support the use of
+ * PANTONE colors to the Ghostscript graphics library.  PANTONE colors
+ * are specified in both PostScript and PDF files via the use of DeviceN
+ * or Separation color spaces.
+ *
+ * PANTONE is a registered trademark and PANTONE colors are a
+ * licensed product of Pantone Inc. See http://www.pantone.com
+ * for more information.
+ *
+ * See the comments at the start of src/gsnamecl.c for description of the
+ * client color processing routines.
+ *
+ * Since this is only a 'demo' implementation, the example implementation does
+ * not have some features which might be expected in a 'real' implementation.
+ *
+ * 1.  The Pantone color data table does not have actual entries for all
+ *     of the different Pantone colors.  This data is not included since
+ *     the values are dependent upon specific details of the output device,
+ *     inks, etc.
+ * 2.  Colors in PostScript and PDF are specified with by values between
+ *     0 and 1.  The output colorant values are scaled linearly.
+ * 3.  DeviceN color spaces can specify multiple colors.  However this
+ *     implementation assumes that if a PANTONE color is specified in a
+ *     DeviceN color space, then only PANTONE colors or CMYK are present.
+ *     This was done to keep the code simple.  If other colors are present,
+ *     then this implementation falls back to using the alternate color space
+ *     specified with the DeviceN color space.  (This is the normal PS
+ *     and PDF operation.)
+ *
+ * See also src/zsncdummy.c for an example custom color callback. 
+ */
+
+#include "stdpre.h"
+#include "math_.h"
+#include "memory_.h"
+#include "gx.h"
+#include "gserrors.h"
+#include "gscdefs.h"
+#include "gscspace.h"
+#include "gscie.h"
+#include "gsicc.h"
+#include "gxdevice.h"
+#include "gzstate.h"
+#include "malloc_.h"
+#include "ghost.h"
+#include "ierrors.h"
+#include "iddict.h"
+#include "store.h"
+#include "gsutil.h"
+#include "gsncdummy.h"
+
+#if ENABLE_CUSTOM_COLOR_CALLBACK		/* Defined in src/gsnamecl.h */
+
+/*
+ * Since this is only a 'demo' list, the list does have not entries for all
+ * of the different PANTONE colors.  Creation of a real list is left as an
+ * exercise for the user.
+ */
+const pantone_list_t pantone_list[] = { 
+    { "PantoneCyan",	1, 0, 0, 0 },
+    { "PantoneMagenta",	0, 1, 0, 0 },
+    { "PantoneYellow",	0, 0, 1, 0 },
+    { "PantoneBlack",	0, 0, 0, 1 },
+    { "Orange",	0, 1, .5, 0 }
+};
+
+/*
+ * We will handle color spaces that include both PANTONE colors, CMYK, and
+ * 'None'.  'None' is a special case in DeviceN color spaces.  It has no
+ * effects upon the output color but it can be present in DeviceN color
+ * spaces in a PDF file.  To simplify the code, we need pantone index values
+ * for these five 'colors'.
+ */
+#define PANTONE_NONE    count_of(pantone_list)
+#define PANTONE_CYAN    (PANTONE_NONE + 1)
+#define PANTONE_MAGENTA (PANTONE_NONE + 2)
+#define PANTONE_YELLOW  (PANTONE_NONE + 3)
+#define PANTONE_BLACK   (PANTONE_NONE + 4)
+
+/* Compare two names */
+#define compare_names(name1, name_size1, name2, name_size2) \
+    (name_size1 == name_size2 && \
+	(memcmp((const char *)name1, (const char *)name2, name_size1) == 0))
+
+/*
+ * Define a structure for holding our client specific data.  In our demo,
+ * we are only supporting Separation and DeviceN color spaces.  To make
+ * life simpler, we are using the same data structure for both types
+ * of color spaces.
+ */
+typedef struct demo_color_space_data_s {
+    /*
+     * All client color space data blocks must begin with a routine for
+     * handling the reference counts for the data block.
+     */
+    cs_proc_adjust_client_cspace_count((*client_adjust_cspace_count));
+
+    /* Use a reference count for knowing when to release the data block. */
+    int ref_count;
+
+    /* A flag which indicates the client wants to process the color space. */
+    bool client_is_going_to_handle_color_space;
+
+    /*
+     * We store an index into our Pantone color translation table for each
+     * colorant in the color space.
+     */
+    int color_index[GS_CLIENT_COLOR_MAX_COMPONENTS];
+} demo_color_space_data_t;
+
+/*
+ * Dummy install routine for color spaces which are not handled by the client.
+ */
+private bool
+client_install_no_op(client_custom_color_params_t * pparams,
+	    gs_color_space * pcs, gs_state * pgs)
+{
+    return false;	/* Do nothing */
+}
+
+/*
+ * Dummy convert routine for simple color spaces (gray, RGB, CMYK, DeviceN,
+ * and Separation) which are not handled by the client.
+ */
+private int
+client_remap_simple_no_op(client_custom_color_params_t * pparams,
+    const frac * pconc, const gs_color_space * pcs, gx_device_color * pdc,
+    const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
+{
+    /*
+     * Returning an error value will cause GS to use its normal processes
+     * for handling the color space.
+     */
+    return_error(gs_error_rangecheck);
+}
+
+/*
+ * Dummy convert routine for complex color spaces (CIEBasedA, CIEBasedABC,
+ * CIEBasedDEF, CIEBasedDEF, CIEBasedDEFG, ICCBased) which are not handled
+ * by the client.
+ */
+private int
+client_remap_complex_no_op(client_custom_color_params_t * pparams,
+    const gs_client_color * pc, const gs_color_space * pcs,
+    gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
+    gs_color_select_t select)
+{
+    /*
+     * Returning an error value will cause GS to use its normal processes
+     * for handling the color space.
+     */
+    return_error(gs_error_rangecheck);
+}
+
+/*
+ * Since this is an example for a client, we are using the system
+ * malloc and free routines instead of the normal GS memory management
+ * routines.
+ */
+private void
+client_adjust_cspace_count(const gs_color_space * pcs, int delta)
+{
+    demo_color_space_data_t * pdata = 
+	(demo_color_space_data_t *)(pcs->pclient_color_space_data);
+
+    pdata->ref_count += delta;
+    if (pdata->ref_count <= 0)
+		free(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.
+ */
+private demo_color_space_data_t *
+allocate_client_data_block(int initial_ref_count)
+{
+    /*
+     * 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.
+     * See client_adjust_cspace_count.
+     */
+    demo_color_space_data_t * pdata =
+	(demo_color_space_data_t *)malloc(size_of(demo_color_space_data_t));
+
+    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;
+
+    }
+    
+    return pdata;
+}
+
+private bool
+client_install_generic(client_custom_color_params_t * pparams,
+	    gs_color_space * pcs, gs_state * pgs)
+{
+	demo_color_space_data_t * pclient_data;
+
+	/* Exit if we have already installed this color space. */
+	if (pcs->pclient_color_space_data != NULL)
+		return true;
+
+	pclient_data = allocate_client_data_block(1);
+	pcs->pclient_color_space_data = (client_color_space_data_t *) pclient_data;
+	if (pclient_data)
+	{
+		pclient_data->client_is_going_to_handle_color_space = 1;
+		return true;
+	}
+	return false;
+}
+
+/*
+ * Check if we want to use the PANTONE color processing logic for the given
+ * Separation color space.
+ */
+private bool
+client_pantone_install_Separation(client_custom_color_params_t * pparam,
+			gs_color_space * pcs, gs_state * pgs)
+{
+    const gs_separation_name name = pcs->params.separation.sep_name;
+    int pan_index;
+    byte * pname;
+    uint name_size;
+    gx_device * dev = pgs->device;
+    int num_pantone_colors = count_of(pantone_list);
+    bool use_custom_color_callback = false;
+
+    /* Exit if we have already installed this color space. */
+    if (pcs->pclient_color_space_data != NULL)
+		return true;
+
+    /*
+     * Get the character string and length for the component name.
+     */
+    pcs->params.separation.get_colorname_string(dev->memory, name,
+						&pname, &name_size);
+    /*
+    * Compare the colorant name to those in our PANTONE color list.
+    */
+    for (pan_index = 0; pan_index < num_pantone_colors ; pan_index++) {
+	const char * pan_name = pantone_list[pan_index].name;
+
+	if (compare_names(pname, name_size, pan_name, strlen(pan_name))) {
+	    use_custom_color_callback = true;
+	    break;
+	}
+    }
+
+    if (use_custom_color_callback) {
+        demo_color_space_data_t * pclient_data = allocate_client_data_block(1);
+
+	if (pclient_data == NULL)
+		return false;
+	pclient_data->color_index[0] = pan_index;
+        pcs->pclient_color_space_data =
+	       (client_color_space_data_t *) pclient_data;
+    }
+    return use_custom_color_callback;
+}
+
+/*
+ * Check if we want to use the PANTONE color processing logic for the given
+ * DeviceN color space.
+ */
+private bool
+client_pantone_install_DeviceN(client_custom_color_params_t * pparam,
+			gs_color_space * pcs, gs_state * pgs)
+{
+    const gs_separation_name *names = pcs->params.device_n.names;
+    int num_comp = pcs->params.device_n.num_components;
+    int i;
+    int pan_index;
+    byte * pname;
+    uint name_size;
+    gx_device * dev = pgs->device;
+    int num_pantone_colors = count_of(pantone_list);
+    bool pantone_found = false;
+    bool other_separation_found = false;
+    bool use_pantone;
+    const char none_str[] = "None";
+    const uint none_size = strlen(none_str);
+    const char cyan_str[] = "Cyan";
+    const uint cyan_size = strlen(cyan_str);
+    const char magenta_str[] = "Magenta";
+    const uint magenta_size = strlen(magenta_str);
+    const char yellow_str[] = "Yellow";
+    const uint yellow_size = strlen(yellow_str);
+    const char black_str[] = "Black";
+    const uint black_size = strlen(black_str);
+    int pantone_color_index[GS_CLIENT_COLOR_MAX_COMPONENTS];
+
+    /* Exit if we have already installed this color space. */
+    if (pcs->pclient_color_space_data != NULL)
+		return true;
+
+    /*
+     * Now check the names of the color components.
+     */
+    for(i = 0; i < num_comp; i++ ) {
+	bool match = false;
+
+	/*
+	 * Get the character string and length for the component name.
+	 */
+	pcs->params.device_n.get_colorname_string(dev->memory, names[i],
+							&pname, &name_size);
+	/*
+         * Postscript does not include /None as a color component but it is
+         * allowed in PDF so we accept it.  We simply skip components named
+	 * 'None'.
+         */
+	if (compare_names(none_str, none_size, pname, name_size)) {
+	    pantone_color_index[i] = PANTONE_NONE;
+	    continue;
+	}
+	/*
+	 * Check if our color space includes the CMYK process colors.
+	 */
+	if (compare_names(cyan_str, cyan_size, pname, name_size)) {
+	    pantone_color_index[i] = PANTONE_CYAN;
+	    continue;
+	}
+	if (compare_names(magenta_str, magenta_size, pname, name_size)) {
+	    pantone_color_index[i] = PANTONE_MAGENTA;
+	    continue;
+	}
+	if (compare_names(yellow_str, yellow_size, pname, name_size)) {
+	    pantone_color_index[i] = PANTONE_YELLOW;
+	    continue;
+	}
+	if (compare_names(black_str, black_size, pname, name_size)) {
+	    pantone_color_index[i] = PANTONE_BLACK;
+	    continue;
+	}
+	/*
+	 * Compare the colorant name to those in our Pantone color list.
+	 */
+	for (pan_index = 0; pan_index < num_pantone_colors ; pan_index++) {
+	    const char * pan_name = pantone_list[pan_index].name;
+
+	    if (compare_names(pname, name_size, pan_name, strlen(pan_name))) {
+	        pantone_color_index[i] = pan_index;
+		match = pantone_found = true;
+		break;
+	    }
+	}
+	if (!match) {		/* Exit if we find a non Pantone color */
+	    other_separation_found = true;
+	    break;
+	}
+    }
+    /*
+     * Handle this color space as a 'pantone color space' if we have only
+     * PANTONE colors and CMYK.  Any other separations will force us to
+     * use the normal Ghostscript processing for a DeviceN color space.
+     */
+    use_pantone = pantone_found && !other_separation_found;
+    if (use_pantone) {
+        demo_color_space_data_t * pclient_data = allocate_client_data_block(1);
+
+        if (pclient_data == NULL)
+	    return false;
+        for(i = 0; i < num_comp; i++ )
+	    pclient_data->color_index[i] = pantone_color_index[i];
+        pcs->pclient_color_space_data =
+	       (client_color_space_data_t *) pclient_data;
+    }
+    return use_pantone;
+}
+
+
+/*
+ * Convert a set of color values in a 'PANTONE color space' into a device
+ * color values.
+ *
+ * This routine creates an equivalent CMYK color and then uses
+ * gx_remap_concrete_cmyk to convert this into device colorants.  Note:  It
+ * is possible to go directy to the output device colorants.  However the
+ * pantone_install_xxx routines should verify that the expected device
+ * colorants match the actual device colorants.  (For instance, Ghostscript
+ * can install temporary compositing devices for functions like handling
+ * PDF 1.4 transparency.  The compositing devices may have a process color
+ * models which differ from the final output device.)
+ */
+private int
+client_pantone_remap_color(client_custom_color_params_t * pparam,
+	const frac * pconc, const demo_color_space_data_t * pparams,
+       	gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
+	gs_color_select_t select, int num_comp)
+{
+    int i, pantone_index, cvalue;
+    int cyan = 0;
+    int magenta = 0;
+    int yellow = 0;
+    int black = 0;
+    frac cc, cm, cy, ck;
+    const pantone_list_t * plist;
+
+    /*
+     * If the client color space data pointer is NULL then we are not processing
+     * this color space.  The rangecheck error will indicate that GS should do
+     * its normal color space processing.
+     */
+    if (pparams == NULL)
+	return_error(gs_error_rangecheck);
+
+    /*
+     * Create a CMYK representation of the various colors in our color space.
+     * Note:  If we have multiple components, then we do a simple sum of the
+     * CMYK equivalent for each color.  If desired, a more complex handling is
+     * left to the user.
+     */
+    for (i = 0; i < num_comp; i++) {
+	cvalue = pconc[i];
+	pantone_index = pparams->color_index[i];
+	switch (pantone_index) {
+	    case PANTONE_NONE:
+		break;
+	    case PANTONE_CYAN:
+		cyan += cvalue;
+		break;
+	    case PANTONE_MAGENTA:
+		magenta += cvalue;
+		break;
+	    case PANTONE_YELLOW:
+		yellow += cvalue;
+		break;
+	    case PANTONE_BLACK:
+		black += cvalue;
+		break;
+	    default:
+		plist = &(pantone_list[pantone_index]);
+		cyan += (int) floor(cvalue * plist->c);
+		magenta += (int) floor(cvalue * plist->m);
+		yellow += (int) floor(cvalue * plist->y);
+		black += (int) floor(cvalue * plist->k);
+		break;
+	}
+    }
+    /* Clamp our color values */
+    cc = (cyan > frac_1) ? frac_1 : (cyan < frac_0) ? frac_0 : cyan;
+    cm = (magenta > frac_1) ? frac_1 : (magenta < frac_0) ? frac_0 : magenta;
+    cy = (yellow > frac_1) ? frac_1 : (yellow < frac_0) ? frac_0 : yellow;
+    ck = (black > frac_1) ? frac_1 : (black < frac_0) ? frac_0 : black;
+    gx_remap_concrete_cmyk(cc, cm, cy, ck, pdc, pis, dev, select);
+    return 0;
+}
+
+/*
+ * Convert a Separation color (with PANTONE colorants) into device color.
+ */
+private int
+client_pantone_remap_Separation(client_custom_color_params_t * pparam,
+	const frac * pconc, const gs_color_space * pcs, gx_device_color * pdc,
+       	const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
+{
+    return client_pantone_remap_color(pparam, pconc,
+	(demo_color_space_data_t *)(pcs->pclient_color_space_data),
+       	pdc, pis, dev, select, 1);
+}
+
+/*
+ * Convert a DeviceN color (with PANTONE colorants) into device color.
+ */
+private int
+client_pantone_remap_DeviceN(client_custom_color_params_t * pparam,
+	const frac * pconc, const gs_color_space * pcs, gx_device_color * pdc,
+       	const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
+{
+   	return client_pantone_remap_color(pparam, pconc,
+	(demo_color_space_data_t *)(pcs->pclient_color_space_data),
+	pdc, pis, dev, select, gs_color_space_num_components(pcs));	
+}
+
+#if OBJECT_TYPE_EXAMPLE
+/*
+ * Install a DeviceGray color space.
+ */
+private bool
+client_install_DeviceGray(client_custom_color_params_t * pparams,
+	    gs_color_space * pcs, gs_state * pgs)
+{
+    /* Nothing to do in our demo */
+    return true;
+}
+
+/*
+ * For demo and debug purposes, make our colors a function of the
+ * intensity of the given colors and the object type.
+ */
+private int
+convert_intensity_into_device_color(const frac intensity,
+	gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
+	gs_color_select_t select)
+{
+    frac cc, cm, cy, ck;
+
+    switch (pis->object_tag) {
+	case GS_TEXT_TAG:		/* Make text red. */
+		cc = ck = 0;
+		cm = cy = frac_1 - intensity;
+		break;
+	case GS_IMAGE_TAG:		/* Make images green. */
+		cm = ck = 0;
+		cc = cy = frac_1 - intensity;
+		break;
+	case GS_PATH_TAG:		/* Make lines and fills blue. */
+	default:
+		cy = ck = 0;
+		cc = cm = frac_1 - intensity;
+		break;
+    }
+
+    /* Send CMYK colors to the device */
+    gx_remap_concrete_cmyk(cc, cm, cy, ck, pdc, pis, dev, select);
+    return 0;
+}
+
+/*
+ * Convert a DeviceGray color into device color.
+ */
+private int
+client_remap_DeviceGray(client_custom_color_params_t * pparams,
+    const frac * pconc, const gs_color_space * pcs, gx_device_color * pdc,
+    const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
+{
+    /*
+     * For demo and debug purposes, make our colors a function of the
+     * intensity of the given colors and the object type.
+     */
+    frac intensity = pconc[0];
+
+    convert_intensity_into_device_color(intensity, pdc, pis, dev, select);
+    return 0;
+}
+
+/*
+ * Install a DeviceRGB color space.
+ */
+private bool
+client_install_DeviceRGB(client_custom_color_params_t * pparams,
+	    gs_color_space * pcs, gs_state * pgs)
+{
+    /* Nothing to do in our demo */
+    dlprintf1("client_install_DeviceRGB ri = %d\n", pgs->renderingintent);
+    return true;
+}
+
+/*
+ * Convert a DeviceRGB color into device color.
+ */
+private int
+client_remap_DeviceRGB(client_custom_color_params_t * pparams,
+	const frac * pconc, const gs_color_space * pcs, gx_device_color * pdc,
+       	const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
+{
+    /*
+     * For demo and debug purposes, make our colors a function of the
+     * intensity of the given colors and the object type.
+     */
+    frac intensity = (frac)(pconc[0] * 0.30 + pconc[1] * 0.59 + pconc[2] * 0.11);
+
+    convert_intensity_into_device_color(intensity, pdc, pis, dev, select);
+    return 0;
+}
+
+/*
+ * Install a DeviceCMYK color space.
+ */
+private bool
+client_install_DeviceCMYK(client_custom_color_params_t * pparams,
+	    gs_color_space * pcs, gs_state * pgs)
+{
+    /* Nothing to do in our demo */
+    return true;
+}
+
+/*
+ * Convert a DeviceGray color into device color.
+ */
+private int
+client_remap_DeviceCMYK(client_custom_color_params_t * pparams,
+	const frac * pconc, const gs_color_space * pcs, gx_device_color * pdc,
+       	const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
+{
+    /*
+     * For demo and debug purposes, make our colors a function of the
+     * intensity of the given colors and the object type.
+     */
+    frac intensity = frac_1 - (frac)(pconc[0] * 0.30 + pconc[1] * 0.59
+		    + pconc[2] * 0.11 + pconc[3]);
+
+    if (intensity < frac_0)
+	intensity = frac_0;
+    convert_intensity_into_device_color(intensity, pdc, pis, dev, select);
+    return 0;
+}
+
+/*
+ * Convert a floating point color value into a fixed (frac) color value
+ * given a specified floating point range.
+ */
+#define convert2frac(color, range) \
+	(color <= range.rmin) ? frac_0 \
+	    : (color >= range.rmax)  ? frac_1 \
+		: (frac) (frac_1 * \
+			(color - range.rmin) / (range.rmax - range.rmin))
+
+/*
+ * Convert a CIEBasedA color into device color.
+ */
+private int
+client_remap_CIEBasedA(client_custom_color_params_t * pparams,
+    const gs_client_color * pc, const gs_color_space * pcs,
+    gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
+    gs_color_select_t select)
+{
+    frac gray = convert2frac(pc->paint.values[0], pcs->params.a->RangeA);
+
+    /*
+     * For demo and debug purposes, make our colors a function of the
+     * intensity of the given color value and the object type.
+     */
+    return client_remap_DeviceGray(pparams, &gray, pcs, pdc, pis, dev, select);
+}
+
+/*
+ * Convert a CIEBasedABC color into device color.
+ */
+private int
+client_remap_CIEBasedABC(client_custom_color_params_t * pparams,
+    const gs_client_color * pc, const gs_color_space * pcs,
+    gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
+    gs_color_select_t select)
+{
+    frac rgb[3];
+    int i;
+
+    /*
+     * For demo and debug purposes, make our colors a function of the
+     * intensity of the given color value and the object type.  The color
+     * values could represent almost anything.  However we are assuming
+     * that they are RGB values.
+     */
+    for (i = 0; i < 3; i++)
+	rgb[i] = convert2frac(pc->paint.values[i],
+		       	pcs->params.abc->RangeABC.ranges[i]);
+    return client_remap_DeviceRGB(pparams, rgb, pcs, pdc, pis, dev, select);
+}
+
+/*
+ * Convert a CIEBasedDEF color into device color.
+ */
+private int
+client_remap_CIEBasedDEF(client_custom_color_params_t * pparams,
+    const gs_client_color * pc, const gs_color_space * pcs,
+    gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
+    gs_color_select_t select)
+{
+    frac rgb[3];
+    int i;
+
+    /*
+     * For demo and debug purposes, make our colors a function of the
+     * intensity of the given color value and the object type.  The color
+     * values could represent almost anything.  However we are assuming
+     * that they are RGB values.
+     */
+    for (i = 0; i < 3; i++)
+	rgb[i] = convert2frac(pc->paint.values[i],
+		       	pcs->params.def->RangeDEF.ranges[i]);
+    return client_remap_DeviceRGB(pparams, rgb, pcs, pdc, pis, dev, select);
+}
+
+/*
+ * Convert a CIEBasedDEFG color into device color.
+ */
+private int
+client_remap_CIEBasedDEFG(client_custom_color_params_t * pparams,
+    const gs_client_color * pc, const gs_color_space * pcs,
+    gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
+    gs_color_select_t select)
+{
+    frac cmyk[4];
+    int i;
+
+    /*
+     * For demo and debug purposes, make our colors a function of the
+     * intensity of the given color value and the object type.  The color
+     * values could represent almost anything.  However we are assuming
+     * that they are CMYK values.
+     */
+    for (i = 0; i < 4; i++)
+	cmyk[i] = convert2frac(pc->paint.values[i],
+		       	pcs->params.defg->RangeDEFG.ranges[i]);
+    return client_remap_DeviceRGB(pparams, cmyk, pcs, pdc, pis, dev, select);
+}
+
+/*
+ * Convert a ICCBased color into device color.
+ */
+private int
+client_remap_ICCBased(client_custom_color_params_t * pparams,
+    const gs_client_color * pc, const gs_color_space * pcs,
+    gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
+    gs_color_select_t select)
+{
+    frac frac_color[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    int i, num_values = pcs->params.icc.picc_info->num_components;
+
+    /*
+     * For demo and debug purposes, make our colors a function of the
+     * intensity of the given color value and the object type.  The color
+     * values could represent almost anything.  However based upon the
+     * number of color values, we are assuming that they are either
+     * gray, RGB, or CMYK values.
+     */
+    for (i = 0; i < num_values; i++)
+	frac_color[i] = convert2frac(pc->paint.values[i],
+		       	pcs->params.icc.picc_info->Range.ranges[i]);
+    switch (num_values) {
+	case 0:
+	case 2:
+	    return_error(e_rangecheck);
+	case 1:
+	    return client_remap_DeviceGray(pparams, frac_color, pcs,
+			   		 pdc, pis, dev, select);
+	case 3:
+	    return client_remap_DeviceRGB(pparams, frac_color, pcs,
+			   		 pdc, pis, dev, select);
+	case 4:
+	default:
+	    return client_remap_DeviceCMYK(pparams, frac_color, pcs,
+			   		 pdc, pis, dev, select);
+    }
+}
+
+#undef convert2frac
+
+#endif 		/* OBJECT_TYPE_EXAMPLE */
+
+#if OBJECT_TYPE_EXAMPLE
+/*
+ * Client call back procedures for our demo which illustrates color
+ * processing based upon object type.
+ */
+client_custom_color_procs_t demo_procs = {
+    client_install_DeviceGray,		/* DeviceGray */
+    client_remap_DeviceGray,
+    client_install_DeviceRGB,		/* DeviceRGB */
+    client_remap_DeviceRGB,
+    client_install_DeviceCMYK,		/* DeviceCMYK */
+    client_remap_DeviceCMYK,
+    client_pantone_install_Separation,	/* Separation */
+    client_pantone_remap_Separation,
+    client_pantone_install_DeviceN,	/* DeviceN */
+    client_pantone_remap_DeviceN,
+    client_install_generic,		/* CIEBasedA */
+    client_remap_CIEBasedA,
+    client_install_generic,		/* CIEBasedABC */
+    client_remap_CIEBasedABC,
+    client_install_generic,		/* CIEBasedDEF */
+    client_remap_CIEBasedDEF,
+    client_install_generic,		/* CIEBasedDEFG */
+    client_remap_CIEBasedDEFG,
+    client_install_generic,		/* ICCBased */
+    client_remap_ICCBased
+};
+#else			/* Not OBJECT_TYPE_EXAMPLE special */
+/*
+ * For PANTONE colors, we only need to handle Separation and DeviceN
+ * color spaces.  These are the only color spaces that can have PANTONE
+ * colors.
+ */
+client_custom_color_procs_t demo_procs = {
+    client_install_no_op,		/* DeviceGray */
+    client_remap_simple_no_op,
+    client_install_no_op,		/* DeviceRGB */
+    client_remap_simple_no_op,
+    client_install_no_op,		/* DeviceCMYK */
+    client_remap_simple_no_op,
+    client_pantone_install_Separation,	/* Separation */
+    client_pantone_remap_Separation,
+    client_pantone_install_DeviceN,	/* DeviceN */
+    client_pantone_remap_DeviceN,
+    client_install_no_op,		/* CIEBasedA */
+    client_remap_complex_no_op,
+    client_install_no_op,		/* CIEBasedABC */
+    client_remap_complex_no_op,
+    client_install_no_op,		/* CIEBasedDEF */
+    client_remap_complex_no_op,
+    client_install_no_op,		/* CIEBasedDEFG */
+    client_remap_complex_no_op,
+    client_install_no_op,		/* ICCBased */
+    client_remap_complex_no_op
+};
+#endif		/* OBJECT_TYPE_EXAMPLE */
+
+#endif		/* ENABLE_CUSTOM_COLOR_CALLBACK */

Added: trunk/gs/src/gsncdummy.h
===================================================================
--- trunk/gs/src/gsncdummy.h	2007-04-06 02:39:31 UTC (rev 7823)
+++ trunk/gs/src/gsncdummy.h	2007-04-06 02:43:19 UTC (rev 7824)
@@ -0,0 +1,31 @@
+/* Copyright (C) 2001-2007 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.
+*/
+/* Global definitions for the example custom color callback handling. */
+
+#ifndef gsncdummy_INCLUDED
+#define gsncdummy_INCLUDED
+
+#if ENABLE_CUSTOM_COLOR_CALLBACK		/* Defined in src/gsnamecl.h */
+
+/*
+ * This s a list of PANTONE color names and a set of equivalent CMYK values,
+ */
+typedef struct pantone_list_s {
+    const char *name;		/* Name of the PANTONE color */
+    double c, m, y, k;		/* Equivalent CMYK values */
+} pantone_list_t;
+
+
+#endif		/* if ENABLE_CUSTOM_COLOR_CALLBACK */
+
+#endif		/* if gsncdummy_INCLUDED */

Added: trunk/gs/src/zncdummy.c
===================================================================
--- trunk/gs/src/zncdummy.c	2007-04-06 02:39:31 UTC (rev 7823)
+++ trunk/gs/src/zncdummy.c	2007-04-06 02:43:19 UTC (rev 7824)
@@ -0,0 +1,102 @@
+/* Copyright (C) 2001-2007 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: zncdummy.c.c 7795 2007-03-23 13:56:11Z tim $ */
+/* Sample implementation for client custom processing of color spaces. */
+
+/*
+ * This module has been created to demonstrate how to add support for the use
+ * of custom color handling to the Ghostscript graphics library via a custom color
+ * callback mechanism.
+ *
+ * See the comments at the start of src/gsncdummy.c for more information.
+ */
+
+#include "math_.h"
+#include "memory_.h"
+#include "gx.h"
+#include "gscdefs.h"
+#include "gsnamecl.h"
+#include "malloc_.h"
+#include "ghost.h"
+#include "oper.h"
+#include "gsncdummy.h"
+
+#if ENABLE_CUSTOM_COLOR_CALLBACK
+
+extern pantone_list_t pantone_list[];
+extern client_custom_color_procs_t demo_procs;
+
+/*
+ * Demo version of the PANTONE call back parameter structure.
+ */
+client_custom_color_params_t demo_callback = {
+    &demo_procs,
+    /*
+     * Use our 'list' of Pantone colors as an example data.
+     */
+    (void *)(&pantone_list)
+};
+
+#endif 			/* ENABLE_CUSTOM_COLOR_CALLBACK */
+
+/*
+ * This procedure is here to simplify debugging.  Normally one would expect the
+ * custom color callback structure to be set up by a calling application.
+ * Since I do not have a calling application, I need a simple way to setup the
+ * callback parameter.  The callback parameter is passed as a string value.
+ * This routine puts the address of our demo callback structure into the
+ * provided string.
+ *
+ * This routine allows the demo version of the PANTONE logic to be enabled
+ * by adding the following to the command line:
+ *  -c "<< /CustomColorCallback 32 string .pantonecallback >> setsystemparams" -f
+ */
+
+/* <string> .pantonecallback <string> */
+private int
+zpantonecallback(i_ctx_t *i_ctx_p)
+{
+#if ENABLE_CUSTOM_COLOR_CALLBACK
+    os_ptr op = osp;
+    int val, idx, buf_pos = 3;
+    size_t iptr;
+#define PTR_STRING_SIZE (2 * size_of(void *) + 3)
+
+    /* Verify that the string size is big enough for our output */
+    check_type(*op, t_string);
+    check_write(*op);
+    if (r_size(op) < PTR_STRING_SIZE)
+	return_error(e_rangecheck);
+
+    /* Convert our call back parameter structure pointer into a string */
+    op->value.bytes[0] = '1';
+    op->value.bytes[1] = '6';
+    op->value.bytes[2] = '#';
+    iptr = (size_t)(&demo_callback);
+    for (idx = ((int)size_of(size_t)) * 8 - 4; idx >= 0; idx -= 4) {
+	val = (int)(iptr >> idx) & 0xf;
+	op->value.bytes[buf_pos++] = (byte)((val <= 9) ? '0' + val
+						       : 'a' - 10 + val);
+    }
+    r_size(op) = PTR_STRING_SIZE;
+#endif 			/* ENABLE_CUSTOM_COLOR_CALLBACK */
+    return 0;
+}
+
+/* ------ Initialization procedure ------ */
+
+const op_def pantone_op_defs[] =
+{
+    {"1.pantonecallback", zpantonecallback},
+    op_def_end(0)
+};



More information about the gs-cvs mailing list