Minor renamings and type fiddling.
[ttfautohint.git] / lib / ttfautohint.c
blob7c6ae8690cae5d44e2516b273ee4f3b860afff2b
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 DUMP_COLUMN "33"
28 #define COMPARE(str) \
29 (len == (sizeof (str) - 1) \
30 && !strncmp(start, str, sizeof (str) - 1))
31 #define DUMPVAL(str, arg) \
32 fprintf(stderr, "%" DUMP_COLUMN "s = %ld\n", \
33 (str), \
34 (FT_Long)(arg))
35 #define DUMPSTR(str, arg) \
36 fprintf(stderr, "%" DUMP_COLUMN "s = %s\n", \
37 (str), \
38 (arg))
39 #define DUMPSTRX(arg) \
40 fprintf(stderr, "%" DUMP_COLUMN "s %s\n", \
41 "", \
42 (arg))
45 void
46 TA_sfnt_set_properties(SFNT* sfnt,
47 FONT* font)
49 TA_FaceGlobals globals = (TA_FaceGlobals)sfnt->face->autohint.data;
52 globals->increase_x_height = font->increase_x_height;
56 TA_Error
57 TTF_autohint(const char* options,
58 ...)
60 va_list ap;
62 FONT* font;
63 FT_Long i;
65 FT_Error error;
66 const char* error_string = NULL;
67 unsigned int errlinenum = 0;
68 char* errline = NULL;
69 char* errpos = NULL;
71 FILE* in_file = NULL;
72 FILE* out_file = NULL;
74 const char* in_buf = NULL;
75 size_t in_len = 0;
76 char** out_bufp = NULL;
77 size_t* out_lenp = NULL;
79 const unsigned char** error_stringp = NULL;
81 FT_Long hinting_range_min = -1;
82 FT_Long hinting_range_max = -1;
83 FT_Long hinting_limit = -1;
84 FT_Long increase_x_height = -1;
86 const char* x_height_snapping_exceptions_string = NULL;
87 number_range* x_height_snapping_exceptions = NULL;
89 FT_Long fallback_stem_width = 0;
91 FT_Bool gray_strong_stem_width = 0;
92 FT_Bool gdi_cleartype_strong_stem_width = 1;
93 FT_Bool dw_cleartype_strong_stem_width = 0;
95 TA_Progress_Func progress = NULL;
96 void* progress_data = NULL;
97 TA_Error_Func err = NULL;
98 void* err_data = NULL;
99 TA_Info_Func info = NULL;
100 void* info_data = NULL;
102 FT_Bool windows_compatibility = 0;
103 FT_Bool ignore_restrictions = 0;
104 FT_Bool adjust_subglyphs = 0;
105 FT_Bool hint_composites = 0;
106 FT_Bool symbol = 0;
108 const char* fallback_script_string = NULL;
109 const char* default_script_string = NULL;
110 TA_Style fallback_style = TA_STYLE_NONE_DFLT;
111 TA_Script default_script = TA_SCRIPT_LATN;
113 FT_Bool dehint = 0;
114 FT_Bool debug = 0;
116 const char* op;
118 #undef SCRIPT
119 #define SCRIPT(s, S, d, h, sc1, sc2, sc3) #s,
121 const char* script_names[] =
124 #include <ttfautohint-scripts.h>
129 if (!options || !*options)
131 error = FT_Err_Invalid_Argument;
132 goto Err1;
135 /* XXX */
136 va_start(ap, options);
138 op = options;
140 for(;;)
142 const char* start;
143 size_t len;
146 start = op;
148 /* search comma */
149 while (*op && *op != ',')
150 op++;
152 /* remove leading whitespace */
153 while (isspace(*start))
154 start++;
156 /* check for empty option */
157 if (start == op)
158 goto End;
160 len = op - start;
162 /* the `COMPARE' macro uses `len' and `start' */
164 /* handle options -- don't forget to update parameter dump below! */
165 if (COMPARE("adjust-subglyphs"))
166 adjust_subglyphs = (FT_Bool)va_arg(ap, FT_Int);
167 else if (COMPARE("debug"))
168 debug = (FT_Bool)va_arg(ap, FT_Int);
169 else if (COMPARE("default-script"))
170 default_script_string = va_arg(ap, const char*);
171 else if (COMPARE("dehint"))
172 dehint = (FT_Bool)va_arg(ap, FT_Int);
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-script"))
182 fallback_script_string = va_arg(ap, const char*);
183 else if (COMPARE("fallback-stem-width"))
184 fallback_stem_width = (FT_Long)va_arg(ap, FT_UInt);
185 else if (COMPARE("gdi-cleartype-strong-stem-width"))
186 gdi_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
187 else if (COMPARE("gray-strong-stem-width"))
188 gray_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
189 else if (COMPARE("hinting-limit"))
190 hinting_limit = (FT_Long)va_arg(ap, FT_UInt);
191 else if (COMPARE("hinting-range-max"))
192 hinting_range_max = (FT_Long)va_arg(ap, FT_UInt);
193 else if (COMPARE("hinting-range-min"))
194 hinting_range_min = (FT_Long)va_arg(ap, FT_UInt);
195 else if (COMPARE("hint-composites"))
196 hint_composites = (FT_Bool)va_arg(ap, FT_Int);
197 else if (COMPARE("ignore-restrictions"))
198 ignore_restrictions = (FT_Bool)va_arg(ap, FT_Int);
199 else if (COMPARE("in-buffer"))
201 in_file = NULL;
202 in_buf = va_arg(ap, const char*);
204 else if (COMPARE("in-buffer-len"))
206 in_file = NULL;
207 in_len = va_arg(ap, size_t);
209 else if (COMPARE("in-file"))
211 in_file = va_arg(ap, FILE*);
212 in_buf = NULL;
213 in_len = 0;
215 else if (COMPARE("increase-x-height"))
216 increase_x_height = (FT_Long)va_arg(ap, FT_UInt);
217 else if (COMPARE("info-callback"))
218 info = va_arg(ap, TA_Info_Func);
219 else if (COMPARE("info-callback-data"))
220 info_data = va_arg(ap, void*);
221 else if (COMPARE("out-buffer"))
223 out_file = NULL;
224 out_bufp = va_arg(ap, char**);
226 else if (COMPARE("out-buffer-len"))
228 out_file = NULL;
229 out_lenp = va_arg(ap, size_t*);
231 else if (COMPARE("out-file"))
233 out_file = va_arg(ap, FILE*);
234 out_bufp = NULL;
235 out_lenp = NULL;
237 else if (COMPARE("pre-hinting"))
238 adjust_subglyphs = (FT_Bool)va_arg(ap, FT_Int);
239 else if (COMPARE("progress-callback"))
240 progress = va_arg(ap, TA_Progress_Func);
241 else if (COMPARE("progress-callback-data"))
242 progress_data = va_arg(ap, void*);
243 else if (COMPARE("symbol"))
244 symbol = (FT_Bool)va_arg(ap, FT_Int);
245 else if (COMPARE("windows-compatibility"))
246 windows_compatibility = (FT_Bool)va_arg(ap, FT_Int);
247 else if (COMPARE("x-height-snapping-exceptions"))
248 x_height_snapping_exceptions_string = va_arg(ap, const char*);
249 else
251 error = TA_Err_Unknown_Argument;
252 goto Err1;
255 End:
256 if (!*op)
257 break;
258 op++;
261 va_end(ap);
263 /* check options */
265 if (!(in_file
266 || (in_buf && in_len)))
268 error = FT_Err_Invalid_Argument;
269 goto Err1;
272 if (!(out_file
273 || (out_bufp && out_lenp)))
275 error = FT_Err_Invalid_Argument;
276 goto Err1;
279 font = (FONT*)calloc(1, sizeof (FONT));
280 if (!font)
282 error = FT_Err_Out_Of_Memory;
283 goto Err1;
286 if (dehint)
287 goto No_check;
289 if (hinting_range_min >= 0 && hinting_range_min < 2)
291 error = FT_Err_Invalid_Argument;
292 goto Err1;
294 if (hinting_range_min < 0)
295 hinting_range_min = TA_HINTING_RANGE_MIN;
297 if (hinting_range_max >= 0 && hinting_range_max < hinting_range_min)
299 error = FT_Err_Invalid_Argument;
300 goto Err1;
302 if (hinting_range_max < 0)
303 hinting_range_max = TA_HINTING_RANGE_MAX;
305 /* value 0 is valid */
306 if (hinting_limit > 0 && hinting_limit < hinting_range_max)
308 error = FT_Err_Invalid_Argument;
309 goto Err1;
311 if (hinting_limit < 0)
312 hinting_limit = TA_HINTING_LIMIT;
314 if (increase_x_height > 0
315 && increase_x_height < TA_PROP_INCREASE_X_HEIGHT_MIN)
317 error = FT_Err_Invalid_Argument;
318 goto Err1;
320 if (increase_x_height < 0)
321 increase_x_height = TA_INCREASE_X_HEIGHT;
323 if (fallback_script_string)
325 int i;
328 for (i = 0; i < TA_STYLE_MAX; i++)
330 TA_StyleClass style_class = ta_style_classes[i];
333 if (style_class->coverage == TA_COVERAGE_DEFAULT
334 && !strcmp(script_names[style_class->script],
335 fallback_script_string))
336 break;
338 if (i == TA_STYLE_MAX)
340 error = FT_Err_Invalid_Argument;
341 goto Err1;
344 fallback_style = (TA_Style)i;
347 if (default_script_string)
349 int i;
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)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 = 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->default_script = default_script;
401 font->symbol = symbol;
403 No_check:
404 font->progress = progress;
405 font->progress_data = progress_data;
406 font->info = info;
407 font->info_data = info_data;
409 font->debug = debug;
410 font->dehint = dehint;
412 font->gasp_idx = MISSING;
414 /* dump parameters */
415 if (debug)
417 fprintf(stderr, "TTF_autohint parameters\n"
418 "=======================\n"
419 "\n");
421 if (dehint)
422 DUMPVAL("dehint",
423 font->dehint);
424 else
426 char *s;
429 DUMPSTR("default-script",
430 script_names[font->default_script]);
431 DUMPVAL("dw-cleartype-strong-stem-width",
432 font->dw_cleartype_strong_stem_width);
433 DUMPSTR("fallback-script",
434 script_names[ta_style_classes[font->fallback_style]->script]);
435 DUMPVAL("fallback-stem-width",
436 font->fallback_stem_width);
437 DUMPVAL("gdi-cleartype-strong-stem-width",
438 font->gdi_cleartype_strong_stem_width);
439 DUMPVAL("gray-strong-stem-width",
440 font->gray_strong_stem_width);
441 DUMPVAL("hinting-limit",
442 font->hinting_limit);
443 DUMPVAL("hinting-range-max",
444 font->hinting_range_max);
445 DUMPVAL("hinting-range-min",
446 font->hinting_range_min);
447 DUMPVAL("hint-composites",
448 font->hint_composites);
449 DUMPVAL("ignore-restrictions",
450 font->ignore_restrictions);
451 DUMPVAL("increase-x-height",
452 font->increase_x_height);
453 DUMPVAL("adjust-subglyphs",
454 font->adjust_subglyphs);
455 DUMPVAL("symbol",
456 font->symbol);
457 DUMPVAL("windows-compatibility",
458 font->windows_compatibility);
460 s = number_set_show(font->x_height_snapping_exceptions,
461 TA_PROP_INCREASE_X_HEIGHT_MIN, 0x7FFF);
462 DUMPSTR("x-height-snapping-exceptions", s);
463 free(s);
466 fprintf(stderr, "\n");
469 /* now start with processing the data */
471 if (in_file)
473 error = TA_font_file_read(font, in_file);
474 if (error)
475 goto Err;
477 else
479 /* a valid TTF can never be that small */
480 if (in_len < 100)
482 error = TA_Err_Invalid_Font_Type;
483 goto Err1;
485 font->in_buf = (FT_Byte*)in_buf;
486 font->in_len = in_len;
489 error = TA_font_init(font);
490 if (error)
491 goto Err;
493 if (font->debug)
495 _ta_debug = 1;
496 _ta_debug_global = 1;
499 /* we do some loops over all subfonts */
500 for (i = 0; i < font->num_sfnts; i++)
502 SFNT* sfnt = &font->sfnts[i];
503 FT_UInt idx;
506 error = FT_New_Memory_Face(font->lib, font->in_buf, font->in_len,
507 i, &sfnt->face);
509 /* assure that the font hasn't been already processed by ttfautohint; */
510 /* another, more thorough check is done in TA_glyph_parse_simple */
511 idx = FT_Get_Name_Index(sfnt->face, (FT_String*)TTFAUTOHINT_GLYPH);
512 if (idx)
514 error = TA_Err_Already_Processed;
515 goto Err;
518 if (error)
519 goto Err;
521 error = TA_sfnt_split_into_SFNT_tables(sfnt, font);
522 if (error)
523 goto Err;
525 /* check permission */
526 if (sfnt->OS2_idx != MISSING)
528 SFNT_Table* OS2_table = &font->tables[sfnt->OS2_idx];
531 /* check lower byte of the `fsType' field */
532 if (OS2_table->buf[OS2_FSTYPE_OFFSET + 1] == 0x02
533 && !font->ignore_restrictions)
535 error = TA_Err_Missing_Legal_Permission;
536 goto Err;
540 if (font->dehint)
542 error = TA_sfnt_split_glyf_table(sfnt, font);
543 if (error)
544 goto Err;
546 else
548 if (font->adjust_subglyphs)
549 error = TA_sfnt_create_glyf_data(sfnt, font);
550 else
551 error = TA_sfnt_split_glyf_table(sfnt, font);
552 if (error)
553 goto Err;
555 /* this call creates a `globals' object... */
556 error = TA_sfnt_handle_coverage(sfnt, font);
557 if (error)
558 goto Err;
560 /* ... so that we now can initialize its properties */
561 TA_sfnt_set_properties(sfnt, font);
565 if (!font->dehint)
567 for (i = 0; i < font->num_sfnts; i++)
569 SFNT* sfnt = &font->sfnts[i];
572 TA_sfnt_adjust_coverage(sfnt, font);
576 #if 0
577 /* this code is here for completeness -- */
578 /* right now, `glyf' tables get hinted only once, */
579 /* and referring subfonts simply reuse it, */
580 /* but this might change in the future */
582 if (!font->dehint)
584 for (i = 0; i < font->num_sfnts; i++)
586 SFNT* sfnt = &font->sfnts[i];
589 TA_sfnt_copy_master_coverage(sfnt, font);
592 #endif
594 /* loop again over subfonts */
595 for (i = 0; i < font->num_sfnts; i++)
597 SFNT* sfnt = &font->sfnts[i];
600 error = ta_loader_init(font);
601 if (error)
602 goto Err;
604 error = TA_sfnt_build_gasp_table(sfnt, font);
605 if (error)
606 goto Err;
607 if (!font->dehint)
609 error = TA_sfnt_build_cvt_table(sfnt, font);
610 if (error)
611 goto Err;
612 error = TA_sfnt_build_fpgm_table(sfnt, font);
613 if (error)
614 goto Err;
615 error = TA_sfnt_build_prep_table(sfnt, font);
616 if (error)
617 goto Err;
619 error = TA_sfnt_build_glyf_table(sfnt, font);
620 if (error)
621 goto Err;
622 error = TA_sfnt_build_loca_table(sfnt, font);
623 if (error)
624 goto Err;
626 if (font->loader)
627 ta_loader_done(font);
630 for (i = 0; i < font->num_sfnts; i++)
632 SFNT* sfnt = &font->sfnts[i];
635 error = TA_sfnt_update_maxp_table(sfnt, font);
636 if (error)
637 goto Err;
639 if (!font->dehint)
641 /* we add one glyph for composites */
642 if (sfnt->max_components
643 && !font->adjust_subglyphs
644 && font->hint_composites)
646 error = TA_sfnt_update_hmtx_table(sfnt, font);
647 if (error)
648 goto Err;
649 error = TA_sfnt_update_post_table(sfnt, font);
650 if (error)
651 goto Err;
652 error = TA_sfnt_update_GPOS_table(sfnt, font);
653 if (error)
654 goto Err;
658 if (font->info)
660 /* add info about ttfautohint to the version string */
661 error = TA_sfnt_update_name_table(sfnt, font);
662 if (error)
663 goto Err;
667 if (font->num_sfnts == 1)
668 error = TA_font_build_TTF(font);
669 else
670 error = TA_font_build_TTC(font);
671 if (error)
672 goto Err;
674 if (out_file)
676 error = TA_font_file_write(font, out_file);
677 if (error)
678 goto Err;
680 else
682 *out_bufp = (char*)font->out_buf;
683 *out_lenp = font->out_len;
686 error = TA_Err_Ok;
688 Err:
689 TA_font_unload(font, in_buf, out_bufp);
691 Err1:
692 error_string = TA_get_error_message(error);
694 if (error_stringp)
695 *error_stringp = (const unsigned char*)error_string;
697 if (err)
698 err(error,
699 error_string,
700 errlinenum,
701 errline,
702 errpos,
703 err_data);
705 return error;
708 /* end of ttfautohint.c */