Coverage Report

Created: 2025-06-10 07:27

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