1 /* Copyright (C) 2000, 2001 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: zfcid1.c,v 1.23 2004/11/19 04:39:11 ray Exp $ */
18 /* CIDFontType 1 and 2 operators */
19 #include "memory_.h"
20 #include "ghost.h"
21 #include "oper.h"
22 #include "gsmatrix.h"
23 #include "gsccode.h"
24 #include "gsstruct.h"
25 #include "gsgcache.h"
26 #include "gxfcid.h"
27 #include "bfont.h"
28 #include "icid.h"
29 #include "idict.h"
30 #include "idparam.h"
31 #include "ifcid.h"
32 #include "ichar1.h"
33 #include "ifont42.h"
34 #include "store.h"
35 #include "stream.h"
36 #include "files.h"
37
38 /* ---------------- CIDFontType 1 (FontType 10) ---------------- */
39
40 /* <string|name> <font_dict> .buildfont10 <string|name> <font> */
41 private int
zbuildfont10(i_ctx_t * i_ctx_p)42 zbuildfont10(i_ctx_t *i_ctx_p)
43 {
44 os_ptr op = osp;
45 build_proc_refs build;
46 int code = build_gs_font_procs(op, &build);
47 gs_cid_system_info_t cidsi;
48 gs_font_base *pfont;
49
50 if (code < 0)
51 return code;
52 code = cid_font_system_info_param(&cidsi, op);
53 if (code < 0)
54 return code;
55 make_null(&build.BuildChar); /* only BuildGlyph */
56 code = build_gs_simple_font(i_ctx_p, op, &pfont, ft_CID_user_defined,
57 &st_gs_font_cid1, &build,
58 bf_Encoding_optional |
59 bf_UniqueID_ignored);
60 if (code < 0)
61 return code;
62 ((gs_font_cid1 *)pfont)->cidata.CIDSystemInfo = cidsi;
63 return define_gs_font((gs_font *)pfont);
64 }
65
66 /* ---------------- CIDFontType 2 (FontType 11) ---------------- */
67
68 /* ------ Accessing ------ */
69
70 /* Map a glyph CID to a TrueType glyph number using the CIDMap. */
71 private int
z11_CIDMap_proc(gs_font_cid2 * pfont,gs_glyph glyph)72 z11_CIDMap_proc(gs_font_cid2 *pfont, gs_glyph glyph)
73 {
74 const ref *pcidmap = &pfont_data(pfont)->u.type42.CIDMap;
75 ulong cid = glyph - gs_min_cid_glyph;
76 int gdbytes = pfont->cidata.common.GDBytes;
77 int gnum = 0;
78 const byte *data;
79 int i, code;
80 ref rcid;
81 ref *prgnum;
82
83 switch (r_type(pcidmap)) {
84 case t_string:
85 if (cid >= r_size(pcidmap) / gdbytes)
86 return_error(e_rangecheck);
87 data = pcidmap->value.const_bytes + cid * gdbytes;
88 break;
89 case t_integer:
90 return cid + pcidmap->value.intval;
91 case t_dictionary:
92 make_int(&rcid, cid);
93 code = dict_find(pcidmap, &rcid, &prgnum);
94 if (code <= 0)
95 return (code < 0 ? code : gs_note_error(e_undefined));
96 if (!r_has_type(prgnum, t_integer))
97 return_error(e_typecheck);
98 return prgnum->value.intval;
99 default: /* array type */
100 code = string_array_access_proc(pfont->memory, pcidmap, 1, cid * gdbytes,
101 gdbytes, &data);
102
103 if (code < 0)
104 return code;
105 if ( code > 0 )
106 return_error(e_invalidfont);
107 }
108 for (i = 0; i < gdbytes; ++i)
109 gnum = (gnum << 8) + data[i];
110 return gnum;
111 }
112
113 /* Handle MetricsCount when accessing outline or metrics information. */
114 private int
z11_get_outline(gs_font_type42 * pfont,uint glyph_index,gs_glyph_data_t * pgd)115 z11_get_outline(gs_font_type42 * pfont, uint glyph_index,
116 gs_glyph_data_t *pgd)
117 {
118 gs_font_cid2 *const pfcid = (gs_font_cid2 *)pfont;
119 int skip = pfcid->cidata.MetricsCount << 1;
120 int code = pfcid->cidata.orig_procs.get_outline(pfont, glyph_index, pgd);
121
122 if (code >= 0) {
123 uint size = pgd->bits.size;
124
125 if (size <= skip) {
126 gs_glyph_data_free(pgd, "z11_get_outline");
127 gs_glyph_data_from_null(pgd);
128 } else {
129 gs_glyph_data_substring(pgd, skip, size - skip);
130 }
131 }
132 return code;
133 }
134
135 #define GET_U16_MSB(p) (((uint)((p)[0]) << 8) + (p)[1])
136 #define GET_S16_MSB(p) (int)((GET_U16_MSB(p) ^ 0x8000) - 0x8000)
137
138 double recipunitsperem(gs_font_type42 *pfont);
139
140 private int
z11_get_metrics(gs_font_type42 * pfont,uint glyph_index,int wmode,float sbw[4])141 z11_get_metrics(gs_font_type42 * pfont, uint glyph_index, int wmode,
142 float sbw[4])
143 {
144 gs_font_cid2 *const pfcid = (gs_font_cid2 *)pfont;
145 int skip = pfcid->cidata.MetricsCount << 1;
146 gs_glyph_data_t gdata;
147 const byte *pmetrics;
148 int lsb, width;
149 int code = 0;
150
151 gdata.memory = pfont->memory;
152 if (wmode >= skip >> 2 ||
153 (code = pfcid->cidata.orig_procs.get_outline(pfont, glyph_index, &gdata)) < 0 ||
154 gdata.bits.size < skip
155 )
156 return pfcid->cidata.orig_procs.get_metrics(pfont, glyph_index, wmode,
157 sbw);
158 pmetrics = gdata.bits.data + skip - 4 - (wmode << 2);
159 lsb = GET_S16_MSB(pmetrics + 2);
160 width = GET_U16_MSB(pmetrics + 0);
161 {
162 double factor = recipunitsperem(pfont);
163
164 if (wmode) {
165 sbw[0] = 0, sbw[1] = -lsb * factor;
166 sbw[2] = 0, sbw[3] = -width * factor;
167 } else {
168 sbw[0] = lsb * factor, sbw[1] = 0;
169 sbw[2] = width * factor, sbw[3] = 0;
170 }
171 }
172 gs_glyph_data_free(&gdata, "z11_get_metrics");
173 return 0;
174 }
175
176 private int
z11_glyph_info_aux(gs_font * font,gs_glyph glyph,const gs_matrix * pmat,int members,gs_glyph_info_t * info)177 z11_glyph_info_aux(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
178 int members, gs_glyph_info_t *info)
179 {
180 gs_font_cid2 *fontCID2 = (gs_font_cid2 *)font;
181 uint glyph_index;
182 int code = (glyph > GS_MIN_GLYPH_INDEX
183 ? glyph - GS_MIN_GLYPH_INDEX
184 : fontCID2->cidata.CIDMap_proc(fontCID2, glyph));
185
186 if(code < 0)
187 return code;
188 glyph_index = (uint)code;
189 return gs_type42_glyph_info_by_gid(font, glyph, pmat, members, info, glyph_index);
190 }
191
192 private int
z11_glyph_info(gs_font * font,gs_glyph glyph,const gs_matrix * pmat,int members,gs_glyph_info_t * info)193 z11_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
194 int members, gs_glyph_info_t *info)
195 {
196 int wmode = (members & GLYPH_INFO_WIDTH0 ? 0 : 1);
197
198 return z1_glyph_info_generic(font, glyph, pmat, members, info,
199 &z11_glyph_info_aux, wmode);
200 }
201
202
203 /* Enumerate glyphs (keys) from GlyphDirectory instead of loca / glyf. */
204 private int
z11_enumerate_glyph(gs_font * font,int * pindex,gs_glyph_space_t glyph_space,gs_glyph * pglyph)205 z11_enumerate_glyph(gs_font *font, int *pindex,
206 gs_glyph_space_t glyph_space, gs_glyph *pglyph)
207 {
208 gs_font_cid2 *pfont = (gs_font_cid2 *)font;
209 int code0 = z11_CIDMap_proc(pfont, GS_MIN_CID_GLYPH);
210 int code;
211
212 for (;;) {
213 code = z11_CIDMap_proc(pfont, GS_MIN_CID_GLYPH + *pindex);
214
215 if (code < 0) {
216 *pindex = 0;
217 return 0;
218 }
219 (*pindex)++;
220 if (*pindex == 1 || code != code0)
221 break;
222 /* else skip an underfined glyph */
223 }
224 if (glyph_space == GLYPH_SPACE_INDEX)
225 *pglyph = GS_MIN_GLYPH_INDEX + (uint)code;
226 else
227 *pglyph = GS_MIN_CID_GLYPH + (uint)(*pindex - 1);
228 return 0;
229 }
230
231 private uint
z11_get_glyph_index(gs_font_type42 * pfont,gs_glyph glyph)232 z11_get_glyph_index(gs_font_type42 *pfont, gs_glyph glyph)
233 {
234 int code = z11_CIDMap_proc((gs_font_cid2 *)pfont, glyph);
235
236 return (code < 0 ? 0 /* notdef */: (uint)code);
237 }
238
239
240 private int
z11_glyph_outline(gs_font * font,int WMode,gs_glyph glyph,const gs_matrix * pmat,gx_path * ppath,double sbw[4])241 z11_glyph_outline(gs_font *font, int WMode, gs_glyph glyph, const gs_matrix *pmat,
242 gx_path *ppath, double sbw[4])
243 {
244 return gs_type42_glyph_outline(font, WMode,
245 z11_get_glyph_index((gs_font_type42 *)font, glyph) + GS_MIN_GLYPH_INDEX,
246 pmat, ppath, sbw);
247 }
248
249 /* ------ Defining ------ */
250
251 /* <string|name> <font_dict> .buildfont11 <string|name> <font> */
252 private int
zbuildfont11(i_ctx_t * i_ctx_p)253 zbuildfont11(i_ctx_t *i_ctx_p)
254 {
255 os_ptr op = osp;
256 gs_font_cid_data common;
257 gs_font_type42 *pfont;
258 gs_font_cid2 *pfcid;
259 int MetricsCount;
260 ref rcidmap, ignore_gdir, file, *pfile, cfnstr, *pCIDFontName, CIDFontName;
261 ulong loca_glyph_pos[2][2];
262 int code = cid_font_data_param(op, &common, &ignore_gdir);
263
264 if (code < 0 ||
265 (code = dict_find_string(op, "CIDFontName", &pCIDFontName)) <= 0 ||
266 (code = dict_int_param(op, "MetricsCount", 0, 4, 0, &MetricsCount)) < 0
267 )
268 return code;
269 /*
270 * Since build_gs_simple_font may resize the dictionary and cause
271 * pointers to become invalid, save CIDFontName
272 */
273 CIDFontName = *pCIDFontName;
274 if (MetricsCount & 1) /* only allowable values are 0, 2, 4 */
275 return_error(e_rangecheck);
276 code = dict_find_string(op, "File", &pfile);
277 if (code < 0 && code != e_dictfull)
278 return code;
279 if (code > 0) {
280 ref *file_table_pos, *a, v;
281 const char *name[2] = {"loca", "glyf"};
282 int i, j;
283
284 /*
285 * Since build_gs_simple_font may resize the dictionary and cause
286 * pointers to become invalid, save File and CIDFontName
287 */
288 file = *pfile;
289 check_read_type(file, t_file);
290 code = dict_find_string(op, "file_table_pos", &file_table_pos);
291 if (code <= 0 || r_type(file_table_pos) != t_dictionary)
292 return_error(e_invalidfont);
293 for (i = 0; i < 2; i++) {
294 code = dict_find_string(file_table_pos, name[i], &a);
295 if (code <= 0 || r_type(a) != t_array)
296 return_error(e_invalidfont);
297 for (j = 0; j < 2; j++) {
298 code = array_get(imemory, a, j, &v);
299 if (code < 0 || r_type(&v) != t_integer)
300 return_error(e_invalidfont);
301 loca_glyph_pos[i][j] = v.value.intval;
302 }
303 }
304 } else
305 pfile = NULL;
306 code = font_string_array_param(imemory, op, "CIDMap", &rcidmap);
307 switch (code) {
308 case 0: /* in PLRM3 */
309 gdb:
310 /* GDBytes is required for indexing a string or string array. */
311 if (common.GDBytes == 0)
312 return_error(e_rangecheck);
313 break;
314 default:
315 return code;
316 case e_typecheck:
317 switch (r_type(&rcidmap)) {
318 case t_string: /* in PLRM3 */
319 goto gdb;
320 case t_dictionary: /* added in 3011 */
321 case t_integer: /* added in 3011 */
322 break;
323 default:
324 return code;
325 }
326 break;
327 }
328 code = build_gs_TrueType_font(i_ctx_p, op, &pfont, ft_CID_TrueType,
329 &st_gs_font_cid2,
330 (const char *)0, "%Type11BuildGlyph",
331 bf_Encoding_optional |
332 bf_UniqueID_ignored |
333 bf_CharStrings_optional);
334 if (code < 0)
335 return code;
336 pfcid = (gs_font_cid2 *)pfont;
337 pfcid->cidata.common = common;
338 pfcid->cidata.MetricsCount = MetricsCount;
339 ref_assign(&pfont_data(pfont)->u.type42.CIDMap, &rcidmap);
340 pfcid->cidata.CIDMap_proc = z11_CIDMap_proc;
341 pfont->procs.enumerate_glyph = z11_enumerate_glyph;
342 pfont->procs.glyph_info = z11_glyph_info;
343 pfont->procs.glyph_outline = z11_glyph_outline;
344 pfont->data.get_glyph_index = z11_get_glyph_index;
345 get_font_name(imemory, &cfnstr, &CIDFontName);
346 copy_font_name(&pfcid->font_name, &cfnstr);
347 if (MetricsCount) {
348 /* "Wrap" the glyph accessor procedures. */
349 pfcid->cidata.orig_procs.get_outline = pfont->data.get_outline;
350 pfont->data.get_outline = z11_get_outline;
351 pfcid->cidata.orig_procs.get_metrics = pfont->data.get_metrics;
352 pfont->data.get_metrics = z11_get_metrics;
353 } else if(pfile != NULL) {
354 /*
355 * We assume that disk fonts has no MetricsCount.
356 * We could do not, but the number of virtual function wariants increases.
357 */
358 stream *s;
359
360 check_read_file(s, &file);
361 pfont->data.loca = loca_glyph_pos[0][0];
362 pfont->data.glyf = loca_glyph_pos[1][0];
363 pfont->data.get_outline = gs_get_glyph_data_cached;
364 pfont->data.gdcache = gs_glyph_cache__alloc(pfont, s, gs_type42_get_outline_from_TT_file);
365 }
366 return define_gs_font((gs_font *)pfont);
367 }
368
369 /* <cid11font> <cid> .type11mapcid <glyph_index> */
370 private int
ztype11mapcid(i_ctx_t * i_ctx_p)371 ztype11mapcid(i_ctx_t *i_ctx_p)
372 {
373 os_ptr op = osp;
374 gs_font *pfont;
375 int code = font_param(op - 1, &pfont);
376
377 if (code < 0)
378 return code;
379 check_type(*op, t_integer);
380 #if defined(TEST)
381 /* Allow a Type 42 font here, for testing .wrapfont. */
382 if (pfont->FontType == ft_TrueType) {
383 /* Use the CID as the glyph index. */
384 if (op->value.intval < 0 ||
385 op->value.intval >= ((gs_font_type42 *)pfont)->data.numGlyphs
386 )
387 return_error(e_rangecheck);
388 code = (int)op->value.intval;
389 } else
390 #endif
391 {
392 if (pfont->FontType != ft_CID_TrueType)
393 return_error(e_invalidfont);
394 code = z11_CIDMap_proc((gs_font_cid2 *)pfont,
395 (gs_glyph)(gs_min_cid_glyph + op->value.intval));
396 }
397 if (code < 0)
398 return code;
399 make_int(op - 1, code);
400 pop(1);
401 return 0;
402 }
403
404 /* <Decoding> <TT_cmap> <SubstNWP> <GDBytes> <CIDMap> .fillCIDMap - */
405 private int
zfillCIDMap(i_ctx_t * i_ctx_p)406 zfillCIDMap(i_ctx_t *i_ctx_p)
407 {
408 os_ptr op = osp;
409 ref *Decoding = op - 4, *TT_cmap = op - 3, *SubstNWP = op - 2,
410 *GDBytes = op - 1, *CIDMap = op;
411 int code;
412
413 check_type(*Decoding, t_dictionary);
414 check_type(*TT_cmap, t_array);
415 check_type(*SubstNWP, t_array);
416 check_type(*GDBytes, t_integer);
417 check_type(*CIDMap, t_array);
418 code = cid_fill_CIDMap(imemory, Decoding, TT_cmap, SubstNWP, GDBytes->value.intval, CIDMap);
419 pop(5);
420 return code;
421 }
422
423 /* ------ Initialization procedure ------ */
424
425 const op_def zfcid1_op_defs[] =
426 {
427 {"2.buildfont10", zbuildfont10},
428 {"2.buildfont11", zbuildfont11},
429 {"2.type11mapcid", ztype11mapcid},
430 {"2.fillCIDMap", zfillCIDMap},
431 op_def_end(0)
432 };
433