/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 | } |