Coverage Report

Created: 2026-07-24 07:44

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