Coverage Report

Created: 2026-09-14 07:34

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
66.1k
{
118
66.1k
    return true;
119
66.1k
}
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
24
{
143
24
    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
24
        ) {
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
24
    return -1;     /* arbitrary <0 */
225
24
}
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
82.6k
{
231
232
82.6k
    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
82.6k
    return pdf_begin_image_data(pdev, &pie->writer, pi, cs_value, i);
247
82.6k
}
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.60k
{
254
2.60k
    gs_color_space *cs;
255
2.60k
    gs_memory_t *mem = pdev->v_memory;
256
257
2.60k
    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.60k
        case gs_color_space_index_DeviceRGB:
262
2.60k
            cs = gs_cspace_new_DeviceRGB(mem);
263
2.60k
            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.60k
    }
275
276
2.60k
    if (cs == NULL)
277
0
        return_error(gs_error_VMerror);
278
279
2.60k
    *ppcs = cs;
280
2.60k
    return 0;
281
2.60k
}
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
74.6k
{
318
74.6k
    const gs_image_t *pim1 = (const gs_image_t *)pic;
319
320
74.6k
    if (pim1->Alpha != gs_image_alpha_none)
321
0
        return -1;
322
74.6k
    if (pim1->ImageMask) {
323
        /* If parameters are invalid, use the fallback implementation. */
324
54.9k
        if (!(gx_dc_is_pattern1_color(pdcolor)))
325
54.6k
            if (pim1->BitsPerComponent != 1 ||
326
54.6k
                !((pim1->Decode[0] == 0.0 && pim1->Decode[1] == 1.0) ||
327
53.2k
                  (pim1->Decode[0] == 1.0 && pim1->Decode[1] == 0.0))
328
54.6k
                )
329
11
                return -1;
330
54.9k
    }
331
74.6k
    image[0].type1 = *pim1;
332
    /* If we can write in-line then make it so */
333
74.6k
    return (context == PDF_IMAGE_DEFAULT &&
334
66.1k
        can_write_image_in_line(pdev, pim1));
335
74.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
96
{
345
96
    const gs_image3_t *pim3 = (const gs_image3_t *)pic;
346
96
    gs_image3_t pim3a;
347
96
    const gs_image_common_t *pic1 = pic;
348
96
    gs_matrix m, mi;
349
96
    const gs_matrix *pmat1 = pmat;
350
96
    int code;
351
352
96
    if (pdev->CompatibilityLevel < 1.3 && !pdev->PatternImagemask) {
353
96
        code = pdf_check_soft_mask(pdev, (gs_gstate *)pgs);
354
96
        if (code < 0)
355
0
            return code;
356
96
        if (pdf_must_put_clip_path(pdev, pcpath))
357
22
            code = pdf_unclip(pdev);
358
74
        else
359
74
            code = pdf_open_page(pdev, PDF_IN_STREAM);
360
96
        if (code < 0)
361
0
            return code;
362
96
        code = pdf_put_clip_path(pdev, pcpath);
363
96
        if (code < 0)
364
0
            return code;
365
96
        gs_make_identity(&m);
366
96
        pmat1 = &m;
367
96
        m.tx = floor(pgs->ctm.tx + 0.5); /* Round the origin against the image size distorsions */
368
96
        m.ty = floor(pgs->ctm.ty + 0.5);
369
96
        pim3a = *pim3;
370
96
        code = gs_matrix_invert(&pim3a.ImageMatrix, &mi);
371
96
        if (code < 0)
372
1
            return code;
373
95
        gs_make_identity(&pim3a.ImageMatrix);
374
95
        if (pim3a.Width < pim3a.MaskDict.Width && pim3a.Width > 0) {
375
23
            int sx = (pim3a.MaskDict.Width + pim3a.Width - 1) / pim3a.Width;
376
377
23
            gs_matrix_scale(&mi, 1.0 / sx, 1, &mi);
378
23
            gs_matrix_scale(&pim3a.ImageMatrix, 1.0 / sx, 1, &pim3a.ImageMatrix);
379
23
        }
380
95
        if (pim3a.Height < pim3a.MaskDict.Height && pim3a.Height > 0) {
381
16
            int sy = (pim3a.MaskDict.Height + pim3a.Height - 1) / pim3a.Height;
382
383
16
            gs_matrix_scale(&mi, 1, 1.0 / sy, &mi);
384
16
            gs_matrix_scale(&pim3a.ImageMatrix, 1, 1.0 / sy, &pim3a.ImageMatrix);
385
16
        }
386
95
        gs_matrix_multiply(&mi, &pim3a.MaskDict.ImageMatrix, &pim3a.MaskDict.ImageMatrix);
387
95
        pim3a.imagematrices_are_untrustworthy = 1;
388
95
        pic1 = (gs_image_common_t *)&pim3a;
389
        /* Setting pdev->converting_image_matrix to communicate with pdf_image3_make_mcde. */
390
95
        gs_matrix_multiply(&mi, &ctm_only(pgs), &pdev->converting_image_matrix);
391
95
    }
392
    /*
393
     * We handle ImageType 3 images in a completely different way:
394
     * the default implementation sets up the enumerator.
395
     */
396
95
    return gx_begin_image3_generic((gx_device *)pdev, pgs, pmat1, pic1,
397
95
                                   prect, pdcolor, pcpath, mem,
398
95
                                   pdf_image3_make_mid,
399
95
                                   pdf_image3_make_mcde, pinfo);
400
96
}
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
24
{
411
    /* Try to convert the image to a plain masked image. */
412
24
    gx_drawing_color icolor;
413
24
    int code = 1;
414
415
24
    pdev->image_mask_is_SMask = false;
416
24
    if (pdf_convert_image4_to_image1(pdev, pgs, pdcolor,
417
24
                                     (const gs_image4_t *)pic,
418
24
                                     &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
24
    return code;
445
24
}
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
24
{
454
24
        gs_matrix m, m1, mi;
455
24
        gs_image4_t pi4 = *(const gs_image4_t *)pic;
456
24
        int code;
457
24
        pdf_lcvd_t *cvd = NULL;
458
459
24
        code = pdf_check_soft_mask(pdev, (gs_gstate *)pgs);
460
24
        if (code < 0)
461
0
            return code;
462
24
        if (pdf_must_put_clip_path(pdev, pcpath))
463
23
            code = pdf_unclip(pdev);
464
1
        else
465
1
            code = pdf_open_page(pdev, PDF_IN_STREAM);
466
24
        if (code < 0)
467
0
            return code;
468
24
        code = pdf_put_clip_path(pdev, pcpath);
469
24
        if (code < 0)
470
0
            return code;
471
24
        gs_make_identity(&m1);
472
24
        code = gs_matrix_invert(&pic->ImageMatrix, &mi);
473
24
        if (code < 0)
474
0
            return code;
475
24
        gs_matrix_multiply(&mi, &ctm_only(pgs), &m);
476
24
        code = pdf_setup_masked_image_converter(pdev, mem, &m, &cvd,
477
24
                             true, 0, 0, pi4.Width, pi4.Height, false);
478
24
        if (code < 0)
479
0
            return code;
480
24
        cvd->mdev.is_open = true; /* fixme: same as above. */
481
24
        cvd->mask->is_open = true; /* fixme: same as above. */
482
24
        cvd->mask_is_empty = false;
483
24
        code = (*dev_proc(cvd->mask, fill_rectangle))((gx_device *)cvd->mask,
484
24
                    0, 0, cvd->mask->width, cvd->mask->height, (gx_color_index)0);
485
24
        if (code < 0)
486
0
            return code;
487
24
        gx_device_retain((gx_device *)cvd, true);
488
24
        gx_device_retain((gx_device *)cvd->mask, true);
489
24
        gs_make_identity(&pi4.ImageMatrix);
490
24
        code = gx_default_begin_typed_image((gx_device *)cvd,
491
24
            pgs, &m1, (gs_image_common_t *)&pi4, prect, pdcolor, NULL, mem, pinfo);
492
24
        if (code < 0)
493
0
            return code;
494
24
        (*pinfo)->procs = &pdf_image_cvd_enum_procs;
495
24
        return 0;
496
24
}
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.30k
{
501
1.30k
    int code;
502
1.30k
    gs_color_space *pcs_device = NULL;
503
504
1.30k
    cos_c_string_value(cs_value, sname);
505
1.30k
    *pcs_orig = image->pixel.ColorSpace;
506
1.30k
    code = make_device_color_space(pdev, pdev->pcm_color_info_index, &pcs_device);
507
1.30k
    if (code < 0)
508
0
        return code;
509
1.30k
    image->pixel.ColorSpace = pcs_device;
510
1.30k
    return 0;
511
1.30k
}
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
15.3k
{
547
15.3k
    int code=0;
548
15.3k
    gs_color_space_index csi;
549
15.3k
    gs_color_space_index csi2;
550
15.3k
    const gs_color_space *pcs2 = pcs;
551
552
15.3k
    csi = csi2 = gs_color_space_get_index(pcs);
553
15.3k
    if (csi == gs_color_space_index_ICC) {
554
13.1k
        csi2 = gsicc_get_default_type(pcs->cmm_icc_profile_data);
555
13.1k
    }
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
15.3k
    if (pdev->CompatibilityLevel <= 1.2) {
559
560
        /* If we have an /Indexed space, we need to look at the base space */
561
7.75k
        if (csi2 == gs_color_space_index_Indexed) {
562
1.21k
            pcs2 = pcs->base_space;
563
1.21k
            csi2 = gs_color_space_get_index(pcs2);
564
1.21k
        }
565
566
7.75k
        switch (csi2) {
567
788
            case gs_color_space_index_DeviceGray:
568
788
                if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
569
788
                    pdev->params.ColorConversionStrategy == ccs_Gray) {
570
788
                    return 0;
571
788
                }
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
4.54k
            case gs_color_space_index_DeviceRGB:
580
4.54k
                if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
581
0
                    pdev->params.ColorConversionStrategy == ccs_RGB || pdev->params.ColorConversionStrategy == ccs_sRGB)
582
4.54k
                    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
135
            case gs_color_space_index_DeviceCMYK:
591
135
                if ((pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
592
135
                    pdev->params.ColorConversionStrategy == ccs_CMYK) && !pdev->params.ConvertCMYKImagesToRGB)
593
135
                    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.25k
            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.25k
                csi2 = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
651
652
2.25k
                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
974
                    case gs_color_space_index_DeviceRGB:
659
974
                        if (pdev->params.ColorConversionStrategy == ccs_RGB || pdev->params.ColorConversionStrategy == ccs_sRGB ||
660
974
                            pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged)
661
974
                            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.28k
                    default:
669
1.28k
                        break;
670
2.25k
                }
671
                /* Fall through for non-handled cases */
672
1.30k
            case gs_color_space_index_DeviceN:
673
1.30k
            case gs_color_space_index_DevicePixel:
674
1.30k
            case gs_color_space_index_Indexed:
675
1.30k
                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.30k
                    case gs_color_space_index_DeviceRGB:
680
1.30k
                        code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceRGB, cs_value);
681
1.30k
                        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.30k
                }
689
1.30k
                if (code < 0)
690
0
                    return code;
691
1.30k
                return 1;
692
0
                break;
693
0
            default:
694
0
                return (gs_note_error(gs_error_rangecheck));
695
0
                break;
696
7.75k
        }
697
7.75k
    } else {
698
7.55k
        int strategy = pdev->params.ColorConversionStrategy;
699
700
7.55k
        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.55k
        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.55k
            case ccs_LeaveColorUnchanged:
729
7.55k
                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.55k
        }
999
7.55k
    }
1000
0
    return 0;
1001
15.3k
}
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
74.6k
{
1010
74.6k
    int code = 0;
1011
74.6k
    gs_rect sbox, dbox, *Box;
1012
74.6k
    gs_point corners[4];
1013
74.6k
    gs_fixed_rect ibox;
1014
74.6k
    gs_matrix * pmat1 = (gs_matrix *)pmat;
1015
74.6k
    gs_matrix mat;
1016
1017
74.6k
    if (!pdev->Eps2Write)
1018
41.2k
        return 0;
1019
1020
33.4k
    if (!pdev->accumulating_charproc)
1021
31.7k
        Box = &pdev->BBox;
1022
1.70k
    else
1023
1.70k
        Box = &pdev->charproc_BBox;
1024
33.4k
    if (pmat1 == 0)
1025
33.4k
        pmat1 = (gs_matrix *)&ctm_only(pgs);
1026
33.4k
    if ((code = gs_matrix_invert(&pic->ImageMatrix, &mat)) < 0 ||
1027
33.4k
        (code = gs_matrix_multiply(&mat, pmat1, &mat)) < 0)
1028
1
        goto exit;
1029
33.4k
    sbox.p.x = prect->p.x;
1030
33.4k
    sbox.p.y = prect->p.y;
1031
33.4k
    sbox.q.x = prect->q.x;
1032
33.4k
    sbox.q.y = prect->q.y;
1033
33.4k
    gs_bbox_transform_only(&sbox, &mat, corners);
1034
33.4k
    gs_points_bbox(corners, &dbox);
1035
33.4k
    ibox.p.x = float2fixed(dbox.p.x);
1036
33.4k
    ibox.p.y = float2fixed(dbox.p.y);
1037
33.4k
    ibox.q.x = float2fixed(dbox.q.x);
1038
33.4k
    ibox.q.y = float2fixed(dbox.q.y);
1039
33.4k
    if (pcpath != NULL &&
1040
32.3k
        !gx_cpath_includes_rectangle(pcpath, ibox.p.x, ibox.p.y,
1041
32.3k
                                     ibox.q.x, ibox.q.y)
1042
33.4k
        ) {
1043
        /* Let the target do the drawing, but drive two triangles */
1044
        /* through the clipping path to get an accurate bounding box. */
1045
5.31k
        gx_device_clip cdev;
1046
5.31k
        gx_drawing_color devc;
1047
1048
5.31k
        fixed x0 = float2fixed(corners[0].x), y0 = float2fixed(corners[0].y);
1049
5.31k
        fixed bx2 = float2fixed(corners[2].x) - x0, by2 = float2fixed(corners[2].y) - y0;
1050
1051
5.31k
        pdev->AccumulatingBBox++;
1052
5.31k
        gx_make_clip_device_on_stack(&cdev, pcpath, (gx_device *)pdev);
1053
5.31k
        set_nonclient_dev_color(&devc, gx_device_black((gx_device *)pdev));  /* any non-white color will do */
1054
5.31k
        gx_default_fill_triangle((gx_device *) & cdev, x0, y0,
1055
5.31k
                                 float2fixed(corners[1].x) - x0,
1056
5.31k
                                 float2fixed(corners[1].y) - y0,
1057
5.31k
                                 bx2, by2, &devc, lop_default);
1058
5.31k
        gx_default_fill_triangle((gx_device *) & cdev, x0, y0,
1059
5.31k
                                 float2fixed(corners[3].x) - x0,
1060
5.31k
                                 float2fixed(corners[3].y) - y0,
1061
5.31k
                                 bx2, by2, &devc, lop_default);
1062
5.31k
        gx_destroy_clip_device_on_stack(&cdev);
1063
5.31k
        pdev->AccumulatingBBox--;
1064
28.1k
    } else {
1065
        /* Just use the bounding box. */
1066
28.1k
        float x0, y0, x1, y1;
1067
28.1k
        x0 = fixed2float(ibox.p.x) / (pdev->HWResolution[0] / 72.0);
1068
28.1k
        y0 = fixed2float(ibox.p.y) / (pdev->HWResolution[1] / 72.0);
1069
28.1k
        x1 = fixed2float(ibox.q.x) / (pdev->HWResolution[0] / 72.0);
1070
28.1k
        y1 = fixed2float(ibox.q.y) / (pdev->HWResolution[1] / 72.0);
1071
28.1k
        if (Box->p.x > x0)
1072
1.51k
            Box->p.x = x0;
1073
28.1k
        if (Box->p.y > y0)
1074
1.80k
            Box->p.y = y0;
1075
28.1k
        if (Box->q.x < x1)
1076
2.42k
            Box->q.x = x1;
1077
28.1k
        if (Box->q.y < y1)
1078
2.82k
            Box->q.y = y1;
1079
28.1k
    }
1080
33.4k
 exit:
1081
33.4k
    return code;
1082
33.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
79.0k
{
1093
79.0k
    int code = 0, i;
1094
79.0k
    unsigned int use_fallback  = 0, in_line = 0, is_mask = 0,
1095
79.0k
        force_lossless = 0, convert_to_process_colors = 0;
1096
79.0k
    int width, height;
1097
79.0k
    cos_dict_t *pnamed = 0;
1098
79.0k
    image_union_t *image;
1099
79.0k
    const gs_pixel_image_t *pim;
1100
79.0k
    gs_int_rect rect;
1101
79.0k
    gs_image_format_t format;
1102
79.0k
    gs_color_space *pcs = NULL;
1103
79.0k
    int num_components;
1104
79.0k
    pdf_image_enum *pie = NULL;
1105
79.0k
    const pdf_color_space_names_t *names;
1106
79.0k
    gs_color_space *pcs_orig = NULL;
1107
79.0k
    gs_color_space *pcs_device = NULL;
1108
79.0k
    cos_value_t cs_value;
1109
79.0k
    const gs_range_t *pranges = 0;
1110
1111
79.0k
    image = (image_union_t *)gs_malloc(mem->non_gc_memory, 4,
1112
79.0k
                       sizeof(image_union_t), "pdf_begin_typed_image(image)");
1113
79.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
79.0k
    {
1121
79.0k
        cos_value_t ni_value;
1122
1123
79.0k
        if (cos_array_unadd(pdev->NI_stack, &ni_value) >= 0)
1124
7
            pnamed = (cos_dict_t *)ni_value.contents.object;
1125
79.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
79.0k
    pdev->image_mask_id = gs_no_id;
1131
1132
79.0k
    pim = (const gs_pixel_image_t *)pic;
1133
1134
    /* Check for the image types we can handle. */
1135
79.0k
    switch (pic->type->index) {
1136
74.6k
    case 1:
1137
74.6k
        is_mask = ((const gs_image_t *)pic)->ImageMask;
1138
74.6k
        code = setup_type1_image(pdev, pic, pdcolor, image, context);
1139
74.6k
        if (code < 0)
1140
11
            use_fallback = 1;
1141
74.6k
        else
1142
74.6k
            in_line = code;
1143
74.6k
        break;
1144
1145
96
    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
96
        pdev->JPEG_PassThrough = 0;
1161
96
        pdev->JPX_PassThrough = 0;
1162
96
        pdev->image_mask_is_SMask = false;
1163
96
        if (pdev->CompatibilityLevel < 1.2 ||
1164
96
            (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
96
        code = setup_type3_image(pdev, pgs, pmat, pic, prect, pdcolor, pcpath, mem, pinfo, image);
1171
96
        goto exit;
1172
1173
4.26k
    case IMAGE3X_IMAGETYPE:
1174
4.26k
        {
1175
4.26k
            char *OC = pdev->PendingOC;
1176
1177
4.26k
            pdev->JPEG_PassThrough = 0;
1178
4.26k
            pdev->JPX_PassThrough = 0;
1179
4.26k
            if (pdev->CompatibilityLevel < 1.4 ||
1180
4.26k
                (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.26k
            pdev->image_mask_is_SMask = true;
1187
1188
4.26k
            if (pdev->PendingOC)
1189
0
                gs_free_object(pdev->memory->non_gc_memory, pdev->PendingOC, "");
1190
4.26k
            OC = pdev->PendingOC = NULL;
1191
4.26k
            code = gx_begin_image3x_generic((gx_device *)pdev, pgs, pmat, pic,
1192
4.26k
                                            prect, pdcolor, pcpath, mem,
1193
4.26k
                                            pdf_image3x_make_mid,
1194
4.26k
                                            pdf_image3x_make_mcde, pinfo, OC);
1195
4.26k
            goto exit;
1196
4.26k
        }
1197
1198
24
    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
24
        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
24
        pdev->JPEG_PassThrough = 0;
1264
24
        pdev->JPX_PassThrough = 0;
1265
24
        code = convert_type4_image(pdev, pgs, pmat, pic, prect, pdcolor,
1266
24
                      pcpath, mem, pinfo, context, image, pnamed);
1267
24
        if (code < 0)
1268
0
            use_fallback = 1;
1269
24
        if (code == 0)
1270
0
            goto exit;
1271
        /* No luck.  Masked images require PDF 1.3 or higher. */
1272
24
        if (pdev->CompatibilityLevel < 1.2)
1273
0
            use_fallback = 1;
1274
24
        if (pdev->CompatibilityLevel < 1.3 && !pdev->PatternImagemask) {
1275
24
            use_fallback = 0;
1276
24
            code = convert_type4_to_masked_image(pdev, pgs, pic, prect, pdcolor,
1277
24
                                                 pcpath, mem,pinfo);
1278
24
            goto exit;
1279
24
        }
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
79.0k
    }
1287
1288
74.6k
    format = pim->format;
1289
74.6k
    switch (format) {
1290
74.6k
    case gs_image_format_chunky:
1291
74.6k
    case gs_image_format_component_planar:
1292
74.6k
        break;
1293
0
    default:
1294
0
        use_fallback = 1;
1295
74.6k
    }
1296
    /* AR5 on Windows doesn't support 0-size images. Skipping. */
1297
74.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
74.6k
    switch (pim->BitsPerComponent) {
1301
55.6k
        case 1:
1302
55.9k
        case 2:
1303
55.9k
        case 4:
1304
74.6k
        case 8:
1305
74.6k
        case 12:
1306
74.6k
        case 16:
1307
74.6k
            break;
1308
0
        default:
1309
0
            code = gs_note_error(gs_error_rangecheck);
1310
0
            goto exit;
1311
74.6k
    }
1312
74.6k
    if (prect)
1313
4.25k
        rect = *prect;
1314
70.3k
    else {
1315
70.3k
        rect.p.x = rect.p.y = 0;
1316
70.3k
        rect.q.x = pim->Width, rect.q.y = pim->Height;
1317
70.3k
    }
1318
74.6k
    if (rect.p.x != 0 || rect.p.y != 0 ||
1319
74.6k
        rect.q.x != pim->Width || rect.q.y != pim->Height ||
1320
74.6k
        (is_mask && pim->CombineWithColor))
1321
0
        use_fallback = 1;
1322
1323
    /* Handle BBox for Eps2Write, if applicable */
1324
74.6k
    code = pdf_image_handle_eps(pdev, pgs, pmat, pic, &rect, pcpath);
1325
74.6k
    if (code < 0) {
1326
1
        use_fallback = 0;
1327
1
        goto exit;
1328
1
    }
1329
1330
74.6k
    if (use_fallback)
1331
17
        goto exit;
1332
1333
74.6k
    pcs = pim->ColorSpace;
1334
74.6k
    rc_increment_cs(pcs);
1335
74.6k
    num_components = (is_mask ? 1 : gs_color_space_num_components(pcs));
1336
1337
74.6k
    code = pdf_check_soft_mask(pdev, (gs_gstate *)pgs);
1338
74.6k
    if (code < 0)
1339
0
        goto exit;
1340
74.6k
    if (pdf_must_put_clip_path(pdev, pcpath))
1341
5.53k
        code = pdf_unclip(pdev);
1342
69.0k
    else
1343
69.0k
        code = pdf_open_page(pdev, PDF_IN_STREAM);
1344
74.6k
    if (code < 0)
1345
0
        goto fail_and_fallback;
1346
1347
74.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.25k
        rc_decrement(pcs, "pdf_begin_typed_image(pcs)");
1355
4.25k
        pcs = gs_cspace_new_DeviceGray(pdev->memory);
1356
4.25k
        if (pcs == NULL)
1357
0
            code = gs_note_error(gs_error_VMerror);
1358
70.3k
    } else if (is_mask)
1359
54.9k
        code = pdf_prepare_imagemask(pdev, pgs, pdcolor);
1360
15.4k
    else
1361
15.4k
        code = pdf_prepare_image(pdev, pgs);
1362
74.6k
    if (code < 0)
1363
144
        goto fail_and_fallback;
1364
1365
74.4k
    pie = gs_alloc_struct(mem, pdf_image_enum, &st_pdf_image_enum,
1366
74.4k
                        "pdf_begin_image");
1367
74.4k
    if (pie == 0) {
1368
0
        code = gs_note_error(gs_error_VMerror);
1369
0
        goto exit;
1370
0
    }
1371
74.4k
    memset(pie, 0, sizeof(*pie)); /* cleanup entirely for GC to work in all cases. */
1372
74.4k
    *pinfo = (gx_image_enum_common_t *) pie;
1373
74.4k
    code = gx_image_enum_common_init(*pinfo, (const gs_data_image_t *) pim,
1374
74.4k
                    ((pdev->CompatibilityLevel >= 1.3) ?
1375
19.0k
                            (context == PDF_IMAGE_TYPE3_MASK ?
1376
4.25k
                            &pdf_image_object_enum_procs :
1377
19.0k
                            &pdf_image_enum_procs) :
1378
74.4k
                            context == PDF_IMAGE_TYPE3_MASK ?
1379
0
                            &pdf_image_object_enum_procs :
1380
55.4k
                            context == PDF_IMAGE_TYPE3_DATA ?
1381
0
                            &pdf_image_object_enum_procs2 :
1382
55.4k
                            &pdf_image_enum_procs),
1383
74.4k
                        (gx_device *)pdev, num_components, format);
1384
74.4k
    if (code < 0)
1385
0
        goto exit;
1386
1387
74.4k
    pie->memory = mem;
1388
74.4k
    pie->pgs = pgs;
1389
74.4k
    if (pgs != NULL)
1390
74.4k
        pie->pgs_level = pgs->level;
1391
74.4k
    width = rect.q.x - rect.p.x;
1392
74.4k
    pie->width = width;
1393
74.4k
    height = rect.q.y - rect.p.y;
1394
74.4k
    pie->bits_per_pixel =
1395
74.4k
        pim->BitsPerComponent * num_components / pie->num_planes;
1396
74.4k
    pie->rows_left = height;
1397
74.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
74.4k
    else {
1400
74.4k
        int64_t nbytes = (int64_t)(((int64_t) pie->width * pie->bits_per_pixel + 7) >> 3) *
1401
74.4k
            pie->num_planes * pie->rows_left;
1402
1403
74.4k
        in_line &= (nbytes < pdev->MaxInlineImageSize);
1404
74.4k
    }
1405
74.4k
    pie->initial_colorspace = pdev->pcm_color_info_index;
1406
1407
74.4k
    if (pmat == 0)
1408
65.9k
        pmat = &ctm_only(pgs);
1409
74.4k
    {
1410
74.4k
        gs_matrix mat;
1411
74.4k
        gs_matrix bmat;
1412
74.4k
        int code;
1413
1414
74.4k
        pdf_make_bitmap_matrix(&bmat, -rect.p.x, -rect.p.y,
1415
74.4k
                               pim->Width, pim->Height, height);
1416
74.4k
        if ((code = gs_matrix_invert(&pim->ImageMatrix, &mat)) < 0 ||
1417
74.4k
            (code = gs_matrix_multiply(&bmat, &mat, &mat)) < 0 ||
1418
74.4k
            (code = gs_matrix_multiply(&mat, pmat, &pie->mat)) < 0
1419
74.4k
            )
1420
0
            goto exit;
1421
        /* AR3,AR4 show no image when CTM is singular; AR5 reports an error */
1422
74.4k
        if (pie->mat.xx * pie->mat.yy == pie->mat.xy * pie->mat.yx) {
1423
490
            use_fallback = 1;
1424
490
            goto fail_and_fallback;
1425
490
        }
1426
74.4k
    }
1427
1428
73.9k
    code = pdf_put_clip_path(pdev, pcpath);
1429
73.9k
    if (code < 0)
1430
0
        goto exit;
1431
73.9k
    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
73.9k
    pie->writer.alt_writer_count = (in_line ||
1441
10.4k
                                    (pim->Width <= 64 && pim->Height <= 64)
1442
73.9k
                                    ? 1 : 2);
1443
73.9k
    if ((image[0].pixel.ColorSpace != NULL &&
1444
19.5k
        image[0].pixel.ColorSpace->type->index == gs_color_space_index_Indexed
1445
2.15k
        && pdev->params.ColorImage.DownsampleType != ds_Subsample) ||
1446
73.0k
        pdev->transfer_not_identity)
1447
951
        force_lossless = true;
1448
1449
73.9k
    if ((image[0].pixel.ColorSpace != NULL && image[0].pixel.ColorSpace->type->index == gs_color_space_index_Indexed)
1450
71.8k
        || force_lossless)
1451
2.16k
        pie->writer.alt_writer_count = 1;
1452
1453
73.9k
    if (image[0].pixel.ColorSpace != NULL && (image[0].pixel.ColorSpace->type->index != gs_color_space_index_DeviceGray &&
1454
19.5k
        image[0].pixel.ColorSpace->type->index != gs_color_space_index_DeviceRGB &&
1455
19.5k
        image[0].pixel.ColorSpace->type->index != gs_color_space_index_DeviceCMYK &&
1456
19.5k
        image[0].pixel.ColorSpace->type->index != gs_color_space_index_Indexed))
1457
17.4k
        names = &pdf_color_space_names;
1458
56.5k
    else
1459
56.5k
        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
73.9k
    if (!is_mask) {
1463
19.5k
#if 1
1464
19.5k
        if (image[0].pixel.ColorSpace != NULL && !(context == PDF_IMAGE_TYPE3_MASK))
1465
15.3k
           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
19.5k
        if (pim->BitsPerComponent > 8 && convert_to_process_colors) {
1486
0
            use_fallback = 1;
1487
0
            goto fail_and_fallback;
1488
0
        }
1489
19.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
19.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
19.5k
        if (convert_to_process_colors == 1) {
1505
1.30k
            code = make_device_color_space(pdev, pdev->pcm_color_info_index, &pcs_device);
1506
1.30k
            if (code < 0)
1507
0
                goto fail_and_fallback;
1508
1.30k
            image[0].pixel.ColorSpace = pcs_device;
1509
1.30k
            image[0].pixel.BitsPerComponent = 8;
1510
1.30k
            code = pdf_color_space_named(pdev, pgs, &cs_value, &pranges, pcs_device, names,
1511
1.30k
                                     in_line, NULL, 0, false);
1512
1.30k
            if (code < 0)
1513
0
                goto fail_and_fallback;
1514
18.2k
        } else {
1515
18.2k
            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
18.2k
            } else {
1522
18.2k
                convert_to_process_colors = 0;
1523
18.2k
                code = pdf_color_space_named(pdev, pgs, &cs_value, &pranges, pcs, names,
1524
18.2k
                                     in_line, NULL, 0, false);
1525
18.2k
                if (code < 0)
1526
0
                    goto fail_and_fallback;
1527
18.2k
            }
1528
18.2k
        }
1529
19.5k
    }
1530
1531
73.9k
    image[1] = image[0];
1532
1533
73.9k
    pdev->ParamCompatibilityLevel = pdev->CompatibilityLevel;
1534
1535
73.9k
    code = pdf_begin_write_image(pdev, &pie->writer, gs_no_id, width,
1536
73.9k
                    height, pnamed, in_line);
1537
73.9k
    if (code < 0)
1538
0
        goto fail_and_fallback;
1539
1540
73.9k
    if (pdev->CompatibilityLevel < 1.5)
1541
55.0k
        pdev->JPX_PassThrough = 0;
1542
1543
73.9k
    if (!convert_to_process_colors)
1544
72.6k
    {
1545
72.6k
        gs_color_space_index csi;
1546
1547
72.6k
        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
72.6k
    }
1598
    /* If we are not preserving the colour space unchanged, then we can't pass through JPEG */
1599
1.30k
    else
1600
1.30k
        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
73.9k
    if (in_line) {
1614
63.5k
        pdev->JPEG_PassThrough = 0;
1615
63.5k
        pdev->JPX_PassThrough = 0;
1616
63.5k
        code = new_setup_lossless_filters((gx_device_psdf *) pdev,
1617
63.5k
                                             &pie->writer.binary[0],
1618
63.5k
                                             &image[0].pixel, in_line, convert_to_process_colors, (gs_matrix *)pmat, (gs_gstate *)pgs);
1619
63.5k
    } else {
1620
10.4k
        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
853
            int saved_downsample = pdev->params.ColorImage.DownsampleType;
1631
1632
853
            pdev->params.ColorImage.DownsampleType = ds_Subsample;
1633
853
            code = new_setup_image_filters((gx_device_psdf *) pdev,
1634
853
                                          &pie->writer.binary[0], &image[0].pixel,
1635
853
                                          pmat, pgs, true, in_line, convert_to_process_colors);
1636
853
            pdev->params.ColorImage.DownsampleType = saved_downsample;
1637
9.61k
        } else {
1638
9.61k
            code = new_setup_image_filters((gx_device_psdf *) pdev,
1639
9.61k
                                          &pie->writer.binary[0], &image[0].pixel,
1640
9.61k
                                          pmat, pgs, true, in_line, convert_to_process_colors);
1641
9.61k
        }
1642
10.4k
    }
1643
1644
73.9k
    if (code < 0)
1645
0
        goto fail_and_fallback;
1646
1647
73.9k
    if (convert_to_process_colors) {
1648
1.30k
        image[0].pixel.ColorSpace = pcs_orig;
1649
1.30k
        image[0].pixel.BitsPerComponent = pim->BitsPerComponent;
1650
1.30k
        code = psdf_setup_image_colors_filter(&pie->writer.binary[0],
1651
1.30k
                                              (gx_device_psdf *)pdev, pim, &image[0].pixel, pgs);
1652
1.30k
        if (code < 0)
1653
0
            goto fail_and_fallback;
1654
1.30k
        image[0].pixel.ColorSpace = pcs_device;
1655
1.30k
    }
1656
1657
73.9k
    if (pdev->JPEG_PassThrough || pdev->JPX_PassThrough) {
1658
588
        pdev->PassThroughWriter = pie->writer.binary[0].strm;
1659
588
        pie->writer.alt_writer_count = 1;
1660
588
    }
1661
73.9k
    pie->JPEG_PassThrough = pdev->JPEG_PassThrough;
1662
73.9k
    pie->JPX_PassThrough = pdev->JPX_PassThrough;
1663
1664
73.9k
    if (pie->writer.alt_writer_count > 1) {
1665
8.68k
        code = pdf_make_alt_stream(pdev, &pie->writer.binary[1]);
1666
8.68k
        if (code < 0)
1667
0
            goto fail_and_fallback;
1668
8.68k
        code = new_setup_image_filters((gx_device_psdf *) pdev,
1669
8.68k
                                  &pie->writer.binary[1], &image[1].pixel,
1670
8.68k
                                  pmat, pgs, force_lossless, in_line, convert_to_process_colors);
1671
8.68k
        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.63k
        } else if (code) {
1691
0
            goto fail_and_fallback;
1692
8.63k
        } 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.68k
    }
1702
1703
156k
    for (i = 0; i < pie->writer.alt_writer_count; i++) {
1704
82.6k
        code = pdf_begin_image_data_decoded(pdev, num_components, pranges, i,
1705
82.6k
                             &image[i].pixel, &cs_value, pie);
1706
82.6k
        if (code < 0)
1707
0
            goto fail_and_fallback;
1708
82.6k
    }
1709
73.9k
    if (pie->writer.alt_writer_count == 2) {
1710
8.63k
        psdf_setup_compression_chooser(&pie->writer.binary[2],
1711
8.63k
             (gx_device_psdf *)pdev, pim->Width, pim->Height,
1712
8.63k
             num_components, pim->BitsPerComponent);
1713
8.63k
        pie->writer.alt_writer_count = 3;
1714
8.63k
    }
1715
73.9k
    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
73.9k
    code = 0;
1749
1750
    /* This label is used when code < 0 and we want to do the fallback code */
1751
74.6k
 fail_and_fallback:
1752
74.6k
    if (code != 0)
1753
144
        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
79.0k
 exit:
1760
    /* Free everything */
1761
79.0k
    rc_decrement(pcs, "pdf_begin_typed_image(pcs)");
1762
79.0k
    rc_decrement(pcs_device, "pdf_begin_typed_image(pcs_device)");
1763
79.0k
    gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
1764
79.0k
                                      "pdf_begin_typed_image(image)");
1765
1766
    /* Free pie only if there was an error or we are falling back */
1767
79.0k
    if (code < 0 || use_fallback) {
1768
667
        if (pie)
1769
490
            gs_free_object(mem, pie, "pdf_begin_typed_image(pie)");
1770
667
        *pinfo = NULL;
1771
667
    }
1772
    /* Do the fallback */
1773
79.0k
    if (use_fallback) {
1774
651
        pdev->JPEG_PassThrough = 0;
1775
651
        pdev->JPX_PassThrough = 0;
1776
651
        code = gx_default_begin_typed_image
1777
651
            ((gx_device *)pdev, pgs, pmat, pic, prect, pdcolor, pcpath, mem, pinfo);
1778
651
    }
1779
79.0k
    return code;
1780
74.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
70.5k
{
1790
70.5k
    return pdf_begin_typed_image((gx_device_pdf *)dev, pgs, pmat, pic, prect,
1791
70.5k
                                 pdcolor, pcpath, mem, pinfo,
1792
70.5k
                                 PDF_IMAGE_DEFAULT);
1793
70.5k
}
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
5.82M
{
1803
5.82M
    pdf_image_enum *pie = (pdf_image_enum *) info;
1804
5.82M
    int h = height;
1805
5.82M
    int y;
1806
    /****** DOESN'T HANDLE IMAGES WITH VARYING WIDTH PER PLANE ******/
1807
5.82M
    uint width_bits = pie->width * pie->plane_depths[0];
1808
    /****** DOESN'T HANDLE NON-ZERO data_x CORRECTLY ******/
1809
5.82M
    uint ignore;
1810
5.82M
    int nplanes = pie->num_planes;
1811
5.82M
    int status = 0;
1812
5.82M
    uint bcount = (width_bits + 7) >> 3;
1813
1814
5.82M
    if (h > pie->rows_left)
1815
52.5k
        h = pie->rows_left;
1816
13.1M
    for (y = 0; y < h; ++y) {
1817
7.31M
        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
7.31M
        } else {
1864
7.31M
            status = sputs(pie->writer.binary[alt_writer_index].strm,
1865
7.31M
                           planes[0].data + planes[0].raster * y, bcount,
1866
7.31M
                           &ignore);
1867
7.31M
        }
1868
7.31M
        if (status < 0)
1869
0
            break;
1870
7.31M
    }
1871
5.82M
    *rows_used = h;
1872
5.82M
    if (status < 0)
1873
0
        return_error(gs_error_ioerror);
1874
5.82M
    return !pie->rows_left;
1875
5.82M
#undef ROW_BYTES
1876
5.82M
}
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
5.12M
{
1883
5.12M
    pdf_image_enum *pie = (pdf_image_enum *) info;
1884
5.12M
    int i;
1885
1886
5.12M
    if (info->pgs != NULL && info->pgs->level < info->pgs_level)
1887
0
        return_error(gs_error_undefinedresult);
1888
1889
5.12M
    if (pie->JPEG_PassThrough || pie->JPX_PassThrough) {
1890
67.0k
        pie->rows_left -= height;
1891
67.0k
        *rows_used = height;
1892
67.0k
        return !pie->rows_left;
1893
67.0k
    }
1894
1895
10.8M
    for (i = 0; i < pie->writer.alt_writer_count; i++) {
1896
5.82M
        int code = pdf_image_plane_data_alt(info, planes, height, rows_used, i);
1897
5.82M
        if (code)
1898
0
            return code;
1899
5.82M
    }
1900
5.05M
    pie->rows_left -= *rows_used;
1901
5.05M
    if (pie->writer.alt_writer_count > 2)
1902
382k
        pdf_choose_compression(&pie->writer, false);
1903
1904
5.05M
    return !pie->rows_left;
1905
5.05M
}
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
71.6k
{
1999
71.6k
    int code = 0;
2000
71.6k
    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
71.6k
    if (do_image == USE_AS_IMAGE) {
2008
67.5k
        if (pdev->image_mask_id != gs_no_id && piw->pres && piw->pres->object) {
2009
4.13k
            char buf[20];
2010
2011
4.13k
            gs_snprintf(buf, sizeof(buf), "%ld 0 R", pdev->image_mask_id);
2012
4.13k
            code = cos_dict_put_string_copy((cos_dict_t *)piw->pres->object,
2013
4.13k
                    pdev->image_mask_is_SMask ? "/SMask" : "/Mask", buf);
2014
4.13k
            (*(piw->pres->object)).md5_valid = 0;
2015
4.13k
            if (code < 0)
2016
0
                return code;
2017
4.13k
        }
2018
67.5k
    }
2019
2020
71.6k
    code = pdf_end_write_image(pdev, piw);
2021
71.6k
    pres = piw->pres;
2022
2023
71.6k
    switch (code) {
2024
0
    default:
2025
0
        return code; /* error */
2026
61.8k
    case 1:
2027
61.8k
        code = 0;
2028
61.8k
        break;
2029
9.78k
    case 0:
2030
9.78k
        if (do_image == USE_AS_IMAGE) {
2031
5.65k
            if (pdev->image_mask_skip)
2032
0
                code = 0;
2033
5.65k
            else
2034
5.65k
                code = pdf_do_image(pdev, pres, mat, true);
2035
5.65k
        } 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.13k
            const pdf_x_object_t *const pxo = (const pdf_x_object_t *)pres;
2040
2041
4.13k
            pdev->image_mask_scale = (double)pxo->data_height / pxo->height;
2042
4.13k
            pdev->image_mask_id = pdf_resource_id(pres);
2043
4.13k
            pdev->converting_image_matrix = *mat;
2044
4.13k
        } else if (do_image == USE_AS_PATTERN)
2045
0
            code = use_image_as_pattern(pdev, pres, mat, ps_bitmap_id);
2046
71.6k
    }
2047
71.6k
    return code;
2048
71.6k
}
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
73.9k
{
2055
73.9k
    gx_device_pdf *pdev = (gx_device_pdf *)info->dev;
2056
73.9k
    pdf_image_enum *pie = (pdf_image_enum *)info;
2057
73.9k
    int height = pie->writer.height;
2058
73.9k
    int data_height = height - pie->rows_left;
2059
73.9k
    int code = 0, ecode;
2060
2061
73.9k
    if (pie->writer.pres)
2062
10.4k
        ((pdf_x_object_t *)pie->writer.pres)->data_height = data_height;
2063
63.5k
    else if (data_height > 0)
2064
61.8k
        pdf_put_image_matrix(pdev, &pie->mat, (double)data_height / height);
2065
73.9k
    if (data_height > 0) {
2066
71.6k
        if (pie->writer.pres) {
2067
9.79k
            code = pdf_complete_image_data(pdev, &pie->writer, data_height,
2068
9.79k
                        pie->width, pie->bits_per_pixel);
2069
9.79k
            if (code < 0)
2070
0
                return code;
2071
9.79k
        }
2072
        /* This closes the stream pointed to by PassThroughWriter
2073
           so we need to NULL that pointer
2074
         */
2075
71.6k
        code = pdf_end_image_binary(pdev, &pie->writer, data_height);
2076
71.6k
        pdev->PassThroughWriter = NULL;
2077
71.6k
        pdev->JPX_PassThrough = false;
2078
71.6k
        pdev->JPEG_PassThrough = false;
2079
        /* The call above possibly decreases pie->writer.alt_writer_count in 2. */
2080
71.6k
        if (code < 0)
2081
1
            return code;
2082
71.6k
        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
71.6k
            code = pdf_end_and_do_image(pdev, &pie->writer, &pie->mat, info->id, do_image);
2102
71.6k
        pie->writer.alt_writer_count--; /* For GC. */
2103
71.6k
    } else {
2104
        /* This closes the stream pointed to by PassThroughWriter
2105
           so we need to NULL that pointer
2106
         */
2107
2.32k
        code = pdf_end_image_binary(pdev, &pie->writer, data_height);
2108
2.32k
        pdev->PassThroughWriter = NULL;
2109
2.32k
        pdev->JPX_PassThrough = false;
2110
2.32k
        pdev->JPEG_PassThrough = false;
2111
2.32k
        code = pdf_end_abort_image(pdev, &pie->writer);
2112
2.32k
        pie->writer.alt_writer_count--; /* For GC. */
2113
2.32k
    }
2114
73.9k
    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
73.9k
    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
73.9k
    gx_image_free_enum(&info);
2131
73.9k
    return code;
2132
73.9k
}
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
69.7k
{
2138
69.7k
    return pdf_image_end_image_data(info, draw_last, USE_AS_IMAGE);
2139
69.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
24
{   pdf_lcvd_t *cvd = (pdf_lcvd_t *)info->dev;
2145
24
    int code = pdf_dump_converted_image(cvd->pdev, cvd, 0);
2146
24
    int code1 = gx_image1_end_image(info, draw_last);
2147
24
    int code2 = gs_closedevice((gx_device *)cvd->mask);
2148
24
    int code3 = gs_closedevice((gx_device *)cvd);
2149
2150
24
    gs_free_object(cvd->mask->memory, (gx_device *)cvd->mask, "pdf_image_end_image_cvd");
2151
24
    gs_free_object(cvd->mdev.memory, (gx_device *)cvd, "pdf_image_end_image_cvd");
2152
24
    return code < 0 ? code : code1 < 0 ? code1 : code2 < 0 ? code2 : code3;
2153
24
}
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.51k
{
2163
8.51k
    gx_device *fdev;
2164
8.51k
    int code = gs_copydevice(&fdev, (const gx_device *)&gs_null_device, mem);
2165
2166
8.51k
    if (code < 0)
2167
0
        return code;
2168
8.51k
    gx_device_set_target((gx_device_forward *)fdev, tdev);
2169
8.51k
    *pmxdev = fdev;
2170
8.51k
    return 0;
2171
8.51k
}
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.25k
{
2177
4.25k
    return pdf_image_end_image_data(info, draw_last, USE_AS_MASK);
2178
4.25k
}
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
92
{
2194
92
    gx_device_pdf *pdev = (gx_device_pdf *)dev;
2195
2196
92
    if (pdev->CompatibilityLevel < 1.3 && !pdev->PatternImagemask) {
2197
92
        gs_matrix m;
2198
92
        pdf_lcvd_t *cvd = NULL;
2199
92
        int code;
2200
2201
92
        gs_make_identity(&m);
2202
92
        code = pdf_setup_masked_image_converter(pdev, mem, &m, &cvd,
2203
92
                                        true, 0, 0, width, height, true);
2204
92
        if (code < 0)
2205
0
            return code;
2206
92
        cvd->mask->target = (gx_device *)cvd; /* Temporary, just to communicate with
2207
                                         pdf_image3_make_mcde. The latter will reset it. */
2208
92
        cvd->mask_is_empty = false;
2209
92
        *pmidev = (gx_device *)cvd->mask;
2210
92
        return 0;
2211
92
    } 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
92
}
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.25k
{
2228
    /* The target of the null device is the pdfwrite device. */
2229
4.25k
    gx_device_pdf *const pdev = (gx_device_pdf *)
2230
4.25k
        ((gx_device_null *)dev)->target;
2231
4.25k
    return pdf_begin_typed_image
2232
4.25k
        (pdev, pgs, pmat, pic, prect, pdcolor, pcpath, mem, pinfo,
2233
4.25k
         PDF_IMAGE_TYPE3_MASK);
2234
4.25k
}
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
92
{
2247
92
    int code;
2248
92
    gx_device_pdf *pdev = (gx_device_pdf *)dev;
2249
2250
92
    if (pdev->CompatibilityLevel < 1.3 && !pdev->PatternImagemask) {
2251
        /* pdf_image3_make_mid must set midev with a pdf_lcvd_t instance.*/
2252
92
        pdf_lcvd_t *cvd = (pdf_lcvd_t *)((gx_device_memory *)midev)->target;
2253
2254
92
        ((gx_device_memory *)midev)->target = NULL;
2255
92
        cvd->m = pdev->converting_image_matrix;
2256
92
        cvd->mdev.mapped_x = origin->x;
2257
92
        cvd->mdev.mapped_y = origin->y;
2258
92
        cvd->mdev.width += origin->x;
2259
92
        cvd->mdev.height += origin->y;
2260
92
        *pmcdev = (gx_device *)&cvd->mdev;
2261
92
        code = gx_default_begin_typed_image
2262
92
            ((gx_device *)&cvd->mdev, pgs, pmat, pic, prect, pdcolor, NULL, mem,
2263
92
            pinfo);
2264
92
        if (code < 0)
2265
0
            return code;
2266
92
    } 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
92
    return 0;
2285
92
}
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.25k
{
2294
4.25k
    int code = pdf_make_mxd(pmidev, dev, mem);
2295
2296
4.25k
    if (code < 0)
2297
0
        return code;
2298
4.25k
    set_dev_proc(*pmidev, begin_typed_image, pdf_mid_begin_typed_image);
2299
4.25k
    return 0;
2300
4.25k
}
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.25k
{
2315
4.25k
    int code;
2316
4.25k
    pdf_image_enum *pmie;
2317
4.25k
    int i;
2318
4.25k
    const gs_image3x_mask_t *pixm;
2319
4.25k
    gx_device_pdf *pdf_dev = (gx_device_pdf *)dev;
2320
2321
4.25k
    if (midev[0]) {
2322
4.25k
        if (midev[1])
2323
0
            return_error(gs_error_rangecheck);
2324
4.25k
        i = 0, pixm = &pim->Opacity;
2325
4.25k
    } else if (midev[1])
2326
2
        i = 1, pixm = &pim->Shape;
2327
0
    else
2328
0
        return_error(gs_error_rangecheck);
2329
4.25k
    code = pdf_make_mxd(pmcdev, midev[i], mem);
2330
4.25k
    if (code < 0)
2331
0
        return code;
2332
2333
4.25k
    if (pminfo[0] != NULL)
2334
4.25k
        pdf_dev->PendingOC = pminfo[0]->OC;
2335
2
    else
2336
2
        pdf_dev->PendingOC = 0;
2337
2338
4.25k
    code = pdf_begin_typed_image
2339
4.25k
        ((gx_device_pdf *)dev, pgs, pmat, pic, prect, pdcolor, pcpath, mem,
2340
4.25k
         pinfo, PDF_IMAGE_TYPE3_DATA);
2341
4.25k
    pdf_dev->PendingOC = 0;
2342
4.25k
    if (code < 0) {
2343
0
        rc_decrement(*pmcdev, "pdf_image3x_make_mcde");
2344
0
        return code;
2345
0
    }
2346
4.25k
    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.25k
    pmie = (pdf_image_enum *)pminfo[i];
2353
4.25k
    if (pmie->writer.alt_writer_count == 3) {
2354
4.06k
        cos_stream_t *s;
2355
2356
4.06k
        s = cos_stream_from_pipeline(pmie->writer.binary[1].strm);
2357
4.06k
        s_close_filters(&pmie->writer.binary[1].strm, pmie->writer.binary[1].target);
2358
4.06k
        s->cos_procs->release((cos_object_t *)s, "pdf_image_choose_filter");
2359
4.06k
        s->written = 1;
2360
4.06k
        s_close_filters(&pmie->writer.binary[2].strm, pmie->writer.binary[2].target);
2361
4.06k
        pmie->writer.binary[1].strm = pmie->writer.binary[2].strm = 0; /* for GC */
2362
4.06k
        pmie->writer.binary[1].target = pmie->writer.binary[2].target = 0;
2363
4.06k
        pmie->writer.alt_writer_count = 1;
2364
4.06k
    }
2365
    /*
2366
     * Add the SMask entry to the image dictionary, and, if needed,
2367
     * the Matte entry to the mask dictionary.
2368
     */
2369
4.25k
    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.25k
    return 0;
2421
4.25k
}
2422
2423
pdf_resource_t *pdf_substitute_pattern(pdf_resource_t *pres)
2424
11.5k
{
2425
11.5k
    pdf_pattern_t *ppat = (pdf_pattern_t *)pres;
2426
2427
11.5k
    return (pdf_resource_t *)(ppat->substitute != 0 ? ppat->substitute : ppat);
2428
11.5k
}
2429
2430
static int
2431
check_unsubstituted2(gx_device_pdf * pdev, pdf_resource_t *pres0, pdf_resource_t *pres1)
2432
953
{
2433
953
    pdf_pattern_t *ppat0 = (pdf_pattern_t *)pres0;
2434
953
    pdf_pattern_t *ppat1 = (pdf_pattern_t *)pres1;
2435
2436
953
    return (ppat0->substitute == NULL && ppat1->substitute == NULL);
2437
953
}
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.14k
{
2449
8.14k
    if (pdev->vg_initial_set) {
2450
8.14k
        destination->strokeconstantalpha = source->strokeconstantalpha;
2451
8.14k
        source->strokeconstantalpha = pdev->vg_initial.strokeconstantalpha;
2452
8.14k
        destination->fillconstantalpha = source->fillconstantalpha;
2453
8.14k
        source->fillconstantalpha = pdev->vg_initial.fillconstantalpha;
2454
8.14k
        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.14k
        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.14k
        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.14k
        if (destination->set_transfer.gray != NULL)
2461
4.07k
            destination->set_transfer.gray->id = (source->set_transfer.gray != NULL ? source->set_transfer.gray->id : 0);
2462
8.14k
        if (source->set_transfer.red != NULL)
2463
0
            source->set_transfer.red->id = pdev->vg_initial.transfer_ids[0];
2464
8.14k
        if (source->set_transfer.green != NULL)
2465
0
            source->set_transfer.green->id = pdev->vg_initial.transfer_ids[1];
2466
8.14k
        if (source->set_transfer.blue != NULL)
2467
0
            source->set_transfer.blue->id = pdev->vg_initial.transfer_ids[2];
2468
8.14k
        if (source->set_transfer.gray != NULL)
2469
4.07k
            source->set_transfer.gray->id = pdev->vg_initial.transfer_ids[3];
2470
8.14k
        destination->alphaisshape = source->alphaisshape;
2471
8.14k
        source->alphaisshape = pdev->vg_initial.alphaisshape;
2472
8.14k
        destination->blend_mode = source->blend_mode;
2473
8.14k
        source->blend_mode = pdev->vg_initial.blend_mode;
2474
8.14k
        if (destination->black_generation != NULL)
2475
4.07k
            destination->black_generation->id = (source->black_generation != NULL ? source->black_generation->id : 0);
2476
8.14k
        if (source->black_generation != NULL)
2477
4.07k
            source->black_generation->id = pdev->vg_initial.black_generation_id;
2478
8.14k
        if (destination->undercolor_removal != NULL)
2479
4.07k
            destination->undercolor_removal->id = (source->undercolor_removal != NULL ? source->undercolor_removal->id : 0);
2480
8.14k
        if (source->undercolor_removal != NULL)
2481
4.07k
            source->undercolor_removal->id = pdev->vg_initial.undercolor_removal_id;
2482
8.14k
        destination->overprint_mode = source->overprint_mode;
2483
8.14k
        source->overprint_mode = pdev->vg_initial.overprint_mode;
2484
8.14k
        destination->flatness = source->flatness;
2485
8.14k
        source->flatness = pdev->vg_initial.flatness;
2486
8.14k
        destination->smoothness = source->smoothness;
2487
8.14k
        source->smoothness = pdev->vg_initial.smoothness;
2488
8.14k
        destination->flatness = source->flatness;
2489
8.14k
        source->flatness = pdev->vg_initial.flatness;
2490
8.14k
        destination->text_knockout = source->text_knockout;
2491
8.14k
        source->text_knockout = pdev->vg_initial.text_knockout;
2492
8.14k
        destination->stroke_adjust = source->stroke_adjust;
2493
8.14k
        source->stroke_adjust = pdev->vg_initial.stroke_adjust;
2494
8.14k
        destination->line_params.half_width = source->line_params.half_width;
2495
8.14k
        source->line_params.half_width = pdev->vg_initial.line_params.half_width;
2496
8.14k
        destination->line_params.start_cap = source->line_params.start_cap;
2497
8.14k
        source->line_params.start_cap = pdev->vg_initial.line_params.start_cap;
2498
8.14k
        destination->line_params.end_cap = source->line_params.end_cap;
2499
8.14k
        source->line_params.end_cap = pdev->vg_initial.line_params.end_cap;
2500
8.14k
        destination->line_params.dash_cap = source->line_params.dash_cap;
2501
8.14k
        source->line_params.dash_cap = pdev->vg_initial.line_params.dash_cap;
2502
8.14k
        destination->line_params.join = source->line_params.join;
2503
8.14k
        source->line_params.join = pdev->vg_initial.line_params.join;
2504
8.14k
        destination->line_params.curve_join = source->line_params.curve_join;
2505
8.14k
        source->line_params.curve_join = pdev->vg_initial.line_params.curve_join;
2506
8.14k
        destination->line_params.miter_limit = source->line_params.miter_limit;
2507
8.14k
        source->line_params.miter_limit = pdev->vg_initial.line_params.miter_limit;
2508
8.14k
        destination->line_params.miter_check = source->line_params.miter_check;
2509
8.14k
        source->line_params.miter_check = pdev->vg_initial.line_params.miter_check;
2510
8.14k
        destination->line_params.dot_length = source->line_params.dot_length;
2511
8.14k
        source->line_params.dot_length = pdev->vg_initial.line_params.dot_length;
2512
8.14k
        destination->line_params.dot_length_absolute = source->line_params.dot_length_absolute;
2513
8.14k
        source->line_params.dot_length_absolute = pdev->vg_initial.line_params.dot_length_absolute;
2514
8.14k
        destination->line_params.dot_orientation = source->line_params.dot_orientation;
2515
8.14k
        source->line_params.dot_orientation = pdev->vg_initial.line_params.dot_orientation;
2516
8.14k
        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.14k
        memcpy(&destination->line_params.dash, &source->line_params.dash, sizeof(source->line_params.dash));
2519
8.14k
        memcpy(&source->line_params.dash, &pdev->vg_initial.line_params.dash, sizeof(source->line_params.dash));
2520
8.14k
    }
2521
8.14k
    return 0;
2522
8.14k
}
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
87.1M
{
2531
87.1M
    gx_device_pdf *pdev = (gx_device_pdf *)pdev1;
2532
87.1M
    int code=0, force_CTM_change=0;
2533
87.1M
    pdf_resource_t *pres, *pres1;
2534
87.1M
    gx_bitmap_id id = (gx_bitmap_id)size;
2535
2536
87.1M
    switch (dev_spec_op) {
2537
54.5k
        case gxdso_skip_icc_component_validation:
2538
54.5k
            return 1;
2539
13.1k
        case gxdso_supports_pattern_transparency:
2540
13.1k
            return 1;
2541
4.35k
        case gxdso_pattern_can_accum:
2542
4.35k
            return 1;
2543
2.27k
        case gxdso_pdf_form_name:
2544
2.27k
            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.27k
            pdev->PDFFormName = (char *)gs_alloc_bytes(pdev->memory->non_gc_memory, size + 1, "Name of Form for pdfmark");
2548
2.27k
            if (pdev->PDFFormName == NULL)
2549
0
                return_error(gs_error_VMerror);
2550
2.27k
            memset(pdev->PDFFormName, 0x00, size + 1);
2551
2.27k
            memcpy(pdev->PDFFormName, data, size);
2552
2.27k
            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.27k
        case gxdso_form_begin:
2560
2.27k
            if ((!pdev->ForOPDFRead || pdev->HighLevelForm == 0) && pdev->PatternDepth == 0) {
2561
2.27k
                gs_form_template_t *tmplate = (gs_form_template_t *)data;
2562
2.27k
                float arry[6];
2563
2.27k
                cos_dict_t *pcd = NULL, *pcd_Resources = NULL;
2564
2565
                /* Make sure the document and page stream are open */
2566
2.27k
                code = pdfwrite_pdf_open_document(pdev);
2567
2.27k
                if (code < 0)
2568
0
                    return code;
2569
2.27k
                code = pdf_open_contents(pdev, PDF_IN_STREAM);
2570
2.27k
                if (code < 0)
2571
0
                    return code;
2572
2.27k
                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.27k
                code = pdf_enter_substream(pdev, resourceXObject, id, &pres, false,
2587
2.27k
                        pdev->CompressStreams);
2588
2.27k
                if (code < 0)
2589
0
                    return code;
2590
2.27k
                pcd = cos_stream_dict((cos_stream_t *)pres->object);
2591
2.27k
                pcd_Resources = cos_dict_alloc(pdev, "pdf_form(Resources)");
2592
2.27k
                if (pcd == NULL || pcd_Resources == NULL)
2593
0
                    return_error(gs_error_VMerror);
2594
2.27k
                code = cos_dict_put_c_strings(pcd, "/Type", "/XObject");
2595
2.27k
                if (code >= 0)
2596
2.27k
                    code = cos_dict_put_c_strings(pcd, "/Subtype", "/Form");
2597
2.27k
                if (code >= 0)
2598
2.27k
                    code = cos_dict_put_c_strings(pcd, "/FormType", "1");
2599
2.27k
                if (code >= 0)
2600
2.27k
                    code = cos_dict_put_c_key_object(pcd, "/Resources", COS_OBJECT(pcd_Resources));
2601
2602
2.27k
                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.27k
                    gs_rect bbox_out;
2612
2.27k
                    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.27k
                    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.27k
                    code = gs_matrix_multiply(&tmplate->form_matrix, &tmplate->CTM, &cmat);
2623
2.27k
                    if (code < 0)
2624
0
                        return code;
2625
2.27k
                    code = gs_bbox_transform(&tmplate->BBox, &cmat, &bbox_out);
2626
2.27k
                    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.27k
                    cmat.xx = cmat.yy = 1.0f;
2633
2.27k
                    cmat.xy = cmat.yx = cmat.tx = cmat.ty = 0.0f;
2634
2.27k
                    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.27k
                    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.27k
                    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.27k
                    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.27k
                    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.27k
                    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.27k
                    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.27k
                    arry[0] = bbox_out.p.x;
2679
2.27k
                    arry[1] = bbox_out.p.y;
2680
2.27k
                    arry[2] = bbox_out.q.x;
2681
2.27k
                    arry[3] = bbox_out.q.y;
2682
2.27k
                    if (code >= 0)
2683
2.27k
                        code = cos_dict_put_c_key_floats(pdev, pcd, "/BBox", arry, 4);
2684
2.27k
                    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.27k
                    arry[0] = arry[3] = 1.0f;
2692
2.27k
                    arry[1] = arry[2] = arry[4] = arry[5] = 0.0f;
2693
2.27k
                } 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.27k
                code = cos_dict_put_c_key_floats(pdev, pcd, "/Matrix", arry, 6);
2715
2.27k
                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.27k
                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.27k
                } 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.27k
                    pdev->substream_Resources = pcd_Resources;
2743
2.27k
                    pres->rid = id;
2744
2.27k
                    if (code >= 0)
2745
2.27k
                        pdev->HighLevelForm++;
2746
2.27k
                    return force_CTM_change;
2747
2.27k
                }
2748
2.27k
            }
2749
0
            return code;
2750
2.27k
        case gxdso_form_end:
2751
            /* This test must be the same as the one in gxdso_form_begin, above */
2752
2.27k
            if ((!pdev->ForOPDFRead || pdev->HighLevelForm == 1) && pdev->PatternDepth == 0) {
2753
2.27k
                if (pdev->CompatibilityLevel <= 1.7) {
2754
2.27k
                    code = pdf_add_procsets(pdev->substream_Resources, pdev->procsets);
2755
2.27k
                    if (code < 0)
2756
0
                        return code;
2757
2.27k
                }
2758
2.27k
                pres = pres1 = pdev->accumulating_substream_resource;
2759
2.27k
                if (pres == NULL)
2760
0
                    return_error(gs_error_unregistered);
2761
2.27k
                code = pdf_exit_substream(pdev);
2762
2.27k
                if (code < 0)
2763
0
                    return code;
2764
2.27k
                code = pdf_find_same_resource(pdev, resourceXObject, &pres, check_unsubstituted2);
2765
2.27k
                if (code < 0)
2766
0
                    return code;
2767
2.27k
                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.27k
                } else if (pres->object->id < 0)
2773
2.27k
                    pdf_reserve_object_id(pdev, pres, 0);
2774
2.27k
                pdev->LastFormID = pdf_resource_id(pres);
2775
2.27k
                pdev->HighLevelForm--;
2776
2.27k
                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.27k
                if (pdev->PDFFormName) {
2782
2.27k
                    cos_value_t value;
2783
2784
2.27k
                    code = cos_dict_put(pdev->local_named_objects, (const byte *)pdev->PDFFormName,
2785
2.27k
                        strlen(pdev->PDFFormName), cos_object_value(&value, pres->object));
2786
2787
2.27k
                    if (code < 0)
2788
0
                        return code;
2789
2.27k
                    pdf_drop_resource_from_chain(pdev, pres, resourceXObject);
2790
2.27k
                    pres->object = NULL;
2791
2.27k
                    gs_free_object(pdev->pdf_memory, pres, "free redundant resource");
2792
2793
2.27k
                    gs_free_object(pdev->memory->non_gc_memory, pdev->PDFFormName, "free Name of Form for pdfmark");
2794
2.27k
                    pdev->PDFFormName = 0x00;
2795
2.27k
                } else {
2796
0
                    pprinti64d1(pdev->strm, "/R%"PRId64" Do Q\n", pdf_resource_id(pres));
2797
0
                }
2798
2.27k
            }
2799
2.27k
            return 0;
2800
2.27k
        case gxdso_get_form_ID:
2801
2.27k
            {
2802
2.27k
                int *ID = data;
2803
2.27k
                *ID = pdev->LastFormID;
2804
2.27k
            }
2805
2.27k
            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.07k
        case gxdso_pattern_start_accum:
2840
4.07k
            {
2841
4.07k
                pattern_accum_param_s *param = (pattern_accum_param_s *)data;
2842
4.07k
                gs_pattern1_instance_t *pinst = param->pinst;
2843
4.07k
                gs_gstate *pgs = param->graphics_state;
2844
2845
4.07k
                code = pdf_check_soft_mask(pdev, (gs_gstate *)pgs);
2846
4.07k
                if (code < 0)
2847
0
                    return code;
2848
4.07k
                if (pdev->context == PDF_IN_NONE) {
2849
99
                    code = pdf_open_page(pdev, PDF_IN_STREAM);
2850
99
                    if (code < 0)
2851
0
                        return code;
2852
99
                }
2853
4.07k
                code = pdf_prepare_fill_stroke(pdev, (gs_gstate *)pgs, false);
2854
4.07k
                if (code < 0)
2855
0
                    return code;
2856
4.07k
                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.07k
                {
2868
4.07k
                    gs_gstate **new_states;
2869
4.07k
                    int pdepth;
2870
2871
4.07k
                    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.07k
                    if (new_states == NULL)
2873
0
                        return_error(gs_error_VMerror);
2874
4.07k
                    memset(new_states, 0x00, sizeof(gs_gstate *) * (pdev->PatternDepth + 2));
2875
4.08k
                    for (pdepth = 0; pdepth < pdev->PatternDepth;pdepth++)
2876
9
                        new_states[pdepth] = pdev->initial_pattern_states[pdepth];
2877
4.07k
                    gs_free_object(pdev->pdf_memory->non_gc_memory, pdev->initial_pattern_states, "Freeing old pattern state stack");
2878
4.07k
                    pdev->initial_pattern_states = new_states;
2879
4.07k
                }
2880
4.07k
                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.07k
                if (pdev->initial_pattern_states[pdev->PatternDepth] == NULL)
2882
0
                    return code;
2883
4.07k
                memset(pdev->initial_pattern_states[pdev->PatternDepth], 0x00, sizeof(gs_gstate));
2884
4.07k
                pdev->initial_pattern_states[pdev->PatternDepth]->memory = pdev->pdf_memory;
2885
2886
4.07k
                reset_gstate_for_pattern(pdev, pdev->initial_pattern_states[pdev->PatternDepth], pgs);
2887
4.07k
                code = pdf_enter_substream(pdev, resourcePattern, pinst->id, &pres, false,
2888
4.07k
                        pdev->CompressStreams);
2889
4.07k
                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.07k
                pdev->state.soft_mask_id = pgs->soft_mask_id;
2903
4.07k
                pres->rid = pinst->id;
2904
4.07k
                code = pdf_store_pattern1_params(pdev, pres, pinst);
2905
4.07k
                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.07k
                pprintg2(pdev->strm, "%g 0 0 %g 0 0 cm\n",
2912
4.07k
                         72.0 / pdev->HWResolution[0], 72.0 / pdev->HWResolution[1]);
2913
4.07k
                pdev->PatternDepth++;
2914
4.07k
                pdev->PatternsSinceForm++;
2915
4.07k
            }
2916
0
            return 1;
2917
4.07k
        case gxdso_pattern_finish_accum:
2918
4.07k
            {
2919
4.07k
                pattern_accum_param_s *param = (pattern_accum_param_s *)data;
2920
4.07k
                gs_gstate *pgs = param->graphics_state;
2921
2922
4.07k
                if (pdev->CompatibilityLevel <= 1.7) {
2923
4.07k
                    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.07k
                    code = pdf_add_procsets(pdev->substream_Resources, pdev->procsets);
2929
4.07k
                    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.07k
                }
2935
4.07k
                pres = pres1 = pdev->accumulating_substream_resource;
2936
4.07k
                if (pres == NULL)
2937
0
                    code = gs_note_error(gs_error_unregistered);
2938
4.07k
                else
2939
4.07k
                    code = pdf_exit_substream(pdev);
2940
4.07k
                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.07k
                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.07k
                code = pdf_find_same_resource(pdev, resourcePattern, &pres, check_unsubstituted2);
2952
4.07k
                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.07k
                if (code > 0) {
2958
953
                    pdf_pattern_t *ppat = (pdf_pattern_t *)pres1;
2959
2960
953
                    code = pdf_cancel_resource(pdev, pres1, resourcePattern);
2961
953
                    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
953
                    ppat->substitute = (pdf_pattern_t *)pres;
2968
953
                    pres->where_used |= pdev->used_mask;
2969
953
                    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.07k
                reset_gstate_for_pattern(pdev, pgs, pdev->initial_pattern_states[pdev->PatternDepth - 1]);
2973
4.07k
                gs_free_object(pdev->pdf_memory, pdev->initial_pattern_states[pdev->PatternDepth - 1], "Freeing dangling pattern state");
2974
4.07k
                pdev->initial_pattern_states[pdev->PatternDepth - 1] = NULL;
2975
4.07k
                if (pdev->PatternDepth == 1) {
2976
4.06k
                    gs_free_object(pdev->pdf_memory->non_gc_memory, pdev->initial_pattern_states, "Freeing dangling pattern state");
2977
4.06k
                    pdev->initial_pattern_states = NULL;
2978
4.06k
                }
2979
2980
4.07k
                pdev->PatternDepth--;
2981
4.07k
                pdev->PatternsSinceForm--;
2982
4.07k
            }
2983
0
            return 1;
2984
9.30k
        case gxdso_pattern_load:
2985
9.30k
            pres = pdf_find_resource_by_gs_id(pdev, resourcePattern, *((gx_bitmap_id *)data));
2986
9.30k
            if (pres == 0)
2987
4.06k
                return 0;
2988
5.23k
            pres = pdf_substitute_pattern(pres);
2989
5.23k
            pres->where_used |= pdev->used_mask;
2990
5.23k
            code = pdf_add_resource(pdev, pdev->substream_Resources, "/Pattern", pres);
2991
5.23k
            if (code < 0)
2992
0
                return code;
2993
5.23k
            return 1;
2994
20.8k
        case gxdso_pattern_shading_area:
2995
20.8k
            return 0;
2996
89.4k
        case gxdso_pattern_is_cpath_accum:
2997
89.4k
            return 0;
2998
4.14k
        case gxdso_pattern_shfill_doesnt_need_path:
2999
4.14k
            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.56k
        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.56k
            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.29k
        case gxdso_JPEG_passthrough_query:
3020
2.29k
            pdev->JPEG_PassThrough = pdev->params.PassThroughJPEGImages;
3021
2.29k
            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.23k
        case gxdso_JPEG_passthrough_begin:
3030
2.23k
            return 0;
3031
0
            break;
3032
202k
        case gxdso_JPEG_passthrough_data:
3033
202k
            if (pdev->JPEG_PassThrough && pdev->PassThroughWriter)
3034
54.5k
            {
3035
54.5k
                uint ignore;
3036
54.5k
                if (sputs(pdev->PassThroughWriter,
3037
54.5k
                           data, size,
3038
54.5k
                           &ignore) < 0)
3039
0
                           return_error(gs_error_ioerror);
3040
54.5k
            }
3041
202k
            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.99k
        case gxdso_JPX_passthrough_query:
3049
1.99k
            pdev->JPX_PassThrough = pdev->params.PassThroughJPXImages;
3050
1.99k
            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.83k
        case gxdso_JPX_passthrough_begin:
3059
1.83k
            return 0;
3060
0
            break;
3061
110k
        case gxdso_JPX_passthrough_data:
3062
110k
            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
110k
            return 0;
3071
0
            break;
3072
1.99k
        case gxdso_JPX_passthrough_end:
3073
1.99k
            pdev->JPX_PassThrough = 0;
3074
1.99k
            pdev->PassThroughWriter = 0;
3075
1.99k
            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.61M
        case gxdso_in_smask_construction:
3112
6.61M
            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
92
        case gxdso_hilevel_text_clip:
3156
92
            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
77
                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
77
            } 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
92
            break;
3238
1.60M
        case gxdso_get_dev_param:
3239
1.60M
            {
3240
1.60M
                int code;
3241
1.60M
                dev_param_req_t *request = (dev_param_req_t *)data;
3242
1.60M
                code = gdev_pdf_get_param(pdev1, request->Param, request->list);
3243
1.60M
                if (code != gs_error_undefined)
3244
1.55M
                    return code;
3245
1.60M
            }
3246
            /* Fall through */
3247
87.1M
    }
3248
78.4M
    return gx_default_dev_spec_op(pdev1, dev_spec_op, data, size);
3249
87.1M
}