Add file missing in previous commit.
[ttfautohint.git] / lib / ttfautohint.c
blob5a8822a3f56bfc2f55079759c78f3c0f0df811f4
1 /* ttfautohint.c */
3 /*
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. */
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 LT_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_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;
105 FT_Bool symbol = 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;
114 FT_Bool dehint = 0;
115 FT_Bool debug = 0;
116 FT_Bool TTFA_info = 0;
117 unsigned long long epoch = ULLONG_MAX;
119 const char* op;
121 if (!options || !*options)
123 error = FT_Err_Invalid_Argument;
124 goto Err1;
127 /* XXX */
128 va_start(ap, options);
130 op = options;
132 for (;;)
134 const char* start;
135 size_t len;
138 start = op;
140 /* search comma */
141 while (*op && *op != ',')
142 op++;
144 /* remove leading whitespace */
145 while (isspace(*start))
146 start++;
148 /* check for empty option */
149 if (start == op)
150 goto End;
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"))
161 control_file = NULL;
162 control_buf = va_arg(ap, const char*);
164 else if (COMPARE("control-buffer-len"))
166 control_file = NULL;
167 control_len = va_arg(ap, size_t);
169 else if (COMPARE("control-file"))
171 control_file = va_arg(ap, FILE*);
172 control_buf = NULL;
173 control_len = 0;
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"))
213 in_file = NULL;
214 in_buf = va_arg(ap, const char*);
216 else if (COMPARE("in-buffer-len"))
218 in_file = NULL;
219 in_len = va_arg(ap, size_t);
221 else if (COMPARE("in-file"))
223 in_file = va_arg(ap, FILE*);
224 in_buf = NULL;
225 in_len = 0;
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"))
237 out_file = NULL;
238 out_bufp = va_arg(ap, char**);
240 else if (COMPARE("out-buffer-len"))
242 out_file = NULL;
243 out_lenp = va_arg(ap, size_t*);
245 else if (COMPARE("out-file"))
247 out_file = va_arg(ap, FILE*);
248 out_bufp = NULL;
249 out_lenp = NULL;
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;
271 reference_len = 0;
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*);
285 else
287 error = TA_Err_Unknown_Argument;
288 goto Err1;
291 End:
292 if (!*op)
293 break;
294 op++;
297 va_end(ap);
299 /* check options */
301 if (!(in_file
302 || (in_buf && in_len)))
304 error = FT_Err_Invalid_Argument;
305 goto Err1;
308 if (!(out_file
309 || (out_bufp && out_lenp)))
311 error = FT_Err_Invalid_Argument;
312 goto Err1;
315 font = (FONT*)calloc(1, sizeof (FONT));
316 if (!font)
318 error = FT_Err_Out_Of_Memory;
319 goto Err1;
322 if (dehint)
323 goto No_check;
325 if (hinting_range_min >= 0 && hinting_range_min < 2)
327 error = FT_Err_Invalid_Argument;
328 goto Err1;
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;
336 goto Err1;
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;
345 goto Err1;
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;
354 goto Err1;
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))
369 break;
371 if (i == TA_STYLE_MAX)
373 error = FT_Err_Invalid_Argument;
374 goto Err1;
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))
385 break;
387 if (i == TA_SCRIPT_MAX)
389 error = FT_Err_Invalid_Argument;
390 goto Err1;
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,
401 0x7FFF);
402 if (*s)
404 /* we map numberset.h's error codes to values starting with 0x100 */
405 error = 0x100 - (FT_Error)(uintptr_t)x_height_snapping_exceptions;
406 errlinenum = 0;
407 errline = (char*)x_height_snapping_exceptions_string;
408 errpos = (char*)s;
410 goto Err1;
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;
437 No_check:
438 font->progress = progress;
439 font->progress_data = progress_data;
440 font->info = info;
441 font->info_post = info_post;
442 font->info_data = info_data;
444 font->debug = debug;
445 font->dehint = dehint;
446 font->TTFA_info = TTFA_info;
447 font->epoch = epoch;
449 font->gasp_idx = MISSING;
451 /* start with processing the data */
453 if (in_file)
455 error = TA_font_file_read(in_file, &font->in_buf, &font->in_len);
456 if (error)
457 goto Err;
459 else
461 /* a valid TTF can never be that small */
462 if (in_len < 100)
464 error = TA_Err_Invalid_Font_Type;
465 goto Err1;
467 font->in_buf = (FT_Byte*)in_buf;
468 font->in_len = in_len;
471 if (control_file)
473 error = TA_control_file_read(font, control_file);
474 if (error)
475 goto Err;
477 else if (control_buf)
479 font->control_buf = (char*)control_buf;
480 font->control_len = control_len;
483 if (reference_file)
485 error = TA_font_file_read(reference_file,
486 &font->reference_buf,
487 &font->reference_len);
488 if (error)
489 goto Err;
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;
497 goto Err1;
499 font->reference_buf = (FT_Byte*)reference_buf;
500 font->reference_len = reference_len;
503 error = TA_font_init(font);
504 if (error)
505 goto Err;
507 if (font->debug)
509 _ta_debug = 1;
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];
518 FT_UInt idx;
521 error = FT_New_Memory_Face(font->lib,
522 font->in_buf,
523 (FT_Long)font->in_len,
525 &sfnt->face);
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);
530 if (idx && !dehint)
532 error = TA_Err_Already_Processed;
533 goto Err;
536 if (error)
537 goto Err;
540 /* process control instructions */
541 error = TA_control_parse_buffer(font,
542 &error_string,
543 &errlinenum, &errline, &errpos);
544 if (error)
546 free_errline = 1;
547 free_error_string = 1;
548 goto Err;
551 /* now we are able to dump all parameters */
552 if (debug)
554 char* s;
557 s = TA_font_dump_parameters(font, 1);
558 if (!s)
560 error = FT_Err_Out_Of_Memory;
561 goto Err;
564 fprintf(stderr, "%s", s);
565 free(s);
568 error = TA_control_build_tree(font);
569 if (error)
570 goto Err;
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);
579 if (error)
580 goto Err;
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;
593 goto Err;
597 if (font->dehint)
599 error = TA_sfnt_split_glyf_table(sfnt, font);
600 if (error)
601 goto Err;
603 else
605 if (font->adjust_subglyphs)
606 error = TA_sfnt_create_glyf_data(sfnt, font);
607 else
608 error = TA_sfnt_split_glyf_table(sfnt, font);
609 if (error)
610 goto Err;
612 /* this call creates a `globals' object... */
613 error = TA_sfnt_handle_coverage(sfnt, font);
614 if (error)
615 goto Err;
617 /* ... so that we now can initialize its properties */
618 TA_sfnt_set_properties(sfnt, font);
622 if (!font->dehint)
624 for (i = 0; i < font->num_sfnts; i++)
626 SFNT* sfnt = &font->sfnts[i];
629 TA_sfnt_adjust_coverage(sfnt, font);
633 #if 0
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 */
639 if (!font->dehint)
641 for (i = 0; i < font->num_sfnts; i++)
643 SFNT* sfnt = &font->sfnts[i];
646 TA_sfnt_copy_master_coverage(sfnt, font);
649 #endif
651 if (!font->dehint)
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);
669 if (error)
670 goto Err;
672 error = TA_sfnt_build_gasp_table(sfnt, font);
673 if (error)
674 goto Err;
675 if (!font->dehint)
677 error = TA_sfnt_build_cvt_table(sfnt, font);
678 if (error)
679 goto Err;
680 error = TA_sfnt_build_fpgm_table(sfnt, font);
681 if (error)
682 goto Err;
683 error = TA_sfnt_build_prep_table(sfnt, font);
684 if (error)
685 goto Err;
687 error = TA_sfnt_build_glyf_table(sfnt, font);
688 if (error)
689 goto Err;
690 error = TA_sfnt_build_loca_table(sfnt, font);
691 if (error)
692 goto Err;
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);
703 if (error)
704 goto Err;
706 if (!font->dehint)
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);
714 if (error)
715 goto Err;
716 error = TA_sfnt_update_post_table(sfnt, font);
717 if (error)
718 goto Err;
719 error = TA_sfnt_update_GPOS_table(sfnt, font);
720 if (error)
721 goto Err;
725 if (font->info)
727 /* add info about ttfautohint to the version string */
728 error = TA_sfnt_update_name_table(sfnt, font);
729 if (error)
730 goto Err;
734 if (font->num_sfnts == 1)
735 error = TA_font_build_TTF(font);
736 else
737 error = TA_font_build_TTC(font);
738 if (error)
739 goto Err;
741 if (out_file)
743 error = TA_font_file_write(font, out_file);
744 if (error)
745 goto Err;
747 else
749 *out_bufp = (char*)font->out_buf;
750 *out_lenp = font->out_len;
753 error = TA_Err_Ok;
755 Err:
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);
760 Err1:
762 FT_Error e = error;
765 /* use standard FreeType error strings for reference file errors */
766 if (error >= 0x300 && error < 0x400)
767 e -= 0x300;
769 if (!error_string)
770 error_string = (char*)TA_get_error_message(e);
772 /* this must be a static value */
773 if (error_stringp)
774 *error_stringp = (const unsigned char*)TA_get_error_message(e);
777 if (err)
778 err(error,
779 error_string,
780 errlinenum,
781 errline,
782 errpos,
783 err_data);
785 if (free_errline)
786 free(errline);
787 if (free_error_string)
788 free(error_string);
790 return error;
793 /* end of ttfautohint.c */