1 /* Copyright (C) 2001-2019 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
7    This software is distributed under license and may not be copied,
8    modified or distributed except as expressly authorized under the terms
9    of the license contained in the file LICENSE in this distribution.
10 
11    Refer to licensing information at http://www.artifex.com or contact
12    Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13    CA 94945, U.S.A., +1(415)492-9861, for further information.
14 */
15 
16 
17 /* Color space substitution "operators" */
18 #include "gx.h"
19 #include "gserrors.h"
20 #include "gscssub.h"
21 #include "gxcspace.h"		/* for st_color_space */
22 #include "gxdevcli.h"
23 #include "gzstate.h"
24 
25 /* .setsubstitutecolorspace */
26 /* Note that, to support PDF, ICCBased color spaces may be used to substitute
27  * for the Device* color spaces (previously, only CIEBased color spaces could
28  * be used for this purpose). */
29 int
gs_setsubstitutecolorspace(gs_gstate * pgs,gs_color_space_index csi,const gs_color_space * pcs)30 gs_setsubstitutecolorspace(gs_gstate *pgs, gs_color_space_index csi,
31                            const gs_color_space *pcs)
32 {
33     int index = (int)csi;
34     static const uint masks[3] = {
35         (1 << gs_color_space_index_DeviceGray) |
36           (1 << gs_color_space_index_CIEA),
37         (1 << gs_color_space_index_DeviceRGB) |
38           (1 << gs_color_space_index_CIEABC) |
39           (1 << gs_color_space_index_CIEDEF),
40         (1 << gs_color_space_index_DeviceCMYK) |
41           (1 << gs_color_space_index_CIEDEFG)
42     };
43     const gs_color_space *pcs_old;
44 
45     if (index < 0 || index > 2)
46         return_error(gs_error_rangecheck);
47     if (pcs) {
48         if (gs_color_space_get_index(pcs) == gs_color_space_index_CIEICC) {
49             static const byte dev_ncomps[3] = {1, 3, 4};
50 
51              if (dev_ncomps[index] != cs_num_components(pcs))
52                  return_error(gs_error_rangecheck);
53         } else if (!masks[index] && (1 << gs_color_space_get_index(pcs)))
54             return_error(gs_error_rangecheck);
55     }
56     pcs_old = pgs->device_color_spaces.indexed[index];
57     if (pcs_old == 0 &&	(pcs == 0 || gs_color_space_get_index(pcs) == csi))
58         return 0;
59     rc_assign(pgs->device_color_space.indexed[index],
60               (pcs ? pcs :
61                pgs->shared->device_color_spaces.indexed[index]),
62               "gs_setsubstitutecolorspace");
63     return 0;
64 }
65 
66 /* Possibly-substituted color space accessors. */
67 const gs_color_space *
gs_current_DeviceGray_space(const gs_gstate * pgs)68 gs_current_DeviceGray_space(const gs_gstate *pgs)
69 {
70     const gs_color_space *pcs;
71 
72     return (!pgs->device->UseCIEColor ||
73             (pcs = pgs->device_color_spaces.named.Gray) == 0 ?
74             pgs->shared->device_color_spaces.named.Gray : pcs);
75 }
76 const gs_color_space *
gs_current_DeviceRGB_space(const gs_gstate * pgs)77 gs_current_DeviceRGB_space(const gs_gstate *pgs)
78 {
79     const gs_color_space *pcs;
80 
81     return (!pgs->device->UseCIEColor ||
82             (pcs = pgs->device_color_spaces.named.RGB) == 0 ?
83             pgs->shared->device_color_spaces.named.RGB : pcs);
84 }
85 const gs_color_space *
gs_current_DeviceCMYK_space(const gs_gstate * pgs)86 gs_current_DeviceCMYK_space(const gs_gstate *pgs)
87 {
88     const gs_color_space *pcs;
89 
90     return (!pgs->device->UseCIEColor ||
91             (pcs = pgs->device_color_spaces.named.CMYK) == 0 ?
92             pgs->shared->device_color_spaces.named.CMYK : pcs);
93 }
94 
95 /* .currentsubstitutecolorspace */
96 const gs_color_space *
gs_currentsubstitutecolorspace(const gs_gstate * pgs,gs_color_space_index csi)97 gs_currentsubstitutecolorspace(const gs_gstate *pgs, gs_color_space_index csi)
98 {
99     switch (csi) {
100     case gs_color_space_index_DeviceGray:
101         return gs_current_DeviceGray_space(pgs);
102     case gs_color_space_index_DeviceRGB:
103         return gs_current_DeviceRGB_space(pgs);
104     case gs_color_space_index_DeviceCMYK:
105         return gs_current_DeviceCMYK_space(pgs);
106     default:
107         return 0;
108     }
109 }
110