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