13ff48bf5SDavid du Colombier /* Copyright (C) 2000 Aladdin Enterprises. All rights reserved.
23ff48bf5SDavid du Colombier
3*593dc095SDavid du Colombier This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier implied.
53ff48bf5SDavid du Colombier
6*593dc095SDavid du Colombier This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier of the license contained in the file LICENSE in this distribution.
93ff48bf5SDavid du Colombier
10*593dc095SDavid du Colombier For more information about licensing, please refer to
11*593dc095SDavid du Colombier http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier San Rafael, CA 94903, U.S.A., +1(415)492-9861.
153ff48bf5SDavid du Colombier */
163ff48bf5SDavid du Colombier
17*593dc095SDavid du Colombier /* $Id: gstrans.c,v 1.25 2005/08/30 16:49:34 igor Exp $ */
183ff48bf5SDavid du Colombier /* Implementation of transparency, other than rendering */
19*593dc095SDavid du Colombier #include "math_.h"
20*593dc095SDavid du Colombier #include "memory_.h"
213ff48bf5SDavid du Colombier #include "gx.h"
223ff48bf5SDavid du Colombier #include "gserrors.h"
233ff48bf5SDavid du Colombier #include "gstrans.h"
243ff48bf5SDavid du Colombier #include "gsutil.h"
253ff48bf5SDavid du Colombier #include "gzstate.h"
263ff48bf5SDavid du Colombier #include "gxdevcli.h"
27*593dc095SDavid du Colombier #include "gdevp14.h"
28*593dc095SDavid du Colombier
29*593dc095SDavid du Colombier #define PUSH_TS 0
303ff48bf5SDavid du Colombier
313ff48bf5SDavid du Colombier /* ------ Transparency-related graphics state elements ------ */
323ff48bf5SDavid du Colombier
333ff48bf5SDavid du Colombier int
gs_setblendmode(gs_state * pgs,gs_blend_mode_t mode)343ff48bf5SDavid du Colombier gs_setblendmode(gs_state *pgs, gs_blend_mode_t mode)
353ff48bf5SDavid du Colombier {
363ff48bf5SDavid du Colombier #ifdef DEBUG
373ff48bf5SDavid du Colombier if (gs_debug_c('v')) {
383ff48bf5SDavid du Colombier static const char *const bm_names[] = { GS_BLEND_MODE_NAMES };
393ff48bf5SDavid du Colombier
403ff48bf5SDavid du Colombier dlprintf1("[v](0x%lx)blend_mode = ", (ulong)pgs);
413ff48bf5SDavid du Colombier if (mode >= 0 && mode < countof(bm_names))
423ff48bf5SDavid du Colombier dprintf1("%s\n", bm_names[mode]);
433ff48bf5SDavid du Colombier else
443ff48bf5SDavid du Colombier dprintf1("%d??\n", (int)mode);
453ff48bf5SDavid du Colombier }
463ff48bf5SDavid du Colombier #endif
473ff48bf5SDavid du Colombier if (mode < 0 || mode > MAX_BLEND_MODE)
483ff48bf5SDavid du Colombier return_error(gs_error_rangecheck);
493ff48bf5SDavid du Colombier pgs->blend_mode = mode;
503ff48bf5SDavid du Colombier return 0;
513ff48bf5SDavid du Colombier }
523ff48bf5SDavid du Colombier
533ff48bf5SDavid du Colombier gs_blend_mode_t
gs_currentblendmode(const gs_state * pgs)543ff48bf5SDavid du Colombier gs_currentblendmode(const gs_state *pgs)
553ff48bf5SDavid du Colombier {
563ff48bf5SDavid du Colombier return pgs->blend_mode;
573ff48bf5SDavid du Colombier }
583ff48bf5SDavid du Colombier
593ff48bf5SDavid du Colombier int
gs_setopacityalpha(gs_state * pgs,floatp alpha)603ff48bf5SDavid du Colombier gs_setopacityalpha(gs_state *pgs, floatp alpha)
613ff48bf5SDavid du Colombier {
623ff48bf5SDavid du Colombier if_debug2('v', "[v](0x%lx)opacity.alpha = %g\n", (ulong)pgs, alpha);
633ff48bf5SDavid du Colombier pgs->opacity.alpha = (alpha < 0.0 ? 0.0 : alpha > 1.0 ? 1.0 : alpha);
643ff48bf5SDavid du Colombier return 0;
653ff48bf5SDavid du Colombier }
663ff48bf5SDavid du Colombier
673ff48bf5SDavid du Colombier float
gs_currentopacityalpha(const gs_state * pgs)683ff48bf5SDavid du Colombier gs_currentopacityalpha(const gs_state *pgs)
693ff48bf5SDavid du Colombier {
703ff48bf5SDavid du Colombier return pgs->opacity.alpha;
713ff48bf5SDavid du Colombier }
723ff48bf5SDavid du Colombier
733ff48bf5SDavid du Colombier int
gs_setshapealpha(gs_state * pgs,floatp alpha)743ff48bf5SDavid du Colombier gs_setshapealpha(gs_state *pgs, floatp alpha)
753ff48bf5SDavid du Colombier {
763ff48bf5SDavid du Colombier if_debug2('v', "[v](0x%lx)shape.alpha = %g\n", (ulong)pgs, alpha);
773ff48bf5SDavid du Colombier pgs->shape.alpha = (alpha < 0.0 ? 0.0 : alpha > 1.0 ? 1.0 : alpha);
783ff48bf5SDavid du Colombier return 0;
793ff48bf5SDavid du Colombier }
803ff48bf5SDavid du Colombier
813ff48bf5SDavid du Colombier float
gs_currentshapealpha(const gs_state * pgs)823ff48bf5SDavid du Colombier gs_currentshapealpha(const gs_state *pgs)
833ff48bf5SDavid du Colombier {
843ff48bf5SDavid du Colombier return pgs->shape.alpha;
853ff48bf5SDavid du Colombier }
863ff48bf5SDavid du Colombier
873ff48bf5SDavid du Colombier int
gs_settextknockout(gs_state * pgs,bool knockout)883ff48bf5SDavid du Colombier gs_settextknockout(gs_state *pgs, bool knockout)
893ff48bf5SDavid du Colombier {
903ff48bf5SDavid du Colombier if_debug2('v', "[v](0x%lx)text_knockout = %s\n", (ulong)pgs,
913ff48bf5SDavid du Colombier (knockout ? "true" : "false"));
923ff48bf5SDavid du Colombier pgs->text_knockout = knockout;
933ff48bf5SDavid du Colombier return 0;
943ff48bf5SDavid du Colombier }
953ff48bf5SDavid du Colombier
963ff48bf5SDavid du Colombier bool
gs_currenttextknockout(const gs_state * pgs)973ff48bf5SDavid du Colombier gs_currenttextknockout(const gs_state *pgs)
983ff48bf5SDavid du Colombier {
993ff48bf5SDavid du Colombier return pgs->text_knockout;
1003ff48bf5SDavid du Colombier }
1013ff48bf5SDavid du Colombier
1023ff48bf5SDavid du Colombier /* ------ Transparency rendering stack ------ */
1033ff48bf5SDavid du Colombier
1043ff48bf5SDavid du Colombier gs_transparency_state_type_t
gs_current_transparency_type(const gs_state * pgs)1053ff48bf5SDavid du Colombier gs_current_transparency_type(const gs_state *pgs)
1063ff48bf5SDavid du Colombier {
1073ff48bf5SDavid du Colombier return (pgs->transparency_stack == 0 ? 0 :
1083ff48bf5SDavid du Colombier pgs->transparency_stack->type);
1093ff48bf5SDavid du Colombier }
1103ff48bf5SDavid du Colombier
1113ff48bf5SDavid du Colombier /* Support for dummy implementation */
1123ff48bf5SDavid du Colombier gs_private_st_ptrs1(st_transparency_state, gs_transparency_state_t,
1133ff48bf5SDavid du Colombier "gs_transparency_state_t", transparency_state_enum_ptrs,
1143ff48bf5SDavid du Colombier transparency_state_reloc_ptrs, saved);
115*593dc095SDavid du Colombier #if PUSH_TS
1163ff48bf5SDavid du Colombier private int
push_transparency_stack(gs_state * pgs,gs_transparency_state_type_t type,client_name_t cname)1173ff48bf5SDavid du Colombier push_transparency_stack(gs_state *pgs, gs_transparency_state_type_t type,
1183ff48bf5SDavid du Colombier client_name_t cname)
1193ff48bf5SDavid du Colombier {
1203ff48bf5SDavid du Colombier gs_transparency_state_t *pts =
1213ff48bf5SDavid du Colombier gs_alloc_struct(pgs->memory, gs_transparency_state_t,
1223ff48bf5SDavid du Colombier &st_transparency_state, cname);
1233ff48bf5SDavid du Colombier
1243ff48bf5SDavid du Colombier if (pts == 0)
1253ff48bf5SDavid du Colombier return_error(gs_error_VMerror);
1263ff48bf5SDavid du Colombier pts->saved = pgs->transparency_stack;
1273ff48bf5SDavid du Colombier pts->type = type;
1283ff48bf5SDavid du Colombier pgs->transparency_stack = pts;
1293ff48bf5SDavid du Colombier return 0;
1303ff48bf5SDavid du Colombier }
131*593dc095SDavid du Colombier #endif
1323ff48bf5SDavid du Colombier private void
pop_transparency_stack(gs_state * pgs,client_name_t cname)1333ff48bf5SDavid du Colombier pop_transparency_stack(gs_state *pgs, client_name_t cname)
1343ff48bf5SDavid du Colombier {
1353ff48bf5SDavid du Colombier gs_transparency_state_t *pts = pgs->transparency_stack; /* known non-0 */
1363ff48bf5SDavid du Colombier gs_transparency_state_t *saved = pts->saved;
1373ff48bf5SDavid du Colombier
1383ff48bf5SDavid du Colombier gs_free_object(pgs->memory, pts, cname);
1393ff48bf5SDavid du Colombier pgs->transparency_stack = saved;
1403ff48bf5SDavid du Colombier
1413ff48bf5SDavid du Colombier }
1423ff48bf5SDavid du Colombier
143*593dc095SDavid du Colombier /*
144*593dc095SDavid du Colombier * Push a PDF 1.4 transparency compositor onto the current device. Note that
145*593dc095SDavid du Colombier * if the current device already is a PDF 1.4 transparency compositor, the
146*593dc095SDavid du Colombier * create_compositor will update its parameters but not create a new
147*593dc095SDavid du Colombier * compositor device.
148*593dc095SDavid du Colombier */
149*593dc095SDavid du Colombier private int
gs_state_update_pdf14trans(gs_state * pgs,gs_pdf14trans_params_t * pparams)150*593dc095SDavid du Colombier gs_state_update_pdf14trans(gs_state * pgs, gs_pdf14trans_params_t * pparams)
151*593dc095SDavid du Colombier {
152*593dc095SDavid du Colombier gs_imager_state * pis = (gs_imager_state *)pgs;
153*593dc095SDavid du Colombier gx_device * dev = pgs->device;
154*593dc095SDavid du Colombier gx_device * pdf14dev;
155*593dc095SDavid du Colombier int code;
156*593dc095SDavid du Colombier
157*593dc095SDavid du Colombier /*
158*593dc095SDavid du Colombier * Send the PDF 1.4 create compositor action specified by the parameters.
159*593dc095SDavid du Colombier */
160*593dc095SDavid du Colombier code = send_pdf14trans(pis, dev, &pdf14dev, pparams, pgs->memory);
161*593dc095SDavid du Colombier /*
162*593dc095SDavid du Colombier * If we created a new PDF 1.4 compositor device then we need to install it
163*593dc095SDavid du Colombier * into the graphics state.
164*593dc095SDavid du Colombier */
165*593dc095SDavid du Colombier if (code >= 0 && pdf14dev != dev)
166*593dc095SDavid du Colombier gx_set_device_only(pgs, pdf14dev);
167*593dc095SDavid du Colombier
168*593dc095SDavid du Colombier return code;
169*593dc095SDavid du Colombier }
170*593dc095SDavid du Colombier
1713ff48bf5SDavid du Colombier void
gs_trans_group_params_init(gs_transparency_group_params_t * ptgp)1723ff48bf5SDavid du Colombier gs_trans_group_params_init(gs_transparency_group_params_t *ptgp)
1733ff48bf5SDavid du Colombier {
1743ff48bf5SDavid du Colombier ptgp->ColorSpace = 0; /* bogus, but can't do better */
1753ff48bf5SDavid du Colombier ptgp->Isolated = false;
1763ff48bf5SDavid du Colombier ptgp->Knockout = false;
1773ff48bf5SDavid du Colombier }
1783ff48bf5SDavid du Colombier
1793ff48bf5SDavid du Colombier int
gs_begin_transparency_group(gs_state * pgs,const gs_transparency_group_params_t * ptgp,const gs_rect * pbbox)1803ff48bf5SDavid du Colombier gs_begin_transparency_group(gs_state *pgs,
1813ff48bf5SDavid du Colombier const gs_transparency_group_params_t *ptgp,
1823ff48bf5SDavid du Colombier const gs_rect *pbbox)
1833ff48bf5SDavid du Colombier {
184*593dc095SDavid du Colombier gs_pdf14trans_params_t params = { 0 };
185*593dc095SDavid du Colombier
1863ff48bf5SDavid du Colombier #ifdef DEBUG
1873ff48bf5SDavid du Colombier if (gs_debug_c('v')) {
1883ff48bf5SDavid du Colombier static const char *const cs_names[] = {
1893ff48bf5SDavid du Colombier GS_COLOR_SPACE_TYPE_NAMES
1903ff48bf5SDavid du Colombier };
1913ff48bf5SDavid du Colombier
1923ff48bf5SDavid du Colombier dlprintf5("[v](0x%lx)begin_transparency_group [%g %g %g %g]\n",
1933ff48bf5SDavid du Colombier (ulong)pgs, pbbox->p.x, pbbox->p.y, pbbox->q.x, pbbox->q.y);
1943ff48bf5SDavid du Colombier if (ptgp->ColorSpace)
1953ff48bf5SDavid du Colombier dprintf1(" CS = %s",
1963ff48bf5SDavid du Colombier cs_names[(int)gs_color_space_get_index(ptgp->ColorSpace)]);
1973ff48bf5SDavid du Colombier else
1983ff48bf5SDavid du Colombier dputs(" (no CS)");
1993ff48bf5SDavid du Colombier dprintf2(" Isolated = %d Knockout = %d\n",
2003ff48bf5SDavid du Colombier ptgp->Isolated, ptgp->Knockout);
2013ff48bf5SDavid du Colombier }
2023ff48bf5SDavid du Colombier #endif
203*593dc095SDavid du Colombier /*
204*593dc095SDavid du Colombier * Put parameters into a compositor parameter and then call the
205*593dc095SDavid du Colombier * create_compositor. This will pass the data to the PDF 1.4
206*593dc095SDavid du Colombier * transparency device.
207*593dc095SDavid du Colombier */
208*593dc095SDavid du Colombier params.pdf14_op = PDF14_BEGIN_TRANS_GROUP;
209*593dc095SDavid du Colombier params.Isolated = ptgp->Isolated;
210*593dc095SDavid du Colombier params.Knockout = ptgp->Knockout;
211*593dc095SDavid du Colombier params.opacity = pgs->opacity;
212*593dc095SDavid du Colombier params.shape = pgs->shape;
213*593dc095SDavid du Colombier params.blend_mode = pgs->blend_mode;
214*593dc095SDavid du Colombier /*
215*593dc095SDavid du Colombier * We are currently doing nothing with the colorspace. Currently
216*593dc095SDavid du Colombier * the blending colorspace is based upon the processs color model
217*593dc095SDavid du Colombier * of the output device.
218*593dc095SDavid du Colombier */
219*593dc095SDavid du Colombier params.bbox = *pbbox;
220*593dc095SDavid du Colombier return gs_state_update_pdf14trans(pgs, ¶ms);
221*593dc095SDavid du Colombier }
222*593dc095SDavid du Colombier
223*593dc095SDavid du Colombier int
gx_begin_transparency_group(gs_imager_state * pis,gx_device * pdev,const gs_pdf14trans_params_t * pparams)224*593dc095SDavid du Colombier gx_begin_transparency_group(gs_imager_state * pis, gx_device * pdev,
225*593dc095SDavid du Colombier const gs_pdf14trans_params_t * pparams)
226*593dc095SDavid du Colombier {
227*593dc095SDavid du Colombier gs_transparency_group_params_t tgp = {0};
228*593dc095SDavid du Colombier gs_rect bbox;
229*593dc095SDavid du Colombier
230*593dc095SDavid du Colombier if (pparams->Background_components != 0 &&
231*593dc095SDavid du Colombier pparams->Background_components != pdev->color_info.num_components)
232*593dc095SDavid du Colombier return_error(gs_error_rangecheck);
233*593dc095SDavid du Colombier tgp.Isolated = pparams->Isolated;
234*593dc095SDavid du Colombier tgp.Knockout = pparams->Knockout;
235*593dc095SDavid du Colombier pis->opacity.alpha = pparams->opacity.alpha;
236*593dc095SDavid du Colombier pis->shape.alpha = pparams->shape.alpha;
237*593dc095SDavid du Colombier pis->blend_mode = pparams->blend_mode;
238*593dc095SDavid du Colombier bbox = pparams->bbox;
239*593dc095SDavid du Colombier #ifdef DEBUG
240*593dc095SDavid du Colombier if (gs_debug_c('v')) {
241*593dc095SDavid du Colombier static const char *const cs_names[] = {
242*593dc095SDavid du Colombier GS_COLOR_SPACE_TYPE_NAMES
243*593dc095SDavid du Colombier };
244*593dc095SDavid du Colombier
245*593dc095SDavid du Colombier dlprintf5("[v](0x%lx)begin_transparency_group [%g %g %g %g]\n",
246*593dc095SDavid du Colombier (ulong)pis, bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y);
247*593dc095SDavid du Colombier if (tgp.ColorSpace)
248*593dc095SDavid du Colombier dprintf1(" CS = %s",
249*593dc095SDavid du Colombier cs_names[(int)gs_color_space_get_index(tgp.ColorSpace)]);
250*593dc095SDavid du Colombier else
251*593dc095SDavid du Colombier dputs(" (no CS)");
252*593dc095SDavid du Colombier dprintf2(" Isolated = %d Knockout = %d\n",
253*593dc095SDavid du Colombier tgp.Isolated, tgp.Knockout);
254*593dc095SDavid du Colombier }
2553ff48bf5SDavid du Colombier #endif
256*593dc095SDavid du Colombier if (dev_proc(pdev, begin_transparency_group) != 0)
257*593dc095SDavid du Colombier return (*dev_proc(pdev, begin_transparency_group)) (pdev, &tgp,
258*593dc095SDavid du Colombier &bbox, pis, NULL, NULL);
259*593dc095SDavid du Colombier else
260*593dc095SDavid du Colombier return 0;
2613ff48bf5SDavid du Colombier }
2623ff48bf5SDavid du Colombier
2633ff48bf5SDavid du Colombier int
gs_end_transparency_group(gs_state * pgs)2643ff48bf5SDavid du Colombier gs_end_transparency_group(gs_state *pgs)
2653ff48bf5SDavid du Colombier {
266*593dc095SDavid du Colombier gs_pdf14trans_params_t params = { 0 };
2673ff48bf5SDavid du Colombier
268*593dc095SDavid du Colombier params.pdf14_op = PDF14_END_TRANS_GROUP; /* Other parameters not used */
269*593dc095SDavid du Colombier return gs_state_update_pdf14trans(pgs, ¶ms);
2703ff48bf5SDavid du Colombier }
2713ff48bf5SDavid du Colombier
272*593dc095SDavid du Colombier int
gx_end_transparency_group(gs_imager_state * pis,gx_device * pdev)273*593dc095SDavid du Colombier gx_end_transparency_group(gs_imager_state * pis, gx_device * pdev)
274*593dc095SDavid du Colombier {
275*593dc095SDavid du Colombier if (dev_proc(pdev, end_transparency_group) != 0)
276*593dc095SDavid du Colombier return (*dev_proc(pdev, end_transparency_group)) (pdev, pis, NULL);
277*593dc095SDavid du Colombier else
278*593dc095SDavid du Colombier return 0;
279*593dc095SDavid du Colombier }
280*593dc095SDavid du Colombier
281*593dc095SDavid du Colombier /*
282*593dc095SDavid du Colombier * Handler for identity mask transfer functions.
283*593dc095SDavid du Colombier */
2843ff48bf5SDavid du Colombier private int
mask_transfer_identity(floatp in,float * out,void * proc_data)2853ff48bf5SDavid du Colombier mask_transfer_identity(floatp in, float *out, void *proc_data)
2863ff48bf5SDavid du Colombier {
287*593dc095SDavid du Colombier *out = (float) in;
2883ff48bf5SDavid du Colombier return 0;
2893ff48bf5SDavid du Colombier }
290*593dc095SDavid du Colombier
2913ff48bf5SDavid du Colombier void
gs_trans_mask_params_init(gs_transparency_mask_params_t * ptmp,gs_transparency_mask_subtype_t subtype)2923ff48bf5SDavid du Colombier gs_trans_mask_params_init(gs_transparency_mask_params_t *ptmp,
2933ff48bf5SDavid du Colombier gs_transparency_mask_subtype_t subtype)
2943ff48bf5SDavid du Colombier {
2953ff48bf5SDavid du Colombier ptmp->subtype = subtype;
296*593dc095SDavid du Colombier ptmp->Background_components = 0;
2973ff48bf5SDavid du Colombier ptmp->TransferFunction = mask_transfer_identity;
2983ff48bf5SDavid du Colombier ptmp->TransferFunction_data = 0;
2993ff48bf5SDavid du Colombier }
3003ff48bf5SDavid du Colombier
3013ff48bf5SDavid du Colombier int
gs_begin_transparency_mask(gs_state * pgs,const gs_transparency_mask_params_t * ptmp,const gs_rect * pbbox,bool mask_is_image)3023ff48bf5SDavid du Colombier gs_begin_transparency_mask(gs_state * pgs,
3033ff48bf5SDavid du Colombier const gs_transparency_mask_params_t * ptmp,
304*593dc095SDavid du Colombier const gs_rect * pbbox, bool mask_is_image)
3053ff48bf5SDavid du Colombier {
306*593dc095SDavid du Colombier gs_pdf14trans_params_t params = { 0 };
307*593dc095SDavid du Colombier const int l = sizeof(params.Background[0]) * ptmp->Background_components;
308*593dc095SDavid du Colombier int i;
309*593dc095SDavid du Colombier
3103ff48bf5SDavid du Colombier if_debug8('v', "[v](0x%lx)begin_transparency_mask [%g %g %g %g]\n\
311*593dc095SDavid du Colombier subtype = %d Background_components = %d %s\n",
3123ff48bf5SDavid du Colombier (ulong)pgs, pbbox->p.x, pbbox->p.y, pbbox->q.x, pbbox->q.y,
313*593dc095SDavid du Colombier (int)ptmp->subtype, ptmp->Background_components,
3143ff48bf5SDavid du Colombier (ptmp->TransferFunction == mask_transfer_identity ? "no TR" :
3153ff48bf5SDavid du Colombier "has TR"));
316*593dc095SDavid du Colombier params.pdf14_op = PDF14_BEGIN_TRANS_MASK;
317*593dc095SDavid du Colombier params.bbox = *pbbox;
318*593dc095SDavid du Colombier params.subtype = ptmp->subtype;
319*593dc095SDavid du Colombier params.Background_components = ptmp->Background_components;
320*593dc095SDavid du Colombier memcpy(params.Background, ptmp->Background, l);
321*593dc095SDavid du Colombier params.GrayBackground = ptmp->GrayBackground;
322*593dc095SDavid du Colombier params.transfer_function = ptmp->TransferFunction_data;
323*593dc095SDavid du Colombier params.function_is_identity =
324*593dc095SDavid du Colombier (ptmp->TransferFunction == mask_transfer_identity);
325*593dc095SDavid du Colombier params.mask_is_image = mask_is_image;
326*593dc095SDavid du Colombier /* Sample the transfer function */
327*593dc095SDavid du Colombier for (i = 0; i < MASK_TRANSFER_FUNCTION_SIZE; i++) {
328*593dc095SDavid du Colombier float in = (float)(i * (1.0 / (MASK_TRANSFER_FUNCTION_SIZE - 1)));
329*593dc095SDavid du Colombier float out;
330*593dc095SDavid du Colombier
331*593dc095SDavid du Colombier ptmp->TransferFunction(in, &out, ptmp->TransferFunction_data);
332*593dc095SDavid du Colombier params.transfer_fn[i] = (byte)floor((double)(out * 255 + 0.5));
333*593dc095SDavid du Colombier }
334*593dc095SDavid du Colombier return gs_state_update_pdf14trans(pgs, ¶ms);
335*593dc095SDavid du Colombier }
336*593dc095SDavid du Colombier
337*593dc095SDavid du Colombier int
gx_begin_transparency_mask(gs_imager_state * pis,gx_device * pdev,const gs_pdf14trans_params_t * pparams)338*593dc095SDavid du Colombier gx_begin_transparency_mask(gs_imager_state * pis, gx_device * pdev,
339*593dc095SDavid du Colombier const gs_pdf14trans_params_t * pparams)
340*593dc095SDavid du Colombier {
341*593dc095SDavid du Colombier gx_transparency_mask_params_t tmp;
342*593dc095SDavid du Colombier const int l = sizeof(pparams->Background[0]) * pparams->Background_components;
343*593dc095SDavid du Colombier
344*593dc095SDavid du Colombier tmp.subtype = pparams->subtype;
345*593dc095SDavid du Colombier tmp.Background_components = pparams->Background_components;
346*593dc095SDavid du Colombier memcpy(tmp.Background, pparams->Background, l);
347*593dc095SDavid du Colombier tmp.GrayBackground = pparams->GrayBackground;
348*593dc095SDavid du Colombier tmp.function_is_identity = pparams->function_is_identity;
349*593dc095SDavid du Colombier memcpy(tmp.transfer_fn, pparams->transfer_fn, size_of(tmp.transfer_fn));
350*593dc095SDavid du Colombier if_debug8('v', "[v](0x%lx)begin_transparency_mask [%g %g %g %g]\n\
351*593dc095SDavid du Colombier subtype = %d Background_components = %d %s\n",
352*593dc095SDavid du Colombier (ulong)pis, pparams->bbox.p.x, pparams->bbox.p.y,
353*593dc095SDavid du Colombier pparams->bbox.q.x, pparams->bbox.q.y,
354*593dc095SDavid du Colombier (int)tmp.subtype, tmp.Background_components,
355*593dc095SDavid du Colombier (tmp.function_is_identity ? "no TR" :
356*593dc095SDavid du Colombier "has TR"));
357*593dc095SDavid du Colombier if (dev_proc(pdev, begin_transparency_mask) != 0)
358*593dc095SDavid du Colombier return (*dev_proc(pdev, begin_transparency_mask))
359*593dc095SDavid du Colombier (pdev, &tmp, &(pparams->bbox), pis, NULL, NULL);
360*593dc095SDavid du Colombier else
361*593dc095SDavid du Colombier return 0;
3623ff48bf5SDavid du Colombier }
3633ff48bf5SDavid du Colombier
3643ff48bf5SDavid du Colombier int
gs_end_transparency_mask(gs_state * pgs,gs_transparency_channel_selector_t csel)3653ff48bf5SDavid du Colombier gs_end_transparency_mask(gs_state *pgs,
3663ff48bf5SDavid du Colombier gs_transparency_channel_selector_t csel)
3673ff48bf5SDavid du Colombier {
368*593dc095SDavid du Colombier gs_pdf14trans_params_t params = { 0 };
3693ff48bf5SDavid du Colombier
3703ff48bf5SDavid du Colombier if_debug2('v', "[v](0x%lx)end_transparency_mask(%d)\n", (ulong)pgs,
3713ff48bf5SDavid du Colombier (int)csel);
372*593dc095SDavid du Colombier
373*593dc095SDavid du Colombier params.pdf14_op = PDF14_END_TRANS_MASK; /* Other parameters not used */
374*593dc095SDavid du Colombier params.csel = csel;
375*593dc095SDavid du Colombier return gs_state_update_pdf14trans(pgs, ¶ms);
376*593dc095SDavid du Colombier }
377*593dc095SDavid du Colombier
378*593dc095SDavid du Colombier int
gx_end_transparency_mask(gs_imager_state * pis,gx_device * pdev,const gs_pdf14trans_params_t * pparams)379*593dc095SDavid du Colombier gx_end_transparency_mask(gs_imager_state * pis, gx_device * pdev,
380*593dc095SDavid du Colombier const gs_pdf14trans_params_t * pparams)
381*593dc095SDavid du Colombier {
382*593dc095SDavid du Colombier if (dev_proc(pdev, end_transparency_mask) != 0)
383*593dc095SDavid du Colombier return (*dev_proc(pdev, end_transparency_mask)) (pdev, NULL);
384*593dc095SDavid du Colombier else
3853ff48bf5SDavid du Colombier return 0;
3863ff48bf5SDavid du Colombier }
3873ff48bf5SDavid du Colombier
3883ff48bf5SDavid du Colombier int
gs_discard_transparency_layer(gs_state * pgs)3893ff48bf5SDavid du Colombier gs_discard_transparency_layer(gs_state *pgs)
3903ff48bf5SDavid du Colombier {
3913ff48bf5SDavid du Colombier /****** NYI, DUMMY ******/
3923ff48bf5SDavid du Colombier gs_transparency_state_t *pts = pgs->transparency_stack;
3933ff48bf5SDavid du Colombier
3943ff48bf5SDavid du Colombier if_debug1('v', "[v](0x%lx)discard_transparency_layer\n", (ulong)pgs);
3953ff48bf5SDavid du Colombier if (!pts)
3963ff48bf5SDavid du Colombier return_error(gs_error_rangecheck);
3973ff48bf5SDavid du Colombier pop_transparency_stack(pgs, "gs_discard_transparency_layer");
3983ff48bf5SDavid du Colombier return 0;
3993ff48bf5SDavid du Colombier }
4003ff48bf5SDavid du Colombier
4013ff48bf5SDavid du Colombier int
gs_init_transparency_mask(gs_state * pgs,gs_transparency_channel_selector_t csel)4023ff48bf5SDavid du Colombier gs_init_transparency_mask(gs_state *pgs,
4033ff48bf5SDavid du Colombier gs_transparency_channel_selector_t csel)
4043ff48bf5SDavid du Colombier {
405*593dc095SDavid du Colombier gs_pdf14trans_params_t params = { 0 };
4063ff48bf5SDavid du Colombier
4073ff48bf5SDavid du Colombier if_debug2('v', "[v](0x%lx)init_transparency_mask(%d)\n", (ulong)pgs,
4083ff48bf5SDavid du Colombier (int)csel);
409*593dc095SDavid du Colombier
410*593dc095SDavid du Colombier params.pdf14_op = PDF14_INIT_TRANS_MASK;
411*593dc095SDavid du Colombier params.csel = csel;
412*593dc095SDavid du Colombier return gs_state_update_pdf14trans(pgs, ¶ms);
413*593dc095SDavid du Colombier }
414*593dc095SDavid du Colombier
415*593dc095SDavid du Colombier int
gx_init_transparency_mask(gs_imager_state * pis,const gs_pdf14trans_params_t * pparams)416*593dc095SDavid du Colombier gx_init_transparency_mask(gs_imager_state * pis,
417*593dc095SDavid du Colombier const gs_pdf14trans_params_t * pparams)
418*593dc095SDavid du Colombier {
419*593dc095SDavid du Colombier gs_transparency_source_t *ptm;
420*593dc095SDavid du Colombier
421*593dc095SDavid du Colombier if_debug2('v', "[v](0x%lx)init_transparency_mask(%d)\n", (ulong)pis,
422*593dc095SDavid du Colombier (int)pparams->csel);
423*593dc095SDavid du Colombier switch (pparams->csel) {
424*593dc095SDavid du Colombier case TRANSPARENCY_CHANNEL_Opacity: ptm = &pis->opacity; break;
425*593dc095SDavid du Colombier case TRANSPARENCY_CHANNEL_Shape: ptm = &pis->shape; break;
4263ff48bf5SDavid du Colombier default: return_error(gs_error_rangecheck);
4273ff48bf5SDavid du Colombier }
4283ff48bf5SDavid du Colombier rc_decrement_only(ptm->mask, "gs_init_transparency_mask");
4293ff48bf5SDavid du Colombier ptm->mask = 0;
4303ff48bf5SDavid du Colombier return 0;
4313ff48bf5SDavid du Colombier }
432*593dc095SDavid du Colombier
433*593dc095SDavid du Colombier int
gs_push_pdf14trans_device(gs_state * pgs)434*593dc095SDavid du Colombier gs_push_pdf14trans_device(gs_state * pgs)
435*593dc095SDavid du Colombier {
436*593dc095SDavid du Colombier gs_pdf14trans_params_t params = { 0 };
437*593dc095SDavid du Colombier
438*593dc095SDavid du Colombier params.pdf14_op = PDF14_PUSH_DEVICE; /* Other parameters not used */
439*593dc095SDavid du Colombier return gs_state_update_pdf14trans(pgs, ¶ms);
440*593dc095SDavid du Colombier }
441*593dc095SDavid du Colombier
442*593dc095SDavid du Colombier int
gs_pop_pdf14trans_device(gs_state * pgs)443*593dc095SDavid du Colombier gs_pop_pdf14trans_device(gs_state * pgs)
444*593dc095SDavid du Colombier {
445*593dc095SDavid du Colombier gs_pdf14trans_params_t params = { 0 };
446*593dc095SDavid du Colombier
447*593dc095SDavid du Colombier params.pdf14_op = PDF14_POP_DEVICE; /* Other parameters not used */
448*593dc095SDavid du Colombier return gs_state_update_pdf14trans(pgs, ¶ms);
449*593dc095SDavid du Colombier }
450