/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 | } |