Coverage Report

Created: 2025-06-10 06:56

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