1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
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.
14
/* $Id: ztrans.c 9043 2008-08-28 22:48:19Z giles $ */
15
/* Transparency operators */
20
#include "gscspace.h" /* for gscolor2.h */
24
#include "gxiparam.h" /* for image enumerator */
38
/* ------ Utilities ------ */
41
set_float_value(i_ctx_t *i_ctx_p, int (*set_value)(gs_state *, floatp))
47
if (real_param(op, &value) < 0)
48
return_op_typecheck(op);
49
if ((code = set_value(igs, value)) < 0)
56
current_float_value(i_ctx_t *i_ctx_p,
57
float (*current_value)(const gs_state *))
62
make_real(op, current_value(igs));
67
enum_param(const gs_memory_t *mem, const ref *pnref,
68
const char *const names[])
73
name_string_ref(mem, pnref, &nsref);
74
for (p = names; *p; ++p)
75
if (r_size(&nsref) == strlen(*p) &&
76
!memcmp(*p, nsref.value.const_bytes, r_size(&nsref))
79
return_error(e_rangecheck);
82
/* ------ Graphics state operators ------ */
84
static const char *const blend_mode_names[] = {
85
GS_BLEND_MODE_NAMES, 0
88
/* <modename> .setblendmode - */
90
zsetblendmode(i_ctx_t *i_ctx_p)
95
check_type(*op, t_name);
96
if ((code = enum_param(imemory, op, blend_mode_names)) < 0 ||
97
(code = gs_setblendmode(igs, code)) < 0
104
/* - .currentblendmode <modename> */
106
zcurrentblendmode(i_ctx_t *i_ctx_p)
109
const char *mode_name = blend_mode_names[gs_currentblendmode(igs)];
111
int code = name_enter_string(imemory, mode_name, &nref);
120
/* <0..1> .setopacityalpha - */
122
zsetopacityalpha(i_ctx_t *i_ctx_p)
124
return set_float_value(i_ctx_p, gs_setopacityalpha);
127
/* - .currentopacityalpha <0..1> */
129
zcurrentopacityalpha(i_ctx_t *i_ctx_p)
131
return current_float_value(i_ctx_p, gs_currentopacityalpha);
134
/* <0..1> .setshapealpha - */
136
zsetshapealpha(i_ctx_t *i_ctx_p)
138
return set_float_value(i_ctx_p, gs_setshapealpha);
141
/* - .currentshapealpha <0..1> */
143
zcurrentshapealpha(i_ctx_t *i_ctx_p)
145
return current_float_value(i_ctx_p, gs_currentshapealpha);
148
/* <bool> .settextknockout - */
150
zsettextknockout(i_ctx_t *i_ctx_p)
154
check_type(*op, t_boolean);
155
gs_settextknockout(igs, op->value.boolval);
160
/* - .currenttextknockout <bool> */
162
zcurrenttextknockout(i_ctx_t *i_ctx_p)
167
make_bool(op, gs_currenttextknockout(igs));
171
/* ------ Rendering stack operators ------ */
174
rect_param(gs_rect *prect, os_ptr op)
177
int code = num_params(op, 4, coords);
181
prect->p.x = coords[0], prect->p.y = coords[1];
182
prect->q.x = coords[2], prect->q.y = coords[3];
187
mask_op(i_ctx_t *i_ctx_p,
188
int (*mask_proc)(gs_state *, gs_transparency_channel_selector_t))
191
int code = int_param(osp, 1, &csel);
195
code = mask_proc(igs, csel);
202
/* <paramdict> <llx> <lly> <urx> <ury> .begintransparencygroup - */
204
zbegintransparencygroup(i_ctx_t *i_ctx_p)
208
gs_transparency_group_params_t params;
212
check_type(*dop, t_dictionary);
213
check_dict_read(*dop);
214
gs_trans_group_params_init(¶ms);
215
if ((code = dict_bool_param(dop, "Isolated", false, ¶ms.Isolated)) < 0 ||
216
(code = dict_bool_param(dop, "Knockout", false, ¶ms.Knockout)) < 0 ||
217
(code = dict_bool_param(dop, ".image_with_SMask", false, ¶ms.image_with_SMask)) < 0
220
code = rect_param(&bbox, op);
223
params.ColorSpace = gs_currentcolorspace(igs);
224
code = gs_begin_transparency_group(igs, ¶ms, &bbox);
231
/* - .discardtransparencygroup - */
233
zdiscardtransparencygroup(i_ctx_t *i_ctx_p)
235
if (gs_current_transparency_type(igs) != TRANSPARENCY_STATE_Group)
236
return_error(e_rangecheck);
237
return gs_discard_transparency_layer(igs);
240
/* - .endtransparencygroup - */
242
zendtransparencygroup(i_ctx_t *i_ctx_p)
244
return gs_end_transparency_group(igs);
247
/* <paramdict> <llx> <lly> <urx> <ury> .begintransparencymaskgroup - */
248
static int tf_using_function(floatp, float *, void *);
250
zbegintransparencymaskgroup(i_ctx_t *i_ctx_p)
254
gs_transparency_mask_params_t params;
258
static const char *const subtype_names[] = {
259
GS_TRANSPARENCY_MASK_SUBTYPE_NAMES, 0
262
check_type(*dop, t_dictionary);
263
check_dict_read(*dop);
264
if (dict_find_string(dop, "Subtype", &pparam) <= 0)
265
return_error(e_rangecheck);
266
if ((code = enum_param(imemory, pparam, subtype_names)) < 0)
268
gs_trans_mask_params_init(¶ms, code);
269
params.replacing = true;
270
if ((code = dict_floats_param(imemory, dop, "Background",
271
cs_num_components(gs_currentcolorspace(i_ctx_p->pgs)),
272
params.Background, NULL)) < 0
276
params.Background_components = code;
277
if ((code = dict_floats_param(imemory, dop, "GrayBackground",
278
1, ¶ms.GrayBackground, NULL)) < 0
281
if (dict_find_string(dop, "TransferFunction", &pparam) >0) {
282
gs_function_t *pfn = ref_function(pparam);
284
if (pfn == 0 || pfn->params.m != 1 || pfn->params.n != 1)
285
return_error(e_rangecheck);
286
params.TransferFunction = tf_using_function;
287
params.TransferFunction_data = pfn;
289
code = rect_param(&bbox, op);
292
code = gs_begin_transparency_mask(igs, ¶ms, &bbox, false);
299
/* - .begintransparencymaskimage - */
301
zbegintransparencymaskimage(i_ctx_t *i_ctx_p)
303
gs_transparency_mask_params_t params;
304
gs_rect bbox = { { 0, 0} , { 1, 1} };
307
gs_trans_mask_params_init(¶ms, TRANSPARENCY_MASK_Luminosity);
308
code = gs_begin_transparency_mask(igs, ¶ms, &bbox, true);
314
/* Implement the TransferFunction using a Function. */
316
tf_using_function(floatp in_val, float *out, void *proc_data)
319
gs_function_t *const pfn = proc_data;
321
return gs_function_evaluate(pfn, &in, out);
324
/* - .discardtransparencymask - */
326
zdiscardtransparencymask(i_ctx_t *i_ctx_p)
328
if (gs_current_transparency_type(igs) != TRANSPARENCY_STATE_Mask)
329
return_error(e_rangecheck);
330
return gs_discard_transparency_layer(igs);
333
/* <mask#> .endtransparencymask - */
335
zendtransparencymask(i_ctx_t *i_ctx_p)
337
return mask_op(i_ctx_p, gs_end_transparency_mask);
340
/* ------ Soft-mask images ------ */
342
/* <dict> .image3x - */
343
static int mask_dict_param(const gs_memory_t *mem, os_ptr,
344
image_params *, const char *, int,
345
gs_image3x_mask_t *);
347
zimage3x(i_ctx_t *i_ctx_p)
352
image_params ip_data;
354
gs_color_space_num_components(gs_currentcolorspace(igs));
358
check_type(*op, t_dictionary);
359
check_dict_read(*op);
360
gs_image3x_t_init(&image, NULL);
361
if (dict_find_string(op, "DataDict", &pDataDict) <= 0)
362
return_error(e_rangecheck);
363
if ((code = pixel_image_params(i_ctx_p, pDataDict,
364
(gs_pixel_image_t *)&image, &ip_data,
365
16, false, gs_currentcolorspace(igs))) < 0 ||
366
(code = dict_int_param(pDataDict, "ImageType", 1, 1, 0, &ignored)) < 0
370
* We have to process the masks in the reverse order, because they
371
* insert their DataSource before the one(s) for the DataDict.
373
if ((code = mask_dict_param(imemory, op, &ip_data,
374
"ShapeMaskDict", num_components,
375
&image.Shape)) < 0 ||
376
(code = mask_dict_param(imemory, op, &ip_data,
377
"OpacityMaskDict", num_components,
381
return zimage_setup(i_ctx_p, (gs_pixel_image_t *)&image,
382
&ip_data.DataSource[0],
383
image.CombineWithColor, 1);
386
/* Get one soft-mask dictionary parameter. */
388
mask_dict_param(const gs_memory_t *mem, os_ptr op,
389
image_params *pip_data, const char *dict_name,
390
int num_components, gs_image3x_mask_t *pixm)
393
image_params ip_mask;
397
if (dict_find_string(op, dict_name, &pMaskDict) <= 0)
399
if ((mcode = code = data_image_params(mem, pMaskDict, &pixm->MaskDict,
400
&ip_mask, false, 1, 16, false)) < 0 ||
401
(code = dict_int_param(pMaskDict, "ImageType", 1, 1, 0, &ignored)) < 0 ||
402
(code = dict_int_param(pMaskDict, "InterleaveType", 1, 3, -1,
403
&pixm->InterleaveType)) < 0 ||
404
(code = dict_floats_param(mem, op, "Matte", num_components,
405
pixm->Matte, NULL)) < 0
408
pixm->has_Matte = code > 0;
410
* The MaskDict must have a DataSource iff InterleaveType == 3.
412
if ((pip_data->MultipleDataSources && pixm->InterleaveType != 3) ||
413
ip_mask.MultipleDataSources ||
414
mcode != (pixm->InterleaveType != 3)
416
return_error(e_rangecheck);
417
if (pixm->InterleaveType == 3) {
418
/* Insert the mask DataSource before the data DataSources. */
419
memmove(&pip_data->DataSource[1], &pip_data->DataSource[0],
420
(countof(pip_data->DataSource) - 1) *
421
sizeof(pip_data->DataSource[0]));
422
pip_data->DataSource[0] = ip_mask.DataSource[0];
427
/* depth .pushpdf14devicefilter - */
428
/* this is a filter operator, but we include it here to maintain
429
modularity of the pdf14 transparency support */
431
zpushpdf14devicefilter(i_ctx_t *i_ctx_p)
436
check_type(*op, t_integer);
437
code = gs_push_pdf14trans_device(igs);
444
/* this is a filter operator, but we include it here to maintain
445
modularity of the pdf14 transparency support */
447
zpoppdf14devicefilter(i_ctx_t *i_ctx_p)
449
return gs_pop_pdf14trans_device(igs);
452
/* ------ Initialization procedure ------ */
454
/* We need to split the table because of the 16-element limit. */
455
const op_def ztrans1_op_defs[] = {
456
{"1.setblendmode", zsetblendmode},
457
{"0.currentblendmode", zcurrentblendmode},
458
{"1.setopacityalpha", zsetopacityalpha},
459
{"0.currentopacityalpha", zcurrentopacityalpha},
460
{"1.setshapealpha", zsetshapealpha},
461
{"0.currentshapealpha", zcurrentshapealpha},
462
{"1.settextknockout", zsettextknockout},
463
{"0.currenttextknockout", zcurrenttextknockout},
466
const op_def ztrans2_op_defs[] = {
467
{"5.begintransparencygroup", zbegintransparencygroup},
468
{"0.discardtransparencygroup", zdiscardtransparencygroup},
469
{"0.endtransparencygroup", zendtransparencygroup},
470
{"5.begintransparencymaskgroup", zbegintransparencymaskgroup},
471
{"5.begintransparencymaskimage", zbegintransparencymaskimage},
472
{"0.discardtransparencymask", zdiscardtransparencymask},
473
{"1.endtransparencymask", zendtransparencymask},
474
{"1.image3x", zimage3x},
475
{"1.pushpdf14devicefilter", zpushpdf14devicefilter},
476
{"0.poppdf14devicefilter", zpoppdf14devicefilter},