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: gschar.c,v 1.6 2002/06/16 05:48:55 lpd Exp $ */
18 /* Character writing "operators" for Ghostscript library */
19 #include "gx.h"
20 #include "gserrors.h"
21 #include "gsstruct.h"
22 #include "gsmatrix.h" /* for gscoord.h */
23 #include "gscoord.h" /* for gs_idtransform */
24 #include "gzstate.h"
25 #include "gxdevice.h"
26 #include "gxdevmem.h"
27 #include "gxchar.h"
28 #include "gxfont.h"
29
30 /* Forward declarations */
31 private int show_n_begin(gs_show_enum *penum, gs_state *pgs, int code,
32 gs_text_enum_t *pte);
33
34 /* Structure descriptors */
35 extern_st(st_gs_show_enum);
36
37 /* ------ String writing operators ------ */
38
39 /* Free the contents of a show enumerator. */
40 void
gs_show_enum_release(gs_show_enum * penum,gs_memory_t * emem)41 gs_show_enum_release(gs_show_enum * penum, gs_memory_t * emem)
42 {
43 if (penum->text.operation) /* otherwise, never initialized */
44 penum->procs->release((gs_text_enum_t *)penum, "gs_show_enum_release");
45 if (emem != 0)
46 gs_free_object(emem, penum, "gs_show_enum_release");
47 }
48
49 /* show[_n] */
50 int
gs_show_n_init(gs_show_enum * penum,gs_state * pgs,const char * str,uint size)51 gs_show_n_init(gs_show_enum * penum, gs_state * pgs,
52 const char *str, uint size)
53 {
54 gs_text_enum_t *pte;
55 int code = gs_show_begin(pgs, (const byte *)str, size, pgs->memory, &pte);
56
57 return show_n_begin(penum, pgs, code, pte);
58 }
59
60 /* ashow[_n] */
61 int
gs_ashow_n_init(gs_show_enum * penum,gs_state * pgs,floatp ax,floatp ay,const char * str,uint size)62 gs_ashow_n_init(gs_show_enum * penum, gs_state * pgs,
63 floatp ax, floatp ay, const char *str, uint size)
64 {
65 gs_text_enum_t *pte;
66 int code = gs_ashow_begin(pgs, ax, ay, (const byte *)str, size,
67 pgs->memory, &pte);
68
69 return show_n_begin(penum, pgs, code, pte);
70 }
71
72 /* widthshow[_n] */
73 int
gs_widthshow_n_init(gs_show_enum * penum,gs_state * pgs,floatp cx,floatp cy,gs_char chr,const char * str,uint size)74 gs_widthshow_n_init(gs_show_enum * penum, gs_state * pgs,
75 floatp cx, floatp cy, gs_char chr,
76 const char *str, uint size)
77 {
78 gs_text_enum_t *pte;
79 int code = gs_widthshow_begin(pgs, cx, cy, chr, (const byte *)str, size,
80 pgs->memory, &pte);
81
82 return show_n_begin(penum, pgs, code, pte);
83 }
84
85 /* awidthshow[_n] */
86 int
gs_awidthshow_n_init(gs_show_enum * penum,gs_state * pgs,floatp cx,floatp cy,gs_char chr,floatp ax,floatp ay,const char * str,uint size)87 gs_awidthshow_n_init(gs_show_enum * penum, gs_state * pgs,
88 floatp cx, floatp cy, gs_char chr, floatp ax, floatp ay,
89 const char *str, uint size)
90 {
91 gs_text_enum_t *pte;
92 int code = gs_awidthshow_begin(pgs, cx, cy, chr, ax, ay,
93 (const byte *)str, size, pgs->memory, &pte);
94
95 return show_n_begin(penum, pgs, code, pte);
96 }
97
98 /* kshow[_n] */
99 int
gs_kshow_n_init(gs_show_enum * penum,gs_state * pgs,const char * str,uint size)100 gs_kshow_n_init(gs_show_enum * penum,
101 gs_state * pgs, const char *str, uint size)
102 {
103 gs_text_enum_t *pte;
104 int code;
105
106 switch (pgs->font->FontType) {
107 case ft_composite:
108 case ft_CID_encrypted:
109 case ft_CID_user_defined:
110 case ft_CID_TrueType:
111 case ft_CID_bitmap:
112 return_error(gs_error_invalidfont);
113 default:
114 break;
115 }
116 code = gs_kshow_begin(pgs, (const byte *)str, size, pgs->memory, &pte);
117 return show_n_begin(penum, pgs, code, pte);
118 }
119
120 /* xyshow[_n] */
121 int
gs_xyshow_n_init(gs_show_enum * penum,gs_state * pgs,const char * str,uint size)122 gs_xyshow_n_init(gs_show_enum * penum,
123 gs_state * pgs, const char *str, uint size)
124 {
125 gs_text_enum_t *pte;
126 int code = gs_xyshow_begin(pgs, (const byte *)str, size, NULL, NULL, 0,
127 pgs->memory, &pte);
128
129 return show_n_begin(penum, pgs, code, pte);
130 }
131
132 /* glyphshow */
133 int
gs_glyphshow_init(gs_show_enum * penum,gs_state * pgs,gs_glyph glyph)134 gs_glyphshow_init(gs_show_enum * penum, gs_state * pgs, gs_glyph glyph)
135 {
136 gs_text_enum_t *pte;
137 int code = gs_glyphshow_begin(pgs, glyph, pgs->memory, &pte);
138
139 return show_n_begin(penum, pgs, code, pte);
140 }
141 int
gs_glyphpath_init(gs_show_enum * penum,gs_state * pgs,gs_glyph glyph,bool stroke_path)142 gs_glyphpath_init(gs_show_enum * penum, gs_state * pgs, gs_glyph glyph,
143 bool stroke_path)
144 {
145 gs_text_enum_t *pte;
146 int code = gs_glyphpath_begin(pgs, glyph, stroke_path, pgs->memory, &pte);
147
148 return show_n_begin(penum, pgs, code, pte);
149 }
150 int
gs_glyphwidth_init(gs_show_enum * penum,gs_state * pgs,gs_glyph glyph)151 gs_glyphwidth_init(gs_show_enum * penum, gs_state * pgs, gs_glyph glyph)
152 {
153 gs_text_enum_t *pte;
154 int code = gs_glyphwidth_begin(pgs, glyph, pgs->memory, &pte);
155
156 return show_n_begin(penum, pgs, code, pte);
157 }
158
159 /* ------ Related operators ------ */
160
161 /* cshow[_n] */
162 int
gs_cshow_n_init(gs_show_enum * penum,gs_state * pgs,const char * str,uint size)163 gs_cshow_n_init(gs_show_enum * penum,
164 gs_state * pgs, const char *str, uint size)
165 {
166 gs_text_enum_t *pte;
167 int code = gs_cshow_begin(pgs, (const byte *)str, size, pgs->memory, &pte);
168
169 return show_n_begin(penum, pgs, code, pte);
170 }
171
172 /* stringwidth[_n] */
173 int
gs_stringwidth_n_init(gs_show_enum * penum,gs_state * pgs,const char * str,uint size)174 gs_stringwidth_n_init(gs_show_enum * penum, gs_state * pgs,
175 const char *str, uint size)
176 {
177 gs_text_enum_t *pte;
178 int code = gs_stringwidth_begin(pgs, (const byte *)str, size,
179 pgs->memory, &pte);
180
181 return show_n_begin(penum, pgs, code, pte);
182 }
183
184 /* charpath[_n] */
185 int
gs_charpath_n_init(gs_show_enum * penum,gs_state * pgs,const char * str,uint size,bool stroke_path)186 gs_charpath_n_init(gs_show_enum * penum, gs_state * pgs,
187 const char *str, uint size, bool stroke_path)
188 {
189 gs_text_enum_t *pte;
190 int code = gs_charpath_begin(pgs, (const byte *)str, size, stroke_path,
191 pgs->memory, &pte);
192
193 return show_n_begin(penum, pgs, code, pte);
194 }
195
196 /* charboxpath[_n] */
197 int
gs_charboxpath_n_init(gs_show_enum * penum,gs_state * pgs,const char * str,uint size,bool use_boxes)198 gs_charboxpath_n_init(gs_show_enum * penum, gs_state * pgs,
199 const char *str, uint size, bool use_boxes)
200 {
201 gs_text_enum_t *pte;
202 int code = gs_charboxpath_begin(pgs, (const byte *)str, size, use_boxes,
203 pgs->memory, &pte);
204
205 return show_n_begin(penum, pgs, code, pte);
206 }
207
208 /* ------ Width/cache operators ------ */
209
210 /* setcachedevice */
211 /* The elements of pw are: wx, wy, llx, lly, urx, ury. */
212 /* Note that this returns 1 if we just set up the cache device. */
213 int
gs_setcachedevice_double(gs_show_enum * penum,gs_state * pgs,const double * pw)214 gs_setcachedevice_double(gs_show_enum *penum, gs_state *pgs, const double *pw)
215 {
216 if (penum->pgs != pgs)
217 return_error(gs_error_rangecheck);
218 return gs_text_setcachedevice((gs_text_enum_t *)penum, pw);
219 }
220 /* The _float procedure is strictly for backward compatibility. */
221 int
gs_setcachedevice_float(gs_show_enum * penum,gs_state * pgs,const float * pw)222 gs_setcachedevice_float(gs_show_enum * penum, gs_state * pgs, const float *pw)
223 {
224 double w[6];
225 int i;
226
227 for (i = 0; i < 6; ++i)
228 w[i] = pw[i];
229 return gs_setcachedevice_double(penum, pgs, w);
230 }
231
232 /* setcachedevice2 */
233 /* The elements of pw2 are: w0x, w0y, llx, lly, urx, ury, w1x, w1y, vx, vy. */
234 /* Note that this returns 1 if we just set up the cache device. */
235 int
gs_setcachedevice2_double(gs_show_enum * penum,gs_state * pgs,const double * pw2)236 gs_setcachedevice2_double(gs_show_enum * penum, gs_state * pgs,
237 const double *pw2)
238 {
239 if (penum->pgs != pgs)
240 return_error(gs_error_rangecheck);
241 return gs_text_setcachedevice2((gs_text_enum_t *)penum, pw2);
242 }
243 /* The _float procedure is strictly for backward compatibility. */
244 int
gs_setcachedevice2_float(gs_show_enum * penum,gs_state * pgs,const float * pw2)245 gs_setcachedevice2_float(gs_show_enum * penum, gs_state * pgs, const float *pw2)
246 {
247 double w2[10];
248 int i;
249
250 for (i = 0; i < 10; ++i)
251 w2[i] = pw2[i];
252 return gs_setcachedevice2_double(penum, pgs, w2);
253 }
254
255 /* setcharwidth */
256 /* Note that this returns 1 if the current show operation is */
257 /* non-displaying (stringwidth or cshow). */
258 int
gs_setcharwidth(gs_show_enum * penum,gs_state * pgs,floatp wx,floatp wy)259 gs_setcharwidth(gs_show_enum * penum, gs_state * pgs,
260 floatp wx, floatp wy)
261 {
262 double w[2];
263
264 if (penum->pgs != pgs)
265 return_error(gs_error_rangecheck);
266 w[0] = wx, w[1] = wy;
267 return gs_text_setcharwidth((gs_text_enum_t *)penum, w);
268 }
269
270 /* ------ Enumerator ------ */
271
272 /* Do the next step of a show (or stringwidth) operation */
273 int
gs_show_next(gs_show_enum * penum)274 gs_show_next(gs_show_enum * penum)
275 {
276 return gs_text_process((gs_text_enum_t *)penum);
277 }
278
279 /*
280 * Return true if we only need the width from the rasterizer
281 * and can short-circuit the full rendering of the character,
282 * false if we need the actual character bits.
283 */
284 bool
gs_show_width_only(const gs_show_enum * penum)285 gs_show_width_only(const gs_show_enum * penum)
286 {
287 return gs_text_is_width_only((const gs_text_enum_t *)penum);
288 }
289
290 /* ------ Accessors ------ */
291
292 /* Return the current character for rendering. */
293 gs_char
gs_show_current_char(const gs_show_enum * penum)294 gs_show_current_char(const gs_show_enum * penum)
295 {
296 return gs_text_current_char((const gs_text_enum_t *)penum);
297 }
298
299 /* Return the current glyph for rendering. */
300 gs_glyph
gs_show_current_glyph(const gs_show_enum * penum)301 gs_show_current_glyph(const gs_show_enum * penum)
302 {
303 return gs_text_current_glyph((const gs_text_enum_t *)penum);
304 }
305
306 /* Return the width of the just-enumerated character (for cshow). */
307 int
gs_show_current_width(const gs_show_enum * penum,gs_point * ppt)308 gs_show_current_width(const gs_show_enum * penum, gs_point * ppt)
309 {
310 return gs_text_current_width((const gs_text_enum_t *)penum, ppt);
311 }
312
313 /* Return the just-displayed character for kerning. */
314 gs_char
gs_kshow_previous_char(const gs_show_enum * penum)315 gs_kshow_previous_char(const gs_show_enum * penum)
316 {
317 return gs_text_current_char((const gs_text_enum_t *)penum);
318 }
319
320 /* Return the about-to-be-displayed character for kerning. */
321 gs_char
gs_kshow_next_char(const gs_show_enum * penum)322 gs_kshow_next_char(const gs_show_enum * penum)
323 {
324 return penum->text.data.bytes[penum->index];
325 }
326
327 /* Return the accumulated width for stringwidth. */
328 void
gs_show_width(const gs_show_enum * penum,gs_point * ppt)329 gs_show_width(const gs_show_enum * penum, gs_point * ppt)
330 {
331 gs_text_total_width((const gs_text_enum_t *)penum, ppt);
332 }
333
334 /* ------ Internal routines ------ */
335
336 /*
337 * Force the enumerator to be a gs_show_enum *, which the current
338 * implementation code requires.
339 */
340 private int
show_n_begin(gs_show_enum * penum,gs_state * pgs,int code,gs_text_enum_t * pte)341 show_n_begin(gs_show_enum *penum, gs_state *pgs, int code, gs_text_enum_t *pte)
342 {
343 if (code < 0)
344 return code;
345 if (gs_object_type(pgs->memory, pte) != &st_gs_show_enum) {
346 /* Use the default implementation. */
347 gx_device *dev = pgs->device;
348 gs_text_params_t text;
349 gs_memory_t *mem = pte->memory;
350 dev_proc_text_begin((*text_begin)) = dev_proc(dev, text_begin);
351
352 text = pte->text;
353 gs_text_release(pte, "show_n_begin");
354 /* Temporarily reset the text_begin procedure to the default. */
355 set_dev_proc(dev, text_begin, gx_default_text_begin);
356 code = gs_text_begin(pgs, &text, mem, &pte);
357 set_dev_proc(dev, text_begin, text_begin);
358 if (code < 0)
359 return code;
360 }
361 /* Now we know pte points to a gs_show_enum. */
362 *penum = *(gs_show_enum *)pte;
363 gs_free_object(pgs->memory, pte, "show_n_begin");
364 return code;
365 }
366