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/planix-v0/sys/src/cmd/gs/src/gstype42.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) 1996, 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: gstype42.c,v 1.51 2005/03/15 11:36:37 igor Exp $ */
18
/* Type 42 (TrueType) font library routines */
19
#include "memory_.h"
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gsstruct.h"
23
#include "gsccode.h"
24
#include "gsline.h"		/* for gs_imager_setflat */
25
#include "gsmatrix.h"
26
#include "gsutil.h"
27
#include "gxchrout.h"
28
#include "gxfixed.h"		/* for gxpath.h */
29
#include "gxpath.h"
30
#include "gxfont.h"
31
#include "gxfont42.h"
32
#include "gxttf.h"
33
#include "gxttfb.h"
34
#include "gxfcache.h"
35
#include "gxistate.h"
36
#include "stream.h"
37
 
38
void abort(void);
39
 
40
/* Structure descriptor */
41
public_st_gs_font_type42();
42
 
43
/* Forward references */
44
private int append_outline_fitted(uint glyph_index, const gs_matrix * pmat,
45
	       gx_path * ppath, cached_fm_pair * pair, 
46
	       const gs_log2_scale_point * pscale, bool design_grid);
47
private uint default_get_glyph_index(gs_font_type42 *pfont, gs_glyph glyph);
48
private int default_get_outline(gs_font_type42 *pfont, uint glyph_index,
49
				gs_glyph_data_t *pgd);
50
 
51
/* Set up a pointer to a substring of the font data. */
52
/* Free variables: pfont, string_proc. */
53
#define ACCESS(base, length, vptr)\
54
  BEGIN\
55
    code = (*string_proc)(pfont, (ulong)(base), length, &vptr);\
56
    if ( code < 0 ) return code;\
57
    if ( code > 0 ) return_error(gs_error_invalidfont);\
58
  END
59
 
60
/* Get 2- or 4-byte quantities from a table. */
61
#define U8(p) ((uint)((p)[0]))
62
#define S8(p) (int)((U8(p) ^ 0x80) - 0x80)
63
#define U16(p) (((uint)((p)[0]) << 8) + (p)[1])
64
#define S16(p) (int)((U16(p) ^ 0x8000) - 0x8000)
65
#define u32(p) get_u32_msb(p)
66
 
67
/* ---------------- Font level ---------------- */
68
 
69
GS_NOTIFY_PROC(gs_len_glyphs_release);
70
 
71
/* Get the offset to a glyph using the loca table */
72
private inline ulong
73
get_glyph_offset(gs_font_type42 *pfont, uint glyph_index) 
74
{
75
    int (*string_proc)(gs_font_type42 *, ulong, uint, const byte **) =
76
	pfont->data.string_proc;
77
    const byte *ploca;
78
    ulong result;
79
    int code;		/* hidden variable used by ACCESS */
80
 
81
    if (pfont->data.indexToLocFormat) {
82
	ACCESS(pfont->data.loca + glyph_index * 4, 4, ploca);
83
	result = u32(ploca);
84
    } else {
85
	ACCESS(pfont->data.loca + glyph_index * 2, 2, ploca);
86
	result = (ulong) U16(ploca) << 1;
87
    }
88
    return result;
89
}
90
 
91
/*
92
 * Initialize the cached values in a Type 42 font.
93
 * Note that this initializes the type42_data procedures other than
94
 * string_proc, and the font procedures as well.
95
 */
96
int
97
gs_type42_font_init(gs_font_type42 * pfont)
98
{
99
    int (*string_proc)(gs_font_type42 *, ulong, uint, const byte **) =
100
	pfont->data.string_proc;
101
    const byte *OffsetTable;
102
    uint numTables;
103
    const byte *TableDirectory;
104
    uint i;
105
    int code;
106
    byte head_box[8];
107
    ulong loca_size = 0;
108
    ulong glyph_start, glyph_offset, glyph_length;
109
 
110
    ACCESS(0, 12, OffsetTable);
111
    {
112
	static const byte version1_0[4] = {0, 1, 0, 0};
113
	static const byte version_true[4] = {'t', 'r', 'u', 'e'};
114
 
115
	if (memcmp(OffsetTable, version1_0, 4) &&
116
	    memcmp(OffsetTable, version_true, 4))
117
	    return_error(gs_error_invalidfont);
118
    }
119
    numTables = U16(OffsetTable + 4);
120
    ACCESS(12, numTables * 16, TableDirectory);
121
    /* Clear all non-client-supplied data. */
122
    {
123
	void *proc_data = pfont->data.proc_data;
124
 
125
	memset(&pfont->data, 0, sizeof(pfont->data));
126
	pfont->data.string_proc = string_proc;
127
	pfont->data.proc_data = proc_data;
128
    }
129
    for (i = 0; i < numTables; ++i) {
130
	const byte *tab = TableDirectory + i * 16;
131
	ulong offset = u32(tab + 8);
132
 
133
	if (!memcmp(tab, "cmap", 4))
134
	    pfont->data.cmap = offset;
135
	else if (!memcmp(tab, "glyf", 4))
136
	    pfont->data.glyf = offset;
137
	else if (!memcmp(tab, "head", 4)) {
138
	    const byte *head;
139
 
140
	    ACCESS(offset, 54, head);
141
	    pfont->data.unitsPerEm = U16(head + 18);
142
	    memcpy(head_box, head + 36, 8);
143
	    pfont->data.indexToLocFormat = U16(head + 50);
144
	} else if (!memcmp(tab, "hhea", 4)) {
145
	    const byte *hhea;
146
 
147
	    ACCESS(offset, 36, hhea);
148
	    pfont->data.metrics[0].numMetrics = U16(hhea + 34);
149
	} else if (!memcmp(tab, "hmtx", 4)) {
150
	    pfont->data.metrics[0].offset = offset;
151
	    pfont->data.metrics[0].length = (uint)u32(tab + 12);
152
	} else if (!memcmp(tab, "loca", 4)) {
153
	    pfont->data.loca = offset;
154
	    loca_size = u32(tab + 12);
155
	} else if (!memcmp(tab, "maxp", 4)) {
156
	    const byte *maxp;
157
 
158
	    ACCESS(offset, 30, maxp);
159
	    pfont->data.trueNumGlyphs = U16(maxp + 4);
160
	} else if (!memcmp(tab, "vhea", 4)) {
161
	    const byte *vhea;
162
 
163
	    ACCESS(offset, 36, vhea);
164
	    pfont->data.metrics[1].numMetrics = U16(vhea + 34);
165
	} else if (!memcmp(tab, "vmtx", 4)) {
166
	    pfont->data.metrics[1].offset = offset;
167
	    pfont->data.metrics[1].length = (uint)u32(tab + 12);
168
	}
169
    }
170
    loca_size >>= pfont->data.indexToLocFormat + 1;
171
    pfont->data.numGlyphs = (loca_size == 0 ? 0 : loca_size - 1);
172
    /* Now build the len_glyphs array since 'loca' may not be properly sorted */
173
    pfont->data.len_glyphs = (uint *)gs_alloc_bytes(pfont->memory, pfont->data.numGlyphs * sizeof(uint),
174
	    "gs_type42_font");
175
    if (pfont->data.len_glyphs == 0)
176
	return_error(gs_error_VMerror);
177
    gs_font_notify_register((gs_font *)pfont, gs_len_glyphs_release, (void *)pfont);
178
 
179
    /* The 'loca' may not be in order, so we construct a glyph length array */
180
    /* Since 'loca' is usually sorted, first try the simple linear scan to  */
181
    /* avoid the need to perform the more expensive process. */
182
    glyph_start = get_glyph_offset(pfont, 0);
183
    for (i=1; i < loca_size; i++) {
184
	glyph_offset = get_glyph_offset(pfont, i);
185
	glyph_length = glyph_offset - glyph_start;
186
	if (glyph_length > 0x80000000)
187
	    break;				/* out of order loca */
188
	pfont->data.len_glyphs[i-1] = glyph_length;
189
	glyph_start = glyph_offset;
190
    }
191
    if (i < loca_size) {
192
        uint j;
193
	ulong trial_glyph_length;
194
        /*
195
         * loca was out of order, build the len_glyphs the hard way      
196
	 * Assume that some of the len_glyphs built so far may be wrong 
197
	 * For each starting offset, find the next higher ending offset
198
	 * Note that doing this means that there can only be zero length
199
	 * glyphs that have loca table offset equal to the last 'dummy'
200
         * entry. Otherwise we assume that it is a duplicated entry.
201
	 */
202
	for (i=0; i < loca_size-1; i++) {
203
	    glyph_start = get_glyph_offset(pfont, i);
204
	    for (j=1, glyph_length = 0x80000000; j<loca_size; j++) {
205
		glyph_offset = get_glyph_offset(pfont, j);
206
		trial_glyph_length = glyph_offset - glyph_start;
207
		if ((trial_glyph_length > 0) && (trial_glyph_length < glyph_length))
208
		    glyph_length = trial_glyph_length;
209
	    }
210
	    pfont->data.len_glyphs[i] = glyph_length < 0x80000000 ? glyph_length : 0;
211
	}
212
    }
213
    /*
214
     * If the font doesn't have a valid FontBBox, compute one from the
215
     * 'head' information.  Since the Adobe PostScript driver sometimes
216
     * outputs garbage FontBBox values, we use a "reasonableness" check
217
     * here.
218
     */
219
    if (pfont->FontBBox.p.x >= pfont->FontBBox.q.x ||
220
	pfont->FontBBox.p.y >= pfont->FontBBox.q.y ||
221
	pfont->FontBBox.p.x < -0.5 || pfont->FontBBox.p.x > 0.5 ||
222
	pfont->FontBBox.p.y < -0.5 || pfont->FontBBox.p.y > 0.5
223
	) {
224
	float upem = (float)pfont->data.unitsPerEm;
225
 
226
	if (upem == 0)
227
		abort(); /* "gs_type42_init_font: 0 pfont->data.unitsPerEm" */
228
	pfont->FontBBox.p.x = S16(head_box) / upem;
229
	pfont->FontBBox.p.y = S16(head_box + 2) / upem;
230
	pfont->FontBBox.q.x = S16(head_box + 4) / upem;
231
	pfont->FontBBox.q.y = S16(head_box + 6) / upem;
232
    }
233
    pfont->data.warning_patented = false;
234
    pfont->data.warning_bad_instruction = false;
235
    pfont->data.get_glyph_index = default_get_glyph_index;
236
    pfont->data.get_outline = default_get_outline;
237
    pfont->data.get_metrics = gs_type42_default_get_metrics;
238
    pfont->procs.glyph_outline = gs_type42_glyph_outline;
239
    pfont->procs.glyph_info = gs_type42_glyph_info;
240
    pfont->procs.enumerate_glyph = gs_type42_enumerate_glyph;
241
    return 0;
242
}
243
 
244
int
245
gs_len_glyphs_release(void *data, void *event)
246
{   
247
    gs_font_type42 *pfont = (gs_font_type42 *)data;
248
 
249
    gs_font_notify_unregister((gs_font *)pfont, gs_len_glyphs_release, (void *)data);
250
    gs_free_object(pfont->memory, pfont->data.len_glyphs, "gs_len_glyphs_release");
251
    return 0;
252
}
253
 
254
/* ---------------- Glyph level ---------------- */
255
 
256
double
257
recipunitsperem(gs_font_type42 *pfont)
258
{
259
	if (pfont->data.unitsPerEm == 0)
260
		abort(); /* "recipunitsperem: 0 pfont->data.unitsPerEm" */
261
	return 1. / pfont->data.unitsPerEm;
262
}
263
 
264
/*
265
 * Parse the definition of one component of a composite glyph.  We don't
266
 * bother to parse the component index, since the caller can do this so
267
 * easily.
268
 */
269
private void
270
parse_component(const byte **pdata, uint *pflags, gs_matrix_fixed *psmat,
271
		int *pmp /*[2], may be null*/, const gs_font_type42 *pfont,
272
		const gs_matrix_fixed *pmat)
273
{
274
    const byte *gdata = *pdata;
275
    uint flags;
276
    double factor = recipunitsperem(pfont);
277
    gs_matrix_fixed mat;
278
    gs_matrix scale_mat;
279
 
280
    flags = U16(gdata);
281
    gdata += 4;
282
    mat = *pmat;
283
    if (flags & TT_CG_ARGS_ARE_XY_VALUES) {
284
	int arg1, arg2;
285
	gs_fixed_point pt;
286
 
287
	if (flags & TT_CG_ARGS_ARE_WORDS)
288
	    arg1 = S16(gdata), arg2 = S16(gdata + 2), gdata += 4;
289
	else
290
	    arg1 = S8(gdata), arg2 = S8(gdata + 1), gdata += 2;
291
	if (flags & TT_CG_ROUND_XY_TO_GRID) {
292
	    /* We should do something here, but we don't. */
293
	}
294
	gs_point_transform2fixed(pmat, arg1 * factor,
295
				 arg2 * factor, &pt);
296
	/****** HACK: WE KNOW ABOUT FIXED MATRICES ******/
297
	mat.tx = fixed2float(mat.tx_fixed = pt.x);
298
	mat.ty = fixed2float(mat.ty_fixed = pt.y);
299
	if (pmp)
300
	    pmp[0] = pmp[1] = -1;
301
    } else {
302
	if (flags & TT_CG_ARGS_ARE_WORDS) {
303
	    if (pmp)
304
		pmp[0] = U16(gdata), pmp[1] = S16(gdata + 2);
305
	    gdata += 4;
306
	} else {
307
	    if (pmp)
308
		pmp[0] = U8(gdata), pmp[1] = U8(gdata + 1);
309
	    gdata += 2;
310
	}
311
    }
312
#define S2_14(p) (S16(p) / 16384.0)
313
    if (flags & TT_CG_HAVE_SCALE) {
314
	scale_mat.xx = scale_mat.yy = S2_14(gdata);
315
	scale_mat.xy = scale_mat.yx = 0;
316
	gdata += 2;
317
    } else if (flags & TT_CG_HAVE_XY_SCALE) {
318
	scale_mat.xx = S2_14(gdata);
319
	scale_mat.yy = S2_14(gdata + 2);
320
	scale_mat.xy = scale_mat.yx = 0;
321
	gdata += 4;
322
    } else if (flags & TT_CG_HAVE_2X2) {
323
	scale_mat.xx = S2_14(gdata);
324
	scale_mat.xy = S2_14(gdata + 2);
325
	scale_mat.yx = S2_14(gdata + 4);
326
	scale_mat.yy = S2_14(gdata + 6);
327
	gdata += 8;
328
    } else
329
	goto no_scale;
330
#undef S2_14
331
    scale_mat.tx = 0;
332
    scale_mat.ty = 0;
333
    /* The scale doesn't affect mat.t{x,y}, so we don't */
334
    /* need to update the fixed components. */
335
    gs_matrix_multiply(&scale_mat, (const gs_matrix *)&mat,
336
		       (gs_matrix *)&mat);
337
no_scale:
338
    *pdata = gdata;
339
    *pflags = flags;
340
    *psmat = mat;
341
}
342
 
343
/* Compute the total number of points in a (possibly composite) glyph. */
344
private int
345
total_points(gs_font_type42 *pfont, uint glyph_index)
346
{
347
    gs_glyph_data_t glyph_data;
348
    int code;
349
    int ocode;
350
    const byte *gdata;
351
    int total;
352
 
353
    glyph_data.memory = pfont->memory;
354
    ocode = pfont->data.get_outline(pfont, glyph_index, &glyph_data);
355
    if (ocode < 0)
356
	return ocode;
357
    if (glyph_data.bits.size == 0)
358
	return 0;
359
    gdata = glyph_data.bits.data;
360
    if (S16(gdata) != -1) {
361
	/* This is a simple glyph. */
362
	int numContours = S16(gdata);
363
	const byte *pends = gdata + 10;
364
	const byte *pinstr = pends + numContours * 2;
365
 
366
	total = (numContours == 0 ? 0 : U16(pinstr - 2) + 1);
367
    } else {
368
	/* This is a composite glyph.  Add up the components. */
369
	uint flags;
370
	gs_matrix_fixed mat;
371
 
372
	gdata += 10;
373
	memset(&mat, 0, sizeof(mat)); /* arbitrary */
374
	total = 0;
375
	do {
376
	    code = total_points(pfont, U16(gdata + 2));
377
	    if (code < 0)
378
		return code;
379
	    total += code;
380
	    parse_component(&gdata, &flags, &mat, NULL, pfont, &mat);
381
	}
382
	while (flags & TT_CG_MORE_COMPONENTS);
383
    }
384
    gs_glyph_data_free(&glyph_data, "total_points");
385
    return total;
386
}
387
 
388
/*
389
 * Define the default implementation for getting the glyph index from a
390
 * gs_glyph.  This is trivial for integer ("CID" but representing a GID)
391
 * gs_glyph values, and not implemented for name glyphs.
392
 */
393
private uint
394
default_get_glyph_index(gs_font_type42 *pfont, gs_glyph glyph)
395
{
396
    return (glyph < GS_MIN_CID_GLYPH ? 0 : /* undefined */
397
	    glyph - GS_MIN_CID_GLYPH);
398
}
399
 
400
/* Define the default implementation for getting the outline data for */
401
/* a glyph, using indexToLocFormat and the loca and glyf tables. */
402
/* Set pglyph->data = 0 if the glyph is empty. */
403
private int
404
default_get_outline(gs_font_type42 * pfont, uint glyph_index,
405
		    gs_glyph_data_t *pgd)
406
{
407
    int (*string_proc) (gs_font_type42 *, ulong, uint, const byte **) =
408
	pfont->data.string_proc;
409
    ulong glyph_start;
410
    uint glyph_length;
411
    int code;
412
 
413
    glyph_start = get_glyph_offset(pfont, glyph_index);
414
    glyph_length = pfont->data.len_glyphs[glyph_index];
415
    if (glyph_length == 0)
416
	gs_glyph_data_from_null(pgd);
417
    else {
418
	const byte *data;
419
	byte *buf;
420
 
421
	code = (*string_proc)(pfont, (ulong)(pfont->data.glyf + glyph_start),
422
			      glyph_length, &data);
423
	if (code < 0) 
424
	    return code;
425
	if (code == 0)
426
	    gs_glyph_data_from_string(pgd, data, glyph_length, NULL);
427
	else {
428
	    /*
429
	     * The glyph is segmented in sfnts. 
430
	     * It is not allowed with Type 42 specification.
431
	     * Perhaps we can handle it (with a low performance),
432
	     * making a contiguous copy.
433
	     */
434
	    uint left = glyph_length;
435
 
436
	    /* 'code' is the returned length */
437
	    buf = (byte *)gs_alloc_string(pgd->memory, glyph_length, "default_get_outline");
438
	    if (buf == 0)
439
		return_error(gs_error_VMerror);
440
	    gs_glyph_data_from_string(pgd, buf, glyph_length, (gs_font *)pfont);
441
	    for (;;) {
442
		memcpy(buf + glyph_length - left, data, code);
443
		if (!(left -= code))
444
		    return 0;
445
		code = (*string_proc)(pfont, (ulong)(pfont->data.glyf + glyph_start + 
446
		              glyph_length - left), left, &data);
447
		if (code < 0) 
448
		    return code;
449
		if (code == 0) 
450
		    code = left;
451
	    }
452
	}
453
    }
454
    return 0;
455
}
456
 
457
/* Take outline data from a True Type font file. */
458
int
459
gs_type42_get_outline_from_TT_file(gs_font_type42 * pfont, stream *s, uint glyph_index,
460
		gs_glyph_data_t *pgd)
461
{
462
    uchar lbuf[8];
463
    ulong glyph_start;
464
    uint glyph_length, count;
465
 
466
    /* fixme: Since this function is being called multiple times per glyph,
467
     * we should cache glyph data in a buffer associated with the font.
468
     */
469
    if (pfont->data.indexToLocFormat) {
470
	sseek(s, pfont->data.loca + glyph_index * 4);
471
        sgets(s, lbuf, 8, &count);
472
	if (count < 8)
473
	    return_error(gs_error_invalidfont);
474
	glyph_start = u32(lbuf);
475
	glyph_length = u32(lbuf + 4) - glyph_start;
476
    } else {
477
	sseek(s, pfont->data.loca + glyph_index * 2);
478
        sgets(s, lbuf, 4, &count);
479
	if (count < 4)
480
	    return_error(gs_error_invalidfont);
481
	glyph_start = (ulong) U16(lbuf) << 1;
482
	glyph_length = ((ulong) U16(lbuf + 2) << 1) - glyph_start;
483
    }
484
    if (glyph_length == 0)
485
	gs_glyph_data_from_null(pgd);
486
    else {
487
	byte *buf;
488
 
489
	sseek(s, pfont->data.glyf + glyph_start);
490
	buf = (byte *)gs_alloc_string(pgd->memory, glyph_length, "default_get_outline");
491
	if (buf == 0)
492
	    return_error(gs_error_VMerror);
493
	gs_glyph_data_from_string(pgd, buf, glyph_length, (gs_font *)pfont);
494
        sgets(s, buf, glyph_length, &count);
495
	if (count < glyph_length)
496
	    return_error(gs_error_invalidfont);
497
    }
498
    return 0;
499
}
500
 
501
/* Parse a glyph into pieces, if any. */
502
private int
503
parse_pieces(gs_font_type42 *pfont, gs_glyph glyph, gs_glyph *pieces,
504
	     int *pnum_pieces)
505
{
506
    uint glyph_index = (glyph >= GS_MIN_GLYPH_INDEX 
507
			? glyph - GS_MIN_GLYPH_INDEX 
508
			: pfont->data.get_glyph_index(pfont, glyph));
509
    gs_glyph_data_t glyph_data;
510
    int code;
511
 
512
    glyph_data.memory = pfont->memory;
513
    code = pfont->data.get_outline(pfont, glyph_index, &glyph_data);
514
    if (code < 0)
515
	return code;
516
    if (glyph_data.bits.size != 0 && S16(glyph_data.bits.data) == -1) {
517
	/* This is a composite glyph. */
518
	int i = 0;
519
	uint flags = TT_CG_MORE_COMPONENTS;
520
	const byte *gdata = glyph_data.bits.data + 10;
521
	gs_matrix_fixed mat;
522
 
523
	memset(&mat, 0, sizeof(mat)); /* arbitrary */
524
	for (i = 0; flags & TT_CG_MORE_COMPONENTS; ++i) {
525
	    if (pieces)
526
		pieces[i] = U16(gdata + 2) + GS_MIN_GLYPH_INDEX;
527
	    parse_component(&gdata, &flags, &mat, NULL, pfont, &mat);
528
	}
529
	*pnum_pieces = i;
530
    } else
531
	*pnum_pieces = 0;
532
    gs_glyph_data_free(&glyph_data, "parse_pieces");
533
    return 0;
534
}
535
 
536
/* Define the font procedures for a Type 42 font. */
537
int
538
gs_type42_glyph_outline(gs_font *font, int WMode, gs_glyph glyph, const gs_matrix *pmat,
539
			gx_path *ppath, double sbw[4])
540
{
541
    gs_font_type42 *const pfont = (gs_font_type42 *)font;
542
    uint glyph_index = (glyph >= GS_MIN_GLYPH_INDEX 
543
		? glyph - GS_MIN_GLYPH_INDEX 
544
		: pfont->data.get_glyph_index(pfont, glyph));
545
    gs_fixed_point origin;
546
    int code;
547
    gs_glyph_info_t info;
548
    static const gs_matrix imat = { identity_matrix_body };
549
    bool design_grid = true;
550
    const gs_log2_scale_point log2_scale = {0, 0}; 
551
    /* fixme : The subpixel numbers doesn't pass through the font_proc_glyph_outline interface.
552
       High level devices can't get a proper grid fitting with AlignToPixels = 1.
553
       Currently font_proc_glyph_outline is only used by pdfwrite for computing a
554
       character bbox, which doesn't need a grid fitting.
555
       We apply design grid here.
556
     */
557
    cached_fm_pair *pair;
558
    code = gx_lookup_fm_pair(font, pmat, &log2_scale, design_grid, &pair);
559
 
560
    if (code < 0)
561
	return code;
562
    if (pmat == 0)
563
	pmat = &imat;
564
    if ((code = gx_path_current_point(ppath, &origin)) < 0 ||
565
	(code = append_outline_fitted(glyph_index, pmat, ppath, pair, 
566
					&log2_scale, design_grid)) < 0 ||
567
	(code = font->procs.glyph_info(font, glyph, pmat,
568
				       GLYPH_INFO_WIDTH0 << WMode, &info)) < 0
569
	)
570
	return code;
571
    return gx_path_add_point(ppath, origin.x + float2fixed(info.width[WMode].x),
572
			     origin.y + float2fixed(info.width[WMode].y));
573
}
574
 
575
/* Get glyph info by glyph index. */
576
int
577
gs_type42_glyph_info_by_gid(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
578
		     int members, gs_glyph_info_t *info, uint glyph_index)
579
{
580
    gs_font_type42 *const pfont = (gs_font_type42 *)font;
581
    int default_members =
582
	members & ~(GLYPH_INFO_WIDTHS | GLYPH_INFO_NUM_PIECES |
583
		    GLYPH_INFO_PIECES | GLYPH_INFO_OUTLINE_WIDTHS |
584
		    GLYPH_INFO_VVECTOR0 | GLYPH_INFO_VVECTOR1);
585
    gs_glyph_data_t outline;
586
    int code = 0;
587
 
588
    outline.memory = pfont->memory;
589
    if (default_members) {
590
	code = gs_default_glyph_info(font, glyph, pmat, default_members, info);
591
 
592
	if (code < 0)
593
	    return code;
594
    } else if ((code = pfont->data.get_outline(pfont, glyph_index, &outline)) < 0)
595
	return code;		/* non-existent glyph */
596
    else {
597
	gs_glyph_data_free(&outline, "gs_type42_glyph_info");
598
	info->members = 0;
599
    }
600
    if (members & GLYPH_INFO_WIDTHS) {
601
	int i;
602
 
603
	for (i = 0; i < 2; ++i)
604
	    if (members & (GLYPH_INFO_WIDTH0 << i)) {
605
		float sbw[4];
606
 
607
		code = gs_type42_wmode_metrics(pfont, glyph_index, i, sbw);
608
		if (code < 0) {
609
		    code = 0;
610
		    continue;
611
		}
612
		if (pmat) {
613
		    code = gs_point_transform(sbw[2], sbw[3], pmat,
614
					      &info->width[i]);
615
		    if (code < 0)
616
			return code;
617
		    code = gs_point_transform(sbw[0], sbw[1], pmat,
618
					      &info->v);
619
		} else {
620
		    info->width[i].x = sbw[2], info->width[i].y = sbw[3];
621
		    info->v.x = sbw[0], info->v.y = sbw[1];
622
		}
623
		info->members |= (GLYPH_INFO_VVECTOR0 << i);
624
		info->members |= (GLYPH_INFO_WIDTH << i);
625
	    }
626
 
627
    }
628
    if (members & (GLYPH_INFO_NUM_PIECES | GLYPH_INFO_PIECES)) {
629
	gs_glyph *pieces =
630
	    (members & GLYPH_INFO_PIECES ? info->pieces : (gs_glyph *)0);
631
	int code = parse_pieces(pfont, glyph, pieces, &info->num_pieces);
632
 
633
	if (code < 0)
634
	    return code;
635
	info->members |= members & (GLYPH_INFO_NUM_PIECES | GLYPH_INFO_PIECES);
636
    }
637
    return code;
638
}
639
int
640
gs_type42_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
641
		     int members, gs_glyph_info_t *info)
642
{
643
    gs_font_type42 *const pfont = (gs_font_type42 *)font;
644
    uint glyph_index;
645
 
646
    if (glyph >= GS_MIN_GLYPH_INDEX)
647
	glyph_index = glyph - GS_MIN_GLYPH_INDEX;
648
    else {
649
	glyph_index = pfont->data.get_glyph_index(pfont, glyph);
650
	if (glyph_index == GS_NO_GLYPH)
651
	    return_error(gs_error_undefined);
652
    }
653
    return gs_type42_glyph_info_by_gid(font, glyph, pmat, members, info, glyph_index);
654
 
655
}
656
int
657
gs_type42_enumerate_glyph(gs_font *font, int *pindex,
658
			  gs_glyph_space_t glyph_space, gs_glyph *pglyph)
659
{
660
    gs_font_type42 *const pfont = (gs_font_type42 *)font;
661
 
662
    while (++*pindex <= pfont->data.numGlyphs) {
663
	gs_glyph_data_t outline;
664
	uint glyph_index = *pindex - 1;
665
	int code;
666
 
667
	outline.memory = pfont->memory;
668
	code = pfont->data.get_outline(pfont, glyph_index, &outline);
669
	if (code < 0)
670
	    return code;
671
	if (outline.bits.data == 0)
672
	    continue;		/* empty (undefined) glyph */
673
	*pglyph = glyph_index + GS_MIN_GLYPH_INDEX;
674
	gs_glyph_data_free(&outline, "gs_type42_enumerate_glyph");
675
	return 0;
676
    }
677
    /* We are done. */
678
    *pindex = 0;
679
    return 0;
680
}
681
 
682
/* Get the metrics of a simple glyph. */
683
private int
684
simple_glyph_metrics(gs_font_type42 * pfont, uint glyph_index, int wmode,
685
		     float sbw[4])
686
{
687
    int (*string_proc)(gs_font_type42 *, ulong, uint, const byte **) =
688
	pfont->data.string_proc;
689
    double factor = recipunitsperem(pfont);
690
    uint width;
691
    int lsb;
692
    int code;
693
 
694
    {
695
	const gs_type42_mtx_t *pmtx = &pfont->data.metrics[wmode];
696
	uint num_metrics = pmtx->numMetrics;
697
	const byte *pmetrics;
698
 
699
	if (pmtx->length == 0)
700
	    return_error(gs_error_rangecheck);
701
	if (glyph_index < num_metrics) {
702
	    ACCESS(pmtx->offset + glyph_index * 4, 4, pmetrics);
703
	    width = U16(pmetrics);
704
	    lsb = S16(pmetrics + 2);
705
	} else {
706
	    uint offset = pmtx->offset + num_metrics * 4;
707
	    uint glyph_offset = (glyph_index - num_metrics) * 2;
708
	    const byte *plsb;
709
 
710
	    ACCESS(offset - 4, 4, pmetrics);
711
	    width = U16(pmetrics);
712
	    if (glyph_offset >= pmtx->length)
713
		glyph_offset = pmtx->length - 2;
714
	    ACCESS(offset + glyph_offset, 2, plsb);
715
	    lsb = S16(plsb);
716
	}
717
    }
718
    if (wmode) {
719
	factor = -factor;	/* lsb and width go down the page */
720
	sbw[0] = 0, sbw[1] = lsb * factor;
721
	sbw[2] = 0, sbw[3] = width * factor;
722
    } else {
723
	sbw[0] = lsb * factor, sbw[1] = 0;
724
	sbw[2] = width * factor, sbw[3] = 0;
725
    }
726
    return 0;
727
}
728
 
729
/* Get the metrics of a glyph. */
730
int
731
gs_type42_default_get_metrics(gs_font_type42 * pfont, uint glyph_index,
732
			      int wmode, float sbw[4])
733
{
734
    gs_glyph_data_t glyph_data;
735
    int code;
736
    int result;
737
 
738
    glyph_data.memory = pfont->memory;
739
    code = pfont->data.get_outline(pfont, glyph_index, &glyph_data);
740
    if (code < 0)
741
	return code;
742
    if (glyph_data.bits.size != 0 && S16(glyph_data.bits.data) == -1) {
743
	/* This is a composite glyph. */
744
	uint flags;
745
	const byte *gdata = glyph_data.bits.data + 10;
746
	gs_matrix_fixed mat;
747
 
748
	memset(&mat, 0, sizeof(mat)); /* arbitrary */
749
	do {
750
	    uint comp_index = U16(gdata + 2);
751
 
752
	    parse_component(&gdata, &flags, &mat, NULL, pfont, &mat);
753
	    if (flags & TT_CG_USE_MY_METRICS) {
754
		result = gs_type42_wmode_metrics(pfont, comp_index, wmode, sbw);
755
		goto done;
756
	    }
757
	}
758
	while (flags & TT_CG_MORE_COMPONENTS);
759
    }
760
    result = simple_glyph_metrics(pfont, glyph_index, wmode, sbw);
761
 done:
762
    gs_glyph_data_free(&glyph_data, "gs_type42_default_get_metrics");
763
    return result;
764
}
765
int
766
gs_type42_wmode_metrics(gs_font_type42 * pfont, uint glyph_index, int wmode,
767
			float sbw[4])
768
{
769
    return pfont->data.get_metrics(pfont, glyph_index, wmode, sbw);
770
}
771
int
772
gs_type42_get_metrics(gs_font_type42 * pfont, uint glyph_index,
773
		      float sbw[4])
774
{
775
    return gs_type42_wmode_metrics(pfont, glyph_index, pfont->WMode, sbw);
776
}
777
 
778
/* Define the bits in the glyph flags. */
779
#define gf_OnCurve 1
780
#define gf_xShort 2
781
#define gf_yShort 4
782
#define gf_Repeat 8
783
#define gf_xPos 16		/* xShort */
784
#define gf_xSame 16		/* !xShort */
785
#define gf_yPos 32		/* yShort */
786
#define gf_ySame 32		/* !yShort */
787
 
788
/* Append a TrueType outline to a path. */
789
/* Note that this does not append the final moveto for the width. */
790
int
791
gs_type42_append(uint glyph_index, gs_imager_state * pis,
792
		 gx_path * ppath, const gs_log2_scale_point * pscale,
793
		 bool charpath_flag, int paint_type, cached_fm_pair *pair)
794
{
795
    int code = append_outline_fitted(glyph_index, &ctm_only(pis), ppath, 
796
			pair, pscale, charpath_flag);
797
 
798
    if (code < 0)
799
	return code;
800
    code = gx_setcurrentpoint_from_path(pis, ppath);
801
    if (code < 0)
802
	return code;
803
    /* Set the flatness for curve rendering. */
804
    return gs_imager_setflat(pis, gs_char_flatness(pis, 1.0));
805
}
806
 
807
/* Add 2nd degree Bezier to the path */
808
private int
809
add_quadratic_curve(gx_path * const ppath, const gs_fixed_point * const a,
810
     const gs_fixed_point * const b, const gs_fixed_point * const c)
811
{
812
    return gx_path_add_curve(ppath, (a->x + 2*b->x)/3, (a->y + 2*b->y)/3,
813
	(c->x + 2*b->x)/3, (c->y + 2*b->y)/3, c->x, c->y);
814
}
815
 
816
/*
817
 * Append a simple glyph outline to a path (ppath != 0) and/or return
818
 * its list of points (ppts != 0).
819
 */
820
private int
821
append_simple(const byte *gdata, float sbw[4], const gs_matrix_fixed *pmat,
822
	      gx_path *ppath, gs_fixed_point *ppts, gs_font_type42 * pfont,
823
	      bool subglyph)
824
{
825
    int numContours = S16(gdata);
826
    const byte *pends = gdata + 10;
827
    const byte *pinstr = pends + numContours * 2;
828
    const byte *pflags;
829
    uint npoints;
830
    const byte *pxc, *pyc;
831
    int code;
832
 
833
    if (numContours == 0)
834
	return 0;
835
    /*
836
     * It appears that the only way to find the X and Y coordinate
837
     * tables is to parse the flags.  If this is true, it is an
838
     * incredible piece of bad design.
839
     */
840
    {
841
	const byte *pf = pflags = pinstr + 2 + U16(pinstr);
842
	uint xbytes = npoints = U16(pinstr - 2) + 1;
843
	uint np = npoints;
844
 
845
	while (np > 0) {
846
	    byte flags = *pf++;
847
	    uint reps = (flags & gf_Repeat ? *pf++ + 1 : 1);
848
 
849
	    if (!(flags & gf_xShort)) {
850
		if (flags & gf_xSame)
851
		    xbytes -= reps;
852
		else
853
		    xbytes += reps;
854
	    }
855
	    np -= reps;
856
	}
857
	pxc = pf;
858
	pyc = pxc + xbytes;
859
    }
860
 
861
    /* Interpret the contours. */
862
 
863
    {
864
	uint i, np;
865
	float offset = 0;
866
	gs_fixed_point pt;
867
	double factor = recipunitsperem(pfont);
868
	/*
869
	 * Decode the first flag byte outside the loop, to avoid a
870
	 * compiler warning about uninitialized variables.
871
	 */
872
	byte flags = *pflags++;
873
	uint reps = (flags & gf_Repeat ? *pflags++ + 1 : 1);
874
 
875
	if (!subglyph) {
876
	    int xmin = S16(gdata + 2); /* We like to see it with debugger. */
877
 
878
	    offset = sbw[0] - xmin * factor;
879
	}
880
	gs_point_transform2fixed(pmat, offset, 0.0, &pt);
881
	for (i = 0, np = 0; i < numContours; ++i) {
882
	    bool move = true;
883
	    bool off_curve = false;
884
            bool is_start_off = false;
885
            uint last_point = U16(pends + i * 2);
886
	    float dx, dy;
887
	    gs_fixed_point start,pt_start_off;
888
	    gs_fixed_point cpoints[2];
889
 
890
            if_debug1('1', "[1t]start %d\n", i);
891
 
892
            for (; np <= last_point; --reps, ++np) {
893
		gs_fixed_point dpt;
894
 
895
		if (reps == 0) {
896
		    flags = *pflags++;
897
		    reps = (flags & gf_Repeat ? *pflags++ + 1 : 1);
898
		}
899
		if (flags & gf_xShort) {
900
		    /*
901
		     * A bug in the Watcom compiler prevents us from doing
902
		     * the following with the obvious conditional expression.
903
		     */
904
		    if (flags & gf_xPos)
905
			dx = *pxc++ * factor;
906
		    else
907
			dx = -(int)*pxc++ * factor;
908
		} else if (!(flags & gf_xSame))
909
		    dx = S16(pxc) * factor, pxc += 2;
910
		else
911
		    dx = 0;
912
		if (flags & gf_yShort) {
913
		    /* See above under dx. */
914
		    if (flags & gf_yPos)
915
			dy = *pyc++ * factor;
916
		    else
917
			dy = -(int)*pyc++ * factor;
918
		} else if (!(flags & gf_ySame))
919
		    dy = S16(pyc) * factor, pyc += 2;
920
		else
921
		    dy = 0;
922
		code = gs_distance_transform2fixed(pmat, dx, dy, &dpt);
923
		if (code < 0)
924
		    return code;
925
		pt.x += dpt.x, pt.y += dpt.y;
926
 
927
                if (ppts)	/* return the points */
928
		    ppts[np] = pt;
929
 
930
                if (ppath) {
931
                    /* append to a path */
932
		    if_debug3('1', "[1t]%s (%g %g)\n",
933
		    	(flags & gf_OnCurve ? "on " : "off"), fixed2float(pt.x), fixed2float(pt.y));
934
 
935
                    if (move) {
936
                        if(is_start_off) {
937
                            if(flags & gf_OnCurve)
938
                                start = pt;
939
                            else { 
940
                                start.x = (pt_start_off.x + pt.x)/2;
941
			        start.y = (pt_start_off.y + pt.y)/2;
942
                                cpoints[1]=pt;
943
			        off_curve=true;
944
                            }
945
                            move = false;
946
                            cpoints[0] = start;
947
                            code = gx_path_add_point(ppath, start.x, start.y);
948
                        } else { 
949
                            if(flags & gf_OnCurve) { 
950
                                cpoints[0] = start = pt;
951
			        code = gx_path_add_point(ppath, pt.x, pt.y);
952
			        move = false;
953
                            } else { 
954
                                is_start_off = true;
955
                                pt_start_off = pt;
956
                            }
957
                        }
958
		    } else if (flags & gf_OnCurve) {
959
                        if (off_curve)
960
			    code = add_quadratic_curve(ppath, cpoints, cpoints+1, &pt);
961
			else
962
			    code = gx_path_add_line(ppath, pt.x, pt.y);
963
			cpoints[0] = pt;
964
			off_curve = false;
965
		    } else {
966
                        if(off_curve) {
967
			    gs_fixed_point p;
968
                            p.x = (cpoints[1].x + pt.x)/2;
969
			    p.y = (cpoints[1].y + pt.y)/2;
970
			    code = add_quadratic_curve(ppath, cpoints, cpoints+1, &p);
971
			    cpoints[0] = p;
972
			}
973
                        off_curve = true;
974
		        cpoints[1] = pt;
975
		    }
976
		    if (code < 0)
977
			return code;
978
		}
979
	    }
980
	    if (ppath) {
981
		if (is_start_off) { 
982
                    if (off_curve) { 
983
                        gs_fixed_point p;
984
                        p.x = (cpoints[1].x + pt_start_off.x)/2;
985
	                p.y = (cpoints[1].y + pt_start_off.y)/2;
986
                        code = add_quadratic_curve(ppath, cpoints, cpoints+1, &p);
987
		        if (code < 0)
988
		            return code;
989
                        code = add_quadratic_curve(ppath, &p, &pt_start_off, &start);
990
		        if (code < 0)
991
		            return code;
992
                    } else { 
993
                        code = add_quadratic_curve(ppath, cpoints, &pt_start_off, &start);
994
		        if (code < 0)
995
		            return code;
996
                    }
997
                } else { 
998
                    if (off_curve) { 
999
                        code = add_quadratic_curve(ppath, cpoints, cpoints+1, &start);
1000
		        if (code < 0)
1001
		            return code;
1002
                    }
1003
                }
1004
                code = gx_path_close_subpath(ppath);
1005
		if (code < 0)
1006
		    return code;
1007
	    }
1008
	}
1009
    }
1010
    return 0;
1011
}
1012
 
1013
/* Append a glyph outline. */
1014
private int
1015
check_component(uint glyph_index, const gs_matrix_fixed *pmat,
1016
		gx_path *ppath, gs_font_type42 *pfont, gs_fixed_point *ppts,
1017
		gs_glyph_data_t *pgd, bool subglyph)
1018
{
1019
    gs_glyph_data_t glyph_data;
1020
    const byte *gdata;
1021
    float sbw[4];
1022
    int numContours;
1023
    int code;
1024
 
1025
    glyph_data.memory = pfont->memory;
1026
    code = pfont->data.get_outline(pfont, glyph_index, &glyph_data);
1027
    if (code < 0)
1028
	return code;
1029
    gdata = glyph_data.bits.data;
1030
    if (gdata == 0 || glyph_data.bits.size == 0)	/* empty glyph */
1031
	return 0;
1032
    numContours = S16(gdata);
1033
    if (numContours >= 0) {
1034
	gs_type42_get_metrics(pfont, glyph_index, sbw);
1035
	code = append_simple(gdata, sbw, pmat, ppath, ppts, pfont, subglyph);
1036
	gs_glyph_data_free(&glyph_data, "check_component");
1037
	return (code < 0 ? code : 0); /* simple */
1038
    }
1039
    if (numContours != -1)
1040
	return_error(gs_error_rangecheck);
1041
    *pgd = glyph_data;
1042
    return 1;			/* composite */
1043
}
1044
private int
1045
append_component(uint glyph_index, const gs_matrix_fixed * pmat,
1046
		 gx_path * ppath, gs_fixed_point *ppts, int point_index,
1047
		 gs_font_type42 * pfont, bool subglyph)
1048
{
1049
    gs_glyph_data_t glyph_data;
1050
    int code;
1051
 
1052
    glyph_data.memory = pfont->memory;
1053
    code = check_component(glyph_index, pmat, ppath, pfont, ppts + point_index,
1054
			   &glyph_data, subglyph);
1055
    if (code != 1)
1056
	return code;
1057
    /*
1058
     * This is a composite glyph.  Because of the "point matching" feature,
1059
     * we have to do an extra pass over each component to fill in the
1060
     * table of points.
1061
     */
1062
    {
1063
	uint flags;
1064
	const byte *gdata = glyph_data.bits.data + 10;
1065
 
1066
	do {
1067
	    uint comp_index = U16(gdata + 2);
1068
	    gs_matrix_fixed mat;
1069
	    int mp[2];
1070
 
1071
	    parse_component(&gdata, &flags, &mat, mp, pfont, pmat);
1072
	    if (mp[0] >= 0) {
1073
		/* Match up points.  What a nuisance! */
1074
		const gs_fixed_point *const pfrom = ppts + mp[0];
1075
		/*
1076
		 * Contrary to the TrueType documentation, mp[1] is not
1077
		 * relative to the start of the compound glyph, but is
1078
		 * relative to the start of the component.
1079
		 */
1080
		const gs_fixed_point *const pto = ppts + point_index + mp[1];
1081
		gs_fixed_point diff;
1082
 
1083
		code = append_component(comp_index, &mat, NULL, ppts,
1084
					point_index, pfont, true);
1085
		if (code < 0)
1086
		    break;
1087
		diff.x = pfrom->x - pto->x;
1088
		diff.y = pfrom->y - pto->y;
1089
		mat.tx = fixed2float(mat.tx_fixed += diff.x);
1090
		mat.ty = fixed2float(mat.ty_fixed += diff.y);
1091
	    }
1092
	    code = append_component(comp_index, &mat, ppath, ppts,
1093
				    point_index, pfont, true);
1094
	    if (code < 0)
1095
		break;
1096
	    point_index += total_points(pfont, comp_index);
1097
	}
1098
	while (flags & TT_CG_MORE_COMPONENTS);
1099
    }
1100
    gs_glyph_data_free(&glyph_data, "append_component");
1101
    return code;
1102
}
1103
 
1104
private int
1105
append_outline_fitted(uint glyph_index, const gs_matrix * pmat,
1106
	       gx_path * ppath, cached_fm_pair * pair, 
1107
	       const gs_log2_scale_point * pscale, bool design_grid)
1108
{
1109
    gs_font_type42 *pfont = (gs_font_type42 *)pair->font;
1110
    int code;
1111
 
1112
    gx_ttfReader__set_font(pair->ttr, pfont);
1113
    code = gx_ttf_outline(pair->ttf, pair->ttr, pfont, (uint)glyph_index, 
1114
	pmat, pscale, ppath, design_grid);
1115
    gx_ttfReader__set_font(pair->ttr, NULL);
1116
    return code;
1117
}
1118