/src/ghostpdl/base/gdevp14.c
Line | Count | Source |
1 | | /* Copyright (C) 2001-2026 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 | | /* Compositing devices for implementing PDF 1.4 imaging model */ |
17 | | |
18 | | #include "assert_.h" |
19 | | #include "math_.h" |
20 | | #include "memory_.h" |
21 | | #include "gx.h" |
22 | | #include "gserrors.h" |
23 | | #include "gscdefs.h" |
24 | | #include "gxdevice.h" |
25 | | #include "gsdevice.h" |
26 | | #include "gsstruct.h" |
27 | | #include "gxgstate.h" |
28 | | #include "gxdcolor.h" |
29 | | #include "gxiparam.h" |
30 | | #include "gstparam.h" |
31 | | #include "gxblend.h" |
32 | | #include "gxtext.h" |
33 | | #include "gsimage.h" |
34 | | #include "gsrect.h" |
35 | | #include "gscoord.h" |
36 | | #include "gzstate.h" |
37 | | #include "gdevdevn.h" |
38 | | #include "gdevmem.h" |
39 | | #include "gdevp14.h" |
40 | | #include "gdevprn.h" /* for prn_device structures */ |
41 | | #include "gdevppla.h" /* for gdev_prn_open_planar */ |
42 | | #include "gdevdevnprn.h" |
43 | | #include "gscdevn.h" |
44 | | #include "gsovrc.h" |
45 | | #include "gxcmap.h" |
46 | | #include "gscolor1.h" |
47 | | #include "gstrans.h" |
48 | | #include "gsutil.h" |
49 | | #include "gxcldev.h" |
50 | | #include "gxclpath.h" |
51 | | #include "gxdcconv.h" |
52 | | #include "gsptype2.h" |
53 | | #include "gxpcolor.h" |
54 | | #include "gsptype1.h" |
55 | | #include "gzcpath.h" |
56 | | #include "gxpaint.h" |
57 | | #include "gsicc_manage.h" |
58 | | #include "gsicc_cache.h" |
59 | | #include "gxclist.h" |
60 | | #include "gxiclass.h" |
61 | | #include "gximage.h" |
62 | | #include "gsmatrix.h" |
63 | | #include "gxdevsop.h" |
64 | | #include "gsicc.h" |
65 | | #ifdef WITH_CAL |
66 | | #include "cal.h" |
67 | | #define CAL_SLOP 16 |
68 | | #else |
69 | | #define CAL_SLOP 0 |
70 | | #endif |
71 | | #include "assert_.h" |
72 | | #include "gxgetbit.h" |
73 | | #include "gdevkrnlsclass.h" |
74 | | |
75 | | #if RAW_DUMP |
76 | | unsigned int global_index = 0; |
77 | | unsigned int clist_band_count = 0; |
78 | | #endif |
79 | | |
80 | | #define DUMP_MASK_STACK 0 |
81 | | |
82 | | /* Static prototypes */ |
83 | | /* Used for filling rects when we are doing a fill with a pattern that |
84 | | has transparency */ |
85 | | static int pdf14_tile_pattern_fill(gx_device * pdev, const gs_gstate * pgs, |
86 | | gx_path * ppath, const gx_fill_params * params, |
87 | | const gx_device_color * pdevc, const gx_clip_path * pcpath); |
88 | | static pdf14_mask_t *pdf14_mask_element_new(gs_memory_t *memory); |
89 | | static void pdf14_free_smask_color(pdf14_device * pdev); |
90 | | static int compute_group_device_int_rect(pdf14_device *pdev, gs_int_rect *rect, |
91 | | const gs_rect *pbbox, gs_gstate *pgs); |
92 | | static int pdf14_clist_update_params(pdf14_clist_device * pdev, |
93 | | const gs_gstate * pgs, |
94 | | bool crop_blend_params, |
95 | | gs_pdf14trans_params_t *group_params); |
96 | | static int pdf14_mark_fill_rectangle_ko_simple(gx_device * dev, int x, int y, |
97 | | int w, int h, gx_color_index color, |
98 | | const gx_device_color *pdc, |
99 | | bool devn); |
100 | | static int pdf14_copy_alpha_color(gx_device * dev, const byte * data, int data_x, |
101 | | int aa_raster, gx_bitmap_id id, int x, int y, int w, int h, |
102 | | gx_color_index color, const gx_device_color *pdc, |
103 | | int depth, bool devn); |
104 | | |
105 | | /* Functions for dealing with soft mask color */ |
106 | | static int pdf14_decrement_smask_color(gs_gstate * pgs, gx_device * dev); |
107 | | static int pdf14_increment_smask_color(gs_gstate * pgs, gx_device * dev); |
108 | | |
109 | | /* |
110 | | * We chose the blending color space based upon the process color model of the |
111 | | * output device. For gray, RGB, CMYK, or CMYK+spot devices, the choice is |
112 | | * usually simple. For other devices or if the user is doing custom color |
113 | | * processing then the user may want to control this choice. |
114 | | */ |
115 | | #define AUTO_USE_CUSTOM_BLENDING 0 |
116 | | #define ALWAYS_USE_CUSTOM_BLENDING 1 |
117 | | #define DO_NOT_USE_CUSTOM_BLENDING 2 |
118 | | |
119 | | #define CUSTOM_BLENDING_MODE AUTO_USE_CUSTOM_BLENDING |
120 | | |
121 | | # define INCR(v) DO_NOTHING |
122 | | |
123 | | /* Forward prototypes */ |
124 | | void pdf14_cmyk_cs_to_cmyk_cm(const gx_device *, frac, frac, frac, frac, frac *); |
125 | | static int gs_pdf14_device_push(gs_memory_t *mem, gs_gstate * pgs, |
126 | | gx_device ** pdev, gx_device * target, |
127 | | const gs_pdf14trans_t * pdf14pct); |
128 | | static int gs_pdf14_clist_device_push(gs_memory_t * mem, gs_gstate * pgs, |
129 | | gx_device ** pdev, gx_device * target, |
130 | | const gs_pdf14trans_t * pdf14pct); |
131 | | static int pdf14_tile_pattern_fill(gx_device * pdev, |
132 | | const gs_gstate * pgs, gx_path * ppath, |
133 | | const gx_fill_params * params, |
134 | | const gx_device_color * pdevc, const gx_clip_path * pcpath); |
135 | | #ifdef DEBUG |
136 | | static void pdf14_debug_mask_stack_state(pdf14_ctx *ctx); |
137 | | #endif |
138 | | |
139 | | /* A structure used by the pdf14 device so that |
140 | | we can do the proper dance when the alphabuf |
141 | | device is being used */ |
142 | | typedef struct pdf14_abuf_state_s { |
143 | | bool op_ca_eq_CA; |
144 | | bool path_empty; |
145 | | float stroke_alpha; |
146 | | float fill_alpha; |
147 | | gs_gstate* pgs; |
148 | | gs_blend_mode_t blend_mode; |
149 | | bool group_needed; |
150 | | OP_FS_STATE orig_state; |
151 | | } pdf14_abuf_state_t; |
152 | | |
153 | | /* Buffer stack data structure */ |
154 | | gs_private_st_ptrs7(st_pdf14_buf, pdf14_buf, "pdf14_buf", |
155 | | pdf14_buf_enum_ptrs, pdf14_buf_reloc_ptrs, |
156 | | saved, data, backdrop, transfer_fn, mask_stack, |
157 | | matte, group_color_info); |
158 | | |
159 | | gs_private_st_ptrs3(st_pdf14_ctx, pdf14_ctx, "pdf14_ctx", |
160 | | pdf14_ctx_enum_ptrs, pdf14_ctx_reloc_ptrs, |
161 | | stack, mask_stack, base_color); |
162 | | |
163 | | gs_private_st_ptrs1(st_pdf14_clr, pdf14_group_color_t, "pdf14_clr", |
164 | | pdf14_clr_enum_ptrs, pdf14_clr_reloc_ptrs, previous); |
165 | | |
166 | | gs_private_st_ptrs2(st_pdf14_mask, pdf14_mask_t, "pdf_mask", |
167 | | pdf14_mask_enum_ptrs, pdf14_mask_reloc_ptrs, |
168 | | mask_buf, previous); |
169 | | |
170 | | gs_private_st_ptrs1(st_pdf14_smaskcolor, pdf14_smaskcolor_t, "pdf14_smaskcolor", |
171 | | pdf14_smaskcolor_enum_ptrs, pdf14_smaskcolor_reloc_ptrs, |
172 | | profiles); |
173 | | |
174 | | /* ------ The device descriptors ------ */ |
175 | | |
176 | | /* |
177 | | * Default X and Y resolution. |
178 | | */ |
179 | | #define X_DPI 72 |
180 | | #define Y_DPI 72 |
181 | | |
182 | | static int pdf14_initialize_device(gx_device *dev); |
183 | | |
184 | | static int pdf14_open(gx_device * pdev); |
185 | | static dev_proc_close_device(pdf14_close); |
186 | | static int pdf14_output_page(gx_device * pdev, int num_copies, int flush); |
187 | | static dev_proc_put_params(pdf14_put_params); |
188 | | static dev_proc_get_color_comp_index(pdf14_cmykspot_get_color_comp_index); |
189 | | static dev_proc_get_color_comp_index(pdf14_rgbspot_get_color_comp_index); |
190 | | static dev_proc_get_color_comp_index(pdf14_grayspot_get_color_comp_index); |
191 | | static dev_proc_get_color_mapping_procs(pdf14_cmykspot_get_color_mapping_procs); |
192 | | static dev_proc_get_color_mapping_procs(pdf14_rgbspot_get_color_mapping_procs); |
193 | | static dev_proc_get_color_mapping_procs(pdf14_grayspot_get_color_mapping_procs); |
194 | | dev_proc_encode_color(pdf14_encode_color); |
195 | | dev_proc_encode_color(pdf14_encode_color_tag); |
196 | | dev_proc_decode_color(pdf14_decode_color); |
197 | | dev_proc_encode_color(pdf14_encode_color16); |
198 | | dev_proc_encode_color(pdf14_encode_color16_tag); |
199 | | dev_proc_decode_color(pdf14_decode_color16); |
200 | | static dev_proc_fill_rectangle(pdf14_fill_rectangle); |
201 | | static dev_proc_fill_rectangle_hl_color(pdf14_fill_rectangle_hl_color); |
202 | | static dev_proc_fill_path(pdf14_fill_path); |
203 | | static dev_proc_fill_stroke_path(pdf14_fill_stroke_path); |
204 | | static dev_proc_copy_mono(pdf14_copy_mono); |
205 | | static dev_proc_fill_mask(pdf14_fill_mask); |
206 | | static dev_proc_stroke_path(pdf14_stroke_path); |
207 | | static dev_proc_begin_typed_image(pdf14_begin_typed_image); |
208 | | static dev_proc_text_begin(pdf14_text_begin); |
209 | | static dev_proc_composite(pdf14_composite); |
210 | | static dev_proc_composite(pdf14_forward_composite); |
211 | | static dev_proc_begin_transparency_group(pdf14_begin_transparency_group); |
212 | | static dev_proc_end_transparency_group(pdf14_end_transparency_group); |
213 | | static dev_proc_begin_transparency_mask(pdf14_begin_transparency_mask); |
214 | | static dev_proc_end_transparency_mask(pdf14_end_transparency_mask); |
215 | | static dev_proc_dev_spec_op(pdf14_dev_spec_op); |
216 | | static dev_proc_push_transparency_state(pdf14_push_transparency_state); |
217 | | static dev_proc_pop_transparency_state(pdf14_pop_transparency_state); |
218 | | static dev_proc_ret_devn_params(pdf14_ret_devn_params); |
219 | | static dev_proc_update_spot_equivalent_colors(pdf14_update_spot_equivalent_colors); |
220 | | static dev_proc_copy_alpha(pdf14_copy_alpha); |
221 | | static dev_proc_copy_planes(pdf14_copy_planes); |
222 | | static dev_proc_copy_alpha_hl_color(pdf14_copy_alpha_hl_color); |
223 | | static dev_proc_discard_transparency_layer(pdf14_discard_trans_layer); |
224 | | static dev_proc_strip_tile_rect_devn(pdf14_strip_tile_rect_devn); |
225 | | static const gx_color_map_procs * |
226 | | pdf14_get_cmap_procs(const gs_gstate *, const gx_device *); |
227 | | |
228 | | #define XSIZE (int)(8.5 * X_DPI) /* 8.5 x 11 inch page, by default */ |
229 | | #define YSIZE (int)(11 * Y_DPI) |
230 | | |
231 | | /* 24-bit color. */ |
232 | | |
233 | | static void |
234 | | pdf14_procs_initialize(gx_device *dev, |
235 | | dev_proc_get_color_mapping_procs(get_color_mapping_procs), |
236 | | dev_proc_get_color_comp_index(get_color_comp_index), |
237 | | dev_proc_encode_color(encode_color), |
238 | | dev_proc_decode_color(decode_color)) |
239 | 5.02M | { |
240 | 5.02M | set_dev_proc(dev, initialize_device, pdf14_initialize_device); |
241 | 5.02M | set_dev_proc(dev, open_device, pdf14_open); |
242 | 5.02M | set_dev_proc(dev, output_page, pdf14_output_page); |
243 | 5.02M | set_dev_proc(dev, close_device, pdf14_close); |
244 | 5.02M | set_dev_proc(dev, map_rgb_color, encode_color); |
245 | 5.02M | set_dev_proc(dev, map_color_rgb, decode_color); |
246 | 5.02M | set_dev_proc(dev, fill_rectangle, pdf14_fill_rectangle); |
247 | 5.02M | set_dev_proc(dev, copy_mono, pdf14_copy_mono); |
248 | 5.02M | set_dev_proc(dev, get_params, gx_forward_get_params); |
249 | 5.02M | set_dev_proc(dev, put_params, pdf14_put_params); |
250 | 5.02M | set_dev_proc(dev, copy_alpha, pdf14_copy_alpha); |
251 | 5.02M | set_dev_proc(dev, fill_path, pdf14_fill_path); |
252 | 5.02M | set_dev_proc(dev, stroke_path, pdf14_stroke_path); |
253 | 5.02M | set_dev_proc(dev, fill_mask, pdf14_fill_mask); |
254 | 5.02M | set_dev_proc(dev, begin_typed_image, pdf14_begin_typed_image); |
255 | 5.02M | set_dev_proc(dev, composite, pdf14_composite); |
256 | 5.02M | set_dev_proc(dev, text_begin, pdf14_text_begin); |
257 | 5.02M | set_dev_proc(dev, begin_transparency_group, pdf14_begin_transparency_group); |
258 | 5.02M | set_dev_proc(dev, end_transparency_group, pdf14_end_transparency_group); |
259 | 5.02M | set_dev_proc(dev, begin_transparency_mask, pdf14_begin_transparency_mask); |
260 | 5.02M | set_dev_proc(dev, end_transparency_mask, pdf14_end_transparency_mask); |
261 | 5.02M | set_dev_proc(dev, discard_transparency_layer, pdf14_discard_trans_layer); |
262 | 5.02M | set_dev_proc(dev, get_color_mapping_procs, get_color_mapping_procs); |
263 | 5.02M | set_dev_proc(dev, get_color_comp_index, get_color_comp_index); |
264 | 5.02M | set_dev_proc(dev, encode_color, encode_color); |
265 | 5.02M | set_dev_proc(dev, decode_color, decode_color); |
266 | 5.02M | set_dev_proc(dev, fill_rectangle_hl_color, pdf14_fill_rectangle_hl_color); |
267 | 5.02M | set_dev_proc(dev, update_spot_equivalent_colors, gx_forward_update_spot_equivalent_colors); |
268 | 5.02M | set_dev_proc(dev, ret_devn_params, pdf14_ret_devn_params); |
269 | 5.02M | set_dev_proc(dev, push_transparency_state, pdf14_push_transparency_state); |
270 | 5.02M | set_dev_proc(dev, pop_transparency_state, pdf14_pop_transparency_state); |
271 | 5.02M | set_dev_proc(dev, dev_spec_op, pdf14_dev_spec_op); |
272 | 5.02M | set_dev_proc(dev, copy_planes, pdf14_copy_planes); |
273 | 5.02M | set_dev_proc(dev, set_graphics_type_tag, gx_forward_set_graphics_type_tag); |
274 | 5.02M | set_dev_proc(dev, strip_tile_rect_devn, pdf14_strip_tile_rect_devn); |
275 | 5.02M | set_dev_proc(dev, copy_alpha_hl_color, pdf14_copy_alpha_hl_color); |
276 | 5.02M | set_dev_proc(dev, fill_stroke_path, pdf14_fill_stroke_path); |
277 | 5.02M | } |
278 | | |
279 | | static void |
280 | | pdf14_Gray_initialize_device_procs(gx_device *dev) |
281 | 1.51M | { |
282 | 1.51M | pdf14_procs_initialize(dev, |
283 | 1.51M | gx_default_DevGray_get_color_mapping_procs, |
284 | 1.51M | gx_default_DevGray_get_color_comp_index, |
285 | 1.51M | pdf14_encode_color, |
286 | 1.51M | pdf14_decode_color); |
287 | 1.51M | } |
288 | | |
289 | | static void |
290 | | pdf14_RGB_initialize_device_procs(gx_device *dev) |
291 | 3.19M | { |
292 | 3.19M | pdf14_procs_initialize(dev, |
293 | 3.19M | gx_default_DevRGB_get_color_mapping_procs, |
294 | 3.19M | gx_default_DevRGB_get_color_comp_index, |
295 | 3.19M | pdf14_encode_color, |
296 | 3.19M | pdf14_decode_color); |
297 | 3.19M | } |
298 | | |
299 | | static void |
300 | | pdf14_CMYK_initialize_device_procs(gx_device *dev) |
301 | 82.1k | { |
302 | 82.1k | pdf14_procs_initialize(dev, |
303 | 82.1k | gx_default_DevCMYK_get_color_mapping_procs, |
304 | 82.1k | gx_default_DevCMYK_get_color_comp_index, |
305 | 82.1k | pdf14_encode_color, |
306 | 82.1k | pdf14_decode_color); |
307 | 82.1k | } |
308 | | |
309 | | static void |
310 | | pdf14_CMYKspot_initialize_device_procs(gx_device *dev) |
311 | 154k | { |
312 | 154k | pdf14_procs_initialize(dev, |
313 | 154k | pdf14_cmykspot_get_color_mapping_procs, |
314 | 154k | pdf14_cmykspot_get_color_comp_index, |
315 | 154k | pdf14_encode_color, |
316 | 154k | pdf14_decode_color); |
317 | 154k | } |
318 | | |
319 | | static void |
320 | | pdf14_RGBspot_initialize_device_procs(gx_device *dev) |
321 | 72.3k | { |
322 | 72.3k | pdf14_procs_initialize(dev, |
323 | 72.3k | pdf14_rgbspot_get_color_mapping_procs, |
324 | 72.3k | pdf14_rgbspot_get_color_comp_index, |
325 | 72.3k | pdf14_encode_color, |
326 | 72.3k | pdf14_decode_color); |
327 | 72.3k | } |
328 | | |
329 | | static void |
330 | | pdf14_Grayspot_initialize_device_procs(gx_device *dev) |
331 | 0 | { |
332 | 0 | pdf14_procs_initialize(dev, |
333 | 0 | pdf14_grayspot_get_color_mapping_procs, |
334 | 0 | pdf14_grayspot_get_color_comp_index, |
335 | 0 | pdf14_encode_color, |
336 | 0 | pdf14_decode_color); |
337 | 0 | } |
338 | | |
339 | | static void |
340 | | pdf14_custom_initialize_device_procs(gx_device *dev) |
341 | 0 | { |
342 | 0 | pdf14_procs_initialize(dev, |
343 | 0 | gx_forward_get_color_mapping_procs, |
344 | 0 | gx_forward_get_color_comp_index, |
345 | 0 | gx_forward_encode_color, |
346 | 0 | gx_forward_decode_color); |
347 | 0 | } |
348 | | |
349 | | static struct_proc_finalize(pdf14_device_finalize); |
350 | | |
351 | | gs_private_st_composite_use_final(st_pdf14_device, pdf14_device, "pdf14_device", |
352 | | pdf14_device_enum_ptrs, pdf14_device_reloc_ptrs, |
353 | | pdf14_device_finalize); |
354 | | |
355 | | static int pdf14_put_image(gx_device * dev, gs_gstate * pgs, |
356 | | gx_device * target); |
357 | | static int pdf14_cmykspot_put_image(gx_device * dev, gs_gstate * pgs, |
358 | | gx_device * target); |
359 | | static int pdf14_custom_put_image(gx_device * dev, gs_gstate * pgs, |
360 | | gx_device * target); |
361 | | |
362 | | /* Alter pdf14 device color model based upon group or softmask. This occurs |
363 | | post clist or in immediate rendering case. Data stored with buffer */ |
364 | | static pdf14_group_color_t* pdf14_push_color_model(gx_device *dev, |
365 | | gs_transparency_color_t group_color, int64_t icc_hashcode, |
366 | | cmm_profile_t *iccprofile, bool is_mask); |
367 | | static void pdf14_pop_color_model(gx_device* dev, pdf14_group_color_t* group_color); |
368 | | |
369 | | /* Alter clist writer device color model based upon group or softmask. Data |
370 | | stored in the device color model stack */ |
371 | | static int pdf14_clist_push_color_model(gx_device* dev, gx_device* cdev, gs_gstate* pgs, |
372 | | const gs_pdf14trans_t* pdf14pct, gs_memory_t* mem, bool is_mask); |
373 | | static int pdf14_clist_pop_color_model(gx_device* dev, gs_gstate* pgs); |
374 | | |
375 | | /* Used for cleaning up the stack if things go wrong */ |
376 | | static void pdf14_pop_group_color(gx_device *dev, const gs_gstate *pgs); |
377 | | |
378 | | static const pdf14_procs_t gray_pdf14_procs = { |
379 | | pdf14_unpack_additive, |
380 | | pdf14_put_image, |
381 | | pdf14_unpack16_additive |
382 | | }; |
383 | | |
384 | | static const pdf14_procs_t rgb_pdf14_procs = { |
385 | | pdf14_unpack_additive, |
386 | | pdf14_put_image, |
387 | | pdf14_unpack16_additive |
388 | | }; |
389 | | |
390 | | static const pdf14_procs_t cmyk_pdf14_procs = { |
391 | | pdf14_unpack_subtractive, |
392 | | pdf14_put_image, |
393 | | pdf14_unpack16_subtractive |
394 | | }; |
395 | | |
396 | | static const pdf14_procs_t cmykspot_pdf14_procs = { |
397 | | pdf14_unpack_custom, /* should never be used since we will use devn values */ |
398 | | pdf14_cmykspot_put_image, |
399 | | pdf14_unpack16_custom /* should never be used since we will use devn values */ |
400 | | }; |
401 | | |
402 | | static const pdf14_procs_t rgbspot_pdf14_procs = { |
403 | | pdf14_unpack_rgb_mix, |
404 | | pdf14_cmykspot_put_image, |
405 | | pdf14_unpack16_rgb_mix |
406 | | }; |
407 | | |
408 | | static const pdf14_procs_t grayspot_pdf14_procs = { |
409 | | pdf14_unpack_gray_mix, |
410 | | pdf14_cmykspot_put_image, |
411 | | pdf14_unpack16_gray_mix |
412 | | }; |
413 | | |
414 | | static const pdf14_procs_t custom_pdf14_procs = { |
415 | | pdf14_unpack_custom, |
416 | | pdf14_custom_put_image, |
417 | | pdf14_unpack16_custom |
418 | | }; |
419 | | |
420 | | static const pdf14_nonseparable_blending_procs_t gray_blending_procs = { |
421 | | art_blend_luminosity_custom_8, |
422 | | art_blend_saturation_custom_8, |
423 | | art_blend_luminosity_custom_16, |
424 | | art_blend_saturation_custom_16 |
425 | | }; |
426 | | |
427 | | static const pdf14_nonseparable_blending_procs_t rgb_blending_procs = { |
428 | | art_blend_luminosity_rgb_8, |
429 | | art_blend_saturation_rgb_8, |
430 | | art_blend_luminosity_rgb_16, |
431 | | art_blend_saturation_rgb_16 |
432 | | }; |
433 | | |
434 | | static const pdf14_nonseparable_blending_procs_t cmyk_blending_procs = { |
435 | | art_blend_luminosity_cmyk_8, |
436 | | art_blend_saturation_cmyk_8, |
437 | | art_blend_luminosity_cmyk_16, |
438 | | art_blend_saturation_cmyk_16 |
439 | | }; |
440 | | |
441 | | static const pdf14_nonseparable_blending_procs_t rgbspot_blending_procs = { |
442 | | art_blend_luminosity_rgb_8, |
443 | | art_blend_saturation_rgb_8, |
444 | | art_blend_luminosity_rgb_16, |
445 | | art_blend_saturation_rgb_16 |
446 | | }; |
447 | | |
448 | | static const pdf14_nonseparable_blending_procs_t grayspot_blending_procs = { |
449 | | art_blend_luminosity_custom_8, |
450 | | art_blend_saturation_custom_8, |
451 | | art_blend_luminosity_custom_16, |
452 | | art_blend_saturation_custom_16 |
453 | | }; |
454 | | |
455 | | static const pdf14_nonseparable_blending_procs_t custom_blending_procs = { |
456 | | art_blend_luminosity_custom_8, |
457 | | art_blend_saturation_custom_8, |
458 | | art_blend_luminosity_custom_16, |
459 | | art_blend_saturation_custom_16 |
460 | | }; |
461 | | |
462 | | const pdf14_device gs_pdf14_Gray_device = { |
463 | | std_device_std_color_full_body_type(pdf14_device, |
464 | | pdf14_Gray_initialize_device_procs, |
465 | | "pdf14gray", |
466 | | &st_pdf14_device, |
467 | | XSIZE, YSIZE, X_DPI, Y_DPI, 8, |
468 | | 0, 0, 0, 0, 0, 0), |
469 | | { 0 }, /* Procs */ |
470 | | NULL, /* target */ |
471 | | { 0 }, /* devn_params - not used */ |
472 | | &gray_pdf14_procs, |
473 | | &gray_blending_procs, |
474 | | 1 |
475 | | }; |
476 | | |
477 | | const pdf14_device gs_pdf14_RGB_device = { |
478 | | std_device_color_stype_body(pdf14_device, |
479 | | pdf14_RGB_initialize_device_procs, |
480 | | "pdf14RGB", |
481 | | &st_pdf14_device, |
482 | | XSIZE, YSIZE, X_DPI, Y_DPI, 24, 255, 256), |
483 | | { 0 }, /* Procs */ |
484 | | NULL, /* target */ |
485 | | { 0 }, /* devn_params - not used */ |
486 | | &rgb_pdf14_procs, |
487 | | &rgb_blending_procs, |
488 | | 3 |
489 | | }; |
490 | | |
491 | | const pdf14_device gs_pdf14_CMYK_device = { |
492 | | std_device_std_color_full_body_type(pdf14_device, |
493 | | pdf14_CMYK_initialize_device_procs, |
494 | | "pdf14cmyk", |
495 | | &st_pdf14_device, |
496 | | XSIZE, YSIZE, X_DPI, Y_DPI, 32, |
497 | | 0, 0, 0, 0, 0, 0), |
498 | | { 0 }, /* Procs */ |
499 | | NULL, /* target */ |
500 | | { 0 }, /* devn_params - not used */ |
501 | | &cmyk_pdf14_procs, |
502 | | &cmyk_blending_procs, |
503 | | 4 |
504 | | }; |
505 | | |
506 | | const pdf14_device gs_pdf14_CMYKspot_device = { |
507 | | std_device_part1_(pdf14_device, |
508 | | pdf14_CMYKspot_initialize_device_procs, |
509 | | "pdf14cmykspot", |
510 | | &st_pdf14_device, |
511 | | open_init_closed), |
512 | | dci_values(GX_DEVICE_COLOR_MAX_COMPONENTS,64,255,255,256,256), |
513 | | std_device_part2_(XSIZE, YSIZE, X_DPI, Y_DPI), |
514 | | offset_margin_values(0, 0, 0, 0, 0, 0), |
515 | | std_device_part3_(), |
516 | | { 0 }, /* Procs */ |
517 | | NULL, /* target */ |
518 | | /* DeviceN parameters */ |
519 | | { 8, /* Not used - Bits per color */ |
520 | | DeviceCMYKComponents, /* Names of color model colorants */ |
521 | | 4, /* Number colorants for CMYK */ |
522 | | 0, /* MaxSeparations has not been specified */ |
523 | | -1, /* PageSpotColors has not been specified */ |
524 | | {0}, /* SeparationNames */ |
525 | | 0, /* SeparationOrder names */ |
526 | | {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */ |
527 | | }, |
528 | | &cmykspot_pdf14_procs, |
529 | | &cmyk_blending_procs, |
530 | | 4 |
531 | | }; |
532 | | |
533 | | const pdf14_device gs_pdf14_RGBspot_device = { |
534 | | std_device_part1_(pdf14_device, |
535 | | pdf14_RGBspot_initialize_device_procs, |
536 | | "pdf14rgbspot", |
537 | | &st_pdf14_device, |
538 | | open_init_closed), |
539 | | dci_values_add(GX_DEVICE_COLOR_MAX_COMPONENTS,64,255,255,256,256), |
540 | | std_device_part2_(XSIZE, YSIZE, X_DPI, Y_DPI), |
541 | | offset_margin_values(0, 0, 0, 0, 0, 0), |
542 | | std_device_part3_(), |
543 | | { 0 }, /* Procs */ |
544 | | NULL, /* target */ |
545 | | /* DeviceN parameters */ |
546 | | { 8, /* Not used - Bits per color */ |
547 | | 0, /* Names of color model colorants */ |
548 | | 3, /* Number colorants for RGB */ |
549 | | 0, /* MaxSeparations has not been specified */ |
550 | | -1, /* PageSpotColors has not been specified */ |
551 | | { 0 }, /* SeparationNames */ |
552 | | 0, /* SeparationOrder names */ |
553 | | { 0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */ |
554 | | }, |
555 | | &rgbspot_pdf14_procs, |
556 | | &rgbspot_blending_procs, |
557 | | 3 |
558 | | }; |
559 | | |
560 | | const pdf14_device gs_pdf14_Grayspot_device = { |
561 | | std_device_part1_(pdf14_device, |
562 | | pdf14_Grayspot_initialize_device_procs, |
563 | | "pdf14grayspot", |
564 | | &st_pdf14_device, |
565 | | open_init_closed), |
566 | | dci_values(GX_DEVICE_COLOR_MAX_COMPONENTS,64,255,255,256,256), |
567 | | std_device_part2_(XSIZE, YSIZE, X_DPI, Y_DPI), |
568 | | offset_margin_values(0, 0, 0, 0, 0, 0), |
569 | | std_device_part3_(), |
570 | | { 0 }, /* Procs */ |
571 | | NULL, /* target */ |
572 | | /* DeviceN parameters */ |
573 | | { 8, /* Not used - Bits per color */ |
574 | | 0, /* Names of color model colorants */ |
575 | | 3, /* Number colorants for RGB */ |
576 | | 0, /* MaxSeparations has not been specified */ |
577 | | -1, /* PageSpotColors has not been specified */ |
578 | | { 0 }, /* SeparationNames */ |
579 | | 0, /* SeparationOrder names */ |
580 | | { 0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */ |
581 | | }, |
582 | | &grayspot_pdf14_procs, |
583 | | &grayspot_blending_procs, |
584 | | 1 |
585 | | }; |
586 | | |
587 | | /* |
588 | | * The 'custom' PDF 1.4 compositor device is for working with those devices |
589 | | * which support spot colors but do not have a CMYK process color model. |
590 | | * |
591 | | * This causes some problems with the Hue, Saturation, Color, and Luminosity |
592 | | * blending modes. These blending modes are 'non separable' and depend upon |
593 | | * knowing the details of the blending color space. However we use the |
594 | | * process color model of the output device for our blending color space. |
595 | | * With an unknown process color model, we have to fall back to some 'guesses' |
596 | | * about how to treat these blending modes. |
597 | | */ |
598 | | const pdf14_device gs_pdf14_custom_device = { |
599 | | std_device_part1_(pdf14_device, |
600 | | pdf14_custom_initialize_device_procs, |
601 | | "pdf14custom", |
602 | | &st_pdf14_device, |
603 | | open_init_closed), |
604 | | dci_values(GX_DEVICE_COLOR_MAX_COMPONENTS,64,255,255,256,256), |
605 | | std_device_part2_(XSIZE, YSIZE, X_DPI, Y_DPI), |
606 | | offset_margin_values(0, 0, 0, 0, 0, 0), |
607 | | std_device_part3_(), |
608 | | { 0 }, /* Procs */ |
609 | | NULL, /* target */ |
610 | | /* DeviceN parameters */ |
611 | | { 8, /* Not used - Bits per color */ |
612 | | DeviceCMYKComponents, /* Names of color model colorants */ |
613 | | 4, /* Number colorants for CMYK */ |
614 | | 0, /* MaxSeparations has not been specified */ |
615 | | -1, /* PageSpotColors has not been specified */ |
616 | | {0}, /* SeparationNames */ |
617 | | 0, /* SeparationOrder names */ |
618 | | {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */ |
619 | | }, |
620 | | &custom_pdf14_procs, |
621 | | &custom_blending_procs, |
622 | | 4 |
623 | | }; |
624 | | |
625 | | /* Devices used for pdf14-accum-* device, one for each image colorspace, */ |
626 | | /* Gray, RGB, CMYK, DeviceN. Before calling gdev_prn_open, the following */ |
627 | | /* are set from the target device: width, height, xdpi, ydpi, MaxBitmap. */ |
628 | | |
629 | | static dev_proc_print_page(no_print_page); |
630 | | static dev_proc_ret_devn_params(pdf14_accum_ret_devn_params); |
631 | | static dev_proc_get_color_comp_index(pdf14_accum_get_color_comp_index); |
632 | | static dev_proc_get_color_mapping_procs(pdf14_accum_get_color_mapping_procs); |
633 | | static dev_proc_update_spot_equivalent_colors(pdf14_accum_update_spot_equivalent_colors); |
634 | | |
635 | | static int |
636 | | no_print_page(gx_device_printer *pdev, gp_file *prn_stream) |
637 | 0 | { |
638 | 0 | return_error(gs_error_unknownerror); |
639 | 0 | } |
640 | | |
641 | | struct gx_device_pdf14_accum_s { |
642 | | gx_devn_prn_device_common; |
643 | | gx_device *save_p14dev; /* the non-clist pdf14 deivce saved for after accum */ |
644 | | }; |
645 | | typedef struct gx_device_pdf14_accum_s gx_device_pdf14_accum; |
646 | | |
647 | | int |
648 | | pdf14_accum_dev_spec_op(gx_device *pdev, int dev_spec_op, void *data, int size) |
649 | 4.36M | { |
650 | 4.36M | gx_device_pdf14_accum *adev = (gx_device_pdf14_accum *)pdev; |
651 | | |
652 | 4.36M | if (dev_spec_op == gxdso_device_child) { |
653 | 2.46k | gxdso_device_child_request *req = (gxdso_device_child_request *)data; |
654 | 2.46k | if (size < sizeof(*req)) |
655 | 0 | return gs_error_unknownerror; |
656 | 2.46k | req->target = adev->save_p14dev; |
657 | 2.46k | req->n = 0; |
658 | 2.46k | return 0; |
659 | 2.46k | } |
660 | | |
661 | 4.36M | return gdev_prn_dev_spec_op(pdev, dev_spec_op, data, size); |
662 | 4.36M | } |
663 | | |
664 | | gs_private_st_suffix_add1_final(st_gx_devn_accum_device, gx_device_pdf14_accum, |
665 | | "gx_device_pdf14_accum", pdf14_accum_device_enum_ptrs, pdf14_accum_device_reloc_ptrs, |
666 | | gx_devn_prn_device_finalize, st_gx_devn_prn_device, save_p14dev); |
667 | | |
668 | | static void |
669 | | pdf14_accum_Gray_initialize_device_procs(gx_device *dev) |
670 | 960 | { |
671 | 960 | gdev_prn_initialize_device_procs_gray8(dev); |
672 | | |
673 | 960 | set_dev_proc(dev, encode_color, gx_default_8bit_map_gray_color); |
674 | 960 | set_dev_proc(dev, decode_color, gx_default_8bit_map_color_gray); |
675 | 960 | } |
676 | | |
677 | | const gx_device_pdf14_accum pdf14_accum_Gray = { |
678 | | prn_device_stype_body(gx_device_pdf14_accum, |
679 | | pdf14_accum_Gray_initialize_device_procs, |
680 | | "pdf14-accum-Gray", |
681 | | &st_gx_devn_accum_device, |
682 | | 0/*width*/, 0/*height*/, 300/*xdpi*/, 300/*ydpi*/, |
683 | | 0/*lm*/, 0/*bm*/, 0/*rm*/, 0/*tm*/, |
684 | | 1/*ncomp*/, 8/*depth*/, 255/*max_gray*/, 0/*max_color*/, |
685 | | 256/*dither_grays*/, 0/*dither_colors*/, |
686 | | no_print_page), |
687 | | { 0 }, /* devn_params - not used */ |
688 | | { 0 }, /* equivalent_cmyk_color_params - not used */ |
689 | | 0/*save_p14dev*/ |
690 | | }; |
691 | | |
692 | | static void |
693 | | pdf14_accum_RGB_initialize_device_procs(gx_device *dev) |
694 | 3.00k | { |
695 | 3.00k | gdev_prn_initialize_device_procs_rgb(dev); |
696 | 3.00k | } |
697 | | |
698 | | const gx_device_pdf14_accum pdf14_accum_RGB = { |
699 | | prn_device_stype_body(gx_device_pdf14_accum, |
700 | | pdf14_accum_RGB_initialize_device_procs, |
701 | | "pdf14-accum-RGB", |
702 | | &st_gx_devn_accum_device, |
703 | | 0/*width*/, 0/*height*/, 300/*xdpi*/, 300/*ydpi*/, |
704 | | 0/*lm*/, 0/*bm*/, 0/*rm*/, 0/*tm*/, |
705 | | 3/*ncomp*/, 24/*depth*/, 0/*max_gray*/, 255/*max_color*/, |
706 | | 1/*dither_grays*/, 256/*dither_colors*/, |
707 | | no_print_page), |
708 | | { 0 }, /* devn_params - not used */ |
709 | | { 0 }, /* equivalent_cmyk_color_params - not used */ |
710 | | 0/*save_p14dev*/ |
711 | | }; |
712 | | |
713 | | static void |
714 | | pdf14_accum_CMYK_initialize_device_procs(gx_device *dev) |
715 | 0 | { |
716 | 0 | gdev_prn_initialize_device_procs_cmyk8(dev); |
717 | |
|
718 | 0 | set_dev_proc(dev, encode_color, cmyk_8bit_map_cmyk_color); |
719 | 0 | set_dev_proc(dev, decode_color, cmyk_8bit_map_color_cmyk); |
720 | 0 | } |
721 | | |
722 | | const gx_device_pdf14_accum pdf14_accum_CMYK = { |
723 | | prn_device_stype_body(gx_device_pdf14_accum, |
724 | | pdf14_accum_CMYK_initialize_device_procs, |
725 | | "pdf14-accum-CMYK", |
726 | | &st_gx_devn_accum_device, |
727 | | 0/*width*/, 0/*height*/, 300/*xdpi*/, 300/*ydpi*/, |
728 | | 0/*lm*/, 0/*bm*/, 0/*rm*/, 0/*tm*/, |
729 | | 4/*ncomp*/, 32/*depth*/, 255/*max_gray*/, 255/*max_color*/, |
730 | | 256/*dither_grays*/, 256/*dither_colors*/, |
731 | | no_print_page), |
732 | | { 0 }, /* devn_params - not used */ |
733 | | { 0 }, /* equivalent_cmyk_color_params - not used */ |
734 | | 0/*save_p14dev*/ |
735 | | }; |
736 | | |
737 | | static void |
738 | | pdf14_accum_initialize_device_procs_cmykspot(gx_device *dev) |
739 | 0 | { |
740 | 0 | pdf14_accum_CMYK_initialize_device_procs(dev); |
741 | |
|
742 | 0 | set_dev_proc(dev, get_color_mapping_procs, pdf14_accum_get_color_mapping_procs); |
743 | 0 | set_dev_proc(dev, get_color_comp_index, pdf14_accum_get_color_comp_index); |
744 | 0 | set_dev_proc(dev, update_spot_equivalent_colors, pdf14_accum_update_spot_equivalent_colors); |
745 | 0 | set_dev_proc(dev, ret_devn_params, pdf14_accum_ret_devn_params); |
746 | 0 | } |
747 | | |
748 | | const gx_device_pdf14_accum pdf14_accum_CMYKspot = { |
749 | | prn_device_stype_body(gx_device_pdf14_accum, |
750 | | pdf14_accum_initialize_device_procs_cmykspot, |
751 | | "pdf14-accum-CMYKspot", |
752 | | &st_gx_devn_accum_device, |
753 | | 0/*width*/, 0/*height*/, 300/*xdpi*/, 300/*ydpi*/, |
754 | | 0/*lm*/, 0/*bm*/, 0/*rm*/, 0/*tm*/, |
755 | | 4/*ncomp*/, 32/*depth*/, 255/*max_gray*/, 255/*max_color*/, |
756 | | 256/*dither_grays*/, 256/*dither_colors*/, |
757 | | no_print_page), |
758 | | /* DeviceN parameters */ |
759 | | { 8, /* Not used - Bits per color */ |
760 | | DeviceCMYKComponents, /* Names of color model colorants */ |
761 | | 4, /* Number colorants for CMYK */ |
762 | | 0, /* MaxSeparations has not been specified */ |
763 | | -1, /* PageSpotColors has not been specified */ |
764 | | { 0 }, /* SeparationNames */ |
765 | | 0, /* SeparationOrder names */ |
766 | | {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */ |
767 | | }, |
768 | | { true }, /* equivalent_cmyk_color_params */ |
769 | | 0/*save_p14dev*/ |
770 | | }; |
771 | | |
772 | | /* GC procedures */ |
773 | | static |
774 | 0 | ENUM_PTRS_WITH(pdf14_device_enum_ptrs, pdf14_device *pdev) |
775 | 0 | { |
776 | 0 | index -= 5; |
777 | 0 | if (index < pdev->devn_params.separations.num_separations) |
778 | 0 | ENUM_RETURN(pdev->devn_params.separations.names[index].data); |
779 | 0 | index -= pdev->devn_params.separations.num_separations; |
780 | 0 | if (index < pdev->devn_params.pdf14_separations.num_separations) |
781 | 0 | ENUM_RETURN(pdev->devn_params.pdf14_separations.names[index].data); |
782 | 0 | return 0; |
783 | 0 | } |
784 | 0 | case 0: return ENUM_OBJ(pdev->ctx); |
785 | 0 | case 1: return ENUM_OBJ(pdev->color_model_stack); |
786 | 0 | case 2: return ENUM_OBJ(pdev->smaskcolor); |
787 | 0 | case 3: ENUM_RETURN(gx_device_enum_ptr(pdev->target)); |
788 | 0 | case 4: ENUM_RETURN(gx_device_enum_ptr(pdev->pclist_device)); |
789 | 0 | ENUM_PTRS_END |
790 | | |
791 | 0 | static RELOC_PTRS_WITH(pdf14_device_reloc_ptrs, pdf14_device *pdev) |
792 | 0 | { |
793 | 0 | { |
794 | 0 | int i; |
795 | |
|
796 | 0 | for (i = 0; i < pdev->devn_params.separations.num_separations; ++i) { |
797 | 0 | RELOC_PTR(pdf14_device, devn_params.separations.names[i].data); |
798 | 0 | } |
799 | 0 | } |
800 | 0 | RELOC_VAR(pdev->ctx); |
801 | 0 | RELOC_VAR(pdev->smaskcolor); |
802 | 0 | RELOC_VAR(pdev->color_model_stack); |
803 | 0 | pdev->target = gx_device_reloc_ptr(pdev->target, gcst); |
804 | 0 | pdev->pclist_device = gx_device_reloc_ptr(pdev->pclist_device, gcst); |
805 | 0 | } |
806 | 0 | RELOC_PTRS_END |
807 | | |
808 | | /* ------ Private definitions ------ */ |
809 | | |
810 | | static void |
811 | | resolve_matte(pdf14_buf *maskbuf, byte *src_data, intptr_t src_planestride, intptr_t src_rowstride, |
812 | | int width, int height, cmm_profile_t *src_profile, int deep) |
813 | 1.11k | { |
814 | 1.11k | if (deep) { |
815 | 0 | int x, y, i; |
816 | 0 | uint16_t *mask_row_ptr = (uint16_t *)maskbuf->data; |
817 | 0 | uint16_t *src_row_ptr = (uint16_t *)src_data; |
818 | 0 | uint16_t *mask_tr_fn = (uint16_t *)maskbuf->transfer_fn; |
819 | |
|
820 | 0 | src_planestride >>= 1; |
821 | 0 | src_rowstride >>= 1; |
822 | |
|
823 | 0 | for (y = 0; y < height; y++) { |
824 | 0 | uint16_t *mask_curr_ptr = mask_row_ptr; |
825 | 0 | uint16_t *src_curr_ptr = src_row_ptr; |
826 | 0 | for (x = 0; x < width; x++) { |
827 | 0 | uint16_t idx = *mask_curr_ptr; |
828 | 0 | byte top = idx>>8; |
829 | 0 | uint16_t a = mask_tr_fn[top]; |
830 | 0 | int b = mask_tr_fn[top+1]-a; |
831 | 0 | uint16_t matte_alpha = a + ((0x80 + b*(idx & 0xff))>>8); |
832 | | |
833 | | /* matte's happen rarely enough that we allow ourselves to |
834 | | * resort to 64bit here. */ |
835 | 0 | if (matte_alpha != 0 && matte_alpha != 0xffff) { |
836 | 0 | for (i = 0; i < src_profile->num_comps; i++) { |
837 | 0 | int val = src_curr_ptr[i * src_planestride] - maskbuf->matte[i]; |
838 | 0 | int temp = (((int64_t)val) * 0xffff / matte_alpha) + maskbuf->matte[i]; |
839 | | |
840 | | /* clip */ |
841 | 0 | if (temp > 0xffff) |
842 | 0 | src_curr_ptr[i * src_planestride] = 0xffff; |
843 | 0 | else if (temp < 0) |
844 | 0 | src_curr_ptr[i * src_planestride] = 0; |
845 | 0 | else |
846 | 0 | src_curr_ptr[i * src_planestride] = temp; |
847 | 0 | } |
848 | 0 | } |
849 | 0 | mask_curr_ptr++; |
850 | 0 | src_curr_ptr++; |
851 | 0 | } |
852 | 0 | src_row_ptr += src_rowstride; |
853 | 0 | mask_row_ptr += (maskbuf->rowstride>>1); |
854 | 0 | } |
855 | 1.11k | } else { |
856 | 1.11k | int x, y, i; |
857 | 1.11k | byte *mask_row_ptr = maskbuf->data; |
858 | 1.11k | byte *src_row_ptr = src_data; |
859 | 1.11k | byte *mask_tr_fn = maskbuf->transfer_fn; |
860 | | |
861 | 14.2k | for (y = 0; y < height; y++) { |
862 | 13.1k | byte *mask_curr_ptr = mask_row_ptr; |
863 | 13.1k | byte *src_curr_ptr = src_row_ptr; |
864 | 16.6M | for (x = 0; x < width; x++) { |
865 | 16.6M | byte matte_alpha = mask_tr_fn[*mask_curr_ptr]; |
866 | 16.6M | if (matte_alpha != 0 && matte_alpha != 0xff) { |
867 | 9.15M | for (i = 0; i < src_profile->num_comps; i++) { |
868 | 6.86M | byte matte = maskbuf->matte[i]>>8; |
869 | 6.86M | int val = src_curr_ptr[i * src_planestride] - matte; |
870 | 6.86M | int temp = ((((val * 0xff) << 8) / matte_alpha) >> 8) + matte; |
871 | | |
872 | | /* clip */ |
873 | 6.86M | if (temp > 0xff) |
874 | 4.91M | src_curr_ptr[i * src_planestride] = 0xff; |
875 | 1.95M | else if (temp < 0) |
876 | 0 | src_curr_ptr[i * src_planestride] = 0; |
877 | 1.95M | else |
878 | 1.95M | src_curr_ptr[i * src_planestride] = temp; |
879 | 6.86M | } |
880 | 2.28M | } |
881 | 16.6M | mask_curr_ptr++; |
882 | 16.6M | src_curr_ptr++; |
883 | 16.6M | } |
884 | 13.1k | src_row_ptr += src_rowstride; |
885 | 13.1k | mask_row_ptr += maskbuf->rowstride; |
886 | 13.1k | } |
887 | 1.11k | } |
888 | 1.11k | } |
889 | | |
890 | | /* Transform of color data and copy noncolor data. Used in |
891 | | group pop and during the pdf14 put image calls when the blend color space |
892 | | is different than the target device color space. The function will try do |
893 | | in-place conversion if possible. If not, it will do an allocation. The |
894 | | put_image call needs to know if an allocation was made so that it can adjust |
895 | | for the fact that we likely don't have a full page any longer and we don't |
896 | | need to do the offset to our data in the buffer. Bug 700686: If we are in |
897 | | a softmask that includes a matte entry, then we need to undo the matte |
898 | | entry here at this time in the image's native color space not the parent |
899 | | color space. The endian_swap term here is only set to true if the data |
900 | | has been baked as BE during the put_image blending operation and we are |
901 | | on a LE machine. */ |
902 | | static forceinline pdf14_buf* |
903 | | template_transform_color_buffer(gs_gstate *pgs, pdf14_ctx *ctx, gx_device *dev, |
904 | | pdf14_buf *src_buf, byte *src_data, cmm_profile_t *src_profile, |
905 | | cmm_profile_t *des_profile, int x0, int y0, int width, int height, bool *did_alloc, |
906 | | bool has_matte, bool deep, bool endian_swap, int num_channels_to_lose) |
907 | 11.7k | { |
908 | 11.7k | gsicc_rendering_param_t rendering_params; |
909 | 11.7k | gsicc_link_t *icc_link; |
910 | 11.7k | gsicc_bufferdesc_t src_buff_desc; |
911 | 11.7k | gsicc_bufferdesc_t des_buff_desc; |
912 | 11.7k | intptr_t src_planestride = src_buf->planestride; |
913 | 11.7k | intptr_t src_rowstride = src_buf->rowstride; |
914 | 11.7k | int src_n_planes = src_buf->n_planes; |
915 | 11.7k | int src_n_chan = src_buf->n_chan; |
916 | 11.7k | intptr_t des_planestride = src_planestride; |
917 | 11.7k | intptr_t des_rowstride = src_rowstride; |
918 | 11.7k | int des_n_planes = src_n_planes; |
919 | 11.7k | int des_n_chan = src_n_chan; |
920 | 11.7k | int diff; |
921 | 11.7k | int k, j; |
922 | 11.7k | byte *des_data = NULL; |
923 | 11.7k | pdf14_buf *output = src_buf; |
924 | 11.7k | pdf14_mask_t *mask_stack; |
925 | 11.7k | pdf14_buf *maskbuf; |
926 | 11.7k | int code; |
927 | | |
928 | 11.7k | *did_alloc = false; |
929 | | |
930 | | /* Same profile */ |
931 | 11.7k | if (gsicc_get_hash(src_profile) == gsicc_get_hash(des_profile)) |
932 | 0 | return src_buf; |
933 | | |
934 | | /* Define the rendering intent get the link */ |
935 | 11.7k | rendering_params.black_point_comp = gsBLACKPTCOMP_ON; |
936 | 11.7k | rendering_params.graphics_type_tag = GS_IMAGE_TAG; |
937 | 11.7k | rendering_params.override_icc = false; |
938 | 11.7k | rendering_params.preserve_black = gsBKPRESNOTSPECIFIED; |
939 | 11.7k | rendering_params.rendering_intent = gsRELATIVECOLORIMETRIC; /* Use relative intent */ |
940 | 11.7k | rendering_params.cmm = gsCMM_DEFAULT; |
941 | 11.7k | icc_link = gsicc_get_link_profile(pgs, dev, src_profile, des_profile, |
942 | 11.7k | &rendering_params, pgs->memory, false); |
943 | 11.7k | if (icc_link == NULL) |
944 | 0 | return NULL; |
945 | | |
946 | | /* If different data sizes, we have to do an allocation */ |
947 | 11.7k | diff = des_profile->num_comps - src_profile->num_comps; |
948 | 11.7k | if (diff != 0) { |
949 | 11.2k | byte *src_ptr; |
950 | 11.2k | byte *des_ptr; |
951 | | |
952 | 11.2k | *did_alloc = true; |
953 | 11.2k | des_rowstride = ((width + 3) & -4)<<deep; |
954 | 11.2k | des_planestride = height * des_rowstride; |
955 | 11.2k | des_n_planes = src_n_planes + diff - num_channels_to_lose; |
956 | 11.2k | des_n_chan = src_n_chan + diff; |
957 | 11.2k | des_data = gs_alloc_bytes(ctx->memory, |
958 | 11.2k | des_planestride * des_n_planes + CAL_SLOP, |
959 | 11.2k | "pdf14_transform_color_buffer"); |
960 | 11.2k | if (des_data == NULL) |
961 | 0 | return NULL; |
962 | | |
963 | | /* Copy over the noncolor planes. May only be a dirty part, so have |
964 | | to copy row by row */ |
965 | 11.2k | src_ptr = src_data; |
966 | 11.2k | des_ptr = des_data; |
967 | 125k | for (j = 0; j < height; j++) { |
968 | 229k | for (k = 0; k < (src_n_planes - src_profile->num_comps); k++) { |
969 | 114k | memcpy(des_ptr + des_planestride * (k + des_profile->num_comps - num_channels_to_lose), |
970 | 114k | src_ptr + src_planestride * (k + src_profile->num_comps), |
971 | 114k | width<<deep); |
972 | 114k | } |
973 | 114k | src_ptr += src_rowstride; |
974 | 114k | des_ptr += des_rowstride; |
975 | 114k | } |
976 | 11.2k | } else |
977 | 460 | des_data = src_data; |
978 | | |
979 | | /* Set up the buffer descriptors. */ |
980 | 11.7k | gsicc_init_buffer(&src_buff_desc, src_profile->num_comps, 1<<deep, false, |
981 | 11.7k | false, true, src_planestride, src_rowstride, height, width); |
982 | 11.7k | gsicc_init_buffer(&des_buff_desc, des_profile->num_comps, 1<<deep, false, |
983 | 11.7k | false, true, des_planestride, des_rowstride, height, width); |
984 | | |
985 | 11.7k | src_buff_desc.endian_swap = endian_swap; |
986 | 11.7k | des_buff_desc.endian_swap = endian_swap; |
987 | | |
988 | | /* If we have a matte entry, undo the pre-blending now. Also set pdf14 |
989 | | context to ensure that this is not done again during the group |
990 | | composition */ |
991 | 11.7k | if (has_matte && |
992 | | /* Should always happen, but check for safety */ |
993 | 1.66k | ((mask_stack = ctx->mask_stack) != NULL) && |
994 | 1.66k | ((maskbuf = mask_stack->mask_buf) != NULL) && |
995 | 1.66k | (maskbuf->data != NULL)) |
996 | 1.11k | { |
997 | 1.11k | resolve_matte(maskbuf, src_data, src_planestride, src_rowstride, width, height, src_profile, deep); |
998 | 1.11k | } |
999 | | |
1000 | | /* Transform the data. Since the pdf14 device should be using RGB, CMYK or |
1001 | | Gray buffers, this transform does not need to worry about the cmap procs |
1002 | | of the target device. */ |
1003 | 11.7k | code = (icc_link->procs.map_buffer)(dev, icc_link, &src_buff_desc, &des_buff_desc, |
1004 | 11.7k | src_data, des_data); |
1005 | 11.7k | gsicc_release_link(icc_link); |
1006 | 11.7k | if (code < 0) |
1007 | 0 | return NULL; |
1008 | | |
1009 | 11.7k | output->planestride = des_planestride; |
1010 | 11.7k | output->rowstride = des_rowstride; |
1011 | 11.7k | output->n_planes = des_n_planes; |
1012 | 11.7k | output->n_chan = des_n_chan; |
1013 | | /* If not in-place conversion, then release. */ |
1014 | 11.7k | if (des_data != src_data) { |
1015 | 11.2k | gs_free_object(ctx->memory, output->data, |
1016 | 11.2k | "pdf14_transform_color_buffer"); |
1017 | 11.2k | output->data = des_data; |
1018 | | /* Note, this is needed for case where we did a put image, as the |
1019 | | resulting transformed buffer may not be a full page. */ |
1020 | 11.2k | output->rect.p.x = x0; |
1021 | 11.2k | output->rect.p.y = y0; |
1022 | 11.2k | output->rect.q.x = x0 + width; |
1023 | 11.2k | output->rect.q.y = y0 + height; |
1024 | 11.2k | } |
1025 | 11.7k | return output; |
1026 | 11.7k | } |
1027 | | |
1028 | | /* This is a routine to do memset's but with 16 bit values. |
1029 | | * Note, that we still take bytes, NOT "num values to set". |
1030 | | * We assume dest is 16 bit aligned. We assume that bytes is |
1031 | | * a multiple of 2. */ |
1032 | | static void gs_memset16(byte *dest_, uint16_t value, int bytes) |
1033 | 0 | { |
1034 | 0 | uint16_t *dest = (uint16_t *)(void *)dest_; |
1035 | 0 | uint32_t v; |
1036 | 0 | if (bytes < 0) |
1037 | 0 | return; |
1038 | 0 | if (((intptr_t)dest) & 2) { |
1039 | 0 | *dest++ = value; |
1040 | 0 | bytes--; |
1041 | 0 | if (bytes == 0) |
1042 | 0 | return; |
1043 | 0 | } |
1044 | 0 | v = value | (value<<16); |
1045 | 0 | bytes -= 2; |
1046 | 0 | while (bytes > 0) { |
1047 | 0 | *(uint32_t *)dest = v; |
1048 | 0 | dest += 2; |
1049 | 0 | bytes -= 4; |
1050 | 0 | } |
1051 | 0 | bytes += 2; |
1052 | 0 | if (bytes & 2) { |
1053 | 0 | *dest = value; |
1054 | 0 | } |
1055 | 0 | } |
1056 | | |
1057 | | static pdf14_buf* |
1058 | | pdf14_transform_color_buffer_no_matte(gs_gstate *pgs, pdf14_ctx *ctx, gx_device *dev, |
1059 | | pdf14_buf *src_buf, byte *src_data, cmm_profile_t *src_profile, |
1060 | | cmm_profile_t *des_profile, int x0, int y0, int width, int height, bool *did_alloc, |
1061 | | bool deep, bool endian_swap, int num_channels_to_lose) |
1062 | 10.0k | { |
1063 | 10.0k | if (deep) |
1064 | 0 | return template_transform_color_buffer(pgs, ctx, dev, src_buf, src_data, src_profile, |
1065 | 0 | des_profile, x0, y0, width, height, did_alloc, false, true, endian_swap, num_channels_to_lose); |
1066 | 10.0k | else |
1067 | 10.0k | return template_transform_color_buffer(pgs, ctx, dev, src_buf, src_data, src_profile, |
1068 | 10.0k | des_profile, x0, y0, width, height, did_alloc, false, false, endian_swap, num_channels_to_lose); |
1069 | 10.0k | } |
1070 | | |
1071 | | static pdf14_buf* |
1072 | | pdf14_transform_color_buffer_with_matte(gs_gstate *pgs, pdf14_ctx *ctx, gx_device *dev, |
1073 | | pdf14_buf *src_buf, byte *src_data, cmm_profile_t *src_profile, |
1074 | | cmm_profile_t *des_profile, int x0, int y0, int width, int height, bool *did_alloc, |
1075 | | bool deep, bool endian_swap) |
1076 | 1.66k | { |
1077 | 1.66k | if (deep) |
1078 | 0 | return template_transform_color_buffer(pgs, ctx, dev, src_buf, src_data, src_profile, |
1079 | 0 | des_profile, x0, y0, width, height, did_alloc, true, true, endian_swap, false); |
1080 | 1.66k | else |
1081 | 1.66k | return template_transform_color_buffer(pgs, ctx, dev, src_buf, src_data, src_profile, |
1082 | 1.66k | des_profile, x0, y0, width, height, did_alloc, true, false, endian_swap, false); |
1083 | 1.66k | } |
1084 | | |
1085 | | /** |
1086 | | * pdf14_buf_new: Allocate a new PDF 1.4 buffer. |
1087 | | * @n_chan: Number of pixel channels including alpha, but not including |
1088 | | * shape, group alpha, or tags. |
1089 | | * |
1090 | | * Return value: Newly allocated buffer, or NULL on failure. |
1091 | | **/ |
1092 | | static pdf14_buf * |
1093 | | pdf14_buf_new(gs_int_rect *rect, bool has_tags, bool has_alpha_g, |
1094 | | bool has_shape, bool idle, int n_chan, int num_spots, |
1095 | | gs_memory_t *memory, bool deep) |
1096 | 3.27M | { |
1097 | | |
1098 | | /* Note that alpha_g is the alpha for the GROUP */ |
1099 | | /* This is distinct from the alpha that may also exist */ |
1100 | | /* for the objects within the group. Hence it can introduce */ |
1101 | | /* yet another plane */ |
1102 | | |
1103 | 3.27M | pdf14_buf *result; |
1104 | 3.27M | int64_t rowstride = ((size_t)((rect->q.x - rect->p.x + 3) & -4))<<deep; |
1105 | 3.27M | int64_t height = (rect->q.y - rect->p.y); |
1106 | 3.27M | int n_planes = n_chan + (has_shape ? 1 : 0) + (has_alpha_g ? 1 : 0) + |
1107 | 3.27M | (has_tags ? 1 : 0); |
1108 | 3.27M | size_t planestride; |
1109 | | #if ARCH_SIZEOF_SIZE_T <= 4 |
1110 | | int64_t dsize = rowstride * height * n_planes; |
1111 | | |
1112 | | if (dsize > max_size_t) |
1113 | | return NULL; |
1114 | | #endif |
1115 | | |
1116 | 3.27M | result = gs_alloc_struct(memory, pdf14_buf, &st_pdf14_buf, |
1117 | 3.27M | "pdf14_buf_new"); |
1118 | 3.27M | if (result == NULL) |
1119 | 0 | return result; |
1120 | | |
1121 | 3.27M | result->memory = memory; |
1122 | 3.27M | result->backdrop = NULL; |
1123 | 3.27M | result->saved = NULL; |
1124 | 3.27M | result->isolated = false; |
1125 | 3.27M | result->knockout = false; |
1126 | 3.27M | result->has_alpha_g = has_alpha_g; |
1127 | 3.27M | result->has_shape = has_shape; |
1128 | 3.27M | result->has_tags = has_tags; |
1129 | 3.27M | result->rect = *rect; |
1130 | 3.27M | result->n_chan = n_chan; |
1131 | 3.27M | result->n_planes = n_planes; |
1132 | 3.27M | result->rowstride = rowstride; |
1133 | 3.27M | result->transfer_fn = NULL; |
1134 | 3.27M | result->is_ident = true; |
1135 | 3.27M | result->matte_num_comps = 0; |
1136 | 3.27M | result->matte = NULL; |
1137 | 3.27M | result->mask_stack = NULL; |
1138 | 3.27M | result->idle = idle; |
1139 | 3.27M | result->mask_id = 0; |
1140 | 3.27M | result->num_spots = num_spots; |
1141 | 3.27M | result->deep = deep; |
1142 | 3.27M | result->page_group = false; |
1143 | 3.27M | result->group_color_info = NULL; |
1144 | 3.27M | result->group_popped = false; |
1145 | | |
1146 | 3.27M | if (idle || height <= 0) { |
1147 | | /* Empty clipping - will skip all drawings. */ |
1148 | 1.45M | result->planestride = 0; |
1149 | 1.45M | result->data = 0; |
1150 | 1.82M | } else { |
1151 | 1.82M | planestride = rowstride * height; |
1152 | 1.82M | result->planestride = planestride; |
1153 | 1.82M | result->data = gs_alloc_bytes(memory, |
1154 | 1.82M | planestride * n_planes + CAL_SLOP, |
1155 | 1.82M | "pdf14_buf_new"); |
1156 | 1.82M | if (result->data == NULL) { |
1157 | 0 | gs_free_object(memory, result, "pdf14_buf_new"); |
1158 | 0 | return NULL; |
1159 | 0 | } |
1160 | 1.82M | if (has_alpha_g) { |
1161 | 436k | int alpha_g_plane = n_chan + (has_shape ? 1 : 0); |
1162 | | /* Memsetting by 0, so this copes with the deep case too */ |
1163 | 436k | memset(result->data + alpha_g_plane * planestride, 0, planestride); |
1164 | 436k | } |
1165 | 1.82M | if (has_tags) { |
1166 | 0 | int tags_plane = n_chan + (has_shape ? 1 : 0) + (has_alpha_g ? 1 : 0); |
1167 | | /* Memsetting by 0, so this copes with the deep case too */ |
1168 | 0 | memset (result->data + tags_plane * planestride, |
1169 | 0 | GS_UNTOUCHED_TAG, planestride); |
1170 | 0 | } |
1171 | 1.82M | } |
1172 | | /* Initialize dirty box with an invalid rectangle (the reversed rectangle). |
1173 | | * Any future drawing will make it valid again, so we won't blend back |
1174 | | * more than we need. */ |
1175 | 3.27M | result->dirty.p.x = rect->q.x; |
1176 | 3.27M | result->dirty.p.y = rect->q.y; |
1177 | 3.27M | result->dirty.q.x = rect->p.x; |
1178 | 3.27M | result->dirty.q.y = rect->p.y; |
1179 | 3.27M | return result; |
1180 | 3.27M | } |
1181 | | |
1182 | | static void |
1183 | | pdf14_buf_free(pdf14_buf *buf) |
1184 | 3.27M | { |
1185 | 3.27M | pdf14_group_color_t *group_color_info = buf->group_color_info; |
1186 | 3.27M | gs_memory_t *memory = buf->memory; |
1187 | | |
1188 | 3.27M | if (buf->mask_stack) |
1189 | 3.27M | rc_decrement(buf->mask_stack, "pdf14_buf_free"); |
1190 | | |
1191 | 3.27M | gs_free_object(memory, buf->transfer_fn, "pdf14_buf_free"); |
1192 | 3.27M | gs_free_object(memory, buf->matte, "pdf14_buf_free"); |
1193 | 3.27M | gs_free_object(memory, buf->data, "pdf14_buf_free"); |
1194 | | |
1195 | 6.55M | while (group_color_info) { |
1196 | 3.27M | if (group_color_info->icc_profile != NULL) { |
1197 | 3.27M | gsicc_adjust_profile_rc(group_color_info->icc_profile, -1, "pdf14_buf_free"); |
1198 | 3.27M | } |
1199 | 3.27M | buf->group_color_info = group_color_info->previous; |
1200 | 3.27M | gs_free_object(memory, group_color_info, "pdf14_buf_free"); |
1201 | 3.27M | group_color_info = buf->group_color_info; |
1202 | 3.27M | } |
1203 | | |
1204 | 3.27M | gs_free_object(memory, buf->backdrop, "pdf14_buf_free"); |
1205 | 3.27M | gs_free_object(memory, buf, "pdf14_buf_free"); |
1206 | 3.27M | } |
1207 | | |
1208 | | static pdf14_ctx * |
1209 | | pdf14_ctx_new(gx_device *dev, bool deep) |
1210 | 1.14M | { |
1211 | 1.14M | pdf14_ctx *result; |
1212 | 1.14M | gs_memory_t *memory = dev->memory->stable_memory; |
1213 | | |
1214 | 1.14M | result = gs_alloc_struct(memory, pdf14_ctx, &st_pdf14_ctx, "pdf14_ctx_new"); |
1215 | 1.14M | if (result == NULL) |
1216 | 0 | return result; |
1217 | 1.14M | result->stack = NULL; |
1218 | 1.14M | result->mask_stack = pdf14_mask_element_new(memory); |
1219 | 1.14M | if (result->mask_stack == NULL) { |
1220 | 0 | gs_free_object(memory, result, "pdf14_ctx_new"); |
1221 | 0 | return NULL; |
1222 | 0 | } |
1223 | 1.14M | result->memory = memory; |
1224 | 1.14M | result->smask_depth = 0; |
1225 | 1.14M | result->smask_blend = false; |
1226 | 1.14M | result->deep = deep; |
1227 | 1.14M | result->base_color = NULL; |
1228 | 1.14M | return result; |
1229 | 1.14M | } |
1230 | | |
1231 | | static void |
1232 | | pdf14_ctx_free(pdf14_ctx *ctx) |
1233 | 1.14M | { |
1234 | 1.14M | pdf14_buf *buf, *next; |
1235 | | |
1236 | 1.14M | if (ctx->base_color) { |
1237 | 612k | gsicc_adjust_profile_rc(ctx->base_color->icc_profile, -1, "pdf14_ctx_free"); |
1238 | 612k | gs_free_object(ctx->memory, ctx->base_color, "pdf14_ctx_free"); |
1239 | 612k | } |
1240 | 1.14M | if (ctx->mask_stack) { |
1241 | | /* A mask was created but was not used in this band. */ |
1242 | 552k | rc_decrement(ctx->mask_stack, "pdf14_ctx_free"); |
1243 | 552k | } |
1244 | 2.11M | for (buf = ctx->stack; buf != NULL; buf = next) { |
1245 | 978k | next = buf->saved; |
1246 | 978k | pdf14_buf_free(buf); |
1247 | 978k | } |
1248 | 1.14M | gs_free_object (ctx->memory, ctx, "pdf14_ctx_free"); |
1249 | 1.14M | } |
1250 | | |
1251 | | /** |
1252 | | * pdf14_find_backdrop_buf: Find backdrop buffer. |
1253 | | * |
1254 | | * Return value: Backdrop buffer for current group operation, or NULL |
1255 | | * if backdrop is fully transparent. |
1256 | | **/ |
1257 | | static pdf14_buf * |
1258 | | pdf14_find_backdrop_buf(pdf14_ctx *ctx, bool *is_backdrop) |
1259 | 1.00M | { |
1260 | | /* Our new buffer is buf */ |
1261 | 1.00M | pdf14_buf *buf = ctx->stack; |
1262 | | |
1263 | 1.00M | *is_backdrop = false; |
1264 | | |
1265 | 1.00M | if (buf != NULL) { |
1266 | | /* If the new buffer is isolated there is no backdrop */ |
1267 | 1.00M | if (buf->isolated) return NULL; |
1268 | | |
1269 | | /* If the previous buffer is a knockout group |
1270 | | then we need to use its backdrop as the backdrop. If |
1271 | | it was isolated then that back drop was NULL */ |
1272 | 436k | if (buf->saved != NULL && buf->saved->knockout) { |
1273 | | /* Per the spec, if we have a non-isolated group |
1274 | | in a knockout group the non-isolated group |
1275 | | uses the backdrop of its parent group (the knockout group) |
1276 | | as its own backdrop. The non-isolated group must |
1277 | | go through the standard re-composition operation |
1278 | | to avoid the double application of the backdrop */ |
1279 | 27 | *is_backdrop = true; |
1280 | 27 | return buf->saved; |
1281 | 27 | } |
1282 | | /* This should be the non-isolated case where its parent is |
1283 | | not a knockout */ |
1284 | 436k | if (buf->saved != NULL) { |
1285 | 436k | return buf->saved; |
1286 | 436k | } |
1287 | 436k | } |
1288 | 0 | return NULL; |
1289 | 1.00M | } |
1290 | | |
1291 | | static pdf14_group_color_t* |
1292 | | pdf14_make_base_group_color(gx_device* dev) |
1293 | 612k | { |
1294 | 612k | pdf14_device* pdev = (pdf14_device*)dev; |
1295 | 612k | pdf14_group_color_t* group_color; |
1296 | 612k | bool deep = pdev->ctx->deep; |
1297 | 612k | bool has_tags = device_encodes_tags(dev); |
1298 | | |
1299 | 612k | if_debug0m('v', dev->memory, "[v]pdf14_make_base_group_color\n"); |
1300 | | |
1301 | 612k | group_color = gs_alloc_struct(pdev->ctx->memory, |
1302 | 612k | pdf14_group_color_t, &st_pdf14_clr, |
1303 | 612k | "pdf14_make_base_group_color"); |
1304 | | |
1305 | 612k | if (group_color == NULL) |
1306 | 0 | return NULL; |
1307 | 612k | memset(group_color, 0, sizeof(pdf14_group_color_t)); |
1308 | | |
1309 | 612k | group_color->num_std_colorants = pdev->num_std_colorants; |
1310 | 612k | group_color->blend_procs = pdev->blend_procs; |
1311 | 612k | group_color->polarity = pdev->color_info.polarity; |
1312 | 612k | group_color->num_components = pdev->color_info.num_components - has_tags; |
1313 | 612k | group_color->isadditive = pdev->ctx->additive; |
1314 | 612k | group_color->unpack_procs = pdev->pdf14_procs; |
1315 | 612k | group_color->max_color = pdev->color_info.max_color = deep ? 65535 : 255; |
1316 | 612k | group_color->max_gray = pdev->color_info.max_gray = deep ? 65535 : 255; |
1317 | 612k | group_color->depth = pdev->color_info.depth; |
1318 | 612k | group_color->decode = dev_proc(pdev, decode_color); |
1319 | 612k | group_color->encode = dev_proc(pdev, encode_color); |
1320 | 612k | group_color->group_color_mapping_procs = dev_proc(pdev, get_color_mapping_procs); |
1321 | 612k | group_color->group_color_comp_index = dev_proc(pdev, get_color_comp_index); |
1322 | 612k | memcpy(&(group_color->comp_bits), &(pdev->color_info.comp_bits), |
1323 | 612k | GX_DEVICE_COLOR_MAX_COMPONENTS); |
1324 | 612k | memcpy(&(group_color->comp_shift), &(pdev->color_info.comp_shift), |
1325 | 612k | GX_DEVICE_COLOR_MAX_COMPONENTS); |
1326 | 612k | group_color->get_cmap_procs = pdf14_get_cmap_procs; |
1327 | 612k | group_color->icc_profile = |
1328 | 612k | pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE]; |
1329 | 612k | gsicc_adjust_profile_rc(group_color->icc_profile, 1, "pdf14_make_base_group_color"); |
1330 | | |
1331 | 612k | return group_color; |
1332 | 612k | } |
1333 | | |
1334 | | /* This wil create the first buffer when we have |
1335 | | either the first drawing operation or transparency |
1336 | | group push. At that time, the color space in which |
1337 | | we are going to be doing the alpha blend will be known. */ |
1338 | | static int |
1339 | | pdf14_initialize_ctx(gx_device* dev, const gs_gstate* pgs) |
1340 | 409M | { |
1341 | 409M | pdf14_device *pdev = (pdf14_device *)dev; |
1342 | 409M | bool has_tags = device_encodes_tags(dev); |
1343 | 409M | int n_chan = pdev->color_info.num_components - has_tags; |
1344 | 409M | bool additive = pdev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE; |
1345 | 409M | int num_spots = pdev->ctx->num_spots; |
1346 | 409M | pdf14_buf* buf; |
1347 | 409M | gs_memory_t* memory = dev->memory->stable_memory; |
1348 | | |
1349 | | /* Check for a blank idle group as a base group */ |
1350 | 409M | if (pdev->ctx->stack != NULL && pdev->ctx->stack->group_popped && |
1351 | 0 | pdev->ctx->stack->idle) { |
1352 | 0 | pdf14_buf_free(pdev->ctx->stack); |
1353 | 0 | pdev->ctx->stack = NULL; |
1354 | 0 | } |
1355 | | |
1356 | 409M | if (pdev->ctx->stack != NULL) |
1357 | 409M | return 0; |
1358 | | |
1359 | 409M | if_debug2m('v', dev->memory, "[v]pdf14_initialize_ctx: width = %d, height = %d\n", |
1360 | 541k | dev->width, dev->height); |
1361 | | |
1362 | 541k | buf = pdf14_buf_new(&(pdev->ctx->rect), has_tags, false, false, false, n_chan + 1, |
1363 | 541k | num_spots, memory, pdev->ctx->deep); |
1364 | 541k | if (buf == NULL) { |
1365 | 0 | return gs_error_VMerror; |
1366 | 0 | } |
1367 | 541k | if_debug5m('v', memory, |
1368 | 541k | "[v]base buf: %d x %d, %d color channels, %d planes, deep=%d\n", |
1369 | 541k | buf->rect.q.x, buf->rect.q.y, buf->n_chan, buf->n_planes, pdev->ctx->deep); |
1370 | | |
1371 | 541k | memset(buf->data, 0, buf->planestride * (buf->n_planes - !!has_tags)); |
1372 | 541k | buf->saved = NULL; |
1373 | 541k | pdev->ctx->stack = buf; |
1374 | 541k | pdev->ctx->additive = additive; |
1375 | | |
1376 | | /* Every buffer needs group color information including the base |
1377 | | one that is created for when we have no group */ |
1378 | 541k | buf->group_color_info = gs_alloc_struct(pdev->memory->stable_memory, |
1379 | 541k | pdf14_group_color_t, &st_pdf14_clr, "pdf14_initialize_ctx"); |
1380 | 541k | if (buf->group_color_info == NULL) |
1381 | 0 | return gs_error_VMerror; |
1382 | | |
1383 | 541k | if (pgs != NULL) |
1384 | 277k | buf->group_color_info->get_cmap_procs = pgs->get_cmap_procs; |
1385 | 263k | else |
1386 | 263k | buf->group_color_info->get_cmap_procs = pdf14_get_cmap_procs; |
1387 | | |
1388 | 541k | buf->group_color_info->group_color_mapping_procs = |
1389 | 541k | dev_proc(pdev, get_color_mapping_procs); |
1390 | 541k | buf->group_color_info->group_color_comp_index = |
1391 | 541k | dev_proc(pdev, get_color_comp_index); |
1392 | 541k | buf->group_color_info->blend_procs = pdev->blend_procs; |
1393 | 541k | buf->group_color_info->polarity = pdev->color_info.polarity; |
1394 | 541k | buf->group_color_info->num_components = pdev->color_info.num_components - has_tags; |
1395 | 541k | buf->group_color_info->isadditive = pdev->ctx->additive; |
1396 | 541k | buf->group_color_info->unpack_procs = pdev->pdf14_procs; |
1397 | 541k | buf->group_color_info->depth = pdev->color_info.depth; |
1398 | 541k | buf->group_color_info->max_color = pdev->color_info.max_color; |
1399 | 541k | buf->group_color_info->max_gray = pdev->color_info.max_gray; |
1400 | 541k | buf->group_color_info->encode = dev_proc(pdev, encode_color); |
1401 | 541k | buf->group_color_info->decode = dev_proc(pdev, decode_color); |
1402 | 541k | memcpy(&(buf->group_color_info->comp_bits), &(pdev->color_info.comp_bits), |
1403 | 541k | GX_DEVICE_COLOR_MAX_COMPONENTS); |
1404 | 541k | memcpy(&(buf->group_color_info->comp_shift), &(pdev->color_info.comp_shift), |
1405 | 541k | GX_DEVICE_COLOR_MAX_COMPONENTS); |
1406 | 541k | buf->group_color_info->previous = NULL; /* used during clist writing */ |
1407 | 541k | buf->group_color_info->icc_profile = |
1408 | 541k | pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE]; |
1409 | 541k | if (buf->group_color_info->icc_profile != NULL) |
1410 | 541k | gsicc_adjust_profile_rc(buf->group_color_info->icc_profile, 1, "pdf14_initialize_ctx"); |
1411 | | |
1412 | 541k | return 0; |
1413 | 541k | } |
1414 | | |
1415 | | static pdf14_group_color_t* |
1416 | | pdf14_clone_group_color_info(gx_device* pdev, pdf14_group_color_t* src) |
1417 | 19.9k | { |
1418 | 19.9k | pdf14_group_color_t* des = gs_alloc_struct(pdev->memory->stable_memory, |
1419 | 19.9k | pdf14_group_color_t, &st_pdf14_clr, "pdf14_clone_group_color_info"); |
1420 | 19.9k | if (des == NULL) |
1421 | 0 | return NULL; |
1422 | | |
1423 | 19.9k | memcpy(des, src, sizeof(pdf14_group_color_t)); |
1424 | 19.9k | if (des->icc_profile != NULL) |
1425 | 19.9k | gsicc_adjust_profile_rc(des->icc_profile, 1, "pdf14_clone_group_color_info"); |
1426 | 19.9k | des->previous = NULL; /* used during clist writing for state stack */ |
1427 | | |
1428 | 19.9k | return des; |
1429 | 19.9k | } |
1430 | | |
1431 | | static int |
1432 | | pdf14_push_transparency_group(pdf14_ctx *ctx, gs_int_rect *rect, bool isolated, |
1433 | | bool knockout, uint16_t alpha, uint16_t shape, uint16_t opacity, |
1434 | | gs_blend_mode_t blend_mode, bool idle, uint mask_id, |
1435 | | int numcomps, bool cm_back_drop, bool shade_group, |
1436 | | cmm_profile_t *group_profile, cmm_profile_t *tos_profile, |
1437 | | pdf14_group_color_t* group_color, gs_gstate *pgs, |
1438 | | gx_device *dev) |
1439 | 2.30M | { |
1440 | 2.30M | pdf14_buf *tos = ctx->stack; |
1441 | 2.30M | pdf14_buf *buf, * pdf14_backdrop; |
1442 | 2.30M | bool has_shape = false; |
1443 | 2.30M | bool is_backdrop; |
1444 | 2.30M | int num_spots; |
1445 | | |
1446 | 2.30M | if_debug1m('v', ctx->memory, |
1447 | 2.30M | "[v]pdf14_push_transparency_group, idle = %d\n", idle); |
1448 | | |
1449 | 2.30M | if (tos != NULL) |
1450 | 1.86M | has_shape = tos->has_shape || tos->knockout; |
1451 | | |
1452 | 2.30M | if (ctx->smask_depth > 0) |
1453 | 962 | num_spots = 0; |
1454 | 2.30M | else |
1455 | 2.30M | num_spots = ctx->num_spots; |
1456 | | |
1457 | | |
1458 | 2.30M | buf = pdf14_buf_new(rect, ctx->has_tags, !isolated, has_shape, idle, numcomps + 1, |
1459 | 2.30M | num_spots, ctx->memory, ctx->deep); |
1460 | 2.30M | if (buf == NULL) |
1461 | 0 | return_error(gs_error_VMerror); |
1462 | | |
1463 | 2.30M | if_debug4m('v', ctx->memory, |
1464 | 2.30M | "[v]base buf: %d x %d, %d color channels, %d planes\n", |
1465 | 2.30M | buf->rect.q.x, buf->rect.q.y, buf->n_chan, buf->n_planes); |
1466 | 2.30M | buf->isolated = isolated; |
1467 | 2.30M | buf->knockout = knockout; |
1468 | 2.30M | buf->alpha = alpha; |
1469 | 2.30M | buf->shape = shape; |
1470 | 2.30M | buf->opacity = opacity; |
1471 | 2.30M | buf->blend_mode = blend_mode; |
1472 | 2.30M | buf->mask_id = mask_id; |
1473 | 2.30M | buf->mask_stack = ctx->mask_stack; /* Save because the group rendering may |
1474 | | set up another (nested) mask. */ |
1475 | 2.30M | ctx->mask_stack = NULL; /* Clean the mask field for rendering this group. |
1476 | | See pdf14_pop_transparency_group how to handle it. */ |
1477 | 2.30M | buf->saved = tos; |
1478 | 2.30M | buf->group_color_info = group_color; |
1479 | | |
1480 | 2.30M | if (tos == NULL) |
1481 | 436k | buf->page_group = true; |
1482 | | |
1483 | 2.30M | ctx->stack = buf; |
1484 | 2.30M | if (buf->data == NULL) |
1485 | 1.30M | return 0; |
1486 | 1.00M | if (idle) |
1487 | 0 | return 0; |
1488 | 1.00M | pdf14_backdrop = pdf14_find_backdrop_buf(ctx, &is_backdrop); |
1489 | | |
1490 | | /* Initializes buf->data with the backdrop or as opaque */ |
1491 | 1.00M | if (pdf14_backdrop == NULL || (is_backdrop && pdf14_backdrop->backdrop == NULL)) { |
1492 | | /* Note, don't clear out tags set by pdf14_buf_new == GS_UNKNOWN_TAG */ |
1493 | | /* Memsetting by 0, so this copes with the deep case too */ |
1494 | 565k | memset(buf->data, 0, buf->planestride * |
1495 | 565k | (buf->n_chan + |
1496 | 565k | (buf->has_shape ? 1 : 0) + |
1497 | 565k | (buf->has_alpha_g ? 1 : 0))); |
1498 | 565k | } else { |
1499 | 436k | if (!cm_back_drop) { |
1500 | 436k | pdf14_preserve_backdrop(buf, pdf14_backdrop, is_backdrop |
1501 | | #if RAW_DUMP |
1502 | | , ctx->memory |
1503 | | #endif |
1504 | 436k | ); |
1505 | 436k | } else { |
1506 | | /* We must have an non-isolated group with a mismatch in color spaces. |
1507 | | In this case, we can't just copy the buffer but must CM it */ |
1508 | 0 | pdf14_preserve_backdrop_cm(buf, group_profile, pdf14_backdrop, tos_profile, |
1509 | 0 | ctx->memory, pgs, dev, is_backdrop); |
1510 | 0 | } |
1511 | 436k | } |
1512 | | |
1513 | | /* If our new group is a non-isolated knockout group, we have to maintain |
1514 | | a copy of the backdrop in case we are drawing nonisolated groups on top of the |
1515 | | knockout group. They have to always blend with the groups backdrop |
1516 | | not what is currently drawn in the group. Selection of the backdrop |
1517 | | depends upon the properties of the parent group. For example, if |
1518 | | the parent itself is a knockout group we actually |
1519 | | need to blend with its backdrop. This could be NULL if the parent was |
1520 | | an isolated knockout group. */ |
1521 | 1.00M | if (buf->knockout && pdf14_backdrop != NULL) { |
1522 | 39.3k | buf->backdrop = gs_alloc_bytes(ctx->memory, |
1523 | 39.3k | buf->planestride * buf->n_planes + CAL_SLOP, |
1524 | 39.3k | "pdf14_push_transparency_group"); |
1525 | 39.3k | if (buf->backdrop == NULL) { |
1526 | 0 | return gs_throw(gs_error_VMerror, "Knockout backdrop allocation failed"); |
1527 | 0 | } |
1528 | | |
1529 | 39.3k | memcpy(buf->backdrop, buf->data, |
1530 | 39.3k | buf->planestride * buf->n_planes); |
1531 | | |
1532 | | #if RAW_DUMP |
1533 | | /* Dump the current buffer to see what we have. */ |
1534 | | dump_raw_buffer(ctx->memory, |
1535 | | ctx->stack->rect.q.y - ctx->stack->rect.p.y, |
1536 | | ctx->stack->rowstride >> buf->deep, buf->n_planes, |
1537 | | ctx->stack->planestride, ctx->stack->rowstride, |
1538 | | "KnockoutBackDrop", buf->backdrop, buf->deep); |
1539 | | global_index++; |
1540 | | #endif |
1541 | 39.3k | } |
1542 | | #if RAW_DUMP |
1543 | | /* Dump the current buffer to see what we have. */ |
1544 | | dump_raw_buffer(ctx->memory, |
1545 | | ctx->stack->rect.q.y-ctx->stack->rect.p.y, |
1546 | | ctx->stack->rowstride>>buf->deep, ctx->stack->n_planes, |
1547 | | ctx->stack->planestride, ctx->stack->rowstride, |
1548 | | "TransGroupPush", ctx->stack->data, buf->deep); |
1549 | | global_index++; |
1550 | | #endif |
1551 | 1.00M | return 0; |
1552 | 1.00M | } |
1553 | | |
1554 | | static int |
1555 | | pdf14_pop_transparency_group(gs_gstate *pgs, pdf14_ctx *ctx, |
1556 | | const pdf14_nonseparable_blending_procs_t * pblend_procs, |
1557 | | int tos_num_color_comp, cmm_profile_t *curr_icc_profile, gx_device *dev) |
1558 | 2.30M | { |
1559 | 2.30M | pdf14_buf *tos = ctx->stack; |
1560 | 2.30M | pdf14_buf *nos = tos->saved; |
1561 | 2.30M | pdf14_mask_t *mask_stack = tos->mask_stack; |
1562 | 2.30M | pdf14_buf *maskbuf; |
1563 | 2.30M | int x0, x1, y0, y1; |
1564 | 2.30M | int nos_num_color_comp; |
1565 | 2.30M | bool no_icc_match; |
1566 | 2.30M | pdf14_device *pdev = (pdf14_device *)dev; |
1567 | 2.30M | bool overprint = pdev->overprint; |
1568 | 2.30M | gx_color_index drawn_comps = pdev->drawn_comps_stroke | pdev->drawn_comps_fill; |
1569 | 2.30M | bool has_matte = false; |
1570 | 2.30M | int code = 0; |
1571 | | |
1572 | | #ifdef DEBUG |
1573 | | pdf14_debug_mask_stack_state(ctx); |
1574 | | #endif |
1575 | 2.30M | maskbuf = (mask_stack == NULL) ? NULL : mask_stack->mask_buf; |
1576 | 2.30M | if (maskbuf != NULL && maskbuf->matte != NULL) |
1577 | 3.84k | has_matte = true; |
1578 | | |
1579 | | /* Check if this is our last buffer, if yes, there is nothing to |
1580 | | compose to. Keep this buffer until we have the put image. |
1581 | | If we have another group push, this group must be destroyed. |
1582 | | This only occurs sometimes when at clist creation time |
1583 | | push_shfill_group occured and nothing was drawn in this group. |
1584 | | There is also the complication if we have a softmask. There |
1585 | | are two approaches to this problem. Apply the softmask during |
1586 | | the put image or handle it now. I choose the later as the |
1587 | | put_image code is already way to complicated. */ |
1588 | 2.30M | if (nos == NULL && maskbuf == NULL) { |
1589 | 435k | tos->group_popped = true; |
1590 | 435k | return 0; |
1591 | 435k | } |
1592 | | |
1593 | | /* Here is the case with the soft mask. Go ahead and create a new |
1594 | | target buffer (nos) with the same color information etc, but blank |
1595 | | and go ahead and do the blend with the softmask so that it gets applied. */ |
1596 | 1.86M | if (nos == NULL && maskbuf != NULL) { |
1597 | 0 | nos = pdf14_buf_new(&(tos->rect), ctx->has_tags, !tos->isolated, tos->has_shape, |
1598 | 0 | tos->idle, tos->n_chan, tos->num_spots, ctx->memory, ctx->deep); |
1599 | 0 | if (nos == NULL) { |
1600 | 0 | code = gs_error_VMerror; |
1601 | 0 | goto exit; |
1602 | 0 | } |
1603 | | |
1604 | 0 | if_debug4m('v', ctx->memory, |
1605 | 0 | "[v] special buffer for softmask application: %d x %d, %d color channels, %d planes\n", |
1606 | 0 | nos->rect.q.x, nos->rect.q.y, nos->n_chan, nos->n_planes); |
1607 | |
|
1608 | 0 | nos->dirty = tos->dirty; |
1609 | 0 | nos->isolated = tos->isolated; |
1610 | 0 | nos->knockout = tos->knockout; |
1611 | 0 | nos->alpha = 65535; |
1612 | 0 | nos->shape = 65535; |
1613 | 0 | nos->opacity = 65535; |
1614 | 0 | nos->blend_mode = tos->blend_mode; |
1615 | 0 | nos->mask_id = tos->mask_id; |
1616 | 0 | nos->group_color_info = pdf14_clone_group_color_info(dev, tos->group_color_info); |
1617 | |
|
1618 | 0 | if (nos->data != NULL) |
1619 | 0 | memset(nos->data, 0, |
1620 | 0 | nos->planestride * (nos->n_chan + |
1621 | 0 | (nos->has_shape ? 1 : 0) + |
1622 | 0 | (nos->has_alpha_g ? 1 : 0))); |
1623 | 0 | } |
1624 | | |
1625 | | /* Before we get started, lets see if we have somehow gotten into |
1626 | | what should be an impossible situation where the group color |
1627 | | information does not match the buffer color information. This |
1628 | | can occur is there were memory issues that have perhaps blown |
1629 | | away information, or in the example of Bug 705197 the PDF interpreter |
1630 | | reuses a pattern during a circular reference causing an aliasing |
1631 | | of two nested patterns, one of which has a softmask. The change in |
1632 | | the buffer size of the inner one blows away the buffer of the |
1633 | | outer one leading to a mismatch of color spaces. Here |
1634 | | we can at least catch the case when the color space sizes have |
1635 | | changed and avoid buffer over-runs that would occur when we try |
1636 | | to do the group composition */ |
1637 | 1.86M | if (nos->n_chan - 1 != nos->group_color_info->num_components || |
1638 | 1.86M | tos->n_chan - 1 != tos_num_color_comp) |
1639 | 0 | return_error(gs_error_Fatal); |
1640 | | |
1641 | 1.86M | nos_num_color_comp = nos->group_color_info->num_components - tos->num_spots; |
1642 | 1.86M | tos_num_color_comp = tos_num_color_comp - tos->num_spots; |
1643 | | |
1644 | | /* Sanitise the dirty rectangles, in case some of the drawing routines |
1645 | | * have made them overly large. */ |
1646 | 1.86M | rect_intersect(tos->dirty, tos->rect); |
1647 | 1.86M | rect_intersect(nos->dirty, nos->rect); |
1648 | | /* dirty = the marked bbox. rect = the entire bounds of the buffer. */ |
1649 | | /* Everything marked on tos that fits onto nos needs to be merged down. */ |
1650 | 1.86M | y0 = max(tos->dirty.p.y, nos->rect.p.y); |
1651 | 1.86M | y1 = min(tos->dirty.q.y, nos->rect.q.y); |
1652 | 1.86M | x0 = max(tos->dirty.p.x, nos->rect.p.x); |
1653 | 1.86M | x1 = min(tos->dirty.q.x, nos->rect.q.x); |
1654 | 1.86M | if (ctx->mask_stack) { |
1655 | | /* This can occur when we have a situation where we are ending out of |
1656 | | a group that has internal to it a soft mask and another group. |
1657 | | The soft mask left over from the previous trans group pop is put |
1658 | | into ctx->masbuf, since it is still active if another trans group |
1659 | | push occurs to use it. If one does not occur, but instead we find |
1660 | | ourselves popping from a parent group, then this softmask is no |
1661 | | longer needed. We will rc_decrement and set it to NULL. */ |
1662 | 99 | rc_decrement(ctx->mask_stack, "pdf14_pop_transparency_group"); |
1663 | 99 | ctx->mask_stack = NULL; |
1664 | 99 | } |
1665 | 1.86M | ctx->mask_stack = mask_stack; /* Restore the mask saved by pdf14_push_transparency_group. */ |
1666 | 1.86M | tos->mask_stack = NULL; /* Clean the pointer sinse the mask ownership is now passed to ctx. */ |
1667 | 1.86M | if (tos->idle) |
1668 | 1.27M | goto exit; |
1669 | 596k | if (maskbuf != NULL && maskbuf->data == NULL && maskbuf->alpha == 255) |
1670 | 0 | goto exit; |
1671 | | |
1672 | | #if RAW_DUMP |
1673 | | /* Dump the current buffer to see what we have. */ |
1674 | | dump_raw_buffer(ctx->memory, |
1675 | | ctx->stack->rect.q.y-ctx->stack->rect.p.y, |
1676 | | ctx->stack->rowstride>>ctx->stack->deep, ctx->stack->n_planes, |
1677 | | ctx->stack->planestride, ctx->stack->rowstride, |
1678 | | "aaTrans_Group_Pop", ctx->stack->data, ctx->stack->deep); |
1679 | | global_index++; |
1680 | | #endif |
1681 | | /* Note currently if a pattern space has transparency, the ICC profile is not used |
1682 | | for blending purposes. Instead we rely upon the gray, rgb, or cmyk parent space. |
1683 | | This is partially due to the fact that pdf14_pop_transparency_group and |
1684 | | pdf14_push_transparnecy_group have no real ICC interaction and those are the |
1685 | | operations called in the tile transparency code. Instead we may want to |
1686 | | look at pdf14_begin_transparency_group and pdf14_end_transparency group which |
1687 | | is where all the ICC information is handled. We will return to look at that later */ |
1688 | 596k | if (nos->group_color_info->icc_profile != NULL) { |
1689 | 596k | no_icc_match = !gsicc_profiles_equal(nos->group_color_info->icc_profile, curr_icc_profile); |
1690 | 596k | } else { |
1691 | | /* Let the other tests make the decision if we need to transform */ |
1692 | 0 | no_icc_match = false; |
1693 | 0 | } |
1694 | | /* If the color spaces are different and we actually did do a swap of |
1695 | | the procs for color */ |
1696 | 596k | if ((nos->group_color_info->group_color_mapping_procs != NULL && |
1697 | 596k | nos_num_color_comp != tos_num_color_comp) || no_icc_match) { |
1698 | 4.00k | if (x0 < x1 && y0 < y1) { |
1699 | 3.58k | pdf14_buf *result; |
1700 | 3.58k | bool did_alloc; /* We don't care here */ |
1701 | | |
1702 | 3.58k | if (has_matte) { |
1703 | 1.66k | result = pdf14_transform_color_buffer_with_matte(pgs, ctx, dev, |
1704 | 1.66k | tos, tos->data, curr_icc_profile, nos->group_color_info->icc_profile, |
1705 | 1.66k | tos->rect.p.x, tos->rect.p.y, tos->rect.q.x - tos->rect.p.x, |
1706 | 1.66k | tos->rect.q.y - tos->rect.p.y, &did_alloc, tos->deep, false); |
1707 | 1.66k | has_matte = false; |
1708 | 1.92k | } else { |
1709 | 1.92k | result = pdf14_transform_color_buffer_no_matte(pgs, ctx, dev, |
1710 | 1.92k | tos, tos->data, curr_icc_profile, nos->group_color_info->icc_profile, |
1711 | 1.92k | tos->rect.p.x, tos->rect.p.y, tos->rect.q.x - tos->rect.p.x, |
1712 | 1.92k | tos->rect.q.y - tos->rect.p.y, &did_alloc, tos->deep, false, false); |
1713 | 1.92k | } |
1714 | 3.58k | if (result == NULL) { |
1715 | | /* Clean up and return error code */ |
1716 | 0 | code = gs_error_unknownerror; |
1717 | 0 | goto exit; |
1718 | 0 | } |
1719 | | |
1720 | | #if RAW_DUMP |
1721 | | /* Dump the current buffer to see what we have. */ |
1722 | | dump_raw_buffer(ctx->memory, |
1723 | | ctx->stack->rect.q.y-ctx->stack->rect.p.y, |
1724 | | ctx->stack->rowstride>>ctx->stack->deep, ctx->stack->n_chan, |
1725 | | ctx->stack->planestride, ctx->stack->rowstride, |
1726 | | "aCMTrans_Group_ColorConv", ctx->stack->data, |
1727 | | ctx->stack->deep); |
1728 | | #endif |
1729 | | /* compose. never do overprint in this case */ |
1730 | 3.58k | pdf14_compose_group(tos, nos, maskbuf, x0, x1, y0, y1, nos->n_chan, |
1731 | 3.58k | nos->group_color_info->isadditive, |
1732 | 3.58k | nos->group_color_info->blend_procs, |
1733 | 3.58k | has_matte, false, drawn_comps, ctx->memory, dev); |
1734 | 3.58k | } |
1735 | 592k | } else { |
1736 | | /* Group color spaces are the same. No color conversions needed */ |
1737 | 592k | if (x0 < x1 && y0 < y1) |
1738 | 371k | pdf14_compose_group(tos, nos, maskbuf, x0, x1, y0, y1, nos->n_chan, |
1739 | 371k | ctx->additive, pblend_procs, has_matte, overprint, |
1740 | 371k | drawn_comps, ctx->memory, dev); |
1741 | 592k | } |
1742 | 1.86M | exit: |
1743 | 1.86M | ctx->stack = nos; |
1744 | | /* We want to detect the cases where we have luminosity soft masks embedded |
1745 | | within one another. The "alpha" channel really needs to be merged into |
1746 | | the luminosity channel in this case. This will occur during the mask pop */ |
1747 | 1.86M | if (ctx->smask_depth > 0 && maskbuf != NULL) { |
1748 | | /* Set the trigger so that we will blend if not alpha. Since |
1749 | | we have softmasks embedded in softmasks */ |
1750 | 701 | ctx->smask_blend = true; |
1751 | 701 | } |
1752 | 1.86M | if_debug1m('v', ctx->memory, "[v]pop buf, idle=%d\n", tos->idle); |
1753 | 1.86M | pdf14_buf_free(tos); |
1754 | 1.86M | if (code < 0) |
1755 | 0 | return_error(code); |
1756 | 1.86M | return 0; |
1757 | 1.86M | } |
1758 | | |
1759 | | /* |
1760 | | * Create a transparency mask that will be used as the mask for |
1761 | | * the next transparency group that is created afterwards. |
1762 | | * The sequence of calls is: |
1763 | | * push_mask, draw the mask, pop_mask, push_group, draw the group, pop_group |
1764 | | */ |
1765 | | static int |
1766 | | pdf14_push_transparency_mask(pdf14_ctx *ctx, gs_int_rect *rect, uint16_t bg_alpha, |
1767 | | byte *transfer_fn, bool is_ident, bool idle, |
1768 | | bool replacing, uint mask_id, |
1769 | | gs_transparency_mask_subtype_t subtype, |
1770 | | int numcomps, int Background_components, |
1771 | | const float Background[], int Matte_components, |
1772 | | const float Matte[], const float GrayBackground, |
1773 | | pdf14_group_color_t* group_color) |
1774 | 433k | { |
1775 | 433k | pdf14_buf *buf; |
1776 | 433k | int i; |
1777 | | |
1778 | 433k | if_debug2m('v', ctx->memory, |
1779 | 433k | "[v]pdf14_push_transparency_mask, idle=%d, replacing=%d\n", |
1780 | 433k | idle, replacing); |
1781 | 433k | ctx->smask_depth += 1; |
1782 | | |
1783 | 433k | if (ctx->stack == NULL) { |
1784 | 0 | return_error(gs_error_VMerror); |
1785 | 0 | } |
1786 | | |
1787 | | /* An optimization to consider is that if the SubType is Alpha |
1788 | | then we really should only be allocating the alpha band and |
1789 | | only draw with that channel. Current architecture makes that |
1790 | | a bit tricky. We need to create this based upon the size of |
1791 | | the color space + an alpha channel. NOT the device size |
1792 | | or the previous ctx size */ |
1793 | | /* A mask doesn't worry about tags */ |
1794 | 433k | buf = pdf14_buf_new(rect, false, false, false, idle, numcomps + 1, 0, |
1795 | 433k | ctx->memory, ctx->deep); |
1796 | 433k | if (buf == NULL) |
1797 | 0 | return_error(gs_error_VMerror); |
1798 | 433k | buf->alpha = bg_alpha; |
1799 | 433k | buf->is_ident = is_ident; |
1800 | | /* fill in, but these values aren't really used */ |
1801 | 433k | buf->isolated = true; |
1802 | 433k | buf->knockout = false; |
1803 | 433k | buf->shape = 0xffff; |
1804 | 433k | buf->blend_mode = BLEND_MODE_Normal; |
1805 | 433k | buf->transfer_fn = transfer_fn; |
1806 | 433k | buf->matte_num_comps = Matte_components; |
1807 | 433k | buf->group_color_info = group_color; |
1808 | | |
1809 | 433k | if (Matte_components) { |
1810 | 3.84k | buf->matte = (uint16_t *)gs_alloc_bytes(ctx->memory, Matte_components * sizeof(uint16_t) + CAL_SLOP, |
1811 | 3.84k | "pdf14_push_transparency_mask"); |
1812 | 3.84k | if (buf->matte == NULL) |
1813 | 0 | return_error(gs_error_VMerror); |
1814 | 15.3k | for (i = 0; i < Matte_components; i++) { |
1815 | 11.5k | buf->matte[i] = (uint16_t) floor(Matte[i] * 65535.0 + 0.5); |
1816 | 11.5k | } |
1817 | 3.84k | } |
1818 | 433k | buf->mask_id = mask_id; |
1819 | | /* If replacing=false, we start the mask for an image with SMask. |
1820 | | In this case the image's SMask temporary replaces the |
1821 | | mask of the containing group. Save the containing droup's mask |
1822 | | in buf->mask_stack */ |
1823 | 433k | buf->mask_stack = ctx->mask_stack; |
1824 | 433k | if (buf->mask_stack) |
1825 | 433k | rc_increment(buf->mask_stack); |
1826 | | #if RAW_DUMP |
1827 | | /* Dump the current buffer to see what we have. */ |
1828 | | if (ctx->stack->planestride > 0 ){ |
1829 | | dump_raw_buffer(ctx->memory, |
1830 | | ctx->stack->rect.q.y-ctx->stack->rect.p.y, |
1831 | | ctx->stack->rowstride>>ctx->stack->deep, ctx->stack->n_planes, |
1832 | | ctx->stack->planestride, ctx->stack->rowstride, |
1833 | | "Raw_Buf_PreSmask", ctx->stack->data, ctx->stack->deep); |
1834 | | global_index++; |
1835 | | } |
1836 | | #endif |
1837 | 433k | buf->saved = ctx->stack; |
1838 | 433k | ctx->stack = buf; |
1839 | | /* Soft Mask related information so we know how to |
1840 | | compute luminosity when we pop the soft mask */ |
1841 | 433k | buf->SMask_SubType = subtype; |
1842 | 433k | if (buf->data != NULL) { |
1843 | | /* We need to initialize it to the BC if it existed */ |
1844 | | /* According to the spec, the CS has to be the same */ |
1845 | | /* If the back ground component is black, then don't bother |
1846 | | with this. Since we are forcing the rendering to gray |
1847 | | earlier now, go ahead and just use the GrayBackGround color |
1848 | | directly. */ |
1849 | 277k | if ( Background_components && GrayBackground != 0.0 ) { |
1850 | 266 | if (buf->deep) { |
1851 | 0 | uint16_t gray = (uint16_t) (65535.0 * GrayBackground); |
1852 | 0 | gs_memset16(buf->data, gray, buf->planestride); |
1853 | | /* If we have a background component that was not black, then we |
1854 | | need to set the alpha for this mask as if we had drawn in the |
1855 | | entire soft mask buffer */ |
1856 | 0 | gs_memset16(buf->data + buf->planestride, 65535, |
1857 | 0 | buf->planestride *(buf->n_chan - 1)); |
1858 | 266 | } else { |
1859 | 266 | unsigned char gray = (unsigned char) (255.0 * GrayBackground); |
1860 | 266 | memset(buf->data, gray, buf->planestride); |
1861 | | /* If we have a background component that was not black, then we |
1862 | | need to set the alpha for this mask as if we had drawn in the |
1863 | | entire soft mask buffer */ |
1864 | 266 | memset(buf->data + buf->planestride, 255, |
1865 | 266 | buf->planestride * (buf->n_chan - 1)); |
1866 | 266 | } |
1867 | 277k | } else { |
1868 | | /* Compose mask with opaque background */ |
1869 | 277k | memset(buf->data, 0, buf->planestride * buf->n_chan); |
1870 | 277k | } |
1871 | 277k | } |
1872 | 433k | return 0; |
1873 | 433k | } |
1874 | | |
1875 | | static int |
1876 | | pdf14_pop_transparency_mask(pdf14_ctx *ctx, gs_gstate *pgs, gx_device *dev) |
1877 | 433k | { |
1878 | 433k | pdf14_buf* tos = ctx->stack; |
1879 | 433k | pdf14_buf* nos = tos->saved; |
1880 | 433k | byte *new_data_buf; |
1881 | 433k | int icc_match; |
1882 | 433k | cmm_profile_t *des_profile = nos->group_color_info->icc_profile; /* If set, this should be a gray profile */ |
1883 | 433k | cmm_profile_t *src_profile; |
1884 | 433k | gsicc_rendering_param_t rendering_params; |
1885 | 433k | gsicc_link_t *icc_link; |
1886 | 433k | gsicc_rendering_param_t render_cond; |
1887 | 433k | cmm_dev_profile_t *dev_profile; |
1888 | 433k | int code = 0; |
1889 | | |
1890 | 433k | dev_proc(dev, get_profile)(dev, &dev_profile); |
1891 | 433k | gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &src_profile, |
1892 | 433k | &render_cond); |
1893 | 433k | ctx->smask_depth -= 1; |
1894 | | /* icc_match == -1 means old non-icc code. |
1895 | | icc_match == 0 means use icc code |
1896 | | icc_match == 1 mean no conversion needed */ |
1897 | 433k | if (des_profile != NULL && src_profile != NULL ) { |
1898 | 433k | icc_match = gsicc_profiles_equal(des_profile, src_profile); |
1899 | 433k | } else { |
1900 | 0 | icc_match = -1; |
1901 | 0 | } |
1902 | 433k | if_debug1m('v', ctx->memory, "[v]pdf14_pop_transparency_mask, idle=%d\n", |
1903 | 433k | tos->idle); |
1904 | 433k | ctx->stack = tos->saved; |
1905 | 433k | tos->saved = NULL; /* To avoid issues with GC */ |
1906 | 433k | if (tos->mask_stack) { |
1907 | | /* During the soft mask push, the mask_stack was copied (not moved) from |
1908 | | the ctx to the tos mask_stack. We are done with this now so it is safe to |
1909 | | just set to NULL. However, before we do that we must perform |
1910 | | rc decrement to match the increment that occured was made. Also, |
1911 | | if this is the last ref count of the rc_mask, we should free the |
1912 | | buffer now since no other groups need it. */ |
1913 | 114k | rc_decrement(tos->mask_stack, "pdf14_pop_transparency_mask"); |
1914 | 114k | tos->mask_stack = NULL; |
1915 | 114k | } |
1916 | | |
1917 | 433k | if (tos->data == NULL ) { |
1918 | | /* This can occur in clist rendering if the soft mask does |
1919 | | not intersect the current band. It would be nice to |
1920 | | catch this earlier and just avoid creating the structure |
1921 | | to begin with. For now we need to delete the structure |
1922 | | that was created. Only delete if the alpha value is 65535 */ |
1923 | 156k | if (ctx->mask_stack != NULL) { |
1924 | 47.7k | rc_decrement(ctx->mask_stack, "pdf14_free_mask_stack"); |
1925 | 47.7k | ctx->mask_stack = NULL; |
1926 | 47.7k | } |
1927 | 156k | if ((tos->alpha == 65535 && tos->is_ident) || |
1928 | 156k | (!tos->is_ident && (tos->transfer_fn[tos->alpha>>8] == 255))) { |
1929 | 4.83k | pdf14_buf_free(tos); |
1930 | 151k | } else { |
1931 | | /* Assign as mask buffer */ |
1932 | 151k | ctx->mask_stack = pdf14_mask_element_new(ctx->memory); |
1933 | 151k | if (ctx->mask_stack == NULL) |
1934 | 0 | return gs_note_error(gs_error_VMerror); |
1935 | 151k | ctx->mask_stack->mask_buf = tos; |
1936 | 151k | } |
1937 | 156k | ctx->smask_blend = false; /* just in case */ |
1938 | 277k | } else { |
1939 | | /* If we are already in the source space then there is no reason |
1940 | | to do the transformation */ |
1941 | | /* Lets get this to a monochrome buffer and map it to a luminance only value */ |
1942 | | /* This will reduce our memory. We won't reuse the existing one, due */ |
1943 | | /* Due to the fact that on certain systems we may have issues recovering */ |
1944 | | /* the data after a resize */ |
1945 | 277k | new_data_buf = gs_alloc_bytes(ctx->memory, tos->planestride + CAL_SLOP, |
1946 | 277k | "pdf14_pop_transparency_mask"); |
1947 | 277k | if (new_data_buf == NULL) |
1948 | 0 | return_error(gs_error_VMerror); |
1949 | | /* Initialize with 0. Need to do this since in Smask_Luminosity_Mapping |
1950 | | we won't be filling everything during the remap if it had not been |
1951 | | written into by the PDF14 fill rect */ |
1952 | 277k | memset(new_data_buf, 0, tos->planestride); |
1953 | | /* If the subtype was alpha, then just grab the alpha channel now |
1954 | | and we are all done */ |
1955 | 277k | if (tos->SMask_SubType == TRANSPARENCY_MASK_Alpha) { |
1956 | 40.5k | ctx->smask_blend = false; /* not used in this case */ |
1957 | 40.5k | smask_copy(tos->rect.q.y - tos->rect.p.y, |
1958 | 40.5k | (tos->rect.q.x - tos->rect.p.x)<<tos->deep, |
1959 | 40.5k | tos->rowstride, |
1960 | 40.5k | (tos->data)+tos->planestride, new_data_buf); |
1961 | | #if RAW_DUMP |
1962 | | /* Dump the current buffer to see what we have. */ |
1963 | | dump_raw_buffer(ctx->memory, |
1964 | | tos->rect.q.y-tos->rect.p.y, |
1965 | | tos->rowstride>>tos->deep, 1, |
1966 | | tos->planestride, tos->rowstride, |
1967 | | "SMask_Pop_Alpha(Mask_Plane1)",tos->data, |
1968 | | tos->deep); |
1969 | | global_index++; |
1970 | | #endif |
1971 | 236k | } else { |
1972 | 236k | if (icc_match == 1 || tos->n_chan == 2) { |
1973 | | #if RAW_DUMP |
1974 | | /* Dump the current buffer to see what we have. */ |
1975 | | dump_raw_buffer(ctx->memory, |
1976 | | tos->rect.q.y-tos->rect.p.y, |
1977 | | tos->rowstride>>tos->deep, tos->n_planes, |
1978 | | tos->planestride, tos->rowstride, |
1979 | | "SMask_Pop_Lum(Mask_Plane0)",tos->data, |
1980 | | tos->deep); |
1981 | | global_index++; |
1982 | | #endif |
1983 | | /* There is no need to color convert. Data is already gray scale. |
1984 | | We just need to copy the gray plane. However it is |
1985 | | possible that the soft mask could have a soft mask which |
1986 | | would end us up with some alpha blending information |
1987 | | (Bug691803). In fact, according to the spec, the alpha |
1988 | | blending has to occur. See FTS test fts_26_2601.pdf |
1989 | | for an example of this. Softmask buffer is intialized |
1990 | | with BG values. It would be nice to keep track if buffer |
1991 | | ever has a alpha value not 1 so that we could detect and |
1992 | | avoid this blend if not needed. */ |
1993 | 236k | smask_blend(tos->data, tos->rect.q.x - tos->rect.p.x, |
1994 | 236k | tos->rect.q.y - tos->rect.p.y, tos->rowstride, |
1995 | 236k | tos->planestride, tos->deep); |
1996 | | #if RAW_DUMP |
1997 | | /* Dump the current buffer to see what we have. */ |
1998 | | dump_raw_buffer(ctx->memory, |
1999 | | tos->rect.q.y-tos->rect.p.y, |
2000 | | tos->rowstride>>tos->deep, 1, |
2001 | | tos->planestride, tos->rowstride, |
2002 | | "SMask_Pop_Lum_Post_Blend",tos->data, |
2003 | | tos->deep); |
2004 | | global_index++; |
2005 | | #endif |
2006 | 236k | smask_copy(tos->rect.q.y - tos->rect.p.y, |
2007 | 236k | (tos->rect.q.x - tos->rect.p.x)<<tos->deep, |
2008 | 236k | tos->rowstride, tos->data, new_data_buf); |
2009 | 236k | } else { |
2010 | 0 | if ( icc_match == -1 ) { |
2011 | | /* The slow old fashioned way */ |
2012 | 0 | smask_luminosity_mapping(tos->rect.q.y - tos->rect.p.y , |
2013 | 0 | tos->rect.q.x - tos->rect.p.x,tos->n_chan, |
2014 | 0 | tos->rowstride, tos->planestride, |
2015 | 0 | tos->data, new_data_buf, ctx->additive, tos->SMask_SubType, |
2016 | 0 | tos->deep |
2017 | | #if RAW_DUMP |
2018 | | , ctx->memory |
2019 | | #endif |
2020 | 0 | ); |
2021 | 0 | } else { |
2022 | | /* ICC case where we use the CMM */ |
2023 | | /* Request the ICC link for the transform that we will need to use */ |
2024 | 0 | rendering_params.black_point_comp = gsBLACKPTCOMP_OFF; |
2025 | 0 | rendering_params.graphics_type_tag = GS_IMAGE_TAG; |
2026 | 0 | rendering_params.override_icc = false; |
2027 | 0 | rendering_params.preserve_black = gsBKPRESNOTSPECIFIED; |
2028 | 0 | rendering_params.rendering_intent = gsRELATIVECOLORIMETRIC; |
2029 | 0 | rendering_params.cmm = gsCMM_DEFAULT; |
2030 | 0 | icc_link = gsicc_get_link_profile(pgs, dev, des_profile, |
2031 | 0 | src_profile, &rendering_params, pgs->memory, false); |
2032 | 0 | code = smask_icc(dev, tos->rect.q.y - tos->rect.p.y, |
2033 | 0 | tos->rect.q.x - tos->rect.p.x, tos->n_chan, |
2034 | 0 | tos->rowstride, tos->planestride, |
2035 | 0 | tos->data, new_data_buf, icc_link, tos->deep); |
2036 | | /* Release the link */ |
2037 | 0 | gsicc_release_link(icc_link); |
2038 | 0 | } |
2039 | 0 | } |
2040 | 236k | } |
2041 | | /* Free the old object, NULL test was above */ |
2042 | 277k | gs_free_object(ctx->memory, tos->data, "pdf14_pop_transparency_mask"); |
2043 | 277k | tos->data = new_data_buf; |
2044 | | /* Data is single channel now */ |
2045 | 277k | tos->n_chan = 1; |
2046 | 277k | tos->n_planes = 1; |
2047 | | /* Assign as reference counted mask buffer */ |
2048 | 277k | if (ctx->mask_stack != NULL) { |
2049 | | /* In this case, the source file is wacky as it already had a |
2050 | | softmask and now is getting a replacement. We need to clean |
2051 | | up the softmask stack before doing this free and creating |
2052 | | a new stack. Bug 693312 */ |
2053 | 66.8k | rc_decrement(ctx->mask_stack, "pdf14_pop_transparency_mask(ctx->mask_stack)"); |
2054 | 66.8k | } |
2055 | 277k | ctx->mask_stack = pdf14_mask_element_new(ctx->memory); |
2056 | 277k | if (ctx->mask_stack == NULL) |
2057 | 0 | return gs_note_error(gs_error_VMerror); |
2058 | 277k | ctx->mask_stack->mask_buf = tos; |
2059 | 277k | } |
2060 | 433k | return code; |
2061 | 433k | } |
2062 | | |
2063 | | static void |
2064 | | rc_pdf14_mask_element_free(gs_memory_t * mem, void *ptr_in, client_name_t cname) |
2065 | 1.56M | { |
2066 | | /* Ending the mask buffer. */ |
2067 | 1.56M | pdf14_mask_t *mask = (pdf14_mask_t *)ptr_in; |
2068 | | /* free the pdf14 buffer. */ |
2069 | 1.56M | if (mask->mask_buf != NULL) { |
2070 | 90.7k | pdf14_buf_free(mask->mask_buf); |
2071 | 90.7k | } |
2072 | 1.56M | gs_free_object(mem, mask, "rc_pdf14_mask_element_free"); |
2073 | 1.56M | } |
2074 | | |
2075 | | static pdf14_mask_t * |
2076 | | pdf14_mask_element_new(gs_memory_t *memory) |
2077 | 1.57M | { |
2078 | 1.57M | pdf14_mask_t *result; |
2079 | | |
2080 | 1.57M | result = gs_alloc_struct(memory, pdf14_mask_t, &st_pdf14_mask, |
2081 | 1.57M | "pdf14_mask_element_new"); |
2082 | 1.57M | if (result == NULL) |
2083 | 0 | return NULL; |
2084 | | |
2085 | 1.57M | rc_init_free(result, memory, 1, rc_pdf14_mask_element_free); |
2086 | | |
2087 | 1.57M | result->mask_buf = NULL; |
2088 | 1.57M | result->memory = memory; |
2089 | 1.57M | result->previous = NULL; |
2090 | | |
2091 | 1.57M | return result; |
2092 | 1.57M | } |
2093 | | |
2094 | | static int |
2095 | | pdf14_push_transparency_state(gx_device *dev, gs_gstate *pgs) |
2096 | 0 | { |
2097 | | /* We need to push the current soft mask. We need to |
2098 | | be able to recover it if we draw a new one and |
2099 | | then obtain a Q operation ( a pop ) */ |
2100 | |
|
2101 | 0 | pdf14_device *pdev = (pdf14_device *)dev; |
2102 | 0 | pdf14_ctx *ctx = pdev->ctx; |
2103 | 0 | pdf14_mask_t *new_mask; |
2104 | |
|
2105 | 0 | if_debug0m('v', ctx->memory, "pdf14_push_transparency_state\n"); |
2106 | | /* We need to push the current mask buffer */ |
2107 | | /* Allocate a new element for the stack. |
2108 | | Don't do anything if there is no mask present.*/ |
2109 | 0 | if (ctx->mask_stack != NULL) { |
2110 | 0 | new_mask = pdf14_mask_element_new(ctx->memory); |
2111 | 0 | if (new_mask == NULL) |
2112 | 0 | return gs_note_error(gs_error_VMerror); |
2113 | 0 | new_mask->previous = ctx->mask_stack; |
2114 | 0 | ctx->mask_stack = new_mask; |
2115 | 0 | } |
2116 | | #ifdef DEBUG |
2117 | | pdf14_debug_mask_stack_state(pdev->ctx); |
2118 | | #endif |
2119 | 0 | return 0; |
2120 | 0 | } |
2121 | | |
2122 | | static int |
2123 | | pdf14_pop_transparency_state(gx_device *dev, gs_gstate *pgs) |
2124 | 3.03M | { |
2125 | | /* Pop the soft mask. It is no longer needed. Likely due to |
2126 | | a Q that has occurred. */ |
2127 | 3.03M | pdf14_device *pdev = (pdf14_device *)dev; |
2128 | 3.03M | pdf14_ctx *ctx = pdev->ctx; |
2129 | 3.03M | pdf14_mask_t *old_mask; |
2130 | | |
2131 | 3.03M | if_debug0m('v', ctx->memory, "pdf14_pop_transparency_state\n"); |
2132 | | /* rc decrement the current link after we break it from |
2133 | | the list, then free the stack element. Don't do |
2134 | | anything if there is no mask present. */ |
2135 | 3.03M | if (ctx->mask_stack != NULL) { |
2136 | 466k | old_mask = ctx->mask_stack; |
2137 | 466k | ctx->mask_stack = ctx->mask_stack->previous; |
2138 | 466k | rc_decrement(old_mask, "pdf14_pop_transparency_state"); |
2139 | | /* We need to have some special handling here for when we have nested |
2140 | | soft masks. There may be a copy in the stack that we may need to |
2141 | | adjust. */ |
2142 | 466k | if (ctx->smask_depth > 0) { |
2143 | 756 | if (ctx->stack != NULL && ctx->stack->mask_stack != NULL) { |
2144 | 756 | ctx->stack->mask_stack = ctx->mask_stack; |
2145 | 756 | } |
2146 | 756 | } |
2147 | 466k | } |
2148 | | #ifdef DEBUG |
2149 | | pdf14_debug_mask_stack_state(pdev->ctx); |
2150 | | #endif |
2151 | 3.03M | return 0; |
2152 | 3.03M | } |
2153 | | |
2154 | | static int |
2155 | | pdf14_open(gx_device *dev) |
2156 | 1.14M | { |
2157 | 1.14M | pdf14_device *pdev = (pdf14_device *)dev; |
2158 | | |
2159 | | /* If we are reenabling the device dont create a new ctx. Bug 697456 */ |
2160 | 1.14M | if (pdev->ctx == NULL) { |
2161 | 1.14M | bool has_tags = device_encodes_tags(dev); |
2162 | 1.14M | int bits_per_comp = (dev->color_info.depth / dev->color_info.num_components); |
2163 | 1.14M | pdev->ctx = pdf14_ctx_new(dev, bits_per_comp > 8); |
2164 | 1.14M | if (pdev->ctx == NULL) |
2165 | 0 | return_error(gs_error_VMerror); |
2166 | | |
2167 | 1.14M | pdev->ctx->rect.p.x = 0; |
2168 | 1.14M | pdev->ctx->rect.p.y = 0; |
2169 | 1.14M | pdev->ctx->rect.q.x = dev->width; |
2170 | 1.14M | pdev->ctx->rect.q.y = dev->height; |
2171 | 1.14M | pdev->ctx->has_tags = has_tags; |
2172 | 1.14M | pdev->ctx->num_spots = pdev->color_info.num_components - has_tags - pdev->num_std_colorants; |
2173 | | /* This can happen because pdev->num_std_colorants is not updated when pdev->color_info.num_components |
2174 | | * is. I am not sure how to fix that. */ |
2175 | 1.14M | if (pdev->ctx->num_spots < 0) |
2176 | 0 | pdev->ctx->num_spots = 0; |
2177 | 1.14M | pdev->ctx->additive = (pdev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE); |
2178 | 1.14M | } |
2179 | 1.14M | pdev->free_devicen = true; |
2180 | 1.14M | pdev->text_group = PDF14_TEXTGROUP_NO_BT; |
2181 | 1.14M | return 0; |
2182 | 1.14M | } |
2183 | | |
2184 | | static const gx_cm_color_map_procs pdf14_DeviceCMYKspot_procs = { |
2185 | | pdf14_gray_cs_to_cmyk_cm, pdf14_rgb_cs_to_cmyk_cm, pdf14_cmyk_cs_to_cmyk_cm |
2186 | | }; |
2187 | | |
2188 | | static const gx_cm_color_map_procs pdf14_DeviceRGBspot_procs = { |
2189 | | pdf14_gray_cs_to_rgbspot_cm, pdf14_rgb_cs_to_rgbspot_cm, pdf14_cmyk_cs_to_rgbspot_cm |
2190 | | }; |
2191 | | |
2192 | | static const gx_cm_color_map_procs pdf14_DeviceGrayspot_procs = { |
2193 | | pdf14_gray_cs_to_grayspot_cm, pdf14_rgb_cs_to_grayspot_cm, pdf14_cmyk_cs_to_grayspot_cm |
2194 | | }; |
2195 | | |
2196 | | static const gx_cm_color_map_procs * |
2197 | | pdf14_cmykspot_get_color_mapping_procs(const gx_device * dev, const gx_device **tdev) |
2198 | 3.01M | { |
2199 | 3.01M | *tdev = dev; |
2200 | 3.01M | return &pdf14_DeviceCMYKspot_procs; |
2201 | 3.01M | } |
2202 | | |
2203 | | static const gx_cm_color_map_procs * |
2204 | | pdf14_rgbspot_get_color_mapping_procs(const gx_device * dev, const gx_device **tdev) |
2205 | 3.01M | { |
2206 | 3.01M | *tdev = dev; |
2207 | 3.01M | return &pdf14_DeviceRGBspot_procs; |
2208 | 3.01M | } |
2209 | | |
2210 | | static const gx_cm_color_map_procs * |
2211 | | pdf14_grayspot_get_color_mapping_procs(const gx_device * dev, const gx_device **tdev) |
2212 | 0 | { |
2213 | 0 | *tdev = dev; |
2214 | 0 | return &pdf14_DeviceGrayspot_procs; |
2215 | 0 | } |
2216 | | |
2217 | | static void |
2218 | | be_rev_cpy(uint16_t *dst,const uint16_t *src,int n) |
2219 | 0 | { |
2220 | 0 | for (; n != 0; n--) { |
2221 | 0 | uint16_t in = *src++; |
2222 | 0 | ((byte *)dst)[0] = in>>8; |
2223 | 0 | ((byte *)dst)[1] = in; |
2224 | 0 | dst++; |
2225 | 0 | } |
2226 | 0 | } |
2227 | | |
2228 | | /* Used to pass along information about the buffer created by the |
2229 | | pdf14 device. This is used by the pattern accumulator when the |
2230 | | pattern contains transparency. Note that if free_device is true then |
2231 | | we need to go ahead and get the buffer data copied and free up the |
2232 | | device. This only occurs at the end of a pattern accumulation operation */ |
2233 | | int |
2234 | | pdf14_get_buffer_information(const gx_device * dev, |
2235 | | gx_pattern_trans_t *transbuff, gs_memory_t *mem, |
2236 | | bool free_device) |
2237 | 24.8k | { |
2238 | 24.8k | const pdf14_device * pdev = (pdf14_device *)dev; |
2239 | 24.8k | pdf14_buf *buf; |
2240 | 24.8k | gs_int_rect rect; |
2241 | 24.8k | int x1,y1,width,height; |
2242 | | |
2243 | 24.8k | if ( pdev->ctx == NULL){ |
2244 | 0 | return 0; /* this can occur if the pattern is a clist */ |
2245 | 0 | } |
2246 | | #ifdef DEBUG |
2247 | | pdf14_debug_mask_stack_state(pdev->ctx); |
2248 | | #endif |
2249 | 24.8k | buf = pdev->ctx->stack; |
2250 | 24.8k | rect = buf->rect; |
2251 | 24.8k | transbuff->buf = (free_device ? NULL : buf); |
2252 | 24.8k | x1 = min(pdev->width, rect.q.x); |
2253 | 24.8k | y1 = min(pdev->height, rect.q.y); |
2254 | 24.8k | width = x1 - rect.p.x; |
2255 | 24.8k | height = y1 - rect.p.y; |
2256 | | |
2257 | 24.8k | transbuff->n_chan = buf->n_chan; |
2258 | 24.8k | transbuff->has_tags = buf->has_tags; |
2259 | 24.8k | transbuff->has_shape = buf->has_shape; |
2260 | 24.8k | transbuff->width = buf->rect.q.x - buf->rect.p.x; |
2261 | 24.8k | transbuff->height = buf->rect.q.y - buf->rect.p.y; |
2262 | 24.8k | transbuff->deep = buf->deep; |
2263 | | |
2264 | 24.8k | if (width <= 0 || height <= 0 || buf->data == NULL) { |
2265 | 8.81k | transbuff->planestride = 0; |
2266 | 8.81k | transbuff->rowstride = 0; |
2267 | 8.81k | return 0; |
2268 | 8.81k | } |
2269 | | |
2270 | 16.0k | if (free_device) { |
2271 | 4.84k | transbuff->pdev14 = NULL; |
2272 | 4.84k | transbuff->rect = rect; |
2273 | 4.84k | if ((width < transbuff->width) || (height < transbuff->height)) { |
2274 | | /* If the bbox is smaller than the whole buffer than go ahead and |
2275 | | create a new one to use. This can occur if we drew in a smaller |
2276 | | area than was specified by the transparency group rect. */ |
2277 | 0 | intptr_t rowstride = ((width + 3) & -4)<<buf->deep; |
2278 | 0 | intptr_t planestride = rowstride * height; |
2279 | 0 | int k, j; |
2280 | 0 | byte *buff_ptr_src, *buff_ptr_des; |
2281 | |
|
2282 | 0 | transbuff->planestride = planestride; |
2283 | 0 | transbuff->rowstride = rowstride; |
2284 | 0 | transbuff->transbytes = |
2285 | 0 | gs_alloc_bytes(mem, |
2286 | 0 | planestride * |
2287 | 0 | (buf->n_chan + |
2288 | 0 | buf->has_tags ? 1 : 0) + CAL_SLOP, |
2289 | 0 | "pdf14_get_buffer_information"); |
2290 | 0 | if (transbuff->transbytes == NULL) |
2291 | 0 | return gs_error_VMerror; |
2292 | | |
2293 | 0 | transbuff->mem = mem; |
2294 | 0 | if (transbuff->deep) { |
2295 | 0 | for (j = 0; j < transbuff->n_chan; j++) { |
2296 | 0 | buff_ptr_src = buf->data + j * buf->planestride + |
2297 | 0 | buf->rowstride * rect.p.y + (rect.p.x<<buf->deep); |
2298 | 0 | buff_ptr_des = transbuff->transbytes + j * planestride; |
2299 | 0 | for (k = 0; k < height; k++) { |
2300 | 0 | be_rev_cpy((uint16_t *)buff_ptr_des, (const uint16_t *)buff_ptr_src, rowstride>>1); |
2301 | 0 | buff_ptr_des += rowstride; |
2302 | 0 | buff_ptr_src += buf->rowstride; |
2303 | 0 | } |
2304 | 0 | } |
2305 | 0 | } else { |
2306 | 0 | for (j = 0; j < transbuff->n_chan; j++) { |
2307 | 0 | buff_ptr_src = buf->data + j * buf->planestride + |
2308 | 0 | buf->rowstride * rect.p.y + (rect.p.x<<buf->deep); |
2309 | 0 | buff_ptr_des = transbuff->transbytes + j * planestride; |
2310 | 0 | for (k = 0; k < height; k++) { |
2311 | 0 | memcpy(buff_ptr_des, buff_ptr_src, rowstride); |
2312 | 0 | buff_ptr_des += rowstride; |
2313 | 0 | buff_ptr_src += buf->rowstride; |
2314 | 0 | } |
2315 | 0 | } |
2316 | 0 | } |
2317 | |
|
2318 | 4.84k | } else { |
2319 | | /* The entire buffer is used. Go ahead and grab the pointer and |
2320 | | clear the pointer in the pdf14 device data buffer so it is not |
2321 | | freed when we close the device */ |
2322 | 4.84k | transbuff->planestride = buf->planestride; |
2323 | 4.84k | transbuff->rowstride = buf->rowstride; |
2324 | 4.84k | transbuff->transbytes = buf->data; |
2325 | 4.84k | transbuff->mem = buf->memory; |
2326 | 4.84k | buf->data = NULL; /* So that the buffer is not freed */ |
2327 | 4.84k | if (transbuff->deep) { |
2328 | | /* We have the data in native endian. We need it in big endian. Do an in-place conversion. */ |
2329 | | /* FIXME: This is a nop on big endian machines. Is the compiler smart enough to spot that? */ |
2330 | 0 | uint16_t *buff_ptr; |
2331 | 0 | int j, k, z; |
2332 | 0 | intptr_t rowstride = transbuff->rowstride>>1; |
2333 | 0 | intptr_t planestride = transbuff->planestride; |
2334 | 0 | for (j = 0; j < transbuff->n_chan; j++) { |
2335 | 0 | buff_ptr = (uint16_t *)(transbuff->transbytes + j * planestride); |
2336 | 0 | for (k = 0; k < height; k++) { |
2337 | 0 | for (z = 0; z < width; z++) { |
2338 | 0 | uint16_t in = buff_ptr[z]; |
2339 | 0 | ((byte *)(&buff_ptr[z]))[0] = in>>8; |
2340 | 0 | ((byte *)(&buff_ptr[z]))[1] = in; |
2341 | 0 | } |
2342 | 0 | buff_ptr += rowstride; |
2343 | 0 | } |
2344 | 0 | } |
2345 | 0 | } |
2346 | 4.84k | } |
2347 | | #if RAW_DUMP |
2348 | | /* Dump the buffer that should be going into the pattern */; |
2349 | | dump_raw_buffer_be(buf->memory, |
2350 | | height, width, transbuff->n_chan, |
2351 | | transbuff->planestride, transbuff->rowstride, |
2352 | | "pdf14_pattern_buff", transbuff->transbytes, |
2353 | | transbuff->deep); |
2354 | | global_index++; |
2355 | | #endif |
2356 | | /* Go ahead and free up the pdf14 device */ |
2357 | 4.84k | dev_proc(dev, close_device)((gx_device *)dev); |
2358 | 11.1k | } else { |
2359 | | /* Here we are coming from one of the fill image / pattern / mask |
2360 | | operations */ |
2361 | 11.1k | transbuff->pdev14 = dev; |
2362 | 11.1k | transbuff->planestride = buf->planestride; |
2363 | 11.1k | transbuff->rowstride = buf->rowstride; |
2364 | 11.1k | transbuff->transbytes = buf->data; |
2365 | 11.1k | transbuff->mem = buf->memory; |
2366 | 11.1k | transbuff->rect = rect; |
2367 | | #if RAW_DUMP |
2368 | | /* Dump the buffer that should be going into the pattern */; |
2369 | | dump_raw_buffer(buf->memory, |
2370 | | height, width, buf->n_chan, |
2371 | | pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride, |
2372 | | "pdf14_pattern_buff", |
2373 | | buf->data, |
2374 | | transbuff->deep); |
2375 | | global_index++; |
2376 | | #endif |
2377 | 11.1k | } |
2378 | 16.0k | return 0; |
2379 | 16.0k | } |
2380 | | |
2381 | | typedef void (blend_image_row_proc_t) (const byte *gs_restrict buf_ptr, |
2382 | | intptr_t planestride, int width, int num_comp, uint16_t bg, byte *gs_restrict linebuf); |
2383 | | |
2384 | | |
2385 | | static int |
2386 | | pdf14_put_image_color_convert(const pdf14_device* dev, gs_gstate* pgs, cmm_profile_t* src_profile, |
2387 | | cmm_dev_profile_t* dev_target_profile, pdf14_buf** buf, |
2388 | | byte** buf_ptr, bool was_blended, int x, int y, int width, int height, int num_channels_to_lose) |
2389 | 8.15k | { |
2390 | 8.15k | pdf14_buf* cm_result = NULL; |
2391 | 8.15k | cmm_profile_t* des_profile; |
2392 | 8.15k | gsicc_rendering_param_t render_cond; |
2393 | 8.15k | bool did_alloc; |
2394 | 8.15k | bool endian_swap; |
2395 | | |
2396 | 8.15k | gsicc_extract_profile(GS_UNKNOWN_TAG, dev_target_profile, &des_profile, |
2397 | 8.15k | &render_cond); |
2398 | | |
2399 | | #if RAW_DUMP |
2400 | | #if !ARCH_IS_BIG_ENDIAN |
2401 | | if (was_blended && (*buf)->deep) |
2402 | | dump_raw_buffer_be(dev->ctx->memory, |
2403 | | height, width, (*buf)->n_planes, (*buf)->planestride, |
2404 | | (*buf)->rowstride, "pdf14_put_image_color_convert_pre", *buf_ptr, (*buf)->deep); |
2405 | | else |
2406 | | #endif |
2407 | | dump_raw_buffer(dev->ctx->memory, |
2408 | | height, width, (*buf)->n_planes, (*buf)->planestride, |
2409 | | (*buf)->rowstride, "pdf14_put_image_color_convert_pre", *buf_ptr, (*buf)->deep); |
2410 | | global_index++; |
2411 | | #endif |
2412 | | |
2413 | | /* If we are doing a 16 bit buffer it will be big endian if we have already done the |
2414 | | blend, otherwise it will be native endian. GS expects its 16bit buffers to be BE |
2415 | | but for sanity pdf14 device maintains 16bit buffers in native format. The CMM |
2416 | | will need to know if it is dealing with native or BE data. */ |
2417 | 8.15k | if (was_blended && (*buf)->deep) { |
2418 | | /* Data is in BE. If we are in a LE machine, CMM will need to swap for |
2419 | | color conversion */ |
2420 | | #if ARCH_IS_BIG_ENDIAN |
2421 | | endian_swap = false; |
2422 | | #else |
2423 | 0 | endian_swap = true; |
2424 | 0 | #endif |
2425 | 8.15k | } else { |
2426 | | /* Data is in native format. No swap needed for CMM */ |
2427 | 8.15k | endian_swap = false; |
2428 | 8.15k | } |
2429 | | |
2430 | 8.15k | cm_result = pdf14_transform_color_buffer_no_matte(pgs, dev->ctx, (gx_device*) dev, *buf, |
2431 | 8.15k | *buf_ptr, src_profile, des_profile, x, y, width, |
2432 | 8.15k | height, &did_alloc, (*buf)->deep, endian_swap, num_channels_to_lose); |
2433 | | |
2434 | 8.15k | if (cm_result == NULL) |
2435 | 0 | return_error(gs_error_VMerror); |
2436 | | |
2437 | | /* Update */ |
2438 | 8.15k | *buf = cm_result; |
2439 | | |
2440 | | /* Make sure our buf_ptr is pointing to the proper location */ |
2441 | 8.15k | if (did_alloc) |
2442 | 8.15k | *buf_ptr = cm_result->data; /* Note the lack of offset */ |
2443 | | |
2444 | | #if RAW_DUMP |
2445 | | dump_raw_buffer(dev->ctx->memory, |
2446 | | height, width, (*buf)->n_planes, (*buf)->planestride, |
2447 | | (*buf)->rowstride, "pdf14_put_image_color_convert_post", *buf_ptr, (*buf)->deep); |
2448 | | global_index++; |
2449 | | #endif |
2450 | 8.15k | return 0; |
2451 | 8.15k | } |
2452 | | |
2453 | | /** |
2454 | | * pdf14_put_image: Put rendered image to target device. |
2455 | | * @pdev: The PDF 1.4 rendering device. |
2456 | | * @pgs: State for image draw operation. |
2457 | | * @target: The target device. |
2458 | | * |
2459 | | * Puts the rendered image in @pdev's buffer to @target. This is called |
2460 | | * as part of the sequence of popping the PDF 1.4 device filter. |
2461 | | * |
2462 | | * Return code: negative on error. |
2463 | | **/ |
2464 | | static int |
2465 | | pdf14_put_image(gx_device * dev, gs_gstate * pgs, gx_device * target) |
2466 | 1.06M | { |
2467 | 1.06M | const pdf14_device * pdev = (pdf14_device *)dev; |
2468 | 1.06M | int code; |
2469 | 1.06M | gs_image1_t image; |
2470 | 1.06M | gx_image_enum_common_t *info; |
2471 | 1.06M | pdf14_buf *buf = pdev->ctx->stack; |
2472 | 1.06M | gs_int_rect rect; |
2473 | 1.06M | int y; |
2474 | 1.06M | int num_comp; |
2475 | 1.06M | byte *linebuf, *linebuf_unaligned; |
2476 | 1.06M | gs_color_space *pcs; |
2477 | 1.06M | int x1, y1, width, height; |
2478 | 1.06M | byte *buf_ptr; |
2479 | 1.06M | int num_rows_left; |
2480 | 1.06M | cmm_profile_t* src_profile = NULL; |
2481 | 1.06M | cmm_profile_t* des_profile = NULL; |
2482 | 1.06M | cmm_dev_profile_t *pdf14dev_profile; |
2483 | 1.06M | cmm_dev_profile_t *dev_target_profile; |
2484 | 1.06M | uint16_t bg; |
2485 | 1.06M | bool has_tags = device_encodes_tags(dev); |
2486 | 1.06M | bool deep = pdev->ctx->deep; |
2487 | 1.06M | intptr_t planestride; |
2488 | 1.06M | intptr_t rowstride; |
2489 | 1.06M | blend_image_row_proc_t *blend_row; |
2490 | 1.06M | bool color_mismatch = false; |
2491 | 1.06M | bool supports_alpha = false; |
2492 | 1.06M | int i; |
2493 | 1.06M | int alpha_offset, tag_offset; |
2494 | 1.06M | const byte* buf_ptrs[GS_CLIENT_COLOR_MAX_COMPONENTS]; |
2495 | 1.06M | int rendering_intent_saved; |
2496 | 1.06M | int additive; |
2497 | | |
2498 | | /* Nothing was ever drawn. */ |
2499 | 1.06M | if (buf == NULL) |
2500 | 132k | return 0; |
2501 | | |
2502 | 928k | additive = buf->group_color_info->isadditive; |
2503 | | |
2504 | 928k | src_profile = buf->group_color_info->icc_profile; |
2505 | | |
2506 | 928k | num_comp = buf->n_chan - 1; |
2507 | 928k | rect = buf->rect; |
2508 | 928k | planestride = buf->planestride; |
2509 | 928k | rowstride = buf->rowstride; |
2510 | | |
2511 | | /* Make sure that this is the only item on the stack. Fuzzing revealed a |
2512 | | potential problem. Bug 694190 */ |
2513 | 928k | if (buf->saved != NULL) { |
2514 | 226 | return gs_throw(gs_error_unknownerror, "PDF14 device push/pop out of sync"); |
2515 | 226 | } |
2516 | 928k | if_debug0m('v', dev->memory, "[v]pdf14_put_image\n"); |
2517 | 928k | rect_intersect(rect, buf->dirty); |
2518 | 928k | x1 = min(pdev->width, rect.q.x); |
2519 | 928k | y1 = min(pdev->height, rect.q.y); |
2520 | 928k | width = x1 - rect.p.x; |
2521 | 928k | height = y1 - rect.p.y; |
2522 | | #ifdef DUMP_TO_PNG |
2523 | | dump_planar_rgba(pdev->memory, buf); |
2524 | | #endif |
2525 | 928k | if (width <= 0 || height <= 0 || buf->data == NULL) |
2526 | 234k | return 0; |
2527 | 693k | buf_ptr = buf->data + (rect.p.y - buf->rect.p.y) * buf->rowstride + ((rect.p.x - buf->rect.p.x) << deep); |
2528 | | |
2529 | | /* Check that target is OK. From fuzzing results the target could have been |
2530 | | destroyed, for e.g if it were a pattern accumulator that was closed |
2531 | | prematurely (Bug 694154). We should always be able to to get an ICC |
2532 | | profile from the target. */ |
2533 | 693k | code = dev_proc(target, get_profile)(target, &dev_target_profile); |
2534 | 693k | if (code < 0) |
2535 | 0 | return code; |
2536 | 693k | if (dev_target_profile == NULL) |
2537 | 0 | return gs_throw_code(gs_error_Fatal); |
2538 | | |
2539 | 693k | if (src_profile == NULL) { |
2540 | 0 | code = dev_proc(dev, get_profile)(dev, &pdf14dev_profile); |
2541 | 0 | if (code < 0) { |
2542 | 0 | return code; |
2543 | 0 | } |
2544 | 0 | src_profile = pdf14dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]; |
2545 | 0 | } |
2546 | | |
2547 | | /* Check if we have a color conversion issue */ |
2548 | 693k | des_profile = dev_target_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]; |
2549 | 693k | if (!gsicc_profiles_equal(des_profile, src_profile)) |
2550 | 116k | color_mismatch = true; |
2551 | | |
2552 | | /* Check if target supports alpha */ |
2553 | 693k | supports_alpha = dev_proc(target, dev_spec_op)(target, gxdso_supports_alpha, NULL, 0); |
2554 | 693k | code = 0; |
2555 | | |
2556 | | #if RAW_DUMP |
2557 | | dump_raw_buffer(pdev->ctx->memory, height, width, buf->n_planes, |
2558 | | pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride, |
2559 | | "pre_final_blend", buf_ptr, deep); |
2560 | | #endif |
2561 | | |
2562 | | /* Note. The logic below will need a little rework if we ever |
2563 | | have a device that has tags and alpha support */ |
2564 | 693k | if (supports_alpha) { |
2565 | 0 | if (!color_mismatch) { |
2566 | 0 | alpha_offset = num_comp; |
2567 | 0 | tag_offset = buf->has_tags ? buf->n_chan : 0; |
2568 | |
|
2569 | 0 | for (i = 0; i < buf->n_planes; i++) |
2570 | 0 | buf_ptrs[i] = buf_ptr + i * planestride; |
2571 | 0 | for (; i < target->color_info.num_components; i++) |
2572 | 0 | buf_ptrs[i] = 0; |
2573 | 0 | code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp, |
2574 | 0 | rect.p.x, rect.p.y, width, height, |
2575 | 0 | rowstride, alpha_offset, |
2576 | 0 | tag_offset); |
2577 | | /* Right now code has number of rows written */ |
2578 | 0 | } else { |
2579 | | /* In this case, just color convert and maintain alpha. This is a case |
2580 | | where we either either blend in the right color space and have no |
2581 | | alpha for the output device or hand back the wrong color space with |
2582 | | alpha data. We choose the later. */ |
2583 | 0 | code = pdf14_put_image_color_convert(pdev, pgs, src_profile, |
2584 | 0 | dev_target_profile, &buf, &buf_ptr, false, rect.p.x, rect.p.y, |
2585 | 0 | width, height, false); |
2586 | 0 | if (code < 0) |
2587 | 0 | return code; |
2588 | | |
2589 | | /* reset */ |
2590 | 0 | rowstride = buf->rowstride; |
2591 | 0 | planestride = buf->planestride; |
2592 | 0 | num_comp = buf->n_chan - 1; |
2593 | 0 | alpha_offset = num_comp; |
2594 | 0 | tag_offset = buf->has_tags ? buf->n_chan : 0; |
2595 | | |
2596 | | /* And then out */ |
2597 | 0 | for (i = 0; i < buf->n_planes; i++) |
2598 | 0 | buf_ptrs[i] = buf_ptr + i * planestride; |
2599 | 0 | for (; i < target->color_info.num_components; i++) |
2600 | 0 | buf_ptrs[i] = 0; |
2601 | 0 | code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp, |
2602 | 0 | rect.p.x, rect.p.y, width, height, rowstride, alpha_offset, |
2603 | 0 | tag_offset); |
2604 | | /* Right now code has number of rows written */ |
2605 | 0 | } |
2606 | 693k | } else if (has_tags) { |
2607 | | /* We are going out to a device that supports tags */ |
2608 | 0 | if (deep) { |
2609 | 0 | gx_blend_image_buffer16(buf_ptr, width, height, rowstride, |
2610 | 0 | buf->planestride, num_comp, additive, false); |
2611 | 0 | } else { |
2612 | 0 | gx_blend_image_buffer(buf_ptr, width, height, rowstride, |
2613 | 0 | buf->planestride, num_comp, additive); |
2614 | 0 | } |
2615 | |
|
2616 | | #if RAW_DUMP |
2617 | | dump_raw_buffer(pdev->ctx->memory, height, width, buf->n_planes, |
2618 | | pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride, |
2619 | | "post_final_blend", buf_ptr, deep); |
2620 | | #endif |
2621 | | |
2622 | | /* Take care of color issues */ |
2623 | 0 | if (color_mismatch) { |
2624 | | /* In this case, just color convert and maintain alpha. This is a case |
2625 | | where we either either blend in the right color space and have no |
2626 | | alpha for the output device or hand back the wrong color space with |
2627 | | alpha data. We choose the later. */ |
2628 | 0 | code = pdf14_put_image_color_convert(pdev, pgs, src_profile, dev_target_profile, |
2629 | 0 | &buf, &buf_ptr, true, rect.p.x, rect.p.y, width, height, false); |
2630 | 0 | if (code < 0) |
2631 | 0 | return code; |
2632 | |
|
2633 | | #if RAW_DUMP |
2634 | | dump_raw_buffer(pdev->ctx->memory, height, width, buf->n_planes, |
2635 | | pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride, |
2636 | | "final_color_manage", buf_ptr, deep); |
2637 | | global_index++; |
2638 | | #endif |
2639 | 0 | } |
2640 | | |
2641 | | /* reset */ |
2642 | 0 | rowstride = buf->rowstride; |
2643 | 0 | planestride = buf->planestride; |
2644 | 0 | num_comp = buf->n_chan - 1; |
2645 | 0 | alpha_offset = 0; /* It is there but this indicates we have done the blend */ |
2646 | 0 | tag_offset = buf->has_tags ? buf->n_chan : 0; |
2647 | | |
2648 | | /* And then out */ |
2649 | 0 | for (i = 0; i < buf->n_planes; i++) |
2650 | 0 | buf_ptrs[i] = buf_ptr + i * planestride; |
2651 | 0 | for (; i < target->color_info.num_components; i++) |
2652 | 0 | buf_ptrs[i] = 0; |
2653 | 0 | code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp, |
2654 | 0 | rect.p.x, rect.p.y, width, height, rowstride, alpha_offset, |
2655 | 0 | tag_offset); |
2656 | | /* Right now code has number of rows written */ |
2657 | |
|
2658 | 0 | } |
2659 | | |
2660 | | /* If code > 0 then put image worked. Let it finish and then exit */ |
2661 | 693k | if (code > 0) { |
2662 | | /* We processed some or all of the rows. Continue until we are done */ |
2663 | 0 | num_rows_left = height - code; |
2664 | 0 | while (num_rows_left > 0) { |
2665 | 0 | code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp, |
2666 | 0 | rect.p.x, rect.p.y + code, width, |
2667 | 0 | num_rows_left, rowstride, |
2668 | 0 | alpha_offset, tag_offset); |
2669 | 0 | num_rows_left = num_rows_left - code; |
2670 | 0 | } |
2671 | 0 | return 0; |
2672 | 0 | } |
2673 | | |
2674 | | /* Target device did not support alpha or tags. |
2675 | | * Set color space in preparation for sending an image. |
2676 | | * color conversion will occur after blending with through |
2677 | | * the begin typed image work flow. |
2678 | | */ |
2679 | | |
2680 | 693k | planestride = buf->planestride; |
2681 | 693k | rowstride = buf->rowstride; |
2682 | 693k | code = gs_cspace_build_ICC(&pcs, NULL, pgs->memory); |
2683 | 693k | if (code < 0) |
2684 | 0 | return code; |
2685 | | /* Need to set this to avoid color management during the image color render |
2686 | | operation. Exception is for the special case when the destination was |
2687 | | CIELAB. Then we need to convert from default RGB to CIELAB in the put |
2688 | | image operation. That will happen here as we should have set the profile |
2689 | | for the pdf14 device to RGB and the target will be CIELAB. In addition, |
2690 | | the case when we have a blend color space that is different than the |
2691 | | target device color space */ |
2692 | 693k | pcs->cmm_icc_profile_data = src_profile; |
2693 | | |
2694 | | /* pcs takes a reference to the profile data it just retrieved. */ |
2695 | 693k | gsicc_adjust_profile_rc(pcs->cmm_icc_profile_data, 1, "pdf14_put_image"); |
2696 | 693k | gsicc_set_icc_range(&(pcs->cmm_icc_profile_data)); |
2697 | 693k | gs_image_t_init_adjust(&image, pcs, false); |
2698 | 693k | image.ImageMatrix.xx = (float)width; |
2699 | 693k | image.ImageMatrix.yy = (float)height; |
2700 | 693k | image.Width = width; |
2701 | 693k | image.Height = height; |
2702 | 693k | image.BitsPerComponent = deep ? 16 : 8; |
2703 | 693k | image.ColorSpace = pcs; |
2704 | 693k | ctm_only_writable(pgs).xx = (float)width; |
2705 | 693k | ctm_only_writable(pgs).xy = 0; |
2706 | 693k | ctm_only_writable(pgs).yx = 0; |
2707 | 693k | ctm_only_writable(pgs).yy = (float)height; |
2708 | 693k | ctm_only_writable(pgs).tx = (float)rect.p.x; |
2709 | 693k | ctm_only_writable(pgs).ty = (float)rect.p.y; |
2710 | | /* Make sure that the relative colorimetric rendering intent is |
2711 | | used for this image. */ |
2712 | 693k | rendering_intent_saved = pgs->renderingintent; |
2713 | 693k | pgs->renderingintent = gsRELATIVECOLORIMETRIC; |
2714 | 693k | code = dev_proc(target, begin_typed_image) (target, |
2715 | 693k | pgs, NULL, |
2716 | 693k | (gs_image_common_t *)&image, |
2717 | 693k | NULL, NULL, NULL, |
2718 | 693k | pgs->memory, &info); |
2719 | 693k | pgs->renderingintent = rendering_intent_saved; |
2720 | 693k | if (code < 0) { |
2721 | 0 | rc_decrement_only_cs(pcs, "pdf14_put_image"); |
2722 | 0 | return code; |
2723 | 0 | } |
2724 | | #if RAW_DUMP |
2725 | | /* Dump the current buffer to see what we have. */ |
2726 | | dump_raw_buffer(pdev->ctx->memory, |
2727 | | pdev->ctx->stack->rect.q.y-pdev->ctx->stack->rect.p.y, |
2728 | | pdev->ctx->stack->rect.q.x-pdev->ctx->stack->rect.p.x, |
2729 | | pdev->ctx->stack->n_planes, |
2730 | | pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride, |
2731 | | "pdF14_putimage", pdev->ctx->stack->data, deep); |
2732 | | dump_raw_buffer(pdev->ctx->memory, |
2733 | | height, width, buf->n_planes, |
2734 | | pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride, |
2735 | | "PDF14_PUTIMAGE_SMALL", buf_ptr, deep); |
2736 | | global_index++; |
2737 | | clist_band_count++; |
2738 | | #endif |
2739 | | /* Allocate on 32-byte border for AVX CMYK case. Four byte overflow for RGB case */ |
2740 | | /* 28 byte overflow for AVX CMYK case. */ |
2741 | 693k | #define SSE_ALIGN 32 |
2742 | 693k | #define SSE_OVERFLOW 28 |
2743 | 693k | linebuf_unaligned = gs_alloc_bytes(pdev->memory, width * (num_comp<<deep) + SSE_ALIGN + SSE_OVERFLOW, "pdf14_put_image"); |
2744 | 693k | if (linebuf_unaligned == NULL) |
2745 | 0 | return gs_error_VMerror; |
2746 | 693k | linebuf = linebuf_unaligned + ((-(intptr_t)linebuf_unaligned) & (SSE_ALIGN-1)); |
2747 | | |
2748 | 693k | blend_row = deep ? gx_build_blended_image_row16 : |
2749 | 693k | gx_build_blended_image_row; |
2750 | | #ifdef WITH_CAL |
2751 | | blend_row = cal_get_blend_row(pdev->memory->gs_lib_ctx->core->cal_ctx, |
2752 | | blend_row, num_comp, deep); |
2753 | | #endif |
2754 | | |
2755 | 693k | bg = additive ? (deep ? 65535 : 255) : 0; |
2756 | 7.71M | for (y = 0; y < height; y++) { |
2757 | 7.02M | gx_image_plane_t planes; |
2758 | 7.02M | int rows_used; |
2759 | | |
2760 | 7.02M | blend_row(buf_ptr, buf->planestride, width, num_comp, bg, linebuf); |
2761 | 7.02M | planes.data = linebuf; |
2762 | 7.02M | planes.data_x = 0; |
2763 | 7.02M | planes.raster = width * num_comp; |
2764 | 7.02M | info->procs->plane_data(info, &planes, 1, &rows_used); |
2765 | | /* todo: check return value */ |
2766 | 7.02M | buf_ptr += buf->rowstride; |
2767 | 7.02M | } |
2768 | 693k | gs_free_object(pdev->memory, linebuf_unaligned, "pdf14_put_image"); |
2769 | 693k | info->procs->end_image(info, true); |
2770 | | /* This will also decrement the device profile */ |
2771 | 693k | rc_decrement_only_cs(pcs, "pdf14_put_image"); |
2772 | 693k | return code; |
2773 | 693k | } |
2774 | | |
2775 | | /* Overprint simulation with spots. Collapse to CMYK */ |
2776 | | static void |
2777 | | template_spots_to_cmyk(byte *buf_ptr, int width, int height, intptr_t rowstride, |
2778 | | intptr_t planestride, int num_comp, int spot_start, int tag_offset, |
2779 | | cmyk_composite_map *map, bool keep_alpha) |
2780 | 0 | { |
2781 | 0 | int comp_num; |
2782 | 0 | uint cyan, magenta, yellow, black; |
2783 | 0 | cmyk_composite_map *cmyk_map_entry; |
2784 | 0 | int x, y; |
2785 | 0 | intptr_t position; |
2786 | 0 | byte comp, a; |
2787 | |
|
2788 | 0 | for (y = 0; y < height; y++) { |
2789 | 0 | position = y * rowstride; |
2790 | 0 | for (x = 0; x < width; x++) { |
2791 | 0 | a = buf_ptr[position + planestride * num_comp]; |
2792 | 0 | if (a != 0) { |
2793 | 0 | cyan = buf_ptr[position] * frac_1; |
2794 | 0 | magenta = buf_ptr[position + planestride] * frac_1; |
2795 | 0 | yellow = buf_ptr[position + planestride * 2] * frac_1; |
2796 | 0 | black = buf_ptr[position + planestride * 3] * frac_1; |
2797 | 0 | cmyk_map_entry = &(map[4]); |
2798 | 0 | for (comp_num = spot_start; comp_num < num_comp; comp_num++) { |
2799 | 0 | comp = buf_ptr[position + planestride * comp_num]; |
2800 | 0 | cyan += cmyk_map_entry->c * comp; |
2801 | 0 | magenta += cmyk_map_entry->m * comp; |
2802 | 0 | yellow += cmyk_map_entry->y * comp; |
2803 | 0 | black += cmyk_map_entry->k * comp; |
2804 | 0 | cmyk_map_entry++; |
2805 | 0 | } |
2806 | 0 | cyan /= frac_1; |
2807 | 0 | magenta /= frac_1; |
2808 | 0 | yellow /= frac_1; |
2809 | 0 | black /= frac_1; |
2810 | |
|
2811 | 0 | if (cyan > 255) |
2812 | 0 | cyan = 255; |
2813 | 0 | if (magenta > 255) |
2814 | 0 | magenta = 255; |
2815 | 0 | if (yellow > 255) |
2816 | 0 | yellow = 255; |
2817 | 0 | if (black > 255) |
2818 | 0 | black = 255; |
2819 | |
|
2820 | 0 | buf_ptr[position] = cyan; |
2821 | 0 | buf_ptr[position + planestride] = magenta; |
2822 | 0 | buf_ptr[position + planestride * 2] = yellow; |
2823 | 0 | buf_ptr[position + planestride * 3] = black; |
2824 | 0 | } |
2825 | 0 | if (keep_alpha) { |
2826 | | /* Move the alpha and tag data */ |
2827 | 0 | buf_ptr[position + planestride * 4] = a; |
2828 | 0 | if (tag_offset > 0) { |
2829 | 0 | buf_ptr[position + planestride * 5] = |
2830 | 0 | buf_ptr[position + planestride * tag_offset]; |
2831 | 0 | } |
2832 | 0 | } else { |
2833 | | /* Remove alpha but keep tags */ |
2834 | 0 | if (tag_offset > 0) { |
2835 | 0 | buf_ptr[position + planestride * 4] = |
2836 | 0 | buf_ptr[position + planestride * tag_offset]; |
2837 | 0 | } |
2838 | |
|
2839 | 0 | } |
2840 | 0 | position += 1; |
2841 | 0 | } |
2842 | 0 | } |
2843 | 0 | } |
2844 | | |
2845 | | static void |
2846 | | template_spots_to_cmyk_16(byte *buf_ptr_, int width, int height, intptr_t rowstride, |
2847 | | intptr_t planestride, int num_comp, int spot_start, int tag_offset, |
2848 | | cmyk_composite_map *map, bool keep_alpha) |
2849 | 0 | { |
2850 | 0 | int comp_num; |
2851 | 0 | ulong cyan, magenta, yellow, black; |
2852 | 0 | cmyk_composite_map *cmyk_map_entry; |
2853 | 0 | int x, y; |
2854 | 0 | intptr_t position; |
2855 | 0 | ulong comp, a; |
2856 | 0 | uint16_t *buf_ptr = (uint16_t *)(void *)buf_ptr_; |
2857 | | |
2858 | | /* planestride and rowstride are in bytes, and we want them in shorts */ |
2859 | 0 | planestride >>= 1; |
2860 | 0 | rowstride >>= 1; |
2861 | |
|
2862 | 0 | for (y = 0; y < height; y++) { |
2863 | 0 | position = y * rowstride; |
2864 | 0 | for (x = 0; x < width; x++) { |
2865 | 0 | a = buf_ptr[position + planestride * num_comp]; |
2866 | 0 | if (a != 0) { |
2867 | 0 | cyan = (ulong)buf_ptr[position] * frac_1_long; |
2868 | 0 | magenta = (ulong)buf_ptr[position + planestride] * frac_1_long; |
2869 | 0 | yellow = (ulong)buf_ptr[position + planestride * 2] * frac_1_long; |
2870 | 0 | black = (ulong)buf_ptr[position + planestride * 3] * frac_1_long; |
2871 | 0 | cmyk_map_entry = &(map[4]); |
2872 | 0 | for (comp_num = spot_start; comp_num < num_comp; comp_num++) { |
2873 | 0 | comp = buf_ptr[position + planestride * comp_num]; |
2874 | 0 | cyan += (ulong)cmyk_map_entry->c * comp; |
2875 | 0 | magenta += (ulong)cmyk_map_entry->m * comp; |
2876 | 0 | yellow += (ulong)cmyk_map_entry->y * comp; |
2877 | 0 | black += (ulong)cmyk_map_entry->k * comp; |
2878 | 0 | cmyk_map_entry++; |
2879 | 0 | } |
2880 | 0 | cyan /= frac_1_long; |
2881 | 0 | magenta /= frac_1_long; |
2882 | 0 | yellow /= frac_1_long; |
2883 | 0 | black /= frac_1_long; |
2884 | |
|
2885 | 0 | if (cyan > 65535) |
2886 | 0 | cyan = 65535; |
2887 | 0 | if (magenta > 65535) |
2888 | 0 | magenta = 65535; |
2889 | 0 | if (yellow > 65535) |
2890 | 0 | yellow = 65535; |
2891 | 0 | if (black > 65535) |
2892 | 0 | black = 65535; |
2893 | |
|
2894 | | #if ARCH_IS_BIG_ENDIAN |
2895 | | buf_ptr[position] = cyan; |
2896 | | buf_ptr[position + planestride] = magenta; |
2897 | | buf_ptr[position + planestride * 2] = yellow; |
2898 | | buf_ptr[position + planestride * 3] = black; |
2899 | | #else |
2900 | 0 | ((byte *)&buf_ptr[position])[0] = cyan >> 8; |
2901 | 0 | ((byte *)&buf_ptr[position])[1] = cyan; |
2902 | 0 | ((byte *)&buf_ptr[position + planestride])[0] = magenta >> 8; |
2903 | 0 | ((byte *)&buf_ptr[position + planestride])[1] = magenta; |
2904 | 0 | ((byte *)&buf_ptr[position + planestride * 2])[0] = yellow >> 8; |
2905 | 0 | ((byte *)&buf_ptr[position + planestride * 2])[1] = yellow; |
2906 | 0 | ((byte *)&buf_ptr[position + planestride * 3])[0] = black >> 8; |
2907 | 0 | ((byte *)&buf_ptr[position + planestride * 3])[1] = black; |
2908 | 0 | #endif |
2909 | 0 | } |
2910 | | /* Move the alpha and tag data */ |
2911 | | #if ARCH_IS_BIG_ENDIAN |
2912 | | if (keep_alpha) { |
2913 | | buf_ptr[position + planestride * 4] = a; |
2914 | | if (tag_offset > 0) { |
2915 | | buf_ptr[position + planestride * 5] = |
2916 | | buf_ptr[position + planestride * tag_offset]; |
2917 | | } |
2918 | | } else { |
2919 | | if (tag_offset > 0) { |
2920 | | buf_ptr[position + planestride * 4] = |
2921 | | buf_ptr[position + planestride * tag_offset]; |
2922 | | } |
2923 | | } |
2924 | | #else |
2925 | 0 | if (keep_alpha) { |
2926 | 0 | ((byte *)&buf_ptr[position + planestride * 4])[0] = a >> 8; |
2927 | 0 | ((byte *)&buf_ptr[position + planestride * 4])[1] = a; |
2928 | 0 | if (tag_offset > 0) { |
2929 | 0 | ((byte *)&buf_ptr[position + planestride * 5])[0] = |
2930 | 0 | buf_ptr[position + planestride * tag_offset] >> 8; |
2931 | 0 | ((byte *)&buf_ptr[position + planestride * 5])[1] = |
2932 | 0 | buf_ptr[position + planestride * tag_offset]; |
2933 | 0 | } |
2934 | 0 | } else { |
2935 | 0 | if (tag_offset > 0) { |
2936 | 0 | ((byte *)&buf_ptr[position + planestride * 4])[0] = |
2937 | 0 | buf_ptr[position + planestride * tag_offset] >> 8; |
2938 | 0 | ((byte *)&buf_ptr[position + planestride * 4])[1] = |
2939 | 0 | buf_ptr[position + planestride * tag_offset]; |
2940 | 0 | } |
2941 | 0 | } |
2942 | 0 | #endif |
2943 | 0 | position += 1; |
2944 | 0 | } |
2945 | 0 | } |
2946 | 0 | } |
2947 | | |
2948 | | static void |
2949 | | pdf14_spots_to_cmyk(byte *buf_ptr, int width, int height, intptr_t rowstride, |
2950 | | intptr_t planestride, int num_comp, int spot_start, int tag_offset, |
2951 | | cmyk_composite_map *map, bool keep_alpha, bool deep) |
2952 | 0 | { |
2953 | 0 | if (deep) { |
2954 | 0 | if (keep_alpha) { |
2955 | 0 | if (tag_offset > 0) { |
2956 | 0 | template_spots_to_cmyk_16(buf_ptr, width, height, rowstride, |
2957 | 0 | planestride, num_comp, spot_start, tag_offset, |
2958 | 0 | map, true); |
2959 | 0 | } else { |
2960 | 0 | template_spots_to_cmyk_16(buf_ptr, width, height, rowstride, |
2961 | 0 | planestride, num_comp, spot_start, 0, |
2962 | 0 | map, true); |
2963 | 0 | } |
2964 | 0 | } else { |
2965 | 0 | if (tag_offset > 0) { |
2966 | 0 | template_spots_to_cmyk_16(buf_ptr, width, height, rowstride, |
2967 | 0 | planestride, num_comp, spot_start, tag_offset, |
2968 | 0 | map, false); |
2969 | 0 | } else { |
2970 | 0 | template_spots_to_cmyk_16(buf_ptr, width, height, rowstride, |
2971 | 0 | planestride, num_comp, spot_start, 0, |
2972 | 0 | map, false); |
2973 | 0 | } |
2974 | 0 | } |
2975 | 0 | } else { |
2976 | 0 | if (keep_alpha) { |
2977 | 0 | if (tag_offset > 0) { |
2978 | 0 | template_spots_to_cmyk(buf_ptr, width, height, rowstride, |
2979 | 0 | planestride, num_comp, spot_start, tag_offset, |
2980 | 0 | map, true); |
2981 | 0 | } else { |
2982 | 0 | template_spots_to_cmyk(buf_ptr, width, height, rowstride, |
2983 | 0 | planestride, num_comp, spot_start, 0, |
2984 | 0 | map, true); |
2985 | 0 | } |
2986 | 0 | } else { |
2987 | 0 | if (tag_offset > 0) { |
2988 | 0 | template_spots_to_cmyk(buf_ptr, width, height, rowstride, |
2989 | 0 | planestride, num_comp, spot_start, tag_offset, |
2990 | 0 | map, false); |
2991 | 0 | } else { |
2992 | 0 | template_spots_to_cmyk(buf_ptr, width, height, rowstride, |
2993 | 0 | planestride, num_comp, spot_start, 0, |
2994 | 0 | map, false); |
2995 | 0 | } |
2996 | 0 | } |
2997 | 0 | } |
2998 | 0 | } |
2999 | | |
3000 | | /* This is for the case where we have mixture of spots and additive color. |
3001 | | For example, RGB + spots or Gray + spots */ |
3002 | | static void |
3003 | | pdf14_blend_image_mixed_buffer(byte* buf_ptr, int width, int height, intptr_t rowstride, |
3004 | | intptr_t planestride, int num_comp, int spot_start) |
3005 | 8.15k | { |
3006 | 8.15k | int x, y; |
3007 | 8.15k | intptr_t position; |
3008 | 8.15k | byte comp, a; |
3009 | 8.15k | int tmp, comp_num; |
3010 | | |
3011 | 85.2k | for (y = 0; y < height; y++) { |
3012 | 77.1k | position = y * rowstride; |
3013 | 60.3M | for (x = 0; x < width; x++) { |
3014 | 60.2M | a = buf_ptr[position + planestride * num_comp]; |
3015 | 60.2M | if ((a + 1) & 0xfe) { |
3016 | 844k | a ^= 0xff; |
3017 | 3.37M | for (comp_num = 0; comp_num < spot_start; comp_num++) { |
3018 | 2.53M | comp = buf_ptr[position + planestride * comp_num]; |
3019 | 2.53M | tmp = ((0xff - comp) * a) + 0x80; |
3020 | 2.53M | comp += (tmp + (tmp >> 8)) >> 8; |
3021 | 2.53M | buf_ptr[position + planestride * comp_num] = comp; |
3022 | 2.53M | } |
3023 | 844k | for (comp_num = spot_start; comp_num < num_comp; comp_num++) { |
3024 | 0 | comp = buf_ptr[position + planestride * comp_num]; |
3025 | 0 | tmp = ((-comp) * a) + 0x80; |
3026 | 0 | comp += (tmp + (tmp >> 8)) >> 8; |
3027 | 0 | buf_ptr[position + planestride * comp_num] = comp; |
3028 | 0 | } |
3029 | 59.4M | } else if (a == 0) { |
3030 | 66.8M | for (comp_num = 0; comp_num < spot_start; comp_num++) { |
3031 | 50.1M | buf_ptr[position + planestride * comp_num] = 0xff; |
3032 | 50.1M | } |
3033 | 16.7M | for (comp_num = spot_start; comp_num < num_comp; comp_num++) { |
3034 | 51.1k | buf_ptr[position + planestride * comp_num] = 0; |
3035 | 51.1k | } |
3036 | 16.7M | } |
3037 | 60.2M | position += 1; |
3038 | 60.2M | } |
3039 | 77.1k | } |
3040 | 8.15k | } |
3041 | | |
3042 | | static void |
3043 | | pdf14_blend_image_mixed_buffer16(byte* buf_ptr_, int width, int height, intptr_t rowstride, |
3044 | | intptr_t planestride, int num_comp, int spot_start) |
3045 | 0 | { |
3046 | 0 | uint16_t* buf_ptr = (uint16_t*)(void*)buf_ptr_; |
3047 | 0 | int x, y; |
3048 | 0 | intptr_t position; |
3049 | 0 | int comp, a; |
3050 | 0 | int tmp, comp_num; |
3051 | | |
3052 | | /* planestride and rowstride are in bytes, and we want them in shorts */ |
3053 | 0 | planestride >>= 1; |
3054 | 0 | rowstride >>= 1; |
3055 | | |
3056 | | /* Note that the input here is native endian, and the output must be in big endian! */ |
3057 | 0 | for (y = 0; y < height; y++) { |
3058 | 0 | position = y * rowstride; |
3059 | 0 | for (x = 0; x < width; x++) { |
3060 | | /* composite RGBA (or CMYKA, etc.) pixel with over solid background */ |
3061 | 0 | a = buf_ptr[position + planestride * num_comp]; |
3062 | 0 | if (a == 0) { |
3063 | 0 | for (comp_num = 0; comp_num < spot_start; comp_num++) { |
3064 | 0 | buf_ptr[position + planestride * comp_num] = 0xffff; |
3065 | 0 | } |
3066 | 0 | for (comp_num = spot_start; comp_num < num_comp; comp_num++) { |
3067 | 0 | buf_ptr[position + planestride * comp_num] = 0; |
3068 | 0 | } |
3069 | 0 | } else if (a == 0xffff) { |
3070 | | #if ARCH_IS_BIG_ENDIAN |
3071 | | #else |
3072 | | /* Convert from native -> big endian */ |
3073 | 0 | for (comp_num = 0; comp_num < num_comp; comp_num++) { |
3074 | 0 | comp = buf_ptr[position + planestride * comp_num]; |
3075 | 0 | ((byte*)&buf_ptr[position + planestride * comp_num])[0] = comp >> 8; |
3076 | 0 | ((byte*)&buf_ptr[position + planestride * comp_num])[1] = comp; |
3077 | 0 | } |
3078 | 0 | #endif |
3079 | 0 | } else { |
3080 | 0 | a ^= 0xffff; |
3081 | 0 | a += a >> 15; /* a is now 0 to 0x10000 */ |
3082 | 0 | a >>= 1; /* We can only use 15 bits as bg-comp has a sign bit we can't lose */ |
3083 | 0 | for (comp_num = 0; comp_num < spot_start; comp_num++) { |
3084 | 0 | comp = buf_ptr[position + planestride * comp_num]; |
3085 | 0 | tmp = ((0xffff - comp) * a) + 0x4000; |
3086 | 0 | comp += (tmp >> 15); /* Errors in bit 16 upwards will be ignored */ |
3087 | | /* Store as big endian */ |
3088 | 0 | ((byte*)&buf_ptr[position + planestride * comp_num])[0] = comp >> 8; |
3089 | 0 | ((byte*)&buf_ptr[position + planestride * comp_num])[1] = comp; |
3090 | 0 | } |
3091 | 0 | for (comp_num = spot_start; comp_num < num_comp; comp_num++) { |
3092 | 0 | comp = buf_ptr[position + planestride * comp_num]; |
3093 | 0 | tmp = ((0 - comp) * a) + 0x4000; |
3094 | 0 | comp += (tmp >> 15); /* Errors in bit 16 upwards will be ignored */ |
3095 | | /* Store as big endian */ |
3096 | 0 | ((byte*)&buf_ptr[position + planestride * comp_num])[0] = comp >> 8; |
3097 | 0 | ((byte*)&buf_ptr[position + planestride * comp_num])[1] = comp; |
3098 | 0 | } |
3099 | 0 | } |
3100 | 0 | position += 1; |
3101 | 0 | } |
3102 | 0 | } |
3103 | 0 | } |
3104 | | |
3105 | | static int |
3106 | | pdf14_put_blended_image_cmykspot(gx_device* dev, gx_device* target, |
3107 | | gs_gstate* pgs, pdf14_buf* buf, intptr_t planestride_in, |
3108 | | intptr_t rowstride_in, int x0, int y0, int width, int height, |
3109 | | int num_comp, int additive, bool has_tags, gs_int_rect rect_in, |
3110 | | gs_separations* pseparations, bool deep) |
3111 | 22.2k | { |
3112 | 22.2k | pdf14_device* pdev = (pdf14_device*)dev; |
3113 | 22.2k | int code = 0; |
3114 | 22.2k | int y; |
3115 | 22.2k | int num_rows_left; |
3116 | 22.2k | int i; |
3117 | 22.2k | gs_int_rect rect = rect_in; |
3118 | 22.2k | intptr_t planestride = planestride_in; |
3119 | 22.2k | intptr_t rowstride = rowstride_in; |
3120 | 22.2k | byte* buf_ptr = NULL; |
3121 | 22.2k | cmm_profile_t* src_profile = buf->group_color_info->icc_profile; |
3122 | 22.2k | cmm_profile_t* des_profile = NULL; |
3123 | 22.2k | cmm_dev_profile_t* dev_target_profile; |
3124 | 22.2k | cmm_dev_profile_t* pdf14dev_profile; |
3125 | 22.2k | bool color_mismatch = false; |
3126 | 22.2k | bool supports_alpha = false; |
3127 | 22.2k | const byte* buf_ptrs[GS_CLIENT_COLOR_MAX_COMPONENTS]; |
3128 | 22.2k | int alpha_offset = num_comp; |
3129 | 22.2k | int tag_offset = has_tags ? num_comp + 1 : 0; |
3130 | 22.2k | gs_color_space *pcs; |
3131 | 22.2k | gs_image1_t image; |
3132 | 22.2k | gx_image_enum_common_t *info; |
3133 | 22.2k | gx_image_plane_t planes[GS_IMAGE_MAX_COMPONENTS]; |
3134 | 22.2k | pdf14_buf *cm_result = NULL; |
3135 | 22.2k | bool did_alloc; |
3136 | 22.2k | bool target_sep_device = (dev_proc(target, dev_spec_op)(target, gxdso_supports_devn, NULL, 0) > 0); |
3137 | 22.2k | bool has_spots = pdev->ctx->num_spots > 0; |
3138 | 22.2k | bool blend_spots = !target_sep_device && has_spots; |
3139 | 22.2k | bool lose_channels = false; |
3140 | | |
3141 | | /* Check if group color space is CMYK based */ |
3142 | 22.2k | code = dev_proc(target, get_profile)(target, &dev_target_profile); |
3143 | 22.2k | if (code < 0) |
3144 | 0 | return code; |
3145 | 22.2k | if (dev_target_profile == NULL) |
3146 | 0 | return gs_throw_code(gs_error_Fatal); |
3147 | | |
3148 | 22.2k | if (src_profile == NULL) { |
3149 | 0 | code = dev_proc(dev, get_profile)(dev, &pdf14dev_profile); |
3150 | 0 | if (code < 0) { |
3151 | 0 | return code; |
3152 | 0 | } |
3153 | 0 | src_profile = pdf14dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]; |
3154 | 0 | } |
3155 | | |
3156 | | /* If the target device does not support spot colors and we have spot colors |
3157 | | here due to overprint simulation (blend_spots == true), then we will need to convert the base |
3158 | | colors to CMYK if it is RGB or Gray so tha we can blend in the spot colors */ |
3159 | 22.2k | if (blend_spots && src_profile->data_cs != gsCMYK) { |
3160 | |
|
3161 | 0 | cm_result = pdf14_transform_color_buffer_no_matte(pgs, pdev->ctx, (gx_device *)dev, buf, |
3162 | 0 | buf->data, src_profile, pgs->icc_manager->default_cmyk, 0, 0, buf->rect.q.x, |
3163 | 0 | buf->rect.q.y, &did_alloc, buf->deep, false, false); |
3164 | 0 | if (cm_result == NULL) |
3165 | 0 | return_error(gs_error_VMerror); |
3166 | | |
3167 | | /* Update */ |
3168 | 0 | buf = cm_result; |
3169 | 0 | src_profile = pgs->icc_manager->default_cmyk; |
3170 | 0 | num_comp = buf->n_chan - 1; |
3171 | 0 | additive = 0; |
3172 | 0 | tag_offset = has_tags ? num_comp + 1 : 0; |
3173 | 0 | alpha_offset = num_comp; |
3174 | |
|
3175 | | #if RAW_DUMP |
3176 | | buf_ptr = buf->data + (rect.p.y - buf->rect.p.y) * buf->rowstride + ((rect.p.x - buf->rect.p.x) << deep); |
3177 | | dump_raw_buffer(target->memory, height, width, buf->n_planes, planestride, rowstride, |
3178 | | "convertbase_to_cmyk_for_spot_blend", buf_ptr, deep); |
3179 | | global_index++; |
3180 | | #endif |
3181 | 0 | } |
3182 | | |
3183 | | /* Fix order map if needed */ |
3184 | 103k | for (i = 0; i < num_comp; i++) { |
3185 | 81.0k | pdev->devn_params.separation_order_map[i] = i; |
3186 | 81.0k | } |
3187 | | |
3188 | | /* Check if we have a color conversion issue */ |
3189 | 22.2k | des_profile = dev_target_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]; |
3190 | 22.2k | if (!gsicc_profiles_equal(des_profile, src_profile)) |
3191 | 8.15k | color_mismatch = true; |
3192 | 22.2k | if (des_profile->data_cs == gsNCHANNEL) |
3193 | 0 | lose_channels = true; |
3194 | | |
3195 | | /* Check if target supports alpha */ |
3196 | 22.2k | supports_alpha = (dev_proc(target, dev_spec_op)(target, gxdso_supports_alpha, NULL, 0) > 0); |
3197 | 22.2k | code = 0; |
3198 | | |
3199 | 22.2k | buf_ptr = buf->data + (rect.p.y - buf->rect.p.y) * buf->rowstride + ((rect.p.x - buf->rect.p.x) << deep); |
3200 | | |
3201 | | /* Note. The logic below will need a little rework if we ever |
3202 | | have a device that has tags and alpha support */ |
3203 | 22.2k | if (supports_alpha) { |
3204 | | |
3205 | | /* If doing simulated overprint, Bring the spot color channels into |
3206 | | CMYK. Data is planar and 16 bit data in native format. */ |
3207 | 0 | if (pdev->overprint_sim && pdev->devn_params.page_spot_colors > 0) { |
3208 | 0 | cmyk_composite_map cmyk_map[GX_DEVICE_MAX_SEPARATIONS]; /* Fracs */ |
3209 | | |
3210 | | /* In the clist case, we need to get equiv spots out of the pseudo-band. */ |
3211 | 0 | if (pdev->pclist_device != NULL) { |
3212 | 0 | gx_device_clist_reader *pcrdev = (gx_device_clist_reader *)(pdev->pclist_device); |
3213 | |
|
3214 | 0 | code = clist_read_op_equiv_cmyk_colors(pcrdev, &(pdev->op_pequiv_cmyk_colors)); |
3215 | 0 | if (code < 0) |
3216 | 0 | return code; |
3217 | 0 | } |
3218 | 0 | build_cmyk_map(dev, num_comp, &(pdev->op_pequiv_cmyk_colors), cmyk_map); |
3219 | | |
3220 | | /* Now we go to big endian */ |
3221 | 0 | pdf14_spots_to_cmyk(buf_ptr, width, height, rowstride, |
3222 | 0 | planestride, num_comp, src_profile->num_comps, |
3223 | 0 | tag_offset, cmyk_map, true, deep); |
3224 | | |
3225 | | /* Reset buffer information. We have CMYK+alpha and maybe tags */ |
3226 | 0 | buf->n_chan = buf->n_chan - buf->num_spots; |
3227 | 0 | buf->n_planes = buf->n_planes - buf->num_spots; |
3228 | 0 | buf->num_spots = 0; |
3229 | 0 | num_comp = buf->n_chan - 1; |
3230 | 0 | tag_offset = has_tags ? buf->n_planes - 1 : 0; /* Tags at end */ |
3231 | 0 | } |
3232 | | |
3233 | 0 | if (!color_mismatch) { |
3234 | 0 | for (i = 0; i < buf->n_planes; i++) |
3235 | 0 | buf_ptrs[i] = buf_ptr + i * planestride; |
3236 | 0 | for (; i < target->color_info.num_components; i++) |
3237 | 0 | buf_ptrs[i] = 0; |
3238 | 0 | code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp, |
3239 | 0 | rect.p.x, rect.p.y, width, height, |
3240 | 0 | rowstride, alpha_offset, tag_offset); |
3241 | | /* Right now code has number of rows written */ |
3242 | 0 | } else { |
3243 | | /* In this case, just color convert and maintain alpha. |
3244 | | This is a case where we either either blend in the |
3245 | | right color space and have no alpha for the output |
3246 | | device or hand back the wrong color space with |
3247 | | alpha data. We choose the later. */ |
3248 | 0 | code = pdf14_put_image_color_convert(pdev, pgs, src_profile, |
3249 | 0 | dev_target_profile, &buf, &buf_ptr, false, rect.p.x, |
3250 | 0 | rect.p.y, width, height, false); |
3251 | 0 | if (code < 0) |
3252 | 0 | return code; |
3253 | | |
3254 | | /* reset */ |
3255 | 0 | rowstride = buf->rowstride; |
3256 | 0 | planestride = buf->planestride; |
3257 | 0 | num_comp = buf->n_chan - 1; |
3258 | 0 | alpha_offset = num_comp; |
3259 | 0 | tag_offset = buf->has_tags ? buf->n_chan : 0; |
3260 | | |
3261 | | /* And then out */ |
3262 | 0 | for (i = 0; i < buf->n_planes; i++) |
3263 | 0 | buf_ptrs[i] = buf_ptr + i * planestride; |
3264 | 0 | for (; i < target->color_info.num_components; i++) |
3265 | 0 | buf_ptrs[i] = 0; |
3266 | 0 | code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp, |
3267 | 0 | rect.p.x, rect.p.y, width, height, rowstride, alpha_offset, |
3268 | 0 | tag_offset); |
3269 | | /* Right now code has number of rows written. Writing continues below */ |
3270 | 0 | } |
3271 | 22.2k | } else { |
3272 | | /* Device could not handle the alpha data (we actually don't have |
3273 | | a device that does spot colorants and has an alpha channel so |
3274 | | the above code is untested. Go ahead and preblend now and then |
3275 | | color convert if needed */ |
3276 | | #if RAW_DUMP |
3277 | | /* Dump before and after the blend to make sure we are doing that ok */ |
3278 | | dump_raw_buffer(target->memory, height, width, buf->n_planes, planestride, rowstride, |
3279 | | "pre_put_image_blend_image", buf_ptr, deep); |
3280 | | global_index++; |
3281 | | #endif |
3282 | | |
3283 | 22.2k | if (color_mismatch && (src_profile->data_cs == gsRGB || src_profile->data_cs == gsGRAY)) { |
3284 | 8.15k | if (deep) { |
3285 | | /* In this case, we are NOT going to bring the spots into the CMYK |
3286 | | equivalent colors, since otherwise src_profile would be CMYK based. So |
3287 | | 16 bit data will be converted now from native endian to big endian during |
3288 | | the blending process */ |
3289 | 0 | pdf14_blend_image_mixed_buffer16(buf_ptr, width, height, rowstride, |
3290 | 0 | planestride, num_comp, src_profile->num_comps); |
3291 | 8.15k | } else { |
3292 | 8.15k | pdf14_blend_image_mixed_buffer(buf_ptr, width, height, rowstride, |
3293 | 8.15k | planestride, num_comp, src_profile->num_comps); |
3294 | 8.15k | } |
3295 | 14.1k | } else { |
3296 | 14.1k | if (deep) { |
3297 | | /* In this case, if blend_spots == true, we will shortly be bringing |
3298 | | the spot colors to CMYK equivalent colors. It is at that time that |
3299 | | we will convert from native endian to big endian. In all other |
3300 | | cases this blending will due to conversion from native to BE */ |
3301 | 0 | bool keep_native = (blend_spots == true); |
3302 | |
|
3303 | 0 | gx_blend_image_buffer16(buf_ptr, width, height, rowstride, |
3304 | 0 | planestride, num_comp, additive, keep_native); |
3305 | 14.1k | } else { |
3306 | 14.1k | gx_blend_image_buffer(buf_ptr, width, height, rowstride, |
3307 | 14.1k | planestride, num_comp, additive); |
3308 | 14.1k | } |
3309 | 14.1k | } |
3310 | | |
3311 | 22.2k | if (deep && has_tags) |
3312 | 0 | { |
3313 | | /* We still need to convert the tags from Native to BE */ |
3314 | | #if ARCH_IS_BIG_ENDIAN |
3315 | | #else |
3316 | 0 | uint16_t *tags = (uint16_t *)&buf_ptr[tag_offset * planestride]; |
3317 | 0 | int i, j; |
3318 | 0 | for (j = 0; j < height; j++) |
3319 | 0 | { |
3320 | 0 | for (i = 0; i < width; i++) |
3321 | 0 | { |
3322 | 0 | uint16_t tag = *tags++; |
3323 | 0 | ((byte *)tags)[-2] = tag >> 8; |
3324 | 0 | ((byte *)tags)[-1] = tag; |
3325 | 0 | } |
3326 | 0 | tags += (buf->rowstride>>1) - width; |
3327 | 0 | } |
3328 | 0 | #endif |
3329 | 0 | } |
3330 | | |
3331 | | #if RAW_DUMP |
3332 | | dump_raw_buffer_be(target->memory, height, width, buf->n_planes, planestride, rowstride, |
3333 | | "post_put_image_blend_image", buf_ptr, deep); |
3334 | | global_index++; |
3335 | | #endif |
3336 | | |
3337 | | /* If doing simulated overprint and we are not going to a sep device and |
3338 | | we have spot colors, then bring the spot color channels into CMYK |
3339 | | (We should have already converted our base color space to CMYK if it was RGB or gray). |
3340 | | At this point, data is planar and 16 bit data is still in native format. It is |
3341 | | here that 16 bit data will be converted to BE. Otherwise it will have been converted |
3342 | | above during the alpha blend operation. */ |
3343 | 22.2k | if (blend_spots) { |
3344 | 0 | cmyk_composite_map cmyk_map[GX_DEVICE_MAX_SEPARATIONS]; /* Fracs */ |
3345 | | |
3346 | | /* In the clist case, we need to get equiv spots out of the |
3347 | | pseudo-band. */ |
3348 | 0 | if (pdev->pclist_device != NULL) { |
3349 | 0 | gx_device_clist_reader *pcrdev = (gx_device_clist_reader *)(pdev->pclist_device); |
3350 | 0 | code = clist_read_op_equiv_cmyk_colors(pcrdev, &(pdev->op_pequiv_cmyk_colors)); |
3351 | 0 | if (code < 0) |
3352 | 0 | return code; |
3353 | 0 | } |
3354 | | |
3355 | 0 | build_cmyk_map(dev, num_comp, &(pdev->op_pequiv_cmyk_colors), cmyk_map); |
3356 | 0 | pdf14_spots_to_cmyk(buf_ptr, width, height, rowstride, |
3357 | 0 | planestride, num_comp, src_profile->num_comps, |
3358 | 0 | tag_offset, cmyk_map, false, deep); |
3359 | | |
3360 | | /* Reset buffer information. We have CMYK and maybe tags */ |
3361 | 0 | num_comp = 4; |
3362 | 0 | alpha_offset = 0; |
3363 | 0 | buf->n_chan = buf->n_chan - buf->num_spots - 1; /* No spots or alpha */ |
3364 | 0 | buf->n_planes = buf->n_planes - buf->num_spots - 1; /* No spots or alpha */ |
3365 | 0 | tag_offset = has_tags ? buf->n_chan : 0; /* Tags at end */ |
3366 | 0 | buf->num_spots = 0; |
3367 | |
|
3368 | | #if RAW_DUMP |
3369 | | dump_raw_buffer(target->memory, height, width, buf->n_planes, planestride, rowstride, |
3370 | | "post_put_image_spot_to_cmyk", buf_ptr, deep); |
3371 | | global_index++; |
3372 | | #endif |
3373 | 0 | } |
3374 | | |
3375 | | /* Map to the destination color space */ |
3376 | 22.2k | if (color_mismatch) { |
3377 | | /* We started out with the original process colorants, and spots. If we have an |
3378 | | * nchannel output profile, this can mean that the first few spots might come from |
3379 | | * that and the rest from the document itself. e.g: |
3380 | | * C, M, Y, K, ICC_COLOR_0, ICC_COLOR_1, Spot 1, Spot 2 |
3381 | | * Then we might have a blend space that changes the process colorants: |
3382 | | * R, G, B, ICC_COLOR_0, ICC_COLOR_1, Spot 1, Spot 2 |
3383 | | * Now we're about to convert 'RGB' back to 'CMYKII'. |
3384 | | * If we're not careful, we'll end up with: |
3385 | | * C, M, Y, K, ICC_COLOR_0, ICC_COLOR_1, ICC_COLOR_0, ICC_COLOR_1, Spot 1, Spot 2 |
3386 | | * so we might need to lose some channels. ^^^^^^^^^^^^^^^^^^^^^^^^ |
3387 | | */ |
3388 | 8.15k | int num_original_process_colorants = target->color_info.num_components - has_tags - buf->num_spots; |
3389 | 8.15k | int num_channels_to_lose = lose_channels ? des_profile->num_comps - num_original_process_colorants : 0; |
3390 | 8.15k | code = pdf14_put_image_color_convert(pdev, pgs, src_profile, dev_target_profile, |
3391 | 8.15k | &buf, &buf_ptr, true, rect.p.x, rect.p.y, width, height, num_channels_to_lose); |
3392 | 8.15k | if (code < 0) |
3393 | 0 | return code; |
3394 | | |
3395 | | /* reset */ |
3396 | 8.15k | rowstride = buf->rowstride; |
3397 | 8.15k | planestride = buf->planestride; |
3398 | 8.15k | num_comp = buf->n_chan; |
3399 | 8.15k | tag_offset = buf->has_tags ? (buf->n_chan - num_channels_to_lose) : 0; |
3400 | 8.15k | } |
3401 | | |
3402 | | #if RAW_DUMP |
3403 | | /* Dump after the CS transform */ |
3404 | | dump_raw_buffer_be(target->memory, height, width, buf->n_planes, planestride, rowstride, |
3405 | | "post_put_image_color_convert", buf_ptr, deep); |
3406 | | global_index++; |
3407 | | /* clist_band_count++; */ |
3408 | | #endif |
3409 | | |
3410 | | /* Try put_image again. This can occur if the |
3411 | | target, like psdcmyk and tiffsep, support put_image */ |
3412 | 22.2k | alpha_offset = 0; |
3413 | 133k | for (i = 0; i < buf->n_planes; i++) |
3414 | 111k | buf_ptrs[i] = buf_ptr + i * planestride; |
3415 | 22.2k | for (; i < target->color_info.num_components; i++) |
3416 | 0 | buf_ptrs[i] = 0; |
3417 | 22.2k | code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp, |
3418 | 22.2k | rect.p.x, rect.p.y, width, height, |
3419 | 22.2k | rowstride, alpha_offset, tag_offset); |
3420 | 22.2k | } |
3421 | | |
3422 | | /* Put image was succesful. We processed some or all of the rows. |
3423 | | Continue until we are done */ |
3424 | 22.2k | if (code > 0) { |
3425 | 114 | num_rows_left = height - code; |
3426 | 114 | while (num_rows_left > 0) { |
3427 | 0 | code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp, |
3428 | 0 | rect.p.x, rect.p.y + code, width, num_rows_left, rowstride, |
3429 | 0 | alpha_offset, tag_offset); |
3430 | 0 | if (code < 0) { |
3431 | 0 | return code; |
3432 | 0 | } |
3433 | 0 | num_rows_left = num_rows_left - code; |
3434 | 0 | } |
3435 | 114 | return 0; |
3436 | 114 | } |
3437 | | |
3438 | | /* Sep devices all support put_image (tiffsep and psdcmyk) |
3439 | | as well as those devices that support alpha (pngalpha, |
3440 | | png16malpha). If we are here, then we are doing an |
3441 | | overprint simulation on some other device. Image data |
3442 | | is aleady blended and in device color space. */ |
3443 | 22.1k | code = gs_cspace_build_ICC(&pcs, NULL, pgs->memory); |
3444 | 22.1k | if (code < 0) |
3445 | 0 | return code; |
3446 | | |
3447 | | /* Already in destination CS */ |
3448 | 22.1k | pcs->cmm_icc_profile_data = des_profile; |
3449 | | |
3450 | | /* pcs takes a reference to the profile data it just retrieved. */ |
3451 | 22.1k | gsicc_adjust_profile_rc(pcs->cmm_icc_profile_data, 1, "pdf14_put_blended_image_cmykspot"); |
3452 | 22.1k | gsicc_set_icc_range(&(pcs->cmm_icc_profile_data)); |
3453 | | |
3454 | | /* If we have more components to write out than are in the des_profile, |
3455 | | * then just using a PCS based on des_profile, will result in us dropping |
3456 | | * the spot colors. |
3457 | | * So, if our target supports devn colors, we instead construct a |
3458 | | * DevN device space with colors names taken from the devn_params, and |
3459 | | * use that instead. */ |
3460 | 22.1k | if (des_profile->num_comps != target->color_info.num_components && |
3461 | 33 | dev_proc(target, dev_spec_op)(target, gxdso_supports_devn, NULL, 0) > 0) |
3462 | 33 | { |
3463 | 33 | int num_std; |
3464 | 33 | gs_devn_params *devn_params = dev_proc(target, ret_devn_params)(target); |
3465 | 33 | gs_color_space *pcs2 = pcs; |
3466 | 33 | code = gs_cspace_new_DeviceN(&pcs, target->color_info.num_components, |
3467 | 33 | pcs2, pgs->memory->non_gc_memory); |
3468 | 33 | if (code < 0) |
3469 | 0 | return code; |
3470 | | /* set up a usable DeviceN space with info from the tdev->devn_params */ |
3471 | 33 | pcs->params.device_n.use_alt_cspace = false; |
3472 | 33 | num_std = devn_params->num_std_colorant_names; |
3473 | 165 | for (i = 0; i < num_std; i++) { |
3474 | 132 | const char *name = devn_params->std_colorant_names[i]; |
3475 | 132 | size_t len = strlen(name); |
3476 | 132 | pcs->params.device_n.names[i] = (char *)gs_alloc_bytes(pgs->memory->non_gc_memory, len + 1, "mem_planar_put_image_very_slow"); |
3477 | 132 | if (pcs->params.device_n.names[i] == NULL) { |
3478 | 0 | int j = 0; |
3479 | 0 | for (j = 0;j < i; j++) { |
3480 | 0 | if (pcs->params.device_n.names[j] != NULL) |
3481 | 0 | gs_free_object(pgs->memory->non_gc_memory, pcs->params.device_n.names[j], "mem_planar_put_image_very_slow"); |
3482 | 0 | pcs->params.device_n.names[j] = NULL; |
3483 | 0 | } |
3484 | 0 | return_error(gs_error_VMerror); |
3485 | 0 | } |
3486 | 132 | strcpy(pcs->params.device_n.names[i], name); |
3487 | 132 | } |
3488 | 33 | for (; i < devn_params->separations.num_separations; i++) { |
3489 | 0 | devn_separation_name *name = &devn_params->separations.names[i - num_std]; |
3490 | 0 | pcs->params.device_n.names[i] = (char *)gs_alloc_bytes(pgs->memory->non_gc_memory, name->size + 1, "mem_planar_put_image_very_slow"); |
3491 | 0 | if (pcs->params.device_n.names[i] == NULL) { |
3492 | 0 | int j = 0; |
3493 | 0 | for (j = 0;j < i; j++) { |
3494 | 0 | if (pcs->params.device_n.names[j] != NULL) |
3495 | 0 | gs_free_object(pgs->memory->non_gc_memory, pcs->params.device_n.names[j], "mem_planar_put_image_very_slow"); |
3496 | 0 | pcs->params.device_n.names[j] = NULL; |
3497 | 0 | } |
3498 | 0 | return_error(gs_error_VMerror); |
3499 | 0 | } |
3500 | 0 | memcpy(pcs->params.device_n.names[i], devn_params->separations.names[i - num_std].data, name->size); |
3501 | 0 | pcs->params.device_n.names[i][name->size] = 0; |
3502 | 0 | } |
3503 | 33 | if ((code = pcs->type->install_cspace(pcs, pgs)) < 0) { |
3504 | 0 | return code; |
3505 | 0 | } |
3506 | | /* One last thing -- we need to fudge the pgs->color_component_map */ |
3507 | 198 | for (i=0; i < dev->color_info.num_components; i++) |
3508 | 165 | pgs->color_component_map.color_map[i] = i; /* enable all components in normal order */ |
3509 | 33 | } |
3510 | | |
3511 | 22.1k | gs_image_t_init_adjust(&image, pcs, false); |
3512 | 22.1k | image.ImageMatrix.xx = (float)width; |
3513 | 22.1k | image.ImageMatrix.yy = (float)height; |
3514 | 22.1k | image.Width = width; |
3515 | 22.1k | image.Height = height; |
3516 | 22.1k | image.BitsPerComponent = deep ? 16 : 8; |
3517 | 22.1k | image.ColorSpace = pcs; |
3518 | 22.1k | image.format = gs_image_format_component_planar; |
3519 | | |
3520 | 22.1k | ctm_only_writable(pgs).xx = (float)width; |
3521 | 22.1k | ctm_only_writable(pgs).xy = 0; |
3522 | 22.1k | ctm_only_writable(pgs).yx = 0; |
3523 | 22.1k | ctm_only_writable(pgs).yy = (float)height; |
3524 | 22.1k | ctm_only_writable(pgs).tx = (float)rect.p.x; |
3525 | 22.1k | ctm_only_writable(pgs).ty = (float)rect.p.y; |
3526 | 22.1k | code = dev_proc(target, begin_typed_image) (target, |
3527 | 22.1k | pgs, NULL, (gs_image_common_t *)&image, |
3528 | 22.1k | NULL, NULL, NULL, pgs->memory, &info); |
3529 | 22.1k | if (code < 0) { |
3530 | 0 | rc_decrement_only_cs(pcs, "pdf14_put_blended_image_cmykspot"); |
3531 | 0 | return code; |
3532 | 0 | } |
3533 | | #if RAW_DUMP |
3534 | | /* Dump the current buffer to see what we have. */ |
3535 | | dump_raw_buffer(pdev->ctx->memory, |
3536 | | pdev->ctx->stack->rect.q.y - pdev->ctx->stack->rect.p.y, |
3537 | | pdev->ctx->stack->rect.q.x - pdev->ctx->stack->rect.p.x, |
3538 | | pdev->ctx->stack->n_planes, |
3539 | | pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride, |
3540 | | "put_image_final_big", pdev->ctx->stack->data, deep); |
3541 | | dump_raw_buffer(pdev->ctx->memory, |
3542 | | height, width, buf->n_planes, |
3543 | | pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride, |
3544 | | "put_image_final_small", buf_ptr, deep); |
3545 | | global_index++; |
3546 | | clist_band_count++; |
3547 | | #endif |
3548 | | |
3549 | 119k | for (i = 0; i < num_comp; i++) { |
3550 | 96.8k | planes[i].data = buf_ptr + i * planestride; |
3551 | 96.8k | planes[i].data_x = 0; |
3552 | 96.8k | planes[i].raster = buf->rowstride; |
3553 | 96.8k | } |
3554 | | |
3555 | 243k | for (y = 0; y < height; y++) { |
3556 | 221k | int rows_used; |
3557 | | |
3558 | 221k | info->procs->plane_data(info, (const gx_image_plane_t*) &planes, 1, &rows_used); |
3559 | | |
3560 | 1.18M | for (i = 0; i < num_comp; i++) { |
3561 | 962k | planes[i].data += buf->rowstride; |
3562 | 962k | } |
3563 | 221k | } |
3564 | 22.1k | info->procs->end_image(info, true); |
3565 | | |
3566 | | /* This will also decrement the profile */ |
3567 | 22.1k | rc_decrement_only_cs(pcs, "pdf14_put_blended_image_cmykspot"); |
3568 | 22.1k | return code; |
3569 | 22.1k | } |
3570 | | |
3571 | | /** |
3572 | | * pdf14_cmykspot_put_image: Put rendered image to target device. |
3573 | | * @pdev: The PDF 1.4 rendering device. |
3574 | | * @pgs: State for image draw operation. |
3575 | | * @target: The target device. |
3576 | | * |
3577 | | * Puts the rendered image in @pdev's buffer to @target. This is called |
3578 | | * as part of the sequence of popping the PDF 1.4 device filter. |
3579 | | * |
3580 | | * Return code: negative on error. |
3581 | | **/ |
3582 | | static int |
3583 | | pdf14_cmykspot_put_image(gx_device *dev, gs_gstate *pgs, gx_device *target) |
3584 | 69.5k | { |
3585 | 69.5k | pdf14_device *pdev = (pdf14_device *)dev; |
3586 | 69.5k | pdf14_buf *buf = pdev->ctx->stack; |
3587 | 69.5k | gs_int_rect rect; |
3588 | 69.5k | int x1, y1, width, height; |
3589 | 69.5k | gs_devn_params *pdevn_params = &pdev->devn_params; |
3590 | 69.5k | gs_separations *pseparations = &pdevn_params->separations; |
3591 | 69.5k | intptr_t planestride; |
3592 | 69.5k | intptr_t rowstride; |
3593 | 69.5k | bool deep = pdev->ctx->deep; |
3594 | 69.5k | int num_comp; |
3595 | | |
3596 | | /* Nothing was ever drawn. */ |
3597 | 69.5k | if (buf == NULL) |
3598 | 26.2k | return 0; |
3599 | | |
3600 | 43.3k | num_comp = buf->n_chan - 1; |
3601 | 43.3k | rect = buf->rect; |
3602 | 43.3k | planestride = buf->planestride; |
3603 | 43.3k | rowstride = buf->rowstride; |
3604 | | |
3605 | | /* Make sure that this is the only item on the stack. Fuzzing revealed a |
3606 | | potential problem. Bug 694190 */ |
3607 | 43.3k | if (buf->saved != NULL) { |
3608 | 1 | return gs_throw(gs_error_unknownerror, "PDF14 device push/pop out of sync"); |
3609 | 1 | } |
3610 | 43.3k | if_debug0m('v', dev->memory, "[v]pdf14_cmykspot_put_image\n"); |
3611 | 43.3k | rect_intersect(rect, buf->dirty); |
3612 | 43.3k | x1 = min(pdev->width, rect.q.x); |
3613 | 43.3k | y1 = min(pdev->height, rect.q.y); |
3614 | 43.3k | width = x1 - rect.p.x; |
3615 | 43.3k | height = y1 - rect.p.y; |
3616 | 43.3k | if (width <= 0 || height <= 0 || buf->data == NULL) |
3617 | 21.0k | return 0; |
3618 | | |
3619 | | #if RAW_DUMP |
3620 | | /* Dump the current buffer to see what we have. */ |
3621 | | dump_raw_buffer(pdev->ctx->memory, |
3622 | | pdev->ctx->stack->rect.q.y-pdev->ctx->stack->rect.p.y, |
3623 | | pdev->ctx->stack->rect.q.x-pdev->ctx->stack->rect.p.x, |
3624 | | pdev->ctx->stack->n_planes, |
3625 | | pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride, |
3626 | | "CMYK_SPOT_PUTIMAGE", pdev->ctx->stack->data, |
3627 | | pdev->ctx->stack->deep); |
3628 | | |
3629 | | global_index++; |
3630 | | clist_band_count++; |
3631 | | #endif |
3632 | | |
3633 | 22.2k | return pdf14_put_blended_image_cmykspot(dev, target, pgs, |
3634 | 22.2k | buf, planestride, rowstride, |
3635 | 22.2k | rect.p.x, rect.p.y, width, height, num_comp, buf->group_color_info->isadditive, |
3636 | 22.2k | buf->has_tags, rect, pseparations, deep); |
3637 | 43.3k | } |
3638 | | |
3639 | | /** |
3640 | | * pdf14_custom_put_image: Put rendered image to target device. |
3641 | | * @pdev: The PDF 1.4 rendering device. |
3642 | | * @pgs: State for image draw operation. |
3643 | | * @target: The target device. |
3644 | | * |
3645 | | * Puts the rendered image in @pdev's buffer to @target. This is called |
3646 | | * as part of the sequence of popping the PDF 1.4 device filter. |
3647 | | * |
3648 | | * Return code: negative on error. |
3649 | | **/ |
3650 | | static int |
3651 | | pdf14_custom_put_image(gx_device * dev, gs_gstate * pgs, gx_device * target) |
3652 | 0 | { |
3653 | 0 | pdf14_device * pdev = (pdf14_device *)dev; |
3654 | 0 | pdf14_buf *buf = pdev->ctx->stack; |
3655 | 0 | bool deep = pdev->ctx->deep; |
3656 | 0 | gs_int_rect rect; |
3657 | 0 | int x0, y0; |
3658 | 0 | intptr_t planestride; |
3659 | 0 | intptr_t rowstride; |
3660 | 0 | int num_comp; |
3661 | 0 | uint16_t bg; |
3662 | 0 | int x1, y1, width, height; |
3663 | 0 | byte *buf_ptr; |
3664 | | |
3665 | | /* Nothing was ever drawn. */ |
3666 | 0 | if (buf == NULL) |
3667 | 0 | return 0; |
3668 | | |
3669 | 0 | bg = pdev->ctx->additive ? 0xffff : 0; |
3670 | 0 | num_comp = buf->n_chan - 1; |
3671 | 0 | rect = buf->rect; |
3672 | 0 | x0 = rect.p.x; |
3673 | 0 | y0 = rect.p.y; |
3674 | 0 | planestride = buf->planestride; |
3675 | 0 | rowstride = buf->rowstride; |
3676 | | |
3677 | | /* Make sure that this is the only item on the stack. Fuzzing revealed a |
3678 | | potential problem. Bug 694190 */ |
3679 | 0 | if (buf->saved != NULL) { |
3680 | 0 | return gs_throw(gs_error_unknownerror, "PDF14 device push/pop out of sync"); |
3681 | 0 | } |
3682 | 0 | if_debug0m('v', dev->memory, "[v]pdf14_custom_put_image\n"); |
3683 | 0 | rect_intersect(rect, buf->dirty); |
3684 | 0 | x1 = min(pdev->width, rect.q.x); |
3685 | 0 | y1 = min(pdev->height, rect.q.y); |
3686 | 0 | width = x1 - rect.p.x; |
3687 | 0 | height = y1 - rect.p.y; |
3688 | 0 | if (width <= 0 || height <= 0 || buf->data == NULL) |
3689 | 0 | return 0; |
3690 | 0 | buf_ptr = buf->data + (rect.p.y - buf->rect.p.y) * buf->rowstride + ((rect.p.x - buf->rect.p.x)<<deep); |
3691 | |
|
3692 | 0 | return gx_put_blended_image_custom(target, buf_ptr, |
3693 | 0 | planestride, rowstride, |
3694 | 0 | x0, y0, width, height, num_comp, bg, deep); |
3695 | 0 | } |
3696 | | |
3697 | | /* This is rather nasty: in the event we are interrupted (by an error) between a push and pop |
3698 | | * of one or more groups, we have to cycle through any ICC profile changes since the push |
3699 | | * putting everything back how it was, and cleaning up the reference counts. |
3700 | | */ |
3701 | | static void pdf14_cleanup_group_color_profiles (pdf14_device *pdev) |
3702 | 2.29M | { |
3703 | 2.29M | if (pdev->ctx && pdev->ctx->stack) { |
3704 | 977k | pdf14_buf *buf, *next; |
3705 | | |
3706 | 978k | for (buf = pdev->ctx->stack->saved; buf != NULL; buf = next) { |
3707 | 322 | pdf14_group_color_t *group_color_info = buf->group_color_info; |
3708 | 322 | next = buf->saved; |
3709 | 644 | while (group_color_info) { |
3710 | 322 | if (group_color_info->icc_profile != NULL) { |
3711 | 322 | cmm_profile_t *group_profile; |
3712 | 322 | gsicc_rendering_param_t render_cond; |
3713 | 322 | cmm_dev_profile_t *dev_profile; |
3714 | 322 | int code = dev_proc((gx_device *)pdev, get_profile)((gx_device *)pdev, &dev_profile); |
3715 | | |
3716 | 322 | if (code >= 0) { |
3717 | 322 | gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &group_profile, |
3718 | 322 | &render_cond); |
3719 | | |
3720 | 322 | gsicc_adjust_profile_rc(pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], |
3721 | 322 | -1, "pdf14_end_transparency_group"); |
3722 | 322 | pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] = |
3723 | 322 | group_color_info->icc_profile; |
3724 | 322 | group_color_info->icc_profile = NULL; |
3725 | 322 | } |
3726 | 322 | } |
3727 | | |
3728 | 322 | group_color_info = group_color_info->previous; |
3729 | 322 | } |
3730 | 322 | } |
3731 | 977k | } |
3732 | 2.29M | } |
3733 | | |
3734 | | static int |
3735 | | pdf14_close(gx_device *dev) |
3736 | 1.14M | { |
3737 | 1.14M | pdf14_device *pdev = (pdf14_device *)dev; |
3738 | | |
3739 | 1.14M | pdf14_cleanup_group_color_profiles(pdev); |
3740 | | |
3741 | 1.14M | if (pdev->ctx) { |
3742 | 1.14M | pdf14_ctx_free(pdev->ctx); |
3743 | 1.14M | pdev->ctx = NULL; |
3744 | 1.14M | } |
3745 | 1.14M | return 0; |
3746 | 1.14M | } |
3747 | | |
3748 | | /* This is called when something has gone wrong and the interpreter received a |
3749 | | stop while in the middle of doing something with the PDF14 device. We need |
3750 | | to clean up and end this in a graceful manner */ |
3751 | | static int |
3752 | | pdf14_discard_trans_layer(gx_device *dev, gs_gstate * pgs) |
3753 | 0 | { |
3754 | 0 | pdf14_device *pdev = (pdf14_device *)dev; |
3755 | | /* The things that need to be cleaned up */ |
3756 | 0 | pdf14_ctx *ctx = pdev->ctx; |
3757 | 0 | pdf14_smaskcolor_t *smaskcolor = pdev->smaskcolor; |
3758 | 0 | pdf14_group_color_t *group_color = pdev->color_model_stack; |
3759 | | |
3760 | | /* Free up the smask color */ |
3761 | 0 | if (smaskcolor != NULL) { |
3762 | 0 | smaskcolor->ref_count = 1; |
3763 | 0 | pdf14_decrement_smask_color(pgs, dev); |
3764 | 0 | pdev->smaskcolor = NULL; |
3765 | 0 | } |
3766 | | |
3767 | | /* Free up the nested color procs and decrement the profiles */ |
3768 | 0 | if (group_color != NULL) { |
3769 | 0 | while (group_color->previous != NULL) |
3770 | 0 | pdf14_pop_group_color(dev, pgs); |
3771 | 0 | gs_free_object(dev->memory->stable_memory, group_color, "pdf14_discard_trans_layer"); |
3772 | 0 | pdev->color_model_stack = NULL; |
3773 | 0 | } |
3774 | | |
3775 | | /* Start the context clean up */ |
3776 | 0 | if (ctx != NULL) { |
3777 | 0 | pdf14_buf *buf, *next; |
3778 | 0 | pdf14_group_color_t *procs, *prev_procs; |
3779 | |
|
3780 | 0 | if (ctx->mask_stack != NULL) { |
3781 | 0 | rc_decrement(ctx->mask_stack, "pdf14_discard_trans_layer"); |
3782 | 0 | } |
3783 | | |
3784 | | /* Now the stack of buffers */ |
3785 | 0 | for (buf = ctx->stack; buf != NULL; buf = next) { |
3786 | 0 | next = buf->saved; |
3787 | |
|
3788 | 0 | gs_free_object(ctx->memory, buf->transfer_fn, "pdf14_discard_trans_layer"); |
3789 | 0 | gs_free_object(ctx->memory, buf->matte, "pdf14_discard_trans_layer"); |
3790 | 0 | gs_free_object(ctx->memory, buf->data, "pdf14_discard_trans_layer"); |
3791 | 0 | gs_free_object(ctx->memory, buf->backdrop, "pdf14_discard_trans_layer"); |
3792 | | /* During the soft mask push, the mask_stack was copied (not moved) from |
3793 | | the ctx to the tos mask_stack. We are done with this now so it is safe |
3794 | | to free this one object */ |
3795 | 0 | gs_free_object(ctx->memory, buf->mask_stack, "pdf14_discard_trans_layer"); |
3796 | 0 | for (procs = buf->group_color_info; procs != NULL; procs = prev_procs) { |
3797 | 0 | prev_procs = procs->previous; |
3798 | 0 | gs_free_object(ctx->memory, procs, "pdf14_discard_trans_layer"); |
3799 | 0 | } |
3800 | 0 | gs_free_object(ctx->memory, buf, "pdf14_discard_trans_layer"); |
3801 | 0 | } |
3802 | | /* Finally the context itself */ |
3803 | 0 | gs_free_object(ctx->memory, ctx, "pdf14_discard_trans_layer"); |
3804 | 0 | pdev->ctx = NULL; |
3805 | 0 | } |
3806 | 0 | return 0; |
3807 | 0 | } |
3808 | | |
3809 | | static int |
3810 | | pdf14_output_page(gx_device * dev, int num_copies, int flush) |
3811 | 0 | { |
3812 | 0 | pdf14_device * pdev = (pdf14_device *)dev; |
3813 | |
|
3814 | 0 | if (pdev->target != NULL) |
3815 | 0 | return (*dev_proc(pdev->target, output_page)) (pdev->target, num_copies, flush); |
3816 | 0 | return 0; |
3817 | 0 | } |
3818 | | |
3819 | 9.25M | #define COPY_PARAM(p) dev->p = target->p |
3820 | 5.78M | #define COPY_ARRAY_PARAM(p) memcpy(dev->p, target->p, sizeof(dev->p)) |
3821 | | |
3822 | | static void |
3823 | | copy_tag_setup(gx_device *dev, const gx_device *target) |
3824 | 1.15M | { |
3825 | 1.15M | bool deep = device_is_deep(target); |
3826 | 1.15M | int had_tags = (dev->graphics_type_tag & GS_DEVICE_ENCODES_TAGS) != 0; |
3827 | 1.15M | int has_tags = (target->graphics_type_tag & GS_DEVICE_ENCODES_TAGS) != 0; |
3828 | 1.15M | COPY_PARAM(graphics_type_tag); |
3829 | 1.15M | if (had_tags && !has_tags) |
3830 | 0 | { |
3831 | | /* We have just removed a tags plane. Adjust num_components and depth accordingly. */ |
3832 | 0 | dev->color_info.num_components--; |
3833 | 0 | dev->color_info.depth -= deep ? 16 : 8; |
3834 | 0 | } |
3835 | 1.15M | else if (!had_tags && has_tags) |
3836 | 0 | { |
3837 | | /* We have just added a tags plane. Adjust num_components and depth accordingly. */ |
3838 | 0 | dev->color_info.num_components++; |
3839 | 0 | dev->color_info.depth += deep ? 16 : 8; |
3840 | 0 | } |
3841 | 1.15M | } |
3842 | | |
3843 | | /* |
3844 | | * Copy device parameters back from a target. This copies all standard |
3845 | | * parameters related to page size and resolution, but not any of the |
3846 | | * color-related parameters, as the pdf14 device retains its own color |
3847 | | * handling. This routine is parallel to gx_device_copy_params(). |
3848 | | * Note that it DOES copy the devn_params since these are required to |
3849 | | * keep agreement with colorant name->number mapping, and don't change |
3850 | | * with the pdf14 color handling. |
3851 | | */ |
3852 | | static int |
3853 | | gs_pdf14_device_copy_params(gx_device *dev, const gx_device *target) |
3854 | 1.15M | { |
3855 | 1.15M | cmm_dev_profile_t *profile_targ; |
3856 | 1.15M | cmm_dev_profile_t *profile_dev14; |
3857 | 1.15M | pdf14_device *pdev = (pdf14_device*) dev; |
3858 | 1.15M | cmm_profile_t *blend_profile = NULL; |
3859 | 1.15M | int k; |
3860 | | |
3861 | 1.15M | COPY_PARAM(width); |
3862 | 1.15M | COPY_PARAM(height); |
3863 | 1.15M | COPY_ARRAY_PARAM(MediaSize); |
3864 | 1.15M | COPY_ARRAY_PARAM(ImagingBBox); |
3865 | 1.15M | COPY_PARAM(ImagingBBox_set); |
3866 | 1.15M | COPY_ARRAY_PARAM(HWResolution); |
3867 | 1.15M | COPY_ARRAY_PARAM(Margins); |
3868 | 1.15M | COPY_ARRAY_PARAM(HWMargins); |
3869 | 1.15M | COPY_PARAM(PageCount); |
3870 | 1.15M | COPY_PARAM(MaxPatternBitmap); |
3871 | | |
3872 | | |
3873 | | /* Supposedly this function isn't supposed to change the color setup of dev. |
3874 | | * BUT... if we change the tags value, we have to change the color setup to |
3875 | | * keep it valid. This is because num_components and depth include tags. */ |
3876 | 1.15M | copy_tag_setup(dev, target); |
3877 | 1.15M | COPY_PARAM(interpolate_control); |
3878 | 1.15M | COPY_PARAM(non_strict_bounds); |
3879 | 1.15M | memcpy(&(dev->space_params), &(target->space_params), sizeof(gdev_space_params)); |
3880 | | |
3881 | 1.15M | if (dev->icc_struct == NULL) { |
3882 | 1.15M | dev->icc_struct = gsicc_new_device_profile_array(dev); |
3883 | 1.15M | if (dev->icc_struct == NULL) |
3884 | 0 | return_error(gs_error_VMerror); |
3885 | 1.15M | profile_dev14 = dev->icc_struct; |
3886 | 1.15M | dev_proc((gx_device *) target, get_profile)((gx_device *) target, |
3887 | 1.15M | &(profile_targ)); |
3888 | | |
3889 | 5.78M | for (k = 0; k < NUM_DEVICE_PROFILES; k++) { |
3890 | 4.62M | if (profile_targ->device_profile[k] != NULL) { |
3891 | 1.15M | gsicc_adjust_profile_rc(profile_targ->device_profile[k], 1, "gs_pdf14_device_copy_params"); |
3892 | 1.15M | } |
3893 | 4.62M | if (profile_dev14->device_profile[k] != NULL) { |
3894 | 0 | gsicc_adjust_profile_rc(profile_dev14->device_profile[k], -1, "gs_pdf14_device_copy_params"); |
3895 | 0 | } |
3896 | 4.62M | profile_dev14->device_profile[k] = profile_targ->device_profile[k]; |
3897 | 4.62M | profile_dev14->rendercond[k] = profile_targ->rendercond[k]; |
3898 | 4.62M | } |
3899 | | |
3900 | 1.15M | dev->icc_struct->devicegraytok = profile_targ->devicegraytok; |
3901 | 1.15M | dev->icc_struct->graydetection = profile_targ->graydetection; |
3902 | 1.15M | dev->icc_struct->pageneutralcolor = profile_targ->pageneutralcolor; |
3903 | 1.15M | dev->icc_struct->supports_devn = profile_targ->supports_devn; |
3904 | 1.15M | dev->icc_struct->usefastcolor = profile_targ->usefastcolor; |
3905 | 1.15M | dev->icc_struct->blacktext = profile_targ->blacktext; |
3906 | 1.15M | dev->icc_struct->blackvector = profile_targ->blackvector; |
3907 | 1.15M | dev->icc_struct->blackthresholdL = profile_targ->blackthresholdL; |
3908 | 1.15M | dev->icc_struct->blackthresholdC = profile_targ->blackthresholdC; |
3909 | | |
3910 | 1.15M | switch (pdev->blend_cs_state) { |
3911 | 1.15M | case PDF14_BLEND_CS_UNSPECIFIED: |
3912 | 1.15M | case PDF14_BLEND_CS_TARGET_CIELAB: |
3913 | | /* PDF14_BLEND_CS_TARGET_CIELAB handled |
3914 | | during the device push, when we have |
3915 | | access to the pgs */ |
3916 | 1.15M | break; |
3917 | 0 | case PDF14_BLEND_CS_OUTPUTINTENT: |
3918 | 0 | blend_profile = profile_targ->oi_profile; |
3919 | 0 | break; |
3920 | 0 | case PDF14_BLEND_CS_SPECIFIED: |
3921 | 0 | blend_profile = profile_targ->blend_profile; |
3922 | 0 | break; |
3923 | 0 | default: |
3924 | 0 | break; |
3925 | 1.15M | } |
3926 | | |
3927 | 1.15M | if (blend_profile != NULL) { |
3928 | | /* Set the device profile to the blend profile. Note only default profile is set */ |
3929 | 0 | gsicc_adjust_profile_rc(blend_profile, 1, "gs_pdf14_device_copy_params"); |
3930 | 0 | gsicc_adjust_profile_rc(profile_dev14->device_profile[GS_DEFAULT_DEVICE_PROFILE], -1, "gs_pdf14_device_copy_params"); |
3931 | 0 | profile_dev14->device_profile[GS_DEFAULT_DEVICE_PROFILE] = blend_profile; |
3932 | 0 | } |
3933 | | |
3934 | 1.15M | profile_dev14->overprint_control = profile_targ->overprint_control; |
3935 | 1.15M | } |
3936 | 1.15M | #undef COPY_ARRAY_PARAM |
3937 | 1.15M | #undef COPY_PARAM |
3938 | 1.15M | return 0; |
3939 | 1.15M | } |
3940 | | |
3941 | | /* |
3942 | | * This is a forwarding version of the put_params device proc. It is only |
3943 | | * used when the PDF 1.4 compositor devices are closed. The routine will |
3944 | | * check if the target device has closed and, if so, close itself. The routine |
3945 | | * also sync the device parameters. |
3946 | | */ |
3947 | | static int |
3948 | | pdf14_forward_put_params(gx_device * dev, gs_param_list * plist) |
3949 | 0 | { |
3950 | 0 | pdf14_device * pdev = (pdf14_device *)dev; |
3951 | 0 | gx_device * tdev = pdev->target; |
3952 | 0 | bool was_open = tdev->is_open; |
3953 | 0 | int code = 0; |
3954 | |
|
3955 | 0 | if (tdev != 0 && (code = dev_proc(tdev, put_params)(tdev, plist)) >= 0) { |
3956 | 0 | gx_device_decache_colors(dev); |
3957 | 0 | if (!tdev->is_open) { |
3958 | 0 | code = gs_closedevice(dev); |
3959 | 0 | if (code == 0) |
3960 | 0 | code = was_open ? 1 : 0; /* target device closed */ |
3961 | 0 | } |
3962 | 0 | gx_device_copy_params(dev, tdev); |
3963 | 0 | } |
3964 | 0 | return code; |
3965 | 0 | } |
3966 | | |
3967 | | /* Function prototypes */ |
3968 | | int put_param_pdf14_spot_names(gx_device * pdev, |
3969 | | gs_separations * pseparations, gs_param_list * plist); |
3970 | 107k | #define PDF14NumSpotColorsParamName "PDF14NumSpotColors" |
3971 | | |
3972 | | /* |
3973 | | * The put_params method for the PDF 1.4 device will check if the |
3974 | | * target device has closed and, if so, close itself. Note: This routine is |
3975 | | * currently being used by both the pdf14_clist_device and the pdf_device. |
3976 | | * Please make sure that any changes are either applicable to both devices |
3977 | | * or clone the routine for each device. |
3978 | | */ |
3979 | | static int |
3980 | | pdf14_put_params(gx_device * dev, gs_param_list * plist) |
3981 | 0 | { |
3982 | 0 | pdf14_device * pdev = (pdf14_device *)dev; |
3983 | 0 | gx_device * tdev = pdev->target; |
3984 | 0 | bool was_open = tdev->is_open; |
3985 | 0 | int code = 0, code2 = 0; |
3986 | |
|
3987 | 0 | if (tdev != 0 && (code = dev_proc(tdev, put_params)(tdev, plist)) >= 0) { |
3988 | 0 | gx_device_decache_colors(dev); |
3989 | 0 | if (!tdev->is_open) { |
3990 | 0 | code = gs_closedevice(dev); |
3991 | 0 | if (code == 0) |
3992 | 0 | code = was_open ? 1 : 0; /* target device closed */ |
3993 | 0 | } |
3994 | 0 | code2 = gs_pdf14_device_copy_params(dev, tdev); |
3995 | 0 | if (code2 < 0) |
3996 | 0 | code = code2; |
3997 | 0 | } |
3998 | 0 | return code; |
3999 | 0 | } |
4000 | | |
4001 | | /* |
4002 | | * Copy marking related parameters into the PDF 1.4 device structure for use |
4003 | | * by pdf14_fill_rectangle. |
4004 | | */ |
4005 | | static void |
4006 | | pdf14_set_marking_params(gx_device *dev, const gs_gstate *pgs) |
4007 | 27.7M | { |
4008 | 27.7M | pdf14_device * pdev = (pdf14_device *)dev; |
4009 | | |
4010 | 27.7M | if (pgs->alphaisshape) { |
4011 | 327k | pdev->opacity = 1.0; |
4012 | 327k | if (pgs->is_fill_color) { |
4013 | 321k | pdev->shape = pgs->fillconstantalpha; |
4014 | 321k | } else { |
4015 | 6.44k | pdev->shape = pgs->strokeconstantalpha; |
4016 | 6.44k | } |
4017 | 27.3M | } else { |
4018 | 27.3M | pdev->shape = 1.0; |
4019 | 27.3M | if (pgs->is_fill_color) { |
4020 | 11.4M | pdev->opacity = pgs->fillconstantalpha; |
4021 | 15.9M | } else { |
4022 | 15.9M | pdev->opacity = pgs->strokeconstantalpha; |
4023 | 15.9M | } |
4024 | 27.3M | } |
4025 | 27.7M | pdev->alpha = pdev->opacity * pdev->shape; |
4026 | 27.7M | pdev->blend_mode = pgs->blend_mode; |
4027 | 27.7M | if (pdev->icc_struct->overprint_control != gs_overprint_control_disable) { |
4028 | 27.7M | pdev->overprint = pgs->overprint; |
4029 | 27.7M | pdev->stroke_overprint = pgs->stroke_overprint; |
4030 | 27.7M | } else { |
4031 | 0 | pdev->overprint = false; |
4032 | 0 | pdev->stroke_overprint = false; |
4033 | 0 | } |
4034 | | |
4035 | 27.7M | pdev->fillconstantalpha = pgs->fillconstantalpha; |
4036 | 27.7M | pdev->strokeconstantalpha = pgs->strokeconstantalpha; |
4037 | | |
4038 | 27.7M | if (pgs->is_fill_color) |
4039 | 11.8M | pdev->op_state = PDF14_OP_STATE_FILL; |
4040 | 15.9M | else |
4041 | 15.9M | pdev->op_state = PDF14_OP_STATE_STROKE; |
4042 | | |
4043 | 27.7M | if_debug6m('v', dev->memory, |
4044 | 27.7M | "[v]set_marking_params, opacity = %g, shape = %g, bm = %d, op = %d, eop = %d seop = %d\n", |
4045 | 27.7M | pdev->opacity, pdev->shape, pgs->blend_mode, pgs->overprint, pdev->effective_overprint_mode, |
4046 | 27.7M | pdev->stroke_effective_op_mode); |
4047 | 27.7M | } |
4048 | | |
4049 | | static void |
4050 | | update_lop_for_pdf14(gs_gstate *pgs, const gx_drawing_color *pdcolor) |
4051 | 19.1M | { |
4052 | 19.1M | bool hastrans = false; |
4053 | | |
4054 | | /* We'd really rather not have to set the pdf14 bit in the lop, as this |
4055 | | * makes other operations much slower. We have no option however, if the |
4056 | | * current colour involves transparency, or if it's anything other than |
4057 | | * a completely solid (or transparent) operation in the normal blend mode. |
4058 | | */ |
4059 | 19.1M | if (pdcolor != NULL) |
4060 | 19.1M | { |
4061 | 19.1M | if (gx_dc_is_pattern1_color(pdcolor) && |
4062 | 495k | gx_pattern1_get_transptr(pdcolor) != NULL) { |
4063 | 4.86k | hastrans = true; |
4064 | 19.1M | } else if (gx_dc_is_pattern2_color(pdcolor)) { |
4065 | | /* FIXME: Here we assume that ALL type 2 patterns are |
4066 | | * transparent - this test could be better. */ |
4067 | 4.83k | hastrans = true; |
4068 | 4.83k | } |
4069 | 19.1M | } |
4070 | | /* The only idempotent blend modes are Normal, Darken and Lighten. |
4071 | | This appears to be the only place where this test is done so |
4072 | | not adding a is_idempotent method */ |
4073 | 19.1M | if ((pgs->blend_mode != BLEND_MODE_Normal && |
4074 | 161k | pgs->blend_mode != BLEND_MODE_Darken && |
4075 | 155k | pgs->blend_mode != BLEND_MODE_Lighten) || |
4076 | 19.0M | (pgs->fillconstantalpha != 1.0) || |
4077 | 18.8M | (pgs->strokeconstantalpha != 1.0) || |
4078 | 18.7M | (hastrans)) |
4079 | 401k | { |
4080 | | /* |
4081 | | * The blend operations are not idempotent. Force non-idempotent |
4082 | | * filling and stroking operations. |
4083 | | */ |
4084 | 401k | pgs->log_op |= lop_pdf14; |
4085 | 401k | } |
4086 | 19.1M | } |
4087 | | |
4088 | | static int |
4089 | | push_shfill_group(pdf14_clist_device *pdev, |
4090 | | gs_gstate *pgs, |
4091 | | gs_fixed_rect *box) |
4092 | 40 | { |
4093 | 40 | gs_transparency_group_params_t params = { 0 }; |
4094 | 40 | int code; |
4095 | 40 | gs_rect cb; |
4096 | 40 | gs_gstate fudged_pgs = *pgs; |
4097 | | |
4098 | 40 | params.shade_group = true; |
4099 | | |
4100 | | /* gs_begin_transparency_group takes a bbox that it then |
4101 | | * transforms by ctm. Our bbox has already been transformed, |
4102 | | * so clear out the ctm. */ |
4103 | 40 | fudged_pgs.ctm.xx = 1.0; |
4104 | 40 | fudged_pgs.ctm.xy = 0; |
4105 | 40 | fudged_pgs.ctm.yx = 0; |
4106 | 40 | fudged_pgs.ctm.yy = 1.0; |
4107 | 40 | fudged_pgs.ctm.tx = 0; |
4108 | 40 | fudged_pgs.ctm.ty = 0; |
4109 | 40 | cb.p.x = fixed2int_pixround(box->p.x); |
4110 | 40 | cb.p.y = fixed2int_pixround(box->p.y); |
4111 | 40 | cb.q.x = fixed2int_pixround(box->q.x); |
4112 | 40 | cb.q.y = fixed2int_pixround(box->q.y); |
4113 | | |
4114 | 40 | params.Isolated = false; |
4115 | 40 | params.Knockout = true; |
4116 | 40 | params.page_group = false; |
4117 | 40 | params.group_opacity = fudged_pgs.fillconstantalpha; |
4118 | 40 | params.group_shape = 1.0; |
4119 | 40 | code = gs_begin_transparency_group(&fudged_pgs, ¶ms, &cb, PDF14_BEGIN_TRANS_GROUP); |
4120 | | |
4121 | | /* We have the group handle the blendmode and the opacity, |
4122 | | * and continue with the existing graphics state reset |
4123 | | * to normal, opaque operation. We could do it the other |
4124 | | * way around, but this way means that if we push a knockout |
4125 | | * group for a stroke, and then the code calls back into |
4126 | | * the fill operation as part of doing the stroking, we don't |
4127 | | * push another one. */ |
4128 | 40 | gs_setblendmode(pgs, BLEND_MODE_Normal); |
4129 | 40 | gs_setfillconstantalpha(pgs, 1.0); |
4130 | 40 | gs_setstrokeconstantalpha(pgs, 1.0); |
4131 | 40 | if (pdev) { |
4132 | 40 | code = pdf14_clist_update_params(pdev, pgs, false, NULL); |
4133 | 40 | if (code < 0) |
4134 | 0 | return code; |
4135 | 40 | } |
4136 | | |
4137 | 40 | return code; |
4138 | 40 | } |
4139 | | |
4140 | | static int |
4141 | | pop_shfill_group(gs_gstate *pgs) |
4142 | 38 | { |
4143 | 38 | return gs_end_transparency_group(pgs); |
4144 | 38 | } |
4145 | | |
4146 | | static int |
4147 | | pdf14_fill_path(gx_device *dev, const gs_gstate *pgs, |
4148 | | gx_path *ppath, const gx_fill_params *params, |
4149 | | const gx_drawing_color *pdcolor, |
4150 | | const gx_clip_path *pcpath) |
4151 | 16.5M | { |
4152 | 16.5M | gs_gstate new_pgs = *pgs; |
4153 | 16.5M | int code = 0; |
4154 | 16.5M | gs_pattern2_instance_t *pinst = NULL; |
4155 | 16.5M | int push_group = 0; |
4156 | | |
4157 | 16.5M | code = pdf14_initialize_ctx(dev, pgs); |
4158 | 16.5M | if (code < 0) |
4159 | 0 | return code; |
4160 | | |
4161 | 16.5M | if (pdcolor == NULL) |
4162 | 0 | return_error(gs_error_unknownerror); /* color must be defined */ |
4163 | 16.5M | ((pdf14_device *)dev)->op_state = pgs->is_fill_color ? PDF14_OP_STATE_FILL : PDF14_OP_STATE_STROKE; |
4164 | 16.5M | if (gx_dc_is_pattern1_color(pdcolor)){ |
4165 | 553k | if( gx_pattern1_get_transptr(pdcolor) != NULL || |
4166 | 533k | gx_pattern1_clist_has_trans(pdcolor) ){ |
4167 | | /* In this case, we need to push a transparency group |
4168 | | and tile the pattern color, which is stored in |
4169 | | a pdf14 device buffer in the ctile object memember |
4170 | | variable ttrans */ |
4171 | | #if RAW_DUMP |
4172 | | /* Since we do not get a put_image to view what |
4173 | | we have do it now */ |
4174 | | if (gx_pattern1_get_transptr(pdcolor) != NULL) { |
4175 | | const pdf14_device * ppatdev14 = (const pdf14_device *) |
4176 | | pdcolor->colors.pattern.p_tile->ttrans->pdev14; |
4177 | | if (ppatdev14 != NULL) { /* can occur during clist reading */ |
4178 | | byte *buf_ptr = ppatdev14->ctx->stack->data + |
4179 | | ppatdev14->ctx->stack->rect.p.y * |
4180 | | ppatdev14->ctx->stack->rowstride + |
4181 | | ppatdev14->ctx->stack->rect.p.x; |
4182 | | dump_raw_buffer(ppatdev14->ctx->memory, |
4183 | | (ppatdev14->ctx->stack->rect.q.y - |
4184 | | ppatdev14->ctx->stack->rect.p.y), |
4185 | | (ppatdev14->ctx->stack->rect.q.x - |
4186 | | ppatdev14->ctx->stack->rect.p.x), |
4187 | | ppatdev14->ctx->stack->n_planes, |
4188 | | ppatdev14->ctx->stack->planestride, |
4189 | | ppatdev14->ctx->stack->rowstride, |
4190 | | "Pattern_Fill", buf_ptr, |
4191 | | ppatdev14->ctx->stack->deep); |
4192 | | global_index++; |
4193 | | } else { |
4194 | | gx_pattern_trans_t *patt_trans = |
4195 | | pdcolor->colors.pattern.p_tile->ttrans; |
4196 | | dump_raw_buffer(patt_trans->mem, |
4197 | | patt_trans->rect.q.y-patt_trans->rect.p.y, |
4198 | | patt_trans->rect.q.x-patt_trans->rect.p.x, |
4199 | | patt_trans->n_chan, |
4200 | | patt_trans->planestride, patt_trans->rowstride, |
4201 | | "Pattern_Fill_clist", |
4202 | | patt_trans->transbytes + |
4203 | | patt_trans->rect.p.y * patt_trans->rowstride + |
4204 | | (patt_trans->rect.p.x<<patt_trans->deep), |
4205 | | patt_trans->deep); |
4206 | | global_index++; |
4207 | | } |
4208 | | } |
4209 | | #endif |
4210 | 66.4k | pdf14_set_marking_params(dev, &new_pgs); |
4211 | 66.4k | code = pdf14_tile_pattern_fill(dev, &new_pgs, ppath, |
4212 | 66.4k | params, pdcolor, pcpath); |
4213 | 66.4k | new_pgs.trans_device = NULL; |
4214 | 66.4k | new_pgs.has_transparency = false; |
4215 | 66.4k | return code; |
4216 | 66.4k | } |
4217 | 553k | } |
4218 | 16.4M | if (gx_dc_is_pattern2_color(pdcolor) || |
4219 | 16.4M | pdcolor->type == &gx_dc_devn_masked) { |
4220 | | /* Non-idempotent blends require a transparency |
4221 | | * group to be pushed because shadings might |
4222 | | * paint several pixels twice. */ |
4223 | 12 | push_group = pgs->fillconstantalpha != 1.0 || |
4224 | 12 | !blend_is_idempotent(gs_currentblendmode(pgs)); |
4225 | 12 | pinst = |
4226 | 12 | (gs_pattern2_instance_t *)pdcolor->ccolor.pattern; |
4227 | 12 | pinst->saved->has_transparency = true; |
4228 | | /* The transparency color space operations are driven |
4229 | | by the pdf14 clist writer device. */ |
4230 | 12 | pinst->saved->trans_device = dev; |
4231 | 12 | } |
4232 | 16.4M | if (push_group) { |
4233 | 0 | gs_fixed_rect box; |
4234 | 0 | if (pcpath) |
4235 | 0 | gx_cpath_outer_box(pcpath, &box); |
4236 | 0 | else |
4237 | 0 | (*dev_proc(dev, get_clipping_box)) (dev, &box); |
4238 | 0 | if (ppath) { |
4239 | 0 | gs_fixed_rect path_box; |
4240 | |
|
4241 | 0 | gx_path_bbox(ppath, &path_box); |
4242 | 0 | if (box.p.x < path_box.p.x) |
4243 | 0 | box.p.x = path_box.p.x; |
4244 | 0 | if (box.p.y < path_box.p.y) |
4245 | 0 | box.p.y = path_box.p.y; |
4246 | 0 | if (box.q.x > path_box.q.x) |
4247 | 0 | box.q.x = path_box.q.x; |
4248 | 0 | if (box.q.y > path_box.q.y) |
4249 | 0 | box.q.y = path_box.q.y; |
4250 | 0 | } |
4251 | | /* Group alpha set from fill value. push_shfill_group does reset to 1.0 */ |
4252 | 0 | code = push_shfill_group(NULL, &new_pgs, &box); |
4253 | 0 | } else |
4254 | 16.4M | update_lop_for_pdf14(&new_pgs, pdcolor); |
4255 | 16.4M | pdf14_set_marking_params(dev, &new_pgs); |
4256 | 16.4M | if (code >= 0) { |
4257 | 16.4M | new_pgs.trans_device = dev; |
4258 | 16.4M | new_pgs.has_transparency = true; |
4259 | | /* ppath can permissibly be NULL here, if we want to have a |
4260 | | * shading or a pattern fill the clipping path. This upsets |
4261 | | * coverity, which is not smart enough to realise that the |
4262 | | * validity of a NULL ppath depends on the type of pdcolor. |
4263 | | * We'll mark it as a false positive. */ |
4264 | 16.4M | code = gx_default_fill_path(dev, &new_pgs, ppath, params, pdcolor, pcpath); |
4265 | 16.4M | new_pgs.trans_device = NULL; |
4266 | 16.4M | new_pgs.has_transparency = false; |
4267 | 16.4M | } |
4268 | 16.4M | if (code >= 0 && push_group) { |
4269 | 0 | code = pop_shfill_group(&new_pgs); |
4270 | 0 | pdf14_set_marking_params(dev, pgs); |
4271 | 0 | } |
4272 | 16.4M | if (pinst != NULL){ |
4273 | 12 | pinst->saved->trans_device = NULL; |
4274 | 12 | } |
4275 | 16.4M | return code; |
4276 | 16.5M | } |
4277 | | |
4278 | | static int |
4279 | | pdf14_stroke_path(gx_device *dev, const gs_gstate *pgs, |
4280 | | gx_path *ppath, const gx_stroke_params *params, |
4281 | | const gx_drawing_color *pdcolor, |
4282 | | const gx_clip_path *pcpath) |
4283 | 1.39M | { |
4284 | 1.39M | gs_gstate new_pgs = *pgs; |
4285 | 1.39M | int push_group = 0; |
4286 | 1.39M | int code = 0; |
4287 | | |
4288 | 1.39M | if (pdcolor == NULL) |
4289 | 0 | return_error(gs_error_unknownerror); /* color must be defined */ |
4290 | | |
4291 | 1.39M | code = pdf14_initialize_ctx(dev, pgs); |
4292 | 1.39M | if (code < 0) |
4293 | 0 | return code; |
4294 | | |
4295 | 1.39M | if (gx_dc_is_pattern2_color(pdcolor)) { |
4296 | | /* Non-idempotent blends require a transparency |
4297 | | * group to be pushed because shadings might |
4298 | | * paint several pixels twice. */ |
4299 | 0 | push_group = pgs->strokeconstantalpha != 1.0 || |
4300 | 0 | !blend_is_idempotent(gs_currentblendmode(pgs)); |
4301 | 0 | } |
4302 | 1.39M | if (push_group) { |
4303 | 0 | gs_fixed_rect box; |
4304 | 0 | if (pcpath) |
4305 | 0 | gx_cpath_outer_box(pcpath, &box); |
4306 | 0 | else |
4307 | 0 | (*dev_proc(dev, get_clipping_box)) (dev, &box); |
4308 | | |
4309 | | /* For fill_path, we accept ppath == NULL to mean |
4310 | | * fill the entire clipping region. That makes no |
4311 | | * sense for stroke_path, hence ppath is always non |
4312 | | * NULL here. */ |
4313 | 0 | { |
4314 | 0 | gs_fixed_rect path_box; |
4315 | 0 | gs_fixed_point expansion; |
4316 | |
|
4317 | 0 | gx_path_bbox(ppath, &path_box); |
4318 | | /* Expand the path bounding box by the scaled line width. */ |
4319 | 0 | if (gx_stroke_path_expansion(pgs, ppath, &expansion) < 0) { |
4320 | | /* The expansion is so large it caused a limitcheck. */ |
4321 | 0 | path_box.p.x = path_box.p.y = min_fixed; |
4322 | 0 | path_box.q.x = path_box.q.y = max_fixed; |
4323 | 0 | } else { |
4324 | 0 | expansion.x += pgs->fill_adjust.x; |
4325 | 0 | expansion.y += pgs->fill_adjust.y; |
4326 | | /* |
4327 | | * It's theoretically possible for the following computations to |
4328 | | * overflow, so we need to check for this. |
4329 | | */ |
4330 | 0 | path_box.p.x = (path_box.p.x < min_fixed + expansion.x ? min_fixed : |
4331 | 0 | path_box.p.x - expansion.x); |
4332 | 0 | path_box.p.y = (path_box.p.y < min_fixed + expansion.y ? min_fixed : |
4333 | 0 | path_box.p.y - expansion.y); |
4334 | 0 | path_box.q.x = (path_box.q.x > max_fixed - expansion.x ? max_fixed : |
4335 | 0 | path_box.q.x + expansion.x); |
4336 | 0 | path_box.q.y = (path_box.q.y > max_fixed - expansion.y ? max_fixed : |
4337 | 0 | path_box.q.y + expansion.y); |
4338 | 0 | } |
4339 | 0 | if (box.p.x < path_box.p.x) |
4340 | 0 | box.p.x = path_box.p.x; |
4341 | 0 | if (box.p.y < path_box.p.y) |
4342 | 0 | box.p.y = path_box.p.y; |
4343 | 0 | if (box.q.x > path_box.q.x) |
4344 | 0 | box.q.x = path_box.q.x; |
4345 | 0 | if (box.q.y > path_box.q.y) |
4346 | 0 | box.q.y = path_box.q.y; |
4347 | 0 | } |
4348 | | /* Group alpha set from fill value. push_shfill_group does reset to 1.0 */ |
4349 | 0 | new_pgs.fillconstantalpha = new_pgs.strokeconstantalpha; |
4350 | 0 | code = push_shfill_group(NULL, &new_pgs, &box); |
4351 | 0 | } else |
4352 | 1.39M | update_lop_for_pdf14(&new_pgs, pdcolor); |
4353 | 1.39M | pdf14_set_marking_params(dev, &new_pgs); |
4354 | 1.39M | if (code >= 0) { |
4355 | 1.39M | PDF14_OP_FS_STATE save_op_state = ((pdf14_device *)dev)->op_state; |
4356 | | |
4357 | 1.39M | ((pdf14_device*)dev)->op_state = PDF14_OP_STATE_STROKE; |
4358 | 1.39M | code = gx_default_stroke_path(dev, &new_pgs, ppath, params, pdcolor, pcpath); |
4359 | 1.39M | ((pdf14_device*)dev)->op_state = save_op_state; |
4360 | 1.39M | } |
4361 | 1.39M | if (code >= 0 && push_group) { |
4362 | 0 | code = pop_shfill_group(&new_pgs); |
4363 | 0 | pdf14_set_marking_params(dev, pgs); |
4364 | 0 | } |
4365 | | |
4366 | 1.39M | return code; |
4367 | 1.39M | } |
4368 | | |
4369 | | /* Pull out steps of transparency updates for fill/stroke |
4370 | | so that they can be invoked elsewhere (e.g. |
4371 | | when the abuf device is handling the stroke/fill */ |
4372 | | |
4373 | | /* Set-up prior to fill operation in fill-stroke */ |
4374 | | static int |
4375 | | pdf14_fill_stroke_prefill(gx_device* dev, gs_gstate* pgs, gx_path* ppath, |
4376 | | const gx_clip_path* pcpath, float fill_alpha, float stroke_alpha, |
4377 | | gs_blend_mode_t blend_mode, bool* op_ca_eq_CA, bool* path_empty, gs_log2_scale_point path_log2scale) |
4378 | 29.1k | { |
4379 | 29.1k | int code = 0; |
4380 | 29.1k | gs_transparency_group_params_t params = { 0 }; |
4381 | 29.1k | gs_fixed_rect clip_bbox; |
4382 | 29.1k | gs_rect bbox, group_stroke_box; |
4383 | 29.1k | gs_fixed_rect path_bbox; |
4384 | 29.1k | int expansion_code; |
4385 | 29.1k | gs_fixed_point expansion; |
4386 | 29.1k | pdf14_device* p14dev = (pdf14_device*)dev; |
4387 | | |
4388 | 29.1k | *path_empty = false; |
4389 | | |
4390 | 29.1k | if ((pgs->fillconstantalpha == 0.0 && pgs->strokeconstantalpha == 0.0) || |
4391 | 29.0k | (pgs->ctm.xx == 0.0 && pgs->ctm.xy == 0.0 && pgs->ctm.yx == 0.0 && pgs->ctm.yy == 0.0)) |
4392 | 69 | { |
4393 | 69 | *op_ca_eq_CA = true; |
4394 | 69 | *path_empty = true; |
4395 | 69 | return 0; |
4396 | 69 | } |
4397 | | |
4398 | | /* The clip box returned here is scaled up by path_log2scale, so we need |
4399 | | * to scale down by this later. */ |
4400 | 29.0k | code = gx_curr_fixed_bbox(pgs, &clip_bbox, NO_PATH); |
4401 | 29.0k | if (code < 0 && code != gs_error_unknownerror) |
4402 | 0 | return code; |
4403 | | |
4404 | 29.0k | if (code == gs_error_unknownerror) { |
4405 | | /* didn't get clip box from gx_curr_fixed_bbox */ |
4406 | | /* This is NOT scaled by path_log2scale, so allow for the fact we'll be |
4407 | | * scaling down by this in a moment. */ |
4408 | 0 | clip_bbox.p.x = clip_bbox.p.y = 0; |
4409 | 0 | clip_bbox.q.x = int2fixed(dev->width) << path_log2scale.x; |
4410 | 0 | clip_bbox.q.y = int2fixed(dev->height) << path_log2scale.y; |
4411 | 0 | } |
4412 | | /* pcpath->outer_box is scaled by path_log2scale too. */ |
4413 | 29.0k | if (pcpath) |
4414 | 29.0k | rect_intersect(clip_bbox, pcpath->outer_box); |
4415 | | |
4416 | | /* expand the ppath using stroke expansion rule, then intersect it */ |
4417 | 29.0k | code = gx_path_bbox(ppath, &path_bbox); |
4418 | | |
4419 | | /* If we are coming from the abuf device, the path has been scaled |
4420 | | by a factor (see alpha_buffer_init). Undo the scaling here so |
4421 | | on the path_bbox so that we get the proper bounding box for our group. */ |
4422 | 29.0k | if (path_log2scale.x != 0 || path_log2scale.y != 0) { |
4423 | 0 | path_bbox.p.x = path_bbox.p.x >> path_log2scale.x; |
4424 | 0 | path_bbox.q.x = path_bbox.q.x >> path_log2scale.x; |
4425 | 0 | path_bbox.p.y = path_bbox.p.y >> path_log2scale.y; |
4426 | 0 | path_bbox.q.y = path_bbox.q.y >> path_log2scale.y; |
4427 | 0 | clip_bbox.p.x = clip_bbox.p.x >> path_log2scale.x; |
4428 | 0 | clip_bbox.q.x = clip_bbox.q.x >> path_log2scale.x; |
4429 | 0 | clip_bbox.p.y = clip_bbox.p.y >> path_log2scale.y; |
4430 | 0 | clip_bbox.q.y = clip_bbox.q.y >> path_log2scale.y; |
4431 | 0 | } |
4432 | | |
4433 | 29.0k | if (code == gs_error_nocurrentpoint && ppath->segments->contents.subpath_first == 0) { |
4434 | 2.36k | *path_empty = true; |
4435 | 2.36k | return 0; /* ignore empty path -- could try to send back a positive code for this but |
4436 | | there are simply too many return cases that I can't account for. */ |
4437 | 2.36k | } |
4438 | 26.6k | if (code < 0) |
4439 | 0 | return code; |
4440 | | |
4441 | 26.6k | expansion_code = gx_stroke_path_expansion(pgs, ppath, &expansion); |
4442 | 26.6k | if (expansion_code >= 0) { |
4443 | 26.6k | path_bbox.p.x -= expansion.x; |
4444 | 26.6k | path_bbox.p.y -= expansion.y; |
4445 | 26.6k | path_bbox.q.x += expansion.x; |
4446 | 26.6k | path_bbox.q.y += expansion.y; |
4447 | 26.6k | } |
4448 | 26.6k | rect_intersect(path_bbox, clip_bbox); |
4449 | 26.6k | bbox.p.x = fixed2float(path_bbox.p.x); |
4450 | 26.6k | bbox.p.y = fixed2float(path_bbox.p.y); |
4451 | 26.6k | bbox.q.x = fixed2float(path_bbox.q.x); |
4452 | 26.6k | bbox.q.y = fixed2float(path_bbox.q.y); |
4453 | | |
4454 | 26.6k | code = gs_bbox_transform_inverse(&bbox, &ctm_only(pgs), &group_stroke_box); |
4455 | 26.6k | if (code < 0) |
4456 | 1 | return code; |
4457 | | |
4458 | 26.6k | if (p14dev->overprint != pgs->overprint || p14dev->stroke_overprint != pgs->stroke_overprint) { |
4459 | 0 | p14dev->overprint = pgs->overprint; |
4460 | 0 | p14dev->stroke_overprint = pgs->stroke_overprint; |
4461 | 0 | } |
4462 | | |
4463 | | /* See if overprint is enabled for both stroke and fill AND if ca == CA */ |
4464 | 26.6k | if (fill_alpha == stroke_alpha && |
4465 | 5.72k | p14dev->overprint && p14dev->stroke_overprint && |
4466 | 0 | dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE) { |
4467 | | |
4468 | | /* Push a non-isolated non-knockout group with alpha = 1.0 and |
4469 | | compatible overprint mode. Group will be composited with |
4470 | | original alpha and blend mode */ |
4471 | 0 | *op_ca_eq_CA = true; |
4472 | 0 | params.Isolated = false; |
4473 | 0 | params.group_color_type = UNKNOWN; |
4474 | 0 | params.Knockout = false; |
4475 | 0 | params.page_group = false; |
4476 | 0 | params.group_opacity = 1.0; |
4477 | 0 | params.group_shape = fill_alpha; |
4478 | | |
4479 | | /* non-isolated non-knockout group pushed with original alpha and blend mode */ |
4480 | 0 | code = gs_begin_transparency_group(pgs, ¶ms, &group_stroke_box, PDF14_BEGIN_TRANS_GROUP); |
4481 | 0 | if (code < 0) |
4482 | 0 | return code; |
4483 | | |
4484 | | /* Change fill alpha to 1.0 and blend mode to compatible overprint for actual drawing */ |
4485 | 0 | (void)gs_setfillconstantalpha(pgs, 1.0); |
4486 | 0 | (void)gs_setblendmode(pgs, BLEND_MODE_CompatibleOverprint); /* Can never fail */ |
4487 | |
|
4488 | 26.6k | } else { |
4489 | | /* Push a non-isolated knockout group. Do not change the alpha or |
4490 | | blend modes. Note: we need to draw those that have alpha = 0 */ |
4491 | 26.6k | *op_ca_eq_CA = false; |
4492 | 26.6k | params.Isolated = false; |
4493 | 26.6k | params.group_color_type = UNKNOWN; |
4494 | 26.6k | params.Knockout = true; |
4495 | 26.6k | params.page_group = false; |
4496 | 26.6k | params.group_shape = 1.0; |
4497 | 26.6k | params.group_opacity = 1.0; |
4498 | | |
4499 | | /* non-isolated knockout group is pushed with alpha = 1.0 and Normal blend mode */ |
4500 | 26.6k | (void)gs_setblendmode(pgs, BLEND_MODE_Normal); /* Can never fail */ |
4501 | 26.6k | code = gs_begin_transparency_group(pgs, ¶ms, &group_stroke_box, PDF14_BEGIN_TRANS_GROUP); |
4502 | 26.6k | if (code < 0) |
4503 | 0 | return code; |
4504 | | |
4505 | | /* restore blend mode for actual drawing in the group */ |
4506 | 26.6k | (void)gs_setblendmode(pgs, blend_mode); /* Can never fail */ |
4507 | | |
4508 | | /* If we are in an overprint situation, set the blend mode to compatible |
4509 | | overprint */ |
4510 | 26.6k | if ((p14dev->icc_struct->overprint_control != gs_overprint_control_disable) && pgs->overprint && |
4511 | 0 | dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE) |
4512 | 0 | (void)gs_setblendmode(pgs, BLEND_MODE_CompatibleOverprint); /* Can never fail */ |
4513 | 26.6k | } |
4514 | 26.6k | p14dev->op_state = PDF14_OP_STATE_FILL; |
4515 | 26.6k | return code; |
4516 | 26.6k | } |
4517 | | |
4518 | | /* Set-up prior to stroke operation in fill-stroke */ |
4519 | | static void |
4520 | | pdf14_fill_stroke_prestroke(gx_device* dev, gs_gstate* pgs, float stroke_alpha, |
4521 | | gs_blend_mode_t blend_mode, bool op_ca_eq_CA) |
4522 | 26.6k | { |
4523 | 26.6k | pdf14_device* p14dev = (pdf14_device*)dev; |
4524 | | |
4525 | 26.6k | if (op_ca_eq_CA) { |
4526 | 0 | (void)gs_setstrokeconstantalpha(pgs, 1.0); |
4527 | 26.6k | } else { |
4528 | 26.6k | if ((p14dev->icc_struct->overprint_control != gs_overprint_control_disable) && pgs->overprint && |
4529 | 0 | dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE) |
4530 | 0 | (void)gs_setblendmode(pgs, blend_mode); /* Can never fail */ |
4531 | | |
4532 | | /* Note that the stroke can end up doing fill methods */ |
4533 | 26.6k | (void)gs_setfillconstantalpha(pgs, stroke_alpha); |
4534 | | |
4535 | 26.6k | if ((p14dev->icc_struct->overprint_control != gs_overprint_control_disable) && pgs->stroke_overprint && |
4536 | 0 | dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE) |
4537 | 0 | (void)gs_setblendmode(pgs, BLEND_MODE_CompatibleOverprint); /* Can never fail */ |
4538 | 26.6k | } |
4539 | 26.6k | p14dev->op_state = PDF14_OP_STATE_STROKE; |
4540 | 26.6k | } |
4541 | | |
4542 | | /* Cleanup after the stroke in fill-stroke */ |
4543 | | static int |
4544 | | pdf14_fill_stroke_poststroke(gx_device* dev, gs_gstate* pgs, float fill_alpha, bool op_ca_eq_CA) |
4545 | 26.6k | { |
4546 | 26.6k | int code; |
4547 | | |
4548 | 26.6k | if (!op_ca_eq_CA) { |
4549 | | /* Bug 703324 we need to reset the fill constant alpha in the graphics |
4550 | | * state to the correct saved value. We also need to reset the 'opacity' member of the |
4551 | | * device, because some device methods (eg fill_masked_image) don't take a graphics |
4552 | | * state pointer as a parameter and so are unable to set the opacity value themselves. |
4553 | | * We therefore need to make sure it is set according to the current fill state. |
4554 | | */ |
4555 | 26.6k | (void)gs_setfillconstantalpha(pgs, fill_alpha); |
4556 | 26.6k | code = gs_update_trans_marking_params(pgs); |
4557 | 26.6k | if (code < 0) |
4558 | 0 | return code; |
4559 | 26.6k | pdf14_set_marking_params(dev, pgs); |
4560 | 26.6k | } |
4561 | | |
4562 | 26.6k | return 0; |
4563 | 26.6k | } |
4564 | | |
4565 | | /* cleanup in fill-stroke */ |
4566 | | static int |
4567 | | pdf14_fill_stroke_cleanup(gx_device* dev, gs_gstate* pgs, float fill_alpha, float stroke_alpha, |
4568 | | gs_blend_mode_t blend_mode, PDF14_OP_FS_STATE save_op_state) |
4569 | 26.6k | { |
4570 | 26.6k | pdf14_device* p14dev = (pdf14_device*)dev; |
4571 | 26.6k | int code2; |
4572 | 26.6k | int code = 0; |
4573 | | |
4574 | | /* Restore the state */ |
4575 | 26.6k | p14dev->op_state = save_op_state; |
4576 | 26.6k | (void)gs_setblendmode(pgs, blend_mode); /* Can never fail */ |
4577 | 26.6k | (void)gs_setstrokeconstantalpha(pgs, stroke_alpha); |
4578 | 26.6k | (void)gs_setfillconstantalpha(pgs, fill_alpha); |
4579 | | |
4580 | 26.6k | code2 = gs_end_transparency_group(pgs); |
4581 | 26.6k | if (code2 < 0) { |
4582 | | /* At this point things have gone very wrong. We should just shut down */ |
4583 | 0 | code = gs_abort_pdf14trans_device(pgs); |
4584 | 0 | return code2; |
4585 | 0 | } |
4586 | 26.6k | return code; |
4587 | 26.6k | } |
4588 | | |
4589 | | static int |
4590 | | pdf14_fill_stroke_path(gx_device *dev, const gs_gstate *cpgs, gx_path *ppath, |
4591 | | const gx_fill_params *fill_params, const gx_drawing_color *pdcolor_fill, |
4592 | | const gx_stroke_params *stroke_params, const gx_drawing_color *pdcolor_stroke, |
4593 | | const gx_clip_path *pcpath) |
4594 | 101k | { |
4595 | 101k | bool op_ca_eq_CA; |
4596 | 101k | bool path_empty; |
4597 | 101k | int code; |
4598 | 101k | float stroke_alpha = cpgs->strokeconstantalpha; |
4599 | 101k | float fill_alpha = cpgs->fillconstantalpha; |
4600 | 101k | gs_blend_mode_t blend_mode = cpgs->blend_mode; |
4601 | 101k | pdf14_device* p14dev = (pdf14_device*)dev; |
4602 | 101k | PDF14_OP_FS_STATE save_op_state = p14dev->op_state; |
4603 | 101k | gs_log2_scale_point path_log2scale; |
4604 | 101k | bool group_needed = true; |
4605 | 101k | gx_device* curr_pgs_dev = cpgs->device; |
4606 | | |
4607 | 101k | union { |
4608 | 101k | const gs_gstate* cpgs; |
4609 | 101k | gs_gstate* pgs; |
4610 | 101k | } const_breaker; |
4611 | 101k | gs_gstate* pgs; |
4612 | | |
4613 | | /* Break const just once, neatly */ |
4614 | 101k | const_breaker.cpgs = cpgs; |
4615 | 101k | pgs = const_breaker.pgs; |
4616 | 101k | path_log2scale.x = 0; |
4617 | 101k | path_log2scale.y = 0; |
4618 | | |
4619 | 101k | code = pdf14_initialize_ctx(dev, pgs); |
4620 | 101k | if (code < 0) |
4621 | 0 | return code; |
4622 | | |
4623 | | /* From looking at what AR is doing, it appears that if alpha is 1 and |
4624 | | * blend is normal we don't do a group push. Just do the stroke |
4625 | | * and the fill, even with overprint */ |
4626 | 101k | if (stroke_alpha == 1 && fill_alpha == 1 && blend_mode == BLEND_MODE_Normal) |
4627 | 71.9k | group_needed = false; |
4628 | | |
4629 | 101k | if (group_needed) { |
4630 | 29.1k | pgs->device = dev; /* This is needed due to the gs_trans calls. This method |
4631 | | can be called on the clist writer side when dealing |
4632 | | with the abuf/pdf14 interaction. Those calls have to |
4633 | | go through the gs_trans API not the gx_trans or pdf14 |
4634 | | methods. Perhaps these methods should have a different |
4635 | | suffix, but they are static methods here in the pdf14 |
4636 | | file. */ |
4637 | 29.1k | code = pdf14_fill_stroke_prefill(dev, pgs, ppath, pcpath, fill_alpha, stroke_alpha, |
4638 | 29.1k | blend_mode, &op_ca_eq_CA, &path_empty, path_log2scale); |
4639 | 29.1k | pgs->device = curr_pgs_dev; |
4640 | 29.1k | if (code < 0) |
4641 | 1 | goto cleanup; |
4642 | 29.1k | if (path_empty) |
4643 | 2.43k | return 0; |
4644 | 29.1k | } |
4645 | | |
4646 | 98.5k | code = pdf14_fill_path(dev, pgs, ppath, fill_params, pdcolor_fill, pcpath); |
4647 | 98.5k | if (code < 0) |
4648 | 0 | goto cleanup; |
4649 | | |
4650 | 98.5k | if (group_needed) |
4651 | 26.6k | pdf14_fill_stroke_prestroke(dev, pgs, stroke_alpha, blend_mode, op_ca_eq_CA); |
4652 | 98.5k | gs_swapcolors_quick(pgs); |
4653 | | |
4654 | | |
4655 | | #if RAW_DUMP |
4656 | | /* Dump the current buffer to see what we have. */ |
4657 | | dump_raw_buffer(p14dev->ctx->memory, |
4658 | | p14dev->ctx->stack->rect.q.y - p14dev->ctx->stack->rect.p.y, |
4659 | | p14dev->ctx->stack->rowstride >> p14dev->ctx->stack->deep, p14dev->ctx->stack->n_planes, |
4660 | | p14dev->ctx->stack->planestride, p14dev->ctx->stack->rowstride, |
4661 | | "BeforeStrokeOnFillStroke", p14dev->ctx->stack->data, p14dev->ctx->stack->deep); |
4662 | | global_index++; |
4663 | | #endif |
4664 | | |
4665 | 98.5k | code = pdf14_stroke_path(dev, pgs, ppath, stroke_params, pdcolor_stroke, pcpath); |
4666 | 98.5k | gs_swapcolors_quick(pgs); |
4667 | 98.5k | if (code < 0) { |
4668 | 0 | goto cleanup; |
4669 | 0 | } |
4670 | | |
4671 | | #if RAW_DUMP |
4672 | | /* Dump the current buffer to see what we have. */ |
4673 | | dump_raw_buffer(p14dev->ctx->memory, |
4674 | | p14dev->ctx->stack->rect.q.y - p14dev->ctx->stack->rect.p.y, |
4675 | | p14dev->ctx->stack->rowstride >> p14dev->ctx->stack->deep, p14dev->ctx->stack->n_planes, |
4676 | | p14dev->ctx->stack->planestride, p14dev->ctx->stack->rowstride, |
4677 | | "AfterStrokeOnFillStroke", p14dev->ctx->stack->data, p14dev->ctx->stack->deep); |
4678 | | global_index++; |
4679 | | #endif |
4680 | 98.5k | if (group_needed) |
4681 | 26.6k | code = pdf14_fill_stroke_poststroke(dev, pgs, fill_alpha, op_ca_eq_CA); |
4682 | | |
4683 | 98.5k | cleanup: |
4684 | 98.5k | if (group_needed) { |
4685 | 26.6k | int code1; |
4686 | 26.6k | pgs->device = dev; /* This is needed due to the gs_trans calls */ |
4687 | 26.6k | code1 = pdf14_fill_stroke_cleanup(dev, pgs, fill_alpha, stroke_alpha, blend_mode, |
4688 | 26.6k | save_op_state); |
4689 | 26.6k | if (code1 < 0) |
4690 | 0 | code = code1; |
4691 | 26.6k | pgs->device = curr_pgs_dev; |
4692 | 26.6k | } |
4693 | 98.5k | return code; |
4694 | 98.5k | } |
4695 | | |
4696 | | static int |
4697 | | pdf14_copy_alpha(gx_device * dev, const byte * data, int data_x, |
4698 | | int aa_raster, gx_bitmap_id id, int x, int y, int w, int h, |
4699 | | gx_color_index color, int depth) |
4700 | 0 | { |
4701 | 0 | return pdf14_copy_alpha_color(dev, data, data_x, aa_raster, id, x, y, w, h, |
4702 | 0 | color, NULL, depth, false); |
4703 | 0 | } |
4704 | | |
4705 | | static int |
4706 | | pdf14_copy_alpha_hl_color(gx_device * dev, const byte * data, int data_x, |
4707 | | int aa_raster, gx_bitmap_id id, int x, int y, int w, int h, |
4708 | | const gx_drawing_color *pdcolor, int depth) |
4709 | 0 | { |
4710 | 0 | return pdf14_copy_alpha_color(dev, data, data_x, aa_raster, id, x, y, w, h, |
4711 | 0 | 0, pdcolor, depth, true); |
4712 | 0 | } |
4713 | | |
4714 | | static int |
4715 | | do_pdf14_copy_alpha_color(gx_device * dev, const byte * data, int data_x, |
4716 | | int aa_raster, gx_bitmap_id id, int x, int y, |
4717 | | int w, int h, gx_color_index color, |
4718 | | const gx_device_color *pdc, int depth, bool devn) |
4719 | 0 | { |
4720 | 0 | const byte *aa_row; |
4721 | 0 | pdf14_device *pdev = (pdf14_device *)dev; |
4722 | 0 | pdf14_buf *buf = pdev->ctx->stack; |
4723 | 0 | int i, j, k; |
4724 | 0 | byte *bline, *line, *dst_ptr, *back_ptr; |
4725 | 0 | byte src[PDF14_MAX_PLANES]; |
4726 | 0 | byte dst[PDF14_MAX_PLANES] = { 0 }; |
4727 | 0 | gs_blend_mode_t blend_mode = pdev->blend_mode; |
4728 | 0 | bool additive = pdev->ctx->additive; |
4729 | 0 | intptr_t rowstride = buf->rowstride; |
4730 | 0 | intptr_t planestride = buf->planestride; |
4731 | 0 | gs_graphics_type_tag_t curr_tag = GS_UNKNOWN_TAG; /* Quiet compiler */ |
4732 | 0 | bool has_alpha_g = buf->has_alpha_g; |
4733 | 0 | bool has_shape = buf->has_shape; |
4734 | 0 | bool has_tags = buf->has_tags; |
4735 | 0 | bool knockout = buf->knockout; |
4736 | 0 | bool tag_blend = blend_mode == BLEND_MODE_Normal || |
4737 | 0 | blend_mode == BLEND_MODE_Compatible || |
4738 | 0 | blend_mode == BLEND_MODE_CompatibleOverprint; |
4739 | 0 | int num_chan = buf->n_chan; |
4740 | 0 | int num_comp = num_chan - 1; |
4741 | 0 | intptr_t shape_off = num_chan * planestride; |
4742 | 0 | intptr_t alpha_g_off = shape_off + (has_shape ? planestride : 0); |
4743 | 0 | intptr_t tag_off = alpha_g_off + (has_alpha_g ? planestride : 0); |
4744 | 0 | bool overprint = pdev->op_state == PDF14_OP_STATE_FILL ? pdev->overprint : pdev->stroke_overprint; |
4745 | 0 | gx_color_index drawn_comps = pdev->op_state == PDF14_OP_STATE_FILL ? |
4746 | 0 | pdev->drawn_comps_fill : pdev->drawn_comps_stroke; |
4747 | 0 | gx_color_index comps; |
4748 | 0 | byte shape = 0; /* Quiet compiler. */ |
4749 | 0 | byte src_alpha; |
4750 | 0 | int alpha2_aa, alpha_aa, sx; |
4751 | 0 | int alpha_aa_act; |
4752 | 0 | int xoff; |
4753 | 0 | gx_color_index mask = ((gx_color_index)1 << 8) - 1; |
4754 | 0 | int shift = 8; |
4755 | 0 | bool has_backdrop = buf->backdrop != NULL; |
4756 | |
|
4757 | 0 | if (buf->data == NULL) |
4758 | 0 | return 0; |
4759 | 0 | aa_row = data; |
4760 | 0 | if (has_tags) { |
4761 | 0 | if (devn) |
4762 | 0 | curr_tag = pdc->tag; |
4763 | 0 | else |
4764 | 0 | curr_tag = (color >> (num_comp*8)) & 0xff; |
4765 | 0 | } |
4766 | |
|
4767 | 0 | if (devn) { |
4768 | 0 | if (additive) { |
4769 | 0 | for (j = 0; j < num_comp; j++) { |
4770 | 0 | src[j] = ((pdc->colors.devn.values[j]) >> shift & mask); |
4771 | 0 | } |
4772 | 0 | } else { |
4773 | 0 | for (j = 0; j < num_comp; j++) { |
4774 | 0 | src[j] = 255 - ((pdc->colors.devn.values[j]) >> shift & mask); |
4775 | 0 | } |
4776 | 0 | } |
4777 | 0 | } else |
4778 | 0 | pdev->pdf14_procs->unpack_color(num_comp, color, pdev, src); |
4779 | 0 | src_alpha = src[num_comp] = (byte)floor (255 * pdev->alpha + 0.5); |
4780 | 0 | if (has_shape) |
4781 | 0 | shape = (byte)floor (255 * pdev->shape + 0.5); |
4782 | | /* Limit the area we write to the bounding rectangle for this buffer */ |
4783 | 0 | if (x < buf->rect.p.x) { |
4784 | 0 | xoff = data_x + buf->rect.p.x - x; |
4785 | 0 | w += x - buf->rect.p.x; |
4786 | 0 | x = buf->rect.p.x; |
4787 | 0 | } else { |
4788 | 0 | xoff = data_x; |
4789 | 0 | } |
4790 | 0 | if (y < buf->rect.p.y) { |
4791 | 0 | h += y - buf->rect.p.y; |
4792 | 0 | aa_row -= (y - buf->rect.p.y) * aa_raster; |
4793 | 0 | y = buf->rect.p.y; |
4794 | 0 | } |
4795 | 0 | if (x + w > buf->rect.q.x) w = buf->rect.q.x - x; |
4796 | 0 | if (y + h > buf->rect.q.y) h = buf->rect.q.y - y; |
4797 | | /* Update the dirty rectangle. */ |
4798 | 0 | if (x < buf->dirty.p.x) buf->dirty.p.x = x; |
4799 | 0 | if (y < buf->dirty.p.y) buf->dirty.p.y = y; |
4800 | 0 | if (x + w > buf->dirty.q.x) buf->dirty.q.x = x + w; |
4801 | 0 | if (y + h > buf->dirty.q.y) buf->dirty.q.y = y + h; |
4802 | | |
4803 | | /* composite with backdrop only. */ |
4804 | 0 | line = buf->data + (x - buf->rect.p.x) + (y - buf->rect.p.y) * rowstride; |
4805 | 0 | if (knockout && has_backdrop) |
4806 | 0 | bline = buf->backdrop + (x - buf->rect.p.x) + (y - buf->rect.p.y) * rowstride; |
4807 | 0 | else |
4808 | 0 | bline = line; |
4809 | |
|
4810 | 0 | for (j = 0; j < h; ++j, aa_row += aa_raster) { |
4811 | 0 | back_ptr = bline; |
4812 | 0 | dst_ptr = line; |
4813 | 0 | sx = xoff; |
4814 | 0 | for (i = 0; i < w; ++i, ++sx) { |
4815 | | /* Complement the components for subtractive color spaces */ |
4816 | 0 | if (additive) { |
4817 | 0 | for (k = 0; k < num_chan; ++k) /* num_chan includes alpha */ |
4818 | 0 | dst[k] = back_ptr[k * planestride]; |
4819 | 0 | } else { /* Complement the components for subtractive color spaces */ |
4820 | 0 | for (k = 0; k < num_comp; ++k) |
4821 | 0 | dst[k] = 255 - back_ptr[k * planestride]; |
4822 | 0 | dst[num_comp] = back_ptr[num_comp * planestride]; /* alpha */ |
4823 | 0 | } |
4824 | | /* Get the aa alpha from the buffer */ |
4825 | 0 | switch(depth) |
4826 | 0 | { |
4827 | 0 | case 2: /* map 0 - 3 to 0 - 255 */ |
4828 | 0 | alpha_aa = ((aa_row[sx >> 2] >> ((3 - (sx & 3)) << 1)) & 3) * 85; |
4829 | 0 | break; |
4830 | 0 | case 4: |
4831 | 0 | alpha2_aa = aa_row[sx >> 1]; |
4832 | 0 | alpha_aa = (sx & 1 ? alpha2_aa & 0xf : alpha2_aa >> 4) * 17; |
4833 | 0 | break; |
4834 | 0 | case 8: |
4835 | 0 | alpha_aa = aa_row[sx]; |
4836 | 0 | break; |
4837 | 0 | default: |
4838 | 0 | return_error(gs_error_rangecheck); |
4839 | 0 | } |
4840 | 0 | if (alpha_aa != 0) { /* This does happen */ |
4841 | 0 | if (alpha_aa != 255) { |
4842 | | /* We have an alpha value from aa */ |
4843 | 0 | alpha_aa_act = alpha_aa; |
4844 | 0 | if (src_alpha != 255) { |
4845 | | /* Need to combine it with the existing alpha */ |
4846 | 0 | int tmp = src_alpha * alpha_aa_act + 0x80; |
4847 | 0 | alpha_aa_act = (tmp + (tmp >> 8)) >> 8; |
4848 | 0 | } |
4849 | | /* Set our source alpha value appropriately */ |
4850 | 0 | src[num_comp] = alpha_aa_act; |
4851 | 0 | } else { |
4852 | | /* We may have to reset this is it was changed as we |
4853 | | moved across the row */ |
4854 | 0 | src[num_comp] = src_alpha; |
4855 | 0 | } |
4856 | 0 | if (knockout) { |
4857 | 0 | if (buf->isolated) { |
4858 | 0 | art_pdf_knockoutisolated_group_8(dst, src, num_comp); |
4859 | 0 | } else { |
4860 | 0 | art_pdf_composite_knockout_8(dst, src, num_comp, |
4861 | 0 | blend_mode, pdev->blend_procs, pdev); |
4862 | 0 | } |
4863 | 0 | } else { |
4864 | 0 | art_pdf_composite_pixel_alpha_8(dst, src, num_comp, blend_mode, num_comp, |
4865 | 0 | pdev->blend_procs, pdev); |
4866 | 0 | } |
4867 | | /* Complement the results for subtractive color spaces */ |
4868 | 0 | if (additive) { |
4869 | 0 | for (k = 0; k < num_chan; ++k) |
4870 | 0 | dst_ptr[k * planestride] = dst[k]; |
4871 | 0 | } else { |
4872 | 0 | if (overprint && dst_ptr[num_comp * planestride] != 0) { |
4873 | 0 | for (k = 0, comps = drawn_comps; comps != 0; |
4874 | 0 | ++k, comps >>= 1) { |
4875 | 0 | if ((comps & 0x1) != 0) { |
4876 | 0 | dst_ptr[k * planestride] = 255 - dst[k]; |
4877 | 0 | } |
4878 | 0 | } |
4879 | | /* The alpha channel */ |
4880 | 0 | dst_ptr[num_comp * planestride] = dst[num_comp]; |
4881 | 0 | } else { |
4882 | 0 | for (k = 0; k < num_comp; ++k) |
4883 | 0 | dst_ptr[k * planestride] = 255 - dst[k]; |
4884 | | /* The alpha channel */ |
4885 | 0 | dst_ptr[num_comp * planestride] = dst[num_comp]; |
4886 | 0 | } |
4887 | 0 | } |
4888 | 0 | if (has_alpha_g) { |
4889 | 0 | int tmp = (255 - back_ptr[alpha_g_off]) * (255 - src[num_comp]) + 0x80; |
4890 | 0 | dst_ptr[alpha_g_off] = 255 - ((tmp + (tmp >> 8)) >> 8); |
4891 | 0 | } |
4892 | 0 | if (has_shape) { |
4893 | 0 | int tmp = (255 - back_ptr[shape_off]) * (255 - shape) + 0x80; |
4894 | 0 | dst_ptr[shape_off] = 255 - ((tmp + (tmp >> 8)) >> 8); |
4895 | 0 | } |
4896 | 0 | if (has_tags) { |
4897 | | /* If alpha is 100% then set to curr_tag, else or */ |
4898 | | /* other than Normal BM, we always OR */ |
4899 | 0 | if (src[num_comp] == 255 && tag_blend) { |
4900 | 0 | dst_ptr[tag_off] = curr_tag; |
4901 | 0 | } else { |
4902 | 0 | dst_ptr[tag_off] = back_ptr[tag_off] | curr_tag; |
4903 | 0 | } |
4904 | 0 | } |
4905 | 0 | } |
4906 | 0 | ++dst_ptr; |
4907 | 0 | ++back_ptr; |
4908 | 0 | } |
4909 | 0 | line += rowstride; |
4910 | 0 | bline += rowstride; |
4911 | 0 | } |
4912 | 0 | return 0; |
4913 | 0 | } |
4914 | | |
4915 | | static int |
4916 | | do_pdf14_copy_alpha_color_16(gx_device * dev, const byte * data, int data_x, |
4917 | | int aa_raster, gx_bitmap_id id, int x, int y, |
4918 | | int w, int h, gx_color_index color, |
4919 | | const gx_device_color *pdc, int depth, bool devn) |
4920 | 0 | { |
4921 | 0 | const byte *aa_row; |
4922 | 0 | pdf14_device *pdev = (pdf14_device *)dev; |
4923 | 0 | pdf14_buf *buf = pdev->ctx->stack; |
4924 | 0 | int i, j, k; |
4925 | 0 | byte *bline, *line; |
4926 | 0 | uint16_t *dst_ptr, *back_ptr; |
4927 | 0 | uint16_t src[PDF14_MAX_PLANES]; |
4928 | 0 | uint16_t dst[PDF14_MAX_PLANES] = { 0 }; |
4929 | 0 | gs_blend_mode_t blend_mode = pdev->blend_mode; |
4930 | 0 | bool tag_blend = blend_mode == BLEND_MODE_Normal || |
4931 | 0 | blend_mode == BLEND_MODE_Compatible || |
4932 | 0 | blend_mode == BLEND_MODE_CompatibleOverprint; |
4933 | 0 | bool additive = pdev->ctx->additive; |
4934 | 0 | intptr_t rowstride = buf->rowstride; |
4935 | 0 | int planestride = buf->planestride; |
4936 | 0 | gs_graphics_type_tag_t curr_tag = GS_UNKNOWN_TAG; /* Quiet compiler */ |
4937 | 0 | bool has_alpha_g = buf->has_alpha_g; |
4938 | 0 | bool has_shape = buf->has_shape; |
4939 | 0 | bool has_tags = buf->has_tags; |
4940 | 0 | bool knockout = buf->knockout; |
4941 | 0 | int num_chan = buf->n_chan; |
4942 | 0 | int num_comp = num_chan - 1; |
4943 | 0 | intptr_t shape_off = num_chan * planestride; |
4944 | 0 | intptr_t alpha_g_off = shape_off + (has_shape ? planestride : 0); |
4945 | 0 | intptr_t tag_off = alpha_g_off + (has_alpha_g ? planestride : 0); |
4946 | 0 | bool overprint = pdev->op_state == PDF14_OP_STATE_FILL ? pdev->overprint : pdev->stroke_overprint; |
4947 | 0 | gx_color_index drawn_comps = pdev->op_state == PDF14_OP_STATE_FILL ? |
4948 | 0 | pdev->drawn_comps_fill : pdev->drawn_comps_stroke; |
4949 | 0 | gx_color_index comps; |
4950 | 0 | uint16_t shape = 0; /* Quiet compiler. */ |
4951 | 0 | uint16_t src_alpha; |
4952 | 0 | int alpha2_aa, alpha_aa, sx; |
4953 | 0 | int alpha_aa_act; |
4954 | 0 | int xoff; |
4955 | 0 | bool has_backdrop = buf->backdrop != NULL; |
4956 | |
|
4957 | 0 | if (buf->data == NULL) |
4958 | 0 | return 0; |
4959 | 0 | aa_row = data; |
4960 | 0 | if (has_tags) { |
4961 | 0 | if (devn) |
4962 | 0 | curr_tag = pdc->tag; |
4963 | 0 | else |
4964 | 0 | curr_tag = (color >> (num_comp*16)) & 0xff; |
4965 | 0 | } |
4966 | |
|
4967 | 0 | if (devn) { |
4968 | 0 | if (additive) { |
4969 | 0 | for (j = 0; j < num_comp; j++) { |
4970 | 0 | src[j] = pdc->colors.devn.values[j]; |
4971 | 0 | } |
4972 | 0 | } else { |
4973 | 0 | for (j = 0; j < num_comp; j++) { |
4974 | 0 | src[j] = 65535 - pdc->colors.devn.values[j]; |
4975 | 0 | } |
4976 | 0 | } |
4977 | 0 | } else |
4978 | 0 | pdev->pdf14_procs->unpack_color16(num_comp, color, pdev, src); |
4979 | 0 | src_alpha = src[num_comp] = (uint16_t)floor (65535 * pdev->alpha + 0.5); |
4980 | 0 | if (has_shape) |
4981 | 0 | shape = (uint16_t)floor (65535 * pdev->shape + 0.5); |
4982 | | /* Limit the area we write to the bounding rectangle for this buffer */ |
4983 | 0 | if (x < buf->rect.p.x) { |
4984 | 0 | xoff = data_x + buf->rect.p.x - x; |
4985 | 0 | w += x - buf->rect.p.x; |
4986 | 0 | x = buf->rect.p.x; |
4987 | 0 | } else { |
4988 | 0 | xoff = data_x; |
4989 | 0 | } |
4990 | 0 | if (y < buf->rect.p.y) { |
4991 | 0 | h += y - buf->rect.p.y; |
4992 | 0 | aa_row -= (y - buf->rect.p.y) * aa_raster; |
4993 | 0 | y = buf->rect.p.y; |
4994 | 0 | } |
4995 | 0 | if (x + w > buf->rect.q.x) w = buf->rect.q.x - x; |
4996 | 0 | if (y + h > buf->rect.q.y) h = buf->rect.q.y - y; |
4997 | | /* Update the dirty rectangle. */ |
4998 | 0 | if (x < buf->dirty.p.x) buf->dirty.p.x = x; |
4999 | 0 | if (y < buf->dirty.p.y) buf->dirty.p.y = y; |
5000 | 0 | if (x + w > buf->dirty.q.x) buf->dirty.q.x = x + w; |
5001 | 0 | if (y + h > buf->dirty.q.y) buf->dirty.q.y = y + h; |
5002 | | |
5003 | | /* composite with backdrop only. */ |
5004 | 0 | line = buf->data + (x - buf->rect.p.x)*2 + (y - buf->rect.p.y) * rowstride; |
5005 | 0 | if (knockout && has_backdrop) |
5006 | 0 | bline = buf->backdrop + (x - buf->rect.p.x)*2 + (y - buf->rect.p.y) * rowstride; |
5007 | 0 | else |
5008 | 0 | bline = line; |
5009 | |
|
5010 | 0 | planestride >>= 1; |
5011 | 0 | rowstride >>= 1; |
5012 | 0 | alpha_g_off >>= 1; |
5013 | 0 | shape_off >>= 1; |
5014 | 0 | tag_off >>= 1; |
5015 | 0 | for (j = 0; j < h; ++j, aa_row += aa_raster) { |
5016 | 0 | back_ptr = (uint16_t *)(void *)bline; |
5017 | 0 | dst_ptr = (uint16_t *)(void *)line; |
5018 | 0 | sx = xoff; |
5019 | 0 | for (i = 0; i < w; ++i, ++sx) { |
5020 | | /* Complement the components for subtractive color spaces */ |
5021 | 0 | if (additive) { |
5022 | 0 | for (k = 0; k < num_chan; ++k) /* num_chan includes alpha */ |
5023 | 0 | dst[k] = back_ptr[k * planestride]; |
5024 | 0 | } else { /* Complement the components for subtractive color spaces */ |
5025 | 0 | for (k = 0; k < num_comp; ++k) |
5026 | 0 | dst[k] = 65535 - back_ptr[k * planestride]; |
5027 | 0 | dst[num_comp] = back_ptr[num_comp * planestride]; /* alpha */ |
5028 | 0 | } |
5029 | | /* Get the aa alpha from the buffer */ |
5030 | 0 | switch(depth) |
5031 | 0 | { |
5032 | 0 | case 2: /* map 0 - 3 to 0 - 255 */ |
5033 | 0 | alpha_aa = ((aa_row[sx >> 2] >> ((3 - (sx & 3)) << 1)) & 3) * 85; |
5034 | 0 | break; |
5035 | 0 | case 4: |
5036 | 0 | alpha2_aa = aa_row[sx >> 1]; |
5037 | 0 | alpha_aa = (sx & 1 ? alpha2_aa & 0xf : alpha2_aa >> 4) * 17; |
5038 | 0 | break; |
5039 | 0 | case 8: |
5040 | 0 | alpha_aa = aa_row[sx]; |
5041 | 0 | break; |
5042 | 0 | default: |
5043 | 0 | return_error(gs_error_rangecheck); |
5044 | 0 | } |
5045 | 0 | if (alpha_aa != 0) { /* This does happen */ |
5046 | 0 | if (alpha_aa != 255) { |
5047 | | /* We have an alpha value from aa */ |
5048 | 0 | alpha_aa_act = alpha_aa * 0x101; |
5049 | 0 | if (src_alpha != 65535) { |
5050 | | /* Need to combine it with the existing alpha */ |
5051 | 0 | int tmp = src_alpha * alpha_aa_act + 0x8000; |
5052 | 0 | alpha_aa_act = (tmp + (tmp >> 16)) >> 16; |
5053 | 0 | } |
5054 | | /* Set our source alpha value appropriately */ |
5055 | 0 | src[num_comp] = alpha_aa_act; |
5056 | 0 | } else { |
5057 | | /* We may have to reset this is it was changed as we |
5058 | | moved across the row */ |
5059 | 0 | src[num_comp] = src_alpha; |
5060 | 0 | } |
5061 | 0 | if (knockout) { |
5062 | 0 | if (buf->isolated) { |
5063 | 0 | art_pdf_knockoutisolated_group_16(dst, src, num_comp); |
5064 | 0 | } else { |
5065 | 0 | art_pdf_composite_knockout_16(dst, src, num_comp, |
5066 | 0 | blend_mode, pdev->blend_procs, pdev); |
5067 | 0 | } |
5068 | 0 | } else { |
5069 | 0 | art_pdf_composite_pixel_alpha_16(dst, src, num_comp, blend_mode, num_comp, |
5070 | 0 | pdev->blend_procs, pdev); |
5071 | 0 | } |
5072 | | /* Complement the results for subtractive color spaces */ |
5073 | 0 | if (additive) { |
5074 | 0 | for (k = 0; k < num_chan; ++k) |
5075 | 0 | dst_ptr[k * planestride] = dst[k]; |
5076 | 0 | } else { |
5077 | 0 | if (overprint && dst_ptr[num_comp * planestride] != 0) { |
5078 | 0 | for (k = 0, comps = drawn_comps; comps != 0; |
5079 | 0 | ++k, comps >>= 1) { |
5080 | 0 | if ((comps & 0x1) != 0) { |
5081 | 0 | dst_ptr[k * planestride] = 65535 - dst[k]; |
5082 | 0 | } |
5083 | 0 | } |
5084 | | /* The alpha channel */ |
5085 | 0 | dst_ptr[num_comp * planestride] = dst[num_comp]; |
5086 | 0 | } else { |
5087 | 0 | for (k = 0; k < num_comp; ++k) |
5088 | 0 | dst_ptr[k * planestride] = 65535 - dst[k]; |
5089 | | /* The alpha channel */ |
5090 | 0 | dst_ptr[num_comp * planestride] = dst[num_comp]; |
5091 | 0 | } |
5092 | 0 | } |
5093 | 0 | if (has_alpha_g) { |
5094 | 0 | int tmp = (65535 - back_ptr[alpha_g_off]) * (65535 - src[num_comp]) + 0x8000; |
5095 | 0 | dst_ptr[alpha_g_off] = 65535 - ((tmp + (tmp >> 16)) >> 16); |
5096 | 0 | } |
5097 | 0 | if (has_shape) { |
5098 | 0 | int tmp = (65535 - back_ptr[shape_off]) * (65535 - shape) + 0x8000; |
5099 | 0 | dst_ptr[shape_off] = 65535 - ((tmp + (tmp >> 16)) >> 16); |
5100 | 0 | } |
5101 | 0 | if (has_tags) { |
5102 | | /* If alpha is 100% then set to curr_tag, else or */ |
5103 | | /* other than Normal BM, we always OR */ |
5104 | 0 | if (src[num_comp] == 65535 && tag_blend) { |
5105 | 0 | dst_ptr[tag_off] = curr_tag; |
5106 | 0 | } else { |
5107 | 0 | dst_ptr[tag_off] = back_ptr[tag_off] | curr_tag; |
5108 | 0 | } |
5109 | 0 | } |
5110 | 0 | } |
5111 | 0 | ++dst_ptr; |
5112 | 0 | ++back_ptr; |
5113 | 0 | } |
5114 | 0 | line += rowstride; |
5115 | 0 | bline += rowstride; |
5116 | 0 | } |
5117 | 0 | return 0; |
5118 | 0 | } |
5119 | | |
5120 | | static int |
5121 | | pdf14_copy_alpha_color(gx_device * dev, const byte * data, int data_x, |
5122 | | int aa_raster, gx_bitmap_id id, int x, int y, int w, int h, |
5123 | | gx_color_index color, const gx_device_color *pdc, |
5124 | | int depth, bool devn) |
5125 | 0 | { |
5126 | 0 | bool deep = device_is_deep(dev); |
5127 | 0 | int code; |
5128 | |
|
5129 | 0 | code = pdf14_initialize_ctx(dev, NULL); |
5130 | 0 | if (code < 0) |
5131 | 0 | return code; |
5132 | | |
5133 | 0 | if (deep) |
5134 | 0 | return do_pdf14_copy_alpha_color_16(dev, data, data_x, aa_raster, |
5135 | 0 | id, x, y, w, h, |
5136 | 0 | color, pdc, depth, devn); |
5137 | 0 | else |
5138 | 0 | return do_pdf14_copy_alpha_color(dev, data, data_x, aa_raster, |
5139 | 0 | id, x, y, w, h, |
5140 | 0 | color, pdc, depth, devn); |
5141 | 0 | } |
5142 | | |
5143 | | static int |
5144 | | pdf14_fill_mask(gx_device * orig_dev, |
5145 | | const byte * data, int dx, int raster, gx_bitmap_id id, |
5146 | | int x, int y, int w, int h, |
5147 | | const gx_drawing_color * pdcolor, int depth, |
5148 | | gs_logical_operation_t lop, const gx_clip_path * pcpath) |
5149 | 12.8M | { |
5150 | 12.8M | gx_device *dev; |
5151 | 12.8M | pdf14_device *p14dev = (pdf14_device *)orig_dev; |
5152 | 12.8M | gx_device_clip cdev; |
5153 | 12.8M | gx_color_tile *ptile = NULL; |
5154 | 12.8M | int code = 0; |
5155 | 12.8M | gs_int_rect group_rect; |
5156 | 12.8M | gx_pattern_trans_t *fill_trans_buffer = NULL; |
5157 | 12.8M | bool has_pattern_trans = false; |
5158 | 12.8M | cmm_dev_profile_t *dev_profile; |
5159 | | |
5160 | 12.8M | if (pdcolor == NULL) |
5161 | 0 | return_error(gs_error_unknownerror); /* color must be defined */ |
5162 | | |
5163 | 12.8M | code = pdf14_initialize_ctx(orig_dev, NULL); |
5164 | 12.8M | if (code < 0) |
5165 | 0 | return code; |
5166 | | |
5167 | | /* If we are doing a fill with a pattern that has a transparency then |
5168 | | go ahead and do a push and a pop of the transparency group */ |
5169 | 12.8M | if (gx_dc_is_pattern1_color(pdcolor)) { |
5170 | 0 | if( gx_pattern1_get_transptr(pdcolor) != NULL) { |
5171 | 0 | ptile = pdcolor->colors.pattern.p_tile; |
5172 | | /* Set up things in the ptile so that we get the proper |
5173 | | blending etc */ |
5174 | | /* Set the blending procs and the is_additive setting based |
5175 | | upon the number of channels */ |
5176 | 0 | if (ptile->ttrans->n_chan-1 < 4) { |
5177 | 0 | ptile->ttrans->blending_procs = &rgb_blending_procs; |
5178 | 0 | ptile->ttrans->is_additive = true; |
5179 | 0 | } else { |
5180 | 0 | ptile->ttrans->blending_procs = &cmyk_blending_procs; |
5181 | 0 | ptile->ttrans->is_additive = false; |
5182 | 0 | } |
5183 | | /* Set the procs so that we use the proper filling method. */ |
5184 | 0 | gx_set_pattern_procs_trans((gx_device_color*) pdcolor); |
5185 | | /* Based upon if the tiles overlap pick the type of rect |
5186 | | fill that we will want to use */ |
5187 | 0 | if (ptile->has_overlap) { |
5188 | | /* This one does blending since there is tile overlap */ |
5189 | 0 | ptile->ttrans->pat_trans_fill = &tile_rect_trans_blend; |
5190 | 0 | } else { |
5191 | | /* This one does no blending since there is no tile overlap */ |
5192 | 0 | ptile->ttrans->pat_trans_fill = &tile_rect_trans_simple; |
5193 | 0 | } |
5194 | | /* Push the group */ |
5195 | 0 | group_rect.p.x = x; |
5196 | 0 | group_rect.p.y = max(0,y); |
5197 | 0 | group_rect.q.x = x + w; |
5198 | 0 | group_rect.q.y = y + h; |
5199 | 0 | if (!(w <= 0 || h <= 0)) { |
5200 | |
|
5201 | 0 | pdf14_group_color_t *group_color_info = pdf14_clone_group_color_info((gx_device *) p14dev, p14dev->ctx->stack->group_color_info); |
5202 | 0 | if (group_color_info == NULL) |
5203 | 0 | return_error(gs_error_VMerror); |
5204 | | |
5205 | 0 | code = pdf14_push_transparency_group(p14dev->ctx, &group_rect, |
5206 | 0 | 1, 0, 65535, 65535, 65535, BLEND_MODE_Normal, 0, 0, |
5207 | 0 | ptile->ttrans->n_chan-1, false, false, NULL, NULL, |
5208 | 0 | group_color_info, NULL, NULL); |
5209 | 0 | if (code < 0) |
5210 | 0 | return code; |
5211 | | /* Set up the output buffer information now that we have |
5212 | | pushed the group */ |
5213 | 0 | fill_trans_buffer = new_pattern_trans_buff(p14dev->memory); |
5214 | 0 | if (fill_trans_buffer == NULL) |
5215 | 0 | return_error(gs_error_VMerror); |
5216 | | |
5217 | 0 | pdf14_get_buffer_information((gx_device *) p14dev, |
5218 | 0 | fill_trans_buffer, NULL, false); |
5219 | | /* Store this in the appropriate place in pdcolor. This |
5220 | | is released later after the mask fill */ |
5221 | 0 | ptile->ttrans->fill_trans_buffer = fill_trans_buffer; |
5222 | 0 | has_pattern_trans = true; |
5223 | 0 | } |
5224 | 0 | } |
5225 | 0 | } |
5226 | 12.8M | if (pcpath != 0) { |
5227 | 1.71M | gx_make_clip_device_on_stack(&cdev, pcpath, orig_dev); |
5228 | 1.71M | dev = (gx_device *) & cdev; |
5229 | 1.71M | } else |
5230 | 11.1M | dev = orig_dev; |
5231 | 12.8M | if (depth > 1) { |
5232 | | /****** CAN'T DO ROP OR HALFTONE WITH ALPHA ******/ |
5233 | 0 | code = (*dev_proc(dev, copy_alpha)) |
5234 | 0 | (dev, data, dx, raster, id, x, y, w, h, |
5235 | 0 | gx_dc_pure_color(pdcolor), depth); |
5236 | 12.8M | } else { |
5237 | 12.8M | code = pdcolor->type->fill_masked(pdcolor, data, dx, raster, id, |
5238 | 12.8M | x, y, w, h, dev, lop, false); |
5239 | 12.8M | } |
5240 | 12.8M | if (has_pattern_trans) { |
5241 | 0 | bool has_tags = device_encodes_tags(dev); |
5242 | 0 | if (code >= 0) |
5243 | 0 | code = dev_proc(dev, get_profile)(dev, &dev_profile); |
5244 | 0 | if (code >= 0) |
5245 | 0 | code = pdf14_pop_transparency_group(NULL, p14dev->ctx, |
5246 | 0 | p14dev->blend_procs, |
5247 | 0 | p14dev->color_info.num_components - has_tags, |
5248 | 0 | dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE], |
5249 | 0 | orig_dev); |
5250 | 0 | gs_free_object(p14dev->memory, ptile->ttrans->fill_trans_buffer, |
5251 | 0 | "pdf14_fill_mask"); |
5252 | 0 | ptile->ttrans->fill_trans_buffer = NULL; /* Avoid GC issues */ |
5253 | 0 | } |
5254 | 12.8M | if (pcpath != 0) |
5255 | 1.71M | gx_destroy_clip_device_on_stack(&cdev); |
5256 | 12.8M | return code; |
5257 | 12.8M | } |
5258 | | |
5259 | | |
5260 | | |
5261 | | /* Used for filling rects when we are doing a fill with a pattern that |
5262 | | has transparency */ |
5263 | | static int |
5264 | | pdf14_tile_pattern_fill(gx_device * pdev, const gs_gstate * pgs, |
5265 | | gx_path * ppath, const gx_fill_params * params, |
5266 | | const gx_device_color * pdevc, |
5267 | | const gx_clip_path * pcpath) |
5268 | 66.4k | { |
5269 | 66.4k | int code; |
5270 | 66.4k | gs_gstate *pgs_noconst = (gs_gstate *)pgs; /* Break const. */ |
5271 | 66.4k | gs_fixed_rect clip_box; |
5272 | 66.4k | gs_fixed_rect outer_box; |
5273 | 66.4k | pdf14_device * p14dev = (pdf14_device *)pdev; |
5274 | 66.4k | gs_int_rect rect; |
5275 | 66.4k | gx_clip_rect *curr_clip_rect; |
5276 | 66.4k | gx_color_tile *ptile = NULL; |
5277 | 66.4k | int k; |
5278 | 66.4k | gx_pattern_trans_t *fill_trans_buffer = NULL; |
5279 | 66.4k | gs_int_point phase; /* Needed during clist rendering for band offset */ |
5280 | 66.4k | int n_chan_tile; |
5281 | 66.4k | gx_clip_path cpath_intersection; |
5282 | 66.4k | gx_path path_ttrans; |
5283 | 66.4k | pdf14_group_color_t *group_color_info; |
5284 | 66.4k | bool has_tags = device_encodes_tags(pdev); |
5285 | | |
5286 | 66.4k | if (ppath == NULL) |
5287 | 0 | return_error(gs_error_unknownerror); /* should not happen */ |
5288 | 66.4k | if (pcpath != NULL) { |
5289 | 62.4k | code = gx_cpath_init_local_shared_nested(&cpath_intersection, pcpath, ppath->memory, 1); |
5290 | 62.4k | } else { |
5291 | 3.97k | (*dev_proc(pdev, get_clipping_box)) (pdev, &clip_box); |
5292 | 3.97k | gx_cpath_init_local(&cpath_intersection, ppath->memory); |
5293 | 3.97k | code = gx_cpath_from_rectangle(&cpath_intersection, &clip_box); |
5294 | 3.97k | } |
5295 | 66.4k | if (code < 0) |
5296 | 0 | return code; |
5297 | 66.4k | code = gx_cpath_intersect_with_params(&cpath_intersection, ppath, |
5298 | 66.4k | params->rule, pgs_noconst, params); |
5299 | 66.4k | if (code < 0) |
5300 | 0 | return code; |
5301 | | /* One (common) case worth optimising for is where we have a pattern that |
5302 | | * is positioned such that only one repeat of the tile is actually |
5303 | | * visible. In this case, we can restrict the size of the blending group |
5304 | | * we need to produce to be that of the actual area of the tile that is |
5305 | | * used. */ |
5306 | 66.4k | ptile = pdevc->colors.pattern.p_tile; |
5307 | 66.4k | if (ptile->ttrans != NULL) |
5308 | 19.9k | { |
5309 | 19.9k | if ((cpath_intersection.outer_box.p.x < 0) || |
5310 | 19.9k | (cpath_intersection.outer_box.p.y < 0) || |
5311 | 19.9k | (cpath_intersection.outer_box.q.x > int2fixed(ptile->ttrans->width)) || |
5312 | 12.4k | (cpath_intersection.outer_box.q.y > int2fixed(ptile->ttrans->height))) |
5313 | 7.97k | { |
5314 | | /* More than one repeat of the tile would be visible, so we can't |
5315 | | * use the optimisation here. (Actually, this test isn't quite |
5316 | | * right - it actually tests whether more than the '0th' repeat |
5317 | | * of the tile is visible. A better test would test if just one |
5318 | | * repeat of the tile was visible, irrespective of which one. |
5319 | | * This is (hopefully) relatively rare, and would make the code |
5320 | | * below more complex too, so we're ignoring that for now. If it |
5321 | | * becomes evident that it's a case that matters we can revisit |
5322 | | * it.) */ |
5323 | 11.9k | } else { |
5324 | | /* Only the 0th repeat is visible. Restrict the size further to |
5325 | | * just the used area of that patch. */ |
5326 | 11.9k | gx_path_init_local(&path_ttrans, ppath->memory); |
5327 | 11.9k | code = gx_path_add_rectangle(&path_ttrans, |
5328 | 11.9k | int2fixed(ptile->ttrans->rect.p.x), |
5329 | 11.9k | int2fixed(ptile->ttrans->rect.p.y), |
5330 | 11.9k | int2fixed(ptile->ttrans->rect.q.x), |
5331 | 11.9k | int2fixed(ptile->ttrans->rect.q.y)); |
5332 | 11.9k | if (code < 0) |
5333 | 0 | return code; |
5334 | 11.9k | code = gx_cpath_intersect(&cpath_intersection, &path_ttrans, |
5335 | 11.9k | params->rule, pgs_noconst); |
5336 | 11.9k | gx_path_free(&path_ttrans, "pdf14_tile_pattern_fill(path_ttrans)"); |
5337 | 11.9k | if (code < 0) |
5338 | 0 | return code; |
5339 | 11.9k | } |
5340 | 19.9k | } |
5341 | | /* Now let us push a transparency group into which we are |
5342 | | * going to tile the pattern. */ |
5343 | 66.4k | if (ppath != NULL) { |
5344 | 66.4k | pdf14_device save_pdf14_dev; /* save area for p14dev */ |
5345 | | |
5346 | 66.4k | gx_cpath_outer_box(&cpath_intersection, &outer_box); |
5347 | 66.4k | rect.p.x = fixed2int(outer_box.p.x); |
5348 | 66.4k | rect.p.y = fixed2int(outer_box.p.y); |
5349 | 66.4k | rect.q.x = fixed2int_ceiling(outer_box.q.x); |
5350 | 66.4k | rect.q.y = fixed2int_ceiling(outer_box.q.y); |
5351 | | |
5352 | | /* The color space of this group must be the same as that of the |
5353 | | tile. Then when we pop the group, if there is a mismatch between |
5354 | | the tile color space and the current context we will do the proper |
5355 | | conversion. In this way, we ensure that if the tile has any overlapping |
5356 | | occuring it will be blended in the proper manner i.e in the tile |
5357 | | underlying color space. */ |
5358 | 66.4k | if (ptile->cdev == NULL) { |
5359 | 19.9k | if (ptile->ttrans == NULL) |
5360 | 0 | return_error(gs_error_unknownerror); /* should not happen */ |
5361 | 19.9k | n_chan_tile = ptile->ttrans->n_chan; |
5362 | 46.4k | } else { |
5363 | 46.4k | n_chan_tile = ptile->cdev->common.color_info.num_components+1; |
5364 | 46.4k | } |
5365 | 66.4k | memcpy(&save_pdf14_dev, p14dev, sizeof(pdf14_device)); |
5366 | | |
5367 | | /* Transparency handling with patterns confuses me, so some notes... |
5368 | | * |
5369 | | * For simple, non-transparent patterns, like you'd get in PS, we've |
5370 | | * used bitmap tiles. Draw into those tiles, and tile those out multiple |
5371 | | * times. To cope with unmarked pixels, we have a "transparency" plane |
5372 | | * (simple on/off) that says whether a pixel is marked or not. |
5373 | | * |
5374 | | * For patterns with transparency (but not blending), we can create an |
5375 | | * isolated transparency group, tile all the bitmap tiles into that, and |
5376 | | * then blend that back with the required alpha at the end. This works |
5377 | | * because the alpha values of the individual objects within the tile are |
5378 | | * recorded in that group. |
5379 | | * |
5380 | | * We can't do that for groups that use blending though, as each object |
5381 | | * in the pattern might use a different blend, and we don't (can't) record |
5382 | | * the blending mode. An isolated group doesn't even allow us to actually |
5383 | | * do the blending at all. So, for such patterns (any patterns that sets (or |
5384 | | * just has a resource that mentions) a non-normal blend mode), we use |
5385 | | * a pattern clist. |
5386 | | */ |
5387 | 66.4k | if (ptile->cdev == NULL) { |
5388 | 19.9k | group_color_info = pdf14_clone_group_color_info(pdev, p14dev->ctx->stack->group_color_info); |
5389 | 19.9k | if (group_color_info == NULL) |
5390 | 0 | return gs_error_VMerror; |
5391 | | |
5392 | 19.9k | code = pdf14_push_transparency_group(p14dev->ctx, &rect, 1, 0, (uint16_t)floor(65535 * p14dev->alpha + 0.5), |
5393 | 19.9k | (uint16_t)floor(65535 * p14dev->shape + 0.5), (uint16_t)floor(65535 * p14dev->opacity + 0.5), |
5394 | 19.9k | BLEND_MODE_Normal, 0, 0, n_chan_tile - 1, false, false, |
5395 | 19.9k | NULL, NULL, group_color_info, pgs_noconst, pdev); |
5396 | 19.9k | if (code < 0) |
5397 | 0 | return code; |
5398 | 19.9k | } |
5399 | | |
5400 | | /* Set the blending procs and the is_additive setting based |
5401 | | upon the number of channels */ |
5402 | 66.4k | if (ptile->cdev == NULL) { |
5403 | 19.9k | if (n_chan_tile-1 < 4) { |
5404 | 19.2k | ptile->ttrans->blending_procs = &rgb_blending_procs; |
5405 | 19.2k | ptile->ttrans->is_additive = true; |
5406 | 19.2k | } else { |
5407 | 690 | ptile->ttrans->blending_procs = &cmyk_blending_procs; |
5408 | 690 | ptile->ttrans->is_additive = false; |
5409 | 690 | } |
5410 | 19.9k | } |
5411 | | /* Now lets go through the rect list and fill with the pattern */ |
5412 | | /* First get the buffer that we will be filling */ |
5413 | 66.4k | if (ptile->cdev == NULL) { |
5414 | 19.9k | fill_trans_buffer = new_pattern_trans_buff(pgs->memory); |
5415 | 19.9k | if (fill_trans_buffer == NULL) { |
5416 | 0 | p14dev->pclist_device = NULL; |
5417 | 0 | return_error(gs_error_VMerror); |
5418 | 0 | } |
5419 | 19.9k | pdf14_get_buffer_information(pdev, fill_trans_buffer, NULL, false); |
5420 | | /* Based upon if the tiles overlap pick the type of rect fill that we will |
5421 | | want to use */ |
5422 | 19.9k | if (ptile->has_overlap) { |
5423 | | /* This one does blending since there is tile overlap */ |
5424 | 1.35k | ptile->ttrans->pat_trans_fill = &tile_rect_trans_blend; |
5425 | 18.6k | } else { |
5426 | | /* This one does no blending since there is no tile overlap */ |
5427 | 18.6k | ptile->ttrans->pat_trans_fill = &tile_rect_trans_simple; |
5428 | 18.6k | } |
5429 | | /* fill the rectangles */ |
5430 | 19.9k | phase.x = pdevc->phase.x; |
5431 | 19.9k | phase.y = pdevc->phase.y; |
5432 | 19.9k | if (cpath_intersection.rect_list->list.head != NULL){ |
5433 | 782 | curr_clip_rect = cpath_intersection.rect_list->list.head->next; |
5434 | 13.0k | for( k = 0; k < cpath_intersection.rect_list->list.count && code >= 0; k++){ |
5435 | 12.2k | if_debug5m('v', pgs->memory, |
5436 | 12.2k | "[v]pdf14_tile_pattern_fill, (%d, %d), %d x %d pat_id %u \n", |
5437 | 12.2k | curr_clip_rect->xmin, curr_clip_rect->ymin, |
5438 | 12.2k | curr_clip_rect->xmax-curr_clip_rect->xmin, |
5439 | 12.2k | curr_clip_rect->ymax-curr_clip_rect->ymin, (int)ptile->id); |
5440 | 12.2k | code = gx_trans_pattern_fill_rect(curr_clip_rect->xmin, curr_clip_rect->ymin, |
5441 | 12.2k | curr_clip_rect->xmax, curr_clip_rect->ymax, ptile, |
5442 | 12.2k | fill_trans_buffer, phase, pdev, pdevc, 1); |
5443 | 12.2k | curr_clip_rect = curr_clip_rect->next; |
5444 | 12.2k | } |
5445 | 19.1k | } else if (cpath_intersection.rect_list->list.count == 1) { |
5446 | | /* The case when there is just a single rect */ |
5447 | 18.9k | if_debug5m('v', pgs->memory, |
5448 | 18.9k | "[v]pdf14_tile_pattern_fill, (%d, %d), %d x %d pat_id %u \n", |
5449 | 18.9k | cpath_intersection.rect_list->list.single.xmin, |
5450 | 18.9k | cpath_intersection.rect_list->list.single.ymin, |
5451 | 18.9k | cpath_intersection.rect_list->list.single.xmax- |
5452 | 18.9k | cpath_intersection.rect_list->list.single.xmin, |
5453 | 18.9k | cpath_intersection.rect_list->list.single.ymax- |
5454 | 18.9k | cpath_intersection.rect_list->list.single.ymin, |
5455 | 18.9k | (int)ptile->id); |
5456 | 18.9k | code = gx_trans_pattern_fill_rect(cpath_intersection.rect_list->list.single.xmin, |
5457 | 18.9k | cpath_intersection.rect_list->list.single.ymin, |
5458 | 18.9k | cpath_intersection.rect_list->list.single.xmax, |
5459 | 18.9k | cpath_intersection.rect_list->list.single.ymax, |
5460 | 18.9k | ptile, fill_trans_buffer, phase, pdev, pdevc, 1); |
5461 | 18.9k | } |
5462 | 46.4k | } else { |
5463 | | /* Clist pattern with transparency. Create a clip device from our |
5464 | | cpath_intersection. The above non-clist case could probably be |
5465 | | done this way too, which will reduce the amount of code here. |
5466 | | That is for another day though due to time constraints*/ |
5467 | 46.4k | gx_device *dev; |
5468 | 46.4k | gx_device_clip clipdev; |
5469 | | |
5470 | 46.4k | gx_make_clip_device_on_stack(&clipdev, &cpath_intersection, pdev); |
5471 | 46.4k | dev = (gx_device *)&clipdev; |
5472 | 46.4k | phase.x = pdevc->phase.x; |
5473 | 46.4k | phase.y = pdevc->phase.y; |
5474 | 46.4k | code = gx_trans_pattern_fill_rect(rect.p.x, rect.p.y, rect.q.x, rect.q.y, |
5475 | 46.4k | ptile, fill_trans_buffer, phase, |
5476 | 46.4k | dev, pdevc, 1); |
5477 | 46.4k | gx_destroy_clip_device_on_stack(&clipdev); |
5478 | 46.4k | } |
5479 | | /* We're done drawing with the pattern, remove the reference to the |
5480 | | * pattern device |
5481 | | */ |
5482 | 66.4k | p14dev->pclist_device = NULL; |
5483 | 66.4k | if (code < 0) |
5484 | 0 | return code; |
5485 | | |
5486 | | /* free our buffer object */ |
5487 | 66.4k | if (fill_trans_buffer != NULL) { |
5488 | 19.9k | gs_free_object(pgs->memory, fill_trans_buffer, "pdf14_tile_pattern_fill"); |
5489 | 19.9k | ptile->ttrans->fill_trans_buffer = NULL; /* Avoid GC issues */ |
5490 | 19.9k | } |
5491 | 66.4k | if (ptile->cdev == NULL) { |
5492 | | /* pop our transparency group which will force the blending. |
5493 | | This was all needed for Bug 693498 */ |
5494 | 19.9k | code = pdf14_pop_transparency_group(pgs_noconst, p14dev->ctx, |
5495 | 19.9k | p14dev->blend_procs, |
5496 | 19.9k | p14dev->color_info.num_components - has_tags, |
5497 | 19.9k | p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], |
5498 | 19.9k | pdev); |
5499 | 19.9k | } |
5500 | 66.4k | memcpy(p14dev, &save_pdf14_dev, sizeof(pdf14_device)); |
5501 | 66.4k | p14dev->pclist_device = NULL; |
5502 | 66.4k | } |
5503 | 66.4k | gx_cpath_free(&cpath_intersection, "pdf14_tile_pattern_fill"); |
5504 | 66.4k | return code; |
5505 | 66.4k | } |
5506 | | |
5507 | | /* Useful function that should probably go elsewhere. |
5508 | | * Call this function to find the topmost pdf14 device in the device chain, |
5509 | | * or NULL if there is not one. |
5510 | | */ |
5511 | | static pdf14_device *find_pdf14_device(gx_device *dev) |
5512 | 0 | { |
5513 | 0 | pdf14_device *pdev; |
5514 | |
|
5515 | 0 | if (dev_proc(dev, dev_spec_op)(dev, gxdso_is_pdf14_device, &pdev, sizeof(pdev)) <= 0) |
5516 | 0 | return NULL; |
5517 | 0 | return pdev; |
5518 | 0 | } |
5519 | | |
5520 | | /* Imager render for pattern transparency filling. This is just here to catch |
5521 | | the final flush, at which time we will pop the group and reset a few items */ |
5522 | | static int |
5523 | | pdf14_pattern_trans_render(gx_image_enum * penum, const byte * buffer, int data_x, |
5524 | | uint w, int h, gx_device * dev) |
5525 | 0 | { |
5526 | 0 | int code; |
5527 | 0 | pdf14_device * p14dev; |
5528 | 0 | const gs_gstate * pgs = penum->pgs; |
5529 | 0 | gx_device_color * pdcolor = (penum->icolor1); |
5530 | 0 | gx_color_tile *ptile = pdcolor->colors.pattern.p_tile; |
5531 | 0 | bool has_tags = device_encodes_tags(dev); |
5532 | | |
5533 | | /* Pass along to the original renderer */ |
5534 | 0 | code = (ptile->ttrans->image_render)(penum, buffer, data_x, w, h, dev); |
5535 | 0 | if (code < 0) |
5536 | 0 | return code; |
5537 | | /* On our final time through here, go ahead and pop the transparency |
5538 | | group and reset the procs in the device color. And free the fill |
5539 | | trans buffer object */ |
5540 | 0 | if (h == 0 && ptile->trans_group_popped == false) { |
5541 | 0 | p14dev = find_pdf14_device(dev); |
5542 | |
|
5543 | 0 | if (p14dev->pclist_device == NULL) { |
5544 | | /* Used if we are on clist writing phase. Would only |
5545 | | occur if we somehow failed in high level clist |
5546 | | image writing */ |
5547 | 0 | code = gs_end_transparency_group((gs_gstate *) pgs); |
5548 | 0 | } else { |
5549 | | /* Used if we are on clist reading phase. If we had high level |
5550 | | image in clist */ |
5551 | 0 | cmm_dev_profile_t *dev_profile; |
5552 | 0 | code = dev_proc(dev, get_profile)(dev, &dev_profile); |
5553 | 0 | if (code < 0) |
5554 | 0 | return code; |
5555 | | |
5556 | 0 | if_debug2m('v', p14dev->ctx->memory, |
5557 | 0 | "[v*] Popping trans group pattern fill, uid = %ld id = %ld \n", |
5558 | 0 | ptile->uid.id, ptile->id); |
5559 | 0 | code = pdf14_pop_transparency_group(NULL, p14dev->ctx, p14dev->blend_procs, |
5560 | 0 | p14dev->color_info.num_components - has_tags, |
5561 | 0 | dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE], |
5562 | 0 | (gx_device *) p14dev); |
5563 | 0 | } |
5564 | 0 | pdcolor->colors.pattern.p_tile->trans_group_popped = true; |
5565 | 0 | gs_free_object(pgs->memory, ptile->ttrans->fill_trans_buffer, |
5566 | 0 | "pdf14_pattern_trans_render"); |
5567 | 0 | ptile->ttrans->fill_trans_buffer = NULL; /* Avoid GC issues */ |
5568 | 0 | } |
5569 | 0 | return code; |
5570 | 0 | } |
5571 | | |
5572 | | /* This function is used to get things in place for filling a mask image |
5573 | | with a pattern that has transparency. It is used by pdf14_begin_type_image |
5574 | | and pdf14_clist_begin_type_image */ |
5575 | | static int |
5576 | | pdf14_patt_trans_image_fill(gx_device * dev, const gs_gstate * pgs, |
5577 | | const gs_matrix *pmat, const gs_image_common_t *pic, |
5578 | | const gs_int_rect * prect, |
5579 | | const gx_drawing_color * pdcolor, |
5580 | | const gx_clip_path * pcpath, gs_memory_t * mem, |
5581 | | gx_image_enum_common_t ** pinfo) |
5582 | 0 | { |
5583 | 0 | const gs_image_t *pim = (const gs_image_t *)pic; |
5584 | 0 | pdf14_device * p14dev = (pdf14_device *)dev; |
5585 | 0 | gx_color_tile *ptile; |
5586 | 0 | int code; |
5587 | 0 | gs_int_rect group_rect; |
5588 | 0 | gx_image_enum *penum; |
5589 | 0 | gs_rect bbox_in, bbox_out; |
5590 | 0 | gx_pattern_trans_t *fill_trans_buffer; |
5591 | |
|
5592 | 0 | ptile = pdcolor->colors.pattern.p_tile; |
5593 | | /* Set up things in the ptile so that we get the proper |
5594 | | blending etc */ |
5595 | | /* Set the blending procs and the is_additive setting based |
5596 | | upon the number of channels */ |
5597 | 0 | if (ptile->ttrans->n_chan-1 < 4) { |
5598 | 0 | ptile->ttrans->blending_procs = &rgb_blending_procs; |
5599 | 0 | ptile->ttrans->is_additive = true; |
5600 | 0 | } else { |
5601 | 0 | ptile->ttrans->blending_procs = &cmyk_blending_procs; |
5602 | 0 | ptile->ttrans->is_additive = false; |
5603 | 0 | } |
5604 | | /* Set the blending mode in the ptile based upon the current |
5605 | | setting in the gs_gstate */ |
5606 | 0 | ptile->blending_mode = pgs->blend_mode; |
5607 | | /* Based upon if the tiles overlap pick the type of rect |
5608 | | fill that we will want to use */ |
5609 | 0 | if (ptile->has_overlap) { |
5610 | | /* This one does blending since there is tile overlap */ |
5611 | 0 | ptile->ttrans->pat_trans_fill = &tile_rect_trans_blend; |
5612 | 0 | } else { |
5613 | | /* This one does no blending since there is no tile overlap */ |
5614 | 0 | ptile->ttrans->pat_trans_fill = &tile_rect_trans_simple; |
5615 | 0 | } |
5616 | | /* Set the procs so that we use the proper filling method. */ |
5617 | 0 | gx_set_pattern_procs_trans((gx_device_color*) pdcolor); |
5618 | | /* Let the imaging stuff get set up */ |
5619 | 0 | code = gx_default_begin_typed_image(dev, pgs, pmat, pic, |
5620 | 0 | prect, pdcolor,pcpath, mem, pinfo); |
5621 | 0 | if (code < 0) |
5622 | 0 | return code; |
5623 | | /* Now Push the group */ |
5624 | | /* First apply the inverse of the image matrix to our |
5625 | | image size to get our bounding box. */ |
5626 | 0 | bbox_in.p.x = 0; |
5627 | 0 | bbox_in.p.y = 0; |
5628 | 0 | bbox_in.q.x = pim->Width; |
5629 | 0 | bbox_in.q.y = pim->Height; |
5630 | 0 | code = gs_bbox_transform_inverse(&bbox_in, &(pim->ImageMatrix), |
5631 | 0 | &bbox_out); |
5632 | 0 | if (code < 0) |
5633 | 0 | return code; |
5634 | | /* That in turn will get hit by the matrix in the gs_gstate */ |
5635 | 0 | code = compute_group_device_int_rect(p14dev, &group_rect, |
5636 | 0 | &bbox_out, (gs_gstate *)pgs); |
5637 | 0 | if (code < 0) |
5638 | 0 | return code; |
5639 | 0 | if (!(pim->Width == 0 || pim->Height == 0)) { |
5640 | 0 | if_debug2m('v', p14dev->ctx->memory, |
5641 | 0 | "[v*] Pushing trans group patt_trans_image_fill, uid = %ld id = %ld \n", |
5642 | 0 | ptile->uid.id, ptile->id); |
5643 | |
|
5644 | 0 | code = pdf14_push_transparency_group(p14dev->ctx, &group_rect, 1, 0, 65535, 65535, |
5645 | 0 | 65535, pgs->blend_mode, 0, 0, |
5646 | 0 | ptile->ttrans->n_chan-1, false, false, |
5647 | 0 | NULL, NULL, NULL, (gs_gstate *)pgs, dev); |
5648 | | |
5649 | | /* Set up the output buffer information now that we have |
5650 | | pushed the group */ |
5651 | 0 | fill_trans_buffer = new_pattern_trans_buff(pgs->memory); |
5652 | 0 | if (fill_trans_buffer == NULL) |
5653 | 0 | return_error(gs_error_VMerror); |
5654 | | |
5655 | 0 | pdf14_get_buffer_information(dev, fill_trans_buffer, NULL, false); |
5656 | | |
5657 | | /* Store this in the appropriate place in pdcolor. This |
5658 | | is released later in pdf14_pattern_trans_render when |
5659 | | we are all done with the mask fill */ |
5660 | 0 | ptile->ttrans->fill_trans_buffer = fill_trans_buffer; |
5661 | | |
5662 | | /* Change the renderer to handle this case so we can catch the |
5663 | | end. We will then pop the group and reset the pdcolor proc. |
5664 | | Keep the base renderer also. */ |
5665 | 0 | penum = (gx_image_enum *) *pinfo; |
5666 | 0 | ptile->ttrans->image_render = penum->render; |
5667 | 0 | penum->render = &pdf14_pattern_trans_render; |
5668 | 0 | ptile->trans_group_popped = false; |
5669 | 0 | } |
5670 | 0 | return code; |
5671 | 0 | } |
5672 | | |
5673 | | static int |
5674 | | pdf14_begin_typed_image(gx_device * dev, const gs_gstate * pgs, |
5675 | | const gs_matrix *pmat, const gs_image_common_t *pic, |
5676 | | const gs_int_rect * prect, |
5677 | | const gx_drawing_color * pdcolor, |
5678 | | const gx_clip_path * pcpath, gs_memory_t * mem, |
5679 | | gx_image_enum_common_t ** pinfo) |
5680 | 382k | { |
5681 | 382k | const gs_image_t *pim = (const gs_image_t *)pic; |
5682 | 382k | int code; |
5683 | | |
5684 | 382k | code = pdf14_initialize_ctx(dev, pgs); |
5685 | 382k | if (code < 0) |
5686 | 0 | return code; |
5687 | | |
5688 | | /* If we are filling an image mask with a pattern that has a transparency |
5689 | | then we need to do some special handling */ |
5690 | 382k | if (pim->ImageMask) { |
5691 | 96 | if (pdcolor != NULL && gx_dc_is_pattern1_color(pdcolor)) { |
5692 | 0 | if( gx_pattern1_get_transptr(pdcolor) != NULL){ |
5693 | | /* If we are in a final run through here for this case then |
5694 | | go ahead and push the transparency group. Also, update |
5695 | | the proc for the pattern color so that we used the |
5696 | | appropriate fill operation. Note that the group |
5697 | | is popped and the proc will be reset when we flush the |
5698 | | image data. This is handled in a special pdf14 image |
5699 | | renderer which will end up installed for this case. |
5700 | | Detect setting of begin_image to gx_no_begin_image. |
5701 | | (final recursive call) */ |
5702 | 0 | if (dev_proc(dev, begin_typed_image) != gx_default_begin_typed_image) { |
5703 | 0 | code = pdf14_patt_trans_image_fill(dev, pgs, pmat, pic, |
5704 | 0 | prect, pdcolor, pcpath, mem, |
5705 | 0 | pinfo); |
5706 | 0 | return code; |
5707 | 0 | } |
5708 | 0 | } |
5709 | 0 | } |
5710 | 96 | } |
5711 | 382k | pdf14_set_marking_params(dev, pgs); |
5712 | 382k | return gx_default_begin_typed_image(dev, pgs, pmat, pic, prect, pdcolor, |
5713 | 382k | pcpath, mem, pinfo); |
5714 | 382k | } |
5715 | | |
5716 | | static void |
5717 | | pdf14_set_params(gs_gstate * pgs, |
5718 | | gx_device * dev, |
5719 | | const gs_pdf14trans_params_t * pparams) |
5720 | 8.26M | { |
5721 | 8.26M | if_debug0m('v', dev->memory, "[v]pdf14_set_params\n"); |
5722 | 8.26M | if (pparams->changed & PDF14_SET_BLEND_MODE) |
5723 | 2.32M | pgs->blend_mode = pparams->blend_mode; |
5724 | 8.26M | if (pparams->changed & PDF14_SET_TEXT_KNOCKOUT) |
5725 | 1.14M | pgs->text_knockout = pparams->text_knockout; |
5726 | 8.26M | if (pparams->changed & PDF14_SET_AIS) |
5727 | 232k | pgs->alphaisshape = pparams->ais; |
5728 | 8.26M | if (pparams->changed & PDF14_SET_OVERPRINT) |
5729 | 2.14M | pgs->overprint = pparams->overprint; |
5730 | 8.26M | if (pparams->changed & PDF14_SET_STROKEOVERPRINT) |
5731 | 2.13M | pgs->stroke_overprint = pparams->stroke_overprint; |
5732 | 8.26M | if (pparams->changed & PDF14_SET_FILLCONSTANTALPHA) |
5733 | 2.68M | pgs->fillconstantalpha = pparams->fillconstantalpha; |
5734 | 8.26M | if (pparams->changed & PDF14_SET_STROKECONSTANTALPHA) |
5735 | 1.78M | pgs->strokeconstantalpha = pparams->strokeconstantalpha; |
5736 | 8.26M | if (pparams->changed & PDF14_SET_FILLSTROKE_STATE) { |
5737 | 1.81M | gs_swapcolors_quick(pgs); |
5738 | 1.81M | if (pparams->op_fs_state == PDF14_OP_STATE_STROKE) |
5739 | 633k | pgs->is_fill_color = false; |
5740 | 1.18M | else |
5741 | 1.18M | pgs->is_fill_color = true; |
5742 | 1.81M | } |
5743 | 8.26M | pdf14_set_marking_params(dev, pgs); |
5744 | 8.26M | } |
5745 | | |
5746 | | /* |
5747 | | * This open_device method for the PDF 1.4 compositor devices is only used |
5748 | | * when these devices are disabled. This routine is about as close to |
5749 | | * a pure "forwarding" open_device operation as is possible. Its only |
5750 | | * significant function is to ensure that the is_open field of the |
5751 | | * PDF 1.4 compositor devices matches that of the target device. |
5752 | | * |
5753 | | * We assume this procedure is called only if the device is not already |
5754 | | * open, and that gs_opendevice will take care of the is_open flag. |
5755 | | */ |
5756 | | static int |
5757 | | pdf14_forward_open_device(gx_device * dev) |
5758 | 0 | { |
5759 | 0 | gx_device_forward * pdev = (gx_device_forward *)dev; |
5760 | 0 | gx_device * tdev = pdev->target; |
5761 | 0 | int code; |
5762 | | |
5763 | | /* The PDF 1.4 compositing devices must have a target */ |
5764 | 0 | if (tdev == 0) |
5765 | 0 | return_error(gs_error_unknownerror); |
5766 | 0 | if ((code = gs_opendevice(tdev)) >= 0) |
5767 | 0 | gx_device_copy_params(dev, tdev); |
5768 | 0 | return code; |
5769 | 0 | } |
5770 | | |
5771 | | /* |
5772 | | * Convert all device procs to be 'forwarding'. The caller is responsible |
5773 | | * for setting any device procs that should not be forwarded. |
5774 | | */ |
5775 | | static void |
5776 | | pdf14_forward_device_procs(gx_device * dev) |
5777 | 1.14M | { |
5778 | 1.14M | gx_device_forward *pdev = (gx_device_forward *)dev; |
5779 | 1.14M | pdf14_device *p14dev = (pdf14_device*)dev; |
5780 | | |
5781 | | /* If doing simulated overprint with spot colors |
5782 | | then makes sure to reset devn setting */ |
5783 | 1.14M | if (p14dev->overprint_sim && |
5784 | 0 | p14dev->color_info.num_components > 4) |
5785 | 0 | p14dev->icc_struct->supports_devn = |
5786 | 0 | p14dev->target_support_devn; |
5787 | | |
5788 | | /* |
5789 | | * We are using gx_device_forward_fill_in_procs to set the various procs. |
5790 | | * This will ensure that any new device procs are also set. However that |
5791 | | * routine only changes procs which are NULL. Thus we start by setting all |
5792 | | * procs to NULL. |
5793 | | */ |
5794 | 1.14M | memset(&(pdev->procs), 0, size_of(pdev->procs)); |
5795 | 1.14M | gx_device_forward_fill_in_procs(pdev); |
5796 | | /* |
5797 | | * gx_device_forward_fill_in_procs does not forward all procs. |
5798 | | * Set the remainding procs to also forward. |
5799 | | */ |
5800 | 1.14M | set_dev_proc(dev, close_device, gx_forward_close_device); |
5801 | 1.14M | set_dev_proc(dev, fill_rectangle, gx_forward_fill_rectangle); |
5802 | 1.14M | set_dev_proc(dev, fill_rectangle_hl_color, gx_forward_fill_rectangle_hl_color); |
5803 | 1.14M | set_dev_proc(dev, copy_mono, gx_forward_copy_mono); |
5804 | 1.14M | set_dev_proc(dev, copy_color, gx_forward_copy_color); |
5805 | 1.14M | set_dev_proc(dev, get_page_device, gx_forward_get_page_device); |
5806 | 1.14M | set_dev_proc(dev, strip_tile_rectangle, gx_forward_strip_tile_rectangle); |
5807 | 1.14M | set_dev_proc(dev, copy_alpha, gx_forward_copy_alpha); |
5808 | 1.14M | set_dev_proc(dev, get_profile, gx_forward_get_profile); |
5809 | 1.14M | set_dev_proc(dev, set_graphics_type_tag, gx_forward_set_graphics_type_tag); |
5810 | | /* These are forwarding devices with minor tweaks. */ |
5811 | 1.14M | set_dev_proc(dev, open_device, pdf14_forward_open_device); |
5812 | 1.14M | set_dev_proc(dev, put_params, pdf14_forward_put_params); |
5813 | 1.14M | } |
5814 | | |
5815 | | /* |
5816 | | * Disable the PDF 1.4 compositor device. Once created, the PDF 1.4 |
5817 | | * compositor device is never removed. (We do not have a remove compositor |
5818 | | * method.) However it is no-op'ed when the PDF 1.4 device is popped. This |
5819 | | * routine implements that action. |
5820 | | */ |
5821 | | int |
5822 | | pdf14_disable_device(gx_device * dev) |
5823 | 1.13M | { |
5824 | 1.13M | gx_device_forward * pdev = (gx_device_forward *)dev; |
5825 | | |
5826 | 1.13M | if_debug0m('v', dev->memory, "[v]pdf14_disable_device\n"); |
5827 | 1.13M | dev->color_info = pdev->target->color_info; |
5828 | 1.13M | pdf14_forward_device_procs(dev); |
5829 | 1.13M | set_dev_proc(dev, composite, pdf14_forward_composite); |
5830 | 1.13M | return 0; |
5831 | 1.13M | } |
5832 | | |
5833 | | /* |
5834 | | * The default color space for PDF 1.4 blend modes is based upon the process |
5835 | | * color model of the output device. |
5836 | | */ |
5837 | | static pdf14_default_colorspace_t |
5838 | | pdf14_determine_default_blend_cs(gx_device * pdev, bool use_pdf14_accum, |
5839 | | pdf14_blend_cs_t *blend_cs_state) |
5840 | 3.53M | { |
5841 | | /* If a blend color space was specified, then go ahead and use that to |
5842 | | define the default color space for the blend modes. Only Gray, RGB |
5843 | | or CMYK blend color spaces are allowed. Note we do not allow this |
5844 | | setting if we are dealing with a separation device. */ |
5845 | 3.53M | cmm_dev_profile_t *dev_profile; |
5846 | 3.53M | cmm_profile_t *blend_profile = NULL; |
5847 | 3.53M | pdf14_blend_cs_t temp_cs_state = PDF14_BLEND_CS_UNSPECIFIED; |
5848 | 3.53M | int code = dev_proc(pdev, get_profile)(pdev, &dev_profile); |
5849 | 3.53M | bool valid_blend_cs = false; |
5850 | 3.53M | int has_tags = device_encodes_tags(pdev); |
5851 | | |
5852 | 3.53M | *blend_cs_state = PDF14_BLEND_CS_UNSPECIFIED; |
5853 | | |
5854 | | /* Are we using a blend color space or the output intent color space? Also |
5855 | | is there a conflict in the settings. i.e. has someone set a blend color |
5856 | | space and tried to use the output intent with simulate overprint setting. |
5857 | | */ |
5858 | 3.53M | if (dev_profile->overprint_control == gs_overprint_control_simulate && |
5859 | 0 | dev_profile->oi_profile != NULL && |
5860 | 0 | !gsicc_profiles_equal(dev_profile->oi_profile, dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE])) { |
5861 | | /* If blend profile is also set, throw a warning about output intent not being used. We have |
5862 | | possible conflicting command line settings and we will err on using the blend profile |
5863 | | if one was specified. */ |
5864 | 0 | if (dev_profile->blend_profile != NULL && |
5865 | 0 | !gsicc_profiles_equal(dev_profile->blend_profile, dev_profile->oi_profile)) { |
5866 | 0 | blend_profile = dev_profile->blend_profile; |
5867 | 0 | temp_cs_state = PDF14_BLEND_CS_SPECIFIED; |
5868 | 0 | emprintf(pdev->memory, "Warning: OI profile not used for blending CS\n"); |
5869 | 0 | } else { |
5870 | | /* All good, use the output intent profile as we have one |
5871 | | and are doing simulate overprint with a different device |
5872 | | profile set. */ |
5873 | 0 | blend_profile = dev_profile->oi_profile; |
5874 | 0 | temp_cs_state = PDF14_BLEND_CS_OUTPUTINTENT; |
5875 | 0 | } |
5876 | 3.53M | } else if (dev_profile->blend_profile != NULL && |
5877 | 0 | !gsicc_profiles_equal(dev_profile->blend_profile, dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE])) { |
5878 | | /* Blend profile is different than device profile */ |
5879 | 0 | blend_profile = dev_profile->blend_profile; |
5880 | 0 | temp_cs_state = PDF14_BLEND_CS_SPECIFIED; |
5881 | 0 | } |
5882 | | |
5883 | | /* Make sure any blend color space is valid along with other cond */ |
5884 | 3.53M | if (code == 0 && blend_profile != NULL && !use_pdf14_accum) { |
5885 | 0 | if (!blend_profile->isdevlink && |
5886 | 0 | !blend_profile->islab && |
5887 | 0 | (blend_profile->data_cs == gsGRAY || |
5888 | 0 | blend_profile->data_cs == gsRGB || |
5889 | 0 | blend_profile->data_cs == gsCMYK)) { |
5890 | | /* Also, do not allow the use of the blend space when we are pushing |
5891 | | a pattern pdf14 device. Those should inherit from the parent */ |
5892 | 0 | if (!(gx_device_is_pattern_clist(pdev) || |
5893 | 0 | gx_device_is_pattern_accum(pdev))) { |
5894 | 0 | valid_blend_cs = true; |
5895 | 0 | } |
5896 | 0 | } |
5897 | 0 | } |
5898 | | |
5899 | | /* If num components is one, just go ahead and use gray. This avoids |
5900 | | issues with additive/subtractive mono color devices */ |
5901 | 3.53M | if (pdev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE || |
5902 | 3.28M | pdev->color_info.num_components == 1) { |
5903 | | /* |
5904 | | * Note: We do not allow the SeparationOrder device parameter for |
5905 | | * additive devices. Thus we always have 1 colorant for DeviceGray |
5906 | | * and 3 colorants for DeviceRGB. |
5907 | | */ |
5908 | 3.28M | if (valid_blend_cs) { |
5909 | 0 | *blend_cs_state = temp_cs_state; |
5910 | 0 | switch (blend_profile->num_comps) { |
5911 | 0 | case 1: |
5912 | 0 | return PDF14_DeviceGray; |
5913 | 0 | case 3: |
5914 | 0 | return PDF14_DeviceRGB; |
5915 | 0 | case 4: |
5916 | 0 | return PDF14_DeviceCMYK; |
5917 | 0 | } |
5918 | 0 | } |
5919 | 3.28M | if (pdev->color_info.num_components - has_tags == 1) |
5920 | 1.14M | return PDF14_DeviceGray; |
5921 | 2.14M | else if (pdev->color_info.num_components - has_tags == 3) |
5922 | 2.14M | return PDF14_DeviceRGB; |
5923 | 0 | else |
5924 | 0 | return PDF14_DeviceRGBspot; |
5925 | 3.28M | } else { |
5926 | | /* |
5927 | | * Check if the device is CMYK only or CMYK plus spot colors. Note |
5928 | | * the CMYK plus spot colors will not support the blend color space |
5929 | | */ |
5930 | 243k | int i, output_comp_num, num_cmyk_used = 0, num_cmyk = 0; |
5931 | | #if CUSTOM_BLENDING_MODE == ALWAYS_USE_CUSTOM_BLENDING |
5932 | | return PDF14_DeviceCustom; |
5933 | | #endif |
5934 | | /* |
5935 | | * Count the number of CMYK process components supported by the output |
5936 | | * device. |
5937 | | */ |
5938 | 1.21M | for (i = 0; i < 4; i++) { |
5939 | 975k | const char * pcomp_name = (const char *)DeviceCMYKComponents[i]; |
5940 | | |
5941 | 975k | output_comp_num = dev_proc(pdev, get_color_comp_index) |
5942 | 975k | (pdev, pcomp_name, strlen(pcomp_name), NO_COMP_NAME_TYPE_OP); |
5943 | 975k | if (output_comp_num >= 0) { |
5944 | 975k | num_cmyk++; |
5945 | 975k | if (output_comp_num != GX_DEVICE_COLOR_MAX_COMPONENTS) |
5946 | 975k | num_cmyk_used++; |
5947 | 975k | } |
5948 | 975k | } |
5949 | | /* |
5950 | | * Check if the device supports only CMYK. Otherewise we assume that |
5951 | | * the output device supports spot colors. Note: This algorithm can |
5952 | | * be fooled if the SeparationOrder device parameter is being used by |
5953 | | * the output device device to only select CMYK. |
5954 | | */ |
5955 | 243k | if (num_cmyk_used == 4 && pdev->color_info.num_components == 4 |
5956 | 232k | && pdev->color_info.max_components == 4) { |
5957 | 49.8k | if (valid_blend_cs) { |
5958 | 0 | *blend_cs_state = temp_cs_state; |
5959 | 0 | switch (blend_profile->num_comps) { |
5960 | 0 | case 1: |
5961 | 0 | return PDF14_DeviceGray; |
5962 | 0 | case 3: |
5963 | 0 | return PDF14_DeviceRGB; |
5964 | 0 | case 4: |
5965 | 0 | return PDF14_DeviceCMYK; |
5966 | 0 | } |
5967 | 0 | } |
5968 | 49.8k | return PDF14_DeviceCMYK; |
5969 | 49.8k | } |
5970 | | /* |
5971 | | * Check if we should use the 'custom' PDF 1.4 compositor device. |
5972 | | * This device is only needed for those devices which do not support |
5973 | | * a basic CMYK process color model. |
5974 | | */ |
5975 | 194k | #if CUSTOM_BLENDING_MODE == AUTO_USE_CUSTOM_BLENDING |
5976 | 194k | if (num_cmyk != 4) |
5977 | 0 | return PDF14_DeviceCustom; |
5978 | 194k | #endif |
5979 | | /* |
5980 | | * Otherewise we use a CMYK plus spot colors for blending. |
5981 | | */ |
5982 | 194k | if (valid_blend_cs) |
5983 | 0 | *blend_cs_state = temp_cs_state; |
5984 | 194k | return PDF14_DeviceCMYKspot; |
5985 | 194k | } |
5986 | 3.53M | } |
5987 | | |
5988 | | /* |
5989 | | * the PDF 1.4 transparency spec says that color space for blending |
5990 | | * operations can be based upon either a color space specified in the |
5991 | | * group or a default value based upon the output device. We are |
5992 | | * currently only using a color space based upon the device. |
5993 | | */ |
5994 | | static int |
5995 | | get_pdf14_device_proto(gx_device *dev, |
5996 | | pdf14_device *pdevproto, |
5997 | | gs_gstate *pgs, |
5998 | | const gs_pdf14trans_t *pdf14pct, |
5999 | | bool use_pdf14_accum) |
6000 | 1.14M | { |
6001 | 1.14M | pdf14_blend_cs_t blend_cs_state; |
6002 | 1.14M | pdf14_default_colorspace_t dev_cs = |
6003 | 1.14M | pdf14_determine_default_blend_cs(dev, use_pdf14_accum, |
6004 | 1.14M | &blend_cs_state); |
6005 | 1.14M | bool deep = device_is_deep(dev); |
6006 | 1.14M | int num_spots = pdf14pct->params.num_spot_colors; |
6007 | 1.14M | bool has_tags = device_encodes_tags(dev); |
6008 | | |
6009 | | /* overprint overide */ |
6010 | 1.14M | if (pdf14pct->params.overprint_sim_push && |
6011 | 0 | blend_cs_state == PDF14_BLEND_CS_UNSPECIFIED) { |
6012 | 0 | if (pdf14pct->params.num_spot_colors_int > 0) { |
6013 | 0 | dev_cs = PDF14_DeviceCMYKspot; |
6014 | 0 | num_spots = pdf14pct->params.num_spot_colors_int; |
6015 | 0 | } else |
6016 | 0 | dev_cs = PDF14_DeviceCMYK; |
6017 | 0 | } |
6018 | | |
6019 | 1.14M | switch (dev_cs) { |
6020 | 415k | case PDF14_DeviceGray: |
6021 | 415k | *pdevproto = gs_pdf14_Gray_device; |
6022 | 415k | pdevproto->color_info.max_components = 1 + has_tags; |
6023 | 415k | pdevproto->color_info.num_components = |
6024 | 415k | pdevproto->color_info.max_components + has_tags; |
6025 | 415k | pdevproto->color_info.depth = pdevproto->color_info.num_components * (8<<deep); |
6026 | 415k | pdevproto->color_info.max_gray = deep ? 65535 : 255; |
6027 | 415k | pdevproto->color_info.gray_index = 0; /* Avoid halftoning */ |
6028 | 415k | pdevproto->color_info.dither_grays = deep ? 65536 : 256; |
6029 | 415k | pdevproto->sep_device = false; |
6030 | 415k | break; |
6031 | 652k | case PDF14_DeviceRGB: |
6032 | 652k | *pdevproto = gs_pdf14_RGB_device; |
6033 | 652k | pdevproto->color_info.max_components += has_tags; |
6034 | 652k | pdevproto->color_info.num_components += has_tags; |
6035 | 652k | pdevproto->color_info.depth = pdevproto->color_info.num_components * (8<<deep); |
6036 | 652k | pdevproto->color_info.max_gray = deep ? 65535 : 255; |
6037 | 652k | pdevproto->color_info.dither_grays = deep ? 65536 : 256; |
6038 | 652k | pdevproto->sep_device = false; |
6039 | 652k | break; |
6040 | 2.59k | case PDF14_DeviceCMYK: |
6041 | 2.59k | *pdevproto = gs_pdf14_CMYK_device; |
6042 | 2.59k | pdevproto->color_info.max_components += has_tags; |
6043 | 2.59k | pdevproto->color_info.num_components += has_tags; |
6044 | 2.59k | pdevproto->color_info.depth = pdevproto->color_info.num_components * (8<<deep); |
6045 | 2.59k | pdevproto->color_info.max_gray = deep ? 65535 : 255; |
6046 | 2.59k | pdevproto->color_info.dither_grays = deep ? 65536 : 256; |
6047 | 2.59k | pdevproto->sep_device = false; |
6048 | 2.59k | break; |
6049 | 70.7k | case PDF14_DeviceCMYKspot: |
6050 | 70.7k | *pdevproto = gs_pdf14_CMYKspot_device; |
6051 | | /* Need to figure out how we want to handle the device profile |
6052 | | for this case */ |
6053 | | /* |
6054 | | * The number of components for the PDF14 device is the sum |
6055 | | * of the process components and the number of spot colors |
6056 | | * for the page. |
6057 | | */ |
6058 | 70.7k | if (num_spots >= 0) { |
6059 | 70.7k | pdevproto->color_info.num_components = |
6060 | 70.7k | pdevproto->devn_params.num_std_colorant_names + num_spots + has_tags; |
6061 | 70.7k | if (pdevproto->color_info.num_components > GS_CLIENT_COLOR_MAX_COMPONENTS) |
6062 | 0 | pdevproto->color_info.num_components = GS_CLIENT_COLOR_MAX_COMPONENTS; |
6063 | 70.7k | pdevproto->color_info.depth = |
6064 | 70.7k | pdevproto->color_info.num_components * (8<<deep); |
6065 | 70.7k | pdevproto->sep_device = true; |
6066 | 70.7k | } |
6067 | 0 | else |
6068 | 0 | { |
6069 | 0 | pdevproto->color_info.max_components += has_tags; |
6070 | 0 | pdevproto->color_info.num_components += has_tags; |
6071 | 0 | pdevproto->color_info.depth = pdevproto->color_info.num_components * (8<<deep); |
6072 | 0 | } |
6073 | 70.7k | break; |
6074 | 0 | case PDF14_DeviceRGBspot: |
6075 | 0 | *pdevproto = gs_pdf14_RGBspot_device; |
6076 | | /* Need to figure out how we want to handle the device profile |
6077 | | for this case */ |
6078 | | /* |
6079 | | * The number of components for the PDF14 device is the sum |
6080 | | * of the process components and the number of spot colors |
6081 | | * for the page. |
6082 | | */ |
6083 | 0 | if (num_spots >= 0) { |
6084 | 0 | pdevproto->color_info.num_components = |
6085 | 0 | pdevproto->devn_params.num_std_colorant_names + num_spots + has_tags; |
6086 | 0 | if (pdevproto->color_info.num_components > GS_CLIENT_COLOR_MAX_COMPONENTS) |
6087 | 0 | pdevproto->color_info.num_components = GS_CLIENT_COLOR_MAX_COMPONENTS; |
6088 | 0 | pdevproto->color_info.depth = |
6089 | 0 | pdevproto->color_info.num_components * (8 << deep); |
6090 | 0 | pdevproto->sep_device = true; |
6091 | 0 | } |
6092 | 0 | else |
6093 | 0 | { |
6094 | 0 | pdevproto->color_info.max_components += has_tags; |
6095 | 0 | pdevproto->color_info.num_components += has_tags; |
6096 | 0 | pdevproto->color_info.depth = pdevproto->color_info.num_components * (8<<deep); |
6097 | 0 | } |
6098 | 0 | break; |
6099 | 0 | case PDF14_DeviceCustom: |
6100 | | /* |
6101 | | * We are using the output device's process color model. The |
6102 | | * color_info for the PDF 1.4 compositing device needs to match |
6103 | | * the output device. |
6104 | | */ |
6105 | 0 | *pdevproto = gs_pdf14_custom_device; |
6106 | 0 | pdevproto->color_info = dev->color_info; |
6107 | | /* The pdf14 device has to be 8 (or 16) bit continuous tone. Force it */ |
6108 | 0 | pdevproto->color_info.depth = |
6109 | 0 | pdevproto->color_info.num_components * (8<<deep); |
6110 | 0 | pdevproto->color_info.max_gray = deep ? 65535 : 255; |
6111 | 0 | pdevproto->color_info.max_color = deep ? 65535 : 255; |
6112 | 0 | pdevproto->color_info.dither_grays = deep ? 65536 : 256; |
6113 | 0 | pdevproto->color_info.dither_colors = deep ? 65536 : 256; |
6114 | 0 | break; |
6115 | 0 | default: /* Should not occur */ |
6116 | 0 | return_error(gs_error_rangecheck); |
6117 | 1.14M | } |
6118 | 1.14M | pdevproto->initialize_device_procs((gx_device *)pdevproto); |
6119 | 1.14M | pdevproto->blend_cs_state = blend_cs_state; |
6120 | 1.14M | pdevproto->overprint_sim = pdf14pct->params.overprint_sim_push; |
6121 | 1.14M | return 0; |
6122 | 1.14M | } |
6123 | | |
6124 | | /* When playing back the clist, we need to know if the buffer device is compatible */ |
6125 | | /* with the pdf14 compositor that was used when writing the clist. Colorspace and */ |
6126 | | /* depth are critical since these must match when reading back colors. */ |
6127 | | bool |
6128 | | pdf14_ok_to_optimize(gx_device *dev) |
6129 | 2.38M | { |
6130 | 2.38M | pdf14_blend_cs_t blend_cs_state; |
6131 | 2.38M | pdf14_default_colorspace_t pdf14_cs = |
6132 | 2.38M | pdf14_determine_default_blend_cs(dev, false, &blend_cs_state); |
6133 | 2.38M | gsicc_colorbuffer_t dev_icc_cs; |
6134 | 2.38M | bool ok = false; |
6135 | 2.38M | int tag_depth = device_encodes_tags(dev) ? 8 : 0; |
6136 | 2.38M | cmm_dev_profile_t *dev_profile; |
6137 | 2.38M | int code = dev_proc(dev, get_profile)(dev, &dev_profile); |
6138 | 2.38M | bool deep = device_is_deep(dev); |
6139 | | |
6140 | 2.38M | if (code < 0) |
6141 | 0 | return false; |
6142 | | |
6143 | 2.38M | check_device_compatible_encoding(dev); |
6144 | | |
6145 | 2.38M | if (dev->color_info.separable_and_linear != GX_CINFO_SEP_LIN_STANDARD) |
6146 | 971k | return false; |
6147 | | |
6148 | 1.40M | dev_icc_cs = dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]->data_cs; |
6149 | | /* If the outputprofile is not "standard" then colors converted to device color */ |
6150 | | /* during clist writing won't match the colors written for the pdf14 clist dev */ |
6151 | 1.40M | if (!(dev_icc_cs == gsGRAY || dev_icc_cs == gsRGB || dev_icc_cs == gsCMYK)) |
6152 | 0 | return false; /* can't handle funky output profiles */ |
6153 | | |
6154 | 1.40M | switch (pdf14_cs) { |
6155 | 385k | case PDF14_DeviceGray: |
6156 | 385k | ok = dev->color_info.max_gray == (deep ? 65535 : 255) && dev->color_info.depth == (8<<deep) + tag_depth; |
6157 | 385k | break; |
6158 | 901k | case PDF14_DeviceRGB: |
6159 | 901k | ok = dev->color_info.max_color == (deep ? 65535: 255) && dev->color_info.depth == (24<<deep) + tag_depth; |
6160 | 901k | break; |
6161 | 0 | case PDF14_DeviceCMYK: |
6162 | 0 | ok = dev->color_info.max_color == (deep ? 65535 : 255) && dev->color_info.depth == (32<<deep) + tag_depth; |
6163 | 0 | break; |
6164 | 122k | case PDF14_DeviceCMYKspot: |
6165 | 122k | ok = false; /* punt for this case */ |
6166 | 122k | break; |
6167 | 0 | case PDF14_DeviceRGBspot: |
6168 | 0 | ok = false; /* punt for this case */ |
6169 | 0 | break; |
6170 | 0 | case PDF14_DeviceCustom: |
6171 | | /* |
6172 | | * We are using the output device's process color model. The |
6173 | | * color_info for the PDF 1.4 compositing device needs to match |
6174 | | * the output device, but it may not have been contone. |
6175 | | */ |
6176 | 0 | ok = dev->color_info.depth == dev->color_info.num_components * (8<<deep) + tag_depth; |
6177 | 0 | break; |
6178 | 0 | default: /* Should not occur */ |
6179 | 0 | ok = false; |
6180 | 1.40M | } |
6181 | 1.40M | return ok; |
6182 | 1.40M | } |
6183 | | |
6184 | | /* |
6185 | | * Recreate the PDF 1.4 compositor device. Once created, the PDF 1.4 |
6186 | | * compositor device is never removed. (We do not have a remove compositor |
6187 | | * method.) However it is no-op'ed when the PDF 1.4 device is popped. This |
6188 | | * routine will re-enable the compositor if the PDF 1.4 device is pushed |
6189 | | * again. |
6190 | | */ |
6191 | | static int |
6192 | | pdf14_recreate_device(gs_memory_t *mem, gs_gstate * pgs, |
6193 | | gx_device * dev, const gs_pdf14trans_t * pdf14pct) |
6194 | 0 | { |
6195 | 0 | pdf14_device * pdev = (pdf14_device *)dev; |
6196 | 0 | gx_device * target = pdev->target; |
6197 | 0 | pdf14_device dev_proto; |
6198 | 0 | bool has_tags = device_encodes_tags(dev); |
6199 | 0 | int code; |
6200 | 0 | bool deep = device_is_deep(dev); |
6201 | |
|
6202 | 0 | if_debug0m('v', dev->memory, "[v]pdf14_recreate_device\n"); |
6203 | | |
6204 | | /* |
6205 | | * We will not use the entire prototype device but we will set the |
6206 | | * color related info and the device procs to match the prototype. |
6207 | | */ |
6208 | 0 | code = get_pdf14_device_proto(target, &dev_proto, pgs, |
6209 | 0 | pdf14pct, false); |
6210 | 0 | if (code < 0) |
6211 | 0 | return code; |
6212 | 0 | pdev->color_info = dev_proto.color_info; |
6213 | 0 | pdev->pad = target->pad; |
6214 | 0 | pdev->log2_align_mod = target->log2_align_mod; |
6215 | | |
6216 | | /* The prototype has the color setup without tags. If we are |
6217 | | * using tags, then we need to extend num_components and depth. |
6218 | | */ |
6219 | 0 | if (has_tags) { |
6220 | 0 | pdev->color_info.num_components++; |
6221 | 0 | pdev->color_info.depth = pdev->color_info.num_components * (deep ? 16 : 8); |
6222 | 0 | } |
6223 | |
|
6224 | 0 | if (pdf14pct->params.overprint_sim_push && pdf14pct->params.num_spot_colors_int > 0 && target->num_planar_planes == 0) |
6225 | 0 | pdev->num_planar_planes = dev->color_info.num_components + pdf14pct->params.num_spot_colors_int; |
6226 | 0 | else |
6227 | 0 | pdev->num_planar_planes = target->num_planar_planes; |
6228 | 0 | pdev->interpolate_threshold = dev_proc(target, dev_spec_op)(target, gxdso_interpolate_threshold, NULL, 0); |
6229 | |
|
6230 | 0 | if (dev_proto.initialize_device_procs != NULL) |
6231 | 0 | dev_proto.initialize_device_procs((gx_device *)&dev_proto); |
6232 | 0 | pdev->procs = dev_proto.procs; |
6233 | 0 | if (deep) { |
6234 | 0 | set_dev_proc(pdev, encode_color, pdf14_encode_color16); |
6235 | 0 | set_dev_proc(pdev, decode_color, pdf14_decode_color16); |
6236 | 0 | } |
6237 | 0 | if (has_tags) { |
6238 | 0 | set_dev_proc(pdev, encode_color, deep ? pdf14_encode_color16_tag : pdf14_encode_color_tag); |
6239 | 0 | } |
6240 | 0 | pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN_STANDARD; |
6241 | 0 | gx_device_fill_in_procs((gx_device *)pdev); |
6242 | 0 | pdev->save_get_cmap_procs = pgs->get_cmap_procs; |
6243 | 0 | pgs->get_cmap_procs = pdf14_get_cmap_procs; |
6244 | 0 | gx_set_cmap_procs(pgs, (gx_device *)pdev); |
6245 | 0 | check_device_separable(dev); |
6246 | 0 | return dev_proc(pdev, open_device)(dev); |
6247 | 0 | } |
6248 | | |
6249 | | /* |
6250 | | * Implement the various operations that can be specified via the PDF 1.4 |
6251 | | * create compositor request. |
6252 | | */ |
6253 | | static int |
6254 | | gx_update_pdf14_compositor(gx_device * pdev, gs_gstate * pgs, |
6255 | | const gs_pdf14trans_t * pdf14pct, gs_memory_t * mem ) |
6256 | 21.6M | { |
6257 | 21.6M | pdf14_device *p14dev = (pdf14_device *)pdev; |
6258 | 21.6M | gs_pdf14trans_params_t params = pdf14pct->params; |
6259 | 21.6M | int code = 0; |
6260 | | |
6261 | 21.6M | params.idle = pdf14pct->idle; |
6262 | 21.6M | switch (params.pdf14_op) { |
6263 | 0 | default: /* Should not occur. */ |
6264 | 0 | break; |
6265 | 11.8k | case PDF14_PUSH_DEVICE: |
6266 | 11.8k | if (!(params.is_pattern)) { |
6267 | 0 | p14dev->blend_mode = 0; |
6268 | 0 | p14dev->opacity = p14dev->shape = 0.0; |
6269 | 0 | pdf14_recreate_device(mem, pgs, pdev, pdf14pct); |
6270 | 0 | } |
6271 | 11.8k | break; |
6272 | 0 | case PDF14_ABORT_DEVICE: |
6273 | | /* Something has gone very wrong. Let transparency device clean up |
6274 | | what ever it has allocated and then we are shutting it down */ |
6275 | 0 | code = gx_abort_trans_device(pgs, pdev); |
6276 | 0 | if (p14dev->free_devicen) { |
6277 | 0 | devn_free_params(pdev); |
6278 | 0 | } |
6279 | 0 | pdf14_disable_device(pdev); |
6280 | 0 | pdf14_close(pdev); |
6281 | 0 | break; |
6282 | 1.14M | case PDF14_POP_DEVICE: |
6283 | 1.14M | if (!(params.is_pattern)) { |
6284 | 1.13M | if_debug0m('v', pdev->memory, |
6285 | 1.13M | "[v]gx_update_pdf14_compositor(PDF14_POP_DEVICE)\n"); |
6286 | 1.13M | pgs->get_cmap_procs = p14dev->save_get_cmap_procs; |
6287 | 1.13M | gx_set_cmap_procs(pgs, p14dev->target); |
6288 | | /* Send image out raster data to output device */ |
6289 | 1.13M | { |
6290 | | /* Make a copy so we can change the ROP */ |
6291 | 1.13M | gs_gstate new_pgs = *pgs; |
6292 | | |
6293 | | /* We don't use the gs_gstate log_op since this is for the */ |
6294 | | /* clist playback. Putting the image (band in the case of the */ |
6295 | | /* clist) only needs to use the default ROP to copy the data */ |
6296 | 1.13M | new_pgs.log_op = rop3_default; |
6297 | 1.13M | code = p14dev->pdf14_procs->put_image(pdev, &new_pgs, p14dev->target); |
6298 | 1.13M | } |
6299 | | /* Before we disable the device release any deviceN structures. |
6300 | | free_devicen is set if the pdf14 device had inherited its |
6301 | | deviceN parameters from the target clist device. In this |
6302 | | case they should not be freed */ |
6303 | 1.13M | if (p14dev->free_devicen) { |
6304 | 1.12M | gs_devn_params *devn_params = dev_proc(pdev, ret_devn_params)(pdev); |
6305 | 1.12M | if (devn_params) { |
6306 | 1.12M | gxdso_spot_info si; |
6307 | 1.12M | si.params = devn_params; |
6308 | 1.12M | si.equiv = &p14dev->op_pequiv_cmyk_colors; |
6309 | 1.12M | (void)dev_proc(p14dev->target, dev_spec_op)(p14dev->target, gxdso_update_spots, &si, sizeof(si)); |
6310 | 1.12M | } |
6311 | 1.12M | devn_free_params(pdev); |
6312 | 1.12M | } |
6313 | 1.13M | pdf14_disable_device(pdev); |
6314 | 1.13M | pdf14_close(pdev); |
6315 | 1.13M | } |
6316 | 1.14M | break; |
6317 | 436k | case PDF14_BEGIN_TRANS_PAGE_GROUP: |
6318 | 2.28M | case PDF14_BEGIN_TRANS_GROUP: |
6319 | 2.28M | if (p14dev->smask_constructed || p14dev->depth_within_smask) |
6320 | 337k | p14dev->depth_within_smask++; |
6321 | 2.28M | p14dev->smask_constructed = 0; |
6322 | 2.28M | code = gx_begin_transparency_group(pgs, pdev, ¶ms); |
6323 | 2.28M | break; |
6324 | 1.78M | case PDF14_END_TRANS_GROUP: |
6325 | 1.78M | code = gx_end_transparency_group(pgs, pdev); |
6326 | 1.78M | if (p14dev->depth_within_smask) |
6327 | 337k | p14dev->depth_within_smask--; |
6328 | 1.78M | break; |
6329 | 166 | case PDF14_BEGIN_TRANS_TEXT_GROUP: |
6330 | 166 | if (p14dev->text_group == PDF14_TEXTGROUP_BT_PUSHED) { |
6331 | 0 | p14dev->text_group = PDF14_TEXTGROUP_MISSING_ET; |
6332 | 0 | emprintf(p14dev->memory, "Warning: Text group pushed but no ET found\n"); |
6333 | 0 | } else |
6334 | 166 | p14dev->text_group = PDF14_TEXTGROUP_BT_NOT_PUSHED; |
6335 | 166 | break; |
6336 | 503k | case PDF14_END_TRANS_TEXT_GROUP: |
6337 | 503k | if (p14dev->text_group == PDF14_TEXTGROUP_BT_PUSHED) |
6338 | 503k | code = gx_end_transparency_group(pgs, pdev); |
6339 | 503k | p14dev->text_group = PDF14_TEXTGROUP_NO_BT; /* Hit ET */ |
6340 | 503k | break; |
6341 | 4.23M | case PDF14_BEGIN_TRANS_MASK: |
6342 | 4.23M | code = gx_begin_transparency_mask(pgs, pdev, ¶ms); |
6343 | 4.23M | if (code >= 0 && params.subtype != TRANSPARENCY_MASK_None) |
6344 | 433k | p14dev->in_smask_construction++; |
6345 | 4.23M | break; |
6346 | 433k | case PDF14_END_TRANS_MASK: |
6347 | 433k | code = gx_end_transparency_mask(pgs, pdev, ¶ms); |
6348 | 433k | if (code >= 0) { |
6349 | 433k | p14dev->in_smask_construction--; |
6350 | 433k | if (p14dev->in_smask_construction < 0) |
6351 | 0 | p14dev->in_smask_construction = 0; |
6352 | 433k | if (p14dev->in_smask_construction == 0) |
6353 | 433k | p14dev->smask_constructed = 1; |
6354 | 433k | } |
6355 | 433k | break; |
6356 | 8.26M | case PDF14_SET_BLEND_PARAMS: |
6357 | 8.26M | pdf14_set_params(pgs, pdev, &pdf14pct->params); |
6358 | 8.26M | break; |
6359 | 0 | case PDF14_PUSH_TRANS_STATE: |
6360 | 0 | code = gx_push_transparency_state(pgs, pdev); |
6361 | 0 | break; |
6362 | 3.03M | case PDF14_POP_TRANS_STATE: |
6363 | 3.03M | code = gx_pop_transparency_state(pgs, pdev); |
6364 | 3.03M | break; |
6365 | 4.26k | case PDF14_PUSH_SMASK_COLOR: |
6366 | 4.26k | code = pdf14_increment_smask_color(pgs, pdev); |
6367 | 4.26k | break; |
6368 | 4.26k | case PDF14_POP_SMASK_COLOR: |
6369 | 4.26k | code = pdf14_decrement_smask_color(pgs, pdev); |
6370 | 4.26k | break; |
6371 | 21.6M | } |
6372 | 21.6M | return code; |
6373 | 21.6M | } |
6374 | | |
6375 | | /* |
6376 | | * The PDF 1.4 compositor is never removed. (We do not have a 'remove |
6377 | | * compositor' method. However the compositor is disabled when we are not |
6378 | | * doing a page which uses PDF 1.4 transparency. This routine is only active |
6379 | | * when the PDF 1.4 compositor is 'disabled'. It checks for reenabling the |
6380 | | * PDF 1.4 compositor. Otherwise it simply passes create compositor requests |
6381 | | * to the target. |
6382 | | */ |
6383 | | static int |
6384 | | pdf14_forward_composite(gx_device * dev, gx_device * * pcdev, |
6385 | | const gs_composite_t * pct, gs_gstate * pgs, |
6386 | | gs_memory_t * mem, gx_device *cdev) |
6387 | 1.38k | { |
6388 | 1.38k | pdf14_device *pdev = (pdf14_device *)dev; |
6389 | 1.38k | gx_device * tdev = pdev->target; |
6390 | 1.38k | int code; |
6391 | | |
6392 | 1.38k | *pcdev = dev; |
6393 | 1.38k | if (gs_is_pdf14trans_compositor(pct)) { |
6394 | 0 | const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct; |
6395 | |
|
6396 | 0 | if (pdf14pct->params.pdf14_op == PDF14_PUSH_DEVICE) |
6397 | 0 | return gx_update_pdf14_compositor(dev, pgs, pdf14pct, mem); |
6398 | 0 | return 0; |
6399 | 0 | } |
6400 | 1.38k | code = dev_proc(tdev, composite)(tdev, pcdev, pct, pgs, mem, cdev); |
6401 | 1.38k | if (code == 1) { |
6402 | | /* We have created a new compositor that wrapped tdev. This means |
6403 | | * that our target should be updated to point to that. */ |
6404 | 0 | gx_device_set_target((gx_device_forward *)pdev, *pcdev); |
6405 | 0 | code = 0; /* We have not created a new compositor that wrapped dev. */ |
6406 | 0 | } |
6407 | 1.38k | return code; |
6408 | 1.38k | } |
6409 | | |
6410 | | /* |
6411 | | * The PDF 1.4 compositor can be handled directly, so just set *pcdev = dev |
6412 | | * and return. Since the gs_pdf14_device only supports the high-level routines |
6413 | | * of the interface, don't bother trying to handle any other compositor. |
6414 | | */ |
6415 | | static int |
6416 | | pdf14_composite(gx_device * dev, gx_device * * pcdev, |
6417 | | const gs_composite_t * pct, gs_gstate * pgs, |
6418 | | gs_memory_t * mem, gx_device *cdev) |
6419 | 100M | { |
6420 | 100M | pdf14_device *p14dev = (pdf14_device *)dev; |
6421 | 100M | if (gs_is_pdf14trans_compositor(pct)) { |
6422 | 21.6M | const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct; |
6423 | 21.6M | *pcdev = dev; |
6424 | | /* cdev, may be the clist reader device which may contain information that |
6425 | | we will need related to the ICC color spaces that define transparency |
6426 | | groups. We want this propogated through all the pdf14 functions. Store |
6427 | | a pointer to it in the pdf14 device */ |
6428 | 21.6M | p14dev->pclist_device = cdev; |
6429 | 21.6M | return gx_update_pdf14_compositor(dev, pgs, pdf14pct, mem); |
6430 | 78.7M | } else if (gs_is_overprint_compositor(pct)) { |
6431 | | /* If we had an overprint compositer action, then the |
6432 | | color components that were drawn should be updated. |
6433 | | The overprint compositor logic and its interactions |
6434 | | with the clist is a little odd as it passes uninitialized |
6435 | | values around a fair amount. Hence the forced assignement here. |
6436 | | See gx_spot_colors_set_overprint in gscspace for issues... */ |
6437 | 78.7M | const gs_overprint_t * op_pct = (const gs_overprint_t *) pct; |
6438 | 78.7M | gx_color_index drawn_comps; |
6439 | 78.7M | PDF14_OP_FS_STATE curr_state = p14dev->op_state; |
6440 | | |
6441 | 78.7M | p14dev->op_state = op_pct->params.op_state; |
6442 | 78.7M | if (p14dev->op_state == PDF14_OP_STATE_NONE) { |
6443 | 39.3M | if (op_pct->params.retain_any_comps) { |
6444 | 30.3k | drawn_comps = op_pct->params.drawn_comps; |
6445 | 39.3M | } else { |
6446 | | /* Draw everything. If this parameter was not set, clist does |
6447 | | not fill it in. */ |
6448 | 39.3M | drawn_comps = ((gx_color_index)1 << (p14dev->color_info.num_components)) - (gx_color_index)1; |
6449 | 39.3M | } |
6450 | | |
6451 | 39.3M | if (op_pct->params.is_fill_color) { |
6452 | 22.0M | p14dev->effective_overprint_mode = op_pct->params.effective_opm; |
6453 | 22.0M | p14dev->drawn_comps_fill = drawn_comps; |
6454 | 22.0M | } else { |
6455 | 17.3M | p14dev->stroke_effective_op_mode = op_pct->params.effective_opm; |
6456 | 17.3M | p14dev->drawn_comps_stroke = drawn_comps; |
6457 | 17.3M | } |
6458 | | /* We restore the NONE states as that is used just to force |
6459 | | overprint settings in the overprint compositor communication */ |
6460 | 39.3M | p14dev->op_state = curr_state; |
6461 | 39.3M | } |
6462 | 78.7M | *pcdev = dev; |
6463 | 78.7M | return 0; |
6464 | 78.7M | } else |
6465 | 0 | return gx_no_composite(dev, pcdev, pct, pgs, mem, cdev); |
6466 | 100M | } |
6467 | | |
6468 | | static int |
6469 | | pdf14_push_text_group(gx_device *dev, gs_gstate *pgs, |
6470 | | gs_blend_mode_t blend_mode, float opacity, |
6471 | | float shape, bool is_clist) |
6472 | 2.96k | { |
6473 | 2.96k | int code; |
6474 | 2.96k | gs_transparency_group_params_t params = { 0 }; |
6475 | 2.96k | gs_rect bbox = { 0 }; /* Bounding box is set by parent */ |
6476 | 2.96k | pdf14_clist_device * pdev = (pdf14_clist_device *)dev; |
6477 | 2.96k | float alpha = pgs->fillconstantalpha; |
6478 | | |
6479 | | /* Push a non-isolated knock-out group making sure the opacity and blend |
6480 | | mode are correct */ |
6481 | 2.96k | params.Isolated = false; |
6482 | 2.96k | params.Knockout = true; |
6483 | 2.96k | params.page_group = false; |
6484 | 2.96k | params.text_group = PDF14_TEXTGROUP_BT_PUSHED; |
6485 | 2.96k | params.group_opacity = 1.0; |
6486 | 2.96k | params.group_shape = 1.0; |
6487 | | |
6488 | 2.96k | gs_setfillconstantalpha(pgs, 1.0); |
6489 | 2.96k | gs_setblendmode(pgs, BLEND_MODE_Normal); |
6490 | | |
6491 | 2.96k | if (is_clist) { |
6492 | 2.96k | code = pdf14_clist_update_params(pdev, pgs, false, NULL); |
6493 | 2.96k | if (code < 0) |
6494 | 0 | return code; |
6495 | 2.96k | } |
6496 | | |
6497 | 2.96k | code = gs_begin_transparency_group(pgs, ¶ms, &bbox, PDF14_BEGIN_TRANS_GROUP); |
6498 | 2.96k | gs_setfillconstantalpha(pgs, alpha); |
6499 | 2.96k | gs_setblendmode(pgs, blend_mode); |
6500 | 2.96k | if (code < 0) |
6501 | 0 | return code; |
6502 | | |
6503 | 2.96k | if (is_clist) { |
6504 | 2.96k | code = pdf14_clist_update_params(pdev, pgs, false, NULL); |
6505 | 2.96k | } |
6506 | 2.96k | return code; |
6507 | 2.96k | } |
6508 | | |
6509 | | static int |
6510 | | pdf14_text_begin(gx_device * dev, gs_gstate * pgs, |
6511 | | const gs_text_params_t * text, gs_font * font, |
6512 | | const gx_clip_path * pcpath, |
6513 | | gs_text_enum_t ** ppenum) |
6514 | 392 | { |
6515 | 392 | int code; |
6516 | 392 | gs_text_enum_t *penum; |
6517 | 392 | gs_blend_mode_t blend_mode = gs_currentblendmode(pgs); |
6518 | 392 | float opacity = pgs->fillconstantalpha; |
6519 | 392 | float shape = 1.0; |
6520 | 392 | bool blend_issue = !(blend_mode == BLEND_MODE_Normal || blend_mode == BLEND_MODE_Compatible || blend_mode == BLEND_MODE_CompatibleOverprint); |
6521 | 392 | pdf14_device *pdev = (pdf14_device*)dev; |
6522 | 392 | bool draw = !(text->operation & TEXT_DO_NONE); |
6523 | 392 | uint text_mode = gs_currenttextrenderingmode(pgs); |
6524 | 392 | bool text_stroke = (text_mode == 1 || text_mode == 2 || text_mode == 5 || text_mode == 6); |
6525 | 392 | bool text_fill = (text_mode == 0 || text_mode == 2 || text_mode == 4 || text_mode == 6); |
6526 | | |
6527 | 392 | code = pdf14_initialize_ctx(dev, pgs); |
6528 | 392 | if (code < 0) |
6529 | 0 | return code; |
6530 | | |
6531 | 392 | if_debug0m('v', pgs->memory, "[v]pdf14_text_begin\n"); |
6532 | 392 | pdf14_set_marking_params(dev, pgs); |
6533 | 392 | code = gx_default_text_begin(dev, pgs, text, font, pcpath, &penum); |
6534 | 392 | if (code < 0) |
6535 | 0 | return code; |
6536 | | |
6537 | | /* We may need to push a non-isolated transparency group if the following |
6538 | | is true. |
6539 | | 1) We are not currently in one that we pushed for text and we are in |
6540 | | a BT/ET pair. This is determined by looking at the pdf14 text_group. |
6541 | | 2) The blend mode is not Normal or the opacity is not 1.0 |
6542 | | 3) Text knockout is set to true |
6543 | | 4) We are actually doing a text drawing |
6544 | | |
6545 | | Special note: If text-knockout is set to false while we are within a |
6546 | | BT ET pair, we should pop the group. I need to create a test file for |
6547 | | this case. */ |
6548 | | |
6549 | | /* Catch case where we already pushed a group and are trying to push another one. |
6550 | | In that case, we will pop the current one first, as we don't want to be left |
6551 | | with it. Note that if we have a BT and no other BTs or ETs then this issue |
6552 | | will not be caught until we do the put_image and notice that the stack is not |
6553 | | empty. */ |
6554 | 392 | if (pdev->text_group == PDF14_TEXTGROUP_MISSING_ET) { |
6555 | 0 | code = gs_end_transparency_group(pgs); |
6556 | 0 | if (code < 0) |
6557 | 0 | return code; |
6558 | 0 | pdev->text_group = PDF14_TEXTGROUP_BT_NOT_PUSHED; |
6559 | 0 | } |
6560 | | |
6561 | 392 | if (gs_currenttextknockout(pgs) && (blend_issue || |
6562 | 391 | (pgs->fillconstantalpha != 1.0 && text_fill) || |
6563 | 391 | (pgs->strokeconstantalpha != 1.0 && text_stroke)) && |
6564 | 1 | text_mode != 3 && /* don't bother with invisible text */ |
6565 | 1 | pdev->text_group == PDF14_TEXTGROUP_BT_NOT_PUSHED) |
6566 | 1 | if (draw) { |
6567 | 1 | code = pdf14_push_text_group(dev, pgs, blend_mode, opacity, shape, |
6568 | 1 | false); |
6569 | 1 | } |
6570 | 392 | *ppenum = (gs_text_enum_t *)penum; |
6571 | 392 | return code; |
6572 | 392 | } |
6573 | | |
6574 | | static int |
6575 | | pdf14_initialize_device(gx_device *new_dev) |
6576 | 1.14M | { |
6577 | 1.14M | pdf14_device *pdev = (pdf14_device*)new_dev; |
6578 | | |
6579 | 1.14M | pdev->ctx = NULL; |
6580 | 1.14M | pdev->color_model_stack = NULL; |
6581 | 1.14M | pdev->smaskcolor = NULL; |
6582 | | |
6583 | 1.14M | return 0; |
6584 | 1.14M | } |
6585 | | |
6586 | | /* |
6587 | | * Implement copy_mono by filling lots of small rectangles. |
6588 | | */ |
6589 | | static int |
6590 | | pdf14_copy_mono(gx_device * dev, |
6591 | | const byte * base, int sourcex, int sraster, gx_bitmap_id id, |
6592 | | int x, int y, int w, int h, gx_color_index zero, gx_color_index one) |
6593 | 12.9M | { |
6594 | 12.9M | const byte *sptr; |
6595 | 12.9M | const byte *line; |
6596 | 12.9M | int sbit, first_bit; |
6597 | 12.9M | int code, sbyte, bit, count; |
6598 | 12.9M | int run_length, startx, current_bit, bit_value; |
6599 | 12.9M | gx_color_index current_color; |
6600 | | |
6601 | 12.9M | fit_copy(dev, base, sourcex, sraster, id, x, y, w, h); |
6602 | 12.9M | line = base + (sourcex >> 3); |
6603 | 12.9M | sbit = sourcex & 7; |
6604 | 12.9M | first_bit = 7 - sbit; |
6605 | | |
6606 | | /* Loop through the height of the specified area. */ |
6607 | 98.7M | while (h-- > 0) { |
6608 | | /* Set up for the start of each line of the area. */ |
6609 | 85.8M | sptr = line; |
6610 | 85.8M | sbyte = *sptr++; |
6611 | | /* The +1 here is 'sacrificial', we are going to decrement it by 1 immediately in |
6612 | | * the loop below so adding 1 means that we don't fall into the bit == 0 |
6613 | | * case and incorrectly read a new byte from the source. This weirdness is because |
6614 | | * the original code wouold read off the end of the buffer if the number of bits in |
6615 | | * the raster was an exact multiple of 8. If it was also a multiple of the word |
6616 | | * size we might read unallocated memory. Moving the 'sbyte = *sptr++' from the end |
6617 | | * of the loop to the beginning meant we would not read past the end of the buffer |
6618 | | * because we would drop out of the 'do ... while (count-- > 0)' loop before |
6619 | | * reading another byte. |
6620 | | */ |
6621 | 85.8M | bit = first_bit + 1; |
6622 | 85.8M | count = w; |
6623 | 85.8M | run_length = 0; |
6624 | 85.8M | startx = x; |
6625 | 85.8M | current_bit = 0; |
6626 | 85.8M | current_color = zero; |
6627 | | |
6628 | | /* Loop across each pixel of a line. */ |
6629 | 1.24G | do { |
6630 | | /* Move to the next input bit. */ |
6631 | 1.24G | if (bit == 0) { |
6632 | 108M | bit = 7; |
6633 | 108M | sbyte = *sptr++; |
6634 | 108M | } |
6635 | 1.13G | else |
6636 | 1.13G | bit--; |
6637 | 1.24G | bit_value = (sbyte >> bit) & 1; |
6638 | 1.24G | if (bit_value == current_bit) { |
6639 | | /* The value did not change, simply increment our run length */ |
6640 | 1.02G | run_length++; |
6641 | 1.02G | } else { |
6642 | | /* The value changed, fill the current rectangle. */ |
6643 | 214M | if (run_length != 0) { |
6644 | 204M | if (current_color != gx_no_color_index) { |
6645 | 88.4M | code = (*dev_proc(dev, fill_rectangle)) |
6646 | 88.4M | (dev, startx, y, run_length, 1, current_color); |
6647 | 88.4M | if (code < 0) |
6648 | 0 | return code; |
6649 | 88.4M | } |
6650 | 204M | startx += run_length; |
6651 | 204M | } |
6652 | 214M | run_length = 1; |
6653 | 214M | current_color = bit_value ? one : zero; |
6654 | 214M | current_bit = bit_value; |
6655 | 214M | } |
6656 | 1.24G | } while (--count > 0); |
6657 | | /* Fill the last rectangle in the line. */ |
6658 | 85.8M | if (run_length != 0 && current_color != gx_no_color_index) { |
6659 | 38.2M | code = (*dev_proc(dev, fill_rectangle)) |
6660 | 38.2M | (dev, startx, y, run_length, 1, current_color); |
6661 | 38.2M | if (code < 0) |
6662 | 0 | return code; |
6663 | 38.2M | } |
6664 | | /* Move to the next line */ |
6665 | 85.8M | line += sraster; |
6666 | 85.8M | y++; |
6667 | 85.8M | } |
6668 | 12.9M | return 0; |
6669 | 12.9M | } |
6670 | | |
6671 | | /* Added to avoid having to go back and forth between fixed and int |
6672 | | in some of the internal methods used for dealing with tiling |
6673 | | and devn colors */ |
6674 | | static int |
6675 | | pdf14_fill_rectangle_devn(gx_device *dev, int x, int y, int w, int h, |
6676 | | const gx_drawing_color *pdcolor) |
6677 | 2.44k | { |
6678 | 2.44k | pdf14_device *pdev = (pdf14_device *)dev; |
6679 | 2.44k | pdf14_buf *buf; |
6680 | 2.44k | int code; |
6681 | | |
6682 | 2.44k | fit_fill_xywh(dev, x, y, w, h); |
6683 | 2.44k | if (w <= 0 || h <= 0) |
6684 | 0 | return 0; |
6685 | | |
6686 | 2.44k | code = pdf14_initialize_ctx(dev, NULL); |
6687 | 2.44k | if (code < 0) |
6688 | 0 | return code; |
6689 | 2.44k | buf = pdev->ctx->stack; |
6690 | | |
6691 | 2.44k | if (buf->knockout) |
6692 | 0 | return pdf14_mark_fill_rectangle_ko_simple(dev, x, y, w, h, 0, pdcolor, |
6693 | 0 | true); |
6694 | 2.44k | else |
6695 | 2.44k | return pdf14_mark_fill_rectangle(dev, x, y, w, h, 0, pdcolor, true); |
6696 | 2.44k | } |
6697 | | |
6698 | | /* Step through and do rect fills with the devn colors as |
6699 | | we hit each transition in the bitmap. It is possible |
6700 | | that one of the colors is not devn, but is pure and |
6701 | | is set to gx_no_color_index. This type of mix happens |
6702 | | for example from tile_clip_fill_rectangle_hl_color */ |
6703 | | static int |
6704 | | pdf14_copy_mono_devn(gx_device *dev, |
6705 | | const byte *base, int sourcex, int sraster, |
6706 | | int x, int y, int w, int h, const gx_drawing_color *pdcolor0, |
6707 | | const gx_drawing_color *pdcolor1) |
6708 | 668 | { |
6709 | 668 | const byte *sptr; |
6710 | 668 | const byte *line; |
6711 | 668 | int sbit, first_bit; |
6712 | 668 | int code, sbyte, bit, count; |
6713 | 668 | int run_length, startx, current_bit, bit_value; |
6714 | 668 | const gx_drawing_color *current_color; |
6715 | | |
6716 | 668 | if ((x | y) < 0) { |
6717 | 0 | if (x < 0) { |
6718 | 0 | w += x; |
6719 | 0 | sourcex -= x; |
6720 | 0 | x = 0; |
6721 | 0 | } |
6722 | 0 | if (y < 0) { |
6723 | 0 | h += y; |
6724 | 0 | base -= (int)(y * sraster); |
6725 | 0 | y = 0; |
6726 | 0 | } |
6727 | 0 | } |
6728 | 668 | if (w > (dev)->width - x) |
6729 | 0 | w = (dev)->width - x; |
6730 | 668 | if (h > (dev)->height - y) |
6731 | 0 | h = (dev)->height - y; |
6732 | 668 | if (w <= 0 || h <= 0) |
6733 | 0 | return 0; |
6734 | | |
6735 | 668 | line = base + (sourcex >> 3); |
6736 | 668 | sbit = sourcex & 7; |
6737 | 668 | first_bit = 7 - sbit; |
6738 | | |
6739 | | /* Loop through the height of the specified area. */ |
6740 | 2.10k | while (h-- > 0) { |
6741 | | /* Set up for the start of each line of the area. */ |
6742 | 1.43k | sptr = line; |
6743 | 1.43k | sbyte = *sptr++; |
6744 | 1.43k | bit = first_bit; |
6745 | 1.43k | count = w; |
6746 | 1.43k | run_length = 0; |
6747 | 1.43k | startx = x; |
6748 | 1.43k | current_bit = 0; |
6749 | 1.43k | current_color = pdcolor0; |
6750 | | |
6751 | | /* Loop across each pixel of a line. */ |
6752 | 15.6k | do { |
6753 | 15.6k | bit_value = (sbyte >> bit) & 1; |
6754 | 15.6k | if (bit_value == current_bit) { |
6755 | | /* The value did not change, simply increment our run length */ |
6756 | 11.3k | run_length++; |
6757 | 11.3k | } else { |
6758 | | /* The value changed, fill the current rectangle. */ |
6759 | 4.26k | if (run_length != 0) { |
6760 | 3.85k | if (current_color->type != gx_dc_type_pure && |
6761 | 1.82k | current_color->colors.pure != gx_no_color_index) { |
6762 | 1.82k | code = pdf14_fill_rectangle_devn(dev, startx, y, |
6763 | 1.82k | run_length, 1, current_color); |
6764 | 1.82k | if (code < 0) |
6765 | 0 | return code; |
6766 | 1.82k | } |
6767 | 3.85k | startx += run_length; |
6768 | 3.85k | } |
6769 | 4.26k | run_length = 1; |
6770 | 4.26k | current_color = bit_value ? pdcolor1 : pdcolor0; |
6771 | 4.26k | current_bit = bit_value; |
6772 | 4.26k | } |
6773 | | |
6774 | | /* Move to the next input bit. */ |
6775 | 15.6k | if (bit == 0) { |
6776 | 1.40k | bit = 7; |
6777 | 1.40k | sbyte = *sptr++; |
6778 | 1.40k | } else |
6779 | 14.2k | bit--; |
6780 | 15.6k | } while (--count > 0); |
6781 | | |
6782 | | /* Fill the last rectangle in the line. */ |
6783 | 1.43k | if (run_length != 0 && current_color->type != gx_dc_type_pure && |
6784 | 619 | current_color->colors.pure != gx_no_color_index) { |
6785 | 619 | code = pdf14_fill_rectangle_devn(dev, startx, y, |
6786 | 619 | run_length, 1, current_color); |
6787 | 619 | if (code < 0) |
6788 | 0 | return code; |
6789 | 619 | } |
6790 | | /* Move to the next line */ |
6791 | 1.43k | line += sraster; |
6792 | 1.43k | y++; |
6793 | 1.43k | } |
6794 | 668 | return 0; |
6795 | 668 | } |
6796 | | |
6797 | | /* Step through the tiles doing essentially copy_mono but with devn colors */ |
6798 | | static int |
6799 | | pdf14_impl_strip_tile_rectangle_devn(gx_device *dev, const gx_strip_bitmap *tiles, |
6800 | | int x, int y, int w, int h, const gx_drawing_color *pdcolor0, |
6801 | | const gx_drawing_color *pdcolor1, int px, int py) |
6802 | 668 | { /* Fill the rectangle in chunks. */ |
6803 | 668 | int width = tiles->size.x; |
6804 | 668 | int height = tiles->size.y; |
6805 | 668 | int raster = tiles->raster; |
6806 | 668 | int rwidth = tiles->rep_width; |
6807 | 668 | int rheight = tiles->rep_height; |
6808 | 668 | int shift = tiles->shift; |
6809 | | |
6810 | 668 | if (rwidth == 0 || rheight == 0) |
6811 | 0 | return_error(gs_error_unregistered); |
6812 | 668 | fit_fill_xy(dev, x, y, w, h); |
6813 | | |
6814 | 668 | { |
6815 | 668 | int xoff = (shift == 0 ? px : |
6816 | 668 | px + (y + py) / rheight * tiles->rep_shift); |
6817 | 668 | int irx = ((rwidth & (rwidth - 1)) == 0 ? /* power of 2 */ |
6818 | 0 | (x + xoff) & (rwidth - 1) : |
6819 | 668 | (x + xoff) % rwidth); |
6820 | 668 | int ry = ((rheight & (rheight - 1)) == 0 ? /* power of 2 */ |
6821 | 0 | (y + py) & (rheight - 1) : |
6822 | 668 | (y + py) % rheight); |
6823 | 668 | int icw = width - irx; |
6824 | 668 | int ch = height - ry; |
6825 | 668 | byte *row = tiles->data + ry * raster; |
6826 | 668 | int code = 0; |
6827 | | |
6828 | 668 | if (ch >= h) { /* Shallow operation */ |
6829 | 668 | if (icw >= w) { /* Just one (partial) tile to transfer. */ |
6830 | 668 | code = pdf14_copy_mono_devn(dev, row, irx, raster, x, y, |
6831 | 668 | w, h, pdcolor0, pdcolor1); |
6832 | 668 | if (code < 0) |
6833 | 0 | return_error(code); |
6834 | 668 | } else { |
6835 | 0 | int ex = x + w; |
6836 | 0 | int fex = ex - width; |
6837 | 0 | int cx = x + icw; |
6838 | |
|
6839 | 0 | code = pdf14_copy_mono_devn(dev, row, irx, raster, |
6840 | 0 | x, y, icw, h, pdcolor0, pdcolor1); |
6841 | 0 | if (code < 0) |
6842 | 0 | return_error(code); |
6843 | | |
6844 | 0 | while (cx <= fex) { |
6845 | 0 | code = pdf14_copy_mono_devn(dev, row, 0, raster, cx, y, |
6846 | 0 | width, h, pdcolor0, pdcolor1); |
6847 | 0 | if (code < 0) |
6848 | 0 | return_error(code); |
6849 | 0 | cx += width; |
6850 | 0 | } |
6851 | 0 | if (cx < ex) { |
6852 | 0 | code = pdf14_copy_mono_devn(dev, row, 0, raster, cx, y, |
6853 | 0 | ex - cx, h, pdcolor0, pdcolor1); |
6854 | 0 | if (code < 0) |
6855 | 0 | return_error(code); |
6856 | 0 | } |
6857 | 0 | } |
6858 | 668 | } else if (icw >= w && shift == 0) { |
6859 | | /* Narrow operation, no shift */ |
6860 | 0 | int ey = y + h; |
6861 | 0 | int fey = ey - height; |
6862 | 0 | int cy = y + ch; |
6863 | |
|
6864 | 0 | code = pdf14_copy_mono_devn(dev, row, irx, raster, |
6865 | 0 | x, y, w, ch, pdcolor0, pdcolor1); |
6866 | 0 | if (code < 0) |
6867 | 0 | return_error(code); |
6868 | 0 | row = tiles->data; |
6869 | 0 | do { |
6870 | 0 | ch = (cy > fey ? ey - cy : height); |
6871 | 0 | code = pdf14_copy_mono_devn(dev, row, irx, raster, |
6872 | 0 | x, cy, w, ch, pdcolor0, pdcolor1); |
6873 | 0 | if (code < 0) |
6874 | 0 | return_error(code); |
6875 | 0 | } while ((cy += ch) < ey); |
6876 | 0 | } else { |
6877 | | /* Full operation. If shift != 0, some scan lines */ |
6878 | | /* may be narrow. We could test shift == 0 in advance */ |
6879 | | /* and use a slightly faster loop, but right now */ |
6880 | | /* we don't bother. */ |
6881 | 0 | int ex = x + w, ey = y + h; |
6882 | 0 | int fex = ex - width, fey = ey - height; |
6883 | 0 | int cx, cy; |
6884 | |
|
6885 | 0 | for (cy = y;;) { |
6886 | 0 | if (icw >= w) { |
6887 | 0 | code = pdf14_copy_mono_devn(dev, row, irx, raster, |
6888 | 0 | x, cy, w, ch, pdcolor0, pdcolor1); |
6889 | 0 | if (code < 0) |
6890 | 0 | return_error(code); |
6891 | 0 | } else { |
6892 | 0 | code = pdf14_copy_mono_devn(dev, row, irx, raster, |
6893 | 0 | x, cy, icw, ch, pdcolor0, pdcolor1); |
6894 | 0 | if (code < 0) |
6895 | 0 | return_error(code); |
6896 | 0 | cx = x + icw; |
6897 | 0 | while (cx <= fex) { |
6898 | 0 | code = pdf14_copy_mono_devn(dev, row, 0, raster, |
6899 | 0 | cx, cy, width, ch, pdcolor0, pdcolor1); |
6900 | 0 | if (code < 0) |
6901 | 0 | return_error(code); |
6902 | 0 | cx += width; |
6903 | 0 | } |
6904 | 0 | if (cx < ex) { |
6905 | 0 | code = pdf14_copy_mono_devn(dev, row, 0, raster, |
6906 | 0 | cx, cy, ex - cx, ch, pdcolor0, pdcolor1); |
6907 | 0 | if (code < 0) |
6908 | 0 | return_error(code); |
6909 | 0 | } |
6910 | 0 | } |
6911 | 0 | if ((cy += ch) >= ey) |
6912 | 0 | break; |
6913 | 0 | ch = (cy > fey ? ey - cy : height); |
6914 | 0 | if ((irx += shift) >= rwidth) |
6915 | 0 | irx -= rwidth; |
6916 | 0 | icw = width - irx; |
6917 | 0 | row = tiles->data; |
6918 | 0 | } |
6919 | 0 | } |
6920 | 668 | } |
6921 | 668 | return 0; |
6922 | 668 | } |
6923 | | |
6924 | | /* pdf14 device supports devn */ |
6925 | | static int |
6926 | | pdf14_strip_tile_rect_devn(gx_device *dev, const gx_strip_bitmap *tiles, |
6927 | | int x, int y, int w, int h, |
6928 | | const gx_drawing_color *pdcolor0, |
6929 | | const gx_drawing_color *pdcolor1, int px, int py) |
6930 | 668 | { |
6931 | 668 | pdf14_device *pdev = (pdf14_device *)dev; |
6932 | 668 | pdf14_buf *buf; |
6933 | 668 | int num_comp; |
6934 | 668 | int k; |
6935 | 668 | bool same = false; |
6936 | 668 | int code; |
6937 | | |
6938 | 668 | code = pdf14_initialize_ctx(dev, NULL); |
6939 | 668 | if (code < 0) |
6940 | 0 | return code; |
6941 | 668 | buf = pdev->ctx->stack; |
6942 | 668 | num_comp = buf->n_chan - 1; |
6943 | | |
6944 | | /* if color0 is identical to color1, do rect fill */ |
6945 | 668 | if (pdcolor0->type == gx_dc_type_devn && pdcolor1->type == gx_dc_type_devn) { |
6946 | 0 | same = true; |
6947 | 0 | for (k = 0; k < num_comp; k++) { |
6948 | 0 | if (pdcolor0->colors.devn.values[k] != pdcolor1->colors.devn.values[k]) { |
6949 | 0 | same = false; |
6950 | 0 | break; |
6951 | 0 | } |
6952 | 0 | } |
6953 | 0 | } |
6954 | | |
6955 | 668 | if (same) { |
6956 | 0 | code = pdf14_fill_rectangle_devn(dev, x, y, w, h, pdcolor0); |
6957 | 668 | } else { |
6958 | | /* Go through the tile stepping using code stolen from |
6959 | | gx_default_strip_tile_rectangle and call the rect fills |
6960 | | using code stolen from pdf14_copy_mono but using devn |
6961 | | colors */ |
6962 | 668 | code = pdf14_impl_strip_tile_rectangle_devn(dev, tiles, |
6963 | 668 | x, y, w, h, pdcolor0, pdcolor1, px, py); |
6964 | 668 | } |
6965 | 668 | return code; |
6966 | 668 | } |
6967 | | |
6968 | | /* Used in a few odd cases where the target device is planar and we have |
6969 | | a planar tile (pattern) and we are copying it into place here */ |
6970 | | static int |
6971 | | pdf14_copy_planes(gx_device * dev, const byte * data, int data_x, int raster, |
6972 | | gx_bitmap_id id, int x, int y, int w, int h, int plane_height) |
6973 | 4.05k | { |
6974 | 4.05k | pdf14_device *pdev = (pdf14_device *)dev; |
6975 | 4.05k | pdf14_ctx *ctx; |
6976 | 4.05k | pdf14_buf *buf; |
6977 | 4.05k | int xo = x; |
6978 | 4.05k | int yo = y; |
6979 | 4.05k | pdf14_buf fake_tos; |
6980 | 4.05k | int deep; |
6981 | | |
6982 | 4.05k | int code = pdf14_initialize_ctx(dev, NULL); |
6983 | 4.05k | if (code < 0) |
6984 | 0 | return code; |
6985 | | |
6986 | 4.05k | fit_fill_xywh(dev, x, y, w, h); |
6987 | 4.05k | if (w <= 0 || h <= 0) |
6988 | 0 | return 0; |
6989 | | |
6990 | 4.05k | ctx = pdev->ctx; |
6991 | 4.05k | buf = ctx->stack; |
6992 | 4.05k | deep = ctx->deep; |
6993 | | |
6994 | 4.05k | fake_tos.deep = deep; |
6995 | 4.05k | fake_tos.alpha = (uint16_t)(0xffff * pdev->alpha + 0.5); |
6996 | 4.05k | fake_tos.backdrop = NULL; |
6997 | 4.05k | fake_tos.blend_mode = pdev->blend_mode; |
6998 | 4.05k | fake_tos.color_space = buf->color_space; |
6999 | 4.05k | fake_tos.data = (byte *)data + ((data_x - (x - xo))<<deep) - (y - yo) * raster; /* Nasty, cast away of const */ |
7000 | 4.05k | fake_tos.dirty.p.x = x; |
7001 | 4.05k | fake_tos.dirty.p.y = y; |
7002 | 4.05k | fake_tos.dirty.q.x = x + w; |
7003 | 4.05k | fake_tos.dirty.q.y = y + h; |
7004 | 4.05k | fake_tos.has_alpha_g = 0; |
7005 | 4.05k | fake_tos.has_shape = 0; |
7006 | 4.05k | fake_tos.has_tags = 0; |
7007 | 4.05k | fake_tos.idle = false; |
7008 | 4.05k | fake_tos.isolated = false; |
7009 | 4.05k | fake_tos.knockout = false; |
7010 | 4.05k | fake_tos.mask_id = 0; |
7011 | 4.05k | fake_tos.mask_stack = NULL; |
7012 | 4.05k | fake_tos.matte = NULL; |
7013 | 4.05k | fake_tos.matte_num_comps = 0; |
7014 | 4.05k | fake_tos.memory = dev->memory; |
7015 | 4.05k | fake_tos.n_chan = dev->color_info.num_components; |
7016 | 4.05k | fake_tos.n_planes = dev->color_info.num_components; |
7017 | 4.05k | fake_tos.num_spots = 0; |
7018 | 4.05k | fake_tos.group_color_info = NULL; |
7019 | 4.05k | fake_tos.planestride = raster * (size_t)plane_height; |
7020 | 4.05k | fake_tos.rect.p.x = x; |
7021 | 4.05k | fake_tos.rect.p.y = y; |
7022 | 4.05k | fake_tos.rect.q.x = x + w; |
7023 | 4.05k | fake_tos.rect.q.y = y + h; |
7024 | 4.05k | fake_tos.rowstride = raster; |
7025 | 4.05k | fake_tos.saved = NULL; |
7026 | 4.05k | fake_tos.shape = 0xffff; |
7027 | 4.05k | fake_tos.SMask_SubType = TRANSPARENCY_MASK_Alpha; |
7028 | 4.05k | fake_tos.transfer_fn = NULL; |
7029 | 4.05k | pdf14_compose_alphaless_group(&fake_tos, buf, x, x+w, y, y+h, |
7030 | 4.05k | pdev->ctx->memory, dev); |
7031 | 4.05k | return 0; |
7032 | 4.05k | } |
7033 | | |
7034 | | static int |
7035 | | pdf14_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect, |
7036 | | const gs_gstate *pgs, const gx_drawing_color *pdcolor, |
7037 | | const gx_clip_path *pcpath) |
7038 | 6.58M | { |
7039 | 6.58M | pdf14_device *pdev = (pdf14_device *)dev; |
7040 | 6.58M | pdf14_buf* buf; |
7041 | 6.58M | int code; |
7042 | 6.58M | int x = fixed2int(rect->p.x); |
7043 | 6.58M | int y = fixed2int(rect->p.y); |
7044 | 6.58M | int w = fixed2int(rect->q.x) - x; |
7045 | 6.58M | int h = fixed2int(rect->q.y) - y; |
7046 | | |
7047 | 6.58M | fit_fill_xywh(dev, x, y, w, h); |
7048 | 6.58M | if (w <= 0 || h <= 0) |
7049 | 267k | return 0; |
7050 | | |
7051 | 6.31M | code = pdf14_initialize_ctx(dev, pgs); |
7052 | 6.31M | if (code < 0) |
7053 | 0 | return code; |
7054 | 6.31M | buf = pdev->ctx->stack; |
7055 | | |
7056 | 6.31M | if (buf->knockout) |
7057 | 76.5k | return pdf14_mark_fill_rectangle_ko_simple(dev, x, y, w, h, 0, pdcolor, |
7058 | 76.5k | true); |
7059 | 6.23M | else |
7060 | 6.23M | return pdf14_mark_fill_rectangle(dev, x, y, w, h, 0, pdcolor, true); |
7061 | 6.31M | } |
7062 | | |
7063 | | static int |
7064 | | pdf14_fill_rectangle(gx_device * dev, |
7065 | | int x, int y, int w, int h, gx_color_index color) |
7066 | 379M | { |
7067 | 379M | pdf14_device *pdev = (pdf14_device *)dev; |
7068 | 379M | pdf14_buf *buf; |
7069 | 379M | int code; |
7070 | | |
7071 | 379M | fit_fill_xywh(dev, x, y, w, h); |
7072 | 379M | if (w <= 0 || h <= 0) |
7073 | 11.7M | return 0; |
7074 | | |
7075 | 367M | code = pdf14_initialize_ctx(dev, NULL); |
7076 | 367M | if (code < 0) |
7077 | 0 | return code; |
7078 | | |
7079 | 367M | buf = pdev->ctx->stack; |
7080 | | |
7081 | 367M | if (buf->knockout) |
7082 | 2.25M | return pdf14_mark_fill_rectangle_ko_simple(dev, x, y, w, h, color, NULL, |
7083 | 2.25M | false); |
7084 | 365M | else |
7085 | 365M | return pdf14_mark_fill_rectangle(dev, x, y, w, h, color, NULL, false); |
7086 | 367M | } |
7087 | | |
7088 | | static int |
7089 | | pdf14_compute_group_device_int_rect(const gs_matrix *ctm, |
7090 | | const gs_rect *pbbox, gs_int_rect *rect) |
7091 | 2.29M | { |
7092 | 2.29M | gs_rect dev_bbox; |
7093 | 2.29M | int code; |
7094 | | |
7095 | 2.29M | code = gs_bbox_transform(pbbox, ctm, &dev_bbox); |
7096 | 2.29M | if (code < 0) |
7097 | 0 | return code; |
7098 | 2.29M | rect->p.x = (int)floor(dev_bbox.p.x); |
7099 | 2.29M | rect->p.y = (int)floor(dev_bbox.p.y); |
7100 | 2.29M | rect->q.x = (int)ceil(dev_bbox.q.x); |
7101 | 2.29M | rect->q.y = (int)ceil(dev_bbox.q.y); |
7102 | | /* Sanity check rect for insane ctms */ |
7103 | 2.29M | if (rect->p.x < 0) |
7104 | 86.6k | rect->p.x = 0; |
7105 | 2.29M | if (rect->q.x < rect->p.x) |
7106 | 2.22k | rect->q.x = rect->p.x; |
7107 | 2.29M | if (rect->p.y < 0) |
7108 | 2.10M | rect->p.y = 0; |
7109 | 2.29M | if (rect->q.y < rect->p.y) |
7110 | 50.0k | rect->q.y = rect->p.y; |
7111 | 2.29M | return 0; |
7112 | 2.29M | } |
7113 | | |
7114 | | static int |
7115 | | compute_group_device_int_rect(pdf14_device *pdev, gs_int_rect *rect, |
7116 | | const gs_rect *pbbox, gs_gstate *pgs) |
7117 | 2.21M | { |
7118 | 2.21M | int code = pdf14_compute_group_device_int_rect(&ctm_only(pgs), pbbox, rect); |
7119 | | |
7120 | 2.21M | if (code < 0) |
7121 | 0 | return code; |
7122 | 2.21M | rect_intersect(*rect, pdev->ctx->rect); |
7123 | | /* Make sure the rectangle is not anomalous (q < p) -- see gsrect.h */ |
7124 | 2.21M | if (rect->q.x < rect->p.x) |
7125 | 14.4k | rect->q.x = rect->p.x; |
7126 | 2.21M | if (rect->q.y < rect->p.y) |
7127 | 27.7k | rect->q.y = rect->p.y; |
7128 | 2.21M | return 0; |
7129 | 2.21M | } |
7130 | | |
7131 | | static int |
7132 | | pdf14_begin_transparency_group(gx_device* dev, |
7133 | | const gs_transparency_group_params_t* ptgp, |
7134 | | const gs_rect* pbbox, |
7135 | | gs_gstate* pgs, gs_memory_t* mem) |
7136 | 2.28M | { |
7137 | 2.28M | pdf14_device* pdev = (pdf14_device*)dev; |
7138 | 2.28M | float alpha = ptgp->group_opacity * ptgp->group_shape; |
7139 | 2.28M | gs_int_rect rect; |
7140 | 2.28M | int code; |
7141 | 2.28M | bool isolated = ptgp->Isolated; |
7142 | 2.28M | gs_transparency_color_t group_color_type; |
7143 | 2.28M | cmm_profile_t* group_profile; |
7144 | 2.28M | cmm_profile_t* tos_profile; |
7145 | 2.28M | gsicc_rendering_param_t render_cond; |
7146 | 2.28M | cmm_dev_profile_t* dev_profile; |
7147 | 2.28M | bool cm_back_drop = false; |
7148 | 2.28M | bool new_icc = false; |
7149 | 2.28M | pdf14_group_color_t* group_color_info; |
7150 | 2.28M | bool has_tags = device_encodes_tags(dev); |
7151 | | |
7152 | 2.28M | code = dev_proc(dev, get_profile)(dev, &dev_profile); |
7153 | 2.28M | if (code < 0) |
7154 | 0 | return code; |
7155 | 2.28M | gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &tos_profile, &render_cond); |
7156 | | |
7157 | 2.28M | if (ptgp->text_group == PDF14_TEXTGROUP_BT_PUSHED) { |
7158 | 503k | pdev->text_group = PDF14_TEXTGROUP_BT_PUSHED; /* For immediate mode and clist reading */ |
7159 | 503k | } |
7160 | | |
7161 | 2.28M | if (ptgp->text_group == PDF14_TEXTGROUP_BT_PUSHED) |
7162 | 503k | rect = pdev->ctx->rect; /* Use parent group for text_group. */ |
7163 | 1.78M | else |
7164 | 1.78M | code = compute_group_device_int_rect(pdev, &rect, pbbox, pgs); |
7165 | | |
7166 | 2.28M | if (code < 0) |
7167 | 0 | return code; |
7168 | 2.28M | if_debug5m('v', pdev->memory, |
7169 | 2.28M | "[v]pdf14_begin_transparency_group, I = %d, K = %d, alpha = %g, bm = %d page_group = %d\n", |
7170 | 2.28M | ptgp->Isolated, ptgp->Knockout, (double)alpha, pgs->blend_mode, ptgp->page_group); |
7171 | | |
7172 | | /* If the group color is unknown then use the current device profile. */ |
7173 | 2.28M | if (ptgp->group_color_type == UNKNOWN) { |
7174 | 1.84M | group_color_type = ICC; |
7175 | 1.84M | group_profile = tos_profile; |
7176 | 1.84M | } |
7177 | 442k | else { |
7178 | 442k | group_color_type = ptgp->group_color_type; |
7179 | 442k | group_profile = ptgp->iccprofile; |
7180 | 442k | } |
7181 | | |
7182 | | /* We have to handle case where the profile is in the clist */ |
7183 | 2.28M | if (group_profile == NULL && pdev->pclist_device != NULL) { |
7184 | | /* Get the serialized data from the clist. */ |
7185 | 442k | gx_device_clist_reader* pcrdev = (gx_device_clist_reader*)(pdev->pclist_device); |
7186 | 442k | group_profile = gsicc_read_serial_icc((gx_device*)pcrdev, ptgp->icc_hashcode); |
7187 | 442k | if (group_profile == NULL) |
7188 | 0 | return gs_throw(gs_error_unknownerror, "ICC data not found in clist"); |
7189 | | /* Keep a pointer to the clist device */ |
7190 | 442k | group_profile->dev = (gx_device*)pcrdev; |
7191 | 442k | new_icc = true; |
7192 | 442k | } |
7193 | 2.28M | if (group_profile != NULL) { |
7194 | | /* If we have a non-isolated group and the color space is different, |
7195 | | we will need to CM the backdrop. */ |
7196 | 2.28M | if (!gsicc_profiles_equal(group_profile, tos_profile)) { |
7197 | 197k | cm_back_drop = true; |
7198 | 197k | } |
7199 | 2.28M | } |
7200 | | |
7201 | | /* Always create the base color group information as it is only through |
7202 | | groups that we can have a color space change. This will survive |
7203 | | the life of the context. */ |
7204 | 2.28M | if (pdev->ctx->base_color == NULL) { |
7205 | 612k | pdev->ctx->base_color = pdf14_make_base_group_color(dev); |
7206 | 612k | } |
7207 | | |
7208 | | /* If this is not the page group and we don't yet have a group, we need |
7209 | | to create a buffer for the whole page so that we can handle stuff drawn |
7210 | | outside this current group (e.g. two non inclusive groups drawn independently) */ |
7211 | 2.28M | if (pdev->ctx->stack == NULL && !ptgp->page_group) { |
7212 | 80.0k | code = pdf14_initialize_ctx(dev, NULL); |
7213 | 80.0k | if (code < 0) |
7214 | 0 | return code; |
7215 | 80.0k | pdev->ctx->stack->isolated = true; |
7216 | 80.0k | } |
7217 | | |
7218 | 2.28M | group_color_info = pdf14_push_color_model(dev, group_color_type, ptgp->icc_hashcode, |
7219 | 2.28M | group_profile, false); |
7220 | 2.28M | if (group_color_info == NULL) |
7221 | 0 | return gs_error_VMerror; |
7222 | 2.28M | if_debug0m('v', dev->memory, "[v]Transparency group color space update\n"); |
7223 | | |
7224 | 2.28M | code = pdf14_push_transparency_group(pdev->ctx, &rect, isolated, ptgp->Knockout, |
7225 | 2.28M | (uint16_t)floor (65535 * alpha + 0.5), |
7226 | 2.28M | (uint16_t)floor(65535 * ptgp->group_shape + 0.5), |
7227 | 2.28M | (uint16_t)floor(65535 * ptgp->group_opacity + 0.5), |
7228 | 2.28M | pgs->blend_mode, ptgp->idle, |
7229 | 2.28M | ptgp->mask_id, pdev->color_info.num_components - has_tags, |
7230 | 2.28M | cm_back_drop, ptgp->shade_group, |
7231 | 2.28M | group_profile, tos_profile, group_color_info, pgs, dev); |
7232 | 2.28M | if (new_icc) |
7233 | 442k | gsicc_adjust_profile_rc(group_profile, -1, "pdf14_begin_transparency_group"); |
7234 | 2.28M | return code; |
7235 | 2.28M | } |
7236 | | |
7237 | | static void |
7238 | | pdf14_pop_color_model(gx_device* dev, pdf14_group_color_t* group_color) |
7239 | 2.28M | { |
7240 | 2.28M | pdf14_device* pdev = (pdf14_device*)dev; |
7241 | | |
7242 | 2.28M | if (group_color != NULL && |
7243 | 2.28M | !(group_color->group_color_mapping_procs == NULL && |
7244 | 2.28M | group_color->group_color_comp_index == NULL)) { |
7245 | 2.28M | bool has_tags = device_encodes_tags(dev); |
7246 | 2.28M | set_dev_proc(pdev, get_color_mapping_procs, group_color->group_color_mapping_procs); |
7247 | 2.28M | set_dev_proc(pdev, get_color_comp_index, group_color->group_color_comp_index); |
7248 | 2.28M | pdev->color_info.polarity = group_color->polarity; |
7249 | 2.28M | if (pdev->num_planar_planes > 0) |
7250 | 84.9k | pdev->num_planar_planes += group_color->num_components - (pdev->color_info.num_components - has_tags); |
7251 | 2.28M | pdev->color_info.num_components = group_color->num_components + has_tags; |
7252 | 2.28M | assert(pdev->num_planar_planes == 0 || pdev->num_planar_planes == pdev->color_info.num_components); |
7253 | 2.28M | assert(pdev->color_info.num_components - has_tags == group_color->num_components); |
7254 | 2.28M | pdev->blend_procs = group_color->blend_procs; |
7255 | 2.28M | pdev->ctx->additive = group_color->isadditive; |
7256 | 2.28M | pdev->pdf14_procs = group_color->unpack_procs; |
7257 | 2.28M | pdev->color_info.opmsupported = GX_CINFO_OPMSUPPORTED_UNKNOWN; |
7258 | 2.28M | pdev->color_info.depth = group_color->depth; |
7259 | 2.28M | pdev->color_info.max_color = group_color->max_color; |
7260 | 2.28M | pdev->color_info.max_gray = group_color->max_gray; |
7261 | 2.28M | memcpy(&(pdev->color_info.comp_bits), &(group_color->comp_bits), |
7262 | 2.28M | GX_DEVICE_COLOR_MAX_COMPONENTS); |
7263 | 2.28M | memcpy(&(pdev->color_info.comp_shift), &(group_color->comp_shift), |
7264 | 2.28M | GX_DEVICE_COLOR_MAX_COMPONENTS); |
7265 | 2.28M | if (group_color->icc_profile != NULL) { |
7266 | | /* make sure to decrement the device profile. If it was allocated |
7267 | | with the push then it will be freed. */ |
7268 | 2.28M | gsicc_adjust_profile_rc(pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], |
7269 | 2.28M | -1, "pdf14_pop_color_model"); |
7270 | 2.28M | pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] = |
7271 | 2.28M | group_color->icc_profile; |
7272 | | |
7273 | 2.28M | gsicc_adjust_profile_rc(pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], |
7274 | 2.28M | 1, "pdf14_pop_color_model"); |
7275 | 2.28M | } |
7276 | 2.28M | pdev->num_std_colorants = group_color->num_std_colorants; |
7277 | 2.28M | } |
7278 | 2.28M | } |
7279 | | |
7280 | | static int |
7281 | | pdf14_end_transparency_group(gx_device* dev, gs_gstate* pgs) |
7282 | 2.28M | { |
7283 | 2.28M | pdf14_device* pdev = (pdf14_device*)dev; |
7284 | 2.28M | int code; |
7285 | 2.28M | cmm_profile_t* group_profile; |
7286 | 2.28M | gsicc_rendering_param_t render_cond; |
7287 | 2.28M | cmm_dev_profile_t* dev_profile; |
7288 | 2.28M | int has_tags = device_encodes_tags(dev); |
7289 | | |
7290 | 2.28M | code = dev_proc(dev, get_profile)(dev, &dev_profile); |
7291 | 2.28M | if (code < 0) |
7292 | 0 | return code; |
7293 | | |
7294 | 2.28M | gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &group_profile, |
7295 | 2.28M | &render_cond); |
7296 | 2.28M | if_debug0m('v', dev->memory, "[v]pdf14_end_transparency_group\n"); |
7297 | | |
7298 | 2.28M | code = pdf14_pop_transparency_group(pgs, pdev->ctx, pdev->blend_procs, |
7299 | 2.28M | pdev->color_info.num_components - has_tags, group_profile, (gx_device*)pdev); |
7300 | 2.28M | if (code < 0) |
7301 | 0 | return code; |
7302 | | #ifdef DEBUG |
7303 | | pdf14_debug_mask_stack_state(pdev->ctx); |
7304 | | #endif |
7305 | | /* If this group is the base group, then restore the color model |
7306 | | of the device at this time. Note that during the actual device pop |
7307 | | we will need to use the profile of the buffer not the pdf14 device |
7308 | | as the source color space */ |
7309 | 2.28M | if (pdev->ctx->stack->group_popped) { |
7310 | 435k | pdf14_pop_color_model(dev, pdev->ctx->base_color); |
7311 | 1.84M | } else { |
7312 | 1.84M | pdf14_pop_color_model(dev, pdev->ctx->stack->group_color_info); |
7313 | 1.84M | } |
7314 | | |
7315 | 2.28M | return code; |
7316 | 2.28M | } |
7317 | | |
7318 | | static pdf14_group_color_t* |
7319 | | pdf14_push_color_model(gx_device *dev, gs_transparency_color_t group_color_type, |
7320 | | int64_t icc_hashcode, cmm_profile_t *iccprofile, |
7321 | | bool is_mask) |
7322 | 2.71M | { |
7323 | 2.71M | pdf14_device *pdevproto = NULL; |
7324 | 2.71M | pdf14_device *pdev = (pdf14_device *)dev; |
7325 | 2.71M | const pdf14_procs_t *new_14procs = NULL; |
7326 | 2.71M | pdf14_group_color_t *group_color; |
7327 | 2.71M | gx_color_polarity_t new_polarity; |
7328 | 2.71M | uchar new_num_comps; |
7329 | 2.71M | bool new_additive; |
7330 | 2.71M | gx_device_clist_reader *pcrdev; |
7331 | 2.71M | byte comp_bits[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
7332 | 2.71M | byte comp_shift[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
7333 | 2.71M | int k; |
7334 | 2.71M | bool has_tags = device_encodes_tags(dev); |
7335 | 2.71M | bool deep = pdev->ctx->deep; |
7336 | | |
7337 | 2.71M | if_debug0m('v', dev->memory, "[v]pdf14_push_color_model\n"); |
7338 | | |
7339 | 2.71M | assert(dev->color_info.num_components == dev->num_planar_planes || dev->num_planar_planes == 0); |
7340 | | |
7341 | 2.71M | group_color = gs_alloc_struct(dev->memory->stable_memory, |
7342 | 2.71M | pdf14_group_color_t, &st_pdf14_clr, |
7343 | 2.71M | "pdf14_push_color_model"); |
7344 | 2.71M | if (group_color == NULL) |
7345 | 0 | return NULL; |
7346 | | |
7347 | 2.71M | memset(group_color, 0, sizeof(pdf14_group_color_t)); |
7348 | | |
7349 | 2.71M | switch (group_color_type) { |
7350 | 0 | case GRAY_SCALE: |
7351 | 0 | new_polarity = GX_CINFO_POLARITY_ADDITIVE; |
7352 | 0 | new_num_comps = 1; |
7353 | 0 | pdevproto = (pdf14_device *)&gs_pdf14_Gray_device; |
7354 | 0 | new_additive = true; |
7355 | 0 | new_14procs = &gray_pdf14_procs; |
7356 | 0 | break; |
7357 | 0 | case DEVICE_RGB: |
7358 | 0 | case CIE_XYZ: |
7359 | 0 | new_polarity = GX_CINFO_POLARITY_ADDITIVE; |
7360 | 0 | new_num_comps = 3; |
7361 | 0 | pdevproto = (pdf14_device *)&gs_pdf14_RGB_device; |
7362 | 0 | new_additive = true; |
7363 | 0 | new_14procs = &rgb_pdf14_procs; |
7364 | 0 | break; |
7365 | 0 | case DEVICE_CMYK: |
7366 | 0 | new_polarity = GX_CINFO_POLARITY_SUBTRACTIVE; |
7367 | 0 | new_num_comps = 4; |
7368 | 0 | pdevproto = (pdf14_device *)&gs_pdf14_CMYK_device; |
7369 | 0 | new_additive = false; |
7370 | | /* This is needed due to the mismatched compressed encode decode |
7371 | | between the device procs and the pdf14 procs */ |
7372 | 0 | if (dev->color_info.num_components > 4){ |
7373 | 0 | new_14procs = &cmykspot_pdf14_procs; |
7374 | 0 | } else { |
7375 | 0 | new_14procs = &cmyk_pdf14_procs; |
7376 | 0 | } |
7377 | 0 | break; |
7378 | 2.71M | case ICC: |
7379 | | /* If we are coming from the clist reader, then we need to get |
7380 | | the ICC data now */ |
7381 | 2.71M | if (iccprofile == NULL && pdev->pclist_device != NULL) { |
7382 | | /* Get the serialized data from the clist. Not the whole |
7383 | | profile. */ |
7384 | 429k | pcrdev = (gx_device_clist_reader *)(pdev->pclist_device); |
7385 | 429k | iccprofile = gsicc_read_serial_icc((gx_device *) pcrdev, |
7386 | 429k | icc_hashcode); |
7387 | 429k | if (iccprofile == NULL) |
7388 | 0 | return NULL; |
7389 | | /* Keep a pointer to the clist device */ |
7390 | 429k | iccprofile->dev = (gx_device *) pcrdev; |
7391 | 2.28M | } else { |
7392 | | /* Go ahead and rc increment right now. This way when |
7393 | | we pop, we will make sure to decrement and avoid a |
7394 | | leak for the above profile that we just created. This |
7395 | | goes with the assignment to the device's profile. |
7396 | | Note that we still do the increment for the group_color |
7397 | | assignment below. */ |
7398 | 2.28M | if (iccprofile == NULL) |
7399 | 0 | return NULL; |
7400 | 2.28M | gsicc_adjust_profile_rc(iccprofile, 1, "pdf14_push_color_model"); |
7401 | 2.28M | } |
7402 | 2.71M | new_num_comps = iccprofile->num_comps; |
7403 | 2.71M | if (new_num_comps == 4) { |
7404 | 89.8k | new_additive = false; |
7405 | 89.8k | new_polarity = GX_CINFO_POLARITY_SUBTRACTIVE; |
7406 | 2.62M | } else { |
7407 | 2.62M | new_additive = true; |
7408 | 2.62M | new_polarity = GX_CINFO_POLARITY_ADDITIVE; |
7409 | 2.62M | } |
7410 | 2.71M | switch (new_num_comps) { |
7411 | 666k | case 1: |
7412 | 666k | if (pdev->sep_device && !is_mask) { |
7413 | 0 | pdevproto = (pdf14_device *)&gs_pdf14_Grayspot_device; |
7414 | 0 | new_14procs = &grayspot_pdf14_procs; |
7415 | 666k | } else { |
7416 | 666k | pdevproto = (pdf14_device *)&gs_pdf14_Gray_device; |
7417 | 666k | new_14procs = &gray_pdf14_procs; |
7418 | 666k | } |
7419 | 666k | break; |
7420 | 1.96M | case 3: |
7421 | 1.96M | if (pdev->sep_device) { |
7422 | 71.8k | pdevproto = (pdf14_device *)&gs_pdf14_RGBspot_device; |
7423 | 71.8k | new_14procs = &rgbspot_pdf14_procs; |
7424 | 71.8k | } |
7425 | 1.89M | else { |
7426 | 1.89M | pdevproto = (pdf14_device *)&gs_pdf14_RGB_device; |
7427 | 1.89M | new_14procs = &rgb_pdf14_procs; |
7428 | 1.89M | } |
7429 | 1.96M | break; |
7430 | 89.8k | case 4: |
7431 | 89.8k | if (pdev->sep_device) { |
7432 | 13.0k | pdevproto = (pdf14_device *)&gs_pdf14_CMYKspot_device; |
7433 | 13.0k | new_14procs = &cmykspot_pdf14_procs; |
7434 | 76.7k | } else { |
7435 | 76.7k | pdevproto = (pdf14_device *)&gs_pdf14_CMYK_device; |
7436 | 76.7k | new_14procs = &cmyk_pdf14_procs; |
7437 | 76.7k | } |
7438 | 89.8k | break; |
7439 | 0 | default: |
7440 | 0 | return NULL; |
7441 | 0 | break; |
7442 | 2.71M | } |
7443 | 2.71M | break; |
7444 | 2.71M | default: |
7445 | 0 | return NULL; |
7446 | 0 | break; |
7447 | 2.71M | } |
7448 | | |
7449 | | /* We might just have changed the colorspace of the device, which means |
7450 | | * the number of colorants have changed. */ |
7451 | 2.71M | group_color->num_std_colorants = new_num_comps; |
7452 | 2.71M | pdev->num_std_colorants = new_num_comps; |
7453 | | |
7454 | 2.71M | if (has_tags) |
7455 | 0 | new_num_comps++; |
7456 | | |
7457 | 2.71M | if (group_color_type == ICC && iccprofile != NULL) { |
7458 | 2.71M | group_color->icc_profile = iccprofile; |
7459 | 2.71M | gsicc_adjust_profile_rc(iccprofile, 1, "pdf14_push_color_model"); |
7460 | 2.71M | } |
7461 | | |
7462 | | /* If we are a sep device and this is not a softmask, ensure we maintain the |
7463 | | spot colorants and know how to index into them */ |
7464 | 2.71M | if (pdev->sep_device && !is_mask) { |
7465 | 84.8k | int num_spots = dev->color_info.num_components - has_tags - |
7466 | 84.8k | dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE]->num_comps; |
7467 | | |
7468 | 84.8k | if (num_spots > 0) |
7469 | 688 | new_num_comps += num_spots; |
7470 | 84.8k | } |
7471 | | /* Calculate the bits and shifts *after* we have allowed for tags. */ |
7472 | 9.63M | for (k = 0; k < new_num_comps; k++) { |
7473 | 6.91M | comp_bits[k] = 8<<deep; |
7474 | 6.91M | comp_shift[k] = (new_num_comps - k - 1) * (8<<deep); |
7475 | 6.91M | } |
7476 | | |
7477 | | /* Set device values now and store settings in group_color. Then they |
7478 | | are available when we pop the previous group */ |
7479 | 2.71M | if_debug2m('v', pdev->memory, |
7480 | 2.71M | "[v]pdf14_push_color_model, num_components_old = %d num_components_new = %d\n", |
7481 | 2.71M | pdev->color_info.num_components,new_num_comps); |
7482 | 2.71M | { |
7483 | 2.71M | gx_device local_device; |
7484 | | |
7485 | 2.71M | local_device.initialize_device_procs = pdevproto->initialize_device_procs; |
7486 | 2.71M | local_device.initialize_device_procs((gx_device *)&local_device); |
7487 | 2.71M | set_dev_proc(pdev, get_color_mapping_procs, local_device.procs.get_color_mapping_procs); |
7488 | 2.71M | set_dev_proc(pdev, get_color_comp_index, local_device.procs.get_color_comp_index); |
7489 | 2.71M | } |
7490 | 2.71M | group_color->blend_procs = pdev->blend_procs = pdevproto->blend_procs; |
7491 | 2.71M | group_color->polarity = pdev->color_info.polarity = new_polarity; |
7492 | 2.71M | group_color->isadditive = pdev->ctx->additive = new_additive; |
7493 | 2.71M | pdev->color_info.opmsupported = GX_CINFO_OPMSUPPORTED_UNKNOWN; |
7494 | 2.71M | group_color->unpack_procs = pdev->pdf14_procs = new_14procs; |
7495 | 2.71M | if (pdev->num_planar_planes > 0) |
7496 | 113k | pdev->num_planar_planes += new_num_comps - pdev->color_info.num_components; |
7497 | 2.71M | group_color->num_components = new_num_comps - has_tags; |
7498 | 2.71M | pdev->color_info.num_components = new_num_comps; |
7499 | 2.71M | assert(pdev->num_planar_planes == 0 || pdev->num_planar_planes == pdev->color_info.num_components); |
7500 | 2.71M | assert(pdev->color_info.num_components - has_tags == group_color->num_components); |
7501 | 2.71M | pdev->color_info.depth = new_num_comps * (8<<deep); |
7502 | 2.71M | memset(&(pdev->color_info.comp_bits), 0, GX_DEVICE_COLOR_MAX_COMPONENTS); |
7503 | 2.71M | memset(&(pdev->color_info.comp_shift), 0, GX_DEVICE_COLOR_MAX_COMPONENTS); |
7504 | 2.71M | memcpy(&(pdev->color_info.comp_bits), comp_bits, new_num_comps); |
7505 | 2.71M | memcpy(&(pdev->color_info.comp_shift), comp_shift, new_num_comps); |
7506 | 2.71M | group_color->max_color = pdev->color_info.max_color = deep ? 65535 : 255; |
7507 | 2.71M | group_color->max_gray = pdev->color_info.max_gray = deep ? 65535 : 255; |
7508 | 2.71M | group_color->depth = pdev->color_info.depth; |
7509 | 2.71M | group_color->decode = dev_proc(pdev, decode_color); |
7510 | 2.71M | group_color->encode = dev_proc(pdev, encode_color); |
7511 | 2.71M | group_color->group_color_mapping_procs = dev_proc(pdev, get_color_mapping_procs); |
7512 | 2.71M | group_color->group_color_comp_index = dev_proc(pdev, get_color_comp_index); |
7513 | 2.71M | memcpy(&(group_color->comp_bits), &(pdev->color_info.comp_bits), |
7514 | 2.71M | GX_DEVICE_COLOR_MAX_COMPONENTS); |
7515 | 2.71M | memcpy(&(group_color->comp_shift), &(pdev->color_info.comp_shift), |
7516 | 2.71M | GX_DEVICE_COLOR_MAX_COMPONENTS); |
7517 | 2.71M | group_color->get_cmap_procs = pdf14_get_cmap_procs; |
7518 | | |
7519 | | /* If the CS was ICC based, we need to update the device ICC profile |
7520 | | in the ICC manager, since that is the profile that is used for the |
7521 | | PDF14 device */ |
7522 | 2.71M | if (group_color_type == ICC && iccprofile != NULL) { |
7523 | | /* iccprofile was incremented above if we had not just created it. |
7524 | | When we do the pop we will decrement and if we just created it, it |
7525 | | will be destroyed */ |
7526 | 2.71M | gsicc_adjust_profile_rc(dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], -1, "pdf14_push_color_model"); |
7527 | 2.71M | dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] = iccprofile; |
7528 | 2.71M | } |
7529 | 2.71M | return group_color; |
7530 | 2.71M | } |
7531 | | |
7532 | | static int |
7533 | | pdf14_clist_push_color_model(gx_device *dev, gx_device* cdev, gs_gstate *pgs, |
7534 | | const gs_pdf14trans_t *pdf14pct, gs_memory_t* mem, |
7535 | | bool is_mask) |
7536 | 63.1k | { |
7537 | 63.1k | pdf14_device* pdev = (pdf14_device*)dev; |
7538 | 63.1k | pdf14_group_color_t* new_group_color; |
7539 | 63.1k | gsicc_rendering_param_t render_cond; |
7540 | 63.1k | cmm_dev_profile_t* dev_profile; |
7541 | 63.1k | pdf14_device* pdevproto; |
7542 | 63.1k | gx_device_clist_writer* cldev = (gx_device_clist_writer*)pdev->pclist_device; |
7543 | 63.1k | const pdf14_procs_t* new_14procs; |
7544 | 63.1k | bool update_color_info; |
7545 | 63.1k | gx_color_polarity_t new_polarity; |
7546 | 63.1k | int new_num_comps; |
7547 | 63.1k | bool new_additive = false; |
7548 | 63.1k | byte new_depth; |
7549 | 63.1k | byte comp_bits[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
7550 | 63.1k | byte comp_shift[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
7551 | 63.1k | int k; |
7552 | 63.1k | bool has_tags = device_encodes_tags(dev); |
7553 | 63.1k | bool deep = device_is_deep(dev); |
7554 | 63.1k | gs_transparency_color_t group_color_type = pdf14pct->params.group_color_type; |
7555 | 63.1k | cmm_profile_t *new_profile = pdf14pct->params.iccprofile; |
7556 | 63.1k | cmm_profile_t *old_profile = NULL; |
7557 | | |
7558 | 63.1k | assert(dev->num_planar_planes == 0 || dev->num_planar_planes == dev->color_info.num_components); |
7559 | | |
7560 | 63.1k | dev_proc(dev, get_profile)(dev, &dev_profile); |
7561 | 63.1k | gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &old_profile, |
7562 | 63.1k | &render_cond); |
7563 | 63.1k | if_debug0m('v', dev->memory, "[v]pdf14_clist_push_color_model\n"); |
7564 | | |
7565 | | /* Allocate a new one */ |
7566 | 63.1k | new_group_color = gs_alloc_struct(dev->memory->stable_memory, pdf14_group_color_t, |
7567 | 63.1k | &st_pdf14_clr, "pdf14_clist_push_color_model"); |
7568 | | |
7569 | 63.1k | if (new_group_color == NULL) |
7570 | 0 | return_error(gs_error_VMerror); |
7571 | | |
7572 | | /* Link to old one */ |
7573 | 63.1k | new_group_color->previous = pdev->color_model_stack; |
7574 | | |
7575 | | /* Reassign new one to dev */ |
7576 | 63.1k | pdev->color_model_stack = new_group_color; |
7577 | | |
7578 | | /* Initialize with values */ |
7579 | 63.1k | new_group_color->get_cmap_procs = pgs->get_cmap_procs; |
7580 | 63.1k | new_group_color->group_color_mapping_procs = |
7581 | 63.1k | dev_proc(pdev, get_color_mapping_procs); |
7582 | 63.1k | new_group_color->group_color_comp_index = |
7583 | 63.1k | dev_proc(pdev, get_color_comp_index); |
7584 | 63.1k | new_group_color->blend_procs = pdev->blend_procs; |
7585 | 63.1k | new_group_color->polarity = pdev->color_info.polarity; |
7586 | 63.1k | new_group_color->num_components = pdev->color_info.num_components - has_tags; |
7587 | 63.1k | new_group_color->unpack_procs = pdev->pdf14_procs; |
7588 | 63.1k | new_group_color->depth = pdev->color_info.depth; |
7589 | 63.1k | new_group_color->max_color = pdev->color_info.max_color; |
7590 | 63.1k | new_group_color->max_gray = pdev->color_info.max_gray; |
7591 | 63.1k | new_group_color->decode = dev_proc(pdev, decode_color); |
7592 | 63.1k | new_group_color->encode = dev_proc(pdev, encode_color); |
7593 | 63.1k | memcpy(&(new_group_color->comp_bits), &(pdev->color_info.comp_bits), |
7594 | 63.1k | GX_DEVICE_COLOR_MAX_COMPONENTS); |
7595 | 63.1k | memcpy(&(new_group_color->comp_shift), &(pdev->color_info.comp_shift), |
7596 | 63.1k | GX_DEVICE_COLOR_MAX_COMPONENTS); |
7597 | | |
7598 | 63.1k | if (new_profile == NULL) |
7599 | 38.1k | new_group_color->icc_profile = NULL; |
7600 | | |
7601 | | /* isadditive is only used in ctx */ |
7602 | 63.1k | if (pdev->ctx) { |
7603 | 0 | new_group_color->isadditive = pdev->ctx->additive; |
7604 | 0 | } |
7605 | | |
7606 | 63.1k | memset(comp_bits, 0, GX_DEVICE_COLOR_MAX_COMPONENTS); |
7607 | 63.1k | memset(comp_shift, 0, GX_DEVICE_COLOR_MAX_COMPONENTS); |
7608 | | |
7609 | 63.1k | if (group_color_type == ICC && new_profile == NULL) |
7610 | 0 | return gs_throw(gs_error_undefinedresult, "Missing ICC data"); |
7611 | 63.1k | if_debug0m('v', cldev->memory, "[v]pdf14_clist_push_color_model\n"); |
7612 | | /* Check if we need to alter the device procs at this stage. Many of the procs |
7613 | | are based upon the color space of the device. We want to remain in the |
7614 | | color space defined by the color space of the soft mask or transparency |
7615 | | group as opposed to the device color space. Later, when we pop the softmask |
7616 | | we will collapse it to a single band and then compose with it to the device |
7617 | | color space (or the parent layer space). In the case where we pop an |
7618 | | isolated transparency group, we will do the blending in the proper color |
7619 | | space and then transform the data when we pop the group. Remember that only |
7620 | | isolated groups can have color spaces that are different than their parent. */ |
7621 | 63.1k | update_color_info = false; |
7622 | 63.1k | switch (group_color_type) { |
7623 | 0 | case GRAY_SCALE: |
7624 | 0 | if (pdev->color_info.num_components != 1) { |
7625 | 0 | update_color_info = true; |
7626 | 0 | new_polarity = GX_CINFO_POLARITY_ADDITIVE; |
7627 | 0 | new_num_comps = 1; |
7628 | 0 | pdevproto = (pdf14_device*)&gs_pdf14_Gray_device; |
7629 | 0 | new_additive = true; |
7630 | 0 | new_14procs = &gray_pdf14_procs; |
7631 | 0 | new_depth = 8 << deep; |
7632 | 0 | } |
7633 | 0 | break; |
7634 | 0 | case DEVICE_RGB: |
7635 | 0 | case CIE_XYZ: |
7636 | 0 | if (pdev->color_info.num_components != 3) { |
7637 | 0 | update_color_info = true; |
7638 | 0 | new_polarity = GX_CINFO_POLARITY_ADDITIVE; |
7639 | 0 | new_num_comps = 3; |
7640 | 0 | pdevproto = (pdf14_device*)&gs_pdf14_RGB_device; |
7641 | 0 | new_additive = true; |
7642 | 0 | new_14procs = &rgb_pdf14_procs; |
7643 | 0 | new_depth = 24 << deep; |
7644 | 0 | } |
7645 | 0 | break; |
7646 | 0 | case DEVICE_CMYK: |
7647 | 0 | if (pdev->color_info.num_components != 4) { |
7648 | 0 | update_color_info = true; |
7649 | 0 | new_polarity = GX_CINFO_POLARITY_SUBTRACTIVE; |
7650 | 0 | new_num_comps = 4; |
7651 | 0 | pdevproto = (pdf14_device*)&gs_pdf14_CMYK_device; |
7652 | 0 | new_additive = false; |
7653 | | /* This is needed due to the mismatched compressed encode decode |
7654 | | between the device procs and the pdf14 procs */ |
7655 | 0 | if (dev->color_info.num_components > 4) { |
7656 | 0 | new_14procs = &cmykspot_pdf14_procs; |
7657 | 0 | } |
7658 | 0 | else { |
7659 | 0 | new_14procs = &cmyk_pdf14_procs; |
7660 | 0 | } |
7661 | 0 | new_depth = 32 << deep; |
7662 | 0 | } |
7663 | 0 | break; |
7664 | 25.0k | case ICC: |
7665 | | /* Check if the profile is different. */ |
7666 | 25.0k | if (!gsicc_profiles_equal(old_profile, new_profile)) { |
7667 | 22.7k | update_color_info = true; |
7668 | 22.7k | new_num_comps = new_profile->num_comps; |
7669 | 22.7k | new_depth = new_profile->num_comps * (8 << deep); |
7670 | 22.7k | switch (new_num_comps) { |
7671 | 20.4k | case 1: |
7672 | 20.4k | if (pdev->sep_device && !is_mask) { |
7673 | 0 | pdevproto = (pdf14_device*)&gs_pdf14_Grayspot_device; |
7674 | 0 | new_14procs = &grayspot_pdf14_procs; |
7675 | 0 | } |
7676 | 20.4k | else { |
7677 | 20.4k | pdevproto = (pdf14_device*)&gs_pdf14_Gray_device; |
7678 | 20.4k | new_14procs = &gray_pdf14_procs; |
7679 | 20.4k | } |
7680 | 20.4k | new_polarity = GX_CINFO_POLARITY_ADDITIVE; |
7681 | 20.4k | new_additive = true; |
7682 | 20.4k | break; |
7683 | 2.09k | case 3: |
7684 | 2.09k | if (pdev->sep_device) { |
7685 | 536 | pdevproto = (pdf14_device*)&gs_pdf14_RGBspot_device; |
7686 | 536 | new_14procs = &rgbspot_pdf14_procs; |
7687 | 536 | } |
7688 | 1.55k | else { |
7689 | 1.55k | pdevproto = (pdf14_device*)&gs_pdf14_RGB_device; |
7690 | 1.55k | new_14procs = &rgb_pdf14_procs; |
7691 | 1.55k | } |
7692 | 2.09k | new_polarity = GX_CINFO_POLARITY_ADDITIVE; |
7693 | 2.09k | new_additive = true; |
7694 | 2.09k | break; |
7695 | 207 | case 4: |
7696 | 207 | if (pdev->sep_device) { |
7697 | 3 | pdevproto = (pdf14_device*)&gs_pdf14_CMYKspot_device; |
7698 | 3 | new_14procs = &cmykspot_pdf14_procs; |
7699 | 3 | } |
7700 | 204 | else { |
7701 | 204 | pdevproto = (pdf14_device*)&gs_pdf14_CMYK_device; |
7702 | 204 | new_14procs = &cmyk_pdf14_procs; |
7703 | 204 | } |
7704 | 207 | new_polarity = GX_CINFO_POLARITY_SUBTRACTIVE; |
7705 | 207 | new_additive = false; |
7706 | 207 | break; |
7707 | 0 | default: |
7708 | 0 | return gs_throw(gs_error_undefinedresult, |
7709 | 22.7k | "ICC Number of colorants illegal"); |
7710 | 22.7k | } |
7711 | 22.7k | } |
7712 | 25.0k | break; |
7713 | 38.1k | case UNKNOWN: |
7714 | 38.1k | return 0; |
7715 | 0 | break; |
7716 | 0 | default: |
7717 | 0 | return_error(gs_error_rangecheck); |
7718 | 0 | break; |
7719 | 63.1k | } |
7720 | | |
7721 | 25.0k | if (!update_color_info) { |
7722 | | /* Profile not updated */ |
7723 | 2.25k | new_group_color->icc_profile = NULL; |
7724 | 2.25k | if_debug0m('v', pdev->memory, "[v]procs not updated\n"); |
7725 | 2.25k | return 0; |
7726 | 2.25k | } |
7727 | | |
7728 | 22.7k | if (has_tags) { |
7729 | 0 | new_num_comps++; |
7730 | | /* In planar mode, planes need to all be the same depth. Otherwise use 8 bits for tags. */ |
7731 | 0 | if (pdev->num_planar_planes > 0) |
7732 | 0 | new_depth += deep ? 16 : 8; |
7733 | 0 | else |
7734 | 0 | new_depth += 8; |
7735 | 0 | } |
7736 | 22.7k | if (pdev->sep_device && !is_mask) { |
7737 | 539 | int num_spots; |
7738 | | |
7739 | 539 | if (old_profile == NULL) |
7740 | 0 | return_error(gs_error_undefined); |
7741 | | |
7742 | 539 | num_spots = pdev->color_info.num_components - has_tags - old_profile->num_comps; |
7743 | | |
7744 | 539 | if (num_spots > 0) { |
7745 | 45 | new_num_comps += num_spots; |
7746 | 45 | new_depth = (8 << deep) * new_num_comps; |
7747 | 45 | } |
7748 | 539 | } |
7749 | | /* Calculate the bits and shifts *after* we have allowed for tags. */ |
7750 | 50.4k | for (k = 0; k < new_num_comps; k++) { |
7751 | 27.6k | comp_bits[k] = 8 << deep; |
7752 | 27.6k | comp_shift[k] = (new_num_comps - 1 - k) * (8 << deep); |
7753 | 27.6k | } |
7754 | 22.7k | if_debug2m('v', pdev->memory, |
7755 | 22.7k | "[v]pdf14_clist_push_color_model, num_components_old = %d num_components_new = %d\n", |
7756 | 22.7k | pdev->color_info.num_components, new_num_comps); |
7757 | | /* Set new information in the device */ |
7758 | 22.7k | { |
7759 | 22.7k | gx_device local_device; |
7760 | | |
7761 | 22.7k | local_device.initialize_device_procs = pdevproto->initialize_device_procs; |
7762 | 22.7k | local_device.initialize_device_procs((gx_device *)&local_device); |
7763 | 22.7k | set_dev_proc(pdev, get_color_mapping_procs, local_device.procs.get_color_mapping_procs); |
7764 | 22.7k | set_dev_proc(pdev, get_color_comp_index, local_device.procs.get_color_comp_index); |
7765 | 22.7k | } |
7766 | 22.7k | pdev->blend_procs = pdevproto->blend_procs; |
7767 | 22.7k | pdev->color_info.polarity = new_polarity; |
7768 | 22.7k | pdev->color_info.max_color = deep ? 65535 : 255; |
7769 | 22.7k | pdev->color_info.max_gray = deep ? 65535 : 255; |
7770 | 22.7k | pdev->pdf14_procs = new_14procs; |
7771 | 22.7k | if (pdev->num_planar_planes > 0) |
7772 | 2.66k | pdev->num_planar_planes += new_num_comps - pdev->color_info.num_components; |
7773 | 22.7k | pdev->color_info.num_components = new_num_comps; |
7774 | 22.7k | assert(pdev->num_planar_planes == 0 || pdev->num_planar_planes == pdev->color_info.num_components); |
7775 | 22.7k | pdev->color_info.depth = new_depth; |
7776 | 22.7k | memset(&(pdev->color_info.comp_bits), 0, GX_DEVICE_COLOR_MAX_COMPONENTS); |
7777 | 22.7k | memset(&(pdev->color_info.comp_shift), 0, GX_DEVICE_COLOR_MAX_COMPONENTS); |
7778 | 22.7k | memcpy(&(pdev->color_info.comp_bits), comp_bits, new_num_comps); |
7779 | 22.7k | memcpy(&(pdev->color_info.comp_shift), comp_shift, new_num_comps); |
7780 | 22.7k | pdev->color_info.opmsupported = GX_CINFO_OPMSUPPORTED_UNKNOWN; |
7781 | | |
7782 | | /* If we have a compressed color codec, and we are doing a soft mask |
7783 | | push operation then go ahead and update the color encode and |
7784 | | decode for the pdf14 device to not used compressed color |
7785 | | encoding while in the soft mask. We will just check for gray |
7786 | | and compressed. Note that we probably don't have_tags if we |
7787 | | are dealing with compressed color. But is is possible so |
7788 | | we add it in to catch for future use. */ |
7789 | 22.7k | cldev->clist_color_info.depth = pdev->color_info.depth; |
7790 | 22.7k | cldev->clist_color_info.polarity = pdev->color_info.polarity; |
7791 | 22.7k | cldev->clist_color_info.opmsupported = GX_CINFO_OPMSUPPORTED_UNKNOWN; |
7792 | 22.7k | cldev->clist_color_info.num_components = pdev->color_info.num_components; |
7793 | 22.7k | cldev->clist_color_info.max_color = pdev->color_info.max_color; |
7794 | 22.7k | cldev->clist_color_info.max_gray = pdev->color_info.max_gray; |
7795 | | /* For the ICC profiles, we want to update the ICC profile for the |
7796 | | device. We store the original in group_color. |
7797 | | That will be stored in the clist and restored during the reading phase. */ |
7798 | 22.7k | if (group_color_type == ICC) { |
7799 | 22.7k | gsicc_adjust_profile_rc(new_profile, 1, "pdf14_clist_push_color_model"); |
7800 | 22.7k | new_group_color->icc_profile = |
7801 | 22.7k | dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE]; |
7802 | 22.7k | dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] = new_profile; |
7803 | 22.7k | } |
7804 | 22.7k | if (pdev->ctx) { |
7805 | 0 | pdev->ctx->additive = new_additive; |
7806 | 0 | } |
7807 | 22.7k | return 1; /* Lets us detect that we did do an update */ |
7808 | 22.7k | } |
7809 | | |
7810 | | static int |
7811 | | pdf14_clist_pop_color_model(gx_device *dev, gs_gstate *pgs) |
7812 | 63.0k | { |
7813 | | |
7814 | 63.0k | pdf14_device *pdev = (pdf14_device *)dev; |
7815 | 63.0k | pdf14_group_color_t *group_color = pdev->color_model_stack; |
7816 | 63.0k | gx_device_clist_writer * cldev = (gx_device_clist_writer *)pdev->pclist_device; |
7817 | | |
7818 | 63.0k | if (group_color == NULL) |
7819 | 0 | return_error(gs_error_Fatal); /* Unmatched group pop */ |
7820 | | |
7821 | 63.0k | if_debug0m('v', pdev->memory, "[v]pdf14_clist_pop_color_model\n"); |
7822 | | /* The color procs are always pushed. Simply restore them. */ |
7823 | 63.0k | if (group_color->group_color_mapping_procs == NULL && |
7824 | 0 | group_color->group_color_comp_index == NULL) { |
7825 | 0 | if_debug0m('v', dev->memory, "[v]pdf14_clist_pop_color_model ERROR \n"); |
7826 | 63.0k | } else { |
7827 | 63.0k | bool has_tags = device_encodes_tags(dev); |
7828 | 63.0k | if_debug2m('v', pdev->memory, |
7829 | 63.0k | "[v]pdf14_clist_pop_color_model, num_components_old = %d num_components_new = %d\n", |
7830 | 63.0k | pdev->color_info.num_components,group_color->num_components); |
7831 | 63.0k | pgs->get_cmap_procs = group_color->get_cmap_procs; |
7832 | 63.0k | gx_set_cmap_procs(pgs, dev); |
7833 | 63.0k | set_dev_proc(pdev, get_color_mapping_procs, group_color->group_color_mapping_procs); |
7834 | 63.0k | set_dev_proc(pdev, get_color_comp_index, group_color->group_color_comp_index); |
7835 | 63.0k | pdev->color_info.polarity = group_color->polarity; |
7836 | 63.0k | pdev->color_info.opmsupported = GX_CINFO_OPMSUPPORTED_UNKNOWN; |
7837 | 63.0k | pdev->color_info.depth = group_color->depth; |
7838 | 63.0k | if (pdev->num_planar_planes > 0) |
7839 | 6.27k | pdev->num_planar_planes += group_color->num_components - (pdev->color_info.num_components - has_tags); |
7840 | 63.0k | pdev->color_info.num_components = group_color->num_components + has_tags; |
7841 | 63.0k | assert(pdev->num_planar_planes == 0 || pdev->num_planar_planes == pdev->color_info.num_components); |
7842 | 63.0k | assert(pdev->color_info.num_components - has_tags == group_color->num_components); |
7843 | 63.0k | pdev->blend_procs = group_color->blend_procs; |
7844 | 63.0k | pdev->pdf14_procs = group_color->unpack_procs; |
7845 | 63.0k | pdev->color_info.max_color = group_color->max_color; |
7846 | 63.0k | pdev->color_info.max_gray = group_color->max_gray; |
7847 | 63.0k | set_dev_proc(pdev, encode_color, group_color->encode); |
7848 | 63.0k | set_dev_proc(pdev, decode_color, group_color->decode); |
7849 | 63.0k | memcpy(&(pdev->color_info.comp_bits),&(group_color->comp_bits), |
7850 | 63.0k | GX_DEVICE_COLOR_MAX_COMPONENTS); |
7851 | 63.0k | memcpy(&(pdev->color_info.comp_shift),&(group_color->comp_shift), |
7852 | 63.0k | GX_DEVICE_COLOR_MAX_COMPONENTS); |
7853 | | |
7854 | | /* clist writer fill rect has no access to gs_gstate */ |
7855 | | /* and it forwards the target device. this information */ |
7856 | | /* is passed along to use in this case */ |
7857 | 63.0k | cldev->clist_color_info.depth = pdev->color_info.depth; |
7858 | 63.0k | cldev->clist_color_info.polarity = pdev->color_info.polarity; |
7859 | 63.0k | cldev->clist_color_info.opmsupported = GX_CINFO_OPMSUPPORTED_UNKNOWN; |
7860 | 63.0k | cldev->clist_color_info.num_components = pdev->color_info.num_components; |
7861 | 63.0k | cldev->clist_color_info.max_color = pdev->color_info.max_color; |
7862 | 63.0k | cldev->clist_color_info.max_gray = pdev->color_info.max_gray; |
7863 | 63.0k | memcpy(&(cldev->clist_color_info.comp_bits),&(group_color->comp_bits), |
7864 | 63.0k | GX_DEVICE_COLOR_MAX_COMPONENTS); |
7865 | 63.0k | memcpy(&(cldev->clist_color_info.comp_shift),&(group_color->comp_shift), |
7866 | 63.0k | GX_DEVICE_COLOR_MAX_COMPONENTS); |
7867 | 63.0k | if (pdev->ctx){ |
7868 | 0 | pdev->ctx->additive = group_color->isadditive; |
7869 | 0 | } |
7870 | | /* The device profile must be restored. */ |
7871 | 63.0k | if (group_color->icc_profile != NULL) { |
7872 | 22.7k | gsicc_adjust_profile_rc(dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], |
7873 | 22.7k | -1, "pdf14_clist_pop_color_model"); |
7874 | 22.7k | dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] = group_color->icc_profile; |
7875 | 22.7k | } |
7876 | 63.0k | if_debug0m('v', dev->memory, "[v]procs updated\n"); |
7877 | 63.0k | } |
7878 | 63.0k | pdf14_pop_group_color(dev, pgs); |
7879 | 63.0k | return 0; |
7880 | 63.0k | } |
7881 | | |
7882 | | /* When a transparency group is popped, the parent colorprocs must be restored. |
7883 | | Since the color mapping procs are all based upon the device, we must have a |
7884 | | nested list based upon the transparency group color space. This nesting |
7885 | | must be outside the nested ctx structures to allow the nesting for the |
7886 | | clist writer */ |
7887 | | static void |
7888 | | pdf14_pop_group_color(gx_device *dev, const gs_gstate *pgs) |
7889 | 63.1k | { |
7890 | 63.1k | pdf14_device *pdev = (pdf14_device *)dev; |
7891 | 63.1k | pdf14_group_color_t *group_color = pdev->color_model_stack; |
7892 | | |
7893 | 63.1k | if_debug0m('v', dev->memory, "[v]pdf14_pop_group_color\n"); |
7894 | | |
7895 | | /* Update the link */ |
7896 | 63.1k | pdev->color_model_stack = group_color->previous; |
7897 | | |
7898 | | /* Free the old one */ |
7899 | 63.1k | gs_free_object(dev->memory->stable_memory, group_color, "pdf14_clr_free"); |
7900 | 63.1k | } |
7901 | | |
7902 | | static int |
7903 | | pdf14_begin_transparency_mask(gx_device *dev, |
7904 | | const gx_transparency_mask_params_t *ptmp, |
7905 | | const gs_rect *pbbox, |
7906 | | gs_gstate *pgs, gs_memory_t *mem) |
7907 | 4.23M | { |
7908 | 4.23M | pdf14_device *pdev = (pdf14_device *)dev; |
7909 | 4.23M | uint16_t bg_alpha = 0; /* By default the background alpha (area outside mask) is zero */ |
7910 | 4.23M | byte *transfer_fn; |
7911 | 4.23M | gs_int_rect rect; |
7912 | 4.23M | int code; |
7913 | 4.23M | int group_color_numcomps; |
7914 | 4.23M | gs_transparency_color_t group_color_type; |
7915 | 4.23M | bool deep = device_is_deep(dev); |
7916 | 4.23M | pdf14_group_color_t* group_color_info; |
7917 | | |
7918 | 4.23M | code = pdf14_initialize_ctx(dev, pgs); |
7919 | 4.23M | if (code < 0) |
7920 | 0 | return code; |
7921 | | |
7922 | 4.23M | if (ptmp->subtype == TRANSPARENCY_MASK_None) { |
7923 | 3.80M | pdf14_ctx *ctx = pdev->ctx; |
7924 | | |
7925 | | /* free up any maskbuf on the current tos */ |
7926 | 3.80M | if (ctx->mask_stack != NULL && ctx->mask_stack->mask_buf != NULL ) { |
7927 | 338k | pdf14_buf_free(ctx->mask_stack->mask_buf); |
7928 | 338k | ctx->mask_stack->mask_buf = NULL; |
7929 | 338k | } |
7930 | 3.80M | return 0; |
7931 | 3.80M | } |
7932 | 433k | transfer_fn = (byte *)gs_alloc_bytes(pdev->ctx->memory, (256+deep)<<deep, |
7933 | 433k | "pdf14_begin_transparency_mask"); |
7934 | 433k | if (transfer_fn == NULL) |
7935 | 0 | return_error(gs_error_VMerror); |
7936 | 433k | code = compute_group_device_int_rect(pdev, &rect, pbbox, pgs); |
7937 | 433k | if (code < 0) |
7938 | 0 | return code; |
7939 | | /* If we have background components the background alpha may be nonzero */ |
7940 | 433k | if (ptmp->Background_components) |
7941 | 51.1k | bg_alpha = (int)(65535 * ptmp->GrayBackground + 0.5); |
7942 | 433k | if_debug1m('v', dev->memory, |
7943 | 433k | "pdf14_begin_transparency_mask, bg_alpha = %d\n", bg_alpha); |
7944 | 433k | memcpy(transfer_fn, ptmp->transfer_fn, (256+deep)<<deep); |
7945 | | /* If the group color is unknown, then we must use the previous group color |
7946 | | space or the device process color space */ |
7947 | 433k | if (ptmp->group_color_type == UNKNOWN){ |
7948 | 0 | if (pdev->ctx->stack){ |
7949 | | /* Use previous group color space */ |
7950 | 0 | group_color_numcomps = pdev->ctx->stack->n_chan-1; /* Remove alpha */ |
7951 | 0 | } else { |
7952 | | /* Use process color space */ |
7953 | 0 | group_color_numcomps = pdev->color_info.num_components; |
7954 | 0 | } |
7955 | 0 | switch (group_color_numcomps) { |
7956 | 0 | case 1: |
7957 | 0 | group_color_type = GRAY_SCALE; |
7958 | 0 | break; |
7959 | 0 | case 3: |
7960 | 0 | group_color_type = DEVICE_RGB; |
7961 | 0 | break; |
7962 | 0 | case 4: |
7963 | 0 | group_color_type = DEVICE_CMYK; |
7964 | 0 | break; |
7965 | 0 | default: |
7966 | | /* We can end up here if we are in a deviceN color space and |
7967 | | we have a sep output device */ |
7968 | 0 | group_color_type = DEVICEN; |
7969 | 0 | break; |
7970 | 0 | } |
7971 | 433k | } else { |
7972 | 433k | group_color_type = ptmp->group_color_type; |
7973 | 433k | group_color_numcomps = ptmp->group_color_numcomps; |
7974 | 433k | } |
7975 | | |
7976 | 433k | group_color_info = pdf14_push_color_model(dev, group_color_type, ptmp->icc_hashcode, |
7977 | 433k | ptmp->iccprofile, true); |
7978 | 433k | if (group_color_info == NULL) |
7979 | 0 | return gs_error_VMerror; |
7980 | | |
7981 | | /* Note that the soft mask always follows the group color requirements even |
7982 | | when we have a separable device */ |
7983 | 433k | code = pdf14_push_transparency_mask(pdev->ctx, &rect, bg_alpha, |
7984 | 433k | transfer_fn, ptmp->function_is_identity, |
7985 | 433k | ptmp->idle, ptmp->replacing, |
7986 | 433k | ptmp->mask_id, ptmp->subtype, |
7987 | 433k | group_color_numcomps, |
7988 | 433k | ptmp->Background_components, |
7989 | 433k | ptmp->Background, |
7990 | 433k | ptmp->Matte_components, |
7991 | 433k | ptmp->Matte, |
7992 | 433k | ptmp->GrayBackground, |
7993 | 433k | group_color_info); |
7994 | 433k | if (code < 0) |
7995 | 0 | return code; |
7996 | | |
7997 | 433k | return 0; |
7998 | 433k | } |
7999 | | |
8000 | | static int |
8001 | | pdf14_end_transparency_mask(gx_device *dev, gs_gstate *pgs) |
8002 | 433k | { |
8003 | 433k | pdf14_device *pdev = (pdf14_device *)dev; |
8004 | 433k | pdf14_group_color_t *group_color; |
8005 | 433k | int ok; |
8006 | 433k | bool has_tags = device_encodes_tags(dev); |
8007 | | |
8008 | 433k | if_debug0m('v', dev->memory, "pdf14_end_transparency_mask\n"); |
8009 | 433k | ok = pdf14_pop_transparency_mask(pdev->ctx, pgs, dev); |
8010 | | #ifdef DEBUG |
8011 | | pdf14_debug_mask_stack_state(pdev->ctx); |
8012 | | #endif |
8013 | | |
8014 | | /* May need to reset some color stuff related |
8015 | | * to a mismatch between the Smask color space |
8016 | | * and the Smask blending space */ |
8017 | 433k | if (pdev->ctx->stack != NULL ) { |
8018 | 433k | group_color = pdev->ctx->stack->group_color_info; |
8019 | 433k | if (!(group_color->group_color_mapping_procs == NULL && |
8020 | 433k | group_color->group_color_comp_index == NULL)) { |
8021 | 433k | pgs->get_cmap_procs = group_color->get_cmap_procs; |
8022 | 433k | gx_set_cmap_procs(pgs, dev); |
8023 | 433k | set_dev_proc(pdev, get_color_mapping_procs, group_color->group_color_mapping_procs); |
8024 | 433k | set_dev_proc(pdev, get_color_comp_index, group_color->group_color_comp_index); |
8025 | 433k | pdev->color_info.polarity = group_color->polarity; |
8026 | 433k | pdev->color_info.opmsupported = GX_CINFO_OPMSUPPORTED_UNKNOWN; |
8027 | 433k | if (pdev->num_planar_planes > 0) |
8028 | 28.3k | pdev->num_planar_planes += group_color->num_components - (pdev->color_info.num_components - has_tags); |
8029 | 433k | pdev->color_info.num_components = group_color->num_components + has_tags; |
8030 | 433k | assert(pdev->num_planar_planes == 0 || pdev->num_planar_planes == pdev->color_info.num_components); |
8031 | 433k | assert(pdev->color_info.num_components - has_tags == group_color->num_components); |
8032 | 433k | pdev->num_std_colorants = group_color->num_std_colorants; |
8033 | 433k | pdev->color_info.depth = group_color->depth; |
8034 | 433k | pdev->blend_procs = group_color->blend_procs; |
8035 | 433k | pdev->ctx->additive = group_color->isadditive; |
8036 | 433k | pdev->pdf14_procs = group_color->unpack_procs; |
8037 | 433k | pdev->color_info.max_color = group_color->max_color; |
8038 | 433k | pdev->color_info.max_gray = group_color->max_gray; |
8039 | 433k | set_dev_proc(pdev, encode_color, group_color->encode); |
8040 | 433k | set_dev_proc(pdev, decode_color, group_color->decode); |
8041 | 433k | memcpy(&(pdev->color_info.comp_bits),&(group_color->comp_bits), |
8042 | 433k | GX_DEVICE_COLOR_MAX_COMPONENTS); |
8043 | 433k | memcpy(&(pdev->color_info.comp_shift),&(group_color->comp_shift), |
8044 | 433k | GX_DEVICE_COLOR_MAX_COMPONENTS); |
8045 | | /* Take care of the ICC profile */ |
8046 | 433k | if (group_color->icc_profile != NULL) { |
8047 | 433k | gsicc_adjust_profile_rc(dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], |
8048 | 433k | -1, "pdf14_end_transparency_mask"); |
8049 | 433k | dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] = group_color->icc_profile; |
8050 | 433k | gsicc_adjust_profile_rc(dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], |
8051 | 433k | 1, "pdf14_end_transparency_mask"); |
8052 | 433k | } |
8053 | 433k | } |
8054 | 433k | } |
8055 | 433k | return ok; |
8056 | 433k | } |
8057 | | |
8058 | | static int |
8059 | | do_mark_fill_rectangle_ko_simple(gx_device *dev, int x, int y, int w, int h, |
8060 | | gx_color_index color, |
8061 | | const gx_device_color *pdc, bool devn) |
8062 | 2.32M | { |
8063 | 2.32M | pdf14_device *pdev = (pdf14_device *)dev; |
8064 | 2.32M | pdf14_buf *buf = pdev->ctx->stack; |
8065 | 2.32M | gs_blend_mode_t blend_mode = pdev->blend_mode; |
8066 | 2.32M | bool tag_blend = blend_mode == BLEND_MODE_Normal || |
8067 | 203k | blend_mode == BLEND_MODE_Compatible || |
8068 | 203k | blend_mode == BLEND_MODE_CompatibleOverprint; |
8069 | 2.32M | int i, j, k; |
8070 | 2.32M | byte *bline, *bg_ptr, *line, *dst_ptr; |
8071 | 2.32M | byte src[PDF14_MAX_PLANES]; |
8072 | 2.32M | byte dst[PDF14_MAX_PLANES] = { 0 }; |
8073 | 2.32M | byte dst2[PDF14_MAX_PLANES] = { 0 }; |
8074 | 2.32M | intptr_t rowstride = buf->rowstride; |
8075 | 2.32M | intptr_t planestride = buf->planestride; |
8076 | 2.32M | int num_chan = buf->n_chan; |
8077 | 2.32M | int num_comp = num_chan - 1; |
8078 | 2.32M | intptr_t shape_off = num_chan * planestride; |
8079 | 2.32M | bool has_shape = buf->has_shape; |
8080 | 2.32M | bool has_alpha_g = buf->has_alpha_g; |
8081 | 2.32M | intptr_t alpha_g_off = shape_off + (has_shape ? planestride : 0); |
8082 | 2.32M | intptr_t tag_off = shape_off + (has_alpha_g ? planestride : 0) + |
8083 | 2.32M | (has_shape ? planestride : 0); |
8084 | 2.32M | bool has_tags = buf->has_tags; |
8085 | 2.32M | bool additive = pdev->ctx->additive; |
8086 | 2.32M | gs_graphics_type_tag_t curr_tag = GS_UNKNOWN_TAG; /* Quiet compiler */ |
8087 | 2.32M | gx_color_index mask = ((gx_color_index)1 << 8) - 1; |
8088 | 2.32M | int shift = 8; |
8089 | 2.32M | byte shape = 0; /* Quiet compiler. */ |
8090 | 2.32M | byte src_alpha; |
8091 | 2.32M | bool overprint = pdev->op_state == PDF14_OP_STATE_FILL ? pdev->overprint : pdev->stroke_overprint; |
8092 | 2.32M | gx_color_index drawn_comps = pdev->op_state == PDF14_OP_STATE_FILL ? |
8093 | 1.86M | pdev->drawn_comps_fill : pdev->drawn_comps_stroke; |
8094 | 2.32M | gx_color_index comps; |
8095 | 2.32M | bool has_backdrop = buf->backdrop != NULL; |
8096 | | |
8097 | | /* If we are going out to a CMYK or CMYK + spots pdf14 device (i.e. |
8098 | | subtractive) and we are doing overprint with drawn_comps == 0 |
8099 | | then this is a no-operation */ |
8100 | 2.32M | if (overprint && drawn_comps == 0 && !buf->group_color_info->isadditive) |
8101 | 0 | return 0; |
8102 | | |
8103 | 2.32M | if (buf->data == NULL) |
8104 | 1 | return 0; |
8105 | | #if 0 |
8106 | | if (sizeof(color) <= sizeof(ulong)) |
8107 | | if_debug6m('v', dev->memory, |
8108 | | "[v]pdf14_mark_fill_rectangle_ko_simple, (%d, %d), %d x %d color = %lx, nc %d,\n", |
8109 | | x, y, w, h, (ulong)color, num_chan); |
8110 | | else |
8111 | | if_debug7m('v', dev->memory, |
8112 | | "[v]pdf14_mark_fill_rectangle_ko_simple, (%d, %d), %d x %d color = %8lx%08lx, nc %d,\n", |
8113 | | x, y, w, h, |
8114 | | (ulong)(color >> 8*(sizeof(color) - sizeof(ulong))), (ulong)color, |
8115 | | num_chan); |
8116 | | #endif |
8117 | | /* |
8118 | | * Unpack the gx_color_index values. Complement the components for subtractive |
8119 | | * color spaces. |
8120 | | */ |
8121 | 2.32M | if (devn) { |
8122 | 76.5k | if (has_tags) { |
8123 | 0 | curr_tag = pdc->tag; |
8124 | 0 | } |
8125 | 76.5k | if (additive) { |
8126 | 109k | for (j = 0; j < num_comp; j++) { |
8127 | 82.2k | src[j] = ((pdc->colors.devn.values[j]) >> shift & mask); |
8128 | 82.2k | } |
8129 | 49.0k | } else { |
8130 | 245k | for (j = 0; j < num_comp; j++) { |
8131 | 196k | src[j] = 255 - ((pdc->colors.devn.values[j]) >> shift & mask); |
8132 | 196k | } |
8133 | 49.0k | } |
8134 | 2.25M | } else { |
8135 | 2.25M | if (has_tags) { |
8136 | 0 | curr_tag = (color >> (num_comp * 8)) & 0xff; |
8137 | 0 | } |
8138 | 2.25M | pdev->pdf14_procs->unpack_color(num_comp, color, pdev, src); |
8139 | 2.25M | } |
8140 | | |
8141 | 2.32M | if (!has_tags) |
8142 | 2.32M | tag_off = 0; |
8143 | | |
8144 | 2.32M | src_alpha = src[num_comp] = (byte)floor (255 * pdev->alpha + 0.5); |
8145 | 2.32M | if (has_shape) { |
8146 | 907 | shape = (byte)floor (255 * pdev->shape + 0.5); |
8147 | 2.32M | } else { |
8148 | 2.32M | shape_off = 0; |
8149 | 2.32M | } |
8150 | | |
8151 | 2.32M | if (!has_alpha_g) |
8152 | 0 | alpha_g_off = 0; |
8153 | 2.32M | src_alpha = 255 - src_alpha; |
8154 | 2.32M | shape = 255 - shape; |
8155 | | |
8156 | | /* Fit the mark into the bounds of the buffer */ |
8157 | 2.32M | if (x < buf->rect.p.x) { |
8158 | 0 | w += x - buf->rect.p.x; |
8159 | 0 | x = buf->rect.p.x; |
8160 | 0 | } |
8161 | 2.32M | if (y < buf->rect.p.y) { |
8162 | 10 | h += y - buf->rect.p.y; |
8163 | 10 | y = buf->rect.p.y; |
8164 | 10 | } |
8165 | 2.32M | if (x + w > buf->rect.q.x) w = buf->rect.q.x - x; |
8166 | 2.32M | if (y + h > buf->rect.q.y) h = buf->rect.q.y - y; |
8167 | | /* Update the dirty rectangle with the mark. */ |
8168 | 2.32M | if (x < buf->dirty.p.x) buf->dirty.p.x = x; |
8169 | 2.32M | if (y < buf->dirty.p.y) buf->dirty.p.y = y; |
8170 | 2.32M | if (x + w > buf->dirty.q.x) buf->dirty.q.x = x + w; |
8171 | 2.32M | if (y + h > buf->dirty.q.y) buf->dirty.q.y = y + h; |
8172 | | |
8173 | | /* composite with backdrop only. */ |
8174 | 2.32M | if (has_backdrop) |
8175 | 2.32M | bline = buf->backdrop + (x - buf->rect.p.x) + (y - buf->rect.p.y) * rowstride; |
8176 | 0 | else |
8177 | 0 | bline = NULL; |
8178 | | |
8179 | 2.32M | line = buf->data + (x - buf->rect.p.x) + (y - buf->rect.p.y) * rowstride; |
8180 | | |
8181 | 4.92M | for (j = 0; j < h; ++j) { |
8182 | 2.59M | bg_ptr = bline; |
8183 | 2.59M | dst_ptr = line; |
8184 | 113M | for (i = 0; i < w; ++i) { |
8185 | | /* Complement the components for subtractive color spaces */ |
8186 | 110M | if (has_backdrop) { |
8187 | 110M | if (additive) { |
8188 | 390M | for (k = 0; k < num_comp; ++k) |
8189 | 282M | dst[k] = bg_ptr[k * planestride]; |
8190 | 107M | } else { |
8191 | 14.8M | for (k = 0; k < num_comp; ++k) |
8192 | 11.8M | dst2[k] = dst[k] = 255 - bg_ptr[k * planestride]; |
8193 | 2.96M | } |
8194 | 110M | dst2[num_comp] = dst[num_comp] = bg_ptr[num_comp * planestride]; /* alpha doesn't invert */ |
8195 | 110M | } |
8196 | 110M | if (buf->isolated || !has_backdrop) { |
8197 | 0 | art_pdf_knockoutisolated_group_8(dst, src, num_comp); |
8198 | 110M | } else { |
8199 | 110M | art_pdf_composite_knockout_8(dst, src, num_comp, |
8200 | 110M | blend_mode, pdev->blend_procs, pdev); |
8201 | 110M | } |
8202 | | /* Complement the results for subtractive color spaces */ |
8203 | 110M | if (additive) { |
8204 | 107M | if (!overprint) { |
8205 | 498M | for (k = 0; k < num_chan; ++k) |
8206 | 390M | dst_ptr[k * planestride] = dst[k]; |
8207 | 107M | } else { |
8208 | | /* Hybrid additive with subtractive spots */ |
8209 | | /* We may have to do the compatible overprint blending */ |
8210 | 51.1k | if (!buf->isolated && drawn_comps != (((size_t)1 << (size_t)dev->color_info.num_components) - (size_t)1)) { |
8211 | 0 | art_pdf_composite_knockout_8(dst2, src, num_comp, |
8212 | 0 | blend_mode, pdev->blend_procs, pdev); |
8213 | 0 | } |
8214 | 204k | for (k = 0, comps = drawn_comps; k < num_comp; ++k, comps >>= 1) { |
8215 | 153k | if ((comps & 0x1) != 0) { |
8216 | 153k | dst_ptr[k * planestride] = dst[k]; |
8217 | 153k | } else { |
8218 | | /* Compatible overprint blend result. */ |
8219 | 0 | dst_ptr[k * planestride] = dst2[k]; |
8220 | 0 | } |
8221 | 153k | } |
8222 | 51.1k | dst_ptr[num_comp * planestride] = dst[num_comp]; /* alpha */ |
8223 | 51.1k | } |
8224 | 107M | } else { |
8225 | 2.96M | if (overprint) { |
8226 | | /* We may have to do the compatible overprint blending */ |
8227 | 0 | if (!buf->isolated && drawn_comps != (( (size_t) 1 << (size_t) dev->color_info.num_components)-(size_t) 1)) { |
8228 | 0 | art_pdf_composite_knockout_8(dst2, src, num_comp, |
8229 | 0 | blend_mode, pdev->blend_procs, pdev); |
8230 | 0 | } |
8231 | 0 | for (k = 0, comps = drawn_comps; k < num_comp; ++k, comps >>= 1) { |
8232 | 0 | if ((comps & 0x1) != 0) { |
8233 | 0 | dst_ptr[k * planestride] = 255 - dst[k]; |
8234 | 0 | } else { |
8235 | | /* Compatible overprint blend result. */ |
8236 | 0 | dst_ptr[k * planestride] = 255 - dst2[k]; |
8237 | 0 | } |
8238 | 0 | } |
8239 | 2.96M | } else { |
8240 | 14.8M | for (k = 0; k < num_comp; ++k) |
8241 | 11.8M | dst_ptr[k * planestride] = 255 - dst[k]; |
8242 | 2.96M | } |
8243 | 2.96M | dst_ptr[num_comp * planestride] = dst[num_comp]; |
8244 | 2.96M | } |
8245 | 110M | if (tag_off) { |
8246 | | /* If src alpha is 100% then set to curr_tag, else or */ |
8247 | | /* other than Normal BM, we always OR */ |
8248 | 0 | if (src[num_comp] == 255 && tag_blend) { |
8249 | 0 | dst_ptr[tag_off] = curr_tag; |
8250 | 0 | } else { |
8251 | 0 | dst_ptr[tag_off] |= curr_tag; |
8252 | 0 | } |
8253 | 0 | } |
8254 | | /* Knockout group alpha and shape too */ |
8255 | 110M | if (alpha_g_off) |
8256 | 110M | dst_ptr[alpha_g_off] = 255 - src_alpha; |
8257 | 110M | if (shape_off) |
8258 | 1.91k | dst_ptr[shape_off] = 255 - shape; |
8259 | 110M | ++dst_ptr; |
8260 | 110M | if (has_backdrop) |
8261 | 110M | ++bg_ptr; |
8262 | 110M | } |
8263 | 2.59M | bline += rowstride; |
8264 | 2.59M | line += rowstride; |
8265 | 2.59M | } |
8266 | | #if 0 |
8267 | | /* #if RAW_DUMP */ |
8268 | | /* Dump the current buffer to see what we have. */ |
8269 | | dump_raw_buffer(pdev->ctx->memory, |
8270 | | pdev->ctx->stack->rect.q.y-pdev->ctx->stack->rect.p.y, |
8271 | | pdev->ctx->stack->rect.q.x-pdev->ctx->stack->rect.p.x, |
8272 | | pdev->ctx->stack->n_planes, |
8273 | | pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride, |
8274 | | "Draw_Rect_KO", pdev->ctx->stack->data, |
8275 | | pdev->ctx->stack->deep); |
8276 | | global_index++; |
8277 | | #endif |
8278 | 2.32M | return 0; |
8279 | 2.32M | } |
8280 | | |
8281 | | static int |
8282 | | do_mark_fill_rectangle_ko_simple16(gx_device *dev, int x, int y, int w, int h, |
8283 | | gx_color_index color, |
8284 | | const gx_device_color *pdc, bool devn) |
8285 | 0 | { |
8286 | 0 | pdf14_device *pdev = (pdf14_device *)dev; |
8287 | 0 | pdf14_buf *buf = pdev->ctx->stack; |
8288 | 0 | gs_blend_mode_t blend_mode = pdev->blend_mode; |
8289 | 0 | bool tag_blend = blend_mode == BLEND_MODE_Normal || |
8290 | 0 | blend_mode == BLEND_MODE_Compatible || |
8291 | 0 | blend_mode == BLEND_MODE_CompatibleOverprint; |
8292 | 0 | int i, j, k; |
8293 | 0 | uint16_t *bline, *bg_ptr, *line, *dst_ptr; |
8294 | 0 | uint16_t src[PDF14_MAX_PLANES]; |
8295 | 0 | uint16_t dst[PDF14_MAX_PLANES] = { 0 }; |
8296 | 0 | uint16_t dst2[PDF14_MAX_PLANES] = { 0 }; |
8297 | 0 | intptr_t rowstride = buf->rowstride; |
8298 | 0 | intptr_t planestride = buf->planestride; |
8299 | 0 | int num_chan = buf->n_chan; |
8300 | 0 | int num_comp = num_chan - 1; |
8301 | 0 | intptr_t shape_off = num_chan * planestride; |
8302 | 0 | bool has_shape = buf->has_shape; |
8303 | 0 | bool has_alpha_g = buf->has_alpha_g; |
8304 | 0 | intptr_t alpha_g_off = shape_off + (has_shape ? planestride : 0); |
8305 | 0 | intptr_t tag_off = shape_off + (has_alpha_g ? planestride : 0) + |
8306 | 0 | (has_shape ? planestride : 0); |
8307 | 0 | bool has_tags = buf->has_tags; |
8308 | 0 | bool additive = pdev->ctx->additive; |
8309 | 0 | gs_graphics_type_tag_t curr_tag = GS_UNKNOWN_TAG; /* Quiet compiler */ |
8310 | 0 | uint16_t shape = 0; /* Quiet compiler. */ |
8311 | 0 | uint16_t src_alpha; |
8312 | 0 | bool overprint = pdev->op_state == PDF14_OP_STATE_FILL ? pdev->overprint : pdev->stroke_overprint; |
8313 | 0 | gx_color_index drawn_comps = pdev->op_state == PDF14_OP_STATE_FILL ? |
8314 | 0 | pdev->drawn_comps_fill : pdev->drawn_comps_stroke; |
8315 | 0 | gx_color_index comps; |
8316 | 0 | bool has_backdrop = buf->backdrop != NULL; |
8317 | | |
8318 | | /* If we are going out to a CMYK or CMYK + spots pdf14 device (i.e. |
8319 | | subtractive) and we are doing overprint with drawn_comps == 0 |
8320 | | then this is a no-operation */ |
8321 | 0 | if (overprint && drawn_comps == 0 && !buf->group_color_info->isadditive) |
8322 | 0 | return 0; |
8323 | | |
8324 | 0 | if (buf->data == NULL) |
8325 | 0 | return 0; |
8326 | | #if 0 |
8327 | | if (sizeof(color) <= sizeof(ulong)) |
8328 | | if_debug6m('v', dev->memory, |
8329 | | "[v]pdf14_mark_fill_rectangle_ko_simple16, (%d, %d), %d x %d color = %lx, nc %d,\n", |
8330 | | x, y, w, h, (ulong)color, num_chan); |
8331 | | else |
8332 | | if_debug7m('v', dev->memory, |
8333 | | "[v]pdf14_mark_fill_rectangle_ko_simple16, (%d, %d), %d x %d color = %8lx%08lx, nc %d,\n", |
8334 | | x, y, w, h, |
8335 | | (ulong)(color >> 8*(sizeof(color) - sizeof(ulong))), (ulong)color, |
8336 | | num_chan); |
8337 | | #endif |
8338 | | /* |
8339 | | * Unpack the gx_color_index values. Complement the components for subtractive |
8340 | | * color spaces. |
8341 | | */ |
8342 | 0 | if (devn) { |
8343 | 0 | if (has_tags) { |
8344 | 0 | curr_tag = pdc->tag; |
8345 | 0 | } |
8346 | 0 | if (additive) { |
8347 | 0 | for (j = 0; j < num_comp; j++) { |
8348 | 0 | src[j] = pdc->colors.devn.values[j]; |
8349 | 0 | } |
8350 | 0 | } else { |
8351 | 0 | for (j = 0; j < num_comp; j++) { |
8352 | 0 | src[j] = 65535 - pdc->colors.devn.values[j]; |
8353 | 0 | } |
8354 | 0 | } |
8355 | 0 | } else { |
8356 | 0 | if (has_tags) { |
8357 | 0 | curr_tag = (color >> (num_comp * 16)) & 0xff; |
8358 | 0 | } |
8359 | 0 | pdev->pdf14_procs->unpack_color16(num_comp, color, pdev, src); |
8360 | 0 | } |
8361 | |
|
8362 | 0 | src_alpha = src[num_comp] = (uint16_t)floor (65535 * pdev->alpha + 0.5); |
8363 | 0 | if (has_shape) { |
8364 | 0 | shape = (uint16_t)floor (65535 * pdev->shape + 0.5); |
8365 | 0 | } else { |
8366 | 0 | shape_off = 0; |
8367 | 0 | } |
8368 | |
|
8369 | 0 | if (!has_tags) { |
8370 | 0 | tag_off = 0; |
8371 | 0 | } |
8372 | |
|
8373 | 0 | if (!has_alpha_g) |
8374 | 0 | alpha_g_off = 0; |
8375 | 0 | src_alpha = 65535 - src_alpha; |
8376 | 0 | shape = 65535 - shape; |
8377 | | |
8378 | | /* Fit the mark into the bounds of the buffer */ |
8379 | 0 | if (x < buf->rect.p.x) { |
8380 | 0 | w += x - buf->rect.p.x; |
8381 | 0 | x = buf->rect.p.x; |
8382 | 0 | } |
8383 | 0 | if (y < buf->rect.p.y) { |
8384 | 0 | h += y - buf->rect.p.y; |
8385 | 0 | y = buf->rect.p.y; |
8386 | 0 | } |
8387 | 0 | if (x + w > buf->rect.q.x) w = buf->rect.q.x - x; |
8388 | 0 | if (y + h > buf->rect.q.y) h = buf->rect.q.y - y; |
8389 | | /* Update the dirty rectangle with the mark. */ |
8390 | 0 | if (x < buf->dirty.p.x) buf->dirty.p.x = x; |
8391 | 0 | if (y < buf->dirty.p.y) buf->dirty.p.y = y; |
8392 | 0 | if (x + w > buf->dirty.q.x) buf->dirty.q.x = x + w; |
8393 | 0 | if (y + h > buf->dirty.q.y) buf->dirty.q.y = y + h; |
8394 | | |
8395 | | |
8396 | | /* composite with backdrop only. */ |
8397 | 0 | if (has_backdrop) |
8398 | 0 | bline = (uint16_t*)(void*)(buf->backdrop + (x - buf->rect.p.x) * 2 + (y - buf->rect.p.y) * rowstride); |
8399 | 0 | else |
8400 | 0 | bline = NULL; |
8401 | |
|
8402 | 0 | line = (uint16_t *)(void *)(buf->data + (x - buf->rect.p.x)*2 + (y - buf->rect.p.y) * rowstride); |
8403 | 0 | planestride >>= 1; |
8404 | 0 | rowstride >>= 1; |
8405 | 0 | alpha_g_off >>= 1; |
8406 | 0 | shape_off >>= 1; |
8407 | 0 | tag_off >>= 1; |
8408 | |
|
8409 | 0 | for (j = 0; j < h; ++j) { |
8410 | 0 | bg_ptr = bline; |
8411 | 0 | dst_ptr = line; |
8412 | 0 | for (i = 0; i < w; ++i) { |
8413 | | /* Complement the components for subtractive color spaces */ |
8414 | 0 | if (has_backdrop) { |
8415 | 0 | if (additive) { |
8416 | 0 | for (k = 0; k < num_comp; ++k) |
8417 | 0 | dst[k] = bg_ptr[k * planestride]; |
8418 | 0 | } else { |
8419 | 0 | for (k = 0; k < num_comp; ++k) |
8420 | 0 | dst2[k] = dst[k] = 65535 - bg_ptr[k * planestride]; |
8421 | 0 | } |
8422 | 0 | dst2[num_comp] = dst[num_comp] = bg_ptr[num_comp * planestride]; /* alpha doesn't invert */ |
8423 | 0 | } |
8424 | 0 | if (buf->isolated || !has_backdrop) { |
8425 | 0 | art_pdf_knockoutisolated_group_16(dst, src, num_comp); |
8426 | 0 | } else { |
8427 | 0 | art_pdf_composite_knockout_16(dst, src, num_comp, |
8428 | 0 | blend_mode, pdev->blend_procs, pdev); |
8429 | 0 | } |
8430 | | /* Complement the results for subtractive color spaces */ |
8431 | 0 | if (additive) { |
8432 | 0 | if (!overprint) { |
8433 | 0 | for (k = 0; k < num_chan; ++k) |
8434 | 0 | dst_ptr[k * planestride] = dst[k]; |
8435 | 0 | } else { |
8436 | | /* Hybrid additive with subtractive spots */ |
8437 | | /* We may have to do the compatible overprint blending */ |
8438 | 0 | if (!buf->isolated && drawn_comps != (((size_t)1 << (size_t)dev->color_info.num_components) - (size_t)1)) { |
8439 | 0 | art_pdf_composite_knockout_16(dst2, src, num_comp, |
8440 | 0 | blend_mode, pdev->blend_procs, pdev); |
8441 | 0 | } |
8442 | 0 | for (k = 0, comps = drawn_comps; k < num_comp; ++k, comps >>= 1) { |
8443 | 0 | if ((comps & 0x1) != 0) { |
8444 | 0 | dst_ptr[k * planestride] = dst[k]; |
8445 | 0 | } else { |
8446 | | /* Compatible overprint blend result. */ |
8447 | 0 | dst_ptr[k * planestride] = dst2[k]; |
8448 | 0 | } |
8449 | 0 | } |
8450 | 0 | dst_ptr[num_comp * planestride] = dst[num_comp]; /* alpha */ |
8451 | 0 | } |
8452 | 0 | } else { |
8453 | 0 | if (overprint) { |
8454 | | /* We may have to do the compatible overprint blending */ |
8455 | 0 | if (!buf->isolated && drawn_comps != (((size_t)1 << (size_t)dev->color_info.num_components) - (size_t)1)) { |
8456 | 0 | art_pdf_composite_knockout_16(dst2, src, num_comp, |
8457 | 0 | blend_mode, pdev->blend_procs, pdev); |
8458 | 0 | } |
8459 | 0 | for (k = 0, comps = drawn_comps; k < num_comp; ++k, comps >>= 1) { |
8460 | 0 | if ((comps & 0x1) != 0) { |
8461 | 0 | dst_ptr[k * planestride] = 65535 - dst[k]; |
8462 | 0 | } else { |
8463 | | /* Compatible overprint blend result. */ |
8464 | 0 | dst_ptr[k * planestride] = 65535 - dst2[k]; |
8465 | 0 | } |
8466 | 0 | } |
8467 | 0 | } else { |
8468 | 0 | for (k = 0; k < num_comp; ++k) |
8469 | 0 | dst_ptr[k * planestride] = 65535 - dst[k]; |
8470 | 0 | } |
8471 | 0 | dst_ptr[num_comp * planestride] = dst[num_comp]; |
8472 | 0 | } |
8473 | 0 | if (tag_off) { |
8474 | | /* FIXME: As we are knocking out, possibly, we should be |
8475 | | * always overwriting tag values here? */ |
8476 | | /* If src alpha is 100% then set to curr_tag, else or */ |
8477 | | /* other than Normal BM, we always OR */ |
8478 | 0 | if (src[num_comp] == 65535 && tag_blend) { |
8479 | 0 | dst_ptr[tag_off] = curr_tag; |
8480 | 0 | } else { |
8481 | 0 | dst_ptr[tag_off] |= curr_tag; |
8482 | 0 | } |
8483 | 0 | } |
8484 | | /* Knockout group alpha and shape too */ |
8485 | 0 | if (alpha_g_off) |
8486 | 0 | dst_ptr[alpha_g_off] = 65535 - src_alpha; |
8487 | 0 | if (shape_off) |
8488 | 0 | dst_ptr[shape_off] = 65535 - shape; |
8489 | 0 | ++dst_ptr; |
8490 | 0 | if (has_backdrop) |
8491 | 0 | ++bg_ptr; |
8492 | 0 | } |
8493 | 0 | bline += rowstride; |
8494 | 0 | line += rowstride; |
8495 | 0 | } |
8496 | | #if 0 |
8497 | | /* #if RAW_DUMP */ |
8498 | | /* Dump the current buffer to see what we have. */ |
8499 | | dump_raw_buffer(pdev->ctx->memory, |
8500 | | pdev->ctx->stack->rect.q.y-pdev->ctx->stack->rect.p.y, |
8501 | | pdev->ctx->stack->rect.q.x-pdev->ctx->stack->rect.p.x, |
8502 | | pdev->ctx->stack->n_planes, |
8503 | | pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride, |
8504 | | "Draw_Rect_KO", pdev->ctx->stack->data, |
8505 | | pdev->ctx->stack->deep); |
8506 | | global_index++; |
8507 | | #endif |
8508 | 0 | return 0; |
8509 | 0 | } |
8510 | | |
8511 | | static int |
8512 | | pdf14_mark_fill_rectangle_ko_simple(gx_device * dev, int x, int y, int w, int h, |
8513 | | gx_color_index color, |
8514 | | const gx_device_color *pdc, bool devn) |
8515 | 2.32M | { |
8516 | 2.32M | pdf14_device *pdev = (pdf14_device *)dev; |
8517 | 2.32M | pdf14_buf *buf = pdev->ctx->stack; |
8518 | | |
8519 | 2.32M | if (buf->deep) |
8520 | 0 | return do_mark_fill_rectangle_ko_simple16(dev, x, y, w, h, color, pdc, devn); |
8521 | 2.32M | else |
8522 | 2.32M | return do_mark_fill_rectangle_ko_simple(dev, x, y, w, h, color, pdc, devn); |
8523 | 2.32M | } |
8524 | | |
8525 | | /** |
8526 | | * Here we have logic to override the cmap_procs with versions that |
8527 | | * do not apply the transfer function. These copies should track the |
8528 | | * versions in gxcmap.c. |
8529 | | **/ |
8530 | | static cmap_proc_gray(pdf14_cmap_gray_direct); |
8531 | | static cmap_proc_rgb(pdf14_cmap_rgb_direct); |
8532 | | static cmap_proc_cmyk(pdf14_cmap_cmyk_direct); |
8533 | | static cmap_proc_separation(pdf14_cmap_separation_direct); |
8534 | | static cmap_proc_devicen(pdf14_cmap_devicen_direct); |
8535 | | static cmap_proc_is_halftoned(pdf14_cmap_is_halftoned); |
8536 | | |
8537 | | static const gx_color_map_procs pdf14_cmap_many = { |
8538 | | pdf14_cmap_gray_direct, |
8539 | | pdf14_cmap_rgb_direct, |
8540 | | pdf14_cmap_cmyk_direct, |
8541 | | pdf14_cmap_separation_direct, |
8542 | | pdf14_cmap_devicen_direct, |
8543 | | pdf14_cmap_is_halftoned |
8544 | | }; |
8545 | | |
8546 | | /** |
8547 | | * Note: copied from gxcmap.c because it's inlined. |
8548 | | **/ |
8549 | | static inline void |
8550 | | map_components_to_colorants(const frac * pcc, |
8551 | | const gs_devicen_color_map * pcolor_component_map, |
8552 | | frac * plist, |
8553 | | int num_additives) |
8554 | 3.34M | { |
8555 | 3.34M | int i = pcolor_component_map->num_colorants - 1; |
8556 | 3.34M | int pos; |
8557 | | |
8558 | | /* Clear all output colorants first */ |
8559 | 16.7M | for (; i >= num_additives; i--) { |
8560 | 13.3M | plist[i] = frac_0; |
8561 | 13.3M | } |
8562 | 3.35M | for (; i >= 0; i--) { |
8563 | 3.37k | plist[i] = frac_1; |
8564 | 3.37k | } |
8565 | | /* Map color components into output list */ |
8566 | 7.01M | for (i = pcolor_component_map->num_components - 1; i >= 0; i--) { |
8567 | 3.66M | pos = pcolor_component_map->color_map[i]; |
8568 | 3.66M | if (pos >= 0) { |
8569 | 3.66M | if (pos < num_additives) |
8570 | 0 | plist[pos] = frac_1 - pcc[i]; |
8571 | 3.66M | else |
8572 | 3.66M | plist[pos] = pcc[i]; |
8573 | 3.66M | } |
8574 | 3.66M | } |
8575 | 3.34M | } |
8576 | | |
8577 | | /* See Section 7.6.4 of PDF 1.7 spec */ |
8578 | | static inline bool |
8579 | | pdf14_state_opaque(gx_device *pdev, const gs_gstate *pgs) |
8580 | 202M | { |
8581 | 202M | if (pgs->fillconstantalpha != 1.0 || |
8582 | 202M | pgs->strokeconstantalpha != 1.0 || |
8583 | 202M | !(pgs->blend_mode == BLEND_MODE_Normal || |
8584 | 11.3M | pgs->blend_mode == BLEND_MODE_CompatibleOverprint)) |
8585 | 12.2M | return 0; |
8586 | | |
8587 | | /* We can only be opaque if we're not in an SMask. */ |
8588 | 190M | return dev_proc(pdev, dev_spec_op)(pdev, |
8589 | 190M | gxdso_in_smask, |
8590 | 190M | NULL, 0) != 1; |
8591 | 202M | } |
8592 | | |
8593 | | static void |
8594 | | pdf14_cmap_gray_direct(frac gray, gx_device_color * pdc, const gs_gstate * pgs, |
8595 | | gx_device * dev, gs_color_select_t select) |
8596 | 12.0M | { |
8597 | 12.0M | int i, nc, ncomps; |
8598 | 12.0M | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
8599 | 12.0M | gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
8600 | 12.0M | gx_color_index color; |
8601 | 12.0M | gx_device *trans_device; |
8602 | 12.0M | const gx_device *map_dev; |
8603 | 12.0M | const gx_cm_color_map_procs *procs; |
8604 | | |
8605 | | /* If trans device is set, we need to use its procs. */ |
8606 | 12.0M | if (pgs->trans_device != NULL) { |
8607 | 7.11M | trans_device = pgs->trans_device; |
8608 | 7.11M | } else { |
8609 | 4.93M | trans_device = dev; |
8610 | 4.93M | } |
8611 | 12.0M | ncomps = trans_device->color_info.num_components; |
8612 | | |
8613 | | /* map to the color model */ |
8614 | 12.0M | procs = dev_proc(trans_device, get_color_mapping_procs)(trans_device, &map_dev); |
8615 | 12.0M | procs->map_gray(map_dev, gray, cm_comps); |
8616 | | |
8617 | 12.0M | nc = ncomps; |
8618 | 12.0M | if (device_encodes_tags(trans_device)) |
8619 | 0 | nc--; |
8620 | 12.0M | if (pdf14_state_opaque(trans_device, pgs)) { |
8621 | 9.28M | for (i = 0; i < nc; i++) |
8622 | 4.64M | cv[i] = frac2cv(gx_map_color_frac(pgs, cm_comps[i], effective_transfer[i])); |
8623 | 7.41M | } else { |
8624 | 14.8M | for (i = 0; i < nc; i++) |
8625 | 7.41M | cv[i] = frac2cv(cm_comps[i]); |
8626 | 7.41M | } |
8627 | | /* Copy tags untransformed. */ |
8628 | 12.0M | if (nc < ncomps) |
8629 | 0 | cv[nc] = dev->graphics_type_tag; |
8630 | | |
8631 | | /* If output device supports devn, we need to make sure we send it the |
8632 | | proper color type. We now support Gray + spots as devn colors */ |
8633 | 12.0M | if (dev_proc(trans_device, dev_spec_op)(trans_device, gxdso_supports_devn, NULL, 0) > 0) { |
8634 | 369k | for (i = 0; i < ncomps; i++) |
8635 | 184k | pdc->colors.devn.values[i] = cv[i]; |
8636 | 11.8M | for (; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) |
8637 | 11.6M | pdc->colors.devn.values[i] = 0; |
8638 | 184k | pdc->type = gx_dc_type_devn; |
8639 | 11.8M | } else { |
8640 | | /* encode as a color index */ |
8641 | 11.8M | color = dev_proc(trans_device, encode_color)(trans_device, cv); |
8642 | | /* check if the encoding was successful; we presume failure is rare */ |
8643 | 11.8M | if (color != gx_no_color_index) |
8644 | 11.8M | color_set_pure(pdc, color); |
8645 | 11.8M | } |
8646 | 12.0M | } |
8647 | | |
8648 | | static void |
8649 | | pdf14_cmap_rgb_direct(frac r, frac g, frac b, gx_device_color * pdc, |
8650 | | const gs_gstate * pgs, gx_device * dev, gs_color_select_t select) |
8651 | 181M | { |
8652 | 181M | int i, nc, ncomps; |
8653 | 181M | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
8654 | 181M | gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
8655 | 181M | gx_color_index color; |
8656 | 181M | gx_device *trans_device; |
8657 | 181M | const gx_device *map_dev; |
8658 | 181M | const gx_cm_color_map_procs *procs; |
8659 | | |
8660 | | /* If trans device is set, we need to use its procs. */ |
8661 | 181M | if (pgs->trans_device != NULL){ |
8662 | 3.95M | trans_device = pgs->trans_device; |
8663 | 177M | } else { |
8664 | 177M | trans_device = dev; |
8665 | 177M | } |
8666 | 181M | ncomps = trans_device->color_info.num_components; |
8667 | | /* map to the color model */ |
8668 | 181M | procs = dev_proc(trans_device, get_color_mapping_procs)(trans_device, &map_dev); |
8669 | 181M | procs->map_rgb(map_dev, pgs, r, g, b, cm_comps); |
8670 | | |
8671 | 181M | nc = ncomps; |
8672 | 181M | if (device_encodes_tags(trans_device)) |
8673 | 0 | nc--; |
8674 | 181M | if (pdf14_state_opaque(trans_device, pgs)) { |
8675 | 426M | for (i = 0; i < nc; i++) |
8676 | 320M | cv[i] = frac2cv(gx_map_color_frac(pgs, cm_comps[i], effective_transfer[i])); |
8677 | 106M | } else { |
8678 | 297M | for (i = 0; i < nc; i++) |
8679 | 223M | cv[i] = frac2cv(cm_comps[i]); |
8680 | 74.3M | } |
8681 | | /* Copy tags untransformed. */ |
8682 | 181M | if (nc < ncomps) |
8683 | 0 | cv[nc] = dev->graphics_type_tag; |
8684 | | |
8685 | | /* If output device supports devn, we need to make sure we send it the |
8686 | | proper color type. We now support RGB + spots as devn colors */ |
8687 | 181M | if (dev_proc(trans_device, dev_spec_op)(trans_device, gxdso_supports_devn, NULL, 0) > 0) { |
8688 | 12.0M | for (i = 0; i < ncomps; i++) |
8689 | 9.05M | pdc->colors.devn.values[i] = cv[i]; |
8690 | 186M | for (; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) |
8691 | 183M | pdc->colors.devn.values[i] = 0; |
8692 | 3.01M | pdc->type = gx_dc_type_devn; |
8693 | 178M | } else { |
8694 | | /* encode as a color index */ |
8695 | 178M | color = dev_proc(trans_device, encode_color)(trans_device, cv); |
8696 | | /* check if the encoding was successful; we presume failure is rare */ |
8697 | 178M | if (color != gx_no_color_index) |
8698 | 178M | color_set_pure(pdc, color); |
8699 | 178M | } |
8700 | 181M | } |
8701 | | |
8702 | | static void |
8703 | | pdf14_cmap_cmyk_direct(frac c, frac m, frac y, frac k, gx_device_color * pdc, |
8704 | | const gs_gstate * pgs, gx_device * dev, gs_color_select_t select, |
8705 | | const gs_color_space *pcs) |
8706 | 9.81M | { |
8707 | 9.81M | int i, nc, ncomps; |
8708 | 9.81M | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
8709 | 9.81M | gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
8710 | 9.81M | gx_color_index color; |
8711 | 9.81M | gx_device *trans_device; |
8712 | 9.81M | const gx_device *map_dev; |
8713 | 9.81M | const gx_cm_color_map_procs *procs; |
8714 | | |
8715 | | |
8716 | | /* If trans device is set, we need to use its procs. */ |
8717 | 9.81M | if (pgs->trans_device != NULL){ |
8718 | 7.16M | trans_device = pgs->trans_device; |
8719 | 7.16M | } else { |
8720 | 2.64M | trans_device = dev; |
8721 | 2.64M | } |
8722 | 9.81M | ncomps = trans_device->color_info.num_components; |
8723 | | |
8724 | | /* Map to the color model. Transfer function is only used |
8725 | | if we are drawing with an opaque color. */ |
8726 | 9.81M | procs = dev_proc(trans_device, get_color_mapping_procs)(trans_device, &map_dev); |
8727 | 9.81M | procs->map_cmyk(map_dev, c, m, y, k, cm_comps); |
8728 | | |
8729 | 9.81M | nc = ncomps; |
8730 | 9.81M | if (device_encodes_tags(trans_device)) |
8731 | 0 | nc--; |
8732 | 9.81M | if (pdf14_state_opaque(trans_device, pgs)) { |
8733 | 41.6M | for (i = 0; i < nc; i++) |
8734 | 33.3M | cv[i] = frac2cv(gx_map_color_frac(pgs, cm_comps[i], effective_transfer[i])); |
8735 | 8.33M | } else { |
8736 | 7.36M | for (i = 0; i < nc; i++) |
8737 | 5.88M | cv[i] = frac2cv(cm_comps[i]); |
8738 | 1.47M | } |
8739 | | /* Copy tags untransformed. */ |
8740 | 9.81M | if (nc < ncomps) |
8741 | 0 | cv[nc] = dev->graphics_type_tag; |
8742 | | |
8743 | | /* if output device supports devn, we need to make sure we send it the |
8744 | | proper color type */ |
8745 | 9.81M | if (dev_proc(trans_device, dev_spec_op)(trans_device, gxdso_supports_devn, NULL, 0) > 0) { |
8746 | 15.0M | for (i = 0; i < ncomps; i++) |
8747 | 12.0M | pdc->colors.devn.values[i] = cv[i]; |
8748 | 184M | for (; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) |
8749 | 181M | pdc->colors.devn.values[i] = 0; |
8750 | 3.01M | pdc->type = gx_dc_type_devn; |
8751 | 6.79M | } else { |
8752 | | /* encode as a color index */ |
8753 | 6.79M | color = dev_proc(trans_device, encode_color)(trans_device, cv); |
8754 | | /* check if the encoding was successful; we presume failure is rare */ |
8755 | 6.79M | if (color != gx_no_color_index) |
8756 | 6.79M | color_set_pure(pdc, color); |
8757 | 6.79M | } |
8758 | 9.81M | } |
8759 | | |
8760 | | static int |
8761 | | pdf14_get_num_spots(gx_device * dev) |
8762 | 3.34M | { |
8763 | 3.34M | cmm_dev_profile_t *dev_profile; |
8764 | 3.34M | cmm_profile_t *icc_profile; |
8765 | 3.34M | gsicc_rendering_param_t render_cond; |
8766 | | |
8767 | 3.34M | dev_proc(dev, get_profile)(dev, &dev_profile); |
8768 | 3.34M | gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &icc_profile, |
8769 | 3.34M | &render_cond); |
8770 | 3.34M | return dev->color_info.num_components - icc_profile->num_comps - device_encodes_tags(dev); |
8771 | 3.34M | } |
8772 | | |
8773 | | static void |
8774 | | pdf14_cmap_separation_direct(frac all, gx_device_color * pdc, const gs_gstate * pgs, |
8775 | | gx_device * dev, gs_color_select_t select, const gs_color_space *pcs) |
8776 | 1.60k | { |
8777 | 1.60k | int i, nc, ncomps = dev->color_info.num_components; |
8778 | 1.60k | int num_spots = pdf14_get_num_spots(dev); |
8779 | 1.60k | bool additive = dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE; |
8780 | 1.60k | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
8781 | 1.60k | gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
8782 | 1.60k | gx_color_index color; |
8783 | 1.60k | int n = 0; |
8784 | | |
8785 | 1.60k | nc = ncomps; |
8786 | 1.60k | if (device_encodes_tags(dev)) |
8787 | 0 | nc--; |
8788 | | |
8789 | 1.60k | n = additive ? nc - num_spots : 0; |
8790 | 1.60k | if (pgs->color_component_map.sep_type == SEP_ALL) { |
8791 | 0 | frac comp_value = all; |
8792 | |
|
8793 | 0 | for (i = pgs->color_component_map.num_colorants - 1; i >= nc - num_spots; i--) |
8794 | 0 | cm_comps[i] = comp_value; |
8795 | | /* |
8796 | | * Invert the photometric interpretation for additive |
8797 | | * color spaces because separations are always subtractive. |
8798 | | */ |
8799 | 0 | if (additive) |
8800 | 0 | comp_value = frac_1 - comp_value; |
8801 | | /* Use the "all" value for all components */ |
8802 | 0 | for (; i >= 0; i--) |
8803 | 0 | cm_comps[i] = comp_value; |
8804 | 1.60k | } else { |
8805 | 1.60k | frac comp_value[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
8806 | | |
8807 | 1.60k | if (pgs->color_component_map.sep_type == SEP_NONE) { |
8808 | 0 | color_set_null(pdc); |
8809 | 0 | return; |
8810 | 0 | } |
8811 | | |
8812 | | /* map to the color model */ |
8813 | 3.21k | for (i = pgs->color_component_map.num_components - 1; i >= 0; i--) |
8814 | 1.60k | comp_value[i] = all; |
8815 | 1.60k | map_components_to_colorants(comp_value, &(pgs->color_component_map), cm_comps, n); |
8816 | 1.60k | } |
8817 | | |
8818 | | /* apply the transfer function(s); convert to color values */ |
8819 | 4.98k | for (i = 0; i < n; i++) |
8820 | 3.37k | cv[i] = frac2cv(gx_map_color_frac(pgs, cm_comps[i], effective_transfer[i])); |
8821 | 4.67k | for (; i < nc; i++) |
8822 | 3.06k | cv[i] = frac2cv(frac_1 - gx_map_color_frac(pgs, (frac)(frac_1 - cm_comps[i]), effective_transfer[i])); |
8823 | | |
8824 | | /* Copy tags untransformed. */ |
8825 | 1.60k | if (nc < ncomps) |
8826 | 0 | cv[nc] = dev->graphics_type_tag; |
8827 | | |
8828 | | /* if output device supports devn, we need to make sure we send it the |
8829 | | proper color type */ |
8830 | 1.60k | if (dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0) > 0) { |
8831 | 8.04k | for (i = 0; i < ncomps; i++) |
8832 | 6.43k | pdc->colors.devn.values[i] = cv[i]; |
8833 | 98.1k | for (; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) |
8834 | 96.5k | pdc->colors.devn.values[i] = 0; |
8835 | 1.60k | pdc->type = gx_dc_type_devn; |
8836 | 1.60k | } else { |
8837 | | /* encode as a color index */ |
8838 | 0 | color = dev_proc(dev, encode_color)(dev, cv); |
8839 | | /* check if the encoding was successful; we presume failure is rare */ |
8840 | 0 | if (color != gx_no_color_index) |
8841 | 0 | color_set_pure(pdc, color); |
8842 | 0 | } |
8843 | 1.60k | } |
8844 | | |
8845 | | static void |
8846 | | pdf14_cmap_devicen_direct(const frac * pcc, |
8847 | | gx_device_color * pdc, const gs_gstate * pgs, gx_device * dev, |
8848 | | gs_color_select_t select, const gs_color_space *pcs) |
8849 | 3.34M | { |
8850 | 3.34M | int i, nc, ncomps = dev->color_info.num_components; |
8851 | 3.34M | int num_spots = pdf14_get_num_spots(dev); |
8852 | 3.34M | frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
8853 | 3.34M | gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS]; |
8854 | 3.34M | gx_color_index color; |
8855 | 3.34M | gx_device *trans_device; |
8856 | 3.34M | int num_add_colorants = 0; |
8857 | | |
8858 | | /* We may be coming from the clist writer which often forwards us the |
8859 | | target device. If this occurs we actually need to get to the color |
8860 | | space defined by the transparency group and we use the operators |
8861 | | defined by the transparency device to do the job. |
8862 | | */ |
8863 | 3.34M | if (pgs->trans_device != NULL){ |
8864 | 3.34M | trans_device = pgs->trans_device; |
8865 | 3.34M | } else { |
8866 | 0 | trans_device = dev; |
8867 | 0 | } |
8868 | 3.34M | ncomps = trans_device->color_info.num_components; |
8869 | 3.34M | nc = ncomps; |
8870 | 3.34M | if (device_encodes_tags(trans_device)) |
8871 | 0 | nc--; |
8872 | | |
8873 | 3.34M | if (trans_device->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) |
8874 | 0 | num_add_colorants = nc - num_spots; |
8875 | | |
8876 | | /* map to the color model */ |
8877 | 3.34M | map_components_to_colorants(pcc, &(pgs->color_component_map), cm_comps, num_add_colorants); |
8878 | | |
8879 | | /* apply the transfer function(s); convert to color values */ |
8880 | | /* The additive ones (if there are any) need to be inverted. */ |
8881 | 3.34M | for (i = 0; i < num_add_colorants; i++) |
8882 | 3.34M | cv[i] = frac2cv(gx_map_color_frac(pgs, cm_comps[i], effective_transfer[i])); |
8883 | 16.7M | for (; i < nc; i++) |
8884 | 13.3M | cv[i] = frac2cv(frac_1 - gx_map_color_frac(pgs, (frac)(frac_1 - cm_comps[i]), effective_transfer[i])); |
8885 | | /* Copy tags untransformed. */ |
8886 | 3.34M | if (nc < ncomps) |
8887 | 0 | cv[nc] = dev->graphics_type_tag; |
8888 | | |
8889 | | /* if output device supports devn, we need to make sure we send it the |
8890 | | proper color type */ |
8891 | 3.34M | if (dev_proc(trans_device, dev_spec_op)(trans_device, gxdso_supports_devn, NULL, 0) > 0) { |
8892 | 1.31M | for (i = 0; i < ncomps; i++) |
8893 | 1.05M | pdc->colors.devn.values[i] = cv[i]; |
8894 | 16.0M | for (; i < GX_DEVICE_COLOR_MAX_COMPONENTS; i++) |
8895 | 15.7M | pdc->colors.devn.values[i] = 0; |
8896 | 262k | pdc->type = gx_dc_type_devn; |
8897 | 3.08M | } else { |
8898 | | /* encode as a color index */ |
8899 | 3.08M | color = dev_proc(trans_device, encode_color)(trans_device, cv); |
8900 | | /* check if the encoding was successful; we presume failure is rare */ |
8901 | 3.08M | if (color != gx_no_color_index) |
8902 | 3.08M | color_set_pure(pdc, color); |
8903 | 3.08M | } |
8904 | 3.34M | } |
8905 | | |
8906 | | static bool |
8907 | | pdf14_cmap_is_halftoned(const gs_gstate * pgs, gx_device * dev) |
8908 | 45.0k | { |
8909 | 45.0k | return false; |
8910 | 45.0k | } |
8911 | | |
8912 | | static const gx_color_map_procs * |
8913 | | pdf14_get_cmap_procs(const gs_gstate *pgs, const gx_device * dev) |
8914 | 1.76M | { |
8915 | | /* The pdf14 marking device itself is always continuous tone. */ |
8916 | 1.76M | return &pdf14_cmap_many; |
8917 | 1.76M | } |
8918 | | |
8919 | | static int |
8920 | | pdf14_dev_spec_op(gx_device *pdev, int dev_spec_op, |
8921 | | void *data, int size) |
8922 | 450M | { |
8923 | 450M | pdf14_device * p14dev = (pdf14_device *)pdev; |
8924 | | |
8925 | 450M | if (dev_spec_op == gxdso_supports_pattern_transparency) |
8926 | 825k | return 1; |
8927 | 449M | if (dev_spec_op == gxdso_pattern_shfill_doesnt_need_path) |
8928 | 4.83k | return 1; |
8929 | 449M | if (dev_spec_op == gxdso_is_pdf14_device) { |
8930 | 1.11k | if (data != NULL && size == sizeof(gx_device *)) |
8931 | 522 | *(gx_device **)data = pdev; |
8932 | 1.11k | return 1; |
8933 | 1.11k | } |
8934 | 449M | if (dev_spec_op == gxdso_device_child) { |
8935 | 2.63k | pdf14_device *dev = (pdf14_device *)pdev; |
8936 | 2.63k | gxdso_device_child_request *d = (gxdso_device_child_request *)data; |
8937 | 2.63k | if (d->target == pdev) { |
8938 | 2.63k | d->target = dev->target; |
8939 | 2.63k | return 1; |
8940 | 2.63k | } |
8941 | 2.63k | } |
8942 | 449M | if (dev_spec_op == gxdso_supports_devn |
8943 | 231M | || dev_spec_op == gxdso_skip_icc_component_validation) { |
8944 | 231M | cmm_dev_profile_t *dev_profile; |
8945 | 231M | int code; |
8946 | 231M | code = dev_proc(pdev, get_profile)((gx_device*) pdev, &dev_profile); |
8947 | 231M | if (code == 0) { |
8948 | 231M | return dev_profile->supports_devn; |
8949 | 231M | } else { |
8950 | 0 | return 0; |
8951 | 0 | } |
8952 | 231M | } |
8953 | 217M | if (dev_spec_op == gxdso_pdf14_sep_device) { |
8954 | 314k | pdf14_device* dev = (pdf14_device*)pdev; |
8955 | | |
8956 | 314k | if (strcmp(dev->dname, "pdf14cmykspot") == 0 || |
8957 | 314k | strcmp(dev->dname, "pdf14clistcmykspot") == 0) |
8958 | 161k | return 1; |
8959 | 153k | return 0; |
8960 | 314k | } |
8961 | 217M | if (dev_spec_op == gxdso_is_encoding_direct) |
8962 | 370k | return 1; |
8963 | | |
8964 | | /* We don't want to pass on these spec_ops either, because the child might respond |
8965 | | * with an inappropriate response when the PDF14 device is active. For example; the |
8966 | | * JPEG passthrough will give utterly wrong results if we pass that to a device which |
8967 | | * supports JPEG passthrough, because the pdf14 device needs to render the image. |
8968 | | */ |
8969 | 216M | if (dev_spec_op == gxdso_in_pattern_accumulator) |
8970 | 394k | return 0; |
8971 | 216M | if (dev_spec_op == gxdso_copy_color_is_fast) |
8972 | 217k | return 0; |
8973 | 216M | if(dev_spec_op == gxdso_pattern_handles_clip_path) |
8974 | 4.83k | return 0; |
8975 | 216M | if(dev_spec_op == gxdso_supports_hlcolor) |
8976 | 1.26k | return 0; |
8977 | 216M | if(dev_spec_op == gxdso_pattern_can_accum) |
8978 | 96.4k | return 0; |
8979 | 215M | if(dev_spec_op == gxdso_JPEG_passthrough_query) |
8980 | 1.63k | return 0; |
8981 | 215M | if (dev_spec_op == gxdso_overprint_active) { |
8982 | 3.62M | if (p14dev->pclist_device != NULL) { |
8983 | 3.61M | return dev_proc(p14dev->pclist_device, dev_spec_op)(p14dev->pclist_device, dev_spec_op, data, size); |
8984 | 3.61M | } else { |
8985 | 9.99k | return p14dev->overprint || p14dev->stroke_overprint; |
8986 | 9.99k | } |
8987 | 3.62M | } |
8988 | | |
8989 | | /* These should be coming only from the abuf device |
8990 | | during fill-stroke operation. Any other use will |
8991 | | result in bad things. */ |
8992 | 212M | if (dev_spec_op == gxdso_abuf_optrans) |
8993 | 0 | { |
8994 | 0 | int ret = p14dev->op_state; |
8995 | 0 | overprint_abuf_state_t *state_data = (overprint_abuf_state_t *)data; |
8996 | 0 | pdf14_abuf_state_t *pdf14_abuf = (pdf14_abuf_state_t *)&state_data->storage[0]; |
8997 | 0 | const gs_gstate* cpgs = state_data->pgs; |
8998 | 0 | union { |
8999 | 0 | const gs_gstate* cpgs; |
9000 | 0 | gs_gstate* pgs; |
9001 | 0 | } const_breaker; |
9002 | 0 | gs_gstate* pgs; |
9003 | 0 | int code = 0; |
9004 | 0 | int code1 = 0; |
9005 | | |
9006 | | /* A compile time assert to check our storage types are appropriately sized. */ |
9007 | 0 | typedef char compile_time_assert[sizeof(pdf14_abuf_state_t) <= sizeof(state_data->storage) ? 1 : -1]; |
9008 | | |
9009 | | /* I don't really like this, but there is no easy way around it. The device |
9010 | | in the pgs needs to be the pdf14 device to ensure that the compositor |
9011 | | actions occur with the gs_transparency calls. We have to call at that |
9012 | | level (as opposed to the gx_ or pdf14_ level) to ensure that the clist |
9013 | | operations are invoked. We could change the gs_trans calls to take a |
9014 | | device to avoid this dance but that changes the device procs. */ |
9015 | 0 | gx_device *curr_dev; |
9016 | |
|
9017 | 0 | const_breaker.cpgs = cpgs; |
9018 | 0 | pgs = const_breaker.pgs; |
9019 | 0 | curr_dev = pgs->device; |
9020 | 0 | pgs->device = pdev; |
9021 | |
|
9022 | 0 | switch (state_data->op_trans) { |
9023 | | |
9024 | 0 | case OP_FS_TRANS_PREFILL: |
9025 | 0 | pdf14_abuf->orig_state = p14dev->op_state; |
9026 | 0 | pdf14_abuf->blend_mode = cpgs->blend_mode; |
9027 | 0 | pdf14_abuf->fill_alpha = cpgs->fillconstantalpha; |
9028 | 0 | pdf14_abuf->stroke_alpha = cpgs->strokeconstantalpha; |
9029 | 0 | pdf14_abuf->pgs = pgs; /* ref count? only used for this back and forth so ok */ |
9030 | 0 | if (pdf14_abuf->fill_alpha == 1.0 && pdf14_abuf->stroke_alpha == 1.0 && |
9031 | 0 | pdf14_abuf->blend_mode == BLEND_MODE_Normal) |
9032 | 0 | pdf14_abuf->group_needed = false; |
9033 | 0 | else |
9034 | 0 | pdf14_abuf->group_needed = true; |
9035 | |
|
9036 | 0 | if (pdf14_abuf->group_needed) { |
9037 | 0 | code = pdf14_fill_stroke_prefill(pdev, pgs, state_data->ppath, |
9038 | 0 | state_data->pcpath, pdf14_abuf->fill_alpha, |
9039 | 0 | pdf14_abuf->stroke_alpha, pdf14_abuf->blend_mode, |
9040 | 0 | &(pdf14_abuf->op_ca_eq_CA), &(pdf14_abuf->path_empty), |
9041 | 0 | state_data->alpha_buf_path_scale); |
9042 | 0 | if (code < 0) |
9043 | 0 | goto cleanup; |
9044 | 0 | if (pdf14_abuf->path_empty) |
9045 | 0 | pdf14_abuf->group_needed = 0; |
9046 | 0 | } |
9047 | 0 | code = gs_update_trans_marking_params(pgs); |
9048 | 0 | break; |
9049 | | |
9050 | 0 | case OP_FS_TRANS_PRESTROKE: |
9051 | 0 | if (pdf14_abuf->group_needed) { |
9052 | 0 | pdf14_fill_stroke_prestroke(pdev, pdf14_abuf->pgs, pdf14_abuf->stroke_alpha, |
9053 | 0 | pdf14_abuf->blend_mode, pdf14_abuf->op_ca_eq_CA); |
9054 | 0 | } |
9055 | 0 | code = gs_update_trans_marking_params(pgs); |
9056 | 0 | break; |
9057 | | |
9058 | 0 | case OP_FS_TRANS_POSTSTROKE: |
9059 | 0 | if (pdf14_abuf->group_needed) { |
9060 | 0 | code = pdf14_fill_stroke_poststroke(pdev, pdf14_abuf->pgs, pdf14_abuf->fill_alpha, |
9061 | 0 | pdf14_abuf->op_ca_eq_CA); |
9062 | 0 | } |
9063 | 0 | if (code >= 0) |
9064 | 0 | code = gs_update_trans_marking_params(pgs); |
9065 | | |
9066 | | /* fallthrough */ |
9067 | |
|
9068 | 0 | case OP_FS_TRANS_CLEANUP: |
9069 | 0 | cleanup: |
9070 | 0 | if (pdf14_abuf->group_needed) { |
9071 | 0 | code1 = pdf14_fill_stroke_cleanup(pdev, pdf14_abuf->pgs, pdf14_abuf->fill_alpha, |
9072 | 0 | pdf14_abuf->stroke_alpha, pdf14_abuf->blend_mode, (PDF14_OP_FS_STATE)pdf14_abuf->orig_state); |
9073 | 0 | if (code1 < 0) |
9074 | 0 | code = gs_note_error(gs_error_Fatal); |
9075 | 0 | } |
9076 | 0 | break; |
9077 | 0 | } |
9078 | 0 | pgs->device = curr_dev; |
9079 | |
|
9080 | 0 | return (code < 0) ? code : ret; |
9081 | 0 | } |
9082 | | |
9083 | 212M | if (dev_spec_op == gxdso_in_smask_construction) |
9084 | 3.76M | return p14dev->in_smask_construction > 0; |
9085 | 208M | if (dev_spec_op == gxdso_in_smask) |
9086 | 191M | return p14dev->in_smask_construction > 0 || p14dev->depth_within_smask; |
9087 | 17.4M | if (dev_spec_op == gxdso_replacecolor) { |
9088 | 17.3M | gx_device *tdev = p14dev->target; |
9089 | 17.3M | cmm_dev_profile_t *tdev_profile; |
9090 | 17.3M | int code; |
9091 | | |
9092 | | /* If in a softmask or softmask construction do not allow |
9093 | | replacement. */ |
9094 | 17.3M | if (p14dev->in_smask_construction > 0 || p14dev->depth_within_smask) |
9095 | 2.72M | return 0; |
9096 | | |
9097 | | /* If the target CS is different than the pdf14 profile add this information |
9098 | | for the target device that will be handling the replacement. While not |
9099 | | perfect this at least lets you do the replacehment and have some information |
9100 | | about what the situation is. */ |
9101 | 14.5M | code = dev_proc(tdev, get_profile)((gx_device*) tdev, &tdev_profile); |
9102 | 14.5M | if (code != 0) |
9103 | 0 | return 0; |
9104 | | |
9105 | 14.5M | if (tdev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]->hashcode != |
9106 | 14.5M | p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE]->hashcode) { |
9107 | 7.33M | color_replace_t* replace_data = (color_replace_t*)data; |
9108 | | /* Not ref counted as data is on the stack (from gx_remap_ICC) and we should be fine during this |
9109 | | color remap operation. */ |
9110 | 7.33M | replace_data->pdf14_iccprofile = p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE]; |
9111 | 7.33M | } |
9112 | | |
9113 | | /* Pass on to target device */ |
9114 | 14.5M | return dev_proc(p14dev->target, dev_spec_op)(p14dev->target, dev_spec_op, data, size); |
9115 | 14.5M | } |
9116 | 186k | if (dev_spec_op == gxdso_device_insert_child) { |
9117 | 168 | gx_device *tdev = p14dev->target; |
9118 | 168 | p14dev->target = (gx_device *)data; |
9119 | 168 | rc_increment(p14dev->target); |
9120 | 168 | rc_decrement_only(tdev, "pdf14_dev_spec_op"); |
9121 | 168 | return 0; |
9122 | 168 | } |
9123 | 186k | if (dev_spec_op == gxdso_interpolate_threshold) |
9124 | 5.21k | return p14dev->interpolate_threshold; |
9125 | | |
9126 | 181k | if (dev_spec_op == gxdso_overprintsim_state) { |
9127 | 5.20k | unsigned char *data_uchar = (unsigned char *) data; |
9128 | 5.20k | data_uchar[0] = (unsigned char) p14dev->overprint_sim; |
9129 | 5.20k | if (p14dev->ctx != NULL) |
9130 | 16 | data_uchar[1] = (unsigned char)p14dev->ctx->num_spots; /* pdf14 page device */ |
9131 | 5.19k | else |
9132 | 5.19k | data_uchar[1] = (unsigned char)p14dev->devn_params.page_spot_colors; /* pdf14 clist device */ |
9133 | 5.20k | return 1; |
9134 | 5.20k | } |
9135 | | |
9136 | 176k | return dev_proc(p14dev->target, dev_spec_op)(p14dev->target, dev_spec_op, data, size); |
9137 | 181k | } |
9138 | | |
9139 | | /* Needed to set color monitoring in the target device's profile */ |
9140 | | int |
9141 | | gs_pdf14_device_color_mon_set(gx_device *pdev, bool monitoring) |
9142 | 0 | { |
9143 | 0 | pdf14_device * p14dev = (pdf14_device *)pdev; |
9144 | 0 | gx_device *targ = p14dev->target; |
9145 | 0 | cmm_dev_profile_t *dev_profile; |
9146 | 0 | int code = dev_proc(targ, get_profile)((gx_device*) targ, &dev_profile); |
9147 | |
|
9148 | 0 | if (code == 0) |
9149 | 0 | dev_profile->pageneutralcolor = monitoring; |
9150 | 0 | return code; |
9151 | 0 | } |
9152 | | |
9153 | | static int |
9154 | | gs_pdf14_device_push(gs_memory_t *mem, gs_gstate * pgs, |
9155 | | gx_device ** pdev, gx_device * target, const gs_pdf14trans_t * pdf14pct) |
9156 | 1.14M | { |
9157 | 1.14M | pdf14_device dev_proto; |
9158 | 1.14M | pdf14_device * p14dev; |
9159 | 1.14M | int code; |
9160 | 1.14M | bool has_tags; |
9161 | 1.14M | cmm_profile_t *icc_profile; |
9162 | 1.14M | gsicc_rendering_param_t render_cond; |
9163 | 1.14M | cmm_dev_profile_t *dev_profile; |
9164 | 1.14M | uchar k; |
9165 | 1.14M | int max_bitmap; |
9166 | 1.14M | bool use_pdf14_accum = false; |
9167 | 1.14M | bool deep; |
9168 | | |
9169 | | /* Guard against later seg faults, this should not be possible */ |
9170 | 1.14M | if (target == NULL) |
9171 | 0 | return gs_throw_code(gs_error_Fatal); |
9172 | | |
9173 | 1.14M | has_tags = device_encodes_tags(target); |
9174 | 1.14M | deep = device_is_deep(target); |
9175 | 1.14M | max_bitmap = target->space_params.MaxBitmap == 0 ? MAX_BITMAP : |
9176 | 1.14M | target->space_params.MaxBitmap; |
9177 | | /* If the device is not a printer class device, it won't support saved-pages */ |
9178 | | /* and so we may need to make a clist device in order to prevent very large */ |
9179 | | /* or high resolution pages from having allocation problems. */ |
9180 | | /* We use MaxBitmap to decide when a clist is needed.*/ |
9181 | 1.14M | if (dev_proc(target, dev_spec_op)(target, gxdso_supports_saved_pages, NULL, 0) <= 0 && |
9182 | 5.69k | gx_device_is_pattern_clist(target) == 0 && |
9183 | 5.69k | gx_device_is_pattern_accum(target) == 0 && |
9184 | 4.24k | gs_device_is_memory(target) == 0) { |
9185 | | |
9186 | 4.24k | uint32_t pdf14_trans_buffer_size = |
9187 | 4.24k | (ESTIMATED_PDF14_ROW_SPACE(max(1, target->width), |
9188 | 4.24k | target->color_info.num_components, |
9189 | 4.24k | deep ? 16 : 8) >> 3); |
9190 | | |
9191 | 4.24k | if (target->height < max_ulong / pdf14_trans_buffer_size) |
9192 | 4.24k | pdf14_trans_buffer_size *= target->height; |
9193 | 0 | else |
9194 | 0 | max_bitmap = 0; /* Force decision to clist */ |
9195 | 4.24k | if (pdf14_trans_buffer_size > max_bitmap) |
9196 | 3.96k | use_pdf14_accum = true; |
9197 | 4.24k | } |
9198 | 1.14M | code = dev_proc(target, get_profile)(target, &dev_profile); |
9199 | 1.14M | if (code < 0) |
9200 | 0 | return code; |
9201 | 1.14M | gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &icc_profile, |
9202 | 1.14M | &render_cond); |
9203 | 1.14M | if_debug0m('v', mem, "[v]gs_pdf14_device_push\n"); |
9204 | | |
9205 | | /* Get the proto from which to copy the device. This will always |
9206 | | * ignore tags! */ |
9207 | 1.14M | code = get_pdf14_device_proto(target, &dev_proto, pgs, |
9208 | 1.14M | pdf14pct, use_pdf14_accum); |
9209 | 1.14M | if (code < 0) |
9210 | 0 | return code; |
9211 | 1.14M | code = gs_copydevice((gx_device **) &p14dev, |
9212 | 1.14M | (const gx_device *) &dev_proto, mem); |
9213 | 1.14M | if (code < 0) |
9214 | 0 | return code; |
9215 | | |
9216 | 1.14M | p14dev->graphics_type_tag = target->graphics_type_tag; |
9217 | | |
9218 | | /* Copying the params across will add tags to the colorinfo as required. */ |
9219 | 1.14M | code = gs_pdf14_device_copy_params((gx_device *)p14dev, target); |
9220 | 1.14M | if (code < 0) |
9221 | 0 | return code; |
9222 | | |
9223 | 1.14M | gx_device_set_target((gx_device_forward *)p14dev, target); |
9224 | 1.14M | p14dev->pad = target->pad; |
9225 | 1.14M | p14dev->log2_align_mod = target->log2_align_mod; |
9226 | 1.14M | if (pdf14pct->params.overprint_sim_push && pdf14pct->params.num_spot_colors_int > 0 && target->num_planar_planes == 0) { |
9227 | 0 | p14dev->num_planar_planes = p14dev->color_info.num_components + pdf14pct->params.num_spot_colors_int; |
9228 | 0 | p14dev->color_info.num_components = p14dev->num_planar_planes; |
9229 | 0 | } |
9230 | 1.14M | else if (pdf14pct->params.overprint_sim_push && target->num_planar_planes != 0) { |
9231 | 0 | p14dev->num_planar_planes = p14dev->color_info.num_components + pdf14pct->params.num_spot_colors_int; |
9232 | 0 | p14dev->color_info.num_components = p14dev->num_planar_planes; |
9233 | 0 | } |
9234 | 1.14M | else |
9235 | 1.14M | { |
9236 | 1.14M | p14dev->color_info.num_components = target->color_info.num_components; |
9237 | 1.14M | p14dev->num_planar_planes = target->num_planar_planes; |
9238 | 1.14M | } |
9239 | 1.14M | p14dev->interpolate_threshold = dev_proc(target, dev_spec_op)(target, gxdso_interpolate_threshold, NULL, 0); |
9240 | | |
9241 | 1.14M | p14dev->alpha = 1.0; |
9242 | 1.14M | p14dev->shape = 1.0; |
9243 | 1.14M | p14dev->opacity = 1.0; |
9244 | 1.14M | p14dev->fillconstantalpha = 1.0; |
9245 | 1.14M | p14dev->strokeconstantalpha = 1.0; |
9246 | | |
9247 | | /* Simulated overprint case. We have to use CMYK-based profile. Also if the target |
9248 | | profile is NCLR, we are going to use a pdf14 device that is CMYK based and |
9249 | | do the mapping to the NCLR profile when the put_image occurs */ |
9250 | 1.14M | if ((p14dev->overprint_sim && icc_profile->data_cs != gsCMYK) || |
9251 | 1.14M | icc_profile->data_cs == gsNCHANNEL) { |
9252 | 0 | gsicc_adjust_profile_rc(pgs->icc_manager->default_cmyk, 1, "gs_pdf14_device_push"); |
9253 | 0 | gsicc_adjust_profile_rc(p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], |
9254 | 0 | -1, "gs_pdf14_device_push"); |
9255 | 0 | p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] = pgs->icc_manager->default_cmyk; |
9256 | 1.14M | } else { |
9257 | | /* If the target profile was CIELAB (and we are not using a blend CS), |
9258 | | then overide with default RGB for proper blending. During put_image |
9259 | | we will convert from RGB to CIELAB. Need to check that we have a |
9260 | | default profile, which will not be the case if we are coming from the clist reader */ |
9261 | 1.14M | if ((icc_profile->data_cs == gsCIELAB || icc_profile->islab) |
9262 | 0 | && pgs->icc_manager->default_rgb != NULL && |
9263 | 0 | p14dev->blend_cs_state == PDF14_BLEND_CS_UNSPECIFIED) { |
9264 | 0 | p14dev->blend_cs_state = PDF14_BLEND_CS_TARGET_CIELAB; |
9265 | 0 | gsicc_adjust_profile_rc(pgs->icc_manager->default_rgb, 1, "gs_pdf14_device_push"); |
9266 | 0 | gsicc_adjust_profile_rc(p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], |
9267 | 0 | -1, "gs_pdf14_device_push"); |
9268 | 0 | p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] = pgs->icc_manager->default_rgb; |
9269 | 0 | } |
9270 | 1.14M | } |
9271 | | |
9272 | 1.14M | if (pdf14pct->params.overprint_sim_push && |
9273 | 0 | pdf14pct->params.num_spot_colors_int > 0) { |
9274 | 0 | p14dev->procs.update_spot_equivalent_colors = pdf14_update_spot_equivalent_colors; |
9275 | 0 | p14dev->procs.ret_devn_params = pdf14_ret_devn_params; |
9276 | 0 | p14dev->op_pequiv_cmyk_colors.all_color_info_valid = false; |
9277 | 0 | p14dev->target_support_devn = p14dev->icc_struct->supports_devn; |
9278 | 0 | p14dev->icc_struct->supports_devn = true; /* Reset when pdf14 device is disabled */ |
9279 | 0 | } |
9280 | | |
9281 | | /* The number of color planes should not exceed that of the target. |
9282 | | Unless we are using a blend CS */ |
9283 | 1.14M | if (!(p14dev->blend_cs_state != PDF14_BLEND_CS_UNSPECIFIED || p14dev->overprint_sim)) { |
9284 | 1.14M | if (p14dev->color_info.num_components > target->color_info.num_components - device_encodes_tags(target) + device_encodes_tags((gx_device *)p14dev)) |
9285 | 0 | p14dev->color_info.num_components = target->color_info.num_components - device_encodes_tags(target) + device_encodes_tags((gx_device *)p14dev); |
9286 | 1.14M | if (p14dev->color_info.max_components > target->color_info.max_components) |
9287 | 70.7k | p14dev->color_info.max_components = target->color_info.max_components; |
9288 | 1.14M | } |
9289 | 1.14M | p14dev->color_info.depth = p14dev->color_info.num_components * (8<<deep); |
9290 | | /* If we have a tag device then go ahead and do a special encoder |
9291 | | decoder for the pdf14 device to make sure we maintain this |
9292 | | information in the encoded color information. We could use |
9293 | | the target device's methods but the PDF14 device has to maintain |
9294 | | 8 bit color always and we could run into other issues if the number |
9295 | | of colorants became large. If we need to do compressed color with |
9296 | | tags that will be a special project at that time */ |
9297 | 1.14M | if (deep) { |
9298 | 0 | set_dev_proc(p14dev, encode_color, pdf14_encode_color16); |
9299 | 0 | set_dev_proc(p14dev, decode_color, pdf14_decode_color16); |
9300 | 0 | } |
9301 | 1.14M | if (has_tags) { |
9302 | 0 | set_dev_proc(p14dev, encode_color, deep ? pdf14_encode_color16_tag : pdf14_encode_color_tag); |
9303 | 0 | } |
9304 | | /* if the device has separations already defined (by SeparationOrderNames) */ |
9305 | | /* we need to copy them (allocating new names) so the colorants are in the */ |
9306 | | /* same order as the target device. */ |
9307 | 1.14M | if (dev_proc(target, dev_spec_op)(target, gxdso_supports_devn, NULL, 0) > 0) { |
9308 | 70.8k | code = devn_copy_params(target, (gx_device *)p14dev); |
9309 | 70.8k | if (code < 0) { |
9310 | 50 | *pdev = NULL; |
9311 | 50 | gx_device_set_target((gx_device_forward *)p14dev, NULL); |
9312 | 50 | rc_decrement(p14dev, "gs_pdf14_device_push"); |
9313 | 50 | return code; |
9314 | 50 | } |
9315 | 70.8k | } |
9316 | | /* by definition pdf14_encode _is_ standard */ |
9317 | 1.14M | p14dev->color_info.separable_and_linear = GX_CINFO_SEP_LIN_STANDARD; |
9318 | 1.14M | gx_device_fill_in_procs((gx_device *)p14dev); |
9319 | 1.14M | p14dev->save_get_cmap_procs = pgs->get_cmap_procs; |
9320 | 1.14M | pgs->get_cmap_procs = pdf14_get_cmap_procs; |
9321 | 1.14M | gx_set_cmap_procs(pgs, (gx_device *)p14dev); |
9322 | | |
9323 | | /* Components shift, etc have to be based upon 8 (or 16) bit */ |
9324 | 3.80M | for (k = 0; k < p14dev->color_info.num_components; k++) { |
9325 | 2.66M | p14dev->color_info.comp_bits[k] = 8<<deep; |
9326 | 2.66M | p14dev->color_info.comp_shift[k] = |
9327 | 2.66M | (p14dev->color_info.num_components - 1 - k) * (8<<deep); |
9328 | 2.66M | } |
9329 | 1.14M | if (use_pdf14_accum) { |
9330 | | /* we will disable this device later, but we don't want to allocate large buffers */ |
9331 | 3.96k | p14dev->width = 1; |
9332 | 3.96k | p14dev->height = 1; |
9333 | 3.96k | } |
9334 | | |
9335 | 1.14M | p14dev->op_state = pgs->is_fill_color ? PDF14_OP_STATE_FILL : PDF14_OP_STATE_NONE; |
9336 | 1.14M | code = dev_proc((gx_device *) p14dev, open_device) ((gx_device *) p14dev); |
9337 | 1.14M | *pdev = (gx_device *) p14dev; |
9338 | 1.14M | pdf14_set_marking_params((gx_device *)p14dev, pgs); |
9339 | 1.14M | p14dev->color_model_stack = NULL; |
9340 | | |
9341 | | /* In case we have alphabits set */ |
9342 | 1.14M | p14dev->color_info.anti_alias = target->color_info.anti_alias; |
9343 | | |
9344 | 1.14M | if (pdf14pct->params.is_pattern) { |
9345 | 6.30k | code = pdf14_initialize_ctx((gx_device*)p14dev, pgs); |
9346 | 6.30k | if (code < 0) { |
9347 | 0 | *pdev = NULL; |
9348 | 0 | gx_device_set_target((gx_device_forward *)p14dev, NULL); |
9349 | 0 | rc_decrement(p14dev, "gs_pdf14_device_push"); |
9350 | 0 | return code; |
9351 | 0 | } |
9352 | 6.30k | } |
9353 | | |
9354 | | /* We should never go into this when using a blend color space */ |
9355 | 1.14M | if (use_pdf14_accum) { |
9356 | 3.96k | const gx_device_pdf14_accum *accum_proto = NULL; |
9357 | 3.96k | gx_device *new_target = NULL; |
9358 | 3.96k | gx_device_color pdcolor; |
9359 | 3.96k | frac pconc_white = frac_1; |
9360 | 3.96k | bool UsePlanarBuffer = false; |
9361 | | |
9362 | 3.96k | if_debug0m('v', mem, "[v]gs_pdf14_device_push: Inserting clist device.\n"); |
9363 | | |
9364 | | /* get the prototype for the accumulator device based on colorspace */ |
9365 | 3.96k | switch (target->color_info.max_components) { /* use max_components in case is devn device */ |
9366 | 960 | case 1: |
9367 | 960 | accum_proto = &pdf14_accum_Gray; |
9368 | 960 | break; |
9369 | 3.00k | case 3: |
9370 | 3.00k | accum_proto = &pdf14_accum_RGB; |
9371 | 3.00k | break; |
9372 | 0 | case 4: |
9373 | 0 | accum_proto = &pdf14_accum_CMYK; |
9374 | 0 | break; |
9375 | 0 | default: |
9376 | 0 | accum_proto = &pdf14_accum_CMYKspot; |
9377 | 0 | UsePlanarBuffer = true; |
9378 | 3.96k | } |
9379 | 3.96k | if (accum_proto == NULL || |
9380 | 3.96k | (code = gs_copydevice(&new_target, (gx_device *)accum_proto, mem->stable_memory)) < 0) |
9381 | 0 | goto no_clist_accum; |
9382 | | |
9383 | 3.96k | ((gx_device_pdf14_accum *)new_target)->save_p14dev = (gx_device *)p14dev; /* non-clist p14dev */ |
9384 | | /* Fill in values from the target device before opening */ |
9385 | 3.96k | new_target->color_info = p14dev->color_info; |
9386 | 3.96k | ((gx_device_pdf14_accum *)new_target)->devn_params = p14dev->devn_params; |
9387 | 3.96k | new_target->color_info.separable_and_linear = GX_CINFO_SEP_LIN; |
9388 | 3.96k | set_linear_color_bits_mask_shift(new_target); |
9389 | 3.96k | gs_pdf14_device_copy_params(new_target, target); |
9390 | 3.96k | ((gx_device_pdf14_accum *)new_target)->page_uses_transparency = true; |
9391 | 3.96k | gx_device_fill_in_procs(new_target); |
9392 | | |
9393 | 3.96k | memcpy(&(new_target->space_params), &(target->space_params), sizeof(gdev_space_params)); |
9394 | 3.96k | max_bitmap = max(target->space_params.MaxBitmap, target->space_params.BufferSpace); |
9395 | 3.96k | ((gx_device_pdf14_accum *)new_target)->space_params.BufferSpace = max_bitmap; |
9396 | | |
9397 | | /* This is used to mark the various internal subclass devices as having already |
9398 | | * been pushed, so that opening the device won't result in us trying to push |
9399 | | * them again, which leads to trouble. |
9400 | | */ |
9401 | 3.96k | code = mark_internal_subclass_devices(new_target); |
9402 | 3.96k | if (code < 0) |
9403 | 0 | return code; |
9404 | | |
9405 | | /* if the device has separations already defined (by SeparationOrderNames) */ |
9406 | | /* we need to copy them (allocating new names) so the colorants are in the */ |
9407 | | /* same order as the target device. */ |
9408 | 3.96k | if (dev_proc(target, dev_spec_op)(target, gxdso_supports_devn, NULL, 0) > 0) { |
9409 | 0 | code = devn_copy_params(target, (gx_device *)*pdev); |
9410 | 0 | if (code < 0) |
9411 | 0 | return code; |
9412 | 0 | } |
9413 | | /* UsePlanarBuffer is true in case this is CMYKspot */ |
9414 | 3.96k | if ((code = gdev_prn_open_planar(new_target, UsePlanarBuffer ? new_target->color_info.num_components : 0)) < 0 || |
9415 | 3.96k | !PRINTER_IS_CLIST((gx_device_printer *)new_target)) { |
9416 | 0 | gs_free_object(mem->stable_memory, new_target, "pdf14-accum"); |
9417 | 0 | goto no_clist_accum; |
9418 | 0 | } |
9419 | | /* Do the initial fillpage into the pdf14-accum device we just created */ |
9420 | 3.96k | dev_proc(new_target, set_graphics_type_tag)((gx_device *)new_target, GS_UNTOUCHED_TAG); |
9421 | 3.96k | if ((code = gx_remap_concrete_DGray(gs_currentcolorspace_inline((gs_gstate *)pgs), |
9422 | 3.96k | &pconc_white, |
9423 | 3.96k | &pdcolor, pgs, new_target, gs_color_select_all, |
9424 | 3.96k | dev_profile)) < 0) |
9425 | 0 | goto no_clist_accum; |
9426 | | |
9427 | 3.96k | (*dev_proc(new_target, fillpage))(new_target, pgs, &pdcolor); |
9428 | 3.96k | code = clist_composite(new_target, pdev, (gs_composite_t *)pdf14pct, pgs, mem, NULL); |
9429 | 3.96k | if (code < 0) |
9430 | 0 | goto no_clist_accum; |
9431 | | |
9432 | 3.96k | pdf14_disable_device((gx_device *)p14dev); /* make the non-clist device forward */ |
9433 | 3.96k | pdf14_close((gx_device *)p14dev); /* and free up the little memory it had */ |
9434 | 3.96k | } |
9435 | 1.14M | return code; |
9436 | | |
9437 | 0 | no_clist_accum: |
9438 | | /* FIXME: We allocated a really small p14dev, but that won't work */ |
9439 | 0 | return gs_throw_code(gs_error_Fatal); /* punt for now */ |
9440 | 1.14M | } |
9441 | | |
9442 | | /* |
9443 | | * In a modest violation of good coding practice, the gs_composite_common |
9444 | | * fields are "known" to be simple (contain no pointers to garbage |
9445 | | * collected memory), and we also know the gs_pdf14trans_params_t structure |
9446 | | * to be simple, so we just create a trivial structure descriptor for the |
9447 | | * entire gs_pdf14trans_s structure. |
9448 | | */ |
9449 | | #define private_st_gs_pdf14trans_t()\ |
9450 | | gs_private_st_ptrs2(st_pdf14trans, gs_pdf14trans_t, "gs_pdf14trans_t",\ |
9451 | | st_pdf14trans_enum_ptrs, st_pdf14trans_reloc_ptrs, params.transfer_function, params.iccprofile) |
9452 | | |
9453 | | /* GC descriptor for gs_pdf14trans_t */ |
9454 | | private_st_gs_pdf14trans_t(); |
9455 | | |
9456 | | /* |
9457 | | * Check for equality of two PDF 1.4 transparency compositor objects. |
9458 | | * |
9459 | | * We are currently always indicating that PDF 1.4 transparency compositors are |
9460 | | * equal. Two transparency compositors may have teh same data but still |
9461 | | * represent separate actions. (E.g. two PDF14_BEGIN_TRANS_GROUP compositor |
9462 | | * operations in a row mean that we are creating a group inside of a group. |
9463 | | */ |
9464 | | static bool |
9465 | | c_pdf14trans_equal(const gs_composite_t * pct0, const gs_composite_t * pct1) |
9466 | 0 | { |
9467 | 0 | return false; |
9468 | 0 | } |
9469 | | |
9470 | | #ifdef DEBUG |
9471 | | static const char * pdf14_opcode_names[] = PDF14_OPCODE_NAMES; |
9472 | | #endif |
9473 | | |
9474 | | #define put_value(dp, value)\ |
9475 | 7.21M | BEGIN\ |
9476 | 7.21M | memcpy(dp, &value, sizeof(value));\ |
9477 | 7.21M | dp += sizeof(value);\ |
9478 | 7.21M | END |
9479 | | |
9480 | | static inline int |
9481 | | c_pdf14trans_write_ctm(byte **ppbuf, const gs_pdf14trans_params_t *pparams) |
9482 | 903k | { |
9483 | | /* Note: We can't skip writing CTM if it is equal to pgs->ctm, |
9484 | | because clist writer may skip this command for some bands. |
9485 | | For a better result we need individual CTM for each band. |
9486 | | */ |
9487 | 903k | byte *pbuf = *ppbuf; |
9488 | 903k | int len, code; |
9489 | | |
9490 | 903k | len = cmd_write_ctm_return_length_nodevice(&pparams->ctm); |
9491 | 903k | pbuf--; /* For cmd_write_ctm. */ |
9492 | 903k | code = cmd_write_ctm(&pparams->ctm, pbuf, len); |
9493 | 903k | if (code < 0) |
9494 | 0 | return code; |
9495 | 903k | pbuf += len + 1; |
9496 | 903k | *ppbuf = pbuf; |
9497 | 903k | return 0; |
9498 | 903k | } |
9499 | | |
9500 | | /* |
9501 | | * Convert a PDF 1.4 transparency compositor to string form for use by the command |
9502 | | * list device. This is also where we update the pdf14_needed. When set the clist |
9503 | | * painting procs will update the trans_bbox state for bands that are affected. |
9504 | | */ |
9505 | | static int |
9506 | | c_pdf14trans_write(const gs_composite_t * pct, byte * data, uint * psize, |
9507 | | gx_device_clist_writer *cdev) |
9508 | 2.05M | { |
9509 | 2.05M | const gs_pdf14trans_params_t * pparams = &((const gs_pdf14trans_t *)pct)->params; |
9510 | 2.05M | int need, avail = *psize; |
9511 | 2.05M | byte buf[MAX_CLIST_TRANSPARENCY_BUFFER_SIZE]; /* Must be large enough |
9512 | | to fit the data written below. We don't implement a dynamic check for |
9513 | | the buffer owerflow, assuming that the consistency is verified in the |
9514 | | coding phase. See the definition of MAX_CLIST_TRANSPARENCY_BUFFER_SIZE. */ |
9515 | 2.05M | byte * pbuf = buf; |
9516 | 2.05M | int opcode = pparams->pdf14_op; |
9517 | 2.05M | int mask_size = 0; |
9518 | 2.05M | uint mask_id = 0; |
9519 | 2.05M | int code; |
9520 | 2.05M | bool found_icc; |
9521 | 2.05M | int64_t hashcode = 0; |
9522 | 2.05M | cmm_profile_t *icc_profile; |
9523 | 2.05M | gsicc_rendering_param_t render_cond; |
9524 | 2.05M | cmm_dev_profile_t *dev_profile; |
9525 | | /* We maintain and update working copies until we actually write the clist */ |
9526 | 2.05M | int pdf14_needed = cdev->pdf14_needed; |
9527 | 2.05M | int trans_group_level = cdev->pdf14_trans_group_level; |
9528 | 2.05M | int smask_level = cdev->pdf14_smask_level; |
9529 | 2.05M | bool deep = device_is_deep((gx_device *)cdev); |
9530 | | |
9531 | 2.05M | code = dev_proc((gx_device *) cdev, get_profile)((gx_device *) cdev, |
9532 | 2.05M | &dev_profile); |
9533 | 2.05M | if (code < 0) |
9534 | 0 | return code; |
9535 | 2.05M | gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &icc_profile, |
9536 | 2.05M | &render_cond); |
9537 | 2.05M | *pbuf++ = opcode; /* 1 byte */ |
9538 | 2.05M | if (trans_group_level < 0 && opcode != PDF14_PUSH_DEVICE) |
9539 | 5 | return_error(gs_error_unregistered); /* prevent spurious transparency ops (Bug 702327) */ |
9540 | | |
9541 | 2.05M | switch (opcode) { |
9542 | 0 | default: /* Should not occur. */ |
9543 | 0 | break; |
9544 | 22.4k | case PDF14_PUSH_DEVICE: |
9545 | 22.4k | trans_group_level = 0; |
9546 | 22.4k | cdev->pdf14_smask_level = 0; |
9547 | 22.4k | cdev->page_pdf14_needed = false; |
9548 | 22.4k | put_value(pbuf, pparams->num_spot_colors); |
9549 | 22.4k | put_value(pbuf, pparams->num_spot_colors_int); |
9550 | 22.4k | put_value(pbuf, pparams->overprint_sim_push); |
9551 | 22.4k | put_value(pbuf, pparams->is_pattern); |
9552 | | |
9553 | | /* If we happen to be going to a color space like CIELAB then |
9554 | | we are going to do our blending in default RGB and convert |
9555 | | to CIELAB at the end. To do this, we need to store the |
9556 | | default RGB profile in the clist so that we can grab it |
9557 | | later on during the clist read back and put image command */ |
9558 | 22.4k | if (icc_profile->data_cs == gsCIELAB || icc_profile->islab) { |
9559 | | /* Get the default RGB profile. Set the device hash code |
9560 | | so that we can extract it during the put_image operation. */ |
9561 | 0 | cdev->trans_dev_icc_hash = gsicc_get_hash(pparams->iccprofile); |
9562 | 0 | found_icc = |
9563 | 0 | clist_icc_searchtable(cdev, gsicc_get_hash(pparams->iccprofile)); |
9564 | 0 | if (!found_icc) { |
9565 | | /* Add it to the table */ |
9566 | 0 | clist_icc_addentry(cdev, gsicc_get_hash(pparams->iccprofile), |
9567 | 0 | pparams->iccprofile); |
9568 | 0 | } |
9569 | 0 | } |
9570 | 22.4k | break; |
9571 | 21.6k | case PDF14_POP_DEVICE: |
9572 | 21.6k | pdf14_needed = false; /* reset pdf14_needed */ |
9573 | 21.6k | trans_group_level = -1; /* reset so we need to PUSH_DEVICE next */ |
9574 | 21.6k | smask_level = 0; |
9575 | 21.6k | put_value(pbuf, pparams->is_pattern); |
9576 | 21.6k | break; |
9577 | 489k | case PDF14_END_TRANS_GROUP: |
9578 | 495k | case PDF14_END_TRANS_TEXT_GROUP: |
9579 | 495k | trans_group_level--; /* if now at page level, pdf14_needed will be updated */ |
9580 | 495k | if (smask_level == 0 && trans_group_level == 0) |
9581 | 29.0k | pdf14_needed = cdev->page_pdf14_needed; |
9582 | 495k | break; /* No data */ |
9583 | 8.03k | case PDF14_BEGIN_TRANS_PAGE_GROUP: |
9584 | 495k | case PDF14_BEGIN_TRANS_GROUP: |
9585 | 495k | pdf14_needed = true; /* the compositor will be needed while reading */ |
9586 | 495k | trans_group_level++; |
9587 | 495k | code = c_pdf14trans_write_ctm(&pbuf, pparams); |
9588 | 495k | if (code < 0) |
9589 | 0 | return code; |
9590 | 495k | *pbuf++ = (pparams->Isolated & 1) + ((pparams->Knockout & 1) << 1); |
9591 | 495k | *pbuf++ = pparams->blend_mode; |
9592 | 495k | *pbuf++ = pparams->group_color_type; |
9593 | 495k | *pbuf++ = pparams->page_group; |
9594 | 495k | put_value(pbuf, pparams->group_color_numcomps); |
9595 | 495k | put_value(pbuf, pparams->opacity); |
9596 | 495k | put_value(pbuf, pparams->shape); |
9597 | 495k | put_value(pbuf, pparams->bbox); |
9598 | 495k | put_value(pbuf, pparams->shade_group); |
9599 | 495k | put_value(pbuf, pparams->text_group); |
9600 | 495k | mask_id = pparams->mask_id; |
9601 | 495k | put_value(pbuf, mask_id); |
9602 | | /* Color space information maybe ICC based |
9603 | | in this case we need to store the ICC |
9604 | | profile or the ID if it is cached already */ |
9605 | 495k | if (pparams->group_color_type == ICC) { |
9606 | | /* Check if it is already in the ICC clist table */ |
9607 | 12.2k | hashcode = gsicc_get_hash(pparams->iccprofile); |
9608 | 12.2k | found_icc = clist_icc_searchtable(cdev, hashcode); |
9609 | 12.2k | if (!found_icc) { |
9610 | | /* Add it to the table */ |
9611 | 4.24k | clist_icc_addentry(cdev, hashcode, pparams->iccprofile); |
9612 | 4.24k | put_value(pbuf, hashcode); |
9613 | 7.97k | } else { |
9614 | | /* It will be in the clist. Just write out the hashcode */ |
9615 | 7.97k | put_value(pbuf, hashcode); |
9616 | 7.97k | } |
9617 | 483k | } else { |
9618 | 483k | put_value(pbuf, hashcode); |
9619 | 483k | } |
9620 | 495k | break; |
9621 | 407k | case PDF14_BEGIN_TRANS_MASK: |
9622 | 407k | if (pparams->subtype != TRANSPARENCY_MASK_None) { |
9623 | 348k | pdf14_needed = true; /* the compositor will be needed while reading */ |
9624 | 348k | smask_level++; |
9625 | 348k | } |
9626 | 407k | code = c_pdf14trans_write_ctm(&pbuf, pparams); |
9627 | 407k | if (code < 0) |
9628 | 0 | return code; |
9629 | 407k | put_value(pbuf, pparams->subtype); |
9630 | 407k | *pbuf++ = pparams->group_color_type; |
9631 | 407k | put_value(pbuf, pparams->group_color_numcomps); |
9632 | 407k | *pbuf++ = pparams->replacing; |
9633 | 407k | *pbuf++ = (pparams->function_is_identity) | (deep<<1); |
9634 | 407k | *pbuf++ = pparams->Background_components; |
9635 | 407k | *pbuf++ = pparams->Matte_components; |
9636 | 407k | put_value(pbuf, pparams->bbox); |
9637 | 407k | mask_id = pparams->mask_id; |
9638 | 407k | put_value(pbuf, mask_id); |
9639 | 407k | if (pparams->Background_components) { |
9640 | 1.18k | const int l = sizeof(pparams->Background[0]) * pparams->Background_components; |
9641 | | |
9642 | 1.18k | memcpy(pbuf, pparams->Background, l); |
9643 | 1.18k | pbuf += l; |
9644 | 1.18k | memcpy(pbuf, &pparams->GrayBackground, sizeof(pparams->GrayBackground)); |
9645 | 1.18k | pbuf += sizeof(pparams->GrayBackground); |
9646 | 1.18k | } |
9647 | 407k | if (pparams->Matte_components) { |
9648 | 105 | const int m = sizeof(pparams->Matte[0]) * pparams->Matte_components; |
9649 | | |
9650 | 105 | memcpy(pbuf, pparams->Matte, m); |
9651 | 105 | pbuf += m; |
9652 | 105 | } |
9653 | 407k | if (!pparams->function_is_identity) |
9654 | 1.36k | mask_size = (256+deep)<<deep; |
9655 | | /* Color space information may be ICC based |
9656 | | in this case we need to store the ICC |
9657 | | profile or the ID if it is cached already */ |
9658 | 407k | if (pparams->group_color_type == ICC) { |
9659 | | /* Check if it is already in the ICC clist table */ |
9660 | 348k | hashcode = gsicc_get_hash(pparams->iccprofile); |
9661 | 348k | found_icc = clist_icc_searchtable(cdev, hashcode); |
9662 | 348k | if (!found_icc) { |
9663 | | /* Add it to the table */ |
9664 | 2.76k | clist_icc_addentry(cdev, hashcode, pparams->iccprofile); |
9665 | 2.76k | put_value(pbuf, hashcode); |
9666 | 346k | } else { |
9667 | | /* It will be in the clist. Just write out the hashcode */ |
9668 | 346k | put_value(pbuf, hashcode); |
9669 | 346k | } |
9670 | 348k | } else { |
9671 | 58.7k | put_value(pbuf, hashcode); |
9672 | 58.7k | } |
9673 | 407k | break; |
9674 | 348k | case PDF14_END_TRANS_MASK: |
9675 | 348k | smask_level--; |
9676 | 348k | if (smask_level == 0 && trans_group_level == 0) |
9677 | 8.28k | pdf14_needed = cdev->page_pdf14_needed; |
9678 | 348k | break; |
9679 | 215k | case PDF14_SET_BLEND_PARAMS: |
9680 | 215k | if (pparams->blend_mode != BLEND_MODE_Normal || pparams->opacity != 1.0 || |
9681 | 0 | pparams->shape != 1.0) |
9682 | 215k | pdf14_needed = true; /* the compositor will be needed while reading */ |
9683 | 0 | else if (smask_level == 0 && trans_group_level == 0) |
9684 | 0 | pdf14_needed = false; /* At page level, set back to false */ |
9685 | 215k | if (smask_level == 0 && trans_group_level == 0) |
9686 | 83.1k | cdev->page_pdf14_needed = pdf14_needed; /* save for after popping to page level */ |
9687 | | /* Changed is now two bytes due to overprint stroke fill. Write as int */ |
9688 | 215k | put_value(pbuf, pparams->changed); |
9689 | 215k | if (pparams->changed & PDF14_SET_BLEND_MODE) |
9690 | 43.8k | *pbuf++ = pparams->blend_mode; |
9691 | 215k | if (pparams->changed & PDF14_SET_TEXT_KNOCKOUT) |
9692 | 20.9k | *pbuf++ = pparams->text_knockout; |
9693 | 215k | if (pparams->changed & PDF14_SET_AIS) |
9694 | 215k | put_value(pbuf, pparams->ais); |
9695 | 215k | if (pparams->changed & PDF14_SET_OVERPRINT) |
9696 | 215k | put_value(pbuf, pparams->overprint); |
9697 | 215k | if (pparams->changed & PDF14_SET_STROKEOVERPRINT) |
9698 | 215k | put_value(pbuf, pparams->stroke_overprint); |
9699 | 215k | if (pparams->changed & PDF14_SET_FILLCONSTANTALPHA) |
9700 | 215k | put_value(pbuf, pparams->fillconstantalpha); |
9701 | 215k | if (pparams->changed & PDF14_SET_STROKECONSTANTALPHA) |
9702 | 215k | put_value(pbuf, pparams->strokeconstantalpha); |
9703 | 215k | if (pparams->changed & PDF14_SET_FILLSTROKE_STATE) |
9704 | 215k | put_value(pbuf, pparams->op_fs_state); |
9705 | 215k | break; |
9706 | 0 | case PDF14_PUSH_TRANS_STATE: |
9707 | 0 | break; |
9708 | 51.0k | case PDF14_POP_TRANS_STATE: |
9709 | 51.0k | break; |
9710 | 0 | case PDF14_PUSH_SMASK_COLOR: |
9711 | 0 | return 0; /* We really should never be here */ |
9712 | 0 | break; |
9713 | 0 | case PDF14_POP_SMASK_COLOR: |
9714 | 0 | return 0; /* We really should never be here */ |
9715 | 0 | break; |
9716 | 2.05M | } |
9717 | | |
9718 | | /* check for fit */ |
9719 | 2.05M | need = (pbuf - buf) + mask_size; |
9720 | 2.05M | *psize = need; |
9721 | 2.05M | if (need > avail) { |
9722 | 300k | if (avail) |
9723 | 0 | return_error(gs_error_rangecheck); |
9724 | 300k | else |
9725 | 300k | return gs_error_rangecheck; |
9726 | 300k | } |
9727 | | |
9728 | | /* If we are writing more than the maximum ever expected, |
9729 | | * return a rangecheck error. Second check is for Coverity |
9730 | | */ |
9731 | 1.75M | if ((need + 3 > MAX_CLIST_COMPOSITOR_SIZE) || |
9732 | 1.75M | (need + 3 - mask_size > MAX_CLIST_TRANSPARENCY_BUFFER_SIZE) ) |
9733 | 0 | return_error(gs_error_rangecheck); |
9734 | | |
9735 | | /* Copy our serialized data into the output buffer */ |
9736 | 1.75M | memcpy(data, buf, need - mask_size); |
9737 | 1.75M | if (mask_size) /* Include the transfer mask data if present */ |
9738 | 1.05k | memcpy(data + need - mask_size, pparams->transfer_fn, mask_size); |
9739 | 1.75M | if_debug3m('v', cdev->memory, |
9740 | 1.75M | "[v] c_pdf14trans_write: opcode = %s mask_id=%d need = %d\n", |
9741 | 1.75M | pdf14_opcode_names[opcode], mask_id, need); |
9742 | 1.75M | cdev->pdf14_needed = pdf14_needed; /* all OK to update */ |
9743 | 1.75M | cdev->pdf14_trans_group_level = trans_group_level; |
9744 | 1.75M | cdev->pdf14_smask_level = smask_level; |
9745 | 1.75M | return 0; |
9746 | 1.75M | } |
9747 | | |
9748 | | #undef put_value |
9749 | | |
9750 | | /* Function prototypes */ |
9751 | | static int gs_create_pdf14trans( gs_composite_t ** ppct, |
9752 | | const gs_pdf14trans_params_t * pparams, |
9753 | | gs_memory_t * mem ); |
9754 | | |
9755 | | #define read_value(dp, value)\ |
9756 | 123M | BEGIN\ |
9757 | 123M | memcpy(&value, dp, sizeof(value));\ |
9758 | 123M | dp += sizeof(value);\ |
9759 | 123M | END |
9760 | | |
9761 | | /* |
9762 | | * Convert the string representation of the PDF 1.4 transparency parameter |
9763 | | * into the full compositor. |
9764 | | */ |
9765 | | static int |
9766 | | c_pdf14trans_read(gs_composite_t * * ppct, const byte * data, |
9767 | | uint size, gs_memory_t * mem ) |
9768 | 38.4M | { |
9769 | 38.4M | gs_pdf14trans_params_t params = {0}; |
9770 | 38.4M | const byte * start = data; |
9771 | 38.4M | int used, code = 0; |
9772 | 38.4M | bool deep; |
9773 | | |
9774 | 38.4M | if (size < 1) |
9775 | 0 | return_error(gs_error_rangecheck); |
9776 | | |
9777 | | /* Read PDF 1.4 compositor data from the clist */ |
9778 | 38.4M | params.pdf14_op = *data++; |
9779 | 38.4M | if_debug2m('v', mem, "[v] c_pdf14trans_read: opcode = %s avail = %d", |
9780 | 38.4M | pdf14_opcode_names[params.pdf14_op], size); |
9781 | 38.4M | memset(¶ms.ctm, 0, sizeof(params.ctm)); |
9782 | 38.4M | switch (params.pdf14_op) { |
9783 | 0 | default: /* Should not occur. */ |
9784 | 0 | break; |
9785 | 1.82M | case PDF14_PUSH_DEVICE: |
9786 | 1.82M | read_value(data, params.num_spot_colors); |
9787 | 1.82M | read_value(data, params.num_spot_colors_int); |
9788 | 1.82M | read_value(data, params.overprint_sim_push); |
9789 | 1.82M | read_value(data, params.is_pattern); |
9790 | 1.82M | break; |
9791 | 0 | case PDF14_ABORT_DEVICE: |
9792 | 0 | break; |
9793 | 1.82M | case PDF14_POP_DEVICE: |
9794 | 1.82M | read_value(data, params.is_pattern); |
9795 | 1.82M | break; |
9796 | 2.28M | case PDF14_END_TRANS_GROUP: |
9797 | 2.84M | case PDF14_END_TRANS_TEXT_GROUP: |
9798 | | #ifdef DEBUG |
9799 | | code += 0; /* A good place for a breakpoint. */ |
9800 | | #endif |
9801 | 2.84M | break; /* No data */ |
9802 | 0 | case PDF14_PUSH_TRANS_STATE: |
9803 | 0 | break; |
9804 | 3.73M | case PDF14_POP_TRANS_STATE: |
9805 | 3.73M | break; |
9806 | 714k | case PDF14_BEGIN_TRANS_PAGE_GROUP: |
9807 | 2.84M | case PDF14_BEGIN_TRANS_GROUP: |
9808 | | /* |
9809 | | * We are currently not using the bbox or the colorspace so they were |
9810 | | * not placed in the clist |
9811 | | */ |
9812 | 2.84M | data = cmd_read_matrix(¶ms.ctm, data); |
9813 | 2.84M | params.Isolated = (*data) & 1; |
9814 | 2.84M | params.Knockout = (*data++ >> 1) & 1; |
9815 | 2.84M | params.blend_mode = *data++; |
9816 | 2.84M | params.group_color_type = *data++; /* Trans group color */ |
9817 | 2.84M | params.page_group = *data++; |
9818 | 2.84M | read_value(data,params.group_color_numcomps); /* color group size */ |
9819 | 2.84M | read_value(data, params.opacity); |
9820 | 2.84M | read_value(data, params.shape); |
9821 | 2.84M | read_value(data, params.bbox); |
9822 | 2.84M | read_value(data, params.shade_group); |
9823 | 2.84M | read_value(data, params.text_group); |
9824 | 2.84M | read_value(data, params.mask_id); |
9825 | 2.84M | read_value(data, params.icc_hash); |
9826 | 2.84M | break; |
9827 | 5.24M | case PDF14_BEGIN_TRANS_MASK: |
9828 | | /* This is the largest transparency parameter at this time (potentially |
9829 | | * 1531 bytes in size if Background_components = |
9830 | | * GS_CLIENT_COLOR_MAX_COMPONENTS and Matte_components = |
9831 | | * GS_CLIENT_COLOR_MAX_COMPONENTS and we have a transfer function as well). |
9832 | | * |
9833 | | * NOTE: |
9834 | | * The clist reader must be able to handle this sized device. |
9835 | | * If any changes are made here the #define MAX_CLIST_COMPOSITOR_SIZE |
9836 | | * may also need to be changed correspondingly (defined in gstparam.h) |
9837 | | * Also... if another compositor param should exceed this size, this |
9838 | | * same condition applies. |
9839 | | */ |
9840 | 5.24M | data = cmd_read_matrix(¶ms.ctm, data); |
9841 | 5.24M | read_value(data, params.subtype); |
9842 | 5.24M | params.group_color_type = *data++; |
9843 | 5.24M | read_value(data, params.group_color_numcomps); |
9844 | 5.24M | params.replacing = *data++; |
9845 | 5.24M | params.function_is_identity = *data & 1; |
9846 | 5.24M | deep = (*data++)>>1; |
9847 | 5.24M | params.Background_components = *data++; |
9848 | 5.24M | params.Matte_components = *data++; |
9849 | 5.24M | read_value(data, params.bbox); |
9850 | 5.24M | read_value(data, params.mask_id); |
9851 | 5.24M | if (params.Background_components) { |
9852 | 81.4k | const int l = sizeof(params.Background[0]) * params.Background_components; |
9853 | | |
9854 | 81.4k | memcpy(params.Background, data, l); |
9855 | 81.4k | data += l; |
9856 | 81.4k | memcpy(¶ms.GrayBackground, data, sizeof(params.GrayBackground)); |
9857 | 81.4k | data += sizeof(params.GrayBackground); |
9858 | 81.4k | } |
9859 | 5.24M | if (params.Matte_components) { |
9860 | 4.21k | const int m = sizeof(params.Matte[0]) * params.Matte_components; |
9861 | | |
9862 | 4.21k | memcpy(params.Matte, data, m); |
9863 | 4.21k | data += m; |
9864 | 4.21k | } |
9865 | 5.24M | read_value(data, params.icc_hash); |
9866 | 5.24M | if (params.function_is_identity) { |
9867 | 5.20M | int i; |
9868 | | |
9869 | 5.20M | if (deep) { |
9870 | 0 | for (i = 0; i < MASK_TRANSFER_FUNCTION_SIZE; i++) |
9871 | 0 | ((uint16_t *)params.transfer_fn)[i] = i*0x10000/MASK_TRANSFER_FUNCTION_SIZE; |
9872 | 0 | ((uint16_t *)params.transfer_fn)[i] = 0xffff; |
9873 | 5.20M | } else { |
9874 | 1.33G | for (i = 0; i < MASK_TRANSFER_FUNCTION_SIZE; i++) { |
9875 | 1.33G | params.transfer_fn[i] = (byte)floor(i * |
9876 | 1.33G | (255.0 / (MASK_TRANSFER_FUNCTION_SIZE - 1)) + 0.5); |
9877 | 1.33G | } |
9878 | 5.20M | } |
9879 | 5.20M | } else { |
9880 | 34.7k | memcpy(params.transfer_fn, data, (256+deep)<<deep); |
9881 | 34.7k | data += (256+deep)<<deep; |
9882 | 34.7k | } |
9883 | 5.24M | break; |
9884 | 503k | case PDF14_END_TRANS_MASK: |
9885 | 503k | break; |
9886 | 0 | case PDF14_PUSH_SMASK_COLOR: |
9887 | 0 | return 0; |
9888 | 0 | break; |
9889 | 0 | case PDF14_POP_SMASK_COLOR: |
9890 | 0 | return 0; |
9891 | 0 | break; |
9892 | 19.6M | case PDF14_SET_BLEND_PARAMS: |
9893 | 19.6M | read_value(data, params.changed); |
9894 | 19.6M | if (params.changed & PDF14_SET_BLEND_MODE) |
9895 | 4.05M | params.blend_mode = *data++; |
9896 | 19.6M | if (params.changed & PDF14_SET_TEXT_KNOCKOUT) |
9897 | 1.77M | params.text_knockout = *data++; |
9898 | 19.6M | if (params.changed & PDF14_SET_AIS) |
9899 | 19.6M | read_value(data, params.ais); |
9900 | 19.6M | if (params.changed & PDF14_SET_OVERPRINT) |
9901 | 19.6M | read_value(data, params.overprint); |
9902 | 19.6M | if (params.changed & PDF14_SET_STROKEOVERPRINT) |
9903 | 19.6M | read_value(data, params.stroke_overprint); |
9904 | 19.6M | if (params.changed & PDF14_SET_FILLCONSTANTALPHA) |
9905 | 19.6M | read_value(data, params.fillconstantalpha); |
9906 | 19.6M | if (params.changed & PDF14_SET_STROKECONSTANTALPHA) |
9907 | 19.6M | read_value(data, params.strokeconstantalpha); |
9908 | 19.6M | if (params.changed & PDF14_SET_FILLSTROKE_STATE) |
9909 | 19.6M | read_value(data, params.op_fs_state); |
9910 | 19.6M | break; |
9911 | 38.4M | } |
9912 | 38.4M | code = gs_create_pdf14trans(ppct, ¶ms, mem); |
9913 | 38.4M | if (code < 0) |
9914 | 0 | return code; |
9915 | 38.4M | used = data - start; |
9916 | 38.4M | if_debug2m('v', mem, " mask_id=%d used = %d\n", params.mask_id, used); |
9917 | | |
9918 | | /* If we read more than the maximum expected, return a rangecheck error */ |
9919 | 38.4M | if ( used + 3 > MAX_CLIST_COMPOSITOR_SIZE ) |
9920 | 0 | return_error(gs_error_rangecheck); |
9921 | 38.4M | else |
9922 | 38.4M | return used; |
9923 | 38.4M | } |
9924 | | |
9925 | | /* |
9926 | | * Adjust the compositor's CTM. |
9927 | | */ |
9928 | | static int |
9929 | | c_pdf14trans_adjust_ctm(gs_composite_t * pct0, int x0, int y0, gs_gstate *pgs) |
9930 | 23.3M | { |
9931 | 23.3M | gs_pdf14trans_t *pct = (gs_pdf14trans_t *)pct0; |
9932 | 23.3M | gs_matrix mat = pct->params.ctm; |
9933 | | |
9934 | 23.3M | if_debug6m('L', pgs->memory, " [%g %g %g %g %g %g]\n", |
9935 | 23.3M | mat.xx, mat.xy, mat.yx, mat.yy, |
9936 | 23.3M | mat.tx, mat.ty); |
9937 | 23.3M | mat.tx -= x0; |
9938 | 23.3M | mat.ty -= y0; |
9939 | 23.3M | gs_gstate_setmatrix(pgs, &mat); |
9940 | 23.3M | return 0; |
9941 | 23.3M | } |
9942 | | |
9943 | | /* |
9944 | | * Create a PDF 1.4 transparency compositor. |
9945 | | * |
9946 | | * Note that this routine will be called only if the device is not already |
9947 | | * a PDF 1.4 transparency compositor. |
9948 | | * Return an error if it is not a PDF14_PUSH_DEVICE operation. |
9949 | | */ |
9950 | | static int |
9951 | | c_pdf14trans_create_default_compositor(const gs_composite_t * pct, |
9952 | | gx_device ** pp14dev, gx_device * tdev, gs_gstate * pgs, |
9953 | | gs_memory_t * mem) |
9954 | 1.16M | { |
9955 | 1.16M | const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct; |
9956 | 1.16M | int code = 0; |
9957 | | |
9958 | | /* |
9959 | | * We only handle the push operation. All other operations are ignored. |
9960 | | * The other operations will be handled by the composite routine |
9961 | | * for the PDF 1.4 compositing device. |
9962 | | */ |
9963 | 1.16M | switch (pdf14pct->params.pdf14_op) { |
9964 | 1.14M | case PDF14_PUSH_DEVICE: |
9965 | 1.14M | code = gs_pdf14_device_push(mem, pgs, pp14dev, tdev, pdf14pct); |
9966 | | /* Change (non-error) code to 1 to indicate that we created |
9967 | | * a device. */ |
9968 | 1.14M | if (code >= 0) |
9969 | 1.14M | code = 1; |
9970 | 1.14M | break; |
9971 | 26.6k | default: |
9972 | | /* No other compositor actions are allowed if this isn't a pdf14 compositor */ |
9973 | 26.6k | *pp14dev = NULL; |
9974 | 26.6k | return_error(gs_error_unregistered); |
9975 | 1.16M | } |
9976 | 1.14M | return code; |
9977 | 1.16M | } |
9978 | | |
9979 | | /* |
9980 | | * Find an opening compositor op. |
9981 | | */ |
9982 | | static gs_compositor_closing_state |
9983 | | find_opening_op(int opening_op, gs_composite_t **ppcte, |
9984 | | gs_compositor_closing_state return_code) |
9985 | 2.43M | { |
9986 | | /* Assuming a right *BEGIN* - *END* operation balance. */ |
9987 | 2.43M | gs_composite_t *pcte = *ppcte; |
9988 | | |
9989 | 5.54M | for (;;) { |
9990 | 5.54M | if (pcte->type->comp_id == GX_COMPOSITOR_PDF14_TRANS) { |
9991 | 5.20M | gs_pdf14trans_t *pct = (gs_pdf14trans_t *)pcte; |
9992 | 5.20M | int op = pct->params.pdf14_op; |
9993 | | |
9994 | 5.20M | *ppcte = pcte; |
9995 | 5.20M | if (op == opening_op) |
9996 | 1.53M | return return_code; |
9997 | 3.66M | if (op != PDF14_SET_BLEND_PARAMS) { |
9998 | 2.10M | if (opening_op == PDF14_BEGIN_TRANS_MASK) |
9999 | 826 | return COMP_ENQUEUE; |
10000 | 2.10M | if (opening_op == PDF14_BEGIN_TRANS_GROUP || opening_op == PDF14_BEGIN_TRANS_PAGE_GROUP) { |
10001 | 273k | if (op != PDF14_BEGIN_TRANS_MASK && op != PDF14_END_TRANS_MASK) |
10002 | 257k | return COMP_ENQUEUE; |
10003 | 273k | } |
10004 | 1.84M | if (opening_op == PDF14_PUSH_DEVICE) { |
10005 | 1.83M | if (op != PDF14_BEGIN_TRANS_MASK && op != PDF14_END_TRANS_MASK && |
10006 | 1.80M | op != PDF14_BEGIN_TRANS_GROUP && op != PDF14_BEGIN_TRANS_PAGE_GROUP && op != PDF14_END_TRANS_GROUP && |
10007 | 322k | op != PDF14_END_TRANS_TEXT_GROUP) |
10008 | 143k | return COMP_ENQUEUE; |
10009 | 1.83M | } |
10010 | 1.84M | } |
10011 | 3.66M | } else |
10012 | 337k | return COMP_ENQUEUE; |
10013 | 3.26M | pcte = pcte->prev; |
10014 | 3.26M | if (pcte == NULL) |
10015 | 156k | return COMP_EXEC_QUEUE; /* Not in queue. */ |
10016 | 3.26M | } |
10017 | 2.43M | } |
10018 | | |
10019 | | /* |
10020 | | * Find an opening compositor op. |
10021 | | */ |
10022 | | static gs_compositor_closing_state |
10023 | | find_same_op(const gs_composite_t *composite_action, int my_op, gs_composite_t **ppcte) |
10024 | 15.8M | { |
10025 | 15.8M | const gs_pdf14trans_t *pct0 = (gs_pdf14trans_t *)composite_action; |
10026 | 15.8M | gs_composite_t *pct = *ppcte; |
10027 | | |
10028 | 15.8M | for (;;) { |
10029 | 15.8M | if (pct->type->comp_id == GX_COMPOSITOR_PDF14_TRANS) { |
10030 | 13.6M | gs_pdf14trans_t *pct_pdf14 = (gs_pdf14trans_t *)pct; |
10031 | | |
10032 | 13.6M | *ppcte = pct; |
10033 | 13.6M | if (pct_pdf14->params.pdf14_op != my_op) |
10034 | 4.38M | return COMP_ENQUEUE; |
10035 | 9.22M | if (pct_pdf14->params.csel == pct0->params.csel) { |
10036 | | /* If the new parameters completely replace the old ones |
10037 | | then remove the old one from the queu */ |
10038 | 9.22M | if ((pct_pdf14->params.changed & pct0->params.changed) == |
10039 | 9.22M | pct_pdf14->params.changed) { |
10040 | 8.47M | return COMP_REPLACE_CURR; |
10041 | 8.47M | } else { |
10042 | 756k | return COMP_ENQUEUE; |
10043 | 756k | } |
10044 | 9.22M | } |
10045 | 9.22M | } else |
10046 | 2.25M | return COMP_ENQUEUE; |
10047 | 0 | pct = pct->prev; |
10048 | 0 | if (pct == NULL) |
10049 | 0 | return COMP_ENQUEUE; /* Not in queue. */ |
10050 | 0 | } |
10051 | 15.8M | } |
10052 | | |
10053 | | /* |
10054 | | * Check for closing compositor. |
10055 | | */ |
10056 | | static gs_compositor_closing_state |
10057 | | c_pdf14trans_is_closing(const gs_composite_t * composite_action, gs_composite_t ** ppcte, |
10058 | | gx_device *dev) |
10059 | 31.8M | { |
10060 | 31.8M | gs_pdf14trans_t *pct0 = (gs_pdf14trans_t *)composite_action; |
10061 | 31.8M | int op0 = pct0->params.pdf14_op; |
10062 | | |
10063 | 31.8M | switch (op0) { |
10064 | 0 | default: return_error(gs_error_unregistered); /* Must not happen. */ |
10065 | 1.24M | case PDF14_PUSH_DEVICE: |
10066 | 1.24M | return COMP_ENQUEUE; |
10067 | 0 | case PDF14_ABORT_DEVICE: |
10068 | 0 | return COMP_ENQUEUE; |
10069 | 1.24M | case PDF14_POP_DEVICE: |
10070 | 1.24M | if (*ppcte == NULL) |
10071 | 842k | return COMP_ENQUEUE; |
10072 | 406k | else { |
10073 | 406k | gs_compositor_closing_state state = find_opening_op(PDF14_PUSH_DEVICE, ppcte, COMP_EXEC_IDLE); |
10074 | | |
10075 | 406k | if (state == COMP_EXEC_IDLE) |
10076 | 106k | return COMP_DROP_QUEUE; |
10077 | 299k | return state; |
10078 | 406k | } |
10079 | 500k | case PDF14_BEGIN_TRANS_PAGE_GROUP: |
10080 | 2.36M | case PDF14_BEGIN_TRANS_GROUP: |
10081 | 2.36M | return COMP_ENQUEUE; |
10082 | 1.86M | case PDF14_END_TRANS_GROUP: |
10083 | 2.36M | case PDF14_END_TRANS_TEXT_GROUP: |
10084 | 2.36M | if (*ppcte == NULL) |
10085 | 483k | return COMP_EXEC_QUEUE; |
10086 | 1.88M | return find_opening_op(PDF14_BEGIN_TRANS_GROUP, ppcte, COMP_MARK_IDLE); |
10087 | 4.22M | case PDF14_BEGIN_TRANS_MASK: |
10088 | 4.22M | return COMP_ENQUEUE; |
10089 | 0 | case PDF14_PUSH_TRANS_STATE: |
10090 | 0 | return COMP_ENQUEUE; |
10091 | 3.02M | case PDF14_POP_TRANS_STATE: |
10092 | 3.02M | return COMP_ENQUEUE; |
10093 | 0 | case PDF14_PUSH_SMASK_COLOR: |
10094 | 0 | return COMP_ENQUEUE; |
10095 | 0 | break; |
10096 | 0 | case PDF14_POP_SMASK_COLOR: |
10097 | 0 | return COMP_ENQUEUE; |
10098 | 0 | break; |
10099 | 429k | case PDF14_END_TRANS_MASK: |
10100 | 429k | if (*ppcte == NULL) |
10101 | 288k | return COMP_EXEC_QUEUE; |
10102 | 141k | return find_opening_op(PDF14_BEGIN_TRANS_MASK, ppcte, COMP_MARK_IDLE); |
10103 | 16.8M | case PDF14_SET_BLEND_PARAMS: |
10104 | 16.8M | if (*ppcte == NULL) |
10105 | 1.01M | return COMP_ENQUEUE; |
10106 | | /* hack : ignore csel - here it is always zero : */ |
10107 | 15.8M | return find_same_op(composite_action, PDF14_SET_BLEND_PARAMS, ppcte); |
10108 | 31.8M | } |
10109 | 31.8M | } |
10110 | | |
10111 | | /* |
10112 | | * Check whether a next operation is friendly to the compositor. |
10113 | | */ |
10114 | | static bool |
10115 | | c_pdf14trans_is_friendly(const gs_composite_t * composite_action, byte cmd0, byte cmd1) |
10116 | 3.82M | { |
10117 | 3.82M | gs_pdf14trans_t *pct0 = (gs_pdf14trans_t *)composite_action; |
10118 | 3.82M | int op0 = pct0->params.pdf14_op; |
10119 | | |
10120 | 3.82M | if (op0 == PDF14_PUSH_DEVICE || op0 == PDF14_END_TRANS_GROUP || |
10121 | 2.50M | op0 == PDF14_END_TRANS_TEXT_GROUP) { |
10122 | | /* Halftone commands are always passed to the target printer device, |
10123 | | because transparency buffers are always contone. |
10124 | | So we're safe to execute them before queued transparency compositors. */ |
10125 | 1.34M | if (cmd0 == cmd_opv_extend && (cmd1 == cmd_opv_ext_put_halftone || |
10126 | 389k | cmd1 == cmd_opv_ext_put_ht_seg)) |
10127 | 636k | return true; |
10128 | 704k | if (cmd0 == cmd_opv_set_misc && (cmd1 >> 6) == (cmd_set_misc_map >> 6)) |
10129 | 700k | return true; |
10130 | 704k | } |
10131 | 2.48M | return false; |
10132 | 3.82M | } |
10133 | | |
10134 | | static composite_create_default_compositor_proc(c_pdf14trans_create_default_compositor); |
10135 | | static composite_equal_proc(c_pdf14trans_equal); |
10136 | | static composite_write_proc(c_pdf14trans_write); |
10137 | | static composite_read_proc(c_pdf14trans_read); |
10138 | | static composite_adjust_ctm_proc(c_pdf14trans_adjust_ctm); |
10139 | | static composite_is_closing_proc(c_pdf14trans_is_closing); |
10140 | | static composite_is_friendly_proc(c_pdf14trans_is_friendly); |
10141 | | static composite_clist_write_update(c_pdf14trans_clist_write_update); |
10142 | | static composite_clist_read_update(c_pdf14trans_clist_read_update); |
10143 | | static composite_get_cropping_proc(c_pdf14trans_get_cropping); |
10144 | | |
10145 | | /* |
10146 | | * Methods for the PDF 1.4 transparency compositor |
10147 | | * |
10148 | | * Note: We have two set of methods. They are the same except for the |
10149 | | * composite_clist_write_update method. Once the clist write device is created, |
10150 | | * we use the second set of procedures. This prevents the creation of multiple |
10151 | | * PDF 1.4 clist write compositor devices being chained together. |
10152 | | */ |
10153 | | const gs_composite_type_t gs_composite_pdf14trans_type = { |
10154 | | GX_COMPOSITOR_PDF14_TRANS, |
10155 | | { |
10156 | | c_pdf14trans_create_default_compositor, /* procs.create_default_compositor */ |
10157 | | c_pdf14trans_equal, /* procs.equal */ |
10158 | | c_pdf14trans_write, /* procs.write */ |
10159 | | c_pdf14trans_read, /* procs.read */ |
10160 | | c_pdf14trans_adjust_ctm, /* procs.adjust_ctm */ |
10161 | | c_pdf14trans_is_closing, /* procs.is_closing */ |
10162 | | c_pdf14trans_is_friendly, /* procs.is_friendly */ |
10163 | | /* Create a PDF 1.4 clist write device */ |
10164 | | c_pdf14trans_clist_write_update, /* procs.composite_clist_write_update */ |
10165 | | c_pdf14trans_clist_read_update, /* procs.composite_clist_read_update */ |
10166 | | c_pdf14trans_get_cropping /* procs.composite_get_cropping */ |
10167 | | } /* procs */ |
10168 | | }; |
10169 | | |
10170 | | const gs_composite_type_t gs_composite_pdf14trans_no_clist_writer_type = { |
10171 | | GX_COMPOSITOR_PDF14_TRANS, |
10172 | | { |
10173 | | c_pdf14trans_create_default_compositor, /* procs.create_default_compositor */ |
10174 | | c_pdf14trans_equal, /* procs.equal */ |
10175 | | c_pdf14trans_write, /* procs.write */ |
10176 | | c_pdf14trans_read, /* procs.read */ |
10177 | | c_pdf14trans_adjust_ctm, /* procs.adjust_ctm */ |
10178 | | c_pdf14trans_is_closing, /* procs.is_closing */ |
10179 | | c_pdf14trans_is_friendly, /* procs.is_friendly */ |
10180 | | /* The PDF 1.4 clist writer already exists, Do not create it. */ |
10181 | | gx_default_composite_clist_write_update, /* procs.composite_clist_write_update */ |
10182 | | c_pdf14trans_clist_read_update, /* procs.composite_clist_read_update */ |
10183 | | c_pdf14trans_get_cropping /* procs.composite_get_cropping */ |
10184 | | } /* procs */ |
10185 | | }; |
10186 | | |
10187 | | /* |
10188 | | * Verify that a compositor data structure is for the PDF 1.4 compositor. |
10189 | | */ |
10190 | | int |
10191 | | gs_is_pdf14trans_compositor(const gs_composite_t * pct) |
10192 | 230M | { |
10193 | 230M | return (pct->type == &gs_composite_pdf14trans_type |
10194 | 169M | || pct->type == &gs_composite_pdf14trans_no_clist_writer_type); |
10195 | 230M | } |
10196 | | |
10197 | | /* |
10198 | | * Create a PDF 1.4 transparency compositor data structure. |
10199 | | */ |
10200 | | static int |
10201 | | gs_create_pdf14trans( |
10202 | | gs_composite_t ** ppct, |
10203 | | const gs_pdf14trans_params_t * pparams, |
10204 | | gs_memory_t * mem ) |
10205 | 39.8M | { |
10206 | 39.8M | gs_pdf14trans_t * pct; |
10207 | | |
10208 | 39.8M | pct = gs_alloc_struct(mem, gs_pdf14trans_t, &st_pdf14trans, |
10209 | 39.8M | "gs_create_pdf14trans"); |
10210 | 39.8M | if (pct == NULL) |
10211 | 0 | return_error(gs_error_VMerror); |
10212 | 39.8M | pct->type = &gs_composite_pdf14trans_type; |
10213 | 39.8M | pct->id = gs_next_ids(mem, 1); |
10214 | 39.8M | pct->params = *pparams; |
10215 | 39.8M | pct->idle = false; |
10216 | 39.8M | *ppct = (gs_composite_t *)pct; |
10217 | 39.8M | return 0; |
10218 | 39.8M | } |
10219 | | |
10220 | | /* |
10221 | | * Send a PDF 1.4 transparency compositor action to the specified device. |
10222 | | */ |
10223 | | int |
10224 | | send_pdf14trans(gs_gstate * pgs, gx_device * dev, |
10225 | | gx_device * * pcdev, gs_pdf14trans_params_t * pparams, gs_memory_t * mem) |
10226 | 1.26M | { |
10227 | 1.26M | gs_composite_t * pct = NULL; |
10228 | 1.26M | int code; |
10229 | | |
10230 | 1.26M | pparams->ctm = ctm_only(pgs); |
10231 | 1.26M | code = gs_create_pdf14trans(&pct, pparams, mem); |
10232 | 1.26M | if (code < 0) |
10233 | 0 | return code; |
10234 | 1.26M | code = dev_proc(dev, composite) (dev, pcdev, pct, pgs, mem, NULL); |
10235 | 1.26M | if (code == gs_error_handled) |
10236 | 0 | code = 0; |
10237 | | |
10238 | 1.26M | gs_free_object(pgs->memory, pct, "send_pdf14trans"); |
10239 | | |
10240 | 1.26M | return code; |
10241 | 1.26M | } |
10242 | | |
10243 | | /* ------------- PDF 1.4 transparency device for clist writing ------------- */ |
10244 | | |
10245 | | /* |
10246 | | * The PDF 1.4 transparency compositor device may have a different process |
10247 | | * color model than the output device. If we are banding then we need to |
10248 | | * create two compositor devices. The output side (clist reader) needs a |
10249 | | * compositor to actually composite the output. We also need a compositor |
10250 | | * device before the clist writer. This is needed to provide a process color |
10251 | | * model which matches the PDF 1.4 blending space. |
10252 | | * |
10253 | | * This section provides support for this device. |
10254 | | */ |
10255 | | |
10256 | | /* |
10257 | | * Define the default pre-clist (clist writer) PDF 1.4 compositing device. |
10258 | | * We actually use the same structure for both the clist writer and reader |
10259 | | * devices. However we use separate names to identify the routines for each |
10260 | | * device. |
10261 | | */ |
10262 | | |
10263 | | static dev_proc_composite(pdf14_clist_composite); |
10264 | | static dev_proc_composite(pdf14_clist_forward_composite); |
10265 | | static dev_proc_fill_path(pdf14_clist_fill_path); |
10266 | | static dev_proc_stroke_path(pdf14_clist_stroke_path); |
10267 | | static dev_proc_fill_stroke_path(pdf14_clist_fill_stroke_path); |
10268 | | static dev_proc_text_begin(pdf14_clist_text_begin); |
10269 | | static dev_proc_begin_typed_image(pdf14_clist_begin_typed_image); |
10270 | | static dev_proc_copy_planes(pdf14_clist_copy_planes); |
10271 | | |
10272 | | static void |
10273 | | pdf14_clist_init_procs(gx_device *dev, |
10274 | | dev_proc_get_color_mapping_procs(get_color_mapping_procs), |
10275 | | dev_proc_get_color_comp_index(get_color_comp_index)) |
10276 | 11.2k | { |
10277 | 11.2k | set_dev_proc(dev, get_initial_matrix, gx_forward_get_initial_matrix); |
10278 | 11.2k | set_dev_proc(dev, sync_output, gx_forward_sync_output); |
10279 | 11.2k | set_dev_proc(dev, output_page, gx_forward_output_page); |
10280 | 11.2k | set_dev_proc(dev, close_device, gx_forward_close_device); |
10281 | 11.2k | set_dev_proc(dev, map_rgb_color, pdf14_encode_color); |
10282 | 11.2k | set_dev_proc(dev, map_color_rgb, pdf14_decode_color); |
10283 | 11.2k | set_dev_proc(dev, fill_rectangle, gx_forward_fill_rectangle); |
10284 | 11.2k | set_dev_proc(dev, copy_mono, gx_forward_copy_mono); |
10285 | 11.2k | set_dev_proc(dev, copy_color, gx_forward_copy_color); |
10286 | 11.2k | set_dev_proc(dev, get_params, gx_forward_get_params); |
10287 | 11.2k | set_dev_proc(dev, put_params, pdf14_put_params); |
10288 | 11.2k | set_dev_proc(dev, map_cmyk_color, pdf14_encode_color); |
10289 | 11.2k | set_dev_proc(dev, get_page_device, gx_forward_get_page_device); |
10290 | 11.2k | set_dev_proc(dev, copy_alpha, gx_forward_copy_alpha); |
10291 | 11.2k | set_dev_proc(dev, fill_path, pdf14_clist_fill_path); |
10292 | 11.2k | set_dev_proc(dev, stroke_path, pdf14_clist_stroke_path); |
10293 | 11.2k | set_dev_proc(dev, fill_mask, gx_forward_fill_mask); |
10294 | 11.2k | set_dev_proc(dev, fill_trapezoid, gx_forward_fill_trapezoid); |
10295 | 11.2k | set_dev_proc(dev, fill_parallelogram, gx_forward_fill_parallelogram); |
10296 | 11.2k | set_dev_proc(dev, fill_triangle, gx_forward_fill_triangle); |
10297 | 11.2k | set_dev_proc(dev, draw_thin_line, gx_forward_draw_thin_line); |
10298 | 11.2k | set_dev_proc(dev, strip_tile_rectangle, gx_forward_strip_tile_rectangle); |
10299 | 11.2k | set_dev_proc(dev, strip_copy_rop2, gx_forward_strip_copy_rop2); |
10300 | 11.2k | set_dev_proc(dev, get_clipping_box, gx_forward_get_clipping_box); |
10301 | 11.2k | set_dev_proc(dev, begin_typed_image, pdf14_clist_begin_typed_image); |
10302 | 11.2k | set_dev_proc(dev, get_bits_rectangle, gx_forward_get_bits_rectangle); |
10303 | 11.2k | set_dev_proc(dev, composite, pdf14_clist_composite); |
10304 | 11.2k | set_dev_proc(dev, get_hardware_params, gx_forward_get_hardware_params); |
10305 | 11.2k | set_dev_proc(dev, text_begin, pdf14_clist_text_begin); |
10306 | 11.2k | set_dev_proc(dev, begin_transparency_group, pdf14_begin_transparency_group); |
10307 | 11.2k | set_dev_proc(dev, end_transparency_group, pdf14_end_transparency_group); |
10308 | 11.2k | set_dev_proc(dev, begin_transparency_mask, pdf14_begin_transparency_mask); |
10309 | 11.2k | set_dev_proc(dev, end_transparency_mask, pdf14_end_transparency_mask); |
10310 | 11.2k | set_dev_proc(dev, discard_transparency_layer, gx_default_discard_transparency_layer); |
10311 | 11.2k | set_dev_proc(dev, get_color_mapping_procs, get_color_mapping_procs); |
10312 | 11.2k | set_dev_proc(dev, get_color_comp_index, get_color_comp_index); |
10313 | 11.2k | set_dev_proc(dev, encode_color, pdf14_encode_color); |
10314 | 11.2k | set_dev_proc(dev, decode_color, pdf14_decode_color); |
10315 | 11.2k | set_dev_proc(dev, fill_rectangle_hl_color, gx_forward_fill_rectangle_hl_color); |
10316 | 11.2k | set_dev_proc(dev, update_spot_equivalent_colors, gx_forward_update_spot_equivalent_colors); |
10317 | 11.2k | set_dev_proc(dev, ret_devn_params, pdf14_ret_devn_params); |
10318 | 11.2k | set_dev_proc(dev, fillpage, gx_forward_fillpage); |
10319 | 11.2k | set_dev_proc(dev, push_transparency_state, pdf14_push_transparency_state); |
10320 | 11.2k | set_dev_proc(dev, pop_transparency_state, pdf14_pop_transparency_state); |
10321 | 11.2k | set_dev_proc(dev, dev_spec_op, pdf14_dev_spec_op); |
10322 | 11.2k | set_dev_proc(dev, copy_planes, pdf14_clist_copy_planes); |
10323 | 11.2k | set_dev_proc(dev, set_graphics_type_tag, gx_forward_set_graphics_type_tag); |
10324 | 11.2k | set_dev_proc(dev, copy_alpha_hl_color, gx_forward_copy_alpha_hl_color); |
10325 | 11.2k | set_dev_proc(dev, fill_stroke_path, pdf14_clist_fill_stroke_path); |
10326 | 11.2k | } |
10327 | | |
10328 | | static void |
10329 | | pdf14_clist_Gray_initialize_device_procs(gx_device *dev) |
10330 | 3.44k | { |
10331 | 3.44k | pdf14_clist_init_procs(dev, |
10332 | 3.44k | gx_default_DevGray_get_color_mapping_procs, |
10333 | 3.44k | gx_default_DevGray_get_color_comp_index); |
10334 | 3.44k | } |
10335 | | |
10336 | | static void |
10337 | | pdf14_clist_RGB_initialize_device_procs(gx_device *dev) |
10338 | 6.51k | { |
10339 | 6.51k | pdf14_clist_init_procs(dev, |
10340 | 6.51k | gx_default_DevRGB_get_color_mapping_procs, |
10341 | 6.51k | gx_default_DevRGB_get_color_comp_index); |
10342 | 6.51k | } |
10343 | | |
10344 | | static void |
10345 | | pdf14_clist_CMYK_initialize_device_procs(gx_device *dev) |
10346 | 13 | { |
10347 | 13 | pdf14_clist_init_procs(dev, |
10348 | 13 | gx_default_DevCMYK_get_color_mapping_procs, |
10349 | 13 | gx_default_DevCMYK_get_color_comp_index); |
10350 | 13 | } |
10351 | | |
10352 | | static void |
10353 | | pdf14_clist_CMYKspot_initialize_device_procs(gx_device *dev) |
10354 | 1.23k | { |
10355 | 1.23k | pdf14_clist_init_procs(dev, |
10356 | 1.23k | pdf14_cmykspot_get_color_mapping_procs, |
10357 | 1.23k | pdf14_cmykspot_get_color_comp_index); |
10358 | 1.23k | } |
10359 | | |
10360 | | static void |
10361 | | pdf14_clist_RGBspot_initialize_device_procs(gx_device *dev) |
10362 | 0 | { |
10363 | 0 | pdf14_clist_init_procs(dev, |
10364 | 0 | pdf14_rgbspot_get_color_mapping_procs, |
10365 | 0 | pdf14_rgbspot_get_color_comp_index); |
10366 | 0 | } |
10367 | | |
10368 | | #if 0 /* NOT USED */ |
10369 | | static int |
10370 | | pdf14_clist_Grayspot_initialize_device_procs(gx_device *dev) |
10371 | | { |
10372 | | pdf14_clist_init_procs(dev, |
10373 | | pdf14_grayspot_get_color_mapping_procs, |
10374 | | pdf14_grayspot_get_color_comp_index); |
10375 | | } |
10376 | | #endif /* NOT USED */ |
10377 | | |
10378 | | const pdf14_clist_device pdf14_clist_Gray_device = { |
10379 | | std_device_color_stype_body(pdf14_clist_device, |
10380 | | pdf14_clist_Gray_initialize_device_procs, |
10381 | | "pdf14clistgray", |
10382 | | &st_pdf14_device, |
10383 | | XSIZE, YSIZE, X_DPI, Y_DPI, 8, 255, 256), |
10384 | | { 0 }, /* Procs */ |
10385 | | NULL, /* target */ |
10386 | | { 0 }, /* devn_params - not used */ |
10387 | | &gray_pdf14_procs, |
10388 | | &gray_blending_procs |
10389 | | }; |
10390 | | |
10391 | | const pdf14_clist_device pdf14_clist_RGB_device = { |
10392 | | std_device_color_stype_body(pdf14_clist_device, |
10393 | | pdf14_clist_RGB_initialize_device_procs, |
10394 | | "pdf14clistRGB", |
10395 | | &st_pdf14_device, |
10396 | | XSIZE, YSIZE, X_DPI, Y_DPI, 24, 255, 256), |
10397 | | { 0 }, /* Procs */ |
10398 | | NULL, /* target */ |
10399 | | { 0 }, /* devn_params - not used */ |
10400 | | &rgb_pdf14_procs, |
10401 | | &rgb_blending_procs |
10402 | | }; |
10403 | | |
10404 | | const pdf14_clist_device pdf14_clist_RGBspot_device = { |
10405 | | std_device_part1_(pdf14_device, |
10406 | | pdf14_clist_RGBspot_initialize_device_procs, |
10407 | | "pdf14clistrgbspot", |
10408 | | &st_pdf14_device, |
10409 | | open_init_closed), |
10410 | | dci_values_add(GX_DEVICE_COLOR_MAX_COMPONENTS,64,255,255,256,256), |
10411 | | std_device_part2_(XSIZE, YSIZE, X_DPI, Y_DPI), |
10412 | | offset_margin_values(0, 0, 0, 0, 0, 0), |
10413 | | std_device_part3_(), |
10414 | | { 0 }, /* Procs */ |
10415 | | NULL, /* target */ |
10416 | | /* DeviceN parameters */ |
10417 | | { 8, /* Not used - Bits per color */ |
10418 | | DeviceRGBComponents, /* Names of color model colorants */ |
10419 | | 3, /* Number colorants for CMYK */ |
10420 | | 0, /* MaxSeparations has not been specified */ |
10421 | | -1, /* PageSpotColors has not been specified */ |
10422 | | {0}, /* SeparationNames */ |
10423 | | 0, /* SeparationOrder names */ |
10424 | | {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */ |
10425 | | }, |
10426 | | &rgbspot_pdf14_procs, |
10427 | | &rgb_blending_procs |
10428 | | }; |
10429 | | |
10430 | | const pdf14_clist_device pdf14_clist_CMYK_device = { |
10431 | | std_device_std_color_full_body_type(pdf14_clist_device, |
10432 | | pdf14_clist_CMYK_initialize_device_procs, |
10433 | | "pdf14clistcmyk", |
10434 | | &st_pdf14_device, |
10435 | | XSIZE, YSIZE, X_DPI, Y_DPI, 32, |
10436 | | 0, 0, 0, 0, 0, 0), |
10437 | | { 0 }, /* Procs */ |
10438 | | NULL, /* target */ |
10439 | | { 0 }, /* devn_params - not used */ |
10440 | | &cmyk_pdf14_procs, |
10441 | | &cmyk_blending_procs |
10442 | | }; |
10443 | | |
10444 | | const pdf14_clist_device pdf14_clist_CMYKspot_device = { |
10445 | | std_device_part1_(pdf14_device, |
10446 | | pdf14_clist_CMYKspot_initialize_device_procs, |
10447 | | "pdf14clistcmykspot", |
10448 | | &st_pdf14_device, |
10449 | | open_init_closed), |
10450 | | dci_values(GX_DEVICE_COLOR_MAX_COMPONENTS,64,255,255,256,256), |
10451 | | std_device_part2_(XSIZE, YSIZE, X_DPI, Y_DPI), |
10452 | | offset_margin_values(0, 0, 0, 0, 0, 0), |
10453 | | std_device_part3_(), |
10454 | | { 0 }, /* Procs */ |
10455 | | NULL, /* target */ |
10456 | | /* DeviceN parameters */ |
10457 | | { 8, /* Not used - Bits per color */ |
10458 | | DeviceCMYKComponents, /* Names of color model colorants */ |
10459 | | 4, /* Number colorants for CMYK */ |
10460 | | 0, /* MaxSeparations has not been specified */ |
10461 | | -1, /* PageSpotColors has not been specified */ |
10462 | | {0}, /* SeparationNames */ |
10463 | | 0, /* SeparationOrder names */ |
10464 | | {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */ |
10465 | | }, |
10466 | | &cmykspot_pdf14_procs, |
10467 | | &cmyk_blending_procs |
10468 | | }; |
10469 | | |
10470 | | const pdf14_clist_device pdf14_clist_custom_device = { |
10471 | | std_device_part1_(pdf14_device, |
10472 | | pdf14_clist_CMYKspot_initialize_device_procs, |
10473 | | "pdf14clistcustom", |
10474 | | &st_pdf14_device, |
10475 | | open_init_closed), |
10476 | | dci_values(GX_DEVICE_COLOR_MAX_COMPONENTS,64,255,255,256,256), |
10477 | | std_device_part2_(XSIZE, YSIZE, X_DPI, Y_DPI), |
10478 | | offset_margin_values(0, 0, 0, 0, 0, 0), |
10479 | | std_device_part3_(), |
10480 | | { 0 }, /* Procs */ |
10481 | | NULL, /* target */ |
10482 | | /* DeviceN parameters */ |
10483 | | { 8, /* Not used - Bits per color */ |
10484 | | DeviceCMYKComponents, /* Names of color model colorants */ |
10485 | | 4, /* Number colorants for CMYK */ |
10486 | | 0, /* MaxSeparations has not been specified */ |
10487 | | -1, /* PageSpotColors has not been specified */ |
10488 | | {0}, /* SeparationNames */ |
10489 | | 0, /* SeparationOrder names */ |
10490 | | {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */ |
10491 | | }, |
10492 | | &custom_pdf14_procs, |
10493 | | &custom_blending_procs |
10494 | | }; |
10495 | | |
10496 | | /* |
10497 | | * the PDF 1.4 transparency spec says that color space for blending |
10498 | | * operations can be based upon either a color space specified in the |
10499 | | * group or a default value based upon the output device. We are |
10500 | | * currently only using a color space based upon the device. |
10501 | | */ |
10502 | | static int |
10503 | | get_pdf14_clist_device_proto(gx_device *dev, |
10504 | | pdf14_clist_device *pdevproto, |
10505 | | gs_gstate *pgs, |
10506 | | const gs_pdf14trans_t *pdf14pct, |
10507 | | bool use_pdf14_accum) |
10508 | 11.2k | { |
10509 | 11.2k | pdf14_blend_cs_t blend_cs_state; |
10510 | 11.2k | pdf14_default_colorspace_t dev_cs = |
10511 | 11.2k | pdf14_determine_default_blend_cs(dev, use_pdf14_accum, |
10512 | 11.2k | &blend_cs_state); |
10513 | 11.2k | bool deep = device_is_deep(dev); |
10514 | 11.2k | int num_spots = pdf14pct->params.num_spot_colors; |
10515 | | |
10516 | | /* overprint overide */ |
10517 | 11.2k | if (pdf14pct->params.overprint_sim_push && |
10518 | 0 | blend_cs_state == PDF14_BLEND_CS_UNSPECIFIED) { |
10519 | |
|
10520 | 0 | if (pdf14pct->params.num_spot_colors_int > 0) { |
10521 | 0 | dev_cs = PDF14_DeviceCMYKspot; |
10522 | 0 | num_spots = pdf14pct->params.num_spot_colors_int; |
10523 | 0 | } else |
10524 | 0 | dev_cs = PDF14_DeviceCMYK; |
10525 | 0 | } |
10526 | | |
10527 | 11.2k | switch (dev_cs) { |
10528 | 3.44k | case PDF14_DeviceGray: |
10529 | | /* We want gray to be single channel. Low level |
10530 | | initialization of gray device prototype is |
10531 | | peculiar in that in dci_std_color_num_components |
10532 | | the comment is |
10533 | | "A device is monochrome only if it is bi-level" |
10534 | | Here we want monochrome anytime we have a gray device. |
10535 | | To avoid breaking things elsewhere, we will overide |
10536 | | the prototype intialization here */ |
10537 | 3.44k | *pdevproto = pdf14_clist_Gray_device; |
10538 | 3.44k | pdevproto->color_info.max_components = 1; |
10539 | 3.44k | pdevproto->color_info.num_components = |
10540 | 3.44k | pdevproto->color_info.max_components; |
10541 | 3.44k | pdevproto->color_info.max_gray = deep ? 65535 : 255; |
10542 | 3.44k | pdevproto->color_info.gray_index = 0; /* Avoid halftoning */ |
10543 | 3.44k | pdevproto->color_info.dither_grays = pdevproto->color_info.max_gray+1; |
10544 | 3.44k | pdevproto->color_info.anti_alias = dev->color_info.anti_alias; |
10545 | 3.44k | pdevproto->color_info.depth = deep ? 16 : 8; |
10546 | 3.44k | pdevproto->sep_device = false; |
10547 | 3.44k | break; |
10548 | 6.51k | case PDF14_DeviceRGB: |
10549 | 6.51k | *pdevproto = pdf14_clist_RGB_device; |
10550 | 6.51k | pdevproto->color_info.anti_alias = dev->color_info.anti_alias; |
10551 | 6.51k | pdevproto->sep_device = false; |
10552 | 6.51k | if (deep) { |
10553 | 0 | pdevproto->color_info.depth = 3*16; |
10554 | 0 | pdevproto->color_info.max_color = 65535; |
10555 | 0 | pdevproto->color_info.max_gray = 65535; |
10556 | 0 | pdevproto->color_info.dither_colors = 65536; |
10557 | 0 | pdevproto->color_info.dither_grays = 65536; |
10558 | 0 | } |
10559 | 6.51k | break; |
10560 | 13 | case PDF14_DeviceCMYK: |
10561 | 13 | *pdevproto = pdf14_clist_CMYK_device; |
10562 | 13 | pdevproto->color_info.anti_alias = dev->color_info.anti_alias; |
10563 | 13 | pdevproto->sep_device = false; |
10564 | 13 | if (deep) { |
10565 | 0 | pdevproto->color_info.depth = 4*16; |
10566 | 0 | pdevproto->color_info.max_color = 65535; |
10567 | 0 | pdevproto->color_info.max_gray = 65535; |
10568 | 0 | pdevproto->color_info.dither_colors = 65536; |
10569 | 0 | pdevproto->color_info.dither_grays = 65536; |
10570 | 0 | } |
10571 | 13 | break; |
10572 | 1.23k | case PDF14_DeviceCMYKspot: |
10573 | 1.23k | *pdevproto = pdf14_clist_CMYKspot_device; |
10574 | | /* |
10575 | | * The number of components for the PDF14 device is the sum |
10576 | | * of the process components and the number of spot colors |
10577 | | * for the page. If we are using an NCLR ICC profile at |
10578 | | * the output device, those spot colors are skipped. They |
10579 | | * do not appear in the transparency buffer, but appear |
10580 | | * during put image transform of the page group to the target |
10581 | | * color space. |
10582 | | */ |
10583 | 1.23k | if (num_spots >= 0) { |
10584 | 1.23k | pdevproto->devn_params.page_spot_colors = num_spots; |
10585 | 1.23k | pdevproto->color_info.num_components = |
10586 | 1.23k | pdevproto->devn_params.num_std_colorant_names + num_spots; |
10587 | 1.23k | if (pdevproto->color_info.num_components > |
10588 | 1.23k | pdevproto->color_info.max_components) |
10589 | 0 | pdevproto->color_info.num_components = |
10590 | 0 | pdevproto->color_info.max_components; |
10591 | 1.23k | pdevproto->color_info.depth = |
10592 | 1.23k | pdevproto->color_info.num_components * (8<<deep); |
10593 | 1.23k | } |
10594 | 1.23k | pdevproto->color_info.anti_alias = dev->color_info.anti_alias; |
10595 | 1.23k | pdevproto->sep_device = true; |
10596 | 1.23k | break; |
10597 | 0 | case PDF14_DeviceRGBspot: |
10598 | 0 | *pdevproto = pdf14_clist_RGBspot_device; |
10599 | | /* |
10600 | | * The number of components for the PDF14 device is the sum |
10601 | | * of the process components and the number of spot colors |
10602 | | * for the page. If we are using an NCLR ICC profile at |
10603 | | * the output device, those spot colors are skipped. They |
10604 | | * do not appear in the transparency buffer, but appear |
10605 | | * during put image transform of the page group to the target |
10606 | | * color space. |
10607 | | */ |
10608 | 0 | if (num_spots >= 0) { |
10609 | 0 | pdevproto->devn_params.page_spot_colors = num_spots; |
10610 | 0 | pdevproto->color_info.num_components = |
10611 | 0 | pdevproto->devn_params.num_std_colorant_names + num_spots; |
10612 | 0 | if (pdevproto->color_info.num_components > |
10613 | 0 | pdevproto->color_info.max_components) |
10614 | 0 | pdevproto->color_info.num_components = |
10615 | 0 | pdevproto->color_info.max_components; |
10616 | 0 | pdevproto->color_info.depth = |
10617 | 0 | pdevproto->color_info.num_components * (8 << deep); |
10618 | 0 | } |
10619 | 0 | pdevproto->color_info.anti_alias = dev->color_info.anti_alias; |
10620 | 0 | pdevproto->sep_device = true; |
10621 | 0 | break; |
10622 | 0 | case PDF14_DeviceCustom: |
10623 | | /* |
10624 | | * We are using the output device's process color model. The |
10625 | | * color_info for the PDF 1.4 compositing device needs to match |
10626 | | * the output device. |
10627 | | */ |
10628 | 0 | *pdevproto = pdf14_clist_custom_device; |
10629 | 0 | pdevproto->color_info = dev->color_info; |
10630 | | /* The pdf14 device has to be 8 (or 16) bit continuous tone. Force it */ |
10631 | 0 | pdevproto->color_info.depth = |
10632 | 0 | pdevproto->color_info.num_components * (8<<deep); |
10633 | 0 | pdevproto->color_info.max_gray = deep ? 65535 : 255; |
10634 | 0 | pdevproto->color_info.max_color = deep ? 65535 : 255; |
10635 | 0 | pdevproto->color_info.dither_grays = deep ? 65536 : 256; |
10636 | 0 | pdevproto->color_info.dither_colors = deep ? 65536 : 256; |
10637 | 0 | pdevproto->color_info.anti_alias = dev->color_info.anti_alias; |
10638 | 0 | break; |
10639 | 0 | default: /* Should not occur */ |
10640 | 0 | return_error(gs_error_rangecheck); |
10641 | 11.2k | } |
10642 | 11.2k | pdevproto->overprint_sim = pdf14pct->params.overprint_sim_push; |
10643 | 11.2k | pdevproto->blend_cs_state = blend_cs_state; |
10644 | 11.2k | return 0; |
10645 | 11.2k | } |
10646 | | |
10647 | | static int |
10648 | | pdf14_create_clist_device(gs_memory_t *mem, gs_gstate * pgs, |
10649 | | gx_device ** ppdev, gx_device * target, |
10650 | | const gs_pdf14trans_t * pdf14pct) |
10651 | 11.2k | { |
10652 | 11.2k | pdf14_clist_device dev_proto; |
10653 | 11.2k | pdf14_clist_device * pdev; |
10654 | 11.2k | int code; |
10655 | 11.2k | bool has_tags = device_encodes_tags(target); |
10656 | 11.2k | cmm_profile_t *target_profile; |
10657 | 11.2k | gsicc_rendering_param_t render_cond; |
10658 | 11.2k | cmm_dev_profile_t *dev_profile; |
10659 | 11.2k | uchar k; |
10660 | 11.2k | bool deep = device_is_deep(target); |
10661 | 11.2k | cmm_profile_t *icc_profile; |
10662 | 11.2k | int nc; |
10663 | | |
10664 | 11.2k | code = dev_proc(target, get_profile)(target, &dev_profile); |
10665 | 11.2k | if (code < 0) |
10666 | 0 | return code; |
10667 | 11.2k | gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &target_profile, |
10668 | 11.2k | &render_cond); |
10669 | 11.2k | if_debug0m('v', pgs->memory, "[v]pdf14_create_clist_device\n"); |
10670 | | /* Prototypes never include tags. We add those in later. */ |
10671 | 11.2k | code = get_pdf14_clist_device_proto(target, &dev_proto, |
10672 | 11.2k | pgs, pdf14pct, false); |
10673 | 11.2k | if (code < 0) |
10674 | 0 | return code; |
10675 | 11.2k | code = gs_copydevice((gx_device **) &pdev, |
10676 | 11.2k | (const gx_device *) &dev_proto, mem); |
10677 | 11.2k | if (code < 0) |
10678 | 0 | return code; |
10679 | | |
10680 | 11.2k | nc = pdev->color_info.num_components; |
10681 | | /* If we are not using a blending color space, the number of color planes |
10682 | | should not exceed that of the target */ |
10683 | 11.2k | if (!(pdev->blend_cs_state != PDF14_BLEND_CS_UNSPECIFIED || pdev->overprint_sim)) { |
10684 | 11.2k | if (nc > target->color_info.num_components - device_encodes_tags(target) + device_encodes_tags((gx_device *)pdev)) |
10685 | 0 | nc = target->color_info.num_components - device_encodes_tags(target) + device_encodes_tags((gx_device *)pdev); |
10686 | 11.2k | if (pdev->color_info.max_components > target->color_info.max_components) |
10687 | 1.30k | pdev->color_info.max_components = target->color_info.max_components; |
10688 | 11.2k | } |
10689 | 11.2k | if (pdf14pct->params.overprint_sim_push && pdf14pct->params.num_spot_colors_int > 0 && target->num_planar_planes == 0) |
10690 | 0 | nc = pdev->color_info.num_components + pdf14pct->params.num_spot_colors_int; |
10691 | | |
10692 | 11.2k | pdev->color_info.num_components = nc; |
10693 | 11.2k | pdev->color_info.depth = pdev->color_info.num_components * (8<<deep); |
10694 | 11.2k | pdev->pad = target->pad; |
10695 | 11.2k | pdev->log2_align_mod = target->log2_align_mod; |
10696 | | |
10697 | 11.2k | pdev->interpolate_threshold = dev_proc(target, dev_spec_op)(target, gxdso_interpolate_threshold, NULL, 0); |
10698 | | |
10699 | 11.2k | pdev->op_state = pgs->is_fill_color ? PDF14_OP_STATE_FILL : PDF14_OP_STATE_NONE; |
10700 | | |
10701 | 11.2k | if (deep) { |
10702 | 0 | set_dev_proc(pdev, encode_color, pdf14_encode_color16); |
10703 | 0 | set_dev_proc(pdev, decode_color, pdf14_decode_color16); |
10704 | 0 | } |
10705 | | /* If we have a tag device then go ahead and do a special encoder decoder |
10706 | | for the pdf14 device to make sure we maintain this information in the |
10707 | | encoded color information. We could use the target device's methods but |
10708 | | the PDF14 device has to maintain 8 bit color always and we could run |
10709 | | into other issues if the number of colorants became large. If we need to |
10710 | | do compressed color with tags that will be a special project at that time */ |
10711 | 11.2k | if (has_tags) { |
10712 | 0 | set_dev_proc(pdev, encode_color, deep ? pdf14_encode_color16_tag: pdf14_encode_color_tag); |
10713 | 0 | } |
10714 | 11.2k | pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN_STANDARD; /* this is the standard */ |
10715 | 11.2k | gx_device_fill_in_procs((gx_device *)pdev); |
10716 | | /* Copying the params adds the tags to the color_info if required. */ |
10717 | 11.2k | gs_pdf14_device_copy_params((gx_device *)pdev, target); |
10718 | 11.2k | if (target->num_planar_planes > 0) |
10719 | 1.34k | pdev->num_planar_planes = pdev->color_info.num_components; |
10720 | 11.2k | gx_device_set_target((gx_device_forward *)pdev, target); |
10721 | | |
10722 | | /* Components shift, etc have to be based upon 8 bit */ |
10723 | 39.2k | for (k = 0; k < pdev->color_info.num_components; k++) { |
10724 | 28.0k | pdev->color_info.comp_bits[k] = 8<<deep; |
10725 | 28.0k | pdev->color_info.comp_shift[k] = (pdev->color_info.num_components - 1 - k) * (8<<deep); |
10726 | 28.0k | } |
10727 | 11.2k | code = dev_proc((gx_device *) pdev, open_device) ((gx_device *) pdev); |
10728 | 11.2k | if (code < 0) |
10729 | 0 | return code; |
10730 | 11.2k | pdev->pclist_device = target; |
10731 | | |
10732 | 11.2k | code = dev_proc(target, get_profile)(target, &dev_profile); |
10733 | 11.2k | if (code < 0) |
10734 | 0 | return code; |
10735 | 11.2k | gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &icc_profile, |
10736 | 11.2k | &render_cond); |
10737 | 11.2k | if_debug0m('v', mem, "[v]pdf14_create_clist_device\n"); |
10738 | | |
10739 | | /* Simulated overprint case. We have to use CMYK-based profile |
10740 | | Also if the target profile is NCLR, we are going to use a pdf14 |
10741 | | device that is CMYK based and do the mapping to the NCLR profile |
10742 | | when the put_image occurs */ |
10743 | 11.2k | if ((pdev->overprint_sim && icc_profile->data_cs != gsCMYK) || |
10744 | 11.2k | icc_profile->data_cs == gsNCHANNEL) { |
10745 | 0 | gsicc_adjust_profile_rc(pgs->icc_manager->default_cmyk, 1, "pdf14_create_clist_device"); |
10746 | 0 | gsicc_adjust_profile_rc(pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], |
10747 | 0 | -1, "pdf14_create_clist_device"); |
10748 | 0 | pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] = pgs->icc_manager->default_cmyk; |
10749 | 11.2k | } else { |
10750 | | /* If the target profile was CIELAB, then overide with default RGB for |
10751 | | proper blending. During put_image we will convert from RGB to |
10752 | | CIELAB */ |
10753 | 11.2k | if ((target_profile->data_cs == gsCIELAB || target_profile->islab) && |
10754 | 0 | pdev->blend_cs_state == PDF14_BLEND_CS_UNSPECIFIED) { |
10755 | 0 | pdev->blend_cs_state = PDF14_BLEND_CS_TARGET_CIELAB; |
10756 | 0 | rc_assign(pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], |
10757 | 0 | pgs->icc_manager->default_rgb, "pdf14_create_clist_device"); |
10758 | 0 | } |
10759 | 11.2k | } |
10760 | | |
10761 | 11.2k | if (pdf14pct->params.overprint_sim_push && |
10762 | 0 | pdf14pct->params.num_spot_colors_int > 0) { |
10763 | 0 | pdev->procs.update_spot_equivalent_colors = pdf14_update_spot_equivalent_colors; |
10764 | 0 | pdev->procs.ret_devn_params = pdf14_ret_devn_params; |
10765 | 0 | pdev->op_pequiv_cmyk_colors.all_color_info_valid = false; |
10766 | 0 | pdev->target_support_devn = pdev->icc_struct->supports_devn; |
10767 | 0 | pdev->icc_struct->supports_devn = true; /* Reset when pdf14 device is disabled */ |
10768 | 0 | } |
10769 | | /* if the device has separations already defined (by SeparationOrderNames) */ |
10770 | | /* we need to copy them (allocating new names) so the colorants are in the */ |
10771 | | /* same order as the target device. */ |
10772 | 11.2k | if (dev_proc(target, dev_spec_op)(target, gxdso_supports_devn, NULL, 0) > 0) { |
10773 | 1.34k | code = devn_copy_params(target, (gx_device *)pdev); |
10774 | 1.34k | if (code < 0) |
10775 | 0 | return code; |
10776 | 1.34k | } |
10777 | 11.2k | pdev->my_encode_color = dev_proc(pdev, encode_color); |
10778 | 11.2k | pdev->my_decode_color = dev_proc(pdev, decode_color); |
10779 | 11.2k | pdev->my_get_color_mapping_procs = dev_proc(pdev, get_color_mapping_procs); |
10780 | 11.2k | pdev->my_get_color_comp_index = dev_proc(pdev, get_color_comp_index); |
10781 | 11.2k | pdev->color_info.separable_and_linear = |
10782 | 11.2k | target->color_info.separable_and_linear; |
10783 | 11.2k | *ppdev = (gx_device *) pdev; |
10784 | 11.2k | return code; |
10785 | 11.2k | } |
10786 | | |
10787 | | /* |
10788 | | * Disable the PDF 1.4 clist compositor device. Once created, the PDF 1.4 |
10789 | | * compositor device is never removed. (We do not have a remove compositor |
10790 | | * method.) However it is no-op'ed when the PDF 1.4 device is popped. This |
10791 | | * routine implements that action. |
10792 | | */ |
10793 | | static int |
10794 | | pdf14_disable_clist_device(gs_memory_t *mem, gs_gstate * pgs, |
10795 | | gx_device * dev) |
10796 | 10.8k | { |
10797 | 10.8k | gx_device_forward * pdev = (gx_device_forward *)dev; |
10798 | 10.8k | gx_device * target = pdev->target; |
10799 | | |
10800 | 10.8k | if_debug0m('v', pgs->memory, "[v]pdf14_disable_clist_device\n"); |
10801 | | |
10802 | | /* |
10803 | | * To disable the action of this device, we forward all device |
10804 | | * procedures to the target except the composite and copy |
10805 | | * the target's color_info. |
10806 | | */ |
10807 | 10.8k | dev->color_info = target->color_info; |
10808 | 10.8k | pdf14_forward_device_procs(dev); |
10809 | 10.8k | set_dev_proc(dev, composite, pdf14_clist_forward_composite); |
10810 | 10.8k | return 0; |
10811 | 10.8k | } |
10812 | | |
10813 | | /* |
10814 | | * Recreate the PDF 1.4 clist compositor device. Once created, the PDF 1.4 |
10815 | | * compositor device is never removed. (We do not have a remove compositor |
10816 | | * method.) However it is no-op'ed when the PDF 1.4 device is popped. This |
10817 | | * routine will re-enable the compositor if the PDF 1.4 device is pushed |
10818 | | * again. |
10819 | | */ |
10820 | | static int |
10821 | | pdf14_recreate_clist_device(gs_memory_t *mem, gs_gstate * pgs, |
10822 | | gx_device * dev, const gs_pdf14trans_t * pdf14pct) |
10823 | 0 | { |
10824 | 0 | pdf14_clist_device * pdev = (pdf14_clist_device *)dev; |
10825 | 0 | gx_device * target = pdev->target; |
10826 | 0 | pdf14_clist_device dev_proto; |
10827 | 0 | int code; |
10828 | |
|
10829 | 0 | if_debug0m('v', pgs->memory, "[v]pdf14_recreate_clist_device\n"); |
10830 | | /* |
10831 | | * We will not use the entire prototype device but we will set the |
10832 | | * color related info to match the prototype. |
10833 | | */ |
10834 | 0 | code = get_pdf14_clist_device_proto(target, &dev_proto, |
10835 | 0 | pgs, pdf14pct, false); |
10836 | 0 | if (code < 0) |
10837 | 0 | return code; |
10838 | 0 | pdev->color_info = dev_proto.color_info; |
10839 | |
|
10840 | 0 | if (dev_proto.initialize_device_procs != NULL) |
10841 | 0 | dev_proto.initialize_device_procs((gx_device *)&dev_proto); |
10842 | |
|
10843 | 0 | pdev->procs = dev_proto.procs; |
10844 | 0 | pdev->pad = target->pad; |
10845 | 0 | pdev->log2_align_mod = target->log2_align_mod; |
10846 | |
|
10847 | 0 | if (pdf14pct->params.overprint_sim_push && pdf14pct->params.num_spot_colors_int > 0 && target->num_planar_planes == 0) |
10848 | 0 | pdev->num_planar_planes = pdev->color_info.num_components + pdf14pct->params.num_spot_colors_int; |
10849 | 0 | else |
10850 | 0 | pdev->num_planar_planes = target->num_planar_planes; |
10851 | 0 | pdev->interpolate_threshold = dev_proc(target, dev_spec_op)(target, gxdso_interpolate_threshold, NULL, 0); |
10852 | |
|
10853 | 0 | copy_tag_setup(dev, target); |
10854 | |
|
10855 | 0 | pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN_STANDARD; |
10856 | 0 | gx_device_fill_in_procs((gx_device *)pdev); |
10857 | 0 | pdev->save_get_cmap_procs = pgs->get_cmap_procs; |
10858 | 0 | pgs->get_cmap_procs = pdf14_get_cmap_procs; |
10859 | 0 | gx_set_cmap_procs(pgs, (gx_device *)pdev); |
10860 | 0 | check_device_separable((gx_device *)pdev); |
10861 | 0 | return code; |
10862 | 0 | } |
10863 | | |
10864 | | /* |
10865 | | * devicen params |
10866 | | */ |
10867 | | gs_devn_params * |
10868 | | pdf14_ret_devn_params(gx_device *pdev) |
10869 | 2.35M | { |
10870 | 2.35M | pdf14_device *p14dev = (pdf14_device *)pdev; |
10871 | | |
10872 | 2.35M | return &(p14dev->devn_params); |
10873 | 2.35M | } |
10874 | | |
10875 | | /* |
10876 | | * devicen params |
10877 | | */ |
10878 | | gs_devn_params * |
10879 | | pdf14_accum_ret_devn_params(gx_device *pdev) |
10880 | 0 | { |
10881 | 0 | gx_device_pdf14_accum *p14dev = (gx_device_pdf14_accum *)pdev; |
10882 | |
|
10883 | 0 | return &(p14dev->devn_params); |
10884 | 0 | } |
10885 | | |
10886 | | static int |
10887 | | pdf14_accum_get_color_comp_index(gx_device * dev, |
10888 | | const char * pname, int name_size, int component_type) |
10889 | 0 | { |
10890 | 0 | pdf14_device *p14dev = (pdf14_device *)(((gx_device_pdf14_accum *)dev)->save_p14dev); |
10891 | 0 | gx_device *target = p14dev->target; |
10892 | 0 | int colorant_number = devn_get_color_comp_index(dev, |
10893 | 0 | &(((gx_device_pdf14_accum *)dev)->devn_params), |
10894 | 0 | &(((gx_device_pdf14_accum *)dev)->equiv_cmyk_colors), |
10895 | 0 | pname, name_size, component_type, ENABLE_AUTO_SPOT_COLORS); |
10896 | |
|
10897 | 0 | if (target != NULL) |
10898 | | /* colorant_number returned here _should_ be the same as from above */ |
10899 | 0 | colorant_number = (*dev_proc(target, get_color_comp_index)) |
10900 | 0 | (target, (const char *)pname, name_size, component_type); |
10901 | 0 | return colorant_number; |
10902 | 0 | } |
10903 | | |
10904 | | /* |
10905 | | * The following procedures are used to map the standard color spaces into |
10906 | | * the separation color components for the pdf14_accum device. |
10907 | | */ |
10908 | | static void |
10909 | | pdf14_accum_gray_cs_to_cmyk_cm(const gx_device * dev, frac gray, frac out[]) |
10910 | 0 | { |
10911 | 0 | int * map = |
10912 | 0 | (int *)(&((gx_device_pdf14_accum *) dev)->devn_params.separation_order_map); |
10913 | |
|
10914 | 0 | gray_cs_to_devn_cm(dev, map, gray, out); |
10915 | 0 | } |
10916 | | |
10917 | | static void |
10918 | | pdf14_accum_rgb_cs_to_cmyk_cm(const gx_device * dev, |
10919 | | const gs_gstate *pgs, frac r, frac g, frac b, frac out[]) |
10920 | 0 | { |
10921 | 0 | int * map = |
10922 | 0 | (int *)(&((gx_device_pdf14_accum *) dev)->devn_params.separation_order_map); |
10923 | |
|
10924 | 0 | rgb_cs_to_devn_cm(dev, map, pgs, r, g, b, out); |
10925 | 0 | } |
10926 | | |
10927 | | static void |
10928 | | pdf14_accum_cmyk_cs_to_cmyk_cm(const gx_device * dev, |
10929 | | frac c, frac m, frac y, frac k, frac out[]) |
10930 | 0 | { |
10931 | 0 | const int * map = |
10932 | 0 | (int *)(&((gx_device_pdf14_accum *) dev)->devn_params.separation_order_map); |
10933 | |
|
10934 | 0 | cmyk_cs_to_devn_cm(dev, map, c, m, y, k, out); |
10935 | 0 | } |
10936 | | |
10937 | | static const gx_cm_color_map_procs pdf14_accum_cm_procs = { |
10938 | | pdf14_accum_gray_cs_to_cmyk_cm, |
10939 | | pdf14_accum_rgb_cs_to_cmyk_cm, |
10940 | | pdf14_accum_cmyk_cs_to_cmyk_cm |
10941 | | }; |
10942 | | |
10943 | | static const gx_cm_color_map_procs * |
10944 | | pdf14_accum_get_color_mapping_procs(const gx_device * dev, const gx_device **map_dev) |
10945 | 0 | { |
10946 | 0 | *map_dev = dev; |
10947 | 0 | return &pdf14_accum_cm_procs; |
10948 | 0 | } |
10949 | | |
10950 | | /* |
10951 | | * Device proc for updating the equivalent CMYK color for spot colors. |
10952 | | */ |
10953 | | static int |
10954 | | pdf14_accum_update_spot_equivalent_colors(gx_device * dev, const gs_gstate * pgs, const gs_color_space *pcs) |
10955 | 0 | { |
10956 | 0 | gx_device_pdf14_accum *pdev = (gx_device_pdf14_accum *)dev; |
10957 | 0 | gx_device *tdev = ((pdf14_device *)(pdev->save_p14dev))->target; |
10958 | 0 | int code = update_spot_equivalent_cmyk_colors(dev, pgs, pcs, &pdev->devn_params, |
10959 | 0 | &pdev->equiv_cmyk_colors); |
10960 | |
|
10961 | 0 | if (code >= 0 && tdev != NULL) |
10962 | 0 | code = dev_proc(tdev, update_spot_equivalent_colors)(tdev, pgs, pcs); |
10963 | 0 | return code; |
10964 | 0 | } |
10965 | | |
10966 | | /* Used when doing overprint simulation and have spot colors */ |
10967 | | static int |
10968 | | pdf14_update_spot_equivalent_colors(gx_device *dev, const gs_gstate *pgs, const gs_color_space *pcs) |
10969 | 0 | { |
10970 | 0 | pdf14_device *pdev = (pdf14_device *)dev; |
10971 | 0 | int code; |
10972 | | |
10973 | | /* Make sure we are not All or None */ |
10974 | 0 | if (pcs != NULL && pcs->type->index == gs_color_space_index_Separation && |
10975 | 0 | pcs->params.separation.sep_type != SEP_OTHER) |
10976 | 0 | return 0; |
10977 | | |
10978 | 0 | code = update_spot_equivalent_cmyk_colors(dev, pgs, pcs, &pdev->devn_params, |
10979 | 0 | &pdev->op_pequiv_cmyk_colors); |
10980 | 0 | return code; |
10981 | 0 | } |
10982 | | |
10983 | | /* |
10984 | | * Retrieve a list of spot color names for the PDF14 device. |
10985 | | */ |
10986 | | int |
10987 | | put_param_pdf14_spot_names(gx_device * pdev, |
10988 | | gs_separations * pseparations, gs_param_list * plist) |
10989 | 107k | { |
10990 | 107k | int code, num_spot_colors, i; |
10991 | 107k | gs_param_string str; |
10992 | | |
10993 | | /* Check if the given keyname is present. */ |
10994 | 107k | code = param_read_int(plist, PDF14NumSpotColorsParamName, |
10995 | 107k | &num_spot_colors); |
10996 | 107k | switch (code) { |
10997 | 0 | default: |
10998 | 0 | param_signal_error(plist, PDF14NumSpotColorsParamName, code); |
10999 | 0 | break; |
11000 | 107k | case 1: |
11001 | 107k | return 0; |
11002 | 0 | case 0: |
11003 | 0 | if (num_spot_colors < 1 || |
11004 | 0 | num_spot_colors > GX_DEVICE_COLOR_MAX_COMPONENTS) |
11005 | 0 | return_error(gs_error_rangecheck); |
11006 | 0 | for (i = 0; i < num_spot_colors; i++) { |
11007 | 0 | char buff[20]; |
11008 | 0 | byte * sep_name; |
11009 | |
|
11010 | 0 | gs_snprintf(buff, sizeof(buff), "PDF14SpotName_%d", i); |
11011 | 0 | code = param_read_string(plist, buff, &str); |
11012 | 0 | switch (code) { |
11013 | 0 | default: |
11014 | 0 | param_signal_error(plist, buff, code); |
11015 | 0 | break; |
11016 | 0 | case 0: |
11017 | 0 | sep_name = gs_alloc_bytes(pdev->memory, |
11018 | 0 | str.size, "put_param_pdf14_spot_names"); |
11019 | 0 | if (sep_name == NULL) |
11020 | 0 | return_error(gs_error_VMerror); |
11021 | | |
11022 | 0 | memcpy(sep_name, str.data, str.size); |
11023 | 0 | pseparations->names[i].size = str.size; |
11024 | 0 | pseparations->names[i].data = sep_name; |
11025 | 0 | } |
11026 | 0 | } |
11027 | 0 | pseparations->num_separations = num_spot_colors; |
11028 | 0 | break; |
11029 | 107k | } |
11030 | 0 | return 0;; |
11031 | 0 | } |
11032 | | |
11033 | | /* |
11034 | | * This procedure will have information from the PDF 1.4 clist writing |
11035 | | * clist compositior device. This is information output the compressed |
11036 | | * color list info which is needed for the support of spot colors in |
11037 | | * PDF 1.4 compositing. This info needs to be passed to the PDF 1.4 |
11038 | | * clist reading compositor. However this device is not created until |
11039 | | * the clist is read. To get this info to that device, we have to |
11040 | | * temporarily store that info in the output device. This routine saves |
11041 | | * that info in the output device. |
11042 | | */ |
11043 | | int |
11044 | | pdf14_put_devn_params(gx_device * pdev, gs_devn_params * pdevn_params, |
11045 | | gs_param_list * plist) |
11046 | 107k | { |
11047 | 107k | int code; |
11048 | 107k | code = put_param_pdf14_spot_names(pdev, |
11049 | 107k | &pdevn_params->pdf14_separations, plist); |
11050 | 107k | return code; |
11051 | 107k | } |
11052 | | |
11053 | | /* |
11054 | | * When we are banding, we have two PDF 1.4 compositor devices. One for |
11055 | | * when we are creating the clist. The second is for imaging the data from |
11056 | | * the clist. This routine is part of the clist writing PDF 1.4 device. |
11057 | | * This routine is only called once the PDF 1.4 clist write compositor already |
11058 | | * exists. |
11059 | | */ |
11060 | | static int |
11061 | | pdf14_clist_composite(gx_device * dev, gx_device ** pcdev, |
11062 | | const gs_composite_t * pct, gs_gstate * pgs, gs_memory_t * mem, |
11063 | | gx_device *cdev) |
11064 | 1.63M | { |
11065 | 1.63M | pdf14_clist_device * pdev = (pdf14_clist_device *)dev; |
11066 | 1.63M | int code, is_pdf14_compositor; |
11067 | 1.63M | const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct; |
11068 | 1.63M | bool deep = device_is_deep(dev); |
11069 | | |
11070 | | /* We only handle a few PDF 1.4 transparency operations */ |
11071 | 1.63M | if ((is_pdf14_compositor = gs_is_pdf14trans_compositor(pct)) != 0) { |
11072 | 1.00M | switch (pdf14pct->params.pdf14_op) { |
11073 | 0 | case PDF14_PUSH_DEVICE: |
11074 | | /* Re-activate the PDF 1.4 compositor */ |
11075 | | /* |
11076 | | We previously did: |
11077 | | |
11078 | | pdev->saved_target_color_info = pdev->target->color_info; |
11079 | | |
11080 | | Here, but since we already saved and modified the the color_info |
11081 | | of the target clist device in gs_pdf14_clist_device_push() this is |
11082 | | overwriting saved_target_color_info that we already saved with the |
11083 | | group color_info, meaning when we set it back again, it's incorrect. |
11084 | | */ |
11085 | 0 | pdev->target->color_info = pdev->color_info; |
11086 | 0 | pdev->saved_target_encode_color = dev_proc(pdev->target, encode_color); |
11087 | 0 | pdev->saved_target_decode_color = dev_proc(pdev->target, decode_color); |
11088 | 0 | set_dev_proc(pdev->target, encode_color, pdev->my_encode_color); |
11089 | 0 | set_dev_proc(pdev, encode_color, pdev->my_encode_color); |
11090 | 0 | set_dev_proc(pdev->target, decode_color, pdev->my_decode_color); |
11091 | 0 | set_dev_proc(pdev, decode_color, pdev->my_decode_color); |
11092 | 0 | pdev->saved_target_get_color_mapping_procs = |
11093 | 0 | dev_proc(pdev->target, get_color_mapping_procs); |
11094 | 0 | pdev->saved_target_get_color_comp_index = |
11095 | 0 | dev_proc(pdev->target, get_color_comp_index); |
11096 | 0 | set_dev_proc(pdev->target, get_color_mapping_procs, pdev->my_get_color_mapping_procs); |
11097 | 0 | set_dev_proc(pdev, get_color_mapping_procs, pdev->my_get_color_mapping_procs); |
11098 | 0 | set_dev_proc(pdev->target, get_color_comp_index, pdev->my_get_color_comp_index); |
11099 | 0 | set_dev_proc(pdev, get_color_comp_index, pdev->my_get_color_comp_index); |
11100 | 0 | pdev->save_get_cmap_procs = pgs->get_cmap_procs; |
11101 | 0 | pgs->get_cmap_procs = pdf14_get_cmap_procs; |
11102 | 0 | gx_set_cmap_procs(pgs, dev); |
11103 | 0 | code = pdf14_recreate_clist_device(mem, pgs, dev, pdf14pct); |
11104 | 0 | pdev->blend_mode = pdev->text_knockout = 0; |
11105 | 0 | pdev->opacity = pdev->shape = 0.0; |
11106 | 0 | if (code < 0) |
11107 | 0 | return code; |
11108 | | /* |
11109 | | * This routine is part of the PDF 1.4 clist write device. |
11110 | | * Change the compositor procs to not create another since we |
11111 | | * do not need to create a chain of identical devices. |
11112 | | */ |
11113 | 0 | { |
11114 | 0 | gs_pdf14trans_t pctemp = *pdf14pct; |
11115 | |
|
11116 | 0 | pctemp.type = &gs_composite_pdf14trans_no_clist_writer_type; |
11117 | 0 | code = dev_proc(pdev->target, composite) |
11118 | 0 | (pdev->target, pcdev, (gs_composite_t *)&pctemp, pgs, mem, cdev); |
11119 | | /* We should never have created a new device here. */ |
11120 | 0 | assert(code != 1); |
11121 | 0 | return code; |
11122 | 0 | } |
11123 | 10.8k | case PDF14_POP_DEVICE: |
11124 | 10.8k | { |
11125 | 10.8k | gx_device *clistdev = pdev->target; |
11126 | | |
11127 | | /* Find the clist device */ |
11128 | 10.8k | while (1) { |
11129 | 10.8k | gxdso_device_child_request req; |
11130 | | /* Ignore any errors here, that's expected as non-clist |
11131 | | * devices don't implement it. */ |
11132 | 10.8k | code = dev_proc(clistdev, dev_spec_op)(clistdev, gxdso_is_clist_device, NULL, 0); |
11133 | 10.8k | if (code == 1) |
11134 | 10.8k | break; |
11135 | 0 | req.n = 0; |
11136 | 0 | req.target = clistdev; |
11137 | 0 | code = dev_proc(clistdev, dev_spec_op)(clistdev, gxdso_device_child, &req, sizeof(req)); |
11138 | 0 | if (code < 0) |
11139 | 0 | return code; |
11140 | 0 | clistdev = req.target; |
11141 | 0 | } |
11142 | | |
11143 | | /* If we have overprint simulation spot color information, store |
11144 | | it in a pseudo-band of the clist */ |
11145 | 10.8k | if (pdev->overprint_sim && |
11146 | 0 | pdev->devn_params.page_spot_colors > 0) { |
11147 | 0 | code = clist_write_op_equiv_cmyk_colors((gx_device_clist_writer *)clistdev, |
11148 | 0 | &pdev->op_pequiv_cmyk_colors); |
11149 | 0 | if (code < 0) |
11150 | 0 | return code; |
11151 | 0 | } |
11152 | | |
11153 | | /* If we hit an error during an SMask, we need to undo the color |
11154 | | * swapping before continuing. pdf14_decrement_smask_color() checks |
11155 | | * for itself if it needs to take action. |
11156 | | */ |
11157 | 10.8k | pdf14_decrement_smask_color(pgs, dev); |
11158 | | /* Restore the color_info for the clist device */ |
11159 | 10.8k | clistdev->color_info = pdev->saved_target_color_info; |
11160 | 10.8k | ((gx_device_clist_writer*)clistdev)->clist_color_info = clistdev->color_info; /* also reset for writer */ |
11161 | 10.8k | set_dev_proc(clistdev, encode_color, pdev->saved_target_encode_color); |
11162 | 10.8k | set_dev_proc(clistdev, decode_color, pdev->saved_target_decode_color); |
11163 | 10.8k | set_dev_proc(clistdev, get_color_mapping_procs, pdev->saved_target_get_color_mapping_procs); |
11164 | 10.8k | set_dev_proc(clistdev, get_color_comp_index, pdev->saved_target_get_color_comp_index); |
11165 | 10.8k | pgs->get_cmap_procs = pdev->save_get_cmap_procs; |
11166 | 10.8k | gx_set_cmap_procs(pgs, clistdev); |
11167 | 10.8k | gx_device_decache_colors(clistdev); |
11168 | | /* Disable the PDF 1.4 compositor */ |
11169 | 10.8k | pdf14_disable_clist_device(mem, pgs, dev); |
11170 | | /* |
11171 | | * Make sure that the transfer funtions, etc. are current. |
11172 | | */ |
11173 | 10.8k | code = cmd_put_color_mapping((gx_device_clist_writer *)clistdev, pgs); |
11174 | 10.8k | if (code < 0) |
11175 | 0 | return code; |
11176 | 10.8k | break; |
11177 | 10.8k | } |
11178 | 10.8k | case PDF14_BEGIN_TRANS_PAGE_GROUP: |
11179 | 42.6k | case PDF14_BEGIN_TRANS_GROUP: |
11180 | 42.6k | if (pdev->smask_constructed || pdev->depth_within_smask) |
11181 | 20.3k | pdev->depth_within_smask++; |
11182 | 42.6k | pdev->smask_constructed = 0; |
11183 | | /* |
11184 | | * Keep track of any changes made in the blending parameters. |
11185 | | These need to be written out in the same bands as the group |
11186 | | information is written. Hence the passing of the dimensions |
11187 | | for the group. */ |
11188 | 42.6k | code = pdf14_clist_update_params(pdev, pgs, true, |
11189 | 42.6k | (gs_pdf14trans_params_t *)&(pdf14pct->params)); |
11190 | 42.6k | if (code < 0) |
11191 | 0 | return code; |
11192 | 42.6k | if (pdf14pct->params.Background_components != 0 && |
11193 | 0 | pdf14pct->params.Background_components != |
11194 | 0 | pdev->color_info.num_components) |
11195 | 0 | return_error(gs_error_rangecheck); |
11196 | | |
11197 | | /* We need to update the clist writer device procs based upon the |
11198 | | the group color space. This ensures the proper color data is |
11199 | | written out to the device. For simplicity, the list item is |
11200 | | created even if the color space did not change */ |
11201 | 42.6k | code = pdf14_clist_push_color_model(dev, cdev, pgs, pdf14pct, mem, false); |
11202 | 42.6k | if (code < 0) |
11203 | 0 | return code; |
11204 | | |
11205 | 42.6k | break; |
11206 | 45.0k | case PDF14_BEGIN_TRANS_MASK: |
11207 | | /* We need to update the clist writer device procs based upon the |
11208 | | the group color space. For simplicity, the list item is created |
11209 | | even if the color space did not change */ |
11210 | | /* First store the current ones */ |
11211 | 45.0k | if (pdf14pct->params.subtype == TRANSPARENCY_MASK_None) |
11212 | 24.5k | break; |
11213 | | |
11214 | | /* Update the color settings of the clist writer. Store information in stack */ |
11215 | 20.4k | code = pdf14_clist_push_color_model(dev, cdev, pgs, pdf14pct, mem, true); |
11216 | 20.4k | if (code < 0) |
11217 | 0 | return code; |
11218 | | |
11219 | | /* Also, if the BC is a value that may end up as something other |
11220 | | than transparent. We must use the parent colors bounding box in |
11221 | | determining the range of bands in which this mask can affect. |
11222 | | So, if needed change the masks bounding box at this time */ |
11223 | 20.4k | pdev->in_smask_construction++; |
11224 | 20.4k | break; |
11225 | 391k | case PDF14_BEGIN_TRANS_TEXT_GROUP: |
11226 | 391k | if (pdev->text_group == PDF14_TEXTGROUP_BT_PUSHED) { |
11227 | 21 | emprintf(pdev->memory, "Warning: Text group pushed but no ET found\n"); |
11228 | 21 | pdev->text_group = PDF14_TEXTGROUP_MISSING_ET; |
11229 | 21 | } else |
11230 | 391k | pdev->text_group = PDF14_TEXTGROUP_BT_NOT_PUSHED; |
11231 | 391k | *pcdev = dev; |
11232 | 391k | return 0; /* Never put into clist. Only used during writing */ |
11233 | 393k | case PDF14_END_TRANS_TEXT_GROUP: |
11234 | 393k | if (pdev->text_group != PDF14_TEXTGROUP_BT_PUSHED) { |
11235 | 390k | *pcdev = dev; |
11236 | 390k | return 0; /* Avoids spurious ET calls in interpreter */ |
11237 | 390k | } |
11238 | 2.93k | pdev->text_group = PDF14_TEXTGROUP_NO_BT; /* These can't be nested */ |
11239 | 2.93k | code = pdf14_clist_pop_color_model(dev, pgs); |
11240 | 2.93k | if (code < 0) |
11241 | 0 | return code; |
11242 | 2.93k | break; |
11243 | 20.4k | case PDF14_END_TRANS_MASK: |
11244 | 20.4k | pdev->in_smask_construction--; |
11245 | 20.4k | if (pdev->in_smask_construction < 0) |
11246 | 0 | pdev->in_smask_construction = 0; |
11247 | 20.4k | if (pdev->in_smask_construction == 0) |
11248 | 20.4k | pdev->smask_constructed = 1; |
11249 | | /* fallthrough */ |
11250 | 60.1k | case PDF14_END_TRANS_GROUP: |
11251 | | /* We need to update the clist writer device procs based upon the |
11252 | | the group color space. */ |
11253 | 60.1k | code = pdf14_clist_pop_color_model(dev, pgs); |
11254 | 60.1k | if (pdev->depth_within_smask) |
11255 | 20.3k | pdev->depth_within_smask--; |
11256 | 60.1k | if (code < 0) |
11257 | 0 | return code; |
11258 | 60.1k | break; |
11259 | 60.1k | case PDF14_PUSH_TRANS_STATE: |
11260 | 0 | break; |
11261 | 19.9k | case PDF14_POP_TRANS_STATE: |
11262 | 19.9k | break; |
11263 | 20.4k | case PDF14_PUSH_SMASK_COLOR: |
11264 | 20.4k | code = pdf14_increment_smask_color(pgs,dev); |
11265 | 20.4k | *pcdev = dev; |
11266 | 20.4k | return code; /* Note, this are NOT put in the clist */ |
11267 | 0 | break; |
11268 | 20.4k | case PDF14_POP_SMASK_COLOR: |
11269 | 20.4k | code = pdf14_decrement_smask_color(pgs,dev); |
11270 | 20.4k | *pcdev = dev; |
11271 | 20.4k | return code; /* Note, this are NOT put in the clist */ |
11272 | 0 | break; |
11273 | 0 | case PDF14_SET_BLEND_PARAMS: |
11274 | | /* If there is a change we go ahead and apply it to the target */ |
11275 | 0 | code = pdf14_clist_update_params(pdev, pgs, false, |
11276 | 0 | (gs_pdf14trans_params_t *)&(pdf14pct->params)); |
11277 | 0 | *pcdev = dev; |
11278 | 0 | return code; |
11279 | 0 | break; |
11280 | 0 | case PDF14_ABORT_DEVICE: |
11281 | 0 | code = gx_abort_trans_device(pgs, dev); |
11282 | 0 | if (pdev->free_devicen) { |
11283 | 0 | devn_free_params(dev); |
11284 | 0 | } |
11285 | 0 | pdf14_disable_device(dev); |
11286 | 0 | pdf14_close(dev); |
11287 | 0 | *pcdev = dev; |
11288 | 0 | return code; |
11289 | 0 | break; |
11290 | 0 | default: |
11291 | 0 | break; /* Pass remaining ops to target */ |
11292 | 1.00M | } |
11293 | 1.00M | } |
11294 | 810k | code = dev_proc(pdev->target, composite) |
11295 | 810k | (pdev->target, pcdev, pct, pgs, mem, cdev); |
11296 | | /* If we were accumulating into a pdf14-clist-accum device, */ |
11297 | | /* we now have to render the page into it's target device */ |
11298 | 810k | if (is_pdf14_compositor && pdf14pct->params.pdf14_op == PDF14_POP_DEVICE && |
11299 | 10.8k | pdev->target->stype == &st_gx_devn_accum_device) { |
11300 | | |
11301 | 3.96k | int i, y, rows_used; |
11302 | 3.96k | byte *linebuf; |
11303 | 3.96k | byte *actual_data; |
11304 | 3.96k | gx_device_pdf14_accum *tdev = (gx_device_pdf14_accum *)(pdev->target); /* the printer class clist device used to accumulate */ |
11305 | | /* get the target device we want to send the image to */ |
11306 | 3.96k | gx_device *target = ((pdf14_device *)(tdev->save_p14dev))->target; |
11307 | 3.96k | gs_image1_t image; |
11308 | 3.96k | gs_color_space *pcs; |
11309 | 3.96k | gx_image_enum_common_t *info = NULL; |
11310 | 3.96k | gx_image_plane_t planes; |
11311 | 3.96k | gsicc_rendering_param_t render_cond; |
11312 | 3.96k | cmm_dev_profile_t *dev_profile; |
11313 | 3.96k | bool save_planar = pdev->num_planar_planes; |
11314 | 3.96k | gs_devn_params *target_devn_params = dev_proc(target, ret_devn_params)(target); |
11315 | 3.96k | int save_num_separations; |
11316 | 3.96k | gs_int_rect rect; |
11317 | | |
11318 | 3.96k | pdev->num_planar_planes = 0; /* so gx_device_raster is for entire chunky pixel line */ |
11319 | 3.96k | linebuf = gs_alloc_bytes(mem, gx_device_raster((gx_device *)pdev, true), "pdf14-clist_accum pop dev"); |
11320 | 3.96k | pdev->num_planar_planes = save_planar; |
11321 | | |
11322 | | /* As long as we don't have spot colors, we can use ICC colorspace, but spot |
11323 | | * colors do require devn support |
11324 | | */ |
11325 | 3.96k | if (tdev->color_info.num_components <= 4 || |
11326 | 3.96k | dev_proc(target, dev_spec_op)(target, gxdso_supports_devn, NULL, 0) <= 0) { |
11327 | | /* |
11328 | | * Set color space in preparation for sending an image. |
11329 | | */ |
11330 | 3.96k | code = gs_cspace_build_ICC(&pcs, NULL, pgs->memory); |
11331 | 3.96k | if (code < 0) |
11332 | 0 | goto put_accum_error; |
11333 | | |
11334 | | /* Need to set this to avoid color management during the |
11335 | | image color render operation. Exception is for the special case |
11336 | | when the destination was CIELAB. Then we need to convert from |
11337 | | default RGB to CIELAB in the put image operation. That will happen |
11338 | | here as we should have set the profile for the pdf14 device to RGB |
11339 | | and the target will be CIELAB */ |
11340 | 3.96k | code = dev_proc(dev, get_profile)(dev, &dev_profile); |
11341 | 3.96k | if (code < 0) |
11342 | 0 | goto put_accum_error; |
11343 | 3.96k | gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, |
11344 | 3.96k | &(pcs->cmm_icc_profile_data), &render_cond); |
11345 | | /* pcs takes a reference to the profile data it just retrieved. */ |
11346 | 3.96k | gsicc_adjust_profile_rc(pcs->cmm_icc_profile_data, 1, "pdf14_clist_composite"); |
11347 | 3.96k | gsicc_set_icc_range(&(pcs->cmm_icc_profile_data)); |
11348 | 3.96k | } else { |
11349 | | /* DeviceN case -- need to handle spot colors */ |
11350 | 0 | code = gs_cspace_new_DeviceN(&pcs, tdev->color_info.num_components, |
11351 | 0 | gs_currentcolorspace(pgs), pgs->memory); |
11352 | 0 | if (code < 0) |
11353 | 0 | goto put_accum_error; |
11354 | | /* set up a usable DeviceN space with info from the tdev->devn_params */ |
11355 | 0 | pcs->params.device_n.use_alt_cspace = false; |
11356 | |
|
11357 | 0 | if ((code = pcs->type->install_cspace(pcs, pgs)) < 0) { |
11358 | 0 | goto put_accum_error; |
11359 | 0 | } |
11360 | | /* One last thing -- we need to fudge the pgs->color_component_map */ |
11361 | 0 | for (i=0; i < tdev->color_info.num_components; i++) |
11362 | 0 | pgs->color_component_map.color_map[i] = i; /* enable all components in normal order */ |
11363 | | /* copy devn_params that were accumulated into the target device's devn_params */ |
11364 | 0 | target_devn_params->bitspercomponent = tdev->devn_params.bitspercomponent; |
11365 | 0 | target_devn_params->std_colorant_names = tdev->devn_params.std_colorant_names; |
11366 | 0 | target_devn_params->num_std_colorant_names = tdev->devn_params.num_std_colorant_names; |
11367 | 0 | target_devn_params->max_separations = tdev->devn_params.max_separations; |
11368 | 0 | target_devn_params->page_spot_colors = tdev->devn_params.page_spot_colors; |
11369 | 0 | target_devn_params->num_separation_order_names = tdev->devn_params.num_separation_order_names; |
11370 | 0 | target_devn_params->separations = tdev->devn_params.separations; |
11371 | 0 | memcpy(target_devn_params->separation_order_map, tdev->devn_params.separation_order_map, |
11372 | 0 | sizeof(gs_separation_map)); |
11373 | 0 | target_devn_params->pdf14_separations = tdev->devn_params.pdf14_separations; |
11374 | 0 | } |
11375 | 3.96k | if (linebuf == NULL) { |
11376 | 0 | code = gs_error_VMerror; |
11377 | 0 | goto put_accum_error; |
11378 | 0 | } |
11379 | 3.96k | gs_image_t_init_adjust(&image, pcs, false); |
11380 | 3.96k | image.ImageMatrix.xx = (float)pdev->width; |
11381 | 3.96k | image.ImageMatrix.yy = (float)pdev->height; |
11382 | 3.96k | image.Width = pdev->width; |
11383 | 3.96k | image.Height = pdev->height; |
11384 | 3.96k | image.BitsPerComponent = 8<<deep; |
11385 | 3.96k | ctm_only_writable(pgs).xx = (float)pdev->width; |
11386 | 3.96k | ctm_only_writable(pgs).xy = 0; |
11387 | 3.96k | ctm_only_writable(pgs).yx = 0; |
11388 | 3.96k | ctm_only_writable(pgs).yy = (float)pdev->height; |
11389 | 3.96k | ctm_only_writable(pgs).tx = 0.0; |
11390 | 3.96k | ctm_only_writable(pgs).ty = 0.0; |
11391 | 3.96k | code = dev_proc(target, begin_typed_image) (target, |
11392 | 3.96k | pgs, NULL, |
11393 | 3.96k | (gs_image_common_t *)&image, |
11394 | 3.96k | NULL, NULL, NULL, |
11395 | 3.96k | pgs->memory, &info); |
11396 | 3.96k | if (code < 0) |
11397 | 0 | goto put_accum_error; |
11398 | 3.96k | rect.p.x = 0; |
11399 | 3.96k | rect.q.x = tdev->width; |
11400 | 8.50M | for (y=0; y < tdev->height; y++) { |
11401 | 8.50M | gs_get_bits_params_t params; |
11402 | | |
11403 | 8.50M | params.options = (GB_ALIGN_ANY | |
11404 | 8.50M | (GB_RETURN_COPY | GB_RETURN_POINTER) | |
11405 | 8.50M | GB_OFFSET_0 | |
11406 | 8.50M | GB_RASTER_STANDARD | GB_PACKING_CHUNKY | |
11407 | 8.50M | GB_COLORS_NATIVE | GB_ALPHA_NONE); |
11408 | 8.50M | params.x_offset = 0; |
11409 | 8.50M | params.raster = bitmap_raster(dev->width * dev->color_info.depth); |
11410 | 8.50M | params.data[0] = linebuf; |
11411 | 8.50M | rect.p.y = y; |
11412 | 8.50M | rect.q.y = y+1; |
11413 | 8.50M | code = dev_proc(tdev, get_bits_rectangle)((gx_device *)tdev, |
11414 | 8.50M | &rect, ¶ms); |
11415 | 8.50M | if (code < 0) |
11416 | 7 | goto put_accum_error; |
11417 | 8.50M | actual_data = params.data[0]; |
11418 | 8.50M | planes.data = actual_data; |
11419 | 8.50M | planes.data_x = 0; |
11420 | 8.50M | planes.raster = tdev->width * tdev->color_info.num_components; |
11421 | 8.50M | if ((code = info->procs->plane_data(info, &planes, 1, &rows_used)) < 0) |
11422 | 0 | goto put_accum_error; |
11423 | 8.50M | } |
11424 | | |
11425 | 3.96k | put_accum_error: |
11426 | 3.96k | if (info != NULL) { |
11427 | 3.96k | if (code < 0) |
11428 | 7 | (void)info->procs->end_image(info, true); |
11429 | 3.95k | else |
11430 | 3.95k | code = info->procs->end_image(info, true); |
11431 | 3.96k | } |
11432 | | |
11433 | 3.96k | gs_free_object(pdev->memory, linebuf, "pdf14_put_image"); |
11434 | | /* This will also decrement the device profile */ |
11435 | 3.96k | rc_decrement_only_cs(pcs, "pdf14_put_image"); |
11436 | 3.96k | dev_proc(tdev, close_device)((gx_device *)tdev); /* frees the prn_device memory */ |
11437 | | /* Now unhook the clist device and hook to the original so we can clean up */ |
11438 | 3.96k | gx_device_set_target((gx_device_forward *)pdev, |
11439 | 3.96k | ((gx_device_pdf14_accum *)(pdev->target))->save_p14dev); |
11440 | 3.96k | pdev->pclist_device = pdev->target; |
11441 | 3.96k | *pcdev = pdev->target; /* pass upwards to switch devices */ |
11442 | 3.96k | pdev->color_info = target->color_info; /* same as in pdf14_disable_clist */ |
11443 | 3.96k | if (target_devn_params != NULL) { |
11444 | | /* prevent devn_free_params from freeing names still in use by target device */ |
11445 | 0 | save_num_separations = tdev->devn_params.separations.num_separations; |
11446 | 0 | tdev->devn_params.separations.num_separations = 0; |
11447 | 0 | } |
11448 | 3.96k | gs_free_object(tdev->memory, tdev, "popdevice pdf14-accum"); |
11449 | 3.96k | if (target_devn_params != NULL) { |
11450 | 0 | target_devn_params->separations.num_separations = save_num_separations; |
11451 | 0 | } |
11452 | 3.96k | return code; /* DON'T perform set_target */ |
11453 | 3.96k | } |
11454 | 806k | if (code == 1) { |
11455 | | /* We just wrapped pdev->target, so we need to update that.*/ |
11456 | 0 | gx_device_set_target((gx_device_forward *)pdev, *pcdev); |
11457 | 0 | code = 0; /* We did not wrap dev. */ |
11458 | 0 | } |
11459 | 806k | *pcdev = dev; |
11460 | 806k | return code; |
11461 | 810k | } |
11462 | | |
11463 | | /* |
11464 | | * The PDF 1.4 clist compositor is never removed. (We do not have a 'remove |
11465 | | * compositor' method. However the compositor is disabled when we are not |
11466 | | * doing a page which uses PDF 1.4 transparency. This routine is only active |
11467 | | * when the PDF 1.4 compositor is 'disabled'. It checks for reenabling the |
11468 | | * PDF 1.4 compositor. Otherwise it simply passes create compositor requests |
11469 | | * to the targer. |
11470 | | */ |
11471 | | static int |
11472 | | pdf14_clist_forward_composite(gx_device * dev, gx_device * * pcdev, |
11473 | | const gs_composite_t * pct, gs_gstate * pgs, |
11474 | | gs_memory_t * mem, gx_device *cdev) |
11475 | 0 | { |
11476 | 0 | pdf14_device *pdev = (pdf14_device *)dev; |
11477 | 0 | gx_device * tdev = pdev->target; |
11478 | 0 | gx_device * ndev; |
11479 | 0 | int code; |
11480 | |
|
11481 | 0 | *pcdev = dev; |
11482 | 0 | if (gs_is_pdf14trans_compositor(pct)) { |
11483 | 0 | const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct; |
11484 | |
|
11485 | 0 | if (pdf14pct->params.pdf14_op == PDF14_PUSH_DEVICE) |
11486 | 0 | return pdf14_clist_composite(dev, &ndev, pct, pgs, mem, cdev); |
11487 | 0 | return 0; |
11488 | 0 | } |
11489 | 0 | code = dev_proc(tdev, composite)(tdev, &ndev, pct, pgs, mem, cdev); |
11490 | 0 | if (code == 1) { |
11491 | | /* We just wrapped tdev, so update our target. */ |
11492 | 0 | gx_device_set_target((gx_device_forward *)pdev, ndev); |
11493 | 0 | code = 0; /* We did not wrap dev. */ |
11494 | 0 | } |
11495 | 0 | return code; |
11496 | 0 | } |
11497 | | |
11498 | | /* |
11499 | | * If any of the PDF 1.4 transparency blending parameters have changed, we |
11500 | | * need to send them to the PDF 1.4 compositor on the output side of the clist. |
11501 | | */ |
11502 | | static int |
11503 | | pdf14_clist_update_params(pdf14_clist_device * pdev, const gs_gstate * pgs, |
11504 | | bool crop_blend_params, |
11505 | | gs_pdf14trans_params_t *group_params) |
11506 | 3.86M | { |
11507 | 3.86M | gs_pdf14trans_params_t params = { 0 }; |
11508 | 3.86M | gx_device * pcdev; |
11509 | 3.86M | int changed = 0; |
11510 | 3.86M | int code = 0; |
11511 | 3.86M | gs_composite_t *pct_new = NULL; |
11512 | | |
11513 | 3.86M | params.crop_blend_params = crop_blend_params; |
11514 | | |
11515 | 3.86M | params.pdf14_op = PDF14_SET_BLEND_PARAMS; |
11516 | 3.86M | if (pgs->blend_mode != pdev->blend_mode) { |
11517 | 21.9k | changed |= PDF14_SET_BLEND_MODE; |
11518 | 21.9k | params.blend_mode = pdev->blend_mode = pgs->blend_mode; |
11519 | 21.9k | } |
11520 | 3.86M | if (pgs->text_knockout != pdev->text_knockout) { |
11521 | 10.4k | changed |= PDF14_SET_TEXT_KNOCKOUT; |
11522 | 10.4k | params.text_knockout = pdev->text_knockout = pgs->text_knockout; |
11523 | 10.4k | } |
11524 | 3.86M | if (pgs->alphaisshape != pdev->ais) { |
11525 | 1.37k | changed |= PDF14_SET_AIS; |
11526 | 1.37k | params.ais = pdev->ais = pgs->alphaisshape; |
11527 | 1.37k | } |
11528 | 3.86M | if (pgs->overprint != pdev->overprint) { |
11529 | 12.9k | changed |= PDF14_SET_OVERPRINT; |
11530 | 12.9k | params.overprint = pdev->overprint = pgs->overprint; |
11531 | 12.9k | } |
11532 | 3.86M | if (pgs->stroke_overprint != pdev->stroke_overprint) { |
11533 | 12.8k | changed |= PDF14_SET_STROKEOVERPRINT; |
11534 | 12.8k | params.stroke_overprint = pdev->stroke_overprint = pgs->stroke_overprint; |
11535 | 12.8k | } |
11536 | 3.86M | if (pgs->fillconstantalpha != pdev->fillconstantalpha) { |
11537 | 24.1k | changed |= PDF14_SET_FILLCONSTANTALPHA; |
11538 | 24.1k | params.fillconstantalpha = pdev->fillconstantalpha = pgs->fillconstantalpha; |
11539 | 24.1k | } |
11540 | 3.86M | if (pgs->strokeconstantalpha != pdev->strokeconstantalpha) { |
11541 | 15.8k | changed |= PDF14_SET_STROKECONSTANTALPHA; |
11542 | 15.8k | params.strokeconstantalpha = pdev->strokeconstantalpha = pgs->strokeconstantalpha; |
11543 | 15.8k | } |
11544 | 3.86M | if ((pgs->is_fill_color && pdev->op_state != PDF14_OP_STATE_FILL)) { |
11545 | 26.1k | changed |= PDF14_SET_FILLSTROKE_STATE; |
11546 | 26.1k | params.op_fs_state = pdev->op_state = PDF14_OP_STATE_FILL; |
11547 | 26.1k | if_debug0m('v', pgs->memory, |
11548 | 26.1k | "[v]c_pdf14_clist_update_params op_fs_state written in clist as PDF14_OP_STATE_FILL \n"); |
11549 | 26.1k | } |
11550 | 3.86M | if ((!pgs->is_fill_color && pdev->op_state != PDF14_OP_STATE_STROKE)) { |
11551 | 27.2k | changed |= PDF14_SET_FILLSTROKE_STATE; |
11552 | 27.2k | params.op_fs_state = pdev->op_state = PDF14_OP_STATE_STROKE; |
11553 | 27.2k | if_debug0m('v', pgs->memory, |
11554 | 27.2k | "[v]c_pdf14_clist_update_params op_fs_state written in clist as PDF14_OP_STATE_STROKE \n"); |
11555 | 27.2k | } |
11556 | 3.86M | if (crop_blend_params) { |
11557 | 42.6k | params.ctm = group_params->ctm; |
11558 | 42.6k | params.bbox = group_params->bbox; |
11559 | 42.6k | } |
11560 | 3.86M | params.changed = changed; |
11561 | | /* Avoid recursion when we have a PDF14_SET_BLEND_PARAMS forced and apply |
11562 | | now to the target. Otherwise we send the compositor action |
11563 | | to the pdf14 device at this time. This is due to the fact that we |
11564 | | need to often perform this operation when we are already starting to |
11565 | | do a compositor action */ |
11566 | 3.86M | if (changed != 0) { |
11567 | 107k | code = gs_create_pdf14trans(&pct_new, ¶ms, pgs->memory); |
11568 | 107k | if (code < 0) |
11569 | 0 | return code; |
11570 | 107k | code = dev_proc(pdev->target, composite) |
11571 | 107k | (pdev->target, &pcdev, pct_new, (gs_gstate *)pgs, pgs->memory, NULL); |
11572 | 107k | gs_free_object(pgs->memory, pct_new, "pdf14_clist_update_params"); |
11573 | 107k | } |
11574 | 3.86M | return code; |
11575 | 3.86M | } |
11576 | | |
11577 | | /* |
11578 | | * fill_path routine for the PDF 1.4 transaprency compositor device for |
11579 | | * writing the clist. |
11580 | | */ |
11581 | | static int |
11582 | | pdf14_clist_fill_path(gx_device *dev, const gs_gstate *pgs, |
11583 | | gx_path *ppath, const gx_fill_params *params, |
11584 | | const gx_drawing_color *pdcolor, |
11585 | | const gx_clip_path *pcpath) |
11586 | 981k | { |
11587 | 981k | pdf14_clist_device * pdev = (pdf14_clist_device *)dev; |
11588 | 981k | gs_gstate new_pgs = *pgs; |
11589 | 981k | int code; |
11590 | 981k | gs_pattern2_instance_t *pinst = NULL; |
11591 | 981k | gx_device_forward * fdev = (gx_device_forward *)dev; |
11592 | 981k | cmm_dev_profile_t *dev_profile, *fwd_profile; |
11593 | 981k | gsicc_rendering_param_t render_cond; |
11594 | 981k | cmm_profile_t *icc_profile_fwd, *icc_profile_dev; |
11595 | 981k | int push_group = 0; |
11596 | | |
11597 | 981k | code = dev_proc(dev, get_profile)(dev, &dev_profile); |
11598 | 981k | if (code < 0) |
11599 | 0 | return code; |
11600 | 981k | code = dev_proc(fdev->target, get_profile)(fdev->target, &fwd_profile); |
11601 | 981k | if (code < 0) |
11602 | 0 | return code; |
11603 | | |
11604 | 981k | if (dev->color_info.separable_and_linear == GX_CINFO_UNKNOWN_SEP_LIN) |
11605 | 1.02k | check_device_separable(dev); |
11606 | | |
11607 | 981k | gsicc_extract_profile(GS_UNKNOWN_TAG, fwd_profile, &icc_profile_fwd, |
11608 | 981k | &render_cond); |
11609 | 981k | gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &icc_profile_dev, |
11610 | 981k | &render_cond); |
11611 | | |
11612 | | /* |
11613 | | * Ensure that that the PDF 1.4 reading compositor will have the current |
11614 | | * blending parameters. This is needed since the fill_rectangle routines |
11615 | | * do not have access to the gs_gstate. Thus we have to pass any |
11616 | | * changes explictly. |
11617 | | */ |
11618 | 981k | code = pdf14_clist_update_params(pdev, pgs, false, NULL); |
11619 | 981k | if (code < 0) |
11620 | 0 | return code; |
11621 | | /* If we are doing a shading fill and we are in a transparency group of a |
11622 | | different color space, then we do not want to do the shading in the |
11623 | | device color space. It must occur in the source space. To handle it in |
11624 | | the device space would require knowing all the nested transparency group |
11625 | | color space as well as the transparency. Some of the shading code ignores |
11626 | | this, so we have to pass on the clist_writer device to enable proper |
11627 | | mapping to the transparency group color space. */ |
11628 | | |
11629 | 981k | if (gx_dc_is_pattern2_color(pdcolor)) { |
11630 | | /* Non-idempotent blends require a transparency |
11631 | | * group to be pushed because shadings might |
11632 | | * paint several pixels twice. */ |
11633 | 4.85k | push_group = pgs->fillconstantalpha != 1.0 || |
11634 | 4.78k | !blend_is_idempotent(gs_currentblendmode(pgs)); |
11635 | 4.85k | pinst = |
11636 | 4.85k | (gs_pattern2_instance_t *)pdcolor->ccolor.pattern; |
11637 | 4.85k | pinst->saved->has_transparency = true; |
11638 | | /* The transparency color space operations are driven by the pdf14 |
11639 | | clist writer device. */ |
11640 | 4.85k | pinst->saved->trans_device = dev; |
11641 | 4.85k | } |
11642 | 981k | if (push_group) { |
11643 | 76 | gs_fixed_rect box; |
11644 | 76 | gs_fixed_rect dev_bbox; |
11645 | | |
11646 | 76 | if (pcpath) { |
11647 | 76 | gx_cpath_outer_box(pcpath, &box); |
11648 | 76 | (*dev_proc(dev, get_clipping_box)) (dev, &dev_bbox); |
11649 | 76 | rect_intersect(box, dev_bbox); |
11650 | 76 | } else |
11651 | 0 | (*dev_proc(dev, get_clipping_box)) (dev, &box); |
11652 | | |
11653 | 76 | if (ppath) { |
11654 | 20 | gs_fixed_rect path_box; |
11655 | | |
11656 | 20 | gx_path_bbox(ppath, &path_box); |
11657 | 20 | if (box.p.x < path_box.p.x) |
11658 | 20 | box.p.x = path_box.p.x; |
11659 | 20 | if (box.p.y < path_box.p.y) |
11660 | 20 | box.p.y = path_box.p.y; |
11661 | 20 | if (box.q.x > path_box.q.x) |
11662 | 20 | box.q.x = path_box.q.x; |
11663 | 20 | if (box.q.y > path_box.q.y) |
11664 | 20 | box.q.y = path_box.q.y; |
11665 | 20 | } |
11666 | | |
11667 | 76 | if (box.p.y >= box.q.y || box.p.x >= box.q.x) { |
11668 | | /* No need to do anything */ |
11669 | 36 | if (pinst != NULL) { |
11670 | 36 | pinst->saved->trans_device = NULL; |
11671 | 36 | } |
11672 | 36 | return 0; |
11673 | 36 | } |
11674 | | |
11675 | | /* Group alpha set from fill value. push_shfill_group does reset to 1.0 */ |
11676 | 40 | code = push_shfill_group(pdev, &new_pgs, &box); |
11677 | 40 | } else |
11678 | 980k | update_lop_for_pdf14(&new_pgs, pdcolor); |
11679 | 980k | if (code >= 0) { |
11680 | 980k | new_pgs.trans_device = dev; |
11681 | 980k | new_pgs.has_transparency = true; |
11682 | 980k | if (gx_dc_is_pattern2_color(pdcolor)) |
11683 | 4.81k | code = gx_default_fill_path_shading_or_pattern(dev, &new_pgs, ppath, params, pdcolor, pcpath); |
11684 | 976k | else |
11685 | 976k | code = gx_forward_fill_path(dev, &new_pgs, ppath, params, pdcolor, pcpath); |
11686 | 980k | new_pgs.trans_device = NULL; |
11687 | 980k | new_pgs.has_transparency = false; |
11688 | 980k | } |
11689 | 980k | if (code >= 0 && push_group) { |
11690 | 38 | code = pop_shfill_group(&new_pgs); |
11691 | 38 | if (code >= 0) |
11692 | 38 | code = pdf14_clist_update_params(pdev, pgs, false, NULL); |
11693 | 38 | } |
11694 | 980k | if (pinst != NULL){ |
11695 | 4.81k | pinst->saved->trans_device = NULL; |
11696 | 4.81k | } |
11697 | 980k | return code; |
11698 | 981k | } |
11699 | | |
11700 | | /* |
11701 | | * stroke_path routine for the PDF 1.4 transparency compositor device for |
11702 | | * writing the clist. |
11703 | | */ |
11704 | | static int |
11705 | | pdf14_clist_stroke_path(gx_device *dev, const gs_gstate *pgs, |
11706 | | gx_path *ppath, const gx_stroke_params *params, |
11707 | | const gx_drawing_color *pdcolor, |
11708 | | const gx_clip_path *pcpath) |
11709 | 341k | { |
11710 | 341k | pdf14_clist_device * pdev = (pdf14_clist_device *)dev; |
11711 | 341k | gs_gstate new_pgs = *pgs; |
11712 | 341k | int code = 0; |
11713 | 341k | gs_pattern2_instance_t *pinst = NULL; |
11714 | 341k | int push_group = 0; |
11715 | | |
11716 | | /* |
11717 | | * Ensure that that the PDF 1.4 reading compositor will have the current |
11718 | | * blending parameters. This is needed since the fill_rectangle routines |
11719 | | * do not have access to the gs_gstate. Thus we have to pass any |
11720 | | * changes explictly. |
11721 | | */ |
11722 | 341k | code = pdf14_clist_update_params(pdev, pgs, false, NULL); |
11723 | 341k | if (code < 0) |
11724 | 0 | return code; |
11725 | | /* If we are doing a shading stroke and we are in a transparency group of a |
11726 | | different color space, then we need to get the proper device information |
11727 | | passed along so that we use the correct color procs and colorinfo about |
11728 | | the transparency device and not the final target device */ |
11729 | 341k | if (gx_dc_is_pattern2_color(pdcolor)) { |
11730 | | /* Non-idempotent blends require a transparency |
11731 | | * group to be pushed because shadings might |
11732 | | * paint several pixels twice. */ |
11733 | 40 | push_group = pgs->strokeconstantalpha != 1.0 || |
11734 | 40 | !blend_is_idempotent(gs_currentblendmode(pgs)); |
11735 | 40 | if (pdev->color_model_stack != NULL) { |
11736 | 40 | pinst = |
11737 | 40 | (gs_pattern2_instance_t *)pdcolor->ccolor.pattern; |
11738 | 40 | pinst->saved->has_transparency = true; |
11739 | | /* The transparency color space operations are driven |
11740 | | by the pdf14 clist writer device. */ |
11741 | 40 | pinst->saved->trans_device = dev; |
11742 | 40 | } |
11743 | 40 | } |
11744 | 341k | if (push_group) { |
11745 | 0 | gs_fixed_rect box; |
11746 | 0 | if (pcpath) |
11747 | 0 | gx_cpath_outer_box(pcpath, &box); |
11748 | 0 | else |
11749 | 0 | (*dev_proc(dev, get_clipping_box)) (dev, &box); |
11750 | 0 | if (ppath) { |
11751 | 0 | gs_fixed_rect path_box; |
11752 | 0 | gs_fixed_point expansion; |
11753 | |
|
11754 | 0 | gx_path_bbox(ppath, &path_box); |
11755 | | /* Expand the path bounding box by the scaled line width. */ |
11756 | 0 | if (gx_stroke_path_expansion(pgs, ppath, &expansion) < 0) { |
11757 | | /* The expansion is so large it caused a limitcheck. */ |
11758 | 0 | path_box.p.x = path_box.p.y = min_fixed; |
11759 | 0 | path_box.q.x = path_box.q.y = max_fixed; |
11760 | 0 | } else { |
11761 | 0 | expansion.x += pgs->fill_adjust.x; |
11762 | 0 | expansion.y += pgs->fill_adjust.y; |
11763 | | /* |
11764 | | * It's theoretically possible for the following computations to |
11765 | | * overflow, so we need to check for this. |
11766 | | */ |
11767 | 0 | path_box.p.x = (path_box.p.x < min_fixed + expansion.x ? min_fixed : |
11768 | 0 | path_box.p.x - expansion.x); |
11769 | 0 | path_box.p.y = (path_box.p.y < min_fixed + expansion.y ? min_fixed : |
11770 | 0 | path_box.p.y - expansion.y); |
11771 | 0 | path_box.q.x = (path_box.q.x > max_fixed - expansion.x ? max_fixed : |
11772 | 0 | path_box.q.x + expansion.x); |
11773 | 0 | path_box.q.y = (path_box.q.y > max_fixed - expansion.y ? max_fixed : |
11774 | 0 | path_box.q.y + expansion.y); |
11775 | 0 | } |
11776 | 0 | if (box.p.x < path_box.p.x) |
11777 | 0 | box.p.x = path_box.p.x; |
11778 | 0 | if (box.p.y < path_box.p.y) |
11779 | 0 | box.p.y = path_box.p.y; |
11780 | 0 | if (box.q.x > path_box.q.x) |
11781 | 0 | box.q.x = path_box.q.x; |
11782 | 0 | if (box.q.y > path_box.q.y) |
11783 | 0 | box.q.y = path_box.q.y; |
11784 | 0 | } |
11785 | | /* Group alpha set from fill value. push_shfill_group does reset to 1.0 */ |
11786 | 0 | new_pgs.fillconstantalpha = new_pgs.strokeconstantalpha; |
11787 | 0 | code = push_shfill_group(pdev, &new_pgs, &box); |
11788 | 0 | } else |
11789 | 341k | update_lop_for_pdf14(&new_pgs, pdcolor); |
11790 | | |
11791 | 341k | if (code >= 0) { |
11792 | 341k | new_pgs.trans_device = dev; |
11793 | 341k | new_pgs.has_transparency = true; |
11794 | 341k | if (gx_dc_is_pattern2_color(pdcolor)) |
11795 | 40 | code = gx_default_stroke_path_shading_or_pattern(dev, &new_pgs, ppath, params, pdcolor, pcpath); |
11796 | 341k | else |
11797 | 341k | code = gx_forward_stroke_path(dev, &new_pgs, ppath, params, pdcolor, pcpath); |
11798 | 341k | new_pgs.trans_device = NULL; |
11799 | 341k | new_pgs.has_transparency = false; |
11800 | 341k | } |
11801 | 341k | if (code >= 0 && push_group) { |
11802 | 0 | code = pop_shfill_group(&new_pgs); |
11803 | 0 | if (code >= 0) |
11804 | 0 | code = pdf14_clist_update_params(pdev, pgs, false, NULL); |
11805 | 0 | } |
11806 | 341k | if (pinst != NULL) |
11807 | 40 | pinst->saved->trans_device = NULL; |
11808 | 341k | return code; |
11809 | 341k | } |
11810 | | |
11811 | | /* Set up work for doing shading patterns in fill stroke through |
11812 | | the clist. We have to do all the dirty work now since we are |
11813 | | going through the default fill and stroke operations individually */ |
11814 | | static int |
11815 | | pdf14_clist_fill_stroke_path_pattern_setup(gx_device* dev, const gs_gstate* cpgs, gx_path* ppath, |
11816 | | const gx_fill_params* params_fill, const gx_drawing_color* pdevc_fill, |
11817 | | const gx_stroke_params* params_stroke, const gx_drawing_color* pdevc_stroke, |
11818 | | const gx_clip_path* pcpath) |
11819 | 0 | { |
11820 | 0 | union { |
11821 | 0 | const gs_gstate *cpgs; |
11822 | 0 | gs_gstate *pgs; |
11823 | 0 | } const_breaker; |
11824 | 0 | gs_gstate *pgs; |
11825 | 0 | int code, code2; |
11826 | 0 | gs_transparency_group_params_t params = { 0 }; |
11827 | 0 | gs_fixed_rect clip_bbox; |
11828 | 0 | gs_rect bbox, group_stroke_box; |
11829 | 0 | float fill_alpha; |
11830 | 0 | float stroke_alpha; |
11831 | 0 | gs_blend_mode_t blend_mode; |
11832 | 0 | gs_fixed_rect path_bbox; |
11833 | 0 | int expansion_code; |
11834 | 0 | gs_fixed_point expansion; |
11835 | | |
11836 | | /* Break const just once, neatly */ |
11837 | 0 | const_breaker.cpgs = cpgs; |
11838 | 0 | pgs = const_breaker.pgs; |
11839 | |
|
11840 | 0 | fill_alpha = pgs->fillconstantalpha; |
11841 | 0 | stroke_alpha = pgs->strokeconstantalpha; |
11842 | 0 | blend_mode = pgs->blend_mode; |
11843 | |
|
11844 | 0 | code = gx_curr_fixed_bbox(pgs, &clip_bbox, NO_PATH); |
11845 | 0 | if (code < 0 && code != gs_error_unknownerror) |
11846 | 0 | return code; |
11847 | 0 | if (code == gs_error_unknownerror) { |
11848 | | /* didn't get clip box from gx_curr_fixed_bbox */ |
11849 | 0 | clip_bbox.p.x = clip_bbox.p.y = 0; |
11850 | 0 | clip_bbox.q.x = int2fixed(dev->width); |
11851 | 0 | clip_bbox.q.y = int2fixed(dev->height); |
11852 | 0 | } |
11853 | 0 | if (pcpath) |
11854 | 0 | rect_intersect(clip_bbox, pcpath->outer_box); |
11855 | | |
11856 | | /* expand the ppath using stroke expansion rule, then intersect it */ |
11857 | 0 | code = gx_path_bbox(ppath, &path_bbox); |
11858 | 0 | if (code == gs_error_nocurrentpoint && ppath->segments->contents.subpath_first == 0) |
11859 | 0 | return 0; /* ignore empty path */ |
11860 | 0 | if (code < 0) |
11861 | 0 | return code; |
11862 | 0 | expansion_code = gx_stroke_path_expansion(pgs, ppath, &expansion); |
11863 | 0 | if (expansion_code >= 0) { |
11864 | 0 | path_bbox.p.x -= expansion.x; |
11865 | 0 | path_bbox.p.y -= expansion.y; |
11866 | 0 | path_bbox.q.x += expansion.x; |
11867 | 0 | path_bbox.q.y += expansion.y; |
11868 | 0 | } |
11869 | 0 | rect_intersect(path_bbox, clip_bbox); |
11870 | 0 | bbox.p.x = fixed2float(path_bbox.p.x); |
11871 | 0 | bbox.p.y = fixed2float(path_bbox.p.y); |
11872 | 0 | bbox.q.x = fixed2float(path_bbox.q.x); |
11873 | 0 | bbox.q.y = fixed2float(path_bbox.q.y); |
11874 | |
|
11875 | 0 | code = gs_bbox_transform_inverse(&bbox, &ctm_only(pgs), &group_stroke_box); |
11876 | 0 | if (code < 0) |
11877 | 0 | return code; |
11878 | | |
11879 | | /* See if overprint is enabled for both stroke and fill AND if ca == CA */ |
11880 | 0 | if (pgs->fillconstantalpha == pgs->strokeconstantalpha && |
11881 | 0 | pgs->overprint && pgs->stroke_overprint && |
11882 | 0 | (dev->icc_struct->overprint_control != gs_overprint_control_disable) && |
11883 | 0 | dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE) { |
11884 | |
|
11885 | 0 | params.Isolated = false; |
11886 | 0 | params.group_color_type = UNKNOWN; |
11887 | 0 | params.Knockout = false; |
11888 | 0 | params.page_group = false; |
11889 | 0 | params.group_opacity = fill_alpha; |
11890 | 0 | params.group_shape = 1.0; |
11891 | | |
11892 | | /* non-isolated non-knockout group pushed with original alpha and blend mode */ |
11893 | 0 | code = gs_begin_transparency_group(pgs, ¶ms, &group_stroke_box, PDF14_BEGIN_TRANS_GROUP); |
11894 | 0 | if (code < 0) |
11895 | 0 | return code; |
11896 | | |
11897 | | /* Set alpha to 1.0 and compatible overprint mode for actual drawings */ |
11898 | 0 | (void)gs_setfillconstantalpha(pgs, 1.0); |
11899 | 0 | (void)gs_setstrokeconstantalpha(pgs, 1.0); |
11900 | 0 | (void)gs_setblendmode(pgs, BLEND_MODE_CompatibleOverprint); /* Can never fail */ |
11901 | |
|
11902 | 0 | code = pdf14_clist_fill_path(dev, pgs, ppath, params_fill, pdevc_fill, pcpath); |
11903 | 0 | if (code < 0) |
11904 | 0 | goto cleanup; |
11905 | | |
11906 | 0 | code = pdf14_clist_stroke_path(dev, pgs, ppath, params_stroke, pdevc_stroke, pcpath); |
11907 | 0 | if (code < 0) |
11908 | 0 | goto cleanup; |
11909 | |
|
11910 | 0 | } else { |
11911 | | /* Push a non-isolated knockout group. Do not change the alpha or |
11912 | | blend modes */ |
11913 | 0 | params.Isolated = false; |
11914 | 0 | params.group_color_type = UNKNOWN; |
11915 | 0 | params.Knockout = true; |
11916 | 0 | params.page_group = false; |
11917 | 0 | params.group_opacity = 1.0; |
11918 | 0 | params.group_shape = 1.0; |
11919 | | |
11920 | | /* non-isolated knockout group is pushed with alpha = 1.0 and Normal blend mode */ |
11921 | 0 | (void)gs_setfillconstantalpha(pgs, 1.0); |
11922 | 0 | (void)gs_setblendmode(pgs, BLEND_MODE_Normal); /* Can never fail */ |
11923 | 0 | code = gs_begin_transparency_group(pgs, ¶ms, &group_stroke_box, PDF14_BEGIN_TRANS_GROUP); |
11924 | | |
11925 | | /* restore blend mode for actual drawing in the group */ |
11926 | 0 | (void)gs_setblendmode(pgs, blend_mode); /* Can never fail */ |
11927 | |
|
11928 | 0 | if (fill_alpha > 0.0) { |
11929 | 0 | (void)gs_setfillconstantalpha(pgs, fill_alpha); |
11930 | | |
11931 | | /* If we are in an overprint situation, set the blend mode to compatible |
11932 | | overprint */ |
11933 | 0 | if ((dev->icc_struct->overprint_control != gs_overprint_control_disable) && |
11934 | 0 | pgs->overprint && |
11935 | 0 | dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE) |
11936 | 0 | (void)gs_setblendmode(pgs, BLEND_MODE_CompatibleOverprint); /* Can never fail */ |
11937 | |
|
11938 | 0 | code = pdf14_clist_fill_path(dev, pgs, ppath, params_fill, pdevc_fill, pcpath); |
11939 | 0 | if (code < 0) |
11940 | 0 | goto cleanup; |
11941 | | |
11942 | 0 | if ((dev->icc_struct->overprint_control != gs_overprint_control_disable) && |
11943 | 0 | pgs->overprint && |
11944 | 0 | dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE) |
11945 | 0 | (void)gs_setblendmode(pgs, blend_mode); /* Can never fail */ |
11946 | 0 | } |
11947 | | |
11948 | 0 | if (stroke_alpha > 0.0) { |
11949 | | /* Note that the stroke can end up looking like a fill here */ |
11950 | 0 | (void)gs_setstrokeconstantalpha(pgs, stroke_alpha); |
11951 | 0 | (void)gs_setfillconstantalpha(pgs, stroke_alpha); |
11952 | |
|
11953 | 0 | if (pgs->overprint && dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE) |
11954 | 0 | (void)gs_setblendmode(pgs, BLEND_MODE_CompatibleOverprint); /* Can never fail */ |
11955 | |
|
11956 | 0 | code = pdf14_clist_stroke_path(dev, pgs, ppath, params_stroke, pdevc_stroke, pcpath); |
11957 | 0 | if (code < 0) |
11958 | 0 | goto cleanup; |
11959 | | |
11960 | 0 | if ((dev->icc_struct->overprint_control != gs_overprint_control_disable) && |
11961 | 0 | pgs->overprint && |
11962 | 0 | dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE) |
11963 | 0 | (void)gs_setblendmode(pgs, blend_mode); /* Can never fail */ |
11964 | 0 | } |
11965 | 0 | } |
11966 | | |
11967 | 0 | cleanup: |
11968 | | /* Now during the pop do the compositing with alpha of 1.0 and normal blend */ |
11969 | 0 | (void)gs_setfillconstantalpha(pgs, 1.0); |
11970 | 0 | (void)gs_setstrokeconstantalpha(pgs, 1.0); |
11971 | 0 | (void)gs_setblendmode(pgs, BLEND_MODE_Normal); /* Can never fail */ |
11972 | | |
11973 | | /* Restore where we were. If an error occured while in the group push |
11974 | | return that error code but try to do the cleanup */ |
11975 | 0 | code2 = gs_end_transparency_group(pgs); |
11976 | 0 | if (code2 < 0) { |
11977 | | /* At this point things have gone very wrong. We should just shut down */ |
11978 | 0 | code = gs_abort_pdf14trans_device(pgs); |
11979 | 0 | return code2; |
11980 | 0 | } |
11981 | | |
11982 | | /* Restore if there were any changes */ |
11983 | 0 | (void)gs_setfillconstantalpha(pgs, fill_alpha); |
11984 | 0 | (void)gs_setstrokeconstantalpha(pgs, stroke_alpha); |
11985 | 0 | (void)gs_setblendmode(pgs, blend_mode); /* Can never fail */ |
11986 | |
|
11987 | 0 | return code; |
11988 | 0 | } |
11989 | | |
11990 | | /* |
11991 | | * fill_path routine for the PDF 1.4 transaprency compositor device for |
11992 | | * writing the clist. |
11993 | | */ |
11994 | | static int |
11995 | | pdf14_clist_fill_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath, |
11996 | | const gx_fill_params *params_fill, const gx_drawing_color *pdevc_fill, |
11997 | | const gx_stroke_params *params_stroke, const gx_drawing_color *pdevc_stroke, |
11998 | | const gx_clip_path *pcpath) |
11999 | 8.80k | { |
12000 | 8.80k | pdf14_clist_device * pdev = (pdf14_clist_device *)dev; |
12001 | 8.80k | gs_gstate new_pgs = *pgs; |
12002 | 8.80k | int code; |
12003 | | |
12004 | 8.80k | if ((pgs->fillconstantalpha == 0.0 && pgs->strokeconstantalpha == 0.0) || |
12005 | 8.71k | (pgs->ctm.xx == 0.0 && pgs->ctm.xy == 0.0 && pgs->ctm.yx == 0.0 && pgs->ctm.yy == 0.0)) |
12006 | 95 | return 0; |
12007 | | |
12008 | | /* |
12009 | | * Ensure that that the PDF 1.4 reading compositor will have the current |
12010 | | * blending parameters. This is needed since the fill_rectangle routines |
12011 | | * do not have access to the gs_gstate. Thus we have to pass any |
12012 | | * changes explictly. |
12013 | | */ |
12014 | 8.70k | code = pdf14_clist_update_params(pdev, pgs, false, NULL); |
12015 | 8.70k | if (code < 0) |
12016 | 0 | return code; |
12017 | | /* If we are doing a shading fill or stroke, the clist can't |
12018 | | deal with this and end up in the pdf_fill_stroke operation. |
12019 | | We will need to break up the fill stroke now and do |
12020 | | the appropriate group pushes and set up. */ |
12021 | | |
12022 | 8.70k | if (gx_dc_is_pattern2_color(pdevc_fill) || |
12023 | 8.70k | gx_dc_is_pattern2_color(pdevc_stroke)) { |
12024 | 0 | return pdf14_clist_fill_stroke_path_pattern_setup(dev, pgs, ppath, |
12025 | 0 | params_fill, pdevc_fill, params_stroke, pdevc_stroke, pcpath); |
12026 | 0 | } |
12027 | 8.70k | update_lop_for_pdf14(&new_pgs, pdevc_fill); |
12028 | 8.70k | new_pgs.trans_device = dev; |
12029 | 8.70k | new_pgs.has_transparency = true; |
12030 | 8.70k | code = gx_forward_fill_stroke_path(dev, &new_pgs, ppath, params_fill, pdevc_fill, |
12031 | 8.70k | params_stroke, pdevc_stroke, pcpath); |
12032 | 8.70k | new_pgs.trans_device = NULL; |
12033 | 8.70k | new_pgs.has_transparency = false; |
12034 | 8.70k | return code; |
12035 | 8.70k | } |
12036 | | |
12037 | | /* |
12038 | | * text_begin routine for the PDF 1.4 transaprency compositor device for |
12039 | | * writing the clist. |
12040 | | */ |
12041 | | static int |
12042 | | pdf14_clist_text_begin(gx_device * dev, gs_gstate * pgs, |
12043 | | const gs_text_params_t * text, gs_font * font, |
12044 | | const gx_clip_path * pcpath, |
12045 | | gs_text_enum_t ** ppenum) |
12046 | 2.43M | { |
12047 | 2.43M | pdf14_clist_device * pdev = (pdf14_clist_device *)dev; |
12048 | 2.43M | gs_text_enum_t *penum; |
12049 | 2.43M | int code; |
12050 | 2.43M | gs_blend_mode_t blend_mode = gs_currentblendmode(pgs); |
12051 | 2.43M | float opacity = pgs->fillconstantalpha; |
12052 | 2.43M | float shape = 1.0; |
12053 | 2.43M | bool blend_issue = !(blend_mode == BLEND_MODE_Normal || blend_mode == BLEND_MODE_Compatible || blend_mode == BLEND_MODE_CompatibleOverprint); |
12054 | 2.43M | bool draw = !(text->operation & TEXT_DO_NONE); |
12055 | 2.43M | uint text_mode = gs_currenttextrenderingmode(pgs); |
12056 | 2.43M | bool text_stroke = (text_mode == 1 || text_mode == 2 || text_mode == 5 || text_mode == 6); |
12057 | 2.43M | bool text_fill = (text_mode == 0 || text_mode == 2 || text_mode == 4 || text_mode == 6); |
12058 | | |
12059 | 2.43M | if_debug0m('v', pgs->memory, "[v]pdf14_clist_text_begin\n"); |
12060 | | /* |
12061 | | * Ensure that that the PDF 1.4 reading compositor will have the current |
12062 | | * blending parameters. This is needed since the fill_rectangle routines |
12063 | | * do not have access to the gs_gstate. Thus we have to pass any |
12064 | | * changes explictly. |
12065 | | */ |
12066 | 2.43M | code = pdf14_clist_update_params(pdev, pgs, false, NULL); |
12067 | 2.43M | if (code < 0) |
12068 | 0 | return code; |
12069 | | /* Pass text_begin to the target */ |
12070 | 2.43M | code = gx_forward_text_begin(dev, pgs, text, font, |
12071 | 2.43M | pcpath, &penum); |
12072 | 2.43M | if (code < 0) |
12073 | 546 | return code; |
12074 | | |
12075 | | /* Catch case where we already pushed a group and are trying to push another one. |
12076 | | In that case, we will pop the current one first, as we don't want to be left |
12077 | | with it. Note that if we have a BT and no other BTs or ETs then this issue |
12078 | | will not be caught until we do the put_image and notice that the stack is not |
12079 | | empty. */ |
12080 | 2.43M | if (pdev->text_group == PDF14_TEXTGROUP_MISSING_ET) { |
12081 | 0 | code = gs_end_transparency_group(pgs); |
12082 | 0 | if (code < 0) |
12083 | 0 | return code; |
12084 | 0 | pdev->text_group = PDF14_TEXTGROUP_BT_NOT_PUSHED; |
12085 | 0 | } |
12086 | | |
12087 | | /* We may need to push a non-isolated transparency group if the following |
12088 | | is true. |
12089 | | 1) We are not currently in one that we pushed for text. This is |
12090 | | is determined by looking at the pdf14 device. |
12091 | | 2) The blend mode is not Normal or the opacity is not 1.0 |
12092 | | 3) Text knockout is set to true |
12093 | | 4) And we are actually drawing text |
12094 | | */ |
12095 | | |
12096 | 2.43M | if (gs_currenttextknockout(pgs) && (blend_issue || |
12097 | 2.43M | (pgs->fillconstantalpha != 1.0 && text_fill) || |
12098 | 2.42M | (pgs->strokeconstantalpha != 1.0 && text_stroke)) && |
12099 | 12.8k | text_mode != 3 && /* don't bother with invisible text */ |
12100 | 12.7k | pdev->text_group == PDF14_TEXTGROUP_BT_NOT_PUSHED) { |
12101 | 2.96k | if (draw) { |
12102 | 2.96k | code = pdf14_push_text_group(dev, pgs, blend_mode, opacity, shape, true); |
12103 | 2.96k | if (code == 0) |
12104 | 2.96k | pdev->text_group = PDF14_TEXTGROUP_BT_PUSHED; /* Needed during clist writing */ |
12105 | 2.96k | } |
12106 | 2.96k | } |
12107 | 2.43M | *ppenum = (gs_text_enum_t *)penum; |
12108 | 2.43M | return code; |
12109 | 2.43M | } |
12110 | | |
12111 | | static int |
12112 | | pdf14_clist_begin_typed_image(gx_device * dev, const gs_gstate * pgs, |
12113 | | const gs_matrix *pmat, const gs_image_common_t *pic, |
12114 | | const gs_int_rect * prect, |
12115 | | const gx_drawing_color * pdcolor, |
12116 | | const gx_clip_path * pcpath, gs_memory_t * mem, |
12117 | | gx_image_enum_common_t ** pinfo) |
12118 | 46.9k | { |
12119 | 46.9k | pdf14_clist_device * pdev = (pdf14_clist_device *)dev; |
12120 | 46.9k | int code; |
12121 | 46.9k | gs_gstate * pgs_noconst = (gs_gstate *)pgs; /* Break 'const'. */ |
12122 | 46.9k | const gs_image_t *pim = (const gs_image_t *)pic; |
12123 | 46.9k | gx_image_enum *penum; |
12124 | 46.9k | gx_color_tile *ptile; |
12125 | 46.9k | gs_rect bbox_in, bbox_out; |
12126 | 46.9k | gs_transparency_group_params_t tgp; |
12127 | | /* |
12128 | | * Ensure that that the PDF 1.4 reading compositor will have the current |
12129 | | * blending parameters. This is needed since the fill_rectangle routines |
12130 | | * do not have access to the gs_gstate. Thus we have to pass any |
12131 | | * changes explictly. |
12132 | | */ |
12133 | 46.9k | code = pdf14_clist_update_params(pdev, pgs, false, NULL); |
12134 | 46.9k | if (code < 0) |
12135 | 0 | return code; |
12136 | | /* Pass image to the target */ |
12137 | | /* Do a quick change to the gs_gstate so that if we can return with -1 in |
12138 | | case the clist writer cannot handle this image itself. In such a case, |
12139 | | we want to make sure we dont use the target device. I don't necc. like |
12140 | | doing it this way. Probably need to go back and do something a bit |
12141 | | more elegant. */ |
12142 | 46.9k | pgs_noconst->has_transparency = true; |
12143 | 46.9k | pgs_noconst->trans_device = dev; |
12144 | | |
12145 | | /* If we are filling an image mask with a pattern that has a transparency |
12146 | | then we need to do some special handling */ |
12147 | 46.9k | if (pim->ImageMask) { |
12148 | 106 | if (pdcolor != NULL && gx_dc_is_pattern1_color(pdcolor)) { |
12149 | 28 | if( gx_pattern1_get_transptr(pdcolor) != NULL){ |
12150 | 0 | if (dev_proc(dev, begin_typed_image) != pdf14_clist_begin_typed_image) { |
12151 | 0 | ptile = pdcolor->colors.pattern.p_tile; |
12152 | | /* Set up things in the ptile so that we get the proper |
12153 | | blending etc */ |
12154 | | /* Set the blending procs and the is_additive setting based |
12155 | | upon the number of channels */ |
12156 | 0 | if (ptile->ttrans->n_chan-1 < 4) { |
12157 | 0 | ptile->ttrans->blending_procs = &rgb_blending_procs; |
12158 | 0 | ptile->ttrans->is_additive = true; |
12159 | 0 | } else { |
12160 | 0 | ptile->ttrans->blending_procs = &cmyk_blending_procs; |
12161 | 0 | ptile->ttrans->is_additive = false; |
12162 | 0 | } |
12163 | | /* Set the blending mode in the ptile based upon the current |
12164 | | setting in the gs_gstate */ |
12165 | 0 | ptile->blending_mode = pgs->blend_mode; |
12166 | | /* Set the procs so that we use the proper filling method. */ |
12167 | | /* Let the imaging stuff get set up */ |
12168 | 0 | code = gx_default_begin_typed_image(dev, pgs, pmat, pic, |
12169 | 0 | prect, pdcolor, |
12170 | 0 | pcpath, mem, pinfo); |
12171 | 0 | if (code < 0) |
12172 | 0 | return code; |
12173 | | |
12174 | 0 | penum = (gx_image_enum *) *pinfo; |
12175 | | /* Apply inverse of the image matrix to our |
12176 | | image size to get our bounding box. */ |
12177 | 0 | bbox_in.p.x = 0; |
12178 | 0 | bbox_in.p.y = 0; |
12179 | 0 | bbox_in.q.x = pim->Width; |
12180 | 0 | bbox_in.q.y = pim->Height; |
12181 | 0 | code = gs_bbox_transform_inverse(&bbox_in, &(pim->ImageMatrix), |
12182 | 0 | &bbox_out); |
12183 | 0 | if (code < 0) |
12184 | 0 | return code; |
12185 | | /* Set up a compositor action for pushing the group */ |
12186 | 0 | if_debug0m('v', pgs->memory, "[v]Pushing special trans group for image\n"); |
12187 | 0 | tgp.Isolated = true; |
12188 | 0 | tgp.Knockout = false; |
12189 | 0 | tgp.page_group = false; |
12190 | 0 | tgp.mask_id = 0; |
12191 | 0 | tgp.image_with_SMask = false; |
12192 | 0 | tgp.idle = false; |
12193 | 0 | tgp.iccprofile = NULL; |
12194 | 0 | tgp.icc_hashcode = 0; |
12195 | 0 | tgp.group_color_numcomps = ptile->ttrans->n_chan-1; |
12196 | 0 | tgp.ColorSpace = NULL; |
12197 | 0 | tgp.text_group = 0; |
12198 | 0 | tgp.group_opacity = pgs->fillconstantalpha; |
12199 | 0 | tgp.group_shape = 1.0; |
12200 | | /* This will handle the compositor command */ |
12201 | 0 | gs_begin_transparency_group((gs_gstate *) pgs_noconst, &tgp, |
12202 | 0 | &bbox_out, PDF14_BEGIN_TRANS_GROUP); |
12203 | 0 | ptile->ttrans->image_render = penum->render; |
12204 | 0 | penum->render = &pdf14_pattern_trans_render; |
12205 | 0 | ptile->trans_group_popped = false; |
12206 | 0 | pgs_noconst->has_transparency = false; |
12207 | 0 | pgs_noconst->trans_device = NULL; |
12208 | 0 | return code; |
12209 | 0 | } |
12210 | 0 | } |
12211 | 28 | } |
12212 | 106 | } |
12213 | | /* This basically tries high level images for clist. If that fails |
12214 | | then we do the default */ |
12215 | 46.9k | code = gx_forward_begin_typed_image(dev, pgs, pmat, |
12216 | 46.9k | pic, prect, pdcolor, pcpath, mem, pinfo); |
12217 | 46.9k | if (code < 0){ |
12218 | 11.6k | code = gx_default_begin_typed_image(dev, pgs, pmat, pic, prect, |
12219 | 11.6k | pdcolor, pcpath, mem, pinfo); |
12220 | 11.6k | pgs_noconst->has_transparency = false; |
12221 | 11.6k | pgs_noconst->trans_device = NULL; |
12222 | 11.6k | return code; |
12223 | 35.3k | } else { |
12224 | 35.3k | pgs_noconst->has_transparency = false; |
12225 | 35.3k | pgs_noconst->trans_device = NULL; |
12226 | 35.3k | return code; |
12227 | 35.3k | } |
12228 | 46.9k | } |
12229 | | |
12230 | | static int |
12231 | | pdf14_clist_copy_planes(gx_device * dev, const byte * data, int data_x, int raster, |
12232 | | gx_bitmap_id id, int x, int y, int w, int h, int plane_height) |
12233 | 2.45k | { |
12234 | 2.45k | int code; |
12235 | | |
12236 | 2.45k | code = gx_forward_copy_planes(dev, data, data_x, raster, id, |
12237 | 2.45k | x, y, w, h, plane_height); |
12238 | 2.45k | return code; |
12239 | 2.45k | } |
12240 | | |
12241 | | static int |
12242 | | gs_pdf14_clist_device_push(gs_memory_t *mem, gs_gstate *pgs, gx_device **pcdev, |
12243 | | gx_device *dev, const gs_pdf14trans_t *pdf14pct) |
12244 | 11.2k | { |
12245 | 11.2k | int code; |
12246 | 11.2k | pdf14_clist_device *p14dev; |
12247 | 11.2k | gx_device_clist_writer * const cdev = &((gx_device_clist *)dev)->writer; |
12248 | | |
12249 | 11.2k | code = pdf14_create_clist_device(mem, pgs, pcdev, dev, pdf14pct); |
12250 | 11.2k | if (code < 0) |
12251 | 0 | return code; |
12252 | | /* |
12253 | | * Set the color_info of the clist device to match the compositing |
12254 | | * device. We will restore it when the compositor is popped. |
12255 | | * See pdf14_clist_composite for the restore. Do the |
12256 | | * same with the gs_gstate's get_cmap_procs. We do not want |
12257 | | * the gs_gstate to use transfer functions on our color values. |
12258 | | * The transfer functions will be applied at the end after we |
12259 | | * have done our PDF 1.4 blend operations. |
12260 | | */ |
12261 | 11.2k | p14dev = (pdf14_clist_device *)(*pcdev); |
12262 | 11.2k | p14dev->saved_target_color_info = dev->color_info; |
12263 | 11.2k | dev->color_info = (*pcdev)->color_info; |
12264 | | /* Make sure that we keep the anti-alias information though */ |
12265 | 11.2k | dev->color_info.anti_alias = p14dev->saved_target_color_info.anti_alias; |
12266 | 11.2k | p14dev->color_info.anti_alias = dev->color_info.anti_alias; |
12267 | | |
12268 | | /* adjust the clist_color_info now */ |
12269 | 11.2k | cdev->clist_color_info.depth = p14dev->color_info.depth; |
12270 | 11.2k | cdev->clist_color_info.polarity = p14dev->color_info.polarity; |
12271 | 11.2k | cdev->clist_color_info.num_components = p14dev->color_info.num_components; |
12272 | 11.2k | cdev->clist_color_info.max_color = p14dev->color_info.max_color; |
12273 | 11.2k | cdev->clist_color_info.max_gray = p14dev->color_info.max_gray; |
12274 | | |
12275 | 11.2k | p14dev->saved_target_encode_color = dev_proc(dev, encode_color); |
12276 | 11.2k | p14dev->saved_target_decode_color = dev_proc(dev, decode_color); |
12277 | 11.2k | set_dev_proc(dev, encode_color, p14dev->my_encode_color); |
12278 | 11.2k | set_dev_proc(p14dev, encode_color, p14dev->my_encode_color); |
12279 | 11.2k | set_dev_proc(dev, decode_color, p14dev->my_decode_color); |
12280 | 11.2k | set_dev_proc(p14dev, decode_color, p14dev->my_decode_color); |
12281 | 11.2k | p14dev->saved_target_get_color_mapping_procs = |
12282 | 11.2k | dev_proc(dev, get_color_mapping_procs); |
12283 | 11.2k | p14dev->saved_target_get_color_comp_index = |
12284 | 11.2k | dev_proc(dev, get_color_comp_index); |
12285 | 11.2k | set_dev_proc(dev, get_color_mapping_procs, p14dev->my_get_color_mapping_procs); |
12286 | 11.2k | set_dev_proc(p14dev, get_color_mapping_procs, p14dev->my_get_color_mapping_procs); |
12287 | 11.2k | set_dev_proc(dev, get_color_comp_index, p14dev->my_get_color_comp_index); |
12288 | 11.2k | set_dev_proc(p14dev, get_color_comp_index, p14dev->my_get_color_comp_index); |
12289 | 11.2k | p14dev->save_get_cmap_procs = pgs->get_cmap_procs; |
12290 | 11.2k | pgs->get_cmap_procs = pdf14_get_cmap_procs; |
12291 | 11.2k | gx_set_cmap_procs(pgs, dev); |
12292 | 11.2k | return code; |
12293 | 11.2k | } |
12294 | | /* |
12295 | | * When we push a PDF 1.4 transparency compositor onto the clist, we also need |
12296 | | * to create a compositing device for clist writing. The primary purpose of |
12297 | | * this device is to provide support for the process color model in which |
12298 | | * the PDF 1.4 transparency is done. (This may differ from the process color |
12299 | | * model of the output device.) The actual work of compositing the image is |
12300 | | * done on the output (reader) side of the clist. |
12301 | | */ |
12302 | | static int |
12303 | | c_pdf14trans_clist_write_update(const gs_composite_t * pcte, gx_device * dev, |
12304 | | gx_device ** pcdev, gs_gstate * pgs, gs_memory_t * mem) |
12305 | 300k | { |
12306 | 300k | gx_device_clist_writer * const cdev = &((gx_device_clist *)dev)->writer; |
12307 | 300k | const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pcte; |
12308 | 300k | int code = 0; |
12309 | | |
12310 | | /* We only handle the push/pop operations */ |
12311 | 300k | switch (pdf14pct->params.pdf14_op) { |
12312 | 11.2k | case PDF14_PUSH_DEVICE: |
12313 | 11.2k | code = gs_pdf14_clist_device_push(mem, pgs, pcdev, dev, pdf14pct); |
12314 | | /* Change (non-error) code to 1 to indicate that we created |
12315 | | * a device. */ |
12316 | 11.2k | if (code >= 0) |
12317 | 11.2k | code = 1; |
12318 | 11.2k | return code; |
12319 | | |
12320 | 10.8k | case PDF14_POP_DEVICE: |
12321 | 10.8k | code = clist_writer_check_empty_cropping_stack(cdev); |
12322 | 10.8k | break; |
12323 | | |
12324 | 4.01k | case PDF14_BEGIN_TRANS_PAGE_GROUP: |
12325 | 42.6k | case PDF14_BEGIN_TRANS_GROUP: |
12326 | 42.6k | { /* HACK: store mask_id into our params for subsequent |
12327 | | calls of c_pdf14trans_write. To do this we must |
12328 | | break const. */ |
12329 | 42.6k | gs_pdf14trans_t * pdf14pct_noconst; |
12330 | | |
12331 | 42.6k | pdf14pct_noconst = (gs_pdf14trans_t *) pcte; |
12332 | | /* What ever the current mask ID is, that is the |
12333 | | softmask group through which this transparency |
12334 | | group must be rendered. Store it now. */ |
12335 | 42.6k | pdf14pct_noconst->params.mask_id = cdev->mask_id; |
12336 | 42.6k | if_debug1m('v', pgs->memory, |
12337 | 42.6k | "[v]c_pdf14trans_clist_write_update group mask_id=%d \n", |
12338 | 42.6k | cdev->mask_id); |
12339 | 42.6k | } |
12340 | 42.6k | break; |
12341 | 39.6k | case PDF14_END_TRANS_GROUP: |
12342 | 42.6k | case PDF14_END_TRANS_TEXT_GROUP: |
12343 | 42.6k | code = 0; /* A place for breakpoint. */ |
12344 | 42.6k | break; |
12345 | 45.0k | case PDF14_BEGIN_TRANS_MASK: |
12346 | | /* A new mask has been started */ |
12347 | 45.0k | cdev->mask_id = ++cdev->mask_id_count; |
12348 | | /* replacing is set everytime that we |
12349 | | have a zpushtransparencymaskgroup */ |
12350 | 45.0k | { /* HACK: store mask_id into our params for subsequent |
12351 | | calls of c_pdf14trans_write. To do this we must |
12352 | | break const. */ |
12353 | 45.0k | gs_pdf14trans_t * pdf14pct_noconst; |
12354 | | |
12355 | 45.0k | pdf14pct_noconst = (gs_pdf14trans_t *) pcte; |
12356 | 45.0k | pdf14pct_noconst->params.mask_id = cdev->mask_id; |
12357 | 45.0k | if_debug1m('v', pgs->memory, |
12358 | 45.0k | "[v]c_pdf14trans_clist_write_update mask mask_id=%d \n", |
12359 | 45.0k | cdev->mask_id); |
12360 | 45.0k | } |
12361 | 45.0k | break; |
12362 | 20.4k | case PDF14_END_TRANS_MASK: |
12363 | 20.4k | code = 0; /* A place for breakpoint. */ |
12364 | 20.4k | break; |
12365 | 0 | case PDF14_PUSH_TRANS_STATE: |
12366 | 0 | code = 0; /* A place for breakpoint. */ |
12367 | 0 | break; |
12368 | 19.9k | case PDF14_POP_TRANS_STATE: |
12369 | 19.9k | code = 0; /* A place for breakpoint. */ |
12370 | 19.9k | break; |
12371 | 0 | case PDF14_ABORT_DEVICE: |
12372 | 0 | code = 0; |
12373 | 0 | break; |
12374 | 0 | case PDF14_PUSH_SMASK_COLOR: |
12375 | 0 | *pcdev = dev; |
12376 | 0 | return 0; |
12377 | 0 | break; |
12378 | 0 | case PDF14_POP_SMASK_COLOR: |
12379 | 0 | *pcdev = dev; |
12380 | 0 | return 0; |
12381 | 0 | break; |
12382 | 107k | default: |
12383 | 107k | break; /* do nothing for remaining ops */ |
12384 | 300k | } |
12385 | 289k | *pcdev = dev; |
12386 | 289k | if (code < 0) |
12387 | 0 | return code; |
12388 | | /* See c_pdf14trans_write, c_pdf14trans_adjust_ctm, and |
12389 | | apply_composite. */ |
12390 | 289k | code = gs_gstate_setmatrix(&cdev->gs_gstate, &pdf14pct->params.ctm); |
12391 | | /* Wrote an extra ctm. */ |
12392 | 289k | cmd_clear_known(cdev, ctm_known); |
12393 | | |
12394 | 289k | return code; |
12395 | 289k | } |
12396 | | |
12397 | | /* |
12398 | | * When we push a PDF 1.4 transparency compositor, we need to make the clist |
12399 | | * device color_info data match the compositing device. We need to do this |
12400 | | * since the PDF 1.4 transparency compositing device may use a different |
12401 | | * process color model than the output device. We do not need to modify the |
12402 | | * color related device procs since the compositing device has its own. We |
12403 | | * restore the color_info data when the transparency device is popped. |
12404 | | */ |
12405 | | static int |
12406 | | c_pdf14trans_clist_read_update(gs_composite_t * pcte, gx_device * cdev, |
12407 | | gx_device * tdev, gs_gstate * pgs, gs_memory_t * mem) |
12408 | 22.7M | { |
12409 | 22.7M | pdf14_device * p14dev = (pdf14_device *)tdev; |
12410 | 22.7M | gs_pdf14trans_t * pdf14pct = (gs_pdf14trans_t *) pcte; |
12411 | 22.7M | gs_devn_params * pclist_devn_params; |
12412 | 22.7M | gx_device_clist_reader *pcrdev = (gx_device_clist_reader *)cdev; |
12413 | 22.7M | cmm_profile_t *cl_icc_profile, *p14_icc_profile; |
12414 | 22.7M | gsicc_rendering_param_t render_cond; |
12415 | 22.7M | cmm_dev_profile_t *dev_profile; |
12416 | | |
12417 | 22.7M | dev_proc(cdev, get_profile)(cdev, &dev_profile); |
12418 | 22.7M | gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &cl_icc_profile, |
12419 | 22.7M | &render_cond); |
12420 | | |
12421 | | /* If we are using the blending color space, then be sure to use that. */ |
12422 | 22.7M | if (p14dev->blend_cs_state == PDF14_BLEND_CS_SPECIFIED && |
12423 | 0 | dev_profile->blend_profile != NULL) |
12424 | 0 | cl_icc_profile = dev_profile->blend_profile; |
12425 | 22.7M | else if (p14dev->blend_cs_state == PDF14_BLEND_CS_OUTPUTINTENT && |
12426 | 0 | dev_profile->oi_profile != NULL) |
12427 | 0 | cl_icc_profile = dev_profile->oi_profile; |
12428 | | |
12429 | 22.7M | dev_proc(p14dev, get_profile)((gx_device *)p14dev, &dev_profile); |
12430 | 22.7M | gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &p14_icc_profile, |
12431 | 22.7M | &render_cond); |
12432 | | /* |
12433 | | * We only handle the push/pop operations. Save and restore the color_info |
12434 | | * field for the clist device. This is needed since the process color |
12435 | | * model of the clist device needs to match the PDF 1.4 compositing |
12436 | | * device. |
12437 | | */ |
12438 | 22.7M | switch (pdf14pct->params.pdf14_op) { |
12439 | 1.14M | case PDF14_PUSH_DEVICE: |
12440 | | /* Overprint simulation sets the profile at prototype creation, as does |
12441 | | when the target profile is NCLR. Match the logic in gs_pdf14_device_push */ |
12442 | 1.14M | if (!((p14dev->overprint_sim && cl_icc_profile->data_cs != gsCMYK) || |
12443 | 1.14M | cl_icc_profile->data_cs == gsNCHANNEL)) { |
12444 | 1.14M | gsicc_adjust_profile_rc(cl_icc_profile, 1, "c_pdf14trans_clist_read_update"); |
12445 | 1.14M | gsicc_adjust_profile_rc(p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], |
12446 | 1.14M | -1, "c_pdf14trans_clist_read_update"); |
12447 | 1.14M | p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] = cl_icc_profile; |
12448 | 1.14M | } |
12449 | | /* |
12450 | | * If we are blending using spot colors (i.e. the output device |
12451 | | * supports spot colors) then we need to transfer |
12452 | | * color info from the clist PDF 1.4 compositing reader device |
12453 | | * to the clist writer PDF 1.4 compositing device. |
12454 | | * This info was transfered from that device to the output |
12455 | | * device as a set of device parameters. However the clist |
12456 | | * reader PDF 1.4 compositing device did not exist when the |
12457 | | * device parameters were read from the clist. So that info |
12458 | | * was buffered into the output device. |
12459 | | */ |
12460 | 1.14M | pclist_devn_params = dev_proc(cdev, ret_devn_params)(cdev); |
12461 | 1.14M | if (pclist_devn_params != NULL && pclist_devn_params->page_spot_colors > 0) { |
12462 | 846 | int num_comp = p14dev->color_info.num_components; |
12463 | 846 | int has_tags = device_encodes_tags((gx_device *)p14dev); |
12464 | | /* |
12465 | | * The number of components for the PDF14 device is the sum |
12466 | | * of the process components and the number of spot colors |
12467 | | * for the page. If the color capabilities of the parent |
12468 | | * device (which coming into this are the same as the p14dev) |
12469 | | * are smaller than the number of page spot colors then |
12470 | | * use that for the number of components. Otherwise use |
12471 | | * the page_spot_colors. The exception is, if we had used |
12472 | | * the sICCOutputColors setting, then just use that, which |
12473 | | * should be already baked into num_comp. With clist patterns, |
12474 | | * cdev->icc_struct may be null. |
12475 | | */ |
12476 | | |
12477 | 846 | if (cdev->icc_struct == NULL || cdev->icc_struct->spotnames == NULL) { |
12478 | 846 | p14dev->devn_params.page_spot_colors = |
12479 | 846 | pclist_devn_params->page_spot_colors; |
12480 | 846 | if (num_comp < p14dev->devn_params.page_spot_colors + 4 ) { |
12481 | 0 | if (p14dev->num_planar_planes > 0) |
12482 | 0 | p14dev->num_planar_planes += num_comp - p14dev->color_info.num_components; |
12483 | 0 | p14dev->color_info.num_components = num_comp; |
12484 | 0 | assert(p14dev->num_planar_planes == 0 || p14dev->num_planar_planes == p14dev->color_info.num_components); |
12485 | 846 | } else { |
12486 | | /* if page_spot_colors < 0, this will be wrong, so don't update num_components */ |
12487 | 846 | if (p14dev->devn_params.page_spot_colors >= 0) { |
12488 | 846 | int n = p14dev->num_std_colorants + |
12489 | 846 | p14dev->devn_params.page_spot_colors + has_tags; |
12490 | 846 | if (p14dev->num_planar_planes > 0) |
12491 | 846 | p14dev->num_planar_planes += n - p14dev->color_info.num_components; |
12492 | 846 | p14dev->color_info.num_components = n; |
12493 | 846 | assert(p14dev->num_planar_planes == 0 || p14dev->num_planar_planes == p14dev->color_info.num_components); |
12494 | 846 | } |
12495 | 846 | } |
12496 | 846 | } |
12497 | | /* limit the num_components to the max. */ |
12498 | 846 | if (p14dev->color_info.num_components > p14dev->color_info.max_components + has_tags) |
12499 | 0 | p14dev->color_info.num_components = p14dev->color_info.max_components + has_tags; |
12500 | | /* Transfer the data for the spot color names |
12501 | | But we have to free what may be there before we do this */ |
12502 | 846 | devn_free_params((gx_device*) p14dev); |
12503 | 846 | p14dev->devn_params.separations = |
12504 | 846 | pclist_devn_params->pdf14_separations; |
12505 | 846 | p14dev->free_devicen = false; /* to avoid freeing the clist ones */ |
12506 | 846 | if (num_comp != p14dev->color_info.num_components) { |
12507 | | /* Historically, there has been a comment here: |
12508 | | "When the pdf14 device is opened it creates a context and some |
12509 | | soft mask related objects. The push device compositor action |
12510 | | will have already created these but they are the wrong size. |
12511 | | We must destroy them though before reopening the device." |
12512 | | I can't see why this is the case, and testing in the cluster |
12513 | | doesn't show ill effects from not doing it. Indeed, Bug 707790 |
12514 | | shows that this freeing/NULLing the ctx here causes problems |
12515 | | when the freed ctx is reinserted at the end of clist pattern |
12516 | | files. Accordingly, I'm removing the freeing/NULLing for now |
12517 | | at least. */ |
12518 | 0 | int code = dev_proc(tdev, open_device) (tdev); |
12519 | 0 | if (code < 0) |
12520 | 0 | return code; |
12521 | 0 | } |
12522 | 846 | } |
12523 | | /* Check if we need to swap out the ICC profile for the pdf14 |
12524 | | device. This will occur if our source profile for our device |
12525 | | happens to be something like CIELAB. Then we will blend in |
12526 | | RGB (unless a trans group is specified) */ |
12527 | 1.14M | if (cl_icc_profile->data_cs == gsCIELAB || cl_icc_profile->islab) { |
12528 | 0 | gsicc_adjust_profile_rc(p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], |
12529 | 0 | -1, "c_pdf14trans_clist_read_update"); |
12530 | | /* Initial ref count from gsicc_read_serial_icc() is 1, which is what we want */ |
12531 | 0 | p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] = |
12532 | 0 | gsicc_read_serial_icc(cdev, pcrdev->trans_dev_icc_hash); |
12533 | | /* Keep a pointer to the clist device */ |
12534 | 0 | p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE]->dev = (gx_device *) cdev; |
12535 | 0 | } |
12536 | 1.14M | break; |
12537 | | |
12538 | 1.14M | case PDF14_POP_DEVICE: |
12539 | | # if 0 /* Disabled because *p14dev has no forwarding methods during |
12540 | | the clist playback. This code is not executed while clist |
12541 | | writing. */ |
12542 | | cdev->color_info = p14dev->saved_target_color_info; |
12543 | | # endif |
12544 | 1.14M | break; |
12545 | | |
12546 | 20.4M | default: |
12547 | 20.4M | break; /* do nothing for remaining ops */ |
12548 | 22.7M | } |
12549 | | |
12550 | 22.7M | return 0; |
12551 | 22.7M | } |
12552 | | |
12553 | | /* |
12554 | | * Get cropping for the compositor command. |
12555 | | */ |
12556 | | static int |
12557 | | c_pdf14trans_get_cropping(const gs_composite_t *pcte, int *ry, int *rheight, |
12558 | | int cropping_min, int cropping_max) |
12559 | 300k | { |
12560 | 300k | gs_pdf14trans_t * pdf14pct = (gs_pdf14trans_t *) pcte; |
12561 | 300k | switch (pdf14pct->params.pdf14_op) { |
12562 | 11.2k | case PDF14_PUSH_DEVICE: return ALLBANDS; /* Applies to all bands. */ |
12563 | 10.8k | case PDF14_POP_DEVICE: return ALLBANDS; /* Applies to all bands. */ |
12564 | 0 | case PDF14_ABORT_DEVICE: return ALLBANDS; /* Applies to all bands */ |
12565 | 4.01k | case PDF14_BEGIN_TRANS_PAGE_GROUP: |
12566 | 42.6k | case PDF14_BEGIN_TRANS_GROUP: |
12567 | 42.6k | { gs_int_rect rect; |
12568 | | |
12569 | | /* Text group always uses parents size*/ |
12570 | 42.6k | if (pdf14pct->params.text_group == PDF14_TEXTGROUP_BT_PUSHED) { |
12571 | 2.96k | *ry = cropping_min; |
12572 | 2.96k | *rheight = cropping_max - *ry; |
12573 | 39.6k | } else { |
12574 | 39.6k | pdf14_compute_group_device_int_rect(&pdf14pct->params.ctm, |
12575 | 39.6k | &pdf14pct->params.bbox, &rect); |
12576 | | /* We have to crop this by the parent object. */ |
12577 | 39.6k | *ry = max(rect.p.y, cropping_min); |
12578 | 39.6k | *rheight = min(rect.q.y, cropping_max) - *ry; |
12579 | 39.6k | } |
12580 | 42.6k | return PUSHCROP; /* Push cropping. */ |
12581 | 4.01k | } |
12582 | 45.0k | case PDF14_BEGIN_TRANS_MASK: |
12583 | 45.0k | { gs_int_rect rect; |
12584 | | |
12585 | 45.0k | pdf14_compute_group_device_int_rect(&pdf14pct->params.ctm, |
12586 | 45.0k | &pdf14pct->params.bbox, &rect); |
12587 | | /* We have to crop this by the parent object and worry about the BC outside |
12588 | | the range, except for image SMask which don't affect areas outside the image. |
12589 | | The presence of a transfer function opens the possibility of issues with this */ |
12590 | 45.0k | if (pdf14pct->params.mask_is_image || (pdf14pct->params.GrayBackground == 1.0 && |
12591 | 19.3k | pdf14pct->params.function_is_identity)) { |
12592 | | /* In this case there will not be a background effect to |
12593 | | worry about. The mask will not have any effect outside |
12594 | | the bounding box. This is NOT the default or common case. */ |
12595 | 19.3k | *ry = max(rect.p.y, cropping_min); |
12596 | 19.3k | *rheight = min(rect.q.y, cropping_max) - *ry; |
12597 | 19.3k | return PUSHCROP; /* Push cropping. */ |
12598 | 25.6k | } else { |
12599 | | /* We need to make the soft mask range as large as the parent |
12600 | | due to the fact that the background color can have an impact |
12601 | | OUTSIDE the bounding box of the soft mask */ |
12602 | 25.6k | *ry = cropping_min; |
12603 | 25.6k | *rheight = cropping_max - cropping_min; |
12604 | 25.6k | if (pdf14pct->params.subtype == TRANSPARENCY_MASK_None) |
12605 | 24.5k | return SAMEAS_PUSHCROP_BUTNOPUSH; |
12606 | 1.15k | else |
12607 | 1.15k | return PUSHCROP; /* Push cropping. */ |
12608 | 25.6k | } |
12609 | 45.0k | } |
12610 | 39.6k | case PDF14_END_TRANS_GROUP: return POPCROP; /* Pop cropping. */ |
12611 | 2.93k | case PDF14_END_TRANS_TEXT_GROUP: return POPCROP; /* Pop cropping. */ |
12612 | 20.4k | case PDF14_END_TRANS_MASK: return POPCROP; /* Pop the cropping */ |
12613 | 0 | case PDF14_PUSH_TRANS_STATE: return CURRBANDS; |
12614 | 19.9k | case PDF14_POP_TRANS_STATE: return CURRBANDS; |
12615 | 107k | case PDF14_SET_BLEND_PARAMS: return ALLBANDS; |
12616 | 0 | case PDF14_PUSH_SMASK_COLOR: return POPCROP; /* Pop cropping. */ |
12617 | 0 | case PDF14_POP_SMASK_COLOR: return POPCROP; /* Pop the cropping */ |
12618 | 0 | case PDF14_BEGIN_TRANS_TEXT_GROUP: return ALLBANDS; /* should never occur */ |
12619 | 300k | } |
12620 | 0 | return ALLBANDS; |
12621 | 300k | } |
12622 | | |
12623 | | /* |
12624 | | * This routine will check to see if the color component name matches those |
12625 | | * that are available amoung the current device's color components. If the |
12626 | | * color name is known to the output device then we add it to the list of |
12627 | | * colorants for the PDF 1.4 transparency compositor. |
12628 | | * |
12629 | | * Notes: There are currently three different versions of The PDF 1.4 |
12630 | | * transparency compositor device. The choice of which one is being used |
12631 | | * depends upon the process color model of the output device. This procedure |
12632 | | * is only used if the output (target) device uses a CMYK, or RGB or Gray |
12633 | | * plus spot color process color model. |
12634 | | * |
12635 | | * Parameters: |
12636 | | * dev - pointer to device data structure. |
12637 | | * pname - pointer to name (zero termination not required) |
12638 | | * nlength - length of the name |
12639 | | * number of process colorants (either 1, 3, or 4) |
12640 | | * |
12641 | | * This routine returns a positive value (0 to n) which is the device colorant |
12642 | | * number if the name is found. It returns GX_DEVICE_COLOR_MAX_COMPONENTS if |
12643 | | * the colorant is not being used due to a SeparationOrder device parameter. |
12644 | | * It returns a negative value if not found. |
12645 | | */ |
12646 | | static int |
12647 | | pdf14_spot_get_color_comp_index(gx_device *dev, const char *pname, |
12648 | | int name_size, int component_type, int num_process_colors, int cmyk) |
12649 | 6.94k | { |
12650 | 6.94k | pdf14_device *pdev = (pdf14_device *)dev; |
12651 | 6.94k | gx_device *tdev = pdev->target; |
12652 | 6.94k | gs_devn_params *pdevn_params = &pdev->devn_params; |
12653 | 6.94k | gs_separations *pseparations; |
12654 | 6.94k | int comp_index; |
12655 | 6.94k | dev_proc_get_color_comp_index(*target_get_color_comp_index); |
12656 | 6.94k | int offset; |
12657 | | |
12658 | 6.94k | while (tdev->child) { |
12659 | 0 | tdev = tdev->child; |
12660 | 0 | } |
12661 | | /* If something has gone wrong and this is no longer the pdf14 compositor, */ |
12662 | | /* get the devn_params from the target to avoid accessing using the wrong */ |
12663 | | /* pointer. Bug 696372. */ |
12664 | 6.94k | if (tdev == (gx_device *)pdev) |
12665 | 0 | pdevn_params = dev_proc(pdev, ret_devn_params)(dev); |
12666 | 6.94k | offset = pdevn_params->num_std_colorant_names - num_process_colors; |
12667 | 6.94k | pseparations = &pdevn_params->separations; |
12668 | | /* If num_process_colors is 3 or 1 (RGB or Gray) then we are in a situation |
12669 | | * where we are in a blend color space that is RGB or Gray based and we |
12670 | | * have a spot colorant. If the spot colorant name is Cyan, Magenta |
12671 | | * Yellow or Black, then we should use the alternate tint transform */ |
12672 | 6.94k | if (num_process_colors < 4) { |
12673 | 594 | int k; |
12674 | 2.97k | for (k = 0; k < pdevn_params->num_std_colorant_names; k++) { |
12675 | 2.37k | if (strncmp(pname, pdevn_params->std_colorant_names[k], name_size) == 0) |
12676 | 0 | return -1; |
12677 | 2.37k | } |
12678 | 594 | } |
12679 | | |
12680 | 6.94k | target_get_color_comp_index = dev_proc(tdev, get_color_comp_index); |
12681 | | |
12682 | | /* The pdf14_clist_composite may have set the color procs. |
12683 | | We need the real target procs. */ |
12684 | 6.94k | if ((target_get_color_comp_index == pdf14_cmykspot_get_color_comp_index || |
12685 | 0 | target_get_color_comp_index == pdf14_rgbspot_get_color_comp_index)) |
12686 | 6.94k | target_get_color_comp_index = |
12687 | 6.94k | ((pdf14_clist_device *)pdev)->saved_target_get_color_comp_index; |
12688 | | /* |
12689 | | * If this is not a separation name then simply forward it to the target |
12690 | | * device or return -1 if we are doing overprint simulation. |
12691 | | * The halftone setup expects this. |
12692 | | */ |
12693 | 6.94k | if (!pdev->overprint_sim && (component_type == NO_COMP_NAME_TYPE_HT || |
12694 | 6.94k | component_type == NO_COMP_NAME_TYPE_OP)) { |
12695 | 6.15k | if (target_get_color_comp_index != NULL) |
12696 | 6.15k | return (*target_get_color_comp_index)(tdev, pname, name_size, component_type); |
12697 | 0 | else |
12698 | 0 | return -1; |
12699 | 6.15k | } |
12700 | 794 | if (pdev->overprint_sim && component_type == NO_COMP_NAME_TYPE_HT) { |
12701 | 0 | return -1; |
12702 | 0 | } |
12703 | | |
12704 | | /* |
12705 | | * Check if the component is in either the process color model list |
12706 | | * or in the SeparationNames list. |
12707 | | */ |
12708 | 794 | comp_index = check_pcm_and_separation_names(dev, pdevn_params, pname, |
12709 | 794 | name_size, component_type); |
12710 | | |
12711 | | /* Additive devices should NOT have C/M/Y/K Colorants added to them. |
12712 | | * This is a decision we take here to avoid problems with PDFI not |
12713 | | * counting such colorants as spots. */ |
12714 | 794 | if (comp_index < 0 && dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) { |
12715 | 36 | if (name_size == 5 && strncmp(pname, "Black", 7) == 0) |
12716 | 0 | return -1; |
12717 | 36 | if (name_size == 4 && strncmp(pname, "Cyan", 4) == 0) |
12718 | 0 | return -1; |
12719 | 36 | if (name_size == 7 && strncmp(pname, "Magenta", 7) == 0) |
12720 | 0 | return -1; |
12721 | 36 | if (name_size == 6 && strncmp(pname, "Yellow", 6) == 0) |
12722 | 0 | return -1; |
12723 | 36 | } |
12724 | | /* A psdrgb device, with simulate overprint will have become a cmyk |
12725 | | * device. As such, we don't want to add Black/Cyan/Magenta/Yellow to that |
12726 | | * either, but we need to return real numbers for them as the underlying |
12727 | | * routine won't know about these. */ |
12728 | 794 | if (comp_index < 0 && dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE && cmyk) { |
12729 | 2 | if (name_size == 5 && strncmp(pname, "Black", 7) == 0) |
12730 | 0 | return 3; |
12731 | 2 | if (name_size == 4 && strncmp(pname, "Cyan", 4) == 0) |
12732 | 0 | return 0; |
12733 | 2 | if (name_size == 7 && strncmp(pname, "Magenta", 7) == 0) |
12734 | 0 | return 1; |
12735 | 2 | if (name_size == 6 && strncmp(pname, "Yellow", 6) == 0) |
12736 | 0 | return 2; |
12737 | 2 | } |
12738 | | |
12739 | | /* |
12740 | | * Return the colorant number if we know this name. Note adjustment for |
12741 | | * compensating of blend color space. |
12742 | | */ |
12743 | 794 | if (comp_index >= 0) |
12744 | 756 | return comp_index - offset; |
12745 | | |
12746 | | /* Only worry about the target if we are not doing an overprint simulation */ |
12747 | 38 | if (!pdev->overprint_sim) { |
12748 | | /* |
12749 | | * If we do not know this color, check if the output (target) device does. |
12750 | | * Note that if the target device has ENABLE_AUTO_SPOT_COLORS this will add |
12751 | | * the colorant so we will only get < 0 returned when we hit the max. for |
12752 | | * the target device. |
12753 | | */ |
12754 | 38 | if (target_get_color_comp_index != NULL) |
12755 | 38 | comp_index = (*target_get_color_comp_index)(tdev, pname, name_size, component_type); |
12756 | 0 | else |
12757 | 0 | return -1; |
12758 | | /* |
12759 | | * Ignore color if unknown to the output device or if color is not being |
12760 | | * imaged due to the SeparationOrder device parameter. |
12761 | | */ |
12762 | 38 | if (comp_index < 0 || comp_index == GX_DEVICE_COLOR_MAX_COMPONENTS) |
12763 | 0 | return comp_index - offset; |
12764 | 38 | } |
12765 | | |
12766 | | /* |
12767 | | * This is a new colorant. Add it to our list of colorants. |
12768 | | * The limit accounts for the number of process colors (at least 4). |
12769 | | */ |
12770 | 38 | if ((pseparations->num_separations + 1) < |
12771 | 38 | (GX_DEVICE_COLOR_MAX_COMPONENTS - max(num_process_colors, 4))) { |
12772 | 38 | int sep_num = pseparations->num_separations++; |
12773 | 38 | int color_component_number; |
12774 | 38 | byte * sep_name; |
12775 | | |
12776 | 38 | sep_name = gs_alloc_bytes(dev->memory->stable_memory, |
12777 | 38 | name_size, "pdf14_spot_get_color_comp_index"); |
12778 | 38 | if (sep_name == NULL) { |
12779 | 0 | pseparations->num_separations--; /* we didn't add it */ |
12780 | 0 | return -1; |
12781 | 0 | } |
12782 | 38 | memcpy(sep_name, pname, name_size); |
12783 | 38 | pseparations->names[sep_num].size = name_size; |
12784 | 38 | pseparations->names[sep_num].data = sep_name; |
12785 | 38 | color_component_number = sep_num + num_process_colors; |
12786 | 38 | if (color_component_number >= dev->color_info.max_components) |
12787 | 0 | color_component_number = GX_DEVICE_COLOR_MAX_COMPONENTS; |
12788 | 38 | else |
12789 | 38 | pdevn_params->separation_order_map[color_component_number] = |
12790 | 38 | color_component_number; |
12791 | | |
12792 | | /* Indicate that we need to find equivalent CMYK color. */ |
12793 | 38 | pdev->op_pequiv_cmyk_colors.color[sep_num].color_info_valid = false; |
12794 | 38 | pdev->op_pequiv_cmyk_colors.all_color_info_valid = false; |
12795 | | |
12796 | | /* If we're doing an overprint simulation, then the target device |
12797 | | * (for instance) might not know about this colorant. This is annoying |
12798 | | * as the target can't then output the correct names. Call the target |
12799 | | * get_color_comp_index routine and ignore the result to give it a |
12800 | | * chance to stash it. */ |
12801 | 38 | if (pdev->overprint_sim && target_get_color_comp_index != NULL) |
12802 | 0 | (void)(*target_get_color_comp_index)(tdev, pname, name_size, component_type); |
12803 | | |
12804 | 38 | return color_component_number; |
12805 | 38 | } |
12806 | | |
12807 | 0 | return GX_DEVICE_COLOR_MAX_COMPONENTS; |
12808 | 38 | } |
12809 | | |
12810 | | |
12811 | | /* CMYK process + spots */ |
12812 | | static int |
12813 | | pdf14_cmykspot_get_color_comp_index(gx_device * dev, const char * pname, |
12814 | | int name_size, int component_type) |
12815 | 6.35k | { |
12816 | 6.35k | return pdf14_spot_get_color_comp_index(dev, pname, name_size, component_type, 4, 1); |
12817 | 6.35k | } |
12818 | | |
12819 | | /* RGB process + spots */ |
12820 | | static int |
12821 | | pdf14_rgbspot_get_color_comp_index(gx_device * dev, const char * pname, |
12822 | | int name_size, int component_type) |
12823 | 594 | { |
12824 | 594 | return pdf14_spot_get_color_comp_index(dev, pname, name_size, component_type, 3, 0); |
12825 | 594 | } |
12826 | | |
12827 | | /* Gray process + spots */ |
12828 | | static int |
12829 | | pdf14_grayspot_get_color_comp_index(gx_device * dev, const char * pname, |
12830 | | int name_size, int component_type) |
12831 | 0 | { |
12832 | 0 | return pdf14_spot_get_color_comp_index(dev, pname, name_size, component_type, 1, 0); |
12833 | 0 | } |
12834 | | |
12835 | | /* These functions keep track of when we are dealing with soft masks. |
12836 | | In such a case, we set the default color profiles to ones that ensure |
12837 | | proper soft mask rendering. */ |
12838 | | static int |
12839 | | pdf14_increment_smask_color(gs_gstate * pgs, gx_device * dev) |
12840 | 24.7k | { |
12841 | 24.7k | pdf14_device * pdev = (pdf14_device *) dev; |
12842 | 24.7k | pdf14_smaskcolor_t *result; |
12843 | 24.7k | gsicc_smask_t *smask_profiles = pgs->icc_manager->smask_profiles; |
12844 | 24.7k | int k; |
12845 | | |
12846 | | /* See if we have profiles already in place. Note we also have to |
12847 | | worry about a corner case where this device does not have a |
12848 | | smaskcolor stucture to store the profiles AND the profiles were |
12849 | | already swapped out in the icc_manager. This can occur when we |
12850 | | pushed a transparency mask and then inside the mask we have a pattern |
12851 | | which also has a transparency mask. The state of the icc_manager |
12852 | | is that it already has done the swap and there is no need to fool |
12853 | | with any of this while dealing with the soft mask within the pattern */ |
12854 | 24.7k | if (pdev->smaskcolor == NULL && pgs->icc_manager->smask_profiles != NULL && |
12855 | 24.7k | pgs->icc_manager->smask_profiles->swapped) { |
12856 | 0 | return 0; |
12857 | 0 | } |
12858 | 24.7k | if (pdev->smaskcolor != NULL) { |
12859 | 22 | pdev->smaskcolor->ref_count++; |
12860 | 22 | if_debug1m(gs_debug_flag_icc, dev->memory, |
12861 | 22 | "[icc] Increment smask color now %d\n", |
12862 | 22 | pdev->smaskcolor->ref_count); |
12863 | 24.7k | } else { |
12864 | | /* Allocate and swap out the current profiles. The softmask |
12865 | | profiles should already be in place */ |
12866 | 24.7k | result = gs_alloc_struct(pdev->memory->stable_memory, pdf14_smaskcolor_t, |
12867 | 24.7k | &st_pdf14_smaskcolor, |
12868 | 24.7k | "pdf14_increment_smask_color"); |
12869 | 24.7k | if (result == NULL) |
12870 | 0 | return gs_error_VMerror; |
12871 | | |
12872 | 24.7k | result->profiles = gsicc_new_iccsmask(pdev->memory->stable_memory); |
12873 | 24.7k | if (result->profiles == NULL) |
12874 | 0 | return gs_error_VMerror; |
12875 | | |
12876 | 24.7k | pdev->smaskcolor = result; |
12877 | | |
12878 | 24.7k | result->profiles->smask_gray = pgs->icc_manager->default_gray; |
12879 | 24.7k | result->profiles->smask_rgb = pgs->icc_manager->default_rgb; |
12880 | 24.7k | result->profiles->smask_cmyk = pgs->icc_manager->default_cmyk; |
12881 | 24.7k | pgs->icc_manager->default_gray = smask_profiles->smask_gray; |
12882 | 24.7k | gsicc_adjust_profile_rc(pgs->icc_manager->default_gray, 1, "pdf14_increment_smask_color"); |
12883 | 24.7k | pgs->icc_manager->default_rgb = smask_profiles->smask_rgb; |
12884 | 24.7k | gsicc_adjust_profile_rc(pgs->icc_manager->default_rgb, 1, "pdf14_increment_smask_color"); |
12885 | 24.7k | pgs->icc_manager->default_cmyk = smask_profiles->smask_cmyk; |
12886 | 24.7k | gsicc_adjust_profile_rc(pgs->icc_manager->default_cmyk, 1, "pdf14_increment_smask_color"); |
12887 | 24.7k | pgs->icc_manager->smask_profiles->swapped = true; |
12888 | 24.7k | if_debug0m(gs_debug_flag_icc, pgs->memory, |
12889 | 24.7k | "[icc] Initial creation of smask color. Ref count 1\n"); |
12890 | 24.7k | pdev->smaskcolor->ref_count = 1; |
12891 | | /* We also need to update the profile that is currently in the |
12892 | | color spaces of the graphic state. Otherwise this can be |
12893 | | referenced, which will result in a mismatch. What we want to do |
12894 | | is see if it was the original default and only swap in that case. */ |
12895 | 74.2k | for (k = 0; k < 2; k++) { |
12896 | 49.4k | gs_color_space *pcs = pgs->color[k].color_space; |
12897 | 49.4k | cmm_profile_t *profile = pcs->cmm_icc_profile_data; |
12898 | 49.4k | if (profile != NULL) { |
12899 | 47.8k | switch(profile->data_cs) { |
12900 | 27.6k | case gsGRAY: |
12901 | 27.6k | if (profile->hashcode == |
12902 | 27.6k | result->profiles->smask_gray->hashcode) { |
12903 | 25.4k | profile = pgs->icc_manager->default_gray; |
12904 | 25.4k | } |
12905 | 27.6k | break; |
12906 | 19.9k | case gsRGB: |
12907 | 19.9k | if (profile->hashcode == |
12908 | 19.9k | result->profiles->smask_rgb->hashcode) { |
12909 | 12.2k | profile = pgs->icc_manager->default_rgb; |
12910 | 12.2k | } |
12911 | 19.9k | break; |
12912 | 186 | case gsCMYK: |
12913 | 186 | if (profile->hashcode == |
12914 | 186 | result->profiles->smask_cmyk->hashcode) { |
12915 | 186 | profile = pgs->icc_manager->default_cmyk; |
12916 | 186 | } |
12917 | 186 | break; |
12918 | 0 | default: |
12919 | |
|
12920 | 0 | break; |
12921 | 47.8k | } |
12922 | 47.8k | if (pcs->cmm_icc_profile_data != profile) { |
12923 | 37.8k | gsicc_adjust_profile_rc(profile, 1, "pdf14_increment_smask_color"); |
12924 | 37.8k | gsicc_adjust_profile_rc(pcs->cmm_icc_profile_data, -1, "pdf14_increment_smask_color"); |
12925 | 37.8k | pcs->cmm_icc_profile_data = profile; |
12926 | 37.8k | } |
12927 | 47.8k | } |
12928 | 49.4k | } |
12929 | 24.7k | } |
12930 | 24.7k | return 0; |
12931 | 24.7k | } |
12932 | | |
12933 | | static int |
12934 | | pdf14_decrement_smask_color(gs_gstate * pgs, gx_device * dev) |
12935 | 35.5k | { |
12936 | 35.5k | pdf14_device * pdev = (pdf14_device *) dev; |
12937 | 35.5k | pdf14_smaskcolor_t *smaskcolor = pdev->smaskcolor; |
12938 | 35.5k | gsicc_manager_t *icc_manager = pgs->icc_manager; |
12939 | 35.5k | int k; |
12940 | | |
12941 | | /* See comment in pdf14_increment_smask_color to understand this one */ |
12942 | 35.5k | if (pdev->smaskcolor == NULL && pgs->icc_manager->smask_profiles != NULL && |
12943 | 4.49k | pgs->icc_manager->smask_profiles->swapped) { |
12944 | 0 | return 0; |
12945 | 0 | } |
12946 | 35.5k | if (smaskcolor != NULL) { |
12947 | 24.7k | smaskcolor->ref_count--; |
12948 | 24.7k | if_debug1m(gs_debug_flag_icc, pgs->memory, |
12949 | 24.7k | "[icc] Decrement smask color. Now %d\n", |
12950 | 24.7k | smaskcolor->ref_count); |
12951 | 24.7k | if (smaskcolor->ref_count == 0) { |
12952 | 24.7k | if_debug0m(gs_debug_flag_icc, pgs->memory, "[icc] Reset smask color.\n"); |
12953 | | /* Lets return the profiles and clean up */ |
12954 | | /* First see if we need to "reset" the profiles that are in |
12955 | | the graphic state */ |
12956 | 24.7k | if_debug0m(gs_debug_flag_icc, pgs->memory, "[icc] Reseting graphic state color spaces\n"); |
12957 | 74.2k | for (k = 0; k < 2; k++) { |
12958 | 49.4k | gs_color_space *pcs = pgs->color[k].color_space; |
12959 | 49.4k | cmm_profile_t *profile = pcs->cmm_icc_profile_data; |
12960 | 49.4k | if (profile != NULL) { |
12961 | 47.8k | switch(profile->data_cs) { |
12962 | 27.6k | case gsGRAY: |
12963 | 27.6k | if (profile->hashcode == |
12964 | 27.6k | pgs->icc_manager->default_gray->hashcode) { |
12965 | 25.4k | profile = |
12966 | 25.4k | smaskcolor->profiles->smask_gray; |
12967 | 25.4k | } |
12968 | 27.6k | break; |
12969 | 19.9k | case gsRGB: |
12970 | 19.9k | if (profile->hashcode == |
12971 | 19.9k | pgs->icc_manager->default_rgb->hashcode) { |
12972 | 12.2k | profile = |
12973 | 12.2k | smaskcolor->profiles->smask_rgb; |
12974 | 12.2k | } |
12975 | 19.9k | break; |
12976 | 186 | case gsCMYK: |
12977 | 186 | if (profile->hashcode == |
12978 | 186 | pgs->icc_manager->default_cmyk->hashcode) { |
12979 | 186 | profile = |
12980 | 186 | smaskcolor->profiles->smask_cmyk; |
12981 | 186 | } |
12982 | 186 | break; |
12983 | 0 | default: |
12984 | |
|
12985 | 0 | break; |
12986 | 47.8k | } |
12987 | 47.8k | if (pcs->cmm_icc_profile_data != profile) { |
12988 | 37.8k | gsicc_adjust_profile_rc(profile, 1, "pdf14_decrement_smask_color"); |
12989 | 37.8k | gsicc_adjust_profile_rc(pcs->cmm_icc_profile_data, -1, "pdf14_decrement_smask_color"); |
12990 | 37.8k | pcs->cmm_icc_profile_data = profile; |
12991 | 37.8k | } |
12992 | 47.8k | } |
12993 | 49.4k | } |
12994 | | |
12995 | 24.7k | gsicc_adjust_profile_rc(icc_manager->default_gray, -1, "pdf14_decrement_smask_color"); |
12996 | 24.7k | icc_manager->default_gray = smaskcolor->profiles->smask_gray; |
12997 | 24.7k | gsicc_adjust_profile_rc(icc_manager->default_rgb, -1, "pdf14_decrement_smask_color"); |
12998 | 24.7k | icc_manager->default_rgb = smaskcolor->profiles->smask_rgb; |
12999 | 24.7k | gsicc_adjust_profile_rc(icc_manager->default_cmyk, -1, "pdf14_decrement_smask_color"); |
13000 | 24.7k | icc_manager->default_cmyk = smaskcolor->profiles->smask_cmyk; |
13001 | 24.7k | icc_manager->smask_profiles->swapped = false; |
13002 | | /* We didn't increment the reference count when we assigned these |
13003 | | * so NULL them to avoid decrementing when smaskcolor is freed |
13004 | | */ |
13005 | 24.7k | smaskcolor->profiles->smask_gray = |
13006 | 24.7k | smaskcolor->profiles->smask_rgb = |
13007 | 24.7k | smaskcolor->profiles->smask_cmyk = NULL; |
13008 | | |
13009 | 24.7k | pdf14_free_smask_color(pdev); |
13010 | 24.7k | } |
13011 | 24.7k | } |
13012 | 35.5k | return 0; |
13013 | 35.5k | } |
13014 | | |
13015 | | static void |
13016 | | pdf14_free_smask_color(pdf14_device * pdev) |
13017 | 24.7k | { |
13018 | 24.7k | if (pdev->smaskcolor != NULL) { |
13019 | 24.7k | if ( pdev->smaskcolor->profiles != NULL) { |
13020 | | /* Do not decrement the profiles - the references were moved |
13021 | | here and moved back again, so the ref counts don't change |
13022 | | */ |
13023 | 24.7k | gs_free_object(pdev->memory->stable_memory, pdev->smaskcolor->profiles, |
13024 | 24.7k | "pdf14_free_smask_color"); |
13025 | 24.7k | } |
13026 | 24.7k | gs_free_object(pdev->memory->stable_memory, pdev->smaskcolor, "pdf14_free_smask_color"); |
13027 | 24.7k | pdev->smaskcolor = NULL; |
13028 | 24.7k | } |
13029 | 24.7k | } |
13030 | | |
13031 | | static void |
13032 | | pdf14_device_finalize(const gs_memory_t *cmem, void *vptr) |
13033 | 1.15M | { |
13034 | 1.15M | gx_device * const dev = (gx_device *)vptr; |
13035 | 1.15M | pdf14_device * pdev = (pdf14_device *)dev; |
13036 | 1.15M | int k; |
13037 | | |
13038 | 1.15M | pdf14_cleanup_group_color_profiles (pdev); |
13039 | | |
13040 | 1.15M | if (pdev->ctx) { |
13041 | 20 | pdf14_ctx_free(pdev->ctx); |
13042 | 20 | pdev->ctx = NULL; |
13043 | 20 | } |
13044 | | |
13045 | 1.15M | while (pdev->color_model_stack) { |
13046 | 39 | pdf14_pop_group_color(dev, NULL); |
13047 | 39 | } |
13048 | | |
13049 | 1.15M | for (k = 0; k < pdev->devn_params.separations.num_separations; k++) { |
13050 | 38 | if (pdev->devn_params.separations.names[k].data) { |
13051 | 38 | gs_free_object(pdev->memory->stable_memory, pdev->devn_params.separations.names[k].data, "pdf14_device_finalize"); |
13052 | 38 | pdev->devn_params.separations.names[k].data = NULL; |
13053 | 38 | } |
13054 | 38 | } |
13055 | | |
13056 | 1.15M | for (k = 0; k < pdev->devn_params.pdf14_separations.num_separations; k++) { |
13057 | 0 | if (pdev->devn_params.pdf14_separations.names[k].data) { |
13058 | 0 | gs_free_object(pdev->memory->stable_memory, pdev->devn_params.pdf14_separations.names[k].data, "pdf14_device_finalize"); |
13059 | 0 | pdev->devn_params.pdf14_separations.names[k].data = NULL; |
13060 | 0 | } |
13061 | 0 | } |
13062 | | |
13063 | 1.15M | gx_device_finalize(cmem, vptr); |
13064 | 1.15M | } |
13065 | | |
13066 | | #if DUMP_MASK_STACK |
13067 | | |
13068 | | static void |
13069 | | dump_mask_stack(pdf14_mask_t *mask_stack) |
13070 | | { |
13071 | | pdf14_mask_t *curr_mask = mask_stack; |
13072 | | int level = 0; |
13073 | | |
13074 | | while (curr_mask != NULL) { |
13075 | | if_debug1m('v', curr_mask->memory, "[v]mask_level, %d\n", level); |
13076 | | if_debug1m('v', curr_mask->memory, "[v]mask_buf, %p\n", curr_mask->rc_mask->mask_buf); |
13077 | | if_debug1m('v', curr_mask->memory, "[v]rc_count, %ld\n", curr_mask->rc_mask->rc.ref_count); |
13078 | | level++; |
13079 | | curr_mask = curr_mask->previous; |
13080 | | } |
13081 | | } |
13082 | | |
13083 | | /* A function to display the current state of the mask stack */ |
13084 | | static void |
13085 | | pdf14_debug_mask_stack_state(pdf14_ctx *ctx) |
13086 | | { |
13087 | | if_debug1m('v', ctx->memory, "[v]ctx_maskstack, %p\n", ctx->mask_stack); |
13088 | | if (ctx->mask_stack != NULL) { |
13089 | | dump_mask_stack(ctx->mask_stack); |
13090 | | } |
13091 | | if_debug1m('v', ctx->memory, "[v]ctx_stack, %p\n", ctx->stack); |
13092 | | if (ctx->stack != NULL) { |
13093 | | if_debug1m('v', ctx->memory, "[v]ctx_stack_maskstack, %p\n", ctx->stack->mask_stack); |
13094 | | if (ctx->stack->mask_stack != NULL) { |
13095 | | dump_mask_stack(ctx->stack->mask_stack); |
13096 | | } |
13097 | | } |
13098 | | } |
13099 | | |
13100 | | #else |
13101 | | |
13102 | | #ifdef DEBUG |
13103 | | static void |
13104 | | pdf14_debug_mask_stack_state(pdf14_ctx *ctx) |
13105 | | { |
13106 | | return; |
13107 | | } |
13108 | | #endif |
13109 | | |
13110 | | #endif /* DUMP_MASK_STACK */ |