Coverage Report

Created: 2026-04-09 07:06

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
434k
{
44
434k
    ref_struct_clear_marks(cmem, vptr, offset_of(font_data, u.type42.mru_sfnts_index)/*size*/, pstype);
45
434k
}
46
static
47
ENUM_PTRS_BEGIN_PROC(font_data_enum_ptrs)
48
4.12M
{
49
4.12M
    return ref_struct_enum_ptrs(mem, vptr, offset_of(font_data, u.type42.mru_sfnts_index)/*size*/, index, pep, pstype, gcst);
50
4.12M
}
51
ENUM_PTRS_END_PROC
52
static
53
412k
RELOC_PTRS_BEGIN(font_data_reloc_ptrs)
54
412k
{
55
412k
    ref_struct_reloc_ptrs(vptr, offset_of(font_data, u.type42.mru_sfnts_index)/*size*/, pstype, gcst);
56
412k
}
57
412k
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
152k
{
64
152k
    os_ptr op = osp;
65
152k
    int code;
66
152k
    build_proc_refs build;
67
152k
    gs_font_base *pfont;
68
69
152k
    check_op(2);
70
152k
    check_type(*op, t_dictionary);
71
152k
    code = build_gs_font_procs(op, &build);
72
152k
    if (code < 0)
73
13
        return code;
74
152k
    code = build_gs_simple_font(i_ctx_p, op, &pfont, ft_user_defined,
75
152k
                                &st_gs_font_base, &build, bf_options_none);
76
152k
    if (code < 0)
77
12
        return code;
78
152k
    return define_gs_font(i_ctx_p, (gs_font *) pfont);
79
152k
}
80
81
/* Encode a character. */
82
gs_glyph
83
zfont_encode_char(gs_font *pfont, gs_char chr, gs_glyph_space_t gspace)
84
37.1M
{
85
37.1M
    font_data *pdata = pfont_data(pfont);
86
37.1M
    const ref *pencoding = &pdata->Encoding;
87
37.1M
    ulong index = chr;  /* work around VAX widening bug */
88
37.1M
    ref cname;
89
37.1M
    int code = array_get(pfont->memory, pencoding, (long)index, &cname);
90
91
37.1M
    if (code < 0 || !r_has_type(&cname, t_name))
92
1.05k
        return GS_NO_GLYPH;
93
37.1M
    if (pfont->FontType == ft_user_defined && r_type(&pdata->BuildGlyph) == t_null) {
94
29.8M
        ref nsref, tname;
95
96
29.8M
        name_string_ref(pfont->memory, &cname, &nsref);
97
29.8M
        if (r_size(&nsref) == 7 &&
98
6.91M
            !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.66M
            char buf[20];
109
6.66M
            int code;
110
111
6.66M
            if (gspace == GLYPH_SPACE_NOGEN)
112
0
                return GS_NO_GLYPH;
113
6.66M
            gs_snprintf(buf, sizeof(buf), "j%ld", chr); /* 'j' is arbutrary. */
114
6.66M
            code = name_ref(pfont->memory, (const byte *)buf, strlen(buf), &tname, 1);
115
6.66M
            if (code < 0) {
116
                /* Can't propagate the error due to interface limitation,
117
                   return with .notdef */
118
0
            } else
119
6.66M
                cname = tname;
120
6.66M
        }
121
29.8M
    }
122
37.1M
    return (gs_glyph)name_index(pfont->memory, &cname);
123
37.1M
}
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
94.4M
{
129
94.4M
    ref nref, sref;
130
131
94.4M
    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
94.4M
    } else {
141
94.4M
        name_index_ref(font->memory, index, &nref);
142
94.4M
        if (nref.value.pname == NULL)
143
0
            return_error(gs_error_unknownerror);
144
94.4M
    }
145
94.4M
    name_string_ref(font->memory, &nref, &sref);
146
94.4M
    pstr->data = sref.value.const_bytes;
147
94.4M
    pstr->size = r_size(&sref);
148
94.4M
    return 0;
149
94.4M
}
150
151
void get_zfont_glyph_name( int (**proc)(gs_font *font, gs_glyph glyph, gs_const_string *pstr) )
152
85.6k
{
153
85.6k
    *proc = zfont_glyph_name;
154
85.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.8k
{
159
35.8k
    ref *v, n;
160
35.8k
    uchar *unicode_return = (uchar *)u;
161
162
35.8k
    if (glyph == GS_NO_GLYPH)
163
0
        return 0;
164
165
35.8k
    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] = v->value.intval >> 24;
179
0
                        unicode_return[1] = (v->value.intval & 0x00FF0000) >> 16;
180
0
                        unicode_return[2] = (v->value.intval & 0x0000FF00) >> 8;
181
0
                        unicode_return[3] = v->value.intval & 0xFF;
182
0
                        return 4;
183
0
                    } else {
184
0
                        if (length < 2)
185
0
                            return 2;
186
0
                        unicode_return[0] = v->value.intval >> 8;
187
0
                        unicode_return[1] = v->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.8k
        name_index_ref(mem, glyph, &n);
198
35.8k
     if (dict_find(map, &n, &v) > 0) {
199
35.3k
        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.3k
        if (r_type(v) == t_integer) {
208
35.3k
            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.3k
            } else {
217
35.3k
                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.3k
            }
223
35.3k
        }
224
35.3k
    }
225
535
    return 0; /* Absent in the map. */
226
35.8k
}
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
73.9k
{
232
73.9k
    font_data *pdata = pfont_data(font);
233
73.9k
    const ref *UnicodeDecoding;
234
73.9k
    uchar *unicode_return = (uchar *)u;
235
236
73.9k
    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
73.9k
    if (glyph <= GS_MIN_CID_GLYPH && glyph != GS_NO_GLYPH) {
289
73.9k
        UnicodeDecoding = zfont_get_to_unicode_map(font->dir);
290
73.9k
        if (UnicodeDecoding != NULL && r_type(UnicodeDecoding) == t_dictionary)
291
35.8k
            return gs_font_map_glyph_by_dict(font->memory, UnicodeDecoding, glyph, u, length);
292
73.9k
    }
293
38.0k
    return 0; /* No map. */
294
73.9k
}
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
143k
{
311
143k
    int code;
312
313
143k
    if (!bcstr)
314
143k
        make_null(&pbuild->BuildChar);
315
143k
    else {
316
143k
        if ((code = name_ref(mem, (const byte *)bcstr,
317
143k
                             strlen(bcstr), &pbuild->BuildChar, 0)) < 0)
318
0
            return code;
319
143k
        r_set_attrs(&pbuild->BuildChar, a_executable);
320
143k
    }
321
143k
    if (!bgstr)
322
143k
        make_null(&pbuild->BuildGlyph);
323
143k
    else {
324
143k
        if ((code = name_ref(mem, (const byte *)bgstr,
325
143k
                             strlen(bgstr), &pbuild->BuildGlyph, 0)) < 0)
326
0
            return code;
327
143k
        r_set_attrs(&pbuild->BuildGlyph, a_executable);
328
143k
    }
329
143k
    return 0;
330
143k
}
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
152k
{
336
152k
    int ccode, gcode;
337
152k
    ref *pBuildChar;
338
152k
    ref *pBuildGlyph;
339
340
152k
    check_type(*op, t_dictionary);
341
152k
    ccode = dict_find_string(op, "BuildChar", &pBuildChar);
342
152k
    gcode = dict_find_string(op, "BuildGlyph", &pBuildGlyph);
343
152k
    if (ccode <= 0) {
344
11
        if (gcode <= 0)
345
11
            return_error(gs_error_invalidfont);
346
0
        make_null(&pbuild->BuildChar);
347
152k
    } else {
348
152k
        check_proc(*pBuildChar);
349
152k
        pbuild->BuildChar = *pBuildChar;
350
152k
    }
351
152k
    if (gcode <= 0)
352
152k
        make_null(&pbuild->BuildGlyph);
353
2
    else {
354
2
        check_proc(*pBuildGlyph);
355
2
        pbuild->BuildGlyph = *pBuildGlyph;
356
2
    }
357
152k
    return 0;
358
152k
}
359
360
static int font_with_same_UID_and_another_metrics(const gs_font *pfont0, const gs_font *pfont1)
361
76
{
362
76
    const gs_font_base *pbfont0 = (const gs_font_base *)pfont0;
363
76
    const gs_font_base *pbfont1 = (const gs_font_base *)pfont1;
364
365
76
    if (uid_equal(&pbfont0->UID, &pbfont1->UID)) {
366
76
        const ref *pfdict0 = &pfont_data(gs_font_parent(pbfont0))->dict;
367
76
        const ref *pfdict1 = &pfont_data(gs_font_parent(pbfont1))->dict;
368
76
        ref *pmdict0, *pmdict1;
369
370
76
        if (pbfont0->WMode || dict_find_string(pfdict0, "Metrics", &pmdict0) <= 0)
371
76
            pmdict0 = NULL;
372
76
        if (pbfont1->WMode || dict_find_string(pfdict1, "Metrics", &pmdict1) <= 0)
373
76
            pmdict1 = NULL;
374
76
        if (!pmdict0 != !pmdict1)
375
0
            return 1;
376
76
        if (pmdict0 != NULL && !obj_eq(pfont0->memory, pmdict0, pmdict1))
377
0
            return 1;
378
76
        if (!pbfont0->WMode || dict_find_string(pfdict0, "Metrics2", &pmdict0) <= 0)
379
76
            pmdict0 = NULL;
380
76
        if (!pbfont0->WMode || dict_find_string(pfdict1, "Metrics2", &pmdict1) <= 0)
381
76
            pmdict1 = NULL;
382
76
        if (!pmdict0 != !pmdict1)
383
0
            return 1;
384
76
        if (pmdict0 != NULL && !obj_eq(pfont0->memory, pmdict0, pmdict1))
385
0
            return 1;
386
76
    }
387
76
    return 0;
388
76
}
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
71.8k
{
399
71.8k
    ref *pcharstrings = 0;
400
71.8k
    ref CharStrings;
401
71.8k
    gs_font_base *pfont;
402
71.8k
    font_data *pdata;
403
71.8k
    int code;
404
405
71.8k
    if (dict_find_string(op, "CharStrings", &pcharstrings) <= 0) {
406
0
        if (!(options & bf_CharStrings_optional))
407
0
            return_error(gs_error_invalidfont);
408
71.8k
    } else {
409
71.8k
        ref *ignore;
410
411
71.8k
        if (!r_has_type(pcharstrings, t_dictionary))
412
0
            return_error(gs_error_invalidfont);
413
71.8k
        if ((options & bf_notdef_required) != 0 &&
414
71.7k
            dict_find_string(pcharstrings, ".notdef", &ignore) <= 0
415
71.8k
            )
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
71.8k
        CharStrings = *pcharstrings;
422
71.8k
    }
423
71.8k
    code = build_gs_outline_font(i_ctx_p, op, ppfont, ftype, pstype, pbuild,
424
71.8k
                                 options, build_gs_simple_font);
425
71.8k
    if (code != 0)
426
28
        return code;
427
71.7k
    pfont = *ppfont;
428
71.7k
    pdata = pfont_data(pfont);
429
71.7k
    if (pcharstrings)
430
71.7k
        ref_assign(&pdata->CharStrings, &CharStrings);
431
0
    else
432
71.7k
        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
71.7k
    if (uid_is_valid(&pfont->UID) &&
436
137
        !dict_check_uid_param(op, &pfont->UID)
437
71.7k
        )
438
0
        uid_set_invalid(&pfont->UID);
439
71.7k
    if (uid_is_valid(&pfont->UID)) {
440
137
        const gs_font *pfont0 = (const gs_font *)pfont;
441
442
137
        code = gs_font_find_similar(ifont_dir, &pfont0,
443
137
                       font_with_same_UID_and_another_metrics);
444
137
        if (code < 0)
445
0
            return code; /* Must not happen. */
446
137
        if (code)
447
0
            uid_set_invalid(&pfont->UID);
448
137
    }
449
71.7k
    return 0;
450
71.7k
}
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
71.8k
{
510
71.8k
    int painttype;
511
71.8k
    float strokewidth;
512
71.8k
    gs_font_base *pfont;
513
71.8k
    int code = dict_int_param(op, "PaintType", 0, 3, 0, &painttype);
514
515
71.8k
    if (code < 0)
516
0
        return code;
517
71.8k
    code = dict_float_param(op, "StrokeWidth", 0.0, &strokewidth);
518
71.8k
    if (code < 0)
519
0
        return code;
520
71.8k
    code = build_base_font(i_ctx_p, op, ppfont, ftype, pstype, pbuild,
521
71.8k
                           options);
522
71.8k
    if (code != 0)
523
28
        return code;
524
71.7k
    pfont = *ppfont;
525
71.7k
    pfont->PaintType = painttype;
526
71.7k
    pfont->StrokeWidth = strokewidth;
527
71.7k
    return 0;
528
71.8k
}
529
530
void
531
get_GlyphNames2Unicode(i_ctx_t *i_ctx_p, gs_font *pfont, ref *pdref)
532
223k
{
533
223k
    ref *pfontinfo = NULL, *g2u = NULL;
534
223k
    font_data *pdata;
535
536
223k
    if (dict_find_string(pdref, "FontInfo", &pfontinfo) <= 0 ||
537
71.7k
            !r_has_type(pfontinfo, t_dictionary) ||
538
71.7k
            dict_find_string(pfontinfo, "GlyphNames2Unicode", &g2u) <= 0 ||
539
0
            !r_has_type(pfontinfo, t_dictionary))
540
223k
        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
224k
{
557
224k
    double bbox[4];
558
224k
    gs_uid uid;
559
224k
    int code;
560
224k
    gs_font_base *pfont;
561
224k
    uint space = ialloc_space(idmemory);
562
563
224k
    code = font_bbox_param(imemory, op, bbox);
564
224k
    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
224k
    ialloc_set_space(idmemory, r_space(op));
572
224k
    code = dict_uid_param(op, &uid, 0, imemory, i_ctx_p);
573
224k
    ialloc_set_space(idmemory, space);
574
224k
    if (code < 0)
575
0
        return code;
576
224k
    if ((options & bf_UniqueID_ignored) && uid_is_UniqueID(&uid))
577
0
        uid_set_invalid(&uid);
578
224k
    code = build_gs_font(i_ctx_p, op, (gs_font **) ppfont, ftype, pstype,
579
224k
                         pbuild, options);
580
224k
    if (code != 0)    /* invalid or scaled font */
581
686
        return code;
582
223k
    pfont = *ppfont;
583
223k
    pfont->procs.init_fstack = gs_default_init_fstack;
584
223k
    pfont->procs.define_font = gs_no_define_font;
585
223k
    pfont->procs.decode_glyph = gs_font_map_glyph_to_unicode;
586
223k
    pfont->procs.make_font = zbase_make_font;
587
223k
    pfont->procs.next_char_glyph = gs_default_next_char_glyph;
588
223k
    pfont->FAPI = 0;
589
223k
    pfont->FAPI_font_data = 0;
590
223k
    init_gs_simple_font(pfont, bbox, &uid);
591
223k
    lookup_gs_simple_font_encoding(pfont);
592
223k
    get_GlyphNames2Unicode(i_ctx_p, (gs_font *)pfont, op);
593
223k
    return 0;
594
224k
}
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
223k
{
601
223k
    pfont->FontBBox.p.x = bbox[0];
602
223k
    pfont->FontBBox.p.y = bbox[1];
603
223k
    pfont->FontBBox.q.x = bbox[2];
604
223k
    pfont->FontBBox.q.y = bbox[3];
605
223k
    pfont->UID = *puid;
606
223k
}
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
223k
{
612
223k
    const ref *pfe = &pfont_data(pfont)->Encoding;
613
223k
    int index = -1;
614
615
223k
    pfont->encoding_index = index;
616
223k
    if (r_type(pfe) == t_array && r_size(pfe) <= 256) {
617
        /* Look for an encoding that's "close". */
618
223k
        uint esize = r_size(pfe);
619
223k
        int near_index = -1;
620
223k
        uint best = esize / 3;  /* must match at least this many */
621
223k
        gs_const_string fstrs[256];
622
223k
        int i;
623
624
        /* Get the string names of the glyphs in the font's Encoding. */
625
57.4M
        for (i = 0; i < esize; ++i) {
626
57.2M
            ref fchar;
627
628
57.2M
            if (array_get(pfont->memory, pfe, (long)i, &fchar) < 0 ||
629
57.2M
                !r_has_type(&fchar, t_name)
630
57.2M
                )
631
15.1k
                fstrs[i].data = 0, fstrs[i].size = 0;
632
57.2M
            else {
633
57.2M
                ref nsref;
634
635
57.2M
                name_string_ref(pfont->memory, &fchar, &nsref);
636
57.2M
                fstrs[i].data = nsref.value.const_bytes;
637
57.2M
                fstrs[i].size = r_size(&nsref);
638
57.2M
            }
639
57.2M
        }
640
        /* Compare them against the known encodings. */
641
229k
        for (index = 0; index < NUM_KNOWN_REAL_ENCODINGS; ++index) {
642
228k
            uint match = esize;
643
644
58.1M
            for (i = esize; --i >= 0;) {
645
57.9M
                gs_const_string rstr;
646
647
57.9M
                gs_c_glyph_name(gs_c_known_encode((gs_char)i, index), &rstr);
648
57.9M
                if (rstr.size == fstrs[i].size &&
649
57.2M
                    !memcmp(rstr.data, fstrs[i].data, rstr.size)
650
57.9M
                    )
651
57.2M
                    continue;
652
721k
                if (--match <= best)
653
4.60k
                    break;
654
721k
            }
655
228k
            if (match > best) {
656
223k
                best = match;
657
223k
                near_index = index;
658
                /* If we have a perfect match, stop now. */
659
223k
                if (best == esize)
660
222k
                    break;
661
223k
            }
662
228k
        }
663
223k
        index = near_index;
664
223k
        if (best == esize)
665
222k
            pfont->encoding_index = index;
666
223k
    }
667
223k
    pfont->nearest_encoding_index = index;
668
223k
}
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
223k
{
674
223k
    ref *pmatrix, *pfontname, *pfontstyle, *porigfont, *pfontinfo;
675
676
223k
    if (dict_find_string(op, "FontMatrix", &pmatrix) <= 0 ||
677
223k
        read_matrix(mem, pmatrix, pmat) < 0
678
223k
        )
679
8
        return_error(gs_error_invalidfont);
680
223k
    if (dict_find_string(op, "OrigFont", &porigfont) <= 0)
681
1
        porigfont = NULL;
682
223k
    if (porigfont != NULL && !r_has_type(porigfont, t_dictionary))
683
0
        return_error(gs_error_typecheck);
684
685
223k
    if (pomat!= NULL) {
686
223k
        if (porigfont == NULL ||
687
223k
            dict_find_string(porigfont, "FontMatrix", &pmatrix) <= 0 ||
688
223k
            read_matrix(mem, pmatrix, pomat) < 0
689
223k
            )
690
1
            memset(pomat, 0, sizeof(*pomat));
691
223k
    }
692
    /* Use the FontInfo/OrigFontName key preferrentially (created by MS PSCRIPT driver) */
693
223k
    if ((dict_find_string((porigfont != NULL ? porigfont : op), "FontInfo", &pfontinfo) > 0) &&
694
71.7k
        r_has_type(pfontinfo, t_dictionary) &&
695
71.7k
        (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 = pfontname->value.const_bytes;
699
0
            const byte *tmpStr2 = pfontstyle->value.const_bytes;
700
0
            int fssize1 = r_size(pfontname), fssize2 = r_size(pfontstyle), fssize = fssize1 + fssize2 + 1;
701
0
            byte *sfname = gs_alloc_string(mem, fssize, "sub_font_params");
702
703
0
            if (sfname == NULL)
704
0
                return_error(gs_error_VMerror);
705
0
            memcpy(sfname, tmpStr1, fssize1);
706
0
            sfname[fssize1]=',' ;
707
0
            memcpy(sfname + fssize1 + 1, tmpStr2, fssize2);
708
0
            make_string(pfname, a_readonly, fssize, sfname);
709
0
        } else
710
0
            get_font_name(mem, pfname, pfontname);
711
223k
    } else if (dict_find_string((porigfont != NULL ? porigfont : op), ".Alias", &pfontname) > 0) {
712
        /* If we emulate the font, we want the requested name rather than a substitute. */
713
60.9k
        get_font_name(mem, pfname, pfontname);
714
162k
    } else if (dict_find_string((porigfont != NULL ? porigfont : op), "FontName", &pfontname) > 0) {
715
162k
        get_font_name(mem, pfname, pfontname);
716
162k
    } else
717
638
        make_empty_string(pfname, a_readonly);
718
223k
    return 0;
719
223k
}
720
721
/* Do the common work for building a font of any FontType. */
722
/* The caller guarantees that *op is a dictionary. */
723
/* op[-1] must be the key under which the font is being registered */
724
/* in FontDirectory, normally a name or string. */
725
/* Return 0 for a new font, 1 for a font made by makefont or scalefont, */
726
/* or a negative error code. */
727
int
728
build_gs_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font ** ppfont, font_type ftype,
729
              gs_memory_type_ptr_t pstype, const build_proc_refs * pbuild,
730
              build_font_options_t options)
731
224k
{
732
224k
    ref kname;      /* t_string */
733
224k
    ref *pftype;
734
224k
    ref *pencoding = 0;
735
224k
    bool bitmapwidths;
736
224k
    int exactsize, inbetweensize, transformedchar;
737
224k
    int wmode;
738
224k
    int code;
739
224k
    gs_font *pfont;
740
224k
    ref *pfid;
741
224k
    ref *aop = dict_access_ref(op);
742
224k
    bool cpsi_mode = gs_currentcpsimode(imemory);
743
744
224k
    get_font_name(imemory, &kname, op - 1);
745
224k
    if (dict_find_string(op, "FontType", &pftype) <= 0 ||
746
224k
        !r_has_type(pftype, t_integer) ||
747
224k
        pftype->value.intval != (int)ftype
748
224k
        )
749
0
        return_error(gs_error_invalidfont);
750
224k
    if (dict_find_string(op, "Encoding", &pencoding) <= 0) {
751
4
        if (!(options & bf_Encoding_optional))
752
3
            return_error(gs_error_invalidfont);
753
1
        pencoding = 0;
754
224k
    } else {
755
224k
        if (!r_is_array(pencoding))
756
0
            return_error(gs_error_invalidfont);
757
224k
    }
758
224k
    if (pencoding) {   /* observed Adobe behavior */
759
224k
        int count = r_size(pencoding);
760
224k
        int type = ftype ? t_name : t_integer;
761
224k
        bool fixit = false;
762
763
58.8M
        while (count--) {
764
58.6M
           ref r;
765
58.6M
           if ((code = array_get(imemory, pencoding, count, &r)) < 0 ||
766
58.6M
             !(r_has_type(&r, type) || r_has_type(&r, t_null))) {
767
0
               if (!cpsi_mode && ftype == ft_user_defined) {
768
0
                   if (code < 0 || r_has_type(&r, t_null)) {
769
0
                       return_error(gs_error_typecheck);
770
0
                   }
771
0
                   fixit = true;
772
0
                   break;
773
0
               }
774
0
               else {
775
0
                   return_error(gs_error_typecheck);
776
0
               }
777
0
           }
778
58.6M
        }
779
780
        /* For at least Type 3 fonts, Adobe Distiller will "fix" an Encoding array, as in, for example
781
         * Bug 692681 where the arrays contain integers rather than names. Once the font is instantiated
782
         * the integers have been converted to names.
783
         * It is preferable to to this manipulation here, rather than in Postscript, because we are less
784
         * restricted by read-only attributes and VM save levels.
785
         */
786
224k
        if (fixit) {
787
0
            ref penc;
788
0
            uint size = 0;
789
0
            char buf[32], *bptr;
790
0
            avm_space curglob = ialloc_space(idmemory);
791
0
            avm_space useglob = r_is_local(pencoding) ? avm_local : avm_global;
792
793
0
            ialloc_set_space(idmemory, useglob);
794
795
0
            count = r_size(pencoding);
796
0
            if ((code = ialloc_ref_array(&penc, (r_type_attrs(pencoding) & a_readonly), count, "build_gs_font")) < 0)
797
0
                 return code;
798
799
0
            while (count--) {
800
0
               ref r;
801
0
               if (array_get(imemory, pencoding, count, &r) < 0){
802
0
                   return_error(gs_error_typecheck);
803
0
               }
804
               /* For type 3, we know the Encoding entries must be names */
805
0
               if (r_has_type(&r, t_name)){
806
0
                   ref_assign(&(penc.value.refs[count]), &r);
807
0
               }
808
0
               else {
809
810
0
                   if ((code = obj_cvs(imemory, &r, (byte *)buf, 32, &size, (const byte **)(&bptr))) < 0) {
811
0
                       return(code);
812
0
                   }
813
0
                   if ((code = name_ref(imemory, (const byte *)bptr, size, &r, true)) < 0)
814
0
                        return code;
815
0
                   ref_assign(&(penc.value.refs[count]), &r);
816
0
               }
817
0
            }
818
819
0
            if ((code = dict_put_string(osp, "Encoding", &penc, NULL)) < 0)
820
0
               return code;
821
0
            ialloc_set_space(idmemory, curglob);
822
0
        }
823
224k
    }
824
224k
    if ((code = dict_int_param(op, "WMode", 0, 1, 0, &wmode)) < 0 ||
825
224k
        (code = dict_bool_param(op, "BitmapWidths", false, &bitmapwidths)) < 0 ||
826
224k
        (code = dict_int_param(op, "ExactSize", 0, 2, fbit_use_bitmaps, &exactsize)) < 0 ||
827
224k
        (code = dict_int_param(op, "InBetweenSize", 0, 2, fbit_use_outlines, &inbetweensize)) < 0 ||
828
224k
        (code = dict_int_param(op, "TransformedChar", 0, 2, fbit_use_outlines, &transformedchar)) < 0
829
224k
        )
830
0
        return code;
831
224k
    code = dict_find_string(op, "FID", &pfid);
832
224k
    if (code > 0 && r_has_type(pfid, t_fontID)) { /* silently ignore invalid FID per CET 13-05.ps */
833
        /*
834
         * If this font has a FID entry already, it might be a scaled font
835
         * made by makefont or scalefont; in a Level 2 environment, it might
836
         * be an existing font being registered under a second name, or a
837
         * re-encoded font (which was invalid in Level 1, but dvips did it
838
         * anyway).
839
         */
840
675
        pfont = r_ptr(pfid, gs_font);
841
        /*
842
         * If the following condition is false this is a re-encoded font,
843
         * or some other questionable situation in which the FID
844
         * was preserved.  Pretend the FID wasn't there.
845
         */
846
675
        if (obj_eq(pfont->memory, pfont_dict(pfont), op)) {
847
675
            if (pfont->base == pfont) { /* original font */
848
675
                if (!level2_enabled)
849
0
                    return_error(gs_error_invalidfont);
850
675
                *ppfont = pfont;
851
675
                return 1;
852
675
            } else {   /* This was made by makefont or scalefont. */
853
                /* Just insert the new name. */
854
0
                gs_matrix mat;
855
0
                ref fname;      /* t_string */
856
857
0
                code = sub_font_params(imemory, op, &mat, NULL, &fname);
858
0
                if (code < 0)
859
0
                    return code;
860
0
                code = 1;
861
0
                copy_font_name(&pfont->font_name, &fname);
862
0
                goto set_name;
863
0
            }
864
675
        }
865
675
    }
866
    /* This is a new font. */
867
223k
    if (!r_has_attr(aop, a_write))
868
0
        return_error(gs_error_invalidaccess);
869
223k
    {
870
223k
        ref encoding;
871
872
        /*
873
         * Since add_FID may resize the dictionary and cause
874
         * pencoding to become invalid, save the Encoding.
875
         */
876
223k
        if (pencoding) {
877
223k
            encoding = *pencoding;
878
223k
            pencoding = &encoding;
879
223k
        }
880
223k
        code = build_gs_sub_font(i_ctx_p, op, &pfont, ftype, pstype,
881
223k
                                 pbuild, pencoding, op);
882
223k
        if (code < 0)
883
8
            return code;
884
223k
    }
885
223k
    pfont->BitmapWidths = bitmapwidths;
886
223k
    pfont->ExactSize = (fbit_type)exactsize;
887
223k
    pfont->InBetweenSize = (fbit_type)inbetweensize;
888
223k
    pfont->TransformedChar = (fbit_type)transformedchar;
889
223k
    pfont->WMode = wmode;
890
223k
    pfont->procs.font_info = zfont_info;
891
223k
    code = 0;
892
223k
set_name:
893
223k
    copy_font_name(&pfont->key_name, &kname);
894
223k
    *ppfont = pfont;
895
223k
    return code;
896
223k
}
897
898
/* Create a sub-font -- a font or an entry in the FDArray of a CIDFontType 0 */
899
/* font.  Default BitmapWidths, ExactSize, InBetweenSize, TransformedChar, */
900
/* and WMode; do not fill in key_name. */
901
/* The caller guarantees that *op is a dictionary. */
902
int
903
build_gs_sub_font(i_ctx_t *i_ctx_p, const ref *op, gs_font **ppfont,
904
                  font_type ftype, gs_memory_type_ptr_t pstype,
905
                  const build_proc_refs * pbuild, const ref *pencoding,
906
                  ref *fid_op)
907
223k
{
908
223k
    gs_matrix mat, omat;
909
223k
    ref fname;      /* t_string */
910
223k
    gs_font *pfont;
911
223k
    font_data *pdata;
912
    /*
913
     * Make sure that we allocate the font data
914
     * in the same VM as the font dictionary.
915
     */
916
223k
    uint space = ialloc_space(idmemory);
917
223k
    int code = sub_font_params(imemory, op, &mat, &omat, &fname);
918
919
223k
    if (code < 0)
920
8
        return code;
921
223k
    ialloc_set_space(idmemory, r_space(op));
922
223k
    pfont = gs_font_alloc(imemory, pstype, &gs_font_procs_default, NULL,
923
223k
                          "buildfont(font)");
924
223k
    pdata = ialloc_struct(font_data, &st_font_data,
925
223k
                          "buildfont(data)");
926
223k
    if (pfont == 0 || pdata == 0)
927
0
        code = gs_note_error(gs_error_VMerror);
928
223k
    else if (fid_op)
929
223k
        code = add_FID(i_ctx_p, fid_op, pfont, iimemory);
930
223k
    if (code < 0) {
931
0
        ifree_object(pdata, "buildfont(data)");
932
0
        ifree_object(pfont, "buildfont(font)");
933
0
        ialloc_set_space(idmemory, space);
934
0
        return code;
935
0
    }
936
223k
    refset_null((ref *) pdata, sizeof(font_data) / sizeof(ref));
937
223k
    ref_assign_new(&pdata->dict, op);
938
223k
    ref_assign_new(&pdata->BuildChar, &pbuild->BuildChar);
939
223k
    ref_assign_new(&pdata->BuildGlyph, &pbuild->BuildGlyph);
940
223k
    if (pencoding)
941
223k
        ref_assign_new(&pdata->Encoding, pencoding);
942
223k
    pfont->client_data = pdata;
943
223k
    pfont->FontType = ftype;
944
223k
    pfont->FontMatrix = mat;
945
223k
    pfont->orig_FontMatrix = omat;
946
223k
    pfont->BitmapWidths = false;
947
223k
    pfont->ExactSize = fbit_use_bitmaps;
948
223k
    pfont->InBetweenSize = fbit_use_outlines;
949
223k
    pfont->TransformedChar = fbit_use_outlines;
950
223k
    pfont->WMode = 0;
951
223k
    pfont->procs.encode_char = zfont_encode_char;
952
223k
    pfont->procs.glyph_name = zfont_glyph_name;
953
223k
    ialloc_set_space(idmemory, space);
954
223k
    copy_font_name(&pfont->font_name, &fname);
955
223k
    *ppfont = pfont;
956
223k
    return 0;
957
223k
}
958
959
/* Get the string corresponding to a font name. */
960
/* If the font name isn't a name or a string, return an empty string. */
961
void
962
get_font_name(const gs_memory_t *mem, ref * pfname, const ref * op)
963
447k
{
964
447k
    switch (r_type(op)) {
965
151k
        case t_string:
966
151k
            *pfname = *op;
967
151k
            break;
968
214k
        case t_name:
969
214k
            name_string_ref(mem, op, pfname);
970
214k
            break;
971
81.5k
        default:
972
            /* This is weird, but legal.... */
973
81.5k
            make_empty_string(pfname, a_readonly);
974
447k
    }
975
447k
}
976
977
/* Copy a font name into the gs_font structure. */
978
void
979
copy_font_name(gs_font_name * pfstr, const ref * pfname)
980
447k
{
981
447k
    uint size = r_size(pfname);
982
983
447k
    if (size > gs_font_name_max)
984
884
        size = gs_font_name_max;
985
447k
    memcpy(&pfstr->chars[0], pfname->value.const_bytes, size);
986
    /* Following is only for debugging printout. */
987
447k
    pfstr->chars[size] = 0;
988
447k
    pfstr->size = size;
989
447k
}
990
991
/* Finish building a font, by calling gs_definefont if needed. */
992
int
993
define_gs_font(i_ctx_t *i_ctx_p, gs_font * pfont)
994
224k
{
995
224k
    return (pfont->base == pfont && pfont->dir == 0 ?
996
            /* i.e., unregistered original font */
997
223k
            gs_definefont(ifont_dir, pfont) :
998
224k
            0);
999
224k
}