Coverage Report

Created: 2025-06-10 06:56

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