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