Coverage Report

Created: 2025-02-15 06:18

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