Coverage Report

Created: 2025-06-24 07:01

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