4 * Copyright (C) 2011-2014 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 DUMPVAL(str, arg) \
30 fprintf(stderr, "%33s = %ld\n", \
33 #define DUMPSTR(str, arg) \
34 fprintf(stderr, "%33s = %s\n", \
40 TA_sfnt_set_properties(SFNT
* sfnt
,
43 TA_FaceGlobals globals
= (TA_FaceGlobals
)sfnt
->face
->autohint
.data
;
46 globals
->increase_x_height
= font
->increase_x_height
;
51 TTF_autohint(const char* options
,
61 FILE* out_file
= NULL
;
63 const char* in_buf
= NULL
;
65 char** out_bufp
= NULL
;
66 size_t* out_lenp
= NULL
;
68 const unsigned char** error_stringp
= NULL
;
70 FT_Long hinting_range_min
= -1;
71 FT_Long hinting_range_max
= -1;
72 FT_Long hinting_limit
= -1;
73 FT_Long increase_x_height
= -1;
75 const char* x_height_snapping_exceptions_string
= NULL
;
76 number_range
* x_height_snapping_exceptions
= NULL
;
78 FT_Bool gray_strong_stem_width
= 0;
79 FT_Bool gdi_cleartype_strong_stem_width
= 1;
80 FT_Bool dw_cleartype_strong_stem_width
= 0;
82 TA_Progress_Func progress
;
87 FT_Bool windows_compatibility
= 0;
88 FT_Bool ignore_restrictions
= 0;
89 FT_Bool pre_hinting
= 0;
90 FT_Bool hint_composites
= 0;
93 const char* fallback_script_string
= NULL
;
94 TA_Script fallback_script
= TA_SCRIPT_NONE
;
103 #define SCRIPT(s, S, d) #s,
105 const char* script_names
[] =
108 #include <ttfautohint-scripts.h>
113 if (!options
|| !*options
)
115 error
= FT_Err_Invalid_Argument
;
120 va_start(ap
, options
);
133 while (*op
&& *op
!= ',')
136 /* remove leading whitespace */
137 while (isspace(*start
))
140 /* check for empty option */
146 /* the `COMPARE' macro uses `len' and `start' */
148 /* handle options -- don't forget to update parameter dump below! */
149 if (COMPARE("debug"))
150 debug
= (FT_Bool
)va_arg(ap
, FT_Int
);
151 else if (COMPARE("dehint"))
152 dehint
= (FT_Bool
)va_arg(ap
, FT_Int
);
153 else if (COMPARE("dw-cleartype-strong-stem-width"))
154 dw_cleartype_strong_stem_width
= (FT_Bool
)va_arg(ap
, FT_Int
);
155 else if (COMPARE("error-string"))
156 error_stringp
= va_arg(ap
, const unsigned char**);
157 else if (COMPARE("fallback-script"))
158 fallback_script_string
= va_arg(ap
, const char*);
159 else if (COMPARE("gdi-cleartype-strong-stem-width"))
160 gdi_cleartype_strong_stem_width
= (FT_Bool
)va_arg(ap
, FT_Int
);
161 else if (COMPARE("gray-strong-stem-width"))
162 gray_strong_stem_width
= (FT_Bool
)va_arg(ap
, FT_Int
);
163 else if (COMPARE("hinting-limit"))
164 hinting_limit
= (FT_Long
)va_arg(ap
, FT_UInt
);
165 else if (COMPARE("hinting-range-max"))
166 hinting_range_max
= (FT_Long
)va_arg(ap
, FT_UInt
);
167 else if (COMPARE("hinting-range-min"))
168 hinting_range_min
= (FT_Long
)va_arg(ap
, FT_UInt
);
169 else if (COMPARE("hint-composites"))
170 hint_composites
= (FT_Bool
)va_arg(ap
, FT_Int
);
171 else if (COMPARE("ignore-restrictions"))
172 ignore_restrictions
= (FT_Bool
)va_arg(ap
, FT_Int
);
173 else if (COMPARE("in-buffer"))
176 in_buf
= va_arg(ap
, const char*);
178 else if (COMPARE("in-buffer-len"))
181 in_len
= va_arg(ap
, size_t);
183 else if (COMPARE("in-file"))
185 in_file
= va_arg(ap
, FILE*);
189 else if (COMPARE("increase-x-height"))
190 increase_x_height
= (FT_Long
)va_arg(ap
, FT_UInt
);
191 else if (COMPARE("info-callback"))
192 info
= va_arg(ap
, TA_Info_Func
);
193 else if (COMPARE("info-callback-data"))
194 info_data
= va_arg(ap
, void*);
195 else if (COMPARE("out-buffer"))
198 out_bufp
= va_arg(ap
, char**);
200 else if (COMPARE("out-buffer-len"))
203 out_lenp
= va_arg(ap
, size_t*);
205 else if (COMPARE("out-file"))
207 out_file
= va_arg(ap
, FILE*);
211 else if (COMPARE("pre-hinting"))
212 pre_hinting
= (FT_Bool
)va_arg(ap
, FT_Int
);
213 else if (COMPARE("progress-callback"))
214 progress
= va_arg(ap
, TA_Progress_Func
);
215 else if (COMPARE("progress-callback-data"))
216 progress_data
= va_arg(ap
, void*);
217 else if (COMPARE("symbol"))
218 symbol
= (FT_Bool
)va_arg(ap
, FT_Int
);
219 else if (COMPARE("windows-compatibility"))
220 windows_compatibility
= (FT_Bool
)va_arg(ap
, FT_Int
);
221 else if (COMPARE("x-height-snapping-exceptions"))
222 x_height_snapping_exceptions_string
= va_arg(ap
, const char*);
225 error
= TA_Err_Unknown_Argument
;
240 || (in_buf
&& in_len
)))
242 error
= FT_Err_Invalid_Argument
;
247 || (out_bufp
&& out_lenp
)))
249 error
= FT_Err_Invalid_Argument
;
253 font
= (FONT
*)calloc(1, sizeof (FONT
));
256 error
= FT_Err_Out_Of_Memory
;
263 if (hinting_range_min
>= 0 && hinting_range_min
< 2)
265 error
= FT_Err_Invalid_Argument
;
268 if (hinting_range_min
< 0)
269 hinting_range_min
= TA_HINTING_RANGE_MIN
;
271 if (hinting_range_max
>= 0 && hinting_range_max
< hinting_range_min
)
273 error
= FT_Err_Invalid_Argument
;
276 if (hinting_range_max
< 0)
277 hinting_range_max
= TA_HINTING_RANGE_MAX
;
279 /* value 0 is valid */
280 if (hinting_limit
> 0 && hinting_limit
< hinting_range_max
)
282 error
= FT_Err_Invalid_Argument
;
285 if (hinting_limit
< 0)
286 hinting_limit
= TA_HINTING_LIMIT
;
288 if (increase_x_height
> 0
289 && increase_x_height
< TA_PROP_INCREASE_X_HEIGHT_MIN
)
291 error
= FT_Err_Invalid_Argument
;
294 if (increase_x_height
< 0)
295 increase_x_height
= TA_INCREASE_X_HEIGHT
;
297 if (fallback_script_string
)
302 for (i
= 0; i
< TA_STYLE_MAX
; i
++)
303 if (!strcmp(script_names
[i
], fallback_script_string
))
305 if (i
== TA_STYLE_MAX
)
307 error
= FT_Err_Invalid_Argument
;
314 if (x_height_snapping_exceptions_string
)
316 const char* s
= number_set_parse(x_height_snapping_exceptions_string
,
317 &x_height_snapping_exceptions
,
318 TA_PROP_INCREASE_X_HEIGHT_MIN
,
322 error
= FT_Err_Invalid_Argument
;
327 font
->hinting_range_min
= (FT_UInt
)hinting_range_min
;
328 font
->hinting_range_max
= (FT_UInt
)hinting_range_max
;
329 font
->hinting_limit
= (FT_UInt
)hinting_limit
;
330 font
->increase_x_height
= increase_x_height
;
331 font
->x_height_snapping_exceptions
= x_height_snapping_exceptions
;
333 font
->gray_strong_stem_width
= gray_strong_stem_width
;
334 font
->gdi_cleartype_strong_stem_width
= gdi_cleartype_strong_stem_width
;
335 font
->dw_cleartype_strong_stem_width
= dw_cleartype_strong_stem_width
;
337 font
->windows_compatibility
= windows_compatibility
;
338 font
->ignore_restrictions
= ignore_restrictions
;
339 font
->pre_hinting
= pre_hinting
;
340 font
->hint_composites
= hint_composites
;
341 font
->fallback_style
= fallback_style
;
342 font
->symbol
= symbol
;
345 font
->progress
= progress
;
346 font
->progress_data
= progress_data
;
348 font
->info_data
= info_data
;
351 font
->dehint
= dehint
;
353 font
->gasp_idx
= MISSING
;
355 /* dump parameters */
358 fprintf(stderr
, "TTF_autohint parameters\n"
359 "=======================\n"
370 DUMPVAL("dw-cleartype-strong-stem-width",
371 font
->dw_cleartype_strong_stem_width
);
372 DUMPSTR("fallback-script",
373 script_names
[font
->fallback_script
]);
374 DUMPVAL("gdi-cleartype-strong-stem-width",
375 font
->gdi_cleartype_strong_stem_width
);
376 DUMPVAL("gray-strong-stem-width",
377 font
->gray_strong_stem_width
);
378 DUMPVAL("hinting-limit",
379 font
->hinting_limit
);
380 DUMPVAL("hinting-range-max",
381 font
->hinting_range_max
);
382 DUMPVAL("hinting-range-min",
383 font
->hinting_range_min
);
384 DUMPVAL("hint-composites",
385 font
->hint_composites
);
386 DUMPVAL("ignore-restrictions",
387 font
->ignore_restrictions
);
388 DUMPVAL("increase-x-height",
389 font
->increase_x_height
);
390 DUMPVAL("pre-hinting",
394 DUMPVAL("windows-compatibility",
395 font
->windows_compatibility
);
397 s
= number_set_show(font
->x_height_snapping_exceptions
,
398 TA_PROP_INCREASE_X_HEIGHT_MIN
, 0x7FFF);
399 DUMPSTR("x-height-snapping-exceptions", s
);
403 fprintf(stderr
, "\n");
406 /* now start with processing the data */
410 error
= TA_font_file_read(font
, in_file
);
416 /* a valid TTF can never be that small */
419 error
= TA_Err_Invalid_Font_Type
;
422 font
->in_buf
= (FT_Byte
*)in_buf
;
423 font
->in_len
= in_len
;
426 error
= TA_font_init(font
);
433 _ta_debug_global
= 1;
436 /* we do some loops over all subfonts */
437 for (i
= 0; i
< font
->num_sfnts
; i
++)
439 SFNT
* sfnt
= &font
->sfnts
[i
];
443 error
= FT_New_Memory_Face(font
->lib
, font
->in_buf
, font
->in_len
,
446 /* assure that the font hasn't been already processed by ttfautohint; */
447 /* another, more thorough check is done in TA_glyph_parse_simple */
448 idx
= FT_Get_Name_Index(sfnt
->face
, TTFAUTOHINT_GLYPH
);
451 error
= TA_Err_Already_Processed
;
458 error
= TA_sfnt_split_into_SFNT_tables(sfnt
, font
);
462 /* check permission */
463 if (sfnt
->OS2_idx
!= MISSING
)
465 SFNT_Table
* OS2_table
= &font
->tables
[sfnt
->OS2_idx
];
468 /* check lower byte of the `fsType' field */
469 if (OS2_table
->buf
[OS2_FSTYPE_OFFSET
+ 1] == 0x02
470 && !font
->ignore_restrictions
)
472 error
= TA_Err_Missing_Legal_Permission
;
479 error
= TA_sfnt_split_glyf_table(sfnt
, font
);
485 if (font
->pre_hinting
)
486 error
= TA_sfnt_create_glyf_data(sfnt
, font
);
488 error
= TA_sfnt_split_glyf_table(sfnt
, font
);
492 /* this call creates a `globals' object... */
493 error
= TA_sfnt_handle_coverage(sfnt
, font
);
497 /* ... so that we now can initialize its properties */
498 TA_sfnt_set_properties(sfnt
, font
);
504 for (i
= 0; i
< font
->num_sfnts
; i
++)
506 SFNT
* sfnt
= &font
->sfnts
[i
];
509 if (TA_sfnt_adjust_master_coverage(sfnt
, font
))
515 /* this code is here for completeness -- */
516 /* right now, `glyf' tables get hinted only once, */
517 /* and referring subfonts simply reuse it, */
518 /* but this might change in the future */
522 for (i
= 0; i
< font
->num_sfnts
; i
++)
524 SFNT
* sfnt
= &font
->sfnts
[i
];
527 TA_sfnt_copy_master_coverage(sfnt
, font
);
532 /* loop again over subfonts */
533 for (i
= 0; i
< font
->num_sfnts
; i
++)
535 SFNT
* sfnt
= &font
->sfnts
[i
];
538 error
= ta_loader_init(font
);
542 error
= TA_sfnt_build_gasp_table(sfnt
, font
);
547 error
= TA_sfnt_build_cvt_table(sfnt
, font
);
550 error
= TA_sfnt_build_fpgm_table(sfnt
, font
);
553 error
= TA_sfnt_build_prep_table(sfnt
, font
);
557 error
= TA_sfnt_build_glyf_table(sfnt
, font
);
560 error
= TA_sfnt_build_loca_table(sfnt
, font
);
565 ta_loader_done(font
);
568 for (i
= 0; i
< font
->num_sfnts
; i
++)
570 SFNT
* sfnt
= &font
->sfnts
[i
];
573 error
= TA_sfnt_update_maxp_table(sfnt
, font
);
579 /* we add one glyph for composites */
580 if (sfnt
->max_components
581 && !font
->pre_hinting
582 && font
->hint_composites
)
584 error
= TA_sfnt_update_hmtx_table(sfnt
, font
);
587 error
= TA_sfnt_update_post_table(sfnt
, font
);
590 error
= TA_sfnt_update_GPOS_table(sfnt
, font
);
598 /* add info about ttfautohint to the version string */
599 error
= TA_sfnt_update_name_table(sfnt
, font
);
605 if (font
->num_sfnts
== 1)
606 error
= TA_font_build_TTF(font
);
608 error
= TA_font_build_TTC(font
);
614 error
= TA_font_file_write(font
, out_file
);
620 *out_bufp
= (char*)font
->out_buf
;
621 *out_lenp
= font
->out_len
;
627 TA_font_unload(font
, in_buf
, out_bufp
);
631 *error_stringp
= (const unsigned char*)TA_get_error_message(error
);
636 /* end of ttfautohint.c */