Coverage Report

Created: 2026-10-28 08:05

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