1 /* Copyright (C) 1996, 2000 artofcode LLC. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify it
4 under the terms of the GNU General Public License as published by the
5 Free Software Foundation; either version 2 of the License, or (at your
6 option) any later version.
7
8 This program is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along
14 with this program; if not, write to the Free Software Foundation, Inc.,
15 59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16
17 */
18
19 /*$Id: gdevpdfi.c,v 1.24.2.1.2.1 2003/01/17 00:49:01 giles Exp $ */
20 /* Image handling for PDF-writing driver */
21 #include "gx.h"
22 #include "gserrors.h"
23 #include "gsdevice.h"
24 #include "gsflip.h"
25 #include "gdevpdfx.h"
26 #include "gdevpdfg.h"
27 #include "gdevpdfo.h" /* for data stream */
28 #include "gxcspace.h"
29 #include "gximage3.h"
30 #include "gximag3x.h"
31 #include "gsiparm4.h"
32
33 /* Forward references */
34 private image_enum_proc_plane_data(pdf_image_plane_data);
35 private image_enum_proc_end_image(pdf_image_end_image);
36 private image_enum_proc_end_image(pdf_image_end_image_object);
37 private IMAGE3_MAKE_MID_PROC(pdf_image3_make_mid);
38 private IMAGE3_MAKE_MCDE_PROC(pdf_image3_make_mcde);
39 private IMAGE3X_MAKE_MID_PROC(pdf_image3x_make_mid);
40 private IMAGE3X_MAKE_MCDE_PROC(pdf_image3x_make_mcde);
41
42 private const gx_image_enum_procs_t pdf_image_enum_procs = {
43 pdf_image_plane_data,
44 pdf_image_end_image
45 };
46 private const gx_image_enum_procs_t pdf_image_object_enum_procs = {
47 pdf_image_plane_data,
48 pdf_image_end_image_object
49 };
50
51 /* ---------------- Driver procedures ---------------- */
52
53 /* Define the structure for keeping track of progress through an image. */
54 typedef struct pdf_image_enum_s {
55 gx_image_enum_common;
56 gs_memory_t *memory;
57 int width;
58 int bits_per_pixel; /* bits per pixel (per plane) */
59 int rows_left;
60 pdf_image_writer writer;
61 gs_matrix mat;
62 } pdf_image_enum;
63 gs_private_st_composite(st_pdf_image_enum, pdf_image_enum, "pdf_image_enum",
64 pdf_image_enum_enum_ptrs, pdf_image_enum_reloc_ptrs);
65 /* GC procedures */
66 private ENUM_PTRS_WITH(pdf_image_enum_enum_ptrs, pdf_image_enum *pie)
67 if (index < pdf_image_writer_max_ptrs) {
68 gs_ptr_type_t ret =
69 ENUM_USING(st_pdf_image_writer, &pie->writer, sizeof(pie->writer),
70 index);
71
72 if (ret == 0) /* don't stop early */
73 ENUM_RETURN(0);
74 return ret;
75 }
76 return ENUM_USING_PREFIX(st_gx_image_enum_common,
77 pdf_image_writer_max_ptrs);
78 ENUM_PTRS_END
RELOC_PTRS_WITH(pdf_image_enum_reloc_ptrs,pdf_image_enum * pie)79 private RELOC_PTRS_WITH(pdf_image_enum_reloc_ptrs, pdf_image_enum *pie)
80 {
81 RELOC_USING(st_pdf_image_writer, &pie->writer, sizeof(pie->writer));
82 RELOC_USING(st_gx_image_enum_common, vptr, size);
83 }
84 RELOC_PTRS_END
85
86 /*
87 * Test whether we can write an image in-line. Before PDF 1.2, this is only
88 * allowed for masks, images in built-in color spaces, and images in Indexed
89 * color spaces based on these with a string lookup table.
90 */
91 private bool
can_write_image_in_line(const gx_device_pdf * pdev,const gs_image_t * pim)92 can_write_image_in_line(const gx_device_pdf *pdev, const gs_image_t *pim)
93 {
94 const gs_color_space *pcs;
95
96 if (pim->ImageMask)
97 return true;
98 if (pdev->CompatibilityLevel >= 1.2)
99 return true;
100 pcs = pim->ColorSpace;
101 cs:
102 switch (gs_color_space_get_index(pcs)) {
103 case gs_color_space_index_DeviceGray:
104 case gs_color_space_index_DeviceRGB:
105 case gs_color_space_index_DeviceCMYK:
106 return true;
107 case gs_color_space_index_Indexed:
108 if (pcs->params.indexed.use_proc)
109 return false;
110 pcs = (const gs_color_space *)&pcs->params.indexed.base_space;
111 goto cs;
112 default:
113 return false;
114 }
115 }
116
117 /*
118 * Start processing an image. This procedure takes extra arguments because
119 * it has to do something slightly different for the parts of an ImageType 3
120 * image.
121 */
122 typedef enum {
123 PDF_IMAGE_DEFAULT,
124 PDF_IMAGE_TYPE3_MASK, /* no in-line, don't render */
125 PDF_IMAGE_TYPE3_DATA /* no in-line */
126 } pdf_typed_image_context_t;
127 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)128 pdf_begin_typed_image(gx_device_pdf *pdev, const gs_imager_state * pis,
129 const gs_matrix *pmat, const gs_image_common_t *pic,
130 const gs_int_rect * prect,
131 const gx_drawing_color * pdcolor,
132 const gx_clip_path * pcpath, gs_memory_t * mem,
133 gx_image_enum_common_t ** pinfo,
134 pdf_typed_image_context_t context)
135 {
136 const gs_pixel_image_t *pim;
137 int code;
138 pdf_image_enum *pie;
139 gs_image_format_t format;
140 const gs_color_space *pcs;
141 gs_color_space cs_gray_temp;
142 cos_value_t cs_value;
143 int num_components;
144 bool is_mask = false, in_line = false;
145 gs_int_rect rect;
146 /*
147 * We define this union because psdf_setup_image_filters may alter the
148 * gs_pixel_image_t part, but pdf_begin_image_data must also have access
149 * to the type-specific parameters.
150 */
151 union iu_ {
152 gs_pixel_image_t pixel; /* we may change some components */
153 gs_image1_t type1;
154 gs_image3_t type3;
155 gs_image3x_t type3x;
156 gs_image4_t type4;
157 } image;
158 ulong nbytes;
159 int width, height;
160
161 /* Check for the image types we can handle. */
162 switch (pic->type->index) {
163 case 1: {
164 const gs_image_t *pim1 = (const gs_image_t *)pic;
165
166 if (pim1->Alpha != gs_image_alpha_none)
167 goto nyi;
168 is_mask = pim1->ImageMask;
169 in_line = context == PDF_IMAGE_DEFAULT &&
170 can_write_image_in_line(pdev, pim1);
171 image.type1 = *pim1;
172 break;
173 }
174 case 3: {
175 const gs_image3_t *pim3 = (const gs_image3_t *)pic;
176
177 if (pdev->CompatibilityLevel < 1.3)
178 goto nyi;
179 if (prect && !(prect->p.x == 0 && prect->p.y == 0 &&
180 prect->q.x == pim3->Width &&
181 prect->q.y == pim3->Height))
182 goto nyi;
183 /*
184 * We handle ImageType 3 images in a completely different way:
185 * the default implementation sets up the enumerator.
186 */
187 return gx_begin_image3_generic((gx_device *)pdev, pis, pmat, pic,
188 prect, pdcolor, pcpath, mem,
189 pdf_image3_make_mid,
190 pdf_image3_make_mcde, pinfo);
191 }
192 case IMAGE3X_IMAGETYPE: {
193 /* See ImageType3 above for more information. */
194 const gs_image3x_t *pim3x = (const gs_image3x_t *)pic;
195
196 if (pdev->CompatibilityLevel < 1.4)
197 goto nyi;
198 if (prect && !(prect->p.x == 0 && prect->p.y == 0 &&
199 prect->q.x == pim3x->Width &&
200 prect->q.y == pim3x->Height))
201 goto nyi;
202 return gx_begin_image3x_generic((gx_device *)pdev, pis, pmat, pic,
203 prect, pdcolor, pcpath, mem,
204 pdf_image3x_make_mid,
205 pdf_image3x_make_mcde, pinfo);
206 }
207 case 4:
208 if (pdev->CompatibilityLevel < 1.3)
209 goto nyi;
210 image.type4 = *(const gs_image4_t *)pic;
211 break;
212 default:
213 goto nyi;
214 }
215 pim = (const gs_pixel_image_t *)pic;
216 format = pim->format;
217 switch (format) {
218 case gs_image_format_chunky:
219 case gs_image_format_component_planar:
220 break;
221 default:
222 goto nyi;
223 }
224 pcs = pim->ColorSpace;
225 num_components = (is_mask ? 1 : gs_color_space_num_components(pcs));
226
227 code = pdf_open_page(pdev, PDF_IN_STREAM);
228 if (code < 0)
229 return code;
230 pdf_put_clip_path(pdev, pcpath);
231 if (context == PDF_IMAGE_TYPE3_MASK) {
232 /*
233 * The soft mask for an ImageType 3x image uses a DevicePixel
234 * color space, which pdf_color_space() can't handle. Patch it
235 * to DeviceGray here.
236 */
237 gs_cspace_init_DeviceGray(&cs_gray_temp);
238 pcs = &cs_gray_temp;
239 } else if (is_mask)
240 code = pdf_prepare_imagemask(pdev, pis, pdcolor);
241 else
242 code = pdf_prepare_image(pdev, pis);
243 if (code < 0)
244 goto nyi;
245 if (prect)
246 rect = *prect;
247 else {
248 rect.p.x = rect.p.y = 0;
249 rect.q.x = pim->Width, rect.q.y = pim->Height;
250 }
251 pie = gs_alloc_struct(mem, pdf_image_enum, &st_pdf_image_enum,
252 "pdf_begin_image");
253 if (pie == 0)
254 return_error(gs_error_VMerror);
255 *pinfo = (gx_image_enum_common_t *) pie;
256 gx_image_enum_common_init(*pinfo, (const gs_data_image_t *) pim,
257 (context == PDF_IMAGE_TYPE3_MASK ?
258 &pdf_image_object_enum_procs :
259 &pdf_image_enum_procs),
260 (gx_device *)pdev, num_components, format);
261 pie->memory = mem;
262 width = rect.q.x - rect.p.x;
263 pie->width = width;
264 height = rect.q.y - rect.p.y;
265 pie->bits_per_pixel =
266 pim->BitsPerComponent * num_components / pie->num_planes;
267 pie->rows_left = height;
268 nbytes = (((ulong) pie->width * pie->bits_per_pixel + 7) >> 3) *
269 pie->num_planes * pie->rows_left;
270 in_line &= nbytes <= MAX_INLINE_IMAGE_BYTES;
271 if (rect.p.x != 0 || rect.p.y != 0 ||
272 rect.q.x != pim->Width || rect.q.y != pim->Height ||
273 (is_mask && pim->CombineWithColor)
274 /* Color space setup used to be done here: see SRZB comment below. */
275 ) {
276 gs_free_object(mem, pie, "pdf_begin_image");
277 goto nyi;
278 }
279 if (pmat == 0)
280 pmat = &ctm_only(pis);
281 {
282 gs_matrix mat;
283 gs_matrix bmat;
284 int code;
285
286 pdf_make_bitmap_matrix(&bmat, -rect.p.x, -rect.p.y,
287 pim->Width, pim->Height, height);
288 if ((code = gs_matrix_invert(&pim->ImageMatrix, &mat)) < 0 ||
289 (code = gs_matrix_multiply(&bmat, &mat, &mat)) < 0 ||
290 (code = gs_matrix_multiply(&mat, pmat, &pie->mat)) < 0
291 ) {
292 gs_free_object(mem, pie, "pdf_begin_image");
293 return code;
294 }
295 }
296 if ((code = pdf_begin_write_image(pdev, &pie->writer, gs_no_id, width,
297 height, NULL, in_line)) < 0 ||
298 /*
299 * Some regrettable PostScript code (such as LanguageLevel 1 output
300 * from Microsoft's PSCRIPT.DLL driver) misuses the transfer
301 * function to accomplish the equivalent of indexed color.
302 * Downsampling (well, only averaging) or JPEG compression are not
303 * compatible with this. Play it safe by using only lossless
304 * filters if the transfer function(s) is/are other than the
305 * identity.
306 */
307 (code = (pdev->transfer_not_identity ?
308 psdf_setup_lossless_filters((gx_device_psdf *) pdev,
309 &pie->writer.binary,
310 &image.pixel) :
311 psdf_setup_image_filters((gx_device_psdf *) pdev,
312 &pie->writer.binary, &image.pixel,
313 pmat, pis))) < 0 ||
314 /* SRZB 2001-04-25/Bl
315 * Since psdf_setup_image_filters may change the color space
316 * (in case of pdev->params.ConvertCMYKImagesToRGB == true),
317 * we postpone the selection of the PDF color space to here:
318 */
319 (!is_mask &&
320 (code = pdf_color_space(pdev, &cs_value, image.pixel.ColorSpace,
321 (in_line ? &pdf_color_space_names_short :
322 &pdf_color_space_names), in_line)) < 0) ||
323 (code = pdf_begin_image_data(pdev, &pie->writer,
324 (const gs_pixel_image_t *)&image,
325 &cs_value)) < 0
326 ) {
327 /****** SHOULD FREE STRUCTURES AND CLEAN UP HERE ******/
328 goto nyi; /* fall back to default implementation */
329 }
330 return 0;
331 nyi:
332 return gx_default_begin_typed_image
333 ((gx_device *)pdev, pis, pmat, pic, prect, pdcolor, pcpath, mem,
334 pinfo);
335 }
336 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)337 gdev_pdf_begin_typed_image(gx_device * dev, const gs_imager_state * pis,
338 const gs_matrix *pmat, const gs_image_common_t *pic,
339 const gs_int_rect * prect,
340 const gx_drawing_color * pdcolor,
341 const gx_clip_path * pcpath, gs_memory_t * mem,
342 gx_image_enum_common_t ** pinfo)
343 {
344 return pdf_begin_typed_image((gx_device_pdf *)dev, pis, pmat, pic, prect,
345 pdcolor, pcpath, mem, pinfo,
346 PDF_IMAGE_DEFAULT);
347 }
348
349 /* ---------------- All images ---------------- */
350
351 /* Process the next piece of an image. */
352 private int
pdf_image_plane_data(gx_image_enum_common_t * info,const gx_image_plane_t * planes,int height,int * rows_used)353 pdf_image_plane_data(gx_image_enum_common_t * info,
354 const gx_image_plane_t * planes, int height,
355 int *rows_used)
356 {
357 gx_device_pdf *pdev = (gx_device_pdf *)info->dev;
358 pdf_image_enum *pie = (pdf_image_enum *) info;
359 int h = height;
360 int y;
361 /****** DOESN'T HANDLE IMAGES WITH VARYING WIDTH PER PLANE ******/
362 uint width_bits = pie->width * pie->plane_depths[0];
363 /****** DOESN'T HANDLE NON-ZERO data_x CORRECTLY ******/
364 uint bcount = (width_bits + 7) >> 3;
365 uint ignore;
366 int nplanes = pie->num_planes;
367 stream *s = pdev->streams.strm;
368 long pos = stell(s);
369 int code;
370 int status = 0;
371
372 if (h > pie->rows_left)
373 h = pie->rows_left;
374 pie->rows_left -= h;
375 for (y = 0; y < h; ++y) {
376 if (nplanes > 1) {
377 /*
378 * We flip images in blocks, and each block except the last one
379 * must contain an integral number of pixels. The easiest way
380 * to meet this condition is for all blocks except the last to
381 * be a multiple of 3 source bytes (guaranteeing an integral
382 * number of 1/2/4/8/12-bit samples), i.e., 3*nplanes flipped
383 * bytes. This requires a buffer of at least
384 * 3*GS_IMAGE_MAX_COMPONENTS bytes.
385 */
386 int pi;
387 uint count = bcount;
388 uint offset = 0;
389 #define ROW_BYTES max(200 /*arbitrary*/, 3 * GS_IMAGE_MAX_COMPONENTS)
390 const byte *bit_planes[GS_IMAGE_MAX_COMPONENTS];
391 int block_bytes = ROW_BYTES / (3 * nplanes) * 3;
392 byte row[ROW_BYTES];
393
394 for (pi = 0; pi < nplanes; ++pi)
395 bit_planes[pi] = planes[pi].data + planes[pi].raster * y;
396 while (count) {
397 uint flip_count;
398 uint flipped_count;
399
400 if (count >= block_bytes) {
401 flip_count = block_bytes;
402 flipped_count = block_bytes * nplanes;
403 } else {
404 flip_count = count;
405 flipped_count =
406 (width_bits % (block_bytes * 8) * nplanes + 7) >> 3;
407 }
408 image_flip_planes(row, bit_planes, offset, flip_count,
409 nplanes, pie->plane_depths[0]);
410 status = sputs(pie->writer.binary.strm, row, flipped_count,
411 &ignore);
412 if (status < 0)
413 break;
414 offset += flip_count;
415 count -= flip_count;
416 }
417 } else {
418 status = sputs(pie->writer.binary.strm,
419 planes[0].data + planes[0].raster * y, bcount,
420 &ignore);
421 }
422 if (status < 0)
423 break;
424 }
425 *rows_used = h;
426 if (status < 0)
427 return_error(gs_error_ioerror);
428 code = cos_stream_add_since(pie->writer.data, pos);
429 return (code < 0 ? code : !pie->rows_left);
430 #undef ROW_BYTES
431 }
432
433 /* Clean up by releasing the buffers. */
434 private int
pdf_image_end_image_data(gx_image_enum_common_t * info,bool draw_last,bool do_image)435 pdf_image_end_image_data(gx_image_enum_common_t * info, bool draw_last,
436 bool do_image)
437 {
438 gx_device_pdf *pdev = (gx_device_pdf *)info->dev;
439 pdf_image_enum *pie = (pdf_image_enum *)info;
440 int height = pie->writer.height;
441 int data_height = height - pie->rows_left;
442 int code;
443
444 if (pie->writer.pres)
445 ((pdf_x_object_t *)pie->writer.pres)->data_height = data_height;
446 else
447 pdf_put_image_matrix(pdev, &pie->mat,
448 (height == 0 || data_height == 0 ? 1.0 :
449 (double)data_height / height));
450 code = pdf_end_image_binary(pdev, &pie->writer, data_height);
451 if (code < 0)
452 return code;
453 code = pdf_end_write_image(pdev, &pie->writer);
454 switch (code) {
455 default:
456 return code; /* error */
457 case 1:
458 code = 0;
459 break;
460 case 0:
461 if (do_image)
462 code = pdf_do_image(pdev, pie->writer.pres, &pie->mat, true);
463 }
464 gs_free_object(pie->memory, pie, "pdf_end_image");
465 return code;
466 }
467
468 /* End a normal image, drawing it. */
469 private int
pdf_image_end_image(gx_image_enum_common_t * info,bool draw_last)470 pdf_image_end_image(gx_image_enum_common_t * info, bool draw_last)
471 {
472 return pdf_image_end_image_data(info, draw_last, true);
473 }
474
475 /* ---------------- Type 3/3x images ---------------- */
476
477 /*
478 * For both types of masked images, we create temporary dummy (null) devices
479 * that forward the begin_typed_image call to the implementation above.
480 */
481 private int
pdf_make_mxd(gx_device ** pmxdev,gx_device * tdev,gs_memory_t * mem)482 pdf_make_mxd(gx_device **pmxdev, gx_device *tdev, gs_memory_t *mem)
483 {
484 gx_device *fdev;
485 int code = gs_copydevice(&fdev, (const gx_device *)&gs_null_device, mem);
486
487 if (code < 0)
488 return code;
489 gx_device_set_target((gx_device_forward *)fdev, tdev);
490 *pmxdev = fdev;
491 return 0;
492 }
493
494 /* End the mask of an ImageType 3 image, not drawing it. */
495 private int
pdf_image_end_image_object(gx_image_enum_common_t * info,bool draw_last)496 pdf_image_end_image_object(gx_image_enum_common_t * info, bool draw_last)
497 {
498 return pdf_image_end_image_data(info, draw_last, false);
499 }
500
501 /* ---------------- Type 3 images ---------------- */
502
503 /* Implement the mask image device. */
504 private dev_proc_begin_typed_image(pdf_mid_begin_typed_image);
505 private int
pdf_image3_make_mid(gx_device ** pmidev,gx_device * dev,int width,int height,gs_memory_t * mem)506 pdf_image3_make_mid(gx_device **pmidev, gx_device *dev, int width, int height,
507 gs_memory_t *mem)
508 {
509 int code = pdf_make_mxd(pmidev, dev, mem);
510
511 if (code < 0)
512 return code;
513 set_dev_proc(*pmidev, begin_typed_image, pdf_mid_begin_typed_image);
514 return 0;
515 }
516 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)517 pdf_mid_begin_typed_image(gx_device * dev, const gs_imager_state * pis,
518 const gs_matrix *pmat, const gs_image_common_t *pic,
519 const gs_int_rect * prect,
520 const gx_drawing_color * pdcolor,
521 const gx_clip_path * pcpath, gs_memory_t * mem,
522 gx_image_enum_common_t ** pinfo)
523 {
524 /* The target of the null device is the pdfwrite device. */
525 gx_device_pdf *const pdev = (gx_device_pdf *)
526 ((gx_device_null *)dev)->target;
527 int code = pdf_begin_typed_image
528 (pdev, pis, pmat, pic, prect, pdcolor, pcpath, mem, pinfo,
529 PDF_IMAGE_TYPE3_MASK);
530
531 if (code < 0)
532 return code;
533 if ((*pinfo)->procs != &pdf_image_object_enum_procs) {
534 /* We couldn't handle the mask image. Bail out. */
535 /* (This is never supposed to happen.) */
536 return_error(gs_error_rangecheck);
537 }
538 return code;
539 }
540
541 /* Implement the mask clip device. */
542 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)543 pdf_image3_make_mcde(gx_device *dev, const gs_imager_state *pis,
544 const gs_matrix *pmat, const gs_image_common_t *pic,
545 const gs_int_rect *prect, const gx_drawing_color *pdcolor,
546 const gx_clip_path *pcpath, gs_memory_t *mem,
547 gx_image_enum_common_t **pinfo,
548 gx_device **pmcdev, gx_device *midev,
549 gx_image_enum_common_t *pminfo,
550 const gs_int_point *origin)
551 {
552 int code = pdf_make_mxd(pmcdev, midev, mem);
553 pdf_image_enum *pmie;
554 pdf_image_enum *pmce;
555 cos_stream_t *pmcs;
556
557 if (code < 0)
558 return code;
559 code = pdf_begin_typed_image
560 ((gx_device_pdf *)dev, pis, pmat, pic, prect, pdcolor, pcpath, mem,
561 pinfo, PDF_IMAGE_TYPE3_DATA);
562 if (code < 0)
563 return code;
564 /* Add the /Mask entry to the image dictionary. */
565 if ((*pinfo)->procs != &pdf_image_enum_procs) {
566 /* We couldn't handle the image. Bail out. */
567 gx_image_end(*pinfo, false);
568 gs_free_object(mem, *pmcdev, "pdf_image3_make_mcde");
569 return_error(gs_error_rangecheck);
570 }
571 pmie = (pdf_image_enum *)pminfo;
572 pmce = (pdf_image_enum *)(*pinfo);
573 pmcs = (cos_stream_t *)pmce->writer.pres->object;
574 return cos_dict_put_c_key_object(cos_stream_dict(pmcs), "/Mask",
575 pmie->writer.pres->object);
576 }
577
578 /* ---------------- Type 3x images ---------------- */
579
580 /* Implement the mask image device. */
581 private int
pdf_image3x_make_mid(gx_device ** pmidev,gx_device * dev,int width,int height,int depth,gs_memory_t * mem)582 pdf_image3x_make_mid(gx_device **pmidev, gx_device *dev, int width, int height,
583 int depth, gs_memory_t *mem)
584 {
585 int code = pdf_make_mxd(pmidev, dev, mem);
586
587 if (code < 0)
588 return code;
589 set_dev_proc(*pmidev, begin_typed_image, pdf_mid_begin_typed_image);
590 return 0;
591 }
592
593 /* Implement the mask clip device. */
594 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)595 pdf_image3x_make_mcde(gx_device *dev, const gs_imager_state *pis,
596 const gs_matrix *pmat, const gs_image_common_t *pic,
597 const gs_int_rect *prect,
598 const gx_drawing_color *pdcolor,
599 const gx_clip_path *pcpath, gs_memory_t *mem,
600 gx_image_enum_common_t **pinfo,
601 gx_device **pmcdev, gx_device *midev[2],
602 gx_image_enum_common_t *pminfo[2],
603 const gs_int_point origin[2],
604 const gs_image3x_t *pim)
605 {
606 int code;
607 pdf_image_enum *pmie;
608 pdf_image_enum *pmce;
609 cos_stream_t *pmcs;
610 int i;
611 const gs_image3x_mask_t *pixm;
612
613 if (midev[0]) {
614 if (midev[1])
615 return_error(gs_error_rangecheck);
616 i = 0, pixm = &pim->Opacity;
617 } else if (midev[1])
618 i = 1, pixm = &pim->Shape;
619 else
620 return_error(gs_error_rangecheck);
621 code = pdf_make_mxd(pmcdev, midev[i], mem);
622 if (code < 0)
623 return code;
624 code = pdf_begin_typed_image
625 ((gx_device_pdf *)dev, pis, pmat, pic, prect, pdcolor, pcpath, mem,
626 pinfo, PDF_IMAGE_TYPE3_DATA);
627 if (code < 0)
628 return code;
629 if ((*pinfo)->procs != &pdf_image_enum_procs) {
630 /* We couldn't handle the image. Bail out. */
631 gx_image_end(*pinfo, false);
632 gs_free_object(mem, *pmcdev, "pdf_image3x_make_mcde");
633 return_error(gs_error_rangecheck);
634 }
635 pmie = (pdf_image_enum *)pminfo[i];
636 pmce = (pdf_image_enum *)(*pinfo);
637 pmcs = (cos_stream_t *)pmce->writer.pres->object;
638 /*
639 * Add the SMask entry to the image dictionary, and, if needed,
640 * the Matte entry to the mask dictionary.
641 */
642 if (pixm->has_Matte) {
643 int num_components =
644 gs_color_space_num_components(pim->ColorSpace);
645
646 code = cos_dict_put_c_key_floats(
647 (cos_dict_t *)pmie->writer.pres->object,
648 "/Matte", pixm->Matte,
649 num_components);
650 if (code < 0)
651 return code;
652 }
653 return cos_dict_put_c_key_object(cos_stream_dict(pmcs), "/SMask",
654 pmie->writer.pres->object);
655 }
656