4 * Copyright (C) 2011-2020 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
;
43 TA_LIB_EXPORT TA_Error
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_Int gray_stem_width_mode
= TA_STEM_WIDTH_MODE_QUANTIZED
;
90 FT_Int gdi_cleartype_stem_width_mode
= TA_STEM_WIDTH_MODE_STRONG
;
91 FT_Int dw_cleartype_stem_width_mode
= TA_STEM_WIDTH_MODE_QUANTIZED
;
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 TA_Alloc_Func allocate
= NULL
;
102 TA_Free_Func deallocate
= NULL
;
104 FT_Bool windows_compatibility
= 0;
105 FT_Bool ignore_restrictions
= 0;
106 FT_Bool adjust_subglyphs
= 0;
107 FT_Bool hint_composites
= 0;
109 FT_Bool fallback_scaling
= 0;
111 const char* fallback_script_string
= NULL
;
112 const char* default_script_string
= NULL
;
114 TA_Style fallback_style
= TA_STYLE_NONE_DFLT
;
115 TA_Script default_script
= TA_SCRIPT_LATN
;
119 FT_Bool TTFA_info
= 0;
120 unsigned long long epoch
= ULLONG_MAX
;
124 if (!options
|| !*options
)
126 error
= FT_Err_Invalid_Argument
;
131 va_start(ap
, options
);
144 while (*op
&& *op
!= ',')
147 /* remove leading whitespace */
148 while (isspace(*start
))
151 /* check for empty option */
155 len
= (size_t)(op
- start
);
157 /* the `COMPARE' macro uses `len' and `start' */
159 /* handle options -- don't forget to update parameter dump below! */
160 if (COMPARE("adjust-subglyphs"))
161 adjust_subglyphs
= (FT_Bool
)va_arg(ap
, FT_Int
);
162 else if (COMPARE("alloc-func"))
163 allocate
= va_arg(ap
, TA_Alloc_Func
);
164 else if (COMPARE("control-buffer"))
167 control_buf
= va_arg(ap
, const char*);
169 else if (COMPARE("control-buffer-len"))
172 control_len
= va_arg(ap
, size_t);
174 else if (COMPARE("control-file"))
176 control_file
= va_arg(ap
, FILE*);
180 else if (COMPARE("debug"))
181 debug
= (FT_Bool
)va_arg(ap
, FT_Int
);
182 else if (COMPARE("default-script"))
183 default_script_string
= va_arg(ap
, const char*);
184 else if (COMPARE("dehint"))
185 dehint
= (FT_Bool
)va_arg(ap
, FT_Int
);
186 else if (COMPARE("dw-cleartype-stem-width-mode"))
187 dw_cleartype_stem_width_mode
= va_arg(ap
, FT_Int
);
188 else if (COMPARE("dw-cleartype-strong-stem-width"))
190 FT_Bool arg
= (FT_Bool
)va_arg(ap
, FT_Int
);
193 dw_cleartype_stem_width_mode
= arg
? TA_STEM_WIDTH_MODE_STRONG
194 : TA_STEM_WIDTH_MODE_QUANTIZED
;
196 else if (COMPARE("epoch"))
197 epoch
= (unsigned long long)va_arg(ap
, unsigned long long);
198 else if (COMPARE("error-callback"))
199 err
= va_arg(ap
, TA_Error_Func
);
200 else if (COMPARE("error-callback-data"))
201 err_data
= va_arg(ap
, void*);
202 else if (COMPARE("error-string"))
203 error_stringp
= va_arg(ap
, const unsigned char**);
204 else if (COMPARE("fallback-scaling"))
205 fallback_scaling
= (FT_Bool
)va_arg(ap
, FT_Int
);
206 else if (COMPARE("fallback-script"))
207 fallback_script_string
= va_arg(ap
, const char*);
208 else if (COMPARE("fallback-stem-width"))
209 fallback_stem_width
= (FT_Long
)va_arg(ap
, FT_UInt
);
210 else if (COMPARE("free-func"))
211 deallocate
= va_arg(ap
, TA_Free_Func
);
212 else if (COMPARE("gdi-cleartype-stem-width-mode"))
213 gdi_cleartype_stem_width_mode
= va_arg(ap
, FT_Int
);
214 else if (COMPARE("gdi-cleartype-strong-stem-width"))
216 FT_Bool arg
= (FT_Bool
)va_arg(ap
, FT_Int
);
219 gdi_cleartype_stem_width_mode
= arg
? TA_STEM_WIDTH_MODE_STRONG
220 : TA_STEM_WIDTH_MODE_QUANTIZED
;
222 else if (COMPARE("gray-stem-width-mode"))
223 gray_stem_width_mode
= va_arg(ap
, FT_Int
);
224 else if (COMPARE("gray-strong-stem-width"))
226 FT_Bool arg
= (FT_Bool
)va_arg(ap
, FT_Int
);
229 gray_stem_width_mode
= arg
? TA_STEM_WIDTH_MODE_STRONG
230 : TA_STEM_WIDTH_MODE_QUANTIZED
;
232 else if (COMPARE("hinting-limit"))
233 hinting_limit
= (FT_Long
)va_arg(ap
, FT_UInt
);
234 else if (COMPARE("hinting-range-max"))
235 hinting_range_max
= (FT_Long
)va_arg(ap
, FT_UInt
);
236 else if (COMPARE("hinting-range-min"))
237 hinting_range_min
= (FT_Long
)va_arg(ap
, FT_UInt
);
238 else if (COMPARE("hint-composites"))
239 hint_composites
= (FT_Bool
)va_arg(ap
, FT_Int
);
240 else if (COMPARE("ignore-restrictions"))
241 ignore_restrictions
= (FT_Bool
)va_arg(ap
, FT_Int
);
242 else if (COMPARE("in-buffer"))
245 in_buf
= va_arg(ap
, const char*);
247 else if (COMPARE("in-buffer-len"))
250 in_len
= va_arg(ap
, size_t);
252 else if (COMPARE("in-file"))
254 in_file
= va_arg(ap
, FILE*);
258 else if (COMPARE("increase-x-height"))
259 increase_x_height
= (FT_Long
)va_arg(ap
, FT_UInt
);
260 else if (COMPARE("info-callback"))
261 info
= va_arg(ap
, TA_Info_Func
);
262 else if (COMPARE("info-callback-data"))
263 info_data
= va_arg(ap
, void*);
264 else if (COMPARE("info-post-callback"))
265 info_post
= va_arg(ap
, TA_Info_Post_Func
);
266 else if (COMPARE("out-buffer"))
269 out_bufp
= va_arg(ap
, char**);
271 else if (COMPARE("out-buffer-len"))
274 out_lenp
= va_arg(ap
, size_t*);
276 else if (COMPARE("out-file"))
278 out_file
= va_arg(ap
, FILE*);
282 else if (COMPARE("pre-hinting"))
283 adjust_subglyphs
= (FT_Bool
)va_arg(ap
, FT_Int
);
284 else if (COMPARE("progress-callback"))
285 progress
= va_arg(ap
, TA_Progress_Func
);
286 else if (COMPARE("progress-callback-data"))
287 progress_data
= va_arg(ap
, void*);
288 else if (COMPARE("reference-buffer"))
290 reference_file
= NULL
;
291 reference_buf
= va_arg(ap
, const char*);
293 else if (COMPARE("reference-buffer-len"))
295 reference_file
= NULL
;
296 reference_len
= va_arg(ap
, size_t);
298 else if (COMPARE("reference-file"))
300 reference_file
= va_arg(ap
, FILE*);
301 reference_buf
= NULL
;
304 else if (COMPARE("reference-index"))
305 reference_index
= (FT_Long
)va_arg(ap
, FT_UInt
);
306 else if (COMPARE("reference-name"))
307 reference_name
= va_arg(ap
, const char*);
308 else if (COMPARE("symbol"))
309 symbol
= (FT_Bool
)va_arg(ap
, FT_Int
);
310 else if (COMPARE("TTFA-info"))
311 TTFA_info
= (FT_Bool
)va_arg(ap
, FT_Int
);
312 else if (COMPARE("windows-compatibility"))
313 windows_compatibility
= (FT_Bool
)va_arg(ap
, FT_Int
);
314 else if (COMPARE("x-height-snapping-exceptions"))
315 x_height_snapping_exceptions_string
= va_arg(ap
, const char*);
318 error
= TA_Err_Unknown_Argument
;
333 || (in_buf
&& in_len
)))
335 error
= FT_Err_Invalid_Argument
;
340 || (out_bufp
&& out_lenp
)))
342 error
= FT_Err_Invalid_Argument
;
346 font
= (FONT
*)calloc(1, sizeof (FONT
));
349 error
= FT_Err_Out_Of_Memory
;
356 if (gray_stem_width_mode
< -1 || gray_stem_width_mode
> 1)
358 error
= FT_Err_Invalid_Argument
;
361 if (gdi_cleartype_stem_width_mode
< -1 || gdi_cleartype_stem_width_mode
> 1)
363 error
= FT_Err_Invalid_Argument
;
366 if (dw_cleartype_stem_width_mode
< -1 || dw_cleartype_stem_width_mode
> 1)
368 error
= FT_Err_Invalid_Argument
;
372 if (hinting_range_min
>= 0 && hinting_range_min
< 2)
374 error
= FT_Err_Invalid_Argument
;
377 if (hinting_range_min
< 0)
378 hinting_range_min
= TA_HINTING_RANGE_MIN
;
380 if (hinting_range_max
>= 0 && hinting_range_max
< hinting_range_min
)
382 error
= FT_Err_Invalid_Argument
;
385 if (hinting_range_max
< 0)
386 hinting_range_max
= TA_HINTING_RANGE_MAX
;
388 /* value 0 is valid */
389 if (hinting_limit
> 0 && hinting_limit
< hinting_range_max
)
391 error
= FT_Err_Invalid_Argument
;
394 if (hinting_limit
< 0)
395 hinting_limit
= TA_HINTING_LIMIT
;
397 if (increase_x_height
> 0
398 && increase_x_height
< TA_PROP_INCREASE_X_HEIGHT_MIN
)
400 error
= FT_Err_Invalid_Argument
;
403 if (increase_x_height
< 0)
404 increase_x_height
= TA_INCREASE_X_HEIGHT
;
406 if (fallback_script_string
)
408 for (i
= 0; i
< TA_STYLE_MAX
; i
++)
410 TA_StyleClass style_class
= ta_style_classes
[i
];
413 if (style_class
->coverage
== TA_COVERAGE_DEFAULT
414 && !strcmp(script_names
[style_class
->script
],
415 fallback_script_string
))
418 if (i
== TA_STYLE_MAX
)
420 error
= FT_Err_Invalid_Argument
;
424 fallback_style
= (TA_Style
)i
;
427 if (default_script_string
)
429 for (i
= 0; i
< TA_SCRIPT_MAX
; i
++)
431 if (!strcmp(script_names
[i
], default_script_string
))
434 if (i
== TA_SCRIPT_MAX
)
436 error
= FT_Err_Invalid_Argument
;
440 default_script
= (TA_Script
)i
;
443 if (x_height_snapping_exceptions_string
)
445 const char* s
= number_set_parse(x_height_snapping_exceptions_string
,
446 &x_height_snapping_exceptions
,
447 TA_PROP_INCREASE_X_HEIGHT_MIN
,
451 /* we map numberset.h's error codes to values starting with 0x100 */
452 error
= 0x100 - (FT_Error
)(uintptr_t)x_height_snapping_exceptions
;
454 errline
= (char*)x_height_snapping_exceptions_string
;
461 font
->reference_index
= reference_index
;
462 font
->reference_name
= reference_name
;
464 font
->hinting_range_min
= (FT_UInt
)hinting_range_min
;
465 font
->hinting_range_max
= (FT_UInt
)hinting_range_max
;
466 font
->hinting_limit
= (FT_UInt
)hinting_limit
;
467 font
->increase_x_height
= (FT_UInt
)increase_x_height
;
468 font
->x_height_snapping_exceptions
= x_height_snapping_exceptions
;
469 font
->fallback_stem_width
= (FT_UInt
)fallback_stem_width
;
471 font
->gray_stem_width_mode
= gray_stem_width_mode
;
472 font
->gdi_cleartype_stem_width_mode
= gdi_cleartype_stem_width_mode
;
473 font
->dw_cleartype_stem_width_mode
= dw_cleartype_stem_width_mode
;
475 font
->windows_compatibility
= windows_compatibility
;
476 font
->ignore_restrictions
= ignore_restrictions
;
477 font
->adjust_subglyphs
= adjust_subglyphs
;
478 font
->hint_composites
= hint_composites
;
479 font
->fallback_style
= fallback_style
;
480 font
->fallback_scaling
= fallback_scaling
;
481 font
->default_script
= default_script
;
482 font
->symbol
= symbol
;
485 font
->allocate
= (allocate
&& out_bufp
) ? allocate
: malloc
;
486 font
->deallocate
= (deallocate
&& out_bufp
) ? deallocate
: free
;
488 font
->progress
= progress
;
489 font
->progress_data
= progress_data
;
491 font
->info_post
= info_post
;
492 font
->info_data
= info_data
;
495 font
->dehint
= dehint
;
496 font
->TTFA_info
= TTFA_info
;
499 font
->gasp_idx
= MISSING
;
501 /* start with processing the data */
505 error
= TA_font_file_read(in_file
, &font
->in_buf
, &font
->in_len
);
511 /* a valid TTF can never be that small */
514 error
= TA_Err_Invalid_Font_Type
;
517 font
->in_buf
= (FT_Byte
*)in_buf
;
518 font
->in_len
= in_len
;
523 error
= TA_control_file_read(font
, control_file
);
527 else if (control_buf
)
529 font
->control_buf
= (char*)control_buf
;
530 font
->control_len
= control_len
;
535 error
= TA_font_file_read(reference_file
,
536 &font
->reference_buf
,
537 &font
->reference_len
);
541 else if (reference_buf
)
543 /* a valid TTF can never be that small */
544 if (reference_len
< 100)
546 error
= TA_Err_Invalid_Font_Type
+ 0x300;
549 font
->reference_buf
= (FT_Byte
*)reference_buf
;
550 font
->reference_len
= reference_len
;
553 error
= TA_font_init(font
);
560 _ta_debug_global
= 1;
563 /* we do some loops over all subfonts -- */
564 /* to process options early, just start with loading all of them */
565 for (i
= 0; i
< font
->num_sfnts
; i
++)
567 SFNT
* sfnt
= &font
->sfnts
[i
];
571 error
= FT_New_Memory_Face(font
->lib
,
573 (FT_Long
)font
->in_len
,
577 /* assure that the font hasn't been already processed by ttfautohint; */
578 /* another, more thorough check is done in TA_glyph_parse_simple */
579 idx
= FT_Get_Name_Index(sfnt
->face
, (FT_String
*)TTFAUTOHINT_GLYPH
);
582 error
= TA_Err_Already_Processed
;
590 /* process control instructions */
591 error
= TA_control_parse_buffer(font
,
593 &errlinenum
, &errline
, &errpos
);
597 free_error_string
= 1;
601 /* now we are able to dump all parameters */
607 s
= TA_font_dump_parameters(font
, 1);
610 error
= FT_Err_Out_Of_Memory
;
614 fprintf(stderr
, "%s", s
);
618 error
= TA_control_build_tree(font
);
622 /* loop again over subfonts and continue processing */
623 for (i
= 0; i
< font
->num_sfnts
; i
++)
625 SFNT
* sfnt
= &font
->sfnts
[i
];
628 error
= TA_sfnt_split_into_SFNT_tables(sfnt
, font
);
632 /* check permission */
633 if (sfnt
->OS2_idx
!= MISSING
)
635 SFNT_Table
* OS2_table
= &font
->tables
[sfnt
->OS2_idx
];
638 /* check lower byte of the `fsType' field */
639 if (OS2_table
->buf
[OS2_FSTYPE_OFFSET
+ 1] == 0x02
640 && !font
->ignore_restrictions
)
642 error
= TA_Err_Missing_Legal_Permission
;
649 error
= TA_sfnt_split_glyf_table(sfnt
, font
);
655 if (font
->adjust_subglyphs
)
656 error
= TA_sfnt_create_glyf_data(sfnt
, font
);
658 error
= TA_sfnt_split_glyf_table(sfnt
, font
);
662 /* we need the total number of points */
663 /* for point delta instructions of composite glyphs; */
664 /* we need composite point number sums */
665 /* for adjustments due to the `.ttfautohint' glyph */
666 if (sfnt
->max_components
)
668 error
= TA_sfnt_compute_composite_pointsums(sfnt
, font
);
673 /* this call creates a `globals' object... */
674 error
= TA_sfnt_handle_coverage(sfnt
, font
);
678 /* ... so that we now can initialize its properties */
679 TA_sfnt_set_properties(sfnt
, font
);
685 for (i
= 0; i
< font
->num_sfnts
; i
++)
687 SFNT
* sfnt
= &font
->sfnts
[i
];
690 TA_sfnt_adjust_coverage(sfnt
, font
);
695 /* this code is here for completeness -- */
696 /* right now, `glyf' tables get hinted only once, */
697 /* and referring subfonts simply reuse it, */
698 /* but this might change in the future */
702 for (i
= 0; i
< font
->num_sfnts
; i
++)
704 SFNT
* sfnt
= &font
->sfnts
[i
];
707 TA_sfnt_copy_master_coverage(sfnt
, font
);
714 for (i
= 0; i
< font
->num_sfnts
; i
++)
716 SFNT
* sfnt
= &font
->sfnts
[i
];
719 TA_control_apply_coverage(sfnt
, font
);
723 /* loop again over subfonts */
724 for (i
= 0; i
< font
->num_sfnts
; i
++)
726 SFNT
* sfnt
= &font
->sfnts
[i
];
729 error
= ta_loader_init(font
);
733 error
= TA_sfnt_build_gasp_table(sfnt
, font
);
738 error
= TA_sfnt_build_cvt_table(sfnt
, font
);
741 error
= TA_sfnt_build_fpgm_table(sfnt
, font
);
744 error
= TA_sfnt_build_prep_table(sfnt
, font
);
748 error
= TA_sfnt_build_glyf_table(sfnt
, font
);
751 error
= TA_sfnt_build_loca_table(sfnt
, font
);
755 ta_loader_done(font
);
758 for (i
= 0; i
< font
->num_sfnts
; i
++)
760 SFNT
* sfnt
= &font
->sfnts
[i
];
763 error
= TA_sfnt_update_maxp_table(sfnt
, font
);
769 /* we add one glyph for composites */
770 if (sfnt
->max_components
771 && !font
->adjust_subglyphs
772 && font
->hint_composites
)
774 error
= TA_sfnt_update_hmtx_table(sfnt
, font
);
777 error
= TA_sfnt_update_post_table(sfnt
, font
);
780 error
= TA_sfnt_update_GPOS_table(sfnt
, font
);
788 /* add info about ttfautohint to the version string */
789 error
= TA_sfnt_update_name_table(sfnt
, font
);
795 if (font
->num_sfnts
== 1)
796 error
= TA_font_build_TTF(font
);
798 error
= TA_font_build_TTC(font
);
804 error
= TA_font_file_write(font
, out_file
);
810 *out_bufp
= (char*)font
->out_buf
;
811 *out_lenp
= font
->out_len
;
817 TA_control_free(font
->control
);
818 TA_control_free_tree(font
);
819 TA_font_unload(font
, in_buf
, out_bufp
, control_buf
, reference_buf
);
826 /* use standard FreeType error strings for reference file errors */
827 if (error
>= 0x300 && error
< 0x400)
831 error_string
= (char*)TA_get_error_message(e
);
833 /* this must be a static value */
835 *error_stringp
= (const unsigned char*)TA_get_error_message(e
);
848 if (free_error_string
)
854 /* end of ttfautohint.c */