Coverage Report

Created: 2025-06-10 07:27

/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
11.4M
{
39
11.4M
    uint added = 0;
40
11.4M
    uint i;
41
11.4M
    const stream_template *templat;
42
11.4M
    stream_AXE_state state;
43
11.4M
    stream_state *st = NULL;
44
45
11.4M
    if (print_ok & PRINT_BINARY_OK) {
46
        /* Only need to escape (, ), \, CR, EOL. */
47
5.00M
        stream_putc(s, '(');
48
14.9M
        for (i = 0; i < size; ++i) {
49
9.98M
            byte ch = str[i];
50
51
9.98M
            switch (ch) {
52
17.6k
                case char_CR:
53
17.6k
                    stream_puts(s, "\\r");
54
17.6k
                    continue;
55
53.1k
                case char_EOL:
56
53.1k
                    stream_puts(s, "\\n");
57
53.1k
                    continue;
58
37.4k
                case '(':
59
74.1k
                case ')':
60
74.9k
                case '\\':
61
74.9k
                    stream_putc(s, '\\');
62
9.98M
            }
63
9.91M
            stream_putc(s, ch);
64
9.91M
        }
65
5.00M
        stream_putc(s, ')');
66
5.00M
        return;
67
5.00M
    }
68
22.6M
    for (i = 0; i < size; ++i) {
69
16.2M
        byte ch = str[i];
70
71
16.2M
        if (ch == 0 || ch >= 127)
72
771k
            added += 3;
73
15.4M
        else if (strchr("()\\\n\r\t\b\f", ch) != 0)
74
439k
            ++added;
75
15.0M
        else if (ch < 32)
76
805k
            added += 3;
77
16.2M
    }
78
79
6.39M
    if (added < size || (print_ok & PRINT_HEX_NOT_OK)) {
80
        /* More efficient, or mandatory, to represent as PostScript string. */
81
5.31M
        templat = &s_PSSE_template;
82
5.31M
        stream_putc(s, '(');
83
5.31M
    } else {
84
        /* More efficient, and permitted, to represent as hex string. */
85
1.08M
        templat = &s_AXE_template;
86
1.08M
        st = (stream_state *) & state;
87
1.08M
        s_AXE_init_inline(&state);
88
1.08M
        stream_putc(s, '<');
89
1.08M
    }
90
91
6.39M
    {
92
6.39M
        byte buf[100];    /* size is arbitrary */
93
6.39M
        stream_cursor_read r;
94
6.39M
        stream_cursor_write w;
95
6.39M
        int status;
96
97
6.39M
        stream_cursor_read_init(&r, str, size);
98
6.41M
        do {
99
6.41M
            stream_cursor_write_init(&w, buf, sizeof(buf));
100
101
6.41M
            status = (*templat->process) (st, &r, &w, true);
102
6.41M
            stream_write(s, buf, (uint) (w.ptr + 1 - buf));
103
6.41M
        }
104
6.41M
        while (status == 1);
105
6.39M
    }
106
6.39M
}
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
466k
{
144
466k
    gs_param_list_init((gs_param_list *)prlist, &printer_param_list_procs,
145
466k
                       NULL);
146
466k
    prlist->strm = s;
147
466k
    prlist->params = *ppp;
148
466k
    prlist->any = false;
149
466k
    return 0;
150
466k
}
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
49.9k
{
172
49.9k
    if (prlist) {
173
49.9k
        if (prlist->any && prlist->params.suffix)
174
0
            stream_puts(prlist->strm, prlist->params.suffix);
175
49.9k
    }
176
49.9k
}
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.14M
{
192
1.14M
    printer_param_list_t *const prlist = (printer_param_list_t *)plist;
193
1.14M
    stream *s = prlist->strm;
194
195
1.14M
    if (!prlist->any) {
196
466k
        if (prlist->params.prefix)
197
0
            stream_puts(s, prlist->params.prefix);
198
466k
        prlist->any = true;
199
466k
    }
200
1.14M
    if (prlist->params.item_prefix)
201
0
        stream_puts(s, prlist->params.item_prefix);
202
1.14M
    pprints1(s, "/%s", pkey);
203
1.14M
    switch (pvalue->type) {
204
0
        case gs_param_type_null:
205
0
            stream_puts(s, " null");
206
0
            break;
207
247k
        case gs_param_type_bool:
208
247k
            stream_puts(s, (pvalue->value.b ? " true" : " false"));
209
247k
            break;
210
820k
        case gs_param_type_int:
211
820k
            pprintd1(s, " %d", pvalue->value.i);
212
820k
            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
27.5k
        case gs_param_type_float:
223
27.5k
            pprintg1(s, " %g", pvalue->value.f);
224
27.5k
            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
52.5k
        case gs_param_type_float_array:
248
52.5k
            {
249
52.5k
                uint i;
250
52.5k
                char sepr = (pvalue->value.fa.size <= 10 ? ' ' : '\n');
251
252
52.5k
                stream_putc(s, '[');
253
383k
                for (i = 0; i < pvalue->value.fa.size; ++i) {
254
331k
                    pprintg1(s, "%g", pvalue->value.fa.data[i]);
255
331k
                    stream_putc(s, sepr);
256
331k
                }
257
52.5k
                stream_putc(s, ']');
258
52.5k
            }
259
52.5k
            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.14M
    }
265
1.14M
    if (prlist->params.item_suffix)
266
314k
        stream_puts(s, prlist->params.item_suffix);
267
1.14M
    return 0;
268
1.14M
}