Update documentation.
[ttfautohint.git] / lib / ttfautohint.c
blobc44c7709ce7284664ab1b8ffa3c7950e9ba00f71
1 /* ttfautohint.c */
3 /*
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. */
18 #include <stdio.h>
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <ctype.h>
24 #include "ta.h"
27 #define COMPARE(str) \
28 (len == (sizeof (str) - 1) \
29 && !strncmp(start, str, sizeof (str) - 1))
32 static void
33 TA_sfnt_set_properties(SFNT* sfnt,
34 FONT* font)
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,
45 ...)
47 va_list ap;
49 FONT* font;
50 FT_Long i;
52 TA_Error error;
53 char* error_string = NULL;
54 unsigned int errlinenum = 0;
55 char* errline = NULL;
56 char* errpos = NULL;
57 FT_Bool free_errline = 0;
58 FT_Bool free_error_string = 0;
60 FILE* in_file = NULL;
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;
69 size_t in_len = 0;
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;
108 FT_Bool symbol = 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;
117 FT_Bool dehint = 0;
118 FT_Bool debug = 0;
119 FT_Bool TTFA_info = 0;
120 unsigned long long epoch = ULLONG_MAX;
122 const char* op;
124 if (!options || !*options)
126 error = FT_Err_Invalid_Argument;
127 goto Err1;
130 /* XXX */
131 va_start(ap, options);
133 op = options;
135 for (;;)
137 const char* start;
138 size_t len;
141 start = op;
143 /* search comma */
144 while (*op && *op != ',')
145 op++;
147 /* remove leading whitespace */
148 while (isspace(*start))
149 start++;
151 /* check for empty option */
152 if (start == op)
153 goto End;
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"))
166 control_file = NULL;
167 control_buf = va_arg(ap, const char*);
169 else if (COMPARE("control-buffer-len"))
171 control_file = NULL;
172 control_len = va_arg(ap, size_t);
174 else if (COMPARE("control-file"))
176 control_file = va_arg(ap, FILE*);
177 control_buf = NULL;
178 control_len = 0;
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"))
244 in_file = NULL;
245 in_buf = va_arg(ap, const char*);
247 else if (COMPARE("in-buffer-len"))
249 in_file = NULL;
250 in_len = va_arg(ap, size_t);
252 else if (COMPARE("in-file"))
254 in_file = va_arg(ap, FILE*);
255 in_buf = NULL;
256 in_len = 0;
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"))
268 out_file = NULL;
269 out_bufp = va_arg(ap, char**);
271 else if (COMPARE("out-buffer-len"))
273 out_file = NULL;
274 out_lenp = va_arg(ap, size_t*);
276 else if (COMPARE("out-file"))
278 out_file = va_arg(ap, FILE*);
279 out_bufp = NULL;
280 out_lenp = NULL;
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;
302 reference_len = 0;
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*);
316 else
318 error = TA_Err_Unknown_Argument;
319 goto Err1;
322 End:
323 if (!*op)
324 break;
325 op++;
328 va_end(ap);
330 /* check options */
332 if (!(in_file
333 || (in_buf && in_len)))
335 error = FT_Err_Invalid_Argument;
336 goto Err1;
339 if (!(out_file
340 || (out_bufp && out_lenp)))
342 error = FT_Err_Invalid_Argument;
343 goto Err1;
346 font = (FONT*)calloc(1, sizeof (FONT));
347 if (!font)
349 error = FT_Err_Out_Of_Memory;
350 goto Err1;
353 if (dehint)
354 goto No_check;
356 if (gray_stem_width_mode < -1 || gray_stem_width_mode > 1)
358 error = FT_Err_Invalid_Argument;
359 goto Err1;
361 if (gdi_cleartype_stem_width_mode < -1 || gdi_cleartype_stem_width_mode > 1)
363 error = FT_Err_Invalid_Argument;
364 goto Err1;
366 if (dw_cleartype_stem_width_mode < -1 || dw_cleartype_stem_width_mode > 1)
368 error = FT_Err_Invalid_Argument;
369 goto Err1;
372 if (hinting_range_min >= 0 && hinting_range_min < 2)
374 error = FT_Err_Invalid_Argument;
375 goto Err1;
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;
383 goto Err1;
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;
392 goto Err1;
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;
401 goto Err1;
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))
416 break;
418 if (i == TA_STYLE_MAX)
420 error = FT_Err_Invalid_Argument;
421 goto Err1;
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))
432 break;
434 if (i == TA_SCRIPT_MAX)
436 error = FT_Err_Invalid_Argument;
437 goto Err1;
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,
448 0x7FFF);
449 if (*s)
451 /* we map numberset.h's error codes to values starting with 0x100 */
452 error = 0x100 - (FT_Error)(uintptr_t)x_height_snapping_exceptions;
453 errlinenum = 0;
454 errline = (char*)x_height_snapping_exceptions_string;
455 errpos = (char*)s;
457 goto Err1;
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;
484 No_check:
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;
490 font->info = info;
491 font->info_post = info_post;
492 font->info_data = info_data;
494 font->debug = debug;
495 font->dehint = dehint;
496 font->TTFA_info = TTFA_info;
497 font->epoch = epoch;
499 font->gasp_idx = MISSING;
501 /* start with processing the data */
503 if (in_file)
505 error = TA_font_file_read(in_file, &font->in_buf, &font->in_len);
506 if (error)
507 goto Err;
509 else
511 /* a valid TTF can never be that small */
512 if (in_len < 100)
514 error = TA_Err_Invalid_Font_Type;
515 goto Err1;
517 font->in_buf = (FT_Byte*)in_buf;
518 font->in_len = in_len;
521 if (control_file)
523 error = TA_control_file_read(font, control_file);
524 if (error)
525 goto Err;
527 else if (control_buf)
529 font->control_buf = (char*)control_buf;
530 font->control_len = control_len;
533 if (reference_file)
535 error = TA_font_file_read(reference_file,
536 &font->reference_buf,
537 &font->reference_len);
538 if (error)
539 goto Err;
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;
547 goto Err1;
549 font->reference_buf = (FT_Byte*)reference_buf;
550 font->reference_len = reference_len;
553 error = TA_font_init(font);
554 if (error)
555 goto Err;
557 if (font->debug)
559 _ta_debug = 1;
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];
568 FT_UInt idx;
571 error = FT_New_Memory_Face(font->lib,
572 font->in_buf,
573 (FT_Long)font->in_len,
575 &sfnt->face);
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);
580 if (idx && !dehint)
582 error = TA_Err_Already_Processed;
583 goto Err;
586 if (error)
587 goto Err;
590 /* process control instructions */
591 error = TA_control_parse_buffer(font,
592 &error_string,
593 &errlinenum, &errline, &errpos);
594 if (error)
596 free_errline = 1;
597 free_error_string = 1;
598 goto Err;
601 /* now we are able to dump all parameters */
602 if (debug)
604 char* s;
607 s = TA_font_dump_parameters(font, 1);
608 if (!s)
610 error = FT_Err_Out_Of_Memory;
611 goto Err;
614 fprintf(stderr, "%s", s);
615 free(s);
618 error = TA_control_build_tree(font);
619 if (error)
620 goto Err;
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);
629 if (error)
630 goto Err;
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;
643 goto Err;
647 if (font->dehint)
649 error = TA_sfnt_split_glyf_table(sfnt, font);
650 if (error)
651 goto Err;
653 else
655 if (font->adjust_subglyphs)
656 error = TA_sfnt_create_glyf_data(sfnt, font);
657 else
658 error = TA_sfnt_split_glyf_table(sfnt, font);
659 if (error)
660 goto Err;
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);
669 if (error)
670 goto Err;
673 /* this call creates a `globals' object... */
674 error = TA_sfnt_handle_coverage(sfnt, font);
675 if (error)
676 goto Err;
678 /* ... so that we now can initialize its properties */
679 TA_sfnt_set_properties(sfnt, font);
683 if (!font->dehint)
685 for (i = 0; i < font->num_sfnts; i++)
687 SFNT* sfnt = &font->sfnts[i];
690 TA_sfnt_adjust_coverage(sfnt, font);
694 #if 0
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 */
700 if (!font->dehint)
702 for (i = 0; i < font->num_sfnts; i++)
704 SFNT* sfnt = &font->sfnts[i];
707 TA_sfnt_copy_master_coverage(sfnt, font);
710 #endif
712 if (!font->dehint)
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);
730 if (error)
731 goto Err;
733 error = TA_sfnt_build_gasp_table(sfnt, font);
734 if (error)
735 goto Err;
736 if (!font->dehint)
738 error = TA_sfnt_build_cvt_table(sfnt, font);
739 if (error)
740 goto Err;
741 error = TA_sfnt_build_fpgm_table(sfnt, font);
742 if (error)
743 goto Err;
744 error = TA_sfnt_build_prep_table(sfnt, font);
745 if (error)
746 goto Err;
748 error = TA_sfnt_build_glyf_table(sfnt, font);
749 if (error)
750 goto Err;
751 error = TA_sfnt_build_loca_table(sfnt, font);
752 if (error)
753 goto Err;
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);
764 if (error)
765 goto Err;
767 if (!font->dehint)
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);
775 if (error)
776 goto Err;
777 error = TA_sfnt_update_post_table(sfnt, font);
778 if (error)
779 goto Err;
780 error = TA_sfnt_update_GPOS_table(sfnt, font);
781 if (error)
782 goto Err;
786 if (font->info)
788 /* add info about ttfautohint to the version string */
789 error = TA_sfnt_update_name_table(sfnt, font);
790 if (error)
791 goto Err;
795 if (font->num_sfnts == 1)
796 error = TA_font_build_TTF(font);
797 else
798 error = TA_font_build_TTC(font);
799 if (error)
800 goto Err;
802 if (out_file)
804 error = TA_font_file_write(font, out_file);
805 if (error)
806 goto Err;
808 else
810 *out_bufp = (char*)font->out_buf;
811 *out_lenp = font->out_len;
814 error = TA_Err_Ok;
816 Err:
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);
821 Err1:
823 FT_Error e = error;
826 /* use standard FreeType error strings for reference file errors */
827 if (error >= 0x300 && error < 0x400)
828 e -= 0x300;
830 if (!error_string)
831 error_string = (char*)TA_get_error_message(e);
833 /* this must be a static value */
834 if (error_stringp)
835 *error_stringp = (const unsigned char*)TA_get_error_message(e);
838 if (err)
839 err(error,
840 error_string,
841 errlinenum,
842 errline,
843 errpos,
844 err_data);
846 if (free_errline)
847 free(errline);
848 if (free_error_string)
849 free(error_string);
851 return error;
854 /* end of ttfautohint.c */