Add options `deltas-file', `deltas-buffer', and `deltas-buffer-len'.
[ttfautohint.git] / lib / ttfautohint.c
blob701b40fddd35790b318adc462f056c3d73d3c852
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 #define _POSIX_SOURCE /* to access `strtok_r' with glibc */
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <ctype.h>
25 #include "ta.h"
28 #define DUMP_COLUMN "33"
30 #define COMPARE(str) \
31 (len == (sizeof (str) - 1) \
32 && !strncmp(start, str, sizeof (str) - 1))
33 #define DUMPVAL(str, arg) \
34 fprintf(stderr, "%" DUMP_COLUMN "s = %ld\n", \
35 (str), \
36 (FT_Long)(arg))
37 #define DUMPSTR(str, arg) \
38 fprintf(stderr, "%" DUMP_COLUMN "s = %s\n", \
39 (str), \
40 (arg))
41 #define DUMPSTRX(arg) \
42 fprintf(stderr, "%" DUMP_COLUMN "s %s\n", \
43 "", \
44 (arg))
47 void
48 TA_sfnt_set_properties(SFNT* sfnt,
49 FONT* font)
51 TA_FaceGlobals globals = (TA_FaceGlobals)sfnt->face->autohint.data;
54 globals->increase_x_height = font->increase_x_height;
58 TA_Error
59 TTF_autohint(const char* options,
60 ...)
62 va_list ap;
64 FONT* font;
65 FT_Long i;
67 TA_Error error;
68 const char* error_string = NULL;
69 unsigned int errlinenum = 0;
70 char* errline = NULL;
71 char* errpos = NULL;
72 FT_Bool free_errline = 0;
74 FILE* in_file = NULL;
75 FILE* out_file = NULL;
76 FILE* deltas_file = NULL;
78 const char* in_buf = NULL;
79 size_t in_len = 0;
80 char** out_bufp = NULL;
81 size_t* out_lenp = NULL;
82 const char* deltas_buf = NULL;
83 size_t deltas_len = 0;
85 const unsigned char** error_stringp = NULL;
87 Deltas* deltas;
89 FT_Long hinting_range_min = -1;
90 FT_Long hinting_range_max = -1;
91 FT_Long hinting_limit = -1;
92 FT_Long increase_x_height = -1;
94 const char* x_height_snapping_exceptions_string = NULL;
95 number_range* x_height_snapping_exceptions = NULL;
97 FT_Long fallback_stem_width = 0;
99 FT_Bool gray_strong_stem_width = 0;
100 FT_Bool gdi_cleartype_strong_stem_width = 1;
101 FT_Bool dw_cleartype_strong_stem_width = 0;
103 TA_Progress_Func progress = NULL;
104 void* progress_data = NULL;
105 TA_Error_Func err = NULL;
106 void* err_data = NULL;
107 TA_Info_Func info = NULL;
108 void* info_data = NULL;
110 FT_Bool windows_compatibility = 0;
111 FT_Bool ignore_restrictions = 0;
112 FT_Bool adjust_subglyphs = 0;
113 FT_Bool hint_composites = 0;
114 FT_Bool symbol = 0;
116 const char* fallback_script_string = NULL;
117 const char* default_script_string = NULL;
118 TA_Style fallback_style = TA_STYLE_NONE_DFLT;
119 TA_Script default_script = TA_SCRIPT_LATN;
121 FT_Bool dehint = 0;
122 FT_Bool debug = 0;
124 const char* op;
126 #undef SCRIPT
127 #define SCRIPT(s, S, d, h, sc1, sc2, sc3) #s,
129 const char* script_names[] =
132 #include <ttfautohint-scripts.h>
137 if (!options || !*options)
139 error = FT_Err_Invalid_Argument;
140 goto Err1;
143 /* XXX */
144 va_start(ap, options);
146 op = options;
148 for(;;)
150 const char* start;
151 size_t len;
154 start = op;
156 /* search comma */
157 while (*op && *op != ',')
158 op++;
160 /* remove leading whitespace */
161 while (isspace(*start))
162 start++;
164 /* check for empty option */
165 if (start == op)
166 goto End;
168 len = op - start;
170 /* the `COMPARE' macro uses `len' and `start' */
172 /* handle options -- don't forget to update parameter dump below! */
173 if (COMPARE("adjust-subglyphs"))
174 adjust_subglyphs = (FT_Bool)va_arg(ap, FT_Int);
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("deltas-buffer"))
183 deltas_file = NULL;
184 deltas_buf = va_arg(ap, const char*);
186 else if (COMPARE("deltas-buffer-len"))
188 deltas_file = NULL;
189 deltas_len = va_arg(ap, size_t);
191 else if (COMPARE("deltas-file"))
193 deltas_file = va_arg(ap, FILE*);
194 deltas_buf = NULL;
195 deltas_len = 0;
197 else if (COMPARE("dw-cleartype-strong-stem-width"))
198 dw_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
199 else if (COMPARE("error-callback"))
200 err = va_arg(ap, TA_Error_Func);
201 else if (COMPARE("error-callback-data"))
202 err_data = va_arg(ap, void*);
203 else if (COMPARE("error-string"))
204 error_stringp = va_arg(ap, const unsigned char**);
205 else if (COMPARE("fallback-script"))
206 fallback_script_string = va_arg(ap, const char*);
207 else if (COMPARE("fallback-stem-width"))
208 fallback_stem_width = (FT_Long)va_arg(ap, FT_UInt);
209 else if (COMPARE("gdi-cleartype-strong-stem-width"))
210 gdi_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
211 else if (COMPARE("gray-strong-stem-width"))
212 gray_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
213 else if (COMPARE("hinting-limit"))
214 hinting_limit = (FT_Long)va_arg(ap, FT_UInt);
215 else if (COMPARE("hinting-range-max"))
216 hinting_range_max = (FT_Long)va_arg(ap, FT_UInt);
217 else if (COMPARE("hinting-range-min"))
218 hinting_range_min = (FT_Long)va_arg(ap, FT_UInt);
219 else if (COMPARE("hint-composites"))
220 hint_composites = (FT_Bool)va_arg(ap, FT_Int);
221 else if (COMPARE("ignore-restrictions"))
222 ignore_restrictions = (FT_Bool)va_arg(ap, FT_Int);
223 else if (COMPARE("in-buffer"))
225 in_file = NULL;
226 in_buf = va_arg(ap, const char*);
228 else if (COMPARE("in-buffer-len"))
230 in_file = NULL;
231 in_len = va_arg(ap, size_t);
233 else if (COMPARE("in-file"))
235 in_file = va_arg(ap, FILE*);
236 in_buf = NULL;
237 in_len = 0;
239 else if (COMPARE("increase-x-height"))
240 increase_x_height = (FT_Long)va_arg(ap, FT_UInt);
241 else if (COMPARE("info-callback"))
242 info = va_arg(ap, TA_Info_Func);
243 else if (COMPARE("info-callback-data"))
244 info_data = va_arg(ap, void*);
245 else if (COMPARE("out-buffer"))
247 out_file = NULL;
248 out_bufp = va_arg(ap, char**);
250 else if (COMPARE("out-buffer-len"))
252 out_file = NULL;
253 out_lenp = va_arg(ap, size_t*);
255 else if (COMPARE("out-file"))
257 out_file = va_arg(ap, FILE*);
258 out_bufp = NULL;
259 out_lenp = NULL;
261 else if (COMPARE("pre-hinting"))
262 adjust_subglyphs = (FT_Bool)va_arg(ap, FT_Int);
263 else if (COMPARE("progress-callback"))
264 progress = va_arg(ap, TA_Progress_Func);
265 else if (COMPARE("progress-callback-data"))
266 progress_data = va_arg(ap, void*);
267 else if (COMPARE("symbol"))
268 symbol = (FT_Bool)va_arg(ap, FT_Int);
269 else if (COMPARE("windows-compatibility"))
270 windows_compatibility = (FT_Bool)va_arg(ap, FT_Int);
271 else if (COMPARE("x-height-snapping-exceptions"))
272 x_height_snapping_exceptions_string = va_arg(ap, const char*);
273 else
275 error = TA_Err_Unknown_Argument;
276 goto Err1;
279 End:
280 if (!*op)
281 break;
282 op++;
285 va_end(ap);
287 /* check options */
289 if (!(in_file
290 || (in_buf && in_len)))
292 error = FT_Err_Invalid_Argument;
293 goto Err1;
296 if (!(out_file
297 || (out_bufp && out_lenp)))
299 error = FT_Err_Invalid_Argument;
300 goto Err1;
303 font = (FONT*)calloc(1, sizeof (FONT));
304 if (!font)
306 error = FT_Err_Out_Of_Memory;
307 goto Err1;
310 if (dehint)
311 goto No_check;
313 if (hinting_range_min >= 0 && hinting_range_min < 2)
315 error = FT_Err_Invalid_Argument;
316 goto Err1;
318 if (hinting_range_min < 0)
319 hinting_range_min = TA_HINTING_RANGE_MIN;
321 if (hinting_range_max >= 0 && hinting_range_max < hinting_range_min)
323 error = FT_Err_Invalid_Argument;
324 goto Err1;
326 if (hinting_range_max < 0)
327 hinting_range_max = TA_HINTING_RANGE_MAX;
329 /* value 0 is valid */
330 if (hinting_limit > 0 && hinting_limit < hinting_range_max)
332 error = FT_Err_Invalid_Argument;
333 goto Err1;
335 if (hinting_limit < 0)
336 hinting_limit = TA_HINTING_LIMIT;
338 if (increase_x_height > 0
339 && increase_x_height < TA_PROP_INCREASE_X_HEIGHT_MIN)
341 error = FT_Err_Invalid_Argument;
342 goto Err1;
344 if (increase_x_height < 0)
345 increase_x_height = TA_INCREASE_X_HEIGHT;
347 if (fallback_script_string)
349 int i;
352 for (i = 0; i < TA_STYLE_MAX; i++)
354 TA_StyleClass style_class = ta_style_classes[i];
357 if (style_class->coverage == TA_COVERAGE_DEFAULT
358 && !strcmp(script_names[style_class->script],
359 fallback_script_string))
360 break;
362 if (i == TA_STYLE_MAX)
364 error = FT_Err_Invalid_Argument;
365 goto Err1;
368 fallback_style = (TA_Style)i;
371 if (default_script_string)
373 int i;
376 for (i = 0; i < TA_SCRIPT_MAX; i++)
378 if (!strcmp(script_names[i], default_script_string))
379 break;
381 if (i == TA_SCRIPT_MAX)
383 error = FT_Err_Invalid_Argument;
384 goto Err1;
387 default_script = (TA_Script)i;
390 if (x_height_snapping_exceptions_string)
392 const char* s = number_set_parse(x_height_snapping_exceptions_string,
393 &x_height_snapping_exceptions,
394 TA_PROP_INCREASE_X_HEIGHT_MIN,
395 0x7FFF);
396 if (*s)
398 /* we map numberset.h's error codes to values starting with 0x100 */
399 error = 0x100 - (FT_Error)x_height_snapping_exceptions;
400 errlinenum = 0;
401 errline = (char*)x_height_snapping_exceptions_string;
402 errpos = (char*)s;
404 goto Err1;
408 font->hinting_range_min = (FT_UInt)hinting_range_min;
409 font->hinting_range_max = (FT_UInt)hinting_range_max;
410 font->hinting_limit = (FT_UInt)hinting_limit;
411 font->increase_x_height = increase_x_height;
412 font->x_height_snapping_exceptions = x_height_snapping_exceptions;
413 font->fallback_stem_width = (FT_UInt)fallback_stem_width;
415 font->gray_strong_stem_width = gray_strong_stem_width;
416 font->gdi_cleartype_strong_stem_width = gdi_cleartype_strong_stem_width;
417 font->dw_cleartype_strong_stem_width = dw_cleartype_strong_stem_width;
419 font->windows_compatibility = windows_compatibility;
420 font->ignore_restrictions = ignore_restrictions;
421 font->adjust_subglyphs = adjust_subglyphs;
422 font->hint_composites = hint_composites;
423 font->fallback_style = fallback_style;
424 font->default_script = default_script;
425 font->symbol = symbol;
427 No_check:
428 font->progress = progress;
429 font->progress_data = progress_data;
430 font->info = info;
431 font->info_data = info_data;
433 font->debug = debug;
434 font->dehint = dehint;
436 font->gasp_idx = MISSING;
438 /* start with processing the data */
440 if (in_file)
442 error = TA_font_file_read(font, in_file);
443 if (error)
444 goto Err;
446 else
448 /* a valid TTF can never be that small */
449 if (in_len < 100)
451 error = TA_Err_Invalid_Font_Type;
452 goto Err1;
454 font->in_buf = (FT_Byte*)in_buf;
455 font->in_len = in_len;
458 if (deltas_file)
460 error = TA_deltas_file_read(font, deltas_file);
461 if (error)
462 goto Err;
464 else if (deltas_buf)
466 font->deltas_buf = (char*)deltas_buf;
467 font->deltas_len = deltas_len;
470 error = TA_font_init(font);
471 if (error)
472 goto Err;
474 if (font->debug)
476 _ta_debug = 1;
477 _ta_debug_global = 1;
480 /* we do some loops over all subfonts -- */
481 /* to process options early, just start with loading all of them */
482 for (i = 0; i < font->num_sfnts; i++)
484 SFNT* sfnt = &font->sfnts[i];
485 FT_UInt idx;
488 error = FT_New_Memory_Face(font->lib, font->in_buf, font->in_len,
489 i, &sfnt->face);
491 /* assure that the font hasn't been already processed by ttfautohint; */
492 /* another, more thorough check is done in TA_glyph_parse_simple */
493 idx = FT_Get_Name_Index(sfnt->face, (FT_String*)TTFAUTOHINT_GLYPH);
494 if (idx)
496 error = TA_Err_Already_Processed;
497 goto Err;
500 if (error)
501 goto Err;
504 /* process delta exceptions data */
505 error = TA_deltas_parse(font, &deltas, &errlinenum, &errline, &errpos);
506 if (error)
508 free_errline = 1;
509 goto Err;
512 /* now we are able to dump all parameters */
513 if (debug)
515 fprintf(stderr, "TTF_autohint parameters\n"
516 "=======================\n"
517 "\n");
519 if (dehint)
520 DUMPVAL("dehint",
521 font->dehint);
522 else
524 char *s;
527 DUMPSTR("default-script",
528 script_names[font->default_script]);
529 DUMPVAL("dw-cleartype-strong-stem-width",
530 font->dw_cleartype_strong_stem_width);
531 DUMPSTR("fallback-script",
532 script_names[ta_style_classes[font->fallback_style]->script]);
533 DUMPVAL("fallback-stem-width",
534 font->fallback_stem_width);
535 DUMPVAL("gdi-cleartype-strong-stem-width",
536 font->gdi_cleartype_strong_stem_width);
537 DUMPVAL("gray-strong-stem-width",
538 font->gray_strong_stem_width);
539 DUMPVAL("hinting-limit",
540 font->hinting_limit);
541 DUMPVAL("hinting-range-max",
542 font->hinting_range_max);
543 DUMPVAL("hinting-range-min",
544 font->hinting_range_min);
545 DUMPVAL("hint-composites",
546 font->hint_composites);
547 DUMPVAL("ignore-restrictions",
548 font->ignore_restrictions);
549 DUMPVAL("increase-x-height",
550 font->increase_x_height);
551 DUMPVAL("adjust-subglyphs",
552 font->adjust_subglyphs);
553 DUMPVAL("symbol",
554 font->symbol);
555 DUMPVAL("windows-compatibility",
556 font->windows_compatibility);
558 s = number_set_show(font->x_height_snapping_exceptions,
559 TA_PROP_INCREASE_X_HEIGHT_MIN, 0x7FFF);
560 if (s)
562 DUMPSTR("x-height-snapping-exceptions", s);
563 free(s);
565 else
567 error = FT_Err_Out_Of_Memory;
568 goto Err;
571 s = TA_deltas_show(font, deltas);
572 if (s)
574 char* token;
575 char* saveptr;
578 /* show delta exceptions data line by line */
579 token = strtok_r(s, "\n", &saveptr);
580 DUMPSTR("delta exceptions", token);
582 for (;;)
584 token = strtok_r(NULL, "\n", &saveptr);
585 if (!token)
586 break;
588 DUMPSTRX(token);
591 free(s);
593 else
595 error = FT_Err_Out_Of_Memory;
596 goto Err;
600 fprintf(stderr, "\n");
603 error = TA_deltas_build_tree(font, deltas);
604 if (error)
605 goto Err;
607 /* loop again over subfonts and continue processing */
608 for (i = 0; i < font->num_sfnts; i++)
610 SFNT* sfnt = &font->sfnts[i];
613 error = TA_sfnt_split_into_SFNT_tables(sfnt, font);
614 if (error)
615 goto Err;
617 /* check permission */
618 if (sfnt->OS2_idx != MISSING)
620 SFNT_Table* OS2_table = &font->tables[sfnt->OS2_idx];
623 /* check lower byte of the `fsType' field */
624 if (OS2_table->buf[OS2_FSTYPE_OFFSET + 1] == 0x02
625 && !font->ignore_restrictions)
627 error = TA_Err_Missing_Legal_Permission;
628 goto Err;
632 if (font->dehint)
634 error = TA_sfnt_split_glyf_table(sfnt, font);
635 if (error)
636 goto Err;
638 else
640 if (font->adjust_subglyphs)
641 error = TA_sfnt_create_glyf_data(sfnt, font);
642 else
643 error = TA_sfnt_split_glyf_table(sfnt, font);
644 if (error)
645 goto Err;
647 /* this call creates a `globals' object... */
648 error = TA_sfnt_handle_coverage(sfnt, font);
649 if (error)
650 goto Err;
652 /* ... so that we now can initialize its properties */
653 TA_sfnt_set_properties(sfnt, font);
657 if (!font->dehint)
659 for (i = 0; i < font->num_sfnts; i++)
661 SFNT* sfnt = &font->sfnts[i];
664 TA_sfnt_adjust_coverage(sfnt, font);
668 #if 0
669 /* this code is here for completeness -- */
670 /* right now, `glyf' tables get hinted only once, */
671 /* and referring subfonts simply reuse it, */
672 /* but this might change in the future */
674 if (!font->dehint)
676 for (i = 0; i < font->num_sfnts; i++)
678 SFNT* sfnt = &font->sfnts[i];
681 TA_sfnt_copy_master_coverage(sfnt, font);
684 #endif
686 /* loop again over subfonts */
687 for (i = 0; i < font->num_sfnts; i++)
689 SFNT* sfnt = &font->sfnts[i];
692 error = ta_loader_init(font);
693 if (error)
694 goto Err;
696 error = TA_sfnt_build_gasp_table(sfnt, font);
697 if (error)
698 goto Err;
699 if (!font->dehint)
701 error = TA_sfnt_build_cvt_table(sfnt, font);
702 if (error)
703 goto Err;
704 error = TA_sfnt_build_fpgm_table(sfnt, font);
705 if (error)
706 goto Err;
707 error = TA_sfnt_build_prep_table(sfnt, font);
708 if (error)
709 goto Err;
711 error = TA_sfnt_build_glyf_table(sfnt, font);
712 if (error)
713 goto Err;
714 error = TA_sfnt_build_loca_table(sfnt, font);
715 if (error)
716 goto Err;
718 if (font->loader)
719 ta_loader_done(font);
722 for (i = 0; i < font->num_sfnts; i++)
724 SFNT* sfnt = &font->sfnts[i];
727 error = TA_sfnt_update_maxp_table(sfnt, font);
728 if (error)
729 goto Err;
731 if (!font->dehint)
733 /* we add one glyph for composites */
734 if (sfnt->max_components
735 && !font->adjust_subglyphs
736 && font->hint_composites)
738 error = TA_sfnt_update_hmtx_table(sfnt, font);
739 if (error)
740 goto Err;
741 error = TA_sfnt_update_post_table(sfnt, font);
742 if (error)
743 goto Err;
744 error = TA_sfnt_update_GPOS_table(sfnt, font);
745 if (error)
746 goto Err;
750 if (font->info)
752 /* add info about ttfautohint to the version string */
753 error = TA_sfnt_update_name_table(sfnt, font);
754 if (error)
755 goto Err;
759 if (font->num_sfnts == 1)
760 error = TA_font_build_TTF(font);
761 else
762 error = TA_font_build_TTC(font);
763 if (error)
764 goto Err;
766 if (out_file)
768 error = TA_font_file_write(font, out_file);
769 if (error)
770 goto Err;
772 else
774 *out_bufp = (char*)font->out_buf;
775 *out_lenp = font->out_len;
778 error = TA_Err_Ok;
780 Err:
781 TA_deltas_free(deltas);
782 TA_deltas_free_tree(font);
783 TA_font_unload(font, in_buf, out_bufp, deltas_buf);
785 Err1:
786 error_string = TA_get_error_message(error);
788 if (error_stringp)
789 *error_stringp = (const unsigned char*)error_string;
791 if (err)
792 err(error,
793 error_string,
794 errlinenum,
795 errline,
796 errpos,
797 err_data);
799 if (free_errline)
800 free(errline);
802 return error;
805 /* end of ttfautohint.c */