1 /* Copyright (C) 2001-2006 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, modified
8 or distributed except as expressly authorized under the terms of that
9 license. Refer to licensing information at http://www.artifex.com/
10 or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11 San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
12 */
13
14 /* $Id: gstrans.c 10414 2009-11-30 23:37:23Z mvrhel $ */
15 /* Implementation of transparency, other than rendering */
16 #include "math_.h"
17 #include "memory_.h"
18 #include "gx.h"
19 #include "gserrors.h"
20 #include "gstrans.h"
21 #include "gsutil.h"
22 #include "gzstate.h"
23 #include "gxdevcli.h"
24 #include "gdevdevn.h"
25 #include "gxblend.h"
26 #include "gdevp14.h"
27 #include "gscspace.h"
28
29 #define PUSH_TS 0
30
31 /* ------ Transparency-related graphics state elements ------ */
32
33 int
gs_setblendmode(gs_state * pgs,gs_blend_mode_t mode)34 gs_setblendmode(gs_state *pgs, gs_blend_mode_t mode)
35 {
36 #ifdef DEBUG
37 if (gs_debug_c('v')) {
38 static const char *const bm_names[] = { GS_BLEND_MODE_NAMES };
39
40 dlprintf1("[v](0x%lx)blend_mode = ", (ulong)pgs);
41 if (mode >= 0 && mode < countof(bm_names))
42 dprintf1("%s\n", bm_names[mode]);
43 else
44 dprintf1("%d??\n", (int)mode);
45 }
46 #endif
47 if (mode < 0 || mode > MAX_BLEND_MODE)
48 return_error(gs_error_rangecheck);
49 pgs->blend_mode = mode;
50 return 0;
51 }
52
53 gs_blend_mode_t
gs_currentblendmode(const gs_state * pgs)54 gs_currentblendmode(const gs_state *pgs)
55 {
56 return pgs->blend_mode;
57 }
58
59 int
gs_setopacityalpha(gs_state * pgs,floatp alpha)60 gs_setopacityalpha(gs_state *pgs, floatp alpha)
61 {
62 if_debug2('v', "[v](0x%lx)opacity.alpha = %g\n", (ulong)pgs, alpha);
63 pgs->opacity.alpha = (alpha < 0.0 ? 0.0 : alpha > 1.0 ? 1.0 : alpha);
64 return 0;
65 }
66
67 float
gs_currentopacityalpha(const gs_state * pgs)68 gs_currentopacityalpha(const gs_state *pgs)
69 {
70 return pgs->opacity.alpha;
71 }
72
73 int
gs_setshapealpha(gs_state * pgs,floatp alpha)74 gs_setshapealpha(gs_state *pgs, floatp alpha)
75 {
76 if_debug2('v', "[v](0x%lx)shape.alpha = %g\n", (ulong)pgs, alpha);
77 pgs->shape.alpha = (alpha < 0.0 ? 0.0 : alpha > 1.0 ? 1.0 : alpha);
78 return 0;
79 }
80
81 float
gs_currentshapealpha(const gs_state * pgs)82 gs_currentshapealpha(const gs_state *pgs)
83 {
84 return pgs->shape.alpha;
85 }
86
87 int
gs_settextknockout(gs_state * pgs,bool knockout)88 gs_settextknockout(gs_state *pgs, bool knockout)
89 {
90 if_debug2('v', "[v](0x%lx)text_knockout = %s\n", (ulong)pgs,
91 (knockout ? "true" : "false"));
92 pgs->text_knockout = knockout;
93 return 0;
94 }
95
96 bool
gs_currenttextknockout(const gs_state * pgs)97 gs_currenttextknockout(const gs_state *pgs)
98 {
99 return pgs->text_knockout;
100 }
101
102 /* ------ Transparency rendering stack ------ */
103
104 gs_transparency_state_type_t
gs_current_transparency_type(const gs_state * pgs)105 gs_current_transparency_type(const gs_state *pgs)
106 {
107 return (pgs->transparency_stack == 0 ? 0 :
108 pgs->transparency_stack->type);
109 }
110
111 /* Support for dummy implementation */
112 gs_private_st_ptrs1(st_transparency_state, gs_transparency_state_t,
113 "gs_transparency_state_t", transparency_state_enum_ptrs,
114 transparency_state_reloc_ptrs, saved);
115 #if PUSH_TS
116 static int
push_transparency_stack(gs_state * pgs,gs_transparency_state_type_t type,client_name_t cname)117 push_transparency_stack(gs_state *pgs, gs_transparency_state_type_t type,
118 client_name_t cname)
119 {
120 gs_transparency_state_t *pts =
121 gs_alloc_struct(pgs->memory, gs_transparency_state_t,
122 &st_transparency_state, cname);
123
124 if (pts == 0)
125 return_error(gs_error_VMerror);
126 pts->saved = pgs->transparency_stack;
127 pts->type = type;
128 pgs->transparency_stack = pts;
129 return 0;
130 }
131 #endif
132 static void
pop_transparency_stack(gs_state * pgs,client_name_t cname)133 pop_transparency_stack(gs_state *pgs, client_name_t cname)
134 {
135 gs_transparency_state_t *pts = pgs->transparency_stack; /* known non-0 */
136 gs_transparency_state_t *saved = pts->saved;
137
138 gs_free_object(pgs->memory, pts, cname);
139 pgs->transparency_stack = saved;
140
141 }
142
143 /*
144 * Push a PDF 1.4 transparency compositor onto the current device. Note that
145 * if the current device already is a PDF 1.4 transparency compositor, the
146 * create_compositor will update its parameters but not create a new
147 * compositor device.
148 */
149 static int
gs_state_update_pdf14trans(gs_state * pgs,gs_pdf14trans_params_t * pparams)150 gs_state_update_pdf14trans(gs_state * pgs, gs_pdf14trans_params_t * pparams)
151 {
152 gs_imager_state * pis = (gs_imager_state *)pgs;
153 gx_device * dev = pgs->device;
154 gx_device *pdf14dev = NULL;
155 int code;
156
157 /*
158 * Send the PDF 1.4 create compositor action specified by the parameters.
159 */
160 code = send_pdf14trans(pis, dev, &pdf14dev, pparams, pgs->memory);
161 /*
162 * If we created a new PDF 1.4 compositor device then we need to install it
163 * into the graphics state.
164 */
165 if (code >= 0 && pdf14dev != dev)
166 gx_set_device_only(pgs, pdf14dev);
167
168 return code;
169 }
170
171 void
gs_trans_group_params_init(gs_transparency_group_params_t * ptgp)172 gs_trans_group_params_init(gs_transparency_group_params_t *ptgp)
173 {
174 ptgp->ColorSpace = 0; /* bogus, but can't do better */
175 ptgp->Isolated = false;
176 ptgp->Knockout = false;
177 ptgp->image_with_SMask = false;
178 ptgp->mask_id = 0;
179 }
180
181 int
gs_begin_transparency_group(gs_state * pgs,const gs_transparency_group_params_t * ptgp,const gs_rect * pbbox)182 gs_begin_transparency_group(gs_state *pgs,
183 const gs_transparency_group_params_t *ptgp,
184 const gs_rect *pbbox)
185 {
186 gs_pdf14trans_params_t params = { 0 };
187 const gs_color_space *blend_color_space;
188 gs_imager_state * pis = (gs_imager_state *)pgs;
189
190
191 /*
192 * Put parameters into a compositor parameter and then call the
193 * create_compositor. This will pass the data to the PDF 1.4
194 * transparency device.
195 */
196 params.pdf14_op = PDF14_BEGIN_TRANS_GROUP;
197 params.Isolated = ptgp->Isolated;
198 params.Knockout = ptgp->Knockout;
199 params.image_with_SMask = ptgp->image_with_SMask;
200 params.opacity = pgs->opacity;
201 params.shape = pgs->shape;
202 params.blend_mode = pgs->blend_mode;
203
204 /* The blending procs must be based upon the current color space */
205 /* Note: This function is called during the c-list writer side.
206 Store some information so that we know what the color space is
207 so that we can adjust according later during the clist reader */
208
209 /* Note that we currently will use the concrete space for any space other than a
210 device space. However, if the device is a sep device it will blend
211 in DeviceN color space as required. */
212
213 if (gs_color_space_get_index(pgs->color_space) <= gs_color_space_index_DeviceCMYK) {
214
215 blend_color_space = pgs->color_space;
216
217 } else {
218
219 /* ICC and CIE based color space. Problem right now is that the
220 current code does a concretization to the color space
221 defined by the CRD. This is not the space that we want
222 to blend in. Instead we want all colors to be mapped TO
223 the ICC color space. Then when the group is popped they
224 should be converted to the parent space.
225 That I will need to fix another day with the color changes.
226 For now we will punt and set our blending space as the
227 concrete space for the ICC space, which is defined by
228 the output (or default) CRD. */
229
230 blend_color_space = cs_concrete_space(pgs->color_space, pis);
231
232 }
233
234 /* Note that if the /CS parameter was not present in the push
235 of the transparency group, then we must actually inherent
236 the previous group color space, or the color space of the
237 target device (process color model). Note here we just want
238 to set it as a unknown type for clist writing, as we . We will later
239 during clist reading
240 */
241
242 if (ptgp->ColorSpace == NULL) {
243
244 params.group_color = UNKNOWN;
245 params.group_color_numcomps = 0;
246
247 } else {
248
249 switch (cs_num_components(blend_color_space)) {
250 case 1:
251 params.group_color = GRAY_SCALE;
252 params.group_color_numcomps = 1; /* Need to check */
253 break;
254 case 3:
255 params.group_color = DEVICE_RGB;
256 params.group_color_numcomps = 3;
257 break;
258 case 4:
259 params.group_color = DEVICE_CMYK;
260 params.group_color_numcomps = 4;
261 break;
262 default:
263
264 /* We can end up here if we are in
265 a deviceN color space and
266 we have a sep output device */
267
268 params.group_color = DEVICEN;
269 params.group_color_numcomps = cs_num_components(blend_color_space);
270
271 break;
272
273 }
274
275 }
276
277 #ifdef DEBUG
278 if (gs_debug_c('v')) {
279 static const char *const cs_names[] = {
280 GS_COLOR_SPACE_TYPE_NAMES
281 };
282
283 dlprintf6("[v](0x%lx)begin_transparency_group [%g %g %g %g] Num_grp_clr_comp = %d\n",
284 (ulong)pgs, pbbox->p.x, pbbox->p.y, pbbox->q.x, pbbox->q.y,params.group_color_numcomps);
285 if (ptgp->ColorSpace)
286 dprintf1(" CS = %s",
287 cs_names[(int)gs_color_space_get_index(ptgp->ColorSpace)]);
288 else
289 dputs(" (no CS)");
290 dprintf2(" Isolated = %d Knockout = %d\n",
291 ptgp->Isolated, ptgp->Knockout);
292 }
293 #endif
294
295 params.bbox = *pbbox;
296 return gs_state_update_pdf14trans(pgs, ¶ms);
297 }
298
299 int
gx_begin_transparency_group(gs_imager_state * pis,gx_device * pdev,const gs_pdf14trans_params_t * pparams)300 gx_begin_transparency_group(gs_imager_state * pis, gx_device * pdev,
301 const gs_pdf14trans_params_t * pparams)
302 {
303 gs_transparency_group_params_t tgp = {0};
304 gs_rect bbox;
305
306 if (pparams->Background_components != 0 &&
307 pparams->Background_components != pdev->color_info.num_components)
308 return_error(gs_error_rangecheck);
309 tgp.Isolated = pparams->Isolated;
310 tgp.Knockout = pparams->Knockout;
311 tgp.idle = pparams->idle;
312 tgp.mask_id = pparams->mask_id;
313
314 /* Needed so that we do proper blending */
315 tgp.group_color = pparams->group_color;
316 tgp.group_color_numcomps = pparams->group_color_numcomps;
317
318 pis->opacity.alpha = pparams->opacity.alpha;
319 pis->shape.alpha = pparams->shape.alpha;
320 pis->blend_mode = pparams->blend_mode;
321 bbox = pparams->bbox;
322 #ifdef DEBUG
323 if (gs_debug_c('v')) {
324 static const char *const cs_names[] = {
325 GS_COLOR_SPACE_TYPE_NAMES
326 };
327
328 dlprintf6("[v](0x%lx)gx_begin_transparency_group [%g %g %g %g] Num_grp_clr_comp = %d\n",
329 (ulong)pis, bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y,pparams->group_color_numcomps);
330 if (tgp.ColorSpace)
331 dprintf1(" CS = %s",
332 cs_names[(int)gs_color_space_get_index(tgp.ColorSpace)]);
333 else
334 dputs(" (no CS)");
335 dprintf2(" Isolated = %d Knockout = %d\n",
336 tgp.Isolated, tgp.Knockout);
337 }
338 #endif
339 if (dev_proc(pdev, begin_transparency_group) != 0)
340 return (*dev_proc(pdev, begin_transparency_group)) (pdev, &tgp,
341 &bbox, pis, NULL, NULL);
342 else
343 return 0;
344 }
345
346 int
gs_end_transparency_group(gs_state * pgs)347 gs_end_transparency_group(gs_state *pgs)
348 {
349 gs_pdf14trans_params_t params = { 0 };
350
351 if_debug0('v', "[v]gs_end_transparency_group\n");
352 params.pdf14_op = PDF14_END_TRANS_GROUP; /* Other parameters not used */
353 return gs_state_update_pdf14trans(pgs, ¶ms);
354 }
355
356 int
gx_end_transparency_group(gs_imager_state * pis,gx_device * pdev)357 gx_end_transparency_group(gs_imager_state * pis, gx_device * pdev)
358 {
359 if_debug0('v', "[v]gx_end_transparency_group\n");
360 if (dev_proc(pdev, end_transparency_group) != 0)
361 return (*dev_proc(pdev, end_transparency_group)) (pdev, pis, NULL);
362 else
363 return 0;
364 }
365
366
367 /* Commands for handling q softmask Q in graphic states */
368
369 int
gs_push_transparency_state(gs_state * pgs)370 gs_push_transparency_state(gs_state *pgs)
371 {
372 gs_pdf14trans_params_t params = { 0 };
373 gs_imager_state * pis = (gs_imager_state *)pgs;
374 int code;
375
376 /* Set the pending flag to true, which indicates
377 that we need to watch for end transparency
378 soft masks when we are at this graphic state
379 level */
380
381 /* pis->trans_flags.xstate_pending = true; */
382
383 /* Actually I believe the above flag is not
384 needed. We really should be watching for
385 the softmask even at the base level. What
386 we need to watch for are q operations after
387 a soft mask end has occured. */
388
389 /* Check if we have a change flag set to true.
390 this indicates that a softmask is present.
391 We will need to send a push state to save
392 the current soft mask, so that we can
393 restore it later */
394
395 if (pis->trans_flags.xstate_change) {
396
397 if_debug0('v', "[v]gs_push_transparency_state sending\n");
398 params.pdf14_op = PDF14_PUSH_TRANS_STATE;
399 code = gs_state_update_pdf14trans(pgs, ¶ms);
400 if (code < 0)
401 return(code);
402
403 } else {
404
405 if_debug0('v', "[v]gs_push_transparency_state NOT sending\n");
406
407 }
408
409
410 return(0);
411 }
412
413
414 int
gs_pop_transparency_state(gs_state * pgs)415 gs_pop_transparency_state(gs_state *pgs)
416 {
417 gs_pdf14trans_params_t params = { 0 };
418 gs_imager_state * pis = (gs_imager_state *)pgs;
419 int code;
420
421 /* Check if flag is set, which indicates that we have
422 an active softmask for the graphic state. We
423 need to communicate to the compositor to pop
424 the softmask */
425
426 if ( pis->trans_flags.xstate_change ) {
427
428 if_debug0('v', "[v]gs_pop_transparency_state sending\n");
429 params.pdf14_op = PDF14_POP_TRANS_STATE;
430 code = gs_state_update_pdf14trans(pgs, ¶ms);
431 if ( code < 0 )
432 return (code);
433
434 } else {
435
436 if_debug0('v', "[v]gs_pop_transparency_state NOT sending\n");
437
438 }
439
440 /* There is no reason to reset any of the flags since
441 they will be reset by the graphic state restore */
442
443 return(0);
444
445 }
446
447
448 int
gx_pop_transparency_state(gs_imager_state * pis,gx_device * pdev)449 gx_pop_transparency_state(gs_imager_state * pis, gx_device * pdev)
450 {
451 if_debug0('v', "[v]gx_pop_transparency_state\n");
452 if (dev_proc(pdev, pop_transparency_state) != 0)
453 return (*dev_proc(pdev, pop_transparency_state)) (pdev, pis);
454 else
455 return 0;
456 }
457
458 int
gx_push_transparency_state(gs_imager_state * pis,gx_device * pdev)459 gx_push_transparency_state(gs_imager_state * pis, gx_device * pdev)
460 {
461 if_debug0('v', "[v]gx_push_transparency_state\n");
462 if (dev_proc(pdev, push_transparency_state) != 0)
463 return (*dev_proc(pdev, push_transparency_state)) (pdev, pis);
464 else
465 return 0;
466 }
467
468
469
470 /*
471 * Handler for identity mask transfer functions.
472 */
473 static int
mask_transfer_identity(floatp in,float * out,void * proc_data)474 mask_transfer_identity(floatp in, float *out, void *proc_data)
475 {
476 *out = (float) in;
477 return 0;
478 }
479
480 void
gs_trans_mask_params_init(gs_transparency_mask_params_t * ptmp,gs_transparency_mask_subtype_t subtype)481 gs_trans_mask_params_init(gs_transparency_mask_params_t *ptmp,
482 gs_transparency_mask_subtype_t subtype)
483 {
484 ptmp->ColorSpace = 0;
485 ptmp->subtype = subtype;
486 ptmp->Background_components = 0;
487 ptmp->TransferFunction = mask_transfer_identity;
488 ptmp->TransferFunction_data = 0;
489 ptmp->replacing = false;
490 }
491
492 int
gs_begin_transparency_mask(gs_state * pgs,const gs_transparency_mask_params_t * ptmp,const gs_rect * pbbox,bool mask_is_image)493 gs_begin_transparency_mask(gs_state * pgs,
494 const gs_transparency_mask_params_t * ptmp,
495 const gs_rect * pbbox, bool mask_is_image)
496 {
497 gs_pdf14trans_params_t params = { 0 };
498 const int l = sizeof(params.Background[0]) * ptmp->Background_components;
499 int i;
500 const gs_color_space *blend_color_space;
501 gs_imager_state * pis = (gs_imager_state *)pgs;
502 int num_components;
503
504 params.pdf14_op = PDF14_BEGIN_TRANS_MASK;
505 params.bbox = *pbbox;
506 params.subtype = ptmp->subtype;
507 /* params.SMask_is_CIE = gs_color_space_is_CIE(pgs->color_space); */ /* See comments in gs_begin_transparency_mask */
508 params.SMask_is_CIE = false;
509 params.Background_components = ptmp->Background_components;
510 memcpy(params.Background, ptmp->Background, l);
511 params.GrayBackground = ptmp->GrayBackground;
512 params.transfer_function = ptmp->TransferFunction_data;
513 params.function_is_identity =
514 (ptmp->TransferFunction == mask_transfer_identity);
515 params.mask_is_image = mask_is_image;
516 params.replacing = ptmp->replacing;
517 /* Note that the SMask buffer may have a different
518 numcomps than the device buffer */
519 params.group_color_numcomps = cs_num_components(pgs->color_space);
520
521 if_debug9('v', "[v](0x%lx)gs_begin_transparency_mask [%g %g %g %g]\n\
522 subtype = %d Background_components = %d Num_grp_clr_comp = %d %s\n",
523 (ulong)pgs, pbbox->p.x, pbbox->p.y, pbbox->q.x, pbbox->q.y,
524 (int)ptmp->subtype, ptmp->Background_components,
525 params.group_color_numcomps,
526 (ptmp->TransferFunction == mask_transfer_identity ? "no TR" :
527 "has TR"));
528
529 /* Sample the transfer function */
530 for (i = 0; i < MASK_TRANSFER_FUNCTION_SIZE; i++) {
531 float in = (float)(i * (1.0 / (MASK_TRANSFER_FUNCTION_SIZE - 1)));
532 float out;
533
534 ptmp->TransferFunction(in, &out, ptmp->TransferFunction_data);
535 params.transfer_fn[i] = (byte)floor((double)(out * 255 + 0.5));
536 }
537
538 /* If we have a CIE space & a luminosity subtype
539 we will need to do our concretization
540 to CIEXYZ so that we can obtain the proper
541 luminance value. This is what SHOULD happen
542 according to the spec. However AR does not
543 follow this. It always seems to do the soft mask
544 creation in the device space. For this reason
545 we will do that too. SMask_is_CIE is always false for now */
546
547 /* The blending procs are currently based upon the device type.
548 We need to have them based upon the current color space */
549
550 /* Note: This function is called during the c-list writer side. */
551
552
553 if ( params.SMask_is_CIE && params.subtype == TRANSPARENCY_MASK_Luminosity ){
554
555 /* Install Color Space to go to CIEXYZ */
556
557 /* int ok;
558 ok = gx_cie_to_xyz_alloc2(pgs->color_space,pgs); */ /* quite compiler */
559 params.group_color_numcomps = 3; /* CIEXYZ */
560
561 /* Mark the proper spaces so that we make
562 * the appropriate changes in the device */
563
564 params.group_color = CIE_XYZ;
565
566 } else {
567
568 /* Set the group color type, which may be
569 * different than the device type. Note
570 we want to check the concrete space due
571 to the fact that things are done
572 in device space always. */
573
574
575 if(!gs_color_space_is_CIE(pgs->color_space)){
576
577 blend_color_space = pgs->color_space;
578
579 } else {
580
581 /* ICC or CIE based color space. Problem right now is that the
582 current code does a concretization to the color space
583 defined by the CRD. This is not the space that we want
584 to blend in. Instead we want all colors to be mapped TO
585 the ICC color space. Then when the group is popped they
586 should be converted to the parent space.
587 That I will need to fix another day with the color changes.
588 For now we will punt and set our blending space as the
589 concrete space for the ICC space, which is defined by
590 the output (or default) CRD. */
591
592 blend_color_space = cs_concrete_space(pgs->color_space, pis);
593
594 }
595
596 /* For the softmask blend color space, we will always use the above blend_color_space.
597 Problems can occur if we go all the way back to the device color space,
598 which could be DeviceN for a sep device. Blending to the luminosity
599 channel for this case would not be defined. */
600
601 num_components = cs_num_components(blend_color_space);
602 switch (abs(num_components)) {
603
604 case 1:
605 params.group_color = GRAY_SCALE;
606 params.group_color_numcomps = 1; /* Need to check */
607 break;
608 case 3:
609 params.group_color = DEVICE_RGB;
610 params.group_color_numcomps = 3;
611 break;
612 case 4:
613 params.group_color = DEVICE_CMYK;
614 params.group_color_numcomps = 4;
615 break;
616 default:
617 /* Transparency soft mask spot
618 colors are NEVER available.
619 We must use the alternate tint
620 transform */
621 return_error(gs_error_rangecheck);
622 break;
623
624 }
625
626 }
627
628 return gs_state_update_pdf14trans(pgs, ¶ms);
629 }
630
631 /* This occurs on the c-list reader side */
632
633 int
gx_begin_transparency_mask(gs_imager_state * pis,gx_device * pdev,const gs_pdf14trans_params_t * pparams)634 gx_begin_transparency_mask(gs_imager_state * pis, gx_device * pdev,
635 const gs_pdf14trans_params_t * pparams)
636 {
637 gx_transparency_mask_params_t tmp;
638 const int l = sizeof(pparams->Background[0]) * pparams->Background_components;
639
640 tmp.group_color = pparams->group_color;
641 tmp.subtype = pparams->subtype;
642 tmp.SMask_is_CIE = pparams->SMask_is_CIE;
643 tmp.group_color_numcomps = pparams->group_color_numcomps;
644 tmp.Background_components = pparams->Background_components;
645 memcpy(tmp.Background, pparams->Background, l);
646 tmp.GrayBackground = pparams->GrayBackground;
647 tmp.function_is_identity = pparams->function_is_identity;
648 tmp.idle = pparams->idle;
649 tmp.replacing = pparams->replacing;
650 tmp.mask_id = pparams->mask_id;
651 memcpy(tmp.transfer_fn, pparams->transfer_fn, size_of(tmp.transfer_fn));
652 if_debug9('v', "[v](0x%lx)gx_begin_transparency_mask [%g %g %g %g]\n\
653 subtype = %d Background_components = %d Num_grp_clr_comp = %d %s\n",
654 (ulong)pis, pparams->bbox.p.x, pparams->bbox.p.y,
655 pparams->bbox.q.x, pparams->bbox.q.y,
656 (int)tmp.subtype, tmp.Background_components,
657 tmp.group_color_numcomps,
658 (tmp.function_is_identity ? "no TR" :
659 "has TR"));
660 if (dev_proc(pdev, begin_transparency_mask) != 0)
661 return (*dev_proc(pdev, begin_transparency_mask))
662 (pdev, &tmp, &(pparams->bbox), pis, NULL, NULL);
663 else
664 return 0;
665 }
666
667 int
gs_end_transparency_mask(gs_state * pgs,gs_transparency_channel_selector_t csel)668 gs_end_transparency_mask(gs_state *pgs,
669 gs_transparency_channel_selector_t csel)
670 {
671 gs_pdf14trans_params_t params = { 0 };
672 gs_imager_state * pis = (gs_imager_state *)pgs;
673
674 /* If we have done a q then set a flag to watch for any Qs */
675
676 /* if (pis->trans_flags.xstate_pending)
677 pis->trans_flags.xstate_change = true; */
678
679 /* This should not depend upon if we have encountered a q
680 operation. We could be setting a softmask, before
681 there is any q operation. Unlikely but it could happen.
682 Then if we encouter a q operation (and this flag
683 is true) we will need to
684 push the mask graphic state (PDF14_PUSH_TRANS_STATE). */
685
686 pis->trans_flags.xstate_change = true;
687
688 if_debug1('v', "[v]xstate_changed set true, gstate level is %d\n", pgs->level);
689
690 if_debug2('v', "[v](0x%lx)gs_end_transparency_mask(%d)\n", (ulong)pgs,
691 (int)csel);
692
693 params.pdf14_op = PDF14_END_TRANS_MASK; /* Other parameters not used */
694 params.csel = csel;
695 return gs_state_update_pdf14trans(pgs, ¶ms);
696 }
697
698 int
gx_end_transparency_mask(gs_imager_state * pis,gx_device * pdev,const gs_pdf14trans_params_t * pparams)699 gx_end_transparency_mask(gs_imager_state * pis, gx_device * pdev,
700 const gs_pdf14trans_params_t * pparams)
701 {
702 if_debug2('v', "[v](0x%lx)gx_end_transparency_mask(%d)\n", (ulong)pis,
703 (int)pparams->csel);
704
705 if (dev_proc(pdev, end_transparency_mask) != 0)
706 return (*dev_proc(pdev, end_transparency_mask)) (pdev, pis, NULL);
707 else
708 return 0;
709 }
710
711 int
gs_discard_transparency_layer(gs_state * pgs)712 gs_discard_transparency_layer(gs_state *pgs)
713 {
714 /****** NYI, DUMMY ******/
715 gs_transparency_state_t *pts = pgs->transparency_stack;
716
717 if_debug1('v', "[v](0x%lx)gs_discard_transparency_layer\n", (ulong)pgs);
718 if (!pts)
719 return_error(gs_error_rangecheck);
720 pop_transparency_stack(pgs, "gs_discard_transparency_layer");
721 return 0;
722 }
723
724 /*
725 * We really only care about the number of spot colors when we have
726 * a device which supports spot colors. With the other devices we use
727 * the tint transform function for DeviceN and Separation color spaces
728 * and convert spot colors into process colors.
729 */
730 static int
get_num_pdf14_spot_colors(gs_state * pgs)731 get_num_pdf14_spot_colors(gs_state * pgs)
732 {
733 gx_device * dev = pgs->device;
734 gs_devn_params * pclist_devn_params = dev_proc(dev, ret_devn_params)(dev);
735
736 /*
737 * Devices which support spot colors store the PageSpotColors device
738 * parameter inside their devn_params structure. (This is done by the
739 * devn_put_params routine.) The PageSpotColors device parameter is
740 * set by pdf_main whenever a PDF page is being processed. See
741 * countspotcolors in lib/pdf_main.ps.
742 */
743 if (pclist_devn_params != NULL) {
744
745 /* If the sep order names were specified, then we should only allocate
746 for those. But only the nonstandard colorants that are stored
747 in num_separations. See devn_put_params for details on this.
748 Right now, the PDF14 device will always include CMYK. A future
749 optimization is to be able to NOT have those included in the buffer
750 allocations if we don't specify them. It would then be possible to
751 output 8 separations at a time without using compressed color. */
752
753 if (pclist_devn_params->num_separation_order_names == 0)
754 return pclist_devn_params->page_spot_colors;
755
756 return (pclist_devn_params->separations.num_separations);
757
758 }
759 return 0;
760 }
761
762 int
gs_push_pdf14trans_device(gs_state * pgs)763 gs_push_pdf14trans_device(gs_state * pgs)
764 {
765 gs_pdf14trans_params_t params = { 0 };
766
767 params.pdf14_op = PDF14_PUSH_DEVICE;
768 /*
769 * We really only care about the number of spot colors when we have
770 * a device which supports spot colors. With the other devices we use
771 * the tint transform function for DeviceN and Separation color spaces
772 * and convert spot colors into process colors.
773 */
774 params.num_spot_colors = get_num_pdf14_spot_colors(pgs);
775 /* Note: Other parameters not used */
776 return gs_state_update_pdf14trans(pgs, ¶ms);
777 }
778
779 int
gs_pop_pdf14trans_device(gs_state * pgs)780 gs_pop_pdf14trans_device(gs_state * pgs)
781 {
782 gs_pdf14trans_params_t params = { 0 };
783
784 params.pdf14_op = PDF14_POP_DEVICE; /* Other parameters not used */
785 return gs_state_update_pdf14trans(pgs, ¶ms);
786 }
787