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