Coverage Report

Created: 2026-08-08 08:00

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