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