/src/ghostpdl/base/gxhldevc.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2023 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., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, 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 | 170k | { |
37 | 170k | gx_device_color temp_devc; |
38 | | |
39 | 170k | memset(psc, 0, sizeof(*psc)); /* clear the entire structure */ |
40 | 170k | psc->color_space_id = psc->pattern_id = gs_no_id; |
41 | 170k | color_set_null(&temp_devc); |
42 | 170k | temp_devc.type->save_dc(&temp_devc, &(psc->saved_dev_color)); |
43 | 170k | } |
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 | 88.9M | { |
55 | 88.9M | memset(psc, 0, sizeof(*psc)); /* clear the entire structure */ |
56 | | |
57 | 88.9M | if (pdevc == NULL) { |
58 | | /* No device color given, should not happen */ |
59 | 280 | gx_hld_saved_color_init(psc); /* revert to unknown color */ |
60 | 280 | return false; |
61 | 88.9M | } else if (pgs == NULL) { |
62 | | /* No color space, simply save device color specific info */ |
63 | 76.0M | psc->color_space_id = psc->pattern_id = gs_no_id; |
64 | 76.0M | pdevc->type->save_dc(pdevc, &(psc->saved_dev_color)); |
65 | 76.0M | return false; |
66 | 76.0M | } 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 | 12.9M | const gs_color_space * pcs = gs_currentcolorspace_inline(pgs); |
74 | 12.9M | int i = gs_color_space_num_components(pcs); |
75 | | |
76 | 12.9M | psc->color_space_id = pcs->id; |
77 | 12.9M | pdevc->type->save_dc(pdevc, &(psc->saved_dev_color)); |
78 | 12.9M | if (pdevc->type == gx_dc_type_pattern2) |
79 | 25.6k | i = 0; |
80 | 12.9M | else if (i < 0) |
81 | 34.0k | i = -i - 1; /* See gx_num_components_Pattern. */ |
82 | 33.8M | for (i--; i >= 0; i--) |
83 | 20.8M | psc->ccolor.paint.values[i] = pdevc->ccolor.paint.values[i]; |
84 | | |
85 | | /* Save the pattern id - if present */ |
86 | 12.9M | if ((pdevc->type == gx_dc_type_pattern |
87 | 12.9M | || pdevc->type == gx_dc_type_pattern2) && pdevc->ccolor_valid) |
88 | 37.6k | psc->pattern_id = pdevc->ccolor.pattern->pattern_id; |
89 | 12.9M | else |
90 | 12.9M | psc->pattern_id = gs_no_id; |
91 | 12.9M | return true; |
92 | 12.9M | } |
93 | 88.9M | } |
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 | 88.6M | { |
103 | | |
104 | 88.6M | int i; |
105 | | |
106 | 88.6M | if (psc1->saved_dev_color.type != psc2->saved_dev_color.type |
107 | 88.6M | || psc1->color_space_id != psc2->color_space_id |
108 | 88.6M | || psc1->pattern_id != psc2->pattern_id |
109 | 88.6M | || psc1->ccolor_valid != psc2->ccolor_valid |
110 | 88.6M | || psc1->ccolor.pattern != psc2->ccolor.pattern |
111 | 88.6M | || psc1->saved_dev_color.phase.x != psc2->saved_dev_color.phase.x |
112 | 88.6M | || psc1->saved_dev_color.phase.y != psc2->saved_dev_color.phase.y) { |
113 | | |
114 | 981k | return(false); |
115 | 981k | } |
116 | | |
117 | | /* early bailout for pattern comparison */ |
118 | 87.6M | if (gx_dc_is_pattern1_color((gx_device_color *)(&psc1->saved_dev_color.type))) { |
119 | | |
120 | 140 | if (psc1->saved_dev_color.colors.pattern.id != psc2->saved_dev_color.colors.pattern.id) |
121 | 0 | return(false); |
122 | 140 | else |
123 | 140 | return true; |
124 | 140 | } |
125 | 87.6M | if (gx_dc_is_pattern2_color((gx_device_color *)(&psc1->saved_dev_color.type))) { |
126 | 0 | if (psc1->saved_dev_color.colors.pattern2.id != psc2->saved_dev_color.colors.pattern2.id |
127 | 0 | || psc1->saved_dev_color.colors.pattern2.shfill != psc2->saved_dev_color.colors.pattern2.shfill) |
128 | 0 | return(false); |
129 | 0 | else |
130 | 0 | return true; |
131 | 0 | } |
132 | | |
133 | 5.61G | for (i = 0; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) { |
134 | 5.52G | if (psc1->ccolor.paint.values[i] != psc2->ccolor.paint.values[i]) { |
135 | 1.33M | return(false); |
136 | 1.33M | } |
137 | 5.52G | } |
138 | | /* NAFF: only gx_dc_pure_masked doesn't have a type checker */ |
139 | 86.3M | if (gx_dc_is_pure(&psc1->saved_dev_color) || psc1->saved_dev_color.type == &gx_dc_pure_masked) { |
140 | 86.2M | if (psc1->saved_dev_color.colors.pure != psc2->saved_dev_color.colors.pure) { |
141 | 33.4M | return(false); |
142 | 33.4M | } |
143 | 86.2M | } |
144 | 93.9k | else if (gx_dc_is_binary_halftone(&psc1->saved_dev_color)) { |
145 | |
|
146 | 0 | if ((psc1->saved_dev_color.colors.binary.b_color[0] != psc2->saved_dev_color.colors.binary.b_color[0]) |
147 | 0 | || (psc1->saved_dev_color.colors.binary.b_color[1] != psc2->saved_dev_color.colors.binary.b_color[1]) |
148 | 0 | || (psc1->saved_dev_color.colors.binary.b_level != psc2->saved_dev_color.colors.binary.b_level) |
149 | 0 | || (psc1->saved_dev_color.colors.binary.b_index != psc2->saved_dev_color.colors.binary.b_index)) { |
150 | |
|
151 | 0 | return(false); |
152 | 0 | } |
153 | 0 | } |
154 | 93.9k | else if (gx_dc_is_colored_halftone(&psc1->saved_dev_color)) { |
155 | |
|
156 | 0 | for (i = 0; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) { |
157 | 0 | if (psc1->saved_dev_color.colors.colored.c_base[i] != psc2->saved_dev_color.colors.colored.c_base[i] |
158 | 0 | || psc1->saved_dev_color.colors.colored.c_level[i] != psc2->saved_dev_color.colors.colored.c_level[i]) { |
159 | |
|
160 | 0 | return(false); |
161 | 0 | } |
162 | 0 | } |
163 | 0 | } |
164 | 93.9k | else if (gx_dc_is_devn(&psc1->saved_dev_color)) { |
165 | |
|
166 | 0 | for (i = 0; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) { |
167 | 0 | if (psc1->saved_dev_color.colors.devn.values[i] != psc2->saved_dev_color.colors.devn.values[i]) { |
168 | |
|
169 | 0 | return(false); |
170 | 0 | } |
171 | 0 | } |
172 | 0 | } |
173 | | |
174 | 52.8M | return (true); |
175 | 86.3M | } |
176 | | |
177 | | /* |
178 | | * Check whether two saved colors have same color space. |
179 | | */ |
180 | | bool gx_hld_saved_color_same_cspace(const gx_hl_saved_color * psc1, |
181 | | const gx_hl_saved_color * psc2) |
182 | 36.9k | { |
183 | 36.9k | if (psc1->color_space_id != psc2->color_space_id) |
184 | 26.0k | return false; |
185 | 10.9k | if (psc1->pattern_id != psc2->pattern_id) |
186 | 0 | return false; |
187 | 10.9k | if (psc1->ccolor_valid != psc2->ccolor_valid) |
188 | 0 | return false; |
189 | 10.9k | if (psc1->color_space_id != psc2->color_space_id) |
190 | 0 | return false; |
191 | 10.9k | return true; |
192 | 10.9k | } |
193 | | |
194 | | /* |
195 | | * Check if a high level color is availavble. |
196 | | */ |
197 | | bool |
198 | | gx_hld_is_hl_color_available(const gs_gstate * pgs, |
199 | | const gx_device_color * pdevc) |
200 | 5.69M | { |
201 | 5.69M | if (pgs != NULL && pdevc != NULL && pdevc->type != gx_dc_type_null && pdevc->ccolor_valid) |
202 | 1.95M | return true; |
203 | 3.73M | return false; |
204 | 5.69M | } |
205 | | |
206 | | /* |
207 | | * Get pointers to the current color space and client color. |
208 | | * |
209 | | * More description in src/gxhldevc.h |
210 | | */ |
211 | | gx_hld_get_color_space_and_ccolor_status |
212 | | gx_hld_get_color_space_and_ccolor(const gs_gstate * pgs, |
213 | | const gx_device_color * pdevc, const gs_color_space ** ppcs, |
214 | | const gs_client_color ** ppcc) |
215 | 2.66M | { |
216 | | /* Check if the current color space was used to build the device color */ |
217 | 2.66M | if (gx_hld_is_hl_color_available(pgs, pdevc)) { |
218 | 1.89M | const gs_color_space * pcs = gs_currentcolorspace_inline(pgs); |
219 | | |
220 | 1.89M | *ppcs = pcs; |
221 | 1.89M | *ppcc = &(pdevc->ccolor); |
222 | 1.89M | if (pdevc->type == gx_dc_type_pattern |
223 | 1.89M | || pdevc->type == &gx_dc_pure_masked |
224 | 1.89M | || pdevc->type == gx_dc_type_pattern2) |
225 | 18.8k | return pattern_color_space; |
226 | 1.87M | else { |
227 | 1.87M | return non_pattern_color_space; |
228 | 1.87M | } |
229 | 1.89M | } |
230 | | /* No color space */ |
231 | 768k | *ppcs = NULL; |
232 | 768k | *ppcc = NULL; |
233 | 768k | return use_process_color; |
234 | 2.66M | } |
235 | | |
236 | | /* |
237 | | * Get the number of components in the current color space. |
238 | | * |
239 | | * More description in src/gxhldevc.h |
240 | | */ |
241 | | int |
242 | | gx_hld_get_number_color_components(const gs_gstate * pgs) |
243 | 828k | { |
244 | 828k | if (pgs != NULL) { |
245 | 828k | const gs_color_space * pcs = gs_currentcolorspace_inline(pgs); |
246 | 828k | int n = gs_color_space_num_components(pcs); |
247 | | |
248 | 828k | return (n >= 0 ? n : -n - 1); |
249 | 828k | } else |
250 | 0 | return -1; |
251 | 828k | } |
252 | | |
253 | | /* |
254 | | * Get the requested high level color value. |
255 | | * |
256 | | * More description in src/gxhldevc.h |
257 | | */ |
258 | | gx_hld_get_color_component_status |
259 | | gx_hld_get_color_component(const gs_gstate * pgs, |
260 | | const gx_device_color * pdevc, |
261 | | int comp_num, float * output) |
262 | 0 | { |
263 | 0 | if (pdevc != NULL && pdevc->ccolor_valid) { |
264 | 0 | int ncomp = gx_hld_get_number_color_components(pgs); |
265 | |
|
266 | 0 | if (ncomp < 0) |
267 | 0 | return invalid_color_info; |
268 | 0 | if (comp_num < 0 || comp_num >= ncomp) |
269 | 0 | return invalid_component_requested; |
270 | 0 | *output = pdevc->ccolor.paint.values[comp_num]; |
271 | 0 | return valid_result; |
272 | 0 | } |
273 | 0 | return invalid_color_info; |
274 | 0 | } |