Coverage Report

Created: 2026-04-01 07:17

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