1 /* Copyright (C) 2001-2012 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., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
13 CA 94903, 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
s_write_ps_string(stream * s,const byte * str,uint size,int print_ok)37 s_write_ps_string(stream * s, const byte * str, uint size, int print_ok)
38 {
39 uint added = 0;
40 uint i;
41 const stream_template *templat;
42 stream_AXE_state state;
43 stream_state *st = NULL;
44
45 if (print_ok & PRINT_BINARY_OK) {
46 /* Only need to escape (, ), \, CR, EOL. */
47 stream_putc(s, '(');
48 for (i = 0; i < size; ++i) {
49 byte ch = str[i];
50
51 switch (ch) {
52 case char_CR:
53 stream_puts(s, "\\r");
54 continue;
55 case char_EOL:
56 stream_puts(s, "\\n");
57 continue;
58 case '(':
59 case ')':
60 case '\\':
61 stream_putc(s, '\\');
62 }
63 stream_putc(s, ch);
64 }
65 stream_putc(s, ')');
66 return;
67 }
68 for (i = 0; i < size; ++i) {
69 byte ch = str[i];
70
71 if (ch == 0 || ch >= 127)
72 added += 3;
73 else if (strchr("()\\\n\r\t\b\f", ch) != 0)
74 ++added;
75 else if (ch < 32)
76 added += 3;
77 }
78
79 if (added < size || (print_ok & PRINT_HEX_NOT_OK)) {
80 /* More efficient, or mandatory, to represent as PostScript string. */
81 templat = &s_PSSE_template;
82 stream_putc(s, '(');
83 } else {
84 /* More efficient, and permitted, to represent as hex string. */
85 templat = &s_AXE_template;
86 st = (stream_state *) & state;
87 s_AXE_init_inline(&state);
88 stream_putc(s, '<');
89 }
90
91 {
92 byte buf[100]; /* size is arbitrary */
93 stream_cursor_read r;
94 stream_cursor_write w;
95 int status;
96
97 r.ptr = str - 1;
98 r.limit = r.ptr + size;
99 w.limit = buf + sizeof(buf) - 1;
100 do {
101 /* One picky compiler complains if we initialize to buf - 1. */
102 w.ptr = buf; w.ptr--;
103 status = (*templat->process) (st, &r, &w, true);
104 stream_write(s, buf, (uint) (w.ptr + 1 - buf));
105 }
106 while (status == 1);
107 }
108 }
109
110 /* Set up a write stream that just keeps track of the position. */
111 int
s_alloc_position_stream(stream ** ps,gs_memory_t * mem)112 s_alloc_position_stream(stream ** ps, gs_memory_t * mem)
113 {
114 stream *s = *ps = s_alloc(mem, "s_alloc_position_stream");
115
116 if (s == 0)
117 return_error(gs_error_VMerror);
118 swrite_position_only(s);
119 return 0;
120 }
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
s_init_param_printer(printer_param_list_t * prlist,const param_printer_params_t * ppp,stream * s)143 s_init_param_printer(printer_param_list_t *prlist,
144 const param_printer_params_t * ppp, stream * s)
145 {
146 gs_param_list_init((gs_param_list *)prlist, &printer_param_list_procs,
147 NULL);
148 prlist->strm = s;
149 prlist->params = *ppp;
150 prlist->any = false;
151 return 0;
152 }
153 int
s_alloc_param_printer(gs_param_list ** pplist,const param_printer_params_t * ppp,stream * s,gs_memory_t * mem)154 s_alloc_param_printer(gs_param_list ** pplist,
155 const param_printer_params_t * ppp, stream * s,
156 gs_memory_t * mem)
157 {
158 printer_param_list_t *prlist =
159 gs_alloc_struct(mem, printer_param_list_t, &st_printer_param_list,
160 "s_alloc_param_printer");
161 int code;
162
163 *pplist = (gs_param_list *)prlist;
164 if (prlist == 0)
165 return_error(gs_error_VMerror);
166 code = s_init_param_printer(prlist, ppp, s);
167 prlist->memory = mem;
168 return code;
169 }
170
171 void
s_release_param_printer(printer_param_list_t * prlist)172 s_release_param_printer(printer_param_list_t *prlist)
173 {
174 if (prlist) {
175 if (prlist->any && prlist->params.suffix)
176 stream_puts(prlist->strm, prlist->params.suffix);
177 }
178 }
179 void
s_free_param_printer(gs_param_list * plist)180 s_free_param_printer(gs_param_list * plist)
181 {
182 if (plist) {
183 printer_param_list_t *const prlist = (printer_param_list_t *) plist;
184
185 s_release_param_printer(prlist);
186 gs_free_object(prlist->memory, plist, "s_free_param_printer");
187 }
188 }
189
190 static int
param_print_typed(gs_param_list * plist,gs_param_name pkey,gs_param_typed_value * pvalue)191 param_print_typed(gs_param_list * plist, gs_param_name pkey,
192 gs_param_typed_value * pvalue)
193 {
194 printer_param_list_t *const prlist = (printer_param_list_t *)plist;
195 stream *s = prlist->strm;
196
197 if (!prlist->any) {
198 if (prlist->params.prefix)
199 stream_puts(s, prlist->params.prefix);
200 prlist->any = true;
201 }
202 if (prlist->params.item_prefix)
203 stream_puts(s, prlist->params.item_prefix);
204 pprints1(s, "/%s", pkey);
205 switch (pvalue->type) {
206 case gs_param_type_null:
207 stream_puts(s, " null");
208 break;
209 case gs_param_type_bool:
210 stream_puts(s, (pvalue->value.b ? " true" : " false"));
211 break;
212 case gs_param_type_int:
213 pprintd1(s, " %d", pvalue->value.i);
214 break;
215 case gs_param_type_long:
216 pprintld1(s, " %l", pvalue->value.l);
217 break;
218 case gs_param_type_float:
219 pprintg1(s, " %g", pvalue->value.f);
220 break;
221 case gs_param_type_string:
222 s_write_ps_string(s, pvalue->value.s.data, pvalue->value.s.size,
223 prlist->params.print_ok);
224 break;
225 case gs_param_type_name:
226 /****** SHOULD USE #-ESCAPES FOR PDF ******/
227 stream_putc(s, '/');
228 stream_write(s, pvalue->value.n.data, pvalue->value.n.size);
229 break;
230 case gs_param_type_int_array:
231 {
232 uint i;
233 char sepr = (pvalue->value.ia.size <= 10 ? ' ' : '\n');
234
235 stream_putc(s, '[');
236 for (i = 0; i < pvalue->value.ia.size; ++i) {
237 pprintd1(s, "%d", pvalue->value.ia.data[i]);
238 stream_putc(s, sepr);
239 }
240 stream_putc(s, ']');
241 }
242 break;
243 case gs_param_type_float_array:
244 {
245 uint i;
246 char sepr = (pvalue->value.fa.size <= 10 ? ' ' : '\n');
247
248 stream_putc(s, '[');
249 for (i = 0; i < pvalue->value.fa.size; ++i) {
250 pprintg1(s, "%g", pvalue->value.fa.data[i]);
251 stream_putc(s, sepr);
252 }
253 stream_putc(s, ']');
254 }
255 break;
256 /*case gs_param_type_string_array: */
257 /*case gs_param_type_name_array: */
258 default:
259 return_error(gs_error_typecheck);
260 }
261 if (prlist->params.item_suffix)
262 stream_puts(s, prlist->params.item_suffix);
263 return 0;
264 }
265