xref: /plan9/sys/src/cmd/gs/src/gscssub.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1999 Aladdin Enterprises.  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: gscssub.c,v 1.5 2002/02/21 22:24:52 giles Exp $ */
18 /* Color space substitution "operators" */
19 #include "gx.h"
20 #include "gserrors.h"
21 #include "gscssub.h"
22 #include "gxcspace.h"		/* for st_color_space */
23 #include "gxdevcli.h"
24 #include "gzstate.h"
25 
26 /* .setsubstitutecolorspace */
27 /* Note that, to support PDF, ICCBased color spaces may be used to substitute
28  * for the Device* color spaces (previously, only CIEBased color spaces could
29  * be used for this purpose). */
30 int
gs_setsubstitutecolorspace(gs_state * pgs,gs_color_space_index csi,const gs_color_space * pcs)31 gs_setsubstitutecolorspace(gs_state *pgs, gs_color_space_index csi,
32 			   const gs_color_space *pcs)
33 {
34     int index = (int)csi;
35     static const uint masks[3] = {
36 	(1 << gs_color_space_index_DeviceGray) |
37 	  (1 << gs_color_space_index_CIEA),
38 	(1 << gs_color_space_index_DeviceRGB) |
39 	  (1 << gs_color_space_index_CIEABC) |
40 	  (1 << gs_color_space_index_CIEDEF),
41 	(1 << gs_color_space_index_DeviceCMYK) |
42 	  (1 << gs_color_space_index_CIEDEFG)
43     };
44     const gs_color_space *pcs_old;
45 
46     if (index < 0 || index > 2)
47 	return_error(gs_error_rangecheck);
48     if (pcs) {
49         if (gs_color_space_get_index(pcs) == gs_color_space_index_CIEICC) {
50             static const byte dev_ncomps[3] = {1, 3, 4};
51 
52              if (dev_ncomps[index] != cs_num_components(pcs))
53                  return_error(gs_error_rangecheck);
54         } else if (!masks[index] && (1 << gs_color_space_get_index(pcs)))
55 	    return_error(gs_error_rangecheck);
56     }
57     pcs_old = pgs->device_color_spaces.indexed[index];
58     if (pcs_old == 0) {
59 	gs_color_space *pcs_new;
60 
61 	if (pcs == 0 || gs_color_space_get_index(pcs) == csi)
62 	    return 0;
63 	pcs_new = gs_alloc_struct(pgs->memory, gs_color_space, &st_color_space,
64 				  "gs_setsubstitutecolorspace");
65 	if (pcs_new == 0)
66 	    return_error(gs_error_VMerror);
67 	gs_cspace_init_from(pcs_new, pcs);
68 	pgs->device_color_spaces.indexed[index] = pcs_new;
69     } else {
70 	gs_cspace_assign(pgs->device_color_spaces.indexed[index],
71 			 (pcs ? pcs :
72 			  pgs->shared->device_color_spaces.indexed[index]));
73     }
74     return 0;
75 }
76 
77 /* Possibly-substituted color space accessors. */
78 const gs_color_space *
gs_current_DeviceGray_space(const gs_state * pgs)79 gs_current_DeviceGray_space(const gs_state *pgs)
80 {
81     const gs_color_space *pcs;
82 
83     return (!pgs->device->UseCIEColor ||
84 	    (pcs = pgs->device_color_spaces.named.Gray) == 0 ?
85 	    pgs->shared->device_color_spaces.named.Gray : pcs);
86 }
87 const gs_color_space *
gs_current_DeviceRGB_space(const gs_state * pgs)88 gs_current_DeviceRGB_space(const gs_state *pgs)
89 {
90     const gs_color_space *pcs;
91 
92     return (!pgs->device->UseCIEColor ||
93 	    (pcs = pgs->device_color_spaces.named.RGB) == 0 ?
94 	    pgs->shared->device_color_spaces.named.RGB : pcs);
95 }
96 const gs_color_space *
gs_current_DeviceCMYK_space(const gs_state * pgs)97 gs_current_DeviceCMYK_space(const gs_state *pgs)
98 {
99     const gs_color_space *pcs;
100 
101     return (!pgs->device->UseCIEColor ||
102 	    (pcs = pgs->device_color_spaces.named.CMYK) == 0 ?
103 	    pgs->shared->device_color_spaces.named.CMYK : pcs);
104 }
105 
106 /* .currentsubstitutecolorspace */
107 const gs_color_space *
gs_currentsubstitutecolorspace(const gs_state * pgs,gs_color_space_index csi)108 gs_currentsubstitutecolorspace(const gs_state *pgs, gs_color_space_index csi)
109 {
110     switch (csi) {
111     case gs_color_space_index_DeviceGray:
112 	return gs_current_DeviceGray_space(pgs);
113     case gs_color_space_index_DeviceRGB:
114 	return gs_current_DeviceRGB_space(pgs);
115     case gs_color_space_index_DeviceCMYK:
116 	return gs_current_DeviceCMYK_space(pgs);
117     default:
118 	return 0;
119     }
120 }
121