Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/pdf/pdf_page.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2019-2022 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
/* Page-level operations for the PDF interpreter */
17
18
#include "pdf_int.h"
19
#include "pdf_stack.h"
20
#include "pdf_doc.h"
21
#include "pdf_deref.h"
22
#include "pdf_page.h"
23
#include "pdf_file.h"
24
#include "pdf_dict.h"
25
#include "pdf_array.h"
26
#include "pdf_loop_detect.h"
27
#include "pdf_colour.h"
28
#include "pdf_trans.h"
29
#include "pdf_font_types.h"
30
#include "pdf_gstate.h"
31
#include "pdf_misc.h"
32
#include "pdf_optcontent.h"
33
#include "pdf_device.h"
34
#include "pdf_annot.h"
35
#include "pdf_check.h"
36
#include "pdf_mark.h"
37
38
#include "gscoord.h"        /* for gs_concat() and others */
39
#include "gspaint.h"        /* For gs_erasepage() */
40
#include "gsstate.h"        /* For gs_initgraphics() */
41
#include "gspath2.h"        /* For gs_rectclip() */
42
43
static int pdfi_process_page_contents(pdf_context *ctx, pdf_dict *page_dict)
44
43.3k
{
45
43.3k
    int i, code = 0;
46
43.3k
    pdf_obj *o, *o1;
47
48
#if PURGE_CACHE_PER_PAGE
49
    pdfi_purge_obj_cache(ctx);
50
#endif
51
52
43.3k
    code = pdfi_dict_get(ctx, page_dict, "Contents", &o);
53
43.3k
    if (code == gs_error_undefined)
54
        /* Don't throw an error if there are no contents, just render nothing.... */
55
1.44k
        return 0;
56
41.9k
    if (code < 0)
57
608
        return code;
58
59
41.3k
    if (pdfi_type_of(o) == PDF_INDIRECT) {
60
5
        if (((pdf_indirect_ref *)o)->ref_object_num == page_dict->object_num)
61
0
            return_error(gs_error_circular_reference);
62
63
5
        code = pdfi_dereference(ctx, ((pdf_indirect_ref *)o)->ref_object_num, ((pdf_indirect_ref *)o)->ref_generation_num, &o1);
64
5
        pdfi_countdown(o);
65
5
        if (code < 0) {
66
1
            if (code == gs_error_VMerror)
67
0
                return code;
68
1
            return 0;
69
1
        }
70
4
        o = o1;
71
4
    }
72
73
41.3k
    code = pdfi_gsave(ctx);
74
41.3k
    if (code < 0) {
75
0
        pdfi_countdown(o);
76
0
        return code;
77
0
    }
78
79
41.3k
    ctx->encryption.decrypt_strings = false;
80
41.3k
    if (pdfi_type_of(o) == PDF_ARRAY) {
81
2.87k
        pdf_array *a = (pdf_array *)o;
82
83
12.1k
        for (i=0;i < pdfi_array_size(a); i++) {
84
9.87k
            pdf_indirect_ref *r;
85
9.87k
            code = pdfi_array_get_no_deref(ctx, a, i, (pdf_obj **)&r);
86
9.87k
            if (code < 0)
87
0
                goto page_error;
88
9.87k
            if (pdfi_type_of (r) == PDF_STREAM) {
89
0
                code = pdfi_interpret_content_stream(ctx, NULL, (pdf_stream *)r, page_dict);
90
0
                pdfi_countdown(r);
91
0
                if (code < 0)
92
0
                    goto page_error;
93
9.87k
            } else {
94
9.87k
                if (pdfi_type_of(r) != PDF_INDIRECT) {
95
18
                        pdfi_countdown(r);
96
18
                        code = gs_note_error(gs_error_typecheck);
97
18
                        goto page_error;
98
9.85k
                } else {
99
9.85k
                    if (r->ref_object_num == page_dict->object_num) {
100
0
                        pdfi_countdown(r);
101
0
                        code = gs_note_error(gs_error_circular_reference);
102
0
                        goto page_error;
103
0
                    }
104
9.85k
                    code = pdfi_dereference(ctx, r->ref_object_num, r->ref_generation_num, &o1);
105
9.85k
                    pdfi_countdown(r);
106
9.85k
                    if (code < 0) {
107
530
                        if (code != gs_error_VMerror || ctx->args.pdfstoponerror == false)
108
530
                            code = 0;
109
530
                        goto page_error;
110
530
                    }
111
9.32k
                    if (pdfi_type_of(o1) != PDF_STREAM) {
112
40
                        pdfi_countdown(o1);
113
40
                        code = gs_note_error(gs_error_typecheck);
114
40
                        goto page_error;
115
40
                    }
116
9.28k
                    code = pdfi_interpret_content_stream(ctx, NULL, (pdf_stream *)o1, page_dict);
117
9.28k
                    pdfi_countdown(o1);
118
9.28k
                    if (code < 0) {
119
159
                        if (code == gs_error_VMerror || ctx->args.pdfstoponerror == true)
120
0
                            goto page_error;
121
159
                    }
122
9.28k
                }
123
9.87k
            }
124
9.87k
        }
125
38.4k
    } else {
126
38.4k
        if (pdfi_type_of(o) == PDF_STREAM) {
127
38.2k
            code = pdfi_interpret_content_stream(ctx, NULL, (pdf_stream *)o, page_dict);
128
38.2k
        } else {
129
257
            pdfi_countdown(o);
130
257
            ctx->encryption.decrypt_strings = true;
131
257
            return_error(gs_error_typecheck);
132
257
        }
133
38.4k
    }
134
41.0k
page_error:
135
41.0k
    ctx->encryption.decrypt_strings = true;
136
41.0k
    pdfi_clearstack(ctx);
137
41.0k
    pdfi_grestore(ctx);
138
41.0k
    pdfi_countdown(o);
139
41.0k
    return code;
140
41.3k
}
141
142
/* Render one page (including annotations) (see pdf_main.ps/showpagecontents) */
143
static int pdfi_process_one_page(pdf_context *ctx, pdf_dict *page_dict)
144
43.3k
{
145
43.3k
    stream_save local_entry_save;
146
43.3k
    int code, code1;
147
148
    /* Save the current stream state, for later cleanup, in a local variable */
149
43.3k
    local_save_stream_state(ctx, &local_entry_save);
150
43.3k
    initialise_stream_save(ctx);
151
152
43.3k
    code = pdfi_process_page_contents(ctx, page_dict);
153
154
    /* Put our state back the way it was before we ran the contents
155
     * and check if the stream had problems
156
     */
157
#if PROBE_STREAMS
158
    if (ctx->pgs->level > ctx->current_stream_save.gsave_level ||
159
        pdfi_count_stack(ctx) > ctx->current_stream_save.stack_count)
160
        code = ((pdf_context *)0)->first_page;
161
#endif
162
163
43.3k
    cleanup_context_interpretation(ctx, &local_entry_save);
164
43.3k
    local_restore_stream_state(ctx, &local_entry_save);
165
166
43.3k
    code1 = pdfi_do_annotations(ctx, page_dict);
167
43.3k
    if (code > 0) code = code1;
168
169
43.3k
    code1 = pdfi_do_acroform(ctx, page_dict);
170
43.3k
    if (code > 0) code = code1;
171
172
43.3k
    return code;
173
43.3k
}
174
175
/* See pdf_PDF2PS_matrix and .pdfshowpage_Install */
176
static void pdfi_set_ctm(pdf_context *ctx)
177
0
{
178
0
    gs_matrix mat;
179
180
    /* Adjust for page.UserUnits */
181
0
    mat.xx = ctx->page.UserUnit;
182
0
    mat.xy = 0;
183
0
    mat.yx = 0;
184
0
    mat.yy = ctx->page.UserUnit;
185
0
    mat.tx = 0;
186
0
    mat.ty = 0;
187
0
    gs_concat(ctx->pgs, &mat);
188
189
    /* We need to make sure the default matrix is properly set.
190
     * If we do gs_initgraphics() later (such as for annotations)
191
     * then it uses this default matrix if it is set.
192
     * Needed for page rotations to work correctly with Annotations.
193
     */
194
0
    gs_setdefaultmatrix(ctx->pgs, &ctm_only(ctx->pgs));
195
196
0
}
197
198
/* Get .MediaSize from the device to setup page.Size in context */
199
static int pdfi_get_media_size(pdf_context *ctx, pdf_dict *page_dict)
200
43.3k
{
201
43.3k
    pdf_array *a = NULL, *default_media = NULL;
202
43.3k
    double d[4];
203
43.3k
    int code = 0;
204
43.3k
    uint64_t i;
205
43.3k
    double userunit = 1.0;
206
207
43.3k
    code = pdfi_dict_get_type(ctx, page_dict, "MediaBox", PDF_ARRAY, (pdf_obj **)&default_media);
208
43.3k
    if (code < 0) {
209
212
        pdfi_set_warning(ctx, code, NULL, W_PDF_BAD_MEDIABOX, "pdfi_get_media_size", NULL);
210
212
        code = gs_erasepage(ctx->pgs);
211
212
        return 0;
212
212
    }
213
214
43.1k
    if (ctx->args.usecropbox) {
215
0
        if (a != NULL)
216
0
            pdfi_countdown(a);
217
0
        (void)pdfi_dict_get_type(ctx, page_dict, "CropBox", PDF_ARRAY, (pdf_obj **)&a);
218
0
    }
219
43.1k
    if (ctx->args.useartbox) {
220
0
        if (a != NULL)
221
0
            pdfi_countdown(a);
222
0
        (void)pdfi_dict_get_type(ctx, page_dict, "ArtBox", PDF_ARRAY, (pdf_obj **)&a);
223
0
    }
224
43.1k
    if (ctx->args.usebleedbox) {
225
0
        if (a != NULL)
226
0
            pdfi_countdown(a);
227
0
        (void)pdfi_dict_get_type(ctx, page_dict, "BleedBox", PDF_ARRAY, (pdf_obj **)&a);
228
0
    }
229
43.1k
    if (ctx->args.usetrimbox) {
230
0
        if (a != NULL)
231
0
            pdfi_countdown(a);
232
0
        (void)pdfi_dict_get_type(ctx, page_dict, "TrimBox", PDF_ARRAY, (pdf_obj **)&a);
233
0
    }
234
43.1k
    if (a == NULL) {
235
43.1k
        a = default_media;
236
43.1k
    }
237
238
43.1k
    if (!ctx->args.nouserunit) {
239
43.1k
        (void)pdfi_dict_knownget_number(ctx, page_dict, "UserUnit", &userunit);
240
43.1k
    }
241
43.1k
    ctx->page.UserUnit = userunit;
242
243
215k
    for (i=0;i<4;i++) {
244
172k
        code = pdfi_array_get_number(ctx, a, i, &d[i]);
245
172k
        d[i] *= userunit;
246
172k
    }
247
43.1k
    pdfi_countdown(a);
248
249
43.1k
    normalize_rectangle(d);
250
43.1k
    memcpy(ctx->page.Size, d, 4 * sizeof(double));
251
252
43.1k
    return code;
253
43.3k
}
254
255
static int pdfi_set_media_size(pdf_context *ctx, pdf_dict *page_dict)
256
0
{
257
0
    gs_c_param_list list;
258
0
    gs_param_float_array fa;
259
0
    pdf_array *a = NULL, *default_media = NULL;
260
0
    float fv[2];
261
0
    double d[4], d_crop[4];
262
0
    gs_rect bbox;
263
0
    int code, do_crop = false;
264
0
    uint64_t i;
265
0
    int64_t rotate = 0;
266
0
    double userunit = 1.0;
267
268
0
    code = pdfi_dict_get_type(ctx, page_dict, "MediaBox", PDF_ARRAY, (pdf_obj **)&default_media);
269
0
    if (code < 0) {
270
0
        pdfi_set_warning(ctx, code, NULL, W_PDF_BAD_MEDIABOX, "pdfi_get_media_size", NULL);
271
0
        code = gs_erasepage(ctx->pgs);
272
0
        return 0;
273
0
    }
274
275
0
    if (ctx->args.usecropbox) {
276
0
        if (a != NULL)
277
0
            pdfi_countdown(a);
278
0
        (void)pdfi_dict_get_type(ctx, page_dict, "CropBox", PDF_ARRAY, (pdf_obj **)&a);
279
0
    }
280
0
    if (ctx->args.useartbox) {
281
0
        if (a != NULL)
282
0
            pdfi_countdown(a);
283
0
        (void)pdfi_dict_get_type(ctx, page_dict, "ArtBox", PDF_ARRAY, (pdf_obj **)&a);
284
0
    }
285
0
    if (ctx->args.usebleedbox) {
286
0
        if (a != NULL)
287
0
            pdfi_countdown(a);
288
0
        (void)pdfi_dict_get_type(ctx, page_dict, "BleedBox", PDF_ARRAY, (pdf_obj **)&a);
289
0
    }
290
0
    if (ctx->args.usetrimbox) {
291
0
        if (a != NULL)
292
0
            pdfi_countdown(a);
293
0
        (void)pdfi_dict_get_type(ctx, page_dict, "TrimBox", PDF_ARRAY, (pdf_obj **)&a);
294
0
    }
295
0
    if (a == NULL) {
296
0
        code = pdfi_dict_get_type(ctx, page_dict, "CropBox", PDF_ARRAY, (pdf_obj **)&a);
297
0
        if (code >= 0 && pdfi_array_size(a) >= 4) {
298
0
            pdf_obj *box_obj = NULL;
299
300
0
            for (i=0;i<4;i++) {
301
0
                code = pdfi_array_get_no_store_R(ctx, a, i, &box_obj);
302
0
                if (code >= 0) {
303
0
                    code = pdfi_obj_to_real(ctx, box_obj, &d_crop[i]);
304
0
                    pdfi_countdown(box_obj);
305
0
                }
306
0
                if (code < 0)
307
0
                    break;
308
0
            }
309
0
            pdfi_countdown(a);
310
0
            if (code >= 0) {
311
0
                normalize_rectangle(d_crop);
312
0
                memcpy(ctx->page.Crop, d_crop, 4 * sizeof(double));
313
0
                do_crop = true;
314
0
            }
315
0
        }
316
0
        a = default_media;
317
0
    }
318
319
0
    if (!ctx->args.nouserunit) {
320
0
        (void)pdfi_dict_knownget_number(ctx, page_dict, "UserUnit", &userunit);
321
0
    }
322
0
    ctx->page.UserUnit = userunit;
323
324
0
    for (i=0;i<4;i++) {
325
0
        pdf_obj *box_obj = NULL;
326
327
0
        code = pdfi_array_get_no_store_R(ctx, a, i, &box_obj);
328
0
        if (code >= 0) {
329
0
            code = pdfi_obj_to_real(ctx, box_obj, &d[i]);
330
0
            pdfi_countdown(box_obj);
331
0
        }
332
333
0
        if (code < 0) {
334
0
            pdfi_countdown(a);
335
0
            pdfi_set_warning(ctx, code, NULL, W_PDF_BAD_MEDIABOX, "pdfi_get_media_size", NULL);
336
0
            code = gs_erasepage(ctx->pgs);
337
0
            return 0;
338
0
        }
339
0
        d[i] *= userunit;
340
0
    }
341
0
    pdfi_countdown(a);
342
343
0
    normalize_rectangle(d);
344
0
    memcpy(ctx->page.Size, d, 4 * sizeof(double));
345
346
0
    code = pdfi_dict_get_int(ctx, page_dict, "Rotate", &rotate);
347
348
0
    rotate = rotate % 360;
349
350
0
    switch(rotate) {
351
0
        default:
352
0
        case 0:
353
0
        case 360:
354
0
        case -180:
355
0
        case 180:
356
0
            fv[0] = (float)(d[2] - d[0]);
357
0
            fv[1] = (float)(d[3] - d[1]);
358
0
            break;
359
0
        case -90:
360
0
        case 90:
361
0
        case -270:
362
0
        case 270:
363
0
            fv[1] = (float)(d[2] - d[0]);
364
0
            fv[0] = (float)(d[3] - d[1]);
365
0
            break;
366
0
    }
367
368
0
    fa.persistent = false;
369
0
    fa.data = fv;
370
0
    fa.size = 2;
371
372
    /* ----- setup specific device parameters ----- */
373
0
    gs_c_param_list_write(&list, ctx->memory);
374
375
0
    code = param_write_float_array((gs_param_list *)&list, ".MediaSize", &fa);
376
0
    if (code >= 0)
377
0
    {
378
0
        gx_device *dev = gs_currentdevice(ctx->pgs);
379
380
0
        gs_c_param_list_read(&list);
381
0
        code = gs_putdeviceparams(dev, (gs_param_list *)&list);
382
0
        if (code < 0) {
383
0
            gs_c_param_list_release(&list);
384
0
            return code;
385
0
        }
386
0
    }
387
0
    gs_c_param_list_release(&list);
388
    /* ----- end setup specific device parameters ----- */
389
390
    /* Resets the default matrix to NULL before doing initgraphics, because
391
     * otherwise initgraphics would keep old matrix.
392
     * (see pdfi_set_ctm())
393
     */
394
0
    gs_setdefaultmatrix(ctx->pgs, NULL);
395
0
    gs_initgraphics(ctx->pgs);
396
397
0
    switch(rotate) {
398
0
        case 0:
399
0
            break;
400
0
        case -270:
401
0
        case 90:
402
0
            gs_translate(ctx->pgs, 0, fv[1]);
403
0
            gs_rotate(ctx->pgs, -90);
404
0
            break;
405
0
        case -180:
406
0
        case 180:
407
0
            gs_translate(ctx->pgs, fv[0], fv[1]);
408
0
            gs_rotate(ctx->pgs, 180);
409
0
            break;
410
0
        case -90:
411
0
        case 270:
412
0
            gs_translate(ctx->pgs, fv[0], 0);
413
0
            gs_rotate(ctx->pgs, 90);
414
0
            break;
415
0
        default:
416
0
            break;
417
0
    }
418
419
0
    if (do_crop) {
420
0
        bbox.p.x = d_crop[0] - d[0];
421
0
        bbox.p.y = d_crop[1] - d[1];
422
0
        bbox.q.x = d_crop[2] - d[0];
423
0
        bbox.q.y = d_crop[3] - d[1];
424
425
0
        code = gs_rectclip(ctx->pgs, &bbox, 1);
426
0
        if (code < 0)
427
0
            return code;
428
0
    }
429
430
0
    gs_translate(ctx->pgs, d[0] * -1, d[1] * -1);
431
432
0
    code = gs_erasepage(ctx->pgs);
433
0
    return 0;
434
0
}
435
436
/* Setup default transfer functions */
437
static void pdfi_setup_transfers(pdf_context *ctx)
438
43.3k
{
439
43.3k
    if (ctx->pgs->set_transfer.red == 0x00) {
440
43.3k
        ctx->page.DefaultTransfers[0].proc = gs_identity_transfer;
441
43.3k
        memset(ctx->page.DefaultTransfers[0].values, 0x00, transfer_map_size * sizeof(frac));
442
43.3k
    } else {
443
0
        ctx->page.DefaultTransfers[0].proc = ctx->pgs->set_transfer.red->proc;
444
0
        memcpy(ctx->page.DefaultTransfers[0].values, ctx->pgs->set_transfer.red->values, transfer_map_size * sizeof(frac));
445
0
    }
446
43.3k
    if (ctx->pgs->set_transfer.green == 0x00) {
447
43.3k
        ctx->page.DefaultTransfers[1].proc = gs_identity_transfer;
448
43.3k
        memset(ctx->page.DefaultTransfers[1].values, 0x00, transfer_map_size * sizeof(frac));
449
43.3k
    } else {
450
0
        ctx->page.DefaultTransfers[1].proc = ctx->pgs->set_transfer.green->proc;
451
0
        memcpy(ctx->page.DefaultTransfers[1].values, ctx->pgs->set_transfer.green->values, transfer_map_size * sizeof(frac));
452
0
    }
453
43.3k
    if (ctx->pgs->set_transfer.blue == 0x00) {
454
43.3k
        ctx->page.DefaultTransfers[2].proc = gs_identity_transfer;
455
43.3k
        memset(ctx->page.DefaultTransfers[2].values, 0x00, transfer_map_size * sizeof(frac));
456
43.3k
    } else {
457
0
        ctx->page.DefaultTransfers[2].proc = ctx->pgs->set_transfer.blue->proc;
458
0
        memcpy(ctx->page.DefaultTransfers[2].values, ctx->pgs->set_transfer.blue->values, transfer_map_size * sizeof(frac));
459
0
    }
460
43.3k
    if (ctx->pgs->set_transfer.gray == 0x00) {
461
0
        ctx->page.DefaultTransfers[3].proc = gs_identity_transfer;
462
0
        memset(ctx->page.DefaultTransfers[3].values, 0x00, transfer_map_size * sizeof(frac));
463
43.3k
    } else {
464
43.3k
        ctx->page.DefaultTransfers[3].proc = ctx->pgs->set_transfer.gray->proc;
465
43.3k
        memcpy(ctx->page.DefaultTransfers[3].values, ctx->pgs->set_transfer.gray->values, transfer_map_size * sizeof(frac));
466
43.3k
    }
467
43.3k
    if (ctx->pgs->black_generation == 0x00) {
468
0
        ctx->page.DefaultBG.proc = gs_identity_transfer;
469
0
        memset(ctx->page.DefaultBG.values, 0x00, transfer_map_size * sizeof(frac));
470
43.3k
    } else {
471
43.3k
        ctx->page.DefaultBG.proc = ctx->pgs->black_generation->proc;
472
43.3k
        memcpy(ctx->page.DefaultBG.values, ctx->pgs->black_generation->values, transfer_map_size * sizeof(frac));
473
43.3k
    }
474
43.3k
    if (ctx->pgs->undercolor_removal == 0x00) {
475
0
        ctx->page.DefaultUCR.proc = gs_identity_transfer;
476
0
        memset(ctx->page.DefaultUCR.values, 0x00, transfer_map_size * sizeof(frac));
477
43.3k
    } else {
478
43.3k
        ctx->page.DefaultUCR.proc = ctx->pgs->undercolor_removal->proc;
479
43.3k
        memcpy(ctx->page.DefaultUCR.values, ctx->pgs->undercolor_removal->values, transfer_map_size * sizeof(frac));
480
43.3k
    }
481
43.3k
}
482
483
/* Return a dictionary containing information about the page. Basic information is that
484
 * required to render the page; if extended is true then additionally contains an
485
 * array of spot ink names and an array of dictionaries each of which contains
486
 * information about a font used on the page. THis is normally only used for tools
487
 * like pdf_info.ps
488
 */
489
int pdfi_page_info(pdf_context *ctx, uint64_t page_num, pdf_dict **info, bool extended)
490
54.0k
{
491
54.0k
    int code = 0, i=0;
492
54.0k
    pdf_dict *page_dict = NULL, *info_dict = NULL;
493
54.0k
    pdf_array *fonts_array = NULL, *spots_array = NULL;
494
54.0k
    pdf_array *a = NULL;
495
54.0k
    pdf_obj *o = NULL;
496
54.0k
    bool known = false;
497
54.0k
    double dummy;
498
499
54.0k
    code = pdfi_page_get_dict(ctx, page_num, &page_dict);
500
54.0k
    if (code < 0)
501
10.5k
        return code;
502
503
43.5k
    if (code > 0) {
504
0
        code = gs_note_error(gs_error_unknownerror);
505
0
        goto done;
506
0
    }
507
508
43.5k
    code = pdfi_dict_alloc(ctx, 6, &info_dict);
509
43.5k
    if (code < 0)
510
0
        goto done;
511
512
43.5k
    pdfi_countup(info_dict);
513
514
43.5k
    if (extended)
515
0
        code = pdfi_check_page(ctx, page_dict, &fonts_array, &spots_array, false);
516
43.5k
    else
517
43.5k
        code = pdfi_check_page(ctx, page_dict, NULL, NULL, false);
518
43.5k
    if (code < 0)
519
0
        goto done;
520
521
43.5k
    if (spots_array != NULL) {
522
0
        code = pdfi_dict_put(ctx, info_dict, "Spots", (pdf_obj *)spots_array);
523
0
        if (code < 0)
524
0
            goto done;
525
0
        pdfi_countdown(spots_array);
526
0
    }
527
528
43.5k
    if (fonts_array != NULL) {
529
0
        code = pdfi_dict_put(ctx, info_dict, "Fonts", (pdf_obj *)fonts_array);
530
0
        if (code < 0)
531
0
            goto done;
532
0
        pdfi_countdown(fonts_array);
533
0
    }
534
535
43.5k
    code = pdfi_dict_get_type(ctx, page_dict, "MediaBox", PDF_ARRAY, (pdf_obj **)&a);
536
43.5k
    if (code < 0)
537
212
        pdfi_set_warning(ctx, code, NULL, W_PDF_BAD_MEDIABOX, "pdfi_page_info", NULL);
538
539
43.5k
    if (code >= 0) {
540
43.3k
        pdf_obj *box_obj = NULL;
541
542
216k
        for (i = 0;i < pdfi_array_size(a); i++) {
543
173k
            code = pdfi_array_get_no_store_R(ctx, a, i, &box_obj);
544
173k
            if (code >= 0) {
545
173k
                code = pdfi_obj_to_real(ctx, box_obj, &dummy);
546
173k
                pdfi_countdown(box_obj);
547
173k
            }
548
173k
            if (code < 0) {
549
42
                pdfi_set_warning(ctx, code, NULL, W_PDF_BAD_MEDIABOX, "pdfi_page_info", NULL);
550
42
                goto done;
551
42
            }
552
173k
        }
553
554
43.2k
        code = pdfi_dict_put(ctx, info_dict, "MediaBox", (pdf_obj *)a);
555
43.2k
        if (code < 0)
556
0
            goto done;
557
43.2k
        pdfi_countdown(a);
558
43.2k
        a = NULL;
559
43.2k
    }
560
561
43.4k
    code = pdfi_dict_get_type(ctx, page_dict, "ArtBox", PDF_ARRAY, (pdf_obj **)&a);
562
43.4k
    if (code >= 0) {
563
3.85k
        pdf_obj *box_obj = NULL;
564
565
19.2k
        for (i = 0;i < pdfi_array_size(a); i++) {
566
15.4k
            code = pdfi_array_get_no_store_R(ctx, a, i, &box_obj);
567
15.4k
            if (code >= 0) {
568
15.4k
                code = pdfi_obj_to_real(ctx, box_obj, &dummy);
569
15.4k
                pdfi_countdown(box_obj);
570
15.4k
            }
571
15.4k
            if (code < 0)
572
0
                break;
573
15.4k
        }
574
3.85k
        if (code >= 0) {
575
3.85k
            code = pdfi_dict_put(ctx, info_dict, "ArtBox", (pdf_obj *)a);
576
3.85k
            if (code < 0)
577
0
                goto done;
578
3.85k
        }
579
3.85k
        pdfi_countdown(a);
580
3.85k
        a = NULL;
581
3.85k
    }
582
583
43.4k
    code = pdfi_dict_get_type(ctx, page_dict, "CropBox", PDF_ARRAY, (pdf_obj **)&a);
584
43.4k
    if (code >= 0) {
585
23.0k
        pdf_obj *box_obj = NULL;
586
587
115k
        for (i = 0;i < pdfi_array_size(a); i++) {
588
92.0k
            code = pdfi_array_get_no_store_R(ctx, a, i, &box_obj);
589
92.0k
            if (code >= 0) {
590
92.0k
                code = pdfi_obj_to_real(ctx, box_obj, &dummy);
591
92.0k
                pdfi_countdown(box_obj);
592
92.0k
            }
593
92.0k
            if (code < 0)
594
14
                break;
595
92.0k
        }
596
23.0k
        if (code >= 0) {
597
22.9k
            code = pdfi_dict_put(ctx, info_dict, "CropBox", (pdf_obj *)a);
598
22.9k
            if (code < 0)
599
0
                goto done;
600
22.9k
        }
601
23.0k
        pdfi_countdown(a);
602
23.0k
        a = NULL;
603
23.0k
    }
604
605
43.4k
    code = pdfi_dict_get_type(ctx, page_dict, "TrimBox", PDF_ARRAY, (pdf_obj **)&a);
606
43.4k
    if (code >= 0) {
607
4.00k
        pdf_obj *box_obj = NULL;
608
609
20.0k
        for (i = 0;i < pdfi_array_size(a); i++) {
610
16.0k
            code = pdfi_array_get_no_store_R(ctx, a, i, &box_obj);
611
16.0k
            if (code >= 0) {
612
16.0k
                code = pdfi_obj_to_real(ctx, box_obj, &dummy);
613
16.0k
                pdfi_countdown(box_obj);
614
16.0k
            }
615
16.0k
            if (code < 0)
616
1
                break;
617
16.0k
        }
618
4.00k
        if (code >= 0) {
619
4.00k
            code = pdfi_dict_put(ctx, info_dict, "TrimBox", (pdf_obj *)a);
620
4.00k
            if (code < 0)
621
0
                goto done;
622
4.00k
        }
623
4.00k
        pdfi_countdown(a);
624
4.00k
        a = NULL;
625
4.00k
    }
626
627
43.4k
    code = pdfi_dict_get_type(ctx, page_dict, "BleedBox", PDF_ARRAY, (pdf_obj **)&a);
628
43.4k
    if (code >= 0) {
629
3.93k
        pdf_obj *box_obj = NULL;
630
631
19.6k
        for (i = 0;i < pdfi_array_size(a); i++) {
632
15.7k
            code = pdfi_array_get_no_store_R(ctx, a, i, &box_obj);
633
15.7k
            if (code >= 0) {
634
15.7k
                code = pdfi_obj_to_real(ctx, box_obj, &dummy);
635
15.7k
                pdfi_countdown(box_obj);
636
15.7k
            }
637
15.7k
            if (code < 0)
638
0
                break;
639
15.7k
        }
640
3.93k
        if (code >= 0) {
641
3.93k
            code = pdfi_dict_put(ctx, info_dict, "BleedBox", (pdf_obj *)a);
642
3.93k
            if (code < 0)
643
0
                goto done;
644
3.93k
        }
645
3.93k
        pdfi_countdown(a);
646
3.93k
        a = NULL;
647
3.93k
    }
648
43.4k
    code = 0;
649
650
43.4k
    code = pdfi_dict_get(ctx, page_dict, "Rotate", &o);
651
43.4k
    if (code >= 0) {
652
22.0k
        if (pdfi_type_of(o) == PDF_INT || pdfi_type_of(o) == PDF_REAL) {
653
22.0k
            code = pdfi_dict_put(ctx, info_dict, "Rotate", o);
654
22.0k
            if (code < 0)
655
0
                goto done;
656
22.0k
        }
657
22.0k
        pdfi_countdown(o);
658
22.0k
    }
659
660
43.4k
    code = pdfi_dict_get(ctx, page_dict, "UserUnit", &o);
661
43.4k
    if (code >= 0) {
662
257
        if (pdfi_type_of(o) == PDF_INT || pdfi_type_of(o) == PDF_REAL) {
663
257
            code = pdfi_dict_put(ctx, info_dict, "UserUnit", o);
664
257
            if (code < 0)
665
0
                goto done;
666
257
        }
667
257
        pdfi_countdown(o);
668
257
    }
669
670
43.4k
    if (ctx->page.has_transparency)
671
2.61k
        code = pdfi_dict_put(ctx, info_dict, "UsesTransparency", PDF_TRUE_OBJ);
672
40.8k
    else
673
40.8k
        code = pdfi_dict_put(ctx, info_dict, "UsesTransparency", PDF_FALSE_OBJ);
674
43.4k
    if (code < 0)
675
0
        goto done;
676
677
43.4k
    code = pdfi_dict_known(ctx, page_dict, "Annots", &known);
678
43.4k
    if (code >= 0 && known)
679
18.7k
        code = pdfi_dict_put(ctx, info_dict, "Annots", PDF_TRUE_OBJ);
680
24.7k
    else
681
24.7k
        code = pdfi_dict_put(ctx, info_dict, "Annots", PDF_FALSE_OBJ);
682
43.4k
    if (code < 0)
683
0
        goto done;
684
685
43.4k
    code = pdfi_object_alloc(ctx, PDF_INT, 0, &o);
686
43.4k
    if (code >= 0) {
687
43.4k
        pdfi_countup(o);
688
43.4k
        ((pdf_num *)o)->value.i = ctx->page.num_spots;
689
43.4k
        code = pdfi_dict_put(ctx, info_dict, "NumSpots", o);
690
43.4k
        pdfi_countdown(o);
691
43.4k
        o = NULL;
692
43.4k
        if (code < 0)
693
0
            goto done;
694
43.4k
    }
695
696
43.5k
done:
697
43.5k
    if (code < 0) {
698
42
        pdfi_countdown(info_dict);
699
42
        info_dict = NULL;
700
42
        *info = NULL;
701
42
    } else
702
43.4k
        *info = info_dict;
703
704
43.5k
    pdfi_countdown(a);
705
43.5k
    pdfi_countdown(page_dict);
706
43.5k
    return code;
707
43.4k
}
708
709
int pdfi_page_get_dict(pdf_context *ctx, uint64_t page_num, pdf_dict **dict)
710
97.5k
{
711
97.5k
    int code = 0;
712
97.5k
    uint64_t page_offset = 0;
713
714
97.5k
    code = pdfi_loop_detector_mark(ctx);
715
97.5k
    if (code < 0)
716
0
        return code;
717
718
97.5k
    if (ctx->PagesTree == NULL) {
719
239
        pdf_obj *o = NULL;
720
239
        pdf_name *n = NULL;
721
        /* The only way this should be true is if the Pages entry in the Root dictionary
722
         * points to a single instance of a Page dictionary, instead of to a Pages dictionary.
723
         * in which case, simply retrieve that dictionary and return.
724
         */
725
239
        code = pdfi_dict_get(ctx, ctx->Root, "Pages", &o);
726
239
        if (code < 0)
727
0
            goto page_error;
728
239
        if (pdfi_type_of(o) != PDF_DICT) {
729
0
            code = gs_note_error(gs_error_typecheck);
730
0
            goto page_error;
731
0
        }
732
239
        code = pdfi_dict_get_type(ctx, (pdf_dict *)o, "Type", PDF_NAME, (pdf_obj **)&n);
733
239
        if (code == 0) {
734
239
            if(pdfi_name_is(n, "Page")) {
735
239
                *dict = (pdf_dict *)o;
736
239
                pdfi_countup(*dict);
737
239
            } else
738
0
                code = gs_note_error(gs_error_undefined);
739
239
        }
740
239
page_error:
741
239
        pdfi_loop_detector_cleartomark(ctx);
742
239
        pdfi_countdown(o);
743
239
        pdfi_countdown(n);
744
239
        return code;
745
239
    }
746
747
97.2k
    code = pdfi_loop_detector_add_object(ctx, ctx->PagesTree->object_num);
748
97.2k
    if (code < 0)
749
0
        goto exit;
750
751
97.2k
    code = pdfi_get_page_dict(ctx, ctx->PagesTree, page_num, &page_offset, dict, NULL);
752
97.2k
    if (code > 0)
753
0
        code = gs_error_unknownerror;
754
755
    /* Cache the page_dict number in page_array */
756
97.2k
    if (*dict)
757
86.7k
        ctx->page_array[page_num] = (*dict)->object_num;
758
759
97.2k
 exit:
760
97.2k
    pdfi_loop_detector_cleartomark(ctx);
761
97.2k
    return code;
762
97.2k
}
763
764
/* Find the page number that corresponds to a page dictionary
765
 * Uses page_array cache to minimize the number of times a page_dict needs to
766
 * be fetched, because this is expensive.
767
 */
768
int pdfi_page_get_number(pdf_context *ctx, pdf_dict *target_dict, uint64_t *page_num)
769
7.10k
{
770
7.10k
    uint64_t i;
771
7.10k
    int code = 0;
772
7.10k
    pdf_dict *page_dict = NULL;
773
7.10k
    uint32_t object_num;
774
775
7.23k
    for (i=0; i<ctx->num_pages; i++) {
776
        /* If the page has been processed before, then its object_num should already
777
         * be cached in the page_array, so check that first
778
         */
779
7.23k
        object_num = ctx->page_array[i];
780
7.23k
        if (object_num == 0) {
781
            /* It wasn't cached, so this will cache it */
782
70
            code = pdfi_page_get_dict(ctx, i, &page_dict);
783
70
            if (code < 0)
784
0
                continue;
785
70
            object_num = ctx->page_array[i];
786
70
        }
787
7.23k
        if (target_dict->object_num == object_num) {
788
7.10k
            *page_num = i;
789
7.10k
            goto exit;
790
7.10k
        }
791
792
133
        pdfi_countdown(page_dict);
793
133
        page_dict = NULL;
794
133
    }
795
796
0
    code = gs_note_error(gs_error_undefined);
797
798
7.10k
 exit:
799
7.10k
    pdfi_countdown(page_dict);
800
7.10k
    return code;
801
0
}
802
803
static void release_page_DefaultSpaces(pdf_context *ctx)
804
86.7k
{
805
86.7k
    if (ctx->page.DefaultGray_cs != NULL) {
806
0
        if (ctx->page.DefaultGray_cs->interpreter_data != NULL) {
807
0
            pdf_obj *o = (pdf_obj *)(ctx->page.DefaultGray_cs->interpreter_data);
808
0
            if (o != NULL && pdfi_type_of(o) == PDF_NAME) {
809
0
                pdfi_countdown(o);
810
0
                ctx->page.DefaultGray_cs->interpreter_data = NULL;
811
0
            }
812
0
        }
813
0
        rc_decrement(ctx->page.DefaultGray_cs, "pdfi_page_render");
814
0
        ctx->page.DefaultGray_cs = NULL;
815
0
    }
816
86.7k
    if (ctx->page.DefaultRGB_cs != NULL) {
817
127
        if (ctx->page.DefaultRGB_cs->interpreter_data != NULL) {
818
127
            pdf_obj *o = (pdf_obj *)(ctx->page.DefaultRGB_cs->interpreter_data);
819
127
            if (o != NULL && pdfi_type_of(o) == PDF_NAME) {
820
28
                pdfi_countdown(o);
821
28
                ctx->page.DefaultRGB_cs->interpreter_data = NULL;
822
28
            }
823
127
        }
824
127
        rc_decrement(ctx->page.DefaultRGB_cs, "pdfi_page_render");
825
127
        ctx->page.DefaultRGB_cs = NULL;
826
127
    }
827
86.7k
    if (ctx->page.DefaultCMYK_cs != NULL) {
828
8
        if (ctx->page.DefaultCMYK_cs->interpreter_data != NULL) {
829
8
            pdf_obj *o = (pdf_obj *)(ctx->page.DefaultCMYK_cs->interpreter_data);
830
8
            if (o != NULL && pdfi_type_of(o) == PDF_NAME) {
831
0
                pdfi_countdown(o);
832
0
                ctx->page.DefaultCMYK_cs->interpreter_data = NULL;
833
0
            }
834
8
        }
835
8
        rc_decrement(ctx->page.DefaultCMYK_cs, "pdfi_page_render");
836
8
        ctx->page.DefaultCMYK_cs = NULL;
837
8
    }
838
86.7k
}
839
840
static int setup_page_DefaultSpaces(pdf_context *ctx, pdf_dict *page_dict)
841
43.3k
{
842
    /* First off, discard any dangling Default* colour spaces, just in case. */
843
43.3k
    release_page_DefaultSpaces(ctx);
844
845
43.3k
    return(pdfi_setup_DefaultSpaces(ctx, page_dict));
846
43.3k
}
847
848
static bool
849
pdfi_pattern_purge_all_proc(gx_color_tile * ctile, void *proc_data)
850
6.96k
{
851
6.96k
    return true;
852
6.96k
}
853
854
int pdfi_page_render(pdf_context *ctx, uint64_t page_num, bool init_graphics)
855
43.3k
{
856
43.3k
    int code, code1=0;
857
43.3k
    pdf_dict *page_dict = NULL;
858
43.3k
    bool page_group_known = false;
859
43.3k
    pdf_dict *group_dict = NULL;
860
43.3k
    bool page_dict_error = false;
861
43.3k
    bool need_pdf14 = false; /* true if the device is needed and was successfully pushed */
862
43.3k
    int trans_depth = 0; /* -1 means special mode for transparency simulation */
863
864
43.3k
    if (page_num > ctx->num_pages)
865
0
        return_error(gs_error_rangecheck);
866
867
43.3k
    if (ctx->args.pdfdebug)
868
43.3k
        dmprintf1(ctx->memory, "%% Processing Page %"PRIi64" content stream\n", page_num + 1);
869
870
43.3k
    code = pdfi_page_get_dict(ctx, page_num, &page_dict);
871
43.3k
    if (code < 0) {
872
0
        char extra_info[256];
873
874
0
        page_dict_error = true;
875
0
        gs_snprintf(extra_info, sizeof(extra_info), "*** ERROR: Page %ld has invalid Page dict, skipping\n", page_num+1);
876
0
        pdfi_set_error(ctx, 0, NULL, E_PDF_PAGEDICTERROR, "pdfi_page_render", extra_info);
877
0
        if (code != gs_error_VMerror && !ctx->args.pdfstoponerror)
878
0
            code = 0;
879
0
        goto exit3;
880
0
    }
881
882
43.3k
    code = pdfi_check_page(ctx, page_dict, NULL, NULL, init_graphics);
883
43.3k
    if (code < 0)
884
0
        goto exit3;
885
886
43.3k
    if (ctx->args.pdfdebug) {
887
0
        dbgmprintf2(ctx->memory, "Current page %ld transparency setting is %d", page_num+1,
888
0
                ctx->page.has_transparency);
889
890
0
        if (ctx->device_state.spot_capable)
891
0
            dbgmprintf1(ctx->memory, ", spots=%d\n", ctx->page.num_spots);
892
0
        else
893
0
            dbgmprintf(ctx->memory, "\n");
894
0
    }
895
896
43.3k
    code = pdfi_dict_knownget_type(ctx, page_dict, "Group", PDF_DICT, (pdf_obj **)&group_dict);
897
    /* Ignore errors retrieving the Group dictionary, we will just ignore it. This allows us
898
     * to handle files such as Bug #705206 where the Group dictionary is a free object in a
899
     * compressed object stream.
900
     */
901
43.3k
    if (code < 0)
902
49
        pdfi_set_error(ctx, 0, NULL, E_BAD_GROUP_DICT, "pdfi_page_render", NULL);
903
43.3k
    if (group_dict != NULL)
904
2.72k
        page_group_known = true;
905
906
43.3k
    pdfi_countdown(ctx->page.CurrentPageDict);
907
43.3k
    ctx->page.CurrentPageDict = page_dict;
908
43.3k
    pdfi_countup(ctx->page.CurrentPageDict);
909
910
    /* In case we don't call pdfi_set_media_size, which sets this up.
911
     * We shouldn't ever use it in that case, but best to be safe.
912
     */
913
43.3k
    ctx->page.UserUnit = 1.0f;
914
    /* If we are being called from the PDF interpreter then
915
     * we need to set up the page  and the default graphics state
916
     * but if we are being called from PostScript we do *not*
917
     * want to alter any of the graphics state or the media size.
918
     */
919
    /* TODO: I think this is a mix of things we might need to
920
     * still be setting up.
921
     * (for example, I noticed the blendmode and moved it outside the if)
922
     */
923
43.3k
    if (init_graphics) {
924
0
        code = pdfi_set_media_size(ctx, page_dict);
925
0
        if (code < 0)
926
0
            goto exit2;
927
928
0
        pdfi_set_ctm(ctx);
929
930
43.3k
    } else {
931
        /* Gets ctx->page.Size setup correctly
932
         * TODO: Probably not right if the page is rotated?
933
         * page.Size is needed by the transparency code,
934
         * not sure where else it might be used, if anywhere.
935
         */
936
43.3k
        pdfi_get_media_size(ctx, page_dict);
937
43.3k
    }
938
939
    /* Write the various CropBox, TrimBox etc to the device */
940
43.3k
    pdfi_pdfmark_write_boxes(ctx, page_dict);
941
942
43.3k
    code = setup_page_DefaultSpaces(ctx, page_dict);
943
43.3k
    if (code < 0)
944
0
        goto exit2;
945
946
43.3k
    pdfi_setup_transfers(ctx);
947
948
    /* Set whether device needs OP support
949
     * This needs to be before transparency device is pushed, if applicable
950
     */
951
43.3k
    pdfi_trans_set_needs_OP(ctx);
952
43.3k
    pdfi_oc_init(ctx);
953
954
43.3k
    code = pdfi_gsave(ctx);
955
43.3k
    if (code < 0)
956
0
        goto exit2;
957
958
    /* Figure out if pdf14 device is needed.
959
     * This can be either for normal transparency deviceN, or because we are using
960
     * Overprint=/simulate for other devices
961
     */
962
43.3k
    if (ctx->page.has_transparency) {
963
2.60k
        need_pdf14 = true;
964
2.60k
        if (ctx->page.simulate_op)
965
0
            trans_depth = -1;
966
40.7k
    } else {
967
        /* This is the case where we are simulating overprint without transparency */
968
40.7k
        if (ctx->page.simulate_op) {
969
0
            need_pdf14 = true;
970
0
            trans_depth = -1;
971
0
        }
972
40.7k
    }
973
43.3k
    if (need_pdf14) {
974
        /* We don't retain the PDF14 device */
975
2.60k
        code = gs_push_pdf14trans_device(ctx->pgs, false, false, trans_depth, ctx->page.num_spots);
976
2.60k
        if (code >= 0) {
977
2.60k
            if (ctx->page.has_transparency && page_group_known) {
978
1.02k
                code = pdfi_trans_begin_page_group(ctx, page_dict, group_dict);
979
                /* If setting the page group failed for some reason, abandon the page group,
980
                 *  but continue with the page
981
                 */
982
1.02k
                if (code < 0)
983
27
                    page_group_known = false;
984
1.02k
            }
985
2.60k
        } else {
986
            /* Couldn't push the transparency compositor.
987
             * This is probably fatal, but attempt to recover by abandoning transparency
988
             */
989
0
            ctx->page.has_transparency = false;
990
0
            need_pdf14 = false;
991
0
        }
992
2.60k
    }
993
994
    /* Init a base_pgs graphics state for Patterns
995
     * (this has to be after transparency device pushed, if applicable)
996
     */
997
43.3k
    pdfi_set_DefaultQState(ctx, ctx->pgs);
998
999
    /* Render one page (including annotations) */
1000
43.3k
    if (!ctx->args.QUIET)
1001
0
        outprintf(ctx->memory, "Page %"PRId64"\n", page_num + 1);
1002
1003
43.3k
    code = pdfi_process_one_page(ctx, page_dict);
1004
1005
43.3k
    if (need_pdf14 && ctx->page.has_transparency && page_group_known) {
1006
1.00k
        code1 = pdfi_trans_end_group(ctx);
1007
1.00k
    }
1008
1009
43.3k
    if (need_pdf14) {
1010
2.60k
        if (code1 < 0) {
1011
0
            (void)gs_abort_pdf14trans_device(ctx->pgs);
1012
0
            code = code1;
1013
0
            goto exit1;
1014
0
        }
1015
1016
2.60k
        code = gs_pop_pdf14trans_device(ctx->pgs, false);
1017
2.60k
        if (code < 0) {
1018
10
            goto exit1;
1019
10
        }
1020
2.60k
    }
1021
1022
43.3k
exit1:
1023
43.3k
    pdfi_free_DefaultQState(ctx);
1024
43.3k
    pdfi_grestore(ctx);
1025
1026
43.3k
exit2:
1027
43.3k
    pdfi_countdown(ctx->page.CurrentPageDict);
1028
43.3k
    ctx->page.CurrentPageDict = NULL;
1029
1030
43.3k
exit3:
1031
43.3k
    pdfi_countdown(page_dict);
1032
43.3k
    pdfi_countdown(group_dict);
1033
1034
43.3k
    release_page_DefaultSpaces(ctx);
1035
1036
    /* Flush any pattern tiles. We don't want to (potentially) return to PostScript
1037
     * with any pattern tiles referencing our objects, in case the garbager runs.
1038
     */
1039
43.3k
    gx_pattern_cache_winnow(gstate_pattern_cache(ctx->pgs), pdfi_pattern_purge_all_proc, NULL);
1040
1041
43.3k
    if (code == 0 || (!ctx->args.pdfstoponerror && code != gs_error_pdf_stackoverflow))
1042
43.3k
        if (!page_dict_error && ctx->finish_page != NULL)
1043
0
            code = ctx->finish_page(ctx);
1044
43.3k
    return code;
1045
43.3k
}