Coverage Report

Created: 2022-10-31 07:00

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