4 * Copyright (C) 2011-2012 by Werner Lemberg.
6 * This file is part of the ttfautohint library, and may only be used,
7 * modified, and distributed under the terms given in `COPYING'. By
8 * continuing to use, modify, or distribute this file you indicate that you
9 * have read `COPYING' and understand and accept it fully.
11 * The file `COPYING' mentioned in the previous paragraph is distributed
12 * with the ttfautohint library.
20 TA_sfnt_build_glyf_hints(SFNT
* sfnt
,
23 FT_Face face
= sfnt
->face
;
28 /* this loop doesn't include the artificial `.ttfautohint' glyph */
29 for (idx
= 0; idx
< face
->num_glyphs
; idx
++)
31 error
= TA_sfnt_build_glyph_instructions(sfnt
, font
, idx
);
39 ret
= font
->progress(idx
, face
->num_glyphs
,
40 sfnt
- font
->sfnts
, font
->num_sfnts
,
43 return TA_Err_Canceled
;
52 TA_glyph_get_components(GLYPH
* glyph
,
58 FT_UShort
* components_new
;
70 /* walk over component records */
74 return FT_Err_Invalid_Table
;
79 /* add component to list */
80 component
= *(p
++) << 8;
83 glyph
->num_components
++;
84 components_new
= (FT_UShort
*)realloc(glyph
->components
,
86 * sizeof (FT_UShort
));
89 glyph
->num_components
--;
90 return FT_Err_Out_Of_Memory
;
93 glyph
->components
= components_new
;
95 glyph
->components
[glyph
->num_components
- 1] = component
;
97 /* skip scaling and offset arguments */
98 if (flags
& ARGS_ARE_WORDS
)
103 if (flags
& WE_HAVE_A_SCALE
)
105 else if (flags
& WE_HAVE_AN_XY_SCALE
)
107 else if (flags
& WE_HAVE_A_2X2
)
109 } while (flags
& MORE_COMPONENTS
);
116 TA_glyph_parse_composite(GLYPH
* glyph
,
119 FT_UShort num_glyphs
)
121 FT_ULong flags_offset
; /* after the loop, this is the offset */
122 /* to the last element in the flags array */
129 /* we allocate too large a buffer */
130 /* (including space for the new component */
131 /* and possible argument size changes for shifted point indices) */
132 /* and reallocate it later to its real size */
133 glyph
->buf
= (FT_Byte
*)malloc(len
+ 8 + glyph
->num_components
* 2);
135 return FT_Err_Out_Of_Memory
;
145 /* if the composite glyph contains one or more contours, */
146 /* we prepend a composite glyph component to call some bytecode */
147 /* which eventually becomes the last glyph in the `glyf' table; */
148 /* for convenience, however, it is not added to the `components' array */
149 /* (doing so simplifies the conversion of point indices later on) */
150 if (glyph
->num_composite_contours
)
160 /* the composite glyph's bounding box */
161 x_min
= (FT_Short
)((buf
[2] << 8) + buf
[3]);
162 y_min
= (FT_Short
)((buf
[4] << 8) + buf
[5]);
163 x_max
= (FT_Short
)((buf
[6] << 8) + buf
[7]);
164 y_max
= (FT_Short
)((buf
[8] << 8) + buf
[9]);
166 /* use ARGS_ARE_WORDS only if necessary; */
167 /* note that the offset value of the component doesn't matter */
168 /* as long as it stays within the bounding box */
169 if (x_min
<= 0 && x_max
>= 0)
176 if (y_min
<= 0 && y_max
>= 0)
183 if (x_offset
>= -128 && x_offset
<= 127
184 && y_offset
>= -128 && y_offset
<= 127)
187 *(q
++) = ARGS_ARE_XY_VALUES
| MORE_COMPONENTS
;
188 *(q
++) = HIGH(num_glyphs
- 1);
189 *(q
++) = LOW(num_glyphs
- 1);
196 *(q
++) = ARGS_ARE_WORDS
| ARGS_ARE_XY_VALUES
| MORE_COMPONENTS
;
197 *(q
++) = HIGH(num_glyphs
- 1);
198 *(q
++) = LOW(num_glyphs
- 1);
199 *(q
++) = HIGH(x_offset
);
200 *(q
++) = LOW(x_offset
);
201 *(q
++) = HIGH(y_offset
);
202 *(q
++) = LOW(y_offset
);
206 /* walk over component records */
209 flags_offset
= q
- glyph
->buf
;
220 if (flags
& ARGS_ARE_XY_VALUES
)
226 if (flags
& ARGS_ARE_WORDS
)
234 /* handle point numbers */
240 if (flags
& ARGS_ARE_WORDS
)
253 /* adjust point numbers */
254 /* (see `TA_adjust_point_index' in `tabytecode.c' for more) */
255 for (i
= 0; i
< glyph
->num_pointsums
; i
++)
256 if (arg1
< glyph
->pointsums
[i
])
260 for (i
= 0; i
< glyph
->num_pointsums
; i
++)
261 if (arg2
< glyph
->pointsums
[i
])
265 if (arg1
<= 0xFF && arg2
<= 0xFF)
267 glyph
->buf
[flags_offset
+ 1] &= ~ARGS_ARE_WORDS
;
274 glyph
->buf
[flags_offset
+ 1] |= ARGS_ARE_WORDS
;
283 /* copy scaling arguments */
284 if (flags
& (WE_HAVE_A_SCALE
| WE_HAVE_AN_XY_SCALE
| WE_HAVE_A_2X2
))
289 if (flags
& (WE_HAVE_AN_XY_SCALE
| WE_HAVE_A_2X2
))
294 if (flags
& WE_HAVE_A_2X2
)
301 } while (flags
& MORE_COMPONENTS
);
303 glyph
->len1
= q
- glyph
->buf
;
304 /* glyph->len2 = 0; */
305 glyph
->flags_offset
= flags_offset
;
306 glyph
->buf
= (FT_Byte
*)realloc(glyph
->buf
, glyph
->len1
);
308 /* we discard instructions (if any) */
309 glyph
->buf
[glyph
->flags_offset
] &= ~(WE_HAVE_INSTR
>> 8);
316 TA_glyph_parse_simple(GLYPH
* glyph
,
321 FT_Byte
* flags_start
;
325 FT_ULong flags_size
; /* size of the flags array */
326 FT_ULong xy_size
; /* size of x and y coordinate arrays together */
337 ins_offset
= 10 + glyph
->num_contours
* 2;
342 return FT_Err_Invalid_Table
;
344 /* get number of instructions */
345 num_ins
= *(p
++) << 8;
351 return FT_Err_Invalid_Table
;
357 while (i
< glyph
->num_points
)
368 return FT_Err_Invalid_Table
;
372 x_short
= (flags
& X_SHORT_VECTOR
) ? 1 : 2;
373 y_short
= (flags
& Y_SHORT_VECTOR
) ? 1 : 2;
375 have_x
= ((flags
& SAME_X
) && !(flags
& X_SHORT_VECTOR
)) ? 0 : 1;
376 have_y
= ((flags
& SAME_Y
) && !(flags
& Y_SHORT_VECTOR
)) ? 0 : 1;
383 return FT_Err_Invalid_Table
;
387 if (i
+ count
> glyph
->num_points
)
388 return FT_Err_Invalid_Table
;
391 xy_size
+= count
* x_short
* have_x
;
392 xy_size
+= count
* y_short
* have_y
;
397 if (p
+ xy_size
> endp
)
398 return FT_Err_Invalid_Table
;
400 flags_size
= p
- flags_start
;
402 /* store the data before and after the bytecode instructions */
403 /* in the same array */
404 glyph
->len1
= ins_offset
;
405 glyph
->len2
= flags_size
+ xy_size
;
406 glyph
->buf
= (FT_Byte
*)malloc(glyph
->len1
+ glyph
->len2
);
408 return FT_Err_Out_Of_Memory
;
410 /* now copy everything but the instructions */
411 memcpy(glyph
->buf
, buf
, glyph
->len1
);
412 memcpy(glyph
->buf
+ glyph
->len1
, flags_start
, glyph
->len2
);
419 TA_iterate_composite_glyph(glyf_Data
* data
,
420 FT_UShort
* components
,
421 FT_UShort num_components
,
422 FT_UShort
** pointsums
,
423 FT_UShort
* num_pointsums
,
424 FT_UShort
* num_composite_contours
,
425 FT_UShort
* num_composite_points
)
427 FT_UShort
* pointsums_new
;
431 /* save current state */
433 if (*num_pointsums
== 0xFFFF)
434 return FT_Err_Invalid_Table
;
437 pointsums_new
= (FT_UShort
*)realloc(*pointsums
,
439 * sizeof (FT_UShort
));
443 return FT_Err_Out_Of_Memory
;
446 *pointsums
= pointsums_new
;
448 (*pointsums
)[*num_pointsums
- 1] = *num_composite_points
;
450 for (i
= 0; i
< num_components
; i
++)
453 FT_UShort component
= components
[i
];
457 if (component
>= data
->num_glyphs
)
458 return FT_Err_Invalid_Table
;
460 glyph
= &data
->glyphs
[component
];
462 if (glyph
->num_components
)
464 error
= TA_iterate_composite_glyph(data
,
466 glyph
->num_components
,
469 num_composite_contours
,
470 num_composite_points
);
476 /* no need for checking overflow of the number of contours */
477 /* since the number of points is always larger or equal */
478 if (*num_composite_points
> 0xFFFF - glyph
->num_points
)
479 return FT_Err_Invalid_Table
;
481 *num_composite_contours
+= glyph
->num_contours
;
482 *num_composite_points
+= glyph
->num_points
;
491 TA_sfnt_compute_composite_pointsums(SFNT
* sfnt
,
494 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
495 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
500 for (i
= 0; i
< data
->num_glyphs
; i
++)
502 GLYPH
* glyph
= &data
->glyphs
[i
];
505 if (glyph
->num_components
)
508 FT_UShort num_composite_contours
= 0;
509 FT_UShort num_composite_points
= 0;
512 error
= TA_iterate_composite_glyph(data
,
514 glyph
->num_components
,
516 &glyph
->num_pointsums
,
517 &num_composite_contours
,
518 &num_composite_points
);
522 glyph
->num_composite_contours
= num_composite_contours
;
524 /* update maximum values, */
525 /* including the subglyphs not in `components' array */
526 /* (each of them has a single point in a single contour) */
527 if (num_composite_points
+ glyph
->num_pointsums
528 > sfnt
->max_composite_points
)
529 sfnt
->max_composite_points
= num_composite_points
530 + glyph
->num_pointsums
;
531 if (num_composite_contours
+ glyph
->num_pointsums
532 > sfnt
->max_composite_contours
)
533 sfnt
->max_composite_contours
= num_composite_contours
534 + glyph
->num_pointsums
;
543 TA_sfnt_split_glyf_table(SFNT
* sfnt
,
546 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
547 SFNT_Table
* loca_table
= &font
->tables
[sfnt
->loca_idx
];
548 SFNT_Table
* head_table
= &font
->tables
[sfnt
->head_idx
];
554 FT_ULong offset_next
;
558 FT_UShort loop_count
;
563 /* in case of success, all allocated arrays are */
564 /* linked and eventually freed in `TA_font_unload' */
566 /* nothing to do if table has already been split */
567 if (glyf_table
->data
)
570 data
= (glyf_Data
*)calloc(1, sizeof (glyf_Data
));
572 return FT_Err_Out_Of_Memory
;
574 glyf_table
->data
= data
;
576 loca_format
= head_table
->buf
[LOCA_FORMAT_OFFSET
];
578 data
->num_glyphs
= loca_format
? loca_table
->len
/ 4
579 : loca_table
->len
/ 2;
580 loop_count
= data
->num_glyphs
- 1;
582 /* allocate one more glyph slot if we have composite glyphs */
583 if (!sfnt
->max_components
)
584 data
->num_glyphs
-= 1;
585 data
->glyphs
= (GLYPH
*)calloc(1, data
->num_glyphs
* sizeof (GLYPH
));
587 return FT_Err_Out_Of_Memory
;
589 /* first loop over `loca' and `glyf' data */
595 offset_next
= *(p
++) << 24;
596 offset_next
+= *(p
++) << 16;
597 offset_next
+= *(p
++) << 8;
598 offset_next
+= *(p
++);
602 offset_next
= *(p
++) << 8;
603 offset_next
+= *(p
++);
607 for (i
= 0; i
< loop_count
; i
++)
609 GLYPH
* glyph
= &data
->glyphs
[i
];
613 offset
= offset_next
;
617 offset_next
= *(p
++) << 24;
618 offset_next
+= *(p
++) << 16;
619 offset_next
+= *(p
++) << 8;
620 offset_next
+= *(p
++);
624 offset_next
= *(p
++) << 8;
625 offset_next
+= *(p
++);
629 if (offset_next
< offset
630 || offset_next
> glyf_table
->len
)
631 return FT_Err_Invalid_Table
;
633 len
= offset_next
- offset
;
635 continue; /* empty glyph */
641 /* check header size */
643 return FT_Err_Invalid_Table
;
645 /* we need the number of contours and points for */
646 /* `TA_sfnt_compute_composite_pointsums' */
647 buf
= glyf_table
->buf
+ offset
;
648 glyph
->num_contours
= (FT_Short
)((buf
[0] << 8) + buf
[1]);
650 if (glyph
->num_contours
< 0)
652 error
= TA_glyph_get_components(glyph
, buf
, len
);
661 /* use the last contour's end point to compute number of points */
662 off
= 10 + (glyph
->num_contours
- 1) * 2;
664 return FT_Err_Invalid_Table
;
666 glyph
->num_points
= buf
[off
] << 8;
667 glyph
->num_points
+= buf
[off
+ 1] + 1;
672 if (sfnt
->max_components
)
674 error
= TA_sfnt_compute_composite_pointsums(sfnt
, font
);
679 /* second loop over `loca' and `glyf' data */
685 offset_next
= *(p
++) << 24;
686 offset_next
+= *(p
++) << 16;
687 offset_next
+= *(p
++) << 8;
688 offset_next
+= *(p
++);
692 offset_next
= *(p
++) << 8;
693 offset_next
+= *(p
++);
697 for (i
= 0; i
< loop_count
; i
++)
699 GLYPH
* glyph
= &data
->glyphs
[i
];
703 offset
= offset_next
;
707 offset_next
= *(p
++) << 24;
708 offset_next
+= *(p
++) << 16;
709 offset_next
+= *(p
++) << 8;
710 offset_next
+= *(p
++);
714 offset_next
= *(p
++) << 8;
715 offset_next
+= *(p
++);
719 len
= offset_next
- offset
;
721 continue; /* empty glyph */
727 buf
= glyf_table
->buf
+ offset
;
729 /* We must parse the rest of the glyph record to get the exact */
730 /* record length. Since the `loca' table rounds record lengths */
731 /* up to multiples of 4 (or 2 for older fonts), and we must round */
732 /* up again after stripping off the instructions, it would be */
733 /* possible otherwise to have more than 4 bytes of padding which */
734 /* is more or less invalid. */
736 if (glyph
->num_contours
< 0)
737 error
= TA_glyph_parse_composite(glyph
, buf
, len
, data
->num_glyphs
);
739 error
= TA_glyph_parse_simple(glyph
, buf
, len
);
745 if (sfnt
->max_components
)
747 /* construct and append our special glyph used as a composite element */
748 GLYPH
* glyph
= &data
->glyphs
[data
->num_glyphs
- 1];
754 /* increment `cvtl_is_subglyph' counter */
767 glyph
->buf
= (FT_Byte
*)malloc(glyph
->len1
+ glyph
->len2
);
769 return FT_Err_Out_Of_Memory
;
773 buf
[0] = 0x00; /* one contour */
775 buf
[2] = 0x00; /* no dimensions */
783 buf
[10] = 0x00; /* one contour end point */
786 buf
[12] = ON_CURVE
| SAME_X
| SAME_Y
; /* the flags for a point at 0,0 */
788 /* add bytecode also; */
789 /* this works because the loop in `TA_sfnt_build_glyf_hints' */
790 /* doesn't include the newly appended glyph */
791 glyph
->ins_len
= sizeof (bytecode
);
792 glyph
->ins_buf
= (FT_Byte
*)malloc(glyph
->ins_len
);
794 return FT_Err_Out_Of_Memory
;
795 memcpy(glyph
->ins_buf
, bytecode
, glyph
->ins_len
);
797 sfnt
->max_components
+= 1;
805 TA_sfnt_build_glyf_table(SFNT
* sfnt
,
808 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
809 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
819 if (glyf_table
->processed
)
824 glyph
= data
->glyphs
;
825 for (i
= 0; i
< data
->num_glyphs
; i
++, glyph
++)
827 /* glyph records should have offsets which are multiples of 4 */
828 len
= (len
+ 3) & ~3;
829 len
+= glyph
->len1
+ glyph
->len2
+ glyph
->ins_len
;
830 /* add two bytes for the instructionLength field */
831 if (glyph
->len2
|| glyph
->ins_len
)
835 /* to make the short format of the `loca' table always work, */
836 /* assure an even length of the `glyf' table */
837 glyf_table
->len
= (len
+ 1) & ~1;
839 buf_new
= (FT_Byte
*)realloc(glyf_table
->buf
, (len
+ 3) & ~3);
841 return FT_Err_Out_Of_Memory
;
843 glyf_table
->buf
= buf_new
;
846 glyph
= data
->glyphs
;
847 for (i
= 0; i
< data
->num_glyphs
; i
++, glyph
++)
849 len
= glyph
->len1
+ glyph
->len2
+ glyph
->ins_len
;
850 if (glyph
->len2
|| glyph
->ins_len
)
855 /* copy glyph data and insert new instructions */
856 memcpy(p
, glyph
->buf
, glyph
->len1
);
862 *(p
++) = HIGH(glyph
->ins_len
);
863 *(p
++) = LOW(glyph
->ins_len
);
864 memcpy(p
, glyph
->ins_buf
, glyph
->ins_len
);
866 memcpy(p
, glyph
->buf
+ glyph
->len1
, glyph
->len2
);
871 /* composite glyph */
874 *(p
+ glyph
->flags_offset
) |= (WE_HAVE_INSTR
>> 8);
876 *(p
++) = HIGH(glyph
->ins_len
);
877 *(p
++) = LOW(glyph
->ins_len
);
878 memcpy(p
, glyph
->ins_buf
, glyph
->ins_len
);
885 /* pad with zero bytes to have an offset which is a multiple of 4; */
886 /* this works even for the last glyph record since the `glyf' */
887 /* table length is a multiple of 4 also */
902 glyf_table
->checksum
= TA_table_compute_checksum(glyf_table
->buf
,
904 glyf_table
->processed
= 1;
911 TA_create_glyph_data(FT_Outline
* outline
,
914 FT_Error error
= TA_Err_Ok
;
920 FT_Byte
* flags
= NULL
;
934 if (!outline
->n_contours
)
935 return TA_Err_Ok
; /* empty glyph */
937 /* in case of success, all non-local allocated arrays are */
938 /* linked and eventually freed in `TA_font_unload' */
942 /* we use `calloc' since we rely on the array */
943 /* being initialized to zero; */
944 /* additionally, we need one more byte for a test after the loop */
945 flags
= (FT_Byte
*)calloc(1, outline
->n_points
+ 1);
948 error
= FT_Err_Out_Of_Memory
;
952 /* we have either one-byte or two-byte elements */
953 x
= (FT_Byte
*)malloc(2 * outline
->n_points
);
956 error
= FT_Err_Out_Of_Memory
;
960 y
= (FT_Byte
*)malloc(2 * outline
->n_points
);
963 error
= FT_Err_Out_Of_Memory
;
970 xmin
= xmax
= (outline
->points
[0].x
+ 32) >> 6;
971 ymin
= ymax
= (outline
->points
[0].y
+ 32) >> 6;
974 oldf
= 0x80; /* start with an impossible value */
976 /* convert the FreeType representation of the glyph's outline */
977 /* into the representation format of the `glyf' table */
978 for (i
= 0; i
< outline
->n_points
; i
++)
980 FT_Pos xcur
= (outline
->points
[i
].x
+ 32) >> 6;
981 FT_Pos ycur
= (outline
->points
[i
].y
+ 32) >> 6;
983 FT_Pos xdelta
= xcur
- lastx
;
984 FT_Pos ydelta
= ycur
- lasty
;
987 /* we are only interested in bit 0 of the `tags' array */
988 f
= outline
->tags
[i
] & ON_CURVE
;
996 if (xdelta
< 256 && xdelta
> -256)
1005 *(xp
++) = (FT_Byte
)xdelta
;
1009 *(xp
++) = HIGH(xdelta
);
1010 *(xp
++) = LOW(xdelta
);
1020 if (ydelta
< 256 && ydelta
> -256)
1022 f
|= Y_SHORT_VECTOR
;
1029 *(yp
++) = (FT_Byte
)ydelta
;
1033 *(yp
++) = HIGH(ydelta
);
1034 *(yp
++) = LOW(ydelta
);
1040 /* set repeat flag */
1041 *(flagsp
- 1) |= REPEAT
;
1045 /* we can only handle 256 repetitions at once, */
1046 /* so use a new counter */
1051 *flagsp
+= 1; /* increase repetition counter */
1056 flagsp
++; /* skip repetition counter */
1074 /* if the last byte was a repetition counter, */
1075 /* we must increase by one to get the correct array size */
1079 header
[0] = HIGH(outline
->n_contours
);
1080 header
[1] = LOW(outline
->n_contours
);
1081 header
[2] = HIGH(xmin
);
1082 header
[3] = LOW(xmin
);
1083 header
[4] = HIGH(ymin
);
1084 header
[5] = LOW(ymin
);
1085 header
[6] = HIGH(xmax
);
1086 header
[7] = LOW(xmax
);
1087 header
[8] = HIGH(ymax
);
1088 header
[9] = LOW(ymax
);
1090 /* concatenate all arrays and fill needed GLYPH structure elements */
1092 glyph
->len1
= 10 + 2 * outline
->n_contours
;
1093 glyph
->len2
= (flagsp
- flags
) + (xp
- x
) + (yp
- y
);
1095 glyph
->buf
= (FT_Byte
*)malloc(glyph
->len1
+ glyph
->len2
);
1098 error
= FT_Err_Out_Of_Memory
;
1103 memcpy(p
, header
, 10);
1107 glyph
->ins_buf
= NULL
;
1109 for (i
= 0; i
< outline
->n_contours
; i
++)
1111 *(p
++) = HIGH(outline
->contours
[i
]);
1112 *(p
++) = LOW(outline
->contours
[i
]);
1115 memcpy(p
, flags
, flagsp
- flags
);
1116 p
+= flagsp
- flags
;
1117 memcpy(p
, x
, xp
- x
);
1119 memcpy(p
, y
, yp
- y
);
1130 /* We hint each glyph at EM size and construct a new `glyf' table. */
1131 /* Some fonts need this; in particular, */
1132 /* there are CJK fonts which use hints to scale and position subglyphs. */
1133 /* As a consequence, there are no longer composite glyphs. */
1136 TA_sfnt_create_glyf_data(SFNT
* sfnt
,
1139 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
1140 FT_Face face
= sfnt
->face
;
1148 /* in case of success, all allocated arrays are */
1149 /* linked and eventually freed in `TA_font_unload' */
1151 /* nothing to do if table has already been created */
1152 if (glyf_table
->data
)
1155 data
= (glyf_Data
*)calloc(1, sizeof (glyf_Data
));
1157 return FT_Err_Out_Of_Memory
;
1159 glyf_table
->data
= data
;
1161 data
->num_glyphs
= face
->num_glyphs
;
1162 data
->glyphs
= (GLYPH
*)calloc(1, data
->num_glyphs
* sizeof (GLYPH
));
1164 return FT_Err_Out_Of_Memory
;
1166 /* XXX: Make size configurable */
1167 /* we use the EM size */
1168 /* so that the resulting coordinates can be used without transformation */
1169 error
= FT_Set_Char_Size(face
, face
->units_per_EM
* 64, 0, 72, 0);
1173 /* loop over all glyphs in font face */
1174 for (i
= 0; i
< data
->num_glyphs
; i
++)
1176 GLYPH
* glyph
= &data
->glyphs
[i
];
1179 error
= FT_Load_Glyph(face
, i
, FT_LOAD_NO_BITMAP
| FT_LOAD_NO_AUTOHINT
);
1183 error
= TA_create_glyph_data(&face
->glyph
->outline
, glyph
);
1191 /* end of taglyf.c */