xref: /plan9/sys/src/cmd/gs/src/gxcmap.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1992-2005 artofcode LLC. All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /* $Id: gxcmap.c,v 1.26 2005/07/13 00:39:50 giles Exp $ */
18 /* Color mapping for Ghostscript */
19 #include "gx.h"
20 #include "gserrors.h"
21 #include "gsccolor.h"
22 #include "gxalpha.h"
23 #include "gxcspace.h"
24 #include "gxfarith.h"
25 #include "gxfrac.h"
26 #include "gxdcconv.h"
27 #include "gxdevice.h"
28 #include "gxcmap.h"
29 #include "gxlum.h"
30 #include "gzstate.h"
31 #include "gxdither.h"
32 #include "gxcdevn.h"
33 #include "string_.h"
34 
35 /* Structure descriptor */
36 public_st_device_color();
37 private
ENUM_PTRS_WITH(device_color_enum_ptrs,gx_device_color * cptr)38 ENUM_PTRS_WITH(device_color_enum_ptrs, gx_device_color *cptr)
39 {
40 	return ENUM_USING(*cptr->type->stype, vptr, size, index);
41 }
42 ENUM_PTRS_END
RELOC_PTRS_WITH(device_color_reloc_ptrs,gx_device_color * cptr)43 private RELOC_PTRS_WITH(device_color_reloc_ptrs, gx_device_color *cptr)
44 {
45     RELOC_USING(*cptr->type->stype, vptr, size);
46 }
47 RELOC_PTRS_END
48 
49 gx_color_index
gx_default_encode_color(gx_device * dev,const gx_color_value cv[])50 gx_default_encode_color(gx_device * dev, const gx_color_value cv[])
51 {
52     int             ncomps = dev->color_info.num_components;
53     int             i;
54     const byte *    comp_shift = dev->color_info.comp_shift;
55     const byte *    comp_bits = dev->color_info.comp_bits;
56     gx_color_index  color = 0;
57 
58 #ifdef DEBUG
59     if ( dev->color_info.separable_and_linear != GX_CINFO_SEP_LIN ) {
60         dprintf( "gx_default_encode_color() requires separable and linear\n" );
61         return gx_no_color_index;
62     }
63 #endif
64     for (i = 0; i < ncomps; i++) {
65 	color |= (gx_color_index)(cv[i] >> (gx_color_value_bits - comp_bits[i]))
66 		<< comp_shift[i];
67 
68     }
69     return color;
70 }
71 
72 /*
73  * This routine is only used if the device is 'separable'.  See
74  * separable_and_linear in gxdevcli.h for more information.
75  */
76 int
gx_default_decode_color(gx_device * dev,gx_color_index color,gx_color_value cv[])77 gx_default_decode_color(gx_device * dev, gx_color_index color, gx_color_value cv[])
78 {
79     int                     ncomps = dev->color_info.num_components;
80     int                     i;
81     const byte *            comp_shift = dev->color_info.comp_shift;
82     const byte *            comp_bits = dev->color_info.comp_bits;
83     const gx_color_index *  comp_mask = dev->color_info.comp_mask;
84     uint shift, ivalue, nbits, scale;
85 
86 #ifdef DEBUG
87     if ( dev->color_info.separable_and_linear != GX_CINFO_SEP_LIN ) {
88         dprintf( "gx_default_decode_color() requires separable and linear\n" );
89         return gs_error_rangecheck;
90     }
91 #endif
92 
93     for (i = 0; i < ncomps; i++) {
94 	/*
95 	 * Convert from the gx_color_index bits to a gx_color_value.
96 	 * Split the conversion into an integer and a fraction calculation
97 	 * so we can do integer arthmetic.  The calculation is equivalent
98 	 * to floor(0xffff.fffff * ivalue / ((1 << nbits) - 1))
99 	 */
100 	nbits = comp_bits[i];
101 	scale = gx_max_color_value / ((1 << nbits) - 1);
102 	ivalue = (color & comp_mask[i]) >> comp_shift[i];
103 	cv[i] = ivalue * scale;
104 	/*
105 	 * Since our scaling factor is an integer, we lost the fraction.
106 	 * Determine what part of the ivalue that the faction would have
107 	 * added into the result.
108 	 */
109 	shift = nbits - (gx_color_value_bits % nbits);
110 	cv[i] += ivalue >> shift;
111     }
112     return 0;
113 }
114 
115 gx_color_index
gx_error_encode_color(gx_device * dev,const gx_color_value colors[])116 gx_error_encode_color(gx_device * dev, const gx_color_value colors[])
117 {
118 #ifdef DEBUG
119     /* The "null" device is expected to be missing encode_color */
120     if (strcmp(dev->dname, "null") != 0)
121 	dprintf("No encode_color proc defined for device.\n");
122 #endif
123     return gx_no_color_index;
124 }
125 
126 int
gx_error_decode_color(gx_device * dev,gx_color_index cindex,gx_color_value colors[])127 gx_error_decode_color(gx_device * dev, gx_color_index cindex, gx_color_value colors[])
128 {
129      int i=dev->color_info.num_components;
130 
131 #ifdef DEBUG
132      dprintf("No decode_color proc defined for device.\n");
133 #endif
134      for(; i>=0; i--)
135  	colors[i] = 0;
136      return gs_error_rangecheck;
137 }
138 
139 /*
140  * The "back-stop" default encode_color method. This will be used only
141  * if no applicable color encoding procedure is provided, and the number
142  * of color model components is 1. The encoding is presumed to induce an
143  * additive color model (DeviceGray).
144  *
145  * The particular method employed is a trivial generalization of the
146  * default map_rgb_color method used in the pre-DeviceN code (this was
147  * known as gx_default_w_b_map_rgb_color). Since the DeviceRGB color
148  * model is assumed additive, any of the procedures used as a default
149  * map_rgb_color method are assumed to induce an additive color model.
150  * gx_default_w_b_map_rgb_color mapped white to 1 and black to 0, so
151  * the new procedure is set up with zero-base and positive slope as well.
152  * The generalization is the use of depth; the earlier procedure assumed
153  * a bi-level device.
154  *
155  * Two versions of this procedure are provided, the first of which
156  * applies if max_gray == 2^depth - 1 and is faster, while the second
157  * applies to the general situation. Note that, as with the encoding
158  * procedures used in the pre-DeviceN code, both of these methods induce
159  * a small rounding error if 1 < depth < gx_color_value_bits.
160  */
161 gx_color_index
gx_default_gray_fast_encode(gx_device * dev,const gx_color_value cv[])162 gx_default_gray_fast_encode(gx_device * dev, const gx_color_value cv[])
163 {
164     return cv[0] >> (gx_color_value_bits - dev->color_info.depth);
165 }
166 
167 gx_color_index
gx_default_gray_encode(gx_device * dev,const gx_color_value cv[])168 gx_default_gray_encode(gx_device * dev, const gx_color_value cv[])
169 {
170     return cv[0] * (dev->color_info.max_gray + 1) / (gx_max_color_value + 1);
171 }
172 
173 /**
174  * This routine is provided for old devices which provide a
175  * map_rgb_color routine but not encode_color. New devices are
176  * encouraged either to use the defaults or to set encode_color rather
177  * than map_rgb_color.
178  **/
179 gx_color_index
gx_backwards_compatible_gray_encode(gx_device * dev,const gx_color_value cv[])180 gx_backwards_compatible_gray_encode(gx_device *dev,
181 				    const gx_color_value cv[])
182 {
183     gx_color_value gray_val = cv[0];
184     gx_color_value rgb_cv[3];
185 
186     rgb_cv[0] = gray_val;
187     rgb_cv[1] = gray_val;
188     rgb_cv[2] = gray_val;
189     return (*dev_proc(dev, map_rgb_color))(dev, rgb_cv);
190 }
191 
192 /* -------- Default color space to color model conversion routines -------- */
193 
194 void
gray_cs_to_gray_cm(gx_device * dev,frac gray,frac out[])195 gray_cs_to_gray_cm(gx_device * dev, frac gray, frac out[])
196 {
197     out[0] = gray;
198 }
199 
200 static void
rgb_cs_to_gray_cm(gx_device * dev,const gs_imager_state * pis,frac r,frac g,frac b,frac out[])201 rgb_cs_to_gray_cm(gx_device * dev, const gs_imager_state *pis,
202 				   frac r, frac g, frac b, frac out[])
203 {
204     out[0] = color_rgb_to_gray(r, g, b, NULL);
205 }
206 
207 static void
cmyk_cs_to_gray_cm(gx_device * dev,frac c,frac m,frac y,frac k,frac out[])208 cmyk_cs_to_gray_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
209 {
210     out[0] = color_cmyk_to_gray(c, m, y, k, NULL);
211 }
212 
213 static void
gray_cs_to_rgb_cm(gx_device * dev,frac gray,frac out[])214 gray_cs_to_rgb_cm(gx_device * dev, frac gray, frac out[])
215 {
216     out[0] = out[1] = out[2] = gray;
217 }
218 
219 void
rgb_cs_to_rgb_cm(gx_device * dev,const gs_imager_state * pis,frac r,frac g,frac b,frac out[])220 rgb_cs_to_rgb_cm(gx_device * dev, const gs_imager_state *pis,
221 				  frac r, frac g, frac b, frac out[])
222 {
223     out[0] = r;
224     out[1] = g;
225     out[2] = b;
226 }
227 
228 static void
cmyk_cs_to_rgb_cm(gx_device * dev,frac c,frac m,frac y,frac k,frac out[])229 cmyk_cs_to_rgb_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
230 {
231     color_cmyk_to_rgb(c, m, y, k, NULL, out);
232 }
233 
234 static void
gray_cs_to_rgbk_cm(gx_device * dev,frac gray,frac out[])235 gray_cs_to_rgbk_cm(gx_device * dev, frac gray, frac out[])
236 {
237     out[0] = out[1] = out[2] = frac_0;
238     out[3] = gray;
239 }
240 
241 static void
rgb_cs_to_rgbk_cm(gx_device * dev,const gs_imager_state * pis,frac r,frac g,frac b,frac out[])242 rgb_cs_to_rgbk_cm(gx_device * dev, const gs_imager_state *pis,
243 				  frac r, frac g, frac b, frac out[])
244 {
245     if ((r == g) && (g == b)) {
246 	out[0] = out[1] = out[2] = frac_0;
247 	out[3] = r;
248     }
249     else {
250 	out[0] = r;
251 	out[1] = g;
252 	out[2] = b;
253 	out[3] = frac_0;
254     }
255 }
256 
257 static void
cmyk_cs_to_rgbk_cm(gx_device * dev,frac c,frac m,frac y,frac k,frac out[])258 cmyk_cs_to_rgbk_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
259 {
260     frac rgb[3];
261     if ((c == frac_0) && (m == frac_0) && (y == frac_0)) {
262 	out[0] = out[1] = out[2] = frac_0;
263 	out[3] = frac_1 - k;
264     }
265     else {
266 	color_cmyk_to_rgb(c, m, y, k, NULL, rgb);
267 	rgb_cs_to_rgbk_cm(dev, NULL, rgb[0], rgb[1], rgb[2], out);
268     }
269 }
270 
271 static void
gray_cs_to_cmyk_cm(gx_device * dev,frac gray,frac out[])272 gray_cs_to_cmyk_cm(gx_device * dev, frac gray, frac out[])
273 {
274     out[0] = out[1] = out[2] = frac_0;
275     out[3] = frac_1 - gray;
276 }
277 
278 /*
279  * Default map from DeviceRGB color space to DeviceCMYK color
280  * model. Since this mapping is defined by the PostScript language
281  * it is unlikely that any device with a DeviceCMYK color model
282  * would define this mapping on its own.
283  *
284  * If the imager state is not available, map as though the black
285  * generation and undercolor removal functions are identity
286  * transformations. This mode is used primarily to support the
287  * raster operation (rop) feature of PCL, which requires that
288  * the raster operation be performed in an RGB color space.
289  * Note that default black generation and undercolor removal
290  * functions in PostScript need NOT be identity transformations:
291  * often they are { pop 0 }.
292  */
293 static void
rgb_cs_to_cmyk_cm(gx_device * dev,const gs_imager_state * pis,frac r,frac g,frac b,frac out[])294 rgb_cs_to_cmyk_cm(gx_device * dev, const gs_imager_state *pis,
295   			   frac r, frac g, frac b, frac out[])
296 {
297     if (pis != 0)
298         color_rgb_to_cmyk(r, g, b, pis, out);
299     else {
300         frac    c = frac_1 - r, m = frac_1 - g, y = frac_1 - b;
301         frac    k = min(c, min(m, g));
302 
303         out[0] = c - k;
304         out[1] = m - k;
305         out[2] = y - k;
306         out[3] = k;
307     }
308 }
309 
310 void
cmyk_cs_to_cmyk_cm(gx_device * dev,frac c,frac m,frac y,frac k,frac out[])311 cmyk_cs_to_cmyk_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
312 {
313     out[0] = c;
314     out[1] = m;
315     out[2] = y;
316     out[3] = k;
317 }
318 
319 
320 /* The list of default color space to color model conversion routines. */
321 
322 static const gx_cm_color_map_procs DeviceGray_procs = {
323     gray_cs_to_gray_cm, rgb_cs_to_gray_cm, cmyk_cs_to_gray_cm
324 };
325 
326 static const gx_cm_color_map_procs DeviceRGB_procs = {
327     gray_cs_to_rgb_cm, rgb_cs_to_rgb_cm, cmyk_cs_to_rgb_cm
328 };
329 
330 static const gx_cm_color_map_procs DeviceCMYK_procs = {
331     gray_cs_to_cmyk_cm, rgb_cs_to_cmyk_cm, cmyk_cs_to_cmyk_cm
332 };
333 
334 static const gx_cm_color_map_procs DeviceRGBK_procs = {
335     gray_cs_to_rgbk_cm, rgb_cs_to_rgbk_cm, cmyk_cs_to_rgbk_cm
336 };
337 
338 /*
339  * These are the default handlers for returning the list of color space
340  * to color model conversion routines.
341  */
342 const gx_cm_color_map_procs *
gx_default_DevGray_get_color_mapping_procs(const gx_device * dev)343 gx_default_DevGray_get_color_mapping_procs(const gx_device * dev)
344 {
345     return &DeviceGray_procs;
346 }
347 
348 const gx_cm_color_map_procs *
gx_default_DevRGB_get_color_mapping_procs(const gx_device * dev)349 gx_default_DevRGB_get_color_mapping_procs(const gx_device * dev)
350 {
351     return &DeviceRGB_procs;
352 }
353 
354 const gx_cm_color_map_procs *
gx_default_DevCMYK_get_color_mapping_procs(const gx_device * dev)355 gx_default_DevCMYK_get_color_mapping_procs(const gx_device * dev)
356 {
357     return &DeviceCMYK_procs;
358 }
359 
360 const gx_cm_color_map_procs *
gx_default_DevRGBK_get_color_mapping_procs(const gx_device * dev)361 gx_default_DevRGBK_get_color_mapping_procs(const gx_device * dev)
362 {
363     return &DeviceRGBK_procs;
364 }
365 
366 const gx_cm_color_map_procs *
gx_error_get_color_mapping_procs(const gx_device * dev)367 gx_error_get_color_mapping_procs(const gx_device * dev)
368 {
369     /*
370      * We should never get here.  If we do then we do not have a "get_color_mapping_procs"
371      * routine for the device.
372      */
373 #ifdef DEBUG
374     dprintf("No get_color_mapping_procs proc defined for device.\n");
375 #endif
376     return NULL;
377 }
378 
379 /* ----- Default color component name to colorant index conversion routines ------ */
380 
381 #define compare_color_names(pname, name_size, name_str) \
382     (name_size == (int)strlen(name_str) && strncmp(pname, name_str, name_size) == 0)
383 
384 /* Default color component to index for a DeviceGray color model */
385 int
gx_default_DevGray_get_color_comp_index(gx_device * dev,const char * pname,int name_size,int component_type)386 gx_default_DevGray_get_color_comp_index(gx_device * dev, const char * pname,
387 					  int name_size, int component_type)
388 {
389     if (compare_color_names(pname, name_size, "Gray") ||
390 	compare_color_names(pname, name_size, "Grey"))
391         return 0;
392     else
393         return -1;		    /* Indicate that the component name is "unknown" */
394 }
395 
396 /* Default color component to index for a DeviceRGB color model */
397 int
gx_default_DevRGB_get_color_comp_index(gx_device * dev,const char * pname,int name_size,int component_type)398 gx_default_DevRGB_get_color_comp_index(gx_device * dev, const char * pname,
399 					   int name_size, int component_type)
400 {
401     if (compare_color_names(pname, name_size, "Red"))
402         return 0;
403     if (compare_color_names(pname, name_size, "Green"))
404         return 1;
405     if (compare_color_names(pname, name_size, "Blue"))
406         return 2;
407     else
408         return -1;		    /* Indicate that the component name is "unknown" */
409 }
410 
411 /* Default color component to index for a DeviceCMYK color model */
412 int
gx_default_DevCMYK_get_color_comp_index(gx_device * dev,const char * pname,int name_size,int component_type)413 gx_default_DevCMYK_get_color_comp_index(gx_device * dev, const char * pname,
414 					    int name_size, int component_type)
415 {
416     if (compare_color_names(pname, name_size, "Cyan"))
417         return 0;
418     if (compare_color_names(pname, name_size, "Magenta"))
419         return 1;
420     if (compare_color_names(pname, name_size, "Yellow"))
421         return 2;
422     if (compare_color_names(pname, name_size, "Black"))
423         return 3;
424     else
425         return -1;		    /* Indicate that the component name is "unknown" */
426 }
427 
428 /* Default color component to index for a DeviceRGBK color model */
429 int
gx_default_DevRGBK_get_color_comp_index(gx_device * dev,const char * pname,int name_size,int component_type)430 gx_default_DevRGBK_get_color_comp_index(gx_device * dev, const char * pname,
431 					    int name_size, int component_type)
432 {
433     if (compare_color_names(pname, name_size, "Red"))
434         return 0;
435     if (compare_color_names(pname, name_size, "Green"))
436         return 1;
437     if (compare_color_names(pname, name_size, "Blue"))
438         return 2;
439     if (compare_color_names(pname, name_size, "Black"))
440         return 3;
441     else
442         return -1;		    /* Indicate that the component name is "unknown" */
443 }
444 
445 /* Default color component to index for an unknown color model */
446 int
gx_error_get_color_comp_index(gx_device * dev,const char * pname,int name_size,int component_type)447 gx_error_get_color_comp_index(gx_device * dev, const char * pname,
448 					int name_size, int component_type)
449 {
450     /*
451      * We should never get here.  If we do then we do not have a "get_color_comp_index"
452      * routine for the device.
453      */
454 #ifdef DEBUG
455     dprintf("No get_color_comp_index proc defined for device.\n");
456 #endif
457     return -1;			    /* Always return "unknown" component name */
458 }
459 
460 #undef compare_color_names
461 
462 /* ---------------- Device color rendering ---------------- */
463 
464 private cmap_proc_gray(cmap_gray_halftoned);
465 private cmap_proc_gray(cmap_gray_direct);
466 
467 private cmap_proc_rgb(cmap_rgb_halftoned);
468 private cmap_proc_rgb(cmap_rgb_direct);
469 
470 #define cmap_cmyk_halftoned cmap_cmyk_direct
471 private cmap_proc_cmyk(cmap_cmyk_direct);
472 
473 private cmap_proc_rgb_alpha(cmap_rgb_alpha_halftoned);
474 private cmap_proc_rgb_alpha(cmap_rgb_alpha_direct);
475 
476 /* Procedure names are only guaranteed unique to 23 characters.... */
477 private cmap_proc_rgb_alpha(cmap_rgb_alpha_halftoned);
478 private cmap_proc_rgb_alpha(cmap_rgb_alpha_direct);
479 
480 private cmap_proc_separation(cmap_separation_halftoned);
481 private cmap_proc_separation(cmap_separation_direct);
482 
483 private cmap_proc_devicen(cmap_devicen_halftoned);
484 private cmap_proc_devicen(cmap_devicen_direct);
485 
486 private cmap_proc_is_halftoned(cmap_halftoned_is_halftoned);
487 private cmap_proc_is_halftoned(cmap_direct_is_halftoned);
488 
489 private const gx_color_map_procs cmap_few = {
490      cmap_gray_halftoned,
491      cmap_rgb_halftoned,
492      cmap_cmyk_halftoned,
493      cmap_rgb_alpha_halftoned,
494      cmap_separation_halftoned,
495      cmap_devicen_halftoned,
496      cmap_halftoned_is_halftoned
497     };
498 private const gx_color_map_procs cmap_many = {
499      cmap_gray_direct,
500      cmap_rgb_direct,
501      cmap_cmyk_direct,
502      cmap_rgb_alpha_direct,
503      cmap_separation_direct,
504      cmap_devicen_direct,
505      cmap_direct_is_halftoned
506     };
507 
508 const gx_color_map_procs *const cmap_procs_default = &cmap_many;
509 
510 
511 /* Determine the color mapping procedures for a device. */
512 /* Note that the default procedure doesn't consult the imager state. */
513 const gx_color_map_procs *
gx_get_cmap_procs(const gs_imager_state * pis,const gx_device * dev)514 gx_get_cmap_procs(const gs_imager_state *pis, const gx_device * dev)
515 {
516     return (pis->get_cmap_procs)(pis, dev);
517 }
518 
519 const gx_color_map_procs *
gx_default_get_cmap_procs(const gs_imager_state * pis,const gx_device * dev)520 gx_default_get_cmap_procs(const gs_imager_state *pis, const gx_device * dev)
521 {
522     return (gx_device_must_halftone(dev) ? &cmap_few : &cmap_many);
523 }
524 
525 /* Set the color mapping procedures in the graphics state. */
526 void
gx_set_cmap_procs(gs_imager_state * pis,const gx_device * dev)527 gx_set_cmap_procs(gs_imager_state * pis, const gx_device * dev)
528 {
529     pis->cmap_procs = gx_get_cmap_procs(pis, dev);
530 }
531 
532 /* Remap the color in the graphics state. */
533 int
gx_remap_color(gs_state * pgs)534 gx_remap_color(gs_state * pgs)
535 {
536     const gs_color_space *pcs = pgs->color_space;
537     int                   code;
538 
539     /* The current color in the graphics state is always used for */
540     /* the texture, never for the source. */
541     code = (*pcs->type->remap_color) (pgs->ccolor, pcs, pgs->dev_color,
542 				      (gs_imager_state *) pgs, pgs->device,
543 				      gs_color_select_texture);
544     /* if overprint mode is in effect, update the overprint information */
545     if (code >= 0 && pgs->effective_overprint_mode == 1)
546 	code = gs_do_set_overprint(pgs);
547     return code;
548 }
549 
550 /* Indicate that a color space has no underlying concrete space. */
551 const gs_color_space *
gx_no_concrete_space(const gs_color_space * pcs,const gs_imager_state * pis)552 gx_no_concrete_space(const gs_color_space * pcs, const gs_imager_state * pis)
553 {
554     return NULL;
555 }
556 
557 /* Indicate that a color space is concrete. */
558 const gs_color_space *
gx_same_concrete_space(const gs_color_space * pcs,const gs_imager_state * pis)559 gx_same_concrete_space(const gs_color_space * pcs, const gs_imager_state * pis)
560 {
561     return pcs;
562 }
563 
564 /* Indicate that a color cannot be concretized. */
565 int
gx_no_concretize_color(const gs_client_color * pcc,const gs_color_space * pcs,frac * pconc,const gs_imager_state * pis)566 gx_no_concretize_color(const gs_client_color * pcc, const gs_color_space * pcs,
567 		       frac * pconc, const gs_imager_state * pis)
568 {
569     return_error(gs_error_rangecheck);
570 }
571 
572 /* By default, remap a color by concretizing it and then */
573 /* remapping the concrete color. */
574 int
gx_default_remap_color(const gs_client_color * pcc,const gs_color_space * pcs,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)575 gx_default_remap_color(const gs_client_color * pcc, const gs_color_space * pcs,
576 	gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
577 		       gs_color_select_t select)
578 {
579     frac conc[GS_CLIENT_COLOR_MAX_COMPONENTS];
580     const gs_color_space *pconcs;
581     int i = pcs->type->num_components(pcs);
582     int code = (*pcs->type->concretize_color)(pcc, pcs, conc, pis);
583 
584     if (code < 0)
585 	return code;
586     pconcs = cs_concrete_space(pcs, pis);
587     code = (*pconcs->type->remap_concrete_color)(conc, pconcs, pdc, pis, dev, select);
588 
589     /* Save original color space and color info into dev color */
590     i = any_abs(i);
591     for (i--; i >= 0; i--)
592 	pdc->ccolor.paint.values[i] = pcc->paint.values[i];
593     pdc->ccolor_valid = true;
594     return code;
595 }
596 
597 /* Color remappers for the standard color spaces. */
598 /* Note that we use D... instead of Device... in some places because */
599 /* gcc under VMS only retains 23 characters of procedure names. */
600 
601 
602 /* DeviceGray */
603 int
gx_concretize_DeviceGray(const gs_client_color * pc,const gs_color_space * pcs,frac * pconc,const gs_imager_state * pis)604 gx_concretize_DeviceGray(const gs_client_color * pc, const gs_color_space * pcs,
605 			 frac * pconc, const gs_imager_state * pis)
606 {
607     float ftemp;
608 
609     pconc[0] = unit_frac(pc->paint.values[0], ftemp);
610     return 0;
611 }
612 int
gx_remap_concrete_DGray(const frac * pconc,const gs_color_space * pcs,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)613 gx_remap_concrete_DGray(const frac * pconc, const gs_color_space * pcs,
614 	gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
615 			gs_color_select_t select)
616 {
617     if (pis->alpha == gx_max_color_value)
618 	(*pis->cmap_procs->map_gray)
619 	    (pconc[0], pdc, pis, dev, select);
620     else
621 	(*pis->cmap_procs->map_rgb_alpha)
622 	    (pconc[0], pconc[0], pconc[0], cv2frac(pis->alpha),
623 	     pdc, pis, dev, select);
624     return 0;
625 }
626 int
gx_remap_DeviceGray(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)627 gx_remap_DeviceGray(const gs_client_color * pc, const gs_color_space * pcs,
628 	gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
629 		    gs_color_select_t select)
630 {
631     float ftemp;
632     frac fgray = unit_frac(pc->paint.values[0], ftemp);
633 
634     /* Save original color space and color info into dev color */
635     pdc->ccolor.paint.values[0] = pc->paint.values[0];
636     pdc->ccolor_valid = true;
637 
638     if (pis->alpha == gx_max_color_value)
639 	(*pis->cmap_procs->map_gray)
640 	    (fgray, pdc, pis, dev, select);
641     else
642 	(*pis->cmap_procs->map_rgb_alpha)
643 	    (fgray, fgray, fgray, cv2frac(pis->alpha), pdc, pis, dev, select);
644     return 0;
645 }
646 
647 /* DeviceRGB */
648 int
gx_concretize_DeviceRGB(const gs_client_color * pc,const gs_color_space * pcs,frac * pconc,const gs_imager_state * pis)649 gx_concretize_DeviceRGB(const gs_client_color * pc, const gs_color_space * pcs,
650 			frac * pconc, const gs_imager_state * pis)
651 {
652     float ftemp;
653 
654     pconc[0] = unit_frac(pc->paint.values[0], ftemp);
655     pconc[1] = unit_frac(pc->paint.values[1], ftemp);
656     pconc[2] = unit_frac(pc->paint.values[2], ftemp);
657     return 0;
658 }
659 int
gx_remap_concrete_DRGB(const frac * pconc,const gs_color_space * pcs,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)660 gx_remap_concrete_DRGB(const frac * pconc, const gs_color_space * pcs,
661 	gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
662 		       gs_color_select_t select)
663 {
664     if (pis->alpha == gx_max_color_value)
665 	gx_remap_concrete_rgb(pconc[0], pconc[1], pconc[2],
666 			      pdc, pis, dev, select);
667     else
668 	gx_remap_concrete_rgb_alpha(pconc[0], pconc[1], pconc[2],
669 				    cv2frac(pis->alpha),
670 				    pdc, pis, dev, select);
671     return 0;
672 }
673 int
gx_remap_DeviceRGB(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)674 gx_remap_DeviceRGB(const gs_client_color * pc, const gs_color_space * pcs,
675 	gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
676 		   gs_color_select_t select)
677 {
678     float ftemp;
679     frac fred = unit_frac(pc->paint.values[0], ftemp), fgreen = unit_frac(pc->paint.values[1], ftemp),
680          fblue = unit_frac(pc->paint.values[2], ftemp);
681 
682     /* Save original color space and color info into dev color */
683     pdc->ccolor.paint.values[0] = pc->paint.values[0];
684     pdc->ccolor.paint.values[1] = pc->paint.values[1];
685     pdc->ccolor.paint.values[2] = pc->paint.values[2];
686     pdc->ccolor_valid = true;
687 
688     if (pis->alpha == gx_max_color_value)
689 	gx_remap_concrete_rgb(fred, fgreen, fblue,
690 			      pdc, pis, dev, select);
691     else
692 	gx_remap_concrete_rgb_alpha(fred, fgreen, fblue, cv2frac(pis->alpha),
693 				    pdc, pis, dev, select);
694     return 0;
695 }
696 
697 /* DeviceCMYK */
698 int
gx_concretize_DeviceCMYK(const gs_client_color * pc,const gs_color_space * pcs,frac * pconc,const gs_imager_state * pis)699 gx_concretize_DeviceCMYK(const gs_client_color * pc, const gs_color_space * pcs,
700 			 frac * pconc, const gs_imager_state * pis)
701 {
702     float ftemp;
703 
704     pconc[0] = unit_frac(pc->paint.values[0], ftemp);
705     pconc[1] = unit_frac(pc->paint.values[1], ftemp);
706     pconc[2] = unit_frac(pc->paint.values[2], ftemp);
707     pconc[3] = unit_frac(pc->paint.values[3], ftemp);
708     return 0;
709 }
710 int
gx_remap_concrete_DCMYK(const frac * pconc,const gs_color_space * pcs,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)711 gx_remap_concrete_DCMYK(const frac * pconc, const gs_color_space * pcs,
712 	gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
713 			gs_color_select_t select)
714 {
715 /****** IGNORE alpha ******/
716     gx_remap_concrete_cmyk(pconc[0], pconc[1], pconc[2], pconc[3], pdc,
717 			   pis, dev, select);
718     return 0;
719 }
720 int
gx_remap_DeviceCMYK(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)721 gx_remap_DeviceCMYK(const gs_client_color * pc, const gs_color_space * pcs,
722 	gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
723 		    gs_color_select_t select)
724 {
725 /****** IGNORE alpha ******/
726     float ft0, ft1, ft2, ft3;
727 
728     /* Save original color space and color info into dev color */
729     pdc->ccolor.paint.values[0] = pc->paint.values[0];
730     pdc->ccolor.paint.values[1] = pc->paint.values[1];
731     pdc->ccolor.paint.values[2] = pc->paint.values[2];
732     pdc->ccolor.paint.values[3] = pc->paint.values[3];
733     pdc->ccolor_valid = true;
734 
735     gx_remap_concrete_cmyk((frac)unit_frac(pc->paint.values[0], ft0),
736 			   (frac)unit_frac(pc->paint.values[1], ft1),
737 			   (frac)unit_frac(pc->paint.values[2], ft2),
738 			   (frac)unit_frac(pc->paint.values[3], ft3),
739 			   pdc, pis, dev, select);
740     return 0;
741 }
742 
743 
744 /* ------ Render Gray color. ------ */
745 
746 private void
cmap_gray_halftoned(frac gray,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)747 cmap_gray_halftoned(frac gray, gx_device_color * pdc,
748      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
749 {
750     int i, ncomps = dev->color_info.num_components;
751     frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
752 
753     /* map to the color model */
754     dev_proc(dev, get_color_mapping_procs)(dev)->map_gray(dev, gray, cm_comps);
755 
756     /* apply the transfer function(s); convert to color values */
757     if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE)
758         for (i = 0; i < ncomps; i++)
759             cm_comps[i] = gx_map_color_frac(pis,
760 	    			cm_comps[i], effective_transfer[i]);
761     else
762         for (i = 0; i < ncomps; i++)
763             cm_comps[i] = frac_1 - gx_map_color_frac(pis,
764 	    		(frac)(frac_1 - cm_comps[i]), effective_transfer[i]);
765 
766     if (gx_render_device_DeviceN(cm_comps, pdc, dev, pis->dev_ht,
767 	    				&pis->screen_phase[select]) == 1)
768 	gx_color_load_select(pdc, pis, dev, select);
769 }
770 
771 private void
cmap_gray_direct(frac gray,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)772 cmap_gray_direct(frac gray, gx_device_color * pdc, const gs_imager_state * pis,
773 		 gx_device * dev, gs_color_select_t select)
774 {
775     int i, ncomps = dev->color_info.num_components;
776     frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
777     gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
778     gx_color_index color;
779 
780     /* map to the color model */
781     dev_proc(dev, get_color_mapping_procs)(dev)->map_gray(dev, gray, cm_comps);
782 
783     /* apply the transfer function(s); convert to color values */
784     if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE)
785         for (i = 0; i < ncomps; i++)
786             cv[i] = frac2cv(gx_map_color_frac(pis,
787 	    			cm_comps[i], effective_transfer[i]));
788     else
789         for (i = 0; i < ncomps; i++)
790             cv[i] = frac2cv(frac_1 - gx_map_color_frac(pis,
791 	    		(frac)(frac_1 - cm_comps[i]), effective_transfer[i]));
792 
793     /* encode as a color index */
794     color = dev_proc(dev, encode_color)(dev, cv);
795 
796     /* check if the encoding was successful; we presume failure is rare */
797     if (color != gx_no_color_index)
798         color_set_pure(pdc, color);
799     else
800         cmap_gray_halftoned(gray, pdc, pis, dev, select);
801 }
802 
803 
804 /* ------ Render RGB color. ------ */
805 
806 private void
cmap_rgb_halftoned(frac r,frac g,frac b,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)807 cmap_rgb_halftoned(frac r, frac g, frac b, gx_device_color * pdc,
808      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
809 {
810     int i, ncomps = dev->color_info.num_components;
811     frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
812 
813     /* map to the color model */
814     dev_proc(dev, get_color_mapping_procs)(dev)->map_rgb(dev, pis, r, g, b, cm_comps);
815 
816     /* apply the transfer function(s); convert to color values */
817     if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE)
818         for (i = 0; i < ncomps; i++)
819             cm_comps[i] = gx_map_color_frac(pis,
820 	    			cm_comps[i], effective_transfer[i]);
821     else
822         for (i = 0; i < ncomps; i++)
823             cm_comps[i] = frac_1 - gx_map_color_frac(pis,
824 	    		(frac)(frac_1 - cm_comps[i]), effective_transfer[i]);
825 
826     if (gx_render_device_DeviceN(cm_comps, pdc, dev, pis->dev_ht,
827 	    				&pis->screen_phase[select]) == 1)
828 	gx_color_load_select(pdc, pis, dev, select);
829 }
830 
831 private void
cmap_rgb_direct(frac r,frac g,frac b,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)832 cmap_rgb_direct(frac r, frac g, frac b, gx_device_color * pdc,
833      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
834 {
835     int i, ncomps = dev->color_info.num_components;
836     frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
837     gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
838     gx_color_index color;
839 
840     /* map to the color model */
841     dev_proc(dev, get_color_mapping_procs)(dev)->map_rgb(dev, pis, r, g, b, cm_comps);
842 
843     /* apply the transfer function(s); convert to color values */
844     if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE)
845         for (i = 0; i < ncomps; i++)
846             cv[i] = frac2cv(gx_map_color_frac(pis,
847 	    			cm_comps[i], effective_transfer[i]));
848     else
849         for (i = 0; i < ncomps; i++)
850             cv[i] = frac2cv(frac_1 - gx_map_color_frac(pis,
851 	    		(frac)(frac_1 - cm_comps[i]), effective_transfer[i]));
852 
853     /* encode as a color index */
854     color = dev_proc(dev, encode_color)(dev, cv);
855 
856     /* check if the encoding was successful; we presume failure is rare */
857     if (color != gx_no_color_index)
858         color_set_pure(pdc, color);
859     else
860         cmap_rgb_halftoned(r, g, b, pdc, pis, dev, select);
861 }
862 
863 
864 /* ------ Render CMYK color. ------ */
865 
866 private void
cmap_cmyk_direct(frac c,frac m,frac y,frac k,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)867 cmap_cmyk_direct(frac c, frac m, frac y, frac k, gx_device_color * pdc,
868      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
869 {
870     int i, ncomps = dev->color_info.num_components;
871     frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
872     gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
873     gx_color_index color;
874 
875     /* map to the color model */
876     dev_proc(dev, get_color_mapping_procs)(dev)->map_cmyk(dev, c, m, y, k, cm_comps);
877 
878     /* apply the transfer function(s); convert to color values */
879     if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE)
880         for (i = 0; i < ncomps; i++)
881             cm_comps[i] = gx_map_color_frac(pis,
882 	    			cm_comps[i], effective_transfer[i]);
883     else
884         for (i = 0; i < ncomps; i++)
885             cm_comps[i] = frac_1 - gx_map_color_frac(pis,
886 	    		(frac)(frac_1 - cm_comps[i]), effective_transfer[i]);
887 
888     /* We make a test for direct vs. halftoned, rather than */
889     /* duplicating most of the code of this procedure. */
890     if (gx_device_must_halftone(dev)) {
891 	if (gx_render_device_DeviceN(cm_comps, pdc, dev,
892 		    pis->dev_ht, &pis->screen_phase[select]) == 1)
893 	    gx_color_load_select(pdc, pis, dev, select);
894 	return;
895     }
896 
897     for (i = 0; i < ncomps; i++)
898         cv[i] = frac2cv(cm_comps[i]);
899 
900     color = dev_proc(dev, encode_color)(dev, cv);
901     if (color != gx_no_color_index)
902 	color_set_pure(pdc, color);
903     else {
904 	if (gx_render_device_DeviceN(cm_comps, pdc, dev,
905 		    pis->dev_ht, &pis->screen_phase[select]) == 1)
906 	    gx_color_load_select(pdc, pis, dev, select);
907 	return;
908     }
909 }
910 
911 private void
cmap_rgb_alpha_halftoned(frac r,frac g,frac b,frac alpha,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)912 cmap_rgb_alpha_halftoned(frac r, frac g, frac b, frac alpha,
913 	gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
914 			 gs_color_select_t select)
915 {
916      int i, ncomps = dev->color_info.num_components;
917     frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
918 
919     /* map to the color model */
920     dev_proc(dev, get_color_mapping_procs)(dev)->map_rgb(dev, pis, r, g, b, cm_comps);
921 
922     /* pre-multiply to account for the alpha weighting */
923     if (alpha != frac_1) {
924 #ifdef PREMULTIPLY_TOWARDS_WHITE
925         frac alpha_bias = frac_1 - alpha;
926 #else
927 	frac alpha_bias = 0;
928 #endif
929 
930         for (i = 0; i < ncomps; i++)
931             cm_comps[i] = (frac)((long)cm_comps[i] * alpha) / frac_1 + alpha_bias;
932     }
933 
934     /* apply the transfer function(s); convert to color values */
935     if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE)
936         for (i = 0; i < ncomps; i++)
937             cm_comps[i] = gx_map_color_frac(pis,
938 	    			cm_comps[i], effective_transfer[i]);
939     else
940         for (i = 0; i < ncomps; i++)
941             cm_comps[i] = frac_1 - gx_map_color_frac(pis,
942 	    		(frac)(frac_1 - cm_comps[i]), effective_transfer[i]);
943 
944     if (gx_render_device_DeviceN(cm_comps, pdc, dev, pis->dev_ht,
945 	    				&pis->screen_phase[select]) == 1)
946 	gx_color_load_select(pdc, pis, dev, select);
947 }
948 
949 private void
cmap_rgb_alpha_direct(frac r,frac g,frac b,frac alpha,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)950 cmap_rgb_alpha_direct(frac r, frac g, frac b, frac alpha, gx_device_color * pdc,
951      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
952 {
953     int i, ncomps = dev->color_info.num_components;
954     frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
955     gx_color_value cv_alpha, cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
956     gx_color_index color;
957 
958     /* map to the color model */
959     dev_proc(dev, get_color_mapping_procs)(dev)->map_rgb(dev, pis, r, g, b, cm_comps);
960 
961     /* pre-multiply to account for the alpha weighting */
962     if (alpha != frac_1) {
963 #ifdef PREMULTIPLY_TOWARDS_WHITE
964         frac alpha_bias = frac_1 - alpha;
965 #else
966 	frac alpha_bias = 0;
967 #endif
968 
969         for (i = 0; i < ncomps; i++)
970             cm_comps[i] = (frac)((long)cm_comps[i] * alpha) / frac_1 + alpha_bias;
971     }
972 
973     /* apply the transfer function(s); convert to color values */
974     if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE)
975         for (i = 0; i < ncomps; i++)
976             cv[i] = frac2cv(gx_map_color_frac(pis,
977 	    			cm_comps[i], effective_transfer[i]));
978     else
979         for (i = 0; i < ncomps; i++)
980             cv[i] = frac2cv(frac_1 - gx_map_color_frac(pis,
981 	    		(frac)(frac_1 - cm_comps[i]), effective_transfer[i]));
982 
983     /* encode as a color index */
984     if (dev_proc(dev, map_rgb_alpha_color) != gx_default_map_rgb_alpha_color &&
985          (cv_alpha = frac2cv(alpha)) != gx_max_color_value)
986         color = dev_proc(dev, map_rgb_alpha_color)(dev, cv[0], cv[1], cv[2], cv_alpha);
987     else
988         color = dev_proc(dev, encode_color)(dev, cv);
989 
990     /* check if the encoding was successful; we presume failure is rare */
991     if (color != gx_no_color_index)
992         color_set_pure(pdc, color);
993     else
994         cmap_rgb_alpha_halftoned(r, g, b, alpha, pdc, pis, dev, select);
995 }
996 
997 
998 /* ------ Render Separation All color. ------ */
999 
1000 /*
1001  * This routine maps DeviceN components into the order of the device's
1002  * colorants.
1003  *
1004  * Parameters:
1005  *    pcc - Pointer to DeviceN components.
1006  *    pcolor_component_map - Map from DeviceN to the Devices colorants.
1007  *        A negative value indicates component is not to be mapped.
1008  *    plist - Pointer to list for mapped components
1009  *
1010  * Returns:
1011  *    Mapped components in plist.
1012  */
1013 private inline void
map_components_to_colorants(const frac * pcc,const gs_devicen_color_map * pcolor_component_map,frac * plist)1014 map_components_to_colorants(const frac * pcc,
1015 	const gs_devicen_color_map * pcolor_component_map, frac * plist)
1016 {
1017     int i = pcolor_component_map->num_colorants - 1;
1018     int pos;
1019 
1020     /* Clear all output colorants first */
1021     for (; i >= 0; i--) {
1022 	plist[i] = frac_0;
1023     }
1024 
1025     /* Map color components into output list */
1026     for (i = pcolor_component_map->num_components - 1; i >= 0; i--) {
1027 	pos = pcolor_component_map->color_map[i];
1028 	if (pos >= 0)
1029 	    plist[pos] = pcc[i];
1030     }
1031 }
1032 
1033 private void
cmap_separation_halftoned(frac all,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)1034 cmap_separation_halftoned(frac all, gx_device_color * pdc,
1035      const gs_imager_state * pis, gx_device * dev, gs_color_select_t select)
1036 {
1037     int i, ncomps = dev->color_info.num_components;
1038     bool additive = dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE;
1039     frac comp_value = all;
1040     frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
1041 
1042     if (pis->color_component_map.sep_type == SEP_ALL) {
1043 	/*
1044 	 * Invert the photometric interpretation for additive
1045 	 * color spaces because separations are always subtractive.
1046 	 */
1047 	if (additive)
1048 	    comp_value = frac_1 - comp_value;
1049 
1050         /* Use the "all" value for all components */
1051 	i = pis->color_component_map.num_colorants - 1;
1052         for (; i >= 0; i--)
1053             cm_comps[i] = comp_value;
1054     }
1055     else {
1056         /* map to the color model */
1057         map_components_to_colorants(&all, &(pis->color_component_map), cm_comps);
1058     }
1059 
1060     /* apply the transfer function(s); convert to color values */
1061     if (additive)
1062         for (i = 0; i < ncomps; i++)
1063             cm_comps[i] = gx_map_color_frac(pis,
1064 	    			cm_comps[i], effective_transfer[i]);
1065     else
1066         for (i = 0; i < ncomps; i++)
1067             cm_comps[i] = frac_1 - gx_map_color_frac(pis,
1068 	    		(frac)(frac_1 - cm_comps[i]), effective_transfer[i]);
1069 
1070     if (gx_render_device_DeviceN(cm_comps, pdc, dev, pis->dev_ht,
1071     					&pis->screen_phase[select]) == 1)
1072 	gx_color_load_select(pdc, pis, dev, select);
1073 }
1074 
1075 private void
cmap_separation_direct(frac all,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)1076 cmap_separation_direct(frac all, gx_device_color * pdc, const gs_imager_state * pis,
1077 		 gx_device * dev, gs_color_select_t select)
1078 {
1079     int i, ncomps = dev->color_info.num_components;
1080     bool additive = dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE;
1081     frac comp_value = all;
1082     frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
1083     gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
1084     gx_color_index color;
1085 
1086     if (pis->color_component_map.sep_type == SEP_ALL) {
1087 	/*
1088 	 * Invert the photometric interpretation for additive
1089 	 * color spaces because separations are always subtractive.
1090 	 */
1091 	if (additive)
1092 	    comp_value = frac_1 - comp_value;
1093 
1094         /* Use the "all" value for all components */
1095         i = pis->color_component_map.num_colorants - 1;
1096         for (; i >= 0; i--)
1097             cm_comps[i] = comp_value;
1098     }
1099     else {
1100         /* map to the color model */
1101         map_components_to_colorants(&comp_value, &(pis->color_component_map), cm_comps);
1102     }
1103 
1104     /* apply the transfer function(s); convert to color values */
1105     if (additive)
1106         for (i = 0; i < ncomps; i++)
1107             cv[i] = frac2cv(gx_map_color_frac(pis,
1108 	    			cm_comps[i], effective_transfer[i]));
1109     else
1110         for (i = 0; i < ncomps; i++)
1111             cv[i] = frac2cv(frac_1 - gx_map_color_frac(pis,
1112 	    		(frac)(frac_1 - cm_comps[i]), effective_transfer[i]));
1113 
1114     /* encode as a color index */
1115     color = dev_proc(dev, encode_color)(dev, cv);
1116 
1117     /* check if the encoding was successful; we presume failure is rare */
1118     if (color != gx_no_color_index)
1119         color_set_pure(pdc, color);
1120     else
1121         cmap_separation_halftoned(all, pdc, pis, dev, select);
1122 }
1123 
1124 
1125 /* ------ DeviceN color mapping */
1126 
1127 /*
1128  * This routine is called to map a DeviceN colorspace to a DeviceN
1129  * output device which requires halftoning.  T
1130  */
1131 private void
cmap_devicen_halftoned(const frac * pcc,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)1132 cmap_devicen_halftoned(const frac * pcc,
1133     gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
1134     gs_color_select_t select)
1135 {
1136     int i, ncomps = dev->color_info.num_components;
1137     frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
1138 
1139     /* map to the color model */
1140     map_components_to_colorants(pcc, &(pis->color_component_map), cm_comps);
1141 
1142     /* apply the transfer function(s); convert to color values */
1143     if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE)
1144         for (i = 0; i < ncomps; i++)
1145             cm_comps[i] = gx_map_color_frac(pis,
1146 	    			cm_comps[i], effective_transfer[i]);
1147     else
1148         for (i = 0; i < ncomps; i++)
1149             cm_comps[i] = frac_1 - gx_map_color_frac(pis,
1150 	    		(frac)(frac_1 - cm_comps[i]), effective_transfer[i]);
1151 
1152     /* We need to finish halftoning */
1153 
1154     if (gx_render_device_DeviceN(cm_comps, pdc, dev, pis->dev_ht,
1155     					&pis->screen_phase[select]) == 1)
1156 	gx_color_load_select(pdc, pis, dev, select);
1157 }
1158 
1159 /*
1160  * This routine is called to map a DeviceN colorspace to a DeviceN
1161  * output device which does not require halftoning.
1162  */
1163 private void
cmap_devicen_direct(const frac * pcc,gx_device_color * pdc,const gs_imager_state * pis,gx_device * dev,gs_color_select_t select)1164 cmap_devicen_direct(const frac * pcc,
1165     gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
1166     gs_color_select_t select)
1167 {
1168     int i, ncomps = dev->color_info.num_components;
1169     frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
1170     gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
1171     gx_color_index color;
1172 
1173     /* map to the color model */
1174     map_components_to_colorants(pcc, &(pis->color_component_map), cm_comps);;
1175 
1176     /* apply the transfer function(s); convert to color values */
1177     if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE)
1178         for (i = 0; i < ncomps; i++)
1179             cv[i] = frac2cv(gx_map_color_frac(pis,
1180 	    			cm_comps[i], effective_transfer[i]));
1181     else
1182         for (i = 0; i < ncomps; i++)
1183             cv[i] = frac2cv(frac_1 - gx_map_color_frac(pis,
1184 	    		(frac)(frac_1 - cm_comps[i]), effective_transfer[i]));
1185 
1186     /* encode as a color index */
1187     color = dev_proc(dev, encode_color)(dev, cv);
1188 
1189     /* check if the encoding was successful; we presume failure is rare */
1190     if (color != gx_no_color_index)
1191         color_set_pure(pdc, color);
1192     else
1193         cmap_devicen_halftoned(pcc, pdc, pis, dev, select);
1194 }
1195 
1196 /* ------ Halftoning check ----- */
1197 
1198 private bool
cmap_halftoned_is_halftoned(const gs_imager_state * pis,gx_device * dev)1199 cmap_halftoned_is_halftoned(const gs_imager_state * pis, gx_device * dev)
1200 {
1201     return true;
1202 }
1203 
1204 private bool
cmap_direct_is_halftoned(const gs_imager_state * pis,gx_device * dev)1205 cmap_direct_is_halftoned(const gs_imager_state * pis, gx_device * dev)
1206 {
1207     return false;
1208 }
1209 
1210 /* ------ Transfer function mapping ------ */
1211 
1212 /* Define an identity transfer function. */
1213 float
gs_identity_transfer(floatp value,const gx_transfer_map * pmap)1214 gs_identity_transfer(floatp value, const gx_transfer_map * pmap)
1215 {
1216     return (float) value;
1217 }
1218 
1219 /* Define the generic transfer function for the library layer. */
1220 /* This just returns what's already in the map. */
1221 float
gs_mapped_transfer(floatp value,const gx_transfer_map * pmap)1222 gs_mapped_transfer(floatp value, const gx_transfer_map * pmap)
1223 {
1224     return gx_map_color_float(pmap, value);
1225 }
1226 
1227 /* Set a transfer map to the identity map. */
1228 void
gx_set_identity_transfer(gx_transfer_map * pmap)1229 gx_set_identity_transfer(gx_transfer_map *pmap)
1230 {
1231     int i;
1232 
1233     pmap->proc = gs_identity_transfer;
1234     /* We still have to fill in the cached values. */
1235     for (i = 0; i < transfer_map_size; ++i)
1236 	pmap->values[i] = bits2frac(i, log2_transfer_map_size);
1237 }
1238 
1239 #if FRAC_MAP_INTERPOLATE	/* NOTA BENE */
1240 
1241 /* Map a color fraction through a transfer map. */
1242 /* We only use this if we are interpolating. */
1243 frac
gx_color_frac_map(frac cv,const frac * values)1244 gx_color_frac_map(frac cv, const frac * values)
1245 {
1246 #define cp_frac_bits (frac_bits - log2_transfer_map_size)
1247     int cmi = frac2bits_floor(cv, log2_transfer_map_size);
1248     frac mv = values[cmi];
1249     int rem, mdv;
1250 
1251     /* Interpolate between two adjacent values if needed. */
1252     rem = cv - bits2frac(cmi, log2_transfer_map_size);
1253     if (rem == 0)
1254 	return mv;
1255     mdv = values[cmi + 1] - mv;
1256 #if arch_ints_are_short
1257     /* Only use long multiplication if necessary. */
1258     if (mdv < -1 << (16 - cp_frac_bits) ||
1259 	mdv > 1 << (16 - cp_frac_bits)
1260 	)
1261 	return mv + (uint) (((ulong) rem * mdv) >> cp_frac_bits);
1262 #endif
1263     return mv + ((rem * mdv) >> cp_frac_bits);
1264 #undef cp_frac_bits
1265 }
1266 
1267 #endif /* FRAC_MAP_INTERPOLATE */
1268 
1269 /* ------ Default device color mapping ------ */
1270 /* White-on-black */
1271 gx_color_index
gx_default_w_b_map_rgb_color(gx_device * dev,const gx_color_value cv[])1272 gx_default_w_b_map_rgb_color(gx_device * dev, const gx_color_value cv[])
1273 {				/* Map values >= 1/2 to 1, < 1/2 to 0. */
1274     int             i, ncomps = dev->color_info.num_components;
1275     gx_color_value  cv_all = 0;
1276 
1277     for (i = 0; i < ncomps; i++)
1278         cv_all |= cv[i];
1279     return cv_all > gx_max_color_value / 2 ? (gx_color_index)1
1280         : (gx_color_index)0;
1281 
1282 }
1283 
1284 int
gx_default_w_b_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])1285 gx_default_w_b_map_color_rgb(gx_device * dev, gx_color_index color,
1286 			     gx_color_value prgb[3])
1287 {				/* Map 1 to max_value, 0 to 0. */
1288     prgb[0] = prgb[1] = prgb[2] = -(gx_color_value) color;
1289     return 0;
1290 }
1291 
1292 /* Black-on-white */
1293 gx_color_index
gx_default_b_w_map_rgb_color(gx_device * dev,const gx_color_value cv[])1294 gx_default_b_w_map_rgb_color(gx_device * dev, const gx_color_value cv[])
1295 {
1296     int             i, ncomps = dev->color_info.num_components;
1297     gx_color_value  cv_all = 0;
1298 
1299     for (i = 0; i < ncomps; i++)
1300         cv_all |= cv[i];
1301     return cv_all > gx_max_color_value / 2 ? (gx_color_index)0
1302         : (gx_color_index)1;
1303 }
1304 
1305 int
gx_default_b_w_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])1306 gx_default_b_w_map_color_rgb(gx_device * dev, gx_color_index color,
1307 			     gx_color_value prgb[3])
1308 {				/* Map 0 to max_value, 1 to 0. */
1309     prgb[0] = prgb[1] = prgb[2] = -((gx_color_value) color ^ 1);
1310     return 0;
1311 }
1312 
1313 /* RGB mapping for gray-scale devices */
1314 
1315 gx_color_index
gx_default_gray_map_rgb_color(gx_device * dev,const gx_color_value cv[])1316 gx_default_gray_map_rgb_color(gx_device * dev, const gx_color_value cv[])
1317 {				/* We round the value rather than truncating it. */
1318     gx_color_value gray =
1319     (((cv[0] * (ulong) lum_red_weight) +
1320       (cv[1] * (ulong) lum_green_weight) +
1321       (cv[2] * (ulong) lum_blue_weight) +
1322       (lum_all_weights / 2)) / lum_all_weights
1323      * dev->color_info.max_gray +
1324      (gx_max_color_value / 2)) / gx_max_color_value;
1325 
1326     return gray;
1327 }
1328 
1329 int
gx_default_gray_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])1330 gx_default_gray_map_color_rgb(gx_device * dev, gx_color_index color,
1331 			      gx_color_value prgb[3])
1332 {
1333     gx_color_value gray = (gx_color_value)
1334 	(color * gx_max_color_value / dev->color_info.max_gray);
1335 
1336     prgb[0] = gray;
1337     prgb[1] = gray;
1338     prgb[2] = gray;
1339     return 0;
1340 }
1341 
1342 gx_color_index
gx_default_8bit_map_gray_color(gx_device * dev,const gx_color_value cv[])1343 gx_default_8bit_map_gray_color(gx_device * dev, const gx_color_value cv[])
1344 {
1345     gx_color_index color = gx_color_value_to_byte(cv[0]);
1346 
1347     return (color == gx_no_color_index ? color ^ 1 : color);
1348 }
1349 
1350 int
gx_default_8bit_map_color_gray(gx_device * dev,gx_color_index color,gx_color_value pgray[1])1351 gx_default_8bit_map_color_gray(gx_device * dev, gx_color_index color,
1352 			      gx_color_value pgray[1])
1353 {
1354     pgray[0] = (gx_color_value)(color * gx_max_color_value / 255);
1355     return 0;
1356 }
1357 
1358 /* RGB mapping for 24-bit true (RGB) color devices */
1359 
1360 gx_color_index
gx_default_rgb_map_rgb_color(gx_device * dev,const gx_color_value cv[])1361 gx_default_rgb_map_rgb_color(gx_device * dev, const gx_color_value cv[])
1362 {
1363     if (dev->color_info.depth == 24)
1364 	return gx_color_value_to_byte(cv[2]) +
1365 	    ((uint) gx_color_value_to_byte(cv[1]) << 8) +
1366 	    ((ulong) gx_color_value_to_byte(cv[0]) << 16);
1367     else {
1368 	int bpc = dev->color_info.depth / 3;
1369 	int drop = sizeof(gx_color_value) * 8 - bpc;
1370 	return ( ( (((gx_color_index)cv[0] >> drop) << bpc) +
1371 		    ((gx_color_index)cv[1] >> drop)         ) << bpc) +
1372 	       ((gx_color_index)cv[2] >> drop);
1373     }
1374 }
1375 
1376 /* Map a color index to a r-g-b color. */
1377 int
gx_default_rgb_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])1378 gx_default_rgb_map_color_rgb(gx_device * dev, gx_color_index color,
1379 			     gx_color_value prgb[3])
1380 {
1381     if (dev->color_info.depth == 24) {
1382 	prgb[0] = gx_color_value_from_byte(color >> 16);
1383 	prgb[1] = gx_color_value_from_byte((color >> 8) & 0xff);
1384 	prgb[2] = gx_color_value_from_byte(color & 0xff);
1385     } else {
1386 	uint bits_per_color = dev->color_info.depth / 3;
1387 	uint color_mask = (1 << bits_per_color) - 1;
1388 
1389 	prgb[0] = ((color >> (bits_per_color * 2)) & color_mask) *
1390 	    (ulong) gx_max_color_value / color_mask;
1391 	prgb[1] = ((color >> (bits_per_color)) & color_mask) *
1392 	    (ulong) gx_max_color_value / color_mask;
1393 	prgb[2] = (color & color_mask) *
1394 	    (ulong) gx_max_color_value / color_mask;
1395     }
1396     return 0;
1397 }
1398 
1399 /* CMYK mapping for RGB devices (should never be called!) */
1400 
1401 gx_color_index
gx_default_map_cmyk_color(gx_device * dev,const gx_color_value cv[])1402 gx_default_map_cmyk_color(gx_device * dev, const gx_color_value cv[])
1403 {				/* Convert to RGB */
1404     frac rgb[3];
1405     gx_color_value rgb_cv[3];
1406     color_cmyk_to_rgb(cv2frac(cv[0]), cv2frac(cv[1]), cv2frac(cv[2]), cv2frac(cv[3]),
1407 		      NULL, rgb);
1408     rgb_cv[0] = frac2cv(rgb[0]);
1409     rgb_cv[1] = frac2cv(rgb[1]);
1410     rgb_cv[2] = frac2cv(rgb[2]);
1411     return (*dev_proc(dev, map_rgb_color)) (dev, rgb_cv);
1412 }
1413 
1414 /* Mapping for CMYK devices */
1415 
1416 gx_color_index
cmyk_1bit_map_cmyk_color(gx_device * dev,const gx_color_value cv[])1417 cmyk_1bit_map_cmyk_color(gx_device * dev, const gx_color_value cv[])
1418 {
1419 #define CV_BIT(v) ((v) >> (gx_color_value_bits - 1))
1420     return (gx_color_index)
1421 	(CV_BIT(cv[3]) + (CV_BIT(cv[2]) << 1) + (CV_BIT(cv[1]) << 2) + (CV_BIT(cv[0]) << 3));
1422 #undef CV_BIT
1423 }
1424 
1425 /* Shouldn't be called: decode_color should be cmyk_1bit_map_color_cmyk */
1426 int
cmyk_1bit_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])1427 cmyk_1bit_map_color_rgb(gx_device * dev, gx_color_index color,
1428 			gx_color_value prgb[3])
1429 {
1430     if (color & 1)
1431 	prgb[0] = prgb[1] = prgb[2] = 0;
1432     else {
1433 	prgb[0] = (color & 8 ? 0 : gx_max_color_value);
1434 	prgb[1] = (color & 4 ? 0 : gx_max_color_value);
1435 	prgb[2] = (color & 2 ? 0 : gx_max_color_value);
1436     }
1437     return 0;
1438 }
1439 
1440 int
cmyk_1bit_map_color_cmyk(gx_device * dev,gx_color_index color,gx_color_value pcv[4])1441 cmyk_1bit_map_color_cmyk(gx_device * dev, gx_color_index color,
1442 			gx_color_value pcv[4])
1443 {
1444     pcv[0] = (color & 8 ? 0 : gx_max_color_value);
1445     pcv[1] = (color & 4 ? 0 : gx_max_color_value);
1446     pcv[2] = (color & 2 ? 0 : gx_max_color_value);
1447     pcv[3] = (color & 1 ? 0 : gx_max_color_value);
1448     return 0;
1449 }
1450 
1451 gx_color_index
cmyk_8bit_map_cmyk_color(gx_device * dev,const gx_color_value cv[])1452 cmyk_8bit_map_cmyk_color(gx_device * dev, const gx_color_value cv[])
1453 {
1454     gx_color_index color =
1455 	gx_color_value_to_byte(cv[3]) +
1456 	((uint)gx_color_value_to_byte(cv[2]) << 8) +
1457 	((uint)gx_color_value_to_byte(cv[1]) << 16) +
1458 	((uint)gx_color_value_to_byte(cv[0]) << 24);
1459 
1460     return (color == gx_no_color_index ? color ^ 1 : color);
1461 }
1462 
1463 /* Shouldn't be called: decode_color should be cmyk_8bit_map_color_cmyk */
1464 int
cmyk_8bit_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])1465 cmyk_8bit_map_color_rgb(gx_device * dev, gx_color_index color,
1466 			gx_color_value prgb[3])
1467 {
1468     int
1469 	not_k = (int) (~color & 0xff),
1470 	r = not_k - (int) (color >> 24),
1471 	g = not_k - (int) ((color >> 16) & 0xff),
1472 	b = not_k - (int) ((color >> 8) & 0xff);
1473 
1474     prgb[0] = (r < 0 ? 0 : gx_color_value_from_byte(r));
1475     prgb[1] = (g < 0 ? 0 : gx_color_value_from_byte(g));
1476     prgb[2] = (b < 0 ? 0 : gx_color_value_from_byte(b));
1477     return 0;
1478 }
1479 
1480 int
cmyk_8bit_map_color_cmyk(gx_device * dev,gx_color_index color,gx_color_value pcv[4])1481 cmyk_8bit_map_color_cmyk(gx_device * dev, gx_color_index color,
1482 			gx_color_value pcv[4])
1483 {
1484     pcv[0] = gx_color_value_from_byte((color >> 24) & 0xff);
1485     pcv[1] = gx_color_value_from_byte((color >> 16) & 0xff);
1486     pcv[2] = gx_color_value_from_byte((color >> 8) & 0xff);
1487     pcv[3] = gx_color_value_from_byte(color & 0xff);
1488     return 0;
1489 }
1490 
1491 /* Default mapping between RGB+alpha and RGB. */
1492 
1493 gx_color_index
gx_default_map_rgb_alpha_color(gx_device * dev,gx_color_value r,gx_color_value g,gx_color_value b,gx_color_value alpha)1494 gx_default_map_rgb_alpha_color(gx_device * dev,
1495  gx_color_value r, gx_color_value g, gx_color_value b, gx_color_value alpha)
1496 {				/* Colors have been premultiplied: we don't need to do it here. */
1497     gx_color_value cv[3];
1498     cv[0] = r; cv[1] = g; cv[2] = b;
1499     return (*dev_proc(dev, map_rgb_color))(dev, cv);
1500 }
1501 
1502 int
gx_default_map_color_rgb_alpha(gx_device * dev,gx_color_index color,gx_color_value prgba[4])1503 gx_default_map_color_rgb_alpha(gx_device * dev, gx_color_index color,
1504 			       gx_color_value prgba[4])
1505 {
1506     prgba[3] = gx_max_color_value;	/* alpha = 1 */
1507     return (*dev_proc(dev, map_color_rgb)) (dev, color, prgba);
1508 }
1509