Coverage Report

Created: 2025-06-24 07:01

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