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