1 /* Copyright (C) 1996, 2000 artofcode LLC.  All rights reserved.
2 
3   This program is free software; you can redistribute it and/or modify it
4   under the terms of the GNU General Public License as published by the
5   Free Software Foundation; either version 2 of the License, or (at your
6   option) any later version.
7 
8   This program is distributed in the hope that it will be useful, but
9   WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   General Public License for more details.
12 
13   You should have received a copy of the GNU General Public License along
14   with this program; if not, write to the Free Software Foundation, Inc.,
15   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16 
17 */
18 
19 /*$Id: gstype42.c,v 1.12.2.2.2.1 2003/01/17 00:49:03 giles Exp $ */
20 /* Type 42 (TrueType) font library routines */
21 #include "memory_.h"
22 #include "gx.h"
23 #include "gserrors.h"
24 #include "gsstruct.h"
25 #include "gsccode.h"
26 #include "gsline.h"		/* for gs_imager_setflat */
27 #include "gsmatrix.h"
28 #include "gsutil.h"
29 #include "gxchrout.h"
30 #include "gxfixed.h"		/* for gxpath.h */
31 #include "gxpath.h"
32 #include "gxfont.h"
33 #include "gxfont42.h"
34 #include "gxistate.h"
35 
36 /* Structure descriptor */
37 public_st_gs_font_type42();
38 
39 /* Forward references */
40 private int append_outline(P4(uint glyph_index, const gs_matrix_fixed * pmat,
41 			      gx_path * ppath, gs_font_type42 * pfont));
42 private int default_get_outline(P3(gs_font_type42 *pfont, uint glyph_index,
43 				   gs_const_string *pgstr));
44 private int default_get_metrics(P4(gs_font_type42 *pfont, uint glyph_index,
45 				   int wmode, float sbw[4]));
46 
47 /* Set up a pointer to a substring of the font data. */
48 /* Free variables: pfont, string_proc. */
49 #define ACCESS(base, length, vptr)\
50   BEGIN\
51     code = (*string_proc)(pfont, (ulong)(base), length, &vptr);\
52     if ( code < 0 ) return code;\
53   END
54 
55 /* Get 2- or 4-byte quantities from a table. */
56 #define U8(p) ((uint)((p)[0]))
57 #define S8(p) (int)((U8(p) ^ 0x80) - 0x80)
58 #define U16(p) (((uint)((p)[0]) << 8) + (p)[1])
59 #define S16(p) (int)((U16(p) ^ 0x8000) - 0x8000)
60 #define u32(p) get_u32_msb(p)
61 
62 /* ---------------- Font level ---------------- */
63 
64 /* Initialize the cached values in a Type 42 font. */
65 /* Note that this initializes get_outline and the font procedures as well. */
66 int
gs_type42_font_init(gs_font_type42 * pfont)67 gs_type42_font_init(gs_font_type42 * pfont)
68 {
69     int (*string_proc)(P4(gs_font_type42 *, ulong, uint, const byte **)) =
70 	pfont->data.string_proc;
71     const byte *OffsetTable;
72     uint numTables;
73     const byte *TableDirectory;
74     uint i;
75     int code;
76     byte head_box[8];
77     ulong loca_size = 0;
78 
79     ACCESS(0, 12, OffsetTable);
80     {
81 	static const byte version1_0[4] = {0, 1, 0, 0};
82 	static const byte version_true[4] = {'t', 'r', 'u', 'e'};
83 
84 	if (memcmp(OffsetTable, version1_0, 4) &&
85 	    memcmp(OffsetTable, version_true, 4))
86 	    return_error(gs_error_invalidfont);
87     }
88     numTables = U16(OffsetTable + 4);
89     ACCESS(12, numTables * 16, TableDirectory);
90     /* Clear optional entries. */
91     memset(pfont->data.metrics, 0, sizeof(pfont->data.metrics));
92     for (i = 0; i < numTables; ++i) {
93 	const byte *tab = TableDirectory + i * 16;
94 	ulong offset = u32(tab + 8);
95 
96 	if (!memcmp(tab, "glyf", 4))
97 	    pfont->data.glyf = offset;
98 	else if (!memcmp(tab, "head", 4)) {
99 	    const byte *head;
100 
101 	    ACCESS(offset, 54, head);
102 	    pfont->data.unitsPerEm = U16(head + 18);
103 	    memcpy(head_box, head + 36, 8);
104 	    pfont->data.indexToLocFormat = U16(head + 50);
105 	} else if (!memcmp(tab, "hhea", 4)) {
106 	    const byte *hhea;
107 
108 	    ACCESS(offset, 36, hhea);
109 	    pfont->data.metrics[0].numMetrics = U16(hhea + 34);
110 	} else if (!memcmp(tab, "hmtx", 4)) {
111 	    pfont->data.metrics[0].offset = offset;
112 	    pfont->data.metrics[0].length = (uint)u32(tab + 12);
113 	} else if (!memcmp(tab, "loca", 4)) {
114 	    pfont->data.loca = offset;
115 	    loca_size = u32(tab + 12);
116 	} else if (!memcmp(tab, "vhea", 4)) {
117 	    const byte *vhea;
118 
119 	    ACCESS(offset, 36, vhea);
120 	    pfont->data.metrics[1].numMetrics = U16(vhea + 34);
121 	} else if (!memcmp(tab, "vmtx", 4)) {
122 	    pfont->data.metrics[1].offset = offset;
123 	    pfont->data.metrics[1].length = (uint)u32(tab + 12);
124 	}
125     }
126     loca_size >>= pfont->data.indexToLocFormat + 1;
127     pfont->data.numGlyphs = (loca_size == 0 ? 0 : loca_size - 1);
128     /*
129      * If the font doesn't have a valid FontBBox, compute one from the
130      * 'head' information.  Since the Adobe PostScript driver sometimes
131      * outputs garbage FontBBox values, we use a "reasonableness" check
132      * here.
133      */
134     if (pfont->FontBBox.p.x >= pfont->FontBBox.q.x ||
135 	pfont->FontBBox.p.y >= pfont->FontBBox.q.y ||
136 	pfont->FontBBox.p.x < -0.5 || pfont->FontBBox.p.x > 0.5 ||
137 	pfont->FontBBox.p.y < -0.5 || pfont->FontBBox.p.y > 0.5
138 	) {
139 	float upem = pfont->data.unitsPerEm;
140 
141 	pfont->FontBBox.p.x = S16(head_box) / upem;
142 	pfont->FontBBox.p.y = S16(head_box + 2) / upem;
143 	pfont->FontBBox.q.x = S16(head_box + 4) / upem;
144 	pfont->FontBBox.q.y = S16(head_box + 6) / upem;
145     }
146     pfont->data.get_outline = default_get_outline;
147     pfont->data.get_metrics = default_get_metrics;
148     pfont->procs.glyph_outline = gs_type42_glyph_outline;
149     pfont->procs.glyph_info = gs_type42_glyph_info;
150     pfont->procs.enumerate_glyph = gs_type42_enumerate_glyph;
151     return 0;
152 }
153 
154 /* ---------------- Glyph level ---------------- */
155 
156 /* Define the bits in the component glyph flags. */
157 #define cg_argsAreWords 1
158 #define cg_argsAreXYValues 2
159 #define cg_roundXYToGrid 4
160 #define cg_haveScale 8
161 #define cg_moreComponents 32
162 #define cg_haveXYScale 64
163 #define cg_have2x2 128
164 #define cg_useMyMetrics 512
165 
166 /*
167  * Parse the definition of one component of a composite glyph.  We don't
168  * bother to parse the component index, since the caller can do this so
169  * easily.
170  */
171 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)172 parse_component(const byte **pdata, uint *pflags, gs_matrix_fixed *psmat,
173 		int *pmp /*[2], may be null*/, const gs_font_type42 *pfont,
174 		const gs_matrix_fixed *pmat)
175 {
176     const byte *gdata = *pdata;
177     uint flags;
178     double factor = 1.0 / pfont->data.unitsPerEm;
179     gs_matrix_fixed mat;
180     gs_matrix scale_mat;
181 
182     flags = U16(gdata);
183     gdata += 4;
184     mat = *pmat;
185     if (flags & cg_argsAreXYValues) {
186 	int arg1, arg2;
187 	gs_fixed_point pt;
188 
189 	if (flags & cg_argsAreWords)
190 	    arg1 = S16(gdata), arg2 = S16(gdata + 2), gdata += 4;
191 	else
192 	    arg1 = S8(gdata), arg2 = S8(gdata + 1), gdata += 2;
193 	if (flags & cg_roundXYToGrid) {
194 	    /* We should do something here, but we don't. */
195 	}
196 	gs_point_transform2fixed(pmat, arg1 * factor,
197 				 arg2 * factor, &pt);
198 	/****** HACK: WE KNOW ABOUT FIXED MATRICES ******/
199 	mat.tx = fixed2float(mat.tx_fixed = pt.x);
200 	mat.ty = fixed2float(mat.ty_fixed = pt.y);
201 	if (pmp)
202 	    pmp[0] = pmp[1] = -1;
203     } else {
204 	if (flags & cg_argsAreWords) {
205 	    if (pmp)
206 		pmp[0] = U16(gdata), pmp[1] = S16(gdata + 2);
207 	    gdata += 4;
208 	} else {
209 	    if (pmp)
210 		pmp[0] = U8(gdata), pmp[1] = U8(gdata + 1);
211 	    gdata += 2;
212 	}
213     }
214 #define S2_14(p) (S16(p) / 16384.0)
215     if (flags & cg_haveScale) {
216 	scale_mat.xx = scale_mat.yy = S2_14(gdata);
217 	scale_mat.xy = scale_mat.yx = 0;
218 	gdata += 2;
219     } else if (flags & cg_haveXYScale) {
220 	scale_mat.xx = S2_14(gdata);
221 	scale_mat.yy = S2_14(gdata + 2);
222 	scale_mat.xy = scale_mat.yx = 0;
223 	gdata += 4;
224     } else if (flags & cg_have2x2) {
225 	scale_mat.xx = S2_14(gdata);
226 	scale_mat.xy = S2_14(gdata + 2);
227 	scale_mat.yx = S2_14(gdata + 4);
228 	scale_mat.yy = S2_14(gdata + 6);
229 	gdata += 8;
230     } else
231 	goto no_scale;
232 #undef S2_14
233     scale_mat.tx = 0;
234     scale_mat.ty = 0;
235     /* The scale doesn't affect mat.t{x,y}, so we don't */
236     /* need to update the fixed components. */
237     gs_matrix_multiply(&scale_mat, (const gs_matrix *)&mat,
238 		       (gs_matrix *)&mat);
239 no_scale:
240     *pdata = gdata;
241     *pflags = flags;
242     *psmat = mat;
243 }
244 
245 /* Compute the total number of points in a (possibly composite) glyph. */
246 private int
total_points(gs_font_type42 * pfont,uint glyph_index)247 total_points(gs_font_type42 *pfont, uint glyph_index)
248 {
249     gs_const_string glyph_string;
250     int code;
251     int ocode = pfont->data.get_outline(pfont, glyph_index, &glyph_string);
252     const byte *gdata = glyph_string.data;
253     int total;
254 
255     if (ocode < 0)
256 	return ocode;
257     if (glyph_string.size == 0)
258 	return 0;
259     if (S16(gdata) != -1) {
260 	/* This is a simple glyph. */
261 	int numContours = S16(gdata);
262 	const byte *pends = gdata + 10;
263 	const byte *pinstr = pends + numContours * 2;
264 
265 	total = (numContours == 0 ? 0 : U16(pinstr - 2) + 1);
266     } else {
267 	/* This is a composite glyph.  Add up the components. */
268 	uint flags;
269 	gs_matrix_fixed mat;
270 
271 	gdata += 10;
272 	memset(&mat, 0, sizeof(mat)); /* arbitrary */
273 	total = 0;
274 	do {
275 	    code = total_points(pfont, U16(gdata + 2));
276 	    if (code < 0)
277 		return code;
278 	    total += code;
279 	    parse_component(&gdata, &flags, &mat, NULL, pfont, &mat);
280 	}
281 	while (flags & cg_moreComponents);
282     }
283     if (ocode > 0)
284 	gs_free_const_string(pfont->memory, gdata, glyph_string.size,
285 			     "total_points");
286     return total;
287 }
288 
289 /* Define the default implementation for getting the outline data for */
290 /* a glyph, using indexToLocFormat and the loca and glyf tables. */
291 /* Set pglyph->data = 0 if the glyph is empty. */
292 private int
default_get_outline(gs_font_type42 * pfont,uint glyph_index,gs_const_string * pglyph)293 default_get_outline(gs_font_type42 * pfont, uint glyph_index,
294 		    gs_const_string * pglyph)
295 {
296     int (*string_proc) (P4(gs_font_type42 *, ulong, uint, const byte **)) =
297     pfont->data.string_proc;
298     const byte *ploca;
299     ulong glyph_start;
300     uint glyph_length;
301     int code;
302 
303     /*
304      * We can't assume that consecutive loca entries are stored
305      * contiguously in memory: we have to access each entry
306      * individually.
307      */
308     if (pfont->data.indexToLocFormat) {
309 	ACCESS(pfont->data.loca + glyph_index * 4, 4, ploca);
310 	glyph_start = u32(ploca);
311 	ACCESS(pfont->data.loca + glyph_index * 4 + 4, 4, ploca);
312 	glyph_length = u32(ploca) - glyph_start;
313     } else {
314 	ACCESS(pfont->data.loca + glyph_index * 2, 2, ploca);
315 	glyph_start = (ulong) U16(ploca) << 1;
316 	ACCESS(pfont->data.loca + glyph_index * 2 + 2, 2, ploca);
317 	glyph_length = ((ulong) U16(ploca) << 1) - glyph_start;
318     }
319     pglyph->size = glyph_length;
320     if (glyph_length == 0)
321 	pglyph->data = 0;
322     else
323 	ACCESS(pfont->data.glyf + glyph_start, glyph_length, pglyph->data);
324     return 0;
325 }
326 
327 /* Parse a glyph into pieces, if any. */
328 private int
parse_pieces(gs_font_type42 * pfont,gs_glyph glyph,gs_glyph * pieces,int * pnum_pieces)329 parse_pieces(gs_font_type42 *pfont, gs_glyph glyph, gs_glyph *pieces,
330 	     int *pnum_pieces)
331 {
332     uint glyph_index = glyph - gs_min_cid_glyph;
333     gs_const_string glyph_string;
334     int code = pfont->data.get_outline(pfont, glyph_index, &glyph_string);
335 
336     if (code < 0)
337 	return code;
338     if (glyph_string.size != 0 && S16(glyph_string.data) == -1) {
339 	/* This is a composite glyph. */
340 	int i = 0;
341 	uint flags = cg_moreComponents;
342 	const byte *gdata = glyph_string.data + 10;
343 	gs_matrix_fixed mat;
344 
345 	memset(&mat, 0, sizeof(mat)); /* arbitrary */
346 	for (i = 0; flags & cg_moreComponents; ++i) {
347 	    if (pieces)
348 		pieces[i] = U16(gdata + 2) + gs_min_cid_glyph;
349 	    parse_component(&gdata, &flags, &mat, NULL, pfont, &mat);
350 	}
351 	*pnum_pieces = i;
352     } else
353 	*pnum_pieces = 0;
354     if (code > 0)
355 	gs_free_const_string(pfont->memory, glyph_string.data,
356 			     glyph_string.size, "parse_pieces");
357     return 0;
358 }
359 
360 /* Define the font procedures for a Type 42 font. */
361 int
gs_type42_glyph_outline(gs_font * font,gs_glyph glyph,const gs_matrix * pmat,gx_path * ppath)362 gs_type42_glyph_outline(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
363 			gx_path *ppath)
364 {
365     gs_font_type42 *const pfont = (gs_font_type42 *)font;
366     uint glyph_index = glyph - gs_min_cid_glyph;
367     gs_fixed_point origin;
368     int code;
369     gs_glyph_info_t info;
370     gs_matrix_fixed fmat;
371     static const gs_matrix imat = { identity_matrix_body };
372 
373     if (pmat == 0)
374 	pmat = &imat;
375     if ((code = gs_matrix_fixed_from_matrix(&fmat, pmat)) < 0 ||
376 	(code = gx_path_current_point(ppath, &origin)) < 0 ||
377 	(code = append_outline(glyph_index, &fmat, ppath, pfont)) < 0 ||
378 	(code = font->procs.glyph_info(font, glyph, pmat,
379 				       GLYPH_INFO_WIDTH, &info)) < 0
380 	)
381 	return code;
382     return gx_path_add_point(ppath, origin.x + float2fixed(info.width[0].x),
383 			     origin.y + float2fixed(info.width[0].y));
384 }
385 int
gs_type42_glyph_info(gs_font * font,gs_glyph glyph,const gs_matrix * pmat,int members,gs_glyph_info_t * info)386 gs_type42_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
387 		     int members, gs_glyph_info_t *info)
388 {
389     gs_font_type42 *const pfont = (gs_font_type42 *)font;
390     uint glyph_index = glyph - gs_min_cid_glyph;
391     int default_members =
392 	members & ~(GLYPH_INFO_WIDTHS | GLYPH_INFO_NUM_PIECES |
393 		    GLYPH_INFO_PIECES);
394     gs_const_string outline;
395     int code = 0;
396 
397     if (default_members) {
398 	code = gs_default_glyph_info(font, glyph, pmat, default_members, info);
399 
400 	if (code < 0)
401 	    return code;
402     } else if ((code = pfont->data.get_outline(pfont, glyph_index, &outline)) < 0)
403 	return code;		/* non-existent glyph */
404     else {
405 	if (code > 0)
406 	    gs_free_const_string(pfont->memory, outline.data, outline.size,
407 				 "gs_type42_glyph_info");
408 	info->members = 0;
409     }
410     if (members & GLYPH_INFO_WIDTH) {
411 	int i;
412 
413 	for (i = 0; i < 2; ++i)
414 	    if (members & (GLYPH_INFO_WIDTH0 << i)) {
415 		float sbw[4];
416 
417 		code = gs_type42_wmode_metrics(pfont, glyph_index, i, sbw);
418 		if (code < 0)
419 		    return code;
420 		if (pmat)
421 		    code = gs_point_transform(sbw[2], sbw[3], pmat,
422 					      &info->width[i]);
423 		else
424 		    info->width[i].x = sbw[2], info->width[i].y = sbw[3];
425 	    }
426 	info->members |= members & GLYPH_INFO_WIDTH;
427     }
428     if (members & (GLYPH_INFO_NUM_PIECES | GLYPH_INFO_PIECES)) {
429 	gs_glyph *pieces =
430 	    (members & GLYPH_INFO_PIECES ? info->pieces : (gs_glyph *)0);
431 	int code = parse_pieces(pfont, glyph, pieces, &info->num_pieces);
432 
433 	if (code < 0)
434 	    return code;
435 	info->members |= members & (GLYPH_INFO_NUM_PIECES | GLYPH_INFO_PIECES);
436     }
437     return code;
438 }
439 int
gs_type42_enumerate_glyph(gs_font * font,int * pindex,gs_glyph_space_t glyph_space,gs_glyph * pglyph)440 gs_type42_enumerate_glyph(gs_font *font, int *pindex,
441 			  gs_glyph_space_t glyph_space, gs_glyph *pglyph)
442 {
443     gs_font_type42 *const pfont = (gs_font_type42 *)font;
444 
445     while (++*pindex <= pfont->data.numGlyphs) {
446 	gs_const_string outline;
447 	uint glyph_index = *pindex - 1;
448 	int code = pfont->data.get_outline(pfont, glyph_index, &outline);
449 
450 	if (code < 0)
451 	    return code;
452 	if (outline.data == 0)
453 	    continue;		/* empty (undefined) glyph */
454 	*pglyph = glyph_index + gs_min_cid_glyph;
455 	if (code > 0)
456 	    gs_free_const_string(pfont->memory, outline.data, outline.size,
457 				 "gs_type42_enumerate_glyph");
458 	return 0;
459     }
460     /* We are done. */
461     *pindex = 0;
462     return 0;
463 }
464 
465 /* Get the metrics of a simple glyph. */
466 private int
simple_glyph_metrics(gs_font_type42 * pfont,uint glyph_index,int wmode,float sbw[4])467 simple_glyph_metrics(gs_font_type42 * pfont, uint glyph_index, int wmode,
468 		     float sbw[4])
469 {
470     int (*string_proc)(P4(gs_font_type42 *, ulong, uint, const byte **)) =
471 	pfont->data.string_proc;
472     double factor = 1.0 / pfont->data.unitsPerEm;
473     uint width;
474     int lsb;
475     int code;
476 
477     {
478 	const gs_type42_mtx_t *pmtx = &pfont->data.metrics[wmode];
479 	uint num_metrics = pmtx->numMetrics;
480 	const byte *pmetrics;
481 
482 	if (glyph_index < num_metrics) {
483 	    ACCESS(pmtx->offset + glyph_index * 4, 4, pmetrics);
484 	    width = U16(pmetrics);
485 	    lsb = S16(pmetrics + 2);
486 	} else {
487 	    uint offset = pmtx->offset + num_metrics * 4;
488 	    uint glyph_offset = (glyph_index - num_metrics) * 2;
489 	    const byte *plsb;
490 
491 	    ACCESS(offset - 4, 4, pmetrics);
492 	    width = U16(pmetrics);
493 	    if (glyph_offset >= pmtx->length)
494 		glyph_offset = pmtx->length - 2;
495 	    ACCESS(offset + glyph_offset, 2, plsb);
496 	    lsb = S16(plsb);
497 	}
498     }
499     if (wmode) {
500 	factor = -factor;	/* lsb and width go down the page */
501 	sbw[0] = 0, sbw[1] = lsb * factor;
502 	sbw[2] = 0, sbw[3] = width * factor;
503     } else {
504 	sbw[0] = lsb * factor, sbw[1] = 0;
505 	sbw[2] = width * factor, sbw[3] = 0;
506     }
507     return 0;
508 }
509 
510 /* Get the metrics of a glyph. */
511 private int
default_get_metrics(gs_font_type42 * pfont,uint glyph_index,int wmode,float sbw[4])512 default_get_metrics(gs_font_type42 * pfont, uint glyph_index, int wmode,
513 		    float sbw[4])
514 {
515     gs_const_string glyph_string;
516     int code = pfont->data.get_outline(pfont, glyph_index, &glyph_string);
517     int result;
518 
519     if (code < 0)
520 	return code;
521     if (glyph_string.size != 0 && S16(glyph_string.data) == -1) {
522 	/* This is a composite glyph. */
523 	uint flags;
524 	const byte *gdata = glyph_string.data + 10;
525 	gs_matrix_fixed mat;
526 
527 	memset(&mat, 0, sizeof(mat)); /* arbitrary */
528 	do {
529 	    uint comp_index = U16(gdata + 2);
530 
531 	    parse_component(&gdata, &flags, &mat, NULL, pfont, &mat);
532 	    if (flags & cg_useMyMetrics) {
533 		result = gs_type42_wmode_metrics(pfont, comp_index, wmode, sbw);
534 		goto done;
535 	    }
536 	}
537 	while (flags & cg_moreComponents);
538     }
539     result = simple_glyph_metrics(pfont, glyph_index, wmode, sbw);
540  done:
541     if (code > 0)
542 	gs_free_const_string(pfont->memory, glyph_string.data,
543 			     glyph_string.size, "default_get_metrics");
544     return result;
545 }
546 int
gs_type42_wmode_metrics(gs_font_type42 * pfont,uint glyph_index,int wmode,float sbw[4])547 gs_type42_wmode_metrics(gs_font_type42 * pfont, uint glyph_index, int wmode,
548 			float sbw[4])
549 {
550     return pfont->data.get_metrics(pfont, glyph_index, wmode, sbw);
551 }
552 int
gs_type42_get_metrics(gs_font_type42 * pfont,uint glyph_index,float sbw[4])553 gs_type42_get_metrics(gs_font_type42 * pfont, uint glyph_index,
554 		      float sbw[4])
555 {
556     return gs_type42_wmode_metrics(pfont, glyph_index, pfont->WMode, sbw);
557 }
558 
559 /* Define the bits in the glyph flags. */
560 #define gf_OnCurve 1
561 #define gf_xShort 2
562 #define gf_yShort 4
563 #define gf_Repeat 8
564 #define gf_xPos 16		/* xShort */
565 #define gf_xSame 16		/* !xShort */
566 #define gf_yPos 32		/* yShort */
567 #define gf_ySame 32		/* !yShort */
568 
569 /* Append a TrueType outline to a path. */
570 /* Note that this does not append the final moveto for the width. */
571 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,gs_font_type42 * pfont)572 gs_type42_append(uint glyph_index, gs_imager_state * pis,
573 		 gx_path * ppath, const gs_log2_scale_point * pscale,
574 		 bool charpath_flag, int paint_type, gs_font_type42 * pfont)
575 {
576     int code = append_outline(glyph_index, &pis->ctm, ppath, pfont);
577 
578     if (code < 0)
579 	return code;
580     /* Set the flatness for curve rendering. */
581     return gs_imager_setflat(pis, gs_char_flatness(pis, 1.0));
582 }
583 
584 /* Add 2nd degree Bezier to the path */
585 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)586 add_quadratic_curve(gx_path * const ppath, const gs_fixed_point * const a,
587      const gs_fixed_point * const b, const gs_fixed_point * const c)
588 {
589     return gx_path_add_curve(ppath, (a->x + 2*b->x)/3, (a->y + 2*b->y)/3,
590 	(c->x + 2*b->x)/3, (c->y + 2*b->y)/3, c->x, c->y);
591 }
592 
593 
594 /*
595  * Append a simple glyph outline to a path (ppath != 0) and/or return
596  * its list of points (ppts != 0).
597  */
598 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)599 append_simple(const byte *gdata, float sbw[4], const gs_matrix_fixed *pmat,
600 	      gx_path *ppath, gs_fixed_point *ppts, gs_font_type42 * pfont)
601 {
602     int numContours = S16(gdata);
603     const byte *pends = gdata + 10;
604     const byte *pinstr = pends + numContours * 2;
605     const byte *pflags;
606     uint npoints;
607     const byte *pxc, *pyc;
608     int code;
609 
610     if (numContours == 0)
611 	return 0;
612     /*
613      * It appears that the only way to find the X and Y coordinate
614      * tables is to parse the flags.  If this is true, it is an
615      * incredible piece of bad design.
616      */
617     {
618 	const byte *pf = pflags = pinstr + 2 + U16(pinstr);
619 	uint xbytes = npoints = U16(pinstr - 2) + 1;
620 	uint np = npoints;
621 
622 	while (np > 0) {
623 	    byte flags = *pf++;
624 	    uint reps = (flags & gf_Repeat ? *pf++ + 1 : 1);
625 
626 	    if (!(flags & gf_xShort)) {
627 		if (flags & gf_xSame)
628 		    xbytes -= reps;
629 		else
630 		    xbytes += reps;
631 	    }
632 	    np -= reps;
633 	}
634 	pxc = pf;
635 	pyc = pxc + xbytes;
636     }
637 
638     /* Interpret the contours. */
639 
640     {
641 	uint i, np;
642 	gs_fixed_point pt;
643 	double factor = 1.0 / pfont->data.unitsPerEm;
644 	/*
645 	 * Decode the first flag byte outside the loop, to avoid a
646 	 * compiler warning about uninitialized variables.
647 	 */
648 	byte flags = *pflags++;
649 	uint reps = (flags & gf_Repeat ? *pflags++ + 1 : 1);
650 
651 	/*
652 	 * The TrueType documentation gives no clue as to how the lsb
653 	 * should affect placement of the outline.  Our best guess is
654 	 * that the outline should be translated by lsb - xMin.
655 	 */
656 	gs_point_transform2fixed(pmat, sbw[0] - S16(gdata + 2) * factor,
657 				 0.0, &pt);
658 	for (i = 0, np = 0; i < numContours; ++i) {
659 	    bool move = true;
660 	    bool off_curve = false;
661             bool is_start_off = false;
662             uint last_point = U16(pends + i * 2);
663 	    float dx, dy;
664 	    gs_fixed_point start,pt_start_off;
665 	    gs_fixed_point cpoints[2];
666 
667             if_debug1('1', "[1t]start %d\n", i);
668 
669             for (; np <= last_point; --reps, ++np) {
670 		gs_fixed_point dpt;
671 
672 		if (reps == 0) {
673 		    flags = *pflags++;
674 		    reps = (flags & gf_Repeat ? *pflags++ + 1 : 1);
675 		}
676 		if (flags & gf_xShort) {
677 		    /*
678 		     * A bug in the Watcom compiler prevents us from doing
679 		     * the following with the obvious conditional expression.
680 		     */
681 		    if (flags & gf_xPos)
682 			dx = *pxc++ * factor;
683 		    else
684 			dx = -(int)*pxc++ * factor;
685 		} else if (!(flags & gf_xSame))
686 		    dx = S16(pxc) * factor, pxc += 2;
687 		else
688 		    dx = 0;
689 		if (flags & gf_yShort) {
690 		    /* See above under dx. */
691 		    if (flags & gf_yPos)
692 			dy = *pyc++ * factor;
693 		    else
694 			dy = -(int)*pyc++ * factor;
695 		} else if (!(flags & gf_ySame))
696 		    dy = S16(pyc) * factor, pyc += 2;
697 		else
698 		    dy = 0;
699 		code = gs_distance_transform2fixed(pmat, dx, dy, &dpt);
700 		if (code < 0)
701 		    return code;
702 		pt.x += dpt.x, pt.y += dpt.y;
703 
704                 if (ppts)	/* return the points */
705 		    ppts[np] = pt;
706 
707                 if (ppath) {
708                     /* append to a path */
709 		    if_debug3('1', "[1t]%s (%g %g)\n",
710 		    	(flags & gf_OnCurve ? "on " : "off"), fixed2float(pt.x), fixed2float(pt.y));
711 
712                     if (move) {
713                         if(is_start_off) {
714                             if(flags & gf_OnCurve)
715                                 start = pt;
716                             else {
717                                 start.x = (pt_start_off.x + pt.x)/2;
718 			        start.y = (pt_start_off.y + pt.y)/2;
719                                 cpoints[1]=pt;
720 			        off_curve=true;
721                             }
722                             move = false;
723                             cpoints[0] = start;
724                             code = gx_path_add_point(ppath, start.x, start.y);
725                         } else {
726                             if(flags & gf_OnCurve) {
727                                 cpoints[0] = start = pt;
728 			        code = gx_path_add_point(ppath, pt.x, pt.y);
729 			        move = false;
730                             } else {
731                                 is_start_off = true;
732                                 pt_start_off = pt;
733                             }
734                         }
735 		    } else if (flags & gf_OnCurve) {
736                         if (off_curve)
737 			    code = add_quadratic_curve(ppath, cpoints, cpoints+1, &pt);
738 			else
739 			    code = gx_path_add_line(ppath, pt.x, pt.y);
740 			cpoints[0] = pt;
741 			off_curve = false;
742 		    } else {
743                         if(off_curve) {
744 			    gs_fixed_point p;
745                             p.x = (cpoints[1].x + pt.x)/2;
746 			    p.y = (cpoints[1].y + pt.y)/2;
747 			    code = add_quadratic_curve(ppath, cpoints, cpoints+1, &p);
748 			    cpoints[0] = p;
749 			}
750                         off_curve = true;
751 		        cpoints[1] = pt;
752 		    }
753 		    if (code < 0)
754 			return code;
755 		}
756 	    }
757 	    if (ppath) {
758 		if (is_start_off) {
759                     if (off_curve) {
760                         gs_fixed_point p;
761                         p.x = (cpoints[1].x + pt_start_off.x)/2;
762 	                p.y = (cpoints[1].y + pt_start_off.y)/2;
763                         code = add_quadratic_curve(ppath, cpoints, cpoints+1, &p);
764 		        if (code < 0)
765 		            return code;
766                         code = add_quadratic_curve(ppath, &p, &pt_start_off, &start);
767 		        if (code < 0)
768 		            return code;
769                     } else {
770                         code = add_quadratic_curve(ppath, cpoints, &pt_start_off, &start);
771 		        if (code < 0)
772 		            return code;
773                     }
774                 } else {
775                     if (off_curve) {
776                         code = add_quadratic_curve(ppath, cpoints, cpoints+1, &start);
777 		        if (code < 0)
778 		            return code;
779                     }
780                 }
781                 code = gx_path_close_subpath(ppath);
782 		if (code < 0)
783 		    return code;
784 	    }
785 	}
786     }
787     return 0;
788 }
789 
790 /* Append a glyph outline. */
791 private int
check_component(uint glyph_index,const gs_matrix_fixed * pmat,gx_path * ppath,gs_font_type42 * pfont,gs_fixed_point * ppts,gs_const_string * pgstr,bool * pfree_data)792 check_component(uint glyph_index, const gs_matrix_fixed *pmat,
793 		gx_path *ppath, gs_font_type42 *pfont, gs_fixed_point *ppts,
794 		gs_const_string *pgstr, bool *pfree_data)
795 {
796     gs_const_string glyph_string;
797     const byte *gdata;
798     float sbw[4];
799     int numContours;
800     int ocode, code;
801 
802     ocode = pfont->data.get_outline(pfont, glyph_index, &glyph_string);
803     if (ocode < 0)
804 	return ocode;
805     gdata = glyph_string.data;
806     if (gdata == 0 || glyph_string.size == 0)	/* empty glyph */
807 	return 0;
808     numContours = S16(gdata);
809     if (numContours >= 0) {
810         /* Only sbw[0] is used in append_simple.
811 	   In order to set sbw[0], 0 is passed to
812 	   simple_glyph_metrics as wmode. */
813 	simple_glyph_metrics(pfont, glyph_index, 0, sbw);
814 	code = append_simple(gdata, sbw, pmat, ppath, ppts, pfont);
815 	if (ocode > 0)
816 	    gs_free_const_string(pfont->memory, gdata, glyph_string.size,
817 				 "check_component");
818 	return (code < 0 ? code : 0); /* simple */
819     }
820     if (numContours != -1)
821 	return_error(gs_error_rangecheck);
822     *pgstr = glyph_string;
823     *pfree_data = ocode > 0;
824     return 1;			/* composite */
825 }
826 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)827 append_component(uint glyph_index, const gs_matrix_fixed * pmat,
828 		 gx_path * ppath, gs_fixed_point *ppts, int point_index,
829 		 gs_font_type42 * pfont)
830 {
831     gs_const_string gstr;
832     bool free_data;
833     int code;
834 
835     code = check_component(glyph_index, pmat, ppath, pfont, ppts + point_index,
836 			   &gstr, &free_data);
837     if (code != 1)
838 	return code;
839     /*
840      * This is a composite glyph.  Because of the "point matching" feature,
841      * we have to do an extra pass over each component to fill in the
842      * table of points.
843      */
844     {
845 	uint flags;
846 	const byte *gdata = gstr.data + 10;
847 
848 	do {
849 	    uint comp_index = U16(gdata + 2);
850 	    gs_matrix_fixed mat;
851 	    int mp[2];
852 
853 	    parse_component(&gdata, &flags, &mat, mp, pfont, pmat);
854 	    if (mp[0] >= 0) {
855 		/* Match up points.  What a nuisance! */
856 		const gs_fixed_point *const pfrom = ppts + mp[0];
857 		/*
858 		 * Contrary to the TrueType documentation, mp[1] is not
859 		 * relative to the start of the compound glyph, but is
860 		 * relative to the start of the component.
861 		 */
862 		const gs_fixed_point *const pto = ppts + point_index + mp[1];
863 		gs_fixed_point diff;
864 
865 		code = append_component(comp_index, &mat, NULL, ppts,
866 					point_index, pfont);
867 		if (code < 0)
868 		    break;
869 		diff.x = pfrom->x - pto->x;
870 		diff.y = pfrom->y - pto->y;
871 		mat.tx = fixed2float(mat.tx_fixed += diff.x);
872 		mat.ty = fixed2float(mat.ty_fixed += diff.y);
873 	    }
874 	    code = append_component(comp_index, &mat, ppath, ppts,
875 				    point_index, pfont);
876 	    if (code < 0)
877 		break;
878 	    point_index += total_points(pfont, comp_index);
879 	}
880 	while (flags & cg_moreComponents);
881     }
882     if (free_data)
883 	gs_free_const_string(pfont->memory, gstr.data, gstr.size,
884 			     "append_component");
885     return code;
886 }
887 private int
append_outline(uint glyph_index,const gs_matrix_fixed * pmat,gx_path * ppath,gs_font_type42 * pfont)888 append_outline(uint glyph_index, const gs_matrix_fixed * pmat,
889 	       gx_path * ppath, gs_font_type42 * pfont)
890 {
891     gs_const_string gstr;
892     bool free_data;
893     int code =
894 	check_component(glyph_index, pmat, ppath, pfont, NULL, &gstr,
895 			&free_data);
896 
897     if (code != 1)
898 	return code;
899     {
900 	/*
901 	 * Set up the points array (only needed for point matching, sigh).
902 	 * We use stack allocation if possible, to avoid creating a sandbar
903 	 * (pts will be allocated before, but also freed before, any path
904 	 * elements).
905 	 */
906 #define MAX_STACK_PTS 150	/* usually enough */
907 	int num_points = total_points(pfont, glyph_index);
908 
909 	if (num_points <= MAX_STACK_PTS) {
910 	    gs_fixed_point pts[MAX_STACK_PTS];
911 
912 	    code = append_component(glyph_index, pmat, ppath, pts, 0, pfont);
913 	} else {
914 	    gs_memory_t *mem = pfont->memory; /* any memory will do */
915 	    gs_fixed_point *ppts = (gs_fixed_point *)
916 		gs_alloc_byte_array(mem, num_points, sizeof(gs_fixed_point),
917 				    "append_outline");
918 
919 	    if (ppts == 0)
920 		code = gs_note_error(gs_error_VMerror);
921 	    else {
922 		code = append_component(glyph_index, pmat, ppath, ppts, 0,
923 					pfont);
924 		gs_free_object(mem, ppts, "append_outline");
925 	    }
926 	}
927 #undef MAX_STACK_PTS
928     }
929     if (free_data)
930 	gs_free_const_string(pfont->memory, gstr.data, gstr.size,
931 			     "append_outline");
932     return code;
933 }
934