Add support for SOURCE_DATE_EPOCH environment variable.
[ttfautohint.git] / lib / ttfautohint.c
blobbb19225eb76afc7be09fa9f4c271a7f9b3b59187
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 <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 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 const char* in_buf = NULL;
65 size_t in_len = 0;
66 char** out_bufp = NULL;
67 size_t* out_lenp = NULL;
68 const char* control_buf = NULL;
69 size_t control_len = 0;
71 const unsigned char** error_stringp = NULL;
73 FT_Long hinting_range_min = -1;
74 FT_Long hinting_range_max = -1;
75 FT_Long hinting_limit = -1;
76 FT_Long increase_x_height = -1;
78 const char* x_height_snapping_exceptions_string = NULL;
79 number_range* x_height_snapping_exceptions = NULL;
81 FT_Long fallback_stem_width = 0;
83 FT_Bool gray_strong_stem_width = 0;
84 FT_Bool gdi_cleartype_strong_stem_width = 1;
85 FT_Bool dw_cleartype_strong_stem_width = 0;
87 TA_Progress_Func progress = NULL;
88 void* progress_data = NULL;
89 TA_Error_Func err = NULL;
90 void* err_data = NULL;
91 TA_Info_Func info = NULL;
92 TA_Info_Post_Func info_post = NULL;
93 void* info_data = NULL;
95 FT_Bool windows_compatibility = 0;
96 FT_Bool ignore_restrictions = 0;
97 FT_Bool adjust_subglyphs = 0;
98 FT_Bool hint_composites = 0;
99 FT_Bool symbol = 0;
100 FT_Bool fallback_scaling = 0;
102 const char* fallback_script_string = NULL;
103 const char* default_script_string = NULL;
105 TA_Style fallback_style = TA_STYLE_NONE_DFLT;
106 TA_Script default_script = TA_SCRIPT_LATN;
108 FT_Bool dehint = 0;
109 FT_Bool debug = 0;
110 FT_Bool TTFA_info = 0;
111 unsigned long long epoch = ULLONG_MAX;
113 const char* op;
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 = (size_t)(op - start);
148 /* the `COMPARE' macro uses `len' and `start' */
150 /* handle options -- don't forget to update parameter dump below! */
151 if (COMPARE("adjust-subglyphs"))
152 adjust_subglyphs = (FT_Bool)va_arg(ap, FT_Int);
153 else if (COMPARE("debug"))
154 debug = (FT_Bool)va_arg(ap, FT_Int);
155 else if (COMPARE("default-script"))
156 default_script_string = va_arg(ap, const char*);
157 else if (COMPARE("dehint"))
158 dehint = (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("dw-cleartype-strong-stem-width"))
176 dw_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
177 else if (COMPARE("epoch"))
178 epoch = (unsigned long long)va_arg(ap, unsigned long long);
179 else if (COMPARE("error-callback"))
180 err = va_arg(ap, TA_Error_Func);
181 else if (COMPARE("error-callback-data"))
182 err_data = va_arg(ap, void*);
183 else if (COMPARE("error-string"))
184 error_stringp = va_arg(ap, const unsigned char**);
185 else if (COMPARE("fallback-scaling"))
186 fallback_scaling = (FT_Bool)va_arg(ap, FT_Int);
187 else if (COMPARE("fallback-script"))
188 fallback_script_string = va_arg(ap, const char*);
189 else if (COMPARE("fallback-stem-width"))
190 fallback_stem_width = (FT_Long)va_arg(ap, FT_UInt);
191 else if (COMPARE("gdi-cleartype-strong-stem-width"))
192 gdi_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
193 else if (COMPARE("gray-strong-stem-width"))
194 gray_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
195 else if (COMPARE("hinting-limit"))
196 hinting_limit = (FT_Long)va_arg(ap, FT_UInt);
197 else if (COMPARE("hinting-range-max"))
198 hinting_range_max = (FT_Long)va_arg(ap, FT_UInt);
199 else if (COMPARE("hinting-range-min"))
200 hinting_range_min = (FT_Long)va_arg(ap, FT_UInt);
201 else if (COMPARE("hint-composites"))
202 hint_composites = (FT_Bool)va_arg(ap, FT_Int);
203 else if (COMPARE("ignore-restrictions"))
204 ignore_restrictions = (FT_Bool)va_arg(ap, FT_Int);
205 else if (COMPARE("in-buffer"))
207 in_file = NULL;
208 in_buf = va_arg(ap, const char*);
210 else if (COMPARE("in-buffer-len"))
212 in_file = NULL;
213 in_len = va_arg(ap, size_t);
215 else if (COMPARE("in-file"))
217 in_file = va_arg(ap, FILE*);
218 in_buf = NULL;
219 in_len = 0;
221 else if (COMPARE("increase-x-height"))
222 increase_x_height = (FT_Long)va_arg(ap, FT_UInt);
223 else if (COMPARE("info-callback"))
224 info = va_arg(ap, TA_Info_Func);
225 else if (COMPARE("info-callback-data"))
226 info_data = va_arg(ap, void*);
227 else if (COMPARE("info-post-callback"))
228 info_post = va_arg(ap, TA_Info_Post_Func);
229 else if (COMPARE("out-buffer"))
231 out_file = NULL;
232 out_bufp = va_arg(ap, char**);
234 else if (COMPARE("out-buffer-len"))
236 out_file = NULL;
237 out_lenp = va_arg(ap, size_t*);
239 else if (COMPARE("out-file"))
241 out_file = va_arg(ap, FILE*);
242 out_bufp = NULL;
243 out_lenp = NULL;
245 else if (COMPARE("pre-hinting"))
246 adjust_subglyphs = (FT_Bool)va_arg(ap, FT_Int);
247 else if (COMPARE("progress-callback"))
248 progress = va_arg(ap, TA_Progress_Func);
249 else if (COMPARE("progress-callback-data"))
250 progress_data = va_arg(ap, void*);
251 else if (COMPARE("symbol"))
252 symbol = (FT_Bool)va_arg(ap, FT_Int);
253 else if (COMPARE("TTFA-info"))
254 TTFA_info = (FT_Bool)va_arg(ap, FT_Int);
255 else if (COMPARE("windows-compatibility"))
256 windows_compatibility = (FT_Bool)va_arg(ap, FT_Int);
257 else if (COMPARE("x-height-snapping-exceptions"))
258 x_height_snapping_exceptions_string = va_arg(ap, const char*);
259 else
261 error = TA_Err_Unknown_Argument;
262 goto Err1;
265 End:
266 if (!*op)
267 break;
268 op++;
271 va_end(ap);
273 /* check options */
275 if (!(in_file
276 || (in_buf && in_len)))
278 error = FT_Err_Invalid_Argument;
279 goto Err1;
282 if (!(out_file
283 || (out_bufp && out_lenp)))
285 error = FT_Err_Invalid_Argument;
286 goto Err1;
289 font = (FONT*)calloc(1, sizeof (FONT));
290 if (!font)
292 error = FT_Err_Out_Of_Memory;
293 goto Err1;
296 if (dehint)
297 goto No_check;
299 if (hinting_range_min >= 0 && hinting_range_min < 2)
301 error = FT_Err_Invalid_Argument;
302 goto Err1;
304 if (hinting_range_min < 0)
305 hinting_range_min = TA_HINTING_RANGE_MIN;
307 if (hinting_range_max >= 0 && hinting_range_max < hinting_range_min)
309 error = FT_Err_Invalid_Argument;
310 goto Err1;
312 if (hinting_range_max < 0)
313 hinting_range_max = TA_HINTING_RANGE_MAX;
315 /* value 0 is valid */
316 if (hinting_limit > 0 && hinting_limit < hinting_range_max)
318 error = FT_Err_Invalid_Argument;
319 goto Err1;
321 if (hinting_limit < 0)
322 hinting_limit = TA_HINTING_LIMIT;
324 if (increase_x_height > 0
325 && increase_x_height < TA_PROP_INCREASE_X_HEIGHT_MIN)
327 error = FT_Err_Invalid_Argument;
328 goto Err1;
330 if (increase_x_height < 0)
331 increase_x_height = TA_INCREASE_X_HEIGHT;
333 if (fallback_script_string)
335 for (i = 0; i < TA_STYLE_MAX; i++)
337 TA_StyleClass style_class = ta_style_classes[i];
340 if (style_class->coverage == TA_COVERAGE_DEFAULT
341 && !strcmp(script_names[style_class->script],
342 fallback_script_string))
343 break;
345 if (i == TA_STYLE_MAX)
347 error = FT_Err_Invalid_Argument;
348 goto Err1;
351 fallback_style = (TA_Style)i;
354 if (default_script_string)
356 for (i = 0; i < TA_SCRIPT_MAX; i++)
358 if (!strcmp(script_names[i], default_script_string))
359 break;
361 if (i == TA_SCRIPT_MAX)
363 error = FT_Err_Invalid_Argument;
364 goto Err1;
367 default_script = (TA_Script)i;
370 if (x_height_snapping_exceptions_string)
372 const char* s = number_set_parse(x_height_snapping_exceptions_string,
373 &x_height_snapping_exceptions,
374 TA_PROP_INCREASE_X_HEIGHT_MIN,
375 0x7FFF);
376 if (*s)
378 /* we map numberset.h's error codes to values starting with 0x100 */
379 error = 0x100 - (FT_Error)(uintptr_t)x_height_snapping_exceptions;
380 errlinenum = 0;
381 errline = (char*)x_height_snapping_exceptions_string;
382 errpos = (char*)s;
384 goto Err1;
388 font->hinting_range_min = (FT_UInt)hinting_range_min;
389 font->hinting_range_max = (FT_UInt)hinting_range_max;
390 font->hinting_limit = (FT_UInt)hinting_limit;
391 font->increase_x_height = (FT_UInt)increase_x_height;
392 font->x_height_snapping_exceptions = x_height_snapping_exceptions;
393 font->fallback_stem_width = (FT_UInt)fallback_stem_width;
395 font->gray_strong_stem_width = gray_strong_stem_width;
396 font->gdi_cleartype_strong_stem_width = gdi_cleartype_strong_stem_width;
397 font->dw_cleartype_strong_stem_width = dw_cleartype_strong_stem_width;
399 font->windows_compatibility = windows_compatibility;
400 font->ignore_restrictions = ignore_restrictions;
401 font->adjust_subglyphs = adjust_subglyphs;
402 font->hint_composites = hint_composites;
403 font->fallback_style = fallback_style;
404 font->fallback_scaling = fallback_scaling;
405 font->default_script = default_script;
406 font->symbol = symbol;
408 No_check:
409 font->progress = progress;
410 font->progress_data = progress_data;
411 font->info = info;
412 font->info_post = info_post;
413 font->info_data = info_data;
415 font->debug = debug;
416 font->dehint = dehint;
417 font->TTFA_info = TTFA_info;
418 font->epoch = epoch;
420 font->gasp_idx = MISSING;
422 /* start with processing the data */
424 if (in_file)
426 error = TA_font_file_read(font, in_file);
427 if (error)
428 goto Err;
430 else
432 /* a valid TTF can never be that small */
433 if (in_len < 100)
435 error = TA_Err_Invalid_Font_Type;
436 goto Err1;
438 font->in_buf = (FT_Byte*)in_buf;
439 font->in_len = in_len;
442 if (control_file)
444 error = TA_control_file_read(font, control_file);
445 if (error)
446 goto Err;
448 else if (control_buf)
450 font->control_buf = (char*)control_buf;
451 font->control_len = control_len;
454 error = TA_font_init(font);
455 if (error)
456 goto Err;
458 if (font->debug)
460 _ta_debug = 1;
461 _ta_debug_global = 1;
464 /* we do some loops over all subfonts -- */
465 /* to process options early, just start with loading all of them */
466 for (i = 0; i < font->num_sfnts; i++)
468 SFNT* sfnt = &font->sfnts[i];
469 FT_UInt idx;
472 error = FT_New_Memory_Face(font->lib,
473 font->in_buf,
474 (FT_Long)font->in_len,
476 &sfnt->face);
478 /* assure that the font hasn't been already processed by ttfautohint; */
479 /* another, more thorough check is done in TA_glyph_parse_simple */
480 idx = FT_Get_Name_Index(sfnt->face, (FT_String*)TTFAUTOHINT_GLYPH);
481 if (idx)
483 error = TA_Err_Already_Processed;
484 goto Err;
487 if (error)
488 goto Err;
491 /* process control instructions */
492 error = TA_control_parse_buffer(font,
493 &error_string,
494 &errlinenum, &errline, &errpos);
495 if (error)
497 free_errline = 1;
498 free_error_string = 1;
499 goto Err;
502 /* now we are able to dump all parameters */
503 if (debug)
505 char* s;
508 s = TA_font_dump_parameters(font, 1);
509 if (!s)
511 error = FT_Err_Out_Of_Memory;
512 goto Err;
515 fprintf(stderr, "%s", s);
516 free(s);
519 error = TA_control_build_tree(font);
520 if (error)
521 goto Err;
523 /* loop again over subfonts and continue processing */
524 for (i = 0; i < font->num_sfnts; i++)
526 SFNT* sfnt = &font->sfnts[i];
529 error = TA_sfnt_split_into_SFNT_tables(sfnt, font);
530 if (error)
531 goto Err;
533 /* check permission */
534 if (sfnt->OS2_idx != MISSING)
536 SFNT_Table* OS2_table = &font->tables[sfnt->OS2_idx];
539 /* check lower byte of the `fsType' field */
540 if (OS2_table->buf[OS2_FSTYPE_OFFSET + 1] == 0x02
541 && !font->ignore_restrictions)
543 error = TA_Err_Missing_Legal_Permission;
544 goto Err;
548 if (font->dehint)
550 error = TA_sfnt_split_glyf_table(sfnt, font);
551 if (error)
552 goto Err;
554 else
556 if (font->adjust_subglyphs)
557 error = TA_sfnt_create_glyf_data(sfnt, font);
558 else
559 error = TA_sfnt_split_glyf_table(sfnt, font);
560 if (error)
561 goto Err;
563 /* this call creates a `globals' object... */
564 error = TA_sfnt_handle_coverage(sfnt, font);
565 if (error)
566 goto Err;
568 /* ... so that we now can initialize its properties */
569 TA_sfnt_set_properties(sfnt, font);
573 if (!font->dehint)
575 for (i = 0; i < font->num_sfnts; i++)
577 SFNT* sfnt = &font->sfnts[i];
580 TA_sfnt_adjust_coverage(sfnt, font);
584 #if 0
585 /* this code is here for completeness -- */
586 /* right now, `glyf' tables get hinted only once, */
587 /* and referring subfonts simply reuse it, */
588 /* but this might change in the future */
590 if (!font->dehint)
592 for (i = 0; i < font->num_sfnts; i++)
594 SFNT* sfnt = &font->sfnts[i];
597 TA_sfnt_copy_master_coverage(sfnt, font);
600 #endif
602 if (!font->dehint)
604 for (i = 0; i < font->num_sfnts; i++)
606 SFNT* sfnt = &font->sfnts[i];
609 TA_control_apply_coverage(sfnt, font);
613 /* loop again over subfonts */
614 for (i = 0; i < font->num_sfnts; i++)
616 SFNT* sfnt = &font->sfnts[i];
619 error = ta_loader_init(font);
620 if (error)
621 goto Err;
623 error = TA_sfnt_build_gasp_table(sfnt, font);
624 if (error)
625 goto Err;
626 if (!font->dehint)
628 error = TA_sfnt_build_cvt_table(sfnt, font);
629 if (error)
630 goto Err;
631 error = TA_sfnt_build_fpgm_table(sfnt, font);
632 if (error)
633 goto Err;
634 error = TA_sfnt_build_prep_table(sfnt, font);
635 if (error)
636 goto Err;
638 error = TA_sfnt_build_glyf_table(sfnt, font);
639 if (error)
640 goto Err;
641 error = TA_sfnt_build_loca_table(sfnt, font);
642 if (error)
643 goto Err;
645 if (font->loader)
646 ta_loader_done(font);
649 for (i = 0; i < font->num_sfnts; i++)
651 SFNT* sfnt = &font->sfnts[i];
654 error = TA_sfnt_update_maxp_table(sfnt, font);
655 if (error)
656 goto Err;
658 if (!font->dehint)
660 /* we add one glyph for composites */
661 if (sfnt->max_components
662 && !font->adjust_subglyphs
663 && font->hint_composites)
665 error = TA_sfnt_update_hmtx_table(sfnt, font);
666 if (error)
667 goto Err;
668 error = TA_sfnt_update_post_table(sfnt, font);
669 if (error)
670 goto Err;
671 error = TA_sfnt_update_GPOS_table(sfnt, font);
672 if (error)
673 goto Err;
677 if (font->info)
679 /* add info about ttfautohint to the version string */
680 error = TA_sfnt_update_name_table(sfnt, font);
681 if (error)
682 goto Err;
686 if (font->num_sfnts == 1)
687 error = TA_font_build_TTF(font);
688 else
689 error = TA_font_build_TTC(font);
690 if (error)
691 goto Err;
693 if (out_file)
695 error = TA_font_file_write(font, out_file);
696 if (error)
697 goto Err;
699 else
701 *out_bufp = (char*)font->out_buf;
702 *out_lenp = font->out_len;
705 error = TA_Err_Ok;
707 Err:
708 TA_control_free(font->control);
709 TA_control_free_tree(font);
710 TA_font_unload(font, in_buf, out_bufp, control_buf);
712 Err1:
713 if (!error_string)
714 error_string = (char*)TA_get_error_message(error);
716 /* this must be a static value */
717 if (error_stringp)
718 *error_stringp = (const unsigned char*)TA_get_error_message(error);
720 if (err)
721 err(error,
722 error_string,
723 errlinenum,
724 errline,
725 errpos,
726 err_data);
728 if (free_errline)
729 free(errline);
730 if (free_error_string)
731 free(error_string);
733 return error;
736 /* end of ttfautohint.c */