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