1 /* Copyright (C) 2000 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: gdevpsfu.c,v 1.12 2004/11/19 04:39:11 ray Exp $ */
18 /* PostScript/PDF font writing utilities */
19 #include "memory_.h"
20 #include <stdlib.h> /* for qsort */
21 #include "gx.h"
22 #include "gserrors.h"
23 #include "gsmatrix.h" /* for gxfont.h */
24 #include "gxfont.h"
25 #include "gdevpsf.h"
26
27 /* Begin enumerating the glyphs in a font or a font subset. */
28 private int
enumerate_font_next(psf_glyph_enum_t * ppge,gs_glyph * pglyph)29 enumerate_font_next(psf_glyph_enum_t *ppge, gs_glyph *pglyph)
30 {
31 gs_font *font = ppge->font;
32 int index = (int)ppge->index;
33 int code = font->procs.enumerate_glyph(font, &index,
34 ppge->glyph_space, pglyph);
35
36 ppge->index = index;
37 return (index == 0 ? 1 : code < 0 ? code : 0);
38 }
39 private int
enumerate_glyphs_next(psf_glyph_enum_t * ppge,gs_glyph * pglyph)40 enumerate_glyphs_next(psf_glyph_enum_t *ppge, gs_glyph *pglyph)
41 {
42 if (ppge->index >= ppge->subset.size)
43 return 1;
44 *pglyph = ppge->subset.selected.list[ppge->index++];
45 return 0;
46 }
47 private int
enumerate_range_next(psf_glyph_enum_t * ppge,gs_glyph * pglyph)48 enumerate_range_next(psf_glyph_enum_t *ppge, gs_glyph *pglyph)
49 {
50 if (ppge->index >= ppge->subset.size)
51 return 1;
52 *pglyph = (gs_glyph)(ppge->index++ + gs_min_cid_glyph);
53 return 0;
54 }
55 void
psf_enumerate_list_begin(psf_glyph_enum_t * ppge,gs_font * font,const gs_glyph * subset_list,uint subset_size,gs_glyph_space_t glyph_space)56 psf_enumerate_list_begin(psf_glyph_enum_t *ppge, gs_font *font,
57 const gs_glyph *subset_list, uint subset_size,
58 gs_glyph_space_t glyph_space)
59 {
60 ppge->font = font;
61 ppge->subset.selected.list = subset_list;
62 ppge->subset.size = subset_size;
63 ppge->glyph_space = glyph_space;
64 ppge->enumerate_next =
65 (subset_list ? enumerate_glyphs_next :
66 subset_size ? enumerate_range_next : enumerate_font_next);
67 psf_enumerate_glyphs_reset(ppge);
68 }
69
70 /* Begin enumerating CID or TT glyphs in a subset given by a bit vector. */
71 private int
enumerate_bits_next(psf_glyph_enum_t * ppge,gs_glyph * pglyph)72 enumerate_bits_next(psf_glyph_enum_t *ppge, gs_glyph *pglyph)
73 {
74 for (; ppge->index < ppge->subset.size; ppge->index++)
75 if (ppge->subset.selected.bits[ppge->index >> 3] & (0x80 >> (ppge->index & 7))) {
76 *pglyph = (gs_glyph)(ppge->index++ + gs_min_cid_glyph);
77 return 0;
78 }
79 return 1;
80 }
81 void
psf_enumerate_bits_begin(psf_glyph_enum_t * ppge,gs_font * font,const byte * subset_bits,uint subset_size,gs_glyph_space_t glyph_space)82 psf_enumerate_bits_begin(psf_glyph_enum_t *ppge, gs_font *font,
83 const byte *subset_bits, uint subset_size,
84 gs_glyph_space_t glyph_space)
85 {
86 ppge->font = font;
87 ppge->subset.selected.bits = subset_bits;
88 ppge->subset.size = subset_size;
89 ppge->glyph_space = glyph_space;
90 ppge->enumerate_next =
91 (subset_bits ? enumerate_bits_next :
92 subset_size ? enumerate_range_next : enumerate_font_next);
93 psf_enumerate_glyphs_reset(ppge);
94 }
95
96 /* Reset a glyph enumeration. */
97 void
psf_enumerate_glyphs_reset(psf_glyph_enum_t * ppge)98 psf_enumerate_glyphs_reset(psf_glyph_enum_t *ppge)
99 {
100 ppge->index = 0;
101 }
102
103 /* Enumerate the next glyph in a font or a font subset. */
104 /* Return 0 if more glyphs, 1 if done, <0 if error. */
105 int
psf_enumerate_glyphs_next(psf_glyph_enum_t * ppge,gs_glyph * pglyph)106 psf_enumerate_glyphs_next(psf_glyph_enum_t *ppge, gs_glyph *pglyph)
107 {
108 return ppge->enumerate_next(ppge, pglyph);
109 }
110
111 /*
112 * Add composite glyph pieces to a list of glyphs. Does not sort or
113 * remove duplicates. max_pieces is the maximum number of pieces that a
114 * single glyph can have: if this value is not known, the caller should
115 * use max_count.
116 */
117 int
psf_add_subset_pieces(gs_glyph * glyphs,uint * pcount,uint max_count,uint max_pieces,gs_font * font)118 psf_add_subset_pieces(gs_glyph *glyphs, uint *pcount, uint max_count,
119 uint max_pieces, gs_font *font)
120 {
121 uint i;
122 uint count = *pcount;
123
124 for (i = 0; i < count; ++i) {
125 gs_glyph_info_t info;
126 int code;
127
128 if (count + max_pieces > max_count) {
129 /* Check first to make sure there is enough room. */
130 code = font->procs.glyph_info(font, glyphs[i], NULL,
131 GLYPH_INFO_NUM_PIECES, &info);
132 if (code < 0)
133 continue;
134 if (count + info.num_pieces > max_count)
135 return_error(gs_error_rangecheck);
136 }
137 info.pieces = &glyphs[count];
138 code = font->procs.glyph_info(font, glyphs[i], NULL,
139 GLYPH_INFO_NUM_PIECES |
140 GLYPH_INFO_PIECES, &info);
141 if (code >= 0)
142 count += info.num_pieces;
143 }
144 *pcount = count;
145 return 0;
146 }
147
148 /*
149 * Sort a list of glyphs and remove duplicates. Return the number of glyphs
150 * in the result.
151 */
152 private int
compare_glyphs(const void * pg1,const void * pg2)153 compare_glyphs(const void *pg1, const void *pg2)
154 {
155 gs_glyph g1 = *(const gs_glyph *)pg1, g2 = *(const gs_glyph *)pg2;
156
157 return (g1 < g2 ? -1 : g1 > g2 ? 1 : 0);
158 }
159 int
psf_sort_glyphs(gs_glyph * glyphs,int count)160 psf_sort_glyphs(gs_glyph *glyphs, int count)
161 {
162 int i, n;
163
164 qsort(glyphs, count, sizeof(*glyphs), compare_glyphs);
165 for (i = n = 0; i < count; ++i)
166 if (i == 0 || glyphs[i] != glyphs[i - 1])
167 glyphs[n++] = glyphs[i];
168 return n;
169 }
170
171 /*
172 * Return the index of a given glyph in a sorted list of glyphs, or -1
173 * if the glyph is not present.
174 */
175 int
psf_sorted_glyphs_index_of(const gs_glyph * glyphs,int count,gs_glyph glyph)176 psf_sorted_glyphs_index_of(const gs_glyph *glyphs, int count, gs_glyph glyph)
177 {
178 int lo = 0, hi = count - 1;
179
180 if (hi < 0)
181 return -1;
182 if (glyph < glyphs[0] || glyph > glyphs[hi])
183 return -1;
184 /*
185 * Loop invariants: hi > lo;
186 * glyphs[lo] <= glyph <= glyphs[hi].
187 */
188 while (hi - lo > 1) {
189 int mid = (lo + hi) >> 1;
190
191 if (glyph >= glyphs[mid])
192 lo = mid;
193 else
194 hi = mid;
195 }
196 return (glyph == glyphs[lo] ? lo : glyph == glyphs[hi] ? hi : -1);
197 }
198 /* Determine whether a sorted list of glyphs includes a given glyph. */
199 bool
psf_sorted_glyphs_include(const gs_glyph * glyphs,int count,gs_glyph glyph)200 psf_sorted_glyphs_include(const gs_glyph *glyphs, int count, gs_glyph glyph)
201 {
202 return psf_sorted_glyphs_index_of(glyphs, count, glyph) >= 0;
203 }
204
205 /* Check that all selected glyphs can be written. */
206 int
psf_check_outline_glyphs(gs_font_base * pfont,psf_glyph_enum_t * ppge,glyph_data_proc_t glyph_data)207 psf_check_outline_glyphs(gs_font_base *pfont, psf_glyph_enum_t *ppge,
208 glyph_data_proc_t glyph_data)
209 {
210 uint members = GLYPH_INFO_WIDTH0 << pfont->WMode;
211 gs_glyph glyph;
212 int code;
213
214 while ((code = psf_enumerate_glyphs_next(ppge, &glyph)) != 1) {
215 gs_glyph_data_t gdata;
216 gs_font_type1 *ignore_font;
217 gs_glyph_info_t info;
218
219 if (code < 0)
220 return code;
221 gdata.memory = pfont->memory;
222 code = glyph_data(pfont, glyph, &gdata, &ignore_font);
223 /*
224 * If the glyph isn't defined by a CharString, glyph_data will
225 * return a typecheck error. But if there's merely a glyph in
226 * in the Encoding that isn't defined, glyph_data will return an
227 * undefined error, which is OK.
228 */
229 if (code < 0) {
230 if (code == gs_error_undefined)
231 continue;
232 return code;
233 }
234 gs_glyph_data_free(&gdata, "psf_check_outline_glyphs");
235 /*
236 * If the font has a CDevProc or calls a non-standard OtherSubr,
237 * glyph_info will return a rangecheck error.
238 */
239 code = pfont->procs.glyph_info((gs_font *)pfont, glyph, NULL,
240 members, &info);
241 if (code < 0)
242 return code;
243 }
244 return 0;
245 }
246
247 /* Gather glyph information for a Type 1 or Type 2 font. */
248 int
psf_get_outline_glyphs(psf_outline_glyphs_t * pglyphs,gs_font_base * pfont,gs_glyph * orig_subset_glyphs,uint orig_subset_size,glyph_data_proc_t glyph_data)249 psf_get_outline_glyphs(psf_outline_glyphs_t *pglyphs, gs_font_base *pfont,
250 gs_glyph *orig_subset_glyphs, uint orig_subset_size,
251 glyph_data_proc_t glyph_data)
252 {
253 gs_glyph notdef = gs_no_glyph;
254 gs_glyph *subset_glyphs = orig_subset_glyphs;
255 uint subset_size = orig_subset_size;
256
257 if (subset_glyphs) {
258 if (subset_size > countof(pglyphs->subset_data))
259 return_error(gs_error_limitcheck);
260 memcpy(pglyphs->subset_data, orig_subset_glyphs,
261 sizeof(gs_glyph) * subset_size);
262 subset_glyphs = pglyphs->subset_data;
263 }
264
265 {
266 /*
267 * Make sure that this font can be written out. Specifically, it
268 * must have no CharStrings defined by PostScript procedures, no
269 * non-standard OtherSubrs, and no CDevProc.
270 */
271 psf_glyph_enum_t genum;
272 int code;
273
274 psf_enumerate_glyphs_begin(&genum, (gs_font *)pfont, subset_glyphs,
275 (subset_glyphs ? subset_size : 0),
276 GLYPH_SPACE_NAME);
277 code = psf_check_outline_glyphs(pfont, &genum, glyph_data);
278 if (code < 0)
279 return code;
280 }
281
282 {
283 /*
284 * Detect the .notdef glyph, needed for subset fonts and to
285 * eliminate unnecessary Encoding assignments.
286 */
287 psf_glyph_enum_t genum;
288 gs_glyph glyph;
289 int code;
290
291 psf_enumerate_glyphs_begin(&genum, (gs_font *)pfont, NULL, 0,
292 GLYPH_SPACE_NAME);
293 while ((code = psf_enumerate_glyphs_next(&genum, &glyph)) != 1) {
294 if (gs_font_glyph_is_notdef(pfont, glyph)) {
295 notdef = glyph;
296 break;
297 }
298 }
299 }
300
301 if (subset_glyphs) {
302 /*
303 * For subset fonts, we must ensure that characters referenced
304 * by seac are also included. Note that seac creates at most
305 * 2 pieces.
306 */
307 int code = psf_add_subset_pieces(subset_glyphs, &subset_size,
308 countof(pglyphs->subset_data) - 1, 2,
309 (gs_font *)pfont);
310 uint keep_size, i;
311
312 if (code < 0)
313 return code;
314 /* Subset fonts require .notdef. */
315 if (notdef == gs_no_glyph)
316 return_error(gs_error_rangecheck);
317 /* Remove undefined glyphs. */
318 for (i = 0, keep_size = 0; i < subset_size; ++i) {
319 gs_glyph_info_t info;
320 gs_glyph glyph = subset_glyphs[i];
321
322 /*
323 * The documentation for the glyph_info procedure says that
324 * using members = 0 is an inexpensive way to find out
325 * whether a given glyph exists, but the implementations
326 * don't actually do this. Request an inexpensive value.
327 */
328 if (pfont->procs.glyph_info((gs_font *)pfont, glyph, NULL,
329 GLYPH_INFO_NUM_PIECES, &info) >= 0)
330 subset_glyphs[keep_size++] = glyph;
331 }
332 subset_size = keep_size;
333 /* Sort the glyphs. Make sure .notdef is included. */
334 subset_glyphs[subset_size++] = notdef;
335 subset_size = psf_sort_glyphs(subset_glyphs, subset_size);
336 }
337
338 pglyphs->notdef = notdef;
339 pglyphs->subset_glyphs = subset_glyphs;
340 pglyphs->subset_size = subset_size;
341 return 0;
342 }
343