Coverage Report

Created: 2026-04-01 07:17

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
77.7k
{
118
77.7k
    return true;
119
77.7k
}
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
88.7k
{
231
232
88.7k
    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
88.7k
    return pdf_begin_image_data(pdev, &pie->writer, pi, cs_value, i);
247
88.7k
}
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.55k
{
254
2.55k
    gs_color_space *cs;
255
2.55k
    gs_memory_t *mem = pdev->v_memory;
256
257
2.55k
    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.55k
        case gs_color_space_index_DeviceRGB:
262
2.55k
            cs = gs_cspace_new_DeviceRGB(mem);
263
2.55k
            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.55k
    }
275
276
2.55k
    if (cs == NULL)
277
0
        return_error(gs_error_VMerror);
278
279
2.55k
    *ppcs = cs;
280
2.55k
    return 0;
281
2.55k
}
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
83.5k
{
318
83.5k
    const gs_image_t *pim1 = (const gs_image_t *)pic;
319
320
83.5k
    if (pim1->Alpha != gs_image_alpha_none)
321
0
        return -1;
322
83.5k
    if (pim1->ImageMask) {
323
        /* If parameters are invalid, use the fallback implementation. */
324
66.0k
        if (!(gx_dc_is_pattern1_color(pdcolor)))
325
65.5k
            if (pim1->BitsPerComponent != 1 ||
326
65.5k
                !((pim1->Decode[0] == 0.0 && pim1->Decode[1] == 1.0) ||
327
63.8k
                  (pim1->Decode[0] == 1.0 && pim1->Decode[1] == 0.0))
328
65.5k
                )
329
12
                return -1;
330
66.0k
    }
331
83.5k
    image[0].type1 = *pim1;
332
    /* If we can write in-line then make it so */
333
83.5k
    return (context == PDF_IMAGE_DEFAULT &&
334
77.7k
        can_write_image_in_line(pdev, pim1));
335
83.5k
}
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
109
{
345
109
    const gs_image3_t *pim3 = (const gs_image3_t *)pic;
346
109
    gs_image3_t pim3a;
347
109
    const gs_image_common_t *pic1 = pic;
348
109
    gs_matrix m, mi;
349
109
    const gs_matrix *pmat1 = pmat;
350
109
    int code;
351
352
109
    if (pdev->CompatibilityLevel < 1.3 && !pdev->PatternImagemask) {
353
88
        code = pdf_check_soft_mask(pdev, (gs_gstate *)pgs);
354
88
        if (code < 0)
355
0
            return code;
356
88
        if (pdf_must_put_clip_path(pdev, pcpath))
357
21
            code = pdf_unclip(pdev);
358
67
        else
359
67
            code = pdf_open_page(pdev, PDF_IN_STREAM);
360
88
        if (code < 0)
361
0
            return code;
362
88
        code = pdf_put_clip_path(pdev, pcpath);
363
88
        if (code < 0)
364
0
            return code;
365
88
        gs_make_identity(&m);
366
88
        pmat1 = &m;
367
88
        m.tx = floor(pgs->ctm.tx + 0.5); /* Round the origin against the image size distorsions */
368
88
        m.ty = floor(pgs->ctm.ty + 0.5);
369
88
        pim3a = *pim3;
370
88
        code = gs_matrix_invert(&pim3a.ImageMatrix, &mi);
371
88
        if (code < 0)
372
1
            return code;
373
87
        gs_make_identity(&pim3a.ImageMatrix);
374
87
        if (pim3a.Width < pim3a.MaskDict.Width && pim3a.Width > 0) {
375
21
            int sx = (pim3a.MaskDict.Width + pim3a.Width - 1) / pim3a.Width;
376
377
21
            gs_matrix_scale(&mi, 1.0 / sx, 1, &mi);
378
21
            gs_matrix_scale(&pim3a.ImageMatrix, 1.0 / sx, 1, &pim3a.ImageMatrix);
379
21
        }
380
87
        if (pim3a.Height < pim3a.MaskDict.Height && pim3a.Height > 0) {
381
14
            int sy = (pim3a.MaskDict.Height + pim3a.Height - 1) / pim3a.Height;
382
383
14
            gs_matrix_scale(&mi, 1, 1.0 / sy, &mi);
384
14
            gs_matrix_scale(&pim3a.ImageMatrix, 1, 1.0 / sy, &pim3a.ImageMatrix);
385
14
        }
386
87
        gs_matrix_multiply(&mi, &pim3a.MaskDict.ImageMatrix, &pim3a.MaskDict.ImageMatrix);
387
87
        pim3a.imagematrices_are_untrustworthy = 1;
388
87
        pic1 = (gs_image_common_t *)&pim3a;
389
        /* Setting pdev->converting_image_matrix to communicate with pdf_image3_make_mcde. */
390
87
        gs_matrix_multiply(&mi, &ctm_only(pgs), &pdev->converting_image_matrix);
391
87
    }
392
    /*
393
     * We handle ImageType 3 images in a completely different way:
394
     * the default implementation sets up the enumerator.
395
     */
396
108
    return gx_begin_image3_generic((gx_device *)pdev, pgs, pmat1, pic1,
397
108
                                   prect, pdcolor, pcpath, mem,
398
108
                                   pdf_image3_make_mid,
399
108
                                   pdf_image3_make_mcde, pinfo);
400
109
}
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
22
{
454
22
        gs_matrix m, m1, mi;
455
22
        gs_image4_t pi4 = *(const gs_image4_t *)pic;
456
22
        int code;
457
22
        pdf_lcvd_t *cvd = NULL;
458
459
22
        code = pdf_check_soft_mask(pdev, (gs_gstate *)pgs);
460
22
        if (code < 0)
461
0
            return code;
462
22
        if (pdf_must_put_clip_path(pdev, pcpath))
463
21
            code = pdf_unclip(pdev);
464
1
        else
465
1
            code = pdf_open_page(pdev, PDF_IN_STREAM);
466
22
        if (code < 0)
467
0
            return code;
468
22
        code = pdf_put_clip_path(pdev, pcpath);
469
22
        if (code < 0)
470
0
            return code;
471
22
        gs_make_identity(&m1);
472
22
        code = gs_matrix_invert(&pic->ImageMatrix, &mi);
473
22
        if (code < 0)
474
0
            return code;
475
22
        gs_matrix_multiply(&mi, &ctm_only(pgs), &m);
476
22
        code = pdf_setup_masked_image_converter(pdev, mem, &m, &cvd,
477
22
                             true, 0, 0, pi4.Width, pi4.Height, false);
478
22
        if (code < 0)
479
0
            return code;
480
22
        cvd->mdev.is_open = true; /* fixme: same as above. */
481
22
        cvd->mask->is_open = true; /* fixme: same as above. */
482
22
        cvd->mask_is_empty = false;
483
22
        code = (*dev_proc(cvd->mask, fill_rectangle))((gx_device *)cvd->mask,
484
22
                    0, 0, cvd->mask->width, cvd->mask->height, (gx_color_index)0);
485
22
        if (code < 0)
486
0
            return code;
487
22
        gx_device_retain((gx_device *)cvd, true);
488
22
        gx_device_retain((gx_device *)cvd->mask, true);
489
22
        gs_make_identity(&pi4.ImageMatrix);
490
22
        code = gx_default_begin_typed_image((gx_device *)cvd,
491
22
            pgs, &m1, (gs_image_common_t *)&pi4, prect, pdcolor, NULL, mem, pinfo);
492
22
        if (code < 0)
493
0
            return code;
494
22
        (*pinfo)->procs = &pdf_image_cvd_enum_procs;
495
22
        return 0;
496
22
}
497
498
static int setup_image_process_colorspace(gx_device_pdf *pdev, image_union_t *image, gs_color_space **pcs_orig,
499
                                          const char *sname, cos_value_t *cs_value)
500
1.27k
{
501
1.27k
    int code;
502
1.27k
    gs_color_space *pcs_device = NULL;
503
504
1.27k
    cos_c_string_value(cs_value, sname);
505
1.27k
    *pcs_orig = image->pixel.ColorSpace;
506
1.27k
    code = make_device_color_space(pdev, pdev->pcm_color_info_index, &pcs_device);
507
1.27k
    if (code < 0)
508
0
        return code;
509
1.27k
    image->pixel.ColorSpace = pcs_device;
510
1.27k
    return 0;
511
1.27k
}
512
513
static int check_colorants_for_pdfx4(const gs_color_space *pcs)
514
0
{
515
0
    int comp, all_present = 1;
516
0
    char *ink;
517
0
    gs_device_n_colorant *colorant = NULL;
518
519
0
    if (pcs->params.device_n.colorants == NULL) {
520
0
        return 0;
521
0
    } else {
522
0
        for (comp = 0; comp < pcs->params.device_n.num_components;comp++){
523
0
            colorant = pcs->params.device_n.colorants;
524
0
            ink = pcs->params.device_n.names[comp];
525
0
            do {
526
0
                if (memcmp(colorant->colorant_name, ink, strlen(ink)) == 0)
527
0
                    break;
528
0
                colorant = colorant->next;
529
0
            }while(colorant);
530
0
            if (!colorant) {
531
0
                all_present = 0;
532
0
                break;
533
0
            }
534
0
        }
535
0
    }
536
0
    return all_present;
537
0
}
538
/* 0 = write unchanged
539
   1 = convert to process
540
   2 = write as ICC
541
   3 = convert base space (Separation)
542
   4 = convert base space (DeviceN)
543
 */
544
static int setup_image_colorspace(gx_device_pdf *pdev, image_union_t *image, const gs_color_space *pcs, gs_color_space **pcs_orig,
545
                                  const pdf_color_space_names_t *names, cos_value_t *cs_value)
546
14.5k
{
547
14.5k
    int code=0;
548
14.5k
    gs_color_space_index csi;
549
14.5k
    gs_color_space_index csi2;
550
14.5k
    const gs_color_space *pcs2 = pcs;
551
552
14.5k
    csi = csi2 = gs_color_space_get_index(pcs);
553
14.5k
    if (csi == gs_color_space_index_ICC) {
554
12.3k
        csi2 = gsicc_get_default_type(pcs->cmm_icc_profile_data);
555
12.3k
    }
556
    /* Figure out what to do if we are outputting to really ancient versions of PDF */
557
    /* NB ps2write sets CompatibilityLevel to 1.2 so we cater for it here */
558
14.5k
    if (pdev->CompatibilityLevel <= 1.2) {
559
560
        /* If we have an /Indexed space, we need to look at the base space */
561
6.67k
        if (csi2 == gs_color_space_index_Indexed) {
562
956
            pcs2 = pcs->base_space;
563
956
            csi2 = gs_color_space_get_index(pcs2);
564
956
        }
565
566
6.67k
        switch (csi2) {
567
503
            case gs_color_space_index_DeviceGray:
568
503
                if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
569
503
                    pdev->params.ColorConversionStrategy == ccs_Gray) {
570
503
                    return 0;
571
503
                }
572
0
                else {
573
0
                    code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceGray, cs_value);
574
0
                    if (code < 0)
575
0
                        return code;
576
0
                    return 1;
577
0
                }
578
0
                break;
579
3.89k
            case gs_color_space_index_DeviceRGB:
580
3.89k
                if (pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
581
0
                    pdev->params.ColorConversionStrategy == ccs_RGB || pdev->params.ColorConversionStrategy == ccs_sRGB)
582
3.89k
                    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
144
            case gs_color_space_index_DeviceCMYK:
591
144
                if ((pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged ||
592
144
                    pdev->params.ColorConversionStrategy == ccs_CMYK) && !pdev->params.ConvertCMYKImagesToRGB)
593
144
                    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.10k
            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.10k
                csi2 = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
651
652
2.10k
                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
836
                    case gs_color_space_index_DeviceRGB:
659
836
                        if (pdev->params.ColorConversionStrategy == ccs_RGB || pdev->params.ColorConversionStrategy == ccs_sRGB ||
660
836
                            pdev->params.ColorConversionStrategy == ccs_LeaveColorUnchanged)
661
836
                            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.26k
                    default:
669
1.26k
                        break;
670
2.10k
                }
671
                /* Fall through for non-handled cases */
672
1.27k
            case gs_color_space_index_DeviceN:
673
1.27k
            case gs_color_space_index_DevicePixel:
674
1.27k
            case gs_color_space_index_Indexed:
675
1.27k
                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.27k
                    case gs_color_space_index_DeviceRGB:
680
1.27k
                        code = setup_image_process_colorspace(pdev, image, pcs_orig, names->DeviceRGB, cs_value);
681
1.27k
                        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.27k
                }
689
1.27k
                if (code < 0)
690
0
                    return code;
691
1.27k
                return 1;
692
0
                break;
693
0
            default:
694
0
                return (gs_note_error(gs_error_rangecheck));
695
0
                break;
696
6.67k
        }
697
7.83k
    } else {
698
7.83k
        int strategy = pdev->params.ColorConversionStrategy;
699
700
7.83k
        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.83k
        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.83k
            case ccs_LeaveColorUnchanged:
729
7.83k
                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.83k
        }
999
7.83k
    }
1000
0
    return 0;
1001
14.5k
}
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
83.5k
{
1010
83.5k
    int code = 0;
1011
83.5k
    gs_rect sbox, dbox, *Box;
1012
83.5k
    gs_point corners[4];
1013
83.5k
    gs_fixed_rect ibox;
1014
83.5k
    gs_matrix * pmat1 = (gs_matrix *)pmat;
1015
83.5k
    gs_matrix mat;
1016
1017
83.5k
    if (!pdev->Eps2Write)
1018
60.8k
        return 0;
1019
1020
22.6k
    if (!pdev->accumulating_charproc)
1021
21.3k
        Box = &pdev->BBox;
1022
1.29k
    else
1023
1.29k
        Box = &pdev->charproc_BBox;
1024
22.6k
    if (pmat1 == 0)
1025
22.6k
        pmat1 = (gs_matrix *)&ctm_only(pgs);
1026
22.6k
    if ((code = gs_matrix_invert(&pic->ImageMatrix, &mat)) < 0 ||
1027
22.6k
        (code = gs_matrix_multiply(&mat, pmat1, &mat)) < 0)
1028
1
        goto exit;
1029
22.6k
    sbox.p.x = prect->p.x;
1030
22.6k
    sbox.p.y = prect->p.y;
1031
22.6k
    sbox.q.x = prect->q.x;
1032
22.6k
    sbox.q.y = prect->q.y;
1033
22.6k
    gs_bbox_transform_only(&sbox, &mat, corners);
1034
22.6k
    gs_points_bbox(corners, &dbox);
1035
22.6k
    ibox.p.x = float2fixed(dbox.p.x);
1036
22.6k
    ibox.p.y = float2fixed(dbox.p.y);
1037
22.6k
    ibox.q.x = float2fixed(dbox.q.x);
1038
22.6k
    ibox.q.y = float2fixed(dbox.q.y);
1039
22.6k
    if (pcpath != NULL &&
1040
21.9k
        !gx_cpath_includes_rectangle(pcpath, ibox.p.x, ibox.p.y,
1041
21.9k
                                     ibox.q.x, ibox.q.y)
1042
22.6k
        ) {
1043
        /* Let the target do the drawing, but drive two triangles */
1044
        /* through the clipping path to get an accurate bounding box. */
1045
2.60k
        gx_device_clip cdev;
1046
2.60k
        gx_drawing_color devc;
1047
1048
2.60k
        fixed x0 = float2fixed(corners[0].x), y0 = float2fixed(corners[0].y);
1049
2.60k
        fixed bx2 = float2fixed(corners[2].x) - x0, by2 = float2fixed(corners[2].y) - y0;
1050
1051
2.60k
        pdev->AccumulatingBBox++;
1052
2.60k
        gx_make_clip_device_on_stack(&cdev, pcpath, (gx_device *)pdev);
1053
2.60k
        set_nonclient_dev_color(&devc, gx_device_black((gx_device *)pdev));  /* any non-white color will do */
1054
2.60k
        gx_default_fill_triangle((gx_device *) & cdev, x0, y0,
1055
2.60k
                                 float2fixed(corners[1].x) - x0,
1056
2.60k
                                 float2fixed(corners[1].y) - y0,
1057
2.60k
                                 bx2, by2, &devc, lop_default);
1058
2.60k
        gx_default_fill_triangle((gx_device *) & cdev, x0, y0,
1059
2.60k
                                 float2fixed(corners[3].x) - x0,
1060
2.60k
                                 float2fixed(corners[3].y) - y0,
1061
2.60k
                                 bx2, by2, &devc, lop_default);
1062
2.60k
        gx_destroy_clip_device_on_stack(&cdev);
1063
2.60k
        pdev->AccumulatingBBox--;
1064
20.0k
    } else {
1065
        /* Just use the bounding box. */
1066
20.0k
        float x0, y0, x1, y1;
1067
20.0k
        x0 = fixed2float(ibox.p.x) / (pdev->HWResolution[0] / 72.0);
1068
20.0k
        y0 = fixed2float(ibox.p.y) / (pdev->HWResolution[1] / 72.0);
1069
20.0k
        x1 = fixed2float(ibox.q.x) / (pdev->HWResolution[0] / 72.0);
1070
20.0k
        y1 = fixed2float(ibox.q.y) / (pdev->HWResolution[1] / 72.0);
1071
20.0k
        if (Box->p.x > x0)
1072
1.16k
            Box->p.x = x0;
1073
20.0k
        if (Box->p.y > y0)
1074
1.42k
            Box->p.y = y0;
1075
20.0k
        if (Box->q.x < x1)
1076
1.82k
            Box->q.x = x1;
1077
20.0k
        if (Box->q.y < y1)
1078
1.97k
            Box->q.y = y1;
1079
20.0k
    }
1080
22.6k
 exit:
1081
22.6k
    return code;
1082
22.6k
}
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
86.5k
{
1093
86.5k
    int code = 0, i;
1094
86.5k
    unsigned int use_fallback  = 0, in_line = 0, is_mask = 0,
1095
86.5k
        force_lossless = 0, convert_to_process_colors = 0;
1096
86.5k
    int width, height;
1097
86.5k
    cos_dict_t *pnamed = 0;
1098
86.5k
    image_union_t *image;
1099
86.5k
    const gs_pixel_image_t *pim;
1100
86.5k
    gs_int_rect rect;
1101
86.5k
    gs_image_format_t format;
1102
86.5k
    gs_color_space *pcs = NULL;
1103
86.5k
    int num_components;
1104
86.5k
    pdf_image_enum *pie = NULL;
1105
86.5k
    const pdf_color_space_names_t *names;
1106
86.5k
    gs_color_space *pcs_orig = NULL;
1107
86.5k
    gs_color_space *pcs_device = NULL;
1108
86.5k
    cos_value_t cs_value;
1109
86.5k
    const gs_range_t *pranges = 0;
1110
1111
86.5k
    image = (image_union_t *)gs_malloc(mem->non_gc_memory, 4,
1112
86.5k
                       sizeof(image_union_t), "pdf_begin_typed_image(image)");
1113
86.5k
    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
86.5k
    {
1121
86.5k
        cos_value_t ni_value;
1122
1123
86.5k
        if (cos_array_unadd(pdev->NI_stack, &ni_value) >= 0)
1124
8
            pnamed = (cos_dict_t *)ni_value.contents.object;
1125
86.5k
    }
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
86.5k
    pdev->image_mask_id = gs_no_id;
1131
1132
86.5k
    pim = (const gs_pixel_image_t *)pic;
1133
1134
    /* Check for the image types we can handle. */
1135
86.5k
    switch (pic->type->index) {
1136
83.5k
    case 1:
1137
83.5k
        is_mask = ((const gs_image_t *)pic)->ImageMask;
1138
83.5k
        code = setup_type1_image(pdev, pic, pdcolor, image, context);
1139
83.5k
        if (code < 0)
1140
12
            use_fallback = 1;
1141
83.5k
        else
1142
83.5k
            in_line = code;
1143
83.5k
        break;
1144
1145
109
    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
109
        pdev->JPEG_PassThrough = 0;
1161
109
        pdev->JPX_PassThrough = 0;
1162
109
        pdev->image_mask_is_SMask = false;
1163
109
        if (pdev->CompatibilityLevel < 1.2 ||
1164
109
            (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
109
        code = setup_type3_image(pdev, pgs, pmat, pic, prect, pdcolor, pcpath, mem, pinfo, image);
1171
109
        goto exit;
1172
1173
2.86k
    case IMAGE3X_IMAGETYPE:
1174
2.86k
        {
1175
2.86k
            char *OC = pdev->PendingOC;
1176
1177
2.86k
            pdev->JPEG_PassThrough = 0;
1178
2.86k
            pdev->JPX_PassThrough = 0;
1179
2.86k
            if (pdev->CompatibilityLevel < 1.4 ||
1180
2.86k
                (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
2.86k
            pdev->image_mask_is_SMask = true;
1187
1188
2.86k
            if (pdev->PendingOC)
1189
1
                gs_free_object(pdev->memory->non_gc_memory, pdev->PendingOC, "");
1190
2.86k
            OC = pdev->PendingOC = NULL;
1191
2.86k
            code = gx_begin_image3x_generic((gx_device *)pdev, pgs, pmat, pic,
1192
2.86k
                                            prect, pdcolor, pcpath, mem,
1193
2.86k
                                            pdf_image3x_make_mid,
1194
2.86k
                                            pdf_image3x_make_mcde, pinfo, OC);
1195
2.86k
            goto exit;
1196
2.86k
        }
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
22
            use_fallback = 0;
1276
22
            code = convert_type4_to_masked_image(pdev, pgs, pic, prect, pdcolor,
1277
22
                                                 pcpath, mem,pinfo);
1278
22
            goto exit;
1279
22
        }
1280
2
        image[0].type4 = *(const gs_image4_t *)pic;
1281
2
        break;
1282
1283
0
    default:
1284
0
        use_fallback = 1;
1285
0
        break;
1286
86.5k
    }
1287
1288
83.5k
    format = pim->format;
1289
83.5k
    switch (format) {
1290
83.5k
    case gs_image_format_chunky:
1291
83.5k
    case gs_image_format_component_planar:
1292
83.5k
        break;
1293
0
    default:
1294
0
        use_fallback = 1;
1295
83.5k
    }
1296
    /* AR5 on Windows doesn't support 0-size images. Skipping. */
1297
83.5k
    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
83.5k
    switch (pim->BitsPerComponent) {
1301
66.7k
        case 1:
1302
66.9k
        case 2:
1303
66.9k
        case 4:
1304
83.5k
        case 8:
1305
83.5k
        case 12:
1306
83.5k
        case 16:
1307
83.5k
            break;
1308
0
        default:
1309
0
            code = gs_note_error(gs_error_rangecheck);
1310
0
            goto exit;
1311
83.5k
    }
1312
83.5k
    if (prect)
1313
2.87k
        rect = *prect;
1314
80.6k
    else {
1315
80.6k
        rect.p.x = rect.p.y = 0;
1316
80.6k
        rect.q.x = pim->Width, rect.q.y = pim->Height;
1317
80.6k
    }
1318
83.5k
    if (rect.p.x != 0 || rect.p.y != 0 ||
1319
83.5k
        rect.q.x != pim->Width || rect.q.y != pim->Height ||
1320
83.5k
        (is_mask && pim->CombineWithColor))
1321
0
        use_fallback = 1;
1322
1323
    /* Handle BBox for Eps2Write, if applicable */
1324
83.5k
    code = pdf_image_handle_eps(pdev, pgs, pmat, pic, &rect, pcpath);
1325
83.5k
    if (code < 0) {
1326
1
        use_fallback = 0;
1327
1
        goto exit;
1328
1
    }
1329
1330
83.5k
    if (use_fallback)
1331
18
        goto exit;
1332
1333
83.4k
    pcs = pim->ColorSpace;
1334
83.4k
    rc_increment_cs(pcs);
1335
83.4k
    num_components = (is_mask ? 1 : gs_color_space_num_components(pcs));
1336
1337
83.4k
    code = pdf_check_soft_mask(pdev, (gs_gstate *)pgs);
1338
83.4k
    if (code < 0)
1339
0
        goto exit;
1340
83.4k
    if (pdf_must_put_clip_path(pdev, pcpath))
1341
4.27k
        code = pdf_unclip(pdev);
1342
79.2k
    else
1343
79.2k
        code = pdf_open_page(pdev, PDF_IN_STREAM);
1344
83.4k
    if (code < 0)
1345
0
        goto fail_and_fallback;
1346
1347
83.4k
    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
2.87k
        rc_decrement(pcs, "pdf_begin_typed_image(pcs)");
1355
2.87k
        pcs = gs_cspace_new_DeviceGray(pdev->memory);
1356
2.87k
        if (pcs == NULL)
1357
0
            code = gs_note_error(gs_error_VMerror);
1358
80.6k
    } else if (is_mask)
1359
65.9k
        code = pdf_prepare_imagemask(pdev, pgs, pdcolor);
1360
14.6k
    else
1361
14.6k
        code = pdf_prepare_image(pdev, pgs);
1362
83.4k
    if (code < 0)
1363
250
        goto fail_and_fallback;
1364
1365
83.2k
    pie = gs_alloc_struct(mem, pdf_image_enum, &st_pdf_image_enum,
1366
83.2k
                        "pdf_begin_image");
1367
83.2k
    if (pie == 0) {
1368
0
        code = gs_note_error(gs_error_VMerror);
1369
0
        goto exit;
1370
0
    }
1371
83.2k
    memset(pie, 0, sizeof(*pie)); /* cleanup entirely for GC to work in all cases. */
1372
83.2k
    *pinfo = (gx_image_enum_common_t *) pie;
1373
83.2k
    gx_image_enum_common_init(*pinfo, (const gs_data_image_t *) pim,
1374
83.2k
                    ((pdev->CompatibilityLevel >= 1.3) ?
1375
40.7k
                            (context == PDF_IMAGE_TYPE3_MASK ?
1376
2.87k
                            &pdf_image_object_enum_procs :
1377
40.7k
                            &pdf_image_enum_procs) :
1378
83.2k
                            context == PDF_IMAGE_TYPE3_MASK ?
1379
0
                            &pdf_image_object_enum_procs :
1380
42.5k
                            context == PDF_IMAGE_TYPE3_DATA ?
1381
0
                            &pdf_image_object_enum_procs2 :
1382
42.5k
                            &pdf_image_enum_procs),
1383
83.2k
                        (gx_device *)pdev, num_components, format);
1384
83.2k
    pie->memory = mem;
1385
83.2k
    pie->pgs = pgs;
1386
83.2k
    if (pgs != NULL)
1387
83.2k
        pie->pgs_level = pgs->level;
1388
83.2k
    width = rect.q.x - rect.p.x;
1389
83.2k
    pie->width = width;
1390
83.2k
    height = rect.q.y - rect.p.y;
1391
83.2k
    pie->bits_per_pixel =
1392
83.2k
        pim->BitsPerComponent * num_components / pie->num_planes;
1393
83.2k
    pie->rows_left = height;
1394
83.2k
    if (pnamed != 0 || pdev->PendingOC) /* Don't in-line the image if it is named. Or has Optional Content */
1395
21
        in_line = false;
1396
83.2k
    else {
1397
83.2k
        int64_t nbytes = (int64_t)(((int64_t) pie->width * pie->bits_per_pixel + 7) >> 3) *
1398
83.2k
            pie->num_planes * pie->rows_left;
1399
1400
83.2k
        in_line &= (nbytes < pdev->MaxInlineImageSize);
1401
83.2k
    }
1402
83.2k
    pie->initial_colorspace = pdev->pcm_color_info_index;
1403
1404
83.2k
    if (pmat == 0)
1405
77.5k
        pmat = &ctm_only(pgs);
1406
83.2k
    {
1407
83.2k
        gs_matrix mat;
1408
83.2k
        gs_matrix bmat;
1409
83.2k
        int code;
1410
1411
83.2k
        pdf_make_bitmap_matrix(&bmat, -rect.p.x, -rect.p.y,
1412
83.2k
                               pim->Width, pim->Height, height);
1413
83.2k
        if ((code = gs_matrix_invert(&pim->ImageMatrix, &mat)) < 0 ||
1414
83.2k
            (code = gs_matrix_multiply(&bmat, &mat, &mat)) < 0 ||
1415
83.2k
            (code = gs_matrix_multiply(&mat, pmat, &pie->mat)) < 0
1416
83.2k
            )
1417
0
            goto exit;
1418
        /* AR3,AR4 show no image when CTM is singular; AR5 reports an error */
1419
83.2k
        if (pie->mat.xx * pie->mat.yy == pie->mat.xy * pie->mat.yx) {
1420
587
            use_fallback = 1;
1421
587
            goto fail_and_fallback;
1422
587
        }
1423
83.2k
    }
1424
1425
82.6k
    code = pdf_put_clip_path(pdev, pcpath);
1426
82.6k
    if (code < 0)
1427
0
        goto exit;
1428
82.6k
    pdf_image_writer_init(&pie->writer);
1429
    /* Note : Possible values for alt_writer_count are 1,2,3,4.
1430
       1 means no alternative streams.
1431
       2 means the main image stream and a mask stream while converting
1432
               an Image Type 4.
1433
       3 means the main image stream, alternative image compression stream,
1434
               and the compression chooser.
1435
       4 meams 3 and a mask stream while convertingh an Image Type 4.
1436
     */
1437
82.6k
    pie->writer.alt_writer_count = (in_line ||
1438
8.94k
                                    (pim->Width <= 64 && pim->Height <= 64)
1439
82.6k
                                    ? 1 : 2);
1440
82.6k
    if ((image[0].pixel.ColorSpace != NULL &&
1441
17.3k
        image[0].pixel.ColorSpace->type->index == gs_color_space_index_Indexed
1442
2.10k
        && pdev->params.ColorImage.DownsampleType != ds_Subsample) ||
1443
81.5k
        pdev->transfer_not_identity)
1444
1.16k
        force_lossless = true;
1445
1446
82.6k
    if ((image[0].pixel.ColorSpace != NULL && image[0].pixel.ColorSpace->type->index == gs_color_space_index_Indexed)
1447
80.5k
        || force_lossless)
1448
2.11k
        pie->writer.alt_writer_count = 1;
1449
1450
82.6k
    if (image[0].pixel.ColorSpace != NULL && (image[0].pixel.ColorSpace->type->index != gs_color_space_index_DeviceGray &&
1451
17.3k
        image[0].pixel.ColorSpace->type->index != gs_color_space_index_DeviceRGB &&
1452
17.3k
        image[0].pixel.ColorSpace->type->index != gs_color_space_index_DeviceCMYK &&
1453
17.3k
        image[0].pixel.ColorSpace->type->index != gs_color_space_index_Indexed))
1454
15.2k
        names = &pdf_color_space_names;
1455
67.4k
    else
1456
67.4k
        names = (in_line ? &pdf_color_space_names_short : &pdf_color_space_names);
1457
1458
    /* We don't want to change the colour space of a mask, or an SMask (both of which are Gray) */
1459
82.6k
    if (!is_mask) {
1460
17.3k
#if 1
1461
17.3k
        if (image[0].pixel.ColorSpace != NULL && !(context == PDF_IMAGE_TYPE3_MASK))
1462
14.5k
           convert_to_process_colors = setup_image_colorspace(pdev, &image[0], pcs, &pcs_orig, names, &cs_value);
1463
#else
1464
        if (image[0].pixel.ColorSpace != NULL) {
1465
            if (context != PDF_IMAGE_TYPE3_MASK)
1466
                convert_to_process_colors = setup_image_colorspace(pdev, &image[0], pcs, &pcs_orig, names, &cs_value);
1467
            else {
1468
                if (pdev->PDFA != 0 && pdev->params.ColorConversionStrategy != ccs_Gray)
1469
                {
1470
                    /* A SMask *must* be in DeviceGray (PDF 1.7 reference, page 555), but if we're producing a PDF/A
1471
                     * and not creating a Gray output then we can't write the SMask as DeviceGray!
1472
                     */
1473
                    emprintf(pdev->memory,
1474
                         "\nDetected SMask which must be in DeviceGray, but we are not converting to DeviceGray, reverting to normal PDF output\n");
1475
                    pdev->AbortPDFAX = true;
1476
                    pdev->PDFA = 0;
1477
                }
1478
            }
1479
        }
1480
#endif
1481
1482
17.3k
        if (pim->BitsPerComponent > 8 && convert_to_process_colors) {
1483
0
            use_fallback = 1;
1484
0
            goto fail_and_fallback;
1485
0
        }
1486
17.3k
        if (convert_to_process_colors == 4) {
1487
0
            if (pdev->PDFX == 1) {
1488
0
                convert_to_process_colors = 1;
1489
0
                code = 0;
1490
0
            }
1491
0
            else
1492
0
                code = convert_DeviceN_alternate(pdev, pgs, pcs, NULL, NULL, NULL, NULL, &cs_value, in_line);
1493
0
            if (code < 0)
1494
0
                goto fail_and_fallback;
1495
0
        }
1496
17.3k
        if (convert_to_process_colors == 3) {
1497
0
            code = convert_separation_alternate(pdev, pgs, pcs, NULL, NULL, NULL, NULL, &cs_value, in_line);
1498
0
            if (code < 0)
1499
0
                goto fail_and_fallback;
1500
0
        }
1501
17.3k
        if (convert_to_process_colors == 1) {
1502
1.27k
            code = make_device_color_space(pdev, pdev->pcm_color_info_index, &pcs_device);
1503
1.27k
            if (code < 0)
1504
0
                goto fail_and_fallback;
1505
1.27k
            image[0].pixel.ColorSpace = pcs_device;
1506
1.27k
            image[0].pixel.BitsPerComponent = 8;
1507
1.27k
            code = pdf_color_space_named(pdev, pgs, &cs_value, &pranges, pcs_device, names,
1508
1.27k
                                     in_line, NULL, 0, false);
1509
1.27k
            if (code < 0)
1510
0
                goto fail_and_fallback;
1511
16.0k
        } else {
1512
16.0k
            if (convert_to_process_colors == 2) {
1513
0
                convert_to_process_colors = 0;
1514
0
                code = pdf_color_space_named(pdev, pgs, &cs_value, &pranges, pcs, names,
1515
0
                                     in_line, NULL, 0, true);
1516
0
                if (code < 0)
1517
0
                    goto fail_and_fallback;
1518
16.0k
            } else {
1519
16.0k
                convert_to_process_colors = 0;
1520
16.0k
                code = pdf_color_space_named(pdev, pgs, &cs_value, &pranges, pcs, names,
1521
16.0k
                                     in_line, NULL, 0, false);
1522
16.0k
                if (code < 0)
1523
0
                    goto fail_and_fallback;
1524
16.0k
            }
1525
16.0k
        }
1526
17.3k
    }
1527
1528
82.6k
    image[1] = image[0];
1529
1530
82.6k
    pdev->ParamCompatibilityLevel = pdev->CompatibilityLevel;
1531
1532
82.6k
    code = pdf_begin_write_image(pdev, &pie->writer, gs_no_id, width,
1533
82.6k
                    height, pnamed, in_line);
1534
82.6k
    if (code < 0)
1535
0
        goto fail_and_fallback;
1536
1537
82.6k
    if (pdev->CompatibilityLevel < 1.5)
1538
42.2k
        pdev->JPX_PassThrough = 0;
1539
1540
82.6k
    if (!convert_to_process_colors)
1541
81.3k
    {
1542
81.3k
        gs_color_space_index csi;
1543
1544
81.3k
        if (pdev->params.TransferFunctionInfo == tfi_Apply && pdev->transfer_not_identity && !is_mask) {
1545
0
            pdev->JPEG_PassThrough = 0;
1546
0
            pdev->JPX_PassThrough = 0;
1547
0
            csi = gs_color_space_get_index(image[0].pixel.ColorSpace);
1548
0
            if (csi == gs_color_space_index_Indexed) {
1549
0
                csi = gs_color_space_get_index(image[0].pixel.ColorSpace->base_space);
1550
0
                if (csi == gs_color_space_index_ICC) {
1551
0
                    csi = gsicc_get_default_type(image[0].pixel.ColorSpace->base_space->cmm_icc_profile_data);
1552
0
                }
1553
0
            } else {
1554
0
                if (csi == gs_color_space_index_ICC) {
1555
0
                    csi = gsicc_get_default_type(image[0].pixel.ColorSpace->cmm_icc_profile_data);
1556
0
                }
1557
0
            }
1558
0
            switch(csi) {
1559
0
                case gs_color_space_index_DevicePixel:
1560
0
                case gs_color_space_index_CIEA:
1561
0
                    convert_to_process_colors = 1;
1562
0
                    pdf_set_process_color_model(pdev, 0);
1563
0
                    break;
1564
0
                case gs_color_space_index_CIEDEF:
1565
0
                case gs_color_space_index_CIEABC:
1566
0
                case gs_color_space_index_DeviceGray:
1567
0
                    convert_to_process_colors = 1;
1568
0
                    pdf_set_process_color_model(pdev, 0);
1569
0
                    break;
1570
0
                case gs_color_space_index_DeviceRGB:
1571
0
                    convert_to_process_colors = 1;
1572
0
                    pdf_set_process_color_model(pdev, 1);
1573
0
                    break;
1574
0
                case gs_color_space_index_CIEDEFG:
1575
0
                case gs_color_space_index_DeviceCMYK:
1576
0
                    convert_to_process_colors = 1;
1577
0
                    pdf_set_process_color_model(pdev, 2);
1578
0
                    break;
1579
0
                default:
1580
0
                    break;
1581
0
            }
1582
0
            if (convert_to_process_colors == 1) {
1583
0
                pcs_orig = image->pixel.ColorSpace;
1584
0
                code = make_device_color_space(pdev, pdev->pcm_color_info_index, &pcs_device);
1585
0
                if (code < 0)
1586
0
                    goto fail_and_fallback;
1587
0
                image[0].pixel.ColorSpace = pcs_device;
1588
0
                code = pdf_color_space_named(pdev, pgs, &cs_value, &pranges, pcs_device, names,
1589
0
                                         in_line, NULL, 0, false);
1590
0
                if (code < 0)
1591
0
                    goto fail_and_fallback;
1592
0
            }
1593
0
        }
1594
81.3k
    }
1595
    /* If we are not preserving the colour space unchanged, then we can't pass through JPEG */
1596
1.27k
    else
1597
1.27k
        pdev->JPEG_PassThrough = pdev->JPX_PassThrough = 0;
1598
1599
    /* Code below here deals with setting up the multiple data stream writing.
1600
     * We can have up to 4 stream writers, which we keep in an array. We must
1601
     * always have at least one which writes the uncompressed stream. If we
1602
     * are writing compressed streams, we have one for the compressed stream
1603
     * and one for the compression chooser.
1604
     * For type 4 images being converted (for old versions of PDF or for ps2write)
1605
     * we need an additional stream to write a mask, which masks the real
1606
     * image.
1607
     * For colour conversion we will place an additional filter in front of all
1608
     * the streams which does the conversion.
1609
     */
1610
82.6k
    if (in_line) {
1611
73.7k
        pdev->JPEG_PassThrough = 0;
1612
73.7k
        pdev->JPX_PassThrough = 0;
1613
73.7k
        code = new_setup_lossless_filters((gx_device_psdf *) pdev,
1614
73.7k
                                             &pie->writer.binary[0],
1615
73.7k
                                             &image[0].pixel, in_line, convert_to_process_colors, (gs_matrix *)pmat, (gs_gstate *)pgs);
1616
73.7k
    } else {
1617
8.94k
        if (force_lossless) {
1618
            /*
1619
             * Some regrettable PostScript code (such as LanguageLevel 1 output
1620
             * from Microsoft's PSCRIPT.DLL driver) misuses the transfer
1621
             * function to accomplish the equivalent of indexed color.
1622
             * Downsampling (well, only averaging) or JPEG compression are not
1623
             * compatible with this.  Play it safe by using only lossless
1624
             * filters if the transfer function(s) is/are other than the
1625
             * identity and by setting the downsample type to Subsample..
1626
             */
1627
947
            int saved_downsample = pdev->params.ColorImage.DownsampleType;
1628
1629
947
            pdev->params.ColorImage.DownsampleType = ds_Subsample;
1630
947
            code = new_setup_image_filters((gx_device_psdf *) pdev,
1631
947
                                          &pie->writer.binary[0], &image[0].pixel,
1632
947
                                          pmat, pgs, true, in_line, convert_to_process_colors);
1633
947
            pdev->params.ColorImage.DownsampleType = saved_downsample;
1634
7.99k
        } else {
1635
7.99k
            code = new_setup_image_filters((gx_device_psdf *) pdev,
1636
7.99k
                                          &pie->writer.binary[0], &image[0].pixel,
1637
7.99k
                                          pmat, pgs, true, in_line, convert_to_process_colors);
1638
7.99k
        }
1639
8.94k
    }
1640
1641
82.6k
    if (code < 0)
1642
0
        goto fail_and_fallback;
1643
1644
82.6k
    if (convert_to_process_colors) {
1645
1.27k
        image[0].pixel.ColorSpace = pcs_orig;
1646
1.27k
        image[0].pixel.BitsPerComponent = pim->BitsPerComponent;
1647
1.27k
        code = psdf_setup_image_colors_filter(&pie->writer.binary[0],
1648
1.27k
                                              (gx_device_psdf *)pdev, pim, &image[0].pixel, pgs);
1649
1.27k
        if (code < 0)
1650
0
            goto fail_and_fallback;
1651
1.27k
        image[0].pixel.ColorSpace = pcs_device;
1652
1.27k
    }
1653
1654
82.6k
    if (pdev->JPEG_PassThrough || pdev->JPX_PassThrough) {
1655
1.33k
        pdev->PassThroughWriter = pie->writer.binary[0].strm;
1656
1.33k
        pie->writer.alt_writer_count = 1;
1657
1.33k
    }
1658
82.6k
    pie->JPEG_PassThrough = pdev->JPEG_PassThrough;
1659
82.6k
    pie->JPX_PassThrough = pdev->JPX_PassThrough;
1660
1661
82.6k
    if (pie->writer.alt_writer_count > 1) {
1662
6.32k
        code = pdf_make_alt_stream(pdev, &pie->writer.binary[1]);
1663
6.32k
        if (code < 0)
1664
0
            goto fail_and_fallback;
1665
6.32k
        code = new_setup_image_filters((gx_device_psdf *) pdev,
1666
6.32k
                                  &pie->writer.binary[1], &image[1].pixel,
1667
6.32k
                                  pmat, pgs, force_lossless, in_line, convert_to_process_colors);
1668
6.32k
        if (code == gs_error_rangecheck) {
1669
1670
430
            for (i=1;i < pie->writer.alt_writer_count; i++) {
1671
215
                stream *s = pie->writer.binary[i].strm;
1672
215
                cos_stream_t *pcos = cos_stream_from_pipeline(pie->writer.binary[i].strm);
1673
215
                s_close_filters(&s, NULL);
1674
215
                gs_free_object(pdev->pdf_memory, s, "compressed image stream");
1675
215
                if (pcos == 0L) {
1676
                    /* TODO: Seems like something should be freed here */
1677
0
                    code = gs_note_error(gs_error_ioerror);
1678
0
                    goto exit;
1679
0
                }
1680
215
                pcos->cos_procs->release((cos_object_t *)pcos, "pdf_begin_typed_image_impl");
1681
215
                gs_free_object(pdev->pdf_memory, pcos, "compressed image cos_stream");
1682
215
            }
1683
            /* setup_image_compression rejected the alternative compression. */
1684
215
            pie->writer.alt_writer_count = 1;
1685
215
            memset(pie->writer.binary + 1, 0, sizeof(pie->writer.binary[1]));
1686
215
            memset(pie->writer.binary + 2, 0, sizeof(pie->writer.binary[1]));
1687
6.10k
        } else if (code) {
1688
0
            goto fail_and_fallback;
1689
6.10k
        } else if (convert_to_process_colors) {
1690
0
            image[1].pixel.ColorSpace = pcs_orig;
1691
0
            image[1].pixel.BitsPerComponent = pim->BitsPerComponent;
1692
0
            code = psdf_setup_image_colors_filter(&pie->writer.binary[1],
1693
0
                                              (gx_device_psdf *)pdev, pim, &image[1].pixel, pgs);
1694
0
            if (code < 0)
1695
0
                goto fail_and_fallback;
1696
0
            image[1].pixel.ColorSpace = pcs_device;
1697
0
        }
1698
6.32k
    }
1699
1700
171k
    for (i = 0; i < pie->writer.alt_writer_count; i++) {
1701
88.7k
        code = pdf_begin_image_data_decoded(pdev, num_components, pranges, i,
1702
88.7k
                             &image[i].pixel, &cs_value, pie);
1703
88.7k
        if (code < 0)
1704
0
            goto fail_and_fallback;
1705
88.7k
    }
1706
82.6k
    if (pie->writer.alt_writer_count == 2) {
1707
6.10k
        psdf_setup_compression_chooser(&pie->writer.binary[2],
1708
6.10k
             (gx_device_psdf *)pdev, pim->Width, pim->Height,
1709
6.10k
             num_components, pim->BitsPerComponent);
1710
6.10k
        pie->writer.alt_writer_count = 3;
1711
6.10k
    }
1712
82.6k
    if (pic->type->index == 4 && pdev->CompatibilityLevel < 1.3) {
1713
0
        int i;
1714
1715
        /* Create a stream for writing the mask. */
1716
0
        i = pie->writer.alt_writer_count;
1717
0
        gs_image_t_init_mask_adjust((gs_image_t *)&image[i].type1, true, false);
1718
0
        image[i].type1.Width = image[0].pixel.Width;
1719
0
        image[i].type1.Height = image[0].pixel.Height;
1720
        /* Won't use image[2]. */
1721
0
        code = pdf_begin_write_image(pdev, &pie->writer, gs_no_id, width,
1722
0
                    height, NULL, false);
1723
0
        if (code < 0)
1724
0
            goto fail_and_fallback;
1725
0
        code = psdf_setup_image_filters((gx_device_psdf *) pdev,
1726
0
                                  &pie->writer.binary[i], &image[i].pixel,
1727
0
                                  pmat, pgs, force_lossless, in_line);
1728
0
        if (code < 0)
1729
0
            goto fail_and_fallback;
1730
        /* Bug701972 -- added input_width arg here.  For this case, just passing in the same
1731
         * width as before, so nothing changes.  This is an obscure case that isn't tested
1732
         * on the cluster (note that it requires CompatibilityLevel < 1.3).
1733
         */
1734
0
        psdf_setup_image_to_mask_filter(&pie->writer.binary[i],
1735
0
                                        (gx_device_psdf *)pdev, pim->Width, pim->Height, pim->Width,
1736
0
                                        num_components, pim->BitsPerComponent, image[i].type4.MaskColor);
1737
0
        code = pdf_begin_image_data_decoded(pdev, num_components, pranges, i,
1738
0
                             &image[i].pixel, &cs_value, pie);
1739
0
        if (code < 0)
1740
0
            goto fail_and_fallback;
1741
0
        ++pie->writer.alt_writer_count;
1742
0
    }
1743
1744
    /* use_fallback = 0, so this will drop through the below labels, doing only the cleanup parts */
1745
82.6k
    code = 0;
1746
1747
    /* This label is used when code < 0 and we want to do the fallback code */
1748
83.4k
 fail_and_fallback:
1749
83.4k
    if (code != 0)
1750
250
        use_fallback = 1;
1751
1752
    /* This label is used either when there's no error and we are just exiting normally
1753
     * (possibly with use_fallback=1), or there is an error but we don't want to do
1754
     * the fallback code.
1755
     */
1756
86.5k
 exit:
1757
    /* Free everything */
1758
86.5k
    rc_decrement(pcs, "pdf_begin_typed_image(pcs)");
1759
86.5k
    rc_decrement(pcs_device, "pdf_begin_typed_image(pcs_device)");
1760
86.5k
    gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
1761
86.5k
                                      "pdf_begin_typed_image(image)");
1762
1763
    /* Free pie only if there was an error or we are falling back */
1764
86.5k
    if (code < 0 || use_fallback) {
1765
875
        if (pie)
1766
587
            gs_free_object(mem, pie, "pdf_begin_typed_image(pie)");
1767
875
        *pinfo = NULL;
1768
875
    }
1769
    /* Do the fallback */
1770
86.5k
    if (use_fallback) {
1771
855
        pdev->JPEG_PassThrough = 0;
1772
855
        pdev->JPX_PassThrough = 0;
1773
855
        code = gx_default_begin_typed_image
1774
855
            ((gx_device *)pdev, pgs, pmat, pic, prect, pdcolor, pcpath, mem, pinfo);
1775
855
    }
1776
86.5k
    return code;
1777
83.4k
}
1778
1779
int
1780
gdev_pdf_begin_typed_image(gx_device * dev, const gs_gstate * pgs,
1781
                           const gs_matrix *pmat, const gs_image_common_t *pic,
1782
                           const gs_int_rect * prect,
1783
                           const gx_drawing_color * pdcolor,
1784
                           const gx_clip_path * pcpath, gs_memory_t * mem,
1785
                           gx_image_enum_common_t ** pinfo)
1786
80.7k
{
1787
80.7k
    return pdf_begin_typed_image((gx_device_pdf *)dev, pgs, pmat, pic, prect,
1788
80.7k
                                 pdcolor, pcpath, mem, pinfo,
1789
80.7k
                                 PDF_IMAGE_DEFAULT);
1790
80.7k
}
1791
1792
/* ---------------- All images ---------------- */
1793
1794
/* Process the next piece of an image. */
1795
static int
1796
pdf_image_plane_data_alt(gx_image_enum_common_t * info,
1797
                     const gx_image_plane_t * planes, int height,
1798
                     int *rows_used, int alt_writer_index)
1799
4.23M
{
1800
4.23M
    pdf_image_enum *pie = (pdf_image_enum *) info;
1801
4.23M
    int h = height;
1802
4.23M
    int y;
1803
    /****** DOESN'T HANDLE IMAGES WITH VARYING WIDTH PER PLANE ******/
1804
4.23M
    uint width_bits = pie->width * pie->plane_depths[0];
1805
    /****** DOESN'T HANDLE NON-ZERO data_x CORRECTLY ******/
1806
4.23M
    uint ignore;
1807
4.23M
    int nplanes = pie->num_planes;
1808
4.23M
    int status = 0;
1809
4.23M
    uint bcount = (width_bits + 7) >> 3;
1810
1811
4.23M
    if (h > pie->rows_left)
1812
63.3k
        h = pie->rows_left;
1813
9.98M
    for (y = 0; y < h; ++y) {
1814
5.74M
        if (nplanes > 1) {
1815
            /*
1816
             * We flip images in blocks, and each block except the last one
1817
             * must contain an integral number of pixels.  The easiest way
1818
             * to meet this condition is for all blocks except the last to
1819
             * be a multiple of 3 source bytes (guaranteeing an integral
1820
             * number of 1/2/4/8/12-bit samples), i.e., 3*nplanes flipped
1821
             * bytes.  This requires a buffer of at least
1822
             * 3*GS_IMAGE_MAX_COMPONENTS bytes.
1823
             */
1824
3.02k
            int pi;
1825
3.02k
            uint count = bcount;
1826
3.02k
            uint offset = 0;
1827
3.02k
#define ROW_BYTES max(200 /*arbitrary*/, 3 * GS_IMAGE_MAX_COMPONENTS)
1828
3.02k
            const byte *bit_planes[GS_IMAGE_MAX_COMPONENTS];
1829
3.02k
            int block_bytes = ROW_BYTES / (3 * nplanes) * 3;
1830
3.02k
            byte row[ROW_BYTES];
1831
1832
12.1k
            for (pi = 0; pi < nplanes; ++pi)
1833
9.07k
                bit_planes[pi] = planes[pi].data + planes[pi].raster * y;
1834
24.2k
            while (count) {
1835
21.1k
                uint flip_count;
1836
21.1k
                uint flipped_count;
1837
1838
21.1k
                if (count > block_bytes) {
1839
18.1k
                    flip_count = block_bytes;
1840
18.1k
                    flipped_count = block_bytes * nplanes;
1841
18.1k
                } else {
1842
3.02k
                    flip_count = count;
1843
3.02k
                    flipped_count =
1844
3.02k
                        (width_bits % (block_bytes * 8) * nplanes + 7) >> 3;
1845
                    /* In case the width of the image is a precise multiple of our block size */
1846
3.02k
                    if (flipped_count == 0)
1847
0
                        flipped_count = block_bytes * nplanes;
1848
3.02k
                }
1849
21.1k
                status = image_flip_planes(row, bit_planes, offset, flip_count,
1850
21.1k
                                           nplanes, pie->plane_depths[0]);
1851
21.1k
                if (status < 0)
1852
0
                    break;
1853
21.1k
                status = sputs(pie->writer.binary[alt_writer_index].strm, row,
1854
21.1k
                               flipped_count, &ignore);
1855
21.1k
                if (status < 0)
1856
0
                    break;
1857
21.1k
                offset += flip_count;
1858
21.1k
                count -= flip_count;
1859
21.1k
            }
1860
5.74M
        } else {
1861
5.74M
            status = sputs(pie->writer.binary[alt_writer_index].strm,
1862
5.74M
                           planes[0].data + planes[0].raster * y, bcount,
1863
5.74M
                           &ignore);
1864
5.74M
        }
1865
5.74M
        if (status < 0)
1866
0
            break;
1867
5.74M
    }
1868
4.23M
    *rows_used = h;
1869
4.23M
    if (status < 0)
1870
0
        return_error(gs_error_ioerror);
1871
4.23M
    return !pie->rows_left;
1872
4.23M
#undef ROW_BYTES
1873
4.23M
}
1874
1875
static int
1876
pdf_image_plane_data(gx_image_enum_common_t * info,
1877
                     const gx_image_plane_t * planes, int height,
1878
                     int *rows_used)
1879
3.98M
{
1880
3.98M
    pdf_image_enum *pie = (pdf_image_enum *) info;
1881
3.98M
    int i;
1882
1883
3.98M
    if (info->pgs != NULL && info->pgs->level < info->pgs_level)
1884
0
        return_error(gs_error_undefinedresult);
1885
1886
3.98M
    if (pie->JPEG_PassThrough || pie->JPX_PassThrough) {
1887
171k
        pie->rows_left -= height;
1888
171k
        *rows_used = height;
1889
171k
        return !pie->rows_left;
1890
171k
    }
1891
1892
8.04M
    for (i = 0; i < pie->writer.alt_writer_count; i++) {
1893
4.23M
        int code = pdf_image_plane_data_alt(info, planes, height, rows_used, i);
1894
4.23M
        if (code)
1895
0
            return code;
1896
4.23M
    }
1897
3.81M
    pie->rows_left -= *rows_used;
1898
3.81M
    if (pie->writer.alt_writer_count > 2)
1899
211k
        pdf_choose_compression(&pie->writer, false);
1900
1901
3.81M
    return !pie->rows_left;
1902
3.81M
}
1903
1904
static int
1905
use_image_as_pattern(gx_device_pdf *pdev, pdf_resource_t *pres1,
1906
                     const gs_matrix *pmat, gs_id id)
1907
0
{   /* See also dump_image in gdevpdfd.c . */
1908
0
    gs_gstate s;
1909
0
    gs_pattern1_instance_t inst;
1910
0
    cos_value_t v;
1911
0
    const pdf_resource_t *pres;
1912
0
    int code;
1913
1914
0
    memset(&s, 0, sizeof(s));
1915
0
    s.ctm.xx = pmat->xx;
1916
0
    s.ctm.xy = pmat->xy;
1917
0
    s.ctm.yx = pmat->yx;
1918
0
    s.ctm.yy = pmat->yy;
1919
0
    s.ctm.tx = pmat->tx;
1920
0
    s.ctm.ty = pmat->ty;
1921
0
    memset(&inst, 0, sizeof(inst));
1922
0
    inst.saved = (gs_gstate *)&s; /* HACK : will use s.ctm only. */
1923
0
    inst.templat.PaintType = 1;
1924
0
    inst.templat.TilingType = 1;
1925
0
    inst.templat.BBox.p.x = inst.templat.BBox.p.y = 0;
1926
0
    inst.templat.BBox.q.x = 1;
1927
0
    inst.templat.BBox.q.y = 1;
1928
0
    inst.templat.XStep = 2; /* Set 2 times bigger step against artifacts. */
1929
0
    inst.templat.YStep = 2;
1930
1931
0
    {
1932
0
        pattern_accum_param_s param;
1933
0
        param.pinst = (void *)&inst;
1934
0
        param.graphics_state = (void *)&s;
1935
0
        param.pinst_id = inst.id;
1936
1937
0
        code = (*dev_proc(pdev, dev_spec_op))((gx_device *)pdev,
1938
0
            gxdso_pattern_start_accum, &param, sizeof(pattern_accum_param_s));
1939
0
    }
1940
1941
0
    if (code >= 0)
1942
0
        pprinti64d1(pdev->strm, "/R%"PRId64" Do\n", pdf_resource_id(pres1));
1943
0
    pres = pdev->accumulating_substream_resource;
1944
0
    if (pres == NULL)
1945
0
        code = gs_note_error(gs_error_unregistered);
1946
0
    if (code >= 0)
1947
0
        code = pdf_add_resource(pdev, pdev->substream_Resources, "/XObject", pres1);
1948
0
    if (code >= 0) {
1949
0
        pattern_accum_param_s param;
1950
0
        param.pinst = (void *)&inst;
1951
0
        param.graphics_state = (void *)&s;
1952
0
        param.pinst_id = inst.id;
1953
1954
0
        code = (*dev_proc(pdev, dev_spec_op))((gx_device *)pdev,
1955
0
            gxdso_pattern_finish_accum, &param, id);
1956
0
    }
1957
0
    if (code >= 0)
1958
0
        code = (*dev_proc(pdev, dev_spec_op))((gx_device *)pdev,
1959
0
            gxdso_pattern_load, &id, sizeof(gs_id));
1960
0
    if (code >= 0) {
1961
0
        stream_puts(pdev->strm, "q ");
1962
0
        code = pdf_cs_Pattern_colored(pdev, &v);
1963
0
    }
1964
0
    if (code >= 0) {
1965
0
        cos_value_write(&v, pdev);
1966
0
        pprinti64d1(pdev->strm, " cs /R%"PRId64" scn ", pdf_resource_id(pres));
1967
0
    }
1968
0
    if (code >= 0) {
1969
        /* The image offset weas broken in gx_begin_image3_generic,
1970
           (see 'origin' in there).
1971
           As a temporary hack use the offset of the image.
1972
           fixme : This isn't generally correct,
1973
           because the mask may be "transpozed" against the image. */
1974
0
        gs_matrix m = pdev->converting_image_matrix;
1975
1976
0
        m.tx = pmat->tx;
1977
0
        m.ty = pmat->ty;
1978
0
        code = pdf_do_image_by_id(pdev, pdev->image_mask_scale,
1979
0
             &m, true, pdev->image_mask_id);
1980
0
        stream_puts(pdev->strm, "Q\n");
1981
0
    }
1982
0
    return code;
1983
0
}
1984
1985
typedef enum {
1986
    USE_AS_MASK,
1987
    USE_AS_IMAGE,
1988
    USE_AS_PATTERN
1989
} pdf_image_usage_t;
1990
1991
/* Close PDF image and do it. */
1992
static int
1993
pdf_end_and_do_image(gx_device_pdf *pdev, pdf_image_writer *piw,
1994
                     const gs_matrix *mat, gs_id ps_bitmap_id, pdf_image_usage_t do_image)
1995
79.6k
{
1996
79.6k
    int code = 0;
1997
79.6k
    pdf_resource_t *pres = NULL;
1998
1999
    /* In order to identify duplicated images which use the same SMask we must
2000
     * add the SMask entry to the image dictionary before we call pdf_end_write_image
2001
     * because that will hash the dictionaries and streams. If we haven't already
2002
     * added the SMask then the hash will not match any existing image which uses an SMask.
2003
     */
2004
79.6k
    if (do_image == USE_AS_IMAGE) {
2005
76.9k
        if (pdev->image_mask_id != gs_no_id && piw->pres && piw->pres->object) {
2006
2.65k
            char buf[20];
2007
2008
2.65k
            gs_snprintf(buf, sizeof(buf), "%ld 0 R", pdev->image_mask_id);
2009
2.65k
            code = cos_dict_put_string_copy((cos_dict_t *)piw->pres->object,
2010
2.65k
                    pdev->image_mask_is_SMask ? "/SMask" : "/Mask", buf);
2011
2.65k
            (*(piw->pres->object)).md5_valid = 0;
2012
2.65k
            if (code < 0)
2013
0
                return code;
2014
2.65k
        }
2015
76.9k
    }
2016
2017
79.6k
    code = pdf_end_write_image(pdev, piw);
2018
79.6k
    pres = piw->pres;
2019
2020
79.6k
    switch (code) {
2021
0
    default:
2022
0
        return code; /* error */
2023
72.0k
    case 1:
2024
72.0k
        code = 0;
2025
72.0k
        break;
2026
7.63k
    case 0:
2027
7.63k
        if (do_image == USE_AS_IMAGE) {
2028
4.97k
            if (pdev->image_mask_skip)
2029
0
                code = 0;
2030
4.97k
            else
2031
4.97k
                code = pdf_do_image(pdev, pres, mat, true);
2032
4.97k
        } else if (do_image == USE_AS_MASK) {
2033
            /* Provide data for pdf_do_image_by_id, which will be called through
2034
                use_image_as_pattern during the next call to this function.
2035
                See pdf_do_image about the meaning of 'scale'. */
2036
2.65k
            const pdf_x_object_t *const pxo = (const pdf_x_object_t *)pres;
2037
2038
2.65k
            pdev->image_mask_scale = (double)pxo->data_height / pxo->height;
2039
2.65k
            pdev->image_mask_id = pdf_resource_id(pres);
2040
2.65k
            pdev->converting_image_matrix = *mat;
2041
2.65k
        } else if (do_image == USE_AS_PATTERN)
2042
0
            code = use_image_as_pattern(pdev, pres, mat, ps_bitmap_id);
2043
79.6k
    }
2044
79.6k
    return code;
2045
79.6k
}
2046
2047
/* Clean up by releasing the buffers. */
2048
static int
2049
pdf_image_end_image_data(gx_image_enum_common_t * info, bool draw_last,
2050
                         pdf_image_usage_t do_image)
2051
82.6k
{
2052
82.6k
    gx_device_pdf *pdev = (gx_device_pdf *)info->dev;
2053
82.6k
    pdf_image_enum *pie = (pdf_image_enum *)info;
2054
82.6k
    int height = pie->writer.height;
2055
82.6k
    int data_height = height - pie->rows_left;
2056
82.6k
    int code = 0, ecode;
2057
2058
82.6k
    if (pie->writer.pres)
2059
8.94k
        ((pdf_x_object_t *)pie->writer.pres)->data_height = data_height;
2060
73.7k
    else if (data_height > 0)
2061
72.0k
        pdf_put_image_matrix(pdev, &pie->mat, (double)data_height / height);
2062
82.6k
    if (data_height > 0) {
2063
79.6k
        if (pie->writer.pres) {
2064
7.63k
            code = pdf_complete_image_data(pdev, &pie->writer, data_height,
2065
7.63k
                        pie->width, pie->bits_per_pixel);
2066
7.63k
            if (code < 0)
2067
0
                return code;
2068
7.63k
        }
2069
        /* This closes the stream pointed to by PassThroughWriter
2070
           so we need to NULL that pointer
2071
         */
2072
79.6k
        code = pdf_end_image_binary(pdev, &pie->writer, data_height);
2073
79.6k
        pdev->PassThroughWriter = NULL;
2074
79.6k
        pdev->JPX_PassThrough = false;
2075
79.6k
        pdev->JPEG_PassThrough = false;
2076
        /* The call above possibly decreases pie->writer.alt_writer_count in 2. */
2077
79.6k
        if (code < 0)
2078
1
            return code;
2079
79.6k
        if (pie->writer.alt_writer_count == 2) {
2080
            /* We're converting a type 4 image into an imagemask with a pattern color. */
2081
            /* Since the type 3 image writes the mask first, do so here. */
2082
0
            pdf_image_writer writer = pie->writer;
2083
2084
0
            writer.binary[0] = pie->writer.binary[1];
2085
0
            writer.pres = pie->writer.pres_mask;
2086
0
            writer.alt_writer_count = 1;
2087
0
            memset(&pie->writer.binary[1], 0, sizeof(pie->writer.binary[1]));
2088
0
            pie->writer.alt_writer_count--; /* For GC. */
2089
0
            pie->writer.pres_mask = 0; /* For GC. */
2090
0
            code = pdf_end_image_binary(pdev, &writer, data_height);
2091
0
            if (code < 0)
2092
0
                return code;
2093
0
            code = pdf_end_and_do_image(pdev, &writer, &pie->mat, info->id, USE_AS_MASK);
2094
0
            if (code < 0)
2095
0
                return code;
2096
0
            code = pdf_end_and_do_image(pdev, &pie->writer, &pie->mat, info->id, USE_AS_PATTERN);
2097
0
        } else
2098
79.6k
            code = pdf_end_and_do_image(pdev, &pie->writer, &pie->mat, info->id, do_image);
2099
79.6k
        pie->writer.alt_writer_count--; /* For GC. */
2100
79.6k
    } else {
2101
        /* This closes the stream pointed to by PassThroughWriter
2102
           so we need to NULL that pointer
2103
         */
2104
3.01k
        code = pdf_end_image_binary(pdev, &pie->writer, data_height);
2105
3.01k
        pdev->PassThroughWriter = NULL;
2106
3.01k
        pdev->JPX_PassThrough = false;
2107
3.01k
        pdev->JPEG_PassThrough = false;
2108
3.01k
        code = pdf_end_abort_image(pdev, &pie->writer);
2109
3.01k
        pie->writer.alt_writer_count--; /* For GC. */
2110
3.01k
    }
2111
82.6k
    if (pie->initial_colorspace != pdev->pcm_color_info_index)
2112
0
        pdf_set_process_color_model(pdev, pie->initial_colorspace);
2113
2114
    /* Clean up any outstanding streams before freeing the enumerator */
2115
82.6k
    while (pie->writer.alt_writer_count-- > 0) {
2116
0
        ecode = psdf_end_binary(&(pie->writer.binary[pie->writer.alt_writer_count]));
2117
        /* If we are skipping an image (because its clipped out or similar) then we
2118
         * won't have written any data to it. Some filters (notably the DCTEncode filter)
2119
         * throw an error (premature EOD) if we close the filter without writing any data to it.
2120
         * So if we are skipping the image, ignore errors when closing the stream.
2121
         * Unfortunately we don't set pie->skipping until after begin_typed_image()
2122
         * or we could avoid a lot of setup....
2123
         */
2124
0
        if (ecode < 0 && code >= 0 && !pie->skipping) code  = ecode;
2125
0
    }
2126
2127
82.6k
    gx_image_free_enum(&info);
2128
82.6k
    return code;
2129
82.6k
}
2130
2131
/* End a normal image, drawing it. */
2132
static int
2133
pdf_image_end_image(gx_image_enum_common_t * info, bool draw_last)
2134
79.7k
{
2135
79.7k
    return pdf_image_end_image_data(info, draw_last, USE_AS_IMAGE);
2136
79.7k
}
2137
2138
/* End an image converted with pdf_lcvd_t. */
2139
static int
2140
pdf_image_end_image_cvd(gx_image_enum_common_t * info, bool draw_last)
2141
22
{   pdf_lcvd_t *cvd = (pdf_lcvd_t *)info->dev;
2142
22
    int code = pdf_dump_converted_image(cvd->pdev, cvd, 0);
2143
22
    int code1 = gx_image1_end_image(info, draw_last);
2144
22
    int code2 = gs_closedevice((gx_device *)cvd->mask);
2145
22
    int code3 = gs_closedevice((gx_device *)cvd);
2146
2147
22
    gs_free_object(cvd->mask->memory, (gx_device *)cvd->mask, "pdf_image_end_image_cvd");
2148
22
    gs_free_object(cvd->mdev.memory, (gx_device *)cvd, "pdf_image_end_image_cvd");
2149
22
    return code < 0 ? code : code1 < 0 ? code1 : code2 < 0 ? code2 : code3;
2150
22
}
2151
/* ---------------- Type 3/3x images ---------------- */
2152
2153
/*
2154
 * For both types of masked images, we create temporary dummy (null) devices
2155
 * that forward the begin_typed_image call to the implementation above.
2156
 */
2157
static int
2158
pdf_make_mxd(gx_device **pmxdev, gx_device *tdev, gs_memory_t *mem)
2159
5.74k
{
2160
5.74k
    gx_device *fdev;
2161
5.74k
    int code = gs_copydevice(&fdev, (const gx_device *)&gs_null_device, mem);
2162
2163
5.74k
    if (code < 0)
2164
0
        return code;
2165
5.74k
    gx_device_set_target((gx_device_forward *)fdev, tdev);
2166
5.74k
    *pmxdev = fdev;
2167
5.74k
    return 0;
2168
5.74k
}
2169
2170
/* End the mask of an ImageType 3 image, not drawing it. */
2171
static int
2172
pdf_image_end_image_object(gx_image_enum_common_t * info, bool draw_last)
2173
2.86k
{
2174
2.86k
    return pdf_image_end_image_data(info, draw_last, USE_AS_MASK);
2175
2.86k
}
2176
/* End the data of an ImageType 3 image, converting it into pattern. */
2177
static int
2178
pdf_image_end_image_object2(gx_image_enum_common_t * info, bool draw_last)
2179
0
{
2180
0
    return pdf_image_end_image_data(info, draw_last, USE_AS_PATTERN);
2181
0
}
2182
2183
/* ---------------- Type 3 images ---------------- */
2184
2185
/* Implement the mask image device. */
2186
static dev_proc_begin_typed_image(pdf_mid_begin_typed_image);
2187
static int
2188
pdf_image3_make_mid(gx_device **pmidev, gx_device *dev, int width, int height,
2189
                    gs_memory_t *mem)
2190
105
{
2191
105
    gx_device_pdf *pdev = (gx_device_pdf *)dev;
2192
2193
105
    if (pdev->CompatibilityLevel < 1.3 && !pdev->PatternImagemask) {
2194
84
        gs_matrix m;
2195
84
        pdf_lcvd_t *cvd = NULL;
2196
84
        int code;
2197
2198
84
        gs_make_identity(&m);
2199
84
        code = pdf_setup_masked_image_converter(pdev, mem, &m, &cvd,
2200
84
                                        true, 0, 0, width, height, true);
2201
84
        if (code < 0)
2202
0
            return code;
2203
84
        cvd->mask->target = (gx_device *)cvd; /* Temporary, just to communicate with
2204
                                         pdf_image3_make_mcde. The latter will reset it. */
2205
84
        cvd->mask_is_empty = false;
2206
84
        *pmidev = (gx_device *)cvd->mask;
2207
84
        return 0;
2208
84
    } else {
2209
21
        int code = pdf_make_mxd(pmidev, dev, mem);
2210
2211
21
        if (code < 0)
2212
0
            return code;
2213
21
        set_dev_proc(*pmidev, begin_typed_image, pdf_mid_begin_typed_image);
2214
21
        return 0;
2215
21
    }
2216
105
}
2217
static int
2218
pdf_mid_begin_typed_image(gx_device * dev, const gs_gstate * pgs,
2219
                          const gs_matrix *pmat, const gs_image_common_t *pic,
2220
                          const gs_int_rect * prect,
2221
                          const gx_drawing_color * pdcolor,
2222
                          const gx_clip_path * pcpath, gs_memory_t * mem,
2223
                          gx_image_enum_common_t ** pinfo)
2224
2.87k
{
2225
    /* The target of the null device is the pdfwrite device. */
2226
2.87k
    gx_device_pdf *const pdev = (gx_device_pdf *)
2227
2.87k
        ((gx_device_null *)dev)->target;
2228
2.87k
    return pdf_begin_typed_image
2229
2.87k
        (pdev, pgs, pmat, pic, prect, pdcolor, pcpath, mem, pinfo,
2230
2.87k
         PDF_IMAGE_TYPE3_MASK);
2231
2.87k
}
2232
2233
/* Implement the mask clip device. */
2234
static int
2235
pdf_image3_make_mcde(gx_device *dev, const gs_gstate *pgs,
2236
                     const gs_matrix *pmat, const gs_image_common_t *pic,
2237
                     const gs_int_rect *prect, const gx_drawing_color *pdcolor,
2238
                     const gx_clip_path *pcpath, gs_memory_t *mem,
2239
                     gx_image_enum_common_t **pinfo,
2240
                     gx_device **pmcdev, gx_device *midev,
2241
                     gx_image_enum_common_t *pminfo,
2242
                     const gs_int_point *origin)
2243
105
{
2244
105
    int code;
2245
105
    gx_device_pdf *pdev = (gx_device_pdf *)dev;
2246
2247
105
    if (pdev->CompatibilityLevel < 1.3 && !pdev->PatternImagemask) {
2248
        /* pdf_image3_make_mid must set midev with a pdf_lcvd_t instance.*/
2249
84
        pdf_lcvd_t *cvd = (pdf_lcvd_t *)((gx_device_memory *)midev)->target;
2250
2251
84
        ((gx_device_memory *)midev)->target = NULL;
2252
84
        cvd->m = pdev->converting_image_matrix;
2253
84
        cvd->mdev.mapped_x = origin->x;
2254
84
        cvd->mdev.mapped_y = origin->y;
2255
84
        cvd->mdev.width += origin->x;
2256
84
        cvd->mdev.height += origin->y;
2257
84
        *pmcdev = (gx_device *)&cvd->mdev;
2258
84
        code = gx_default_begin_typed_image
2259
84
            ((gx_device *)&cvd->mdev, pgs, pmat, pic, prect, pdcolor, NULL, mem,
2260
84
            pinfo);
2261
84
        if (code < 0)
2262
0
            return code;
2263
84
    } else {
2264
21
        code = pdf_make_mxd(pmcdev, midev, mem);
2265
21
        if (code < 0)
2266
0
            return code;
2267
21
        code = pdf_begin_typed_image
2268
21
            ((gx_device_pdf *)dev, pgs, pmat, pic, prect, pdcolor, pcpath, mem,
2269
21
            pinfo, PDF_IMAGE_TYPE3_DATA);
2270
21
        if (code < 0) {
2271
0
            gx_device_set_target((gx_device_forward *)(*pmcdev), NULL);
2272
0
            gs_closedevice((*pmcdev));
2273
0
            gs_free_object(mem, (*pmcdev), "pdf_image3_make_mcde(*pmcdev)");
2274
0
            *pmcdev = NULL;
2275
0
            return code;
2276
0
        }
2277
21
    }
2278
    /* Due to equal image merging, we delay the adding of the "Mask" entry into
2279
       a type 3 image dictionary until the mask is completed.
2280
       Will do in pdf_end_and_do_image.*/
2281
105
    return 0;
2282
105
}
2283
2284
/* ---------------- Type 3x images ---------------- */
2285
2286
/* Implement the mask image device. */
2287
static int
2288
pdf_image3x_make_mid(gx_device **pmidev, gx_device *dev, int width, int height,
2289
                     int depth, gs_memory_t *mem)
2290
2.85k
{
2291
2.85k
    int code = pdf_make_mxd(pmidev, dev, mem);
2292
2293
2.85k
    if (code < 0)
2294
0
        return code;
2295
2.85k
    set_dev_proc(*pmidev, begin_typed_image, pdf_mid_begin_typed_image);
2296
2.85k
    return 0;
2297
2.85k
}
2298
2299
/* Implement the mask clip device. */
2300
static int
2301
pdf_image3x_make_mcde(gx_device *dev, const gs_gstate *pgs,
2302
                      const gs_matrix *pmat, const gs_image_common_t *pic,
2303
                      const gs_int_rect *prect,
2304
                      const gx_drawing_color *pdcolor,
2305
                      const gx_clip_path *pcpath, gs_memory_t *mem,
2306
                      gx_image_enum_common_t **pinfo,
2307
                      gx_device **pmcdev, gx_device *midev[2],
2308
                      gx_image_enum_common_t *pminfo[2],
2309
                      const gs_int_point origin[2],
2310
                      const gs_image3x_t *pim)
2311
2.85k
{
2312
2.85k
    int code;
2313
2.85k
    pdf_image_enum *pmie;
2314
2.85k
    int i;
2315
2.85k
    const gs_image3x_mask_t *pixm;
2316
2.85k
    gx_device_pdf *pdf_dev = (gx_device_pdf *)dev;
2317
2318
2.85k
    if (midev[0]) {
2319
2.84k
        if (midev[1])
2320
0
            return_error(gs_error_rangecheck);
2321
2.84k
        i = 0, pixm = &pim->Opacity;
2322
2.84k
    } else if (midev[1])
2323
8
        i = 1, pixm = &pim->Shape;
2324
0
    else
2325
0
        return_error(gs_error_rangecheck);
2326
2.85k
    code = pdf_make_mxd(pmcdev, midev[i], mem);
2327
2.85k
    if (code < 0)
2328
0
        return code;
2329
2330
2.85k
    if (pminfo[0] != NULL)
2331
2.84k
        pdf_dev->PendingOC = pminfo[0]->OC;
2332
8
    else
2333
8
        pdf_dev->PendingOC = 0;
2334
2335
2.85k
    code = pdf_begin_typed_image
2336
2.85k
        ((gx_device_pdf *)dev, pgs, pmat, pic, prect, pdcolor, pcpath, mem,
2337
2.85k
         pinfo, PDF_IMAGE_TYPE3_DATA);
2338
2.85k
    pdf_dev->PendingOC = 0;
2339
2.85k
    if (code < 0) {
2340
0
        rc_decrement(*pmcdev, "pdf_image3x_make_mcde");
2341
0
        return code;
2342
0
    }
2343
2.85k
    if ((*pinfo)->procs != &pdf_image_enum_procs) {
2344
        /* We couldn't handle the image.  Bail out. */
2345
4
        gx_image_end(*pinfo, false);
2346
4
        gs_free_object(mem, *pmcdev, "pdf_image3x_make_mcde");
2347
4
        return_error(gs_error_rangecheck);
2348
4
    }
2349
2.84k
    pmie = (pdf_image_enum *)pminfo[i];
2350
2.84k
    if (pmie->writer.alt_writer_count == 3) {
2351
2.63k
        cos_stream_t *s;
2352
2353
2.63k
        s = cos_stream_from_pipeline(pmie->writer.binary[1].strm);
2354
2.63k
        s_close_filters(&pmie->writer.binary[1].strm, pmie->writer.binary[1].target);
2355
2.63k
        s->cos_procs->release((cos_object_t *)s, "pdf_image_choose_filter");
2356
2.63k
        s->written = 1;
2357
2.63k
        s_close_filters(&pmie->writer.binary[2].strm, pmie->writer.binary[2].target);
2358
2.63k
        pmie->writer.binary[1].strm = pmie->writer.binary[2].strm = 0; /* for GC */
2359
2.63k
        pmie->writer.binary[1].target = pmie->writer.binary[2].target = 0;
2360
2.63k
        pmie->writer.alt_writer_count = 1;
2361
2.63k
    }
2362
    /*
2363
     * Add the SMask entry to the image dictionary, and, if needed,
2364
     * the Matte entry to the mask dictionary.
2365
     */
2366
2.84k
    if (pixm->has_Matte) {
2367
2
        gx_device_pdf *pdev = (gx_device_pdf *)dev;
2368
2
        int DoMatte = 0, num_components =
2369
2
            gs_color_space_num_components(pim->ColorSpace);
2370
2371
2
        switch (pdev->params.ColorConversionStrategy) {
2372
2
            case ccs_LeaveColorUnchanged:
2373
2
                DoMatte = 1;
2374
2
                break;
2375
0
            case ccs_RGB:
2376
0
            case ccs_sRGB:
2377
0
                if (num_components == 3)
2378
0
                    DoMatte = 1;
2379
0
                else
2380
0
                    DoMatte = 0;
2381
0
                break;
2382
0
            case ccs_CMYK:
2383
0
                if (num_components == 4)
2384
0
                    DoMatte = 1;
2385
0
                else
2386
0
                    DoMatte = 0;
2387
0
                break;
2388
0
            case ccs_Gray:
2389
0
                if (num_components == 1)
2390
0
                    DoMatte = 1;
2391
0
                else
2392
0
                    DoMatte = 0;
2393
0
                break;
2394
0
            case ccs_UseDeviceIndependentColor:
2395
0
            case ccs_UseDeviceIndependentColorForImages:
2396
0
            case ccs_ByObjectType:
2397
0
            default:
2398
0
                DoMatte = 0;
2399
0
                break;
2400
2
        }
2401
2402
2
        if (DoMatte) {
2403
2
            int code;
2404
2405
2
            code = cos_dict_put_c_key_floats((gx_device_pdf *)dev,
2406
2
                                    (cos_dict_t *)pmie->writer.pres->object,
2407
2
                                    "/Matte", pixm->Matte,
2408
2
                                    num_components);
2409
2
            if (code < 0)
2410
0
                return code;
2411
2
        }
2412
2
    }
2413
/* Don't put SMask here because pmie->writer.pres->object may be substituted
2414
 * after the image stream is accummulated. pdf_end_and_do_image will set
2415
 * SMask with the right value. Bug 690345.
2416
 */
2417
2.84k
    return 0;
2418
2.84k
}
2419
2420
pdf_resource_t *pdf_substitute_pattern(pdf_resource_t *pres)
2421
12.8k
{
2422
12.8k
    pdf_pattern_t *ppat = (pdf_pattern_t *)pres;
2423
2424
12.8k
    return (pdf_resource_t *)(ppat->substitute != 0 ? ppat->substitute : ppat);
2425
12.8k
}
2426
2427
static int
2428
check_unsubstituted2(gx_device_pdf * pdev, pdf_resource_t *pres0, pdf_resource_t *pres1)
2429
1.64k
{
2430
1.64k
    pdf_pattern_t *ppat0 = (pdf_pattern_t *)pres0;
2431
1.64k
    pdf_pattern_t *ppat1 = (pdf_pattern_t *)pres1;
2432
2433
1.64k
    return (ppat0->substitute == NULL && ppat1->substitute == NULL);
2434
1.64k
}
2435
2436
static int
2437
check_unsubstituted1(gx_device_pdf * pdev, pdf_resource_t *pres0)
2438
0
{
2439
0
    pdf_pattern_t *ppat = (pdf_pattern_t *)pres0;
2440
2441
0
    return ppat->substitute != NULL;
2442
0
}
2443
2444
static int reset_gstate_for_pattern(gx_device_pdf * pdev, gs_gstate *destination, gs_gstate *source)
2445
9.04k
{
2446
9.04k
    if (pdev->vg_initial_set) {
2447
9.04k
        destination->strokeconstantalpha = source->strokeconstantalpha;
2448
9.04k
        source->strokeconstantalpha = pdev->vg_initial.strokeconstantalpha;
2449
9.04k
        destination->fillconstantalpha = source->fillconstantalpha;
2450
9.04k
        source->fillconstantalpha = pdev->vg_initial.fillconstantalpha;
2451
9.04k
        if (destination->set_transfer.red != NULL)
2452
0
            destination->set_transfer.red->id = (source->set_transfer.red != NULL ? source->set_transfer.red->id : 0);
2453
9.04k
        if (destination->set_transfer.green != NULL)
2454
0
            destination->set_transfer.green->id = (source->set_transfer.green != NULL ? source->set_transfer.green->id : 0);
2455
9.04k
        if (destination->set_transfer.blue != NULL)
2456
0
            destination->set_transfer.blue->id = (source->set_transfer.blue != NULL ? source->set_transfer.blue->id : 0);
2457
9.04k
        if (destination->set_transfer.gray != NULL)
2458
4.51k
            destination->set_transfer.gray->id = (source->set_transfer.gray != NULL ? source->set_transfer.gray->id : 0);
2459
9.04k
        if (source->set_transfer.red != NULL)
2460
0
            source->set_transfer.red->id = pdev->vg_initial.transfer_ids[0];
2461
9.04k
        if (source->set_transfer.green != NULL)
2462
0
            source->set_transfer.green->id = pdev->vg_initial.transfer_ids[1];
2463
9.04k
        if (source->set_transfer.blue != NULL)
2464
0
            source->set_transfer.blue->id = pdev->vg_initial.transfer_ids[2];
2465
9.04k
        if (source->set_transfer.gray != NULL)
2466
4.52k
            source->set_transfer.gray->id = pdev->vg_initial.transfer_ids[3];
2467
9.04k
        destination->alphaisshape = source->alphaisshape;
2468
9.04k
        source->alphaisshape = pdev->vg_initial.alphaisshape;
2469
9.04k
        destination->blend_mode = source->blend_mode;
2470
9.04k
        source->blend_mode = pdev->vg_initial.blend_mode;
2471
9.04k
        if (destination->black_generation != NULL)
2472
4.51k
            destination->black_generation->id = (source->black_generation != NULL ? source->black_generation->id : 0);
2473
9.04k
        if (source->black_generation != NULL)
2474
4.52k
            source->black_generation->id = pdev->vg_initial.black_generation_id;
2475
9.04k
        if (destination->undercolor_removal != NULL)
2476
4.51k
            destination->undercolor_removal->id = (source->undercolor_removal != NULL ? source->undercolor_removal->id : 0);
2477
9.04k
        if (source->undercolor_removal != NULL)
2478
4.52k
            source->undercolor_removal->id = pdev->vg_initial.undercolor_removal_id;
2479
9.04k
        destination->overprint_mode = source->overprint_mode;
2480
9.04k
        source->overprint_mode = pdev->vg_initial.overprint_mode;
2481
9.04k
        destination->flatness = source->flatness;
2482
9.04k
        source->flatness = pdev->vg_initial.flatness;
2483
9.04k
        destination->smoothness = source->smoothness;
2484
9.04k
        source->smoothness = pdev->vg_initial.smoothness;
2485
9.04k
        destination->flatness = source->flatness;
2486
9.04k
        source->flatness = pdev->vg_initial.flatness;
2487
9.04k
        destination->text_knockout = source->text_knockout;
2488
9.04k
        source->text_knockout = pdev->vg_initial.text_knockout;
2489
9.04k
        destination->stroke_adjust = source->stroke_adjust;
2490
9.04k
        source->stroke_adjust = pdev->vg_initial.stroke_adjust;
2491
9.04k
        destination->line_params.half_width = source->line_params.half_width;
2492
9.04k
        source->line_params.half_width = pdev->vg_initial.line_params.half_width;
2493
9.04k
        destination->line_params.start_cap = source->line_params.start_cap;
2494
9.04k
        source->line_params.start_cap = pdev->vg_initial.line_params.start_cap;
2495
9.04k
        destination->line_params.end_cap = source->line_params.end_cap;
2496
9.04k
        source->line_params.end_cap = pdev->vg_initial.line_params.end_cap;
2497
9.04k
        destination->line_params.dash_cap = source->line_params.dash_cap;
2498
9.04k
        source->line_params.dash_cap = pdev->vg_initial.line_params.dash_cap;
2499
9.04k
        destination->line_params.join = source->line_params.join;
2500
9.04k
        source->line_params.join = pdev->vg_initial.line_params.join;
2501
9.04k
        destination->line_params.curve_join = source->line_params.curve_join;
2502
9.04k
        source->line_params.curve_join = pdev->vg_initial.line_params.curve_join;
2503
9.04k
        destination->line_params.miter_limit = source->line_params.miter_limit;
2504
9.04k
        source->line_params.miter_limit = pdev->vg_initial.line_params.miter_limit;
2505
9.04k
        destination->line_params.miter_check = source->line_params.miter_check;
2506
9.04k
        source->line_params.miter_check = pdev->vg_initial.line_params.miter_check;
2507
9.04k
        destination->line_params.dot_length = source->line_params.dot_length;
2508
9.04k
        source->line_params.dot_length = pdev->vg_initial.line_params.dot_length;
2509
9.04k
        destination->line_params.dot_length_absolute = source->line_params.dot_length_absolute;
2510
9.04k
        source->line_params.dot_length_absolute = pdev->vg_initial.line_params.dot_length_absolute;
2511
9.04k
        destination->line_params.dot_orientation = source->line_params.dot_orientation;
2512
9.04k
        source->line_params.dot_orientation = pdev->vg_initial.line_params.dot_orientation;
2513
9.04k
        if (destination->line_params.dash.pattern != NULL && destination->line_params.dash.pattern != source->line_params.dash.pattern)
2514
0
            gs_free_object(destination->memory, destination->line_params.dash.pattern, "free dash assigned during pattern accumulation");
2515
9.04k
        memcpy(&destination->line_params.dash, &source->line_params.dash, sizeof(source->line_params.dash));
2516
9.04k
        memcpy(&source->line_params.dash, &pdev->vg_initial.line_params.dash, sizeof(source->line_params.dash));
2517
9.04k
    }
2518
9.04k
    return 0;
2519
9.04k
}
2520
2521
/*
2522
   The device specific operations - just pattern management.
2523
   See gxdevcli.h about return codes.
2524
 */
2525
int
2526
gdev_pdf_dev_spec_op(gx_device *pdev1, int dev_spec_op, void *data, int size)
2527
73.6M
{
2528
73.6M
    gx_device_pdf *pdev = (gx_device_pdf *)pdev1;
2529
73.6M
    int code=0, force_CTM_change=0;
2530
73.6M
    pdf_resource_t *pres, *pres1;
2531
73.6M
    gx_bitmap_id id = (gx_bitmap_id)size;
2532
2533
73.6M
    switch (dev_spec_op) {
2534
71.3k
        case gxdso_skip_icc_component_validation:
2535
71.3k
            return 1;
2536
16.0k
        case gxdso_supports_pattern_transparency:
2537
16.0k
            return 1;
2538
4.91k
        case gxdso_pattern_can_accum:
2539
4.91k
            return 1;
2540
13.5k
        case gxdso_pdf_form_name:
2541
13.5k
            if (pdev->PDFFormName) {
2542
1
                gs_free_object(pdev->memory->non_gc_memory, pdev->PDFFormName, "free Name of Form for pdfmark");
2543
1
            }
2544
13.5k
            pdev->PDFFormName = (char *)gs_alloc_bytes(pdev->memory->non_gc_memory, size + 1, "Name of Form for pdfmark");
2545
13.5k
            if (pdev->PDFFormName == NULL)
2546
0
                return_error(gs_error_VMerror);
2547
13.5k
            memset(pdev->PDFFormName, 0x00, size + 1);
2548
13.5k
            memcpy(pdev->PDFFormName, data, size);
2549
13.5k
            return 0;
2550
0
        case gxdso_pdf_last_form_ID:
2551
0
            {
2552
0
            int *i = (int *)data;
2553
0
            *i = pdev->LastFormID;
2554
0
            }
2555
0
            return 0;
2556
13.5k
        case gxdso_form_begin:
2557
13.5k
            if ((!pdev->ForOPDFRead || pdev->HighLevelForm == 0) && pdev->PatternDepth == 0) {
2558
13.5k
                gs_form_template_t *tmplate = (gs_form_template_t *)data;
2559
13.5k
                float arry[6];
2560
13.5k
                cos_dict_t *pcd = NULL, *pcd_Resources = NULL;
2561
2562
                /* Make sure the document and page stream are open */
2563
13.5k
                code = pdfwrite_pdf_open_document(pdev);
2564
13.5k
                if (code < 0)
2565
0
                    return code;
2566
13.5k
                code = pdf_open_contents(pdev, PDF_IN_STREAM);
2567
13.5k
                if (code < 0)
2568
0
                    return code;
2569
13.5k
                if (!pdev->PDFFormName) {
2570
                    /* Put any extant clip out before we start the form */
2571
0
                    code = pdf_put_clip_path(pdev, tmplate->pcpath);
2572
0
                    if (code < 0)
2573
0
                        return code;
2574
                    /* Set the CTM to be the one passed in from the interpreter,
2575
                     * this allows us to spot forms even when translation/rotation takes place
2576
                     * as we remove the CTN from the form stream before capture
2577
                     */
2578
0
                    pprintg6(pdev->strm, "q %g %g %g %g %g %g cm\n", tmplate->CTM.xx, tmplate->CTM.xy,
2579
0
                             tmplate->CTM.yx, tmplate->CTM.yy, tmplate->CTM.tx, tmplate->CTM.ty);
2580
0
                }
2581
2582
                /* start capturing the form stream */
2583
13.5k
                code = pdf_enter_substream(pdev, resourceXObject, id, &pres, false,
2584
13.5k
                        pdev->CompressStreams);
2585
13.5k
                if (code < 0)
2586
0
                    return code;
2587
13.5k
                pcd = cos_stream_dict((cos_stream_t *)pres->object);
2588
13.5k
                pcd_Resources = cos_dict_alloc(pdev, "pdf_form(Resources)");
2589
13.5k
                if (pcd == NULL || pcd_Resources == NULL)
2590
0
                    return_error(gs_error_VMerror);
2591
13.5k
                code = cos_dict_put_c_strings(pcd, "/Type", "/XObject");
2592
13.5k
                if (code >= 0)
2593
13.5k
                    code = cos_dict_put_c_strings(pcd, "/Subtype", "/Form");
2594
13.5k
                if (code >= 0)
2595
13.5k
                    code = cos_dict_put_c_strings(pcd, "/FormType", "1");
2596
13.5k
                if (code >= 0)
2597
13.5k
                    code = cos_dict_put_c_key_object(pcd, "/Resources", COS_OBJECT(pcd_Resources));
2598
2599
13.5k
                if (pdev->PDFFormName) {
2600
                    /* This is not (I think) required when executing PS forms, because the
2601
                     * CTM is written out before we execute the Form. It *is* required for
2602
                     * PDF Appearance Forms, because the Form is written directly from the
2603
                     * outer context, not from the page, so we don't emit the CTM first.
2604
                     * We want to alter the Form BBox to take any required rotation and scaling
2605
                     * (from FitPage and /Rotate) into account so that the form appearance is
2606
                     * properly scaled and rotated.
2607
                     */
2608
13.5k
                    gs_rect bbox_out;
2609
13.5k
                    gs_matrix cmat, new_mat = tmplate->CTM;
2610
2611
                    /* We don't want anything left over from the page content stream, or other
2612
                     * annotation appearances, to affect whether or not we emit any graphics
2613
                     * state, so reset the state here to the defaults.
2614
                     */
2615
13.5k
                    pdf_viewer_state_from_gs_gstate(pdev, tmplate->pgs, NULL);
2616
                    /* For PDF Appearance streams at least, the Form BBox is modified by the
2617
                     * Form Matrix.
2618
                     */
2619
13.5k
                    code = gs_matrix_multiply(&tmplate->form_matrix, &tmplate->CTM, &cmat);
2620
13.5k
                    if (code < 0)
2621
0
                        return code;
2622
13.5k
                    code = gs_bbox_transform(&tmplate->BBox, &cmat, &bbox_out);
2623
13.5k
                    if (code < 0)
2624
0
                        return code;
2625
2626
                    /* Check the BBox is on the page. Modify it if it is not (this can happen
2627
                     * if the MediaBox does not have bottom left at 0,0)
2628
                     */
2629
13.5k
                    cmat.xx = cmat.yy = 1.0f;
2630
13.5k
                    cmat.xy = cmat.yx = cmat.tx = cmat.ty = 0.0f;
2631
13.5k
                    if(bbox_out.q.x - bbox_out.p.x > pdev->width) {
2632
0
                        cmat.xx = pdev->width / (bbox_out.q.x - bbox_out.p.x);
2633
0
                        bbox_out.q.x = bbox_out.p.x + ((bbox_out.q.x - bbox_out.p.x) * cmat.xx);
2634
0
                        force_CTM_change = 1;
2635
0
                    }
2636
13.5k
                    if(bbox_out.q.y - bbox_out.p.y > pdev->height) {
2637
0
                        cmat.yy = pdev->height / (bbox_out.q.y - bbox_out.p.y);
2638
0
                        bbox_out.q.y = bbox_out.p.y + ((bbox_out.q.y - bbox_out.p.y) * cmat.yy);
2639
0
                        force_CTM_change = 1;
2640
0
                    }
2641
2642
13.5k
                    if (bbox_out.p.x < 0) {
2643
0
                        cmat.tx = bbox_out.p.x * -1;
2644
0
                        bbox_out.q.x += cmat.tx;
2645
0
                        force_CTM_change = 1;
2646
0
                    }
2647
13.5k
                    if (floor(bbox_out.q.x) > pdev->width) {
2648
0
                        cmat.tx -= bbox_out.p.x;
2649
0
                        bbox_out.q.x -= bbox_out.p.x;
2650
0
                        bbox_out.p.x = 0;
2651
0
                        force_CTM_change = 1;
2652
0
                    }
2653
13.5k
                    if (bbox_out.p.y < 0) {
2654
3
                        cmat.ty = bbox_out.p.y * -1;
2655
3
                        bbox_out.q.y += cmat.ty;
2656
3
                        force_CTM_change = 1;
2657
3
                    }
2658
13.5k
                    if (floor(bbox_out.q.y) > pdev->height) {
2659
0
                        cmat.ty += pdev->height - bbox_out.q.y;
2660
0
                        force_CTM_change = 1;
2661
0
                    }
2662
2663
13.5k
                    if (force_CTM_change) {
2664
3
                        code = gs_matrix_multiply(&tmplate->CTM, &cmat, &new_mat);
2665
3
                        if (code < 0)
2666
0
                            return code;
2667
3
                        code = gs_matrix_multiply(&tmplate->form_matrix, &new_mat, &cmat);
2668
3
                        if (code < 0)
2669
0
                            return code;
2670
3
                        code = gs_bbox_transform(&tmplate->BBox, &cmat, &bbox_out);
2671
3
                        if (code < 0)
2672
0
                            return code;
2673
3
                        tmplate->CTM = cmat;
2674
3
                    }
2675
13.5k
                    arry[0] = bbox_out.p.x;
2676
13.5k
                    arry[1] = bbox_out.p.y;
2677
13.5k
                    arry[2] = bbox_out.q.x;
2678
13.5k
                    arry[3] = bbox_out.q.y;
2679
13.5k
                    if (code >= 0)
2680
13.5k
                        code = cos_dict_put_c_key_floats(pdev, pcd, "/BBox", arry, 4);
2681
13.5k
                    if (code < 0)
2682
0
                        return code;
2683
2684
                    /* Note that we will apply the CTM to the form, and the Form Matrix. To prevcent
2685
                     * us applying the Matrix twice, we need to set it to the identity in the Form
2686
                     * dictionary. I'm not sure why we don't need to do that for PostScript Forms.
2687
                     */
2688
13.5k
                    arry[0] = arry[3] = 1.0f;
2689
13.5k
                    arry[1] = arry[2] = arry[4] = arry[5] = 0.0f;
2690
13.5k
                } else {
2691
0
                    arry[0] = tmplate->BBox.p.x;
2692
0
                    arry[1] = tmplate->BBox.p.y;
2693
0
                    arry[2] = tmplate->BBox.q.x;
2694
0
                    arry[3] = tmplate->BBox.q.y;
2695
0
                    if (code >= 0)
2696
0
                        code = cos_dict_put_c_key_floats(pdev, pcd, "/BBox", arry, 4);
2697
0
                    if (code < 0)
2698
0
                        return code;
2699
2700
0
                    arry[0] = tmplate->form_matrix.xx;
2701
0
                    arry[1] = tmplate->form_matrix.xy;
2702
0
                    arry[2] = tmplate->form_matrix.yx;
2703
0
                    arry[3] = tmplate->form_matrix.yy;
2704
0
                    arry[4] = tmplate->form_matrix.tx;
2705
0
                    arry[5] = tmplate->form_matrix.ty;
2706
2707
0
                    pprintg2(pdev->strm, "%g 0 0 %g 0 0 cm\n",
2708
0
                         72.0 / pdev->HWResolution[0], 72.0 / pdev->HWResolution[1]);
2709
0
                }
2710
2711
13.5k
                code = cos_dict_put_c_key_floats(pdev, pcd, "/Matrix", arry, 6);
2712
13.5k
                if (code < 0)
2713
0
                    return code;
2714
2715
                /* We'll return this to the interpreter and have it set
2716
                 * as the CTM, so that we remove the prior CTM before capturing the form.
2717
                 * This is safe because forms are always run inside a gsave/grestore, so
2718
                 * CTM will be put back for us.
2719
                 */
2720
13.5k
                if (!pdev->PDFFormName) {
2721
0
                    tmplate->CTM.xx = pdev->HWResolution[0] / 72;
2722
0
                    tmplate->CTM.xy = 0.0;
2723
0
                    tmplate->CTM.yx = 0.0;
2724
0
                    tmplate->CTM.yy = pdev->HWResolution[0] / 72;
2725
0
                    tmplate->CTM.tx = 0.0;
2726
0
                    tmplate->CTM.ty = 0.0;
2727
2728
0
                    pdev->substream_Resources = pcd_Resources;
2729
0
                    pres->rid = id;
2730
0
                    if (code >= 0)
2731
0
                        pdev->HighLevelForm++;
2732
0
                    return 1;
2733
13.5k
                } else {
2734
                    /* For PDF Appearance streams (Forms) we *must* apply the
2735
                     * CTM. This is because if the PDF has a non-zero Rotate key
2736
                     * we bake that rotation into the CTM. If we didn't apply that
2737
                     * then the annotation wouldn't get rotated :-(
2738
                     */
2739
13.5k
                    pdev->substream_Resources = pcd_Resources;
2740
13.5k
                    pres->rid = id;
2741
13.5k
                    if (code >= 0)
2742
13.5k
                        pdev->HighLevelForm++;
2743
13.5k
                    return force_CTM_change;
2744
13.5k
                }
2745
13.5k
            }
2746
0
            return code;
2747
13.5k
        case gxdso_form_end:
2748
            /* This test must be the same as the one in gxdso_form_begin, above */
2749
13.5k
            if ((!pdev->ForOPDFRead || pdev->HighLevelForm == 1) && pdev->PatternDepth == 0) {
2750
13.5k
                if (pdev->CompatibilityLevel <= 1.7) {
2751
13.5k
                    code = pdf_add_procsets(pdev->substream_Resources, pdev->procsets);
2752
13.5k
                    if (code < 0)
2753
0
                        return code;
2754
13.5k
                }
2755
13.5k
                pres = pres1 = pdev->accumulating_substream_resource;
2756
13.5k
                if (pres == NULL)
2757
0
                    return_error(gs_error_unregistered);
2758
13.5k
                code = pdf_exit_substream(pdev);
2759
13.5k
                if (code < 0)
2760
0
                    return code;
2761
13.5k
                code = pdf_find_same_resource(pdev, resourceXObject, &pres, check_unsubstituted2);
2762
13.5k
                if (code < 0)
2763
0
                    return code;
2764
13.5k
                if (code > 0) {
2765
0
                    code = pdf_cancel_resource(pdev, pres1, resourceXObject);
2766
0
                    if (code < 0)
2767
0
                        return code;
2768
0
                    pres->where_used |= pdev->used_mask;
2769
13.5k
                } else if (pres->object->id < 0)
2770
13.5k
                    pdf_reserve_object_id(pdev, pres, 0);
2771
13.5k
                pdev->LastFormID = pdf_resource_id(pres);
2772
13.5k
                pdev->HighLevelForm--;
2773
13.5k
                if (pdev->accumulating_substream_resource) {
2774
0
                    code = pdf_add_resource(pdev, pdev->substream_Resources, "/XObject", pres);
2775
0
                    if (code < 0)
2776
0
                        return code;
2777
0
                }
2778
13.5k
                if (pdev->PDFFormName) {
2779
13.5k
                    cos_value_t value;
2780
2781
13.5k
                    code = cos_dict_put(pdev->local_named_objects, (const byte *)pdev->PDFFormName,
2782
13.5k
                        strlen(pdev->PDFFormName), cos_object_value(&value, pres->object));
2783
2784
13.5k
                    if (code < 0)
2785
0
                        return code;
2786
13.5k
                    pdf_drop_resource_from_chain(pdev, pres, resourceXObject);
2787
13.5k
                    pres->object = NULL;
2788
13.5k
                    gs_free_object(pdev->pdf_memory, pres, "free redundant resource");
2789
2790
13.5k
                    gs_free_object(pdev->memory->non_gc_memory, pdev->PDFFormName, "free Name of Form for pdfmark");
2791
13.5k
                    pdev->PDFFormName = 0x00;
2792
13.5k
                } else {
2793
0
                    pprinti64d1(pdev->strm, "/R%"PRId64" Do Q\n", pdf_resource_id(pres));
2794
0
                }
2795
13.5k
            }
2796
13.5k
            return 0;
2797
13.5k
        case gxdso_get_form_ID:
2798
13.5k
            {
2799
13.5k
                int *ID = data;
2800
13.5k
                *ID = pdev->LastFormID;
2801
13.5k
            }
2802
13.5k
            return 0;
2803
0
        case gxdso_repeat_form:
2804
0
            {
2805
0
                gs_form_template_t *tmplate = (gs_form_template_t *)data;
2806
2807
                /* Make sure the document and page stream are open */
2808
0
                code = pdfwrite_pdf_open_document(pdev);
2809
0
                if (code < 0)
2810
0
                    return code;
2811
0
                code = pdf_open_contents(pdev, PDF_IN_STREAM);
2812
0
                if (code < 0)
2813
0
                    return code;
2814
                /* Put any extant clip out before we start the form */
2815
0
                code = pdf_put_clip_path(pdev, tmplate->pcpath);
2816
0
                if (code < 0)
2817
0
                    return code;
2818
                /* Set the CTM to be the one passed in from the interpreter,
2819
                 * this allows us to spot forms even when translation/rotation takes place
2820
                 * as we remove the CTN from the form stream before capture
2821
                 */
2822
0
                pprintg6(pdev->strm, "q %g %g %g %g %g %g cm\n", tmplate->CTM.xx, tmplate->CTM.xy,
2823
0
                         tmplate->CTM.yx, tmplate->CTM.yy, tmplate->CTM.tx, tmplate->CTM.ty);
2824
0
                pprintld1(pdev->strm, "/R%ld Do Q\n", tmplate->FormID);
2825
0
                pres = pdf_find_resource_by_resource_id(pdev, resourceXObject, tmplate->FormID);
2826
0
                if (pres == NULL)
2827
0
                    return_error(gs_error_undefined);
2828
0
                pres->where_used |= pdev->used_mask;
2829
0
                if (pdev->accumulating_substream_resource) {
2830
0
                    code = pdf_add_resource(pdev, pdev->substream_Resources, "/XObject", pres);
2831
0
                    if (code < 0)
2832
0
                        return code;
2833
0
                }
2834
0
            }
2835
0
            return 0;
2836
4.52k
        case gxdso_pattern_start_accum:
2837
4.52k
            {
2838
4.52k
                pattern_accum_param_s *param = (pattern_accum_param_s *)data;
2839
4.52k
                gs_pattern1_instance_t *pinst = param->pinst;
2840
4.52k
                gs_gstate *pgs = param->graphics_state;
2841
2842
4.52k
                code = pdf_check_soft_mask(pdev, (gs_gstate *)pgs);
2843
4.52k
                if (code < 0)
2844
0
                    return code;
2845
4.52k
                if (pdev->context == PDF_IN_NONE) {
2846
128
                    code = pdf_open_page(pdev, PDF_IN_STREAM);
2847
128
                    if (code < 0)
2848
0
                        return code;
2849
128
                }
2850
4.52k
                code = pdf_prepare_fill_stroke(pdev, (gs_gstate *)pgs, false);
2851
4.52k
                if (code < 0)
2852
0
                    return code;
2853
4.52k
                if (pdev->PatternDepth == 0 && pdev->initial_pattern_states != NULL) {
2854
0
                    int pdepth = 0;
2855
2856
0
                    while (pdev->initial_pattern_states[pdepth] != 0x00) {
2857
0
                        gs_free_object(pdev->pdf_memory, pdev->initial_pattern_states[pdepth], "Freeing dangling pattern state");
2858
0
                        pdev->initial_pattern_states[pdepth] = NULL;
2859
0
                        pdepth++;
2860
0
                    }
2861
0
                    gs_free_object(pdev->pdf_memory->non_gc_memory, pdev->initial_pattern_states, "Freeing dangling pattern state stack");
2862
0
                }
2863
2864
4.52k
                {
2865
4.52k
                    gs_gstate **new_states;
2866
4.52k
                    int pdepth;
2867
2868
4.52k
                    new_states = (gs_gstate **)gs_alloc_bytes(pdev->pdf_memory->non_gc_memory, sizeof(gs_gstate *) * (pdev->PatternDepth + 2), "pattern initial graphics state stack");
2869
4.52k
                    if (new_states == NULL)
2870
0
                        return_error(gs_error_VMerror);
2871
4.52k
                    memset(new_states, 0x00, sizeof(gs_gstate *) * (pdev->PatternDepth + 2));
2872
4.53k
                    for (pdepth = 0; pdepth < pdev->PatternDepth;pdepth++)
2873
9
                        new_states[pdepth] = pdev->initial_pattern_states[pdepth];
2874
4.52k
                    gs_free_object(pdev->pdf_memory->non_gc_memory, pdev->initial_pattern_states, "Freeing old pattern state stack");
2875
4.52k
                    pdev->initial_pattern_states = new_states;
2876
4.52k
                }
2877
4.52k
                pdev->initial_pattern_states[pdev->PatternDepth] = (gs_gstate *)gs_alloc_struct(pdev->pdf_memory, gs_gstate, &st_gs_gstate, "gdev_pdf_dev_spec_op");
2878
4.52k
                if (pdev->initial_pattern_states[pdev->PatternDepth] == NULL)
2879
0
                    return code;
2880
4.52k
                memset(pdev->initial_pattern_states[pdev->PatternDepth], 0x00, sizeof(gs_gstate));
2881
4.52k
                pdev->initial_pattern_states[pdev->PatternDepth]->memory = pdev->pdf_memory;
2882
2883
4.52k
                reset_gstate_for_pattern(pdev, pdev->initial_pattern_states[pdev->PatternDepth], pgs);
2884
4.52k
                code = pdf_enter_substream(pdev, resourcePattern, pinst->id, &pres, false,
2885
4.52k
                        pdev->CompressStreams);
2886
4.52k
                if (code < 0) {
2887
0
                    gs_free_object(pdev->pdf_memory, pdev->initial_pattern_states[pdev->PatternDepth], "Freeing dangling pattern state");
2888
0
                    pdev->initial_pattern_states[pdev->PatternDepth] = NULL;
2889
0
                    return code;
2890
0
                }
2891
2892
                /* We have started a new substream, to avoid confusing the 'saved viewer state'
2893
                 * (the stack of pdfwrite's saved copies of graophics states) we need to reset the
2894
                 * soft_mask_id, which is the ID of the SMask we have already created in the pdfwrite
2895
                 * output. The gsave/grestore round the spec_op to start and finish the pattern
2896
                 * accumulator (see pattern_paint_prepare and pattern_paint_finish) will ensure that
2897
                 * the ID is restored when we finish capturing the pattern.
2898
                 */
2899
4.52k
                pdev->state.soft_mask_id = pgs->soft_mask_id;
2900
4.52k
                pres->rid = pinst->id;
2901
4.52k
                code = pdf_store_pattern1_params(pdev, pres, pinst);
2902
4.52k
                if (code < 0) {
2903
0
                    gs_free_object(pdev->pdf_memory, pdev->initial_pattern_states[pdev->PatternDepth], "Freeing dangling pattern state");
2904
0
                    pdev->initial_pattern_states[pdev->PatternDepth] = NULL;
2905
0
                    return code;
2906
0
                }
2907
                /* Scale the coordinate system, because object handlers assume so. See none_to_stream. */
2908
4.52k
                pprintg2(pdev->strm, "%g 0 0 %g 0 0 cm\n",
2909
4.52k
                         72.0 / pdev->HWResolution[0], 72.0 / pdev->HWResolution[1]);
2910
4.52k
                pdev->PatternDepth++;
2911
4.52k
                pdev->PatternsSinceForm++;
2912
4.52k
            }
2913
0
            return 1;
2914
4.51k
        case gxdso_pattern_finish_accum:
2915
4.51k
            {
2916
4.51k
                pattern_accum_param_s *param = (pattern_accum_param_s *)data;
2917
4.51k
                gs_gstate *pgs = param->graphics_state;
2918
2919
4.51k
                if (pdev->CompatibilityLevel <= 1.7) {
2920
4.51k
                    if (pdev->substream_Resources == NULL) {
2921
0
                        pdev->substream_Resources = cos_dict_alloc(pdev, "pdf_pattern(Resources)");
2922
0
                        if (pdev->substream_Resources == NULL)
2923
0
                            return_error(gs_error_VMerror);
2924
0
                    }
2925
4.51k
                    code = pdf_add_procsets(pdev->substream_Resources, pdev->procsets);
2926
4.51k
                    if (code < 0) {
2927
0
                        gs_free_object(pdev->pdf_memory, pdev->initial_pattern_states[pdev->PatternDepth], "Freeing dangling pattern state");
2928
0
                        pdev->initial_pattern_states[pdev->PatternDepth] = NULL;
2929
0
                        return code;
2930
0
                    }
2931
4.51k
                }
2932
4.51k
                pres = pres1 = pdev->accumulating_substream_resource;
2933
4.51k
                if (pres == NULL)
2934
0
                    code = gs_note_error(gs_error_unregistered);
2935
4.51k
                else
2936
4.51k
                    code = pdf_exit_substream(pdev);
2937
4.51k
                if (code < 0) {
2938
0
                    gs_free_object(pdev->pdf_memory, pdev->initial_pattern_states[pdev->PatternDepth], "Freeing dangling pattern state");
2939
0
                    pdev->initial_pattern_states[pdev->PatternDepth] = NULL;
2940
0
                    return code;
2941
0
                }
2942
4.51k
                if (pdev->substituted_pattern_count > 300 &&
2943
0
                        pdev->substituted_pattern_drop_page != pdev->next_page) { /* arbitrary */
2944
0
                    pdf_drop_resources(pdev, resourcePattern, check_unsubstituted1);
2945
0
                    pdev->substituted_pattern_count = 0;
2946
0
                    pdev->substituted_pattern_drop_page = pdev->next_page;
2947
0
                }
2948
4.51k
                code = pdf_find_same_resource(pdev, resourcePattern, &pres, check_unsubstituted2);
2949
4.51k
                if (code < 0) {
2950
0
                    gs_free_object(pdev->pdf_memory, pdev->initial_pattern_states[pdev->PatternDepth], "Freeing dangling pattern state");
2951
0
                    pdev->initial_pattern_states[pdev->PatternDepth] = NULL;
2952
0
                    return code;
2953
0
                }
2954
4.51k
                if (code > 0) {
2955
1.64k
                    pdf_pattern_t *ppat = (pdf_pattern_t *)pres1;
2956
2957
1.64k
                    code = pdf_cancel_resource(pdev, pres1, resourcePattern);
2958
1.64k
                    if (code < 0) {
2959
0
                        gs_free_object(pdev->pdf_memory, pdev->initial_pattern_states[pdev->PatternDepth], "Freeing dangling pattern state");
2960
0
                        pdev->initial_pattern_states[pdev->PatternDepth] = NULL;
2961
0
                        return code;
2962
0
                    }
2963
                    /* Do not remove pres1, because it keeps the substitution. */
2964
1.64k
                    ppat->substitute = (pdf_pattern_t *)pres;
2965
1.64k
                    pres->where_used |= pdev->used_mask;
2966
1.64k
                    pdev->substituted_pattern_count++;
2967
2.87k
                } else if (pres->object->id < 0)
2968
2.87k
                    pdf_reserve_object_id(pdev, pres, 0);
2969
4.51k
                reset_gstate_for_pattern(pdev, pgs, pdev->initial_pattern_states[pdev->PatternDepth - 1]);
2970
4.51k
                gs_free_object(pdev->pdf_memory, pdev->initial_pattern_states[pdev->PatternDepth - 1], "Freeing dangling pattern state");
2971
4.51k
                pdev->initial_pattern_states[pdev->PatternDepth - 1] = NULL;
2972
4.51k
                if (pdev->PatternDepth == 1) {
2973
4.51k
                    gs_free_object(pdev->pdf_memory->non_gc_memory, pdev->initial_pattern_states, "Freeing dangling pattern state");
2974
4.51k
                    pdev->initial_pattern_states = NULL;
2975
4.51k
                }
2976
2977
4.51k
                pdev->PatternDepth--;
2978
4.51k
                pdev->PatternsSinceForm--;
2979
4.51k
            }
2980
0
            return 1;
2981
10.4k
        case gxdso_pattern_load:
2982
10.4k
            pres = pdf_find_resource_by_gs_id(pdev, resourcePattern, *((gx_bitmap_id *)data));
2983
10.4k
            if (pres == 0)
2984
4.51k
                return 0;
2985
5.95k
            pres = pdf_substitute_pattern(pres);
2986
5.95k
            pres->where_used |= pdev->used_mask;
2987
5.95k
            code = pdf_add_resource(pdev, pdev->substream_Resources, "/Pattern", pres);
2988
5.95k
            if (code < 0)
2989
0
                return code;
2990
5.95k
            return 1;
2991
9.97k
        case gxdso_pattern_shading_area:
2992
9.97k
            return 0;
2993
89.2k
        case gxdso_pattern_is_cpath_accum:
2994
89.2k
            return 0;
2995
3.86k
        case gxdso_pattern_shfill_doesnt_need_path:
2996
3.86k
            return 0; /* gdev_pdf_fill_path still does need a path. */
2997
1
        case gxdso_pattern_handles_clip_path:
2998
            /* This is important when the default implementation of
2999
               of fill_path is called due to a failure in setcolor
3000
               or so, for example when a shading is incorrect.
3001
               The test case is the unfixed (buggy) Genoa test 446-01.ps .
3002
               In this case pdfwrite converts the object into rectangles,
3003
               and the clipping device has to be set up. */
3004
1
            return 0;
3005
9.87k
        case gxdso_supports_hlcolor:
3006
            /* This is used due to some aliasing between the rect_hl color
3007
               filling used by pdfwrite vs. that used by the planar device
3008
               which is actually a devn vs. the pattern type for pdfwrite.
3009
               We use this to distingush between the two */
3010
9.87k
            return 1;
3011
0
        case gxdso_needs_invariant_palette:
3012
            /* Indicates that it is not permissible to change /Indexed colour space
3013
             * palette entries after the colour space has been set.
3014
             */
3015
0
            return 1;
3016
2.78k
        case gxdso_JPEG_passthrough_query:
3017
2.78k
            pdev->JPEG_PassThrough = pdev->params.PassThroughJPEGImages;
3018
2.78k
            return 1;
3019
0
            break;
3020
0
        case gxdso_set_JPEG_PassThrough:
3021
0
            pdev->params.PassThroughJPEGImages = *((bool *)data);
3022
0
            if (*((bool *)data) == 0 && pdev->JPEG_PassThrough)
3023
0
                pdev->JPEG_PassThrough = 0;
3024
0
            return 0;
3025
0
            break;
3026
2.76k
        case gxdso_JPEG_passthrough_begin:
3027
2.76k
            return 0;
3028
0
            break;
3029
280k
        case gxdso_JPEG_passthrough_data:
3030
280k
            if (pdev->JPEG_PassThrough && pdev->PassThroughWriter)
3031
115k
            {
3032
115k
                uint ignore;
3033
115k
                if (sputs(pdev->PassThroughWriter,
3034
115k
                           data, size,
3035
115k
                           &ignore) < 0)
3036
0
                           return_error(gs_error_ioerror);
3037
115k
            }
3038
280k
            return 0;
3039
0
            break;
3040
2.59k
        case gxdso_JPEG_passthrough_end:
3041
2.59k
            pdev->JPEG_PassThrough = 0;
3042
2.59k
            pdev->PassThroughWriter = 0;
3043
2.59k
            return 0;
3044
0
            break;
3045
2.75k
        case gxdso_JPX_passthrough_query:
3046
2.75k
            pdev->JPX_PassThrough = pdev->params.PassThroughJPXImages;
3047
2.75k
            return 1;
3048
0
            break;
3049
0
        case gxdso_set_JPX_PassThrough:
3050
0
            pdev->params.PassThroughJPXImages = *((bool *)data);
3051
0
            if (*((bool *)data) == 0 && pdev->JPX_PassThrough)
3052
0
                pdev->JPX_PassThrough = 0;
3053
0
            return 0;
3054
0
            break;
3055
2.55k
        case gxdso_JPX_passthrough_begin:
3056
2.55k
            return 0;
3057
0
            break;
3058
140k
        case gxdso_JPX_passthrough_data:
3059
140k
            if (pdev->JPX_PassThrough && pdev->PassThroughWriter)
3060
44.5k
            {
3061
44.5k
                uint ignore;
3062
44.5k
                if (sputs(pdev->PassThroughWriter,
3063
44.5k
                           data, size,
3064
44.5k
                           &ignore) < 0)
3065
0
                           return_error(gs_error_ioerror);
3066
44.5k
            }
3067
140k
            return 0;
3068
0
            break;
3069
2.75k
        case gxdso_JPX_passthrough_end:
3070
2.75k
            pdev->JPX_PassThrough = 0;
3071
2.75k
            pdev->PassThroughWriter = 0;
3072
2.75k
            return 0;
3073
0
            break;
3074
3075
0
        case gxdso_event_info:
3076
0
            {
3077
0
                dev_param_req_t *request = (dev_param_req_t *)data;
3078
0
                if (memcmp(request->Param, "SubstitutedFont", 15) == 0 && (pdev->PDFA || pdev->PDFX)) {
3079
0
                    switch (pdev->PDFACompatibilityPolicy) {
3080
0
                        case 0:
3081
0
                        case 1:
3082
0
                            emprintf(pdev->memory,
3083
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");
3084
0
                            pdev->AbortPDFAX = true;
3085
0
                            pdev->PDFX = 0;
3086
0
                            pdev->PDFA = 0;
3087
0
                            break;
3088
0
                        case 2:
3089
0
                            emprintf(pdev->memory,
3090
0
                             "\n **** A font missing from the input PDF has been substituted with a different font.\n\tWidths may differ, aborting conversion!\n");
3091
0
                            pdev->AbortPDFAX = true;
3092
0
                            pdev->PDFX = 0;
3093
0
                            pdev->PDFA = 0;
3094
0
                            return gs_note_error(gs_error_unknownerror);
3095
0
                            break;
3096
0
                        default:
3097
0
                            emprintf(pdev->memory,
3098
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");
3099
0
                            pdev->AbortPDFAX = true;
3100
0
                            pdev->PDFX = 0;
3101
0
                            pdev->PDFA = 0;
3102
0
                            break;
3103
0
                    }
3104
0
                }
3105
0
                return 0;
3106
0
            }
3107
0
            break;
3108
5.67M
        case gxdso_in_smask_construction:
3109
5.67M
            return pdev->smask_construction;
3110
48
        case gxdso_pending_optional_content:
3111
48
            if (pdev->CompatibilityLevel < 1.4999) {
3112
0
                if (pdev->PDFA) {
3113
0
                    switch (pdev->PDFACompatibilityPolicy) {
3114
0
                        case 0:
3115
0
                            emprintf(pdev->memory,
3116
0
                                     "Optional Content not valid in this version of PDF, reverting to normal PDF output\n");
3117
0
                            pdev->AbortPDFAX = true;
3118
0
                            pdev->PDFA = 0;
3119
0
                            break;
3120
0
                        case 1:
3121
0
                            emprintf(pdev->memory,
3122
0
                                     "Optional Content not valid in this version of PDF. Dropping feature to preserve PDF/A compatibility\n");
3123
0
                            break;
3124
0
                        case 2:
3125
0
                            emprintf(pdev->memory,
3126
0
                                     "Optional Content not valid in this version of PDF,  aborting conversion\n");
3127
0
                            return_error (gs_error_typecheck);
3128
0
                            break;
3129
0
                        default:
3130
0
                            emprintf(pdev->memory,
3131
0
                                     "Optional Content not valid in this version of PDF, unrecognised PDFACompatibilityLevel,\nreverting to normal PDF output\n");
3132
0
                            pdev->AbortPDFAX = true;
3133
0
                            pdev->PDFA = 0;
3134
0
                            break;
3135
0
                    }
3136
0
                } else {
3137
0
                    emprintf(pdev->memory,
3138
0
                             "Optional Content not valid in this version of PDF. Dropping feature to preserve compatibility\n");
3139
0
                }
3140
0
            } else
3141
48
            {
3142
48
                char *object = data;
3143
48
                if (pdev->PendingOC)
3144
1
                    gs_free_object(pdev->memory->non_gc_memory, pdev->PendingOC, "");
3145
48
                pdev->PendingOC = (char *)gs_alloc_bytes(pdev->memory->non_gc_memory, strlen(object) + 1, "");
3146
48
                if (pdev->PendingOC == NULL)
3147
0
                    return_error(gs_error_VMerror);
3148
48
                memcpy(pdev->PendingOC, object, strlen(object) + 1);
3149
48
            }
3150
48
            return 0;
3151
0
            break;
3152
94
        case gxdso_hilevel_text_clip:
3153
94
            if (data == 0 && !pdev->accumulating_charproc) {
3154
                /* We are exiting a text render mode 'clip' by grestoring back to
3155
                 *  a time when the clip wasn't active.
3156
                 * First, check if we have a clip (this should always be true).
3157
                 */
3158
76
                if (pdev->clipped_text_pending) {
3159
                    /* Get back to the content stream. This will (amongst other things) flush
3160
                     * any pending text.
3161
                     */
3162
6
                    code = pdf_open_page(pdev, PDF_IN_STREAM);
3163
6
                    if (code < 0)
3164
0
                        return code;
3165
                    /* Reset the pending state */
3166
6
                    pdev->clipped_text_pending = 0;
3167
                    /* Restore to our saved state */
3168
3169
                    /* The saved state in this case is the dpeth of the saved gstate stack at the time we
3170
                     * started the text clipping. Note; we cannot restore back past the 'bottom' of the
3171
                     * stack, which is why we alter vgstack_bottom here, rather than just using the saved
3172
                     * level in the loop below.
3173
                     */
3174
6
                    if (pdev->vgstack_bottom)
3175
6
                        pdev->vgstack_bottom = pdev->saved_vgstack_depth_for_textclip;
3176
3177
12
                    while (pdev->vgstack_depth > pdev->vgstack_bottom) {
3178
6
                        code = pdf_restore_viewer_state(pdev, pdev->strm);
3179
6
                        if (code < 0)
3180
0
                            return code;
3181
6
                    }
3182
3183
6
                    pdev->vgstack_bottom = pdev->saved_vgstack_bottom_for_textclip;
3184
6
                    pdf_reset_text(pdev); /* because of Q */
3185
6
                }
3186
76
            } else {
3187
18
                if (!pdev->accumulating_charproc) {
3188
18
                    gs_gstate *pgs = (gs_gstate *)data;
3189
                    /* We are starting text in a clip mode
3190
                     * First make sure we aren't already in a clip mode (this should never be true)
3191
                     */
3192
18
                    if (!pdev->clipped_text_pending) {
3193
                        /* Return to the content stream, this will (amongst other things) flush
3194
                         * any pending text.
3195
                         */
3196
18
                        code = pdf_open_page(pdev, PDF_IN_STREAM);
3197
18
                        if (code < 0)
3198
0
                            return code;
3199
3200
18
                        if (pdf_must_put_clip_path(pdev, pgs->clip_path)) {
3201
0
                           code = pdf_unclip(pdev);
3202
0
                            if (code < 0)
3203
0
                                return code;
3204
0
                            code = pdf_put_clip_path(pdev, pgs->clip_path);
3205
0
                            if (code < 0)
3206
0
                                return code;
3207
0
                        }
3208
3209
18
                        pdev->saved_vgstack_depth_for_textclip = pdev->vgstack_depth;
3210
3211
                        /* Save the current graphics state (or at least that bit which we track) so
3212
                         * that we can put it back later.
3213
                         */
3214
18
                        code = pdf_save_viewer_state(pdev, pdev->strm);
3215
18
                        if (code < 0)
3216
0
                            return code;
3217
18
                        pdev->clipped_text_pending = 1;
3218
3219
                        /* Save the current 'bottom' of the saved gstate stack, we need to
3220
                         * restore back to this state when we exit the graphics state
3221
                         * with a text rendering mode involving a clip.
3222
                         */
3223
18
                        pdev->saved_vgstack_bottom_for_textclip = pdev->vgstack_bottom;
3224
                        /* And push the bottom of the stack up until it is where we are now.
3225
                         * This is because clip paths, images, and possibly other constructs
3226
                         * will emit a clip path if the 'depth - bottom' is not zero, to create
3227
                         * a clip path. We want to make sure that it doesn't try to restore back
3228
                         * to a point before we established the text clip.
3229
                         */
3230
18
                        pdev->vgstack_bottom = pdev->vgstack_depth;
3231
18
                    }
3232
18
                }
3233
18
            }
3234
94
            break;
3235
2.64M
        case gxdso_get_dev_param:
3236
2.64M
            {
3237
2.64M
                int code;
3238
2.64M
                dev_param_req_t *request = (dev_param_req_t *)data;
3239
2.64M
                code = gdev_pdf_get_param(pdev1, request->Param, request->list);
3240
2.64M
                if (code != gs_error_undefined)
3241
2.58M
                    return code;
3242
2.64M
            }
3243
            /* Fall through */
3244
73.6M
    }
3245
64.6M
    return gx_default_dev_spec_op(pdev1, dev_spec_op, data, size);
3246
73.6M
}