4 * Copyright (C) 2011-2017 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. */
27 #define COMPARE(str) \
28 (len == (sizeof (str) - 1) \
29 && !strncmp(start, str, sizeof (str) - 1))
33 TA_sfnt_set_properties(SFNT
* sfnt
,
36 TA_FaceGlobals globals
= (TA_FaceGlobals
)sfnt
->face
->autohint
.data
;
39 globals
->increase_x_height
= font
->increase_x_height
;
44 TTF_autohint(const char* options
,
53 char* error_string
= NULL
;
54 unsigned int errlinenum
= 0;
57 FT_Bool free_errline
= 0;
58 FT_Bool free_error_string
= 0;
61 FILE* out_file
= NULL
;
62 FILE* control_file
= NULL
;
64 FILE* reference_file
= NULL
;
65 FT_Long reference_index
= 0;
66 const char* reference_name
= NULL
;
68 const char* in_buf
= NULL
;
70 char** out_bufp
= NULL
;
71 size_t* out_lenp
= NULL
;
72 const char* control_buf
= NULL
;
73 size_t control_len
= 0;
74 const char* reference_buf
= NULL
;
75 size_t reference_len
= 0;
77 const unsigned char** error_stringp
= NULL
;
79 FT_Long hinting_range_min
= -1;
80 FT_Long hinting_range_max
= -1;
81 FT_Long hinting_limit
= -1;
82 FT_Long increase_x_height
= -1;
84 const char* x_height_snapping_exceptions_string
= NULL
;
85 number_range
* x_height_snapping_exceptions
= NULL
;
87 FT_Long fallback_stem_width
= 0;
89 FT_Bool gray_strong_stem_width
= 0;
90 FT_Bool gdi_cleartype_strong_stem_width
= 1;
91 FT_Bool dw_cleartype_strong_stem_width
= 0;
93 TA_Progress_Func progress
= NULL
;
94 void* progress_data
= NULL
;
95 TA_Error_Func err
= NULL
;
96 void* err_data
= NULL
;
97 TA_Info_Func info
= NULL
;
98 TA_Info_Post_Func info_post
= NULL
;
99 void* info_data
= NULL
;
101 FT_Bool windows_compatibility
= 0;
102 FT_Bool ignore_restrictions
= 0;
103 FT_Bool adjust_subglyphs
= 0;
104 FT_Bool hint_composites
= 0;
106 FT_Bool fallback_scaling
= 0;
108 const char* fallback_script_string
= NULL
;
109 const char* default_script_string
= NULL
;
111 TA_Style fallback_style
= TA_STYLE_NONE_DFLT
;
112 TA_Script default_script
= TA_SCRIPT_LATN
;
116 FT_Bool TTFA_info
= 0;
117 unsigned long long epoch
= ULLONG_MAX
;
121 if (!options
|| !*options
)
123 error
= FT_Err_Invalid_Argument
;
128 va_start(ap
, options
);
141 while (*op
&& *op
!= ',')
144 /* remove leading whitespace */
145 while (isspace(*start
))
148 /* check for empty option */
152 len
= (size_t)(op
- start
);
154 /* the `COMPARE' macro uses `len' and `start' */
156 /* handle options -- don't forget to update parameter dump below! */
157 if (COMPARE("adjust-subglyphs"))
158 adjust_subglyphs
= (FT_Bool
)va_arg(ap
, FT_Int
);
159 else if (COMPARE("control-buffer"))
162 control_buf
= va_arg(ap
, const char*);
164 else if (COMPARE("control-buffer-len"))
167 control_len
= va_arg(ap
, size_t);
169 else if (COMPARE("control-file"))
171 control_file
= va_arg(ap
, FILE*);
175 else if (COMPARE("debug"))
176 debug
= (FT_Bool
)va_arg(ap
, FT_Int
);
177 else if (COMPARE("default-script"))
178 default_script_string
= va_arg(ap
, const char*);
179 else if (COMPARE("dehint"))
180 dehint
= (FT_Bool
)va_arg(ap
, FT_Int
);
181 else if (COMPARE("dw-cleartype-strong-stem-width"))
182 dw_cleartype_strong_stem_width
= (FT_Bool
)va_arg(ap
, FT_Int
);
183 else if (COMPARE("epoch"))
184 epoch
= (unsigned long long)va_arg(ap
, unsigned long long);
185 else if (COMPARE("error-callback"))
186 err
= va_arg(ap
, TA_Error_Func
);
187 else if (COMPARE("error-callback-data"))
188 err_data
= va_arg(ap
, void*);
189 else if (COMPARE("error-string"))
190 error_stringp
= va_arg(ap
, const unsigned char**);
191 else if (COMPARE("fallback-scaling"))
192 fallback_scaling
= (FT_Bool
)va_arg(ap
, FT_Int
);
193 else if (COMPARE("fallback-script"))
194 fallback_script_string
= va_arg(ap
, const char*);
195 else if (COMPARE("fallback-stem-width"))
196 fallback_stem_width
= (FT_Long
)va_arg(ap
, FT_UInt
);
197 else if (COMPARE("gdi-cleartype-strong-stem-width"))
198 gdi_cleartype_strong_stem_width
= (FT_Bool
)va_arg(ap
, FT_Int
);
199 else if (COMPARE("gray-strong-stem-width"))
200 gray_strong_stem_width
= (FT_Bool
)va_arg(ap
, FT_Int
);
201 else if (COMPARE("hinting-limit"))
202 hinting_limit
= (FT_Long
)va_arg(ap
, FT_UInt
);
203 else if (COMPARE("hinting-range-max"))
204 hinting_range_max
= (FT_Long
)va_arg(ap
, FT_UInt
);
205 else if (COMPARE("hinting-range-min"))
206 hinting_range_min
= (FT_Long
)va_arg(ap
, FT_UInt
);
207 else if (COMPARE("hint-composites"))
208 hint_composites
= (FT_Bool
)va_arg(ap
, FT_Int
);
209 else if (COMPARE("ignore-restrictions"))
210 ignore_restrictions
= (FT_Bool
)va_arg(ap
, FT_Int
);
211 else if (COMPARE("in-buffer"))
214 in_buf
= va_arg(ap
, const char*);
216 else if (COMPARE("in-buffer-len"))
219 in_len
= va_arg(ap
, size_t);
221 else if (COMPARE("in-file"))
223 in_file
= va_arg(ap
, FILE*);
227 else if (COMPARE("increase-x-height"))
228 increase_x_height
= (FT_Long
)va_arg(ap
, FT_UInt
);
229 else if (COMPARE("info-callback"))
230 info
= va_arg(ap
, TA_Info_Func
);
231 else if (COMPARE("info-callback-data"))
232 info_data
= va_arg(ap
, void*);
233 else if (COMPARE("info-post-callback"))
234 info_post
= va_arg(ap
, TA_Info_Post_Func
);
235 else if (COMPARE("out-buffer"))
238 out_bufp
= va_arg(ap
, char**);
240 else if (COMPARE("out-buffer-len"))
243 out_lenp
= va_arg(ap
, size_t*);
245 else if (COMPARE("out-file"))
247 out_file
= va_arg(ap
, FILE*);
251 else if (COMPARE("pre-hinting"))
252 adjust_subglyphs
= (FT_Bool
)va_arg(ap
, FT_Int
);
253 else if (COMPARE("progress-callback"))
254 progress
= va_arg(ap
, TA_Progress_Func
);
255 else if (COMPARE("progress-callback-data"))
256 progress_data
= va_arg(ap
, void*);
257 else if (COMPARE("reference-buffer"))
259 reference_file
= NULL
;
260 reference_buf
= va_arg(ap
, const char*);
262 else if (COMPARE("reference-buffer-len"))
264 reference_file
= NULL
;
265 reference_len
= va_arg(ap
, size_t);
267 else if (COMPARE("reference-file"))
269 reference_file
= va_arg(ap
, FILE*);
270 reference_buf
= NULL
;
273 else if (COMPARE("reference-index"))
274 reference_index
= (FT_Long
)va_arg(ap
, FT_UInt
);
275 else if (COMPARE("reference-name"))
276 reference_name
= va_arg(ap
, const char*);
277 else if (COMPARE("symbol"))
278 symbol
= (FT_Bool
)va_arg(ap
, FT_Int
);
279 else if (COMPARE("TTFA-info"))
280 TTFA_info
= (FT_Bool
)va_arg(ap
, FT_Int
);
281 else if (COMPARE("windows-compatibility"))
282 windows_compatibility
= (FT_Bool
)va_arg(ap
, FT_Int
);
283 else if (COMPARE("x-height-snapping-exceptions"))
284 x_height_snapping_exceptions_string
= va_arg(ap
, const char*);
287 error
= TA_Err_Unknown_Argument
;
302 || (in_buf
&& in_len
)))
304 error
= FT_Err_Invalid_Argument
;
309 || (out_bufp
&& out_lenp
)))
311 error
= FT_Err_Invalid_Argument
;
315 font
= (FONT
*)calloc(1, sizeof (FONT
));
318 error
= FT_Err_Out_Of_Memory
;
325 if (hinting_range_min
>= 0 && hinting_range_min
< 2)
327 error
= FT_Err_Invalid_Argument
;
330 if (hinting_range_min
< 0)
331 hinting_range_min
= TA_HINTING_RANGE_MIN
;
333 if (hinting_range_max
>= 0 && hinting_range_max
< hinting_range_min
)
335 error
= FT_Err_Invalid_Argument
;
338 if (hinting_range_max
< 0)
339 hinting_range_max
= TA_HINTING_RANGE_MAX
;
341 /* value 0 is valid */
342 if (hinting_limit
> 0 && hinting_limit
< hinting_range_max
)
344 error
= FT_Err_Invalid_Argument
;
347 if (hinting_limit
< 0)
348 hinting_limit
= TA_HINTING_LIMIT
;
350 if (increase_x_height
> 0
351 && increase_x_height
< TA_PROP_INCREASE_X_HEIGHT_MIN
)
353 error
= FT_Err_Invalid_Argument
;
356 if (increase_x_height
< 0)
357 increase_x_height
= TA_INCREASE_X_HEIGHT
;
359 if (fallback_script_string
)
361 for (i
= 0; i
< TA_STYLE_MAX
; i
++)
363 TA_StyleClass style_class
= ta_style_classes
[i
];
366 if (style_class
->coverage
== TA_COVERAGE_DEFAULT
367 && !strcmp(script_names
[style_class
->script
],
368 fallback_script_string
))
371 if (i
== TA_STYLE_MAX
)
373 error
= FT_Err_Invalid_Argument
;
377 fallback_style
= (TA_Style
)i
;
380 if (default_script_string
)
382 for (i
= 0; i
< TA_SCRIPT_MAX
; i
++)
384 if (!strcmp(script_names
[i
], default_script_string
))
387 if (i
== TA_SCRIPT_MAX
)
389 error
= FT_Err_Invalid_Argument
;
393 default_script
= (TA_Script
)i
;
396 if (x_height_snapping_exceptions_string
)
398 const char* s
= number_set_parse(x_height_snapping_exceptions_string
,
399 &x_height_snapping_exceptions
,
400 TA_PROP_INCREASE_X_HEIGHT_MIN
,
404 /* we map numberset.h's error codes to values starting with 0x100 */
405 error
= 0x100 - (FT_Error
)(uintptr_t)x_height_snapping_exceptions
;
407 errline
= (char*)x_height_snapping_exceptions_string
;
414 font
->reference_index
= reference_index
;
415 font
->reference_name
= reference_name
;
417 font
->hinting_range_min
= (FT_UInt
)hinting_range_min
;
418 font
->hinting_range_max
= (FT_UInt
)hinting_range_max
;
419 font
->hinting_limit
= (FT_UInt
)hinting_limit
;
420 font
->increase_x_height
= (FT_UInt
)increase_x_height
;
421 font
->x_height_snapping_exceptions
= x_height_snapping_exceptions
;
422 font
->fallback_stem_width
= (FT_UInt
)fallback_stem_width
;
424 font
->gray_strong_stem_width
= gray_strong_stem_width
;
425 font
->gdi_cleartype_strong_stem_width
= gdi_cleartype_strong_stem_width
;
426 font
->dw_cleartype_strong_stem_width
= dw_cleartype_strong_stem_width
;
428 font
->windows_compatibility
= windows_compatibility
;
429 font
->ignore_restrictions
= ignore_restrictions
;
430 font
->adjust_subglyphs
= adjust_subglyphs
;
431 font
->hint_composites
= hint_composites
;
432 font
->fallback_style
= fallback_style
;
433 font
->fallback_scaling
= fallback_scaling
;
434 font
->default_script
= default_script
;
435 font
->symbol
= symbol
;
438 font
->progress
= progress
;
439 font
->progress_data
= progress_data
;
441 font
->info_post
= info_post
;
442 font
->info_data
= info_data
;
445 font
->dehint
= dehint
;
446 font
->TTFA_info
= TTFA_info
;
449 font
->gasp_idx
= MISSING
;
451 /* start with processing the data */
455 error
= TA_font_file_read(in_file
, &font
->in_buf
, &font
->in_len
);
461 /* a valid TTF can never be that small */
464 error
= TA_Err_Invalid_Font_Type
;
467 font
->in_buf
= (FT_Byte
*)in_buf
;
468 font
->in_len
= in_len
;
473 error
= TA_control_file_read(font
, control_file
);
477 else if (control_buf
)
479 font
->control_buf
= (char*)control_buf
;
480 font
->control_len
= control_len
;
485 error
= TA_font_file_read(reference_file
,
486 &font
->reference_buf
,
487 &font
->reference_len
);
491 else if (reference_buf
)
493 /* a valid TTF can never be that small */
494 if (reference_len
< 100)
496 error
= TA_Err_Invalid_Font_Type
+ 0x300;
499 font
->reference_buf
= (FT_Byte
*)reference_buf
;
500 font
->reference_len
= reference_len
;
503 error
= TA_font_init(font
);
510 _ta_debug_global
= 1;
513 /* we do some loops over all subfonts -- */
514 /* to process options early, just start with loading all of them */
515 for (i
= 0; i
< font
->num_sfnts
; i
++)
517 SFNT
* sfnt
= &font
->sfnts
[i
];
521 error
= FT_New_Memory_Face(font
->lib
,
523 (FT_Long
)font
->in_len
,
527 /* assure that the font hasn't been already processed by ttfautohint; */
528 /* another, more thorough check is done in TA_glyph_parse_simple */
529 idx
= FT_Get_Name_Index(sfnt
->face
, (FT_String
*)TTFAUTOHINT_GLYPH
);
532 error
= TA_Err_Already_Processed
;
540 /* process control instructions */
541 error
= TA_control_parse_buffer(font
,
543 &errlinenum
, &errline
, &errpos
);
547 free_error_string
= 1;
551 /* now we are able to dump all parameters */
557 s
= TA_font_dump_parameters(font
, 1);
560 error
= FT_Err_Out_Of_Memory
;
564 fprintf(stderr
, "%s", s
);
568 error
= TA_control_build_tree(font
);
572 /* loop again over subfonts and continue processing */
573 for (i
= 0; i
< font
->num_sfnts
; i
++)
575 SFNT
* sfnt
= &font
->sfnts
[i
];
578 error
= TA_sfnt_split_into_SFNT_tables(sfnt
, font
);
582 /* check permission */
583 if (sfnt
->OS2_idx
!= MISSING
)
585 SFNT_Table
* OS2_table
= &font
->tables
[sfnt
->OS2_idx
];
588 /* check lower byte of the `fsType' field */
589 if (OS2_table
->buf
[OS2_FSTYPE_OFFSET
+ 1] == 0x02
590 && !font
->ignore_restrictions
)
592 error
= TA_Err_Missing_Legal_Permission
;
599 error
= TA_sfnt_split_glyf_table(sfnt
, font
);
605 if (font
->adjust_subglyphs
)
606 error
= TA_sfnt_create_glyf_data(sfnt
, font
);
608 error
= TA_sfnt_split_glyf_table(sfnt
, font
);
612 /* this call creates a `globals' object... */
613 error
= TA_sfnt_handle_coverage(sfnt
, font
);
617 /* ... so that we now can initialize its properties */
618 TA_sfnt_set_properties(sfnt
, font
);
624 for (i
= 0; i
< font
->num_sfnts
; i
++)
626 SFNT
* sfnt
= &font
->sfnts
[i
];
629 TA_sfnt_adjust_coverage(sfnt
, font
);
634 /* this code is here for completeness -- */
635 /* right now, `glyf' tables get hinted only once, */
636 /* and referring subfonts simply reuse it, */
637 /* but this might change in the future */
641 for (i
= 0; i
< font
->num_sfnts
; i
++)
643 SFNT
* sfnt
= &font
->sfnts
[i
];
646 TA_sfnt_copy_master_coverage(sfnt
, font
);
653 for (i
= 0; i
< font
->num_sfnts
; i
++)
655 SFNT
* sfnt
= &font
->sfnts
[i
];
658 TA_control_apply_coverage(sfnt
, font
);
662 /* loop again over subfonts */
663 for (i
= 0; i
< font
->num_sfnts
; i
++)
665 SFNT
* sfnt
= &font
->sfnts
[i
];
668 error
= ta_loader_init(font
);
672 error
= TA_sfnt_build_gasp_table(sfnt
, font
);
677 error
= TA_sfnt_build_cvt_table(sfnt
, font
);
680 error
= TA_sfnt_build_fpgm_table(sfnt
, font
);
683 error
= TA_sfnt_build_prep_table(sfnt
, font
);
687 error
= TA_sfnt_build_glyf_table(sfnt
, font
);
690 error
= TA_sfnt_build_loca_table(sfnt
, font
);
694 ta_loader_done(font
);
697 for (i
= 0; i
< font
->num_sfnts
; i
++)
699 SFNT
* sfnt
= &font
->sfnts
[i
];
702 error
= TA_sfnt_update_maxp_table(sfnt
, font
);
708 /* we add one glyph for composites */
709 if (sfnt
->max_components
710 && !font
->adjust_subglyphs
711 && font
->hint_composites
)
713 error
= TA_sfnt_update_hmtx_table(sfnt
, font
);
716 error
= TA_sfnt_update_post_table(sfnt
, font
);
719 error
= TA_sfnt_update_GPOS_table(sfnt
, font
);
727 /* add info about ttfautohint to the version string */
728 error
= TA_sfnt_update_name_table(sfnt
, font
);
734 if (font
->num_sfnts
== 1)
735 error
= TA_font_build_TTF(font
);
737 error
= TA_font_build_TTC(font
);
743 error
= TA_font_file_write(font
, out_file
);
749 *out_bufp
= (char*)font
->out_buf
;
750 *out_lenp
= font
->out_len
;
756 TA_control_free(font
->control
);
757 TA_control_free_tree(font
);
758 TA_font_unload(font
, in_buf
, out_bufp
, control_buf
, reference_buf
);
765 /* use standard FreeType error strings for reference file errors */
766 if (error
>= 0x300 && error
< 0x400)
770 error_string
= (char*)TA_get_error_message(e
);
772 /* this must be a static value */
774 *error_stringp
= (const unsigned char*)TA_get_error_message(e
);
787 if (free_error_string
)
793 /* end of ttfautohint.c */