Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/psi/zfont.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
/* Generic font operators */
18
#include "ghost.h"
19
#include "oper.h"
20
#include "gsstruct.h"   /* for registering root */
21
#include "gzstate.h"    /* must precede gxdevice */
22
#include "gxdevice.h"   /* must precede gxfont */
23
#include "gxfont.h"
24
#include "gxfcache.h"
25
#include "bfont.h"
26
#include "ialloc.h"
27
#include "iddict.h"
28
#include "igstate.h"
29
#include "iname.h"    /* for name_mark_index */
30
#include "isave.h"
31
#include "store.h"
32
#include "ivmspace.h"
33
#include "gscencs.h"
34
#include "ichar.h"
35
36
/* Forward references */
37
static int make_font(i_ctx_t *, const gs_matrix *);
38
static void make_uint_array(os_ptr, const uint *, int);
39
static int setup_unicode_decoder(i_ctx_t *i_ctx_p, ref *Decoding);
40
41
/* Mark a glyph as a PostScript name (if it isn't a CID). */
42
bool
43
zfont_mark_glyph_name(const gs_memory_t *mem, gs_glyph glyph, void *ignore_data)
44
2.24M
{
45
2.24M
    if (glyph == GS_NO_GLYPH)
46
0
        return false;
47
2.24M
    if (glyph >= gs_c_min_std_encoding_glyph)
48
0
        return false;
49
2.24M
    return name_mark_index(mem, (uint) glyph);
50
2.24M
}
51
52
/* Get a global glyph code.  */
53
static int
54
zfont_global_glyph_code(const gs_font *pbfont, gs_const_string *gstr, gs_glyph *pglyph)
55
0
{
56
0
    ref v;
57
0
    int code = name_ref(pbfont->memory, gstr->data, gstr->size, &v, 0);
58
59
0
    if (code < 0)
60
0
        return code;
61
0
    *pglyph = (gs_glyph)name_index(pbfont->memory, &v);
62
0
    return 0;
63
0
}
64
65
/* Initialize the font operators */
66
static int
67
zfont_init(i_ctx_t *i_ctx_p)
68
162k
{
69
162k
    ifont_dir = gs_font_dir_alloc2(imemory->stable_memory, imemory->non_gc_memory);
70
162k
    if (ifont_dir == NULL)
71
0
        return gs_error_VMerror;
72
162k
    ifont_dir->ccache.mark_glyph = zfont_mark_glyph_name;
73
162k
    ifont_dir->global_glyph_code = zfont_global_glyph_code;
74
162k
    return gs_register_struct_root(imemory, &imemory->gs_lib_ctx->font_dir_root,
75
162k
        (void **)&ifont_dir, "ifont_dir");
76
162k
}
77
78
/* <font> <scale> scalefont <new_font> */
79
static int
80
zscalefont(i_ctx_t *i_ctx_p)
81
26.3k
{
82
26.3k
    os_ptr op = osp;
83
26.3k
    int code;
84
26.3k
    double scale;
85
26.3k
    gs_matrix mat;
86
87
26.3k
    check_op(2);
88
26.3k
    if ((code = real_param(op, &scale)) < 0)
89
118
        return code;
90
26.1k
    if ((code = gs_make_scaling(scale, scale, &mat)) < 0)
91
0
        return code;
92
26.1k
    return make_font(i_ctx_p, &mat);
93
26.1k
}
94
95
/* <font> <matrix> makefont <new_font> */
96
static int
97
zmakefont(i_ctx_t *i_ctx_p)
98
25
{
99
25
    os_ptr op = osp;
100
25
    int code;
101
25
    gs_matrix mat;
102
103
25
    check_op(2);
104
12
    if ((code = read_matrix(imemory, op, &mat)) < 0)
105
8
        return code;
106
4
    return make_font(i_ctx_p, &mat);
107
12
}
108
109
/* <font> setfont - */
110
int
111
zsetfont(i_ctx_t *i_ctx_p)
112
180k
{
113
180k
    os_ptr op = osp;
114
180k
    gs_font *pfont;
115
180k
    int code;
116
117
180k
    check_op(1);
118
180k
    code = font_param(op, &pfont);
119
180k
    if (code < 0 || (code = gs_setfont(igs, pfont)) < 0)
120
17
        return code;
121
180k
    pop(1);
122
180k
    return code;
123
180k
}
124
125
/* - currentfont <font> */
126
static int
127
zcurrentfont(i_ctx_t *i_ctx_p)
128
175k
{
129
175k
    os_ptr op = osp;
130
131
175k
    push(1);
132
175k
    *op = *pfont_dict(gs_currentfont(igs));
133
175k
    return 0;
134
175k
}
135
136
/* - cachestatus <mark> <bsize> <bmax> <msize> <mmax> <csize> <cmax> <blimit> */
137
static int
138
zcachestatus(i_ctx_t *i_ctx_p)
139
162k
{
140
162k
    os_ptr op = osp;
141
162k
    uint status[7];
142
143
162k
    gs_cachestatus(ifont_dir, status);
144
162k
    push(7);
145
162k
    make_uint_array(op - 6, status, 7);
146
162k
    return 0;
147
162k
}
148
149
/* <blimit> setcachelimit - */
150
static int
151
zsetcachelimit(i_ctx_t *i_ctx_p)
152
0
{
153
0
    os_ptr op = osp;
154
155
0
    check_op(1);
156
0
    check_int_leu(*op, max_uint);
157
0
    gs_setcachelimit(ifont_dir, (uint) op->value.intval);
158
0
    pop(1);
159
0
    return 0;
160
0
}
161
162
/* <mark> <size> <lower> <upper> setcacheparams - */
163
static int
164
zsetcacheparams(i_ctx_t *i_ctx_p)
165
162k
{
166
162k
    os_ptr op = osp;
167
162k
    uint params[3];
168
162k
    int i, code;
169
162k
    os_ptr opp = op;
170
171
    /* Changing the cache params clears the "pairs" cache, which
172
       causes a crash if the in use font/matrix pair disappears
173
       during a text operation. So don't allow that to happen.
174
     */
175
162k
    if (op_show_find(i_ctx_p) != NULL)
176
0
        return_error(gs_error_invalidaccess);
177
178
162k
    check_op(1);
179
487k
    for (i = 0; i < 3 && !r_has_type(opp, t_mark); i++, opp--) {
180
324k
        check_op(i + 1);
181
324k
        check_int_leu(*opp, max_uint);
182
324k
        params[i] = opp->value.intval;
183
324k
    }
184
162k
    switch (i) {
185
0
        case 3:
186
0
            if ((code = gs_setcachesize(igs, ifont_dir, params[2])) < 0)
187
0
                return code;
188
162k
        case 2:
189
162k
            if ((code = gs_setcachelower(ifont_dir, params[1])) < 0)
190
0
                return code;
191
162k
        case 1:
192
162k
            if ((code = gs_setcacheupper(ifont_dir, params[0])) < 0)
193
0
                return code;
194
162k
        case 0:;
195
162k
    }
196
162k
    return zcleartomark(i_ctx_p);
197
162k
}
198
199
/* - currentcacheparams <mark> <size> <lower> <upper> */
200
static int
201
zcurrentcacheparams(i_ctx_t *i_ctx_p)
202
162k
{
203
162k
    os_ptr op = osp;
204
162k
    uint params[3];
205
206
162k
    params[0] = gs_currentcachesize(ifont_dir);
207
162k
    params[1] = gs_currentcachelower(ifont_dir);
208
162k
    params[2] = gs_currentcacheupper(ifont_dir);
209
162k
    push(4);
210
162k
    make_mark(op - 3);
211
162k
    make_uint_array(op - 2, params, 3);
212
162k
    return 0;
213
162k
}
214
215
/* <font> .registerfont - */
216
static int
217
zregisterfont(i_ctx_t *i_ctx_p)
218
123k
{
219
123k
    os_ptr op = osp;
220
123k
    gs_font *pfont;
221
123k
    int code;
222
223
123k
    check_op(1);
224
123k
    code = font_param(op, &pfont);
225
226
123k
    if (code < 0)
227
0
        return code;
228
123k
    pfont->is_resource = true;
229
123k
    pop(1);
230
123k
    return 0;
231
123k
}
232
233
/* <Decoding> .setupUnicodeDecoder - */
234
static int
235
zsetupUnicodeDecoder(i_ctx_t *i_ctx_p)
236
9.18k
{   /* The allocation mode must be global. */
237
9.18k
    os_ptr op = osp;
238
9.18k
    int code;
239
240
9.18k
    check_op(1);
241
9.18k
    check_type(*op, t_dictionary);
242
9.18k
    code = setup_unicode_decoder(i_ctx_p, op);
243
9.18k
    if (code < 0)
244
0
        return code;
245
9.18k
    pop(1);
246
9.18k
    return 0;
247
9.18k
}
248
249
/* ------ Initialization procedure ------ */
250
251
const op_def zfont_op_defs[] =
252
{
253
    {"0currentfont", zcurrentfont},
254
    {"2makefont", zmakefont},
255
    {"2scalefont", zscalefont},
256
    {"1setfont", zsetfont},
257
    {"0cachestatus", zcachestatus},
258
    {"1setcachelimit", zsetcachelimit},
259
    {"1setcacheparams", zsetcacheparams},
260
    {"0currentcacheparams", zcurrentcacheparams},
261
    {"1.registerfont", zregisterfont},
262
    {"1.setupUnicodeDecoder", zsetupUnicodeDecoder},
263
    op_def_end(zfont_init)
264
};
265
266
/* ------ Subroutines ------ */
267
268
/* Validate a font parameter. */
269
int
270
font_param(const ref * pfdict, gs_font ** ppfont)
271
1.97M
{ /*
272
         * Check that pfdict is a read-only dictionary, that it has a FID
273
         * entry whose value is a fontID, and that the fontID points to a
274
         * gs_font structure whose associated PostScript dictionary is
275
         * pfdict.
276
         */
277
1.97M
    ref *pid;
278
1.97M
    gs_font *pfont;
279
1.97M
    const font_data *pdata;
280
281
1.97M
    check_type(*pfdict, t_dictionary);
282
1.97M
    if (dict_find_string(pfdict, "FID", &pid) <= 0 ||
283
1.97M
        !r_has_type(pid, t_fontID)
284
1.97M
        )
285
10
        return_error(gs_error_invalidfont);
286
1.97M
    pfont = r_ptr(pid, gs_font);
287
1.97M
    if (pfont == 0)
288
0
        return_error(gs_error_invalidfont); /* unregistered font */
289
1.97M
    pdata = pfont->client_data;
290
1.97M
    if (!obj_eq(pfont->memory, &pdata->dict, pfdict))
291
0
        return_error(gs_error_invalidfont);
292
1.97M
    *ppfont = pfont;
293
1.97M
    return 0;
294
1.97M
}
295
296
/* Add the FID entry to a font dictionary. */
297
/* Note that i_ctx_p may be NULL. */
298
int
299
add_FID(i_ctx_t *i_ctx_p, ref * fp /* t_dictionary */ , gs_font * pfont,
300
        gs_ref_memory_t *imem)
301
307k
{
302
307k
    ref fid;
303
304
307k
    make_tav(&fid, t_fontID,
305
307k
             a_readonly | imemory_space(imem) | imemory_new_mask(imem),
306
307k
             pstruct, (void *)pfont);
307
307k
    return (i_ctx_p ? idict_put_string(fp, "FID", &fid) :
308
307k
            dict_put_string(fp, "FID", &fid, NULL));
309
307k
}
310
311
/* Make a transformed font (common code for makefont/scalefont). */
312
static int
313
make_font(i_ctx_t *i_ctx_p, const gs_matrix * pmat)
314
26.1k
{
315
26.1k
    os_ptr op = osp;
316
26.1k
    os_ptr fp = op - 1;
317
26.1k
    gs_font *oldfont, *newfont;
318
26.1k
    int code;
319
26.1k
    ref *pencoding = 0;
320
321
26.1k
    code = font_param(fp, &oldfont);
322
26.1k
    if (code < 0)
323
18
        return code;
324
26.1k
    {
325
26.1k
        uint space = ialloc_space(idmemory);
326
327
26.1k
        ialloc_set_space(idmemory, r_space(fp));
328
26.1k
        if (dict_find_string(fp, "Encoding", &pencoding) > 0 &&
329
26.1k
            !r_is_array(pencoding)
330
26.1k
            )
331
0
            code = gs_note_error(gs_error_invalidfont);
332
26.1k
        else {
333
                /*
334
                 * Temporarily substitute the new dictionary
335
                 * for the old one, in case the Encoding changed.
336
                 */
337
26.1k
            ref olddict;
338
339
26.1k
            olddict = *pfont_dict(oldfont);
340
26.1k
            *pfont_dict(oldfont) = *fp;
341
26.1k
            code = gs_makefont(ifont_dir, oldfont, pmat, &newfont);
342
26.1k
            *pfont_dict(oldfont) = olddict;
343
26.1k
        }
344
26.1k
        ialloc_set_space(idmemory, space);
345
26.1k
    }
346
26.1k
    if (code < 0)
347
0
        return code;
348
    /*
349
     * We have to allow for the possibility that the font's Encoding
350
     * is different from that of the base font.  Note that the
351
     * font_data of the new font was simply copied from the old one.
352
     */
353
26.1k
    if (pencoding != 0 &&
354
26.1k
        !obj_eq(imemory, pencoding, &pfont_data(newfont)->Encoding)
355
26.1k
        ) {
356
0
        if (newfont->FontType == ft_composite)
357
0
            return_error(gs_error_rangecheck);
358
        /* We should really do validity checking here.... */
359
0
        ref_assign(&pfont_data(newfont)->Encoding, pencoding);
360
0
        lookup_gs_simple_font_encoding((gs_font_base *) newfont);
361
0
    }
362
26.1k
    *fp = *pfont_dict(newfont);
363
26.1k
    pop(1);
364
26.1k
    return 0;
365
26.1k
}
366
/* Create the transformed font dictionary. */
367
/* This is the make_font completion procedure for all non-composite fonts */
368
/* created at the interpreter level (see build_gs_simple_font in zbfont.c.) */
369
int
370
zbase_make_font(gs_font_dir * pdir, const gs_font * oldfont,
371
                const gs_matrix * pmat, gs_font ** ppfont)
372
20.4k
{
373
    /*
374
     * We must call gs_base_make_font so that the XUID gets copied
375
     * if necessary.
376
     */
377
20.4k
    int code = gs_base_make_font(pdir, oldfont, pmat, ppfont);
378
379
20.4k
    if (code < 0)
380
0
        return code;
381
20.4k
    return zdefault_make_font(pdir, oldfont, pmat, ppfont);
382
20.4k
}
383
int
384
zdefault_make_font(gs_font_dir * pdir, const gs_font * oldfont,
385
                   const gs_matrix * pmat, gs_font ** ppfont)
386
20.4k
{
387
20.4k
    gs_font *newfont = *ppfont;
388
20.4k
    gs_memory_t *mem = newfont->memory;
389
    /* HACK: we know this font was allocated by the interpreter. */
390
20.4k
    gs_ref_memory_t *imem = (gs_ref_memory_t *)mem;
391
20.4k
    ref *fp = pfont_dict(oldfont);
392
20.4k
    font_data *pdata;
393
20.4k
    ref newdict, newmat, scalemat;
394
20.4k
    uint dlen = dict_maxlength(fp);
395
20.4k
    uint mlen = dict_length(fp) + 3;  /* FontID, OrigFont, ScaleMatrix */
396
20.4k
    int code;
397
398
20.4k
    if (dlen < mlen)
399
13.9k
        dlen = mlen;
400
20.4k
    if ((pdata = gs_alloc_struct(mem, font_data, &st_font_data,
401
20.4k
                                 "make_font(font_data)")) == 0
402
20.4k
        )
403
0
        return_error(gs_error_VMerror);
404
    /*
405
     * This dictionary is newly created: it's safe to pass NULL as the
406
     * dstack pointer to dict_copy and dict_put_string.
407
     */
408
20.4k
    if ((code = dict_alloc(imem, dlen, &newdict)) < 0 ||
409
20.4k
        (code = dict_copy(fp, &newdict, NULL)) < 0 ||
410
20.4k
        (code = gs_alloc_ref_array(imem, &newmat, a_all, 12,
411
20.4k
                                   "make_font(matrices)")) < 0
412
20.4k
        )
413
0
        return code;
414
20.4k
    refset_null_new(newmat.value.refs, 12, imemory_new_mask(imem));
415
20.4k
    ref_assign(&scalemat, &newmat);
416
20.4k
    r_set_size(&scalemat, 6);
417
20.4k
    scalemat.value.refs += 6;
418
    /*
419
     * Create the scaling matrix.  We could do this several different
420
     * ways: by "dividing" the new FontMatrix by the base FontMatrix, by
421
     * multiplying the current scaling matrix by a ScaleMatrix kept in
422
     * the gs_font, or by multiplying the current scaling matrix by the
423
     * ScaleMatrix from the font dictionary.  We opt for the last of
424
     * these.
425
     */
426
20.4k
    {
427
20.4k
        gs_matrix scale, prev_scale;
428
20.4k
        ref *ppsm;
429
430
20.4k
        if (!(dict_find_string(fp, "ScaleMatrix", &ppsm) > 0 &&
431
20.4k
              read_matrix(mem, ppsm, &prev_scale) >= 0 &&
432
20.4k
              gs_matrix_multiply(pmat, &prev_scale, &scale) >= 0)
433
20.4k
            )
434
13.8k
            scale = *pmat;
435
20.4k
        write_matrix_new(&scalemat, &scale, imem);
436
20.4k
    }
437
20.4k
    r_clear_attrs(&scalemat, a_write);
438
20.4k
    r_set_size(&newmat, 6);
439
20.4k
    write_matrix_new(&newmat, &newfont->FontMatrix, imem);
440
20.4k
    r_clear_attrs(&newmat, a_write);
441
20.4k
    if ((code = dict_put_string(&newdict, "FontMatrix", &newmat, NULL)) < 0 ||
442
20.4k
        (code = dict_put_string(&newdict, "OrigFont", pfont_dict(oldfont->base), NULL)) < 0 ||
443
20.4k
        (code = dict_put_string(&newdict, "ScaleMatrix", &scalemat, NULL)) < 0 ||
444
20.4k
        (code = add_FID(NULL, &newdict, newfont, imem)) < 0
445
20.4k
        )
446
0
        return code;
447
20.4k
    newfont->client_data = pdata;
448
20.4k
    *pdata = *pfont_data(oldfont);
449
20.4k
    pdata->dict = newdict;
450
20.4k
    r_clear_attrs(dict_access_ref(&newdict), a_write);
451
20.4k
    return 0;
452
20.4k
}
453
454
/* Convert an array of (unsigned) integers to stack form. */
455
static void
456
make_uint_array(register os_ptr op, const uint * intp, int count)
457
324k
{
458
324k
    int i;
459
460
1.95M
    for (i = 0; i < count; i++, op++, intp++)
461
1.62M
        make_int(op, *intp);
462
324k
}
463
464
/* Remove scaled font and character cache entries that would be */
465
/* invalidated by a restore. */
466
static bool
467
purge_if_name_removed(const gs_memory_t *mem, cached_char * cc, void *vsave)
468
0
{
469
0
    return alloc_name_index_is_since_save(mem, cc->code, vsave);
470
0
}
471
472
/* Remove entries from font and character caches. */
473
int
474
font_restore(const alloc_save_t * save)
475
1.51M
{
476
477
1.51M
    gs_memory_t *smem = gs_save_any_memory(save);
478
1.51M
    gs_font_dir *pdir = smem->gs_lib_ctx->font_dir;
479
1.51M
    int code;
480
481
1.51M
    if (pdir == 0)    /* not initialized yet */
482
162k
        return 0;
483
484
    /* Purge original (unscaled) fonts. */
485
486
1.34M
    {
487
1.34M
        gs_font *pfont;
488
489
1.51M
otop:
490
3.41M
        for (pfont = pdir->orig_fonts; pfont != 0;
491
1.90M
             pfont = pfont->next
492
2.06M
            ) {
493
2.06M
            if (alloc_is_since_save((char *)pfont, save)) {
494
162k
                code = gs_purge_font(pfont);
495
162k
                if (code < 0)
496
0
                    return code;
497
162k
                goto otop;
498
162k
            }
499
2.06M
        }
500
1.51M
    }
501
502
    /* Purge cached scaled fonts. */
503
504
1.34M
    {
505
1.34M
        gs_font *pfont;
506
507
1.34M
top:
508
1.63M
        for (pfont = pdir->scaled_fonts; pfont != 0;
509
1.34M
             pfont = pfont->next
510
1.34M
            ) {
511
291k
            if (alloc_is_since_save((char *)pfont, save)) {
512
0
                code = gs_purge_font(pfont);
513
0
                if (code < 0)
514
0
                    return code;
515
0
                goto top;
516
0
            }
517
291k
        }
518
1.34M
    }
519
520
    /* Purge xfonts and uncached scaled fonts. */
521
522
1.34M
    {
523
1.34M
        cached_fm_pair *pair;
524
1.34M
        uint n;
525
526
1.34M
        for (pair = pdir->fmcache.mdata, n = pdir->fmcache.mmax;
527
270M
             n > 0; pair++, n--
528
1.34M
            )
529
269M
            if (!fm_pair_is_free(pair)) {
530
#if 0
531
                /* We disabled this code portion because
532
                   gx_add_fm_pair now copied xvalues
533
                   into a stable memory.
534
                 */
535
                if ((uid_is_XUID(&pair->UID) &&
536
                     alloc_is_since_save((char *)pair->UID.xvalues,
537
                                         save))
538
                    ) {
539
                    code = gs_purge_fm_pair(pdir, pair, 0);
540
                    if (code < 0)
541
                        return code;
542
                    continue;
543
                }
544
#endif
545
311k
                if (pair->font != 0 &&
546
311k
                    alloc_is_since_save((char *)pair->font, save)
547
311k
                    ) {
548
0
                    if (!uid_is_valid(&pair->UID))
549
0
                        gs_clean_fm_pair(pdir, pair);
550
                    /* Don't discard pairs with a surviving UID. */
551
0
                    pair->font = 0;
552
0
                }
553
311k
                if (pair->xfont != 0 &&
554
311k
                    alloc_is_since_save((char *)pair->xfont, save)
555
311k
                    ) {
556
0
                    code = gs_purge_fm_pair(pdir, pair, 1);
557
0
                    if (code < 0)
558
0
                        return code;
559
0
                }
560
311k
            }
561
1.34M
    }
562
563
    /* Purge characters with names about to be removed. */
564
    /* We only need to do this if any new names have been created */
565
    /* since the save. */
566
567
1.34M
    if (alloc_any_names_since_save(save))
568
0
        gx_purge_selected_cached_chars(pdir, purge_if_name_removed,
569
0
                                       (void *)save);
570
1.34M
    return 0;
571
1.34M
}
572
573
/* ------ Font procedures for PostScript fonts ------ */
574
575
/* font_info procedure */
576
static bool
577
zfont_info_has(const ref *pfidict, const char *key, gs_const_string *pmember)
578
7.84k
{
579
7.84k
    ref *pvalue;
580
581
7.84k
    if (dict_find_string(pfidict, key, &pvalue) > 0 &&
582
7.84k
        r_has_type(pvalue, t_string)
583
7.84k
        ) {
584
7.84k
        pmember->data = pvalue->value.const_bytes;
585
7.84k
        pmember->size = r_size(pvalue);
586
7.84k
        return true;
587
7.84k
    }
588
0
    return false;
589
7.84k
}
590
int
591
zfont_info(gs_font *font, const gs_point *pscale, int members,
592
           gs_font_info_t *info)
593
3.44k
{
594
3.44k
    int code = gs_default_font_info(font, pscale, members &
595
3.44k
                    ~(FONT_INFO_COPYRIGHT | FONT_INFO_NOTICE |
596
3.44k
                      FONT_INFO_FAMILY_NAME | FONT_INFO_FULL_NAME),
597
3.44k
                                    info);
598
3.44k
    const ref *pfdict;
599
3.44k
    ref *pfontinfo, *pvalue;
600
601
3.44k
    if (code < 0)
602
0
        return code;
603
3.44k
    pfdict = &pfont_data(font)->dict;
604
3.44k
    if (dict_find_string(pfdict, "FontInfo", &pfontinfo) <= 0 ||
605
3.44k
        !r_has_type(pfontinfo, t_dictionary))
606
306
        return 0;
607
3.13k
    if ((members & FONT_INFO_COPYRIGHT) &&
608
3.13k
        zfont_info_has(pfontinfo, "Copyright", &info->Copyright))
609
1.96k
        info->members |= FONT_INFO_COPYRIGHT;
610
3.13k
    if ((members & FONT_INFO_NOTICE) &&
611
3.13k
        zfont_info_has(pfontinfo, "Notice", &info->Notice))
612
1.96k
        info->members |= FONT_INFO_NOTICE;
613
3.13k
    if ((members & FONT_INFO_FAMILY_NAME) &&
614
3.13k
        zfont_info_has(pfontinfo, "FamilyName", &info->FamilyName))
615
1.96k
        info->members |= FONT_INFO_FAMILY_NAME;
616
3.13k
    if ((members & FONT_INFO_FULL_NAME) &&
617
3.13k
        zfont_info_has(pfontinfo, "FullName", &info->FullName))
618
1.96k
        info->members |= FONT_INFO_FULL_NAME;
619
3.13k
    if ((members & FONT_INFO_EMBEDDING_RIGHTS)
620
3.13k
        && (dict_find_string(pfontinfo, "FSType", &pvalue) > 0)) {
621
0
        if (r_type(pvalue) != t_integer)
622
0
            return gs_note_error(gs_error_typecheck);
623
624
0
        info->EmbeddingRights = pvalue->value.intval;
625
0
        info->members |= FONT_INFO_EMBEDDING_RIGHTS;
626
0
    }
627
3.13k
    return code;
628
3.13k
}
629
630
/* -------------------- Utilities --------------*/
631
632
typedef struct gs_unicode_decoder_s {
633
    ref data;
634
} gs_unicode_decoder;
635
636
/* GC procedures */
637
static
638
CLEAR_MARKS_PROC(unicode_decoder_clear_marks)
639
22.1k
{   gs_unicode_decoder *const pptr = vptr;
640
641
22.1k
    r_clear_attrs(&pptr->data, l_mark);
642
22.1k
}
643
static
644
40.4k
ENUM_PTRS_WITH(unicode_decoder_enum_ptrs, gs_unicode_decoder *pptr) return 0;
645
20.2k
case 0:
646
20.2k
ENUM_RETURN_REF(&pptr->data);
647
40.4k
ENUM_PTRS_END
648
20.2k
static RELOC_PTRS_WITH(unicode_decoder_reloc_ptrs, gs_unicode_decoder *pptr);
649
20.2k
RELOC_REF_VAR(pptr->data);
650
20.2k
r_clear_attrs(&pptr->data, l_mark);
651
20.2k
RELOC_PTRS_END
652
653
gs_private_st_complex_only(st_unicode_decoder, gs_unicode_decoder,\
654
    "unicode_decoder", unicode_decoder_clear_marks, unicode_decoder_enum_ptrs,
655
    unicode_decoder_reloc_ptrs, 0);
656
657
/* Get the Unicode value for a glyph. */
658
const ref *
659
zfont_get_to_unicode_map(gs_font_dir *dir)
660
74.1k
{
661
74.1k
    const gs_unicode_decoder *pud = (gs_unicode_decoder *)dir->glyph_to_unicode_table;
662
663
74.1k
    return (pud == NULL ? NULL : &pud->data);
664
74.1k
}
665
666
static int
667
setup_unicode_decoder(i_ctx_t *i_ctx_p, ref *Decoding)
668
9.18k
{
669
9.18k
    gs_unicode_decoder *pud = gs_alloc_struct(imemory, gs_unicode_decoder,
670
9.18k
                             &st_unicode_decoder, "setup_unicode_decoder");
671
9.18k
    if (pud == NULL)
672
0
        return_error(gs_error_VMerror);
673
9.18k
    ref_assign_new(&pud->data, Decoding);
674
9.18k
    ifont_dir->glyph_to_unicode_table = pud;
675
9.18k
    return 0;
676
9.18k
}