Coverage Report

Created: 2025-08-28 07:06

/src/ghostpdl/psi/zpdfops.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2025 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* Custom operators for PDF interpreter */
18
19
#if defined(BUILD_PDF) && BUILD_PDF == 1
20
#include "ghostpdf.h"
21
#include "pdf_page.h"
22
#include "gzht.h"
23
#include "gsrefct.h"
24
#include "pdf_misc.h"
25
#include "pdf_stack.h"
26
#include "pdf_dict.h"
27
#include "pdf_array.h"
28
#include "pdf_loop_detect.h"
29
30
#include "iminst.h"
31
#include "dstack.h"
32
#include "gsicc_profilecache.h"
33
#include "pagelist.h"
34
#endif
35
36
#include "ghost.h"
37
#include "gsmchunk.h"
38
#include "oper.h"
39
#include "igstate.h"
40
#include "istack.h"
41
#include "iutil.h"
42
#include "gspath.h"
43
#include "math_.h"
44
#include "ialloc.h"
45
#include "igc.h" /* needed for definition of gc_state for the ref_struct_clear_marks call */
46
#include "malloc_.h"
47
#include "string_.h"
48
#include "store.h"
49
#include "gxgstate.h"
50
#include "gxdevsop.h"
51
#include "idict.h"
52
#include "iname.h"
53
#include "bfont.h"
54
55
#if defined(BUILD_PDF) && BUILD_PDF == 1
56
57
static int zpdfi_populate_search_paths(i_ctx_t *i_ctx_p, pdf_context *ctx)
58
109k
{
59
109k
    int code = 0;
60
    /* This should only be called once per pdfi context
61
       if the paths are already populated, just skip it.
62
     */
63
109k
    if (ctx->search_paths.resource_paths == NULL) {
64
109k
        ref *l2dictref, *grdref, *fpathref;
65
109k
        int i;
66
109k
        const gs_file_path *pfpath = i_ctx_p->lib_path;
67
109k
        gs_main_instance *minst = get_minst_from_memory(imemory);
68
109k
        code = dict_find_string(systemdict, "pssystemparams", &l2dictref);
69
109k
        if (code >= 0 && r_has_type(l2dictref, t_dictionary)) {
70
109k
            code = dict_find_string(l2dictref, "GenericResourceDir", &grdref);
71
109k
            if (code >= 0 && r_has_type(grdref, t_string)) {
72
109k
                ctx->search_paths.genericresourcedir.data = gs_alloc_bytes(ctx->memory, r_size(grdref), "zpdfi_populate_search_paths");
73
109k
                if (ctx->search_paths.genericresourcedir.data == NULL) {
74
0
                    code = gs_note_error(gs_error_VMerror);
75
0
                    goto done;
76
0
                }
77
109k
                memcpy((char *)ctx->search_paths.genericresourcedir.data, grdref->value.const_bytes, r_size(grdref));
78
109k
                ctx->search_paths.genericresourcedir.size = r_size(grdref);
79
109k
                ctx->search_paths.genericresourcedir.persistent = false;
80
109k
            }
81
109k
        }
82
83
109k
        ctx->search_paths.resource_paths = (gs_param_string *)gs_alloc_bytes(ctx->memory, (size_t)sizeof(gs_param_string) * r_size(&pfpath->list), "array of paths");
84
109k
        if (ctx->search_paths.resource_paths == NULL) {
85
0
            code = gs_note_error(gs_error_VMerror);
86
0
            goto done;
87
0
        }
88
109k
        memset(ctx->search_paths.resource_paths, 0x00, sizeof(gs_param_string) * r_size(&pfpath->list));
89
90
109k
        ctx->search_paths.num_resource_paths = r_size(&pfpath->list);
91
1.52M
        for (i = 0; i < r_size(&pfpath->list); i++) {
92
1.41M
            const ref *prdir = pfpath->list.value.refs + i; /* By nature, this cannot be a short/mixed array, only a "normal" array */
93
1.41M
            ctx->search_paths.resource_paths[i].data = gs_alloc_bytes(ctx->memory, r_size(prdir), "zpdfi_populate_search_paths");
94
1.41M
            if (ctx->search_paths.resource_paths[i].data == NULL) {
95
0
                code = gs_note_error(gs_error_VMerror);
96
0
                goto done;
97
0
            }
98
1.41M
            memcpy((char *)ctx->search_paths.resource_paths[i].data, prdir->value.const_bytes, r_size(prdir));
99
1.41M
            ctx->search_paths.resource_paths[i].size = r_size(prdir);
100
1.41M
            ctx->search_paths.resource_paths[i].persistent = false;
101
1.41M
        }
102
109k
        code = dict_find_string(systemdict, "FONTPATH", &fpathref);
103
109k
        if (code >= 0 && r_has_type(fpathref, t_array)) {
104
0
            ctx->search_paths.font_paths = (gs_param_string *)gs_alloc_bytes(ctx->memory, (size_t)sizeof(gs_param_string) * r_size(fpathref), "array of font paths");
105
0
            if (ctx->search_paths.font_paths == NULL) {
106
0
                code = gs_note_error(gs_error_VMerror);
107
0
                goto done;
108
0
            }
109
0
            memset(ctx->search_paths.font_paths, 0x00, sizeof(gs_param_string) * r_size(fpathref));
110
111
0
            ctx->search_paths.num_font_paths = r_size(fpathref);
112
0
            for (i = 0; i < r_size(fpathref); i++) {
113
0
                const ref *prdir = fpathref->value.refs + i; /* By nature, this cannot be a short/mixed array, only a "normal" array */
114
0
                ctx->search_paths.font_paths[i].data = gs_alloc_bytes(ctx->memory, r_size(prdir), "zpdfi_populate_search_paths");
115
0
                if (ctx->search_paths.font_paths[i].data == NULL) {
116
0
                    code = gs_note_error(gs_error_VMerror);
117
0
                    goto done;
118
0
                }
119
0
                memcpy((char *)ctx->search_paths.font_paths[i].data, prdir->value.const_bytes, r_size(prdir));
120
0
                ctx->search_paths.font_paths[i].size = r_size(prdir);
121
0
                ctx->search_paths.font_paths[i].persistent = false;
122
0
            }
123
0
        }
124
109k
        ctx->search_paths.search_here_first = minst->search_here_first;
125
109k
    }
126
109k
done:
127
109k
    return code >= 0 ? 0 : code;
128
109k
}
129
130
static int zpdfi_populate_fontmap_files(i_ctx_t *i_ctx_p, pdf_context *ctx)
131
109k
{
132
109k
    int code, i;
133
109k
    ref *fontmaps;
134
135
109k
    code = dict_find_string(systemdict, "FONTMAP", &fontmaps);
136
109k
    if (code >= 0 && r_has_type(fontmaps, t_array)) {
137
0
        ctx->fontmapfiles = (gs_string *)gs_alloc_bytes(ctx->memory, (size_t)sizeof(gs_string) * r_size(fontmaps), "array of fontmap files");
138
0
        if (ctx->fontmapfiles != 0) {
139
0
            memset(ctx->fontmapfiles, 0x00, sizeof(gs_string) * r_size(fontmaps));
140
0
            ctx->num_fontmapfiles = r_size(fontmaps);
141
0
            for (i = 0; i < r_size(fontmaps); i++) {
142
0
                const ref *fmapfile = fontmaps->value.refs + i; /* By nature, this cannot be a short/mixed array, only a "normal" array */
143
0
                ctx->fontmapfiles[i].data = gs_alloc_bytes(ctx->memory, r_size(fmapfile), "zpdfi_populate_fontmap_files");
144
0
                if (ctx->fontmapfiles[i].data == NULL) {
145
0
                    code = gs_note_error(gs_error_VMerror);
146
0
                    goto done;
147
0
                }
148
0
                memcpy((char *)ctx->fontmapfiles[i].data, fmapfile->value.const_bytes, r_size(fmapfile));
149
0
                ctx->fontmapfiles[i].size = r_size(fmapfile);
150
0
            }
151
0
        }
152
0
        else {
153
0
            code = gs_note_error(gs_error_VMerror);
154
0
            goto done;
155
0
        }
156
0
    }
157
109k
    else if (code >= 0 && r_has_type(fontmaps, t_string)) {
158
0
        ctx->fontmapfiles = (gs_string *)gs_alloc_bytes(ctx->memory, sizeof(gs_string), "array of fontmap files");
159
0
        if (ctx->fontmapfiles != 0) {
160
0
            ctx->num_fontmapfiles = 1;
161
0
            ctx->fontmapfiles[0].data = gs_alloc_bytes(ctx->memory, r_size(fontmaps), "zpdfi_populate_fontmap_files");
162
0
            if (ctx->fontmapfiles[0].data == NULL) {
163
0
                code = gs_note_error(gs_error_VMerror);
164
0
                goto done;
165
0
            }
166
0
            memcpy((char *)ctx->fontmapfiles[0].data, fontmaps->value.const_bytes, r_size(fontmaps));
167
0
            ctx->fontmapfiles[0].size = r_size(fontmaps);
168
0
        }
169
0
        else {
170
0
            code = gs_note_error(gs_error_VMerror);
171
0
            goto done;
172
0
        }
173
0
    }
174
109k
    else
175
109k
        code = 0;
176
109k
done:
177
109k
    return code;
178
109k
}
179
180
/*
181
 * Declare the structure we use to represent an instance of the PDF parser
182
 * as a t_struct.
183
 */
184
typedef struct pdfctx_s {
185
    pdf_context *ctx;               /* Not exposed to garbager */
186
    stream *ps_stream;
187
    gs_memory_t *pdf_memory;        /* The 'wrapped' memory allocator used by the PDF interpreter. Not exposed to garbager */
188
    gs_memory_t *pdf_stream_memory; /* The memory allocator used to copy the PostScript stream to pdf_stream. Not exposed to garbager */
189
    stream *pdf_stream;
190
    bool UsingPDFFile;
191
    gsicc_profile_cache_t *profile_cache;
192
    ref names_dict;
193
    gs_memory_t *cache_memory;      /* The memory allocator used to allocate the working (GC'ed) profile cache */
194
} pdfctx_t;
195
196
/* There is some unfortunately necessary complication in the structure above regarding the ICC profile cache.
197
 * Initially the problem was due to adding the colour space name to the 'interpreter data' part of the colour
198
 * space, in order to be able to identify the case where we switch to the current colour space.
199
 *
200
 * This caused problems with ICC spaces, because these maintain a reference to the colour space. If the profile
201
 * was stored in the PostScript profile cache (which it would be, because the profile cache is stored in the
202
 * grapchis state, which we inherit from the PostScript interpreter) then it would outlive the PDF interpreter,
203
 *  and when we came to free the cache it would try to free the colour space, which would try to free the PDF
204
 * name object, which had already been freed.
205
 *
206
 * To work around this we replaced the profile cache in the graphics state with the profile cache from the PDF
207
 * interpreter. Now when we free the PDF profile cache, it frees the colour spaces, and the PDF names, while they
208
 * are still valid.
209
 *
210
 * However, we then discovered that the garbage collector could reclaim the colour spaces. This happens because
211
 * no GC-visible object declares it has a reference to the colour space. It doesn't matter that the colour
212
 * space has been counted up, the GC frees it. Now the profile cache in pdfi is pointing to a colour space which
213
 * has gone away....
214
 *
215
 * To get round this, we create a brand-new profile cache, using GC'ed memory (well actually the interpreter
216
 * allocator, which is GC'ed for Ghostscript). When we switch to pdfi we replace the graphics state pdfi is
217
 * using with the one from the PostScript environment, and at the same time we swap out the profile cache
218
 * being used by that graphics state, so it uses our new one. On return to PostScript we swap them back.
219
 * This allows the lifetime of the profiles in the profile cache to be correct, because they are visible to the
220
 * garbage collector (the PDF context is a GC-visible object and enumerates it's member profile cache)
221
 * When we finalize the PDF context we count down the profile cache which dereferences all its entries. This
222
 * effectively frees the colour space (the memory may not be reclaimed yet) which calls the interpreter
223
 * specific cleanup, which frees the (still valid at this point) PDF name object and sets the pointer to NULL.
224
 *
225
 * The net result is that we have the profiles visible to the garbage collector during their lifetime, but
226
 * still have control over the cache, so we can empty it of the profiles created for pdfi when we close the
227
 * PDF interpreter.
228
 */
229
230
/* Structure descriptors */
231
static void pdfctx_finalize(const gs_memory_t *cmem, void *vptr);
232
233
gs_private_st_composite_final(st_pdfctx_t, pdfctx_t, "pdfctx_struct",\
234
    pdfctx_enum_ptrs, pdfctx_reloc_ptrs, pdfctx_finalize);
235
236
static
237
4.38k
ENUM_PTRS_BEGIN(pdfctx_enum_ptrs) return 0;
238
876
  ENUM_PTR3(0, pdfctx_t, ps_stream, pdf_stream, profile_cache);
239
876
  case 3:
240
876
    ENUM_RETURN_REF(&((pdfctx_t *)vptr)->names_dict);
241
4.38k
ENUM_PTRS_END
242
243
876
static RELOC_PTRS_BEGIN(pdfctx_reloc_ptrs);
244
876
RELOC_REF_VAR(((pdfctx_t *)vptr)->names_dict);
245
876
ref_struct_clear_marks(gcst->cur_mem, &(((pdfctx_t *)vptr)->names_dict), 1, pstype);
246
876
RELOC_PTR3(pdfctx_t, ps_stream, pdf_stream, profile_cache);
247
876
RELOC_PTRS_END
248
249
static void
250
pdfctx_finalize(const gs_memory_t *cmem, void *vptr)
251
109k
{
252
109k
    pdfctx_t *pdfctx = vptr;
253
    /* Finalize methods have to cope with the possibility of being called multiple times
254
     *  on the same object - hence we null the entries.
255
     */
256
257
109k
    make_null(&pdfctx->names_dict);
258
109k
    if (pdfctx->profile_cache != NULL) {
259
439
        rc_decrement(pdfctx->profile_cache, "free the working profile cache");
260
439
        pdfctx->profile_cache = NULL;
261
439
    }
262
109k
    if (cmem != NULL) {
263
109k
        if (pdfctx->ctx != NULL) {
264
439
            if (pdfctx->pdf_stream) {
265
415
                 memset(pdfctx->pdf_stream, 0x00, sizeof(stream));
266
415
                 gs_free_object(pdfctx->pdf_stream_memory, pdfctx->pdf_stream, "free PDF copy of stream");
267
415
                 pdfctx->pdf_stream = NULL;
268
415
            }
269
270
439
            if (pdfctx->ps_stream) {
271
                /* Detach the PostScript stream from the PDF context, otherwise the
272
                 * free_context code will close the main stream.
273
                 */
274
415
                pdfctx->ctx->main_stream->s = NULL;
275
415
            }
276
439
            (void)pdfi_free_context(pdfctx->ctx);
277
439
            pdfctx->ctx = NULL;
278
439
        }
279
109k
        if (pdfctx->pdf_memory != NULL) {
280
            /* gs_memory_chunk_unwrap() returns the "wrapped" allocator, which we don't need */
281
109k
            (void)gs_memory_chunk_unwrap(pdfctx->pdf_memory);
282
109k
            pdfctx->pdf_memory = NULL;
283
109k
        }
284
109k
    }
285
109k
}
286
287
static int zPDFstream(i_ctx_t *i_ctx_p)
288
109k
{
289
109k
    os_ptr op = osp;
290
109k
    int code = 0;
291
109k
    stream *s;
292
109k
    pdfctx_t *pdfctx;
293
109k
    pdfi_switch_t i_switch;
294
295
109k
    check_op(2);
296
297
109k
    check_read_file(i_ctx_p, s, op - 1);
298
299
109k
    check_type(*op, t_pdfctx);
300
109k
    pdfctx = r_ptr(op, pdfctx_t);
301
302
    /* If the supplied context already has a file open, signal an error */
303
109k
    if (pdfctx->ps_stream != NULL || pdfctx->UsingPDFFile)
304
0
        return_error(gs_error_ioerror);
305
306
109k
    s->close_at_eod = false;
307
109k
    pdfctx->ps_stream = s;
308
109k
    pdfctx->pdf_stream = s_alloc_immovable(imemory->stable_memory, "PDFstream copy of PS stream");
309
109k
    pdfctx->pdf_stream_memory = imemory->stable_memory;
310
109k
    if (pdfctx->pdf_stream == NULL)
311
0
        return_error(gs_error_VMerror);
312
313
109k
    *(pdfctx->pdf_stream) = *(pdfctx->ps_stream);
314
315
109k
    code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
316
317
109k
    if (code >= 0) {
318
109k
        code = pdfi_set_input_stream(pdfctx->ctx, pdfctx->pdf_stream);
319
320
109k
        pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
321
109k
    }
322
323
109k
    if (code < 0) {
324
23.3k
        memset(pdfctx->pdf_stream, 0x00, sizeof(stream));
325
23.3k
        gs_free_object(imemory, pdfctx->pdf_stream, "PDFstream copy of PS stream");
326
23.3k
        pdfctx->ctx->main_stream->s = NULL;
327
23.3k
        pdfctx->pdf_stream = NULL;
328
23.3k
        pdfctx->ps_stream = NULL;
329
23.3k
        return code;
330
23.3k
    }
331
332
85.6k
    pdfctx->ctx->finish_page = NULL;
333
85.6k
    make_tav(op, t_pdfctx, icurrent_space | a_all, pstruct, (obj_header_t *)(pdfctx));
334
335
85.6k
    pop(2);
336
85.6k
    return 0;
337
109k
}
338
339
static int zPDFfile(i_ctx_t *i_ctx_p)
340
16
{
341
16
    os_ptr op = osp;
342
16
    pdfctx_t *pdfctx;
343
16
    char pdffilename[gp_file_name_sizeof];
344
16
    int code = 0;
345
16
    pdfi_switch_t i_switch;
346
347
16
    check_op(2);
348
349
6
    check_type(*op, t_pdfctx);
350
0
    pdfctx = r_ptr(op, pdfctx_t);
351
352
0
    check_read_type(*(op - 1), t_string);
353
0
    if (r_size(op - 1) > gp_file_name_sizeof - 2)
354
0
        return_error(gs_error_limitcheck);
355
356
    /* If the supplied context already has a file open, signal an error */
357
0
    if (pdfctx->ps_stream != NULL)
358
0
        return_error(gs_error_ioerror);
359
360
0
    pdfctx->ps_stream = NULL;
361
362
0
    memcpy(pdffilename, (op - 1)->value.bytes, r_size(op - 1));
363
0
    pdffilename[r_size(op - 1)] = 0;
364
365
0
    code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
366
367
0
    if (code >= 0) {
368
0
        code = pdfi_open_pdf_file(pdfctx->ctx, pdffilename);
369
370
0
        pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
371
0
    }
372
373
0
    if (code < 0)
374
0
        return code;
375
376
0
    pdfctx->UsingPDFFile = true;
377
0
    pdfctx->ctx->finish_page = NULL;
378
379
0
    pop(2);
380
0
    return 0;
381
0
}
382
383
static int zPDFclose(i_ctx_t *i_ctx_p)
384
108k
{
385
108k
    os_ptr op = osp;
386
108k
    int code = 0;
387
108k
    pdfctx_t *pdfctx;
388
389
108k
    check_type(*op, t_pdfctx);
390
108k
    pdfctx = r_ptr(op, pdfctx_t);
391
392
108k
    if (pdfctx->profile_cache != NULL) {
393
108k
        rc_decrement(pdfctx->profile_cache, "free the working profile cache");
394
108k
        pdfctx->profile_cache = NULL;
395
108k
    }
396
397
108k
    if (pdfctx->ctx != NULL) {
398
108k
        if (pdfctx->pdf_stream != NULL || pdfctx->ps_stream != NULL) {
399
85.2k
            pdfi_switch_t i_switch;
400
401
85.2k
            code = gs_gsave(igs);
402
85.2k
            if (code < 0)
403
0
                return code;
404
405
85.2k
            code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
406
407
85.2k
            if (code >= 0) {
408
85.2k
                pdfi_finish_pdf_file(pdfctx->ctx);
409
85.2k
                pdfi_report_errors(pdfctx->ctx);
410
411
85.2k
                pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
412
85.2k
            }
413
85.2k
            code = gs_grestore(igs);
414
85.2k
            if (code < 0)
415
0
                return code;
416
85.2k
        }
417
108k
        if (pdfctx->ps_stream) {
418
            /* Detach the PostScript stream from the PDF context, otherwise the
419
             * close code will close the main stream
420
             */
421
85.2k
            if (pdfctx->ctx->main_stream)
422
85.2k
                pdfctx->ctx->main_stream->s = NULL;
423
85.2k
        }
424
108k
        code = pdfi_free_context(pdfctx->ctx);
425
108k
        pdfctx->ctx = NULL;
426
108k
    }
427
108k
    if (pdfctx->pdf_stream) {
428
85.2k
        memset(pdfctx->pdf_stream, 0x00, sizeof(stream));
429
85.2k
        gs_free_object(imemory, pdfctx->pdf_stream, "free copy of PostScript stream");
430
85.2k
        pdfctx->pdf_stream = NULL;
431
85.2k
    }
432
108k
    if (pdfctx->ps_stream)
433
85.2k
        pdfctx->ps_stream = NULL;
434
108k
    pop(1);
435
108k
    return code;
436
108k
}
437
438
static int PDFobj_to_PSobj(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_obj *PDFobj, ref *PSobj);
439
440
#define DEBUG_INFO_DICT 0
441
442
static void debug_printmark(int type)
443
713k
{
444
#if DEBUG_INFO_DICT
445
    switch(type) {
446
        case 0:
447
            dbgprintf("<<\n");
448
            break;
449
        case 1:
450
            dbgprintf(">>\n");
451
            break;
452
        case 2:
453
            dbgprintf("[");
454
            break;
455
        case 3:
456
            dbgprintf("]\n");
457
            break;
458
    }
459
#endif
460
713k
}
461
462
static void debug_pdfobj(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_obj *PDFobj)
463
2.49M
{
464
#if DEBUG_INFO_DICT
465
    char *str = NULL;
466
    int code = 0, len = 0;
467
468
    switch(pdfi_type_of(PDFobj)) {
469
        case PDF_NAME:
470
            code = pdfi_string_from_name(pdfctx->ctx, (pdf_name *)PDFobj, &str, &len);
471
            if (code < 0)
472
                return;
473
            dbgprintf1("/%s ", str);
474
            (void)pdfi_free_string_from_name(pdfctx->ctx, str);
475
            break;
476
        case PDF_STRING:
477
            str = (char *)gs_alloc_bytes(pdfctx->ctx->memory, ((pdf_string *)PDFobj)->length + (size_t)1, "");
478
            if (str == NULL)
479
                return;
480
            memset(str, 0x00, ((pdf_string *)PDFobj)->length + 1);
481
            memcpy(str, ((pdf_string *)PDFobj)->data, ((pdf_string *)PDFobj)->length);
482
            dbgprintf1("/%s ", str);
483
            gs_free_object(pdfctx->ctx->memory, str, "");
484
            break;
485
        case PDF_INT:
486
            dbgprintf1("/%d ", ((pdf_num *)PDFobj)->value.i);
487
            break;
488
        case PDF_REAL:
489
            dbgprintf1("/%f ", ((pdf_num *)PDFobj)->value.d);
490
            break;
491
            break;
492
        case PDF_BOOL:
493
            if (PDFobj == PDF_TRUE_OBJ)
494
                dbgprintf("true ");
495
            else
496
                dbgprintf("false ");
497
            break;
498
        default:
499
            break;
500
    }
501
#endif
502
2.49M
}
503
504
static int PDFdict_to_PSdict(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_dict *PDFdict, ref *PSdict)
505
152k
{
506
152k
    int code = 0;
507
152k
    uint64_t index = 0;
508
152k
    pdf_name *Key = NULL;
509
152k
    pdf_obj *Value = NULL;
510
152k
    ref nameref, valueref;
511
152k
    char *str = NULL;
512
152k
    int len = 0;
513
514
152k
    code = dict_create(pdfi_dict_entries(PDFdict), PSdict);
515
152k
    if (code < 0)
516
0
        return code;
517
518
152k
    code = pdfi_loop_detector_mark(pdfctx->ctx);
519
152k
    if (code < 0)
520
0
        goto error;
521
522
152k
    code = pdfi_dict_first(pdfctx->ctx, PDFdict, (pdf_obj **)&Key, &Value, &index);
523
152k
    if (code == gs_error_undefined) {
524
756
        code = 0;
525
756
        goto error;
526
756
    }
527
528
759k
    while (code >= 0) {
529
759k
        code = pdfi_string_from_name(pdfctx->ctx, Key, &str, &len);
530
759k
        if (code < 0)
531
0
            goto error;
532
533
759k
        debug_pdfobj(i_ctx_p, pdfctx, (pdf_obj *)Key);
534
535
759k
        code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)str, len, &nameref, 1);
536
759k
        if (code < 0)
537
0
            goto error;
538
539
759k
        code = PDFobj_to_PSobj(i_ctx_p, pdfctx, Value, &valueref);
540
759k
        if (code < 0)
541
277
            goto error;
542
543
759k
        code = dict_put(PSdict, &nameref, &valueref, &i_ctx_p->dict_stack);
544
759k
        if (code < 0)
545
0
            goto error;
546
547
759k
        pdfi_countdown(Key);
548
759k
        pdfi_countdown(Value);
549
759k
        Key = NULL;
550
759k
        Value = NULL;
551
552
759k
        code = pdfi_loop_detector_cleartomark(pdfctx->ctx);
553
759k
        if (code < 0)
554
0
            goto error;
555
556
759k
        code = pdfi_loop_detector_mark(pdfctx->ctx);
557
759k
        if (code < 0)
558
0
            goto error;
559
560
759k
        (void)pdfi_free_string_from_name(pdfctx->ctx, str);
561
759k
        str = NULL;
562
759k
        code = pdfi_dict_next(pdfctx->ctx, PDFdict, (pdf_obj **)&Key, &Value, &index);
563
759k
        if (code == gs_error_undefined) {
564
151k
            code = 0;
565
151k
            break;
566
151k
        }
567
759k
    }
568
152k
error:
569
152k
    (void)pdfi_free_string_from_name(pdfctx->ctx, str);
570
152k
    pdfi_countdown(Key);
571
152k
    pdfi_countdown(Value);
572
573
152k
    if (code < 0)
574
324
        (void)pdfi_loop_detector_cleartomark(pdfctx->ctx);
575
151k
    else
576
151k
        code = pdfi_loop_detector_cleartomark(pdfctx->ctx);
577
152k
    return code;
578
151k
}
579
580
static int PDFarray_to_PSarray(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_array *PDFarray, ref *PSarray)
581
204k
{
582
204k
    int code = 0, i = 0;
583
204k
    ref PS_ref;
584
204k
    pdf_obj *array_obj = NULL;
585
204k
    ref *eltp = NULL;
586
587
204k
    code = pdfi_loop_detector_mark(pdfctx->ctx);
588
204k
    if (code < 0)
589
0
        goto error;
590
591
204k
    code = ialloc_ref_array(PSarray, a_all, pdfi_array_size(PDFarray), "zPDFInfo");
592
204k
    if (code < 0)
593
0
        goto error;
594
595
1.03M
    for (i = 0;i < pdfi_array_size(PDFarray); i++) {
596
827k
        code = pdfi_array_fetch_recursing(pdfctx->ctx, PDFarray, i, &array_obj, true, true);
597
827k
        if (code < 0)
598
37
            goto error;
599
827k
        code = PDFobj_to_PSobj(i_ctx_p, pdfctx, array_obj, &PS_ref);
600
827k
        if (code < 0) {
601
100
            pdfi_countdown(array_obj);
602
100
            goto error;
603
100
        }
604
605
826k
        eltp = PSarray->value.refs + i;
606
826k
        ref_assign_old((const ref *)PSarray, eltp, &PS_ref, "zPDFInfo");
607
608
826k
        pdfi_countdown(array_obj);
609
826k
        array_obj = NULL;
610
826k
    }
611
204k
error:
612
204k
    if (code < 0)
613
137
        (void)pdfi_loop_detector_cleartomark(pdfctx->ctx);
614
204k
    else
615
204k
        code = pdfi_loop_detector_cleartomark(pdfctx->ctx);
616
204k
    return code;
617
204k
}
618
619
static int PDFobj_to_PSobj(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_obj *PDFobj, ref *PSobj)
620
1.73M
{
621
1.73M
    int code = 0;
622
623
1.73M
    code = pdfi_loop_detector_mark(pdfctx->ctx);
624
1.73M
    if (code < 0)
625
0
        goto error;
626
627
1.73M
    debug_pdfobj(i_ctx_p, pdfctx, PDFobj);
628
629
1.73M
    switch(pdfi_type_of(PDFobj)) {
630
8.36k
        case PDF_NAME:
631
8.36k
            {
632
8.36k
                char *str = NULL;
633
8.36k
                int len;
634
635
8.36k
                code = pdfi_string_from_name(pdfctx->ctx, (pdf_name *)PDFobj, &str, &len);
636
8.36k
                if (code < 0)
637
0
                    goto error;
638
8.36k
                code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)str, len, PSobj, 1);
639
8.36k
                (void)pdfi_free_string_from_name(pdfctx->ctx, str);
640
8.36k
            }
641
0
            break;
642
124k
        case PDF_STRING:
643
124k
            {
644
124k
                byte *sbody;
645
124k
                uint size = ((pdf_name *)PDFobj)->length;
646
647
124k
                sbody = ialloc_string(size, "string");
648
124k
                if (sbody == 0) {
649
0
                    code = gs_note_error(gs_error_VMerror);
650
124k
                } else {
651
124k
                    make_string(PSobj, a_all | icurrent_space, size, sbody);
652
124k
                    memcpy(sbody, ((pdf_name *)PDFobj)->data, size);
653
124k
                }
654
124k
            }
655
124k
            break;
656
656k
        case PDF_INT:
657
656k
            {
658
656k
                int64_t i;
659
660
656k
                code = pdfi_obj_to_int(pdfctx->ctx, PDFobj, &i);
661
656k
                if (code < 0)
662
0
                    goto error;
663
656k
                make_int(PSobj, i);
664
656k
            }
665
0
            break;
666
247k
        case PDF_BOOL:
667
247k
            if (PDFobj == PDF_TRUE_OBJ)
668
247k
                make_bool(PSobj, 1);
669
198k
            else
670
247k
                make_bool(PSobj, 0);
671
247k
            break;
672
342k
        case PDF_REAL:
673
342k
            {
674
342k
                double d;
675
676
342k
                code = pdfi_obj_to_real(pdfctx->ctx, PDFobj, &d);
677
342k
                if (code < 0)
678
0
                    goto error;
679
342k
                make_real(PSobj, d);
680
342k
            }
681
0
            break;
682
152k
        case PDF_DICT:
683
152k
            if (PDFobj->object_num != 0) {
684
27.7k
                code = pdfi_loop_detector_add_object(pdfctx->ctx, PDFobj->object_num);
685
27.7k
                if (code < 0)
686
0
                    goto error;
687
27.7k
            }
688
152k
            debug_printmark(0);
689
152k
            code = PDFdict_to_PSdict(i_ctx_p, pdfctx, (pdf_dict *)PDFobj, PSobj);
690
152k
            debug_printmark(1);
691
152k
            break;
692
204k
        case PDF_ARRAY:
693
204k
            if (PDFobj->object_num != 0) {
694
1.46k
                code = pdfi_loop_detector_add_object(pdfctx->ctx, PDFobj->object_num);
695
1.46k
                if (code < 0)
696
0
                    goto error;
697
1.46k
            }
698
204k
            debug_printmark(2);
699
204k
            code = PDFarray_to_PSarray(i_ctx_p, pdfctx, (pdf_array *)PDFobj, PSobj);
700
204k
            debug_printmark(3);
701
204k
            break;
702
798
        default:
703
798
            make_null(PSobj);
704
798
            break;
705
1.73M
    }
706
707
1.73M
error:
708
1.73M
    if (code < 0)
709
461
        (void)pdfi_loop_detector_cleartomark(pdfctx->ctx);
710
1.73M
    else
711
1.73M
        code = pdfi_loop_detector_cleartomark(pdfctx->ctx);
712
1.73M
    return code;
713
1.73M
}
714
715
static int zPDFinfo(i_ctx_t *i_ctx_p)
716
85.6k
{
717
85.6k
    os_ptr op = osp;
718
85.6k
    pdfctx_t *pdfctx;
719
85.6k
    int code = 0;
720
85.6k
    ref intref, nameref;
721
85.6k
    uint64_t TotalFiles = 0, ix = 0;
722
85.6k
    char **names_array = NULL;
723
724
85.6k
    check_type(*(op), t_pdfctx);
725
85.6k
    pdfctx = r_ptr(op, pdfctx_t);
726
727
85.6k
    if (pdfctx->pdf_stream != NULL || pdfctx->UsingPDFFile) {
728
85.6k
        code = dict_create(4, op);
729
85.6k
        if (code < 0)
730
0
            return code;
731
732
85.6k
        code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"NumPages", 8, &nameref, 1);
733
85.6k
        if (code < 0)
734
0
            return code;
735
736
85.6k
        make_int(&intref, pdfctx->ctx->num_pages);
737
738
85.6k
        code = dict_put(op, &nameref, &intref, &i_ctx_p->dict_stack);
739
85.6k
        if (code < 0)
740
0
            return code;
741
742
        /* Code to process Collections. The pdfi_prep_collection() function returns an
743
         * array of descriptions and filenames. Because the descriptions can contain
744
         * UTF16-BE encoded data we can't sue a NULL terminated string, so the description
745
         * strings are terminated with a triple-NULL sequence of bytes.
746
         * We copy the contents into a PostScript array, which we store in the info
747
         * dictionary using the /Collection key.
748
         */
749
85.6k
        if (pdfctx->ctx->Collection != NULL) {
750
0
            code = pdfi_prep_collection(pdfctx->ctx, &TotalFiles, &names_array);
751
0
            if (code >= 0 && TotalFiles > 0) {
752
0
                uint size;
753
0
                ref collection, stringref;
754
755
0
                code = ialloc_ref_array(&collection, a_all, TotalFiles * 2, "names array");
756
0
                if (code < 0)
757
0
                    goto error;
758
759
0
                code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"Collection", 10, &nameref, 1);
760
0
                if (code < 0)
761
0
                    goto error;
762
763
0
                code = dict_put(op, &nameref, &collection, &i_ctx_p->dict_stack);
764
0
                if (code < 0)
765
0
                    goto error;
766
767
0
                for (ix=0; ix < TotalFiles * 2; ix++) {
768
0
                    char *ptr = names_array[ix];
769
0
                    byte *sbody;
770
0
                    ref *pelement;
771
772
0
                    size = 0;
773
0
                    do {
774
0
                        if (ptr[0] == 0x00 && ptr[1] == 0x00 && ptr[2] == 0x00)
775
0
                            break;
776
0
                        ptr++;
777
0
                        size++;
778
0
                    } while (1);
779
0
                    sbody = ialloc_string(size, "string");
780
0
                    if (sbody == 0) {
781
0
                        code = gs_error_VMerror;
782
0
                        goto error;
783
0
                    }
784
0
                    make_string(&stringref, a_all | icurrent_space, size, sbody);
785
0
                    memset(sbody, 0x00, size);
786
0
                    memcpy(sbody, names_array[ix], size);
787
0
                    gs_free_object(pdfctx->ctx->memory, names_array[ix], "free collection temporary filenames");
788
0
                    names_array[ix] = NULL;
789
0
                    pelement = collection.value.refs + ix;
790
0
                    ref_assign_old(&collection, pelement, &stringref, "put names string");
791
0
                }
792
0
            }
793
0
            gs_free_object(pdfctx->ctx->memory, names_array, "free collection temporary filenames");
794
0
            code = 0;
795
85.6k
        } else {
796
85.6k
            if (pdfctx->ctx->Info != NULL) {
797
26.5k
                code = PDFobj_to_PSobj(i_ctx_p, pdfctx, (pdf_obj *)pdfctx->ctx->Info, (ref *)op);
798
26.5k
                if (code < 0)
799
84
                    return code;
800
801
26.4k
                code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"NumPages", 8, &nameref, 1);
802
26.4k
                if (code < 0)
803
0
                    return code;
804
805
26.4k
                make_int(&intref, pdfctx->ctx->num_pages);
806
807
26.4k
                code = dict_put(op, &nameref, &intref, &i_ctx_p->dict_stack);
808
26.4k
                if (code < 0)
809
0
                    return code;
810
59.1k
            } else {
811
59.1k
                code = dict_create(1, op);
812
59.1k
                if (code < 0)
813
0
                    return code;
814
815
59.1k
                code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"NumPages", 8, &nameref, 1);
816
59.1k
                if (code < 0)
817
0
                    return code;
818
819
59.1k
                make_int(&intref, pdfctx->ctx->num_pages);
820
821
59.1k
                code = dict_put(op, &nameref, &intref, &i_ctx_p->dict_stack);
822
59.1k
                if (code < 0)
823
0
                    return code;
824
59.1k
            }
825
85.6k
        }
826
85.6k
    }
827
0
    else {
828
0
        return_error(gs_error_ioerror);
829
0
    }
830
85.6k
    return code;
831
832
0
error:
833
0
    for (ix=0; ix < TotalFiles * 2; ix++)
834
0
        gs_free_object(pdfctx->ctx->memory, names_array[ix], "free collection temporary filenames");
835
0
    gs_free_object(pdfctx->ctx->memory, names_array, "free collection temporary filenames");
836
0
    return code;
837
85.6k
}
838
839
static int zPDFpageinfo(i_ctx_t *i_ctx_p)
840
167k
{
841
167k
    os_ptr op = osp;
842
167k
    int page = 0, code = 0;
843
167k
    pdfctx_t *pdfctx;
844
167k
    pdf_dict *InfoDict = NULL;
845
167k
    pdfi_switch_t i_switch;
846
847
167k
    check_op(2);
848
849
167k
    check_type(*op, t_integer);
850
167k
    page = op->value.intval;
851
852
167k
    check_type(*(op - 1), t_pdfctx);
853
167k
    pdfctx = r_ptr(op - 1, pdfctx_t);
854
855
167k
    if (pdfctx->pdf_stream != NULL || pdfctx->UsingPDFFile) {
856
167k
        code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
857
858
167k
        if (code >= 0) {
859
167k
            code = pdfi_page_info(pdfctx->ctx, (uint64_t)page, &InfoDict, false);
860
861
167k
            pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
862
167k
        }
863
864
167k
        if (code < 0)
865
44.1k
            return code;
866
867
123k
        pop(1);
868
123k
        op = osp;
869
870
123k
        code = PDFobj_to_PSobj(i_ctx_p, pdfctx, (pdf_obj *)InfoDict, op);
871
123k
        pdfi_countdown(InfoDict);
872
123k
        if (code < 0)
873
0
            return code;
874
123k
    }
875
0
    else {
876
0
        return_error(gs_error_ioerror);
877
0
    }
878
123k
    return 0;
879
167k
}
880
881
static int zPDFpageinfoExt(i_ctx_t *i_ctx_p)
882
0
{
883
0
    os_ptr op = osp;
884
0
    int page = 0, code = 0;
885
0
    pdfctx_t *pdfctx;
886
0
    pdf_dict *InfoDict = NULL;
887
0
    pdfi_switch_t i_switch;
888
889
0
    check_op(2);
890
891
0
    check_type(*op, t_integer);
892
0
    page = op->value.intval;
893
894
0
    check_type(*(op - 1), t_pdfctx);
895
0
    pdfctx = r_ptr(op - 1, pdfctx_t);
896
897
0
    if (pdfctx->pdf_stream != NULL || pdfctx->UsingPDFFile) {
898
0
        code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
899
900
0
        if (code >= 0) {
901
0
            code = pdfi_page_info(pdfctx->ctx, (uint64_t)page, &InfoDict, true);
902
903
0
            pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
904
0
        }
905
906
0
        if (code < 0)
907
0
            return code;
908
909
0
        pop(1);
910
0
        op = osp;
911
912
0
        code = PDFobj_to_PSobj(i_ctx_p, pdfctx, (pdf_obj *)InfoDict, op);
913
0
        pdfi_countdown(InfoDict);
914
0
        if (code < 0)
915
0
            return code;
916
0
    }
917
0
    else {
918
0
        return_error(gs_error_ioerror);
919
0
    }
920
0
    return 0;
921
0
}
922
923
static int zPDFmetadata(i_ctx_t *i_ctx_p)
924
0
{
925
#if 0
926
    os_ptr op = osp;
927
    pdfctx_t *pdfctx;
928
929
    check_type(*op, t_pdfctx);
930
    pdfctx = r_ptr(op, pdfctx_t);
931
#endif
932
933
0
    return_error(gs_error_undefined);
934
0
}
935
936
static int zPDFdrawpage(i_ctx_t *i_ctx_p)
937
123k
{
938
123k
    os_ptr op = osp;
939
123k
    int code = 0;
940
123k
    uint64_t page = 0;
941
123k
    pdfctx_t *pdfctx;
942
123k
    pdfi_switch_t i_switch;
943
944
123k
    check_op(2);
945
946
123k
    check_type(*op, t_integer);
947
123k
    page = op->value.intval;
948
949
123k
    check_type(*(op - 1), t_pdfctx);
950
123k
    pdfctx = r_ptr(op - 1, pdfctx_t);
951
952
123k
    if (pdfctx->pdf_stream != NULL || pdfctx->UsingPDFFile) {
953
123k
        code = gs_gsave(igs);
954
123k
        if (code < 0)
955
0
            return code;
956
957
123k
        code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
958
959
123k
        if (code >= 0) {
960
123k
            if (pdfctx->ctx->args.pdfinfo)
961
0
                code = pdfi_output_page_info(pdfctx->ctx, page);
962
123k
            else
963
123k
                code = pdfi_page_render(pdfctx->ctx, page, false);
964
123k
            if (code >= 0)
965
109k
                pop(2);
966
967
123k
            pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
968
123k
        }
969
123k
        if (code == 0)
970
109k
            code = gs_grestore(igs);
971
14.1k
        else
972
14.1k
            (void)gs_grestore(igs);
973
123k
    }
974
0
    else {
975
0
        return_error(gs_error_ioerror);
976
0
    }
977
123k
    return code;
978
123k
}
979
980
static int zPDFdrawannots(i_ctx_t *i_ctx_p)
981
0
{
982
#if 0
983
    os_ptr op = osp;
984
    pdfctx_t *pdfctx;
985
986
    check_type(*op, t_pdfctx);
987
    pdfctx = r_ptr(op, pdfctx_t);
988
#endif
989
990
0
    return_error(gs_error_undefined);
991
0
}
992
993
static int zpdfi_glyph_index(gs_font *pfont, byte *str, uint size, uint *glyph)
994
263M
{
995
263M
    int code = 0;
996
263M
    ref nref;
997
263M
    i_ctx_t *i_ctx_p = get_minst_from_memory(pfont->memory)->i_ctx_p;
998
263M
    os_ptr op = osp;
999
263M
    pdfctx_t *pdfctx;
1000
1001
263M
    check_type(*op - 1, t_pdfctx);
1002
263M
    pdfctx = r_ptr(op - 1, pdfctx_t);
1003
1004
263M
    code = name_ref(pfont->memory, str, size, &nref, true);
1005
263M
    if (code < 0)
1006
8
        return code;
1007
1008
263M
    code = dict_put(&pdfctx->names_dict, &nref, &nref, &i_ctx_p->dict_stack);
1009
263M
    if (code < 0)
1010
0
        return code;
1011
1012
263M
    *glyph = name_index(pfont->memory, &nref);
1013
263M
    return 0;
1014
263M
}
1015
1016
static int param_value_get_namelist(gs_memory_t *ps_mem, pdf_context *ctx, ref *pvalueref, char ***pstrlist)
1017
0
{
1018
0
    uint count;
1019
0
    char **strlist = NULL;
1020
0
    ref lval, sref;
1021
0
    int code;
1022
1023
0
    check_read_type(*pvalueref, t_array);
1024
1025
0
    strlist = (char **)gs_alloc_bytes(ctx->memory, (size_t)(r_size(pvalueref)+1)*sizeof(char *), "param_value_get_namelist");
1026
0
    if (strlist == NULL)
1027
0
        return_error(gs_error_VMerror);
1028
0
    memset(strlist, 0x00, (r_size(pvalueref)+1)*sizeof(char *));
1029
1030
0
    for (count = 0;count < r_size(pvalueref); count++) {
1031
0
        code = array_get(ps_mem, pvalueref, count, &lval);
1032
0
        if (code < 0)
1033
0
            return code;
1034
1035
0
        if (!r_has_type(&lval, t_string) && !r_has_type(&lval, t_name))
1036
0
            return_error(gs_error_typecheck);
1037
1038
0
        if (r_has_type(&lval, t_name))
1039
0
            name_string_ref(ps_mem, (const ref *)&lval, &sref);
1040
0
        else
1041
0
            sref = lval;
1042
1043
0
        strlist[count] = (char *)gs_alloc_bytes(ctx->memory, (size_t)sref.tas.rsize + 1, "param_value_get_namelist");
1044
0
        if (strlist[count] == NULL)
1045
0
            return_error(gs_error_VMerror);
1046
0
        memset(strlist[count], 0x00, sref.tas.rsize + 1);
1047
0
        memcpy(strlist[count], sref.value.bytes, sref.tas.rsize);
1048
0
    }
1049
0
    *pstrlist = strlist;
1050
0
    return 0;
1051
0
}
1052
1053
static int apply_interpreter_params(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, ref *pdictref)
1054
109k
{
1055
109k
    int code = gs_error_typecheck;
1056
109k
    ref *pvalueref;
1057
1058
109k
    if (dict_find_string(pdictref, "PDFCACHE", &pvalueref) > 0) {
1059
0
        if (!r_has_type(pvalueref, t_integer))
1060
0
            goto error;
1061
0
        pdfctx->ctx->args.PDFCacheSize = pvalueref->value.intval;
1062
0
    }
1063
1064
109k
    if (dict_find_string(pdictref, "PDFDEBUG", &pvalueref) > 0) {
1065
109k
        if (!r_has_type(pvalueref, t_boolean))
1066
0
            goto error;
1067
109k
        pdfctx->ctx->args.pdfdebug = pvalueref->value.boolval;
1068
109k
    }
1069
1070
109k
    if (dict_find_string(pdictref, "PDFSTOPONERROR", &pvalueref) > 0) {
1071
109k
        if (!r_has_type(pvalueref, t_boolean))
1072
0
            goto error;
1073
109k
        pdfctx->ctx->args.pdfstoponerror = pvalueref->value.boolval;
1074
109k
    }
1075
1076
109k
    if (dict_find_string(pdictref, "PDFSTOPONWARNING", &pvalueref) > 0) {
1077
109k
        if (!r_has_type(pvalueref, t_boolean))
1078
0
            goto error;
1079
109k
        pdfctx->ctx->args.pdfstoponwarning = pvalueref->value.boolval;
1080
109k
        if (pvalueref->value.boolval)
1081
0
            pdfctx->ctx->args.pdfstoponerror = pvalueref->value.boolval;
1082
109k
    }
1083
1084
109k
    if (dict_find_string(pdictref, "NOTRANSPARENCY", &pvalueref) > 0) {
1085
109k
        if (!r_has_type(pvalueref, t_boolean))
1086
0
            goto error;
1087
109k
        pdfctx->ctx->args.notransparency = pvalueref->value.boolval;
1088
109k
    }
1089
1090
109k
    if (dict_find_string(pdictref, "QUIET", &pvalueref) > 0) {
1091
109k
        if (!r_has_type(pvalueref, t_boolean))
1092
0
            goto error;
1093
109k
        pdfctx->ctx->args.QUIET = pvalueref->value.boolval;
1094
109k
    }
1095
1096
109k
    if (dict_find_string(pdictref, "VerboseErrors", &pvalueref) > 0) {
1097
0
        if (!r_has_type(pvalueref, t_boolean))
1098
0
            goto error;
1099
0
        pdfctx->ctx->args.verbose_errors = pvalueref->value.boolval;
1100
0
    }
1101
1102
109k
    if (dict_find_string(pdictref, "VerboseWarnings", &pvalueref) > 0) {
1103
0
        if (!r_has_type(pvalueref, t_boolean))
1104
0
            goto error;
1105
0
        pdfctx->ctx->args.verbose_warnings = pvalueref->value.boolval;
1106
0
    }
1107
1108
109k
    if (dict_find_string(pdictref, "PDFPassword", &pvalueref) > 0) {
1109
0
        if (!r_has_type(pvalueref, t_string))
1110
0
            goto error;
1111
0
        pdfctx->ctx->encryption.Password = (char *)gs_alloc_bytes(pdfctx->ctx->memory, (size_t)r_size(pvalueref) + 1, "PDF Password from zpdfops");
1112
0
        if (pdfctx->ctx->encryption.Password == NULL) {
1113
0
            code = gs_note_error(gs_error_VMerror);
1114
0
            goto error;
1115
0
        }
1116
0
        memset(pdfctx->ctx->encryption.Password, 0x00, r_size(pvalueref) + 1);
1117
0
        memcpy(pdfctx->ctx->encryption.Password, pvalueref->value.const_bytes, r_size(pvalueref));
1118
0
        pdfctx->ctx->encryption.PasswordLen = r_size(pvalueref);
1119
0
    }
1120
1121
109k
    if (dict_find_string(pdictref, "FirstPage", &pvalueref) > 0) {
1122
0
        if (!r_has_type(pvalueref, t_integer))
1123
0
            goto error;
1124
0
        pdfctx->ctx->args.first_page = pvalueref->value.intval;
1125
0
    }
1126
1127
109k
    if (dict_find_string(pdictref, "LastPage", &pvalueref) > 0) {
1128
0
        if (!r_has_type(pvalueref, t_integer))
1129
0
            goto error;
1130
0
        pdfctx->ctx->args.last_page = pvalueref->value.intval;
1131
0
    }
1132
1133
109k
    if (dict_find_string(pdictref, "PDFNOCIDFALLBACK", &pvalueref) > 0) {
1134
109k
        if (!r_has_type(pvalueref, t_boolean))
1135
0
            goto error;
1136
109k
        pdfctx->ctx->args.nocidfallback = pvalueref->value.boolval;
1137
109k
    }
1138
1139
109k
    if (dict_find_string(pdictref, "NO_PDFMARK_OUTLINES", &pvalueref) > 0) {
1140
0
        if (!r_has_type(pvalueref, t_boolean))
1141
0
            goto error;
1142
0
        pdfctx->ctx->args.no_pdfmark_outlines = pvalueref->value.boolval;
1143
0
    }
1144
1145
109k
    if (dict_find_string(pdictref, "PDFA", &pvalueref) > 0) {
1146
0
        if (!r_has_type(pvalueref, t_integer))
1147
0
            goto error;
1148
0
        pdfctx->ctx->args.PDFA = pvalueref->value.intval;
1149
0
    }
1150
1151
109k
    if (dict_find_string(pdictref, "PDFX", &pvalueref) > 0) {
1152
0
        if (!r_has_type(pvalueref, t_integer))
1153
0
            goto error;
1154
0
        pdfctx->ctx->args.PDFX = pvalueref->value.intval;
1155
0
    }
1156
1157
109k
    if (dict_find_string(pdictref, "PDFACompatibilityPolicy", &pvalueref) > 0) {
1158
0
        if (!r_has_type(pvalueref, t_integer))
1159
0
            goto error;
1160
0
        pdfctx->ctx->args.PDFA = pvalueref->value.intval;
1161
0
    }
1162
1163
    /* This one can be a boolean OR an integer */
1164
109k
    if (dict_find_string(pdictref, "UsePDFX3Profile", &pvalueref) > 0) {
1165
0
        if (!r_has_type(pvalueref, t_boolean)) {
1166
0
            if (!r_has_type(pvalueref, t_integer))
1167
0
                goto error;
1168
0
            else {
1169
0
                pdfctx->ctx->args.UsePDFX3Profile = true;
1170
0
                pdfctx->ctx->args.PDFX3Profile_num = pvalueref->value.intval;
1171
0
            }
1172
0
        } else {
1173
0
            pdfctx->ctx->args.UsePDFX3Profile = pvalueref->value.boolval;
1174
0
            pdfctx->ctx->args.PDFX3Profile_num = 0;
1175
0
        }
1176
0
    }
1177
1178
109k
    if (dict_find_string(pdictref, "NO_PDFMARK_DESTS", &pvalueref) > 0) {
1179
0
        if (!r_has_type(pvalueref, t_boolean))
1180
0
            goto error;
1181
0
        pdfctx->ctx->args.no_pdfmark_dests = pvalueref->value.boolval;
1182
0
    }
1183
1184
109k
    if (dict_find_string(pdictref, "PDFFitPage", &pvalueref) > 0) {
1185
0
        if (!r_has_type(pvalueref, t_boolean))
1186
0
            goto error;
1187
0
        pdfctx->ctx->args.pdffitpage = pvalueref->value.boolval;
1188
0
    }
1189
1190
109k
    if (dict_find_string(pdictref, "OutputFile", &pvalueref) > 0)
1191
109k
        pdfctx->ctx->args.printed = true;
1192
0
    else
1193
0
        pdfctx->ctx->args.printed = false;
1194
1195
109k
    if (dict_find_string(pdictref, "Printed", &pvalueref) > 0) {
1196
0
        if (!r_has_type(pvalueref, t_boolean))
1197
0
            goto error;
1198
0
        pdfctx->ctx->args.printed = pvalueref->value.boolval;
1199
0
    }
1200
1201
109k
    if (dict_find_string(pdictref, "UseBleedBox", &pvalueref) > 0) {
1202
0
        if (!r_has_type(pvalueref, t_boolean))
1203
0
            goto error;
1204
0
        pdfctx->ctx->args.usebleedbox = pvalueref->value.boolval;
1205
0
    }
1206
1207
109k
    if (dict_find_string(pdictref, "UseCropBox", &pvalueref) > 0) {
1208
0
        if (!r_has_type(pvalueref, t_boolean))
1209
0
            goto error;
1210
0
        pdfctx->ctx->args.usecropbox = pvalueref->value.boolval;
1211
0
    }
1212
1213
109k
    if (dict_find_string(pdictref, "UseArtBox", &pvalueref) > 0) {
1214
0
        if (!r_has_type(pvalueref, t_boolean))
1215
0
            goto error;
1216
0
        pdfctx->ctx->args.useartbox = pvalueref->value.boolval;
1217
0
    }
1218
1219
109k
    if (dict_find_string(pdictref, "UseTrimBox", &pvalueref) > 0) {
1220
0
        if (!r_has_type(pvalueref, t_boolean))
1221
0
            goto error;
1222
0
        pdfctx->ctx->args.usetrimbox = pvalueref->value.boolval;
1223
0
    }
1224
1225
109k
    if (dict_find_string(pdictref, "ShowAcroForm", &pvalueref) > 0) {
1226
0
        if (!r_has_type(pvalueref, t_boolean))
1227
0
            goto error;
1228
0
        pdfctx->ctx->args.showacroform = pvalueref->value.boolval;
1229
0
    }
1230
1231
109k
    if (dict_find_string(pdictref, "ShowAnnots", &pvalueref) > 0) {
1232
0
        if (!r_has_type(pvalueref, t_boolean))
1233
0
            goto error;
1234
0
        pdfctx->ctx->args.showannots = pvalueref->value.boolval;
1235
0
    }
1236
1237
109k
    if (dict_find_string(pdictref, "PreserveAnnots", &pvalueref) > 0) {
1238
0
        if (!r_has_type(pvalueref, t_boolean))
1239
0
            goto error;
1240
0
        pdfctx->ctx->args.preserveannots = pvalueref->value.boolval;
1241
0
    }
1242
1243
109k
    if (dict_find_string(pdictref, "PreserveMarkedContent", &pvalueref) > 0) {
1244
0
        if (!r_has_type(pvalueref, t_boolean))
1245
0
            goto error;
1246
0
        pdfctx->ctx->args.preservemarkedcontent = pvalueref->value.boolval;
1247
0
    }
1248
1249
109k
    if (dict_find_string(pdictref, "PreserveEmbeddedFiles", &pvalueref) > 0) {
1250
0
        if (!r_has_type(pvalueref, t_boolean))
1251
0
            goto error;
1252
0
        pdfctx->ctx->args.preserveembeddedfiles = pvalueref->value.boolval;
1253
0
    }
1254
1255
109k
    if (dict_find_string(pdictref, "PreserveDocView", &pvalueref) > 0) {
1256
0
        if (!r_has_type(pvalueref, t_boolean))
1257
0
            goto error;
1258
0
        pdfctx->ctx->args.preservedocview = pvalueref->value.boolval;
1259
0
    }
1260
1261
109k
    if (dict_find_string(pdictref, "NoUserUnit", &pvalueref) > 0) {
1262
0
        if (!r_has_type(pvalueref, t_boolean))
1263
0
            goto error;
1264
0
        pdfctx->ctx->args.nouserunit = pvalueref->value.boolval;
1265
0
    }
1266
1267
109k
    if (dict_find_string(pdictref, "RENDERTTNOTDEF", &pvalueref) > 0) {
1268
109k
        if (!r_has_type(pvalueref, t_boolean))
1269
0
            goto error;
1270
109k
        pdfctx->ctx->args.renderttnotdef = pvalueref->value.boolval;
1271
109k
    }
1272
1273
109k
    if (dict_find_string(pdictref, "DOPDFMARKS", &pvalueref) > 0) {
1274
0
        if (!r_has_type(pvalueref, t_boolean))
1275
0
            goto error;
1276
0
        pdfctx->ctx->args.dopdfmarks = pvalueref->value.boolval;
1277
0
    }
1278
1279
109k
    if (dict_find_string(pdictref, "PDFINFO", &pvalueref) > 0) {
1280
0
        if (!r_has_type(pvalueref, t_boolean))
1281
0
            goto error;
1282
0
        pdfctx->ctx->args.pdfinfo = pvalueref->value.boolval;
1283
0
    }
1284
109k
    if (dict_find_string(pdictref, "ShowAnnotTypes", &pvalueref) > 0) {
1285
0
        code = param_value_get_namelist(imemory, pdfctx->ctx, pvalueref,
1286
0
                                        &pdfctx->ctx->args.showannottypes);
1287
0
        if (code < 0)
1288
0
            goto error;
1289
0
    }
1290
109k
    if (dict_find_string(pdictref, "PreserveAnnotTypes", &pvalueref) > 0) {
1291
0
        code = param_value_get_namelist(imemory, pdfctx->ctx, pvalueref,
1292
0
                                        &pdfctx->ctx->args.preserveannottypes);
1293
0
        if (code < 0)
1294
0
            goto error;
1295
0
    }
1296
109k
    if (dict_find_string(pdictref, "CIDFSubstPath", &pvalueref) > 0) {
1297
0
        if (!r_has_type(pvalueref, t_string))
1298
0
            goto error;
1299
0
        pdfctx->ctx->args.cidfsubstpath.data = (byte *)gs_alloc_bytes(pdfctx->ctx->memory, (size_t)r_size(pvalueref) + 1, "PDF cidfsubstpath from zpdfops");
1300
0
        if (pdfctx->ctx->args.cidfsubstpath.data == NULL) {
1301
0
            code = gs_note_error(gs_error_VMerror);
1302
0
            goto error;
1303
0
        }
1304
0
        memcpy(pdfctx->ctx->args.cidfsubstpath.data, pvalueref->value.const_bytes, r_size(pvalueref));
1305
0
        pdfctx->ctx->args.cidfsubstpath.size = r_size(pvalueref);
1306
0
    }
1307
109k
    if (dict_find_string(pdictref, "CIDFSubstFont", &pvalueref) > 0) {
1308
0
        if (!r_has_type(pvalueref, t_string))
1309
0
            goto error;
1310
0
        pdfctx->ctx->args.cidfsubstfont.data = (byte *)gs_alloc_bytes(pdfctx->ctx->memory, (size_t)r_size(pvalueref) + 1, "PDF cidfsubstfont from zpdfops");
1311
0
        if (pdfctx->ctx->args.cidfsubstfont.data == NULL) {
1312
0
            code = gs_note_error(gs_error_VMerror);
1313
0
            goto error;
1314
0
        }
1315
0
        memcpy(pdfctx->ctx->args.cidfsubstfont.data, pvalueref->value.const_bytes, r_size(pvalueref));
1316
0
        pdfctx->ctx->args.cidfsubstfont.size = r_size(pvalueref);
1317
0
    }
1318
109k
    if (dict_find_string(pdictref, "SUBSTFONT", &pvalueref) > 0) {
1319
0
        ref nmstr, *namstrp;
1320
0
        if (r_has_type(pvalueref, t_string)) {
1321
0
            namstrp = pvalueref;
1322
0
            pdfctx->ctx->args.defaultfont_is_name = false;
1323
0
        } else if (r_has_type(pvalueref, t_name)) {
1324
0
            name_string_ref(imemory, pvalueref, &nmstr);
1325
0
            namstrp = &nmstr;
1326
0
            pdfctx->ctx->args.defaultfont_is_name = true;
1327
0
        }
1328
0
        else {
1329
0
            code = gs_note_error(gs_error_typecheck);
1330
0
            goto error;
1331
0
        }
1332
0
        pdfctx->ctx->args.defaultfont.data = (byte *)gs_alloc_bytes(pdfctx->ctx->memory, (size_t)r_size(namstrp) + 1, "PDF defaultfontname from zpdfops");
1333
0
        if (pdfctx->ctx->args.defaultfont.data == NULL) {
1334
0
            code = gs_note_error(gs_error_VMerror);
1335
0
            goto error;
1336
0
        }
1337
0
        memcpy(pdfctx->ctx->args.defaultfont.data, pvalueref->value.const_bytes, r_size(namstrp));
1338
0
        pdfctx->ctx->args.defaultfont.size = r_size(namstrp);
1339
0
    }
1340
109k
    if (dict_find_string(pdictref, "IgnoreToUnicode", &pvalueref) > 0) {
1341
0
        if (!r_has_type(pvalueref, t_boolean))
1342
0
            goto error;
1343
0
        pdfctx->ctx->args.ignoretounicode = pvalueref->value.boolval;
1344
0
    }
1345
109k
    if (dict_find_string(pdictref, "NONATIVEFONTMAP", &pvalueref) > 0) {
1346
0
        if (!r_has_type(pvalueref, t_boolean))
1347
0
            goto error;
1348
0
        pdfctx->ctx->args.nonativefontmap = pvalueref->value.boolval;
1349
0
    }
1350
109k
    if (dict_find_string(pdictref, "PageCount", &pvalueref) > 0) {
1351
109k
        if (!r_has_type(pvalueref, t_integer))
1352
0
            goto error;
1353
109k
        pdfctx->ctx->Pdfmark_InitialPage = pvalueref->value.intval;
1354
109k
    }
1355
109k
    code = 0;
1356
1357
109k
error:
1358
109k
    return code;
1359
109k
}
1360
1361
static int zPDFSetParams(i_ctx_t *i_ctx_p)
1362
0
{
1363
0
    os_ptr op = osp;
1364
0
    int code = 0;
1365
0
    pdfctx_t *pdfctx = NULL;
1366
1367
0
    check_op(2);
1368
1369
0
    check_type(*(op - 1), t_pdfctx);
1370
0
    pdfctx = r_ptr(op - 1, pdfctx_t);
1371
1372
0
    check_type(*op, t_dictionary);
1373
1374
0
    code = apply_interpreter_params(i_ctx_p, pdfctx, op);
1375
1376
0
    pop(2);
1377
0
    return code;
1378
0
}
1379
1380
static int zPDFInit(i_ctx_t *i_ctx_p)
1381
109k
{
1382
109k
    os_ptr op = osp;
1383
109k
    pdfctx_t *pdfctx = NULL;
1384
109k
    pdf_context *ctx = NULL;
1385
109k
    int code = 0;
1386
109k
    gs_memory_t *cmem;
1387
1388
109k
    code = gs_memory_chunk_wrap(&cmem, imemory->non_gc_memory);
1389
109k
    if (code < 0)
1390
0
        return_error(gs_error_VMerror);
1391
1392
109k
    pdfctx = gs_alloc_struct(imemory, pdfctx_t, &st_pdfctx_t, "PDFcontext");
1393
109k
    if (!pdfctx) {
1394
0
        code = gs_note_error(gs_error_VMerror);
1395
0
        goto error;
1396
0
    }
1397
109k
    pdfctx->pdf_memory = cmem;
1398
109k
    pdfctx->ctx = NULL;
1399
109k
    pdfctx->ps_stream = NULL;
1400
109k
    pdfctx->pdf_stream = NULL;
1401
109k
    pdfctx->UsingPDFFile = false;
1402
109k
    pdfctx->pdf_stream_memory = NULL;
1403
109k
    pdfctx->profile_cache = gsicc_profilecache_new(imemory);
1404
109k
    if (pdfctx->profile_cache == NULL) {
1405
0
        code = gs_note_error(gs_error_VMerror);
1406
0
        goto error;
1407
0
    }
1408
109k
    pdfctx->cache_memory = imemory;
1409
    /* The size is arbitrary */
1410
109k
    code = dict_alloc(iimemory, 1, &pdfctx->names_dict);
1411
109k
    if (code < 0)
1412
0
        goto error;
1413
1414
109k
    ctx = pdfi_create_context(cmem);
1415
109k
    if (ctx == NULL) {
1416
0
        code = gs_note_error(gs_error_VMerror);
1417
0
        goto error;
1418
0
    }
1419
1420
109k
    pdfctx->ctx = ctx;
1421
109k
    get_zfont_glyph_name(&pdfctx->ctx->get_glyph_name);
1422
109k
    pdfctx->ctx->get_glyph_index = zpdfi_glyph_index;
1423
1424
109k
    if (ref_stack_count(&o_stack) > 0) {
1425
109k
        if (r_has_type(op, t_dictionary))
1426
109k
            code = apply_interpreter_params(i_ctx_p, pdfctx, op);
1427
109k
        pop(1);
1428
109k
        if (code < 0)
1429
0
            goto error;
1430
109k
    }
1431
109k
    code = zpdfi_populate_search_paths(i_ctx_p, ctx);
1432
109k
    if (code < 0)
1433
0
        goto error;
1434
1435
109k
    code = zpdfi_populate_fontmap_files(i_ctx_p, ctx);
1436
109k
    if (code < 0)
1437
0
        goto error;
1438
1439
109k
    op = osp;
1440
109k
    push(1);
1441
109k
    make_tav(op, t_pdfctx, icurrent_space | a_all, pstruct, (obj_header_t *)(pdfctx));
1442
109k
    return 0;
1443
1444
0
error:
1445
0
    if (ctx != NULL)
1446
0
        pdfi_free_context(ctx);
1447
    /* gs_memory_chunk_unwrap() returns the "wrapped" allocator, which we don't need */
1448
0
    (void)gs_memory_chunk_unwrap(cmem);
1449
0
    if (pdfctx != NULL) {
1450
0
        pdfctx->ctx = NULL; /* Freed already above! */
1451
0
        if (pdfctx->profile_cache != NULL) {
1452
0
            gs_free_object(imemory, pdfctx->profile_cache, "discard temporary profile cache");
1453
0
            pdfctx->profile_cache = NULL;
1454
0
        }
1455
0
        pdfctx->pdf_memory = NULL;
1456
0
        gs_free_object(imemory, pdfctx, "PDFcontext");
1457
0
    }
1458
0
    return code;
1459
109k
}
1460
1461
/*   <Pagelist_string> num_pages .PDFparsePageList even/odd, start, end ... range_count */
1462
/*   PostScript will create an array of 3 integers per range      */
1463
static int zPDFparsePageList(i_ctx_t *i_ctx_p)
1464
8
{
1465
8
    int code = 0, size = 0, i;
1466
8
    os_ptr op = osp;
1467
8
    int *page_range_array;
1468
8
    int num_pages;
1469
8
    ref *o;
1470
8
    char *PageString = NULL;
1471
1472
8
    check_op(2);
1473
1474
2
    code = int_param(op, max_int, &num_pages);
1475
2
    if (code < 0)
1476
1
        return code;
1477
1478
2
    check_type_only(*(op - 1), t_string);
1479
1480
0
    PageString = (char *)gs_alloc_bytes(imemory, (size_t)r_size(op - 1) + 1, "zPDFparsePageList");
1481
0
    if (PageString == NULL)
1482
0
        return_error(gs_error_VMerror);
1483
0
    memcpy(PageString, (op - 1)->value.const_bytes, r_size(op - 1));
1484
0
    PageString[r_size(op - 1)] = 0x00;
1485
0
    code = pagelist_parse_to_array(PageString, imemory, num_pages, &page_range_array);
1486
0
    gs_free_object(imemory, PageString, "zPDFparsePageList");
1487
1488
0
    make_int(op, 0);        /* default return 0 */
1489
0
    if (code < 0) {
1490
0
        return code;
1491
0
    }
1492
    /* code returned is the number of ranges */
1493
0
    size = 3 * (code - 1);    /* runpdfpagerange doesn't use 0, 0, 0 marker at end */
1494
0
    code = ref_stack_push(&o_stack, size - 1);
1495
0
    if (code < 0) {
1496
0
        return code;
1497
0
    }
1498
    /* push the even/odd, start, end triples on the stack */
1499
0
    for (i=0; i < size;  i++) {
1500
0
        o = ref_stack_index(&o_stack, size - i);
1501
0
        if (o == NULL)
1502
0
            return_error(gs_error_stackunderflow);
1503
        /* skip the initial "ordered" flag */
1504
0
        make_int(o, page_range_array[i+1]);
1505
0
    }
1506
0
    o = ref_stack_index(&o_stack, 0);
1507
0
    if (o == NULL)
1508
0
        return_error(gs_error_stackunderflow);
1509
0
    make_int(o, size);
1510
0
    pagelist_free_range_array(imemory, page_range_array);    /* all done with C array */
1511
0
    return 0;
1512
0
}
1513
#else
1514
1515
static int zPDFfile(i_ctx_t *i_ctx_p)
1516
{
1517
    return_error(gs_error_undefined);
1518
}
1519
1520
static int zPDFstream(i_ctx_t *i_ctx_p)
1521
{
1522
    return_error(gs_error_undefined);
1523
}
1524
1525
static int zPDFclose(i_ctx_t *i_ctx_p)
1526
{
1527
    return_error(gs_error_undefined);
1528
}
1529
1530
static int zPDFinfo(i_ctx_t *i_ctx_p)
1531
{
1532
    return_error(gs_error_undefined);
1533
}
1534
1535
static int zPDFpageinfo(i_ctx_t *i_ctx_p)
1536
{
1537
    return_error(gs_error_undefined);
1538
}
1539
1540
static int zPDFpageinfoExt(i_ctx_t *i_ctx_p)
1541
{
1542
    return_error(gs_error_undefined);
1543
}
1544
1545
static int zPDFmetadata(i_ctx_t *i_ctx_p)
1546
{
1547
    return_error(gs_error_undefined);
1548
}
1549
1550
static int zPDFdrawpage(i_ctx_t *i_ctx_p)
1551
{
1552
    return_error(gs_error_undefined);
1553
}
1554
1555
static int zPDFdrawannots(i_ctx_t *i_ctx_p)
1556
{
1557
    return_error(gs_error_undefined);
1558
}
1559
1560
static int zPDFSetParams(i_ctx_t *i_ctx_p)
1561
{
1562
    return_error(gs_error_undefined);
1563
}
1564
1565
static int zPDFInit(i_ctx_t *i_ctx_p)
1566
{
1567
    return_error(gs_error_undefined);
1568
}
1569
1570
static int zPDFparsePageList(i_ctx_t *i_ctx_p)
1571
{
1572
    return_error(gs_error_undefined);
1573
}
1574
#endif
1575
1576
static int zPDFAvailable(i_ctx_t *i_ctx_p)
1577
109k
{
1578
109k
    os_ptr op = osp;
1579
1580
109k
    push(1);
1581
109k
#if defined(BUILD_PDF) && BUILD_PDF == 1
1582
109k
    make_bool(op, true);
1583
#else
1584
    make_bool(op, false);
1585
#endif
1586
109k
    return 0;
1587
109k
}
1588
1589
/* ------ Initialization procedure ------ */
1590
1591
const op_def zpdfops_op_defs[] =
1592
{
1593
    {"0.PDFFile", zPDFfile},
1594
    {"1.PDFStream", zPDFstream},
1595
    {"1.PDFClose", zPDFclose},
1596
    {"1.PDFInfo", zPDFinfo},
1597
    {"1.PDFPageInfo", zPDFpageinfo},
1598
    {"1.PDFPageInfoExt", zPDFpageinfoExt},
1599
    {"1.PDFMetadata", zPDFmetadata},
1600
    {"1.PDFDrawPage", zPDFdrawpage},
1601
    {"1.PDFDrawAnnots", zPDFdrawannots},
1602
    {"1.PDFInit", zPDFInit},
1603
    {"1.PDFparsePageList", zPDFparsePageList},
1604
    {"0.PDFAvailable", zPDFAvailable},
1605
    {"2.PDFSetParams", zPDFSetParams},
1606
    op_def_end(0)
1607
};