1 /* Copyright (C) 2001-2006 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, modified
8 or distributed except as expressly authorized under the terms of that
9 license. Refer to licensing information at http://www.artifex.com/
10 or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11 San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
12 */
13
14 /* $Id: spsdf.c 8250 2007-09-25 13:31:24Z giles $ */
15 /* Common utilities for PostScript and PDF format printing */
16 #include "stdio_.h" /* for stream.h */
17 #include "string_.h"
18 #include "gstypes.h"
19 #include "gsmemory.h"
20 #include "gserror.h"
21 #include "gserrors.h"
22 #include "spprint.h"
23 #include "spsdf.h"
24 #include "stream.h"
25 #include "strimpl.h"
26 #include "sa85x.h"
27 #include "sstring.h"
28 #include "scanchar.h"
29
30 /*
31 * Write a string in its shortest form ( () or <> ). Note that
32 * this form is different depending on whether binary data are allowed.
33 * Currently we don't support ASCII85 strings ( <~ ~> ).
34 */
35 void
s_write_ps_string(stream * s,const byte * str,uint size,int print_ok)36 s_write_ps_string(stream * s, const byte * str, uint size, int print_ok)
37 {
38 uint added = 0;
39 uint i;
40 const stream_template *template;
41 stream_AXE_state state;
42 stream_state *st = NULL;
43
44 if (print_ok & PRINT_BINARY_OK) {
45 /* Only need to escape (, ), \, CR, EOL. */
46 stream_putc(s, '(');
47 for (i = 0; i < size; ++i) {
48 byte ch = str[i];
49
50 switch (ch) {
51 case char_CR:
52 stream_puts(s, "\\r");
53 continue;
54 case char_EOL:
55 stream_puts(s, "\\n");
56 continue;
57 case '(':
58 case ')':
59 case '\\':
60 stream_putc(s, '\\');
61 }
62 stream_putc(s, ch);
63 }
64 stream_putc(s, ')');
65 return;
66 }
67 for (i = 0; i < size; ++i) {
68 byte ch = str[i];
69
70 if (ch == 0 || ch >= 127)
71 added += 3;
72 else if (strchr("()\\\n\r\t\b\f", ch) != 0)
73 ++added;
74 else if (ch < 32)
75 added += 3;
76 }
77
78 if (added < size || (print_ok & PRINT_HEX_NOT_OK)) {
79 /* More efficient, or mandatory, to represent as PostScript string. */
80 template = &s_PSSE_template;
81 stream_putc(s, '(');
82 } else {
83 /* More efficient, and permitted, to represent as hex string. */
84 template = &s_AXE_template;
85 st = (stream_state *) & state;
86 s_AXE_init_inline(&state);
87 stream_putc(s, '<');
88 }
89
90 {
91 byte buf[100]; /* size is arbitrary */
92 stream_cursor_read r;
93 stream_cursor_write w;
94 int status;
95
96 r.ptr = str - 1;
97 r.limit = r.ptr + size;
98 w.limit = buf + sizeof(buf) - 1;
99 do {
100 /* One picky compiler complains if we initialize to buf - 1. */
101 w.ptr = buf; w.ptr--;
102 status = (*template->process) (st, &r, &w, true);
103 stream_write(s, buf, (uint) (w.ptr + 1 - buf));
104 }
105 while (status == 1);
106 }
107 }
108
109 /* Set up a write stream that just keeps track of the position. */
110 int
s_alloc_position_stream(stream ** ps,gs_memory_t * mem)111 s_alloc_position_stream(stream ** ps, gs_memory_t * mem)
112 {
113 stream *s = *ps = s_alloc(mem, "s_alloc_position_stream");
114
115 if (s == 0)
116 return_error(gs_error_VMerror);
117 swrite_position_only(s);
118 return 0;
119 }
120
121 /* ---------------- Parameter printing ---------------- */
122
123 private_st_printer_param_list();
124 const param_printer_params_t param_printer_params_default = {
125 param_printer_params_default_values
126 };
127
128 /* We'll implement the other printers later if we have to. */
129 static param_proc_xmit_typed(param_print_typed);
130 /*static param_proc_begin_xmit_collection(param_print_begin_collection);*/
131 /*static param_proc_end_xmit_collection(param_print_end_collection);*/
132 static const gs_param_list_procs printer_param_list_procs = {
133 param_print_typed,
134 NULL /* begin_collection */ ,
135 NULL /* end_collection */ ,
136 NULL /* get_next_key */ ,
137 gs_param_request_default,
138 gs_param_requested_default
139 };
140
141 int
s_init_param_printer(printer_param_list_t * prlist,const param_printer_params_t * ppp,stream * s)142 s_init_param_printer(printer_param_list_t *prlist,
143 const param_printer_params_t * ppp, stream * s)
144 {
145 gs_param_list_init((gs_param_list *)prlist, &printer_param_list_procs,
146 NULL);
147 prlist->strm = s;
148 prlist->params = *ppp;
149 prlist->any = false;
150 return 0;
151 }
152 int
s_alloc_param_printer(gs_param_list ** pplist,const param_printer_params_t * ppp,stream * s,gs_memory_t * mem)153 s_alloc_param_printer(gs_param_list ** pplist,
154 const param_printer_params_t * ppp, stream * s,
155 gs_memory_t * mem)
156 {
157 printer_param_list_t *prlist =
158 gs_alloc_struct(mem, printer_param_list_t, &st_printer_param_list,
159 "s_alloc_param_printer");
160 int code;
161
162 *pplist = (gs_param_list *)prlist;
163 if (prlist == 0)
164 return_error(gs_error_VMerror);
165 code = s_init_param_printer(prlist, ppp, s);
166 prlist->memory = mem;
167 return code;
168 }
169
170 void
s_release_param_printer(printer_param_list_t * prlist)171 s_release_param_printer(printer_param_list_t *prlist)
172 {
173 if (prlist) {
174 if (prlist->any && prlist->params.suffix)
175 stream_puts(prlist->strm, prlist->params.suffix);
176 }
177 }
178 void
s_free_param_printer(gs_param_list * plist)179 s_free_param_printer(gs_param_list * plist)
180 {
181 if (plist) {
182 printer_param_list_t *const prlist = (printer_param_list_t *) plist;
183
184 s_release_param_printer(prlist);
185 gs_free_object(prlist->memory, plist, "s_free_param_printer");
186 }
187 }
188
189 static int
param_print_typed(gs_param_list * plist,gs_param_name pkey,gs_param_typed_value * pvalue)190 param_print_typed(gs_param_list * plist, gs_param_name pkey,
191 gs_param_typed_value * pvalue)
192 {
193 printer_param_list_t *const prlist = (printer_param_list_t *)plist;
194 stream *s = prlist->strm;
195
196 if (!prlist->any) {
197 if (prlist->params.prefix)
198 stream_puts(s, prlist->params.prefix);
199 prlist->any = true;
200 }
201 if (prlist->params.item_prefix)
202 stream_puts(s, prlist->params.item_prefix);
203 pprints1(s, "/%s", pkey);
204 switch (pvalue->type) {
205 case gs_param_type_null:
206 stream_puts(s, " null");
207 break;
208 case gs_param_type_bool:
209 stream_puts(s, (pvalue->value.b ? " true" : " false"));
210 break;
211 case gs_param_type_int:
212 pprintd1(s, " %d", pvalue->value.i);
213 break;
214 case gs_param_type_long:
215 pprintld1(s, " %l", pvalue->value.l);
216 break;
217 case gs_param_type_float:
218 pprintg1(s, " %g", pvalue->value.f);
219 break;
220 case gs_param_type_string:
221 s_write_ps_string(s, pvalue->value.s.data, pvalue->value.s.size,
222 prlist->params.print_ok);
223 break;
224 case gs_param_type_name:
225 /****** SHOULD USE #-ESCAPES FOR PDF ******/
226 stream_putc(s, '/');
227 stream_write(s, pvalue->value.n.data, pvalue->value.n.size);
228 break;
229 case gs_param_type_int_array:
230 {
231 uint i;
232 char sepr = (pvalue->value.ia.size <= 10 ? ' ' : '\n');
233
234 stream_putc(s, '[');
235 for (i = 0; i < pvalue->value.ia.size; ++i) {
236 pprintd1(s, "%d", pvalue->value.ia.data[i]);
237 stream_putc(s, sepr);
238 }
239 stream_putc(s, ']');
240 }
241 break;
242 case gs_param_type_float_array:
243 {
244 uint i;
245 char sepr = (pvalue->value.fa.size <= 10 ? ' ' : '\n');
246
247 stream_putc(s, '[');
248 for (i = 0; i < pvalue->value.fa.size; ++i) {
249 pprintg1(s, "%g", pvalue->value.fa.data[i]);
250 stream_putc(s, sepr);
251 }
252 stream_putc(s, ']');
253 }
254 break;
255 /*case gs_param_type_string_array: */
256 /*case gs_param_type_name_array: */
257 default:
258 return_error(gs_error_typecheck);
259 }
260 if (prlist->params.item_suffix)
261 stream_puts(s, prlist->params.item_suffix);
262 return 0;
263 }
264