Synchronize with FreeType.
[ttfautohint.git] / lib / ttfautohint.c
blobec8e30ce219cb000413b3be812080f170d9e8410
1 /* ttfautohint.c */
3 /*
4 * Copyright (C) 2011-2016 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 <stdlib.h>
20 #include <string.h>
21 #include <ctype.h>
23 #include "ta.h"
26 #define COMPARE(str) \
27 (len == (sizeof (str) - 1) \
28 && !strncmp(start, str, sizeof (str) - 1))
31 static void
32 TA_sfnt_set_properties(SFNT* sfnt,
33 FONT* font)
35 TA_FaceGlobals globals = (TA_FaceGlobals)sfnt->face->autohint.data;
38 globals->increase_x_height = font->increase_x_height;
42 TA_Error
43 TTF_autohint(const char* options,
44 ...)
46 va_list ap;
48 FONT* font;
49 FT_Long i;
51 TA_Error error;
52 char* error_string = NULL;
53 unsigned int errlinenum = 0;
54 char* errline = NULL;
55 char* errpos = NULL;
56 FT_Bool free_errline = 0;
57 FT_Bool free_error_string = 0;
59 FILE* in_file = NULL;
60 FILE* out_file = NULL;
61 FILE* control_file = NULL;
63 const char* in_buf = NULL;
64 size_t in_len = 0;
65 char** out_bufp = NULL;
66 size_t* out_lenp = NULL;
67 const char* control_buf = NULL;
68 size_t control_len = 0;
70 const unsigned char** error_stringp = NULL;
72 FT_Long hinting_range_min = -1;
73 FT_Long hinting_range_max = -1;
74 FT_Long hinting_limit = -1;
75 FT_Long increase_x_height = -1;
77 const char* x_height_snapping_exceptions_string = NULL;
78 number_range* x_height_snapping_exceptions = NULL;
80 FT_Long fallback_stem_width = 0;
82 FT_Bool gray_strong_stem_width = 0;
83 FT_Bool gdi_cleartype_strong_stem_width = 1;
84 FT_Bool dw_cleartype_strong_stem_width = 0;
86 TA_Progress_Func progress = NULL;
87 void* progress_data = NULL;
88 TA_Error_Func err = NULL;
89 void* err_data = NULL;
90 TA_Info_Func info = NULL;
91 TA_Info_Post_Func info_post = NULL;
92 void* info_data = NULL;
94 FT_Bool windows_compatibility = 0;
95 FT_Bool ignore_restrictions = 0;
96 FT_Bool adjust_subglyphs = 0;
97 FT_Bool hint_composites = 0;
98 FT_Bool symbol = 0;
99 FT_Bool fallback_scaling = 0;
101 const char* fallback_script_string = NULL;
102 const char* default_script_string = NULL;
104 TA_Style fallback_style = TA_STYLE_NONE_DFLT;
105 TA_Script default_script = TA_SCRIPT_LATN;
107 FT_Bool dehint = 0;
108 FT_Bool debug = 0;
109 FT_Bool TTFA_info = 0;
111 const char* op;
113 if (!options || !*options)
115 error = FT_Err_Invalid_Argument;
116 goto Err1;
119 /* XXX */
120 va_start(ap, options);
122 op = options;
124 for(;;)
126 const char* start;
127 size_t len;
130 start = op;
132 /* search comma */
133 while (*op && *op != ',')
134 op++;
136 /* remove leading whitespace */
137 while (isspace(*start))
138 start++;
140 /* check for empty option */
141 if (start == op)
142 goto End;
144 len = (size_t)(op - start);
146 /* the `COMPARE' macro uses `len' and `start' */
148 /* handle options -- don't forget to update parameter dump below! */
149 if (COMPARE("adjust-subglyphs"))
150 adjust_subglyphs = (FT_Bool)va_arg(ap, FT_Int);
151 else if (COMPARE("debug"))
152 debug = (FT_Bool)va_arg(ap, FT_Int);
153 else if (COMPARE("default-script"))
154 default_script_string = va_arg(ap, const char*);
155 else if (COMPARE("dehint"))
156 dehint = (FT_Bool)va_arg(ap, FT_Int);
157 else if (COMPARE("control-buffer"))
159 control_file = NULL;
160 control_buf = va_arg(ap, const char*);
162 else if (COMPARE("control-buffer-len"))
164 control_file = NULL;
165 control_len = va_arg(ap, size_t);
167 else if (COMPARE("control-file"))
169 control_file = va_arg(ap, FILE*);
170 control_buf = NULL;
171 control_len = 0;
173 else if (COMPARE("dw-cleartype-strong-stem-width"))
174 dw_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
175 else if (COMPARE("error-callback"))
176 err = va_arg(ap, TA_Error_Func);
177 else if (COMPARE("error-callback-data"))
178 err_data = va_arg(ap, void*);
179 else if (COMPARE("error-string"))
180 error_stringp = va_arg(ap, const unsigned char**);
181 else if (COMPARE("fallback-scaling"))
182 fallback_scaling = (FT_Bool)va_arg(ap, FT_Int);
183 else if (COMPARE("fallback-script"))
184 fallback_script_string = va_arg(ap, const char*);
185 else if (COMPARE("fallback-stem-width"))
186 fallback_stem_width = (FT_Long)va_arg(ap, FT_UInt);
187 else if (COMPARE("gdi-cleartype-strong-stem-width"))
188 gdi_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
189 else if (COMPARE("gray-strong-stem-width"))
190 gray_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
191 else if (COMPARE("hinting-limit"))
192 hinting_limit = (FT_Long)va_arg(ap, FT_UInt);
193 else if (COMPARE("hinting-range-max"))
194 hinting_range_max = (FT_Long)va_arg(ap, FT_UInt);
195 else if (COMPARE("hinting-range-min"))
196 hinting_range_min = (FT_Long)va_arg(ap, FT_UInt);
197 else if (COMPARE("hint-composites"))
198 hint_composites = (FT_Bool)va_arg(ap, FT_Int);
199 else if (COMPARE("ignore-restrictions"))
200 ignore_restrictions = (FT_Bool)va_arg(ap, FT_Int);
201 else if (COMPARE("in-buffer"))
203 in_file = NULL;
204 in_buf = va_arg(ap, const char*);
206 else if (COMPARE("in-buffer-len"))
208 in_file = NULL;
209 in_len = va_arg(ap, size_t);
211 else if (COMPARE("in-file"))
213 in_file = va_arg(ap, FILE*);
214 in_buf = NULL;
215 in_len = 0;
217 else if (COMPARE("increase-x-height"))
218 increase_x_height = (FT_Long)va_arg(ap, FT_UInt);
219 else if (COMPARE("info-callback"))
220 info = va_arg(ap, TA_Info_Func);
221 else if (COMPARE("info-callback-data"))
222 info_data = va_arg(ap, void*);
223 else if (COMPARE("info-post-callback"))
224 info_post = va_arg(ap, TA_Info_Post_Func);
225 else if (COMPARE("out-buffer"))
227 out_file = NULL;
228 out_bufp = va_arg(ap, char**);
230 else if (COMPARE("out-buffer-len"))
232 out_file = NULL;
233 out_lenp = va_arg(ap, size_t*);
235 else if (COMPARE("out-file"))
237 out_file = va_arg(ap, FILE*);
238 out_bufp = NULL;
239 out_lenp = NULL;
241 else if (COMPARE("pre-hinting"))
242 adjust_subglyphs = (FT_Bool)va_arg(ap, FT_Int);
243 else if (COMPARE("progress-callback"))
244 progress = va_arg(ap, TA_Progress_Func);
245 else if (COMPARE("progress-callback-data"))
246 progress_data = va_arg(ap, void*);
247 else if (COMPARE("symbol"))
248 symbol = (FT_Bool)va_arg(ap, FT_Int);
249 else if (COMPARE("TTFA-info"))
250 TTFA_info = (FT_Bool)va_arg(ap, FT_Int);
251 else if (COMPARE("windows-compatibility"))
252 windows_compatibility = (FT_Bool)va_arg(ap, FT_Int);
253 else if (COMPARE("x-height-snapping-exceptions"))
254 x_height_snapping_exceptions_string = va_arg(ap, const char*);
255 else
257 error = TA_Err_Unknown_Argument;
258 goto Err1;
261 End:
262 if (!*op)
263 break;
264 op++;
267 va_end(ap);
269 /* check options */
271 if (!(in_file
272 || (in_buf && in_len)))
274 error = FT_Err_Invalid_Argument;
275 goto Err1;
278 if (!(out_file
279 || (out_bufp && out_lenp)))
281 error = FT_Err_Invalid_Argument;
282 goto Err1;
285 font = (FONT*)calloc(1, sizeof (FONT));
286 if (!font)
288 error = FT_Err_Out_Of_Memory;
289 goto Err1;
292 if (dehint)
293 goto No_check;
295 if (hinting_range_min >= 0 && hinting_range_min < 2)
297 error = FT_Err_Invalid_Argument;
298 goto Err1;
300 if (hinting_range_min < 0)
301 hinting_range_min = TA_HINTING_RANGE_MIN;
303 if (hinting_range_max >= 0 && hinting_range_max < hinting_range_min)
305 error = FT_Err_Invalid_Argument;
306 goto Err1;
308 if (hinting_range_max < 0)
309 hinting_range_max = TA_HINTING_RANGE_MAX;
311 /* value 0 is valid */
312 if (hinting_limit > 0 && hinting_limit < hinting_range_max)
314 error = FT_Err_Invalid_Argument;
315 goto Err1;
317 if (hinting_limit < 0)
318 hinting_limit = TA_HINTING_LIMIT;
320 if (increase_x_height > 0
321 && increase_x_height < TA_PROP_INCREASE_X_HEIGHT_MIN)
323 error = FT_Err_Invalid_Argument;
324 goto Err1;
326 if (increase_x_height < 0)
327 increase_x_height = TA_INCREASE_X_HEIGHT;
329 if (fallback_script_string)
331 for (i = 0; i < TA_STYLE_MAX; i++)
333 TA_StyleClass style_class = ta_style_classes[i];
336 if (style_class->coverage == TA_COVERAGE_DEFAULT
337 && !strcmp(script_names[style_class->script],
338 fallback_script_string))
339 break;
341 if (i == TA_STYLE_MAX)
343 error = FT_Err_Invalid_Argument;
344 goto Err1;
347 fallback_style = (TA_Style)i;
350 if (default_script_string)
352 for (i = 0; i < TA_SCRIPT_MAX; i++)
354 if (!strcmp(script_names[i], default_script_string))
355 break;
357 if (i == TA_SCRIPT_MAX)
359 error = FT_Err_Invalid_Argument;
360 goto Err1;
363 default_script = (TA_Script)i;
366 if (x_height_snapping_exceptions_string)
368 const char* s = number_set_parse(x_height_snapping_exceptions_string,
369 &x_height_snapping_exceptions,
370 TA_PROP_INCREASE_X_HEIGHT_MIN,
371 0x7FFF);
372 if (*s)
374 /* we map numberset.h's error codes to values starting with 0x100 */
375 error = 0x100 - (FT_Error)(uintptr_t)x_height_snapping_exceptions;
376 errlinenum = 0;
377 errline = (char*)x_height_snapping_exceptions_string;
378 errpos = (char*)s;
380 goto Err1;
384 font->hinting_range_min = (FT_UInt)hinting_range_min;
385 font->hinting_range_max = (FT_UInt)hinting_range_max;
386 font->hinting_limit = (FT_UInt)hinting_limit;
387 font->increase_x_height = (FT_UInt)increase_x_height;
388 font->x_height_snapping_exceptions = x_height_snapping_exceptions;
389 font->fallback_stem_width = (FT_UInt)fallback_stem_width;
391 font->gray_strong_stem_width = gray_strong_stem_width;
392 font->gdi_cleartype_strong_stem_width = gdi_cleartype_strong_stem_width;
393 font->dw_cleartype_strong_stem_width = dw_cleartype_strong_stem_width;
395 font->windows_compatibility = windows_compatibility;
396 font->ignore_restrictions = ignore_restrictions;
397 font->adjust_subglyphs = adjust_subglyphs;
398 font->hint_composites = hint_composites;
399 font->fallback_style = fallback_style;
400 font->fallback_scaling = fallback_scaling;
401 font->default_script = default_script;
402 font->symbol = symbol;
404 No_check:
405 font->progress = progress;
406 font->progress_data = progress_data;
407 font->info = info;
408 font->info_post = info_post;
409 font->info_data = info_data;
411 font->debug = debug;
412 font->dehint = dehint;
413 font->TTFA_info = TTFA_info;
415 font->gasp_idx = MISSING;
417 /* start with processing the data */
419 if (in_file)
421 error = TA_font_file_read(font, in_file);
422 if (error)
423 goto Err;
425 else
427 /* a valid TTF can never be that small */
428 if (in_len < 100)
430 error = TA_Err_Invalid_Font_Type;
431 goto Err1;
433 font->in_buf = (FT_Byte*)in_buf;
434 font->in_len = in_len;
437 if (control_file)
439 error = TA_control_file_read(font, control_file);
440 if (error)
441 goto Err;
443 else if (control_buf)
445 font->control_buf = (char*)control_buf;
446 font->control_len = control_len;
449 error = TA_font_init(font);
450 if (error)
451 goto Err;
453 if (font->debug)
455 _ta_debug = 1;
456 _ta_debug_global = 1;
459 /* we do some loops over all subfonts -- */
460 /* to process options early, just start with loading all of them */
461 for (i = 0; i < font->num_sfnts; i++)
463 SFNT* sfnt = &font->sfnts[i];
464 FT_UInt idx;
467 error = FT_New_Memory_Face(font->lib,
468 font->in_buf,
469 (FT_Long)font->in_len,
471 &sfnt->face);
473 /* assure that the font hasn't been already processed by ttfautohint; */
474 /* another, more thorough check is done in TA_glyph_parse_simple */
475 idx = FT_Get_Name_Index(sfnt->face, (FT_String*)TTFAUTOHINT_GLYPH);
476 if (idx)
478 error = TA_Err_Already_Processed;
479 goto Err;
482 if (error)
483 goto Err;
486 /* process control instructions */
487 error = TA_control_parse_buffer(font,
488 &error_string,
489 &errlinenum, &errline, &errpos);
490 if (error)
492 free_errline = 1;
493 free_error_string = 1;
494 goto Err;
497 /* now we are able to dump all parameters */
498 if (debug)
500 char* s;
503 s = TA_font_dump_parameters(font, 1);
504 if (!s)
506 error = FT_Err_Out_Of_Memory;
507 goto Err;
510 fprintf(stderr, "%s", s);
511 free(s);
514 error = TA_control_build_tree(font);
515 if (error)
516 goto Err;
518 /* loop again over subfonts and continue processing */
519 for (i = 0; i < font->num_sfnts; i++)
521 SFNT* sfnt = &font->sfnts[i];
524 error = TA_sfnt_split_into_SFNT_tables(sfnt, font);
525 if (error)
526 goto Err;
528 /* check permission */
529 if (sfnt->OS2_idx != MISSING)
531 SFNT_Table* OS2_table = &font->tables[sfnt->OS2_idx];
534 /* check lower byte of the `fsType' field */
535 if (OS2_table->buf[OS2_FSTYPE_OFFSET + 1] == 0x02
536 && !font->ignore_restrictions)
538 error = TA_Err_Missing_Legal_Permission;
539 goto Err;
543 if (font->dehint)
545 error = TA_sfnt_split_glyf_table(sfnt, font);
546 if (error)
547 goto Err;
549 else
551 if (font->adjust_subglyphs)
552 error = TA_sfnt_create_glyf_data(sfnt, font);
553 else
554 error = TA_sfnt_split_glyf_table(sfnt, font);
555 if (error)
556 goto Err;
558 /* this call creates a `globals' object... */
559 error = TA_sfnt_handle_coverage(sfnt, font);
560 if (error)
561 goto Err;
563 /* ... so that we now can initialize its properties */
564 TA_sfnt_set_properties(sfnt, font);
568 if (!font->dehint)
570 for (i = 0; i < font->num_sfnts; i++)
572 SFNT* sfnt = &font->sfnts[i];
575 TA_sfnt_adjust_coverage(sfnt, font);
579 #if 0
580 /* this code is here for completeness -- */
581 /* right now, `glyf' tables get hinted only once, */
582 /* and referring subfonts simply reuse it, */
583 /* but this might change in the future */
585 if (!font->dehint)
587 for (i = 0; i < font->num_sfnts; i++)
589 SFNT* sfnt = &font->sfnts[i];
592 TA_sfnt_copy_master_coverage(sfnt, font);
595 #endif
597 if (!font->dehint)
599 for (i = 0; i < font->num_sfnts; i++)
601 SFNT* sfnt = &font->sfnts[i];
604 TA_control_apply_coverage(sfnt, font);
608 /* loop again over subfonts */
609 for (i = 0; i < font->num_sfnts; i++)
611 SFNT* sfnt = &font->sfnts[i];
614 error = ta_loader_init(font);
615 if (error)
616 goto Err;
618 error = TA_sfnt_build_gasp_table(sfnt, font);
619 if (error)
620 goto Err;
621 if (!font->dehint)
623 error = TA_sfnt_build_cvt_table(sfnt, font);
624 if (error)
625 goto Err;
626 error = TA_sfnt_build_fpgm_table(sfnt, font);
627 if (error)
628 goto Err;
629 error = TA_sfnt_build_prep_table(sfnt, font);
630 if (error)
631 goto Err;
633 error = TA_sfnt_build_glyf_table(sfnt, font);
634 if (error)
635 goto Err;
636 error = TA_sfnt_build_loca_table(sfnt, font);
637 if (error)
638 goto Err;
640 if (font->loader)
641 ta_loader_done(font);
644 for (i = 0; i < font->num_sfnts; i++)
646 SFNT* sfnt = &font->sfnts[i];
649 error = TA_sfnt_update_maxp_table(sfnt, font);
650 if (error)
651 goto Err;
653 if (!font->dehint)
655 /* we add one glyph for composites */
656 if (sfnt->max_components
657 && !font->adjust_subglyphs
658 && font->hint_composites)
660 error = TA_sfnt_update_hmtx_table(sfnt, font);
661 if (error)
662 goto Err;
663 error = TA_sfnt_update_post_table(sfnt, font);
664 if (error)
665 goto Err;
666 error = TA_sfnt_update_GPOS_table(sfnt, font);
667 if (error)
668 goto Err;
672 if (font->info)
674 /* add info about ttfautohint to the version string */
675 error = TA_sfnt_update_name_table(sfnt, font);
676 if (error)
677 goto Err;
681 if (font->num_sfnts == 1)
682 error = TA_font_build_TTF(font);
683 else
684 error = TA_font_build_TTC(font);
685 if (error)
686 goto Err;
688 if (out_file)
690 error = TA_font_file_write(font, out_file);
691 if (error)
692 goto Err;
694 else
696 *out_bufp = (char*)font->out_buf;
697 *out_lenp = font->out_len;
700 error = TA_Err_Ok;
702 Err:
703 TA_control_free(font->control);
704 TA_control_free_tree(font);
705 TA_font_unload(font, in_buf, out_bufp, control_buf);
707 Err1:
708 if (!error_string)
709 error_string = (char*)TA_get_error_message(error);
711 /* this must be a static value */
712 if (error_stringp)
713 *error_stringp = (const unsigned char*)TA_get_error_message(error);
715 if (err)
716 err(error,
717 error_string,
718 errlinenum,
719 errline,
720 errpos,
721 err_data);
723 if (free_errline)
724 free(errline);
725 if (free_error_string)
726 free(error_string);
728 return error;
731 /* end of ttfautohint.c */