[gs-cvs] rev 7795 - in trunk/gs: lib src
tim at ghostscript.com
tim at ghostscript.com
Fri Mar 23 06:56:19 PDT 2007
Author: tim
Date: 2007-03-23 06:56:11 -0700 (Fri, 23 Mar 2007)
New Revision: 7795
Modified:
trunk/gs/lib/pdf_main.ps
trunk/gs/lib/pdf_ops.ps
trunk/gs/src/gdevbbox.c
trunk/gs/src/gdevdevn.c
trunk/gs/src/gdevdevn.h
trunk/gs/src/gdevdflt.c
trunk/gs/src/gdevdsp.c
trunk/gs/src/gdevnfwd.c
trunk/gs/src/gdevp14.c
trunk/gs/src/gdevp14.h
trunk/gs/src/gdevpbm.c
trunk/gs/src/gdevpnga.c
trunk/gs/src/gdevprn.c
trunk/gs/src/gdevpsd.c
trunk/gs/src/gdevrops.c
trunk/gs/src/gdevtsep.c
trunk/gs/src/gscdevn.c
trunk/gs/src/gscie.c
trunk/gs/src/gsciemap.c
trunk/gs/src/gscolor2.c
trunk/gs/src/gscscie.c
trunk/gs/src/gscsepr.c
trunk/gs/src/gscspace.c
trunk/gs/src/gscspace.h
trunk/gs/src/gsdparam.c
trunk/gs/src/gsdps1.c
trunk/gs/src/gsicc.c
trunk/gs/src/gsimage.c
trunk/gs/src/gsnamecl.c
trunk/gs/src/gsnamecl.h
trunk/gs/src/gsncdemo.c
trunk/gs/src/gspaint.c
trunk/gs/src/gsstate.c
trunk/gs/src/gsstate.h
trunk/gs/src/gstext.c
trunk/gs/src/gstrans.c
trunk/gs/src/gstrans.h
trunk/gs/src/gsutil.c
trunk/gs/src/gxblend.c
trunk/gs/src/gxblend.h
trunk/gs/src/gxcie.h
trunk/gs/src/gxclip.c
trunk/gs/src/gxclip2.c
trunk/gs/src/gxclipm.c
trunk/gs/src/gxclist.c
trunk/gs/src/gxcmap.c
trunk/gs/src/gxdcolor.h
trunk/gs/src/gxdevcli.h
trunk/gs/src/gxdevice.h
trunk/gs/src/gxistate.h
trunk/gs/src/iparam.c
trunk/gs/src/lib.mak
trunk/gs/src/zcolor3.c
trunk/gs/src/zfapi.c
trunk/gs/src/ztrans.c
trunk/gs/src/zusparam.c
Log:
Custom color hooks code merge
Modified: trunk/gs/lib/pdf_main.ps
===================================================================
--- trunk/gs/lib/pdf_main.ps 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/lib/pdf_main.ps 2007-03-23 13:56:11 UTC (rev 7795)
@@ -461,6 +461,7 @@
if
pdfopenfile begin
pdfopencache
+ writeoutputintents
.writepdfmarks {
% Copy bookmarks (outline) to the output.
Trailer /Root oget /Outlines knownoget {
@@ -1147,6 +1148,10 @@
} ifelse
% Don't change the page size if we are going to fit the PDF to the page
systemdict /PDFFitPage known { currentdict /PageSize undef } if
+ % Determine the number of spot colors used on the page. Note: This searches
+ % the pages resources. It may be high if a spot color is in a resource but
+ % is not actually used on the page.
+ << /PageSpotColors 3 index countspotcolors >> setpagedevice
% Let the device know if we will be using PDF 1.4 transparency.
% The clist logic may need to adjust the size of bands.
1 index pageusestransparency /PageUsesTransparency exch def
@@ -1274,6 +1279,9 @@
% problems, for example with the pnga device.
endpage
end % scratch dict
+ % Indicate that the number of spot colors is unknown in case the next page
+ % imaged is a PS file.
+ << /PageSpotColors -1 >> setpagedevice
% Some PDF files don't have matching q/Q (gsave/grestore) so we need
% to clean up any left over dicts from the dictstack
countdictstack PDFdictstackcount sub dup 0 ne {
@@ -1409,6 +1417,119 @@
} if
} bind def
+% Add a color name to our spot color list. Ignore /All and /None
+/putspotcolor { % <name> <spotcolordict> putspotcolor -
+ % The 'name' could be a string. If so then convert to a name.
+ exch dup type /stringtype eq { cvn } if
+ dup dup /None eq exch /All eq or { pop pop } { 0 put } ifelse
+} bind def
+
+% Determine which spot colors are used within a color space Note: This
+% dict will include all colors used in Separation or DeviceN color spaces.
+% Thus it may include Cyan, Magenta, Yellow, and Black.
+% <colorspace> <spotcolordict> colorspacespotcolors -
+/colorspacespotcolors {
+ exch dup type /arraytype eq {
+ % If we have an Indexed color space then get the base space.
+ dup 0 oget dup /Indexed eq {
+ pop 1 oget 2 copy colorspacespotcolors
+ } {
+ % Stack: <spotcolordict> <colorspace> <colorspacetype>
+ dup /Separation eq exch /DeviceN eq or {
+ dup 1 oget dup type /arraytype eq {
+ { oforce 2 index putspotcolor } forall
+ } {
+ 2 index putspotcolor
+ } ifelse
+ } if
+ } ifelse
+ } if
+ pop pop
+} bind def
+
+% Check the Resources of a page, form, or annotation. Determine which spot
+% colors are used within the resource Note: The spot color dict will include
+% all colors used in Separation or DeviceN color spaces. Thus it may include
+% Cyan, Magenta, Yellow, and Black. We also pass a dict that is used to check
+% for loops in the resource list.
+% <spotcolordict> <loopdict> <page/form/annot dict>
+% resourcespotcolors <spotcolordict> <loopdict>
+/resourcespotcolors {
+ { % Use loop to provide an exitable context.
+ % Exit if no Resources entry
+ /Resources knownoget not { exit } if
+ % Exit if we have already seen this dict
+ 2 copy known { pop exit } if
+
+ % Save the Resources dict into our loop checking dict.
+ 2 copy 0 put
+
+ % Scan resources that might contain a color space.
+ dup /ColorSpace knownoget {
+ { exch pop oforce 3 index colorspacespotcolors } forall
+ } if
+ dup /Pattern knownoget {
+ { exch pop oforce 4 copy exch pop resourcespotcolors pop pop pop } forall
+ } if
+ dup /Shading knownoget {
+ { exch pop oforce /ColorSpace oget 3 index colorspacespotcolors } forall
+ } if
+ /XObject knownoget {
+ { exch pop oforce dup
+ /Subtype get /Form eq { resourcespotcolors } { pop } ifelse
+ } forall
+ } if
+ exit
+ } loop
+} bind def
+
+% Determine which spot colors are used within the annotations. Note: This
+% dict will include all colors used in Separation or DeviceN color spaces.
+% Thus it may include Cyan, Magenta, Yellow, and Black.
+% <spotcolordict> <loopdict> <annotsarray>
+% annotsspotcolors <spotcolordict> <loopdict>
+/annotsspotcolors {
+ { oforce /AP knownoget { % Get appearance dict for the annoation
+ /N knownoget { % Get the /N (i.e. normal) appearance stream
+ resourcespotcolors
+ } if % If normal appearance streamknown
+ } if % If AP dict known
+ } forall
+} bind def
+
+% Determine spot colors are used within a page. We are creating a dict to
+% hold the spot color names as keys. Using a dict avoids having to worry
+% about duplicate entries. The keys in the dict contain the spot color
+% names. However the values have no meaning. Note: This dict will include
+% all colors used in Separation or DeviceN color spaces specified in the
+% page's resources. Thus it may include Cyan, Magenta, Yellow, and Black.
+% There is no attempt to verify that these color spaces are actually used
+% within the object streams for the page.
+/pagespotcolors { % <pagedict> pagespotcolors <spotcolordict>
+ dup
+ % Create a dict to hold spot color names.
+ 0 dict exch
+ % Create a dict to be used to check for reference loops.
+ 4 dict exch
+ % Check for color spaces in the Resources
+ resourcespotcolors
+ % Also check for color spaces in the annotations.
+ 3 -1 roll
+ /Annots knownoget { annotsspotcolors } if
+ pop % Discard reference loop dict
+} bind def
+
+% Determine how many (if any) spot colors are used by a page.
+% Note: This count does not include Cyan, Magenta, Yellow, or Black
+/countspotcolors { % <pagedict> countspotcolors <count>
+ pagespotcolors % Get dict with all spot colors
+ dup length % spot color dict length
+ % Remove CMYK from the spot color count.
+ [ /Cyan /Magenta /Yellow /Black ]
+ { 2 index exch known { 1 sub } if } forall
+ exch pop % Remove spot color dict
+} bind def
+
% ------ ColorSpace substitution support ------ %
%
@@ -1458,7 +1579,47 @@
}
bind def
+% Write OutputIntents to device if the device handles it
+/writeoutputintents {
+ currentdevice 1 dict dup /OutputIntent null put readonly
+ .getdeviceparams
+ mark ne { pop pop
+ % device supports OutputIntent parameter
+ Trailer /Root oget /OutputIntents knownoget {
+ { % process all output profiles present
+ dup length dict .copydict
+ dup /DestOutputProfile knownoget {
+ PDFfile fileposition exch
+ mark exch { oforce } forall .dicttomark
+ true resolvestream
+ [ { counttomark 1 add index
+ 64000 string readstring
+ not { exit} if
+ } loop
+ ] exch closefile
+ 0 1 index { length add } forall .bytestring
+ 0 3 2 roll {
+ 3 copy putinterval
+ length add
+ } forall pop
+ exch PDFfile exch setfileposition
+ 1 index /DestOutputProfile 3 2 roll put
+ } if
+ % Convert to string array because it's easier for the device
+ [ 1 index /OutputCondition knownoget not { () } if
+ 2 index /OutputConditionIdentifier knownoget not { () } if
+ 3 index /RegistryName knownoget not { () } if
+ 4 index /Info knownoget not { () } if
+ 5 index /DestOutputProfile knownoget not { () } if
+ ]
+ [ /OutputIntent 3 2 roll .pdfputparams pop pop
+ pop % done with this OutputIntent dictionary
+ } forall
+ } if % OutputIntents known
+ % tell device there are no more OutputIntents
+ [ /OutputIntent [ ] .pdfputparams pop pop
+ } if
+} bind def
-
end % pdfdict
.setglobal
Modified: trunk/gs/lib/pdf_ops.ps
===================================================================
--- trunk/gs/lib/pdf_ops.ps 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/lib/pdf_ops.ps 2007-03-23 13:56:11 UTC (rev 7795)
@@ -25,6 +25,13 @@
systemdict /pdfmark known not
{ userdict /pdfmark { cleartomark } bind put } if
+/renderingintentdict mark
+ /Absolute 0
+ /RelativeColorimetric 1
+ /Saturation 2
+ /Perceptual 3
+.dicttomark readonly def
+
userdict /GS_PDF_ProcSet 127 dict dup begin
% ---------------- Abbreviations ---------------- %
@@ -194,7 +201,7 @@
/K { 4 array astore cvx //csdevcmyk scput } bdef
/cs { csset fcput } bdef
/CS { csset scput } bdef
-/ri { pop } bdef
+/ri { //renderingintentdict exch .knownget { .setrenderingintent } if } bdef
% We have to break up sc according to the number of operands.
/sc1 { /FillColor gput } bdef
/SC1 { /StrokeColor gput } bdef
Modified: trunk/gs/src/gdevbbox.c
===================================================================
--- trunk/gs/src/gdevbbox.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gdevbbox.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -272,6 +272,7 @@
set_dev_proc(dev, update_spot_equivalent_colors,
gx_forward_update_spot_equivalent_colors);
set_dev_proc(dev, get_page_device, gx_forward_get_page_device);
+ set_dev_proc(dev, ret_devn_params, gx_forward_ret_devn_params);
gx_device_set_target((gx_device_forward *)dev, target);
} else {
gx_device_fill_in_procs((gx_device *)dev);
Modified: trunk/gs/src/gdevdevn.c
===================================================================
--- trunk/gs/src/gdevdevn.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gdevdevn.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -25,6 +25,8 @@
#include "gxdcconv.h"
#include "gdevdevn.h"
#include "gsequivc.h"
+#include "gxblend.h"
+#include "gdevp14.h"
/*
* Utility routines for common DeviceN related parameters:
@@ -349,6 +351,7 @@
bool num_spot_changed = false;
int num_order = pdevn_params->num_separation_order_names;
int max_sep = pdevn_params->max_separations;
+ int page_spot_colors = pdevn_params->page_spot_colors;
gs_param_string_array scna; /* SeparationColorNames array */
gs_param_string_array sona; /* SeparationOrder names array */
@@ -415,7 +418,8 @@
num_order = sona.size;
for (i = 0; i < num_spot + npcmcolors; i++)
- pdevn_params->separation_order_map[i] = GX_DEVICE_COLOR_MAX_COMPONENTS;
+ pdevn_params->separation_order_map[i] =
+ GX_DEVICE_COLOR_MAX_COMPONENTS;
for (i = 0; i < num_order; i++) {
/*
* Check if names match either the process color model or
@@ -445,26 +449,30 @@
case 0:
if (max_sep < 1 || max_sep > GX_DEVICE_COLOR_MAX_COMPONENTS)
return_error(gs_error_rangecheck);
-#if !USE_COMPRESSED_ENCODING
- /*
- * If we are not using a compressed pixel encoding, then the
- * device depth (pixel size) varies with the number of
- * separations. The depth is constant with the compressed
- * encoding scheme.
- */
- {
- int depth =
- bpc_to_depth(max_sep, pdevn_params->bitspercomponent);
-
- if (depth > 8 * size_of(gx_color_index))
- return_error(gs_error_rangecheck);
- pdev->color_info.depth = depth;
- }
-#endif
- pdevn_params->max_separations =
- pdev->color_info.max_components =
- pdev->color_info.num_components = max_sep;
}
+ /*
+ * The PDF interpreter scans the resources for pages to try to
+ * determine the number of spot colors. (Unfortuneately there is
+ * no way to determine the number of spot colors for a PS page
+ * except to interpret the entire page.) The spot color count for
+ * a PDF page may be high since there may be spot colors in a PDF
+ * page's resources that are not used. However this does give us
+ * an upper limit on the number of spot colors. A value of -1
+ * indicates that the number of spot colors in unknown (a PS file).
+ */
+ code = param_read_int(plist, param_name = "PageSpotColors",
+ &page_spot_colors);
+ switch (code) {
+ default:
+ param_signal_error(plist, param_name, code);
+ case 1:
+ break;
+ case 0:
+ if (page_spot_colors < -1)
+ return_error(gs_error_rangecheck);
+ if (page_spot_colors > GX_DEVICE_COLOR_MAX_COMPONENTS)
+ page_spot_colors = GX_DEVICE_COLOR_MAX_COMPONENTS;
+ }
/*
* The DeviceN device can have zero components if nothing has been
* specified. This causes some problems so force at least one
@@ -477,10 +485,14 @@
* SeparationColorNames, SeparationOrder, or MaxSeparations.
*/
if (num_spot_changed || pdevn_params->max_separations != max_sep ||
- pdevn_params->num_separation_order_names != num_order) {
+ pdevn_params->num_separation_order_names != num_order ||
+ pdevn_params->page_spot_colors != page_spot_colors) {
pdevn_params->separations.num_separations = num_spot;
pdevn_params->num_separation_order_names = num_order;
pdevn_params->max_separations = max_sep;
+ pdevn_params->page_spot_colors = page_spot_colors;
+ if (max_sep != 0)
+ pdev->color_info.max_components = max_sep;
/*
* If we have SeparationOrder specified then the number of
* components is given by the number of names in the list.
@@ -489,10 +501,17 @@
* of ProcessColorModel components plus the number of
* SeparationColorNames is used.
*/
- pdev->color_info.num_components = (num_order) ? num_order
+ pdev->color_info.num_components = (num_order)
+ ? num_order
: (pdevn_params->max_separations)
- ? pdevn_params->max_separations
- : npcmcolors + num_spot;
+ ? pdevn_params->max_separations
+ : (page_spot_colors >= 0)
+ ? npcmcolors + num_spot + page_spot_colors
+ : pdev->color_info.max_components;
+ if (pdev->color_info.num_components >
+ pdev->color_info.max_components)
+ pdev->color_info.num_components =
+ pdev->color_info.max_components;
#if !USE_COMPRESSED_ENCODING
/*
* See earlier comment about the depth and non compressed
@@ -550,7 +569,15 @@
/* Reset the sparable and linear shift, masks, bits. */
set_linear_color_bits_mask_shift(pdev);
}
-
+ /*
+ * Also check for parameters which are being passed from the PDF 1.4
+ * compositior clist write device. This device needs to pass info
+ * to the PDF 1.4 compositor clist reader device. However this device
+ * is not crated until the clist is being read. Thus we have to buffer
+ * this info in the output device. (This is only needed for devices
+ * which support spot colors.)
+ */
+ code = pdf14_put_devn_params(pdev, pdevn_params, plist);
return code;
}
@@ -643,7 +670,7 @@
/*
* Allocate an list level element for our encode color list.
*/
-private compressed_color_list_t *
+compressed_color_list_t *
alloc_compressed_color_list_elem(gs_memory_t * mem, int num_comps)
{
compressed_color_list_t * plist =
@@ -659,6 +686,43 @@
}
/*
+ * Free the elements of a compressed color list.
+ */
+void
+free_compressed_color_list(gs_memory_t * mem,
+ compressed_color_list_t * pcomp_list)
+{
+ int i;
+
+ if (pcomp_list == NULL)
+ return;
+
+ /* Discard the sub levels. */
+ for (i = 0; i < pcomp_list->num_sub_level_ptrs; i++)
+ free_compressed_color_list(mem, pcomp_list->u.sub_level_ptrs[i]);
+
+ gs_free_object(mem, pcomp_list, "free_compressed_color_list");
+ return;
+}
+
+/*
+ * Free a set of separation names
+ */
+void
+free_separation_names(gs_memory_t * mem,
+ gs_separations * pseparation)
+{
+ int i;
+
+ /* Discard the sub levels. */
+ for (i = 0; i < pseparation->num_separations; i++)
+ gs_free_object(mem, pseparation->names[i].data,
+ "free_separation_names");
+ pseparation->num_separations = 0;
+ return;
+}
+
+/*
* Add a new set of bit mapped colorant lists to our list of encoded color
* colorants.
*/
@@ -840,7 +904,7 @@
* the number of colorants being used times size of the colorant value saved
* must fit into a gx_color_index value.
*/
-static int num_comp_bits[MAX_ENCODED_COMPONENTS + 1] = {
+int num_comp_bits[MAX_ENCODED_COMPONENTS + 1] = {
8, /* 0 colorants - not used */
8, /* 1 colorants */
8, /* 2 colorants */
@@ -868,7 +932,7 @@
#define gx_color_value_factor(num_bits) \
((gx_max_color_value << 8) + 0xff) / ((1 << num_bits) - 1)
-static int comp_bit_factor[MAX_ENCODED_COMPONENTS + 1] = {
+int comp_bit_factor[MAX_ENCODED_COMPONENTS + 1] = {
gx_color_value_factor(8), /* 0 colorants (8 bits) */
gx_color_value_factor(8), /* 1 colorants (8 bits) */
gx_color_value_factor(8), /* 2 colorants (8 bits) */
@@ -1193,7 +1257,7 @@
/*
* Find the bit map for given bit map index.
*/
-private comp_bit_map_list_t *
+comp_bit_map_list_t *
find_bit_map(gx_color_index index, compressed_color_list_t * pcomp_list)
{
int loc = (int)(index >> (NUM_GX_COLOR_INDEX_BITS - 8));
@@ -1336,8 +1400,6 @@
*out++ = solid_color >> 8;
else {
*out++ = (factor * ((int)color & bit_mask)) >> 16;
- if (comp_num == 3 && out[-1] != 0)
- comp_num = comp_num;
color >>= bit_count;
}
}
@@ -1521,6 +1583,7 @@
DeviceCMYKComponents, /* Names of color model colorants */
4, /* Number colorants for CMYK */
0, /* MaxSeparations has not been specified */
+ -1, /* PageSpotColors has not been specified */
{0}, /* SeparationNames */
0, /* SeparationOrder names */
{0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
@@ -1540,6 +1603,7 @@
NULL, /* No names for standard DeviceN color model */
0, /* No standard colorants for DeviceN */
0, /* MaxSeparations has not been specified */
+ -1, /* PageSpotColors has not been specified */
{0}, /* SeparationNames */
0, /* SeparationOrder names */
{0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
Modified: trunk/gs/src/gdevdevn.h
===================================================================
--- trunk/gs/src/gdevdevn.h 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gdevdevn.h 2007-03-23 13:56:11 UTC (rev 7795)
@@ -90,6 +90,15 @@
fixed_colorant_names_list std_colorant_names;
int num_std_colorant_names; /* Number of names in list */
int max_separations; /* From MaxSeparation parameter */
+ /*
+ * This value comes from scanning color space resources in PDF files.
+ * Thus this value is only valid for PDF files. The value may also
+ * be high if there are color space resources that are defined for
+ * a page but which are not actually used. This value does give us
+ * a maximum value for the number of spot colors.
+ * From the PageSpotColors parameter.
+ */
+ int page_spot_colors;
/*
* Separation info (if any).
@@ -109,9 +118,23 @@
* Pointer to our list of which colorant combinations are being used.
*/
struct compressed_color_list_s * compressed_color_list;
+ /*
+ * If the file is using PDF 1.4 transparency compositing and we are using
+ * the clist then we need to pass the compressed color list from the PDF
+ * 1.4 clist writer device to the PDF 1.4 reader device. However that
+ * device is not created until the clist is read and being processed.
+ * We need to temporary hold that data in the output device until after
+ * clist reader PDF 1.4 compositing device is created. The PDF 1.4
+ * compositor may also have a different list of separations.
+ */
+ struct compressed_color_list_s * pdf14_compressed_color_list;
+ gs_separations pdf14_separations;
} gs_devn_params_t;
-typedef gs_devn_params_t gs_devn_params;
+#ifndef gs_devn_params_DEFINED
+# define gs_devn_params_DEFINED
+typedef struct gs_devn_params_s gs_devn_params;
+#endif
extern fixed_colorant_name DeviceCMYKComponents[];
@@ -465,9 +488,53 @@
int width, byte * in, byte * out);
/*
+ * Find the bit map for given bit map index.
+ */
+comp_bit_map_list_t * find_bit_map(gx_color_index index,
+ compressed_color_list_t * pcomp_list);
+
+/*
+ * Allocate an list level element for our encode color list.
+ */
+compressed_color_list_t * alloc_compressed_color_list_elem(gs_memory_t * mem,
+ int num_comps);
+
+/*
+ * The elements of this array contain the number of bits used to encode a color
+ * value in a 'compressed' gx_color_index value. The index into the array is
+ * the number of compressed components.
+ */
+extern int num_comp_bits[];
+
+/*
+ * Values used to decompressed the colorants in our encoded values back into
+ * a gx_color value. The color value will be (comp_bits * entry) >> 8
+ * The number of bits in comp_bits are defined in the num_comp_bits table.
+ * These values are chosen to expand these bit combinations back to 16 bit values
+ * (after shifting right 8 bits).
+ */
+/*
+ * The elements of this array contain factors used to convert compressed color
+ * values to gx_color_values. The index into the array is the number of
+ * compressed components.
+ */
+extern int comp_bit_factor[];
+
+/*
* A routine for debugging the encoded color colorant list. This routine
* dumps the contents of the list.
*/
void print_compressed_color_list(compressed_color_list_t * pcomp_list, int num_comp);
+/*
+ * Free the elements of a compressed color list.
+ */
+void free_compressed_color_list(gs_memory_t * mem,
+ compressed_color_list_t * pcomp_list);
+
+/*
+ * Free a set of separation names
+ */
+void free_separation_names(gs_memory_t * mem, gs_separations * pseparation);
+
#endif /* ifndef gdevdevn_INCLUDED */
Modified: trunk/gs/src/gdevdflt.c
===================================================================
--- trunk/gs/src/gdevdflt.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gdevdflt.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -665,6 +665,7 @@
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);
+ fill_dev_proc(dev, ret_devn_params, gx_default_ret_devn_params);
}
int
@@ -889,7 +890,7 @@
}
/*
- * If a device want to determine an equivalent color for its spot colors then
+ * If a device wants 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.
*/
@@ -899,6 +900,16 @@
return 0;
}
+/*
+ * If a device wants to determine implement support for spot colors then
+ * it needs to implement this method.
+ */
+gs_devn_params *
+gx_default_ret_devn_params(gx_device *pdev)
+{
+ return NULL;
+}
+
/* ---------------- Default per-instance procedures ---------------- */
int
Modified: trunk/gs/src/gdevdsp.c
===================================================================
--- trunk/gs/src/gdevdsp.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gdevdsp.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -89,6 +89,7 @@
private dev_proc_encode_color(display_separation_encode_color);
private dev_proc_decode_color(display_separation_decode_color);
private dev_proc_update_spot_equivalent_colors(display_update_spot_equivalent_colors);
+private dev_proc_ret_devn_params(display_ret_devn_params);
private const gx_device_procs display_procs =
@@ -153,7 +154,8 @@
NULL, /* fill_linear_color_scanline */\
NULL, /* fill_linear_color_trapezoid */\
NULL, /* fill_linear_color_triangle */\
- display_update_spot_equivalent_colors /* update_spot_equivalent_colors */
+ display_update_spot_equivalent_colors, /* update_spot_equivalent_colors */
+ display_ret_devn_params /* ret_devn_params */\
};
/* GC descriptor */
@@ -207,6 +209,7 @@
DeviceCMYKComponents, /* Names of color model colorants */
4, /* Number of colorants for CMYK */
0, /* MaxSeparations has not been specified */
+ -1, /* PageSpotColors has not been specified */
{0}, /* SeparationNames */
{0}, /* SeparationOrder names */
{0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
@@ -1166,6 +1169,17 @@
}
/*
+ * Device proc for returning a pointer to DeviceN parameter structure
+ */
+private gs_devn_params *
+display_ret_devn_params(gx_device * dev)
+{
+ gx_device_display * pdev = (gx_device_display *)dev;
+
+ return &pdev->devn_params;
+}
+
+/*
* This routine will check to see if the color component name match those
* that are available amoung the current device's color components.
*
Modified: trunk/gs/src/gdevnfwd.c
===================================================================
--- trunk/gs/src/gdevnfwd.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gdevnfwd.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -104,6 +104,7 @@
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);
+ fill_dev_proc(dev, ret_devn_params, gx_forward_ret_devn_params);
gx_device_fill_in_procs((gx_device *) dev);
}
@@ -843,7 +844,18 @@
return code;
}
+gs_devn_params *
+gx_forward_ret_devn_params(gx_device *dev)
+{
+ gx_device_forward * const fdev = (gx_device_forward *)dev;
+ gx_device *tdev = fdev->target;
+ if (tdev != NULL)
+ return dev_proc(tdev, ret_devn_params)(tdev);
+ return NULL;
+}
+
+
/* ---------------- The null device(s) ---------------- */
private dev_proc_get_initial_matrix(gx_forward_upright_get_initial_matrix);
Modified: trunk/gs/src/gdevp14.c
===================================================================
--- trunk/gs/src/gdevp14.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gdevp14.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -31,6 +31,7 @@
#include "gsimage.h"
#include "gsrect.h"
#include "gzstate.h"
+#include "gdevdevn.h"
#include "gdevp14.h"
#include "gsovrc.h"
#include "gxcmap.h"
@@ -38,7 +39,20 @@
#include "gstrans.h"
#include "gsutil.h"
#include "gxcldev.h"
+#include "gxdcconv.h"
+/*
+ * We chose the blending color space based upon the process color model of the
+ * output device. For gray, RGB, CMYK, or CMYK+spot devices, the choice is
+ * usually simple. For other devices or if the user is doing custom color
+ * processing then the user may want to control this choice.
+ */
+#define AUTO_CUSTOM_BLENDING 0
+#define ALWAYS_USE_CUSTOM_BLENDING 1
+#define DO_NOT_USE_CUSTOM_BLENDING 2
+
+#define CUSTOM_BLENDING_MODE AUTO_CUSTOM_BLENDING
+
/* #define DUMP_TO_PNG */
#ifdef DUMP_TO_PNG
@@ -49,7 +63,7 @@
/* Buffer stack data structure */
-#define PDF14_MAX_PLANES 16
+#define PDF14_MAX_PLANES GX_DEVICE_COLOR_MAX_COMPONENTS
/* GC procedures for buffer stack */
@@ -77,6 +91,115 @@
pdf14_ctx_enum_ptrs, pdf14_ctx_reloc_ptrs,
stack, maskbuf);
+/*
+ * Unpack a device color. This routine is similar to the device's
+ * decode_color procedure except for two things. The procedure produces 1
+ * byte values instead of gx_color_values (2 bytes) and the output values
+ * are inverted for subtractive color spaces (like CMYK). A separate
+ * procedure is used instead of the decode_color to minimize execution time.
+ */
+private void
+pdf14_unpack_additive(int num_comp, gx_color_index color,
+ pdf14_device * p14dev, byte * out)
+{
+ int i;
+
+ for (i = num_comp - 1; i >= 0; i--) {
+ out[i] = (byte)(color & 0xff);
+ color >>= 8;
+ }
+}
+
+/*
+ * Unpack a device color. This routine is similar to the device's
+ * decode_color procedure except for two things. The procedure produces 1
+ * byte values instead of gx_color_values (2 bytes) and the output values
+ * are inverted for subtractive color spaces (like CMYK). A separate
+ * procedure is used instead of the decode_color to minimize execution time.
+ */
+private void
+pdf14_unpack_subtractive(int num_comp, gx_color_index color,
+ pdf14_device * p14dev, byte * out)
+{
+ int i;
+
+ for (i = num_comp - 1; i >= 0; i--) {
+ out[i] = 0xff - (byte)(color & 0xff);
+ color >>= 8;
+ }
+}
+
+/*
+ * Unpack a 'compressed' CMYK color index. The color index value is unpacked
+ * into a set of 8 bit values. For more information about 'compressed' color
+ * index values see the comments before the devn_encode_compressed_color routine.
+ *
+ * Note: For simplicity of coding the calling routines, this routine will also
+ * handle 'uncompressed' color index values.
+ */
+private void
+pdf14_unpack_compressed(int num_comp, gx_color_index color,
+ pdf14_device * p14dev, byte * out)
+{
+ int comp_num;
+
+ if (p14dev->devn_params.compressed_color_list == NULL) {
+ /*
+ * For 'uncompressed' data we simply have to unpack the gx_color_index
+ * value directly.
+ */
+ for (comp_num = num_comp - 1; comp_num >= 0; comp_num--) {
+ out[comp_num] = 0xff - (byte)(color & 0xff);
+ color >>= 8;
+ }
+ }
+ else {
+ int factor, bit_count, bit_mask;
+ comp_bit_map_list_t * pbitmap;
+ gx_color_value solid_color = 0xff;
+
+ pbitmap = find_bit_map(color,
+ p14dev->devn_params.compressed_color_list);
+ bit_count = num_comp_bits[pbitmap->num_non_solid_comp];
+ bit_mask = (1 << bit_count) - 1;
+ factor = comp_bit_factor[pbitmap->num_non_solid_comp];
+ if (pbitmap->solid_not_100) {
+ solid_color = 0xff - ((factor * ((int)color & bit_mask)) >> 16);
+ color >>= bit_count;
+ }
+ for (comp_num = 0; comp_num < num_comp; comp_num++) {
+ if (colorant_present(pbitmap, colorants, comp_num)) {
+ if (colorant_present(pbitmap, solid_colorants, comp_num))
+ *out++ = (byte)solid_color;
+ else {
+ *out++ = 0xff - ((factor * ((int)color & bit_mask)) >> 16);
+ color >>= bit_count;
+ }
+ }
+ else
+ *out++ = 0xff;
+ }
+ }
+}
+
+/*
+ * Unpack a device color. This routine is used for devices in which we do
+ * not know the details of the process color model. In this case we use
+ * the device's decode_color procedure.
+ */
+private void
+pdf14_unpack_custom(int num_comp, gx_color_index color,
+ pdf14_device * p14dev, byte * out)
+{
+ int i;
+ gx_device * tdev = p14dev->target;
+ gx_color_value cm_values[GX_DEVICE_COLOR_MAX_COMPONENTS];
+
+ dev_proc(tdev, decode_color)(tdev, color, cm_values);
+ for (i = 0; i < num_comp; i++)
+ out[i] = 0xff - gx_color_value_to_byte(cm_values[i]);
+}
+
/* ------ The device descriptors ------ */
/*
@@ -89,8 +212,12 @@
private dev_proc_close_device(pdf14_close);
private int pdf14_output_page(gx_device * pdev, int num_copies, int flush);
private dev_proc_put_params(pdf14_put_params);
+private dev_proc_get_color_comp_index(pdf14_cmykspot_get_color_comp_index);
+private dev_proc_get_color_mapping_procs(pdf14_cmykspot_get_color_mapping_procs);
private dev_proc_encode_color(pdf14_encode_color);
+private dev_proc_encode_color(pdf14_compressed_encode_color);
private dev_proc_decode_color(pdf14_decode_color);
+private dev_proc_decode_color(pdf14_compressed_decode_color);
private dev_proc_fill_rectangle(pdf14_fill_rectangle);
private dev_proc_fill_rectangle(pdf14_mark_fill_rectangle);
private dev_proc_fill_rectangle(pdf14_mark_fill_rectangle_ko_simple);
@@ -105,6 +232,7 @@
private dev_proc_end_transparency_group(pdf14_end_transparency_group);
private dev_proc_begin_transparency_mask(pdf14_begin_transparency_mask);
private dev_proc_end_transparency_mask(pdf14_end_transparency_mask);
+private int pdf14_clist_get_param_compressed_color_list(pdf14_device * p14dev);
private const gx_color_map_procs *
pdf14_get_cmap_procs(const gs_imager_state *, const gx_device *);
@@ -114,15 +242,15 @@
/* 24-bit color. */
-#define pdf14_procs(get_color_mapping_procs, get_color_comp_index) \
+#define pdf14_dev_procs(get_color_mapping_procs, get_color_comp_index, encode_color, decode_color) \
{\
pdf14_open, /* open */\
NULL, /* get_initial_matrix */\
NULL, /* sync_output */\
pdf14_output_page, /* output_page */\
pdf14_close, /* close */\
- pdf14_encode_color, /* rgb_map_rgb_color */\
- pdf14_decode_color, /* gx_default_rgb_map_color_rgb */\
+ encode_color, /* rgb_map_rgb_color */\
+ decode_color, /* gx_default_rgb_map_color_rgb */\
pdf14_fill_rectangle, /* fill_rectangle */\
NULL, /* tile_rectangle */\
pdf14_copy_mono, /* copy_mono */\
@@ -167,55 +295,215 @@
NULL, /* discard_transparency_layer */\
get_color_mapping_procs, /* get_color_mapping_procs */\
get_color_comp_index, /* get_color_comp_index */\
- pdf14_encode_color, /* encode_color */\
- pdf14_decode_color /* decode_color */\
+ encode_color, /* encode_color */\
+ decode_color, /* decode_color */\
+ NULL, /* pattern_manage */\
+ NULL, /* fill_rectangle_hl_color */\
+ NULL, /* include_color_space */\
+ NULL, /* fill_linear_color_scanline */\
+ NULL, /* fill_linear_color_trapezoid */\
+ NULL, /* fill_linear_color_triangle */\
+ gx_forward_update_spot_equivalent_colors /* update spot */\
}
private const gx_device_procs pdf14_Gray_procs =
- pdf14_procs(gx_default_DevGray_get_color_mapping_procs,
- gx_default_DevGray_get_color_comp_index);
+ pdf14_dev_procs(gx_default_DevGray_get_color_mapping_procs,
+ gx_default_DevGray_get_color_comp_index,
+ pdf14_encode_color, pdf14_decode_color);
private const gx_device_procs pdf14_RGB_procs =
- pdf14_procs(gx_default_DevRGB_get_color_mapping_procs,
- gx_default_DevRGB_get_color_comp_index);
+ pdf14_dev_procs(gx_default_DevRGB_get_color_mapping_procs,
+ gx_default_DevRGB_get_color_comp_index,
+ pdf14_encode_color, pdf14_decode_color);
private const gx_device_procs pdf14_CMYK_procs =
- pdf14_procs(gx_default_DevCMYK_get_color_mapping_procs,
- gx_default_DevCMYK_get_color_comp_index);
+ pdf14_dev_procs(gx_default_DevCMYK_get_color_mapping_procs,
+ gx_default_DevCMYK_get_color_comp_index,
+ pdf14_encode_color, pdf14_decode_color);
+private const gx_device_procs pdf14_CMYKspot_procs =
+ pdf14_dev_procs(pdf14_cmykspot_get_color_mapping_procs,
+ pdf14_cmykspot_get_color_comp_index,
+ pdf14_compressed_encode_color,
+ pdf14_compressed_decode_color);
+
+private const gx_device_procs pdf14_custom_procs =
+ pdf14_dev_procs(gx_forward_get_color_mapping_procs,
+ gx_forward_get_color_comp_index,
+ gx_forward_encode_color,
+ gx_forward_decode_color);
+
gs_private_st_composite_use_final(st_pdf14_device, pdf14_device, "pdf14_device",
pdf14_device_enum_ptrs, pdf14_device_reloc_ptrs,
gx_device_finalize);
+private int pdf14_put_image(gx_device * dev, gs_imager_state * pis,
+ gx_device * target);
+private int pdf14_cmykspot_put_image(gx_device * dev, gs_imager_state * pis,
+ gx_device * target);
+private int pdf14_custom_put_image(gx_device * dev, gs_imager_state * pis,
+ gx_device * target);
+
+private const pdf14_procs_t gray_pdf14_procs = {
+ pdf14_unpack_additive,
+ pdf14_put_image
+};
+
+private const pdf14_procs_t rgb_pdf14_procs = {
+ pdf14_unpack_additive,
+ pdf14_put_image
+};
+
+private const pdf14_procs_t cmyk_pdf14_procs = {
+ pdf14_unpack_subtractive,
+ pdf14_put_image
+};
+
+private const pdf14_procs_t cmykspot_pdf14_procs = {
+ pdf14_unpack_compressed,
+ pdf14_cmykspot_put_image
+};
+
+private const pdf14_procs_t custom_pdf14_procs = {
+ pdf14_unpack_custom,
+ pdf14_custom_put_image
+};
+
+private const pdf14_nonseparable_blending_procs_t gray_blending_procs = {
+ art_blend_luminosity_rgb_8,
+ art_blend_saturation_rgb_8
+};
+
+private const pdf14_nonseparable_blending_procs_t rgb_blending_procs = {
+ art_blend_luminosity_rgb_8,
+ art_blend_saturation_rgb_8
+};
+
+private const pdf14_nonseparable_blending_procs_t cmyk_blending_procs = {
+ art_blend_luminosity_cmyk_8,
+ art_blend_saturation_cmyk_8
+};
+
+private const pdf14_nonseparable_blending_procs_t custom_blending_procs = {
+ art_blend_luminosity_custom_8,
+ art_blend_saturation_custom_8
+};
+
const pdf14_device gs_pdf14_Gray_device = {
std_device_color_stype_body(pdf14_device, &pdf14_Gray_procs, "pdf14gray",
&st_pdf14_device,
XSIZE, YSIZE, X_DPI, Y_DPI, 8, 255, 256),
- { 0 }
+ { 0 }, /* Procs */
+ NULL, /* target */
+ { 0 }, /* devn_params - not used */
+ &gray_pdf14_procs,
+ &gray_blending_procs
};
const pdf14_device gs_pdf14_RGB_device = {
std_device_color_stype_body(pdf14_device, &pdf14_RGB_procs, "pdf14RGB",
&st_pdf14_device,
XSIZE, YSIZE, X_DPI, Y_DPI, 24, 255, 256),
- { 0 }
+ { 0 }, /* Procs */
+ NULL, /* target */
+ { 0 }, /* devn_params - not used */
+ &rgb_pdf14_procs,
+ &rgb_blending_procs
};
const pdf14_device gs_pdf14_CMYK_device = {
std_device_std_color_full_body_type(pdf14_device, &pdf14_CMYK_procs,
- "PDF14cmyk", &st_pdf14_device, XSIZE, YSIZE, X_DPI, Y_DPI, 32,
- 0, 0, 0, 0, 0, 0),
- { 0 }
+ "PDF14cmyk", &st_pdf14_device, XSIZE, YSIZE, X_DPI, Y_DPI, 32,
+ 0, 0, 0, 0, 0, 0),
+ { 0 }, /* Procs */
+ NULL, /* target */
+ { 0 }, /* devn_params - not used */
+ &cmyk_pdf14_procs,
+ &cmyk_blending_procs
};
+const pdf14_device gs_pdf14_CMYKspot_device = {
+ std_device_part1_(pdf14_device, &pdf14_CMYKspot_procs, "PDF14cmykspot", &st_pdf14_device, open_init_closed),
+ dci_values(GX_DEVICE_COLOR_MAX_COMPONENTS,64,255,255,256,256),
+ std_device_part2_(XSIZE, YSIZE, X_DPI, Y_DPI),
+ offset_margin_values(0, 0, 0, 0, 0, 0),
+ std_device_part3_(),
+ { 0 }, /* Procs */
+ NULL, /* target */
+ /* DeviceN parameters */
+ { 8, /* Not used - Bits per color */
+ DeviceCMYKComponents, /* Names of color model colorants */
+ 4, /* Number colorants for CMYK */
+ 0, /* MaxSeparations has not been specified */
+ -1, /* PageSpotColors has not been specified */
+ {0}, /* SeparationNames */
+ 0, /* SeparationOrder names */
+ {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
+ },
+ &cmykspot_pdf14_procs,
+ &cmyk_blending_procs
+};
+
+/*
+ * The 'custom' PDF 1.4 compositor device is for working with those devices
+ * which support spot colors but do not have a CMYK process color model.
+ *
+ * This causes some problems with the Hue, Saturation, Color, and Luminosity
+ * blending modes. These blending modes are 'non separable' and depend upon
+ * knowing the details of the blending color space. However we use the
+ * process color model of the output device for our blending color space.
+ * With an unknown process color model, we have to fall back to some 'guesses'
+ * about how to treat these blending modes.
+ */
+const pdf14_device gs_pdf14_custom_device = {
+ std_device_part1_(pdf14_device, &pdf14_custom_procs, "PDF14custom", &st_pdf14_device, open_init_closed),
+ dci_values(GX_DEVICE_COLOR_MAX_COMPONENTS,64,255,255,256,256),
+ std_device_part2_(XSIZE, YSIZE, X_DPI, Y_DPI),
+ offset_margin_values(0, 0, 0, 0, 0, 0),
+ std_device_part3_(),
+ { 0 }, /* Procs */
+ NULL, /* target */
+ /* DeviceN parameters */
+ { 8, /* Not used - Bits per color */
+ DeviceCMYKComponents, /* Names of color model colorants */
+ 4, /* Number colorants for CMYK */
+ 0, /* MaxSeparations has not been specified */
+ -1, /* PageSpotColors has not been specified */
+ {0}, /* SeparationNames */
+ 0, /* SeparationOrder names */
+ {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
+ },
+ &custom_pdf14_procs,
+ &custom_blending_procs
+};
+
/* GC procedures */
private
-ENUM_PTRS_WITH(pdf14_device_enum_ptrs, pdf14_device *pdev) return 0;
+ENUM_PTRS_WITH(pdf14_device_enum_ptrs, pdf14_device *pdev)
+{
+ index -= 3;
+ if (index < pdev->devn_params.separations.num_separations)
+ ENUM_RETURN(pdev->devn_params.separations.names[index].data);
+ index -= pdev->devn_params.separations.num_separations;
+ if (index < pdev->devn_params.pdf14_separations.num_separations)
+ ENUM_RETURN(pdev->devn_params.pdf14_separations.names[index].data);
+ return 0;
+}
case 0: return ENUM_OBJ(pdev->ctx);
case 1: ENUM_RETURN(gx_device_enum_ptr(pdev->target));
+case 2: ENUM_RETURN(pdev->devn_params.compressed_color_list);
ENUM_PTRS_END
+
private RELOC_PTRS_WITH(pdf14_device_reloc_ptrs, pdf14_device *pdev)
{
+ {
+ int i;
+
+ for (i = 0; i < pdev->devn_params.separations.num_separations; ++i) {
+ RELOC_PTR(pdf14_device, devn_params.separations.names[i].data);
+ }
+ }
+ RELOC_PTR(pdf14_device, devn_params.compressed_color_list);
RELOC_VAR(pdev->ctx);
pdev->target = gx_device_reloc_ptr(pdev->target, gcst);
}
@@ -406,28 +694,29 @@
int n_chan_copy = buf->n_chan + (tos->has_shape ? 1 : 0);
for (i = 0; i < n_chan_copy; i++) {
- byte *buf_ptr = buf_plane;
- byte *tos_ptr = tos_plane;
- int y;
-
- for (y = y0; y < y1; ++y) {
- memcpy (buf_ptr, tos_ptr, width);
- buf_ptr += buf->rowstride;
- tos_ptr += tos->rowstride;
+ byte *buf_ptr = buf_plane;
+ byte *tos_ptr = tos_plane;
+ int y;
+
+ for (y = y0; y < y1; ++y) {
+ memcpy (buf_ptr, tos_ptr, width);
+ buf_ptr += buf->rowstride;
+ tos_ptr += tos->rowstride;
+ }
+ buf_plane += buf->planestride;
+ tos_plane += tos->planestride;
}
- buf_plane += buf->planestride;
- tos_plane += tos->planestride;
- }
if (has_shape && !tos->has_shape)
- memset (buf_plane, 0, buf->planestride);
+ memset (buf_plane, 0, buf->planestride);
+ }
}
- }
- return 0;
+ return 0;
}
private int
-pdf14_pop_transparency_group(pdf14_ctx *ctx)
+pdf14_pop_transparency_group(pdf14_ctx *ctx,
+ const pdf14_nonseparable_blending_procs_t * pblend_procs)
{
pdf14_buf *tos = ctx->stack;
pdf14_buf *nos = tos->saved;
@@ -547,15 +836,13 @@
pix_alpha, shape);
} else if (tos_isolated) {
art_pdf_composite_group_8(nos_pixel, nos_alpha_g_ptr,
- tos_pixel,
- n_chan - 1,
- pix_alpha, blend_mode);
+ tos_pixel, n_chan - 1,
+ pix_alpha, blend_mode, pblend_procs);
} else {
byte tos_alpha_g = tos_ptr[x + tos_alpha_g_offset];
art_pdf_recomposite_group_8(nos_pixel, nos_alpha_g_ptr,
- tos_pixel, tos_alpha_g,
- n_chan - 1,
- pix_alpha, blend_mode);
+ tos_pixel, tos_alpha_g, n_chan - 1,
+ pix_alpha, blend_mode, pblend_procs);
}
if (nos_has_shape) {
nos_ptr[x + nos_shape_offset] =
@@ -685,6 +972,100 @@
return 0;
}
+/*
+ * Encode a list of colorant values into a gx_color_index_value. For more
+ * information about 'compressed' color index values see the comments before
+ * the devn_encode_compressed_color routine.
+ */
+private gx_color_index
+pdf14_compressed_encode_color(gx_device *dev, const gx_color_value colors[])
+{
+ return devn_encode_compressed_color(dev, colors,
+ &(((pdf14_device *)dev)->devn_params));
+}
+
+/*
+ * Decode a gx_color_index value back to a list of colorant values. For more
+ * information about 'compressed' color index values see the comments before
+ * the devn_encode_compressed_color routine.
+ */
+private int
+pdf14_compressed_decode_color(gx_device * dev, gx_color_index color,
+ gx_color_value * out)
+{
+ return devn_decode_compressed_color(dev, color, out,
+ &(((pdf14_device *)dev)->devn_params));
+}
+
+static void
+pdf14_gray_cs_to_cmyk_cm(gx_device * dev, frac gray, frac out[])
+{
+ int num_comp = dev->color_info.num_components;
+
+ out[0] = out[1] = out[2] = frac_0;
+ out[3] = frac_1 - gray;
+ for (--num_comp; num_comp > 3; num_comp--)
+ out[num_comp] = 0;
+}
+
+/*
+ * Default map from DeviceRGB color space to DeviceCMYK color
+ * model. Since this mapping is defined by the PostScript language
+ * it is unlikely that any device with a DeviceCMYK color model
+ * would define this mapping on its own.
+ *
+ * If the imager state is not available, map as though the black
+ * generation and undercolor removal functions are identity
+ * transformations. This mode is used primarily to support the
+ * raster operation (rop) feature of PCL, which requires that
+ * the raster operation be performed in an RGB color space.
+ * Note that default black generation and undercolor removal
+ * functions in PostScript need NOT be identity transformations:
+ * often they are { pop 0 }.
+ */
+static void
+pdf14_rgb_cs_to_cmyk_cm(gx_device * dev, const gs_imager_state *pis,
+ frac r, frac g, frac b, frac out[])
+{
+ int num_comp = dev->color_info.num_components;
+
+ if (pis != 0)
+ color_rgb_to_cmyk(r, g, b, pis, out);
+ else {
+ frac c = frac_1 - r, m = frac_1 - g, y = frac_1 - b;
+ frac k = min(c, min(m, g));
+
+ out[0] = c - k;
+ out[1] = m - k;
+ out[2] = y - k;
+ out[3] = k;
+ }
+ for (--num_comp; num_comp > 3; num_comp--)
+ out[num_comp] = 0;
+}
+
+void
+pdf14_cmyk_cs_to_cmyk_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
+{
+ int num_comp = dev->color_info.num_components;
+
+ out[0] = c;
+ out[1] = m;
+ out[2] = y;
+ out[3] = k;
+ for (--num_comp; num_comp > 3; num_comp--)
+ out[num_comp] = 0;
+}
+static const gx_cm_color_map_procs pdf14_DeviceCMYKspot_procs = {
+ pdf14_gray_cs_to_cmyk_cm, pdf14_rgb_cs_to_cmyk_cm, pdf14_cmyk_cs_to_cmyk_cm
+};
+
+const gx_cm_color_map_procs *
+pdf14_cmykspot_get_color_mapping_procs(const gx_device * dev)
+{
+ return &pdf14_DeviceCMYKspot_procs;
+}
+
#ifdef DUMP_TO_PNG
/* Dumps a planar RGBA image to a PNG file. */
private int
@@ -799,8 +1180,9 @@
* Return code: negative on error.
**/
private int
-pdf14_put_image(pdf14_device *pdev, gs_imager_state *pis, gx_device *target)
+pdf14_put_image(gx_device * dev, gs_imager_state * pis, gx_device * target)
{
+ const pdf14_device * pdev = (pdf14_device *)dev;
int code;
gs_image1_t image;
gs_matrix pmat;
@@ -931,7 +1313,181 @@
return code;
}
+/**
+ * pdf14_cmykspot_put_image: Put rendered image to target device.
+ * @pdev: The PDF 1.4 rendering device.
+ * @pis: State for image draw operation.
+ * @target: The target device.
+ *
+ * Puts the rendered image in @pdev's buffer to @target. This is called
+ * as part of the sequence of popping the PDF 1.4 device filter.
+ *
+ * Return code: negative on error.
+ **/
private int
+pdf14_cmykspot_put_image(gx_device * dev, gs_imager_state * pis, gx_device * target)
+{
+ pdf14_device * pdev = (pdf14_device *)dev;
+ int code = 0;
+ int width = pdev->width;
+ int height = pdev->height;
+ int x, y, tmp, comp_num, output_comp_num;
+ pdf14_buf *buf = pdev->ctx->stack;
+ int planestride = buf->planestride;
+ int num_comp = buf->n_chan - 1;
+ byte *buf_ptr = buf->data;
+ const byte bg = pdev->ctx->additive ? gx_max_color_value : 0;
+ gx_color_index color;
+ gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
+ gx_color_value comp;
+ byte a;
+ int input_map[GX_DEVICE_COLOR_MAX_COMPONENTS];
+ int output_map[GX_DEVICE_COLOR_MAX_COMPONENTS];
+ int num_known_comp = 0;
+ int output_num_comp = target->color_info.num_components;
+ gs_devn_params * pdevn_params = &pdev->devn_params;
+ gs_separations * pseparations = &pdevn_params->separations;
+ int num_sep = pseparations->num_separations++;
+
+ if_debug0('v', "[v]pdf14_cmykspot_put_image\n");
+ /*
+ * The process color model for the PDF 1.4 compositor device is CMYK plus
+ * spot colors. The target device may have only some of these colorants due
+ * to the SeparationOrder device parameter. Thus we need to determine the
+ * mapping between the PDF 1.4 compositor and the target device. Note:
+ * There should not be a spot colorant in the PDF 1.4 device that is not
+ * present in the target device.
+ */
+ /* Check if target processes CMYK colorants. */
+ for (comp_num = 0; comp_num < 4; comp_num++) {
+ const char * pcomp_name = (const char *)DeviceCMYKComponents[comp_num];
+
+ output_comp_num = dev_proc(target, get_color_comp_index)
+ (target, pcomp_name, strlen(pcomp_name), NO_COMP_NAME_TYPE);
+ if (output_comp_num >=0 &&
+ output_comp_num < GX_DEVICE_COLOR_MAX_COMPONENTS) {
+ output_map[num_known_comp] = output_comp_num;
+ input_map[num_known_comp++] = comp_num;
+ }
+ }
+ /* Check if target processes our spot colorants. */
+ for (comp_num = 0; comp_num < num_sep; comp_num++) {
+ output_comp_num = dev_proc(target, get_color_comp_index)
+ (target, (const char *)(pseparations->names[comp_num].data),
+ pseparations->names[comp_num].size, NO_COMP_NAME_TYPE);
+ if (output_comp_num >= 0 &&
+ output_comp_num < GX_DEVICE_COLOR_MAX_COMPONENTS) {
+ output_map[num_known_comp] = output_comp_num;
+ input_map[num_known_comp++] = comp_num + 4;
+ }
+ }
+
+ /* Clear all output colorants first */
+ for (comp_num = 0; comp_num < output_num_comp; comp_num++)
+ cv[comp_num] = 0;
+
+ /* Send pixel data to the target device. */
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+
+ /* composite CMYKA, etc. pixel with over solid background */
+ a = buf_ptr[x + planestride * num_comp];
+
+ if ((a + 1) & 0xfe) {
+ a ^= 0xff;
+ for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
+ comp = buf_ptr[x + planestride * input_map[comp_num]];
+ tmp = ((bg - comp) * a) + 0x80;
+ comp += tmp + (tmp >> 8);
+ cv[output_map[comp_num]] = comp;
+ }
+ } else if (a == 0) {
+ for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
+ cv[output_map[comp_num]] = bg;
+ }
+ } else {
+ for (comp_num = 0; comp_num < num_known_comp; comp_num++) {
+ comp = buf_ptr[x + planestride * input_map[comp_num]];
+ cv[output_map[comp_num]] = (comp << 8) + comp;
+ }
+ }
+ color = dev_proc(target, encode_color)(target, cv);
+ code = dev_proc(target, fill_rectangle)(target, x, y, 1, 1, color);
+ }
+
+ buf_ptr += buf->rowstride;
+ }
+
+ return code;
+}
+
+/**
+ * pdf14_custom_put_image: Put rendered image to target device.
+ * @pdev: The PDF 1.4 rendering device.
+ * @pis: State for image draw operation.
+ * @target: The target device.
+ *
+ * Puts the rendered image in @pdev's buffer to @target. This is called
+ * as part of the sequence of popping the PDF 1.4 device filter.
+ *
+ * Return code: negative on error.
+ **/
+private int
+pdf14_custom_put_image(gx_device * dev, gs_imager_state * pis, gx_device * target)
+{
+ pdf14_device * pdev = (pdf14_device *)dev;
+ int code = 0;
+ int width = pdev->width;
+ int height = pdev->height;
+ int x, y, tmp, comp_num;
+ pdf14_buf *buf = pdev->ctx->stack;
+ int planestride = buf->planestride;
+ int num_comp = buf->n_chan - 1;
+ byte *buf_ptr = buf->data;
+ const byte bg = pdev->ctx->additive ? gx_max_color_value : 0;
+ gx_color_index color;
+ gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
+ gx_color_value comp;
+ byte a;
+
+ if_debug0('v', "[v]pdf14_custom_put_image\n");
+
+ /* Send pixel data to the target device. */
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+
+ /* composite CMYKA, etc. pixel with over solid background */
+ a = buf_ptr[x + planestride * num_comp];
+
+ if ((a + 1) & 0xfe) {
+ a ^= 0xff;
+ for (comp_num = 0; comp_num < num_comp; comp_num++) {
+ comp = buf_ptr[x + planestride * comp_num];
+ tmp = ((bg - comp) * a) + 0x80;
+ comp += tmp + (tmp >> 8);
+ cv[comp_num] = comp;
+ }
+ } else if (a == 0) {
+ for (comp_num = 0; comp_num < num_comp; comp_num++) {
+ cv[comp_num] = bg;
+ }
+ } else {
+ for (comp_num = 0; comp_num < num_comp; comp_num++) {
+ comp = buf_ptr[x + planestride * comp_num];
+ cv[comp_num] = (comp << 8) + comp;
+ }
+ }
+ color = dev_proc(target, encode_color)(target, cv);
+ code = dev_proc(target, fill_rectangle)(target, x, y, 1, 1, color);
+ }
+
+ buf_ptr += buf->rowstride;
+ }
+
+ return code;
+}
+
+private int
pdf14_close(gx_device *dev)
{
pdf14_device *pdev = (pdf14_device *)dev;
@@ -1001,6 +1557,15 @@
return code;
}
+/* Function prototypes */
+int put_param_compressed_color_list_elem(gx_device * pdev,
+ gs_param_list * plist, compressed_color_list_t ** pret_comp_list,
+ char * keyname, int num_comps);
+int put_param_pdf14_spot_names(gx_device * pdev,
+ gs_separations * pseparations, gs_param_list * plist);
+#define PDF14CompressedColorListParamName "PDF14CompressedColorList"
+#define PDF14NumSpotColorsParamName "PDF14NumSpotColors"
+
/*
* The put_params method for the PDF 1.4 device will check if the
* target device has closed and, if so, close itself. Note: This routine is
@@ -1021,6 +1586,11 @@
code = gs_closedevice(dev);
gs_pdf14_device_copy_params(dev, tdev);
}
+#if 0
+ put_param_compressed_color_list_elem(pdev, plist, &pret_comp_list,
+ PDF14CompressedColorListParamName, TOP_ENCODED_LEVEL);
+ put_param_pdf14_spot_names(dev, &pdev->devn_params, plist);
+#endif
return code;
}
@@ -1188,17 +1758,61 @@
private pdf14_default_colorspace_t
pdf14_determine_default_blend_cs(gx_device * pdev)
{
- if (pdev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE)
- /* Use DeviceCMYK for all subrtactive process color models. */
- return DeviceCMYK;
- else {
+ if (pdev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE)
/*
* Note: We do not allow the SeparationOrder device parameter for
* additive devices. Thus we always have 1 colorant for DeviceGray
* and 3 colorants for DeviceRGB. We do not currently support
* blending in a DeviceGray color space. Thus we oniy use DeviceRGB.
*/
- return DeviceRGB;
+ return PDF14_DeviceRGB;
+ else {
+ /*
+ * Check if the device is CMYK only or CMYK plus spot colors.
+ */
+ int i, output_comp_num, num_cmyk_used = 0, num_cmyk = 0;
+
+#if CUSTOM_BLENDING_MODE == ALWAYS_USE_CUSTOM_BLENDING
+ return PDF14_DeviceCustom;
+#endif
+ /*
+ * Count the number of CMYK process components supported by the output
+ * device.
+ */
+ for (i = 0; i < 4; i++) {
+ const char * pcomp_name = (const char *)DeviceCMYKComponents[i];
+
+ output_comp_num = dev_proc(pdev, get_color_comp_index)
+ (pdev, pcomp_name, strlen(pcomp_name), NO_COMP_NAME_TYPE);
+
+ if (output_comp_num >= 0) {
+ num_cmyk++;
+ if (output_comp_num != GX_DEVICE_COLOR_MAX_COMPONENTS)
+ num_cmyk_used++;
+ }
+ }
+ /*
+ * Check if the device supports only CMYK. Otherewise we assume that
+ * the output device supports spot colors. Note: This algorithm can
+ * be fooled if the SeparationOrder device parameter is being used by
+ * the output device device to only select CMYK.
+ */
+ if (num_cmyk_used == 4 && pdev->color_info.num_components == 4
+ && pdev->color_info.max_components == 4)
+ return PDF14_DeviceCMYK;
+ /*
+ * Check if we should use the 'custom' PDF 1.4 compositor device.
+ * This device is only needed for those devices which do not support
+ * a basic CMYK process color model.
+ */
+#if CUSTOM_BLENDING_MODE == AUTO_USE_CUSTOM_BLENDING
+ if (num_cmyk != 4)
+ return PDF14_DeviceCustom;
+#endif
+ /*
+ * Otherewise we use a CMYK plus spot colors for blending.
+ */
+ return PDF14_DeviceCMYKspot;
}
}
@@ -1209,22 +1823,54 @@
* currently only using a color space based upon the device.
*/
private int
-get_pdf14_device_proto(gx_device * dev,
- const pdf14_device ** pdevproto)
+get_pdf14_device_proto(gx_device * dev, pdf14_device ** pdevproto,
+ pdf14_device * ptempdevproto, gs_imager_state * pis,
+ const gs_pdf14trans_t * pdf14pct)
{
pdf14_default_colorspace_t dev_cs =
pdf14_determine_default_blend_cs(dev);
switch (dev_cs) {
- case DeviceGray:
- *pdevproto = &gs_pdf14_Gray_device;
+ case PDF14_DeviceGray:
+ *pdevproto = (pdf14_device *)&gs_pdf14_Gray_device;
break;
- case DeviceRGB:
- *pdevproto = &gs_pdf14_RGB_device;
+ case PDF14_DeviceRGB:
+ *pdevproto = (pdf14_device *)&gs_pdf14_RGB_device;
break;
- case DeviceCMYK:
- *pdevproto = &gs_pdf14_CMYK_device;
+ case PDF14_DeviceCMYK:
+ *pdevproto = (pdf14_device *)&gs_pdf14_CMYK_device;
break;
+ case PDF14_DeviceCMYKspot:
+ *pdevproto = (pdf14_device *)&gs_pdf14_CMYKspot_device;
+ /*
+ * The number of components for the PDF14 device is the sum
+ * of the process components and the number of spot colors
+ * for the page.
+ */
+ if (pdf14pct->params.num_spot_colors >= 0) {
+ *ptempdevproto = **pdevproto;
+ ptempdevproto->devn_params.page_spot_colors =
+ pdf14pct->params.num_spot_colors;
+ ptempdevproto->color_info.num_components =
+ ptempdevproto->devn_params.num_std_colorant_names +
+ pdf14pct->params.num_spot_colors;
+ if (ptempdevproto->color_info.num_components >
+ ptempdevproto->color_info.max_components)
+ ptempdevproto->color_info.num_components =
+ ptempdevproto->color_info.max_components;
+ *pdevproto = ptempdevproto;
+ }
+ break;
+ case PDF14_DeviceCustom:
+ /*
+ * We are using the output device's process color model. The
+ * color_info for the PDF 1.4 compositing device needs to match
+ * the output device.
+ */
+ *ptempdevproto = gs_pdf14_custom_device;
+ ptempdevproto->color_info = dev->color_info;
+ *pdevproto = ptempdevproto;
+ break;
default: /* Should not occur */
return_error(gs_error_rangecheck);
}
@@ -1240,11 +1886,12 @@
*/
private int
pdf14_recreate_device(gs_memory_t *mem, gs_imager_state * pis,
- gx_device * dev)
+ gx_device * dev, const gs_pdf14trans_t * pdf14pct)
{
pdf14_device * pdev = (pdf14_device *)dev;
gx_device * target = pdev->target;
- const pdf14_device * dev_proto;
+ pdf14_device * dev_proto;
+ pdf14_device temp_dev_proto;
int code;
if_debug0('v', "[v]pdf14_recreate_device\n");
@@ -1253,10 +1900,11 @@
* We will not use the entire prototype device but we will set the
* color related info and the device procs to match the prototype.
*/
- code = get_pdf14_device_proto(target, &dev_proto);
+ code = get_pdf14_device_proto(target, &dev_proto,
+ &temp_dev_proto, pis, pdf14pct);
if (code < 0)
return code;
- pdev->color_info = dev_proto->color_info;
+ pdev->color_info = temp_dev_proto.color_info;
pdev->procs = dev_proto->procs;
gx_device_fill_in_procs(dev);
check_device_separable((gx_device *)pdev);
@@ -1281,12 +1929,13 @@
case PDF14_PUSH_DEVICE:
p14dev->blend_mode = 0;
p14dev->opacity = p14dev->shape = 0.0;
- pdf14_recreate_device(mem, pis, pdev);
+ pdf14_recreate_device(mem, pis, pdev, pdf14pct);
break;
case PDF14_POP_DEVICE:
pis->get_cmap_procs = p14dev->save_get_cmap_procs;
gx_set_cmap_procs(pis, p14dev->target);
- code = pdf14_put_image(p14dev, pis, p14dev->target);
+ /* Send image out raster data to output device */
+ p14dev->pdf14_procs->put_image(pdev, pis, p14dev->target);
pdf14_disable_device(pdev);
pdf14_close(pdev);
break;
@@ -1524,7 +2173,7 @@
int code;
if_debug0('v', "[v]end_transparency_group\n");
- code = pdf14_pop_transparency_group(pdev->ctx);
+ code = pdf14_pop_transparency_group(pdev->ctx, pdev->blend_procs);
return code;
}
@@ -1582,6 +2231,7 @@
byte shape = 0; /* Quiet compiler. */
byte src_alpha;
+ /* NB: gx_color_index is 4 or 8 bytes */
if (sizeof(color) <= sizeof(ulong))
if_debug7('v', "[v]pdf14_mark_fill_rectangle, (%d, %d), %d x %d color = %lx bm %d, nc %d,\n",
x, y, w, h, (ulong)color, blend_mode, num_chan);
@@ -1590,21 +2240,13 @@
x, y, w, h,
(ulong)(color >> 8*(sizeof(color) - sizeof(ulong))), (ulong)color,
blend_mode, num_chan);
- /* NB: gx_color_index is 4 or 8 bytes */
- /* Complement the components for subtractive color spaces */
- if (additive) {
- for (i = num_comp - 1; i >= 0; i--) {
- src[i] = (byte)(color & 0xff);
- color >>= 8;
- }
- }
- else {
- for (i = num_comp - 1; i >= 0; i--) {
- src[i] = (byte)(0xff - (color & 0xff));
- color >>= 8;
- }
- }
+ /*
+ * Unpack the gx_color_index values. Complement the components for subtractive
+ * color spaces.
+ */
+ pdev->pdf14_procs->unpack_color(num_comp, color, pdev, src);
+
src_alpha = src[num_comp] = (byte)floor (255 * pdev->alpha + 0.5);
if (has_shape)
shape = (byte)floor (255 * pdev->shape + 0.5);
@@ -1634,7 +2276,8 @@
dst[k] = 255 - dst_ptr[k * planestride];
dst[num_comp] = dst_ptr[num_comp * planestride];
}
- art_pdf_composite_pixel_alpha_8(dst, src, num_comp, blend_mode);
+ art_pdf_composite_pixel_alpha_8(dst, src, num_comp,
+ blend_mode, pdev->blend_procs);
/* Complement the results for subtractive color spaces */
if (additive) {
for (k = 0; k < num_chan; ++k)
@@ -1688,19 +2331,12 @@
(ulong)(color >> 8*(sizeof(color) - sizeof(ulong))), (ulong)color,
num_chan);
- /* Complement the components for subtractive color spaces */
- if (additive) {
- for (i = num_comp - 1; i >= 0; i--) {
- src[i] = (byte)(color & 0xff);
- color >>= 8;
- }
- }
- else {
- for (i = num_comp - 1; i >= 0; i--) {
- src[i] = (byte)(0xff - (color & 0xff));
- color >>= 8;
- }
- }
+ /*
+ * Unpack the gx_color_index values. Complement the components for subtractive
+ * color spaces.
+ */
+ pdev->pdf14_procs->unpack_color(num_comp, color, pdev, src);
+
src[num_comp] = (byte)floor (255 * pdev->alpha + 0.5);
opacity = (byte)floor (255 * pdev->opacity + 0.5);
@@ -1997,15 +2633,16 @@
int
gs_pdf14_device_push(gs_memory_t *mem, gs_imager_state * pis,
- gx_device ** pdev, gx_device * target)
+ gx_device ** pdev, gx_device * target, const gs_pdf14trans_t * pdf14pct)
{
- const pdf14_device * dev_proto;
- pdf14_device *p14dev;
+ pdf14_device * dev_proto;
+ pdf14_device * p14dev, temp_dev_proto;
int code;
if_debug0('v', "[v]gs_pdf14_device_push\n");
- code = get_pdf14_device_proto(target, &dev_proto);
+ code = get_pdf14_device_proto(target, &dev_proto,
+ &temp_dev_proto, pis, pdf14pct);
if (code < 0)
return code;
code = gs_copydevice((gx_device **) &p14dev,
@@ -2013,13 +2650,13 @@
if (code < 0)
return code;
- check_device_separable((gx_device *)p14dev);
- gx_device_fill_in_procs((gx_device *)p14dev);
-
gs_pdf14_device_copy_params((gx_device *)p14dev, target);
rc_assign(p14dev->target, target, "gs_pdf14_device_push");
+ check_device_separable((gx_device *)p14dev);
+ gx_device_fill_in_procs((gx_device *)p14dev);
+
p14dev->save_get_cmap_procs = pis->get_cmap_procs;
pis->get_cmap_procs = pdf14_get_cmap_procs;
gx_set_cmap_procs(pis, (gx_device *)p14dev);
@@ -2089,6 +2726,8 @@
default: /* Should not occur. */
break;
case PDF14_PUSH_DEVICE:
+ put_value(pbuf, pparams->num_spot_colors);
+ break;
case PDF14_POP_DEVICE:
case PDF14_END_TRANS_GROUP:
case PDF14_END_TRANS_MASK:
@@ -2183,6 +2822,8 @@
default: /* Should not occur. */
break;
case PDF14_PUSH_DEVICE:
+ read_value(data, params.num_spot_colors);
+ break;
case PDF14_POP_DEVICE:
case PDF14_END_TRANS_GROUP:
break; /* No data */
@@ -2263,10 +2904,12 @@
/*
* We only handle the push operation. All other operations are ignored.
+ * The other operations will be handled by the create_compositor routine
+ * for the PDF 1.4 compositing device.
*/
switch (pdf14pct->params.pdf14_op) {
case PDF14_PUSH_DEVICE:
- code = gs_pdf14_device_push(mem, pis, &p14dev, tdev);
+ code = gs_pdf14_device_push(mem, pis, &p14dev, tdev, pdf14pct);
*pp14dev = p14dev;
break;
default:
@@ -2380,23 +3023,13 @@
* This section provides support for this device.
*/
-/* Define the default alpha-compositing device. */
-typedef struct pdf14_clist_device_s {
- gx_device_forward_common;
- const gx_color_map_procs *(*save_get_cmap_procs)(const gs_imager_state *,
- const gx_device *);
- gx_device_color_info saved_target_color_info;
- float opacity;
- float shape;
- gs_blend_mode_t blend_mode;
- bool text_knockout;
-} pdf14_clist_device;
+/*
+ * Define the default pre-clist (clist writer) PDF 1.4 compositing device.
+ * We actually use the same structure for both the clist writer and reader
+ * devices. However we use separate names to identify the routines for each
+ * device.
+ */
-gs_private_st_suffix_add0_final(st_pdf14_clist_device,
- pdf14_clist_device, "pdf14_clist_device",
- device_c_pdf14_clist_enum_ptrs, device_c_pdf14_clist_reloc_ptrs,
- gx_device_finalize, st_device_forward);
-
#define pdf14_clist_procs(get_color_mapping_procs, get_color_comp_index,\
encode_color, decode_color) \
{\
@@ -2452,7 +3085,14 @@
get_color_mapping_procs, /* get_color_mapping_procs */\
get_color_comp_index, /* get_color_comp_index */\
encode_color, /* encode_color */\
- decode_color /* decode_color */\
+ decode_color, /* decode_color */\
+ NULL, /* pattern_manage */\
+ NULL, /* fill_rectangle_hl_color */\
+ NULL, /* include_color_space */\
+ NULL, /* fill_linear_color_scanline */\
+ NULL, /* fill_linear_color_trapezoid */\
+ NULL, /* fill_linear_color_triangle */\
+ gx_forward_update_spot_equivalent_colors /* update spot */\
}
private dev_proc_create_compositor(pdf14_clist_create_compositor);
@@ -2480,28 +3120,97 @@
gx_default_DevCMYK_get_color_comp_index,
cmyk_8bit_map_cmyk_color, cmyk_8bit_map_color_cmyk);
+private const gx_device_procs pdf14_clist_CMYKspot_procs =
+ pdf14_clist_procs(pdf14_cmykspot_get_color_mapping_procs,
+ pdf14_cmykspot_get_color_comp_index,
+ pdf14_compressed_encode_color,
+ pdf14_compressed_decode_color);
+
+private const gx_device_procs pdf14_clist_custom_procs =
+ pdf14_clist_procs(gx_forward_get_color_mapping_procs,
+ gx_forward_get_color_comp_index,
+ gx_forward_encode_color,
+ gx_forward_decode_color);
+
const pdf14_clist_device pdf14_clist_Gray_device = {
std_device_color_stype_body(pdf14_clist_device, &pdf14_clist_Gray_procs,
- "pdf14clistgray", &st_pdf14_clist_device,
+ "pdf14clistgray", &st_pdf14_device,
XSIZE, YSIZE, X_DPI, Y_DPI, 8, 255, 256),
- { 0 }
+ { 0 }, /* Procs */
+ NULL, /* target */
+ { 0 }, /* devn_params - not used */
+ &gray_pdf14_procs,
+ &gray_blending_procs
};
const pdf14_clist_device pdf14_clist_RGB_device = {
std_device_color_stype_body(pdf14_clist_device, &pdf14_clist_RGB_procs,
- "pdf14clistRGB", &st_pdf14_clist_device,
+ "pdf14clistRGB", &st_pdf14_device,
XSIZE, YSIZE, X_DPI, Y_DPI, 24, 255, 256),
- { 0 }
+ { 0 }, /* Procs */
+ NULL, /* target */
+ { 0 }, /* devn_params - not used */
+ &rgb_pdf14_procs,
+ &rgb_blending_procs
};
const pdf14_clist_device pdf14_clist_CMYK_device = {
std_device_std_color_full_body_type(pdf14_clist_device,
&pdf14_clist_CMYK_procs, "PDF14clistcmyk",
- &st_pdf14_clist_device, XSIZE, YSIZE, X_DPI, Y_DPI, 32,
+ &st_pdf14_device, XSIZE, YSIZE, X_DPI, Y_DPI, 32,
0, 0, 0, 0, 0, 0),
- { 0 }
+ { 0 }, /* Procs */
+ NULL, /* target */
+ { 0 }, /* devn_params - not used */
+ &cmyk_pdf14_procs,
+ &cmyk_blending_procs
};
+const pdf14_clist_device pdf14_clist_CMYKspot_device = {
+ std_device_part1_(pdf14_device, &pdf14_clist_CMYKspot_procs, "PDF14clistcmykspot", &st_pdf14_device, open_init_closed),
+ dci_values(GX_DEVICE_COLOR_MAX_COMPONENTS,64,255,255,256,256),
+ std_device_part2_(XSIZE, YSIZE, X_DPI, Y_DPI),
+ offset_margin_values(0, 0, 0, 0, 0, 0),
+ std_device_part3_(),
+ { 0 }, /* Procs */
+ NULL, /* target */
+ /* DeviceN parameters */
+ { 8, /* Not used - Bits per color */
+ DeviceCMYKComponents, /* Names of color model colorants */
+ 4, /* Number colorants for CMYK */
+ 0, /* MaxSeparations has not been specified */
+ -1, /* PageSpotColors has not been specified */
+ {0}, /* SeparationNames */
+ 0, /* SeparationOrder names */
+ {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
+ },
+ &cmykspot_pdf14_procs,
+ &cmyk_blending_procs
+};
+
+const pdf14_clist_device pdf14_clist_custom_device = {
+ std_device_part1_(pdf14_device, &pdf14_clist_CMYKspot_procs, "PDF14clistcustom", &st_pdf14_device, open_init_closed),
+ dci_values(GX_DEVICE_COLOR_MAX_COMPONENTS,64,255,255,256,256),
+ std_device_part2_(XSIZE, YSIZE, X_DPI, Y_DPI),
+ offset_margin_values(0, 0, 0, 0, 0, 0),
+ std_device_part3_(),
+ { 0 }, /* Procs */
+ NULL, /* target */
+ /* DeviceN parameters */
+ { 8, /* Not used - Bits per color */
+ DeviceCMYKComponents, /* Names of color model colorants */
+ 4, /* Number colorants for CMYK */
+ 0, /* MaxSeparations has not been specified */
+ -1, /* PageSpotColors has not been specified */
+ {0}, /* SeparationNames */
+ 0, /* SeparationOrder names */
+ {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
+ },
+ &custom_pdf14_procs,
+ &custom_blending_procs
+};
+
+
/*
* the PDF 1.4 transparency spec says that color space for blending
* operations can be based upon either a color space specified in the
@@ -2509,22 +3218,55 @@
* currently only using a color space based upon the device.
*/
private int
-get_pdf14_clist_device_proto(gx_device * dev,
- const pdf14_clist_device ** pdevproto)
+get_pdf14_clist_device_proto(gx_device * dev, pdf14_clist_device ** pdevproto,
+ pdf14_clist_device * ptempdevproto, gs_imager_state * pis,
+ const gs_pdf14trans_t * pdf14pct)
{
pdf14_default_colorspace_t dev_cs =
pdf14_determine_default_blend_cs(dev);
switch (dev_cs) {
- case DeviceGray:
- *pdevproto = &pdf14_clist_Gray_device;
+ case PDF14_DeviceGray:
+ *pdevproto = (pdf14_clist_device *)&pdf14_clist_Gray_device;
break;
- case DeviceRGB:
- *pdevproto = &pdf14_clist_RGB_device;
+ case PDF14_DeviceRGB:
+ *pdevproto = (pdf14_clist_device *)&pdf14_clist_RGB_device;
break;
- case DeviceCMYK:
- *pdevproto = &pdf14_clist_CMYK_device;
+ case PDF14_DeviceCMYK:
+ *pdevproto = (pdf14_clist_device *)&pdf14_clist_CMYK_device;
break;
+ case PDF14_DeviceCMYKspot:
+ *pdevproto = (pdf14_clist_device *)&pdf14_clist_CMYKspot_device;
+ *pdevproto = (pdf14_clist_device *)&pdf14_clist_custom_device;
+ /*
+ * The number of components for the PDF14 device is the sum
+ * of the process components and the number of spot colors
+ * for the page.
+ */
+ if (pdf14pct->params.num_spot_colors >= 0) {
+ *ptempdevproto = **pdevproto;
+ ptempdevproto->devn_params.page_spot_colors =
+ pdf14pct->params.num_spot_colors;
+ ptempdevproto->color_info.num_components =
+ ptempdevproto->devn_params.num_std_colorant_names +
+ pdf14pct->params.num_spot_colors;
+ if (ptempdevproto->color_info.num_components >
+ ptempdevproto->color_info.max_components)
+ ptempdevproto->color_info.num_components =
+ ptempdevproto->color_info.max_components;
+ *pdevproto = ptempdevproto;
+ }
+ break;
+ case PDF14_DeviceCustom:
+ /*
+ * We are using the output device's process color model. The
+ * color_info for the PDF 1.4 compositing device needs to match
+ * the output device.
+ */
+ *ptempdevproto = pdf14_clist_custom_device;
+ ptempdevproto->color_info = dev->color_info;
+ *pdevproto = ptempdevproto;
+ break;
default: /* Should not occur */
return_error(gs_error_rangecheck);
}
@@ -2533,18 +3275,19 @@
private int
pdf14_create_clist_device(gs_memory_t *mem, gs_imager_state * pis,
- gx_device ** ppdev, gx_device * target)
+ gx_device ** ppdev, gx_device * target,
+ const gs_pdf14trans_t * pdf14pct)
{
- const pdf14_clist_device * dev_proto;
- pdf14_clist_device *pdev;
+ pdf14_clist_device * dev_proto;
+ pdf14_clist_device * pdev, temp_dev_proto;
int code;
if_debug0('v', "[v]pdf14_create_clist_device\n");
- code = get_pdf14_clist_device_proto(target, &dev_proto);
+ code = get_pdf14_clist_device_proto(target, &dev_proto,
+ &temp_dev_proto, pis, pdf14pct);
if (code < 0)
return code;
-
code = gs_copydevice((gx_device **) &pdev,
(const gx_device *) dev_proto, mem);
if (code < 0)
@@ -2558,6 +3301,7 @@
rc_assign(pdev->target, target, "pdf14_create_clist_device");
code = dev_proc((gx_device *) pdev, open_device) ((gx_device *) pdev);
+ pdev->pclist_device = target;
*ppdev = (gx_device *) pdev;
return code;
}
@@ -2597,11 +3341,12 @@
*/
private int
pdf14_recreate_clist_device(gs_memory_t *mem, gs_imager_state * pis,
- gx_device * dev)
+ gx_device * dev, const gs_pdf14trans_t * pdf14pct)
{
pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
gx_device * target = pdev->target;
- const pdf14_clist_device * dev_proto;
+ pdf14_clist_device * dev_proto;
+ pdf14_clist_device temp_dev_proto;
int code;
if_debug0('v', "[v]pdf14_recreate_clist_device\n");
@@ -2610,7 +3355,8 @@
* We will not use the entire prototype device but we will set the
* color related info to match the prototype.
*/
- code = get_pdf14_clist_device_proto(target, &dev_proto);
+ code = get_pdf14_clist_device_proto(target, &dev_proto,
+ &temp_dev_proto, pis, pdf14pct);
if (code < 0)
return code;
pdev->color_info = dev_proto->color_info;
@@ -2622,6 +3368,366 @@
}
/*
+ * Key names are normally C const strings. However we need to create temp
+ * parameter key names. They only need to have a short life. We need to
+ * create a parameter list with the key names. Then we will put the parameters
+ * into the clist. That process will create a permanent copy of the key
+ * name. At that point we can release our temp key names.
+ */
+typedef struct keyname_link_list_s {
+ struct keyname_link_list_s * next;
+ char * key_name;
+ } keyname_link_list_t;
+
+/*
+ * The GC description for the keyname link list is being included for
+ * completeness. Since this structure is only temporary, this structure
+ * should never be exposed to the GC.
+ */
+gs_private_st_ptrs2(st_keyname_link_list, keyname_link_list_t,
+ "keyname_link_list", keyname_link_list_enum_ptrs,
+ keyname_link_list_reloc_ptrs, next, key_name);
+
+/* See comments before the definition of keyname_link_list_t */
+private int
+free_temp_keyname_list(gs_memory_t * mem, keyname_link_list_t * plist)
+{
+ keyname_link_list_t * pthis_elem;
+
+ while (plist != NULL) {
+ pthis_elem = plist;
+ plist = plist->next;
+ gs_free_object(mem, (byte *)pthis_elem, "free_temp_keyname_list");
+ }
+ return 0;
+}
+
+/* Put a data value into our 'string' */
+#define put_data(pdata, value, count)\
+ for(j = 0; j < count; j++)\
+ *pdata++ = (byte)((value) >> (j * 8))
+
+/*
+ * Convert a compressed color list element into a set of device parameters.
+ * Note: This routine recursively calls itself. As a result it can create
+ * mulitple device parameters. The parameters are 'strings'. Actually the
+ * data is stored in the strings as binary data.
+ *
+ * See comments before the definition of keyname_link_list_t
+ */
+private int
+get_param_compressed_color_list_elem(pdf14_clist_device * pdev,
+ gs_param_list * plist, compressed_color_list_t * pcomp_list,
+ char * keyname, keyname_link_list_t ** pkeyname_list)
+{
+ int max_list_elem_size =
+ 6 + NUM_ENCODE_LIST_ITEMS * sizeof(comp_bit_map_list_t);
+ int code, i, j;
+ byte * pdata;
+ gs_param_string str;
+
+ if (pcomp_list == NULL) /* Exit if we don not have a list. */
+ return 0;
+
+ /* Allocate a string for temp data */
+ pdata = gs_alloc_bytes(pdev->memory, max_list_elem_size,
+ "convert_compressed_color_list_elem");
+ str.data = (const byte *)pdata;
+ str.persistent = false;
+
+ put_data(pdata, pcomp_list->num_sub_level_ptrs, 2);
+ put_data(pdata, pcomp_list->first_bit_map, 2);
+
+ /* . */
+ for (i = pcomp_list->first_bit_map; i < NUM_ENCODE_LIST_ITEMS; i++) {
+ put_data(pdata, pcomp_list->u.comp_data[i].num_comp, 2);
+ put_data(pdata, pcomp_list->u.comp_data[i].num_non_solid_comp, 2);
+ put_data(pdata, pcomp_list->u.comp_data[i].solid_not_100, 1);
+ put_data(pdata, pcomp_list->u.comp_data[i].colorants,
+ sizeof(pcomp_list->u.comp_data[i].colorants));
+ if (pcomp_list->u.comp_data[i].num_comp !=
+ pcomp_list->u.comp_data[i].num_non_solid_comp) {
+ put_data(pdata, pcomp_list->u.comp_data[i].solid_colorants,
+ sizeof(pcomp_list->u.comp_data[i].solid_colorants));
+ }
+ }
+ str.size = pdata - str.data;
+ code = param_write_string(plist, keyname, &str);
+ gs_free_object(pdev->memory, (byte *)str.data,
+ "convert_compressed_color_list_elem");
+
+ /* Convert the sub levels. */
+ for (i = 0; i < pcomp_list->num_sub_level_ptrs; i++) {
+ /*
+ * We generate a keyname for the sub level elements based upon
+ * the keyname for the current level. See comments before the
+ * definition of keyname_link_list_t for comments about the lifetime
+ * of the keynames.
+ */
+ /* Allocate a string for the keyname */
+ char * keyname_buf = (char *)gs_alloc_bytes(pdev->memory,
+ strlen(keyname) + 10, "convert_compressed_color_list_elem");
+ /*
+ * Allocate a link list element so we can keep track of the memory
+ * allocated to hold the keynames.
+ */
+ keyname_link_list_t * pkeyname_list_elem =
+ gs_alloc_struct(pdev->memory, keyname_link_list_t,
+ &st_keyname_link_list, "convert_compressed_color_list_elem");
+ pkeyname_list_elem->next = *pkeyname_list;
+ pkeyname_list_elem->key_name = keyname_buf;
+ *pkeyname_list = pkeyname_list_elem;
+ sprintf(keyname_buf, "%s_%d", keyname, i);
+ get_param_compressed_color_list_elem(pdev, plist,
+ pcomp_list->u.sub_level_ptrs[i], keyname_buf,
+ pkeyname_list);
+ }
+
+ return 0;;
+}
+#undef put_data
+
+/* Get data value from our 'string' */
+#define get_data(pdata, value, count)\
+ j = count - 1;\
+ value = pdata[j--];\
+ for(; j >= 0; j--)\
+ value = (value <<= 8) | pdata[j];\
+ pdata += count
+
+/*
+ * Retrieve a compressed color list from a set of device parameters.
+ * Note: This routine recursively calls itself. As a result it can process
+ * mulitple device parameters and create the entire compressed color list.
+ * The parameters are 'strings'. Actually the data is stored in the strings
+ * as binary data.
+ */
+int
+put_param_compressed_color_list_elem(gx_device * pdev,
+ gs_param_list * plist, compressed_color_list_t ** pret_comp_list,
+ char * keyname, int num_comps)
+{
+ int code, i, j;
+ byte * pdata;
+ gs_param_string str;
+ compressed_color_list_t * pcomp_list;
+
+ /* Check if the given keyname is present. */
+ code = param_read_string(plist, keyname, &str);
+ switch (code) {
+ case 0:
+ break; /* We have the given keyname, continue. */
+ default:
+ param_signal_error(plist, keyname, code);
+ case 1:
+ *pret_comp_list = NULL;
+ return 0;
+ }
+ /* Allocate a compressed color list element. */
+ pdata = (byte *)str.data;
+ pcomp_list = alloc_compressed_color_list_elem(pdev->memory, num_comps);
+ get_data(pdata, pcomp_list->num_sub_level_ptrs, 2);
+ get_data(pdata, pcomp_list->first_bit_map, 2);
+
+ /* Read the bit maps */
+ for (i = pcomp_list->first_bit_map; i < NUM_ENCODE_LIST_ITEMS; i++) {
+ get_data(pdata, pcomp_list->u.comp_data[i].num_comp, 2);
+ get_data(pdata, pcomp_list->u.comp_data[i].num_non_solid_comp, 2);
+ get_data(pdata, pcomp_list->u.comp_data[i].solid_not_100, 1);
+ get_data(pdata, pcomp_list->u.comp_data[i].colorants,
+ sizeof(pcomp_list->u.comp_data[i].colorants));
+ if (pcomp_list->u.comp_data[i].num_comp !=
+ pcomp_list->u.comp_data[i].num_non_solid_comp) {
+ get_data(pdata, pcomp_list->u.comp_data[i].solid_colorants,
+ sizeof(pcomp_list->u.comp_data[i].solid_colorants));
+ }
+ }
+
+ /* Get the sub levels. */
+ for (i = 0; i < pcomp_list->num_sub_level_ptrs; i++) {
+ char buff[50];
+ compressed_color_list_t * sub_list_ptr;
+
+ sprintf(buff, "%s_%d", keyname, i);
+ put_param_compressed_color_list_elem(pdev, plist,
+ &sub_list_ptr, buff, num_comps - 1);
+ pcomp_list->u.sub_level_ptrs[i] = sub_list_ptr;
+ }
+
+ *pret_comp_list = pcomp_list;
+ return 0;;
+}
+#undef get_data
+
+/*
+ * Convert a list of spot color names into a set of device parameters.
+ * This is done to transfer information from the PDf14 clist writer
+ * compositing device to the PDF14 clist reader compositing device.
+ *
+ * See comments before the definition of keyname_link_list_t
+ */
+private int
+get_param_spot_color_names(pdf14_clist_device * pdev,
+ gs_param_list * plist, keyname_link_list_t ** pkeyname_list)
+{
+ int code, i;
+ gs_param_string str;
+ gs_separations * separations = &pdev->devn_params.separations;
+ int num_spot_colors = separations->num_separations;
+
+ if (num_spot_colors == 0)
+ return 0;
+
+ code = param_write_int(plist, PDF14NumSpotColorsParamName,
+ &num_spot_colors);
+ for (i = 0; i < num_spot_colors; i++) {
+ /*
+ * We generate a keyname for the spot color based upon the
+ * spot color number. See comments before the definition of
+ * keyname_link_list_t for comments about the lifetime of the keynames.
+ */
+ /* Allocate a string for the keyname */
+ char * keyname_buf = (char *)gs_alloc_bytes(pdev->memory,
+ strlen("PDF14SpotName_") + 10, "get_param_spot_color_names");
+ /*
+ * Allocate a link list element so we can keep track of the memory
+ * allocated to hold the keynames.
+ */
+ keyname_link_list_t * pkeyname_list_elem =
+ gs_alloc_struct(pdev->memory, keyname_link_list_t,
+ &st_keyname_link_list, "get_param_spot_color_names");
+ pkeyname_list_elem->next = *pkeyname_list;
+ pkeyname_list_elem->key_name = keyname_buf;
+ *pkeyname_list = pkeyname_list_elem;
+ sprintf(keyname_buf, "%PDF14SpotName_%d", i);
+ str.size = separations->names[i].size;
+ str.data = separations->names[i].data;
+ str.persistent = false;
+ code = param_write_string(plist, keyname_buf, &str);
+ }
+ return 0;;
+}
+
+/*
+ * Retrieve a list of spot color names for the PDF14 device.
+ */
+int
+put_param_pdf14_spot_names(gx_device * pdev,
+ gs_separations * pseparations, gs_param_list * plist)
+{
+ int code, num_spot_colors, i;
+ gs_param_string str;
+
+ /* Check if the given keyname is present. */
+ code = param_read_int(plist, PDF14NumSpotColorsParamName,
+ &num_spot_colors);
+ switch (code) {
+ default:
+ param_signal_error(plist, PDF14NumSpotColorsParamName, code);
+ break;
+ case 1:
+ return 0;
+ case 0:
+ if (num_spot_colors < 1 ||
+ num_spot_colors > GX_DEVICE_COLOR_MAX_COMPONENTS)
+ return_error(gs_error_rangecheck);
+ for (i = 0; i < num_spot_colors; i++) {
+ char buff[20];
+ byte * sep_name;
+
+ sprintf(buff, "PDF14SpotName_%d", i);
+ code = param_read_string(plist, buff, &str);
+ switch (code) {
+ default:
+ param_signal_error(plist, buff, code);
+ break;
+ case 0:
+ sep_name = gs_alloc_bytes(pdev->memory,
+ str.size, "put_param_pdf14_spot_names");
+ memcpy(sep_name, str.data, str.size);
+ pseparations->names[i].size = str.size;
+ pseparations->names[i].data = sep_name;
+ }
+ }
+ pseparations->num_separations = num_spot_colors;
+ break;
+ }
+ return 0;;
+}
+
+private int
+pdf14_clist_get_param_compressed_color_list(pdf14_device * p14dev)
+{
+ gx_device_clist_writer * cldev = (gx_device_clist_writer *)p14dev->pclist_device;
+ gs_c_param_list param_list;
+ keyname_link_list_t * pkeyname_list_head = NULL;
+ int code;
+
+ /*
+ * If a put_params call fails, the device will be left in a closed
+ * state, but higher-level code won't notice this fact. We flag this by
+ * setting permanent_error, which prevents writing to the command list.
+ */
+
+ if (cldev->permanent_error)
+ return cldev->permanent_error;
+ gs_c_param_list_write(¶m_list, p14dev->memory);
+ code = get_param_compressed_color_list_elem(p14dev,
+ (gs_param_list *)¶m_list,
+ p14dev->devn_params.compressed_color_list,
+ PDF14CompressedColorListParamName, &pkeyname_list_head);
+ get_param_spot_color_names(p14dev, (gs_param_list *)¶m_list,
+ &pkeyname_list_head);
+ if (code >= 0) {
+ gx_device * tdev = p14dev->target;
+
+ gs_c_param_list_read(¶m_list);
+ // put_param_compressed_color_list_elem(p14dev,
+ // (gs_param_list *)¶m_list,
+ // &pret_comp_list, "PDF14CompressedColorList",
+ // TOP_ENCODED_LEVEL);
+ // put_param_pdf14_spot_names(p14dev, (gs_param_list *)¶m_list);
+#if 1
+ code = dev_proc(tdev, put_params)(tdev, (gs_param_list *)¶m_list);
+#else
+ /*
+ * This call will put the compressed color list info into the
+ * clist. However there are two problems. The info goes into
+ * the list at the end of the list.
+ */
+ code = cmd_put_params(cldev, (gs_param_list *)¶m_list );
+#endif
+ }
+ gs_c_param_list_release(¶m_list);
+ free_temp_keyname_list(p14dev->memory, pkeyname_list_head);
+
+ return code;
+}
+
+/*
+ * This procedure will have information from the PDF 1.4 clist writing
+ * clist compositior device. This is information output the compressed
+ * color list info which is needed for the support of spot colors in
+ * PDF 1.4 compositing. This info needs to be passed to the PDF 1.4
+ * clist reading compositor. However this device is not created until
+ * the clist is read. To get this info to that device, we have to
+ * temporarily store that info in the output device. This routine saves
+ * that info in the output device.
+ */
+int
+pdf14_put_devn_params(gx_device * pdev, gs_devn_params * pdevn_params,
+ gs_param_list * plist)
+{
+ int code = put_param_compressed_color_list_elem(pdev, plist,
+ &pdevn_params->pdf14_compressed_color_list,
+ PDF14CompressedColorListParamName, TOP_ENCODED_LEVEL);
+ if (code >= 0)
+ code = put_param_pdf14_spot_names(pdev,
+ &pdevn_params->pdf14_separations, plist);
+ return code;
+}
+
+/*
* When we are banding, we have two PDF 1.4 compositor devices. One for
* when we are creating the clist. The second is for imaging the data from
* the clist. This routine is part of the clist writing PDF 1.4 device.
@@ -2647,7 +3753,7 @@
pdev->save_get_cmap_procs = pis->get_cmap_procs;
pis->get_cmap_procs = pdf14_get_cmap_procs;
gx_set_cmap_procs(pis, dev);
- code = pdf14_recreate_clist_device(mem, pis, dev);
+ code = pdf14_recreate_clist_device(mem, pis, dev, pdf14pct);
pdev->blend_mode = pdev->text_knockout = 0;
pdev->opacity = pdev->shape = 0.0;
if (code < 0)
@@ -2667,6 +3773,12 @@
return code;
}
case PDF14_POP_DEVICE:
+ /*
+ * For spot colors we use a 'compressed encoding' for
+ * gx_color_index values. Send the related data struct
+ * to the clist.
+ */
+ pdf14_clist_get_param_compressed_color_list(pdev);
/* Restore the color_info for the clist device */
pdev->target->color_info = pdev->saved_target_color_info;
pis->get_cmap_procs = pdev->save_get_cmap_procs;
@@ -2950,7 +4062,7 @@
/* We only handle the push/pop operations */
switch (pdf14pct->params.pdf14_op) {
case PDF14_PUSH_DEVICE:
- code = pdf14_create_clist_device(mem, pis, pcdev, dev);
+ code = pdf14_create_clist_device(mem, pis, pcdev, dev, pdf14pct);
/*
* Set the color_info of the clist device to match the compositing
* device. We will restore it when the compositor is popped.
@@ -2996,6 +4108,7 @@
{
pdf14_device * p14dev = (pdf14_device *)tdev;
gs_pdf14trans_t * pdf14pct = (gs_pdf14trans_t *) pcte;
+ gs_devn_params * pclist_devn_params;
/*
* We only handle the push/pop operations. Save and restore the color_info
@@ -3005,14 +4118,139 @@
*/
switch (pdf14pct->params.pdf14_op) {
case PDF14_PUSH_DEVICE:
- p14dev->saved_clist_color_info = cdev->color_info;
+ p14dev->saved_target_color_info = cdev->color_info;
cdev->color_info = p14dev->color_info;
+ /*
+ * If we are blending using spot colors (i.e. the output device
+ * supports spot colors) then we need to transfer compressed
+ * color info from the clist PDF 1.4 compositing reader device
+ * to the clist writer PDF 1.4 compositing device.
+ * This info was transfered from that device to the output
+ * device as a set of device parameters. However the clist
+ * reader PDF 1.4 compositing device did not exist when the
+ * device parameters were read from the clist. So that info
+ * was buffered into the output device.
+ */
+ pclist_devn_params = dev_proc(cdev, ret_devn_params)(cdev);
+ if (pclist_devn_params != NULL) {
+ int num_comp = p14dev->color_info.num_components;
+ /*
+ * The number of components for the PDF14 device is the sum
+ * of the process components and the number of spot colors
+ * for the page.
+ */
+ p14dev->devn_params.page_spot_colors =
+ pclist_devn_params->page_spot_colors;
+ p14dev->color_info.num_components =
+ p14dev->devn_params.num_std_colorant_names +
+ p14dev->devn_params.page_spot_colors;
+ /* Transfer the data for the compressed color encoding. */
+ // free_compressed_color_list(p14dev->memory,
+ // p14dev->devn_params.compressed_color_list);
+ p14dev->devn_params.compressed_color_list =
+ pclist_devn_params->pdf14_compressed_color_list;
+ // free_separation_names(p14dev->memory,
+ // &p14dev->devn_params.separations);
+ p14dev->devn_params.separations =
+ pclist_devn_params->pdf14_separations;
+ if ( num_comp != p14dev->color_info.num_components) {
+ dev_proc(tdev, open_device) (tdev);
+ dev_proc(tdev, open_device) (tdev);
+ }
+ }
break;
case PDF14_POP_DEVICE:
- cdev->color_info = p14dev->saved_clist_color_info;
+ cdev->color_info = p14dev->saved_target_color_info;
break;
default:
break; /* do nothing for remaining ops */
}
return 0;
}
+
+/*
+ * This routine will check to see if the color component name matches those
+ * that are available amoung the current device's color components. If the
+ * color name is known to the output device then we add it to the list of
+ * colorants for the PDF 1.4 transparency compositor.
+ *
+ * Notes: There are currently three different versions of The PDF 1.4
+ * transparency compositor device. The choice of which one is being used
+ * depends upon the process color model of the output device. This procedure
+ * is only used if the output (target) device uses a CMYK plus spot color
+ * process color model.
+ *
+ * Parameters:
+ * dev - pointer to device data structure.
+ * pname - pointer to name (zero termination not required)
+ * nlength - length of the name
+ *
+ * This routine returns a positive value (0 to n) which is the device colorant
+ * number if the name is found. It returns GX_DEVICE_COLOR_MAX_COMPONENTS if
+ * the colorant is not being used due to a SeparationOrder device parameter.
+ * It returns a negative value if not found.
+ */
+private int
+pdf14_cmykspot_get_color_comp_index(gx_device * dev, const char * pname,
+ int name_size, int component_type)
+{
+ pdf14_device * pdev = (pdf14_device *) dev;
+ gx_device * tdev = pdev->target;
+ gs_devn_params * pdevn_params = &pdev->devn_params;
+ gs_separations * pseparations = &pdevn_params->separations;
+ int comp_index;
+
+ /*
+ * If this is not a separation name then simply forward it to the target
+ * device.
+ */
+ if (component_type == NO_COMP_NAME_TYPE)
+ return dev_proc(tdev, get_color_comp_index)
+ (tdev, pname, name_size, component_type);
+ /*
+ * Check if the component is in either the process color model list
+ * or in the SeparationNames list.
+ */
+ comp_index = check_pcm_and_separation_names(dev, pdevn_params,
+ pname, name_size, component_type);
+ /*
+ * Return the colorant number if we know this name.
+ */
+ if (comp_index >= 0)
+ return comp_index;
+ /*
+ * If we do not know this color, check if the output (target) device does.
+ */
+ comp_index = dev_proc(tdev, get_color_comp_index)
+ (tdev, pname, name_size, component_type);
+ /*
+ * Ignore color if unknown to the output device or if color is not being
+ * imaged due to the SeparationOrder device parameter.
+ */
+ if (comp_index < 0 || comp_index == GX_DEVICE_COLOR_MAX_COMPONENTS)
+ return comp_index;
+
+ /*
+ * This is a new colorant. Add it to our list of colorants.
+ */
+ if (pseparations->num_separations < GX_DEVICE_COLOR_MAX_COMPONENTS - 1) {
+ int sep_num = pseparations->num_separations++;
+ int color_component_number;
+ byte * sep_name;
+
+ sep_name = gs_alloc_bytes(dev->memory,
+ name_size, "pdf14_cmykspot_get_color_comp_index");
+ memcpy(sep_name, pname, name_size);
+ pseparations->names[sep_num].size = name_size;
+ pseparations->names[sep_num].data = sep_name;
+ color_component_number = sep_num + pdevn_params->num_std_colorant_names;
+ if (color_component_number >= dev->color_info.num_components)
+ color_component_number = GX_DEVICE_COLOR_MAX_COMPONENTS;
+ else
+ pdevn_params->separation_order_map[color_component_number] =
+ color_component_number;
+ return color_component_number;
+ }
+
+ return GX_DEVICE_COLOR_MAX_COMPONENTS;
+}
Modified: trunk/gs/src/gdevp14.h
===================================================================
--- trunk/gs/src/gdevp14.h 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gdevp14.h 2007-03-23 13:56:11 UTC (rev 7795)
@@ -17,9 +17,11 @@
# define gdevp14_INCLUDED
typedef enum {
- DeviceGray = 0,
- DeviceRGB = 1,
- DeviceCMYK = 2
+ PDF14_DeviceGray = 0,
+ PDF14_DeviceRGB = 1,
+ PDF14_DeviceCMYK = 2,
+ PDF14_DeviceCMYKspot = 3,
+ PDF14_DeviceCustom = 4
} pdf14_default_colorspace_t;
typedef struct pdf14_buf_s pdf14_buf;
@@ -63,23 +65,103 @@
int n_chan;
};
+#ifndef gs_devn_params_DEFINED
+# define gs_devn_params_DEFINED
+typedef struct gs_devn_params_s gs_devn_params;
+#endif
+
+#ifndef gs_imager_state_DEFINED
+# define gs_imager_state_DEFINED
+typedef struct gs_imager_state_s gs_imager_state;
+#endif
+
+#ifndef gx_device_DEFINED
+# define gx_device_DEFINED
+typedef struct gx_device_s gx_device;
+#endif
+
+#ifndef gs_pdf14trans_params_DEFINED
+# define gs_pdf14trans_params_DEFINED
+typedef struct gs_pdf14trans_params_s gs_pdf14trans_params_t;
+#endif
+
+typedef struct pdf14_device_s pdf14_device;
+
+/*
+ * This structure contains procedures for processing routine which differ
+ * between the different blending color spaces.
+ */
+typedef struct {
+ /*
+ * Unpack a device color. This routine is similar to the device's
+ * decode_color procedure except for two things. The procedure produces
+ * 1 byte values instead of gx_color_values (2 bytes) and the output
+ * values are inverted for subtractive color spaces (like CMYK).
+ * A separate procedure is used instead of the decode_color to minimize
+ * execution time.
+ */
+ void (* unpack_color)(int num_comp, gx_color_index color,
+ pdf14_device * p14dev, byte * out);
+ /*
+ * This procedure sends the final rasterized transparency data to the
+ * output device as an image.
+ */
+ int (* put_image)(gx_device * dev,
+ gs_imager_state * pis, gx_device * target);
+} pdf14_procs_s;
+
+typedef pdf14_procs_s pdf14_procs_t;
+
+/*
+ * Define the default post-clist (clist reader) PDF 1.4 compositing device.
+ * We actually use the same structure for both the clist writer and reader
+ * devices. However we use separate names to identify the routines for each
+ * device.
+ */
typedef struct pdf14_device_s {
gx_device_forward_common;
+ gs_devn_params devn_params; /* Must follow gx_device_forward_common */
+ const pdf14_procs_t * pdf14_procs; /* Must follow devn_params. */
+ const pdf14_nonseparable_blending_procs_t * blend_procs; /* Must follow pdf14_procs */
pdf14_ctx *ctx;
float opacity;
float shape;
float alpha; /* alpha = opacity * shape */
gs_blend_mode_t blend_mode;
+ bool text_knockout;
+ gx_device * pclist_device;
const gx_color_map_procs *(*save_get_cmap_procs)(const gs_imager_state *,
const gx_device *);
- gx_device_color_info saved_clist_color_info;
-} pdf14_device;
+ gx_device_color_info saved_target_color_info;
+} pdf14_device_t;
-int gs_pdf14_device_push(gs_memory_t *mem, gs_imager_state * pis,
- gx_device * * pdev, gx_device * target);
+/*
+ * Define the default pre-clist (clist writer) PDF 1.4 compositing device.
+ * We actually use the same structure for both the clist writer and reader
+ * devices. However we use separate names to identify the routines for each
+ * device.
+ */
+typedef struct pdf14_device_s pdf14_clist_device;
+/*
+ * Send a PDF 1.4 transparency compositor action to the specified device.
+ */
int send_pdf14trans(gs_imager_state * pis, gx_device * dev,
gx_device * * pcdev, gs_pdf14trans_params_t * pparams, gs_memory_t * mem);
+/*
+ * This procedure will save information from the PDF 1.4 clist writing
+ * clist compositior device. This is information about the compressed
+ * color list info which is needed for the support of spot colors in
+ * PDF 1.4 compositing. This info needs to be passed to the PDF 1.4
+ * clist reading compositor. However this device is not created until
+ * the clist is read. To get this info to that device, we have to
+ * temporarily store that info in the output device. This routine saves
+ * that info in the output device.
+ */
+int
+pdf14_put_devn_params(gx_device * pdev, gs_devn_params * pdevn_params,
+ gs_param_list * plist);
+
#endif /* gdevp14_INCLUDED */
Modified: trunk/gs/src/gdevpbm.c
===================================================================
--- trunk/gs/src/gdevpbm.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gdevpbm.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -429,8 +429,12 @@
ppm_get_params(gx_device * pdev, gs_param_list * plist)
{
gx_device_pbm * const bdev = (gx_device_pbm *)pdev;
+ int code;
- return gdev_prn_get_params_planar(pdev, plist, &bdev->UsePlanarBuffer);
+ code = gdev_prn_get_params_planar(pdev, plist, &bdev->UsePlanarBuffer);
+ if (code < 0) return code;
+ code = param_write_null(plist, "OutputIntent");
+ return code;
}
private int
@@ -443,8 +447,26 @@
int ecode = 0;
int code;
long v;
+ gs_param_string_array intent;
const char *vname;
+ if ((code = param_read_string_array(plist, "OutputIntent", &intent)) == 0) {
+ int i, j;
+
+ dlprintf1("%d strings:\n", intent.size);
+ for (i = 0; i < intent.size; i++) {
+ const gs_param_string *s = &intent.data[i];
+ dlprintf2(" %d: size %d:", i, s->size);
+ if (i < 4) {
+ for (j = 0; j < s->size; j++)
+ dlprintf1("%c", s->data[j]);
+ } else {
+ for (j = 0; j < 16; j++)
+ dlprintf1(" %02x", s->data[j]);
+ }
+ dlprintf("\n");
+ }
+ }
save_info = pdev->color_info;
if ((code = param_read_long(plist, (vname = "GrayValues"), &v)) != 1 ||
(code = param_read_long(plist, (vname = "RedValues"), &v)) != 1 ||
Modified: trunk/gs/src/gdevpnga.c
===================================================================
--- trunk/gs/src/gdevpnga.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gdevpnga.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -19,6 +19,7 @@
#include "gscdefs.h"
#include "gsdevice.h"
#include "gdevmem.h"
+#include "gxcindex.h"
#include "gxblend.h"
#include "gxtext.h"
Modified: trunk/gs/src/gdevprn.c
===================================================================
--- trunk/gs/src/gdevprn.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gdevprn.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -401,6 +401,7 @@
COPY_PROC(stroke_path);
COPY_PROC(fill_rectangle_hl_color);
COPY_PROC(update_spot_equivalent_colors);
+ COPY_PROC(ret_devn_params);
#undef COPY_PROC
/* If using a command list, already opened the device. */
if (is_command_list)
Modified: trunk/gs/src/gdevpsd.c
===================================================================
--- trunk/gs/src/gdevpsd.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gdevpsd.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -244,6 +244,7 @@
DeviceRGBComponents, /* Names of color model colorants */
3, /* Number colorants for RGB */
0, /* MaxSeparations has not been specified */
+ -1, /* PageSpotColors has not been specified */
{0}, /* SeparationNames */
0, /* SeparationOrder names */
{0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
@@ -287,6 +288,7 @@
DeviceCMYKComponents, /* Names of color model colorants */
4, /* Number colorants for CMYK */
0, /* MaxSeparations has not been specified */
+ -1, /* PageSpotColors has not been specified */
{0}, /* SeparationNames */
0, /* SeparationOrder names */
{0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
Modified: trunk/gs/src/gdevrops.c
===================================================================
--- trunk/gs/src/gdevrops.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gdevrops.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -105,7 +105,8 @@
gx_forward_fill_linear_color_scanline,
gx_forward_fill_linear_color_trapezoid,
gx_forward_fill_linear_color_triangle,
- gx_forward_update_spot_equivalent_colors
+ gx_forward_update_spot_equivalent_colors,
+ gx_forward_ret_devn_parms
},
0, /* target */
lop_default /* log_op */
Modified: trunk/gs/src/gdevtsep.c
===================================================================
--- trunk/gs/src/gdevtsep.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gdevtsep.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -238,6 +238,7 @@
private dev_proc_encode_color(tiffsep_encode_compressed_color);
private dev_proc_decode_color(tiffsep_decode_compressed_color);
private dev_proc_update_spot_equivalent_colors(tiffsep_update_spot_equivalent_colors);
+private dev_proc_ret_devn_params(tiffsep_ret_devn_params);
/*
@@ -362,7 +363,8 @@
NULL, /* fill_linear_color_scanline */\
NULL, /* fill_linear_color_trapezoid */\
NULL, /* fill_linear_color_triangle */\
- tiffsep_update_spot_equivalent_colors /* update_spot_equivalent_colors */\
+ tiffsep_update_spot_equivalent_colors, /* update_spot_equivalent_colors */\
+ tiffsep_ret_devn_params /* ret_devn_params */\
}
#define tiffsep_device_body(procs, dname, ncomp, pol, depth, mg, mc, sl, cn)\
@@ -421,6 +423,7 @@
DeviceCMYKComponents, /* Names of color model colorants */
4, /* Number colorants for CMYK */
0, /* MaxSeparations has not been specified */
+ -1, /* PageSpotColors has not been specified */
{0}, /* SeparationNames */
0, /* SeparationOrder names */
{0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
@@ -555,6 +558,17 @@
return 0;
}
+/*
+ * Device proc for returning a pointer to DeviceN parameter structure
+ */
+private gs_devn_params *
+tiffsep_ret_devn_params(gx_device * dev)
+{
+ tiffsep_device * pdev = (tiffsep_device *)dev;
+
+ return &pdev->devn_params;
+}
+
/* Get parameters. We provide a default CRD. */
private int
tiffsep_get_params(gx_device * pdev, gs_param_list * plist)
Modified: trunk/gs/src/gscdevn.c
===================================================================
--- trunk/gs/src/gscdevn.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gscdevn.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -398,10 +398,12 @@
dprintf("gx_remap_concrete_DeviceN: color space id mismatch");
#endif
-#if ENABLE_NAMED_COLOR_CALLBACK
- if (pis->color_component_map.use_named_color_callback) {
- return gx_remap_concrete_named_color_DeviceN(pconc, pcs, pdc,
+#if ENABLE_CUSTOM_COLOR_CALLBACK
+ if (pis->custom_color_callback) {
+ int code = gx_remap_concrete_custom_color_DeviceN(pconc, pcs, pdc,
pis, dev, select);
+ if (code >= 0)
+ return code;
}
#endif
if (pis->color_component_map.use_alt_cspace) {
@@ -502,16 +504,15 @@
gx_install_DeviceN(const gs_color_space * pcs, gs_state * pgs)
{
int code;
-#if ENABLE_NAMED_COLOR_CALLBACK
+#if ENABLE_CUSTOM_COLOR_CALLBACK
/*
- * Check if we want to use the callback color processing for this color space.
+ * Check if we want to use the callback color processing for this
+ * color space.
*/
- bool use_named_color_callback =
- named_color_callback_install_DeviceN(pgs->color_space, pgs);
+ bool use_custom_color_callback =
+ custom_color_callback_install_DeviceN(pcs, pgs);
- pgs->color_component_map.use_named_color_callback =
- use_named_color_callback;
- if (use_named_color_callback) {
+ if (use_custom_color_callback) {
/*
* We are using the callback instead of the alternate tint transform
* for this color space.
@@ -522,6 +523,7 @@
return 0;
}
#endif
+
code = check_DeviceN_component_names(pcs, pgs);
if (code < 0)
return code;
Modified: trunk/gs/src/gscie.c
===================================================================
--- trunk/gs/src/gscie.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gscie.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -419,6 +419,22 @@
{
gs_cie_defg *pcie = pcs->params.defg;
+#if ENABLE_CUSTOM_COLOR_CALLBACK
+ {
+ /*
+ * Check if we want to use the callback color processing for this
+ * color space.
+ */
+ client_custom_color_params_t * pcb =
+ (client_custom_color_params_t *) pgs->custom_color_callback;
+
+ if (pcb != NULL) {
+ if (pcb->client_procs->install_CIEBasedDEFG(pcb, pcs, pgs))
+ /* Exit if the client will handle the colorspace completely */
+ return 0;
+ }
+ }
+#endif
CIE_LOAD_CACHE_BODY(pcie->caches_defg.DecodeDEFG, pcie->RangeDEFG.ranges,
&pcie->DecodeDEFG, DecodeDEFG_default, pcie,
"DecodeDEFG");
@@ -430,6 +446,22 @@
{
gs_cie_def *pcie = pcs->params.def;
+#if ENABLE_CUSTOM_COLOR_CALLBACK
+ {
+ /*
+ * Check if we want to use the callback color processing for this
+ * color space.
+ */
+ client_custom_color_params_t * pcb =
+ (client_custom_color_params_t *) pgs->custom_color_callback;
+
+ if (pcb != NULL) {
+ if (pcb->client_procs->install_CIEBasedDEF(pcb, pcs, pgs))
+ /* Exit if the client will handle the colorspace completely */
+ return 0;
+ }
+ }
+#endif
CIE_LOAD_CACHE_BODY(pcie->caches_def.DecodeDEF, pcie->RangeDEF.ranges,
&pcie->DecodeDEF, DecodeDEF_default, pcie,
"DecodeDEF");
@@ -439,6 +471,22 @@
int
gx_install_CIEABC(const gs_color_space * pcs, gs_state * pgs)
{
+#if ENABLE_CUSTOM_COLOR_CALLBACK
+ {
+ /*
+ * Check if we want to use the callback color processing for this
+ * color space.
+ */
+ client_custom_color_params_t * pcb =
+ (client_custom_color_params_t *) pgs->custom_color_callback;
+
+ if (pcb != NULL) {
+ if (pcb->client_procs->install_CIEBasedABC(pcb, pcs, pgs))
+ /* Exit if the client will handle the colorspace completely */
+ return 0;
+ }
+ }
+#endif
return gx_install_cie_abc(pcs->params.abc, pgs);
}
@@ -449,6 +497,22 @@
gs_sample_loop_params_t lp;
int i;
+#if ENABLE_CUSTOM_COLOR_CALLBACK
+ {
+ /*
+ * Check if we want to use the callback color processing for this
+ * color space.
+ */
+ client_custom_color_params_t * pcb =
+ (client_custom_color_params_t *) pgs->custom_color_callback;
+
+ if (pcb != NULL) {
+ if (pcb->client_procs->install_CIEBasedA(pcb, pcs, pgs))
+ /* Exit if the client will handle the colorspace completely */
+ return 0;
+ }
+ }
+#endif
gs_cie_cache_init(&pcie->caches.DecodeA.floats.params, &lp,
&pcie->RangeA, "DecodeA");
for (i = 0; i <= lp.N; ++i) {
Modified: trunk/gs/src/gsciemap.c
===================================================================
--- trunk/gs/src/gsciemap.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gsciemap.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -202,6 +202,80 @@
}
#undef SCALE_TO_RANGE
+#if ENABLE_CUSTOM_COLOR_CALLBACK
+/*
+ * This routine is only used if ENABLE_CUSTOM_COLOR_CALLBACK is true.
+ * Otherwise we use gx_default_remap_color directly for CIEBasedDEFG color
+ * spaces.
+ *
+ * Render a CIEBasedDEFG color.
+ */
+int
+gx_remap_CIEDEFG(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)
+{
+ client_custom_color_params_t * pcb =
+ (client_custom_color_params_t *) (pis->custom_color_callback);
+
+ if (pcb != NULL) {
+ if (pcb->client_procs->remap_CIEBasedDEFG(pcb, pc, pcs,
+ pdc, pis, dev, select) == 0)
+ return 0;
+ }
+ /* Use default routine for non custom color processing. */
+ return gx_default_remap_color(pc, pcs, pdc, pis, dev, select);
+}
+
+/*
+ * This routine is only used if ENABLE_CUSTOM_COLOR_CALLBACK is true.
+ * Otherwise we use gx_default_remap_color directly for CIEBasedDEF color
+ * spaces.
+ *
+ * Render a CIEBasedDEF color.
+ */
+int
+gx_remap_CIEDEF(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)
+{
+ client_custom_color_params_t * pcb =
+ (client_custom_color_params_t *) (pis->custom_color_callback);
+
+ if (pcb != NULL) {
+ if (pcb->client_procs->remap_CIEBasedDEF(pcb, pc, pcs,
+ pdc, pis, dev, select) == 0)
+ return 0;
+ }
+ /* Use default routine for non custom color processing. */
+ return gx_default_remap_color(pc, pcs, pdc, pis, dev, select);
+}
+
+/*
+ * This routine is only used if ENABLE_CUSTOM_COLOR_CALLBACK is true.
+ * Otherwise we use gx_default_remap_color directly for CIEBasedA color
+ * spaces.
+ *
+ * Render a CIEBasedA color.
+ */
+int
+gx_remap_CIEA(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)
+{
+ client_custom_color_params_t * pcb =
+ (client_custom_color_params_t *) (pis->custom_color_callback);
+
+ if (pcb != NULL) {
+ if (pcb->client_procs->remap_CIEBasedA(pcb, pc, pcs,
+ pdc, pis, dev, select) == 0)
+ return 0;
+ }
+ /* Use default routine for non custom color processing. */
+ return gx_default_remap_color(pc, pcs, pdc, pis, dev, select);
+}
+#endif
+
/* Render a CIEBasedABC color. */
/* We provide both remap and concretize, but only the former */
/* needs to be efficient. */
@@ -216,6 +290,19 @@
if_debug3('c', "[c]remap CIEABC [%g %g %g]\n",
pc->paint.values[0], pc->paint.values[1],
pc->paint.values[2]);
+#if ENABLE_CUSTOM_COLOR_CALLBACK
+ {
+ client_custom_color_params_t * pcb =
+ (client_custom_color_params_t *) (pis->custom_color_callback);
+
+ if (pcb != NULL) {
+ if (pcb->client_procs->remap_CIEBasedABC(pcb, pc, pcs,
+ pdc, pis, dev, select) == 0)
+ return 0;
+ }
+ }
+#endif
+
CIE_CHECK_RENDERING(pcs, conc, pis, goto map3);
vec3.u = float2cie_cached(pc->paint.values[0]);
vec3.v = float2cie_cached(pc->paint.values[1]);
Modified: trunk/gs/src/gscolor2.c
===================================================================
--- trunk/gs/src/gscolor2.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gscolor2.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -52,6 +52,8 @@
}
if (code >= 0) {
+ pgs->color_space->pclient_color_space_data =
+ pcs->pclient_color_space_data;
cs_full_init_color(pgs->ccolor, pcs);
gx_unset_dev_color(pgs);
}
Modified: trunk/gs/src/gscscie.c
===================================================================
--- trunk/gs/src/gscscie.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gscscie.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -51,7 +51,12 @@
gx_init_CIE, gx_restrict_CIEDEFG,
gx_concrete_space_CIE,
gx_concretize_CIEDEFG, NULL,
- gx_default_remap_color, gx_install_CIE,
+#if ENABLE_CUSTOM_COLOR_CALLBACK
+ gx_remap_CIEDEFG,
+#else
+ gx_default_remap_color,
+#endif
+ gx_install_CIE,
gx_spot_colors_set_overprint,
gx_final_CIEDEFG, gx_no_adjust_color_count,
gx_serialize_CIEDEFG,
@@ -70,7 +75,12 @@
gx_init_CIE, gx_restrict_CIEDEF,
gx_concrete_space_CIE,
gx_concretize_CIEDEF, NULL,
- gx_default_remap_color, gx_install_CIE,
+#if ENABLE_CUSTOM_COLOR_CALLBACK
+ gx_remap_CIEDEF,
+#else
+ gx_default_remap_color,
+#endif
+ gx_install_CIE,
gx_spot_colors_set_overprint,
gx_final_CIEDEF, gx_no_adjust_color_count,
gx_serialize_CIEDEF,
@@ -108,7 +118,12 @@
gx_init_CIE, gx_restrict_CIEA,
gx_concrete_space_CIE,
gx_concretize_CIEA, NULL,
- gx_default_remap_color, gx_install_CIE,
+#if ENABLE_CUSTOM_COLOR_CALLBACK
+ gx_remap_CIEA,
+#else
+ gx_default_remap_color,
+#endif
+ gx_install_CIE,
gx_spot_colors_set_overprint,
gx_final_CIEA, gx_no_adjust_color_count,
gx_serialize_CIEA,
Modified: trunk/gs/src/gscsepr.c
===================================================================
--- trunk/gs/src/gscsepr.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gscsepr.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -30,6 +30,7 @@
#include "gxdevcli.h"
#include "gsovrc.h"
#include "stream.h"
+#include "gsnamecl.h"
/* ---------------- Color space ---------------- */
@@ -105,17 +106,15 @@
gx_install_Separation(const gs_color_space * pcs, gs_state * pgs)
{
int code;
-#if ENABLE_NAMED_COLOR_CALLBACK
+#if ENABLE_CUSTOM_COLOR_CALLBACK
/*
- * Check if we want to use the named color callback color processing for
+ * Check if we want to use the custom color callback color processing for
* this color space.
*/
- bool use_named_color_callback =
- named_color_callback_install_Separation(pgs->color_space, pgs);
+ bool use_custom_color_callback =
+ custom_color_callback_install_Separation(pcs, pgs);
- pgs->color_component_map.use_named_color_callback =
- use_named_color_callback;
- if (use_named_color_callback) {
+ if (use_custom_color_callback) {
/*
* We are using the callback instead of the alternate tint transform
* for this color space.
@@ -354,12 +353,15 @@
dprintf("gx_remap_concrete_Separation: color space id mismatch");
#endif
-#if ENABLE_NAMED_COLOR_CALLBACK
- if (pis->color_component_map.use_named_color_callback) {
- return gx_remap_concrete_named_color_Separation(pconc, pcs, pdc,
+#if ENABLE_CUSTOM_COLOR_CALLBACK
+ {
+ int code = gx_remap_concrete_custom_color_Separation(pconc, pcs, pdc,
pis, dev, select);
+ if (code >= 0)
+ return code;
}
#endif
+
if (pis->color_component_map.use_alt_cspace) {
const gs_color_space *pacs = pcs->base_space;
Modified: trunk/gs/src/gscspace.c
===================================================================
--- trunk/gs/src/gscspace.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gscspace.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -29,6 +29,9 @@
#include "gzstate.h"
#include "stream.h"
+private cs_proc_install_cspace(gx_install_DeviceGray);
+private cs_proc_install_cspace(gx_install_DeviceRGB);
+private cs_proc_install_cspace(gx_install_DeviceCMYK);
/*
* Define the standard color space types. We include DeviceCMYK in the base
* build because it's too awkward to omit it, but we don't provide any of
@@ -41,7 +44,7 @@
gx_init_paint_1, gx_restrict01_paint_1,
gx_same_concrete_space,
gx_concretize_DeviceGray, gx_remap_concrete_DGray,
- gx_remap_DeviceGray, gx_no_install_cspace,
+ gx_remap_DeviceGray, gx_install_DeviceGray,
gx_spot_colors_set_overprint,
NULL, gx_no_adjust_color_count,
gx_serialize_cspace_type,
@@ -53,7 +56,7 @@
gx_init_paint_3, gx_restrict01_paint_3,
gx_same_concrete_space,
gx_concretize_DeviceRGB, gx_remap_concrete_DRGB,
- gx_remap_DeviceRGB, gx_no_install_cspace,
+ gx_remap_DeviceRGB, gx_install_DeviceRGB,
gx_spot_colors_set_overprint,
NULL, gx_no_adjust_color_count,
gx_serialize_cspace_type,
@@ -68,7 +71,7 @@
gx_init_paint_4, gx_restrict01_paint_4,
gx_same_concrete_space,
gx_concretize_DeviceCMYK, gx_remap_concrete_DCMYK,
- gx_remap_DeviceCMYK, gx_no_install_cspace,
+ gx_remap_DeviceCMYK, gx_install_DeviceCMYK,
gx_set_overprint_DeviceCMYK,
NULL, gx_no_adjust_color_count,
gx_serialize_cspace_type,
@@ -90,6 +93,15 @@
if (pcs->type->final)
pcs->type->final(pcs);
if_debug2('c', "[c]cspace final %08x %d\n", pcs, pcs->id);
+
+#if ENABLE_CUSTOM_COLOR_CALLBACK
+
+ client_color_space_data_t *pclient_data = pcs->pclient_color_space_data;
+ if ( pclient_data )
+ pclient_data->client_adjust_cspace_count( pcs, -1 );
+
+#endif /*ENABLE_CUSTOM_COLOR_CALLBACK*/
+
rc_decrement_only(pcs->base_space, "gs_cspace_final");
}
@@ -106,9 +118,14 @@
pcs->type = pcstype;
pcs->id = id;
pcs->base_space = NULL;
+ pcs->pclient_color_space_data = NULL;
return pcs;
}
+private cs_proc_install_cspace(gx_install_DeviceGray);
+private cs_proc_install_cspace(gx_install_DeviceRGB);
+private cs_proc_install_cspace(gx_install_DeviceCMYK);
+
/*
* Generic allocation function for colorspace implementations. Return
* NULL on allocation failure.
@@ -165,6 +182,24 @@
cs_restrict_color(pcc, pcs);
}
+/* Install a DeviceGray color space. */
+private int
+gx_install_DeviceGray(const gs_color_space * pcs, gs_state * pgs)
+{
+#if ENABLE_CUSTOM_COLOR_CALLBACK
+ /*
+ * Check if we want to use the callback color processing for this
+ * color space.
+ */
+ client_custom_color_params_t * pcb =
+ (client_custom_color_params_t *) pgs->custom_color_callback;
+
+ if (pcb != NULL)
+ pcb->client_procs->install_DeviceGray(pcb, pcs, pgs);
+#endif
+ return 0;
+}
+
int
gx_num_components_1(const gs_color_space * pcs)
{
@@ -199,7 +234,43 @@
{
return 0;
}
+
+/* Install a DeviceRGB color space. */
+private int
+gx_install_DeviceRGB(const gs_color_space * pcs, gs_state * pgs)
+{
+#if ENABLE_CUSTOM_COLOR_CALLBACK
+ /*
+ * Check if we want to use the callback color processing for this
+ * color space.
+ */
+ client_custom_color_params_t * pcb =
+ (client_custom_color_params_t *) pgs->custom_color_callback;
+ if (pcb != NULL)
+ pcb->client_procs->install_DeviceRGB(pcb, pcs, pgs);
+#endif
+ return 0;
+}
+
+/* Install a DeviceCMYK color space. */
+private int
+gx_install_DeviceCMYK(const gs_color_space * pcs, gs_state * pgs)
+{
+#if ENABLE_CUSTOM_COLOR_CALLBACK
+ /*
+ * Check if we want to use the callback color processing for this
+ * color space.
+ */
+ client_custom_color_params_t * pcb =
+ (client_custom_color_params_t *) pgs->custom_color_callback;
+
+ if (pcb != NULL)
+ pcb->client_procs->install_DeviceCMYK(pcb, pcs, pgs);
+#endif
+ return 0;
+}
+
/*
* Push an overprint compositor onto the current device indicating that,
* at most, the spot color parameters are to be preserved.
Modified: trunk/gs/src/gscspace.h
===================================================================
--- trunk/gs/src/gscspace.h 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gscspace.h 2007-03-23 13:56:11 UTC (rev 7795)
@@ -19,7 +19,6 @@
#include "gsmemory.h"
#include "gsiparam.h"
-#include "gsnamecl.h"
#include "gsrefct.h"
/*
@@ -188,9 +187,6 @@
separation_type sep_type;
bool use_alt_cspace;
gs_callback_func_get_colorname_string *get_colorname_string;
-#if ENABLE_NAMED_COLOR_CALLBACK
- named_color_params_t named_color_params;
-#endif
} gs_separation_params;
typedef struct gs_device_n_params_s {
@@ -200,11 +196,11 @@
gs_device_n_attributes *colorants;
bool use_alt_cspace;
gs_callback_func_get_colorname_string *get_colorname_string;
-#if ENABLE_NAMED_COLOR_CALLBACK
- named_color_params_t named_color_params;
-#endif
} gs_device_n_params;
+/* Define an abstract type for the client color space data */
+typedef struct client_color_space_data_s client_color_space_data_t;
+
/*
* Non-direct paint space: Indexed space.
*
@@ -251,6 +247,7 @@
rc_header rc;
gs_id id;
gs_color_space *base_space;
+ client_color_space_data_t *pclient_color_space_data;
union {
gs_device_pixel_params pixel;
gs_cie_defg * defg;
Modified: trunk/gs/src/gsdparam.c
===================================================================
--- trunk/gs/src/gsdparam.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gsdparam.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -117,12 +117,6 @@
/* Transmit the values. */
-#if ENABLE_NAMED_COLOR_CALLBACK
- /* The named color callback pointer */
- code = named_color_callback_get_params(dev, plist);
- if (code < 0)
- return code;
-#endif
if (
/* Standard parameters */
@@ -481,12 +475,6 @@
}\
END
-#if ENABLE_NAMED_COLOR_CALLBACK
- /* The named_color callback pointer */
- code = named_color_callback_put_params(dev, plist);
- if (code < 0)
- ecode = code;
-#endif
/*
* The actual value of LeadingEdge must be changed inside this routine,
* so that we can detect that it has been changed. Thus, instead of a
Modified: trunk/gs/src/gsdps1.c
===================================================================
--- trunk/gs/src/gsdps1.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gsdps1.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -28,6 +28,7 @@
#include "gzpath.h"
#include "gzcpath.h"
#include "gzstate.h"
+#include "gsutil.h"
/*
* Define how much rounding slop setbbox should leave,
@@ -196,6 +197,9 @@
dev_proc(pdev, fill_rectangle_hl_color)(pdev,
&empty, pis, pdc, NULL) == 0);
+ /* Processing a fill object operation */
+ gs_set_object_tag(pgs, GS_PATH_TAG);
+
gx_set_dev_color(pgs);
if ((is_fzero2(pgs->ctm.xy, pgs->ctm.yx) ||
is_fzero2(pgs->ctm.xx, pgs->ctm.yy)) &&
Modified: trunk/gs/src/gsicc.c
===================================================================
--- trunk/gs/src/gsicc.c 2007-03-21 01:48:30 UTC (rev 7794)
+++ trunk/gs/src/gsicc.c 2007-03-23 13:56:11 UTC (rev 7795)
@@ -115,6 +115,9 @@
private cs_proc_restrict_color(gx_restrict_CIEICC);
private cs_proc_concrete_space(gx_concrete_space_CIEICC);
private cs_proc_concretize_color(gx_concretize_CIEICC);
+#if ENABLE_CUSTOM_COLOR_CA