Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/devices/vector/gdevpdfp.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2022 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
17
/* Get/put parameters for PDF-writing driver */
18
#include "memory_.h"
19
#include "gx.h"
20
#include "gserrors.h"
21
#include "gdevpdfx.h"
22
#include "gdevpdfo.h"
23
#include "gdevpdfg.h"
24
#include "gdevpsdf.h"
25
#include "gsparamx.h"
26
#include "gsicc_manage.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
static int pdf_dsc_process(gx_device_pdf * pdev,
42
                            const gs_param_string_array * pma);
43
44
static const int CoreDistVersion = 5000;  /* Distiller 5.0 */
45
static 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("CompressStreams", gs_param_type_bool, CompressStreams),
78
    pi("PrintStatistics", gs_param_type_bool, PrintStatistics),
79
    pi("MaxInlineImageSize", gs_param_type_long, MaxInlineImageSize),
80
81
        /* PDF Encryption */
82
    pi("OwnerPassword", gs_param_type_string, OwnerPassword),
83
    pi("UserPassword", gs_param_type_string, UserPassword),
84
    pi("KeyLength", gs_param_type_int, KeyLength),
85
    pi("Permissions", gs_param_type_int, Permissions),
86
    pi("EncryptionR", gs_param_type_int, EncryptionR),
87
    pi("NoEncrypt", gs_param_type_string, NoEncrypt),
88
89
        /* Target viewer capabilities (Ghostscript-specific)  */
90
 /* pi("ForOPDFRead", gs_param_type_bool, ForOPDFRead),         pdfwrite-only */
91
    pi("ProduceDSC", gs_param_type_bool, ProduceDSC),
92
    pi("PatternImagemask", gs_param_type_bool, PatternImagemask),
93
    pi("MaxClipPathSize", gs_param_type_int, MaxClipPathSize),
94
    pi("MaxShadingBitmapSize", gs_param_type_int, MaxShadingBitmapSize),
95
    pi("HaveTrueTypes", gs_param_type_bool, HaveTrueTypes),
96
    pi("HaveCIDSystem", gs_param_type_bool, HaveCIDSystem),
97
    pi("HaveTransparency", gs_param_type_bool, HaveTransparency),
98
    pi("CompressEntireFile", gs_param_type_bool, CompressEntireFile),
99
    pi("PDFX", gs_param_type_bool, PDFX),
100
    pi("PDFA", gs_param_type_int, PDFA),
101
    pi("DocumentUUID", gs_param_type_string, DocumentUUID),
102
    pi("InstanceUUID", gs_param_type_string, InstanceUUID),
103
    pi("DocumentTimeSeq", gs_param_type_int, DocumentTimeSeq),
104
105
    /* PDF/X parameters */
106
    pi("PDFXTrimBoxToMediaBoxOffset", gs_param_type_float_array, PDFXTrimBoxToMediaBoxOffset),
107
    pi("PDFXSetBleedBoxToMediaBox", gs_param_type_bool, PDFXSetBleedBoxToMediaBox),
108
    pi("PDFXBleedBoxToTrimBoxOffset", gs_param_type_float_array, PDFXBleedBoxToTrimBoxOffset),
109
110
    /* media selection parameters */
111
    pi("SetPageSize", gs_param_type_bool, SetPageSize),
112
    pi("RotatePages", gs_param_type_bool, RotatePages),
113
    pi("FitPages", gs_param_type_bool, FitPages),
114
    pi("CenterPages", gs_param_type_bool, CenterPages),
115
    pi("DoNumCopies", gs_param_type_bool, DoNumCopies),
116
    pi("PreserveSeparation", gs_param_type_bool, PreserveSeparation),
117
    pi("PreserveDeviceN", gs_param_type_bool, PreserveDeviceN),
118
    pi("PDFACompatibilityPolicy", gs_param_type_int, PDFACompatibilityPolicy),
119
    pi("DetectDuplicateImages", gs_param_type_bool, DetectDuplicateImages),
120
    pi("AllowIncrementalCFF", gs_param_type_bool, AllowIncrementalCFF),
121
    pi("WantsToUnicode", gs_param_type_bool, WantsToUnicode),
122
    pi("PdfmarkCapable", gs_param_type_bool, PdfmarkCapable),
123
    pi("AllowPSRepeatFunctions", gs_param_type_bool, AllowPSRepeatFunctions),
124
    pi("IsDistiller", gs_param_type_bool, IsDistiller),
125
    pi("PreserveSMask", gs_param_type_bool, PreserveSMask),
126
    pi("PreserveTrMode", gs_param_type_bool, PreserveTrMode),
127
    pi("NoT3CCITT", gs_param_type_bool, NoT3CCITT),
128
    pi("FastWebView", gs_param_type_bool, Linearise),
129
    pi("NoOutputFonts", gs_param_type_bool, FlattenFonts),
130
    pi("WantsPageLabels", gs_param_type_bool, WantsPageLabels),
131
    pi("UserUnit", gs_param_type_float, UserUnit),
132
    pi("OmitInfoDate", gs_param_type_bool, OmitInfoDate),
133
    pi("OmitID", gs_param_type_bool, OmitID),
134
    pi("OmitXMP", gs_param_type_bool, OmitXMP),
135
#undef pi
136
    gs_param_item_end
137
};
138
139
/*
140
  Notes on implementing the remaining Distiller functionality
141
  ===========================================================
142
143
  Architectural issues
144
  --------------------
145
146
  Must optionally disable application of TR, BG, UCR similarly.  Affects:
147
    PreserveHalftoneInfo
148
    PreserveOverprintSettings
149
    TransferFunctionInfo
150
    UCRandBGInfo
151
152
  Current limitations
153
  -------------------
154
155
  Non-primary elements in HalftoneType 5 are not written correctly
156
157
  Acrobat Distiller 3
158
  -------------------
159
160
  ---- Image parameters ----
161
162
  AntiAlias{Color,Gray,Mono}Images
163
164
  ---- Other parameters ----
165
166
  CompressPages
167
    Compress things other than page contents
168
  * PreserveHalftoneInfo
169
  PreserveOPIComments
170
    ? see OPI spec?
171
  * PreserveOverprintSettings
172
  * TransferFunctionInfo
173
  * UCRandBGInfo
174
  ColorConversionStrategy
175
    Select color space for drawing commands
176
  ConvertImagesToIndexed
177
    Postprocess image data *after* downsampling (requires an extra pass)
178
179
  Acrobat Distiller 4
180
  -------------------
181
182
  ---- Other functionality ----
183
184
  Document structure pdfmarks
185
186
  ---- Parameters ----
187
188
  xxxDownsampleType = /Bicubic
189
    Add new filter (or use siscale?) & to setup (gdevpsdi.c)
190
  DetectBlends
191
    Idiom recognition?  PatternType 2 patterns / shfill?  (see AD4)
192
  DoThumbnails
193
    Also output to memory device -- resolution issue
194
195
  ---- Job-level control ----
196
197
  EmitDSCWarnings
198
    Require DSC parser / interceptor
199
  CreateJobTicket
200
    ?
201
  AutoPositionEPSFiles
202
    Require DSC parsing
203
  PreserveCopyPage
204
    Concatenate Contents streams
205
  UsePrologue
206
    Needs hack in top-level control?
207
208
*/
209
210
/* Transfer a collection of parameters. */
211
static const byte xfer_item_sizes[] = {
212
    GS_PARAM_TYPE_SIZES(0)
213
};
214
int
215
gdev_pdf_get_param(gx_device *dev, char *Param, void *list)
216
541k
{
217
541k
    gx_device_pdf *pdev = (gx_device_pdf *)dev;
218
541k
    const gs_param_item_t *pi;
219
541k
    gs_param_list * plist = (gs_param_list *)list;
220
541k
    int code = 0;
221
222
31.0M
    for (pi = pdf_param_items; pi->key != 0; ++pi) {
223
30.8M
        if (strcmp(pi->key, Param) == 0) {
224
385k
            const char *key = pi->key;
225
385k
            const void *pvalue = (const void *)((const char *)pdev + pi->offset);
226
385k
            int size = xfer_item_sizes[pi->type];
227
385k
            gs_param_typed_value typed;
228
229
385k
            memcpy(&typed.value, pvalue, size);
230
385k
            typed.type = pi->type;
231
385k
            code = (*plist->procs->xmit_typed) (plist, key, &typed);
232
385k
            return code;
233
385k
        }
234
30.8M
    }
235
155k
    if (strcmp(Param, "CoreDistVersion") == 0) {
236
0
        return(param_write_int(plist, "CoreDistVersion", &CoreDistVersion));
237
0
    }
238
155k
    if (strcmp(Param, "CompatibilityLevel") == 0) {
239
0
        float f = pdev->CompatibilityLevel;
240
0
        return(param_write_float(plist, "CompatibilityLevel", &f));
241
0
    }
242
155k
    if (strcmp(Param, "ForOPDFRead") == 0) {
243
53.4k
        return(param_write_bool(plist, "ForOPDFRead", &pdev->ForOPDFRead));
244
53.4k
    }
245
102k
    if (strcmp(Param, "PassUserUnit") == 0) {
246
11.9k
        bool dummy;
247
11.9k
        if (pdev->CompatibilityLevel > 1.5)
248
6.04k
            dummy = true;
249
5.90k
        else
250
5.90k
            dummy = false;
251
11.9k
        return(param_write_bool(plist, "PassUserUnit", &dummy));
252
11.9k
    }
253
90.3k
    if (!pdev->is_ps2write) {
254
59.0k
        if (strcmp(Param, "pdfmark")  == 0){
255
3.83k
            return(param_write_null(plist, "pdfmark"));
256
3.83k
        }
257
55.2k
        if (strcmp(Param, "DSC") == 0){
258
0
            return(param_write_null(plist, "DSC"));
259
0
        }
260
55.2k
    }
261
262
#if OCR_VERSION > 0
263
    if (strcmp(Param, "OCRLanguage") == 0) {
264
        gs_param_string langstr;
265
        if (pdev->ocr_language[0]) {
266
            langstr.data = (const byte *)pdev->ocr_language;
267
            langstr.size = strlen(pdev->ocr_language);
268
            langstr.persistent = false;
269
        } else {
270
            langstr.data = (const byte *)"eng";
271
            langstr.size = 3;
272
            langstr.persistent = false;
273
        }
274
        return param_write_string(plist, "OCRLanguage", &langstr);
275
    }
276
    if (strcmp(Param, "OCREngine") == 0)
277
        return param_write_int(plist, "OCREngine", &pdev->ocr_engine);
278
279
    if (strcmp(Param, "UseOCR") == 0) {
280
        gs_param_string ocrstr;
281
282
        switch(pdev->UseOCR) {
283
            case UseOCRNever:
284
                ocrstr.data = (const byte *)"Never";
285
                ocrstr.size = 5;
286
                ocrstr.persistent = false;
287
                break;
288
            UseOCRAsNeeded:
289
                ocrstr.data = (const byte *)"AsNeeded";
290
                ocrstr.size = 8;
291
                ocrstr.persistent = false;
292
                break;
293
            UseOCRAlways:
294
                ocrstr.data = (const byte *)"Always";
295
                ocrstr.size = 8;
296
                ocrstr.persistent = false;
297
                break;
298
        }
299
        return param_write_string(plist, "UseOCR", &ocrstr);
300
    }
301
#endif
302
303
86.5k
    if (strcmp(Param, "OmitInfoDate") == 0)
304
0
        return(param_write_bool(plist, "OmitInfoDate", &pdev->OmitInfoDate));
305
86.5k
    if (strcmp(Param, "OmitXMP") == 0)
306
0
        return(param_write_bool(plist, "OmitXMP", &pdev->OmitXMP));
307
86.5k
    if (strcmp(Param, "OmitID") == 0)
308
0
        return(param_write_bool(plist, "OmitID", &pdev->OmitID));
309
310
86.5k
    return gdev_psdf_get_param(dev, Param, list);
311
86.5k
}
312
313
/* ---------------- Get parameters ---------------- */
314
315
/* Get parameters. */
316
int
317
gdev_pdf_get_params(gx_device * dev, gs_param_list * plist)
318
258k
{
319
258k
    gx_device_pdf *pdev = (gx_device_pdf *) dev;
320
258k
    float cl = (float)pdev->CompatibilityLevel;
321
258k
    int code;
322
258k
    int cdv = CoreDistVersion;
323
324
#if OCR_VERSION > 0
325
    gs_param_string langstr;
326
327
    if (pdev->ocr_language[0]) {
328
        langstr.data = (const byte *)pdev->ocr_language;
329
        langstr.size = strlen(pdev->ocr_language);
330
        langstr.persistent = false;
331
    } else {
332
        langstr.data = (const byte *)"eng";
333
        langstr.size = 3;
334
        langstr.persistent = false;
335
    }
336
337
    {
338
        gs_param_string ocrstr;
339
340
        switch(pdev->UseOCR) {
341
            case UseOCRNever:
342
                ocrstr.data = (const byte *)"Never";
343
                ocrstr.size = 5;
344
                ocrstr.persistent = false;
345
                break;
346
            UseOCRAsNeeded:
347
                ocrstr.data = (const byte *)"AsNeeded";
348
                ocrstr.size = 8;
349
                ocrstr.persistent = false;
350
                break;
351
            UseOCRAlways:
352
                ocrstr.data = (const byte *)"Always";
353
                ocrstr.size = 8;
354
                ocrstr.persistent = false;
355
                break;
356
        }
357
        code = param_write_string(plist, "UseOCR", &ocrstr);
358
    }
359
    code = param_write_string(plist, "OCRLanguage", &langstr);
360
    if(code < 0)
361
        return code;
362
    code = param_write_int(plist, "OCREngine", &pdev->ocr_engine);
363
    if(code < 0)
364
        return code;
365
#endif
366
367
258k
    pdev->ParamCompatibilityLevel = cl;
368
258k
    code = gdev_psdf_get_params(dev, plist);
369
258k
    if (code < 0 ||
370
258k
        (code = param_write_int(plist, "CoreDistVersion", &cdv)) < 0 ||
371
258k
        (code = param_write_float(plist, "CompatibilityLevel", &cl)) < 0 ||
372
258k
        (!pdev->is_ps2write && (code = param_write_bool(plist, "ForOPDFRead", &pdev->ForOPDFRead)) < 0) ||
373
        /* Indicate that we can process pdfmark and DSC. */
374
258k
        (param_requested(plist, "pdfmark") > 0 &&
375
258k
         (code = param_write_null(plist, "pdfmark")) < 0) ||
376
258k
        (param_requested(plist, "DSC") > 0 &&
377
258k
         (code = param_write_null(plist, "DSC")) < 0) ||
378
258k
        (code = gs_param_write_items(plist, pdev, NULL, pdf_param_items)) < 0
379
258k
        )
380
0
    {}
381
258k
    return code;
382
258k
}
383
384
/* ---------------- Put parameters ---------------- */
385
386
/* Put parameters, implementation */
387
static int
388
gdev_pdf_put_params_impl(gx_device * dev, const gx_device_pdf * save_dev, gs_param_list * plist)
389
342k
{
390
342k
    int ecode, code;
391
342k
    gx_device_pdf *pdev = (gx_device_pdf *) dev;
392
342k
    float cl = (float)pdev->CompatibilityLevel;
393
342k
    bool locked = pdev->params.LockDistillerParams, ForOPDFRead;
394
342k
    gs_param_name param_name;
395
396
342k
    pdev->pdf_memory = gs_memory_stable(pdev->memory);
397
    /*
398
     * If this is a pseudo-parameter (pdfmark or DSC),
399
     * don't bother checking for any real ones.
400
     */
401
402
342k
    {
403
342k
        gs_param_string_array ppa;
404
342k
        gs_param_string pps;
405
406
342k
        code = param_read_string_array(plist, (param_name = "pdfmark"), &ppa);
407
342k
        switch (code) {
408
65.2k
            case 0:
409
65.2k
                code = pdfwrite_pdf_open_document(pdev);
410
65.2k
                if (code < 0)
411
0
                    return code;
412
65.2k
                code = pdfmark_process(pdev, &ppa);
413
65.2k
                if (code >= 0)
414
65.2k
                    return code;
415
                /* falls through for errors */
416
12
            default:
417
12
                param_signal_error(plist, param_name, code);
418
12
                return code;
419
277k
            case 1:
420
277k
                break;
421
342k
        }
422
423
277k
        code = param_read_string_array(plist, (param_name = "DSC"), &ppa);
424
277k
        switch (code) {
425
24.0k
            case 0:
426
24.0k
                code = pdfwrite_pdf_open_document(pdev);
427
24.0k
                if (code < 0)
428
0
                    return code;
429
24.0k
                code = pdf_dsc_process(pdev, &ppa);
430
24.0k
                if (code >= 0)
431
24.0k
                    return code;
432
                /* falls through for errors */
433
0
            default:
434
0
                param_signal_error(plist, param_name, code);
435
0
                return code;
436
253k
            case 1:
437
253k
                break;
438
277k
        }
439
440
253k
        code = param_read_string(plist, (param_name = "pdfpagelabels"), &pps);
441
253k
        switch (code) {
442
44
            case 0:
443
44
                {
444
44
                    if (!pdev->ForOPDFRead) {
445
44
                        cos_dict_t *const pcd = pdev->Catalog;
446
44
                        code = pdfwrite_pdf_open_document(pdev);
447
44
                        if (code < 0)
448
0
                            return code;
449
44
                        code = cos_dict_put_string(pcd, (const byte *)"/PageLabels", 11,
450
44
                                   pps.data, pps.size);
451
44
                        if (code >= 0)
452
44
                            return code;
453
44
                    } else
454
0
                        return 0;
455
44
                 }
456
                /* falls through for errors */
457
0
            default:
458
0
                param_signal_error(plist, param_name, code);
459
0
                return code;
460
253k
            case 1:
461
253k
                break;
462
253k
        }
463
253k
    }
464
465
#if OCR_VERSION > 0
466
    {
467
        int len;
468
        gs_param_string langstr;
469
        switch (code = param_read_string(plist, (param_name = "OCRLanguage"), &langstr)) {
470
            case 0:
471
                len = langstr.size;
472
                if (len >= sizeof(pdev->ocr_language))
473
                    len = sizeof(pdev->ocr_language)-1;
474
                memcpy(pdev->ocr_language, langstr.data, len);
475
                pdev->ocr_language[len] = 0;
476
                break;
477
            case 1:
478
                break;
479
            default:
480
                ecode = code;
481
                param_signal_error(plist, param_name, ecode);
482
        }
483
    }
484
485
    {
486
        int engine;
487
        switch (code = param_read_int(plist, (param_name = "OCREngine"), &engine)) {
488
            case 0:
489
                pdev->ocr_engine = engine;
490
                break;
491
            case 1:
492
                break;
493
            default:
494
                ecode = code;
495
                param_signal_error(plist, param_name, ecode);
496
        }
497
    }
498
499
    {
500
        gs_param_string ocrstr;
501
502
        code = param_read_string(plist, (param_name = "UseOCR"), &ocrstr);
503
        switch(code) {
504
            case 0:
505
                if (ocrstr.size == 5 && memcmp(ocrstr.data, "Never", 5) == 0)
506
                    pdev->UseOCR = UseOCRNever;
507
                if (ocrstr.size == 8 && memcmp(ocrstr.data, "AsNeeded", 8) == 0)
508
                    pdev->UseOCR = UseOCRAsNeeded;
509
                if (ocrstr.size == 6 && memcmp(ocrstr.data, "Always", 6) == 0)
510
                    pdev->UseOCR = UseOCRAlways;
511
                break;
512
            case 1:
513
                break;
514
            default:
515
                param_signal_error(plist, param_name, code);
516
                break;
517
        }
518
    }
519
520
    {
521
        gs_param_string ocrstr;
522
523
        code = param_read_string(plist, (param_name = "UseOCR"), &ocrstr);
524
        switch(code) {
525
            case 0:
526
                if (ocrstr.size == 5 && memcmp(ocrstr.data, "Never", 5) == 0)
527
                    pdev->UseOCR = UseOCRNever;
528
                if (ocrstr.size == 8 && memcmp(ocrstr.data, "AsNeeded", 8) == 0)
529
                    pdev->UseOCR = UseOCRAsNeeded;
530
                if (ocrstr.size == 6 && memcmp(ocrstr.data, "Always", 6) == 0)
531
                    pdev->UseOCR = UseOCRAlways;
532
                break;
533
            case 1:
534
                break;
535
            default:
536
                param_signal_error(plist, param_name, code);
537
                break;
538
        }
539
    }
540
#endif
541
542
    /*
543
     * Check for LockDistillerParams before doing anything else.
544
     * If LockDistillerParams is true and is not being set to false,
545
     * ignore all resettings of PDF-specific parameters.  Note that
546
     * LockDistillerParams is read again, and reset if necessary, in
547
     * psdf_put_params.
548
     */
549
253k
    ecode = param_read_bool(plist, (param_name = "LockDistillerParams"), &locked);
550
253k
    if (ecode < 0)
551
0
        param_signal_error(plist, param_name, ecode);
552
553
    /* General parameters. */
554
555
253k
    {
556
253k
        int efo = 1;
557
558
253k
        ecode = param_put_int(plist, (param_name = ".EmbedFontObjects"), &efo, ecode);
559
253k
        if (ecode < 0)
560
0
            param_signal_error(plist, param_name, ecode);
561
253k
        if (efo != 1)
562
0
            param_signal_error(plist, param_name, ecode = gs_error_rangecheck);
563
253k
    }
564
253k
    {
565
253k
        int cdv = CoreDistVersion;
566
567
253k
        ecode = param_put_int(plist, (param_name = "CoreDistVersion"), &cdv, ecode);
568
253k
        if (ecode < 0)
569
0
            return gs_note_error(ecode);
570
253k
        if (cdv != CoreDistVersion)
571
0
            param_signal_error(plist, param_name, ecode = gs_error_rangecheck);
572
253k
    }
573
574
0
    switch (code = param_read_float(plist, (param_name = "CompatibilityLevel"), &cl)) {
575
0
        default:
576
0
            ecode = code;
577
0
            param_signal_error(plist, param_name, ecode);
578
0
            break;
579
10.0k
        case 0:
580
10.0k
            if (!(locked && pdev->params.LockDistillerParams)) {
581
                /*
582
                 * Must be 1.2, 1.3, 1.4, or 1.5.  Per Adobe documentation, substitute
583
                 * the nearest achievable value.
584
                 */
585
10.0k
                if (cl < (float)1.15)
586
14
                    cl = (float)1.1;
587
10.0k
                else if (cl < (float)1.25)
588
6.20k
                    cl = (float)1.2;
589
3.80k
                else if (cl < (float)1.35)
590
0
                    cl = (float)1.3;
591
3.80k
                else if (cl < (float)1.45)
592
72
                    cl = (float)1.4;
593
3.73k
                else if (cl < (float)1.55)
594
0
                    cl = (float)1.5;
595
3.73k
                else if (cl < (float)1.65)
596
0
                    cl = (float)1.6;
597
3.73k
                else if (cl < (float)1.75)
598
3.71k
                    cl = (float)1.7;
599
24
                else {
600
24
                    cl = (float)2.0;
601
24
                    if (pdev->params.TransferFunctionInfo == tfi_Preserve)
602
12
                        pdev->params.TransferFunctionInfo = tfi_Apply;
603
24
                }
604
10.0k
            }
605
253k
        case 1:
606
253k
            break;
607
253k
    }
608
253k
    {
609
253k
        code = gs_param_read_items(plist, pdev, pdf_param_items, pdev->pdf_memory);
610
253k
        if (code < 0 || (code = param_read_bool(plist, "ForOPDFRead", &ForOPDFRead)) < 0)
611
0
        {
612
0
        }
613
253k
        if (code == 0 && !pdev->is_ps2write && !(locked && pdev->params.LockDistillerParams))
614
3.71k
            pdev->ForOPDFRead = ForOPDFRead;
615
253k
    }
616
253k
    if (code < 0)
617
0
        ecode = code;
618
253k
    {
619
        /*
620
         * Setting FirstObjectNumber is only legal if the file
621
         * has just been opened and nothing has been written,
622
         * or if we are setting it to the same value.
623
         */
624
253k
        long fon = pdev->FirstObjectNumber;
625
626
253k
        if (fon != save_dev->FirstObjectNumber) {
627
0
            if (fon <= 0 || fon > 0x7fff0000 ||
628
0
                (pdev->next_id != 0 &&
629
0
                 pdev->next_id !=
630
0
                 save_dev->FirstObjectNumber + pdf_num_initial_ids)
631
0
                ) {
632
0
                ecode = gs_error_rangecheck;
633
0
                param_signal_error(plist, "FirstObjectNumber", ecode);
634
0
            }
635
0
        }
636
253k
    }
637
253k
    {
638
        /*
639
         * Set ProcessColorModel now, because gx_default_put_params checks
640
         * it.
641
         */
642
253k
        static const char *const pcm_names[] = {
643
253k
            "DeviceGray", "DeviceRGB", "DeviceCMYK", "DeviceN", 0
644
253k
        };
645
253k
        int pcm = -1;
646
647
253k
        ecode = param_put_enum(plist, "ProcessColorModel", &pcm,
648
253k
                               pcm_names, ecode);
649
253k
        if (ecode < 0)
650
0
            goto fail;
651
253k
        if (pcm >= 0) {
652
5.08k
            pdf_set_process_color_model(pdev, pcm);
653
5.08k
            rc_decrement(pdev->icc_struct, "gdev_pdf_put_params_impl, ProcessColorModel changed");
654
5.08k
            pdev->icc_struct = 0;
655
5.08k
        }
656
253k
    }
657
658
253k
    if (pdev->is_ps2write && (code = param_read_bool(plist, "ProduceDSC", &pdev->ProduceDSC)) < 0) {
659
0
        param_signal_error(plist, param_name, code);
660
0
    }
661
662
253k
    if (pdev->OmitInfoDate && pdev->PDFX != 0) {
663
0
        emprintf(pdev->memory, "\nIt is not possible to omit the CreationDate when creating PDF/X\nOmitInfoDate is being ignored.\n");
664
0
        pdev->OmitInfoDate = 0;
665
0
    }
666
667
253k
    if (pdev->OmitID && pdev->CompatibilityLevel > 1.7) {
668
0
        emprintf(pdev->memory, "\nIt is not possible to omit the ID array when creating a version 2.0 or greater PDF\nOmitID is being ignored.\n");
669
0
        pdev->OmitID = 0;
670
0
    }
671
253k
    if (pdev->OmitID && pdev->OwnerPassword.size != 0) {
672
0
        emprintf(pdev->memory, "\nIt is not possible to omit the ID array when creating an encrypted PDF\nOmitID is being ignored.\n");
673
0
        pdev->OmitID = 0;
674
0
    }
675
676
253k
    if (pdev->OmitXMP && pdev->PDFA != 0) {
677
0
        emprintf(pdev->memory, "\nIt is not possible to omit the XMP metadta when creating a PDF/A\nOmitXMP is being ignored.\n");
678
0
        pdev->OmitXMP = 0;
679
0
    }
680
681
    /* PDFA and PDFX are stored in the page device dictionary and therefore
682
     * set on every setpagedevice. However, if we have encountered a file which
683
     * can't be made this way, and the PDFACompatibilityPolicy is 1, we want to
684
     * continue producing the file, but not as a PDF/A or PDF/X file. Its more
685
     * or less impossible to alter the setting in the (potentially saved) page
686
     * device dictionary, so we use this rather clunky method.
687
     */
688
253k
    if (pdev->PDFA < 0 || pdev->PDFA > 3){
689
0
        ecode = gs_note_error(gs_error_rangecheck);
690
0
        param_signal_error(plist, "PDFA", ecode);
691
0
        goto fail;
692
0
    }
693
253k
    if(pdev->PDFA != 0 && pdev->AbortPDFAX)
694
0
        pdev->PDFA = 0;
695
253k
    if(pdev->PDFX && pdev->AbortPDFAX)
696
0
        pdev->PDFX = 0;
697
253k
    if (pdev->PDFX && pdev->PDFA != 0) {
698
0
        ecode = gs_note_error(gs_error_rangecheck);
699
0
        param_signal_error(plist, "PDFA", ecode);
700
0
        goto fail;
701
0
    }
702
253k
    if (pdev->PDFX && pdev->ForOPDFRead) {
703
0
        ecode = gs_note_error(gs_error_rangecheck);
704
0
        param_signal_error(plist, "PDFX", ecode);
705
0
        goto fail;
706
0
    }
707
253k
    if (pdev->PDFA != 0 && pdev->ForOPDFRead) {
708
0
        ecode = gs_note_error(gs_error_rangecheck);
709
0
        param_signal_error(plist, "PDFA", ecode);
710
0
        goto fail;
711
0
    }
712
253k
    if (pdev->PDFA == 1 || pdev->PDFX || pdev->CompatibilityLevel < 1.4) {
713
29.8k
         pdev->HaveTransparency = false;
714
29.8k
         pdev->PreserveSMask = false;
715
29.8k
    }
716
717
    /*
718
     * We have to set version to the new value, because the set of
719
     * legal parameter values for psdf_put_params varies according to
720
     * the version.
721
     */
722
253k
    if (pdev->PDFX)
723
0
        cl = (float)1.3; /* Instead pdev->CompatibilityLevel = 1.2; - see below. */
724
253k
    if (pdev->PDFA == 1 && cl != 1.4)
725
0
        cl = (float)1.4;
726
253k
    if (pdev->PDFA == 2 && cl < 1.7)
727
0
        cl = (float)1.7;
728
253k
    pdev->version = (cl < 1.2 ? psdf_version_level2 : psdf_version_ll3);
729
253k
    if (pdev->ForOPDFRead) {
730
34.6k
        pdev->ResourcesBeforeUsage = true;
731
34.6k
        pdev->HaveCFF = false;
732
34.6k
        pdev->HavePDFWidths = false;
733
34.6k
        pdev->HaveStrokeColor = false;
734
34.6k
        cl = (float)1.2; /* Instead pdev->CompatibilityLevel = 1.2; - see below. */
735
34.6k
        pdev->MaxInlineImageSize = max_long; /* Save printer's RAM from saving temporary image data.
736
                                                Immediate images doen't need buffering. */
737
34.6k
        pdev->version = psdf_version_level2;
738
218k
    } else {
739
218k
        pdev->ResourcesBeforeUsage = false;
740
218k
        pdev->HaveCFF = true;
741
218k
        pdev->HavePDFWidths = true;
742
218k
        pdev->HaveStrokeColor = true;
743
218k
    }
744
253k
    pdev->ParamCompatibilityLevel = cl;
745
253k
    if (cl < 1.2) {
746
12
        pdev->HaveCFF = false;
747
12
    }
748
749
253k
    ecode = param_read_float(plist, "UserUnit", &pdev->UserUnit);
750
253k
    if (ecode < 0)
751
0
        goto fail;
752
253k
    if (pdev->UserUnit == 0 || (pdev->UserUnit != 1 && pdev->CompatibilityLevel < 1.6)) {
753
0
        ecode = gs_note_error(gs_error_rangecheck);
754
0
        param_signal_error(plist, "UserUnit", ecode);
755
0
        goto fail;
756
0
    }
757
758
253k
    ecode = gdev_psdf_put_params(dev, plist);
759
253k
    if (ecode < 0)
760
73
        goto fail;
761
762
253k
    if (pdev->CompatibilityLevel > 1.7 && pdev->params.TransferFunctionInfo == tfi_Preserve) {
763
0
        pdev->params.TransferFunctionInfo = tfi_Apply;
764
0
        emprintf(pdev->memory, "\nIt is not possible to preserve transfer functions in PDF 2.0\ntransfer functions will be applied instead\n");
765
0
    }
766
767
253k
    if (pdev->params.ConvertCMYKImagesToRGB) {
768
0
        if (pdev->params.ColorConversionStrategy == ccs_CMYK) {
769
0
            emprintf(pdev->memory, "ConvertCMYKImagesToRGB is not compatible with ColorConversionStrategy of CMYK\n");
770
0
        } else {
771
0
            if (pdev->params.ColorConversionStrategy == ccs_Gray) {
772
0
                emprintf(pdev->memory, "ConvertCMYKImagesToRGB is not compatible with ColorConversionStrategy of Gray\n");
773
0
            } else {
774
0
                pdf_set_process_color_model(pdev,1);
775
0
                ecode = gsicc_init_device_profile_struct((gx_device *)pdev, NULL, 0);
776
0
                if (ecode < 0)
777
0
                    goto fail;
778
0
            }
779
0
        }
780
0
    }
781
253k
    switch (pdev->params.ColorConversionStrategy) {
782
0
        case ccs_ByObjectType:
783
253k
        case ccs_LeaveColorUnchanged:
784
253k
            break;
785
0
        case ccs_UseDeviceIndependentColor:
786
0
        case ccs_UseDeviceIndependentColorForImages:
787
0
            pdev->params.TransferFunctionInfo = tfi_Apply;
788
0
            break;
789
0
        case ccs_CMYK:
790
0
            pdf_set_process_color_model(pdev, 2);
791
0
            ecode = gsicc_init_device_profile_struct((gx_device *)pdev, NULL, 0);
792
0
            if (ecode < 0)
793
0
                goto fail;
794
0
            break;
795
0
        case ccs_Gray:
796
0
            pdf_set_process_color_model(pdev,0);
797
0
            ecode = gsicc_init_device_profile_struct((gx_device *)pdev, NULL, 0);
798
0
            if (ecode < 0)
799
0
                goto fail;
800
0
            break;
801
0
        case ccs_sRGB:
802
0
        case ccs_RGB:
803
            /* Only bother to do this if we didn't handle it above */
804
0
            if (!pdev->params.ConvertCMYKImagesToRGB) {
805
0
                pdf_set_process_color_model(pdev,1);
806
0
                ecode = gsicc_init_device_profile_struct((gx_device *)pdev, NULL, 0);
807
0
                if (ecode < 0)
808
0
                    goto fail;
809
0
            }
810
0
            break;
811
0
        default:
812
0
            break;
813
253k
    }
814
253k
    if (cl < 1.5f && pdev->params.ColorImage.Filter != NULL &&
815
253k
            !strcmp(pdev->params.ColorImage.Filter, "JPXEncode")) {
816
0
        emprintf(pdev->memory,
817
0
                 "JPXEncode requires CompatibilityLevel >= 1.5 .\n");
818
0
        ecode = gs_note_error(gs_error_rangecheck);
819
0
    }
820
253k
    if (cl < 1.5f && pdev->params.GrayImage.Filter != NULL &&
821
253k
            !strcmp(pdev->params.GrayImage.Filter, "JPXEncode")) {
822
0
        emprintf(pdev->memory,
823
0
                 "JPXEncode requires CompatibilityLevel >= 1.5 .\n");
824
0
        ecode = gs_note_error(gs_error_rangecheck);
825
0
    }
826
253k
    if (cl < 1.4f && pdev->params.MonoImage.Filter != NULL &&
827
253k
            !strcmp(pdev->params.MonoImage.Filter, "JBIG2Encode")) {
828
0
        emprintf(pdev->memory,
829
0
                 "JBIG2Encode requires CompatibilityLevel >= 1.4 .\n");
830
0
        ecode = gs_note_error(gs_error_rangecheck);
831
0
    }
832
253k
    if (pdev->HaveTrueTypes && pdev->version == psdf_version_level2) {
833
34.6k
        pdev->version = psdf_version_level2_with_TT ;
834
34.6k
    }
835
253k
    if (ecode < 0)
836
0
        goto fail;
837
838
253k
    if (pdev->FirstObjectNumber != save_dev->FirstObjectNumber) {
839
0
        if (pdev->xref.file != 0) {
840
0
            if (gp_fseek(pdev->xref.file, 0L, SEEK_SET) != 0) {
841
0
                ecode = gs_error_ioerror;
842
0
                goto fail;
843
0
            }
844
0
            pdf_initialize_ids(pdev);
845
0
        }
846
0
    }
847
    /* Handle the float/double mismatch. */
848
253k
    pdev->CompatibilityLevel = (int)(cl * 10 + 0.5) / 10.0;
849
850
253k
    if (pdev->ForOPDFRead && pdev->OwnerPassword.size != 0) {
851
0
        emprintf(pdev->memory, "\n\tSetting OwnerPassword for PostScript output would result in an encrypted\n\tunusable PostScript file, ignoring.\n");
852
0
        pdev->OwnerPassword.size = 0;
853
0
    }
854
855
253k
    if(pdev->OwnerPassword.size != save_dev->OwnerPassword.size ||
856
253k
        (pdev->OwnerPassword.size != 0 &&
857
253k
         memcmp(pdev->OwnerPassword.data, save_dev->OwnerPassword.data,
858
0
         pdev->OwnerPassword.size) != 0)) {
859
0
        if (pdev->is_open) {
860
0
            if (pdev->PageCount == 0) {
861
0
                gs_closedevice((gx_device *)save_dev);
862
0
                return 0;
863
0
            }
864
0
            else
865
0
                emprintf(pdev->memory, "Owner Password changed mid-job, ignoring.\n");
866
0
        }
867
0
    }
868
869
253k
    if (pdev->Linearise && pdev->file != NULL && !gp_fseekable(pdev->file)) {
870
0
        emprintf(pdev->memory, "Can't linearise a non-seekable output file, ignoring\n");
871
0
        pdev->Linearise = false;
872
0
    }
873
874
253k
    if (pdev->Linearise && pdev->is_ps2write) {
875
0
        emprintf(pdev->memory, "Can't linearise PostScript output, ignoring\n");
876
0
        pdev->Linearise = false;
877
0
    }
878
879
253k
    if (pdev->Linearise && pdev->OwnerPassword.size != 0) {
880
0
        emprintf(pdev->memory, "Can't linearise encrypted PDF, ignoring\n");
881
0
        pdev->Linearise = false;
882
0
    }
883
884
253k
    if (pdev->FlattenFonts)
885
0
        pdev->PreserveTrMode = false;
886
253k
    return 0;
887
73
 fail:
888
    /* Restore all the parameters to their original state. */
889
73
    pdev->version = save_dev->version;
890
73
    pdf_set_process_color_model(pdev, save_dev->pcm_color_info_index);
891
73
    pdev->saved_fill_color = save_dev->saved_fill_color;
892
73
    pdev->saved_stroke_color = save_dev->saved_fill_color;
893
73
    {
894
73
        const gs_param_item_t *ppi = pdf_param_items;
895
896
4.81k
        for (; ppi->key; ++ppi)
897
4.74k
            memcpy((char *)pdev + ppi->offset,
898
4.74k
                   (char *)save_dev + ppi->offset,
899
4.74k
                   gs_param_type_sizes[ppi->type]);
900
73
        pdev->ForOPDFRead = save_dev->ForOPDFRead;
901
73
    }
902
73
    return ecode;
903
253k
}
904
905
/* Put parameters */
906
int
907
gdev_pdf_put_params(gx_device * dev, gs_param_list * plist)
908
342k
{
909
342k
    int code;
910
342k
    gx_device_pdf *pdev = (gx_device_pdf *) dev;
911
342k
    gs_memory_t *mem = gs_memory_stable(pdev->memory);
912
342k
    gx_device_pdf *save_dev = gs_malloc(mem, sizeof(gx_device_pdf), 1,
913
342k
        "saved gx_device_pdf");
914
915
342k
    if (!save_dev)
916
0
        return_error(gs_error_VMerror);
917
342k
    memcpy(save_dev, pdev, sizeof(gx_device_pdf));
918
342k
    code = gdev_pdf_put_params_impl(dev, save_dev, plist);
919
342k
    gs_free(mem, save_dev, sizeof(gx_device_pdf), 1, "saved gx_device_pdf");
920
342k
    return code;
921
342k
}
922
923
/* ---------------- Process DSC comments ---------------- */
924
925
/* Bug #695850 DSC comments are not actually encoded, nor are they PostScript strings
926
 * they are simply a sequence of bytes. SO it would seem we should just preserve that
927
 * byte sequence. Bizarrely, Distiller treats the comment as 'almost' a PostScript
928
 * string. In particular it converts octal codes into an equivalent binary byte. It
929
 * also converts (eg) '\n' and '\r' into 'n' and 'r' and invalid octal escapes
930
 * (eg \11) simply have the '\' turned into a '?'.
931
 * We think this is nuts and have no intention of trying to mimic it precisely. This
932
 * routine will find octal escapes and convert them into binary. The way this works is
933
 * a little obscure. The DSC parser does convert the comment into a PostScript string
934
 * and so has to escape any unusual characters. This means our octal escaped values in
935
 * the original DSC comment have had the escape character ('\') escaped to become '\\'.
936
 * All we need to do is remove the escape of the escape and we will end up with a
937
 * properly escaped PostScript string.
938
 */
939
static int unescape_octals(gx_device_pdf * pdev, char *src, int size)
940
11.5k
{
941
11.5k
    char *start, *dest;
942
943
11.5k
    start = src;
944
11.5k
    dest = src;
945
946
786k
    while(size) {
947
775k
        if (size > 4 && src[0] == '\\' && src[1] == '\\' &&
948
775k
                src[2] > 0x29 && src[2] < 0x35 &&
949
775k
                src[3] > 0x29 &&src[3] < 0x38 &&
950
775k
                src[4] > 0x29 && src[4] < 0x38) {
951
27
            src++;
952
27
            size--;
953
775k
        } else {
954
775k
            *dest++ = *src++;
955
775k
            size--;
956
775k
        }
957
775k
    }
958
11.5k
    return (dest - start);
959
11.5k
}
960
961
static int
962
pdf_dsc_process(gx_device_pdf * pdev, const gs_param_string_array * pma)
963
24.0k
{
964
    /*
965
     * The Adobe "Distiller Parameters" documentation says that Distiller
966
     * looks at DSC comments, but it doesn't say which ones.  We look at
967
     * the ones that we see how to map directly to obvious PDF constructs.
968
     */
969
24.0k
    int code = 0;
970
24.0k
    uint i;
971
972
    /*
973
     * If ParseDSCComments is false, all DSC comments are ignored, even if
974
     * ParseDSCComentsForDocInfo or PreserveEPSInfo is true.
975
     */
976
24.0k
    if (!pdev->ParseDSCComments)
977
0
        return 0;
978
979
47.6k
    for (i = 0; i + 1 < pma->size && code >= 0; i += 2) {
980
23.6k
        const gs_param_string *pkey = &pma->data[i];
981
23.6k
        gs_param_string *pvalue = (gs_param_string *)&pma->data[i + 1];
982
23.6k
        const char *key;
983
23.6k
        int newsize;
984
985
        /*
986
         * %%For, %%Creator, and %%Title are recognized only if either
987
         * ParseDSCCommentsForDocInfo or PreserveEPSInfo is true.
988
         * The other DSC comments are always recognized.
989
         *
990
         * Acrobat Distiller sets CreationDate and ModDate to the current
991
         * time, not the value of %%CreationDate.  We think this is wrong,
992
         * but we do the same -- we ignore %%CreationDate here.
993
         */
994
995
23.6k
        if (pdf_key_eq(pkey, "Creator") && pdev->CompatibilityLevel <= 1.7) {
996
4.88k
            key = "/Creator";
997
4.88k
            newsize = unescape_octals(pdev, (char *)pvalue->data, pvalue->size);
998
4.88k
            code = cos_dict_put_c_key_string(pdev->Info, key,
999
4.88k
                                             pvalue->data, newsize);
1000
4.88k
            continue;
1001
18.7k
        } else if (pdf_key_eq(pkey, "Title") && pdev->CompatibilityLevel <= 1.7) {
1002
5.83k
            key = "/Title";
1003
5.83k
            newsize = unescape_octals(pdev, (char *)pvalue->data, pvalue->size);
1004
5.83k
            code = cos_dict_put_c_key_string(pdev->Info, key,
1005
5.83k
                                             pvalue->data, newsize);
1006
5.83k
            continue;
1007
12.9k
        } else if (pdf_key_eq(pkey, "For") && pdev->CompatibilityLevel <= 1.7) {
1008
853
            key = "/Author";
1009
853
            newsize = unescape_octals(pdev, (char *)pvalue->data, pvalue->size);
1010
853
            code = cos_dict_put_c_key_string(pdev->Info, key,
1011
853
                                             pvalue->data, newsize);
1012
853
            continue;
1013
12.0k
        } else {
1014
12.0k
            pdf_page_dsc_info_t *ppdi;
1015
12.0k
            char scan_buf[200]; /* arbitrary */
1016
1017
12.0k
            if ((ppdi = &pdev->doc_dsc_info,
1018
12.0k
                 pdf_key_eq(pkey, "Orientation")) ||
1019
12.0k
                (ppdi = &pdev->page_dsc_info,
1020
12.0k
                 pdf_key_eq(pkey, "PageOrientation"))
1021
12.0k
                ) {
1022
0
                if (pvalue->size == 1 && pvalue->data[0] >= '0' &&
1023
0
                    pvalue->data[0] <= '3'
1024
0
                    )
1025
0
                    ppdi->orientation = pvalue->data[0] - '0';
1026
0
                else
1027
0
                    ppdi->orientation = -1;
1028
12.0k
            } else if ((ppdi = &pdev->doc_dsc_info,
1029
12.0k
                        pdf_key_eq(pkey, "ViewingOrientation")) ||
1030
12.0k
                       (ppdi = &pdev->page_dsc_info,
1031
12.0k
                        pdf_key_eq(pkey, "PageViewingOrientation"))
1032
12.0k
                       ) {
1033
0
                gs_matrix mat;
1034
0
                int orient;
1035
1036
0
                if(pvalue->size >= sizeof(scan_buf) - 1)
1037
0
                    continue; /* error */
1038
0
                memcpy(scan_buf, pvalue->data, pvalue->size);
1039
0
                scan_buf[pvalue->size] = 0;
1040
0
                if (sscanf(scan_buf, "[%g %g %g %g]",
1041
0
                           &mat.xx, &mat.xy, &mat.yx, &mat.yy) != 4
1042
0
                    )
1043
0
                    continue; /* error */
1044
0
                for (orient = 0; orient < 4; ++orient) {
1045
0
                    if (mat.xx == 1 && mat.xy == 0 && mat.yx == 0 && mat.yy == 1)
1046
0
                        break;
1047
0
                    gs_matrix_rotate(&mat, -90.0, &mat);
1048
0
                }
1049
0
                if (orient == 4) /* error */
1050
0
                    orient = -1;
1051
0
                ppdi->viewing_orientation = orient;
1052
12.0k
            } else {
1053
12.0k
                gs_rect box;
1054
1055
12.0k
                if (pdf_key_eq(pkey, "EPSF")) {
1056
2.18k
                    pdev->is_EPS = (pvalue->size >= 1 && pvalue->data[0] != '0');
1057
2.18k
                    continue;
1058
2.18k
                }
1059
                /*
1060
                 * We only parse the BoundingBox for the sake of
1061
                 * AutoPositionEPSFiles.
1062
                 */
1063
9.89k
                if (pdf_key_eq(pkey, "BoundingBox"))
1064
5.16k
                    ppdi = &pdev->doc_dsc_info;
1065
4.72k
                else if (pdf_key_eq(pkey, "PageBoundingBox"))
1066
0
                    ppdi = &pdev->page_dsc_info;
1067
4.72k
                else
1068
4.72k
                    continue;
1069
5.16k
                if(pvalue->size >= sizeof(scan_buf) - 1)
1070
0
                    continue; /* error */
1071
5.16k
                memcpy(scan_buf, pvalue->data, pvalue->size);
1072
5.16k
                scan_buf[pvalue->size] = 0;
1073
5.16k
                if (sscanf(scan_buf, "[%lg %lg %lg %lg]",
1074
5.16k
                           &box.p.x, &box.p.y, &box.q.x, &box.q.y) != 4
1075
5.16k
                    )
1076
0
                    continue; /* error */
1077
5.16k
                ppdi->bounding_box = box;
1078
5.16k
            }
1079
5.16k
            continue;
1080
12.0k
        }
1081
23.6k
    }
1082
24.0k
    return code;
1083
24.0k
}