Coverage Report

Created: 2022-10-31 07:00

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