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