Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/devices/vector/gdevpsfu.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
/* PostScript/PDF font writing utilities */
18
#include "memory_.h"
19
#include <stdlib.h>   /* for qsort */
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gsmatrix.h"   /* for gxfont.h */
23
#include "gxfont.h"
24
#include "gdevpsf.h"
25
26
/* Begin enumerating the glyphs in a font or a font subset. */
27
static int
28
enumerate_font_next(psf_glyph_enum_t *ppge, gs_glyph *pglyph)
29
3.72M
{
30
3.72M
    gs_font *font = ppge->font;
31
3.72M
    int index = (int)ppge->index;
32
3.72M
    int code = font->procs.enumerate_glyph(font, &index,
33
3.72M
                                           ppge->glyph_space, pglyph);
34
35
3.72M
    ppge->index = index;
36
3.72M
    return (index == 0 ? 1 : code < 0 ? code : 0);
37
3.72M
}
38
static int
39
enumerate_glyphs_next(psf_glyph_enum_t *ppge, gs_glyph *pglyph)
40
1.07M
{
41
1.07M
    if (ppge->index >= ppge->subset.size)
42
52.9k
        return 1;
43
1.02M
    *pglyph = ppge->subset.selected.list[ppge->index++];
44
1.02M
    return 0;
45
1.07M
}
46
static int
47
enumerate_range_next(psf_glyph_enum_t *ppge, gs_glyph *pglyph)
48
0
{
49
0
    if (ppge->index >= ppge->subset.size)
50
0
        return 1;
51
0
    *pglyph = (gs_glyph)(ppge->index++ + GS_MIN_CID_GLYPH);
52
0
    return 0;
53
0
}
54
void
55
psf_enumerate_list_begin(psf_glyph_enum_t *ppge, gs_font *font,
56
                         const gs_glyph *subset_list, uint subset_size,
57
                         gs_glyph_space_t glyph_space)
58
73.6k
{
59
73.6k
    ppge->font = font;
60
73.6k
    ppge->subset.selected.list = subset_list;
61
73.6k
    ppge->subset.size = subset_size;
62
73.6k
    ppge->glyph_space = glyph_space;
63
73.6k
    ppge->enumerate_next =
64
73.6k
        (subset_list ? enumerate_glyphs_next :
65
73.6k
         subset_size ? enumerate_range_next : enumerate_font_next);
66
73.6k
    psf_enumerate_glyphs_reset(ppge);
67
73.6k
}
68
69
/* Begin enumerating CID or TT glyphs in a subset given by a bit vector. */
70
static int
71
enumerate_bits_next(psf_glyph_enum_t *ppge, gs_glyph *pglyph)
72
56.0k
{
73
34.9M
    for (; ppge->index < ppge->subset.size; ppge->index++)
74
34.9M
        if (ppge->subset.selected.bits[ppge->index >> 3] & (0x80 >> (ppge->index & 7))) {
75
17.4k
            *pglyph = (gs_glyph)(ppge->index++ + GS_MIN_CID_GLYPH);
76
17.4k
            return 0;
77
17.4k
        }
78
38.5k
    return 1;
79
56.0k
}
80
void
81
psf_enumerate_bits_begin(psf_glyph_enum_t *ppge, gs_font *font,
82
                         const byte *subset_bits, uint subset_size,
83
                         gs_glyph_space_t glyph_space)
84
38.9k
{
85
38.9k
    ppge->font = font;
86
38.9k
    ppge->subset.selected.bits = subset_bits;
87
38.9k
    ppge->subset.size = subset_size;
88
38.9k
    ppge->glyph_space = glyph_space;
89
38.9k
    ppge->enumerate_next =
90
38.9k
        (subset_bits ? enumerate_bits_next :
91
38.9k
         subset_size ? enumerate_range_next : enumerate_font_next);
92
38.9k
    psf_enumerate_glyphs_reset(ppge);
93
38.9k
}
94
95
/* Reset a glyph enumeration. */
96
void
97
psf_enumerate_glyphs_reset(psf_glyph_enum_t *ppge)
98
192k
{
99
192k
    ppge->index = 0;
100
192k
}
101
102
/* Enumerate the next glyph in a font or a font subset. */
103
/* Return 0 if more glyphs, 1 if done, <0 if error. */
104
int
105
psf_enumerate_glyphs_next(psf_glyph_enum_t *ppge, gs_glyph *pglyph)
106
4.85M
{
107
4.85M
    return ppge->enumerate_next(ppge, pglyph);
108
4.85M
}
109
110
/*
111
 * Add composite glyph pieces to a list of glyphs.  Does not sort or
112
 * remove duplicates.  max_pieces is the maximum number of pieces that a
113
 * single glyph can have: if this value is not known, the caller should
114
 * use max_count.
115
 */
116
int
117
psf_add_subset_pieces(gs_glyph *glyphs, uint *pcount, uint max_count,
118
                       uint max_pieces, gs_font *font)
119
18.8M
{
120
18.8M
    uint i;
121
18.8M
    uint count = *pcount;
122
123
37.7M
    for (i = 0; i < count; ++i) {
124
18.9M
        gs_glyph_info_t info;
125
18.9M
        int code;
126
127
18.9M
        if (count + max_pieces > max_count) {
128
            /* Check first to make sure there is enough room. */
129
18.9M
            code = font->procs.glyph_info(font, glyphs[i], NULL,
130
18.9M
                                          GLYPH_INFO_NUM_PIECES, &info);
131
18.9M
            if (code < 0)
132
369
                continue;
133
18.9M
            if (count + info.num_pieces > max_count)
134
4
                return_error(gs_error_rangecheck);
135
18.9M
        }
136
18.9M
        info.pieces = &glyphs[count];
137
18.9M
        code = font->procs.glyph_info(font, glyphs[i], NULL,
138
18.9M
                                      GLYPH_INFO_NUM_PIECES |
139
18.9M
                                      GLYPH_INFO_PIECES, &info);
140
18.9M
        if (code >= 0)
141
18.9M
            count += info.num_pieces;
142
18.9M
    }
143
18.8M
    *pcount = count;
144
18.8M
    return 0;
145
18.8M
}
146
147
/*
148
 * Sort a list of glyphs and remove duplicates.  Return the number of glyphs
149
 * in the result.
150
 */
151
static int
152
compare_glyphs(const void *pg1, const void *pg2)
153
691k
{
154
691k
    gs_glyph g1 = *(const gs_glyph *)pg1, g2 = *(const gs_glyph *)pg2;
155
156
691k
    return (g1 < g2 ? -1 : g1 > g2 ? 1 : 0);
157
691k
}
158
int
159
psf_sort_glyphs(gs_glyph *glyphs, int count)
160
10.6k
{
161
10.6k
    int i, n;
162
163
10.6k
    qsort(glyphs, count, sizeof(*glyphs), compare_glyphs);
164
210k
    for (i = n = 0; i < count; ++i)
165
199k
        if (i == 0 || glyphs[i] != glyphs[i - 1])
166
199k
            glyphs[n++] = glyphs[i];
167
10.6k
    return n;
168
10.6k
}
169
170
/*
171
 * Return the index of a given glyph in a sorted list of glyphs, or -1
172
 * if the glyph is not present.
173
 */
174
int
175
psf_sorted_glyphs_index_of(const gs_glyph *glyphs, int count, gs_glyph glyph)
176
582k
{
177
582k
    int lo = 0, hi = count - 1;
178
179
582k
    if (hi < 0)
180
0
        return -1;
181
582k
    if (glyph < glyphs[0] || glyph > glyphs[hi])
182
0
        return -1;
183
    /*
184
     * Loop invariants: hi > lo;
185
     * glyphs[lo] <= glyph <= glyphs[hi].
186
     */
187
3.44M
    while (hi - lo > 1) {
188
2.85M
        int mid = (lo + hi) >> 1;
189
190
2.85M
        if (glyph >= glyphs[mid])
191
1.57M
            lo = mid;
192
1.28M
        else
193
1.28M
            hi = mid;
194
2.85M
    }
195
582k
    return (glyph == glyphs[lo] ? lo : glyph == glyphs[hi] ? hi : -1);
196
582k
}
197
/* Determine whether a sorted list of glyphs includes a given glyph. */
198
bool
199
psf_sorted_glyphs_include(const gs_glyph *glyphs, int count, gs_glyph glyph)
200
97.3k
{
201
97.3k
    return psf_sorted_glyphs_index_of(glyphs, count, glyph) >= 0;
202
97.3k
}
203
204
/* Check that all selected glyphs can be written. */
205
int
206
psf_check_outline_glyphs(gs_font_base *pfont, psf_glyph_enum_t *ppge,
207
                         glyph_data_proc_t glyph_data)
208
18.4k
{
209
18.4k
    uint members = GLYPH_INFO_WIDTH0 << pfont->WMode;
210
18.4k
    gs_glyph glyph;
211
18.4k
    int code, good_glyphs = 0;
212
213
374k
    while ((code = psf_enumerate_glyphs_next(ppge, &glyph)) != 1) {
214
356k
        gs_glyph_data_t gdata;
215
356k
        gs_font_type1 *ignore_font;
216
356k
        gs_glyph_info_t info;
217
218
356k
        if (code < 0)
219
0
            return code;
220
356k
        gdata.memory = pfont->memory;
221
356k
        code = glyph_data(pfont, glyph, &gdata, &ignore_font);
222
        /*
223
         * If the glyph isn't defined by a CharString, glyph_data will
224
         * return a typecheck error.  But if there's merely a glyph in
225
         * in the Encoding that isn't defined, glyph_data will return an
226
         * undefined error, which is OK.
227
         */
228
356k
        if (code < 0) {
229
0
            if (code == gs_error_undefined)
230
0
                continue;
231
0
            return code;
232
0
        }
233
356k
        gs_glyph_data_free(&gdata, "psf_check_outline_glyphs");
234
        /*
235
         * If the font has a CDevProc or calls a non-standard OtherSubr,
236
         * glyph_info will return a rangecheck error.
237
         */
238
356k
        code = pfont->procs.glyph_info((gs_font *)pfont, glyph, NULL,
239
356k
                                       members, &info);
240
241
        /* It may be that a single glyph is bad (eg no (h)sbw), we'll ignore it */
242
        /* here, the glyph may not be included in any subset, or not used at all */
243
        /* (ie the /.notdef). If an invalid glyph is actually used then the text */
244
        /* processing will still signal an error causing the document to fail. */
245
356k
        if(code == gs_error_invalidfont || code == gs_error_rangecheck)
246
73
            continue;
247
248
356k
        if (code < 0)
249
0
            return code;
250
356k
        good_glyphs++;
251
356k
    }
252
18.4k
    if(good_glyphs)
253
18.4k
        return 0;
254
0
    else
255
0
        return_error(gs_error_invalidfont);
256
18.4k
}
257
258
/* Gather glyph information for a Type 1 or Type 2 font. */
259
int
260
psf_get_outline_glyphs(psf_outline_glyphs_t *pglyphs, gs_font_base *pfont,
261
                       gs_glyph *orig_subset_glyphs, uint orig_subset_size,
262
                       glyph_data_proc_t glyph_data)
263
18.4k
{
264
18.4k
    gs_glyph notdef = GS_NO_GLYPH;
265
18.4k
    gs_glyph *subset_glyphs = orig_subset_glyphs;
266
18.4k
    uint subset_size = orig_subset_size;
267
268
    /* Currently its impossible to hit this code (subset_glyphs is always NULL) and if
269
     * we ever did, there's a problem with countof(pglyphs->subset_data), the count
270
     * will always be incorrect it seems. Since we never use the code we could just
271
     * leave it in place, but Coverity complains. We could remove it, but it might
272
     * actually be useful one day (if fixed) so for now, ifdef it out.
273
     */
274
#if 0
275
    if (subset_glyphs) {
276
        if (subset_size > countof(pglyphs->subset_data))
277
            return_error(gs_error_limitcheck);
278
        memcpy(pglyphs->subset_data, orig_subset_glyphs,
279
               sizeof(gs_glyph) * subset_size);
280
        subset_glyphs = pglyphs->subset_data;
281
    }
282
#endif
283
284
18.4k
    {
285
        /*
286
         * Make sure that this font can be written out.  Specifically, it
287
         * must have no CharStrings defined by PostScript procedures, no
288
         * non-standard OtherSubrs, and no CDevProc.
289
         */
290
18.4k
        psf_glyph_enum_t genum;
291
18.4k
        int code;
292
293
18.4k
        psf_enumerate_glyphs_begin(&genum, (gs_font *)pfont, subset_glyphs,
294
18.4k
                                    (subset_glyphs ? subset_size : 0),
295
18.4k
                                    GLYPH_SPACE_NAME);
296
18.4k
        code = psf_check_outline_glyphs(pfont, &genum, glyph_data);
297
18.4k
        if (code < 0)
298
0
            return code;
299
18.4k
    }
300
301
18.4k
    {
302
        /*
303
         * Detect the .notdef glyph, needed for subset fonts and to
304
         * eliminate unnecessary Encoding assignments.
305
         */
306
18.4k
        psf_glyph_enum_t genum;
307
18.4k
        gs_glyph glyph;
308
18.4k
        int code;
309
310
18.4k
        psf_enumerate_glyphs_begin(&genum, (gs_font *)pfont, NULL, 0,
311
18.4k
                                    GLYPH_SPACE_NAME);
312
18.4k
        while ((code = psf_enumerate_glyphs_next(&genum, &glyph)) != 1) {
313
18.4k
            if (gs_font_glyph_is_notdef(pfont, glyph)) {
314
18.4k
                notdef = glyph;
315
18.4k
                break;
316
18.4k
            }
317
18.4k
        }
318
18.4k
    }
319
320
#if 0
321
    if (subset_glyphs) {
322
        /*
323
         * For subset fonts, we must ensure that characters referenced
324
         * by seac are also included.  Note that seac creates at most
325
         * 2 pieces.
326
         */
327
        int code = psf_add_subset_pieces(subset_glyphs, &subset_size,
328
                                          countof(pglyphs->subset_data) - 1, 2,
329
                                          (gs_font *)pfont);
330
        uint keep_size, i;
331
332
        if (code < 0)
333
            return code;
334
        /* Subset fonts require .notdef. */
335
        if (notdef == GS_NO_GLYPH)
336
            return_error(gs_error_rangecheck);
337
        /* Remove undefined glyphs. */
338
        for (i = 0, keep_size = 0; i < subset_size; ++i) {
339
            gs_glyph_info_t info;
340
            gs_glyph glyph = subset_glyphs[i];
341
342
            /*
343
             * The documentation for the glyph_info procedure says that
344
             * using members = 0 is an inexpensive way to find out
345
             * whether a given glyph exists, but the implementations
346
             * don't actually do this.  Request an inexpensive value.
347
             */
348
            if (pfont->procs.glyph_info((gs_font *)pfont, glyph, NULL,
349
                                        GLYPH_INFO_NUM_PIECES, &info) >= 0)
350
                subset_glyphs[keep_size++] = glyph;
351
        }
352
        subset_size = keep_size;
353
        /* Sort the glyphs.  Make sure .notdef is included. */
354
        subset_glyphs[subset_size++] = notdef;
355
        subset_size = psf_sort_glyphs(subset_glyphs, subset_size);
356
    }
357
#endif
358
359
18.4k
    pglyphs->notdef = notdef;
360
18.4k
    pglyphs->subset_glyphs = subset_glyphs;
361
18.4k
    pglyphs->subset_size = subset_size;
362
18.4k
    return 0;
363
18.4k
}