Coverage Report

Created: 2025-06-10 06:58

/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
40.6k
{
44
40.6k
    ref_struct_clear_marks(cmem, vptr, offset_of(font_data, u.type42.mru_sfnts_index)/*size*/, pstype);
45
40.6k
}
46
static
47
ENUM_PTRS_BEGIN_PROC(font_data_enum_ptrs)
48
393k
{
49
393k
    return ref_struct_enum_ptrs(mem, vptr, offset_of(font_data, u.type42.mru_sfnts_index)/*size*/, index, pep, pstype, gcst);
50
393k
}
51
ENUM_PTRS_END_PROC
52
static
53
39.3k
RELOC_PTRS_BEGIN(font_data_reloc_ptrs)
54
39.3k
{
55
39.3k
    ref_struct_reloc_ptrs(vptr, offset_of(font_data, u.type42.mru_sfnts_index)/*size*/, pstype, gcst);
56
39.3k
}
57
39.3k
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
10.3k
{
64
10.3k
    os_ptr op = osp;
65
10.3k
    int code;
66
10.3k
    build_proc_refs build;
67
10.3k
    gs_font_base *pfont;
68
69
10.3k
    check_op(2);
70
10.3k
    check_type(*op, t_dictionary);
71
10.3k
    code = build_gs_font_procs(op, &build);
72
10.3k
    if (code < 0)
73
1
        return code;
74
10.3k
    code = build_gs_simple_font(i_ctx_p, op, &pfont, ft_user_defined,
75
10.3k
                                &st_gs_font_base, &build, bf_options_none);
76
10.3k
    if (code < 0)
77
1
        return code;
78
10.3k
    return define_gs_font(i_ctx_p, (gs_font *) pfont);
79
10.3k
}
80
81
/* Encode a character. */
82
gs_glyph
83
zfont_encode_char(gs_font *pfont, gs_char chr, gs_glyph_space_t gspace)
84
38.2M
{
85
38.2M
    font_data *pdata = pfont_data(pfont);
86
38.2M
    const ref *pencoding = &pdata->Encoding;
87
38.2M
    ulong index = chr;  /* work around VAX widening bug */
88
38.2M
    ref cname;
89
38.2M
    int code = array_get(pfont->memory, pencoding, (long)index, &cname);
90
91
38.2M
    if (code < 0 || !r_has_type(&cname, t_name))
92
1.04k
        return GS_NO_GLYPH;
93
38.2M
    if (pfont->FontType == ft_user_defined && r_type(&pdata->BuildGlyph) == t_null) {
94
37.6M
        ref nsref, tname;
95
96
37.6M
        name_string_ref(pfont->memory, &cname, &nsref);
97
37.6M
        if (r_size(&nsref) == 7 &&
98
37.6M
            !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
5.68M
            char buf[20];
109
5.68M
            int code;
110
111
5.68M
            if (gspace == GLYPH_SPACE_NOGEN)
112
0
                return GS_NO_GLYPH;
113
5.68M
            gs_snprintf(buf, sizeof(buf), "j%ld", chr); /* 'j' is arbutrary. */
114
5.68M
            code = name_ref(pfont->memory, (const byte *)buf, strlen(buf), &tname, 1);
115
5.68M
            if (code < 0) {
116
                /* Can't propagate the error due to interface limitation,
117
                   return with .notdef */
118
0
            } else
119
5.68M
                cname = tname;
120
5.68M
        }
121
37.6M
    }
122
38.2M
    return (gs_glyph)name_index(pfont->memory, &cname);
123
38.2M
}
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
44.4M
{
129
44.4M
    ref nref, sref;
130
131
44.4M
    if (index >= GS_MIN_CID_GLYPH) { /* Fabricate a numeric name. */
132
487
        char cid_name[sizeof(gs_glyph) * 3 + 1];
133
487
        int code;
134
135
487
        gs_snprintf(cid_name, sizeof(cid_name), "%lu", (ulong) index);
136
487
        code = name_ref(font->memory, (const byte *)cid_name, strlen(cid_name),
137
487
                        &nref, 1);
138
487
        if (code < 0)
139
0
            return code;
140
44.4M
    } else {
141
44.4M
        name_index_ref(font->memory, index, &nref);
142
44.4M
        if (nref.value.pname == NULL)
143
0
            return_error(gs_error_unknownerror);
144
44.4M
    }
145
44.4M
    name_string_ref(font->memory, &nref, &sref);
146
44.4M
    pstr->data = sref.value.const_bytes;
147
44.4M
    pstr->size = r_size(&sref);
148
44.4M
    return 0;
149
44.4M
}
150
151
void get_zfont_glyph_name( int (**proc)(gs_font *font, gs_glyph glyph, gs_const_string *pstr) )
152
6.13k
{
153
6.13k
    *proc = zfont_glyph_name;
154
6.13k
}
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
10.5k
{
159
10.5k
    ref *v, n;
160
10.5k
    uchar *unicode_return = (uchar *)u;
161
10.5k
    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
10.5k
        name_index_ref(mem, glyph, &n);
194
10.5k
     if (dict_find(map, &n, &v) > 0) {
195
9.27k
        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
9.27k
        if (r_type(v) == t_integer) {
204
9.27k
            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
9.27k
            } else {
213
9.27k
                if (length < 2)
214
4.63k
                    return 2;
215
4.63k
                unicode_return[0] = v->value.intval >> 8;
216
4.63k
                unicode_return[1] = v->value.intval & 0xFF;
217
4.63k
                return 2;
218
9.27k
            }
219
9.27k
        }
220
9.27k
    }
221
1.31k
    return 0; /* Absent in the map. */
222
10.5k
}
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
10.5k
{
228
10.5k
    font_data *pdata = pfont_data(font);
229
10.5k
    const ref *UnicodeDecoding;
230
10.5k
    uchar *unicode_return = (uchar *)u;
231
232
10.5k
    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
10.5k
    if (glyph <= GS_MIN_CID_GLYPH && glyph != GS_NO_GLYPH) {
285
10.5k
        UnicodeDecoding = zfont_get_to_unicode_map(font->dir);
286
10.5k
        if (UnicodeDecoding != NULL && r_type(UnicodeDecoding) == t_dictionary)
287
10.5k
            return gs_font_map_glyph_by_dict(font->memory, UnicodeDecoding, glyph, u, length);
288
10.5k
    }
289
0
    return 0; /* No map. */
290
10.5k
}
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
33.3k
{
307
33.3k
    int code;
308
309
33.3k
    if (!bcstr)
310
33.3k
        make_null(&pbuild->BuildChar);
311
33.3k
    else {
312
33.3k
        if ((code = name_ref(mem, (const byte *)bcstr,
313
33.3k
                             strlen(bcstr), &pbuild->BuildChar, 0)) < 0)
314
0
            return code;
315
33.3k
        r_set_attrs(&pbuild->BuildChar, a_executable);
316
33.3k
    }
317
33.3k
    if (!bgstr)
318
33.3k
        make_null(&pbuild->BuildGlyph);
319
33.3k
    else {
320
33.3k
        if ((code = name_ref(mem, (const byte *)bgstr,
321
33.3k
                             strlen(bgstr), &pbuild->BuildGlyph, 0)) < 0)
322
0
            return code;
323
33.3k
        r_set_attrs(&pbuild->BuildGlyph, a_executable);
324
33.3k
    }
325
33.3k
    return 0;
326
33.3k
}
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
10.3k
{
332
10.3k
    int ccode, gcode;
333
10.3k
    ref *pBuildChar;
334
10.3k
    ref *pBuildGlyph;
335
336
10.3k
    check_type(*op, t_dictionary);
337
10.3k
    ccode = dict_find_string(op, "BuildChar", &pBuildChar);
338
10.3k
    gcode = dict_find_string(op, "BuildGlyph", &pBuildGlyph);
339
10.3k
    if (ccode <= 0) {
340
1
        if (gcode <= 0)
341
1
            return_error(gs_error_invalidfont);
342
0
        make_null(&pbuild->BuildChar);
343
10.3k
    } else {
344
10.3k
        check_proc(*pBuildChar);
345
10.3k
        pbuild->BuildChar = *pBuildChar;
346
10.3k
    }
347
10.3k
    if (gcode <= 0)
348
10.3k
        make_null(&pbuild->BuildGlyph);
349
0
    else {
350
0
        check_proc(*pBuildGlyph);
351
0
        pbuild->BuildGlyph = *pBuildGlyph;
352
0
    }
353
10.3k
    return 0;
354
10.3k
}
355
356
static int font_with_same_UID_and_another_metrics(const gs_font *pfont0, const gs_font *pfont1)
357
79
{
358
79
    const gs_font_base *pbfont0 = (const gs_font_base *)pfont0;
359
79
    const gs_font_base *pbfont1 = (const gs_font_base *)pfont1;
360
361
79
    if (uid_equal(&pbfont0->UID, &pbfont1->UID)) {
362
13
        const ref *pfdict0 = &pfont_data(gs_font_parent(pbfont0))->dict;
363
13
        const ref *pfdict1 = &pfont_data(gs_font_parent(pbfont1))->dict;
364
13
        ref *pmdict0, *pmdict1;
365
366
13
        if (pbfont0->WMode || dict_find_string(pfdict0, "Metrics", &pmdict0) <= 0)
367
13
            pmdict0 = NULL;
368
13
        if (pbfont1->WMode || dict_find_string(pfdict1, "Metrics", &pmdict1) <= 0)
369
13
            pmdict1 = NULL;
370
13
        if (!pmdict0 != !pmdict1)
371
0
            return 1;
372
13
        if (pmdict0 != NULL && !obj_eq(pfont0->memory, pmdict0, pmdict1))
373
0
            return 1;
374
13
        if (!pbfont0->WMode || dict_find_string(pfdict0, "Metrics2", &pmdict0) <= 0)
375
13
            pmdict0 = NULL;
376
13
        if (!pbfont0->WMode || dict_find_string(pfdict1, "Metrics2", &pmdict1) <= 0)
377
13
            pmdict1 = NULL;
378
13
        if (!pmdict0 != !pmdict1)
379
0
            return 1;
380
13
        if (pmdict0 != NULL && !obj_eq(pfont0->memory, pmdict0, pmdict1))
381
0
            return 1;
382
13
    }
383
79
    return 0;
384
79
}
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
16.6k
{
395
16.6k
    ref *pcharstrings = 0;
396
16.6k
    ref CharStrings;
397
16.6k
    gs_font_base *pfont;
398
16.6k
    font_data *pdata;
399
16.6k
    int code;
400
401
16.6k
    if (dict_find_string(op, "CharStrings", &pcharstrings) <= 0) {
402
0
        if (!(options & bf_CharStrings_optional))
403
0
            return_error(gs_error_invalidfont);
404
16.6k
    } else {
405
16.6k
        ref *ignore;
406
407
16.6k
        if (!r_has_type(pcharstrings, t_dictionary))
408
0
            return_error(gs_error_invalidfont);
409
16.6k
        if ((options & bf_notdef_required) != 0 &&
410
16.6k
            dict_find_string(pcharstrings, ".notdef", &ignore) <= 0
411
16.6k
            )
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
16.6k
        CharStrings = *pcharstrings;
418
16.6k
    }
419
16.6k
    code = build_gs_outline_font(i_ctx_p, op, ppfont, ftype, pstype, pbuild,
420
16.6k
                                 options, build_gs_simple_font);
421
16.6k
    if (code != 0)
422
0
        return code;
423
16.6k
    pfont = *ppfont;
424
16.6k
    pdata = pfont_data(pfont);
425
16.6k
    if (pcharstrings)
426
16.6k
        ref_assign(&pdata->CharStrings, &CharStrings);
427
0
    else
428
16.6k
        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
16.6k
    if (uid_is_valid(&pfont->UID) &&
432
16.6k
        !dict_check_uid_param(op, &pfont->UID)
433
16.6k
        )
434
0
        uid_set_invalid(&pfont->UID);
435
16.6k
    if (uid_is_valid(&pfont->UID)) {
436
20
        const gs_font *pfont0 = (const gs_font *)pfont;
437
438
20
        code = gs_font_find_similar(ifont_dir, &pfont0,
439
20
                       font_with_same_UID_and_another_metrics);
440
20
        if (code < 0)
441
0
            return code; /* Must not happen. */
442
20
        if (code)
443
0
            uid_set_invalid(&pfont->UID);
444
20
    }
445
16.6k
    return 0;
446
16.6k
}
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
16.6k
{
506
16.6k
    int painttype;
507
16.6k
    float strokewidth;
508
16.6k
    gs_font_base *pfont;
509
16.6k
    int code = dict_int_param(op, "PaintType", 0, 3, 0, &painttype);
510
511
16.6k
    if (code < 0)
512
0
        return code;
513
16.6k
    code = dict_float_param(op, "StrokeWidth", 0.0, &strokewidth);
514
16.6k
    if (code < 0)
515
0
        return code;
516
16.6k
    code = build_base_font(i_ctx_p, op, ppfont, ftype, pstype, pbuild,
517
16.6k
                           options);
518
16.6k
    if (code != 0)
519
0
        return code;
520
16.6k
    pfont = *ppfont;
521
16.6k
    pfont->PaintType = painttype;
522
16.6k
    pfont->StrokeWidth = strokewidth;
523
16.6k
    return 0;
524
16.6k
}
525
526
void
527
get_GlyphNames2Unicode(i_ctx_t *i_ctx_p, gs_font *pfont, ref *pdref)
528
26.9k
{
529
26.9k
    ref *pfontinfo = NULL, *g2u = NULL;
530
26.9k
    font_data *pdata;
531
532
26.9k
    if (dict_find_string(pdref, "FontInfo", &pfontinfo) <= 0 ||
533
26.9k
            !r_has_type(pfontinfo, t_dictionary) ||
534
26.9k
            dict_find_string(pfontinfo, "GlyphNames2Unicode", &g2u) <= 0 ||
535
26.9k
            !r_has_type(pfontinfo, t_dictionary))
536
26.9k
        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
26.9k
{
553
26.9k
    double bbox[4];
554
26.9k
    gs_uid uid;
555
26.9k
    int code;
556
26.9k
    gs_font_base *pfont;
557
26.9k
    uint space = ialloc_space(idmemory);
558
559
26.9k
    code = font_bbox_param(imemory, op, bbox);
560
26.9k
    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
26.9k
    ialloc_set_space(idmemory, r_space(op));
568
26.9k
    code = dict_uid_param(op, &uid, 0, imemory, i_ctx_p);
569
26.9k
    ialloc_set_space(idmemory, space);
570
26.9k
    if (code < 0)
571
0
        return code;
572
26.9k
    if ((options & bf_UniqueID_ignored) && uid_is_UniqueID(&uid))
573
0
        uid_set_invalid(&uid);
574
26.9k
    code = build_gs_font(i_ctx_p, op, (gs_font **) ppfont, ftype, pstype,
575
26.9k
                         pbuild, options);
576
26.9k
    if (code != 0)    /* invalid or scaled font */
577
1
        return code;
578
26.9k
    pfont = *ppfont;
579
26.9k
    pfont->procs.init_fstack = gs_default_init_fstack;
580
26.9k
    pfont->procs.define_font = gs_no_define_font;
581
26.9k
    pfont->procs.decode_glyph = gs_font_map_glyph_to_unicode;
582
26.9k
    pfont->procs.make_font = zbase_make_font;
583
26.9k
    pfont->procs.next_char_glyph = gs_default_next_char_glyph;
584
26.9k
    pfont->FAPI = 0;
585
26.9k
    pfont->FAPI_font_data = 0;
586
26.9k
    init_gs_simple_font(pfont, bbox, &uid);
587
26.9k
    lookup_gs_simple_font_encoding(pfont);
588
26.9k
    get_GlyphNames2Unicode(i_ctx_p, (gs_font *)pfont, op);
589
26.9k
    return 0;
590
26.9k
}
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
26.9k
{
597
26.9k
    pfont->FontBBox.p.x = bbox[0];
598
26.9k
    pfont->FontBBox.p.y = bbox[1];
599
26.9k
    pfont->FontBBox.q.x = bbox[2];
600
26.9k
    pfont->FontBBox.q.y = bbox[3];
601
26.9k
    pfont->UID = *puid;
602
26.9k
}
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
26.9k
{
608
26.9k
    const ref *pfe = &pfont_data(pfont)->Encoding;
609
26.9k
    int index = -1;
610
611
26.9k
    pfont->encoding_index = index;
612
26.9k
    if (r_type(pfe) == t_array && r_size(pfe) <= 256) {
613
        /* Look for an encoding that's "close". */
614
26.9k
        uint esize = r_size(pfe);
615
26.9k
        int near_index = -1;
616
26.9k
        uint best = esize / 3;  /* must match at least this many */
617
26.9k
        gs_const_string fstrs[256];
618
26.9k
        int i;
619
620
        /* Get the string names of the glyphs in the font's Encoding. */
621
6.93M
        for (i = 0; i < esize; ++i) {
622
6.90M
            ref fchar;
623
624
6.90M
            if (array_get(pfont->memory, pfe, (long)i, &fchar) < 0 ||
625
6.90M
                !r_has_type(&fchar, t_name)
626
6.90M
                )
627
482
                fstrs[i].data = 0, fstrs[i].size = 0;
628
6.90M
            else {
629
6.90M
                ref nsref;
630
631
6.90M
                name_string_ref(pfont->memory, &fchar, &nsref);
632
6.90M
                fstrs[i].data = nsref.value.const_bytes;
633
6.90M
                fstrs[i].size = r_size(&nsref);
634
6.90M
            }
635
6.90M
        }
636
        /* Compare them against the known encodings. */
637
27.2k
        for (index = 0; index < NUM_KNOWN_REAL_ENCODINGS; ++index) {
638
27.1k
            uint match = esize;
639
640
6.95M
            for (i = esize; --i >= 0;) {
641
6.93M
                gs_const_string rstr;
642
643
6.93M
                gs_c_glyph_name(gs_c_known_encode((gs_char)i, index), &rstr);
644
6.93M
                if (rstr.size == fstrs[i].size &&
645
6.93M
                    !memcmp(rstr.data, fstrs[i].data, rstr.size)
646
6.93M
                    )
647
6.90M
                    continue;
648
21.5k
                if (--match <= best)
649
188
                    break;
650
21.5k
            }
651
27.1k
            if (match > best) {
652
26.9k
                best = match;
653
26.9k
                near_index = index;
654
                /* If we have a perfect match, stop now. */
655
26.9k
                if (best == esize)
656
26.9k
                    break;
657
26.9k
            }
658
27.1k
        }
659
26.9k
        index = near_index;
660
26.9k
        if (best == esize)
661
26.9k
            pfont->encoding_index = index;
662
26.9k
    }
663
26.9k
    pfont->nearest_encoding_index = index;
664
26.9k
}
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
26.9k
{
670
26.9k
    ref *pmatrix, *pfontname, *pfontstyle, *porigfont, *pfontinfo;
671
672
26.9k
    if (dict_find_string(op, "FontMatrix", &pmatrix) <= 0 ||
673
26.9k
        read_matrix(mem, pmatrix, pmat) < 0
674
26.9k
        )
675
1
        return_error(gs_error_invalidfont);
676
26.9k
    if (dict_find_string(op, "OrigFont", &porigfont) <= 0)
677
0
        porigfont = NULL;
678
26.9k
    if (porigfont != NULL && !r_has_type(porigfont, t_dictionary))
679
0
        return_error(gs_error_typecheck);
680
681
26.9k
    if (pomat!= NULL) {
682
26.9k
        if (porigfont == NULL ||
683
26.9k
            dict_find_string(porigfont, "FontMatrix", &pmatrix) <= 0 ||
684
26.9k
            read_matrix(mem, pmatrix, pomat) < 0
685
26.9k
            )
686
0
            memset(pomat, 0, sizeof(*pomat));
687
26.9k
    }
688
    /* Use the FontInfo/OrigFontName key preferrentially (created by MS PSCRIPT driver) */
689
26.9k
    if ((dict_find_string((porigfont != NULL ? porigfont : op), "FontInfo", &pfontinfo) > 0) &&
690
26.9k
        r_has_type(pfontinfo, t_dictionary) &&
691
26.9k
        (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
26.9k
    } 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
15.6k
        get_font_name(mem, pfname, pfontname);
710
15.6k
    } else if (dict_find_string((porigfont != NULL ? porigfont : op), "FontName", &pfontname) > 0) {
711
11.3k
        get_font_name(mem, pfname, pfontname);
712
11.3k
    } else
713
11
        make_empty_string(pfname, a_readonly);
714
26.9k
    return 0;
715
26.9k
}
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
26.9k
{
728
26.9k
    ref kname;      /* t_string */
729
26.9k
    ref *pftype;
730
26.9k
    ref *pencoding = 0;
731
26.9k
    bool bitmapwidths;
732
26.9k
    int exactsize, inbetweensize, transformedchar;
733
26.9k
    int wmode;
734
26.9k
    int code;
735
26.9k
    gs_font *pfont;
736
26.9k
    ref *pfid;
737
26.9k
    ref *aop = dict_access_ref(op);
738
26.9k
    bool cpsi_mode = gs_currentcpsimode(imemory);
739
740
26.9k
    get_font_name(imemory, &kname, op - 1);
741
26.9k
    if (dict_find_string(op, "FontType", &pftype) <= 0 ||
742
26.9k
        !r_has_type(pftype, t_integer) ||
743
26.9k
        pftype->value.intval != (int)ftype
744
26.9k
        )
745
0
        return_error(gs_error_invalidfont);
746
26.9k
    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
26.9k
    } else {
751
26.9k
        if (!r_is_array(pencoding))
752
0
            return_error(gs_error_invalidfont);
753
26.9k
    }
754
26.9k
    if (pencoding) {   /* observed Adobe behavior */
755
26.9k
        int count = r_size(pencoding);
756
26.9k
        int type = ftype ? t_name : t_integer;
757
26.9k
        bool fixit = false;
758
759
6.93M
        while (count--) {
760
6.90M
           ref r;
761
6.90M
           if ((code = array_get(imemory, pencoding, count, &r)) < 0 ||
762
6.90M
             !(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
6.90M
        }
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
26.9k
        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
26.9k
    }
820
26.9k
    if ((code = dict_int_param(op, "WMode", 0, 1, 0, &wmode)) < 0 ||
821
26.9k
        (code = dict_bool_param(op, "BitmapWidths", false, &bitmapwidths)) < 0 ||
822
26.9k
        (code = dict_int_param(op, "ExactSize", 0, 2, fbit_use_bitmaps, &exactsize)) < 0 ||
823
26.9k
        (code = dict_int_param(op, "InBetweenSize", 0, 2, fbit_use_outlines, &inbetweensize)) < 0 ||
824
26.9k
        (code = dict_int_param(op, "TransformedChar", 0, 2, fbit_use_outlines, &transformedchar)) < 0
825
26.9k
        )
826
0
        return code;
827
26.9k
    code = dict_find_string(op, "FID", &pfid);
828
26.9k
    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
26.9k
    if (!r_has_attr(aop, a_write))
864
0
        return_error(gs_error_invalidaccess);
865
26.9k
    {
866
26.9k
        ref encoding;
867
868
        /*
869
         * Since add_FID may resize the dictionary and cause
870
         * pencoding to become invalid, save the Encoding.
871
         */
872
26.9k
        if (pencoding) {
873
26.9k
            encoding = *pencoding;
874
26.9k
            pencoding = &encoding;
875
26.9k
        }
876
26.9k
        code = build_gs_sub_font(i_ctx_p, op, &pfont, ftype, pstype,
877
26.9k
                                 pbuild, pencoding, op);
878
26.9k
        if (code < 0)
879
1
            return code;
880
26.9k
    }
881
26.9k
    pfont->BitmapWidths = bitmapwidths;
882
26.9k
    pfont->ExactSize = (fbit_type)exactsize;
883
26.9k
    pfont->InBetweenSize = (fbit_type)inbetweensize;
884
26.9k
    pfont->TransformedChar = (fbit_type)transformedchar;
885
26.9k
    pfont->WMode = wmode;
886
26.9k
    pfont->procs.font_info = zfont_info;
887
26.9k
    code = 0;
888
26.9k
set_name:
889
26.9k
    copy_font_name(&pfont->key_name, &kname);
890
26.9k
    *ppfont = pfont;
891
26.9k
    return code;
892
26.9k
}
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
26.9k
{
904
26.9k
    gs_matrix mat, omat;
905
26.9k
    ref fname;      /* t_string */
906
26.9k
    gs_font *pfont;
907
26.9k
    font_data *pdata;
908
    /*
909
     * Make sure that we allocate the font data
910
     * in the same VM as the font dictionary.
911
     */
912
26.9k
    uint space = ialloc_space(idmemory);
913
26.9k
    int code = sub_font_params(imemory, op, &mat, &omat, &fname);
914
915
26.9k
    if (code < 0)
916
1
        return code;
917
26.9k
    ialloc_set_space(idmemory, r_space(op));
918
26.9k
    pfont = gs_font_alloc(imemory, pstype, &gs_font_procs_default, NULL,
919
26.9k
                          "buildfont(font)");
920
26.9k
    pdata = ialloc_struct(font_data, &st_font_data,
921
26.9k
                          "buildfont(data)");
922
26.9k
    if (pfont == 0 || pdata == 0)
923
0
        code = gs_note_error(gs_error_VMerror);
924
26.9k
    else if (fid_op)
925
26.9k
        code = add_FID(i_ctx_p, fid_op, pfont, iimemory);
926
26.9k
    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
26.9k
    refset_null((ref *) pdata, sizeof(font_data) / sizeof(ref));
933
26.9k
    ref_assign_new(&pdata->dict, op);
934
26.9k
    ref_assign_new(&pdata->BuildChar, &pbuild->BuildChar);
935
26.9k
    ref_assign_new(&pdata->BuildGlyph, &pbuild->BuildGlyph);
936
26.9k
    if (pencoding)
937
26.9k
        ref_assign_new(&pdata->Encoding, pencoding);
938
26.9k
    pfont->client_data = pdata;
939
26.9k
    pfont->FontType = ftype;
940
26.9k
    pfont->FontMatrix = mat;
941
26.9k
    pfont->orig_FontMatrix = omat;
942
26.9k
    pfont->BitmapWidths = false;
943
26.9k
    pfont->ExactSize = fbit_use_bitmaps;
944
26.9k
    pfont->InBetweenSize = fbit_use_outlines;
945
26.9k
    pfont->TransformedChar = fbit_use_outlines;
946
26.9k
    pfont->WMode = 0;
947
26.9k
    pfont->procs.encode_char = zfont_encode_char;
948
26.9k
    pfont->procs.glyph_name = zfont_glyph_name;
949
26.9k
    ialloc_set_space(idmemory, space);
950
26.9k
    copy_font_name(&pfont->font_name, &fname);
951
26.9k
    *ppfont = pfont;
952
26.9k
    return 0;
953
26.9k
}
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
53.9k
{
960
53.9k
    switch (r_type(op)) {
961
10.3k
        case t_string:
962
10.3k
            *pfname = *op;
963
10.3k
            break;
964
15.0k
        case t_name:
965
15.0k
            name_string_ref(mem, op, pfname);
966
15.0k
            break;
967
28.5k
        default:
968
            /* This is weird, but legal.... */
969
28.5k
            make_empty_string(pfname, a_readonly);
970
53.9k
    }
971
53.9k
}
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
53.9k
{
977
53.9k
    uint size = r_size(pfname);
978
979
53.9k
    if (size > gs_font_name_max)
980
46
        size = gs_font_name_max;
981
53.9k
    memcpy(&pfstr->chars[0], pfname->value.const_bytes, size);
982
    /* Following is only for debugging printout. */
983
53.9k
    pfstr->chars[size] = 0;
984
53.9k
    pfstr->size = size;
985
53.9k
}
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
26.9k
{
991
26.9k
    return (pfont->base == pfont && pfont->dir == 0 ?
992
            /* i.e., unregistered original font */
993
26.9k
            gs_definefont(ifont_dir, pfont) :
994
26.9k
            0);
995
26.9k
}