/src/ghostpdl/base/gsicc_monitorcm.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 | | /* gsicc handling for monitoring colors. Used for detecting gray only pages */ |
17 | | |
18 | | |
19 | | #include <stdlib.h> /* abs() */ |
20 | | |
21 | | #include "std.h" |
22 | | #include "stdpre.h" |
23 | | #include "gstypes.h" |
24 | | #include "gsmemory.h" |
25 | | #include "gxdevcli.h" |
26 | | #include "gxcspace.h" |
27 | | #include "gsicc_cms.h" |
28 | | #include "gsicc_cache.h" |
29 | | #include "gxcvalue.h" |
30 | | #include "gxdevsop.h" |
31 | | #include "gdevp14.h" |
32 | | #include "string_.h" |
33 | | |
34 | | static int gsicc_mcm_transform_general(gx_device *dev, gsicc_link_t *icclink, |
35 | | void *inputcolor, void *outputcolor, |
36 | | int num_bytes_in, int num_bytes_out); |
37 | | |
38 | | /* Functions that should be optimized later to do planar/chunky with |
39 | | color conversions. Just putting in something that should work |
40 | | right now */ |
41 | | static int |
42 | | gsicc_mcm_planar_to_planar(gx_device *dev, gsicc_link_t *icclink, |
43 | | gsicc_bufferdesc_t *input_buff_desc, |
44 | | gsicc_bufferdesc_t *output_buff_desc, |
45 | | void *inputbuffer, void *outputbuffer) |
46 | 0 | { |
47 | 0 | int k, j; |
48 | 0 | byte *inputpos[4]; |
49 | 0 | byte *outputpos[4]; |
50 | 0 | byte *in_buffer_ptr = (byte *) inputbuffer; |
51 | 0 | byte *out_buffer_ptr = (byte *) outputbuffer; |
52 | 0 | byte in_color[4], out_color[4]; |
53 | 0 | int code; |
54 | |
|
55 | 0 | for (k = 0; k < input_buff_desc->num_chan; k++) { |
56 | 0 | inputpos[k] = in_buffer_ptr + k * input_buff_desc->plane_stride; |
57 | 0 | } |
58 | 0 | for (k = 0; k < output_buff_desc->num_chan; k++) { |
59 | 0 | outputpos[k] = out_buffer_ptr + k * output_buff_desc->plane_stride; |
60 | 0 | } |
61 | | /* Note to self. We currently only do this in the transparency buffer |
62 | | case which has byte representation so just stepping through |
63 | | plane_stride is ok at this time. */ |
64 | 0 | for (k = 0; k < input_buff_desc->plane_stride ; k++) { |
65 | 0 | for (j = 0; j < input_buff_desc->num_chan; j++) { |
66 | 0 | in_color[j] = *(inputpos[j]); |
67 | 0 | inputpos[j] += input_buff_desc->bytes_per_chan; |
68 | 0 | } |
69 | 0 | code = gsicc_mcm_transform_general(dev, icclink, |
70 | 0 | (void*) &(in_color[0]), |
71 | 0 | (void*) &(out_color[0]), 1, 1); |
72 | 0 | if (code < 0) |
73 | 0 | return code; |
74 | 0 | for (j = 0; j < output_buff_desc->num_chan; j++) { |
75 | 0 | *(outputpos[j]) = out_color[j]; |
76 | 0 | outputpos[j] += output_buff_desc->bytes_per_chan; |
77 | 0 | } |
78 | 0 | } |
79 | 0 | return 0; |
80 | 0 | } |
81 | | |
82 | | /* This is not really used yet */ |
83 | | static int |
84 | | gsicc_mcm_planar_to_chunky(gx_device *dev, gsicc_link_t *icclink, |
85 | | gsicc_bufferdesc_t *input_buff_desc, |
86 | | gsicc_bufferdesc_t *output_buff_desc, |
87 | | void *inputbuffer, void *outputbuffer) |
88 | 0 | { |
89 | 0 | return 0; |
90 | 0 | } |
91 | | |
92 | | /* This is used with the fast thresholding code when doing -dUseFastColor |
93 | | and going out to a planar device */ |
94 | | static int |
95 | | gsicc_mcm_chunky_to_planar(gx_device *dev, gsicc_link_t *icclink, |
96 | | gsicc_bufferdesc_t *input_buff_desc, |
97 | | gsicc_bufferdesc_t *output_buff_desc, |
98 | | void *inputbuffer, void *outputbuffer) |
99 | 0 | { |
100 | 0 | int k, j, m; |
101 | 0 | byte *inputpos = (byte *) inputbuffer; |
102 | 0 | byte *outputpos = (byte *) outputbuffer; |
103 | 0 | byte *output_loc; |
104 | 0 | byte *inputcolor; |
105 | 0 | byte outputcolor[8]; /* 8 since we have max 4 colorants and 2 bytes/colorant */ |
106 | 0 | unsigned short *pos_in_short, *pos_out_short; |
107 | 0 | int num_bytes_in = input_buff_desc->bytes_per_chan; |
108 | 0 | int num_bytes_out = output_buff_desc->bytes_per_chan; |
109 | 0 | int pixel_in_step = num_bytes_in * input_buff_desc->num_chan; |
110 | 0 | int plane_stride = output_buff_desc->plane_stride; |
111 | 0 | int code; |
112 | | |
113 | | /* Do row by row. */ |
114 | 0 | for (k = 0; k < input_buff_desc->num_rows ; k++) { |
115 | 0 | inputcolor = inputpos; |
116 | 0 | output_loc = outputpos; |
117 | | |
118 | | /* split the 2 byte 1 byte case here to avoid decision in inner loop */ |
119 | 0 | if (output_buff_desc->bytes_per_chan == 1) { |
120 | 0 | for (j = 0; j < input_buff_desc->pixels_per_row; j++) { |
121 | 0 | code = gsicc_mcm_transform_general(dev, icclink, |
122 | 0 | (void*) inputcolor, |
123 | 0 | (void*) &(outputcolor[0]), |
124 | 0 | num_bytes_in, |
125 | 0 | num_bytes_out); |
126 | 0 | if (code < 0) |
127 | 0 | return code; |
128 | | /* Stuff the output in the proper planar location */ |
129 | 0 | for (m = 0; m < output_buff_desc->num_chan; m++) { |
130 | 0 | *(output_loc + m * plane_stride + j) = outputcolor[m]; |
131 | 0 | } |
132 | 0 | inputcolor += pixel_in_step; |
133 | 0 | } |
134 | 0 | inputpos += input_buff_desc->row_stride; |
135 | 0 | outputpos += output_buff_desc->row_stride; |
136 | 0 | } else { |
137 | 0 | for (j = 0; j < input_buff_desc->pixels_per_row; j++) { |
138 | 0 | code = gsicc_mcm_transform_general(dev, icclink, |
139 | 0 | (void*) inputcolor, |
140 | 0 | (void*) &(outputcolor[0]), |
141 | 0 | num_bytes_in, |
142 | 0 | num_bytes_out); |
143 | 0 | if (code < 0) |
144 | 0 | return code; |
145 | | /* Stuff the output in the proper planar location */ |
146 | 0 | pos_in_short = (unsigned short*) &(outputcolor[0]); |
147 | 0 | pos_out_short = (unsigned short*) (output_loc); |
148 | 0 | for (m = 0; m < output_buff_desc->num_chan; m++) { |
149 | 0 | *(pos_out_short + m * plane_stride + j) = pos_in_short[m]; |
150 | 0 | } |
151 | 0 | inputcolor += pixel_in_step; |
152 | 0 | } |
153 | 0 | inputpos += input_buff_desc->row_stride; |
154 | 0 | outputpos += output_buff_desc->row_stride; |
155 | 0 | } |
156 | 0 | } |
157 | 0 | return 0; |
158 | 0 | } |
159 | | |
160 | | static int |
161 | | gsicc_mcm_chunky_to_chunky(gx_device *dev, gsicc_link_t *icclink, |
162 | | gsicc_bufferdesc_t *input_buff_desc, |
163 | | gsicc_bufferdesc_t *output_buff_desc, |
164 | | void *inputbuffer, void *outputbuffer) |
165 | 0 | { |
166 | 0 | int k, j; |
167 | 0 | byte *inputpos = (byte *) inputbuffer; |
168 | 0 | byte *outputpos = (byte *) outputbuffer; |
169 | 0 | byte *inputcolor, *outputcolor; |
170 | 0 | int num_bytes_in = input_buff_desc->bytes_per_chan; |
171 | 0 | int num_bytes_out = output_buff_desc->bytes_per_chan; |
172 | 0 | int pixel_in_step = num_bytes_in * input_buff_desc->num_chan; |
173 | 0 | int pixel_out_step = num_bytes_out * output_buff_desc->num_chan; |
174 | 0 | int code; |
175 | | |
176 | | /* Do row by row. */ |
177 | 0 | for (k = 0; k < input_buff_desc->num_rows ; k++) { |
178 | 0 | inputcolor = inputpos; |
179 | 0 | outputcolor = outputpos; |
180 | 0 | for (j = 0; j < input_buff_desc->pixels_per_row; j++) { |
181 | 0 | code = gsicc_mcm_transform_general(dev, icclink, |
182 | 0 | (void*) inputcolor, |
183 | 0 | (void*) outputcolor, |
184 | 0 | num_bytes_in, |
185 | 0 | num_bytes_out); |
186 | 0 | if (code < 0) |
187 | 0 | return code; |
188 | 0 | inputcolor += pixel_in_step; |
189 | 0 | outputcolor += pixel_out_step; |
190 | 0 | } |
191 | 0 | inputpos += input_buff_desc->row_stride; |
192 | 0 | outputpos += output_buff_desc->row_stride; |
193 | 0 | } |
194 | 0 | return 0; |
195 | 0 | } |
196 | | |
197 | | /* Transform an entire buffer monitoring and transforming the colors */ |
198 | | static int |
199 | | gsicc_mcm_transform_color_buffer(gx_device *dev, gsicc_link_t *icclink, |
200 | | gsicc_bufferdesc_t *input_buff_desc, |
201 | | gsicc_bufferdesc_t *output_buff_desc, |
202 | | void *inputbuffer, void *outputbuffer) |
203 | 0 | { |
204 | 0 | if (input_buff_desc->is_planar) { |
205 | 0 | if (output_buff_desc->is_planar) { |
206 | 0 | return gsicc_mcm_planar_to_planar(dev, icclink, input_buff_desc, |
207 | 0 | output_buff_desc, inputbuffer, |
208 | 0 | outputbuffer); |
209 | 0 | } else { |
210 | 0 | return gsicc_mcm_planar_to_chunky(dev, icclink, input_buff_desc, |
211 | 0 | output_buff_desc, inputbuffer, |
212 | 0 | outputbuffer); |
213 | 0 | } |
214 | 0 | } else { |
215 | 0 | if (output_buff_desc->is_planar) { |
216 | 0 | return gsicc_mcm_chunky_to_planar(dev, icclink, input_buff_desc, |
217 | 0 | output_buff_desc, inputbuffer, |
218 | 0 | outputbuffer); |
219 | 0 | } else { |
220 | 0 | return gsicc_mcm_chunky_to_chunky(dev, icclink, input_buff_desc, |
221 | 0 | output_buff_desc, inputbuffer, |
222 | 0 | outputbuffer); |
223 | 0 | } |
224 | 0 | } |
225 | 0 | } |
226 | | |
227 | | /* This is where we do the monitoring and the conversion if needed */ |
228 | | static int |
229 | | gsicc_mcm_transform_general(gx_device *dev, gsicc_link_t *icclink, |
230 | | void *inputcolor, void *outputcolor, |
231 | | int num_bytes_in, int num_bytes_out) |
232 | 0 | { |
233 | 0 | bool is_neutral = false; |
234 | 0 | unsigned short outputcolor_cm[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
235 | 0 | void *outputcolor_cm_ptr = (void*) outputcolor_cm; |
236 | 0 | cmm_dev_profile_t *dev_profile; |
237 | 0 | int code; |
238 | 0 | int k; |
239 | |
|
240 | 0 | code = dev_proc(dev, get_profile)(dev, &dev_profile); |
241 | 0 | if (code < 0) |
242 | 0 | return code; |
243 | | |
244 | | /* Monitor only if gray detection is still true */ |
245 | 0 | if (dev_profile->pageneutralcolor) |
246 | 0 | is_neutral = icclink->procs.is_color(inputcolor, num_bytes_in); |
247 | | |
248 | | /* Color found turn off gray detection */ |
249 | 0 | if (!is_neutral) |
250 | 0 | dev_profile->pageneutralcolor = false; |
251 | | |
252 | | /* Reset all links so that they will no longer monitor. This one will finish |
253 | | the buffer but we will not have any additional ones */ |
254 | 0 | if (!dev_profile->pageneutralcolor) |
255 | 0 | { |
256 | 0 | code = gsicc_mcm_end_monitor(icclink->icc_link_cache, dev); |
257 | 0 | if (code < 0) |
258 | 0 | return code; |
259 | 0 | } |
260 | | |
261 | | /* Now apply the color transform using the original color procs, but don't |
262 | | do this if we had the identity. We also have to worry about 8 and 16 bit |
263 | | depth */ |
264 | 0 | if (icclink->hashcode.des_hash == icclink->hashcode.src_hash) { |
265 | 0 | if (num_bytes_in == num_bytes_out) { |
266 | | /* The easy case */ |
267 | 0 | memcpy(outputcolor, inputcolor, (size_t)num_bytes_in * icclink->num_input); |
268 | 0 | } else { |
269 | 0 | if (num_bytes_in == 2) { |
270 | 0 | unsigned short *in_ptr = (unsigned short*) inputcolor; |
271 | 0 | byte *out_ptr = (byte*) outputcolor; |
272 | 0 | for (k = 0; k < icclink->num_input; k++) { |
273 | 0 | out_ptr[k] = gx_color_value_to_byte(in_ptr[k]); |
274 | 0 | } |
275 | 0 | } else { |
276 | 0 | byte *in_ptr = (byte*) inputcolor; |
277 | 0 | unsigned short *out_ptr = (unsigned short*) outputcolor; |
278 | 0 | for (k = 0; k < icclink->num_input; k++) { |
279 | 0 | out_ptr[k] = gx_color_value_to_byte(in_ptr[k]); |
280 | 0 | } |
281 | 0 | } |
282 | 0 | } |
283 | 0 | } else { |
284 | 0 | if (num_bytes_in == num_bytes_out) { |
285 | 0 | icclink->orig_procs.map_color(dev, icclink, inputcolor, outputcolor, |
286 | 0 | num_bytes_in); |
287 | 0 | } else { |
288 | 0 | icclink->orig_procs.map_color(dev, icclink, inputcolor, outputcolor_cm_ptr, |
289 | 0 | num_bytes_in); |
290 | 0 | if (num_bytes_in == 2) { |
291 | 0 | unsigned short *in_ptr = (unsigned short*) outputcolor_cm_ptr; |
292 | 0 | byte *out_ptr = (byte*) outputcolor; |
293 | 0 | for (k = 0; k < icclink->num_input; k++) { |
294 | 0 | out_ptr[k] = gx_color_value_to_byte(in_ptr[k]); |
295 | 0 | } |
296 | 0 | } else { |
297 | 0 | byte *in_ptr = (byte*) outputcolor_cm_ptr; |
298 | 0 | unsigned short *out_ptr = (unsigned short*) outputcolor; |
299 | 0 | for (k = 0; k < icclink->num_input; k++) { |
300 | 0 | out_ptr[k] = gx_color_value_to_byte(in_ptr[k]); |
301 | 0 | } |
302 | 0 | } |
303 | 0 | } |
304 | 0 | } |
305 | 0 | return 0; |
306 | 0 | } |
307 | | |
308 | | /* Monitor for color */ |
309 | | static int |
310 | | gsicc_mcm_transform_color(gx_device *dev, gsicc_link_t *icclink, void *inputcolor, |
311 | | void *outputcolor, int num_bytes) |
312 | 0 | { |
313 | 0 | return gsicc_mcm_transform_general(dev, icclink, inputcolor, outputcolor, |
314 | 0 | num_bytes, num_bytes); |
315 | 0 | } |
316 | | |
317 | | bool gsicc_mcm_monitor_rgb(void *inputcolor, int num_bytes) |
318 | 0 | { |
319 | 0 | if (num_bytes == 1) { |
320 | 0 | byte *rgb_val = (byte*) inputcolor; |
321 | 0 | int rg_diff = (int) abs((int) rgb_val[0] - (int) rgb_val[1]); |
322 | 0 | int rb_diff = (int) abs((int) rgb_val[0] - (int) rgb_val[2]); |
323 | 0 | int bg_diff = (int) abs((int) rgb_val[1] - (int) rgb_val[2]); |
324 | 0 | return (rg_diff < DEV_NEUTRAL_8 && rb_diff < DEV_NEUTRAL_8 |
325 | 0 | && bg_diff < DEV_NEUTRAL_8); |
326 | 0 | } else { |
327 | 0 | unsigned short *rgb_val = (unsigned short*) inputcolor; |
328 | 0 | int rg_diff = (int) abs((int) rgb_val[0] - (int) rgb_val[1]); |
329 | 0 | int rb_diff = (int) abs((int) rgb_val[0] - (int) rgb_val[2]); |
330 | 0 | int bg_diff = (int) abs((int) rgb_val[1] - (int) rgb_val[2]); |
331 | 0 | return (rg_diff < DEV_NEUTRAL_16 && rb_diff < DEV_NEUTRAL_16 |
332 | 0 | && bg_diff < DEV_NEUTRAL_16); |
333 | 0 | } |
334 | 0 | } |
335 | | |
336 | | bool gsicc_mcm_monitor_cmyk(void *inputcolor, int num_bytes) |
337 | 0 | { |
338 | | #ifdef PESSIMISTIC_CMYK_NEUTRAL |
339 | | if (num_bytes == 1) { |
340 | | byte *cmyk = (byte*) inputcolor; |
341 | | return (cmyk[0] < DEV_NEUTRAL_8 && cmyk[1] < DEV_NEUTRAL_8 |
342 | | && cmyk[2] < DEV_NEUTRAL_8); |
343 | | } else { |
344 | | unsigned short *cmyk = (unsigned short*) inputcolor; |
345 | | return (cmyk[0] < DEV_NEUTRAL_16 && cmyk[1] < DEV_NEUTRAL_16 |
346 | | && cmyk[2] < DEV_NEUTRAL_16); |
347 | | } |
348 | | #else /* The code below is more similar to RGB in that C = M = Y (or close) */ |
349 | | /* will be treated as neutral. */ |
350 | 0 | if (num_bytes == 1) { |
351 | 0 | byte *cmyk = (byte*) inputcolor; |
352 | 0 | int cm_diff = (int) abs((int) cmyk[0] - (int) cmyk[1]); |
353 | 0 | int cy_diff = (int) abs((int) cmyk[0] - (int) cmyk[2]); |
354 | 0 | int my_diff = (int) abs((int) cmyk[1] - (int) cmyk[2]); |
355 | 0 | return (cm_diff < DEV_NEUTRAL_8 && cy_diff < DEV_NEUTRAL_8 |
356 | 0 | && my_diff < DEV_NEUTRAL_8); |
357 | 0 | } else { |
358 | 0 | unsigned short *cmyk = (unsigned short*) inputcolor; |
359 | 0 | int cm_diff = (int) abs((int) cmyk[0] - (int) cmyk[1]); |
360 | 0 | int cy_diff = (int) abs((int) cmyk[0] - (int) cmyk[2]); |
361 | 0 | int my_diff = (int) abs((int) cmyk[1] - (int) cmyk[2]); |
362 | 0 | return (cm_diff < DEV_NEUTRAL_16 && cy_diff < DEV_NEUTRAL_16 |
363 | 0 | && my_diff < DEV_NEUTRAL_16); |
364 | 0 | } |
365 | 0 | #endif |
366 | 0 | } |
367 | | |
368 | | bool gsicc_mcm_monitor_lab(void *inputcolor, int num_bytes) |
369 | 0 | { |
370 | 0 | if (num_bytes == 1) { |
371 | 0 | byte *lab = (byte*) inputcolor; |
372 | 0 | int diffa = (int) abs((int) lab[1] - (int) 0x80); |
373 | 0 | int diffb = (int) abs((int) lab[2] - (int) 0x80); |
374 | 0 | return (diffa < AB_NEUTRAL_8 && diffb < AB_NEUTRAL_8); |
375 | 0 | } else { |
376 | 0 | unsigned short *lab = (unsigned short*) inputcolor; |
377 | 0 | int diffa = (int) abs((int) lab[1] - (int) 0x8000); |
378 | 0 | int diffb = (int) abs((int) lab[2] - (int) 0x8000); |
379 | 0 | return (diffa < AB_NEUTRAL_16 && diffb < AB_NEUTRAL_16); |
380 | 0 | } |
381 | 0 | } |
382 | | |
383 | | /* Set the link up to monitor */ |
384 | | void |
385 | | gsicc_mcm_set_link(gsicc_link_t* link) |
386 | 0 | { |
387 | 0 | link->orig_procs = link->procs; |
388 | 0 | link->is_monitored = true; |
389 | 0 | link->is_identity = false; |
390 | |
|
391 | 0 | link->procs.map_buffer = gsicc_mcm_transform_color_buffer; |
392 | 0 | link->procs.map_color = gsicc_mcm_transform_color; |
393 | |
|
394 | 0 | switch (link->data_cs) { |
395 | 0 | case gsRGB: |
396 | 0 | link->procs.is_color = gsicc_mcm_monitor_rgb; |
397 | 0 | break; |
398 | 0 | case gsCIELAB: |
399 | 0 | link->procs.is_color = gsicc_mcm_monitor_lab; |
400 | 0 | break; |
401 | 0 | case gsCMYK: |
402 | 0 | link->procs.is_color = gsicc_mcm_monitor_cmyk; |
403 | 0 | break; |
404 | 0 | default: |
405 | 0 | break; |
406 | 0 | } |
407 | 0 | } |
408 | | |
409 | | /* This gets rid of the monitoring */ |
410 | | int |
411 | | gsicc_mcm_end_monitor(gsicc_link_cache_t *cache, gx_device *dev) |
412 | 0 | { |
413 | 0 | gx_monitor_t *lock = cache->lock; |
414 | 0 | gsicc_link_t *curr; |
415 | 0 | int code; |
416 | 0 | cmm_dev_profile_t *dev_profile; |
417 | | |
418 | | |
419 | | /* Get the device profile */ |
420 | 0 | code = dev_proc(dev, get_profile)(dev, &dev_profile); |
421 | 0 | if (code < 0) |
422 | 0 | return code; |
423 | 0 | dev_profile->pageneutralcolor = false; |
424 | | /* If this device is a pdf14 device, then we may need to take care of the |
425 | | profile in the target device also. This is a special case since the |
426 | | pdf14 device has its own profile different from the target device */ |
427 | 0 | if (dev_proc(dev, dev_spec_op)(dev, gxdso_is_pdf14_device, NULL, 0) > 0) { |
428 | 0 | gs_pdf14_device_color_mon_set(dev, false); |
429 | 0 | } |
430 | | |
431 | | /* Lock the cache as we remove monitoring from the links */ |
432 | 0 | gx_monitor_enter(lock); |
433 | 0 | curr = cache->head; |
434 | 0 | while (curr != NULL ) { |
435 | 0 | if (curr->is_monitored) { |
436 | 0 | curr->procs = curr->orig_procs; |
437 | 0 | if (curr->hashcode.des_hash == curr->hashcode.src_hash) |
438 | 0 | curr->is_identity = true; |
439 | 0 | curr->is_monitored = false; |
440 | 0 | } |
441 | | /* Now release any tasks/threads waiting for these contents */ |
442 | 0 | gx_monitor_leave(curr->lock); |
443 | 0 | curr = curr->next; |
444 | 0 | } |
445 | 0 | gx_monitor_leave(lock); /* done with updating, let everyone run */ |
446 | 0 | return 0; |
447 | 0 | } |
448 | | |
449 | | /* Conversely to the above, this gets restores monitoring, needed after |
450 | | * monitoring was turned off above (for the next page) |
451 | | */ |
452 | | int |
453 | | gsicc_mcm_begin_monitor(gsicc_link_cache_t *cache, gx_device *dev) |
454 | 0 | { |
455 | 0 | gx_monitor_t *lock = cache->lock; |
456 | 0 | gsicc_link_t *curr; |
457 | 0 | int code; |
458 | 0 | cmm_dev_profile_t *dev_profile; |
459 | | |
460 | | /* Get the device profile */ |
461 | 0 | code = dev_proc(dev, get_profile)(dev, &dev_profile); |
462 | 0 | if (code < 0) |
463 | 0 | return code; |
464 | 0 | dev_profile->pageneutralcolor = true; |
465 | | /* If this device is a pdf14 device, then we may need to take care of the |
466 | | profile in the target device also. This is a special case since the |
467 | | pdf14 device has its own profile different from the target device */ |
468 | 0 | if (dev_proc(dev, dev_spec_op)(dev, gxdso_is_pdf14_device, NULL, 0) > 0) { |
469 | 0 | gs_pdf14_device_color_mon_set(dev, true); |
470 | 0 | } |
471 | | |
472 | | /* Lock the cache as we remove monitoring from the links */ |
473 | 0 | gx_monitor_enter(lock); |
474 | |
|
475 | 0 | curr = cache->head; |
476 | 0 | while (curr != NULL ) { |
477 | 0 | if (curr->data_cs != gsGRAY) { |
478 | 0 | gsicc_mcm_set_link(curr); |
479 | | /* Now release any tasks/threads waiting for these contents */ |
480 | 0 | gx_monitor_leave(curr->lock); |
481 | 0 | } |
482 | 0 | curr = curr->next; |
483 | 0 | } |
484 | 0 | gx_monitor_leave(lock); /* done with updating, let everyone run */ |
485 | 0 | return 0; |
486 | 0 | } |