xref: /plan9/sys/src/cmd/gs/src/zfcid1.c (revision 409b3aff3015608d158d294a437acca386aba474)
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