Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1996, 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: gdevpdft.c,v 1.52 2005/09/06 22:21:14 leonardo Exp $ */
18
/* transparency processing for PDF-writing driver */
19
#include "gx.h"
20
#include "string_.h"
21
#include "gserrors.h"
22
#include "gstrans.h"
23
#include "gscolor2.h"
24
#include "gzstate.h"
25
#include "gdevpdfx.h"
26
#include "gdevpdfg.h"
27
#include "gdevpdfo.h"
28
 
29
private int
30
pdf_make_soft_mask_dict(gx_device_pdf * pdev, const gs_pdf14trans_params_t * pparams)
31
{
32
    pdf_resource_t *pres_soft_mask_dict = 0;
33
    cos_dict_t *soft_mask_dict;
34
    int code;
35
 
36
    /* Fixme : merge redundant objects. */
37
    code = pdf_alloc_resource(pdev, resourceSoftMaskDict, gs_no_id, &pres_soft_mask_dict, -1);
38
    if (code < 0)
39
	return code;
40
    cos_become(pres_soft_mask_dict->object, cos_type_dict);
41
    pdev->pres_soft_mask_dict = pres_soft_mask_dict;
42
    soft_mask_dict = (cos_dict_t *)pres_soft_mask_dict->object;
43
    code = cos_dict_put_c_key_string(soft_mask_dict, "/S", 
44
	    pparams->subtype == TRANSPARENCY_MASK_Alpha ? (byte *)"/Alpha" : (byte *)"/Luminosity", 
45
	    pparams->subtype == TRANSPARENCY_MASK_Alpha ? 6 : 11);
46
    if (code < 0)
47
	return code;
48
    if (pparams->Background_components) {
49
	cos_array_t *Background;
50
 
51
	Background = cos_array_from_floats(pdev, pparams->Background, 
52
		    pparams->Background_components, "pdf_write_soft_mask_dict");
53
	if (Background == NULL)
54
	    return_error(gs_error_VMerror);
55
	code = cos_dict_put_c_key_object(soft_mask_dict, "/BC", (cos_object_t *)Background);
56
	if (code < 0)
57
	    return code;
58
    }
59
    if (pparams->transfer_function != NULL) {
60
	long id;
61
	char buf[20];
62
 
63
	code = pdf_write_function(pdev, pparams->transfer_function, &id);
64
	if (code < 0)
65
	    return code;
66
	sprintf(buf, " %ld 0 R", id);
67
	code = cos_dict_put_c_key_string(soft_mask_dict, "/TR", (const byte *)buf, strlen(buf));
68
	if (code < 0)
69
	    return code;
70
    }
71
    return 0;
72
 
73
}
74
 
75
private int
76
pdf_make_group_dict(gx_device_pdf * pdev, const gs_pdf14trans_params_t * pparams,
77
			    const gs_imager_state * pis, cos_dict_t **pdict)
78
{
79
    pdf_resource_t *pres_group;
80
    cos_dict_t *group_dict;
81
    int code;
82
    const gs_state *gstate = gx_hld_get_gstate_ptr(pis);
83
    cos_value_t cs_value;
84
 
85
    code = pdf_alloc_resource(pdev, resourceGroup, gs_no_id, &pres_group, -1);
86
    if (code < 0)
87
	return code;
88
    cos_become(pres_group->object, cos_type_dict);
89
    group_dict = (cos_dict_t *)pres_group->object;
90
    code = cos_dict_put_c_key_string(group_dict, "/Type", (const byte *)"/Group", 6);
91
    if (code < 0)
92
	return code;
93
    code = cos_dict_put_c_key_string(group_dict, "/S", (const byte *)"/Transparency", 13);
94
    if (code < 0)
95
	return code;
96
    if (pparams->Isolated) {
97
	code = cos_dict_put_c_key_bool(group_dict, "/I", true);
98
	if (code < 0)
99
	    return code;
100
    }
101
    if (pparams->Knockout) {
102
	code = cos_dict_put_c_key_bool(group_dict, "/K", true);
103
	if (code < 0)
104
	    return code;
105
    }
106
    if (gstate != NULL) {
107
	const gs_color_space *cs = gstate->color_space;
108
 
109
	code = pdf_color_space(pdev, &cs_value, NULL, cs,
110
		&pdf_color_space_names, false);
111
	if (code < 0)
112
	    return code;
113
	code = cos_dict_put_c_key(group_dict, "/CS", &cs_value);
114
	if (code < 0)
115
	    return code;
116
    }
117
    group_dict = NULL; /* The next line invalidates it. */
118
    code = pdf_substitute_resource(pdev, &pres_group, resourceGroup, NULL, false);
119
    if (code < 0)
120
	return code;
121
    *pdict = (cos_dict_t *)pres_group->object;
122
    return 0;
123
}
124
 
125
private int
126
pdf_make_form_dict(gx_device_pdf * pdev, const gs_pdf14trans_params_t * pparams,
127
			    const gs_imager_state * pis, 
128
			    const cos_dict_t *group_dict, cos_dict_t *form_dict)
129
{
130
    cos_array_t *bbox_array;
131
    float bbox[4];
132
    gs_rect bbox_rect;
133
    int code;
134
 
135
 
136
    code = gs_bbox_transform(&pparams->bbox, &ctm_only(pis), &bbox_rect);
137
    if (code < 0)
138
	return code;
139
    bbox[0] = bbox_rect.p.x;
140
    bbox[1] = bbox_rect.p.y;
141
    bbox[2] = bbox_rect.q.x;
142
    bbox[3] = bbox_rect.q.y;
143
    code = cos_dict_put_c_key_string(form_dict, "/Type", (const byte *)"/XObject", 8);
144
    if (code < 0)
145
	return code;
146
    code = cos_dict_put_c_key_string(form_dict, "/Subtype", (const byte *)"/Form", 5);
147
    if (code < 0)
148
	return code;
149
    code = cos_dict_put_c_key_int(form_dict, "/FormType", 1);
150
    if (code < 0)
151
	return code;
152
    code = cos_dict_put_c_key_string(form_dict, "/Matrix", (const byte *)"[1 0 0 1 0 0]", 13);
153
    if (code < 0)
154
	return code;
155
    bbox_array = cos_array_from_floats(pdev, bbox, 4, "pdf_begin_transparency_group");
156
    if (bbox_array == NULL)
157
	return_error(gs_error_VMerror);
158
    code = cos_dict_put_c_key_object(form_dict, "/BBox", (cos_object_t *)bbox_array);
159
    if (code < 0)
160
	return code;
161
    return cos_dict_put_c_key_object(form_dict, "/Group", (cos_object_t *)group_dict);
162
}
163
 
164
private int 
165
pdf_begin_transparency_group(gs_imager_state * pis, gx_device_pdf * pdev,
166
				const gs_pdf14trans_params_t * pparams)
167
{
168
    cos_dict_t *group_dict;
169
    bool in_page = is_in_page(pdev);
170
    const gs_state *gstate = gx_hld_get_gstate_ptr(pis);
171
    int code;
172
 
173
    if (gstate == NULL)
174
	return_error(gs_error_unregistered); /* Must not happen. */
175
    code = pdf_make_group_dict(pdev, pparams, pis, &group_dict);
176
    if (code < 0)
177
	return code;
178
    code = pdf_open_page(pdev, PDF_IN_STREAM);
179
    if (code < 0)
180
	return code;
181
    if (pdf_must_put_clip_path(pdev, gstate->clip_path)) {
182
	code = pdf_put_clip_path(pdev, gstate->clip_path);
183
	if (code < 0)
184
	    return code;
185
    }
186
    if (!in_page) 
187
	pdev->pages[pdev->next_page].group_id = group_dict->id;
188
    else {
189
	pdf_resource_t *pres, *pres_gstate = NULL;
190
 
191
	code = pdf_prepare_drawing(pdev, pis, &pres_gstate);
192
	if (code < 0)
193
	    return code;
194
	code = pdf_end_gstate(pdev, pres_gstate);
195
	if (code < 0)
196
	    return code;
197
	code = pdf_enter_substream(pdev, resourceXObject, 
198
		gs_no_id, &pres, false, pdev->params.CompressPages);
199
	if (code < 0)
200
	    return code;
201
	return pdf_make_form_dict(pdev, pparams, pis, group_dict, (cos_dict_t *)pres->object);
202
    }
203
    return 0;
204
}
205
 
206
private int 
207
pdf_end_transparency_group(gs_imager_state * pis, gx_device_pdf * pdev)
208
{
209
    int bottom = (pdev->ResourcesBeforeUsage ? 1 : 0);
210
 
211
    if (pdev->sbstack_depth == bottom) {
212
	/* We're closing the page group. */
213
	if (pdev->pages[pdev->next_page].group_id == 0)
214
	    return_error(gs_error_unregistered); /* Must not happen. */
215
	return 0;
216
    } else {
217
	pdf_resource_t *pres = pdev->accumulating_substream_resource;
218
	int code;
219
	uint ignore;
220
 
221
	code = pdf_exit_substream(pdev);
222
	if (code < 0)
223
	    return code;
224
	code = pdf_substitute_resource(pdev, &pres, resourceXObject, NULL, false);
225
	if (code < 0)
226
	    return code;
227
	sputc(pdev->strm,'/');
228
	sputs(pdev->strm, (const byte *)pres->rname, strlen(pres->rname), &ignore);
229
	sputs(pdev->strm, (const byte *)" Do\n", 4, &ignore);
230
	return 0;    
231
    }
232
}
233
 
234
private int 
235
pdf_begin_transparency_mask(gs_imager_state * pis, gx_device_pdf * pdev,
236
				const gs_pdf14trans_params_t * pparams)
237
{
238
    if (pparams->mask_is_image) {
239
	/* HACK : 
240
	    The control comes here when 
241
	    the PDF interpreter will make the PS interpreter 
242
	    to interprete the mask for filling the transparency buffer
243
    	    with an SMask image.
244
	    Since we handle Type 3 images as a high level objects, 
245
	    we don't install the transparency buffer here
246
	    and need to skip the image enumeration for the SMask.
247
	    However we have no right method for skipping
248
	    an image enumeration due to possible side effect 
249
	    of the image data proc in Postscript language.
250
	    Therefore we do enumerate the image mask and accumulate
251
	    it as a PDF stream, but don't create a reference to it.
252
	    Later it will be enumerated once again as a part of SMask-ed image,
253
	    and the pdfwrite image handler will recognize duplicated images 
254
	    and won't create the second stream for same image.
255
 
256
	    We could make a special workaround for 
257
	    skipping mask images either in the graphics library or 
258
	    in the PS code of the PDF interpreter,
259
	    but we don't want to complicate things now.
260
	    The performance leak for the second enumeration 
261
	    shouldn't be harmful.
262
 
263
	    So now just set a flag for pdf_end_and_do_image.
264
	*/
265
	pdev->image_mask_skip = true;
266
	return 0;
267
    } else {
268
	int code;
269
 
270
	code = pdf_make_soft_mask_dict(pdev, pparams);
271
	if (code < 0)
272
	    return code;
273
	code = pdf_open_page(pdev, PDF_IN_STREAM);
274
	if (code < 0)
275
	    return code;
276
	return pdf_begin_transparency_group(pis, pdev, pparams);
277
    }
278
}
279
 
280
private int 
281
pdf_end_transparency_mask(gs_imager_state * pis, gx_device_pdf * pdev,
282
				const gs_pdf14trans_params_t * pparams)
283
{
284
    if (pdev->image_mask_skip) 
285
	pdev->image_mask_skip = false;
286
    else {
287
	pdf_resource_t *pres = pdev->accumulating_substream_resource;
288
	int code;
289
	char buf[20];
290
 
291
	code = pdf_exit_substream(pdev);
292
	if (code < 0)
293
	    return code;
294
	code = pdf_substitute_resource(pdev, &pres, resourceXObject, NULL, false);
295
	if (code < 0)
296
	    return 0;
297
	sprintf(buf, "%ld 0 R", pdf_resource_id(pres));
298
	code = cos_dict_put_c_key_string((cos_dict_t *)pdev->pres_soft_mask_dict->object,
299
		"/G", (const byte *)buf, strlen(buf));
300
	if (code < 0)
301
	    return code;
302
	code = pdf_substitute_resource(pdev, &pdev->pres_soft_mask_dict, 
303
					resourceSoftMaskDict, NULL, false);
304
	if (code < 0)
305
	    return code;
306
	pis->soft_mask_id = pdev->pres_soft_mask_dict->object->id;
307
	pdev->pres_soft_mask_dict = NULL;
308
    }
309
    return 0;
310
}
311
 
312
private int
313
pdf_set_blend_params(gs_imager_state * pis, gx_device_pdf * dev,
314
				const gs_pdf14trans_params_t * pparams)
315
{
316
    return 0;
317
}
318
 
319
int 
320
gdev_pdf_create_compositor(gx_device *dev,
321
    gx_device **pcdev, const gs_composite_t *pct,
322
    gs_imager_state *pis, gs_memory_t *memory)
323
{
324
    gx_device_pdf *pdev = (gx_device_pdf *)dev;
325
 
326
    if (pdev->HaveTransparency && pdev->CompatibilityLevel >= 1.4 &&
327
	    pct->type->comp_id == GX_COMPOSITOR_PDF14_TRANS) {
328
	gs_pdf14trans_t *pcte = (gs_pdf14trans_t *)pct;
329
	gs_pdf14trans_params_t *params = &pcte->params;
330
 
331
	*pcdev = dev;
332
	switch(params->pdf14_op) {
333
	    case PDF14_PUSH_DEVICE:
334
		return 0;
335
	    case PDF14_POP_DEVICE:
336
		return 0;
337
	    case PDF14_BEGIN_TRANS_GROUP:
338
		return pdf_begin_transparency_group(pis, pdev, params);
339
	    case PDF14_END_TRANS_GROUP:
340
		return pdf_end_transparency_group(pis, pdev);
341
	    case PDF14_INIT_TRANS_MASK:
342
		return gx_init_transparency_mask(pis, params);
343
	    case PDF14_BEGIN_TRANS_MASK:
344
		return pdf_begin_transparency_mask(pis, pdev, params);
345
	    case PDF14_END_TRANS_MASK:
346
		return pdf_end_transparency_mask(pis, pdev, params);
347
	    case PDF14_SET_BLEND_PARAMS:
348
		return pdf_set_blend_params(pis, pdev, params);
349
	    default :
350
		return_error(gs_error_unregistered); /* Must not happen. */
351
	}
352
    }
353
    return psdf_create_compositor(dev, pcdev, pct, pis, memory);
354
}
355
 
356
/* We're not sure why the folllowing device methods are never called.
357
   Stub them for a while. */
358
 
359
int 
360
gdev_pdf_begin_transparency_group(gx_device *dev,
361
    const gs_transparency_group_params_t *ptgp,
362
    const gs_rect *pbbox,
363
    gs_imager_state *pis,
364
    gs_transparency_state_t **ppts,
365
    gs_memory_t *mem)
366
{
367
    return 0;
368
}
369
 
370
int
371
gdev_pdf_end_transparency_group(gx_device *dev,
372
    gs_imager_state *pis,
373
    gs_transparency_state_t **ppts)
374
{
375
    return 0;
376
}
377
 
378
int
379
gdev_pdf_begin_transparency_mask(gx_device *dev,
380
    const gx_transparency_mask_params_t *ptmp,
381
    const gs_rect *pbbox,
382
    gs_imager_state *pis,
383
    gs_transparency_state_t **ppts,
384
    gs_memory_t *mem)
385
{
386
    return 0;
387
}
388
 
389
int
390
gdev_pdf_end_transparency_mask(gx_device *dev,
391
    gs_transparency_mask_t **pptm)
392
{
393
    return 0;
394
}
395
 
396
int
397
gdev_pdf_discard_transparency_layer(gx_device *dev,
398
    gs_transparency_state_t **ppts)
399
{
400
    return 0;
401
}