Coverage Report

Created: 2026-09-14 07:34

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
413k
{
44
413k
    ref_struct_clear_marks(cmem, vptr, offset_of(font_data, u.type42.mru_sfnts_index)/*size*/, pstype);
45
413k
}
46
static
47
ENUM_PTRS_BEGIN_PROC(font_data_enum_ptrs)
48
3.92M
{
49
3.92M
    return ref_struct_enum_ptrs(mem, vptr, offset_of(font_data, u.type42.mru_sfnts_index)/*size*/, index, pep, pstype, gcst);
50
3.92M
}
51
ENUM_PTRS_END_PROC
52
static
53
392k
RELOC_PTRS_BEGIN(font_data_reloc_ptrs)
54
392k
{
55
392k
    ref_struct_reloc_ptrs(vptr, offset_of(font_data, u.type42.mru_sfnts_index)/*size*/, pstype, gcst);
56
392k
}
57
392k
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
148k
{
64
148k
    os_ptr op = osp;
65
148k
    int code;
66
148k
    build_proc_refs build;
67
148k
    gs_font_base *pfont;
68
69
148k
    check_op(2);
70
148k
    check_type(*op, t_dictionary);
71
148k
    code = build_gs_font_procs(op, &build);
72
148k
    if (code < 0)
73
10
        return code;
74
148k
    code = build_gs_simple_font(i_ctx_p, op, &pfont, ft_user_defined,
75
148k
                                &st_gs_font_base, &build, bf_options_none);
76
148k
    if (code < 0)
77
11
        return code;
78
148k
    return define_gs_font(i_ctx_p, (gs_font *) pfont);
79
148k
}
80
81
/* Encode a character. */
82
gs_glyph
83
zfont_encode_char(gs_font *pfont, gs_char chr, gs_glyph_space_t gspace)
84
34.5M
{
85
34.5M
    font_data *pdata = pfont_data(pfont);
86
34.5M
    const ref *pencoding = &pdata->Encoding;
87
34.5M
    ulong index = chr;  /* work around VAX widening bug */
88
34.5M
    ref cname;
89
34.5M
    int code = array_get(pfont->memory, pencoding, (long)index, &cname);
90
91
34.5M
    if (code < 0 || !r_has_type(&cname, t_name))
92
1.05k
        return GS_NO_GLYPH;
93
34.5M
    if (pfont->FontType == ft_user_defined && r_type(&pdata->BuildGlyph) == t_null) {
94
27.8M
        ref nsref, tname;
95
96
27.8M
        name_string_ref(pfont->memory, &cname, &nsref);
97
27.8M
        if (r_size(&nsref) == 7 &&
98
6.31M
            !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.08M
            char buf[20];
109
6.08M
            int code;
110
111
6.08M
            if (gspace == GLYPH_SPACE_NOGEN)
112
0
                return GS_NO_GLYPH;
113
6.08M
            gs_snprintf(buf, sizeof(buf), "j%ld", chr); /* 'j' is arbutrary. */
114
6.08M
            code = name_ref(pfont->memory, (const byte *)buf, strlen(buf), &tname, 1);
115
6.08M
            if (code < 0) {
116
                /* Can't propagate the error due to interface limitation,
117
                   return with .notdef */
118
0
            } else
119
6.08M
                cname = tname;
120
6.08M
        }
121
27.8M
    }
122
34.5M
    return (gs_glyph)name_index(pfont->memory, &cname);
123
34.5M
}
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
102M
{
129
102M
    ref nref, sref;
130
131
102M
    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
102M
    } else {
141
102M
        name_index_ref(font->memory, index, &nref);
142
102M
        if (nref.value.pname == NULL)
143
0
            return_error(gs_error_unknownerror);
144
102M
    }
145
102M
    name_string_ref(font->memory, &nref, &sref);
146
102M
    pstr->data = sref.value.const_bytes;
147
102M
    pstr->size = r_size(&sref);
148
102M
    return 0;
149
102M
}
150
151
void get_zfont_glyph_name( int (**proc)(gs_font *font, gs_glyph glyph, gs_const_string *pstr) )
152
83.0k
{
153
83.0k
    *proc = zfont_glyph_name;
154
83.0k
}
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.5k
{
159
35.5k
    ref *v, n;
160
35.5k
    uchar *unicode_return = (uchar *)u;
161
162
35.5k
    if (glyph == GS_NO_GLYPH)
163
0
        return 0;
164
165
35.5k
    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.5k
        name_index_ref(mem, glyph, &n);
198
35.5k
     if (dict_find(map, &n, &v) > 0) {
199
35.0k
        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.0k
        if (r_type(v) == t_integer) {
208
35.0k
            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.0k
            } else {
217
35.0k
                if (length < 2)
218
17.5k
                    return 2;
219
17.5k
                unicode_return[0] = v->value.intval >> 8;
220
17.5k
                unicode_return[1] = v->value.intval & 0xFF;
221
17.5k
                return 2;
222
35.0k
            }
223
35.0k
        }
224
35.0k
    }
225
532
    return 0; /* Absent in the map. */
226
35.5k
}
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.1k
{
232
69.1k
    font_data *pdata = pfont_data(font);
233
69.1k
    const ref *UnicodeDecoding;
234
69.1k
    uchar *unicode_return = (uchar *)u;
235
236
69.1k
    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.1k
    if (glyph <= GS_MIN_CID_GLYPH && glyph != GS_NO_GLYPH) {
289
69.1k
        UnicodeDecoding = zfont_get_to_unicode_map(font->dir);
290
69.1k
        if (UnicodeDecoding != NULL && r_type(UnicodeDecoding) == t_dictionary)
291
35.5k
            return gs_font_map_glyph_by_dict(font->memory, UnicodeDecoding, glyph, u, length);
292
69.1k
    }
293
33.6k
    return 0; /* No map. */
294
69.1k
}
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
129k
{
311
129k
    int code;
312
313
129k
    if (!bcstr)
314
129k
        make_null(&pbuild->BuildChar);
315
129k
    else {
316
129k
        if ((code = name_ref(mem, (const byte *)bcstr,
317
129k
                             strlen(bcstr), &pbuild->BuildChar, 0)) < 0)
318
0
            return code;
319
129k
        r_set_attrs(&pbuild->BuildChar, a_executable);
320
129k
    }
321
129k
    if (!bgstr)
322
129k
        make_null(&pbuild->BuildGlyph);
323
129k
    else {
324
129k
        if ((code = name_ref(mem, (const byte *)bgstr,
325
129k
                             strlen(bgstr), &pbuild->BuildGlyph, 0)) < 0)
326
0
            return code;
327
129k
        r_set_attrs(&pbuild->BuildGlyph, a_executable);
328
129k
    }
329
129k
    return 0;
330
129k
}
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
148k
{
336
148k
    int ccode, gcode;
337
148k
    ref *pBuildChar;
338
148k
    ref *pBuildGlyph;
339
340
148k
    check_type(*op, t_dictionary);
341
148k
    ccode = dict_find_string(op, "BuildChar", &pBuildChar);
342
148k
    gcode = dict_find_string(op, "BuildGlyph", &pBuildGlyph);
343
148k
    if (ccode <= 0) {
344
16
        if (gcode <= 0)
345
8
            return_error(gs_error_invalidfont);
346
8
        make_null(&pbuild->BuildChar);
347
148k
    } else {
348
148k
        check_proc(*pBuildChar);
349
148k
        pbuild->BuildChar = *pBuildChar;
350
148k
    }
351
148k
    if (gcode <= 0)
352
148k
        make_null(&pbuild->BuildGlyph);
353
12
    else {
354
12
        check_proc(*pBuildGlyph);
355
12
        pbuild->BuildGlyph = *pBuildGlyph;
356
12
    }
357
148k
    return 0;
358
148k
}
359
360
static int font_with_same_UID_and_another_metrics(const gs_font *pfont0, const gs_font *pfont1)
361
62
{
362
62
    const gs_font_base *pbfont0 = (const gs_font_base *)pfont0;
363
62
    const gs_font_base *pbfont1 = (const gs_font_base *)pfont1;
364
365
62
    if (uid_equal(&pbfont0->UID, &pbfont1->UID)) {
366
62
        const ref *pfdict0 = &pfont_data(gs_font_parent(pbfont0))->dict;
367
62
        const ref *pfdict1 = &pfont_data(gs_font_parent(pbfont1))->dict;
368
62
        ref *pmdict0, *pmdict1;
369
370
62
        if (pbfont0->WMode || dict_find_string(pfdict0, "Metrics", &pmdict0) <= 0)
371
62
            pmdict0 = NULL;
372
62
        if (pbfont1->WMode || dict_find_string(pfdict1, "Metrics", &pmdict1) <= 0)
373
62
            pmdict1 = NULL;
374
62
        if (!pmdict0 != !pmdict1)
375
0
            return 1;
376
62
        if (pmdict0 != NULL && !obj_eq(pfont0->memory, pmdict0, pmdict1))
377
0
            return 1;
378
62
        if (!pbfont0->WMode || dict_find_string(pfdict0, "Metrics2", &pmdict0) <= 0)
379
62
            pmdict0 = NULL;
380
62
        if (!pbfont0->WMode || dict_find_string(pfdict1, "Metrics2", &pmdict1) <= 0)
381
62
            pmdict1 = NULL;
382
62
        if (!pmdict0 != !pmdict1)
383
0
            return 1;
384
62
        if (pmdict0 != NULL && !obj_eq(pfont0->memory, pmdict0, pmdict1))
385
0
            return 1;
386
62
    }
387
62
    return 0;
388
62
}
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
64.5k
{
399
64.5k
    ref *pcharstrings = 0;
400
64.5k
    ref CharStrings;
401
64.5k
    gs_font_base *pfont;
402
64.5k
    font_data *pdata;
403
64.5k
    int code;
404
405
64.5k
    if (dict_find_string(op, "CharStrings", &pcharstrings) <= 0) {
406
0
        if (!(options & bf_CharStrings_optional))
407
0
            return_error(gs_error_invalidfont);
408
64.5k
    } else {
409
64.5k
        ref *ignore;
410
411
64.5k
        if (!r_has_type(pcharstrings, t_dictionary))
412
0
            return_error(gs_error_invalidfont);
413
64.5k
        if ((options & bf_notdef_required) != 0 &&
414
64.5k
            dict_find_string(pcharstrings, ".notdef", &ignore) <= 0
415
64.5k
            )
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
64.5k
        CharStrings = *pcharstrings;
422
64.5k
    }
423
64.5k
    code = build_gs_outline_font(i_ctx_p, op, ppfont, ftype, pstype, pbuild,
424
64.5k
                                 options, build_gs_simple_font);
425
64.5k
    if (code != 0)
426
28
        return code;
427
64.5k
    pfont = *ppfont;
428
64.5k
    pdata = pfont_data(pfont);
429
64.5k
    if (pcharstrings)
430
64.5k
        ref_assign(&pdata->CharStrings, &CharStrings);
431
0
    else
432
64.5k
        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
64.5k
    if (uid_is_valid(&pfont->UID) &&
436
115
        !dict_check_uid_param(op, &pfont->UID)
437
64.5k
        )
438
0
        uid_set_invalid(&pfont->UID);
439
64.5k
    if (uid_is_valid(&pfont->UID)) {
440
115
        const gs_font *pfont0 = (const gs_font *)pfont;
441
442
115
        code = gs_font_find_similar(ifont_dir, &pfont0,
443
115
                       font_with_same_UID_and_another_metrics);
444
115
        if (code < 0)
445
0
            return code; /* Must not happen. */
446
115
        if (code)
447
0
            uid_set_invalid(&pfont->UID);
448
115
    }
449
64.5k
    return 0;
450
64.5k
}
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
64.5k
{
510
64.5k
    int painttype;
511
64.5k
    float strokewidth;
512
64.5k
    gs_font_base *pfont;
513
64.5k
    int code = dict_int_param(op, "PaintType", 0, 3, 0, &painttype);
514
515
64.5k
    if (code < 0)
516
0
        return code;
517
64.5k
    code = dict_float_param(op, "StrokeWidth", 0.0, &strokewidth);
518
64.5k
    if (code < 0)
519
0
        return code;
520
64.5k
    code = build_base_font(i_ctx_p, op, ppfont, ftype, pstype, pbuild,
521
64.5k
                           options);
522
64.5k
    if (code != 0)
523
28
        return code;
524
64.5k
    pfont = *ppfont;
525
64.5k
    pfont->PaintType = painttype;
526
64.5k
    pfont->StrokeWidth = strokewidth;
527
64.5k
    return 0;
528
64.5k
}
529
530
void
531
get_GlyphNames2Unicode(i_ctx_t *i_ctx_p, gs_font *pfont, ref *pdref)
532
212k
{
533
212k
    ref *pfontinfo = NULL, *g2u = NULL;
534
212k
    font_data *pdata;
535
536
212k
    if (dict_find_string(pdref, "FontInfo", &pfontinfo) <= 0 ||
537
64.5k
            !r_has_type(pfontinfo, t_dictionary) ||
538
64.5k
            dict_find_string(pfontinfo, "GlyphNames2Unicode", &g2u) <= 0 ||
539
0
            !r_has_type(pfontinfo, t_dictionary))
540
212k
        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
212k
{
557
212k
    double bbox[4];
558
212k
    gs_uid uid;
559
212k
    int code;
560
212k
    gs_font_base *pfont;
561
212k
    uint space = ialloc_space(idmemory);
562
563
212k
    code = font_bbox_param(imemory, op, bbox);
564
212k
    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
212k
    ialloc_set_space(idmemory, r_space(op));
572
212k
    code = dict_uid_param(op, &uid, 0, imemory, i_ctx_p);
573
212k
    ialloc_set_space(idmemory, space);
574
212k
    if (code < 0)
575
0
        return code;
576
212k
    if ((options & bf_UniqueID_ignored) && uid_is_UniqueID(&uid))
577
0
        uid_set_invalid(&uid);
578
212k
    code = build_gs_font(i_ctx_p, op, (gs_font **) ppfont, ftype, pstype,
579
212k
                         pbuild, options);
580
212k
    if (code != 0)    /* invalid or scaled font */
581
621
        return code;
582
212k
    pfont = *ppfont;
583
212k
    pfont->procs.init_fstack = gs_default_init_fstack;
584
212k
    pfont->procs.define_font = gs_no_define_font;
585
212k
    pfont->procs.decode_glyph = gs_font_map_glyph_to_unicode;
586
212k
    pfont->procs.make_font = zbase_make_font;
587
212k
    pfont->procs.next_char_glyph = gs_default_next_char_glyph;
588
212k
    pfont->FAPI = 0;
589
212k
    pfont->FAPI_font_data = 0;
590
212k
    init_gs_simple_font(pfont, bbox, &uid);
591
212k
    lookup_gs_simple_font_encoding(pfont);
592
212k
    get_GlyphNames2Unicode(i_ctx_p, (gs_font *)pfont, op);
593
212k
    return 0;
594
212k
}
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
212k
{
601
212k
    pfont->FontBBox.p.x = bbox[0];
602
212k
    pfont->FontBBox.p.y = bbox[1];
603
212k
    pfont->FontBBox.q.x = bbox[2];
604
212k
    pfont->FontBBox.q.y = bbox[3];
605
212k
    pfont->UID = *puid;
606
212k
}
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
212k
{
612
212k
    const ref *pfe = &pfont_data(pfont)->Encoding;
613
212k
    int index = -1;
614
615
212k
    pfont->encoding_index = index;
616
212k
    if (r_type(pfe) == t_array && r_size(pfe) <= 256) {
617
        /* Look for an encoding that's "close". */
618
212k
        uint esize = r_size(pfe);
619
212k
        int near_index = -1;
620
212k
        uint best = esize / 3;  /* must match at least this many */
621
212k
        gs_const_string fstrs[256];
622
212k
        int i;
623
624
        /* Get the string names of the glyphs in the font's Encoding. */
625
54.5M
        for (i = 0; i < esize; ++i) {
626
54.3M
            ref fchar;
627
628
54.3M
            if (array_get(pfont->memory, pfe, (long)i, &fchar) < 0 ||
629
54.3M
                !r_has_type(&fchar, t_name)
630
54.3M
                )
631
15.8k
                fstrs[i].data = 0, fstrs[i].size = 0;
632
54.3M
            else {
633
54.3M
                ref nsref;
634
635
54.3M
                name_string_ref(pfont->memory, &fchar, &nsref);
636
54.3M
                fstrs[i].data = nsref.value.const_bytes;
637
54.3M
                fstrs[i].size = r_size(&nsref);
638
54.3M
            }
639
54.3M
        }
640
        /* Compare them against the known encodings. */
641
216k
        for (index = 0; index < NUM_KNOWN_REAL_ENCODINGS; ++index) {
642
216k
            uint match = esize;
643
644
55.1M
            for (i = esize; --i >= 0;) {
645
54.9M
                gs_const_string rstr;
646
647
54.9M
                gs_c_glyph_name(gs_c_known_encode((gs_char)i, index), &rstr);
648
54.9M
                if (rstr.size == fstrs[i].size &&
649
54.3M
                    !memcmp(rstr.data, fstrs[i].data, rstr.size)
650
54.9M
                    )
651
54.3M
                    continue;
652
596k
                if (--match <= best)
653
3.81k
                    break;
654
596k
            }
655
216k
            if (match > best) {
656
212k
                best = match;
657
212k
                near_index = index;
658
                /* If we have a perfect match, stop now. */
659
212k
                if (best == esize)
660
211k
                    break;
661
212k
            }
662
216k
        }
663
212k
        index = near_index;
664
212k
        if (best == esize)
665
211k
            pfont->encoding_index = index;
666
212k
    }
667
212k
    pfont->nearest_encoding_index = index;
668
212k
}
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
212k
{
674
212k
    ref *pmatrix, *pfontname, *pfontstyle, *porigfont, *pfontinfo;
675
676
212k
    if (dict_find_string(op, "FontMatrix", &pmatrix) <= 0 ||
677
212k
        read_matrix(mem, pmatrix, pmat) < 0
678
212k
        )
679
7
        return_error(gs_error_invalidfont);
680
212k
    if (dict_find_string(op, "OrigFont", &porigfont) <= 0)
681
1
        porigfont = NULL;
682
212k
    if (porigfont != NULL && !r_has_type(porigfont, t_dictionary))
683
0
        return_error(gs_error_typecheck);
684
685
212k
    if (pomat!= NULL) {
686
212k
        if (porigfont == NULL ||
687
212k
            dict_find_string(porigfont, "FontMatrix", &pmatrix) <= 0 ||
688
212k
            read_matrix(mem, pmatrix, pomat) < 0
689
212k
            )
690
1
            memset(pomat, 0, sizeof(*pomat));
691
212k
    }
692
    /* Use the FontInfo/OrigFontName key preferrentially (created by MS PSCRIPT driver) */
693
212k
    if ((dict_find_string((porigfont != NULL ? porigfont : op), "FontInfo", &pfontinfo) > 0) &&
694
64.5k
        r_has_type(pfontinfo, t_dictionary) &&
695
64.5k
        (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
212k
    } 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
54.8k
        get_font_name(mem, pfname, pfontname);
735
157k
    } else if (dict_find_string((porigfont != NULL ? porigfont : op), "FontName", &pfontname) > 0) {
736
156k
        get_font_name(mem, pfname, pfontname);
737
156k
    } else
738
523
        make_empty_string(pfname, a_readonly);
739
212k
    return 0;
740
212k
}
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
212k
{
753
212k
    ref kname;      /* t_string */
754
212k
    ref *pftype;
755
212k
    ref *pencoding = 0;
756
212k
    bool bitmapwidths;
757
212k
    int exactsize, inbetweensize, transformedchar;
758
212k
    int wmode;
759
212k
    int code;
760
212k
    gs_font *pfont;
761
212k
    ref *pfid;
762
212k
    ref *aop = dict_access_ref(op);
763
212k
    bool cpsi_mode = gs_currentcpsimode(imemory);
764
765
212k
    get_font_name(imemory, &kname, op - 1);
766
212k
    if (dict_find_string(op, "FontType", &pftype) <= 0 ||
767
212k
        !r_has_type(pftype, t_integer) ||
768
212k
        pftype->value.intval != (int)ftype
769
212k
        )
770
0
        return_error(gs_error_invalidfont);
771
212k
    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
212k
    } else {
776
212k
        if (!r_is_array(pencoding))
777
0
            return_error(gs_error_invalidfont);
778
212k
    }
779
212k
    if (pencoding) {   /* observed Adobe behavior */
780
212k
        int count = r_size(pencoding);
781
212k
        int type = ftype ? t_name : t_integer;
782
212k
        bool fixit = false;
783
784
55.5M
        while (count--) {
785
55.3M
           ref r;
786
55.3M
           if ((code = array_get(imemory, pencoding, count, &r)) < 0 ||
787
55.3M
             !(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
55.3M
        }
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
212k
        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
212k
    }
845
212k
    if ((code = dict_int_param(op, "WMode", 0, 1, 0, &wmode)) < 0 ||
846
212k
        (code = dict_bool_param(op, "BitmapWidths", false, &bitmapwidths)) < 0 ||
847
212k
        (code = dict_int_param(op, "ExactSize", 0, 2, fbit_use_bitmaps, &exactsize)) < 0 ||
848
212k
        (code = dict_int_param(op, "InBetweenSize", 0, 2, fbit_use_outlines, &inbetweensize)) < 0 ||
849
212k
        (code = dict_int_param(op, "TransformedChar", 0, 2, fbit_use_outlines, &transformedchar)) < 0
850
212k
        )
851
0
        return code;
852
212k
    code = dict_find_string(op, "FID", &pfid);
853
212k
    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) && pfont->FontType == ftype) {
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
212k
    if (!r_has_attr(aop, a_write))
889
0
        return_error(gs_error_invalidaccess);
890
212k
    {
891
212k
        ref encoding;
892
893
        /*
894
         * Since add_FID may resize the dictionary and cause
895
         * pencoding to become invalid, save the Encoding.
896
         */
897
212k
        if (pencoding) {
898
212k
            encoding = *pencoding;
899
212k
            pencoding = &encoding;
900
212k
        }
901
212k
        code = build_gs_sub_font(i_ctx_p, op, &pfont, ftype, pstype,
902
212k
                                 pbuild, pencoding, op);
903
212k
        if (code < 0)
904
7
            return code;
905
212k
    }
906
212k
    pfont->BitmapWidths = bitmapwidths;
907
212k
    pfont->ExactSize = (fbit_type)exactsize;
908
212k
    pfont->InBetweenSize = (fbit_type)inbetweensize;
909
212k
    pfont->TransformedChar = (fbit_type)transformedchar;
910
212k
    pfont->WMode = wmode;
911
212k
    pfont->procs.font_info = zfont_info;
912
212k
    code = 0;
913
212k
set_name:
914
212k
    copy_font_name(&pfont->key_name, &kname);
915
212k
    *ppfont = pfont;
916
212k
    return code;
917
212k
}
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
212k
{
929
212k
    gs_matrix mat, omat;
930
212k
    ref fname;      /* t_string */
931
212k
    gs_font *pfont;
932
212k
    font_data *pdata;
933
    /*
934
     * Make sure that we allocate the font data
935
     * in the same VM as the font dictionary.
936
     */
937
212k
    uint space = ialloc_space(idmemory);
938
212k
    int code = sub_font_params(imemory, op, &mat, &omat, &fname);
939
940
212k
    if (code < 0)
941
7
        return code;
942
212k
    ialloc_set_space(idmemory, r_space(op));
943
212k
    pfont = gs_font_alloc(imemory, pstype, &gs_font_procs_default, NULL,
944
212k
                          "buildfont(font)");
945
212k
    pdata = ialloc_struct(font_data, &st_font_data,
946
212k
                          "buildfont(data)");
947
212k
    if (pfont == 0 || pdata == 0)
948
0
        code = gs_note_error(gs_error_VMerror);
949
212k
    else if (fid_op)
950
212k
        code = add_FID(i_ctx_p, fid_op, pfont, iimemory);
951
212k
    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
212k
    refset_null((ref *) pdata, sizeof(font_data) / sizeof(ref));
958
212k
    ref_assign_new(&pdata->dict, op);
959
212k
    ref_assign_new(&pdata->BuildChar, &pbuild->BuildChar);
960
212k
    ref_assign_new(&pdata->BuildGlyph, &pbuild->BuildGlyph);
961
212k
    if (pencoding)
962
212k
        ref_assign_new(&pdata->Encoding, pencoding);
963
212k
    pfont->client_data = pdata;
964
212k
    pfont->FontType = ftype;
965
212k
    pfont->FontMatrix = mat;
966
212k
    pfont->orig_FontMatrix = omat;
967
212k
    pfont->BitmapWidths = false;
968
212k
    pfont->ExactSize = fbit_use_bitmaps;
969
212k
    pfont->InBetweenSize = fbit_use_outlines;
970
212k
    pfont->TransformedChar = fbit_use_outlines;
971
212k
    pfont->WMode = 0;
972
212k
    pfont->procs.encode_char = zfont_encode_char;
973
212k
    pfont->procs.glyph_name = zfont_glyph_name;
974
212k
    ialloc_set_space(idmemory, space);
975
212k
    copy_font_name(&pfont->font_name, &fname);
976
212k
    *ppfont = pfont;
977
212k
    return 0;
978
212k
}
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
424k
{
985
424k
    switch (r_type(op)) {
986
147k
        case t_string:
987
147k
            *pfname = *op;
988
147k
            break;
989
204k
        case t_name:
990
204k
            name_string_ref(mem, op, pfname);
991
204k
            break;
992
73.2k
        default:
993
            /* This is weird, but legal.... */
994
73.2k
            make_empty_string(pfname, a_readonly);
995
424k
    }
996
424k
}
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
424k
{
1002
424k
    uint size = r_size(pfname);
1003
1004
424k
    if (size > gs_font_name_max)
1005
768
        size = gs_font_name_max;
1006
424k
    memcpy(&pfstr->chars[0], pfname->value.const_bytes, size);
1007
    /* Following is only for debugging printout. */
1008
424k
    pfstr->chars[size] = 0;
1009
424k
    pfstr->size = size;
1010
424k
}
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
212k
{
1016
212k
    return (pfont->base == pfont && pfont->dir == 0 ?
1017
            /* i.e., unregistered original font */
1018
212k
            gs_definefont(ifont_dir, pfont) :
1019
212k
            0);
1020
212k
}