Coverage Report

Created: 2025-11-16 07:40

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