Coverage Report

Created: 2026-04-01 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/devices/vector/gdevpsdp.c
Line
Count
Source
1
/* Copyright (C) 2001-2026 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.93M
ENUM_PTRS_WITH(param_string_enum_ptrs, gs_param_string *pstr) return 0;
41
4.60M
case 0: return ENUM_CONST_STRING(pstr);
42
4.93M
ENUM_PTRS_END
43
static
44
4.60M
RELOC_PTRS_WITH(param_string_reloc_ptrs, gs_param_string *pstr)
45
4.60M
{
46
4.60M
    gs_const_string str;
47
48
4.60M
    str.data = pstr->data, str.size = pstr->size;
49
4.60M
    RELOC_CONST_STRING_VAR(str);
50
4.60M
    pstr->data = str.data;
51
4.60M
}
52
4.60M
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 BlendConversionStrategy_names[] = {
193
    psdf_bcs_names, 0
194
};
195
static const char *const DownsampleType_names[] = {
196
    psdf_ds_names, 0
197
};
198
static const char *const AutoFilterStrategy_names[] = {
199
    psdf_afs_names, 0
200
};
201
static const char *const Binding_names[] = {
202
    psdf_binding_names, 0
203
};
204
static const char *const DefaultRenderingIntent_names[] = {
205
    psdf_ri_names, 0
206
};
207
static const char *const TransferFunctionInfo_names[] = {
208
    psdf_tfi_names, 0
209
};
210
static const char *const UCRandBGInfo_names[] = {
211
    psdf_ucrbg_names, 0
212
};
213
static const char *const CannotEmbedFontPolicy_names[] = {
214
    psdf_cefp_names, 0
215
};
216
217
static const gs_param_item_t psdf_param_items[] = {
218
#define pi(key, type, memb) { key, type, offset_of(psdf_distiller_params, memb) }
219
220
    /* General parameters */
221
222
    pi("ASCII85EncodePages", gs_param_type_bool, ASCII85EncodePages),
223
    /* (AutoRotatePages) */
224
    /* (Binding) */
225
    pi("CompressPages", gs_param_type_bool, CompressPages),
226
    /* (DefaultRenderingIntent) */
227
    pi("DetectBlends", gs_param_type_bool, DetectBlends),
228
    pi("DoThumbnails", gs_param_type_bool, DoThumbnails),
229
    pi("ImageMemory", gs_param_type_size_t, ImageMemory),
230
    /* (LockDistillerParams) */
231
    pi("LZWEncodePages", gs_param_type_bool, LZWEncodePages),
232
    pi("OPM", gs_param_type_int, OPM),
233
    pi("PreserveHalftoneInfo", gs_param_type_bool, PreserveHalftoneInfo),
234
    pi("PreserveOPIComments", gs_param_type_bool, PreserveOPIComments),
235
    pi("PreserveOverprintSettings", gs_param_type_bool, PreserveOverprintSettings),
236
    /* (TransferFunctionInfo) */
237
    /* (UCRandBGInfo) */
238
    pi("UseFlateCompression", gs_param_type_bool, UseFlateCompression),
239
    pi("UseBrotliCompression", gs_param_type_bool, UseBrotliCompression),
240
241
    /* Color image processing parameters */
242
243
    pi("ConvertCMYKImagesToRGB", gs_param_type_bool, ConvertCMYKImagesToRGB),
244
    pi("ConvertImagesToIndexed", gs_param_type_bool, ConvertImagesToIndexed),
245
246
    /* Font embedding parameters */
247
248
    /* (CannotEmbedFontPolicy) */
249
    pi("EmbedAllFonts", gs_param_type_bool, EmbedAllFonts),
250
    pi("MaxSubsetPct", gs_param_type_int, MaxSubsetPct),
251
    pi("SubsetFonts", gs_param_type_bool, SubsetFonts),
252
    pi("PassThroughJPEGImages", gs_param_type_bool, PassThroughJPEGImages),
253
    pi("PassThroughJPXImages", gs_param_type_bool, PassThroughJPXImages),
254
    pi("PSPageOptionsWrap", gs_param_type_bool, PSPageOptionsWrap),
255
256
#undef pi
257
    gs_param_item_end
258
};
259
260
/* -------- Get parameters -------- */
261
262
static int
263
psdf_write_name(gs_param_list *plist, const char *key, const char *str)
264
17.3M
{
265
17.3M
    gs_param_string pstr;
266
267
17.3M
    param_string_from_string(pstr, str);
268
17.3M
    return param_write_name(plist, key, &pstr);
269
17.3M
}
270
271
static int
272
psdf_write_string_param(gs_param_list *plist, const char *key,
273
                        const gs_const_string *pstr)
274
4.62M
{
275
4.62M
    gs_param_string ps;
276
277
4.62M
    ps.data = pstr->data;
278
4.62M
    ps.size = pstr->size;
279
4.62M
    ps.persistent = false;
280
4.62M
    return param_write_string(plist, key, &ps);
281
4.62M
}
282
283
/*
284
 * Get an image Dict parameter.  Note that we return a default (empty)
285
 * dictionary if the parameter has never been set.
286
 */
287
static int
288
psdf_get_image_dict_param(gs_param_list * plist, const gs_param_name pname,
289
                          gs_c_param_list *plvalue)
290
6.94M
{
291
6.94M
    gs_param_dict dict;
292
6.94M
    int code;
293
294
6.94M
    if (pname == 0)
295
1.15M
        return 0;
296
5.78M
    dict.size = 12;   /* enough for all param dicts we know about */
297
5.78M
    if ((code = param_begin_write_dict(plist, pname, &dict, false)) < 0)
298
0
        return code;
299
5.78M
    if (plvalue != 0) {
300
4.91M
        gs_c_param_list_read(plvalue);
301
4.91M
        code = param_list_copy(dict.list, (gs_param_list *)plvalue);
302
4.91M
    }
303
5.78M
    param_end_write_dict(plist, pname, &dict);
304
5.78M
    return code;
305
5.78M
}
306
307
/* Get a set of image-related parameters. */
308
static int
309
psdf_get_image_params(gs_param_list * plist,
310
          const psdf_image_param_names_t * pnames, psdf_image_params * params)
311
3.47M
{
312
    /* Skip AutoFilter for mono images. */
313
3.47M
    const gs_param_item_t *items =
314
3.47M
        (pnames->items[0].key == 0 ? pnames->items + 1 : pnames->items);
315
3.47M
    int code;
316
317
    /*
318
     * We must actually return a value for every parameter, so that
319
     * all parameter names will be recognized as settable by -d or -s
320
     * from the command line.
321
     */
322
3.47M
    code = gs_param_write_items(plist, params, NULL, items);
323
3.47M
    if (code < 0)
324
0
        return code;
325
326
3.47M
    code = psdf_get_image_dict_param(plist, pnames->ACSDict, params->ACSDict);
327
3.47M
    if (code < 0)
328
0
        return code;
329
330
           /* (AntiAlias) */
331
           /* (AutoFilter) */
332
           /* (Depth) */
333
3.47M
    code = psdf_get_image_dict_param(plist, pnames->Dict, params->Dict);
334
3.47M
    if (code < 0)
335
0
        return code;
336
337
           /* (Downsample) */
338
3.47M
    code = psdf_write_name(plist, pnames->DownsampleType,
339
3.47M
                DownsampleType_names[params->DownsampleType]);
340
3.47M
    if (code < 0)
341
0
        return code;
342
343
           /* (DownsampleThreshold) */
344
           /* (Encode) */
345
3.47M
    code = psdf_write_name(plist, pnames->Filter,
346
3.47M
                                   (params->Filter == 0 ?
347
348k
                                    pnames->filter_names[0].pname :
348
3.47M
                                    params->Filter));
349
3.47M
    if (code < 0)
350
0
        return code;
351
352
           /* (Resolution) */
353
3.47M
    if (pnames->AutoFilterStrategy != 0)
354
1.14M
        code = psdf_write_name(plist, pnames->AutoFilterStrategy,
355
1.14M
                AutoFilterStrategy_names[params->AutoFilterStrategy]);
356
3.47M
    if (code < 0)
357
0
        return code;
358
359
3.47M
    return code;
360
3.47M
}
361
362
/* Get a font embedding parameter. */
363
static int
364
psdf_get_embed_param(gs_param_list *plist, gs_param_name allpname,
365
                     const gs_param_string_array *psa)
366
4.62M
{
367
4.62M
    int code = param_write_name_array(plist, allpname, psa);
368
369
4.62M
    if (code >= 0)
370
4.62M
        code = param_write_name_array(plist, allpname + 1, psa);
371
4.62M
    return code;
372
4.62M
}
373
374
/* Transfer a collection of parameters. */
375
static const byte xfer_item_sizes[] = {
376
    GS_PARAM_TYPE_SIZES(0)
377
};
378
/* Get parameters. */
379
static
380
int gdev_psdf_get_image_param(gx_device_psdf *pdev, const psdf_image_param_names_t *image_names,
381
                              psdf_image_params * params, char *Param, gs_param_list * plist)
382
170k
{
383
170k
    const gs_param_item_t *pi;
384
170k
    int code;
385
386
965k
    for (pi = image_names->items; pi->key != 0; ++pi) {
387
794k
        if (strcmp(pi->key, Param) == 0) {
388
0
            const char *key = pi->key;
389
0
            const void *pvalue = (const void *)((const char *)params + pi->offset);
390
0
            int size = xfer_item_sizes[pi->type];
391
0
            gs_param_typed_value typed;
392
393
0
            memcpy(&typed.value, pvalue, size);
394
0
            typed.type = pi->type;
395
0
            code = (*plist->procs->xmit_typed) (plist, key, &typed);
396
0
            return code;
397
0
        }
398
794k
    }
399
    /* We only have an ACSDict for color image parameters */
400
170k
    if (image_names->ACSDict) {
401
113k
        if (strcmp(Param, image_names->ACSDict) == 0)
402
0
            return psdf_get_image_dict_param(plist, image_names->ACSDict, params->ACSDict);
403
113k
    }
404
170k
    if (strcmp(Param, image_names->Dict) == 0)
405
0
        return psdf_get_image_dict_param(plist, image_names->Dict, params->Dict);
406
407
170k
    if (strcmp(Param, image_names->DownsampleType) == 0)
408
0
        return psdf_write_name(plist, image_names->DownsampleType,
409
0
                DownsampleType_names[params->DownsampleType]);
410
170k
    if (strcmp(Param, image_names->Filter) == 0)
411
0
        return psdf_write_name(plist, image_names->Filter,
412
0
                                   (params->Filter == 0 ?
413
0
                                    image_names->filter_names[0].pname :
414
0
                                    params->Filter));
415
170k
    return_error(gs_error_undefined);
416
170k
}
417
int
418
gdev_psdf_get_param(gx_device *dev, char *Param, void *list)
419
365k
{
420
365k
    gx_device_psdf *pdev = (gx_device_psdf *) dev;
421
365k
    const psdf_image_param_names_t *image_names;
422
365k
    const gs_param_item_t *pi;
423
365k
    gs_param_list * plist = (gs_param_list *)list;
424
365k
    int code = 0;
425
426
365k
    code = gdev_vector_get_param(dev, Param, list);
427
365k
    if (code != gs_error_undefined)
428
309k
        return code;
429
430
    /* General parameters first */
431
1.19M
    for (pi = psdf_param_items; pi->key != 0; ++pi) {
432
1.13M
        if (strcmp(pi->key, Param) == 0) {
433
0
            const char *key = pi->key;
434
0
            const void *pvalue = (const void *)((const char *)&pdev + pi->offset);
435
0
            int size = xfer_item_sizes[pi->type];
436
0
            gs_param_typed_value typed;
437
438
0
            memcpy(&typed.value, pvalue, size);
439
0
            typed.type = pi->type;
440
0
            code = (*plist->procs->xmit_typed) (plist, key, &typed);
441
0
            return code;
442
0
        }
443
1.13M
    }
444
445
    /* Color image parameters */
446
56.7k
    if (pdev->ParamCompatibilityLevel >= 1.5)
447
19.4k
        image_names = &Color_names15;
448
37.3k
    else
449
37.3k
        image_names = &Color_names;
450
451
56.7k
    code = gdev_psdf_get_image_param(pdev, image_names, &pdev->params.ColorImage, Param, plist);
452
56.7k
    if (code != gs_error_undefined)
453
0
        return code;
454
455
    /* Grey image parameters */
456
56.7k
    if (pdev->ParamCompatibilityLevel >= 1.5)
457
19.4k
        image_names = &Gray_names15;
458
37.3k
    else
459
37.3k
        image_names = &Gray_names;
460
461
56.7k
    code = gdev_psdf_get_image_param(pdev, image_names, &pdev->params.GrayImage, Param, plist);
462
56.7k
    if (code != gs_error_undefined)
463
0
        return code;
464
465
    /* Mono image parameters */
466
56.7k
    code = gdev_psdf_get_image_param(pdev, &Mono_names, &pdev->params.MonoImage, Param, plist);
467
56.7k
    if (code != gs_error_undefined)
468
0
        return code;
469
470
56.7k
    if (strcmp(Param, "AutoRotatePages") == 0) {
471
0
        return(psdf_write_name(plist, "AutoRotatePages",
472
0
                AutoRotatePages_names[(int)pdev->params.AutoRotatePages]));
473
0
    }
474
56.7k
    if (strcmp(Param, "Binding") == 0) {
475
0
        return(psdf_write_name(plist, "Binding",
476
0
                Binding_names[(int)pdev->params.Binding]));
477
0
    }
478
56.7k
    if (strcmp(Param, "DefaultRenderingIntent") == 0) {
479
0
        return(psdf_write_name(plist, "DefaultRenderingIntent",
480
0
                DefaultRenderingIntent_names[(int)pdev->params.DefaultRenderingIntent]));
481
0
    }
482
56.7k
    if (strcmp(Param, "TransferFunctionInfo") == 0) {
483
0
        return(psdf_write_name(plist, "TransferFunctionInfo",
484
0
                TransferFunctionInfo_names[(int)pdev->params.TransferFunctionInfo]));
485
0
    }
486
56.7k
    if (strcmp(Param, "UCRandBGInfo") == 0) {
487
0
        return(psdf_write_name(plist, "UCRandBGInfo",
488
0
                UCRandBGInfo_names[(int)pdev->params.UCRandBGInfo]));
489
0
    }
490
56.7k
    if (strcmp(Param, "ColorConversionStrategy") == 0) {
491
0
        return(psdf_write_name(plist, "ColorConversionStrategy",
492
0
                ColorConversionStrategy_names[(int)pdev->params.ColorConversionStrategy]));
493
0
    }
494
56.7k
    if (strcmp(Param, "BlendConversionStrategy") == 0) {
495
0
        return(psdf_write_name(plist, "BlendConversionStrategy",
496
0
                BlendConversionStrategy_names[(int)pdev->params.BlendConversionStrategy]));
497
0
    }
498
56.7k
    if (strcmp(Param, "CalCMYKProfile") == 0) {
499
0
        return(psdf_write_string_param(plist, "CalCMYKProfile",
500
0
                                        &pdev->params.CalCMYKProfile));
501
0
    }
502
56.7k
    if (strcmp(Param, "CalGrayProfile") == 0) {
503
0
        return(psdf_write_string_param(plist, "CalGrayProfile",
504
0
                                        &pdev->params.CalGrayProfile));
505
0
    }
506
56.7k
    if (strcmp(Param, "CalRGBProfile") == 0) {
507
0
        return(psdf_write_string_param(plist, "CalRGBProfile",
508
0
                                        &pdev->params.CalRGBProfile));
509
0
    }
510
56.7k
    if (strcmp(Param, "sRGBProfile") == 0) {
511
0
        return(psdf_write_string_param(plist, "sRGBProfile",
512
0
                                        &pdev->params.sRGBProfile));
513
0
    }
514
56.7k
    if (strcmp(Param, ".AlwaysOutline") == 0) {
515
0
        return(psdf_get_embed_param(plist, ".AlwaysOutline", &pdev->params.AlwaysOutline));
516
0
    }
517
56.7k
    if (strcmp(Param, ".NeverOutline") == 0) {
518
0
        return(psdf_get_embed_param(plist, ".NeverOutline", &pdev->params.NeverOutline));
519
0
    }
520
56.7k
    if (strcmp(Param, ".AlwaysEmbed") == 0) {
521
0
        return(psdf_get_embed_param(plist, ".AlwaysEmbed", &pdev->params.AlwaysEmbed));
522
0
    }
523
56.7k
    if (strcmp(Param, ".NeverEmbed") == 0) {
524
0
        return(psdf_get_embed_param(plist, ".NeverEmbed", &pdev->params.NeverEmbed));
525
0
    }
526
56.7k
    if (strcmp(Param, "CannotEmbedFontPolicy") == 0) {
527
0
        return(psdf_write_name(plist, "CannotEmbedFontPolicy",
528
0
                CannotEmbedFontPolicy_names[(int)pdev->params.CannotEmbedFontPolicy]));
529
0
    }
530
56.7k
    return_error(gs_error_undefined);
531
56.7k
}
532
533
int
534
gdev_psdf_get_params(gx_device * dev, gs_param_list * plist)
535
1.15M
{
536
1.15M
    gx_device_psdf *pdev = (gx_device_psdf *) dev;
537
1.15M
    int code = gdev_vector_get_params(dev, plist);
538
1.15M
    if (code < 0)
539
0
        return code;
540
541
1.15M
    code = gs_param_write_items(plist, &pdev->params, NULL, psdf_param_items);
542
1.15M
    if (code < 0)
543
0
        return code;
544
545
    /* General parameters */
546
547
1.15M
    code = psdf_write_name(plist, "AutoRotatePages",
548
1.15M
                AutoRotatePages_names[(int)pdev->params.AutoRotatePages]);
549
1.15M
    if (code < 0)
550
0
        return code;
551
552
1.15M
    code = psdf_write_name(plist, "Binding",
553
1.15M
                Binding_names[(int)pdev->params.Binding]);
554
1.15M
    if (code < 0)
555
0
        return code;
556
557
1.15M
    code = psdf_write_name(plist, "DefaultRenderingIntent",
558
1.15M
                DefaultRenderingIntent_names[(int)pdev->params.DefaultRenderingIntent]);
559
1.15M
    if (code < 0)
560
0
        return code;
561
562
1.15M
    code = psdf_write_name(plist, "TransferFunctionInfo",
563
1.15M
                TransferFunctionInfo_names[(int)pdev->params.TransferFunctionInfo]);
564
1.15M
    if (code < 0)
565
0
        return code;
566
567
1.15M
    code = psdf_write_name(plist, "UCRandBGInfo",
568
1.15M
                UCRandBGInfo_names[(int)pdev->params.UCRandBGInfo]);
569
1.15M
    if (code < 0)
570
0
        return code;
571
572
    /* Color sampled image parameters */
573
574
1.15M
    code = psdf_get_image_params(plist,
575
1.15M
                        (pdev->ParamCompatibilityLevel >= 1.5 ? &Color_names15 : &Color_names),
576
1.15M
                        &pdev->params.ColorImage);
577
1.15M
    if (code < 0)
578
0
        return code;
579
580
1.15M
    code = psdf_write_name(plist, "ColorConversionStrategy",
581
1.15M
                ColorConversionStrategy_names[(int)pdev->params.ColorConversionStrategy]);
582
1.15M
    if (code < 0)
583
0
        return code;
584
585
1.15M
    code = psdf_write_name(plist, "BlendConversionStrategy",
586
1.15M
                BlendConversionStrategy_names[(int)pdev->params.BlendConversionStrategy]);
587
1.15M
    if (code < 0)
588
0
        return code;
589
590
1.15M
    code = psdf_write_string_param(plist, "CalCMYKProfile",
591
1.15M
                                        &pdev->params.CalCMYKProfile);
592
1.15M
    if (code < 0)
593
0
        return code;
594
595
1.15M
    code = psdf_write_string_param(plist, "CalGrayProfile",
596
1.15M
                                        &pdev->params.CalGrayProfile);
597
1.15M
    if (code < 0)
598
0
        return code;
599
600
1.15M
    code = psdf_write_string_param(plist, "CalRGBProfile",
601
1.15M
                                        &pdev->params.CalRGBProfile);
602
1.15M
    if (code < 0)
603
0
        return code;
604
605
1.15M
    code = psdf_write_string_param(plist, "sRGBProfile",
606
1.15M
                                        &pdev->params.sRGBProfile);
607
1.15M
    if (code < 0)
608
0
        return code;
609
610
    /* Gray sampled image parameters */
611
612
1.15M
    code = psdf_get_image_params(plist,
613
1.15M
                        (pdev->ParamCompatibilityLevel >= 1.5 ? &Gray_names15 : &Gray_names),
614
1.15M
                        &pdev->params.GrayImage);
615
1.15M
    if (code < 0)
616
0
        return code;
617
618
    /* Mono sampled image parameters */
619
620
1.15M
    code = psdf_get_image_params(plist, &Mono_names, &pdev->params.MonoImage);
621
1.15M
    if (code < 0)
622
0
        return code;
623
624
    /* Font outlining parameters */
625
626
1.15M
    code = psdf_get_embed_param(plist, ".AlwaysOutline", &pdev->params.AlwaysOutline);
627
1.15M
    if (code < 0)
628
0
        return code;
629
630
1.15M
    code = psdf_get_embed_param(plist, ".NeverOutline", &pdev->params.NeverOutline);
631
1.15M
    if (code < 0)
632
0
        return code;
633
634
    /* Font embedding parameters */
635
636
1.15M
    code = psdf_get_embed_param(plist, ".AlwaysEmbed", &pdev->params.AlwaysEmbed);
637
1.15M
    if (code < 0)
638
0
        return code;
639
640
1.15M
    code = psdf_get_embed_param(plist, ".NeverEmbed", &pdev->params.NeverEmbed);
641
1.15M
    if (code < 0)
642
0
        return code;
643
644
1.15M
    code = param_write_string_array(plist, "PSPageOptions", &pdev->params.PSPageOptions);
645
1.15M
    if (code < 0)
646
0
        return code;
647
648
1.15M
    code = psdf_write_name(plist, "CannotEmbedFontPolicy",
649
1.15M
                CannotEmbedFontPolicy_names[(int)pdev->params.CannotEmbedFontPolicy]);
650
651
1.15M
    return code;
652
1.15M
}
653
654
/* -------- Put parameters -------- */
655
656
extern stream_state_proc_put_params(s_CF_put_params, stream_CF_state);
657
extern stream_state_proc_put_params(s_DCTE_put_params, stream_DCT_state);
658
typedef stream_state_proc_put_params((*ss_put_params_t), stream_state);
659
660
static int
661
psdf_read_string_param(gs_param_list *plist, const char *key,
662
                       gs_const_string *pstr, gs_memory_t *mem, int ecode)
663
3.45M
{
664
3.45M
    gs_param_string ps;
665
3.45M
    int code;
666
667
3.45M
    switch (code = param_read_string(plist, key, &ps)) {
668
841k
    case 0: {
669
841k
        uint size = ps.size;
670
841k
        byte *data = gs_alloc_string(mem, size, "psdf_read_string_param");
671
672
841k
        if (data == 0)
673
0
            return_error(gs_error_VMerror);
674
841k
        memcpy(data, ps.data, size);
675
841k
        pstr->data = data;
676
841k
        pstr->size = size;
677
841k
        break;
678
841k
    }
679
0
    default:
680
0
        ecode = code;
681
2.61M
    case 1:
682
2.61M
        break;
683
3.45M
    }
684
3.45M
    return ecode;
685
3.45M
}
686
687
/*
688
 * The arguments and return value for psdf_put_enum are different because
689
 * we must cast the value both going in and coming out.
690
 */
691
static int
692
psdf_put_enum(gs_param_list *plist, const char *key, int value,
693
              const char *const pnames[], int *pecode)
694
7.60M
{
695
7.60M
    *pecode = param_put_enum(plist, key, &value, pnames, *pecode);
696
7.60M
    return value;
697
7.60M
}
698
699
static int
700
psdf_CF_put_params(gs_param_list * plist, stream_state * st)
701
0
{
702
0
    stream_CFE_state *const ss = (stream_CFE_state *) st;
703
704
0
    (*s_CFE_template.set_defaults) (st);
705
0
    ss->K = -1;
706
0
    ss->BlackIs1 = true;
707
0
    return s_CF_put_params(plist, (stream_CF_state *) ss);
708
0
}
709
710
static int
711
psdf_DCT_put_params(gs_param_list * plist, stream_state * st)
712
0
{
713
0
    return psdf_DCT_filter(plist, st, 8 /*nominal*/, 8 /*ibid.*/, 3 /*ibid.*/,
714
0
                           NULL);
715
0
}
716
717
/* Put [~](Always|Never)Embed parameters. */
718
/* Returns 0 = OK, 1 = no paramewter specified, <0 = error. */
719
static int
720
param_read_embed_array(gs_param_list * plist, gs_param_name pname,
721
                       gs_param_string_array * psa)
722
8.98M
{
723
8.98M
    int code;
724
725
8.98M
    psa->data = 0, psa->size = 0;
726
8.98M
    switch (code = param_read_name_array(plist, pname, psa)) {
727
0
        default:
728
0
            param_signal_error(plist, pname, code);
729
615k
        case 0:
730
8.98M
        case 1:
731
8.98M
            break;
732
8.98M
    }
733
8.98M
    return code;
734
8.98M
}
735
static bool
736
param_string_eq(const gs_param_string *ps1, const gs_param_string *ps2)
737
16.1M
{
738
16.1M
    return !bytes_compare(ps1->data, ps1->size, ps2->data, ps2->size);
739
16.1M
}
740
static int
741
add_embed(gs_param_string_array *prsa, const gs_param_string_array *psa,
742
          gs_memory_t *mem)
743
173k
{
744
173k
    uint i;
745
173k
    gs_param_string *const rdata =
746
173k
        (gs_param_string *)prsa->data; /* break const */
747
173k
    uint count = prsa->size;
748
749
2.60M
    for (i = 0; i < psa->size; ++i) {
750
2.42M
        uint j;
751
752
18.2M
        for (j = 0; j < count; ++j)
753
15.9M
            if (param_string_eq(&psa->data[i], &rdata[j]))
754
207k
                    break;
755
2.42M
        if (j == count) {
756
2.21M
            uint size = psa->data[i].size;
757
2.21M
            byte *data = gs_alloc_string(mem, size, "add_embed");
758
759
2.21M
            if (data == 0)
760
0
                return_error(gs_error_VMerror);
761
2.21M
            memcpy(data, psa->data[i].data, size);
762
2.21M
            rdata[count].data = data;
763
2.21M
            rdata[count].size = size;
764
2.21M
            rdata[count].persistent = false;
765
2.21M
            count++;
766
2.21M
        }
767
2.42M
    }
768
173k
    prsa->size = count;
769
173k
    return 0;
770
173k
}
771
static void
772
delete_embed(gs_param_string_array *prsa, const gs_param_string_array *pnsa,
773
             gs_memory_t *mem)
774
158k
{
775
158k
    uint i;
776
158k
    gs_param_string *const rdata =
777
158k
        (gs_param_string *)prsa->data; /* break const */
778
158k
    uint count = prsa->size;
779
780
158k
    for (i = pnsa->size; i-- > 0;) {
781
0
        uint j;
782
783
0
        for (j = count; j-- > 0;)
784
0
            if (param_string_eq(&pnsa->data[i], &rdata[j]))
785
0
                break;
786
0
        if (j + 1 != 0) {
787
0
            gs_free_const_string(mem, rdata[j].data, rdata[j].size,
788
0
                                 "delete_embed");
789
0
            rdata[j] = rdata[--count];
790
0
        }
791
0
    }
792
158k
    prsa->size = count;
793
158k
}
794
static int merge_embed(gs_param_string_array * psa, gs_param_string_array * asa,
795
                     gs_memory_t *mem)
796
173k
{
797
173k
    gs_param_string_array rsa;
798
173k
    gs_param_string *rdata;
799
173k
    int code;
800
801
173k
    rdata = gs_alloc_struct_array(mem, psa->size + asa->size,
802
173k
                                  gs_param_string,
803
173k
                                  &st_param_string_element,
804
173k
                                  "psdf_put_embed_param(update)");
805
173k
    if (rdata == 0)
806
0
        return_error(gs_error_VMerror);
807
173k
    if (psa->size > 0)
808
14.8k
        memcpy(rdata, psa->data, psa->size * sizeof(*psa->data));
809
173k
    rsa.data = rdata;
810
173k
    rsa.size = psa->size;
811
173k
    rsa.persistent = false;
812
173k
    code = add_embed(&rsa, asa, mem);
813
173k
    if (code < 0) {
814
0
        gs_free_object(mem, rdata, "psdf_put_embed_param(update)");
815
0
        return code;
816
0
    }
817
173k
    gs_free_const_object(mem, psa->data, "psdf_put_embed_param(free)");
818
173k
    *psa = rsa;
819
173k
    return 0;
820
173k
}
821
822
static int
823
psdf_put_embed_param(gs_param_list * plist, gs_param_name notpname,
824
                     gs_param_name pname, gs_param_string_array * psa,
825
                     gs_memory_t *mem, int ecode)
826
2.76M
{
827
2.76M
    gs_param_name allpname = pname + 1;
828
2.76M
    gs_param_string_array sa, nsa, asa;
829
2.76M
    int code;
830
831
2.76M
    mem = gs_memory_stable(mem);
832
2.76M
    code  = param_read_embed_array(plist, pname, &sa);
833
2.76M
    if (code < 0)
834
0
        return code;
835
2.76M
    if (code == 0) {
836
        /* Optimize for sa == *psa. */
837
476k
        int i;
838
839
476k
        if (sa.size == psa->size) {
840
525k
            for (i = 0; i < sa.size; ++i) {
841
207k
                if (!param_string_eq(&sa.data[i], &psa->data[i]))
842
0
                    break;
843
207k
     }
844
318k
        } else
845
158k
            i = -1;
846
476k
        if (i == sa.size) {
847
            /* equal, no-op. */
848
318k
        } else {
849
158k
            delete_embed(psa, psa, mem);
850
158k
            code = merge_embed(psa, &sa, mem);
851
158k
            if (code < 0)
852
0
                return code;
853
158k
        }
854
476k
    }
855
2.76M
    code = param_read_embed_array(plist, notpname, &nsa);
856
2.76M
    if (code < 0)
857
0
        return code;
858
2.76M
    if (nsa.data != 0)
859
0
        delete_embed(psa, &nsa, mem);
860
2.76M
    code = param_read_embed_array(plist, allpname, &asa);
861
2.76M
    if (code < 0)
862
0
        return code;
863
2.76M
    if (asa.data != 0) {
864
14.8k
        code = merge_embed(psa, &asa, mem);
865
14.8k
        if (code < 0)
866
0
            return code;
867
14.8k
    }
868
2.76M
    if (psa->data)
869
441k
        psa->data = gs_resize_object(mem, (gs_param_string *)psa->data, psa->size,
870
2.76M
                                        "psdf_put_embed_param(resize)");
871
2.76M
    return 0;
872
2.76M
}
873
874
/* Put an image Dict parameter. */
875
static int
876
psdf_put_image_dict_param(gs_param_list * plist, const gs_param_name pname,
877
                          gs_c_param_list **pplvalue,
878
                          const stream_template * templat,
879
                          ss_put_params_t put_params, gs_memory_t * mem)
880
3.45M
{
881
3.45M
    gs_param_dict dict;
882
3.45M
    gs_c_param_list *plvalue = *pplvalue;
883
3.45M
    int code;
884
885
3.45M
    mem = gs_memory_stable(mem);
886
3.45M
    switch (code = param_begin_read_dict(plist, pname, &dict, false)) {
887
0
        default:
888
0
            param_signal_error(plist, pname, code);
889
0
            return code;
890
2.40M
        case 1:
891
2.40M
            return 0;
892
1.05M
        case 0: {
893
1.05M
            plvalue = gs_c_param_list_alloc(mem, pname);
894
1.05M
            if (plvalue == 0)
895
0
                return_error(gs_error_VMerror);
896
1.05M
            gs_c_param_list_write(plvalue, mem);
897
1.05M
            code = param_list_copy((gs_param_list *)plvalue,
898
1.05M
                                   dict.list);
899
1.05M
            if (code < 0) {
900
0
                gs_c_param_list_release(plvalue);
901
0
                gs_free_object(mem, plvalue, pname);
902
0
                plvalue = *pplvalue;
903
0
            }
904
1.05M
        }
905
1.05M
        param_end_read_dict(plist, pname, &dict);
906
1.05M
        break;
907
3.45M
    }
908
1.05M
    if (plvalue != *pplvalue) {
909
1.05M
        if (*pplvalue)
910
139k
            gs_c_param_list_release(*pplvalue);
911
1.05M
        *pplvalue = plvalue;
912
1.05M
    }
913
1.05M
    return code;
914
3.45M
}
915
916
/* Put a set of image-related parameters. */
917
static int
918
psdf_put_image_params(const gx_device_psdf * pdev, gs_param_list * plist,
919
                      const psdf_image_param_names_t * pnames,
920
                      psdf_image_params * params, int ecode)
921
2.07M
{
922
2.07M
    gs_param_string fs;
923
    /*
924
     * Since this procedure can be called before the device is open,
925
     * we must use pdev->memory rather than pdev->v_memory.
926
     */
927
2.07M
    gs_memory_t *mem = gs_memory_stable(pdev->memory);
928
2.07M
    gs_param_name pname;
929
    /* Skip AutoFilter for mono images. */
930
2.07M
    const gs_param_item_t *items =
931
2.07M
        (pnames->items[0].key == 0 ? pnames->items + 1 : pnames->items);
932
2.07M
    int code = gs_param_read_items(plist, params, items, mem);
933
2.07M
    if (code < 0)
934
0
        ecode = code;
935
936
2.07M
    if ((pname = pnames->ACSDict) != 0) {
937
1.38M
        code = psdf_put_image_dict_param(plist, pname, &params->ACSDict,
938
1.38M
                                         &s_DCTE_template,
939
1.38M
                                         psdf_DCT_put_params, mem);
940
1.38M
        if (code < 0)
941
0
            ecode = code;
942
1.38M
    }
943
    /* (AntiAlias) */
944
    /* (AutoFilter) */
945
    /* (Depth) */
946
2.07M
    if ((pname = pnames->Dict) != 0) {
947
2.07M
        const stream_template *templat;
948
2.07M
        ss_put_params_t put_params;
949
950
        /* Hack to determine what kind of a Dict we want: */
951
2.07M
        if (pnames->Dict[0] == 'M')
952
691k
            templat = &s_CFE_template,
953
691k
                put_params = psdf_CF_put_params;
954
1.38M
        else
955
1.38M
            templat = &s_DCTE_template,
956
1.38M
                put_params = psdf_DCT_put_params;
957
2.07M
        code = psdf_put_image_dict_param(plist, pname, &params->Dict,
958
2.07M
                                         templat, put_params, mem);
959
2.07M
        if (code < 0)
960
0
            ecode = code;
961
2.07M
    }
962
    /* (Downsample) */
963
2.07M
    params->DownsampleType = (enum psdf_downsample_type)
964
2.07M
        psdf_put_enum(plist, pnames->DownsampleType,
965
2.07M
                      (int)params->DownsampleType, DownsampleType_names,
966
2.07M
                      &ecode);
967
    /* (DownsampleThreshold) */
968
    /* (Encode) */
969
    /* Process AutoFilterStrategy before Filter, because it sets defaults
970
       for the latter. */
971
2.07M
    if (pnames->AutoFilterStrategy != NULL) {
972
961k
        switch (code = param_read_string(plist, pnames->AutoFilterStrategy, &fs)) {
973
29.6k
            case 0:
974
29.6k
                {
975
29.6k
                    const psdf_image_filter_name *pn = pnames->filter_names;
976
29.6k
                    const char *param_name = 0;
977
978
29.6k
                    if (gs_param_string_eq(&fs, "JPEG")) {
979
29.6k
                        params->AutoFilterStrategy = af_Jpeg;
980
29.6k
                        param_name = "DCTEncode";
981
29.6k
                    } else {
982
0
                        if (gs_param_string_eq(&fs, "JPEG2000")) {
983
0
                            params->AutoFilterStrategy = af_Jpeg2000;
984
0
                            param_name = "JPXEncode";
985
0
                        } else {
986
0
                            ecode = gs_error_rangecheck;
987
0
                            goto ipe1;
988
0
                        }
989
0
                    }
990
148k
                    while (pn->pname != 0 && !gs_param_string_eq(&fs, param_name))
991
118k
                        pn++;
992
29.6k
                    if (pn->pname != 0 && pn->min_version <= pdev->version) {
993
0
                        params->Filter = pn->pname;
994
0
                        params->filter_template = pn->templat;
995
0
                    }
996
29.6k
                    break;
997
29.6k
                }
998
0
            default:
999
0
                ecode = code;
1000
0
            ipe1:param_signal_error(plist, pnames->AutoFilterStrategy, ecode);
1001
931k
            case 1:
1002
931k
                break;
1003
961k
        }
1004
961k
    }
1005
1006
2.07M
    switch (code = param_read_string(plist, pnames->Filter, &fs)) {
1007
631k
        case 0:
1008
631k
            {
1009
631k
                const psdf_image_filter_name *pn = pnames->filter_names;
1010
1011
631k
                while (pn->pname != 0 && !gs_param_string_eq(&fs, pn->pname))
1012
0
                    pn++;
1013
631k
                if (pn->pname == 0 || pn->min_version > pdev->version) {
1014
0
                    ecode = gs_error_rangecheck;
1015
0
                    goto ipe;
1016
0
                }
1017
631k
                params->Filter = pn->pname;
1018
631k
                params->filter_template = pn->templat;
1019
631k
                break;
1020
631k
            }
1021
0
        default:
1022
0
            ecode = code;
1023
0
          ipe:param_signal_error(plist, pnames->Filter, ecode);
1024
1.44M
        case 1:
1025
1.44M
            break;
1026
2.07M
    }
1027
    /* (Resolution) */
1028
2.07M
    if (ecode >= 0) {   /* Force parameters to acceptable values. */
1029
2.07M
        if (params->Resolution < 1)
1030
0
            params->Resolution = 1;
1031
2.07M
        if (params->DownsampleThreshold < 1 ||
1032
2.07M
            params->DownsampleThreshold > 10)
1033
0
            params->DownsampleThreshold = pnames->DownsampleThreshold_default;
1034
2.07M
        switch (params->Depth) {
1035
0
            default:
1036
0
                params->Depth = -1;
1037
0
            case 1:
1038
0
            case 2:
1039
0
            case 4:
1040
0
            case 8:
1041
2.07M
            case -1:
1042
2.07M
                break;
1043
2.07M
        }
1044
2.07M
    }
1045
2.07M
    return ecode;
1046
2.07M
}
1047
1048
/* This is a convenience routine. There doesn't seem to be any way to have a param_string_array
1049
 * enumerated for garbage collection, and we have (currently) three members of the psdf_distiller_params
1050
 * structure which store param_string_array. If the interpreter is using garbage collection then there
1051
 * is the potential for the array, or its contents, to be relocated or freed while we are still
1052
 * maintaining pointers to them, unless we enumerate the pointers.
1053
 * Instead, we'll copy the string data from the interpreter, make our own param_string_array, and
1054
 * manage the memory ourselves. This allows us to move the data into non-GC memory which is preferable
1055
 * anyway.
1056
 */
1057
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)
1058
0
{
1059
0
    if (sa->size > 0) {
1060
0
        int ix;
1061
1062
0
        if (da->data != NULL) {
1063
0
            for (ix = 0; ix < da->size;ix++)
1064
0
                gs_free_object(mem->non_gc_memory, (byte *)da->data[ix].data, "freeing old string array copy");
1065
0
            gs_free_object(mem->non_gc_memory, (byte *)da->data, "freeing old string array");
1066
0
        }
1067
0
        da->data = (const gs_param_string *)gs_alloc_bytes(mem->non_gc_memory, (size_t)sa->size * sizeof(gs_param_string), "allocate new string array");
1068
0
        if (da->data == NULL)
1069
0
            return_error(gs_note_error(gs_error_VMerror));
1070
0
        memset((byte *)da->data, 0x00, sa->size * sizeof(gs_param_string));
1071
0
        da->size = sa->size;
1072
0
        da->persistent = false;
1073
1074
0
        for(ix=0;ix < sa->size;ix++) {
1075
0
            ((gs_param_string *)&da->data[ix])->data = gs_alloc_bytes(mem->non_gc_memory, sa->data[ix].size, "allocate new strings");
1076
0
            if (da->data[ix].data == NULL)
1077
0
                return_error(gs_note_error(gs_error_VMerror));
1078
0
            memcpy((byte *)(da->data[ix].data), sa->data[ix].data, sa->data[ix].size);
1079
0
            ((gs_param_string *)&da->data[ix])->size = sa->data[ix].size;
1080
0
            ((gs_param_string *)&da->data[ix])->persistent = false;
1081
0
        }
1082
0
        gs_free_object(plist->memory, (byte *)sa->data, "freeing temporary param string array");
1083
0
        sa->data = NULL;
1084
0
        sa->size = 0;
1085
0
    }
1086
0
    return 0;
1087
0
}
1088
1089
static int psdf_read_copy_param_string_array(gs_memory_t *mem, gs_param_list * plist, const char *Key, gs_param_string_array *da)
1090
691k
{
1091
691k
    gs_param_string_array sa;
1092
691k
    int code;
1093
1094
691k
    code  = param_read_embed_array(plist, Key, &sa);
1095
691k
    if (code < 0)
1096
0
        return code;
1097
1098
691k
    if(sa.size)
1099
0
        code = psdf_copy_param_string_array(mem, plist, &sa, da);
1100
1101
691k
    return code;
1102
691k
}
1103
1104
/* Put parameters. */
1105
int
1106
gdev_psdf_put_params(gx_device * dev, gs_param_list * plist)
1107
691k
{
1108
691k
    gx_device_psdf *pdev = (gx_device_psdf *) dev;
1109
691k
    gs_memory_t *mem =
1110
691k
        (pdev->v_memory ? pdev->v_memory : dev->memory);
1111
691k
    int ecode, code = 0;
1112
691k
    psdf_distiller_params params;
1113
1114
691k
    params = pdev->params;
1115
1116
    /*
1117
     * If LockDistillerParams was true and isn't being set to false,
1118
     * ignore all other psdf parameters.  However, do not ignore the
1119
     * standard device parameters.
1120
     */
1121
691k
    ecode = code = param_read_bool(plist, "LockDistillerParams",
1122
691k
                                   &params.LockDistillerParams);
1123
1124
691k
    if ((pdev->params.LockDistillerParams && params.LockDistillerParams)) {
1125
        /* If we are not going to use the parameters we must still read them
1126
         * in order to use up all the keys, otherwise, if we are being called
1127
         * from .installpagedevice, it will error out on unconsumed keys. We
1128
         * use a dummy params structure to read into, but we must make sure any
1129
         * pointers are not copied from the real params structure, or they get
1130
         * overwritten.
1131
         */
1132
0
        params.CalCMYKProfile.size = params.CalGrayProfile.size = params.CalRGBProfile.size = params.sRGBProfile.size = 0;
1133
0
        params.CalCMYKProfile.data = 0;params.CalGrayProfile.data = params.CalRGBProfile.data = params.sRGBProfile.data = (byte *)0;
1134
1135
0
        params.ColorImage.ACSDict = params.ColorImage.Dict = 0;
1136
0
        params.GrayImage.ACSDict = params.GrayImage.Dict = 0;
1137
0
        params.MonoImage.ACSDict = params.MonoImage.Dict = 0;
1138
0
        params.AlwaysOutline.data = params.NeverOutline.data = NULL;
1139
0
        params.AlwaysOutline.size = params.NeverOutline.size = 0;
1140
0
        params.AlwaysEmbed.data = params.NeverEmbed.data = 0;
1141
0
        params.AlwaysEmbed.size = params.NeverEmbed.size = 0;
1142
0
  params.AlwaysEmbed.persistent = params.NeverEmbed.persistent = false;
1143
0
        params.PSPageOptions.data = NULL;
1144
0
        params.PSPageOptions.size = 0;
1145
0
    }
1146
1147
    /* General parameters. */
1148
1149
691k
    code = gs_param_read_items(plist, &params, psdf_param_items, NULL);
1150
691k
    if (code < 0)
1151
0
        return code;
1152
1153
691k
    params.AutoRotatePages = (enum psdf_auto_rotate_pages)
1154
691k
        psdf_put_enum(plist, "AutoRotatePages", (int)params.AutoRotatePages,
1155
691k
                      AutoRotatePages_names, &ecode);
1156
691k
    if (ecode < 0) {
1157
0
        code = ecode;
1158
0
        goto exit;
1159
0
    }
1160
1161
691k
    params.Binding = (enum psdf_binding)
1162
691k
        psdf_put_enum(plist, "Binding", (int)params.Binding,
1163
691k
                      Binding_names, &ecode);
1164
691k
    if (ecode < 0) {
1165
0
        code = ecode;
1166
0
        goto exit;
1167
0
    }
1168
1169
691k
    params.DefaultRenderingIntent = (enum psdf_default_rendering_intent)
1170
691k
        psdf_put_enum(plist, "DefaultRenderingIntent",
1171
691k
                      (int)params.DefaultRenderingIntent,
1172
691k
                      DefaultRenderingIntent_names, &ecode);
1173
691k
    if (ecode < 0) {
1174
0
        code = ecode;
1175
0
        goto exit;
1176
0
    }
1177
1178
691k
    params.TransferFunctionInfo = (enum psdf_transfer_function_info)
1179
691k
        psdf_put_enum(plist, "TransferFunctionInfo",
1180
691k
                      (int)params.TransferFunctionInfo,
1181
691k
                      TransferFunctionInfo_names, &ecode);
1182
691k
    if (ecode < 0) {
1183
0
        code = ecode;
1184
0
        goto exit;
1185
0
    }
1186
1187
691k
    params.UCRandBGInfo = (enum psdf_ucr_and_bg_info)
1188
691k
        psdf_put_enum(plist, "UCRandBGInfo", (int)params.UCRandBGInfo,
1189
691k
                      UCRandBGInfo_names, &ecode);
1190
691k
    if (ecode < 0) {
1191
0
        code = ecode;
1192
0
        goto exit;
1193
0
    }
1194
1195
691k
    ecode = param_put_bool(plist, "UseFlateCompression",
1196
691k
                           &params.UseFlateCompression, ecode);
1197
1198
    /* Color sampled image parameters */
1199
1200
691k
    ecode = psdf_put_image_params(pdev, plist,
1201
691k
                    (pdev->ParamCompatibilityLevel >= 1.5 ? &Color_names15 : &Color_names),
1202
691k
                                  &params.ColorImage, ecode);
1203
691k
    if (ecode < 0) {
1204
0
        code = ecode;
1205
0
        goto exit;
1206
0
    }
1207
1208
691k
    params.ColorConversionStrategy = (enum psdf_color_conversion_strategy)
1209
691k
        psdf_put_enum(plist, "ColorConversionStrategy",
1210
691k
                      (int)params.ColorConversionStrategy,
1211
691k
                      ColorConversionStrategy_names, &ecode);
1212
691k
    if (ecode < 0) {
1213
0
        code = ecode;
1214
0
        goto exit;
1215
0
    }
1216
1217
691k
    params.BlendConversionStrategy = (enum psdf_blend_conversion_strategy)
1218
691k
        psdf_put_enum(plist, "BlendConversionStrategy",
1219
691k
                      (int)params.BlendConversionStrategy,
1220
691k
                      BlendConversionStrategy_names, &ecode);
1221
691k
    if (ecode < 0) {
1222
0
        code = ecode;
1223
0
        goto exit;
1224
0
    }
1225
1226
691k
    ecode = psdf_read_string_param(plist, "CalCMYKProfile",
1227
691k
                                   &params.CalCMYKProfile, mem, ecode);
1228
691k
    ecode = psdf_read_string_param(plist, "CalGrayProfile",
1229
691k
                                   &params.CalGrayProfile, mem, ecode);
1230
691k
    ecode = psdf_read_string_param(plist, "CalRGBProfile",
1231
691k
                                   &params.CalRGBProfile, mem, ecode);
1232
691k
    ecode = psdf_read_string_param(plist, "sRGBProfile",
1233
691k
                                   &params.sRGBProfile, mem, ecode);
1234
1235
    /* Gray sampled image parameters */
1236
1237
691k
    ecode = psdf_put_image_params(pdev, plist,
1238
691k
                    (pdev->ParamCompatibilityLevel >= 1.5 ? &Gray_names15 : &Gray_names),
1239
691k
                                  &params.GrayImage, ecode);
1240
691k
    if (ecode < 0) {
1241
0
        code = ecode;
1242
0
        goto exit;
1243
0
    }
1244
1245
1246
    /* Mono sampled image parameters */
1247
1248
691k
    ecode = psdf_put_image_params(pdev, plist, &Mono_names,
1249
691k
                                  &params.MonoImage, ecode);
1250
1251
691k
    if (ecode < 0) {
1252
0
        code = ecode;
1253
0
        goto exit;
1254
0
    }
1255
1256
    /* Font outlining parameters */
1257
1258
691k
    ecode = psdf_put_embed_param(plist, "~AlwaysOutline", ".AlwaysOutline",
1259
691k
                                 &params.AlwaysOutline, mem, ecode);
1260
691k
    ecode = psdf_put_embed_param(plist, "~NeverOutline", ".NeverOutline",
1261
691k
                                 &params.NeverOutline, mem, ecode);
1262
1263
691k
    if (ecode < 0) {
1264
0
        code = ecode;
1265
0
        goto exit;
1266
0
    }
1267
1268
    /* Font embedding parameters */
1269
1270
691k
    ecode = psdf_put_embed_param(plist, "~AlwaysEmbed", ".AlwaysEmbed",
1271
691k
                                 &params.AlwaysEmbed, mem, ecode);
1272
691k
    ecode = psdf_put_embed_param(plist, "~NeverEmbed", ".NeverEmbed",
1273
691k
                                 &params.NeverEmbed, mem, ecode);
1274
1275
691k
    params.CannotEmbedFontPolicy = (enum psdf_cannot_embed_font_policy)
1276
691k
        psdf_put_enum(plist, "CannotEmbedFontPolicy",
1277
691k
                      (int)params.CannotEmbedFontPolicy,
1278
691k
                      CannotEmbedFontPolicy_names, &ecode);
1279
691k
    if (ecode < 0) {
1280
0
        code = ecode;
1281
0
        goto exit;
1282
0
    }
1283
1284
    /* ps2write-specific output configuration options */
1285
691k
    code = psdf_read_string_param(plist, "PSDocOptions",
1286
691k
                                   (gs_const_string *)&params.PSDocOptions, mem, ecode);
1287
691k
    if (code < 0)
1288
0
        goto exit;
1289
1290
691k
    params.PSPageOptions.size = 0;
1291
691k
    params.PSPageOptions.data = NULL;
1292
691k
    code = psdf_read_copy_param_string_array(pdev->memory, plist, "PSPageOptions", &params.PSPageOptions);
1293
691k
    if (code < 0)
1294
0
        goto exit;
1295
1296
691k
    code = gdev_vector_put_params(dev, plist);
1297
1298
691k
exit:
1299
691k
    if (!(pdev->params.LockDistillerParams && params.LockDistillerParams)) {
1300
        /* Only update the device paramters if there was no error */
1301
        /* Do not permit changes to pdev->Params.PSPageOptions, it doesn't make any sense */
1302
691k
        if (pdev->params.PSPageOptions.size != 0) {
1303
0
            if (params.PSPageOptions.size != 0 && params.PSPageOptions.data != pdev->params.PSPageOptions.data) {
1304
0
                int ix;
1305
1306
0
                for (ix = 0; ix < params.PSPageOptions.size;ix++)
1307
0
                    gs_free_object(mem->non_gc_memory, (byte *)params.PSPageOptions.data[ix].data, "freeing old string array copy");
1308
0
                gs_free_object(mem->non_gc_memory, (byte *)params.PSPageOptions.data, "freeing old string array");
1309
0
            }
1310
0
            params.PSPageOptions.data = pdev->params.PSPageOptions.data;
1311
0
            params.PSPageOptions.size = pdev->params.PSPageOptions.size;
1312
0
        }
1313
691k
        pdev->params = params;
1314
691k
    } else {
1315
        /* We read a bunch of parameters and are now throwing them away. Either because there
1316
         * was an error, or because the parameters were locked. We need to tidy up any memory
1317
         * we allocated to hold these parameters.
1318
         */
1319
0
        gs_memory_t *stable_mem = gs_memory_stable(mem);
1320
1321
0
        if (params.PSPageOptions.data != NULL) {
1322
0
            int ix;
1323
1324
0
            if (params.PSPageOptions.size != 0 && params.PSPageOptions.data != pdev->params.PSPageOptions.data) {
1325
0
                for (ix = 0; ix < params.PSPageOptions.size;ix++)
1326
0
                    gs_free_object(mem->non_gc_memory, (byte *)params.PSPageOptions.data[ix].data, "freeing dummy PSPageOptions");
1327
0
                gs_free_object(mem->non_gc_memory, (byte *)params.PSPageOptions.data, "freeing dummy PSPageOptions");
1328
0
            }
1329
0
            params.PSPageOptions.data = NULL;
1330
0
            params.PSPageOptions.size = 0;
1331
0
        }
1332
0
        if (params.CalCMYKProfile.data != 0)
1333
0
            gs_free_string(stable_mem, (void *)params.CalCMYKProfile.data, params.CalCMYKProfile.size, "free dummy param CalCMYKProfile");
1334
0
        if (params.CalGrayProfile.data != 0)
1335
0
            gs_free_string(stable_mem, (void *)params.CalGrayProfile.data, params.CalGrayProfile.size, "free dummy param CalGrayProfile");
1336
0
        if (params.CalRGBProfile.data != 0)
1337
0
            gs_free_string(stable_mem, (void *)params.CalRGBProfile.data, params.CalRGBProfile.size, "free dummy param CalRGBProfile");
1338
0
        if (params.sRGBProfile.data != 0)
1339
0
            gs_free_string(stable_mem, (void *)params.sRGBProfile.data, params.sRGBProfile.size, "free dummy param sRGBProfile");
1340
0
        if (params.ColorImage.ACSDict)
1341
0
            gs_c_param_list_release(params.ColorImage.ACSDict);
1342
0
        if (params.ColorImage.Dict)
1343
0
            gs_c_param_list_release(params.ColorImage.Dict);
1344
0
        if (params.GrayImage.ACSDict)
1345
0
            gs_c_param_list_release(params.GrayImage.ACSDict);
1346
0
        if (params.GrayImage.Dict)
1347
0
            gs_c_param_list_release(params.GrayImage.Dict);
1348
0
        if (params.MonoImage.ACSDict)
1349
0
            gs_c_param_list_release(params.MonoImage.ACSDict);
1350
0
        if (params.MonoImage.Dict)
1351
0
            gs_c_param_list_release(params.MonoImage.Dict);
1352
0
    }
1353
691k
    return code;
1354
691k
}