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