Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 2000 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: gstrans.c,v 1.25 2005/08/30 16:49:34 igor Exp $ */
18
/* Implementation of transparency, other than rendering */
19
#include "math_.h"
20
#include "memory_.h"
21
#include "gx.h"
22
#include "gserrors.h"
23
#include "gstrans.h"
24
#include "gsutil.h"
25
#include "gzstate.h"
26
#include "gxdevcli.h"
27
#include "gdevp14.h"
28
 
29
#define PUSH_TS 0
30
 
31
/* ------ Transparency-related graphics state elements ------ */
32
 
33
int
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
54
gs_currentblendmode(const gs_state *pgs)
55
{
56
    return pgs->blend_mode;
57
}
58
 
59
int
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
68
gs_currentopacityalpha(const gs_state *pgs)
69
{
70
    return pgs->opacity.alpha;
71
}
72
 
73
int
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
82
gs_currentshapealpha(const gs_state *pgs)
83
{
84
    return pgs->shape.alpha;
85
}
86
 
87
int
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
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
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
private int
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
private void
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
private int
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;
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
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
}
178
 
179
int
180
gs_begin_transparency_group(gs_state *pgs,
181
			    const gs_transparency_group_params_t *ptgp,
182
			    const gs_rect *pbbox)
183
{
184
    gs_pdf14trans_params_t params = { 0 };
185
 
186
#ifdef DEBUG
187
    if (gs_debug_c('v')) {
188
	static const char *const cs_names[] = {
189
	    GS_COLOR_SPACE_TYPE_NAMES
190
	};
191
 
192
	dlprintf5("[v](0x%lx)begin_transparency_group [%g %g %g %g]\n",
193
		  (ulong)pgs, pbbox->p.x, pbbox->p.y, pbbox->q.x, pbbox->q.y);
194
	if (ptgp->ColorSpace)
195
	    dprintf1("     CS = %s",
196
		cs_names[(int)gs_color_space_get_index(ptgp->ColorSpace)]);
197
	else
198
	    dputs("     (no CS)");
199
	dprintf2("  Isolated = %d  Knockout = %d\n",
200
		 ptgp->Isolated, ptgp->Knockout);
201
    }
202
#endif
203
    /*
204
     * Put parameters into a compositor parameter and then call the
205
     * create_compositor.  This will pass the data to the PDF 1.4
206
     * transparency device.
207
     */
208
    params.pdf14_op = PDF14_BEGIN_TRANS_GROUP;
209
    params.Isolated = ptgp->Isolated;
210
    params.Knockout = ptgp->Knockout;
211
    params.opacity = pgs->opacity;
212
    params.shape = pgs->shape;
213
    params.blend_mode = pgs->blend_mode;
214
    /*
215
     * We are currently doing nothing with the colorspace.  Currently
216
     * the blending colorspace is based upon the processs color model
217
     * of the output device.
218
     */
219
    params.bbox = *pbbox;
220
    return gs_state_update_pdf14trans(pgs, &params);
221
}
222
 
223
int
224
gx_begin_transparency_group(gs_imager_state * pis, gx_device * pdev,
225
				const gs_pdf14trans_params_t * pparams)
226
{
227
    gs_transparency_group_params_t tgp = {0};
228
    gs_rect bbox;
229
 
230
    if (pparams->Background_components != 0 && 
231
	pparams->Background_components != pdev->color_info.num_components)
232
	return_error(gs_error_rangecheck);
233
    tgp.Isolated = pparams->Isolated;
234
    tgp.Knockout = pparams->Knockout;
235
    pis->opacity.alpha = pparams->opacity.alpha;
236
    pis->shape.alpha = pparams->shape.alpha;
237
    pis->blend_mode = pparams->blend_mode;
238
    bbox = pparams->bbox;
239
#ifdef DEBUG
240
    if (gs_debug_c('v')) {
241
	static const char *const cs_names[] = {
242
	    GS_COLOR_SPACE_TYPE_NAMES
243
	};
244
 
245
	dlprintf5("[v](0x%lx)begin_transparency_group [%g %g %g %g]\n",
246
		  (ulong)pis, bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y);
247
	if (tgp.ColorSpace)
248
	    dprintf1("     CS = %s",
249
		cs_names[(int)gs_color_space_get_index(tgp.ColorSpace)]);
250
	else
251
	    dputs("     (no CS)");
252
	dprintf2("  Isolated = %d  Knockout = %d\n",
253
		 tgp.Isolated, tgp.Knockout);
254
    }
255
#endif
256
    if (dev_proc(pdev, begin_transparency_group) != 0)
257
	return (*dev_proc(pdev, begin_transparency_group)) (pdev, &tgp,
258
							&bbox, pis, NULL, NULL);
259
    else
260
	return 0;
261
}
262
 
263
int
264
gs_end_transparency_group(gs_state *pgs)
265
{
266
    gs_pdf14trans_params_t params = { 0 };
267
 
268
    params.pdf14_op = PDF14_END_TRANS_GROUP;  /* Other parameters not used */
269
    return gs_state_update_pdf14trans(pgs, &params);
270
}
271
 
272
int
273
gx_end_transparency_group(gs_imager_state * pis, gx_device * pdev)
274
{
275
    if (dev_proc(pdev, end_transparency_group) != 0)
276
	return (*dev_proc(pdev, end_transparency_group)) (pdev, pis, NULL);
277
    else
278
	return 0;
279
}
280
 
281
/*
282
 * Handler for identity mask transfer functions.
283
 */
284
private int
285
mask_transfer_identity(floatp in, float *out, void *proc_data)
286
{
287
    *out = (float) in;
288
    return 0;
289
}
290
 
291
void
292
gs_trans_mask_params_init(gs_transparency_mask_params_t *ptmp,
293
			  gs_transparency_mask_subtype_t subtype)
294
{
295
    ptmp->subtype = subtype;
296
    ptmp->Background_components = 0;
297
    ptmp->TransferFunction = mask_transfer_identity;
298
    ptmp->TransferFunction_data = 0;
299
}
300
 
301
int
302
gs_begin_transparency_mask(gs_state * pgs,
303
			   const gs_transparency_mask_params_t * ptmp,
304
			   const gs_rect * pbbox, bool mask_is_image)
305
{
306
    gs_pdf14trans_params_t params = { 0 };
307
    const int l = sizeof(params.Background[0]) * ptmp->Background_components;
308
    int i;
309
 
310
    if_debug8('v', "[v](0x%lx)begin_transparency_mask [%g %g %g %g]\n\
311
      subtype = %d  Background_components = %d  %s\n",
312
	      (ulong)pgs, pbbox->p.x, pbbox->p.y, pbbox->q.x, pbbox->q.y,
313
	      (int)ptmp->subtype, ptmp->Background_components,
314
	      (ptmp->TransferFunction == mask_transfer_identity ? "no TR" :
315
	       "has TR"));
316
    params.pdf14_op = PDF14_BEGIN_TRANS_MASK;
317
    params.bbox = *pbbox;
318
    params.subtype = ptmp->subtype;
319
    params.Background_components = ptmp->Background_components;
320
    memcpy(params.Background, ptmp->Background, l);
321
    params.GrayBackground = ptmp->GrayBackground;
322
    params.transfer_function = ptmp->TransferFunction_data;
323
    params.function_is_identity =
324
	    (ptmp->TransferFunction == mask_transfer_identity);
325
    params.mask_is_image = mask_is_image;
326
    /* Sample the transfer function */
327
    for (i = 0; i < MASK_TRANSFER_FUNCTION_SIZE; i++) {
328
	float in = (float)(i * (1.0 / (MASK_TRANSFER_FUNCTION_SIZE - 1)));
329
	float out;
330
 
331
	ptmp->TransferFunction(in, &out, ptmp->TransferFunction_data);
332
	params.transfer_fn[i] = (byte)floor((double)(out * 255 + 0.5));
333
    }
334
    return gs_state_update_pdf14trans(pgs, &params);
335
}
336
 
337
int
338
gx_begin_transparency_mask(gs_imager_state * pis, gx_device * pdev,
339
				const gs_pdf14trans_params_t * pparams)
340
{
341
    gx_transparency_mask_params_t tmp;
342
    const int l = sizeof(pparams->Background[0]) * pparams->Background_components;
343
 
344
    tmp.subtype = pparams->subtype;
345
    tmp.Background_components = pparams->Background_components;
346
    memcpy(tmp.Background, pparams->Background, l);
347
    tmp.GrayBackground = pparams->GrayBackground;
348
    tmp.function_is_identity = pparams->function_is_identity;
349
    memcpy(tmp.transfer_fn, pparams->transfer_fn, size_of(tmp.transfer_fn));
350
    if_debug8('v', "[v](0x%lx)begin_transparency_mask [%g %g %g %g]\n\
351
      subtype = %d  Background_components = %d  %s\n",
352
	      (ulong)pis, pparams->bbox.p.x, pparams->bbox.p.y,
353
	      pparams->bbox.q.x, pparams->bbox.q.y,
354
	      (int)tmp.subtype, tmp.Background_components,
355
	      (tmp.function_is_identity ? "no TR" :
356
	       "has TR"));
357
    if (dev_proc(pdev, begin_transparency_mask) != 0)
358
	return (*dev_proc(pdev, begin_transparency_mask))
359
	    		(pdev, &tmp, &(pparams->bbox), pis, NULL, NULL);
360
    else
361
	return 0;
362
}
363
 
364
int
365
gs_end_transparency_mask(gs_state *pgs,
366
			 gs_transparency_channel_selector_t csel)
367
{
368
    gs_pdf14trans_params_t params = { 0 };
369
 
370
    if_debug2('v', "[v](0x%lx)end_transparency_mask(%d)\n", (ulong)pgs,
371
	      (int)csel);
372
 
373
    params.pdf14_op = PDF14_END_TRANS_MASK;  /* Other parameters not used */
374
    params.csel = csel;
375
    return gs_state_update_pdf14trans(pgs, &params);
376
}
377
 
378
int
379
gx_end_transparency_mask(gs_imager_state * pis, gx_device * pdev,
380
				const gs_pdf14trans_params_t * pparams)
381
{
382
    if (dev_proc(pdev, end_transparency_mask) != 0)
383
	return (*dev_proc(pdev, end_transparency_mask)) (pdev, NULL);
384
    else
385
	return 0;
386
}
387
 
388
int
389
gs_discard_transparency_layer(gs_state *pgs)
390
{
391
    /****** NYI, DUMMY ******/
392
    gs_transparency_state_t *pts = pgs->transparency_stack;
393
 
394
    if_debug1('v', "[v](0x%lx)discard_transparency_layer\n", (ulong)pgs);
395
    if (!pts)
396
	return_error(gs_error_rangecheck);
397
    pop_transparency_stack(pgs, "gs_discard_transparency_layer");
398
    return 0;
399
}
400
 
401
int
402
gs_init_transparency_mask(gs_state *pgs,
403
			  gs_transparency_channel_selector_t csel)
404
{
405
    gs_pdf14trans_params_t params = { 0 };
406
 
407
    if_debug2('v', "[v](0x%lx)init_transparency_mask(%d)\n", (ulong)pgs,
408
	      (int)csel);
409
 
410
    params.pdf14_op = PDF14_INIT_TRANS_MASK;
411
    params.csel = csel;
412
    return gs_state_update_pdf14trans(pgs, &params);
413
}
414
 
415
int
416
gx_init_transparency_mask(gs_imager_state * pis,
417
				const gs_pdf14trans_params_t * pparams)
418
{
419
    gs_transparency_source_t *ptm;
420
 
421
    if_debug2('v', "[v](0x%lx)init_transparency_mask(%d)\n", (ulong)pis,
422
	      (int)pparams->csel);
423
    switch (pparams->csel) {
424
    case TRANSPARENCY_CHANNEL_Opacity: ptm = &pis->opacity; break;
425
    case TRANSPARENCY_CHANNEL_Shape: ptm = &pis->shape; break;
426
    default: return_error(gs_error_rangecheck);
427
    }
428
    rc_decrement_only(ptm->mask, "gs_init_transparency_mask");
429
    ptm->mask = 0;
430
    return 0;
431
}
432
 
433
int
434
gs_push_pdf14trans_device(gs_state * pgs)
435
{
436
    gs_pdf14trans_params_t params = { 0 };
437
 
438
    params.pdf14_op = PDF14_PUSH_DEVICE;  /* Other parameters not used */
439
    return gs_state_update_pdf14trans(pgs, &params);
440
}
441
 
442
int
443
gs_pop_pdf14trans_device(gs_state * pgs)
444
{
445
    gs_pdf14trans_params_t params = { 0 };
446
 
447
    params.pdf14_op = PDF14_POP_DEVICE;  /* Other parameters not used */
448
    return gs_state_update_pdf14trans(pgs, &params);
449
}