xref: /plan9/sys/src/cmd/gs/src/zfcid0.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
13ff48bf5SDavid du Colombier /* Copyright (C) 2000 Aladdin Enterprises.  All rights reserved.
23ff48bf5SDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
53ff48bf5SDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
93ff48bf5SDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
153ff48bf5SDavid du Colombier */
163ff48bf5SDavid du Colombier 
17*593dc095SDavid du Colombier /* $Id: zfcid0.c,v 1.25 2004/11/19 04:39:11 ray Exp $ */
183ff48bf5SDavid du Colombier /* CIDFontType 0 operators */
193ff48bf5SDavid du Colombier #include "memory_.h"
203ff48bf5SDavid du Colombier #include "ghost.h"
213ff48bf5SDavid du Colombier #include "oper.h"
223ff48bf5SDavid du Colombier #include "gsmatrix.h"
233ff48bf5SDavid du Colombier #include "gsccode.h"
243ff48bf5SDavid du Colombier #include "gsstruct.h"
253ff48bf5SDavid du Colombier #include "gxfcid.h"
263ff48bf5SDavid du Colombier #include "gxfont1.h"
273ff48bf5SDavid du Colombier #include "gxalloc.h"		/* for gs_ref_memory_t */
283ff48bf5SDavid du Colombier #include "stream.h"		/* for files.h */
293ff48bf5SDavid du Colombier #include "bfont.h"
303ff48bf5SDavid du Colombier #include "files.h"
313ff48bf5SDavid du Colombier #include "ichar.h"
323ff48bf5SDavid du Colombier #include "ichar1.h"
333ff48bf5SDavid du Colombier #include "icid.h"
343ff48bf5SDavid du Colombier #include "idict.h"
353ff48bf5SDavid du Colombier #include "idparam.h"
363ff48bf5SDavid du Colombier #include "ifcid.h"
373ff48bf5SDavid du Colombier #include "ifont1.h"
383ff48bf5SDavid du Colombier #include "ifont2.h"
393ff48bf5SDavid du Colombier #include "ifont42.h"
403ff48bf5SDavid du Colombier #include "store.h"
413ff48bf5SDavid du Colombier 
423ff48bf5SDavid du Colombier /* Type 1 font procedures (defined in zchar1.c) */
433ff48bf5SDavid du Colombier font_proc_glyph_outline(zcharstring_glyph_outline);
443ff48bf5SDavid du Colombier 
453ff48bf5SDavid du Colombier /* ---------------- CIDFontType 0 (FontType 9) ---------------- */
463ff48bf5SDavid du Colombier 
473ff48bf5SDavid du Colombier /* ------ Accessing ------ */
483ff48bf5SDavid du Colombier 
493ff48bf5SDavid du Colombier /* Parse a multi-byte integer from a string. */
503ff48bf5SDavid du Colombier private int
get_index(gs_glyph_data_t * pgd,int count,ulong * pval)51*593dc095SDavid du Colombier get_index(gs_glyph_data_t *pgd, int count, ulong *pval)
523ff48bf5SDavid du Colombier {
533ff48bf5SDavid du Colombier     int i;
543ff48bf5SDavid du Colombier 
55*593dc095SDavid du Colombier     if (pgd->bits.size < count)
563ff48bf5SDavid du Colombier 	return_error(e_rangecheck);
573ff48bf5SDavid du Colombier     *pval = 0;
583ff48bf5SDavid du Colombier     for (i = 0; i < count; ++i)
59*593dc095SDavid du Colombier 	*pval = (*pval << 8) + pgd->bits.data[i];
60*593dc095SDavid du Colombier     pgd->bits.data += count;
61*593dc095SDavid du Colombier     pgd->bits.size -= count;
623ff48bf5SDavid du Colombier     return 0;
633ff48bf5SDavid du Colombier }
643ff48bf5SDavid du Colombier 
653ff48bf5SDavid du Colombier /* Get bytes from GlyphData or DataSource. */
663ff48bf5SDavid du Colombier private int
cid0_read_bytes(gs_font_cid0 * pfont,ulong base,uint count,byte * buf,gs_glyph_data_t * pgd)673ff48bf5SDavid du Colombier cid0_read_bytes(gs_font_cid0 *pfont, ulong base, uint count, byte *buf,
68*593dc095SDavid du Colombier 		gs_glyph_data_t *pgd)
693ff48bf5SDavid du Colombier {
703ff48bf5SDavid du Colombier     const font_data *pfdata = pfont_data(pfont);
713ff48bf5SDavid du Colombier     byte *data = buf;
72*593dc095SDavid du Colombier     gs_font *gdfont = 0;	/* pfont if newly allocated, 0 if not */
733ff48bf5SDavid du Colombier     int code = 0;
743ff48bf5SDavid du Colombier 
753ff48bf5SDavid du Colombier     /* Check for overflow. */
763ff48bf5SDavid du Colombier     if (base != (long)base || base > base + count)
773ff48bf5SDavid du Colombier 	return_error(e_rangecheck);
783ff48bf5SDavid du Colombier     if (r_has_type(&pfdata->u.cid0.DataSource, t_null)) {
793ff48bf5SDavid du Colombier 	/* Get the bytes from GlyphData (a string or array of strings). */
803ff48bf5SDavid du Colombier 	const ref *pgdata = &pfdata->u.cid0.GlyphData;
813ff48bf5SDavid du Colombier 
823ff48bf5SDavid du Colombier 	if (r_has_type(pgdata, t_string)) {  /* single string */
833ff48bf5SDavid du Colombier 	    uint size = r_size(pgdata);
843ff48bf5SDavid du Colombier 
853ff48bf5SDavid du Colombier 	    if (base >= size || count > size - base)
863ff48bf5SDavid du Colombier 		return_error(e_rangecheck);
873ff48bf5SDavid du Colombier 	    data = pgdata->value.bytes + base;
883ff48bf5SDavid du Colombier 	} else {		/* array of strings */
893ff48bf5SDavid du Colombier 	    /*
903ff48bf5SDavid du Colombier 	     * The algorithm is similar to the one in
913ff48bf5SDavid du Colombier 	     * string_array_access_proc in zfont42.c, but it also has to
923ff48bf5SDavid du Colombier 	     * deal with the case where the requested string crosses array
933ff48bf5SDavid du Colombier 	     * elements.
943ff48bf5SDavid du Colombier 	     */
953ff48bf5SDavid du Colombier 	    ulong skip = base;
963ff48bf5SDavid du Colombier 	    uint copied = 0;
973ff48bf5SDavid du Colombier 	    uint index = 0;
983ff48bf5SDavid du Colombier 	    ref rstr;
993ff48bf5SDavid du Colombier 	    uint size;
1003ff48bf5SDavid du Colombier 
1013ff48bf5SDavid du Colombier 	    for (;; skip -= size, ++index) {
102*593dc095SDavid du Colombier 		int code = array_get(pfont->memory, pgdata, index, &rstr);
1033ff48bf5SDavid du Colombier 
1043ff48bf5SDavid du Colombier 		if (code < 0)
1053ff48bf5SDavid du Colombier 		    return code;
1063ff48bf5SDavid du Colombier 		if (!r_has_type(&rstr, t_string))
1073ff48bf5SDavid du Colombier 		    return_error(e_typecheck);
1083ff48bf5SDavid du Colombier 		size = r_size(&rstr);
1093ff48bf5SDavid du Colombier 		if (skip < size)
1103ff48bf5SDavid du Colombier 		    break;
1113ff48bf5SDavid du Colombier 	    }
1123ff48bf5SDavid du Colombier 	    size -= skip;
1133ff48bf5SDavid du Colombier 	    if (count <= size) {
1143ff48bf5SDavid du Colombier 		data = rstr.value.bytes + skip;
1153ff48bf5SDavid du Colombier 	    } else {		/* multiple strings needed */
1163ff48bf5SDavid du Colombier 		if (data == 0) {  /* no buffer provided */
1173ff48bf5SDavid du Colombier 		    data = gs_alloc_string(pfont->memory, count,
1183ff48bf5SDavid du Colombier 					   "cid0_read_bytes");
1193ff48bf5SDavid du Colombier 		    if (data == 0)
1203ff48bf5SDavid du Colombier 			return_error(e_VMerror);
121*593dc095SDavid du Colombier 		    gdfont = (gs_font *)pfont; /* newly allocated */
1223ff48bf5SDavid du Colombier 		}
1233ff48bf5SDavid du Colombier 		memcpy(data, rstr.value.bytes + skip, size);
1243ff48bf5SDavid du Colombier 		copied = size;
1253ff48bf5SDavid du Colombier 		while (copied < count) {
126*593dc095SDavid du Colombier 		    int code = array_get(pfont->memory, pgdata, ++index, &rstr);
1273ff48bf5SDavid du Colombier 
1283ff48bf5SDavid du Colombier 		    if (code < 0)
1293ff48bf5SDavid du Colombier 			goto err;
1303ff48bf5SDavid du Colombier 		    if (!r_has_type(&rstr, t_string)) {
1313ff48bf5SDavid du Colombier 			code = gs_note_error(e_typecheck);
1323ff48bf5SDavid du Colombier 			goto err;
1333ff48bf5SDavid du Colombier 		    }
1343ff48bf5SDavid du Colombier 		    size = r_size(&rstr);
1353ff48bf5SDavid du Colombier 		    if (size > count - copied)
1363ff48bf5SDavid du Colombier 			size = count - copied;
1373ff48bf5SDavid du Colombier 		    memcpy(data + copied, rstr.value.bytes, size);
1383ff48bf5SDavid du Colombier 		    copied += size;
1393ff48bf5SDavid du Colombier 		}
1403ff48bf5SDavid du Colombier 	    }
1413ff48bf5SDavid du Colombier 	}
1423ff48bf5SDavid du Colombier     } else {
1433ff48bf5SDavid du Colombier 	/* Get the bytes from DataSource (a stream). */
1443ff48bf5SDavid du Colombier 	stream *s;
1453ff48bf5SDavid du Colombier 	uint nread;
1463ff48bf5SDavid du Colombier 
1473ff48bf5SDavid du Colombier 	check_read_known_file(s, &pfdata->u.cid0.DataSource, return_error);
1483ff48bf5SDavid du Colombier 	if (sseek(s, base) < 0)
1493ff48bf5SDavid du Colombier 	    return_error(e_ioerror);
1503ff48bf5SDavid du Colombier 	if (data == 0) {	/* no buffer provided */
1513ff48bf5SDavid du Colombier 	    data = gs_alloc_string(pfont->memory, count, "cid0_read_bytes");
1523ff48bf5SDavid du Colombier 	    if (data == 0)
1533ff48bf5SDavid du Colombier 		return_error(e_VMerror);
154*593dc095SDavid du Colombier 	    gdfont = (gs_font *)pfont; /* newly allocated */
1553ff48bf5SDavid du Colombier 	}
1563ff48bf5SDavid du Colombier 	if (sgets(s, data, count, &nread) < 0 || nread != count) {
1573ff48bf5SDavid du Colombier 	    code = gs_note_error(e_ioerror);
1583ff48bf5SDavid du Colombier 	    goto err;
1593ff48bf5SDavid du Colombier 	}
1603ff48bf5SDavid du Colombier     }
161*593dc095SDavid du Colombier     gs_glyph_data_from_string(pgd, data, count, gdfont);
1623ff48bf5SDavid du Colombier     return code;
1633ff48bf5SDavid du Colombier  err:
1643ff48bf5SDavid du Colombier     if (data != buf)
1653ff48bf5SDavid du Colombier 	gs_free_string(pfont->memory, data, count, "cid0_read_bytes");
1663ff48bf5SDavid du Colombier     return code;
1673ff48bf5SDavid du Colombier }
1683ff48bf5SDavid du Colombier 
1693ff48bf5SDavid du Colombier /* Get the CharString data for a CIDFontType 0 font. */
1703ff48bf5SDavid du Colombier /* This is the glyph_data procedure in the font itself. */
171*593dc095SDavid du Colombier /* Note that pgd may be NULL. */
1723ff48bf5SDavid du Colombier private int
z9_glyph_data(gs_font_base * pbfont,gs_glyph glyph,gs_glyph_data_t * pgd,int * pfidx)173*593dc095SDavid du Colombier z9_glyph_data(gs_font_base *pbfont, gs_glyph glyph, gs_glyph_data_t *pgd,
1743ff48bf5SDavid du Colombier 	      int *pfidx)
1753ff48bf5SDavid du Colombier {
1763ff48bf5SDavid du Colombier     gs_font_cid0 *pfont = (gs_font_cid0 *)pbfont;
1773ff48bf5SDavid du Colombier     const font_data *pfdata = pfont_data(pfont);
1783ff48bf5SDavid du Colombier     long glyph_index = (long)(glyph - gs_min_cid_glyph);
179*593dc095SDavid du Colombier     gs_glyph_data_t gdata;
1803ff48bf5SDavid du Colombier     ulong fidx;
1813ff48bf5SDavid du Colombier     int code;
1823ff48bf5SDavid du Colombier 
183*593dc095SDavid du Colombier     gdata.memory = pfont->memory;
1843ff48bf5SDavid du Colombier     if (!r_has_type(&pfdata->u.cid0.GlyphDirectory, t_null)) {
185*593dc095SDavid du Colombier         code = font_gdir_get_outline(pfont->memory,
186*593dc095SDavid du Colombier 				     &pfdata->u.cid0.GlyphDirectory,
187*593dc095SDavid du Colombier 				     glyph_index, &gdata);
1883ff48bf5SDavid du Colombier 	if (code < 0)
1893ff48bf5SDavid du Colombier 	    return code;
1903ff48bf5SDavid du Colombier 	/* Get the definition from GlyphDirectory. */
191*593dc095SDavid du Colombier 	if (!gdata.bits.data)
192*593dc095SDavid du Colombier 	    return_error(e_rangecheck);
193*593dc095SDavid du Colombier 	code = get_index(&gdata, pfont->cidata.FDBytes, &fidx);
1943ff48bf5SDavid du Colombier 	if (code < 0)
1953ff48bf5SDavid du Colombier 	    return code;
1963ff48bf5SDavid du Colombier 	if (fidx >= pfont->cidata.FDArray_size)
1973ff48bf5SDavid du Colombier 	    return_error(e_rangecheck);
198*593dc095SDavid du Colombier 	if (pgd)
199*593dc095SDavid du Colombier 	    *pgd = gdata;
2003ff48bf5SDavid du Colombier 	*pfidx = (int)fidx;
2013ff48bf5SDavid du Colombier 	return code;
2023ff48bf5SDavid du Colombier     }
2033ff48bf5SDavid du Colombier     /* Get the definition from the binary data (GlyphData or DataSource). */
2043ff48bf5SDavid du Colombier     if (glyph_index < 0 || glyph_index >= pfont->cidata.common.CIDCount) {
2053ff48bf5SDavid du Colombier 	*pfidx = 0;
206*593dc095SDavid du Colombier 	if (pgd)
207*593dc095SDavid du Colombier 	    gs_glyph_data_from_null(pgd);
208*593dc095SDavid du Colombier 	return_error(e_rangecheck);
2093ff48bf5SDavid du Colombier     }
2103ff48bf5SDavid du Colombier     {
2113ff48bf5SDavid du Colombier 	byte fd_gd[(MAX_FDBytes + MAX_GDBytes) * 2];
2123ff48bf5SDavid du Colombier 	uint num_bytes = pfont->cidata.FDBytes + pfont->cidata.common.GDBytes;
2133ff48bf5SDavid du Colombier 	ulong base = pfont->cidata.CIDMapOffset + glyph_index * num_bytes;
2143ff48bf5SDavid du Colombier 	ulong gidx, fidx_next, gidx_next;
2153ff48bf5SDavid du Colombier 	int rcode = cid0_read_bytes(pfont, base, (ulong)(num_bytes * 2), fd_gd,
216*593dc095SDavid du Colombier 				    &gdata);
217*593dc095SDavid du Colombier 	gs_glyph_data_t orig_data;
2183ff48bf5SDavid du Colombier 
2193ff48bf5SDavid du Colombier 	if (rcode < 0)
2203ff48bf5SDavid du Colombier 	    return rcode;
221*593dc095SDavid du Colombier 	orig_data = gdata;
222*593dc095SDavid du Colombier 	if ((code = get_index(&gdata, pfont->cidata.FDBytes, &fidx)) < 0 ||
223*593dc095SDavid du Colombier 	    (code = get_index(&gdata, pfont->cidata.common.GDBytes, &gidx)) < 0 ||
224*593dc095SDavid du Colombier 	    (code = get_index(&gdata, pfont->cidata.FDBytes, &fidx_next)) < 0 ||
225*593dc095SDavid du Colombier 	    (code = get_index(&gdata, pfont->cidata.common.GDBytes, &gidx_next)) < 0
2263ff48bf5SDavid du Colombier 	    )
2273ff48bf5SDavid du Colombier 	    DO_NOTHING;
228*593dc095SDavid du Colombier 	gs_glyph_data_free(&orig_data, "z9_glyph_data");
2293ff48bf5SDavid du Colombier 	if (code < 0)
2303ff48bf5SDavid du Colombier 	    return code;
2313ff48bf5SDavid du Colombier 	/*
2323ff48bf5SDavid du Colombier 	 * Some CID fonts (from Adobe!) have invalid font indexes for
2333ff48bf5SDavid du Colombier 	 * missing glyphs.  Handle this now.
2343ff48bf5SDavid du Colombier 	 */
2353ff48bf5SDavid du Colombier 	if (gidx_next <= gidx) { /* missing glyph */
2363ff48bf5SDavid du Colombier 	    *pfidx = 0;
237*593dc095SDavid du Colombier 	    if (pgd)
238*593dc095SDavid du Colombier 		gs_glyph_data_from_null(pgd);
2393ff48bf5SDavid du Colombier 	    return_error(e_undefined);
2403ff48bf5SDavid du Colombier 	}
2413ff48bf5SDavid du Colombier 	if (fidx >= pfont->cidata.FDArray_size)
2423ff48bf5SDavid du Colombier 	    return_error(e_rangecheck);
2433ff48bf5SDavid du Colombier 	*pfidx = (int)fidx;
244*593dc095SDavid du Colombier 	if (pgd == 0)
2453ff48bf5SDavid du Colombier 	    return 0;
246*593dc095SDavid du Colombier 	return cid0_read_bytes(pfont, gidx, gidx_next - gidx, NULL, pgd);
2473ff48bf5SDavid du Colombier     }
2483ff48bf5SDavid du Colombier }
2493ff48bf5SDavid du Colombier 
2503ff48bf5SDavid du Colombier /* Get the outline of a CIDFontType 0 glyph. */
2513ff48bf5SDavid du Colombier private int
z9_glyph_outline(gs_font * font,int WMode,gs_glyph glyph,const gs_matrix * pmat,gx_path * ppath,double sbw[4])252*593dc095SDavid du Colombier z9_glyph_outline(gs_font *font, int WMode, gs_glyph glyph, const gs_matrix *pmat,
253*593dc095SDavid du Colombier 		 gx_path *ppath, double sbw[4])
2543ff48bf5SDavid du Colombier {
2553ff48bf5SDavid du Colombier     gs_font_cid0 *const pfcid = (gs_font_cid0 *)font;
2563ff48bf5SDavid du Colombier     ref gref;
257*593dc095SDavid du Colombier     gs_glyph_data_t gdata;
2583ff48bf5SDavid du Colombier     int code, fidx, ocode;
2593ff48bf5SDavid du Colombier 
260*593dc095SDavid du Colombier     gdata.memory = font->memory;
261*593dc095SDavid du Colombier     code = pfcid->cidata.glyph_data((gs_font_base *)pfcid, glyph, &gdata,
2623ff48bf5SDavid du Colombier 				    &fidx);
2633ff48bf5SDavid du Colombier     if (code < 0)
2643ff48bf5SDavid du Colombier 	return code;
265*593dc095SDavid du Colombier     glyph_ref(font->memory, glyph, &gref);
266*593dc095SDavid du Colombier     ocode = zcharstring_outline(pfcid->cidata.FDArray[fidx], WMode, &gref, &gdata,
267*593dc095SDavid du Colombier 				pmat, ppath, sbw);
268*593dc095SDavid du Colombier     gs_glyph_data_free(&gdata, "z9_glyph_outline");
2693ff48bf5SDavid du Colombier     return ocode;
2703ff48bf5SDavid du Colombier }
2713ff48bf5SDavid du Colombier 
272*593dc095SDavid du Colombier private int
z9_glyph_info(gs_font * font,gs_glyph glyph,const gs_matrix * pmat,int members,gs_glyph_info_t * info)273*593dc095SDavid du Colombier z9_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
274*593dc095SDavid du Colombier 		     int members, gs_glyph_info_t *info)
275*593dc095SDavid du Colombier {   /* fixme : same as z11_glyph_info. */
276*593dc095SDavid du Colombier     int wmode = (members & GLYPH_INFO_WIDTH0 ? 0 : 1);
277*593dc095SDavid du Colombier 
278*593dc095SDavid du Colombier     return z1_glyph_info_generic(font, glyph, pmat, members, info,
279*593dc095SDavid du Colombier 				    &gs_default_glyph_info, wmode);
280*593dc095SDavid du Colombier }
281*593dc095SDavid du Colombier 
282*593dc095SDavid du Colombier 
2833ff48bf5SDavid du Colombier /*
2843ff48bf5SDavid du Colombier  * The "fonts" in the FDArray don't have access to their outlines -- the
2853ff48bf5SDavid du Colombier  * outlines are always provided externally.  Replace the accessor procedures
2863ff48bf5SDavid du Colombier  * with ones that will give an error if called.
2873ff48bf5SDavid du Colombier  */
2883ff48bf5SDavid du Colombier private int
z9_FDArray_glyph_data(gs_font_type1 * pfont,gs_glyph glyph,gs_glyph_data_t * pgd)2893ff48bf5SDavid du Colombier z9_FDArray_glyph_data(gs_font_type1 * pfont, gs_glyph glyph,
290*593dc095SDavid du Colombier 		      gs_glyph_data_t *pgd)
2913ff48bf5SDavid du Colombier {
2923ff48bf5SDavid du Colombier     return_error(e_invalidfont);
2933ff48bf5SDavid du Colombier }
2943ff48bf5SDavid du Colombier private int
z9_FDArray_seac_data(gs_font_type1 * pfont,int ccode,gs_glyph * pglyph,gs_const_string * gstr,gs_glyph_data_t * pgd)2953ff48bf5SDavid du Colombier z9_FDArray_seac_data(gs_font_type1 *pfont, int ccode, gs_glyph *pglyph,
296*593dc095SDavid du Colombier 		     gs_const_string *gstr, gs_glyph_data_t *pgd)
2973ff48bf5SDavid du Colombier {
2983ff48bf5SDavid du Colombier     return_error(e_invalidfont);
2993ff48bf5SDavid du Colombier }
3003ff48bf5SDavid du Colombier 
3013ff48bf5SDavid du Colombier /* ------ Defining ------ */
3023ff48bf5SDavid du Colombier 
3033ff48bf5SDavid du Colombier /* Get one element of a FDArray. */
3043ff48bf5SDavid du Colombier private int
fd_array_element(i_ctx_t * i_ctx_p,gs_font_type1 ** ppfont,ref * prfd)3053ff48bf5SDavid du Colombier fd_array_element(i_ctx_t *i_ctx_p, gs_font_type1 **ppfont, ref *prfd)
3063ff48bf5SDavid du Colombier {
3073ff48bf5SDavid du Colombier     charstring_font_refs_t refs;
3083ff48bf5SDavid du Colombier     gs_type1_data data1;
3093ff48bf5SDavid du Colombier     build_proc_refs build;
3103ff48bf5SDavid du Colombier     gs_font_base *pbfont;
3113ff48bf5SDavid du Colombier     gs_font_type1 *pfont;
3123ff48bf5SDavid du Colombier     /*
3133ff48bf5SDavid du Colombier      * Standard CIDFontType 0 fonts have Type 1 fonts in the FDArray, but
3143ff48bf5SDavid du Colombier      * CFF CIDFontType 0 fonts have Type 2 fonts there.
3153ff48bf5SDavid du Colombier      */
3163ff48bf5SDavid du Colombier     int fonttype = 1;		/* default */
3173ff48bf5SDavid du Colombier     int code = charstring_font_get_refs(prfd, &refs);
3183ff48bf5SDavid du Colombier 
3193ff48bf5SDavid du Colombier     if (code < 0 ||
3203ff48bf5SDavid du Colombier 	(code = dict_int_param(prfd, "FontType", 1, 2, 1, &fonttype)) < 0
3213ff48bf5SDavid du Colombier 	)
3223ff48bf5SDavid du Colombier 	return code;
3233ff48bf5SDavid du Colombier     /*
3243ff48bf5SDavid du Colombier      * We don't handle the alternate Subr representation (SubrCount,
3253ff48bf5SDavid du Colombier      * SDBytes, SubrMapOffset) here: currently that is handled in
3263ff48bf5SDavid du Colombier      * PostScript code (lib/gs_cidfn.ps).
3273ff48bf5SDavid du Colombier      */
3283ff48bf5SDavid du Colombier     switch (fonttype) {
3293ff48bf5SDavid du Colombier     case 1:
3303ff48bf5SDavid du Colombier 	data1.interpret = gs_type1_interpret;
3313ff48bf5SDavid du Colombier 	data1.subroutineNumberBias = 0;
3323ff48bf5SDavid du Colombier 	data1.lenIV = DEFAULT_LENIV_1;
333*593dc095SDavid du Colombier 	code = charstring_font_params(imemory, prfd, &refs, &data1);
3343ff48bf5SDavid du Colombier 	if (code < 0)
3353ff48bf5SDavid du Colombier 	    return code;
336*593dc095SDavid du Colombier 	code = build_proc_name_refs(imemory, &build,
3373ff48bf5SDavid du Colombier 				    "%Type1BuildChar", "%Type1BuildGlyph");
3383ff48bf5SDavid du Colombier 	break;
3393ff48bf5SDavid du Colombier     case 2:
3403ff48bf5SDavid du Colombier 	code = type2_font_params(prfd, &refs, &data1);
3413ff48bf5SDavid du Colombier 	if (code < 0)
3423ff48bf5SDavid du Colombier 	    return code;
343*593dc095SDavid du Colombier 	code = charstring_font_params(imemory, prfd, &refs, &data1);
3443ff48bf5SDavid du Colombier 	if (code < 0)
3453ff48bf5SDavid du Colombier 	    return code;
346*593dc095SDavid du Colombier 	code = build_proc_name_refs(imemory, &build,
3473ff48bf5SDavid du Colombier 				    "%Type2BuildChar", "%Type2BuildGlyph");
3483ff48bf5SDavid du Colombier 	break;
3493ff48bf5SDavid du Colombier     default:			/* can't happen */
3503ff48bf5SDavid du Colombier 	return_error(e_Fatal);
3513ff48bf5SDavid du Colombier     }
3523ff48bf5SDavid du Colombier     if (code < 0)
3533ff48bf5SDavid du Colombier 	return code;
3543ff48bf5SDavid du Colombier     code = build_gs_FDArray_font(i_ctx_p, prfd, &pbfont, fonttype,
3553ff48bf5SDavid du Colombier 				 &st_gs_font_type1, &build);
3563ff48bf5SDavid du Colombier     if (code < 0)
3573ff48bf5SDavid du Colombier 	return code;
3583ff48bf5SDavid du Colombier     pfont = (gs_font_type1 *)pbfont;
359*593dc095SDavid du Colombier     pbfont->FAPI = NULL;
360*593dc095SDavid du Colombier     pbfont->FAPI_font_data = NULL;
3613ff48bf5SDavid du Colombier     charstring_font_init(pfont, &refs, &data1);
3623ff48bf5SDavid du Colombier     pfont->data.procs.glyph_data = z9_FDArray_glyph_data;
3633ff48bf5SDavid du Colombier     pfont->data.procs.seac_data = z9_FDArray_seac_data;
3643ff48bf5SDavid du Colombier     *ppfont = pfont;
3653ff48bf5SDavid du Colombier     return 0;
3663ff48bf5SDavid du Colombier }
3673ff48bf5SDavid du Colombier 
368*593dc095SDavid du Colombier 
369*593dc095SDavid du Colombier 
370*593dc095SDavid du Colombier private int
notify_remove_font_type9(void * proc_data,void * event_data)371*593dc095SDavid du Colombier notify_remove_font_type9(void *proc_data, void *event_data)
372*593dc095SDavid du Colombier {  /* Likely type 9 font descendents are never released explicitly.
373*593dc095SDavid du Colombier       So releaseing a type 9 font we must reset pointers in descendents.
374*593dc095SDavid du Colombier     */
375*593dc095SDavid du Colombier     /* gs_font_finalize passes event_data == NULL, so check it here. */
376*593dc095SDavid du Colombier     if (event_data == NULL) {
377*593dc095SDavid du Colombier         gs_font_cid0 *pfcid = proc_data;
378*593dc095SDavid du Colombier 	int i;
379*593dc095SDavid du Colombier 
380*593dc095SDavid du Colombier 	for (i = 0; i < pfcid->cidata.FDArray_size; ++i) {
381*593dc095SDavid du Colombier 	    if (pfcid->cidata.FDArray[i]->data.parent == (gs_font_base *)pfcid)
382*593dc095SDavid du Colombier 		pfcid->cidata.FDArray[i]->data.parent = NULL;
383*593dc095SDavid du Colombier 	}
384*593dc095SDavid du Colombier     }
385*593dc095SDavid du Colombier     return 0;
386*593dc095SDavid du Colombier }
387*593dc095SDavid du Colombier 
3883ff48bf5SDavid du Colombier /* <string|name> <font_dict> .buildfont9 <string|name> <font> */
3893ff48bf5SDavid du Colombier private int
zbuildfont9(i_ctx_t * i_ctx_p)3903ff48bf5SDavid du Colombier zbuildfont9(i_ctx_t *i_ctx_p)
3913ff48bf5SDavid du Colombier {
3923ff48bf5SDavid du Colombier     os_ptr op = osp;
3933ff48bf5SDavid du Colombier     build_proc_refs build;
394*593dc095SDavid du Colombier     int code = build_proc_name_refs(imemory, &build, NULL, "%Type9BuildGlyph");
3953ff48bf5SDavid du Colombier     gs_font_cid_data common;
3963ff48bf5SDavid du Colombier     ref GlyphDirectory, GlyphData, DataSource;
397*593dc095SDavid du Colombier     ref *prfda, cfnstr;
398*593dc095SDavid du Colombier     ref *pCIDFontName, CIDFontName;
3993ff48bf5SDavid du Colombier     gs_font_type1 **FDArray;
4003ff48bf5SDavid du Colombier     uint FDArray_size;
4013ff48bf5SDavid du Colombier     int FDBytes;
4023ff48bf5SDavid du Colombier     uint CIDMapOffset;
4033ff48bf5SDavid du Colombier     gs_font_base *pfont;
4043ff48bf5SDavid du Colombier     gs_font_cid0 *pfcid;
4053ff48bf5SDavid du Colombier     uint i;
4063ff48bf5SDavid du Colombier 
4073ff48bf5SDavid du Colombier     /*
4083ff48bf5SDavid du Colombier      * If the CIDFont's data have been loaded into VM, GlyphData will be
4093ff48bf5SDavid du Colombier      * a string or an array of strings; if they are loaded incrementally
4103ff48bf5SDavid du Colombier      * from a file, GlyphData will be an integer, and DataSource will be
4113ff48bf5SDavid du Colombier      * a (reusable) stream.
4123ff48bf5SDavid du Colombier      */
4133ff48bf5SDavid du Colombier     if (code < 0 ||
4143ff48bf5SDavid du Colombier 	(code = cid_font_data_param(op, &common, &GlyphDirectory)) < 0 ||
4153ff48bf5SDavid du Colombier 	(code = dict_find_string(op, "FDArray", &prfda)) < 0 ||
416*593dc095SDavid du Colombier 	(code = dict_find_string(op, "CIDFontName", &pCIDFontName)) <= 0 ||
4173ff48bf5SDavid du Colombier 	(code = dict_int_param(op, "FDBytes", 0, MAX_FDBytes, -1, &FDBytes)) < 0
4183ff48bf5SDavid du Colombier 	)
4193ff48bf5SDavid du Colombier 	return code;
420*593dc095SDavid du Colombier     /*
421*593dc095SDavid du Colombier      * Since build_gs_simple_font may resize the dictionary and cause
422*593dc095SDavid du Colombier      * pointers to become invalid, save CIDFontName
423*593dc095SDavid du Colombier      */
424*593dc095SDavid du Colombier     CIDFontName = *pCIDFontName;
4253ff48bf5SDavid du Colombier     if (r_has_type(&GlyphDirectory, t_null)) {
4263ff48bf5SDavid du Colombier 	/* Standard CIDFont, require GlyphData and CIDMapOffset. */
4273ff48bf5SDavid du Colombier 	ref *pGlyphData;
4283ff48bf5SDavid du Colombier 
4293ff48bf5SDavid du Colombier 	if ((code = dict_find_string(op, "GlyphData", &pGlyphData)) < 0 ||
4303ff48bf5SDavid du Colombier 	    (code = dict_uint_param(op, "CIDMapOffset", 0, max_uint - 1,
4313ff48bf5SDavid du Colombier 				    max_uint, &CIDMapOffset)) < 0)
4323ff48bf5SDavid du Colombier 	    return code;
4333ff48bf5SDavid du Colombier 	GlyphData = *pGlyphData;
4343ff48bf5SDavid du Colombier 	if (r_has_type(&GlyphData, t_integer)) {
4353ff48bf5SDavid du Colombier 	    ref *pds;
4363ff48bf5SDavid du Colombier 	    stream *ignore_s;
4373ff48bf5SDavid du Colombier 
4383ff48bf5SDavid du Colombier 	    if ((code = dict_find_string(op, "DataSource", &pds)) < 0)
4393ff48bf5SDavid du Colombier 		return code;
4403ff48bf5SDavid du Colombier 	    check_read_file(ignore_s, pds);
4413ff48bf5SDavid du Colombier 	    DataSource = *pds;
4423ff48bf5SDavid du Colombier 	} else {
4433ff48bf5SDavid du Colombier 	    if (!r_has_type(&GlyphData, t_string) && !r_is_array(&GlyphData))
4443ff48bf5SDavid du Colombier 		return_error(e_typecheck);
4453ff48bf5SDavid du Colombier 	    make_null(&DataSource);
4463ff48bf5SDavid du Colombier 	}
4473ff48bf5SDavid du Colombier     } else {
4483ff48bf5SDavid du Colombier 	make_null(&GlyphData);
4493ff48bf5SDavid du Colombier 	make_null(&DataSource);
4503ff48bf5SDavid du Colombier 	CIDMapOffset = 0;
4513ff48bf5SDavid du Colombier     }
4523ff48bf5SDavid du Colombier     if (!r_is_array(prfda))
4533ff48bf5SDavid du Colombier 	return_error(e_invalidfont);
4543ff48bf5SDavid du Colombier     FDArray_size = r_size(prfda);
4553ff48bf5SDavid du Colombier     if (FDArray_size == 0)
4563ff48bf5SDavid du Colombier 	return_error(e_invalidfont);
4573ff48bf5SDavid du Colombier     FDArray = ialloc_struct_array(FDArray_size, gs_font_type1 *,
4583ff48bf5SDavid du Colombier 				  &st_gs_font_type1_ptr_element,
4593ff48bf5SDavid du Colombier 				  "buildfont9(FDarray)");
4603ff48bf5SDavid du Colombier     if (FDArray == 0)
4613ff48bf5SDavid du Colombier 	return_error(e_VMerror);
4623ff48bf5SDavid du Colombier     memset(FDArray, 0, sizeof(gs_font_type1 *) * FDArray_size);
4633ff48bf5SDavid du Colombier     for (i = 0; i < FDArray_size; ++i) {
4643ff48bf5SDavid du Colombier 	ref rfd;
4653ff48bf5SDavid du Colombier 
466*593dc095SDavid du Colombier 	array_get(imemory, prfda, (long)i, &rfd);
4673ff48bf5SDavid du Colombier 	code = fd_array_element(i_ctx_p, &FDArray[i], &rfd);
4683ff48bf5SDavid du Colombier 	if (code < 0)
4693ff48bf5SDavid du Colombier 	    goto fail;
4703ff48bf5SDavid du Colombier     }
4713ff48bf5SDavid du Colombier     code = build_gs_simple_font(i_ctx_p, op, &pfont, ft_CID_encrypted,
4723ff48bf5SDavid du Colombier 				&st_gs_font_cid0, &build,
4733ff48bf5SDavid du Colombier 				bf_Encoding_optional |
4743ff48bf5SDavid du Colombier 				bf_UniqueID_ignored);
4753ff48bf5SDavid du Colombier     if (code < 0)
4763ff48bf5SDavid du Colombier 	goto fail;
4773ff48bf5SDavid du Colombier     pfont->procs.enumerate_glyph = gs_font_cid0_enumerate_glyph;
4783ff48bf5SDavid du Colombier     pfont->procs.glyph_outline = z9_glyph_outline;
479*593dc095SDavid du Colombier     pfont->procs.glyph_info = z9_glyph_info;
4803ff48bf5SDavid du Colombier     pfcid = (gs_font_cid0 *)pfont;
4813ff48bf5SDavid du Colombier     pfcid->cidata.common = common;
4823ff48bf5SDavid du Colombier     pfcid->cidata.CIDMapOffset = CIDMapOffset;
4833ff48bf5SDavid du Colombier     pfcid->cidata.FDArray = FDArray;
4843ff48bf5SDavid du Colombier     pfcid->cidata.FDArray_size = FDArray_size;
4853ff48bf5SDavid du Colombier     pfcid->cidata.FDBytes = FDBytes;
4863ff48bf5SDavid du Colombier     pfcid->cidata.glyph_data = z9_glyph_data;
4873ff48bf5SDavid du Colombier     pfcid->cidata.proc_data = 0;	/* for GC */
488*593dc095SDavid du Colombier     get_font_name(imemory, &cfnstr, &CIDFontName);
489*593dc095SDavid du Colombier     copy_font_name(&pfcid->font_name, &cfnstr);
4903ff48bf5SDavid du Colombier     ref_assign(&pfont_data(pfont)->u.cid0.GlyphDirectory, &GlyphDirectory);
4913ff48bf5SDavid du Colombier     ref_assign(&pfont_data(pfont)->u.cid0.GlyphData, &GlyphData);
4923ff48bf5SDavid du Colombier     ref_assign(&pfont_data(pfont)->u.cid0.DataSource, &DataSource);
4933ff48bf5SDavid du Colombier     code = define_gs_font((gs_font *)pfont);
4943ff48bf5SDavid du Colombier     if (code >= 0)
495*593dc095SDavid du Colombier        code = gs_notify_register(&pfont->notify_list, notify_remove_font_type9, pfont);
496*593dc095SDavid du Colombier     if (code >= 0) {
497*593dc095SDavid du Colombier 	for (i = 0; i < FDArray_size; ++i) {
498*593dc095SDavid du Colombier 	    FDArray[i]->dir = pfont->dir;
499*593dc095SDavid du Colombier 	    FDArray[i]->data.parent = pfont;
500*593dc095SDavid du Colombier 	}
5013ff48bf5SDavid du Colombier 	return code;
502*593dc095SDavid du Colombier     }
5033ff48bf5SDavid du Colombier  fail:
5043ff48bf5SDavid du Colombier     ifree_object(FDArray, "buildfont9(FDarray)");
5053ff48bf5SDavid du Colombier     return code;
5063ff48bf5SDavid du Colombier }
5073ff48bf5SDavid du Colombier 
5083ff48bf5SDavid du Colombier /* <cid9font> <cid> .type9mapcid <charstring> <font_index> */
509*593dc095SDavid du Colombier int
ztype9mapcid(i_ctx_t * i_ctx_p)5103ff48bf5SDavid du Colombier ztype9mapcid(i_ctx_t *i_ctx_p)
5113ff48bf5SDavid du Colombier {
5123ff48bf5SDavid du Colombier     os_ptr op = osp;
5133ff48bf5SDavid du Colombier     gs_font *pfont;
5143ff48bf5SDavid du Colombier     gs_font_cid0 *pfcid;
5153ff48bf5SDavid du Colombier     int code = font_param(op - 1, &pfont);
516*593dc095SDavid du Colombier     gs_glyph_data_t gdata;
5173ff48bf5SDavid du Colombier     int fidx;
5183ff48bf5SDavid du Colombier 
5193ff48bf5SDavid du Colombier     if (code < 0)
5203ff48bf5SDavid du Colombier 	return code;
5213ff48bf5SDavid du Colombier     if (pfont->FontType != ft_CID_encrypted)
5223ff48bf5SDavid du Colombier 	return_error(e_invalidfont);
5233ff48bf5SDavid du Colombier     check_type(*op, t_integer);
5243ff48bf5SDavid du Colombier     pfcid = (gs_font_cid0 *)pfont;
525*593dc095SDavid du Colombier     gdata.memory = pfont->memory;
5263ff48bf5SDavid du Colombier     code = pfcid->cidata.glyph_data((gs_font_base *)pfcid,
5273ff48bf5SDavid du Colombier 			(gs_glyph)(gs_min_cid_glyph + op->value.intval),
528*593dc095SDavid du Colombier 				    &gdata, &fidx);
5293ff48bf5SDavid du Colombier 
5303ff48bf5SDavid du Colombier     /* return code; original error-sensitive & fragile code */
5313ff48bf5SDavid du Colombier     if (code < 0) { /* failed to load glyph data, put CID 0 */
5323ff48bf5SDavid du Colombier        int default_fallback_CID = 0 ;
5333ff48bf5SDavid du Colombier 
5343ff48bf5SDavid du Colombier        if_debug2('J', "[J]ztype9cidmap() use CID %d instead of glyph-missing CID %d\n", default_fallback_CID, op->value.intval);
5353ff48bf5SDavid du Colombier 
5363ff48bf5SDavid du Colombier        op->value.intval = default_fallback_CID;
5373ff48bf5SDavid du Colombier 
5383ff48bf5SDavid du Colombier        /* reload glyph for default_fallback_CID */
5393ff48bf5SDavid du Colombier 
5403ff48bf5SDavid du Colombier        code = pfcid->cidata.glyph_data((gs_font_base *)pfcid,
5413ff48bf5SDavid du Colombier                     (gs_glyph)(gs_min_cid_glyph + default_fallback_CID),
542*593dc095SDavid du Colombier                                    &gdata, &fidx);
543*593dc095SDavid du Colombier 
544*593dc095SDavid du Colombier        if (code < 0) {
545*593dc095SDavid du Colombier            if_debug1('J', "[J]ztype9cidmap() could not load default glyph (CID %d)\n", op->value.intval);
546*593dc095SDavid du Colombier            return_error(e_invalidfont);
5473ff48bf5SDavid du Colombier        }
5483ff48bf5SDavid du Colombier 
549*593dc095SDavid du Colombier     }
550*593dc095SDavid du Colombier 
551*593dc095SDavid du Colombier     /****** FOLLOWING IS NOT GENERAL W.R.T. ALLOCATION OF GLYPH DATA ******/
5523ff48bf5SDavid du Colombier     make_const_string(op - 1,
5533ff48bf5SDavid du Colombier 		      a_readonly | imemory_space((gs_ref_memory_t *)pfont->memory),
554*593dc095SDavid du Colombier 		      gdata.bits.size,
555*593dc095SDavid du Colombier 		      gdata.bits.data);
5563ff48bf5SDavid du Colombier     make_int(op, fidx);
5573ff48bf5SDavid du Colombier     return code;
5583ff48bf5SDavid du Colombier }
5593ff48bf5SDavid du Colombier 
5603ff48bf5SDavid du Colombier /* ------ Initialization procedure ------ */
5613ff48bf5SDavid du Colombier 
5623ff48bf5SDavid du Colombier const op_def zfcid0_op_defs[] =
5633ff48bf5SDavid du Colombier {
5643ff48bf5SDavid du Colombier     {"2.buildfont9", zbuildfont9},
5653ff48bf5SDavid du Colombier     {"2.type9mapcid", ztype9mapcid},
5663ff48bf5SDavid du Colombier     op_def_end(0)
5673ff48bf5SDavid du Colombier };
568