/src/libspectre/ghostscript/base/gxhldevc.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2020 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 | | /* High level device color save/compare procedures */ |
17 | | |
18 | | /* |
19 | | * See comments at the start of gxhldevc.h for more explanation of the |
20 | | * purpose and operation of these procedures. |
21 | | */ |
22 | | #include "gx.h" |
23 | | #include "gzstate.h" |
24 | | #include "gscspace.h" |
25 | | #include "gxcspace.h" |
26 | | #include "gxhldevc.h" |
27 | | #include "memory_.h" |
28 | | #include "gxpcolor.h" |
29 | | #include "gsptype1.h" |
30 | | #include "gsptype2.h" |
31 | | |
32 | | /* |
33 | | * Initiailze a high level saved color to null |
34 | | */ |
35 | | void gx_hld_saved_color_init(gx_hl_saved_color * psc) |
36 | 0 | { |
37 | 0 | gx_device_color temp_devc; |
38 | |
|
39 | 0 | memset(psc, 0, sizeof(*psc)); /* clear the entire structure */ |
40 | 0 | psc->color_space_id = psc->pattern_id = gs_no_id; |
41 | 0 | color_set_null(&temp_devc); |
42 | 0 | temp_devc.type->save_dc(&temp_devc, &(psc->saved_dev_color)); |
43 | 0 | } |
44 | | |
45 | | /* |
46 | | * Save the device color information including the color space id and |
47 | | * client color data (if available). |
48 | | * |
49 | | * More description in src/gxhldevc.h |
50 | | */ |
51 | | bool |
52 | | gx_hld_save_color(const gs_gstate * pgs, const gx_device_color * pdevc, |
53 | | gx_hl_saved_color * psc) |
54 | 0 | { |
55 | 0 | memset(psc, 0, sizeof(*psc)); /* clear the entire structure */ |
56 | |
|
57 | 0 | if (pdevc == NULL) { |
58 | | /* No device color given, should not happen */ |
59 | 0 | gx_hld_saved_color_init(psc); /* revert to unknown color */ |
60 | 0 | return false; |
61 | 0 | } else if (pgs == NULL) { |
62 | | /* No color space, simply save device color specific info */ |
63 | 0 | psc->color_space_id = psc->pattern_id = gs_no_id; |
64 | 0 | pdevc->type->save_dc(pdevc, &(psc->saved_dev_color)); |
65 | 0 | return false; |
66 | 0 | } else { |
67 | | /* |
68 | | * Have color space, save id, ccolor, & device color specific info. |
69 | | * Also save the high level colors since two gx_color_index values |
70 | | * may be the same but for differing high level colors (due to the |
71 | | * usual lower resolution of the gx_color_index values. |
72 | | */ |
73 | 0 | const gs_color_space * pcs = gs_currentcolorspace_inline(pgs); |
74 | 0 | int i = gs_color_space_num_components(pcs); |
75 | |
|
76 | 0 | psc->color_space_id = pcs->id; |
77 | 0 | pdevc->type->save_dc(pdevc, &(psc->saved_dev_color)); |
78 | 0 | if (pdevc->type == gx_dc_type_pattern2) |
79 | 0 | i = 0; |
80 | 0 | else if (i < 0) |
81 | 0 | i = -i - 1; /* See gx_num_components_Pattern. */ |
82 | 0 | for (i--; i >= 0; i--) |
83 | 0 | psc->ccolor.paint.values[i] = pdevc->ccolor.paint.values[i]; |
84 | | |
85 | | /* Save the pattern id - if present */ |
86 | 0 | if ((pdevc->type == gx_dc_type_pattern |
87 | 0 | || pdevc->type == gx_dc_type_pattern2) && pdevc->ccolor_valid) |
88 | 0 | psc->pattern_id = pdevc->ccolor.pattern->pattern_id; |
89 | 0 | else |
90 | 0 | psc->pattern_id = gs_no_id; |
91 | 0 | return true; |
92 | 0 | } |
93 | 0 | } |
94 | | |
95 | | /* |
96 | | * Compare two saved colors to check if match. |
97 | | * This routine used to be a simple memcmp(), but |
98 | | * that is insufficient, the checks must be explicit. |
99 | | */ |
100 | | bool gx_hld_saved_color_equal(const gx_hl_saved_color * psc1, |
101 | | const gx_hl_saved_color * psc2) |
102 | 0 | { |
103 | |
|
104 | 0 | int i; |
105 | |
|
106 | 0 | if (psc1->saved_dev_color.type != psc2->saved_dev_color.type |
107 | 0 | || psc1->color_space_id != psc2->color_space_id |
108 | 0 | || psc1->pattern_id != psc2->pattern_id |
109 | 0 | || psc1->ccolor_valid != psc2->ccolor_valid |
110 | 0 | || psc1->ccolor.pattern != psc2->ccolor.pattern |
111 | 0 | || psc1->saved_dev_color.phase.x != psc2->saved_dev_color.phase.x |
112 | 0 | || psc1->saved_dev_color.phase.y != psc2->saved_dev_color.phase.y) { |
113 | |
|
114 | 0 | return(false); |
115 | 0 | } |
116 | | |
117 | | /* early bailout for pattern comparison */ |
118 | 0 | if (gx_dc_is_pattern1_color((gx_device_color *)(&psc1->saved_dev_color.type))) { |
119 | |
|
120 | 0 | if (psc1->saved_dev_color.colors.pattern.id != psc2->saved_dev_color.colors.pattern.id |
121 | 0 | || psc1->saved_dev_color.colors.pattern.phase.x != psc2->saved_dev_color.colors.pattern.phase.x |
122 | 0 | || psc1->saved_dev_color.colors.pattern.phase.y != psc2->saved_dev_color.colors.pattern.phase.y) |
123 | 0 | return(false); |
124 | 0 | else |
125 | 0 | return true; |
126 | 0 | } |
127 | 0 | if (gx_dc_is_pattern2_color((gx_device_color *)(&psc1->saved_dev_color.type))) { |
128 | 0 | if (psc1->saved_dev_color.colors.pattern2.id != psc2->saved_dev_color.colors.pattern2.id |
129 | 0 | || psc1->saved_dev_color.colors.pattern2.shfill != psc2->saved_dev_color.colors.pattern2.shfill) |
130 | 0 | return(false); |
131 | 0 | else |
132 | 0 | return true; |
133 | 0 | } |
134 | | |
135 | 0 | for (i = 0; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) { |
136 | 0 | if (psc1->ccolor.paint.values[i] != psc2->ccolor.paint.values[i]) { |
137 | 0 | return(false); |
138 | 0 | } |
139 | 0 | } |
140 | | /* NAFF: only gx_dc_pure_masked doesn't have a type checker */ |
141 | 0 | if (gx_dc_is_pure(&psc1->saved_dev_color) || psc1->saved_dev_color.type == &gx_dc_pure_masked) { |
142 | 0 | if (psc1->saved_dev_color.colors.pure != psc2->saved_dev_color.colors.pure) { |
143 | 0 | return(false); |
144 | 0 | } |
145 | 0 | } |
146 | 0 | else if (gx_dc_is_binary_halftone(&psc1->saved_dev_color)) { |
147 | |
|
148 | 0 | if ((psc1->saved_dev_color.colors.binary.b_color[0] != psc2->saved_dev_color.colors.binary.b_color[0]) |
149 | 0 | || (psc1->saved_dev_color.colors.binary.b_color[1] != psc2->saved_dev_color.colors.binary.b_color[1]) |
150 | 0 | || (psc1->saved_dev_color.colors.binary.b_level != psc2->saved_dev_color.colors.binary.b_level) |
151 | 0 | || (psc1->saved_dev_color.colors.binary.b_index != psc2->saved_dev_color.colors.binary.b_index)) { |
152 | |
|
153 | 0 | return(false); |
154 | 0 | } |
155 | 0 | } |
156 | 0 | else if (gx_dc_is_colored_halftone(&psc1->saved_dev_color)) { |
157 | |
|
158 | 0 | for (i = 0; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) { |
159 | 0 | if (psc1->saved_dev_color.colors.colored.c_base[i] != psc2->saved_dev_color.colors.colored.c_base[i] |
160 | 0 | || psc1->saved_dev_color.colors.colored.c_level[i] != psc2->saved_dev_color.colors.colored.c_level[i]) { |
161 | |
|
162 | 0 | return(false); |
163 | 0 | } |
164 | 0 | } |
165 | 0 | } |
166 | 0 | else if (gx_dc_is_devn(&psc1->saved_dev_color)) { |
167 | |
|
168 | 0 | for (i = 0; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) { |
169 | 0 | if (psc1->saved_dev_color.colors.devn.values[i] != psc2->saved_dev_color.colors.devn.values[i]) { |
170 | |
|
171 | 0 | return(false); |
172 | 0 | } |
173 | 0 | } |
174 | 0 | } |
175 | | |
176 | 0 | return (true); |
177 | 0 | } |
178 | | |
179 | | /* |
180 | | * Check whether two saved colors have same color space. |
181 | | */ |
182 | | bool gx_hld_saved_color_same_cspace(const gx_hl_saved_color * psc1, |
183 | | const gx_hl_saved_color * psc2) |
184 | 0 | { |
185 | 0 | if (psc1->color_space_id != psc2->color_space_id) |
186 | 0 | return false; |
187 | 0 | if (psc1->pattern_id != psc2->pattern_id) |
188 | 0 | return false; |
189 | 0 | if (psc1->ccolor_valid != psc2->ccolor_valid) |
190 | 0 | return false; |
191 | 0 | if (psc1->color_space_id != psc2->color_space_id) |
192 | 0 | return false; |
193 | 0 | return true; |
194 | 0 | } |
195 | | |
196 | | /* |
197 | | * Check if a high level color is availavble. |
198 | | */ |
199 | | bool |
200 | | gx_hld_is_hl_color_available(const gs_gstate * pgs, |
201 | | const gx_device_color * pdevc) |
202 | 0 | { |
203 | 0 | if (pgs != NULL && pdevc != NULL && pdevc->type != gx_dc_type_null && pdevc->ccolor_valid) |
204 | 0 | return true; |
205 | 0 | return false; |
206 | 0 | } |
207 | | |
208 | | /* |
209 | | * Get pointers to the current color space and client color. |
210 | | * |
211 | | * More description in src/gxhldevc.h |
212 | | */ |
213 | | gx_hld_get_color_space_and_ccolor_status |
214 | | gx_hld_get_color_space_and_ccolor(const gs_gstate * pgs, |
215 | | const gx_device_color * pdevc, const gs_color_space ** ppcs, |
216 | | const gs_client_color ** ppcc) |
217 | 0 | { |
218 | | /* Check if the current color space was used to build the device color */ |
219 | 0 | if (gx_hld_is_hl_color_available(pgs, pdevc)) { |
220 | 0 | const gs_color_space * pcs = gs_currentcolorspace_inline(pgs); |
221 | |
|
222 | 0 | *ppcs = pcs; |
223 | 0 | *ppcc = &(pdevc->ccolor); |
224 | 0 | if (pdevc->type == gx_dc_type_pattern |
225 | 0 | || pdevc->type == &gx_dc_pure_masked |
226 | 0 | || pdevc->type == gx_dc_type_pattern2) |
227 | 0 | return pattern_color_space; |
228 | 0 | else { |
229 | 0 | return non_pattern_color_space; |
230 | 0 | } |
231 | 0 | } |
232 | | /* No color space */ |
233 | 0 | *ppcs = NULL; |
234 | 0 | *ppcc = NULL; |
235 | 0 | return use_process_color; |
236 | 0 | } |
237 | | |
238 | | /* |
239 | | * Get the number of components in the current color space. |
240 | | * |
241 | | * More description in src/gxhldevc.h |
242 | | */ |
243 | | int |
244 | | gx_hld_get_number_color_components(const gs_gstate * pgs) |
245 | 0 | { |
246 | 0 | if (pgs != NULL) { |
247 | 0 | const gs_color_space * pcs = gs_currentcolorspace_inline(pgs); |
248 | 0 | int n = gs_color_space_num_components(pcs); |
249 | |
|
250 | 0 | return (n >= 0 ? n : -n - 1); |
251 | 0 | } else |
252 | 0 | return -1; |
253 | 0 | } |
254 | | |
255 | | /* |
256 | | * Get the requested high level color value. |
257 | | * |
258 | | * More description in src/gxhldevc.h |
259 | | */ |
260 | | gx_hld_get_color_component_status |
261 | | gx_hld_get_color_component(const gs_gstate * pgs, |
262 | | const gx_device_color * pdevc, |
263 | | int comp_num, float * output) |
264 | 0 | { |
265 | 0 | if (pdevc != NULL && pdevc->ccolor_valid) { |
266 | 0 | int ncomp = gx_hld_get_number_color_components(pgs); |
267 | |
|
268 | 0 | if (ncomp < 0) |
269 | 0 | return invalid_color_info; |
270 | 0 | if (comp_num < 0 || comp_num >= ncomp) |
271 | 0 | return invalid_component_requested; |
272 | 0 | *output = pdevc->ccolor.paint.values[comp_num]; |
273 | 0 | return valid_result; |
274 | 0 | } |
275 | 0 | return invalid_color_info; |
276 | 0 | } |