/src/libspectre/ghostscript/base/spsdf.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2020 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 | | |
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 | r.ptr = str - 1; |
98 | 0 | r.limit = r.ptr + size; |
99 | 0 | w.limit = buf + sizeof(buf) - 1; |
100 | 0 | do { |
101 | | /* One picky compiler complains if we initialize to buf - 1. */ |
102 | 0 | w.ptr = buf; w.ptr--; |
103 | 0 | status = (*templat->process) (st, &r, &w, true); |
104 | 0 | stream_write(s, buf, (uint) (w.ptr + 1 - buf)); |
105 | 0 | } |
106 | 0 | while (status == 1); |
107 | 0 | } |
108 | 0 | } |
109 | | |
110 | | /* Set up a write stream that just keeps track of the position. */ |
111 | | int |
112 | | s_alloc_position_stream(stream ** ps, gs_memory_t * mem) |
113 | 0 | { |
114 | 0 | stream *s = *ps = s_alloc(mem, "s_alloc_position_stream"); |
115 | |
|
116 | 0 | if (s == 0) |
117 | 0 | return_error(gs_error_VMerror); |
118 | 0 | swrite_position_only(s); |
119 | 0 | return 0; |
120 | 0 | } |
121 | | |
122 | | /* ---------------- Parameter printing ---------------- */ |
123 | | |
124 | | private_st_printer_param_list(); |
125 | | const param_printer_params_t param_printer_params_default = { |
126 | | param_printer_params_default_values |
127 | | }; |
128 | | |
129 | | /* We'll implement the other printers later if we have to. */ |
130 | | static param_proc_xmit_typed(param_print_typed); |
131 | | /*static param_proc_begin_xmit_collection(param_print_begin_collection);*/ |
132 | | /*static param_proc_end_xmit_collection(param_print_end_collection);*/ |
133 | | static const gs_param_list_procs printer_param_list_procs = { |
134 | | param_print_typed, |
135 | | NULL /* begin_collection */ , |
136 | | NULL /* end_collection */ , |
137 | | NULL /* get_next_key */ , |
138 | | gs_param_request_default, |
139 | | gs_param_requested_default |
140 | | }; |
141 | | |
142 | | int |
143 | | s_init_param_printer(printer_param_list_t *prlist, |
144 | | const param_printer_params_t * ppp, stream * s) |
145 | 0 | { |
146 | 0 | gs_param_list_init((gs_param_list *)prlist, &printer_param_list_procs, |
147 | 0 | NULL); |
148 | 0 | prlist->strm = s; |
149 | 0 | prlist->params = *ppp; |
150 | 0 | prlist->any = false; |
151 | 0 | return 0; |
152 | 0 | } |
153 | | int |
154 | | s_alloc_param_printer(gs_param_list ** pplist, |
155 | | const param_printer_params_t * ppp, stream * s, |
156 | | gs_memory_t * mem) |
157 | 0 | { |
158 | 0 | printer_param_list_t *prlist = |
159 | 0 | gs_alloc_struct(mem, printer_param_list_t, &st_printer_param_list, |
160 | 0 | "s_alloc_param_printer"); |
161 | 0 | int code; |
162 | |
|
163 | 0 | *pplist = (gs_param_list *)prlist; |
164 | 0 | if (prlist == 0) |
165 | 0 | return_error(gs_error_VMerror); |
166 | 0 | code = s_init_param_printer(prlist, ppp, s); |
167 | 0 | prlist->memory = mem; |
168 | 0 | return code; |
169 | 0 | } |
170 | | |
171 | | void |
172 | | s_release_param_printer(printer_param_list_t *prlist) |
173 | 0 | { |
174 | 0 | if (prlist) { |
175 | 0 | if (prlist->any && prlist->params.suffix) |
176 | 0 | stream_puts(prlist->strm, prlist->params.suffix); |
177 | 0 | } |
178 | 0 | } |
179 | | void |
180 | | s_free_param_printer(gs_param_list * plist) |
181 | 0 | { |
182 | 0 | if (plist) { |
183 | 0 | printer_param_list_t *const prlist = (printer_param_list_t *) plist; |
184 | |
|
185 | 0 | s_release_param_printer(prlist); |
186 | 0 | gs_free_object(prlist->memory, plist, "s_free_param_printer"); |
187 | 0 | } |
188 | 0 | } |
189 | | |
190 | | static int |
191 | | param_print_typed(gs_param_list * plist, gs_param_name pkey, |
192 | | gs_param_typed_value * pvalue) |
193 | 0 | { |
194 | 0 | printer_param_list_t *const prlist = (printer_param_list_t *)plist; |
195 | 0 | stream *s = prlist->strm; |
196 | |
|
197 | 0 | if (!prlist->any) { |
198 | 0 | if (prlist->params.prefix) |
199 | 0 | stream_puts(s, prlist->params.prefix); |
200 | 0 | prlist->any = true; |
201 | 0 | } |
202 | 0 | if (prlist->params.item_prefix) |
203 | 0 | stream_puts(s, prlist->params.item_prefix); |
204 | 0 | pprints1(s, "/%s", pkey); |
205 | 0 | switch (pvalue->type) { |
206 | 0 | case gs_param_type_null: |
207 | 0 | stream_puts(s, " null"); |
208 | 0 | break; |
209 | 0 | case gs_param_type_bool: |
210 | 0 | stream_puts(s, (pvalue->value.b ? " true" : " false")); |
211 | 0 | break; |
212 | 0 | case gs_param_type_int: |
213 | 0 | pprintd1(s, " %d", pvalue->value.i); |
214 | 0 | break; |
215 | 0 | case gs_param_type_long: |
216 | 0 | pprintld1(s, " %ld", pvalue->value.l); |
217 | 0 | break; |
218 | 0 | case gs_param_type_size_t: |
219 | 0 | pprintzd1(s, " %"PRIdSIZE, pvalue->value.z); |
220 | 0 | break; |
221 | 0 | case gs_param_type_i64: |
222 | 0 | pprinti64d1(s, " %"PRId64, pvalue->value.i64); |
223 | 0 | break; |
224 | 0 | case gs_param_type_float: |
225 | 0 | pprintg1(s, " %g", pvalue->value.f); |
226 | 0 | break; |
227 | 0 | case gs_param_type_string: |
228 | 0 | s_write_ps_string(s, pvalue->value.s.data, pvalue->value.s.size, |
229 | 0 | prlist->params.print_ok); |
230 | 0 | break; |
231 | 0 | case gs_param_type_name: |
232 | | /****** SHOULD USE #-ESCAPES FOR PDF ******/ |
233 | 0 | stream_putc(s, '/'); |
234 | 0 | stream_write(s, pvalue->value.n.data, pvalue->value.n.size); |
235 | 0 | break; |
236 | 0 | case gs_param_type_int_array: |
237 | 0 | { |
238 | 0 | uint i; |
239 | 0 | char sepr = (pvalue->value.ia.size <= 10 ? ' ' : '\n'); |
240 | |
|
241 | 0 | stream_putc(s, '['); |
242 | 0 | for (i = 0; i < pvalue->value.ia.size; ++i) { |
243 | 0 | pprintd1(s, "%d", pvalue->value.ia.data[i]); |
244 | 0 | stream_putc(s, sepr); |
245 | 0 | } |
246 | 0 | stream_putc(s, ']'); |
247 | 0 | } |
248 | 0 | break; |
249 | 0 | case gs_param_type_float_array: |
250 | 0 | { |
251 | 0 | uint i; |
252 | 0 | char sepr = (pvalue->value.fa.size <= 10 ? ' ' : '\n'); |
253 | |
|
254 | 0 | stream_putc(s, '['); |
255 | 0 | for (i = 0; i < pvalue->value.fa.size; ++i) { |
256 | 0 | pprintg1(s, "%g", pvalue->value.fa.data[i]); |
257 | 0 | stream_putc(s, sepr); |
258 | 0 | } |
259 | 0 | stream_putc(s, ']'); |
260 | 0 | } |
261 | 0 | break; |
262 | | /*case gs_param_type_string_array: */ |
263 | | /*case gs_param_type_name_array: */ |
264 | 0 | default: |
265 | 0 | return_error(gs_error_typecheck); |
266 | 0 | } |
267 | 0 | if (prlist->params.item_suffix) |
268 | 0 | stream_puts(s, prlist->params.item_suffix); |
269 | 0 | return 0; |
270 | 0 | } |