Coverage Report

Created: 2025-06-10 06:59

/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
36.7k
{
44
36.7k
    ref_struct_clear_marks(cmem, vptr, offset_of(font_data, u.type42.mru_sfnts_index)/*size*/, pstype);
45
36.7k
}
46
static
47
ENUM_PTRS_BEGIN_PROC(font_data_enum_ptrs)
48
350k
{
49
350k
    return ref_struct_enum_ptrs(mem, vptr, offset_of(font_data, u.type42.mru_sfnts_index)/*size*/, index, pep, pstype, gcst);
50
350k
}
51
ENUM_PTRS_END_PROC
52
static
53
35.0k
RELOC_PTRS_BEGIN(font_data_reloc_ptrs)
54
35.0k
{
55
35.0k
    ref_struct_reloc_ptrs(vptr, offset_of(font_data, u.type42.mru_sfnts_index)/*size*/, pstype, gcst);
56
35.0k
}
57
35.0k
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.0k
{
64
10.0k
    os_ptr op = osp;
65
10.0k
    int code;
66
10.0k
    build_proc_refs build;
67
10.0k
    gs_font_base *pfont;
68
69
10.0k
    check_op(2);
70
10.0k
    check_type(*op, t_dictionary);
71
10.0k
    code = build_gs_font_procs(op, &build);
72
10.0k
    if (code < 0)
73
1
        return code;
74
10.0k
    code = build_gs_simple_font(i_ctx_p, op, &pfont, ft_user_defined,
75
10.0k
                                &st_gs_font_base, &build, bf_options_none);
76
10.0k
    if (code < 0)
77
2
        return code;
78
10.0k
    return define_gs_font(i_ctx_p, (gs_font *) pfont);
79
10.0k
}
80
81
/* Encode a character. */
82
gs_glyph
83
zfont_encode_char(gs_font *pfont, gs_char chr, gs_glyph_space_t gspace)
84
420k
{
85
420k
    font_data *pdata = pfont_data(pfont);
86
420k
    const ref *pencoding = &pdata->Encoding;
87
420k
    ulong index = chr;  /* work around VAX widening bug */
88
420k
    ref cname;
89
420k
    int code = array_get(pfont->memory, pencoding, (long)index, &cname);
90
91
420k
    if (code < 0 || !r_has_type(&cname, t_name))
92
1
        return GS_NO_GLYPH;
93
420k
    if (pfont->FontType == ft_user_defined && r_type(&pdata->BuildGlyph) == t_null) {
94
199k
        ref nsref, tname;
95
96
199k
        name_string_ref(pfont->memory, &cname, &nsref);
97
199k
        if (r_size(&nsref) == 7 &&
98
199k
            !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
2.11k
            char buf[20];
109
2.11k
            int code;
110
111
2.11k
            if (gspace == GLYPH_SPACE_NOGEN)
112
0
                return GS_NO_GLYPH;
113
2.11k
            gs_snprintf(buf, sizeof(buf), "j%ld", chr); /* 'j' is arbutrary. */
114
2.11k
            code = name_ref(pfont->memory, (const byte *)buf, strlen(buf), &tname, 1);
115
2.11k
            if (code < 0) {
116
                /* Can't propagate the error due to interface limitation,
117
                   return with .notdef */
118
0
            } else
119
2.11k
                cname = tname;
120
2.11k
        }
121
199k
    }
122
420k
    return (gs_glyph)name_index(pfont->memory, &cname);
123
420k
}
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
811k
{
129
811k
    ref nref, sref;
130
131
811k
    if (index >= GS_MIN_CID_GLYPH) { /* Fabricate a numeric name. */
132
0
        char cid_name[sizeof(gs_glyph) * 3 + 1];
133
0
        int code;
134
135
0
        gs_snprintf(cid_name, sizeof(cid_name), "%lu", (ulong) index);
136
0
        code = name_ref(font->memory, (const byte *)cid_name, strlen(cid_name),
137
0
                        &nref, 1);
138
0
        if (code < 0)
139
0
            return code;
140
811k
    } else {
141
811k
        name_index_ref(font->memory, index, &nref);
142
811k
        if (nref.value.pname == NULL)
143
0
            return_error(gs_error_unknownerror);
144
811k
    }
145
811k
    name_string_ref(font->memory, &nref, &sref);
146
811k
    pstr->data = sref.value.const_bytes;
147
811k
    pstr->size = r_size(&sref);
148
811k
    return 0;
149
811k
}
150
151
void get_zfont_glyph_name( int (**proc)(gs_font *font, gs_glyph glyph, gs_const_string *pstr) )
152
5.15k
{
153
5.15k
    *proc = zfont_glyph_name;
154
5.15k
}
155
156
static gs_char
157
gs_font_map_glyph_by_dict(const gs_memory_t *mem, const ref *map, gs_glyph glyph, ushort *u, unsigned int length)
158
0
{
159
0
    ref *v, n;
160
0
    uchar *unicode_return = (uchar *)u;
161
0
    if (glyph >= GS_MIN_CID_GLYPH) {
162
0
        uint cid = glyph - GS_MIN_CID_GLYPH;
163
164
0
        if (dict_find_string(map, "CIDCount", &v) > 0) {
165
            /* This is a CIDDEcoding resource. */
166
0
            make_int(&n, cid / 256);
167
0
            if (dict_find(map, &n, &v) > 0) {
168
0
                ref vv;
169
170
0
                if (array_get(mem, v, cid % 256, &vv) == 0 && r_type(&vv) == t_integer) {
171
0
                    if (v->value.intval > 65535) {
172
0
                        if (length < 4)
173
0
                            return 4;
174
0
                        unicode_return[0] = v->value.intval >> 24;
175
0
                        unicode_return[1] = (v->value.intval & 0x00FF0000) >> 16;
176
0
                        unicode_return[2] = (v->value.intval & 0x0000FF00) >> 8;
177
0
                        unicode_return[3] = v->value.intval & 0xFF;
178
0
                        return 4;
179
0
                    } else {
180
0
                        if (length < 2)
181
0
                            return 2;
182
0
                        unicode_return[0] = v->value.intval >> 8;
183
0
                        unicode_return[1] = v->value.intval & 0xFF;
184
0
                        return 2;
185
0
                    }
186
0
                }
187
0
            }
188
0
            return 0; /* Absent in the map. */
189
0
        }
190
        /* This is GlyphNames2Unicode dictionary. */
191
0
        make_int(&n, cid);
192
0
    } else
193
0
        name_index_ref(mem, glyph, &n);
194
0
     if (dict_find(map, &n, &v) > 0) {
195
0
        if (r_has_type(v, t_string)) {
196
0
            int l = r_size(v);
197
198
0
            if (length < l)
199
0
                return l;
200
0
            memcpy(unicode_return, v->value.const_bytes, l);
201
0
            return l;
202
0
        }
203
0
        if (r_type(v) == t_integer) {
204
0
            if (v->value.intval > 65535) {
205
0
                if (length < 4)
206
0
                    return 4;
207
0
                unicode_return[0] = v->value.intval >> 24;
208
0
                unicode_return[1] = (v->value.intval & 0x00FF0000) >> 16;
209
0
                unicode_return[2] = (v->value.intval & 0x0000FF00) >> 8;
210
0
                unicode_return[3] = v->value.intval & 0xFF;
211
0
                return 4;
212
0
            } else {
213
0
                if (length < 2)
214
0
                    return 2;
215
0
                unicode_return[0] = v->value.intval >> 8;
216
0
                unicode_return[1] = v->value.intval & 0xFF;
217
0
                return 2;
218
0
            }
219
0
        }
220
0
    }
221
0
    return 0; /* Absent in the map. */
222
0
}
223
224
/* Get Unicode UTF-16 code for a glyph. */
225
int
226
gs_font_map_glyph_to_unicode(gs_font *font, gs_glyph glyph, int ch, ushort *u, unsigned int length)
227
0
{
228
0
    font_data *pdata = pfont_data(font);
229
0
    const ref *UnicodeDecoding;
230
0
    uchar *unicode_return = (uchar *)u;
231
232
0
    if (r_type(&pdata->GlyphNames2Unicode) == t_dictionary) {
233
0
        int c = gs_font_map_glyph_by_dict(font->memory,
234
0
                                              &pdata->GlyphNames2Unicode, glyph, u, length);
235
236
0
        if (c != 0)
237
0
            return c;
238
0
        if (ch != -1) { /* -1 indicates a CIDFont */
239
            /* Its possible that we have a GlyphNames2Unicode dictionary
240
             * which contains integers and Unicode values, rather than names
241
             * and Unicode values. This happens if the input was PDF, the font
242
             * has a ToUnicode Cmap, but no Encoding. In this case we need to
243
             * use the character code as an index into the dictionary. Try that
244
             * now before we fall back to the UnicodeDecoding.
245
             */
246
0
            ref *v, n;
247
248
0
            make_int(&n, ch);
249
0
            if (dict_find(&pdata->GlyphNames2Unicode, &n, &v) > 0) {
250
0
                if (r_has_type(v, t_string)) {
251
0
                    int l = r_size(v);
252
253
0
                    if (l > length)
254
0
                        return l;
255
256
0
                    memcpy(unicode_return, v->value.const_bytes, l);
257
0
                    return l;
258
0
                }
259
0
                if (r_type(v) == t_integer) {
260
0
                    if (v->value.intval > 65535) {
261
0
                        if (length < 4)
262
0
                            return 4;
263
0
                        unicode_return[0] = v->value.intval >> 24;
264
0
                        unicode_return[1] = (v->value.intval & 0x00FF0000) >> 16;
265
0
                        unicode_return[2] = (v->value.intval & 0x0000FF00) >> 8;
266
0
                        unicode_return[3] = v->value.intval & 0xFF;
267
0
                        return 4;
268
0
                    } else {
269
0
                        if (length < 2)
270
0
                            return 2;
271
0
                        unicode_return[0] = v->value.intval >> 8;
272
0
                        unicode_return[1] = v->value.intval & 0xFF;
273
0
                        return 2;
274
0
                    }
275
0
                }
276
0
            }
277
0
        }
278
        /*
279
         * Fall through, because test.ps for SF bug #529103 requres
280
         * to examine both tables. Due to that the Unicode Decoding resource
281
         * can't be a default value for FontInfo.GlyphNames2Unicode .
282
         */
283
0
    }
284
0
    if (glyph <= GS_MIN_CID_GLYPH && glyph != GS_NO_GLYPH) {
285
0
        UnicodeDecoding = zfont_get_to_unicode_map(font->dir);
286
0
        if (UnicodeDecoding != NULL && r_type(UnicodeDecoding) == t_dictionary)
287
0
            return gs_font_map_glyph_by_dict(font->memory, UnicodeDecoding, glyph, u, length);
288
0
    }
289
0
    return 0; /* No map. */
290
0
}
291
292
/* ------ Initialization procedure ------ */
293
294
const op_def zbfont_op_defs[] =
295
{
296
    {"2.buildfont3", zbuildfont3},
297
    op_def_end(0)
298
};
299
300
/* ------ Subroutines ------ */
301
302
/* Convert strings to executable names for build_proc_refs. */
303
int
304
build_proc_name_refs(const gs_memory_t *mem, build_proc_refs * pbuild,
305
                     const char *bcstr, const char *bgstr)
306
24.0k
{
307
24.0k
    int code;
308
309
24.0k
    if (!bcstr)
310
24.0k
        make_null(&pbuild->BuildChar);
311
24.0k
    else {
312
24.0k
        if ((code = name_ref(mem, (const byte *)bcstr,
313
24.0k
                             strlen(bcstr), &pbuild->BuildChar, 0)) < 0)
314
0
            return code;
315
24.0k
        r_set_attrs(&pbuild->BuildChar, a_executable);
316
24.0k
    }
317
24.0k
    if (!bgstr)
318
24.0k
        make_null(&pbuild->BuildGlyph);
319
24.0k
    else {
320
24.0k
        if ((code = name_ref(mem, (const byte *)bgstr,
321
24.0k
                             strlen(bgstr), &pbuild->BuildGlyph, 0)) < 0)
322
0
            return code;
323
24.0k
        r_set_attrs(&pbuild->BuildGlyph, a_executable);
324
24.0k
    }
325
24.0k
    return 0;
326
24.0k
}
327
328
/* Get the BuildChar and/or BuildGlyph routines from a (base) font. */
329
int
330
build_gs_font_procs(os_ptr op, build_proc_refs * pbuild)
331
10.0k
{
332
10.0k
    int ccode, gcode;
333
10.0k
    ref *pBuildChar;
334
10.0k
    ref *pBuildGlyph;
335
336
10.0k
    check_type(*op, t_dictionary);
337
10.0k
    ccode = dict_find_string(op, "BuildChar", &pBuildChar);
338
10.0k
    gcode = dict_find_string(op, "BuildGlyph", &pBuildGlyph);
339
10.0k
    if (ccode <= 0) {
340
0
        if (gcode <= 0)
341
0
            return_error(gs_error_invalidfont);
342
0
        make_null(&pbuild->BuildChar);
343
10.0k
    } else {
344
10.0k
        check_proc(*pBuildChar);
345
10.0k
        pbuild->BuildChar = *pBuildChar;
346
10.0k
    }
347
10.0k
    if (gcode <= 0)
348
10.0k
        make_null(&pbuild->BuildGlyph);
349
0
    else {
350
0
        check_proc(*pBuildGlyph);
351
0
        pbuild->BuildGlyph = *pBuildGlyph;
352
0
    }
353
10.0k
    return 0;
354
10.0k
}
355
356
static int font_with_same_UID_and_another_metrics(const gs_font *pfont0, const gs_font *pfont1)
357
6
{
358
6
    const gs_font_base *pbfont0 = (const gs_font_base *)pfont0;
359
6
    const gs_font_base *pbfont1 = (const gs_font_base *)pfont1;
360
361
6
    if (uid_equal(&pbfont0->UID, &pbfont1->UID)) {
362
6
        const ref *pfdict0 = &pfont_data(gs_font_parent(pbfont0))->dict;
363
6
        const ref *pfdict1 = &pfont_data(gs_font_parent(pbfont1))->dict;
364
6
        ref *pmdict0, *pmdict1;
365
366
6
        if (pbfont0->WMode || dict_find_string(pfdict0, "Metrics", &pmdict0) <= 0)
367
6
            pmdict0 = NULL;
368
6
        if (pbfont1->WMode || dict_find_string(pfdict1, "Metrics", &pmdict1) <= 0)
369
6
            pmdict1 = NULL;
370
6
        if (!pmdict0 != !pmdict1)
371
0
            return 1;
372
6
        if (pmdict0 != NULL && !obj_eq(pfont0->memory, pmdict0, pmdict1))
373
0
            return 1;
374
6
        if (!pbfont0->WMode || dict_find_string(pfdict0, "Metrics2", &pmdict0) <= 0)
375
6
            pmdict0 = NULL;
376
6
        if (!pbfont0->WMode || dict_find_string(pfdict1, "Metrics2", &pmdict1) <= 0)
377
6
            pmdict1 = NULL;
378
6
        if (!pmdict0 != !pmdict1)
379
0
            return 1;
380
6
        if (pmdict0 != NULL && !obj_eq(pfont0->memory, pmdict0, pmdict1))
381
0
            return 1;
382
6
    }
383
6
    return 0;
384
6
}
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
12.0k
{
395
12.0k
    ref *pcharstrings = 0;
396
12.0k
    ref CharStrings;
397
12.0k
    gs_font_base *pfont;
398
12.0k
    font_data *pdata;
399
12.0k
    int code;
400
401
12.0k
    if (dict_find_string(op, "CharStrings", &pcharstrings) <= 0) {
402
0
        if (!(options & bf_CharStrings_optional))
403
0
            return_error(gs_error_invalidfont);
404
12.0k
    } else {
405
12.0k
        ref *ignore;
406
407
12.0k
        if (!r_has_type(pcharstrings, t_dictionary))
408
0
            return_error(gs_error_invalidfont);
409
12.0k
        if ((options & bf_notdef_required) != 0 &&
410
12.0k
            dict_find_string(pcharstrings, ".notdef", &ignore) <= 0
411
12.0k
            )
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
12.0k
        CharStrings = *pcharstrings;
418
12.0k
    }
419
12.0k
    code = build_gs_outline_font(i_ctx_p, op, ppfont, ftype, pstype, pbuild,
420
12.0k
                                 options, build_gs_simple_font);
421
12.0k
    if (code != 0)
422
0
        return code;
423
12.0k
    pfont = *ppfont;
424
12.0k
    pdata = pfont_data(pfont);
425
12.0k
    if (pcharstrings)
426
12.0k
        ref_assign(&pdata->CharStrings, &CharStrings);
427
0
    else
428
12.0k
        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
12.0k
    if (uid_is_valid(&pfont->UID) &&
432
12.0k
        !dict_check_uid_param(op, &pfont->UID)
433
12.0k
        )
434
0
        uid_set_invalid(&pfont->UID);
435
12.0k
    if (uid_is_valid(&pfont->UID)) {
436
12
        const gs_font *pfont0 = (const gs_font *)pfont;
437
438
12
        code = gs_font_find_similar(ifont_dir, &pfont0,
439
12
                       font_with_same_UID_and_another_metrics);
440
12
        if (code < 0)
441
0
            return code; /* Must not happen. */
442
12
        if (code)
443
0
            uid_set_invalid(&pfont->UID);
444
12
    }
445
12.0k
    return 0;
446
12.0k
}
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
12.0k
{
506
12.0k
    int painttype;
507
12.0k
    float strokewidth;
508
12.0k
    gs_font_base *pfont;
509
12.0k
    int code = dict_int_param(op, "PaintType", 0, 3, 0, &painttype);
510
511
12.0k
    if (code < 0)
512
0
        return code;
513
12.0k
    code = dict_float_param(op, "StrokeWidth", 0.0, &strokewidth);
514
12.0k
    if (code < 0)
515
0
        return code;
516
12.0k
    code = build_base_font(i_ctx_p, op, ppfont, ftype, pstype, pbuild,
517
12.0k
                           options);
518
12.0k
    if (code != 0)
519
0
        return code;
520
12.0k
    pfont = *ppfont;
521
12.0k
    pfont->PaintType = painttype;
522
12.0k
    pfont->StrokeWidth = strokewidth;
523
12.0k
    return 0;
524
12.0k
}
525
526
void
527
get_GlyphNames2Unicode(i_ctx_t *i_ctx_p, gs_font *pfont, ref *pdref)
528
21.9k
{
529
21.9k
    ref *pfontinfo = NULL, *g2u = NULL;
530
21.9k
    font_data *pdata;
531
532
21.9k
    if (dict_find_string(pdref, "FontInfo", &pfontinfo) <= 0 ||
533
21.9k
            !r_has_type(pfontinfo, t_dictionary) ||
534
21.9k
            dict_find_string(pfontinfo, "GlyphNames2Unicode", &g2u) <= 0 ||
535
21.9k
            !r_has_type(pfontinfo, t_dictionary))
536
21.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
22.0k
{
553
22.0k
    double bbox[4];
554
22.0k
    gs_uid uid;
555
22.0k
    int code;
556
22.0k
    gs_font_base *pfont;
557
22.0k
    uint space = ialloc_space(idmemory);
558
559
22.0k
    code = font_bbox_param(imemory, op, bbox);
560
22.0k
    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
22.0k
    ialloc_set_space(idmemory, r_space(op));
568
22.0k
    code = dict_uid_param(op, &uid, 0, imemory, i_ctx_p);
569
22.0k
    ialloc_set_space(idmemory, space);
570
22.0k
    if (code < 0)
571
0
        return code;
572
22.0k
    if ((options & bf_UniqueID_ignored) && uid_is_UniqueID(&uid))
573
0
        uid_set_invalid(&uid);
574
22.0k
    code = build_gs_font(i_ctx_p, op, (gs_font **) ppfont, ftype, pstype,
575
22.0k
                         pbuild, options);
576
22.0k
    if (code != 0)    /* invalid or scaled font */
577
116
        return code;
578
21.9k
    pfont = *ppfont;
579
21.9k
    pfont->procs.init_fstack = gs_default_init_fstack;
580
21.9k
    pfont->procs.define_font = gs_no_define_font;
581
21.9k
    pfont->procs.decode_glyph = gs_font_map_glyph_to_unicode;
582
21.9k
    pfont->procs.make_font = zbase_make_font;
583
21.9k
    pfont->procs.next_char_glyph = gs_default_next_char_glyph;
584
21.9k
    pfont->FAPI = 0;
585
21.9k
    pfont->FAPI_font_data = 0;
586
21.9k
    init_gs_simple_font(pfont, bbox, &uid);
587
21.9k
    lookup_gs_simple_font_encoding(pfont);
588
21.9k
    get_GlyphNames2Unicode(i_ctx_p, (gs_font *)pfont, op);
589
21.9k
    return 0;
590
22.0k
}
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
21.9k
{
597
21.9k
    pfont->FontBBox.p.x = bbox[0];
598
21.9k
    pfont->FontBBox.p.y = bbox[1];
599
21.9k
    pfont->FontBBox.q.x = bbox[2];
600
21.9k
    pfont->FontBBox.q.y = bbox[3];
601
21.9k
    pfont->UID = *puid;
602
21.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
21.9k
{
608
21.9k
    const ref *pfe = &pfont_data(pfont)->Encoding;
609
21.9k
    int index = -1;
610
611
21.9k
    pfont->encoding_index = index;
612
21.9k
    if (r_type(pfe) == t_array && r_size(pfe) <= 256) {
613
        /* Look for an encoding that's "close". */
614
21.9k
        uint esize = r_size(pfe);
615
21.9k
        int near_index = -1;
616
21.9k
        uint best = esize / 3;  /* must match at least this many */
617
21.9k
        gs_const_string fstrs[256];
618
21.9k
        int i;
619
620
        /* Get the string names of the glyphs in the font's Encoding. */
621
5.64M
        for (i = 0; i < esize; ++i) {
622
5.62M
            ref fchar;
623
624
5.62M
            if (array_get(pfont->memory, pfe, (long)i, &fchar) < 0 ||
625
5.62M
                !r_has_type(&fchar, t_name)
626
5.62M
                )
627
3.07k
                fstrs[i].data = 0, fstrs[i].size = 0;
628
5.61M
            else {
629
5.61M
                ref nsref;
630
631
5.61M
                name_string_ref(pfont->memory, &fchar, &nsref);
632
5.61M
                fstrs[i].data = nsref.value.const_bytes;
633
5.61M
                fstrs[i].size = r_size(&nsref);
634
5.61M
            }
635
5.62M
        }
636
        /* Compare them against the known encodings. */
637
22.6k
        for (index = 0; index < NUM_KNOWN_REAL_ENCODINGS; ++index) {
638
22.5k
            uint match = esize;
639
640
5.73M
            for (i = esize; --i >= 0;) {
641
5.71M
                gs_const_string rstr;
642
643
5.71M
                gs_c_glyph_name(gs_c_known_encode((gs_char)i, index), &rstr);
644
5.71M
                if (rstr.size == fstrs[i].size &&
645
5.71M
                    !memcmp(rstr.data, fstrs[i].data, rstr.size)
646
5.71M
                    )
647
5.61M
                    continue;
648
95.3k
                if (--match <= best)
649
588
                    break;
650
95.3k
            }
651
22.5k
            if (match > best) {
652
21.9k
                best = match;
653
21.9k
                near_index = index;
654
                /* If we have a perfect match, stop now. */
655
21.9k
                if (best == esize)
656
21.8k
                    break;
657
21.9k
            }
658
22.5k
        }
659
21.9k
        index = near_index;
660
21.9k
        if (best == esize)
661
21.8k
            pfont->encoding_index = index;
662
21.9k
    }
663
21.9k
    pfont->nearest_encoding_index = index;
664
21.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
21.9k
{
670
21.9k
    ref *pmatrix, *pfontname, *pfontstyle, *porigfont, *pfontinfo;
671
672
21.9k
    if (dict_find_string(op, "FontMatrix", &pmatrix) <= 0 ||
673
21.9k
        read_matrix(mem, pmatrix, pmat) < 0
674
21.9k
        )
675
1
        return_error(gs_error_invalidfont);
676
21.9k
    if (dict_find_string(op, "OrigFont", &porigfont) <= 0)
677
0
        porigfont = NULL;
678
21.9k
    if (porigfont != NULL && !r_has_type(porigfont, t_dictionary))
679
0
        return_error(gs_error_typecheck);
680
681
21.9k
    if (pomat!= NULL) {
682
21.9k
        if (porigfont == NULL ||
683
21.9k
            dict_find_string(porigfont, "FontMatrix", &pmatrix) <= 0 ||
684
21.9k
            read_matrix(mem, pmatrix, pomat) < 0
685
21.9k
            )
686
0
            memset(pomat, 0, sizeof(*pomat));
687
21.9k
    }
688
    /* Use the FontInfo/OrigFontName key preferrentially (created by MS PSCRIPT driver) */
689
21.9k
    if ((dict_find_string((porigfont != NULL ? porigfont : op), "FontInfo", &pfontinfo) > 0) &&
690
21.9k
        r_has_type(pfontinfo, t_dictionary) &&
691
21.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
21.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
10.8k
        get_font_name(mem, pfname, pfontname);
710
11.0k
    } else if (dict_find_string((porigfont != NULL ? porigfont : op), "FontName", &pfontname) > 0) {
711
10.9k
        get_font_name(mem, pfname, pfontname);
712
10.9k
    } else
713
85
        make_empty_string(pfname, a_readonly);
714
21.9k
    return 0;
715
21.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
22.0k
{
728
22.0k
    ref kname;      /* t_string */
729
22.0k
    ref *pftype;
730
22.0k
    ref *pencoding = 0;
731
22.0k
    bool bitmapwidths;
732
22.0k
    int exactsize, inbetweensize, transformedchar;
733
22.0k
    int wmode;
734
22.0k
    int code;
735
22.0k
    gs_font *pfont;
736
22.0k
    ref *pfid;
737
22.0k
    ref *aop = dict_access_ref(op);
738
22.0k
    bool cpsi_mode = gs_currentcpsimode(imemory);
739
740
22.0k
    get_font_name(imemory, &kname, op - 1);
741
22.0k
    if (dict_find_string(op, "FontType", &pftype) <= 0 ||
742
22.0k
        !r_has_type(pftype, t_integer) ||
743
22.0k
        pftype->value.intval != (int)ftype
744
22.0k
        )
745
0
        return_error(gs_error_invalidfont);
746
22.0k
    if (dict_find_string(op, "Encoding", &pencoding) <= 0) {
747
1
        if (!(options & bf_Encoding_optional))
748
1
            return_error(gs_error_invalidfont);
749
0
        pencoding = 0;
750
22.0k
    } else {
751
22.0k
        if (!r_is_array(pencoding))
752
0
            return_error(gs_error_invalidfont);
753
22.0k
    }
754
22.0k
    if (pencoding) {   /* observed Adobe behavior */
755
22.0k
        int count = r_size(pencoding);
756
22.0k
        int type = ftype ? t_name : t_integer;
757
22.0k
        bool fixit = false;
758
759
5.73M
        while (count--) {
760
5.71M
           ref r;
761
5.71M
           if ((code = array_get(imemory, pencoding, count, &r)) < 0 ||
762
5.71M
             !(r_has_type(&r, type) || r_has_type(&r, t_null))) {
763
0
               if (!cpsi_mode && ftype == ft_user_defined) {
764
0
                   if (code < 0 || r_has_type(&r, t_null)) {
765
0
                       return_error(gs_error_typecheck);
766
0
                   }
767
0
                   fixit = true;
768
0
                   break;
769
0
               }
770
0
               else {
771
0
                   return_error(gs_error_typecheck);
772
0
               }
773
0
           }
774
5.71M
        }
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
22.0k
        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
22.0k
    }
820
22.0k
    if ((code = dict_int_param(op, "WMode", 0, 1, 0, &wmode)) < 0 ||
821
22.0k
        (code = dict_bool_param(op, "BitmapWidths", false, &bitmapwidths)) < 0 ||
822
22.0k
        (code = dict_int_param(op, "ExactSize", 0, 2, fbit_use_bitmaps, &exactsize)) < 0 ||
823
22.0k
        (code = dict_int_param(op, "InBetweenSize", 0, 2, fbit_use_outlines, &inbetweensize)) < 0 ||
824
22.0k
        (code = dict_int_param(op, "TransformedChar", 0, 2, fbit_use_outlines, &transformedchar)) < 0
825
22.0k
        )
826
0
        return code;
827
22.0k
    code = dict_find_string(op, "FID", &pfid);
828
22.0k
    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
114
        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
114
        if (obj_eq(pfont->memory, pfont_dict(pfont), op)) {
843
114
            if (pfont->base == pfont) { /* original font */
844
114
                if (!level2_enabled)
845
0
                    return_error(gs_error_invalidfont);
846
114
                *ppfont = pfont;
847
114
                return 1;
848
114
            } 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
114
        }
861
114
    }
862
    /* This is a new font. */
863
21.9k
    if (!r_has_attr(aop, a_write))
864
0
        return_error(gs_error_invalidaccess);
865
21.9k
    {
866
21.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
21.9k
        if (pencoding) {
873
21.9k
            encoding = *pencoding;
874
21.9k
            pencoding = &encoding;
875
21.9k
        }
876
21.9k
        code = build_gs_sub_font(i_ctx_p, op, &pfont, ftype, pstype,
877
21.9k
                                 pbuild, pencoding, op);
878
21.9k
        if (code < 0)
879
1
            return code;
880
21.9k
    }
881
21.9k
    pfont->BitmapWidths = bitmapwidths;
882
21.9k
    pfont->ExactSize = (fbit_type)exactsize;
883
21.9k
    pfont->InBetweenSize = (fbit_type)inbetweensize;
884
21.9k
    pfont->TransformedChar = (fbit_type)transformedchar;
885
21.9k
    pfont->WMode = wmode;
886
21.9k
    pfont->procs.font_info = zfont_info;
887
21.9k
    code = 0;
888
21.9k
set_name:
889
21.9k
    copy_font_name(&pfont->key_name, &kname);
890
21.9k
    *ppfont = pfont;
891
21.9k
    return code;
892
21.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
21.9k
{
904
21.9k
    gs_matrix mat, omat;
905
21.9k
    ref fname;      /* t_string */
906
21.9k
    gs_font *pfont;
907
21.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
21.9k
    uint space = ialloc_space(idmemory);
913
21.9k
    int code = sub_font_params(imemory, op, &mat, &omat, &fname);
914
915
21.9k
    if (code < 0)
916
1
        return code;
917
21.9k
    ialloc_set_space(idmemory, r_space(op));
918
21.9k
    pfont = gs_font_alloc(imemory, pstype, &gs_font_procs_default, NULL,
919
21.9k
                          "buildfont(font)");
920
21.9k
    pdata = ialloc_struct(font_data, &st_font_data,
921
21.9k
                          "buildfont(data)");
922
21.9k
    if (pfont == 0 || pdata == 0)
923
0
        code = gs_note_error(gs_error_VMerror);
924
21.9k
    else if (fid_op)
925
21.9k
        code = add_FID(i_ctx_p, fid_op, pfont, iimemory);
926
21.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
21.9k
    refset_null((ref *) pdata, sizeof(font_data) / sizeof(ref));
933
21.9k
    ref_assign_new(&pdata->dict, op);
934
21.9k
    ref_assign_new(&pdata->BuildChar, &pbuild->BuildChar);
935
21.9k
    ref_assign_new(&pdata->BuildGlyph, &pbuild->BuildGlyph);
936
21.9k
    if (pencoding)
937
21.9k
        ref_assign_new(&pdata->Encoding, pencoding);
938
21.9k
    pfont->client_data = pdata;
939
21.9k
    pfont->FontType = ftype;
940
21.9k
    pfont->FontMatrix = mat;
941
21.9k
    pfont->orig_FontMatrix = omat;
942
21.9k
    pfont->BitmapWidths = false;
943
21.9k
    pfont->ExactSize = fbit_use_bitmaps;
944
21.9k
    pfont->InBetweenSize = fbit_use_outlines;
945
21.9k
    pfont->TransformedChar = fbit_use_outlines;
946
21.9k
    pfont->WMode = 0;
947
21.9k
    pfont->procs.encode_char = zfont_encode_char;
948
21.9k
    pfont->procs.glyph_name = zfont_glyph_name;
949
21.9k
    ialloc_set_space(idmemory, space);
950
21.9k
    copy_font_name(&pfont->font_name, &fname);
951
21.9k
    *ppfont = pfont;
952
21.9k
    return 0;
953
21.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
43.9k
{
960
43.9k
    switch (r_type(op)) {
961
9.86k
        case t_string:
962
9.86k
            *pfname = *op;
963
9.86k
            break;
964
16.4k
        case t_name:
965
16.4k
            name_string_ref(mem, op, pfname);
966
16.4k
            break;
967
17.5k
        default:
968
            /* This is weird, but legal.... */
969
17.5k
            make_empty_string(pfname, a_readonly);
970
43.9k
    }
971
43.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
43.9k
{
977
43.9k
    uint size = r_size(pfname);
978
979
43.9k
    if (size > gs_font_name_max)
980
72
        size = gs_font_name_max;
981
43.9k
    memcpy(&pfstr->chars[0], pfname->value.const_bytes, size);
982
    /* Following is only for debugging printout. */
983
43.9k
    pfstr->chars[size] = 0;
984
43.9k
    pfstr->size = size;
985
43.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
22.0k
{
991
22.0k
    return (pfont->base == pfont && pfont->dir == 0 ?
992
            /* i.e., unregistered original font */
993
21.9k
            gs_definefont(ifont_dir, pfont) :
994
22.0k
            0);
995
22.0k
}