Coverage Report

Created: 2025-12-31 07:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/psi/zpdfops.c
Line
Count
Source
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
110k
{
59
110k
    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
110k
    if (ctx->search_paths.resource_paths == NULL) {
64
110k
        ref *l2dictref, *grdref, *fpathref;
65
110k
        int i;
66
110k
        const gs_file_path *pfpath = i_ctx_p->lib_path;
67
110k
        gs_main_instance *minst = get_minst_from_memory(imemory);
68
110k
        code = dict_find_string(systemdict, "pssystemparams", &l2dictref);
69
110k
        if (code >= 0 && r_has_type(l2dictref, t_dictionary)) {
70
110k
            code = dict_find_string(l2dictref, "GenericResourceDir", &grdref);
71
110k
            if (code >= 0 && r_has_type(grdref, t_string)) {
72
110k
                ctx->search_paths.genericresourcedir.data = gs_alloc_bytes(ctx->memory, r_size(grdref), "zpdfi_populate_search_paths");
73
110k
                if (ctx->search_paths.genericresourcedir.data == NULL) {
74
0
                    code = gs_note_error(gs_error_VMerror);
75
0
                    goto done;
76
0
                }
77
110k
                memcpy((char *)ctx->search_paths.genericresourcedir.data, grdref->value.const_bytes, r_size(grdref));
78
110k
                ctx->search_paths.genericresourcedir.size = r_size(grdref);
79
110k
                ctx->search_paths.genericresourcedir.persistent = false;
80
110k
            }
81
110k
        }
82
83
110k
        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
110k
        if (ctx->search_paths.resource_paths == NULL) {
85
0
            code = gs_note_error(gs_error_VMerror);
86
0
            goto done;
87
0
        }
88
110k
        memset(ctx->search_paths.resource_paths, 0x00, sizeof(gs_param_string) * r_size(&pfpath->list));
89
90
110k
        ctx->search_paths.num_resource_paths = r_size(&pfpath->list);
91
1.54M
        for (i = 0; i < r_size(&pfpath->list); i++) {
92
1.43M
            const ref *prdir = pfpath->list.value.refs + i; /* By nature, this cannot be a short/mixed array, only a "normal" array */
93
1.43M
            ctx->search_paths.resource_paths[i].data = gs_alloc_bytes(ctx->memory, r_size(prdir), "zpdfi_populate_search_paths");
94
1.43M
            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.43M
            memcpy((char *)ctx->search_paths.resource_paths[i].data, prdir->value.const_bytes, r_size(prdir));
99
1.43M
            ctx->search_paths.resource_paths[i].size = r_size(prdir);
100
1.43M
            ctx->search_paths.resource_paths[i].persistent = false;
101
1.43M
        }
102
110k
        code = dict_find_string(systemdict, "FONTPATH", &fpathref);
103
110k
        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
110k
        ctx->search_paths.search_here_first = minst->search_here_first;
125
110k
    }
126
110k
done:
127
110k
    return code >= 0 ? 0 : code;
128
110k
}
129
130
static int zpdfi_populate_fontmap_files(i_ctx_t *i_ctx_p, pdf_context *ctx)
131
110k
{
132
110k
    int code, i;
133
110k
    ref *fontmaps;
134
135
110k
    code = dict_find_string(systemdict, "FONTMAP", &fontmaps);
136
110k
    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
110k
    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
110k
    else
175
110k
        code = 0;
176
110k
done:
177
110k
    return code;
178
110k
}
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.67k
ENUM_PTRS_BEGIN(pdfctx_enum_ptrs) return 0;
238
934
  ENUM_PTR3(0, pdfctx_t, ps_stream, pdf_stream, profile_cache);
239
934
  case 3:
240
934
    ENUM_RETURN_REF(&((pdfctx_t *)vptr)->names_dict);
241
4.67k
ENUM_PTRS_END
242
243
934
static RELOC_PTRS_BEGIN(pdfctx_reloc_ptrs);
244
934
RELOC_REF_VAR(((pdfctx_t *)vptr)->names_dict);
245
934
ref_struct_clear_marks(gcst->cur_mem, &(((pdfctx_t *)vptr)->names_dict), 1, pstype);
246
934
RELOC_PTR3(pdfctx_t, ps_stream, pdf_stream, profile_cache);
247
934
RELOC_PTRS_END
248
249
static void
250
pdfctx_finalize(const gs_memory_t *cmem, void *vptr)
251
110k
{
252
110k
    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
110k
    make_null(&pdfctx->names_dict);
258
110k
    if (pdfctx->profile_cache != NULL) {
259
440
        rc_decrement(pdfctx->profile_cache, "free the working profile cache");
260
440
        pdfctx->profile_cache = NULL;
261
440
    }
262
110k
    if (cmem != NULL) {
263
110k
        if (pdfctx->ctx != NULL) {
264
440
            if (pdfctx->pdf_stream) {
265
418
                 memset(pdfctx->pdf_stream, 0x00, sizeof(stream));
266
418
                 gs_free_object(pdfctx->pdf_stream_memory, pdfctx->pdf_stream, "free PDF copy of stream");
267
418
                 pdfctx->pdf_stream = NULL;
268
418
            }
269
270
440
            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
418
                pdfctx->ctx->main_stream->s = NULL;
275
418
            }
276
440
            (void)pdfi_free_context(pdfctx->ctx);
277
440
            pdfctx->ctx = NULL;
278
440
        }
279
110k
        if (pdfctx->pdf_memory != NULL) {
280
            /* gs_memory_chunk_unwrap() returns the "wrapped" allocator, which we don't need */
281
110k
            (void)gs_memory_chunk_unwrap(pdfctx->pdf_memory);
282
110k
            pdfctx->pdf_memory = NULL;
283
110k
        }
284
110k
    }
285
110k
}
286
287
static int zPDFstream(i_ctx_t *i_ctx_p)
288
110k
{
289
110k
    os_ptr op = osp;
290
110k
    int code = 0;
291
110k
    stream *s;
292
110k
    pdfctx_t *pdfctx;
293
110k
    pdfi_switch_t i_switch;
294
295
110k
    check_op(2);
296
297
110k
    check_read_file(i_ctx_p, s, op - 1);
298
299
110k
    check_type(*op, t_pdfctx);
300
110k
    pdfctx = r_ptr(op, pdfctx_t);
301
302
    /* If the supplied context already has a file open, signal an error */
303
110k
    if (pdfctx->ps_stream != NULL || pdfctx->UsingPDFFile)
304
0
        return_error(gs_error_ioerror);
305
306
110k
    s->close_at_eod = false;
307
110k
    pdfctx->ps_stream = s;
308
110k
    pdfctx->pdf_stream = s_alloc_immovable(imemory->stable_memory, "PDFstream copy of PS stream");
309
110k
    pdfctx->pdf_stream_memory = imemory->stable_memory;
310
110k
    if (pdfctx->pdf_stream == NULL)
311
0
        return_error(gs_error_VMerror);
312
313
110k
    *(pdfctx->pdf_stream) = *(pdfctx->ps_stream);
314
315
110k
    code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
316
317
110k
    if (code >= 0) {
318
110k
        code = pdfi_set_input_stream(pdfctx->ctx, pdfctx->pdf_stream);
319
320
110k
        pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
321
110k
    }
322
323
110k
    if (code < 0) {
324
21.5k
        memset(pdfctx->pdf_stream, 0x00, sizeof(stream));
325
21.5k
        gs_free_object(imemory, pdfctx->pdf_stream, "PDFstream copy of PS stream");
326
21.5k
        pdfctx->ctx->main_stream->s = NULL;
327
21.5k
        pdfctx->pdf_stream = NULL;
328
21.5k
        pdfctx->ps_stream = NULL;
329
21.5k
        return code;
330
21.5k
    }
331
332
89.0k
    pdfctx->ctx->finish_page = NULL;
333
89.0k
    make_tav(op, t_pdfctx, icurrent_space | a_all, pstruct, (obj_header_t *)(pdfctx));
334
335
89.0k
    pop(2);
336
89.0k
    return 0;
337
110k
}
338
339
static int zPDFfile(i_ctx_t *i_ctx_p)
340
14
{
341
14
    os_ptr op = osp;
342
14
    pdfctx_t *pdfctx;
343
14
    char pdffilename[gp_file_name_sizeof];
344
14
    int code = 0;
345
14
    pdfi_switch_t i_switch;
346
347
14
    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
110k
{
385
110k
    os_ptr op = osp;
386
110k
    int code = 0;
387
110k
    pdfctx_t *pdfctx;
388
389
110k
    check_type(*op, t_pdfctx);
390
110k
    pdfctx = r_ptr(op, pdfctx_t);
391
392
110k
    if (pdfctx->profile_cache != NULL) {
393
110k
        rc_decrement(pdfctx->profile_cache, "free the working profile cache");
394
110k
        pdfctx->profile_cache = NULL;
395
110k
    }
396
397
110k
    if (pdfctx->ctx != NULL) {
398
110k
        if (pdfctx->pdf_stream != NULL || pdfctx->ps_stream != NULL) {
399
88.6k
            pdfi_switch_t i_switch;
400
401
88.6k
            code = gs_gsave(igs);
402
88.6k
            if (code < 0)
403
0
                return code;
404
405
88.6k
            code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
406
407
88.6k
            if (code >= 0) {
408
88.6k
                pdfi_finish_pdf_file(pdfctx->ctx);
409
88.6k
                pdfi_report_errors(pdfctx->ctx);
410
411
88.6k
                pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
412
88.6k
            }
413
88.6k
            code = gs_grestore(igs);
414
88.6k
            if (code < 0)
415
0
                return code;
416
88.6k
        }
417
110k
        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
88.6k
            if (pdfctx->ctx->main_stream)
422
88.6k
                pdfctx->ctx->main_stream->s = NULL;
423
88.6k
        }
424
110k
        code = pdfi_free_context(pdfctx->ctx);
425
110k
        pdfctx->ctx = NULL;
426
110k
    }
427
110k
    if (pdfctx->pdf_stream) {
428
88.6k
        memset(pdfctx->pdf_stream, 0x00, sizeof(stream));
429
88.6k
        gs_free_object(imemory, pdfctx->pdf_stream, "free copy of PostScript stream");
430
88.6k
        pdfctx->pdf_stream = NULL;
431
88.6k
    }
432
110k
    if (pdfctx->ps_stream)
433
88.6k
        pdfctx->ps_stream = NULL;
434
110k
    pop(1);
435
110k
    return code;
436
110k
}
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
782k
{
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
782k
}
461
462
static void debug_pdfobj(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_obj *PDFobj)
463
2.74M
{
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.74M
}
503
504
static int PDFdict_to_PSdict(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_dict *PDFdict, ref *PSdict)
505
167k
{
506
167k
    int code = 0;
507
167k
    uint64_t index = 0;
508
167k
    pdf_name *Key = NULL;
509
167k
    pdf_obj *Value = NULL;
510
167k
    ref nameref, valueref;
511
167k
    char *str = NULL;
512
167k
    int len = 0;
513
514
167k
    code = dict_create(pdfi_dict_entries(PDFdict), PSdict);
515
167k
    if (code < 0)
516
0
        return code;
517
518
167k
    code = pdfi_loop_detector_mark(pdfctx->ctx);
519
167k
    if (code < 0)
520
0
        goto error;
521
522
167k
    code = pdfi_dict_first(pdfctx->ctx, PDFdict, (pdf_obj **)&Key, &Value, &index);
523
167k
    if (code == gs_error_undefined) {
524
896
        code = 0;
525
896
        goto error;
526
896
    }
527
528
833k
    while (code >= 0) {
529
833k
        code = pdfi_string_from_name(pdfctx->ctx, Key, &str, &len);
530
833k
        if (code < 0)
531
0
            goto error;
532
533
833k
        debug_pdfobj(i_ctx_p, pdfctx, (pdf_obj *)Key);
534
535
833k
        code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)str, len, &nameref, 1);
536
833k
        if (code < 0)
537
0
            goto error;
538
539
833k
        code = PDFobj_to_PSobj(i_ctx_p, pdfctx, Value, &valueref);
540
833k
        if (code < 0)
541
327
            goto error;
542
543
833k
        code = dict_put(PSdict, &nameref, &valueref, &i_ctx_p->dict_stack);
544
833k
        if (code < 0)
545
0
            goto error;
546
547
833k
        pdfi_countdown(Key);
548
833k
        pdfi_countdown(Value);
549
833k
        Key = NULL;
550
833k
        Value = NULL;
551
552
833k
        code = pdfi_loop_detector_cleartomark(pdfctx->ctx);
553
833k
        if (code < 0)
554
0
            goto error;
555
556
833k
        code = pdfi_loop_detector_mark(pdfctx->ctx);
557
833k
        if (code < 0)
558
0
            goto error;
559
560
833k
        (void)pdfi_free_string_from_name(pdfctx->ctx, str);
561
833k
        str = NULL;
562
833k
        code = pdfi_dict_next(pdfctx->ctx, PDFdict, (pdf_obj **)&Key, &Value, &index);
563
833k
        if (code == gs_error_undefined) {
564
165k
            code = 0;
565
165k
            break;
566
165k
        }
567
833k
    }
568
167k
error:
569
167k
    (void)pdfi_free_string_from_name(pdfctx->ctx, str);
570
167k
    pdfi_countdown(Key);
571
167k
    pdfi_countdown(Value);
572
573
167k
    if (code < 0)
574
380
        (void)pdfi_loop_detector_cleartomark(pdfctx->ctx);
575
166k
    else
576
166k
        code = pdfi_loop_detector_cleartomark(pdfctx->ctx);
577
167k
    return code;
578
166k
}
579
580
static int PDFarray_to_PSarray(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_array *PDFarray, ref *PSarray)
581
224k
{
582
224k
    int code = 0, i = 0;
583
224k
    ref PS_ref;
584
224k
    pdf_obj *array_obj = NULL;
585
224k
    ref *eltp = NULL;
586
587
224k
    code = pdfi_loop_detector_mark(pdfctx->ctx);
588
224k
    if (code < 0)
589
0
        goto error;
590
591
224k
    code = ialloc_ref_array(PSarray, a_all, pdfi_array_size(PDFarray), "zPDFInfo");
592
224k
    if (code < 0)
593
0
        goto error;
594
595
1.13M
    for (i = 0;i < pdfi_array_size(PDFarray); i++) {
596
908k
        code = pdfi_array_fetch_recursing(pdfctx->ctx, PDFarray, i, &array_obj, true, true);
597
908k
        if (code < 0)
598
45
            goto error;
599
908k
        code = PDFobj_to_PSobj(i_ctx_p, pdfctx, array_obj, &PS_ref);
600
908k
        if (code < 0) {
601
119
            pdfi_countdown(array_obj);
602
119
            goto error;
603
119
        }
604
605
908k
        eltp = PSarray->value.refs + i;
606
908k
        ref_assign_old((const ref *)PSarray, eltp, &PS_ref, "zPDFInfo");
607
608
908k
        pdfi_countdown(array_obj);
609
908k
        array_obj = NULL;
610
908k
    }
611
224k
error:
612
224k
    if (code < 0)
613
164
        (void)pdfi_loop_detector_cleartomark(pdfctx->ctx);
614
223k
    else
615
223k
        code = pdfi_loop_detector_cleartomark(pdfctx->ctx);
616
224k
    return code;
617
224k
}
618
619
static int PDFobj_to_PSobj(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_obj *PDFobj, ref *PSobj)
620
1.90M
{
621
1.90M
    int code = 0;
622
623
1.90M
    code = pdfi_loop_detector_mark(pdfctx->ctx);
624
1.90M
    if (code < 0)
625
0
        goto error;
626
627
1.90M
    debug_pdfobj(i_ctx_p, pdfctx, PDFobj);
628
629
1.90M
    switch(pdfi_type_of(PDFobj)) {
630
10.4k
        case PDF_NAME:
631
10.4k
            {
632
10.4k
                char *str = NULL;
633
10.4k
                int len;
634
635
10.4k
                code = pdfi_string_from_name(pdfctx->ctx, (pdf_name *)PDFobj, &str, &len);
636
10.4k
                if (code < 0)
637
0
                    goto error;
638
10.4k
                code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)str, len, PSobj, 1);
639
10.4k
                (void)pdfi_free_string_from_name(pdfctx->ctx, str);
640
10.4k
            }
641
0
            break;
642
141k
        case PDF_STRING:
643
141k
            {
644
141k
                byte *sbody;
645
141k
                uint size = ((pdf_name *)PDFobj)->length;
646
647
141k
                sbody = ialloc_string(size, "string");
648
141k
                if (sbody == 0) {
649
0
                    code = gs_note_error(gs_error_VMerror);
650
141k
                } else {
651
141k
                    make_string(PSobj, a_all | icurrent_space, size, sbody);
652
141k
                    memcpy(sbody, ((pdf_name *)PDFobj)->data, size);
653
141k
                }
654
141k
            }
655
141k
            break;
656
716k
        case PDF_INT:
657
716k
            {
658
716k
                int64_t i;
659
660
716k
                code = pdfi_obj_to_int(pdfctx->ctx, PDFobj, &i);
661
716k
                if (code < 0)
662
0
                    goto error;
663
716k
                make_int(PSobj, i);
664
716k
            }
665
0
            break;
666
269k
        case PDF_BOOL:
667
269k
            if (PDFobj == PDF_TRUE_OBJ)
668
269k
                make_bool(PSobj, 1);
669
215k
            else
670
269k
                make_bool(PSobj, 0);
671
269k
            break;
672
376k
        case PDF_REAL:
673
376k
            {
674
376k
                double d;
675
676
376k
                code = pdfi_obj_to_real(pdfctx->ctx, PDFobj, &d);
677
376k
                if (code < 0)
678
0
                    goto error;
679
376k
                make_real(PSobj, d);
680
376k
            }
681
0
            break;
682
167k
        case PDF_DICT:
683
167k
            if (PDFobj->object_num != 0) {
684
31.8k
                code = pdfi_loop_detector_add_object(pdfctx->ctx, PDFobj->object_num);
685
31.8k
                if (code < 0)
686
0
                    goto error;
687
31.8k
            }
688
167k
            debug_printmark(0);
689
167k
            code = PDFdict_to_PSdict(i_ctx_p, pdfctx, (pdf_dict *)PDFobj, PSobj);
690
167k
            debug_printmark(1);
691
167k
            break;
692
224k
        case PDF_ARRAY:
693
224k
            if (PDFobj->object_num != 0) {
694
1.55k
                code = pdfi_loop_detector_add_object(pdfctx->ctx, PDFobj->object_num);
695
1.55k
                if (code < 0)
696
0
                    goto error;
697
1.55k
            }
698
224k
            debug_printmark(2);
699
224k
            code = PDFarray_to_PSarray(i_ctx_p, pdfctx, (pdf_array *)PDFobj, PSobj);
700
224k
            debug_printmark(3);
701
224k
            break;
702
1.06k
        default:
703
1.06k
            make_null(PSobj);
704
1.06k
            break;
705
1.90M
    }
706
707
1.90M
error:
708
1.90M
    if (code < 0)
709
544
        (void)pdfi_loop_detector_cleartomark(pdfctx->ctx);
710
1.90M
    else
711
1.90M
        code = pdfi_loop_detector_cleartomark(pdfctx->ctx);
712
1.90M
    return code;
713
1.90M
}
714
715
static int zPDFinfo(i_ctx_t *i_ctx_p)
716
89.0k
{
717
89.0k
    os_ptr op = osp;
718
89.0k
    pdfctx_t *pdfctx;
719
89.0k
    int code = 0;
720
89.0k
    ref intref, nameref;
721
89.0k
    uint64_t TotalFiles = 0, ix = 0;
722
89.0k
    char **names_array = NULL;
723
724
89.0k
    check_type(*(op), t_pdfctx);
725
89.0k
    pdfctx = r_ptr(op, pdfctx_t);
726
727
89.0k
    if (pdfctx->pdf_stream != NULL || pdfctx->UsingPDFFile) {
728
89.0k
        code = dict_create(4, op);
729
89.0k
        if (code < 0)
730
0
            return code;
731
732
89.0k
        code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"NumPages", 8, &nameref, 1);
733
89.0k
        if (code < 0)
734
0
            return code;
735
736
89.0k
        make_int(&intref, pdfctx->ctx->num_pages);
737
738
89.0k
        code = dict_put(op, &nameref, &intref, &i_ctx_p->dict_stack);
739
89.0k
        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
89.0k
        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;
769
0
                    byte *sbody;
770
0
                    ref *pelement;
771
772
0
                    if ((ptr = names_array[ix]) == NULL)
773
0
                        continue;
774
775
0
                    size = 0;
776
0
                    do {
777
0
                        if (ptr[0] == 0x00 && ptr[1] == 0x00 && ptr[2] == 0x00)
778
0
                            break;
779
0
                        ptr++;
780
0
                        size++;
781
0
                    } while (1);
782
0
                    sbody = ialloc_string(size, "string");
783
0
                    if (sbody == 0) {
784
0
                        code = gs_error_VMerror;
785
0
                        goto error;
786
0
                    }
787
0
                    make_string(&stringref, a_all | icurrent_space, size, sbody);
788
0
                    memset(sbody, 0x00, size);
789
0
                    memcpy(sbody, names_array[ix], size);
790
0
                    gs_free_object(pdfctx->ctx->memory, names_array[ix], "free collection temporary filenames");
791
0
                    names_array[ix] = NULL;
792
0
                    pelement = collection.value.refs + ix;
793
0
                    ref_assign_old(&collection, pelement, &stringref, "put names string");
794
0
                }
795
0
            }
796
0
            gs_free_object(pdfctx->ctx->memory, names_array, "free collection temporary filenames");
797
0
            code = 0;
798
89.0k
        } else {
799
89.0k
            if (pdfctx->ctx->Info != NULL) {
800
30.0k
                code = PDFobj_to_PSobj(i_ctx_p, pdfctx, (pdf_obj *)pdfctx->ctx->Info, (ref *)op);
801
30.0k
                if (code < 0) {
802
98
                    if (pdfctx->ctx->args.pdfstoponerror)
803
0
                        return code;
804
98
                    code = dict_create(1, op);
805
98
                    if (code < 0)
806
0
                        return code;
807
98
                }
808
809
30.0k
                code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"NumPages", 8, &nameref, 1);
810
30.0k
                if (code < 0)
811
0
                    return code;
812
813
30.0k
                make_int(&intref, pdfctx->ctx->num_pages);
814
815
30.0k
                code = dict_put(op, &nameref, &intref, &i_ctx_p->dict_stack);
816
30.0k
                if (code < 0)
817
0
                    return code;
818
58.9k
            } else {
819
58.9k
                code = dict_create(1, op);
820
58.9k
                if (code < 0)
821
0
                    return code;
822
823
58.9k
                code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)"NumPages", 8, &nameref, 1);
824
58.9k
                if (code < 0)
825
0
                    return code;
826
827
58.9k
                make_int(&intref, pdfctx->ctx->num_pages);
828
829
58.9k
                code = dict_put(op, &nameref, &intref, &i_ctx_p->dict_stack);
830
58.9k
                if (code < 0)
831
0
                    return code;
832
58.9k
            }
833
89.0k
        }
834
89.0k
    }
835
0
    else {
836
0
        return_error(gs_error_ioerror);
837
0
    }
838
89.0k
    return code;
839
840
0
error:
841
0
    for (ix=0; ix < TotalFiles * 2; ix++)
842
0
        gs_free_object(pdfctx->ctx->memory, names_array[ix], "free collection temporary filenames");
843
0
    gs_free_object(pdfctx->ctx->memory, names_array, "free collection temporary filenames");
844
0
    return code;
845
89.0k
}
846
847
static int zPDFpageinfo(i_ctx_t *i_ctx_p)
848
182k
{
849
182k
    os_ptr op = osp;
850
182k
    int page = 0, code = 0;
851
182k
    pdfctx_t *pdfctx;
852
182k
    pdf_dict *InfoDict = NULL;
853
182k
    pdfi_switch_t i_switch;
854
855
182k
    check_op(2);
856
857
182k
    check_type(*op, t_integer);
858
182k
    page = op->value.intval;
859
860
182k
    check_type(*(op - 1), t_pdfctx);
861
182k
    pdfctx = r_ptr(op - 1, pdfctx_t);
862
863
182k
    if (pdfctx->pdf_stream != NULL || pdfctx->UsingPDFFile) {
864
182k
        code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
865
866
182k
        if (code >= 0) {
867
182k
            code = pdfi_page_info(pdfctx->ctx, (uint64_t)page, &InfoDict, false);
868
869
182k
            pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
870
182k
        }
871
872
182k
        if (code < 0)
873
48.0k
            return code;
874
875
134k
        pop(1);
876
134k
        op = osp;
877
878
134k
        code = PDFobj_to_PSobj(i_ctx_p, pdfctx, (pdf_obj *)InfoDict, op);
879
134k
        pdfi_countdown(InfoDict);
880
134k
        if (code < 0)
881
0
            return code;
882
134k
    }
883
0
    else {
884
0
        return_error(gs_error_ioerror);
885
0
    }
886
134k
    return 0;
887
182k
}
888
889
static int zPDFpageinfoExt(i_ctx_t *i_ctx_p)
890
0
{
891
0
    os_ptr op = osp;
892
0
    int page = 0, code = 0;
893
0
    pdfctx_t *pdfctx;
894
0
    pdf_dict *InfoDict = NULL;
895
0
    pdfi_switch_t i_switch;
896
897
0
    check_op(2);
898
899
0
    check_type(*op, t_integer);
900
0
    page = op->value.intval;
901
902
0
    check_type(*(op - 1), t_pdfctx);
903
0
    pdfctx = r_ptr(op - 1, pdfctx_t);
904
905
0
    if (pdfctx->pdf_stream != NULL || pdfctx->UsingPDFFile) {
906
0
        code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
907
908
0
        if (code >= 0) {
909
0
            code = pdfi_page_info(pdfctx->ctx, (uint64_t)page, &InfoDict, true);
910
911
0
            pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
912
0
        }
913
914
0
        if (code < 0)
915
0
            return code;
916
917
0
        pop(1);
918
0
        op = osp;
919
920
0
        code = PDFobj_to_PSobj(i_ctx_p, pdfctx, (pdf_obj *)InfoDict, op);
921
0
        pdfi_countdown(InfoDict);
922
0
        if (code < 0)
923
0
            return code;
924
0
    }
925
0
    else {
926
0
        return_error(gs_error_ioerror);
927
0
    }
928
0
    return 0;
929
0
}
930
931
static int zPDFmetadata(i_ctx_t *i_ctx_p)
932
0
{
933
#if 0
934
    os_ptr op = osp;
935
    pdfctx_t *pdfctx;
936
937
    check_type(*op, t_pdfctx);
938
    pdfctx = r_ptr(op, pdfctx_t);
939
#endif
940
941
0
    return_error(gs_error_undefined);
942
0
}
943
944
static int zPDFdrawpage(i_ctx_t *i_ctx_p)
945
133k
{
946
133k
    os_ptr op = osp;
947
133k
    int code = 0;
948
133k
    uint64_t page = 0;
949
133k
    pdfctx_t *pdfctx;
950
133k
    pdfi_switch_t i_switch;
951
952
133k
    check_op(2);
953
954
133k
    check_type(*op, t_integer);
955
133k
    page = op->value.intval;
956
957
133k
    check_type(*(op - 1), t_pdfctx);
958
133k
    pdfctx = r_ptr(op - 1, pdfctx_t);
959
960
133k
    if (pdfctx->pdf_stream != NULL || pdfctx->UsingPDFFile) {
961
133k
        code = gs_gsave(igs);
962
133k
        if (code < 0)
963
0
            return code;
964
965
133k
        code = pdfi_gstate_from_PS(pdfctx->ctx, igs, &i_switch, pdfctx->profile_cache);
966
967
133k
        if (code >= 0) {
968
133k
            if (pdfctx->ctx->args.pdfinfo)
969
0
                code = pdfi_output_page_info(pdfctx->ctx, page);
970
133k
            else
971
133k
                code = pdfi_page_render(pdfctx->ctx, page, false);
972
133k
            if (code >= 0)
973
119k
                pop(2);
974
975
133k
            pdfi_gstate_to_PS(pdfctx->ctx, igs, &i_switch);
976
133k
        }
977
133k
        if (code == 0)
978
119k
            code = gs_grestore(igs);
979
14.8k
        else
980
14.8k
            (void)gs_grestore(igs);
981
133k
    }
982
0
    else {
983
0
        return_error(gs_error_ioerror);
984
0
    }
985
133k
    return code;
986
133k
}
987
988
static int zPDFdrawannots(i_ctx_t *i_ctx_p)
989
0
{
990
#if 0
991
    os_ptr op = osp;
992
    pdfctx_t *pdfctx;
993
994
    check_type(*op, t_pdfctx);
995
    pdfctx = r_ptr(op, pdfctx_t);
996
#endif
997
998
0
    return_error(gs_error_undefined);
999
0
}
1000
1001
static int zpdfi_glyph_index(gs_font *pfont, byte *str, uint size, uint *glyph)
1002
268M
{
1003
268M
    int code = 0;
1004
268M
    ref nref;
1005
268M
    i_ctx_t *i_ctx_p = get_minst_from_memory(pfont->memory)->i_ctx_p;
1006
268M
    os_ptr op = osp;
1007
268M
    pdfctx_t *pdfctx;
1008
1009
268M
    check_type(*op - 1, t_pdfctx);
1010
268M
    pdfctx = r_ptr(op - 1, pdfctx_t);
1011
1012
268M
    code = name_ref(pfont->memory, str, size, &nref, true);
1013
268M
    if (code < 0)
1014
8
        return code;
1015
1016
268M
    code = dict_put(&pdfctx->names_dict, &nref, &nref, &i_ctx_p->dict_stack);
1017
268M
    if (code < 0)
1018
0
        return code;
1019
1020
268M
    *glyph = name_index(pfont->memory, &nref);
1021
268M
    return 0;
1022
268M
}
1023
1024
static int param_value_get_namelist(gs_memory_t *ps_mem, pdf_context *ctx, ref *pvalueref, char ***pstrlist)
1025
0
{
1026
0
    uint count;
1027
0
    char **strlist = NULL;
1028
0
    ref lval, sref;
1029
0
    int code;
1030
1031
0
    check_read_type(*pvalueref, t_array);
1032
1033
0
    strlist = (char **)gs_alloc_bytes(ctx->memory, (size_t)(r_size(pvalueref)+1)*sizeof(char *), "param_value_get_namelist");
1034
0
    if (strlist == NULL)
1035
0
        return_error(gs_error_VMerror);
1036
0
    memset(strlist, 0x00, (r_size(pvalueref)+1)*sizeof(char *));
1037
1038
0
    for (count = 0;count < r_size(pvalueref); count++) {
1039
0
        code = array_get(ps_mem, pvalueref, count, &lval);
1040
0
        if (code < 0)
1041
0
            return code;
1042
1043
0
        if (!r_has_type(&lval, t_string) && !r_has_type(&lval, t_name))
1044
0
            return_error(gs_error_typecheck);
1045
1046
0
        if (r_has_type(&lval, t_name))
1047
0
            name_string_ref(ps_mem, (const ref *)&lval, &sref);
1048
0
        else
1049
0
            sref = lval;
1050
1051
0
        strlist[count] = (char *)gs_alloc_bytes(ctx->memory, (size_t)sref.tas.rsize + 1, "param_value_get_namelist");
1052
0
        if (strlist[count] == NULL)
1053
0
            return_error(gs_error_VMerror);
1054
0
        memset(strlist[count], 0x00, sref.tas.rsize + 1);
1055
0
        memcpy(strlist[count], sref.value.bytes, sref.tas.rsize);
1056
0
    }
1057
0
    *pstrlist = strlist;
1058
0
    return 0;
1059
0
}
1060
1061
static int apply_interpreter_params(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, ref *pdictref)
1062
110k
{
1063
110k
    int code = gs_error_typecheck;
1064
110k
    ref *pvalueref;
1065
1066
110k
    if (dict_find_string(pdictref, "PDFCACHE", &pvalueref) > 0) {
1067
0
        if (!r_has_type(pvalueref, t_integer))
1068
0
            goto error;
1069
0
        pdfctx->ctx->args.PDFCacheSize = pvalueref->value.intval;
1070
0
    }
1071
1072
110k
    if (dict_find_string(pdictref, "PDFDEBUG", &pvalueref) > 0) {
1073
110k
        if (!r_has_type(pvalueref, t_boolean))
1074
0
            goto error;
1075
110k
        pdfctx->ctx->args.pdfdebug = pvalueref->value.boolval;
1076
110k
    }
1077
1078
110k
    if (dict_find_string(pdictref, "PDFSTOPONERROR", &pvalueref) > 0) {
1079
110k
        if (!r_has_type(pvalueref, t_boolean))
1080
0
            goto error;
1081
110k
        pdfctx->ctx->args.pdfstoponerror = pvalueref->value.boolval;
1082
110k
    }
1083
1084
110k
    if (dict_find_string(pdictref, "PDFSTOPONWARNING", &pvalueref) > 0) {
1085
110k
        if (!r_has_type(pvalueref, t_boolean))
1086
0
            goto error;
1087
110k
        pdfctx->ctx->args.pdfstoponwarning = pvalueref->value.boolval;
1088
110k
        if (pvalueref->value.boolval)
1089
0
            pdfctx->ctx->args.pdfstoponerror = pvalueref->value.boolval;
1090
110k
    }
1091
1092
110k
    if (dict_find_string(pdictref, "NOTRANSPARENCY", &pvalueref) > 0) {
1093
110k
        if (!r_has_type(pvalueref, t_boolean))
1094
0
            goto error;
1095
110k
        pdfctx->ctx->args.notransparency = pvalueref->value.boolval;
1096
110k
    }
1097
1098
110k
    if (dict_find_string(pdictref, "QUIET", &pvalueref) > 0) {
1099
110k
        if (!r_has_type(pvalueref, t_boolean))
1100
0
            goto error;
1101
110k
        pdfctx->ctx->args.QUIET = pvalueref->value.boolval;
1102
110k
    }
1103
1104
110k
    if (dict_find_string(pdictref, "VerboseErrors", &pvalueref) > 0) {
1105
0
        if (!r_has_type(pvalueref, t_boolean))
1106
0
            goto error;
1107
0
        pdfctx->ctx->args.verbose_errors = pvalueref->value.boolval;
1108
0
    }
1109
1110
110k
    if (dict_find_string(pdictref, "VerboseWarnings", &pvalueref) > 0) {
1111
0
        if (!r_has_type(pvalueref, t_boolean))
1112
0
            goto error;
1113
0
        pdfctx->ctx->args.verbose_warnings = pvalueref->value.boolval;
1114
0
    }
1115
1116
110k
    if (dict_find_string(pdictref, "PDFPassword", &pvalueref) > 0) {
1117
0
        if (!r_has_type(pvalueref, t_string))
1118
0
            goto error;
1119
0
        pdfctx->ctx->encryption.Password = (char *)gs_alloc_bytes(pdfctx->ctx->memory, (size_t)r_size(pvalueref) + 1, "PDF Password from zpdfops");
1120
0
        if (pdfctx->ctx->encryption.Password == NULL) {
1121
0
            code = gs_note_error(gs_error_VMerror);
1122
0
            goto error;
1123
0
        }
1124
0
        memset(pdfctx->ctx->encryption.Password, 0x00, r_size(pvalueref) + 1);
1125
0
        memcpy(pdfctx->ctx->encryption.Password, pvalueref->value.const_bytes, r_size(pvalueref));
1126
0
        pdfctx->ctx->encryption.PasswordLen = r_size(pvalueref);
1127
0
    }
1128
1129
110k
    if (dict_find_string(pdictref, "FirstPage", &pvalueref) > 0) {
1130
0
        if (!r_has_type(pvalueref, t_integer))
1131
0
            goto error;
1132
0
        pdfctx->ctx->args.first_page = pvalueref->value.intval;
1133
0
    }
1134
1135
110k
    if (dict_find_string(pdictref, "LastPage", &pvalueref) > 0) {
1136
0
        if (!r_has_type(pvalueref, t_integer))
1137
0
            goto error;
1138
0
        pdfctx->ctx->args.last_page = pvalueref->value.intval;
1139
0
    }
1140
1141
110k
    if (dict_find_string(pdictref, "PDFNOCIDFALLBACK", &pvalueref) > 0) {
1142
110k
        if (!r_has_type(pvalueref, t_boolean))
1143
0
            goto error;
1144
110k
        pdfctx->ctx->args.nocidfallback = pvalueref->value.boolval;
1145
110k
    }
1146
1147
110k
    if (dict_find_string(pdictref, "NO_PDFMARK_OUTLINES", &pvalueref) > 0) {
1148
0
        if (!r_has_type(pvalueref, t_boolean))
1149
0
            goto error;
1150
0
        pdfctx->ctx->args.no_pdfmark_outlines = pvalueref->value.boolval;
1151
0
    }
1152
1153
110k
    if (dict_find_string(pdictref, "PDFA", &pvalueref) > 0) {
1154
0
        if (!r_has_type(pvalueref, t_integer))
1155
0
            goto error;
1156
0
        pdfctx->ctx->args.PDFA = pvalueref->value.intval;
1157
0
    }
1158
1159
110k
    if (dict_find_string(pdictref, "PDFX", &pvalueref) > 0) {
1160
0
        if (!r_has_type(pvalueref, t_integer))
1161
0
            goto error;
1162
0
        pdfctx->ctx->args.PDFX = pvalueref->value.intval;
1163
0
    }
1164
1165
110k
    if (dict_find_string(pdictref, "PDFACompatibilityPolicy", &pvalueref) > 0) {
1166
0
        if (!r_has_type(pvalueref, t_integer))
1167
0
            goto error;
1168
0
        pdfctx->ctx->args.PDFA = pvalueref->value.intval;
1169
0
    }
1170
1171
    /* This one can be a boolean OR an integer */
1172
110k
    if (dict_find_string(pdictref, "UsePDFX3Profile", &pvalueref) > 0) {
1173
0
        if (!r_has_type(pvalueref, t_boolean)) {
1174
0
            if (!r_has_type(pvalueref, t_integer))
1175
0
                goto error;
1176
0
            else {
1177
0
                pdfctx->ctx->args.UsePDFX3Profile = true;
1178
0
                pdfctx->ctx->args.PDFX3Profile_num = pvalueref->value.intval;
1179
0
            }
1180
0
        } else {
1181
0
            pdfctx->ctx->args.UsePDFX3Profile = pvalueref->value.boolval;
1182
0
            pdfctx->ctx->args.PDFX3Profile_num = 0;
1183
0
        }
1184
0
    }
1185
1186
110k
    if (dict_find_string(pdictref, "NO_PDFMARK_DESTS", &pvalueref) > 0) {
1187
0
        if (!r_has_type(pvalueref, t_boolean))
1188
0
            goto error;
1189
0
        pdfctx->ctx->args.no_pdfmark_dests = pvalueref->value.boolval;
1190
0
    }
1191
1192
110k
    if (dict_find_string(pdictref, "PDFFitPage", &pvalueref) > 0) {
1193
0
        if (!r_has_type(pvalueref, t_boolean))
1194
0
            goto error;
1195
0
        pdfctx->ctx->args.pdffitpage = pvalueref->value.boolval;
1196
0
    }
1197
1198
110k
    if (dict_find_string(pdictref, "OutputFile", &pvalueref) > 0)
1199
110k
        pdfctx->ctx->args.printed = true;
1200
0
    else
1201
0
        pdfctx->ctx->args.printed = false;
1202
1203
110k
    if (dict_find_string(pdictref, "Printed", &pvalueref) > 0) {
1204
0
        if (!r_has_type(pvalueref, t_boolean))
1205
0
            goto error;
1206
0
        pdfctx->ctx->args.printed = pvalueref->value.boolval;
1207
0
    }
1208
1209
110k
    if (dict_find_string(pdictref, "UseBleedBox", &pvalueref) > 0) {
1210
0
        if (!r_has_type(pvalueref, t_boolean))
1211
0
            goto error;
1212
0
        pdfctx->ctx->args.usebleedbox = pvalueref->value.boolval;
1213
0
    }
1214
1215
110k
    if (dict_find_string(pdictref, "UseCropBox", &pvalueref) > 0) {
1216
0
        if (!r_has_type(pvalueref, t_boolean))
1217
0
            goto error;
1218
0
        pdfctx->ctx->args.usecropbox = pvalueref->value.boolval;
1219
0
    }
1220
1221
110k
    if (dict_find_string(pdictref, "UseArtBox", &pvalueref) > 0) {
1222
0
        if (!r_has_type(pvalueref, t_boolean))
1223
0
            goto error;
1224
0
        pdfctx->ctx->args.useartbox = pvalueref->value.boolval;
1225
0
    }
1226
1227
110k
    if (dict_find_string(pdictref, "UseTrimBox", &pvalueref) > 0) {
1228
0
        if (!r_has_type(pvalueref, t_boolean))
1229
0
            goto error;
1230
0
        pdfctx->ctx->args.usetrimbox = pvalueref->value.boolval;
1231
0
    }
1232
1233
110k
    if (dict_find_string(pdictref, "ShowAcroForm", &pvalueref) > 0) {
1234
0
        if (!r_has_type(pvalueref, t_boolean))
1235
0
            goto error;
1236
0
        pdfctx->ctx->args.showacroform = pvalueref->value.boolval;
1237
0
    }
1238
1239
110k
    if (dict_find_string(pdictref, "ShowAnnots", &pvalueref) > 0) {
1240
0
        if (!r_has_type(pvalueref, t_boolean))
1241
0
            goto error;
1242
0
        pdfctx->ctx->args.showannots = pvalueref->value.boolval;
1243
0
    }
1244
1245
110k
    if (dict_find_string(pdictref, "PreserveAnnots", &pvalueref) > 0) {
1246
0
        if (!r_has_type(pvalueref, t_boolean))
1247
0
            goto error;
1248
0
        pdfctx->ctx->args.preserveannots = pvalueref->value.boolval;
1249
0
    }
1250
1251
110k
    if (dict_find_string(pdictref, "PreserveMarkedContent", &pvalueref) > 0) {
1252
0
        if (!r_has_type(pvalueref, t_boolean))
1253
0
            goto error;
1254
0
        pdfctx->ctx->args.preservemarkedcontent = pvalueref->value.boolval;
1255
0
    }
1256
1257
110k
    if (dict_find_string(pdictref, "PreserveEmbeddedFiles", &pvalueref) > 0) {
1258
0
        if (!r_has_type(pvalueref, t_boolean))
1259
0
            goto error;
1260
0
        pdfctx->ctx->args.preserveembeddedfiles = pvalueref->value.boolval;
1261
0
    }
1262
1263
110k
    if (dict_find_string(pdictref, "PreserveDocView", &pvalueref) > 0) {
1264
0
        if (!r_has_type(pvalueref, t_boolean))
1265
0
            goto error;
1266
0
        pdfctx->ctx->args.preservedocview = pvalueref->value.boolval;
1267
0
    }
1268
1269
110k
    if (dict_find_string(pdictref, "NoUserUnit", &pvalueref) > 0) {
1270
0
        if (!r_has_type(pvalueref, t_boolean))
1271
0
            goto error;
1272
0
        pdfctx->ctx->args.nouserunit = pvalueref->value.boolval;
1273
0
    }
1274
1275
110k
    if (dict_find_string(pdictref, "RENDERTTNOTDEF", &pvalueref) > 0) {
1276
110k
        if (!r_has_type(pvalueref, t_boolean))
1277
0
            goto error;
1278
110k
        pdfctx->ctx->args.renderttnotdef = pvalueref->value.boolval;
1279
110k
    }
1280
1281
110k
    if (dict_find_string(pdictref, "DOPDFMARKS", &pvalueref) > 0) {
1282
0
        if (!r_has_type(pvalueref, t_boolean))
1283
0
            goto error;
1284
0
        pdfctx->ctx->args.dopdfmarks = pvalueref->value.boolval;
1285
0
    }
1286
1287
110k
    if (dict_find_string(pdictref, "PDFINFO", &pvalueref) > 0) {
1288
0
        if (!r_has_type(pvalueref, t_boolean))
1289
0
            goto error;
1290
0
        pdfctx->ctx->args.pdfinfo = pvalueref->value.boolval;
1291
0
    }
1292
110k
    if (dict_find_string(pdictref, "ShowAnnotTypes", &pvalueref) > 0) {
1293
0
        code = param_value_get_namelist(imemory, pdfctx->ctx, pvalueref,
1294
0
                                        &pdfctx->ctx->args.showannottypes);
1295
0
        if (code < 0)
1296
0
            goto error;
1297
0
    }
1298
110k
    if (dict_find_string(pdictref, "PreserveAnnotTypes", &pvalueref) > 0) {
1299
0
        code = param_value_get_namelist(imemory, pdfctx->ctx, pvalueref,
1300
0
                                        &pdfctx->ctx->args.preserveannottypes);
1301
0
        if (code < 0)
1302
0
            goto error;
1303
0
    }
1304
110k
    if (dict_find_string(pdictref, "CIDFSubstPath", &pvalueref) > 0) {
1305
0
        if (!r_has_type(pvalueref, t_string))
1306
0
            goto error;
1307
0
        pdfctx->ctx->args.cidfsubstpath.data = (byte *)gs_alloc_bytes(pdfctx->ctx->memory, (size_t)r_size(pvalueref) + 1, "PDF cidfsubstpath from zpdfops");
1308
0
        if (pdfctx->ctx->args.cidfsubstpath.data == NULL) {
1309
0
            code = gs_note_error(gs_error_VMerror);
1310
0
            goto error;
1311
0
        }
1312
0
        memcpy(pdfctx->ctx->args.cidfsubstpath.data, pvalueref->value.const_bytes, r_size(pvalueref));
1313
0
        pdfctx->ctx->args.cidfsubstpath.size = r_size(pvalueref);
1314
0
    }
1315
110k
    if (dict_find_string(pdictref, "CIDFSubstFont", &pvalueref) > 0) {
1316
0
        if (!r_has_type(pvalueref, t_string))
1317
0
            goto error;
1318
0
        pdfctx->ctx->args.cidfsubstfont.data = (byte *)gs_alloc_bytes(pdfctx->ctx->memory, (size_t)r_size(pvalueref) + 1, "PDF cidfsubstfont from zpdfops");
1319
0
        if (pdfctx->ctx->args.cidfsubstfont.data == NULL) {
1320
0
            code = gs_note_error(gs_error_VMerror);
1321
0
            goto error;
1322
0
        }
1323
0
        memcpy(pdfctx->ctx->args.cidfsubstfont.data, pvalueref->value.const_bytes, r_size(pvalueref));
1324
0
        pdfctx->ctx->args.cidfsubstfont.size = r_size(pvalueref);
1325
0
    }
1326
110k
    if (dict_find_string(pdictref, "SUBSTFONT", &pvalueref) > 0) {
1327
0
        ref nmstr, *namstrp;
1328
0
        if (r_has_type(pvalueref, t_string)) {
1329
0
            namstrp = pvalueref;
1330
0
            pdfctx->ctx->args.defaultfont_is_name = false;
1331
0
        } else if (r_has_type(pvalueref, t_name)) {
1332
0
            name_string_ref(imemory, pvalueref, &nmstr);
1333
0
            namstrp = &nmstr;
1334
0
            pdfctx->ctx->args.defaultfont_is_name = true;
1335
0
        }
1336
0
        else {
1337
0
            code = gs_note_error(gs_error_typecheck);
1338
0
            goto error;
1339
0
        }
1340
0
        pdfctx->ctx->args.defaultfont.data = (byte *)gs_alloc_bytes(pdfctx->ctx->memory, (size_t)r_size(namstrp) + 1, "PDF defaultfontname from zpdfops");
1341
0
        if (pdfctx->ctx->args.defaultfont.data == NULL) {
1342
0
            code = gs_note_error(gs_error_VMerror);
1343
0
            goto error;
1344
0
        }
1345
0
        memcpy(pdfctx->ctx->args.defaultfont.data, pvalueref->value.const_bytes, r_size(namstrp));
1346
0
        pdfctx->ctx->args.defaultfont.size = r_size(namstrp);
1347
0
    }
1348
110k
    if (dict_find_string(pdictref, "IgnoreToUnicode", &pvalueref) > 0) {
1349
0
        if (!r_has_type(pvalueref, t_boolean))
1350
0
            goto error;
1351
0
        pdfctx->ctx->args.ignoretounicode = pvalueref->value.boolval;
1352
0
    }
1353
110k
    if (dict_find_string(pdictref, "NONATIVEFONTMAP", &pvalueref) > 0) {
1354
0
        if (!r_has_type(pvalueref, t_boolean))
1355
0
            goto error;
1356
0
        pdfctx->ctx->args.nonativefontmap = pvalueref->value.boolval;
1357
0
    }
1358
110k
    if (dict_find_string(pdictref, "PageCount", &pvalueref) > 0) {
1359
110k
        if (!r_has_type(pvalueref, t_integer))
1360
0
            goto error;
1361
110k
        pdfctx->ctx->Pdfmark_InitialPage = pvalueref->value.intval;
1362
110k
    }
1363
110k
    code = 0;
1364
1365
110k
error:
1366
110k
    return code;
1367
110k
}
1368
1369
static int zPDFSetParams(i_ctx_t *i_ctx_p)
1370
0
{
1371
0
    os_ptr op = osp;
1372
0
    int code = 0;
1373
0
    pdfctx_t *pdfctx = NULL;
1374
1375
0
    check_op(2);
1376
1377
0
    check_type(*(op - 1), t_pdfctx);
1378
0
    pdfctx = r_ptr(op - 1, pdfctx_t);
1379
1380
0
    check_type(*op, t_dictionary);
1381
1382
0
    code = apply_interpreter_params(i_ctx_p, pdfctx, op);
1383
1384
0
    pop(2);
1385
0
    return code;
1386
0
}
1387
1388
static int zPDFInit(i_ctx_t *i_ctx_p)
1389
110k
{
1390
110k
    os_ptr op = osp;
1391
110k
    pdfctx_t *pdfctx = NULL;
1392
110k
    pdf_context *ctx = NULL;
1393
110k
    int code = 0;
1394
110k
    gs_memory_t *cmem;
1395
1396
110k
    code = gs_memory_chunk_wrap(&cmem, imemory->non_gc_memory);
1397
110k
    if (code < 0)
1398
0
        return_error(gs_error_VMerror);
1399
1400
110k
    pdfctx = gs_alloc_struct(imemory, pdfctx_t, &st_pdfctx_t, "PDFcontext");
1401
110k
    if (!pdfctx) {
1402
0
        code = gs_note_error(gs_error_VMerror);
1403
0
        goto error;
1404
0
    }
1405
110k
    pdfctx->pdf_memory = cmem;
1406
110k
    pdfctx->ctx = NULL;
1407
110k
    pdfctx->ps_stream = NULL;
1408
110k
    pdfctx->pdf_stream = NULL;
1409
110k
    pdfctx->UsingPDFFile = false;
1410
110k
    pdfctx->pdf_stream_memory = NULL;
1411
110k
    pdfctx->profile_cache = gsicc_profilecache_new(imemory);
1412
110k
    if (pdfctx->profile_cache == NULL) {
1413
0
        code = gs_note_error(gs_error_VMerror);
1414
0
        goto error;
1415
0
    }
1416
110k
    pdfctx->cache_memory = imemory;
1417
    /* The size is arbitrary */
1418
110k
    code = dict_alloc(iimemory, 1, &pdfctx->names_dict);
1419
110k
    if (code < 0)
1420
0
        goto error;
1421
1422
110k
    ctx = pdfi_create_context(cmem);
1423
110k
    if (ctx == NULL) {
1424
0
        code = gs_note_error(gs_error_VMerror);
1425
0
        goto error;
1426
0
    }
1427
1428
110k
    pdfctx->ctx = ctx;
1429
110k
    get_zfont_glyph_name(&pdfctx->ctx->get_glyph_name);
1430
110k
    pdfctx->ctx->get_glyph_index = zpdfi_glyph_index;
1431
1432
110k
    if (ref_stack_count(&o_stack) > 0) {
1433
110k
        if (r_has_type(op, t_dictionary))
1434
110k
            code = apply_interpreter_params(i_ctx_p, pdfctx, op);
1435
110k
        pop(1);
1436
110k
        if (code < 0)
1437
0
            goto error;
1438
110k
    }
1439
110k
    code = zpdfi_populate_search_paths(i_ctx_p, ctx);
1440
110k
    if (code < 0)
1441
0
        goto error;
1442
1443
110k
    code = zpdfi_populate_fontmap_files(i_ctx_p, ctx);
1444
110k
    if (code < 0)
1445
0
        goto error;
1446
1447
110k
    op = osp;
1448
110k
    push(1);
1449
110k
    make_tav(op, t_pdfctx, icurrent_space | a_all, pstruct, (obj_header_t *)(pdfctx));
1450
110k
    return 0;
1451
1452
0
error:
1453
0
    if (ctx != NULL)
1454
0
        pdfi_free_context(ctx);
1455
    /* gs_memory_chunk_unwrap() returns the "wrapped" allocator, which we don't need */
1456
0
    (void)gs_memory_chunk_unwrap(cmem);
1457
0
    if (pdfctx != NULL) {
1458
0
        pdfctx->ctx = NULL; /* Freed already above! */
1459
0
        if (pdfctx->profile_cache != NULL) {
1460
0
            gs_free_object(imemory, pdfctx->profile_cache, "discard temporary profile cache");
1461
0
            pdfctx->profile_cache = NULL;
1462
0
        }
1463
0
        pdfctx->pdf_memory = NULL;
1464
0
        gs_free_object(imemory, pdfctx, "PDFcontext");
1465
0
    }
1466
0
    return code;
1467
110k
}
1468
1469
/*   <Pagelist_string> num_pages .PDFparsePageList even/odd, start, end ... range_count */
1470
/*   PostScript will create an array of 3 integers per range      */
1471
static int zPDFparsePageList(i_ctx_t *i_ctx_p)
1472
7
{
1473
7
    int code = 0, size = 0, i;
1474
7
    os_ptr op = osp;
1475
7
    int *page_range_array;
1476
7
    int num_pages;
1477
7
    ref *o;
1478
7
    char *PageString = NULL;
1479
1480
7
    check_op(2);
1481
1482
0
    code = int_param(op, max_int, &num_pages);
1483
0
    if (code < 0)
1484
0
        return code;
1485
1486
0
    check_type_only(*(op - 1), t_string);
1487
1488
0
    PageString = (char *)gs_alloc_bytes(imemory, (size_t)r_size(op - 1) + 1, "zPDFparsePageList");
1489
0
    if (PageString == NULL)
1490
0
        return_error(gs_error_VMerror);
1491
0
    memcpy(PageString, (op - 1)->value.const_bytes, r_size(op - 1));
1492
0
    PageString[r_size(op - 1)] = 0x00;
1493
0
    code = pagelist_parse_to_array(PageString, imemory, num_pages, &page_range_array);
1494
0
    gs_free_object(imemory, PageString, "zPDFparsePageList");
1495
1496
0
    make_int(op, 0);        /* default return 0 */
1497
0
    if (code < 0) {
1498
0
        return code;
1499
0
    }
1500
    /* code returned is the number of ranges */
1501
0
    size = 3 * (code - 1);    /* runpdfpagerange doesn't use 0, 0, 0 marker at end */
1502
0
    code = ref_stack_push(&o_stack, size - 1);
1503
0
    if (code < 0) {
1504
0
        return code;
1505
0
    }
1506
    /* push the even/odd, start, end triples on the stack */
1507
0
    for (i=0; i < size;  i++) {
1508
0
        o = ref_stack_index(&o_stack, size - i);
1509
0
        if (o == NULL)
1510
0
            return_error(gs_error_stackunderflow);
1511
        /* skip the initial "ordered" flag */
1512
0
        make_int(o, page_range_array[i+1]);
1513
0
    }
1514
0
    o = ref_stack_index(&o_stack, 0);
1515
0
    if (o == NULL)
1516
0
        return_error(gs_error_stackunderflow);
1517
0
    make_int(o, size);
1518
0
    pagelist_free_range_array(imemory, page_range_array);    /* all done with C array */
1519
0
    return 0;
1520
0
}
1521
#else
1522
1523
static int zPDFfile(i_ctx_t *i_ctx_p)
1524
{
1525
    return_error(gs_error_undefined);
1526
}
1527
1528
static int zPDFstream(i_ctx_t *i_ctx_p)
1529
{
1530
    return_error(gs_error_undefined);
1531
}
1532
1533
static int zPDFclose(i_ctx_t *i_ctx_p)
1534
{
1535
    return_error(gs_error_undefined);
1536
}
1537
1538
static int zPDFinfo(i_ctx_t *i_ctx_p)
1539
{
1540
    return_error(gs_error_undefined);
1541
}
1542
1543
static int zPDFpageinfo(i_ctx_t *i_ctx_p)
1544
{
1545
    return_error(gs_error_undefined);
1546
}
1547
1548
static int zPDFpageinfoExt(i_ctx_t *i_ctx_p)
1549
{
1550
    return_error(gs_error_undefined);
1551
}
1552
1553
static int zPDFmetadata(i_ctx_t *i_ctx_p)
1554
{
1555
    return_error(gs_error_undefined);
1556
}
1557
1558
static int zPDFdrawpage(i_ctx_t *i_ctx_p)
1559
{
1560
    return_error(gs_error_undefined);
1561
}
1562
1563
static int zPDFdrawannots(i_ctx_t *i_ctx_p)
1564
{
1565
    return_error(gs_error_undefined);
1566
}
1567
1568
static int zPDFSetParams(i_ctx_t *i_ctx_p)
1569
{
1570
    return_error(gs_error_undefined);
1571
}
1572
1573
static int zPDFInit(i_ctx_t *i_ctx_p)
1574
{
1575
    return_error(gs_error_undefined);
1576
}
1577
1578
static int zPDFparsePageList(i_ctx_t *i_ctx_p)
1579
{
1580
    return_error(gs_error_undefined);
1581
}
1582
#endif
1583
1584
static int zPDFAvailable(i_ctx_t *i_ctx_p)
1585
110k
{
1586
110k
    os_ptr op = osp;
1587
1588
110k
    push(1);
1589
110k
#if defined(BUILD_PDF) && BUILD_PDF == 1
1590
110k
    make_bool(op, true);
1591
#else
1592
    make_bool(op, false);
1593
#endif
1594
110k
    return 0;
1595
110k
}
1596
1597
/* ------ Initialization procedure ------ */
1598
1599
const op_def zpdfops_op_defs[] =
1600
{
1601
    {"0.PDFFile", zPDFfile},
1602
    {"1.PDFStream", zPDFstream},
1603
    {"1.PDFClose", zPDFclose},
1604
    {"1.PDFInfo", zPDFinfo},
1605
    {"1.PDFPageInfo", zPDFpageinfo},
1606
    {"1.PDFPageInfoExt", zPDFpageinfoExt},
1607
    {"1.PDFMetadata", zPDFmetadata},
1608
    {"1.PDFDrawPage", zPDFdrawpage},
1609
    {"1.PDFDrawAnnots", zPDFdrawannots},
1610
    {"1.PDFInit", zPDFInit},
1611
    {"1.PDFparsePageList", zPDFparsePageList},
1612
    {"0.PDFAvailable", zPDFAvailable},
1613
    {"2.PDFSetParams", zPDFSetParams},
1614
    op_def_end(0)
1615
};