Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: gdevpsdp.c,v 1.14 2004/06/30 14:35:37 igor Exp $ */
18
/* (Distiller) parameter handling for PostScript and PDF writers */
19
#include "string_.h"
20
#include "jpeglib_.h"		/* for sdct.h */
21
#include "gx.h"
22
#include "gserrors.h"
23
#include "gsutil.h"
24
#include "gxdevice.h"
25
#include "gsparamx.h"
26
#include "gdevpsdf.h"
27
#include "strimpl.h"		/* for short-sighted compilers */
28
#include "scfx.h"
29
#include "sdct.h"
30
#include "slzwx.h"
31
#include "spprint.h"
32
#include "srlx.h"
33
#include "szlibx.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
private
40
ENUM_PTRS_WITH(param_string_enum_ptrs, gs_param_string *pstr) return 0;
41
case 0: return ENUM_CONST_STRING(pstr);
42
ENUM_PTRS_END
43
private
44
RELOC_PTRS_WITH(param_string_reloc_ptrs, gs_param_string *pstr)
45
{
46
    gs_const_string str;
47
 
48
    str.data = pstr->data, str.size = pstr->size;
49
    RELOC_CONST_STRING_VAR(str);
50
    pstr->data = str.data;
51
}
52
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
 
58
/* ---------------- Get/put Distiller parameters ---------------- */
59
 
60
/*
61
 * ColorConversionStrategy is supposed to affect output color space
62
 * according to the following table.  ****** NOT IMPLEMENTED YET ******
63
 
64
PS Input:  LeaveCU UseDIC           UseDICFI         sRGB
65
Gray art   Gray    CalGray/ICCBased Gray             Gray
66
Gray image Gray    CalGray/ICCBased CalGray/ICCBased Gray
67
RGB art    RGB     CalGray/ICCBased RGB              CalRGB/sRGB
68
RGB image  RGB     CalGray/ICCBased CalRGB/ICCBased  CalRGB/sRGB
69
CMYK art   CMYK    LAB/ICCBased     CMYK             CalRGB/sRGB
70
CMYK image CMYK    LAB/ICCBased     LAB/ICCBased     CalRGB/sRGB
71
CIE art    Cal/ICC Cal/ICC          Cal/ICC          CalRGB/sRGB
72
CIE image  Cal/ICC Cal/ICC          Cal/ICC          CalRGB/sRGB
73
 
74
 */
75
 
76
/*
77
 * The Always/NeverEmbed parameters are defined as being incremental.  Since
78
 * this isn't compatible with the general property of page devices that if
79
 * you do a currentpagedevice, doing a setpagedevice later will restore the
80
 * same state, we actually define the parameters in sets of 3:
81
 *	- AlwaysEmbed is used for incremental additions.
82
 *	- ~AlwaysEmbed is used for incremental deletions.
83
 *	- .AlwaysEmbed is used for the complete list.
84
 * and analogously for NeverEmbed.
85
 */
86
 
87
typedef struct psdf_image_filter_name_s {
88
    const char *pname;
89
    const stream_template *template;
90
    psdf_version min_version;
91
} psdf_image_filter_name;
92
 
93
private const psdf_image_filter_name Poly_filters[] = {
94
    {"DCTEncode", &s_DCTE_template},
95
    {"FlateEncode", &s_zlibE_template, psdf_version_ll3},
96
    {"LZWEncode", &s_LZWE_template},
97
    {0, 0}
98
};
99
 
100
private 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
    {0, 0}
106
};
107
 
108
typedef struct psdf_image_param_names_s {
109
    const char *ACSDict;	/* not used for mono */
110
    const char *Dict;
111
    const char *DownsampleType;
112
    float DownsampleThreshold_default;
113
    const psdf_image_filter_name *filter_names;
114
    const char *Filter;
115
    gs_param_item_t items[8];	/* AutoFilter (not used for mono), */
116
				/* AntiAlias, */
117
				/* Depth, Downsample, DownsampleThreshold, */
118
				/* Encode, Resolution, end marker */
119
} psdf_image_param_names_t;
120
#define pi(key, type, memb) { key, type, offset_of(psdf_image_params, memb) }
121
#define psdf_image_param_names(acs, aa, af, de, di, ds, dt, dst, dstd, e, f, fns, r)\
122
    acs, di, dt, dstd, fns, f, {\
123
      pi(af, gs_param_type_bool, AutoFilter),\
124
      pi(aa, gs_param_type_bool, AntiAlias),\
125
      pi(de, gs_param_type_int, Depth),\
126
      pi(ds, gs_param_type_bool, Downsample),\
127
      pi(dst, gs_param_type_float, DownsampleThreshold),\
128
      pi(e, gs_param_type_bool, Encode),\
129
      pi(r, gs_param_type_int, Resolution),\
130
      gs_param_item_end\
131
    }
132
 
133
private const psdf_image_param_names_t Color_names = {
134
    psdf_image_param_names(
135
	"ColorACSImageDict", "AntiAliasColorImages", "AutoFilterColorImages",
136
	"ColorImageDepth", "ColorImageDict",
137
	"DownsampleColorImages", "ColorImageDownsampleType",
138
	"ColorImageDownsampleThreshold", 1.5,
139
	"EncodeColorImages", "ColorImageFilter", Poly_filters,
140
	"ColorImageResolution"
141
    )
142
};
143
private const psdf_image_param_names_t Gray_names = {
144
    psdf_image_param_names(
145
	"GrayACSImageDict", "AntiAliasGrayImages", "AutoFilterGrayImages",
146
	"GrayImageDepth", "GrayImageDict",
147
	"DownsampleGrayImages", "GrayImageDownsampleType",
148
	"GrayImageDownsampleThreshold", 2.0,
149
	"EncodeGrayImages", "GrayImageFilter", Poly_filters,
150
	"GrayImageResolution"
151
    )
152
};
153
private const psdf_image_param_names_t Mono_names = {
154
    psdf_image_param_names(
155
	0, "AntiAliasMonoImages", 0,
156
	"MonoImageDepth", "MonoImageDict",
157
	"DownsampleMonoImages", "MonoImageDownsampleType",
158
	"MonoImageDownsampleThreshold", 2.0,
159
	"EncodeMonoImages", "MonoImageFilter", Mono_filters,
160
	"MonoImageResolution"
161
    )
162
};
163
#undef pi
164
private const char *const AutoRotatePages_names[] = {
165
    psdf_arp_names, 0
166
};
167
private const char *const ColorConversionStrategy_names[] = {
168
    psdf_ccs_names, 0
169
};
170
private const char *const DownsampleType_names[] = {
171
    psdf_ds_names, 0
172
};
173
private const char *const Binding_names[] = {
174
    psdf_binding_names, 0
175
};
176
private const char *const DefaultRenderingIntent_names[] = {
177
    psdf_ri_names, 0
178
};
179
private const char *const TransferFunctionInfo_names[] = {
180
    psdf_tfi_names, 0
181
};
182
private const char *const UCRandBGInfo_names[] = {
183
    psdf_ucrbg_names, 0
184
};
185
private const char *const CannotEmbedFontPolicy_names[] = {
186
    psdf_cefp_names, 0
187
};
188
 
189
private const gs_param_item_t psdf_param_items[] = {
190
#define pi(key, type, memb) { key, type, offset_of(psdf_distiller_params, memb) }
191
 
192
    /* General parameters */
193
 
194
    pi("ASCII85EncodePages", gs_param_type_bool, ASCII85EncodePages),
195
    /* (AutoRotatePages) */
196
    /* (Binding) */
197
    pi("CompressPages", gs_param_type_bool, CompressPages),
198
    /* (DefaultRenderingIntent) */
199
    pi("DetectBlends", gs_param_type_bool, DetectBlends),
200
    pi("DoThumbnails", gs_param_type_bool, DoThumbnails),
201
    pi("ImageMemory", gs_param_type_long, ImageMemory),
202
    /* (LockDistillerParams) */
203
    pi("LZWEncodePages", gs_param_type_bool, LZWEncodePages),
204
    pi("OPM", gs_param_type_int, OPM),
205
    pi("PreserveHalftoneInfo", gs_param_type_bool, PreserveHalftoneInfo),
206
    pi("PreserveOPIComments", gs_param_type_bool, PreserveOPIComments),
207
    pi("PreserveOverprintSettings", gs_param_type_bool, PreserveOverprintSettings),
208
    /* (TransferFunctionInfo) */
209
    /* (UCRandBGInfo) */
210
    pi("UseFlateCompression", gs_param_type_bool, UseFlateCompression),
211
 
212
    /* Color image processing parameters */
213
 
214
    pi("ConvertCMYKImagesToRGB", gs_param_type_bool, ConvertCMYKImagesToRGB),
215
    pi("ConvertImagesToIndexed", gs_param_type_bool, ConvertImagesToIndexed),
216
 
217
    /* Font embedding parameters */
218
 
219
    /* (CannotEmbedFontPolicy) */
220
    pi("EmbedAllFonts", gs_param_type_bool, EmbedAllFonts),
221
    pi("MaxSubsetPct", gs_param_type_int, MaxSubsetPct),
222
    pi("SubsetFonts", gs_param_type_bool, SubsetFonts),
223
 
224
#undef pi
225
    gs_param_item_end
226
};
227
 
228
/* -------- Get parameters -------- */
229
 
230
private int
231
psdf_write_name(gs_param_list *plist, const char *key, const char *str)
232
{
233
    gs_param_string pstr;
234
 
235
    param_string_from_string(pstr, str);
236
    return param_write_name(plist, key, &pstr);
237
}
238
 
239
private int
240
psdf_write_string_param(gs_param_list *plist, const char *key,
241
			const gs_const_string *pstr)
242
{
243
    gs_param_string ps;
244
 
245
    ps.data = pstr->data;
246
    ps.size = pstr->size;
247
    ps.persistent = false;
248
    return param_write_string(plist, key, &ps);
249
}
250
 
251
/*
252
 * Get an image Dict parameter.  Note that we return a default (empty)
253
 * dictionary if the parameter has never been set.
254
 */
255
private int
256
psdf_get_image_dict_param(gs_param_list * plist, const gs_param_name pname,
257
			  gs_c_param_list *plvalue)
258
{
259
    gs_param_dict dict;
260
    int code;
261
 
262
    if (pname == 0)
263
	return 0;
264
    dict.size = 12;		/* enough for all param dicts we know about */
265
    if ((code = param_begin_write_dict(plist, pname, &dict, false)) < 0)
266
	return code;
267
    if (plvalue != 0) {
268
	gs_c_param_list_read(plvalue);
269
	code = param_list_copy(dict.list, (gs_param_list *)plvalue);
270
    }
271
    param_end_write_dict(plist, pname, &dict);
272
    return code;
273
}
274
 
275
/* Get a set of image-related parameters. */
276
private int
277
psdf_get_image_params(gs_param_list * plist,
278
	  const psdf_image_param_names_t * pnames, psdf_image_params * params)
279
{
280
    /* Skip AutoFilter for mono images. */
281
    const gs_param_item_t *items =
282
	(pnames->items[0].key == 0 ? pnames->items + 1 : pnames->items);
283
    int code;
284
 
285
    /*
286
     * We must actually return a value for every parameter, so that
287
     * all parameter names will be recognized as settable by -d or -s
288
     * from the command line.
289
     */
290
    if (
291
	   (code = gs_param_write_items(plist, params, NULL, items)) < 0 ||
292
	   (code = psdf_get_image_dict_param(plist, pnames->ACSDict,
293
					     params->ACSDict)) < 0 ||
294
	   /* (AntiAlias) */
295
	   /* (AutoFilter) */
296
	   /* (Depth) */
297
	   (code = psdf_get_image_dict_param(plist, pnames->Dict,
298
					     params->Dict)) < 0 ||
299
	   /* (Downsample) */
300
	   (code = psdf_write_name(plist, pnames->DownsampleType,
301
		DownsampleType_names[params->DownsampleType])) < 0 ||
302
	   /* (DownsampleThreshold) */
303
	   /* (Encode) */
304
	   (code = psdf_write_name(plist, pnames->Filter,
305
				   (params->Filter == 0 ?
306
				    pnames->filter_names[0].pname :
307
				    params->Filter))) < 0
308
	   /* (Resolution) */
309
	)
310
	DO_NOTHING;
311
    return code;
312
}
313
 
314
/* Get a font embedding parameter. */
315
private int
316
psdf_get_embed_param(gs_param_list *plist, gs_param_name allpname,
317
		     const gs_param_string_array *psa)
318
{
319
    int code = param_write_name_array(plist, allpname, psa);
320
 
321
    if (code >= 0)
322
	code = param_write_name_array(plist, allpname + 1, psa);
323
    return code;
324
}
325
 
326
/* Get parameters. */
327
int
328
gdev_psdf_get_params(gx_device * dev, gs_param_list * plist)
329
{
330
    gx_device_psdf *pdev = (gx_device_psdf *) dev;
331
    int code = gdev_vector_get_params(dev, plist);
332
 
333
    if (
334
	code < 0 ||
335
	(code = gs_param_write_items(plist, &pdev->params, NULL, psdf_param_items)) < 0 ||
336
 
337
    /* General parameters */
338
 
339
	(code = psdf_write_name(plist, "AutoRotatePages",
340
		AutoRotatePages_names[(int)pdev->params.AutoRotatePages])) < 0 ||
341
	(code = psdf_write_name(plist, "Binding",
342
		Binding_names[(int)pdev->params.Binding])) < 0 ||
343
	(code = psdf_write_name(plist, "DefaultRenderingIntent",
344
		DefaultRenderingIntent_names[(int)pdev->params.DefaultRenderingIntent])) < 0 ||
345
	(code = psdf_write_name(plist, "TransferFunctionInfo",
346
		TransferFunctionInfo_names[(int)pdev->params.TransferFunctionInfo])) < 0 ||
347
	(code = psdf_write_name(plist, "UCRandBGInfo",
348
		UCRandBGInfo_names[(int)pdev->params.UCRandBGInfo])) < 0 ||
349
 
350
    /* Color sampled image parameters */
351
 
352
	(code = psdf_get_image_params(plist, &Color_names, &pdev->params.ColorImage)) < 0 ||
353
	(code = psdf_write_name(plist, "ColorConversionStrategy",
354
		ColorConversionStrategy_names[(int)pdev->params.ColorConversionStrategy])) < 0 ||
355
	(code = psdf_write_string_param(plist, "CalCMYKProfile",
356
					&pdev->params.CalCMYKProfile)) < 0 ||
357
	(code = psdf_write_string_param(plist, "CalGrayProfile",
358
					&pdev->params.CalGrayProfile)) < 0 ||
359
	(code = psdf_write_string_param(plist, "CalRGBProfile",
360
					&pdev->params.CalRGBProfile)) < 0 ||
361
	(code = psdf_write_string_param(plist, "sRGBProfile",
362
					&pdev->params.sRGBProfile)) < 0 ||
363
 
364
    /* Gray sampled image parameters */
365
 
366
	(code = psdf_get_image_params(plist, &Gray_names, &pdev->params.GrayImage)) < 0 ||
367
 
368
    /* Mono sampled image parameters */
369
 
370
	(code = psdf_get_image_params(plist, &Mono_names, &pdev->params.MonoImage)) < 0 ||
371
 
372
    /* Font embedding parameters */
373
 
374
	(code = psdf_get_embed_param(plist, ".AlwaysEmbed", &pdev->params.AlwaysEmbed)) < 0 ||
375
	(code = psdf_get_embed_param(plist, ".NeverEmbed", &pdev->params.NeverEmbed)) < 0 ||
376
	(code = psdf_write_name(plist, "CannotEmbedFontPolicy",
377
		CannotEmbedFontPolicy_names[(int)pdev->params.CannotEmbedFontPolicy])) < 0
378
	)
379
	DO_NOTHING;
380
    return code;
381
}
382
 
383
/* -------- Put parameters -------- */
384
 
385
extern stream_state_proc_put_params(s_CF_put_params, stream_CF_state);
386
extern stream_state_proc_put_params(s_DCTE_put_params, stream_DCT_state);
387
typedef stream_state_proc_put_params((*ss_put_params_t), stream_state);
388
 
389
private int
390
psdf_read_string_param(gs_param_list *plist, const char *key,
391
		       gs_const_string *pstr, gs_memory_t *mem, int ecode)
392
{
393
    gs_param_string ps;
394
    int code;
395
 
396
    switch (code = param_read_string(plist, key, &ps)) {
397
    case 0: {
398
	uint size = ps.size;
399
	byte *data = gs_alloc_string(mem, size, "psdf_read_string_param");
400
 
401
	if (data == 0)
402
	    return_error(gs_error_VMerror);
403
	memcpy(data, ps.data, size);
404
	pstr->data = data;
405
	pstr->size = size;
406
	break;
407
    }
408
    default:
409
	ecode = code;
410
    case 1:
411
	break;
412
    }
413
    return ecode;
414
}
415
 
416
/*
417
 * The arguments and return value for psdf_put_enum are different because
418
 * we must cast the value both going in and coming out.
419
 */
420
private int
421
psdf_put_enum(gs_param_list *plist, const char *key, int value,
422
	      const char *const pnames[], int *pecode)
423
{
424
    *pecode = param_put_enum(plist, key, &value, pnames, *pecode);
425
    return value;
426
}
427
 
428
private int
429
psdf_CF_put_params(gs_param_list * plist, stream_state * st)
430
{
431
    stream_CFE_state *const ss = (stream_CFE_state *) st;
432
 
433
    (*s_CFE_template.set_defaults) (st);
434
    ss->K = -1;
435
    ss->BlackIs1 = true;
436
    return s_CF_put_params(plist, (stream_CF_state *) ss);
437
}
438
 
439
private int
440
psdf_DCT_put_params(gs_param_list * plist, stream_state * st)
441
{
442
    return psdf_DCT_filter(plist, st, 8 /*nominal*/, 8 /*ibid.*/, 3 /*ibid.*/,
443
			   NULL);
444
}
445
 
446
/* Put [~](Always|Never)Embed parameters. */
447
private int
448
param_read_embed_array(gs_param_list * plist, gs_param_name pname,
449
		       gs_param_string_array * psa, int ecode)
450
{
451
    int code;
452
 
453
    psa->data = 0, psa->size = 0;
454
    switch (code = param_read_name_array(plist, pname, psa)) {
455
	default:
456
	    ecode = code;
457
	    param_signal_error(plist, pname, ecode);
458
	case 0:
459
	case 1:
460
	    break;
461
    }
462
    return ecode;
463
}
464
private bool
465
param_string_eq(const gs_param_string *ps1, const gs_param_string *ps2)
466
{
467
    return !bytes_compare(ps1->data, ps1->size, ps2->data, ps2->size);
468
}
469
private int
470
add_embed(gs_param_string_array *prsa, const gs_param_string_array *psa,
471
	  gs_memory_t *mem)
472
{
473
    uint i;
474
    gs_param_string *const rdata =
475
	(gs_param_string *)prsa->data; /* break const */
476
    uint count = prsa->size;
477
 
478
    for (i = 0; i < psa->size; ++i) {
479
	uint j;
480
 
481
	for (j = 0; j < count; ++j)
482
	    if (param_string_eq(&psa->data[i], &rdata[j]))
483
		    break;
484
	if (j == count) {
485
	    uint size = psa->data[i].size;
486
	    byte *data = gs_alloc_string(mem, size, "add_embed");
487
 
488
	    if (data == 0)
489
		return_error(gs_error_VMerror);
490
	    memcpy(data, psa->data[i].data, size);
491
	    rdata[count].data = data;
492
	    rdata[count].size = size;
493
	    rdata[count].persistent = false;
494
	    count++;
495
	}
496
    }
497
    prsa->size = count;
498
    return 0;
499
}
500
private void
501
delete_embed(gs_param_string_array *prsa, const gs_param_string_array *pnsa,
502
	     gs_memory_t *mem)
503
{
504
    uint i;
505
    gs_param_string *const rdata =
506
	(gs_param_string *)prsa->data; /* break const */
507
    uint count = prsa->size;
508
 
509
    for (i = pnsa->size; i-- > 0;) {
510
	uint j;
511
 
512
	for (j = count; j-- > 0;)
513
	    if (param_string_eq(&pnsa->data[i], &rdata[j]))
514
		break;
515
	if (j + 1 != 0) {
516
	    gs_free_const_string(mem, rdata[j].data, rdata[j].size,
517
				 "delete_embed");
518
	    rdata[j] = rdata[--count];
519
	}
520
    }
521
    prsa->size = count;
522
}
523
private int
524
psdf_put_embed_param(gs_param_list * plist, gs_param_name notpname,
525
		     gs_param_name allpname, gs_param_string_array * psa,
526
		     gs_memory_t *mem, int ecode)
527
{
528
    gs_param_name pname = notpname + 1;
529
    gs_param_string_array sa, nsa, asa;
530
    bool replace;
531
    gs_param_string *rdata;
532
    gs_param_string_array rsa;
533
    int code = 0;
534
 
535
    mem = gs_memory_stable(mem);
536
    ecode = param_read_embed_array(plist, pname, &sa, ecode);
537
    ecode = param_read_embed_array(plist, notpname, &nsa, ecode);
538
    ecode = param_read_embed_array(plist, allpname, &asa, ecode);
539
    if (ecode < 0)
540
	return ecode;
541
    /*
542
     * Figure out whether we're replacing (sa == asa or asa and no sa,
543
     * no nsa) or updating (all other cases).
544
     */
545
    if (asa.data == 0 || nsa.data != 0)
546
	replace = false;
547
    else if (sa.data == 0)
548
	replace = true;
549
    else if (sa.size != asa.size)
550
	replace = false;
551
    else {
552
	/* Test whether sa == asa. */
553
	uint i;
554
 
555
	replace = true;
556
	for (i = 0; i < sa.size; ++i)
557
	    if (!param_string_eq(&sa.data[i], &asa.data[i])) {
558
		replace = false;
559
		break;
560
	    }
561
	if (replace)
562
	    return 0;		/* no-op */
563
    }
564
    if (replace) {
565
	/* Wholesale replacement, only asa is relevant. */
566
	rdata = gs_alloc_struct_array(mem, asa.size, gs_param_string,
567
				      &st_param_string_element,
568
				      "psdf_put_embed_param(replace)");
569
	if (rdata == 0)
570
	    return_error(gs_error_VMerror);
571
	rsa.data = rdata;
572
	rsa.size = 0;
573
	if ((code = add_embed(&rsa, &asa, mem)) < 0) {
574
	    gs_free_object(mem, rdata, "psdf_put_embed_param(replace)");
575
	    ecode = code;
576
	} else
577
	    delete_embed(psa, psa, mem);
578
    } else if (sa.data || nsa.data) {
579
	/* Incremental update, sa and nsa are relevant, asa is not. */
580
	rdata = gs_alloc_struct_array(mem, psa->size + sa.size,
581
				      gs_param_string,
582
				      &st_param_string_element,
583
				      "psdf_put_embed_param(update)");
584
	if (rdata == 0)
585
	    return_error(gs_error_VMerror);
586
	memcpy(rdata, psa->data, psa->size * sizeof(*psa->data));
587
	rsa.data = rdata;
588
	rsa.size = psa->size;
589
	if ((code = add_embed(&rsa, &sa, mem)) < 0) {
590
	    gs_free_object(mem, rdata, "psdf_put_embed_param(update)");
591
	    ecode = code;
592
	} else {
593
	    delete_embed(&rsa, &nsa, mem);
594
	    rsa.data = gs_resize_object(mem, rdata, rsa.size,
595
					"psdf_put_embed_param(resize)");
596
	}
597
    } else
598
	return 0;		/* no-op */
599
    if (code >= 0) {
600
	gs_free_const_object(mem, psa->data, "psdf_put_embed_param(free)");
601
	rsa.persistent = false;
602
	*psa = rsa;
603
    }
604
    return ecode;
605
}
606
 
607
/* Put an image Dict parameter. */
608
private int
609
psdf_put_image_dict_param(gs_param_list * plist, const gs_param_name pname,
610
			  gs_c_param_list **pplvalue,
611
			  const stream_template * template,
612
			  ss_put_params_t put_params, gs_memory_t * mem)
613
{
614
    gs_param_dict dict;
615
    gs_c_param_list *plvalue = *pplvalue;
616
    int code;
617
 
618
    mem = gs_memory_stable(mem);
619
    switch (code = param_begin_read_dict(plist, pname, &dict, false)) {
620
	default:
621
	    param_signal_error(plist, pname, code);
622
	    return code;
623
	case 1:
624
	    return 0;
625
	case 0: {
626
	    /* Check the parameter values now. */
627
	    stream_state *ss = s_alloc_state(mem, template->stype, pname);
628
 
629
	    if (ss == 0)
630
		return_error(gs_error_VMerror);
631
	    ss->template = template;
632
	    if (template->set_defaults)
633
		template->set_defaults(ss);
634
	    code = put_params(dict.list, ss);
635
	    if (template->release)
636
		template->release(ss);
637
	    gs_free_object(mem, ss, pname);
638
	    if (code < 0) {
639
		param_signal_error(plist, pname, code);
640
	    } else {
641
		plvalue = gs_c_param_list_alloc(mem, pname);
642
		if (plvalue == 0)
643
		    return_error(gs_error_VMerror);
644
		gs_c_param_list_write(plvalue, mem);
645
		code = param_list_copy((gs_param_list *)plvalue,
646
				       dict.list);
647
		if (code < 0) {
648
		    gs_c_param_list_release(plvalue);
649
		    gs_free_object(mem, plvalue, pname);
650
		    plvalue = *pplvalue;
651
		}
652
	    }
653
	}
654
	param_end_read_dict(plist, pname, &dict);
655
	break;
656
    }
657
    if (plvalue != *pplvalue) {
658
	if (*pplvalue)
659
	    gs_c_param_list_release(*pplvalue);
660
	*pplvalue = plvalue;
661
    }
662
    return code;
663
}
664
 
665
/* Put a set of image-related parameters. */
666
private int
667
psdf_put_image_params(const gx_device_psdf * pdev, gs_param_list * plist,
668
		      const psdf_image_param_names_t * pnames,
669
		      psdf_image_params * params, int ecode)
670
{
671
    gs_param_string fs;
672
    /*
673
     * Since this procedure can be called before the device is open,
674
     * we must use pdev->memory rather than pdev->v_memory.
675
     */
676
    gs_memory_t *mem = pdev->memory;
677
    gs_param_name pname;
678
    /* Skip AutoFilter for mono images. */
679
    const gs_param_item_t *items =
680
	(pnames->items[0].key == 0 ? pnames->items + 1 : pnames->items);
681
    int code = gs_param_read_items(plist, params, items);
682
 
683
    if ((pname = pnames->ACSDict) != 0) {
684
	code = psdf_put_image_dict_param(plist, pname, &params->ACSDict,
685
					 &s_DCTE_template,
686
					 psdf_DCT_put_params, mem);
687
	if (code < 0)
688
	    ecode = code;
689
    }
690
    /* (AntiAlias) */
691
    /* (AutoFilter) */
692
    /* (Depth) */
693
    if ((pname = pnames->Dict) != 0) {
694
	const stream_template *template;
695
	ss_put_params_t put_params;
696
 
697
	/* Hack to determine what kind of a Dict we want: */
698
	if (pnames->Dict[0] == 'M')
699
	    template = &s_CFE_template,
700
		put_params = psdf_CF_put_params;
701
	else
702
	    template = &s_DCTE_template,
703
		put_params = psdf_DCT_put_params;
704
	code = psdf_put_image_dict_param(plist, pname, &params->Dict,
705
					 template, put_params, mem);
706
	if (code < 0)
707
	    ecode = code;
708
    }
709
    /* (Downsample) */
710
    params->DownsampleType = (enum psdf_downsample_type)
711
	psdf_put_enum(plist, pnames->DownsampleType,
712
		      (int)params->DownsampleType, DownsampleType_names,
713
		      &ecode);
714
    /* (DownsampleThreshold) */
715
    /* (Encode) */
716
    switch (code = param_read_string(plist, pnames->Filter, &fs)) {
717
	case 0:
718
	    {
719
		const psdf_image_filter_name *pn = pnames->filter_names;
720
 
721
		while (pn->pname != 0 && !gs_param_string_eq(&fs, pn->pname))
722
		    pn++;
723
		if (pn->pname == 0 || pn->min_version > pdev->version) {
724
		    ecode = gs_error_rangecheck;
725
		    goto ipe;
726
		}
727
		params->Filter = pn->pname;
728
		params->filter_template = pn->template;
729
		break;
730
	    }
731
	default:
732
	    ecode = code;
733
	  ipe:param_signal_error(plist, pnames->Filter, ecode);
734
	case 1:
735
	    break;
736
    }
737
    /* (Resolution) */
738
    if (ecode >= 0) {		/* Force parameters to acceptable values. */
739
	if (params->Resolution < 1)
740
	    params->Resolution = 1;
741
	if (params->DownsampleThreshold < 1 ||
742
	    params->DownsampleThreshold > 10)
743
	    params->DownsampleThreshold = pnames->DownsampleThreshold_default;
744
	switch (params->Depth) {
745
	    default:
746
		params->Depth = -1;
747
	    case 1:
748
	    case 2:
749
	    case 4:
750
	    case 8:
751
	    case -1:
752
		break;
753
	}
754
    }
755
    return ecode;
756
}
757
 
758
/* Put parameters. */
759
int
760
gdev_psdf_put_params(gx_device * dev, gs_param_list * plist)
761
{
762
    gx_device_psdf *pdev = (gx_device_psdf *) dev;
763
    gs_memory_t *mem =
764
	(pdev->v_memory ? pdev->v_memory : dev->memory);
765
    int ecode, code;
766
    psdf_distiller_params params;
767
 
768
    params = pdev->params;
769
 
770
    /*
771
     * If LockDistillerParams was true and isn't being set to false,
772
     * ignore all other psdf parameters.  However, do not ignore the
773
     * standard device parameters.
774
     */
775
    ecode = code = param_read_bool(plist, "LockDistillerParams",
776
  				   &params.LockDistillerParams);
777
    if (!(pdev->params.LockDistillerParams && params.LockDistillerParams)) {
778
 
779
	/* General parameters. */
780
 
781
	code = gs_param_read_items(plist, &params, psdf_param_items);
782
	if (code < 0)
783
	    ecode = code;
784
	params.AutoRotatePages = (enum psdf_auto_rotate_pages)
785
	    psdf_put_enum(plist, "AutoRotatePages", (int)params.AutoRotatePages,
786
			  AutoRotatePages_names, &ecode);
787
	params.Binding = (enum psdf_binding)
788
	    psdf_put_enum(plist, "Binding", (int)params.Binding,
789
			  Binding_names, &ecode);
790
	params.DefaultRenderingIntent = (enum psdf_default_rendering_intent)
791
	    psdf_put_enum(plist, "DefaultRenderingIntent",
792
			  (int)params.DefaultRenderingIntent,
793
			  DefaultRenderingIntent_names, &ecode);
794
	params.TransferFunctionInfo = (enum psdf_transfer_function_info)
795
	    psdf_put_enum(plist, "TransferFunctionInfo",
796
			  (int)params.TransferFunctionInfo,
797
			  TransferFunctionInfo_names, &ecode);
798
	params.UCRandBGInfo = (enum psdf_ucr_and_bg_info)
799
	    psdf_put_enum(plist, "UCRandBGInfo", (int)params.UCRandBGInfo,
800
			  UCRandBGInfo_names, &ecode);
801
	ecode = param_put_bool(plist, "UseFlateCompression",
802
			       &params.UseFlateCompression, ecode);
803
 
804
	/* Color sampled image parameters */
805
 
806
	ecode = psdf_put_image_params(pdev, plist, &Color_names,
807
				      &params.ColorImage, ecode);
808
	params.ColorConversionStrategy = (enum psdf_color_conversion_strategy)
809
	    psdf_put_enum(plist, "ColorConversionStrategy",
810
			  (int)params.ColorConversionStrategy,
811
			  ColorConversionStrategy_names, &ecode);
812
	ecode = psdf_read_string_param(plist, "CalCMYKProfile",
813
				       &params.CalCMYKProfile, mem, ecode);
814
	ecode = psdf_read_string_param(plist, "CalGrayProfile",
815
				       &params.CalGrayProfile, mem, ecode);
816
	ecode = psdf_read_string_param(plist, "CalRGBProfile",
817
				       &params.CalRGBProfile, mem, ecode);
818
	ecode = psdf_read_string_param(plist, "sRGBProfile",
819
				       &params.sRGBProfile, mem, ecode);
820
 
821
	/* Gray sampled image parameters */
822
 
823
	ecode = psdf_put_image_params(pdev, plist, &Gray_names,
824
				      &params.GrayImage, ecode);
825
 
826
	/* Mono sampled image parameters */
827
 
828
	ecode = psdf_put_image_params(pdev, plist, &Mono_names,
829
				      &params.MonoImage, ecode);
830
 
831
	/* Font embedding parameters */
832
 
833
	ecode = psdf_put_embed_param(plist, "~AlwaysEmbed", ".AlwaysEmbed",
834
				     &params.AlwaysEmbed, mem, ecode);
835
	ecode = psdf_put_embed_param(plist, "~NeverEmbed", ".NeverEmbed",
836
				     &params.NeverEmbed, mem, ecode);
837
	params.CannotEmbedFontPolicy = (enum psdf_cannot_embed_font_policy)
838
	    psdf_put_enum(plist, "CannotEmbedFontPolicy",
839
			  (int)params.CannotEmbedFontPolicy,
840
			  CannotEmbedFontPolicy_names, &ecode);
841
    }
842
    if (ecode < 0)
843
	return ecode;
844
    code = gdev_vector_put_params(dev, plist);
845
    if (code < 0)
846
	return code;
847
 
848
    pdev->params = params;	/* OK to update now */
849
    return 0;
850
}