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.
16 /* This file needs FreeType 2.4.5 or newer. */
26 #define COMPARE(str) (len == (sizeof (str) - 1) \
27 && !strncmp(start, str, sizeof (str) - 1))
31 TTF_autohint(const char* options
,
41 FILE* out_file
= NULL
;
43 const char* in_buf
= NULL
;
45 char** out_bufp
= NULL
;
46 size_t* out_lenp
= NULL
;
48 const unsigned char** error_stringp
= NULL
;
50 FT_Long hinting_range_min
= -1;
51 FT_Long hinting_range_max
= -1;
52 FT_Long hinting_limit
= -1;
54 TA_Progress_Func progress
;
59 FT_Bool ignore_permissions
= 0;
60 FT_Bool pre_hinting
= 0;
61 FT_Bool increase_x_height
= 0;
62 FT_UInt fallback_script
= 0;
68 if (!options
|| !*options
)
70 error
= FT_Err_Invalid_Argument
;
75 va_start(ap
, options
);
88 while (*op
&& *op
!= ',')
91 /* remove leading whitespace */
92 while (isspace(*start
))
95 /* check for empty option */
101 /* the `COMPARE' macro uses `len' and `start' */
104 if (COMPARE("error-string"))
105 error_stringp
= va_arg(ap
, const unsigned char**);
106 else if (COMPARE("fallback-script"))
107 fallback_script
= va_arg(ap
, FT_UInt
);
108 else if (COMPARE("hinting-limit"))
109 hinting_limit
= (FT_Long
)va_arg(ap
, FT_UInt
);
110 else if (COMPARE("hinting-range-max"))
111 hinting_range_max
= (FT_Long
)va_arg(ap
, FT_UInt
);
112 else if (COMPARE("hinting-range-min"))
113 hinting_range_min
= (FT_Long
)va_arg(ap
, FT_UInt
);
114 else if (COMPARE("ignore-permissions"))
115 ignore_permissions
= (FT_Bool
)va_arg(ap
, FT_Int
);
116 else if (COMPARE("in-buffer"))
119 in_buf
= va_arg(ap
, const char*);
121 else if (COMPARE("in-buffer-len"))
124 in_len
= va_arg(ap
, size_t);
126 else if (COMPARE("in-file"))
128 in_file
= va_arg(ap
, FILE*);
132 else if (COMPARE("increase-x-height"))
133 increase_x_height
= (FT_Bool
)va_arg(ap
, FT_Int
);
134 else if (COMPARE("out-buffer"))
137 out_bufp
= va_arg(ap
, char**);
139 else if (COMPARE("info-callback"))
140 info
= va_arg(ap
, TA_Info_Func
);
141 else if (COMPARE("info-callback-data"))
142 info_data
= va_arg(ap
, void*);
143 else if (COMPARE("out-buffer-len"))
146 out_lenp
= va_arg(ap
, size_t*);
148 else if (COMPARE("out-file"))
150 out_file
= va_arg(ap
, FILE*);
154 else if (COMPARE("pre-hinting"))
155 pre_hinting
= (FT_Bool
)va_arg(ap
, FT_Int
);
156 else if (COMPARE("progress-callback"))
157 progress
= va_arg(ap
, TA_Progress_Func
);
158 else if (COMPARE("progress-callback-data"))
159 progress_data
= va_arg(ap
, void*);
160 else if (COMPARE("symbol"))
161 symbol
= (FT_Bool
)va_arg(ap
, FT_Int
);
164 x-height-snapping-exceptions
178 || (in_buf
&& in_len
)))
180 error
= FT_Err_Invalid_Argument
;
185 || (out_bufp
&& out_lenp
)))
187 error
= FT_Err_Invalid_Argument
;
191 font
= (FONT
*)calloc(1, sizeof (FONT
));
194 error
= FT_Err_Out_Of_Memory
;
198 if (hinting_range_min
>= 0 && hinting_range_min
< 2)
200 error
= FT_Err_Invalid_Argument
;
203 if (hinting_range_min
< 0)
204 hinting_range_min
= TA_HINTING_RANGE_MIN
;
206 if (hinting_range_max
>= 0 && hinting_range_max
< hinting_range_min
)
208 error
= FT_Err_Invalid_Argument
;
211 if (hinting_range_max
< 0)
212 hinting_range_max
= TA_HINTING_RANGE_MAX
;
214 /* value 0 is valid */
215 if (hinting_limit
> 0 && hinting_limit
< hinting_range_max
)
217 error
= FT_Err_Invalid_Argument
;
220 if (hinting_limit
< 0)
221 hinting_limit
= TA_HINTING_LIMIT
;
223 font
->hinting_range_min
= (FT_UInt
)hinting_range_min
;
224 font
->hinting_range_max
= (FT_UInt
)hinting_range_max
;
225 font
->hinting_limit
= (FT_UInt
)hinting_limit
;
227 font
->progress
= progress
;
228 font
->progress_data
= progress_data
;
230 font
->info_data
= info_data
;
232 font
->ignore_permissions
= ignore_permissions
;
233 font
->pre_hinting
= pre_hinting
;
234 font
->increase_x_height
= increase_x_height
;
235 /* restrict value to two bits */
236 font
->fallback_script
= fallback_script
& 3;
237 font
->symbol
= symbol
;
239 /* now start with processing the data */
243 error
= TA_font_file_read(font
, in_file
);
249 /* a valid TTF can never be that small */
252 error
= FT_Err_Invalid_Argument
;
255 font
->in_buf
= (FT_Byte
*)in_buf
;
256 font
->in_len
= in_len
;
259 error
= TA_font_init(font
);
263 /* loop over subfonts */
264 for (i
= 0; i
< font
->num_sfnts
; i
++)
266 SFNT
* sfnt
= &font
->sfnts
[i
];
270 error
= FT_New_Memory_Face(font
->lib
, font
->in_buf
, font
->in_len
,
273 /* assure that the font hasn't been already processed by ttfautohint */
274 idx
= FT_Get_Name_Index(sfnt
->face
, TTFAUTOHINT_GLYPH
);
277 error
= TA_Err_Already_Processed
;
284 error
= TA_sfnt_split_into_SFNT_tables(sfnt
, font
);
288 if (font
->pre_hinting
)
289 error
= TA_sfnt_create_glyf_data(sfnt
, font
);
291 error
= TA_sfnt_split_glyf_table(sfnt
, font
);
295 /* check permission */
296 if (sfnt
->OS2_idx
!= MISSING
)
298 SFNT_Table
* OS2_table
= &font
->tables
[sfnt
->OS2_idx
];
301 /* check lower byte of the `fsType' field */
302 if (OS2_table
->buf
[OS2_FSTYPE_OFFSET
+ 1] == 0x02
303 && !font
->ignore_permissions
)
305 error
= TA_Err_Missing_Legal_Permission
;
311 /* build `gasp' table */
312 error
= TA_sfnt_build_gasp_table(&font
->sfnts
[0], font
);
316 /* XXX handle subfonts for bytecode tables */
318 /* build `cvt ' table */
319 error
= TA_sfnt_build_cvt_table(&font
->sfnts
[0], font
);
323 /* build `fpgm' table */
324 error
= TA_sfnt_build_fpgm_table(&font
->sfnts
[0], font
);
328 /* build `prep' table */
329 error
= TA_sfnt_build_prep_table(&font
->sfnts
[0], font
);
333 /* hint the glyphs and build bytecode */
334 error
= TA_sfnt_build_glyf_hints(&font
->sfnts
[0], font
);
338 /* loop again over subfonts */
339 for (i
= 0; i
< font
->num_sfnts
; i
++)
341 SFNT
* sfnt
= &font
->sfnts
[i
];
344 error
= TA_sfnt_build_glyf_table(sfnt
, font
);
347 error
= TA_sfnt_build_loca_table(sfnt
, font
);
350 error
= TA_sfnt_update_maxp_table(sfnt
, font
);
354 /* we add one glyph for composites */
355 if (sfnt
->max_components
&& !font
->pre_hinting
)
357 error
= TA_sfnt_update_hmtx_table(sfnt
, font
);
360 error
= TA_sfnt_update_post_table(sfnt
, font
);
363 error
= TA_sfnt_update_GPOS_table(sfnt
, font
);
370 /* add info about ttfautohint to the version string */
371 error
= TA_sfnt_update_name_table(sfnt
, font
);
377 if (font
->num_sfnts
== 1)
378 error
= TA_font_build_TTF(font
);
380 error
= TA_font_build_TTC(font
);
386 error
= TA_font_file_write(font
, out_file
);
392 *out_bufp
= (char*)font
->out_buf
;
393 *out_lenp
= font
->out_len
;
399 TA_font_unload(font
, in_buf
, out_bufp
);
403 *error_stringp
= (const unsigned char*)TA_get_error_message(error
);
408 /* end of ttfautohint.c */