Coverage Report

Created: 2022-10-31 07:00

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