Synchronize with FreeType.
[ttfautohint.git] / lib / ttfautohint.c
blob11a2352f447e57fd9ea1e8fa238c929d4308d5d7
1 /* ttfautohint.c */
3 /*
4 * Copyright (C) 2011-2014 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))
29 #define DUMPVAL(str, arg) \
30 fprintf(stderr, "%33s = %ld\n", \
31 (str), \
32 (FT_Long)(arg))
33 #define DUMPSTR(str, arg) \
34 fprintf(stderr, "%33s = %s\n", \
35 (str), \
36 (arg))
39 void
40 TA_sfnt_set_properties(SFNT* sfnt,
41 FONT* font)
43 TA_FaceGlobals globals = (TA_FaceGlobals)sfnt->face->autohint.data;
46 globals->increase_x_height = font->increase_x_height;
50 TA_Error
51 TTF_autohint(const char* options,
52 ...)
54 va_list ap;
56 FONT* font;
57 FT_Error error;
58 FT_Long i;
60 FILE* in_file = NULL;
61 FILE* out_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;
68 const unsigned char** error_stringp = NULL;
70 FT_Long hinting_range_min = -1;
71 FT_Long hinting_range_max = -1;
72 FT_Long hinting_limit = -1;
73 FT_Long increase_x_height = -1;
75 const char* x_height_snapping_exceptions_string = NULL;
76 number_range* x_height_snapping_exceptions = NULL;
78 FT_Bool gray_strong_stem_width = 0;
79 FT_Bool gdi_cleartype_strong_stem_width = 1;
80 FT_Bool dw_cleartype_strong_stem_width = 0;
82 TA_Progress_Func progress;
83 void* progress_data;
84 TA_Info_Func info;
85 void* info_data;
87 FT_Bool windows_compatibility = 0;
88 FT_Bool ignore_restrictions = 0;
89 FT_Bool pre_hinting = 0;
90 FT_Bool hint_composites = 0;
91 FT_Bool symbol = 0;
93 const char* fallback_script_string = NULL;
94 const char* default_script_string = NULL;
95 TA_Style fallback_style = TA_STYLE_NONE_DFLT;
96 TA_Script default_script = TA_SCRIPT_LATN;
98 FT_Bool dehint = 0;
100 FT_Bool debug = 0;
102 const char* op;
104 #undef SCRIPT
105 #define SCRIPT(s, S, d, h, sc1, sc2, sc3) #s,
107 const char* script_names[] =
110 #include <ttfautohint-scripts.h>
115 if (!options || !*options)
117 error = FT_Err_Invalid_Argument;
118 goto Err1;
121 /* XXX */
122 va_start(ap, options);
124 op = options;
126 for(;;)
128 const char* start;
129 size_t len;
132 start = op;
134 /* search comma */
135 while (*op && *op != ',')
136 op++;
138 /* remove leading whitespace */
139 while (isspace(*start))
140 start++;
142 /* check for empty option */
143 if (start == op)
144 goto End;
146 len = op - start;
148 /* the `COMPARE' macro uses `len' and `start' */
150 /* handle options -- don't forget to update parameter dump below! */
151 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("dw-cleartype-strong-stem-width"))
158 dw_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
159 else if (COMPARE("error-string"))
160 error_stringp = va_arg(ap, const unsigned char**);
161 else if (COMPARE("fallback-script"))
162 fallback_script_string = va_arg(ap, const char*);
163 else if (COMPARE("gdi-cleartype-strong-stem-width"))
164 gdi_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
165 else if (COMPARE("gray-strong-stem-width"))
166 gray_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
167 else if (COMPARE("hinting-limit"))
168 hinting_limit = (FT_Long)va_arg(ap, FT_UInt);
169 else if (COMPARE("hinting-range-max"))
170 hinting_range_max = (FT_Long)va_arg(ap, FT_UInt);
171 else if (COMPARE("hinting-range-min"))
172 hinting_range_min = (FT_Long)va_arg(ap, FT_UInt);
173 else if (COMPARE("hint-composites"))
174 hint_composites = (FT_Bool)va_arg(ap, FT_Int);
175 else if (COMPARE("ignore-restrictions"))
176 ignore_restrictions = (FT_Bool)va_arg(ap, FT_Int);
177 else if (COMPARE("in-buffer"))
179 in_file = NULL;
180 in_buf = va_arg(ap, const char*);
182 else if (COMPARE("in-buffer-len"))
184 in_file = NULL;
185 in_len = va_arg(ap, size_t);
187 else if (COMPARE("in-file"))
189 in_file = va_arg(ap, FILE*);
190 in_buf = NULL;
191 in_len = 0;
193 else if (COMPARE("increase-x-height"))
194 increase_x_height = (FT_Long)va_arg(ap, FT_UInt);
195 else if (COMPARE("info-callback"))
196 info = va_arg(ap, TA_Info_Func);
197 else if (COMPARE("info-callback-data"))
198 info_data = va_arg(ap, void*);
199 else if (COMPARE("out-buffer"))
201 out_file = NULL;
202 out_bufp = va_arg(ap, char**);
204 else if (COMPARE("out-buffer-len"))
206 out_file = NULL;
207 out_lenp = va_arg(ap, size_t*);
209 else if (COMPARE("out-file"))
211 out_file = va_arg(ap, FILE*);
212 out_bufp = NULL;
213 out_lenp = NULL;
215 else if (COMPARE("pre-hinting"))
216 pre_hinting = (FT_Bool)va_arg(ap, FT_Int);
217 else if (COMPARE("progress-callback"))
218 progress = va_arg(ap, TA_Progress_Func);
219 else if (COMPARE("progress-callback-data"))
220 progress_data = va_arg(ap, void*);
221 else if (COMPARE("symbol"))
222 symbol = (FT_Bool)va_arg(ap, FT_Int);
223 else if (COMPARE("windows-compatibility"))
224 windows_compatibility = (FT_Bool)va_arg(ap, FT_Int);
225 else if (COMPARE("x-height-snapping-exceptions"))
226 x_height_snapping_exceptions_string = va_arg(ap, const char*);
227 else
229 error = TA_Err_Unknown_Argument;
230 goto Err1;
233 End:
234 if (!*op)
235 break;
236 op++;
239 va_end(ap);
241 /* check options */
243 if (!(in_file
244 || (in_buf && in_len)))
246 error = FT_Err_Invalid_Argument;
247 goto Err1;
250 if (!(out_file
251 || (out_bufp && out_lenp)))
253 error = FT_Err_Invalid_Argument;
254 goto Err1;
257 font = (FONT*)calloc(1, sizeof (FONT));
258 if (!font)
260 error = FT_Err_Out_Of_Memory;
261 goto Err1;
264 if (dehint)
265 goto No_check;
267 if (hinting_range_min >= 0 && hinting_range_min < 2)
269 error = FT_Err_Invalid_Argument;
270 goto Err1;
272 if (hinting_range_min < 0)
273 hinting_range_min = TA_HINTING_RANGE_MIN;
275 if (hinting_range_max >= 0 && hinting_range_max < hinting_range_min)
277 error = FT_Err_Invalid_Argument;
278 goto Err1;
280 if (hinting_range_max < 0)
281 hinting_range_max = TA_HINTING_RANGE_MAX;
283 /* value 0 is valid */
284 if (hinting_limit > 0 && hinting_limit < hinting_range_max)
286 error = FT_Err_Invalid_Argument;
287 goto Err1;
289 if (hinting_limit < 0)
290 hinting_limit = TA_HINTING_LIMIT;
292 if (increase_x_height > 0
293 && increase_x_height < TA_PROP_INCREASE_X_HEIGHT_MIN)
295 error = FT_Err_Invalid_Argument;
296 goto Err1;
298 if (increase_x_height < 0)
299 increase_x_height = TA_INCREASE_X_HEIGHT;
301 if (fallback_script_string)
303 int i;
306 for (i = 0; i < TA_STYLE_MAX; i++)
308 TA_StyleClass style_class = ta_style_classes[i];
311 if (style_class->coverage == TA_COVERAGE_DEFAULT
312 && !strcmp(script_names[style_class->script],
313 fallback_script_string))
314 break;
316 if (i == TA_STYLE_MAX)
318 error = FT_Err_Invalid_Argument;
319 goto Err1;
322 fallback_style = (TA_Style)i;
325 if (default_script_string)
327 int i;
330 for (i = 0; i < TA_SCRIPT_MAX; i++)
332 if (!strcmp(script_names[i], default_script_string))
333 break;
335 if (i == TA_SCRIPT_MAX)
337 error = FT_Err_Invalid_Argument;
338 goto Err1;
341 default_script = (TA_Script)i;
344 if (x_height_snapping_exceptions_string)
346 const char* s = number_set_parse(x_height_snapping_exceptions_string,
347 &x_height_snapping_exceptions,
348 TA_PROP_INCREASE_X_HEIGHT_MIN,
349 0x7FFF);
350 if (*s)
352 error = FT_Err_Invalid_Argument;
353 goto Err1;
357 font->hinting_range_min = (FT_UInt)hinting_range_min;
358 font->hinting_range_max = (FT_UInt)hinting_range_max;
359 font->hinting_limit = (FT_UInt)hinting_limit;
360 font->increase_x_height = increase_x_height;
361 font->x_height_snapping_exceptions = x_height_snapping_exceptions;
363 font->gray_strong_stem_width = gray_strong_stem_width;
364 font->gdi_cleartype_strong_stem_width = gdi_cleartype_strong_stem_width;
365 font->dw_cleartype_strong_stem_width = dw_cleartype_strong_stem_width;
367 font->windows_compatibility = windows_compatibility;
368 font->ignore_restrictions = ignore_restrictions;
369 font->pre_hinting = pre_hinting;
370 font->hint_composites = hint_composites;
371 font->fallback_style = fallback_style;
372 font->default_script = default_script;
373 font->symbol = symbol;
375 No_check:
376 font->progress = progress;
377 font->progress_data = progress_data;
378 font->info = info;
379 font->info_data = info_data;
381 font->debug = debug;
382 font->dehint = dehint;
384 font->gasp_idx = MISSING;
386 /* dump parameters */
387 if (debug)
389 fprintf(stderr, "TTF_autohint parameters\n"
390 "=======================\n"
391 "\n");
393 if (dehint)
394 DUMPVAL("dehint",
395 font->dehint);
396 else
398 char *s;
401 DUMPSTR("default-script",
402 script_names[font->default_script]);
403 DUMPVAL("dw-cleartype-strong-stem-width",
404 font->dw_cleartype_strong_stem_width);
405 DUMPSTR("fallback-script",
406 script_names[ta_style_classes[font->fallback_style]->script]);
407 DUMPVAL("gdi-cleartype-strong-stem-width",
408 font->gdi_cleartype_strong_stem_width);
409 DUMPVAL("gray-strong-stem-width",
410 font->gray_strong_stem_width);
411 DUMPVAL("hinting-limit",
412 font->hinting_limit);
413 DUMPVAL("hinting-range-max",
414 font->hinting_range_max);
415 DUMPVAL("hinting-range-min",
416 font->hinting_range_min);
417 DUMPVAL("hint-composites",
418 font->hint_composites);
419 DUMPVAL("ignore-restrictions",
420 font->ignore_restrictions);
421 DUMPVAL("increase-x-height",
422 font->increase_x_height);
423 DUMPVAL("pre-hinting",
424 font->pre_hinting);
425 DUMPVAL("symbol",
426 font->symbol);
427 DUMPVAL("windows-compatibility",
428 font->windows_compatibility);
430 s = number_set_show(font->x_height_snapping_exceptions,
431 TA_PROP_INCREASE_X_HEIGHT_MIN, 0x7FFF);
432 DUMPSTR("x-height-snapping-exceptions", s);
433 free(s);
436 fprintf(stderr, "\n");
439 /* now start with processing the data */
441 if (in_file)
443 error = TA_font_file_read(font, in_file);
444 if (error)
445 goto Err;
447 else
449 /* a valid TTF can never be that small */
450 if (in_len < 100)
452 error = TA_Err_Invalid_Font_Type;
453 goto Err1;
455 font->in_buf = (FT_Byte*)in_buf;
456 font->in_len = in_len;
459 error = TA_font_init(font);
460 if (error)
461 goto Err;
463 if (font->debug)
465 _ta_debug = 1;
466 _ta_debug_global = 1;
469 /* we do some loops over all subfonts */
470 for (i = 0; i < font->num_sfnts; i++)
472 SFNT* sfnt = &font->sfnts[i];
473 FT_UInt idx;
476 error = FT_New_Memory_Face(font->lib, font->in_buf, font->in_len,
477 i, &sfnt->face);
479 /* assure that the font hasn't been already processed by ttfautohint; */
480 /* another, more thorough check is done in TA_glyph_parse_simple */
481 idx = FT_Get_Name_Index(sfnt->face, (FT_String*)TTFAUTOHINT_GLYPH);
482 if (idx)
484 error = TA_Err_Already_Processed;
485 goto Err;
488 if (error)
489 goto Err;
491 error = TA_sfnt_split_into_SFNT_tables(sfnt, font);
492 if (error)
493 goto Err;
495 /* check permission */
496 if (sfnt->OS2_idx != MISSING)
498 SFNT_Table* OS2_table = &font->tables[sfnt->OS2_idx];
501 /* check lower byte of the `fsType' field */
502 if (OS2_table->buf[OS2_FSTYPE_OFFSET + 1] == 0x02
503 && !font->ignore_restrictions)
505 error = TA_Err_Missing_Legal_Permission;
506 goto Err;
510 if (font->dehint)
512 error = TA_sfnt_split_glyf_table(sfnt, font);
513 if (error)
514 goto Err;
516 else
518 if (font->pre_hinting)
519 error = TA_sfnt_create_glyf_data(sfnt, font);
520 else
521 error = TA_sfnt_split_glyf_table(sfnt, font);
522 if (error)
523 goto Err;
525 /* this call creates a `globals' object... */
526 error = TA_sfnt_handle_coverage(sfnt, font);
527 if (error)
528 goto Err;
530 /* ... so that we now can initialize its properties */
531 TA_sfnt_set_properties(sfnt, font);
535 if (!font->dehint)
537 for (i = 0; i < font->num_sfnts; i++)
539 SFNT* sfnt = &font->sfnts[i];
542 if (TA_sfnt_adjust_master_coverage(sfnt, font))
543 break;
547 #if 0
548 /* this code is here for completeness -- */
549 /* right now, `glyf' tables get hinted only once, */
550 /* and referring subfonts simply reuse it, */
551 /* but this might change in the future */
553 if (!font->dehint)
555 for (i = 0; i < font->num_sfnts; i++)
557 SFNT* sfnt = &font->sfnts[i];
560 TA_sfnt_copy_master_coverage(sfnt, font);
563 #endif
565 /* loop again over subfonts */
566 for (i = 0; i < font->num_sfnts; i++)
568 SFNT* sfnt = &font->sfnts[i];
571 error = ta_loader_init(font);
572 if (error)
573 goto Err;
575 error = TA_sfnt_build_gasp_table(sfnt, font);
576 if (error)
577 goto Err;
578 if (!font->dehint)
580 error = TA_sfnt_build_cvt_table(sfnt, font);
581 if (error)
582 goto Err;
583 error = TA_sfnt_build_fpgm_table(sfnt, font);
584 if (error)
585 goto Err;
586 error = TA_sfnt_build_prep_table(sfnt, font);
587 if (error)
588 goto Err;
590 error = TA_sfnt_build_glyf_table(sfnt, font);
591 if (error)
592 goto Err;
593 error = TA_sfnt_build_loca_table(sfnt, font);
594 if (error)
595 goto Err;
597 if (font->loader)
598 ta_loader_done(font);
601 for (i = 0; i < font->num_sfnts; i++)
603 SFNT* sfnt = &font->sfnts[i];
606 error = TA_sfnt_update_maxp_table(sfnt, font);
607 if (error)
608 goto Err;
610 if (!font->dehint)
612 /* we add one glyph for composites */
613 if (sfnt->max_components
614 && !font->pre_hinting
615 && font->hint_composites)
617 error = TA_sfnt_update_hmtx_table(sfnt, font);
618 if (error)
619 goto Err;
620 error = TA_sfnt_update_post_table(sfnt, font);
621 if (error)
622 goto Err;
623 error = TA_sfnt_update_GPOS_table(sfnt, font);
624 if (error)
625 goto Err;
629 if (font->info)
631 /* add info about ttfautohint to the version string */
632 error = TA_sfnt_update_name_table(sfnt, font);
633 if (error)
634 goto Err;
638 if (font->num_sfnts == 1)
639 error = TA_font_build_TTF(font);
640 else
641 error = TA_font_build_TTC(font);
642 if (error)
643 goto Err;
645 if (out_file)
647 error = TA_font_file_write(font, out_file);
648 if (error)
649 goto Err;
651 else
653 *out_bufp = (char*)font->out_buf;
654 *out_lenp = font->out_len;
657 error = TA_Err_Ok;
659 Err:
660 TA_font_unload(font, in_buf, out_bufp);
662 Err1:
663 if (error_stringp)
664 *error_stringp = (const unsigned char*)TA_get_error_message(error);
666 return error;
669 /* end of ttfautohint.c */