Coverage Report

Created: 2025-06-24 07:01

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