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_TABLES_H
15 #include FT_TRUETYPE_TAGS_H
17 #include "ttfautohint.h"
20 /* this structure represents both the data contained in the SFNT */
21 /* table records and the actual SFNT table data */
22 typedef struct SFNT_Table_
{
28 /* this structure is used to model a font within a TTC */
29 typedef struct SFNT_
{
31 SFNT_Table
* table_infos
;
32 FT_ULong num_table_infos
;
36 typedef struct FONT_
{
51 TA_font_load_into_memory(FILE* in
,
54 fseek(in
, 0, SEEK_END
);
55 font
->in_len
= ftell(in
);
56 fseek(in
, 0, SEEK_SET
);
58 /* a TTF can never be that small */
59 if (font
->in_len
< 100)
60 return FT_Err_Invalid_Argument
;
62 font
->in_buf
= (FT_Byte
*)malloc(font
->in_len
);
64 return FT_Err_Out_Of_Memory
;
66 if (fread(font
->in_buf
, 1, font
->in_len
, in
) != font
->in_len
)
67 return FT_Err_Invalid_Stream_Read
;
74 TA_font_init(FONT
* font
)
80 error
= FT_Init_FreeType(&font
->lib
);
84 /* get number of faces (i.e. subfonts) */
85 error
= FT_New_Memory_Face(font
->lib
, font
->in_buf
, font
->in_len
, -1, &f
);
88 font
->num_sfnts
= f
->num_faces
;
91 /* it is a TTC if we have more than a single subfont */
92 font
->sfnts
= (SFNT
*)calloc(1, font
->num_sfnts
* sizeof (SFNT
));
94 return FT_Err_Out_Of_Memory
;
101 TA_font_collect_table_info(SFNT
* sfnt
)
108 /* check that font is TTF */
109 if (!FT_IS_SFNT(sfnt
->face
))
110 return FT_Err_Invalid_Argument
;
112 error
= FT_Sfnt_Table_Info(sfnt
->face
, 0, NULL
, &sfnt
->num_table_infos
);
117 (SFNT_Table
*)calloc(1, sfnt
->num_table_infos
* sizeof (SFNT_Table
));
118 if (!sfnt
->table_infos
)
119 return FT_Err_Out_Of_Memory
;
121 /* collect SFNT table information and search for `glyf' table */
122 glyf_idx
= sfnt
->num_table_infos
;
123 for (i
= 0; i
< sfnt
->num_table_infos
; i
++)
128 error
= FT_Sfnt_Table_Info(sfnt
->face
, i
, &tag
, &len
);
129 if (error
&& error
!= FT_Err_Table_Missing
)
134 if (tag
== TTAG_glyf
)
137 /* ignore tables which we are going to create by ourselves */
138 if (!(tag
== TTAG_fpgm
142 sfnt
->table_infos
[i
].tag
= tag
;
143 sfnt
->table_infos
[i
].len
= len
;
148 /* no (non-empty) `glyf' table; this can't be a TTF with outlines */
149 if (glyf_idx
== sfnt
->num_table_infos
)
150 return FT_Err_Invalid_Argument
;
157 TA_font_split_into_SFNT_tables(SFNT
* sfnt
,
164 for (i
= 0; i
< sfnt
->num_table_infos
; i
++)
166 SFNT_Table
* table_info
= &sfnt
->table_infos
[i
];
169 /* we ignore empty tables */
176 buf
= (FT_Byte
*)malloc(table_info
->len
);
178 return FT_Err_Out_Of_Memory
;
181 error
= FT_Load_Sfnt_Table(sfnt
->face
, table_info
->tag
, 0,
182 buf
, &table_info
->len
);
186 /* check whether we already have this table */
187 for (j
= 0; j
< font
->num_tables
; j
++)
189 SFNT_Table
* table
= &font
->tables
[j
];
192 if (table
->tag
== table_info
->tag
193 && table
->len
== table_info
->len
194 && !memcmp(table
->buf
, buf
, table
->len
))
198 /* add element to table array if it's missing or not the same */
199 if (j
== font
->num_tables
)
201 SFNT_Table
* tables_new
;
202 SFNT_Table
* table_last
;
207 (SFNT_Table
*)realloc(font
->tables
,
208 font
->num_tables
* sizeof (SFNT_Table
));
211 error
= FT_Err_Out_Of_Memory
;
215 font
->tables
= tables_new
;
217 table_last
= &font
->tables
[font
->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
= font
->tables
[j
].buf
;
244 TA_font_unload(FONT
* font
)
246 /* in case of error it is expected that unallocated pointers */
247 /* are NULL (and counters are zero) */
257 for (i
= 0; i
< font
->num_tables
; i
++)
258 free(font
->tables
[i
].buf
);
267 for (i
= 0; i
< font
->num_sfnts
; i
++)
269 FT_Done_Face(font
->sfnts
[i
].face
);
270 free(font
->sfnts
[i
].table_infos
);
275 FT_Done_FreeType(font
->lib
);
282 TTF_autohint(FILE* in
,
290 font
= (FONT
*)calloc(1, sizeof (FONT
));
292 return FT_Err_Out_Of_Memory
;
294 error
= TA_font_load_into_memory(in
, font
);
298 error
= TA_font_init(font
);
302 /* loop over subfonts */
303 for (i
= 0; i
< font
->num_sfnts
; i
++)
305 SFNT
* sfnt
= &font
->sfnts
[i
];
308 error
= FT_New_Memory_Face(font
->lib
, font
->in_buf
, font
->in_len
,
313 error
= TA_font_collect_table_info(sfnt
);
317 error
= TA_font_split_into_SFNT_tables(sfnt
, font
);
323 /* compute global hints */
324 /* construct `fpgm' table */
325 /* construct `prep' table */
326 /* construct `cvt ' table */
328 /* split `glyf' table */
329 /* handle all glyphs in a loop */
332 /* construct bytecode */
334 /* construct `glyf' table */
335 /* build font from SFNT tables */
336 /* write font from memory */
341 TA_font_unload(font
);
346 /* end of ttfautohint.c */