Coverage Report

Created: 2025-06-10 07:26

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