xref: /plan9/sys/src/cmd/gs/src/zchar42.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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