Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/devices/vector/gdevpsdp.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2025 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* (Distiller) parameter handling for PostScript and PDF writers */
18
#include "string_.h"
19
#include "jpeglib_.h"   /* for sdct.h */
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gsutil.h"
23
#include "gxdevice.h"
24
#include "gsparamx.h"
25
#include "gdevpsdf.h"
26
#include "sbrotlix.h"
27
#include "strimpl.h"    /* for short-sighted compilers */
28
#include "scfx.h"
29
#include "sdct.h"
30
#include "slzwx.h"
31
#include "srlx.h"
32
#include "szlibx.h"
33
#include "gdevvec.h"
34
35
/* Define a (bogus) GC descriptor for gs_param_string. */
36
/* The only ones we use are GC-able and not persistent. */
37
gs_private_st_composite(st_gs_param_string, gs_param_string, "gs_param_string",
38
                        param_string_enum_ptrs, param_string_reloc_ptrs);
39
static
40
4.33M
ENUM_PTRS_WITH(param_string_enum_ptrs, gs_param_string *pstr) return 0;
41
4.04M
case 0: return ENUM_CONST_STRING(pstr);
42
4.33M
ENUM_PTRS_END
43
static
44
4.04M
RELOC_PTRS_WITH(param_string_reloc_ptrs, gs_param_string *pstr)
45
4.04M
{
46
4.04M
    gs_const_string str;
47
48
4.04M
    str.data = pstr->data, str.size = pstr->size;
49
4.04M
    RELOC_CONST_STRING_VAR(str);
50
4.04M
    pstr->data = str.data;
51
4.04M
}
52
4.04M
RELOC_PTRS_END
53
gs_private_st_element(st_param_string_element, gs_param_string,
54
                      "gs_param_string[]", param_string_elt_enum_ptrs,
55
                      param_string_elt_reloc_ptrs, st_gs_param_string);
56
57
/* ---------------- Get/put Distiller parameters ---------------- */
58
59
/*
60
 * ColorConversionStrategy is supposed to affect output color space
61
 * according to the following table.  ****** NOT IMPLEMENTED YET ******
62
63
PS Input:  LeaveCU UseDIC           UseDICFI         sRGB
64
Gray art   Gray    CalGray/ICCBased Gray             Gray
65
Gray image Gray    CalGray/ICCBased CalGray/ICCBased Gray
66
RGB art    RGB     CalGray/ICCBased RGB              CalRGB/sRGB
67
RGB image  RGB     CalGray/ICCBased CalRGB/ICCBased  CalRGB/sRGB
68
CMYK art   CMYK    LAB/ICCBased     CMYK             CalRGB/sRGB
69
CMYK image CMYK    LAB/ICCBased     LAB/ICCBased     CalRGB/sRGB
70
CIE art    Cal/ICC Cal/ICC          Cal/ICC          CalRGB/sRGB
71
CIE image  Cal/ICC Cal/ICC          Cal/ICC          CalRGB/sRGB
72
73
 */
74
75
/*
76
 * The Always/NeverEmbed parameters are defined as being incremental.  Since
77
 * this isn't compatible with the general property of page devices that if
78
 * you do a currentpagedevice, doing a setpagedevice later will restore the
79
 * same state, we actually define the parameters in sets of 3:
80
 *  - AlwaysEmbed is used for incremental additions.
81
 *  - ~AlwaysEmbed is used for incremental deletions.
82
 *  - .AlwaysEmbed is used for the complete list.
83
 * and analogously for NeverEmbed.
84
 */
85
86
typedef struct psdf_image_filter_name_s {
87
    const char *pname;
88
    const stream_template *templat;
89
    psdf_version min_version;
90
} psdf_image_filter_name;
91
92
static const psdf_image_filter_name Poly_filters[] = {
93
    {"DCTEncode", &s_DCTE_template},
94
    {"FlateEncode", &s_zlibE_template, psdf_version_ll3},
95
    {"LZWEncode", &s_LZWE_template},
96
    {"BrotliEncode", &s_brotliE_template},
97
    {0, 0}
98
};
99
100
static const psdf_image_filter_name Mono_filters[] = {
101
    {"CCITTFaxEncode", &s_CFE_template},
102
    {"FlateEncode", &s_zlibE_template, psdf_version_ll3},
103
    {"LZWEncode", &s_LZWE_template},
104
    {"RunLengthEncode", &s_RLE_template},
105
    {"BrotliEncode", &s_brotliE_template},
106
    {0, 0}
107
};
108
109
typedef struct psdf_image_param_names_s {
110
    const char *ACSDict;  /* not used for mono */
111
    const char *Dict;
112
    const char *DownsampleType;
113
    float DownsampleThreshold_default;
114
    const psdf_image_filter_name *filter_names;
115
    const char *Filter;
116
    const char *AutoFilterStrategy;
117
    gs_param_item_t items[9]; /* AutoFilter (not used for mono), */
118
                                /* AntiAlias, */
119
                                /* Depth, Downsample, DownsampleThreshold, */
120
                                /* Encode, Resolution, AutoFilterStrategy, end marker */
121
} psdf_image_param_names_t;
122
#define pi(key, type, memb) { key, type, offset_of(psdf_image_params, memb) }
123
#define psdf_image_param_names(acs, aa, af, de, di, ds, dt, dst, dstd, e, f, fns, r, afs)\
124
    acs, di, dt, dstd, fns, f, afs, {\
125
      pi(af, gs_param_type_bool, AutoFilter),\
126
      pi(aa, gs_param_type_bool, AntiAlias),\
127
      pi(de, gs_param_type_int, Depth),\
128
      pi(ds, gs_param_type_bool, Downsample),\
129
      pi(dst, gs_param_type_float, DownsampleThreshold),\
130
      pi(e, gs_param_type_bool, Encode),\
131
      pi(r, gs_param_type_int, Resolution),\
132
      gs_param_item_end\
133
    }
134
135
static const psdf_image_param_names_t Color_names = {
136
    psdf_image_param_names(
137
        "ColorACSImageDict", "AntiAliasColorImages", "AutoFilterColorImages",
138
        "ColorImageDepth", "ColorImageDict",
139
        "DownsampleColorImages", "ColorImageDownsampleType",
140
        "ColorImageDownsampleThreshold", 1.5,
141
        "EncodeColorImages", "ColorImageFilter", Poly_filters,
142
        "ColorImageResolution", 0
143
    )
144
};
145
static const psdf_image_param_names_t Gray_names = {
146
    psdf_image_param_names(
147
        "GrayACSImageDict", "AntiAliasGrayImages", "AutoFilterGrayImages",
148
        "GrayImageDepth", "GrayImageDict",
149
        "DownsampleGrayImages", "GrayImageDownsampleType",
150
        "GrayImageDownsampleThreshold", 2.0,
151
        "EncodeGrayImages", "GrayImageFilter", Poly_filters,
152
        "GrayImageResolution", 0
153
    )
154
};
155
static const psdf_image_param_names_t Mono_names = {
156
    psdf_image_param_names(
157
        0, "AntiAliasMonoImages", 0,
158
        "MonoImageDepth", "MonoImageDict",
159
        "DownsampleMonoImages", "MonoImageDownsampleType",
160
        "MonoImageDownsampleThreshold", 2.0,
161
        "EncodeMonoImages", "MonoImageFilter", Mono_filters,
162
        "MonoImageResolution", 0
163
    )
164
};
165
static const psdf_image_param_names_t Color_names15 = {
166
    psdf_image_param_names(
167
        "ColorACSImageDict", "AntiAliasColorImages", "AutoFilterColorImages",
168
        "ColorImageDepth", "ColorImageDict",
169
        "DownsampleColorImages", "ColorImageDownsampleType",
170
        "ColorImageDownsampleThreshold", 1.5,
171
        "EncodeColorImages", "ColorImageFilter", Poly_filters,
172
        "ColorImageResolution", "ColorImageAutoFilterStrategy"
173
    )
174
};
175
static const psdf_image_param_names_t Gray_names15 = {
176
    psdf_image_param_names(
177
        "GrayACSImageDict", "AntiAliasGrayImages", "AutoFilterGrayImages",
178
        "GrayImageDepth", "GrayImageDict",
179
        "DownsampleGrayImages", "GrayImageDownsampleType",
180
        "GrayImageDownsampleThreshold", 2.0,
181
        "EncodeGrayImages", "GrayImageFilter", Poly_filters,
182
        "GrayImageResolution", "GrayImageAutoFilterStrategy"
183
    )
184
};
185
#undef pi
186
static const char *const AutoRotatePages_names[] = {
187
    psdf_arp_names, 0
188
};
189
static const char *const ColorConversionStrategy_names[] = {
190
    psdf_ccs_names, 0
191
};
192
static const char *const DownsampleType_names[] = {
193
    psdf_ds_names, 0
194
};
195
static const char *const AutoFilterStrategy_names[] = {
196
    psdf_afs_names, 0
197
};
198
static const char *const Binding_names[] = {
199
    psdf_binding_names, 0
200
};
201
static const char *const DefaultRenderingIntent_names[] = {
202
    psdf_ri_names, 0
203
};
204
static const char *const TransferFunctionInfo_names[] = {
205
    psdf_tfi_names, 0
206
};
207
static const char *const UCRandBGInfo_names[] = {
208
    psdf_ucrbg_names, 0
209
};
210
static const char *const CannotEmbedFontPolicy_names[] = {
211
    psdf_cefp_names, 0
212
};
213
214
static const gs_param_item_t psdf_param_items[] = {
215
#define pi(key, type, memb) { key, type, offset_of(psdf_distiller_params, memb) }
216
217
    /* General parameters */
218
219
    pi("ASCII85EncodePages", gs_param_type_bool, ASCII85EncodePages),
220
    /* (AutoRotatePages) */
221
    /* (Binding) */
222
    pi("CompressPages", gs_param_type_bool, CompressPages),
223
    /* (DefaultRenderingIntent) */
224
    pi("DetectBlends", gs_param_type_bool, DetectBlends),
225
    pi("DoThumbnails", gs_param_type_bool, DoThumbnails),
226
    pi("ImageMemory", gs_param_type_size_t, ImageMemory),
227
    /* (LockDistillerParams) */
228
    pi("LZWEncodePages", gs_param_type_bool, LZWEncodePages),
229
    pi("OPM", gs_param_type_int, OPM),
230
    pi("PreserveHalftoneInfo", gs_param_type_bool, PreserveHalftoneInfo),
231
    pi("PreserveOPIComments", gs_param_type_bool, PreserveOPIComments),
232
    pi("PreserveOverprintSettings", gs_param_type_bool, PreserveOverprintSettings),
233
    /* (TransferFunctionInfo) */
234
    /* (UCRandBGInfo) */
235
    pi("UseFlateCompression", gs_param_type_bool, UseFlateCompression),
236
    pi("UseBrotliCompression", gs_param_type_bool, UseBrotliCompression),
237
238
    /* Color image processing parameters */
239
240
    pi("ConvertCMYKImagesToRGB", gs_param_type_bool, ConvertCMYKImagesToRGB),
241
    pi("ConvertImagesToIndexed", gs_param_type_bool, ConvertImagesToIndexed),
242
243
    /* Font embedding parameters */
244
245
    /* (CannotEmbedFontPolicy) */
246
    pi("EmbedAllFonts", gs_param_type_bool, EmbedAllFonts),
247
    pi("MaxSubsetPct", gs_param_type_int, MaxSubsetPct),
248
    pi("SubsetFonts", gs_param_type_bool, SubsetFonts),
249
    pi("PassThroughJPEGImages", gs_param_type_bool, PassThroughJPEGImages),
250
    pi("PassThroughJPXImages", gs_param_type_bool, PassThroughJPXImages),
251
    pi("PSPageOptionsWrap", gs_param_type_bool, PSPageOptionsWrap),
252
253
#undef pi
254
    gs_param_item_end
255
};
256
257
/* -------- Get parameters -------- */
258
259
static int
260
psdf_write_name(gs_param_list *plist, const char *key, const char *str)
261
13.0M
{
262
13.0M
    gs_param_string pstr;
263
264
13.0M
    param_string_from_string(pstr, str);
265
13.0M
    return param_write_name(plist, key, &pstr);
266
13.0M
}
267
268
static int
269
psdf_write_string_param(gs_param_list *plist, const char *key,
270
                        const gs_const_string *pstr)
271
3.84M
{
272
3.84M
    gs_param_string ps;
273
274
3.84M
    ps.data = pstr->data;
275
3.84M
    ps.size = pstr->size;
276
3.84M
    ps.persistent = false;
277
3.84M
    return param_write_string(plist, key, &ps);
278
3.84M
}
279
280
/*
281
 * Get an image Dict parameter.  Note that we return a default (empty)
282
 * dictionary if the parameter has never been set.
283
 */
284
static int
285
psdf_get_image_dict_param(gs_param_list * plist, const gs_param_name pname,
286
                          gs_c_param_list *plvalue)
287
5.76M
{
288
5.76M
    gs_param_dict dict;
289
5.76M
    int code;
290
291
5.76M
    if (pname == 0)
292
961k
        return 0;
293
4.80M
    dict.size = 12;   /* enough for all param dicts we know about */
294
4.80M
    if ((code = param_begin_write_dict(plist, pname, &dict, false)) < 0)
295
0
        return code;
296
4.80M
    if (plvalue != 0) {
297
4.12M
        gs_c_param_list_read(plvalue);
298
4.12M
        code = param_list_copy(dict.list, (gs_param_list *)plvalue);
299
4.12M
    }
300
4.80M
    param_end_write_dict(plist, pname, &dict);
301
4.80M
    return code;
302
4.80M
}
303
304
/* Get a set of image-related parameters. */
305
static int
306
psdf_get_image_params(gs_param_list * plist,
307
          const psdf_image_param_names_t * pnames, psdf_image_params * params)
308
2.88M
{
309
    /* Skip AutoFilter for mono images. */
310
2.88M
    const gs_param_item_t *items =
311
2.88M
        (pnames->items[0].key == 0 ? pnames->items + 1 : pnames->items);
312
2.88M
    int code;
313
314
    /*
315
     * We must actually return a value for every parameter, so that
316
     * all parameter names will be recognized as settable by -d or -s
317
     * from the command line.
318
     */
319
2.88M
    code = gs_param_write_items(plist, params, NULL, items);
320
2.88M
    if (code < 0)
321
0
        return code;
322
323
2.88M
    code = psdf_get_image_dict_param(plist, pnames->ACSDict, params->ACSDict);
324
2.88M
    if (code < 0)
325
0
        return code;
326
327
           /* (AntiAlias) */
328
           /* (AutoFilter) */
329
           /* (Depth) */
330
2.88M
    code = psdf_get_image_dict_param(plist, pnames->Dict, params->Dict);
331
2.88M
    if (code < 0)
332
0
        return code;
333
334
           /* (Downsample) */
335
2.88M
    code = psdf_write_name(plist, pnames->DownsampleType,
336
2.88M
                DownsampleType_names[params->DownsampleType]);
337
2.88M
    if (code < 0)
338
0
        return code;
339
340
           /* (DownsampleThreshold) */
341
           /* (Encode) */
342
2.88M
    code = psdf_write_name(plist, pnames->Filter,
343
2.88M
                                   (params->Filter == 0 ?
344
272k
                                    pnames->filter_names[0].pname :
345
2.88M
                                    params->Filter));
346
2.88M
    if (code < 0)
347
0
        return code;
348
349
           /* (Resolution) */
350
2.88M
    if (pnames->AutoFilterStrategy != 0)
351
561k
        code = psdf_write_name(plist, pnames->AutoFilterStrategy,
352
561k
                AutoFilterStrategy_names[params->AutoFilterStrategy]);
353
2.88M
    if (code < 0)
354
0
        return code;
355
356
2.88M
    return code;
357
2.88M
}
358
359
/* Get a font embedding parameter. */
360
static int
361
psdf_get_embed_param(gs_param_list *plist, gs_param_name allpname,
362
                     const gs_param_string_array *psa)
363
3.84M
{
364
3.84M
    int code = param_write_name_array(plist, allpname, psa);
365
366
3.84M
    if (code >= 0)
367
3.84M
        code = param_write_name_array(plist, allpname + 1, psa);
368
3.84M
    return code;
369
3.84M
}
370
371
/* Transfer a collection of parameters. */
372
static const byte xfer_item_sizes[] = {
373
    GS_PARAM_TYPE_SIZES(0)
374
};
375
/* Get parameters. */
376
static
377
int gdev_psdf_get_image_param(gx_device_psdf *pdev, const psdf_image_param_names_t *image_names,
378
                              psdf_image_params * params, char *Param, gs_param_list * plist)
379
148k
{
380
148k
    const gs_param_item_t *pi;
381
148k
    int code;
382
383
841k
    for (pi = image_names->items; pi->key != 0; ++pi) {
384
692k
        if (strcmp(pi->key, Param) == 0) {
385
0
            const char *key = pi->key;
386
0
            const void *pvalue = (const void *)((const char *)params + pi->offset);
387
0
            int size = xfer_item_sizes[pi->type];
388
0
            gs_param_typed_value typed;
389
390
0
            memcpy(&typed.value, pvalue, size);
391
0
            typed.type = pi->type;
392
0
            code = (*plist->procs->xmit_typed) (plist, key, &typed);
393
0
            return code;
394
0
        }
395
692k
    }
396
    /* We only have an ACSDict for color image parameters */
397
148k
    if (image_names->ACSDict) {
398
98.9k
        if (strcmp(Param, image_names->ACSDict) == 0)
399
0
            return psdf_get_image_dict_param(plist, image_names->ACSDict, params->ACSDict);
400
98.9k
    }
401
148k
    if (strcmp(Param, image_names->Dict) == 0)
402
0
        return psdf_get_image_dict_param(plist, image_names->Dict, params->Dict);
403
404
148k
    if (strcmp(Param, image_names->DownsampleType) == 0)
405
0
        return psdf_write_name(plist, image_names->DownsampleType,
406
0
                DownsampleType_names[params->DownsampleType]);
407
148k
    if (strcmp(Param, image_names->Filter) == 0)
408
0
        return psdf_write_name(plist, image_names->Filter,
409
0
                                   (params->Filter == 0 ?
410
0
                                    image_names->filter_names[0].pname :
411
0
                                    params->Filter));
412
148k
    return_error(gs_error_undefined);
413
148k
}
414
int
415
gdev_psdf_get_param(gx_device *dev, char *Param, void *list)
416
303k
{
417
303k
    gx_device_psdf *pdev = (gx_device_psdf *) dev;
418
303k
    const psdf_image_param_names_t *image_names;
419
303k
    const gs_param_item_t *pi;
420
303k
    gs_param_list * plist = (gs_param_list *)list;
421
303k
    int code = 0;
422
423
303k
    code = gdev_vector_get_param(dev, Param, list);
424
303k
    if (code != gs_error_undefined)
425
253k
        return code;
426
427
    /* General parameters first */
428
1.03M
    for (pi = psdf_param_items; pi->key != 0; ++pi) {
429
989k
        if (strcmp(pi->key, Param) == 0) {
430
0
            const char *key = pi->key;
431
0
            const void *pvalue = (const void *)((const char *)&pdev + pi->offset);
432
0
            int size = xfer_item_sizes[pi->type];
433
0
            gs_param_typed_value typed;
434
435
0
            memcpy(&typed.value, pvalue, size);
436
0
            typed.type = pi->type;
437
0
            code = (*plist->procs->xmit_typed) (plist, key, &typed);
438
0
            return code;
439
0
        }
440
989k
    }
441
442
    /* Color image parameters */
443
49.4k
    if (pdev->ParamCompatibilityLevel >= 1.5)
444
9.17k
        image_names = &Color_names15;
445
40.3k
    else
446
40.3k
        image_names = &Color_names;
447
448
49.4k
    code = gdev_psdf_get_image_param(pdev, image_names, &pdev->params.ColorImage, Param, plist);
449
49.4k
    if (code != gs_error_undefined)
450
0
        return code;
451
452
    /* Grey image parameters */
453
49.4k
    if (pdev->ParamCompatibilityLevel >= 1.5)
454
9.17k
        image_names = &Gray_names15;
455
40.3k
    else
456
40.3k
        image_names = &Gray_names;
457
458
49.4k
    code = gdev_psdf_get_image_param(pdev, image_names, &pdev->params.GrayImage, Param, plist);
459
49.4k
    if (code != gs_error_undefined)
460
0
        return code;
461
462
    /* Mono image parameters */
463
49.4k
    code = gdev_psdf_get_image_param(pdev, &Mono_names, &pdev->params.MonoImage, Param, plist);
464
49.4k
    if (code != gs_error_undefined)
465
0
        return code;
466
467
49.4k
    if (strcmp(Param, "AutoRotatePages") == 0) {
468
0
        return(psdf_write_name(plist, "AutoRotatePages",
469
0
                AutoRotatePages_names[(int)pdev->params.AutoRotatePages]));
470
0
    }
471
49.4k
    if (strcmp(Param, "Binding") == 0) {
472
0
        return(psdf_write_name(plist, "Binding",
473
0
                Binding_names[(int)pdev->params.Binding]));
474
0
    }
475
49.4k
    if (strcmp(Param, "DefaultRenderingIntent") == 0) {
476
0
        return(psdf_write_name(plist, "DefaultRenderingIntent",
477
0
                DefaultRenderingIntent_names[(int)pdev->params.DefaultRenderingIntent]));
478
0
    }
479
49.4k
    if (strcmp(Param, "TransferFunctionInfo") == 0) {
480
0
        return(psdf_write_name(plist, "TransferFunctionInfo",
481
0
                TransferFunctionInfo_names[(int)pdev->params.TransferFunctionInfo]));
482
0
    }
483
49.4k
    if (strcmp(Param, "UCRandBGInfo") == 0) {
484
0
        return(psdf_write_name(plist, "UCRandBGInfo",
485
0
                UCRandBGInfo_names[(int)pdev->params.UCRandBGInfo]));
486
0
    }
487
49.4k
    if (strcmp(Param, "ColorConversionStrategy") == 0) {
488
0
        return(psdf_write_name(plist, "ColorConversionStrategy",
489
0
                ColorConversionStrategy_names[(int)pdev->params.ColorConversionStrategy]));
490
0
    }
491
49.4k
    if (strcmp(Param, "CalCMYKProfile") == 0) {
492
0
        return(psdf_write_string_param(plist, "CalCMYKProfile",
493
0
                                        &pdev->params.CalCMYKProfile));
494
0
    }
495
49.4k
    if (strcmp(Param, "CalGrayProfile") == 0) {
496
0
        return(psdf_write_string_param(plist, "CalGrayProfile",
497
0
                                        &pdev->params.CalGrayProfile));
498
0
    }
499
49.4k
    if (strcmp(Param, "CalRGBProfile") == 0) {
500
0
        return(psdf_write_string_param(plist, "CalRGBProfile",
501
0
                                        &pdev->params.CalRGBProfile));
502
0
    }
503
49.4k
    if (strcmp(Param, "sRGBProfile") == 0) {
504
0
        return(psdf_write_string_param(plist, "sRGBProfile",
505
0
                                        &pdev->params.sRGBProfile));
506
0
    }
507
49.4k
    if (strcmp(Param, ".AlwaysOutline") == 0) {
508
0
        return(psdf_get_embed_param(plist, ".AlwaysOutline", &pdev->params.AlwaysOutline));
509
0
    }
510
49.4k
    if (strcmp(Param, ".NeverOutline") == 0) {
511
0
        return(psdf_get_embed_param(plist, ".NeverOutline", &pdev->params.NeverOutline));
512
0
    }
513
49.4k
    if (strcmp(Param, ".AlwaysEmbed") == 0) {
514
0
        return(psdf_get_embed_param(plist, ".AlwaysEmbed", &pdev->params.AlwaysEmbed));
515
0
    }
516
49.4k
    if (strcmp(Param, ".NeverEmbed") == 0) {
517
0
        return(psdf_get_embed_param(plist, ".NeverEmbed", &pdev->params.NeverEmbed));
518
0
    }
519
49.4k
    if (strcmp(Param, "CannotEmbedFontPolicy") == 0) {
520
0
        return(psdf_write_name(plist, "CannotEmbedFontPolicy",
521
0
                CannotEmbedFontPolicy_names[(int)pdev->params.CannotEmbedFontPolicy]));
522
0
    }
523
49.4k
    return_error(gs_error_undefined);
524
49.4k
}
525
526
int
527
gdev_psdf_get_params(gx_device * dev, gs_param_list * plist)
528
961k
{
529
961k
    gx_device_psdf *pdev = (gx_device_psdf *) dev;
530
961k
    int code = gdev_vector_get_params(dev, plist);
531
961k
    if (code < 0)
532
0
        return code;
533
534
961k
    code = gs_param_write_items(plist, &pdev->params, NULL, psdf_param_items);
535
961k
    if (code < 0)
536
0
        return code;
537
538
    /* General parameters */
539
540
961k
    code = psdf_write_name(plist, "AutoRotatePages",
541
961k
                AutoRotatePages_names[(int)pdev->params.AutoRotatePages]);
542
961k
    if (code < 0)
543
0
        return code;
544
545
961k
    code = psdf_write_name(plist, "Binding",
546
961k
                Binding_names[(int)pdev->params.Binding]);
547
961k
    if (code < 0)
548
0
        return code;
549
550
961k
    code = psdf_write_name(plist, "DefaultRenderingIntent",
551
961k
                DefaultRenderingIntent_names[(int)pdev->params.DefaultRenderingIntent]);
552
961k
    if (code < 0)
553
0
        return code;
554
555
961k
    code = psdf_write_name(plist, "TransferFunctionInfo",
556
961k
                TransferFunctionInfo_names[(int)pdev->params.TransferFunctionInfo]);
557
961k
    if (code < 0)
558
0
        return code;
559
560
961k
    code = psdf_write_name(plist, "UCRandBGInfo",
561
961k
                UCRandBGInfo_names[(int)pdev->params.UCRandBGInfo]);
562
961k
    if (code < 0)
563
0
        return code;
564
565
    /* Color sampled image parameters */
566
567
961k
    code = psdf_get_image_params(plist,
568
961k
                        (pdev->ParamCompatibilityLevel >= 1.5 ? &Color_names15 : &Color_names),
569
961k
                        &pdev->params.ColorImage);
570
961k
    if (code < 0)
571
0
        return code;
572
573
961k
    code = psdf_write_name(plist, "ColorConversionStrategy",
574
961k
                ColorConversionStrategy_names[(int)pdev->params.ColorConversionStrategy]);
575
961k
    if (code < 0)
576
0
        return code;
577
578
961k
    code = psdf_write_string_param(plist, "CalCMYKProfile",
579
961k
                                        &pdev->params.CalCMYKProfile);
580
961k
    if (code < 0)
581
0
        return code;
582
583
961k
    code = psdf_write_string_param(plist, "CalGrayProfile",
584
961k
                                        &pdev->params.CalGrayProfile);
585
961k
    if (code < 0)
586
0
        return code;
587
588
961k
    code = psdf_write_string_param(plist, "CalRGBProfile",
589
961k
                                        &pdev->params.CalRGBProfile);
590
961k
    if (code < 0)
591
0
        return code;
592
593
961k
    code = psdf_write_string_param(plist, "sRGBProfile",
594
961k
                                        &pdev->params.sRGBProfile);
595
961k
    if (code < 0)
596
0
        return code;
597
598
    /* Gray sampled image parameters */
599
600
961k
    code = psdf_get_image_params(plist,
601
961k
                        (pdev->ParamCompatibilityLevel >= 1.5 ? &Gray_names15 : &Gray_names),
602
961k
                        &pdev->params.GrayImage);
603
961k
    if (code < 0)
604
0
        return code;
605
606
    /* Mono sampled image parameters */
607
608
961k
    code = psdf_get_image_params(plist, &Mono_names, &pdev->params.MonoImage);
609
961k
    if (code < 0)
610
0
        return code;
611
612
    /* Font outlining parameters */
613
614
961k
    code = psdf_get_embed_param(plist, ".AlwaysOutline", &pdev->params.AlwaysOutline);
615
961k
    if (code < 0)
616
0
        return code;
617
618
961k
    code = psdf_get_embed_param(plist, ".NeverOutline", &pdev->params.NeverOutline);
619
961k
    if (code < 0)
620
0
        return code;
621
622
    /* Font embedding parameters */
623
624
961k
    code = psdf_get_embed_param(plist, ".AlwaysEmbed", &pdev->params.AlwaysEmbed);
625
961k
    if (code < 0)
626
0
        return code;
627
628
961k
    code = psdf_get_embed_param(plist, ".NeverEmbed", &pdev->params.NeverEmbed);
629
961k
    if (code < 0)
630
0
        return code;
631
632
961k
    code = param_write_string_array(plist, "PSPageOptions", &pdev->params.PSPageOptions);
633
961k
    if (code < 0)
634
0
        return code;
635
636
961k
    code = psdf_write_name(plist, "CannotEmbedFontPolicy",
637
961k
                CannotEmbedFontPolicy_names[(int)pdev->params.CannotEmbedFontPolicy]);
638
639
961k
    return code;
640
961k
}
641
642
/* -------- Put parameters -------- */
643
644
extern stream_state_proc_put_params(s_CF_put_params, stream_CF_state);
645
extern stream_state_proc_put_params(s_DCTE_put_params, stream_DCT_state);
646
typedef stream_state_proc_put_params((*ss_put_params_t), stream_state);
647
648
static int
649
psdf_read_string_param(gs_param_list *plist, const char *key,
650
                       gs_const_string *pstr, gs_memory_t *mem, int ecode)
651
2.92M
{
652
2.92M
    gs_param_string ps;
653
2.92M
    int code;
654
655
2.92M
    switch (code = param_read_string(plist, key, &ps)) {
656
736k
    case 0: {
657
736k
        uint size = ps.size;
658
736k
        byte *data = gs_alloc_string(mem, size, "psdf_read_string_param");
659
660
736k
        if (data == 0)
661
0
            return_error(gs_error_VMerror);
662
736k
        memcpy(data, ps.data, size);
663
736k
        pstr->data = data;
664
736k
        pstr->size = size;
665
736k
        break;
666
736k
    }
667
0
    default:
668
0
        ecode = code;
669
2.19M
    case 1:
670
2.19M
        break;
671
2.92M
    }
672
2.92M
    return ecode;
673
2.92M
}
674
675
/*
676
 * The arguments and return value for psdf_put_enum are different because
677
 * we must cast the value both going in and coming out.
678
 */
679
static int
680
psdf_put_enum(gs_param_list *plist, const char *key, int value,
681
              const char *const pnames[], int *pecode)
682
5.85M
{
683
5.85M
    *pecode = param_put_enum(plist, key, &value, pnames, *pecode);
684
5.85M
    return value;
685
5.85M
}
686
687
static int
688
psdf_CF_put_params(gs_param_list * plist, stream_state * st)
689
0
{
690
0
    stream_CFE_state *const ss = (stream_CFE_state *) st;
691
692
0
    (*s_CFE_template.set_defaults) (st);
693
0
    ss->K = -1;
694
0
    ss->BlackIs1 = true;
695
0
    return s_CF_put_params(plist, (stream_CF_state *) ss);
696
0
}
697
698
static int
699
psdf_DCT_put_params(gs_param_list * plist, stream_state * st)
700
0
{
701
0
    return psdf_DCT_filter(plist, st, 8 /*nominal*/, 8 /*ibid.*/, 3 /*ibid.*/,
702
0
                           NULL);
703
0
}
704
705
/* Put [~](Always|Never)Embed parameters. */
706
/* Returns 0 = OK, 1 = no paramewter specified, <0 = error. */
707
static int
708
param_read_embed_array(gs_param_list * plist, gs_param_name pname,
709
                       gs_param_string_array * psa)
710
7.61M
{
711
7.61M
    int code;
712
713
7.61M
    psa->data = 0, psa->size = 0;
714
7.61M
    switch (code = param_read_name_array(plist, pname, psa)) {
715
0
        default:
716
0
            param_signal_error(plist, pname, code);
717
519k
        case 0:
718
7.61M
        case 1:
719
7.61M
            break;
720
7.61M
    }
721
7.61M
    return code;
722
7.61M
}
723
static bool
724
param_string_eq(const gs_param_string *ps1, const gs_param_string *ps2)
725
13.2M
{
726
13.2M
    return !bytes_compare(ps1->data, ps1->size, ps2->data, ps2->size);
727
13.2M
}
728
static int
729
add_embed(gs_param_string_array *prsa, const gs_param_string_array *psa,
730
          gs_memory_t *mem)
731
144k
{
732
144k
    uint i;
733
144k
    gs_param_string *const rdata =
734
144k
        (gs_param_string *)prsa->data; /* break const */
735
144k
    uint count = prsa->size;
736
737
2.16M
    for (i = 0; i < psa->size; ++i) {
738
2.01M
        uint j;
739
740
15.1M
        for (j = 0; j < count; ++j)
741
13.1M
            if (param_string_eq(&psa->data[i], &rdata[j]))
742
89.9k
                    break;
743
2.01M
        if (j == count) {
744
1.92M
            uint size = psa->data[i].size;
745
1.92M
            byte *data = gs_alloc_string(mem, size, "add_embed");
746
747
1.92M
            if (data == 0)
748
0
                return_error(gs_error_VMerror);
749
1.92M
            memcpy(data, psa->data[i].data, size);
750
1.92M
            rdata[count].data = data;
751
1.92M
            rdata[count].size = size;
752
1.92M
            rdata[count].persistent = false;
753
1.92M
            count++;
754
1.92M
        }
755
2.01M
    }
756
144k
    prsa->size = count;
757
144k
    return 0;
758
144k
}
759
static void
760
delete_embed(gs_param_string_array *prsa, const gs_param_string_array *pnsa,
761
             gs_memory_t *mem)
762
137k
{
763
137k
    uint i;
764
137k
    gs_param_string *const rdata =
765
137k
        (gs_param_string *)prsa->data; /* break const */
766
137k
    uint count = prsa->size;
767
768
137k
    for (i = pnsa->size; i-- > 0;) {
769
0
        uint j;
770
771
0
        for (j = count; j-- > 0;)
772
0
            if (param_string_eq(&pnsa->data[i], &rdata[j]))
773
0
                break;
774
0
        if (j + 1 != 0) {
775
0
            gs_free_const_string(mem, rdata[j].data, rdata[j].size,
776
0
                                 "delete_embed");
777
0
            rdata[j] = rdata[--count];
778
0
        }
779
0
    }
780
137k
    prsa->size = count;
781
137k
}
782
static int merge_embed(gs_param_string_array * psa, gs_param_string_array * asa,
783
                     gs_memory_t *mem)
784
144k
{
785
144k
    gs_param_string_array rsa;
786
144k
    gs_param_string *rdata;
787
144k
    int code;
788
789
144k
    rdata = gs_alloc_struct_array(mem, psa->size + asa->size,
790
144k
                                  gs_param_string,
791
144k
                                  &st_param_string_element,
792
144k
                                  "psdf_put_embed_param(update)");
793
144k
    if (rdata == 0)
794
0
        return_error(gs_error_VMerror);
795
144k
    if (psa->size > 0)
796
6.42k
        memcpy(rdata, psa->data, psa->size * sizeof(*psa->data));
797
144k
    rsa.data = rdata;
798
144k
    rsa.size = psa->size;
799
144k
    rsa.persistent = false;
800
144k
    code = add_embed(&rsa, asa, mem);
801
144k
    if (code < 0) {
802
0
        gs_free_object(mem, rdata, "psdf_put_embed_param(update)");
803
0
        return code;
804
0
    }
805
144k
    gs_free_const_object(mem, psa->data, "psdf_put_embed_param(free)");
806
144k
    *psa = rsa;
807
144k
    return 0;
808
144k
}
809
810
static int
811
psdf_put_embed_param(gs_param_list * plist, gs_param_name notpname,
812
                     gs_param_name pname, gs_param_string_array * psa,
813
                     gs_memory_t *mem, int ecode)
814
2.34M
{
815
2.34M
    gs_param_name allpname = pname + 1;
816
2.34M
    gs_param_string_array sa, nsa, asa;
817
2.34M
    int code;
818
819
2.34M
    mem = gs_memory_stable(mem);
820
2.34M
    code  = param_read_embed_array(plist, pname, &sa);
821
2.34M
    if (code < 0)
822
0
        return code;
823
2.34M
    if (code == 0) {
824
        /* Optimize for sa == *psa. */
825
411k
        int i;
826
827
411k
        if (sa.size == psa->size) {
828
363k
            for (i = 0; i < sa.size; ++i) {
829
89.9k
                if (!param_string_eq(&sa.data[i], &psa->data[i]))
830
0
                    break;
831
89.9k
     }
832
273k
        } else
833
137k
            i = -1;
834
411k
        if (i == sa.size) {
835
            /* equal, no-op. */
836
273k
        } else {
837
137k
            delete_embed(psa, psa, mem);
838
137k
            code = merge_embed(psa, &sa, mem);
839
137k
            if (code < 0)
840
0
                return code;
841
137k
        }
842
411k
    }
843
2.34M
    code = param_read_embed_array(plist, notpname, &nsa);
844
2.34M
    if (code < 0)
845
0
        return code;
846
2.34M
    if (nsa.data != 0)
847
0
        delete_embed(psa, &nsa, mem);
848
2.34M
    code = param_read_embed_array(plist, allpname, &asa);
849
2.34M
    if (code < 0)
850
0
        return code;
851
2.34M
    if (asa.data != 0) {
852
6.42k
        code = merge_embed(psa, &asa, mem);
853
6.42k
        if (code < 0)
854
0
            return code;
855
6.42k
    }
856
2.34M
    if (psa->data)
857
332k
        psa->data = gs_resize_object(mem, (gs_param_string *)psa->data, psa->size,
858
2.34M
                                        "psdf_put_embed_param(resize)");
859
2.34M
    return 0;
860
2.34M
}
861
862
/* Put an image Dict parameter. */
863
static int
864
psdf_put_image_dict_param(gs_param_list * plist, const gs_param_name pname,
865
                          gs_c_param_list **pplvalue,
866
                          const stream_template * templat,
867
                          ss_put_params_t put_params, gs_memory_t * mem)
868
2.92M
{
869
2.92M
    gs_param_dict dict;
870
2.92M
    gs_c_param_list *plvalue = *pplvalue;
871
2.92M
    int code;
872
873
2.92M
    mem = gs_memory_stable(mem);
874
2.92M
    switch (code = param_begin_read_dict(plist, pname, &dict, false)) {
875
0
        default:
876
0
            param_signal_error(plist, pname, code);
877
0
            return code;
878
2.00M
        case 1:
879
2.00M
            return 0;
880
920k
        case 0: {
881
920k
            plvalue = gs_c_param_list_alloc(mem, pname);
882
920k
            if (plvalue == 0)
883
0
                return_error(gs_error_VMerror);
884
920k
            gs_c_param_list_write(plvalue, mem);
885
920k
            code = param_list_copy((gs_param_list *)plvalue,
886
920k
                                   dict.list);
887
920k
            if (code < 0) {
888
0
                gs_c_param_list_release(plvalue);
889
0
                gs_free_object(mem, plvalue, pname);
890
0
                plvalue = *pplvalue;
891
0
            }
892
920k
        }
893
920k
        param_end_read_dict(plist, pname, &dict);
894
920k
        break;
895
2.92M
    }
896
920k
    if (plvalue != *pplvalue) {
897
920k
        if (*pplvalue)
898
108k
            gs_c_param_list_release(*pplvalue);
899
920k
        *pplvalue = plvalue;
900
920k
    }
901
920k
    return code;
902
2.92M
}
903
904
/* Put a set of image-related parameters. */
905
static int
906
psdf_put_image_params(const gx_device_psdf * pdev, gs_param_list * plist,
907
                      const psdf_image_param_names_t * pnames,
908
                      psdf_image_params * params, int ecode)
909
1.75M
{
910
1.75M
    gs_param_string fs;
911
    /*
912
     * Since this procedure can be called before the device is open,
913
     * we must use pdev->memory rather than pdev->v_memory.
914
     */
915
1.75M
    gs_memory_t *mem = gs_memory_stable(pdev->memory);
916
1.75M
    gs_param_name pname;
917
    /* Skip AutoFilter for mono images. */
918
1.75M
    const gs_param_item_t *items =
919
1.75M
        (pnames->items[0].key == 0 ? pnames->items + 1 : pnames->items);
920
1.75M
    int code = gs_param_read_items(plist, params, items, mem);
921
1.75M
    if (code < 0)
922
0
        ecode = code;
923
924
1.75M
    if ((pname = pnames->ACSDict) != 0) {
925
1.17M
        code = psdf_put_image_dict_param(plist, pname, &params->ACSDict,
926
1.17M
                                         &s_DCTE_template,
927
1.17M
                                         psdf_DCT_put_params, mem);
928
1.17M
        if (code < 0)
929
0
            ecode = code;
930
1.17M
    }
931
    /* (AntiAlias) */
932
    /* (AutoFilter) */
933
    /* (Depth) */
934
1.75M
    if ((pname = pnames->Dict) != 0) {
935
1.75M
        const stream_template *templat;
936
1.75M
        ss_put_params_t put_params;
937
938
        /* Hack to determine what kind of a Dict we want: */
939
1.75M
        if (pnames->Dict[0] == 'M')
940
585k
            templat = &s_CFE_template,
941
585k
                put_params = psdf_CF_put_params;
942
1.17M
        else
943
1.17M
            templat = &s_DCTE_template,
944
1.17M
                put_params = psdf_DCT_put_params;
945
1.75M
        code = psdf_put_image_dict_param(plist, pname, &params->Dict,
946
1.75M
                                         templat, put_params, mem);
947
1.75M
        if (code < 0)
948
0
            ecode = code;
949
1.75M
    }
950
    /* (Downsample) */
951
1.75M
    params->DownsampleType = (enum psdf_downsample_type)
952
1.75M
        psdf_put_enum(plist, pnames->DownsampleType,
953
1.75M
                      (int)params->DownsampleType, DownsampleType_names,
954
1.75M
                      &ecode);
955
    /* (DownsampleThreshold) */
956
    /* (Encode) */
957
    /* Process AutoFilterStrategy before Filter, because it sets defaults
958
       for the latter. */
959
1.75M
    if (pnames->AutoFilterStrategy != NULL) {
960
701k
        switch (code = param_read_string(plist, pnames->AutoFilterStrategy, &fs)) {
961
12.8k
            case 0:
962
12.8k
                {
963
12.8k
                    const psdf_image_filter_name *pn = pnames->filter_names;
964
12.8k
                    const char *param_name = 0;
965
966
12.8k
                    if (gs_param_string_eq(&fs, "JPEG")) {
967
12.8k
                        params->AutoFilterStrategy = af_Jpeg;
968
12.8k
                        param_name = "DCTEncode";
969
12.8k
                    } else {
970
0
                        if (gs_param_string_eq(&fs, "JPEG2000")) {
971
0
                            params->AutoFilterStrategy = af_Jpeg2000;
972
0
                            param_name = "JPXEncode";
973
0
                        } else {
974
0
                            ecode = gs_error_rangecheck;
975
0
                            goto ipe1;
976
0
                        }
977
0
                    }
978
64.2k
                    while (pn->pname != 0 && !gs_param_string_eq(&fs, param_name))
979
51.4k
                        pn++;
980
12.8k
                    if (pn->pname != 0 && pn->min_version <= pdev->version) {
981
0
                        params->Filter = pn->pname;
982
0
                        params->filter_template = pn->templat;
983
0
                    }
984
12.8k
                    break;
985
12.8k
                }
986
0
            default:
987
0
                ecode = code;
988
0
            ipe1:param_signal_error(plist, pnames->AutoFilterStrategy, ecode);
989
688k
            case 1:
990
688k
                break;
991
701k
        }
992
701k
    }
993
994
1.75M
    switch (code = param_read_string(plist, pnames->Filter, &fs)) {
995
552k
        case 0:
996
552k
            {
997
552k
                const psdf_image_filter_name *pn = pnames->filter_names;
998
999
552k
                while (pn->pname != 0 && !gs_param_string_eq(&fs, pn->pname))
1000
0
                    pn++;
1001
552k
                if (pn->pname == 0 || pn->min_version > pdev->version) {
1002
0
                    ecode = gs_error_rangecheck;
1003
0
                    goto ipe;
1004
0
                }
1005
552k
                params->Filter = pn->pname;
1006
552k
                params->filter_template = pn->templat;
1007
552k
                break;
1008
552k
            }
1009
0
        default:
1010
0
            ecode = code;
1011
0
          ipe:param_signal_error(plist, pnames->Filter, ecode);
1012
1.20M
        case 1:
1013
1.20M
            break;
1014
1.75M
    }
1015
    /* (Resolution) */
1016
1.75M
    if (ecode >= 0) {   /* Force parameters to acceptable values. */
1017
1.75M
        if (params->Resolution < 1)
1018
0
            params->Resolution = 1;
1019
1.75M
        if (params->DownsampleThreshold < 1 ||
1020
1.75M
            params->DownsampleThreshold > 10)
1021
0
            params->DownsampleThreshold = pnames->DownsampleThreshold_default;
1022
1.75M
        switch (params->Depth) {
1023
0
            default:
1024
0
                params->Depth = -1;
1025
0
            case 1:
1026
0
            case 2:
1027
0
            case 4:
1028
0
            case 8:
1029
1.75M
            case -1:
1030
1.75M
                break;
1031
1.75M
        }
1032
1.75M
    }
1033
1.75M
    return ecode;
1034
1.75M
}
1035
1036
/* This is a convenience routine. There doesn't seem to be any way to have a param_string_array
1037
 * enumerated for garbage collection, and we have (currently) three members of the psdf_distiller_params
1038
 * structure which store param_string_array. If the interpreter is using garbage collection then there
1039
 * is the potential for the array, or its contents, to be relocated or freed while we are still
1040
 * maintaining pointers to them, unless we enumerate the pointers.
1041
 * Instead, we'll copy the string data from the interpreter, make our own param_string_array, and
1042
 * manage the memory ourselves. This allows us to move the data into non-GC memory which is preferable
1043
 * anyway.
1044
 */
1045
static int psdf_copy_param_string_array(gs_memory_t *mem, gs_param_list * plist, gs_param_string_array *sa, gs_param_string_array *da)
1046
0
{
1047
0
    if (sa->size > 0) {
1048
0
        int ix;
1049
1050
0
        if (da->data != NULL) {
1051
0
            for (ix = 0; ix < da->size;ix++)
1052
0
                gs_free_object(mem->non_gc_memory, (byte *)da->data[ix].data, "freeing old string array copy");
1053
0
            gs_free_object(mem->non_gc_memory, (byte *)da->data, "freeing old string array");
1054
0
        }
1055
0
        da->data = (const gs_param_string *)gs_alloc_bytes(mem->non_gc_memory, sa->size * sizeof(gs_param_string), "allocate new string array");
1056
0
        if (da->data == NULL)
1057
0
            return_error(gs_note_error(gs_error_VMerror));
1058
0
        memset((byte *)da->data, 0x00, sa->size * sizeof(gs_param_string));
1059
0
        da->size = sa->size;
1060
0
        da->persistent = false;
1061
1062
0
        for(ix=0;ix < sa->size;ix++) {
1063
0
            ((gs_param_string *)&da->data[ix])->data = gs_alloc_bytes(mem->non_gc_memory, sa->data[ix].size, "allocate new strings");
1064
0
            if (da->data[ix].data == NULL)
1065
0
                return_error(gs_note_error(gs_error_VMerror));
1066
0
            memcpy((byte *)(da->data[ix].data), sa->data[ix].data, sa->data[ix].size);
1067
0
            ((gs_param_string *)&da->data[ix])->size = sa->data[ix].size;
1068
0
            ((gs_param_string *)&da->data[ix])->persistent = false;
1069
0
        }
1070
0
        gs_free_object(plist->memory, (byte *)sa->data, "freeing temporary param string array");
1071
0
        sa->data = NULL;
1072
0
        sa->size = 0;
1073
0
    }
1074
0
    return 0;
1075
0
}
1076
1077
static int psdf_read_copy_param_string_array(gs_memory_t *mem, gs_param_list * plist, const char *Key, gs_param_string_array *da)
1078
585k
{
1079
585k
    gs_param_string_array sa;
1080
585k
    int code;
1081
1082
585k
    code  = param_read_embed_array(plist, Key, &sa);
1083
585k
    if (code < 0)
1084
0
        return code;
1085
1086
585k
    if(sa.size)
1087
0
        code = psdf_copy_param_string_array(mem, plist, &sa, da);
1088
1089
585k
    return code;
1090
585k
}
1091
1092
/* Put parameters. */
1093
int
1094
gdev_psdf_put_params(gx_device * dev, gs_param_list * plist)
1095
585k
{
1096
585k
    gx_device_psdf *pdev = (gx_device_psdf *) dev;
1097
585k
    gs_memory_t *mem =
1098
585k
        (pdev->v_memory ? pdev->v_memory : dev->memory);
1099
585k
    int ecode, code = 0;
1100
585k
    psdf_distiller_params params;
1101
1102
585k
    params = pdev->params;
1103
1104
    /*
1105
     * If LockDistillerParams was true and isn't being set to false,
1106
     * ignore all other psdf parameters.  However, do not ignore the
1107
     * standard device parameters.
1108
     */
1109
585k
    ecode = code = param_read_bool(plist, "LockDistillerParams",
1110
585k
                                   &params.LockDistillerParams);
1111
1112
585k
    if ((pdev->params.LockDistillerParams && params.LockDistillerParams)) {
1113
        /* If we are not going to use the parameters we must still read them
1114
         * in order to use up all the keys, otherwise, if we are being called
1115
         * from .installpagedevice, it will error out on unconsumed keys. We
1116
         * use a dummy params structure to read into, but we must make sure any
1117
         * pointers are not copied from the real params structure, or they get
1118
         * overwritten.
1119
         */
1120
0
        params.CalCMYKProfile.size = params.CalGrayProfile.size = params.CalRGBProfile.size = params.sRGBProfile.size = 0;
1121
0
        params.CalCMYKProfile.data = 0;params.CalGrayProfile.data = params.CalRGBProfile.data = params.sRGBProfile.data = (byte *)0;
1122
1123
0
        params.ColorImage.ACSDict = params.ColorImage.Dict = 0;
1124
0
        params.GrayImage.ACSDict = params.GrayImage.Dict = 0;
1125
0
        params.MonoImage.ACSDict = params.MonoImage.Dict = 0;
1126
0
        params.AlwaysOutline.data = params.NeverOutline.data = NULL;
1127
0
        params.AlwaysOutline.size = params.NeverOutline.size = 0;
1128
0
        params.AlwaysEmbed.data = params.NeverEmbed.data = 0;
1129
0
        params.AlwaysEmbed.size = params.AlwaysEmbed.persistent = params.NeverEmbed.size = params.NeverEmbed.persistent = 0;
1130
0
        params.PSPageOptions.data = NULL;
1131
0
        params.PSPageOptions.size = 0;
1132
0
    }
1133
1134
    /* General parameters. */
1135
1136
585k
    code = gs_param_read_items(plist, &params, psdf_param_items, NULL);
1137
585k
    if (code < 0)
1138
0
        return code;
1139
1140
585k
    params.AutoRotatePages = (enum psdf_auto_rotate_pages)
1141
585k
        psdf_put_enum(plist, "AutoRotatePages", (int)params.AutoRotatePages,
1142
585k
                      AutoRotatePages_names, &ecode);
1143
585k
    if (ecode < 0) {
1144
0
        code = ecode;
1145
0
        goto exit;
1146
0
    }
1147
1148
585k
    params.Binding = (enum psdf_binding)
1149
585k
        psdf_put_enum(plist, "Binding", (int)params.Binding,
1150
585k
                      Binding_names, &ecode);
1151
585k
    if (ecode < 0) {
1152
0
        code = ecode;
1153
0
        goto exit;
1154
0
    }
1155
1156
585k
    params.DefaultRenderingIntent = (enum psdf_default_rendering_intent)
1157
585k
        psdf_put_enum(plist, "DefaultRenderingIntent",
1158
585k
                      (int)params.DefaultRenderingIntent,
1159
585k
                      DefaultRenderingIntent_names, &ecode);
1160
585k
    if (ecode < 0) {
1161
0
        code = ecode;
1162
0
        goto exit;
1163
0
    }
1164
1165
585k
    params.TransferFunctionInfo = (enum psdf_transfer_function_info)
1166
585k
        psdf_put_enum(plist, "TransferFunctionInfo",
1167
585k
                      (int)params.TransferFunctionInfo,
1168
585k
                      TransferFunctionInfo_names, &ecode);
1169
585k
    if (ecode < 0) {
1170
0
        code = ecode;
1171
0
        goto exit;
1172
0
    }
1173
1174
585k
    params.UCRandBGInfo = (enum psdf_ucr_and_bg_info)
1175
585k
        psdf_put_enum(plist, "UCRandBGInfo", (int)params.UCRandBGInfo,
1176
585k
                      UCRandBGInfo_names, &ecode);
1177
585k
    if (ecode < 0) {
1178
0
        code = ecode;
1179
0
        goto exit;
1180
0
    }
1181
1182
585k
    ecode = param_put_bool(plist, "UseFlateCompression",
1183
585k
                           &params.UseFlateCompression, ecode);
1184
1185
    /* Color sampled image parameters */
1186
1187
585k
    ecode = psdf_put_image_params(pdev, plist,
1188
585k
                    (pdev->ParamCompatibilityLevel >= 1.5 ? &Color_names15 : &Color_names),
1189
585k
                                  &params.ColorImage, ecode);
1190
585k
    if (ecode < 0) {
1191
0
        code = ecode;
1192
0
        goto exit;
1193
0
    }
1194
1195
585k
    params.ColorConversionStrategy = (enum psdf_color_conversion_strategy)
1196
585k
        psdf_put_enum(plist, "ColorConversionStrategy",
1197
585k
                      (int)params.ColorConversionStrategy,
1198
585k
                      ColorConversionStrategy_names, &ecode);
1199
585k
    if (ecode < 0) {
1200
0
        code = ecode;
1201
0
        goto exit;
1202
0
    }
1203
1204
585k
    ecode = psdf_read_string_param(plist, "CalCMYKProfile",
1205
585k
                                   &params.CalCMYKProfile, mem, ecode);
1206
585k
    ecode = psdf_read_string_param(plist, "CalGrayProfile",
1207
585k
                                   &params.CalGrayProfile, mem, ecode);
1208
585k
    ecode = psdf_read_string_param(plist, "CalRGBProfile",
1209
585k
                                   &params.CalRGBProfile, mem, ecode);
1210
585k
    ecode = psdf_read_string_param(plist, "sRGBProfile",
1211
585k
                                   &params.sRGBProfile, mem, ecode);
1212
1213
    /* Gray sampled image parameters */
1214
1215
585k
    ecode = psdf_put_image_params(pdev, plist,
1216
585k
                    (pdev->ParamCompatibilityLevel >= 1.5 ? &Gray_names15 : &Gray_names),
1217
585k
                                  &params.GrayImage, ecode);
1218
585k
    if (ecode < 0) {
1219
0
        code = ecode;
1220
0
        goto exit;
1221
0
    }
1222
1223
1224
    /* Mono sampled image parameters */
1225
1226
585k
    ecode = psdf_put_image_params(pdev, plist, &Mono_names,
1227
585k
                                  &params.MonoImage, ecode);
1228
1229
585k
    if (ecode < 0) {
1230
0
        code = ecode;
1231
0
        goto exit;
1232
0
    }
1233
1234
    /* Font outlining parameters */
1235
1236
585k
    ecode = psdf_put_embed_param(plist, "~AlwaysOutline", ".AlwaysOutline",
1237
585k
                                 &params.AlwaysOutline, mem, ecode);
1238
585k
    ecode = psdf_put_embed_param(plist, "~NeverOutline", ".NeverOutline",
1239
585k
                                 &params.NeverOutline, mem, ecode);
1240
1241
585k
    if (ecode < 0) {
1242
0
        code = ecode;
1243
0
        goto exit;
1244
0
    }
1245
1246
    /* Font embedding parameters */
1247
1248
585k
    ecode = psdf_put_embed_param(plist, "~AlwaysEmbed", ".AlwaysEmbed",
1249
585k
                                 &params.AlwaysEmbed, mem, ecode);
1250
585k
    ecode = psdf_put_embed_param(plist, "~NeverEmbed", ".NeverEmbed",
1251
585k
                                 &params.NeverEmbed, mem, ecode);
1252
1253
585k
    params.CannotEmbedFontPolicy = (enum psdf_cannot_embed_font_policy)
1254
585k
        psdf_put_enum(plist, "CannotEmbedFontPolicy",
1255
585k
                      (int)params.CannotEmbedFontPolicy,
1256
585k
                      CannotEmbedFontPolicy_names, &ecode);
1257
585k
    if (ecode < 0) {
1258
0
        code = ecode;
1259
0
        goto exit;
1260
0
    }
1261
1262
    /* ps2write-specific output configuration options */
1263
585k
    code = psdf_read_string_param(plist, "PSDocOptions",
1264
585k
                                   (gs_const_string *)&params.PSDocOptions, mem, ecode);
1265
585k
    if (code < 0)
1266
0
        goto exit;
1267
1268
585k
    params.PSPageOptions.size = 0;
1269
585k
    params.PSPageOptions.data = NULL;
1270
585k
    code = psdf_read_copy_param_string_array(pdev->memory, plist, "PSPageOptions", &params.PSPageOptions);
1271
585k
    if (code < 0)
1272
0
        goto exit;
1273
1274
585k
    code = gdev_vector_put_params(dev, plist);
1275
1276
585k
exit:
1277
585k
    if (!(pdev->params.LockDistillerParams && params.LockDistillerParams)) {
1278
        /* Only update the device paramters if there was no error */
1279
        /* Do not permit changes to pdev->Params.PSPageOptions, it doesn't make any sense */
1280
585k
        if (pdev->params.PSPageOptions.size != 0) {
1281
0
            if (params.PSPageOptions.size != 0 && params.PSPageOptions.data != pdev->params.PSPageOptions.data) {
1282
0
                int ix;
1283
1284
0
                for (ix = 0; ix < pdev->params.PSPageOptions.size;ix++)
1285
0
                    gs_free_object(mem->non_gc_memory, (byte *)params.PSPageOptions.data[ix].data, "freeing old string array copy");
1286
0
                gs_free_object(mem->non_gc_memory, (byte *)params.PSPageOptions.data, "freeing old string array");
1287
0
            }
1288
0
            params.PSPageOptions.data = pdev->params.PSPageOptions.data;
1289
0
            params.PSPageOptions.size = pdev->params.PSPageOptions.size;
1290
0
        }
1291
585k
        pdev->params = params;
1292
585k
    } else {
1293
        /* We read a bunch of parameters and are now throwing them away. Either because there
1294
         * was an error, or because the parameters were locked. We need to tidy up any memory
1295
         * we allocated to hold these parameters.
1296
         */
1297
0
        gs_memory_t *stable_mem = gs_memory_stable(mem);
1298
1299
0
        if (params.PSPageOptions.data != NULL) {
1300
0
            int ix;
1301
1302
0
            if (params.PSPageOptions.size != 0 && params.PSPageOptions.data != pdev->params.PSPageOptions.data) {
1303
0
                for (ix = 0; ix < params.PSPageOptions.size;ix++)
1304
0
                    gs_free_object(mem->non_gc_memory, (byte *)params.PSPageOptions.data[ix].data, "freeing dummy PSPageOptions");
1305
0
                gs_free_object(mem->non_gc_memory, (byte *)params.PSPageOptions.data, "freeing dummy PSPageOptions");
1306
0
            }
1307
0
            params.PSPageOptions.data = NULL;
1308
0
            params.PSPageOptions.size = 0;
1309
0
        }
1310
0
        if (params.CalCMYKProfile.data != 0)
1311
0
            gs_free_string(stable_mem, (void *)params.CalCMYKProfile.data, params.CalCMYKProfile.size, "free dummy param CalCMYKProfile");
1312
0
        if (params.CalGrayProfile.data != 0)
1313
0
            gs_free_string(stable_mem, (void *)params.CalGrayProfile.data, params.CalGrayProfile.size, "free dummy param CalGrayProfile");
1314
0
        if (params.CalRGBProfile.data != 0)
1315
0
            gs_free_string(stable_mem, (void *)params.CalRGBProfile.data, params.CalRGBProfile.size, "free dummy param CalRGBProfile");
1316
0
        if (params.sRGBProfile.data != 0)
1317
0
            gs_free_string(stable_mem, (void *)params.sRGBProfile.data, params.sRGBProfile.size, "free dummy param sRGBProfile");
1318
0
        if (params.ColorImage.ACSDict)
1319
0
            gs_c_param_list_release(params.ColorImage.ACSDict);
1320
0
        if (params.ColorImage.Dict)
1321
0
            gs_c_param_list_release(params.ColorImage.Dict);
1322
0
        if (params.GrayImage.ACSDict)
1323
0
            gs_c_param_list_release(params.GrayImage.ACSDict);
1324
0
        if (params.GrayImage.Dict)
1325
0
            gs_c_param_list_release(params.GrayImage.Dict);
1326
0
        if (params.MonoImage.ACSDict)
1327
0
            gs_c_param_list_release(params.MonoImage.ACSDict);
1328
0
        if (params.MonoImage.Dict)
1329
0
            gs_c_param_list_release(params.MonoImage.Dict);
1330
0
    }
1331
585k
    return code;
1332
585k
}