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