Coverage Report

Created: 2026-10-28 08:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/psi/zbfont.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
/* Font creation utilities */
18
#include "memory_.h"
19
#include "string_.h"
20
#include "ghost.h"
21
#include "oper.h"
22
#include "gxfixed.h"
23
#include "gscencs.h"
24
#include "gsmatrix.h"
25
#include "gxdevice.h"
26
#include "gxfont.h"
27
#include "bfont.h"
28
#include "ialloc.h"
29
#include "idict.h"
30
#include "dstack.h"
31
#include "iddict.h"
32
#include "idparam.h"
33
#include "ilevel.h"
34
#include "iname.h"
35
#include "inamedef.h"   /* for inlining name_index */
36
#include "interp.h"   /* for initial_enter_name */
37
#include "ipacked.h"
38
#include "istruct.h"
39
#include "store.h"
40
#include "gsstate.h" /* for gs_currentcpsimode() */
41
/* Structure descriptor and GC procedures for font_data */
42
public_st_font_data();
43
static
44
CLEAR_MARKS_PROC(font_data_clear_marks)
45
448k
{
46
448k
    ref_struct_clear_marks(cmem, vptr, offset_of(font_data, u.type42.mru_sfnts_index)/*size*/, pstype);
47
448k
}
48
static
49
ENUM_PTRS_BEGIN_PROC(font_data_enum_ptrs)
50
4.27M
{
51
4.27M
    return ref_struct_enum_ptrs(mem, vptr, offset_of(font_data, u.type42.mru_sfnts_index)/*size*/, index, pep, pstype, gcst);
52
4.27M
}
53
ENUM_PTRS_END_PROC
54
static
55
427k
RELOC_PTRS_BEGIN(font_data_reloc_ptrs)
56
427k
{
57
427k
    ref_struct_reloc_ptrs(vptr, offset_of(font_data, u.type42.mru_sfnts_index)/*size*/, pstype, gcst);
58
427k
}
59
427k
RELOC_PTRS_END
60
61
/* <string|name> <font_dict> .buildfont3 <string|name> <font> */
62
/* Build a type 3 (user-defined) font. */
63
static int
64
zbuildfont3(i_ctx_t *i_ctx_p)
65
163k
{
66
163k
    os_ptr op = osp;
67
163k
    int code;
68
163k
    build_proc_refs build;
69
163k
    gs_font_base *pfont;
70
71
163k
    check_op(2);
72
163k
    check_type(*op, t_dictionary);
73
163k
    code = build_gs_font_procs(op, &build);
74
163k
    if (code < 0)
75
12
        return code;
76
163k
    code = build_gs_simple_font(i_ctx_p, op, &pfont, ft_user_defined,
77
163k
                                &st_gs_font_base, &build, bf_options_none);
78
163k
    if (code < 0)
79
12
        return code;
80
163k
    return define_gs_font(i_ctx_p, (gs_font *) pfont);
81
163k
}
82
83
/* Encode a character. */
84
gs_glyph
85
zfont_encode_char(gs_font *pfont, gs_char chr, gs_glyph_space_t gspace)
86
33.9M
{
87
33.9M
    font_data *pdata = pfont_data(pfont);
88
33.9M
    const ref *pencoding = &pdata->Encoding;
89
33.9M
    ulong index = chr;  /* work around VAX widening bug */
90
33.9M
    ref cname;
91
33.9M
    int code = array_get(pfont->memory, pencoding, (long)index, &cname);
92
93
33.9M
    if (code < 0 || !r_has_type(&cname, t_name))
94
1.05k
        return GS_NO_GLYPH;
95
33.9M
    if (pfont->FontType == ft_user_defined && r_type(&pdata->BuildGlyph) == t_null) {
96
27.2M
        ref nsref, tname;
97
98
27.2M
        name_string_ref(pfont->memory, &cname, &nsref);
99
27.2M
        if (r_size(&nsref) == 7 &&
100
5.72M
            !memcmp(nsref.value.const_bytes, ".notdef", r_size(&nsref))) {
101
            /* A special support for high level devices.
102
               They need a glyph name but the font doesn't provide one
103
               due to an instandard BuildChar.
104
               Such fonts don't conform to PLRM section 5.3.7,
105
               but we've got real examples that we want to handle (Bug 686982).
106
               Construct a name here.
107
               Low level devices don't pass here, because regular PS interpretation
108
               doesn't need such names.
109
            */
110
5.49M
            char buf[20];
111
5.49M
            int code;
112
113
5.49M
            if (gspace == GLYPH_SPACE_NOGEN)
114
0
                return GS_NO_GLYPH;
115
5.49M
            gs_snprintf(buf, sizeof(buf), "j%ld", chr); /* 'j' is arbutrary. */
116
5.49M
            code = name_ref(pfont->memory, (const byte *)buf, strlen(buf), &tname, 1);
117
5.49M
            if (code < 0) {
118
                /* Can't propagate the error due to interface limitation,
119
                   return with .notdef */
120
0
            } else
121
5.49M
                cname = tname;
122
5.49M
        }
123
27.2M
    }
124
33.9M
    return (gs_glyph)name_index(pfont->memory, &cname);
125
33.9M
}
126
127
/* Get the name of a glyph. */
128
static int
129
zfont_glyph_name(gs_font *font, gs_glyph index, gs_const_string *pstr)
130
98.4M
{
131
98.4M
    ref nref, sref;
132
133
98.4M
    if (index >= GS_MIN_CID_GLYPH) { /* Fabricate a numeric name. */
134
26
        char cid_name[sizeof(gs_glyph) * 3 + 1];
135
26
        int code;
136
137
26
        gs_snprintf(cid_name, sizeof(cid_name), "%lu", (ulong) index);
138
26
        code = name_ref(font->memory, (const byte *)cid_name, strlen(cid_name),
139
26
                        &nref, 1);
140
26
        if (code < 0)
141
0
            return code;
142
98.4M
    } else {
143
98.4M
        name_index_ref(font->memory, index, &nref);
144
98.4M
        if (nref.value.pname == NULL)
145
0
            return_error(gs_error_unknownerror);
146
98.4M
    }
147
98.4M
    name_string_ref(font->memory, &nref, &sref);
148
98.4M
    pstr->data = sref.value.const_bytes;
149
98.4M
    pstr->size = r_size(&sref);
150
98.4M
    return 0;
151
98.4M
}
152
153
void get_zfont_glyph_name( int (**proc)(gs_font *font, gs_glyph glyph, gs_const_string *pstr) )
154
89.0k
{
155
89.0k
    *proc = zfont_glyph_name;
156
89.0k
}
157
158
static gs_char
159
gs_font_map_glyph_by_dict(const gs_memory_t *mem, const ref *map, gs_glyph glyph, ushort *u, unsigned int length)
160
35.6k
{
161
35.6k
    ref *v, n;
162
35.6k
    uchar *unicode_return = (uchar *)u;
163
164
35.6k
    if (glyph == GS_NO_GLYPH)
165
0
        return 0;
166
167
35.6k
    if (glyph >= GS_MIN_CID_GLYPH) {
168
0
        uint cid = glyph - GS_MIN_CID_GLYPH;
169
170
0
        if (dict_find_string_with_type(map, "CIDCount", &v, t_integer) > 0) {
171
            /* This is a CIDDEcoding resource. */
172
0
            make_int(&n, cid / 256);
173
0
            if (dict_find_with_type(map, &n, &v, t_array) > 0) {
174
0
                ref vv;
175
176
0
                if (array_get_with_type(mem, v, cid % 256, &vv, t_integer) == 0) {
177
0
                    if (vv.value.intval > 65535) {
178
0
                        if (length < 4)
179
0
                            return 4;
180
0
                        unicode_return[0] = vv.value.intval >> 24;
181
0
                        unicode_return[1] = (vv.value.intval & 0x00FF0000) >> 16;
182
0
                        unicode_return[2] = (vv.value.intval & 0x0000FF00) >> 8;
183
0
                        unicode_return[3] = vv.value.intval & 0xFF;
184
0
                        return 4;
185
0
                    } else {
186
0
                        if (length < 2)
187
0
                            return 2;
188
0
                        unicode_return[0] = vv.value.intval >> 8;
189
0
                        unicode_return[1] = vv.value.intval & 0xFF;
190
0
                        return 2;
191
0
                    }
192
0
                }
193
0
            }
194
0
            return 0; /* Absent in the map. */
195
0
        }
196
        /* This is GlyphNames2Unicode dictionary. */
197
0
        make_int(&n, cid);
198
0
    } else
199
35.6k
        name_index_ref(mem, glyph, &n);
200
35.6k
     if (dict_find(map, &n, &v) > 0) {
201
35.0k
        if (r_has_type(v, t_string)) {
202
0
            int l = r_size(v);
203
204
0
            if (length < l)
205
0
                return l;
206
0
            memcpy(unicode_return, v->value.const_bytes, l);
207
0
            return l;
208
0
        }
209
35.0k
        if (r_type(v) == t_integer) {
210
35.0k
            if (v->value.intval > 65535) {
211
0
                if (length < 4)
212
0
                    return 4;
213
0
                unicode_return[0] = v->value.intval >> 24;
214
0
                unicode_return[1] = (v->value.intval & 0x00FF0000) >> 16;
215
0
                unicode_return[2] = (v->value.intval & 0x0000FF00) >> 8;
216
0
                unicode_return[3] = v->value.intval & 0xFF;
217
0
                return 4;
218
35.0k
            } else {
219
35.0k
                if (length < 2)
220
17.5k
                    return 2;
221
17.5k
                unicode_return[0] = v->value.intval >> 8;
222
17.5k
                unicode_return[1] = v->value.intval & 0xFF;
223
17.5k
                return 2;
224
35.0k
            }
225
35.0k
        }
226
35.0k
    }
227
534
    return 0; /* Absent in the map. */
228
35.6k
}
229
230
/* Get Unicode UTF-16 code for a glyph. */
231
int
232
gs_font_map_glyph_to_unicode(gs_font *font, gs_glyph glyph, int ch, ushort *u, unsigned int length)
233
69.0k
{
234
69.0k
    font_data *pdata = pfont_data(font);
235
69.0k
    const ref *UnicodeDecoding;
236
69.0k
    uchar *unicode_return = (uchar *)u;
237
238
69.0k
    if (r_type(&pdata->GlyphNames2Unicode) == t_dictionary) {
239
0
        int c = gs_font_map_glyph_by_dict(font->memory,
240
0
                                              &pdata->GlyphNames2Unicode, glyph, u, length);
241
242
0
        if (c != 0)
243
0
            return c;
244
0
        if (ch != -1) { /* -1 indicates a CIDFont */
245
            /* Its possible that we have a GlyphNames2Unicode dictionary
246
             * which contains integers and Unicode values, rather than names
247
             * and Unicode values. This happens if the input was PDF, the font
248
             * has a ToUnicode Cmap, but no Encoding. In this case we need to
249
             * use the character code as an index into the dictionary. Try that
250
             * now before we fall back to the UnicodeDecoding.
251
             */
252
0
            ref *v, n;
253
254
0
            make_int(&n, ch);
255
0
            if (dict_find(&pdata->GlyphNames2Unicode, &n, &v) > 0) {
256
0
                if (r_has_type(v, t_string)) {
257
0
                    int l = r_size(v);
258
259
0
                    if (l > length)
260
0
                        return l;
261
262
0
                    memcpy(unicode_return, v->value.const_bytes, l);
263
0
                    return l;
264
0
                }
265
0
                if (r_type(v) == t_integer) {
266
0
                    if (v->value.intval > 65535) {
267
0
                        if (length < 4)
268
0
                            return 4;
269
0
                        unicode_return[0] = v->value.intval >> 24;
270
0
                        unicode_return[1] = (v->value.intval & 0x00FF0000) >> 16;
271
0
                        unicode_return[2] = (v->value.intval & 0x0000FF00) >> 8;
272
0
                        unicode_return[3] = v->value.intval & 0xFF;
273
0
                        return 4;
274
0
                    } else {
275
0
                        if (length < 2)
276
0
                            return 2;
277
0
                        unicode_return[0] = v->value.intval >> 8;
278
0
                        unicode_return[1] = v->value.intval & 0xFF;
279
0
                        return 2;
280
0
                    }
281
0
                }
282
0
            }
283
0
        }
284
        /*
285
         * Fall through, because test.ps for SF bug #529103 requres
286
         * to examine both tables. Due to that the Unicode Decoding resource
287
         * can't be a default value for FontInfo.GlyphNames2Unicode .
288
         */
289
0
    }
290
69.0k
    if (glyph <= GS_MIN_CID_GLYPH && glyph != GS_NO_GLYPH) {
291
69.0k
        UnicodeDecoding = zfont_get_to_unicode_map(font->dir);
292
69.0k
        if (UnicodeDecoding != NULL && r_type(UnicodeDecoding) == t_dictionary)
293
35.6k
            return gs_font_map_glyph_by_dict(font->memory, UnicodeDecoding, glyph, u, length);
294
69.0k
    }
295
33.4k
    return 0; /* No map. */
296
69.0k
}
297
298
/* <bool> .setnativefontmapbuilt - */
299
static int
300
zsetnativefontmapbuilt(i_ctx_t *i_ctx_p)
301
168k
{
302
168k
    int code;
303
168k
    os_ptr op = osp;
304
168k
    check_op(1);
305
168k
    check_type(*op, t_boolean);
306
307
168k
    code = idict_put_string(systemdict, ".nativefontmapbuilt", op);
308
168k
    pop(1);
309
168k
    return code;
310
168k
}
311
312
/* <bool> .setloadingfont - */
313
static int
314
zsetloadingfont(i_ctx_t *i_ctx_p)
315
20.2k
{
316
20.2k
    int code;
317
20.2k
    os_ptr op = osp;
318
20.2k
    check_op(1);
319
20.2k
    check_type(*op, t_boolean);
320
321
20.2k
    code = idict_put_string(systemdict, ".loadingfont", op);
322
20.2k
    pop(1);
323
20.2k
    return code;
324
20.2k
}
325
326
/* <any> <dict|null> .updatefontdirectory -
327
 * If the second parameter is a dictionary, add the font dict to the FontDirectory.
328
 * If the second parameter is NULL, undefine the font.
329
 */
330
static int
331
zupdatefontdirectory(i_ctx_t *i_ctx_p)
332
631k
{
333
631k
    os_ptr op = osp;
334
631k
    int code = 0;
335
336
631k
    check_op(2);
337
338
631k
    if (r_has_type(op, t_null)) {
339
        /* undefinefont */
340
341
401k
        if (ialloc_space(idmemory) != avm_local) {
342
            /* global - undefine in the GlobalFontDirectory, too */
343
172k
            (void)idict_undef(&i_ctx_p->LocalFontDirectory, op - 1);  /* ignore undefined error */
344
172k
            (void)idict_undef(&i_ctx_p->GlobalFontDirectory, op - 1);  /* ignore undefined error */
345
172k
        }
346
228k
        else {
347
            /* local - if a font of the same name exists in the GlobalFontDirectory
348
               copy it into the local one
349
             */
350
228k
            ref *gfi;
351
228k
            code = dict_find(&i_ctx_p->GlobalFontDirectory, op - 1, &gfi);
352
228k
            if (code > 0)
353
                /* undefinefont cannot fail at this point, so ignore error */
354
228k
                (void)idict_put(&i_ctx_p->LocalFontDirectory, op - 1, gfi);
355
0
            else
356
0
                (void)idict_undef(&i_ctx_p->LocalFontDirectory, op - 1);  /* ignore undefined error */
357
358
228k
            code = 0;
359
228k
        }
360
401k
    }
361
230k
    else if (r_has_type(op, t_dictionary)) {
362
        /* definefont */
363
230k
        gs_font *pfont;
364
365
        /* This should always be a properly instantiated font - confirm that */
366
230k
        code = font_param(op, &pfont);
367
230k
        if (code < 0)
368
0
            return code;
369
370
230k
        code = idict_put(&i_ctx_p->LocalFontDirectory, op - 1, op);
371
230k
        if (code >= 0 && ialloc_space(idmemory) != avm_local)
372
228k
            code = idict_put(&i_ctx_p->GlobalFontDirectory, op - 1, op);
373
230k
    }
374
0
    else {
375
0
        code = gs_note_error(gs_error_typecheck);
376
0
    }
377
378
631k
    if (code >= 0)
379
631k
        pop(2);
380
381
631k
    return code;
382
631k
}
383
384
/* ------ Initialization procedure ------ */
385
386
const op_def zbfont_op_defs[] =
387
{
388
    {"2.updatefontdirectory", zupdatefontdirectory},
389
    {"2.setnativefontmapbuilt", zsetnativefontmapbuilt},
390
    {"2.setloadingfont", zsetloadingfont},
391
    {"2.buildfont3", zbuildfont3},
392
    op_def_end(0)
393
};
394
395
/* ------ Subroutines ------ */
396
397
/* Convert strings to executable names for build_proc_refs. */
398
int
399
build_proc_name_refs(const gs_memory_t *mem, build_proc_refs * pbuild,
400
                     const char *bcstr, const char *bgstr)
401
134k
{
402
134k
    int code;
403
404
134k
    if (!bcstr)
405
134k
        make_null(&pbuild->BuildChar);
406
134k
    else {
407
134k
        if ((code = name_ref(mem, (const byte *)bcstr,
408
134k
                             strlen(bcstr), &pbuild->BuildChar, 0)) < 0)
409
0
            return code;
410
134k
        r_set_attrs(&pbuild->BuildChar, a_executable);
411
134k
    }
412
134k
    if (!bgstr)
413
134k
        make_null(&pbuild->BuildGlyph);
414
134k
    else {
415
134k
        if ((code = name_ref(mem, (const byte *)bgstr,
416
134k
                             strlen(bgstr), &pbuild->BuildGlyph, 0)) < 0)
417
0
            return code;
418
134k
        r_set_attrs(&pbuild->BuildGlyph, a_executable);
419
134k
    }
420
134k
    return 0;
421
134k
}
422
423
/* Get the BuildChar and/or BuildGlyph routines from a (base) font. */
424
int
425
build_gs_font_procs(os_ptr op, build_proc_refs * pbuild)
426
163k
{
427
163k
    int ccode, gcode;
428
163k
    ref *pBuildChar;
429
163k
    ref *pBuildGlyph;
430
431
163k
    check_type(*op, t_dictionary);
432
163k
    ccode = dict_find_string(op, "BuildChar", &pBuildChar);
433
163k
    gcode = dict_find_string(op, "BuildGlyph", &pBuildGlyph);
434
163k
    if (ccode <= 0) {
435
22
        if (gcode <= 0)
436
9
            return_error(gs_error_invalidfont);
437
13
        make_null(&pbuild->BuildChar);
438
163k
    } else {
439
163k
        check_proc(*pBuildChar);
440
163k
        pbuild->BuildChar = *pBuildChar;
441
163k
    }
442
163k
    if (gcode <= 0)
443
163k
        make_null(&pbuild->BuildGlyph);
444
17
    else {
445
17
        check_proc(*pBuildGlyph);
446
17
        pbuild->BuildGlyph = *pBuildGlyph;
447
17
    }
448
163k
    return 0;
449
163k
}
450
451
static int font_with_same_UID_and_another_metrics(const gs_font *pfont0, const gs_font *pfont1)
452
63
{
453
63
    const gs_font_base *pbfont0 = (const gs_font_base *)pfont0;
454
63
    const gs_font_base *pbfont1 = (const gs_font_base *)pfont1;
455
456
63
    if (uid_equal(&pbfont0->UID, &pbfont1->UID)) {
457
63
        const ref *pfdict0 = &pfont_data(gs_font_parent(pbfont0))->dict;
458
63
        const ref *pfdict1 = &pfont_data(gs_font_parent(pbfont1))->dict;
459
63
        ref *pmdict0, *pmdict1;
460
461
63
        if (pbfont0->WMode || dict_find_string(pfdict0, "Metrics", &pmdict0) <= 0)
462
63
            pmdict0 = NULL;
463
63
        if (pbfont1->WMode || dict_find_string(pfdict1, "Metrics", &pmdict1) <= 0)
464
63
            pmdict1 = NULL;
465
63
        if (!pmdict0 != !pmdict1)
466
0
            return 1;
467
63
        if (pmdict0 != NULL && !obj_eq(pfont0->memory, pmdict0, pmdict1))
468
0
            return 1;
469
63
        if (!pbfont0->WMode || dict_find_string(pfdict0, "Metrics2", &pmdict0) <= 0)
470
63
            pmdict0 = NULL;
471
63
        if (!pbfont0->WMode || dict_find_string(pfdict1, "Metrics2", &pmdict1) <= 0)
472
63
            pmdict1 = NULL;
473
63
        if (!pmdict0 != !pmdict1)
474
0
            return 1;
475
63
        if (pmdict0 != NULL && !obj_eq(pfont0->memory, pmdict0, pmdict1))
476
0
            return 1;
477
63
    }
478
63
    return 0;
479
63
}
480
481
/* Do the common work for building a primitive font -- one whose execution */
482
/* algorithm is implemented in C (Type 1, Type 2, Type 4, or Type 42). */
483
/* The caller guarantees that *op is a dictionary. */
484
int
485
build_gs_primitive_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font_base ** ppfont,
486
                        font_type ftype, gs_memory_type_ptr_t pstype,
487
                        const build_proc_refs * pbuild,
488
                        build_font_options_t options)
489
66.9k
{
490
66.9k
    ref *pcharstrings = 0;
491
66.9k
    ref CharStrings;
492
66.9k
    gs_font_base *pfont;
493
66.9k
    font_data *pdata;
494
66.9k
    int code;
495
496
66.9k
    if (dict_find_string(op, "CharStrings", &pcharstrings) <= 0) {
497
0
        if (!(options & bf_CharStrings_optional))
498
0
            return_error(gs_error_invalidfont);
499
66.9k
    } else {
500
66.9k
        ref *ignore;
501
502
66.9k
        if (!r_has_type(pcharstrings, t_dictionary))
503
0
            return_error(gs_error_invalidfont);
504
66.9k
        if ((options & bf_notdef_required) != 0 &&
505
66.9k
            dict_find_string(pcharstrings, ".notdef", &ignore) <= 0
506
66.9k
            )
507
0
            return_error(gs_error_invalidfont);
508
        /*
509
         * Since build_gs_simple_font may resize the dictionary and cause
510
         * pointers to become invalid, save CharStrings.
511
         */
512
66.9k
        CharStrings = *pcharstrings;
513
66.9k
    }
514
66.9k
    code = build_gs_outline_font(i_ctx_p, op, ppfont, ftype, pstype, pbuild,
515
66.9k
                                 options, build_gs_simple_font);
516
66.9k
    if (code != 0)
517
28
        return code;
518
66.9k
    pfont = *ppfont;
519
66.9k
    pdata = pfont_data(pfont);
520
66.9k
    if (pcharstrings)
521
66.9k
        ref_assign(&pdata->CharStrings, &CharStrings);
522
0
    else
523
66.9k
        make_null(&pdata->CharStrings);
524
    /* Check that the UniqueIDs match.  This is part of the */
525
    /* Adobe protection scheme, but we may as well emulate it. */
526
66.9k
    if (uid_is_valid(&pfont->UID) &&
527
117
        !dict_check_uid_param(op, &pfont->UID)
528
66.9k
        )
529
0
        uid_set_invalid(&pfont->UID);
530
66.9k
    if (uid_is_valid(&pfont->UID)) {
531
117
        const gs_font *pfont0 = (const gs_font *)pfont;
532
533
117
        code = gs_font_find_similar(ifont_dir, &pfont0,
534
117
                       font_with_same_UID_and_another_metrics);
535
117
        if (code < 0)
536
0
            return code; /* Must not happen. */
537
117
        if (code)
538
0
            uid_set_invalid(&pfont->UID);
539
117
    }
540
66.9k
    return 0;
541
66.9k
}
542
543
/* Build a FDArray entry for a CIDFontType 0 font. */
544
/* Note that as of Adobe PostScript version 3011, this may be either */
545
/* a Type 1 or Type 2 font. */
546
static int
547
build_FDArray_sub_font(i_ctx_t *i_ctx_p, ref *op,
548
                       gs_font_base **ppfont,
549
                       font_type ftype, gs_memory_type_ptr_t pstype,
550
                       const build_proc_refs * pbuild,
551
                       build_font_options_t ignore_options)
552
1
{
553
1
    gs_font *pfont;
554
1
    int code = build_gs_sub_font(i_ctx_p, op, &pfont, ftype, pstype, pbuild,
555
1
                                 NULL, op);
556
557
1
    if (code >= 0)
558
1
        *ppfont = (gs_font_base *)pfont;
559
1
    return code;
560
1
}
561
int
562
build_gs_FDArray_font(i_ctx_t *i_ctx_p, ref *op,
563
                      gs_font_base **ppfont,
564
                      font_type ftype, gs_memory_type_ptr_t pstype,
565
                      const build_proc_refs * pbuild)
566
1
{
567
1
    gs_font_base *pfont;
568
1
    font_data *pdata;
569
1
    int code = build_gs_outline_font(i_ctx_p, op, &pfont, ftype, pstype,
570
1
                                     pbuild, bf_options_none,
571
1
                                     build_FDArray_sub_font);
572
1
    static const double bbox[4] = { 0, 0, 0, 0 };
573
1
    gs_uid uid;
574
575
1
    if (code < 0)
576
0
        return code;
577
1
    pdata = pfont_data(pfont);
578
    /* Fill in members normally set by build_gs_primitive_font. */
579
1
    make_null(&pdata->CharStrings);
580
    /* Fill in members normally set by build_gs_simple_font. */
581
1
    uid_set_invalid(&uid);
582
1
    init_gs_simple_font(pfont, bbox, &uid);
583
1
    pfont->encoding_index = ENCODING_INDEX_UNKNOWN;
584
1
    pfont->nearest_encoding_index = ENCODING_INDEX_UNKNOWN;
585
    /* Fill in members normally set by build_gs_font. */
586
1
    pfont->key_name = pfont->font_name;
587
1
    *ppfont = pfont;
588
1
    return 0;
589
1
}
590
591
/* Do the common work for building an outline font -- a non-composite font */
592
/* for which PaintType and StrokeWidth are meaningful. */
593
/* The caller guarantees that *op is a dictionary. */
594
int
595
build_gs_outline_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font_base ** ppfont,
596
                      font_type ftype, gs_memory_type_ptr_t pstype,
597
                      const build_proc_refs * pbuild,
598
                      build_font_options_t options,
599
                      build_base_font_proc_t build_base_font)
600
67.0k
{
601
67.0k
    int painttype;
602
67.0k
    float strokewidth;
603
67.0k
    gs_font_base *pfont;
604
67.0k
    int code = dict_int_param(op, "PaintType", 0, 3, 0, &painttype);
605
606
67.0k
    if (code < 0)
607
0
        return code;
608
67.0k
    code = dict_float_param(op, "StrokeWidth", 0.0, &strokewidth);
609
67.0k
    if (code < 0)
610
0
        return code;
611
67.0k
    code = build_base_font(i_ctx_p, op, ppfont, ftype, pstype, pbuild,
612
67.0k
                           options);
613
67.0k
    if (code != 0)
614
28
        return code;
615
66.9k
    pfont = *ppfont;
616
66.9k
    pfont->PaintType = painttype;
617
66.9k
    pfont->StrokeWidth = strokewidth;
618
66.9k
    return 0;
619
67.0k
}
620
621
void
622
get_GlyphNames2Unicode(i_ctx_t *i_ctx_p, gs_font *pfont, ref *pdref)
623
229k
{
624
229k
    ref *pfontinfo = NULL, *g2u = NULL;
625
229k
    font_data *pdata;
626
627
229k
    if (dict_find_string(pdref, "FontInfo", &pfontinfo) <= 0 ||
628
66.9k
            !r_has_type(pfontinfo, t_dictionary) ||
629
66.9k
            dict_find_string(pfontinfo, "GlyphNames2Unicode", &g2u) <= 0 ||
630
0
            !r_has_type(pfontinfo, t_dictionary))
631
229k
        return;
632
    /*
633
     * Since build_gs_font may resize the dictionary and cause
634
     * pointers to become invalid, save Glyph2Unicode
635
     */
636
0
    pdata = pfont_data(pfont);
637
0
    ref_assign_new(&pdata->GlyphNames2Unicode, g2u);
638
0
}
639
640
/* Do the common work for building a font of any non-composite FontType. */
641
/* The caller guarantees that *op is a dictionary. */
642
int
643
build_gs_simple_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font_base ** ppfont,
644
                     font_type ftype, gs_memory_type_ptr_t pstype,
645
                     const build_proc_refs * pbuild,
646
                     build_font_options_t options)
647
230k
{
648
230k
    double bbox[4];
649
230k
    gs_uid uid;
650
230k
    int code;
651
230k
    gs_font_base *pfont;
652
230k
    uint space = ialloc_space(idmemory);
653
654
230k
    code = font_bbox_param(imemory, op, bbox);
655
230k
    if (code < 0)
656
1
        return code;
657
    /*
658
     * Make sure that we allocate uid
659
     * in the same VM as the font dictionary
660
     * (see build_gs_sub_font).
661
     */
662
230k
    ialloc_set_space(idmemory, r_space(op));
663
230k
    code = dict_uid_param(op, &uid, 0, imemory, i_ctx_p);
664
230k
    ialloc_set_space(idmemory, space);
665
230k
    if (code < 0)
666
0
        return code;
667
230k
    if ((options & bf_UniqueID_ignored) && uid_is_UniqueID(&uid))
668
0
        uid_set_invalid(&uid);
669
230k
    code = build_gs_font(i_ctx_p, op, (gs_font **) ppfont, ftype, pstype,
670
230k
                         pbuild, options);
671
230k
    if (code != 0)    /* invalid or scaled font */
672
637
        return code;
673
229k
    pfont = *ppfont;
674
229k
    pfont->procs.init_fstack = gs_default_init_fstack;
675
229k
    pfont->procs.define_font = gs_no_define_font;
676
229k
    pfont->procs.decode_glyph = gs_font_map_glyph_to_unicode;
677
229k
    pfont->procs.make_font = zbase_make_font;
678
229k
    pfont->procs.next_char_glyph = gs_default_next_char_glyph;
679
229k
    pfont->FAPI = 0;
680
229k
    pfont->FAPI_font_data = 0;
681
229k
    init_gs_simple_font(pfont, bbox, &uid);
682
229k
    lookup_gs_simple_font_encoding(pfont);
683
229k
    get_GlyphNames2Unicode(i_ctx_p, (gs_font *)pfont, op);
684
229k
    return 0;
685
230k
}
686
687
/* Initialize the FontBBox and UID of a non-composite font. */
688
void
689
init_gs_simple_font(gs_font_base *pfont, const double bbox[4],
690
                    const gs_uid *puid)
691
229k
{
692
229k
    pfont->FontBBox.p.x = bbox[0];
693
229k
    pfont->FontBBox.p.y = bbox[1];
694
229k
    pfont->FontBBox.q.x = bbox[2];
695
229k
    pfont->FontBBox.q.y = bbox[3];
696
229k
    pfont->UID = *puid;
697
229k
}
698
699
/* Compare the encoding of a simple font with the registered encodings. */
700
void
701
lookup_gs_simple_font_encoding(gs_font_base * pfont)
702
229k
{
703
229k
    const ref *pfe = &pfont_data(pfont)->Encoding;
704
229k
    int index = -1;
705
706
229k
    pfont->encoding_index = index;
707
229k
    if (r_type(pfe) == t_array && r_size(pfe) <= 256) {
708
        /* Look for an encoding that's "close". */
709
229k
        uint esize = r_size(pfe);
710
229k
        int near_index = -1;
711
229k
        uint best = esize / 3;  /* must match at least this many */
712
229k
        gs_const_string fstrs[256];
713
229k
        int i;
714
715
        /* Get the string names of the glyphs in the font's Encoding. */
716
59.0M
        for (i = 0; i < esize; ++i) {
717
58.8M
            ref fchar;
718
719
58.8M
            if (array_get(pfont->memory, pfe, (long)i, &fchar) < 0 ||
720
58.8M
                !r_has_type(&fchar, t_name)
721
58.8M
                )
722
19.3k
                fstrs[i].data = 0, fstrs[i].size = 0;
723
58.8M
            else {
724
58.8M
                ref nsref;
725
726
58.8M
                name_string_ref(pfont->memory, &fchar, &nsref);
727
58.8M
                fstrs[i].data = nsref.value.const_bytes;
728
58.8M
                fstrs[i].size = r_size(&nsref);
729
58.8M
            }
730
58.8M
        }
731
        /* Compare them against the known encodings. */
732
234k
        for (index = 0; index < NUM_KNOWN_REAL_ENCODINGS; ++index) {
733
234k
            uint match = esize;
734
735
59.7M
            for (i = esize; --i >= 0;) {
736
59.5M
                gs_const_string rstr;
737
738
59.5M
                gs_c_glyph_name(gs_c_known_encode((gs_char)i, index), &rstr);
739
59.5M
                if (rstr.size == fstrs[i].size &&
740
58.8M
                    !memcmp(rstr.data, fstrs[i].data, rstr.size)
741
59.5M
                    )
742
58.8M
                    continue;
743
696k
                if (--match <= best)
744
4.39k
                    break;
745
696k
            }
746
234k
            if (match > best) {
747
229k
                best = match;
748
229k
                near_index = index;
749
                /* If we have a perfect match, stop now. */
750
229k
                if (best == esize)
751
229k
                    break;
752
229k
            }
753
234k
        }
754
229k
        index = near_index;
755
229k
        if (best == esize)
756
229k
            pfont->encoding_index = index;
757
229k
    }
758
229k
    pfont->nearest_encoding_index = index;
759
229k
}
760
761
/* Get FontMatrix and FontName parameters. */
762
static int
763
sub_font_params(gs_memory_t *mem, const ref *op, gs_matrix *pmat, gs_matrix *pomat, ref *pfname)
764
229k
{
765
229k
    ref *pmatrix, *pfontname, *pfontstyle, *porigfont, *pfontinfo;
766
767
229k
    if (dict_find_string(op, "FontMatrix", &pmatrix) <= 0 ||
768
229k
        read_matrix(mem, pmatrix, pmat) < 0
769
229k
        )
770
7
        return_error(gs_error_invalidfont);
771
229k
    if (dict_find_string(op, "OrigFont", &porigfont) <= 0)
772
1
        porigfont = NULL;
773
229k
    if (porigfont != NULL && !r_has_type(porigfont, t_dictionary))
774
0
        return_error(gs_error_typecheck);
775
776
229k
    if (pomat!= NULL) {
777
229k
        if (porigfont == NULL ||
778
229k
            dict_find_string(porigfont, "FontMatrix", &pmatrix) <= 0 ||
779
229k
            read_matrix(mem, pmatrix, pomat) < 0
780
229k
            )
781
1
            memset(pomat, 0, sizeof(*pomat));
782
229k
    }
783
    /* Use the FontInfo/OrigFontName key preferrentially (created by MS PSCRIPT driver) */
784
229k
    if ((dict_find_string((porigfont != NULL ? porigfont : op), "FontInfo", &pfontinfo) > 0) &&
785
66.9k
        r_has_type(pfontinfo, t_dictionary) &&
786
66.9k
        (dict_find_string(pfontinfo, "OrigFontName", &pfontname) > 0) && (r_has_type(pfontname, t_name) || r_has_type(pfontname, t_string))) {
787
0
        if ((dict_find_string(pfontinfo, "OrigFontStyle", &pfontstyle) > 0) && (r_has_type(pfontstyle, t_name) || r_has_type(pfontstyle, t_string)) &&
788
0
                r_size(pfontstyle) > 0) {
789
0
            const byte *tmpStr1 = NULL, *tmpStr2 = NULL;
790
0
            ref pfn_str, pfs_str;
791
0
            int fssize1, fssize2, fssize;
792
0
            byte *sfname;
793
794
0
            if (r_has_type(pfontstyle, t_string)) {
795
0
                tmpStr1 = pfontstyle->value.const_bytes;
796
0
                fssize1 = r_size(pfontstyle);
797
0
            }
798
0
            else {
799
0
                name_string_ref(mem, pfontstyle, &pfs_str);
800
0
                tmpStr1 = pfs_str.value.const_bytes;
801
0
                fssize1 = r_size(&pfs_str);
802
0
            }
803
0
            if (r_has_type(pfontname, t_string)) {
804
0
                tmpStr2 = pfontname->value.const_bytes;
805
0
                fssize2 = r_size(pfontname);
806
0
            }
807
0
            else {
808
0
                name_string_ref(mem, pfontname, &pfn_str);
809
0
                tmpStr2 = pfn_str.value.const_bytes;
810
0
                fssize2 = r_size(&pfn_str);
811
0
            }
812
813
0
            fssize = fssize1 + fssize2 + 1;
814
0
            sfname = gs_alloc_string(mem, fssize, "sub_font_params");
815
0
            if (sfname == NULL)
816
0
                return_error(gs_error_VMerror);
817
0
            memcpy(sfname, tmpStr1, fssize1);
818
0
            sfname[fssize1]=',' ;
819
0
            memcpy(sfname + fssize1 + 1, tmpStr2, fssize2);
820
0
            make_string(pfname, a_readonly, fssize, sfname);
821
0
        } else
822
0
            get_font_name(mem, pfname, pfontname);
823
229k
    } else if (dict_find_string((porigfont != NULL ? porigfont : op), ".Alias", &pfontname) > 0) {
824
        /* If we emulate the font, we want the requested name rather than a substitute. */
825
56.8k
        get_font_name(mem, pfname, pfontname);
826
172k
    } else if (dict_find_string((porigfont != NULL ? porigfont : op), "FontName", &pfontname) > 0) {
827
172k
        get_font_name(mem, pfname, pfontname);
828
172k
    } else
829
616
        make_empty_string(pfname, a_readonly);
830
229k
    return 0;
831
229k
}
832
833
/* Do the common work for building a font of any FontType. */
834
/* The caller guarantees that *op is a dictionary. */
835
/* op[-1] must be the key under which the font is being registered */
836
/* in FontDirectory, normally a name or string. */
837
/* Return 0 for a new font, 1 for a font made by makefont or scalefont, */
838
/* or a negative error code. */
839
int
840
build_gs_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font ** ppfont, font_type ftype,
841
              gs_memory_type_ptr_t pstype, const build_proc_refs * pbuild,
842
              build_font_options_t options)
843
230k
{
844
230k
    ref kname;      /* t_string */
845
230k
    ref *pftype;
846
230k
    ref *pencoding = 0;
847
230k
    bool bitmapwidths;
848
230k
    int exactsize, inbetweensize, transformedchar;
849
230k
    int wmode;
850
230k
    int code;
851
230k
    gs_font *pfont;
852
230k
    ref *pfid;
853
230k
    ref *aop = dict_access_ref(op);
854
230k
    bool cpsi_mode = gs_currentcpsimode(imemory);
855
856
230k
    get_font_name(imemory, &kname, op - 1);
857
230k
    if (dict_find_string(op, "FontType", &pftype) <= 0 ||
858
230k
        !r_has_type(pftype, t_integer) ||
859
230k
        pftype->value.intval != (int)ftype
860
230k
        )
861
0
        return_error(gs_error_invalidfont);
862
230k
    if (dict_find_string(op, "Encoding", &pencoding) <= 0) {
863
5
        if (!(options & bf_Encoding_optional))
864
4
            return_error(gs_error_invalidfont);
865
1
        pencoding = 0;
866
230k
    } else {
867
230k
        if (!r_is_array(pencoding))
868
0
            return_error(gs_error_invalidfont);
869
230k
    }
870
230k
    if (pencoding) {   /* observed Adobe behavior */
871
230k
        int count = r_size(pencoding);
872
230k
        int type = ftype ? t_name : t_integer;
873
230k
        bool fixit = false;
874
875
60.1M
        while (count--) {
876
59.9M
           ref r;
877
59.9M
           if ((code = array_get(imemory, pencoding, count, &r)) < 0 ||
878
59.9M
             !(r_has_type(&r, type) || r_has_type(&r, t_null))) {
879
0
               if (!cpsi_mode && ftype == ft_user_defined) {
880
0
                   if (code < 0 || r_has_type(&r, t_null)) {
881
0
                       return_error(gs_error_typecheck);
882
0
                   }
883
0
                   fixit = true;
884
0
                   break;
885
0
               }
886
0
               else {
887
0
                   return_error(gs_error_typecheck);
888
0
               }
889
0
           }
890
59.9M
        }
891
892
        /* For at least Type 3 fonts, Adobe Distiller will "fix" an Encoding array, as in, for example
893
         * Bug 692681 where the arrays contain integers rather than names. Once the font is instantiated
894
         * the integers have been converted to names.
895
         * It is preferable to to this manipulation here, rather than in Postscript, because we are less
896
         * restricted by read-only attributes and VM save levels.
897
         */
898
230k
        if (fixit) {
899
0
            ref penc;
900
0
            uint size = 0;
901
0
            char buf[32], *bptr;
902
0
            avm_space curglob = ialloc_space(idmemory);
903
0
            avm_space useglob = r_is_local(pencoding) ? avm_local : avm_global;
904
905
0
            ialloc_set_space(idmemory, useglob);
906
907
0
            count = r_size(pencoding);
908
0
            if ((code = ialloc_ref_array(&penc, (r_type_attrs(pencoding) & a_readonly), count, "build_gs_font")) < 0)
909
0
                 return code;
910
911
0
            while (count--) {
912
0
               ref r;
913
0
               if (array_get(imemory, pencoding, count, &r) < 0){
914
0
                   return_error(gs_error_typecheck);
915
0
               }
916
               /* For type 3, we know the Encoding entries must be names */
917
0
               if (r_has_type(&r, t_name)){
918
0
                   ref_assign(&(penc.value.refs[count]), &r);
919
0
               }
920
0
               else {
921
922
0
                   if ((code = obj_cvs(imemory, &r, (byte *)buf, 32, &size, (const byte **)(&bptr))) < 0) {
923
0
                       return(code);
924
0
                   }
925
0
                   if ((code = name_ref(imemory, (const byte *)bptr, size, &r, true)) < 0)
926
0
                        return code;
927
0
                   ref_assign(&(penc.value.refs[count]), &r);
928
0
               }
929
0
            }
930
931
0
            if ((code = dict_put_string(osp, "Encoding", &penc, NULL)) < 0)
932
0
               return code;
933
0
            ialloc_set_space(idmemory, curglob);
934
0
        }
935
230k
    }
936
230k
    if ((code = dict_int_param(op, "WMode", 0, 1, 0, &wmode)) < 0 ||
937
230k
        (code = dict_bool_param(op, "BitmapWidths", false, &bitmapwidths)) < 0 ||
938
230k
        (code = dict_int_param(op, "ExactSize", 0, 2, fbit_use_bitmaps, &exactsize)) < 0 ||
939
230k
        (code = dict_int_param(op, "InBetweenSize", 0, 2, fbit_use_outlines, &inbetweensize)) < 0 ||
940
230k
        (code = dict_int_param(op, "TransformedChar", 0, 2, fbit_use_outlines, &transformedchar)) < 0
941
230k
        )
942
0
        return code;
943
230k
    code = dict_find_string(op, "FID", &pfid);
944
230k
    if (code > 0 && r_has_type(pfid, t_fontID)) { /* silently ignore invalid FID per CET 13-05.ps */
945
        /*
946
         * If this font has a FID entry already, it might be a scaled font
947
         * made by makefont or scalefont; in a Level 2 environment, it might
948
         * be an existing font being registered under a second name, or a
949
         * re-encoded font (which was invalid in Level 1, but dvips did it
950
         * anyway).
951
         */
952
626
        pfont = r_ptr(pfid, gs_font);
953
        /*
954
         * If the following condition is false this is a re-encoded font,
955
         * or some other questionable situation in which the FID
956
         * was preserved.  Pretend the FID wasn't there.
957
         */
958
626
        if (obj_eq(pfont->memory, pfont_dict(pfont), op) && pfont->FontType == ftype) {
959
626
            if (pfont->base == pfont) { /* original font */
960
626
                if (!level2_enabled)
961
0
                    return_error(gs_error_invalidfont);
962
626
                *ppfont = pfont;
963
626
                return 1;
964
626
            } else {   /* This was made by makefont or scalefont. */
965
                /* Just insert the new name. */
966
0
                gs_matrix mat;
967
0
                ref fname;      /* t_string */
968
969
0
                code = sub_font_params(imemory, op, &mat, NULL, &fname);
970
0
                if (code < 0)
971
0
                    return code;
972
0
                code = 1;
973
0
                copy_font_name(&pfont->font_name, &fname);
974
0
                goto set_name;
975
0
            }
976
626
        }
977
626
    }
978
    /* This is a new font. */
979
229k
    if (!r_has_attr(aop, a_write))
980
0
        return_error(gs_error_invalidaccess);
981
229k
    {
982
229k
        ref encoding;
983
984
        /*
985
         * Since add_FID may resize the dictionary and cause
986
         * pencoding to become invalid, save the Encoding.
987
         */
988
229k
        if (pencoding) {
989
229k
            encoding = *pencoding;
990
229k
            pencoding = &encoding;
991
229k
        }
992
229k
        code = build_gs_sub_font(i_ctx_p, op, &pfont, ftype, pstype,
993
229k
                                 pbuild, pencoding, op);
994
229k
        if (code < 0)
995
7
            return code;
996
229k
    }
997
229k
    pfont->BitmapWidths = bitmapwidths;
998
229k
    pfont->ExactSize = (fbit_type)exactsize;
999
229k
    pfont->InBetweenSize = (fbit_type)inbetweensize;
1000
229k
    pfont->TransformedChar = (fbit_type)transformedchar;
1001
229k
    pfont->WMode = wmode;
1002
229k
    pfont->procs.font_info = zfont_info;
1003
229k
    code = 0;
1004
229k
set_name:
1005
229k
    copy_font_name(&pfont->key_name, &kname);
1006
229k
    *ppfont = pfont;
1007
229k
    return code;
1008
229k
}
1009
1010
/* Create a sub-font -- a font or an entry in the FDArray of a CIDFontType 0 */
1011
/* font.  Default BitmapWidths, ExactSize, InBetweenSize, TransformedChar, */
1012
/* and WMode; do not fill in key_name. */
1013
/* The caller guarantees that *op is a dictionary. */
1014
int
1015
build_gs_sub_font(i_ctx_t *i_ctx_p, const ref *op, gs_font **ppfont,
1016
                  font_type ftype, gs_memory_type_ptr_t pstype,
1017
                  const build_proc_refs * pbuild, const ref *pencoding,
1018
                  ref *fid_op)
1019
229k
{
1020
229k
    gs_matrix mat, omat;
1021
229k
    ref fname;      /* t_string */
1022
229k
    gs_font *pfont;
1023
229k
    font_data *pdata;
1024
    /*
1025
     * Make sure that we allocate the font data
1026
     * in the same VM as the font dictionary.
1027
     */
1028
229k
    uint space = ialloc_space(idmemory);
1029
229k
    int code = sub_font_params(imemory, op, &mat, &omat, &fname);
1030
1031
229k
    if (code < 0)
1032
7
        return code;
1033
229k
    ialloc_set_space(idmemory, r_space(op));
1034
229k
    pfont = gs_font_alloc(imemory, pstype, &gs_font_procs_default, NULL,
1035
229k
                          "buildfont(font)");
1036
229k
    pdata = ialloc_struct(font_data, &st_font_data,
1037
229k
                          "buildfont(data)");
1038
229k
    if (pfont == 0 || pdata == 0)
1039
0
        code = gs_note_error(gs_error_VMerror);
1040
229k
    else if (fid_op)
1041
229k
        code = add_FID(i_ctx_p, fid_op, pfont, iimemory);
1042
229k
    if (code < 0) {
1043
0
        ifree_object(pdata, "buildfont(data)");
1044
0
        ifree_object(pfont, "buildfont(font)");
1045
0
        ialloc_set_space(idmemory, space);
1046
0
        return code;
1047
0
    }
1048
229k
    refset_null((ref *) pdata, sizeof(font_data) / sizeof(ref));
1049
229k
    ref_assign_new(&pdata->dict, op);
1050
229k
    ref_assign_new(&pdata->BuildChar, &pbuild->BuildChar);
1051
229k
    ref_assign_new(&pdata->BuildGlyph, &pbuild->BuildGlyph);
1052
229k
    if (pencoding)
1053
229k
        ref_assign_new(&pdata->Encoding, pencoding);
1054
229k
    pfont->client_data = pdata;
1055
229k
    pfont->FontType = ftype;
1056
229k
    pfont->FontMatrix = mat;
1057
229k
    pfont->orig_FontMatrix = omat;
1058
229k
    pfont->BitmapWidths = false;
1059
229k
    pfont->ExactSize = fbit_use_bitmaps;
1060
229k
    pfont->InBetweenSize = fbit_use_outlines;
1061
229k
    pfont->TransformedChar = fbit_use_outlines;
1062
229k
    pfont->WMode = 0;
1063
229k
    pfont->procs.encode_char = zfont_encode_char;
1064
229k
    pfont->procs.glyph_name = zfont_glyph_name;
1065
229k
    ialloc_set_space(idmemory, space);
1066
229k
    copy_font_name(&pfont->font_name, &fname);
1067
229k
    *ppfont = pfont;
1068
229k
    return 0;
1069
229k
}
1070
1071
/* Get the string corresponding to a font name. */
1072
/* If the font name isn't a name or a string, return an empty string. */
1073
void
1074
get_font_name(const gs_memory_t *mem, ref * pfname, const ref * op)
1075
459k
{
1076
459k
    switch (r_type(op)) {
1077
162k
        case t_string:
1078
162k
            *pfname = *op;
1079
162k
            break;
1080
222k
        case t_name:
1081
222k
            name_string_ref(mem, op, pfname);
1082
222k
            break;
1083
75.1k
        default:
1084
            /* This is weird, but legal.... */
1085
75.1k
            make_empty_string(pfname, a_readonly);
1086
459k
    }
1087
459k
}
1088
1089
/* Copy a font name into the gs_font structure. */
1090
void
1091
copy_font_name(gs_font_name * pfstr, const ref * pfname)
1092
459k
{
1093
459k
    uint size = r_size(pfname);
1094
1095
459k
    if (size > gs_font_name_max)
1096
822
        size = gs_font_name_max;
1097
459k
    memcpy(&pfstr->chars[0], pfname->value.const_bytes, size);
1098
    /* Following is only for debugging printout. */
1099
459k
    pfstr->chars[size] = 0;
1100
459k
    pfstr->size = size;
1101
459k
}
1102
1103
/* Finish building a font, by calling gs_definefont if needed. */
1104
int
1105
define_gs_font(i_ctx_t *i_ctx_p, gs_font * pfont)
1106
230k
{
1107
230k
    return (pfont->base == pfont && pfont->dir == 0 ?
1108
            /* i.e., unregistered original font */
1109
229k
            gs_definefont(ifont_dir, pfont) :
1110
230k
            0);
1111
230k
}