3 /* written 2011 by Werner Lemberg <wl@gnu.org> */
5 /* This file needs FreeType 2.4.5 or newer. */
13 #include FT_FREETYPE_H
14 #include FT_TRUETYPE_TAGS_H
16 #include "ttfautohint.h"
19 typedef struct SFNT_Table_
{
25 typedef struct SFNT_
{
27 SFNT_Table
* table_infos
;
28 FT_ULong num_table_infos
;
33 TTF_autohint(FILE *in
,
36 FT_Library lib
= NULL
;
42 FT_Long num_sfnts
= 0;
44 SFNT_Table
* tables
= NULL
;
45 FT_ULong num_tables
= 0;
55 /*** load font into memory ***/
57 fseek(in
, 0, SEEK_END
);
59 fseek(in
, 0, SEEK_SET
);
61 /* a TTF can never be that small */
63 return FT_Err_Invalid_Argument
;
65 in_buf
= (FT_Byte
*)malloc(in_len
);
67 return FT_Err_Out_Of_Memory
;
69 if (fread(in_buf
, 1, in_len
, in
) != in_len
)
71 error
= FT_Err_Invalid_Stream_Read
;
75 error
= FT_Init_FreeType(&lib
);
83 error
= FT_New_Memory_Face(lib
, in_buf
, in_len
, -1, &f
);
86 num_sfnts
= f
->num_faces
;
90 /* it is a TTC if we have more than a single face */
91 sfnts
= (SFNT
*)calloc(1, num_sfnts
* sizeof (SFNT
));
94 error
= FT_Err_Out_Of_Memory
;
98 for (i
= 0; i
< num_sfnts
; i
++)
100 SFNT
*sfnt
= &sfnts
[i
];
103 error
= FT_New_Memory_Face(lib
, in_buf
, in_len
, i
, &sfnt
->face
);
107 /* check that font is TTF */
108 if (!FT_IS_SFNT(sfnt
->face
))
110 error
= FT_Err_Invalid_Argument
;
114 error
= FT_Sfnt_Table_Info(sfnt
->face
, 0, NULL
, &sfnt
->num_table_infos
);
119 (SFNT_Table
*)calloc(1, sfnt
->num_table_infos
* sizeof (SFNT_Table
));
120 if (!sfnt
->table_infos
)
122 error
= FT_Err_Out_Of_Memory
;
126 /* collect SFNT table data */
127 glyf_idx
= sfnt
->num_table_infos
;
128 for (j
= 0; j
< sfnt
->num_table_infos
; j
++)
133 error
= FT_Sfnt_Table_Info(sfnt
->face
, j
, &tag
, &len
);
134 if (error
&& error
!= FT_Err_Table_Missing
)
139 if (tag
== TTAG_glyf
)
142 /* ignore tables which we are going to create by ourselves */
143 if (!(tag
== TTAG_fpgm
147 sfnt
->table_infos
[j
].tag
= tag
;
148 sfnt
->table_infos
[j
].len
= len
;
153 /* no (non-empty) `glyf' table; this can't be a TTF with outlines */
154 if (glyf_idx
== sfnt
->num_table_infos
)
156 error
= FT_Err_Invalid_Argument
;
161 /*** split font into SFNT tables ***/
163 for (j
= 0; j
< sfnt
->num_table_infos
; j
++)
165 SFNT_Table
*table_info
= &sfnt
->table_infos
[j
];
170 SFNT_Table
* tables_new
;
171 SFNT_Table
* table_last
;
178 buf
= (FT_Byte
*)malloc(table_info
->len
);
181 error
= FT_Err_Out_Of_Memory
;
186 error
= FT_Load_Sfnt_Table(sfnt
->face
, table_info
->tag
, 0,
187 buf
, &table_info
->len
);
191 /* check whether we already have this table */
192 for (k
= 0; k
< num_tables
; k
++)
196 if (table
->tag
== table_info
->tag
197 && table
->len
== table_info
->len
198 && !memcmp(table
->buf
, buf
, table
->len
))
202 /* add one element to table array if it's missing or not the same */
207 (SFNT_Table
*)realloc(tables
,
208 num_tables
* sizeof (SFNT_Table
));
211 error
= FT_Err_Out_Of_Memory
;
217 table_last
= &tables
[num_tables
- 1];
219 table_last
->tag
= table_info
->tag
;
220 table_last
->len
= table_info
->len
;
221 table_last
->buf
= buf
;
223 /* link buffer pointer */
224 table_info
->buf
= table_last
->buf
;
229 table_info
->buf
= tables
[k
].buf
;
235 /* compute global hints */
236 /* construct `fpgm' table */
237 /* construct `prep' table */
238 /* construct `cvt ' table */
240 /* split `glyf' table */
241 /* handle all glyphs in a loop */
244 /* construct bytecode */
246 /* construct `glyf' table */
247 /* build font from SFNT tables */
248 /* write font from memory */
253 /* in case of error it is expected that the unallocated pointers */
254 /* are NULL (and counters are zero) */
257 for (j
= 0; j
< num_tables
; j
++)
263 for (i
= 0; i
< num_sfnts
; i
++)
265 FT_Done_Face(sfnts
[i
].face
);
266 free(sfnts
[i
].table_infos
);
270 FT_Done_FreeType(lib
);
276 /* end of ttfautohint.c */