Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_unix/sys/src/cmd/gs/src/gdevpsfu.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
}