xref: /plan9/sys/src/cmd/gs/src/gstype42.c (revision 409b3aff3015608d158d294a437acca386aba474)
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
get_glyph_offset(gs_font_type42 * pfont,uint glyph_index)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
gs_type42_font_init(gs_font_type42 * pfont)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
gs_len_glyphs_release(void * data,void * event)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
recipunitsperem(gs_font_type42 * pfont)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
parse_component(const byte ** pdata,uint * pflags,gs_matrix_fixed * psmat,int * pmp,const gs_font_type42 * pfont,const gs_matrix_fixed * pmat)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
total_points(gs_font_type42 * pfont,uint glyph_index)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
default_get_glyph_index(gs_font_type42 * pfont,gs_glyph glyph)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
default_get_outline(gs_font_type42 * pfont,uint glyph_index,gs_glyph_data_t * pgd)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
gs_type42_get_outline_from_TT_file(gs_font_type42 * pfont,stream * s,uint glyph_index,gs_glyph_data_t * pgd)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
parse_pieces(gs_font_type42 * pfont,gs_glyph glyph,gs_glyph * pieces,int * pnum_pieces)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
gs_type42_glyph_outline(gs_font * font,int WMode,gs_glyph glyph,const gs_matrix * pmat,gx_path * ppath,double sbw[4])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
gs_type42_glyph_info_by_gid(gs_font * font,gs_glyph glyph,const gs_matrix * pmat,int members,gs_glyph_info_t * info,uint glyph_index)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
gs_type42_glyph_info(gs_font * font,gs_glyph glyph,const gs_matrix * pmat,int members,gs_glyph_info_t * info)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
gs_type42_enumerate_glyph(gs_font * font,int * pindex,gs_glyph_space_t glyph_space,gs_glyph * pglyph)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
simple_glyph_metrics(gs_font_type42 * pfont,uint glyph_index,int wmode,float sbw[4])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
gs_type42_default_get_metrics(gs_font_type42 * pfont,uint glyph_index,int wmode,float sbw[4])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
gs_type42_wmode_metrics(gs_font_type42 * pfont,uint glyph_index,int wmode,float sbw[4])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
gs_type42_get_metrics(gs_font_type42 * pfont,uint glyph_index,float sbw[4])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
gs_type42_append(uint glyph_index,gs_imager_state * pis,gx_path * ppath,const gs_log2_scale_point * pscale,bool charpath_flag,int paint_type,cached_fm_pair * pair)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
add_quadratic_curve(gx_path * const ppath,const gs_fixed_point * const a,const gs_fixed_point * const b,const gs_fixed_point * const c)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
append_simple(const byte * gdata,float sbw[4],const gs_matrix_fixed * pmat,gx_path * ppath,gs_fixed_point * ppts,gs_font_type42 * pfont,bool subglyph)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
check_component(uint glyph_index,const gs_matrix_fixed * pmat,gx_path * ppath,gs_font_type42 * pfont,gs_fixed_point * ppts,gs_glyph_data_t * pgd,bool subglyph)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
append_component(uint glyph_index,const gs_matrix_fixed * pmat,gx_path * ppath,gs_fixed_point * ppts,int point_index,gs_font_type42 * pfont,bool subglyph)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
append_outline_fitted(uint glyph_index,const gs_matrix * pmat,gx_path * ppath,cached_fm_pair * pair,const gs_log2_scale_point * pscale,bool design_grid)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 
1119