Coverage Report

Created: 2026-07-24 07:44

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