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) \
27 (len == (sizeof (str) - 1) \
28 && !strncmp(start, str, sizeof (str) - 1))
29 #define DUMP(str, arg) \
30 fprintf(stderr, "%33s = %ld\n", \
36 TTF_autohint(const char* options
,
46 FILE* out_file
= NULL
;
48 const char* in_buf
= NULL
;
50 char** out_bufp
= NULL
;
51 size_t* out_lenp
= NULL
;
53 const unsigned char** error_stringp
= NULL
;
55 FT_Long hinting_range_min
= -1;
56 FT_Long hinting_range_max
= -1;
57 FT_Long hinting_limit
= -1;
58 FT_Long increase_x_height
= -1;
60 FT_Bool gray_strong_stem_width
= 0;
61 FT_Bool gdi_cleartype_strong_stem_width
= 1;
62 FT_Bool dw_cleartype_strong_stem_width
= 0;
64 TA_Progress_Func progress
;
69 FT_Bool ignore_restrictions
= 0;
70 FT_Bool pre_hinting
= 0;
71 FT_Bool hint_with_components
= 0;
72 FT_UInt fallback_script
= TA_SCRIPT_FALLBACK
;
80 if (!options
|| !*options
)
82 error
= FT_Err_Invalid_Argument
;
87 va_start(ap
, options
);
100 while (*op
&& *op
!= ',')
103 /* remove leading whitespace */
104 while (isspace(*start
))
107 /* check for empty option */
113 /* the `COMPARE' macro uses `len' and `start' */
115 /* handle options -- don't forget to update parameter dump below! */
116 if (COMPARE("debug"))
117 debug
= (FT_Bool
)va_arg(ap
, FT_Int
);
118 else if (COMPARE("dw-cleartype-strong-stem-width"))
119 dw_cleartype_strong_stem_width
= (FT_Bool
)va_arg(ap
, FT_Int
);
120 else if (COMPARE("error-string"))
121 error_stringp
= va_arg(ap
, const unsigned char**);
122 else if (COMPARE("fallback-script"))
123 fallback_script
= va_arg(ap
, FT_UInt
);
124 else if (COMPARE("gdi-cleartype-strong-stem-width"))
125 gdi_cleartype_strong_stem_width
= (FT_Bool
)va_arg(ap
, FT_Int
);
126 else if (COMPARE("gray-strong-stem-width"))
127 gray_strong_stem_width
= (FT_Bool
)va_arg(ap
, FT_Int
);
128 else if (COMPARE("hinting-limit"))
129 hinting_limit
= (FT_Long
)va_arg(ap
, FT_UInt
);
130 else if (COMPARE("hinting-range-max"))
131 hinting_range_max
= (FT_Long
)va_arg(ap
, FT_UInt
);
132 else if (COMPARE("hinting-range-min"))
133 hinting_range_min
= (FT_Long
)va_arg(ap
, FT_UInt
);
134 else if (COMPARE("hint-with-components"))
135 hint_with_components
= (FT_Bool
)va_arg(ap
, FT_Int
);
136 else if (COMPARE("ignore-restrictions"))
137 ignore_restrictions
= (FT_Bool
)va_arg(ap
, FT_Int
);
138 else if (COMPARE("in-buffer"))
141 in_buf
= va_arg(ap
, const char*);
143 else if (COMPARE("in-buffer-len"))
146 in_len
= va_arg(ap
, size_t);
148 else if (COMPARE("in-file"))
150 in_file
= va_arg(ap
, FILE*);
154 else if (COMPARE("increase-x-height"))
155 increase_x_height
= (FT_Long
)va_arg(ap
, FT_UInt
);
156 else if (COMPARE("info-callback"))
157 info
= va_arg(ap
, TA_Info_Func
);
158 else if (COMPARE("info-callback-data"))
159 info_data
= va_arg(ap
, void*);
160 else if (COMPARE("out-buffer"))
163 out_bufp
= va_arg(ap
, char**);
165 else if (COMPARE("out-buffer-len"))
168 out_lenp
= va_arg(ap
, size_t*);
170 else if (COMPARE("out-file"))
172 out_file
= va_arg(ap
, FILE*);
176 else if (COMPARE("pre-hinting"))
177 pre_hinting
= (FT_Bool
)va_arg(ap
, FT_Int
);
178 else if (COMPARE("progress-callback"))
179 progress
= va_arg(ap
, TA_Progress_Func
);
180 else if (COMPARE("progress-callback-data"))
181 progress_data
= va_arg(ap
, void*);
182 else if (COMPARE("symbol"))
183 symbol
= (FT_Bool
)va_arg(ap
, FT_Int
);
186 error
= TA_Err_Unknown_Argument
;
191 x-height-snapping-exceptions
205 || (in_buf
&& in_len
)))
207 error
= FT_Err_Invalid_Argument
;
212 || (out_bufp
&& out_lenp
)))
214 error
= FT_Err_Invalid_Argument
;
218 font
= (FONT
*)calloc(1, sizeof (FONT
));
221 error
= FT_Err_Out_Of_Memory
;
225 if (hinting_range_min
>= 0 && hinting_range_min
< 2)
227 error
= FT_Err_Invalid_Argument
;
230 if (hinting_range_min
< 0)
231 hinting_range_min
= TA_HINTING_RANGE_MIN
;
233 if (hinting_range_max
>= 0 && hinting_range_max
< hinting_range_min
)
235 error
= FT_Err_Invalid_Argument
;
238 if (hinting_range_max
< 0)
239 hinting_range_max
= TA_HINTING_RANGE_MAX
;
241 /* value 0 is valid */
242 if (hinting_limit
> 0 && hinting_limit
< hinting_range_max
)
244 error
= FT_Err_Invalid_Argument
;
247 if (hinting_limit
< 0)
248 hinting_limit
= TA_HINTING_LIMIT
;
250 if (increase_x_height
> 0 && increase_x_height
< 6)
252 error
= FT_Err_Invalid_Argument
;
255 if (increase_x_height
< 0)
256 increase_x_height
= TA_INCREASE_X_HEIGHT
;
258 font
->hinting_range_min
= (FT_UInt
)hinting_range_min
;
259 font
->hinting_range_max
= (FT_UInt
)hinting_range_max
;
260 font
->hinting_limit
= (FT_UInt
)hinting_limit
;
261 font
->increase_x_height
= increase_x_height
;
263 font
->gray_strong_stem_width
= gray_strong_stem_width
;
264 font
->gdi_cleartype_strong_stem_width
= gdi_cleartype_strong_stem_width
;
265 font
->dw_cleartype_strong_stem_width
= dw_cleartype_strong_stem_width
;
267 font
->progress
= progress
;
268 font
->progress_data
= progress_data
;
270 font
->info_data
= info_data
;
272 font
->ignore_restrictions
= ignore_restrictions
;
273 font
->pre_hinting
= pre_hinting
;
274 font
->hint_with_components
= hint_with_components
;
275 font
->fallback_script
= fallback_script
;
276 font
->symbol
= symbol
;
278 font
->gasp_idx
= MISSING
;
282 /* dump parameters */
285 fprintf(stderr
, "TTF_autohint parameters\n"
286 "=======================\n\n");
288 DUMP("dw-cleartype-strong-stem-width",
289 font
->dw_cleartype_strong_stem_width
);
290 DUMP("fallback-script",
291 font
->fallback_script
);
292 DUMP("gdi-cleartype-strong-stem-width",
293 font
->gdi_cleartype_strong_stem_width
);
294 DUMP("gray-strong-stem-width",
295 font
->gray_strong_stem_width
);
296 DUMP("hinting-limit",
297 font
->hinting_limit
);
298 DUMP("hinting-range-max",
299 font
->hinting_range_max
);
300 DUMP("hinting-range-min",
301 font
->hinting_range_min
);
302 DUMP("hint-with-components",
303 font
->hint_with_components
);
304 DUMP("ignore-restrictions",
305 font
->ignore_restrictions
);
306 DUMP("increase-x-height",
307 font
->increase_x_height
);
313 fprintf(stderr
, "\n");
316 /* now start with processing the data */
320 error
= TA_font_file_read(font
, in_file
);
326 /* a valid TTF can never be that small */
329 error
= TA_Err_Invalid_Font_Type
;
332 font
->in_buf
= (FT_Byte
*)in_buf
;
333 font
->in_len
= in_len
;
336 error
= TA_font_init(font
);
343 /* we do some loops over all subfonts */
344 for (i
= 0; i
< font
->num_sfnts
; i
++)
346 SFNT
* sfnt
= &font
->sfnts
[i
];
350 error
= FT_New_Memory_Face(font
->lib
, font
->in_buf
, font
->in_len
,
353 /* assure that the font hasn't been already processed by ttfautohint; */
354 /* another, more thorough check is done in TA_glyph_parse_simple */
355 idx
= FT_Get_Name_Index(sfnt
->face
, TTFAUTOHINT_GLYPH
);
358 error
= TA_Err_Already_Processed
;
365 error
= TA_sfnt_split_into_SFNT_tables(sfnt
, font
);
369 if (font
->pre_hinting
)
370 error
= TA_sfnt_create_glyf_data(sfnt
, font
);
372 error
= TA_sfnt_split_glyf_table(sfnt
, font
);
376 error
= TA_sfnt_handle_coverage(sfnt
, font
);
380 /* check permission */
381 if (sfnt
->OS2_idx
!= MISSING
)
383 SFNT_Table
* OS2_table
= &font
->tables
[sfnt
->OS2_idx
];
386 /* check lower byte of the `fsType' field */
387 if (OS2_table
->buf
[OS2_FSTYPE_OFFSET
+ 1] == 0x02
388 && !font
->ignore_restrictions
)
390 error
= TA_Err_Missing_Legal_Permission
;
396 for (i
= 0; i
< font
->num_sfnts
; i
++)
398 SFNT
* sfnt
= &font
->sfnts
[i
];
401 TA_sfnt_adjust_master_coverage(sfnt
, font
);
405 /* this code is here for completeness -- */
406 /* right now, `glyf' tables get hinted only once, */
407 /* and referring subfonts simply reuse it, */
408 /* but this might change in the future */
410 for (i
= 0; i
< font
->num_sfnts
; i
++)
412 SFNT
* sfnt
= &font
->sfnts
[i
];
415 TA_sfnt_copy_master_coverage(sfnt
, font
);
419 /* loop again over subfonts */
420 for (i
= 0; i
< font
->num_sfnts
; i
++)
422 SFNT
* sfnt
= &font
->sfnts
[i
];
425 error
= ta_loader_init(font
);
429 error
= TA_sfnt_build_gasp_table(sfnt
, font
);
432 error
= TA_sfnt_build_cvt_table(sfnt
, font
);
435 error
= TA_sfnt_build_fpgm_table(sfnt
, font
);
438 error
= TA_sfnt_build_prep_table(sfnt
, font
);
441 error
= TA_sfnt_build_glyf_table(sfnt
, font
);
444 error
= TA_sfnt_build_loca_table(sfnt
, font
);
449 ta_loader_done(font
);
452 for (i
= 0; i
< font
->num_sfnts
; i
++)
454 SFNT
* sfnt
= &font
->sfnts
[i
];
457 error
= TA_sfnt_update_maxp_table(sfnt
, font
);
461 /* we add one glyph for composites */
462 if (sfnt
->max_components
463 && !font
->pre_hinting
464 && font
->hint_with_components
)
466 error
= TA_sfnt_update_hmtx_table(sfnt
, font
);
469 error
= TA_sfnt_update_post_table(sfnt
, font
);
472 error
= TA_sfnt_update_GPOS_table(sfnt
, font
);
479 /* add info about ttfautohint to the version string */
480 error
= TA_sfnt_update_name_table(sfnt
, font
);
486 if (font
->num_sfnts
== 1)
487 error
= TA_font_build_TTF(font
);
489 error
= TA_font_build_TTC(font
);
495 error
= TA_font_file_write(font
, out_file
);
501 *out_bufp
= (char*)font
->out_buf
;
502 *out_lenp
= font
->out_len
;
508 TA_font_unload(font
, in_buf
, out_bufp
);
512 *error_stringp
= (const unsigned char*)TA_get_error_message(error
);
517 /* end of ttfautohint.c */