1 /* Copyright (C) 2001-2019 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.,  1305 Grant Avenue - Suite 200, Novato,
13    CA 94945, U.S.A., +1(415)492-9861, for further information.
14 */
15 
16 
17 /* Image handling for PDF-writing driver */
18 #include "memory_.h"
19 #include "math_.h"
20 #include "gx.h"
21 #include "gserrors.h"
22 #include "gsdevice.h"
23 #include "gsflip.h"
24 #include "gsstate.h"
25 #include "gscolor2.h"
26 #include "gdevpdfx.h"
27 #include "gdevpdfg.h"
28 #include "gdevpdfo.h"		/* for data stream */
29 #include "gxcspace.h"
30 #include "gximage3.h"
31 #include "gximag3x.h"
32 #include "gsiparm4.h"
33 #include "gxdcolor.h"
34 #include "gxpcolor.h"
35 #include "gxcolor2.h"
36 #include "gxhldevc.h"
37 #include "gxdevsop.h"
38 #include "gsicc_manage.h"
39 #include "gsform1.h"
40 #include "gxpath.h"
41 
42 /* Forward references */
43 static image_enum_proc_plane_data(pdf_image_plane_data);
44 static image_enum_proc_end_image(pdf_image_end_image);
45 static image_enum_proc_end_image(pdf_image_end_image_object);
46 static image_enum_proc_end_image(pdf_image_end_image_object2);
47 static image_enum_proc_end_image(pdf_image_end_image_cvd);
48 static IMAGE3_MAKE_MID_PROC(pdf_image3_make_mid);
49 static IMAGE3_MAKE_MCDE_PROC(pdf_image3_make_mcde);
50 static IMAGE3X_MAKE_MID_PROC(pdf_image3x_make_mid);
51 static IMAGE3X_MAKE_MCDE_PROC(pdf_image3x_make_mcde);
52 
53 static const gx_image_enum_procs_t pdf_image_enum_procs = {
54     pdf_image_plane_data,
55     pdf_image_end_image
56 };
57 static const gx_image_enum_procs_t pdf_image_object_enum_procs = {
58     pdf_image_plane_data,
59     pdf_image_end_image_object
60 };
61 static const gx_image_enum_procs_t pdf_image_object_enum_procs2 = {
62     pdf_image_plane_data,
63     pdf_image_end_image_object2
64 };
65 static const gx_image_enum_procs_t pdf_image_cvd_enum_procs = {
66     gx_image1_plane_data,
67     pdf_image_end_image_cvd,
68     gx_image1_flush
69 };
70 
71 /* ---------------- Driver procedures ---------------- */
72 
73 /* Define the structure for keeping track of progress through an image. */
74 typedef struct pdf_image_enum_s {
75     gx_image_enum_common;
76     int width;
77     int bits_per_pixel;		/* bits per pixel (per plane) */
78     int rows_left;
79     pdf_image_writer writer;
80     gs_matrix mat;
81     gs_color_space_index initial_colorspace;
82     int JPEG_PassThrough;
83 } pdf_image_enum;
84 gs_private_st_composite(st_pdf_image_enum, pdf_image_enum, "pdf_image_enum",
85   pdf_image_enum_enum_ptrs, pdf_image_enum_reloc_ptrs);
86 /* GC procedures */
87 static ENUM_PTRS_WITH(pdf_image_enum_enum_ptrs, pdf_image_enum *pie)
88     if (index < pdf_image_writer_max_ptrs) {
89         gs_ptr_type_t ret =
90             ENUM_USING(st_pdf_image_writer, &pie->writer, sizeof(pie->writer),
91                        index);
92 
93         if (ret == 0)		/* don't stop early */
94             ENUM_RETURN(0);
95         return ret;
96     }
97     return ENUM_USING_PREFIX(st_gx_image_enum_common,
98                              pdf_image_writer_max_ptrs);
99 ENUM_PTRS_END
RELOC_PTRS_WITH(pdf_image_enum_reloc_ptrs,pdf_image_enum * pie)100 static RELOC_PTRS_WITH(pdf_image_enum_reloc_ptrs, pdf_image_enum *pie)
101 {
102     RELOC_USING(st_pdf_image_writer, &pie->writer, sizeof(pie->writer));
103     RELOC_USING(st_gx_image_enum_common, vptr, size);
104 }
105 RELOC_PTRS_END
106 
107 /*
108  * Test whether we can write an image in-line.  This is always true,
109  * because we only support PDF 1.2 and later.
110  */
111 static bool
can_write_image_in_line(const gx_device_pdf * pdev,const gs_image_t * pim)112 can_write_image_in_line(const gx_device_pdf *pdev, const gs_image_t *pim)
113 {
114     return true;
115 }
116 
117 /*
118  * Convert a Type 4 image to a Type 1 masked image if possible.
119  * Type 1 masked images are more compact, and are supported in all PDF
120  * versions, whereas general masked images require PDF 1.3 or higher.
121  * Also, Acrobat 5 for Windows has a bug that causes an error for images
122  * with a color-key mask, at least for 1-bit-deep images using an Indexed
123  * color space.
124  */
125 static int
color_is_black_or_white(gx_device * dev,const gx_drawing_color * pdcolor)126 color_is_black_or_white(gx_device *dev, const gx_drawing_color *pdcolor)
127 {
128     return (!color_is_pure(pdcolor) ? -1 :
129             gx_dc_pure_color(pdcolor) == gx_device_black(dev) ? 0 :
130             gx_dc_pure_color(pdcolor) == gx_device_white(dev) ? 1 : -1);
131 }
132 static int
pdf_convert_image4_to_image1(gx_device_pdf * pdev,const gs_gstate * pgs,const gx_drawing_color * pbcolor,const gs_image4_t * pim4,gs_image_t * pim1,gx_drawing_color * pdcolor)133 pdf_convert_image4_to_image1(gx_device_pdf *pdev,
134                              const gs_gstate *pgs,
135                              const gx_drawing_color *pbcolor,
136                              const gs_image4_t *pim4, gs_image_t *pim1,
137                              gx_drawing_color *pdcolor)
138 {
139     if (pim4->BitsPerComponent == 1 &&
140         pim4->ColorSpace->type->num_components(pim4->ColorSpace) == 1 &&
141         (pim4->MaskColor_is_range ?
142          pim4->MaskColor[0] | pim4->MaskColor[1] :
143          pim4->MaskColor[0]) <= 1
144         ) {
145         gx_device *const dev = (gx_device *)pdev;
146         const gs_color_space *pcs = pim4->ColorSpace;
147         bool write_1s = !pim4->MaskColor[0];
148         gs_client_color cc;
149         int code;
150 
151         /*
152          * Prepare the drawing color.  (pdf_prepare_imagemask will set it.)
153          * This is the other color in the image (the one that isn't the
154          * mask key), taking Decode into account.
155          */
156 
157         cc.paint.values[0] = pim4->Decode[(int)write_1s];
158         cc.pattern = 0;
159         code = pcs->type->remap_color(&cc, pcs, pdcolor, pgs, dev,
160                                       gs_color_select_texture);
161         if (code < 0)
162             return code;
163 
164         /*
165          * The PDF imaging model doesn't support RasterOp.  We can convert a
166          * Type 4 image to a Type 1 imagemask only if the effective RasterOp
167          * passes through the source color unchanged.  "Effective" means we
168          * take into account CombineWithColor, and whether the source and/or
169          * texture are black, white, or neither.
170          */
171         {
172             gs_logical_operation_t lop = pgs->log_op;
173             int black_or_white = color_is_black_or_white(dev, pdcolor);
174 
175             lop = lop_sanitize(lop);
176 
177             switch (black_or_white) {
178             case 0: lop = lop_know_S_0(lop); break;
179             case 1: lop = lop_know_S_1(lop); break;
180             default: DO_NOTHING;
181             }
182             if (pim4->CombineWithColor)
183                 switch (color_is_black_or_white(dev, pbcolor)) {
184                 case 0: lop = lop_know_T_0(lop); break;
185                 case 1: lop = lop_know_T_1(lop); break;
186                 default: DO_NOTHING;
187                 }
188             else
189                 lop = lop_know_T_0(lop);
190             switch (lop_rop(lop)) {
191             case rop3_0:
192                 if (black_or_white != 0)
193                     return -1;
194                 break;
195             case rop3_1:
196                 if (black_or_white != 1)
197                     return -1;
198                 break;
199             case rop3_S:
200                 break;
201             default:
202                 return -1;
203             }
204         }
205 
206         /* All conditions are met.  Convert to a masked image. */
207 
208         gs_image_t_init_mask_adjust(pim1, write_1s, false);
209 #define COPY_ELEMENT(e) pim1->e = pim4->e
210         COPY_ELEMENT(ImageMatrix);
211         COPY_ELEMENT(Width);
212         COPY_ELEMENT(Height);
213         pim1->BitsPerComponent = 1;
214         /* not Decode */
215         COPY_ELEMENT(Interpolate);
216         pim1->format = gs_image_format_chunky; /* BPC = 1, doesn't matter */
217 #undef COPY_ELEMENT
218         return 0;
219     }
220     return -1;			/* arbitrary <0 */
221 }
222 
223 static 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)224 pdf_begin_image_data_decoded(gx_device_pdf *pdev, int num_components, const gs_range_t *pranges, int i,
225                              gs_pixel_image_t *pi, cos_value_t *cs_value, pdf_image_enum *pie)
226 {
227 
228     if (pranges) {
229         /* Rescale the Decode values for the image data. */
230         const gs_range_t *pr = pranges;
231         float *decode = pi->Decode;
232         int j;
233 
234         for (j = 0; j < num_components; ++j, ++pr, decode += 2) {
235             double vmin = decode[0], vmax = decode[1];
236             double base = pr->rmin, factor = pr->rmax - base;
237 
238             decode[1] = (vmax - vmin) / factor + (vmin - base);
239             decode[0] = vmin - base;
240         }
241     }
242     return pdf_begin_image_data(pdev, &pie->writer, pi, cs_value, i);
243 }
244 
245 static int
make_device_color_space(gx_device_pdf * pdev,gs_color_space_index output_cspace_index,gs_color_space ** ppcs)246 make_device_color_space(gx_device_pdf *pdev,
247                         gs_color_space_index output_cspace_index,
248                         gs_color_space **ppcs)
249 {
250     gs_color_space *cs;
251     gs_memory_t *mem = pdev->v_memory;
252 
253     switch (output_cspace_index) {
254         case gs_color_space_index_DeviceGray:
255             cs = gs_cspace_new_DeviceGray(mem);
256             break;
257         case gs_color_space_index_DeviceRGB:
258             cs = gs_cspace_new_DeviceRGB(mem);
259             break;
260         case gs_color_space_index_DeviceCMYK:
261             cs = gs_cspace_new_DeviceCMYK(mem);
262             break;
263         default:
264             /* Notify the user and terminate.
265                Don't emit rangecheck becuause it would fall back
266                to a default implementation (rasterisation).
267              */
268             emprintf(mem, "Unsupported ProcessColorModel");
269             return_error(gs_error_undefined);
270     }
271 
272     if (cs == NULL)
273         return_error(gs_error_VMerror);
274 
275     *ppcs = cs;
276     return 0;
277 }
278 
279 /*
280  * Start processing an image.  This procedure takes extra arguments because
281  * it has to do something slightly different for the parts of an ImageType 3
282  * image.
283  */
284 typedef enum {
285     PDF_IMAGE_DEFAULT,
286     PDF_IMAGE_TYPE3_MASK,	/* no in-line, don't render */
287     PDF_IMAGE_TYPE3_DATA	/* no in-line */
288 } pdf_typed_image_context_t;
289 
290 /*
291  * We define this union because psdf_setup_image_filters may alter the
292  * gs_pixel_image_t part, but pdf_begin_image_data must also have access
293  * to the type-specific parameters.
294  */
295 typedef union image_union_s {
296     gs_pixel_image_t pixel;	/* we may change some components */
297     gs_image1_t type1;
298     gs_image3_t type3;
299     gs_image3x_t type3x;
300     gs_image4_t type4;
301 } image_union_t;
302 
303 static int pdf_begin_typed_image(gx_device_pdf *pdev,
304     const gs_gstate * pgs, const gs_matrix *pmat,
305     const gs_image_common_t *pic, const gs_int_rect * prect,
306     const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
307     gs_memory_t * mem, gx_image_enum_common_t ** pinfo,
308     pdf_typed_image_context_t context);
309 
setup_type1_image(gx_device_pdf * pdev,const gs_image_common_t * pic,const gx_drawing_color * pdcolor,image_union_t * image,pdf_typed_image_context_t context)310 static int setup_type1_image(gx_device_pdf *pdev, const gs_image_common_t *pic,
311                              const gx_drawing_color * pdcolor, image_union_t *image,
312                              pdf_typed_image_context_t context)
313 {
314     const gs_image_t *pim1 = (const gs_image_t *)pic;
315 
316     if (pim1->Alpha != gs_image_alpha_none)
317         return -1;
318     if (pim1->ImageMask) {
319         /* If parameters are invalid, use the fallback implementation. */
320         if (!(gx_dc_is_pattern1_color(pdcolor)))
321             if (pim1->BitsPerComponent != 1 ||
322                 !((pim1->Decode[0] == 0.0 && pim1->Decode[1] == 1.0) ||
323                   (pim1->Decode[0] == 1.0 && pim1->Decode[1] == 0.0))
324                 )
325                 return -1;
326     }
327     image[0].type1 = *pim1;
328     /* If we can write in-line then make it so */
329     return (context == PDF_IMAGE_DEFAULT &&
330         can_write_image_in_line(pdev, pim1));
331 }
332 
setup_type3_image(gx_device_pdf * pdev,const gs_gstate * pgs,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,image_union_t * image)333 static int setup_type3_image(gx_device_pdf *pdev, const gs_gstate * pgs,
334                       const gs_matrix *pmat, const gs_image_common_t *pic,
335                       const gs_int_rect * prect,
336                       const gx_drawing_color * pdcolor,
337                       const gx_clip_path * pcpath, gs_memory_t * mem,
338                       gx_image_enum_common_t ** pinfo,
339                       image_union_t *image)
340 {
341     const gs_image3_t *pim3 = (const gs_image3_t *)pic;
342     gs_image3_t pim3a;
343     const gs_image_common_t *pic1 = pic;
344     gs_matrix m, mi;
345     const gs_matrix *pmat1 = pmat;
346     int code;
347 
348     if (pdev->CompatibilityLevel < 1.3 && !pdev->PatternImagemask) {
349         code = pdf_check_soft_mask(pdev, (gs_gstate *)pgs);
350         if (code < 0)
351             return code;
352         if (pdf_must_put_clip_path(pdev, pcpath))
353             code = pdf_unclip(pdev);
354         else
355             code = pdf_open_page(pdev, PDF_IN_STREAM);
356         if (code < 0)
357             return code;
358         code = pdf_put_clip_path(pdev, pcpath);
359         if (code < 0)
360             return code;
361         gs_make_identity(&m);
362         pmat1 = &m;
363         m.tx = floor(pgs->ctm.tx + 0.5); /* Round the origin against the image size distorsions */
364         m.ty = floor(pgs->ctm.ty + 0.5);
365         pim3a = *pim3;
366         code = gs_matrix_invert(&pim3a.ImageMatrix, &mi);
367         if (code < 0)
368             return code;
369         gs_make_identity(&pim3a.ImageMatrix);
370         if (pim3a.Width < pim3a.MaskDict.Width && pim3a.Width > 0) {
371             int sx = (pim3a.MaskDict.Width + pim3a.Width - 1) / pim3a.Width;
372 
373             gs_matrix_scale(&mi, 1.0 / sx, 1, &mi);
374             gs_matrix_scale(&pim3a.ImageMatrix, 1.0 / sx, 1, &pim3a.ImageMatrix);
375         }
376         if (pim3a.Height < pim3a.MaskDict.Height && pim3a.Height > 0) {
377             int sy = (pim3a.MaskDict.Height + pim3a.Height - 1) / pim3a.Height;
378 
379             gs_matrix_scale(&mi, 1, 1.0 / sy, &mi);
380             gs_matrix_scale(&pim3a.ImageMatrix, 1, 1.0 / sy, &pim3a.ImageMatrix);
381         }
382         gs_matrix_multiply(&mi, &pim3a.MaskDict.ImageMatrix, &pim3a.MaskDict.ImageMatrix);
383         pic1 = (gs_image_common_t *)&pim3a;
384         /* Setting pdev->converting_image_matrix to communicate with pdf_image3_make_mcde. */
385         gs_matrix_multiply(&mi, &ctm_only(pgs), &pdev->converting_image_matrix);
386     }
387     /*
388      * We handle ImageType 3 images in a completely different way:
389      * the default implementation sets up the enumerator.
390      */
391     return gx_begin_image3_generic((gx_device *)pdev, pgs, pmat1, pic1,
392                                    prect, pdcolor, pcpath, mem,
393                                    pdf_image3_make_mid,
394                                    pdf_image3_make_mcde, pinfo);
395 }
396 
convert_type4_image(gx_device_pdf * pdev,const gs_gstate * pgs,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,image_union_t * image,cos_dict_t * pnamed)397 static int convert_type4_image(gx_device_pdf *pdev, const gs_gstate * pgs,
398                       const gs_matrix *pmat, const gs_image_common_t *pic,
399                       const gs_int_rect * prect,
400                       const gx_drawing_color * pdcolor,
401                       const gx_clip_path * pcpath, gs_memory_t * mem,
402                       gx_image_enum_common_t ** pinfo,
403                       pdf_typed_image_context_t context, image_union_t *image,
404                       cos_dict_t *pnamed)
405 {
406     /* Try to convert the image to a plain masked image. */
407     gx_drawing_color icolor;
408     int code;
409 
410     pdev->image_mask_is_SMask = false;
411     if (pdf_convert_image4_to_image1(pdev, pgs, pdcolor,
412                                      (const gs_image4_t *)pic,
413                                      &image[0].type1, &icolor) >= 0) {
414         if (pgs == NULL)
415             return_error(gs_error_unregistered); /* Must not happen. */
416 
417         /* Undo the pop of the NI stack if necessary. */
418         if (pnamed)
419             cos_array_add_object(pdev->NI_stack, COS_OBJECT(pnamed));
420         /* HACK: temporary patch the color space, to allow
421            pdf_prepare_imagemask to write the right color for the imagemask. */
422         code = gs_gsave((gs_gstate *)pgs);
423         if (code < 0)
424             return code;
425         /* {csrc}: const cast warning */
426         code = gs_setcolorspace((gs_gstate *)pgs, ((const gs_image4_t *)pic)->ColorSpace);
427         if (code < 0)
428             return code;
429         code = pdf_begin_typed_image(pdev, pgs, pmat,
430                                      (gs_image_common_t *)&image[0].type1,
431                                      prect, &icolor, pcpath, mem,
432                                      pinfo, context);
433         if (code < 0)
434             return code;
435         return gs_grestore((gs_gstate *)pgs);
436     }
437     return 1;
438 }
439 
convert_type4_to_masked_image(gx_device_pdf * pdev,const gs_gstate * pgs,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)440 static int convert_type4_to_masked_image(gx_device_pdf *pdev, const gs_gstate * pgs,
441                       const gs_image_common_t *pic,
442                       const gs_int_rect * prect,
443                       const gx_drawing_color * pdcolor,
444                       const gx_clip_path * pcpath, gs_memory_t * mem,
445                       gx_image_enum_common_t ** pinfo)
446 {
447         gs_matrix m, m1, mi;
448         gs_image4_t pi4 = *(const gs_image4_t *)pic;
449         int code;
450         pdf_lcvd_t *cvd = NULL;
451 
452         code = pdf_check_soft_mask(pdev, (gs_gstate *)pgs);
453         if (code < 0)
454             return code;
455         if (pdf_must_put_clip_path(pdev, pcpath))
456             code = pdf_unclip(pdev);
457         else
458             code = pdf_open_page(pdev, PDF_IN_STREAM);
459         if (code < 0)
460             return code;
461         code = pdf_put_clip_path(pdev, pcpath);
462         if (code < 0)
463             return code;
464         gs_make_identity(&m1);
465         code = gs_matrix_invert(&pic->ImageMatrix, &mi);
466         if (code < 0)
467             return code;
468         gs_matrix_multiply(&mi, &ctm_only(pgs), &m);
469         code = pdf_setup_masked_image_converter(pdev, mem, &m, &cvd,
470                              true, 0, 0, pi4.Width, pi4.Height, false);
471         if (code < 0)
472             return code;
473         cvd->mdev.is_open = true; /* fixme: same as above. */
474         cvd->mask->is_open = true; /* fixme: same as above. */
475         cvd->mask_is_empty = false;
476         code = (*dev_proc(cvd->mask, fill_rectangle))((gx_device *)cvd->mask,
477                     0, 0, cvd->mask->width, cvd->mask->height, (gx_color_index)0);
478         if (code < 0)
479             return code;
480         gx_device_retain((gx_device *)cvd, true);
481         gx_device_retain((gx_device *)cvd->mask, true);
482         gs_make_identity(&pi4.ImageMatrix);
483         code = gx_default_begin_typed_image((gx_device *)cvd,
484             pgs, &m1, (gs_image_common_t *)&pi4, prect, pdcolor, NULL, mem, pinfo);
485         if (code < 0)
486             return code;
487         (*pinfo)->procs = &pdf_image_cvd_enum_procs;
488         return 0;
489 }
490 
setup_image_process_colorspace(gx_device_pdf * pdev,image_union_t * image,gs_color_space ** pcs_orig,const char * sname,cos_value_t * cs_value)491 static int setup_image_process_colorspace(gx_device_pdf *pdev, image_union_t *image, gs_color_space **pcs_orig,
492                                           const char *sname, cos_value_t *cs_value)
493 {
494     int code;
495     gs_color_space *pcs_device = NULL;
496 
497     cos_c_string_value(cs_value, sname);
498     *pcs_orig = image->pixel.ColorSpace;
499     code = make_device_color_space(pdev, pdev->pcm_color_info_index, &pcs_device);
500     if (code < 0)
501         return code;
502     image->pixel.ColorSpace = pcs_device;
503     return 0;
504 }
505 
506 /* 0 = write unchanged
507    1 = convert to process
508    2 = write as ICC
509    3 = convert base space (Separation)
510    4 = convert base space (DeviceN)
511  */
setup_image_colorspace(gx_device_pdf * pdev,image_union_t * image,const gs_color_space * pcs,gs_color_space ** pcs_orig,const pdf_color_space_names_t * names,cos_value_t * cs_value)512 static int setup_image_colorspace(gx_device_pdf *pdev, image_union_t *image, const gs_color_space *pcs, gs_color_space **pcs_orig,
513                                   const pdf_color_space_names_t *names, cos_value_t *cs_value)
514 {
515     int code=0;
516     gs_color_space_index csi;
517     gs_color_space_index csi2;
518     const gs_color_space *pcs2 = pcs;
519 
520     csi = csi2 = gs_color_space_get_index(pcs);
521     if (csi == gs_color_space_index_ICC) {
522         csi2 = gsicc_get_default_type(pcs->cmm_icc_profile_data);
523     }
524     /* Figure out what to do if we are outputting to really ancient versions of PDF */
525     /* NB ps2write sets CompatibilityLevel to 1.2 so we cater for it here */
526     if (pdev->CompatibilityLevel <= 1.2) {
527 
528         /* If we have an /Indexed space, we need to look at the base space */
529         if (csi2 == gs_color_space_index_Indexed) {
530             pcs2 = pcs->base_space;
531             csi2 = gs_color_space_get_index(pcs2);
532         }
533 
534         switch (csi2) {
535             case gs_color_space_index_DeviceGray:
536                 if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
537                     pdev->params.ColorConversionStrategy == ccs_Gray) {
538                     return 0;
539                 }
540                 else {
541                     code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceGray, cs_value);
542                     if (code < 0)
543                         return code;
544                     return 1;
545                 }
546                 break;
547             case gs_color_space_index_DeviceRGB:
548                 if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
549                     pdev->params.ColorConversionStrategy == ccs_RGB || pdev->params.ColorConversionStrategy == ccs_sRGB)
550                     return 0;
551                 else {
552                     code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceRGB, cs_value);
553                     if (code < 0)
554                         return code;
555                     return 1;
556                 }
557                 break;
558             case gs_color_space_index_DeviceCMYK:
559                 if ((pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
560                     pdev->params.ColorConversionStrategy == ccs_CMYK) && !pdev->params.ConvertCMYKImagesToRGB)
561                     return 0;
562                 else {
563                     code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceCMYK, cs_value);
564                     if (code < 0)
565                         return code;
566                     return 1;
567                 }
568                 break;
569             case gs_color_space_index_CIEA:
570             case gs_color_space_index_CIEABC:
571             case gs_color_space_index_CIEDEF:
572             case gs_color_space_index_CIEDEFG:
573             case gs_color_space_index_Separation:
574                 if (pdev->ForOPDFRead) {
575                     switch (pdev->params.ColorConversionStrategy) {
576                         case ccs_ByObjectType:
577                             /* Object type not implemented yet */
578                         case ccs_UseDeviceIndependentColorForImages:
579                             /* If only correcting images, then leave unchanged */
580                         case ccs_LeaveColorUnchanged:
581                             if (csi2 == gs_color_space_index_Separation)
582                                 return 0;
583                             /* Fall through and convert CIE to the device space */
584                         default:
585                             switch (pdev->pcm_color_info_index) {
586                                 case gs_color_space_index_DeviceGray:
587                                     code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceGray, cs_value);
588                                     break;
589                                 case gs_color_space_index_DeviceRGB:
590                                     code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceRGB, cs_value);
591                                     break;
592                                 case gs_color_space_index_DeviceCMYK:
593                                     code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceCMYK, cs_value);
594                                     break;
595                                 default:
596                                     emprintf(pdev->memory, "Unsupported ProcessColorModel.");
597                                     return_error(gs_error_undefined);
598                             }
599                             if (code < 0)
600                                 return code;
601                             return 1;
602                             break;
603                     }
604                 }
605                 else
606                     *pcs_orig = (gs_color_space *)pcs;
607                 return 1;
608                 break;
609 
610             case gs_color_space_index_ICC:
611                 /* Note that if csi is ICC, check to see if this was one of
612                    the default substitutes that we introduced for DeviceGray,
613                    DeviceRGB or DeviceCMYK.  If it is, then just write
614                    the default color.  Depending upon the flavor of PDF,
615                    or other options, we may want to actually have all
616                    the colors defined by ICC profiles and not do the following
617                    substituion of the Device space. */
618                 csi2 = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
619 
620                 switch (csi2) {
621                     case gs_color_space_index_DeviceGray:
622                         if (pdev->params.ColorConversionStrategy == ccs_Gray ||
623                             pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged)
624                             return 0;
625                         break;
626                     case gs_color_space_index_DeviceRGB:
627                         if (pdev->params.ColorConversionStrategy == ccs_RGB || pdev->params.ColorConversionStrategy == ccs_sRGB ||
628                             pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged)
629                             return 0;
630                         break;
631                     case gs_color_space_index_DeviceCMYK:
632                         if (pdev->params.ColorConversionStrategy == ccs_CMYK ||
633                             pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged)
634                             return 0;
635                         break;
636                     default:
637                         break;
638                 }
639                 /* Fall through for non-handled cases */
640             case gs_color_space_index_DeviceN:
641             case gs_color_space_index_DevicePixel:
642             case gs_color_space_index_Indexed:
643                 switch (pdev->pcm_color_info_index) {
644                     case gs_color_space_index_DeviceGray:
645                         code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceGray, cs_value);
646                         break;
647                     case gs_color_space_index_DeviceRGB:
648                         code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceRGB, cs_value);
649                         break;
650                     case gs_color_space_index_DeviceCMYK:
651                         code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceCMYK, cs_value);
652                         break;
653                     default:
654                         emprintf(pdev->memory, "Unsupported ProcessColorModel.");
655                         return_error(gs_error_undefined);
656                 }
657                 if (code < 0)
658                     return code;
659                 return 1;
660                 break;
661             default:
662                 return (gs_note_error(gs_error_rangecheck));
663                 break;
664         }
665     } else {
666         int strategy = pdev->params.ColorConversionStrategy;
667 
668         if (pdev->params.TransferFunctionInfo == tfi_Apply && pdev->transfer_not_identity && csi2 == gs_color_space_index_Indexed) {
669             csi = gs_color_space_get_index(pcs->base_space);
670             if (csi == gs_color_space_index_ICC) {
671                 csi = gsicc_get_default_type(pcs->base_space->cmm_icc_profile_data);
672             }
673             /* If its still not a base space, make it the ProcessCOlorModel of the device */
674             if (csi > gs_color_space_index_DeviceCMYK)
675                 csi = pdev->pcm_color_info_index;
676             switch(csi) {
677                 case gs_color_space_index_DeviceGray:
678                     strategy = ccs_Gray;
679                     break;
680                 case gs_color_space_index_DeviceRGB:
681                     strategy = ccs_RGB;
682                     break;
683                 case gs_color_space_index_DeviceCMYK:
684                     strategy = ccs_CMYK;
685                     break;
686                 default:
687                     break;
688             }
689         }
690 
691         switch(strategy) {
692             case ccs_ByObjectType:
693                 /* Object type not implemented yet */
694             case ccs_UseDeviceIndependentColorForImages:
695                 /* If only correcting images, then leave unchanged */
696             case ccs_LeaveColorUnchanged:
697                 return 0;
698                 break;
699             case ccs_UseDeviceIndependentColor:
700                 return 2;
701                 break;
702             case ccs_CMYK:
703                 switch(csi2) {
704                     case gs_color_space_index_DeviceGray:
705                     case gs_color_space_index_DeviceCMYK:
706                         return 0;
707                         break;
708                     case gs_color_space_index_Separation:
709                         pcs2 = pcs;
710                         while (pcs2->base_space)
711                             pcs2 = pcs2->base_space;
712                         csi = gs_color_space_get_index(pcs2);
713                         if (csi == gs_color_space_index_ICC)
714                             csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
715                         if (csi == gs_color_space_index_DeviceCMYK)
716                             return 0;
717                         else
718                             return 3;
719                         break;
720                     case gs_color_space_index_DeviceN:
721                         pcs2 = pcs;
722                         while (pcs2->base_space)
723                             pcs2 = pcs2->base_space;
724                         csi = gs_color_space_get_index(pcs2);
725                         if (csi == gs_color_space_index_ICC)
726                             csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
727                         if (csi == gs_color_space_index_DeviceCMYK)
728                             return 0;
729                         else
730                             return 4;
731                         break;
732                     case gs_color_space_index_Indexed:
733                         pcs2 = pcs->base_space;
734                         csi = gs_color_space_get_index(pcs2);
735                         if (csi == gs_color_space_index_ICC)
736                             csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
737                         switch(csi) {
738                             case gs_color_space_index_DeviceGray:
739                             case gs_color_space_index_DeviceCMYK:
740                                 return 0;
741                                 break;
742                             case gs_color_space_index_Separation:
743                                 pcs2 = pcs;
744                                 while (pcs2->base_space)
745                                     pcs2 = pcs2->base_space;
746                                 csi = gs_color_space_get_index(pcs2);
747                                 if (csi == gs_color_space_index_ICC)
748                                     csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
749                                 if (csi == gs_color_space_index_DeviceCMYK)
750                                     return 0;
751                                 else
752                                     return 3;
753                                 break;
754                             case gs_color_space_index_DeviceN:
755                                 pcs2 = pcs;
756                                 while (pcs2->base_space)
757                                     pcs2 = pcs2->base_space;
758                                 csi = gs_color_space_get_index(pcs2);
759                                 if (csi == gs_color_space_index_ICC)
760                                     csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
761                                 if (csi == gs_color_space_index_DeviceCMYK)
762                                     return 0;
763                                 else
764                                     return 4;
765                                 break;
766                             default:
767                                 switch (pdev->pcm_color_info_index) {
768                                     case gs_color_space_index_DeviceGray:
769                                         code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceGray, cs_value);
770                                         break;
771                                     case gs_color_space_index_DeviceRGB:
772                                         code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceRGB, cs_value);
773                                         break;
774                                     case gs_color_space_index_DeviceCMYK:
775                                         code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceCMYK, cs_value);
776                                         break;
777                                     default:
778                                         emprintf(pdev->memory, "Unsupported ProcessColorModel.");
779                                         return_error(gs_error_undefined);
780                                 }
781                                 if (code < 0)
782                                     return code;
783                                 return 1;
784                                 break;
785                         }
786                         break;
787                     default:
788                         code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceCMYK, cs_value);
789                         if (code < 0)
790                             return code;
791                         return 1;
792                         break;
793                 }
794                 break;
795             case ccs_Gray:
796                 switch(csi2) {
797                     case gs_color_space_index_DeviceGray:
798                         return 0;
799                         break;
800                     case gs_color_space_index_Separation:
801                         pcs2 = pcs;
802                         while (pcs2->base_space)
803                             pcs2 = pcs2->base_space;
804                         csi = gs_color_space_get_index(pcs2);
805                         if (csi == gs_color_space_index_ICC)
806                             csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
807                         if (csi == gs_color_space_index_DeviceGray)
808                             return 0;
809                         else
810                             return 3;
811                         break;
812                     case gs_color_space_index_DeviceN:
813                         pcs2 = pcs;
814                         while (pcs2->base_space)
815                             pcs2 = pcs2->base_space;
816                         csi = gs_color_space_get_index(pcs2);
817                         if (csi == gs_color_space_index_ICC)
818                             csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
819                         if (csi == gs_color_space_index_DeviceGray)
820                             return 0;
821                         else
822                             return 4;
823                         break;
824                     case gs_color_space_index_Indexed:
825                         pcs2 = pcs->base_space;
826                         csi = gs_color_space_get_index(pcs2);
827                         if (csi == gs_color_space_index_ICC)
828                             csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
829                         switch(csi) {
830                             case gs_color_space_index_DeviceGray:
831                                 return 0;
832                                 break;
833                             case gs_color_space_index_Separation:
834                                 pcs2 = pcs;
835                                 while (pcs2->base_space)
836                                     pcs2 = pcs2->base_space;
837                                 csi = gs_color_space_get_index(pcs2);
838                                 if (csi == gs_color_space_index_ICC)
839                                     csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
840                                 if (csi == gs_color_space_index_DeviceGray)
841                                     return 0;
842                                 else
843                                     return 3;
844                                 break;
845                             case gs_color_space_index_DeviceN:
846                                 pcs2 = pcs;
847                                 while (pcs2->base_space)
848                                     pcs2 = pcs2->base_space;
849                                 csi = gs_color_space_get_index(pcs2);
850                                 if (csi == gs_color_space_index_ICC)
851                                     csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
852                                 if (csi == gs_color_space_index_DeviceGray)
853                                     return 0;
854                                 else
855                                     return 4;
856                                 break;
857                             default:
858                                 code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceGray, cs_value);
859                                 if (code < 0)
860                                     return code;
861                                 return 1;
862                                 break;
863                         }
864                         break;
865                     default:
866                         code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceGray, cs_value);
867                         if (code < 0)
868                             return code;
869                         return 1;
870                         break;
871                 }
872                 break;
873             case ccs_sRGB:
874             case ccs_RGB:
875                 switch(csi2) {
876                     case gs_color_space_index_DeviceGray:
877                     case gs_color_space_index_DeviceRGB:
878                         return 0;
879                         break;
880                     case gs_color_space_index_Separation:
881                         pcs2 = pcs;
882                         while (pcs2->base_space)
883                             pcs2 = pcs2->base_space;
884                         csi = gs_color_space_get_index(pcs2);
885                         if (csi == gs_color_space_index_ICC)
886                             csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
887                         if (csi == gs_color_space_index_DeviceRGB)
888                             return 0;
889                         else
890                             return 3;
891                         break;
892                     case gs_color_space_index_DeviceN:
893                         pcs2 = pcs;
894                         while (pcs2->base_space)
895                             pcs2 = pcs2->base_space;
896                         csi = gs_color_space_get_index(pcs2);
897                         if (csi == gs_color_space_index_ICC)
898                             csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
899                         if (csi == gs_color_space_index_DeviceRGB)
900                             return 0;
901                         else
902                             return 4;
903                         break;
904                     case gs_color_space_index_Indexed:
905                         pcs2 = pcs->base_space;
906                         csi = gs_color_space_get_index(pcs2);
907                         if (csi == gs_color_space_index_ICC)
908                             csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
909                         switch(csi) {
910                             case gs_color_space_index_DeviceGray:
911                             case gs_color_space_index_DeviceRGB:
912                                 return 0;
913                                 break;
914                             case gs_color_space_index_Separation:
915                                 pcs2 = pcs;
916                                 while (pcs2->base_space)
917                                     pcs2 = pcs2->base_space;
918                                 csi = gs_color_space_get_index(pcs2);
919                                 if (csi == gs_color_space_index_ICC)
920                                     csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
921                                 if (csi == gs_color_space_index_DeviceRGB)
922                                     return 0;
923                                 else
924                                     return 3;
925                                 break;
926                             case gs_color_space_index_DeviceN:
927                                 pcs2 = pcs;
928                                 while (pcs2->base_space)
929                                     pcs2 = pcs2->base_space;
930                                 csi = gs_color_space_get_index(pcs2);
931                                 if (csi == gs_color_space_index_ICC)
932                                     csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
933                                 if (csi == gs_color_space_index_DeviceRGB)
934                                     return 0;
935                                 else
936                                     return 4;
937                                 break;
938                             default:
939                                 code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceRGB, cs_value);
940                                 if (code < 0)
941                                     return code;
942                                 return 1;
943                                 break;
944                         }
945                         break;
946                     default:
947                         code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceRGB, cs_value);
948                         if (code < 0)
949                             return code;
950                         return 1;
951                         break;
952                 }
953                 break;
954             default:
955                 break;
956         }
957     }
958     return 0;
959 }
960 
961 static int
pdf_begin_typed_image(gx_device_pdf * pdev,const gs_gstate * pgs,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)962 pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
963                       const gs_matrix *pmat, const gs_image_common_t *pic,
964                       const gs_int_rect * prect,
965                       const gx_drawing_color * pdcolor,
966                       const gx_clip_path * pcpath, gs_memory_t * mem,
967                       gx_image_enum_common_t ** pinfo,
968                       pdf_typed_image_context_t context)
969 {
970     int code, i;
971     unsigned int use_fallback  = 0, in_line = 0, is_mask = 0,
972         force_lossless = 0, convert_to_process_colors = 0;
973     int width, height;
974     cos_dict_t *pnamed = 0;
975     image_union_t *image;
976     const gs_pixel_image_t *pim;
977     gs_int_rect rect;
978     gs_image_format_t format;
979     const gs_color_space *pcs;
980     int num_components;
981     pdf_image_enum *pie;
982     const pdf_color_space_names_t *names;
983     gs_color_space *pcs_orig = NULL;
984     gs_color_space *pcs_device = NULL;
985     cos_value_t cs_value;
986     const gs_range_t *pranges = 0;
987 
988     image = (image_union_t *)gs_malloc(mem->non_gc_memory, 4,
989                        sizeof(image_union_t), "pdf_begin_typed_image(image)");
990     if (image == 0)
991         return_error(gs_error_VMerror);
992 
993     /*
994      * Pop the image name from the NI stack.  We must do this, to keep the
995      * stack in sync, even if it turns out we can't handle the image.
996      */
997     {
998         cos_value_t ni_value;
999 
1000         if (cos_array_unadd(pdev->NI_stack, &ni_value) >= 0)
1001             pnamed = (cos_dict_t *)ni_value.contents.object;
1002     }
1003 
1004     /* An initialization for pdf_end_and_do_image :
1005        We need to delay adding the "Mask" entry into a type 3 image dictionary
1006        until the mask is completed due to equal image merging. */
1007     pdev->image_mask_id = gs_no_id;
1008 
1009     /* Check for the image types we can handle. */
1010     switch (pic->type->index) {
1011     case 1:
1012         is_mask = ((const gs_image_t *)pic)->ImageMask;
1013         code = setup_type1_image(pdev, pic, pdcolor, image, context);
1014         if (code < 0) {
1015             use_fallback = 1;
1016         }
1017         else
1018             in_line = code;
1019         break;
1020 
1021     case 3:
1022         /* Currently we can't handle images with masks, because we have two
1023          * image enumerators, and the JPEG passthrough is stored at the device
1024          * level, not the enumerator level. This means that when we skip the
1025          * image data (because its handled as JPEG) we also skip the mask data,
1026          * which is no use at all. FIXME: not sure how but if possible I
1027          * should fix this. Probably need to store the PassThrough in the
1028          * enumerator, and then store a pointer to the enumerator in the
1029          * device in place of the flag, so that when we get JPEG data supplied
1030          * we know where to send it. Of course, that won't work if we ever end
1031          * up in the situation where we have two JPEG sources at the same time.....
1032          * That can probably be handled with some judicious work in the DCTDecode
1033          * structure, to hold some reference to the particular stream that
1034          * should get the data. But lets get the simple code working first.
1035          */
1036         pdev->JPEG_PassThrough = 0;
1037         pdev->image_mask_is_SMask = false;
1038         if (pdev->CompatibilityLevel < 1.2 ||
1039             (prect && !(prect->p.x == 0 && prect->p.y == 0 &&
1040                    prect->q.x == ((const gs_image3_t *)pic)->Width &&
1041                    prect->q.y == ((const gs_image3_t *)pic)->Height))) {
1042             gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
1043                                               "pdf_begin_typed_image(image)");
1044             return (gx_default_begin_typed_image((gx_device *)pdev, pgs, pmat, pic, prect, pdcolor,
1045                 pcpath, mem, pinfo));
1046         }
1047         gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
1048                                           "pdf_begin_typed_image(image)");
1049         return (setup_type3_image(pdev, pgs, pmat, pic, prect, pdcolor, pcpath, mem, pinfo, image));
1050         break;
1051 
1052     case IMAGE3X_IMAGETYPE:
1053         pdev->JPEG_PassThrough = 0;
1054         gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
1055                                               "pdf_begin_typed_image(image)");
1056         if (pdev->CompatibilityLevel < 1.4 ||
1057             (prect && !(prect->p.x == 0 && prect->p.y == 0 &&
1058                        prect->q.x == ((const gs_image3x_t *)pic)->Width &&
1059                        prect->q.y == ((const gs_image3x_t *)pic)->Height))) {
1060             return (gx_default_begin_typed_image((gx_device *)pdev, pgs, pmat, pic, prect, pdcolor,
1061                 pcpath, mem, pinfo));
1062         }
1063         pdev->image_mask_is_SMask = true;
1064         return gx_begin_image3x_generic((gx_device *)pdev, pgs, pmat, pic,
1065                                         prect, pdcolor, pcpath, mem,
1066                                         pdf_image3x_make_mid,
1067                                         pdf_image3x_make_mcde, pinfo);
1068         break;
1069 
1070     case 4:
1071         pdev->JPEG_PassThrough = 0;
1072         code = convert_type4_image(pdev, pgs, pmat, pic, prect, pdcolor,
1073                       pcpath, mem, pinfo, context, image, pnamed);
1074         if (code < 0) {
1075             use_fallback = 1;
1076         }
1077         if (code == 0) {
1078             gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
1079                                                   "pdf_begin_typed_image(image)");
1080             return code;
1081         }
1082         /* No luck.  Masked images require PDF 1.3 or higher. */
1083         if (pdev->CompatibilityLevel < 1.2) {
1084             use_fallback = 1;
1085         }
1086         if (pdev->CompatibilityLevel < 1.3 && !pdev->PatternImagemask) {
1087             gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
1088                                                   "pdf_begin_typed_image(image)");
1089             return (convert_type4_to_masked_image(pdev, pgs, pic, prect, pdcolor,
1090                       pcpath, mem,pinfo));
1091         }
1092         image[0].type4 = *(const gs_image4_t *)pic;
1093         break;
1094 
1095     default:
1096         use_fallback = 1;
1097         break;
1098     }
1099 
1100     pim = (const gs_pixel_image_t *)pic;
1101     format = pim->format;
1102     switch (format) {
1103     case gs_image_format_chunky:
1104     case gs_image_format_component_planar:
1105         break;
1106     default:
1107         use_fallback = 1;
1108     }
1109     /* AR5 on Windows doesn't support 0-size images. Skipping. */
1110     if (pim->Width == 0 || pim->Height == 0)
1111         use_fallback = 1;
1112     /* PDF doesn't support images with more than 8 bits per component. */
1113     switch (pim->BitsPerComponent) {
1114         case 1:
1115         case 2:
1116         case 4:
1117         case 8:
1118             break;
1119         case 12:
1120         case 16:
1121             break;
1122         default:
1123             gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
1124                                               "pdf_begin_typed_image(image)");
1125             return_error(gs_error_rangecheck);
1126     }
1127     if (prect)
1128         rect = *prect;
1129     else {
1130         rect.p.x = rect.p.y = 0;
1131         rect.q.x = pim->Width, rect.q.y = pim->Height;
1132     }
1133     if (rect.p.x != 0 || rect.p.y != 0 ||
1134         rect.q.x != pim->Width || rect.q.y != pim->Height ||
1135         (is_mask && pim->CombineWithColor))
1136         use_fallback = 1;
1137 
1138     if (pdev->Eps2Write) {
1139         gs_rect sbox, dbox, *Box;
1140         gs_point corners[4];
1141         gs_fixed_rect ibox;
1142         gs_matrix * pmat1 = (gs_matrix *)pmat;
1143         gs_matrix mat;
1144 
1145         if (!pdev->accumulating_charproc)
1146             Box = &pdev->BBox;
1147         else
1148             Box = &pdev->charproc_BBox;
1149         if (pmat1 == 0)
1150             pmat1 = (gs_matrix *)&ctm_only(pgs);
1151         if ((code = gs_matrix_invert(&pic->ImageMatrix, &mat)) < 0 ||
1152             (code = gs_matrix_multiply(&mat, pmat1, &mat)) < 0)
1153             return code;
1154         sbox.p.x = rect.p.x;
1155         sbox.p.y = rect.p.y;
1156         sbox.q.x = rect.q.x;
1157         sbox.q.y = rect.q.y;
1158         gs_bbox_transform_only(&sbox, &mat, corners);
1159         gs_points_bbox(corners, &dbox);
1160         ibox.p.x = float2fixed(dbox.p.x);
1161         ibox.p.y = float2fixed(dbox.p.y);
1162         ibox.q.x = float2fixed(dbox.q.x);
1163         ibox.q.y = float2fixed(dbox.q.y);
1164         if (pcpath != NULL &&
1165             !gx_cpath_includes_rectangle(pcpath, ibox.p.x, ibox.p.y,
1166             ibox.q.x, ibox.q.y)
1167             ) {
1168             /* Let the target do the drawing, but drive two triangles */
1169             /* through the clipping path to get an accurate bounding box. */
1170             gx_device_clip cdev;
1171             gx_drawing_color devc;
1172 
1173             fixed x0 = float2fixed(corners[0].x), y0 = float2fixed(corners[0].y);
1174             fixed bx2 = float2fixed(corners[2].x) - x0, by2 = float2fixed(corners[2].y) - y0;
1175 
1176             pdev->AccumulatingBBox++;
1177             gx_make_clip_device_on_stack(&cdev, pcpath, (gx_device *)pdev);
1178             set_nonclient_dev_color(&devc, gx_device_black((gx_device *)pdev));  /* any non-white color will do */
1179             gx_default_fill_triangle((gx_device *) & cdev, x0, y0,
1180                 float2fixed(corners[1].x) - x0,
1181                 float2fixed(corners[1].y) - y0,
1182                 bx2, by2, &devc, lop_default);
1183             gx_default_fill_triangle((gx_device *) & cdev, x0, y0,
1184                 float2fixed(corners[3].x) - x0,
1185                 float2fixed(corners[3].y) - y0,
1186                 bx2, by2, &devc, lop_default);
1187             pdev->AccumulatingBBox--;
1188         } else {
1189             /* Just use the bounding box. */
1190             float x0, y0, x1, y1;
1191             x0 = fixed2float(ibox.p.x) / (pdev->HWResolution[0] / 72.0);
1192             y0 = fixed2float(ibox.p.y) / (pdev->HWResolution[1] / 72.0);
1193             x1 = fixed2float(ibox.q.x) / (pdev->HWResolution[0] / 72.0);
1194             y1 = fixed2float(ibox.q.y) / (pdev->HWResolution[1] / 72.0);
1195             if (Box->p.x > x0)
1196                 Box->p.x = x0;
1197             if (Box->p.y > y0)
1198                 Box->p.y = y0;
1199             if (Box->q.x < x1)
1200                 Box->q.x = x1;
1201             if (Box->q.y < y1)
1202                 Box->q.y = y1;
1203         }
1204     }
1205 
1206     if (use_fallback) {
1207         pdev->JPEG_PassThrough = 0;
1208         gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
1209                                               "pdf_begin_typed_image(image)");
1210         return gx_default_begin_typed_image
1211             ((gx_device *)pdev, pgs, pmat, pic, prect, pdcolor, pcpath, mem,
1212             pinfo);
1213     }
1214 
1215     pcs = pim->ColorSpace;
1216     num_components = (is_mask ? 1 : gs_color_space_num_components(pcs));
1217 
1218     code = pdf_check_soft_mask(pdev, (gs_gstate *)pgs);
1219     if (code < 0)
1220         return code;
1221     if (pdf_must_put_clip_path(pdev, pcpath))
1222         code = pdf_unclip(pdev);
1223     else
1224         code = pdf_open_page(pdev, PDF_IN_STREAM);
1225     if (code < 0) {
1226         pdev->JPEG_PassThrough = 0;
1227         gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
1228                                               "pdf_begin_typed_image(image)");
1229         return gx_default_begin_typed_image
1230             ((gx_device *)pdev, pgs, pmat, pic, prect, pdcolor, pcpath, mem,
1231             pinfo);
1232     }
1233 
1234     if (context == PDF_IMAGE_TYPE3_MASK) {
1235         /*
1236          * The soft mask for an ImageType 3x image uses a DevicePixel
1237          * color space, which pdf_color_space() can't handle.  Patch it
1238          * to DeviceGray here.
1239          */
1240         /* {csrc} make sure this gets freed */
1241         pcs = gs_cspace_new_DeviceGray(pdev->memory);
1242         if (pcs == NULL)
1243             code = gs_note_error(gs_error_VMerror);
1244     } else if (is_mask)
1245         code = pdf_prepare_imagemask(pdev, pgs, pdcolor);
1246     else
1247         code = pdf_prepare_image(pdev, pgs);
1248     if (code < 0) {
1249         pdev->JPEG_PassThrough = 0;
1250         gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
1251                                               "pdf_begin_typed_image(image)");
1252         return gx_default_begin_typed_image
1253             ((gx_device *)pdev, pgs, pmat, pic, prect, pdcolor, pcpath, mem,
1254             pinfo);
1255     }
1256 
1257     pie = gs_alloc_struct(mem, pdf_image_enum, &st_pdf_image_enum,
1258                         "pdf_begin_image");
1259     if (pie == 0) {
1260         gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
1261                                               "pdf_begin_typed_image(image)");
1262         return_error(gs_error_VMerror);
1263     }
1264     memset(pie, 0, sizeof(*pie)); /* cleanup entirely for GC to work in all cases. */
1265     *pinfo = (gx_image_enum_common_t *) pie;
1266     gx_image_enum_common_init(*pinfo, (const gs_data_image_t *) pim,
1267                     ((pdev->CompatibilityLevel >= 1.3) ?
1268                             (context == PDF_IMAGE_TYPE3_MASK ?
1269                             &pdf_image_object_enum_procs :
1270                             &pdf_image_enum_procs) :
1271                             context == PDF_IMAGE_TYPE3_MASK ?
1272                             &pdf_image_object_enum_procs :
1273                             context == PDF_IMAGE_TYPE3_DATA ?
1274                             &pdf_image_object_enum_procs2 :
1275                             &pdf_image_enum_procs),
1276                         (gx_device *)pdev, num_components, format);
1277     pie->memory = mem;
1278     width = rect.q.x - rect.p.x;
1279     pie->width = width;
1280     height = rect.q.y - rect.p.y;
1281     pie->bits_per_pixel =
1282         pim->BitsPerComponent * num_components / pie->num_planes;
1283     pie->rows_left = height;
1284     if (pnamed != 0) /* Don't in-line the image if it is named. */
1285         in_line = false;
1286     else {
1287         double nbytes = (double)(((ulong) pie->width * pie->bits_per_pixel + 7) >> 3) *
1288             pie->num_planes * pie->rows_left;
1289 
1290         in_line &= (nbytes < pdev->MaxInlineImageSize);
1291     }
1292     pie->initial_colorspace = pdev->pcm_color_info_index;
1293 
1294     if (pmat == 0)
1295         pmat = &ctm_only(pgs);
1296     {
1297         gs_matrix mat;
1298         gs_matrix bmat;
1299         int code;
1300 
1301         pdf_make_bitmap_matrix(&bmat, -rect.p.x, -rect.p.y,
1302                                pim->Width, pim->Height, height);
1303         if ((code = gs_matrix_invert(&pim->ImageMatrix, &mat)) < 0 ||
1304             (code = gs_matrix_multiply(&bmat, &mat, &mat)) < 0 ||
1305             (code = gs_matrix_multiply(&mat, pmat, &pie->mat)) < 0
1306             ) {
1307             gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
1308                                               "pdf_begin_typed_image(image)");
1309             gs_free_object(mem, pie, "pdf_begin_image");
1310             return code;
1311         }
1312         /* AR3,AR4 show no image when CTM is singular; AR5 reports an error */
1313         if (pie->mat.xx * pie->mat.yy == pie->mat.xy * pie->mat.yx)
1314             goto fail_and_fallback;
1315     }
1316 
1317     code = pdf_put_clip_path(pdev, pcpath);
1318     if (code < 0) {
1319         gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
1320                                           "pdf_begin_typed_image(image)");
1321         gs_free_object(mem, pie, "pdf_begin_image");
1322         return code;
1323     }
1324     pdf_image_writer_init(&pie->writer);
1325     /* Note : Possible values for alt_writer_count are 1,2,3,4.
1326        1 means no alternative streams.
1327        2 means the main image stream and a mask stream while converting
1328                an Image Type 4.
1329        3 means the main image stream, alternative image compression stream,
1330                and the compression chooser.
1331        4 meams 3 and a mask stream while convertingh an Image Type 4.
1332      */
1333     pie->writer.alt_writer_count = (in_line ||
1334                                     (pim->Width <= 64 && pim->Height <= 64)
1335                                     ? 1 : 2);
1336     if ((image[0].pixel.ColorSpace != NULL &&
1337         image[0].pixel.ColorSpace->type->index == gs_color_space_index_Indexed
1338         && pdev->params.ColorImage.DownsampleType != ds_Subsample) ||
1339         pdev->transfer_not_identity)
1340         force_lossless = true;
1341 
1342     if ((image[0].pixel.ColorSpace != NULL && image[0].pixel.ColorSpace->type->index == gs_color_space_index_Indexed)
1343         || force_lossless)
1344         pie->writer.alt_writer_count = 1;
1345 
1346     names = (in_line ? &pdf_color_space_names_short : &pdf_color_space_names);
1347 
1348     /* We don't want to change the colour space of a mask, or an SMask (both of which are Gray) */
1349     if (!is_mask) {
1350         if (image[0].pixel.ColorSpace != NULL && !(context == PDF_IMAGE_TYPE3_MASK))
1351             convert_to_process_colors = setup_image_colorspace(pdev, &image[0], pcs, &pcs_orig, names, &cs_value);
1352 
1353         if (pim->BitsPerComponent > 8 && convert_to_process_colors)
1354             goto fail_and_fallback;
1355         if (convert_to_process_colors == 4) {
1356             code = convert_DeviceN_alternate(pdev, pgs, pcs, NULL, NULL, NULL, NULL, &cs_value, in_line);
1357             if (code < 0)
1358                 goto fail_and_fallback;
1359         }
1360         if (convert_to_process_colors == 3) {
1361             code = convert_separation_alternate(pdev, pgs, pcs, NULL, NULL, NULL, NULL, &cs_value, in_line);
1362             if (code < 0)
1363                 goto fail_and_fallback;
1364         }
1365         if (convert_to_process_colors == 1) {
1366             code = make_device_color_space(pdev, pdev->pcm_color_info_index, &pcs_device);
1367             if (code < 0)
1368                 goto fail_and_fallback;
1369             image[0].pixel.ColorSpace = pcs_device;
1370             image[0].pixel.BitsPerComponent = 8;
1371             code = pdf_color_space_named(pdev, pgs, &cs_value, &pranges, pcs_device, names,
1372                                      in_line, NULL, 0, false);
1373             if (code < 0)
1374                 goto fail_and_fallback;
1375         } else {
1376             if (convert_to_process_colors == 2) {
1377                 convert_to_process_colors = 0;
1378                 code = pdf_color_space_named(pdev, pgs, &cs_value, &pranges, pcs, names,
1379                                      in_line, NULL, 0, true);
1380                 if (code < 0)
1381                     goto fail_and_fallback;
1382             } else {
1383                 convert_to_process_colors = 0;
1384                 code = pdf_color_space_named(pdev, pgs, &cs_value, &pranges, pcs, names,
1385                                      in_line, NULL, 0, false);
1386                 if (code < 0)
1387                     goto fail_and_fallback;
1388             }
1389         }
1390     }
1391 
1392     image[1] = image[0];
1393 
1394     pdev->ParamCompatibilityLevel = pdev->CompatibilityLevel;
1395 
1396     code = pdf_begin_write_image(pdev, &pie->writer, gs_no_id, width,
1397                     height, pnamed, in_line);
1398     if (code < 0)
1399         goto fail_and_fallback;
1400 
1401     if (pdev->params.TransferFunctionInfo == tfi_Apply && pdev->transfer_not_identity && !is_mask)
1402         pdev->JPEG_PassThrough = 0;
1403 
1404 /*    if (pdev->JPEG_PassThrough)
1405         uncompressed = pie->writer.binary[0].strm;*/
1406 
1407     /* Code below here deals with setting up the multiple data stream writing.
1408      * We can have up to 4 stream writers, which we keep in an array. We must
1409      * always have at least one which writes the uncompressed stream. If we
1410      * are writing compressed streams, we have one for the compressed stream
1411      * and one for the compression chooser.
1412      * For type 4 images being converted (for old versions of PDF or for ps2write)
1413      * we need an additional stream to write a mask, which masks the real
1414      * image.
1415      * For colour conversion we will place an additional filter in front of all
1416      * the streams which does the conversion.
1417      */
1418     if (in_line) {
1419         pdev->JPEG_PassThrough = 0;
1420         code = new_setup_lossless_filters((gx_device_psdf *) pdev,
1421                                              &pie->writer.binary[0],
1422                                              &image[0].pixel, in_line, convert_to_process_colors, (gs_matrix *)pmat, (gs_gstate *)pgs);
1423     } else {
1424         if (force_lossless) {
1425             /*
1426              * Some regrettable PostScript code (such as LanguageLevel 1 output
1427              * from Microsoft's PSCRIPT.DLL driver) misuses the transfer
1428              * function to accomplish the equivalent of indexed color.
1429              * Downsampling (well, only averaging) or JPEG compression are not
1430              * compatible with this.  Play it safe by using only lossless
1431              * filters if the transfer function(s) is/are other than the
1432              * identity and by setting the downsample type to Subsample..
1433              */
1434             int saved_downsample = pdev->params.ColorImage.DownsampleType;
1435 
1436             pdev->params.ColorImage.DownsampleType = ds_Subsample;
1437             code = new_setup_image_filters((gx_device_psdf *) pdev,
1438                                           &pie->writer.binary[0], &image[0].pixel,
1439                                           pmat, pgs, true, in_line, convert_to_process_colors);
1440             pdev->params.ColorImage.DownsampleType = saved_downsample;
1441         } else {
1442             code = new_setup_image_filters((gx_device_psdf *) pdev,
1443                                           &pie->writer.binary[0], &image[0].pixel,
1444                                           pmat, pgs, true, in_line, convert_to_process_colors);
1445         }
1446     }
1447 
1448     if (code < 0)
1449         goto fail_and_fallback;
1450 
1451     if (!convert_to_process_colors)
1452     {
1453         gs_color_space_index csi;
1454 
1455         if (pdev->params.TransferFunctionInfo == tfi_Apply && pdev->transfer_not_identity && !is_mask) {
1456             pdev->JPEG_PassThrough = 0;
1457             csi = gs_color_space_get_index(image[0].pixel.ColorSpace);
1458             if (csi == gs_color_space_index_Indexed) {
1459                 csi = gs_color_space_get_index(image[0].pixel.ColorSpace->base_space);
1460                 if (csi == gs_color_space_index_ICC) {
1461                     csi = gsicc_get_default_type(image[0].pixel.ColorSpace->base_space->cmm_icc_profile_data);
1462                 }
1463             } else {
1464                 if (csi == gs_color_space_index_ICC) {
1465                     csi = gsicc_get_default_type(image[0].pixel.ColorSpace->cmm_icc_profile_data);
1466                 }
1467             }
1468             switch(csi) {
1469                 case gs_color_space_index_DevicePixel:
1470                 case gs_color_space_index_CIEA:
1471                     convert_to_process_colors = 1;
1472                     pdf_set_process_color_model(pdev, 0);
1473                     break;
1474                 case gs_color_space_index_CIEDEF:
1475                 case gs_color_space_index_CIEABC:
1476                 case gs_color_space_index_DeviceGray:
1477                     convert_to_process_colors = 1;
1478                     pdf_set_process_color_model(pdev, 0);
1479                     break;
1480                 case gs_color_space_index_DeviceRGB:
1481                     convert_to_process_colors = 1;
1482                     pdf_set_process_color_model(pdev, 1);
1483                     break;
1484                 case gs_color_space_index_CIEDEFG:
1485                 case gs_color_space_index_DeviceCMYK:
1486                     convert_to_process_colors = 1;
1487                     pdf_set_process_color_model(pdev, 2);
1488                     break;
1489                 default:
1490                     break;
1491             }
1492             if (convert_to_process_colors == 1) {
1493                 pcs_orig = image->pixel.ColorSpace;
1494                 code = make_device_color_space(pdev, pdev->pcm_color_info_index, &pcs_device);
1495                 if (code < 0)
1496                     goto fail_and_fallback;
1497                 image[0].pixel.ColorSpace = pcs_device;
1498                 code = pdf_color_space_named(pdev, pgs, &cs_value, &pranges, pcs_device, names,
1499                                          in_line, NULL, 0, false);
1500                 if (code < 0)
1501                     goto fail_and_fallback;
1502             }
1503         }
1504     }
1505     /* If we are not preserving the colour space unchanged, thenwe can't pass through JPEG */
1506     else
1507         pdev->JPEG_PassThrough = 0;
1508 
1509 
1510     if (convert_to_process_colors) {
1511         image[0].pixel.ColorSpace = pcs_orig;
1512         image[0].pixel.BitsPerComponent = pim->BitsPerComponent;
1513         code = psdf_setup_image_colors_filter(&pie->writer.binary[0],
1514                                               (gx_device_psdf *)pdev, pim, &image[0].pixel, pgs);
1515         if (code < 0)
1516             goto fail_and_fallback;
1517         image[0].pixel.ColorSpace = pcs_device;
1518     }
1519 
1520     if (pdev->JPEG_PassThrough) {
1521 /*        if (pie->writer.alt_writer_count > 1) {
1522             s_close_filters(&pie->writer.binary[0].strm, uncompressed);
1523             memset(pie->writer.binary + 1, 0, sizeof(pie->writer.binary[1]));
1524             memset(pie->writer.binary + 2, 0, sizeof(pie->writer.binary[1]));
1525         }*/
1526         pdev->PassThroughWriter = pie->writer.binary[0].strm;
1527         pie->writer.alt_writer_count = 1;
1528     }
1529     pie->JPEG_PassThrough = pdev->JPEG_PassThrough;
1530 
1531     if (pie->writer.alt_writer_count > 1) {
1532         code = pdf_make_alt_stream(pdev, &pie->writer.binary[1]);
1533         if (code) {
1534             goto fail_and_fallback;
1535         }
1536         code = new_setup_image_filters((gx_device_psdf *) pdev,
1537                                   &pie->writer.binary[1], &image[1].pixel,
1538                                   pmat, pgs, force_lossless, in_line, convert_to_process_colors);
1539         if (code == gs_error_rangecheck) {
1540 
1541             for (i=1;i < pie->writer.alt_writer_count; i++) {
1542                 stream *s = pie->writer.binary[i].strm;
1543                 cos_stream_t *pcos = cos_stream_from_pipeline(pie->writer.binary[i].strm);
1544                 s_close_filters(&s, NULL);
1545                 gs_free_object(pdev->pdf_memory, s, "compressed image stream");
1546                 if (pcos == 0L)
1547                     return gs_note_error(gs_error_ioerror);
1548                 pcos->cos_procs->release((cos_object_t *)pcos, "pdf_begin_typed_image_impl");
1549                 gs_free_object(pdev->pdf_memory, pcos, "compressed image cos_stream");
1550             }
1551             /* setup_image_compression rejected the alternative compression. */
1552             pie->writer.alt_writer_count = 1;
1553             memset(pie->writer.binary + 1, 0, sizeof(pie->writer.binary[1]));
1554             memset(pie->writer.binary + 2, 0, sizeof(pie->writer.binary[1]));
1555         } else if (code) {
1556             goto fail_and_fallback;
1557         } else if (convert_to_process_colors) {
1558             image[1].pixel.ColorSpace = pcs_orig;
1559             image[1].pixel.BitsPerComponent = pim->BitsPerComponent;
1560             code = psdf_setup_image_colors_filter(&pie->writer.binary[1],
1561                                               (gx_device_psdf *)pdev, pim, &image[1].pixel, pgs);
1562             if (code < 0) {
1563                 goto fail_and_fallback;
1564             }
1565             image[1].pixel.ColorSpace = pcs_device;
1566         }
1567     }
1568 
1569     for (i = 0; i < pie->writer.alt_writer_count; i++) {
1570         code = pdf_begin_image_data_decoded(pdev, num_components, pranges, i,
1571                              &image[i].pixel, &cs_value, pie);
1572         if (code < 0)
1573             goto fail_and_fallback;
1574     }
1575     if (pie->writer.alt_writer_count == 2) {
1576         psdf_setup_compression_chooser(&pie->writer.binary[2],
1577              (gx_device_psdf *)pdev, pim->Width, pim->Height,
1578              num_components, pim->BitsPerComponent);
1579         pie->writer.alt_writer_count = 3;
1580     }
1581     if (pic->type->index == 4 && pdev->CompatibilityLevel < 1.3) {
1582         int i;
1583 
1584         /* Create a stream for writing the mask. */
1585         i = pie->writer.alt_writer_count;
1586         gs_image_t_init_mask_adjust((gs_image_t *)&image[i].type1, true, false);
1587         image[i].type1.Width = image[0].pixel.Width;
1588         image[i].type1.Height = image[0].pixel.Height;
1589         /* Won't use image[2]. */
1590         code = pdf_begin_write_image(pdev, &pie->writer, gs_no_id, width,
1591                     height, NULL, false);
1592         if (code)
1593             goto fail_and_fallback;
1594         code = psdf_setup_image_filters((gx_device_psdf *) pdev,
1595                                   &pie->writer.binary[i], &image[i].pixel,
1596                                   pmat, pgs, force_lossless, in_line);
1597         if (code < 0)
1598             goto fail_and_fallback;
1599         /* Bug701972 -- added input_width arg here.  For this case, just passing in the same
1600          * width as before, so nothing changes.  This is an obscure case that isn't tested
1601          * on the cluster (note that it requires CompatibilityLevel < 1.3).
1602          */
1603         psdf_setup_image_to_mask_filter(&pie->writer.binary[i],
1604                                         (gx_device_psdf *)pdev, pim->Width, pim->Height, pim->Width,
1605                                         num_components, pim->BitsPerComponent, image[i].type4.MaskColor);
1606         code = pdf_begin_image_data_decoded(pdev, num_components, pranges, i,
1607                              &image[i].pixel, &cs_value, pie);
1608         if (code < 0)
1609             goto fail_and_fallback;
1610         ++pie->writer.alt_writer_count;
1611     }
1612 
1613     gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
1614                                               "pdf_begin_typed_image(image)");
1615     return 0;
1616 
1617 fail_and_fallback:
1618     pdev->JPEG_PassThrough = 0;
1619     gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
1620                                       "pdf_begin_typed_image(image)");
1621     gs_free_object(mem, pie, "pdf_begin_image");
1622     return gx_default_begin_typed_image
1623         ((gx_device *)pdev, pgs, pmat, pic, prect, pdcolor, pcpath, mem,
1624         pinfo);
1625 }
1626 
1627 int
gdev_pdf_begin_typed_image(gx_device * dev,const gs_gstate * pgs,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)1628 gdev_pdf_begin_typed_image(gx_device * dev, const gs_gstate * pgs,
1629                            const gs_matrix *pmat, const gs_image_common_t *pic,
1630                            const gs_int_rect * prect,
1631                            const gx_drawing_color * pdcolor,
1632                            const gx_clip_path * pcpath, gs_memory_t * mem,
1633                            gx_image_enum_common_t ** pinfo)
1634 {
1635     return pdf_begin_typed_image((gx_device_pdf *)dev, pgs, pmat, pic, prect,
1636                                  pdcolor, pcpath, mem, pinfo,
1637                                  PDF_IMAGE_DEFAULT);
1638 }
1639 
1640 /* ---------------- All images ---------------- */
1641 
1642 /* Process the next piece of an image. */
1643 static 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)1644 pdf_image_plane_data_alt(gx_image_enum_common_t * info,
1645                      const gx_image_plane_t * planes, int height,
1646                      int *rows_used, int alt_writer_index)
1647 {
1648     pdf_image_enum *pie = (pdf_image_enum *) info;
1649     int h = height;
1650     int y;
1651     /****** DOESN'T HANDLE IMAGES WITH VARYING WIDTH PER PLANE ******/
1652     uint width_bits = pie->width * pie->plane_depths[0];
1653     /****** DOESN'T HANDLE NON-ZERO data_x CORRECTLY ******/
1654     uint ignore;
1655     int nplanes = pie->num_planes;
1656     int status = 0;
1657     uint bcount = (width_bits + 7) >> 3;
1658 
1659     if (h > pie->rows_left)
1660         h = pie->rows_left;
1661     for (y = 0; y < h; ++y) {
1662         if (nplanes > 1) {
1663             /*
1664              * We flip images in blocks, and each block except the last one
1665              * must contain an integral number of pixels.  The easiest way
1666              * to meet this condition is for all blocks except the last to
1667              * be a multiple of 3 source bytes (guaranteeing an integral
1668              * number of 1/2/4/8/12-bit samples), i.e., 3*nplanes flipped
1669              * bytes.  This requires a buffer of at least
1670              * 3*GS_IMAGE_MAX_COMPONENTS bytes.
1671              */
1672             int pi;
1673             uint count = bcount;
1674             uint offset = 0;
1675 #define ROW_BYTES max(200 /*arbitrary*/, 3 * GS_IMAGE_MAX_COMPONENTS)
1676             const byte *bit_planes[GS_IMAGE_MAX_COMPONENTS];
1677             int block_bytes = ROW_BYTES / (3 * nplanes) * 3;
1678             byte row[ROW_BYTES];
1679 
1680             for (pi = 0; pi < nplanes; ++pi)
1681                 bit_planes[pi] = planes[pi].data + planes[pi].raster * y;
1682             while (count) {
1683                 uint flip_count;
1684                 uint flipped_count;
1685 
1686                 if (count > block_bytes) {
1687                     flip_count = block_bytes;
1688                     flipped_count = block_bytes * nplanes;
1689                 } else {
1690                     flip_count = count;
1691                     flipped_count =
1692                         (width_bits % (block_bytes * 8) * nplanes + 7) >> 3;
1693                     /* In case the width of the image is a precise multiple of our block size */
1694                     if (flipped_count == 0)
1695                         flipped_count = block_bytes * nplanes;
1696                 }
1697                 image_flip_planes(row, bit_planes, offset, flip_count,
1698                                   nplanes, pie->plane_depths[0]);
1699                 status = sputs(pie->writer.binary[alt_writer_index].strm, row,
1700                                flipped_count, &ignore);
1701                 if (status < 0)
1702                     break;
1703                 offset += flip_count;
1704                 count -= flip_count;
1705             }
1706         } else {
1707             status = sputs(pie->writer.binary[alt_writer_index].strm,
1708                            planes[0].data + planes[0].raster * y, bcount,
1709                            &ignore);
1710         }
1711         if (status < 0)
1712             break;
1713     }
1714     *rows_used = h;
1715     if (status < 0)
1716         return_error(gs_error_ioerror);
1717     return !pie->rows_left;
1718 #undef ROW_BYTES
1719 }
1720 
1721 static int
pdf_image_plane_data(gx_image_enum_common_t * info,const gx_image_plane_t * planes,int height,int * rows_used)1722 pdf_image_plane_data(gx_image_enum_common_t * info,
1723                      const gx_image_plane_t * planes, int height,
1724                      int *rows_used)
1725 {
1726     pdf_image_enum *pie = (pdf_image_enum *) info;
1727     int i;
1728 
1729     if (pie->JPEG_PassThrough) {
1730         pie->rows_left -= height;
1731         *rows_used = height;
1732         return 0;
1733     }
1734 
1735     for (i = 0; i < pie->writer.alt_writer_count; i++) {
1736         int code = pdf_image_plane_data_alt(info, planes, height, rows_used, i);
1737         if (code)
1738             return code;
1739     }
1740     pie->rows_left -= *rows_used;
1741     if (pie->writer.alt_writer_count > 2)
1742         pdf_choose_compression(&pie->writer, false);
1743 
1744     return !pie->rows_left;
1745 }
1746 
1747 static int
use_image_as_pattern(gx_device_pdf * pdev,pdf_resource_t * pres1,const gs_matrix * pmat,gs_id id)1748 use_image_as_pattern(gx_device_pdf *pdev, pdf_resource_t *pres1,
1749                      const gs_matrix *pmat, gs_id id)
1750 {   /* See also dump_image in gdevpdfd.c . */
1751     gs_gstate s;
1752     gs_pattern1_instance_t inst;
1753     cos_value_t v;
1754     const pdf_resource_t *pres;
1755     int code;
1756 
1757     memset(&s, 0, sizeof(s));
1758     s.ctm.xx = pmat->xx;
1759     s.ctm.xy = pmat->xy;
1760     s.ctm.yx = pmat->yx;
1761     s.ctm.yy = pmat->yy;
1762     s.ctm.tx = pmat->tx;
1763     s.ctm.ty = pmat->ty;
1764     memset(&inst, 0, sizeof(inst));
1765     inst.saved = (gs_gstate *)&s; /* HACK : will use s.ctm only. */
1766     inst.templat.PaintType = 1;
1767     inst.templat.TilingType = 1;
1768     inst.templat.BBox.p.x = inst.templat.BBox.p.y = 0;
1769     inst.templat.BBox.q.x = 1;
1770     inst.templat.BBox.q.y = 1;
1771     inst.templat.XStep = 2; /* Set 2 times bigger step against artifacts. */
1772     inst.templat.YStep = 2;
1773 
1774     {
1775         pattern_accum_param_s param;
1776         param.pinst = (void *)&inst;
1777         param.graphics_state = (void *)&s;
1778         param.pinst_id = inst.id;
1779 
1780         code = (*dev_proc(pdev, dev_spec_op))((gx_device *)pdev,
1781             gxdso_pattern_start_accum, &param, sizeof(pattern_accum_param_s));
1782     }
1783 
1784     if (code >= 0)
1785         pprintld1(pdev->strm, "/R%ld Do\n", pdf_resource_id(pres1));
1786     pres = pdev->accumulating_substream_resource;
1787     if (code >= 0)
1788         code = pdf_add_resource(pdev, pdev->substream_Resources, "/XObject", pres1);
1789     if (code >= 0) {
1790         pattern_accum_param_s param;
1791         param.pinst = (void *)&inst;
1792         param.graphics_state = (void *)&s;
1793         param.pinst_id = inst.id;
1794 
1795         code = (*dev_proc(pdev, dev_spec_op))((gx_device *)pdev,
1796             gxdso_pattern_finish_accum, &param, id);
1797     }
1798     if (code >= 0)
1799         code = (*dev_proc(pdev, dev_spec_op))((gx_device *)pdev,
1800             gxdso_pattern_load, &inst, id);
1801     if (code >= 0) {
1802         stream_puts(pdev->strm, "q ");
1803         code = pdf_cs_Pattern_colored(pdev, &v);
1804     }
1805     if (code >= 0) {
1806         cos_value_write(&v, pdev);
1807         pprintld1(pdev->strm, " cs /R%ld scn ", pdf_resource_id(pres));
1808     }
1809     if (code >= 0) {
1810         /* The image offset weas broken in gx_begin_image3_generic,
1811            (see 'origin' in there).
1812            As a temporary hack use the offset of the image.
1813            fixme : This isn't generally correct,
1814            because the mask may be "transpozed" against the image. */
1815         gs_matrix m = pdev->converting_image_matrix;
1816 
1817         m.tx = pmat->tx;
1818         m.ty = pmat->ty;
1819         code = pdf_do_image_by_id(pdev, pdev->image_mask_scale,
1820              &m, true, pdev->image_mask_id);
1821         stream_puts(pdev->strm, "Q\n");
1822     }
1823     return code;
1824 }
1825 
1826 typedef enum {
1827     USE_AS_MASK,
1828     USE_AS_IMAGE,
1829     USE_AS_PATTERN
1830 } pdf_image_usage_t;
1831 
1832 /* Close PDF image and do it. */
1833 static 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)1834 pdf_end_and_do_image(gx_device_pdf *pdev, pdf_image_writer *piw,
1835                      const gs_matrix *mat, gs_id ps_bitmap_id, pdf_image_usage_t do_image)
1836 {
1837     int code = pdf_end_write_image(pdev, piw);
1838     pdf_resource_t *pres = piw->pres;
1839 
1840     switch (code) {
1841     default:
1842         return code;	/* error */
1843     case 1:
1844         code = 0;
1845         break;
1846     case 0:
1847         if (do_image == USE_AS_IMAGE) {
1848             if (pdev->image_mask_id != gs_no_id) {
1849                 char buf[20];
1850 
1851                 gs_sprintf(buf, "%ld 0 R", pdev->image_mask_id);
1852                 code = cos_dict_put_string_copy((cos_dict_t *)pres->object,
1853                         pdev->image_mask_is_SMask ? "/SMask" : "/Mask", buf);
1854                 (*(pres->object)).md5_valid = 0;
1855                 if (code < 0)
1856                     return code;
1857             }
1858             if (pdev->image_mask_skip)
1859                 code = 0;
1860             else
1861                 code = pdf_do_image(pdev, pres, mat, true);
1862         } else if (do_image == USE_AS_MASK) {
1863             /* Provide data for pdf_do_image_by_id, which will be called through
1864                 use_image_as_pattern during the next call to this function.
1865                 See pdf_do_image about the meaning of 'scale'. */
1866             const pdf_x_object_t *const pxo = (const pdf_x_object_t *)pres;
1867 
1868             pdev->image_mask_scale = (double)pxo->data_height / pxo->height;
1869             pdev->image_mask_id = pdf_resource_id(pres);
1870             pdev->converting_image_matrix = *mat;
1871         } else if (do_image == USE_AS_PATTERN)
1872             code = use_image_as_pattern(pdev, pres, mat, ps_bitmap_id);
1873     }
1874     return code;
1875 }
1876 
1877 /* Clean up by releasing the buffers. */
1878 static int
pdf_image_end_image_data(gx_image_enum_common_t * info,bool draw_last,pdf_image_usage_t do_image)1879 pdf_image_end_image_data(gx_image_enum_common_t * info, bool draw_last,
1880                          pdf_image_usage_t do_image)
1881 {
1882     gx_device_pdf *pdev = (gx_device_pdf *)info->dev;
1883     pdf_image_enum *pie = (pdf_image_enum *)info;
1884     int height = pie->writer.height;
1885     int data_height = height - pie->rows_left;
1886     int code = 0, ecode;
1887 
1888     if (pie->writer.pres)
1889         ((pdf_x_object_t *)pie->writer.pres)->data_height = data_height;
1890     else if (data_height > 0)
1891         pdf_put_image_matrix(pdev, &pie->mat, (double)data_height / height);
1892     if (data_height > 0) {
1893         if (pie->writer.pres) {
1894             code = pdf_complete_image_data(pdev, &pie->writer, data_height,
1895                         pie->width, pie->bits_per_pixel);
1896             if (code < 0)
1897                 return code;
1898         }
1899         code = pdf_end_image_binary(pdev, &pie->writer, data_height);
1900         /* The call above possibly decreases pie->writer.alt_writer_count in 2. */
1901         if (code < 0)
1902             return code;
1903         if (pie->writer.alt_writer_count == 2) {
1904             /* We're converting a type 4 image into an imagemask with a pattern color. */
1905             /* Since the type 3 image writes the mask first, do so here. */
1906             pdf_image_writer writer = pie->writer;
1907 
1908             writer.binary[0] = pie->writer.binary[1];
1909             writer.pres = pie->writer.pres_mask;
1910             writer.alt_writer_count = 1;
1911             memset(&pie->writer.binary[1], 0, sizeof(pie->writer.binary[1]));
1912             pie->writer.alt_writer_count--; /* For GC. */
1913             pie->writer.pres_mask = 0; /* For GC. */
1914             code = pdf_end_image_binary(pdev, &writer, data_height);
1915             if (code < 0)
1916                 return code;
1917             code = pdf_end_and_do_image(pdev, &writer, &pie->mat, info->id, USE_AS_MASK);
1918             if (code < 0)
1919                 return code;
1920             code = pdf_end_and_do_image(pdev, &pie->writer, &pie->mat, info->id, USE_AS_PATTERN);
1921         } else
1922             code = pdf_end_and_do_image(pdev, &pie->writer, &pie->mat, info->id, do_image);
1923         pie->writer.alt_writer_count--; /* For GC. */
1924     }
1925     if (pie->initial_colorspace != pdev->pcm_color_info_index)
1926         pdf_set_process_color_model(pdev, pie->initial_colorspace);
1927 
1928     /* Clean up any outstanding streams before freeing the enumerator */
1929     while (pie->writer.alt_writer_count-- > 0) {
1930         ecode = psdf_end_binary(&(pie->writer.binary[pie->writer.alt_writer_count]));
1931         if (ecode < 0 && code >= 0) code  = ecode;
1932     }
1933 
1934     gx_image_free_enum(&info);
1935     return code;
1936 }
1937 
1938 /* End a normal image, drawing it. */
1939 static int
pdf_image_end_image(gx_image_enum_common_t * info,bool draw_last)1940 pdf_image_end_image(gx_image_enum_common_t * info, bool draw_last)
1941 {
1942     return pdf_image_end_image_data(info, draw_last, USE_AS_IMAGE);
1943 }
1944 
1945 /* End an image converted with pdf_lcvd_t. */
1946 static int
pdf_image_end_image_cvd(gx_image_enum_common_t * info,bool draw_last)1947 pdf_image_end_image_cvd(gx_image_enum_common_t * info, bool draw_last)
1948 {   pdf_lcvd_t *cvd = (pdf_lcvd_t *)info->dev;
1949     int code = pdf_dump_converted_image(cvd->pdev, cvd);
1950     int code1 = gx_image1_end_image(info, draw_last);
1951     int code2 = gs_closedevice((gx_device *)cvd->mask);
1952     int code3 = gs_closedevice((gx_device *)cvd);
1953 
1954     gs_free_object(cvd->mask->memory, (gx_device *)cvd->mask, "pdf_image_end_image_cvd");
1955     gs_free_object(cvd->mdev.memory, (gx_device *)cvd, "pdf_image_end_image_cvd");
1956     return code < 0 ? code : code1 < 0 ? code1 : code2 < 0 ? code2 : code3;
1957 }
1958 /* ---------------- Type 3/3x images ---------------- */
1959 
1960 /*
1961  * For both types of masked images, we create temporary dummy (null) devices
1962  * that forward the begin_typed_image call to the implementation above.
1963  */
1964 static int
pdf_make_mxd(gx_device ** pmxdev,gx_device * tdev,gs_memory_t * mem)1965 pdf_make_mxd(gx_device **pmxdev, gx_device *tdev, gs_memory_t *mem)
1966 {
1967     gx_device *fdev;
1968     int code = gs_copydevice(&fdev, (const gx_device *)&gs_null_device, mem);
1969 
1970     if (code < 0)
1971         return code;
1972     gx_device_set_target((gx_device_forward *)fdev, tdev);
1973     *pmxdev = fdev;
1974     return 0;
1975 }
1976 
1977 /* End the mask of an ImageType 3 image, not drawing it. */
1978 static int
pdf_image_end_image_object(gx_image_enum_common_t * info,bool draw_last)1979 pdf_image_end_image_object(gx_image_enum_common_t * info, bool draw_last)
1980 {
1981     return pdf_image_end_image_data(info, draw_last, USE_AS_MASK);
1982 }
1983 /* End the data of an ImageType 3 image, converting it into pattern. */
1984 static int
pdf_image_end_image_object2(gx_image_enum_common_t * info,bool draw_last)1985 pdf_image_end_image_object2(gx_image_enum_common_t * info, bool draw_last)
1986 {
1987     return pdf_image_end_image_data(info, draw_last, USE_AS_PATTERN);
1988 }
1989 
1990 /* ---------------- Type 3 images ---------------- */
1991 
1992 /* Implement the mask image device. */
1993 static dev_proc_begin_typed_image(pdf_mid_begin_typed_image);
1994 static int
pdf_image3_make_mid(gx_device ** pmidev,gx_device * dev,int width,int height,gs_memory_t * mem)1995 pdf_image3_make_mid(gx_device **pmidev, gx_device *dev, int width, int height,
1996                     gs_memory_t *mem)
1997 {
1998     gx_device_pdf *pdev = (gx_device_pdf *)dev;
1999 
2000     if (pdev->CompatibilityLevel < 1.3 && !pdev->PatternImagemask) {
2001         gs_matrix m;
2002         pdf_lcvd_t *cvd = NULL;
2003         int code;
2004 
2005         gs_make_identity(&m);
2006         code = pdf_setup_masked_image_converter(pdev, mem, &m, &cvd,
2007                                         true, 0, 0, width, height, true);
2008         if (code < 0)
2009             return code;
2010         cvd->mask->target = (gx_device *)cvd; /* Temporary, just to communicate with
2011                                          pdf_image3_make_mcde. The latter will reset it. */
2012         cvd->mask_is_empty = false;
2013         *pmidev = (gx_device *)cvd->mask;
2014         return 0;
2015     } else {
2016         int code = pdf_make_mxd(pmidev, dev, mem);
2017 
2018         if (code < 0)
2019             return code;
2020         set_dev_proc(*pmidev, begin_typed_image, pdf_mid_begin_typed_image);
2021         return 0;
2022     }
2023 }
2024 static int
pdf_mid_begin_typed_image(gx_device * dev,const gs_gstate * pgs,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)2025 pdf_mid_begin_typed_image(gx_device * dev, const gs_gstate * pgs,
2026                           const gs_matrix *pmat, const gs_image_common_t *pic,
2027                           const gs_int_rect * prect,
2028                           const gx_drawing_color * pdcolor,
2029                           const gx_clip_path * pcpath, gs_memory_t * mem,
2030                           gx_image_enum_common_t ** pinfo)
2031 {
2032     /* The target of the null device is the pdfwrite device. */
2033     gx_device_pdf *const pdev = (gx_device_pdf *)
2034         ((gx_device_null *)dev)->target;
2035     return pdf_begin_typed_image
2036         (pdev, pgs, pmat, pic, prect, pdcolor, pcpath, mem, pinfo,
2037          PDF_IMAGE_TYPE3_MASK);
2038 }
2039 
2040 /* Implement the mask clip device. */
2041 static int
pdf_image3_make_mcde(gx_device * dev,const gs_gstate * pgs,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)2042 pdf_image3_make_mcde(gx_device *dev, const gs_gstate *pgs,
2043                      const gs_matrix *pmat, const gs_image_common_t *pic,
2044                      const gs_int_rect *prect, const gx_drawing_color *pdcolor,
2045                      const gx_clip_path *pcpath, gs_memory_t *mem,
2046                      gx_image_enum_common_t **pinfo,
2047                      gx_device **pmcdev, gx_device *midev,
2048                      gx_image_enum_common_t *pminfo,
2049                      const gs_int_point *origin)
2050 {
2051     int code;
2052     gx_device_pdf *pdev = (gx_device_pdf *)dev;
2053 
2054     if (pdev->CompatibilityLevel < 1.3 && !pdev->PatternImagemask) {
2055         /* pdf_image3_make_mid must set midev with a pdf_lcvd_t instance.*/
2056         pdf_lcvd_t *cvd = (pdf_lcvd_t *)((gx_device_memory *)midev)->target;
2057 
2058         ((gx_device_memory *)midev)->target = NULL;
2059         cvd->m = pdev->converting_image_matrix;
2060         cvd->mdev.mapped_x = origin->x;
2061         cvd->mdev.mapped_y = origin->y;
2062         *pmcdev = (gx_device *)&cvd->mdev;
2063         code = gx_default_begin_typed_image
2064             ((gx_device *)&cvd->mdev, pgs, pmat, pic, prect, pdcolor, NULL, mem,
2065             pinfo);
2066         if (code < 0)
2067             return code;
2068     } else {
2069         code = pdf_make_mxd(pmcdev, midev, mem);
2070         if (code < 0)
2071             return code;
2072         code = pdf_begin_typed_image
2073             ((gx_device_pdf *)dev, pgs, pmat, pic, prect, pdcolor, pcpath, mem,
2074             pinfo, PDF_IMAGE_TYPE3_DATA);
2075         if (code < 0)
2076             return code;
2077     }
2078     /* Due to equal image merging, we delay the adding of the "Mask" entry into
2079        a type 3 image dictionary until the mask is completed.
2080        Will do in pdf_end_and_do_image.*/
2081     return 0;
2082 }
2083 
2084 /* ---------------- Type 3x images ---------------- */
2085 
2086 /* Implement the mask image device. */
2087 static int
pdf_image3x_make_mid(gx_device ** pmidev,gx_device * dev,int width,int height,int depth,gs_memory_t * mem)2088 pdf_image3x_make_mid(gx_device **pmidev, gx_device *dev, int width, int height,
2089                      int depth, gs_memory_t *mem)
2090 {
2091     int code = pdf_make_mxd(pmidev, dev, mem);
2092 
2093     if (code < 0)
2094         return code;
2095     set_dev_proc(*pmidev, begin_typed_image, pdf_mid_begin_typed_image);
2096     return 0;
2097 }
2098 
2099 /* Implement the mask clip device. */
2100 static int
pdf_image3x_make_mcde(gx_device * dev,const gs_gstate * pgs,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)2101 pdf_image3x_make_mcde(gx_device *dev, const gs_gstate *pgs,
2102                       const gs_matrix *pmat, const gs_image_common_t *pic,
2103                       const gs_int_rect *prect,
2104                       const gx_drawing_color *pdcolor,
2105                       const gx_clip_path *pcpath, gs_memory_t *mem,
2106                       gx_image_enum_common_t **pinfo,
2107                       gx_device **pmcdev, gx_device *midev[2],
2108                       gx_image_enum_common_t *pminfo[2],
2109                       const gs_int_point origin[2],
2110                       const gs_image3x_t *pim)
2111 {
2112     int code;
2113     pdf_image_enum *pmie;
2114     int i;
2115     const gs_image3x_mask_t *pixm;
2116 
2117     if (midev[0]) {
2118         if (midev[1])
2119             return_error(gs_error_rangecheck);
2120         i = 0, pixm = &pim->Opacity;
2121     } else if (midev[1])
2122         i = 1, pixm = &pim->Shape;
2123     else
2124         return_error(gs_error_rangecheck);
2125     code = pdf_make_mxd(pmcdev, midev[i], mem);
2126     if (code < 0)
2127         return code;
2128     code = pdf_begin_typed_image
2129         ((gx_device_pdf *)dev, pgs, pmat, pic, prect, pdcolor, pcpath, mem,
2130          pinfo, PDF_IMAGE_TYPE3_DATA);
2131     if (code < 0)
2132         return code;
2133     if ((*pinfo)->procs != &pdf_image_enum_procs) {
2134         /* We couldn't handle the image.  Bail out. */
2135         gx_image_end(*pinfo, false);
2136         gs_free_object(mem, *pmcdev, "pdf_image3x_make_mcde");
2137         return_error(gs_error_rangecheck);
2138     }
2139     pmie = (pdf_image_enum *)pminfo[i];
2140     /*
2141      * Add the SMask entry to the image dictionary, and, if needed,
2142      * the Matte entry to the mask dictionary.
2143      */
2144     if (pixm->has_Matte) {
2145         gx_device_pdf *pdev = (gx_device_pdf *)dev;
2146         int DoMatte = 0, num_components =
2147             gs_color_space_num_components(pim->ColorSpace);
2148 
2149         switch (pdev->params.ColorConversionStrategy) {
2150             case ccs_LeaveColorUnchanged:
2151                 DoMatte = 1;
2152                 break;
2153             case ccs_RGB:
2154             case ccs_sRGB:
2155                 if (num_components == 3)
2156                     DoMatte = 1;
2157                 else
2158                     DoMatte = 0;
2159                 break;
2160             case ccs_CMYK:
2161                 if (num_components == 4)
2162                     DoMatte = 1;
2163                 else
2164                     DoMatte = 0;
2165                 break;
2166             case ccs_Gray:
2167                 if (num_components == 1)
2168                     DoMatte = 1;
2169                 else
2170                     DoMatte = 0;
2171                 break;
2172             case ccs_UseDeviceIndependentColor:
2173             case ccs_UseDeviceIndependentColorForImages:
2174             case ccs_ByObjectType:
2175             default:
2176                 DoMatte = 0;
2177                 break;
2178         }
2179 
2180         if (DoMatte) {
2181             code = cos_dict_put_c_key_floats((gx_device_pdf *)dev,
2182                                     (cos_dict_t *)pmie->writer.pres->object,
2183                                     "/Matte", pixm->Matte,
2184                                     num_components);
2185             if (code < 0)
2186                 return code;
2187         }
2188     }
2189 /* Don't put SMask here because pmie->writer.pres->object may be substituted
2190  * after the image stream is accummulated. pdf_end_and_do_image will set
2191  * SMask with the right value. Bug 690345.
2192  */
2193     return 0;
2194 }
2195 
pdf_substitute_pattern(pdf_resource_t * pres)2196 pdf_resource_t *pdf_substitute_pattern(pdf_resource_t *pres)
2197 {
2198     pdf_pattern_t *ppat = (pdf_pattern_t *)pres;
2199 
2200     return (pdf_resource_t *)(ppat->substitute != 0 ? ppat->substitute : ppat);
2201 }
2202 
2203 static int
check_unsubstituted2(gx_device_pdf * pdev,pdf_resource_t * pres0,pdf_resource_t * pres1)2204 check_unsubstituted2(gx_device_pdf * pdev, pdf_resource_t *pres0, pdf_resource_t *pres1)
2205 {
2206     pdf_pattern_t *ppat0 = (pdf_pattern_t *)pres0;
2207     pdf_pattern_t *ppat1 = (pdf_pattern_t *)pres1;
2208 
2209     return (ppat0->substitute == NULL && ppat1->substitute == NULL);
2210 }
2211 
2212 static int
check_unsubstituted1(gx_device_pdf * pdev,pdf_resource_t * pres0)2213 check_unsubstituted1(gx_device_pdf * pdev, pdf_resource_t *pres0)
2214 {
2215     pdf_pattern_t *ppat = (pdf_pattern_t *)pres0;
2216 
2217     return ppat->substitute != NULL;
2218 }
2219 
2220 /*
2221    The device specific operations - just pattern management.
2222    See gxdevcli.h about return codes.
2223  */
2224 int
gdev_pdf_dev_spec_op(gx_device * pdev1,int dev_spec_op,void * data,int size)2225 gdev_pdf_dev_spec_op(gx_device *pdev1, int dev_spec_op, void *data, int size)
2226 {
2227     gx_device_pdf *pdev = (gx_device_pdf *)pdev1;
2228     int code=0, force_CTM_change=0;
2229     pdf_resource_t *pres, *pres1;
2230     gx_bitmap_id id = (gx_bitmap_id)size;
2231 
2232     switch (dev_spec_op) {
2233         case gxdso_pattern_can_accum:
2234             return 1;
2235         case gxdso_pdf_form_name:
2236             if (pdev->PDFFormName) {
2237                 gs_free_object(pdev->memory->non_gc_memory, pdev->PDFFormName, "free Name of Form for pdfmark");
2238             }
2239             pdev->PDFFormName = (char *)gs_alloc_bytes(pdev->memory->non_gc_memory, size + 1, "Name of Form for pdfmark");
2240             memset(pdev->PDFFormName, 0x00, size + 1);
2241             memcpy(pdev->PDFFormName, data, size);
2242             return 0;
2243         case gxdso_pdf_last_form_ID:
2244             {
2245             int *i = (int *)data;
2246             *i = pdev->LastFormID;
2247             }
2248             return 0;
2249         case gxdso_form_begin:
2250             if ((!pdev->ForOPDFRead || pdev->HighLevelForm == 0) && pdev->PatternDepth == 0) {
2251                 gs_form_template_t *tmplate = (gs_form_template_t *)data;
2252                 float arry[6];
2253                 cos_dict_t *pcd = NULL, *pcd_Resources = NULL;
2254 
2255                 /* Make sure the document and page stream are open */
2256                 code = pdfwrite_pdf_open_document(pdev);
2257                 if (code < 0)
2258                     return code;
2259                 code = pdf_open_contents(pdev, PDF_IN_STREAM);
2260                 if (code < 0)
2261                     return code;
2262                 if (!pdev->PDFFormName) {
2263                     /* Put any extant clip out before we start the form */
2264                     code = pdf_put_clip_path(pdev, tmplate->pcpath);
2265                     if (code < 0)
2266                         return code;
2267                     /* Set the CTM to be the one passed in from the interpreter,
2268                      * this allows us to spot forms even when translation/rotation takes place
2269                      * as we remove the CTN from the form stream before capture
2270                      */
2271                     pprintg6(pdev->strm, "q %g %g %g %g %g %g cm\n", tmplate->CTM.xx, tmplate->CTM.xy,
2272                              tmplate->CTM.yx, tmplate->CTM.yy, tmplate->CTM.tx, tmplate->CTM.ty);
2273                 }
2274 
2275                 /* start capturing the form stream */
2276                 code = pdf_enter_substream(pdev, resourceXObject, id, &pres, false,
2277                         pdev->CompressStreams);
2278                 if (code < 0)
2279                     return code;
2280                 pcd = cos_stream_dict((cos_stream_t *)pres->object);
2281                 pcd_Resources = cos_dict_alloc(pdev, "pdf_pattern(Resources)");
2282                 if (pcd == NULL || pcd_Resources == NULL)
2283                     return_error(gs_error_VMerror);
2284                 code = cos_dict_put_c_strings(pcd, "/Type", "/XObject");
2285                 if (code >= 0)
2286                     code = cos_dict_put_c_strings(pcd, "/Subtype", "/Form");
2287                 if (code >= 0)
2288                     code = cos_dict_put_c_strings(pcd, "/FormType", "1");
2289                 if (code >= 0)
2290                     code = cos_dict_put_c_key_object(pcd, "/Resources", COS_OBJECT(pcd_Resources));
2291 
2292                 if (pdev->PDFFormName) {
2293                     /* This is not (I think) required when executing PS forms, because the
2294                      * CTM is written out before we execute the Form. It *is* required for
2295                      * PDF Appearance Forms, because the Form is written directly from the
2296                      * outer context, not from the page, so we don't emit the CTM first.
2297                      * We want to alter the Form BBox to take any required rotation and scaling
2298                      * (from FitPage and /Rotate) into account so that the form appearance is
2299                      * properly scaled and rotated.
2300                      */
2301                     gs_rect bbox_out;
2302                     gs_matrix cmat, new_mat = tmplate->CTM;
2303 
2304                     /* We don't want anything left over from the page content stream, or other
2305                      * annotation appearances, to affect whether or not we emit any graphics
2306                      * state, so reset the state here to the defaults.
2307                      */
2308                     pdf_viewer_state_from_gs_gstate(pdev, tmplate->pgs, NULL);
2309                     /* For PDF Appearance streams at least, the Form BBox is modified by the
2310                      * Form Matrix.
2311                      */
2312                     code = gs_matrix_multiply(&tmplate->form_matrix, &tmplate->CTM, &cmat);
2313                     if (code < 0)
2314                         return code;
2315                     code = gs_bbox_transform(&tmplate->BBox, &cmat, &bbox_out);
2316                     if (code < 0)
2317                         return code;
2318 
2319                     /* Check the BBox is on the page. Modify it if it is not (this can happen
2320                      * if the MediaBox does not have bottom left at 0,0)
2321                      */
2322                     cmat.xx = cmat.yy = 1.0f;
2323                     cmat.xy = cmat.yx = cmat.tx = cmat.ty = 0.0f;
2324                     if(bbox_out.q.x - bbox_out.p.x > pdev->width) {
2325                         cmat.xx = pdev->width / (bbox_out.q.x - bbox_out.p.x);
2326                         bbox_out.q.x = bbox_out.p.x + ((bbox_out.q.x - bbox_out.p.x) * cmat.xx);
2327                         force_CTM_change = 1;
2328                     }
2329                     if(bbox_out.q.y - bbox_out.p.y > pdev->height) {
2330                         cmat.yy = pdev->height / (bbox_out.q.y - bbox_out.p.y);
2331                         bbox_out.q.y = bbox_out.p.y + ((bbox_out.q.y - bbox_out.p.y) * cmat.yy);
2332                         force_CTM_change = 1;
2333                     }
2334 
2335                     if (bbox_out.p.x < 0) {
2336                         cmat.tx = bbox_out.p.x * -1;
2337                         bbox_out.q.x += cmat.tx;
2338                         force_CTM_change = 1;
2339                     }
2340                     if (floor(bbox_out.q.x) > pdev->width) {
2341                         cmat.tx -= bbox_out.p.x;
2342                         bbox_out.q.x -= bbox_out.p.x;
2343                         bbox_out.p.x = 0;
2344                         force_CTM_change = 1;
2345                     }
2346                     if (bbox_out.p.y < 0) {
2347                         cmat.ty = bbox_out.p.y * -1;
2348                         bbox_out.q.y += cmat.ty;
2349                         force_CTM_change = 1;
2350                     }
2351                     if (floor(bbox_out.q.y) > pdev->height) {
2352                         cmat.ty += pdev->height - bbox_out.q.y;
2353                         force_CTM_change = 1;
2354                     }
2355 
2356                     if (force_CTM_change) {
2357                         code = gs_matrix_multiply(&tmplate->CTM, &cmat, &new_mat);
2358                         if (code < 0)
2359                             return code;
2360                         code = gs_matrix_multiply(&tmplate->form_matrix, &new_mat, &cmat);
2361                         if (code < 0)
2362                             return code;
2363                         code = gs_bbox_transform(&tmplate->BBox, &cmat, &bbox_out);
2364                         if (code < 0)
2365                             return code;
2366                         tmplate->CTM = cmat;
2367                     }
2368                     arry[0] = bbox_out.p.x;
2369                     arry[1] = bbox_out.p.y;
2370                     arry[2] = bbox_out.q.x;
2371                     arry[3] = bbox_out.q.y;
2372                     if (code >= 0)
2373                         code = cos_dict_put_c_key_floats(pdev, pcd, "/BBox", arry, 4);
2374                     if (code < 0)
2375                         return code;
2376 
2377                     /* Note that we will apply the CTM to the form, and the Form Matrix. To prevcent
2378                      * us applying the Matrix twice, we need to set it to the identity in the Form
2379                      * dictionary. I'm not sure why we don't need to do that for PostScript Forms.
2380                      */
2381                     arry[0] = arry[3] = 1.0f;
2382                     arry[1] = arry[2] = arry[4] = arry[5] = 0.0f;
2383                 } else {
2384                     arry[0] = tmplate->BBox.p.x;
2385                     arry[1] = tmplate->BBox.p.y;
2386                     arry[2] = tmplate->BBox.q.x;
2387                     arry[3] = tmplate->BBox.q.y;
2388                     if (code >= 0)
2389                         code = cos_dict_put_c_key_floats(pdev, pcd, "/BBox", arry, 4);
2390                     if (code < 0)
2391                         return code;
2392 
2393                     arry[0] = tmplate->form_matrix.xx;
2394                     arry[1] = tmplate->form_matrix.xy;
2395                     arry[2] = tmplate->form_matrix.yx;
2396                     arry[3] = tmplate->form_matrix.yy;
2397                     arry[4] = tmplate->form_matrix.tx;
2398                     arry[5] = tmplate->form_matrix.ty;
2399 
2400                     pprintg2(pdev->strm, "%g 0 0 %g 0 0 cm\n",
2401                          72.0 / pdev->HWResolution[0], 72.0 / pdev->HWResolution[1]);
2402                 }
2403 
2404                 code = cos_dict_put_c_key_floats(pdev, pcd, "/Matrix", arry, 6);
2405                 if (code < 0)
2406                     return code;
2407 
2408                 /* We'll return this to the interpreter and have it set
2409                  * as the CTM, so that we remove the prior CTM before capturing the form.
2410                  * This is safe because forms are always run inside a gsave/grestore, so
2411                  * CTM will be put back for us.
2412                  */
2413                 if (!pdev->PDFFormName) {
2414                     tmplate->CTM.xx = pdev->HWResolution[0] / 72;
2415                     tmplate->CTM.xy = 0.0;
2416                     tmplate->CTM.yx = 0.0;
2417                     tmplate->CTM.yy = pdev->HWResolution[0] / 72;
2418                     tmplate->CTM.tx = 0.0;
2419                     tmplate->CTM.ty = 0.0;
2420 
2421                     pdev->substream_Resources = pcd_Resources;
2422                     pres->rid = id;
2423                     if (code >= 0)
2424                         pdev->HighLevelForm++;
2425                     return 1;
2426                 } else {
2427                     /* For PDF Appearance streams (Forms) we *must* apply the
2428                      * CTM. This is because if the PDF has a non-zero Rotate key
2429                      * we bake that rotation into the CTM. If we didn't apply that
2430                      * then the annotation wouldn't get rotated :-(
2431                      */
2432                     pdev->substream_Resources = pcd_Resources;
2433                     pres->rid = id;
2434                     if (code >= 0)
2435                         pdev->HighLevelForm++;
2436                     return force_CTM_change;
2437                 }
2438             }
2439             return code;
2440         case gxdso_form_end:
2441             /* This test must be the same as the one in gxdso_form_begin, above */
2442             if ((!pdev->ForOPDFRead || pdev->HighLevelForm == 1) && pdev->PatternDepth == 0) {
2443                 if (pdev->CompatibilityLevel <= 1.7) {
2444                     code = pdf_add_procsets(pdev->substream_Resources, pdev->procsets);
2445                     if (code < 0)
2446                         return code;
2447                 }
2448                 pres = pres1 = pdev->accumulating_substream_resource;
2449                 code = pdf_exit_substream(pdev);
2450                 if (code < 0)
2451                     return code;
2452                 code = pdf_find_same_resource(pdev, resourceXObject, &pres, check_unsubstituted2);
2453                 if (code < 0)
2454                     return code;
2455                 if (code > 0) {
2456                     code = pdf_cancel_resource(pdev, pres1, resourceXObject);
2457                     if (code < 0)
2458                         return code;
2459                     pres->where_used |= pdev->used_mask;
2460                 } else if (pres->object->id < 0)
2461                     pdf_reserve_object_id(pdev, pres, 0);
2462                 if (pdev->PDFFormName) {
2463                     cos_value_t value;
2464 
2465                     code = cos_dict_put(pdev->local_named_objects, (const byte *)pdev->PDFFormName,
2466                         strlen(pdev->PDFFormName), cos_object_value(&value, pres->object));
2467 
2468                     if (code < 0)
2469                         return code;
2470                     pdf_drop_resource_from_chain(pdev, pres, resourceXObject);
2471 
2472                     gs_free_object(pdev->memory->non_gc_memory, pdev->PDFFormName, "free Name oof Form for pdfmark");
2473                     pdev->PDFFormName = 0x00;
2474                 } else {
2475                     pprintld1(pdev->strm, "/R%ld Do Q\n", pdf_resource_id(pres));
2476                 }
2477                 pdev->HighLevelForm--;
2478                 if (pdev->accumulating_substream_resource) {
2479                     code = pdf_add_resource(pdev, pdev->substream_Resources, "/XObject", pres);
2480                     if (code < 0)
2481                         return code;
2482                 }
2483                 pdev->LastFormID = pdf_resource_id(pres);
2484             }
2485             return 0;
2486         case gxdso_get_form_ID:
2487             {
2488                 int *ID = data;
2489                 *ID = pdev->LastFormID;
2490             }
2491             return 0;
2492         case gxdso_repeat_form:
2493             {
2494                 gs_form_template_t *tmplate = (gs_form_template_t *)data;
2495 
2496                 /* Make sure the document and page stream are open */
2497                 code = pdfwrite_pdf_open_document(pdev);
2498                 if (code < 0)
2499                     return code;
2500                 code = pdf_open_contents(pdev, PDF_IN_STREAM);
2501                 if (code < 0)
2502                     return code;
2503                 /* Put any extant clip out before we start the form */
2504                 code = pdf_put_clip_path(pdev, tmplate->pcpath);
2505                 if (code < 0)
2506                     return code;
2507                 /* Set the CTM to be the one passed in from the interpreter,
2508                  * this allows us to spot forms even when translation/rotation takes place
2509                  * as we remove the CTN from the form stream before capture
2510                  */
2511                 pprintg6(pdev->strm, "q %g %g %g %g %g %g cm\n", tmplate->CTM.xx, tmplate->CTM.xy,
2512                          tmplate->CTM.yx, tmplate->CTM.yy, tmplate->CTM.tx, tmplate->CTM.ty);
2513                 pprintld1(pdev->strm, "/R%ld Do Q\n", tmplate->FormID);
2514                 pres = pdf_find_resource_by_resource_id(pdev, resourceXObject, tmplate->FormID);
2515                 if (pres == NULL)
2516                     return_error(gs_error_undefined);
2517                 pres->where_used |= pdev->used_mask;
2518                 if (pdev->accumulating_substream_resource) {
2519                     code = pdf_add_resource(pdev, pdev->substream_Resources, "/XObject", pres);
2520                     if (code < 0)
2521                         return code;
2522                 }
2523             }
2524             return 0;
2525         case gxdso_pattern_start_accum:
2526             {
2527                 pattern_accum_param_s *param = (pattern_accum_param_s *)data;
2528                 gs_pattern1_instance_t *pinst = param->pinst;
2529                 gs_gstate *pgs = param->graphics_state;
2530 
2531                 id = param->pinst_id;
2532                 code = pdf_check_soft_mask(pdev, (gs_gstate *)pgs);
2533                 if (code < 0)
2534                     return code;
2535                 code = pdf_enter_substream(pdev, resourcePattern, id, &pres, false,
2536                         pdev->CompressStreams);
2537                 if (code < 0)
2538                     return code;
2539                 /* We have started a new substream, to avoid confusing the 'saved viewer state'
2540                  * (the stack of pdfwrite's saved copies of graophics states) we need to reset the
2541                  * soft_mask_id, which is the ID of the SMask we have already created in the pdfwrite
2542                  * output. The gsave/grestore round the spec_op to start and finish the pattern
2543                  * accumulator (see pattern_paint_prepare and pattern_paint_finish) will ensure that
2544                  * the ID is restored when we finish capturing the pattern.
2545                  */
2546                 pdev->state.soft_mask_id = pgs->soft_mask_id;
2547                 pres->rid = id;
2548                 code = pdf_store_pattern1_params(pdev, pres, pinst);
2549                 if (code < 0)
2550                     return code;
2551                 /* Scale the coordinate system, because object handlers assume so. See none_to_stream. */
2552                 pprintg2(pdev->strm, "%g 0 0 %g 0 0 cm\n",
2553                          72.0 / pdev->HWResolution[0], 72.0 / pdev->HWResolution[1]);
2554                 pdev->PatternDepth++;
2555                 pdev->PatternsSinceForm++;
2556             }
2557             return 1;
2558         case gxdso_pattern_finish_accum:
2559             if (pdev->CompatibilityLevel <= 1.7) {
2560                 if (pdev->substream_Resources == NULL) {
2561                     pdev->substream_Resources = cos_dict_alloc(pdev, "pdf_pattern(Resources)");
2562                     if (pdev->substream_Resources == NULL)
2563                         return_error(gs_error_VMerror);
2564                 }
2565                 code = pdf_add_procsets(pdev->substream_Resources, pdev->procsets);
2566                 if (code < 0)
2567                     return code;
2568             }
2569             pres = pres1 = pdev->accumulating_substream_resource;
2570             code = pdf_exit_substream(pdev);
2571             if (code < 0)
2572                 return code;
2573             if (pdev->substituted_pattern_count > 300 &&
2574                     pdev->substituted_pattern_drop_page != pdev->next_page) { /* arbitrary */
2575                 pdf_drop_resources(pdev, resourcePattern, check_unsubstituted1);
2576                 pdev->substituted_pattern_count = 0;
2577                 pdev->substituted_pattern_drop_page = pdev->next_page;
2578             }
2579             code = pdf_find_same_resource(pdev, resourcePattern, &pres, check_unsubstituted2);
2580             if (code < 0)
2581                 return code;
2582             if (code > 0) {
2583                 pdf_pattern_t *ppat = (pdf_pattern_t *)pres1;
2584 
2585                 code = pdf_cancel_resource(pdev, pres1, resourcePattern);
2586                 if (code < 0)
2587                     return code;
2588                 /* Do not remove pres1, because it keeps the substitution. */
2589                 ppat->substitute = (pdf_pattern_t *)pres;
2590                 pres->where_used |= pdev->used_mask;
2591                 pdev->substituted_pattern_count++;
2592             } else if (pres->object->id < 0)
2593                 pdf_reserve_object_id(pdev, pres, 0);
2594             pdev->PatternDepth--;
2595             pdev->PatternsSinceForm--;
2596             return 1;
2597         case gxdso_pattern_load:
2598             pres = pdf_find_resource_by_gs_id(pdev, resourcePattern, id);
2599             if (pres == 0)
2600                 return 0;
2601             pres = pdf_substitute_pattern(pres);
2602             pres->where_used |= pdev->used_mask;
2603             code = pdf_add_resource(pdev, pdev->substream_Resources, "/Pattern", pres);
2604             if (code < 0)
2605                 return code;
2606             return 1;
2607         case gxdso_pattern_shading_area:
2608             return 0;
2609         case gxdso_pattern_is_cpath_accum:
2610             return 0;
2611         case gxdso_pattern_shfill_doesnt_need_path:
2612             return 0; /* gdev_pdf_fill_path still does need a path. */
2613         case gxdso_pattern_handles_clip_path:
2614             /* This is important when the default implementation of
2615                of fill_path is called due to a failure in setcolor
2616                or so, for example when a shading is incorrect.
2617                The test case is the unfixed (buggy) Genoa test 446-01.ps .
2618                In this case pdfwrite converts the object into rectangles,
2619                and the clipping device has to be set up. */
2620             return 0;
2621         case gxdso_supports_hlcolor:
2622             /* This is used due to some aliasing between the rect_hl color
2623                filling used by pdfwrite vs. that used by the planar device
2624                which is actually a devn vs. the pattern type for pdfwrite.
2625                We use this to distingush between the two */
2626             return 1;
2627         case gxdso_needs_invariant_palette:
2628             /* Indicates that it is not permissible to change /Indexed colour space
2629              * palette entries after the colour space has been set.
2630              */
2631             return 1;
2632         case gxdso_JPEG_passthrough_query:
2633             pdev->JPEG_PassThrough = pdev->params.PassThroughJPEGImages;
2634             return 1;
2635             break;
2636         case gxdso_JPEG_passthrough_begin:
2637             return 0;
2638             break;
2639         case gxdso_JPEG_passthrough_data:
2640             if (pdev->JPEG_PassThrough && pdev->PassThroughWriter)
2641             {
2642                 uint ignore;
2643                 if (sputs(pdev->PassThroughWriter,
2644                            data, size,
2645                            &ignore) < 0)
2646                            return_error(gs_error_ioerror);
2647             }
2648             return 0;
2649             break;
2650         case gxdso_JPEG_passthrough_end:
2651             pdev->JPEG_PassThrough = 0;
2652             pdev->PassThroughWriter = 0;
2653             return 0;
2654             break;
2655         case gxdso_event_info:
2656             {
2657                 dev_param_req_t *request = (dev_param_req_t *)data;
2658                 if (memcmp(request->Param, "SubstitutedFont", 15) == 0 && pdev->PDFA) {
2659                     switch (pdev->PDFACompatibilityPolicy) {
2660                         case 0:
2661                         case 1:
2662                             emprintf(pdev->memory,
2663                              "\n **** A font missing from the input PDF has been substituted with a different font.\n\tWidths may differ, reverting to normal PDF output!\n");
2664                             pdev->AbortPDFAX = true;
2665                             pdev->PDFX = 0;
2666                             break;
2667                         case 2:
2668                             emprintf(pdev->memory,
2669                              "\n **** A font missing from the input PDF has been substituted with a different font.\n\tWidths may differ, aborting conversion!\n");
2670                             pdev->AbortPDFAX = true;
2671                             pdev->PDFX = 0;
2672                             return gs_note_error(gs_error_unknownerror);
2673                             break;
2674                         default:
2675                             emprintf(pdev->memory,
2676                              "\n **** A font missing from the input PDF has been substituted with a different font.\n\tWidths may differ, unknown PDFACompatibilityPolicy, reverting to normal PDF output!\n");
2677                             pdev->AbortPDFAX = true;
2678                             pdev->PDFX = 0;
2679                             break;
2680                     }
2681                 }
2682                 return 0;
2683             }
2684             break;
2685         case gxdso_get_dev_param:
2686             {
2687                 int code;
2688                 dev_param_req_t *request = (dev_param_req_t *)data;
2689                 code = gdev_pdf_get_param(pdev1, request->Param, request->list);
2690                 if (code != gs_error_undefined)
2691                     return code;
2692             }
2693             /* Fall through */
2694     }
2695     return gx_default_dev_spec_op(pdev1, dev_spec_op, data, size);
2696 }
2697