/src/ghostpdl/devices/vector/gdevpdft.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2025 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, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* transparency processing for PDF-writing driver */ |
18 | | #include "gx.h" |
19 | | #include "string_.h" |
20 | | #include "gserrors.h" |
21 | | #include "gstrans.h" |
22 | | #include "gscolor2.h" |
23 | | #include "gzstate.h" |
24 | | #include "gdevpdfx.h" |
25 | | #include "gdevpdfg.h" |
26 | | #include "gdevpdfo.h" |
27 | | #include "gsccolor.h" |
28 | | |
29 | | static int |
30 | | pdf_make_soft_mask_dict(gx_device_pdf * pdev, const gs_pdf14trans_params_t * pparams) |
31 | 117 | { |
32 | 117 | pdf_resource_t *pres_soft_mask_dict = 0; |
33 | 117 | cos_dict_t *soft_mask_dict; |
34 | 117 | int code; |
35 | | |
36 | | /* Fixme : merge redundant objects. */ |
37 | 117 | code = pdf_alloc_resource(pdev, resourceSoftMaskDict, gs_no_id, &pres_soft_mask_dict, -1); |
38 | 117 | if (code < 0) |
39 | 0 | return code; |
40 | 117 | cos_become(pres_soft_mask_dict->object, cos_type_dict); |
41 | 117 | pdev->pres_soft_mask_dict = pres_soft_mask_dict; |
42 | 117 | soft_mask_dict = (cos_dict_t *)pres_soft_mask_dict->object; |
43 | 117 | code = cos_dict_put_c_key_string(soft_mask_dict, "/S", |
44 | 117 | pparams->subtype == TRANSPARENCY_MASK_Alpha ? (byte *)"/Alpha" : (byte *)"/Luminosity", |
45 | 117 | pparams->subtype == TRANSPARENCY_MASK_Alpha ? 6 : 11); |
46 | 117 | if (code < 0) |
47 | 0 | return code; |
48 | 117 | if (pparams->Background_components) { |
49 | 91 | cos_array_t *Background; |
50 | | |
51 | 91 | Background = cos_array_from_floats(pdev, pparams->Background, |
52 | 91 | pparams->Background_components, "pdf_write_soft_mask_dict"); |
53 | 91 | if (Background == NULL) |
54 | 0 | return_error(gs_error_VMerror); |
55 | 91 | code = cos_dict_put_c_key_object(soft_mask_dict, "/BC", (cos_object_t *)Background); |
56 | 91 | if (code < 0) |
57 | 0 | return code; |
58 | 91 | } |
59 | 117 | if (pdev->CompatibilityLevel <= 1.7 && pparams->transfer_function != NULL && pdev->params.TransferFunctionInfo == tfi_Preserve) { |
60 | 42 | int64_t id; |
61 | 42 | char buf[20]; |
62 | | |
63 | 42 | code = pdf_write_function(pdev, pparams->transfer_function, &id); |
64 | 42 | if (code < 0) |
65 | 0 | return code; |
66 | 42 | gs_snprintf(buf, sizeof(buf), " %"PRId64" 0 R", id); |
67 | 42 | code = cos_dict_put_c_key_string(soft_mask_dict, "/TR", (const byte *)buf, strlen(buf)); |
68 | 42 | if (code < 0) |
69 | 0 | return code; |
70 | 42 | } |
71 | 117 | return 0; |
72 | | |
73 | 117 | } |
74 | | |
75 | | static int |
76 | | pdf_make_group_dict(gx_device_pdf * pdev, const gs_pdf14trans_params_t * pparams, |
77 | | const gs_gstate * pgs, cos_dict_t **pdict) |
78 | 4.50k | { |
79 | 4.50k | pdf_resource_t *pres_group; |
80 | 4.50k | cos_dict_t *group_dict; |
81 | 4.50k | int code; |
82 | 4.50k | cos_value_t cs_value; |
83 | | |
84 | 4.50k | code = pdf_alloc_resource(pdev, resourceGroup, gs_no_id, &pres_group, -1); |
85 | 4.50k | if (code < 0) |
86 | 0 | return code; |
87 | 4.50k | cos_become(pres_group->object, cos_type_dict); |
88 | 4.50k | group_dict = (cos_dict_t *)pres_group->object; |
89 | 4.50k | code = cos_dict_put_c_key_string(group_dict, "/Type", (const byte *)"/Group", 6); |
90 | 4.50k | if (code < 0) |
91 | 0 | return code; |
92 | 4.50k | code = cos_dict_put_c_key_string(group_dict, "/S", (const byte *)"/Transparency", 13); |
93 | 4.50k | if (code < 0) |
94 | 0 | return code; |
95 | 4.50k | if (pparams->Isolated) { |
96 | 3.96k | code = cos_dict_put_c_key_bool(group_dict, "/I", true); |
97 | 3.96k | if (code < 0) |
98 | 0 | return code; |
99 | 3.96k | } |
100 | 4.50k | if (pparams->Knockout) { |
101 | 2 | code = cos_dict_put_c_key_bool(group_dict, "/K", true); |
102 | 2 | if (code < 0) |
103 | 0 | return code; |
104 | 2 | } |
105 | | /* Note that we should not add in the graphic state |
106 | | color space for the group color if there was not |
107 | | a group color specified. |
108 | | In this case, the parent group is inherited from |
109 | | the previous group or the device color space */ |
110 | 4.50k | if (pgs != NULL && pparams->ColorSpace != NULL) { |
111 | 591 | const gs_color_space *cs = pparams->ColorSpace; |
112 | | |
113 | 591 | if (pparams->ColorSpace == NULL) |
114 | 0 | code = pdf_color_space_named(pdev, pgs, &cs_value, NULL, cs, |
115 | 0 | &pdf_color_space_names, false, NULL, 0, false); |
116 | 591 | else |
117 | 591 | code = pdf_color_space_named(pdev, pgs, &cs_value, NULL, pparams->ColorSpace, |
118 | 591 | &pdf_color_space_names, false, NULL, 0, false); |
119 | 591 | if (code < 0) |
120 | 0 | return code; |
121 | 591 | code = cos_dict_put_c_key(group_dict, "/CS", &cs_value); |
122 | 591 | if (code < 0) |
123 | 0 | return code; |
124 | 591 | } |
125 | 4.50k | group_dict = NULL; /* The next line invalidates it. */ |
126 | 4.50k | code = pdf_substitute_resource(pdev, &pres_group, resourceGroup, NULL, false); |
127 | 4.50k | if (code < 0) |
128 | 0 | return code; |
129 | 4.50k | pres_group->where_used |= pdev->used_mask; |
130 | 4.50k | *pdict = (cos_dict_t *)pres_group->object; |
131 | 4.50k | return 0; |
132 | 4.50k | } |
133 | | |
134 | | static int |
135 | | pdf_make_form_dict(gx_device_pdf * pdev, const gs_pdf14trans_params_t * pparams, |
136 | | const gs_gstate * pgs, |
137 | | const cos_dict_t *group_dict, cos_dict_t *form_dict) |
138 | 1.16k | { |
139 | 1.16k | cos_array_t *bbox_array; |
140 | 1.16k | float bbox[4]; |
141 | 1.16k | gs_rect bbox_rect; |
142 | 1.16k | int code; |
143 | | |
144 | 1.16k | code = gs_bbox_transform(&pparams->bbox, &ctm_only(pgs), &bbox_rect); |
145 | 1.16k | if (code < 0) |
146 | 0 | return code; |
147 | 1.16k | bbox[0] = bbox_rect.p.x; |
148 | 1.16k | bbox[1] = bbox_rect.p.y; |
149 | 1.16k | bbox[2] = bbox_rect.q.x; |
150 | 1.16k | bbox[3] = bbox_rect.q.y; |
151 | 1.16k | code = cos_dict_put_c_key_string(form_dict, "/Type", (const byte *)"/XObject", 8); |
152 | 1.16k | if (code < 0) |
153 | 0 | return code; |
154 | 1.16k | code = cos_dict_put_c_key_string(form_dict, "/Subtype", (const byte *)"/Form", 5); |
155 | 1.16k | if (code < 0) |
156 | 0 | return code; |
157 | 1.16k | code = cos_dict_put_c_key_int(form_dict, "/FormType", 1); |
158 | 1.16k | if (code < 0) |
159 | 0 | return code; |
160 | 1.16k | code = cos_dict_put_c_key_string(form_dict, "/Matrix", (const byte *)"[1 0 0 1 0 0]", 13); |
161 | 1.16k | if (code < 0) |
162 | 0 | return code; |
163 | 1.16k | bbox_array = cos_array_from_floats(pdev, bbox, 4, "pdf_begin_transparency_group"); |
164 | 1.16k | if (bbox_array == NULL) |
165 | 0 | return_error(gs_error_VMerror); |
166 | 1.16k | code = cos_dict_put_c_key_object(form_dict, "/BBox", (cos_object_t *)bbox_array); |
167 | 1.16k | if (code < 0) |
168 | 0 | return code; |
169 | 1.16k | if (pdev->PendingOC != 0) { |
170 | 1 | if (pdev->CompatibilityLevel < 1.4999) { |
171 | 0 | if (pdev->PDFA) { |
172 | 0 | switch (pdev->PDFACompatibilityPolicy) { |
173 | 0 | case 0: |
174 | 0 | emprintf(pdev->memory, |
175 | 0 | "Optional Content not valid in this version of PDF, reverting to normal PDF output\n"); |
176 | 0 | pdev->AbortPDFAX = true; |
177 | 0 | pdev->PDFA = 0; |
178 | 0 | break; |
179 | 0 | case 1: |
180 | 0 | emprintf(pdev->memory, |
181 | 0 | "Optional Content not valid in this version of PDF. Dropping feature to preserve PDF/A compatibility\n"); |
182 | 0 | break; |
183 | 0 | case 2: |
184 | 0 | emprintf(pdev->memory, |
185 | 0 | "Optional Content not valid in this version of PDF, aborting conversion\n"); |
186 | 0 | return_error (gs_error_typecheck); |
187 | 0 | break; |
188 | 0 | default: |
189 | 0 | emprintf(pdev->memory, |
190 | 0 | "Optional Content not valid in this version of PDF, unrecognised PDFACompatibilityLevel,\nreverting to normal PDF output\n"); |
191 | 0 | pdev->AbortPDFAX = true; |
192 | 0 | pdev->PDFA = 0; |
193 | 0 | break; |
194 | 0 | } |
195 | 0 | } else { |
196 | 0 | emprintf(pdev->memory, |
197 | 0 | "Optional Content not valid in this version of PDF. Dropping feature to preserve compatibility\n"); |
198 | 0 | } |
199 | 1 | } else { |
200 | 1 | char str[256]; |
201 | 1 | gs_param_string param; |
202 | 1 | cos_object_t *pco = NULL; |
203 | | |
204 | 1 | param.data = (const byte *)pdev->PendingOC; |
205 | 1 | param.size = strlen(pdev->PendingOC); |
206 | 1 | code = pdf_refer_named(pdev, ¶m, &pco); |
207 | 1 | gs_free_object(pdev->memory, pdev->PendingOC, ""); |
208 | 1 | if(code < 0) |
209 | 0 | return code; |
210 | | |
211 | 1 | gs_snprintf(str, sizeof(str), "%"PRId64" 0 R", pco->id); |
212 | 1 | code = cos_dict_put_string_copy(form_dict, "/OC", str); |
213 | 1 | if (code < 0) |
214 | 0 | return code; |
215 | | |
216 | 1 | pdev->PendingOC = 0; |
217 | 1 | } |
218 | 1 | } |
219 | 1.16k | return cos_dict_put_c_key_object(form_dict, "/Group", (cos_object_t *)group_dict); |
220 | 1.16k | } |
221 | | |
222 | | static int |
223 | | pdf_begin_transparency_group(gs_gstate * pgs, gx_device_pdf * pdev, |
224 | | const gs_pdf14trans_params_t * pparams, bool page_group) |
225 | 4.50k | { |
226 | 4.50k | cos_dict_t *group_dict; |
227 | 4.50k | int code; |
228 | | |
229 | 4.50k | if (pgs == NULL) |
230 | 0 | return_error(gs_error_unregistered); /* Must not happen. */ |
231 | 4.50k | code = pdf_make_group_dict(pdev, pparams, pgs, &group_dict); |
232 | 4.50k | if (code < 0) |
233 | 0 | return code; |
234 | 4.50k | code = pdf_open_page(pdev, PDF_IN_STREAM); |
235 | 4.50k | if (code < 0) |
236 | 0 | return code; |
237 | 4.50k | code = pdf_check_soft_mask(pdev, pgs); |
238 | 4.50k | if (code < 0) |
239 | 0 | return code; |
240 | 4.50k | if (pdf_must_put_clip_path(pdev, pgs->clip_path)) { |
241 | 314 | code = pdf_put_clip_path(pdev, pgs->clip_path); |
242 | 314 | if (code < 0) |
243 | 0 | return code; |
244 | 314 | } |
245 | 4.50k | if (page_group) |
246 | 241 | pdev->pages[pdev->next_page].group_id = group_dict->id; |
247 | 4.25k | else if (pparams->image_with_SMask) { |
248 | | /* An internal group for the image implementation. |
249 | | See doimagesmask in gs/lib/pdf_draw.ps . |
250 | | Just set a flag for skipping pdf_end_transparency_group. */ |
251 | 3.09k | pdev->image_with_SMask |= 1 << ++pdev->FormDepth; |
252 | 3.09k | pdev->PatternsSinceForm = 0; |
253 | 3.09k | } else { |
254 | 1.16k | pdf_resource_t *pres, *pres_gstate = NULL; |
255 | 1.16k | cos_dict_t *pcd = NULL, *pcd_Resources = NULL; |
256 | | |
257 | 1.16k | code = pdf_prepare_drawing(pdev, pgs, &pres_gstate, false); |
258 | 1.16k | if (code < 0) |
259 | 0 | return code; |
260 | 1.16k | code = pdf_end_gstate(pdev, pres_gstate); |
261 | 1.16k | if (code < 0) |
262 | 0 | return code; |
263 | 1.16k | code = pdf_enter_substream(pdev, resourceXObject, |
264 | 1.16k | gs_no_id, &pres, false, pdev->params.CompressPages); |
265 | 1.16k | if (code < 0) |
266 | 0 | return code; |
267 | 1.16k | pdev->FormDepth++; |
268 | 1.16k | pdev->PatternsSinceForm = 0; |
269 | 1.16k | code = pdf_make_form_dict(pdev, pparams, pgs, group_dict, (cos_dict_t *)pres->object); |
270 | 1.16k | if (code < 0) |
271 | 0 | return code; |
272 | | |
273 | | /* Create a Resources dictionary and add it to the form dictionary */ |
274 | 1.16k | pcd = cos_stream_dict((cos_stream_t *)pres->object); |
275 | 1.16k | pcd_Resources = cos_dict_alloc(pdev, "pdf_group(Resources)"); |
276 | 1.16k | if (pcd == NULL || pcd_Resources == NULL) |
277 | 0 | return_error(gs_error_VMerror); |
278 | 1.16k | code = cos_dict_put_c_key_object(pcd, "/Resources", COS_OBJECT(pcd_Resources)); |
279 | 1.16k | pdev->substream_Resources = pcd_Resources; |
280 | 1.16k | return code; |
281 | 1.16k | } |
282 | 3.33k | return 0; |
283 | 4.50k | } |
284 | | |
285 | | static int |
286 | | pdf_end_transparency_group(gs_gstate * pgs, gx_device_pdf * pdev) |
287 | 4.38k | { |
288 | 4.38k | int bottom = (pdev->ResourcesBeforeUsage ? 1 : 0); |
289 | | |
290 | 4.38k | if (!is_in_page(pdev) && pdev->sbstack_depth == 0) |
291 | 0 | return 0; /* A Group definition at the page level, handled separately. */ |
292 | 4.38k | if (pdev->image_with_SMask & (1 << pdev->FormDepth)) { |
293 | | /* An internal group for the image implementation. |
294 | | See pdf_begin_transparency_group. */ |
295 | 3.09k | pdev->image_with_SMask &= ~(1 << pdev->FormDepth--); |
296 | 3.09k | pdev->PatternsSinceForm = 0; |
297 | 3.09k | return 0; |
298 | 3.09k | } else if (pdev->sbstack_depth == bottom) { |
299 | | /* We're closing the page group. */ |
300 | 241 | if (pdev->pages[pdev->next_page].group_id == 0) |
301 | 0 | return_error(gs_error_unregistered); /* Must not happen. */ |
302 | 241 | return 0; |
303 | 1.04k | } else { |
304 | 1.04k | pdf_resource_t *pres = pdev->accumulating_substream_resource; |
305 | 1.04k | int code; |
306 | 1.04k | uint ignore; |
307 | | |
308 | 1.04k | if (pres == NULL) |
309 | 0 | return_error(gs_error_unregistered); |
310 | 1.04k | pdev->FormDepth--; |
311 | 1.04k | pdev->PatternsSinceForm = 0; |
312 | 1.04k | code = pdf_exit_substream(pdev); |
313 | 1.04k | if (code < 0) |
314 | 0 | return code; |
315 | 1.04k | code = pdf_substitute_resource(pdev, &pres, resourceXObject, NULL, false); |
316 | 1.04k | if (code < 0) |
317 | 0 | return code; |
318 | | /* We need to update the 'where_used' field, in case we substituted a resource */ |
319 | 1.04k | pres->where_used |= pdev->used_mask; |
320 | 1.04k | sputc(pdev->strm,'/'); |
321 | 1.04k | sputs(pdev->strm, (const byte *)pres->rname, strlen(pres->rname), &ignore); |
322 | 1.04k | sputs(pdev->strm, (const byte *)" Do\n", 4, &ignore); |
323 | 1.04k | code = pdf_add_resource(pdev, pdev->substream_Resources, "/XObject", pres); |
324 | 1.04k | return code; |
325 | 1.04k | } |
326 | 4.38k | } |
327 | | |
328 | | static int |
329 | | pdf_begin_transparency_mask(gs_gstate * pgs, gx_device_pdf * pdev, |
330 | | const gs_pdf14trans_params_t * pparams) |
331 | 1.95k | { |
332 | 1.95k | if (pparams->subtype == TRANSPARENCY_MASK_None) { |
333 | 1.83k | int code; |
334 | 1.83k | pdf_resource_t *pres = 0L; |
335 | | |
336 | | /* reset the soft mask ID. Apparently this is only used by pdfwrite, if we don't |
337 | | * reset it, then the pdf_prepare_drawing code doesn't know that the SMask has |
338 | | * changed, and so doesn't write out the GState |
339 | | */ |
340 | 1.83k | pgs->soft_mask_id = 0; |
341 | 1.83k | code = pdf_prepare_drawing(pdev, pgs, &pres, false); |
342 | 1.83k | if (code == gs_error_interrupt) { |
343 | | /* */ |
344 | | /* Not in an appropriate context. Do not restore the soft_mask_id. |
345 | | Otherwise any group push that occurs following this will use that |
346 | | softmask, which clearly should be NONE here. |
347 | | */ |
348 | | /* ignore return code, we don't care about this graphics state as we aren't |
349 | | * emitting it anyway |
350 | | */ |
351 | 347 | pdf_end_gstate(pdev, pres); |
352 | 347 | return 0; |
353 | 347 | } |
354 | 1.48k | if (code < 0) |
355 | 0 | return code; |
356 | 1.48k | code = pdf_end_gstate(pdev, pres); |
357 | 1.48k | if (code < 0) |
358 | 0 | return code; |
359 | 1.48k | return 0; |
360 | 1.48k | } |
361 | 117 | if (pparams->mask_is_image) { |
362 | | /* HACK : |
363 | | The control comes here when |
364 | | the PDF interpreter will make the PS interpreter |
365 | | to interprete the mask for filling the transparency buffer |
366 | | with an SMask image. |
367 | | Since we handle Type 3 images as a high level objects, |
368 | | we don't install the transparency buffer here |
369 | | and need to skip the image enumeration for the SMask. |
370 | | However we have no right method for skipping |
371 | | an image enumeration due to possible side effect |
372 | | of the image data proc in Postscript language. |
373 | | Therefore we do enumerate the image mask and accumulate |
374 | | it as a PDF stream, but don't create a reference to it. |
375 | | Later it will be enumerated once again as a part of SMask-ed image, |
376 | | and the pdfwrite image handler will recognize duplicated images |
377 | | and won't create the second stream for same image. |
378 | | |
379 | | We could make a special workaround for |
380 | | skipping mask images either in the graphics library or |
381 | | in the PS code of the PDF interpreter, |
382 | | but we don't want to complicate things now. |
383 | | The performance leak for the second enumeration |
384 | | shouldn't be harmful. |
385 | | |
386 | | So now just set a flag for pdf_end_and_do_image. |
387 | | */ |
388 | 0 | pdev->image_mask_skip = true; |
389 | 0 | return 0; |
390 | 117 | } else { |
391 | 117 | int code; |
392 | | |
393 | 117 | pdev->smask_construction = true; |
394 | 117 | code = pdf_make_soft_mask_dict(pdev, pparams); |
395 | 117 | if (code < 0) |
396 | 0 | return code; |
397 | 117 | code = pdf_open_page(pdev, PDF_IN_STREAM); |
398 | 117 | if (code < 0) |
399 | 0 | return code; |
400 | 117 | return pdf_begin_transparency_group(pgs, pdev, pparams, 0); |
401 | 117 | } |
402 | 117 | } |
403 | | |
404 | | static int |
405 | | pdf_end_transparency_mask(gs_gstate * pgs, gx_device_pdf * pdev, |
406 | | const gs_pdf14trans_params_t * pparams) |
407 | 117 | { |
408 | 117 | pdev->smask_construction = false; |
409 | 117 | if (pdev->image_mask_skip) |
410 | 0 | pdev->image_mask_skip = false; |
411 | 117 | else { |
412 | 117 | pdf_resource_t *pres = pdev->accumulating_substream_resource; |
413 | 117 | int code; |
414 | 117 | char buf[20]; |
415 | | |
416 | 117 | if (pres == NULL) |
417 | 0 | return_error(gs_error_unregistered); |
418 | 117 | code = pdf_exit_substream(pdev); |
419 | 117 | if (code < 0) |
420 | 0 | return code; |
421 | 117 | code = pdf_substitute_resource(pdev, &pres, resourceXObject, NULL, false); |
422 | 117 | if (code < 0) |
423 | 0 | return 0; |
424 | | /* We need to update the 'where_used' field, in case we substituted a resource */ |
425 | 117 | pres->where_used |= pdev->used_mask; |
426 | 117 | gs_snprintf(buf, sizeof(buf), "%"PRId64" 0 R", pdf_resource_id(pres)); |
427 | 117 | if (pdev->pres_soft_mask_dict == 0L) { |
428 | | /* something went horribly wrong, we have an 'end' wihtout a matching 'begin' |
429 | | * Give up, throw an error. |
430 | | */ |
431 | 0 | return_error(gs_error_undefined); |
432 | 0 | } |
433 | 117 | code = cos_dict_put_c_key_string((cos_dict_t *)pdev->pres_soft_mask_dict->object, |
434 | 117 | "/G", (const byte *)buf, strlen(buf)); |
435 | 117 | if (code < 0) |
436 | 0 | return code; |
437 | 117 | code = pdf_substitute_resource(pdev, &pdev->pres_soft_mask_dict, |
438 | 117 | resourceSoftMaskDict, NULL, false); |
439 | 117 | if (code < 0) |
440 | 0 | return code; |
441 | 117 | pdev->pres_soft_mask_dict->where_used |= pdev->used_mask; |
442 | 117 | pgs->soft_mask_id = pdev->pres_soft_mask_dict->object->id; |
443 | 117 | pdev->pres_soft_mask_dict = NULL; |
444 | | /* We called pdf_start_trnasparency_group (see pdf_begin_transparency_mask |
445 | | * above) but we don't call pdf_end_transparency_group, so we must reduce |
446 | | * the FormDepth ourselves. |
447 | | */ |
448 | 117 | pdev->FormDepth--; |
449 | 117 | pdev->PatternsSinceForm = 0; |
450 | 117 | } |
451 | 117 | return 0; |
452 | 117 | } |
453 | | |
454 | | static int |
455 | | pdf_set_blend_params(gs_gstate * pgs, gx_device_pdf * dev, |
456 | | const gs_pdf14trans_params_t * pparams) |
457 | 0 | { |
458 | 0 | return 0; |
459 | 0 | } |
460 | | |
461 | | int |
462 | | gdev_pdf_composite(gx_device *dev, |
463 | | gx_device **pcdev, const gs_composite_t *pct, |
464 | | gs_gstate *pgs, gs_memory_t *memory, gx_device *cdev) |
465 | 179k | { |
466 | 179k | gx_device_pdf *pdev = (gx_device_pdf *)dev; |
467 | | |
468 | 179k | if (pdev->HaveTransparency && pdev->CompatibilityLevel >= 1.4 && |
469 | 179k | pct->type->comp_id == GX_COMPOSITOR_PDF14_TRANS && |
470 | 179k | pdev->PDFA != 1) { |
471 | 32.2k | gs_pdf14trans_t *pcte = (gs_pdf14trans_t *)pct; |
472 | 32.2k | gs_pdf14trans_params_t *params = &pcte->params; |
473 | | |
474 | 32.2k | *pcdev = dev; |
475 | 32.2k | switch(params->pdf14_op) { |
476 | 497 | case PDF14_PUSH_DEVICE: |
477 | 497 | return 0; |
478 | 497 | case PDF14_POP_DEVICE: |
479 | 497 | return 0; |
480 | 0 | case PDF14_ABORT_DEVICE: |
481 | 0 | return 0; |
482 | 241 | case PDF14_BEGIN_TRANS_PAGE_GROUP: |
483 | 241 | return pdf_begin_transparency_group(pgs, pdev, params, 1); |
484 | 4.14k | case PDF14_BEGIN_TRANS_GROUP: |
485 | 4.14k | return pdf_begin_transparency_group(pgs, pdev, params, 0); |
486 | 4.38k | case PDF14_END_TRANS_GROUP: |
487 | 4.38k | return pdf_end_transparency_group(pgs, pdev); |
488 | 9.46k | case PDF14_BEGIN_TRANS_TEXT_GROUP: |
489 | 9.46k | return 0; |
490 | 10.6k | case PDF14_END_TRANS_TEXT_GROUP: |
491 | 10.6k | return 0; |
492 | 1.95k | case PDF14_BEGIN_TRANS_MASK: |
493 | 1.95k | return pdf_begin_transparency_mask(pgs, pdev, params); |
494 | 117 | case PDF14_END_TRANS_MASK: |
495 | 117 | return pdf_end_transparency_mask(pgs, pdev, params); |
496 | 0 | case PDF14_SET_BLEND_PARAMS: |
497 | 0 | return pdf_set_blend_params(pgs, pdev, params); |
498 | 0 | case PDF14_PUSH_TRANS_STATE: |
499 | 0 | return 0; |
500 | 76 | case PDF14_POP_TRANS_STATE: |
501 | 76 | return 0; |
502 | 117 | case PDF14_PUSH_SMASK_COLOR: |
503 | 117 | return 0; |
504 | 117 | case PDF14_POP_SMASK_COLOR: |
505 | 117 | return 0; |
506 | | |
507 | 0 | default : |
508 | 0 | return_error(gs_error_unregistered); /* Must not happen. */ |
509 | 32.2k | } |
510 | 0 | return 0; |
511 | 32.2k | } |
512 | 146k | return psdf_composite(dev, pcdev, pct, pgs, memory, cdev); |
513 | 179k | } |
514 | | |
515 | | /* We're not sure why the folllowing device methods are never called. |
516 | | Stub them for a while. */ |
517 | | |
518 | | int |
519 | | gdev_pdf_begin_transparency_group(gx_device *dev, |
520 | | const gs_transparency_group_params_t *ptgp, |
521 | | const gs_rect *pbbox, |
522 | | gs_gstate *pgs, gs_memory_t *mem) |
523 | 0 | { |
524 | 0 | return 0; |
525 | 0 | } |
526 | | |
527 | | int |
528 | | gdev_pdf_end_transparency_group(gx_device *dev, |
529 | | gs_gstate *pgs) |
530 | 0 | { |
531 | 0 | return 0; |
532 | 0 | } |
533 | | |
534 | | int |
535 | | gdev_pdf_begin_transparency_mask(gx_device *dev, |
536 | | const gx_transparency_mask_params_t *ptmp, |
537 | | const gs_rect *pbbox, |
538 | | gs_gstate *pgs, gs_memory_t *mem) |
539 | 0 | { |
540 | 0 | return 0; |
541 | 0 | } |
542 | | |
543 | | int |
544 | | gdev_pdf_end_transparency_mask(gx_device *dev, |
545 | | gs_gstate *pgs) |
546 | 0 | { |
547 | 0 | return 0; |
548 | 0 | } |