Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/devices/vector/gdevpsfu.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
/* 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
1.88M
{
30
1.88M
    gs_font *font = ppge->font;
31
1.88M
    int index = (int)ppge->index;
32
1.88M
    int code = font->procs.enumerate_glyph(font, &index,
33
1.88M
                                           ppge->glyph_space, pglyph);
34
35
1.88M
    ppge->index = index;
36
1.88M
    return (index == 0 ? 1 : code < 0 ? code : 0);
37
1.88M
}
38
static int
39
enumerate_glyphs_next(psf_glyph_enum_t *ppge, gs_glyph *pglyph)
40
1.00M
{
41
1.00M
    if (ppge->index >= ppge->subset.size)
42
48.8k
        return 1;
43
960k
    *pglyph = ppge->subset.selected.list[ppge->index++];
44
960k
    return 0;
45
1.00M
}
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
38.4k
{
59
38.4k
    ppge->font = font;
60
38.4k
    ppge->subset.selected.list = subset_list;
61
38.4k
    ppge->subset.size = subset_size;
62
38.4k
    ppge->glyph_space = glyph_space;
63
38.4k
    ppge->enumerate_next =
64
38.4k
        (subset_list ? enumerate_glyphs_next :
65
38.4k
         subset_size ? enumerate_range_next : enumerate_font_next);
66
38.4k
    psf_enumerate_glyphs_reset(ppge);
67
38.4k
}
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
28.1k
{
73
13.4M
    for (; ppge->index < ppge->subset.size; ppge->index++)
74
13.4M
        if (ppge->subset.selected.bits[ppge->index >> 3] & (0x80 >> (ppge->index & 7))) {
75
8.60k
            *pglyph = (gs_glyph)(ppge->index++ + GS_MIN_CID_GLYPH);
76
8.60k
            return 0;
77
8.60k
        }
78
19.5k
    return 1;
79
28.1k
}
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
19.8k
{
85
19.8k
    ppge->font = font;
86
19.8k
    ppge->subset.selected.bits = subset_bits;
87
19.8k
    ppge->subset.size = subset_size;
88
19.8k
    ppge->glyph_space = glyph_space;
89
19.8k
    ppge->enumerate_next =
90
19.8k
        (subset_bits ? enumerate_bits_next :
91
19.8k
         subset_size ? enumerate_range_next : enumerate_font_next);
92
19.8k
    psf_enumerate_glyphs_reset(ppge);
93
19.8k
}
94
95
/* Reset a glyph enumeration. */
96
void
97
psf_enumerate_glyphs_reset(psf_glyph_enum_t *ppge)
98
122k
{
99
122k
    ppge->index = 0;
100
122k
}
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
2.91M
{
107
2.91M
    return ppge->enumerate_next(ppge, pglyph);
108
2.91M
}
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
8.62M
{
120
8.62M
    uint i;
121
8.62M
    uint count = *pcount;
122
123
17.2M
    for (i = 0; i < count; ++i) {
124
8.65M
        gs_glyph_info_t info;
125
8.65M
        int code;
126
127
8.65M
        if (count + max_pieces > max_count) {
128
            /* Check first to make sure there is enough room. */
129
8.65M
            code = font->procs.glyph_info(font, glyphs[i], NULL,
130
8.65M
                                          GLYPH_INFO_NUM_PIECES, &info);
131
8.65M
            if (code < 0)
132
2.86k
                continue;
133
8.65M
            if (count + info.num_pieces > max_count)
134
0
                return_error(gs_error_rangecheck);
135
8.65M
        }
136
8.65M
        info.pieces = &glyphs[count];
137
8.65M
        code = font->procs.glyph_info(font, glyphs[i], NULL,
138
8.65M
                                      GLYPH_INFO_NUM_PIECES |
139
8.65M
                                      GLYPH_INFO_PIECES, &info);
140
8.65M
        if (code >= 0)
141
8.65M
            count += info.num_pieces;
142
8.65M
    }
143
8.62M
    *pcount = count;
144
8.62M
    return 0;
145
8.62M
}
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
559k
{
154
559k
    gs_glyph g1 = *(const gs_glyph *)pg1, g2 = *(const gs_glyph *)pg2;
155
156
559k
    return (g1 < g2 ? -1 : g1 > g2 ? 1 : 0);
157
559k
}
158
int
159
psf_sort_glyphs(gs_glyph *glyphs, int count)
160
9.25k
{
161
9.25k
    int i, n;
162
163
9.25k
    qsort(glyphs, count, sizeof(*glyphs), compare_glyphs);
164
182k
    for (i = n = 0; i < count; ++i)
165
172k
        if (i == 0 || glyphs[i] != glyphs[i - 1])
166
172k
            glyphs[n++] = glyphs[i];
167
9.25k
    return n;
168
9.25k
}
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
539k
{
177
539k
    int lo = 0, hi = count - 1;
178
179
539k
    if (hi < 0)
180
0
        return -1;
181
539k
    if (glyph < glyphs[0] || glyph > glyphs[hi])
182
3
        return -1;
183
    /*
184
     * Loop invariants: hi > lo;
185
     * glyphs[lo] <= glyph <= glyphs[hi].
186
     */
187
3.05M
    while (hi - lo > 1) {
188
2.51M
        int mid = (lo + hi) >> 1;
189
190
2.51M
        if (glyph >= glyphs[mid])
191
1.40M
            lo = mid;
192
1.11M
        else
193
1.11M
            hi = mid;
194
2.51M
    }
195
539k
    return (glyph == glyphs[lo] ? lo : glyph == glyphs[hi] ? hi : -1);
196
539k
}
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
84.1k
{
201
84.1k
    return psf_sorted_glyphs_index_of(glyphs, count, glyph) >= 0;
202
84.1k
}
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
7.68k
{
209
7.68k
    uint members = GLYPH_INFO_WIDTH0 << pfont->WMode;
210
7.68k
    gs_glyph glyph;
211
7.68k
    int code, good_glyphs = 0;
212
213
203k
    while ((code = psf_enumerate_glyphs_next(ppge, &glyph)) != 1) {
214
195k
        gs_glyph_data_t gdata;
215
195k
        gs_font_type1 *ignore_font;
216
195k
        gs_glyph_info_t info;
217
218
195k
        if (code < 0)
219
0
            return code;
220
195k
        gdata.memory = pfont->memory;
221
195k
        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
195k
        if (code < 0) {
229
0
            if (code == gs_error_undefined)
230
0
                continue;
231
0
            return code;
232
0
        }
233
195k
        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
195k
        code = pfont->procs.glyph_info((gs_font *)pfont, glyph, NULL,
239
195k
                                       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
195k
        if(code == gs_error_invalidfont || code == gs_error_rangecheck)
246
81
            continue;
247
248
195k
        if (code < 0)
249
0
            return code;
250
195k
        good_glyphs++;
251
195k
    }
252
7.68k
    if(good_glyphs)
253
7.68k
        return 0;
254
0
    else
255
0
        return_error(gs_error_invalidfont);
256
7.68k
}
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
7.65k
{
264
7.65k
    gs_glyph notdef = GS_NO_GLYPH;
265
7.65k
    gs_glyph *subset_glyphs = orig_subset_glyphs;
266
7.65k
    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
7.65k
    {
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
7.65k
        psf_glyph_enum_t genum;
291
7.65k
        int code;
292
293
7.65k
        psf_enumerate_glyphs_begin(&genum, (gs_font *)pfont, subset_glyphs,
294
7.65k
                                    (subset_glyphs ? subset_size : 0),
295
7.65k
                                    GLYPH_SPACE_NAME);
296
7.65k
        code = psf_check_outline_glyphs(pfont, &genum, glyph_data);
297
7.65k
        if (code < 0)
298
0
            return code;
299
7.65k
    }
300
301
7.65k
    {
302
        /*
303
         * Detect the .notdef glyph, needed for subset fonts and to
304
         * eliminate unnecessary Encoding assignments.
305
         */
306
7.65k
        psf_glyph_enum_t genum;
307
7.65k
        gs_glyph glyph;
308
7.65k
        int code;
309
310
7.65k
        psf_enumerate_glyphs_begin(&genum, (gs_font *)pfont, NULL, 0,
311
7.65k
                                    GLYPH_SPACE_NAME);
312
7.65k
        while ((code = psf_enumerate_glyphs_next(&genum, &glyph)) != 1) {
313
7.65k
            if (gs_font_glyph_is_notdef(pfont, glyph)) {
314
7.65k
                notdef = glyph;
315
7.65k
                break;
316
7.65k
            }
317
7.65k
        }
318
7.65k
    }
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
7.65k
    pglyphs->notdef = notdef;
360
7.65k
    pglyphs->subset_glyphs = subset_glyphs;
361
7.65k
    pglyphs->subset_size = subset_size;
362
7.65k
    return 0;
363
7.65k
}