Coverage Report

Created: 2022-10-31 07:00

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