Coverage Report

Created: 2026-04-01 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/psi/zfont42.c
Line
Count
Source
1
/* Copyright (C) 2001-2026 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* Type 42 font creation operator */
18
#include "memory_.h"
19
#include "ghost.h"
20
#include "oper.h"
21
#include "gsccode.h"
22
#include "gsmatrix.h"
23
#include "gxfont.h"
24
#include "gxfont42.h"
25
#include "bfont.h"
26
#include "icharout.h"
27
#include "idict.h"
28
#include "idparam.h"
29
#include "ifont42.h"
30
#include "ichar1.h"
31
#include "iname.h"
32
#include "store.h"
33
#include "ipacked.h"
34
35
/* Forward references */
36
static int z42_string_proc(gs_font_type42 *, ulong, uint, const byte **);
37
static uint z42_get_glyph_index(gs_font_type42 *, gs_glyph);
38
static int z42_gdir_get_outline(gs_font_type42 *, uint, gs_glyph_data_t *);
39
static font_proc_enumerate_glyph(z42_enumerate_glyph);
40
static font_proc_enumerate_glyph(z42_gdir_enumerate_glyph);
41
static font_proc_encode_char(z42_encode_char);
42
static font_proc_glyph_info(z42_glyph_info);
43
static font_proc_glyph_outline(z42_glyph_outline);
44
static font_proc_font_info(z42_font_info);
45
46
/* <string|name> <font_dict> .buildfont11/42 <string|name> <font> */
47
/* Build a type 11 (TrueType CID-keyed) or 42 (TrueType) font. */
48
int
49
build_gs_TrueType_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font_type42 **ppfont,
50
                       font_type ftype, gs_memory_type_ptr_t pstype,
51
                       const char *bcstr, const char *bgstr,
52
                       build_font_options_t options)
53
38
{
54
38
    build_proc_refs build;
55
38
    ref sfnts, GlyphDirectory;
56
38
    gs_font_type42 *pfont;
57
38
    font_data *pdata;
58
38
    int code;
59
60
38
    check_op(2);
61
26
    code = build_proc_name_refs(imemory, &build, bcstr, bgstr);
62
26
    if (code < 0)
63
0
        return code;
64
26
    check_type(*op, t_dictionary);
65
    /*
66
     * Since build_gs_primitive_font may resize the dictionary and cause
67
     * pointers to become invalid, we save sfnts and GlyphDirectory.
68
     */
69
26
    if ((code = font_string_array_param(imemory, op, "sfnts", &sfnts)) < 0 ||
70
26
        (code = font_GlyphDirectory_param(op, &GlyphDirectory)) < 0
71
26
        )
72
0
        return code;
73
26
    code = build_gs_primitive_font(i_ctx_p, op, (gs_font_base **)ppfont,
74
26
                                   ftype, pstype, &build, options);
75
26
    if (code != 0)
76
0
        return code;
77
26
    pfont = *ppfont;
78
26
    pdata = pfont_data(pfont);
79
26
    ref_assign(&pdata->u.type42.sfnts, &sfnts);
80
26
    pdata->u.type42.mru_sfnts_index = 0;
81
26
    pdata->u.type42.mru_sfnts_pos = 0;
82
26
    make_null_new(&pdata->u.type42.CIDMap);
83
26
    ref_assign(&pdata->u.type42.GlyphDirectory, &GlyphDirectory);
84
26
    pfont->data.string_proc = z42_string_proc;
85
26
    pfont->data.proc_data = (char *)pdata;
86
26
    pfont->is_resource = (options & bf_has_font_file ? true : false);
87
26
    code = gs_type42_font_init(pfont, 0);
88
26
    if (code < 0)
89
0
        return code;
90
26
    pfont->procs.font_info = z42_font_info;
91
    /*
92
     * If the font has a GlyphDictionary, this replaces loca and glyf for
93
     * accessing character outlines.  In this case, we use alternate
94
     * get_outline and enumerate_glyph procedures.
95
     */
96
26
    if (!r_has_type(&GlyphDirectory, t_null)) {
97
0
        pfont->data.get_outline = z42_gdir_get_outline;
98
0
        pfont->procs.enumerate_glyph = z42_gdir_enumerate_glyph;
99
0
    } else
100
26
        pfont->procs.enumerate_glyph = z42_enumerate_glyph;
101
    /*
102
     * The procedures that access glyph information must accept either
103
     * glyph names or glyph indexes.
104
     */
105
26
    pfont->data.get_glyph_index = z42_get_glyph_index;
106
26
    pfont->data.substitute_glyph_index_vertical = gs_type42_substitute_glyph_index_vertical;
107
26
    pfont->procs.encode_char = z42_encode_char;
108
26
    pfont->procs.glyph_info = z42_glyph_info;
109
26
    pfont->procs.glyph_outline = z42_glyph_outline;
110
26
    return 0;
111
26
}
112
static int
113
zbuildfont42(i_ctx_t *i_ctx_p)
114
38
{
115
38
    os_ptr op = osp;
116
38
    gs_font_type42 *pfont;
117
38
    int code = build_gs_TrueType_font(i_ctx_p, op, &pfont, ft_TrueType,
118
38
                                      &st_gs_font_type42, "%Type42BuildChar",
119
38
                                      "%Type42BuildGlyph", bf_options_none);
120
121
38
    if (code < 0)
122
12
        return code;
123
26
    return define_gs_font(i_ctx_p, (gs_font *)pfont);
124
38
}
125
126
/*
127
 * Check a parameter for being an array of strings.  Return the parameter
128
 * value even if it is of the wrong type.
129
 */
130
int
131
font_string_array_param(const gs_memory_t *mem, os_ptr op, const char *kstr, ref *psa)
132
26
{
133
26
    ref *pvsa;
134
26
    ref rstr0;
135
26
    int code;
136
137
26
    if (dict_find_string(op, kstr, &pvsa) <= 0)
138
0
        return_error(gs_error_invalidfont);
139
26
    *psa = *pvsa;
140
26
    if (!r_has_type(pvsa, t_array))
141
0
        return_error(gs_error_typecheck);
142
    /*
143
     * We only check the first element of the array now, as a sanity test;
144
     * elements are checked as needed by string_array_access_proc.
145
     */
146
26
    if ((code = array_get(mem, pvsa, 0L, &rstr0)) < 0)
147
0
        return code;
148
26
    if (!r_has_type(&rstr0, t_string))
149
0
        return_error(gs_error_typecheck);
150
26
    return 0;
151
26
}
152
153
/*
154
 * Get a GlyphDirectory if present.  Return 0 if present, 1 if absent,
155
 * or an error code.
156
 */
157
int
158
font_GlyphDirectory_param(os_ptr op, ref *pGlyphDirectory)
159
26
{
160
26
    ref *pgdir;
161
162
26
    if (dict_find_string(op, "GlyphDirectory", &pgdir) <= 0)
163
26
        make_null(pGlyphDirectory);
164
0
    else if (!r_has_type(pgdir, t_dictionary) && !r_is_array(pgdir))
165
0
        return_error(gs_error_typecheck);
166
0
    else
167
0
        *pGlyphDirectory = *pgdir;
168
26
    return 0;
169
26
}
170
171
/*
172
 * Access a given byte offset and length in an array of strings.
173
 * This is used for sfnts and for CIDMap.  The int argument is 2 for sfnts
174
 * (because of the strange behavior of odd-length strings), 1 for CIDMap.
175
 * Return code : 0 - success, <0 - error,
176
 *               >0 - number of accessible bytes (client must cycle).
177
 */
178
int
179
string_array_access_proc(const gs_memory_t *mem,
180
                         const ref *psa, int modulus, ulong offset, uint length,
181
                         uint *mru_index, ulong *mru_pos,
182
                         const byte **pdata)
183
338
{
184
338
    ulong left;
185
338
    uint index;
186
338
    bool backwards;
187
188
338
    if (length == 0)
189
0
        return 0;
190
338
    if (mru_index && mru_pos && offset >= (*mru_pos >> 1)) {
191
        /*    offset in or after mru string       */
192
        /* OR offset in 2nd half of the fragment before the mru string  */
193
338
        backwards = (*mru_pos > offset);
194
338
        if (backwards) {
195
0
            index = *mru_index - 1; /* 1st string to examine */
196
0
            left = *mru_pos - offset; /* how many bytes to seek backwards */
197
338
        } else {
198
338
            index = *mru_index;   /* 1st string to examine */
199
338
            left = offset - *mru_pos; /* how many bytes to seek forward */
200
338
        }
201
338
    } else {
202
        /*    no mru              */
203
        /* OR offset in 1st half of the fragment before the mru string  */
204
0
        backwards = false;
205
0
        index = 0;
206
0
        left = offset;
207
0
    }
208
494
    for (;;) {
209
494
        ref rstr;
210
494
        int code = array_get(mem, psa, index, &rstr);
211
494
        uint size;
212
213
494
        if (code < 0)
214
0
            return code;
215
494
        if (!r_has_type(&rstr, t_string))
216
0
            return_error(gs_error_typecheck);
217
        /*
218
         * NOTE: According to the Adobe documentation, each sfnts
219
         * string should have even length.  If the length is odd,
220
         * the additional byte is padding and should be ignored.
221
         */
222
494
        size = r_size(&rstr) & -modulus;
223
494
        if (backwards) {
224
0
            if (left <= size) {
225
0
                left = size - left;
226
0
                backwards = false;
227
                /* "index" does not change */
228
0
            } else {
229
0
                left -= size;
230
0
                --index;
231
0
                continue;
232
0
            }
233
0
        }
234
494
        if (left < size) {
235
338
            *pdata = rstr.value.const_bytes + left;
236
338
            if (mru_index)
237
338
                *mru_index = index;
238
338
            if (mru_pos)
239
338
                *mru_pos = offset - left;
240
338
            if (left + length > size)
241
0
                return size - left;
242
338
            return 0;
243
338
        }
244
156
        left -= size;
245
156
        ++index;
246
156
    }
247
338
}
248
249
/* ------ Initialization procedure ------ */
250
251
const op_def zfont42_op_defs[] =
252
{
253
    {"2.buildfont42", zbuildfont42},
254
    op_def_end(0)
255
};
256
257
/* Reduce a glyph name to a glyph index if needed. */
258
static gs_glyph
259
glyph_to_index(const gs_font *font, gs_glyph glyph)
260
0
{
261
0
    ref gref;
262
0
    ref *pcstr;
263
264
0
    if (glyph >= GS_MIN_GLYPH_INDEX)
265
0
        return glyph;
266
0
    name_index_ref(font->memory, glyph, &gref);
267
0
    if (dict_find(&pfont_data(font)->CharStrings, &gref, &pcstr) > 0 &&
268
0
        r_has_type(pcstr, t_integer)
269
0
        ) {
270
0
        gs_glyph index_glyph = pcstr->value.intval + GS_MIN_GLYPH_INDEX;
271
272
        /* We don't need to check the upper limit of the value, since the
273
         * upper limit is the maximum value of the data type
274
         */
275
0
        if (index_glyph >= GS_MIN_GLYPH_INDEX)
276
0
            return index_glyph;
277
0
    }
278
0
    return GS_MIN_GLYPH_INDEX; /* glyph 0 is notdef */
279
0
}
280
static uint
281
z42_get_glyph_index(gs_font_type42 *pfont, gs_glyph glyph)
282
0
{
283
0
    gs_glyph gid = glyph_to_index((gs_font *)pfont, glyph);
284
285
0
    return gid - GS_MIN_GLYPH_INDEX;
286
0
}
287
288
/*
289
 * Get a glyph outline from GlyphDirectory.  Return an empty string if
290
 * the glyph is missing or out of range.
291
 */
292
int
293
font_gdir_get_outline(const gs_memory_t *mem,
294
                      const ref *pgdir,
295
                      long glyph_index,
296
                      gs_glyph_data_t *pgd)
297
0
{
298
0
    ref iglyph;
299
0
    ref gdef;
300
0
    ref *pgdef;
301
0
    int code;
302
303
0
    if (r_has_type(pgdir, t_dictionary)) {
304
0
        make_int(&iglyph, glyph_index);
305
0
        code = dict_find(pgdir, &iglyph, &pgdef) - 1; /* 0 => not found */
306
0
    } else {
307
0
        code = array_get(mem, pgdir, glyph_index, &gdef);
308
0
        pgdef = &gdef;
309
0
    }
310
0
    if (code < 0) {
311
0
        gs_glyph_data_from_null(pgd);
312
0
    } else if (!r_has_type(pgdef, t_string)) {
313
0
        return_error(gs_error_typecheck);
314
0
    } else {
315
0
        gs_glyph_data_from_string(pgd, pgdef->value.const_bytes, r_size(pgdef),
316
0
                                  NULL);
317
0
    }
318
0
    return 0;
319
0
}
320
static int
321
z42_gdir_get_outline(gs_font_type42 * pfont, uint glyph_index,
322
                     gs_glyph_data_t *pgd)
323
0
{
324
0
    const font_data *pfdata = pfont_data(pfont);
325
0
    const ref *pgdir = &pfdata->u.type42.GlyphDirectory;
326
327
0
    return font_gdir_get_outline(pfont->memory, pgdir, (long)glyph_index, pgd);
328
0
}
329
330
/* Enumerate glyphs from CharStrings or loca / glyf. */
331
static int
332
z42_enumerate_glyph(gs_font *font, int *pindex, gs_glyph_space_t glyph_space,
333
                    gs_glyph *pglyph)
334
0
{
335
0
    if (glyph_space == GLYPH_SPACE_INDEX)
336
0
        return gs_type42_enumerate_glyph(font, pindex, glyph_space, pglyph);
337
0
    else {
338
0
        const ref *pcsdict = &pfont_data(font)->CharStrings;
339
340
0
        return zchar_enumerate_glyph(font->memory, pcsdict, pindex, pglyph);
341
0
    }
342
0
}
343
344
/* Enumerate glyphs (keys) from GlyphDirectory instead of loca / glyf. */
345
static int
346
z42_gdir_enumerate_glyph(gs_font *font, int *pindex,
347
                         gs_glyph_space_t glyph_space, gs_glyph *pglyph)
348
0
{
349
0
    const ref *pgdict;
350
0
    int code;
351
352
0
    if (glyph_space == GLYPH_SPACE_INDEX) {
353
0
        pgdict = &pfont_data(font)->u.type42.GlyphDirectory;
354
0
        if (!r_has_type(pgdict, t_dictionary)) {
355
0
            const ref_packed *packed = pgdict->value.packed;
356
0
            ref gdef;
357
0
            uint i;
358
359
            /* Advance to *pindex */
360
0
            for (i = 0; i < (uint)*pindex; i++)
361
0
                packed = packed_next(packed);
362
363
            /* Scan forward for non-null */
364
0
            for (; (uint)*pindex < r_size(pgdict); (*pindex)++) {
365
0
                packed_get(font->memory, packed, &gdef);
366
0
                packed = packed_next(packed);
367
0
                if (!r_has_type(&gdef, t_null)) {
368
0
                    *pglyph = GS_MIN_GLYPH_INDEX + (*pindex)++;
369
0
                    return 0;
370
0
                }
371
0
            }
372
0
            *pindex = 0;
373
0
            return 0;
374
0
        }
375
0
    } else
376
0
        pgdict = &pfont_data(font)->CharStrings;
377
    /* A trick : use zchar_enumerate_glyph to enumerate GIDs : */
378
0
    code = zchar_enumerate_glyph(font->memory, pgdict, pindex, pglyph);
379
0
    if (*pindex != 0 && *pglyph >= GS_MIN_CID_GLYPH)
380
0
        *pglyph = *pglyph - GS_MIN_CID_GLYPH + GS_MIN_GLYPH_INDEX;
381
0
    return code;
382
0
}
383
384
/*
385
 * Define font procedures that accept either a character name or a glyph
386
 * index as the glyph.
387
 */
388
static gs_glyph
389
z42_encode_char(gs_font *font, gs_char chr, gs_glyph_space_t glyph_space)
390
0
{
391
0
    gs_glyph glyph = zfont_encode_char(font, chr, glyph_space);
392
393
0
    return (glyph_space == GLYPH_SPACE_INDEX && glyph != GS_NO_GLYPH ?
394
0
            glyph_to_index(font, glyph) : glyph);
395
0
}
396
static int
397
z42_glyph_outline(gs_font *font, int WMode, gs_glyph glyph, const gs_matrix *pmat,
398
                  gx_path *ppath, double sbw[4])
399
0
{
400
0
    return gs_type42_glyph_outline(font, WMode, glyph_to_index(font, glyph),
401
0
                                   pmat, ppath, sbw);
402
0
}
403
static int
404
z42_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
405
               int members, gs_glyph_info_t *info)
406
0
{   /* fixme : same as z1_glyph_info. */
407
0
    int wmode = font->WMode;
408
409
0
    return z1_glyph_info_generic(font, glyph, pmat, members, info, gs_type42_glyph_info, wmode);
410
0
}
411
412
/* Procedure for accessing the sfnts array.
413
 * Return code : 0 - success, <0 - error,
414
 *               >0 - number of accessible bytes (client must cycle).
415
 */
416
static int
417
z42_string_proc(gs_font_type42 * pfont, ulong offset, uint length,
418
                const byte ** pdata)
419
338
{
420
338
    return string_array_access_proc(pfont->memory, &pfont_data(pfont)->u.type42.sfnts, 2,
421
338
                                    offset, length, &pfont_data(pfont)->u.type42.mru_sfnts_index,
422
338
                                    &pfont_data(pfont)->u.type42.mru_sfnts_pos, pdata);
423
338
}
424
425
static int
426
z42_font_info(gs_font *font, const gs_point *pscale, int members,
427
           gs_font_info_t *info)
428
0
{
429
0
    int code = zfont_info(font, pscale, members, info);
430
431
0
    if (code < 0)
432
0
        return code;
433
0
    return gs_truetype_font_info(font, pscale, members, info);
434
0
}