xref: /plan9/sys/src/cmd/gs/src/zfcid0.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 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: zfcid0.c,v 1.25 2004/11/19 04:39:11 ray Exp $ */
18 /* CIDFontType 0 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 "gxfcid.h"
26 #include "gxfont1.h"
27 #include "gxalloc.h"		/* for gs_ref_memory_t */
28 #include "stream.h"		/* for files.h */
29 #include "bfont.h"
30 #include "files.h"
31 #include "ichar.h"
32 #include "ichar1.h"
33 #include "icid.h"
34 #include "idict.h"
35 #include "idparam.h"
36 #include "ifcid.h"
37 #include "ifont1.h"
38 #include "ifont2.h"
39 #include "ifont42.h"
40 #include "store.h"
41 
42 /* Type 1 font procedures (defined in zchar1.c) */
43 font_proc_glyph_outline(zcharstring_glyph_outline);
44 
45 /* ---------------- CIDFontType 0 (FontType 9) ---------------- */
46 
47 /* ------ Accessing ------ */
48 
49 /* Parse a multi-byte integer from a string. */
50 private int
get_index(gs_glyph_data_t * pgd,int count,ulong * pval)51 get_index(gs_glyph_data_t *pgd, int count, ulong *pval)
52 {
53     int i;
54 
55     if (pgd->bits.size < count)
56 	return_error(e_rangecheck);
57     *pval = 0;
58     for (i = 0; i < count; ++i)
59 	*pval = (*pval << 8) + pgd->bits.data[i];
60     pgd->bits.data += count;
61     pgd->bits.size -= count;
62     return 0;
63 }
64 
65 /* Get bytes from GlyphData or DataSource. */
66 private int
cid0_read_bytes(gs_font_cid0 * pfont,ulong base,uint count,byte * buf,gs_glyph_data_t * pgd)67 cid0_read_bytes(gs_font_cid0 *pfont, ulong base, uint count, byte *buf,
68 		gs_glyph_data_t *pgd)
69 {
70     const font_data *pfdata = pfont_data(pfont);
71     byte *data = buf;
72     gs_font *gdfont = 0;	/* pfont if newly allocated, 0 if not */
73     int code = 0;
74 
75     /* Check for overflow. */
76     if (base != (long)base || base > base + count)
77 	return_error(e_rangecheck);
78     if (r_has_type(&pfdata->u.cid0.DataSource, t_null)) {
79 	/* Get the bytes from GlyphData (a string or array of strings). */
80 	const ref *pgdata = &pfdata->u.cid0.GlyphData;
81 
82 	if (r_has_type(pgdata, t_string)) {  /* single string */
83 	    uint size = r_size(pgdata);
84 
85 	    if (base >= size || count > size - base)
86 		return_error(e_rangecheck);
87 	    data = pgdata->value.bytes + base;
88 	} else {		/* array of strings */
89 	    /*
90 	     * The algorithm is similar to the one in
91 	     * string_array_access_proc in zfont42.c, but it also has to
92 	     * deal with the case where the requested string crosses array
93 	     * elements.
94 	     */
95 	    ulong skip = base;
96 	    uint copied = 0;
97 	    uint index = 0;
98 	    ref rstr;
99 	    uint size;
100 
101 	    for (;; skip -= size, ++index) {
102 		int code = array_get(pfont->memory, pgdata, index, &rstr);
103 
104 		if (code < 0)
105 		    return code;
106 		if (!r_has_type(&rstr, t_string))
107 		    return_error(e_typecheck);
108 		size = r_size(&rstr);
109 		if (skip < size)
110 		    break;
111 	    }
112 	    size -= skip;
113 	    if (count <= size) {
114 		data = rstr.value.bytes + skip;
115 	    } else {		/* multiple strings needed */
116 		if (data == 0) {  /* no buffer provided */
117 		    data = gs_alloc_string(pfont->memory, count,
118 					   "cid0_read_bytes");
119 		    if (data == 0)
120 			return_error(e_VMerror);
121 		    gdfont = (gs_font *)pfont; /* newly allocated */
122 		}
123 		memcpy(data, rstr.value.bytes + skip, size);
124 		copied = size;
125 		while (copied < count) {
126 		    int code = array_get(pfont->memory, pgdata, ++index, &rstr);
127 
128 		    if (code < 0)
129 			goto err;
130 		    if (!r_has_type(&rstr, t_string)) {
131 			code = gs_note_error(e_typecheck);
132 			goto err;
133 		    }
134 		    size = r_size(&rstr);
135 		    if (size > count - copied)
136 			size = count - copied;
137 		    memcpy(data + copied, rstr.value.bytes, size);
138 		    copied += size;
139 		}
140 	    }
141 	}
142     } else {
143 	/* Get the bytes from DataSource (a stream). */
144 	stream *s;
145 	uint nread;
146 
147 	check_read_known_file(s, &pfdata->u.cid0.DataSource, return_error);
148 	if (sseek(s, base) < 0)
149 	    return_error(e_ioerror);
150 	if (data == 0) {	/* no buffer provided */
151 	    data = gs_alloc_string(pfont->memory, count, "cid0_read_bytes");
152 	    if (data == 0)
153 		return_error(e_VMerror);
154 	    gdfont = (gs_font *)pfont; /* newly allocated */
155 	}
156 	if (sgets(s, data, count, &nread) < 0 || nread != count) {
157 	    code = gs_note_error(e_ioerror);
158 	    goto err;
159 	}
160     }
161     gs_glyph_data_from_string(pgd, data, count, gdfont);
162     return code;
163  err:
164     if (data != buf)
165 	gs_free_string(pfont->memory, data, count, "cid0_read_bytes");
166     return code;
167 }
168 
169 /* Get the CharString data for a CIDFontType 0 font. */
170 /* This is the glyph_data procedure in the font itself. */
171 /* Note that pgd may be NULL. */
172 private int
z9_glyph_data(gs_font_base * pbfont,gs_glyph glyph,gs_glyph_data_t * pgd,int * pfidx)173 z9_glyph_data(gs_font_base *pbfont, gs_glyph glyph, gs_glyph_data_t *pgd,
174 	      int *pfidx)
175 {
176     gs_font_cid0 *pfont = (gs_font_cid0 *)pbfont;
177     const font_data *pfdata = pfont_data(pfont);
178     long glyph_index = (long)(glyph - gs_min_cid_glyph);
179     gs_glyph_data_t gdata;
180     ulong fidx;
181     int code;
182 
183     gdata.memory = pfont->memory;
184     if (!r_has_type(&pfdata->u.cid0.GlyphDirectory, t_null)) {
185         code = font_gdir_get_outline(pfont->memory,
186 				     &pfdata->u.cid0.GlyphDirectory,
187 				     glyph_index, &gdata);
188 	if (code < 0)
189 	    return code;
190 	/* Get the definition from GlyphDirectory. */
191 	if (!gdata.bits.data)
192 	    return_error(e_rangecheck);
193 	code = get_index(&gdata, pfont->cidata.FDBytes, &fidx);
194 	if (code < 0)
195 	    return code;
196 	if (fidx >= pfont->cidata.FDArray_size)
197 	    return_error(e_rangecheck);
198 	if (pgd)
199 	    *pgd = gdata;
200 	*pfidx = (int)fidx;
201 	return code;
202     }
203     /* Get the definition from the binary data (GlyphData or DataSource). */
204     if (glyph_index < 0 || glyph_index >= pfont->cidata.common.CIDCount) {
205 	*pfidx = 0;
206 	if (pgd)
207 	    gs_glyph_data_from_null(pgd);
208 	return_error(e_rangecheck);
209     }
210     {
211 	byte fd_gd[(MAX_FDBytes + MAX_GDBytes) * 2];
212 	uint num_bytes = pfont->cidata.FDBytes + pfont->cidata.common.GDBytes;
213 	ulong base = pfont->cidata.CIDMapOffset + glyph_index * num_bytes;
214 	ulong gidx, fidx_next, gidx_next;
215 	int rcode = cid0_read_bytes(pfont, base, (ulong)(num_bytes * 2), fd_gd,
216 				    &gdata);
217 	gs_glyph_data_t orig_data;
218 
219 	if (rcode < 0)
220 	    return rcode;
221 	orig_data = gdata;
222 	if ((code = get_index(&gdata, pfont->cidata.FDBytes, &fidx)) < 0 ||
223 	    (code = get_index(&gdata, pfont->cidata.common.GDBytes, &gidx)) < 0 ||
224 	    (code = get_index(&gdata, pfont->cidata.FDBytes, &fidx_next)) < 0 ||
225 	    (code = get_index(&gdata, pfont->cidata.common.GDBytes, &gidx_next)) < 0
226 	    )
227 	    DO_NOTHING;
228 	gs_glyph_data_free(&orig_data, "z9_glyph_data");
229 	if (code < 0)
230 	    return code;
231 	/*
232 	 * Some CID fonts (from Adobe!) have invalid font indexes for
233 	 * missing glyphs.  Handle this now.
234 	 */
235 	if (gidx_next <= gidx) { /* missing glyph */
236 	    *pfidx = 0;
237 	    if (pgd)
238 		gs_glyph_data_from_null(pgd);
239 	    return_error(e_undefined);
240 	}
241 	if (fidx >= pfont->cidata.FDArray_size)
242 	    return_error(e_rangecheck);
243 	*pfidx = (int)fidx;
244 	if (pgd == 0)
245 	    return 0;
246 	return cid0_read_bytes(pfont, gidx, gidx_next - gidx, NULL, pgd);
247     }
248 }
249 
250 /* Get the outline of a CIDFontType 0 glyph. */
251 private int
z9_glyph_outline(gs_font * font,int WMode,gs_glyph glyph,const gs_matrix * pmat,gx_path * ppath,double sbw[4])252 z9_glyph_outline(gs_font *font, int WMode, gs_glyph glyph, const gs_matrix *pmat,
253 		 gx_path *ppath, double sbw[4])
254 {
255     gs_font_cid0 *const pfcid = (gs_font_cid0 *)font;
256     ref gref;
257     gs_glyph_data_t gdata;
258     int code, fidx, ocode;
259 
260     gdata.memory = font->memory;
261     code = pfcid->cidata.glyph_data((gs_font_base *)pfcid, glyph, &gdata,
262 				    &fidx);
263     if (code < 0)
264 	return code;
265     glyph_ref(font->memory, glyph, &gref);
266     ocode = zcharstring_outline(pfcid->cidata.FDArray[fidx], WMode, &gref, &gdata,
267 				pmat, ppath, sbw);
268     gs_glyph_data_free(&gdata, "z9_glyph_outline");
269     return ocode;
270 }
271 
272 private int
z9_glyph_info(gs_font * font,gs_glyph glyph,const gs_matrix * pmat,int members,gs_glyph_info_t * info)273 z9_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
274 		     int members, gs_glyph_info_t *info)
275 {   /* fixme : same as z11_glyph_info. */
276     int wmode = (members & GLYPH_INFO_WIDTH0 ? 0 : 1);
277 
278     return z1_glyph_info_generic(font, glyph, pmat, members, info,
279 				    &gs_default_glyph_info, wmode);
280 }
281 
282 
283 /*
284  * The "fonts" in the FDArray don't have access to their outlines -- the
285  * outlines are always provided externally.  Replace the accessor procedures
286  * with ones that will give an error if called.
287  */
288 private int
z9_FDArray_glyph_data(gs_font_type1 * pfont,gs_glyph glyph,gs_glyph_data_t * pgd)289 z9_FDArray_glyph_data(gs_font_type1 * pfont, gs_glyph glyph,
290 		      gs_glyph_data_t *pgd)
291 {
292     return_error(e_invalidfont);
293 }
294 private int
z9_FDArray_seac_data(gs_font_type1 * pfont,int ccode,gs_glyph * pglyph,gs_const_string * gstr,gs_glyph_data_t * pgd)295 z9_FDArray_seac_data(gs_font_type1 *pfont, int ccode, gs_glyph *pglyph,
296 		     gs_const_string *gstr, gs_glyph_data_t *pgd)
297 {
298     return_error(e_invalidfont);
299 }
300 
301 /* ------ Defining ------ */
302 
303 /* Get one element of a FDArray. */
304 private int
fd_array_element(i_ctx_t * i_ctx_p,gs_font_type1 ** ppfont,ref * prfd)305 fd_array_element(i_ctx_t *i_ctx_p, gs_font_type1 **ppfont, ref *prfd)
306 {
307     charstring_font_refs_t refs;
308     gs_type1_data data1;
309     build_proc_refs build;
310     gs_font_base *pbfont;
311     gs_font_type1 *pfont;
312     /*
313      * Standard CIDFontType 0 fonts have Type 1 fonts in the FDArray, but
314      * CFF CIDFontType 0 fonts have Type 2 fonts there.
315      */
316     int fonttype = 1;		/* default */
317     int code = charstring_font_get_refs(prfd, &refs);
318 
319     if (code < 0 ||
320 	(code = dict_int_param(prfd, "FontType", 1, 2, 1, &fonttype)) < 0
321 	)
322 	return code;
323     /*
324      * We don't handle the alternate Subr representation (SubrCount,
325      * SDBytes, SubrMapOffset) here: currently that is handled in
326      * PostScript code (lib/gs_cidfn.ps).
327      */
328     switch (fonttype) {
329     case 1:
330 	data1.interpret = gs_type1_interpret;
331 	data1.subroutineNumberBias = 0;
332 	data1.lenIV = DEFAULT_LENIV_1;
333 	code = charstring_font_params(imemory, prfd, &refs, &data1);
334 	if (code < 0)
335 	    return code;
336 	code = build_proc_name_refs(imemory, &build,
337 				    "%Type1BuildChar", "%Type1BuildGlyph");
338 	break;
339     case 2:
340 	code = type2_font_params(prfd, &refs, &data1);
341 	if (code < 0)
342 	    return code;
343 	code = charstring_font_params(imemory, prfd, &refs, &data1);
344 	if (code < 0)
345 	    return code;
346 	code = build_proc_name_refs(imemory, &build,
347 				    "%Type2BuildChar", "%Type2BuildGlyph");
348 	break;
349     default:			/* can't happen */
350 	return_error(e_Fatal);
351     }
352     if (code < 0)
353 	return code;
354     code = build_gs_FDArray_font(i_ctx_p, prfd, &pbfont, fonttype,
355 				 &st_gs_font_type1, &build);
356     if (code < 0)
357 	return code;
358     pfont = (gs_font_type1 *)pbfont;
359     pbfont->FAPI = NULL;
360     pbfont->FAPI_font_data = NULL;
361     charstring_font_init(pfont, &refs, &data1);
362     pfont->data.procs.glyph_data = z9_FDArray_glyph_data;
363     pfont->data.procs.seac_data = z9_FDArray_seac_data;
364     *ppfont = pfont;
365     return 0;
366 }
367 
368 
369 
370 private int
notify_remove_font_type9(void * proc_data,void * event_data)371 notify_remove_font_type9(void *proc_data, void *event_data)
372 {  /* Likely type 9 font descendents are never released explicitly.
373       So releaseing a type 9 font we must reset pointers in descendents.
374     */
375     /* gs_font_finalize passes event_data == NULL, so check it here. */
376     if (event_data == NULL) {
377         gs_font_cid0 *pfcid = proc_data;
378 	int i;
379 
380 	for (i = 0; i < pfcid->cidata.FDArray_size; ++i) {
381 	    if (pfcid->cidata.FDArray[i]->data.parent == (gs_font_base *)pfcid)
382 		pfcid->cidata.FDArray[i]->data.parent = NULL;
383 	}
384     }
385     return 0;
386 }
387 
388 /* <string|name> <font_dict> .buildfont9 <string|name> <font> */
389 private int
zbuildfont9(i_ctx_t * i_ctx_p)390 zbuildfont9(i_ctx_t *i_ctx_p)
391 {
392     os_ptr op = osp;
393     build_proc_refs build;
394     int code = build_proc_name_refs(imemory, &build, NULL, "%Type9BuildGlyph");
395     gs_font_cid_data common;
396     ref GlyphDirectory, GlyphData, DataSource;
397     ref *prfda, cfnstr;
398     ref *pCIDFontName, CIDFontName;
399     gs_font_type1 **FDArray;
400     uint FDArray_size;
401     int FDBytes;
402     uint CIDMapOffset;
403     gs_font_base *pfont;
404     gs_font_cid0 *pfcid;
405     uint i;
406 
407     /*
408      * If the CIDFont's data have been loaded into VM, GlyphData will be
409      * a string or an array of strings; if they are loaded incrementally
410      * from a file, GlyphData will be an integer, and DataSource will be
411      * a (reusable) stream.
412      */
413     if (code < 0 ||
414 	(code = cid_font_data_param(op, &common, &GlyphDirectory)) < 0 ||
415 	(code = dict_find_string(op, "FDArray", &prfda)) < 0 ||
416 	(code = dict_find_string(op, "CIDFontName", &pCIDFontName)) <= 0 ||
417 	(code = dict_int_param(op, "FDBytes", 0, MAX_FDBytes, -1, &FDBytes)) < 0
418 	)
419 	return code;
420     /*
421      * Since build_gs_simple_font may resize the dictionary and cause
422      * pointers to become invalid, save CIDFontName
423      */
424     CIDFontName = *pCIDFontName;
425     if (r_has_type(&GlyphDirectory, t_null)) {
426 	/* Standard CIDFont, require GlyphData and CIDMapOffset. */
427 	ref *pGlyphData;
428 
429 	if ((code = dict_find_string(op, "GlyphData", &pGlyphData)) < 0 ||
430 	    (code = dict_uint_param(op, "CIDMapOffset", 0, max_uint - 1,
431 				    max_uint, &CIDMapOffset)) < 0)
432 	    return code;
433 	GlyphData = *pGlyphData;
434 	if (r_has_type(&GlyphData, t_integer)) {
435 	    ref *pds;
436 	    stream *ignore_s;
437 
438 	    if ((code = dict_find_string(op, "DataSource", &pds)) < 0)
439 		return code;
440 	    check_read_file(ignore_s, pds);
441 	    DataSource = *pds;
442 	} else {
443 	    if (!r_has_type(&GlyphData, t_string) && !r_is_array(&GlyphData))
444 		return_error(e_typecheck);
445 	    make_null(&DataSource);
446 	}
447     } else {
448 	make_null(&GlyphData);
449 	make_null(&DataSource);
450 	CIDMapOffset = 0;
451     }
452     if (!r_is_array(prfda))
453 	return_error(e_invalidfont);
454     FDArray_size = r_size(prfda);
455     if (FDArray_size == 0)
456 	return_error(e_invalidfont);
457     FDArray = ialloc_struct_array(FDArray_size, gs_font_type1 *,
458 				  &st_gs_font_type1_ptr_element,
459 				  "buildfont9(FDarray)");
460     if (FDArray == 0)
461 	return_error(e_VMerror);
462     memset(FDArray, 0, sizeof(gs_font_type1 *) * FDArray_size);
463     for (i = 0; i < FDArray_size; ++i) {
464 	ref rfd;
465 
466 	array_get(imemory, prfda, (long)i, &rfd);
467 	code = fd_array_element(i_ctx_p, &FDArray[i], &rfd);
468 	if (code < 0)
469 	    goto fail;
470     }
471     code = build_gs_simple_font(i_ctx_p, op, &pfont, ft_CID_encrypted,
472 				&st_gs_font_cid0, &build,
473 				bf_Encoding_optional |
474 				bf_UniqueID_ignored);
475     if (code < 0)
476 	goto fail;
477     pfont->procs.enumerate_glyph = gs_font_cid0_enumerate_glyph;
478     pfont->procs.glyph_outline = z9_glyph_outline;
479     pfont->procs.glyph_info = z9_glyph_info;
480     pfcid = (gs_font_cid0 *)pfont;
481     pfcid->cidata.common = common;
482     pfcid->cidata.CIDMapOffset = CIDMapOffset;
483     pfcid->cidata.FDArray = FDArray;
484     pfcid->cidata.FDArray_size = FDArray_size;
485     pfcid->cidata.FDBytes = FDBytes;
486     pfcid->cidata.glyph_data = z9_glyph_data;
487     pfcid->cidata.proc_data = 0;	/* for GC */
488     get_font_name(imemory, &cfnstr, &CIDFontName);
489     copy_font_name(&pfcid->font_name, &cfnstr);
490     ref_assign(&pfont_data(pfont)->u.cid0.GlyphDirectory, &GlyphDirectory);
491     ref_assign(&pfont_data(pfont)->u.cid0.GlyphData, &GlyphData);
492     ref_assign(&pfont_data(pfont)->u.cid0.DataSource, &DataSource);
493     code = define_gs_font((gs_font *)pfont);
494     if (code >= 0)
495        code = gs_notify_register(&pfont->notify_list, notify_remove_font_type9, pfont);
496     if (code >= 0) {
497 	for (i = 0; i < FDArray_size; ++i) {
498 	    FDArray[i]->dir = pfont->dir;
499 	    FDArray[i]->data.parent = pfont;
500 	}
501 	return code;
502     }
503  fail:
504     ifree_object(FDArray, "buildfont9(FDarray)");
505     return code;
506 }
507 
508 /* <cid9font> <cid> .type9mapcid <charstring> <font_index> */
509 int
ztype9mapcid(i_ctx_t * i_ctx_p)510 ztype9mapcid(i_ctx_t *i_ctx_p)
511 {
512     os_ptr op = osp;
513     gs_font *pfont;
514     gs_font_cid0 *pfcid;
515     int code = font_param(op - 1, &pfont);
516     gs_glyph_data_t gdata;
517     int fidx;
518 
519     if (code < 0)
520 	return code;
521     if (pfont->FontType != ft_CID_encrypted)
522 	return_error(e_invalidfont);
523     check_type(*op, t_integer);
524     pfcid = (gs_font_cid0 *)pfont;
525     gdata.memory = pfont->memory;
526     code = pfcid->cidata.glyph_data((gs_font_base *)pfcid,
527 			(gs_glyph)(gs_min_cid_glyph + op->value.intval),
528 				    &gdata, &fidx);
529 
530     /* return code; original error-sensitive & fragile code */
531     if (code < 0) { /* failed to load glyph data, put CID 0 */
532        int default_fallback_CID = 0 ;
533 
534        if_debug2('J', "[J]ztype9cidmap() use CID %d instead of glyph-missing CID %d\n", default_fallback_CID, op->value.intval);
535 
536        op->value.intval = default_fallback_CID;
537 
538        /* reload glyph for default_fallback_CID */
539 
540        code = pfcid->cidata.glyph_data((gs_font_base *)pfcid,
541                     (gs_glyph)(gs_min_cid_glyph + default_fallback_CID),
542                                    &gdata, &fidx);
543 
544        if (code < 0) {
545            if_debug1('J', "[J]ztype9cidmap() could not load default glyph (CID %d)\n", op->value.intval);
546            return_error(e_invalidfont);
547        }
548 
549     }
550 
551     /****** FOLLOWING IS NOT GENERAL W.R.T. ALLOCATION OF GLYPH DATA ******/
552     make_const_string(op - 1,
553 		      a_readonly | imemory_space((gs_ref_memory_t *)pfont->memory),
554 		      gdata.bits.size,
555 		      gdata.bits.data);
556     make_int(op, fidx);
557     return code;
558 }
559 
560 /* ------ Initialization procedure ------ */
561 
562 const op_def zfcid0_op_defs[] =
563 {
564     {"2.buildfont9", zbuildfont9},
565     {"2.type9mapcid", ztype9mapcid},
566     op_def_end(0)
567 };
568