1 /* Copyright (C) 1996, 1997, 1998, 1999 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: zchar42.c,v 1.15 2004/02/08 17:35:20 igor Exp $ */
18 /* Type 42 character display operator */
19 #include "ghost.h"
20 #include "oper.h"
21 #include "gsmatrix.h"
22 #include "gspaint.h" /* for gs_fill, gs_stroke */
23 #include "gspath.h"
24 #include "gxfixed.h"
25 #include "gxfont.h"
26 #include "gxfont42.h"
27 #include "gxistate.h"
28 #include "gxpath.h"
29 #include "gxtext.h"
30 #include "gzstate.h" /* only for ->path */
31 #include "dstack.h" /* only for systemdict */
32 #include "estack.h"
33 #include "ichar.h"
34 #include "icharout.h"
35 #include "ifont.h" /* for font_param */
36 #include "igstate.h"
37 #include "store.h"
38 #include "zchar42.h"
39
40 /* Get a Type 42 character metrics and set the cache device. */
41 int
zchar42_set_cache(i_ctx_t * i_ctx_p,gs_font_base * pbfont,ref * cnref,uint glyph_index,op_proc_t cont,op_proc_t * exec_cont,bool put_lsb)42 zchar42_set_cache(i_ctx_t *i_ctx_p, gs_font_base *pbfont, ref *cnref,
43 uint glyph_index, op_proc_t cont, op_proc_t *exec_cont, bool put_lsb)
44 { double sbw[4];
45 double w[2];
46 int present;
47 int code = zchar_get_metrics(pbfont, cnref, sbw);
48
49 if (code < 0)
50 return code;
51 present = code;
52 if (present == metricsNone) {
53 float sbw42[4];
54 int i;
55
56 code = gs_type42_wmode_metrics((gs_font_type42 *)pbfont,
57 glyph_index, false, sbw42);
58 if (code < 0)
59 return code;
60 present = metricsSideBearingAndWidth;
61 for (i = 0; i < 4; ++i)
62 sbw[i] = sbw42[i];
63 w[0] = sbw[2];
64 w[1] = sbw[3];
65 if (gs_rootfont(igs)->WMode) { /* for vertically-oriented metrics */
66 code = gs_type42_wmode_metrics((gs_font_type42 *)pbfont,
67 glyph_index,
68 true, sbw42);
69 if (code < 0) { /* no vertical metrics */
70 if (pbfont->FontType == ft_CID_TrueType) {
71 sbw[0] = sbw[2] / 2;
72 sbw[1] = pbfont->FontBBox.q.y;
73 sbw[2] = 0;
74 sbw[3] = pbfont->FontBBox.p.y - pbfont->FontBBox.q.y;
75 }
76 } else {
77 sbw[0] = sbw[2] / 2;
78 sbw[1] = (pbfont->FontBBox.q.y + pbfont->FontBBox.p.y - sbw42[3]) / 2;
79 sbw[2] = sbw42[2];
80 sbw[3] = sbw42[3];
81 }
82 }
83 } else {
84 w[0] = sbw[2];
85 w[1] = sbw[3];
86 }
87 return zchar_set_cache(i_ctx_p, pbfont, cnref,
88 (put_lsb && present == metricsSideBearingAndWidth ?
89 sbw : NULL),
90 w, &pbfont->FontBBox,
91 cont, exec_cont,
92 gs_rootfont(igs)->WMode ? sbw : NULL);
93 }
94
95 /* <font> <code|name> <name> <glyph_index> .type42execchar - */
96 private int type42_fill(i_ctx_t *);
97 private int type42_stroke(i_ctx_t *);
98 private int
ztype42execchar(i_ctx_t * i_ctx_p)99 ztype42execchar(i_ctx_t *i_ctx_p)
100 {
101 os_ptr op = osp;
102 gs_font *pfont;
103 int code = font_param(op - 3, &pfont);
104 gs_font_base *const pbfont = (gs_font_base *) pfont;
105 gs_text_enum_t *penum = op_show_find(i_ctx_p);
106 op_proc_t cont = (pbfont->PaintType == 0 ? type42_fill : type42_stroke), exec_cont = 0;
107 ref *cnref;
108 uint glyph_index;
109
110 if (code < 0)
111 return code;
112 if (penum == 0 ||
113 (pfont->FontType != ft_TrueType &&
114 pfont->FontType != ft_CID_TrueType)
115 )
116 return_error(e_undefined);
117 /*
118 * Any reasonable implementation would execute something like
119 * 1 setmiterlimit 0 setlinejoin 0 setlinecap
120 * here, but apparently the Adobe implementations aren't reasonable.
121 *
122 * If this is a stroked font, set the stroke width.
123 */
124 if (pfont->PaintType)
125 gs_setlinewidth(igs, pfont->StrokeWidth);
126 check_estack(3); /* for continuations */
127 /*
128 * Execute the definition of the character.
129 */
130 if (r_is_proc(op))
131 return zchar_exec_char_proc(i_ctx_p);
132 /*
133 * The definition must be a Type 42 glyph index.
134 * Note that we do not require read access: this is deliberate.
135 */
136 check_type(*op, t_integer);
137 check_ostack(3); /* for lsb values */
138 /* Establish a current point. */
139 code = gs_moveto(igs, 0.0, 0.0);
140 if (code < 0)
141 return code;
142 cnref = op - 1;
143 glyph_index = (uint)op->value.intval;
144 code = zchar42_set_cache(i_ctx_p, pbfont, cnref, glyph_index, cont, &exec_cont, true);
145 if (code >= 0 && exec_cont != 0)
146 code = (*exec_cont)(i_ctx_p);
147 return code;
148 }
149
150 /* Continue after a CDevProc callout. */
151 private int type42_finish(i_ctx_t *i_ctx_p,
152 int (*cont)(gs_state *));
153 private int
type42_fill(i_ctx_t * i_ctx_p)154 type42_fill(i_ctx_t *i_ctx_p)
155 {
156 int code;
157 gs_fixed_point fa = i_ctx_p->pgs->fill_adjust;
158
159 i_ctx_p->pgs->fill_adjust.x = i_ctx_p->pgs->fill_adjust.y = -1;
160 code = type42_finish(i_ctx_p, gs_fill);
161 i_ctx_p->pgs->fill_adjust = fa; /* Not sure whether we need to restore it,
162 but this isn't harmful. */
163 return code;
164 }
165 private int
type42_stroke(i_ctx_t * i_ctx_p)166 type42_stroke(i_ctx_t *i_ctx_p)
167 {
168 return type42_finish(i_ctx_p, gs_stroke);
169 }
170 /* <font> <code|name> <name> <glyph_index> <sbx> <sby> %type42_{fill|stroke} - */
171 /* <font> <code|name> <name> <glyph_index> %type42_{fill|stroke} - */
172 private int
type42_finish(i_ctx_t * i_ctx_p,int (* cont)(gs_state *))173 type42_finish(i_ctx_t *i_ctx_p, int (*cont) (gs_state *))
174 {
175 os_ptr op = osp;
176 gs_font *pfont;
177 int code;
178 gs_text_enum_t *penum = op_show_find(i_ctx_p);
179 double sbxy[2];
180 gs_point sbpt;
181 gs_point *psbpt = 0;
182 os_ptr opc = op;
183
184 if (!r_has_type(op - 3, t_dictionary)) {
185 check_op(6);
186 code = num_params(op, 2, sbxy);
187 if (code < 0)
188 return code;
189 sbpt.x = sbxy[0];
190 sbpt.y = sbxy[1];
191 psbpt = &sbpt;
192 opc -= 2;
193 }
194 check_type(*opc, t_integer);
195 code = font_param(opc - 3, &pfont);
196 if (code < 0)
197 return code;
198 if (penum == 0 || (pfont->FontType != ft_TrueType &&
199 pfont->FontType != ft_CID_TrueType)
200 )
201 return_error(e_undefined);
202 /*
203 * We have to disregard penum->pis and penum->path, and render to
204 * the current gstate and path. This is a design bug that we will
205 * have to address someday!
206 */
207 code = gs_type42_append((uint)opc->value.intval, (gs_imager_state *)igs,
208 igs->path, &penum->log2_scale,
209 (penum->text.operation & TEXT_DO_ANY_CHARPATH) != 0,
210 pfont->PaintType, penum->pair);
211 if (code < 0)
212 return code;
213 pop((psbpt == 0 ? 4 : 6));
214 return (*cont)(igs);
215 }
216
217 /* ------ Initialization procedure ------ */
218
219 const op_def zchar42_op_defs[] =
220 {
221 {"4.type42execchar", ztype42execchar},
222 op_def_end(0)
223 };
224