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