2 |
- |
1 |
/* Copyright (C) 1996, 2000, 2001 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: gdevpdfp.c,v 1.53 2005/09/12 11:34:50 leonardo Exp $ */
|
|
|
18 |
/* Get/put parameters for PDF-writing driver */
|
|
|
19 |
#include "memory_.h"
|
|
|
20 |
#include "string_.h"
|
|
|
21 |
#include "gx.h"
|
|
|
22 |
#include "gserrors.h"
|
|
|
23 |
#include "gdevpdfx.h"
|
|
|
24 |
#include "gdevpdfo.h"
|
|
|
25 |
#include "gdevpdfg.h"
|
|
|
26 |
#include "gsparamx.h"
|
|
|
27 |
|
|
|
28 |
/*
|
|
|
29 |
* The pdfwrite device supports the following "real" parameters:
|
|
|
30 |
* OutputFile <string>
|
|
|
31 |
* all the Distiller parameters (also see gdevpsdp.c)
|
|
|
32 |
* Only some of the Distiller parameters actually have any effect.
|
|
|
33 |
*
|
|
|
34 |
* The device also supports the following write-only pseudo-parameters that
|
|
|
35 |
* serve only to communicate other information from the PostScript file.
|
|
|
36 |
* Their "value" is an array of strings, some of which may be the result
|
|
|
37 |
* of converting arbitrary PostScript objects to string form.
|
|
|
38 |
* pdfmark - see gdevpdfm.c
|
|
|
39 |
* DSC - processed in this file
|
|
|
40 |
*/
|
|
|
41 |
private int pdf_dsc_process(gx_device_pdf * pdev,
|
|
|
42 |
const gs_param_string_array * pma);
|
|
|
43 |
|
|
|
44 |
private const int CoreDistVersion = 5000; /* Distiller 5.0 */
|
|
|
45 |
private const gs_param_item_t pdf_param_items[] = {
|
|
|
46 |
#define pi(key, type, memb) { key, type, offset_of(gx_device_pdf, memb) }
|
|
|
47 |
|
|
|
48 |
/* Acrobat Distiller 4 parameters */
|
|
|
49 |
|
|
|
50 |
/*
|
|
|
51 |
* EndPage and StartPage are renamed because EndPage collides with
|
|
|
52 |
* a page device parameter.
|
|
|
53 |
*/
|
|
|
54 |
pi("PDFEndPage", gs_param_type_int, EndPage),
|
|
|
55 |
pi("PDFStartPage", gs_param_type_int, StartPage),
|
|
|
56 |
pi("Optimize", gs_param_type_bool, Optimize),
|
|
|
57 |
pi("ParseDSCCommentsForDocInfo", gs_param_type_bool,
|
|
|
58 |
ParseDSCCommentsForDocInfo),
|
|
|
59 |
pi("ParseDSCComments", gs_param_type_bool, ParseDSCComments),
|
|
|
60 |
pi("EmitDSCWarnings", gs_param_type_bool, EmitDSCWarnings),
|
|
|
61 |
pi("CreateJobTicket", gs_param_type_bool, CreateJobTicket),
|
|
|
62 |
pi("PreserveEPSInfo", gs_param_type_bool, PreserveEPSInfo),
|
|
|
63 |
pi("AutoPositionEPSFiles", gs_param_type_bool, AutoPositionEPSFiles),
|
|
|
64 |
pi("PreserveCopyPage", gs_param_type_bool, PreserveCopyPage),
|
|
|
65 |
pi("UsePrologue", gs_param_type_bool, UsePrologue),
|
|
|
66 |
|
|
|
67 |
/* Acrobat Distiller 5 parameters */
|
|
|
68 |
|
|
|
69 |
pi("OffOptimizations", gs_param_type_int, OffOptimizations),
|
|
|
70 |
|
|
|
71 |
/* Ghostscript-specific parameters */
|
|
|
72 |
|
|
|
73 |
pi("ReAssignCharacters", gs_param_type_bool, ReAssignCharacters),
|
|
|
74 |
pi("ReEncodeCharacters", gs_param_type_bool, ReEncodeCharacters),
|
|
|
75 |
pi("FirstObjectNumber", gs_param_type_long, FirstObjectNumber),
|
|
|
76 |
pi("CompressFonts", gs_param_type_bool, CompressFonts),
|
|
|
77 |
pi("PrintStatistics", gs_param_type_bool, PrintStatistics),
|
|
|
78 |
pi("MaxInlineImageSize", gs_param_type_long, MaxInlineImageSize),
|
|
|
79 |
|
|
|
80 |
/* PDF Encryption */
|
|
|
81 |
pi("OwnerPassword", gs_param_type_string, OwnerPassword),
|
|
|
82 |
pi("UserPassword", gs_param_type_string, UserPassword),
|
|
|
83 |
pi("KeyLength", gs_param_type_int, KeyLength),
|
|
|
84 |
pi("Permissions", gs_param_type_int, Permissions),
|
|
|
85 |
pi("EncryptionR", gs_param_type_int, EncryptionR),
|
|
|
86 |
pi("NoEncrypt", gs_param_type_string, NoEncrypt),
|
|
|
87 |
|
|
|
88 |
/* Target viewer capabilities (Ghostscript-specific) */
|
|
|
89 |
pi("ForOPDFRead", gs_param_type_bool, ForOPDFRead),
|
|
|
90 |
pi("PatternImagemask", gs_param_type_bool, PatternImagemask),
|
|
|
91 |
pi("MaxClipPathSize", gs_param_type_int, MaxClipPathSize),
|
|
|
92 |
pi("MaxShadingBitmapSize", gs_param_type_int, MaxShadingBitmapSize),
|
|
|
93 |
pi("MaxViewerMemorySize", gs_param_type_int, MaxViewerMemorySize),
|
|
|
94 |
pi("HaveTrueTypes", gs_param_type_bool, HaveTrueTypes),
|
|
|
95 |
pi("HaveCIDSystem", gs_param_type_bool, HaveCIDSystem),
|
|
|
96 |
pi("HaveTransparency", gs_param_type_bool, HaveTransparency),
|
|
|
97 |
pi("OPDFReadProcsetPath", gs_param_type_string, OPDFReadProcsetPath),
|
|
|
98 |
pi("CompressEntireFile", gs_param_type_bool, CompressEntireFile),
|
|
|
99 |
pi("PDFX", gs_param_type_bool, PDFX),
|
|
|
100 |
#undef pi
|
|
|
101 |
gs_param_item_end
|
|
|
102 |
};
|
|
|
103 |
|
|
|
104 |
/*
|
|
|
105 |
Notes on implementing the remaining Distiller functionality
|
|
|
106 |
===========================================================
|
|
|
107 |
|
|
|
108 |
Architectural issues
|
|
|
109 |
--------------------
|
|
|
110 |
|
|
|
111 |
Must optionally disable application of TR, BG, UCR similarly. Affects:
|
|
|
112 |
PreserveHalftoneInfo
|
|
|
113 |
PreserveOverprintSettings
|
|
|
114 |
TransferFunctionInfo
|
|
|
115 |
UCRandBGInfo
|
|
|
116 |
|
|
|
117 |
Current limitations
|
|
|
118 |
-------------------
|
|
|
119 |
|
|
|
120 |
Non-primary elements in HalftoneType 5 are not written correctly
|
|
|
121 |
|
|
|
122 |
Acrobat Distiller 3
|
|
|
123 |
-------------------
|
|
|
124 |
|
|
|
125 |
---- Image parameters ----
|
|
|
126 |
|
|
|
127 |
AntiAlias{Color,Gray,Mono}Images
|
|
|
128 |
|
|
|
129 |
---- Other parameters ----
|
|
|
130 |
|
|
|
131 |
CompressPages
|
|
|
132 |
Compress things other than page contents
|
|
|
133 |
* PreserveHalftoneInfo
|
|
|
134 |
PreserveOPIComments
|
|
|
135 |
? see OPI spec?
|
|
|
136 |
* PreserveOverprintSettings
|
|
|
137 |
* TransferFunctionInfo
|
|
|
138 |
* UCRandBGInfo
|
|
|
139 |
ColorConversionStrategy
|
|
|
140 |
Select color space for drawing commands
|
|
|
141 |
ConvertImagesToIndexed
|
|
|
142 |
Postprocess image data *after* downsampling (requires an extra pass)
|
|
|
143 |
|
|
|
144 |
Acrobat Distiller 4
|
|
|
145 |
-------------------
|
|
|
146 |
|
|
|
147 |
---- Other functionality ----
|
|
|
148 |
|
|
|
149 |
Document structure pdfmarks
|
|
|
150 |
|
|
|
151 |
---- Parameters ----
|
|
|
152 |
|
|
|
153 |
xxxDownsampleType = /Bicubic
|
|
|
154 |
Add new filter (or use siscale?) & to setup (gdevpsdi.c)
|
|
|
155 |
DetectBlends
|
|
|
156 |
Idiom recognition? PatternType 2 patterns / shfill? (see AD4)
|
|
|
157 |
DoThumbnails
|
|
|
158 |
Also output to memory device -- resolution issue
|
|
|
159 |
|
|
|
160 |
---- Job-level control ----
|
|
|
161 |
|
|
|
162 |
EmitDSCWarnings
|
|
|
163 |
Require DSC parser / interceptor
|
|
|
164 |
CreateJobTicket
|
|
|
165 |
?
|
|
|
166 |
AutoPositionEPSFiles
|
|
|
167 |
Require DSC parsing
|
|
|
168 |
PreserveCopyPage
|
|
|
169 |
Concatenate Contents streams
|
|
|
170 |
UsePrologue
|
|
|
171 |
Needs hack in top-level control?
|
|
|
172 |
|
|
|
173 |
*/
|
|
|
174 |
|
|
|
175 |
/* ---------------- Get parameters ---------------- */
|
|
|
176 |
|
|
|
177 |
/* Get parameters. */
|
|
|
178 |
int
|
|
|
179 |
gdev_pdf_get_params(gx_device * dev, gs_param_list * plist)
|
|
|
180 |
{
|
|
|
181 |
gx_device_pdf *pdev = (gx_device_pdf *) dev;
|
|
|
182 |
float cl = (float)pdev->CompatibilityLevel;
|
|
|
183 |
int code = gdev_psdf_get_params(dev, plist);
|
|
|
184 |
int cdv = CoreDistVersion;
|
|
|
185 |
int EmbedFontObjects = 1;
|
|
|
186 |
|
|
|
187 |
if (code < 0 ||
|
|
|
188 |
(code = param_write_int(plist, ".EmbedFontObjects", &EmbedFontObjects)) < 0 ||
|
|
|
189 |
(code = param_write_int(plist, "CoreDistVersion", &cdv)) < 0 ||
|
|
|
190 |
(code = param_write_float(plist, "CompatibilityLevel", &cl)) < 0 ||
|
|
|
191 |
/* Indicate that we can process pdfmark and DSC. */
|
|
|
192 |
(param_requested(plist, "pdfmark") > 0 &&
|
|
|
193 |
(code = param_write_null(plist, "pdfmark")) < 0) ||
|
|
|
194 |
(param_requested(plist, "DSC") > 0 &&
|
|
|
195 |
(code = param_write_null(plist, "DSC")) < 0) ||
|
|
|
196 |
(code = gs_param_write_items(plist, pdev, NULL, pdf_param_items)) < 0
|
|
|
197 |
);
|
|
|
198 |
return code;
|
|
|
199 |
}
|
|
|
200 |
|
|
|
201 |
/* ---------------- Put parameters ---------------- */
|
|
|
202 |
|
|
|
203 |
/* Put parameters. */
|
|
|
204 |
int
|
|
|
205 |
gdev_pdf_put_params(gx_device * dev, gs_param_list * plist)
|
|
|
206 |
{
|
|
|
207 |
gx_device_pdf *pdev = (gx_device_pdf *) dev;
|
|
|
208 |
int ecode, code;
|
|
|
209 |
gx_device_pdf save_dev;
|
|
|
210 |
float cl = (float)pdev->CompatibilityLevel;
|
|
|
211 |
bool locked = pdev->params.LockDistillerParams;
|
|
|
212 |
gs_param_name param_name;
|
|
|
213 |
|
|
|
214 |
/*
|
|
|
215 |
* If this is a pseudo-parameter (pdfmark or DSC),
|
|
|
216 |
* don't bother checking for any real ones.
|
|
|
217 |
*/
|
|
|
218 |
|
|
|
219 |
{
|
|
|
220 |
gs_param_string_array ppa;
|
|
|
221 |
|
|
|
222 |
code = param_read_string_array(plist, (param_name = "pdfmark"), &ppa);
|
|
|
223 |
switch (code) {
|
|
|
224 |
case 0:
|
|
|
225 |
code = pdf_open_document(pdev);
|
|
|
226 |
if (code < 0)
|
|
|
227 |
return code;
|
|
|
228 |
code = pdfmark_process(pdev, &ppa);
|
|
|
229 |
if (code >= 0)
|
|
|
230 |
return code;
|
|
|
231 |
/* falls through for errors */
|
|
|
232 |
default:
|
|
|
233 |
param_signal_error(plist, param_name, code);
|
|
|
234 |
return code;
|
|
|
235 |
case 1:
|
|
|
236 |
break;
|
|
|
237 |
}
|
|
|
238 |
|
|
|
239 |
code = param_read_string_array(plist, (param_name = "DSC"), &ppa);
|
|
|
240 |
switch (code) {
|
|
|
241 |
case 0:
|
|
|
242 |
code = pdf_open_document(pdev);
|
|
|
243 |
if (code < 0)
|
|
|
244 |
return code;
|
|
|
245 |
code = pdf_dsc_process(pdev, &ppa);
|
|
|
246 |
if (code >= 0)
|
|
|
247 |
return code;
|
|
|
248 |
/* falls through for errors */
|
|
|
249 |
default:
|
|
|
250 |
param_signal_error(plist, param_name, code);
|
|
|
251 |
return code;
|
|
|
252 |
case 1:
|
|
|
253 |
break;
|
|
|
254 |
}
|
|
|
255 |
}
|
|
|
256 |
|
|
|
257 |
/*
|
|
|
258 |
* Check for LockDistillerParams before doing anything else.
|
|
|
259 |
* If LockDistillerParams is true and is not being set to false,
|
|
|
260 |
* ignore all resettings of PDF-specific parameters. Note that
|
|
|
261 |
* LockDistillerParams is read again, and reset if necessary, in
|
|
|
262 |
* psdf_put_params.
|
|
|
263 |
*/
|
|
|
264 |
ecode = code = param_read_bool(plist, "LockDistillerParams", &locked);
|
|
|
265 |
|
|
|
266 |
if (!(locked && pdev->params.LockDistillerParams)) {
|
|
|
267 |
/* General parameters. */
|
|
|
268 |
|
|
|
269 |
{
|
|
|
270 |
int efo = 1;
|
|
|
271 |
|
|
|
272 |
ecode = param_put_int(plist, (param_name = ".EmbedFontObjects"), &efo, ecode);
|
|
|
273 |
if (efo != 1)
|
|
|
274 |
param_signal_error(plist, param_name, ecode = gs_error_rangecheck);
|
|
|
275 |
}
|
|
|
276 |
{
|
|
|
277 |
int cdv = CoreDistVersion;
|
|
|
278 |
|
|
|
279 |
ecode = param_put_int(plist, (param_name = "CoreDistVersion"), &cdv, ecode);
|
|
|
280 |
if (cdv != CoreDistVersion)
|
|
|
281 |
param_signal_error(plist, param_name, ecode = gs_error_rangecheck);
|
|
|
282 |
}
|
|
|
283 |
|
|
|
284 |
save_dev = *pdev;
|
|
|
285 |
|
|
|
286 |
switch (code = param_read_float(plist, (param_name = "CompatibilityLevel"), &cl)) {
|
|
|
287 |
default:
|
|
|
288 |
ecode = code;
|
|
|
289 |
param_signal_error(plist, param_name, ecode);
|
|
|
290 |
case 0:
|
|
|
291 |
/*
|
|
|
292 |
* Must be 1.2, 1.3, or 1.4. Per Adobe documentation, substitute
|
|
|
293 |
* the nearest achievable value.
|
|
|
294 |
*/
|
|
|
295 |
if (cl < (float)1.15)
|
|
|
296 |
cl = (float)1.1;
|
|
|
297 |
else if (cl < (float)1.25)
|
|
|
298 |
cl = (float)1.2;
|
|
|
299 |
else if (cl >= (float)1.35)
|
|
|
300 |
cl = (float)1.4;
|
|
|
301 |
else
|
|
|
302 |
cl = (float)1.3;
|
|
|
303 |
case 1:
|
|
|
304 |
break;
|
|
|
305 |
}
|
|
|
306 |
|
|
|
307 |
code = gs_param_read_items(plist, pdev, pdf_param_items);
|
|
|
308 |
if (code < 0)
|
|
|
309 |
ecode = code;
|
|
|
310 |
{
|
|
|
311 |
/*
|
|
|
312 |
* Setting FirstObjectNumber is only legal if the file
|
|
|
313 |
* has just been opened and nothing has been written,
|
|
|
314 |
* or if we are setting it to the same value.
|
|
|
315 |
*/
|
|
|
316 |
long fon = pdev->FirstObjectNumber;
|
|
|
317 |
|
|
|
318 |
if (fon != save_dev.FirstObjectNumber) {
|
|
|
319 |
if (fon <= 0 || fon > 0x7fff0000 ||
|
|
|
320 |
(pdev->next_id != 0 &&
|
|
|
321 |
pdev->next_id !=
|
|
|
322 |
save_dev.FirstObjectNumber + pdf_num_initial_ids)
|
|
|
323 |
) {
|
|
|
324 |
ecode = gs_error_rangecheck;
|
|
|
325 |
param_signal_error(plist, "FirstObjectNumber", ecode);
|
|
|
326 |
}
|
|
|
327 |
}
|
|
|
328 |
}
|
|
|
329 |
{
|
|
|
330 |
/*
|
|
|
331 |
* Set ProcessColorModel now, because gx_default_put_params checks
|
|
|
332 |
* it.
|
|
|
333 |
*/
|
|
|
334 |
static const char *const pcm_names[] = {
|
|
|
335 |
"DeviceGray", "DeviceRGB", "DeviceCMYK", "DeviceN", 0
|
|
|
336 |
};
|
|
|
337 |
int pcm = -1;
|
|
|
338 |
|
|
|
339 |
ecode = param_put_enum(plist, "ProcessColorModel", &pcm,
|
|
|
340 |
pcm_names, ecode);
|
|
|
341 |
if (pcm >= 0) {
|
|
|
342 |
pdf_set_process_color_model(pdev, pcm);
|
|
|
343 |
pdf_set_initial_color(pdev, &pdev->saved_fill_color, &pdev->saved_stroke_color,
|
|
|
344 |
&pdev->fill_used_process_color, &pdev->stroke_used_process_color);
|
|
|
345 |
}
|
|
|
346 |
}
|
|
|
347 |
}
|
|
|
348 |
if (ecode < 0)
|
|
|
349 |
goto fail;
|
|
|
350 |
/*
|
|
|
351 |
* We have to set version to the new value, because the set of
|
|
|
352 |
* legal parameter values for psdf_put_params varies according to
|
|
|
353 |
* the version.
|
|
|
354 |
*/
|
|
|
355 |
if (pdev->PDFX)
|
|
|
356 |
cl = (float)1.3; /* Instead pdev->CompatibilityLevel = 1.2; - see below. */
|
|
|
357 |
pdev->version = (cl < 1.2 ? psdf_version_level2 : psdf_version_ll3);
|
|
|
358 |
if (pdev->ForOPDFRead) {
|
|
|
359 |
pdev->ResourcesBeforeUsage = true;
|
|
|
360 |
pdev->HaveCFF = false;
|
|
|
361 |
pdev->HavePDFWidths = false;
|
|
|
362 |
pdev->HaveStrokeColor = false;
|
|
|
363 |
cl = (float)1.2; /* Instead pdev->CompatibilityLevel = 1.2; - see below. */
|
|
|
364 |
pdev->MaxInlineImageSize = max_long; /* Save printer's RAM from saving temporary image data.
|
|
|
365 |
Immediate images doen't need buffering. */
|
|
|
366 |
pdev->version = psdf_version_level2;
|
|
|
367 |
} else {
|
|
|
368 |
pdev->ResourcesBeforeUsage = false;
|
|
|
369 |
pdev->HaveCFF = true;
|
|
|
370 |
pdev->HavePDFWidths = true;
|
|
|
371 |
pdev->HaveStrokeColor = true;
|
|
|
372 |
}
|
|
|
373 |
ecode = gdev_psdf_put_params(dev, plist);
|
|
|
374 |
if (ecode < 0)
|
|
|
375 |
goto fail;
|
|
|
376 |
if (pdev->HaveTrueTypes && pdev->version == psdf_version_level2) {
|
|
|
377 |
pdev->version = psdf_version_level2_with_TT ;
|
|
|
378 |
}
|
|
|
379 |
/*
|
|
|
380 |
* Acrobat Reader doesn't handle user-space coordinates larger than
|
|
|
381 |
* MAX_USER_COORD. To compensate for this, reduce the resolution so
|
|
|
382 |
* that the page size in device space (which we equate to user space) is
|
|
|
383 |
* significantly less than MAX_USER_COORD. Note that this still does
|
|
|
384 |
* not protect us against input files that use coordinates far outside
|
|
|
385 |
* the page boundaries.
|
|
|
386 |
*/
|
|
|
387 |
#define MAX_EXTENT ((int)(MAX_USER_COORD * 0.9))
|
|
|
388 |
/* Changing resolution or page size requires closing the device, */
|
|
|
389 |
if (dev->height > MAX_EXTENT || dev->width > MAX_EXTENT) {
|
|
|
390 |
double factor =
|
|
|
391 |
max(dev->height / (double)MAX_EXTENT,
|
|
|
392 |
dev->width / (double)MAX_EXTENT);
|
|
|
393 |
|
|
|
394 |
gx_device_set_resolution(dev, dev->HWResolution[0] / factor,
|
|
|
395 |
dev->HWResolution[1] / factor);
|
|
|
396 |
}
|
|
|
397 |
#undef MAX_EXTENT
|
|
|
398 |
if (pdev->FirstObjectNumber != save_dev.FirstObjectNumber) {
|
|
|
399 |
if (pdev->xref.file != 0) {
|
|
|
400 |
fseek(pdev->xref.file, 0L, SEEK_SET);
|
|
|
401 |
pdf_initialize_ids(pdev);
|
|
|
402 |
}
|
|
|
403 |
}
|
|
|
404 |
/* Handle the float/double mismatch. */
|
|
|
405 |
pdev->CompatibilityLevel = (int)(cl * 10 + 0.5) / 10.0;
|
|
|
406 |
return 0;
|
|
|
407 |
fail:
|
|
|
408 |
/* Restore all the parameters to their original state. */
|
|
|
409 |
pdev->version = save_dev.version;
|
|
|
410 |
pdf_set_process_color_model(pdev, save_dev.pcm_color_info_index);
|
|
|
411 |
pdev->saved_fill_color = save_dev.saved_fill_color;
|
|
|
412 |
pdev->saved_stroke_color = save_dev.saved_fill_color;
|
|
|
413 |
{
|
|
|
414 |
const gs_param_item_t *ppi = pdf_param_items;
|
|
|
415 |
|
|
|
416 |
for (; ppi->key; ++ppi)
|
|
|
417 |
memcpy((char *)pdev + ppi->offset,
|
|
|
418 |
(char *)&save_dev + ppi->offset,
|
|
|
419 |
gs_param_type_sizes[ppi->type]);
|
|
|
420 |
}
|
|
|
421 |
return ecode;
|
|
|
422 |
}
|
|
|
423 |
|
|
|
424 |
/* ---------------- Process DSC comments ---------------- */
|
|
|
425 |
|
|
|
426 |
private int
|
|
|
427 |
pdf_dsc_process(gx_device_pdf * pdev, const gs_param_string_array * pma)
|
|
|
428 |
{
|
|
|
429 |
/*
|
|
|
430 |
* The Adobe "Distiller Parameters" documentation says that Distiller
|
|
|
431 |
* looks at DSC comments, but it doesn't say which ones. We look at
|
|
|
432 |
* the ones that we see how to map directly to obvious PDF constructs.
|
|
|
433 |
*/
|
|
|
434 |
int code = 0;
|
|
|
435 |
int i;
|
|
|
436 |
|
|
|
437 |
/*
|
|
|
438 |
* If ParseDSCComments is false, all DSC comments are ignored, even if
|
|
|
439 |
* ParseDSCComentsForDocInfo or PreserveEPSInfo is true.
|
|
|
440 |
*/
|
|
|
441 |
if (!pdev->ParseDSCComments)
|
|
|
442 |
return 0;
|
|
|
443 |
|
|
|
444 |
for (i = 0; i + 1 < pma->size && code >= 0; i += 2) {
|
|
|
445 |
const gs_param_string *pkey = &pma->data[i];
|
|
|
446 |
const gs_param_string *pvalue = &pma->data[i + 1];
|
|
|
447 |
const char *key;
|
|
|
448 |
int code;
|
|
|
449 |
|
|
|
450 |
/*
|
|
|
451 |
* %%For, %%Creator, and %%Title are recognized only if either
|
|
|
452 |
* ParseDSCCommentsForDocInfo or PreserveEPSInfo is true.
|
|
|
453 |
* The other DSC comments are always recognized.
|
|
|
454 |
*
|
|
|
455 |
* Acrobat Distiller sets CreationDate and ModDate to the current
|
|
|
456 |
* time, not the value of %%CreationDate. We think this is wrong,
|
|
|
457 |
* but we do the same -- we ignore %%CreationDate here.
|
|
|
458 |
*/
|
|
|
459 |
|
|
|
460 |
if (pdf_key_eq(pkey, "Creator"))
|
|
|
461 |
key = "/Creator";
|
|
|
462 |
else if (pdf_key_eq(pkey, "Title"))
|
|
|
463 |
key = "/Title";
|
|
|
464 |
else if (pdf_key_eq(pkey, "For"))
|
|
|
465 |
key = "/Author";
|
|
|
466 |
else {
|
|
|
467 |
pdf_page_dsc_info_t *ppdi;
|
|
|
468 |
|
|
|
469 |
if ((ppdi = &pdev->doc_dsc_info,
|
|
|
470 |
pdf_key_eq(pkey, "Orientation")) ||
|
|
|
471 |
(ppdi = &pdev->page_dsc_info,
|
|
|
472 |
pdf_key_eq(pkey, "PageOrientation"))
|
|
|
473 |
) {
|
|
|
474 |
if (pvalue->size == 1 && pvalue->data[0] >= '0' &&
|
|
|
475 |
pvalue->data[0] <= '3'
|
|
|
476 |
)
|
|
|
477 |
ppdi->orientation = pvalue->data[0] - '0';
|
|
|
478 |
else
|
|
|
479 |
ppdi->orientation = -1;
|
|
|
480 |
} else if ((ppdi = &pdev->doc_dsc_info,
|
|
|
481 |
pdf_key_eq(pkey, "ViewingOrientation")) ||
|
|
|
482 |
(ppdi = &pdev->page_dsc_info,
|
|
|
483 |
pdf_key_eq(pkey, "PageViewingOrientation"))
|
|
|
484 |
) {
|
|
|
485 |
gs_matrix mat;
|
|
|
486 |
int orient;
|
|
|
487 |
|
|
|
488 |
if (sscanf((const char *)pvalue->data, "[%g %g %g %g]",
|
|
|
489 |
&mat.xx, &mat.xy, &mat.yx, &mat.yy) != 4
|
|
|
490 |
)
|
|
|
491 |
continue; /* error */
|
|
|
492 |
for (orient = 0; orient < 4; ++orient) {
|
|
|
493 |
if (mat.xx == 1 && mat.xy == 0 && mat.yx == 0 && mat.yy == 1)
|
|
|
494 |
break;
|
|
|
495 |
gs_matrix_rotate(&mat, -90.0, &mat);
|
|
|
496 |
}
|
|
|
497 |
if (orient == 4) /* error */
|
|
|
498 |
orient = -1;
|
|
|
499 |
ppdi->viewing_orientation = orient;
|
|
|
500 |
} else {
|
|
|
501 |
gs_rect box;
|
|
|
502 |
|
|
|
503 |
if (pdf_key_eq(pkey, "EPSF")) {
|
|
|
504 |
pdev->is_EPS = (pvalue->size >= 1 && pvalue->data[0] != '0');
|
|
|
505 |
continue;
|
|
|
506 |
}
|
|
|
507 |
/*
|
|
|
508 |
* We only parse the BoundingBox for the sake of
|
|
|
509 |
* AutoPositionEPSFiles.
|
|
|
510 |
*/
|
|
|
511 |
if (pdf_key_eq(pkey, "BoundingBox"))
|
|
|
512 |
ppdi = &pdev->doc_dsc_info;
|
|
|
513 |
else if (pdf_key_eq(pkey, "PageBoundingBox"))
|
|
|
514 |
ppdi = &pdev->page_dsc_info;
|
|
|
515 |
else
|
|
|
516 |
continue;
|
|
|
517 |
if (sscanf((const char *)pvalue->data, "[%lg %lg %lg %lg]",
|
|
|
518 |
&box.p.x, &box.p.y, &box.q.x, &box.q.y) != 4
|
|
|
519 |
)
|
|
|
520 |
continue; /* error */
|
|
|
521 |
ppdi->bounding_box = box;
|
|
|
522 |
}
|
|
|
523 |
continue;
|
|
|
524 |
}
|
|
|
525 |
|
|
|
526 |
if (pdev->ParseDSCCommentsForDocInfo || pdev->PreserveEPSInfo)
|
|
|
527 |
code = cos_dict_put_c_key_string(pdev->Info, key,
|
|
|
528 |
pvalue->data, pvalue->size);
|
|
|
529 |
}
|
|
|
530 |
return code;
|
|
|
531 |
}
|