Coverage Report

Created: 2026-08-08 08:00

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