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 /* Character writing "operators" for Ghostscript library */
18 #include "gx.h"
19 #include "gserrors.h"
20 #include "gsstruct.h"
21 #include "gsmatrix.h" /* for gscoord.h */
22 #include "gscoord.h" /* for gs_idtransform */
23 #include "gzstate.h"
24 #include "gxdevice.h"
25 #include "gxdevmem.h"
26 #include "gxchar.h"
27 #include "gxfont.h"
28
29 /* Structure descriptors */
30 extern_st(st_gs_show_enum);
31
32 /* ------ String writing operators ------ */
33
34 /* Free the contents of a show enumerator. */
35 void
gs_show_enum_release(gs_show_enum * penum,gs_memory_t * emem)36 gs_show_enum_release(gs_show_enum * penum, gs_memory_t * emem)
37 {
38 if (penum->text.operation) /* otherwise, never initialized */
39 penum->procs->release((gs_text_enum_t *)penum, "gs_show_enum_release");
40 if (emem != 0)
41 gs_free_object(emem, penum, "gs_show_enum_release");
42 }
43
44 /* ------ Width/cache operators ------ */
45
46 /* setcachedevice */
47 /* The elements of pw are: wx, wy, llx, lly, urx, ury. */
48 /* Note that this returns 1 if we just set up the cache device. */
49 int
gs_setcachedevice_double(gs_show_enum * penum,gs_state * pgs,const double * pw)50 gs_setcachedevice_double(gs_show_enum *penum, gs_state *pgs, const double *pw)
51 {
52 if (penum->pgs != pgs)
53 return_error(gs_error_rangecheck);
54 return gs_text_setcachedevice((gs_text_enum_t *)penum, pw);
55 }
56 /* The _float procedure is strictly for backward compatibility. */
57 int
gs_setcachedevice_float(gs_show_enum * penum,gs_state * pgs,const float * pw)58 gs_setcachedevice_float(gs_show_enum * penum, gs_state * pgs, const float *pw)
59 {
60 double w[6];
61 int i;
62
63 for (i = 0; i < 6; ++i)
64 w[i] = pw[i];
65 return gs_setcachedevice_double(penum, pgs, w);
66 }
67
68 /* setcachedevice2 */
69 /* The elements of pw2 are: w0x, w0y, llx, lly, urx, ury, w1x, w1y, vx, vy. */
70 /* Note that this returns 1 if we just set up the cache device. */
71 int
gs_setcachedevice2_double(gs_show_enum * penum,gs_state * pgs,const double * pw2)72 gs_setcachedevice2_double(gs_show_enum * penum, gs_state * pgs,
73 const double *pw2)
74 {
75 if (penum->pgs != pgs)
76 return_error(gs_error_rangecheck);
77 return gs_text_setcachedevice2((gs_text_enum_t *)penum, pw2);
78 }
79 /* The _float procedure is strictly for backward compatibility. */
80 int
gs_setcachedevice2_float(gs_show_enum * penum,gs_state * pgs,const float * pw2)81 gs_setcachedevice2_float(gs_show_enum * penum, gs_state * pgs, const float *pw2)
82 {
83 double w2[10];
84 int i;
85
86 for (i = 0; i < 10; ++i)
87 w2[i] = pw2[i];
88 return gs_setcachedevice2_double(penum, pgs, w2);
89 }
90
91 /* setcharwidth */
92 /* Note that this returns 1 if the current show operation is */
93 /* non-displaying (stringwidth or cshow). */
94 int
gs_setcharwidth(gs_show_enum * penum,gs_state * pgs,floatp wx,floatp wy)95 gs_setcharwidth(gs_show_enum * penum, gs_state * pgs,
96 floatp wx, floatp wy)
97 {
98 double w[2];
99
100 if (penum->pgs != pgs)
101 return_error(gs_error_rangecheck);
102 w[0] = wx, w[1] = wy;
103 return gs_text_setcharwidth((gs_text_enum_t *)penum, w);
104 }
105
106 /* ------ Enumerator ------ */
107
108 /* Do the next step of a show (or stringwidth) operation */
109 int
gs_show_next(gs_show_enum * penum)110 gs_show_next(gs_show_enum * penum)
111 {
112 return gs_text_process((gs_text_enum_t *)penum);
113 }
114
115 /*
116 * Return true if we only need the width from the rasterizer
117 * and can short-circuit the full rendering of the character,
118 * false if we need the actual character bits.
119 */
120 bool
gs_show_width_only(const gs_show_enum * penum)121 gs_show_width_only(const gs_show_enum * penum)
122 {
123 return gs_text_is_width_only((const gs_text_enum_t *)penum);
124 }
125
126 /* ------ Accessors ------ */
127
128 /* Return the current character for rendering. */
129 gs_char
gs_show_current_char(const gs_show_enum * penum)130 gs_show_current_char(const gs_show_enum * penum)
131 {
132 return gs_text_current_char((const gs_text_enum_t *)penum);
133 }
134
135 /* Return the current glyph for rendering. */
136 gs_glyph
gs_show_current_glyph(const gs_show_enum * penum)137 gs_show_current_glyph(const gs_show_enum * penum)
138 {
139 return gs_text_current_glyph((const gs_text_enum_t *)penum);
140 }
141
142 /* Return the width of the just-enumerated character (for cshow). */
143 int
gs_show_current_width(const gs_show_enum * penum,gs_point * ppt)144 gs_show_current_width(const gs_show_enum * penum, gs_point * ppt)
145 {
146 return gs_text_current_width((const gs_text_enum_t *)penum, ppt);
147 }
148
149 /* Return the just-displayed character for kerning. */
150 gs_char
gs_kshow_previous_char(const gs_show_enum * penum)151 gs_kshow_previous_char(const gs_show_enum * penum)
152 {
153 return gs_text_current_char((const gs_text_enum_t *)penum);
154 }
155
156 /* Return the about-to-be-displayed character for kerning. */
157 gs_char
gs_kshow_next_char(const gs_show_enum * penum)158 gs_kshow_next_char(const gs_show_enum * penum)
159 {
160 return penum->text.data.bytes[penum->index];
161 }
162
163 /* Return the accumulated width for stringwidth. */
164 void
gs_show_width(const gs_show_enum * penum,gs_point * ppt)165 gs_show_width(const gs_show_enum * penum, gs_point * ppt)
166 {
167 gs_text_total_width((const gs_text_enum_t *)penum, ppt);
168 }
169
170 /* ------ Internal routines ------ */
171
172 #if 0
173 /*
174 * Force the enumerator to be a gs_show_enum *, which the current
175 * implementation code requires.
176 */
177 static int
178 show_n_begin(gs_show_enum *penum, gs_state *pgs, int code, gs_text_enum_t *pte)
179 {
180 if (code < 0)
181 return code;
182 if (gs_object_type(pgs->memory, pte) != &st_gs_show_enum) {
183 /* Use the default implementation. */
184 gx_device *dev = pgs->device;
185 gs_text_params_t text;
186 gs_memory_t *mem = pte->memory;
187 dev_proc_text_begin((*text_begin)) = dev_proc(dev, text_begin);
188
189 text = pte->text;
190 gs_text_release(pte, "show_n_begin");
191 /* Temporarily reset the text_begin procedure to the default. */
192 set_dev_proc(dev, text_begin, gx_default_text_begin);
193 code = gs_text_begin(pgs, &text, mem, &pte);
194 set_dev_proc(dev, text_begin, text_begin);
195 if (code < 0)
196 return code;
197 }
198 /* Now we know pte points to a gs_show_enum. */
199 *penum = *(gs_show_enum *)pte;
200 gs_free_object(pgs->memory, pte, "show_n_begin");
201 return code;
202 }
203 #endif
204