Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/spsdf.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2023 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* Common utilities for PostScript and PDF format printing */
18
#include "stdio_.h"   /* for stream.h */
19
#include "string_.h"
20
#include "gstypes.h"
21
#include "gsmemory.h"
22
#include "gserrors.h"
23
#include "spprint.h"
24
#include "spsdf.h"
25
#include "stream.h"
26
#include "strimpl.h"
27
#include "sa85x.h"
28
#include "sstring.h"
29
#include "scanchar.h"
30
31
/*
32
 * Write a string in its shortest form ( () or <> ).  Note that
33
 * this form is different depending on whether binary data are allowed.
34
 * Currently we don't support ASCII85 strings ( <~ ~> ).
35
 */
36
void
37
s_write_ps_string(stream * s, const byte * str, uint size, int print_ok)
38
9.39M
{
39
9.39M
    uint added = 0;
40
9.39M
    uint i;
41
9.39M
    const stream_template *templat;
42
9.39M
    stream_AXE_state state;
43
9.39M
    stream_state *st = NULL;
44
45
9.39M
    if (print_ok & PRINT_BINARY_OK) {
46
        /* Only need to escape (, ), \, CR, EOL. */
47
2.20M
        stream_putc(s, '(');
48
6.44M
        for (i = 0; i < size; ++i) {
49
4.23M
            byte ch = str[i];
50
51
4.23M
            switch (ch) {
52
5.04k
                case char_CR:
53
5.04k
                    stream_puts(s, "\\r");
54
5.04k
                    continue;
55
19.8k
                case char_EOL:
56
19.8k
                    stream_puts(s, "\\n");
57
19.8k
                    continue;
58
20.3k
                case '(':
59
39.6k
                case ')':
60
40.0k
                case '\\':
61
40.0k
                    stream_putc(s, '\\');
62
4.23M
            }
63
4.20M
            stream_putc(s, ch);
64
4.20M
        }
65
2.20M
        stream_putc(s, ')');
66
2.20M
        return;
67
2.20M
    }
68
25.2M
    for (i = 0; i < size; ++i) {
69
18.0M
        byte ch = str[i];
70
71
18.0M
        if (ch == 0 || ch >= 127)
72
672k
            added += 3;
73
17.3M
        else if (strchr("()\\\n\r\t\b\f", ch) != 0)
74
537k
            ++added;
75
16.8M
        else if (ch < 32)
76
959k
            added += 3;
77
18.0M
    }
78
79
7.18M
    if (added < size || (print_ok & PRINT_HEX_NOT_OK)) {
80
        /* More efficient, or mandatory, to represent as PostScript string. */
81
5.90M
        templat = &s_PSSE_template;
82
5.90M
        stream_putc(s, '(');
83
5.90M
    } else {
84
        /* More efficient, and permitted, to represent as hex string. */
85
1.28M
        templat = &s_AXE_template;
86
1.28M
        st = (stream_state *) & state;
87
1.28M
        s_AXE_init_inline(&state);
88
1.28M
        stream_putc(s, '<');
89
1.28M
    }
90
91
7.18M
    {
92
7.18M
        byte buf[100];    /* size is arbitrary */
93
7.18M
        stream_cursor_read r;
94
7.18M
        stream_cursor_write w;
95
7.18M
        int status;
96
97
7.18M
        stream_cursor_read_init(&r, str, size);
98
7.21M
        do {
99
7.21M
            stream_cursor_write_init(&w, buf, sizeof(buf));
100
101
7.21M
            status = (*templat->process) (st, &r, &w, true);
102
7.21M
            stream_write(s, buf, (uint) (w.ptr + 1 - buf));
103
7.21M
        }
104
7.21M
        while (status == 1);
105
7.18M
    }
106
7.18M
}
107
108
/* Set up a write stream that just keeps track of the position. */
109
int
110
s_alloc_position_stream(stream ** ps, gs_memory_t * mem)
111
0
{
112
0
    stream *s = *ps = s_alloc(mem, "s_alloc_position_stream");
113
114
0
    if (s == 0)
115
0
        return_error(gs_error_VMerror);
116
0
    swrite_position_only(s);
117
0
    return 0;
118
0
}
119
120
/* ---------------- Parameter printing ---------------- */
121
122
private_st_printer_param_list();
123
const param_printer_params_t param_printer_params_default = {
124
    param_printer_params_default_values
125
};
126
127
/* We'll implement the other printers later if we have to. */
128
static param_proc_xmit_typed(param_print_typed);
129
/*static param_proc_begin_xmit_collection(param_print_begin_collection);*/
130
/*static param_proc_end_xmit_collection(param_print_end_collection);*/
131
static const gs_param_list_procs printer_param_list_procs = {
132
    param_print_typed,
133
    NULL /* begin_collection */ ,
134
    NULL /* end_collection */ ,
135
    NULL /* get_next_key */ ,
136
    gs_param_request_default,
137
    gs_param_requested_default
138
};
139
140
int
141
s_init_param_printer(printer_param_list_t *prlist,
142
                     const param_printer_params_t * ppp, stream * s)
143
486k
{
144
486k
    gs_param_list_init((gs_param_list *)prlist, &printer_param_list_procs,
145
486k
                       NULL);
146
486k
    prlist->strm = s;
147
486k
    prlist->params = *ppp;
148
486k
    prlist->any = false;
149
486k
    return 0;
150
486k
}
151
int
152
s_alloc_param_printer(gs_param_list ** pplist,
153
                      const param_printer_params_t * ppp, stream * s,
154
                      gs_memory_t * mem)
155
0
{
156
0
    printer_param_list_t *prlist =
157
0
        gs_alloc_struct(mem, printer_param_list_t, &st_printer_param_list,
158
0
                        "s_alloc_param_printer");
159
0
    int code;
160
161
0
    *pplist = (gs_param_list *)prlist;
162
0
    if (prlist == 0)
163
0
        return_error(gs_error_VMerror);
164
0
    code = s_init_param_printer(prlist, ppp, s);
165
0
    prlist->memory = mem;
166
0
    return code;
167
0
}
168
169
void
170
s_release_param_printer(printer_param_list_t *prlist)
171
47.4k
{
172
47.4k
    if (prlist) {
173
47.4k
        if (prlist->any && prlist->params.suffix)
174
0
            stream_puts(prlist->strm, prlist->params.suffix);
175
47.4k
    }
176
47.4k
}
177
void
178
s_free_param_printer(gs_param_list * plist)
179
0
{
180
0
    if (plist) {
181
0
        printer_param_list_t *const prlist = (printer_param_list_t *) plist;
182
183
0
        s_release_param_printer(prlist);
184
0
        gs_free_object(prlist->memory, plist, "s_free_param_printer");
185
0
    }
186
0
}
187
188
static int
189
param_print_typed(gs_param_list * plist, gs_param_name pkey,
190
                  gs_param_typed_value * pvalue)
191
1.15M
{
192
1.15M
    printer_param_list_t *const prlist = (printer_param_list_t *)plist;
193
1.15M
    stream *s = prlist->strm;
194
195
1.15M
    if (!prlist->any) {
196
486k
        if (prlist->params.prefix)
197
0
            stream_puts(s, prlist->params.prefix);
198
486k
        prlist->any = true;
199
486k
    }
200
1.15M
    if (prlist->params.item_prefix)
201
0
        stream_puts(s, prlist->params.item_prefix);
202
1.15M
    pprints1(s, "/%s", pkey);
203
1.15M
    switch (pvalue->type) {
204
0
        case gs_param_type_null:
205
0
            stream_puts(s, " null");
206
0
            break;
207
281k
        case gs_param_type_bool:
208
281k
            stream_puts(s, (pvalue->value.b ? " true" : " false"));
209
281k
            break;
210
799k
        case gs_param_type_int:
211
799k
            pprintd1(s, " %d", pvalue->value.i);
212
799k
            break;
213
0
        case gs_param_type_long:
214
0
            pprintld1(s, " %ld", pvalue->value.l);
215
0
            break;
216
0
        case gs_param_type_size_t:
217
0
            pprintzd1(s, " %"PRIdSIZE, pvalue->value.z);
218
0
            break;
219
0
        case gs_param_type_i64:
220
0
            pprinti64d1(s, " %"PRId64, pvalue->value.i64);
221
0
            break;
222
14.4k
        case gs_param_type_float:
223
14.4k
            pprintg1(s, " %g", pvalue->value.f);
224
14.4k
            break;
225
0
        case gs_param_type_string:
226
0
            s_write_ps_string(s, pvalue->value.s.data, pvalue->value.s.size,
227
0
                              prlist->params.print_ok);
228
0
            break;
229
0
        case gs_param_type_name:
230
            /****** SHOULD USE #-ESCAPES FOR PDF ******/
231
0
            stream_putc(s, '/');
232
0
            stream_write(s, pvalue->value.n.data, pvalue->value.n.size);
233
0
            break;
234
0
        case gs_param_type_int_array:
235
0
            {
236
0
                uint i;
237
0
                char sepr = (pvalue->value.ia.size <= 10 ? ' ' : '\n');
238
239
0
                stream_putc(s, '[');
240
0
                for (i = 0; i < pvalue->value.ia.size; ++i) {
241
0
                    pprintd1(s, "%d", pvalue->value.ia.data[i]);
242
0
                    stream_putc(s, sepr);
243
0
                }
244
0
                stream_putc(s, ']');
245
0
            }
246
0
            break;
247
63.8k
        case gs_param_type_float_array:
248
63.8k
            {
249
63.8k
                uint i;
250
63.8k
                char sepr = (pvalue->value.fa.size <= 10 ? ' ' : '\n');
251
252
63.8k
                stream_putc(s, '[');
253
468k
                for (i = 0; i < pvalue->value.fa.size; ++i) {
254
405k
                    pprintg1(s, "%g", pvalue->value.fa.data[i]);
255
405k
                    stream_putc(s, sepr);
256
405k
                }
257
63.8k
                stream_putc(s, ']');
258
63.8k
            }
259
63.8k
            break;
260
            /*case gs_param_type_string_array: */
261
            /*case gs_param_type_name_array: */
262
0
        default:
263
0
            return_error(gs_error_typecheck);
264
1.15M
    }
265
1.15M
    if (prlist->params.item_suffix)
266
281k
        stream_puts(s, prlist->params.item_suffix);
267
1.15M
    return 0;
268
1.15M
}