Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/base/gdevp14.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2022 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
/* Compositing devices for implementing PDF 1.4 imaging model */
17
18
#include "assert_.h"
19
#include "math_.h"
20
#include "memory_.h"
21
#include "gx.h"
22
#include "gserrors.h"
23
#include "gscdefs.h"
24
#include "gxdevice.h"
25
#include "gsdevice.h"
26
#include "gsstruct.h"
27
#include "gxgstate.h"
28
#include "gxdcolor.h"
29
#include "gxiparam.h"
30
#include "gstparam.h"
31
#include "gxblend.h"
32
#include "gxtext.h"
33
#include "gsimage.h"
34
#include "gsrect.h"
35
#include "gscoord.h"
36
#include "gzstate.h"
37
#include "gdevdevn.h"
38
#include "gdevmem.h"
39
#include "gdevp14.h"
40
#include "gdevprn.h"    /* for prn_device structures */
41
#include "gdevppla.h"   /* for gdev_prn_open_planar */
42
#include "gdevdevnprn.h"
43
#include "gscdevn.h"
44
#include "gsovrc.h"
45
#include "gxcmap.h"
46
#include "gscolor1.h"
47
#include "gstrans.h"
48
#include "gsutil.h"
49
#include "gxcldev.h"
50
#include "gxclpath.h"
51
#include "gxdcconv.h"
52
#include "gsptype2.h"
53
#include "gxpcolor.h"
54
#include "gsptype1.h"
55
#include "gzcpath.h"
56
#include "gxpaint.h"
57
#include "gsicc_manage.h"
58
#include "gsicc_cache.h"
59
#include "gxclist.h"
60
#include "gxiclass.h"
61
#include "gximage.h"
62
#include "gsmatrix.h"
63
#include "gxdevsop.h"
64
#include "gsicc.h"
65
#ifdef WITH_CAL
66
#include "cal.h"
67
#define CAL_SLOP 16
68
#else
69
#define CAL_SLOP 0
70
#endif
71
#include "assert_.h"
72
#include "gxgetbit.h"
73
74
#if RAW_DUMP
75
unsigned int global_index = 0;
76
unsigned int clist_band_count = 0;
77
#endif
78
79
#define DUMP_MASK_STACK 0
80
81
/* Static prototypes */
82
/* Used for filling rects when we are doing a fill with a pattern that
83
   has transparency */
84
static int pdf14_tile_pattern_fill(gx_device * pdev, const gs_gstate * pgs,
85
                                   gx_path * ppath, const gx_fill_params * params,
86
                                   const gx_device_color * pdevc, const gx_clip_path * pcpath);
87
static pdf14_mask_t *pdf14_mask_element_new(gs_memory_t *memory);
88
static void pdf14_free_smask_color(pdf14_device * pdev);
89
static int compute_group_device_int_rect(pdf14_device *pdev, gs_int_rect *rect,
90
                                         const gs_rect *pbbox, gs_gstate *pgs);
91
static int pdf14_clist_update_params(pdf14_clist_device * pdev,
92
                                     const gs_gstate * pgs,
93
                                     bool crop_blend_params,
94
                                     gs_pdf14trans_params_t *group_params);
95
static int pdf14_mark_fill_rectangle_ko_simple(gx_device *  dev, int x, int y,
96
                                               int w, int h, gx_color_index color,
97
                                               const gx_device_color *pdc,
98
                                               bool devn);
99
static int pdf14_copy_alpha_color(gx_device * dev, const byte * data, int data_x,
100
                                  int aa_raster, gx_bitmap_id id, int x, int y, int w, int h,
101
                                  gx_color_index color, const gx_device_color *pdc,
102
                                  int depth, bool devn);
103
104
/* Functions for dealing with soft mask color */
105
static int pdf14_decrement_smask_color(gs_gstate * pgs, gx_device * dev);
106
static int pdf14_increment_smask_color(gs_gstate * pgs, gx_device * dev);
107
108
/*
109
 * We chose the blending color space based upon the process color model of the
110
 * output device.  For gray, RGB, CMYK, or CMYK+spot devices, the choice is
111
 * usually simple.  For other devices or if the user is doing custom color
112
 * processing then the user may want to control this choice.
113
 */
114
#define AUTO_USE_CUSTOM_BLENDING 0
115
#define ALWAYS_USE_CUSTOM_BLENDING 1
116
#define DO_NOT_USE_CUSTOM_BLENDING 2
117
118
#define CUSTOM_BLENDING_MODE AUTO_USE_CUSTOM_BLENDING
119
120
# define INCR(v) DO_NOTHING
121
122
/* Forward prototypes */
123
void pdf14_cmyk_cs_to_cmyk_cm(const gx_device *, frac, frac, frac, frac, frac *);
124
static int gs_pdf14_device_push(gs_memory_t *mem, gs_gstate * pgs,
125
                                gx_device ** pdev, gx_device * target,
126
                                const gs_pdf14trans_t * pdf14pct);
127
static int gs_pdf14_clist_device_push(gs_memory_t * mem, gs_gstate * pgs,
128
                                      gx_device ** pdev, gx_device * target,
129
                                      const gs_pdf14trans_t * pdf14pct);
130
static int pdf14_tile_pattern_fill(gx_device * pdev,
131
                const gs_gstate * pgs, gx_path * ppath,
132
                const gx_fill_params * params,
133
                const gx_device_color * pdevc, const gx_clip_path * pcpath);
134
static pdf14_mask_t * pdf14_mask_element_new(gs_memory_t * memory);
135
#ifdef DEBUG
136
static void pdf14_debug_mask_stack_state(pdf14_ctx *ctx);
137
#endif
138
139
/* A structure used by the pdf14 device so that
140
   we can do the proper dance when the alphabuf
141
   device is being used */
142
typedef struct pdf14_abuf_state_s {
143
    bool op_ca_eq_CA;
144
    bool path_empty;
145
    float stroke_alpha;
146
    float fill_alpha;
147
    gs_gstate* pgs;
148
    gs_blend_mode_t blend_mode;
149
    bool group_needed;
150
    OP_FS_STATE orig_state;
151
} pdf14_abuf_state_t;
152
153
/* Buffer stack data structure */
154
gs_private_st_ptrs7(st_pdf14_buf, pdf14_buf, "pdf14_buf",
155
                    pdf14_buf_enum_ptrs, pdf14_buf_reloc_ptrs,
156
                    saved, data, backdrop, transfer_fn, mask_stack,
157
                    matte, group_color_info);
158
159
gs_private_st_ptrs3(st_pdf14_ctx, pdf14_ctx, "pdf14_ctx",
160
                    pdf14_ctx_enum_ptrs, pdf14_ctx_reloc_ptrs,
161
                    stack, mask_stack, base_color);
162
163
gs_private_st_ptrs1(st_pdf14_clr, pdf14_group_color_t, "pdf14_clr",
164
                    pdf14_clr_enum_ptrs, pdf14_clr_reloc_ptrs, previous);
165
166
gs_private_st_ptrs2(st_pdf14_mask, pdf14_mask_t, "pdf_mask",
167
                    pdf14_mask_enum_ptrs, pdf14_mask_reloc_ptrs,
168
                    rc_mask, previous);
169
170
gs_private_st_ptrs1(st_pdf14_rcmask, pdf14_rcmask_t, "pdf_rcmask",
171
                    pdf14_rcmask_enum_ptrs, pdf14_rcmask_reloc_ptrs,
172
                    mask_buf);
173
174
gs_private_st_ptrs1(st_pdf14_smaskcolor, pdf14_smaskcolor_t, "pdf14_smaskcolor",
175
                    pdf14_smaskcolor_enum_ptrs, pdf14_smaskcolor_reloc_ptrs,
176
                    profiles);
177
178
/* ------ The device descriptors ------ */
179
180
/*
181
 * Default X and Y resolution.
182
 */
183
#define X_DPI 72
184
#define Y_DPI 72
185
186
static int pdf14_initialize_device(gx_device *dev);
187
188
static  int pdf14_open(gx_device * pdev);
189
static  dev_proc_close_device(pdf14_close);
190
static  int pdf14_output_page(gx_device * pdev, int num_copies, int flush);
191
static  dev_proc_put_params(pdf14_put_params);
192
static  dev_proc_get_color_comp_index(pdf14_cmykspot_get_color_comp_index);
193
static  dev_proc_get_color_comp_index(pdf14_rgbspot_get_color_comp_index);
194
static  dev_proc_get_color_comp_index(pdf14_grayspot_get_color_comp_index);
195
static  dev_proc_get_color_mapping_procs(pdf14_cmykspot_get_color_mapping_procs);
196
static  dev_proc_get_color_mapping_procs(pdf14_rgbspot_get_color_mapping_procs);
197
static  dev_proc_get_color_mapping_procs(pdf14_grayspot_get_color_mapping_procs);
198
dev_proc_encode_color(pdf14_encode_color);
199
dev_proc_encode_color(pdf14_encode_color_tag);
200
dev_proc_decode_color(pdf14_decode_color);
201
dev_proc_encode_color(pdf14_encode_color16);
202
dev_proc_encode_color(pdf14_encode_color16_tag);
203
dev_proc_decode_color(pdf14_decode_color16);
204
static  dev_proc_fill_rectangle(pdf14_fill_rectangle);
205
static  dev_proc_fill_rectangle_hl_color(pdf14_fill_rectangle_hl_color);
206
static  dev_proc_fill_path(pdf14_fill_path);
207
static  dev_proc_fill_stroke_path(pdf14_fill_stroke_path);
208
static  dev_proc_copy_mono(pdf14_copy_mono);
209
static  dev_proc_fill_mask(pdf14_fill_mask);
210
static  dev_proc_stroke_path(pdf14_stroke_path);
211
static  dev_proc_begin_typed_image(pdf14_begin_typed_image);
212
static  dev_proc_text_begin(pdf14_text_begin);
213
static  dev_proc_composite(pdf14_composite);
214
static  dev_proc_composite(pdf14_forward_composite);
215
static  dev_proc_begin_transparency_group(pdf14_begin_transparency_group);
216
static  dev_proc_end_transparency_group(pdf14_end_transparency_group);
217
static  dev_proc_begin_transparency_mask(pdf14_begin_transparency_mask);
218
static  dev_proc_end_transparency_mask(pdf14_end_transparency_mask);
219
static  dev_proc_dev_spec_op(pdf14_dev_spec_op);
220
static  dev_proc_push_transparency_state(pdf14_push_transparency_state);
221
static  dev_proc_pop_transparency_state(pdf14_pop_transparency_state);
222
static  dev_proc_ret_devn_params(pdf14_ret_devn_params);
223
static  dev_proc_update_spot_equivalent_colors(pdf14_update_spot_equivalent_colors);
224
static  dev_proc_copy_alpha(pdf14_copy_alpha);
225
static  dev_proc_copy_planes(pdf14_copy_planes);
226
static  dev_proc_copy_alpha_hl_color(pdf14_copy_alpha_hl_color);
227
static  dev_proc_discard_transparency_layer(pdf14_discard_trans_layer);
228
static  dev_proc_strip_tile_rect_devn(pdf14_strip_tile_rect_devn);
229
static  const gx_color_map_procs *
230
    pdf14_get_cmap_procs(const gs_gstate *, const gx_device *);
231
232
#define XSIZE (int)(8.5 * X_DPI)  /* 8.5 x 11 inch page, by default */
233
#define YSIZE (int)(11 * Y_DPI)
234
235
/* 24-bit color. */
236
237
static void
238
pdf14_procs_initialize(gx_device *dev,
239
                       dev_proc_get_color_mapping_procs(get_color_mapping_procs),
240
                       dev_proc_get_color_comp_index(get_color_comp_index),
241
                       dev_proc_encode_color(encode_color),
242
                       dev_proc_decode_color(decode_color))
243
1.21M
{
244
1.21M
    set_dev_proc(dev, initialize_device, pdf14_initialize_device);
245
1.21M
    set_dev_proc(dev, open_device, pdf14_open);
246
1.21M
    set_dev_proc(dev, output_page, pdf14_output_page);
247
1.21M
    set_dev_proc(dev, close_device, pdf14_close);
248
1.21M
    set_dev_proc(dev, map_rgb_color, encode_color);
249
1.21M
    set_dev_proc(dev, map_color_rgb, decode_color);
250
1.21M
    set_dev_proc(dev, fill_rectangle, pdf14_fill_rectangle);
251
1.21M
    set_dev_proc(dev, copy_mono, pdf14_copy_mono);
252
1.21M
    set_dev_proc(dev, get_params, gx_forward_get_params);
253
1.21M
    set_dev_proc(dev, put_params, pdf14_put_params);
254
1.21M
    set_dev_proc(dev, copy_alpha, pdf14_copy_alpha);
255
1.21M
    set_dev_proc(dev, fill_path, pdf14_fill_path);
256
1.21M
    set_dev_proc(dev, stroke_path, pdf14_stroke_path);
257
1.21M
    set_dev_proc(dev, fill_mask, pdf14_fill_mask);
258
1.21M
    set_dev_proc(dev, begin_typed_image, pdf14_begin_typed_image);
259
1.21M
    set_dev_proc(dev, composite, pdf14_composite);
260
1.21M
    set_dev_proc(dev, text_begin, pdf14_text_begin);
261
1.21M
    set_dev_proc(dev, begin_transparency_group, pdf14_begin_transparency_group);
262
1.21M
    set_dev_proc(dev, end_transparency_group, pdf14_end_transparency_group);
263
1.21M
    set_dev_proc(dev, begin_transparency_mask, pdf14_begin_transparency_mask);
264
1.21M
    set_dev_proc(dev, end_transparency_mask, pdf14_end_transparency_mask);
265
1.21M
    set_dev_proc(dev, discard_transparency_layer, pdf14_discard_trans_layer);
266
1.21M
    set_dev_proc(dev, get_color_mapping_procs, get_color_mapping_procs);
267
1.21M
    set_dev_proc(dev, get_color_comp_index, get_color_comp_index);
268
1.21M
    set_dev_proc(dev, encode_color, encode_color);
269
1.21M
    set_dev_proc(dev, decode_color, decode_color);
270
1.21M
    set_dev_proc(dev, fill_rectangle_hl_color, pdf14_fill_rectangle_hl_color);
271
1.21M
    set_dev_proc(dev, update_spot_equivalent_colors, gx_forward_update_spot_equivalent_colors);
272
1.21M
    set_dev_proc(dev, ret_devn_params, pdf14_ret_devn_params);
273
1.21M
    set_dev_proc(dev, push_transparency_state, pdf14_push_transparency_state);
274
1.21M
    set_dev_proc(dev, pop_transparency_state, pdf14_pop_transparency_state);
275
1.21M
    set_dev_proc(dev, dev_spec_op, pdf14_dev_spec_op);
276
1.21M
    set_dev_proc(dev, copy_planes, pdf14_copy_planes);
277
1.21M
    set_dev_proc(dev, set_graphics_type_tag, gx_forward_set_graphics_type_tag);
278
1.21M
    set_dev_proc(dev, strip_tile_rect_devn, pdf14_strip_tile_rect_devn);
279
1.21M
    set_dev_proc(dev, copy_alpha_hl_color, pdf14_copy_alpha_hl_color);
280
1.21M
    set_dev_proc(dev, fill_stroke_path, pdf14_fill_stroke_path);
281
1.21M
}
282
283
static void
284
pdf14_Gray_initialize_device_procs(gx_device *dev)
285
171k
{
286
171k
    pdf14_procs_initialize(dev,
287
171k
                           gx_default_DevGray_get_color_mapping_procs,
288
171k
                           gx_default_DevGray_get_color_comp_index,
289
171k
                           pdf14_encode_color,
290
171k
                           pdf14_decode_color);
291
171k
}
292
293
static void
294
pdf14_RGB_initialize_device_procs(gx_device *dev)
295
825k
{
296
825k
    pdf14_procs_initialize(dev,
297
825k
                           gx_default_DevRGB_get_color_mapping_procs,
298
825k
                           gx_default_DevRGB_get_color_comp_index,
299
825k
                           pdf14_encode_color,
300
825k
                           pdf14_decode_color);
301
825k
}
302
303
static void
304
pdf14_CMYK_initialize_device_procs(gx_device *dev)
305
187k
{
306
187k
    pdf14_procs_initialize(dev,
307
187k
                           gx_default_DevCMYK_get_color_mapping_procs,
308
187k
                           gx_default_DevCMYK_get_color_comp_index,
309
187k
                           pdf14_encode_color,
310
187k
                           pdf14_decode_color);
311
187k
}
312
313
static void
314
pdf14_CMYKspot_initialize_device_procs(gx_device *dev)
315
26.1k
{
316
26.1k
    pdf14_procs_initialize(dev,
317
26.1k
                           pdf14_cmykspot_get_color_mapping_procs,
318
26.1k
                           pdf14_cmykspot_get_color_comp_index,
319
26.1k
                           pdf14_encode_color,
320
26.1k
                           pdf14_decode_color);
321
26.1k
}
322
323
static void
324
pdf14_RGBspot_initialize_device_procs(gx_device *dev)
325
4.66k
{
326
4.66k
    pdf14_procs_initialize(dev,
327
4.66k
                           pdf14_rgbspot_get_color_mapping_procs,
328
4.66k
                           pdf14_rgbspot_get_color_comp_index,
329
4.66k
                           pdf14_encode_color,
330
4.66k
                           pdf14_decode_color);
331
4.66k
}
332
333
static void
334
pdf14_Grayspot_initialize_device_procs(gx_device *dev)
335
0
{
336
0
    pdf14_procs_initialize(dev,
337
0
                           pdf14_grayspot_get_color_mapping_procs,
338
0
                           pdf14_grayspot_get_color_comp_index,
339
0
                           pdf14_encode_color,
340
0
                           pdf14_decode_color);
341
0
}
342
343
static void
344
pdf14_custom_initialize_device_procs(gx_device *dev)
345
0
{
346
0
    pdf14_procs_initialize(dev,
347
0
                           gx_forward_get_color_mapping_procs,
348
0
                           gx_forward_get_color_comp_index,
349
0
                           gx_forward_encode_color,
350
0
                           gx_forward_decode_color);
351
0
}
352
353
static struct_proc_finalize(pdf14_device_finalize);
354
355
gs_private_st_composite_use_final(st_pdf14_device, pdf14_device, "pdf14_device",
356
                                  pdf14_device_enum_ptrs, pdf14_device_reloc_ptrs,
357
                          pdf14_device_finalize);
358
359
static int pdf14_put_image(gx_device * dev, gs_gstate * pgs,
360
                                                        gx_device * target);
361
static int pdf14_cmykspot_put_image(gx_device * dev, gs_gstate * pgs,
362
                                                        gx_device * target);
363
static int pdf14_custom_put_image(gx_device * dev, gs_gstate * pgs,
364
                                                        gx_device * target);
365
366
/* Alter pdf14 device color model based upon group or softmask. This occurs
367
   post clist or in immediate rendering case. Data stored with buffer */
368
static pdf14_group_color_t* pdf14_push_color_model(gx_device *dev,
369
                              gs_transparency_color_t group_color, int64_t icc_hashcode,
370
                              cmm_profile_t *iccprofile, bool is_mask);
371
static void pdf14_pop_color_model(gx_device* dev, pdf14_group_color_t* group_color);
372
373
/* Alter clist writer device color model based upon group or softmask. Data
374
   stored in the device color model stack */
375
static int pdf14_clist_push_color_model(gx_device* dev, gx_device* cdev, gs_gstate* pgs,
376
    const gs_pdf14trans_t* pdf14pct, gs_memory_t* mem, bool is_mask);
377
static int pdf14_clist_pop_color_model(gx_device* dev, gs_gstate* pgs);
378
379
/* Used for cleaning up the stack if things go wrong */
380
static void pdf14_pop_group_color(gx_device *dev, const gs_gstate *pgs);
381
382
static const pdf14_procs_t gray_pdf14_procs = {
383
    pdf14_unpack_additive,
384
    pdf14_put_image,
385
    pdf14_unpack16_additive
386
};
387
388
static const pdf14_procs_t rgb_pdf14_procs = {
389
    pdf14_unpack_additive,
390
    pdf14_put_image,
391
    pdf14_unpack16_additive
392
};
393
394
static const pdf14_procs_t cmyk_pdf14_procs = {
395
    pdf14_unpack_subtractive,
396
    pdf14_put_image,
397
    pdf14_unpack16_subtractive
398
};
399
400
static const pdf14_procs_t cmykspot_pdf14_procs = {
401
    pdf14_unpack_custom,  /* should never be used since we will use devn values */
402
    pdf14_cmykspot_put_image,
403
    pdf14_unpack16_custom /* should never be used since we will use devn values */
404
};
405
406
static const pdf14_procs_t rgbspot_pdf14_procs = {
407
    pdf14_unpack_rgb_mix,
408
    pdf14_cmykspot_put_image,
409
    pdf14_unpack16_rgb_mix
410
};
411
412
static const pdf14_procs_t grayspot_pdf14_procs = {
413
    pdf14_unpack_gray_mix,
414
    pdf14_cmykspot_put_image,
415
    pdf14_unpack16_gray_mix
416
};
417
418
static const pdf14_procs_t custom_pdf14_procs = {
419
    pdf14_unpack_custom,
420
    pdf14_custom_put_image,
421
    pdf14_unpack16_custom
422
};
423
424
static const pdf14_nonseparable_blending_procs_t gray_blending_procs = {
425
    art_blend_luminosity_custom_8,
426
    art_blend_saturation_custom_8,
427
    art_blend_luminosity_custom_16,
428
    art_blend_saturation_custom_16
429
};
430
431
static const pdf14_nonseparable_blending_procs_t rgb_blending_procs = {
432
    art_blend_luminosity_rgb_8,
433
    art_blend_saturation_rgb_8,
434
    art_blend_luminosity_rgb_16,
435
    art_blend_saturation_rgb_16
436
};
437
438
static const pdf14_nonseparable_blending_procs_t cmyk_blending_procs = {
439
    art_blend_luminosity_cmyk_8,
440
    art_blend_saturation_cmyk_8,
441
    art_blend_luminosity_cmyk_16,
442
    art_blend_saturation_cmyk_16
443
};
444
445
static const pdf14_nonseparable_blending_procs_t rgbspot_blending_procs = {
446
    art_blend_luminosity_rgb_8,
447
    art_blend_saturation_rgb_8,
448
    art_blend_luminosity_rgb_16,
449
    art_blend_saturation_rgb_16
450
};
451
452
static const pdf14_nonseparable_blending_procs_t grayspot_blending_procs = {
453
    art_blend_luminosity_custom_8,
454
    art_blend_saturation_custom_8,
455
    art_blend_luminosity_custom_16,
456
    art_blend_saturation_custom_16
457
};
458
459
static const pdf14_nonseparable_blending_procs_t custom_blending_procs = {
460
    art_blend_luminosity_custom_8,
461
    art_blend_saturation_custom_8,
462
    art_blend_luminosity_custom_16,
463
    art_blend_saturation_custom_16
464
};
465
466
const pdf14_device gs_pdf14_Gray_device = {
467
    std_device_std_color_full_body_type(pdf14_device,
468
                                        pdf14_Gray_initialize_device_procs,
469
                                        "pdf14gray",
470
                                        &st_pdf14_device,
471
                                        XSIZE, YSIZE, X_DPI, Y_DPI, 8,
472
                                        0, 0, 0, 0, 0, 0),
473
    { 0 },      /* Procs */
474
    NULL,     /* target */
475
    { 0 },      /* devn_params - not used */
476
    &gray_pdf14_procs,
477
    &gray_blending_procs,
478
    1
479
};
480
481
const pdf14_device gs_pdf14_RGB_device = {
482
    std_device_color_stype_body(pdf14_device,
483
                                pdf14_RGB_initialize_device_procs,
484
                                "pdf14RGB",
485
                                &st_pdf14_device,
486
                                XSIZE, YSIZE, X_DPI, Y_DPI, 24, 255, 256),
487
    { 0 },      /* Procs */
488
    NULL,     /* target */
489
    { 0 },      /* devn_params - not used */
490
    &rgb_pdf14_procs,
491
    &rgb_blending_procs,
492
    3
493
};
494
495
const pdf14_device gs_pdf14_CMYK_device = {
496
    std_device_std_color_full_body_type(pdf14_device,
497
                                        pdf14_CMYK_initialize_device_procs,
498
                                        "pdf14cmyk",
499
                                        &st_pdf14_device,
500
                                        XSIZE, YSIZE, X_DPI, Y_DPI, 32,
501
                                        0, 0, 0, 0, 0, 0),
502
    { 0 },      /* Procs */
503
    NULL,     /* target */
504
    { 0 },      /* devn_params - not used */
505
    &cmyk_pdf14_procs,
506
    &cmyk_blending_procs,
507
    4
508
};
509
510
const pdf14_device gs_pdf14_CMYKspot_device = {
511
    std_device_part1_(pdf14_device,
512
                      pdf14_CMYKspot_initialize_device_procs,
513
                      "pdf14cmykspot",
514
                      &st_pdf14_device,
515
                      open_init_closed),
516
    dci_values(GX_DEVICE_COLOR_MAX_COMPONENTS,64,255,255,256,256),
517
    std_device_part2_(XSIZE, YSIZE, X_DPI, Y_DPI),
518
    offset_margin_values(0, 0, 0, 0, 0, 0),
519
    std_device_part3_(),
520
    { 0 },      /* Procs */
521
    NULL,     /* target */
522
    /* DeviceN parameters */
523
    { 8,      /* Not used - Bits per color */
524
      DeviceCMYKComponents, /* Names of color model colorants */
525
      4,      /* Number colorants for CMYK */
526
      0,      /* MaxSeparations has not been specified */
527
      -1,     /* PageSpotColors has not been specified */
528
      {0},      /* SeparationNames */
529
      0,      /* SeparationOrder names */
530
      {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
531
    },
532
    &cmykspot_pdf14_procs,
533
    &cmyk_blending_procs,
534
    4
535
};
536
537
const pdf14_device gs_pdf14_RGBspot_device = {
538
    std_device_part1_(pdf14_device,
539
                      pdf14_RGBspot_initialize_device_procs,
540
                      "pdf14rgbspot",
541
                      &st_pdf14_device,
542
                      open_init_closed),
543
    dci_values(GX_DEVICE_COLOR_MAX_COMPONENTS,64,255,255,256,256),
544
    std_device_part2_(XSIZE, YSIZE, X_DPI, Y_DPI),
545
    offset_margin_values(0, 0, 0, 0, 0, 0),
546
    std_device_part3_(),
547
    { 0 },      /* Procs */
548
    NULL,     /* target */
549
                    /* DeviceN parameters */
550
    { 8,      /* Not used - Bits per color */
551
    0,              /* Names of color model colorants */
552
    3,          /* Number colorants for RGB */
553
    0,          /* MaxSeparations has not been specified */
554
    -1,         /* PageSpotColors has not been specified */
555
    { 0 },      /* SeparationNames */
556
    0,          /* SeparationOrder names */
557
    { 0, 1, 2, 3, 4, 5, 6, 7 }  /* Initial component SeparationOrder */
558
    },
559
    &rgbspot_pdf14_procs,
560
    &rgbspot_blending_procs,
561
    3
562
};
563
564
const pdf14_device gs_pdf14_Grayspot_device = {
565
    std_device_part1_(pdf14_device,
566
                      pdf14_Grayspot_initialize_device_procs,
567
                      "pdf14grayspot",
568
                      &st_pdf14_device,
569
                      open_init_closed),
570
    dci_values(GX_DEVICE_COLOR_MAX_COMPONENTS,64,255,255,256,256),
571
    std_device_part2_(XSIZE, YSIZE, X_DPI, Y_DPI),
572
    offset_margin_values(0, 0, 0, 0, 0, 0),
573
    std_device_part3_(),
574
    { 0 },      /* Procs */
575
    NULL,     /* target */
576
                    /* DeviceN parameters */
577
    { 8,      /* Not used - Bits per color */
578
    0,              /* Names of color model colorants */
579
    3,          /* Number colorants for RGB */
580
    0,          /* MaxSeparations has not been specified */
581
    -1,         /* PageSpotColors has not been specified */
582
    { 0 },      /* SeparationNames */
583
    0,          /* SeparationOrder names */
584
    { 0, 1, 2, 3, 4, 5, 6, 7 }  /* Initial component SeparationOrder */
585
    },
586
    &grayspot_pdf14_procs,
587
    &grayspot_blending_procs,
588
    1
589
};
590
591
/*
592
 * The 'custom' PDF 1.4 compositor device is for working with those devices
593
 * which support spot colors but do not have a CMYK process color model.
594
 *
595
 * This causes some problems with the Hue, Saturation, Color, and Luminosity
596
 * blending modes.  These blending modes are 'non separable' and depend upon
597
 * knowing the details of the blending color space.  However we use the
598
 * process color model of the output device for our blending color space.
599
 * With an unknown process color model, we have to fall back to some 'guesses'
600
 * about how to treat these blending modes.
601
 */
602
const pdf14_device gs_pdf14_custom_device = {
603
    std_device_part1_(pdf14_device,
604
                      pdf14_custom_initialize_device_procs,
605
                      "pdf14custom",
606
                      &st_pdf14_device,
607
                      open_init_closed),
608
    dci_values(GX_DEVICE_COLOR_MAX_COMPONENTS,64,255,255,256,256),
609
    std_device_part2_(XSIZE, YSIZE, X_DPI, Y_DPI),
610
    offset_margin_values(0, 0, 0, 0, 0, 0),
611
    std_device_part3_(),
612
    { 0 },      /* Procs */
613
    NULL,     /* target */
614
    /* DeviceN parameters */
615
    { 8,      /* Not used - Bits per color */
616
      DeviceCMYKComponents, /* Names of color model colorants */
617
      4,      /* Number colorants for CMYK */
618
      0,      /* MaxSeparations has not been specified */
619
      -1,     /* PageSpotColors has not been specified */
620
      {0},      /* SeparationNames */
621
      0,      /* SeparationOrder names */
622
      {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
623
    },
624
    &custom_pdf14_procs,
625
    &custom_blending_procs,
626
    4
627
};
628
629
/* Devices used for pdf14-accum-* device, one for  each image colorspace, */
630
/* Gray, RGB, CMYK, DeviceN. Before calling gdev_prn_open, the following  */
631
/* are set from the target device: width, height, xdpi, ydpi, MaxBitmap.  */
632
633
static dev_proc_print_page(no_print_page);
634
static  dev_proc_ret_devn_params(pdf14_accum_ret_devn_params);
635
static  dev_proc_get_color_comp_index(pdf14_accum_get_color_comp_index);
636
static  dev_proc_get_color_mapping_procs(pdf14_accum_get_color_mapping_procs);
637
static  dev_proc_update_spot_equivalent_colors(pdf14_accum_update_spot_equivalent_colors);
638
639
static int
640
no_print_page(gx_device_printer *pdev, gp_file *prn_stream)
641
0
{
642
0
    return_error(gs_error_unknownerror);
643
0
}
644
645
struct gx_device_pdf14_accum_s {
646
    gx_devn_prn_device_common;
647
    gx_device *save_p14dev;   /* the non-clist pdf14 deivce saved for after accum */
648
};
649
typedef struct gx_device_pdf14_accum_s gx_device_pdf14_accum;
650
651
int
652
pdf14_accum_dev_spec_op(gx_device *pdev, int dev_spec_op, void *data, int size)
653
3.06M
{
654
3.06M
    gx_device_pdf14_accum *adev = (gx_device_pdf14_accum *)pdev;
655
656
3.06M
    if (dev_spec_op == gxdso_device_child) {
657
799
        gxdso_device_child_request *req = (gxdso_device_child_request *)data;
658
799
        if (size < sizeof(*req))
659
0
            return gs_error_unknownerror;
660
799
        req->target = adev->save_p14dev;
661
799
        req->n = 0;
662
799
        return 0;
663
799
    }
664
665
3.06M
    return gdev_prn_dev_spec_op(pdev, dev_spec_op, data, size);
666
3.06M
}
667
668
gs_private_st_suffix_add1_final(st_gx_devn_accum_device, gx_device_pdf14_accum,
669
        "gx_device_pdf14_accum", pdf14_accum_device_enum_ptrs, pdf14_accum_device_reloc_ptrs,
670
                          gx_devn_prn_device_finalize, st_gx_devn_prn_device, save_p14dev);
671
672
static void
673
pdf14_accum_Gray_initialize_device_procs(gx_device *dev)
674
67
{
675
67
    gdev_prn_initialize_device_procs_gray8(dev);
676
677
67
    set_dev_proc(dev, encode_color, gx_default_8bit_map_gray_color);
678
67
    set_dev_proc(dev, decode_color, gx_default_8bit_map_color_gray);
679
67
}
680
681
const gx_device_pdf14_accum pdf14_accum_Gray = {
682
    prn_device_stype_body(gx_device_pdf14_accum,
683
                          pdf14_accum_Gray_initialize_device_procs,
684
                          "pdf14-accum-Gray",
685
                          &st_gx_devn_accum_device,
686
                          0/*width*/, 0/*height*/, 300/*xdpi*/, 300/*ydpi*/,
687
                          0/*lm*/, 0/*bm*/, 0/*rm*/, 0/*tm*/,
688
                          1/*ncomp*/, 8/*depth*/, 255/*max_gray*/, 0/*max_color*/,
689
                          256/*dither_grays*/, 0/*dither_colors*/,
690
                          no_print_page),
691
    { 0 },      /* devn_params - not used */
692
    { 0 },      /* equivalent_cmyk_color_params - not used */
693
    0/*save_p14dev*/
694
};
695
696
static void
697
pdf14_accum_RGB_initialize_device_procs(gx_device *dev)
698
851
{
699
851
    gdev_prn_initialize_device_procs_rgb(dev);
700
851
}
701
702
const gx_device_pdf14_accum pdf14_accum_RGB = {
703
    prn_device_stype_body(gx_device_pdf14_accum,
704
                          pdf14_accum_RGB_initialize_device_procs,
705
                          "pdf14-accum-RGB",
706
                          &st_gx_devn_accum_device,
707
                          0/*width*/, 0/*height*/, 300/*xdpi*/, 300/*ydpi*/,
708
                          0/*lm*/, 0/*bm*/, 0/*rm*/, 0/*tm*/,
709
                          3/*ncomp*/, 24/*depth*/, 0/*max_gray*/, 255/*max_color*/,
710
                          1/*dither_grays*/, 256/*dither_colors*/,
711
                          no_print_page),
712
    { 0 },      /* devn_params - not used */
713
    { 0 },      /* equivalent_cmyk_color_params - not used */
714
    0/*save_p14dev*/
715
};
716
717
static void
718
pdf14_accum_CMYK_initialize_device_procs(gx_device *dev)
719
0
{
720
0
    gdev_prn_initialize_device_procs_cmyk8(dev);
721
722
0
    set_dev_proc(dev, encode_color, cmyk_8bit_map_cmyk_color);
723
0
    set_dev_proc(dev, decode_color, cmyk_8bit_map_color_cmyk);
724
0
}
725
726
const gx_device_pdf14_accum pdf14_accum_CMYK = {
727
    prn_device_stype_body(gx_device_pdf14_accum,
728
                          pdf14_accum_CMYK_initialize_device_procs,
729
                          "pdf14-accum-CMYK",
730
                          &st_gx_devn_accum_device,
731
                          0/*width*/, 0/*height*/, 300/*xdpi*/, 300/*ydpi*/,
732
                          0/*lm*/, 0/*bm*/, 0/*rm*/, 0/*tm*/,
733
                          4/*ncomp*/, 32/*depth*/, 255/*max_gray*/, 255/*max_color*/,
734
                          256/*dither_grays*/, 256/*dither_colors*/,
735
                          no_print_page),
736
    { 0 },      /* devn_params - not used */
737
    { 0 },      /* equivalent_cmyk_color_params - not used */
738
    0/*save_p14dev*/
739
};
740
741
static void
742
pdf14_accum_initialize_device_procs_cmykspot(gx_device *dev)
743
0
{
744
0
    pdf14_accum_CMYK_initialize_device_procs(dev);
745
746
0
    set_dev_proc(dev, get_color_mapping_procs, pdf14_accum_get_color_mapping_procs);
747
0
    set_dev_proc(dev, get_color_comp_index, pdf14_accum_get_color_comp_index);
748
0
    set_dev_proc(dev, update_spot_equivalent_colors, pdf14_accum_update_spot_equivalent_colors);
749
0
    set_dev_proc(dev, ret_devn_params, pdf14_accum_ret_devn_params);
750
0
}
751
752
const gx_device_pdf14_accum pdf14_accum_CMYKspot = {
753
    prn_device_stype_body(gx_device_pdf14_accum,
754
                          pdf14_accum_initialize_device_procs_cmykspot,
755
                          "pdf14-accum-CMYKspot",
756
                          &st_gx_devn_accum_device,
757
                          0/*width*/, 0/*height*/, 300/*xdpi*/, 300/*ydpi*/,
758
                          0/*lm*/, 0/*bm*/, 0/*rm*/, 0/*tm*/,
759
                          4/*ncomp*/, 32/*depth*/, 255/*max_gray*/, 255/*max_color*/,
760
                          256/*dither_grays*/, 256/*dither_colors*/,
761
                          no_print_page),
762
    /* DeviceN parameters */
763
    { 8,      /* Not used - Bits per color */
764
      DeviceCMYKComponents, /* Names of color model colorants */
765
      4,      /* Number colorants for CMYK */
766
      0,      /* MaxSeparations has not been specified */
767
      -1,     /* PageSpotColors has not been specified */
768
      { 0 },      /* SeparationNames */
769
      0,      /* SeparationOrder names */
770
      {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
771
    },
772
    { true },     /* equivalent_cmyk_color_params */
773
    0/*save_p14dev*/
774
};
775
776
/* GC procedures */
777
static
778
0
ENUM_PTRS_WITH(pdf14_device_enum_ptrs, pdf14_device *pdev)
779
0
{
780
0
    index -= 5;
781
0
    if (index < pdev->devn_params.separations.num_separations)
782
0
        ENUM_RETURN(pdev->devn_params.separations.names[index].data);
783
0
    index -= pdev->devn_params.separations.num_separations;
784
0
    if (index < pdev->devn_params.pdf14_separations.num_separations)
785
0
        ENUM_RETURN(pdev->devn_params.pdf14_separations.names[index].data);
786
0
    return 0;
787
0
}
788
0
case 0: return ENUM_OBJ(pdev->ctx);
789
0
case 1: return ENUM_OBJ(pdev->color_model_stack);
790
0
case 2: return ENUM_OBJ(pdev->smaskcolor);
791
0
case 3: ENUM_RETURN(gx_device_enum_ptr(pdev->target));
792
0
case 4: ENUM_RETURN(gx_device_enum_ptr(pdev->pclist_device));
793
0
ENUM_PTRS_END
794
795
0
static  RELOC_PTRS_WITH(pdf14_device_reloc_ptrs, pdf14_device *pdev)
796
0
{
797
0
    {
798
0
        int i;
799
800
0
        for (i = 0; i < pdev->devn_params.separations.num_separations; ++i) {
801
0
            RELOC_PTR(pdf14_device, devn_params.separations.names[i].data);
802
0
        }
803
0
    }
804
0
    RELOC_VAR(pdev->ctx);
805
0
    RELOC_VAR(pdev->smaskcolor);
806
0
    RELOC_VAR(pdev->color_model_stack);
807
0
    pdev->target = gx_device_reloc_ptr(pdev->target, gcst);
808
0
    pdev->pclist_device = gx_device_reloc_ptr(pdev->pclist_device, gcst);
809
0
}
810
0
RELOC_PTRS_END
811
812
/* ------ Private definitions ------ */
813
814
static void
815
resolve_matte(pdf14_buf *maskbuf, byte *src_data, int src_planestride, int src_rowstride,
816
              int width, int height, cmm_profile_t *src_profile, int deep)
817
0
{
818
0
    if (deep) {
819
0
        int x, y, i;
820
0
        uint16_t *mask_row_ptr  = (uint16_t *)maskbuf->data;
821
0
        uint16_t *src_row_ptr   = (uint16_t *)src_data;
822
0
        uint16_t *mask_tr_fn    = (uint16_t *)maskbuf->transfer_fn;
823
824
0
        src_planestride >>= 1;
825
0
        src_rowstride >>= 1;
826
827
0
        for (y = 0; y < height; y++) {
828
0
            uint16_t *mask_curr_ptr = mask_row_ptr;
829
0
            uint16_t *src_curr_ptr = src_row_ptr;
830
0
            for (x = 0; x < width; x++) {
831
0
                uint16_t idx = *mask_curr_ptr;
832
0
                byte     top = idx>>8;
833
0
                uint16_t a   = mask_tr_fn[top];
834
0
                int      b   = mask_tr_fn[top+1]-a;
835
0
                uint16_t matte_alpha = a + ((0x80 + b*(idx & 0xff))>>8);
836
837
                /* matte's happen rarely enough that we allow ourselves to
838
                 * resort to 64bit here. */
839
0
                if (matte_alpha != 0 && matte_alpha != 0xffff) {
840
0
                    for (i = 0; i < src_profile->num_comps; i++) {
841
0
                        int val = src_curr_ptr[i * src_planestride] - maskbuf->matte[i];
842
0
                        int temp = (((int64_t)val) * 0xffff / matte_alpha) + maskbuf->matte[i];
843
844
                        /* clip */
845
0
                        if (temp > 0xffff)
846
0
                            src_curr_ptr[i * src_planestride] = 0xffff;
847
0
                        else if (temp < 0)
848
0
                            src_curr_ptr[i * src_planestride] = 0;
849
0
                        else
850
0
                            src_curr_ptr[i * src_planestride] = temp;
851
0
                    }
852
0
                }
853
0
                mask_curr_ptr++;
854
0
                src_curr_ptr++;
855
0
            }
856
0
            src_row_ptr += src_rowstride;
857
0
            mask_row_ptr += (maskbuf->rowstride>>1);
858
0
        }
859
0
    } else {
860
0
        int x, y, i;
861
0
        byte *mask_row_ptr  = maskbuf->data;
862
0
        byte *src_row_ptr   = src_data;
863
0
        byte *mask_tr_fn    = maskbuf->transfer_fn;
864
865
0
        for (y = 0; y < height; y++) {
866
0
            byte *mask_curr_ptr = mask_row_ptr;
867
0
            byte *src_curr_ptr = src_row_ptr;
868
0
            for (x = 0; x < width; x++) {
869
0
                byte matte_alpha = mask_tr_fn[*mask_curr_ptr];
870
0
                if (matte_alpha != 0 && matte_alpha != 0xff) {
871
0
                    for (i = 0; i < src_profile->num_comps; i++) {
872
0
                        byte matte = maskbuf->matte[i]>>8;
873
0
                        int val = src_curr_ptr[i * src_planestride] - matte;
874
0
                        int temp = ((((val * 0xff) << 8) / matte_alpha) >> 8) + matte;
875
876
                        /* clip */
877
0
                        if (temp > 0xff)
878
0
                            src_curr_ptr[i * src_planestride] = 0xff;
879
0
                        else if (temp < 0)
880
0
                            src_curr_ptr[i * src_planestride] = 0;
881
0
                        else
882
0
                            src_curr_ptr[i * src_planestride] = temp;
883
0
                    }
884
0
                }
885
0
                mask_curr_ptr++;
886
0
                src_curr_ptr++;
887
0
            }
888
0
            src_row_ptr += src_rowstride;
889
0
            mask_row_ptr += maskbuf->rowstride;
890
0
        }
891
0
    }
892
0
}
893
894
/* Transform of color data and copy noncolor data.  Used in
895
   group pop and during the pdf14 put image calls when the blend color space
896
   is different than the target device color space.  The function will try do
897
   in-place conversion if possible.  If not, it will do an allocation.  The
898
   put_image call needs to know if an allocation was made so that it can adjust
899
   for the fact that we likely don't have a full page any longer and we don't
900
   need to do the offset to our data in the buffer. Bug 700686: If we are in
901
   a softmask that includes a matte entry, then we need to undo the matte
902
   entry here at this time in the image's native color space not the parent
903
   color space.   The endian_swap term here is only set to true if the data
904
   has been baked as BE during the put_image blending operation and we are
905
   on a LE machine.  */
906
static forceinline pdf14_buf*
907
template_transform_color_buffer(gs_gstate *pgs, pdf14_ctx *ctx, gx_device *dev,
908
    pdf14_buf *src_buf, byte *src_data, cmm_profile_t *src_profile,
909
    cmm_profile_t *des_profile, int x0, int y0, int width, int height, bool *did_alloc,
910
    bool has_matte, bool deep, bool endian_swap)
911
4.01k
{
912
4.01k
    gsicc_rendering_param_t rendering_params;
913
4.01k
    gsicc_link_t *icc_link;
914
4.01k
    gsicc_bufferdesc_t src_buff_desc;
915
4.01k
    gsicc_bufferdesc_t des_buff_desc;
916
4.01k
    int src_planestride = src_buf->planestride;
917
4.01k
    int src_rowstride = src_buf->rowstride;
918
4.01k
    int src_n_planes = src_buf->n_planes;
919
4.01k
    int src_n_chan = src_buf->n_chan;
920
4.01k
    int des_planestride = src_planestride;
921
4.01k
    int des_rowstride = src_rowstride;
922
4.01k
    int des_n_planes = src_n_planes;
923
4.01k
    int des_n_chan = src_n_chan;
924
4.01k
    int diff;
925
4.01k
    int k, j;
926
4.01k
    byte *des_data = NULL;
927
4.01k
    pdf14_buf *output = src_buf;
928
4.01k
    pdf14_mask_t *mask_stack;
929
4.01k
    pdf14_buf *maskbuf;
930
4.01k
    int code;
931
932
4.01k
    *did_alloc = false;
933
934
    /* Same profile */
935
4.01k
    if (gsicc_get_hash(src_profile) == gsicc_get_hash(des_profile))
936
0
        return src_buf;
937
938
    /* Define the rendering intent get the link */
939
4.01k
    rendering_params.black_point_comp = gsBLACKPTCOMP_ON;
940
4.01k
    rendering_params.graphics_type_tag = GS_IMAGE_TAG;
941
4.01k
    rendering_params.override_icc = false;
942
4.01k
    rendering_params.preserve_black = gsBKPRESNOTSPECIFIED;
943
4.01k
    rendering_params.rendering_intent = gsRELATIVECOLORIMETRIC;  /* Use relative intent */
944
4.01k
    rendering_params.cmm = gsCMM_DEFAULT;
945
4.01k
    icc_link = gsicc_get_link_profile(pgs, dev, src_profile, des_profile,
946
4.01k
        &rendering_params, pgs->memory, false);
947
4.01k
    if (icc_link == NULL)
948
0
        return NULL;
949
950
    /* If different data sizes, we have to do an allocation */
951
4.01k
    diff = des_profile->num_comps - src_profile->num_comps;
952
4.01k
    if (diff != 0) {
953
3.86k
        byte *src_ptr;
954
3.86k
        byte *des_ptr;
955
956
3.86k
        *did_alloc = true;
957
3.86k
        des_rowstride = ((width + 3) & -4)<<deep;
958
3.86k
        des_planestride = height * des_rowstride;
959
3.86k
        des_n_planes = src_n_planes + diff;
960
3.86k
        des_n_chan = src_n_chan + diff;
961
3.86k
        des_data = gs_alloc_bytes(ctx->memory,
962
3.86k
                                  (size_t)des_planestride * des_n_planes + CAL_SLOP,
963
3.86k
                                  "pdf14_transform_color_buffer");
964
3.86k
        if (des_data == NULL)
965
0
            return NULL;
966
967
        /* Copy over the noncolor planes. May only be a dirty part, so have
968
           to copy row by row */
969
3.86k
        src_ptr = src_data;
970
3.86k
        des_ptr = des_data;
971
46.5k
        for (j = 0; j < height; j++) {
972
85.4k
            for (k = 0; k < (src_n_planes - src_profile->num_comps); k++) {
973
42.7k
                memcpy(des_ptr + des_planestride * (k + des_profile->num_comps),
974
42.7k
                       src_ptr + src_planestride * (k + src_profile->num_comps),
975
42.7k
                       width<<deep);
976
42.7k
            }
977
42.7k
            src_ptr += src_rowstride;
978
42.7k
            des_ptr += des_rowstride;
979
42.7k
        }
980
3.86k
    } else
981
157
        des_data = src_data;
982
983
    /* Set up the buffer descriptors. */
984
4.01k
    gsicc_init_buffer(&src_buff_desc, src_profile->num_comps, 1<<deep, false,
985
4.01k
                      false, true, src_planestride, src_rowstride, height, width);
986
4.01k
    gsicc_init_buffer(&des_buff_desc, des_profile->num_comps, 1<<deep, false,
987
4.01k
                      false, true, des_planestride, des_rowstride, height, width);
988
989
4.01k
    src_buff_desc.endian_swap = endian_swap;
990
4.01k
    des_buff_desc.endian_swap = endian_swap;
991
992
    /* If we have a matte entry, undo the pre-blending now.  Also set pdf14
993
       context to ensure that this is not done again during the group
994
       composition */
995
4.01k
    if (has_matte &&
996
        /* Should always happen, but check for safety */
997
4.01k
        ((mask_stack = ctx->mask_stack) != NULL) &&
998
4.01k
        ((maskbuf = mask_stack->rc_mask->mask_buf) != NULL))
999
0
    {
1000
0
        resolve_matte(maskbuf, src_data, src_planestride, src_rowstride, width, height, src_profile, deep);
1001
0
    }
1002
1003
    /* Transform the data. Since the pdf14 device should be using RGB, CMYK or
1004
       Gray buffers, this transform does not need to worry about the cmap procs
1005
       of the target device. */
1006
4.01k
    code = (icc_link->procs.map_buffer)(dev, icc_link, &src_buff_desc, &des_buff_desc,
1007
4.01k
        src_data, des_data);
1008
4.01k
    gsicc_release_link(icc_link);
1009
4.01k
    if (code < 0)
1010
0
        return NULL;
1011
1012
4.01k
    output->planestride = des_planestride;
1013
4.01k
    output->rowstride = des_rowstride;
1014
4.01k
    output->n_planes = des_n_planes;
1015
4.01k
    output->n_chan = des_n_chan;
1016
    /* If not in-place conversion, then release. */
1017
4.01k
    if (des_data != src_data) {
1018
3.86k
        gs_free_object(ctx->memory, output->data,
1019
3.86k
            "pdf14_transform_color_buffer");
1020
3.86k
        output->data = des_data;
1021
        /* Note, this is needed for case where we did a put image, as the
1022
           resulting transformed buffer may not be a full page. */
1023
3.86k
        output->rect.p.x = x0;
1024
3.86k
        output->rect.p.y = y0;
1025
3.86k
        output->rect.q.x = x0 + width;
1026
3.86k
        output->rect.q.y = y0 + height;
1027
3.86k
    }
1028
4.01k
    return output;
1029
4.01k
}
1030
1031
/* This is a routine to do memset's but with 16 bit values.
1032
 * Note, that we still take bytes, NOT "num values to set".
1033
 * We assume dest is 16 bit aligned. We assume that bytes is
1034
 * a multiple of 2. */
1035
static void gs_memset16(byte *dest_, uint16_t value, int bytes)
1036
0
{
1037
0
    uint16_t *dest = (uint16_t *)(void *)dest_;
1038
0
    uint32_t v;
1039
0
    if (bytes < 0)
1040
0
        return;
1041
0
    if (((intptr_t)dest) & 2) {
1042
0
        *dest++ = value;
1043
0
        bytes--;
1044
0
        if (bytes == 0)
1045
0
            return;
1046
0
    }
1047
0
    v = value | (value<<16);
1048
0
    bytes -= 2;
1049
0
    while (bytes > 0) {
1050
0
        *(uint32_t *)dest = v;
1051
0
        dest += 2;
1052
0
        bytes -= 4;
1053
0
    }
1054
0
    bytes += 2;
1055
0
    if (bytes & 2) {
1056
0
        *dest = value;
1057
0
    }
1058
0
}
1059
1060
static pdf14_buf*
1061
pdf14_transform_color_buffer_no_matte(gs_gstate *pgs, pdf14_ctx *ctx, gx_device *dev,
1062
    pdf14_buf *src_buf, byte *src_data, cmm_profile_t *src_profile,
1063
    cmm_profile_t *des_profile, int x0, int y0, int width, int height, bool *did_alloc,
1064
    bool deep, bool endian_swap)
1065
4.01k
{
1066
4.01k
    if (deep)
1067
0
        return template_transform_color_buffer(pgs, ctx, dev, src_buf, src_data, src_profile,
1068
0
            des_profile, x0, y0, width, height, did_alloc, false, true, endian_swap);
1069
4.01k
    else
1070
4.01k
        return template_transform_color_buffer(pgs, ctx, dev, src_buf, src_data, src_profile,
1071
4.01k
            des_profile, x0, y0, width, height, did_alloc, false, false, endian_swap);
1072
4.01k
}
1073
1074
static pdf14_buf*
1075
pdf14_transform_color_buffer_with_matte(gs_gstate *pgs, pdf14_ctx *ctx, gx_device *dev,
1076
    pdf14_buf *src_buf, byte *src_data, cmm_profile_t *src_profile,
1077
    cmm_profile_t *des_profile, int x0, int y0, int width, int height, bool *did_alloc,
1078
    bool deep, bool endian_swap)
1079
0
{
1080
0
    if (deep)
1081
0
        return template_transform_color_buffer(pgs, ctx, dev, src_buf, src_data, src_profile,
1082
0
            des_profile, x0, y0, width, height, did_alloc, true, true, endian_swap);
1083
0
    else
1084
0
        return template_transform_color_buffer(pgs, ctx, dev, src_buf, src_data, src_profile,
1085
0
            des_profile, x0, y0, width, height, did_alloc, true, false, endian_swap);
1086
0
}
1087
1088
/**
1089
 * pdf14_buf_new: Allocate a new PDF 1.4 buffer.
1090
 * @n_chan: Number of pixel channels including alpha.
1091
 *
1092
 * Return value: Newly allocated buffer, or NULL on failure.
1093
 **/
1094
static  pdf14_buf *
1095
pdf14_buf_new(gs_int_rect *rect, bool has_tags, bool has_alpha_g,
1096
              bool has_shape, bool idle, int n_chan, int num_spots,
1097
              gs_memory_t *memory, bool deep)
1098
834k
{
1099
1100
    /* Note that alpha_g is the alpha for the GROUP */
1101
    /* This is distinct from the alpha that may also exist */
1102
    /* for the objects within the group.  Hence it can introduce */
1103
    /* yet another plane */
1104
1105
834k
    pdf14_buf *result;
1106
834k
    int rowstride = ((rect->q.x - rect->p.x + 3) & -4)<<deep;
1107
834k
    int height = (rect->q.y - rect->p.y);
1108
834k
    int n_planes = n_chan + (has_shape ? 1 : 0) + (has_alpha_g ? 1 : 0) +
1109
834k
                   (has_tags ? 1 : 0);
1110
834k
    int planestride;
1111
834k
    double dsize = (((double) rowstride) * height) * n_planes;
1112
1113
834k
    if (dsize > (double)max_uint)
1114
0
      return NULL;
1115
1116
834k
    result = gs_alloc_struct(memory, pdf14_buf, &st_pdf14_buf,
1117
834k
                             "pdf14_buf_new");
1118
834k
    if (result == NULL)
1119
0
        return result;
1120
1121
834k
    result->memory = memory;
1122
834k
    result->backdrop = NULL;
1123
834k
    result->saved = NULL;
1124
834k
    result->isolated = false;
1125
834k
    result->knockout = false;
1126
834k
    result->has_alpha_g = has_alpha_g;
1127
834k
    result->has_shape = has_shape;
1128
834k
    result->has_tags = has_tags;
1129
834k
    result->rect = *rect;
1130
834k
    result->n_chan = n_chan;
1131
834k
    result->n_planes = n_planes;
1132
834k
    result->rowstride = rowstride;
1133
834k
    result->transfer_fn = NULL;
1134
834k
    result->is_ident = true;
1135
834k
    result->matte_num_comps = 0;
1136
834k
    result->matte = NULL;
1137
834k
    result->mask_stack = NULL;
1138
834k
    result->idle = idle;
1139
834k
    result->mask_id = 0;
1140
834k
    result->num_spots = num_spots;
1141
834k
    result->deep = deep;
1142
834k
    result->page_group = false;
1143
834k
    result->group_color_info = NULL;
1144
834k
    result->group_popped = false;
1145
1146
834k
    if (idle || height <= 0) {
1147
        /* Empty clipping - will skip all drawings. */
1148
369k
        result->planestride = 0;
1149
369k
        result->data = 0;
1150
464k
    } else {
1151
464k
        planestride = rowstride * height;
1152
464k
        result->planestride = planestride;
1153
464k
        result->data = gs_alloc_bytes(memory,
1154
464k
                                      (size_t)planestride * n_planes + CAL_SLOP,
1155
464k
                                      "pdf14_buf_new");
1156
464k
        if (result->data == NULL) {
1157
0
            gs_free_object(memory, result, "pdf14_buf_new");
1158
0
            return NULL;
1159
0
        }
1160
464k
        if (has_alpha_g) {
1161
78.4k
            int alpha_g_plane = n_chan + (has_shape ? 1 : 0);
1162
            /* Memsetting by 0, so this copes with the deep case too */
1163
78.4k
            memset(result->data + alpha_g_plane * planestride, 0, planestride);
1164
78.4k
        }
1165
464k
        if (has_tags) {
1166
0
            int tags_plane = n_chan + (has_shape ? 1 : 0) + (has_alpha_g ? 1 : 0);
1167
            /* Memsetting by 0, so this copes with the deep case too */
1168
0
            memset (result->data + tags_plane * planestride,
1169
0
                    GS_UNTOUCHED_TAG, planestride);
1170
0
        }
1171
464k
    }
1172
    /* Initialize dirty box with an invalid rectangle (the reversed rectangle).
1173
     * Any future drawing will make it valid again, so we won't blend back
1174
     * more than we need. */
1175
834k
    result->dirty.p.x = rect->q.x;
1176
834k
    result->dirty.p.y = rect->q.y;
1177
834k
    result->dirty.q.x = rect->p.x;
1178
834k
    result->dirty.q.y = rect->p.y;
1179
834k
    return result;
1180
834k
}
1181
1182
static  void
1183
pdf14_buf_free(pdf14_buf *buf)
1184
834k
{
1185
834k
    pdf14_group_color_t *group_color_info = buf->group_color_info;
1186
834k
    gs_memory_t *memory = buf->memory;
1187
1188
834k
    if (buf->mask_stack && buf->mask_stack->rc_mask)
1189
834k
        rc_decrement(buf->mask_stack->rc_mask, "pdf14_buf_free");
1190
1191
834k
    gs_free_object(memory, buf->mask_stack, "pdf14_buf_free");
1192
834k
    gs_free_object(memory, buf->transfer_fn, "pdf14_buf_free");
1193
834k
    gs_free_object(memory, buf->matte, "pdf14_buf_free");
1194
834k
    gs_free_object(memory, buf->data, "pdf14_buf_free");
1195
1196
1.66M
    while (group_color_info) {
1197
834k
       if (group_color_info->icc_profile != NULL) {
1198
834k
           gsicc_adjust_profile_rc(group_color_info->icc_profile, -1, "pdf14_buf_free");
1199
834k
       }
1200
834k
       buf->group_color_info = group_color_info->previous;
1201
834k
       gs_free_object(memory, group_color_info, "pdf14_buf_free");
1202
834k
       group_color_info = buf->group_color_info;
1203
834k
    }
1204
1205
834k
    gs_free_object(memory, buf->backdrop, "pdf14_buf_free");
1206
834k
    gs_free_object(memory, buf, "pdf14_buf_free");
1207
834k
}
1208
1209
static void
1210
rc_pdf14_maskbuf_free(gs_memory_t * mem, void *ptr_in, client_name_t cname)
1211
396k
{
1212
    /* Ending the mask buffer. */
1213
396k
    pdf14_rcmask_t *rcmask = (pdf14_rcmask_t * ) ptr_in;
1214
    /* free the pdf14 buffer. */
1215
396k
    if ( rcmask->mask_buf != NULL ){
1216
39.1k
        pdf14_buf_free(rcmask->mask_buf);
1217
39.1k
    }
1218
396k
    gs_free_object(mem, rcmask, "rc_pdf14_maskbuf_free");
1219
396k
}
1220
1221
static  pdf14_rcmask_t *
1222
pdf14_rcmask_new(gs_memory_t *memory)
1223
396k
{
1224
396k
    pdf14_rcmask_t *result;
1225
1226
396k
    result = gs_alloc_struct(memory, pdf14_rcmask_t, &st_pdf14_rcmask,
1227
396k
                             "pdf14_maskbuf_new");
1228
396k
    if (result == NULL)
1229
0
        return NULL;
1230
396k
    rc_init_free(result, memory, 1, rc_pdf14_maskbuf_free);
1231
396k
    result->mask_buf = NULL;
1232
396k
    result->memory = memory;
1233
396k
    return result;
1234
396k
}
1235
1236
static  pdf14_ctx *
1237
pdf14_ctx_new(gx_device *dev, bool deep)
1238
261k
{
1239
261k
    pdf14_ctx *result;
1240
261k
    gs_memory_t *memory = dev->memory->stable_memory;
1241
1242
261k
    result = gs_alloc_struct(memory, pdf14_ctx, &st_pdf14_ctx, "pdf14_ctx_new");
1243
261k
    if (result == NULL)
1244
0
        return result;
1245
261k
    result->stack = NULL;
1246
261k
    result->mask_stack = pdf14_mask_element_new(memory);
1247
261k
    result->mask_stack->rc_mask = pdf14_rcmask_new(memory);
1248
261k
    result->memory = memory;
1249
261k
    result->smask_depth = 0;
1250
261k
    result->smask_blend = false;
1251
261k
    result->deep = deep;
1252
261k
    result->base_color = NULL;
1253
261k
    return result;
1254
261k
}
1255
1256
static  void
1257
pdf14_ctx_free(pdf14_ctx *ctx)
1258
261k
{
1259
261k
    pdf14_buf *buf, *next;
1260
1261
261k
    if (ctx->base_color) {
1262
121k
       gsicc_adjust_profile_rc(ctx->base_color->icc_profile, -1, "pdf14_ctx_free");
1263
121k
        gs_free_object(ctx->memory, ctx->base_color, "pdf14_ctx_free");
1264
121k
    }
1265
261k
    if (ctx->mask_stack) {
1266
        /* A mask was created but was not used in this band. */
1267
102k
        rc_decrement(ctx->mask_stack->rc_mask, "pdf14_ctx_free");
1268
102k
        gs_free_object(ctx->memory, ctx->mask_stack, "pdf14_ctx_free");
1269
102k
    }
1270
495k
    for (buf = ctx->stack; buf != NULL; buf = next) {
1271
233k
        next = buf->saved;
1272
233k
        pdf14_buf_free(buf);
1273
233k
    }
1274
261k
    gs_free_object (ctx->memory, ctx, "pdf14_ctx_free");
1275
261k
}
1276
1277
/**
1278
 * pdf14_find_backdrop_buf: Find backdrop buffer.
1279
 *
1280
 * Return value: Backdrop buffer for current group operation, or NULL
1281
 * if backdrop is fully transparent.
1282
 **/
1283
static  pdf14_buf *
1284
pdf14_find_backdrop_buf(pdf14_ctx *ctx, bool *is_backdrop)
1285
239k
{
1286
    /* Our new buffer is buf */
1287
239k
    pdf14_buf *buf = ctx->stack;
1288
1289
239k
    *is_backdrop = false;
1290
1291
239k
    if (buf != NULL) {
1292
        /* If the new buffer is isolated there is no backdrop */
1293
239k
        if (buf->isolated) return NULL;
1294
1295
        /* If the previous buffer is a knockout group
1296
           then we need to use its backdrop as the backdrop. If
1297
           it was isolated then that back drop was NULL */
1298
78.4k
        if (buf->saved != NULL && buf->saved->knockout) {
1299
            /* Per the spec, if we have a non-isolated group
1300
               in a knockout group the non-isolated group
1301
               uses the backdrop of its parent group (the knockout group)
1302
               as its own backdrop.  The non-isolated group must
1303
               go through the standard re-composition operation
1304
               to avoid the double application of the backdrop */
1305
41
            *is_backdrop = true;
1306
41
            return buf->saved;
1307
41
        }
1308
        /* This should be the non-isolated case where its parent is
1309
           not a knockout */
1310
78.4k
        if (buf->saved != NULL) {
1311
78.4k
            return buf->saved;
1312
78.4k
        }
1313
78.4k
    }
1314
0
    return NULL;
1315
239k
}
1316
1317
static pdf14_group_color_t*
1318
pdf14_make_base_group_color(gx_device* dev)
1319
121k
{
1320
121k
    pdf14_device* pdev = (pdf14_device*)dev;
1321
121k
    pdf14_group_color_t* group_color;
1322
121k
    bool deep = pdev->ctx->deep;
1323
1324
121k
    if_debug0m('v', dev->memory, "[v]pdf14_make_base_group_color\n");
1325
1326
121k
    group_color = gs_alloc_struct(pdev->ctx->memory,
1327
121k
        pdf14_group_color_t, &st_pdf14_clr,
1328
121k
        "pdf14_make_base_group_color");
1329
1330
121k
    if (group_color == NULL)
1331
0
        return NULL;
1332
121k
    memset(group_color, 0, sizeof(pdf14_group_color_t));
1333
1334
121k
    group_color->blend_procs = pdev->blend_procs;
1335
121k
    group_color->polarity = pdev->color_info.polarity;
1336
121k
    group_color->num_components = pdev->color_info.num_components;
1337
121k
    group_color->isadditive = pdev->ctx->additive;
1338
121k
    group_color->unpack_procs = pdev->pdf14_procs;
1339
121k
    group_color->max_color = pdev->color_info.max_color = deep ? 65535 : 255;
1340
121k
    group_color->max_gray = pdev->color_info.max_gray = deep ? 65535 : 255;
1341
121k
    group_color->depth = pdev->color_info.depth;
1342
121k
    group_color->decode = dev_proc(pdev, decode_color);
1343
121k
    group_color->encode = dev_proc(pdev, encode_color);
1344
121k
    group_color->group_color_mapping_procs = dev_proc(pdev, get_color_mapping_procs);
1345
121k
    group_color->group_color_comp_index = dev_proc(pdev, get_color_comp_index);
1346
121k
    memcpy(&(group_color->comp_bits), &(pdev->color_info.comp_bits),
1347
121k
        GX_DEVICE_COLOR_MAX_COMPONENTS);
1348
121k
    memcpy(&(group_color->comp_shift), &(pdev->color_info.comp_shift),
1349
121k
        GX_DEVICE_COLOR_MAX_COMPONENTS);
1350
121k
    group_color->get_cmap_procs = pdf14_get_cmap_procs;
1351
121k
    group_color->icc_profile =
1352
121k
        pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE];
1353
121k
    gsicc_adjust_profile_rc(group_color->icc_profile, 1, "pdf14_make_base_group_color");
1354
1355
121k
    return group_color;
1356
121k
}
1357
1358
/* This wil create the first buffer when we have
1359
   either the first drawing operation or transparency
1360
   group push.  At that time, the color space in which
1361
   we are going to be doing the alpha blend will be known. */
1362
static int
1363
pdf14_initialize_ctx(gx_device* dev, int n_chan, bool additive, const gs_gstate* pgs)
1364
155M
{
1365
155M
    pdf14_device* pdev = (pdf14_device*)dev;
1366
155M
    bool has_tags = device_encodes_tags(dev);
1367
155M
    int num_spots = pdev->ctx->num_spots;
1368
155M
    pdf14_buf* buf;
1369
155M
    gs_memory_t* memory = dev->memory->stable_memory;
1370
1371
    /* Check for a blank idle group as a base group */
1372
155M
    if (pdev->ctx->stack != NULL && pdev->ctx->stack->group_popped &&
1373
155M
        pdev->ctx->stack->idle) {
1374
0
        pdf14_buf_free(pdev->ctx->stack);
1375
0
        pdev->ctx->stack = NULL;
1376
0
    }
1377
1378
155M
    if (pdev->ctx->stack != NULL)
1379
155M
        return 0;
1380
1381
155M
    if_debug2m('v', dev->memory, "[v]pdf14_initialize_ctx: width = %d, height = %d\n",
1382
135k
        dev->width, dev->height);
1383
1384
135k
    buf = pdf14_buf_new(&(pdev->ctx->rect), has_tags, false, false, false, n_chan + 1,
1385
135k
        num_spots, memory, pdev->ctx->deep);
1386
135k
    if (buf == NULL) {
1387
0
        return gs_error_VMerror;
1388
0
    }
1389
135k
    if_debug5m('v', memory,
1390
135k
        "[v]base buf: %d x %d, %d color channels, %d planes, deep=%d\n",
1391
135k
        buf->rect.q.x, buf->rect.q.y, buf->n_chan, buf->n_planes, pdev->ctx->deep);
1392
1393
    /* This check is not really needed */
1394
135k
    if (buf->data != NULL) {
1395
        /* Memsetting by 0, so this copes with the deep case too */
1396
135k
        if (buf->has_tags) {
1397
0
            memset(buf->data, 0, (size_t)buf->planestride * (buf->n_planes - 1));
1398
0
        }
1399
135k
        else {
1400
135k
            memset(buf->data, 0, (size_t)buf->planestride * buf->n_planes);
1401
135k
        }
1402
135k
    }
1403
135k
    buf->saved = NULL;
1404
135k
    pdev->ctx->stack = buf;
1405
135k
    pdev->ctx->n_chan = n_chan;
1406
135k
    pdev->ctx->additive = additive;
1407
1408
    /* Every buffer needs group color information including the base
1409
       one that is created for when we have no group */
1410
135k
    buf->group_color_info = gs_alloc_struct(pdev->memory->stable_memory,
1411
135k
            pdf14_group_color_t, &st_pdf14_clr, "pdf14_initialize_ctx");
1412
135k
    if (buf->group_color_info == NULL)
1413
0
        return gs_error_VMerror;
1414
1415
135k
    if (pgs != NULL)
1416
69.9k
        buf->group_color_info->get_cmap_procs = pgs->get_cmap_procs;
1417
65.6k
    else
1418
65.6k
        buf->group_color_info->get_cmap_procs = pdf14_get_cmap_procs;
1419
1420
135k
    buf->group_color_info->group_color_mapping_procs =
1421
135k
        dev_proc(pdev, get_color_mapping_procs);
1422
135k
    buf->group_color_info->group_color_comp_index =
1423
135k
        dev_proc(pdev, get_color_comp_index);
1424
135k
    buf->group_color_info->blend_procs = pdev->blend_procs;
1425
135k
    buf->group_color_info->polarity = pdev->color_info.polarity;
1426
135k
    buf->group_color_info->num_components = pdev->color_info.num_components;
1427
135k
    buf->group_color_info->isadditive = pdev->ctx->additive;
1428
135k
    buf->group_color_info->unpack_procs = pdev->pdf14_procs;
1429
135k
    buf->group_color_info->depth = pdev->color_info.depth;
1430
135k
    buf->group_color_info->max_color = pdev->color_info.max_color;
1431
135k
    buf->group_color_info->max_gray = pdev->color_info.max_gray;
1432
135k
    buf->group_color_info->encode = dev_proc(pdev, encode_color);
1433
135k
    buf->group_color_info->decode = dev_proc(pdev, decode_color);
1434
135k
    memcpy(&(buf->group_color_info->comp_bits), &(pdev->color_info.comp_bits),
1435
135k
        GX_DEVICE_COLOR_MAX_COMPONENTS);
1436
135k
    memcpy(&(buf->group_color_info->comp_shift), &(pdev->color_info.comp_shift),
1437
135k
        GX_DEVICE_COLOR_MAX_COMPONENTS);
1438
135k
    buf->group_color_info->previous = NULL;  /* used during clist writing */
1439
135k
    buf->group_color_info->icc_profile =
1440
135k
        pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE];
1441
135k
    if (buf->group_color_info->icc_profile != NULL)
1442
135k
        gsicc_adjust_profile_rc(buf->group_color_info->icc_profile, 1, "pdf14_initialize_ctx");
1443
1444
135k
    return 0;
1445
135k
}
1446
1447
static pdf14_group_color_t*
1448
pdf14_clone_group_color_info(gx_device* pdev, pdf14_group_color_t* src)
1449
13.0k
{
1450
13.0k
    pdf14_group_color_t* des = gs_alloc_struct(pdev->memory->stable_memory,
1451
13.0k
        pdf14_group_color_t, &st_pdf14_clr, "pdf14_clone_group_color_info");
1452
13.0k
    if (des == NULL)
1453
0
        return NULL;
1454
1455
13.0k
    memcpy(des, src, sizeof(pdf14_group_color_t));
1456
13.0k
    if (des->icc_profile != NULL)
1457
13.0k
        gsicc_adjust_profile_rc(des->icc_profile, 1, "pdf14_clone_group_color_info");
1458
13.0k
    des->previous = NULL;  /* used during clist writing for state stack */
1459
1460
13.0k
    return des;
1461
13.0k
}
1462
1463
static  int
1464
pdf14_push_transparency_group(pdf14_ctx *ctx, gs_int_rect *rect, bool isolated,
1465
                              bool knockout, uint16_t alpha, uint16_t shape, uint16_t opacity,
1466
                              gs_blend_mode_t blend_mode, bool idle, uint mask_id,
1467
                              int numcomps, bool cm_back_drop, bool shade_group,
1468
                              cmm_profile_t *group_profile, cmm_profile_t *tos_profile,
1469
                              pdf14_group_color_t* group_color, gs_gstate *pgs,
1470
                              gx_device *dev)
1471
561k
{
1472
561k
    pdf14_buf *tos = ctx->stack;
1473
561k
    pdf14_buf *buf, * pdf14_backdrop;
1474
561k
    bool has_shape = false;
1475
561k
    bool is_backdrop;
1476
561k
    int num_spots;
1477
1478
561k
    if_debug1m('v', ctx->memory,
1479
561k
               "[v]pdf14_push_transparency_group, idle = %d\n", idle);
1480
1481
561k
    if (tos != NULL)
1482
463k
        has_shape = tos->has_shape || tos->knockout;
1483
1484
561k
    if (ctx->smask_depth > 0)
1485
959
        num_spots = 0;
1486
560k
    else
1487
560k
        num_spots = ctx->num_spots;
1488
1489
1490
561k
    buf = pdf14_buf_new(rect, ctx->has_tags, !isolated, has_shape, idle, numcomps + 1,
1491
561k
                        num_spots, ctx->memory, ctx->deep);
1492
561k
    if (buf == NULL)
1493
0
        return_error(gs_error_VMerror);
1494
1495
561k
    if_debug4m('v', ctx->memory,
1496
561k
        "[v]base buf: %d x %d, %d color channels, %d planes\n",
1497
561k
        buf->rect.q.x, buf->rect.q.y, buf->n_chan, buf->n_planes);
1498
561k
    buf->isolated = isolated;
1499
561k
    buf->knockout = knockout;
1500
561k
    buf->alpha = alpha;
1501
561k
    buf->shape = shape;
1502
561k
    buf->opacity = opacity;
1503
561k
    buf->blend_mode = blend_mode;
1504
561k
    buf->mask_id = mask_id;
1505
561k
    buf->mask_stack = ctx->mask_stack; /* Save because the group rendering may
1506
                                          set up another (nested) mask. */
1507
561k
    ctx->mask_stack = NULL; /* Clean the mask field for rendering this group.
1508
                            See pdf14_pop_transparency_group how to handle it. */
1509
561k
    buf->saved = tos;
1510
561k
    buf->group_color_info = group_color;
1511
1512
561k
    if (tos == NULL)
1513
98.3k
        buf->page_group = true;
1514
1515
561k
    ctx->stack = buf;
1516
561k
    if (buf->data == NULL)
1517
322k
        return 0;
1518
239k
    if (idle)
1519
0
        return 0;
1520
239k
    pdf14_backdrop = pdf14_find_backdrop_buf(ctx, &is_backdrop);
1521
1522
    /* Initializes buf->data with the backdrop or as opaque */
1523
239k
    if (pdf14_backdrop == NULL || (is_backdrop && pdf14_backdrop->backdrop == NULL)) {
1524
        /* Note, don't clear out tags set by pdf14_buf_new == GS_UNKNOWN_TAG */
1525
        /* Memsetting by 0, so this copes with the deep case too */
1526
160k
        memset(buf->data, 0, (size_t)buf->planestride *
1527
160k
                                          (buf->n_chan +
1528
160k
                                           (buf->has_shape ? 1 : 0) +
1529
160k
                                           (buf->has_alpha_g ? 1 : 0)));
1530
160k
    } else {
1531
78.4k
        if (!cm_back_drop) {
1532
78.4k
            pdf14_preserve_backdrop(buf, pdf14_backdrop, is_backdrop
1533
#if RAW_DUMP
1534
                                    , ctx->memory
1535
#endif
1536
78.4k
                                    );
1537
78.4k
        } else {
1538
            /* We must have an non-isolated group with a mismatch in color spaces.
1539
                In this case, we can't just copy the buffer but must CM it */
1540
0
            pdf14_preserve_backdrop_cm(buf, group_profile, pdf14_backdrop, tos_profile,
1541
0
                                        ctx->memory, pgs, dev, is_backdrop);
1542
0
        }
1543
78.4k
    }
1544
1545
    /* If our new group is a non-isolated knockout group, we have to maintain
1546
       a copy of the backdrop in case we are drawing nonisolated groups on top of the
1547
       knockout group. They have to always blend with the groups backdrop
1548
       not what is currently drawn in the group. Selection of the backdrop
1549
       depends upon the properties of the parent group. For example, if
1550
       the parent itself is a knockout group we actually
1551
       need to blend with its backdrop. This could be NULL if the parent was
1552
       an isolated knockout group. */
1553
239k
    if (buf->knockout && pdf14_backdrop != NULL) {
1554
4.90k
        buf->backdrop = gs_alloc_bytes(ctx->memory,
1555
4.90k
                                       (size_t)buf->planestride * buf->n_planes + CAL_SLOP,
1556
4.90k
                                       "pdf14_push_transparency_group");
1557
4.90k
        if (buf->backdrop == NULL) {
1558
0
            return gs_throw(gs_error_VMerror, "Knockout backdrop allocation failed");
1559
0
        }
1560
1561
4.90k
        memcpy(buf->backdrop, buf->data,
1562
4.90k
               (size_t)buf->planestride * buf->n_planes);
1563
1564
#if RAW_DUMP
1565
        /* Dump the current buffer to see what we have. */
1566
        dump_raw_buffer(ctx->memory,
1567
            ctx->stack->rect.q.y - ctx->stack->rect.p.y,
1568
            ctx->stack->rowstride >> buf->deep, buf->n_planes,
1569
            ctx->stack->planestride, ctx->stack->rowstride,
1570
            "KnockoutBackDrop", buf->backdrop, buf->deep);
1571
        global_index++;
1572
#endif
1573
4.90k
    }
1574
#if RAW_DUMP
1575
    /* Dump the current buffer to see what we have. */
1576
    dump_raw_buffer(ctx->memory,
1577
                    ctx->stack->rect.q.y-ctx->stack->rect.p.y,
1578
                    ctx->stack->rowstride>>buf->deep, ctx->stack->n_planes,
1579
                    ctx->stack->planestride, ctx->stack->rowstride,
1580
                    "TransGroupPush", ctx->stack->data, buf->deep);
1581
    global_index++;
1582
#endif
1583
239k
    return 0;
1584
239k
}
1585
1586
static  int
1587
pdf14_pop_transparency_group(gs_gstate *pgs, pdf14_ctx *ctx,
1588
    const pdf14_nonseparable_blending_procs_t * pblend_procs,
1589
    int tos_num_color_comp, cmm_profile_t *curr_icc_profile, gx_device *dev)
1590
561k
{
1591
561k
    pdf14_buf *tos = ctx->stack;
1592
561k
    pdf14_buf *nos = tos->saved;
1593
561k
    pdf14_mask_t *mask_stack = tos->mask_stack;
1594
561k
    pdf14_buf *maskbuf;
1595
561k
    int x0, x1, y0, y1;
1596
561k
    int nos_num_color_comp;
1597
561k
    bool no_icc_match;
1598
561k
    pdf14_device *pdev = (pdf14_device *)dev;
1599
561k
    bool overprint = pdev->overprint;
1600
561k
    gx_color_index drawn_comps = pdev->drawn_comps_stroke | pdev->drawn_comps_fill;
1601
561k
    bool has_matte = false;
1602
561k
    int code = 0;
1603
1604
#ifdef DEBUG
1605
    pdf14_debug_mask_stack_state(ctx);
1606
#endif
1607
561k
    if (mask_stack == NULL) {
1608
282k
        maskbuf = NULL;
1609
282k
    }
1610
278k
    else {
1611
278k
        maskbuf = mask_stack->rc_mask->mask_buf;
1612
278k
    }
1613
1614
561k
    if (maskbuf != NULL && maskbuf->matte != NULL)
1615
360
        has_matte = true;
1616
1617
    /* Check if this is our last buffer, if yes, there is nothing to
1618
       compose to.  Keep this buffer until we have the put image.
1619
       If we have another group push, this group must be destroyed.
1620
       This only occurs sometimes when at clist creation time
1621
       push_shfill_group occured and nothing was drawn in this group.
1622
       There is also the complication if we have a softmask.  There
1623
       are two approaches to this problem.  Apply the softmask during
1624
       the put image or handle it now.  I choose the later as the
1625
       put_image code is already way to complicated. */
1626
561k
    if (nos == NULL && maskbuf == NULL) {
1627
98.1k
        tos->group_popped = true;
1628
98.1k
        return 0;
1629
98.1k
    }
1630
1631
    /* Here is the case with the soft mask.  Go ahead and create a new
1632
       target buffer (nos) with the same color information etc, but blank
1633
       and go ahead and do the blend with the softmask so that it gets applied. */
1634
463k
    if (nos == NULL && maskbuf != NULL) {
1635
0
        nos = pdf14_buf_new(&(tos->rect), ctx->has_tags, !tos->isolated, tos->has_shape,
1636
0
            tos->idle, tos->n_chan, tos->num_spots, ctx->memory, ctx->deep);
1637
0
        if (nos == NULL) {
1638
0
            code = gs_error_VMerror;
1639
0
            goto exit;
1640
0
        }
1641
1642
0
        if_debug4m('v', ctx->memory,
1643
0
            "[v] special buffer for softmask application: %d x %d, %d color channels, %d planes\n",
1644
0
            nos->rect.q.x, nos->rect.q.y, nos->n_chan, nos->n_planes);
1645
1646
0
        nos->dirty = tos->dirty;
1647
0
        nos->isolated = tos->isolated;
1648
0
        nos->knockout = tos->knockout;
1649
0
        nos->alpha = 65535;
1650
0
        nos->shape = 65535;
1651
0
        nos->opacity = 65535;
1652
0
        nos->blend_mode = tos->blend_mode;
1653
0
        nos->mask_id = tos->mask_id;
1654
0
        nos->group_color_info = pdf14_clone_group_color_info(dev, tos->group_color_info);
1655
1656
0
        if (nos->data != NULL)
1657
0
            memset(nos->data, 0,
1658
0
                   (size_t)nos->planestride *
1659
0
                                          (nos->n_chan +
1660
0
                                           (nos->has_shape ? 1 : 0) +
1661
0
                                           (nos->has_alpha_g ? 1 : 0)));
1662
0
    }
1663
1664
    /* Before we get started, lets see if we have somehow gotten into
1665
       what should be an impossible situation where the group color
1666
       information does not match the buffer color information. This
1667
       can occur is there were memory issues that have perhaps blown
1668
       away information, or in the example of Bug 705197 the PDF interpreter
1669
       reuses a pattern during a circular reference causing an aliasing
1670
       of two nested patterns, one of which has a softmask. The change in
1671
       the buffer size of the inner one blows away the buffer of the
1672
       outer one leading to a mismatch of color spaces. Here
1673
       we can at least catch the case when the color space sizes have
1674
       changed and avoid buffer over-runs that would occur when we try
1675
       to do the group composition */
1676
463k
    if (nos->n_chan - 1 != nos->group_color_info->num_components ||
1677
463k
        tos->n_chan - 1 != tos_num_color_comp)
1678
0
        return_error(gs_error_Fatal);
1679
1680
463k
    nos_num_color_comp = nos->group_color_info->num_components - tos->num_spots;
1681
463k
    tos_num_color_comp = tos_num_color_comp - tos->num_spots;
1682
1683
    /* Sanitise the dirty rectangles, in case some of the drawing routines
1684
     * have made them overly large. */
1685
463k
    rect_intersect(tos->dirty, tos->rect);
1686
463k
    rect_intersect(nos->dirty, nos->rect);
1687
    /* dirty = the marked bbox. rect = the entire bounds of the buffer. */
1688
    /* Everything marked on tos that fits onto nos needs to be merged down. */
1689
463k
    y0 = max(tos->dirty.p.y, nos->rect.p.y);
1690
463k
    y1 = min(tos->dirty.q.y, nos->rect.q.y);
1691
463k
    x0 = max(tos->dirty.p.x, nos->rect.p.x);
1692
463k
    x1 = min(tos->dirty.q.x, nos->rect.q.x);
1693
463k
    if (ctx->mask_stack) {
1694
        /* This can occur when we have a situation where we are ending out of
1695
           a group that has internal to it a soft mask and another group.
1696
           The soft mask left over from the previous trans group pop is put
1697
           into ctx->masbuf, since it is still active if another trans group
1698
           push occurs to use it.  If one does not occur, but instead we find
1699
           ourselves popping from a parent group, then this softmask is no
1700
           longer needed.  We will rc_decrement and set it to NULL. */
1701
117
        rc_decrement(ctx->mask_stack->rc_mask, "pdf14_pop_transparency_group");
1702
117
        if (ctx->mask_stack->rc_mask == NULL ){
1703
117
            gs_free_object(ctx->memory, ctx->mask_stack, "pdf14_pop_transparency_group");
1704
117
        }
1705
117
        ctx->mask_stack = NULL;
1706
117
    }
1707
463k
    ctx->mask_stack = mask_stack;  /* Restore the mask saved by pdf14_push_transparency_group. */
1708
463k
    tos->mask_stack = NULL;        /* Clean the pointer sinse the mask ownership is now passed to ctx. */
1709
463k
    if (tos->idle)
1710
317k
        goto exit;
1711
145k
    if (maskbuf != NULL && maskbuf->data == NULL && maskbuf->alpha == 255)
1712
0
        goto exit;
1713
1714
#if RAW_DUMP
1715
    /* Dump the current buffer to see what we have. */
1716
    dump_raw_buffer(ctx->memory,
1717
                    ctx->stack->rect.q.y-ctx->stack->rect.p.y,
1718
                    ctx->stack->rowstride>>ctx->stack->deep, ctx->stack->n_planes,
1719
                    ctx->stack->planestride, ctx->stack->rowstride,
1720
                    "aaTrans_Group_Pop", ctx->stack->data, ctx->stack->deep);
1721
    global_index++;
1722
#endif
1723
/* Note currently if a pattern space has transparency, the ICC profile is not used
1724
   for blending purposes.  Instead we rely upon the gray, rgb, or cmyk parent space.
1725
   This is partially due to the fact that pdf14_pop_transparency_group and
1726
   pdf14_push_transparnecy_group have no real ICC interaction and those are the
1727
   operations called in the tile transparency code.  Instead we may want to
1728
   look at pdf14_begin_transparency_group and pdf14_end_transparency group which
1729
   is where all the ICC information is handled.  We will return to look at that later */
1730
145k
    if (nos->group_color_info->icc_profile != NULL) {
1731
145k
        no_icc_match = !gsicc_profiles_equal(nos->group_color_info->icc_profile, curr_icc_profile);
1732
145k
    } else {
1733
        /* Let the other tests make the decision if we need to transform */
1734
0
        no_icc_match = false;
1735
0
    }
1736
    /* If the color spaces are different and we actually did do a swap of
1737
       the procs for color */
1738
145k
    if ((nos->group_color_info->group_color_mapping_procs != NULL &&
1739
145k
        nos_num_color_comp != tos_num_color_comp) || no_icc_match) {
1740
1.34k
        if (x0 < x1 && y0 < y1) {
1741
1.30k
            pdf14_buf *result;
1742
1.30k
            bool did_alloc; /* We don't care here */
1743
1744
1.30k
            if (has_matte) {
1745
0
                result = pdf14_transform_color_buffer_with_matte(pgs, ctx, dev,
1746
0
                    tos, tos->data, curr_icc_profile, nos->group_color_info->icc_profile,
1747
0
                    tos->rect.p.x, tos->rect.p.y, tos->rect.q.x - tos->rect.p.x,
1748
0
                    tos->rect.q.y - tos->rect.p.y, &did_alloc, tos->deep, false);
1749
0
                has_matte = false;
1750
1.30k
            } else {
1751
1.30k
                result = pdf14_transform_color_buffer_no_matte(pgs, ctx, dev,
1752
1.30k
                    tos, tos->data, curr_icc_profile, nos->group_color_info->icc_profile,
1753
1.30k
                    tos->rect.p.x, tos->rect.p.y, tos->rect.q.x - tos->rect.p.x,
1754
1.30k
                    tos->rect.q.y - tos->rect.p.y, &did_alloc, tos->deep, false);
1755
1.30k
            }
1756
1.30k
            if (result == NULL) {
1757
                /* Clean up and return error code */
1758
0
                code = gs_error_unknownerror;
1759
0
                goto exit;
1760
0
            }
1761
1762
#if RAW_DUMP
1763
            /* Dump the current buffer to see what we have. */
1764
            dump_raw_buffer(ctx->memory,
1765
                            ctx->stack->rect.q.y-ctx->stack->rect.p.y,
1766
                            ctx->stack->rowstride>>ctx->stack->deep, ctx->stack->n_chan,
1767
                            ctx->stack->planestride, ctx->stack->rowstride,
1768
                            "aCMTrans_Group_ColorConv", ctx->stack->data,
1769
                            ctx->stack->deep);
1770
#endif
1771
             /* compose. never do overprint in this case */
1772
1.30k
            pdf14_compose_group(tos, nos, maskbuf, x0, x1, y0, y1, nos->n_chan,
1773
1.30k
                 nos->group_color_info->isadditive,
1774
1.30k
                 nos->group_color_info->blend_procs,
1775
1.30k
                 has_matte, false, drawn_comps, ctx->memory, dev);
1776
1.30k
        }
1777
144k
    } else {
1778
        /* Group color spaces are the same.  No color conversions needed */
1779
144k
        if (x0 < x1 && y0 < y1)
1780
89.6k
            pdf14_compose_group(tos, nos, maskbuf, x0, x1, y0, y1, nos->n_chan,
1781
89.6k
                                ctx->additive, pblend_procs, has_matte, overprint,
1782
89.6k
                                drawn_comps, ctx->memory, dev);
1783
144k
    }
1784
463k
exit:
1785
463k
    ctx->stack = nos;
1786
    /* We want to detect the cases where we have luminosity soft masks embedded
1787
       within one another.  The "alpha" channel really needs to be merged into
1788
       the luminosity channel in this case.  This will occur during the mask pop */
1789
463k
    if (ctx->smask_depth > 0 && maskbuf != NULL) {
1790
        /* Set the trigger so that we will blend if not alpha. Since
1791
           we have softmasks embedded in softmasks */
1792
363
        ctx->smask_blend = true;
1793
363
    }
1794
463k
    if_debug1m('v', ctx->memory, "[v]pop buf, idle=%d\n", tos->idle);
1795
463k
    pdf14_buf_free(tos);
1796
463k
    if (code < 0)
1797
0
        return_error(code);
1798
463k
    return 0;
1799
463k
}
1800
1801
/*
1802
 * Create a transparency mask that will be used as the mask for
1803
 * the next transparency group that is created afterwards.
1804
 * The sequence of calls is:
1805
 * push_mask, draw the mask, pop_mask, push_group, draw the group, pop_group
1806
 */
1807
static  int
1808
pdf14_push_transparency_mask(pdf14_ctx *ctx, gs_int_rect *rect, uint16_t bg_alpha,
1809
                             byte *transfer_fn, bool is_ident, bool idle,
1810
                             bool replacing, uint mask_id,
1811
                             gs_transparency_mask_subtype_t subtype,
1812
                             int numcomps, int Background_components,
1813
                             const float Background[], int Matte_components,
1814
                             const float Matte[], const float GrayBackground,
1815
                             pdf14_group_color_t* group_color)
1816
137k
{
1817
137k
    pdf14_buf *buf;
1818
137k
    int i;
1819
1820
137k
    if_debug2m('v', ctx->memory,
1821
137k
               "[v]pdf14_push_transparency_mask, idle=%d, replacing=%d\n",
1822
137k
               idle, replacing);
1823
137k
    ctx->smask_depth += 1;
1824
1825
137k
    if (ctx->stack == NULL) {
1826
0
        return_error(gs_error_VMerror);
1827
0
    }
1828
1829
    /* An optimization to consider is that if the SubType is Alpha
1830
       then we really should only be allocating the alpha band and
1831
       only draw with that channel.  Current architecture makes that
1832
       a bit tricky.  We need to create this based upon the size of
1833
       the color space + an alpha channel. NOT the device size
1834
       or the previous ctx size */
1835
    /* A mask doesn't worry about tags */
1836
137k
    buf = pdf14_buf_new(rect, false, false, false, idle, numcomps + 1, 0,
1837
137k
                        ctx->memory, ctx->deep);
1838
137k
    if (buf == NULL)
1839
0
        return_error(gs_error_VMerror);
1840
137k
    buf->alpha = bg_alpha;
1841
137k
    buf->is_ident = is_ident;
1842
    /* fill in, but these values aren't really used */
1843
137k
    buf->isolated = true;
1844
137k
    buf->knockout = false;
1845
137k
    buf->shape = 0xffff;
1846
137k
    buf->blend_mode = BLEND_MODE_Normal;
1847
137k
    buf->transfer_fn = transfer_fn;
1848
137k
    buf->matte_num_comps = Matte_components;
1849
137k
    buf->group_color_info = group_color;
1850
1851
137k
    if (Matte_components) {
1852
360
        buf->matte = (uint16_t *)gs_alloc_bytes(ctx->memory, Matte_components * sizeof(uint16_t) + CAL_SLOP,
1853
360
                                                "pdf14_push_transparency_mask");
1854
360
        if (buf->matte == NULL)
1855
0
            return_error(gs_error_VMerror);
1856
1.44k
        for (i = 0; i < Matte_components; i++) {
1857
1.08k
            buf->matte[i] = (uint16_t) floor(Matte[i] * 65535.0 + 0.5);
1858
1.08k
        }
1859
360
    }
1860
137k
    buf->mask_id = mask_id;
1861
    /* If replacing=false, we start the mask for an image with SMask.
1862
       In this case the image's SMask temporary replaces the
1863
       mask of the containing group. Save the containing droup's mask
1864
       in buf->mask_stack */
1865
137k
    buf->mask_stack = ctx->mask_stack;
1866
137k
    if (buf->mask_stack){
1867
28.9k
        rc_increment(buf->mask_stack->rc_mask);
1868
28.9k
    }
1869
#if RAW_DUMP
1870
    /* Dump the current buffer to see what we have. */
1871
    if (ctx->stack->planestride > 0 ){
1872
        dump_raw_buffer(ctx->memory,
1873
                        ctx->stack->rect.q.y-ctx->stack->rect.p.y,
1874
                        ctx->stack->rowstride>>ctx->stack->deep, ctx->stack->n_planes,
1875
                        ctx->stack->planestride, ctx->stack->rowstride,
1876
                        "Raw_Buf_PreSmask", ctx->stack->data, ctx->stack->deep);
1877
        global_index++;
1878
    }
1879
#endif
1880
137k
    buf->saved = ctx->stack;
1881
137k
    ctx->stack = buf;
1882
    /* Soft Mask related information so we know how to
1883
       compute luminosity when we pop the soft mask */
1884
137k
    buf->SMask_SubType = subtype;
1885
137k
    if (buf->data != NULL) {
1886
        /* We need to initialize it to the BC if it existed */
1887
        /* According to the spec, the CS has to be the same */
1888
        /* If the back ground component is black, then don't bother
1889
           with this.  Since we are forcing the rendering to gray
1890
           earlier now, go ahead and just use the GrayBackGround color
1891
           directly. */
1892
89.6k
        if ( Background_components && GrayBackground != 0.0 ) {
1893
36
            if (buf->deep) {
1894
0
                uint16_t gray = (uint16_t) (65535.0 * GrayBackground);
1895
0
                gs_memset16(buf->data, gray, buf->planestride);
1896
                /* If we have a background component that was not black, then we
1897
                   need to set the alpha for this mask as if we had drawn in the
1898
                   entire soft mask buffer */
1899
0
                gs_memset16(buf->data + buf->planestride, 65535,
1900
0
                            buf->planestride *(buf->n_chan - 1));
1901
36
            } else {
1902
36
                unsigned char gray = (unsigned char) (255.0 * GrayBackground);
1903
36
                memset(buf->data, gray, buf->planestride);
1904
                /* If we have a background component that was not black, then we
1905
                   need to set the alpha for this mask as if we had drawn in the
1906
                   entire soft mask buffer */
1907
36
                memset(buf->data + buf->planestride, 255,
1908
36
                       (size_t)buf->planestride * (buf->n_chan - 1));
1909
36
            }
1910
89.6k
        } else {
1911
            /* Compose mask with opaque background */
1912
89.6k
            memset(buf->data, 0, (size_t)buf->planestride * buf->n_chan);
1913
89.6k
        }
1914
89.6k
    }
1915
137k
    return 0;
1916
137k
}
1917
1918
static void pdf14_free_mask_stack(pdf14_ctx *ctx, gs_memory_t *memory)
1919
28.9k
{
1920
28.9k
    pdf14_mask_t *mask_stack = ctx->mask_stack;
1921
1922
28.9k
    if (mask_stack->rc_mask != NULL) {
1923
66
        pdf14_mask_t *curr_mask = mask_stack;
1924
66
        pdf14_mask_t *old_mask;
1925
132
        while (curr_mask != NULL) {
1926
            /* Force to decrement until free */
1927
198
            while (curr_mask->rc_mask != NULL)
1928
132
                rc_decrement(curr_mask->rc_mask, "pdf14_free_mask_stack");
1929
66
            old_mask = curr_mask;
1930
66
            curr_mask = curr_mask->previous;
1931
66
            gs_free_object(old_mask->memory, old_mask, "pdf14_free_mask_stack");
1932
66
        }
1933
28.8k
    } else {
1934
28.8k
        gs_free_object(memory, mask_stack, "pdf14_free_mask_stack");
1935
28.8k
    }
1936
28.9k
    ctx->mask_stack = NULL;
1937
28.9k
}
1938
1939
static  int
1940
pdf14_pop_transparency_mask(pdf14_ctx *ctx, gs_gstate *pgs, gx_device *dev)
1941
137k
{
1942
137k
    pdf14_buf* tos = ctx->stack;
1943
137k
    pdf14_buf* nos = tos->saved;
1944
137k
    byte *new_data_buf;
1945
137k
    int icc_match;
1946
137k
    cmm_profile_t *des_profile = nos->group_color_info->icc_profile; /* If set, this should be a gray profile */
1947
137k
    cmm_profile_t *src_profile;
1948
137k
    gsicc_rendering_param_t rendering_params;
1949
137k
    gsicc_link_t *icc_link;
1950
137k
    gsicc_rendering_param_t render_cond;
1951
137k
    cmm_dev_profile_t *dev_profile;
1952
137k
    int code = 0;
1953
1954
137k
    dev_proc(dev, get_profile)(dev,  &dev_profile);
1955
137k
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &src_profile,
1956
137k
                          &render_cond);
1957
137k
    ctx->smask_depth -= 1;
1958
    /* icc_match == -1 means old non-icc code.
1959
       icc_match == 0 means use icc code
1960
       icc_match == 1 mean no conversion needed */
1961
137k
    if (des_profile != NULL && src_profile != NULL ) {
1962
137k
        icc_match = gsicc_profiles_equal(des_profile, src_profile);
1963
137k
    } else {
1964
0
        icc_match = -1;
1965
0
    }
1966
137k
    if_debug1m('v', ctx->memory, "[v]pdf14_pop_transparency_mask, idle=%d\n",
1967
137k
               tos->idle);
1968
137k
    ctx->stack = tos->saved;
1969
137k
    tos->saved = NULL;  /* To avoid issues with GC */
1970
137k
    if (tos->mask_stack) {
1971
        /* During the soft mask push, the mask_stack was copied (not moved) from
1972
           the ctx to the tos mask_stack. We are done with this now so it is safe to
1973
           just set to NULL.  However, before we do that we must perform
1974
           rc decrement to match the increment that occured was made.  Also,
1975
           if this is the last ref count of the rc_mask, we should free the
1976
           buffer now since no other groups need it. */
1977
28.9k
        rc_decrement(tos->mask_stack->rc_mask,
1978
28.9k
                     "pdf14_pop_transparency_mask(tos->mask_stack->rc_mask)");
1979
28.9k
        if (tos->mask_stack->rc_mask) {
1980
28.8k
            if (tos->mask_stack->rc_mask->rc.ref_count == 1){
1981
28.7k
                rc_decrement(tos->mask_stack->rc_mask,
1982
28.7k
                            "pdf14_pop_transparency_mask(tos->mask_stack->rc_mask)");
1983
28.7k
            }
1984
28.8k
        }
1985
28.9k
        tos->mask_stack = NULL;
1986
28.9k
    }
1987
137k
    if (tos->data == NULL ) {
1988
        /* This can occur in clist rendering if the soft mask does
1989
           not intersect the current band.  It would be nice to
1990
           catch this earlier and just avoid creating the structure
1991
           to begin with.  For now we need to delete the structure
1992
           that was created.  Only delete if the alpha value is 65535 */
1993
47.4k
        if ((tos->alpha == 65535 && tos->is_ident) ||
1994
47.4k
            (!tos->is_ident && (tos->transfer_fn[tos->alpha>>8] == 255))) {
1995
1.99k
            pdf14_buf_free(tos);
1996
1.99k
            if (ctx->mask_stack != NULL) {
1997
427
                pdf14_free_mask_stack(ctx, ctx->memory);
1998
427
            }
1999
45.4k
        } else {
2000
            /* Assign as mask buffer */
2001
45.4k
            if (ctx->mask_stack != NULL) {
2002
7.74k
                pdf14_free_mask_stack(ctx, ctx->memory);
2003
7.74k
            }
2004
45.4k
            ctx->mask_stack = pdf14_mask_element_new(ctx->memory);
2005
45.4k
            ctx->mask_stack->rc_mask = pdf14_rcmask_new(ctx->memory);
2006
45.4k
            ctx->mask_stack->rc_mask->mask_buf = tos;
2007
45.4k
        }
2008
47.4k
        ctx->smask_blend = false;  /* just in case */
2009
89.6k
    } else {
2010
        /* If we are already in the source space then there is no reason
2011
           to do the transformation */
2012
        /* Lets get this to a monochrome buffer and map it to a luminance only value */
2013
        /* This will reduce our memory.  We won't reuse the existing one, due */
2014
        /* Due to the fact that on certain systems we may have issues recovering */
2015
        /* the data after a resize */
2016
89.6k
        new_data_buf = gs_alloc_bytes(ctx->memory, tos->planestride + CAL_SLOP,
2017
89.6k
                                        "pdf14_pop_transparency_mask");
2018
89.6k
        if (new_data_buf == NULL)
2019
0
            return_error(gs_error_VMerror);
2020
        /* Initialize with 0.  Need to do this since in Smask_Luminosity_Mapping
2021
           we won't be filling everything during the remap if it had not been
2022
           written into by the PDF14 fill rect */
2023
89.6k
        memset(new_data_buf, 0, tos->planestride);
2024
        /* If the subtype was alpha, then just grab the alpha channel now
2025
           and we are all done */
2026
89.6k
        if (tos->SMask_SubType == TRANSPARENCY_MASK_Alpha) {
2027
10.8k
            ctx->smask_blend = false;  /* not used in this case */
2028
10.8k
            smask_copy(tos->rect.q.y - tos->rect.p.y,
2029
10.8k
                       (tos->rect.q.x - tos->rect.p.x)<<tos->deep,
2030
10.8k
                       tos->rowstride,
2031
10.8k
                       (tos->data)+tos->planestride, new_data_buf);
2032
#if RAW_DUMP
2033
            /* Dump the current buffer to see what we have. */
2034
            dump_raw_buffer(ctx->memory,
2035
                            tos->rect.q.y-tos->rect.p.y,
2036
                            tos->rowstride>>tos->deep, tos->n_planes,
2037
                            tos->planestride, tos->rowstride,
2038
                            "SMask_Pop_Alpha(Mask_Plane1)",tos->data,
2039
                            tos->deep);
2040
            global_index++;
2041
#endif
2042
78.8k
        } else {
2043
78.8k
            if (icc_match == 1 || tos->n_chan == 2) {
2044
#if RAW_DUMP
2045
                /* Dump the current buffer to see what we have. */
2046
                dump_raw_buffer(ctx->memory,
2047
                                tos->rect.q.y-tos->rect.p.y,
2048
                                tos->rowstride>>tos->deep, tos->n_planes,
2049
                                tos->planestride, tos->rowstride,
2050
                                "SMask_Pop_Lum(Mask_Plane0)",tos->data,
2051
                                tos->deep);
2052
                global_index++;
2053
#endif
2054
                /* There is no need to color convert.  Data is already gray scale.
2055
                   We just need to copy the gray plane.  However it is
2056
                   possible that the soft mask could have a soft mask which
2057
                   would end us up with some alpha blending information
2058
                   (Bug691803). In fact, according to the spec, the alpha
2059
                   blending has to occur.  See FTS test fts_26_2601.pdf
2060
                   for an example of this.  Softmask buffer is intialized
2061
                   with BG values.  It would be nice to keep track if buffer
2062
                   ever has a alpha value not 1 so that we could detect and
2063
                   avoid this blend if not needed. */
2064
78.8k
                smask_blend(tos->data, tos->rect.q.x - tos->rect.p.x,
2065
78.8k
                            tos->rect.q.y - tos->rect.p.y, tos->rowstride,
2066
78.8k
                            tos->planestride, tos->deep);
2067
#if RAW_DUMP
2068
                /* Dump the current buffer to see what we have. */
2069
                dump_raw_buffer(ctx->memory,
2070
                                tos->rect.q.y-tos->rect.p.y,
2071
                                tos->rowstride>>tos->deep, tos->n_planes,
2072
                                tos->planestride, tos->rowstride,
2073
                                "SMask_Pop_Lum_Post_Blend",tos->data,
2074
                                tos->deep);
2075
                global_index++;
2076
#endif
2077
78.8k
                smask_copy(tos->rect.q.y - tos->rect.p.y,
2078
78.8k
                           (tos->rect.q.x - tos->rect.p.x)<<tos->deep,
2079
78.8k
                           tos->rowstride, tos->data, new_data_buf);
2080
78.8k
            } else {
2081
0
                if ( icc_match == -1 ) {
2082
                    /* The slow old fashioned way */
2083
0
                    smask_luminosity_mapping(tos->rect.q.y - tos->rect.p.y ,
2084
0
                        tos->rect.q.x - tos->rect.p.x,tos->n_chan,
2085
0
                        tos->rowstride, tos->planestride,
2086
0
                        tos->data,  new_data_buf, ctx->additive, tos->SMask_SubType,
2087
0
                        tos->deep
2088
#if RAW_DUMP
2089
                        , ctx->memory
2090
#endif
2091
0
                        );
2092
0
                } else {
2093
                    /* ICC case where we use the CMM */
2094
                    /* Request the ICC link for the transform that we will need to use */
2095
0
                    rendering_params.black_point_comp = gsBLACKPTCOMP_OFF;
2096
0
                    rendering_params.graphics_type_tag = GS_IMAGE_TAG;
2097
0
                    rendering_params.override_icc = false;
2098
0
                    rendering_params.preserve_black = gsBKPRESNOTSPECIFIED;
2099
0
                    rendering_params.rendering_intent = gsRELATIVECOLORIMETRIC;
2100
0
                    rendering_params.cmm = gsCMM_DEFAULT;
2101
0
                    icc_link = gsicc_get_link_profile(pgs, dev, des_profile,
2102
0
                        src_profile, &rendering_params, pgs->memory, false);
2103
0
                    code = smask_icc(dev, tos->rect.q.y - tos->rect.p.y,
2104
0
                              tos->rect.q.x - tos->rect.p.x, tos->n_chan,
2105
0
                              tos->rowstride, tos->planestride,
2106
0
                              tos->data, new_data_buf, icc_link, tos->deep);
2107
                    /* Release the link */
2108
0
                    gsicc_release_link(icc_link);
2109
0
                }
2110
0
            }
2111
78.8k
        }
2112
        /* Free the old object, NULL test was above */
2113
89.6k
        gs_free_object(ctx->memory, tos->data, "pdf14_pop_transparency_mask");
2114
89.6k
        tos->data = new_data_buf;
2115
        /* Data is single channel now */
2116
89.6k
        tos->n_chan = 1;
2117
89.6k
        tos->n_planes = 1;
2118
        /* Assign as reference counted mask buffer */
2119
89.6k
        if (ctx->mask_stack != NULL) {
2120
            /* In this case, the source file is wacky as it already had a
2121
               softmask and now is getting a replacement. We need to clean
2122
               up the softmask stack before doing this free and creating
2123
               a new stack. Bug 693312 */
2124
20.7k
            pdf14_free_mask_stack(ctx, ctx->memory);
2125
20.7k
        }
2126
89.6k
        ctx->mask_stack = pdf14_mask_element_new(ctx->memory);
2127
89.6k
        if (ctx->mask_stack == NULL)
2128
0
            return gs_note_error(gs_error_VMerror);
2129
89.6k
        ctx->mask_stack->rc_mask = pdf14_rcmask_new(ctx->memory);
2130
89.6k
        if (ctx->mask_stack->rc_mask == NULL)
2131
0
            return gs_note_error(gs_error_VMerror);
2132
89.6k
        ctx->mask_stack->rc_mask->mask_buf = tos;
2133
89.6k
    }
2134
137k
    return code;
2135
137k
}
2136
2137
static pdf14_mask_t *
2138
pdf14_mask_element_new(gs_memory_t *memory)
2139
396k
{
2140
396k
    pdf14_mask_t *result;
2141
2142
396k
    result = gs_alloc_struct(memory, pdf14_mask_t, &st_pdf14_mask,
2143
396k
                             "pdf14_mask_element_new");
2144
396k
    if (result == NULL)
2145
0
        return NULL;
2146
    /* Get the reference counted mask */
2147
396k
    result->rc_mask = NULL;
2148
396k
    result->previous = NULL;
2149
396k
    result->memory = memory;
2150
396k
    return result;
2151
396k
}
2152
2153
static int
2154
pdf14_push_transparency_state(gx_device *dev, gs_gstate *pgs)
2155
0
{
2156
    /* We need to push the current soft mask.  We need to
2157
       be able to recover it if we draw a new one and
2158
       then obtain a Q operation ( a pop ) */
2159
2160
0
    pdf14_device *pdev = (pdf14_device *)dev;
2161
0
    pdf14_ctx *ctx = pdev->ctx;
2162
0
    pdf14_mask_t *new_mask;
2163
2164
0
    if_debug0m('v', ctx->memory, "pdf14_push_transparency_state\n");
2165
    /* We need to push the current mask buffer   */
2166
    /* Allocate a new element for the stack.
2167
       Don't do anything if there is no mask present.*/
2168
0
    if (ctx->mask_stack != NULL) {
2169
0
        new_mask = pdf14_mask_element_new(ctx->memory);
2170
        /* Duplicate and make the link */
2171
0
        new_mask->rc_mask = ctx->mask_stack->rc_mask;
2172
0
        rc_increment(new_mask->rc_mask);
2173
0
        new_mask->previous = ctx->mask_stack;
2174
0
        ctx->mask_stack = new_mask;
2175
0
    }
2176
#ifdef DEBUG
2177
    pdf14_debug_mask_stack_state(pdev->ctx);
2178
#endif
2179
0
    return 0;
2180
0
}
2181
2182
static int
2183
pdf14_pop_transparency_state(gx_device *dev, gs_gstate *pgs)
2184
1.00M
{
2185
    /* Pop the soft mask.  It is no longer needed. Likely due to
2186
       a Q that has occurred. */
2187
1.00M
    pdf14_device *pdev = (pdf14_device *)dev;
2188
1.00M
    pdf14_ctx *ctx = pdev->ctx;
2189
1.00M
    pdf14_mask_t *old_mask;
2190
2191
1.00M
    if_debug0m('v', ctx->memory, "pdf14_pop_transparency_state\n");
2192
    /* rc decrement the current link after we break it from
2193
       the list, then free the stack element.  Don't do
2194
       anything if there is no mask present. */
2195
1.00M
    if (ctx->mask_stack != NULL) {
2196
166k
        old_mask = ctx->mask_stack;
2197
166k
        ctx->mask_stack = ctx->mask_stack->previous;
2198
166k
        if (old_mask->rc_mask) {
2199
166k
            rc_decrement(old_mask->rc_mask, "pdf14_pop_transparency_state");
2200
166k
        }
2201
166k
        gs_free_object(old_mask->memory, old_mask, "pdf14_pop_transparency_state");
2202
        /* We need to have some special handling here for when we have nested
2203
           soft masks.  There may be a copy in the stack that we may need to
2204
           adjust. */
2205
166k
        if (ctx->smask_depth > 0) {
2206
33
            if (ctx->stack != NULL && ctx->stack->mask_stack != NULL) {
2207
0
                ctx->stack->mask_stack = ctx->mask_stack;
2208
0
            }
2209
33
        }
2210
166k
    }
2211
#ifdef DEBUG
2212
    pdf14_debug_mask_stack_state(pdev->ctx);
2213
#endif
2214
1.00M
    return 0;
2215
1.00M
}
2216
2217
static  int
2218
pdf14_open(gx_device *dev)
2219
261k
{
2220
261k
    pdf14_device *pdev = (pdf14_device *)dev;
2221
2222
    /* If we are reenabling the device dont create a new ctx. Bug 697456 */
2223
261k
    if (pdev->ctx == NULL) {
2224
261k
        bool has_tags = device_encodes_tags(dev);
2225
261k
        int bits_per_comp = ((dev->color_info.depth - has_tags*8) /
2226
261k
                             dev->color_info.num_components);
2227
261k
        pdev->ctx = pdf14_ctx_new(dev, bits_per_comp > 8);
2228
261k
        if (pdev->ctx == NULL)
2229
0
            return_error(gs_error_VMerror);
2230
2231
261k
        pdev->ctx->rect.p.x = 0;
2232
261k
        pdev->ctx->rect.p.y = 0;
2233
261k
        pdev->ctx->rect.q.x = dev->width;
2234
261k
        pdev->ctx->rect.q.y = dev->height;
2235
261k
        pdev->ctx->has_tags = has_tags;
2236
261k
        pdev->ctx->num_spots = pdev->color_info.num_components - pdev->num_std_colorants;
2237
261k
        pdev->ctx->additive = (pdev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE);
2238
261k
        pdev->ctx->n_chan = pdev->color_info.num_components;
2239
261k
    }
2240
261k
    pdev->free_devicen = true;
2241
261k
    pdev->text_group = PDF14_TEXTGROUP_NO_BT;
2242
261k
    return 0;
2243
261k
}
2244
2245
static const gx_cm_color_map_procs pdf14_DeviceCMYKspot_procs = {
2246
    pdf14_gray_cs_to_cmyk_cm, pdf14_rgb_cs_to_cmyk_cm, pdf14_cmyk_cs_to_cmyk_cm
2247
};
2248
2249
static const gx_cm_color_map_procs pdf14_DeviceRGBspot_procs = {
2250
    pdf14_gray_cs_to_rgbspot_cm, pdf14_rgb_cs_to_rgbspot_cm, pdf14_cmyk_cs_to_rgbspot_cm
2251
};
2252
2253
static const gx_cm_color_map_procs pdf14_DeviceGrayspot_procs = {
2254
    pdf14_gray_cs_to_grayspot_cm, pdf14_rgb_cs_to_grayspot_cm, pdf14_cmyk_cs_to_grayspot_cm
2255
};
2256
2257
static const gx_cm_color_map_procs *
2258
pdf14_cmykspot_get_color_mapping_procs(const gx_device * dev, const gx_device **tdev)
2259
2.20M
{
2260
2.20M
    *tdev = dev;
2261
2.20M
    return &pdf14_DeviceCMYKspot_procs;
2262
2.20M
}
2263
2264
static const gx_cm_color_map_procs *
2265
pdf14_rgbspot_get_color_mapping_procs(const gx_device * dev, const gx_device **tdev)
2266
4.48M
{
2267
4.48M
    *tdev = dev;
2268
4.48M
    return &pdf14_DeviceRGBspot_procs;
2269
4.48M
}
2270
2271
static const gx_cm_color_map_procs *
2272
pdf14_grayspot_get_color_mapping_procs(const gx_device * dev, const gx_device **tdev)
2273
0
{
2274
0
    *tdev = dev;
2275
0
    return &pdf14_DeviceGrayspot_procs;
2276
0
}
2277
2278
static void
2279
be_rev_cpy(uint16_t *dst,const uint16_t *src,int n)
2280
0
{
2281
0
    for (; n != 0; n--) {
2282
0
        uint16_t in = *src++;
2283
0
        ((byte *)dst)[0] = in>>8;
2284
0
        ((byte *)dst)[1] = in;
2285
0
        dst++;
2286
0
    }
2287
0
}
2288
2289
/* Used to pass along information about the buffer created by the
2290
   pdf14 device.  This is used by the pattern accumulator when the
2291
   pattern contains transparency.  Note that if free_device is true then
2292
   we need to go ahead and get the buffer data copied and free up the
2293
   device.  This only occurs at the end of a pattern accumulation operation */
2294
int
2295
pdf14_get_buffer_information(const gx_device * dev,
2296
                             gx_pattern_trans_t *transbuff, gs_memory_t *mem,
2297
                             bool free_device)
2298
17.6k
{
2299
17.6k
    const pdf14_device * pdev = (pdf14_device *)dev;
2300
17.6k
    pdf14_buf *buf;
2301
17.6k
    gs_int_rect rect;
2302
17.6k
    int x1,y1,width,height;
2303
2304
17.6k
    if ( pdev->ctx == NULL){
2305
0
        return 0;  /* this can occur if the pattern is a clist */
2306
0
    }
2307
#ifdef DEBUG
2308
    pdf14_debug_mask_stack_state(pdev->ctx);
2309
#endif
2310
17.6k
    buf = pdev->ctx->stack;
2311
17.6k
    rect = buf->rect;
2312
17.6k
    transbuff->buf = (free_device ? NULL : buf);
2313
17.6k
    x1 = min(pdev->width, rect.q.x);
2314
17.6k
    y1 = min(pdev->height, rect.q.y);
2315
17.6k
    width = x1 - rect.p.x;
2316
17.6k
    height = y1 - rect.p.y;
2317
2318
17.6k
    transbuff->n_chan    = buf->n_chan;
2319
17.6k
    transbuff->has_tags  = buf->has_tags;
2320
17.6k
    transbuff->has_shape = buf->has_shape;
2321
17.6k
    transbuff->width     = buf->rect.q.x - buf->rect.p.x;
2322
17.6k
    transbuff->height    = buf->rect.q.y - buf->rect.p.y;
2323
17.6k
    transbuff->deep      = buf->deep;
2324
2325
17.6k
    if (width <= 0 || height <= 0 || buf->data == NULL) {
2326
1.52k
        transbuff->planestride = 0;
2327
1.52k
        transbuff->rowstride = 0;
2328
1.52k
        return 0;
2329
1.52k
    }
2330
2331
16.1k
    if (free_device) {
2332
6.11k
        transbuff->pdev14 = NULL;
2333
6.11k
        transbuff->rect = rect;
2334
6.11k
        if ((width < transbuff->width) || (height < transbuff->height)) {
2335
            /* If the bbox is smaller than the whole buffer than go ahead and
2336
               create a new one to use.  This can occur if we drew in a smaller
2337
               area than was specified by the transparency group rect. */
2338
0
            int rowstride = ((width + 3) & -4)<<buf->deep;
2339
0
            int planestride = rowstride * height;
2340
0
            int k, j;
2341
0
            byte *buff_ptr_src, *buff_ptr_des;
2342
2343
0
            transbuff->planestride = planestride;
2344
0
            transbuff->rowstride = rowstride;
2345
0
            transbuff->transbytes =
2346
0
                         gs_alloc_bytes(mem,
2347
0
                                        (size_t)planestride *
2348
0
                                                (buf->n_chan +
2349
0
                                                 buf->has_tags ? 1 : 0) + CAL_SLOP,
2350
0
                                        "pdf14_get_buffer_information");
2351
0
            if (transbuff->transbytes == NULL)
2352
0
                return gs_error_VMerror;
2353
2354
0
            transbuff->mem = mem;
2355
0
            if (transbuff->deep) {
2356
0
                for (j = 0; j < transbuff->n_chan; j++) {
2357
0
                    buff_ptr_src = buf->data + j * buf->planestride +
2358
0
                               buf->rowstride * rect.p.y + (rect.p.x<<buf->deep);
2359
0
                    buff_ptr_des = transbuff->transbytes + j * planestride;
2360
0
                    for (k = 0; k < height; k++) {
2361
0
                        be_rev_cpy((uint16_t *)buff_ptr_des, (const uint16_t *)buff_ptr_src, rowstride>>1);
2362
0
                        buff_ptr_des += rowstride;
2363
0
                        buff_ptr_src += buf->rowstride;
2364
0
                    }
2365
0
                }
2366
0
            } else {
2367
0
                for (j = 0; j < transbuff->n_chan; j++) {
2368
0
                    buff_ptr_src = buf->data + j * buf->planestride +
2369
0
                               buf->rowstride * rect.p.y + (rect.p.x<<buf->deep);
2370
0
                    buff_ptr_des = transbuff->transbytes + j * planestride;
2371
0
                    for (k = 0; k < height; k++) {
2372
0
                        memcpy(buff_ptr_des, buff_ptr_src, rowstride);
2373
0
                        buff_ptr_des += rowstride;
2374
0
                        buff_ptr_src += buf->rowstride;
2375
0
                    }
2376
0
                }
2377
0
            }
2378
2379
6.11k
        } else {
2380
            /* The entire buffer is used.  Go ahead and grab the pointer and
2381
               clear the pointer in the pdf14 device data buffer so it is not
2382
               freed when we close the device */
2383
6.11k
            transbuff->planestride = buf->planestride;
2384
6.11k
            transbuff->rowstride = buf->rowstride;
2385
6.11k
            transbuff->transbytes = buf->data;
2386
6.11k
            transbuff->mem = buf->memory;
2387
6.11k
            buf->data = NULL;  /* So that the buffer is not freed */
2388
6.11k
            if (transbuff->deep) {
2389
                /* We have the data in native endian. We need it in big endian. Do an in-place conversion. */
2390
                /* FIXME: This is a nop on big endian machines. Is the compiler smart enough to spot that? */
2391
0
                uint16_t *buff_ptr;
2392
0
                int j, k, z;
2393
0
                int rowstride = transbuff->rowstride>>1;
2394
0
                int planestride = transbuff->planestride;
2395
0
                for (j = 0; j < transbuff->n_chan; j++) {
2396
0
                    buff_ptr = (uint16_t *)(transbuff->transbytes + j * planestride);
2397
0
                    for (k = 0; k < height; k++) {
2398
0
                        for (z = 0; z < width; z++) {
2399
0
                            uint16_t in = buff_ptr[z];
2400
0
                            ((byte *)(&buff_ptr[z]))[0] = in>>8;
2401
0
                            ((byte *)(&buff_ptr[z]))[1] = in;
2402
0
                        }
2403
0
                        buff_ptr += rowstride;
2404
0
                    }
2405
0
                }
2406
0
            }
2407
6.11k
        }
2408
#if RAW_DUMP
2409
        /* Dump the buffer that should be going into the pattern */;
2410
        dump_raw_buffer_be(buf->memory,
2411
                           height, width, transbuff->n_chan,
2412
                           transbuff->planestride, transbuff->rowstride,
2413
                           "pdf14_pattern_buff", transbuff->transbytes,
2414
                           transbuff->deep);
2415
        global_index++;
2416
#endif
2417
        /* Go ahead and free up the pdf14 device */
2418
6.11k
        dev_proc(dev, close_device)((gx_device *)dev);
2419
9.99k
    } else {
2420
        /* Here we are coming from one of the fill image / pattern / mask
2421
           operations */
2422
9.99k
        transbuff->pdev14 = dev;
2423
9.99k
        transbuff->planestride = buf->planestride;
2424
9.99k
        transbuff->rowstride = buf->rowstride;
2425
9.99k
        transbuff->transbytes = buf->data;
2426
9.99k
        transbuff->mem = buf->memory;
2427
9.99k
        transbuff->rect = rect;
2428
#if RAW_DUMP
2429
    /* Dump the buffer that should be going into the pattern */;
2430
        dump_raw_buffer(buf->memory,
2431
                        height, width, buf->n_chan,
2432
                        pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
2433
                        "pdf14_pattern_buff",
2434
                        buf->data,
2435
                        transbuff->deep);
2436
        global_index++;
2437
#endif
2438
9.99k
    }
2439
16.1k
    return 0;
2440
16.1k
}
2441
2442
typedef void(*blend_image_row_proc_t) (const byte *gs_restrict buf_ptr,
2443
    int planestride, int width, int num_comp, uint16_t bg, byte *gs_restrict linebuf);
2444
2445
2446
static int
2447
pdf14_put_image_color_convert(const pdf14_device* dev, gs_gstate* pgs, cmm_profile_t* src_profile,
2448
                        cmm_dev_profile_t* dev_target_profile, pdf14_buf** buf,
2449
                        byte** buf_ptr, bool was_blended, int x, int y, int width, int height)
2450
2.71k
{
2451
2.71k
    pdf14_buf* cm_result = NULL;
2452
2.71k
    cmm_profile_t* des_profile;
2453
2.71k
    gsicc_rendering_param_t render_cond;
2454
2.71k
    bool did_alloc;
2455
2.71k
    bool endian_swap;
2456
2457
2.71k
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_target_profile, &des_profile,
2458
2.71k
        &render_cond);
2459
2460
#if RAW_DUMP
2461
    dump_raw_buffer(dev->ctx->memory,
2462
        height, width, (*buf)->n_planes, (*buf)->planestride,
2463
        (*buf)->rowstride, "pdf14_put_image_color_convert_pre", *buf_ptr, (*buf)->deep);
2464
    global_index++;
2465
#endif
2466
2467
    /* If we are doing a 16 bit buffer it will be big endian if we have already done the
2468
       blend, otherwise it will be native endian. GS expects its 16bit buffers to be BE
2469
       but for sanity pdf14 device maintains 16bit buffers in native format.  The CMM
2470
       will need to know if it is dealing with native or BE data. */
2471
2.71k
    if (was_blended && (*buf)->deep) {
2472
        /* Data is in BE.  If we are in a LE machine, CMM will need to swap for
2473
           color conversion */
2474
#if ARCH_IS_BIG_ENDIAN
2475
        endian_swap = false;
2476
#else
2477
0
        endian_swap = true;
2478
0
#endif
2479
2.71k
    } else {
2480
        /* Data is in native format. No swap needed for CMM */
2481
2.71k
        endian_swap = false;
2482
2.71k
    }
2483
2484
2.71k
    cm_result = pdf14_transform_color_buffer_no_matte(pgs, dev->ctx, (gx_device*) dev, *buf,
2485
2.71k
        *buf_ptr, src_profile, des_profile, x, y, width,
2486
2.71k
        height, &did_alloc, (*buf)->deep, endian_swap);
2487
2488
2.71k
    if (cm_result == NULL)
2489
0
        return_error(gs_error_VMerror);
2490
2491
    /* Update */
2492
2.71k
    *buf = cm_result;
2493
2494
    /* Make sure our buf_ptr is pointing to the proper location */
2495
2.71k
    if (did_alloc)
2496
2.71k
        *buf_ptr = cm_result->data;  /* Note the lack of offset */
2497
2498
#if RAW_DUMP
2499
    dump_raw_buffer(dev->ctx->memory,
2500
        height, width, (*buf)->n_planes, (*buf)->planestride,
2501
        (*buf)->rowstride, "pdf14_put_image_color_convert_post", *buf_ptr, (*buf)->deep);
2502
    global_index++;
2503
#endif
2504
2.71k
    return 0;
2505
2.71k
}
2506
2507
/**
2508
 * pdf14_put_image: Put rendered image to target device.
2509
 * @pdev: The PDF 1.4 rendering device.
2510
 * @pgs: State for image draw operation.
2511
 * @target: The target device.
2512
 *
2513
 * Puts the rendered image in @pdev's buffer to @target. This is called
2514
 * as part of the sequence of popping the PDF 1.4 device filter.
2515
 *
2516
 * Return code: negative on error.
2517
 **/
2518
static  int
2519
pdf14_put_image(gx_device * dev, gs_gstate * pgs, gx_device * target)
2520
244k
{
2521
244k
    const pdf14_device * pdev = (pdf14_device *)dev;
2522
244k
    int code;
2523
244k
    gs_image1_t image;
2524
244k
    gx_image_enum_common_t *info;
2525
244k
    pdf14_buf *buf = pdev->ctx->stack;
2526
244k
    gs_int_rect rect;
2527
244k
    int y;
2528
244k
    int num_comp;
2529
244k
    byte *linebuf, *linebuf_unaligned;
2530
244k
    gs_color_space *pcs;
2531
244k
    int x1, y1, width, height;
2532
244k
    byte *buf_ptr;
2533
244k
    int num_rows_left;
2534
244k
    cmm_profile_t* src_profile = NULL;
2535
244k
    cmm_profile_t* des_profile = NULL;
2536
244k
    cmm_dev_profile_t *pdf14dev_profile;
2537
244k
    cmm_dev_profile_t *dev_target_profile;
2538
244k
    uint16_t bg;
2539
244k
    bool has_tags = device_encodes_tags(dev);
2540
244k
    bool deep = pdev->ctx->deep;
2541
244k
    int planestride;
2542
244k
    int rowstride;
2543
244k
    blend_image_row_proc_t blend_row;
2544
244k
    bool color_mismatch = false;
2545
244k
    bool supports_alpha = false;
2546
244k
    int i;
2547
244k
    int alpha_offset, tag_offset;
2548
244k
    const byte* buf_ptrs[GS_CLIENT_COLOR_MAX_COMPONENTS];
2549
244k
    int rendering_intent_saved;
2550
2551
    /* Nothing was ever drawn. */
2552
244k
    if (buf == NULL)
2553
24.0k
        return 0;
2554
2555
220k
    bg = buf->group_color_info->isadditive ? 65535 : 0;
2556
220k
    src_profile = buf->group_color_info->icc_profile;
2557
2558
220k
    num_comp = buf->n_chan - 1;
2559
220k
    rect = buf->rect;
2560
220k
    planestride = buf->planestride;
2561
220k
    rowstride = buf->rowstride;
2562
2563
    /* Make sure that this is the only item on the stack. Fuzzing revealed a
2564
       potential problem. Bug 694190 */
2565
220k
    if (buf->saved != NULL) {
2566
3
        return gs_throw(gs_error_unknownerror, "PDF14 device push/pop out of sync");
2567
3
    }
2568
220k
    if_debug0m('v', dev->memory, "[v]pdf14_put_image\n");
2569
220k
    rect_intersect(rect, buf->dirty);
2570
220k
    x1 = min(pdev->width, rect.q.x);
2571
220k
    y1 = min(pdev->height, rect.q.y);
2572
220k
    width = x1 - rect.p.x;
2573
220k
    height = y1 - rect.p.y;
2574
#ifdef DUMP_TO_PNG
2575
    dump_planar_rgba(pdev->memory, buf);
2576
#endif
2577
220k
    if (width <= 0 || height <= 0 || buf->data == NULL)
2578
44.2k
        return 0;
2579
175k
    buf_ptr = buf->data + (rect.p.y - buf->rect.p.y) * buf->rowstride + ((rect.p.x - buf->rect.p.x) << deep);
2580
2581
    /* Check that target is OK.  From fuzzing results the target could have been
2582
       destroyed, for e.g if it were a pattern accumulator that was closed
2583
       prematurely (Bug 694154).  We should always be able to to get an ICC
2584
       profile from the target. */
2585
175k
    code = dev_proc(target, get_profile)(target,  &dev_target_profile);
2586
175k
    if (code < 0)
2587
0
        return code;
2588
175k
    if (dev_target_profile == NULL)
2589
0
        return gs_throw_code(gs_error_Fatal);
2590
2591
175k
    if (src_profile == NULL) {
2592
0
        code = dev_proc(dev, get_profile)(dev, &pdf14dev_profile);
2593
0
        if (code < 0) {
2594
0
            return code;
2595
0
        }
2596
0
        src_profile = pdf14dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE];
2597
0
    }
2598
2599
    /* Check if we have a color conversion issue */
2600
175k
    des_profile = dev_target_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE];
2601
175k
    if (!gsicc_profiles_equal(des_profile, src_profile))
2602
11.3k
        color_mismatch = true;
2603
2604
    /* Check if target supports alpha */
2605
175k
    supports_alpha = dev_proc(target, dev_spec_op)(target, gxdso_supports_alpha, NULL, 0);
2606
175k
    code = 0;
2607
2608
#if RAW_DUMP
2609
    dump_raw_buffer(pdev->ctx->memory, height, width, buf->n_planes,
2610
        pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
2611
        "pre_final_blend", buf_ptr, deep);
2612
#endif
2613
2614
    /* Note. The logic below will need a little rework if we ever
2615
       have a device that has tags and alpha support */
2616
175k
    if (supports_alpha) {
2617
0
        if (!color_mismatch) {
2618
0
            alpha_offset = num_comp;
2619
0
            tag_offset = buf->has_tags ? buf->n_chan : 0;
2620
2621
0
            for (i = 0; i < buf->n_planes; i++)
2622
0
                buf_ptrs[i] = buf_ptr + i * planestride;
2623
0
            code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
2624
0
                rect.p.x, rect.p.y, width, height,
2625
0
                rowstride, alpha_offset,
2626
0
                tag_offset);
2627
            /* Right now code has number of rows written */
2628
0
        } else {
2629
            /* In this case, just color convert and maintain alpha.  This is a case
2630
               where we either either blend in the right color space and have no
2631
               alpha for the output device or hand back the wrong color space with
2632
               alpha data.  We choose the later. */
2633
0
            code = pdf14_put_image_color_convert(pdev, pgs, src_profile,
2634
0
                dev_target_profile, &buf, &buf_ptr, false, rect.p.x, rect.p.y,
2635
0
                width, height);
2636
0
            if (code < 0)
2637
0
                return code;
2638
2639
            /* reset */
2640
0
            rowstride = buf->rowstride;
2641
0
            planestride = buf->planestride;
2642
0
            num_comp = buf->n_chan - 1;
2643
0
            alpha_offset = num_comp;
2644
0
            tag_offset = buf->has_tags ? buf->n_chan : 0;
2645
2646
            /* And then out */
2647
0
            for (i = 0; i < buf->n_planes; i++)
2648
0
                buf_ptrs[i] = buf_ptr + i * planestride;
2649
0
            code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
2650
0
                rect.p.x, rect.p.y, width, height, rowstride, alpha_offset,
2651
0
                tag_offset);
2652
            /* Right now code has number of rows written */
2653
0
        }
2654
175k
    } else if (has_tags) {
2655
        /* We are going out to a device that supports tags */
2656
0
        if (deep) {
2657
0
            gx_blend_image_buffer16(buf_ptr, width, height, rowstride,
2658
0
                buf->planestride, num_comp, bg, false);
2659
0
        } else {
2660
0
            gx_blend_image_buffer(buf_ptr, width, height, rowstride,
2661
0
                buf->planestride, num_comp, bg >> 8);
2662
0
        }
2663
2664
#if RAW_DUMP
2665
        dump_raw_buffer(pdev->ctx->memory, height, width, buf->n_planes,
2666
            pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
2667
            "post_final_blend", buf_ptr, deep);
2668
#endif
2669
2670
        /* Take care of color issues */
2671
0
        if (color_mismatch) {
2672
            /* In this case, just color convert and maintain alpha.  This is a case
2673
               where we either either blend in the right color space and have no
2674
               alpha for the output device or hand back the wrong color space with
2675
               alpha data.  We choose the later. */
2676
0
            code = pdf14_put_image_color_convert(pdev, pgs, src_profile, dev_target_profile,
2677
0
                &buf, &buf_ptr, true, rect.p.x, rect.p.y, width, height);
2678
0
            if (code < 0)
2679
0
                return code;
2680
2681
#if RAW_DUMP
2682
            dump_raw_buffer(pdev->ctx->memory, height, width, buf->n_planes,
2683
                pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
2684
                "final_color_manage", buf_ptr, deep);
2685
            global_index++;
2686
#endif
2687
0
        }
2688
2689
        /* reset */
2690
0
        rowstride = buf->rowstride;
2691
0
        planestride = buf->planestride;
2692
0
        num_comp = buf->n_chan - 1;
2693
0
        alpha_offset = 0;  /* It is there but this indicates we have done the blend */
2694
0
        tag_offset = buf->has_tags ? buf->n_chan : 0;
2695
2696
        /* And then out */
2697
0
        for (i = 0; i < buf->n_planes; i++)
2698
0
            buf_ptrs[i] = buf_ptr + i * planestride;
2699
0
        code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
2700
0
            rect.p.x, rect.p.y, width, height, rowstride, alpha_offset,
2701
0
            tag_offset);
2702
        /* Right now code has number of rows written */
2703
2704
0
    }
2705
2706
    /* If code > 0 then put image worked.  Let it finish and then exit */
2707
175k
    if (code > 0) {
2708
        /* We processed some or all of the rows.  Continue until we are done */
2709
0
        num_rows_left = height - code;
2710
0
        while (num_rows_left > 0) {
2711
0
            code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
2712
0
                                                rect.p.x, rect.p.y + code, width,
2713
0
                                                num_rows_left, rowstride,
2714
0
                                                alpha_offset, tag_offset);
2715
0
            num_rows_left = num_rows_left - code;
2716
0
        }
2717
0
        return 0;
2718
0
    }
2719
2720
    /* Target device did not support alpha or tags.
2721
     * Set color space in preparation for sending an image.
2722
     * color conversion will occur after blending with through
2723
     * the begin typed image work flow.
2724
     */
2725
2726
175k
    planestride = buf->planestride;
2727
175k
    rowstride = buf->rowstride;
2728
175k
    code = gs_cspace_build_ICC(&pcs, NULL, pgs->memory);
2729
175k
    if (code < 0)
2730
0
        return code;
2731
    /* Need to set this to avoid color management during the image color render
2732
       operation.  Exception is for the special case when the destination was
2733
       CIELAB.  Then we need to convert from default RGB to CIELAB in the put
2734
       image operation.  That will happen here as we should have set the profile
2735
       for the pdf14 device to RGB and the target will be CIELAB.  In addition,
2736
       the case when we have a blend color space that is different than the
2737
       target device color space */
2738
175k
    pcs->cmm_icc_profile_data = src_profile;
2739
2740
    /* pcs takes a reference to the profile data it just retrieved. */
2741
175k
    gsicc_adjust_profile_rc(pcs->cmm_icc_profile_data, 1, "pdf14_put_image");
2742
175k
    gsicc_set_icc_range(&(pcs->cmm_icc_profile_data));
2743
175k
    gs_image_t_init_adjust(&image, pcs, false);
2744
175k
    image.ImageMatrix.xx = (float)width;
2745
175k
    image.ImageMatrix.yy = (float)height;
2746
175k
    image.Width = width;
2747
175k
    image.Height = height;
2748
175k
    image.BitsPerComponent = deep ? 16 : 8;
2749
175k
    image.ColorSpace = pcs;
2750
175k
    ctm_only_writable(pgs).xx = (float)width;
2751
175k
    ctm_only_writable(pgs).xy = 0;
2752
175k
    ctm_only_writable(pgs).yx = 0;
2753
175k
    ctm_only_writable(pgs).yy = (float)height;
2754
175k
    ctm_only_writable(pgs).tx = (float)rect.p.x;
2755
175k
    ctm_only_writable(pgs).ty = (float)rect.p.y;
2756
    /* Make sure that the relative colorimetric rendering intent is
2757
       used for this image. */
2758
175k
    rendering_intent_saved = pgs->renderingintent;
2759
175k
    pgs->renderingintent = gsRELATIVECOLORIMETRIC;
2760
175k
    code = dev_proc(target, begin_typed_image) (target,
2761
175k
                                                pgs, NULL,
2762
175k
                                                (gs_image_common_t *)&image,
2763
175k
                                                NULL, NULL, NULL,
2764
175k
                                                pgs->memory, &info);
2765
175k
    pgs->renderingintent = rendering_intent_saved;
2766
175k
    if (code < 0) {
2767
0
        rc_decrement_only_cs(pcs, "pdf14_put_image");
2768
0
        return code;
2769
0
    }
2770
#if RAW_DUMP
2771
    /* Dump the current buffer to see what we have. */
2772
    dump_raw_buffer(pdev->ctx->memory,
2773
                    pdev->ctx->stack->rect.q.y-pdev->ctx->stack->rect.p.y,
2774
                    pdev->ctx->stack->rect.q.x-pdev->ctx->stack->rect.p.x,
2775
                    pdev->ctx->stack->n_planes,
2776
                    pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
2777
                    "pdF14_putimage", pdev->ctx->stack->data, deep);
2778
    dump_raw_buffer(pdev->ctx->memory,
2779
                    height, width, buf->n_planes,
2780
                    pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
2781
                    "PDF14_PUTIMAGE_SMALL", buf_ptr, deep);
2782
    global_index++;
2783
    clist_band_count++;
2784
#endif
2785
    /* Allocate on 32-byte border for AVX CMYK case. Four byte overflow for RGB case */
2786
    /* 28 byte overflow for AVX CMYK case. */
2787
175k
#define SSE_ALIGN 32
2788
175k
#define SSE_OVERFLOW 28
2789
175k
    linebuf_unaligned = gs_alloc_bytes(pdev->memory, width * (num_comp<<deep) + SSE_ALIGN + SSE_OVERFLOW, "pdf14_put_image");
2790
175k
    if (linebuf_unaligned == NULL)
2791
0
        return gs_error_VMerror;
2792
175k
    linebuf = linebuf_unaligned + ((-(intptr_t)linebuf_unaligned) & (SSE_ALIGN-1));
2793
2794
175k
    blend_row = deep ? gx_build_blended_image_row16 :
2795
175k
                       gx_build_blended_image_row;
2796
#ifdef WITH_CAL
2797
    blend_row = cal_get_blend_row(pdev->memory->gs_lib_ctx->core->cal_ctx,
2798
                                  blend_row, num_comp, deep);
2799
#endif
2800
2801
175k
    if (!deep)
2802
175k
        bg >>= 8;
2803
2.01M
    for (y = 0; y < height; y++) {
2804
1.83M
        gx_image_plane_t planes;
2805
1.83M
        int rows_used;
2806
2807
1.83M
        blend_row(buf_ptr, buf->planestride, width, num_comp, bg, linebuf);
2808
1.83M
        planes.data = linebuf;
2809
1.83M
        planes.data_x = 0;
2810
1.83M
        planes.raster = width * num_comp;
2811
1.83M
        info->procs->plane_data(info, &planes, 1, &rows_used);
2812
        /* todo: check return value */
2813
1.83M
        buf_ptr += buf->rowstride;
2814
1.83M
    }
2815
175k
    gs_free_object(pdev->memory, linebuf_unaligned, "pdf14_put_image");
2816
175k
    info->procs->end_image(info, true);
2817
    /* This will also decrement the device profile */
2818
175k
    rc_decrement_only_cs(pcs, "pdf14_put_image");
2819
175k
    return code;
2820
175k
}
2821
2822
/* Overprint simulation with spots.  Collapse to CMYK */
2823
static void
2824
template_spots_to_cmyk(byte *buf_ptr, int width, int height, int rowstride,
2825
    int planestride, int num_comp, int spot_start, int tag_offset,
2826
    cmyk_composite_map *map, bool keep_alpha)
2827
0
{
2828
0
    int comp_num;
2829
0
    uint cyan, magenta, yellow, black;
2830
0
    cmyk_composite_map *cmyk_map_entry;
2831
0
    int x, y;
2832
0
    int position;
2833
0
    byte comp, a;
2834
2835
0
    for (y = 0; y < height; y++) {
2836
0
        position = y * rowstride;
2837
0
        for (x = 0; x < width; x++) {
2838
0
            a = buf_ptr[position + planestride * num_comp];
2839
0
            if (a != 0) {
2840
0
                cyan = buf_ptr[position] * frac_1;
2841
0
                magenta = buf_ptr[position + planestride] * frac_1;
2842
0
                yellow = buf_ptr[position + planestride * 2] * frac_1;
2843
0
                black = buf_ptr[position + planestride * 3] * frac_1;
2844
0
                cmyk_map_entry = &(map[4]);
2845
0
                for (comp_num = spot_start; comp_num < num_comp; comp_num++) {
2846
0
                    comp = buf_ptr[position + planestride * comp_num];
2847
0
                    cyan += cmyk_map_entry->c * comp;
2848
0
                    magenta += cmyk_map_entry->m * comp;
2849
0
                    yellow += cmyk_map_entry->y * comp;
2850
0
                    black += cmyk_map_entry->k * comp;
2851
0
                    cmyk_map_entry++;
2852
0
                }
2853
0
                cyan /= frac_1;
2854
0
                magenta /= frac_1;
2855
0
                yellow /= frac_1;
2856
0
                black /= frac_1;
2857
2858
0
                if (cyan > 255)
2859
0
                    cyan = 255;
2860
0
                if (magenta > 255)
2861
0
                    magenta = 255;
2862
0
                if (yellow > 255)
2863
0
                    yellow = 255;
2864
0
                if (black > 255)
2865
0
                    black = 255;
2866
2867
0
                buf_ptr[position] = cyan;
2868
0
                buf_ptr[position + planestride] = magenta;
2869
0
                buf_ptr[position + planestride * 2] = yellow;
2870
0
                buf_ptr[position + planestride * 3] = black;
2871
0
            }
2872
0
            if (keep_alpha) {
2873
                /* Move the alpha and tag data */
2874
0
                buf_ptr[position + planestride * 4] = a;
2875
0
                if (tag_offset > 0) {
2876
0
                    buf_ptr[position + planestride * 5] =
2877
0
                        buf_ptr[position + planestride * tag_offset];
2878
0
                }
2879
0
            } else {
2880
                /* Remove alpha but keep tags */
2881
0
                if (tag_offset > 0) {
2882
0
                    buf_ptr[position + planestride * 4] =
2883
0
                        buf_ptr[position + planestride * tag_offset];
2884
0
                }
2885
2886
0
            }
2887
0
            position += 1;
2888
0
        }
2889
0
    }
2890
0
}
2891
2892
static void
2893
template_spots_to_cmyk_16(byte *buf_ptr_, int width, int height, int rowstride,
2894
    int planestride, int num_comp, int spot_start, int tag_offset,
2895
    cmyk_composite_map *map, bool keep_alpha)
2896
0
{
2897
0
    int comp_num;
2898
0
    ulong cyan, magenta, yellow, black;
2899
0
    cmyk_composite_map *cmyk_map_entry;
2900
0
    int x, y;
2901
0
    int position;
2902
0
    ulong comp, a;
2903
0
    uint16_t *buf_ptr = (uint16_t *)(void *)buf_ptr_;
2904
2905
    /* planestride and rowstride are in bytes, and we want them in shorts */
2906
0
    planestride >>= 1;
2907
0
    rowstride >>= 1;
2908
2909
0
    for (y = 0; y < height; y++) {
2910
0
        position = y * rowstride;
2911
0
        for (x = 0; x < width; x++) {
2912
0
            a = buf_ptr[position + planestride * num_comp];
2913
0
            if (a != 0) {
2914
0
                cyan = (ulong)buf_ptr[position] * frac_1_long;
2915
0
                magenta = (ulong)buf_ptr[position + planestride] * frac_1_long;
2916
0
                yellow = (ulong)buf_ptr[position + planestride * 2] * frac_1_long;
2917
0
                black = (ulong)buf_ptr[position + planestride * 3] * frac_1_long;
2918
0
                cmyk_map_entry = &(map[4]);
2919
0
                for (comp_num = spot_start; comp_num < num_comp; comp_num++) {
2920
0
                    comp = buf_ptr[position + planestride * comp_num];
2921
0
                    cyan += (ulong)cmyk_map_entry->c * comp;
2922
0
                    magenta += (ulong)cmyk_map_entry->m * comp;
2923
0
                    yellow += (ulong)cmyk_map_entry->y * comp;
2924
0
                    black += (ulong)cmyk_map_entry->k * comp;
2925
0
                    cmyk_map_entry++;
2926
0
                }
2927
0
                cyan /= frac_1_long;
2928
0
                magenta /= frac_1_long;
2929
0
                yellow /= frac_1_long;
2930
0
                black /= frac_1_long;
2931
2932
0
                if (cyan > 65535)
2933
0
                    cyan = 65535;
2934
0
                if (magenta > 65535)
2935
0
                    magenta = 65535;
2936
0
                if (yellow > 65535)
2937
0
                    yellow = 65535;
2938
0
                if (black > 65535)
2939
0
                    black = 65535;
2940
2941
#if ARCH_IS_BIG_ENDIAN
2942
                buf_ptr[position] = cyan;
2943
                buf_ptr[position + planestride] = magenta;
2944
                buf_ptr[position + planestride * 2] = yellow;
2945
                buf_ptr[position + planestride * 3] = black;
2946
#else
2947
0
                ((byte *)&buf_ptr[position])[0] = cyan >> 8;
2948
0
                ((byte *)&buf_ptr[position])[1] = cyan;
2949
0
                ((byte *)&buf_ptr[position + planestride])[0] = magenta >> 8;
2950
0
                ((byte *)&buf_ptr[position + planestride])[1] = magenta;
2951
0
                ((byte *)&buf_ptr[position + planestride * 2])[0] = yellow >> 8;
2952
0
                ((byte *)&buf_ptr[position + planestride * 2])[1] = yellow;
2953
0
                ((byte *)&buf_ptr[position + planestride * 3])[0] = black >> 8;
2954
0
                ((byte *)&buf_ptr[position + planestride * 3])[1] = black;
2955
0
#endif
2956
0
            }
2957
            /* Move the alpha and tag data */
2958
#if ARCH_IS_BIG_ENDIAN
2959
            if (keep_alpha) {
2960
                buf_ptr[position + planestride * 4] = a;
2961
                if (tag_offset > 0) {
2962
                    buf_ptr[position + planestride * 5] =
2963
                        buf_ptr[position + planestride * tag_offset];
2964
                }
2965
            } else {
2966
                if (tag_offset > 0) {
2967
                    buf_ptr[position + planestride * 4] =
2968
                        buf_ptr[position + planestride * tag_offset];
2969
                }
2970
            }
2971
#else
2972
0
            if (keep_alpha) {
2973
0
                ((byte *)&buf_ptr[position + planestride * 4])[0] = a >> 8;
2974
0
                ((byte *)&buf_ptr[position + planestride * 4])[1] = a;
2975
0
                if (tag_offset > 0) {
2976
0
                    ((byte *)&buf_ptr[position + planestride * 5])[0] =
2977
0
                        buf_ptr[position + planestride * tag_offset] >> 8;
2978
0
                    ((byte *)&buf_ptr[position + planestride * 5])[1] =
2979
0
                        buf_ptr[position + planestride * tag_offset];
2980
0
                }
2981
0
            } else {
2982
0
                if (tag_offset > 0) {
2983
0
                    ((byte *)&buf_ptr[position + planestride * 4])[0] =
2984
0
                        buf_ptr[position + planestride * tag_offset] >> 8;
2985
0
                    ((byte *)&buf_ptr[position + planestride * 4])[1] =
2986
0
                        buf_ptr[position + planestride * tag_offset];
2987
0
                }
2988
0
            }
2989
0
#endif
2990
0
            position += 1;
2991
0
        }
2992
0
    }
2993
0
}
2994
2995
static void
2996
pdf14_spots_to_cmyk(byte *buf_ptr, int width, int height, int rowstride,
2997
    int planestride, int num_comp, int spot_start, int tag_offset,
2998
    cmyk_composite_map *map, bool keep_alpha, bool deep)
2999
0
{
3000
0
    if (deep) {
3001
0
        if (keep_alpha) {
3002
0
            if (tag_offset > 0) {
3003
0
                template_spots_to_cmyk_16(buf_ptr, width, height, rowstride,
3004
0
                    planestride, num_comp, spot_start, tag_offset,
3005
0
                    map, true);
3006
0
            } else {
3007
0
                template_spots_to_cmyk_16(buf_ptr, width, height, rowstride,
3008
0
                    planestride, num_comp, spot_start, 0,
3009
0
                    map, true);
3010
0
            }
3011
0
        } else {
3012
0
            if (tag_offset > 0) {
3013
0
                template_spots_to_cmyk_16(buf_ptr, width, height, rowstride,
3014
0
                    planestride, num_comp, spot_start, tag_offset,
3015
0
                    map, false);
3016
0
            } else {
3017
0
                template_spots_to_cmyk_16(buf_ptr, width, height, rowstride,
3018
0
                    planestride, num_comp, spot_start, 0,
3019
0
                    map, false);
3020
0
            }
3021
0
        }
3022
0
    } else {
3023
0
        if (keep_alpha) {
3024
0
            if (tag_offset > 0) {
3025
0
                template_spots_to_cmyk(buf_ptr, width, height, rowstride,
3026
0
                    planestride, num_comp, spot_start, tag_offset,
3027
0
                    map, true);
3028
0
            } else {
3029
0
                template_spots_to_cmyk(buf_ptr, width, height, rowstride,
3030
0
                    planestride, num_comp, spot_start, 0,
3031
0
                    map, true);
3032
0
            }
3033
0
        } else {
3034
0
            if (tag_offset > 0) {
3035
0
                template_spots_to_cmyk(buf_ptr, width, height, rowstride,
3036
0
                    planestride, num_comp, spot_start, tag_offset,
3037
0
                    map, false);
3038
0
            } else {
3039
0
                template_spots_to_cmyk(buf_ptr, width, height, rowstride,
3040
0
                    planestride, num_comp, spot_start, 0,
3041
0
                    map, false);
3042
0
            }
3043
0
        }
3044
0
    }
3045
0
}
3046
3047
/* This is for the case where we have mixture of spots and additive color.
3048
   For example, RGB + spots or Gray + spots */
3049
static void
3050
pdf14_blend_image_mixed_buffer(byte* buf_ptr, int width, int height, int rowstride,
3051
    int planestride, int num_comp, int spot_start)
3052
2.71k
{
3053
2.71k
    int x, y;
3054
2.71k
    int position;
3055
2.71k
    byte comp, a;
3056
2.71k
    int tmp, comp_num;
3057
3058
33.6k
    for (y = 0; y < height; y++) {
3059
30.9k
        position = y * rowstride;
3060
42.4M
        for (x = 0; x < width; x++) {
3061
42.4M
            a = buf_ptr[position + planestride * num_comp];
3062
42.4M
            if ((a + 1) & 0xfe) {
3063
584k
                a ^= 0xff;
3064
2.33M
                for (comp_num = 0; comp_num < spot_start; comp_num++) {
3065
1.75M
                    comp = buf_ptr[position + planestride * comp_num];
3066
1.75M
                    tmp = ((0xff - comp) * a) + 0x80;
3067
1.75M
                    comp += (tmp + (tmp >> 8)) >> 8;
3068
1.75M
                    buf_ptr[position + planestride * comp_num] = comp;
3069
1.75M
                }
3070
584k
                for (comp_num = spot_start; comp_num < num_comp; comp_num++) {
3071
0
                    comp = buf_ptr[position + planestride * comp_num];
3072
0
                    tmp = ((-comp) * a) + 0x80;
3073
0
                    comp += (tmp + (tmp >> 8)) >> 8;
3074
0
                    buf_ptr[position + planestride * comp_num] = comp;
3075
0
                }
3076
41.8M
            } else if (a == 0) {
3077
10.1M
                for (comp_num = 0; comp_num < spot_start; comp_num++) {
3078
7.62M
                    buf_ptr[position + planestride * comp_num] = 0xff;
3079
7.62M
                }
3080
2.54M
                for (comp_num = spot_start; comp_num < num_comp; comp_num++) {
3081
0
                    buf_ptr[position + planestride * comp_num] = 0;
3082
0
                }
3083
2.54M
            }
3084
42.4M
            position += 1;
3085
42.4M
        }
3086
30.9k
    }
3087
2.71k
}
3088
3089
static void
3090
pdf14_blend_image_mixed_buffer16(byte* buf_ptr_, int width, int height, int rowstride,
3091
    int planestride, int num_comp, int spot_start)
3092
0
{
3093
0
    uint16_t* buf_ptr = (uint16_t*)(void*)buf_ptr_;
3094
0
    int x, y;
3095
0
    int position;
3096
0
    int comp, a;
3097
0
    int tmp, comp_num;
3098
3099
    /* planestride and rowstride are in bytes, and we want them in shorts */
3100
0
    planestride >>= 1;
3101
0
    rowstride >>= 1;
3102
3103
    /* Note that the input here is native endian, and the output must be in big endian! */
3104
0
    for (y = 0; y < height; y++) {
3105
0
        position = y * rowstride;
3106
0
        for (x = 0; x < width; x++) {
3107
            /* composite RGBA (or CMYKA, etc.) pixel with over solid background */
3108
0
            a = buf_ptr[position + planestride * num_comp];
3109
0
            if (a == 0) {
3110
0
                for (comp_num = 0; comp_num < spot_start; comp_num++) {
3111
0
                    buf_ptr[position + planestride * comp_num] = 0xffff;
3112
0
                }
3113
0
                for (comp_num = spot_start; comp_num < num_comp; comp_num++) {
3114
0
                    buf_ptr[position + planestride * comp_num] = 0;
3115
0
                }
3116
0
            } else if (a == 0xffff) {
3117
#if ARCH_IS_BIG_ENDIAN
3118
#else
3119
                /* Convert from native -> big endian */
3120
0
                for (comp_num = 0; comp_num < num_comp; comp_num++) {
3121
0
                    comp = buf_ptr[position + planestride * comp_num];
3122
0
                    ((byte*)&buf_ptr[position + planestride * comp_num])[0] = comp >> 8;
3123
0
                    ((byte*)&buf_ptr[position + planestride * comp_num])[1] = comp;
3124
0
                }
3125
0
#endif
3126
0
            } else {
3127
0
                a ^= 0xffff;
3128
0
                a += a >> 15; /* a is now 0 to 0x10000 */
3129
0
                a >>= 1; /* We can only use 15 bits as bg-comp has a sign bit we can't lose */
3130
0
                for (comp_num = 0; comp_num < spot_start; comp_num++) {
3131
0
                    comp = buf_ptr[position + planestride * comp_num];
3132
0
                    tmp = ((0xffff - comp) * a) + 0x4000;
3133
0
                    comp += (tmp >> 15); /* Errors in bit 16 upwards will be ignored */
3134
                    /* Store as big endian */
3135
0
                    ((byte*)&buf_ptr[position + planestride * comp_num])[0] = comp >> 8;
3136
0
                    ((byte*)&buf_ptr[position + planestride * comp_num])[1] = comp;
3137
0
                }
3138
0
                for (comp_num = spot_start; comp_num < num_comp; comp_num++) {
3139
0
                    comp = buf_ptr[position + planestride * comp_num];
3140
0
                    tmp = ((0 - comp) * a) + 0x4000;
3141
0
                    comp += (tmp >> 15); /* Errors in bit 16 upwards will be ignored */
3142
                    /* Store as big endian */
3143
0
                    ((byte*)&buf_ptr[position + planestride * comp_num])[0] = comp >> 8;
3144
0
                    ((byte*)&buf_ptr[position + planestride * comp_num])[1] = comp;
3145
0
                }
3146
0
            }
3147
0
            position += 1;
3148
0
        }
3149
0
    }
3150
0
}
3151
3152
static int
3153
pdf14_put_blended_image_cmykspot(gx_device* dev, gx_device* target,
3154
    gs_gstate* pgs, pdf14_buf* buf, int planestride_in,
3155
    int rowstride_in, int x0, int y0, int width, int height,
3156
    int num_comp, uint16_t bg, bool has_tags, gs_int_rect rect_in,
3157
    gs_separations* pseparations, bool deep)
3158
6.37k
{
3159
6.37k
    pdf14_device* pdev = (pdf14_device*)dev;
3160
6.37k
    int code = 0;
3161
6.37k
    int y;
3162
6.37k
    int num_rows_left;
3163
6.37k
    int i;
3164
6.37k
    gs_int_rect rect = rect_in;
3165
6.37k
    int planestride = planestride_in;
3166
6.37k
    int rowstride = rowstride_in;
3167
6.37k
    byte* buf_ptr = NULL;
3168
6.37k
    cmm_profile_t* src_profile = buf->group_color_info->icc_profile;
3169
6.37k
    cmm_profile_t* des_profile = NULL;
3170
6.37k
    cmm_dev_profile_t* dev_target_profile;
3171
6.37k
    cmm_dev_profile_t* pdf14dev_profile;
3172
6.37k
    bool color_mismatch = false;
3173
6.37k
    bool supports_alpha = false;
3174
6.37k
    const byte* buf_ptrs[GS_CLIENT_COLOR_MAX_COMPONENTS];
3175
6.37k
    int alpha_offset = num_comp;
3176
6.37k
    int tag_offset = has_tags ? num_comp + 1 : 0;
3177
6.37k
    gs_color_space *pcs;
3178
6.37k
    gs_image1_t image;
3179
6.37k
    gx_image_enum_common_t *info;
3180
6.37k
    gx_image_plane_t planes[GS_IMAGE_MAX_COMPONENTS];
3181
6.37k
    pdf14_buf *cm_result = NULL;
3182
6.37k
    bool did_alloc;
3183
6.37k
    bool target_sep_device = dev_proc(target, dev_spec_op)(target, gxdso_supports_devn, NULL, 0);
3184
6.37k
    bool has_spots = pdev->ctx->num_spots > 0;
3185
6.37k
    bool blend_spots = !target_sep_device && has_spots;
3186
3187
    /* Check if group color space is CMYK based */
3188
6.37k
    code = dev_proc(target, get_profile)(target, &dev_target_profile);
3189
6.37k
    if (code < 0)
3190
0
        return code;
3191
6.37k
    if (dev_target_profile == NULL)
3192
0
        return gs_throw_code(gs_error_Fatal);
3193
3194
6.37k
    if (src_profile == NULL) {
3195
0
        code = dev_proc(dev, get_profile)(dev, &pdf14dev_profile);
3196
0
        if (code < 0) {
3197
0
            return code;
3198
0
        }
3199
0
        src_profile = pdf14dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE];
3200
0
    }
3201
3202
    /* If the target device does not support spot colors and we have spot colors
3203
       here due to overprint simulation (blend_spots == true), then we will need to convert the base
3204
       colors to CMYK if it is RGB or Gray so tha we can blend in the spot colors */
3205
6.37k
    if (blend_spots && src_profile->data_cs != gsCMYK) {
3206
3207
0
        cm_result = pdf14_transform_color_buffer_no_matte(pgs, pdev->ctx, (gx_device *)dev, buf,
3208
0
            buf->data, src_profile, pgs->icc_manager->default_cmyk, 0, 0, buf->rect.q.x,
3209
0
            buf->rect.q.y, &did_alloc, buf->deep, false);
3210
0
        if (cm_result == NULL)
3211
0
            return_error(gs_error_VMerror);
3212
3213
        /* Update */
3214
0
        buf = cm_result;
3215
0
        src_profile = pgs->icc_manager->default_cmyk;
3216
0
        num_comp = buf->n_chan - 1;
3217
0
        bg = 0;
3218
0
        tag_offset = has_tags ? num_comp + 1 : 0;
3219
0
        alpha_offset = num_comp;
3220
3221
#if RAW_DUMP
3222
        buf_ptr = buf->data + (rect.p.y - buf->rect.p.y) * buf->rowstride + ((rect.p.x - buf->rect.p.x) << deep);
3223
        dump_raw_buffer(target->memory, height, width, buf->n_planes, planestride, rowstride,
3224
            "convertbase_to_cmyk_for_spot_blend", buf_ptr, deep);
3225
        global_index++;
3226
#endif
3227
0
    }
3228
3229
    /* Fix order map if needed */
3230
29.1k
    for (i = 0; i < num_comp; i++) {
3231
22.7k
        pdev->devn_params.separation_order_map[i] = i;
3232
22.7k
    }
3233
3234
    /* Check if we have a color conversion issue */
3235
6.37k
    des_profile = dev_target_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE];
3236
6.37k
    if (!gsicc_profiles_equal(des_profile, src_profile))
3237
2.71k
        color_mismatch = true;
3238
3239
    /* Check if target supports alpha */
3240
6.37k
    supports_alpha = dev_proc(target, dev_spec_op)(target, gxdso_supports_alpha, NULL, 0);
3241
6.37k
    code = 0;
3242
3243
6.37k
    buf_ptr = buf->data + (rect.p.y - buf->rect.p.y) * buf->rowstride + ((rect.p.x - buf->rect.p.x) << deep);
3244
3245
    /* Note. The logic below will need a little rework if we ever
3246
       have a device that has tags and alpha support */
3247
6.37k
    if (supports_alpha) {
3248
3249
        /* If doing simulated overprint, Bring the spot color channels into
3250
           CMYK. Data is planar and 16 bit data in native format. */
3251
0
        if (pdev->overprint_sim && pdev->devn_params.page_spot_colors > 0) {
3252
0
            cmyk_composite_map cmyk_map[GX_DEVICE_MAX_SEPARATIONS];  /* Fracs */
3253
3254
            /* In the clist case, we need to get equiv spots out of the pseudo-band. */
3255
0
            if (pdev->pclist_device != NULL) {
3256
0
                gx_device_clist_reader *pcrdev = (gx_device_clist_reader *)(pdev->pclist_device);
3257
3258
0
                code = clist_read_op_equiv_cmyk_colors(pcrdev, &(pdev->op_pequiv_cmyk_colors));
3259
0
                if (code < 0)
3260
0
                    return code;
3261
0
            }
3262
0
            build_cmyk_map(dev, num_comp, &(pdev->op_pequiv_cmyk_colors), cmyk_map);
3263
3264
            /* Now we go to big endian */
3265
0
            pdf14_spots_to_cmyk(buf_ptr, width, height, rowstride,
3266
0
                planestride, num_comp, src_profile->num_comps,
3267
0
                tag_offset, cmyk_map, true, deep);
3268
3269
            /* Reset buffer information. We have CMYK+alpha and maybe tags */
3270
0
            buf->n_chan = buf->n_chan - buf->num_spots;
3271
0
            buf->n_planes = buf->n_planes - buf->num_spots;
3272
0
            buf->num_spots = 0;
3273
0
            num_comp = buf->n_chan - 1;
3274
0
            tag_offset = has_tags ? buf->n_planes - 1 : 0; /* Tags at end */
3275
0
        }
3276
3277
0
        if (!color_mismatch) {
3278
0
            for (i = 0; i < buf->n_planes; i++)
3279
0
                buf_ptrs[i] = buf_ptr + i * planestride;
3280
0
            code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
3281
0
                rect.p.x, rect.p.y, width, height,
3282
0
                rowstride, alpha_offset, tag_offset);
3283
            /* Right now code has number of rows written */
3284
0
        } else {
3285
            /* In this case, just color convert and maintain alpha.
3286
               This is a case where we either either blend in the
3287
               right color space and have no alpha for the output
3288
               device or hand back the wrong color space with
3289
               alpha data.  We choose the later. */
3290
0
            code = pdf14_put_image_color_convert(pdev, pgs, src_profile,
3291
0
                        dev_target_profile, &buf, &buf_ptr, false, rect.p.x,
3292
0
                        rect.p.y, width, height);
3293
0
            if (code < 0)
3294
0
                return code;
3295
3296
            /* reset */
3297
0
            rowstride = buf->rowstride;
3298
0
            planestride = buf->planestride;
3299
0
            num_comp = buf->n_chan - 1;
3300
0
            alpha_offset = num_comp;
3301
0
            tag_offset = buf->has_tags ? buf->n_chan : 0;
3302
3303
            /* And then out */
3304
0
            for (i = 0; i < buf->n_planes; i++)
3305
0
                buf_ptrs[i] = buf_ptr + i * planestride;
3306
0
            code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
3307
0
                rect.p.x, rect.p.y, width, height, rowstride, alpha_offset,
3308
0
                tag_offset);
3309
            /* Right now code has number of rows written.  Writing continues below */
3310
0
        }
3311
6.37k
    } else {
3312
        /* Device could not handle the alpha data (we actually don't have
3313
           a device that does spot colorants and has an alpha channel so
3314
           the above code is untested.  Go ahead and preblend now and then
3315
           color convert if needed */
3316
#if RAW_DUMP
3317
           /* Dump before and after the blend to make sure we are doing that ok */
3318
        dump_raw_buffer(target->memory, height, width, buf->n_planes, planestride, rowstride,
3319
            "pre_put_image_blend_image", buf_ptr, deep);
3320
        global_index++;
3321
#endif
3322
3323
6.37k
        if (color_mismatch && (src_profile->data_cs == gsRGB || src_profile->data_cs == gsGRAY)) {
3324
2.71k
            if (deep) {
3325
            /* In this case, we are NOT going to bring the spots into the CMYK
3326
               equivalent colors, since otherwise src_profile would be CMYK based.  So
3327
               16 bit data will be converted now from native endian to big endian during
3328
               the blending process */
3329
0
                pdf14_blend_image_mixed_buffer16(buf_ptr, width, height, rowstride,
3330
0
                    planestride, num_comp, src_profile->num_comps);
3331
2.71k
            } else {
3332
2.71k
                pdf14_blend_image_mixed_buffer(buf_ptr, width, height, rowstride,
3333
2.71k
                    planestride, num_comp, src_profile->num_comps);
3334
2.71k
            }
3335
3.66k
        } else {
3336
3.66k
            if (deep) {
3337
            /* In this case, if blend_spots == true, we will shortly be bringing
3338
               the spot colors to CMYK equivalent colors. It is at that time that
3339
               we will convert from native endian to big endian. In all other
3340
               cases this blending will due to conversion from native to BE */
3341
0
                bool keep_native = (blend_spots == true);
3342
3343
0
                gx_blend_image_buffer16(buf_ptr, width, height, rowstride,
3344
0
                    planestride, num_comp, bg, keep_native);
3345
3.66k
            } else {
3346
3.66k
                gx_blend_image_buffer(buf_ptr, width, height, rowstride,
3347
3.66k
                    planestride, num_comp, bg >> 8);
3348
3.66k
            }
3349
3.66k
        }
3350
3351
#if RAW_DUMP
3352
        dump_raw_buffer_be(target->memory, height, width, buf->n_planes, planestride, rowstride,
3353
            "post_put_image_blend_image", buf_ptr, deep);
3354
        global_index++;
3355
#endif
3356
3357
        /* If doing simulated overprint and we are not going to a sep device and
3358
           we have spot colors, then bring the spot color channels into CMYK
3359
           (We should have already converted our base color space to CMYK if it was RGB or gray).
3360
           At this point, data is planar and 16 bit data is still in native format. It is
3361
           here that 16 bit data will be converted to BE. Otherwise it will have been converted
3362
           above during the alpha blend operation. */
3363
6.37k
        if (blend_spots) {
3364
0
            cmyk_composite_map cmyk_map[GX_DEVICE_MAX_SEPARATIONS];  /* Fracs */
3365
3366
            /* In the clist case, we need to get equiv spots out of the
3367
               pseudo-band. */
3368
0
            if (pdev->pclist_device != NULL) {
3369
0
                gx_device_clist_reader *pcrdev = (gx_device_clist_reader *)(pdev->pclist_device);
3370
0
                code = clist_read_op_equiv_cmyk_colors(pcrdev, &(pdev->op_pequiv_cmyk_colors));
3371
0
                if (code < 0)
3372
0
                    return code;
3373
0
            }
3374
3375
0
            build_cmyk_map(dev, num_comp, &(pdev->op_pequiv_cmyk_colors), cmyk_map);
3376
0
            pdf14_spots_to_cmyk(buf_ptr, width, height, rowstride,
3377
0
                planestride, num_comp, src_profile->num_comps,
3378
0
                tag_offset, cmyk_map, false, deep);
3379
3380
            /* Reset buffer information. We have CMYK and maybe tags */
3381
0
            num_comp = 4;
3382
0
            alpha_offset = 0;
3383
0
            buf->n_chan = buf->n_chan - buf->num_spots - 1;     /* No spots or alpha */
3384
0
            buf->n_planes = buf->n_planes - buf->num_spots - 1; /* No spots or alpha */
3385
0
            tag_offset = has_tags ? buf->n_chan : 0;      /* Tags at end */
3386
0
            buf->num_spots = 0;
3387
3388
#if RAW_DUMP
3389
            dump_raw_buffer(target->memory, height, width, buf->n_planes, planestride, rowstride,
3390
                "post_put_image_spot_to_cmyk", buf_ptr, deep);
3391
            global_index++;
3392
#endif
3393
0
        }
3394
3395
        /* Map to the destination color space */
3396
6.37k
        if (color_mismatch) {
3397
2.71k
            code = pdf14_put_image_color_convert(pdev, pgs, src_profile, dev_target_profile,
3398
2.71k
                &buf, &buf_ptr, true, rect.p.x, rect.p.y, width, height);
3399
2.71k
            if (code < 0)
3400
0
                return code;
3401
3402
            /* reset */
3403
2.71k
            rowstride = buf->rowstride;
3404
2.71k
            planestride = buf->planestride;
3405
2.71k
            num_comp = buf->n_chan;
3406
2.71k
            tag_offset = buf->has_tags ? buf->n_chan : 0;
3407
2.71k
        }
3408
3409
#if RAW_DUMP
3410
        /* Dump after the CS transform */
3411
        dump_raw_buffer_be(target->memory, height, width, buf->n_planes, planestride, rowstride,
3412
            "post_put_image_color_convert", buf_ptr, deep);
3413
        global_index++;
3414
        /* clist_band_count++; */
3415
#endif
3416
3417
        /* Try put_image again. This can occur if the
3418
           target, like psdcmyk and tiffsep, support put_image */
3419
6.37k
        alpha_offset = 0;
3420
38.2k
        for (i = 0; i < buf->n_planes; i++)
3421
31.8k
            buf_ptrs[i] = buf_ptr + i * planestride;
3422
6.37k
        code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
3423
6.37k
            rect.p.x, rect.p.y, width, height,
3424
6.37k
            rowstride, alpha_offset, tag_offset);
3425
6.37k
    }
3426
3427
    /* Put image was succesful.  We processed some or all of the rows.
3428
       Continue until we are done */
3429
6.37k
    if (code > 0) {
3430
41
        num_rows_left = height - code;
3431
41
        while (num_rows_left > 0) {
3432
0
            code = dev_proc(target, put_image) (target, target, buf_ptrs, num_comp,
3433
0
                rect.p.x, rect.p.y + code, width, num_rows_left, rowstride,
3434
0
                alpha_offset, tag_offset);
3435
0
            if (code < 0) {
3436
0
                return code;
3437
0
            }
3438
0
            num_rows_left = num_rows_left - code;
3439
0
        }
3440
41
        return 0;
3441
41
    }
3442
3443
    /* Sep devices all support put_image (tiffsep and psdcmyk)
3444
       as well as those devices that support alpha (pngalpha,
3445
       png16malpha). If we are here, then we are doing an
3446
       overprint simulation on some other device. Image data
3447
       is aleady blended and in device color space. */
3448
6.33k
    code = gs_cspace_build_ICC(&pcs, NULL, pgs->memory);
3449
6.33k
    if (code < 0)
3450
0
        return code;
3451
3452
    /* Already in destination CS */
3453
6.33k
    pcs->cmm_icc_profile_data = des_profile;
3454
3455
    /* pcs takes a reference to the profile data it just retrieved. */
3456
6.33k
    gsicc_adjust_profile_rc(pcs->cmm_icc_profile_data, 1, "pdf14_put_blended_image_cmykspot");
3457
6.33k
    gsicc_set_icc_range(&(pcs->cmm_icc_profile_data));
3458
6.33k
    gs_image_t_init_adjust(&image, pcs, false);
3459
6.33k
    image.ImageMatrix.xx = (float)width;
3460
6.33k
    image.ImageMatrix.yy = (float)height;
3461
6.33k
    image.Width = width;
3462
6.33k
    image.Height = height;
3463
6.33k
    image.BitsPerComponent = deep ? 16 : 8;
3464
6.33k
    image.ColorSpace = pcs;
3465
6.33k
    image.format = gs_image_format_component_planar;
3466
3467
6.33k
    ctm_only_writable(pgs).xx = (float)width;
3468
6.33k
    ctm_only_writable(pgs).xy = 0;
3469
6.33k
    ctm_only_writable(pgs).yx = 0;
3470
6.33k
    ctm_only_writable(pgs).yy = (float)height;
3471
6.33k
    ctm_only_writable(pgs).tx = (float)rect.p.x;
3472
6.33k
    ctm_only_writable(pgs).ty = (float)rect.p.y;
3473
6.33k
    code = dev_proc(target, begin_typed_image) (target,
3474
6.33k
        pgs, NULL, (gs_image_common_t *)&image,
3475
6.33k
        NULL, NULL, NULL, pgs->memory, &info);
3476
6.33k
    if (code < 0) {
3477
0
        rc_decrement_only_cs(pcs, "pdf14_put_blended_image_cmykspot");
3478
0
        return code;
3479
0
    }
3480
#if RAW_DUMP
3481
    /* Dump the current buffer to see what we have. */
3482
    dump_raw_buffer(pdev->ctx->memory,
3483
        pdev->ctx->stack->rect.q.y - pdev->ctx->stack->rect.p.y,
3484
        pdev->ctx->stack->rect.q.x - pdev->ctx->stack->rect.p.x,
3485
        pdev->ctx->stack->n_planes,
3486
        pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
3487
        "put_image_final_big", pdev->ctx->stack->data, deep);
3488
    dump_raw_buffer(pdev->ctx->memory,
3489
        height, width, buf->n_planes,
3490
        pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
3491
        "put_image_final_small", buf_ptr, deep);
3492
    global_index++;
3493
    clist_band_count++;
3494
#endif
3495
3496
34.3k
    for (i = 0; i < num_comp; i++) {
3497
28.0k
        planes[i].data = buf_ptr + i * planestride;
3498
28.0k
        planes[i].data_x = 0;
3499
28.0k
        planes[i].raster = buf->rowstride;
3500
28.0k
    }
3501
3502
74.8k
    for (y = 0; y < height; y++) {
3503
68.4k
        int rows_used;
3504
3505
68.4k
        info->procs->plane_data(info, (const gx_image_plane_t*) &planes, 1, &rows_used);
3506
3507
373k
        for (i = 0; i < num_comp; i++) {
3508
304k
            planes[i].data += buf->rowstride;
3509
304k
        }
3510
68.4k
    }
3511
6.33k
    info->procs->end_image(info, true);
3512
3513
    /* This will also decrement the profile */
3514
6.33k
    rc_decrement_only_cs(pcs, "pdf14_put_blended_image_cmykspot");
3515
6.33k
    return code;
3516
6.33k
}
3517
3518
/**
3519
 * pdf14_cmykspot_put_image: Put rendered image to target device.
3520
 * @pdev: The PDF 1.4 rendering device.
3521
 * @pgs: State for image draw operation.
3522
 * @target: The target device.
3523
 *
3524
 * Puts the rendered image in @pdev's buffer to @target. This is called
3525
 * as part of the sequence of popping the PDF 1.4 device filter.
3526
 *
3527
 * Return code: negative on error.
3528
 **/
3529
static  int
3530
pdf14_cmykspot_put_image(gx_device *dev, gs_gstate *pgs, gx_device *target)
3531
9.64k
{
3532
9.64k
    pdf14_device *pdev = (pdf14_device *)dev;
3533
9.64k
    pdf14_buf *buf = pdev->ctx->stack;
3534
9.64k
    gs_int_rect rect;
3535
9.64k
    int x1, y1, width, height;
3536
9.64k
    gs_devn_params *pdevn_params = &pdev->devn_params;
3537
9.64k
    gs_separations *pseparations = &pdevn_params->separations;
3538
9.64k
    int planestride;
3539
9.64k
    int rowstride;
3540
9.64k
    bool deep = pdev->ctx->deep;
3541
9.64k
    uint16_t bg;
3542
9.64k
    int num_comp;
3543
3544
    /* Nothing was ever drawn. */
3545
9.64k
    if (buf == NULL)
3546
2.17k
        return 0;
3547
3548
7.47k
    bg = buf->group_color_info->isadditive ? 65535 : 0;
3549
7.47k
    num_comp = buf->n_chan - 1;
3550
7.47k
    rect = buf->rect;
3551
7.47k
    planestride = buf->planestride;
3552
7.47k
    rowstride = buf->rowstride;
3553
3554
    /* Make sure that this is the only item on the stack. Fuzzing revealed a
3555
       potential problem. Bug 694190 */
3556
7.47k
    if (buf->saved != NULL) {
3557
0
        return gs_throw(gs_error_unknownerror, "PDF14 device push/pop out of sync");
3558
0
    }
3559
7.47k
    if_debug0m('v', dev->memory, "[v]pdf14_cmykspot_put_image\n");
3560
7.47k
    rect_intersect(rect, buf->dirty);
3561
7.47k
    x1 = min(pdev->width, rect.q.x);
3562
7.47k
    y1 = min(pdev->height, rect.q.y);
3563
7.47k
    width = x1 - rect.p.x;
3564
7.47k
    height = y1 - rect.p.y;
3565
7.47k
    if (width <= 0 || height <= 0 || buf->data == NULL)
3566
1.10k
        return 0;
3567
3568
#if RAW_DUMP
3569
    /* Dump the current buffer to see what we have. */
3570
    dump_raw_buffer(pdev->ctx->memory,
3571
                    pdev->ctx->stack->rect.q.y-pdev->ctx->stack->rect.p.y,
3572
                    pdev->ctx->stack->rect.q.x-pdev->ctx->stack->rect.p.x,
3573
                    pdev->ctx->stack->n_planes,
3574
                    pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
3575
                    "CMYK_SPOT_PUTIMAGE", pdev->ctx->stack->data,
3576
                    pdev->ctx->stack->deep);
3577
3578
    global_index++;
3579
    clist_band_count++;
3580
#endif
3581
3582
6.37k
    return pdf14_put_blended_image_cmykspot(dev, target, pgs,
3583
6.37k
                      buf, planestride, rowstride,
3584
6.37k
                      rect.p.x, rect.p.y, width, height, num_comp, bg,
3585
6.37k
                      buf->has_tags, rect, pseparations, deep);
3586
7.47k
}
3587
3588
/**
3589
 * pdf14_custom_put_image: Put rendered image to target device.
3590
 * @pdev: The PDF 1.4 rendering device.
3591
 * @pgs: State for image draw operation.
3592
 * @target: The target device.
3593
 *
3594
 * Puts the rendered image in @pdev's buffer to @target. This is called
3595
 * as part of the sequence of popping the PDF 1.4 device filter.
3596
 *
3597
 * Return code: negative on error.
3598
 **/
3599
static  int
3600
pdf14_custom_put_image(gx_device * dev, gs_gstate * pgs, gx_device * target)
3601
0
{
3602
0
    pdf14_device * pdev = (pdf14_device *)dev;
3603
0
    pdf14_buf *buf = pdev->ctx->stack;
3604
0
    bool deep = pdev->ctx->deep;
3605
0
    gs_int_rect rect;
3606
0
    int x0, y0;
3607
0
    int planestride;
3608
0
    int rowstride;
3609
0
    int num_comp;
3610
0
    uint16_t bg;
3611
0
    int x1, y1, width, height;
3612
0
    byte *buf_ptr;
3613
3614
    /* Nothing was ever drawn. */
3615
0
    if (buf == NULL)
3616
0
        return 0;
3617
3618
0
    bg = pdev->ctx->additive ? 0xffff : 0;
3619
0
    num_comp = buf->n_chan - 1;
3620
0
    rect = buf->rect;
3621
0
    x0 = rect.p.x;
3622
0
    y0 = rect.p.y;
3623
0
    planestride = buf->planestride;
3624
0
    rowstride = buf->rowstride;
3625
3626
    /* Make sure that this is the only item on the stack. Fuzzing revealed a
3627
       potential problem. Bug 694190 */
3628
0
    if (buf->saved != NULL) {
3629
0
        return gs_throw(gs_error_unknownerror, "PDF14 device push/pop out of sync");
3630
0
    }
3631
0
    if_debug0m('v', dev->memory, "[v]pdf14_custom_put_image\n");
3632
0
    rect_intersect(rect, buf->dirty);
3633
0
    x1 = min(pdev->width, rect.q.x);
3634
0
    y1 = min(pdev->height, rect.q.y);
3635
0
    width = x1 - rect.p.x;
3636
0
    height = y1 - rect.p.y;
3637
0
    if (width <= 0 || height <= 0 || buf->data == NULL)
3638
0
        return 0;
3639
0
    buf_ptr = buf->data + (rect.p.y - buf->rect.p.y) * buf->rowstride + ((rect.p.x - buf->rect.p.x)<<deep);
3640
3641
0
    return gx_put_blended_image_custom(target, buf_ptr,
3642
0
                      planestride, rowstride,
3643
0
                      x0, y0, width, height, num_comp, bg, deep);
3644
0
}
3645
3646
/* This is rather nasty: in the event we are interrupted (by an error) between a push and pop
3647
 * of one or more groups, we have to cycle through any ICC profile changes since the push
3648
 * putting everything back how it was, and cleaning up the reference counts.
3649
 */
3650
static void pdf14_cleanup_group_color_profiles (pdf14_device *pdev)
3651
531k
{
3652
531k
    if (pdev->ctx && pdev->ctx->stack) {
3653
233k
        pdf14_buf *buf, *next;
3654
3655
233k
        for (buf = pdev->ctx->stack->saved; buf != NULL; buf = next) {
3656
22
            pdf14_group_color_t *group_color_info = buf->group_color_info;
3657
22
            next = buf->saved;
3658
44
            while (group_color_info) {
3659
22
               if (group_color_info->icc_profile != NULL) {
3660
22
                   cmm_profile_t *group_profile;
3661
22
                   gsicc_rendering_param_t render_cond;
3662
22
                   cmm_dev_profile_t *dev_profile;
3663
22
                   int code = dev_proc((gx_device *)pdev, get_profile)((gx_device *)pdev,  &dev_profile);
3664
3665
22
                   if (code >= 0) {
3666
22
                       gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &group_profile,
3667
22
                                             &render_cond);
3668
3669
22
                       gsicc_adjust_profile_rc(pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE],
3670
22
                                               -1, "pdf14_end_transparency_group");
3671
22
                       pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] =
3672
22
                           group_color_info->icc_profile;
3673
22
                       group_color_info->icc_profile = NULL;
3674
22
                   }
3675
22
               }
3676
3677
22
               group_color_info = group_color_info->previous;
3678
22
            }
3679
22
        }
3680
233k
    }
3681
531k
}
3682
3683
static  int
3684
pdf14_close(gx_device *dev)
3685
267k
{
3686
267k
    pdf14_device *pdev = (pdf14_device *)dev;
3687
3688
267k
    pdf14_cleanup_group_color_profiles(pdev);
3689
3690
267k
    if (pdev->ctx) {
3691
261k
        pdf14_ctx_free(pdev->ctx);
3692
261k
        pdev->ctx = NULL;
3693
261k
    }
3694
267k
    return 0;
3695
267k
}
3696
3697
/* This is called when something has gone wrong and the interpreter received a
3698
   stop while in the middle of doing something with the PDF14 device.  We need
3699
   to clean up and end this in a graceful manner */
3700
static int
3701
pdf14_discard_trans_layer(gx_device *dev, gs_gstate * pgs)
3702
0
{
3703
0
    pdf14_device *pdev = (pdf14_device *)dev;
3704
    /* The things that need to be cleaned up */
3705
0
    pdf14_ctx *ctx = pdev->ctx;
3706
0
    pdf14_smaskcolor_t *smaskcolor = pdev->smaskcolor;
3707
0
    pdf14_group_color_t *group_color = pdev->color_model_stack;
3708
3709
    /* Free up the smask color */
3710
0
    if (smaskcolor != NULL) {
3711
0
        smaskcolor->ref_count = 1;
3712
0
        pdf14_decrement_smask_color(pgs, dev);
3713
0
        pdev->smaskcolor = NULL;
3714
0
    }
3715
3716
    /* Free up the nested color procs and decrement the profiles */
3717
0
    if (group_color != NULL) {
3718
0
        while (group_color->previous != NULL)
3719
0
            pdf14_pop_group_color(dev, pgs);
3720
0
        gs_free_object(dev->memory->stable_memory, group_color, "pdf14_discard_trans_layer");
3721
0
        pdev->color_model_stack = NULL;
3722
0
    }
3723
3724
    /* Start the context clean up */
3725
0
    if (ctx != NULL) {
3726
0
        pdf14_buf *buf, *next;
3727
0
        pdf14_group_color_t *procs, *prev_procs;
3728
3729
0
        if (ctx->mask_stack != NULL) {
3730
0
            pdf14_free_mask_stack(ctx, ctx->memory);
3731
0
        }
3732
3733
        /* Now the stack of buffers */
3734
0
        for (buf = ctx->stack; buf != NULL; buf = next) {
3735
0
            next = buf->saved;
3736
3737
0
            gs_free_object(ctx->memory, buf->transfer_fn, "pdf14_discard_trans_layer");
3738
0
            gs_free_object(ctx->memory, buf->matte, "pdf14_discard_trans_layer");
3739
0
            gs_free_object(ctx->memory, buf->data, "pdf14_discard_trans_layer");
3740
0
            gs_free_object(ctx->memory, buf->backdrop, "pdf14_discard_trans_layer");
3741
            /* During the soft mask push, the mask_stack was copied (not moved) from
3742
               the ctx to the tos mask_stack. We are done with this now so it is safe
3743
               to free this one object */
3744
0
            gs_free_object(ctx->memory, buf->mask_stack, "pdf14_discard_trans_layer");
3745
0
            for (procs = buf->group_color_info; procs != NULL; procs = prev_procs) {
3746
0
                prev_procs = procs->previous;
3747
0
                gs_free_object(ctx->memory, procs, "pdf14_discard_trans_layer");
3748
0
            }
3749
0
            gs_free_object(ctx->memory, buf, "pdf14_discard_trans_layer");
3750
0
        }
3751
        /* Finally the context itself */
3752
0
        gs_free_object(ctx->memory, ctx, "pdf14_discard_trans_layer");
3753
0
        pdev->ctx = NULL;
3754
0
    }
3755
0
    return 0;
3756
0
}
3757
3758
static  int
3759
pdf14_output_page(gx_device * dev, int num_copies, int flush)
3760
0
{
3761
0
    pdf14_device * pdev = (pdf14_device *)dev;
3762
3763
0
    if (pdev->target != NULL)
3764
0
        return (*dev_proc(pdev->target, output_page)) (pdev->target, num_copies, flush);
3765
0
    return 0;
3766
0
}
3767
3768
1.85M
#define COPY_PARAM(p) dev->p = target->p
3769
1.32M
#define COPY_ARRAY_PARAM(p) memcpy(dev->p, target->p, sizeof(dev->p))
3770
3771
/*
3772
 * Copy device parameters back from a target.  This copies all standard
3773
 * parameters related to page size and resolution, but not any of the
3774
 * color-related parameters, as the pdf14 device retains its own color
3775
 * handling. This routine is parallel to gx_device_copy_params().
3776
 * Note that it DOES copy the devn_params since these are required to
3777
 * keep agreement with colorant name->number mapping, and don't change
3778
 * with the pdf14 color handling.
3779
 */
3780
static  void
3781
gs_pdf14_device_copy_params(gx_device *dev, const gx_device *target)
3782
264k
{
3783
264k
    cmm_dev_profile_t *profile_targ;
3784
264k
    cmm_dev_profile_t *profile_dev14;
3785
264k
    pdf14_device *pdev = (pdf14_device*) dev;
3786
264k
    cmm_profile_t *blend_profile = NULL;
3787
264k
    int k;
3788
3789
264k
    COPY_PARAM(width);
3790
264k
    COPY_PARAM(height);
3791
264k
    COPY_ARRAY_PARAM(MediaSize);
3792
264k
    COPY_ARRAY_PARAM(ImagingBBox);
3793
264k
    COPY_PARAM(ImagingBBox_set);
3794
264k
    COPY_ARRAY_PARAM(HWResolution);
3795
264k
    COPY_ARRAY_PARAM(Margins);
3796
264k
    COPY_ARRAY_PARAM(HWMargins);
3797
264k
    COPY_PARAM(PageCount);
3798
264k
    COPY_PARAM(MaxPatternBitmap);
3799
264k
    COPY_PARAM(graphics_type_tag);
3800
264k
    COPY_PARAM(interpolate_control);
3801
264k
    memcpy(&(dev->space_params), &(target->space_params), sizeof(gdev_space_params));
3802
3803
264k
    if (dev->icc_struct == NULL) {
3804
264k
        dev->icc_struct = gsicc_new_device_profile_array(dev);
3805
264k
        profile_dev14 = dev->icc_struct;
3806
264k
        dev_proc((gx_device *) target, get_profile)((gx_device *) target,
3807
264k
                                          &(profile_targ));
3808
3809
1.32M
        for (k = 0; k < NUM_DEVICE_PROFILES; k++) {
3810
1.05M
            if (profile_targ->device_profile[k] != NULL) {
3811
264k
                gsicc_adjust_profile_rc(profile_targ->device_profile[k], 1, "gs_pdf14_device_copy_params");
3812
264k
            }
3813
1.05M
            if (profile_dev14->device_profile[k] != NULL) {
3814
0
                gsicc_adjust_profile_rc(profile_dev14->device_profile[k], -1, "gs_pdf14_device_copy_params");
3815
0
            }
3816
1.05M
            profile_dev14->device_profile[k] = profile_targ->device_profile[k];
3817
1.05M
            profile_dev14->rendercond[k] = profile_targ->rendercond[k];
3818
1.05M
        }
3819
3820
264k
        dev->icc_struct->devicegraytok = profile_targ->devicegraytok;
3821
264k
        dev->icc_struct->graydetection = profile_targ->graydetection;
3822
264k
        dev->icc_struct->pageneutralcolor = profile_targ->pageneutralcolor;
3823
264k
        dev->icc_struct->supports_devn = profile_targ->supports_devn;
3824
264k
        dev->icc_struct->usefastcolor = profile_targ->usefastcolor;
3825
264k
        dev->icc_struct->blacktext = profile_targ->blacktext;
3826
264k
        dev->icc_struct->blackvector = profile_targ->blackvector;
3827
264k
        dev->icc_struct->blackthresholdL = profile_targ->blackthresholdL;
3828
264k
        dev->icc_struct->blackthresholdC = profile_targ->blackthresholdC;
3829
3830
264k
        switch (pdev->blend_cs_state) {
3831
264k
            case PDF14_BLEND_CS_UNSPECIFIED:
3832
264k
            case PDF14_BLEND_CS_TARGET_CIELAB:
3833
                /* PDF14_BLEND_CS_TARGET_CIELAB handled
3834
                   during the device push, when we have
3835
                   access to the pgs */
3836
264k
                break;
3837
0
            case PDF14_BLEND_CS_OUTPUTINTENT:
3838
0
                blend_profile = profile_targ->oi_profile;
3839
0
                break;
3840
0
            case PDF14_BLEND_CS_SPECIFIED:
3841
0
                blend_profile = profile_targ->blend_profile;
3842
0
                break;
3843
0
            default:
3844
0
                break;
3845
264k
        }
3846
3847
264k
        if (blend_profile != NULL) {
3848
            /* Set the device profile to the blend profile. Note only default profile is set */
3849
0
            gsicc_adjust_profile_rc(blend_profile, 1, "gs_pdf14_device_copy_params");
3850
0
            gsicc_adjust_profile_rc(profile_dev14->device_profile[GS_DEFAULT_DEVICE_PROFILE], -1, "gs_pdf14_device_copy_params");
3851
0
            profile_dev14->device_profile[GS_DEFAULT_DEVICE_PROFILE] = blend_profile;
3852
0
        }
3853
3854
264k
        profile_dev14->overprint_control = profile_targ->overprint_control;
3855
264k
    }
3856
264k
#undef COPY_ARRAY_PARAM
3857
264k
#undef COPY_PARAM
3858
264k
}
3859
3860
/*
3861
 * This is a forwarding version of the put_params device proc.  It is only
3862
 * used when the PDF 1.4 compositor devices are closed.  The routine will
3863
 * check if the target device has closed and, if so, close itself.  The routine
3864
 * also sync the device parameters.
3865
 */
3866
static  int
3867
pdf14_forward_put_params(gx_device * dev, gs_param_list * plist)
3868
0
{
3869
0
    pdf14_device * pdev = (pdf14_device *)dev;
3870
0
    gx_device * tdev = pdev->target;
3871
0
    bool was_open = tdev->is_open;
3872
0
    int code = 0;
3873
3874
0
    if (tdev != 0 && (code = dev_proc(tdev, put_params)(tdev, plist)) >= 0) {
3875
0
        gx_device_decache_colors(dev);
3876
0
        if (!tdev->is_open) {
3877
0
            code = gs_closedevice(dev);
3878
0
            if (code == 0)
3879
0
                code = was_open ? 1 : 0;   /* target device closed */
3880
0
        }
3881
0
        gx_device_copy_params(dev, tdev);
3882
0
    }
3883
0
    return code;
3884
0
}
3885
3886
/* Function prototypes */
3887
int put_param_pdf14_spot_names(gx_device * pdev,
3888
                gs_separations * pseparations, gs_param_list * plist);
3889
41.2k
#define PDF14NumSpotColorsParamName "PDF14NumSpotColors"
3890
3891
/*
3892
 * The put_params method for the PDF 1.4 device will check if the
3893
 * target device has closed and, if so, close itself.  Note:  This routine is
3894
 * currently being used by both the pdf14_clist_device and the pdf_device.
3895
 * Please make sure that any changes are either applicable to both devices
3896
 * or clone the routine for each device.
3897
 */
3898
static  int
3899
pdf14_put_params(gx_device * dev, gs_param_list * plist)
3900
0
{
3901
0
    pdf14_device * pdev = (pdf14_device *)dev;
3902
0
    gx_device * tdev = pdev->target;
3903
0
    bool was_open = tdev->is_open;
3904
0
    int code = 0;
3905
3906
0
    if (tdev != 0 && (code = dev_proc(tdev, put_params)(tdev, plist)) >= 0) {
3907
0
        gx_device_decache_colors(dev);
3908
0
        if (!tdev->is_open) {
3909
0
            code = gs_closedevice(dev);
3910
0
            if (code == 0)
3911
0
                code = was_open ? 1 : 0;   /* target device closed */
3912
0
        }
3913
0
        gs_pdf14_device_copy_params(dev, tdev);
3914
0
    }
3915
0
    return code;
3916
0
}
3917
3918
/*
3919
 * Copy marking related parameters into the PDF 1.4 device structure for use
3920
 * by pdf14_fill_rectangle.
3921
 */
3922
static  void
3923
pdf14_set_marking_params(gx_device *dev, const gs_gstate *pgs)
3924
6.73M
{
3925
6.73M
    pdf14_device * pdev = (pdf14_device *)dev;
3926
3927
6.73M
    if (pgs->alphaisshape) {
3928
74.2k
        pdev->opacity = 1.0;
3929
74.2k
        if (pgs->is_fill_color) {
3930
70.2k
            pdev->shape = pgs->fillconstantalpha;
3931
70.2k
        } else {
3932
3.99k
            pdev->shape = pgs->strokeconstantalpha;
3933
3.99k
        }
3934
6.65M
    } else {
3935
6.65M
        pdev->shape = 1.0;
3936
6.65M
        if (pgs->is_fill_color) {
3937
3.15M
            pdev->opacity = pgs->fillconstantalpha;
3938
3.50M
        } else {
3939
3.50M
            pdev->opacity = pgs->strokeconstantalpha;
3940
3.50M
        }
3941
6.65M
    }
3942
6.73M
    pdev->alpha = pdev->opacity * pdev->shape;
3943
6.73M
    pdev->blend_mode = pgs->blend_mode;
3944
6.73M
    if (pdev->icc_struct->overprint_control != gs_overprint_control_disable) {
3945
6.73M
        pdev->overprint = pgs->overprint;
3946
6.73M
        pdev->stroke_overprint = pgs->stroke_overprint;
3947
6.73M
    } else {
3948
0
        pdev->overprint = false;
3949
0
        pdev->stroke_overprint = false;
3950
0
    }
3951
3952
6.73M
    pdev->fillconstantalpha = pgs->fillconstantalpha;
3953
6.73M
    pdev->strokeconstantalpha = pgs->strokeconstantalpha;
3954
3955
6.73M
    if (pgs->is_fill_color)
3956
3.22M
        pdev->op_state = PDF14_OP_STATE_FILL;
3957
3.50M
    else
3958
3.50M
        pdev->op_state = PDF14_OP_STATE_STROKE;
3959
3960
6.73M
    if_debug6m('v', dev->memory,
3961
6.73M
               "[v]set_marking_params, opacity = %g, shape = %g, bm = %d, op = %d, eop = %d seop = %d\n",
3962
6.73M
               pdev->opacity, pdev->shape, pgs->blend_mode, pgs->overprint, pdev->effective_overprint_mode,
3963
6.73M
               pdev->stroke_effective_op_mode);
3964
6.73M
}
3965
3966
static  void
3967
update_lop_for_pdf14(gs_gstate *pgs, const gx_drawing_color *pdcolor)
3968
5.10M
{
3969
5.10M
    bool hastrans = false;
3970
3971
    /* We'd really rather not have to set the pdf14 bit in the lop, as this
3972
     * makes other operations much slower. We have no option however, if the
3973
     * current colour involves transparency, or if it's anything other than
3974
     * a completely solid (or transparent) operation in the normal blend mode.
3975
     */
3976
5.10M
    if (pdcolor != NULL)
3977
5.10M
    {
3978
5.10M
        if (gx_dc_is_pattern1_color(pdcolor) &&
3979
5.10M
            gx_pattern1_get_transptr(pdcolor) != NULL) {
3980
6.11k
            hastrans = true;
3981
5.10M
        } else if (gx_dc_is_pattern2_color(pdcolor)) {
3982
            /* FIXME: Here we assume that ALL type 2 patterns are
3983
             * transparent - this test could be better. */
3984
11.0k
            hastrans = true;
3985
11.0k
        }
3986
5.10M
    }
3987
    /* The only idempotent blend modes are Normal, Darken and Lighten.
3988
       This appears to be the only place where this test is done so
3989
       not adding a is_idempotent method */
3990
5.10M
    if ((pgs->blend_mode != BLEND_MODE_Normal &&
3991
5.10M
        pgs->blend_mode != BLEND_MODE_Darken &&
3992
5.10M
        pgs->blend_mode != BLEND_MODE_Lighten) ||
3993
5.10M
        (pgs->fillconstantalpha != 1.0) ||
3994
5.10M
        (pgs->strokeconstantalpha != 1.0) ||
3995
5.10M
        (hastrans))
3996
172k
    {
3997
        /*
3998
         * The blend operations are not idempotent.  Force non-idempotent
3999
         * filling and stroking operations.
4000
         */
4001
172k
        pgs->log_op |= lop_pdf14;
4002
172k
    }
4003
5.10M
}
4004
4005
static int
4006
push_shfill_group(pdf14_clist_device *pdev,
4007
                  gs_gstate *pgs,
4008
                  gs_fixed_rect *box)
4009
8
{
4010
8
    gs_transparency_group_params_t params = { 0 };
4011
8
    int code;
4012
8
    gs_rect cb;
4013
8
    gs_gstate fudged_pgs = *pgs;
4014
4015
8
    params.shade_group = true;
4016
4017
    /* gs_begin_transparency_group takes a bbox that it then
4018
     * transforms by ctm. Our bbox has already been transformed,
4019
     * so clear out the ctm. */
4020
8
    fudged_pgs.ctm.xx = 1.0;
4021
8
    fudged_pgs.ctm.xy = 0;
4022
8
    fudged_pgs.ctm.yx = 0;
4023
8
    fudged_pgs.ctm.yy = 1.0;
4024
8
    fudged_pgs.ctm.tx = 0;
4025
8
    fudged_pgs.ctm.ty = 0;
4026
8
    cb.p.x = fixed2int_pixround(box->p.x);
4027
8
    cb.p.y = fixed2int_pixround(box->p.y);
4028
8
    cb.q.x = fixed2int_pixround(box->q.x);
4029
8
    cb.q.y = fixed2int_pixround(box->q.y);
4030
4031
8
    params.Isolated = false;
4032
8
    params.Knockout = true;
4033
8
    params.page_group = false;
4034
8
    params.group_opacity = fudged_pgs.fillconstantalpha;
4035
8
    params.group_shape = 1.0;
4036
8
    code = gs_begin_transparency_group(&fudged_pgs, &params, &cb, PDF14_BEGIN_TRANS_GROUP);
4037
4038
    /* We have the group handle the blendmode and the opacity,
4039
     * and continue with the existing graphics state reset
4040
     * to normal, opaque operation. We could do it the other
4041
     * way around, but this way means that if we push a knockout
4042
     * group for a stroke, and then the code calls back into
4043
     * the fill operation as part of doing the stroking, we don't
4044
     * push another one. */
4045
8
    gs_setblendmode(pgs, BLEND_MODE_Normal);
4046
8
    gs_setfillconstantalpha(pgs, 1.0);
4047
8
    gs_setstrokeconstantalpha(pgs, 1.0);
4048
8
    if (pdev) {
4049
8
        code = pdf14_clist_update_params(pdev, pgs, false, NULL);
4050
8
        if (code < 0)
4051
0
            return code;
4052
8
    }
4053
4054
8
    return code;
4055
8
}
4056
4057
static int
4058
pop_shfill_group(gs_gstate *pgs)
4059
8
{
4060
8
     return gs_end_transparency_group(pgs);
4061
8
}
4062
4063
static int
4064
pdf14_fill_path(gx_device *dev, const gs_gstate *pgs,
4065
                           gx_path *ppath, const gx_fill_params *params,
4066
                           const gx_drawing_color *pdcolor,
4067
                           const gx_clip_path *pcpath)
4068
3.70M
{
4069
3.70M
    gs_gstate new_pgs = *pgs;
4070
3.70M
    int code = 0;
4071
3.70M
    gs_pattern2_instance_t *pinst = NULL;
4072
3.70M
    int push_group = 0;
4073
4074
3.70M
    code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
4075
3.70M
        dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, pgs);
4076
3.70M
    if (code < 0)
4077
0
        return code;
4078
4079
3.70M
    if (pdcolor == NULL)
4080
0
       return_error(gs_error_unknownerror);  /* color must be defined */
4081
3.70M
    ((pdf14_device *)dev)->op_state = pgs->is_fill_color ? PDF14_OP_STATE_FILL : PDF14_OP_STATE_STROKE;
4082
3.70M
    if (gx_dc_is_pattern1_color(pdcolor)){
4083
94.0k
        if( gx_pattern1_get_transptr(pdcolor) != NULL ||
4084
94.0k
            gx_pattern1_clist_has_trans(pdcolor) ){
4085
            /* In this case, we need to push a transparency group
4086
               and tile the pattern color, which is stored in
4087
               a pdf14 device buffer in the ctile object memember
4088
               variable ttrans */
4089
#if RAW_DUMP
4090
            /* Since we do not get a put_image to view what
4091
               we have do it now */
4092
            if (gx_pattern1_get_transptr(pdcolor) != NULL) {
4093
                const pdf14_device * ppatdev14 = (const pdf14_device *)
4094
                                pdcolor->colors.pattern.p_tile->ttrans->pdev14;
4095
                if (ppatdev14 != NULL) {  /* can occur during clist reading */
4096
                    byte *buf_ptr = ppatdev14->ctx->stack->data  +
4097
                        ppatdev14->ctx->stack->rect.p.y *
4098
                        ppatdev14->ctx->stack->rowstride +
4099
                        ppatdev14->ctx->stack->rect.p.x;
4100
                    dump_raw_buffer(ppatdev14->ctx->memory,
4101
                                    (ppatdev14->ctx->stack->rect.q.y -
4102
                                     ppatdev14->ctx->stack->rect.p.y),
4103
                                    (ppatdev14->ctx->stack->rect.q.x -
4104
                                     ppatdev14->ctx->stack->rect.p.x),
4105
                                    ppatdev14->ctx->stack->n_planes,
4106
                                    ppatdev14->ctx->stack->planestride,
4107
                                    ppatdev14->ctx->stack->rowstride,
4108
                                    "Pattern_Fill", buf_ptr,
4109
                                    ppatdev14->ctx->stack->deep);
4110
                    global_index++;
4111
                } else {
4112
                     gx_pattern_trans_t *patt_trans =
4113
                                        pdcolor->colors.pattern.p_tile->ttrans;
4114
                     dump_raw_buffer(patt_trans->mem,
4115
                                     patt_trans->rect.q.y-patt_trans->rect.p.y,
4116
                                     patt_trans->rect.q.x-patt_trans->rect.p.x,
4117
                                     patt_trans->n_chan,
4118
                                     patt_trans->planestride, patt_trans->rowstride,
4119
                                     "Pattern_Fill_clist",
4120
                                     patt_trans->transbytes +
4121
                                         patt_trans->rect.p.y * patt_trans->rowstride +
4122
                                         (patt_trans->rect.p.x<<patt_trans->deep),
4123
                                     patt_trans->deep);
4124
                    global_index++;
4125
                }
4126
            }
4127
#endif
4128
13.0k
            pdf14_set_marking_params(dev, &new_pgs);
4129
13.0k
            code = pdf14_tile_pattern_fill(dev, &new_pgs, ppath,
4130
13.0k
                params, pdcolor, pcpath);
4131
13.0k
            new_pgs.trans_device = NULL;
4132
13.0k
            new_pgs.has_transparency = false;
4133
13.0k
            return code;
4134
13.0k
        }
4135
94.0k
    }
4136
3.69M
    if (gx_dc_is_pattern2_color(pdcolor) ||
4137
3.69M
        pdcolor->type == &gx_dc_devn_masked) {
4138
        /* Non-idempotent blends require a transparency
4139
         * group to be pushed because shadings might
4140
         * paint several pixels twice. */
4141
24
        push_group = pgs->fillconstantalpha != 1.0 ||
4142
24
               !blend_is_idempotent(gs_currentblendmode(pgs));
4143
24
        pinst =
4144
24
            (gs_pattern2_instance_t *)pdcolor->ccolor.pattern;
4145
24
        pinst->saved->has_transparency = true;
4146
        /* The transparency color space operations are driven
4147
           by the pdf14 clist writer device.  */
4148
24
        pinst->saved->trans_device = dev;
4149
24
    }
4150
3.69M
    if (push_group) {
4151
0
        gs_fixed_rect box;
4152
0
        if (pcpath)
4153
0
            gx_cpath_outer_box(pcpath, &box);
4154
0
        else
4155
0
            (*dev_proc(dev, get_clipping_box)) (dev, &box);
4156
0
        if (ppath) {
4157
0
            gs_fixed_rect path_box;
4158
4159
0
            gx_path_bbox(ppath, &path_box);
4160
0
            if (box.p.x < path_box.p.x)
4161
0
                box.p.x = path_box.p.x;
4162
0
            if (box.p.y < path_box.p.y)
4163
0
                box.p.y = path_box.p.y;
4164
0
            if (box.q.x > path_box.q.x)
4165
0
                box.q.x = path_box.q.x;
4166
0
            if (box.q.y > path_box.q.y)
4167
0
                box.q.y = path_box.q.y;
4168
0
        }
4169
        /* Group alpha set from fill value. push_shfill_group does reset to 1.0 */
4170
0
        code = push_shfill_group(NULL, &new_pgs, &box);
4171
0
    } else
4172
3.69M
        update_lop_for_pdf14(&new_pgs, pdcolor);
4173
3.69M
    pdf14_set_marking_params(dev, &new_pgs);
4174
3.69M
    if (code >= 0) {
4175
3.69M
        new_pgs.trans_device = dev;
4176
3.69M
        new_pgs.has_transparency = true;
4177
        /* ppath can permissibly be NULL here, if we want to have a
4178
         * shading or a pattern fill the clipping path. This upsets
4179
         * coverity, which is not smart enough to realise that the
4180
         * validity of a NULL ppath depends on the type of pdcolor.
4181
         * We'll mark it as a false positive. */
4182
3.69M
        code = gx_default_fill_path(dev, &new_pgs, ppath, params, pdcolor, pcpath);
4183
3.69M
        new_pgs.trans_device = NULL;
4184
3.69M
        new_pgs.has_transparency = false;
4185
3.69M
    }
4186
3.69M
    if (code >= 0 && push_group) {
4187
0
        code = pop_shfill_group(&new_pgs);
4188
0
        pdf14_set_marking_params(dev, pgs);
4189
0
    }
4190
3.69M
    if (pinst != NULL){
4191
24
        pinst->saved->trans_device = NULL;
4192
24
    }
4193
3.69M
    return code;
4194
3.70M
}
4195
4196
static  int
4197
pdf14_stroke_path(gx_device *dev, const gs_gstate *pgs,
4198
                             gx_path *ppath, const gx_stroke_params *params,
4199
                             const gx_drawing_color *pdcolor,
4200
                             const gx_clip_path *pcpath)
4201
386k
{
4202
386k
    gs_gstate new_pgs = *pgs;
4203
386k
    int push_group = 0;
4204
386k
    int code = 0;
4205
4206
386k
    if (pdcolor == NULL)
4207
0
       return_error(gs_error_unknownerror);  /* color must be defined */
4208
4209
386k
    code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
4210
386k
        dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, pgs);
4211
386k
    if (code < 0)
4212
0
        return code;
4213
4214
386k
    if (gx_dc_is_pattern2_color(pdcolor)) {
4215
        /* Non-idempotent blends require a transparency
4216
         * group to be pushed because shadings might
4217
         * paint several pixels twice. */
4218
0
        push_group = pgs->strokeconstantalpha != 1.0 ||
4219
0
               !blend_is_idempotent(gs_currentblendmode(pgs));
4220
0
    }
4221
386k
    if (push_group) {
4222
0
        gs_fixed_rect box;
4223
0
        if (pcpath)
4224
0
            gx_cpath_outer_box(pcpath, &box);
4225
0
        else
4226
0
            (*dev_proc(dev, get_clipping_box)) (dev, &box);
4227
4228
        /* For fill_path, we accept ppath == NULL to mean
4229
         * fill the entire clipping region. That makes no
4230
         * sense for stroke_path, hence ppath is always non
4231
         * NULL here. */
4232
0
        {
4233
0
            gs_fixed_rect path_box;
4234
0
            gs_fixed_point expansion;
4235
4236
0
            gx_path_bbox(ppath, &path_box);
4237
            /* Expand the path bounding box by the scaled line width. */
4238
0
            if (gx_stroke_path_expansion(pgs, ppath, &expansion) < 0) {
4239
                /* The expansion is so large it caused a limitcheck. */
4240
0
                path_box.p.x = path_box.p.y = min_fixed;
4241
0
                path_box.q.x = path_box.q.y = max_fixed;
4242
0
            } else {
4243
0
                expansion.x += pgs->fill_adjust.x;
4244
0
                expansion.y += pgs->fill_adjust.y;
4245
                /*
4246
                 * It's theoretically possible for the following computations to
4247
                 * overflow, so we need to check for this.
4248
                 */
4249
0
                path_box.p.x = (path_box.p.x < min_fixed + expansion.x ? min_fixed :
4250
0
                                path_box.p.x - expansion.x);
4251
0
                path_box.p.y = (path_box.p.y < min_fixed + expansion.y ? min_fixed :
4252
0
                                path_box.p.y - expansion.y);
4253
0
                path_box.q.x = (path_box.q.x > max_fixed - expansion.x ? max_fixed :
4254
0
                                path_box.q.x + expansion.x);
4255
0
                path_box.q.y = (path_box.q.y > max_fixed - expansion.y ? max_fixed :
4256
0
                                path_box.q.y + expansion.y);
4257
0
            }
4258
0
            if (box.p.x < path_box.p.x)
4259
0
                box.p.x = path_box.p.x;
4260
0
            if (box.p.y < path_box.p.y)
4261
0
                box.p.y = path_box.p.y;
4262
0
            if (box.q.x > path_box.q.x)
4263
0
                box.q.x = path_box.q.x;
4264
0
            if (box.q.y > path_box.q.y)
4265
0
                box.q.y = path_box.q.y;
4266
0
        }
4267
        /* Group alpha set from fill value. push_shfill_group does reset to 1.0 */
4268
0
        new_pgs.fillconstantalpha = new_pgs.strokeconstantalpha;
4269
0
        code = push_shfill_group(NULL, &new_pgs, &box);
4270
0
    } else
4271
386k
        update_lop_for_pdf14(&new_pgs, pdcolor);
4272
386k
    pdf14_set_marking_params(dev, &new_pgs);
4273
386k
    if (code >= 0) {
4274
386k
        PDF14_OP_FS_STATE save_op_state = ((pdf14_device *)dev)->op_state;
4275
4276
386k
        ((pdf14_device*)dev)->op_state = PDF14_OP_STATE_STROKE;
4277
386k
        code = gx_default_stroke_path(dev, &new_pgs, ppath, params, pdcolor, pcpath);
4278
386k
        ((pdf14_device*)dev)->op_state = save_op_state;
4279
386k
    }
4280
386k
    if (code >= 0 && push_group) {
4281
0
        code = pop_shfill_group(&new_pgs);
4282
0
        pdf14_set_marking_params(dev, pgs);
4283
0
    }
4284
4285
386k
    return code;
4286
386k
}
4287
4288
/* Pull out steps of transparency updates for fill/stroke
4289
   so that they can be invoked elsewhere (e.g.
4290
   when the abuf device is handling the stroke/fill */
4291
4292
/* Set-up prior to fill operation in fill-stroke */
4293
static int
4294
pdf14_fill_stroke_prefill(gx_device* dev, gs_gstate* pgs, gx_path* ppath,
4295
    const gx_clip_path* pcpath, float fill_alpha, float stroke_alpha,
4296
    gs_blend_mode_t blend_mode, bool* op_ca_eq_CA, bool* path_empty, gs_log2_scale_point path_log2scale)
4297
6.08k
{
4298
6.08k
    int code = 0;
4299
6.08k
    gs_transparency_group_params_t params = { 0 };
4300
6.08k
    gs_fixed_rect clip_bbox;
4301
6.08k
    gs_rect bbox, group_stroke_box;
4302
6.08k
    gs_fixed_rect path_bbox;
4303
6.08k
    int expansion_code;
4304
6.08k
    gs_fixed_point expansion;
4305
6.08k
    pdf14_device* p14dev = (pdf14_device*)dev;
4306
4307
6.08k
    *path_empty = false;
4308
4309
6.08k
    if ((pgs->fillconstantalpha == 0.0 && pgs->strokeconstantalpha == 0.0) ||
4310
6.08k
        (pgs->ctm.xx == 0.0 && pgs->ctm.xy == 0.0 && pgs->ctm.yx == 0.0 && pgs->ctm.yy == 0.0))
4311
7
        return 0;
4312
4313
6.08k
    code = gx_curr_fixed_bbox(pgs, &clip_bbox, NO_PATH);
4314
6.08k
    if (code < 0 && code != gs_error_unknownerror)
4315
0
        return code;
4316
4317
6.08k
    if (code == gs_error_unknownerror) {
4318
        /* didn't get clip box from gx_curr_fixed_bbox */
4319
0
        clip_bbox.p.x = clip_bbox.p.y = 0;
4320
0
        clip_bbox.q.x = int2fixed(dev->width);
4321
0
        clip_bbox.q.y = int2fixed(dev->height);
4322
0
    }
4323
6.08k
    if (pcpath)
4324
6.08k
        rect_intersect(clip_bbox, pcpath->outer_box);
4325
4326
    /* expand the ppath using stroke expansion rule, then intersect it */
4327
6.08k
    code = gx_path_bbox(ppath, &path_bbox);
4328
4329
    /* If we are coming from the abuf device, the path has been scaled
4330
       by a factor (see alpha_buffer_init).  Undo the scaling here so
4331
       on the path_bbox so that we get the proper bounding box for our group. */
4332
6.08k
    if (path_log2scale.x != 0 || path_log2scale.y != 0) {
4333
0
        path_bbox.p.x = path_bbox.p.x >> path_log2scale.x;
4334
0
        path_bbox.q.x = path_bbox.q.x >> path_log2scale.x;
4335
0
        path_bbox.p.y = path_bbox.p.y >> path_log2scale.y;
4336
0
        path_bbox.q.y = path_bbox.q.y >> path_log2scale.y;
4337
0
    }
4338
4339
6.08k
    if (code == gs_error_nocurrentpoint && ppath->segments->contents.subpath_first == 0) {
4340
3.04k
        *path_empty = true;
4341
3.04k
        return 0; /* ignore empty path -- could try to send back a positive code for this but
4342
                     there are simply too many return cases that I can't account for. */
4343
3.04k
    }
4344
3.03k
    if (code < 0)
4345
0
        return code;
4346
4347
3.03k
    expansion_code = gx_stroke_path_expansion(pgs, ppath, &expansion);
4348
3.03k
    if (expansion_code >= 0) {
4349
2.64k
        path_bbox.p.x -= expansion.x;
4350
2.64k
        path_bbox.p.y -= expansion.y;
4351
2.64k
        path_bbox.q.x += expansion.x;
4352
2.64k
        path_bbox.q.y += expansion.y;
4353
2.64k
    }
4354
3.03k
    rect_intersect(path_bbox, clip_bbox);
4355
3.03k
    bbox.p.x = fixed2float(path_bbox.p.x);
4356
3.03k
    bbox.p.y = fixed2float(path_bbox.p.y);
4357
3.03k
    bbox.q.x = fixed2float(path_bbox.q.x);
4358
3.03k
    bbox.q.y = fixed2float(path_bbox.q.y);
4359
4360
3.03k
    code = gs_bbox_transform_inverse(&bbox, &ctm_only(pgs), &group_stroke_box);
4361
3.03k
    if (code < 0)
4362
0
        return code;
4363
4364
3.03k
    if (p14dev->overprint != pgs->overprint || p14dev->stroke_overprint != pgs->stroke_overprint) {
4365
0
        p14dev->overprint = pgs->overprint;
4366
0
        p14dev->stroke_overprint = pgs->stroke_overprint;
4367
0
    }
4368
4369
    /* See if overprint is enabled for both stroke and fill AND if ca == CA */
4370
3.03k
    if (fill_alpha == stroke_alpha &&
4371
3.03k
        p14dev->overprint && p14dev->stroke_overprint &&
4372
3.03k
        dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE) {
4373
4374
        /* Push a non-isolated non-knockout group with alpha = 1.0 and
4375
           compatible overprint mode.  Group will be composited with
4376
           original alpha and blend mode */
4377
0
        *op_ca_eq_CA = true;
4378
0
        params.Isolated = false;
4379
0
        params.group_color_type = UNKNOWN;
4380
0
        params.Knockout = false;
4381
0
        params.page_group = false;
4382
0
        params.group_opacity = 1.0;
4383
0
        params.group_shape = fill_alpha;
4384
4385
        /* non-isolated non-knockout group pushed with original alpha and blend mode */
4386
0
        code = gs_begin_transparency_group(pgs, &params, &group_stroke_box, PDF14_BEGIN_TRANS_GROUP);
4387
0
        if (code < 0)
4388
0
            return code;
4389
4390
        /* Change fill alpha to 1.0 and blend mode to compatible overprint for actual drawing */
4391
0
        (void)gs_setfillconstantalpha(pgs, 1.0);
4392
0
        (void)gs_setblendmode(pgs, BLEND_MODE_CompatibleOverprint); /* Can never fail */
4393
4394
3.03k
    } else {
4395
        /* Push a non-isolated knockout group. Do not change the alpha or
4396
            blend modes. Note: we need to draw those that have alpha = 0 */
4397
3.03k
        *op_ca_eq_CA = false;
4398
3.03k
        params.Isolated = false;
4399
3.03k
        params.group_color_type = UNKNOWN;
4400
3.03k
        params.Knockout = true;
4401
3.03k
        params.page_group = false;
4402
3.03k
        params.group_shape = 1.0;
4403
3.03k
        params.group_opacity = 1.0;
4404
4405
        /* non-isolated knockout group is pushed with alpha = 1.0 and Normal blend mode */
4406
3.03k
        (void)gs_setblendmode(pgs, BLEND_MODE_Normal); /* Can never fail */
4407
3.03k
        code = gs_begin_transparency_group(pgs, &params, &group_stroke_box, PDF14_BEGIN_TRANS_GROUP);
4408
3.03k
        if (code < 0)
4409
0
            return code;
4410
4411
        /* restore blend mode for actual drawing in the group */
4412
3.03k
        (void)gs_setblendmode(pgs, blend_mode); /* Can never fail */
4413
4414
        /* If we are in an overprint situation, set the blend mode to compatible
4415
            overprint */
4416
3.03k
        if ((p14dev->icc_struct->overprint_control != gs_overprint_control_disable) && pgs->overprint &&
4417
3.03k
            dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE)
4418
0
            (void)gs_setblendmode(pgs, BLEND_MODE_CompatibleOverprint); /* Can never fail */
4419
3.03k
    }
4420
3.03k
    p14dev->op_state = PDF14_OP_STATE_FILL;
4421
3.03k
    return code;
4422
3.03k
}
4423
4424
/* Set-up prior to stroke operation in fill-stroke */
4425
static void
4426
pdf14_fill_stroke_prestroke(gx_device* dev, gs_gstate* pgs, float stroke_alpha,
4427
    gs_blend_mode_t blend_mode, bool op_ca_eq_CA)
4428
3.04k
{
4429
3.04k
    pdf14_device* p14dev = (pdf14_device*)dev;
4430
4431
3.04k
    if (op_ca_eq_CA) {
4432
7
        (void)gs_setstrokeconstantalpha(pgs, 1.0);
4433
3.03k
    } else {
4434
3.03k
        if ((p14dev->icc_struct->overprint_control != gs_overprint_control_disable) && pgs->overprint &&
4435
3.03k
            dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE)
4436
0
            (void)gs_setblendmode(pgs, blend_mode); /* Can never fail */
4437
4438
        /* Note that the stroke can end up doing fill methods */
4439
3.03k
        (void)gs_setfillconstantalpha(pgs, stroke_alpha);
4440
4441
3.03k
        if ((p14dev->icc_struct->overprint_control != gs_overprint_control_disable) && pgs->stroke_overprint &&
4442
3.03k
            dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE)
4443
0
            (void)gs_setblendmode(pgs, BLEND_MODE_CompatibleOverprint); /* Can never fail */
4444
3.03k
    }
4445
3.04k
    p14dev->op_state = PDF14_OP_STATE_STROKE;
4446
3.04k
}
4447
4448
/* Cleanup after the stroke in fill-stroke  */
4449
static void
4450
pdf14_fill_stroke_poststroke(gx_device* dev, gs_gstate* pgs, float fill_alpha, bool op_ca_eq_CA)
4451
3.04k
{
4452
3.04k
    if (!op_ca_eq_CA) {
4453
        /* Bug 703324 we need to reset the fill constant alpha in the graphics
4454
          * state to the correct saved value. We also need to reset the 'opacity' member of the
4455
          * device, because some device methods (eg fill_masked_image) don't take a graphics
4456
          * state pointer as a parameter and so are unable to set the opacity value themselves.
4457
          * We therefore need to make sure it is set according to the current fill state.
4458
          */
4459
0
        (void)gs_setfillconstantalpha(pgs, fill_alpha);
4460
0
        pdf14_set_marking_params(dev, pgs);
4461
0
    }
4462
3.04k
}
4463
4464
/* cleanup in fill-stroke  */
4465
static int
4466
pdf14_fill_stroke_cleanup(gx_device* dev, gs_gstate* pgs, float fill_alpha, float stroke_alpha,
4467
    gs_blend_mode_t blend_mode, PDF14_OP_FS_STATE save_op_state)
4468
3.04k
{
4469
3.04k
    pdf14_device* p14dev = (pdf14_device*)dev;
4470
3.04k
    int code2;
4471
3.04k
    int code = 0;
4472
4473
    /* Restore the state */
4474
3.04k
    p14dev->op_state = save_op_state;
4475
3.04k
    (void)gs_setblendmode(pgs, blend_mode); /* Can never fail */
4476
3.04k
    (void)gs_setstrokeconstantalpha(pgs, stroke_alpha);
4477
3.04k
    (void)gs_setfillconstantalpha(pgs, fill_alpha);
4478
4479
3.04k
    code2 = gs_end_transparency_group(pgs);
4480
3.04k
    if (code2 < 0) {
4481
        /* At this point things have gone very wrong. We should just shut down */
4482
0
        code = gs_abort_pdf14trans_device(pgs);
4483
0
        return code2;
4484
0
    }
4485
3.04k
    return code;
4486
3.04k
}
4487
4488
static int
4489
pdf14_fill_stroke_path(gx_device *dev, const gs_gstate *cpgs, gx_path *ppath,
4490
    const gx_fill_params *fill_params, const gx_drawing_color *pdcolor_fill,
4491
    const gx_stroke_params *stroke_params, const gx_drawing_color *pdcolor_stroke,
4492
    const gx_clip_path *pcpath)
4493
30.8k
{
4494
30.8k
    bool op_ca_eq_CA;
4495
30.8k
    bool path_empty;
4496
30.8k
    int code;
4497
30.8k
    float stroke_alpha = cpgs->strokeconstantalpha;
4498
30.8k
    float fill_alpha = cpgs->fillconstantalpha;
4499
30.8k
    gs_blend_mode_t blend_mode = cpgs->blend_mode;
4500
30.8k
    pdf14_device* p14dev = (pdf14_device*)dev;
4501
30.8k
    PDF14_OP_FS_STATE save_op_state = p14dev->op_state;
4502
30.8k
    gs_log2_scale_point path_log2scale;
4503
30.8k
    bool group_needed = true;
4504
30.8k
    gx_device* curr_pgs_dev = cpgs->device;
4505
4506
30.8k
    union {
4507
30.8k
        const gs_gstate* cpgs;
4508
30.8k
        gs_gstate* pgs;
4509
30.8k
    } const_breaker;
4510
30.8k
    gs_gstate* pgs;
4511
4512
    /* Break const just once, neatly */
4513
30.8k
    const_breaker.cpgs = cpgs;
4514
30.8k
    pgs = const_breaker.pgs;
4515
30.8k
    path_log2scale.x = 0;
4516
30.8k
    path_log2scale.y = 0;
4517
4518
30.8k
    code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
4519
30.8k
        dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, pgs);
4520
30.8k
    if (code < 0)
4521
0
        return code;
4522
4523
    /* From looking at what AR is doing, it appears that if alpha is 1 and
4524
     * blend is normal we don't do a group push. Just do the stroke
4525
     * and the fill, even with overprint */
4526
30.8k
    if (stroke_alpha == 1 && fill_alpha == 1 && blend_mode == BLEND_MODE_Normal)
4527
24.7k
        group_needed = false;
4528
4529
30.8k
    if (group_needed) {
4530
6.08k
        pgs->device = dev; /* This is needed due to the gs_trans calls.  This method
4531
                              can be called on the clist writer side when dealing
4532
                              with the abuf/pdf14 interaction. Those calls have to
4533
                              go through the gs_trans API not the gx_trans or pdf14
4534
                              methods.  Perhaps these methods should have a different
4535
                              suffix, but they are static methods here in the pdf14
4536
                              file. */
4537
6.08k
        code = pdf14_fill_stroke_prefill(dev, pgs, ppath, pcpath, fill_alpha, stroke_alpha,
4538
6.08k
            blend_mode, &op_ca_eq_CA, &path_empty, path_log2scale);
4539
6.08k
        pgs->device = curr_pgs_dev;
4540
6.08k
        if (code < 0)
4541
0
            goto cleanup;
4542
6.08k
        if (path_empty)
4543
3.04k
            return 0;
4544
6.08k
    }
4545
4546
27.7k
    code = pdf14_fill_path(dev, pgs, ppath, fill_params, pdcolor_fill, pcpath);
4547
27.7k
    if (code < 0)
4548
0
        goto cleanup;
4549
4550
27.7k
    if (group_needed)
4551
3.04k
        pdf14_fill_stroke_prestroke(dev, pgs, stroke_alpha, blend_mode, op_ca_eq_CA);
4552
27.7k
    gs_swapcolors_quick(pgs);
4553
4554
4555
#if RAW_DUMP
4556
    /* Dump the current buffer to see what we have. */
4557
    dump_raw_buffer(p14dev->ctx->memory,
4558
        p14dev->ctx->stack->rect.q.y - p14dev->ctx->stack->rect.p.y,
4559
        p14dev->ctx->stack->rowstride >> p14dev->ctx->stack->deep, p14dev->ctx->stack->n_planes,
4560
        p14dev->ctx->stack->planestride, p14dev->ctx->stack->rowstride,
4561
        "BeforeStrokeOnFillStroke", p14dev->ctx->stack->data, p14dev->ctx->stack->deep);
4562
    global_index++;
4563
#endif
4564
4565
27.7k
    code = pdf14_stroke_path(dev, pgs, ppath, stroke_params, pdcolor_stroke, pcpath);
4566
27.7k
    gs_swapcolors_quick(pgs);
4567
27.7k
    if (code < 0) {
4568
0
        goto cleanup;
4569
0
    }
4570
4571
#if RAW_DUMP
4572
    /* Dump the current buffer to see what we have. */
4573
    dump_raw_buffer(p14dev->ctx->memory,
4574
        p14dev->ctx->stack->rect.q.y - p14dev->ctx->stack->rect.p.y,
4575
        p14dev->ctx->stack->rowstride >> p14dev->ctx->stack->deep, p14dev->ctx->stack->n_planes,
4576
        p14dev->ctx->stack->planestride, p14dev->ctx->stack->rowstride,
4577
        "AfterStrokeOnFillStroke", p14dev->ctx->stack->data, p14dev->ctx->stack->deep);
4578
    global_index++;
4579
#endif
4580
27.7k
    if (group_needed)
4581
3.04k
        pdf14_fill_stroke_poststroke(dev, pgs, fill_alpha, save_op_state);
4582
4583
27.7k
cleanup:
4584
27.7k
    if (group_needed) {
4585
3.04k
        pgs->device = dev; /* This is needed due to the gs_trans calls */
4586
3.04k
        code = pdf14_fill_stroke_cleanup(dev, pgs, fill_alpha, stroke_alpha, blend_mode,
4587
3.04k
            save_op_state);
4588
3.04k
        pgs->device = curr_pgs_dev;
4589
3.04k
    }
4590
27.7k
    return code;
4591
27.7k
}
4592
4593
static int
4594
pdf14_copy_alpha(gx_device * dev, const byte * data, int data_x,
4595
           int aa_raster, gx_bitmap_id id, int x, int y, int w, int h,
4596
                      gx_color_index color, int depth)
4597
0
{
4598
0
    return pdf14_copy_alpha_color(dev, data, data_x, aa_raster, id, x, y, w, h,
4599
0
                                  color, NULL, depth, false);
4600
0
}
4601
4602
static int
4603
pdf14_copy_alpha_hl_color(gx_device * dev, const byte * data, int data_x,
4604
           int aa_raster, gx_bitmap_id id, int x, int y, int w, int h,
4605
                      const gx_drawing_color *pdcolor, int depth)
4606
0
{
4607
0
    return pdf14_copy_alpha_color(dev, data, data_x, aa_raster, id, x, y, w, h,
4608
0
                                  0, pdcolor, depth, true);
4609
0
}
4610
4611
static int
4612
do_pdf14_copy_alpha_color(gx_device * dev, const byte * data, int data_x,
4613
                          int aa_raster, gx_bitmap_id id, int x, int y,
4614
                          int w, int h, gx_color_index color,
4615
                          const gx_device_color *pdc, int depth, bool devn)
4616
0
{
4617
0
    const byte *aa_row;
4618
0
    pdf14_device *pdev = (pdf14_device *)dev;
4619
0
    pdf14_buf *buf = pdev->ctx->stack;
4620
0
    int i, j, k;
4621
0
    byte *line, *dst_ptr;
4622
0
    byte src[PDF14_MAX_PLANES];
4623
0
    byte dst[PDF14_MAX_PLANES] = { 0 };
4624
0
    gs_blend_mode_t blend_mode = pdev->blend_mode;
4625
0
    bool additive = pdev->ctx->additive;
4626
0
    int rowstride = buf->rowstride;
4627
0
    int planestride = buf->planestride;
4628
0
    gs_graphics_type_tag_t curr_tag = GS_UNKNOWN_TAG;  /* Quiet compiler */
4629
0
    bool has_alpha_g = buf->has_alpha_g;
4630
0
    bool has_shape = buf->has_shape;
4631
0
    bool has_tags = buf->has_tags;
4632
0
    bool knockout = buf->knockout;
4633
0
    bool tag_blend = blend_mode == BLEND_MODE_Normal ||
4634
0
        blend_mode == BLEND_MODE_Compatible ||
4635
0
        blend_mode == BLEND_MODE_CompatibleOverprint;
4636
0
    int num_chan = buf->n_chan;
4637
0
    int num_comp = num_chan - 1;
4638
0
    int shape_off = num_chan * planestride;
4639
0
    int alpha_g_off = shape_off + (has_shape ? planestride : 0);
4640
0
    int tag_off = alpha_g_off + (has_alpha_g ? planestride : 0);
4641
0
    bool overprint = pdev->op_state == PDF14_OP_STATE_FILL ? pdev->overprint : pdev->stroke_overprint;
4642
0
    gx_color_index drawn_comps = pdev->op_state == PDF14_OP_STATE_FILL ?
4643
0
                                 pdev->drawn_comps_fill : pdev->drawn_comps_stroke;
4644
0
    gx_color_index comps;
4645
0
    byte shape = 0; /* Quiet compiler. */
4646
0
    byte src_alpha;
4647
0
    int alpha2_aa, alpha_aa, sx;
4648
0
    int alpha_aa_act;
4649
0
    int xoff;
4650
0
    gx_color_index mask = ((gx_color_index)1 << 8) - 1;
4651
0
    int shift = 8;
4652
4653
0
    if (buf->data == NULL)
4654
0
        return 0;
4655
0
    aa_row = data;
4656
0
    if (has_tags) {
4657
0
        curr_tag = (color >> (num_comp*8)) & 0xff;
4658
0
    }
4659
4660
0
    if (devn) {
4661
0
        if (additive) {
4662
0
            for (j = 0; j < num_comp; j++) {
4663
0
                src[j] = ((pdc->colors.devn.values[j]) >> shift & mask);
4664
0
            }
4665
0
        } else {
4666
0
            for (j = 0; j < num_comp; j++) {
4667
0
                src[j] = 255 - ((pdc->colors.devn.values[j]) >> shift & mask);
4668
0
            }
4669
0
        }
4670
0
    } else
4671
0
        pdev->pdf14_procs->unpack_color(num_comp, color, pdev, src);
4672
0
    src_alpha = src[num_comp] = (byte)floor (255 * pdev->alpha + 0.5);
4673
0
    if (has_shape)
4674
0
        shape = (byte)floor (255 * pdev->shape + 0.5);
4675
    /* Limit the area we write to the bounding rectangle for this buffer */
4676
0
    if (x < buf->rect.p.x) {
4677
0
        xoff = data_x + buf->rect.p.x - x;
4678
0
        w += x - buf->rect.p.x;
4679
0
        x = buf->rect.p.x;
4680
0
    } else {
4681
0
        xoff = data_x;
4682
0
    }
4683
0
    if (y < buf->rect.p.y) {
4684
0
      h += y - buf->rect.p.y;
4685
0
      aa_row -= (y - buf->rect.p.y) * aa_raster;
4686
0
      y = buf->rect.p.y;
4687
0
    }
4688
0
    if (x + w > buf->rect.q.x) w = buf->rect.q.x - x;
4689
0
    if (y + h > buf->rect.q.y) h = buf->rect.q.y - y;
4690
    /* Update the dirty rectangle. */
4691
0
    if (x < buf->dirty.p.x) buf->dirty.p.x = x;
4692
0
    if (y < buf->dirty.p.y) buf->dirty.p.y = y;
4693
0
    if (x + w > buf->dirty.q.x) buf->dirty.q.x = x + w;
4694
0
    if (y + h > buf->dirty.q.y) buf->dirty.q.y = y + h;
4695
0
    line = buf->data + (x - buf->rect.p.x) + (y - buf->rect.p.y) * rowstride;
4696
4697
0
    for (j = 0; j < h; ++j, aa_row += aa_raster) {
4698
0
        dst_ptr = line;
4699
0
        sx = xoff;
4700
0
        for (i = 0; i < w; ++i, ++sx) {
4701
            /* Complement the components for subtractive color spaces */
4702
0
            if (additive) {
4703
0
                for (k = 0; k < num_chan; ++k)   /* num_chan includes alpha */
4704
0
                    dst[k] = dst_ptr[k * planestride];
4705
0
            } else { /* Complement the components for subtractive color spaces */
4706
0
                for (k = 0; k < num_comp; ++k)
4707
0
                    dst[k] = 255 - dst_ptr[k * planestride];
4708
0
                dst[num_comp] = dst_ptr[num_comp * planestride];  /* alpha */
4709
0
            }
4710
            /* Get the aa alpha from the buffer */
4711
0
            switch(depth)
4712
0
            {
4713
0
            case 2:  /* map 0 - 3 to 0 - 255 */
4714
0
                alpha_aa = ((aa_row[sx >> 2] >> ((3 - (sx & 3)) << 1)) & 3) * 85;
4715
0
                break;
4716
0
            case 4:
4717
0
                alpha2_aa = aa_row[sx >> 1];
4718
0
                alpha_aa = (sx & 1 ? alpha2_aa & 0xf : alpha2_aa >> 4) * 17;
4719
0
                break;
4720
0
            case 8:
4721
0
                alpha_aa = aa_row[sx];
4722
0
                break;
4723
0
            default:
4724
0
                return_error(gs_error_rangecheck);
4725
0
            }
4726
0
            if (alpha_aa != 0) {  /* This does happen */
4727
0
                if (alpha_aa != 255) {
4728
                    /* We have an alpha value from aa */
4729
0
                    alpha_aa_act = alpha_aa;
4730
0
                    if (src_alpha != 255) {
4731
                        /* Need to combine it with the existing alpha */
4732
0
                        int tmp = src_alpha * alpha_aa_act + 0x80;
4733
0
                        alpha_aa_act = (tmp + (tmp >> 8)) >> 8;
4734
0
                    }
4735
                    /* Set our source alpha value appropriately */
4736
0
                    src[num_comp] = alpha_aa_act;
4737
0
                } else {
4738
                    /* We may have to reset this is it was changed as we
4739
                       moved across the row */
4740
0
                    src[num_comp] = src_alpha;
4741
0
                }
4742
0
                if (knockout) {
4743
0
                    if (buf->isolated) {
4744
0
                        art_pdf_knockoutisolated_group_8(dst, src, num_comp);
4745
0
                    } else {
4746
0
                        art_pdf_composite_knockout_8(dst, src, num_comp,
4747
0
                            blend_mode, pdev->blend_procs, pdev);
4748
0
                    }
4749
0
                } else {
4750
0
                    art_pdf_composite_pixel_alpha_8(dst, src, num_comp, blend_mode, num_comp,
4751
0
                                                    pdev->blend_procs, pdev);
4752
0
                }
4753
                /* Complement the results for subtractive color spaces */
4754
0
                if (additive) {
4755
0
                    for (k = 0; k < num_chan; ++k)
4756
0
                        dst_ptr[k * planestride] = dst[k];
4757
0
                } else {
4758
0
                    if (overprint && dst_ptr[num_comp * planestride] != 0) {
4759
0
                        for (k = 0, comps = drawn_comps; comps != 0;
4760
0
                                ++k, comps >>= 1) {
4761
0
                            if ((comps & 0x1) != 0) {
4762
0
                                dst_ptr[k * planestride] = 255 - dst[k];
4763
0
                            }
4764
0
                        }
4765
                        /* The alpha channel */
4766
0
                        dst_ptr[num_comp * planestride] = dst[num_comp];
4767
0
                    } else {
4768
0
                        for (k = 0; k < num_comp; ++k)
4769
0
                            dst_ptr[k * planestride] = 255 - dst[k];
4770
                        /* The alpha channel */
4771
0
                        dst_ptr[num_comp * planestride] = dst[num_comp];
4772
0
                    }
4773
0
                }
4774
0
                if (has_alpha_g) {
4775
0
                    int tmp = (255 - dst_ptr[alpha_g_off]) * (255 - src[num_comp]) + 0x80;
4776
0
                    dst_ptr[alpha_g_off] = 255 - ((tmp + (tmp >> 8)) >> 8);
4777
0
                }
4778
0
                if (has_shape) {
4779
0
                    int tmp = (255 - dst_ptr[shape_off]) * (255 - shape) + 0x80;
4780
0
                    dst_ptr[shape_off] = 255 - ((tmp + (tmp >> 8)) >> 8);
4781
0
                }
4782
0
                if (has_tags) {
4783
                    /* If alpha is 100% then set to curr_tag, else or */
4784
                    /* other than Normal BM, we always OR */
4785
0
                    if (src[num_comp] == 255 && tag_blend) {
4786
0
                        dst_ptr[tag_off] = curr_tag;
4787
0
                    } else {
4788
0
                        dst_ptr[tag_off] |= curr_tag;
4789
0
                    }
4790
0
                }
4791
0
            }
4792
0
            ++dst_ptr;
4793
0
        }
4794
0
        line += rowstride;
4795
0
    }
4796
0
    return 0;
4797
0
}
4798
4799
static int
4800
do_pdf14_copy_alpha_color_16(gx_device * dev, const byte * data, int data_x,
4801
                             int aa_raster, gx_bitmap_id id, int x, int y,
4802
                             int w, int h, gx_color_index color,
4803
                             const gx_device_color *pdc, int depth, bool devn)
4804
0
{
4805
0
    const byte *aa_row;
4806
0
    pdf14_device *pdev = (pdf14_device *)dev;
4807
0
    pdf14_buf *buf = pdev->ctx->stack;
4808
0
    int i, j, k;
4809
0
    byte *line;
4810
0
    uint16_t *dst_ptr;
4811
0
    uint16_t src[PDF14_MAX_PLANES];
4812
0
    uint16_t dst[PDF14_MAX_PLANES] = { 0 };
4813
0
    gs_blend_mode_t blend_mode = pdev->blend_mode;
4814
0
    bool tag_blend = blend_mode == BLEND_MODE_Normal ||
4815
0
        blend_mode == BLEND_MODE_Compatible ||
4816
0
        blend_mode == BLEND_MODE_CompatibleOverprint;
4817
0
    bool additive = pdev->ctx->additive;
4818
0
    int rowstride = buf->rowstride;
4819
0
    int planestride = buf->planestride;
4820
0
    gs_graphics_type_tag_t curr_tag = GS_UNKNOWN_TAG;  /* Quiet compiler */
4821
0
    bool has_alpha_g = buf->has_alpha_g;
4822
0
    bool has_shape = buf->has_shape;
4823
0
    bool has_tags = buf->has_tags;
4824
0
    bool knockout = buf->knockout;
4825
0
    int num_chan = buf->n_chan;
4826
0
    int num_comp = num_chan - 1;
4827
0
    int shape_off = num_chan * planestride;
4828
0
    int alpha_g_off = shape_off + (has_shape ? planestride : 0);
4829
0
    int tag_off = alpha_g_off + (has_alpha_g ? planestride : 0);
4830
0
    bool overprint = pdev->op_state == PDF14_OP_STATE_FILL ? pdev->overprint : pdev->stroke_overprint;
4831
0
    gx_color_index drawn_comps = pdev->op_state == PDF14_OP_STATE_FILL ?
4832
0
        pdev->drawn_comps_fill : pdev->drawn_comps_stroke;
4833
0
    gx_color_index comps;
4834
0
    uint16_t shape = 0; /* Quiet compiler. */
4835
0
    uint16_t src_alpha;
4836
0
    int alpha2_aa, alpha_aa, sx;
4837
0
    int alpha_aa_act;
4838
0
    int xoff;
4839
4840
0
    if (buf->data == NULL)
4841
0
        return 0;
4842
0
    aa_row = data;
4843
0
    if (has_tags) {
4844
0
        curr_tag = (color >> (num_comp*16)) & 0xff;
4845
0
    }
4846
4847
0
    if (devn) {
4848
0
        if (additive) {
4849
0
            for (j = 0; j < num_comp; j++) {
4850
0
                src[j] = pdc->colors.devn.values[j];
4851
0
            }
4852
0
        } else {
4853
0
            for (j = 0; j < num_comp; j++) {
4854
0
                src[j] = 65535 - pdc->colors.devn.values[j];
4855
0
            }
4856
0
        }
4857
0
    } else
4858
0
        pdev->pdf14_procs->unpack_color16(num_comp, color, pdev, src);
4859
0
    src_alpha = src[num_comp] = (uint16_t)floor (65535 * pdev->alpha + 0.5);
4860
0
    if (has_shape)
4861
0
        shape = (uint16_t)floor (65535 * pdev->shape + 0.5);
4862
    /* Limit the area we write to the bounding rectangle for this buffer */
4863
0
    if (x < buf->rect.p.x) {
4864
0
        xoff = data_x + buf->rect.p.x - x;
4865
0
        w += x - buf->rect.p.x;
4866
0
        x = buf->rect.p.x;
4867
0
    } else {
4868
0
        xoff = data_x;
4869
0
    }
4870
0
    if (y < buf->rect.p.y) {
4871
0
      h += y - buf->rect.p.y;
4872
0
      aa_row -= (y - buf->rect.p.y) * aa_raster;
4873
0
      y = buf->rect.p.y;
4874
0
    }
4875
0
    if (x + w > buf->rect.q.x) w = buf->rect.q.x - x;
4876
0
    if (y + h > buf->rect.q.y) h = buf->rect.q.y - y;
4877
    /* Update the dirty rectangle. */
4878
0
    if (x < buf->dirty.p.x) buf->dirty.p.x = x;
4879
0
    if (y < buf->dirty.p.y) buf->dirty.p.y = y;
4880
0
    if (x + w > buf->dirty.q.x) buf->dirty.q.x = x + w;
4881
0
    if (y + h > buf->dirty.q.y) buf->dirty.q.y = y + h;
4882
0
    line = buf->data + (x - buf->rect.p.x)*2 + (y - buf->rect.p.y) * rowstride;
4883
4884
0
    planestride >>= 1;
4885
0
    rowstride   >>= 1;
4886
0
    alpha_g_off >>= 1;
4887
0
    shape_off   >>= 1;
4888
0
    tag_off     >>= 1;
4889
0
    for (j = 0; j < h; ++j, aa_row += aa_raster) {
4890
0
        dst_ptr = (uint16_t *)(void *)line;
4891
0
        sx = xoff;
4892
0
        for (i = 0; i < w; ++i, ++sx) {
4893
            /* Complement the components for subtractive color spaces */
4894
0
            if (additive) {
4895
0
                for (k = 0; k < num_chan; ++k)   /* num_chan includes alpha */
4896
0
                    dst[k] = dst_ptr[k * planestride];
4897
0
            } else { /* Complement the components for subtractive color spaces */
4898
0
                for (k = 0; k < num_comp; ++k)
4899
0
                    dst[k] = 65535 - dst_ptr[k * planestride];
4900
0
                dst[num_comp] = dst_ptr[num_comp * planestride];  /* alpha */
4901
0
            }
4902
            /* Get the aa alpha from the buffer */
4903
0
            switch(depth)
4904
0
            {
4905
0
            case 2:  /* map 0 - 3 to 0 - 255 */
4906
0
                alpha_aa = ((aa_row[sx >> 2] >> ((3 - (sx & 3)) << 1)) & 3) * 85;
4907
0
                break;
4908
0
            case 4:
4909
0
                alpha2_aa = aa_row[sx >> 1];
4910
0
                alpha_aa = (sx & 1 ? alpha2_aa & 0xf : alpha2_aa >> 4) * 17;
4911
0
                break;
4912
0
            case 8:
4913
0
                alpha_aa = aa_row[sx];
4914
0
                break;
4915
0
            default:
4916
0
                return_error(gs_error_rangecheck);
4917
0
            }
4918
0
            if (alpha_aa != 0) {  /* This does happen */
4919
0
                if (alpha_aa != 255) {
4920
                    /* We have an alpha value from aa */
4921
0
                    alpha_aa_act = alpha_aa * 0x101;
4922
0
                    if (src_alpha != 65535) {
4923
                        /* Need to combine it with the existing alpha */
4924
0
                        int tmp = src_alpha * alpha_aa_act + 0x8000;
4925
0
                        alpha_aa_act = (tmp + (tmp >> 16)) >> 16;
4926
0
                    }
4927
                    /* Set our source alpha value appropriately */
4928
0
                    src[num_comp] = alpha_aa_act;
4929
0
                } else {
4930
                    /* We may have to reset this is it was changed as we
4931
                       moved across the row */
4932
0
                    src[num_comp] = src_alpha;
4933
0
                }
4934
0
                if (knockout) {
4935
0
                    if (buf->isolated) {
4936
0
                        art_pdf_knockoutisolated_group_16(dst, src, num_comp);
4937
0
                    } else {
4938
0
                        art_pdf_composite_knockout_16(dst, src, num_comp,
4939
0
                            blend_mode, pdev->blend_procs, pdev);
4940
0
                    }
4941
0
                } else {
4942
0
                    art_pdf_composite_pixel_alpha_16(dst, src, num_comp, blend_mode, num_comp,
4943
0
                                                     pdev->blend_procs, pdev);
4944
0
                }
4945
                /* Complement the results for subtractive color spaces */
4946
0
                if (additive) {
4947
0
                    for (k = 0; k < num_chan; ++k)
4948
0
                        dst_ptr[k * planestride] = dst[k];
4949
0
                } else {
4950
0
                    if (overprint && dst_ptr[num_comp * planestride] != 0) {
4951
0
                        for (k = 0, comps = drawn_comps; comps != 0;
4952
0
                                ++k, comps >>= 1) {
4953
0
                            if ((comps & 0x1) != 0) {
4954
0
                                dst_ptr[k * planestride] = 65535 - dst[k];
4955
0
                            }
4956
0
                        }
4957
                        /* The alpha channel */
4958
0
                        dst_ptr[num_comp * planestride] = dst[num_comp];
4959
0
                    } else {
4960
0
                        for (k = 0; k < num_comp; ++k)
4961
0
                            dst_ptr[k * planestride] = 65535 - dst[k];
4962
                        /* The alpha channel */
4963
0
                        dst_ptr[num_comp * planestride] = dst[num_comp];
4964
0
                    }
4965
0
                }
4966
0
                if (has_alpha_g) {
4967
0
                    int tmp = (65535 - dst_ptr[alpha_g_off]) * (65535 - src[num_comp]) + 0x8000;
4968
0
                    dst_ptr[alpha_g_off] = 65535 - ((tmp + (tmp >> 16)) >> 16);
4969
0
                }
4970
0
                if (has_shape) {
4971
0
                    int tmp = (65535 - dst_ptr[shape_off]) * (65535 - shape) + 0x8000;
4972
0
                    dst_ptr[shape_off] = 65535 - ((tmp + (tmp >> 16)) >> 16);
4973
0
                }
4974
0
                if (has_tags) {
4975
                    /* If alpha is 100% then set to curr_tag, else or */
4976
                    /* other than Normal BM, we always OR */
4977
0
                    if (src[num_comp] == 65535 && tag_blend) {
4978
0
                        dst_ptr[tag_off] = curr_tag;
4979
0
                    } else {
4980
0
                        dst_ptr[tag_off] |= curr_tag;
4981
0
                    }
4982
0
                }
4983
0
            }
4984
0
            ++dst_ptr;
4985
0
        }
4986
0
        line += rowstride;
4987
0
    }
4988
0
    return 0;
4989
0
}
4990
4991
static int
4992
pdf14_copy_alpha_color(gx_device * dev, const byte * data, int data_x,
4993
           int aa_raster, gx_bitmap_id id, int x, int y, int w, int h,
4994
                      gx_color_index color, const gx_device_color *pdc,
4995
                      int depth, bool devn)
4996
0
{
4997
0
    bool deep = device_is_deep(dev);
4998
0
    int code;
4999
5000
0
    code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
5001
0
        dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, NULL);
5002
0
    if (code < 0)
5003
0
        return code;
5004
5005
0
    if (deep)
5006
0
        return do_pdf14_copy_alpha_color_16(dev, data, data_x, aa_raster,
5007
0
                                            id, x, y, w, h,
5008
0
                                            color, pdc, depth, devn);
5009
0
    else
5010
0
        return do_pdf14_copy_alpha_color(dev, data, data_x, aa_raster,
5011
0
                                         id, x, y, w, h,
5012
0
                                         color, pdc, depth, devn);
5013
0
}
5014
5015
static  int
5016
pdf14_fill_mask(gx_device * orig_dev,
5017
                     const byte * data, int dx, int raster, gx_bitmap_id id,
5018
                     int x, int y, int w, int h,
5019
                     const gx_drawing_color * pdcolor, int depth,
5020
                     gs_logical_operation_t lop, const gx_clip_path * pcpath)
5021
5.42M
{
5022
5.42M
    gx_device *dev;
5023
5.42M
    pdf14_device *p14dev = (pdf14_device *)orig_dev;
5024
5.42M
    gx_device_clip cdev;
5025
5.42M
    gx_color_tile *ptile = NULL;
5026
5.42M
    int code = 0;
5027
5.42M
    gs_int_rect group_rect;
5028
5.42M
    gx_pattern_trans_t *fill_trans_buffer = NULL;
5029
5.42M
    bool has_pattern_trans = false;
5030
5.42M
    cmm_dev_profile_t *dev_profile;
5031
5032
5.42M
    if (pdcolor == NULL)
5033
0
        return_error(gs_error_unknownerror);  /* color must be defined */
5034
5035
5.42M
    code = pdf14_initialize_ctx(orig_dev, orig_dev->color_info.num_components,
5036
5.42M
        orig_dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, NULL);
5037
5.42M
    if (code < 0)
5038
0
        return code;
5039
5040
    /* If we are doing a fill with a pattern that has a transparency then
5041
       go ahead and do a push and a pop of the transparency group */
5042
5.42M
    if (gx_dc_is_pattern1_color(pdcolor)) {
5043
0
        if( gx_pattern1_get_transptr(pdcolor) != NULL) {
5044
0
            ptile = pdcolor->colors.pattern.p_tile;
5045
            /* Set up things in the ptile so that we get the proper
5046
               blending etc */
5047
            /* Set the blending procs and the is_additive setting based
5048
               upon the number of channels */
5049
0
            if (ptile->ttrans->n_chan-1 < 4) {
5050
0
                ptile->ttrans->blending_procs = &rgb_blending_procs;
5051
0
                ptile->ttrans->is_additive = true;
5052
0
            } else {
5053
0
                ptile->ttrans->blending_procs = &cmyk_blending_procs;
5054
0
                ptile->ttrans->is_additive = false;
5055
0
            }
5056
            /* Set the procs so that we use the proper filling method. */
5057
0
            gx_set_pattern_procs_trans((gx_device_color*) pdcolor);
5058
            /* Based upon if the tiles overlap pick the type of rect
5059
               fill that we will want to use */
5060
0
            if (ptile->has_overlap) {
5061
                /* This one does blending since there is tile overlap */
5062
0
                ptile->ttrans->pat_trans_fill = &tile_rect_trans_blend;
5063
0
            } else {
5064
                /* This one does no blending since there is no tile overlap */
5065
0
                ptile->ttrans->pat_trans_fill = &tile_rect_trans_simple;
5066
0
            }
5067
            /* Push the group */
5068
0
            group_rect.p.x = x;
5069
0
            group_rect.p.y = max(0,y);
5070
0
            group_rect.q.x = x + w;
5071
0
            group_rect.q.y = y + h;
5072
0
            if (!(w <= 0 || h <= 0)) {
5073
5074
0
                pdf14_group_color_t *group_color_info = pdf14_clone_group_color_info((gx_device *) p14dev, p14dev->ctx->stack->group_color_info);
5075
0
                if (group_color_info == NULL)
5076
0
                    return gs_error_VMerror;
5077
5078
0
                code = pdf14_push_transparency_group(p14dev->ctx, &group_rect,
5079
0
                     1, 0, 65535, 65535, 65535, ptile->blending_mode, 0, 0,
5080
0
                     ptile->ttrans->n_chan-1, false, false, NULL, NULL,
5081
0
                     group_color_info, NULL, NULL);
5082
0
                if (code < 0)
5083
0
                    return code;
5084
                /* Set up the output buffer information now that we have
5085
                   pushed the group */
5086
0
                fill_trans_buffer = new_pattern_trans_buff(p14dev->memory);
5087
0
                pdf14_get_buffer_information((gx_device *) p14dev,
5088
0
                                              fill_trans_buffer, NULL, false);
5089
                /* Store this in the appropriate place in pdcolor.  This
5090
                   is released later after the mask fill */
5091
0
                ptile->ttrans->fill_trans_buffer = fill_trans_buffer;
5092
0
                has_pattern_trans = true;
5093
0
            }
5094
0
        }
5095
0
    }
5096
5.42M
    if (pcpath != 0) {
5097
771k
        gx_make_clip_device_on_stack(&cdev, pcpath, orig_dev);
5098
771k
        dev = (gx_device *) & cdev;
5099
771k
    } else
5100
4.65M
        dev = orig_dev;
5101
5.42M
    if (depth > 1) {
5102
        /****** CAN'T DO ROP OR HALFTONE WITH ALPHA ******/
5103
0
        code = (*dev_proc(dev, copy_alpha))
5104
0
            (dev, data, dx, raster, id, x, y, w, h,
5105
0
             gx_dc_pure_color(pdcolor), depth);
5106
5.42M
    } else {
5107
5.42M
        code = pdcolor->type->fill_masked(pdcolor, data, dx, raster, id,
5108
5.42M
                                          x, y, w, h, dev, lop, false);
5109
5.42M
    }
5110
5.42M
    if (has_pattern_trans) {
5111
0
        if (code >= 0)
5112
0
            code = dev_proc(dev, get_profile)(dev,  &dev_profile);
5113
0
        if (code >= 0)
5114
0
            code = pdf14_pop_transparency_group(NULL, p14dev->ctx,
5115
0
                                                p14dev->blend_procs,
5116
0
                                                p14dev->color_info.num_components,
5117
0
                                                dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE],
5118
0
                                                orig_dev);
5119
0
        gs_free_object(p14dev->memory, ptile->ttrans->fill_trans_buffer,
5120
0
                       "pdf14_fill_mask");
5121
0
        ptile->ttrans->fill_trans_buffer = NULL;  /* Avoid GC issues */
5122
0
    }
5123
5.42M
    return code;
5124
5.42M
}
5125
5126
5127
5128
/* Used for filling rects when we are doing a fill with a pattern that
5129
   has transparency */
5130
static  int
5131
pdf14_tile_pattern_fill(gx_device * pdev, const gs_gstate * pgs,
5132
                        gx_path * ppath, const gx_fill_params * params,
5133
                        const gx_device_color * pdevc,
5134
                        const gx_clip_path * pcpath)
5135
13.0k
{
5136
13.0k
    int code;
5137
13.0k
    gs_gstate *pgs_noconst = (gs_gstate *)pgs; /* Break const. */
5138
13.0k
    gs_fixed_rect clip_box;
5139
13.0k
    gs_fixed_rect outer_box;
5140
13.0k
    pdf14_device * p14dev = (pdf14_device *)pdev;
5141
13.0k
    gs_int_rect rect;
5142
13.0k
    gx_clip_rect *curr_clip_rect;
5143
13.0k
    gx_color_tile *ptile = NULL;
5144
13.0k
    int k;
5145
13.0k
    gx_pattern_trans_t *fill_trans_buffer = NULL;
5146
13.0k
    gs_int_point phase;  /* Needed during clist rendering for band offset */
5147
13.0k
    int n_chan_tile;
5148
13.0k
    gx_clip_path cpath_intersection;
5149
13.0k
    gx_path path_ttrans;
5150
13.0k
    gs_blend_mode_t blend_mode;
5151
13.0k
    pdf14_group_color_t *group_color_info;
5152
5153
13.0k
    if (ppath == NULL)
5154
0
        return_error(gs_error_unknownerror);  /* should not happen */
5155
13.0k
    if (pcpath != NULL) {
5156
12.2k
        code = gx_cpath_init_local_shared_nested(&cpath_intersection, pcpath, ppath->memory, 1);
5157
12.2k
    } else {
5158
818
        (*dev_proc(pdev, get_clipping_box)) (pdev, &clip_box);
5159
818
        gx_cpath_init_local(&cpath_intersection, ppath->memory);
5160
818
        code = gx_cpath_from_rectangle(&cpath_intersection, &clip_box);
5161
818
    }
5162
13.0k
    if (code < 0)
5163
0
        return code;
5164
13.0k
    code = gx_cpath_intersect_with_params(&cpath_intersection, ppath,
5165
13.0k
                                          params->rule, pgs_noconst, params);
5166
13.0k
    if (code < 0)
5167
0
        return code;
5168
    /* One (common) case worth optimising for is where we have a pattern that
5169
     * is positioned such that only one repeat of the tile is actually
5170
     * visible. In this case, we can restrict the size of the blending group
5171
     * we need to produce to be that of the actual area of the tile that is
5172
     * used. */
5173
13.0k
    ptile = pdevc->colors.pattern.p_tile;
5174
13.0k
    if (ptile->ttrans != NULL)
5175
11.5k
    {
5176
11.5k
        if ((cpath_intersection.outer_box.p.x < 0) ||
5177
11.5k
            (cpath_intersection.outer_box.p.y < 0) ||
5178
11.5k
            (cpath_intersection.outer_box.q.x > int2fixed(ptile->ttrans->width)) ||
5179
11.5k
            (cpath_intersection.outer_box.q.y > int2fixed(ptile->ttrans->height)))
5180
9.86k
        {
5181
            /* More than one repeat of the tile would be visible, so we can't
5182
             * use the optimisation here. (Actually, this test isn't quite
5183
             * right - it actually tests whether more than the '0th' repeat
5184
             * of the tile is visible. A better test would test if just one
5185
             * repeat of the tile was visible, irrespective of which one.
5186
             * This is (hopefully) relatively rare, and would make the code
5187
             * below more complex too, so we're ignoring that for now. If it
5188
             * becomes evident that it's a case that matters we can revisit
5189
             * it.) */
5190
9.86k
        } else {
5191
            /* Only the 0th repeat is visible. Restrict the size further to
5192
             * just the used area of that patch. */
5193
1.65k
            gx_path_init_local(&path_ttrans, ppath->memory);
5194
1.65k
            code = gx_path_add_rectangle(&path_ttrans,
5195
1.65k
                                         int2fixed(ptile->ttrans->rect.p.x),
5196
1.65k
                                         int2fixed(ptile->ttrans->rect.p.y),
5197
1.65k
                                         int2fixed(ptile->ttrans->rect.q.x),
5198
1.65k
                                         int2fixed(ptile->ttrans->rect.q.y));
5199
1.65k
            if (code < 0)
5200
0
                return code;
5201
1.65k
            code = gx_cpath_intersect(&cpath_intersection, &path_ttrans,
5202
1.65k
                                      params->rule, pgs_noconst);
5203
1.65k
            gx_path_free(&path_ttrans, "pdf14_tile_pattern_fill(path_ttrans)");
5204
1.65k
            if (code < 0)
5205
0
                return code;
5206
1.65k
        }
5207
11.5k
    }
5208
    /* Now let us push a transparency group into which we are
5209
     * going to tile the pattern.  */
5210
13.0k
    if (ppath != NULL) {
5211
13.0k
        pdf14_device save_pdf14_dev;    /* save area for p14dev */
5212
5213
13.0k
        gx_cpath_outer_box(&cpath_intersection, &outer_box);
5214
13.0k
        rect.p.x = fixed2int(outer_box.p.x);
5215
13.0k
        rect.p.y = fixed2int(outer_box.p.y);
5216
13.0k
        rect.q.x = fixed2int_ceiling(outer_box.q.x);
5217
13.0k
        rect.q.y = fixed2int_ceiling(outer_box.q.y);
5218
5219
        /* The color space of this group must be the same as that of the
5220
           tile.  Then when we pop the group, if there is a mismatch between
5221
           the tile color space and the current context we will do the proper
5222
           conversion.  In this way, we ensure that if the tile has any overlapping
5223
           occuring it will be blended in the proper manner i.e in the tile
5224
           underlying color space. */
5225
13.0k
        if (ptile->cdev == NULL) {
5226
11.5k
            if (ptile->ttrans == NULL)
5227
0
                return_error(gs_error_unknownerror);  /* should not happen */
5228
11.5k
            n_chan_tile = ptile->ttrans->n_chan;
5229
11.5k
        } else {
5230
1.51k
            n_chan_tile = ptile->cdev->common.color_info.num_components+1;
5231
1.51k
        }
5232
13.0k
        blend_mode = ptile->blending_mode;
5233
13.0k
        memcpy(&save_pdf14_dev, p14dev, sizeof(pdf14_device));
5234
5235
13.0k
        group_color_info = pdf14_clone_group_color_info(pdev, p14dev->ctx->stack->group_color_info);
5236
13.0k
        if (group_color_info == NULL)
5237
0
            return gs_error_VMerror;
5238
5239
13.0k
        code = pdf14_push_transparency_group(p14dev->ctx, &rect, 1, 0, (uint16_t)floor(65535 * p14dev->alpha + 0.5),
5240
13.0k
                                             (uint16_t)floor(65535 * p14dev->shape + 0.5), (uint16_t)floor(65535 * p14dev->opacity + 0.5),
5241
13.0k
                                              blend_mode, 0, 0, n_chan_tile - 1, false, false,
5242
13.0k
                                              NULL, NULL, group_color_info, pgs_noconst, pdev);
5243
13.0k
        if (code < 0)
5244
0
            return code;
5245
5246
        /* Set the blending procs and the is_additive setting based
5247
           upon the number of channels */
5248
13.0k
        if (ptile->cdev == NULL) {
5249
11.5k
            if (n_chan_tile-1 < 4) {
5250
11.5k
                ptile->ttrans->blending_procs = &rgb_blending_procs;
5251
11.5k
                ptile->ttrans->is_additive = true;
5252
11.5k
            } else {
5253
4
                ptile->ttrans->blending_procs = &cmyk_blending_procs;
5254
4
                ptile->ttrans->is_additive = false;
5255
4
            }
5256
11.5k
        }
5257
        /* Now lets go through the rect list and fill with the pattern */
5258
        /* First get the buffer that we will be filling */
5259
13.0k
        if (ptile->cdev == NULL) {
5260
11.5k
            fill_trans_buffer = new_pattern_trans_buff(pgs->memory);
5261
11.5k
            pdf14_get_buffer_information(pdev, fill_trans_buffer, NULL, false);
5262
            /* Based upon if the tiles overlap pick the type of rect fill that we will
5263
               want to use */
5264
11.5k
            if (ptile->has_overlap) {
5265
                /* This one does blending since there is tile overlap */
5266
18
                ptile->ttrans->pat_trans_fill = &tile_rect_trans_blend;
5267
11.5k
            } else {
5268
                /* This one does no blending since there is no tile overlap */
5269
11.5k
                ptile->ttrans->pat_trans_fill = &tile_rect_trans_simple;
5270
11.5k
            }
5271
            /* fill the rectangles */
5272
11.5k
            phase.x = pdevc->phase.x;
5273
11.5k
            phase.y = pdevc->phase.y;
5274
11.5k
            if (cpath_intersection.rect_list->list.head != NULL){
5275
0
                curr_clip_rect = cpath_intersection.rect_list->list.head->next;
5276
0
                for( k = 0; k < cpath_intersection.rect_list->list.count && code >= 0; k++){
5277
0
                    if_debug5m('v', pgs->memory,
5278
0
                               "[v]pdf14_tile_pattern_fill, (%d, %d), %d x %d pat_id %u \n",
5279
0
                               curr_clip_rect->xmin, curr_clip_rect->ymin,
5280
0
                               curr_clip_rect->xmax-curr_clip_rect->xmin,
5281
0
                               curr_clip_rect->ymax-curr_clip_rect->ymin, (int)ptile->id);
5282
0
                    code = gx_trans_pattern_fill_rect(curr_clip_rect->xmin, curr_clip_rect->ymin,
5283
0
                                                      curr_clip_rect->xmax, curr_clip_rect->ymax, ptile,
5284
0
                                                      fill_trans_buffer, phase, pdev, pdevc, 1);
5285
0
                    curr_clip_rect = curr_clip_rect->next;
5286
0
                }
5287
11.5k
            } else if (cpath_intersection.rect_list->list.count == 1) {
5288
                /* The case when there is just a single rect */
5289
11.5k
                if_debug5m('v', pgs->memory,
5290
11.5k
                           "[v]pdf14_tile_pattern_fill, (%d, %d), %d x %d pat_id %u \n",
5291
11.5k
                           cpath_intersection.rect_list->list.single.xmin,
5292
11.5k
                           cpath_intersection.rect_list->list.single.ymin,
5293
11.5k
                           cpath_intersection.rect_list->list.single.xmax-
5294
11.5k
                              cpath_intersection.rect_list->list.single.xmin,
5295
11.5k
                           cpath_intersection.rect_list->list.single.ymax-
5296
11.5k
                              cpath_intersection.rect_list->list.single.ymin,
5297
11.5k
                           (int)ptile->id);
5298
11.5k
                code = gx_trans_pattern_fill_rect(cpath_intersection.rect_list->list.single.xmin,
5299
11.5k
                                                  cpath_intersection.rect_list->list.single.ymin,
5300
11.5k
                                                  cpath_intersection.rect_list->list.single.xmax,
5301
11.5k
                                                  cpath_intersection.rect_list->list.single.ymax,
5302
11.5k
                                                  ptile, fill_trans_buffer, phase, pdev, pdevc, 1);
5303
11.5k
            }
5304
11.5k
        } else {
5305
            /* Clist pattern with transparency.  Create a clip device from our
5306
               cpath_intersection.  The above non-clist case could probably be
5307
               done this way too, which will reduce the amount of code here.
5308
               That is for another day though due to time constraints*/
5309
1.51k
            gx_device *dev;
5310
1.51k
            gx_device_clip clipdev;
5311
5312
1.51k
            gx_make_clip_device_on_stack(&clipdev, &cpath_intersection, pdev);
5313
1.51k
            dev = (gx_device *)&clipdev;
5314
1.51k
            phase.x = pdevc->phase.x;
5315
1.51k
            phase.y = pdevc->phase.y;
5316
1.51k
            code = gx_trans_pattern_fill_rect(rect.p.x, rect.p.y, rect.q.x, rect.q.y,
5317
1.51k
                                              ptile, fill_trans_buffer, phase,
5318
1.51k
                                              dev, pdevc, 1);
5319
5320
1.51k
        }
5321
        /* We're done drawing with the pattern, remove the reference to the
5322
         * pattern device
5323
         */
5324
13.0k
        p14dev->pclist_device = NULL;
5325
13.0k
        if (code < 0)
5326
0
            return code;
5327
5328
        /* free our buffer object */
5329
13.0k
        if (fill_trans_buffer != NULL) {
5330
11.5k
            gs_free_object(pgs->memory, fill_trans_buffer, "pdf14_tile_pattern_fill");
5331
11.5k
            ptile->ttrans->fill_trans_buffer = NULL;  /* Avoid GC issues */
5332
11.5k
        }
5333
        /* pop our transparency group which will force the blending.
5334
           This was all needed for Bug 693498 */
5335
13.0k
        code = pdf14_pop_transparency_group(pgs_noconst, p14dev->ctx,
5336
13.0k
                                            p14dev->blend_procs,
5337
13.0k
                                            p14dev->color_info.num_components,
5338
13.0k
                                            p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE],
5339
13.0k
                                            pdev);
5340
13.0k
        memcpy(p14dev, &save_pdf14_dev, sizeof(pdf14_device));
5341
13.0k
        p14dev->pclist_device = NULL;
5342
13.0k
    }
5343
13.0k
    gx_cpath_free(&cpath_intersection, "pdf14_tile_pattern_fill");
5344
13.0k
    return code;
5345
13.0k
}
5346
5347
/* Useful function that should probably go elsewhere.
5348
 * Call this function to find the topmost pdf14 device in the device chain,
5349
 * or NULL if there is not one.
5350
 */
5351
static pdf14_device *find_pdf14_device(gx_device *dev)
5352
0
{
5353
0
    pdf14_device *pdev;
5354
5355
0
    if (dev_proc(dev, dev_spec_op)(dev, gxdso_is_pdf14_device, &pdev, sizeof(pdev)) <= 0)
5356
0
        return NULL;
5357
0
    return pdev;
5358
0
}
5359
5360
/* Imager render for pattern transparency filling.  This is just here to catch
5361
   the final flush, at which time we will pop the group and reset a few items */
5362
static  int
5363
pdf14_pattern_trans_render(gx_image_enum * penum, const byte * buffer, int data_x,
5364
                    uint w, int h, gx_device * dev)
5365
0
{
5366
0
    int code;
5367
0
    pdf14_device * p14dev;
5368
0
    const gs_gstate * pgs = penum->pgs;
5369
0
    gx_device_color * pdcolor = (penum->icolor1);
5370
0
    gx_color_tile *ptile = pdcolor->colors.pattern.p_tile;
5371
5372
    /* Pass along to the original renderer */
5373
0
    code = (ptile->ttrans->image_render)(penum, buffer, data_x, w, h, dev);
5374
0
    if (code < 0)
5375
0
        return code;
5376
    /* On our final time through here, go ahead and pop the transparency
5377
       group and reset the procs in the device color. And free the fill
5378
       trans buffer object */
5379
0
    if (h == 0 && ptile->trans_group_popped == false) {
5380
0
        p14dev = find_pdf14_device(dev);
5381
5382
0
        if (p14dev->pclist_device == NULL) {
5383
            /* Used if we are on clist writing phase.  Would only
5384
               occur if we somehow failed in high level clist
5385
               image writing */
5386
0
            code = gs_end_transparency_group((gs_gstate *) pgs);
5387
0
        } else {
5388
            /* Used if we are on clist reading phase.  If we had high level
5389
               image in clist */
5390
0
            cmm_dev_profile_t *dev_profile;
5391
0
            code = dev_proc(dev, get_profile)(dev,  &dev_profile);
5392
0
            if (code < 0)
5393
0
                return code;
5394
5395
0
            if_debug2m('v', p14dev->ctx->memory,
5396
0
                      "[v*] Popping trans group pattern fill, uid = %ld id = %ld \n",
5397
0
                       ptile->uid.id, ptile->id);
5398
0
            code = pdf14_pop_transparency_group(NULL, p14dev->ctx, p14dev->blend_procs,
5399
0
                    p14dev->color_info.num_components,
5400
0
                    dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE],
5401
0
                    (gx_device *) p14dev);
5402
0
        }
5403
0
        pdcolor->colors.pattern.p_tile->trans_group_popped = true;
5404
0
        gs_free_object(pgs->memory, ptile->ttrans->fill_trans_buffer,
5405
0
                       "pdf14_pattern_trans_render");
5406
0
        ptile->ttrans->fill_trans_buffer = NULL;  /* Avoid GC issues */
5407
0
    }
5408
0
    return code;
5409
0
}
5410
5411
/* This function is used to get things in place for filling a mask image
5412
   with a pattern that has transparency.  It is used by pdf14_begin_type_image
5413
   and pdf14_clist_begin_type_image */
5414
static int
5415
pdf14_patt_trans_image_fill(gx_device * dev, const gs_gstate * pgs,
5416
                           const gs_matrix *pmat, const gs_image_common_t *pic,
5417
                           const gs_int_rect * prect,
5418
                           const gx_drawing_color * pdcolor,
5419
                           const gx_clip_path * pcpath, gs_memory_t * mem,
5420
                           gx_image_enum_common_t ** pinfo)
5421
0
{
5422
0
    const gs_image_t *pim = (const gs_image_t *)pic;
5423
0
    pdf14_device * p14dev = (pdf14_device *)dev;
5424
0
    gx_color_tile *ptile;
5425
0
    int code;
5426
0
    gs_int_rect group_rect;
5427
0
    gx_image_enum *penum;
5428
0
    gs_rect bbox_in, bbox_out;
5429
0
    gx_pattern_trans_t *fill_trans_buffer;
5430
5431
0
    ptile = pdcolor->colors.pattern.p_tile;
5432
    /* Set up things in the ptile so that we get the proper
5433
       blending etc */
5434
    /* Set the blending procs and the is_additive setting based
5435
       upon the number of channels */
5436
0
    if (ptile->ttrans->n_chan-1 < 4) {
5437
0
        ptile->ttrans->blending_procs = &rgb_blending_procs;
5438
0
        ptile->ttrans->is_additive = true;
5439
0
    } else {
5440
0
        ptile->ttrans->blending_procs = &cmyk_blending_procs;
5441
0
        ptile->ttrans->is_additive = false;
5442
0
    }
5443
    /* Set the blending mode in the ptile based upon the current
5444
       setting in the gs_gstate */
5445
0
    ptile->blending_mode = pgs->blend_mode;
5446
    /* Based upon if the tiles overlap pick the type of rect
5447
       fill that we will want to use */
5448
0
    if (ptile->has_overlap) {
5449
        /* This one does blending since there is tile overlap */
5450
0
        ptile->ttrans->pat_trans_fill = &tile_rect_trans_blend;
5451
0
    } else {
5452
        /* This one does no blending since there is no tile overlap */
5453
0
        ptile->ttrans->pat_trans_fill = &tile_rect_trans_simple;
5454
0
    }
5455
    /* Set the procs so that we use the proper filling method. */
5456
0
    gx_set_pattern_procs_trans((gx_device_color*) pdcolor);
5457
    /* Let the imaging stuff get set up */
5458
0
    code = gx_default_begin_typed_image(dev, pgs, pmat, pic,
5459
0
                            prect, pdcolor,pcpath, mem, pinfo);
5460
0
    if (code < 0)
5461
0
        return code;
5462
    /* Now Push the group */
5463
    /* First apply the inverse of the image matrix to our
5464
       image size to get our bounding box. */
5465
0
    bbox_in.p.x = 0;
5466
0
    bbox_in.p.y = 0;
5467
0
    bbox_in.q.x = pim->Width;
5468
0
    bbox_in.q.y = pim->Height;
5469
0
    code = gs_bbox_transform_inverse(&bbox_in, &(pim->ImageMatrix),
5470
0
                                &bbox_out);
5471
0
    if (code < 0)
5472
0
        return code;
5473
    /* That in turn will get hit by the matrix in the gs_gstate */
5474
0
    code = compute_group_device_int_rect(p14dev, &group_rect,
5475
0
                                            &bbox_out, (gs_gstate *)pgs);
5476
0
    if (code < 0)
5477
0
        return code;
5478
0
    if (!(pim->Width == 0 || pim->Height == 0)) {
5479
0
        if_debug2m('v', p14dev->ctx->memory,
5480
0
                   "[v*] Pushing trans group patt_trans_image_fill, uid = %ld id = %ld \n",
5481
0
                   ptile->uid.id, ptile->id);
5482
5483
0
        code = pdf14_push_transparency_group(p14dev->ctx, &group_rect, 1, 0, 65535, 65535,
5484
0
                                             65535, pgs->blend_mode, 0, 0,
5485
0
                                             ptile->ttrans->n_chan-1, false, false,
5486
0
                                             NULL, NULL, NULL, (gs_gstate *)pgs, dev);
5487
5488
        /* Set up the output buffer information now that we have
5489
           pushed the group */
5490
0
        fill_trans_buffer = new_pattern_trans_buff(pgs->memory);
5491
0
        pdf14_get_buffer_information(dev, fill_trans_buffer, NULL, false);
5492
5493
        /* Store this in the appropriate place in pdcolor.  This
5494
           is released later in pdf14_pattern_trans_render when
5495
           we are all done with the mask fill */
5496
0
        ptile->ttrans->fill_trans_buffer = fill_trans_buffer;
5497
5498
        /* Change the renderer to handle this case so we can catch the
5499
           end.  We will then pop the group and reset the pdcolor proc.
5500
           Keep the base renderer also. */
5501
0
        penum = (gx_image_enum *) *pinfo;
5502
0
        ptile->ttrans->image_render = penum->render;
5503
0
        penum->render = &pdf14_pattern_trans_render;
5504
0
        ptile->trans_group_popped = false;
5505
0
    }
5506
0
    return code;
5507
0
}
5508
5509
static  int
5510
pdf14_begin_typed_image(gx_device * dev, const gs_gstate * pgs,
5511
                           const gs_matrix *pmat, const gs_image_common_t *pic,
5512
                           const gs_int_rect * prect,
5513
                           const gx_drawing_color * pdcolor,
5514
                           const gx_clip_path * pcpath, gs_memory_t * mem,
5515
                           gx_image_enum_common_t ** pinfo)
5516
121k
{
5517
121k
    const gs_image_t *pim = (const gs_image_t *)pic;
5518
121k
    int code;
5519
5520
121k
    code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
5521
121k
        dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, pgs);
5522
121k
    if (code < 0)
5523
0
        return code;
5524
5525
    /* If we are filling an image mask with a pattern that has a transparency
5526
       then we need to do some special handling */
5527
121k
    if (pim->ImageMask) {
5528
0
        if (pdcolor != NULL && gx_dc_is_pattern1_color(pdcolor)) {
5529
0
            if( gx_pattern1_get_transptr(pdcolor) != NULL){
5530
                /* If we are in a final run through here for this case then
5531
                   go ahead and push the transparency group.   Also, update
5532
                   the proc for the pattern color so that we used the
5533
                   appropriate fill operation.  Note that the group
5534
                   is popped and the proc will be reset when we flush the
5535
                   image data.  This is handled in a special pdf14 image
5536
                   renderer which will end up installed for this case.
5537
                   Detect setting of begin_image to gx_no_begin_image.
5538
                   (final recursive call) */
5539
0
                if (dev_proc(dev, begin_typed_image) != gx_default_begin_typed_image) {
5540
0
                    code = pdf14_patt_trans_image_fill(dev, pgs, pmat, pic,
5541
0
                                                prect, pdcolor, pcpath, mem,
5542
0
                                                pinfo);
5543
0
                    return code;
5544
0
                }
5545
0
            }
5546
0
        }
5547
0
    }
5548
121k
    pdf14_set_marking_params(dev, pgs);
5549
121k
    return gx_default_begin_typed_image(dev, pgs, pmat, pic, prect, pdcolor,
5550
121k
                                        pcpath, mem, pinfo);
5551
121k
}
5552
5553
static  void
5554
pdf14_set_params(gs_gstate * pgs,
5555
                 gx_device * dev,
5556
                 const gs_pdf14trans_params_t * pparams)
5557
2.25M
{
5558
2.25M
    if_debug0m('v', dev->memory, "[v]pdf14_set_params\n");
5559
2.25M
    if (pparams->changed & PDF14_SET_BLEND_MODE)
5560
502k
        pgs->blend_mode = pparams->blend_mode;
5561
2.25M
    if (pparams->changed & PDF14_SET_TEXT_KNOCKOUT)
5562
253k
        pgs->text_knockout = pparams->text_knockout;
5563
2.25M
    if (pparams->changed & PDF14_SET_AIS)
5564
80.3k
        pgs->alphaisshape = pparams->ais;
5565
2.25M
    if (pparams->changed & PDF14_SET_OVERPRINT)
5566
384k
        pgs->overprint = pparams->overprint;
5567
2.25M
    if (pparams->changed & PDF14_SET_STROKEOVERPRINT)
5568
382k
        pgs->stroke_overprint = pparams->stroke_overprint;
5569
2.25M
    if (pparams->changed & PDF14_SET_FILLCONSTANTALPHA)
5570
704k
        pgs->fillconstantalpha = pparams->fillconstantalpha;
5571
2.25M
    if (pparams->changed & PDF14_SET_STROKECONSTANTALPHA)
5572
654k
        pgs->strokeconstantalpha = pparams->strokeconstantalpha;
5573
2.25M
    if (pparams->changed & PDF14_SET_FILLSTROKE_STATE) {
5574
746k
        gs_swapcolors_quick(pgs);
5575
746k
        if (pparams->op_fs_state == PDF14_OP_STATE_STROKE)
5576
256k
            pgs->is_fill_color = false;
5577
489k
        else
5578
489k
            pgs->is_fill_color = true;
5579
746k
    }
5580
2.25M
    pdf14_set_marking_params(dev, pgs);
5581
2.25M
}
5582
5583
/*
5584
 * This open_device method for the PDF 1.4 compositor devices is only used
5585
 * when these devices are disabled.  This routine is about as close to
5586
 * a pure "forwarding" open_device operation as is possible. Its only
5587
 * significant function is to ensure that the is_open field of the
5588
 * PDF 1.4 compositor devices matches that of the target device.
5589
 *
5590
 * We assume this procedure is called only if the device is not already
5591
 * open, and that gs_opendevice will take care of the is_open flag.
5592
 */
5593
static  int
5594
pdf14_forward_open_device(gx_device * dev)
5595
0
{
5596
0
    gx_device_forward * pdev = (gx_device_forward *)dev;
5597
0
    gx_device * tdev = pdev->target;
5598
0
    int code;
5599
5600
    /* The PDF 1.4 compositing devices must have a target */
5601
0
    if (tdev == 0)
5602
0
        return_error(gs_error_unknownerror);
5603
0
    if ((code = gs_opendevice(tdev)) >= 0)
5604
0
        gx_device_copy_params(dev, tdev);
5605
0
    return code;
5606
0
}
5607
5608
/*
5609
 * Convert all device procs to be 'forwarding'.  The caller is responsible
5610
 * for setting any device procs that should not be forwarded.
5611
 */
5612
static  void
5613
pdf14_forward_device_procs(gx_device * dev)
5614
257k
{
5615
257k
    gx_device_forward *pdev = (gx_device_forward *)dev;
5616
257k
    pdf14_device *p14dev = (pdf14_device*)dev;
5617
5618
    /* If doing simulated overprint with spot colors
5619
       then makes sure to reset devn setting */
5620
257k
    if (p14dev->overprint_sim &&
5621
257k
        p14dev->color_info.num_components > 4)
5622
0
        p14dev->icc_struct->supports_devn =
5623
0
            p14dev->target_support_devn;
5624
5625
    /*
5626
     * We are using gx_device_forward_fill_in_procs to set the various procs.
5627
     * This will ensure that any new device procs are also set.  However that
5628
     * routine only changes procs which are NULL.  Thus we start by setting all
5629
     * procs to NULL.
5630
     */
5631
257k
    memset(&(pdev->procs), 0, size_of(pdev->procs));
5632
257k
    gx_device_forward_fill_in_procs(pdev);
5633
    /*
5634
     * gx_device_forward_fill_in_procs does not forward all procs.
5635
     * Set the remainding procs to also forward.
5636
     */
5637
257k
    set_dev_proc(dev, close_device, gx_forward_close_device);
5638
257k
    set_dev_proc(dev, fill_rectangle, gx_forward_fill_rectangle);
5639
257k
    set_dev_proc(dev, fill_rectangle_hl_color, gx_forward_fill_rectangle_hl_color);
5640
257k
    set_dev_proc(dev, copy_mono, gx_forward_copy_mono);
5641
257k
    set_dev_proc(dev, copy_color, gx_forward_copy_color);
5642
257k
    set_dev_proc(dev, get_page_device, gx_forward_get_page_device);
5643
257k
    set_dev_proc(dev, strip_tile_rectangle, gx_forward_strip_tile_rectangle);
5644
257k
    set_dev_proc(dev, copy_alpha, gx_forward_copy_alpha);
5645
257k
    set_dev_proc(dev, get_profile, gx_forward_get_profile);
5646
257k
    set_dev_proc(dev, set_graphics_type_tag, gx_forward_set_graphics_type_tag);
5647
    /* These are forwarding devices with minor tweaks. */
5648
257k
    set_dev_proc(dev, open_device, pdf14_forward_open_device);
5649
257k
    set_dev_proc(dev, put_params, pdf14_forward_put_params);
5650
257k
}
5651
5652
/*
5653
 * Disable the PDF 1.4 compositor device.  Once created, the PDF 1.4
5654
 * compositor device is never removed.  (We do not have a remove compositor
5655
 * method.)  However it is no-op'ed when the PDF 1.4 device is popped.  This
5656
 * routine implements that action.
5657
 */
5658
int
5659
pdf14_disable_device(gx_device * dev)
5660
254k
{
5661
254k
    gx_device_forward * pdev = (gx_device_forward *)dev;
5662
5663
254k
    if_debug0m('v', dev->memory, "[v]pdf14_disable_device\n");
5664
254k
    dev->color_info = pdev->target->color_info;
5665
254k
    pdf14_forward_device_procs(dev);
5666
254k
    set_dev_proc(dev, composite, pdf14_forward_composite);
5667
254k
    return 0;
5668
254k
}
5669
5670
/*
5671
 * The default color space for PDF 1.4 blend modes is based upon the process
5672
 * color model of the output device.
5673
 */
5674
static  pdf14_default_colorspace_t
5675
pdf14_determine_default_blend_cs(gx_device * pdev, bool use_pdf14_accum,
5676
                                 pdf14_blend_cs_t *blend_cs_state)
5677
904k
{
5678
    /* If a blend color space was specified, then go ahead and use that to
5679
       define the default color space for the blend modes.  Only Gray, RGB
5680
       or CMYK blend color spaces are allowed.  Note we do not allow this
5681
       setting if we are dealing with a separation device. */
5682
904k
    cmm_dev_profile_t *dev_profile;
5683
904k
    cmm_profile_t *blend_profile = NULL;
5684
904k
    pdf14_blend_cs_t temp_cs_state = PDF14_BLEND_CS_UNSPECIFIED;
5685
904k
    int code = dev_proc(pdev, get_profile)(pdev, &dev_profile);
5686
904k
    bool valid_blend_cs = false;
5687
5688
904k
    *blend_cs_state = PDF14_BLEND_CS_UNSPECIFIED;
5689
5690
    /* Are we using a blend color space or the output intent color space? Also
5691
       is there a conflict in the settings. i.e. has someone set a blend color
5692
       space and tried to use the output intent with simulate overprint setting.
5693
    */
5694
904k
    if (dev_profile->overprint_control == gs_overprint_control_simulate &&
5695
904k
        dev_profile->oi_profile != NULL &&
5696
904k
        !gsicc_profiles_equal(dev_profile->oi_profile, dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE])) {
5697
        /* If blend profile is also set, throw a warning about output intent not being used. We have
5698
           possible conflicting command line settings and we will err on using the blend profile
5699
           if one was specified. */
5700
0
        if (dev_profile->blend_profile != NULL &&
5701
0
            !gsicc_profiles_equal(dev_profile->blend_profile, dev_profile->oi_profile)) {
5702
0
            blend_profile = dev_profile->blend_profile;
5703
0
            temp_cs_state = PDF14_BLEND_CS_SPECIFIED;
5704
0
            emprintf(pdev->memory, "Warning: OI profile not used for blending CS\n");
5705
0
        } else {
5706
            /* All good, use the output intent profile as we have one
5707
               and are doing simulate overprint with a different device
5708
               profile set. */
5709
0
            blend_profile = dev_profile->oi_profile;
5710
0
            temp_cs_state = PDF14_BLEND_CS_OUTPUTINTENT;
5711
0
        }
5712
904k
    } else if (dev_profile->blend_profile != NULL &&
5713
904k
               !gsicc_profiles_equal(dev_profile->blend_profile, dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE])) {
5714
        /* Blend profile is different than device profile */
5715
0
        blend_profile = dev_profile->blend_profile;
5716
0
        temp_cs_state = PDF14_BLEND_CS_SPECIFIED;
5717
0
    }
5718
5719
    /* Make sure any blend color space is valid along with other cond */
5720
904k
    if (code == 0 && blend_profile != NULL && !use_pdf14_accum) {
5721
0
        if (!blend_profile->isdevlink &&
5722
0
            !blend_profile->islab &&
5723
0
            (blend_profile->data_cs == gsGRAY ||
5724
0
             blend_profile->data_cs == gsRGB ||
5725
0
             blend_profile->data_cs == gsCMYK)) {
5726
            /* Also, do not allow the use of the blend space when we are pushing
5727
               a pattern pdf14 device.  Those should inherit from the parent */
5728
0
            if (!(gx_device_is_pattern_clist(pdev) ||
5729
0
                  gx_device_is_pattern_accum(pdev))) {
5730
0
                valid_blend_cs = true;
5731
0
            }
5732
0
        }
5733
0
    }
5734
5735
    /* If num components is one, just go ahead and use gray.  This avoids
5736
       issues with additive/subtractive mono color devices  */
5737
904k
    if (pdev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE ||
5738
904k
        pdev->color_info.num_components == 1) {
5739
        /*
5740
        * Note:  We do not allow the SeparationOrder device parameter for
5741
        * additive devices.  Thus we always have 1 colorant for DeviceGray
5742
        * and 3 colorants for DeviceRGB.
5743
        */
5744
864k
        if (valid_blend_cs) {
5745
0
            *blend_cs_state = temp_cs_state;
5746
0
            switch (blend_profile->num_comps) {
5747
0
            case 1:
5748
0
                return PDF14_DeviceGray;
5749
0
            case 3:
5750
0
                return PDF14_DeviceRGB;
5751
0
            case 4:
5752
0
                return PDF14_DeviceCMYK;
5753
0
            }
5754
0
        }
5755
864k
        if (pdev->color_info.num_components == 1)
5756
186k
            return PDF14_DeviceGray;
5757
677k
        else
5758
677k
            return PDF14_DeviceRGB;
5759
864k
    } else {
5760
        /*
5761
         * Check if the device is CMYK only or CMYK plus spot colors. Note
5762
         * the CMYK plus spot colors will not support the blend color space
5763
         */
5764
40.7k
        int i, output_comp_num, num_cmyk_used = 0, num_cmyk = 0;
5765
#if CUSTOM_BLENDING_MODE == ALWAYS_USE_CUSTOM_BLENDING
5766
        return PDF14_DeviceCustom;
5767
#endif
5768
        /*
5769
         * Count the number of CMYK process components supported by the output
5770
         * device.
5771
         */
5772
203k
        for (i = 0; i < 4; i++) {
5773
163k
            const char * pcomp_name = (const char *)DeviceCMYKComponents[i];
5774
5775
163k
            output_comp_num = dev_proc(pdev, get_color_comp_index)
5776
163k
                (pdev, pcomp_name, strlen(pcomp_name), NO_COMP_NAME_TYPE_OP);
5777
163k
            if (output_comp_num >= 0) {
5778
163k
                num_cmyk++;
5779
163k
                if (output_comp_num != GX_DEVICE_COLOR_MAX_COMPONENTS)
5780
163k
                    num_cmyk_used++;
5781
163k
            }
5782
163k
        }
5783
        /*
5784
         * Check if the device supports only CMYK.  Otherewise we assume that
5785
         * the output device supports spot colors.  Note:  This algorithm can
5786
         * be fooled if the SeparationOrder device parameter is being used by
5787
         * the output device device to only select CMYK.
5788
         */
5789
40.7k
        if (num_cmyk_used == 4 && pdev->color_info.num_components == 4
5790
40.7k
            && pdev->color_info.max_components == 4) {
5791
12.8k
            if (valid_blend_cs) {
5792
0
                *blend_cs_state = temp_cs_state;
5793
0
                switch (blend_profile->num_comps) {
5794
0
                case 1:
5795
0
                    return PDF14_DeviceGray;
5796
0
                case 3:
5797
0
                    return PDF14_DeviceRGB;
5798
0
                case 4:
5799
0
                    return PDF14_DeviceCMYK;
5800
0
                }
5801
0
            }
5802
12.8k
            return PDF14_DeviceCMYK;
5803
12.8k
        }
5804
        /*
5805
         * Check if we should use the 'custom' PDF 1.4 compositor device.
5806
         * This device is only needed for those devices which do not support
5807
         * a basic CMYK process color model.
5808
         */
5809
27.9k
#if CUSTOM_BLENDING_MODE == AUTO_USE_CUSTOM_BLENDING
5810
27.9k
        if (num_cmyk != 4)
5811
0
            return PDF14_DeviceCustom;
5812
27.9k
#endif
5813
        /*
5814
         * Otherewise we use a CMYK plus spot colors for blending.
5815
         */
5816
27.9k
        if (valid_blend_cs)
5817
0
            *blend_cs_state = temp_cs_state;
5818
27.9k
        return PDF14_DeviceCMYKspot;
5819
27.9k
    }
5820
904k
}
5821
5822
/*
5823
 * the PDF 1.4 transparency spec says that color space for blending
5824
 * operations can be based upon either a color space specified in the
5825
 * group or a default value based upon the output device.  We are
5826
 * currently only using a color space based upon the device.
5827
 */
5828
static  int
5829
get_pdf14_device_proto(gx_device       *dev,
5830
                       pdf14_device    *pdevproto,
5831
                       gs_gstate       *pgs,
5832
                 const gs_pdf14trans_t *pdf14pct,
5833
                       bool             use_pdf14_accum)
5834
261k
{
5835
261k
    pdf14_blend_cs_t blend_cs_state;
5836
261k
    pdf14_default_colorspace_t dev_cs =
5837
261k
                pdf14_determine_default_blend_cs(dev, use_pdf14_accum,
5838
261k
                                                 &blend_cs_state);
5839
261k
    bool deep = device_is_deep(dev);
5840
261k
    int num_spots = pdf14pct->params.num_spot_colors;
5841
5842
    /* overprint overide */
5843
261k
    if (pdf14pct->params.overprint_sim_push &&
5844
261k
        blend_cs_state == PDF14_BLEND_CS_UNSPECIFIED) {
5845
0
        if (pdf14pct->params.num_spot_colors_int > 0) {
5846
0
            dev_cs = PDF14_DeviceCMYKspot;
5847
0
            num_spots = pdf14pct->params.num_spot_colors_int;
5848
0
        } else
5849
0
            dev_cs = PDF14_DeviceCMYK;
5850
0
    }
5851
5852
261k
    switch (dev_cs) {
5853
11.4k
        case PDF14_DeviceGray:
5854
11.4k
            *pdevproto = gs_pdf14_Gray_device;
5855
11.4k
            pdevproto->color_info.max_components = 1;
5856
11.4k
            pdevproto->color_info.num_components =
5857
11.4k
                                    pdevproto->color_info.max_components;
5858
11.4k
            pdevproto->color_info.depth = 8<<deep;
5859
11.4k
            pdevproto->color_info.max_gray = deep ? 65535 : 255;
5860
11.4k
            pdevproto->color_info.gray_index = 0; /* Avoid halftoning */
5861
11.4k
            pdevproto->color_info.dither_grays = deep ? 65536 : 256;
5862
11.4k
            pdevproto->sep_device = false;
5863
11.4k
            break;
5864
238k
        case PDF14_DeviceRGB:
5865
238k
            *pdevproto = gs_pdf14_RGB_device;
5866
238k
            pdevproto->color_info.depth = 24<<deep;
5867
238k
            pdevproto->color_info.max_gray = deep ? 65535 : 255;
5868
238k
            pdevproto->color_info.dither_grays = deep ? 65536 : 256;
5869
238k
            pdevproto->sep_device = false;
5870
238k
            break;
5871
0
        case PDF14_DeviceCMYK:
5872
0
            *pdevproto = gs_pdf14_CMYK_device;
5873
0
            pdevproto->color_info.depth = 32<<deep;
5874
0
            pdevproto->color_info.max_gray = deep ? 65535 : 255;
5875
0
            pdevproto->color_info.dither_grays = deep ? 65536 : 256;
5876
0
            pdevproto->sep_device = false;
5877
0
            break;
5878
11.4k
        case PDF14_DeviceCMYKspot:
5879
11.4k
            *pdevproto = gs_pdf14_CMYKspot_device;
5880
            /* Need to figure out how we want to handle the device profile
5881
               for this case */
5882
            /*
5883
             * The number of components for the PDF14 device is the sum
5884
             * of the process components and the number of spot colors
5885
             * for the page.
5886
             */
5887
11.4k
            if (num_spots >= 0) {
5888
11.4k
                pdevproto->color_info.num_components =
5889
11.4k
                    pdevproto->devn_params.num_std_colorant_names + num_spots;
5890
11.4k
                if (pdevproto->color_info.num_components > GS_CLIENT_COLOR_MAX_COMPONENTS)
5891
0
                    pdevproto->color_info.num_components = GS_CLIENT_COLOR_MAX_COMPONENTS;
5892
11.4k
                pdevproto->color_info.depth =
5893
11.4k
                                    pdevproto->color_info.num_components * (8<<deep);
5894
11.4k
                pdevproto->sep_device = true;
5895
11.4k
            }
5896
11.4k
            break;
5897
0
        case PDF14_DeviceCustom:
5898
            /*
5899
             * We are using the output device's process color model.  The
5900
             * color_info for the PDF 1.4 compositing device needs to match
5901
             * the output device.
5902
             */
5903
0
            *pdevproto = gs_pdf14_custom_device;
5904
0
            pdevproto->color_info = dev->color_info;
5905
            /* The pdf14 device has to be 8 (or 16) bit continuous tone. Force it */
5906
0
            pdevproto->color_info.depth =
5907
0
                       pdevproto->color_info.num_components * (8<<deep);
5908
0
            pdevproto->color_info.max_gray = deep ? 65535 : 255;
5909
0
            pdevproto->color_info.max_color = deep ? 65535 : 255;
5910
0
            pdevproto->color_info.dither_grays = deep ? 65536 : 256;
5911
0
            pdevproto->color_info.dither_colors = deep ? 65536 : 256;
5912
0
            break;
5913
0
        default:      /* Should not occur */
5914
0
            return_error(gs_error_rangecheck);
5915
261k
    }
5916
261k
    pdevproto->initialize_device_procs((gx_device *)pdevproto);
5917
261k
    pdevproto->blend_cs_state = blend_cs_state;
5918
261k
    pdevproto->overprint_sim = pdf14pct->params.overprint_sim_push;
5919
261k
    return 0;
5920
261k
}
5921
5922
/* When playing back the clist, we need to know if the buffer device is compatible */
5923
/* with the pdf14 compositor that was used when writing the clist. Colorspace and  */
5924
/* depth are critical since these must match when reading back colors.             */
5925
bool
5926
pdf14_ok_to_optimize(gx_device *dev)
5927
641k
{
5928
641k
    pdf14_blend_cs_t blend_cs_state;
5929
641k
    pdf14_default_colorspace_t pdf14_cs =
5930
641k
        pdf14_determine_default_blend_cs(dev, false, &blend_cs_state);
5931
641k
    gsicc_colorbuffer_t dev_icc_cs;
5932
641k
    bool ok = false;
5933
641k
    int tag_depth = device_encodes_tags(dev) ? 8 : 0;
5934
641k
    cmm_dev_profile_t *dev_profile;
5935
641k
    int code = dev_proc(dev, get_profile)(dev,  &dev_profile);
5936
641k
    bool deep = device_is_deep(dev);
5937
5938
641k
    if (code < 0)
5939
0
        return false;
5940
5941
641k
    check_device_compatible_encoding(dev);
5942
5943
641k
    if (dev->color_info.separable_and_linear != GX_CINFO_SEP_LIN_STANDARD)
5944
293k
        return false;
5945
5946
348k
    dev_icc_cs = dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]->data_cs;
5947
    /* If the outputprofile is not "standard" then colors converted to device color */
5948
    /* during clist writing won't match the colors written for the pdf14 clist dev  */
5949
348k
    if (!(dev_icc_cs == gsGRAY || dev_icc_cs == gsRGB || dev_icc_cs == gsCMYK))
5950
0
        return false;                           /* can't handle funky output profiles */
5951
5952
348k
    switch (pdf14_cs) {
5953
154k
        case PDF14_DeviceGray:
5954
154k
            ok = dev->color_info.max_gray == (deep ? 65535 : 255) && dev->color_info.depth == (8<<deep) + tag_depth;
5955
154k
            break;
5956
177k
        case PDF14_DeviceRGB:
5957
177k
            ok = dev->color_info.max_color == (deep ? 65535: 255) && dev->color_info.depth == (24<<deep) + tag_depth;
5958
177k
            break;
5959
0
        case PDF14_DeviceCMYK:
5960
0
            ok = dev->color_info.max_color == (deep ? 65535 : 255) && dev->color_info.depth == (32<<deep) + tag_depth;
5961
0
            break;
5962
15.9k
        case PDF14_DeviceCMYKspot:
5963
15.9k
            ok = false;     /* punt for this case */
5964
15.9k
            break;
5965
0
        case PDF14_DeviceCustom:
5966
            /*
5967
             * We are using the output device's process color model.  The
5968
             * color_info for the PDF 1.4 compositing device needs to match
5969
             * the output device, but it may not have been contone.
5970
             */
5971
0
            ok = dev->color_info.depth == dev->color_info.num_components * (8<<deep) + tag_depth;
5972
0
            break;
5973
0
        default:      /* Should not occur */
5974
0
            ok = false;
5975
348k
    }
5976
348k
    return ok;
5977
348k
}
5978
5979
/*
5980
 * Recreate the PDF 1.4 compositor device.  Once created, the PDF 1.4
5981
 * compositor device is never removed.  (We do not have a remove compositor
5982
 * method.)  However it is no-op'ed when the PDF 1.4 device is popped.  This
5983
 * routine will re-enable the compositor if the PDF 1.4 device is pushed
5984
 * again.
5985
 */
5986
static  int
5987
pdf14_recreate_device(gs_memory_t *mem, gs_gstate * pgs,
5988
                gx_device * dev, const gs_pdf14trans_t * pdf14pct)
5989
0
{
5990
0
    pdf14_device * pdev = (pdf14_device *)dev;
5991
0
    gx_device * target = pdev->target;
5992
0
    pdf14_device dev_proto;
5993
0
    bool has_tags = device_encodes_tags(dev);
5994
0
    int code;
5995
0
    bool deep = device_is_deep(dev);
5996
5997
0
    if_debug0m('v', dev->memory, "[v]pdf14_recreate_device\n");
5998
5999
    /*
6000
     * We will not use the entire prototype device but we will set the
6001
     * color related info and the device procs to match the prototype.
6002
     */
6003
0
    code = get_pdf14_device_proto(target, &dev_proto, pgs,
6004
0
                                  pdf14pct, false);
6005
0
    if (code < 0)
6006
0
        return code;
6007
0
    pdev->color_info = dev_proto.color_info;
6008
0
    pdev->pad = target->pad;
6009
0
    pdev->log2_align_mod = target->log2_align_mod;
6010
6011
0
    if (pdf14pct->params.overprint_sim_push && pdf14pct->params.num_spot_colors_int > 0 && !target->is_planar)
6012
0
        pdev->is_planar = true;
6013
0
    else
6014
0
        pdev->is_planar = target->is_planar;
6015
0
    pdev->interpolate_threshold = dev_proc(target, dev_spec_op)(target, gxdso_interpolate_threshold, NULL, 0);
6016
6017
0
    pdev->procs = dev_proto.procs;
6018
0
    if (deep) {
6019
0
        set_dev_proc(pdev, encode_color, pdf14_encode_color16);
6020
0
        set_dev_proc(pdev, decode_color, pdf14_decode_color16);
6021
0
    }
6022
0
    if (has_tags) {
6023
0
        set_dev_proc(pdev, encode_color, deep ? pdf14_encode_color16_tag : pdf14_encode_color_tag);
6024
0
        pdev->color_info.comp_shift[pdev->color_info.num_components] = pdev->color_info.depth;
6025
0
        pdev->color_info.depth += 8;
6026
0
    }
6027
0
    pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN_STANDARD;
6028
0
    gx_device_fill_in_procs((gx_device *)pdev);
6029
0
    pdev->save_get_cmap_procs = pgs->get_cmap_procs;
6030
0
    pgs->get_cmap_procs = pdf14_get_cmap_procs;
6031
0
    gx_set_cmap_procs(pgs, (gx_device *)pdev);
6032
0
    check_device_separable(dev);
6033
0
    return dev_proc(pdev, open_device)(dev);
6034
0
}
6035
6036
/*
6037
 * Implement the various operations that can be specified via the PDF 1.4
6038
 * create compositor request.
6039
 */
6040
static  int
6041
gx_update_pdf14_compositor(gx_device * pdev, gs_gstate * pgs,
6042
    const gs_pdf14trans_t * pdf14pct, gs_memory_t * mem )
6043
5.98M
{
6044
5.98M
    pdf14_device *p14dev = (pdf14_device *)pdev;
6045
5.98M
    gs_pdf14trans_params_t params = pdf14pct->params;
6046
5.98M
    int code = 0;
6047
6048
5.98M
    params.idle = pdf14pct->idle;
6049
5.98M
    switch (params.pdf14_op) {
6050
0
        default:      /* Should not occur. */
6051
0
            break;
6052
336
        case PDF14_PUSH_DEVICE:
6053
336
            if (!(params.is_pattern)) {
6054
0
                p14dev->blend_mode = 0;
6055
0
                p14dev->opacity = p14dev->shape = 0.0;
6056
0
                pdf14_recreate_device(mem, pgs, pdev, pdf14pct);
6057
0
            }
6058
336
            break;
6059
0
        case PDF14_ABORT_DEVICE:
6060
            /* Something has gone very wrong.  Let transparency device clean up
6061
               what ever it has allocated and then we are shutting it down */
6062
0
            code = gx_abort_trans_device(pgs, pdev);
6063
0
            if (p14dev->free_devicen) {
6064
0
                devn_free_params(pdev);
6065
0
            }
6066
0
            pdf14_disable_device(pdev);
6067
0
            pdf14_close(pdev);
6068
0
            break;
6069
254k
        case PDF14_POP_DEVICE:
6070
254k
            if (!(params.is_pattern)) {
6071
253k
                if_debug0m('v', pdev->memory,
6072
253k
                           "[v]gx_update_pdf14_compositor(PDF14_POP_DEVICE)\n");
6073
253k
                pgs->get_cmap_procs = p14dev->save_get_cmap_procs;
6074
253k
                gx_set_cmap_procs(pgs, p14dev->target);
6075
                /* Send image out raster data to output device */
6076
253k
                {
6077
                    /* Make a copy so we can change the ROP */
6078
253k
                    gs_gstate new_pgs = *pgs;
6079
6080
                    /* We don't use the gs_gstate log_op since this is for the */
6081
                    /* clist playback. Putting the image (band in the case of the */
6082
                    /* clist) only needs to use the default ROP to copy the data  */
6083
253k
                    new_pgs.log_op = rop3_default;
6084
253k
                    code = p14dev->pdf14_procs->put_image(pdev, &new_pgs, p14dev->target);
6085
253k
                }
6086
                /* Before we disable the device release any deviceN structures.
6087
                    free_devicen is set if the pdf14 device had inherited its
6088
                    deviceN parameters from the target clist device.  In this
6089
                    case they should not be freed */
6090
253k
                if (p14dev->free_devicen) {
6091
253k
                    devn_free_params(pdev);
6092
253k
                }
6093
253k
                pdf14_disable_device(pdev);
6094
253k
                pdf14_close(pdev);
6095
253k
            }
6096
254k
            break;
6097
98.3k
        case PDF14_BEGIN_TRANS_PAGE_GROUP:
6098
548k
        case PDF14_BEGIN_TRANS_GROUP:
6099
548k
            if (p14dev->smask_constructed || p14dev->depth_within_smask)
6100
107k
                p14dev->depth_within_smask++;
6101
548k
            p14dev->smask_constructed = 0;
6102
548k
            code = gx_begin_transparency_group(pgs, pdev, &params);
6103
548k
            break;
6104
509k
        case PDF14_END_TRANS_GROUP:
6105
509k
            code = gx_end_transparency_group(pgs, pdev);
6106
509k
            if (p14dev->depth_within_smask)
6107
107k
                p14dev->depth_within_smask--;
6108
509k
            break;
6109
18
        case PDF14_BEGIN_TRANS_TEXT_GROUP:
6110
18
            if (p14dev->text_group == PDF14_TEXTGROUP_BT_PUSHED) {
6111
0
                p14dev->text_group = PDF14_TEXTGROUP_MISSING_ET;
6112
0
                emprintf(p14dev->memory, "Warning: Text group pushed but no ET found\n");
6113
0
            } else
6114
18
                p14dev->text_group = PDF14_TEXTGROUP_BT_NOT_PUSHED;
6115
18
            break;
6116
38.8k
        case PDF14_END_TRANS_TEXT_GROUP:
6117
38.8k
            if (p14dev->text_group == PDF14_TEXTGROUP_BT_PUSHED)
6118
38.8k
                code = gx_end_transparency_group(pgs, pdev);
6119
38.8k
            p14dev->text_group = PDF14_TEXTGROUP_NO_BT; /* Hit ET */
6120
38.8k
            break;
6121
1.22M
        case PDF14_BEGIN_TRANS_MASK:
6122
1.22M
            code = gx_begin_transparency_mask(pgs, pdev, &params);
6123
1.22M
            if (code >= 0 && params.subtype != TRANSPARENCY_MASK_None)
6124
137k
                p14dev->in_smask_construction++;
6125
1.22M
            break;
6126
137k
        case PDF14_END_TRANS_MASK:
6127
137k
            code = gx_end_transparency_mask(pgs, pdev, &params);
6128
137k
            if (code >= 0) {
6129
137k
                p14dev->in_smask_construction--;
6130
137k
                if (p14dev->in_smask_construction < 0)
6131
0
                    p14dev->in_smask_construction = 0;
6132
137k
                if (p14dev->in_smask_construction == 0)
6133
136k
                    p14dev->smask_constructed = 1;
6134
137k
            }
6135
137k
            break;
6136
2.25M
        case PDF14_SET_BLEND_PARAMS:
6137
2.25M
            pdf14_set_params(pgs, pdev, &pdf14pct->params);
6138
2.25M
            break;
6139
0
        case PDF14_PUSH_TRANS_STATE:
6140
0
            code = gx_push_transparency_state(pgs, pdev);
6141
0
            break;
6142
1.00M
        case PDF14_POP_TRANS_STATE:
6143
1.00M
            code = gx_pop_transparency_state(pgs, pdev);
6144
1.00M
            break;
6145
5.52k
        case PDF14_PUSH_SMASK_COLOR:
6146
5.52k
            code = pdf14_increment_smask_color(pgs, pdev);
6147
5.52k
            break;
6148
5.52k
        case PDF14_POP_SMASK_COLOR:
6149
5.52k
            code = pdf14_decrement_smask_color(pgs, pdev);
6150
5.52k
            break;
6151
5.98M
    }
6152
5.98M
    return code;
6153
5.98M
}
6154
6155
/*
6156
 * The PDF 1.4 compositor is never removed.  (We do not have a 'remove
6157
 * compositor' method.  However the compositor is disabled when we are not
6158
 * doing a page which uses PDF 1.4 transparency.  This routine is only active
6159
 * when the PDF 1.4 compositor is 'disabled'.  It checks for reenabling the
6160
 * PDF 1.4 compositor.  Otherwise it simply passes create compositor requests
6161
 * to the target.
6162
 */
6163
static  int
6164
pdf14_forward_composite(gx_device * dev, gx_device * * pcdev,
6165
        const gs_composite_t * pct, gs_gstate * pgs,
6166
        gs_memory_t * mem, gx_device *cdev)
6167
74
{
6168
74
    pdf14_device *pdev = (pdf14_device *)dev;
6169
74
    gx_device * tdev = pdev->target;
6170
74
    int code;
6171
6172
74
    *pcdev = dev;
6173
74
    if (gs_is_pdf14trans_compositor(pct)) {
6174
0
        const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct;
6175
6176
0
        if (pdf14pct->params.pdf14_op == PDF14_PUSH_DEVICE)
6177
0
            return gx_update_pdf14_compositor(dev, pgs, pdf14pct, mem);
6178
0
        return 0;
6179
0
    }
6180
74
    code = dev_proc(tdev, composite)(tdev, pcdev, pct, pgs, mem, cdev);
6181
74
    if (code == 1) {
6182
        /* We have created a new compositor that wrapped tdev. This means
6183
         * that our target should be updated to point to that. */
6184
0
        gx_device_set_target((gx_device_forward *)pdev, *pcdev);
6185
0
        code = 0; /* We have not created a new compositor that wrapped dev. */
6186
0
    }
6187
74
    return code;
6188
74
}
6189
6190
/*
6191
 * The PDF 1.4 compositor can be handled directly, so just set *pcdev = dev
6192
 * and return. Since the gs_pdf14_device only supports the high-level routines
6193
 * of the interface, don't bother trying to handle any other compositor.
6194
 */
6195
static int
6196
pdf14_composite(gx_device * dev, gx_device * * pcdev,
6197
        const gs_composite_t * pct, gs_gstate * pgs,
6198
        gs_memory_t * mem, gx_device *cdev)
6199
13.1M
{
6200
13.1M
    pdf14_device *p14dev = (pdf14_device *)dev;
6201
13.1M
    if (gs_is_pdf14trans_compositor(pct)) {
6202
5.98M
        const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct;
6203
5.98M
        *pcdev = dev;
6204
        /* cdev, may be the clist reader device which may contain information that
6205
           we will need related to the ICC color spaces that define transparency
6206
           groups.  We want this propogated through all the pdf14 functions.  Store
6207
           a pointer to it in the pdf14 device */
6208
5.98M
        p14dev->pclist_device = cdev;
6209
5.98M
        return gx_update_pdf14_compositor(dev, pgs, pdf14pct, mem);
6210
7.18M
    } else if (gs_is_overprint_compositor(pct)) {
6211
                /* If we had an overprint compositer action, then the
6212
                   color components that were drawn should be updated.
6213
                   The overprint compositor logic and its interactions
6214
                   with the clist is a little odd as it passes uninitialized
6215
                   values around a fair amount.  Hence the forced assignement here.
6216
                   See gx_spot_colors_set_overprint in gscspace for issues... */
6217
7.18M
                const gs_overprint_t * op_pct = (const gs_overprint_t *) pct;
6218
7.18M
                gx_color_index drawn_comps;
6219
7.18M
                PDF14_OP_FS_STATE curr_state = p14dev->op_state;
6220
6221
7.18M
                p14dev->op_state = op_pct->params.op_state;
6222
7.18M
                if (p14dev->op_state == PDF14_OP_STATE_NONE) {
6223
4.76M
                    if (op_pct->params.retain_any_comps) {
6224
777
                        drawn_comps = op_pct->params.drawn_comps;
6225
4.76M
                    } else {
6226
                        /* Draw everything. If this parameter was not set, clist does
6227
                           not fill it in.  */
6228
4.76M
                        drawn_comps = ((gx_color_index)1 << (p14dev->color_info.num_components)) - (gx_color_index)1;
6229
4.76M
                    }
6230
6231
4.76M
                    if (op_pct->params.is_fill_color) {
6232
2.41M
                        p14dev->effective_overprint_mode = op_pct->params.effective_opm;
6233
2.41M
                        p14dev->drawn_comps_fill = drawn_comps;
6234
2.41M
                    } else {
6235
2.35M
                        p14dev->stroke_effective_op_mode = op_pct->params.effective_opm;
6236
2.35M
                        p14dev->drawn_comps_stroke = drawn_comps;
6237
2.35M
                    }
6238
                    /* We restore the NONE states as that is used just to force
6239
                       overprint settings in the overprint compositor communication */
6240
4.76M
                    p14dev->op_state = curr_state;
6241
4.76M
                }
6242
7.18M
                *pcdev = dev;
6243
7.18M
                return 0;
6244
7.18M
    } else
6245
0
        return gx_no_composite(dev, pcdev, pct, pgs, mem, cdev);
6246
13.1M
}
6247
6248
static int
6249
pdf14_push_text_group(gx_device *dev, gs_gstate *pgs,
6250
                      gs_blend_mode_t blend_mode, float opacity,
6251
                      float shape, bool is_clist)
6252
578
{
6253
578
    int code;
6254
578
    gs_transparency_group_params_t params = { 0 };
6255
578
    gs_rect bbox = { 0 }; /* Bounding box is set by parent */
6256
578
    pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
6257
578
    float alpha = pgs->fillconstantalpha;
6258
6259
    /* Push a non-isolated knock-out group making sure the opacity and blend
6260
       mode are correct */
6261
578
    params.Isolated = false;
6262
578
    params.Knockout = true;
6263
578
    params.page_group = false;
6264
578
    params.text_group = PDF14_TEXTGROUP_BT_PUSHED;
6265
578
    params.group_opacity = 1.0;
6266
578
    params.group_shape = 1.0;
6267
6268
578
    gs_setfillconstantalpha(pgs, 1.0);
6269
578
    gs_setblendmode(pgs, BLEND_MODE_Normal);
6270
6271
578
    if (is_clist) {
6272
578
        code = pdf14_clist_update_params(pdev, pgs, false, NULL);
6273
578
        if (code < 0)
6274
0
            return code;
6275
578
    }
6276
6277
578
    code = gs_begin_transparency_group(pgs, &params, &bbox, PDF14_BEGIN_TRANS_GROUP);
6278
578
    gs_setfillconstantalpha(pgs, alpha);
6279
578
    gs_setblendmode(pgs, blend_mode);
6280
578
    if (code < 0)
6281
0
        return code;
6282
6283
578
    if (is_clist) {
6284
578
        code = pdf14_clist_update_params(pdev, pgs, false, NULL);
6285
578
    }
6286
578
    return code;
6287
578
}
6288
6289
static  int
6290
pdf14_text_begin(gx_device * dev, gs_gstate * pgs,
6291
                 const gs_text_params_t * text, gs_font * font,
6292
                 const gx_clip_path * pcpath,
6293
                 gs_text_enum_t ** ppenum)
6294
44
{
6295
44
    int code;
6296
44
    gs_text_enum_t *penum;
6297
44
    gs_blend_mode_t blend_mode = gs_currentblendmode(pgs);
6298
44
    float opacity = pgs->fillconstantalpha;
6299
44
    float shape = 1.0;
6300
44
    bool blend_issue = !(blend_mode == BLEND_MODE_Normal || blend_mode == BLEND_MODE_Compatible || blend_mode == BLEND_MODE_CompatibleOverprint);
6301
44
    pdf14_device *pdev = (pdf14_device*)dev;
6302
44
    bool draw = !(text->operation & TEXT_DO_NONE);
6303
44
    uint text_mode = gs_currenttextrenderingmode(pgs);
6304
44
    bool text_stroke = (text_mode == 1 || text_mode == 2 || text_mode == 5 || text_mode == 6);
6305
44
    bool text_fill = (text_mode == 0 || text_mode == 2 || text_mode == 4 || text_mode == 6);
6306
6307
44
    code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
6308
44
        dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, (const gs_gstate*) pgs);
6309
44
    if (code < 0)
6310
0
        return code;
6311
6312
44
    if_debug0m('v', pgs->memory, "[v]pdf14_text_begin\n");
6313
44
    pdf14_set_marking_params(dev, pgs);
6314
44
    code = gx_default_text_begin(dev, pgs, text, font, pcpath, &penum);
6315
44
    if (code < 0)
6316
0
        return code;
6317
6318
    /* We may need to push a non-isolated transparency group if the following
6319
       is true.
6320
       1) We are not currently in one that we pushed for text and we are in
6321
          a BT/ET pair.  This is determined by looking at the pdf14 text_group.
6322
       2) The blend mode is not Normal or the opacity is not 1.0
6323
       3) Text knockout is set to true
6324
       4) We are actually doing a text drawing
6325
6326
       Special note:  If text-knockout is set to false while we are within a
6327
       BT ET pair, we should pop the group.  I need to create a test file for
6328
       this case.  */
6329
6330
       /* Catch case where we already pushed a group and are trying to push another one.
6331
       In that case, we will pop the current one first, as we don't want to be left
6332
       with it. Note that if we have a BT and no other BTs or ETs then this issue
6333
       will not be caught until we do the put_image and notice that the stack is not
6334
       empty. */
6335
44
    if (pdev->text_group == PDF14_TEXTGROUP_MISSING_ET) {
6336
0
        code = gs_end_transparency_group(pgs);
6337
0
        if (code < 0)
6338
0
            return code;
6339
0
        pdev->text_group = PDF14_TEXTGROUP_BT_NOT_PUSHED;
6340
0
    }
6341
6342
44
    if (gs_currenttextknockout(pgs) && (blend_issue ||
6343
44
         (pgs->fillconstantalpha != 1.0 && text_fill) ||
6344
44
         (pgs->strokeconstantalpha != 1.0 && text_stroke)) &&
6345
44
         text_mode != 3 && /* don't bother with invisible text */
6346
44
         pdev->text_group == PDF14_TEXTGROUP_BT_NOT_PUSHED)
6347
0
        if (draw) {
6348
0
            code = pdf14_push_text_group(dev, pgs, blend_mode, opacity, shape,
6349
0
                false);
6350
0
        }
6351
44
    *ppenum = (gs_text_enum_t *)penum;
6352
44
    return code;
6353
44
}
6354
6355
static  int
6356
pdf14_initialize_device(gx_device *new_dev)
6357
261k
{
6358
261k
    pdf14_device *pdev = (pdf14_device*)new_dev;
6359
6360
261k
    pdev->ctx = NULL;
6361
261k
    pdev->color_model_stack = NULL;
6362
261k
    pdev->smaskcolor = NULL;
6363
6364
261k
    return 0;
6365
261k
}
6366
6367
/*
6368
 * Implement copy_mono by filling lots of small rectangles.
6369
 */
6370
static int
6371
pdf14_copy_mono(gx_device * dev,
6372
               const byte * base, int sourcex, int sraster, gx_bitmap_id id,
6373
        int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
6374
5.44M
{
6375
5.44M
    const byte *sptr;
6376
5.44M
    const byte *line;
6377
5.44M
    int sbit, first_bit;
6378
5.44M
    int code, sbyte, bit, count;
6379
5.44M
    int run_length, startx, current_bit, bit_value;
6380
5.44M
    gx_color_index current_color;
6381
6382
5.44M
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
6383
5.44M
    line = base + (sourcex >> 3);
6384
5.44M
    sbit = sourcex & 7;
6385
5.44M
    first_bit = 7 - sbit;
6386
6387
    /* Loop through the height of the specified area. */
6388
41.1M
    while (h-- > 0) {
6389
        /* Set up for the start of each line of the area. */
6390
35.6M
        sptr = line;
6391
35.6M
        sbyte = *sptr++;
6392
        /* The +1 here is 'sacrificial', we are going to decrement it by 1 immediately in
6393
         * the loop below so adding 1 means that we don't fall into the bit == 0
6394
         * case and incorrectly read a new byte from the source. This weirdness is because
6395
         * the original code wouold read off the end of the buffer if the number of bits in
6396
         * the raster was an exact multiple of 8. If it was also a multiple of the word
6397
         * size we might read unallocated memory. Moving the 'sbyte = *sptr++' from the end
6398
         * of the loop to the beginning meant we would not read past the end of the buffer
6399
         * because we would drop out of the 'do ... while (count-- > 0)' loop before
6400
         * reading another byte.
6401
         */
6402
35.6M
        bit = first_bit + 1;
6403
35.6M
        count = w;
6404
35.6M
        run_length = 0;
6405
35.6M
        startx = x;
6406
35.6M
        current_bit = 0;
6407
35.6M
        current_color = zero;
6408
6409
        /* Loop across each pixel of a line. */
6410
485M
        do {
6411
            /* Move to the next input bit. */
6412
485M
            if (bit == 0) {
6413
42.5M
                bit = 7;
6414
42.5M
                sbyte = *sptr++;
6415
42.5M
            }
6416
442M
            else
6417
442M
                bit--;
6418
485M
            bit_value = (sbyte >> bit) & 1;
6419
485M
            if (bit_value == current_bit) {
6420
                /* The value did not change, simply increment our run length */
6421
396M
                run_length++;
6422
396M
            } else {
6423
                /* The value changed, fill the current rectangle. */
6424
88.3M
                if (run_length != 0) {
6425
84.4M
                    if (current_color != gx_no_color_index) {
6426
36.5M
                        code = (*dev_proc(dev, fill_rectangle))
6427
36.5M
                                (dev, startx, y, run_length, 1, current_color);
6428
36.5M
                        if (code < 0)
6429
0
                            return code;
6430
36.5M
                    }
6431
84.4M
                    startx += run_length;
6432
84.4M
                }
6433
88.3M
                run_length = 1;
6434
88.3M
                current_color = bit_value ? one : zero;
6435
88.3M
                current_bit = bit_value;
6436
88.3M
            }
6437
485M
        } while (--count > 0);
6438
        /* Fill the last rectangle in the line. */
6439
35.6M
        if (run_length != 0 && current_color != gx_no_color_index) {
6440
15.3M
            code = (*dev_proc(dev, fill_rectangle))
6441
15.3M
                        (dev, startx, y, run_length, 1, current_color);
6442
15.3M
            if (code < 0)
6443
0
                return code;
6444
15.3M
        }
6445
        /* Move to the next line */
6446
35.6M
        line += sraster;
6447
35.6M
        y++;
6448
35.6M
    }
6449
5.44M
    return 0;
6450
5.44M
}
6451
6452
/* Added to avoid having to go back and forth between fixed and int
6453
   in some of the internal methods used for dealing with tiling
6454
   and devn colors */
6455
static int
6456
pdf14_fill_rectangle_devn(gx_device *dev, int x, int y, int w, int h,
6457
    const gx_drawing_color *pdcolor)
6458
0
{
6459
0
    pdf14_device *pdev = (pdf14_device *)dev;
6460
0
    pdf14_buf *buf;
6461
0
    int code;
6462
6463
0
    fit_fill_xywh(dev, x, y, w, h);
6464
0
    if (w <= 0 || h <= 0)
6465
0
        return 0;
6466
6467
0
    code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
6468
0
        dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, NULL);
6469
0
    if (code < 0)
6470
0
        return code;
6471
0
    buf = pdev->ctx->stack;
6472
6473
0
    if (buf->knockout)
6474
0
        return pdf14_mark_fill_rectangle_ko_simple(dev, x, y, w, h, 0, pdcolor,
6475
0
            true);
6476
0
    else
6477
0
        return pdf14_mark_fill_rectangle(dev, x, y, w, h, 0, pdcolor, true);
6478
0
}
6479
6480
/* Step through and do rect fills with the devn colors as
6481
   we hit each transition in the bitmap. It is possible
6482
   that one of the colors is not devn, but is pure and
6483
   is set to gx_no_color_index. This type of mix happens
6484
   for example from tile_clip_fill_rectangle_hl_color */
6485
static int
6486
pdf14_copy_mono_devn(gx_device *dev,
6487
    const byte *base, int sourcex, int sraster,
6488
    int x, int y, int w, int h, const gx_drawing_color *pdcolor0,
6489
    const gx_drawing_color *pdcolor1)
6490
0
{
6491
0
    const byte *sptr;
6492
0
    const byte *line;
6493
0
    int sbit, first_bit;
6494
0
    int code, sbyte, bit, count;
6495
0
    int run_length, startx, current_bit, bit_value;
6496
0
    const gx_drawing_color *current_color;
6497
6498
0
    if ((x | y) < 0) {
6499
0
        if (x < 0) {
6500
0
            w += x;
6501
0
            sourcex -= x;
6502
0
            x = 0;
6503
0
        }
6504
0
        if (y < 0) {
6505
0
            h += y;
6506
0
            base -= (int)(y * sraster);
6507
0
            y = 0;
6508
0
        }
6509
0
    }
6510
0
    if (w > (dev)->width - x)
6511
0
        w = (dev)->width - x;
6512
0
    if (h > (dev)->height - y)
6513
0
        h = (dev)->height - y;
6514
0
    if (w <= 0 || h <= 0)
6515
0
        return 0;
6516
6517
0
    line = base + (sourcex >> 3);
6518
0
    sbit = sourcex & 7;
6519
0
    first_bit = 7 - sbit;
6520
6521
    /* Loop through the height of the specified area. */
6522
0
    while (h-- > 0) {
6523
        /* Set up for the start of each line of the area. */
6524
0
        sptr = line;
6525
0
        sbyte = *sptr++;
6526
0
        bit = first_bit;
6527
0
        count = w;
6528
0
        run_length = 0;
6529
0
        startx = x;
6530
0
        current_bit = 0;
6531
0
        current_color = pdcolor0;
6532
6533
        /* Loop across each pixel of a line. */
6534
0
        do {
6535
0
            bit_value = (sbyte >> bit) & 1;
6536
0
            if (bit_value == current_bit) {
6537
                /* The value did not change, simply increment our run length */
6538
0
                run_length++;
6539
0
            } else {
6540
                /* The value changed, fill the current rectangle. */
6541
0
                if (run_length != 0) {
6542
0
                    if (current_color->type != gx_dc_type_pure &&
6543
0
                        current_color->colors.pure != gx_no_color_index) {
6544
0
                        code = pdf14_fill_rectangle_devn(dev, startx, y,
6545
0
                            run_length, 1, current_color);
6546
0
                        if (code < 0)
6547
0
                            return code;
6548
0
                    }
6549
0
                    startx += run_length;
6550
0
                }
6551
0
                run_length = 1;
6552
0
                current_color = bit_value ? pdcolor1 : pdcolor0;
6553
0
                current_bit = bit_value;
6554
0
            }
6555
6556
            /* Move to the next input bit. */
6557
0
            if (bit == 0) {
6558
0
                bit = 7;
6559
0
                sbyte = *sptr++;
6560
0
            } else
6561
0
                bit--;
6562
0
        } while (--count > 0);
6563
6564
        /* Fill the last rectangle in the line. */
6565
0
        if (run_length != 0 && current_color->type != gx_dc_type_pure &&
6566
0
            current_color->colors.pure != gx_no_color_index) {
6567
0
            code = pdf14_fill_rectangle_devn(dev, startx, y,
6568
0
                run_length, 1, current_color);
6569
0
            if (code < 0)
6570
0
                return code;
6571
0
        }
6572
        /* Move to the next line */
6573
0
        line += sraster;
6574
0
        y++;
6575
0
    }
6576
0
    return 0;
6577
0
}
6578
6579
/* Step through the tiles doing essentially copy_mono but with devn colors */
6580
static int
6581
pdf14_impl_strip_tile_rectangle_devn(gx_device *dev, const gx_strip_bitmap *tiles,
6582
    int x, int y, int w, int h, const gx_drawing_color *pdcolor0,
6583
    const gx_drawing_color *pdcolor1, int px, int py)
6584
0
{   /* Fill the rectangle in chunks. */
6585
0
    int width = tiles->size.x;
6586
0
    int height = tiles->size.y;
6587
0
    int raster = tiles->raster;
6588
0
    int rwidth = tiles->rep_width;
6589
0
    int rheight = tiles->rep_height;
6590
0
    int shift = tiles->shift;
6591
6592
0
    if (rwidth == 0 || rheight == 0)
6593
0
        return_error(gs_error_unregistered);
6594
0
    fit_fill_xy(dev, x, y, w, h);
6595
6596
0
     {
6597
0
        int xoff = (shift == 0 ? px :
6598
0
                px + (y + py) / rheight * tiles->rep_shift);
6599
0
        int irx = ((rwidth & (rwidth - 1)) == 0 ? /* power of 2 */
6600
0
            (x + xoff) & (rwidth - 1) :
6601
0
            (x + xoff) % rwidth);
6602
0
        int ry = ((rheight & (rheight - 1)) == 0 ? /* power of 2 */
6603
0
            (y + py) & (rheight - 1) :
6604
0
            (y + py) % rheight);
6605
0
        int icw = width - irx;
6606
0
        int ch = height - ry;
6607
0
        byte *row = tiles->data + ry * raster;
6608
0
        int code = 0;
6609
6610
0
        if (ch >= h) {      /* Shallow operation */
6611
0
            if (icw >= w) { /* Just one (partial) tile to transfer. */
6612
0
                code = pdf14_copy_mono_devn(dev, row, irx, raster, x, y,
6613
0
                    w, h, pdcolor0, pdcolor1);
6614
0
                if (code < 0)
6615
0
                    return_error(code);
6616
0
            } else {
6617
0
                int ex = x + w;
6618
0
                int fex = ex - width;
6619
0
                int cx = x + icw;
6620
6621
0
                code = pdf14_copy_mono_devn(dev, row, irx, raster,
6622
0
                    x, y, icw, h, pdcolor0, pdcolor1);
6623
0
                if (code < 0)
6624
0
                    return_error(code);
6625
6626
0
                while (cx <= fex) {
6627
0
                    code = pdf14_copy_mono_devn(dev, row, 0, raster, cx, y,
6628
0
                        width, h, pdcolor0, pdcolor1);
6629
0
                    if (code < 0)
6630
0
                        return_error(code);
6631
0
                    cx += width;
6632
0
                }
6633
0
                if (cx < ex) {
6634
0
                    code = pdf14_copy_mono_devn(dev, row, 0, raster, cx, y,
6635
0
                        ex - cx, h, pdcolor0, pdcolor1);
6636
0
                    if (code < 0)
6637
0
                        return_error(code);
6638
0
                }
6639
0
            }
6640
0
        } else if (icw >= w && shift == 0) {
6641
            /* Narrow operation, no shift */
6642
0
            int ey = y + h;
6643
0
            int fey = ey - height;
6644
0
            int cy = y + ch;
6645
6646
0
            code = pdf14_copy_mono_devn(dev, row, irx, raster,
6647
0
                x, y, w, ch, pdcolor0, pdcolor1);
6648
0
            if (code < 0)
6649
0
                return_error(code);
6650
0
            row = tiles->data;
6651
0
            do {
6652
0
                ch = (cy > fey ? ey - cy : height);
6653
0
                code = pdf14_copy_mono_devn(dev, row, irx, raster,
6654
0
                    x, cy, w, ch, pdcolor0, pdcolor1);
6655
0
                if (code < 0)
6656
0
                    return_error(code);
6657
0
            } while ((cy += ch) < ey);
6658
0
        } else {
6659
            /* Full operation.  If shift != 0, some scan lines */
6660
            /* may be narrow.  We could test shift == 0 in advance */
6661
            /* and use a slightly faster loop, but right now */
6662
            /* we don't bother. */
6663
0
            int ex = x + w, ey = y + h;
6664
0
            int fex = ex - width, fey = ey - height;
6665
0
            int cx, cy;
6666
6667
0
            for (cy = y;;) {
6668
0
                if (icw >= w) {
6669
0
                    code = pdf14_copy_mono_devn(dev, row, irx, raster,
6670
0
                        x, cy, w, ch, pdcolor0, pdcolor1);
6671
0
                    if (code < 0)
6672
0
                        return_error(code);
6673
0
                } else {
6674
0
                    code = pdf14_copy_mono_devn(dev, row, irx, raster,
6675
0
                        x, cy, icw, ch, pdcolor0, pdcolor1);
6676
0
                    if (code < 0)
6677
0
                        return_error(code);
6678
0
                    cx = x + icw;
6679
0
                    while (cx <= fex) {
6680
0
                        code = pdf14_copy_mono_devn(dev, row, 0, raster,
6681
0
                            cx, cy, width, ch, pdcolor0, pdcolor1);
6682
0
                        if (code < 0)
6683
0
                            return_error(code);
6684
0
                        cx += width;
6685
0
                    }
6686
0
                    if (cx < ex) {
6687
0
                        code = pdf14_copy_mono_devn(dev, row, 0, raster,
6688
0
                            cx, cy, ex - cx, ch, pdcolor0, pdcolor1);
6689
0
                        if (code < 0)
6690
0
                            return_error(code);
6691
0
                    }
6692
0
                }
6693
0
                if ((cy += ch) >= ey)
6694
0
                    break;
6695
0
                ch = (cy > fey ? ey - cy : height);
6696
0
                if ((irx += shift) >= rwidth)
6697
0
                    irx -= rwidth;
6698
0
                icw = width - irx;
6699
0
                row = tiles->data;
6700
0
            }
6701
0
        }
6702
0
    }
6703
0
    return 0;
6704
0
}
6705
6706
/* pdf14 device supports devn */
6707
static int
6708
pdf14_strip_tile_rect_devn(gx_device *dev, const gx_strip_bitmap *tiles,
6709
    int x, int y, int w, int h,
6710
    const gx_drawing_color *pdcolor0,
6711
    const gx_drawing_color *pdcolor1, int px, int py)
6712
0
{
6713
0
    pdf14_device *pdev = (pdf14_device *)dev;
6714
0
    pdf14_buf *buf;
6715
0
    int num_comp;
6716
0
    int k;
6717
0
    bool same = false;
6718
0
    int code;
6719
6720
0
    code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
6721
0
        dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, NULL);
6722
0
    if (code < 0)
6723
0
        return code;
6724
0
    buf = pdev->ctx->stack;
6725
0
    num_comp = buf->n_chan - 1;
6726
6727
    /* if color0 is identical to color1, do rect fill */
6728
0
    if (pdcolor0->type == gx_dc_type_devn && pdcolor1->type == gx_dc_type_devn) {
6729
0
        same = true;
6730
0
        for (k = 0; k < num_comp; k++) {
6731
0
            if (pdcolor0->colors.devn.values[k] != pdcolor1->colors.devn.values[k]) {
6732
0
                same = false;
6733
0
                break;
6734
0
            }
6735
0
        }
6736
0
    }
6737
6738
0
    if (same) {
6739
0
        code = pdf14_fill_rectangle_devn(dev, x, y, w, h, pdcolor0);
6740
0
    } else {
6741
        /* Go through the tile stepping using code stolen from
6742
           gx_default_strip_tile_rectangle and call the rect fills
6743
           using code stolen from pdf14_copy_mono but using devn
6744
           colors */
6745
0
        code = pdf14_impl_strip_tile_rectangle_devn(dev, tiles,
6746
0
            x, y, w, h, pdcolor0, pdcolor1, px, py);
6747
0
    }
6748
0
    return code;
6749
0
}
6750
6751
/* Used in a few odd cases where the target device is planar and we have
6752
   a planar tile (pattern) and we are copying it into place here */
6753
static int
6754
pdf14_copy_planes(gx_device * dev, const byte * data, int data_x, int raster,
6755
                  gx_bitmap_id id, int x, int y, int w, int h, int plane_height)
6756
0
{
6757
0
    pdf14_device *pdev = (pdf14_device *)dev;
6758
#if RAW_DUMP
6759
    pdf14_ctx *ctx = pdev->ctx;
6760
#endif
6761
0
    pdf14_buf *buf = pdev->ctx->stack;
6762
0
    int xo = x;
6763
0
    int yo = y;
6764
0
    pdf14_buf fake_tos;
6765
0
    int deep = pdev->ctx->deep;
6766
6767
0
    fit_fill_xywh(dev, x, y, w, h);
6768
0
    if (w <= 0 || h <= 0)
6769
0
        return 0;
6770
6771
0
    fake_tos.deep = deep;
6772
0
    fake_tos.alpha = (uint16_t)(0xffff * pdev->alpha + 0.5);
6773
0
    fake_tos.backdrop = NULL;
6774
0
    fake_tos.blend_mode = pdev->blend_mode;
6775
0
    fake_tos.color_space = buf->color_space;
6776
0
    fake_tos.data = (byte *)data + ((data_x - (x - xo))<<deep) - (y - yo) * raster; /* Nasty, cast away of const */
6777
0
    fake_tos.dirty.p.x = x;
6778
0
    fake_tos.dirty.p.y = y;
6779
0
    fake_tos.dirty.q.x = x + w;
6780
0
    fake_tos.dirty.q.y = y + h;
6781
0
    fake_tos.has_alpha_g = 0;
6782
0
    fake_tos.has_shape = 0;
6783
0
    fake_tos.has_tags = 0;
6784
0
    fake_tos.idle = false;
6785
0
    fake_tos.isolated = false;
6786
0
    fake_tos.knockout = false;
6787
0
    fake_tos.mask_id = 0;
6788
0
    fake_tos.mask_stack = NULL;
6789
0
    fake_tos.matte = NULL;
6790
0
    fake_tos.matte_num_comps = 0;
6791
0
    fake_tos.memory = dev->memory;
6792
0
    fake_tos.n_chan = dev->color_info.num_components;
6793
0
    fake_tos.n_planes = dev->color_info.num_components;
6794
0
    fake_tos.num_spots = 0;
6795
0
    fake_tos.group_color_info = NULL;
6796
0
    fake_tos.planestride = raster * plane_height;
6797
0
    fake_tos.rect.p.x = x;
6798
0
    fake_tos.rect.p.y = y;
6799
0
    fake_tos.rect.q.x = x + w;
6800
0
    fake_tos.rect.q.y = y + h;
6801
0
    fake_tos.rowstride = raster;
6802
0
    fake_tos.saved = NULL;
6803
0
    fake_tos.shape = 0xffff;
6804
0
    fake_tos.SMask_SubType = TRANSPARENCY_MASK_Alpha;
6805
0
    fake_tos.transfer_fn = NULL;
6806
0
    pdf14_compose_alphaless_group(&fake_tos, buf, x, x+w, y, y+h,
6807
0
                                  pdev->ctx->memory, dev);
6808
0
    return 0;
6809
0
}
6810
6811
static int
6812
pdf14_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect,
6813
    const gs_gstate *pgs, const gx_drawing_color *pdcolor,
6814
    const gx_clip_path *pcpath)
6815
8.21M
{
6816
8.21M
    pdf14_device *pdev = (pdf14_device *)dev;
6817
8.21M
    pdf14_buf* buf;
6818
8.21M
    int code;
6819
8.21M
    int x = fixed2int(rect->p.x);
6820
8.21M
    int y = fixed2int(rect->p.y);
6821
8.21M
    int w = fixed2int(rect->q.x) - x;
6822
8.21M
    int h = fixed2int(rect->q.y) - y;
6823
6824
8.21M
    fit_fill_xywh(dev, x, y, w, h);
6825
8.21M
    if (w <= 0 || h <= 0)
6826
98.3k
        return 0;
6827
6828
8.11M
    code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
6829
8.11M
        dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, pgs);
6830
8.11M
    if (code < 0)
6831
0
        return code;
6832
8.11M
    buf = pdev->ctx->stack;
6833
6834
8.11M
    if (buf->knockout)
6835
281
        return pdf14_mark_fill_rectangle_ko_simple(dev, x, y, w, h, 0, pdcolor,
6836
281
                                                   true);
6837
8.11M
    else
6838
8.11M
        return pdf14_mark_fill_rectangle(dev, x, y, w, h, 0, pdcolor, true);
6839
8.11M
}
6840
6841
static  int
6842
pdf14_fill_rectangle(gx_device * dev,
6843
                    int x, int y, int w, int h, gx_color_index color)
6844
139M
{
6845
139M
    pdf14_device *pdev = (pdf14_device *)dev;
6846
139M
    pdf14_buf *buf;
6847
139M
    int code;
6848
6849
139M
    fit_fill_xywh(dev, x, y, w, h);
6850
139M
    if (w <= 0 || h <= 0)
6851
3.09M
        return 0;
6852
6853
136M
    code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
6854
136M
            dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, NULL);
6855
136M
    if (code < 0)
6856
0
        return code;
6857
6858
136M
    buf = pdev->ctx->stack;
6859
6860
136M
    if (buf->knockout)
6861
138k
        return pdf14_mark_fill_rectangle_ko_simple(dev, x, y, w, h, color, NULL,
6862
138k
                                                   false);
6863
136M
    else
6864
136M
        return pdf14_mark_fill_rectangle(dev, x, y, w, h, color, NULL, false);
6865
136M
}
6866
6867
static int
6868
pdf14_compute_group_device_int_rect(const gs_matrix *ctm,
6869
                                    const gs_rect *pbbox, gs_int_rect *rect)
6870
673k
{
6871
673k
    gs_rect dev_bbox;
6872
673k
    int code;
6873
6874
673k
    code = gs_bbox_transform(pbbox, ctm, &dev_bbox);
6875
673k
    if (code < 0)
6876
0
        return code;
6877
673k
    rect->p.x = (int)floor(dev_bbox.p.x);
6878
673k
    rect->p.y = (int)floor(dev_bbox.p.y);
6879
673k
    rect->q.x = (int)ceil(dev_bbox.q.x);
6880
673k
    rect->q.y = (int)ceil(dev_bbox.q.y);
6881
673k
    return 0;
6882
673k
}
6883
6884
static  int
6885
compute_group_device_int_rect(pdf14_device *pdev, gs_int_rect *rect,
6886
                              const gs_rect *pbbox, gs_gstate *pgs)
6887
646k
{
6888
646k
    int code = pdf14_compute_group_device_int_rect(&ctm_only(pgs), pbbox, rect);
6889
6890
646k
    if (code < 0)
6891
0
        return code;
6892
646k
    rect_intersect(*rect, pdev->ctx->rect);
6893
    /* Make sure the rectangle is not anomalous (q < p) -- see gsrect.h */
6894
646k
    if (rect->q.x < rect->p.x)
6895
5.58k
        rect->q.x = rect->p.x;
6896
646k
    if (rect->q.y < rect->p.y)
6897
28.8k
        rect->q.y = rect->p.y;
6898
646k
    return 0;
6899
646k
}
6900
6901
static  int
6902
pdf14_begin_transparency_group(gx_device* dev,
6903
    const gs_transparency_group_params_t* ptgp,
6904
    const gs_rect* pbbox,
6905
    gs_gstate* pgs, gs_memory_t* mem)
6906
548k
{
6907
548k
    pdf14_device* pdev = (pdf14_device*)dev;
6908
548k
    float alpha = ptgp->group_opacity * ptgp->group_shape;
6909
548k
    gs_int_rect rect;
6910
548k
    int code;
6911
548k
    bool isolated = ptgp->Isolated;
6912
548k
    gs_transparency_color_t group_color_type;
6913
548k
    cmm_profile_t* group_profile;
6914
548k
    cmm_profile_t* tos_profile;
6915
548k
    gsicc_rendering_param_t render_cond;
6916
548k
    cmm_dev_profile_t* dev_profile;
6917
548k
    bool cm_back_drop = false;
6918
548k
    bool new_icc = false;
6919
548k
    pdf14_group_color_t* group_color_info;
6920
6921
548k
    code = dev_proc(dev, get_profile)(dev, &dev_profile);
6922
548k
    if (code < 0)
6923
0
        return code;
6924
548k
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &tos_profile, &render_cond);
6925
6926
548k
    if (ptgp->text_group == PDF14_TEXTGROUP_BT_PUSHED) {
6927
39.3k
        pdev->text_group = PDF14_TEXTGROUP_BT_PUSHED;  /* For immediate mode and clist reading */
6928
39.3k
    }
6929
6930
548k
    if (ptgp->text_group == PDF14_TEXTGROUP_BT_PUSHED)
6931
39.3k
        rect = pdev->ctx->rect; /* Use parent group for text_group. */
6932
509k
    else
6933
509k
        code = compute_group_device_int_rect(pdev, &rect, pbbox, pgs);
6934
6935
548k
    if (code < 0)
6936
0
        return code;
6937
548k
    if_debug5m('v', pdev->memory,
6938
548k
        "[v]pdf14_begin_transparency_group, I = %d, K = %d, alpha = %g, bm = %d page_group = %d\n",
6939
548k
        ptgp->Isolated, ptgp->Knockout, (double)alpha, pgs->blend_mode, ptgp->page_group);
6940
6941
    /* If the group color is unknown then use the current device profile. */
6942
548k
    if (ptgp->group_color_type == UNKNOWN) {
6943
444k
        group_color_type = ICC;
6944
444k
        group_profile = tos_profile;
6945
444k
    }
6946
104k
    else {
6947
104k
        group_color_type = ptgp->group_color_type;
6948
104k
        group_profile = ptgp->iccprofile;
6949
104k
    }
6950
6951
    /* We have to handle case where the profile is in the clist */
6952
548k
    if (group_profile == NULL && pdev->pclist_device != NULL) {
6953
        /* Get the serialized data from the clist. */
6954
104k
        gx_device_clist_reader* pcrdev = (gx_device_clist_reader*)(pdev->pclist_device);
6955
104k
        group_profile = gsicc_read_serial_icc((gx_device*)pcrdev, ptgp->icc_hashcode);
6956
104k
        if (group_profile == NULL)
6957
0
            return gs_throw(gs_error_unknownerror, "ICC data not found in clist");
6958
        /* Keep a pointer to the clist device */
6959
104k
        group_profile->dev = (gx_device*)pcrdev;
6960
104k
        new_icc = true;
6961
104k
    }
6962
548k
    if (group_profile != NULL) {
6963
        /* If we have a non-isolated group and the color space is different,
6964
            we will need to CM the backdrop. */
6965
548k
        if (!gsicc_profiles_equal(group_profile, tos_profile)) {
6966
19.9k
            cm_back_drop = true;
6967
19.9k
        }
6968
548k
    }
6969
6970
    /* Always create the base color group information as it is only through
6971
       groups that we can have a color space change.  This will survive
6972
       the life of the context. */
6973
548k
    if (pdev->ctx->base_color == NULL) {
6974
121k
        pdev->ctx->base_color = pdf14_make_base_group_color(dev);
6975
121k
    }
6976
6977
    /* If this is not the page group and we don't yet have a group, we need
6978
       to create a buffer for the whole page so that we can handle stuff drawn
6979
       outside this current group (e.g. two non inclusive groups drawn independently) */
6980
548k
    if (pdev->ctx->stack == NULL && !ptgp->page_group) {
6981
4.52k
        code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
6982
4.52k
            dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, NULL);
6983
4.52k
        if (code < 0)
6984
0
            return code;
6985
4.52k
        pdev->ctx->stack->isolated = true;
6986
4.52k
    }
6987
6988
548k
    group_color_info = pdf14_push_color_model(dev, group_color_type, ptgp->icc_hashcode,
6989
548k
        group_profile, false);
6990
548k
    if (group_color_info == NULL)
6991
0
        return gs_error_VMerror;
6992
548k
    if_debug0m('v', dev->memory, "[v]Transparency group color space update\n");
6993
6994
548k
    code = pdf14_push_transparency_group(pdev->ctx, &rect, isolated, ptgp->Knockout,
6995
548k
                                        (uint16_t)floor (65535 * alpha + 0.5),
6996
548k
                                        (uint16_t)floor(65535 * ptgp->group_shape + 0.5),
6997
548k
                                        (uint16_t)floor(65535 * ptgp->group_opacity + 0.5),
6998
548k
                                        pgs->blend_mode, ptgp->idle,
6999
548k
                                         ptgp->mask_id, pdev->color_info.num_components,
7000
548k
                                         cm_back_drop, ptgp->shade_group,
7001
548k
                                         group_profile, tos_profile, group_color_info, pgs, dev);
7002
548k
    if (new_icc)
7003
104k
        gsicc_adjust_profile_rc(group_profile, -1, "pdf14_begin_transparency_group");
7004
548k
    return code;
7005
548k
}
7006
7007
static void
7008
pdf14_pop_color_model(gx_device* dev, pdf14_group_color_t* group_color)
7009
548k
{
7010
548k
    pdf14_device* pdev = (pdf14_device*)dev;
7011
7012
548k
    if (group_color != NULL &&
7013
548k
        !(group_color->group_color_mapping_procs == NULL &&
7014
548k
            group_color->group_color_comp_index == NULL)) {
7015
548k
        set_dev_proc(pdev, get_color_mapping_procs, group_color->group_color_mapping_procs);
7016
548k
        set_dev_proc(pdev, get_color_comp_index, group_color->group_color_comp_index);
7017
548k
        pdev->color_info.polarity = group_color->polarity;
7018
548k
        pdev->color_info.num_components = group_color->num_components;
7019
548k
        pdev->blend_procs = group_color->blend_procs;
7020
548k
        pdev->ctx->additive = group_color->isadditive;
7021
548k
        pdev->pdf14_procs = group_color->unpack_procs;
7022
548k
        pdev->color_info.opmsupported = GX_CINFO_OPMSUPPORTED_UNKNOWN;
7023
548k
        pdev->color_info.depth = group_color->depth;
7024
548k
        pdev->color_info.max_color = group_color->max_color;
7025
548k
        pdev->color_info.max_gray = group_color->max_gray;
7026
548k
        memcpy(&(pdev->color_info.comp_bits), &(group_color->comp_bits),
7027
548k
            GX_DEVICE_COLOR_MAX_COMPONENTS);
7028
548k
        memcpy(&(pdev->color_info.comp_shift), &(group_color->comp_shift),
7029
548k
            GX_DEVICE_COLOR_MAX_COMPONENTS);
7030
548k
        if (group_color->icc_profile != NULL) {
7031
            /* make sure to decrement the device profile.  If it was allocated
7032
               with the push then it will be freed. */
7033
548k
            gsicc_adjust_profile_rc(pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE],
7034
548k
                                    -1, "pdf14_pop_color_model");
7035
548k
            pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] =
7036
548k
                                    group_color->icc_profile;
7037
7038
548k
            gsicc_adjust_profile_rc(pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE],
7039
548k
                                    1, "pdf14_pop_color_model");
7040
548k
        }
7041
548k
    }
7042
548k
}
7043
7044
static  int
7045
pdf14_end_transparency_group(gx_device* dev, gs_gstate* pgs)
7046
548k
{
7047
548k
    pdf14_device* pdev = (pdf14_device*)dev;
7048
548k
    int code;
7049
548k
    cmm_profile_t* group_profile;
7050
548k
    gsicc_rendering_param_t render_cond;
7051
548k
    cmm_dev_profile_t* dev_profile;
7052
7053
548k
    code = dev_proc(dev, get_profile)(dev, &dev_profile);
7054
548k
    if (code < 0)
7055
0
        return code;
7056
7057
548k
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &group_profile,
7058
548k
        &render_cond);
7059
548k
    if_debug0m('v', dev->memory, "[v]pdf14_end_transparency_group\n");
7060
7061
548k
    code = pdf14_pop_transparency_group(pgs, pdev->ctx, pdev->blend_procs,
7062
548k
        pdev->color_info.num_components, group_profile, (gx_device*)pdev);
7063
548k
    if (code < 0)
7064
0
        return code;
7065
#ifdef DEBUG
7066
    pdf14_debug_mask_stack_state(pdev->ctx);
7067
#endif
7068
    /* If this group is the base group, then restore the color model
7069
       of the device at this time.  Note that during the actual device pop
7070
       we will need to use the profile of the buffer not the pdf14 device
7071
       as the source color space */
7072
548k
    if (pdev->ctx->stack->group_popped) {
7073
98.1k
        pdf14_pop_color_model(dev, pdev->ctx->base_color);
7074
450k
    } else {
7075
450k
        pdf14_pop_color_model(dev, pdev->ctx->stack->group_color_info);
7076
450k
    }
7077
7078
548k
    return code;
7079
548k
}
7080
7081
static pdf14_group_color_t*
7082
pdf14_push_color_model(gx_device *dev, gs_transparency_color_t group_color_type,
7083
                        int64_t icc_hashcode, cmm_profile_t *iccprofile,
7084
                        bool is_mask)
7085
685k
{
7086
685k
    pdf14_device *pdevproto = NULL;
7087
685k
    pdf14_device *pdev = (pdf14_device *)dev;
7088
685k
    const pdf14_procs_t *new_14procs = NULL;
7089
685k
    pdf14_group_color_t *group_color;
7090
685k
    gx_color_polarity_t new_polarity;
7091
685k
    uchar new_num_comps;
7092
685k
    bool new_additive;
7093
685k
    gx_device_clist_reader *pcrdev;
7094
685k
    byte comp_bits[GX_DEVICE_COLOR_MAX_COMPONENTS];
7095
685k
    byte comp_shift[GX_DEVICE_COLOR_MAX_COMPONENTS];
7096
685k
    int k;
7097
685k
    bool has_tags = device_encodes_tags(dev);
7098
685k
    bool deep = pdev->ctx->deep;
7099
7100
685k
    if_debug0m('v', dev->memory, "[v]pdf14_push_color_model\n");
7101
7102
685k
    group_color = gs_alloc_struct(dev->memory->stable_memory,
7103
685k
                               pdf14_group_color_t, &st_pdf14_clr,
7104
685k
                               "pdf14_push_color_model");
7105
685k
    if (group_color == NULL)
7106
0
        return NULL;
7107
7108
685k
    memset(group_color, 0, sizeof(pdf14_group_color_t));
7109
7110
685k
    switch (group_color_type) {
7111
0
        case GRAY_SCALE:
7112
0
            new_polarity = GX_CINFO_POLARITY_ADDITIVE;
7113
0
            new_num_comps = 1;
7114
0
            pdevproto = (pdf14_device *)&gs_pdf14_Gray_device;
7115
0
            new_additive = true;
7116
0
            new_14procs = &gray_pdf14_procs;
7117
0
            comp_bits[0] = 8<<deep;
7118
0
            comp_shift[0] = 0;
7119
0
            break;
7120
0
        case DEVICE_RGB:
7121
0
        case CIE_XYZ:
7122
0
            new_polarity = GX_CINFO_POLARITY_ADDITIVE;
7123
0
            new_num_comps = 3;
7124
0
            pdevproto = (pdf14_device *)&gs_pdf14_RGB_device;
7125
0
            new_additive = true;
7126
0
            new_14procs = &rgb_pdf14_procs;
7127
0
            for (k = 0; k < 3; k++) {
7128
0
                comp_bits[k] = 8<<deep;
7129
0
                comp_shift[k] = (2 - k) * (8<<deep);
7130
0
            }
7131
0
            break;
7132
0
        case DEVICE_CMYK:
7133
0
            new_polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
7134
0
            new_num_comps = 4;
7135
0
            pdevproto = (pdf14_device *)&gs_pdf14_CMYK_device;
7136
0
            new_additive = false;
7137
            /* This is needed due to the mismatched compressed encode decode
7138
                between the device procs and the pdf14 procs */
7139
0
            if (dev->color_info.num_components > 4){
7140
0
                new_14procs = &cmykspot_pdf14_procs;
7141
0
            } else {
7142
0
                new_14procs = &cmyk_pdf14_procs;
7143
0
            }
7144
0
            for (k = 0; k < 4; k++) {
7145
0
                comp_bits[k] = 8<<deep;
7146
0
                comp_shift[k] = (3 - k) * (8<<deep);
7147
0
            }
7148
0
            break;
7149
685k
        case ICC:
7150
            /* If we are coming from the clist reader, then we need to get
7151
                the ICC data now  */
7152
685k
            if (iccprofile == NULL && pdev->pclist_device != NULL) {
7153
                /* Get the serialized data from the clist.  Not the whole
7154
                    profile. */
7155
131k
                pcrdev = (gx_device_clist_reader *)(pdev->pclist_device);
7156
131k
                iccprofile = gsicc_read_serial_icc((gx_device *) pcrdev,
7157
131k
                                                    icc_hashcode);
7158
131k
                if (iccprofile == NULL)
7159
0
                    return NULL;
7160
                /* Keep a pointer to the clist device */
7161
131k
                iccprofile->dev = (gx_device *) pcrdev;
7162
554k
            } else {
7163
                /* Go ahead and rc increment right now.  This way when
7164
                    we pop, we will make sure to decrement and avoid a
7165
                    leak for the above profile that we just created.  This
7166
                    goes with the assignment to the device's profile.
7167
                    Note that we still do the increment for the group_color
7168
                    assignment below. */
7169
554k
                if (iccprofile == NULL)
7170
0
                    return NULL;
7171
554k
                gsicc_adjust_profile_rc(iccprofile, 1, "pdf14_push_color_model");
7172
554k
            }
7173
685k
            new_num_comps = iccprofile->num_comps;
7174
685k
            if (new_num_comps == 4) {
7175
190k
                new_additive = false;
7176
190k
                new_polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
7177
495k
            } else {
7178
495k
                new_additive = true;
7179
495k
                new_polarity = GX_CINFO_POLARITY_ADDITIVE;
7180
495k
            }
7181
685k
            switch (new_num_comps) {
7182
141k
                case 1:
7183
141k
                    if (pdev->sep_device && !is_mask) {
7184
0
                        pdevproto = (pdf14_device *)&gs_pdf14_Grayspot_device;
7185
0
                        new_14procs = &grayspot_pdf14_procs;
7186
141k
                    } else {
7187
141k
                        pdevproto = (pdf14_device *)&gs_pdf14_Gray_device;
7188
141k
                        new_14procs = &gray_pdf14_procs;
7189
141k
                    }
7190
141k
                    comp_bits[0] = 8<<deep;
7191
141k
                    comp_shift[0] = 0;
7192
141k
                    break;
7193
353k
                case 3:
7194
353k
                    if (pdev->sep_device) {
7195
4.48k
                        pdevproto = (pdf14_device *)&gs_pdf14_RGBspot_device;
7196
4.48k
                        new_14procs = &rgbspot_pdf14_procs;
7197
4.48k
                    }
7198
348k
                    else {
7199
348k
                        pdevproto = (pdf14_device *)&gs_pdf14_RGB_device;
7200
348k
                        new_14procs = &rgb_pdf14_procs;
7201
348k
                    }
7202
1.41M
                    for (k = 0; k < 3; k++) {
7203
1.05M
                        comp_bits[k] = 8<<deep;
7204
1.05M
                        comp_shift[k] = (2 - k) * (8<<deep);
7205
1.05M
                    }
7206
353k
                    break;
7207
190k
                case 4:
7208
190k
                    if (pdev->sep_device) {
7209
3.31k
                        pdevproto = (pdf14_device *)&gs_pdf14_CMYKspot_device;
7210
3.31k
                        new_14procs = &cmykspot_pdf14_procs;
7211
187k
                    } else {
7212
187k
                        pdevproto = (pdf14_device *)&gs_pdf14_CMYK_device;
7213
187k
                        new_14procs = &cmyk_pdf14_procs;
7214
187k
                    }
7215
953k
                    for (k = 0; k < 4; k++) {
7216
763k
                        comp_bits[k] = 8<<deep;
7217
763k
                        comp_shift[k] = (3 - k) * (8<<deep);
7218
763k
                    }
7219
190k
                    break;
7220
0
                default:
7221
0
                    return NULL;
7222
0
                    break;
7223
685k
            }
7224
685k
            break;
7225
685k
        default:
7226
0
            return NULL;
7227
0
            break;
7228
685k
    }
7229
7230
685k
    if (group_color_type == ICC && iccprofile != NULL) {
7231
685k
        group_color->icc_profile = iccprofile;
7232
685k
        gsicc_adjust_profile_rc(iccprofile, 1, "pdf14_push_color_model");
7233
685k
    }
7234
7235
    /* If we are a sep device and this is not a softmask, ensure we maintain the
7236
       spot colorants and know how to index into them */
7237
685k
    if (pdev->sep_device && !is_mask) {
7238
7.79k
        int num_spots = dev->color_info.num_components -
7239
7.79k
            dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE]->num_comps;
7240
7241
7.79k
        if (num_spots > 0) {
7242
12
            new_num_comps += num_spots;
7243
60
            for (k = 0; k < new_num_comps; k++) {
7244
48
                comp_bits[k] = 8<<deep;
7245
48
                comp_shift[k] = (new_num_comps - k - 1) * (8<<deep);
7246
48
            }
7247
12
        }
7248
7.79k
    }
7249
7250
    /* Set device values now and store settings in group_color.  Then they
7251
       are available when we pop the previous group */
7252
685k
    if_debug2m('v', pdev->memory,
7253
685k
                "[v]pdf14_push_color_model, num_components_old = %d num_components_new = %d\n",
7254
685k
                pdev->color_info.num_components,new_num_comps);
7255
685k
    {
7256
685k
        gx_device local_device;
7257
7258
685k
        local_device.initialize_device_procs = pdevproto->initialize_device_procs;
7259
685k
        local_device.initialize_device_procs((gx_device *)&local_device);
7260
685k
        set_dev_proc(pdev, get_color_mapping_procs, local_device.procs.get_color_mapping_procs);
7261
685k
        set_dev_proc(pdev, get_color_comp_index, local_device.procs.get_color_comp_index);
7262
685k
    }
7263
685k
    group_color->blend_procs = pdev->blend_procs = pdevproto->blend_procs;
7264
685k
    group_color->polarity = pdev->color_info.polarity = new_polarity;
7265
685k
    group_color->num_components = pdev->color_info.num_components = new_num_comps;
7266
685k
    group_color->isadditive = pdev->ctx->additive = new_additive;
7267
685k
    pdev->color_info.opmsupported = GX_CINFO_OPMSUPPORTED_UNKNOWN;
7268
685k
    group_color->unpack_procs = pdev->pdf14_procs = new_14procs;
7269
685k
    pdev->color_info.depth = new_num_comps * (8<<deep);
7270
685k
    memset(&(pdev->color_info.comp_bits), 0, GX_DEVICE_COLOR_MAX_COMPONENTS);
7271
685k
    memset(&(pdev->color_info.comp_shift), 0, GX_DEVICE_COLOR_MAX_COMPONENTS);
7272
685k
    memcpy(&(pdev->color_info.comp_bits), comp_bits, new_num_comps);
7273
685k
    memcpy(&(pdev->color_info.comp_shift), comp_shift, new_num_comps);
7274
685k
    if (has_tags) {
7275
0
        pdev->color_info.comp_shift[pdev->color_info.num_components] = pdev->color_info.depth;
7276
0
        pdev->color_info.depth += 8;
7277
0
    }
7278
685k
    group_color->max_color = pdev->color_info.max_color = deep ? 65535 : 255;
7279
685k
    group_color->max_gray = pdev->color_info.max_gray = deep ? 65535 : 255;
7280
685k
    group_color->depth = pdev->color_info.depth;
7281
685k
    group_color->decode = dev_proc(pdev, decode_color);
7282
685k
    group_color->encode = dev_proc(pdev, encode_color);
7283
685k
    group_color->group_color_mapping_procs = dev_proc(pdev, get_color_mapping_procs);
7284
685k
    group_color->group_color_comp_index = dev_proc(pdev, get_color_comp_index);
7285
685k
    memcpy(&(group_color->comp_bits), &(pdev->color_info.comp_bits),
7286
685k
        GX_DEVICE_COLOR_MAX_COMPONENTS);
7287
685k
    memcpy(&(group_color->comp_shift), &(pdev->color_info.comp_shift),
7288
685k
        GX_DEVICE_COLOR_MAX_COMPONENTS);
7289
685k
    group_color->get_cmap_procs = pdf14_get_cmap_procs;
7290
7291
    /* If the CS was ICC based, we need to update the device ICC profile
7292
        in the ICC manager, since that is the profile that is used for the
7293
        PDF14 device */
7294
685k
    if (group_color_type == ICC && iccprofile != NULL) {
7295
        /* iccprofile was incremented above if we had not just created it.
7296
           When we do the pop we will decrement and if we just created it, it
7297
           will be destroyed */
7298
685k
        gsicc_adjust_profile_rc(dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], -1, "pdf14_push_color_model");
7299
685k
        dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] = iccprofile;
7300
685k
    }
7301
685k
    return group_color;
7302
685k
}
7303
7304
static int
7305
pdf14_clist_push_color_model(gx_device *dev, gx_device* cdev, gs_gstate *pgs,
7306
                             const gs_pdf14trans_t *pdf14pct, gs_memory_t* mem,
7307
                             bool is_mask)
7308
19.6k
{
7309
19.6k
    pdf14_device* pdev = (pdf14_device*)dev;
7310
19.6k
    pdf14_group_color_t* new_group_color;
7311
19.6k
    gsicc_rendering_param_t render_cond;
7312
19.6k
    cmm_dev_profile_t* dev_profile;
7313
19.6k
    pdf14_device* pdevproto;
7314
19.6k
    gx_device_clist_writer* cldev = (gx_device_clist_writer*)pdev->pclist_device;
7315
19.6k
    const pdf14_procs_t* new_14procs;
7316
19.6k
    bool update_color_info;
7317
19.6k
    gx_color_polarity_t new_polarity;
7318
19.6k
    int new_num_comps;
7319
19.6k
    bool new_additive = false;
7320
19.6k
    byte new_depth;
7321
19.6k
    byte comp_bits[GX_DEVICE_COLOR_MAX_COMPONENTS];
7322
19.6k
    byte comp_shift[GX_DEVICE_COLOR_MAX_COMPONENTS];
7323
19.6k
    int k;
7324
19.6k
    bool has_tags = device_encodes_tags(dev);
7325
19.6k
    bool deep = device_is_deep(dev);
7326
19.6k
    gs_transparency_color_t group_color_type = pdf14pct->params.group_color_type;
7327
19.6k
    cmm_profile_t *new_profile = pdf14pct->params.iccprofile;
7328
19.6k
    cmm_profile_t *old_profile = NULL;
7329
7330
19.6k
    dev_proc(dev, get_profile)(dev, &dev_profile);
7331
19.6k
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &old_profile,
7332
19.6k
        &render_cond);
7333
19.6k
    if_debug0m('v', dev->memory, "[v]pdf14_clist_push_color_model\n");
7334
7335
    /* Allocate a new one */
7336
19.6k
    new_group_color = gs_alloc_struct(dev->memory->stable_memory, pdf14_group_color_t,
7337
19.6k
        &st_pdf14_clr, "pdf14_clist_push_color_model");
7338
7339
19.6k
    if (new_group_color == NULL)
7340
1
        return_error(gs_error_VMerror);
7341
7342
    /* Link to old one */
7343
19.6k
    new_group_color->previous = pdev->color_model_stack;
7344
7345
    /* Reassign new one to dev */
7346
19.6k
    pdev->color_model_stack = new_group_color;
7347
7348
    /* Initialize with values */
7349
19.6k
    new_group_color->get_cmap_procs = pgs->get_cmap_procs;
7350
19.6k
    new_group_color->group_color_mapping_procs =
7351
19.6k
        dev_proc(pdev, get_color_mapping_procs);
7352
19.6k
    new_group_color->group_color_comp_index =
7353
19.6k
        dev_proc(pdev, get_color_comp_index);
7354
19.6k
    new_group_color->blend_procs = pdev->blend_procs;
7355
19.6k
    new_group_color->polarity = pdev->color_info.polarity;
7356
19.6k
    new_group_color->num_components = pdev->color_info.num_components;
7357
19.6k
    new_group_color->unpack_procs = pdev->pdf14_procs;
7358
19.6k
    new_group_color->depth = pdev->color_info.depth;
7359
19.6k
    new_group_color->max_color = pdev->color_info.max_color;
7360
19.6k
    new_group_color->max_gray = pdev->color_info.max_gray;
7361
19.6k
    new_group_color->decode = dev_proc(pdev, decode_color);
7362
19.6k
    new_group_color->encode = dev_proc(pdev, encode_color);
7363
19.6k
    memcpy(&(new_group_color->comp_bits), &(pdev->color_info.comp_bits),
7364
19.6k
        GX_DEVICE_COLOR_MAX_COMPONENTS);
7365
19.6k
    memcpy(&(new_group_color->comp_shift), &(pdev->color_info.comp_shift),
7366
19.6k
        GX_DEVICE_COLOR_MAX_COMPONENTS);
7367
7368
19.6k
    if (new_profile == NULL)
7369
11.4k
        new_group_color->icc_profile = NULL;
7370
7371
    /* isadditive is only used in ctx */
7372
19.6k
    if (pdev->ctx) {
7373
0
        new_group_color->isadditive = pdev->ctx->additive;
7374
0
    }
7375
7376
19.6k
    memset(comp_bits, 0, GX_DEVICE_COLOR_MAX_COMPONENTS);
7377
19.6k
    memset(comp_shift, 0, GX_DEVICE_COLOR_MAX_COMPONENTS);
7378
7379
19.6k
    if (group_color_type == ICC && new_profile == NULL)
7380
0
        return gs_throw(gs_error_undefinedresult, "Missing ICC data");
7381
19.6k
    if_debug0m('v', cldev->memory, "[v]pdf14_clist_push_color_model\n");
7382
    /* Check if we need to alter the device procs at this stage.  Many of the procs
7383
       are based upon the color space of the device.  We want to remain in the
7384
       color space defined by the color space of the soft mask or transparency
7385
       group as opposed to the device color space. Later, when we pop the softmask
7386
       we will collapse it to a single band and then compose with it to the device
7387
       color space (or the parent layer space).  In the case where we pop an
7388
       isolated transparency group, we will do the blending in the proper color
7389
       space and then transform the data when we pop the group.  Remember that only
7390
       isolated groups can have color spaces that are different than their parent. */
7391
19.6k
    update_color_info = false;
7392
19.6k
    switch (group_color_type) {
7393
0
    case GRAY_SCALE:
7394
0
        if (pdev->color_info.num_components != 1) {
7395
0
            update_color_info = true;
7396
0
            new_polarity = GX_CINFO_POLARITY_ADDITIVE;
7397
0
            new_num_comps = 1;
7398
0
            pdevproto = (pdf14_device*)&gs_pdf14_Gray_device;
7399
0
            new_additive = true;
7400
0
            new_14procs = &gray_pdf14_procs;
7401
0
            new_depth = 8 << deep;
7402
0
            comp_bits[0] = 8 << deep;
7403
0
            comp_shift[0] = 0;
7404
0
        }
7405
0
        break;
7406
0
    case DEVICE_RGB:
7407
0
    case CIE_XYZ:
7408
0
        if (pdev->color_info.num_components != 3) {
7409
0
            update_color_info = true;
7410
0
            new_polarity = GX_CINFO_POLARITY_ADDITIVE;
7411
0
            new_num_comps = 3;
7412
0
            pdevproto = (pdf14_device*)&gs_pdf14_RGB_device;
7413
0
            new_additive = true;
7414
0
            new_14procs = &rgb_pdf14_procs;
7415
0
            new_depth = 24 << deep;
7416
0
            for (k = 0; k < 3; k++) {
7417
0
                comp_bits[k] = 8 << deep;
7418
0
                comp_shift[k] = (2 - k) * (8 << deep);
7419
0
            }
7420
0
        }
7421
0
        break;
7422
0
    case DEVICE_CMYK:
7423
0
        if (pdev->color_info.num_components != 4) {
7424
0
            update_color_info = true;
7425
0
            new_polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
7426
0
            new_num_comps = 4;
7427
0
            pdevproto = (pdf14_device*)&gs_pdf14_CMYK_device;
7428
0
            new_additive = false;
7429
            /* This is needed due to the mismatched compressed encode decode
7430
               between the device procs and the pdf14 procs */
7431
0
            if (dev->color_info.num_components > 4) {
7432
0
                new_14procs = &cmykspot_pdf14_procs;
7433
0
            }
7434
0
            else {
7435
0
                new_14procs = &cmyk_pdf14_procs;
7436
0
            }
7437
0
            new_depth = 32 << deep;
7438
0
            for (k = 0; k < 4; k++) {
7439
0
                comp_bits[k] = 8 << deep;
7440
0
                comp_shift[k] = (3 - k) * (8 << deep);
7441
0
            }
7442
0
        }
7443
0
        break;
7444
8.25k
    case ICC:
7445
        /* Check if the profile is different. */
7446
8.25k
        if (!gsicc_profiles_equal(old_profile, new_profile)) {
7447
7.60k
            update_color_info = true;
7448
7.60k
            new_num_comps = new_profile->num_comps;
7449
7.60k
            new_depth = new_profile->num_comps * (8 << deep);
7450
7.60k
            switch (new_num_comps) {
7451
7.14k
            case 1:
7452
7.14k
                if (pdev->sep_device && !is_mask) {
7453
0
                    pdevproto = (pdf14_device*)&gs_pdf14_Grayspot_device;
7454
0
                    new_14procs = &grayspot_pdf14_procs;
7455
0
                }
7456
7.14k
                else {
7457
7.14k
                    pdevproto = (pdf14_device*)&gs_pdf14_Gray_device;
7458
7.14k
                    new_14procs = &gray_pdf14_procs;
7459
7.14k
                }
7460
7.14k
                new_polarity = GX_CINFO_POLARITY_ADDITIVE;
7461
7.14k
                new_additive = true;
7462
7.14k
                comp_bits[0] = 8 << deep;
7463
7.14k
                comp_shift[0] = 0;
7464
7.14k
                break;
7465
323
            case 3:
7466
323
                if (pdev->sep_device) {
7467
179
                    pdevproto = (pdf14_device*)&gs_pdf14_RGBspot_device;
7468
179
                    new_14procs = &rgbspot_pdf14_procs;
7469
179
                }
7470
144
                else {
7471
144
                    pdevproto = (pdf14_device*)&gs_pdf14_RGB_device;
7472
144
                    new_14procs = &rgb_pdf14_procs;
7473
144
                }
7474
323
                new_polarity = GX_CINFO_POLARITY_ADDITIVE;
7475
323
                new_additive = true;
7476
1.29k
                for (k = 0; k < 3; k++) {
7477
969
                    comp_bits[k] = 8 << deep;
7478
969
                    comp_shift[k] = (2 - k) * (8 << deep);
7479
969
                }
7480
323
                break;
7481
137
            case 4:
7482
137
                if (pdev->sep_device) {
7483
6
                    pdevproto = (pdf14_device*)&gs_pdf14_CMYKspot_device;
7484
6
                    new_14procs = &cmykspot_pdf14_procs;
7485
6
                }
7486
131
                else {
7487
131
                    pdevproto = (pdf14_device*)&gs_pdf14_CMYK_device;
7488
131
                    new_14procs = &cmyk_pdf14_procs;
7489
131
                }
7490
137
                new_polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
7491
137
                new_additive = false;
7492
685
                for (k = 0; k < 4; k++) {
7493
548
                    comp_bits[k] = 8 << deep;
7494
548
                    comp_shift[k] = (3 - k) * (8 << deep);
7495
548
                }
7496
137
                break;
7497
0
            default:
7498
0
                return gs_throw(gs_error_undefinedresult,
7499
7.60k
                    "ICC Number of colorants illegal");
7500
7.60k
            }
7501
7.60k
        }
7502
8.25k
        break;
7503
11.4k
    case UNKNOWN:
7504
11.4k
        return 0;
7505
0
        break;
7506
0
    default:
7507
0
        return_error(gs_error_rangecheck);
7508
0
        break;
7509
19.6k
    }
7510
7511
8.25k
    if (!update_color_info) {
7512
        /* Profile not updated */
7513
650
        new_group_color->icc_profile = NULL;
7514
650
        if_debug0m('v', pdev->memory, "[v]procs not updated\n");
7515
650
        return 0;
7516
650
    }
7517
7518
7.60k
    if (pdev->sep_device && !is_mask) {
7519
185
        int num_spots;
7520
7521
185
        if (old_profile == NULL)
7522
0
            return_error(gs_error_undefined);
7523
7524
185
        num_spots = pdev->color_info.num_components - old_profile->num_comps;
7525
7526
185
        if (num_spots > 0) {
7527
12
            new_num_comps += num_spots;
7528
60
            for (k = 0; k < new_num_comps; k++) {
7529
48
                comp_bits[k] = 8 << deep;
7530
48
                comp_shift[k] = (new_num_comps - k - 1) * (8 << deep);
7531
48
            }
7532
12
            new_depth = (8 << deep) * new_num_comps;
7533
12
        }
7534
185
    }
7535
7.60k
    if (has_tags) {
7536
0
        new_depth += 8;
7537
0
    }
7538
7.60k
    if_debug2m('v', pdev->memory,
7539
7.60k
        "[v]pdf14_clist_push_color_model, num_components_old = %d num_components_new = %d\n",
7540
7.60k
        pdev->color_info.num_components, new_num_comps);
7541
    /* Set new information in the device */
7542
7.60k
    {
7543
7.60k
        gx_device local_device;
7544
7545
7.60k
        local_device.initialize_device_procs = pdevproto->initialize_device_procs;
7546
7.60k
        local_device.initialize_device_procs((gx_device *)&local_device);
7547
7.60k
        set_dev_proc(pdev, get_color_mapping_procs, local_device.procs.get_color_mapping_procs);
7548
7.60k
        set_dev_proc(pdev, get_color_comp_index, local_device.procs.get_color_comp_index);
7549
7.60k
    }
7550
7.60k
    pdev->blend_procs = pdevproto->blend_procs;
7551
7.60k
    pdev->color_info.polarity = new_polarity;
7552
7.60k
    pdev->color_info.num_components = new_num_comps;
7553
7.60k
    pdev->color_info.max_color = deep ? 65535 : 255;
7554
7.60k
    pdev->color_info.max_gray = deep ? 65535 : 255;
7555
7.60k
    pdev->pdf14_procs = new_14procs;
7556
7.60k
    pdev->color_info.depth = new_depth;
7557
7.60k
    memset(&(pdev->color_info.comp_bits), 0, GX_DEVICE_COLOR_MAX_COMPONENTS);
7558
7.60k
    memset(&(pdev->color_info.comp_shift), 0, GX_DEVICE_COLOR_MAX_COMPONENTS);
7559
7.60k
    memcpy(&(pdev->color_info.comp_bits), comp_bits, new_num_comps);
7560
7.60k
    memcpy(&(pdev->color_info.comp_shift), comp_shift, new_num_comps);
7561
7.60k
    pdev->color_info.comp_shift[new_num_comps] = new_depth - 8; /* in case we has_tags is set */
7562
7.60k
    pdev->color_info.opmsupported = GX_CINFO_OPMSUPPORTED_UNKNOWN;
7563
7564
    /* If we have a compressed color codec, and we are doing a soft mask
7565
       push operation then go ahead and update the color encode and
7566
       decode for the pdf14 device to not used compressed color
7567
       encoding while in the soft mask.  We will just check for gray
7568
       and compressed.  Note that we probably don't have_tags if we
7569
       are dealing with compressed color.  But is is possible so
7570
       we add it in to catch for future use. */
7571
7.60k
    cldev->clist_color_info.depth = pdev->color_info.depth;
7572
7.60k
    cldev->clist_color_info.polarity = pdev->color_info.polarity;
7573
7.60k
    cldev->clist_color_info.opmsupported = GX_CINFO_OPMSUPPORTED_UNKNOWN;
7574
7.60k
    cldev->clist_color_info.num_components = pdev->color_info.num_components;
7575
7.60k
    cldev->clist_color_info.max_color = pdev->color_info.max_color;
7576
7.60k
    cldev->clist_color_info.max_gray = pdev->color_info.max_gray;
7577
    /* For the ICC profiles, we want to update the ICC profile for the
7578
       device.  We store the original in group_color.
7579
       That will be stored in the clist and restored during the reading phase. */
7580
7.60k
    if (group_color_type == ICC) {
7581
7.60k
        gsicc_adjust_profile_rc(new_profile, 1, "pdf14_clist_push_color_model");
7582
7.60k
        new_group_color->icc_profile =
7583
7.60k
            dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE];
7584
7.60k
        dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] = new_profile;
7585
7.60k
    }
7586
7.60k
    if (pdev->ctx) {
7587
0
        pdev->ctx->additive = new_additive;
7588
0
    }
7589
7.60k
    return 1;  /* Lets us detect that we did do an update */
7590
7.60k
}
7591
7592
static int
7593
pdf14_clist_pop_color_model(gx_device *dev, gs_gstate *pgs)
7594
19.6k
{
7595
7596
19.6k
    pdf14_device *pdev = (pdf14_device *)dev;
7597
19.6k
    pdf14_group_color_t *group_color = pdev->color_model_stack;
7598
19.6k
    gx_device_clist_writer * cldev = (gx_device_clist_writer *)pdev->pclist_device;
7599
7600
19.6k
    if (group_color == NULL)
7601
0
        return_error(gs_error_Fatal);  /* Unmatched group pop */
7602
7603
19.6k
    if_debug0m('v', pdev->memory, "[v]pdf14_clist_pop_color_model\n");
7604
    /* The color procs are always pushed.  Simply restore them. */
7605
19.6k
    if (group_color->group_color_mapping_procs == NULL &&
7606
19.6k
        group_color->group_color_comp_index == NULL) {
7607
0
        if_debug0m('v', dev->memory, "[v]pdf14_clist_pop_color_model ERROR \n");
7608
19.6k
    } else {
7609
19.6k
        if_debug2m('v', pdev->memory,
7610
19.6k
                   "[v]pdf14_clist_pop_color_model, num_components_old = %d num_components_new = %d\n",
7611
19.6k
                   pdev->color_info.num_components,group_color->num_components);
7612
19.6k
        pgs->get_cmap_procs = group_color->get_cmap_procs;
7613
19.6k
        gx_set_cmap_procs(pgs, dev);
7614
19.6k
        set_dev_proc(pdev, get_color_mapping_procs, group_color->group_color_mapping_procs);
7615
19.6k
        set_dev_proc(pdev, get_color_comp_index, group_color->group_color_comp_index);
7616
19.6k
        pdev->color_info.polarity = group_color->polarity;
7617
19.6k
        pdev->color_info.opmsupported = GX_CINFO_OPMSUPPORTED_UNKNOWN;
7618
19.6k
        pdev->color_info.depth = group_color->depth;
7619
19.6k
        pdev->color_info.num_components = group_color->num_components;
7620
19.6k
        pdev->blend_procs = group_color->blend_procs;
7621
19.6k
        pdev->pdf14_procs = group_color->unpack_procs;
7622
19.6k
        pdev->color_info.max_color = group_color->max_color;
7623
19.6k
        pdev->color_info.max_gray = group_color->max_gray;
7624
19.6k
        set_dev_proc(pdev, encode_color, group_color->encode);
7625
19.6k
        set_dev_proc(pdev, decode_color, group_color->decode);
7626
19.6k
        memcpy(&(pdev->color_info.comp_bits),&(group_color->comp_bits),
7627
19.6k
                            GX_DEVICE_COLOR_MAX_COMPONENTS);
7628
19.6k
        memcpy(&(pdev->color_info.comp_shift),&(group_color->comp_shift),
7629
19.6k
                            GX_DEVICE_COLOR_MAX_COMPONENTS);
7630
7631
        /* clist writer fill rect has no access to gs_gstate */
7632
        /* and it forwards the target device.  this information */
7633
        /* is passed along to use in this case */
7634
19.6k
        cldev->clist_color_info.depth = pdev->color_info.depth;
7635
19.6k
        cldev->clist_color_info.polarity = pdev->color_info.polarity;
7636
19.6k
        cldev->clist_color_info.opmsupported = GX_CINFO_OPMSUPPORTED_UNKNOWN;
7637
19.6k
        cldev->clist_color_info.num_components = pdev->color_info.num_components;
7638
19.6k
        cldev->clist_color_info.max_color = pdev->color_info.max_color;
7639
19.6k
        cldev->clist_color_info.max_gray = pdev->color_info.max_gray;
7640
19.6k
        memcpy(&(cldev->clist_color_info.comp_bits),&(group_color->comp_bits),
7641
19.6k
               GX_DEVICE_COLOR_MAX_COMPONENTS);
7642
19.6k
        memcpy(&(cldev->clist_color_info.comp_shift),&(group_color->comp_shift),
7643
19.6k
               GX_DEVICE_COLOR_MAX_COMPONENTS);
7644
19.6k
        if (pdev->ctx){
7645
0
            pdev->ctx->additive = group_color->isadditive;
7646
0
        }
7647
       /* The device profile must be restored. */
7648
19.6k
        if (group_color->icc_profile != NULL) {
7649
7.60k
            gsicc_adjust_profile_rc(dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE],
7650
7.60k
                                    -1, "pdf14_clist_pop_color_model");
7651
7.60k
            dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] = group_color->icc_profile;
7652
7.60k
        }
7653
19.6k
        if_debug0m('v', dev->memory, "[v]procs updated\n");
7654
19.6k
    }
7655
19.6k
   pdf14_pop_group_color(dev, pgs);
7656
19.6k
    return 0;
7657
19.6k
}
7658
7659
/* When a transparency group is popped, the parent colorprocs must be restored.
7660
   Since the color mapping procs are all based upon the device, we must have a
7661
   nested list based upon the transparency group color space.  This nesting
7662
   must be outside the nested ctx structures to allow the nesting for the
7663
   clist writer */
7664
static void
7665
pdf14_pop_group_color(gx_device *dev, const gs_gstate *pgs)
7666
19.6k
{
7667
19.6k
    pdf14_device *pdev = (pdf14_device *)dev;
7668
19.6k
    pdf14_group_color_t *group_color = pdev->color_model_stack;
7669
7670
19.6k
    if_debug0m('v', dev->memory, "[v]pdf14_pop_group_color\n");
7671
7672
    /* Update the link */
7673
19.6k
    pdev->color_model_stack = group_color->previous;
7674
7675
    /* Free the old one */
7676
19.6k
    gs_free_object(dev->memory->stable_memory, group_color, "pdf14_clr_free");
7677
19.6k
}
7678
7679
static  int
7680
pdf14_begin_transparency_mask(gx_device *dev,
7681
                              const gx_transparency_mask_params_t *ptmp,
7682
                              const gs_rect *pbbox,
7683
                              gs_gstate *pgs, gs_memory_t *mem)
7684
1.22M
{
7685
1.22M
    pdf14_device *pdev = (pdf14_device *)dev;
7686
1.22M
    uint16_t bg_alpha = 0;   /* By default the background alpha (area outside mask) is zero */
7687
1.22M
    byte *transfer_fn;
7688
1.22M
    gs_int_rect rect;
7689
1.22M
    int code;
7690
1.22M
    int group_color_numcomps;
7691
1.22M
    gs_transparency_color_t group_color_type;
7692
1.22M
    bool deep = device_is_deep(dev);
7693
1.22M
    pdf14_group_color_t* group_color_info;
7694
7695
1.22M
    code = pdf14_initialize_ctx(dev, dev->color_info.num_components,
7696
1.22M
        dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, (const gs_gstate*)pgs);
7697
1.22M
    if (code < 0)
7698
0
        return code;
7699
7700
1.22M
    if (ptmp->subtype == TRANSPARENCY_MASK_None) {
7701
1.08M
        pdf14_ctx *ctx = pdev->ctx;
7702
7703
        /* free up any maskbuf on the current tos */
7704
1.08M
        if (ctx->mask_stack) {
7705
187k
            if (ctx->mask_stack->rc_mask->mask_buf != NULL ) {
7706
95.9k
                pdf14_buf_free(ctx->mask_stack->rc_mask->mask_buf);
7707
95.9k
                ctx->mask_stack->rc_mask->mask_buf = NULL;
7708
95.9k
            }
7709
187k
        }
7710
1.08M
        return 0;
7711
1.08M
    }
7712
137k
    transfer_fn = (byte *)gs_alloc_bytes(pdev->ctx->memory, (256+deep)<<deep,
7713
137k
                                         "pdf14_begin_transparency_mask");
7714
137k
    if (transfer_fn == NULL)
7715
0
        return_error(gs_error_VMerror);
7716
137k
    code = compute_group_device_int_rect(pdev, &rect, pbbox, pgs);
7717
137k
    if (code < 0)
7718
0
        return code;
7719
    /* If we have background components the background alpha may be nonzero */
7720
137k
    if (ptmp->Background_components)
7721
32.8k
        bg_alpha = (int)(65535 * ptmp->GrayBackground + 0.5);
7722
137k
    if_debug1m('v', dev->memory,
7723
137k
               "pdf14_begin_transparency_mask, bg_alpha = %d\n", bg_alpha);
7724
137k
    memcpy(transfer_fn, ptmp->transfer_fn, (256+deep)<<deep);
7725
   /* If the group color is unknown, then we must use the previous group color
7726
       space or the device process color space */
7727
137k
    if (ptmp->group_color_type == UNKNOWN){
7728
0
        if (pdev->ctx->stack){
7729
            /* Use previous group color space */
7730
0
            group_color_numcomps = pdev->ctx->stack->n_chan-1;  /* Remove alpha */
7731
0
        } else {
7732
            /* Use process color space */
7733
0
            group_color_numcomps = pdev->color_info.num_components;
7734
0
        }
7735
0
        switch (group_color_numcomps) {
7736
0
            case 1:
7737
0
                group_color_type = GRAY_SCALE;
7738
0
                break;
7739
0
            case 3:
7740
0
                group_color_type = DEVICE_RGB;
7741
0
                break;
7742
0
            case 4:
7743
0
                group_color_type = DEVICE_CMYK;
7744
0
            break;
7745
0
            default:
7746
                /* We can end up here if we are in a deviceN color space and
7747
                   we have a sep output device */
7748
0
                group_color_type = DEVICEN;
7749
0
            break;
7750
0
         }
7751
137k
    } else {
7752
137k
        group_color_type = ptmp->group_color_type;
7753
137k
        group_color_numcomps = ptmp->group_color_numcomps;
7754
137k
    }
7755
7756
137k
    group_color_info = pdf14_push_color_model(dev, group_color_type, ptmp->icc_hashcode,
7757
137k
                                               ptmp->iccprofile, true);
7758
137k
    if (group_color_info == NULL)
7759
0
        return gs_error_VMerror;
7760
7761
    /* Note that the soft mask always follows the group color requirements even
7762
       when we have a separable device */
7763
137k
    code = pdf14_push_transparency_mask(pdev->ctx, &rect, bg_alpha,
7764
137k
                                        transfer_fn, ptmp->function_is_identity,
7765
137k
                                        ptmp->idle, ptmp->replacing,
7766
137k
                                        ptmp->mask_id, ptmp->subtype,
7767
137k
                                        group_color_numcomps,
7768
137k
                                        ptmp->Background_components,
7769
137k
                                        ptmp->Background,
7770
137k
                                        ptmp->Matte_components,
7771
137k
                                        ptmp->Matte,
7772
137k
                                        ptmp->GrayBackground,
7773
137k
                                        group_color_info);
7774
137k
    if (code < 0)
7775
0
        return code;
7776
7777
137k
    return 0;
7778
137k
}
7779
7780
static  int
7781
pdf14_end_transparency_mask(gx_device *dev, gs_gstate *pgs)
7782
137k
{
7783
137k
    pdf14_device *pdev = (pdf14_device *)dev;
7784
137k
    pdf14_group_color_t *group_color;
7785
137k
    int ok;
7786
7787
137k
    if_debug0m('v', dev->memory, "pdf14_end_transparency_mask\n");
7788
137k
    ok = pdf14_pop_transparency_mask(pdev->ctx, pgs, dev);
7789
#ifdef DEBUG
7790
    pdf14_debug_mask_stack_state(pdev->ctx);
7791
#endif
7792
7793
    /* May need to reset some color stuff related
7794
     * to a mismatch between the Smask color space
7795
     * and the Smask blending space */
7796
137k
    if (pdev->ctx->stack != NULL ) {
7797
137k
        group_color = pdev->ctx->stack->group_color_info;
7798
137k
        if (!(group_color->group_color_mapping_procs == NULL &&
7799
137k
            group_color->group_color_comp_index == NULL)) {
7800
137k
            pgs->get_cmap_procs = group_color->get_cmap_procs;
7801
137k
            gx_set_cmap_procs(pgs, dev);
7802
137k
            set_dev_proc(pdev, get_color_mapping_procs, group_color->group_color_mapping_procs);
7803
137k
            set_dev_proc(pdev, get_color_comp_index, group_color->group_color_comp_index);
7804
137k
            pdev->color_info.polarity = group_color->polarity;
7805
137k
            pdev->color_info.opmsupported = GX_CINFO_OPMSUPPORTED_UNKNOWN;
7806
137k
            pdev->color_info.num_components = group_color->num_components;
7807
137k
            pdev->color_info.depth = group_color->depth;
7808
137k
            pdev->blend_procs = group_color->blend_procs;
7809
137k
            pdev->ctx->additive = group_color->isadditive;
7810
137k
            pdev->pdf14_procs = group_color->unpack_procs;
7811
137k
            pdev->color_info.max_color = group_color->max_color;
7812
137k
            pdev->color_info.max_gray = group_color->max_gray;
7813
137k
            set_dev_proc(pdev, encode_color, group_color->encode);
7814
137k
            set_dev_proc(pdev, decode_color, group_color->decode);
7815
137k
            memcpy(&(pdev->color_info.comp_bits),&(group_color->comp_bits),
7816
137k
                                GX_DEVICE_COLOR_MAX_COMPONENTS);
7817
137k
            memcpy(&(pdev->color_info.comp_shift),&(group_color->comp_shift),
7818
137k
                                GX_DEVICE_COLOR_MAX_COMPONENTS);
7819
            /* Take care of the ICC profile */
7820
137k
            if (group_color->icc_profile != NULL) {
7821
137k
                gsicc_adjust_profile_rc(dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE],
7822
137k
                                        -1, "pdf14_end_transparency_mask");
7823
137k
                dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] = group_color->icc_profile;
7824
137k
                gsicc_adjust_profile_rc(dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE],
7825
137k
                                         1, "pdf14_end_transparency_mask");
7826
137k
            }
7827
137k
        }
7828
137k
    }
7829
137k
    return ok;
7830
137k
}
7831
7832
static  int
7833
do_mark_fill_rectangle_ko_simple(gx_device *dev, int x, int y, int w, int h,
7834
                                 gx_color_index color,
7835
                                 const gx_device_color *pdc, bool devn)
7836
138k
{
7837
138k
    pdf14_device *pdev = (pdf14_device *)dev;
7838
138k
    pdf14_buf *buf = pdev->ctx->stack;
7839
138k
    gs_blend_mode_t blend_mode = pdev->blend_mode;
7840
138k
    bool tag_blend = blend_mode == BLEND_MODE_Normal ||
7841
138k
        blend_mode == BLEND_MODE_Compatible ||
7842
138k
        blend_mode == BLEND_MODE_CompatibleOverprint;
7843
138k
    int i, j, k;
7844
138k
    byte *bline, *bg_ptr, *line, *dst_ptr;
7845
138k
    byte src[PDF14_MAX_PLANES];
7846
138k
    byte dst[PDF14_MAX_PLANES] = { 0 };
7847
138k
    byte dst2[PDF14_MAX_PLANES] = { 0 };
7848
138k
    int rowstride = buf->rowstride;
7849
138k
    int planestride = buf->planestride;
7850
138k
    int num_chan = buf->n_chan;
7851
138k
    int num_comp = num_chan - 1;
7852
138k
    int shape_off = num_chan * planestride;
7853
138k
    bool has_shape = buf->has_shape;
7854
138k
    bool has_alpha_g = buf->has_alpha_g;
7855
138k
    int alpha_g_off = shape_off + (has_shape ? planestride : 0);
7856
138k
    int tag_off = shape_off + (has_alpha_g ? planestride : 0) +
7857
138k
                              (has_shape ? planestride : 0);
7858
138k
    bool has_tags = buf->has_tags;
7859
138k
    bool additive = pdev->ctx->additive;
7860
138k
    gs_graphics_type_tag_t curr_tag = GS_UNKNOWN_TAG;  /* Quiet compiler */
7861
138k
    gx_color_index mask = ((gx_color_index)1 << 8) - 1;
7862
138k
    int shift = 8;
7863
138k
    byte shape = 0; /* Quiet compiler. */
7864
138k
    byte src_alpha;
7865
138k
    bool overprint = pdev->op_state == PDF14_OP_STATE_FILL ? pdev->overprint : pdev->stroke_overprint;
7866
138k
    gx_color_index drawn_comps = pdev->op_state == PDF14_OP_STATE_FILL ?
7867
93.5k
        pdev->drawn_comps_fill : pdev->drawn_comps_stroke;
7868
138k
    gx_color_index comps;
7869
138k
    bool has_backdrop = buf->backdrop != NULL;
7870
7871
    /* If we are going out to a CMYK or CMYK + spots pdf14 device (i.e.
7872
       subtractive) and we are doing overprint with drawn_comps == 0
7873
       then this is a no-operation */
7874
138k
    if (overprint && drawn_comps == 0 && !buf->group_color_info->isadditive)
7875
0
        return 0;
7876
7877
138k
    if (buf->data == NULL)
7878
0
        return 0;
7879
#if 0
7880
    if (sizeof(color) <= sizeof(ulong))
7881
        if_debug6m('v', dev->memory,
7882
                   "[v]pdf14_mark_fill_rectangle_ko_simple, (%d, %d), %d x %d color = %lx, nc %d,\n",
7883
                   x, y, w, h, (ulong)color, num_chan);
7884
    else
7885
        if_debug7m('v', dev->memory,
7886
                   "[v]pdf14_mark_fill_rectangle_ko_simple, (%d, %d), %d x %d color = %8lx%08lx, nc %d,\n",
7887
                   x, y, w, h,
7888
                   (ulong)(color >> 8*(sizeof(color) - sizeof(ulong))), (ulong)color,
7889
                   num_chan);
7890
#endif
7891
    /*
7892
     * Unpack the gx_color_index values.  Complement the components for subtractive
7893
     * color spaces.
7894
     */
7895
138k
    if (devn) {
7896
281
        if (has_tags) {
7897
0
            curr_tag = pdc->tag;
7898
0
        }
7899
281
        if (additive) {
7900
1.12k
            for (j = 0; j < num_comp; j++) {
7901
843
                src[j] = ((pdc->colors.devn.values[j]) >> shift & mask);
7902
843
            }
7903
281
        } else {
7904
0
            for (j = 0; j < num_comp; j++) {
7905
0
                src[j] = 255 - ((pdc->colors.devn.values[j]) >> shift & mask);
7906
0
            }
7907
0
        }
7908
138k
    } else {
7909
138k
        if (has_tags) {
7910
0
            curr_tag = (color >> (num_comp * 8)) & 0xff;
7911
0
        }
7912
138k
        pdev->pdf14_procs->unpack_color(num_comp, color, pdev, src);
7913
138k
    }
7914
7915
138k
    if (!has_tags)
7916
138k
        tag_off = 0;
7917
7918
138k
    src_alpha = src[num_comp] = (byte)floor (255 * pdev->alpha + 0.5);
7919
138k
    if (has_shape) {
7920
0
        shape = (byte)floor (255 * pdev->shape + 0.5);
7921
138k
    } else {
7922
138k
        shape_off = 0;
7923
138k
    }
7924
7925
138k
    if (!has_alpha_g)
7926
0
        alpha_g_off = 0;
7927
138k
    src_alpha = 255 - src_alpha;
7928
138k
    shape = 255 - shape;
7929
7930
    /* Fit the mark into the bounds of the buffer */
7931
138k
    if (x < buf->rect.p.x) {
7932
0
        w += x - buf->rect.p.x;
7933
0
        x = buf->rect.p.x;
7934
0
    }
7935
138k
    if (y < buf->rect.p.y) {
7936
0
      h += y - buf->rect.p.y;
7937
0
      y = buf->rect.p.y;
7938
0
    }
7939
138k
    if (x + w > buf->rect.q.x) w = buf->rect.q.x - x;
7940
138k
    if (y + h > buf->rect.q.y) h = buf->rect.q.y - y;
7941
    /* Update the dirty rectangle with the mark. */
7942
138k
    if (x < buf->dirty.p.x) buf->dirty.p.x = x;
7943
138k
    if (y < buf->dirty.p.y) buf->dirty.p.y = y;
7944
138k
    if (x + w > buf->dirty.q.x) buf->dirty.q.x = x + w;
7945
138k
    if (y + h > buf->dirty.q.y) buf->dirty.q.y = y + h;
7946
7947
    /* composite with backdrop only. */
7948
138k
    if (has_backdrop)
7949
138k
        bline = buf->backdrop + (x - buf->rect.p.x) + (y - buf->rect.p.y) * rowstride;
7950
0
    else
7951
0
        bline = NULL;
7952
7953
138k
    line = buf->data + (x - buf->rect.p.x) + (y - buf->rect.p.y) * rowstride;
7954
7955
296k
    for (j = 0; j < h; ++j) {
7956
158k
        bg_ptr = bline;
7957
158k
        dst_ptr = line;
7958
13.1M
        for (i = 0; i < w; ++i) {
7959
            /* Complement the components for subtractive color spaces */
7960
13.0M
            if (has_backdrop) {
7961
13.0M
                if (additive) {
7962
63.9M
                    for (k = 0; k < num_chan; ++k)
7963
50.8M
                        dst[k] = bg_ptr[k * planestride];
7964
13.0M
                } else {
7965
0
                    for (k = 0; k < num_comp; ++k)
7966
0
                        dst2[k] = dst[k] = 255 - bg_ptr[k * planestride];
7967
0
                }
7968
13.0M
                dst2[num_comp] = dst[num_comp] = bg_ptr[num_comp * planestride];  /* alpha doesn't invert */
7969
13.0M
            }
7970
13.0M
            if (buf->isolated || !has_backdrop) {
7971
0
                art_pdf_knockoutisolated_group_8(dst, src, num_comp);
7972
13.0M
            } else {
7973
13.0M
                art_pdf_composite_knockout_8(dst, src, num_comp,
7974
13.0M
                                            blend_mode, pdev->blend_procs, pdev);
7975
13.0M
            }
7976
            /* Complement the results for subtractive color spaces */
7977
13.0M
            if (additive) {
7978
13.0M
                if (!overprint) {
7979
63.9M
                    for (k = 0; k < num_chan; ++k)
7980
50.8M
                        dst_ptr[k * planestride] = dst[k];
7981
13.0M
                } else {
7982
                    /* Hybrid additive with subtractive spots */
7983
                    /* We may have to do the compatible overprint blending */
7984
0
                    if (!buf->isolated && drawn_comps != (((size_t)1 << (size_t)dev->color_info.num_components) - (size_t)1)) {
7985
0
                        art_pdf_composite_knockout_8(dst2, src, num_comp,
7986
0
                            blend_mode, pdev->blend_procs, pdev);
7987
0
                    }
7988
0
                    for (k = 0, comps = drawn_comps; k < num_comp; ++k, comps >>= 1) {
7989
0
                        if ((comps & 0x1) != 0) {
7990
0
                            dst_ptr[k * planestride] = dst[k];
7991
0
                        } else {
7992
                            /* Compatible overprint blend result. */
7993
0
                            dst_ptr[k * planestride] = dst2[k];
7994
0
                        }
7995
0
                    }
7996
0
                    dst_ptr[num_comp * planestride] = dst[num_comp];    /* alpha */
7997
0
                }
7998
13.0M
            } else {
7999
0
                if (overprint) {
8000
                    /* We may have to do the compatible overprint blending */
8001
0
                    if (!buf->isolated && drawn_comps != (( (size_t) 1 << (size_t) dev->color_info.num_components)-(size_t) 1)) {
8002
0
                        art_pdf_composite_knockout_8(dst2, src, num_comp,
8003
0
                            blend_mode, pdev->blend_procs, pdev);
8004
0
                    }
8005
0
                    for (k = 0, comps = drawn_comps; k < num_comp; ++k, comps >>= 1) {
8006
0
                        if ((comps & 0x1) != 0) {
8007
0
                            dst_ptr[k * planestride] = 255 - dst[k];
8008
0
                        } else {
8009
                            /* Compatible overprint blend result. */
8010
0
                            dst_ptr[k * planestride] = 255 - dst2[k];
8011
0
                        }
8012
0
                    }
8013
0
                } else {
8014
0
                    for (k = 0; k < num_comp; ++k)
8015
0
                        dst_ptr[k * planestride] = 255 - dst[k];
8016
0
                }
8017
0
                dst_ptr[num_comp * planestride] = dst[num_comp];
8018
0
            }
8019
13.0M
            if (tag_off) {
8020
                /* If src alpha is 100% then set to curr_tag, else or */
8021
                /* other than Normal BM, we always OR */
8022
0
                if (src[num_comp] == 255 && tag_blend) {
8023
0
                    dst_ptr[tag_off] = curr_tag;
8024
0
                } else {
8025
0
                    dst_ptr[tag_off] |= curr_tag;
8026
0
                }
8027
0
            }
8028
            /* Knockout group alpha and shape too */
8029
13.0M
            if (alpha_g_off)
8030
13.0M
                dst_ptr[alpha_g_off] = 255 - src_alpha;
8031
13.0M
            if (shape_off)
8032
0
                dst_ptr[shape_off] = 255 - shape;
8033
13.0M
            ++dst_ptr;
8034
13.0M
            if (has_backdrop)
8035
13.0M
                ++bg_ptr;
8036
13.0M
        }
8037
158k
        bline += rowstride;
8038
158k
        line += rowstride;
8039
158k
    }
8040
#if 0
8041
/* #if RAW_DUMP */
8042
    /* Dump the current buffer to see what we have. */
8043
    dump_raw_buffer(pdev->ctx->memory,
8044
                    pdev->ctx->stack->rect.q.y-pdev->ctx->stack->rect.p.y,
8045
                    pdev->ctx->stack->rect.q.x-pdev->ctx->stack->rect.p.x,
8046
                    pdev->ctx->stack->n_planes,
8047
                    pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
8048
                    "Draw_Rect_KO", pdev->ctx->stack->data,
8049
                    pdev->ctx->stack->deep);
8050
    global_index++;
8051
#endif
8052
138k
    return 0;
8053
138k
}
8054
8055
static  int
8056
do_mark_fill_rectangle_ko_simple16(gx_device *dev, int x, int y, int w, int h,
8057
                                   gx_color_index color,
8058
                                   const gx_device_color *pdc, bool devn)
8059
0
{
8060
0
    pdf14_device *pdev = (pdf14_device *)dev;
8061
0
    pdf14_buf *buf = pdev->ctx->stack;
8062
0
    gs_blend_mode_t blend_mode = pdev->blend_mode;
8063
0
    bool tag_blend = blend_mode == BLEND_MODE_Normal ||
8064
0
        blend_mode == BLEND_MODE_Compatible ||
8065
0
        blend_mode == BLEND_MODE_CompatibleOverprint;
8066
0
    int i, j, k;
8067
0
    uint16_t *bline, *bg_ptr, *line, *dst_ptr;
8068
0
    uint16_t src[PDF14_MAX_PLANES];
8069
0
    uint16_t dst[PDF14_MAX_PLANES] = { 0 };
8070
0
    uint16_t dst2[PDF14_MAX_PLANES] = { 0 };
8071
0
    int rowstride = buf->rowstride;
8072
0
    int planestride = buf->planestride;
8073
0
    int num_chan = buf->n_chan;
8074
0
    int num_comp = num_chan - 1;
8075
0
    int shape_off = num_chan * planestride;
8076
0
    bool has_shape = buf->has_shape;
8077
0
    bool has_alpha_g = buf->has_alpha_g;
8078
0
    int alpha_g_off = shape_off + (has_shape ? planestride : 0);
8079
0
    int tag_off = shape_off + (has_alpha_g ? planestride : 0) +
8080
0
                              (has_shape ? planestride : 0);
8081
0
    bool has_tags = buf->has_tags;
8082
0
    bool additive = pdev->ctx->additive;
8083
0
    gs_graphics_type_tag_t curr_tag = GS_UNKNOWN_TAG;  /* Quiet compiler */
8084
0
    uint16_t shape = 0; /* Quiet compiler. */
8085
0
    uint16_t src_alpha;
8086
0
    bool overprint = pdev->op_state == PDF14_OP_STATE_FILL ? pdev->overprint : pdev->stroke_overprint;
8087
0
    gx_color_index drawn_comps = pdev->op_state == PDF14_OP_STATE_FILL ?
8088
0
        pdev->drawn_comps_fill : pdev->drawn_comps_stroke;
8089
0
    gx_color_index comps;
8090
0
    bool has_backdrop = buf->backdrop != NULL;
8091
8092
    /* If we are going out to a CMYK or CMYK + spots pdf14 device (i.e.
8093
       subtractive) and we are doing overprint with drawn_comps == 0
8094
       then this is a no-operation */
8095
0
    if (overprint && drawn_comps == 0 && !buf->group_color_info->isadditive)
8096
0
        return 0;
8097
8098
0
    if (buf->data == NULL)
8099
0
        return 0;
8100
#if 0
8101
    if (sizeof(color) <= sizeof(ulong))
8102
        if_debug6m('v', dev->memory,
8103
                   "[v]pdf14_mark_fill_rectangle_ko_simple16, (%d, %d), %d x %d color = %lx, nc %d,\n",
8104
                   x, y, w, h, (ulong)color, num_chan);
8105
    else
8106
        if_debug7m('v', dev->memory,
8107
                   "[v]pdf14_mark_fill_rectangle_ko_simple16, (%d, %d), %d x %d color = %8lx%08lx, nc %d,\n",
8108
                   x, y, w, h,
8109
                   (ulong)(color >> 8*(sizeof(color) - sizeof(ulong))), (ulong)color,
8110
                   num_chan);
8111
#endif
8112
    /*
8113
     * Unpack the gx_color_index values.  Complement the components for subtractive
8114
     * color spaces.
8115
     */
8116
0
    if (devn) {
8117
0
        if (has_tags) {
8118
0
            curr_tag = pdc->tag;
8119
0
        }
8120
0
        if (additive) {
8121
0
            for (j = 0; j < num_comp; j++) {
8122
0
                src[j] = pdc->colors.devn.values[j];
8123
0
            }
8124
0
        } else {
8125
0
            for (j = 0; j < num_comp; j++) {
8126
0
                src[j] = 65535 - pdc->colors.devn.values[j];
8127
0
            }
8128
0
        }
8129
0
    } else {
8130
0
        if (has_tags) {
8131
0
            curr_tag = (color >> (num_comp * 16)) & 0xff;
8132
0
        }
8133
0
        pdev->pdf14_procs->unpack_color16(num_comp, color, pdev, src);
8134
0
    }
8135
8136
0
    src_alpha = src[num_comp] = (uint16_t)floor (65535 * pdev->alpha + 0.5);
8137
0
    if (has_shape) {
8138
0
        shape = (uint16_t)floor (65535 * pdev->shape + 0.5);
8139
0
    } else {
8140
0
        shape_off = 0;
8141
0
    }
8142
8143
0
    if (!has_tags) {
8144
0
        tag_off = 0;
8145
0
    }
8146
8147
0
    if (!has_alpha_g)
8148
0
        alpha_g_off = 0;
8149
0
    src_alpha = 65535 - src_alpha;
8150
0
    shape = 65535 - shape;
8151
8152
    /* Fit the mark into the bounds of the buffer */
8153
0
    if (x < buf->rect.p.x) {
8154
0
        w += x - buf->rect.p.x;
8155
0
        x = buf->rect.p.x;
8156
0
    }
8157
0
    if (y < buf->rect.p.y) {
8158
0
      h += y - buf->rect.p.y;
8159
0
      y = buf->rect.p.y;
8160
0
    }
8161
0
    if (x + w > buf->rect.q.x) w = buf->rect.q.x - x;
8162
0
    if (y + h > buf->rect.q.y) h = buf->rect.q.y - y;
8163
    /* Update the dirty rectangle with the mark. */
8164
0
    if (x < buf->dirty.p.x) buf->dirty.p.x = x;
8165
0
    if (y < buf->dirty.p.y) buf->dirty.p.y = y;
8166
0
    if (x + w > buf->dirty.q.x) buf->dirty.q.x = x + w;
8167
0
    if (y + h > buf->dirty.q.y) buf->dirty.q.y = y + h;
8168
8169
8170
    /* composite with backdrop only. */
8171
0
    if (has_backdrop)
8172
0
        bline = (uint16_t*)(void*)(buf->backdrop + (x - buf->rect.p.x) * 2 + (y - buf->rect.p.y) * rowstride);
8173
0
    else
8174
0
        bline = NULL;
8175
8176
0
    line = (uint16_t *)(void *)(buf->data + (x - buf->rect.p.x)*2 + (y - buf->rect.p.y) * rowstride);
8177
0
    planestride >>= 1;
8178
0
    rowstride >>= 1;
8179
0
    alpha_g_off >>= 1;
8180
0
    shape_off >>= 1;
8181
0
    tag_off >>= 1;
8182
8183
0
    for (j = 0; j < h; ++j) {
8184
0
        bg_ptr = bline;
8185
0
        dst_ptr = line;
8186
0
        for (i = 0; i < w; ++i) {
8187
            /* Complement the components for subtractive color spaces */
8188
0
            if (has_backdrop) {
8189
0
                if (additive) {
8190
0
                    for (k = 0; k < num_chan; ++k)
8191
0
                        dst[k] = bg_ptr[k * planestride];
8192
0
                } else {
8193
0
                    for (k = 0; k < num_comp; ++k)
8194
0
                        dst2[k] = dst[k] = 65535 - bg_ptr[k * planestride];
8195
0
                }
8196
0
                dst2[num_comp] = dst[num_comp] = bg_ptr[num_comp * planestride];  /* alpha doesn't invert */
8197
0
            }
8198
0
            if (buf->isolated || !has_backdrop) {
8199
0
                art_pdf_knockoutisolated_group_16(dst, src, num_comp);
8200
0
            } else {
8201
0
                art_pdf_composite_knockout_16(dst, src, num_comp,
8202
0
                                              blend_mode, pdev->blend_procs, pdev);
8203
0
            }
8204
            /* Complement the results for subtractive color spaces */
8205
0
            if (additive) {
8206
0
                if (!overprint) {
8207
0
                    for (k = 0; k < num_chan; ++k)
8208
0
                        dst_ptr[k * planestride] = dst[k];
8209
0
                } else {
8210
                    /* Hybrid additive with subtractive spots */
8211
                    /* We may have to do the compatible overprint blending */
8212
0
                    if (!buf->isolated && drawn_comps != (((size_t)1 << (size_t)dev->color_info.num_components) - (size_t)1)) {
8213
0
                        art_pdf_composite_knockout_16(dst2, src, num_comp,
8214
0
                            blend_mode, pdev->blend_procs, pdev);
8215
0
                    }
8216
0
                    for (k = 0, comps = drawn_comps; k < num_comp; ++k, comps >>= 1) {
8217
0
                        if ((comps & 0x1) != 0) {
8218
0
                            dst_ptr[k * planestride] = dst[k];
8219
0
                        } else {
8220
                            /* Compatible overprint blend result. */
8221
0
                            dst_ptr[k * planestride] = dst2[k];
8222
0
                        }
8223
0
                    }
8224
0
                    dst_ptr[num_comp * planestride] = dst[num_comp];    /* alpha */
8225
0
                }
8226
0
            } else {
8227
0
                if (overprint) {
8228
                    /* We may have to do the compatible overprint blending */
8229
0
                    if (!buf->isolated && drawn_comps != (((size_t)1 << (size_t)dev->color_info.num_components) - (size_t)1)) {
8230
0
                        art_pdf_composite_knockout_16(dst2, src, num_comp,
8231
0
                            blend_mode, pdev->blend_procs, pdev);
8232
0
                    }
8233
0
                    for (k = 0, comps = drawn_comps; k < num_comp; ++k, comps >>= 1) {
8234
0
                        if ((comps & 0x1) != 0) {
8235
0
                            dst_ptr[k * planestride] = 65535 - dst[k];
8236
0
                        } else {
8237
                            /* Compatible overprint blend result. */
8238
0
                            dst_ptr[k * planestride] = 65535 - dst2[k];
8239
0
                        }
8240
0
                    }
8241
0
                } else {
8242
0
                    for (k = 0; k < num_comp; ++k)
8243
0
                        dst_ptr[k * planestride] = 65535 - dst[k];
8244
0
                }
8245
0
                dst_ptr[num_comp * planestride] = dst[num_comp];
8246
0
            }
8247
0
            if (tag_off) {
8248
                /* FIXME: As we are knocking out, possibly, we should be
8249
                 * always overwriting tag values here? */
8250
                /* If src alpha is 100% then set to curr_tag, else or */
8251
                /* other than Normal BM, we always OR */
8252
0
                if (src[num_comp] == 65535 && tag_blend) {
8253
0
                    dst_ptr[tag_off] = curr_tag;
8254
0
                } else {
8255
0
                    dst_ptr[tag_off] |= curr_tag;
8256
0
                }
8257
0
            }
8258
            /* Knockout group alpha and shape too */
8259
0
            if (alpha_g_off)
8260
0
                dst_ptr[alpha_g_off] = 65535 - src_alpha;
8261
0
            if (shape_off)
8262
0
                dst_ptr[shape_off] = 65535 - shape;
8263
0
            ++dst_ptr;
8264
0
            if (has_backdrop)
8265
0
                ++bg_ptr;
8266
0
        }
8267
0
        bline += rowstride;
8268
0
        line += rowstride;
8269
0
    }
8270
#if 0
8271
/* #if RAW_DUMP */
8272
    /* Dump the current buffer to see what we have. */
8273
    dump_raw_buffer(pdev->ctx->memory,
8274
                    pdev->ctx->stack->rect.q.y-pdev->ctx->stack->rect.p.y,
8275
                    pdev->ctx->stack->rect.q.x-pdev->ctx->stack->rect.p.x,
8276
                    pdev->ctx->stack->n_planes,
8277
                    pdev->ctx->stack->planestride, pdev->ctx->stack->rowstride,
8278
                    "Draw_Rect_KO", pdev->ctx->stack->data,
8279
                    pdev->ctx->stack->deep);
8280
    global_index++;
8281
#endif
8282
0
    return 0;
8283
0
}
8284
8285
static  int
8286
pdf14_mark_fill_rectangle_ko_simple(gx_device * dev, int x, int y, int w, int h,
8287
                                    gx_color_index color,
8288
                                    const gx_device_color *pdc, bool devn)
8289
138k
{
8290
138k
    pdf14_device *pdev = (pdf14_device *)dev;
8291
138k
    pdf14_buf *buf = pdev->ctx->stack;
8292
8293
138k
    if (buf->deep)
8294
0
        return do_mark_fill_rectangle_ko_simple16(dev, x, y, w, h, color, pdc, devn);
8295
138k
    else
8296
138k
        return do_mark_fill_rectangle_ko_simple(dev, x, y, w, h, color, pdc, devn);
8297
138k
}
8298
8299
/**
8300
 * Here we have logic to override the cmap_procs with versions that
8301
 * do not apply the transfer function. These copies should track the
8302
 * versions in gxcmap.c.
8303
 **/
8304
static  cmap_proc_gray(pdf14_cmap_gray_direct);
8305
static  cmap_proc_rgb(pdf14_cmap_rgb_direct);
8306
static  cmap_proc_cmyk(pdf14_cmap_cmyk_direct);
8307
static  cmap_proc_separation(pdf14_cmap_separation_direct);
8308
static  cmap_proc_devicen(pdf14_cmap_devicen_direct);
8309
static  cmap_proc_is_halftoned(pdf14_cmap_is_halftoned);
8310
8311
static  const gx_color_map_procs pdf14_cmap_many = {
8312
     pdf14_cmap_gray_direct,
8313
     pdf14_cmap_rgb_direct,
8314
     pdf14_cmap_cmyk_direct,
8315
     pdf14_cmap_separation_direct,
8316
     pdf14_cmap_devicen_direct,
8317
     pdf14_cmap_is_halftoned
8318
    };
8319
8320
/**
8321
 * Note: copied from gxcmap.c because it's inlined.
8322
 **/
8323
static  inline void
8324
map_components_to_colorants(const frac * pcc,
8325
                            const gs_devicen_color_map * pcolor_component_map,
8326
                            frac * plist)
8327
234k
{
8328
234k
    int i = pcolor_component_map->num_colorants - 1;
8329
234k
    int pos;
8330
8331
    /* Clear all output colorants first */
8332
1.17M
    for (; i >= 0; i--) {
8333
938k
        plist[i] = frac_0;
8334
938k
    }
8335
    /* Map color components into output list */
8336
479k
    for (i = pcolor_component_map->num_components - 1; i >= 0; i--) {
8337
245k
        pos = pcolor_component_map->color_map[i];
8338
245k
        if (pos >= 0)
8339
245k
            plist[pos] = pcc[i];
8340
245k
    }
8341
234k
}
8342
8343
/* See Section 7.6.4 of PDF 1.7 spec */
8344
static inline bool
8345
pdf14_state_opaque(gx_device *pdev, const gs_gstate *pgs)
8346
13.4M
{
8347
13.4M
    if (pgs->fillconstantalpha != 1.0 ||
8348
13.4M
        pgs->strokeconstantalpha != 1.0 ||
8349
13.4M
        !(pgs->blend_mode == BLEND_MODE_Normal ||
8350
13.4M
          pgs->blend_mode == BLEND_MODE_CompatibleOverprint))
8351
8.47k
        return 0;
8352
8353
    /* We can only be opaque if we're not in an SMask. */
8354
13.4M
    return dev_proc(pdev, dev_spec_op)(pdev,
8355
13.4M
                                       gxdso_in_smask,
8356
13.4M
                                       NULL, 0) != 1;
8357
13.4M
}
8358
8359
static  void
8360
pdf14_cmap_gray_direct(frac gray, gx_device_color * pdc, const gs_gstate * pgs,
8361
                       gx_device * dev, gs_color_select_t select)
8362
2.14M
{
8363
2.14M
    int i,ncomps;
8364
2.14M
    frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
8365
2.14M
    gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
8366
2.14M
    gx_color_index color;
8367
2.14M
    gx_device *trans_device;
8368
2.14M
    const gx_device *map_dev;
8369
2.14M
    const gx_cm_color_map_procs *procs;
8370
8371
    /* If trans device is set, we need to use its procs. */
8372
2.14M
    if (pgs->trans_device != NULL) {
8373
31.6k
        trans_device = pgs->trans_device;
8374
2.11M
    } else {
8375
2.11M
        trans_device = dev;
8376
2.11M
    }
8377
2.14M
    ncomps = trans_device->color_info.num_components;
8378
8379
    /* map to the color model */
8380
2.14M
    procs = dev_proc(trans_device, get_color_mapping_procs)(trans_device, &map_dev);
8381
2.14M
    procs->map_gray(map_dev, gray, cm_comps);
8382
8383
2.14M
    if (pdf14_state_opaque(trans_device, pgs)) {
8384
43.8k
        for (i = 0; i < ncomps; i++)
8385
22.8k
            cv[i] = frac2cv(gx_map_color_frac(pgs, cm_comps[i], effective_transfer[i]));
8386
2.12M
    } else {
8387
4.24M
        for (i = 0; i < ncomps; i++)
8388
2.12M
            cv[i] = frac2cv(cm_comps[i]);
8389
2.12M
    }
8390
8391
    /* If output device supports devn, we need to make sure we send it the
8392
       proper color type.  We now support Gray + spots as devn colors */
8393
2.14M
    if (dev_proc(trans_device, dev_spec_op)(trans_device, gxdso_supports_devn, NULL, 0)) {
8394
180k
        for (i = 0; i < ncomps; i++)
8395
90.0k
            pdc->colors.devn.values[i] = cv[i];
8396
90.0k
        pdc->type = gx_dc_type_devn;
8397
2.05M
    } else {
8398
        /* encode as a color index */
8399
2.05M
        color = dev_proc(trans_device, encode_color)(trans_device, cv);
8400
        /* check if the encoding was successful; we presume failure is rare */
8401
2.05M
        if (color != gx_no_color_index)
8402
2.05M
            color_set_pure(pdc, color);
8403
2.05M
    }
8404
2.14M
}
8405
8406
static  void
8407
pdf14_cmap_rgb_direct(frac r, frac g, frac b, gx_device_color * pdc,
8408
     const gs_gstate * pgs, gx_device * dev, gs_color_select_t select)
8409
4.89M
{
8410
4.89M
    int i,ncomps;
8411
4.89M
    frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
8412
4.89M
    gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
8413
4.89M
    gx_color_index color;
8414
4.89M
    gx_device *trans_device;
8415
4.89M
    const gx_device *map_dev;
8416
4.89M
    const gx_cm_color_map_procs *procs;
8417
8418
    /* If trans device is set, we need to use its procs. */
8419
4.89M
    if (pgs->trans_device != NULL){
8420
224k
        trans_device = pgs->trans_device;
8421
4.67M
    } else {
8422
4.67M
        trans_device = dev;
8423
4.67M
    }
8424
4.89M
    ncomps = trans_device->color_info.num_components;
8425
    /* map to the color model */
8426
4.89M
    procs = dev_proc(trans_device, get_color_mapping_procs)(trans_device, &map_dev);
8427
4.89M
    procs->map_rgb(map_dev, pgs, r, g, b, cm_comps);
8428
8429
4.89M
    if (pdf14_state_opaque(trans_device, pgs)) {
8430
13.4M
        for (i = 0; i < ncomps; i++)
8431
10.1M
            cv[i] = frac2cv(gx_map_color_frac(pgs, cm_comps[i], effective_transfer[i]));
8432
3.37M
    } else {
8433
6.08M
        for (i = 0; i < ncomps; i++)
8434
4.55M
            cv[i] = frac2cv(cm_comps[i]);
8435
1.52M
    }
8436
8437
    /* If output device supports devn, we need to make sure we send it the
8438
       proper color type.  We now support RGB + spots as devn colors */
8439
4.89M
    if (dev_proc(trans_device, dev_spec_op)(trans_device, gxdso_supports_devn, NULL, 0)) {
8440
17.9M
        for (i = 0; i < ncomps; i++)
8441
13.4M
            pdc->colors.devn.values[i] = cv[i];
8442
4.48M
        pdc->type = gx_dc_type_devn;
8443
4.48M
    } else {
8444
        /* encode as a color index */
8445
408k
        color = dev_proc(trans_device, encode_color)(trans_device, cv);
8446
        /* check if the encoding was successful; we presume failure is rare */
8447
408k
        if (color != gx_no_color_index)
8448
408k
            color_set_pure(pdc, color);
8449
408k
    }
8450
4.89M
}
8451
8452
static  void
8453
pdf14_cmap_cmyk_direct(frac c, frac m, frac y, frac k, gx_device_color * pdc,
8454
     const gs_gstate * pgs, gx_device * dev, gs_color_select_t select,
8455
     const gs_color_space *pcs)
8456
6.38M
{
8457
6.38M
    int i, ncomps;
8458
6.38M
    frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
8459
6.38M
    gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
8460
6.38M
    gx_color_index color;
8461
6.38M
    gx_device *trans_device;
8462
6.38M
    const gx_device *map_dev;
8463
6.38M
    const gx_cm_color_map_procs *procs;
8464
8465
8466
    /* If trans device is set, we need to use its procs. */
8467
6.38M
    if (pgs->trans_device != NULL){
8468
4.74M
        trans_device = pgs->trans_device;
8469
4.74M
    } else {
8470
1.63M
        trans_device = dev;
8471
1.63M
    }
8472
6.38M
    ncomps = trans_device->color_info.num_components;
8473
8474
    /* Map to the color model. Transfer function is only used
8475
       if we are drawing with an opaque color. */
8476
6.38M
    procs = dev_proc(trans_device, get_color_mapping_procs)(trans_device, &map_dev);
8477
6.38M
    procs->map_cmyk(map_dev, c, m, y, k, cm_comps);
8478
8479
6.38M
    if (pdf14_state_opaque(trans_device, pgs)) {
8480
28.6M
        for (i = 0; i < ncomps; i++)
8481
22.9M
            cv[i] = frac2cv(gx_map_color_frac(pgs, cm_comps[i], effective_transfer[i]));
8482
5.72M
    } else {
8483
3.28M
        for (i = 0; i < ncomps; i++)
8484
2.62M
            cv[i] = frac2cv(cm_comps[i]);
8485
657k
    }
8486
8487
    /* if output device supports devn, we need to make sure we send it the
8488
       proper color type */
8489
6.38M
    if (dev_proc(trans_device, dev_spec_op)(trans_device, gxdso_supports_devn, NULL, 0)) {
8490
10.9M
        for (i = 0; i < ncomps; i++)
8491
8.79M
            pdc->colors.devn.values[i] = cv[i];
8492
2.20M
        pdc->type = gx_dc_type_devn;
8493
4.18M
    } else {
8494
        /* encode as a color index */
8495
4.18M
        color = dev_proc(trans_device, encode_color)(trans_device, cv);
8496
        /* check if the encoding was successful; we presume failure is rare */
8497
4.18M
        if (color != gx_no_color_index)
8498
4.18M
            color_set_pure(pdc, color);
8499
4.18M
    }
8500
6.38M
}
8501
8502
static int
8503
pdf14_get_num_spots(gx_device * dev)
8504
234k
{
8505
234k
    cmm_dev_profile_t *dev_profile;
8506
234k
    cmm_profile_t *icc_profile;
8507
234k
    gsicc_rendering_param_t render_cond;
8508
8509
234k
    dev_proc(dev, get_profile)(dev, &dev_profile);
8510
234k
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &icc_profile,
8511
234k
        &render_cond);
8512
234k
    return dev->color_info.num_components - icc_profile->num_comps;
8513
234k
}
8514
8515
static  void
8516
pdf14_cmap_separation_direct(frac all, gx_device_color * pdc, const gs_gstate * pgs,
8517
                 gx_device * dev, gs_color_select_t select, const gs_color_space *pcs)
8518
940
{
8519
940
    int i, ncomps = dev->color_info.num_components;
8520
940
    int num_spots = pdf14_get_num_spots(dev);
8521
940
    bool additive = dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE;
8522
940
    frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
8523
940
    gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
8524
940
    gx_color_index color;
8525
8526
940
    if (pgs->color_component_map.sep_type == SEP_ALL) {
8527
0
        frac comp_value = all;
8528
8529
        /*
8530
         * Invert the photometric interpretation for additive
8531
         * color spaces because separations are always subtractive.
8532
         */
8533
0
        if (additive)
8534
0
            comp_value = frac_1 - comp_value;
8535
        /* Use the "all" value for all components */
8536
0
        i = pgs->color_component_map.num_colorants - 1;
8537
0
        for (; i >= 0; i--)
8538
0
            cm_comps[i] = comp_value;
8539
940
    } else {
8540
940
        frac comp_value[GX_DEVICE_COLOR_MAX_COMPONENTS];
8541
8542
940
        if (pgs->color_component_map.sep_type == SEP_NONE) {
8543
0
            color_set_null(pdc);
8544
0
            return;
8545
0
        }
8546
8547
        /* map to the color model */
8548
1.88k
        for (i = pgs->color_component_map.num_components - 1; i >= 0; i--)
8549
940
            comp_value[i] = all;
8550
940
        map_components_to_colorants(comp_value, &(pgs->color_component_map), cm_comps);
8551
940
    }
8552
    /* apply the transfer function(s); convert to color values */
8553
940
    if (additive) {
8554
4.25k
        for (i = 0; i < ncomps; i++)
8555
3.40k
            cv[i] = frac2cv(gx_map_color_frac(pgs, cm_comps[i], effective_transfer[i]));
8556
        /* We are in an additive mode (blend space) and drawing with a sep color
8557
        into a sep device.  Make sure we are drawing "white" with the process
8558
        colorants, but only if we are not in an ALL case */
8559
850
        if (pgs->color_component_map.sep_type != SEP_ALL)
8560
3.40k
            for (i = 0; i < ncomps - num_spots; i++)
8561
2.55k
                cv[i] = gx_max_color_value;
8562
850
    } else
8563
450
        for (i = 0; i < ncomps; i++)
8564
360
            cv[i] = frac2cv(frac_1 - gx_map_color_frac(pgs, (frac)(frac_1 - cm_comps[i]), effective_transfer[i]));
8565
8566
8567
    /* if output device supports devn, we need to make sure we send it the
8568
       proper color type */
8569
940
    if (dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0)) {
8570
4.70k
        for (i = 0; i < ncomps; i++)
8571
3.76k
            pdc->colors.devn.values[i] = cv[i];
8572
940
        pdc->type = gx_dc_type_devn;
8573
940
    } else {
8574
        /* encode as a color index */
8575
0
        color = dev_proc(dev, encode_color)(dev, cv);
8576
        /* check if the encoding was successful; we presume failure is rare */
8577
0
        if (color != gx_no_color_index)
8578
0
            color_set_pure(pdc, color);
8579
0
    }
8580
940
}
8581
8582
static  void
8583
pdf14_cmap_devicen_direct(const frac * pcc,
8584
    gx_device_color * pdc, const gs_gstate * pgs, gx_device * dev,
8585
    gs_color_select_t select, const gs_color_space *pcs)
8586
233k
{
8587
233k
    int i, ncomps = dev->color_info.num_components;
8588
233k
    int num_spots = pdf14_get_num_spots(dev);
8589
233k
    frac cm_comps[GX_DEVICE_COLOR_MAX_COMPONENTS];
8590
233k
    gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
8591
233k
    gx_color_index color;
8592
233k
    gx_device *trans_device;
8593
8594
     /*  We may be coming from the clist writer which often forwards us the
8595
         target device. If this occurs we actually need to get to the color
8596
         space defined by the transparency group and we use the operators
8597
         defined by the transparency device to do the job.
8598
       */
8599
233k
    if (pgs->trans_device != NULL){
8600
233k
        trans_device = pgs->trans_device;
8601
233k
    } else {
8602
0
        trans_device = dev;
8603
0
    }
8604
233k
    ncomps = trans_device->color_info.num_components;
8605
    /* map to the color model */
8606
233k
    map_components_to_colorants(pcc, &(pgs->color_component_map), cm_comps);;
8607
    /* apply the transfer function(s); convert to color values */
8608
233k
    if (trans_device->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) {
8609
0
        for (i = 0; i < ncomps; i++)
8610
0
            cv[i] = frac2cv(gx_map_color_frac(pgs, cm_comps[i], effective_transfer[i]));
8611
        /* We are in an additive mode (blend space) and drawing with a sep color
8612
        into a sep device.  Make sure we are drawing "white" with the process
8613
        colorants */
8614
0
        for (i = 0; i < ncomps - num_spots; i++)
8615
0
            cv[i] = gx_max_color_value;
8616
0
    } else
8617
1.16M
        for (i = 0; i < ncomps; i++)
8618
934k
            cv[i] = frac2cv(frac_1 - gx_map_color_frac(pgs, (frac)(frac_1 - cm_comps[i]), effective_transfer[i]));
8619
    /* if output device supports devn, we need to make sure we send it the
8620
       proper color type */
8621
233k
    if (dev_proc(trans_device, dev_spec_op)(trans_device, gxdso_supports_devn, NULL, 0)) {
8622
182k
        for (i = 0; i < ncomps; i++)
8623
145k
            pdc->colors.devn.values[i] = cv[i];
8624
36.4k
        pdc->type = gx_dc_type_devn;
8625
197k
    } else {
8626
    /* encode as a color index */
8627
197k
        color = dev_proc(trans_device, encode_color)(trans_device, cv);
8628
        /* check if the encoding was successful; we presume failure is rare */
8629
197k
        if (color != gx_no_color_index)
8630
197k
            color_set_pure(pdc, color);
8631
197k
    }
8632
233k
}
8633
8634
static  bool
8635
pdf14_cmap_is_halftoned(const gs_gstate * pgs, gx_device * dev)
8636
40.9k
{
8637
40.9k
    return false;
8638
40.9k
}
8639
8640
static  const gx_color_map_procs *
8641
pdf14_get_cmap_procs(const gs_gstate *pgs, const gx_device * dev)
8642
482k
{
8643
    /* The pdf14 marking device itself is always continuous tone. */
8644
482k
    return &pdf14_cmap_many;
8645
482k
}
8646
8647
static int
8648
pdf14_dev_spec_op(gx_device *pdev, int dev_spec_op,
8649
                  void *data, int size)
8650
48.1M
{
8651
48.1M
    pdf14_device * p14dev = (pdf14_device *)pdev;
8652
8653
48.1M
    if (dev_spec_op == gxdso_supports_pattern_transparency)
8654
794k
        return 1;
8655
47.3M
    if (dev_spec_op == gxdso_pattern_shfill_doesnt_need_path)
8656
11.0k
        return 1;
8657
47.3M
    if (dev_spec_op == gxdso_is_pdf14_device) {
8658
1.06k
        if (data != NULL && size == sizeof(gx_device *))
8659
66
            *(gx_device **)data = pdev;
8660
1.06k
        return 1;
8661
1.06k
    }
8662
47.3M
    if (dev_spec_op == gxdso_device_child) {
8663
836
        pdf14_device *dev = (pdf14_device *)pdev;
8664
836
        gxdso_device_child_request *d = (gxdso_device_child_request *)data;
8665
836
        if (d->target == pdev) {
8666
836
            d->target = dev->target;
8667
836
            return 1;
8668
836
        }
8669
836
    }
8670
47.3M
    if (dev_spec_op == gxdso_supports_devn
8671
47.3M
     || dev_spec_op == gxdso_skip_icc_component_validation) {
8672
22.2M
        cmm_dev_profile_t *dev_profile;
8673
22.2M
        int code;
8674
22.2M
        code = dev_proc(pdev, get_profile)((gx_device*) pdev, &dev_profile);
8675
22.2M
        if (code == 0) {
8676
22.2M
            return dev_profile->supports_devn;
8677
22.2M
        } else {
8678
0
            return 0;
8679
0
        }
8680
22.2M
    }
8681
25.1M
    if (dev_spec_op == gxdso_pdf14_sep_device) {
8682
71.3k
        pdf14_device* dev = (pdf14_device*)pdev;
8683
8684
71.3k
        if (strcmp(dev->dname, "pdf14cmykspot") == 0 ||
8685
71.3k
            strcmp(dev->dname, "pdf14clistcmykspot") == 0)
8686
51.4k
            return 1;
8687
19.8k
        return 0;
8688
71.3k
    }
8689
25.0M
    if (dev_spec_op == gxdso_is_encoding_direct)
8690
785k
        return 1;
8691
8692
    /* We don't want to pass on these spec_ops either, because the child might respond
8693
     * with an inappropriate response when the PDF14 device is active. For example; the
8694
     * JPEG passthrough will give utterly wrong results if we pass that to a device which
8695
     * supports JPEG passthrough, because the pdf14 device needs to render the image.
8696
     */
8697
24.2M
    if (dev_spec_op == gxdso_in_pattern_accumulator)
8698
126k
        return 0;
8699
24.1M
    if (dev_spec_op == gxdso_copy_color_is_fast)
8700
460k
        return 0;
8701
23.6M
    if(dev_spec_op == gxdso_pattern_handles_clip_path)
8702
11.0k
        return 0;
8703
23.6M
    if(dev_spec_op == gxdso_supports_hlcolor)
8704
161
        return 0;
8705
23.6M
    if(dev_spec_op == gxdso_pattern_can_accum)
8706
35.6k
        return 0;
8707
23.6M
    if(dev_spec_op == gxdso_JPEG_passthrough_query)
8708
585
        return 0;
8709
23.6M
    if (dev_spec_op == gxdso_overprint_active) {
8710
2.09M
        if (p14dev->pclist_device != NULL) {
8711
2.07M
            return dev_proc(p14dev->pclist_device, dev_spec_op)(p14dev->pclist_device, dev_spec_op, data, size);
8712
2.07M
        } else {
8713
11.5k
            return p14dev->overprint || p14dev->stroke_overprint;
8714
11.5k
        }
8715
2.09M
    }
8716
8717
    /* These should be coming only from the abuf device
8718
       during fill-stroke operation. Any other use will
8719
       result in bad things. */
8720
21.5M
    if (dev_spec_op == gxdso_abuf_optrans)
8721
0
    {
8722
0
        int ret = p14dev->op_state;
8723
0
        overprint_abuf_state_t *state_data = (overprint_abuf_state_t *)data;
8724
0
        pdf14_abuf_state_t *pdf14_abuf = (pdf14_abuf_state_t *)&state_data->storage[0];
8725
0
        const gs_gstate* cpgs = state_data->pgs;
8726
0
        union {
8727
0
            const gs_gstate* cpgs;
8728
0
            gs_gstate* pgs;
8729
0
        } const_breaker;
8730
0
        gs_gstate* pgs;
8731
0
        int code = 0;
8732
0
        int code1 = 0;
8733
8734
        /* A compile time assert to check our storage types are appropriately sized. */
8735
0
        typedef char compile_time_assert[sizeof(pdf14_abuf_state_t) <= sizeof(state_data->storage) ? 1 : -1];
8736
8737
        /* I don't really like this, but there is no easy way around it. The device
8738
           in the pgs needs to be the pdf14 device to ensure that the compositor
8739
           actions occur with the gs_transparency calls. We have to call at that
8740
           level (as opposed to the gx_ or pdf14_ level) to ensure that the clist
8741
           operations are invoked. We could change the gs_trans calls to take a
8742
           device to avoid this dance but that changes the device procs. */
8743
0
        gx_device *curr_dev;
8744
8745
0
        const_breaker.cpgs = cpgs;
8746
0
        pgs = const_breaker.pgs;
8747
0
        curr_dev = pgs->device;
8748
0
        pgs->device = pdev;
8749
8750
0
        switch (state_data->op_trans) {
8751
8752
0
            case OP_FS_TRANS_PREFILL:
8753
0
                pdf14_abuf->orig_state = p14dev->op_state;
8754
0
                pdf14_abuf->blend_mode = cpgs->blend_mode;
8755
0
                pdf14_abuf->fill_alpha = cpgs->fillconstantalpha;
8756
0
                pdf14_abuf->stroke_alpha = cpgs->strokeconstantalpha;
8757
0
                pdf14_abuf->pgs = pgs; /* ref count? only used for this back and forth so ok */
8758
0
                if (pdf14_abuf->fill_alpha == 1.0 && pdf14_abuf->stroke_alpha == 1.0 &&
8759
0
                    pdf14_abuf->blend_mode == BLEND_MODE_Normal)
8760
0
                    pdf14_abuf->group_needed = false;
8761
0
                else
8762
0
                    pdf14_abuf->group_needed = true;
8763
8764
0
                if (pdf14_abuf->group_needed) {
8765
0
                    code = pdf14_fill_stroke_prefill(pdev, pgs, state_data->ppath,
8766
0
                        state_data->pcpath, pdf14_abuf->fill_alpha,
8767
0
                        pdf14_abuf->stroke_alpha, pdf14_abuf->blend_mode,
8768
0
                        &(pdf14_abuf->op_ca_eq_CA), &(pdf14_abuf->path_empty),
8769
0
                        state_data->alpha_buf_path_scale);
8770
0
                    if (code < 0)
8771
0
                        goto cleanup;
8772
0
                }
8773
0
                gs_update_trans_marking_params(pgs);
8774
0
                break;
8775
8776
0
            case OP_FS_TRANS_PRESTROKE:
8777
0
                if (pdf14_abuf->group_needed) {
8778
0
                    pdf14_fill_stroke_prestroke(pdev, pdf14_abuf->pgs, pdf14_abuf->stroke_alpha,
8779
0
                                                pdf14_abuf->blend_mode, pdf14_abuf->op_ca_eq_CA);
8780
0
                }
8781
0
                gs_update_trans_marking_params(pgs);
8782
0
                break;
8783
8784
0
            case OP_FS_TRANS_POSTSTROKE:
8785
0
                if (pdf14_abuf->group_needed) {
8786
0
                    pdf14_fill_stroke_poststroke(pdev, pdf14_abuf->pgs, pdf14_abuf->fill_alpha,
8787
0
                                                 pdf14_abuf->op_ca_eq_CA);
8788
0
                }
8789
0
                gs_update_trans_marking_params(pgs);
8790
8791
                /* fallthrough */
8792
8793
0
            case OP_FS_TRANS_CLEANUP:
8794
0
cleanup:
8795
0
                if (pdf14_abuf->group_needed) {
8796
0
                    code1 = pdf14_fill_stroke_cleanup(pdev, pdf14_abuf->pgs, pdf14_abuf->fill_alpha,
8797
0
                        pdf14_abuf->stroke_alpha, pdf14_abuf->blend_mode, (PDF14_OP_FS_STATE)pdf14_abuf->orig_state);
8798
0
                    if (code1 < 0)
8799
0
                        code = gs_note_error(gs_error_Fatal);
8800
0
                }
8801
0
                break;
8802
0
        }
8803
0
        pgs->device = curr_dev;
8804
8805
0
        return (code < 0) ? code : ret;
8806
0
    }
8807
8808
21.5M
    if (dev_spec_op == gxdso_in_smask_construction)
8809
2.10M
        return p14dev->in_smask_construction > 0;
8810
19.4M
    if (dev_spec_op == gxdso_in_smask)
8811
13.7M
        return p14dev->in_smask_construction > 0 || p14dev->depth_within_smask;
8812
5.63M
    if (dev_spec_op == gxdso_replacecolor) {
8813
5.42M
        gx_device *tdev = p14dev->target;
8814
5.42M
        cmm_dev_profile_t *tdev_profile;
8815
5.42M
        int code;
8816
8817
         /* If in a softmask or softmask construction do not allow
8818
           replacement. */
8819
5.42M
        if (p14dev->in_smask_construction > 0 || p14dev->depth_within_smask)
8820
181k
            return 0;
8821
8822
        /* If the target CS is different than the pdf14 profile add this information
8823
           for the target device that will be handling the replacement. While not
8824
           perfect this at least lets you do the replacehment and have some information
8825
           about what the situation is. */
8826
5.24M
        code = dev_proc(tdev, get_profile)((gx_device*) tdev, &tdev_profile);
8827
5.24M
        if (code != 0)
8828
0
            return 0;
8829
8830
5.24M
        if (tdev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]->hashcode !=
8831
5.24M
            p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE]->hashcode) {
8832
4.15M
            color_replace_t* replace_data = (color_replace_t*)data;
8833
            /* Not ref counted as data is on the stack (from gx_remap_ICC) and we should be fine during this
8834
               color remap operation. */
8835
4.15M
            replace_data->pdf14_iccprofile = p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE];
8836
4.15M
        }
8837
8838
        /* Pass on to target device */
8839
5.24M
        return dev_proc(p14dev->target, dev_spec_op)(p14dev->target, dev_spec_op, data, size);
8840
5.24M
    }
8841
209k
    if (dev_spec_op == gxdso_device_insert_child) {
8842
37
        gx_device *tdev = p14dev->target;
8843
37
        p14dev->target = (gx_device *)data;
8844
37
        rc_increment(p14dev->target);
8845
37
        rc_decrement_only(tdev, "pdf14_dev_spec_op");
8846
37
        return 0;
8847
37
    }
8848
209k
    if (dev_spec_op == gxdso_interpolate_threshold)
8849
6.36k
        return p14dev->interpolate_threshold;
8850
8851
202k
    if (dev_spec_op == gxdso_overprintsim_state) {
8852
6.36k
        unsigned char *data_uchar = (unsigned char *) data;
8853
6.36k
        data_uchar[0] = (unsigned char) p14dev->overprint_sim;
8854
6.36k
        if (p14dev->ctx != NULL)
8855
1
            data_uchar[1] = (unsigned char)p14dev->ctx->num_spots; /* pdf14 page device */
8856
6.36k
        else
8857
6.36k
            data_uchar[1] = (unsigned char)p14dev->devn_params.page_spot_colors;  /* pdf14 clist device */
8858
6.36k
        return 1;
8859
6.36k
    }
8860
8861
196k
    return dev_proc(p14dev->target, dev_spec_op)(p14dev->target, dev_spec_op, data, size);
8862
202k
}
8863
8864
/* Needed to set color monitoring in the target device's profile */
8865
int
8866
gs_pdf14_device_color_mon_set(gx_device *pdev, bool monitoring)
8867
0
{
8868
0
    pdf14_device * p14dev = (pdf14_device *)pdev;
8869
0
    gx_device *targ = p14dev->target;
8870
0
    cmm_dev_profile_t *dev_profile;
8871
0
    int code = dev_proc(targ, get_profile)((gx_device*) targ, &dev_profile);
8872
8873
0
    if (code == 0)
8874
0
        dev_profile->pageneutralcolor = monitoring;
8875
0
    return code;
8876
0
}
8877
8878
static int
8879
gs_pdf14_device_push(gs_memory_t *mem, gs_gstate * pgs,
8880
        gx_device ** pdev, gx_device * target, const gs_pdf14trans_t * pdf14pct)
8881
261k
{
8882
261k
    pdf14_device dev_proto;
8883
261k
    pdf14_device * p14dev;
8884
261k
    int code;
8885
261k
    bool has_tags;
8886
261k
    cmm_profile_t *icc_profile;
8887
261k
    gsicc_rendering_param_t render_cond;
8888
261k
    cmm_dev_profile_t *dev_profile;
8889
261k
    uchar k;
8890
261k
    int max_bitmap;
8891
261k
    bool use_pdf14_accum = false;
8892
261k
    bool deep;
8893
8894
    /* Guard against later seg faults, this should not be possible */
8895
261k
    if (target == NULL)
8896
0
        return gs_throw_code(gs_error_Fatal);
8897
8898
261k
    has_tags = device_encodes_tags(target);
8899
261k
    deep = device_is_deep(target);
8900
261k
    max_bitmap = target->space_params.MaxBitmap == 0 ? MAX_BITMAP :
8901
261k
                                 target->space_params.MaxBitmap;
8902
    /* If the device is not a printer class device, it won't support saved-pages */
8903
    /* and so we may need to make a clist device in order to prevent very large  */
8904
    /* or high resolution pages from having allocation problems.                 */
8905
    /* We use MaxBitmap to decide when a clist is needed.*/
8906
261k
    if (dev_proc(target, dev_spec_op)(target, gxdso_supports_saved_pages, NULL, 0) <= 0 &&
8907
261k
        gx_device_is_pattern_clist(target) == 0 &&
8908
261k
        gx_device_is_pattern_accum(target) == 0 &&
8909
261k
        gs_device_is_memory(target) == 0) {
8910
8911
955
        uint32_t pdf14_trans_buffer_size =
8912
955
              (ESTIMATED_PDF14_ROW_SPACE(max(1, target->width),
8913
955
                                         target->color_info.num_components,
8914
955
                                         deep ? 16 : 8) >> 3);
8915
8916
955
        if (target->height < max_ulong / pdf14_trans_buffer_size)
8917
955
                pdf14_trans_buffer_size *= target->height;
8918
0
        else
8919
0
                max_bitmap = 0;     /* Force decision to clist */
8920
955
        if (pdf14_trans_buffer_size > max_bitmap)
8921
918
            use_pdf14_accum = true;
8922
955
    }
8923
261k
    code = dev_proc(target, get_profile)(target,  &dev_profile);
8924
261k
    if (code < 0)
8925
0
        return code;
8926
261k
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &icc_profile,
8927
261k
                          &render_cond);
8928
261k
    if_debug0m('v', mem, "[v]gs_pdf14_device_push\n");
8929
8930
261k
    code = get_pdf14_device_proto(target, &dev_proto, pgs,
8931
261k
                                  pdf14pct, use_pdf14_accum);
8932
261k
    if (code < 0)
8933
0
        return code;
8934
261k
    code = gs_copydevice((gx_device **) &p14dev,
8935
261k
                         (const gx_device *) &dev_proto, mem);
8936
261k
    if (code < 0)
8937
0
        return code;
8938
8939
261k
    gs_pdf14_device_copy_params((gx_device *)p14dev, target);
8940
261k
    gx_device_set_target((gx_device_forward *)p14dev, target);
8941
261k
    p14dev->pad = target->pad;
8942
261k
    p14dev->log2_align_mod = target->log2_align_mod;
8943
261k
    if (pdf14pct->params.overprint_sim_push && pdf14pct->params.num_spot_colors_int > 0 && !target->is_planar)
8944
0
        p14dev->is_planar = true;
8945
261k
    else
8946
261k
        p14dev->is_planar = target->is_planar;
8947
261k
    p14dev->interpolate_threshold = dev_proc(target, dev_spec_op)(target, gxdso_interpolate_threshold, NULL, 0);
8948
8949
261k
    p14dev->alpha = 1.0;
8950
261k
    p14dev->shape = 1.0;
8951
261k
    p14dev->opacity = 1.0;
8952
261k
    p14dev->fillconstantalpha = 1.0;
8953
261k
    p14dev->strokeconstantalpha = 1.0;
8954
8955
    /* Simulated overprint case.  We have to use CMYK-based profile.  Also if the target
8956
       profile is NCLR, we are going to use a pdf14 device that is CMYK based and
8957
       do the mapping to the NCLR profile when the put_image occurs */
8958
261k
    if ((p14dev->overprint_sim && icc_profile->data_cs != gsCMYK) ||
8959
261k
        icc_profile->data_cs == gsNCHANNEL) {
8960
0
        gsicc_adjust_profile_rc(pgs->icc_manager->default_cmyk, 1, "gs_pdf14_device_push");
8961
0
        gsicc_adjust_profile_rc(p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE],
8962
0
            -1, "gs_pdf14_device_push");
8963
0
        p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] = pgs->icc_manager->default_cmyk;
8964
261k
    } else {
8965
        /* If the target profile was CIELAB (and we are not using a blend CS),
8966
           then overide with default RGB for proper blending.  During put_image
8967
           we will convert from RGB to CIELAB.  Need to check that we have a
8968
           default profile, which will not be the case if we are coming from the clist reader */
8969
261k
        if ((icc_profile->data_cs == gsCIELAB || icc_profile->islab)
8970
261k
            && pgs->icc_manager->default_rgb != NULL &&
8971
261k
            p14dev->blend_cs_state == PDF14_BLEND_CS_UNSPECIFIED) {
8972
0
            p14dev->blend_cs_state = PDF14_BLEND_CS_TARGET_CIELAB;
8973
0
            gsicc_adjust_profile_rc(pgs->icc_manager->default_rgb, 1, "gs_pdf14_device_push");
8974
0
            gsicc_adjust_profile_rc(p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE],
8975
0
                -1, "gs_pdf14_device_push");
8976
0
            p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] = pgs->icc_manager->default_rgb;
8977
0
        }
8978
261k
    }
8979
8980
261k
    if (pdf14pct->params.overprint_sim_push &&
8981
261k
        pdf14pct->params.num_spot_colors_int > 0) {
8982
0
        p14dev->procs.update_spot_equivalent_colors = pdf14_update_spot_equivalent_colors;
8983
0
        p14dev->procs.ret_devn_params = pdf14_ret_devn_params;
8984
0
        p14dev->op_pequiv_cmyk_colors.all_color_info_valid = false;
8985
0
        p14dev->target_support_devn = p14dev->icc_struct->supports_devn;
8986
0
        p14dev->icc_struct->supports_devn = true;  /* Reset when pdf14 device is disabled */
8987
0
    }
8988
8989
    /* The number of color planes should not exceed that of the target.
8990
       Unless we are using a blend CS */
8991
261k
    if (!(p14dev->blend_cs_state != PDF14_BLEND_CS_UNSPECIFIED || p14dev->overprint_sim)) {
8992
261k
        if (p14dev->color_info.num_components > target->color_info.num_components)
8993
0
            p14dev->color_info.num_components = target->color_info.num_components;
8994
261k
        if (p14dev->color_info.max_components > target->color_info.max_components)
8995
11.4k
            p14dev->color_info.max_components = target->color_info.max_components;
8996
261k
    }
8997
261k
    p14dev->color_info.depth = p14dev->color_info.num_components * (8<<deep);
8998
    /* If we have a tag device then go ahead and do a special encoder
8999
       decoder for the pdf14 device to make sure we maintain this
9000
       information in the encoded color information.  We could use
9001
       the target device's methods but the PDF14 device has to maintain
9002
       8 bit color always and we could run into other issues if the number
9003
       of colorants became large.  If we need to do compressed color with
9004
       tags that will be a special project at that time */
9005
261k
    if (deep) {
9006
0
        set_dev_proc(p14dev, encode_color, pdf14_encode_color16);
9007
0
        set_dev_proc(p14dev, decode_color, pdf14_decode_color16);
9008
0
    }
9009
261k
    if (has_tags) {
9010
0
        set_dev_proc(p14dev, encode_color, deep ? pdf14_encode_color16_tag : pdf14_encode_color_tag);
9011
0
        p14dev->color_info.comp_shift[p14dev->color_info.num_components] = p14dev->color_info.depth;
9012
0
        p14dev->color_info.depth += 8;
9013
0
    }
9014
    /* if the device has separations already defined (by SeparationOrderNames) */
9015
    /* we need to copy them (allocating new names) so the colorants are in the */
9016
    /* same order as the target device.                                        */
9017
261k
    if (dev_proc(target, dev_spec_op)(target, gxdso_supports_devn, NULL, 0)) {
9018
11.4k
        code = devn_copy_params(target, (gx_device *)p14dev);
9019
11.4k
        if (code < 0)
9020
0
            return code;
9021
11.4k
    }
9022
    /* by definition pdf14_encode _is_ standard */
9023
261k
    p14dev->color_info.separable_and_linear = GX_CINFO_SEP_LIN_STANDARD;
9024
261k
    gx_device_fill_in_procs((gx_device *)p14dev);
9025
261k
    p14dev->save_get_cmap_procs = pgs->get_cmap_procs;
9026
261k
    pgs->get_cmap_procs = pdf14_get_cmap_procs;
9027
261k
    gx_set_cmap_procs(pgs, (gx_device *)p14dev);
9028
9029
    /* Components shift, etc have to be based upon 8 (or 16) bit */
9030
1.03M
    for (k = 0; k < p14dev->color_info.num_components; k++) {
9031
771k
        p14dev->color_info.comp_bits[k] = 8<<deep;
9032
771k
        p14dev->color_info.comp_shift[k] =
9033
771k
                            (p14dev->color_info.num_components - 1 - k) * (8<<deep);
9034
771k
    }
9035
261k
    if (use_pdf14_accum) {
9036
        /* we will disable this device later, but we don't want to allocate large buffers */
9037
918
        p14dev->width = 1;
9038
918
        p14dev->height = 1;
9039
918
    }
9040
9041
261k
    p14dev->op_state = pgs->is_fill_color ? PDF14_OP_STATE_FILL : PDF14_OP_STATE_NONE;
9042
261k
    code = dev_proc((gx_device *) p14dev, open_device) ((gx_device *) p14dev);
9043
261k
    *pdev = (gx_device *) p14dev;
9044
261k
    pdf14_set_marking_params((gx_device *)p14dev, pgs);
9045
261k
    p14dev->color_model_stack = NULL;
9046
9047
    /* In case we have alphabits set */
9048
261k
    p14dev->color_info.anti_alias = target->color_info.anti_alias;
9049
9050
261k
    if (pdf14pct->params.is_pattern) {
9051
6.22k
        code = pdf14_initialize_ctx((gx_device*)p14dev,
9052
6.22k
            p14dev->color_info.num_components,
9053
6.22k
            p14dev->color_info.polarity != GX_CINFO_POLARITY_SUBTRACTIVE, (const gs_gstate*) pgs);
9054
6.22k
        if (code < 0)
9055
0
            return code;
9056
6.22k
    }
9057
9058
    /* We should never go into this when using a blend color space */
9059
261k
    if (use_pdf14_accum) {
9060
918
        const gx_device_pdf14_accum *accum_proto = NULL;
9061
918
        gx_device *new_target = NULL;
9062
918
        gx_device_color pdcolor;
9063
918
        frac pconc_white = frac_1;
9064
918
        bool UsePlanarBuffer = false;
9065
9066
918
        if_debug0m('v', mem, "[v]gs_pdf14_device_push: Inserting clist device.\n");
9067
9068
        /* get the prototype for the accumulator device based on colorspace */
9069
918
        switch (target->color_info.max_components) { /* use max_components in case is devn device */
9070
67
            case 1:
9071
67
                accum_proto = &pdf14_accum_Gray;
9072
67
                break;
9073
851
            case 3:
9074
851
                accum_proto = &pdf14_accum_RGB;
9075
851
                break;
9076
0
            case 4:
9077
0
                accum_proto = &pdf14_accum_CMYK;
9078
0
                break;
9079
0
            default:
9080
0
                accum_proto = &pdf14_accum_CMYKspot;
9081
0
                UsePlanarBuffer = true;
9082
918
        }
9083
918
        if (accum_proto == NULL ||
9084
918
            (code = gs_copydevice(&new_target, (gx_device *)accum_proto, mem->stable_memory)) < 0)
9085
0
            goto no_clist_accum;
9086
9087
918
        ((gx_device_pdf14_accum *)new_target)->save_p14dev = (gx_device *)p14dev;  /* non-clist p14dev */
9088
        /* Fill in values from the target device before opening */
9089
918
        new_target->color_info = p14dev->color_info;
9090
918
        ((gx_device_pdf14_accum *)new_target)->devn_params = p14dev->devn_params;
9091
918
        new_target->color_info.separable_and_linear = GX_CINFO_SEP_LIN;
9092
918
        set_linear_color_bits_mask_shift(new_target);
9093
918
        gs_pdf14_device_copy_params(new_target, target);
9094
918
        ((gx_device_pdf14_accum *)new_target)->page_uses_transparency = true;
9095
918
        gx_device_fill_in_procs(new_target);
9096
9097
918
        memcpy(&(new_target->space_params), &(target->space_params), sizeof(gdev_space_params));
9098
918
        max_bitmap = max(target->space_params.MaxBitmap, target->space_params.BufferSpace);
9099
918
        ((gx_device_pdf14_accum *)new_target)->space_params.BufferSpace = max_bitmap;
9100
9101
918
        new_target->PageHandlerPushed = true;
9102
918
        new_target->ObjectHandlerPushed = true;
9103
918
        new_target->NupHandlerPushed = true;
9104
        /* if the device has separations already defined (by SeparationOrderNames) */
9105
        /* we need to copy them (allocating new names) so the colorants are in the */
9106
        /* same order as the target device.                                        */
9107
918
        if (dev_proc(target, dev_spec_op)(target, gxdso_supports_devn, NULL, 0)) {
9108
0
            code = devn_copy_params(target, (gx_device *)pdev);
9109
0
            if (code < 0)
9110
0
                return code;
9111
0
        }
9112
        /* UsePlanarBuffer is true in case this is CMYKspot */
9113
918
        if ((code = gdev_prn_open_planar(new_target, UsePlanarBuffer)) < 0 ||
9114
918
             !PRINTER_IS_CLIST((gx_device_printer *)new_target)) {
9115
0
            gs_free_object(mem->stable_memory, new_target, "pdf14-accum");
9116
0
            goto no_clist_accum;
9117
0
        }
9118
        /* Do the initial fillpage into the pdf14-accum device we just created */
9119
918
        dev_proc(new_target, set_graphics_type_tag)((gx_device *)new_target, GS_UNTOUCHED_TAG);
9120
918
        if ((code = gx_remap_concrete_DGray(gs_currentcolorspace_inline((gs_gstate *)pgs),
9121
918
                                            &pconc_white,
9122
918
                                            &pdcolor, pgs, new_target, gs_color_select_all,
9123
918
                                            dev_profile)) < 0)
9124
0
            goto no_clist_accum;
9125
9126
918
        (*dev_proc(new_target, fillpage))(new_target, pgs, &pdcolor);
9127
918
        code = clist_composite(new_target, pdev, (gs_composite_t *)pdf14pct, pgs, mem, NULL);
9128
918
        if (code < 0)
9129
0
            goto no_clist_accum;
9130
9131
918
        pdf14_disable_device((gx_device *)p14dev);           /* make the non-clist device forward */
9132
918
        pdf14_close((gx_device *)p14dev);                    /* and free up the little memory it had */
9133
918
    }
9134
261k
    return code;
9135
9136
0
no_clist_accum:
9137
        /* FIXME: We allocated a really small p14dev, but that won't work */
9138
0
    return gs_throw_code(gs_error_Fatal); /* punt for now */
9139
261k
}
9140
9141
/*
9142
 * In a modest violation of good coding practice, the gs_composite_common
9143
 * fields are "known" to be simple (contain no pointers to garbage
9144
 * collected memory), and we also know the gs_pdf14trans_params_t structure
9145
 * to be simple, so we just create a trivial structure descriptor for the
9146
 * entire gs_pdf14trans_s structure.
9147
 */
9148
#define private_st_gs_pdf14trans_t()\
9149
  gs_private_st_ptrs2(st_pdf14trans, gs_pdf14trans_t, "gs_pdf14trans_t",\
9150
      st_pdf14trans_enum_ptrs, st_pdf14trans_reloc_ptrs, params.transfer_function, params.iccprofile)
9151
9152
/* GC descriptor for gs_pdf14trans_t */
9153
private_st_gs_pdf14trans_t();
9154
9155
/*
9156
 * Check for equality of two PDF 1.4 transparency compositor objects.
9157
 *
9158
 * We are currently always indicating that PDF 1.4 transparency compositors are
9159
 * equal.  Two transparency compositors may have teh same data but still
9160
 * represent separate actions.  (E.g. two PDF14_BEGIN_TRANS_GROUP compositor
9161
 * operations in a row mean that we are creating a group inside of a group.
9162
 */
9163
static  bool
9164
c_pdf14trans_equal(const gs_composite_t * pct0, const gs_composite_t * pct1)
9165
0
{
9166
0
    return false;
9167
0
}
9168
9169
#ifdef DEBUG
9170
static const char * pdf14_opcode_names[] = PDF14_OPCODE_NAMES;
9171
#endif
9172
9173
#define put_value(dp, value)\
9174
2.25M
    BEGIN\
9175
2.25M
        memcpy(dp, &value, sizeof(value));\
9176
2.25M
        dp += sizeof(value);\
9177
2.25M
    END
9178
9179
static inline int
9180
c_pdf14trans_write_ctm(byte **ppbuf, const gs_pdf14trans_params_t *pparams)
9181
266k
{
9182
    /* Note: We can't skip writing CTM if it is equal to pgs->ctm,
9183
       because clist writer may skip this command for some bands.
9184
       For a better result we need individual CTM for each band.
9185
     */
9186
266k
    byte *pbuf = *ppbuf;
9187
266k
    int len, code;
9188
9189
266k
    len = cmd_write_ctm_return_length_nodevice(&pparams->ctm);
9190
266k
    pbuf--; /* For cmd_write_ctm. */
9191
266k
    code = cmd_write_ctm(&pparams->ctm, pbuf, len);
9192
266k
    if (code < 0)
9193
0
        return code;
9194
266k
    pbuf += len + 1;
9195
266k
    *ppbuf = pbuf;
9196
266k
    return 0;
9197
266k
}
9198
9199
/*
9200
 * Convert a PDF 1.4 transparency compositor to string form for use by the command
9201
 * list device. This is also where we update the pdf14_needed. When set the clist
9202
 * painting procs will update the trans_bbox state for bands that are affected.
9203
*/
9204
static  int
9205
c_pdf14trans_write(const gs_composite_t * pct, byte * data, uint * psize,
9206
                   gx_device_clist_writer *cdev)
9207
651k
{
9208
651k
    const gs_pdf14trans_params_t * pparams = &((const gs_pdf14trans_t *)pct)->params;
9209
651k
    int need, avail = *psize;
9210
651k
    byte buf[MAX_CLIST_TRANSPARENCY_BUFFER_SIZE]; /* Must be large enough
9211
        to fit the data written below. We don't implement a dynamic check for
9212
        the buffer owerflow, assuming that the consistency is verified in the
9213
        coding phase. See the definition of MAX_CLIST_TRANSPARENCY_BUFFER_SIZE. */
9214
651k
    byte * pbuf = buf;
9215
651k
    int opcode = pparams->pdf14_op;
9216
651k
    int mask_size = 0;
9217
651k
    uint mask_id = 0;
9218
651k
    int code;
9219
651k
    bool found_icc;
9220
651k
    int64_t hashcode = 0;
9221
651k
    cmm_profile_t *icc_profile;
9222
651k
    gsicc_rendering_param_t render_cond;
9223
651k
    cmm_dev_profile_t *dev_profile;
9224
    /* We maintain and update working copies until we actually write the clist */
9225
651k
    int pdf14_needed = cdev->pdf14_needed;
9226
651k
    int trans_group_level = cdev->pdf14_trans_group_level;
9227
651k
    int smask_level = cdev->pdf14_smask_level;
9228
651k
    bool deep = device_is_deep((gx_device *)cdev);
9229
9230
651k
    code = dev_proc((gx_device *) cdev, get_profile)((gx_device *) cdev,
9231
651k
                                                     &dev_profile);
9232
651k
    if (code < 0)
9233
0
        return code;
9234
651k
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &icc_profile,
9235
651k
                          &render_cond);
9236
651k
    *pbuf++ = opcode;     /* 1 byte */
9237
651k
    if (trans_group_level < 0 && opcode != PDF14_PUSH_DEVICE)
9238
0
        return_error(gs_error_unregistered);  /* prevent spurious transparency ops (Bug 702327) */
9239
9240
651k
    switch (opcode) {
9241
0
        default:      /* Should not occur. */
9242
0
            break;
9243
5.45k
        case PDF14_PUSH_DEVICE:
9244
5.45k
            trans_group_level = 0;
9245
5.45k
            cdev->pdf14_smask_level = 0;
9246
5.45k
            cdev->page_pdf14_needed = false;
9247
5.45k
            put_value(pbuf, pparams->num_spot_colors);
9248
5.45k
            put_value(pbuf, pparams->num_spot_colors_int);
9249
5.45k
            put_value(pbuf, pparams->overprint_sim_push);
9250
5.45k
            put_value(pbuf, pparams->is_pattern);
9251
9252
            /* If we happen to be going to a color space like CIELAB then
9253
               we are going to do our blending in default RGB and convert
9254
               to CIELAB at the end.  To do this, we need to store the
9255
               default RGB profile in the clist so that we can grab it
9256
               later on during the clist read back and put image command */
9257
5.45k
            if (icc_profile->data_cs == gsCIELAB || icc_profile->islab) {
9258
                /* Get the default RGB profile.  Set the device hash code
9259
                   so that we can extract it during the put_image operation. */
9260
0
                cdev->trans_dev_icc_hash = gsicc_get_hash(pparams->iccprofile);
9261
0
                found_icc =
9262
0
                    clist_icc_searchtable(cdev, gsicc_get_hash(pparams->iccprofile));
9263
0
                if (!found_icc) {
9264
                    /* Add it to the table */
9265
0
                    clist_icc_addentry(cdev, gsicc_get_hash(pparams->iccprofile),
9266
0
                                       pparams->iccprofile);
9267
0
                }
9268
0
            }
9269
5.45k
            break;
9270
5.29k
        case PDF14_POP_DEVICE:
9271
5.29k
            pdf14_needed = false;   /* reset pdf14_needed */
9272
5.29k
            trans_group_level = -1;   /* reset so we need to PUSH_DEVICE next */
9273
5.29k
            smask_level = 0;
9274
5.29k
            put_value(pbuf, pparams->is_pattern);
9275
5.29k
            break;
9276
136k
        case PDF14_END_TRANS_GROUP:
9277
137k
        case PDF14_END_TRANS_TEXT_GROUP:
9278
137k
            trans_group_level--;  /* if now at page level, pdf14_needed will be updated */
9279
137k
            if (smask_level == 0 && trans_group_level == 0)
9280
7.19k
                pdf14_needed = cdev->page_pdf14_needed;
9281
137k
            break;      /* No data */
9282
1.87k
        case PDF14_BEGIN_TRANS_PAGE_GROUP:
9283
137k
        case PDF14_BEGIN_TRANS_GROUP:
9284
137k
            pdf14_needed = true;   /* the compositor will be needed while reading */
9285
137k
            trans_group_level++;
9286
137k
            code = c_pdf14trans_write_ctm(&pbuf, pparams);
9287
137k
            if (code < 0)
9288
0
                return code;
9289
137k
            *pbuf++ = (pparams->Isolated & 1) + ((pparams->Knockout & 1) << 1);
9290
137k
            *pbuf++ = pparams->blend_mode;
9291
137k
            *pbuf++ = pparams->group_color_type;
9292
137k
            *pbuf++ = pparams->page_group;
9293
137k
            put_value(pbuf, pparams->group_color_numcomps);
9294
137k
            put_value(pbuf, pparams->opacity);
9295
137k
            put_value(pbuf, pparams->shape);
9296
137k
            put_value(pbuf, pparams->bbox);
9297
137k
            put_value(pbuf, pparams->shade_group);
9298
137k
            put_value(pbuf, pparams->text_group);
9299
137k
            mask_id = pparams->mask_id;
9300
137k
            put_value(pbuf, mask_id);
9301
            /* Color space information maybe ICC based
9302
               in this case we need to store the ICC
9303
               profile or the ID if it is cached already */
9304
137k
            if (pparams->group_color_type == ICC) {
9305
                /* Check if it is already in the ICC clist table */
9306
3.41k
                hashcode = gsicc_get_hash(pparams->iccprofile);
9307
3.41k
                found_icc = clist_icc_searchtable(cdev, hashcode);
9308
3.41k
                if (!found_icc) {
9309
                    /* Add it to the table */
9310
993
                    clist_icc_addentry(cdev, hashcode, pparams->iccprofile);
9311
993
                    put_value(pbuf, hashcode);
9312
2.42k
                } else {
9313
                    /* It will be in the clist. Just write out the hashcode */
9314
2.42k
                    put_value(pbuf, hashcode);
9315
2.42k
                }
9316
133k
            } else {
9317
133k
                put_value(pbuf, hashcode);
9318
133k
            }
9319
137k
            break;
9320
128k
        case PDF14_BEGIN_TRANS_MASK:
9321
128k
            if (pparams->subtype != TRANSPARENCY_MASK_None) {
9322
112k
                pdf14_needed = true;   /* the compositor will be needed while reading */
9323
112k
                smask_level++;
9324
112k
            }
9325
128k
            code = c_pdf14trans_write_ctm(&pbuf, pparams);
9326
128k
            if (code < 0)
9327
0
                return code;
9328
128k
            put_value(pbuf, pparams->subtype);
9329
128k
            *pbuf++ = pparams->group_color_type;
9330
128k
            put_value(pbuf, pparams->group_color_numcomps);
9331
128k
            *pbuf++ = pparams->replacing;
9332
128k
            *pbuf++ = (pparams->function_is_identity) | (deep<<1);
9333
128k
            *pbuf++ = pparams->Background_components;
9334
128k
            *pbuf++ = pparams->Matte_components;
9335
128k
            put_value(pbuf, pparams->bbox);
9336
128k
            mask_id = pparams->mask_id;
9337
128k
            put_value(pbuf, mask_id);
9338
128k
            if (pparams->Background_components) {
9339
728
                const int l = sizeof(pparams->Background[0]) * pparams->Background_components;
9340
9341
728
                memcpy(pbuf, pparams->Background, l);
9342
728
                pbuf += l;
9343
728
                memcpy(pbuf, &pparams->GrayBackground, sizeof(pparams->GrayBackground));
9344
728
                pbuf += sizeof(pparams->GrayBackground);
9345
728
            }
9346
128k
            if (pparams->Matte_components) {
9347
6
                const int m = sizeof(pparams->Matte[0]) * pparams->Matte_components;
9348
9349
6
                memcpy(pbuf, pparams->Matte, m);
9350
6
                pbuf += m;
9351
6
            }
9352
128k
            if (!pparams->function_is_identity)
9353
355
                mask_size = (256+deep)<<deep;
9354
            /* Color space information may be ICC based
9355
               in this case we need to store the ICC
9356
               profile or the ID if it is cached already */
9357
128k
            if (pparams->group_color_type == ICC) {
9358
                /* Check if it is already in the ICC clist table */
9359
112k
                hashcode = gsicc_get_hash(pparams->iccprofile);
9360
112k
                found_icc = clist_icc_searchtable(cdev, hashcode);
9361
112k
                if (!found_icc) {
9362
                    /* Add it to the table */
9363
888
                    clist_icc_addentry(cdev, hashcode, pparams->iccprofile);
9364
888
                    put_value(pbuf, hashcode);
9365
111k
                } else {
9366
                    /* It will be in the clist. Just write out the hashcode */
9367
111k
                    put_value(pbuf, hashcode);
9368
111k
                }
9369
112k
            } else {
9370
16.7k
                put_value(pbuf, hashcode);
9371
16.7k
            }
9372
128k
            break;
9373
112k
        case PDF14_END_TRANS_MASK:
9374
112k
            smask_level--;
9375
112k
            if (smask_level == 0 && trans_group_level == 0)
9376
3.66k
                pdf14_needed = cdev->page_pdf14_needed;
9377
112k
            break;
9378
111k
        case PDF14_SET_BLEND_PARAMS:
9379
111k
            if (pparams->blend_mode != BLEND_MODE_Normal || pparams->opacity != 1.0 ||
9380
111k
                pparams->shape != 1.0)
9381
111k
                pdf14_needed = true;    /* the compositor will be needed while reading */
9382
0
            else if (smask_level == 0 && trans_group_level == 0)
9383
0
                pdf14_needed = false;   /* At page level, set back to false */
9384
111k
            if (smask_level == 0 && trans_group_level == 0)
9385
53.8k
                cdev->page_pdf14_needed = pdf14_needed;         /* save for after popping to page level */
9386
            /* Changed is now two bytes due to overprint stroke fill. Write as int */
9387
111k
            put_value(pbuf, pparams->changed);
9388
111k
            if (pparams->changed & PDF14_SET_BLEND_MODE)
9389
10.0k
                *pbuf++ = pparams->blend_mode;
9390
111k
            if (pparams->changed & PDF14_SET_TEXT_KNOCKOUT)
9391
5.09k
                *pbuf++ = pparams->text_knockout;
9392
111k
            if (pparams->changed & PDF14_SET_AIS)
9393
111k
                put_value(pbuf, pparams->ais);
9394
111k
            if (pparams->changed & PDF14_SET_OVERPRINT)
9395
111k
                put_value(pbuf, pparams->overprint);
9396
111k
            if (pparams->changed & PDF14_SET_STROKEOVERPRINT)
9397
111k
                put_value(pbuf, pparams->stroke_overprint);
9398
111k
            if (pparams->changed & PDF14_SET_FILLCONSTANTALPHA)
9399
111k
                put_value(pbuf, pparams->fillconstantalpha);
9400
111k
            if (pparams->changed & PDF14_SET_STROKECONSTANTALPHA)
9401
111k
                put_value(pbuf, pparams->strokeconstantalpha);
9402
111k
            if (pparams->changed & PDF14_SET_FILLSTROKE_STATE)
9403
111k
                put_value(pbuf, pparams->op_fs_state);
9404
111k
            break;
9405
0
        case PDF14_PUSH_TRANS_STATE:
9406
0
            break;
9407
14.3k
        case PDF14_POP_TRANS_STATE:
9408
14.3k
            break;
9409
0
        case PDF14_PUSH_SMASK_COLOR:
9410
0
            return 0;   /* We really should never be here */
9411
0
            break;
9412
0
        case PDF14_POP_SMASK_COLOR:
9413
0
            return 0;   /* We really should never be here */
9414
0
            break;
9415
651k
    }
9416
9417
    /* check for fit */
9418
651k
    need = (pbuf - buf) + mask_size;
9419
651k
    *psize = need;
9420
651k
    if (need > avail) {
9421
114k
        if (avail)
9422
0
            return_error(gs_error_rangecheck);
9423
114k
        else
9424
114k
            return gs_error_rangecheck;
9425
114k
    }
9426
9427
    /* If we are writing more than the maximum ever expected,
9428
     * return a rangecheck error. Second check is for Coverity
9429
     */
9430
536k
    if ((need + 3 > MAX_CLIST_COMPOSITOR_SIZE) ||
9431
536k
        (need + 3 - mask_size > MAX_CLIST_TRANSPARENCY_BUFFER_SIZE) )
9432
0
        return_error(gs_error_rangecheck);
9433
9434
    /* Copy our serialized data into the output buffer */
9435
536k
    memcpy(data, buf, need - mask_size);
9436
536k
    if (mask_size)  /* Include the transfer mask data if present */
9437
264
        memcpy(data + need - mask_size, pparams->transfer_fn, mask_size);
9438
536k
    if_debug3m('v', cdev->memory,
9439
536k
               "[v] c_pdf14trans_write: opcode = %s mask_id=%d need = %d\n",
9440
536k
               pdf14_opcode_names[opcode], mask_id, need);
9441
536k
    cdev->pdf14_needed = pdf14_needed;          /* all OK to update */
9442
536k
    cdev->pdf14_trans_group_level = trans_group_level;
9443
536k
    cdev->pdf14_smask_level = smask_level;
9444
536k
    return 0;
9445
536k
}
9446
9447
#undef put_value
9448
9449
/* Function prototypes */
9450
static int gs_create_pdf14trans( gs_composite_t ** ppct,
9451
                const gs_pdf14trans_params_t * pparams,
9452
                gs_memory_t * mem );
9453
9454
#define read_value(dp, value)\
9455
40.9M
    BEGIN\
9456
40.9M
        memcpy(&value, dp, sizeof(value));\
9457
40.9M
        dp += sizeof(value);\
9458
40.9M
    END
9459
9460
/*
9461
 * Convert the string representation of the PDF 1.4 transparency parameter
9462
 * into the full compositor.
9463
 */
9464
static  int
9465
c_pdf14trans_read(gs_composite_t * * ppct, const byte * data,
9466
                                uint size, gs_memory_t * mem )
9467
13.0M
{
9468
13.0M
    gs_pdf14trans_params_t params = {0};
9469
13.0M
    const byte * start = data;
9470
13.0M
    int used, code = 0;
9471
13.0M
    bool deep;
9472
9473
13.0M
    if (size < 1)
9474
0
        return_error(gs_error_rangecheck);
9475
9476
    /* Read PDF 1.4 compositor data from the clist */
9477
13.0M
    params.pdf14_op = *data++;
9478
13.0M
    if_debug2m('v', mem, "[v] c_pdf14trans_read: opcode = %s  avail = %d",
9479
13.0M
               pdf14_opcode_names[params.pdf14_op], size);
9480
13.0M
    memset(&params.ctm, 0, sizeof(params.ctm));
9481
13.0M
    switch (params.pdf14_op) {
9482
0
        default:      /* Should not occur. */
9483
0
            break;
9484
358k
        case PDF14_PUSH_DEVICE:
9485
358k
            read_value(data, params.num_spot_colors);
9486
358k
            read_value(data, params.num_spot_colors_int);
9487
358k
            read_value(data, params.overprint_sim_push);
9488
358k
            read_value(data, params.is_pattern);
9489
358k
            break;
9490
0
        case PDF14_ABORT_DEVICE:
9491
0
            break;
9492
358k
        case PDF14_POP_DEVICE:
9493
358k
            read_value(data, params.is_pattern);
9494
358k
            break;
9495
585k
        case PDF14_END_TRANS_GROUP:
9496
629k
        case PDF14_END_TRANS_TEXT_GROUP:
9497
#ifdef DEBUG
9498
            code += 0; /* A good place for a breakpoint. */
9499
#endif
9500
629k
            break;      /* No data */
9501
0
        case PDF14_PUSH_TRANS_STATE:
9502
0
            break;
9503
1.09M
        case PDF14_POP_TRANS_STATE:
9504
1.09M
            break;
9505
141k
        case PDF14_BEGIN_TRANS_PAGE_GROUP:
9506
629k
        case PDF14_BEGIN_TRANS_GROUP:
9507
            /*
9508
             * We are currently not using the bbox or the colorspace so they were
9509
             * not placed in the clist
9510
             */
9511
629k
            data = cmd_read_matrix(&params.ctm, data);
9512
629k
            params.Isolated = (*data) & 1;
9513
629k
            params.Knockout = (*data++ >> 1) & 1;
9514
629k
            params.blend_mode = *data++;
9515
629k
            params.group_color_type = *data++;  /* Trans group color */
9516
629k
            params.page_group = *data++;
9517
629k
            read_value(data,params.group_color_numcomps);  /* color group size */
9518
629k
            read_value(data, params.opacity);
9519
629k
            read_value(data, params.shape);
9520
629k
            read_value(data, params.bbox);
9521
629k
            read_value(data, params.shade_group);
9522
629k
            read_value(data, params.text_group);
9523
629k
            read_value(data, params.mask_id);
9524
629k
            read_value(data, params.icc_hash);
9525
629k
            break;
9526
1.34M
        case PDF14_BEGIN_TRANS_MASK:
9527
                /* This is the largest transparency parameter at this time (potentially
9528
                 * 1531 bytes in size if Background_components =
9529
                 * GS_CLIENT_COLOR_MAX_COMPONENTS and Matte_components =
9530
                 * GS_CLIENT_COLOR_MAX_COMPONENTS and we have a transfer function as well).
9531
                 *
9532
                 * NOTE:
9533
                 * The clist reader must be able to handle this sized device.
9534
                 * If any changes are made here the #define MAX_CLIST_COMPOSITOR_SIZE
9535
                 * may also need to be changed correspondingly (defined in gstparam.h)
9536
                 * Also... if another compositor param should exceed this size, this
9537
                 * same condition applies.
9538
                 */
9539
1.34M
            data = cmd_read_matrix(&params.ctm, data);
9540
1.34M
            read_value(data, params.subtype);
9541
1.34M
            params.group_color_type = *data++;
9542
1.34M
            read_value(data, params.group_color_numcomps);
9543
1.34M
            params.replacing = *data++;
9544
1.34M
            params.function_is_identity = *data & 1;
9545
1.34M
            deep = (*data++)>>1;
9546
1.34M
            params.Background_components = *data++;
9547
1.34M
            params.Matte_components = *data++;
9548
1.34M
            read_value(data, params.bbox);
9549
1.34M
            read_value(data, params.mask_id);
9550
1.34M
            if (params.Background_components) {
9551
37.0k
                const int l = sizeof(params.Background[0]) * params.Background_components;
9552
9553
37.0k
                memcpy(params.Background, data, l);
9554
37.0k
                data += l;
9555
37.0k
                memcpy(&params.GrayBackground, data, sizeof(params.GrayBackground));
9556
37.0k
                data += sizeof(params.GrayBackground);
9557
37.0k
            }
9558
1.34M
            if (params.Matte_components) {
9559
409
                const int m = sizeof(params.Matte[0]) * params.Matte_components;
9560
9561
409
                memcpy(params.Matte, data, m);
9562
409
                data += m;
9563
409
            }
9564
1.34M
            read_value(data, params.icc_hash);
9565
1.34M
            if (params.function_is_identity) {
9566
1.33M
                int i;
9567
9568
1.33M
                if (deep) {
9569
0
                    for (i = 0; i < MASK_TRANSFER_FUNCTION_SIZE; i++)
9570
0
                        ((uint16_t *)params.transfer_fn)[i] = i*0x10000/MASK_TRANSFER_FUNCTION_SIZE;
9571
0
                    ((uint16_t *)params.transfer_fn)[i] = 0xffff;
9572
1.33M
                } else {
9573
342M
                    for (i = 0; i < MASK_TRANSFER_FUNCTION_SIZE; i++) {
9574
341M
                        params.transfer_fn[i] = (byte)floor(i *
9575
341M
                            (255.0 / (MASK_TRANSFER_FUNCTION_SIZE - 1)) + 0.5);
9576
341M
                    }
9577
1.33M
                }
9578
1.33M
            } else {
9579
9.50k
                memcpy(params.transfer_fn, data, (256+deep)<<deep);
9580
9.50k
                data += (256+deep)<<deep;
9581
9.50k
            }
9582
1.34M
            break;
9583
139k
        case PDF14_END_TRANS_MASK:
9584
139k
            break;
9585
0
        case PDF14_PUSH_SMASK_COLOR:
9586
0
            return 0;
9587
0
            break;
9588
0
        case PDF14_POP_SMASK_COLOR:
9589
0
            return 0;
9590
0
            break;
9591
8.50M
        case PDF14_SET_BLEND_PARAMS:
9592
8.50M
            read_value(data, params.changed);
9593
8.50M
            if (params.changed & PDF14_SET_BLEND_MODE)
9594
778k
                params.blend_mode = *data++;
9595
8.50M
            if (params.changed & PDF14_SET_TEXT_KNOCKOUT)
9596
344k
                params.text_knockout = *data++;
9597
8.50M
            if (params.changed & PDF14_SET_AIS)
9598
8.50M
                read_value(data, params.ais);
9599
8.50M
            if (params.changed & PDF14_SET_OVERPRINT)
9600
8.50M
                read_value(data, params.overprint);
9601
8.50M
            if (params.changed & PDF14_SET_STROKEOVERPRINT)
9602
8.50M
                read_value(data, params.stroke_overprint);
9603
8.50M
            if (params.changed & PDF14_SET_FILLCONSTANTALPHA)
9604
8.50M
                read_value(data, params.fillconstantalpha);
9605
8.50M
            if (params.changed & PDF14_SET_STROKECONSTANTALPHA)
9606
8.50M
                read_value(data, params.strokeconstantalpha);
9607
8.50M
            if (params.changed & PDF14_SET_FILLSTROKE_STATE)
9608
8.50M
                read_value(data, params.op_fs_state);
9609
8.50M
            break;
9610
13.0M
    }
9611
13.0M
    code = gs_create_pdf14trans(ppct, &params, mem);
9612
13.0M
    if (code < 0)
9613
0
        return code;
9614
13.0M
    used = data - start;
9615
13.0M
    if_debug2m('v', mem, " mask_id=%d used = %d\n", params.mask_id, used);
9616
9617
    /* If we read more than the maximum expected, return a rangecheck error */
9618
13.0M
    if ( used + 3 > MAX_CLIST_COMPOSITOR_SIZE )
9619
0
        return_error(gs_error_rangecheck);
9620
13.0M
    else
9621
13.0M
        return used;
9622
13.0M
}
9623
9624
/*
9625
 * Adjust the compositor's CTM.
9626
 */
9627
static int
9628
c_pdf14trans_adjust_ctm(gs_composite_t * pct0, int x0, int y0, gs_gstate *pgs)
9629
6.36M
{
9630
6.36M
    gs_pdf14trans_t *pct = (gs_pdf14trans_t *)pct0;
9631
6.36M
    gs_matrix mat = pct->params.ctm;
9632
9633
6.36M
    if_debug6m('L', pgs->memory, " [%g %g %g %g %g %g]\n",
9634
6.36M
               mat.xx, mat.xy, mat.yx, mat.yy,
9635
6.36M
               mat.tx, mat.ty);
9636
6.36M
    mat.tx -= x0;
9637
6.36M
    mat.ty -= y0;
9638
6.36M
    gs_gstate_setmatrix(pgs, &mat);
9639
6.36M
    return 0;
9640
6.36M
}
9641
9642
/*
9643
 * Create a PDF 1.4 transparency compositor.
9644
 *
9645
 * Note that this routine will be called only if the device is not already
9646
 * a PDF 1.4 transparency compositor.
9647
 * Return an error if it is not a PDF14_PUSH_DEVICE operation.
9648
 */
9649
static  int
9650
c_pdf14trans_create_default_compositor(const gs_composite_t * pct,
9651
    gx_device ** pp14dev, gx_device * tdev, gs_gstate * pgs,
9652
    gs_memory_t * mem)
9653
261k
{
9654
261k
    const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct;
9655
261k
    int code = 0;
9656
9657
    /*
9658
     * We only handle the push operation.  All other operations are ignored.
9659
     * The other operations will be handled by the composite routine
9660
     * for the PDF 1.4 compositing device.
9661
     */
9662
261k
    switch (pdf14pct->params.pdf14_op) {
9663
261k
        case PDF14_PUSH_DEVICE:
9664
261k
            code = gs_pdf14_device_push(mem, pgs, pp14dev, tdev, pdf14pct);
9665
            /* Change (non-error) code to 1 to indicate that we created
9666
             * a device. */
9667
261k
            if (code >= 0)
9668
261k
                code = 1;
9669
261k
            break;
9670
4
        default:
9671
            /* No other compositor actions are allowed if this isn't a pdf14 compositor */
9672
4
            *pp14dev = NULL;
9673
4
            return_error(gs_error_unregistered);
9674
261k
    }
9675
261k
    return code;
9676
261k
}
9677
9678
/*
9679
 * Find an opening compositor op.
9680
 */
9681
static gs_compositor_closing_state
9682
find_opening_op(int opening_op, gs_composite_t **ppcte,
9683
                gs_compositor_closing_state return_code)
9684
610k
{
9685
    /* Assuming a right *BEGIN* - *END* operation balance. */
9686
610k
    gs_composite_t *pcte = *ppcte;
9687
9688
1.46M
    for (;;) {
9689
1.46M
        if (pcte->type->comp_id == GX_COMPOSITOR_PDF14_TRANS) {
9690
1.40M
            gs_pdf14trans_t *pct = (gs_pdf14trans_t *)pcte;
9691
1.40M
            int op = pct->params.pdf14_op;
9692
9693
1.40M
            *ppcte = pcte;
9694
1.40M
            if (op == opening_op)
9695
400k
                return return_code;
9696
1.00M
            if (op != PDF14_SET_BLEND_PARAMS) {
9697
651k
                if (opening_op == PDF14_BEGIN_TRANS_MASK)
9698
33
                    return COMP_ENQUEUE;
9699
651k
                if (opening_op == PDF14_BEGIN_TRANS_GROUP || opening_op == PDF14_BEGIN_TRANS_PAGE_GROUP) {
9700
72.9k
                    if (op != PDF14_BEGIN_TRANS_MASK && op != PDF14_END_TRANS_MASK)
9701
69.6k
                        return COMP_ENQUEUE;
9702
72.9k
                }
9703
581k
                if (opening_op == PDF14_PUSH_DEVICE) {
9704
578k
                    if (op != PDF14_BEGIN_TRANS_MASK && op != PDF14_END_TRANS_MASK &&
9705
578k
                        op != PDF14_BEGIN_TRANS_GROUP && op != PDF14_BEGIN_TRANS_PAGE_GROUP && op != PDF14_END_TRANS_GROUP &&
9706
578k
                        op != PDF14_END_TRANS_TEXT_GROUP)
9707
37.9k
                        return COMP_ENQUEUE;
9708
578k
                }
9709
581k
            }
9710
1.00M
        } else
9711
59.0k
            return COMP_ENQUEUE;
9712
894k
        pcte = pcte->prev;
9713
894k
        if (pcte == NULL)
9714
43.1k
            return COMP_EXEC_QUEUE; /* Not in queue. */
9715
894k
    }
9716
610k
}
9717
9718
/*
9719
 * Find an opening compositor op.
9720
 */
9721
static gs_compositor_closing_state
9722
find_same_op(const gs_composite_t *composite_action, int my_op, gs_composite_t **ppcte)
9723
7.14M
{
9724
7.14M
    const gs_pdf14trans_t *pct0 = (gs_pdf14trans_t *)composite_action;
9725
7.14M
    gs_composite_t *pct = *ppcte;
9726
9727
7.14M
    for (;;) {
9728
7.14M
        if (pct->type->comp_id == GX_COMPOSITOR_PDF14_TRANS) {
9729
6.76M
            gs_pdf14trans_t *pct_pdf14 = (gs_pdf14trans_t *)pct;
9730
9731
6.76M
            *ppcte = pct;
9732
6.76M
            if (pct_pdf14->params.pdf14_op != my_op)
9733
988k
                return COMP_ENQUEUE;
9734
5.77M
            if (pct_pdf14->params.csel == pct0->params.csel) {
9735
                /* If the new parameters completely replace the old ones
9736
                   then remove the old one from the queu */
9737
5.77M
                if ((pct_pdf14->params.changed & pct0->params.changed) ==
9738
5.77M
                    pct_pdf14->params.changed) {
9739
5.44M
                    return COMP_REPLACE_CURR;
9740
5.44M
                } else {
9741
334k
                    return COMP_ENQUEUE;
9742
334k
                }
9743
5.77M
            }
9744
5.77M
        } else
9745
382k
            return COMP_ENQUEUE;
9746
0
        pct = pct->prev;
9747
0
        if (pct == NULL)
9748
0
            return COMP_ENQUEUE; /* Not in queue. */
9749
0
    }
9750
7.14M
}
9751
9752
/*
9753
 * Check for closing compositor.
9754
 */
9755
static gs_compositor_closing_state
9756
c_pdf14trans_is_closing(const gs_composite_t * composite_action, gs_composite_t ** ppcte,
9757
                        gx_device *dev)
9758
11.8M
{
9759
11.8M
    gs_pdf14trans_t *pct0 = (gs_pdf14trans_t *)composite_action;
9760
11.8M
    int op0 = pct0->params.pdf14_op;
9761
9762
11.8M
    switch (op0) {
9763
0
        default: return_error(gs_error_unregistered); /* Must not happen. */
9764
284k
        case PDF14_PUSH_DEVICE:
9765
284k
            return COMP_ENQUEUE;
9766
0
        case PDF14_ABORT_DEVICE:
9767
0
            return COMP_ENQUEUE;
9768
284k
        case PDF14_POP_DEVICE:
9769
284k
            if (*ppcte == NULL)
9770
195k
                return COMP_ENQUEUE;
9771
88.8k
            else {
9772
88.8k
                gs_compositor_closing_state state = find_opening_op(PDF14_PUSH_DEVICE, ppcte, COMP_EXEC_IDLE);
9773
9774
88.8k
                if (state == COMP_EXEC_IDLE)
9775
30.0k
                    return COMP_DROP_QUEUE;
9776
58.8k
                return state;
9777
88.8k
            }
9778
120k
        case PDF14_BEGIN_TRANS_PAGE_GROUP:
9779
574k
        case PDF14_BEGIN_TRANS_GROUP:
9780
574k
            return COMP_ENQUEUE;
9781
535k
        case PDF14_END_TRANS_GROUP:
9782
574k
        case PDF14_END_TRANS_TEXT_GROUP:
9783
574k
            if (*ppcte == NULL)
9784
97.7k
                return COMP_EXEC_QUEUE;
9785
476k
            return find_opening_op(PDF14_BEGIN_TRANS_GROUP, ppcte, COMP_MARK_IDLE);
9786
1.21M
        case PDF14_BEGIN_TRANS_MASK:
9787
1.21M
            return COMP_ENQUEUE;
9788
0
        case PDF14_PUSH_TRANS_STATE:
9789
0
            return COMP_ENQUEUE;
9790
1.00M
        case PDF14_POP_TRANS_STATE:
9791
1.00M
            return COMP_ENQUEUE;
9792
0
        case PDF14_PUSH_SMASK_COLOR:
9793
0
            return COMP_ENQUEUE;
9794
0
            break;
9795
0
        case PDF14_POP_SMASK_COLOR:
9796
0
            return COMP_ENQUEUE;
9797
0
            break;
9798
131k
        case PDF14_END_TRANS_MASK:
9799
131k
            if (*ppcte == NULL)
9800
87.2k
                return COMP_EXEC_QUEUE;
9801
44.3k
            return find_opening_op(PDF14_BEGIN_TRANS_MASK, ppcte, COMP_MARK_IDLE);
9802
7.74M
        case PDF14_SET_BLEND_PARAMS:
9803
7.74M
            if (*ppcte == NULL)
9804
592k
                return COMP_ENQUEUE;
9805
            /* hack : ignore csel - here it is always zero : */
9806
7.14M
            return find_same_op(composite_action, PDF14_SET_BLEND_PARAMS, ppcte);
9807
11.8M
    }
9808
11.8M
}
9809
9810
/*
9811
 * Check whether a next operation is friendly to the compositor.
9812
 */
9813
static bool
9814
c_pdf14trans_is_friendly(const gs_composite_t * composite_action, byte cmd0, byte cmd1)
9815
1.26M
{
9816
1.26M
    gs_pdf14trans_t *pct0 = (gs_pdf14trans_t *)composite_action;
9817
1.26M
    int op0 = pct0->params.pdf14_op;
9818
9819
1.26M
    if (op0 == PDF14_PUSH_DEVICE || op0 == PDF14_END_TRANS_GROUP ||
9820
1.26M
        op0 == PDF14_END_TRANS_TEXT_GROUP) {
9821
        /* Halftone commands are always passed to the target printer device,
9822
           because transparency buffers are always contone.
9823
           So we're safe to execute them before queued transparency compositors. */
9824
313k
        if (cmd0 == cmd_opv_extend && (cmd1 == cmd_opv_ext_put_halftone ||
9825
171k
                                       cmd1 == cmd_opv_ext_put_ht_seg))
9826
171k
            return true;
9827
142k
        if (cmd0 == cmd_opv_set_misc && (cmd1 >> 6) == (cmd_set_misc_map >> 6))
9828
141k
            return true;
9829
142k
    }
9830
949k
    return false;
9831
1.26M
}
9832
9833
static composite_create_default_compositor_proc(c_pdf14trans_create_default_compositor);
9834
static composite_equal_proc(c_pdf14trans_equal);
9835
static composite_write_proc(c_pdf14trans_write);
9836
static composite_read_proc(c_pdf14trans_read);
9837
static composite_adjust_ctm_proc(c_pdf14trans_adjust_ctm);
9838
static composite_is_closing_proc(c_pdf14trans_is_closing);
9839
static composite_is_friendly_proc(c_pdf14trans_is_friendly);
9840
static composite_clist_write_update(c_pdf14trans_clist_write_update);
9841
static composite_clist_read_update(c_pdf14trans_clist_read_update);
9842
static composite_get_cropping_proc(c_pdf14trans_get_cropping);
9843
9844
/*
9845
 * Methods for the PDF 1.4 transparency compositor
9846
 *
9847
 * Note:  We have two set of methods.  They are the same except for the
9848
 * composite_clist_write_update method.  Once the clist write device is created,
9849
 * we use the second set of procedures.  This prevents the creation of multiple
9850
 * PDF 1.4 clist write compositor devices being chained together.
9851
 */
9852
const gs_composite_type_t   gs_composite_pdf14trans_type = {
9853
    GX_COMPOSITOR_PDF14_TRANS,
9854
    {
9855
        c_pdf14trans_create_default_compositor, /* procs.create_default_compositor */
9856
        c_pdf14trans_equal,                      /* procs.equal */
9857
        c_pdf14trans_write,                      /* procs.write */
9858
        c_pdf14trans_read,                       /* procs.read */
9859
        c_pdf14trans_adjust_ctm,     /* procs.adjust_ctm */
9860
        c_pdf14trans_is_closing,                 /* procs.is_closing */
9861
        c_pdf14trans_is_friendly,                /* procs.is_friendly */
9862
                /* Create a PDF 1.4 clist write device */
9863
        c_pdf14trans_clist_write_update,   /* procs.composite_clist_write_update */
9864
        c_pdf14trans_clist_read_update,    /* procs.composite_clist_read_update */
9865
        c_pdf14trans_get_cropping    /* procs.composite_get_cropping */
9866
    }                                            /* procs */
9867
};
9868
9869
const gs_composite_type_t   gs_composite_pdf14trans_no_clist_writer_type = {
9870
    GX_COMPOSITOR_PDF14_TRANS,
9871
    {
9872
        c_pdf14trans_create_default_compositor, /* procs.create_default_compositor */
9873
        c_pdf14trans_equal,                      /* procs.equal */
9874
        c_pdf14trans_write,                      /* procs.write */
9875
        c_pdf14trans_read,                       /* procs.read */
9876
        c_pdf14trans_adjust_ctm,     /* procs.adjust_ctm */
9877
        c_pdf14trans_is_closing,                 /* procs.is_closing */
9878
        c_pdf14trans_is_friendly,                /* procs.is_friendly */
9879
                /* The PDF 1.4 clist writer already exists, Do not create it. */
9880
        gx_default_composite_clist_write_update, /* procs.composite_clist_write_update */
9881
        c_pdf14trans_clist_read_update,    /* procs.composite_clist_read_update */
9882
        c_pdf14trans_get_cropping    /* procs.composite_get_cropping */
9883
    }                                            /* procs */
9884
};
9885
9886
/*
9887
 * Verify that a compositor data structure is for the PDF 1.4 compositor.
9888
 */
9889
int
9890
gs_is_pdf14trans_compositor(const gs_composite_t * pct)
9891
35.5M
{
9892
35.5M
    return (pct->type == &gs_composite_pdf14trans_type
9893
35.5M
                || pct->type == &gs_composite_pdf14trans_no_clist_writer_type);
9894
35.5M
}
9895
9896
/*
9897
 * Create a PDF 1.4 transparency compositor data structure.
9898
 */
9899
static int
9900
gs_create_pdf14trans(
9901
    gs_composite_t **               ppct,
9902
    const gs_pdf14trans_params_t *  pparams,
9903
    gs_memory_t *                   mem )
9904
13.6M
{
9905
13.6M
    gs_pdf14trans_t *                pct;
9906
9907
13.6M
    pct = gs_alloc_struct(mem, gs_pdf14trans_t, &st_pdf14trans,
9908
13.6M
                             "gs_create_pdf14trans");
9909
13.6M
    if (pct == NULL)
9910
0
        return_error(gs_error_VMerror);
9911
13.6M
    pct->type = &gs_composite_pdf14trans_type;
9912
13.6M
    pct->id = gs_next_ids(mem, 1);
9913
13.6M
    pct->params = *pparams;
9914
13.6M
    pct->idle = false;
9915
13.6M
    *ppct = (gs_composite_t *)pct;
9916
13.6M
    return 0;
9917
13.6M
}
9918
9919
/*
9920
 * Send a PDF 1.4 transparency compositor action to the specified device.
9921
 */
9922
int
9923
send_pdf14trans(gs_gstate * pgs, gx_device * dev,
9924
    gx_device * * pcdev, gs_pdf14trans_params_t * pparams, gs_memory_t * mem)
9925
524k
{
9926
524k
    gs_composite_t * pct = NULL;
9927
524k
    int code;
9928
9929
524k
    pparams->ctm = ctm_only(pgs);
9930
524k
    code = gs_create_pdf14trans(&pct, pparams, mem);
9931
524k
    if (code < 0)
9932
0
        return code;
9933
524k
    code = dev_proc(dev, composite) (dev, pcdev, pct, pgs, mem, NULL);
9934
524k
    if (code == gs_error_handled)
9935
0
        code = 0;
9936
9937
524k
    gs_free_object(pgs->memory, pct, "send_pdf14trans");
9938
9939
524k
    return code;
9940
524k
}
9941
9942
/* ------------- PDF 1.4 transparency device for clist writing ------------- */
9943
9944
/*
9945
 * The PDF 1.4 transparency compositor device may have a different process
9946
 * color model than the output device.  If we are banding then we need to
9947
 * create two compositor devices.  The output side (clist reader) needs a
9948
 * compositor to actually composite the output.  We also need a compositor
9949
 * device before the clist writer.  This is needed to provide a process color
9950
 * model which matches the PDF 1.4 blending space.
9951
 *
9952
 * This section provides support for this device.
9953
 */
9954
9955
/*
9956
 * Define the default pre-clist (clist writer) PDF 1.4 compositing device.
9957
 * We actually use the same structure for both the clist writer and reader
9958
 * devices.  However we use separate names to identify the routines for each
9959
 * device.
9960
 */
9961
9962
static  dev_proc_composite(pdf14_clist_composite);
9963
static  dev_proc_composite(pdf14_clist_forward_composite);
9964
static  dev_proc_fill_path(pdf14_clist_fill_path);
9965
static  dev_proc_stroke_path(pdf14_clist_stroke_path);
9966
static  dev_proc_fill_stroke_path(pdf14_clist_fill_stroke_path);
9967
static  dev_proc_text_begin(pdf14_clist_text_begin);
9968
static  dev_proc_begin_typed_image(pdf14_clist_begin_typed_image);
9969
static  dev_proc_copy_planes(pdf14_clist_copy_planes);
9970
9971
static void
9972
pdf14_clist_init_procs(gx_device *dev,
9973
                       dev_proc_get_color_mapping_procs(get_color_mapping_procs),
9974
                       dev_proc_get_color_comp_index(get_color_comp_index))
9975
2.72k
{
9976
2.72k
    set_dev_proc(dev, get_initial_matrix, gx_forward_get_initial_matrix);
9977
2.72k
    set_dev_proc(dev, sync_output, gx_forward_sync_output);
9978
2.72k
    set_dev_proc(dev, output_page, gx_forward_output_page);
9979
2.72k
    set_dev_proc(dev, close_device, gx_forward_close_device);
9980
2.72k
    set_dev_proc(dev, map_rgb_color, pdf14_encode_color);
9981
2.72k
    set_dev_proc(dev, map_color_rgb, pdf14_decode_color);
9982
2.72k
    set_dev_proc(dev, fill_rectangle, gx_forward_fill_rectangle);
9983
2.72k
    set_dev_proc(dev, copy_mono, gx_forward_copy_mono);
9984
2.72k
    set_dev_proc(dev, copy_color, gx_forward_copy_color);
9985
2.72k
    set_dev_proc(dev, get_params, gx_forward_get_params);
9986
2.72k
    set_dev_proc(dev, put_params, pdf14_put_params);
9987
2.72k
    set_dev_proc(dev, map_cmyk_color, pdf14_encode_color);
9988
2.72k
    set_dev_proc(dev, get_page_device, gx_forward_get_page_device);
9989
2.72k
    set_dev_proc(dev, copy_alpha, gx_forward_copy_alpha);
9990
2.72k
    set_dev_proc(dev, fill_path, pdf14_clist_fill_path);
9991
2.72k
    set_dev_proc(dev, stroke_path, pdf14_clist_stroke_path);
9992
2.72k
    set_dev_proc(dev, fill_mask, gx_forward_fill_mask);
9993
2.72k
    set_dev_proc(dev, fill_trapezoid, gx_forward_fill_trapezoid);
9994
2.72k
    set_dev_proc(dev, fill_parallelogram, gx_forward_fill_parallelogram);
9995
2.72k
    set_dev_proc(dev, fill_triangle, gx_forward_fill_triangle);
9996
2.72k
    set_dev_proc(dev, draw_thin_line, gx_forward_draw_thin_line);
9997
2.72k
    set_dev_proc(dev, strip_tile_rectangle, gx_forward_strip_tile_rectangle);
9998
2.72k
    set_dev_proc(dev, strip_copy_rop2, gx_forward_strip_copy_rop2);
9999
2.72k
    set_dev_proc(dev, get_clipping_box, gx_forward_get_clipping_box);
10000
2.72k
    set_dev_proc(dev, begin_typed_image, pdf14_clist_begin_typed_image);
10001
2.72k
    set_dev_proc(dev, get_bits_rectangle, gx_forward_get_bits_rectangle);
10002
2.72k
    set_dev_proc(dev, composite, pdf14_clist_composite);
10003
2.72k
    set_dev_proc(dev, get_hardware_params, gx_forward_get_hardware_params);
10004
2.72k
    set_dev_proc(dev, text_begin, pdf14_clist_text_begin);
10005
2.72k
    set_dev_proc(dev, begin_transparency_group, pdf14_begin_transparency_group);
10006
2.72k
    set_dev_proc(dev, end_transparency_group, pdf14_end_transparency_group);
10007
2.72k
    set_dev_proc(dev, begin_transparency_mask, pdf14_begin_transparency_mask);
10008
2.72k
    set_dev_proc(dev, end_transparency_mask, pdf14_end_transparency_mask);
10009
2.72k
    set_dev_proc(dev, discard_transparency_layer, gx_default_discard_transparency_layer);
10010
2.72k
    set_dev_proc(dev, get_color_mapping_procs, get_color_mapping_procs);
10011
2.72k
    set_dev_proc(dev, get_color_comp_index, get_color_comp_index);
10012
2.72k
    set_dev_proc(dev, encode_color, pdf14_encode_color);
10013
2.72k
    set_dev_proc(dev, decode_color, pdf14_decode_color);
10014
2.72k
    set_dev_proc(dev, fill_rectangle_hl_color, gx_forward_fill_rectangle_hl_color);
10015
2.72k
    set_dev_proc(dev, update_spot_equivalent_colors, gx_forward_update_spot_equivalent_colors);
10016
2.72k
    set_dev_proc(dev, ret_devn_params, pdf14_ret_devn_params);
10017
2.72k
    set_dev_proc(dev, fillpage, gx_forward_fillpage);
10018
2.72k
    set_dev_proc(dev, push_transparency_state, pdf14_push_transparency_state);
10019
2.72k
    set_dev_proc(dev, pop_transparency_state, pdf14_pop_transparency_state);
10020
2.72k
    set_dev_proc(dev, dev_spec_op, pdf14_dev_spec_op);
10021
2.72k
    set_dev_proc(dev, copy_planes, pdf14_clist_copy_planes);
10022
2.72k
    set_dev_proc(dev, set_graphics_type_tag, gx_forward_set_graphics_type_tag);
10023
2.72k
    set_dev_proc(dev, copy_alpha_hl_color, gx_forward_copy_alpha_hl_color);
10024
2.72k
    set_dev_proc(dev, fill_stroke_path, pdf14_clist_fill_stroke_path);
10025
2.72k
}
10026
10027
static void
10028
pdf14_clist_Gray_initialize_device_procs(gx_device *dev)
10029
155
{
10030
155
    pdf14_clist_init_procs(dev,
10031
155
                           gx_default_DevGray_get_color_mapping_procs,
10032
155
                           gx_default_DevGray_get_color_comp_index);
10033
155
}
10034
10035
static void
10036
pdf14_clist_RGB_initialize_device_procs(gx_device *dev)
10037
2.03k
{
10038
2.03k
    pdf14_clist_init_procs(dev,
10039
2.03k
                           gx_default_DevRGB_get_color_mapping_procs,
10040
2.03k
                           gx_default_DevRGB_get_color_comp_index);
10041
2.03k
}
10042
10043
static void
10044
pdf14_clist_CMYK_initialize_device_procs(gx_device *dev)
10045
0
{
10046
0
    pdf14_clist_init_procs(dev,
10047
0
                           gx_default_DevCMYK_get_color_mapping_procs,
10048
0
                           gx_default_DevCMYK_get_color_comp_index);
10049
0
}
10050
10051
static void
10052
pdf14_clist_CMYKspot_initialize_device_procs(gx_device *dev)
10053
539
{
10054
539
    pdf14_clist_init_procs(dev,
10055
539
                           pdf14_cmykspot_get_color_mapping_procs,
10056
539
                           pdf14_cmykspot_get_color_comp_index);
10057
539
}
10058
10059
#if 0 /* NOT USED */
10060
static void
10061
pdf14_clist_RGBspot_initialize_device_procs(gx_device *dev)
10062
{
10063
    pdf14_clist_init_procs(dev,
10064
                           pdf14_rgbspot_get_color_mapping_procs,
10065
                           pdf14_rgbspot_get_color_comp_index);
10066
}
10067
10068
static int
10069
pdf14_clist_Grayspot_initialize_device_procs(gx_device *dev)
10070
{
10071
    pdf14_clist_init_procs(dev,
10072
                           pdf14_grayspot_get_color_mapping_procs,
10073
                           pdf14_grayspot_get_color_comp_index);
10074
}
10075
#endif  /* NOT USED */
10076
10077
const pdf14_clist_device pdf14_clist_Gray_device = {
10078
    std_device_color_stype_body(pdf14_clist_device,
10079
                                pdf14_clist_Gray_initialize_device_procs,
10080
                                "pdf14clistgray",
10081
                                &st_pdf14_device,
10082
                                XSIZE, YSIZE, X_DPI, Y_DPI, 8, 255, 256),
10083
    { 0 },      /* Procs */
10084
    NULL,     /* target */
10085
    { 0 },      /* devn_params - not used */
10086
    &gray_pdf14_procs,
10087
    &gray_blending_procs
10088
};
10089
10090
const pdf14_clist_device pdf14_clist_RGB_device = {
10091
    std_device_color_stype_body(pdf14_clist_device,
10092
                                pdf14_clist_RGB_initialize_device_procs,
10093
                                "pdf14clistRGB",
10094
                                &st_pdf14_device,
10095
                                XSIZE, YSIZE, X_DPI, Y_DPI, 24, 255, 256),
10096
    { 0 },      /* Procs */
10097
    NULL,     /* target */
10098
    { 0 },      /* devn_params - not used */
10099
    &rgb_pdf14_procs,
10100
    &rgb_blending_procs
10101
};
10102
10103
const pdf14_clist_device pdf14_clist_CMYK_device = {
10104
    std_device_std_color_full_body_type(pdf14_clist_device,
10105
                                        pdf14_clist_CMYK_initialize_device_procs,
10106
                                        "pdf14clistcmyk",
10107
                                        &st_pdf14_device,
10108
                                        XSIZE, YSIZE, X_DPI, Y_DPI, 32,
10109
                                        0, 0, 0, 0, 0, 0),
10110
    { 0 },      /* Procs */
10111
    NULL,     /* target */
10112
    { 0 },      /* devn_params - not used */
10113
    &cmyk_pdf14_procs,
10114
    &cmyk_blending_procs
10115
};
10116
10117
const pdf14_clist_device pdf14_clist_CMYKspot_device = {
10118
    std_device_part1_(pdf14_device,
10119
                      pdf14_clist_CMYKspot_initialize_device_procs,
10120
                      "pdf14clistcmykspot",
10121
                      &st_pdf14_device,
10122
                      open_init_closed),
10123
    dci_values(GX_DEVICE_COLOR_MAX_COMPONENTS,64,255,255,256,256),
10124
    std_device_part2_(XSIZE, YSIZE, X_DPI, Y_DPI),
10125
    offset_margin_values(0, 0, 0, 0, 0, 0),
10126
    std_device_part3_(),
10127
    { 0 },      /* Procs */
10128
    NULL,     /* target */
10129
    /* DeviceN parameters */
10130
    { 8,      /* Not used - Bits per color */
10131
      DeviceCMYKComponents, /* Names of color model colorants */
10132
      4,      /* Number colorants for CMYK */
10133
      0,      /* MaxSeparations has not been specified */
10134
      -1,     /* PageSpotColors has not been specified */
10135
      {0},      /* SeparationNames */
10136
      0,      /* SeparationOrder names */
10137
      {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
10138
    },
10139
    &cmykspot_pdf14_procs,
10140
    &cmyk_blending_procs
10141
};
10142
10143
const pdf14_clist_device pdf14_clist_custom_device = {
10144
    std_device_part1_(pdf14_device,
10145
                      pdf14_clist_CMYKspot_initialize_device_procs,
10146
                      "pdf14clistcustom",
10147
                      &st_pdf14_device,
10148
                      open_init_closed),
10149
    dci_values(GX_DEVICE_COLOR_MAX_COMPONENTS,64,255,255,256,256),
10150
    std_device_part2_(XSIZE, YSIZE, X_DPI, Y_DPI),
10151
    offset_margin_values(0, 0, 0, 0, 0, 0),
10152
    std_device_part3_(),
10153
    { 0 },      /* Procs */
10154
    NULL,     /* target */
10155
    /* DeviceN parameters */
10156
    { 8,      /* Not used - Bits per color */
10157
      DeviceCMYKComponents, /* Names of color model colorants */
10158
      4,      /* Number colorants for CMYK */
10159
      0,      /* MaxSeparations has not been specified */
10160
      -1,     /* PageSpotColors has not been specified */
10161
      {0},      /* SeparationNames */
10162
      0,      /* SeparationOrder names */
10163
      {0, 1, 2, 3, 4, 5, 6, 7 } /* Initial component SeparationOrder */
10164
    },
10165
    &custom_pdf14_procs,
10166
    &custom_blending_procs
10167
};
10168
10169
/*
10170
 * the PDF 1.4 transparency spec says that color space for blending
10171
 * operations can be based upon either a color space specified in the
10172
 * group or a default value based upon the output device.  We are
10173
 * currently only using a color space based upon the device.
10174
 */
10175
static  int
10176
get_pdf14_clist_device_proto(gx_device          *dev,
10177
                             pdf14_clist_device *pdevproto,
10178
                             gs_gstate          *pgs,
10179
                       const gs_pdf14trans_t    *pdf14pct,
10180
                             bool                use_pdf14_accum)
10181
2.72k
{
10182
2.72k
    pdf14_blend_cs_t blend_cs_state;
10183
2.72k
    pdf14_default_colorspace_t dev_cs =
10184
2.72k
                pdf14_determine_default_blend_cs(dev, use_pdf14_accum,
10185
2.72k
                                                 &blend_cs_state);
10186
2.72k
    bool has_tags = device_encodes_tags(dev);
10187
2.72k
    bool deep = device_is_deep(dev);
10188
2.72k
    int num_spots = pdf14pct->params.num_spot_colors;
10189
10190
    /* overprint overide */
10191
2.72k
    if (pdf14pct->params.overprint_sim_push &&
10192
2.72k
        blend_cs_state == PDF14_BLEND_CS_UNSPECIFIED) {
10193
0
        if (pdf14pct->params.num_spot_colors_int > 0) {
10194
0
            dev_cs = PDF14_DeviceCMYKspot;
10195
0
            num_spots = pdf14pct->params.num_spot_colors_int;
10196
0
        } else
10197
0
            dev_cs = PDF14_DeviceCMYK;
10198
0
    }
10199
10200
2.72k
    switch (dev_cs) {
10201
155
        case PDF14_DeviceGray:
10202
           /* We want gray to be single channel.  Low level
10203
               initialization of gray device prototype is
10204
               peculiar in that in dci_std_color_num_components
10205
               the comment is
10206
              "A device is monochrome only if it is bi-level"
10207
              Here we want monochrome anytime we have a gray device.
10208
              To avoid breaking things elsewhere, we will overide
10209
              the prototype intialization here */
10210
155
            *pdevproto = pdf14_clist_Gray_device;
10211
155
            pdevproto->color_info.max_components = 1;
10212
155
            pdevproto->color_info.num_components =
10213
155
                                    pdevproto->color_info.max_components;
10214
155
            pdevproto->color_info.max_gray = deep ? 65535 : 255;
10215
155
            pdevproto->color_info.gray_index = 0; /* Avoid halftoning */
10216
155
            pdevproto->color_info.dither_grays = pdevproto->color_info.max_gray+1;
10217
155
            pdevproto->color_info.anti_alias = dev->color_info.anti_alias;
10218
155
            pdevproto->color_info.depth = deep ? 16 : 8;
10219
155
            pdevproto->sep_device = false;
10220
155
            break;
10221
2.03k
        case PDF14_DeviceRGB:
10222
2.03k
            *pdevproto = pdf14_clist_RGB_device;
10223
2.03k
            pdevproto->color_info.anti_alias = dev->color_info.anti_alias;
10224
2.03k
            pdevproto->sep_device = false;
10225
2.03k
            if (deep) {
10226
0
                pdevproto->color_info.depth = 3*16;
10227
0
                pdevproto->color_info.max_color = 65535;
10228
0
                pdevproto->color_info.max_gray = 65535;
10229
0
                pdevproto->color_info.dither_colors = 65536;
10230
0
                pdevproto->color_info.dither_grays = 65536;
10231
0
            }
10232
2.03k
            break;
10233
0
        case PDF14_DeviceCMYK:
10234
0
            *pdevproto = pdf14_clist_CMYK_device;
10235
0
            pdevproto->color_info.anti_alias = dev->color_info.anti_alias;
10236
0
            pdevproto->sep_device = false;
10237
0
            if (deep) {
10238
0
                pdevproto->color_info.depth = 4*16;
10239
0
                pdevproto->color_info.max_color = 65535;
10240
0
                pdevproto->color_info.max_gray = 65535;
10241
0
                pdevproto->color_info.dither_colors = 65536;
10242
0
                pdevproto->color_info.dither_grays = 65536;
10243
0
            }
10244
0
            break;
10245
539
        case PDF14_DeviceCMYKspot:
10246
539
            *pdevproto = pdf14_clist_CMYKspot_device;
10247
            /*
10248
             * The number of components for the PDF14 device is the sum
10249
             * of the process components and the number of spot colors
10250
             * for the page. If we are using an NCLR ICC profile at
10251
             * the output device, those spot colors are skipped. They
10252
             * do not appear in the transparency buffer, but appear
10253
             * during put image transform of the page group to the target
10254
             * color space.
10255
             */
10256
539
            if (num_spots >= 0) {
10257
539
                pdevproto->devn_params.page_spot_colors = num_spots;
10258
539
                pdevproto->color_info.num_components =
10259
539
                    pdevproto->devn_params.num_std_colorant_names + num_spots;
10260
539
                if (pdevproto->color_info.num_components >
10261
539
                              pdevproto->color_info.max_components)
10262
0
                    pdevproto->color_info.num_components =
10263
0
                              pdevproto->color_info.max_components;
10264
539
                pdevproto->color_info.depth =
10265
539
                              pdevproto->color_info.num_components * (8<<deep);
10266
539
                if (deep && has_tags)
10267
0
                    pdevproto->color_info.depth -= 8;
10268
539
            }
10269
539
            pdevproto->color_info.anti_alias = dev->color_info.anti_alias;
10270
539
            pdevproto->sep_device = true;
10271
539
            break;
10272
0
        case PDF14_DeviceCustom:
10273
            /*
10274
             * We are using the output device's process color model.  The
10275
             * color_info for the PDF 1.4 compositing device needs to match
10276
             * the output device.
10277
             */
10278
0
            *pdevproto = pdf14_clist_custom_device;
10279
0
            pdevproto->color_info = dev->color_info;
10280
            /* The pdf14 device has to be 8 (or 16) bit continuous tone. Force it */
10281
0
            pdevproto->color_info.depth =
10282
0
                pdevproto->color_info.num_components * (8<<deep);
10283
0
            pdevproto->color_info.max_gray = deep ? 65535 : 255;
10284
0
            pdevproto->color_info.max_color = deep ? 65535 : 255;
10285
0
            pdevproto->color_info.dither_grays = deep ? 65536 : 256;
10286
0
            pdevproto->color_info.dither_colors = deep ? 65536 : 256;
10287
0
            pdevproto->color_info.anti_alias = dev->color_info.anti_alias;
10288
0
            break;
10289
0
        default:      /* Should not occur */
10290
0
            return_error(gs_error_rangecheck);
10291
2.72k
    }
10292
2.72k
    pdevproto->overprint_sim = pdf14pct->params.overprint_sim_push;
10293
2.72k
    pdevproto->blend_cs_state = blend_cs_state;
10294
2.72k
    return 0;
10295
2.72k
}
10296
10297
static  int
10298
pdf14_create_clist_device(gs_memory_t *mem, gs_gstate * pgs,
10299
                                gx_device ** ppdev, gx_device * target,
10300
                                const gs_pdf14trans_t * pdf14pct)
10301
2.72k
{
10302
2.72k
    pdf14_clist_device dev_proto;
10303
2.72k
    pdf14_clist_device * pdev;
10304
2.72k
    int code;
10305
2.72k
    bool has_tags = device_encodes_tags(target);
10306
2.72k
    cmm_profile_t *target_profile;
10307
2.72k
    gsicc_rendering_param_t render_cond;
10308
2.72k
    cmm_dev_profile_t *dev_profile;
10309
2.72k
    uchar k;
10310
2.72k
    bool deep = device_is_deep(target);
10311
2.72k
    cmm_profile_t *icc_profile;
10312
10313
10314
2.72k
    code = dev_proc(target, get_profile)(target,  &dev_profile);
10315
2.72k
    if (code < 0)
10316
0
        return code;
10317
2.72k
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &target_profile,
10318
2.72k
                          &render_cond);
10319
2.72k
    if_debug0m('v', pgs->memory, "[v]pdf14_create_clist_device\n");
10320
2.72k
    code = get_pdf14_clist_device_proto(target, &dev_proto,
10321
2.72k
                                        pgs, pdf14pct, false);
10322
2.72k
    if (code < 0)
10323
0
        return code;
10324
2.72k
    code = gs_copydevice((gx_device **) &pdev,
10325
2.72k
                         (const gx_device *) &dev_proto, mem);
10326
2.72k
    if (code < 0)
10327
0
        return code;
10328
10329
    /* If we are not using a blending color space, the number of color planes
10330
       should not exceed that of the target */
10331
2.72k
    if (!(pdev->blend_cs_state != PDF14_BLEND_CS_UNSPECIFIED || pdev->overprint_sim)) {
10332
2.72k
        if (pdev->color_info.num_components > target->color_info.num_components)
10333
0
            pdev->color_info.num_components = target->color_info.num_components;
10334
2.72k
        if (pdev->color_info.max_components > target->color_info.max_components)
10335
539
            pdev->color_info.max_components = target->color_info.max_components;
10336
2.72k
    }
10337
2.72k
    pdev->color_info.depth = pdev->color_info.num_components * (8<<deep);
10338
2.72k
    pdev->pad = target->pad;
10339
2.72k
    pdev->log2_align_mod = target->log2_align_mod;
10340
10341
2.72k
    if (pdf14pct->params.overprint_sim_push && pdf14pct->params.num_spot_colors_int > 0 && !target->is_planar)
10342
0
        pdev->is_planar = true;
10343
2.72k
    else
10344
2.72k
        pdev->is_planar = target->is_planar;
10345
2.72k
    pdev->interpolate_threshold = dev_proc(target, dev_spec_op)(target, gxdso_interpolate_threshold, NULL, 0);
10346
10347
2.72k
    pdev->op_state = pgs->is_fill_color ? PDF14_OP_STATE_FILL : PDF14_OP_STATE_NONE;
10348
10349
2.72k
    if (deep) {
10350
0
        set_dev_proc(pdev, encode_color, pdf14_encode_color16);
10351
0
        set_dev_proc(pdev, decode_color, pdf14_decode_color16);
10352
0
    }
10353
    /* If we have a tag device then go ahead and do a special encoder decoder
10354
       for the pdf14 device to make sure we maintain this information in the
10355
       encoded color information.  We could use the target device's methods but
10356
       the PDF14 device has to maintain 8 bit color always and we could run
10357
       into other issues if the number of colorants became large.  If we need to
10358
       do compressed color with tags that will be a special project at that time */
10359
2.72k
    if (has_tags) {
10360
0
        set_dev_proc(pdev, encode_color, pdf14_encode_color_tag);
10361
0
        pdev->color_info.comp_shift[pdev->color_info.num_components] = pdev->color_info.depth;
10362
0
        pdev->color_info.depth += 8;
10363
0
    }
10364
2.72k
    pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN_STANDARD;  /* this is the standard */
10365
2.72k
    gx_device_fill_in_procs((gx_device *)pdev);
10366
2.72k
    gs_pdf14_device_copy_params((gx_device *)pdev, target);
10367
2.72k
    gx_device_set_target((gx_device_forward *)pdev, target);
10368
10369
    /* Components shift, etc have to be based upon 8 bit */
10370
11.1k
    for (k = 0; k < pdev->color_info.num_components; k++) {
10371
8.42k
        pdev->color_info.comp_bits[k] = 8<<deep;
10372
8.42k
        pdev->color_info.comp_shift[k] = (pdev->color_info.num_components - 1 - k) * (8<<deep);
10373
8.42k
    }
10374
2.72k
    code = dev_proc((gx_device *) pdev, open_device) ((gx_device *) pdev);
10375
2.72k
    pdev->pclist_device = target;
10376
10377
2.72k
    code = dev_proc(target, get_profile)(target, &dev_profile);
10378
2.72k
    if (code < 0)
10379
0
        return code;
10380
2.72k
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &icc_profile,
10381
2.72k
        &render_cond);
10382
2.72k
    if_debug0m('v', mem, "[v]pdf14_create_clist_device\n");
10383
10384
    /* Simulated overprint case.  We have to use CMYK-based profile
10385
       Also if the target profile is NCLR, we are going to use a pdf14
10386
       device that is CMYK based and do the mapping to the NCLR profile
10387
       when the put_image occurs */
10388
2.72k
    if ((pdev->overprint_sim && icc_profile->data_cs != gsCMYK) ||
10389
2.72k
         icc_profile->data_cs == gsNCHANNEL) {
10390
0
        gsicc_adjust_profile_rc(pgs->icc_manager->default_cmyk, 1, "pdf14_create_clist_device");
10391
0
        gsicc_adjust_profile_rc(pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE],
10392
0
            -1, "pdf14_create_clist_device");
10393
0
        pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] = pgs->icc_manager->default_cmyk;
10394
2.72k
    } else {
10395
        /* If the target profile was CIELAB, then overide with default RGB for
10396
           proper blending.  During put_image we will convert from RGB to
10397
           CIELAB */
10398
2.72k
        if ((target_profile->data_cs == gsCIELAB || target_profile->islab) &&
10399
2.72k
            pdev->blend_cs_state == PDF14_BLEND_CS_UNSPECIFIED) {
10400
0
            pdev->blend_cs_state = PDF14_BLEND_CS_TARGET_CIELAB;
10401
0
            rc_assign(pdev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE],
10402
0
                pgs->icc_manager->default_rgb, "pdf14_create_clist_device");
10403
0
        }
10404
2.72k
    }
10405
10406
2.72k
    if (pdf14pct->params.overprint_sim_push &&
10407
2.72k
        pdf14pct->params.num_spot_colors_int > 0) {
10408
0
        pdev->procs.update_spot_equivalent_colors = pdf14_update_spot_equivalent_colors;
10409
0
        pdev->procs.ret_devn_params = pdf14_ret_devn_params;
10410
0
        pdev->op_pequiv_cmyk_colors.all_color_info_valid = false;
10411
0
        pdev->target_support_devn = pdev->icc_struct->supports_devn;
10412
0
        pdev->icc_struct->supports_devn = true;  /* Reset when pdf14 device is disabled */
10413
0
    }
10414
    /* if the device has separations already defined (by SeparationOrderNames) */
10415
    /* we need to copy them (allocating new names) so the colorants are in the */
10416
    /* same order as the target device.                                        */
10417
2.72k
    if (dev_proc(target, dev_spec_op)(target, gxdso_supports_devn, NULL, 0)) {
10418
775
        code = devn_copy_params(target, (gx_device *)pdev);
10419
775
        if (code < 0)
10420
0
            return code;
10421
775
    }
10422
2.72k
    pdev->my_encode_color = dev_proc(pdev, encode_color);
10423
2.72k
    pdev->my_decode_color = dev_proc(pdev, decode_color);
10424
2.72k
    pdev->my_get_color_mapping_procs = dev_proc(pdev, get_color_mapping_procs);
10425
2.72k
    pdev->my_get_color_comp_index = dev_proc(pdev, get_color_comp_index);
10426
2.72k
    pdev->color_info.separable_and_linear =
10427
2.72k
        target->color_info.separable_and_linear;
10428
2.72k
    *ppdev = (gx_device *) pdev;
10429
2.72k
    return code;
10430
2.72k
}
10431
10432
/*
10433
 * Disable the PDF 1.4 clist compositor device.  Once created, the PDF 1.4
10434
 * compositor device is never removed.  (We do not have a remove compositor
10435
 * method.)  However it is no-op'ed when the PDF 1.4 device is popped.  This
10436
 * routine implements that action.
10437
 */
10438
static  int
10439
pdf14_disable_clist_device(gs_memory_t *mem, gs_gstate * pgs,
10440
                                gx_device * dev)
10441
2.65k
{
10442
2.65k
    gx_device_forward * pdev = (gx_device_forward *)dev;
10443
2.65k
    gx_device * target = pdev->target;
10444
10445
2.65k
    if_debug0m('v', pgs->memory, "[v]pdf14_disable_clist_device\n");
10446
10447
    /*
10448
     * To disable the action of this device, we forward all device
10449
     * procedures to the target except the composite and copy
10450
     * the target's color_info.
10451
     */
10452
2.65k
    dev->color_info = target->color_info;
10453
2.65k
    pdf14_forward_device_procs(dev);
10454
2.65k
    set_dev_proc(dev, composite, pdf14_clist_forward_composite);
10455
2.65k
    return 0;
10456
2.65k
}
10457
10458
/*
10459
 * Recreate the PDF 1.4 clist compositor device.  Once created, the PDF 1.4
10460
 * compositor device is never removed.  (We do not have a remove compositor
10461
 * method.)  However it is no-op'ed when the PDF 1.4 device is popped.  This
10462
 * routine will re-enable the compositor if the PDF 1.4 device is pushed
10463
 * again.
10464
 */
10465
static  int
10466
pdf14_recreate_clist_device(gs_memory_t *mem, gs_gstate * pgs,
10467
                gx_device * dev, const gs_pdf14trans_t * pdf14pct)
10468
0
{
10469
0
    pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
10470
0
    gx_device * target = pdev->target;
10471
0
    pdf14_clist_device dev_proto;
10472
0
    int code;
10473
10474
0
    if_debug0m('v', pgs->memory, "[v]pdf14_recreate_clist_device\n");
10475
    /*
10476
     * We will not use the entire prototype device but we will set the
10477
     * color related info to match the prototype.
10478
     */
10479
0
    code = get_pdf14_clist_device_proto(target, &dev_proto,
10480
0
                                        pgs, pdf14pct, false);
10481
0
    if (code < 0)
10482
0
        return code;
10483
0
    pdev->color_info = dev_proto.color_info;
10484
0
    pdev->procs = dev_proto.procs;
10485
0
    pdev->pad = target->pad;
10486
0
    pdev->log2_align_mod = target->log2_align_mod;
10487
10488
0
    if (pdf14pct->params.overprint_sim_push && pdf14pct->params.num_spot_colors_int > 0 && !target->is_planar)
10489
0
        pdev->is_planar = true;
10490
0
    else
10491
0
        pdev->is_planar = target->is_planar;
10492
0
    pdev->interpolate_threshold = dev_proc(target, dev_spec_op)(target, gxdso_interpolate_threshold, NULL, 0);
10493
10494
0
    pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN_STANDARD;
10495
0
    gx_device_fill_in_procs((gx_device *)pdev);
10496
0
    pdev->save_get_cmap_procs = pgs->get_cmap_procs;
10497
0
    pgs->get_cmap_procs = pdf14_get_cmap_procs;
10498
0
    gx_set_cmap_procs(pgs, (gx_device *)pdev);
10499
0
    check_device_separable((gx_device *)pdev);
10500
0
    return code;
10501
0
}
10502
10503
/*
10504
 * devicen params
10505
 */
10506
gs_devn_params *
10507
pdf14_ret_devn_params(gx_device *pdev)
10508
274k
{
10509
274k
    pdf14_device *p14dev = (pdf14_device *)pdev;
10510
10511
274k
    return &(p14dev->devn_params);
10512
274k
}
10513
10514
/*
10515
 * devicen params
10516
 */
10517
gs_devn_params *
10518
pdf14_accum_ret_devn_params(gx_device *pdev)
10519
0
{
10520
0
    gx_device_pdf14_accum *p14dev = (gx_device_pdf14_accum *)pdev;
10521
10522
0
    return &(p14dev->devn_params);
10523
0
}
10524
10525
static int
10526
pdf14_accum_get_color_comp_index(gx_device * dev,
10527
    const char * pname, int name_size, int component_type)
10528
0
{
10529
0
    pdf14_device *p14dev = (pdf14_device *)(((gx_device_pdf14_accum *)dev)->save_p14dev);
10530
0
    gx_device *target = p14dev->target;
10531
0
    int colorant_number = devn_get_color_comp_index(dev,
10532
0
                &(((gx_device_pdf14_accum *)dev)->devn_params),
10533
0
                &(((gx_device_pdf14_accum *)dev)->equiv_cmyk_colors),
10534
0
                pname, name_size, component_type, ENABLE_AUTO_SPOT_COLORS);
10535
10536
0
    if (target != NULL)
10537
        /* colorant_number returned here _should_ be the same as from above */
10538
0
        colorant_number = (*dev_proc(target, get_color_comp_index))
10539
0
                              (target, (const char *)pname, name_size, component_type);
10540
0
    return colorant_number;
10541
0
}
10542
10543
/*
10544
 * The following procedures are used to map the standard color spaces into
10545
 * the separation color components for the pdf14_accum device.
10546
 */
10547
static void
10548
pdf14_accum_gray_cs_to_cmyk_cm(const gx_device * dev, frac gray, frac out[])
10549
0
{
10550
0
    int * map =
10551
0
      (int *)(&((gx_device_pdf14_accum *) dev)->devn_params.separation_order_map);
10552
10553
0
    gray_cs_to_devn_cm(dev, map, gray, out);
10554
0
}
10555
10556
static void
10557
pdf14_accum_rgb_cs_to_cmyk_cm(const gx_device * dev,
10558
    const gs_gstate *pgs, frac r, frac g, frac b, frac out[])
10559
0
{
10560
0
    int * map =
10561
0
      (int *)(&((gx_device_pdf14_accum *) dev)->devn_params.separation_order_map);
10562
10563
0
    rgb_cs_to_devn_cm(dev, map, pgs, r, g, b, out);
10564
0
}
10565
10566
static void
10567
pdf14_accum_cmyk_cs_to_cmyk_cm(const gx_device * dev,
10568
    frac c, frac m, frac y, frac k, frac out[])
10569
0
{
10570
0
    const int * map =
10571
0
      (int *)(&((gx_device_pdf14_accum *) dev)->devn_params.separation_order_map);
10572
10573
0
    cmyk_cs_to_devn_cm(dev, map, c, m, y, k, out);
10574
0
}
10575
10576
static const gx_cm_color_map_procs pdf14_accum_cm_procs = {
10577
    pdf14_accum_gray_cs_to_cmyk_cm,
10578
    pdf14_accum_rgb_cs_to_cmyk_cm,
10579
    pdf14_accum_cmyk_cs_to_cmyk_cm
10580
};
10581
10582
static const gx_cm_color_map_procs *
10583
pdf14_accum_get_color_mapping_procs(const gx_device * dev, const gx_device **map_dev)
10584
0
{
10585
0
    *map_dev = dev;
10586
0
    return &pdf14_accum_cm_procs;
10587
0
}
10588
10589
/*
10590
 *  Device proc for updating the equivalent CMYK color for spot colors.
10591
 */
10592
static int
10593
pdf14_accum_update_spot_equivalent_colors(gx_device * dev, const gs_gstate * pgs, const gs_color_space *pcs)
10594
0
{
10595
0
    gx_device_pdf14_accum *pdev = (gx_device_pdf14_accum *)dev;
10596
0
    gx_device *tdev = ((pdf14_device *)(pdev->save_p14dev))->target;
10597
0
    int code = update_spot_equivalent_cmyk_colors(dev, pgs, pcs, &pdev->devn_params,
10598
0
                                              &pdev->equiv_cmyk_colors);
10599
10600
0
    if (code >= 0 && tdev != NULL)
10601
0
        code = dev_proc(tdev, update_spot_equivalent_colors)(tdev, pgs, pcs);
10602
0
    return code;
10603
0
}
10604
10605
/* Used when doing overprint simulation and have spot colors */
10606
static int
10607
pdf14_update_spot_equivalent_colors(gx_device *dev, const gs_gstate *pgs, const gs_color_space *pcs)
10608
0
{
10609
0
    pdf14_device *pdev = (pdf14_device *)dev;
10610
0
    int code;
10611
10612
    /* Make sure we are not All or None */
10613
0
    if (pcs != NULL && pcs->type->index == gs_color_space_index_Separation &&
10614
0
        pcs->params.separation.sep_type != SEP_OTHER)
10615
0
            return 0;
10616
10617
0
    code = update_spot_equivalent_cmyk_colors(dev, pgs, pcs, &pdev->devn_params,
10618
0
        &pdev->op_pequiv_cmyk_colors);
10619
0
    return code;
10620
0
}
10621
10622
/*
10623
 * Retrieve a list of spot color names for the PDF14 device.
10624
 */
10625
int
10626
put_param_pdf14_spot_names(gx_device * pdev,
10627
                gs_separations * pseparations, gs_param_list * plist)
10628
41.2k
{
10629
41.2k
    int code, num_spot_colors, i;
10630
41.2k
    gs_param_string str;
10631
10632
    /* Check if the given keyname is present. */
10633
41.2k
    code = param_read_int(plist, PDF14NumSpotColorsParamName,
10634
41.2k
                                                &num_spot_colors);
10635
41.2k
    switch (code) {
10636
0
        default:
10637
0
            param_signal_error(plist, PDF14NumSpotColorsParamName, code);
10638
0
            break;
10639
41.2k
        case 1:
10640
41.2k
            return 0;
10641
0
        case 0:
10642
0
            if (num_spot_colors < 1 ||
10643
0
                num_spot_colors > GX_DEVICE_COLOR_MAX_COMPONENTS)
10644
0
                return_error(gs_error_rangecheck);
10645
0
            for (i = 0; i < num_spot_colors; i++) {
10646
0
                char buff[20];
10647
0
                byte * sep_name;
10648
10649
0
                gs_snprintf(buff, sizeof(buff), "PDF14SpotName_%d", i);
10650
0
                code = param_read_string(plist, buff, &str);
10651
0
                switch (code) {
10652
0
                    default:
10653
0
                        param_signal_error(plist, buff, code);
10654
0
                        break;
10655
0
                    case 0:
10656
0
                        sep_name = gs_alloc_bytes(pdev->memory,
10657
0
                                str.size, "put_param_pdf14_spot_names");
10658
0
                        memcpy(sep_name, str.data, str.size);
10659
0
                        pseparations->names[i].size = str.size;
10660
0
                        pseparations->names[i].data = sep_name;
10661
0
                }
10662
0
            }
10663
0
            pseparations->num_separations = num_spot_colors;
10664
0
            break;
10665
41.2k
    }
10666
0
    return 0;;
10667
0
}
10668
10669
/*
10670
 * This procedure will have information from the PDF 1.4 clist writing
10671
 * clist compositior device.  This is information output the compressed
10672
 * color list info which is needed for the support of spot colors in
10673
 * PDF 1.4 compositing.  This info needs to be passed to the PDF 1.4
10674
 * clist reading compositor.  However this device is not created until
10675
 * the clist is read.  To get this info to that device, we have to
10676
 * temporarily store that info in the output device.  This routine saves
10677
 * that info in the output device.
10678
 */
10679
int
10680
pdf14_put_devn_params(gx_device * pdev, gs_devn_params * pdevn_params,
10681
                                        gs_param_list * plist)
10682
41.2k
{
10683
41.2k
    int code;
10684
41.2k
    code = put_param_pdf14_spot_names(pdev,
10685
41.2k
                       &pdevn_params->pdf14_separations, plist);
10686
41.2k
    return code;
10687
41.2k
}
10688
10689
/*
10690
 * When we are banding, we have two PDF 1.4 compositor devices.  One for
10691
 * when we are creating the clist.  The second is for imaging the data from
10692
 * the clist.  This routine is part of the clist writing PDF 1.4 device.
10693
 * This routine is only called once the PDF 1.4 clist write compositor already
10694
 * exists.
10695
 */
10696
static  int
10697
pdf14_clist_composite(gx_device * dev, gx_device ** pcdev,
10698
    const gs_composite_t * pct, gs_gstate * pgs, gs_memory_t * mem,
10699
    gx_device *cdev)
10700
579k
{
10701
579k
    pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
10702
579k
    int code, is_pdf14_compositor;
10703
579k
    const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct;
10704
579k
    bool deep = device_is_deep(dev);
10705
10706
    /* We only handle a few PDF 1.4 transparency operations */
10707
579k
    if ((is_pdf14_compositor = gs_is_pdf14trans_compositor(pct)) != 0) {
10708
451k
        switch (pdf14pct->params.pdf14_op) {
10709
0
            case PDF14_PUSH_DEVICE:
10710
                /* Re-activate the PDF 1.4 compositor */
10711
0
                pdev->saved_target_color_info = pdev->target->color_info;
10712
0
                pdev->target->color_info = pdev->color_info;
10713
0
                pdev->saved_target_encode_color = dev_proc(pdev->target, encode_color);
10714
0
                pdev->saved_target_decode_color = dev_proc(pdev->target, decode_color);
10715
0
                set_dev_proc(pdev->target, encode_color, pdev->my_encode_color);
10716
0
                set_dev_proc(pdev, encode_color, pdev->my_encode_color);
10717
0
                set_dev_proc(pdev->target, decode_color, pdev->my_decode_color);
10718
0
                set_dev_proc(pdev, decode_color, pdev->my_decode_color);
10719
0
                pdev->saved_target_get_color_mapping_procs =
10720
0
                                        dev_proc(pdev->target, get_color_mapping_procs);
10721
0
                pdev->saved_target_get_color_comp_index =
10722
0
                                        dev_proc(pdev->target, get_color_comp_index);
10723
0
                set_dev_proc(pdev->target, get_color_mapping_procs, pdev->my_get_color_mapping_procs);
10724
0
                set_dev_proc(pdev, get_color_mapping_procs, pdev->my_get_color_mapping_procs);
10725
0
                set_dev_proc(pdev->target, get_color_comp_index, pdev->my_get_color_comp_index);
10726
0
                set_dev_proc(pdev, get_color_comp_index, pdev->my_get_color_comp_index);
10727
0
                pdev->save_get_cmap_procs = pgs->get_cmap_procs;
10728
0
                pgs->get_cmap_procs = pdf14_get_cmap_procs;
10729
0
                gx_set_cmap_procs(pgs, dev);
10730
0
                code = pdf14_recreate_clist_device(mem, pgs, dev, pdf14pct);
10731
0
                pdev->blend_mode = pdev->text_knockout = 0;
10732
0
                pdev->opacity = pdev->shape = 0.0;
10733
0
                if (code < 0)
10734
0
                    return code;
10735
                /*
10736
                 * This routine is part of the PDF 1.4 clist write device.
10737
                 * Change the compositor procs to not create another since we
10738
                 * do not need to create a chain of identical devices.
10739
                 */
10740
0
                {
10741
0
                    gs_pdf14trans_t pctemp = *pdf14pct;
10742
10743
0
                    pctemp.type = &gs_composite_pdf14trans_no_clist_writer_type;
10744
0
                    code = dev_proc(pdev->target, composite)
10745
0
                                (pdev->target, pcdev, (gs_composite_t *)&pctemp, pgs, mem, cdev);
10746
                    /* We should never have created a new device here. */
10747
0
                    assert(code != 1);
10748
0
                    return code;
10749
0
                }
10750
2.65k
            case PDF14_POP_DEVICE:
10751
2.65k
            {
10752
2.65k
                gx_device *clistdev = pdev->target;
10753
10754
                /* Find the clist device */
10755
2.65k
                while (1) {
10756
2.65k
                    gxdso_device_child_request req;
10757
                    /* Ignore any errors here, that's expected as non-clist
10758
                     * devices don't implement it. */
10759
2.65k
                    code = dev_proc(clistdev, dev_spec_op)(clistdev, gxdso_is_clist_device, NULL, 0);
10760
2.65k
                    if (code == 1)
10761
2.65k
                        break;
10762
0
                    req.n = 0;
10763
0
                    req.target = clistdev;
10764
0
                    code = dev_proc(clistdev, dev_spec_op)(clistdev, gxdso_device_child, &req, sizeof(req));
10765
0
                    if (code < 0)
10766
0
                        return code;
10767
0
                    clistdev = req.target;
10768
0
                }
10769
10770
                /* If we have overprint simulation spot color information, store
10771
                   it in a pseudo-band of the clist */
10772
2.65k
                if (pdev->overprint_sim &&
10773
2.65k
                    pdev->devn_params.page_spot_colors > 0) {
10774
0
                    code = clist_write_op_equiv_cmyk_colors((gx_device_clist_writer *)clistdev,
10775
0
                        &pdev->op_pequiv_cmyk_colors);
10776
0
                    if (code < 0)
10777
0
                        return code;
10778
0
                }
10779
10780
                /* If we hit an error during an SMask, we need to undo the color
10781
                 * swapping before continuing. pdf14_decrement_smask_color() checks
10782
                 * for itself if it needs to take action.
10783
                 */
10784
2.65k
                pdf14_decrement_smask_color(pgs, dev);
10785
                /* Restore the color_info for the clist device */
10786
2.65k
                clistdev->color_info = pdev->saved_target_color_info;
10787
2.65k
                ((gx_device_clist_writer*)clistdev)->clist_color_info = clistdev->color_info; /* also reset for writer */
10788
2.65k
                set_dev_proc(clistdev, encode_color, pdev->saved_target_encode_color);
10789
2.65k
                set_dev_proc(clistdev, decode_color, pdev->saved_target_decode_color);
10790
2.65k
                set_dev_proc(clistdev, get_color_mapping_procs, pdev->saved_target_get_color_mapping_procs);
10791
2.65k
                set_dev_proc(clistdev, get_color_comp_index, pdev->saved_target_get_color_comp_index);
10792
2.65k
                pgs->get_cmap_procs = pdev->save_get_cmap_procs;
10793
2.65k
                gx_set_cmap_procs(pgs, clistdev);
10794
2.65k
                gx_device_decache_colors(clistdev);
10795
                /* Disable the PDF 1.4 compositor */
10796
2.65k
                pdf14_disable_clist_device(mem, pgs, dev);
10797
                /*
10798
                 * Make sure that the transfer funtions, etc. are current.
10799
                 */
10800
2.65k
                code = cmd_put_color_mapping((gx_device_clist_writer *)clistdev, pgs);
10801
2.65k
                if (code < 0)
10802
8
                    return code;
10803
2.64k
                break;
10804
2.65k
            }
10805
2.64k
            case PDF14_BEGIN_TRANS_PAGE_GROUP:
10806
12.5k
            case PDF14_BEGIN_TRANS_GROUP:
10807
12.5k
                if (pdev->smask_constructed || pdev->depth_within_smask)
10808
7.10k
                    pdev->depth_within_smask++;
10809
12.5k
                pdev->smask_constructed = 0;
10810
                /*
10811
                 * Keep track of any changes made in the blending parameters.
10812
                   These need to be written out in the same bands as the group
10813
                   information is written.  Hence the passing of the dimensions
10814
                   for the group. */
10815
12.5k
                code = pdf14_clist_update_params(pdev, pgs, true,
10816
12.5k
                                                 (gs_pdf14trans_params_t *)&(pdf14pct->params));
10817
12.5k
                if (code < 0)
10818
0
                    return code;
10819
12.5k
                if (pdf14pct->params.Background_components != 0 &&
10820
12.5k
                    pdf14pct->params.Background_components !=
10821
0
                    pdev->color_info.num_components)
10822
0
                    return_error(gs_error_rangecheck);
10823
10824
                /* We need to update the clist writer device procs based upon the
10825
                   the group color space. This ensures the proper color data is
10826
                   written out to the device. For simplicity, the list item is
10827
                   created even if the color space did not change */
10828
12.5k
                code = pdf14_clist_push_color_model(dev, cdev, pgs, pdf14pct, mem, false);
10829
12.5k
                if (code < 0)
10830
1
                    return code;
10831
10832
12.5k
                break;
10833
14.6k
            case PDF14_BEGIN_TRANS_MASK:
10834
                /* We need to update the clist writer device procs based upon the
10835
                   the group color space.  For simplicity, the list item is created
10836
                   even if the color space did not change */
10837
                /* First store the current ones */
10838
14.6k
                if (pdf14pct->params.subtype == TRANSPARENCY_MASK_None)
10839
7.49k
                    break;
10840
10841
                /* Update the color settings of the clist writer.  Store information in stack */
10842
7.15k
                code = pdf14_clist_push_color_model(dev, cdev, pgs, pdf14pct, mem, true);
10843
7.15k
                if (code < 0)
10844
0
                    return code;
10845
10846
                /* Also, if the BC is a value that may end up as something other
10847
                  than transparent. We must use the parent colors bounding box in
10848
                  determining the range of bands in which this mask can affect.
10849
                  So, if needed change the masks bounding box at this time */
10850
7.15k
                pdev->in_smask_construction++;
10851
7.15k
                break;
10852
174k
            case PDF14_BEGIN_TRANS_TEXT_GROUP:
10853
174k
                if (pdev->text_group == PDF14_TEXTGROUP_BT_PUSHED) {
10854
74
                    emprintf(pdev->memory, "Warning: Text group pushed but no ET found\n");
10855
74
                    pdev->text_group = PDF14_TEXTGROUP_MISSING_ET;
10856
74
                } else
10857
174k
                    pdev->text_group = PDF14_TEXTGROUP_BT_NOT_PUSHED;
10858
174k
                *pcdev = dev;
10859
174k
                return 0; /* Never put into clist. Only used during writing */
10860
206k
            case PDF14_END_TRANS_TEXT_GROUP:
10861
206k
                if (pdev->text_group != PDF14_TEXTGROUP_BT_PUSHED) {
10862
205k
                    *pcdev = dev;
10863
205k
                    return 0; /* Avoids spurious ET calls in interpreter */
10864
205k
                }
10865
502
                pdev->text_group = PDF14_TEXTGROUP_NO_BT; /* These can't be nested */
10866
502
                code = pdf14_clist_pop_color_model(dev, pgs);
10867
502
                if (code < 0)
10868
0
                    return code;
10869
502
                break;
10870
7.15k
            case PDF14_END_TRANS_MASK:
10871
7.15k
                pdev->in_smask_construction--;
10872
7.15k
                if (pdev->in_smask_construction < 0)
10873
0
                    pdev->in_smask_construction = 0;
10874
7.15k
                if (pdev->in_smask_construction == 0)
10875
7.14k
                    pdev->smask_constructed = 1;
10876
                /* fallthrough */
10877
19.1k
            case PDF14_END_TRANS_GROUP:
10878
                /* We need to update the clist writer device procs based upon the
10879
                   the group color space. */
10880
19.1k
                code = pdf14_clist_pop_color_model(dev, pgs);
10881
19.1k
                if (pdev->depth_within_smask)
10882
7.10k
                    pdev->depth_within_smask--;
10883
19.1k
                if (code < 0)
10884
0
                    return code;
10885
19.1k
                break;
10886
19.1k
            case PDF14_PUSH_TRANS_STATE:
10887
0
                break;
10888
6.95k
            case PDF14_POP_TRANS_STATE:
10889
6.95k
                break;
10890
7.15k
            case PDF14_PUSH_SMASK_COLOR:
10891
7.15k
                code = pdf14_increment_smask_color(pgs,dev);
10892
7.15k
                *pcdev = dev;
10893
7.15k
                return code;  /* Note, this are NOT put in the clist */
10894
0
                break;
10895
7.15k
            case PDF14_POP_SMASK_COLOR:
10896
7.15k
                code = pdf14_decrement_smask_color(pgs,dev);
10897
7.15k
                *pcdev = dev;
10898
7.15k
                return code;  /* Note, this are NOT put in the clist */
10899
0
                break;
10900
0
            case PDF14_SET_BLEND_PARAMS:
10901
                /* If there is a change we go ahead and apply it to the target */
10902
0
                code = pdf14_clist_update_params(pdev, pgs, false,
10903
0
                                                 (gs_pdf14trans_params_t *)&(pdf14pct->params));
10904
0
                *pcdev = dev;
10905
0
                return code;
10906
0
                break;
10907
0
            case PDF14_ABORT_DEVICE:
10908
0
                code = gx_abort_trans_device(pgs, dev);
10909
0
                if (pdev->free_devicen) {
10910
0
                    devn_free_params(dev);
10911
0
                }
10912
0
                pdf14_disable_device(dev);
10913
0
                pdf14_close(dev);
10914
0
                *pcdev = dev;
10915
0
                return code;
10916
0
                break;
10917
0
            default:
10918
0
                break;   /* Pass remaining ops to target */
10919
451k
        }
10920
451k
    }
10921
184k
    code = dev_proc(pdev->target, composite)
10922
184k
                        (pdev->target, pcdev, pct, pgs, mem, cdev);
10923
    /* If we were accumulating into a pdf14-clist-accum device, */
10924
    /* we now have to render the page into it's target device */
10925
184k
    if (is_pdf14_compositor && pdf14pct->params.pdf14_op == PDF14_POP_DEVICE &&
10926
184k
        pdev->target->stype == &st_gx_devn_accum_device) {
10927
10928
918
        int i, y, rows_used;
10929
918
        byte *linebuf;
10930
918
        byte *actual_data;
10931
918
        gx_device_pdf14_accum *tdev = (gx_device_pdf14_accum *)(pdev->target);     /* the printer class clist device used to accumulate */
10932
        /* get the target device we want to send the image to */
10933
918
        gx_device *target = ((pdf14_device *)(tdev->save_p14dev))->target;
10934
918
        gs_image1_t image;
10935
918
        gs_color_space *pcs;
10936
918
        gx_image_enum_common_t *info = NULL;
10937
918
        gx_image_plane_t planes;
10938
918
        gsicc_rendering_param_t render_cond;
10939
918
        cmm_dev_profile_t *dev_profile;
10940
918
        bool save_planar = pdev->is_planar;
10941
918
        gs_devn_params *target_devn_params = dev_proc(target, ret_devn_params)(target);
10942
918
        int save_num_separations;
10943
918
        gs_int_rect rect;
10944
10945
918
        pdev->is_planar = false;   /* so gx_device_raster is for entire chunky pixel line */
10946
918
        linebuf = gs_alloc_bytes(mem, gx_device_raster((gx_device *)pdev, true), "pdf14-clist_accum pop dev");
10947
918
        pdev->is_planar = save_planar;
10948
10949
        /* As long as we don't have spot colors, we can use ICC colorspace, but spot
10950
         * colors do require devn support
10951
         */
10952
918
        if (tdev->color_info.num_components <= 4 ||
10953
918
             dev_proc(target, dev_spec_op)(target, gxdso_supports_devn, NULL, 0) <= 0) {
10954
            /*
10955
             * Set color space in preparation for sending an image.
10956
             */
10957
918
            code = gs_cspace_build_ICC(&pcs, NULL, pgs->memory);
10958
918
            if (code < 0)
10959
0
                goto put_accum_error;
10960
10961
            /* Need to set this to avoid color management during the
10962
               image color render operation.  Exception is for the special case
10963
               when the destination was CIELAB.  Then we need to convert from
10964
               default RGB to CIELAB in the put image operation.  That will happen
10965
               here as we should have set the profile for the pdf14 device to RGB
10966
               and the target will be CIELAB */
10967
918
            code = dev_proc(dev, get_profile)(dev,  &dev_profile);
10968
918
            if (code < 0)
10969
0
                goto put_accum_error;
10970
918
            gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile,
10971
918
                                  &(pcs->cmm_icc_profile_data), &render_cond);
10972
            /* pcs takes a reference to the profile data it just retrieved. */
10973
918
            gsicc_adjust_profile_rc(pcs->cmm_icc_profile_data, 1, "pdf14_clist_composite");
10974
918
            gsicc_set_icc_range(&(pcs->cmm_icc_profile_data));
10975
918
        } else {
10976
             /* DeviceN case -- need to handle spot colors */
10977
0
            code = gs_cspace_new_DeviceN(&pcs, tdev->color_info.num_components,
10978
0
                                         gs_currentcolorspace(pgs), pgs->memory);
10979
0
            if (code < 0)
10980
0
                goto put_accum_error;
10981
            /* set up a usable DeviceN space with info from the tdev->devn_params */
10982
0
            pcs->params.device_n.use_alt_cspace = false;
10983
10984
0
            if ((code = pcs->type->install_cspace(pcs, pgs)) < 0) {
10985
0
                goto put_accum_error;
10986
0
            }
10987
            /* One last thing -- we need to fudge the pgs->color_component_map */
10988
0
            for (i=0; i < tdev->color_info.num_components; i++)
10989
0
                pgs->color_component_map.color_map[i] = i; /* enable all components in normal order */
10990
            /* copy devn_params that were accumulated into the target device's devn_params */
10991
0
            target_devn_params->bitspercomponent = tdev->devn_params.bitspercomponent;
10992
0
            target_devn_params->std_colorant_names = tdev->devn_params.std_colorant_names;
10993
0
            target_devn_params->num_std_colorant_names = tdev->devn_params.num_std_colorant_names;
10994
0
            target_devn_params->max_separations = tdev->devn_params.max_separations;
10995
0
            target_devn_params->page_spot_colors = tdev->devn_params.page_spot_colors;
10996
0
            target_devn_params->num_separation_order_names = tdev->devn_params.num_separation_order_names;
10997
0
            target_devn_params->separations = tdev->devn_params.separations;
10998
0
            memcpy(target_devn_params->separation_order_map, tdev->devn_params.separation_order_map,
10999
0
                   sizeof(gs_separation_map));
11000
0
            target_devn_params->pdf14_separations = tdev->devn_params.pdf14_separations;
11001
0
        }
11002
918
        if (linebuf == NULL) {
11003
0
            code = gs_error_VMerror;
11004
0
            goto put_accum_error;
11005
0
        }
11006
918
        gs_image_t_init_adjust(&image, pcs, false);
11007
918
        image.ImageMatrix.xx = (float)pdev->width;
11008
918
        image.ImageMatrix.yy = (float)pdev->height;
11009
918
        image.Width = pdev->width;
11010
918
        image.Height = pdev->height;
11011
918
        image.BitsPerComponent = 8<<deep;
11012
918
        ctm_only_writable(pgs).xx = (float)pdev->width;
11013
918
        ctm_only_writable(pgs).xy = 0;
11014
918
        ctm_only_writable(pgs).yx = 0;
11015
918
        ctm_only_writable(pgs).yy = (float)pdev->height;
11016
918
        ctm_only_writable(pgs).tx = 0.0;
11017
918
        ctm_only_writable(pgs).ty = 0.0;
11018
918
        code = dev_proc(target, begin_typed_image) (target,
11019
918
                                                    pgs, NULL,
11020
918
                                                    (gs_image_common_t *)&image,
11021
918
                                                    NULL, NULL, NULL,
11022
918
                                                    pgs->memory, &info);
11023
918
        if (code < 0)
11024
0
            goto put_accum_error;
11025
918
        rect.p.x = 0;
11026
918
        rect.q.x = tdev->width;
11027
1.98M
        for (y=0; y < tdev->height; y++) {
11028
1.98M
            gs_get_bits_params_t params;
11029
11030
1.98M
            params.options = (GB_ALIGN_ANY |
11031
1.98M
                              (GB_RETURN_COPY | GB_RETURN_POINTER) |
11032
1.98M
                              GB_OFFSET_0 |
11033
1.98M
                              GB_RASTER_STANDARD | GB_PACKING_CHUNKY |
11034
1.98M
                              GB_COLORS_NATIVE | GB_ALPHA_NONE);
11035
1.98M
            params.x_offset = 0;
11036
1.98M
            params.raster = bitmap_raster(dev->width * dev->color_info.depth);
11037
1.98M
            params.data[0] = linebuf;
11038
1.98M
            rect.p.y = y;
11039
1.98M
            rect.q.y = y+1;
11040
1.98M
            code = dev_proc(tdev, get_bits_rectangle)((gx_device *)tdev,
11041
1.98M
                                                      &rect, &params);
11042
1.98M
            if (code < 0)
11043
2
                goto put_accum_error;
11044
1.98M
            actual_data = params.data[0];
11045
1.98M
            planes.data = actual_data;
11046
1.98M
            planes.data_x = 0;
11047
1.98M
            planes.raster = tdev->width * tdev->color_info.num_components;
11048
1.98M
            if ((code = info->procs->plane_data(info, &planes, 1, &rows_used)) < 0)
11049
0
                goto put_accum_error;
11050
1.98M
        }
11051
11052
918
put_accum_error:
11053
918
        if (info != NULL) {
11054
918
            if (code < 0)
11055
2
                (void)info->procs->end_image(info, true);
11056
916
            else
11057
916
                code = info->procs->end_image(info, true);
11058
918
        }
11059
11060
918
        gs_free_object(pdev->memory, linebuf, "pdf14_put_image");
11061
        /* This will also decrement the device profile */
11062
918
        rc_decrement_only_cs(pcs, "pdf14_put_image");
11063
918
        dev_proc(tdev, close_device)((gx_device *)tdev);  /* frees the prn_device memory */
11064
        /* Now unhook the clist device and hook to the original so we can clean up */
11065
918
        gx_device_set_target((gx_device_forward *)pdev,
11066
918
                             ((gx_device_pdf14_accum *)(pdev->target))->save_p14dev);
11067
918
        pdev->pclist_device = pdev->target;
11068
918
        *pcdev = pdev->target;          /* pass upwards to switch devices */
11069
918
        pdev->color_info = target->color_info;      /* same as in pdf14_disable_clist */
11070
918
        if (target_devn_params != NULL) {
11071
            /* prevent devn_free_params from freeing names still in use by target device */
11072
0
            save_num_separations = tdev->devn_params.separations.num_separations;
11073
0
            tdev->devn_params.separations.num_separations = 0;
11074
0
        }
11075
918
        gs_free_object(tdev->memory, tdev, "popdevice pdf14-accum");
11076
918
        if (target_devn_params != NULL) {
11077
0
            target_devn_params->separations.num_separations = save_num_separations;
11078
0
        }
11079
918
        return code;    /* DON'T perform set_target */
11080
918
    }
11081
183k
    if (code == 1) {
11082
        /* We just wrapped pdev->target, so we need to update that.*/
11083
0
        gx_device_set_target((gx_device_forward *)pdev, *pcdev);
11084
0
        code = 0; /* We did not wrap dev. */
11085
0
    }
11086
183k
    *pcdev = dev;
11087
183k
    return code;
11088
184k
}
11089
11090
/*
11091
 * The PDF 1.4 clist compositor is never removed.  (We do not have a 'remove
11092
 * compositor' method.  However the compositor is disabled when we are not
11093
 * doing a page which uses PDF 1.4 transparency.  This routine is only active
11094
 * when the PDF 1.4 compositor is 'disabled'.  It checks for reenabling the
11095
 * PDF 1.4 compositor.  Otherwise it simply passes create compositor requests
11096
 * to the targer.
11097
 */
11098
static  int
11099
pdf14_clist_forward_composite(gx_device * dev, gx_device * * pcdev,
11100
        const gs_composite_t * pct, gs_gstate * pgs,
11101
        gs_memory_t * mem, gx_device *cdev)
11102
0
{
11103
0
    pdf14_device *pdev = (pdf14_device *)dev;
11104
0
    gx_device * tdev = pdev->target;
11105
0
    gx_device * ndev;
11106
0
    int code;
11107
11108
0
    *pcdev = dev;
11109
0
    if (gs_is_pdf14trans_compositor(pct)) {
11110
0
        const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pct;
11111
11112
0
        if (pdf14pct->params.pdf14_op == PDF14_PUSH_DEVICE)
11113
0
            return pdf14_clist_composite(dev, &ndev, pct, pgs, mem, cdev);
11114
0
        return 0;
11115
0
    }
11116
0
    code = dev_proc(tdev, composite)(tdev, &ndev, pct, pgs, mem, cdev);
11117
0
    if (code == 1) {
11118
        /* We just wrapped tdev, so update our target. */
11119
0
        gx_device_set_target((gx_device_forward *)pdev, ndev);
11120
0
        code = 0; /* We did not wrap dev. */
11121
0
    }
11122
0
    return code;
11123
0
}
11124
11125
/*
11126
 * If any of the PDF 1.4 transparency blending parameters have changed, we
11127
 * need to send them to the PDF 1.4 compositor on the output side of the clist.
11128
 */
11129
static  int
11130
pdf14_clist_update_params(pdf14_clist_device * pdev, const gs_gstate * pgs,
11131
                          bool crop_blend_params,
11132
                          gs_pdf14trans_params_t *group_params)
11133
2.14M
{
11134
2.14M
    gs_pdf14trans_params_t params = { 0 };
11135
2.14M
    gx_device * pcdev;
11136
2.14M
    int changed = 0;
11137
2.14M
    int code = 0;
11138
2.14M
    gs_composite_t *pct_new = NULL;
11139
11140
2.14M
    params.crop_blend_params = crop_blend_params;
11141
11142
2.14M
    params.pdf14_op = PDF14_SET_BLEND_PARAMS;
11143
2.14M
    if (pgs->blend_mode != pdev->blend_mode) {
11144
5.03k
        changed |= PDF14_SET_BLEND_MODE;
11145
5.03k
        params.blend_mode = pdev->blend_mode = pgs->blend_mode;
11146
5.03k
    }
11147
2.14M
    if (pgs->text_knockout != pdev->text_knockout) {
11148
2.54k
        changed |= PDF14_SET_TEXT_KNOCKOUT;
11149
2.54k
        params.text_knockout = pdev->text_knockout = pgs->text_knockout;
11150
2.54k
    }
11151
2.14M
    if (pgs->alphaisshape != pdev->ais) {
11152
509
        changed |= PDF14_SET_AIS;
11153
509
        params.ais = pdev->ais = pgs->alphaisshape;
11154
509
    }
11155
2.14M
    if (pgs->overprint != pdev->overprint) {
11156
3.04k
        changed |= PDF14_SET_OVERPRINT;
11157
3.04k
        params.overprint = pdev->overprint = pgs->overprint;
11158
3.04k
    }
11159
2.14M
    if (pgs->stroke_overprint != pdev->stroke_overprint) {
11160
3.02k
        changed |= PDF14_SET_STROKEOVERPRINT;
11161
3.02k
        params.stroke_overprint = pdev->stroke_overprint = pgs->stroke_overprint;
11162
3.02k
    }
11163
2.14M
    if (pgs->fillconstantalpha != pdev->fillconstantalpha) {
11164
7.05k
        changed |= PDF14_SET_FILLCONSTANTALPHA;
11165
7.05k
        params.fillconstantalpha = pdev->fillconstantalpha = pgs->fillconstantalpha;
11166
7.05k
    }
11167
2.14M
    if (pgs->strokeconstantalpha != pdev->strokeconstantalpha) {
11168
5.97k
        changed |= PDF14_SET_STROKECONSTANTALPHA;
11169
5.97k
        params.strokeconstantalpha = pdev->strokeconstantalpha = pgs->strokeconstantalpha;
11170
5.97k
    }
11171
2.14M
    if ((pgs->is_fill_color && pdev->op_state != PDF14_OP_STATE_FILL)) {
11172
20.3k
        changed |= PDF14_SET_FILLSTROKE_STATE;
11173
20.3k
        params.op_fs_state = pdev->op_state = PDF14_OP_STATE_FILL;
11174
20.3k
        if_debug0m('v', pgs->memory,
11175
20.3k
            "[v]c_pdf14_clist_update_params op_fs_state written in clist as PDF14_OP_STATE_FILL \n");
11176
20.3k
    }
11177
2.14M
    if ((!pgs->is_fill_color && pdev->op_state != PDF14_OP_STATE_STROKE)) {
11178
20.7k
        changed |= PDF14_SET_FILLSTROKE_STATE;
11179
20.7k
        params.op_fs_state = pdev->op_state = PDF14_OP_STATE_STROKE;
11180
20.7k
        if_debug0m('v', pgs->memory,
11181
20.7k
            "[v]c_pdf14_clist_update_params op_fs_state written in clist as PDF14_OP_STATE_STROKE \n");
11182
20.7k
    }
11183
2.14M
    if (crop_blend_params) {
11184
12.5k
        params.ctm = group_params->ctm;
11185
12.5k
        params.bbox = group_params->bbox;
11186
12.5k
    }
11187
2.14M
    params.changed = changed;
11188
    /* Avoid recursion when we have a PDF14_SET_BLEND_PARAMS forced and apply
11189
       now to the target.  Otherwise we send the compositor action
11190
       to the pdf14 device at this time.  This is due to the fact that we
11191
       need to often perform this operation when we are already starting to
11192
       do a compositor action */
11193
2.14M
    if (changed != 0) {
11194
55.5k
        code = gs_create_pdf14trans(&pct_new, &params, pgs->memory);
11195
55.5k
        if (code < 0)
11196
0
            return code;
11197
55.5k
        code = dev_proc(pdev->target, composite)
11198
55.5k
                    (pdev->target, &pcdev, pct_new, (gs_gstate *)pgs, pgs->memory, NULL);
11199
55.5k
        gs_free_object(pgs->memory, pct_new, "pdf14_clist_update_params");
11200
55.5k
    }
11201
2.14M
    return code;
11202
2.14M
}
11203
11204
/*
11205
 * fill_path routine for the PDF 1.4 transaprency compositor device for
11206
 * writing the clist.
11207
 */
11208
static  int
11209
pdf14_clist_fill_path(gx_device *dev, const gs_gstate *pgs,
11210
                           gx_path *ppath, const gx_fill_params *params,
11211
                           const gx_drawing_color *pdcolor,
11212
                           const gx_clip_path *pcpath)
11213
877k
{
11214
877k
    pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
11215
877k
    gs_gstate new_pgs = *pgs;
11216
877k
    int code;
11217
877k
    gs_pattern2_instance_t *pinst = NULL;
11218
877k
    gx_device_forward * fdev = (gx_device_forward *)dev;
11219
877k
    cmm_dev_profile_t *dev_profile, *fwd_profile;
11220
877k
    gsicc_rendering_param_t render_cond;
11221
877k
    cmm_profile_t *icc_profile_fwd, *icc_profile_dev;
11222
877k
    int push_group = 0;
11223
11224
877k
    code = dev_proc(dev, get_profile)(dev,  &dev_profile);
11225
877k
    if (code < 0)
11226
0
        return code;
11227
877k
    code = dev_proc(fdev->target, get_profile)(fdev->target,  &fwd_profile);
11228
877k
    if (code < 0)
11229
0
        return code;
11230
11231
877k
    if (dev->color_info.separable_and_linear == GX_CINFO_UNKNOWN_SEP_LIN)
11232
24
        check_device_separable(dev);
11233
11234
877k
    gsicc_extract_profile(GS_UNKNOWN_TAG, fwd_profile, &icc_profile_fwd,
11235
877k
                          &render_cond);
11236
877k
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &icc_profile_dev,
11237
877k
                          &render_cond);
11238
11239
    /*
11240
     * Ensure that that the PDF 1.4 reading compositor will have the current
11241
     * blending parameters.  This is needed since the fill_rectangle routines
11242
     * do not have access to the gs_gstate.  Thus we have to pass any
11243
     * changes explictly.
11244
     */
11245
877k
    code = pdf14_clist_update_params(pdev, pgs, false, NULL);
11246
877k
    if (code < 0)
11247
0
        return code;
11248
    /* If we are doing a shading fill and we are in a transparency group of a
11249
       different color space, then we do not want to do the shading in the
11250
       device color space. It must occur in the source space.  To handle it in
11251
       the device space would require knowing all the nested transparency group
11252
       color space as well as the transparency.  Some of the shading code ignores
11253
       this, so we have to pass on the clist_writer device to enable proper
11254
       mapping to the transparency group color space. */
11255
11256
877k
    if (gx_dc_is_pattern2_color(pdcolor)) {
11257
        /* Non-idempotent blends require a transparency
11258
         * group to be pushed because shadings might
11259
         * paint several pixels twice. */
11260
11.0k
        push_group = pgs->fillconstantalpha != 1.0 ||
11261
11.0k
               !blend_is_idempotent(gs_currentblendmode(pgs));
11262
11.0k
        pinst =
11263
11.0k
            (gs_pattern2_instance_t *)pdcolor->ccolor.pattern;
11264
11.0k
           pinst->saved->has_transparency = true;
11265
           /* The transparency color space operations are driven by the pdf14
11266
              clist writer device.  */
11267
11.0k
           pinst->saved->trans_device = dev;
11268
11.0k
    }
11269
877k
    if (push_group) {
11270
101
        gs_fixed_rect box;
11271
101
        gs_fixed_rect dev_bbox;
11272
11273
101
        if (pcpath) {
11274
101
            gx_cpath_outer_box(pcpath, &box);
11275
101
            (*dev_proc(dev, get_clipping_box)) (dev, &dev_bbox);
11276
101
            rect_intersect(box, dev_bbox);
11277
101
        } else
11278
0
            (*dev_proc(dev, get_clipping_box)) (dev, &box);
11279
11280
101
        if (ppath) {
11281
0
            gs_fixed_rect path_box;
11282
11283
0
            gx_path_bbox(ppath, &path_box);
11284
0
            if (box.p.x < path_box.p.x)
11285
0
                box.p.x = path_box.p.x;
11286
0
            if (box.p.y < path_box.p.y)
11287
0
                box.p.y = path_box.p.y;
11288
0
            if (box.q.x > path_box.q.x)
11289
0
                box.q.x = path_box.q.x;
11290
0
            if (box.q.y > path_box.q.y)
11291
0
                box.q.y = path_box.q.y;
11292
0
        }
11293
11294
101
        if (box.p.y >= box.q.y || box.p.x >= box.q.x) {
11295
            /* No need to do anything */
11296
93
            if (pinst != NULL) {
11297
93
                pinst->saved->trans_device = NULL;
11298
93
            }
11299
93
            return 0;
11300
93
        }
11301
11302
        /* Group alpha set from fill value. push_shfill_group does reset to 1.0 */
11303
8
        code = push_shfill_group(pdev, &new_pgs, &box);
11304
8
    } else
11305
877k
        update_lop_for_pdf14(&new_pgs, pdcolor);
11306
877k
    if (code >= 0) {
11307
877k
        new_pgs.trans_device = dev;
11308
877k
        new_pgs.has_transparency = true;
11309
877k
        if (gx_dc_is_pattern2_color(pdcolor))
11310
10.9k
            code = gx_default_fill_path_shading_or_pattern(dev, &new_pgs, ppath, params, pdcolor, pcpath);
11311
866k
        else
11312
866k
            code = gx_forward_fill_path(dev, &new_pgs, ppath, params, pdcolor, pcpath);
11313
877k
        new_pgs.trans_device = NULL;
11314
877k
        new_pgs.has_transparency = false;
11315
877k
    }
11316
877k
    if (code >= 0 && push_group) {
11317
8
        code = pop_shfill_group(&new_pgs);
11318
8
        if (code >= 0)
11319
8
            code = pdf14_clist_update_params(pdev, pgs, false, NULL);
11320
8
    }
11321
877k
    if (pinst != NULL){
11322
10.9k
        pinst->saved->trans_device = NULL;
11323
10.9k
    }
11324
877k
    return code;
11325
877k
}
11326
11327
/*
11328
 * stroke_path routine for the PDF 1.4 transparency compositor device for
11329
 * writing the clist.
11330
 */
11331
static  int
11332
pdf14_clist_stroke_path(gx_device *dev, const gs_gstate *pgs,
11333
                             gx_path *ppath, const gx_stroke_params *params,
11334
                             const gx_drawing_color *pdcolor,
11335
                             const gx_clip_path *pcpath)
11336
147k
{
11337
147k
    pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
11338
147k
    gs_gstate new_pgs = *pgs;
11339
147k
    int code = 0;
11340
147k
    gs_pattern2_instance_t *pinst = NULL;
11341
147k
    int push_group = 0;
11342
11343
    /*
11344
     * Ensure that that the PDF 1.4 reading compositor will have the current
11345
     * blending parameters.  This is needed since the fill_rectangle routines
11346
     * do not have access to the gs_gstate.  Thus we have to pass any
11347
     * changes explictly.
11348
     */
11349
147k
    code = pdf14_clist_update_params(pdev, pgs, false, NULL);
11350
147k
    if (code < 0)
11351
4
        return code;
11352
    /* If we are doing a shading stroke and we are in a transparency group of a
11353
       different color space, then we need to get the proper device information
11354
       passed along so that we use the correct color procs and colorinfo about
11355
       the transparency device and not the final target device */
11356
147k
    if (gx_dc_is_pattern2_color(pdcolor)) {
11357
        /* Non-idempotent blends require a transparency
11358
         * group to be pushed because shadings might
11359
         * paint several pixels twice. */
11360
28
        push_group = pgs->strokeconstantalpha != 1.0 ||
11361
28
               !blend_is_idempotent(gs_currentblendmode(pgs));
11362
28
        if (pdev->color_model_stack != NULL) {
11363
28
            pinst =
11364
28
                (gs_pattern2_instance_t *)pdcolor->ccolor.pattern;
11365
28
            pinst->saved->has_transparency = true;
11366
            /* The transparency color space operations are driven
11367
              by the pdf14 clist writer device.  */
11368
28
            pinst->saved->trans_device = dev;
11369
28
        }
11370
28
    }
11371
147k
    if (push_group) {
11372
0
        gs_fixed_rect box;
11373
0
        if (pcpath)
11374
0
            gx_cpath_outer_box(pcpath, &box);
11375
0
        else
11376
0
            (*dev_proc(dev, get_clipping_box)) (dev, &box);
11377
0
        if (ppath) {
11378
0
            gs_fixed_rect path_box;
11379
0
            gs_fixed_point expansion;
11380
11381
0
            gx_path_bbox(ppath, &path_box);
11382
            /* Expand the path bounding box by the scaled line width. */
11383
0
            if (gx_stroke_path_expansion(pgs, ppath, &expansion) < 0) {
11384
                /* The expansion is so large it caused a limitcheck. */
11385
0
                path_box.p.x = path_box.p.y = min_fixed;
11386
0
                path_box.q.x = path_box.q.y = max_fixed;
11387
0
            } else {
11388
0
                expansion.x += pgs->fill_adjust.x;
11389
0
                expansion.y += pgs->fill_adjust.y;
11390
                /*
11391
                 * It's theoretically possible for the following computations to
11392
                 * overflow, so we need to check for this.
11393
                 */
11394
0
                path_box.p.x = (path_box.p.x < min_fixed + expansion.x ? min_fixed :
11395
0
                                path_box.p.x - expansion.x);
11396
0
                path_box.p.y = (path_box.p.y < min_fixed + expansion.y ? min_fixed :
11397
0
                                path_box.p.y - expansion.y);
11398
0
                path_box.q.x = (path_box.q.x > max_fixed - expansion.x ? max_fixed :
11399
0
                                path_box.q.x + expansion.x);
11400
0
                path_box.q.y = (path_box.q.y > max_fixed - expansion.y ? max_fixed :
11401
0
                                path_box.q.y + expansion.y);
11402
0
            }
11403
0
            if (box.p.x < path_box.p.x)
11404
0
                box.p.x = path_box.p.x;
11405
0
            if (box.p.y < path_box.p.y)
11406
0
                box.p.y = path_box.p.y;
11407
0
            if (box.q.x > path_box.q.x)
11408
0
                box.q.x = path_box.q.x;
11409
0
            if (box.q.y > path_box.q.y)
11410
0
                box.q.y = path_box.q.y;
11411
0
        }
11412
        /* Group alpha set from fill value. push_shfill_group does reset to 1.0 */
11413
0
        new_pgs.fillconstantalpha = new_pgs.strokeconstantalpha;
11414
0
        code = push_shfill_group(pdev, &new_pgs, &box);
11415
0
    } else
11416
147k
        update_lop_for_pdf14(&new_pgs, pdcolor);
11417
11418
147k
    if (code >= 0) {
11419
147k
        new_pgs.trans_device = dev;
11420
147k
        new_pgs.has_transparency = true;
11421
147k
        if (gx_dc_is_pattern2_color(pdcolor))
11422
28
            code = gx_default_stroke_path_shading_or_pattern(dev, &new_pgs, ppath, params, pdcolor, pcpath);
11423
147k
        else
11424
147k
            code = gx_forward_stroke_path(dev, &new_pgs, ppath, params, pdcolor, pcpath);
11425
147k
        new_pgs.trans_device = NULL;
11426
147k
        new_pgs.has_transparency = false;
11427
147k
    }
11428
147k
    if (code >= 0 && push_group) {
11429
0
        code = pop_shfill_group(&new_pgs);
11430
0
        if (code >= 0)
11431
0
            code = pdf14_clist_update_params(pdev, pgs, false, NULL);
11432
0
    }
11433
147k
    if (pinst != NULL)
11434
28
        pinst->saved->trans_device = NULL;
11435
147k
    return code;
11436
147k
}
11437
11438
/* Set up work for doing shading patterns in fill stroke through
11439
   the clist.  We have to do all the dirty work now since we are
11440
   going through the default fill and stroke operations individually */
11441
static int
11442
pdf14_clist_fill_stroke_path_pattern_setup(gx_device* dev, const gs_gstate* cpgs, gx_path* ppath,
11443
    const gx_fill_params* params_fill, const gx_drawing_color* pdevc_fill,
11444
    const gx_stroke_params* params_stroke, const gx_drawing_color* pdevc_stroke,
11445
    const gx_clip_path* pcpath)
11446
0
{
11447
0
    union {
11448
0
        const gs_gstate *cpgs;
11449
0
        gs_gstate *pgs;
11450
0
    } const_breaker;
11451
0
    gs_gstate *pgs;
11452
0
    int code, code2;
11453
0
    gs_transparency_group_params_t params = { 0 };
11454
0
    gs_fixed_rect clip_bbox;
11455
0
    gs_rect bbox, group_stroke_box;
11456
0
    float fill_alpha;
11457
0
    float stroke_alpha;
11458
0
    gs_blend_mode_t blend_mode;
11459
0
    gs_fixed_rect path_bbox;
11460
0
    int expansion_code;
11461
0
    gs_fixed_point expansion;
11462
11463
    /* Break const just once, neatly */
11464
0
    const_breaker.cpgs = cpgs;
11465
0
    pgs = const_breaker.pgs;
11466
11467
0
    fill_alpha = pgs->fillconstantalpha;
11468
0
    stroke_alpha = pgs->strokeconstantalpha;
11469
0
    blend_mode = pgs->blend_mode;
11470
11471
0
    code = gx_curr_fixed_bbox(pgs, &clip_bbox, NO_PATH);
11472
0
    if (code < 0 && code != gs_error_unknownerror)
11473
0
        return code;
11474
0
    if (code == gs_error_unknownerror) {
11475
        /* didn't get clip box from gx_curr_fixed_bbox */
11476
0
        clip_bbox.p.x = clip_bbox.p.y = 0;
11477
0
        clip_bbox.q.x = int2fixed(dev->width);
11478
0
        clip_bbox.q.y = int2fixed(dev->height);
11479
0
    }
11480
0
    if (pcpath)
11481
0
        rect_intersect(clip_bbox, pcpath->outer_box);
11482
11483
    /* expand the ppath using stroke expansion rule, then intersect it */
11484
0
    code = gx_path_bbox(ppath, &path_bbox);
11485
0
    if (code == gs_error_nocurrentpoint && ppath->segments->contents.subpath_first == 0)
11486
0
        return 0;   /* ignore empty path */
11487
0
    if (code < 0)
11488
0
        return code;
11489
0
    expansion_code = gx_stroke_path_expansion(pgs, ppath, &expansion);
11490
0
    if (expansion_code >= 0) {
11491
0
        path_bbox.p.x -= expansion.x;
11492
0
        path_bbox.p.y -= expansion.y;
11493
0
        path_bbox.q.x += expansion.x;
11494
0
        path_bbox.q.y += expansion.y;
11495
0
    }
11496
0
    rect_intersect(path_bbox, clip_bbox);
11497
0
    bbox.p.x = fixed2float(path_bbox.p.x);
11498
0
    bbox.p.y = fixed2float(path_bbox.p.y);
11499
0
    bbox.q.x = fixed2float(path_bbox.q.x);
11500
0
    bbox.q.y = fixed2float(path_bbox.q.y);
11501
11502
0
    code = gs_bbox_transform_inverse(&bbox, &ctm_only(pgs), &group_stroke_box);
11503
0
    if (code < 0)
11504
0
        return code;
11505
11506
    /* See if overprint is enabled for both stroke and fill AND if ca == CA */
11507
0
    if (pgs->fillconstantalpha == pgs->strokeconstantalpha &&
11508
0
        pgs->overprint && pgs->stroke_overprint &&
11509
0
        (dev->icc_struct->overprint_control != gs_overprint_control_disable) &&
11510
0
        dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE) {
11511
11512
0
        params.Isolated = false;
11513
0
        params.group_color_type = UNKNOWN;
11514
0
        params.Knockout = false;
11515
0
        params.page_group = false;
11516
0
        params.group_opacity = fill_alpha;
11517
0
        params.group_shape = 1.0;
11518
11519
        /* non-isolated non-knockout group pushed with original alpha and blend mode */
11520
0
        code = gs_begin_transparency_group(pgs, &params, &group_stroke_box, PDF14_BEGIN_TRANS_GROUP);
11521
0
        if (code < 0)
11522
0
            return code;
11523
11524
        /* Set alpha to 1.0 and compatible overprint mode for actual drawings */
11525
0
        (void)gs_setfillconstantalpha(pgs, 1.0);
11526
0
        (void)gs_setstrokeconstantalpha(pgs, 1.0);
11527
0
        (void)gs_setblendmode(pgs, BLEND_MODE_CompatibleOverprint); /* Can never fail */
11528
11529
0
        code = pdf14_clist_fill_path(dev, pgs, ppath, params_fill, pdevc_fill, pcpath);
11530
0
        if (code < 0)
11531
0
            goto cleanup;
11532
11533
0
        code = pdf14_clist_stroke_path(dev, pgs, ppath, params_stroke, pdevc_stroke, pcpath);
11534
0
        if (code < 0)
11535
0
            goto cleanup;
11536
11537
0
    } else {
11538
        /* Push a non-isolated knockout group. Do not change the alpha or
11539
           blend modes */
11540
0
        params.Isolated = false;
11541
0
        params.group_color_type = UNKNOWN;
11542
0
        params.Knockout = true;
11543
0
        params.page_group = false;
11544
0
        params.group_opacity = 1.0;
11545
0
        params.group_shape = 1.0;
11546
11547
        /* non-isolated knockout group is pushed with alpha = 1.0 and Normal blend mode */
11548
0
        (void)gs_setfillconstantalpha(pgs, 1.0);
11549
0
        (void)gs_setblendmode(pgs, BLEND_MODE_Normal); /* Can never fail */
11550
0
        code = gs_begin_transparency_group(pgs, &params, &group_stroke_box, PDF14_BEGIN_TRANS_GROUP);
11551
11552
        /* restore blend mode for actual drawing in the group */
11553
0
        (void)gs_setblendmode(pgs, blend_mode); /* Can never fail */
11554
11555
0
        if (fill_alpha > 0.0) {
11556
0
            (void)gs_setfillconstantalpha(pgs, fill_alpha);
11557
11558
            /* If we are in an overprint situation, set the blend mode to compatible
11559
               overprint */
11560
0
            if ((dev->icc_struct->overprint_control != gs_overprint_control_disable) &&
11561
0
                pgs->overprint &&
11562
0
                dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE)
11563
0
                (void)gs_setblendmode(pgs, BLEND_MODE_CompatibleOverprint); /* Can never fail */
11564
11565
0
            code = pdf14_clist_fill_path(dev, pgs, ppath, params_fill, pdevc_fill, pcpath);
11566
0
            if (code < 0)
11567
0
                goto cleanup;
11568
11569
0
            if ((dev->icc_struct->overprint_control != gs_overprint_control_disable) &&
11570
0
                pgs->overprint &&
11571
0
                dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE)
11572
0
                (void)gs_setblendmode(pgs, blend_mode); /* Can never fail */
11573
0
        }
11574
11575
0
        if (stroke_alpha > 0.0) {
11576
            /* Note that the stroke can end up looking like a fill here */
11577
0
            (void)gs_setstrokeconstantalpha(pgs, stroke_alpha);
11578
0
            (void)gs_setfillconstantalpha(pgs, stroke_alpha);
11579
11580
0
            if (pgs->overprint && dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE)
11581
0
                (void)gs_setblendmode(pgs, BLEND_MODE_CompatibleOverprint); /* Can never fail */
11582
11583
0
            code = pdf14_clist_stroke_path(dev, pgs, ppath, params_stroke, pdevc_stroke, pcpath);
11584
0
            if (code < 0)
11585
0
                goto cleanup;
11586
11587
0
            if ((dev->icc_struct->overprint_control != gs_overprint_control_disable) &&
11588
0
                pgs->overprint &&
11589
0
                dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE)
11590
0
                (void)gs_setblendmode(pgs, blend_mode); /* Can never fail */
11591
0
        }
11592
0
    }
11593
11594
0
cleanup:
11595
    /* Now during the pop do the compositing with alpha of 1.0 and normal blend */
11596
0
    (void)gs_setfillconstantalpha(pgs, 1.0);
11597
0
    (void)gs_setstrokeconstantalpha(pgs, 1.0);
11598
0
    (void)gs_setblendmode(pgs, BLEND_MODE_Normal); /* Can never fail */
11599
11600
    /* Restore where we were. If an error occured while in the group push
11601
       return that error code but try to do the cleanup */
11602
0
    code2 = gs_end_transparency_group(pgs);
11603
0
    if (code2 < 0) {
11604
        /* At this point things have gone very wrong. We should just shut down */
11605
0
        code = gs_abort_pdf14trans_device(pgs);
11606
0
        return code2;
11607
0
    }
11608
11609
    /* Restore if there were any changes */
11610
0
    (void)gs_setfillconstantalpha(pgs, fill_alpha);
11611
0
    (void)gs_setstrokeconstantalpha(pgs, stroke_alpha);
11612
0
    (void)gs_setblendmode(pgs, blend_mode); /* Can never fail */
11613
11614
0
    return code;
11615
0
}
11616
11617
/*
11618
 * fill_path routine for the PDF 1.4 transaprency compositor device for
11619
 * writing the clist.
11620
 */
11621
static  int
11622
pdf14_clist_fill_stroke_path(gx_device  *dev, const gs_gstate *pgs, gx_path *ppath,
11623
                             const gx_fill_params *params_fill, const gx_drawing_color *pdevc_fill,
11624
                             const gx_stroke_params *params_stroke, const gx_drawing_color *pdevc_stroke,
11625
                             const gx_clip_path *pcpath)
11626
2.29k
{
11627
2.29k
    pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
11628
2.29k
    gs_gstate new_pgs = *pgs;
11629
2.29k
    int code;
11630
11631
2.29k
    if ((pgs->fillconstantalpha == 0.0 && pgs->strokeconstantalpha == 0.0) ||
11632
2.29k
        (pgs->ctm.xx == 0.0 && pgs->ctm.xy == 0.0 && pgs->ctm.yx == 0.0 && pgs->ctm.yy == 0.0))
11633
42
        return 0;
11634
11635
    /*
11636
     * Ensure that that the PDF 1.4 reading compositor will have the current
11637
     * blending parameters.  This is needed since the fill_rectangle routines
11638
     * do not have access to the gs_gstate.  Thus we have to pass any
11639
     * changes explictly.
11640
     */
11641
2.25k
    code = pdf14_clist_update_params(pdev, pgs, false, NULL);
11642
2.25k
    if (code < 0)
11643
0
        return code;
11644
    /* If we are doing a shading fill or stroke, the clist can't
11645
       deal with this and end up in the pdf_fill_stroke operation.
11646
       We will need to break up the fill stroke now and do
11647
       the appropriate group pushes and set up. */
11648
11649
2.25k
    if (gx_dc_is_pattern2_color(pdevc_fill) ||
11650
2.25k
        gx_dc_is_pattern2_color(pdevc_stroke)) {
11651
0
        return pdf14_clist_fill_stroke_path_pattern_setup(dev, pgs, ppath,
11652
0
            params_fill, pdevc_fill, params_stroke, pdevc_stroke, pcpath);
11653
0
    }
11654
2.25k
    update_lop_for_pdf14(&new_pgs, pdevc_fill);
11655
2.25k
    new_pgs.trans_device = dev;
11656
2.25k
    new_pgs.has_transparency = true;
11657
2.25k
    code = gx_forward_fill_stroke_path(dev, &new_pgs, ppath, params_fill, pdevc_fill,
11658
2.25k
                                       params_stroke, pdevc_stroke, pcpath);
11659
2.25k
    new_pgs.trans_device = NULL;
11660
2.25k
    new_pgs.has_transparency = false;
11661
2.25k
    return code;
11662
2.25k
}
11663
11664
/*
11665
 * text_begin routine for the PDF 1.4 transaprency compositor device for
11666
 * writing the clist.
11667
 */
11668
static  int
11669
pdf14_clist_text_begin(gx_device * dev, gs_gstate * pgs,
11670
                 const gs_text_params_t * text, gs_font * font,
11671
                 const gx_clip_path * pcpath,
11672
                 gs_text_enum_t ** ppenum)
11673
1.09M
{
11674
1.09M
    pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
11675
1.09M
    gs_text_enum_t *penum;
11676
1.09M
    int code;
11677
1.09M
    gs_blend_mode_t blend_mode = gs_currentblendmode(pgs);
11678
1.09M
    float opacity = pgs->fillconstantalpha;
11679
1.09M
    float shape = 1.0;
11680
1.09M
    bool blend_issue = !(blend_mode == BLEND_MODE_Normal || blend_mode == BLEND_MODE_Compatible || blend_mode == BLEND_MODE_CompatibleOverprint);
11681
1.09M
    bool draw = !(text->operation & TEXT_DO_NONE);
11682
1.09M
    uint text_mode = gs_currenttextrenderingmode(pgs);
11683
1.09M
    bool text_stroke = (text_mode == 1 || text_mode == 2 || text_mode == 5 || text_mode == 6);
11684
1.09M
    bool text_fill = (text_mode == 0 || text_mode == 2 || text_mode == 4 || text_mode == 6);
11685
11686
1.09M
    if_debug0m('v', pgs->memory, "[v]pdf14_clist_text_begin\n");
11687
    /*
11688
     * Ensure that that the PDF 1.4 reading compositor will have the current
11689
     * blending parameters.  This is needed since the fill_rectangle routines
11690
     * do not have access to the gs_gstate.  Thus we have to pass any
11691
     * changes explictly.
11692
     */
11693
1.09M
    code = pdf14_clist_update_params(pdev, pgs, false, NULL);
11694
1.09M
    if (code < 0)
11695
0
        return code;
11696
    /* Pass text_begin to the target */
11697
1.09M
    code = gx_forward_text_begin(dev, pgs, text, font,
11698
1.09M
                                 pcpath, &penum);
11699
1.09M
    if (code < 0)
11700
1
        return code;
11701
11702
   /* Catch case where we already pushed a group and are trying to push another one.
11703
   In that case, we will pop the current one first, as we don't want to be left
11704
   with it. Note that if we have a BT and no other BTs or ETs then this issue
11705
   will not be caught until we do the put_image and notice that the stack is not
11706
   empty. */
11707
1.09M
    if (pdev->text_group == PDF14_TEXTGROUP_MISSING_ET) {
11708
52
        code = gs_end_transparency_group(pgs);
11709
52
        if (code < 0)
11710
0
            return code;
11711
52
        pdev->text_group = PDF14_TEXTGROUP_BT_NOT_PUSHED;
11712
52
    }
11713
11714
    /* We may need to push a non-isolated transparency group if the following
11715
    is true.
11716
    1) We are not currently in one that we pushed for text.  This is
11717
    is determined by looking at the pdf14 device.
11718
    2) The blend mode is not Normal or the opacity is not 1.0
11719
    3) Text knockout is set to true
11720
    4) And we are actually drawing text
11721
    */
11722
11723
1.09M
    if (gs_currenttextknockout(pgs) && (blend_issue ||
11724
1.09M
        (pgs->fillconstantalpha != 1.0 && text_fill) ||
11725
1.09M
        (pgs->strokeconstantalpha != 1.0 && text_stroke)) &&
11726
1.09M
        text_mode != 3 && /* don't bother with invisible text */
11727
1.09M
        pdev->text_group == PDF14_TEXTGROUP_BT_NOT_PUSHED) {
11728
578
        if (draw) {
11729
578
            code = pdf14_push_text_group(dev, pgs, blend_mode, opacity, shape, true);
11730
578
            if (code == 0)
11731
578
                pdev->text_group = PDF14_TEXTGROUP_BT_PUSHED;  /* Needed during clist writing */
11732
578
        }
11733
578
    }
11734
1.09M
    *ppenum = (gs_text_enum_t *)penum;
11735
1.09M
    return code;
11736
1.09M
}
11737
11738
static  int
11739
pdf14_clist_begin_typed_image(gx_device * dev, const gs_gstate * pgs,
11740
                           const gs_matrix *pmat, const gs_image_common_t *pic,
11741
                           const gs_int_rect * prect,
11742
                           const gx_drawing_color * pdcolor,
11743
                           const gx_clip_path * pcpath, gs_memory_t * mem,
11744
                           gx_image_enum_common_t ** pinfo)
11745
14.6k
{
11746
14.6k
    pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
11747
14.6k
    int code;
11748
14.6k
    gs_gstate * pgs_noconst = (gs_gstate *)pgs; /* Break 'const'. */
11749
14.6k
    const gs_image_t *pim = (const gs_image_t *)pic;
11750
14.6k
    gx_image_enum *penum;
11751
14.6k
    gx_color_tile *ptile;
11752
14.6k
    gs_rect bbox_in, bbox_out;
11753
14.6k
    gs_transparency_group_params_t tgp;
11754
    /*
11755
     * Ensure that that the PDF 1.4 reading compositor will have the current
11756
     * blending parameters.  This is needed since the fill_rectangle routines
11757
     * do not have access to the gs_gstate.  Thus we have to pass any
11758
     * changes explictly.
11759
     */
11760
14.6k
    code = pdf14_clist_update_params(pdev, pgs, false, NULL);
11761
14.6k
    if (code < 0)
11762
0
        return code;
11763
    /* Pass image to the target */
11764
    /* Do a quick change to the gs_gstate so that if we can return with -1 in
11765
       case the clist writer cannot handle this image itself.  In such a case,
11766
       we want to make sure we dont use the target device.  I don't necc. like
11767
       doing it this way.  Probably need to go back and do something a bit
11768
       more elegant. */
11769
14.6k
    pgs_noconst->has_transparency = true;
11770
14.6k
    pgs_noconst->trans_device = dev;
11771
11772
    /* If we are filling an image mask with a pattern that has a transparency
11773
       then we need to do some special handling */
11774
14.6k
    if (pim->ImageMask) {
11775
0
        if (pdcolor != NULL && gx_dc_is_pattern1_color(pdcolor)) {
11776
0
            if( gx_pattern1_get_transptr(pdcolor) != NULL){
11777
0
                if (dev_proc(dev, begin_typed_image) != pdf14_clist_begin_typed_image) {
11778
0
                    ptile = pdcolor->colors.pattern.p_tile;
11779
                    /* Set up things in the ptile so that we get the proper
11780
                       blending etc */
11781
                    /* Set the blending procs and the is_additive setting based
11782
                       upon the number of channels */
11783
0
                    if (ptile->ttrans->n_chan-1 < 4) {
11784
0
                        ptile->ttrans->blending_procs = &rgb_blending_procs;
11785
0
                        ptile->ttrans->is_additive = true;
11786
0
                    } else {
11787
0
                        ptile->ttrans->blending_procs = &cmyk_blending_procs;
11788
0
                        ptile->ttrans->is_additive = false;
11789
0
                    }
11790
                    /* Set the blending mode in the ptile based upon the current
11791
                       setting in the gs_gstate */
11792
0
                    ptile->blending_mode = pgs->blend_mode;
11793
                    /* Set the procs so that we use the proper filling method. */
11794
                    /* Let the imaging stuff get set up */
11795
0
                    code = gx_default_begin_typed_image(dev, pgs, pmat, pic,
11796
0
                                                        prect, pdcolor,
11797
0
                                                        pcpath, mem, pinfo);
11798
0
                    if (code < 0)
11799
0
                        return code;
11800
11801
0
                    penum = (gx_image_enum *) *pinfo;
11802
                    /* Apply inverse of the image matrix to our
11803
                       image size to get our bounding box. */
11804
0
                    bbox_in.p.x = 0;
11805
0
                    bbox_in.p.y = 0;
11806
0
                    bbox_in.q.x = pim->Width;
11807
0
                    bbox_in.q.y = pim->Height;
11808
0
                    code = gs_bbox_transform_inverse(&bbox_in, &(pim->ImageMatrix),
11809
0
                                                     &bbox_out);
11810
0
                    if (code < 0)
11811
0
                        return code;
11812
                    /* Set up a compositor action for pushing the group */
11813
0
                    if_debug0m('v', pgs->memory, "[v]Pushing special trans group for image\n");
11814
0
                    tgp.Isolated = true;
11815
0
                    tgp.Knockout = false;
11816
0
                    tgp.page_group = false;
11817
0
                    tgp.mask_id = 0;
11818
0
                    tgp.image_with_SMask = false;
11819
0
                    tgp.idle = false;
11820
0
                    tgp.iccprofile = NULL;
11821
0
                    tgp.icc_hashcode = 0;
11822
0
                    tgp.group_color_numcomps = ptile->ttrans->n_chan-1;
11823
0
                    tgp.ColorSpace = NULL;
11824
0
                    tgp.text_group = 0;
11825
0
                    tgp.group_opacity = pgs->fillconstantalpha;
11826
0
                    tgp.group_shape = 1.0;
11827
                    /* This will handle the compositor command */
11828
0
                    gs_begin_transparency_group((gs_gstate *) pgs_noconst, &tgp,
11829
0
                                                &bbox_out, PDF14_BEGIN_TRANS_GROUP);
11830
0
                    ptile->ttrans->image_render = penum->render;
11831
0
                    penum->render = &pdf14_pattern_trans_render;
11832
0
                    ptile->trans_group_popped = false;
11833
0
                    pgs_noconst->has_transparency = false;
11834
0
                    pgs_noconst->trans_device = NULL;
11835
0
                    return code;
11836
0
                }
11837
0
            }
11838
0
        }
11839
0
    }
11840
    /* This basically tries high level images for clist. If that fails
11841
       then we do the default */
11842
14.6k
    code = gx_forward_begin_typed_image(dev, pgs, pmat,
11843
14.6k
                            pic, prect, pdcolor, pcpath, mem, pinfo);
11844
14.6k
    if (code < 0){
11845
4.50k
        code = gx_default_begin_typed_image(dev, pgs, pmat, pic, prect,
11846
4.50k
                                        pdcolor, pcpath, mem, pinfo);
11847
4.50k
        pgs_noconst->has_transparency = false;
11848
4.50k
        pgs_noconst->trans_device = NULL;
11849
4.50k
        return code;
11850
10.1k
    } else {
11851
10.1k
        pgs_noconst->has_transparency = false;
11852
10.1k
        pgs_noconst->trans_device = NULL;
11853
10.1k
        return code;
11854
10.1k
    }
11855
14.6k
}
11856
11857
static int
11858
pdf14_clist_copy_planes(gx_device * dev, const byte * data, int data_x, int raster,
11859
                  gx_bitmap_id id, int x, int y, int w, int h, int plane_height)
11860
0
{
11861
0
    int code;
11862
11863
0
    code = gx_forward_copy_planes(dev, data, data_x, raster, id,
11864
0
                                  x, y, w, h, plane_height);
11865
0
    return code;
11866
0
}
11867
11868
static int
11869
gs_pdf14_clist_device_push(gs_memory_t *mem, gs_gstate *pgs, gx_device **pcdev,
11870
                           gx_device *dev, const gs_pdf14trans_t *pdf14pct)
11871
2.72k
{
11872
2.72k
    int code;
11873
2.72k
    pdf14_clist_device *p14dev;
11874
2.72k
    gx_device_clist_writer * const cdev = &((gx_device_clist *)dev)->writer;
11875
11876
2.72k
    code = pdf14_create_clist_device(mem, pgs, pcdev, dev, pdf14pct);
11877
2.72k
    if (code < 0)
11878
0
        return code;
11879
    /*
11880
     * Set the color_info of the clist device to match the compositing
11881
     * device.  We will restore it when the compositor is popped.
11882
     * See pdf14_clist_composite for the restore.  Do the
11883
     * same with the gs_gstate's get_cmap_procs.  We do not want
11884
     * the gs_gstate to use transfer functions on our color values.
11885
     * The transfer functions will be applied at the end after we
11886
     * have done our PDF 1.4 blend operations.
11887
     */
11888
2.72k
    p14dev = (pdf14_clist_device *)(*pcdev);
11889
2.72k
    p14dev->saved_target_color_info = dev->color_info;
11890
2.72k
    dev->color_info = (*pcdev)->color_info;
11891
    /* Make sure that we keep the anti-alias information though */
11892
2.72k
    dev->color_info.anti_alias = p14dev->saved_target_color_info.anti_alias;
11893
2.72k
    p14dev->color_info.anti_alias = dev->color_info.anti_alias;
11894
11895
    /* adjust the clist_color_info now */
11896
2.72k
    cdev->clist_color_info.depth = p14dev->color_info.depth;
11897
2.72k
    cdev->clist_color_info.polarity = p14dev->color_info.polarity;
11898
2.72k
    cdev->clist_color_info.num_components = p14dev->color_info.num_components;
11899
2.72k
    cdev->clist_color_info.max_color = p14dev->color_info.max_color;
11900
2.72k
    cdev->clist_color_info.max_gray = p14dev->color_info.max_gray;
11901
11902
2.72k
    p14dev->saved_target_encode_color = dev_proc(dev, encode_color);
11903
2.72k
    p14dev->saved_target_decode_color = dev_proc(dev, decode_color);
11904
2.72k
    set_dev_proc(dev, encode_color, p14dev->my_encode_color);
11905
2.72k
    set_dev_proc(p14dev, encode_color, p14dev->my_encode_color);
11906
2.72k
    set_dev_proc(dev, decode_color, p14dev->my_decode_color);
11907
2.72k
    set_dev_proc(p14dev, decode_color, p14dev->my_decode_color);
11908
2.72k
    p14dev->saved_target_get_color_mapping_procs =
11909
2.72k
                              dev_proc(dev, get_color_mapping_procs);
11910
2.72k
    p14dev->saved_target_get_color_comp_index =
11911
2.72k
                              dev_proc(dev, get_color_comp_index);
11912
2.72k
    set_dev_proc(dev, get_color_mapping_procs, p14dev->my_get_color_mapping_procs);
11913
2.72k
    set_dev_proc(p14dev, get_color_mapping_procs, p14dev->my_get_color_mapping_procs);
11914
2.72k
    set_dev_proc(dev, get_color_comp_index, p14dev->my_get_color_comp_index);
11915
2.72k
    set_dev_proc(p14dev, get_color_comp_index, p14dev->my_get_color_comp_index);
11916
2.72k
    p14dev->save_get_cmap_procs = pgs->get_cmap_procs;
11917
2.72k
    pgs->get_cmap_procs = pdf14_get_cmap_procs;
11918
2.72k
    gx_set_cmap_procs(pgs, dev);
11919
2.72k
    return code;
11920
2.72k
}
11921
/*
11922
 * When we push a PDF 1.4 transparency compositor onto the clist, we also need
11923
 * to create a compositing device for clist writing.  The primary purpose of
11924
 * this device is to provide support for the process color model in which
11925
 * the PDF 1.4 transparency is done.  (This may differ from the process color
11926
 * model of the output device.)  The actual work of compositing the image is
11927
 * done on the output (reader) side of the clist.
11928
 */
11929
static  int
11930
c_pdf14trans_clist_write_update(const gs_composite_t * pcte, gx_device * dev,
11931
                gx_device ** pcdev, gs_gstate * pgs, gs_memory_t * mem)
11932
114k
{
11933
114k
    gx_device_clist_writer * const cdev = &((gx_device_clist *)dev)->writer;
11934
114k
    const gs_pdf14trans_t * pdf14pct = (const gs_pdf14trans_t *) pcte;
11935
114k
    int code = 0;
11936
11937
    /* We only handle the push/pop operations */
11938
114k
    switch (pdf14pct->params.pdf14_op) {
11939
2.72k
        case PDF14_PUSH_DEVICE:
11940
2.72k
            code = gs_pdf14_clist_device_push(mem, pgs, pcdev, dev, pdf14pct);
11941
            /* Change (non-error) code to 1 to indicate that we created
11942
             * a device. */
11943
2.72k
            if (code >= 0)
11944
2.72k
                code = 1;
11945
2.72k
            return code;
11946
11947
2.64k
        case PDF14_POP_DEVICE:
11948
2.64k
            code = clist_writer_check_empty_cropping_stack(cdev);
11949
2.64k
            break;
11950
11951
935
        case PDF14_BEGIN_TRANS_PAGE_GROUP:
11952
12.5k
        case PDF14_BEGIN_TRANS_GROUP:
11953
12.5k
            { /* HACK: store mask_id into our params for subsequent
11954
                   calls of c_pdf14trans_write. To do this we must
11955
                   break const. */
11956
12.5k
                gs_pdf14trans_t * pdf14pct_noconst;
11957
11958
12.5k
                pdf14pct_noconst = (gs_pdf14trans_t *) pcte;
11959
                /* What ever the current mask ID is, that is the
11960
                   softmask group through which this transparency
11961
                   group must be rendered. Store it now. */
11962
12.5k
                pdf14pct_noconst->params.mask_id = cdev->mask_id;
11963
12.5k
                if_debug1m('v', pgs->memory,
11964
12.5k
                           "[v]c_pdf14trans_clist_write_update group mask_id=%d \n",
11965
12.5k
                           cdev->mask_id);
11966
12.5k
            }
11967
12.5k
            break;
11968
11.9k
        case PDF14_END_TRANS_GROUP:
11969
12.4k
        case PDF14_END_TRANS_TEXT_GROUP:
11970
12.4k
            code = 0; /* A place for breakpoint. */
11971
12.4k
            break;
11972
14.6k
        case PDF14_BEGIN_TRANS_MASK:
11973
            /* A new mask has been started */
11974
14.6k
            cdev->mask_id = ++cdev->mask_id_count;
11975
            /* replacing is set everytime that we
11976
               have a zpushtransparencymaskgroup */
11977
14.6k
            { /* HACK: store mask_id into our params for subsequent
11978
                   calls of c_pdf14trans_write. To do this we must
11979
                   break const. */
11980
14.6k
                gs_pdf14trans_t * pdf14pct_noconst;
11981
11982
14.6k
                pdf14pct_noconst = (gs_pdf14trans_t *) pcte;
11983
14.6k
                pdf14pct_noconst->params.mask_id = cdev->mask_id;
11984
14.6k
                if_debug1m('v', pgs->memory,
11985
14.6k
                           "[v]c_pdf14trans_clist_write_update mask mask_id=%d \n",
11986
14.6k
                           cdev->mask_id);
11987
14.6k
            }
11988
14.6k
            break;
11989
7.15k
        case PDF14_END_TRANS_MASK:
11990
7.15k
            code = 0; /* A place for breakpoint. */
11991
7.15k
            break;
11992
0
        case PDF14_PUSH_TRANS_STATE:
11993
0
            code = 0; /* A place for breakpoint. */
11994
0
            break;
11995
6.95k
        case PDF14_POP_TRANS_STATE:
11996
6.95k
            code = 0; /* A place for breakpoint. */
11997
6.95k
            break;
11998
0
        case PDF14_ABORT_DEVICE:
11999
0
            code = 0;
12000
0
            break;
12001
0
        case PDF14_PUSH_SMASK_COLOR:
12002
0
            *pcdev = dev;
12003
0
            return 0;
12004
0
            break;
12005
0
        case PDF14_POP_SMASK_COLOR:
12006
0
            *pcdev = dev;
12007
0
            return 0;
12008
0
            break;
12009
55.5k
        default:
12010
55.5k
            break;   /* do nothing for remaining ops */
12011
114k
    }
12012
111k
    *pcdev = dev;
12013
111k
    if (code < 0)
12014
0
        return code;
12015
    /* See c_pdf14trans_write, c_pdf14trans_adjust_ctm, and
12016
       apply_composite. */
12017
111k
    code = gs_gstate_setmatrix(&cdev->gs_gstate, &pdf14pct->params.ctm);
12018
    /* Wrote an extra ctm. */
12019
111k
    cmd_clear_known(cdev, ctm_known);
12020
12021
111k
    return code;
12022
111k
}
12023
12024
/*
12025
 * When we push a PDF 1.4 transparency compositor, we need to make the clist
12026
 * device color_info data match the compositing device.  We need to do this
12027
 * since the PDF 1.4 transparency compositing device may use a different
12028
 * process color model than the output device.  We do not need to modify the
12029
 * color related device procs since the compositing device has its own.  We
12030
 * restore the color_info data when the transparency device is popped.
12031
 */
12032
static  int
12033
c_pdf14trans_clist_read_update(gs_composite_t * pcte, gx_device * cdev,
12034
                gx_device * tdev, gs_gstate * pgs, gs_memory_t * mem)
12035
6.18M
{
12036
6.18M
    pdf14_device * p14dev = (pdf14_device *)tdev;
12037
6.18M
    gs_pdf14trans_t * pdf14pct = (gs_pdf14trans_t *) pcte;
12038
6.18M
    gs_devn_params * pclist_devn_params;
12039
6.18M
    gx_device_clist_reader *pcrdev = (gx_device_clist_reader *)cdev;
12040
6.18M
    cmm_profile_t *cl_icc_profile, *p14_icc_profile;
12041
6.18M
    gsicc_rendering_param_t render_cond;
12042
6.18M
    cmm_dev_profile_t *dev_profile;
12043
12044
6.18M
    dev_proc(cdev, get_profile)(cdev,  &dev_profile);
12045
6.18M
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &cl_icc_profile,
12046
6.18M
                          &render_cond);
12047
12048
    /* If we are using the blending color space, then be sure to use that. */
12049
6.18M
    if (p14dev->blend_cs_state == PDF14_BLEND_CS_SPECIFIED &&
12050
6.18M
        dev_profile->blend_profile != NULL)
12051
0
        cl_icc_profile = dev_profile->blend_profile;
12052
6.18M
    else if (p14dev->blend_cs_state == PDF14_BLEND_CS_OUTPUTINTENT &&
12053
6.18M
        dev_profile->oi_profile != NULL)
12054
0
        cl_icc_profile = dev_profile->oi_profile;
12055
12056
6.18M
    dev_proc(p14dev, get_profile)((gx_device *)p14dev,  &dev_profile);
12057
6.18M
    gsicc_extract_profile(GS_UNKNOWN_TAG, dev_profile, &p14_icc_profile,
12058
6.18M
                          &render_cond);
12059
    /*
12060
     * We only handle the push/pop operations. Save and restore the color_info
12061
     * field for the clist device.  This is needed since the process color
12062
     * model of the clist device needs to match the PDF 1.4 compositing
12063
     * device.
12064
     */
12065
6.18M
    switch (pdf14pct->params.pdf14_op) {
12066
254k
    case PDF14_PUSH_DEVICE:
12067
        /* Overprint simulation sets the profile at prototype creation, as does
12068
           when the target profile is NCLR. Match the logic in gs_pdf14_device_push */
12069
254k
        if (!((p14dev->overprint_sim && cl_icc_profile->data_cs != gsCMYK) ||
12070
254k
            cl_icc_profile->data_cs == gsNCHANNEL)) {
12071
254k
            gsicc_adjust_profile_rc(cl_icc_profile, 1, "c_pdf14trans_clist_read_update");
12072
254k
            gsicc_adjust_profile_rc(p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE],
12073
254k
                -1, "c_pdf14trans_clist_read_update");
12074
254k
            p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] = cl_icc_profile;
12075
254k
        }
12076
            /*
12077
             * If we are blending using spot colors (i.e. the output device
12078
             * supports spot colors) then we need to transfer
12079
             * color info from the clist PDF 1.4 compositing reader device
12080
             * to the clist writer PDF 1.4 compositing device.
12081
             * This info was transfered from that device to the output
12082
             * device as a set of device parameters.  However the clist
12083
             * reader PDF 1.4 compositing device did not exist when the
12084
             * device parameters were read from the clist.  So that info
12085
             * was buffered into the output device.
12086
             */
12087
254k
            pclist_devn_params = dev_proc(cdev, ret_devn_params)(cdev);
12088
254k
            if (pclist_devn_params != NULL && pclist_devn_params->page_spot_colors > 0) {
12089
12
                int num_comp = p14dev->color_info.num_components;
12090
                /*
12091
                 * The number of components for the PDF14 device is the sum
12092
                 * of the process components and the number of spot colors
12093
                 * for the page.  If the color capabilities of the parent
12094
                 * device (which coming into this are the same as the p14dev)
12095
                 * are smaller than the number of page spot colors then
12096
                 * use that for the number of components. Otherwise use
12097
                 * the page_spot_colors.  The exception is, if we had used
12098
                 * the sICCOutputColors setting, then just use that, which
12099
                 * should be already baked into num_comp. With clist patterns,
12100
                 * cdev->icc_struct may be null.
12101
                 */
12102
12103
12
                if (cdev->icc_struct == NULL || cdev->icc_struct->spotnames == NULL) {
12104
12
                    p14dev->devn_params.page_spot_colors =
12105
12
                        pclist_devn_params->page_spot_colors;
12106
12
                    if (num_comp < p14dev->devn_params.page_spot_colors + 4 ) {
12107
0
                        p14dev->color_info.num_components = num_comp;
12108
12
                    } else {
12109
                        /* if page_spot_colors < 0, this will be wrong, so don't update num_components */
12110
12
                        if (p14dev->devn_params.page_spot_colors >= 0) {
12111
12
                            p14dev->color_info.num_components =
12112
12
                                p14dev->devn_params.num_std_colorant_names +
12113
12
                                p14dev->devn_params.page_spot_colors;
12114
12
                        }
12115
12
                    }
12116
12
                }
12117
                /* limit the num_components to the max. */
12118
12
                if (p14dev->color_info.num_components > p14dev->color_info.max_components)
12119
0
                    p14dev->color_info.num_components = p14dev->color_info.max_components;
12120
                /* Transfer the data for the spot color names
12121
                   But we have to free what may be there before we do this */
12122
12
                devn_free_params((gx_device*) p14dev);
12123
12
                p14dev->devn_params.separations =
12124
12
                    pclist_devn_params->pdf14_separations;
12125
12
                p14dev->free_devicen = false;  /* to avoid freeing the clist ones */
12126
12
                if (num_comp != p14dev->color_info.num_components) {
12127
                    /* When the pdf14 device is opened it creates a context
12128
                       and some soft mask related objects.  The push device
12129
                       compositor action will have already created these but
12130
                       they are the wrong size.  We must destroy them though
12131
                       before reopening the device */
12132
0
                    if (p14dev->ctx != NULL) {
12133
0
                        pdf14_ctx_free(p14dev->ctx);
12134
0
                        p14dev->ctx = NULL;
12135
0
                    }
12136
0
                    dev_proc(tdev, open_device) (tdev);
12137
0
                }
12138
12
            }
12139
            /* Check if we need to swap out the ICC profile for the pdf14
12140
               device.  This will occur if our source profile for our device
12141
               happens to be something like CIELAB.  Then we will blend in
12142
               RGB (unless a trans group is specified) */
12143
254k
            if (cl_icc_profile->data_cs == gsCIELAB || cl_icc_profile->islab) {
12144
0
                gsicc_adjust_profile_rc(p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE],
12145
0
                                        -1, "c_pdf14trans_clist_read_update");
12146
                /* Initial ref count from gsicc_read_serial_icc() is 1, which is what we want */
12147
0
                p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE] =
12148
0
                                        gsicc_read_serial_icc(cdev, pcrdev->trans_dev_icc_hash);
12149
                /* Keep a pointer to the clist device */
12150
0
                p14dev->icc_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE]->dev = (gx_device *) cdev;
12151
0
            }
12152
254k
            break;
12153
12154
254k
        case PDF14_POP_DEVICE:
12155
#     if 0 /* Disabled because *p14dev has no forwarding methods during
12156
                    the clist playback. This code is not executed while clist
12157
                    writing. */
12158
            cdev->color_info = p14dev->saved_target_color_info;
12159
#     endif
12160
254k
           break;
12161
12162
5.68M
        default:
12163
5.68M
            break;   /* do nothing for remaining ops */
12164
6.18M
    }
12165
12166
6.18M
    return 0;
12167
6.18M
}
12168
12169
/*
12170
 * Get cropping for the compositor command.
12171
 */
12172
static  int
12173
c_pdf14trans_get_cropping(const gs_composite_t *pcte, int *ry, int *rheight,
12174
                          int cropping_min, int cropping_max)
12175
114k
{
12176
114k
    gs_pdf14trans_t * pdf14pct = (gs_pdf14trans_t *) pcte;
12177
114k
    switch (pdf14pct->params.pdf14_op) {
12178
2.72k
        case PDF14_PUSH_DEVICE: return ALLBANDS; /* Applies to all bands. */
12179
2.64k
        case PDF14_POP_DEVICE:  return ALLBANDS; /* Applies to all bands. */
12180
0
        case PDF14_ABORT_DEVICE: return ALLBANDS; /* Applies to all bands */
12181
935
        case PDF14_BEGIN_TRANS_PAGE_GROUP:
12182
12.5k
        case PDF14_BEGIN_TRANS_GROUP:
12183
12.5k
            { gs_int_rect rect;
12184
12185
                /* Text group always uses parents size*/
12186
12.5k
                if (pdf14pct->params.text_group == PDF14_TEXTGROUP_BT_PUSHED) {
12187
578
                    *ry = cropping_min;
12188
578
                    *rheight = cropping_max - *ry;
12189
11.9k
                } else {
12190
11.9k
                    pdf14_compute_group_device_int_rect(&pdf14pct->params.ctm,
12191
11.9k
                        &pdf14pct->params.bbox, &rect);
12192
                    /* We have to crop this by the parent object.   */
12193
11.9k
                    *ry = max(rect.p.y, cropping_min);
12194
11.9k
                    *rheight = min(rect.q.y, cropping_max) - *ry;
12195
11.9k
                }
12196
12.5k
                return PUSHCROP; /* Push cropping. */
12197
935
            }
12198
14.6k
        case PDF14_BEGIN_TRANS_MASK:
12199
14.6k
            { gs_int_rect rect;
12200
12201
14.6k
                pdf14_compute_group_device_int_rect(&pdf14pct->params.ctm,
12202
14.6k
                                                    &pdf14pct->params.bbox, &rect);
12203
                /* We have to crop this by the parent object and worry about the BC outside
12204
                   the range, except for image SMask which don't affect areas outside the image.
12205
                   The presence of a transfer function opens the possibility of issues with this */
12206
14.6k
                if (pdf14pct->params.mask_is_image || (pdf14pct->params.GrayBackground == 1.0 &&
12207
7.87k
                      pdf14pct->params.function_is_identity)) {
12208
                    /* In this case there will not be a background effect to
12209
                       worry about.  The mask will not have any effect outside
12210
                       the bounding box.  This is NOT the default or common case. */
12211
6.78k
                    *ry = max(rect.p.y, cropping_min);
12212
6.78k
                    *rheight = min(rect.q.y, cropping_max) - *ry;
12213
6.78k
                    return PUSHCROP; /* Push cropping. */
12214
7.86k
                }  else {
12215
                    /* We need to make the soft mask range as large as the parent
12216
                       due to the fact that the background color can have an impact
12217
                       OUTSIDE the bounding box of the soft mask */
12218
7.86k
                    *ry = cropping_min;
12219
7.86k
                    *rheight = cropping_max - cropping_min;
12220
7.86k
                    if (pdf14pct->params.subtype == TRANSPARENCY_MASK_None)
12221
7.49k
                        return SAMEAS_PUSHCROP_BUTNOPUSH;
12222
372
                    else
12223
372
                        return PUSHCROP; /* Push cropping. */
12224
7.86k
                }
12225
14.6k
            }
12226
11.9k
        case PDF14_END_TRANS_GROUP: return POPCROP; /* Pop cropping. */
12227
502
        case PDF14_END_TRANS_TEXT_GROUP: return POPCROP; /* Pop cropping. */
12228
7.15k
        case PDF14_END_TRANS_MASK: return POPCROP;   /* Pop the cropping */
12229
0
        case PDF14_PUSH_TRANS_STATE: return CURRBANDS;
12230
6.95k
        case PDF14_POP_TRANS_STATE: return CURRBANDS;
12231
55.5k
        case PDF14_SET_BLEND_PARAMS: return ALLBANDS;
12232
0
        case PDF14_PUSH_SMASK_COLOR: return POPCROP; /* Pop cropping. */
12233
0
        case PDF14_POP_SMASK_COLOR: return POPCROP;   /* Pop the cropping */
12234
0
        case PDF14_BEGIN_TRANS_TEXT_GROUP: return ALLBANDS; /* should never occur */
12235
114k
    }
12236
0
    return ALLBANDS;
12237
114k
}
12238
12239
/*
12240
 * This routine will check to see if the color component name matches those
12241
 * that are available amoung the current device's color components.  If the
12242
 * color name is known to the output device then we add it to the list of
12243
 * colorants for the PDF 1.4 transparency compositor.
12244
 *
12245
 * Notes:  There are currently three different versions of The PDF 1.4
12246
 * transparency compositor device.  The choice of which one is being used
12247
 * depends upon the process color model of the output device.  This procedure
12248
 * is only used if the output (target) device uses a CMYK, or RGB or Gray
12249
 * plus spot color process color model.
12250
 *
12251
 * Parameters:
12252
 *   dev - pointer to device data structure.
12253
 *   pname - pointer to name (zero termination not required)
12254
 *   nlength - length of the name
12255
 *   number of process colorants (either 1, 3, or 4)
12256
 *
12257
 * This routine returns a positive value (0 to n) which is the device colorant
12258
 * number if the name is found.  It returns GX_DEVICE_COLOR_MAX_COMPONENTS if
12259
 * the colorant is not being used due to a SeparationOrder device parameter.
12260
 * It returns a negative value if not found.
12261
 */
12262
static int
12263
pdf14_spot_get_color_comp_index(gx_device *dev, const char *pname,
12264
    int name_size, int component_type, int num_process_colors)
12265
8.14k
{
12266
8.14k
    pdf14_device *pdev = (pdf14_device *)dev;
12267
8.14k
    gx_device *tdev = pdev->target;
12268
8.14k
    gs_devn_params *pdevn_params = &pdev->devn_params;
12269
8.14k
    gs_separations *pseparations;
12270
8.14k
    int comp_index;
12271
8.14k
    dev_proc_get_color_comp_index(*target_get_color_comp_index);
12272
8.14k
    int offset = 4 - num_process_colors;
12273
12274
8.14k
    while (tdev->child) {
12275
0
        tdev = tdev->child;
12276
0
    }
12277
    /* If something has gone wrong and this is no longer the pdf14 compositor, */
12278
    /* get the devn_params from the target to avoid accessing using the wrong  */
12279
    /* pointer. Bug 696372.                                                    */
12280
8.14k
    if (tdev == (gx_device *)pdev)
12281
0
        pdevn_params = dev_proc(pdev, ret_devn_params)(dev);
12282
8.14k
    pseparations = &pdevn_params->separations;
12283
    /* If num_process_colors is 3 or 1 (RGB or Gray) then we are in a situation
12284
     * where we are in a blend color space that is RGB or Gray based and we
12285
     * have a spot colorant.  If the spot colorant name is Cyan, Magenta
12286
     * Yellow or Black, then we should use the alternate tint transform */
12287
8.14k
    if (num_process_colors < 4) {
12288
446
        int k;
12289
2.23k
        for (k = 0; k < 4; k++) {
12290
1.78k
            if (strncmp(pname, pdev->devn_params.std_colorant_names[k], name_size) == 0)
12291
0
                return -1;
12292
1.78k
        }
12293
446
    }
12294
12295
8.14k
    target_get_color_comp_index = dev_proc(tdev, get_color_comp_index);
12296
12297
    /* The pdf14_clist_composite may have set the color procs.
12298
       We need the real target procs, but not if we are doing simulated
12299
       overprint */
12300
8.14k
    if (target_get_color_comp_index == pdf14_cmykspot_get_color_comp_index &&
12301
8.14k
        !pdev->overprint_sim)
12302
8.13k
        target_get_color_comp_index =
12303
8.13k
            ((pdf14_clist_device *)pdev)->saved_target_get_color_comp_index;
12304
    /*
12305
    * If this is not a separation name then simply forward it to the target
12306
    * device or return -1 if we are doing overprint simulation.
12307
    * The halftone setup expects this.
12308
    */
12309
8.14k
    if (!pdev->overprint_sim && (component_type == NO_COMP_NAME_TYPE_HT ||
12310
8.14k
        component_type == NO_COMP_NAME_TYPE_OP)) {
12311
7.06k
        return  (*target_get_color_comp_index)(tdev, pname, name_size, component_type);
12312
7.06k
    }
12313
1.08k
    if (pdev->overprint_sim && component_type == NO_COMP_NAME_TYPE_HT) {
12314
0
        return -1;
12315
0
    }
12316
12317
    /*
12318
    * Check if the component is in either the process color model list
12319
    * or in the SeparationNames list.
12320
    */
12321
1.08k
    comp_index = check_pcm_and_separation_names(dev, pdevn_params, pname,
12322
1.08k
        name_size, component_type);
12323
    /*
12324
    * Return the colorant number if we know this name.  Note adjustment for
12325
    * compensating of blend color space.
12326
    */
12327
1.08k
    if (comp_index >= 0)
12328
1.06k
        return comp_index - offset;
12329
12330
    /* Only worry about the target if we are not doing an overprint simulation */
12331
12
    if (!pdev->overprint_sim) {
12332
        /*
12333
        * If we do not know this color, check if the output (target) device does.
12334
        * Note that if the target device has ENABLE_AUTO_SPOT_COLORS this will add
12335
        * the colorant so we will only get < 0 returned when we hit the max. for
12336
        * the target device.
12337
        */
12338
12
        comp_index = (*target_get_color_comp_index)(tdev, pname, name_size, component_type);
12339
        /*
12340
        * Ignore color if unknown to the output device or if color is not being
12341
        * imaged due to the SeparationOrder device parameter.
12342
        */
12343
12
        if (comp_index < 0 || comp_index == GX_DEVICE_COLOR_MAX_COMPONENTS)
12344
0
            return comp_index - offset;
12345
12
    }
12346
12347
    /*
12348
    * This is a new colorant.  Add it to our list of colorants.
12349
    * The limit accounts for the number of process colors (at least 4).
12350
    */
12351
12
    if ((pseparations->num_separations + 1) <
12352
12
            (GX_DEVICE_COLOR_MAX_COMPONENTS - max(num_process_colors, 4))) {
12353
12
        int sep_num = pseparations->num_separations++;
12354
12
        int color_component_number;
12355
12
        byte * sep_name;
12356
12357
12
        sep_name = gs_alloc_bytes(dev->memory->stable_memory,
12358
12
            name_size, "pdf14_spot_get_color_comp_index");
12359
12
        if (sep_name == NULL) {
12360
0
            pseparations->num_separations--;  /* we didn't add it */
12361
0
            return -1;
12362
0
        }
12363
12
        memcpy(sep_name, pname, name_size);
12364
12
        pseparations->names[sep_num].size = name_size;
12365
12
        pseparations->names[sep_num].data = sep_name;
12366
12
        color_component_number = sep_num + num_process_colors;
12367
12
        if (color_component_number >= dev->color_info.max_components)
12368
0
            color_component_number = GX_DEVICE_COLOR_MAX_COMPONENTS;
12369
12
        else
12370
12
            pdevn_params->separation_order_map[color_component_number] =
12371
12
            color_component_number;
12372
12373
        /* Indicate that we need to find equivalent CMYK color. */
12374
12
        pdev->op_pequiv_cmyk_colors.color[sep_num].color_info_valid = false;
12375
12
        pdev->op_pequiv_cmyk_colors.all_color_info_valid = false;
12376
12377
12
        return color_component_number;
12378
12
    }
12379
12380
0
    return GX_DEVICE_COLOR_MAX_COMPONENTS;
12381
12
}
12382
12383
12384
/* CMYK process + spots */
12385
static int
12386
pdf14_cmykspot_get_color_comp_index(gx_device * dev, const char * pname,
12387
    int name_size, int component_type)
12388
7.69k
{
12389
7.69k
    return pdf14_spot_get_color_comp_index(dev, pname, name_size, component_type, 4);
12390
7.69k
}
12391
12392
/* RGB process + spots */
12393
static int
12394
pdf14_rgbspot_get_color_comp_index(gx_device * dev, const char * pname,
12395
    int name_size, int component_type)
12396
446
{
12397
446
    return pdf14_spot_get_color_comp_index(dev, pname, name_size, component_type, 3);
12398
446
}
12399
12400
/* Gray process + spots */
12401
static int
12402
pdf14_grayspot_get_color_comp_index(gx_device * dev, const char * pname,
12403
    int name_size, int component_type)
12404
0
{
12405
0
    return pdf14_spot_get_color_comp_index(dev, pname, name_size, component_type, 1);
12406
0
}
12407
12408
/* These functions keep track of when we are dealing with soft masks.
12409
   In such a case, we set the default color profiles to ones that ensure
12410
   proper soft mask rendering. */
12411
static int
12412
pdf14_increment_smask_color(gs_gstate * pgs, gx_device * dev)
12413
12.6k
{
12414
12.6k
    pdf14_device * pdev = (pdf14_device *) dev;
12415
12.6k
    pdf14_smaskcolor_t *result;
12416
12.6k
    gsicc_smask_t *smask_profiles = pgs->icc_manager->smask_profiles;
12417
12.6k
    int k;
12418
12419
    /* See if we have profiles already in place.   Note we also have to
12420
       worry about a corner case where this device does not have a
12421
       smaskcolor stucture to store the profiles AND the profiles were
12422
       already swapped out in the icc_manager.  This can occur when we
12423
       pushed a transparency mask and then inside the mask we have a pattern
12424
       which also has a transparency mask.   The state of the icc_manager
12425
       is that it already has done the swap and there is no need to fool
12426
       with any of this while dealing with the soft mask within the pattern */
12427
12.6k
    if (pdev->smaskcolor == NULL && pgs->icc_manager->smask_profiles != NULL &&
12428
12.6k
        pgs->icc_manager->smask_profiles->swapped) {
12429
0
            return 0;
12430
0
    }
12431
12.6k
    if (pdev->smaskcolor != NULL) {
12432
16
        pdev->smaskcolor->ref_count++;
12433
16
        if_debug1m(gs_debug_flag_icc, dev->memory,
12434
16
                   "[icc] Increment smask color now %d\n",
12435
16
                   pdev->smaskcolor->ref_count);
12436
12.6k
    } else {
12437
        /* Allocate and swap out the current profiles.  The softmask
12438
           profiles should already be in place */
12439
12.6k
        result = gs_alloc_struct(pdev->memory->stable_memory, pdf14_smaskcolor_t,
12440
12.6k
                                &st_pdf14_smaskcolor,
12441
12.6k
                                "pdf14_increment_smask_color");
12442
12.6k
        if (result == NULL)
12443
0
            return gs_error_VMerror;
12444
12445
12.6k
        result->profiles = gsicc_new_iccsmask(pdev->memory->stable_memory);
12446
12.6k
        if (result->profiles == NULL)
12447
0
            return gs_error_VMerror;
12448
12449
12.6k
        pdev->smaskcolor = result;
12450
12451
12.6k
        result->profiles->smask_gray = pgs->icc_manager->default_gray;
12452
12.6k
        result->profiles->smask_rgb = pgs->icc_manager->default_rgb;
12453
12.6k
        result->profiles->smask_cmyk = pgs->icc_manager->default_cmyk;
12454
12.6k
        pgs->icc_manager->default_gray = smask_profiles->smask_gray;
12455
12.6k
        gsicc_adjust_profile_rc(pgs->icc_manager->default_gray, 1, "pdf14_increment_smask_color");
12456
12.6k
        pgs->icc_manager->default_rgb = smask_profiles->smask_rgb;
12457
12.6k
        gsicc_adjust_profile_rc(pgs->icc_manager->default_rgb, 1, "pdf14_increment_smask_color");
12458
12.6k
        pgs->icc_manager->default_cmyk = smask_profiles->smask_cmyk;
12459
12.6k
        gsicc_adjust_profile_rc(pgs->icc_manager->default_cmyk, 1, "pdf14_increment_smask_color");
12460
12.6k
        pgs->icc_manager->smask_profiles->swapped = true;
12461
12.6k
        if_debug0m(gs_debug_flag_icc, pgs->memory,
12462
12.6k
                   "[icc] Initial creation of smask color. Ref count 1\n");
12463
12.6k
        pdev->smaskcolor->ref_count = 1;
12464
        /* We also need to update the profile that is currently in the
12465
           color spaces of the graphic state.  Otherwise this can be
12466
           referenced, which will result in a mismatch.  What we want to do
12467
           is see if it was the original default and only swap in that case. */
12468
37.9k
        for (k = 0; k < 2; k++) {
12469
25.3k
            gs_color_space *pcs     = pgs->color[k].color_space;
12470
25.3k
            cmm_profile_t  *profile = pcs->cmm_icc_profile_data;
12471
25.3k
            if (profile != NULL) {
12472
25.1k
                switch(profile->data_cs) {
12473
13.2k
                    case gsGRAY:
12474
13.2k
                        if (profile->hashcode ==
12475
13.2k
                            result->profiles->smask_gray->hashcode) {
12476
12.4k
                                profile = pgs->icc_manager->default_gray;
12477
12.4k
                        }
12478
13.2k
                        break;
12479
11.8k
                    case gsRGB:
12480
11.8k
                        if (profile->hashcode ==
12481
11.8k
                            result->profiles->smask_rgb->hashcode) {
12482
4.44k
                                profile = pgs->icc_manager->default_rgb;
12483
4.44k
                        }
12484
11.8k
                        break;
12485
97
                    case gsCMYK:
12486
97
                        if (profile->hashcode ==
12487
97
                            result->profiles->smask_cmyk->hashcode) {
12488
97
                                profile = pgs->icc_manager->default_cmyk;
12489
97
                        }
12490
97
                        break;
12491
0
                    default:
12492
12493
0
                        break;
12494
25.1k
                }
12495
25.1k
                if (pcs->cmm_icc_profile_data != profile) {
12496
17.0k
                    gsicc_adjust_profile_rc(profile, 1, "pdf14_increment_smask_color");
12497
17.0k
                    gsicc_adjust_profile_rc(pcs->cmm_icc_profile_data, -1, "pdf14_increment_smask_color");
12498
17.0k
                    pcs->cmm_icc_profile_data = profile;
12499
17.0k
                }
12500
25.1k
            }
12501
25.3k
        }
12502
12.6k
    }
12503
12.6k
    return 0;
12504
12.6k
}
12505
12506
static int
12507
pdf14_decrement_smask_color(gs_gstate * pgs, gx_device * dev)
12508
15.3k
{
12509
15.3k
    pdf14_device * pdev = (pdf14_device *) dev;
12510
15.3k
    pdf14_smaskcolor_t *smaskcolor = pdev->smaskcolor;
12511
15.3k
    gsicc_manager_t *icc_manager = pgs->icc_manager;
12512
15.3k
    int k;
12513
12514
    /* See comment in pdf14_increment_smask_color to understand this one */
12515
15.3k
    if (pdev->smaskcolor == NULL && pgs->icc_manager->smask_profiles != NULL &&
12516
15.3k
        pgs->icc_manager->smask_profiles->swapped) {
12517
0
            return 0;
12518
0
    }
12519
15.3k
    if (smaskcolor != NULL) {
12520
12.6k
        smaskcolor->ref_count--;
12521
12.6k
        if_debug1m(gs_debug_flag_icc, pgs->memory,
12522
12.6k
                   "[icc] Decrement smask color.  Now %d\n",
12523
12.6k
                   smaskcolor->ref_count);
12524
12.6k
        if (smaskcolor->ref_count == 0) {
12525
12.6k
            if_debug0m(gs_debug_flag_icc, pgs->memory, "[icc] Reset smask color.\n");
12526
            /* Lets return the profiles and clean up */
12527
            /* First see if we need to "reset" the profiles that are in
12528
               the graphic state */
12529
12.6k
            if_debug0m(gs_debug_flag_icc, pgs->memory, "[icc] Reseting graphic state color spaces\n");
12530
37.9k
            for (k = 0; k < 2; k++) {
12531
25.3k
                gs_color_space *pcs = pgs->color[k].color_space;
12532
25.3k
                cmm_profile_t  *profile = pcs->cmm_icc_profile_data;
12533
25.3k
                if (profile != NULL) {
12534
25.1k
                    switch(profile->data_cs) {
12535
13.2k
                        case gsGRAY:
12536
13.2k
                            if (profile->hashcode ==
12537
13.2k
                                pgs->icc_manager->default_gray->hashcode) {
12538
12.4k
                                    profile =
12539
12.4k
                                        smaskcolor->profiles->smask_gray;
12540
12.4k
                            }
12541
13.2k
                            break;
12542
11.8k
                        case gsRGB:
12543
11.8k
                            if (profile->hashcode ==
12544
11.8k
                                pgs->icc_manager->default_rgb->hashcode) {
12545
4.44k
                                    profile =
12546
4.44k
                                        smaskcolor->profiles->smask_rgb;
12547
4.44k
                            }
12548
11.8k
                            break;
12549
97
                        case gsCMYK:
12550
97
                            if (profile->hashcode ==
12551
97
                                pgs->icc_manager->default_cmyk->hashcode) {
12552
97
                                    profile =
12553
97
                                        smaskcolor->profiles->smask_cmyk;
12554
97
                            }
12555
97
                            break;
12556
0
                        default:
12557
12558
0
                            break;
12559
25.1k
                    }
12560
25.1k
                    if (pcs->cmm_icc_profile_data != profile) {
12561
17.0k
                        gsicc_adjust_profile_rc(profile, 1, "pdf14_decrement_smask_color");
12562
17.0k
                        gsicc_adjust_profile_rc(pcs->cmm_icc_profile_data, -1, "pdf14_decrement_smask_color");
12563
17.0k
                        pcs->cmm_icc_profile_data = profile;
12564
17.0k
                    }
12565
25.1k
                }
12566
25.3k
            }
12567
12568
12.6k
            gsicc_adjust_profile_rc(icc_manager->default_gray, -1, "pdf14_decrement_smask_color");
12569
12.6k
            icc_manager->default_gray = smaskcolor->profiles->smask_gray;
12570
12.6k
            gsicc_adjust_profile_rc(icc_manager->default_rgb, -1, "pdf14_decrement_smask_color");
12571
12.6k
            icc_manager->default_rgb = smaskcolor->profiles->smask_rgb;
12572
12.6k
            gsicc_adjust_profile_rc(icc_manager->default_cmyk, -1, "pdf14_decrement_smask_color");
12573
12.6k
            icc_manager->default_cmyk = smaskcolor->profiles->smask_cmyk;
12574
12.6k
            icc_manager->smask_profiles->swapped = false;
12575
            /* We didn't increment the reference count when we assigned these
12576
             * so NULL them to avoid decrementing when smaskcolor is freed
12577
             */
12578
12.6k
            smaskcolor->profiles->smask_gray =
12579
12.6k
              smaskcolor->profiles->smask_rgb =
12580
12.6k
              smaskcolor->profiles->smask_cmyk = NULL;
12581
12582
12.6k
            pdf14_free_smask_color(pdev);
12583
12.6k
        }
12584
12.6k
    }
12585
15.3k
    return 0;
12586
15.3k
}
12587
12588
static void
12589
pdf14_free_smask_color(pdf14_device * pdev)
12590
12.6k
{
12591
12.6k
    if (pdev->smaskcolor != NULL) {
12592
12.6k
        if ( pdev->smaskcolor->profiles != NULL) {
12593
            /* Do not decrement the profiles - the references were moved
12594
               here and moved back again, so the ref counts don't change
12595
             */
12596
12.6k
            gs_free_object(pdev->memory->stable_memory, pdev->smaskcolor->profiles,
12597
12.6k
                        "pdf14_free_smask_color");
12598
12.6k
        }
12599
12.6k
        gs_free_object(pdev->memory->stable_memory, pdev->smaskcolor, "pdf14_free_smask_color");
12600
12.6k
        pdev->smaskcolor = NULL;
12601
12.6k
    }
12602
12.6k
}
12603
12604
static void
12605
pdf14_device_finalize(const gs_memory_t *cmem, void *vptr)
12606
263k
{
12607
263k
    gx_device * const dev = (gx_device *)vptr;
12608
263k
    pdf14_device * pdev = (pdf14_device *)dev;
12609
263k
    int k;
12610
12611
263k
    pdf14_cleanup_group_color_profiles (pdev);
12612
12613
263k
    if (pdev->ctx) {
12614
0
        pdf14_ctx_free(pdev->ctx);
12615
0
        pdev->ctx = NULL;
12616
0
    }
12617
12618
263k
    while (pdev->color_model_stack) {
12619
24
        pdf14_pop_group_color(dev, NULL);
12620
24
    }
12621
12622
263k
    for (k = 0; k < pdev->devn_params.separations.num_separations; k++) {
12623
12
        if (pdev->devn_params.separations.names[k].data) {
12624
12
            gs_free_object(pdev->memory->stable_memory, pdev->devn_params.separations.names[k].data, "pdf14_device_finalize");
12625
12
            pdev->devn_params.separations.names[k].data = NULL;
12626
12
        }
12627
12
    }
12628
12629
263k
    for (k = 0; k < pdev->devn_params.pdf14_separations.num_separations; k++) {
12630
0
        if (pdev->devn_params.pdf14_separations.names[k].data) {
12631
0
            gs_free_object(pdev->memory->stable_memory, pdev->devn_params.pdf14_separations.names[k].data, "pdf14_device_finalize");
12632
0
            pdev->devn_params.pdf14_separations.names[k].data = NULL;
12633
0
        }
12634
0
    }
12635
12636
263k
    gx_device_finalize(cmem, vptr);
12637
263k
}
12638
12639
#if DUMP_MASK_STACK
12640
12641
static void
12642
dump_mask_stack(pdf14_mask_t *mask_stack)
12643
{
12644
    pdf14_mask_t *curr_mask = mask_stack;
12645
    int level = 0;
12646
12647
    while (curr_mask != NULL) {
12648
        if_debug1m('v', curr_mask->memory, "[v]mask_level, %d\n", level);
12649
        if_debug1m('v', curr_mask->memory, "[v]mask_buf, %p\n", curr_mask->rc_mask->mask_buf);
12650
        if_debug1m('v', curr_mask->memory, "[v]rc_count, %ld\n", curr_mask->rc_mask->rc.ref_count);
12651
        level++;
12652
        curr_mask = curr_mask->previous;
12653
    }
12654
}
12655
12656
/* A function to display the current state of the mask stack */
12657
static void
12658
pdf14_debug_mask_stack_state(pdf14_ctx *ctx)
12659
{
12660
    if_debug1m('v', ctx->memory, "[v]ctx_maskstack, %p\n", ctx->mask_stack);
12661
    if (ctx->mask_stack != NULL) {
12662
        dump_mask_stack(ctx->mask_stack);
12663
    }
12664
    if_debug1m('v', ctx->memory, "[v]ctx_stack, %p\n", ctx->stack);
12665
    if (ctx->stack != NULL) {
12666
        if_debug1m('v', ctx->memory, "[v]ctx_stack_maskstack, %p\n", ctx->stack->mask_stack);
12667
        if (ctx->stack->mask_stack != NULL) {
12668
            dump_mask_stack(ctx->stack->mask_stack);
12669
        }
12670
    }
12671
}
12672
12673
#else
12674
12675
#ifdef DEBUG
12676
static void
12677
pdf14_debug_mask_stack_state(pdf14_ctx *ctx)
12678
{
12679
    return;
12680
}
12681
#endif
12682
12683
#endif /* DUMP_MASK_STACK */