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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
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, &params);
786 }
787