xref: /plan9/sys/src/cmd/gs/src/zfont42.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1996, 1998, 1999, 2000 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: zfont42.c,v 1.23 2005/06/19 21:03:32 igor Exp $ */
18 /* Type 42 font creation operator */
19 #include "memory_.h"
20 #include "ghost.h"
21 #include "oper.h"
22 #include "gsccode.h"
23 #include "gsmatrix.h"
24 #include "gxfont.h"
25 #include "gxfont42.h"
26 #include "bfont.h"
27 #include "icharout.h"
28 #include "idict.h"
29 #include "idparam.h"
30 #include "ifont42.h"
31 #include "ichar1.h"
32 #include "iname.h"
33 #include "store.h"
34 
35 /* Forward references */
36 private int z42_string_proc(gs_font_type42 *, ulong, uint, const byte **);
37 private uint z42_get_glyph_index(gs_font_type42 *, gs_glyph);
38 private int z42_gdir_get_outline(gs_font_type42 *, uint, gs_glyph_data_t *);
39 private font_proc_enumerate_glyph(z42_enumerate_glyph);
40 private font_proc_enumerate_glyph(z42_gdir_enumerate_glyph);
41 private font_proc_encode_char(z42_encode_char);
42 private font_proc_glyph_info(z42_glyph_info);
43 private font_proc_glyph_outline(z42_glyph_outline);
44 
45 /* <string|name> <font_dict> .buildfont11/42 <string|name> <font> */
46 /* Build a type 11 (TrueType CID-keyed) or 42 (TrueType) font. */
47 int
build_gs_TrueType_font(i_ctx_t * i_ctx_p,os_ptr op,gs_font_type42 ** ppfont,font_type ftype,gs_memory_type_ptr_t pstype,const char * bcstr,const char * bgstr,build_font_options_t options)48 build_gs_TrueType_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font_type42 **ppfont,
49 		       font_type ftype, gs_memory_type_ptr_t pstype,
50 		       const char *bcstr, const char *bgstr,
51 		       build_font_options_t options)
52 {
53     build_proc_refs build;
54     ref sfnts, GlyphDirectory;
55     gs_font_type42 *pfont;
56     font_data *pdata;
57     int code;
58 
59     code = build_proc_name_refs(imemory, &build, bcstr, bgstr);
60     if (code < 0)
61 	return code;
62     check_type(*op, t_dictionary);
63     /*
64      * Since build_gs_primitive_font may resize the dictionary and cause
65      * pointers to become invalid, we save sfnts and GlyphDirectory.
66      */
67     if ((code = font_string_array_param(imemory, op, "sfnts", &sfnts)) < 0 ||
68 	(code = font_GlyphDirectory_param(op, &GlyphDirectory)) < 0
69 	)
70 	return code;
71     code = build_gs_primitive_font(i_ctx_p, op, (gs_font_base **)ppfont,
72 				   ftype, pstype, &build, options);
73     if (code != 0)
74 	return code;
75     pfont = *ppfont;
76     pdata = pfont_data(pfont);
77     ref_assign(&pdata->u.type42.sfnts, &sfnts);
78     make_null_new(&pdata->u.type42.CIDMap);
79     ref_assign(&pdata->u.type42.GlyphDirectory, &GlyphDirectory);
80     pfont->data.string_proc = z42_string_proc;
81     pfont->data.proc_data = (char *)pdata;
82     code = gs_type42_font_init(pfont);
83     if (code < 0)
84 	return code;
85     /*
86      * If the font has a GlyphDictionary, this replaces loca and glyf for
87      * accessing character outlines.  In this case, we use alternate
88      * get_outline and enumerate_glyph procedures.
89      */
90     if (!r_has_type(&GlyphDirectory, t_null)) {
91 	pfont->data.get_outline = z42_gdir_get_outline;
92 	pfont->procs.enumerate_glyph = z42_gdir_enumerate_glyph;
93     } else
94 	pfont->procs.enumerate_glyph = z42_enumerate_glyph;
95     /*
96      * The procedures that access glyph information must accept either
97      * glyph names or glyph indexes.
98      */
99     pfont->data.get_glyph_index = z42_get_glyph_index;
100     pfont->procs.encode_char = z42_encode_char;
101     pfont->procs.glyph_info = z42_glyph_info;
102     pfont->procs.glyph_outline = z42_glyph_outline;
103     return 0;
104 }
105 private int
zbuildfont42(i_ctx_t * i_ctx_p)106 zbuildfont42(i_ctx_t *i_ctx_p)
107 {
108     os_ptr op = osp;
109     gs_font_type42 *pfont;
110     int code = build_gs_TrueType_font(i_ctx_p, op, &pfont, ft_TrueType,
111 				      &st_gs_font_type42, "%Type42BuildChar",
112 				      "%Type42BuildGlyph", bf_options_none);
113 
114     if (code < 0)
115 	return code;
116     return define_gs_font((gs_font *)pfont);
117 }
118 
119 /*
120  * Check a parameter for being an array of strings.  Return the parameter
121  * value even if it is of the wrong type.
122  */
123 int
font_string_array_param(const gs_memory_t * mem,os_ptr op,const char * kstr,ref * psa)124 font_string_array_param(const gs_memory_t *mem, os_ptr op, const char *kstr, ref *psa)
125 {
126     ref *pvsa;
127     ref rstr0;
128     int code;
129 
130     if (dict_find_string(op, kstr, &pvsa) <= 0)
131 	return_error(e_invalidfont);
132     *psa = *pvsa;
133     /*
134      * We only check the first element of the array now, as a sanity test;
135      * elements are checked as needed by string_array_access_proc.
136      */
137     if ((code = array_get(mem, pvsa, 0L, &rstr0)) < 0)
138 	return code;
139     if (!r_has_type(&rstr0, t_string))
140 	return_error(e_typecheck);
141     return 0;
142 }
143 
144 /*
145  * Get a GlyphDirectory if present.  Return 0 if present, 1 if absent,
146  * or an error code.
147  */
148 int
font_GlyphDirectory_param(os_ptr op,ref * pGlyphDirectory)149 font_GlyphDirectory_param(os_ptr op, ref *pGlyphDirectory)
150 {
151     ref *pgdir;
152 
153     if (dict_find_string(op, "GlyphDirectory", &pgdir) <= 0)
154 	make_null(pGlyphDirectory);
155     else if (!r_has_type(pgdir, t_dictionary) && !r_is_array(pgdir))
156 	return_error(e_typecheck);
157     else
158 	*pGlyphDirectory = *pgdir;
159     return 0;
160 }
161 
162 /*
163  * Access a given byte offset and length in an array of strings.
164  * This is used for sfnts and for CIDMap.  The int argument is 2 for sfnts
165  * (because of the strange behavior of odd-length strings), 1 for CIDMap.
166  * Return code : 0 - success, <0 - error,
167  *               >0 - number of accessible bytes (client must cycle).
168  */
169 int
string_array_access_proc(const gs_memory_t * mem,const ref * psa,int modulus,ulong offset,uint length,const byte ** pdata)170 string_array_access_proc(const gs_memory_t *mem,
171 			 const ref *psa, int modulus, ulong offset,
172 			 uint length, const byte **pdata)
173 {
174     ulong left = offset;
175     uint index = 0;
176 
177     if (length == 0)
178         return 0;
179     for (;; ++index) {
180 	ref rstr;
181 	int code = array_get(mem, psa, index, &rstr);
182 	uint size;
183 
184 	if (code < 0)
185 	    return code;
186 	if (!r_has_type(&rstr, t_string))
187 	    return_error(e_typecheck);
188 	/*
189 	 * NOTE: According to the Adobe documentation, each sfnts
190 	 * string should have even length.  If the length is odd,
191 	 * the additional byte is padding and should be ignored.
192 	 */
193 	size = r_size(&rstr) & -modulus;
194 	if (left < size) {
195 	    *pdata = rstr.value.const_bytes + left;
196 	    if (left + length > size)
197 		return size - left;
198 	    return 0;
199 	}
200 	left -= size;
201     }
202 }
203 
204 /* ------ Initialization procedure ------ */
205 
206 const op_def zfont42_op_defs[] =
207 {
208     {"2.buildfont42", zbuildfont42},
209     op_def_end(0)
210 };
211 
212 /* Reduce a glyph name to a glyph index if needed. */
213 private gs_glyph
glyph_to_index(const gs_font * font,gs_glyph glyph)214 glyph_to_index(const gs_font *font, gs_glyph glyph)
215 {
216     ref gref;
217     ref *pcstr;
218 
219     if (glyph >= GS_MIN_GLYPH_INDEX)
220 	return glyph;
221     name_index_ref(font->memory, glyph, &gref);
222     if (dict_find(&pfont_data(font)->CharStrings, &gref, &pcstr) > 0 &&
223 	r_has_type(pcstr, t_integer)
224 	) {
225 	gs_glyph index_glyph = pcstr->value.intval + GS_MIN_GLYPH_INDEX;
226 
227 	if (index_glyph >= GS_MIN_GLYPH_INDEX && index_glyph <= gs_max_glyph)
228 	    return index_glyph;
229     }
230     return GS_MIN_GLYPH_INDEX;	/* glyph 0 is notdef */
231 }
232 private uint
z42_get_glyph_index(gs_font_type42 * pfont,gs_glyph glyph)233 z42_get_glyph_index(gs_font_type42 *pfont, gs_glyph glyph)
234 {
235     gs_glyph gid = glyph_to_index((gs_font *)pfont, glyph);
236 
237     return gid - GS_MIN_GLYPH_INDEX;
238 }
239 
240 /*
241  * Get a glyph outline from GlyphDirectory.  Return an empty string if
242  * the glyph is missing or out of range.
243  */
244 int
font_gdir_get_outline(const gs_memory_t * mem,const ref * pgdir,long glyph_index,gs_glyph_data_t * pgd)245 font_gdir_get_outline(const gs_memory_t *mem,
246 		      const ref *pgdir,
247 		      long glyph_index,
248 		      gs_glyph_data_t *pgd)
249 {
250     ref iglyph;
251     ref gdef;
252     ref *pgdef;
253     int code;
254 
255     if (r_has_type(pgdir, t_dictionary)) {
256 	make_int(&iglyph, glyph_index);
257 	code = dict_find(pgdir, &iglyph, &pgdef) - 1; /* 0 => not found */
258     } else {
259 	code = array_get(mem, pgdir, glyph_index, &gdef);
260 	pgdef = &gdef;
261     }
262     if (code < 0) {
263 	gs_glyph_data_from_null(pgd);
264     } else if (!r_has_type(pgdef, t_string)) {
265 	return_error(e_typecheck);
266     } else {
267 	gs_glyph_data_from_string(pgd, pgdef->value.const_bytes, r_size(pgdef),
268 				  NULL);
269     }
270     return 0;
271 }
272 private int
z42_gdir_get_outline(gs_font_type42 * pfont,uint glyph_index,gs_glyph_data_t * pgd)273 z42_gdir_get_outline(gs_font_type42 * pfont, uint glyph_index,
274 		     gs_glyph_data_t *pgd)
275 {
276     const font_data *pfdata = pfont_data(pfont);
277     const ref *pgdir = &pfdata->u.type42.GlyphDirectory;
278 
279     return font_gdir_get_outline(pfont->memory, pgdir, (long)glyph_index, pgd);
280 }
281 
282 /* Enumerate glyphs from CharStrings or loca / glyf. */
283 private int
z42_enumerate_glyph(gs_font * font,int * pindex,gs_glyph_space_t glyph_space,gs_glyph * pglyph)284 z42_enumerate_glyph(gs_font *font, int *pindex, gs_glyph_space_t glyph_space,
285 		    gs_glyph *pglyph)
286 {
287     if (glyph_space == GLYPH_SPACE_INDEX)
288 	return gs_type42_enumerate_glyph(font, pindex, glyph_space, pglyph);
289     else {
290 	const ref *pcsdict = &pfont_data(font)->CharStrings;
291 
292 	return zchar_enumerate_glyph(font->memory, pcsdict, pindex, pglyph);
293     }
294 }
295 
296 /* Enumerate glyphs (keys) from GlyphDirectory instead of loca / glyf. */
297 private int
z42_gdir_enumerate_glyph(gs_font * font,int * pindex,gs_glyph_space_t glyph_space,gs_glyph * pglyph)298 z42_gdir_enumerate_glyph(gs_font *font, int *pindex,
299 			 gs_glyph_space_t glyph_space, gs_glyph *pglyph)
300 {
301     const ref *pgdict;
302     int code;
303 
304     if (glyph_space == GLYPH_SPACE_INDEX) {
305 	pgdict = &pfont_data(font)->u.type42.GlyphDirectory;
306 	if (!r_has_type(pgdict, t_dictionary)) {
307 	    ref gdef;
308 
309 	    for (;; (*pindex)++) {
310 		if (array_get(font->memory, pgdict, (long)*pindex, &gdef) < 0) {
311 		    *pindex = 0;
312 		    return 0;
313 		}
314 		if (!r_has_type(&gdef, t_null)) {
315 		    *pglyph = GS_MIN_GLYPH_INDEX + (*pindex)++;
316 		    return 0;
317 		}
318 	    }
319 	}
320     } else
321 	pgdict = &pfont_data(font)->CharStrings;
322     /* A trick : use zchar_enumerate_glyph to enumerate GIDs : */
323     code = zchar_enumerate_glyph(font->memory, pgdict, pindex, pglyph);
324     if (*pindex != 0 && *pglyph >= gs_min_cid_glyph)
325 	*pglyph	= *pglyph - gs_min_cid_glyph + GS_MIN_GLYPH_INDEX;
326     return code;
327 }
328 
329 /*
330  * Define font procedures that accept either a character name or a glyph
331  * index as the glyph.
332  */
333 private gs_glyph
z42_encode_char(gs_font * font,gs_char chr,gs_glyph_space_t glyph_space)334 z42_encode_char(gs_font *font, gs_char chr, gs_glyph_space_t glyph_space)
335 {
336     gs_glyph glyph = zfont_encode_char(font, chr, glyph_space);
337 
338     return (glyph_space == GLYPH_SPACE_INDEX && glyph != gs_no_glyph ?
339 	    glyph_to_index(font, glyph) : glyph);
340 }
341 private int
z42_glyph_outline(gs_font * font,int WMode,gs_glyph glyph,const gs_matrix * pmat,gx_path * ppath,double sbw[4])342 z42_glyph_outline(gs_font *font, int WMode, gs_glyph glyph, const gs_matrix *pmat,
343 		  gx_path *ppath, double sbw[4])
344 {
345     return gs_type42_glyph_outline(font, WMode, glyph_to_index(font, glyph),
346 				   pmat, ppath, sbw);
347 }
348 private int
z42_glyph_info(gs_font * font,gs_glyph glyph,const gs_matrix * pmat,int members,gs_glyph_info_t * info)349 z42_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
350 	       int members, gs_glyph_info_t *info)
351 {   /* fixme : same as z1_glyph_info. */
352     int wmode = font->WMode;
353 
354     return z1_glyph_info_generic(font, glyph, pmat, members, info, gs_type42_glyph_info, wmode);
355 }
356 
357 /* Procedure for accessing the sfnts array.
358  * Return code : 0 - success, <0 - error,
359  *               >0 - number of accessible bytes (client must cycle).
360  */
361 private int
z42_string_proc(gs_font_type42 * pfont,ulong offset,uint length,const byte ** pdata)362 z42_string_proc(gs_font_type42 * pfont, ulong offset, uint length,
363 		const byte ** pdata)
364 {
365     return string_array_access_proc(pfont->memory, &pfont_data(pfont)->u.type42.sfnts, 2,
366 				    offset, length, pdata);
367 }
368