Coverage Report

Created: 2025-06-24 07:01

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