Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/pdf/pdf_device.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
/* Routines for dealing with devices */
17
18
#include "pdf_int.h"
19
#include "pdf_stack.h"
20
#include "pdf_device.h"
21
#include "gsdevice.h"       /* For gs_setdevice_no_erase */
22
#include "gspaint.h"        /* For gs_erasepage */
23
#include "gdevvec.h"        /* for gs_device_vector */
24
#include "gxdevsop.h"       /* For special ops : dev_param_req_t */
25
26
int pdfi_device_check_param(gx_device *dev, const char *param, gs_c_param_list *list)
27
195k
{
28
195k
    dev_param_req_t request;
29
195k
    int code;
30
31
195k
    gs_c_param_list_write(list, dev->memory);
32
    /* Stuff the data into a structure for passing to the spec_op */
33
195k
    request.Param = (char *)param;
34
195k
    request.list = list;
35
195k
    code = dev_proc(dev, dev_spec_op)(dev, gxdso_get_dev_param, &request, sizeof(dev_param_req_t));
36
195k
    if (code < 0) {
37
146k
        gs_c_param_list_release(list);
38
146k
        return code;
39
146k
    }
40
49.1k
    return 0;
41
195k
}
42
43
/* Check value of boolean device parameter */
44
bool pdfi_device_check_param_bool(gx_device *dev, const char *param)
45
170k
{
46
170k
    int code;
47
170k
    gs_c_param_list list;
48
170k
    int value;
49
50
170k
    code = pdfi_device_check_param(dev, param, &list);
51
170k
    if (code < 0)
52
124k
        return false;
53
45.3k
    gs_c_param_list_read(&list);
54
45.3k
    code = param_read_bool((gs_param_list *)&list,
55
45.3k
                           param,
56
45.3k
                           &value);
57
45.3k
    if (code < 0)
58
0
        value = false;
59
45.3k
    gs_c_param_list_release(&list);
60
45.3k
    return (bool)value;
61
170k
}
62
63
/* Set value of string device parameter */
64
int pdfi_device_set_param_string(gx_device *dev, const char *paramname, const char *value)
65
0
{
66
0
    int code;
67
0
    gs_c_param_list list;
68
0
    gs_param_string paramstring;
69
70
0
    paramstring.data = (byte *)value;
71
0
    paramstring.size = strlen(value);
72
0
    paramstring.persistent = 0;
73
74
0
    gs_c_param_list_write(&list, dev->memory);
75
76
0
    gs_param_list_set_persistent_keys((gs_param_list *) &list, false);
77
0
    code = param_write_string((gs_param_list *)&list, paramname, &paramstring);
78
0
    if (code < 0) goto exit;
79
0
    gs_c_param_list_read(&list);
80
0
    code = gs_putdeviceparams(dev, (gs_param_list *)&list);
81
82
0
 exit:
83
0
    gs_c_param_list_release(&list);
84
0
    return code;
85
0
}
86
87
/* Set value of boolean device parameter */
88
int pdfi_device_set_param_bool(gx_device *dev, const char *param, bool value)
89
0
{
90
0
    int code;
91
0
    gs_c_param_list list;
92
0
    bool paramval = value;
93
94
0
    gs_c_param_list_write(&list, dev->memory);
95
96
0
    code = param_write_bool((gs_param_list *)&list, param, &paramval);
97
0
    if (code < 0) goto exit;
98
0
    gs_c_param_list_read(&list);
99
0
    code = gs_putdeviceparams(dev, (gs_param_list *)&list);
100
101
0
 exit:
102
0
    gs_c_param_list_release(&list);
103
0
    return code;
104
0
}
105
106
/* Checks whether a parameter exists for the device */
107
bool pdfi_device_check_param_exists(gx_device *dev, const char *param)
108
25.3k
{
109
25.3k
    int code;
110
25.3k
    gs_c_param_list list;
111
112
25.3k
    code = pdfi_device_check_param(dev, param, &list);
113
25.3k
    if (code < 0)
114
21.5k
        return false;
115
3.83k
    gs_c_param_list_release(&list);
116
3.83k
    return true;
117
25.3k
}
118
119
/* Config some device-related variables */
120
void pdfi_device_set_flags(pdf_context *ctx)
121
25.3k
{
122
25.3k
    bool has_pdfmark;
123
25.3k
    bool has_ForOPDFRead;
124
25.3k
    gx_device *dev = ctx->pgs->device;
125
126
25.3k
    has_pdfmark = pdfi_device_check_param_exists(dev, "pdfmark");
127
25.3k
    has_ForOPDFRead = pdfi_device_check_param_bool(dev, "ForOPDFRead");
128
129
    /* Cache these so they don't have to constantly be calculated */
130
25.3k
    ctx->device_state.writepdfmarks = has_pdfmark || ctx->args.dopdfmarks;
131
25.3k
    ctx->device_state.annotations_preserved = ctx->device_state.writepdfmarks && !has_ForOPDFRead;
132
133
    /* PreserveTrMode is for pdfwrite device */
134
25.3k
    ctx->device_state.preserve_tr_mode = pdfi_device_check_param_bool(dev, "PreserveTrMode");
135
25.3k
    ctx->device_state.preserve_smask = pdfi_device_check_param_bool(dev, "PreserveSMask");
136
25.3k
    ctx->device_state.HighLevelDevice = pdfi_device_check_param_bool(dev, "HighLevelDevice");
137
25.3k
    ctx->device_state.WantsPageLabels = pdfi_device_check_param_bool(dev, "WantsPageLabels");
138
139
    /* See if it is a DeviceN (spot capable) */
140
25.3k
    ctx->device_state.spot_capable = dev_proc(dev, dev_spec_op)(dev, gxdso_supports_devn, NULL, 0);
141
142
    /* If multi-page output, can't do certain pdfmarks */
143
25.3k
    if (ctx->device_state.writepdfmarks) {
144
3.83k
        if (gx_outputfile_is_separate_pages(((gx_device_vector *)dev)->fname, dev->memory)) {
145
0
            ctx->args.no_pdfmark_outlines = true;
146
0
            ctx->args.no_pdfmark_dests = true;
147
0
        }
148
3.83k
    }
149
150
#if DEBUG_DEVICE
151
    dbgmprintf2(ctx->memory, "Device writepdfmarks=%s, annotations_preserved=%s\n",
152
        ctx->writepdfmarks ? "TRUE" : "FALSE",
153
                ctx->annotations_preserved ? "TRUE" : "FALSE");
154
#endif
155
25.3k
}
156
157
/* Config the output device
158
 * This will configure any special device parameters.
159
 * Right now it just sets up some stuff for pdfwrite.
160
 */
161
int pdfi_device_misc_config(pdf_context *ctx)
162
0
{
163
0
    bool has_pdfmark = false;
164
0
    int code;
165
0
    gx_device *dev = ctx->pgs->device;
166
167
0
    if (ctx->args.first_page != 0 || ctx->args.last_page != 0) {
168
0
        code = pdfi_device_set_param_bool(dev, "DisablePageHandler", true);
169
0
        if (code < 0) goto exit;
170
0
    }
171
172
    /* I am using pdfmark to identify the pdfwrite device */
173
0
    has_pdfmark = pdfi_device_check_param_bool(dev, "pdfmark");
174
    /* (only handling pdfwrite for now) */
175
0
    if (!has_pdfmark)
176
0
        return 0;
177
178
    /* TODO: I think the pdfwrite device should have these automatically set to true,
179
     * but that doesn't seem to be the case now.
180
     * See pdf_document_metadata()
181
     */
182
0
    code = pdfi_device_set_param_string(dev, "AutoRotatePages", "PageByPage");
183
0
    if (code < 0) goto exit;
184
185
0
exit:
186
0
    return code;
187
0
}