Coverage Report

Created: 2026-04-01 07:17

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