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