/src/ghostpdl/base/gstrans.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2023 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* Implementation of transparency, other than rendering */ |
18 | | #include "math_.h" |
19 | | #include "memory_.h" |
20 | | #include "gx.h" |
21 | | #include "gserrors.h" |
22 | | #include "gstrans.h" |
23 | | #include "gsutil.h" |
24 | | #include "gzstate.h" |
25 | | #include "gxdevcli.h" |
26 | | #include "gdevdevn.h" |
27 | | #include "gxblend.h" |
28 | | #include "gdevp14.h" |
29 | | #include "gscspace.h" |
30 | | #include "gxarith.h" |
31 | | #include "gxclist.h" |
32 | | #include "gsicc_manage.h" |
33 | | #include "gsicc_cache.h" |
34 | | #include "gxdevsop.h" |
35 | | |
36 | | /* ------ Transparency-related graphics state elements ------ */ |
37 | | |
38 | | int |
39 | | gs_setblendmode(gs_gstate *pgs, gs_blend_mode_t mode) |
40 | 124k | { |
41 | | #ifdef DEBUG |
42 | | if (gs_debug_c('v')) { |
43 | | static const char *const bm_names[] = { GS_BLEND_MODE_NAMES }; |
44 | | |
45 | | dmlprintf1(pgs->memory, "[v]("PRI_INTPTR")blend_mode = ", (intptr_t)pgs); |
46 | | if (mode >= 0 && mode < countof(bm_names)) |
47 | | dmprintf1(pgs->memory, "%s\n", bm_names[mode]); |
48 | | else |
49 | | dmprintf1(pgs->memory, "%d??\n", (int)mode); |
50 | | } |
51 | | #endif |
52 | | /* Map Compatible to Normal so other code treats Compatible as Normal */ |
53 | | /* Often BLEND_MODE_Normal is checked for optimized handling, and */ |
54 | | /* Compatible is now specified to be the same. */ |
55 | 124k | if (mode == BLEND_MODE_Compatible) |
56 | 95.9k | mode = BLEND_MODE_Normal; |
57 | 124k | if ((int)mode < 0 || (int)mode > MAX_BLEND_MODE) |
58 | 0 | return_error(gs_error_rangecheck); |
59 | 124k | pgs->blend_mode = mode; |
60 | 124k | return 0; |
61 | 124k | } |
62 | | |
63 | | gs_blend_mode_t |
64 | | gs_currentblendmode(const gs_gstate *pgs) |
65 | 1.58M | { |
66 | 1.58M | return pgs->blend_mode; |
67 | 1.58M | } |
68 | | |
69 | | int |
70 | | gs_settextknockout(gs_gstate *pgs, bool knockout) |
71 | 92.6k | { |
72 | 92.6k | if_debug2m('v', pgs->memory, "[v]("PRI_INTPTR")text_knockout = %s\n", |
73 | 92.6k | (intptr_t)pgs, (knockout ? "true" : "false")); |
74 | 92.6k | pgs->text_knockout = knockout; |
75 | 92.6k | return 0; |
76 | 92.6k | } |
77 | | |
78 | | bool |
79 | | gs_currenttextknockout(const gs_gstate *pgs) |
80 | 492k | { |
81 | 492k | return pgs->text_knockout; |
82 | 492k | } |
83 | | |
84 | | /* This is used to keep pdf14 compositor actions from the interpreter from |
85 | | corrupting pattern renderings. For example, if the file has a softmask, |
86 | | the intrepter will send push and pop transparency state commands when |
87 | | q and Q operations are encountered. If we are writing out to a pattern |
88 | | clist that has no trasparency we do not want these state changes to |
89 | | be entered as compositor actions in the pattern clist */ |
90 | | |
91 | | static int |
92 | | check_for_nontrans_pattern(gs_gstate *pgs, unsigned char *comp_name) |
93 | 487k | { |
94 | 487k | gx_device * dev = pgs->device; |
95 | 487k | bool is_patt_clist = gx_device_is_pattern_clist(dev); |
96 | 487k | bool is_patt_acum = gx_device_is_pattern_accum(dev); |
97 | | |
98 | | /* Check if we are collecting data for a pattern that has no |
99 | | transparency. In that case, we need to ignore the state changes */ |
100 | 487k | if (is_patt_clist || is_patt_acum) { |
101 | 656 | if (is_patt_clist) { |
102 | 8 | gx_device_clist_writer *clwdev = (gx_device_clist_writer*) dev; |
103 | 8 | const gs_pattern1_instance_t *pinst = clwdev->pinst; |
104 | | |
105 | 8 | if (!(pinst->templat.uses_transparency)) { |
106 | 8 | if_debug1m('v', pgs->memory, |
107 | 8 | "[v]%s NOT sending in pattern\n",comp_name); |
108 | 8 | return(1); |
109 | 8 | } |
110 | 8 | } |
111 | 648 | if (is_patt_acum) { |
112 | 648 | gx_device_pattern_accum *padev = (gx_device_pattern_accum*) dev; |
113 | 648 | const gs_pattern1_instance_t *pinst = padev->instance; |
114 | | |
115 | 648 | if (!(pinst->templat.uses_transparency)) { |
116 | 648 | if_debug1m('v', pgs->memory, |
117 | 648 | "[v]%s NOT sending in pattern\n",comp_name); |
118 | 648 | return(1); |
119 | 648 | } |
120 | 648 | } |
121 | 648 | } |
122 | 486k | return(0); |
123 | 487k | } |
124 | | |
125 | | /* |
126 | | * Push a PDF 1.4 transparency compositor onto the current device. Note that |
127 | | * if the current device already is a PDF 1.4 transparency compositor, the |
128 | | * composite will update its parameters but not create a new |
129 | | * compositor device. |
130 | | */ |
131 | | static int |
132 | | gs_gstate_update_pdf14trans2(gs_gstate * pgs, gs_pdf14trans_params_t * pparams, bool retain_on_create) |
133 | 169k | { |
134 | 169k | gx_device * dev = pgs->device; |
135 | 169k | gx_device *pdf14dev = NULL; |
136 | 169k | int code; |
137 | 169k | int curr_num = dev->color_info.num_components; |
138 | | |
139 | | /* |
140 | | * Send the PDF 1.4 create compositor action specified by the parameters. |
141 | | */ |
142 | 169k | code = send_pdf14trans(pgs, dev, &pdf14dev, pparams, pgs->memory); |
143 | 169k | if (code < 0) |
144 | 2.96k | return code; |
145 | | /* |
146 | | * If we created a new PDF 1.4 compositor device then we need to install it |
147 | | * into the graphics state. |
148 | | */ |
149 | 166k | if (code == 1) { |
150 | 2.65k | gx_set_device_only(pgs, pdf14dev); |
151 | 2.65k | gx_device_retain(pdf14dev, retain_on_create); |
152 | 2.65k | code = 0; |
153 | 2.65k | } |
154 | | |
155 | | /* If we had a color space change and we are in overprint, then we need to |
156 | | update the drawn_comps */ |
157 | 166k | if (pgs->overprint && curr_num != pdf14dev->color_info.num_components) { |
158 | 76 | code = gs_do_set_overprint(pgs); |
159 | 76 | } |
160 | | |
161 | 166k | return code; |
162 | 169k | } |
163 | | |
164 | | static int |
165 | | gs_gstate_update_pdf14trans(gs_gstate * pgs, gs_pdf14trans_params_t * pparams) |
166 | 166k | { |
167 | 166k | return gs_gstate_update_pdf14trans2(pgs, pparams, true); |
168 | 166k | } |
169 | | |
170 | | void |
171 | | gs_trans_group_params_init(gs_transparency_group_params_t *ptgp, float opacity) |
172 | 6.01k | { |
173 | 6.01k | ptgp->ColorSpace = NULL; /* bogus, but can't do better */ |
174 | 6.01k | ptgp->Isolated = false; |
175 | 6.01k | ptgp->Knockout = false; |
176 | 6.01k | ptgp->page_group = false; |
177 | 6.01k | ptgp->text_group = PDF14_TEXTGROUP_NO_BT; |
178 | 6.01k | ptgp->image_with_SMask = false; |
179 | 6.01k | ptgp->mask_id = 0; |
180 | 6.01k | ptgp->iccprofile = NULL; |
181 | 6.01k | ptgp->group_opacity = opacity; |
182 | 6.01k | ptgp->group_shape = 1.0; |
183 | 6.01k | ptgp->shade_group = false; |
184 | 6.01k | } |
185 | | |
186 | | int |
187 | | gs_update_trans_marking_params(gs_gstate * pgs) |
188 | 2.96k | { |
189 | 2.96k | gs_pdf14trans_params_t params = { 0 }; |
190 | 2.96k | int code; |
191 | | |
192 | 2.96k | if_debug0m('v', pgs->memory, "[v]gs_update_trans_marking_params\n"); |
193 | 2.96k | params.pdf14_op = PDF14_SET_BLEND_PARAMS; |
194 | 2.96k | code = gs_gstate_update_pdf14trans(pgs, ¶ms); |
195 | 2.96k | if (code == gs_error_unregistered) |
196 | 2.96k | code = 0; |
197 | 2.96k | return code; |
198 | 2.96k | } |
199 | | |
200 | | int |
201 | | gs_begin_transparency_group(gs_gstate *pgs, |
202 | | const gs_transparency_group_params_t *ptgp, |
203 | | const gs_rect *pbbox, pdf14_compositor_operations group_type) |
204 | 9.08k | { |
205 | 9.08k | gs_pdf14trans_params_t params = { 0 }; |
206 | 9.08k | const gs_color_space *blend_color_space; |
207 | 9.08k | cmm_profile_t *profile; |
208 | | |
209 | 9.08k | if (check_for_nontrans_pattern(pgs, |
210 | 9.08k | (unsigned char *)"gs_begin_transparency_group")) { |
211 | 0 | return(0); |
212 | 0 | } |
213 | | /* |
214 | | * Put parameters into a compositor parameter and then call the |
215 | | * composite. This will pass the data to the PDF 1.4 |
216 | | * transparency device. |
217 | | */ |
218 | 9.08k | params.pdf14_op = group_type; |
219 | 9.08k | params.Isolated = ptgp->Isolated; |
220 | 9.08k | params.Knockout = ptgp->Knockout; |
221 | 9.08k | if (group_type == PDF14_BEGIN_TRANS_PAGE_GROUP) |
222 | 519 | params.page_group = true; |
223 | 9.08k | params.image_with_SMask = ptgp->image_with_SMask; |
224 | 9.08k | params.opacity = ptgp->group_opacity; |
225 | 9.08k | params.shape = ptgp->group_shape; |
226 | 9.08k | params.blend_mode = pgs->blend_mode; |
227 | 9.08k | params.text_group = ptgp->text_group; |
228 | 9.08k | params.shade_group = ptgp->shade_group; |
229 | 9.08k | params.ColorSpace = ptgp->ColorSpace; |
230 | | /* This function is called during the c-list writer side. |
231 | | Store some information so that we know what the color space is |
232 | | so that we can adjust according later during the clist reader. |
233 | | We currently will use the concrete space for any space other than a |
234 | | device space. However, if the device is a sep device it will blend |
235 | | in DeviceN color space as required. */ |
236 | 9.08k | blend_color_space = gs_currentcolorspace_inline(pgs); |
237 | 9.08k | if (gs_color_space_get_index(blend_color_space) > gs_color_space_index_DeviceCMYK) { |
238 | | /* ICC and PS CIE based case. Note that unidirectional PS CIE color |
239 | | spaces should not be allowed but end up occuring when processing |
240 | | PDF files with -dUseCIEColor. We will end up using the appropriate |
241 | | ICC default color space in these cases. */ |
242 | 9.08k | blend_color_space = gs_currentcolorspace_inline(pgs); |
243 | 9.08k | } else { |
244 | 0 | blend_color_space = cs_concrete_space(blend_color_space, pgs); |
245 | 0 | if (!blend_color_space) |
246 | 0 | return_error(gs_error_undefined); |
247 | 0 | } |
248 | | /* Note that if the /CS parameter was NOT present in the push |
249 | | of the transparency group, then we must actually inherent |
250 | | the previous group color space, or the color space of the |
251 | | target device (process color model). Here we just want |
252 | | to set it as a unknown type for clist writing, as we will take care |
253 | | of using the parent group color space later during clist reading. |
254 | | Also, if the group was not isolated we MUST use the parent group |
255 | | color space regardless of what the group color space is specified to be. |
256 | | Note that the page group should always be isolated */ |
257 | 9.08k | if (group_type == PDF14_BEGIN_TRANS_PAGE_GROUP) |
258 | 519 | params.Isolated = true; |
259 | | |
260 | 9.08k | if (ptgp->ColorSpace == NULL || params.Isolated != true) { |
261 | 8.50k | params.group_color_type = UNKNOWN; |
262 | 8.50k | params.group_color_numcomps = 0; |
263 | 8.50k | } else { |
264 | | /* The /CS parameter was present. Use what was set. Currently |
265 | | all our Device spaces are actually ICC based. The other options |
266 | | are if -dUseCIEColor is set, in which case it could be |
267 | | coming in as a PS CIE color space, which should not be allowed |
268 | | but should default to one of the default ICC color spaces. Note |
269 | | that CalRGB and CalGray, which are valid bidirectional color spaces |
270 | | are converted to ICC profiles during installation. PS CIE building |
271 | | to ICC is delayed. */ |
272 | 582 | if ( gs_color_space_is_ICC(blend_color_space) ) { |
273 | | /* Blending space is ICC based. If we are doing c-list rendering |
274 | | we will need to write this color space into the clist. |
275 | | */ |
276 | 582 | params.group_color_type = ICC; |
277 | 582 | params.group_color_numcomps = |
278 | 582 | blend_color_space->cmm_icc_profile_data->num_comps; |
279 | | /* Get the ICC profile */ |
280 | 582 | params.iccprofile = blend_color_space->cmm_icc_profile_data; |
281 | 582 | params.icc_hash = gsicc_get_hash(blend_color_space->cmm_icc_profile_data); |
282 | 582 | } else { |
283 | | /* Color space was NOT ICC based. PS CIE space and DeviceN are the only |
284 | | other option. Use the ICC default based upon the component count. */ |
285 | 0 | switch (cs_num_components(blend_color_space)) { |
286 | 0 | case 1: |
287 | 0 | profile = pgs->icc_manager->default_gray; |
288 | 0 | break; |
289 | 0 | case 3: |
290 | 0 | profile = pgs->icc_manager->default_rgb; |
291 | 0 | break; |
292 | 0 | case 4: |
293 | 0 | profile = pgs->icc_manager->default_cmyk; |
294 | 0 | break; |
295 | 0 | default: |
296 | | /* We can end up here if we are in a deviceN color space and |
297 | | we have a sep output device */ |
298 | 0 | profile = NULL; |
299 | 0 | params.group_color_type = DEVICEN; |
300 | 0 | params.group_color_numcomps = cs_num_components(blend_color_space); |
301 | 0 | break; |
302 | 0 | } |
303 | 0 | if (profile != NULL) { |
304 | 0 | params.group_color_type = ICC; |
305 | 0 | params.group_color_numcomps = profile->num_comps; |
306 | 0 | params.iccprofile = profile; |
307 | 0 | params.icc_hash = gsicc_get_hash(profile); |
308 | 0 | } |
309 | 0 | } |
310 | 582 | } |
311 | | #ifdef DEBUG |
312 | | if (gs_debug_c('v')) { |
313 | | static const char *const cs_names[] = { |
314 | | GS_COLOR_SPACE_TYPE_NAMES |
315 | | }; |
316 | | dmlprintf6(pgs->memory, "[v]("PRI_INTPTR")begin_transparency_group [%g %g %g %g] Num_grp_clr_comp = %d\n", |
317 | | (intptr_t)pgs, pbbox->p.x, pbbox->p.y, pbbox->q.x, pbbox->q.y,params.group_color_numcomps); |
318 | | if (ptgp->ColorSpace) |
319 | | dmprintf1(pgs->memory, " CS = %s", |
320 | | cs_names[(int)gs_color_space_get_index(ptgp->ColorSpace)]); |
321 | | else |
322 | | dmputs(pgs->memory, " (no CS)"); |
323 | | |
324 | | dmprintf4(pgs->memory, " Isolated = %d Knockout = %d text_group = %d page_group = %d\n", |
325 | | ptgp->Isolated, ptgp->Knockout, ptgp->text_group, ptgp->page_group); |
326 | | } |
327 | | #endif |
328 | 9.08k | params.bbox = *pbbox; |
329 | 9.08k | return gs_gstate_update_pdf14trans(pgs, ¶ms); |
330 | 9.08k | } |
331 | | |
332 | | int |
333 | | gx_begin_transparency_group(gs_gstate * pgs, gx_device * pdev, |
334 | | const gs_pdf14trans_params_t * pparams) |
335 | 254k | { |
336 | 254k | gs_transparency_group_params_t tgp = {0}; |
337 | 254k | gs_rect bbox; |
338 | | |
339 | 254k | if (pparams->Background_components != 0 && |
340 | 254k | pparams->Background_components != pdev->color_info.num_components) |
341 | 0 | return_error(gs_error_rangecheck); |
342 | 254k | tgp.Isolated = pparams->Isolated; |
343 | 254k | tgp.Knockout = pparams->Knockout; |
344 | 254k | tgp.page_group = pparams->page_group; |
345 | 254k | tgp.idle = pparams->idle; |
346 | 254k | tgp.mask_id = pparams->mask_id; |
347 | 254k | tgp.text_group = pparams->text_group; |
348 | 254k | tgp.shade_group = pparams->shade_group; |
349 | | |
350 | | /* Needed so that we do proper blending */ |
351 | 254k | tgp.group_color_type = pparams->group_color_type; |
352 | 254k | tgp.group_color_numcomps = pparams->group_color_numcomps; |
353 | 254k | tgp.iccprofile = pparams->iccprofile; |
354 | 254k | tgp.icc_hashcode = pparams->icc_hash; |
355 | | |
356 | 254k | tgp.group_opacity = pparams->opacity; |
357 | 254k | tgp.group_shape = pparams->shape; |
358 | | |
359 | 254k | if (tgp.Knockout && tgp.text_group == PDF14_TEXTGROUP_BT_PUSHED && |
360 | 254k | ((pgs->overprint && pgs->is_fill_color) || (pgs->stroke_overprint && !pgs->is_fill_color))) |
361 | 834 | pgs->blend_mode = BLEND_MODE_CompatibleOverprint; |
362 | 253k | else |
363 | 253k | pgs->blend_mode = pparams->blend_mode; |
364 | 254k | bbox = pparams->bbox; |
365 | | #ifdef DEBUG |
366 | | if (gs_debug_c('v')) { |
367 | | static const char *const cs_names[] = { |
368 | | GS_COLOR_SPACE_TYPE_NAMES |
369 | | }; |
370 | | dmlprintf6(pdev->memory, "[v]("PRI_INTPTR")gx_begin_transparency_group [%g %g %g %g] Num_grp_clr_comp = %d\n", |
371 | | (intptr_t)pgs, bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y, |
372 | | pparams->group_color_numcomps); |
373 | | dmlprintf2(pdev->memory, " opacity = %g shape = %g\n", pparams->opacity, pparams->shape); |
374 | | if (tgp.ColorSpace) |
375 | | dmprintf1(pdev->memory, " CS = %s", |
376 | | cs_names[(int)gs_color_space_get_index(tgp.ColorSpace)]); |
377 | | else |
378 | | dmputs(pdev->memory, " (no CS)"); |
379 | | dmprintf3(pdev->memory, " Isolated = %d Knockout = %d page_group = %d\n", |
380 | | tgp.Isolated, tgp.Knockout, tgp.page_group); |
381 | | if (tgp.iccprofile) |
382 | | dmprintf(pdev->memory, " Have ICC Profile for blending\n"); |
383 | | |
384 | | } |
385 | | #endif |
386 | 254k | return (*dev_proc(pdev, begin_transparency_group)) (pdev, &tgp, &bbox, pgs, |
387 | 254k | NULL); |
388 | 254k | } |
389 | | |
390 | | int |
391 | | gs_end_transparency_group(gs_gstate *pgs) |
392 | 8.98k | { |
393 | 8.98k | gs_pdf14trans_params_t params = { 0 }; |
394 | | |
395 | 8.98k | if (check_for_nontrans_pattern(pgs, |
396 | 8.98k | (unsigned char *)"gs_end_transparency_group")) { |
397 | 0 | return(0); |
398 | 0 | } |
399 | 8.98k | if_debug0m('v', pgs->memory, "[v]gs_end_transparency_group\n"); |
400 | 8.98k | params.pdf14_op = PDF14_END_TRANS_GROUP; /* Other parameters not used */ |
401 | 8.98k | return gs_gstate_update_pdf14trans(pgs, ¶ms); |
402 | 8.98k | } |
403 | | |
404 | | int |
405 | | gs_end_transparency_text_group(gs_gstate *pgs) |
406 | 62.6k | { |
407 | 62.6k | gs_pdf14trans_params_t params = { 0 }; |
408 | | |
409 | 62.6k | if (check_for_nontrans_pattern(pgs, |
410 | 62.6k | (unsigned char *)"gs_end_transparency_text_group")) { |
411 | 0 | return(0); |
412 | 0 | } |
413 | 62.6k | if_debug0m('v', pgs->memory, "[v]gs_end_transparency_text_group\n"); |
414 | 62.6k | params.pdf14_op = PDF14_END_TRANS_TEXT_GROUP; /* Other parameters not used */ |
415 | 62.6k | return gs_gstate_update_pdf14trans(pgs, ¶ms); |
416 | 62.6k | } |
417 | | |
418 | | int |
419 | | gs_begin_transparency_text_group(gs_gstate *pgs) |
420 | 59.9k | { |
421 | 59.9k | gs_pdf14trans_params_t params = { 0 }; |
422 | | |
423 | 59.9k | if (check_for_nontrans_pattern(pgs, |
424 | 59.9k | (unsigned char *)"gs_begin_transparency_text_group")) { |
425 | 0 | return(0); |
426 | 0 | } |
427 | 59.9k | if_debug0m('v', pgs->memory, "[v]gs_begin_transparency_text_group\n"); |
428 | 59.9k | params.pdf14_op = PDF14_BEGIN_TRANS_TEXT_GROUP; /* Other parameters not used */ |
429 | 59.9k | return gs_gstate_update_pdf14trans(pgs, ¶ms); |
430 | 59.9k | } |
431 | | |
432 | | int |
433 | | gx_end_transparency_group(gs_gstate * pgs, gx_device * pdev) |
434 | 254k | { |
435 | 254k | if_debug0m('v', pgs->memory, "[v]gx_end_transparency_group\n"); |
436 | 254k | return (*dev_proc(pdev, end_transparency_group)) (pdev, pgs); |
437 | 254k | } |
438 | | |
439 | | /* Commands for handling q softmask Q in graphic states */ |
440 | | |
441 | | int |
442 | | gs_push_transparency_state(gs_gstate *pgs) |
443 | 169k | { |
444 | 169k | gs_pdf14trans_params_t params = { 0 }; |
445 | 169k | int code; |
446 | | |
447 | 169k | if (check_for_nontrans_pattern(pgs, |
448 | 169k | (unsigned char *)"gs_push_transparency_state")) { |
449 | 328 | return(0); |
450 | 328 | } |
451 | | /* Set the pending flag to true, which indicates |
452 | | that we need to watch for end transparency |
453 | | soft masks when we are at this graphic state |
454 | | level */ |
455 | | /* pgs->trans_flags.xstate_pending = true; */ |
456 | | /* Actually I believe the above flag is not |
457 | | needed. We really should be watching for |
458 | | the softmask even at the base level. What |
459 | | we need to watch for are q operations after |
460 | | a soft mask end has occured. */ |
461 | | /* Check if we have a change flag set to true. |
462 | | this indicates that a softmask is present. |
463 | | We will need to send a push state to save |
464 | | the current soft mask, so that we can |
465 | | restore it later */ |
466 | 169k | if (pgs->trans_flags.xstate_change) { |
467 | 0 | if_debug0m('v', pgs->memory, "[v]gs_push_transparency_state sending\n"); |
468 | 0 | params.pdf14_op = PDF14_PUSH_TRANS_STATE; |
469 | 0 | code = gs_gstate_update_pdf14trans(pgs, ¶ms); |
470 | 0 | if (code < 0) |
471 | 0 | return(code); |
472 | 169k | } else { |
473 | 169k | if_debug0m('v', pgs->memory, "[v]gs_push_transparency_state NOT sending\n"); |
474 | 169k | } |
475 | 169k | return(0); |
476 | 169k | } |
477 | | |
478 | | int |
479 | | gs_pop_transparency_state(gs_gstate *pgs, bool force) |
480 | 165k | { |
481 | 165k | gs_pdf14trans_params_t params = { 0 }; |
482 | 165k | int code; |
483 | | |
484 | 165k | if (check_for_nontrans_pattern(pgs, |
485 | 165k | (unsigned char *)"gs_pop_transparency_state")) { |
486 | 328 | return(0); |
487 | 328 | } |
488 | | /* Check if flag is set, which indicates that we have |
489 | | an active softmask for the graphic state. We |
490 | | need to communicate to the compositor to pop |
491 | | the softmask */ |
492 | 164k | if ( pgs->trans_flags.xstate_change || force) { |
493 | 3.37k | if_debug0m('v', pgs->memory, "[v]gs_pop_transparency_state sending\n"); |
494 | 3.37k | params.pdf14_op = PDF14_POP_TRANS_STATE; |
495 | 3.37k | code = gs_gstate_update_pdf14trans(pgs, ¶ms); |
496 | 3.37k | if ( code < 0 ) |
497 | 0 | return (code); |
498 | 161k | } else { |
499 | 161k | if_debug0m('v', pgs->memory, "[v]gs_pop_transparency_state NOT sending\n"); |
500 | 161k | } |
501 | | /* There is no reason to reset any of the flags since |
502 | | they will be reset by the graphic state restore */ |
503 | 164k | return(0); |
504 | 164k | } |
505 | | |
506 | | int |
507 | | gx_pop_transparency_state(gs_gstate * pgs, gx_device * pdev) |
508 | 299k | { |
509 | 299k | if_debug0m('v', pgs->memory, "[v]gx_pop_transparency_state\n"); |
510 | 299k | return (*dev_proc(pdev, pop_transparency_state)) (pdev, pgs); |
511 | 299k | } |
512 | | |
513 | | int |
514 | | gx_push_transparency_state(gs_gstate * pgs, gx_device * pdev) |
515 | 0 | { |
516 | 0 | if_debug0m('v', pgs->memory, "[v]gx_push_transparency_state\n"); |
517 | 0 | return (*dev_proc(pdev, push_transparency_state)) (pdev, pgs); |
518 | 0 | } |
519 | | |
520 | | /* |
521 | | * Handler for identity mask transfer functions. |
522 | | */ |
523 | | static int |
524 | | mask_transfer_identity(double in, float *out, void *proc_data) |
525 | 883k | { |
526 | 883k | *out = (float) in; |
527 | 883k | return 0; |
528 | 883k | } |
529 | | |
530 | | void |
531 | | gs_trans_mask_params_init(gs_transparency_mask_params_t *ptmp, |
532 | | gs_transparency_mask_subtype_t subtype) |
533 | 8.35k | { |
534 | 8.35k | ptmp->ColorSpace = 0; |
535 | 8.35k | ptmp->subtype = subtype; |
536 | 8.35k | ptmp->Background_components = 0; |
537 | 8.35k | ptmp->Matte_components = 0; |
538 | 8.35k | ptmp->GrayBackground = 0.0; |
539 | 8.35k | ptmp->TransferFunction = mask_transfer_identity; |
540 | 8.35k | ptmp->TransferFunction_data = 0; |
541 | 8.35k | ptmp->replacing = false; |
542 | 8.35k | ptmp->iccprofile = NULL; |
543 | 8.35k | } |
544 | | |
545 | | int |
546 | | gs_begin_transparency_mask(gs_gstate * pgs, |
547 | | const gs_transparency_mask_params_t * ptmp, |
548 | | const gs_rect * pbbox, bool mask_is_image) |
549 | 8.07k | { |
550 | 8.07k | gs_pdf14trans_params_t params = { 0 }; |
551 | 8.07k | gs_pdf14trans_params_t params_color = { 0 }; |
552 | 8.07k | const int l = sizeof(params.Background[0]) * ptmp->Background_components; |
553 | 8.07k | const int m = sizeof(params.Matte[0]) * ptmp->Matte_components; |
554 | 8.07k | int i, code; |
555 | 8.07k | gs_color_space *blend_color_space; |
556 | 8.07k | gsicc_manager_t *icc_manager = pgs->icc_manager; |
557 | 8.07k | bool deep = device_is_deep(pgs->device); |
558 | | |
559 | 8.07k | if (check_for_nontrans_pattern(pgs, |
560 | 8.07k | (unsigned char *)"gs_pop_transparency_state")) { |
561 | 0 | return(0); |
562 | 0 | } |
563 | 8.07k | params.pdf14_op = PDF14_BEGIN_TRANS_MASK; |
564 | 8.07k | params.bbox = *pbbox; |
565 | 8.07k | params.subtype = ptmp->subtype; |
566 | 8.07k | params.Background_components = ptmp->Background_components; |
567 | 8.07k | memcpy(params.Background, ptmp->Background, l); |
568 | 8.07k | params.ColorSpace = ptmp->ColorSpace; |
569 | 8.07k | params.Matte_components = ptmp->Matte_components; |
570 | 8.07k | memcpy(params.Matte, ptmp->Matte, m); |
571 | 8.07k | params.GrayBackground = ptmp->GrayBackground; |
572 | 8.07k | params.transfer_function = ptmp->TransferFunction_data; |
573 | 8.07k | params.function_is_identity = |
574 | 8.07k | (ptmp->TransferFunction == mask_transfer_identity); |
575 | 8.07k | params.mask_is_image = mask_is_image; |
576 | 8.07k | params.replacing = ptmp->replacing; |
577 | | |
578 | | /* The eventual state that we want this smask to be moved to |
579 | | is always gray. This should provide us with a significant |
580 | | speed improvement over the old code. This does not keep us |
581 | | from having groups within the softmask getting blended in different |
582 | | color spaces, it just makes the final space be gray, which is what |
583 | | we will need to get to eventually anyway. In this way we avoid a |
584 | | final color conversion on a potentially large buffer. */ |
585 | | /* Also check if we have loaded in the transparency icc profiles. If not |
586 | | go ahead and take care of that now */ |
587 | 8.07k | if (icc_manager->smask_profiles == NULL) { |
588 | 460 | code = gsicc_initialize_iccsmask(icc_manager); |
589 | 460 | if (code < 0) |
590 | 0 | return(code); |
591 | 460 | } |
592 | | /* A new soft mask group, make sure the profiles are set */ |
593 | 8.07k | if_debug0m('v', pgs->memory, "[v]pushing soft mask color sending\n"); |
594 | 8.07k | if (params.subtype != TRANSPARENCY_MASK_None) { |
595 | 3.47k | params_color.pdf14_op = PDF14_PUSH_SMASK_COLOR; |
596 | 3.47k | code = gs_gstate_update_pdf14trans(pgs, ¶ms_color); |
597 | 3.47k | if (code < 0) |
598 | 0 | return(code); |
599 | 3.47k | blend_color_space = gs_cspace_new_DeviceGray(pgs->memory); |
600 | 3.47k | if (blend_color_space == NULL) |
601 | 0 | return_error(gs_error_VMerror); |
602 | 3.47k | blend_color_space->cmm_icc_profile_data = pgs->icc_manager->default_gray; |
603 | 3.47k | gsicc_adjust_profile_rc(blend_color_space->cmm_icc_profile_data, 1, "gs_begin_transparency_mask"); |
604 | 3.47k | if_debug9m('v', pgs->memory, "[v]("PRI_INTPTR")gs_begin_transparency_mask [%g %g %g %g]\n" |
605 | 3.47k | " subtype = %d Background_components = %d, Matte_components = %d, %s\n", |
606 | 3.47k | (intptr_t)pgs, pbbox->p.x, pbbox->p.y, pbbox->q.x, pbbox->q.y, |
607 | 3.47k | (int)ptmp->subtype, ptmp->Background_components, |
608 | 3.47k | ptmp->Matte_components, |
609 | 3.47k | (ptmp->TransferFunction == mask_transfer_identity ? "no TR" : |
610 | 3.47k | "has TR")); |
611 | | /* Sample the transfer function */ |
612 | | /* For non-deep cases, we sample at 00,01,02..fe,ff. |
613 | | * For deep cases, we sample from 0000,0100,0200..fe00,ff00 and a final one at ffff. |
614 | | * This enables us to interpolate easily. |
615 | | */ |
616 | 3.47k | if (deep) { |
617 | 0 | uint16_t *trans16 = (uint16_t *)params.transfer_fn; |
618 | 0 | float out; |
619 | 0 | for (i = 0; i < MASK_TRANSFER_FUNCTION_SIZE; i++) { |
620 | 0 | float in = (float)(i * (1.0 / MASK_TRANSFER_FUNCTION_SIZE)); |
621 | |
|
622 | 0 | ptmp->TransferFunction(in, &out, ptmp->TransferFunction_data); |
623 | 0 | trans16[i] = (uint16_t)floor((double)(out * 65535 + 0.5)); |
624 | 0 | } |
625 | 0 | ptmp->TransferFunction(1.0, &out, ptmp->TransferFunction_data); |
626 | 0 | trans16[MASK_TRANSFER_FUNCTION_SIZE] = (uint16_t)floor((double)(out * 65535 + 0.5)); |
627 | 3.47k | } else { |
628 | 893k | for (i = 0; i < MASK_TRANSFER_FUNCTION_SIZE; i++) { |
629 | 890k | float in = (float)(i * (1.0 / (MASK_TRANSFER_FUNCTION_SIZE - 1))); |
630 | 890k | float out; |
631 | | |
632 | 890k | ptmp->TransferFunction(in, &out, ptmp->TransferFunction_data); |
633 | 890k | params.transfer_fn[i] = (byte)floor((double)(out * 255 + 0.5)); |
634 | 890k | } |
635 | 3.47k | } |
636 | | /* Note: This function is called during the c-list writer side. */ |
637 | 3.47k | if ( blend_color_space->cmm_icc_profile_data != NULL ) { |
638 | | /* Blending space is ICC based. If we are doing c-list rendering we will |
639 | | need to write this color space into the clist. */ |
640 | 3.47k | params.group_color_type = ICC; |
641 | 3.47k | params.group_color_numcomps = |
642 | 3.47k | blend_color_space->cmm_icc_profile_data->num_comps; |
643 | | /* Get the ICC profile */ |
644 | | /* We don't reference count this - see comment in |
645 | | * pdf14_update_device_color_procs_pop_c() |
646 | | */ |
647 | 3.47k | params.iccprofile = blend_color_space->cmm_icc_profile_data; |
648 | 3.47k | params.icc_hash = gsicc_get_hash(blend_color_space->cmm_icc_profile_data); |
649 | 3.47k | } else { |
650 | 0 | params.group_color_type = GRAY_SCALE; |
651 | 0 | params.group_color_numcomps = 1; /* Need to check */ |
652 | 0 | } |
653 | | /* Explicitly decrement the profile data since blend_color_space may not |
654 | | * be an ICC color space object. |
655 | | */ |
656 | 3.47k | gsicc_adjust_profile_rc(blend_color_space->cmm_icc_profile_data, -1, "gs_begin_transparency_mask"); |
657 | 3.47k | rc_decrement_only_cs(blend_color_space, "gs_begin_transparency_mask"); |
658 | 3.47k | } |
659 | 8.07k | return gs_gstate_update_pdf14trans(pgs, ¶ms); |
660 | 8.07k | } |
661 | | |
662 | | /* This occurs on the c-list reader side */ |
663 | | |
664 | | int |
665 | | gx_begin_transparency_mask(gs_gstate * pgs, gx_device * pdev, |
666 | | const gs_pdf14trans_params_t * pparams) |
667 | 633k | { |
668 | 633k | gx_transparency_mask_params_t tmp; |
669 | 633k | const int l = sizeof(pparams->Background[0]) * pparams->Background_components; |
670 | 633k | const int m = sizeof(pparams->Matte[0]) * pparams->Matte_components; |
671 | | |
672 | 633k | tmp.group_color_type = pparams->group_color_type; |
673 | 633k | tmp.subtype = pparams->subtype; |
674 | 633k | tmp.group_color_numcomps = pparams->group_color_numcomps; |
675 | 633k | tmp.Background_components = pparams->Background_components; |
676 | 633k | memcpy(tmp.Background, pparams->Background, l); |
677 | 633k | tmp.Matte_components = pparams->Matte_components; |
678 | 633k | memcpy(tmp.Matte, pparams->Matte, m); |
679 | 633k | tmp.GrayBackground = pparams->GrayBackground; |
680 | 633k | tmp.function_is_identity = pparams->function_is_identity; |
681 | 633k | tmp.idle = pparams->idle; |
682 | 633k | tmp.replacing = pparams->replacing; |
683 | 633k | tmp.mask_id = pparams->mask_id; |
684 | | |
685 | 633k | if (tmp.group_color_type == ICC ) { |
686 | | /* Do I need to ref count here? */ |
687 | 62.9k | tmp.iccprofile = pparams->iccprofile; |
688 | 62.9k | tmp.icc_hashcode = pparams->icc_hash; |
689 | 570k | } else { |
690 | 570k | tmp.iccprofile = NULL; |
691 | 570k | tmp.icc_hashcode = 0; |
692 | 570k | } |
693 | 633k | memcpy(tmp.transfer_fn, pparams->transfer_fn, size_of(tmp.transfer_fn)); |
694 | 633k | if_debug10m('v', pgs->memory, |
695 | 633k | "[v]("PRI_INTPTR")gx_begin_transparency_mask [%g %g %g %g]\n" |
696 | 633k | " subtype = %d Background_components = %d Matte_components = %d Num_grp_clr_comp = %d %s\n", |
697 | 633k | (intptr_t)pgs, pparams->bbox.p.x, pparams->bbox.p.y, |
698 | 633k | pparams->bbox.q.x, pparams->bbox.q.y, |
699 | 633k | (int)tmp.subtype, tmp.Background_components, tmp.Matte_components, |
700 | 633k | tmp.group_color_numcomps, |
701 | 633k | (tmp.function_is_identity ? "no TR" : |
702 | 633k | "has TR")); |
703 | 633k | return (*dev_proc(pdev, begin_transparency_mask)) |
704 | 633k | (pdev, &tmp, &(pparams->bbox), pgs, NULL); |
705 | 633k | } |
706 | | |
707 | | int |
708 | | gs_end_transparency_mask(gs_gstate *pgs, |
709 | | gs_transparency_channel_selector_t csel) |
710 | 3.47k | { |
711 | 3.47k | gs_pdf14trans_params_t params = { 0 }; |
712 | 3.47k | gs_pdf14trans_params_t params_color = { 0 }; |
713 | 3.47k | int code; |
714 | | |
715 | 3.47k | if (check_for_nontrans_pattern(pgs, |
716 | 3.47k | (unsigned char *)"gs_end_transparency_mask")) { |
717 | 0 | return(0); |
718 | 0 | } |
719 | | /* If we have done a q then set a flag to watch for any Qs */ |
720 | | /* if (pgs->trans_flags.xstate_pending) |
721 | | pgs->trans_flags.xstate_change = true; */ |
722 | | /* This should not depend upon if we have encountered a q |
723 | | operation. We could be setting a softmask, before |
724 | | there is any q operation. Unlikely but it could happen. |
725 | | Then if we encouter a q operation (and this flag |
726 | | is true) we will need to |
727 | | push the mask graphic state (PDF14_PUSH_TRANS_STATE). */ |
728 | 3.47k | pgs->trans_flags.xstate_change = true; |
729 | 3.47k | if_debug1m('v', pgs->memory, |
730 | 3.47k | "[v]xstate_changed set true, gstate level is %d\n", pgs->level); |
731 | 3.47k | if_debug2m('v', pgs->memory, |
732 | 3.47k | "[v]("PRI_INTPTR")gs_end_transparency_mask(%d)\n", (intptr_t)pgs, |
733 | 3.47k | (int)csel); |
734 | 3.47k | params.pdf14_op = PDF14_END_TRANS_MASK; /* Other parameters not used */ |
735 | 3.47k | params.csel = csel; |
736 | | /* If this is the outer end then return us to our normal defaults */ |
737 | 3.47k | if_debug0m('v', pgs->memory, "[v]popping soft mask color sending\n"); |
738 | 3.47k | params_color.pdf14_op = PDF14_POP_SMASK_COLOR; |
739 | 3.47k | code = gs_gstate_update_pdf14trans(pgs, ¶ms_color); |
740 | 3.47k | if (code < 0) |
741 | 0 | return(code); |
742 | 3.47k | return gs_gstate_update_pdf14trans(pgs, ¶ms); |
743 | 3.47k | } |
744 | | |
745 | | int |
746 | | gx_end_transparency_mask(gs_gstate * pgs, gx_device * pdev, |
747 | | const gs_pdf14trans_params_t * pparams) |
748 | 62.9k | { |
749 | 62.9k | if_debug2m('v', pgs->memory, |
750 | 62.9k | "[v]("PRI_INTPTR")gx_end_transparency_mask(%d)\n", (intptr_t)pgs, |
751 | 62.9k | (int)pparams->csel); |
752 | 62.9k | return (*dev_proc(pdev, end_transparency_mask)) (pdev, pgs); |
753 | 62.9k | } |
754 | | |
755 | | /* |
756 | | * We really only care about the number of spot colors when we have |
757 | | * a device which supports spot colors. With the other devices we use |
758 | | * the tint transform function for DeviceN and Separation color spaces |
759 | | * and convert spot colors into process colors. |
760 | | */ |
761 | | static int |
762 | | get_num_pdf14_spot_colors(gs_gstate * pgs) |
763 | 2.65k | { |
764 | 2.65k | gx_device * dev = pgs->device; |
765 | 2.65k | gs_devn_params * pclist_devn_params = dev_proc(dev, ret_devn_params)(dev); |
766 | | |
767 | | /* |
768 | | * Devices which support spot colors store the PageSpotColors device |
769 | | * parameter inside their devn_params structure. (This is done by the |
770 | | * devn_put_params routine.) The PageSpotColors device parameter is |
771 | | * set by pdf_main whenever a PDF page is being processed. See |
772 | | * countspotcolors in lib/pdf_main.ps. |
773 | | */ |
774 | 2.65k | if (pclist_devn_params != NULL) { |
775 | | /* If the sep order names were specified, then we should only allocate |
776 | | for those. But only the nonstandard colorants that are stored |
777 | | in num_separations. See devn_put_params for details on this. |
778 | | Right now, the PDF14 device will always include CMYK. A future |
779 | | optimization is to be able to NOT have those included in the buffer |
780 | | allocations if we don't specify them. It would then be possible to |
781 | | output 8 separations at a time without using compressed color. */ |
782 | 1.53k | if (pclist_devn_params->num_separation_order_names == 0) { |
783 | 1.53k | return pclist_devn_params->page_spot_colors; |
784 | 1.53k | } |
785 | 0 | return (pclist_devn_params->separations.num_separations); |
786 | 1.53k | } |
787 | 1.11k | return 0; |
788 | 2.65k | } |
789 | | |
790 | | int |
791 | | gs_push_pdf14trans_device(gs_gstate * pgs, bool is_pattern, bool retain, |
792 | | int depth, int spot_color_count) |
793 | 2.65k | { |
794 | 2.65k | gs_pdf14trans_params_t params = { 0 }; |
795 | 2.65k | cmm_profile_t *icc_profile; |
796 | 2.65k | gsicc_rendering_param_t render_cond; |
797 | 2.65k | int code; |
798 | 2.65k | cmm_dev_profile_t *dev_profile; |
799 | 2.65k | unsigned char pattern_opsim_setting[2]; |
800 | | |
801 | 2.65k | code = dev_proc(pgs->device, get_profile)(pgs->device, &dev_profile); |
802 | 2.65k | if (code < 0) |
803 | 0 | return code; |
804 | 2.65k | gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &icc_profile, |
805 | 2.65k | &render_cond); |
806 | 2.65k | params.pdf14_op = PDF14_PUSH_DEVICE; |
807 | | /* |
808 | | * We really only care about the number of spot colors when we have |
809 | | * a device which supports spot colors. With the other devices we use |
810 | | * the tint transform function for DeviceN and Separation color spaces |
811 | | * and convert spot colors into process colors. |
812 | | */ |
813 | 2.65k | params.num_spot_colors = get_num_pdf14_spot_colors(pgs); |
814 | 2.65k | params.is_pattern = is_pattern; |
815 | | |
816 | | /* If pattern, get overprint simulation information from |
817 | | the pattern accumulators target device */ |
818 | 2.65k | if (is_pattern && dev_proc(pgs->device, dev_spec_op)(pgs->device, gxdso_overprintsim_state, &pattern_opsim_setting, sizeof(pattern_opsim_setting))) { |
819 | | /* Use the target device setting */ |
820 | 1.53k | params.overprint_sim_push = pattern_opsim_setting[0]; |
821 | 1.53k | params.num_spot_colors_int = pattern_opsim_setting[1]; |
822 | 1.53k | } else { |
823 | | /* Use information from interpreter */ |
824 | 1.11k | params.num_spot_colors_int = spot_color_count; |
825 | 1.11k | if (depth < 0) |
826 | 0 | params.overprint_sim_push = true; |
827 | 1.11k | } |
828 | | |
829 | | /* If we have an NCLR ICC profile, the extra spot colorants do |
830 | | * get included in the transparency buffers. Trying to avoid |
831 | | * including them became a rube goldberg mess in terms of knowing |
832 | | * which colorants are on the page vs what has been specified and |
833 | | * any aliasing between these two. Just too many things to go wrong. |
834 | | * So we allocate all and carry around. If you are doing special |
835 | | * spot handling with transparency this is the cost. */ |
836 | | |
837 | 2.65k | if (dev_profile->spotnames != NULL && dev_profile->spotnames->count > 4) { |
838 | | /* Making an assumption here, that list is CMYK + extra. |
839 | | An error should have been thrown by the target device if not. */ |
840 | 0 | int avail_page_spots = pgs->device->color_info.num_components - 4; |
841 | 0 | params.num_spot_colors_int = avail_page_spots; |
842 | 0 | params.num_spot_colors = avail_page_spots; |
843 | | |
844 | | /* This should not be possible, but lets be safe. We can't have a negative |
845 | | number of source spots to carry forward, so apply threshold. */ |
846 | 0 | if (params.num_spot_colors_int < 0) |
847 | 0 | params.num_spot_colors_int = 0; |
848 | 0 | if (params.num_spot_colors < 0) |
849 | 0 | params.num_spot_colors = 0; |
850 | 0 | } |
851 | | |
852 | | /* If we happen to be in a situation where we are going out to a device |
853 | | whose profile is CIELAB then we will need to make sure that we |
854 | | do our blending in RGB and convert to CIELAB when we do the put_image |
855 | | command */ |
856 | 2.65k | if (icc_profile->data_cs == gsCIELAB || |
857 | 2.65k | icc_profile->islab) { |
858 | 0 | params.iccprofile = pgs->icc_manager->default_rgb; |
859 | 0 | } |
860 | | /* Note: Other parameters not used */ |
861 | 2.65k | return gs_gstate_update_pdf14trans2(pgs, ¶ms, retain); |
862 | 2.65k | } |
863 | | |
864 | | int |
865 | | gs_pop_pdf14trans_device(gs_gstate * pgs, bool is_pattern) |
866 | 1.12k | { |
867 | 1.12k | gs_pdf14trans_params_t params = { 0 }; |
868 | | |
869 | 1.12k | params.is_pattern = is_pattern; |
870 | 1.12k | params.pdf14_op = PDF14_POP_DEVICE; /* Other parameters not used */ |
871 | 1.12k | return gs_gstate_update_pdf14trans(pgs, ¶ms); |
872 | 1.12k | } |
873 | | |
874 | | int |
875 | | gs_abort_pdf14trans_device(gs_gstate * pgs) |
876 | 0 | { |
877 | 0 | gs_pdf14trans_params_t params = { 0 }; |
878 | |
|
879 | 0 | params.pdf14_op = PDF14_ABORT_DEVICE; /* Other parameters not used */ |
880 | 0 | return gs_gstate_update_pdf14trans(pgs, ¶ms); |
881 | 0 | } |
882 | | |
883 | | /* Something has gone wrong have the device clean up everything */ |
884 | | |
885 | | int |
886 | | gx_abort_trans_device(gs_gstate * pgs, gx_device * pdev) |
887 | 0 | { |
888 | 0 | if_debug1m('v', pgs->memory, "[v]("PRI_INTPTR")gx_abort_trans_device\n", (intptr_t)pgs); |
889 | 0 | return (*dev_proc(pdev, discard_transparency_layer)) (pdev, pgs); |
890 | 0 | } |
891 | | |
892 | | int gs_setstrokeconstantalpha(gs_gstate *pgs, float alpha) |
893 | 142k | { |
894 | 142k | pgs->strokeconstantalpha = alpha; |
895 | 142k | return 0; |
896 | 142k | } |
897 | | |
898 | | float gs_getstrokeconstantalpha(const gs_gstate *pgs) |
899 | 3.23k | { |
900 | 3.23k | return pgs->strokeconstantalpha; |
901 | 3.23k | } |
902 | | |
903 | | int gs_setfillconstantalpha(gs_gstate *pgs, float alpha) |
904 | 148k | { |
905 | 148k | pgs->fillconstantalpha = (float)alpha; |
906 | 148k | return 0; |
907 | 148k | } |
908 | | |
909 | | float gs_getfillconstantalpha(const gs_gstate *pgs) |
910 | 9.00k | { |
911 | 9.00k | return pgs->fillconstantalpha; |
912 | 9.00k | } |
913 | | |
914 | | int gs_setalphaisshape(gs_gstate *pgs, bool AIS) |
915 | 119k | { |
916 | 119k | pgs->alphaisshape = AIS; |
917 | 119k | return 0; |
918 | 119k | } |
919 | | |
920 | | bool gs_getalphaisshape(gs_gstate *pgs) |
921 | 85.7k | { |
922 | 85.7k | return pgs->alphaisshape; |
923 | 85.7k | } |