1 /* Copyright (C) 1996, 2000, 2002 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: gdevpdfi.c,v 1.73 2005/08/29 18:21:57 igor Exp $ */
18 /* Image handling for PDF-writing driver */
19 #include "memory_.h"
20 #include "math_.h"
21 #include "gx.h"
22 #include "gserrors.h"
23 #include "gsdevice.h"
24 #include "gsflip.h"
25 #include "gsstate.h"
26 #include "gscolor2.h"
27 #include "gdevpdfx.h"
28 #include "gdevpdfg.h"
29 #include "gdevpdfo.h" /* for data stream */
30 #include "gxcspace.h"
31 #include "gximage3.h"
32 #include "gximag3x.h"
33 #include "gsiparm4.h"
34 #include "gxdcolor.h"
35 #include "gxpcolor.h"
36 #include "gxcolor2.h"
37 #include "gxhldevc.h"
38
39
40 /* Forward references */
41 private image_enum_proc_plane_data(pdf_image_plane_data);
42 private image_enum_proc_end_image(pdf_image_end_image);
43 private image_enum_proc_end_image(pdf_image_end_image_object);
44 private image_enum_proc_end_image(pdf_image_end_image_object2);
45 private image_enum_proc_end_image(pdf_image_end_image_cvd);
46 private IMAGE3_MAKE_MID_PROC(pdf_image3_make_mid);
47 private IMAGE3_MAKE_MCDE_PROC(pdf_image3_make_mcde);
48 private IMAGE3X_MAKE_MID_PROC(pdf_image3x_make_mid);
49 private IMAGE3X_MAKE_MCDE_PROC(pdf_image3x_make_mcde);
50
51 private const gx_image_enum_procs_t pdf_image_enum_procs = {
52 pdf_image_plane_data,
53 pdf_image_end_image
54 };
55 private const gx_image_enum_procs_t pdf_image_object_enum_procs = {
56 pdf_image_plane_data,
57 pdf_image_end_image_object
58 };
59 private const gx_image_enum_procs_t pdf_image_object_enum_procs2 = {
60 pdf_image_plane_data,
61 pdf_image_end_image_object2
62 };
63 private const gx_image_enum_procs_t pdf_image_cvd_enum_procs = {
64 gx_image1_plane_data,
65 pdf_image_end_image_cvd,
66 gx_image1_flush
67 };
68
69 /* ---------------- Driver procedures ---------------- */
70
71 /* Define the structure for keeping track of progress through an image. */
72 typedef struct pdf_image_enum_s {
73 gx_image_enum_common;
74 gs_memory_t *memory;
75 int width;
76 int bits_per_pixel; /* bits per pixel (per plane) */
77 int rows_left;
78 pdf_image_writer writer;
79 gs_matrix mat;
80 } pdf_image_enum;
81 gs_private_st_composite(st_pdf_image_enum, pdf_image_enum, "pdf_image_enum",
82 pdf_image_enum_enum_ptrs, pdf_image_enum_reloc_ptrs);
83 /* GC procedures */
84 private ENUM_PTRS_WITH(pdf_image_enum_enum_ptrs, pdf_image_enum *pie)
85 if (index < pdf_image_writer_max_ptrs) {
86 gs_ptr_type_t ret =
87 ENUM_USING(st_pdf_image_writer, &pie->writer, sizeof(pie->writer),
88 index);
89
90 if (ret == 0) /* don't stop early */
91 ENUM_RETURN(0);
92 return ret;
93 }
94 return ENUM_USING_PREFIX(st_gx_image_enum_common,
95 pdf_image_writer_max_ptrs);
96 ENUM_PTRS_END
RELOC_PTRS_WITH(pdf_image_enum_reloc_ptrs,pdf_image_enum * pie)97 private RELOC_PTRS_WITH(pdf_image_enum_reloc_ptrs, pdf_image_enum *pie)
98 {
99 RELOC_USING(st_pdf_image_writer, &pie->writer, sizeof(pie->writer));
100 RELOC_USING(st_gx_image_enum_common, vptr, size);
101 }
102 RELOC_PTRS_END
103
104 /*
105 * Test whether we can write an image in-line. This is always true,
106 * because we only support PDF 1.2 and later.
107 */
108 private bool
can_write_image_in_line(const gx_device_pdf * pdev,const gs_image_t * pim)109 can_write_image_in_line(const gx_device_pdf *pdev, const gs_image_t *pim)
110 {
111 return true;
112 }
113
114 /*
115 * Convert a Type 4 image to a Type 1 masked image if possible.
116 * Type 1 masked images are more compact, and are supported in all PDF
117 * versions, whereas general masked images require PDF 1.3 or higher.
118 * Also, Acrobat 5 for Windows has a bug that causes an error for images
119 * with a color-key mask, at least for 1-bit-deep images using an Indexed
120 * color space.
121 */
122 private int
color_is_black_or_white(gx_device * dev,const gx_drawing_color * pdcolor)123 color_is_black_or_white(gx_device *dev, const gx_drawing_color *pdcolor)
124 {
125 return (!color_is_pure(pdcolor) ? -1 :
126 gx_dc_pure_color(pdcolor) == gx_device_black(dev) ? 0 :
127 gx_dc_pure_color(pdcolor) == gx_device_white(dev) ? 1 : -1);
128 }
129 private int
pdf_convert_image4_to_image1(gx_device_pdf * pdev,const gs_imager_state * pis,const gx_drawing_color * pbcolor,const gs_image4_t * pim4,gs_image_t * pim1,gx_drawing_color * pdcolor)130 pdf_convert_image4_to_image1(gx_device_pdf *pdev,
131 const gs_imager_state *pis,
132 const gx_drawing_color *pbcolor,
133 const gs_image4_t *pim4, gs_image_t *pim1,
134 gx_drawing_color *pdcolor)
135 {
136 if (pim4->BitsPerComponent == 1 &&
137 (pim4->MaskColor_is_range ?
138 pim4->MaskColor[0] | pim4->MaskColor[1] :
139 pim4->MaskColor[0]) <= 1
140 ) {
141 gx_device *const dev = (gx_device *)pdev;
142 const gs_color_space *pcs = pim4->ColorSpace;
143 bool write_1s = !pim4->MaskColor[0];
144 gs_client_color cc;
145 int code;
146
147 /*
148 * Prepare the drawing color. (pdf_prepare_imagemask will set it.)
149 * This is the other color in the image (the one that isn't the
150 * mask key), taking Decode into account.
151 */
152
153 cc.paint.values[0] = pim4->Decode[(int)write_1s];
154 cc.pattern = 0;
155 code = pcs->type->remap_color(&cc, pcs, pdcolor, pis, dev,
156 gs_color_select_texture);
157 if (code < 0)
158 return code;
159
160 /*
161 * The PDF imaging model doesn't support RasterOp. We can convert a
162 * Type 4 image to a Type 1 imagemask only if the effective RasterOp
163 * passes through the source color unchanged. "Effective" means we
164 * take into account CombineWithColor, and whether the source and/or
165 * texture are black, white, or neither.
166 */
167 {
168 gs_logical_operation_t lop = pis->log_op;
169 int black_or_white = color_is_black_or_white(dev, pdcolor);
170
171 switch (black_or_white) {
172 case 0: lop = lop_know_S_0(lop); break;
173 case 1: lop = lop_know_S_1(lop); break;
174 default: DO_NOTHING;
175 }
176 if (pim4->CombineWithColor)
177 switch (color_is_black_or_white(dev, pbcolor)) {
178 case 0: lop = lop_know_T_0(lop); break;
179 case 1: lop = lop_know_T_1(lop); break;
180 default: DO_NOTHING;
181 }
182 else
183 lop = lop_know_T_0(lop);
184 switch (lop_rop(lop)) {
185 case rop3_0:
186 if (black_or_white != 0)
187 return -1;
188 break;
189 case rop3_1:
190 if (black_or_white != 1)
191 return -1;
192 break;
193 case rop3_S:
194 break;
195 default:
196 return -1;
197 }
198 if ((lop & lop_S_transparent) && black_or_white == 1)
199 return -1;
200 }
201
202 /* All conditions are met. Convert to a masked image. */
203
204 gs_image_t_init_mask_adjust(pim1, write_1s, false);
205 #define COPY_ELEMENT(e) pim1->e = pim4->e
206 COPY_ELEMENT(ImageMatrix);
207 COPY_ELEMENT(Width);
208 COPY_ELEMENT(Height);
209 pim1->BitsPerComponent = 1;
210 /* not Decode */
211 COPY_ELEMENT(Interpolate);
212 pim1->format = gs_image_format_chunky; /* BPC = 1, doesn't matter */
213 #undef COPY_ELEMENT
214 return 0;
215 }
216 return -1; /* arbitrary <0 */
217 }
218
219 private int
pdf_begin_image_data_decoded(gx_device_pdf * pdev,int num_components,const gs_range_t * pranges,int i,gs_pixel_image_t * pi,cos_value_t * cs_value,pdf_image_enum * pie)220 pdf_begin_image_data_decoded(gx_device_pdf *pdev, int num_components, const gs_range_t *pranges, int i,
221 gs_pixel_image_t *pi, cos_value_t *cs_value, pdf_image_enum *pie)
222 {
223
224 if (pranges) {
225 /* Rescale the Decode values for the image data. */
226 const gs_range_t *pr = pranges;
227 float *decode = pi->Decode;
228 int j;
229
230 for (j = 0; j < num_components; ++j, ++pr, decode += 2) {
231 double vmin = decode[0], vmax = decode[1];
232 double base = pr->rmin, factor = pr->rmax - base;
233
234 decode[1] = (vmax - vmin) / factor + (vmin - base);
235 decode[0] = vmin - base;
236 }
237 }
238 return pdf_begin_image_data(pdev, &pie->writer, pi, cs_value, i);
239 }
240
241 /*
242 * Start processing an image. This procedure takes extra arguments because
243 * it has to do something slightly different for the parts of an ImageType 3
244 * image.
245 */
246 typedef enum {
247 PDF_IMAGE_DEFAULT,
248 PDF_IMAGE_TYPE3_MASK, /* no in-line, don't render */
249 PDF_IMAGE_TYPE3_DATA /* no in-line */
250 } pdf_typed_image_context_t;
251 private int
pdf_begin_typed_image(gx_device_pdf * pdev,const gs_imager_state * pis,const gs_matrix * pmat,const gs_image_common_t * pic,const gs_int_rect * prect,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * mem,gx_image_enum_common_t ** pinfo,pdf_typed_image_context_t context)252 pdf_begin_typed_image(gx_device_pdf *pdev, const gs_imager_state * pis,
253 const gs_matrix *pmat, const gs_image_common_t *pic,
254 const gs_int_rect * prect,
255 const gx_drawing_color * pdcolor,
256 const gx_clip_path * pcpath, gs_memory_t * mem,
257 gx_image_enum_common_t ** pinfo,
258 pdf_typed_image_context_t context)
259 {
260 cos_dict_t *pnamed = 0;
261 const gs_pixel_image_t *pim;
262 int code, i;
263 pdf_image_enum *pie;
264 gs_image_format_t format;
265 const gs_color_space *pcs;
266 gs_color_space cs_gray_temp;
267 cos_value_t cs_value;
268 int num_components;
269 bool is_mask = false, in_line = false;
270 gs_int_rect rect;
271 /*
272 * We define this union because psdf_setup_image_filters may alter the
273 * gs_pixel_image_t part, but pdf_begin_image_data must also have access
274 * to the type-specific parameters.
275 */
276 union iu_ {
277 gs_pixel_image_t pixel; /* we may change some components */
278 gs_image1_t type1;
279 gs_image3_t type3;
280 gs_image3x_t type3x;
281 gs_image4_t type4;
282 } image[4];
283 int width, height;
284 const gs_range_t *pranges = 0;
285 const pdf_color_space_names_t *names;
286 bool convert_to_process_colors = false;
287 pdf_lcvd_t *cvd = NULL;
288
289 /*
290 * Pop the image name from the NI stack. We must do this, to keep the
291 * stack in sync, even if it turns out we can't handle the image.
292 */
293 {
294 cos_value_t ni_value;
295
296 if (cos_array_unadd(pdev->NI_stack, &ni_value) >= 0)
297 pnamed = (cos_dict_t *)ni_value.contents.object;
298 }
299
300 /* An initialization for pdf_end_and_do_image :
301 We need to delay adding the "Mask" entry into a type 3 image dictionary
302 until the mask is completed due to equal image merging. */
303 pdev->image_mask_id = gs_no_id;
304
305 /* Check for the image types we can handle. */
306 switch (pic->type->index) {
307 case 1: {
308 const gs_image_t *pim1 = (const gs_image_t *)pic;
309
310 if (pim1->Alpha != gs_image_alpha_none)
311 goto nyi;
312 is_mask = pim1->ImageMask;
313 if (is_mask) {
314 /* If parameters are invalid, use the default implementation. */
315 if (pdcolor->type != &gx_dc_pattern)
316 if (pim1->BitsPerComponent != 1 ||
317 !((pim1->Decode[0] == 0.0 && pim1->Decode[1] == 1.0) ||
318 (pim1->Decode[0] == 1.0 && pim1->Decode[1] == 0.0))
319 )
320 goto nyi;
321 }
322 in_line = context == PDF_IMAGE_DEFAULT &&
323 can_write_image_in_line(pdev, pim1);
324 image[0].type1 = *pim1;
325 break;
326 }
327 case 3: {
328 const gs_image3_t *pim3 = (const gs_image3_t *)pic;
329 gs_image3_t pim3a;
330 const gs_image_common_t *pic1 = pic;
331 gs_matrix m, mi;
332 const gs_matrix *pmat1 = pmat;
333
334 pdev->image_mask_is_SMask = false;
335 if (pdev->CompatibilityLevel < 1.2)
336 goto nyi;
337 if (prect && !(prect->p.x == 0 && prect->p.y == 0 &&
338 prect->q.x == pim3->Width &&
339 prect->q.y == pim3->Height))
340 goto nyi;
341 if (pdev->CompatibilityLevel < 1.3 && !pdev->PatternImagemask) {
342 gs_make_identity(&m);
343 pmat1 = &m;
344 m.tx = floor(pis->ctm.tx + 0.5); /* Round the origin against the image size distorsions */
345 m.ty = floor(pis->ctm.ty + 0.5);
346 pim3a = *pim3;
347 gs_matrix_invert(&pim3a.ImageMatrix, &mi);
348 gs_make_identity(&pim3a.ImageMatrix);
349 if (pim3a.Width < pim3a.MaskDict.Width && pim3a.Width > 0) {
350 int sx = (pim3a.MaskDict.Width + pim3a.Width - 1) / pim3a.Width;
351
352 gs_matrix_scale(&mi, 1.0 / sx, 1, &mi);
353 gs_matrix_scale(&pim3a.ImageMatrix, 1.0 / sx, 1, &pim3a.ImageMatrix);
354 }
355 if (pim3a.Height < pim3a.MaskDict.Height && pim3a.Height > 0) {
356 int sy = (pim3a.MaskDict.Height + pim3a.Height - 1) / pim3a.Height;
357
358 gs_matrix_scale(&mi, 1, 1.0 / sy, &mi);
359 gs_matrix_scale(&pim3a.ImageMatrix, 1, 1.0 / sy, &pim3a.ImageMatrix);
360 }
361 gs_matrix_multiply(&mi, &pim3a.MaskDict.ImageMatrix, &pim3a.MaskDict.ImageMatrix);
362 pic1 = (gs_image_common_t *)&pim3a;
363 /* Setting pdev->converting_image_matrix to communicate with pdf_image3_make_mcde. */
364 gs_matrix_multiply(&mi, &ctm_only(pis), &pdev->converting_image_matrix);
365 }
366 /*
367 * We handle ImageType 3 images in a completely different way:
368 * the default implementation sets up the enumerator.
369 */
370 return gx_begin_image3_generic((gx_device *)pdev, pis, pmat1, pic1,
371 prect, pdcolor, pcpath, mem,
372 pdf_image3_make_mid,
373 pdf_image3_make_mcde, pinfo);
374 }
375 case IMAGE3X_IMAGETYPE: {
376 /* See ImageType3 above for more information. */
377 const gs_image3x_t *pim3x = (const gs_image3x_t *)pic;
378
379 if (pdev->CompatibilityLevel < 1.4)
380 goto nyi;
381 if (prect && !(prect->p.x == 0 && prect->p.y == 0 &&
382 prect->q.x == pim3x->Width &&
383 prect->q.y == pim3x->Height))
384 goto nyi;
385 pdev->image_mask_is_SMask = true;
386 return gx_begin_image3x_generic((gx_device *)pdev, pis, pmat, pic,
387 prect, pdcolor, pcpath, mem,
388 pdf_image3x_make_mid,
389 pdf_image3x_make_mcde, pinfo);
390 }
391 case 4: {
392 /* Try to convert the image to a plain masked image. */
393 gx_drawing_color icolor;
394
395 pdev->image_mask_is_SMask = false;
396 if (pdf_convert_image4_to_image1(pdev, pis, pdcolor,
397 (const gs_image4_t *)pic,
398 &image[0].type1, &icolor) >= 0) {
399 gs_state *pgs = (gs_state *)gx_hld_get_gstate_ptr(pis);
400
401 if (pgs == NULL)
402 return_error(gs_error_unregistered); /* Must not happen. */
403
404 /* Undo the pop of the NI stack if necessary. */
405 if (pnamed)
406 cos_array_add_object(pdev->NI_stack, COS_OBJECT(pnamed));
407 /* HACK: temporary patch the color space, to allow
408 pdf_prepare_imagemask to write the right color for the imagemask. */
409 code = gs_gsave(pgs);
410 if (code < 0)
411 return code;
412 code = gs_setcolorspace(pgs, ((const gs_image4_t *)pic)->ColorSpace);
413 if (code < 0)
414 return code;
415 code = pdf_begin_typed_image(pdev, pis, pmat,
416 (gs_image_common_t *)&image[0].type1,
417 prect, &icolor, pcpath, mem,
418 pinfo, context);
419 if (code < 0)
420 return code;
421 return gs_grestore(pgs);
422 }
423 /* No luck. Masked images require PDF 1.3 or higher. */
424 if (pdev->CompatibilityLevel < 1.2)
425 goto nyi;
426 if (pdev->CompatibilityLevel < 1.3 && !pdev->PatternImagemask) {
427 gs_matrix m, m1, mi;
428 gs_image4_t pi4 = *(const gs_image4_t *)pic;
429
430 gs_make_identity(&m1);
431 gs_matrix_invert(&pic->ImageMatrix, &mi);
432 gs_matrix_multiply(&mi, &ctm_only(pis), &m);
433 code = pdf_setup_masked_image_converter(pdev, mem, &m, &cvd,
434 true, 0, 0, pi4.Width, pi4.Height, false);
435 if (code < 0)
436 return code;
437 cvd->mdev.is_open = true; /* fixme: same as above. */
438 cvd->mask->is_open = true; /* fixme: same as above. */
439 cvd->mask_is_empty = false;
440 code = (*dev_proc(cvd->mask, fill_rectangle))((gx_device *)cvd->mask,
441 0, 0, cvd->mask->width, cvd->mask->height, (gx_color_index)0);
442 if (code < 0)
443 return code;
444 gx_device_retain((gx_device *)cvd, true);
445 gx_device_retain((gx_device *)cvd->mask, true);
446 gs_make_identity(&pi4.ImageMatrix);
447 code = gx_default_begin_typed_image((gx_device *)cvd,
448 pis, &m1, (gs_image_common_t *)&pi4, prect, pdcolor, NULL, mem, pinfo);
449 if (code < 0)
450 return code;
451 (*pinfo)->procs = &pdf_image_cvd_enum_procs;
452 return 0;
453 }
454 image[0].type4 = *(const gs_image4_t *)pic;
455 break;
456 }
457 default:
458 goto nyi;
459 }
460 pim = (const gs_pixel_image_t *)pic;
461 format = pim->format;
462 switch (format) {
463 case gs_image_format_chunky:
464 case gs_image_format_component_planar:
465 break;
466 default:
467 goto nyi;
468 }
469 /* AR5 on Windows doesn't support 0-size images. Skipping. */
470 if (pim->Width == 0 || pim->Height == 0)
471 goto nyi;
472 /* PDF doesn't support images with more than 8 bits per component. */
473 if (pim->BitsPerComponent > 8)
474 goto nyi;
475 pcs = pim->ColorSpace;
476 num_components = (is_mask ? 1 : gs_color_space_num_components(pcs));
477
478 if (pdf_must_put_clip_path(pdev, pcpath))
479 code = pdf_unclip(pdev);
480 else
481 code = pdf_open_page(pdev, PDF_IN_STREAM);
482 if (code < 0)
483 return code;
484 if (context == PDF_IMAGE_TYPE3_MASK) {
485 /*
486 * The soft mask for an ImageType 3x image uses a DevicePixel
487 * color space, which pdf_color_space() can't handle. Patch it
488 * to DeviceGray here.
489 */
490 gs_cspace_init_DeviceGray(pdev->memory, &cs_gray_temp);
491 pcs = &cs_gray_temp;
492 } else if (is_mask)
493 code = pdf_prepare_imagemask(pdev, pis, pdcolor);
494 else
495 code = pdf_prepare_image(pdev, pis);
496 if (code < 0)
497 goto nyi;
498 code = pdf_put_clip_path(pdev, pcpath);
499 if (code < 0)
500 return code;
501 if (prect)
502 rect = *prect;
503 else {
504 rect.p.x = rect.p.y = 0;
505 rect.q.x = pim->Width, rect.q.y = pim->Height;
506 }
507 pie = gs_alloc_struct(mem, pdf_image_enum, &st_pdf_image_enum,
508 "pdf_begin_image");
509 if (pie == 0)
510 return_error(gs_error_VMerror);
511 memset(pie, 0, sizeof(*pie)); /* cleanup entirely for GC to work in all cases. */
512 *pinfo = (gx_image_enum_common_t *) pie;
513 gx_image_enum_common_init(*pinfo, (const gs_data_image_t *) pim,
514 ((pdev->CompatibilityLevel >= 1.3) ?
515 (context == PDF_IMAGE_TYPE3_MASK ?
516 &pdf_image_object_enum_procs :
517 &pdf_image_enum_procs) :
518 context == PDF_IMAGE_TYPE3_MASK ?
519 &pdf_image_object_enum_procs :
520 context == PDF_IMAGE_TYPE3_DATA ?
521 &pdf_image_object_enum_procs2 :
522 &pdf_image_enum_procs),
523 (gx_device *)pdev, num_components, format);
524 pie->memory = mem;
525 width = rect.q.x - rect.p.x;
526 pie->width = width;
527 height = rect.q.y - rect.p.y;
528 pie->bits_per_pixel =
529 pim->BitsPerComponent * num_components / pie->num_planes;
530 pie->rows_left = height;
531 if (pnamed != 0) /* Don't in-line the image if it is named. */
532 in_line = false;
533 else {
534 double nbytes = (double)(((ulong) pie->width * pie->bits_per_pixel + 7) >> 3) *
535 pie->num_planes * pie->rows_left;
536
537 in_line &= (nbytes < pdev->MaxInlineImageSize);
538 }
539 if (rect.p.x != 0 || rect.p.y != 0 ||
540 rect.q.x != pim->Width || rect.q.y != pim->Height ||
541 (is_mask && pim->CombineWithColor)
542 /* Color space setup used to be done here: see SRZB comment below. */
543 ) {
544 gs_free_object(mem, pie, "pdf_begin_image");
545 goto nyi;
546 }
547 if (pmat == 0)
548 pmat = &ctm_only(pis);
549 {
550 gs_matrix mat;
551 gs_matrix bmat;
552 int code;
553
554 pdf_make_bitmap_matrix(&bmat, -rect.p.x, -rect.p.y,
555 pim->Width, pim->Height, height);
556 if ((code = gs_matrix_invert(&pim->ImageMatrix, &mat)) < 0 ||
557 (code = gs_matrix_multiply(&bmat, &mat, &mat)) < 0 ||
558 (code = gs_matrix_multiply(&mat, pmat, &pie->mat)) < 0
559 ) {
560 gs_free_object(mem, pie, "pdf_begin_image");
561 return code;
562 }
563 /* AR3,AR4 show no image when CTM is singular; AR5 reports an error */
564 if (pie->mat.xx * pie->mat.yy == pie->mat.xy * pie->mat.yx) {
565 gs_free_object(mem, pie, "pdf_begin_image");
566 goto nyi;
567 }
568 }
569 pdf_image_writer_init(&pie->writer);
570 pie->writer.alt_writer_count = (in_line ||
571 (pim->Width <= 64 && pim->Height <= 64) ||
572 pdev->transfer_not_identity ? 1 : 2);
573 image[1] = image[0];
574 names = (in_line ? &pdf_color_space_names_short : &pdf_color_space_names);
575 if (psdf_is_converting_image_to_RGB((gx_device_psdf *)pdev, pis, pim)) {
576 /* psdf_setup_image_filters may change the color space
577 * (in case of pdev->params.ConvertCMYKImagesToRGB == true).
578 * Account it here.
579 */
580 cos_c_string_value(&cs_value, names->DeviceRGB);
581 } else if (!is_mask) {
582 code = pdf_color_space(pdev, &cs_value, &pranges,
583 pcs,
584 names, in_line);
585 if (code < 0) {
586 const char *sname;
587
588 convert_to_process_colors = true;
589 switch (pdev->pcm_color_info_index) {
590 case gs_color_space_index_DeviceGray: sname = names->DeviceGray; break;
591 case gs_color_space_index_DeviceRGB: sname = names->DeviceRGB; break;
592 case gs_color_space_index_DeviceCMYK: sname = names->DeviceCMYK; break;
593 default:
594 eprintf("Unsupported ProcessColorModel.");
595 return_error(gs_error_undefined);
596 }
597 cos_c_string_value(&cs_value, sname);
598 }
599 }
600 if ((code = pdf_begin_write_image(pdev, &pie->writer, gs_no_id, width,
601 height, pnamed, in_line)) < 0 ||
602 /*
603 * Some regrettable PostScript code (such as LanguageLevel 1 output
604 * from Microsoft's PSCRIPT.DLL driver) misuses the transfer
605 * function to accomplish the equivalent of indexed color.
606 * Downsampling (well, only averaging) or JPEG compression are not
607 * compatible with this. Play it safe by using only lossless
608 * filters if the transfer function(s) is/are other than the
609 * identity.
610 */
611 (code = (pie->writer.alt_writer_count == 1 ?
612 psdf_setup_lossless_filters((gx_device_psdf *) pdev,
613 &pie->writer.binary[0],
614 &image[0].pixel) :
615 psdf_setup_image_filters((gx_device_psdf *) pdev,
616 &pie->writer.binary[0], &image[0].pixel,
617 pmat, pis, true))) < 0
618 )
619 goto fail;
620 if (convert_to_process_colors) {
621 code = psdf_setup_image_colors_filter(&pie->writer.binary[0],
622 (gx_device_psdf *)pdev, &image[0].pixel, pis,
623 pdev->pcm_color_info_index);
624 if (code < 0)
625 goto fail;
626 }
627 if (pie->writer.alt_writer_count > 1) {
628 code = pdf_make_alt_stream(pdev, &pie->writer.binary[1]);
629 if (code)
630 goto fail;
631 code = psdf_setup_image_filters((gx_device_psdf *) pdev,
632 &pie->writer.binary[1], &image[1].pixel,
633 pmat, pis, false);
634 if (code == gs_error_rangecheck) {
635 /* setup_image_compression rejected the alternative compression. */
636 pie->writer.alt_writer_count = 1;
637 memset(pie->writer.binary + 1, 0, sizeof(pie->writer.binary[1]));
638 memset(pie->writer.binary + 2, 0, sizeof(pie->writer.binary[1]));
639 } else if (code)
640 goto fail;
641 else if (convert_to_process_colors) {
642 code = psdf_setup_image_colors_filter(&pie->writer.binary[1],
643 (gx_device_psdf *)pdev, &image[1].pixel, pis,
644 pdev->pcm_color_info_index);
645 if (code < 0)
646 goto fail;
647 }
648 }
649 for (i = 0; i < pie->writer.alt_writer_count; i++) {
650 code = pdf_begin_image_data_decoded(pdev, num_components, pranges, i,
651 &image[i].pixel, &cs_value, pie);
652 if (code < 0)
653 goto fail;
654 }
655 if (pie->writer.alt_writer_count == 2) {
656 psdf_setup_compression_chooser(&pie->writer.binary[2],
657 (gx_device_psdf *)pdev, pim->Width, pim->Height,
658 num_components, pim->BitsPerComponent);
659 pie->writer.alt_writer_count = 3;
660 }
661 if (pic->type->index == 4 && pdev->CompatibilityLevel < 1.3) {
662 int i;
663
664 /* Create a stream for writing the mask. */
665 i = pie->writer.alt_writer_count;
666 gs_image_t_init_mask_adjust((gs_image_t *)&image[i].type1, true, false);
667 image[i].type1.Width = image[0].pixel.Width;
668 image[i].type1.Height = image[0].pixel.Height;
669 /* Won't use image[2]. */
670 code = pdf_begin_write_image(pdev, &pie->writer, gs_no_id, width,
671 height, NULL, false);
672 if (code)
673 goto fail;
674 code = psdf_setup_image_filters((gx_device_psdf *) pdev,
675 &pie->writer.binary[i], &image[i].pixel,
676 pmat, pis, true);
677 if (code < 0)
678 goto fail;
679 psdf_setup_image_to_mask_filter(&pie->writer.binary[i],
680 (gx_device_psdf *)pdev, pim->Width, pim->Height,
681 num_components, pim->BitsPerComponent, image[i].type4.MaskColor);
682 code = pdf_begin_image_data_decoded(pdev, num_components, pranges, i,
683 &image[i].pixel, &cs_value, pie);
684 if (code < 0)
685 goto fail;
686 ++pie->writer.alt_writer_count;
687 /* Note : Possible values for alt_writer_count are 1,2,3, 4.
688 1 means no alternative streams.
689 2 means the main image stream and a mask stream while converting
690 an Image Type 4.
691 3 means the main image steram, alternative image compression stream,
692 and the compression chooser.
693 4 meams 3 and a mask stream while convertingh an Image Type 4.
694 */
695 }
696 return 0;
697 fail:
698 /****** SHOULD FREE STRUCTURES AND CLEAN UP HERE ******/
699 /* Fall back to the default implementation. */
700 nyi:
701 return gx_default_begin_typed_image
702 ((gx_device *)pdev, pis, pmat, pic, prect, pdcolor, pcpath, mem,
703 pinfo);
704 }
705 int
gdev_pdf_begin_typed_image(gx_device * dev,const gs_imager_state * pis,const gs_matrix * pmat,const gs_image_common_t * pic,const gs_int_rect * prect,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * mem,gx_image_enum_common_t ** pinfo)706 gdev_pdf_begin_typed_image(gx_device * dev, const gs_imager_state * pis,
707 const gs_matrix *pmat, const gs_image_common_t *pic,
708 const gs_int_rect * prect,
709 const gx_drawing_color * pdcolor,
710 const gx_clip_path * pcpath, gs_memory_t * mem,
711 gx_image_enum_common_t ** pinfo)
712 {
713 return pdf_begin_typed_image((gx_device_pdf *)dev, pis, pmat, pic, prect,
714 pdcolor, pcpath, mem, pinfo,
715 PDF_IMAGE_DEFAULT);
716 }
717
718 /* ---------------- All images ---------------- */
719
720 /* Process the next piece of an image. */
721 private int
pdf_image_plane_data_alt(gx_image_enum_common_t * info,const gx_image_plane_t * planes,int height,int * rows_used,int alt_writer_index)722 pdf_image_plane_data_alt(gx_image_enum_common_t * info,
723 const gx_image_plane_t * planes, int height,
724 int *rows_used, int alt_writer_index)
725 {
726 pdf_image_enum *pie = (pdf_image_enum *) info;
727 int h = height;
728 int y;
729 /****** DOESN'T HANDLE IMAGES WITH VARYING WIDTH PER PLANE ******/
730 uint width_bits = pie->width * pie->plane_depths[0];
731 /****** DOESN'T HANDLE NON-ZERO data_x CORRECTLY ******/
732 uint bcount = (width_bits + 7) >> 3;
733 uint ignore;
734 int nplanes = pie->num_planes;
735 int status = 0;
736
737 if (h > pie->rows_left)
738 h = pie->rows_left;
739 for (y = 0; y < h; ++y) {
740 if (nplanes > 1) {
741 /*
742 * We flip images in blocks, and each block except the last one
743 * must contain an integral number of pixels. The easiest way
744 * to meet this condition is for all blocks except the last to
745 * be a multiple of 3 source bytes (guaranteeing an integral
746 * number of 1/2/4/8/12-bit samples), i.e., 3*nplanes flipped
747 * bytes. This requires a buffer of at least
748 * 3*GS_IMAGE_MAX_COMPONENTS bytes.
749 */
750 int pi;
751 uint count = bcount;
752 uint offset = 0;
753 #define ROW_BYTES max(200 /*arbitrary*/, 3 * GS_IMAGE_MAX_COMPONENTS)
754 const byte *bit_planes[GS_IMAGE_MAX_COMPONENTS];
755 int block_bytes = ROW_BYTES / (3 * nplanes) * 3;
756 byte row[ROW_BYTES];
757
758 for (pi = 0; pi < nplanes; ++pi)
759 bit_planes[pi] = planes[pi].data + planes[pi].raster * y;
760 while (count) {
761 uint flip_count;
762 uint flipped_count;
763
764 if (count >= block_bytes) {
765 flip_count = block_bytes;
766 flipped_count = block_bytes * nplanes;
767 } else {
768 flip_count = count;
769 flipped_count =
770 (width_bits % (block_bytes * 8) * nplanes + 7) >> 3;
771 }
772 image_flip_planes(row, bit_planes, offset, flip_count,
773 nplanes, pie->plane_depths[0]);
774 status = sputs(pie->writer.binary[alt_writer_index].strm, row,
775 flipped_count, &ignore);
776 if (status < 0)
777 break;
778 offset += flip_count;
779 count -= flip_count;
780 }
781 } else {
782 status = sputs(pie->writer.binary[alt_writer_index].strm,
783 planes[0].data + planes[0].raster * y, bcount,
784 &ignore);
785 }
786 if (status < 0)
787 break;
788 }
789 *rows_used = h;
790 if (status < 0)
791 return_error(gs_error_ioerror);
792 return !pie->rows_left;
793 #undef ROW_BYTES
794 }
795
796 private int
pdf_image_plane_data(gx_image_enum_common_t * info,const gx_image_plane_t * planes,int height,int * rows_used)797 pdf_image_plane_data(gx_image_enum_common_t * info,
798 const gx_image_plane_t * planes, int height,
799 int *rows_used)
800 {
801 pdf_image_enum *pie = (pdf_image_enum *) info;
802 int i;
803 for (i = 0; i < pie->writer.alt_writer_count; i++) {
804 int code = pdf_image_plane_data_alt(info, planes, height, rows_used, i);
805 if (code)
806 return code;
807 }
808 pie->rows_left -= *rows_used;
809 if (pie->writer.alt_writer_count > 2)
810 pdf_choose_compression(&pie->writer, false);
811 return !pie->rows_left;
812 }
813
814 private int
use_image_as_pattern(gx_device_pdf * pdev,pdf_resource_t * pres1,const gs_matrix * pmat,gs_id id)815 use_image_as_pattern(gx_device_pdf *pdev, pdf_resource_t *pres1,
816 const gs_matrix *pmat, gs_id id)
817 { /* See also dump_image in gdevpdfd.c . */
818 gs_imager_state s;
819 gs_pattern1_instance_t inst;
820 cos_value_t v;
821 const pdf_resource_t *pres;
822 int code;
823
824 memset(&s, 0, sizeof(s));
825 s.ctm.xx = pmat->xx;
826 s.ctm.xy = pmat->xy;
827 s.ctm.yx = pmat->yx;
828 s.ctm.yy = pmat->yy;
829 s.ctm.tx = pmat->tx;
830 s.ctm.ty = pmat->ty;
831 memset(&inst, 0, sizeof(inst));
832 inst.saved = (gs_state *)&s; /* HACK : will use s.ctm only. */
833 inst.template.PaintType = 1;
834 inst.template.TilingType = 1;
835 inst.template.BBox.p.x = inst.template.BBox.p.y = 0;
836 inst.template.BBox.q.x = 1;
837 inst.template.BBox.q.y = 1;
838 inst.template.XStep = 2; /* Set 2 times bigger step against artifacts. */
839 inst.template.YStep = 2;
840 code = (*dev_proc(pdev, pattern_manage))((gx_device *)pdev,
841 id, &inst, pattern_manage__start_accum);
842 if (code >= 0)
843 pprintld1(pdev->strm, "/R%ld Do\n", pdf_resource_id(pres1));
844 pres = pdev->accumulating_substream_resource;
845 if (code >= 0)
846 code = pdf_add_resource(pdev, pdev->substream_Resources, "/XObject", pres1);
847 if (code >= 0)
848 code = (*dev_proc(pdev, pattern_manage))((gx_device *)pdev,
849 id, &inst, pattern_manage__finish_accum);
850 if (code >= 0)
851 code = (*dev_proc(pdev, pattern_manage))((gx_device *)pdev,
852 id, &inst, pattern_manage__load);
853 if (code >= 0) {
854 stream_puts(pdev->strm, "q ");
855 code = pdf_cs_Pattern_colored(pdev, &v);
856 }
857 if (code >= 0) {
858 cos_value_write(&v, pdev);
859 pprintld1(pdev->strm, " cs /R%ld scn ", pdf_resource_id(pres));
860 }
861 if (code >= 0) {
862 /* The image offset weas broken in gx_begin_image3_generic,
863 (see 'origin' in there).
864 As a temporary hack use the offset of the image.
865 fixme : This isn't generally correct,
866 because the mask may be "transpozed" against the image. */
867 gs_matrix m = pdev->converting_image_matrix;
868
869 m.tx = pmat->tx;
870 m.ty = pmat->ty;
871 code = pdf_do_image_by_id(pdev, pdev->image_mask_scale,
872 &m, true, pdev->image_mask_id);
873 stream_puts(pdev->strm, "Q\n");
874 }
875 return code;
876 }
877
878 typedef enum {
879 USE_AS_MASK,
880 USE_AS_IMAGE,
881 USE_AS_PATTERN
882 } pdf_image_usage_t;
883
884 /* Close PDF image and do it. */
885 private int
pdf_end_and_do_image(gx_device_pdf * pdev,pdf_image_writer * piw,const gs_matrix * mat,gs_id ps_bitmap_id,pdf_image_usage_t do_image)886 pdf_end_and_do_image(gx_device_pdf *pdev, pdf_image_writer *piw,
887 const gs_matrix *mat, gs_id ps_bitmap_id, pdf_image_usage_t do_image)
888 {
889 int code = pdf_end_write_image(pdev, piw);
890 pdf_resource_t *pres = piw->pres;
891
892 switch (code) {
893 default:
894 return code; /* error */
895 case 1:
896 code = 0;
897 break;
898 case 0:
899 if (do_image == USE_AS_IMAGE) {
900 if (pdev->image_mask_id != gs_no_id) {
901 char buf[20];
902
903 sprintf(buf, "%ld 0 R", pdev->image_mask_id);
904 code = cos_dict_put_string_copy((cos_dict_t *)pres->object,
905 pdev->image_mask_is_SMask ? "/SMask" : "/Mask", buf);
906 if (code < 0)
907 return code;
908 }
909 if (pdev->image_mask_skip)
910 code = 0;
911 else
912 code = pdf_do_image(pdev, pres, mat, true);
913 } else if (do_image == USE_AS_MASK) {
914 /* Provide data for pdf_do_image_by_id, which will be called through
915 use_image_as_pattern during the next call to this function.
916 See pdf_do_image about the meaning of 'scale'. */
917 const pdf_x_object_t *const pxo = (const pdf_x_object_t *)pres;
918
919 pdev->image_mask_scale = (double)pxo->data_height / pxo->height;
920 pdev->image_mask_id = pdf_resource_id(pres);
921 pdev->converting_image_matrix = *mat;
922 } else if (do_image == USE_AS_PATTERN)
923 code = use_image_as_pattern(pdev, pres, mat, ps_bitmap_id);
924 }
925 return code;
926 }
927
928 /* Clean up by releasing the buffers. */
929 private int
pdf_image_end_image_data(gx_image_enum_common_t * info,bool draw_last,pdf_image_usage_t do_image)930 pdf_image_end_image_data(gx_image_enum_common_t * info, bool draw_last,
931 pdf_image_usage_t do_image)
932 {
933 gx_device_pdf *pdev = (gx_device_pdf *)info->dev;
934 pdf_image_enum *pie = (pdf_image_enum *)info;
935 int height = pie->writer.height;
936 int data_height = height - pie->rows_left;
937 int code = 0;
938
939 if (pie->writer.pres)
940 ((pdf_x_object_t *)pie->writer.pres)->data_height = data_height;
941 else if (data_height > 0)
942 pdf_put_image_matrix(pdev, &pie->mat, (double)data_height / height);
943 if (data_height > 0) {
944 code = pdf_complete_image_data(pdev, &pie->writer, data_height,
945 pie->width, pie->bits_per_pixel);
946 if (code < 0)
947 return code;
948 code = pdf_end_image_binary(pdev, &pie->writer, data_height);
949 /* The call above possibly decreases pie->writer.alt_writer_count in 2. */
950 if (code < 0)
951 return code;
952 if (pie->writer.alt_writer_count == 2) {
953 /* We're converting a type 4 image into an imagemask with a pattern color. */
954 /* Since the type 3 image writes the mask first, do so here. */
955 pdf_image_writer writer = pie->writer;
956
957 writer.binary[0] = pie->writer.binary[1];
958 writer.pres = pie->writer.pres_mask;
959 writer.alt_writer_count = 1;
960 memset(&pie->writer.binary[1], 0, sizeof(pie->writer.binary[1]));
961 pie->writer.alt_writer_count--; /* For GC. */
962 pie->writer.pres_mask = 0; /* For GC. */
963 code = pdf_end_image_binary(pdev, &writer, data_height);
964 if (code < 0)
965 return code;
966 code = pdf_end_and_do_image(pdev, &writer, &pie->mat, info->id, USE_AS_MASK);
967 if (code < 0)
968 return code;
969 code = pdf_end_and_do_image(pdev, &pie->writer, &pie->mat, info->id, USE_AS_PATTERN);
970 } else
971 code = pdf_end_and_do_image(pdev, &pie->writer, &pie->mat, info->id, do_image);
972 pie->writer.alt_writer_count--; /* For GC. */
973 }
974 gs_free_object(pie->memory, pie, "pdf_end_image");
975 return code;
976 }
977
978 /* End a normal image, drawing it. */
979 private int
pdf_image_end_image(gx_image_enum_common_t * info,bool draw_last)980 pdf_image_end_image(gx_image_enum_common_t * info, bool draw_last)
981 {
982 return pdf_image_end_image_data(info, draw_last, USE_AS_IMAGE);
983 }
984
985 /* End an image converted with pdf_lcvd_t. */
986 private int
pdf_image_end_image_cvd(gx_image_enum_common_t * info,bool draw_last)987 pdf_image_end_image_cvd(gx_image_enum_common_t * info, bool draw_last)
988 { pdf_lcvd_t *cvd = (pdf_lcvd_t *)info->dev;
989 int code = pdf_dump_converted_image(cvd->pdev, cvd);
990 int code1 = gx_image1_end_image(info, draw_last);
991 int code2 = gs_closedevice((gx_device *)cvd->mask);
992 int code3 = gs_closedevice((gx_device *)cvd);
993
994 gs_free_object(cvd->mask->memory, (gx_device *)cvd->mask, "pdf_image_end_image_cvd");
995 gs_free_object(cvd->mdev.memory, (gx_device *)cvd, "pdf_image_end_image_cvd");
996 return code < 0 ? code : code1 < 0 ? code1 : code2 < 0 ? code2 : code3;
997 }
998 /* ---------------- Type 3/3x images ---------------- */
999
1000 /*
1001 * For both types of masked images, we create temporary dummy (null) devices
1002 * that forward the begin_typed_image call to the implementation above.
1003 */
1004 private int
pdf_make_mxd(gx_device ** pmxdev,gx_device * tdev,gs_memory_t * mem)1005 pdf_make_mxd(gx_device **pmxdev, gx_device *tdev, gs_memory_t *mem)
1006 {
1007 gx_device *fdev;
1008 int code = gs_copydevice(&fdev, (const gx_device *)&gs_null_device, mem);
1009
1010 if (code < 0)
1011 return code;
1012 gx_device_set_target((gx_device_forward *)fdev, tdev);
1013 *pmxdev = fdev;
1014 return 0;
1015 }
1016
1017 /* End the mask of an ImageType 3 image, not drawing it. */
1018 private int
pdf_image_end_image_object(gx_image_enum_common_t * info,bool draw_last)1019 pdf_image_end_image_object(gx_image_enum_common_t * info, bool draw_last)
1020 {
1021 return pdf_image_end_image_data(info, draw_last, USE_AS_MASK);
1022 }
1023 /* End the data of an ImageType 3 image, converting it into pattern. */
1024 private int
pdf_image_end_image_object2(gx_image_enum_common_t * info,bool draw_last)1025 pdf_image_end_image_object2(gx_image_enum_common_t * info, bool draw_last)
1026 {
1027 return pdf_image_end_image_data(info, draw_last, USE_AS_PATTERN);
1028 }
1029
1030 /* ---------------- Type 3 images ---------------- */
1031
1032 /* Implement the mask image device. */
1033 private dev_proc_begin_typed_image(pdf_mid_begin_typed_image);
1034 private int
pdf_image3_make_mid(gx_device ** pmidev,gx_device * dev,int width,int height,gs_memory_t * mem)1035 pdf_image3_make_mid(gx_device **pmidev, gx_device *dev, int width, int height,
1036 gs_memory_t *mem)
1037 {
1038 gx_device_pdf *pdev = (gx_device_pdf *)dev;
1039
1040 if (pdev->CompatibilityLevel < 1.3 && !pdev->PatternImagemask) {
1041 gs_matrix m;
1042 pdf_lcvd_t *cvd = NULL;
1043 int code;
1044
1045 gs_make_identity(&m);
1046 code = pdf_setup_masked_image_converter(pdev, mem, &m, &cvd,
1047 true, 0, 0, width, height, true);
1048 if (code < 0)
1049 return code;
1050 cvd->mask->target = (gx_device *)cvd; /* Temporary, just to communicate with
1051 pdf_image3_make_mcde. The latter will reset it. */
1052 cvd->mask_is_empty = false;
1053 *pmidev = (gx_device *)cvd->mask;
1054 return 0;
1055 } else {
1056 int code = pdf_make_mxd(pmidev, dev, mem);
1057
1058 if (code < 0)
1059 return code;
1060 set_dev_proc(*pmidev, begin_typed_image, pdf_mid_begin_typed_image);
1061 return 0;
1062 }
1063 }
1064 private int
pdf_mid_begin_typed_image(gx_device * dev,const gs_imager_state * pis,const gs_matrix * pmat,const gs_image_common_t * pic,const gs_int_rect * prect,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * mem,gx_image_enum_common_t ** pinfo)1065 pdf_mid_begin_typed_image(gx_device * dev, const gs_imager_state * pis,
1066 const gs_matrix *pmat, const gs_image_common_t *pic,
1067 const gs_int_rect * prect,
1068 const gx_drawing_color * pdcolor,
1069 const gx_clip_path * pcpath, gs_memory_t * mem,
1070 gx_image_enum_common_t ** pinfo)
1071 {
1072 /* The target of the null device is the pdfwrite device. */
1073 gx_device_pdf *const pdev = (gx_device_pdf *)
1074 ((gx_device_null *)dev)->target;
1075 return pdf_begin_typed_image
1076 (pdev, pis, pmat, pic, prect, pdcolor, pcpath, mem, pinfo,
1077 PDF_IMAGE_TYPE3_MASK);
1078 }
1079
1080 /* Implement the mask clip device. */
1081 private int
pdf_image3_make_mcde(gx_device * dev,const gs_imager_state * pis,const gs_matrix * pmat,const gs_image_common_t * pic,const gs_int_rect * prect,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * mem,gx_image_enum_common_t ** pinfo,gx_device ** pmcdev,gx_device * midev,gx_image_enum_common_t * pminfo,const gs_int_point * origin)1082 pdf_image3_make_mcde(gx_device *dev, const gs_imager_state *pis,
1083 const gs_matrix *pmat, const gs_image_common_t *pic,
1084 const gs_int_rect *prect, const gx_drawing_color *pdcolor,
1085 const gx_clip_path *pcpath, gs_memory_t *mem,
1086 gx_image_enum_common_t **pinfo,
1087 gx_device **pmcdev, gx_device *midev,
1088 gx_image_enum_common_t *pminfo,
1089 const gs_int_point *origin)
1090 {
1091 int code;
1092 gx_device_pdf *pdev = (gx_device_pdf *)dev;
1093
1094 if (pdev->CompatibilityLevel < 1.3 && !pdev->PatternImagemask) {
1095 /* pdf_image3_make_mid must set midev with a pdf_lcvd_t instance.*/
1096 pdf_lcvd_t *cvd = (pdf_lcvd_t *)((gx_device_memory *)midev)->target;
1097
1098 ((gx_device_memory *)midev)->target = NULL;
1099 cvd->m = pdev->converting_image_matrix;
1100 cvd->mdev.mapped_x = origin->x;
1101 cvd->mdev.mapped_y = origin->y;
1102 *pmcdev = (gx_device *)&cvd->mdev;
1103 code = gx_default_begin_typed_image
1104 ((gx_device *)&cvd->mdev, pis, pmat, pic, prect, pdcolor, pcpath, mem,
1105 pinfo);
1106 } else {
1107 code = pdf_make_mxd(pmcdev, midev, mem);
1108 if (code < 0)
1109 return code;
1110 code = pdf_begin_typed_image
1111 ((gx_device_pdf *)dev, pis, pmat, pic, prect, pdcolor, pcpath, mem,
1112 pinfo, PDF_IMAGE_TYPE3_DATA);
1113 }
1114 /* Due to equal image merging, we delay the adding of the "Mask" entry into
1115 a type 3 image dictionary until the mask is completed.
1116 Will do in pdf_end_and_do_image.*/
1117 return 0;
1118 }
1119
1120 /* ---------------- Type 3x images ---------------- */
1121
1122 /* Implement the mask image device. */
1123 private int
pdf_image3x_make_mid(gx_device ** pmidev,gx_device * dev,int width,int height,int depth,gs_memory_t * mem)1124 pdf_image3x_make_mid(gx_device **pmidev, gx_device *dev, int width, int height,
1125 int depth, gs_memory_t *mem)
1126 {
1127 int code = pdf_make_mxd(pmidev, dev, mem);
1128
1129 if (code < 0)
1130 return code;
1131 set_dev_proc(*pmidev, begin_typed_image, pdf_mid_begin_typed_image);
1132 return 0;
1133 }
1134
1135 /* Implement the mask clip device. */
1136 private int
pdf_image3x_make_mcde(gx_device * dev,const gs_imager_state * pis,const gs_matrix * pmat,const gs_image_common_t * pic,const gs_int_rect * prect,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * mem,gx_image_enum_common_t ** pinfo,gx_device ** pmcdev,gx_device * midev[2],gx_image_enum_common_t * pminfo[2],const gs_int_point origin[2],const gs_image3x_t * pim)1137 pdf_image3x_make_mcde(gx_device *dev, const gs_imager_state *pis,
1138 const gs_matrix *pmat, const gs_image_common_t *pic,
1139 const gs_int_rect *prect,
1140 const gx_drawing_color *pdcolor,
1141 const gx_clip_path *pcpath, gs_memory_t *mem,
1142 gx_image_enum_common_t **pinfo,
1143 gx_device **pmcdev, gx_device *midev[2],
1144 gx_image_enum_common_t *pminfo[2],
1145 const gs_int_point origin[2],
1146 const gs_image3x_t *pim)
1147 {
1148 int code;
1149 pdf_image_enum *pmie;
1150 pdf_image_enum *pmce;
1151 cos_stream_t *pmcs;
1152 int i;
1153 const gs_image3x_mask_t *pixm;
1154
1155 if (midev[0]) {
1156 if (midev[1])
1157 return_error(gs_error_rangecheck);
1158 i = 0, pixm = &pim->Opacity;
1159 } else if (midev[1])
1160 i = 1, pixm = &pim->Shape;
1161 else
1162 return_error(gs_error_rangecheck);
1163 code = pdf_make_mxd(pmcdev, midev[i], mem);
1164 if (code < 0)
1165 return code;
1166 code = pdf_begin_typed_image
1167 ((gx_device_pdf *)dev, pis, pmat, pic, prect, pdcolor, pcpath, mem,
1168 pinfo, PDF_IMAGE_TYPE3_DATA);
1169 if (code < 0)
1170 return code;
1171 if ((*pinfo)->procs != &pdf_image_enum_procs) {
1172 /* We couldn't handle the image. Bail out. */
1173 gx_image_end(*pinfo, false);
1174 gs_free_object(mem, *pmcdev, "pdf_image3x_make_mcde");
1175 return_error(gs_error_rangecheck);
1176 }
1177 pmie = (pdf_image_enum *)pminfo[i];
1178 pmce = (pdf_image_enum *)(*pinfo);
1179 pmcs = (cos_stream_t *)pmce->writer.pres->object;
1180 /*
1181 * Add the SMask entry to the image dictionary, and, if needed,
1182 * the Matte entry to the mask dictionary.
1183 */
1184 if (pixm->has_Matte) {
1185 int num_components =
1186 gs_color_space_num_components(pim->ColorSpace);
1187
1188 code = cos_dict_put_c_key_floats(
1189 (cos_dict_t *)pmie->writer.pres->object,
1190 "/Matte", pixm->Matte,
1191 num_components);
1192 if (code < 0)
1193 return code;
1194 }
1195 return cos_dict_put_c_key_object(cos_stream_dict(pmcs), "/SMask",
1196 pmie->writer.pres->object);
1197 }
1198
pdf_substitute_pattern(pdf_resource_t * pres)1199 pdf_resource_t *pdf_substitute_pattern(pdf_resource_t *pres)
1200 {
1201 pdf_pattern_t *ppat = (pdf_pattern_t *)pres;
1202
1203 return (pdf_resource_t *)(ppat->substitute != 0 ? ppat->substitute : ppat);
1204 }
1205
1206
1207 private int
check_unsubstituted2(gx_device_pdf * pdev,pdf_resource_t * pres0,pdf_resource_t * pres1)1208 check_unsubstituted2(gx_device_pdf * pdev, pdf_resource_t *pres0, pdf_resource_t *pres1)
1209 {
1210 pdf_pattern_t *ppat = (pdf_pattern_t *)pres0;
1211
1212 return ppat->substitute == NULL;
1213 }
1214
1215 private int
check_unsubstituted1(gx_device_pdf * pdev,pdf_resource_t * pres0)1216 check_unsubstituted1(gx_device_pdf * pdev, pdf_resource_t *pres0)
1217 {
1218 pdf_pattern_t *ppat = (pdf_pattern_t *)pres0;
1219
1220 return ppat->substitute != NULL;
1221 }
1222
1223 /*
1224 The pattern management device method.
1225 See gxdevcli.h about return codes.
1226 */
1227 int
gdev_pdf_pattern_manage(gx_device * pdev1,gx_bitmap_id id,gs_pattern1_instance_t * pinst,pattern_manage_t function)1228 gdev_pdf_pattern_manage(gx_device *pdev1, gx_bitmap_id id,
1229 gs_pattern1_instance_t *pinst, pattern_manage_t function)
1230 {
1231 gx_device_pdf *pdev = (gx_device_pdf *)pdev1;
1232 int code;
1233 pdf_resource_t *pres, *pres1;
1234
1235 switch (function) {
1236 case pattern_manage__can_accum:
1237 return 1;
1238 case pattern_manage__start_accum:
1239 code = pdf_enter_substream(pdev, resourcePattern, id, &pres, false,
1240 pdev->CompressFonts/* Have no better switch.*/);
1241 if (code < 0)
1242 return code;
1243 pres->rid = id;
1244 code = pdf_store_pattern1_params(pdev, pres, pinst);
1245 if (code < 0)
1246 return code;
1247 return 1;
1248 case pattern_manage__finish_accum:
1249 code = pdf_add_procsets(pdev->substream_Resources, pdev->procsets);
1250 if (code < 0)
1251 return code;
1252 pres = pres1 = pdev->accumulating_substream_resource;
1253 code = pdf_exit_substream(pdev);
1254 if (code < 0)
1255 return code;
1256 if (pdev->substituted_pattern_count > 300 &&
1257 pdev->substituted_pattern_drop_page != pdev->next_page) { /* arbitrary */
1258 pdf_drop_resources(pdev, resourcePattern, check_unsubstituted1);
1259 pdev->substituted_pattern_count = 0;
1260 pdev->substituted_pattern_drop_page = pdev->next_page;
1261 }
1262 code = pdf_find_same_resource(pdev, resourcePattern, &pres, check_unsubstituted2);
1263 if (code < 0)
1264 return code;
1265 if (code > 0) {
1266 pdf_pattern_t *ppat = (pdf_pattern_t *)pres1;
1267
1268 code = pdf_cancel_resource(pdev, pres1, resourcePattern);
1269 if (code < 0)
1270 return code;
1271 /* Do not remove pres1, because it keeps the substitution. */
1272 ppat->substitute = (pdf_pattern_t *)pres;
1273 pres->where_used |= pdev->used_mask;
1274 pdev->substituted_pattern_count++;
1275 } else if (pres->object->id < 0)
1276 pdf_reserve_object_id(pdev, pres, 0);
1277 return 1;
1278 case pattern_manage__load:
1279 pres = pdf_find_resource_by_gs_id(pdev, resourcePattern, id);
1280 if (pres == 0)
1281 return gs_error_undefined;
1282 pres = pdf_substitute_pattern(pres);
1283 code = pdf_add_resource(pdev, pdev->substream_Resources, "/Pattern", pres);
1284 if (code < 0)
1285 return code;
1286 return 1;
1287 case pattern_manage__shading_area:
1288 return 0;
1289 }
1290 return_error(gs_error_unregistered);
1291 }
1292
1293