Use `Control_Type' to handle different segment directions.
[ttfautohint.git] / lib / ttfautohint.c
blob7772d886e28dc2f403edb51ecffb0fd38bc29768
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))
31 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 void* info_data = NULL;
93 FT_Bool windows_compatibility = 0;
94 FT_Bool ignore_restrictions = 0;
95 FT_Bool adjust_subglyphs = 0;
96 FT_Bool hint_composites = 0;
97 FT_Bool symbol = 0;
99 const char* fallback_script_string = NULL;
100 const char* default_script_string = NULL;
101 TA_Style fallback_style = TA_STYLE_NONE_DFLT;
102 TA_Script default_script = TA_SCRIPT_LATN;
104 FT_Bool dehint = 0;
105 FT_Bool debug = 0;
106 FT_Bool TTFA_info = 0;
108 const char* op;
110 if (!options || !*options)
112 error = FT_Err_Invalid_Argument;
113 goto Err1;
116 /* XXX */
117 va_start(ap, options);
119 op = options;
121 for(;;)
123 const char* start;
124 size_t len;
127 start = op;
129 /* search comma */
130 while (*op && *op != ',')
131 op++;
133 /* remove leading whitespace */
134 while (isspace(*start))
135 start++;
137 /* check for empty option */
138 if (start == op)
139 goto End;
141 len = op - start;
143 /* the `COMPARE' macro uses `len' and `start' */
145 /* handle options -- don't forget to update parameter dump below! */
146 if (COMPARE("adjust-subglyphs"))
147 adjust_subglyphs = (FT_Bool)va_arg(ap, FT_Int);
148 else if (COMPARE("debug"))
149 debug = (FT_Bool)va_arg(ap, FT_Int);
150 else if (COMPARE("default-script"))
151 default_script_string = va_arg(ap, const char*);
152 else if (COMPARE("dehint"))
153 dehint = (FT_Bool)va_arg(ap, FT_Int);
154 else if (COMPARE("control-buffer"))
156 control_file = NULL;
157 control_buf = va_arg(ap, const char*);
159 else if (COMPARE("control-buffer-len"))
161 control_file = NULL;
162 control_len = va_arg(ap, size_t);
164 else if (COMPARE("control-file"))
166 control_file = va_arg(ap, FILE*);
167 control_buf = NULL;
168 control_len = 0;
170 else if (COMPARE("dw-cleartype-strong-stem-width"))
171 dw_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
172 else if (COMPARE("error-callback"))
173 err = va_arg(ap, TA_Error_Func);
174 else if (COMPARE("error-callback-data"))
175 err_data = va_arg(ap, void*);
176 else if (COMPARE("error-string"))
177 error_stringp = va_arg(ap, const unsigned char**);
178 else if (COMPARE("fallback-script"))
179 fallback_script_string = va_arg(ap, const char*);
180 else if (COMPARE("fallback-stem-width"))
181 fallback_stem_width = (FT_Long)va_arg(ap, FT_UInt);
182 else if (COMPARE("gdi-cleartype-strong-stem-width"))
183 gdi_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
184 else if (COMPARE("gray-strong-stem-width"))
185 gray_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
186 else if (COMPARE("hinting-limit"))
187 hinting_limit = (FT_Long)va_arg(ap, FT_UInt);
188 else if (COMPARE("hinting-range-max"))
189 hinting_range_max = (FT_Long)va_arg(ap, FT_UInt);
190 else if (COMPARE("hinting-range-min"))
191 hinting_range_min = (FT_Long)va_arg(ap, FT_UInt);
192 else if (COMPARE("hint-composites"))
193 hint_composites = (FT_Bool)va_arg(ap, FT_Int);
194 else if (COMPARE("ignore-restrictions"))
195 ignore_restrictions = (FT_Bool)va_arg(ap, FT_Int);
196 else if (COMPARE("in-buffer"))
198 in_file = NULL;
199 in_buf = va_arg(ap, const char*);
201 else if (COMPARE("in-buffer-len"))
203 in_file = NULL;
204 in_len = va_arg(ap, size_t);
206 else if (COMPARE("in-file"))
208 in_file = va_arg(ap, FILE*);
209 in_buf = NULL;
210 in_len = 0;
212 else if (COMPARE("increase-x-height"))
213 increase_x_height = (FT_Long)va_arg(ap, FT_UInt);
214 else if (COMPARE("info-callback"))
215 info = va_arg(ap, TA_Info_Func);
216 else if (COMPARE("info-callback-data"))
217 info_data = va_arg(ap, void*);
218 else if (COMPARE("out-buffer"))
220 out_file = NULL;
221 out_bufp = va_arg(ap, char**);
223 else if (COMPARE("out-buffer-len"))
225 out_file = NULL;
226 out_lenp = va_arg(ap, size_t*);
228 else if (COMPARE("out-file"))
230 out_file = va_arg(ap, FILE*);
231 out_bufp = NULL;
232 out_lenp = NULL;
234 else if (COMPARE("pre-hinting"))
235 adjust_subglyphs = (FT_Bool)va_arg(ap, FT_Int);
236 else if (COMPARE("progress-callback"))
237 progress = va_arg(ap, TA_Progress_Func);
238 else if (COMPARE("progress-callback-data"))
239 progress_data = va_arg(ap, void*);
240 else if (COMPARE("symbol"))
241 symbol = (FT_Bool)va_arg(ap, FT_Int);
242 else if (COMPARE("TTFA-info"))
243 TTFA_info = (FT_Bool)va_arg(ap, FT_Int);
244 else if (COMPARE("windows-compatibility"))
245 windows_compatibility = (FT_Bool)va_arg(ap, FT_Int);
246 else if (COMPARE("x-height-snapping-exceptions"))
247 x_height_snapping_exceptions_string = va_arg(ap, const char*);
248 else
250 error = TA_Err_Unknown_Argument;
251 goto Err1;
254 End:
255 if (!*op)
256 break;
257 op++;
260 va_end(ap);
262 /* check options */
264 if (!(in_file
265 || (in_buf && in_len)))
267 error = FT_Err_Invalid_Argument;
268 goto Err1;
271 if (!(out_file
272 || (out_bufp && out_lenp)))
274 error = FT_Err_Invalid_Argument;
275 goto Err1;
278 font = (FONT*)calloc(1, sizeof (FONT));
279 if (!font)
281 error = FT_Err_Out_Of_Memory;
282 goto Err1;
285 if (dehint)
286 goto No_check;
288 if (hinting_range_min >= 0 && hinting_range_min < 2)
290 error = FT_Err_Invalid_Argument;
291 goto Err1;
293 if (hinting_range_min < 0)
294 hinting_range_min = TA_HINTING_RANGE_MIN;
296 if (hinting_range_max >= 0 && hinting_range_max < hinting_range_min)
298 error = FT_Err_Invalid_Argument;
299 goto Err1;
301 if (hinting_range_max < 0)
302 hinting_range_max = TA_HINTING_RANGE_MAX;
304 /* value 0 is valid */
305 if (hinting_limit > 0 && hinting_limit < hinting_range_max)
307 error = FT_Err_Invalid_Argument;
308 goto Err1;
310 if (hinting_limit < 0)
311 hinting_limit = TA_HINTING_LIMIT;
313 if (increase_x_height > 0
314 && increase_x_height < TA_PROP_INCREASE_X_HEIGHT_MIN)
316 error = FT_Err_Invalid_Argument;
317 goto Err1;
319 if (increase_x_height < 0)
320 increase_x_height = TA_INCREASE_X_HEIGHT;
322 if (fallback_script_string)
324 int i;
327 for (i = 0; i < TA_STYLE_MAX; i++)
329 TA_StyleClass style_class = ta_style_classes[i];
332 if (style_class->coverage == TA_COVERAGE_DEFAULT
333 && !strcmp(script_names[style_class->script],
334 fallback_script_string))
335 break;
337 if (i == TA_STYLE_MAX)
339 error = FT_Err_Invalid_Argument;
340 goto Err1;
343 fallback_style = (TA_Style)i;
346 if (default_script_string)
348 int i;
351 for (i = 0; i < TA_SCRIPT_MAX; i++)
353 if (!strcmp(script_names[i], default_script_string))
354 break;
356 if (i == TA_SCRIPT_MAX)
358 error = FT_Err_Invalid_Argument;
359 goto Err1;
362 default_script = (TA_Script)i;
365 if (x_height_snapping_exceptions_string)
367 const char* s = number_set_parse(x_height_snapping_exceptions_string,
368 &x_height_snapping_exceptions,
369 TA_PROP_INCREASE_X_HEIGHT_MIN,
370 0x7FFF);
371 if (*s)
373 /* we map numberset.h's error codes to values starting with 0x100 */
374 error = 0x100 - (FT_Error)x_height_snapping_exceptions;
375 errlinenum = 0;
376 errline = (char*)x_height_snapping_exceptions_string;
377 errpos = (char*)s;
379 goto Err1;
383 font->hinting_range_min = (FT_UInt)hinting_range_min;
384 font->hinting_range_max = (FT_UInt)hinting_range_max;
385 font->hinting_limit = (FT_UInt)hinting_limit;
386 font->increase_x_height = increase_x_height;
387 font->x_height_snapping_exceptions = x_height_snapping_exceptions;
388 font->fallback_stem_width = (FT_UInt)fallback_stem_width;
390 font->gray_strong_stem_width = gray_strong_stem_width;
391 font->gdi_cleartype_strong_stem_width = gdi_cleartype_strong_stem_width;
392 font->dw_cleartype_strong_stem_width = dw_cleartype_strong_stem_width;
394 font->windows_compatibility = windows_compatibility;
395 font->ignore_restrictions = ignore_restrictions;
396 font->adjust_subglyphs = adjust_subglyphs;
397 font->hint_composites = hint_composites;
398 font->fallback_style = fallback_style;
399 font->default_script = default_script;
400 font->symbol = symbol;
402 No_check:
403 font->progress = progress;
404 font->progress_data = progress_data;
405 font->info = info;
406 font->info_data = info_data;
408 font->debug = debug;
409 font->dehint = dehint;
410 font->TTFA_info = TTFA_info;
412 font->gasp_idx = MISSING;
414 /* start with processing the data */
416 if (in_file)
418 error = TA_font_file_read(font, in_file);
419 if (error)
420 goto Err;
422 else
424 /* a valid TTF can never be that small */
425 if (in_len < 100)
427 error = TA_Err_Invalid_Font_Type;
428 goto Err1;
430 font->in_buf = (FT_Byte*)in_buf;
431 font->in_len = in_len;
434 if (control_file)
436 error = TA_control_file_read(font, control_file);
437 if (error)
438 goto Err;
440 else if (control_buf)
442 font->control_buf = (char*)control_buf;
443 font->control_len = control_len;
446 error = TA_font_init(font);
447 if (error)
448 goto Err;
450 if (font->debug)
452 _ta_debug = 1;
453 _ta_debug_global = 1;
456 /* we do some loops over all subfonts -- */
457 /* to process options early, just start with loading all of them */
458 for (i = 0; i < font->num_sfnts; i++)
460 SFNT* sfnt = &font->sfnts[i];
461 FT_UInt idx;
464 error = FT_New_Memory_Face(font->lib, font->in_buf, font->in_len,
465 i, &sfnt->face);
467 /* assure that the font hasn't been already processed by ttfautohint; */
468 /* another, more thorough check is done in TA_glyph_parse_simple */
469 idx = FT_Get_Name_Index(sfnt->face, (FT_String*)TTFAUTOHINT_GLYPH);
470 if (idx)
472 error = TA_Err_Already_Processed;
473 goto Err;
476 if (error)
477 goto Err;
480 /* process control instructions */
481 error = TA_control_parse_buffer(font,
482 &error_string,
483 &errlinenum, &errline, &errpos);
484 if (error)
486 free_errline = 1;
487 free_error_string = 1;
488 goto Err;
491 /* now we are able to dump all parameters */
492 if (debug)
494 char* s;
497 s = TA_font_dump_parameters(font, 1);
498 if (!s)
500 error = FT_Err_Out_Of_Memory;
501 goto Err;
504 fprintf(stderr, "%s", s);
505 free(s);
508 error = TA_control_build_tree(font);
509 if (error)
510 goto Err;
512 /* loop again over subfonts and continue processing */
513 for (i = 0; i < font->num_sfnts; i++)
515 SFNT* sfnt = &font->sfnts[i];
518 error = TA_sfnt_split_into_SFNT_tables(sfnt, font);
519 if (error)
520 goto Err;
522 /* check permission */
523 if (sfnt->OS2_idx != MISSING)
525 SFNT_Table* OS2_table = &font->tables[sfnt->OS2_idx];
528 /* check lower byte of the `fsType' field */
529 if (OS2_table->buf[OS2_FSTYPE_OFFSET + 1] == 0x02
530 && !font->ignore_restrictions)
532 error = TA_Err_Missing_Legal_Permission;
533 goto Err;
537 if (font->dehint)
539 error = TA_sfnt_split_glyf_table(sfnt, font);
540 if (error)
541 goto Err;
543 else
545 if (font->adjust_subglyphs)
546 error = TA_sfnt_create_glyf_data(sfnt, font);
547 else
548 error = TA_sfnt_split_glyf_table(sfnt, font);
549 if (error)
550 goto Err;
552 /* this call creates a `globals' object... */
553 error = TA_sfnt_handle_coverage(sfnt, font);
554 if (error)
555 goto Err;
557 /* ... so that we now can initialize its properties */
558 TA_sfnt_set_properties(sfnt, font);
562 if (!font->dehint)
564 for (i = 0; i < font->num_sfnts; i++)
566 SFNT* sfnt = &font->sfnts[i];
569 TA_sfnt_adjust_coverage(sfnt, font);
573 #if 0
574 /* this code is here for completeness -- */
575 /* right now, `glyf' tables get hinted only once, */
576 /* and referring subfonts simply reuse it, */
577 /* but this might change in the future */
579 if (!font->dehint)
581 for (i = 0; i < font->num_sfnts; i++)
583 SFNT* sfnt = &font->sfnts[i];
586 TA_sfnt_copy_master_coverage(sfnt, font);
589 #endif
591 /* loop again over subfonts */
592 for (i = 0; i < font->num_sfnts; i++)
594 SFNT* sfnt = &font->sfnts[i];
597 error = ta_loader_init(font);
598 if (error)
599 goto Err;
601 error = TA_sfnt_build_gasp_table(sfnt, font);
602 if (error)
603 goto Err;
604 if (!font->dehint)
606 error = TA_sfnt_build_cvt_table(sfnt, font);
607 if (error)
608 goto Err;
609 error = TA_sfnt_build_fpgm_table(sfnt, font);
610 if (error)
611 goto Err;
612 error = TA_sfnt_build_prep_table(sfnt, font);
613 if (error)
614 goto Err;
616 error = TA_sfnt_build_glyf_table(sfnt, font);
617 if (error)
618 goto Err;
619 error = TA_sfnt_build_loca_table(sfnt, font);
620 if (error)
621 goto Err;
623 if (font->loader)
624 ta_loader_done(font);
627 for (i = 0; i < font->num_sfnts; i++)
629 SFNT* sfnt = &font->sfnts[i];
632 error = TA_sfnt_update_maxp_table(sfnt, font);
633 if (error)
634 goto Err;
636 if (!font->dehint)
638 /* we add one glyph for composites */
639 if (sfnt->max_components
640 && !font->adjust_subglyphs
641 && font->hint_composites)
643 error = TA_sfnt_update_hmtx_table(sfnt, font);
644 if (error)
645 goto Err;
646 error = TA_sfnt_update_post_table(sfnt, font);
647 if (error)
648 goto Err;
649 error = TA_sfnt_update_GPOS_table(sfnt, font);
650 if (error)
651 goto Err;
655 if (font->info)
657 /* add info about ttfautohint to the version string */
658 error = TA_sfnt_update_name_table(sfnt, font);
659 if (error)
660 goto Err;
664 if (font->num_sfnts == 1)
665 error = TA_font_build_TTF(font);
666 else
667 error = TA_font_build_TTC(font);
668 if (error)
669 goto Err;
671 if (out_file)
673 error = TA_font_file_write(font, out_file);
674 if (error)
675 goto Err;
677 else
679 *out_bufp = (char*)font->out_buf;
680 *out_lenp = font->out_len;
683 error = TA_Err_Ok;
685 Err:
686 TA_control_free(font->control);
687 TA_control_free_tree(font);
688 TA_font_unload(font, in_buf, out_bufp, control_buf);
690 Err1:
691 if (!error_string)
692 error_string = (char*)TA_get_error_message(error);
694 /* this must be a static value */
695 if (error_stringp)
696 *error_stringp = (const unsigned char*)TA_get_error_message(error);
698 if (err)
699 err(error,
700 error_string,
701 errlinenum,
702 errline,
703 errpos,
704 err_data);
706 if (free_errline)
707 free(errline);
708 if (free_error_string)
709 free(error_string);
711 return error;
714 /* end of ttfautohint.c */