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: zfcid1.c 10452 2009-12-05 19:21:42Z alexcher $ */
15 /* CIDFontType 1 and 2 operators */
16 #include "memory_.h"
17 #include "ghost.h"
18 #include "oper.h"
19 #include "gsmatrix.h"
20 #include "gsccode.h"
21 #include "gsstruct.h"
22 #include "gsgcache.h"
23 #include "gsutil.h"
24 #include "gxfcid.h"
25 #include "gxfcache.h"
26 #include "bfont.h"
27 #include "icid.h"
28 #include "idict.h"
29 #include "idparam.h"
30 #include "ifcid.h"
31 #include "ichar1.h"
32 #include "ifont42.h"
33 #include "store.h"
34 #include "stream.h"
35 #include "files.h"
36
37 /* ---------------- CIDFontType 1 (FontType 10) ---------------- */
38
39 /* <string|name> <font_dict> .buildfont10 <string|name> <font> */
40 static int
zbuildfont10(i_ctx_t * i_ctx_p)41 zbuildfont10(i_ctx_t *i_ctx_p)
42 {
43 os_ptr op = osp;
44 build_proc_refs build;
45 int code = build_gs_font_procs(op, &build);
46 gs_cid_system_info_t cidsi;
47 gs_font_base *pfont;
48
49 if (code < 0)
50 return code;
51 code = cid_font_system_info_param(&cidsi, op);
52 if (code < 0)
53 return code;
54 make_null(&build.BuildChar); /* only BuildGlyph */
55 code = build_gs_simple_font(i_ctx_p, op, &pfont, ft_CID_user_defined,
56 &st_gs_font_cid1, &build,
57 bf_Encoding_optional |
58 bf_UniqueID_ignored);
59 if (code < 0)
60 return code;
61 ((gs_font_cid1 *)pfont)->cidata.CIDSystemInfo = cidsi;
62 return define_gs_font((gs_font *)pfont);
63 }
64
65 /* ---------------- CIDFontType 2 (FontType 11) ---------------- */
66
67 /* ------ Accessing ------ */
68
69 /* Map a glyph CID to a TrueType glyph number using the CIDMap. */
70 static int
z11_CIDMap_proc(gs_font_cid2 * pfont,gs_glyph glyph)71 z11_CIDMap_proc(gs_font_cid2 *pfont, gs_glyph glyph)
72 {
73 const ref *pcidmap = &pfont_data(pfont)->u.type42.CIDMap;
74 ulong cid = glyph - gs_min_cid_glyph;
75 int gdbytes = pfont->cidata.common.GDBytes;
76 int gnum = 0;
77 const byte *data;
78 int i, code;
79 ref rcid;
80 ref *prgnum;
81
82 switch (r_type(pcidmap)) {
83 case t_string:
84 if (cid >= r_size(pcidmap) / gdbytes)
85 return_error(e_rangecheck);
86 data = pcidmap->value.const_bytes + cid * gdbytes;
87 break;
88 case t_integer:
89 return cid + pcidmap->value.intval;
90 case t_dictionary:
91 make_int(&rcid, cid);
92 code = dict_find(pcidmap, &rcid, &prgnum);
93 if (code <= 0)
94 return (code < 0 ? code : gs_note_error(e_undefined));
95 if (!r_has_type(prgnum, t_integer))
96 return_error(e_typecheck);
97 return prgnum->value.intval;
98 default: /* array type */
99 code = string_array_access_proc(pfont->memory, pcidmap, 1, cid * gdbytes,
100 gdbytes, NULL, NULL, &data);
101
102 if (code < 0)
103 return code;
104 if ( code > 0 )
105 return_error(e_invalidfont);
106 }
107 for (i = 0; i < gdbytes; ++i)
108 gnum = (gnum << 8) + data[i];
109 if (gnum >= pfont->data.trueNumGlyphs)
110 return_error(e_invalidfont);
111 return gnum;
112 }
113
114 /* Handle MetricsCount when accessing outline or metrics information. */
115 static int
z11_get_outline(gs_font_type42 * pfont,uint glyph_index,gs_glyph_data_t * pgd)116 z11_get_outline(gs_font_type42 * pfont, uint glyph_index,
117 gs_glyph_data_t *pgd)
118 {
119 gs_font_cid2 *const pfcid = (gs_font_cid2 *)pfont;
120 int skip = pfcid->cidata.MetricsCount << 1;
121 int code = pfcid->cidata.orig_procs.get_outline(pfont, glyph_index, pgd);
122
123 if (code >= 0) {
124 uint size = pgd->bits.size;
125
126 if (size <= skip) {
127 gs_glyph_data_free(pgd, "z11_get_outline");
128 gs_glyph_data_from_null(pgd);
129 } else {
130 gs_glyph_data_substring(pgd, skip, size - skip);
131 }
132 }
133 return code;
134 }
135
136 #define GET_U16_MSB(p) (((uint)((p)[0]) << 8) + (p)[1])
137 #define GET_S16_MSB(p) (int)((GET_U16_MSB(p) ^ 0x8000) - 0x8000)
138
139 static int
z11_get_metrics(gs_font_type42 * pfont,uint glyph_index,gs_type42_metrics_options_t options,float sbw[4])140 z11_get_metrics(gs_font_type42 * pfont, uint glyph_index,
141 gs_type42_metrics_options_t options, float sbw[4])
142 {
143 gs_font_cid2 *const pfcid = (gs_font_cid2 *)pfont;
144 int skip = pfcid->cidata.MetricsCount << 1;
145 gs_glyph_data_t gdata;
146 const byte *pmetrics;
147 int lsb, width;
148 int code = 0;
149 int wmode = gs_type42_metrics_options_wmode(options);
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, options, sbw);
157 if(gs_type42_metrics_options_bbox_requested(options)) {
158 code = pfcid->cidata.orig_procs.get_metrics(pfont, glyph_index,
159 gs_type42_metrics_options_BBOX, sbw);;
160 if (code < 0)
161 return code;
162 }
163 if (gs_type42_metrics_options_sbw_requested(options)) {
164 pmetrics = gdata.bits.data + skip - 4 - (wmode << 2);
165 lsb = GET_S16_MSB(pmetrics + 2);
166 width = GET_U16_MSB(pmetrics + 0);
167 {
168 double factor = 1.0 / pfont->data.unitsPerEm;
169
170 if (wmode) {
171 sbw[0] = 0, sbw[1] = -lsb * factor;
172 sbw[2] = 0, sbw[3] = -width * factor;
173 } else {
174 sbw[0] = lsb * factor, sbw[1] = 0;
175 sbw[2] = width * factor, sbw[3] = 0;
176 }
177 }
178 }
179 gs_glyph_data_free(&gdata, "z11_get_metrics");
180 return 0;
181 }
182
183 static int
z11_glyph_info_aux(gs_font * font,gs_glyph glyph,const gs_matrix * pmat,int members,gs_glyph_info_t * info)184 z11_glyph_info_aux(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
185 int members, gs_glyph_info_t *info)
186 {
187 gs_font_cid2 *fontCID2 = (gs_font_cid2 *)font;
188 uint glyph_index;
189 int code = (glyph > GS_MIN_GLYPH_INDEX
190 ? glyph - GS_MIN_GLYPH_INDEX
191 : fontCID2->cidata.CIDMap_proc(fontCID2, glyph));
192
193 if(code < 0)
194 return code;
195 glyph_index = (uint)code;
196 return gs_type42_glyph_info_by_gid(font, glyph, pmat, members, info, glyph_index);
197 }
198
199 static int
z11_glyph_info(gs_font * font,gs_glyph glyph,const gs_matrix * pmat,int members,gs_glyph_info_t * info)200 z11_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
201 int members, gs_glyph_info_t *info)
202 {
203 int wmode = (members & GLYPH_INFO_WIDTH0 ? 0 : 1);
204
205 return z1_glyph_info_generic(font, glyph, pmat, members, info,
206 &z11_glyph_info_aux, wmode);
207 }
208
209
210 /* Enumerate glyphs (keys) from GlyphDirectory instead of loca / glyf. */
211 static int
z11_enumerate_glyph(gs_font * font,int * pindex,gs_glyph_space_t glyph_space,gs_glyph * pglyph)212 z11_enumerate_glyph(gs_font *font, int *pindex,
213 gs_glyph_space_t glyph_space, gs_glyph *pglyph)
214 {
215 gs_font_cid2 *pfont = (gs_font_cid2 *)font;
216 int code0 = z11_CIDMap_proc(pfont, GS_MIN_CID_GLYPH);
217 int code;
218
219 if(*pindex > pfont->cidata.common.CIDCount)
220 return_error(e_rangecheck);
221
222 for (;;) {
223 code = z11_CIDMap_proc(pfont, GS_MIN_CID_GLYPH + *pindex);
224
225 if (code < 0) {
226 *pindex = 0;
227 return 0;
228 }
229 (*pindex)++;
230 if (*pindex == 1 || code != code0)
231 break;
232 /* else skip an underfined glyph */
233 }
234 if (glyph_space == GLYPH_SPACE_INDEX)
235 *pglyph = GS_MIN_GLYPH_INDEX + (uint)code;
236 else
237 *pglyph = GS_MIN_CID_GLYPH + (uint)(*pindex - 1);
238 return 0;
239 }
240
241 static uint
z11_get_glyph_index(gs_font_type42 * pfont,gs_glyph glyph)242 z11_get_glyph_index(gs_font_type42 *pfont, gs_glyph glyph)
243 {
244 int code = z11_CIDMap_proc((gs_font_cid2 *)pfont, glyph);
245
246 return (code < 0 ? 0 /* notdef */: (uint)code);
247 }
248
249
250 static int
z11_glyph_outline(gs_font * font,int WMode,gs_glyph glyph,const gs_matrix * pmat,gx_path * ppath,double sbw[4])251 z11_glyph_outline(gs_font *font, int WMode, gs_glyph glyph, const gs_matrix *pmat,
252 gx_path *ppath, double sbw[4])
253 {
254 return gs_type42_glyph_outline(font, WMode,
255 z11_get_glyph_index((gs_font_type42 *)font, glyph) + GS_MIN_GLYPH_INDEX,
256 pmat, ppath, sbw);
257 }
258
259 static int
get_subst_CID_on_WMode(gs_subst_CID_on_WMode_t * subst,ref * t,int WMode)260 get_subst_CID_on_WMode(gs_subst_CID_on_WMode_t *subst, ref *t, int WMode)
261 {
262 ref r, *a, e;;
263
264 make_int(&r, WMode);
265 if (dict_find(t, &r, &a) > 0 && r_type(a) == t_array) {
266 int n = r_size(a), i;
267 uint *s;
268
269 s = (uint *)gs_alloc_byte_array(subst->rc.memory, n, sizeof(int), "zbuildfont11");
270 if (s == NULL)
271 return_error(e_VMerror);
272 for (i = 0; i < n; i++) {
273 array_get(subst->rc.memory, a, (long)i, &e);
274 if (r_type(&e) != t_integer)
275 return_error(e_invalidfont);
276 s[i] = e.value.intval;
277 }
278 subst->data[WMode] = s;
279 subst->size[WMode] = n;
280 }
281 return 0;
282 }
283
284 static GS_NOTIFY_PROC(release_subst_CID_on_WMode);
285
286 static int
release_subst_CID_on_WMode(void * data,void * event)287 release_subst_CID_on_WMode(void *data, void *event)
288 {
289 gs_font_cid2 *pfcid = (gs_font_cid2 *)data;
290 gs_subst_CID_on_WMode_t *subst = pfcid->subst_CID_on_WMode;
291
292 gs_font_notify_unregister((gs_font *)pfcid, release_subst_CID_on_WMode, data);
293 pfcid->subst_CID_on_WMode = NULL;
294 rc_adjust(subst, -2, "release_subst_CID_on_WMode");
295 return 0;
296 }
297
298 static uint
font11_substitute_glyph_index_vertical(gs_font_type42 * pfont,uint glyph_index,int WMode,gs_glyph glyph)299 font11_substitute_glyph_index_vertical(gs_font_type42 *pfont, uint glyph_index,
300 int WMode, gs_glyph glyph)
301 {
302 gs_font_cid2 *pfcid = (gs_font_cid2 *)pfont;
303 uint cid = (glyph >= GS_MIN_CID_GLYPH ? glyph - GS_MIN_CID_GLYPH : glyph);
304 int WMode1 = !WMode;\
305 gs_subst_CID_on_WMode_t *s = pfcid->subst_CID_on_WMode;
306
307 if (s != NULL) {
308 uint *subst = s->data[WMode1];
309 int bi, ei, i;
310
311 /* Binary search for cid in subst (2-int elements) : */
312 bi = 0;
313 ei = pfcid->subst_CID_on_WMode->size[WMode1];
314
315 if (ei > 0) {
316 for (;;) {
317 i = ((bi + ei) / 2) & ~1;
318 if (subst[i] == cid) {
319 WMode = WMode1;
320 break;
321 }
322 if (bi + 2 >= ei)
323 break;
324 if (subst[i] > cid)
325 ei = i;
326 else
327 bi = i;
328 }
329 }
330 }
331 return gs_type42_substitute_glyph_index_vertical(pfont, glyph_index, WMode, glyph);
332 }
333
334 /* ------ Defining ------ */
335
336 extern_st(st_subst_CID_on_WMode);
337
338 /* <string|name> <font_dict> .buildfont11 <string|name> <font> */
339 static int
zbuildfont11(i_ctx_t * i_ctx_p)340 zbuildfont11(i_ctx_t *i_ctx_p)
341 {
342 os_ptr op = osp;
343 gs_font_cid_data common;
344 gs_font_type42 *pfont;
345 gs_font_cid2 *pfcid;
346 int MetricsCount;
347 ref rcidmap, ignore_gdir, file, *pfile, cfnstr, *pCIDFontName, CIDFontName, *t;
348 ulong loca_glyph_pos[2][2];
349 int code = cid_font_data_param(op, &common, &ignore_gdir);
350
351 if (code < 0 ||
352 (code = dict_find_string(op, "CIDFontName", &pCIDFontName)) <= 0 ||
353 (code = dict_int_param(op, "MetricsCount", 0, 4, 0, &MetricsCount)) < 0
354 )
355 return code;
356 /*
357 * Since build_gs_simple_font may resize the dictionary and cause
358 * pointers to become invalid, save CIDFontName
359 */
360 CIDFontName = *pCIDFontName;
361 if (MetricsCount & 1) /* only allowable values are 0, 2, 4 */
362 return_error(e_rangecheck);
363 code = dict_find_string(op, "File", &pfile);
364 if (code < 0 && code != e_undefined)
365 return code;
366 if (code > 0) {
367 ref *file_table_pos, *a, v;
368 const char *name[2] = {"loca", "glyf"};
369 int i, j;
370
371 /*
372 * Since build_gs_simple_font may resize the dictionary and cause
373 * pointers to become invalid, save File and CIDFontName
374 */
375 file = *pfile;
376 check_read_type(file, t_file);
377 code = dict_find_string(op, "file_table_pos", &file_table_pos);
378 if (code <= 0 || r_type(file_table_pos) != t_dictionary)
379 return_error(e_invalidfont);
380 for (i = 0; i < 2; i++) {
381 code = dict_find_string(file_table_pos, name[i], &a);
382 if (code <= 0 || r_type(a) != t_array)
383 return_error(e_invalidfont);
384 for (j = 0; j < 2; j++) {
385 code = array_get(imemory, a, j, &v);
386 if (code < 0 || r_type(&v) != t_integer)
387 return_error(e_invalidfont);
388 loca_glyph_pos[i][j] = v.value.intval;
389 }
390 }
391 } else
392 pfile = NULL;
393 code = font_string_array_param(imemory, op, "CIDMap", &rcidmap);
394 switch (code) {
395 case 0: /* in PLRM3 */
396 gdb:
397 /* GDBytes is required for indexing a string or string array. */
398 if (common.GDBytes == 0)
399 return_error(e_rangecheck);
400 break;
401 default:
402 return code;
403 case e_typecheck:
404 switch (r_type(&rcidmap)) {
405 case t_string: /* in PLRM3 */
406 goto gdb;
407 case t_dictionary: /* added in 3011 */
408 case t_integer: /* added in 3011 */
409 break;
410 default:
411 return code;
412 }
413 break;
414 }
415 code = build_gs_TrueType_font(i_ctx_p, op, &pfont, ft_CID_TrueType,
416 &st_gs_font_cid2,
417 (const char *)0, "%Type11BuildGlyph",
418 bf_Encoding_optional |
419 bf_UniqueID_ignored |
420 bf_CharStrings_optional |
421 (pfile != NULL ? bf_has_font_file : 0));
422 if (code < 0)
423 return code;
424 pfcid = (gs_font_cid2 *)pfont;
425 if (dict_find_string(op, "subst_CID_on_WMode", &t) > 0 && r_type(t) == t_dictionary) {
426 gs_subst_CID_on_WMode_t *subst = NULL;
427 ref *o;
428 gs_font *font;
429
430 if (dict_find_string(t, "Ordering", &o) <= 0 || r_type(o) != t_string)
431 return_error(e_invalidfont);
432 for (font = ifont_dir->orig_fonts; font != NULL; font = font->next) {
433 if (font->FontType == ft_CID_TrueType) {
434 gs_font_cid2 *pfcid1 = (gs_font_cid2 *)font;
435 if (pfcid1->subst_CID_on_WMode != NULL &&
436 bytes_compare(o->value.const_bytes, r_size(o),
437 pfcid1->cidata.common.CIDSystemInfo.Ordering.data,
438 pfcid1->cidata.common.CIDSystemInfo.Ordering.size)) {
439 subst = pfcid1->subst_CID_on_WMode;
440 break;
441 }
442 }
443 }
444 if (subst == NULL) {
445 rc_alloc_struct_1(subst, gs_subst_CID_on_WMode_t, &st_subst_CID_on_WMode,
446 pfcid->memory, return_error(e_VMerror), "zbuildfont11");
447 subst->data[0] = subst->data[1] = 0;
448 pfcid->subst_CID_on_WMode = subst;
449 code = get_subst_CID_on_WMode(subst, t, 0);
450 if (code < 0)
451 return code;
452 code = get_subst_CID_on_WMode(subst, t, 1);
453 if (code < 0)
454 return code;
455 } else {
456 pfcid->subst_CID_on_WMode = subst;
457 rc_increment(subst);
458 }
459 code = gs_font_notify_register((gs_font *)pfcid, release_subst_CID_on_WMode, (void *)pfcid);
460 if (code < 0)
461 return code;
462 rc_increment(subst);
463 }
464 pfcid->cidata.common = common;
465 pfcid->cidata.MetricsCount = MetricsCount;
466 ref_assign(&pfont_data(pfont)->u.type42.CIDMap, &rcidmap);
467 pfcid->cidata.CIDMap_proc = z11_CIDMap_proc;
468 pfcid->data.substitute_glyph_index_vertical = font11_substitute_glyph_index_vertical;
469 pfont->procs.enumerate_glyph = z11_enumerate_glyph;
470 pfont->procs.glyph_info = z11_glyph_info;
471 pfont->procs.glyph_outline = z11_glyph_outline;
472 pfont->data.get_glyph_index = z11_get_glyph_index;
473 if (pfcid->font_name.size == 0) {
474 get_font_name(imemory, &cfnstr, &CIDFontName);
475 copy_font_name(&pfcid->font_name, &cfnstr);
476 }
477 if (MetricsCount) {
478 /* "Wrap" the glyph accessor procedures. */
479 pfcid->cidata.orig_procs.get_outline = pfont->data.get_outline;
480 pfont->data.get_outline = z11_get_outline;
481 pfcid->cidata.orig_procs.get_metrics = pfont->data.get_metrics;
482 pfont->data.get_metrics = z11_get_metrics;
483 } else if(pfile != NULL) {
484 /*
485 * We assume that disk fonts has no MetricsCount.
486 * We could do not, but the number of virtual function wariants increases.
487 */
488 stream *s;
489
490 check_read_file(s, &file);
491 pfont->data.loca = loca_glyph_pos[0][0];
492 pfont->data.glyf = loca_glyph_pos[1][0];
493 pfont->data.get_outline = gs_get_glyph_data_cached;
494 pfont->data.gdcache = gs_glyph_cache__alloc(pfont, s, gs_type42_get_outline_from_TT_file);
495 }
496 return define_gs_font((gs_font *)pfont);
497 }
498
499 /* <cid11font> <cid> .type11mapcid <glyph_index> */
500 static int
ztype11mapcid(i_ctx_t * i_ctx_p)501 ztype11mapcid(i_ctx_t *i_ctx_p)
502 {
503 os_ptr op = osp;
504 gs_font *pfont;
505 int code = font_param(op - 1, &pfont);
506
507 if (code < 0)
508 return code;
509 check_type(*op, t_integer);
510 #if defined(TEST)
511 /* Allow a Type 42 font here, for testing .wrapfont. */
512 if (pfont->FontType == ft_TrueType) {
513 /* Use the CID as the glyph index. */
514 if (op->value.intval < 0 ||
515 op->value.intval >= ((gs_font_type42 *)pfont)->data.numGlyphs
516 )
517 return_error(e_rangecheck);
518 code = (int)op->value.intval;
519 } else
520 #endif
521 {
522 if (pfont->FontType != ft_CID_TrueType)
523 return_error(e_invalidfont);
524 code = z11_CIDMap_proc((gs_font_cid2 *)pfont,
525 (gs_glyph)(gs_min_cid_glyph + op->value.intval));
526 }
527 if (code < 0)
528 return code;
529 make_int(op - 1, code);
530 pop(1);
531 return 0;
532 }
533
534 /* <Decoding> <TT_cmap> <SubstNWP> <GDBytes> <CIDMap> .fillCIDMap - */
535 static int
zfillCIDMap(i_ctx_t * i_ctx_p)536 zfillCIDMap(i_ctx_t *i_ctx_p)
537 {
538 os_ptr op = osp;
539 ref *Decoding = op - 4, *TT_cmap = op - 3, *SubstNWP = op - 2,
540 *GDBytes = op - 1, *CIDMap = op;
541 int code;
542
543 check_type(*Decoding, t_dictionary);
544 check_type(*TT_cmap, t_dictionary);
545 check_type(*SubstNWP, t_array);
546 check_type(*GDBytes, t_integer);
547 check_type(*CIDMap, t_array);
548 code = cid_fill_CIDMap(imemory, Decoding, TT_cmap, SubstNWP, GDBytes->value.intval, CIDMap);
549 pop(5);
550 return code;
551 }
552
553 static int
zfillIdentityCIDMap(i_ctx_t * i_ctx_p)554 zfillIdentityCIDMap(i_ctx_t *i_ctx_p)
555 {
556 os_ptr op = osp;
557 ref *Decoding = op - 4, *TT_cmap = op - 3, *SubstNWP = op - 2,
558 *GDBytes = op - 1, *CIDMap = op;
559 int code;
560
561 check_type(*CIDMap, t_array);
562 code = cid_fill_Identity_CIDMap(imemory, CIDMap);
563 pop(1);
564 return code;
565 }
566
567 /* ------ Initialization procedure ------ */
568
569 const op_def zfcid1_op_defs[] =
570 {
571 {"2.buildfont10", zbuildfont10},
572 {"2.buildfont11", zbuildfont11},
573 {"2.type11mapcid", ztype11mapcid},
574 {"2.fillCIDMap", zfillCIDMap},
575 {"2.fillIdentityCIDMap", zfillIdentityCIDMap},
576 op_def_end(0)
577 };
578