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
RELOC_PTRS_WITH(param_string_reloc_ptrs,gs_param_string * pstr)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
psdf_write_name(gs_param_list * plist,const char * key,const char * str)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
psdf_write_string_param(gs_param_list * plist,const char * key,const gs_const_string * pstr)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
psdf_get_image_dict_param(gs_param_list * plist,const gs_param_name pname,gs_c_param_list * plvalue)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
psdf_get_image_params(gs_param_list * plist,const psdf_image_param_names_t * pnames,psdf_image_params * params)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
psdf_get_embed_param(gs_param_list * plist,gs_param_name allpname,const gs_param_string_array * psa)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
gdev_psdf_get_params(gx_device * dev,gs_param_list * plist)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
psdf_read_string_param(gs_param_list * plist,const char * key,gs_const_string * pstr,gs_memory_t * mem,int ecode)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
psdf_put_enum(gs_param_list * plist,const char * key,int value,const char * const pnames[],int * pecode)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
psdf_CF_put_params(gs_param_list * plist,stream_state * st)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
psdf_DCT_put_params(gs_param_list * plist,stream_state * st)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
param_read_embed_array(gs_param_list * plist,gs_param_name pname,gs_param_string_array * psa,int ecode)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
param_string_eq(const gs_param_string * ps1,const gs_param_string * ps2)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
add_embed(gs_param_string_array * prsa,const gs_param_string_array * psa,gs_memory_t * mem)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
delete_embed(gs_param_string_array * prsa,const gs_param_string_array * pnsa,gs_memory_t * mem)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
psdf_put_embed_param(gs_param_list * plist,gs_param_name notpname,gs_param_name allpname,gs_param_string_array * psa,gs_memory_t * mem,int ecode)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
psdf_put_image_dict_param(gs_param_list * plist,const gs_param_name pname,gs_c_param_list ** pplvalue,const stream_template * template,ss_put_params_t put_params,gs_memory_t * mem)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
psdf_put_image_params(const gx_device_psdf * pdev,gs_param_list * plist,const psdf_image_param_names_t * pnames,psdf_image_params * params,int ecode)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, ¶ms->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, ¶ms->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
gdev_psdf_put_params(gx_device * dev,gs_param_list * plist)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 ¶ms.LockDistillerParams);
777 if (!(pdev->params.LockDistillerParams && params.LockDistillerParams)) {
778
779 /* General parameters. */
780
781 code = gs_param_read_items(plist, ¶ms, 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 ¶ms.UseFlateCompression, ecode);
803
804 /* Color sampled image parameters */
805
806 ecode = psdf_put_image_params(pdev, plist, &Color_names,
807 ¶ms.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 ¶ms.CalCMYKProfile, mem, ecode);
814 ecode = psdf_read_string_param(plist, "CalGrayProfile",
815 ¶ms.CalGrayProfile, mem, ecode);
816 ecode = psdf_read_string_param(plist, "CalRGBProfile",
817 ¶ms.CalRGBProfile, mem, ecode);
818 ecode = psdf_read_string_param(plist, "sRGBProfile",
819 ¶ms.sRGBProfile, mem, ecode);
820
821 /* Gray sampled image parameters */
822
823 ecode = psdf_put_image_params(pdev, plist, &Gray_names,
824 ¶ms.GrayImage, ecode);
825
826 /* Mono sampled image parameters */
827
828 ecode = psdf_put_image_params(pdev, plist, &Mono_names,
829 ¶ms.MonoImage, ecode);
830
831 /* Font embedding parameters */
832
833 ecode = psdf_put_embed_param(plist, "~AlwaysEmbed", ".AlwaysEmbed",
834 ¶ms.AlwaysEmbed, mem, ecode);
835 ecode = psdf_put_embed_param(plist, "~NeverEmbed", ".NeverEmbed",
836 ¶ms.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 }
851