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