Update documentation.
[ttfautohint.git] / lib / ttfautohint.c
blobb2caf08bf171d1fd04c1babd68a36a906835f3fe
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_Long fallback_stem_width = 0;
80 FT_Bool gray_strong_stem_width = 0;
81 FT_Bool gdi_cleartype_strong_stem_width = 1;
82 FT_Bool dw_cleartype_strong_stem_width = 0;
84 TA_Progress_Func progress;
85 void* progress_data;
86 TA_Info_Func info;
87 void* info_data;
89 FT_Bool windows_compatibility = 0;
90 FT_Bool ignore_restrictions = 0;
91 FT_Bool pre_hinting = 0;
92 FT_Bool hint_composites = 0;
93 FT_Bool symbol = 0;
95 const char* fallback_script_string = NULL;
96 const char* default_script_string = NULL;
97 TA_Style fallback_style = TA_STYLE_NONE_DFLT;
98 TA_Script default_script = TA_SCRIPT_LATN;
100 FT_Bool dehint = 0;
102 FT_Bool debug = 0;
104 const char* op;
106 #undef SCRIPT
107 #define SCRIPT(s, S, d, h, sc1, sc2, sc3) #s,
109 const char* script_names[] =
112 #include <ttfautohint-scripts.h>
117 if (!options || !*options)
119 error = FT_Err_Invalid_Argument;
120 goto Err1;
123 /* XXX */
124 va_start(ap, options);
126 op = options;
128 for(;;)
130 const char* start;
131 size_t len;
134 start = op;
136 /* search comma */
137 while (*op && *op != ',')
138 op++;
140 /* remove leading whitespace */
141 while (isspace(*start))
142 start++;
144 /* check for empty option */
145 if (start == op)
146 goto End;
148 len = op - start;
150 /* the `COMPARE' macro uses `len' and `start' */
152 /* handle options -- don't forget to update parameter dump below! */
153 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("dw-cleartype-strong-stem-width"))
160 dw_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
161 else if (COMPARE("error-string"))
162 error_stringp = va_arg(ap, const unsigned char**);
163 else if (COMPARE("fallback-script"))
164 fallback_script_string = va_arg(ap, const char*);
165 else if (COMPARE("fallback-stem-width"))
166 fallback_stem_width = (FT_Long)va_arg(ap, FT_UInt);
167 else if (COMPARE("gdi-cleartype-strong-stem-width"))
168 gdi_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
169 else if (COMPARE("gray-strong-stem-width"))
170 gray_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
171 else if (COMPARE("hinting-limit"))
172 hinting_limit = (FT_Long)va_arg(ap, FT_UInt);
173 else if (COMPARE("hinting-range-max"))
174 hinting_range_max = (FT_Long)va_arg(ap, FT_UInt);
175 else if (COMPARE("hinting-range-min"))
176 hinting_range_min = (FT_Long)va_arg(ap, FT_UInt);
177 else if (COMPARE("hint-composites"))
178 hint_composites = (FT_Bool)va_arg(ap, FT_Int);
179 else if (COMPARE("ignore-restrictions"))
180 ignore_restrictions = (FT_Bool)va_arg(ap, FT_Int);
181 else if (COMPARE("in-buffer"))
183 in_file = NULL;
184 in_buf = va_arg(ap, const char*);
186 else if (COMPARE("in-buffer-len"))
188 in_file = NULL;
189 in_len = va_arg(ap, size_t);
191 else if (COMPARE("in-file"))
193 in_file = va_arg(ap, FILE*);
194 in_buf = NULL;
195 in_len = 0;
197 else if (COMPARE("increase-x-height"))
198 increase_x_height = (FT_Long)va_arg(ap, FT_UInt);
199 else if (COMPARE("info-callback"))
200 info = va_arg(ap, TA_Info_Func);
201 else if (COMPARE("info-callback-data"))
202 info_data = va_arg(ap, void*);
203 else if (COMPARE("out-buffer"))
205 out_file = NULL;
206 out_bufp = va_arg(ap, char**);
208 else if (COMPARE("out-buffer-len"))
210 out_file = NULL;
211 out_lenp = va_arg(ap, size_t*);
213 else if (COMPARE("out-file"))
215 out_file = va_arg(ap, FILE*);
216 out_bufp = NULL;
217 out_lenp = NULL;
219 else if (COMPARE("pre-hinting"))
220 pre_hinting = (FT_Bool)va_arg(ap, FT_Int);
221 else if (COMPARE("progress-callback"))
222 progress = va_arg(ap, TA_Progress_Func);
223 else if (COMPARE("progress-callback-data"))
224 progress_data = va_arg(ap, void*);
225 else if (COMPARE("symbol"))
226 symbol = (FT_Bool)va_arg(ap, FT_Int);
227 else if (COMPARE("windows-compatibility"))
228 windows_compatibility = (FT_Bool)va_arg(ap, FT_Int);
229 else if (COMPARE("x-height-snapping-exceptions"))
230 x_height_snapping_exceptions_string = va_arg(ap, const char*);
231 else
233 error = TA_Err_Unknown_Argument;
234 goto Err1;
237 End:
238 if (!*op)
239 break;
240 op++;
243 va_end(ap);
245 /* check options */
247 if (!(in_file
248 || (in_buf && in_len)))
250 error = FT_Err_Invalid_Argument;
251 goto Err1;
254 if (!(out_file
255 || (out_bufp && out_lenp)))
257 error = FT_Err_Invalid_Argument;
258 goto Err1;
261 font = (FONT*)calloc(1, sizeof (FONT));
262 if (!font)
264 error = FT_Err_Out_Of_Memory;
265 goto Err1;
268 if (dehint)
269 goto No_check;
271 if (hinting_range_min >= 0 && hinting_range_min < 2)
273 error = FT_Err_Invalid_Argument;
274 goto Err1;
276 if (hinting_range_min < 0)
277 hinting_range_min = TA_HINTING_RANGE_MIN;
279 if (hinting_range_max >= 0 && hinting_range_max < hinting_range_min)
281 error = FT_Err_Invalid_Argument;
282 goto Err1;
284 if (hinting_range_max < 0)
285 hinting_range_max = TA_HINTING_RANGE_MAX;
287 /* value 0 is valid */
288 if (hinting_limit > 0 && hinting_limit < hinting_range_max)
290 error = FT_Err_Invalid_Argument;
291 goto Err1;
293 if (hinting_limit < 0)
294 hinting_limit = TA_HINTING_LIMIT;
296 if (increase_x_height > 0
297 && increase_x_height < TA_PROP_INCREASE_X_HEIGHT_MIN)
299 error = FT_Err_Invalid_Argument;
300 goto Err1;
302 if (increase_x_height < 0)
303 increase_x_height = TA_INCREASE_X_HEIGHT;
305 if (fallback_script_string)
307 int i;
310 for (i = 0; i < TA_STYLE_MAX; i++)
312 TA_StyleClass style_class = ta_style_classes[i];
315 if (style_class->coverage == TA_COVERAGE_DEFAULT
316 && !strcmp(script_names[style_class->script],
317 fallback_script_string))
318 break;
320 if (i == TA_STYLE_MAX)
322 error = FT_Err_Invalid_Argument;
323 goto Err1;
326 fallback_style = (TA_Style)i;
329 if (default_script_string)
331 int i;
334 for (i = 0; i < TA_SCRIPT_MAX; i++)
336 if (!strcmp(script_names[i], default_script_string))
337 break;
339 if (i == TA_SCRIPT_MAX)
341 error = FT_Err_Invalid_Argument;
342 goto Err1;
345 default_script = (TA_Script)i;
348 if (x_height_snapping_exceptions_string)
350 const char* s = number_set_parse(x_height_snapping_exceptions_string,
351 &x_height_snapping_exceptions,
352 TA_PROP_INCREASE_X_HEIGHT_MIN,
353 0x7FFF);
354 if (*s)
356 error = FT_Err_Invalid_Argument;
357 goto Err1;
361 font->hinting_range_min = (FT_UInt)hinting_range_min;
362 font->hinting_range_max = (FT_UInt)hinting_range_max;
363 font->hinting_limit = (FT_UInt)hinting_limit;
364 font->increase_x_height = increase_x_height;
365 font->x_height_snapping_exceptions = x_height_snapping_exceptions;
366 font->fallback_stem_width = (FT_UInt)fallback_stem_width;
368 font->gray_strong_stem_width = gray_strong_stem_width;
369 font->gdi_cleartype_strong_stem_width = gdi_cleartype_strong_stem_width;
370 font->dw_cleartype_strong_stem_width = dw_cleartype_strong_stem_width;
372 font->windows_compatibility = windows_compatibility;
373 font->ignore_restrictions = ignore_restrictions;
374 font->pre_hinting = pre_hinting;
375 font->hint_composites = hint_composites;
376 font->fallback_style = fallback_style;
377 font->default_script = default_script;
378 font->symbol = symbol;
380 No_check:
381 font->progress = progress;
382 font->progress_data = progress_data;
383 font->info = info;
384 font->info_data = info_data;
386 font->debug = debug;
387 font->dehint = dehint;
389 font->gasp_idx = MISSING;
391 /* dump parameters */
392 if (debug)
394 fprintf(stderr, "TTF_autohint parameters\n"
395 "=======================\n"
396 "\n");
398 if (dehint)
399 DUMPVAL("dehint",
400 font->dehint);
401 else
403 char *s;
406 DUMPSTR("default-script",
407 script_names[font->default_script]);
408 DUMPVAL("dw-cleartype-strong-stem-width",
409 font->dw_cleartype_strong_stem_width);
410 DUMPSTR("fallback-script",
411 script_names[ta_style_classes[font->fallback_style]->script]);
412 DUMPVAL("fallback-stem-width",
413 font->fallback_stem_width);
414 DUMPVAL("gdi-cleartype-strong-stem-width",
415 font->gdi_cleartype_strong_stem_width);
416 DUMPVAL("gray-strong-stem-width",
417 font->gray_strong_stem_width);
418 DUMPVAL("hinting-limit",
419 font->hinting_limit);
420 DUMPVAL("hinting-range-max",
421 font->hinting_range_max);
422 DUMPVAL("hinting-range-min",
423 font->hinting_range_min);
424 DUMPVAL("hint-composites",
425 font->hint_composites);
426 DUMPVAL("ignore-restrictions",
427 font->ignore_restrictions);
428 DUMPVAL("increase-x-height",
429 font->increase_x_height);
430 DUMPVAL("pre-hinting",
431 font->pre_hinting);
432 DUMPVAL("symbol",
433 font->symbol);
434 DUMPVAL("windows-compatibility",
435 font->windows_compatibility);
437 s = number_set_show(font->x_height_snapping_exceptions,
438 TA_PROP_INCREASE_X_HEIGHT_MIN, 0x7FFF);
439 DUMPSTR("x-height-snapping-exceptions", s);
440 free(s);
443 fprintf(stderr, "\n");
446 /* now start with processing the data */
448 if (in_file)
450 error = TA_font_file_read(font, in_file);
451 if (error)
452 goto Err;
454 else
456 /* a valid TTF can never be that small */
457 if (in_len < 100)
459 error = TA_Err_Invalid_Font_Type;
460 goto Err1;
462 font->in_buf = (FT_Byte*)in_buf;
463 font->in_len = in_len;
466 error = TA_font_init(font);
467 if (error)
468 goto Err;
470 if (font->debug)
472 _ta_debug = 1;
473 _ta_debug_global = 1;
476 /* we do some loops over all subfonts */
477 for (i = 0; i < font->num_sfnts; i++)
479 SFNT* sfnt = &font->sfnts[i];
480 FT_UInt idx;
483 error = FT_New_Memory_Face(font->lib, font->in_buf, font->in_len,
484 i, &sfnt->face);
486 /* assure that the font hasn't been already processed by ttfautohint; */
487 /* another, more thorough check is done in TA_glyph_parse_simple */
488 idx = FT_Get_Name_Index(sfnt->face, (FT_String*)TTFAUTOHINT_GLYPH);
489 if (idx)
491 error = TA_Err_Already_Processed;
492 goto Err;
495 if (error)
496 goto Err;
498 error = TA_sfnt_split_into_SFNT_tables(sfnt, font);
499 if (error)
500 goto Err;
502 /* check permission */
503 if (sfnt->OS2_idx != MISSING)
505 SFNT_Table* OS2_table = &font->tables[sfnt->OS2_idx];
508 /* check lower byte of the `fsType' field */
509 if (OS2_table->buf[OS2_FSTYPE_OFFSET + 1] == 0x02
510 && !font->ignore_restrictions)
512 error = TA_Err_Missing_Legal_Permission;
513 goto Err;
517 if (font->dehint)
519 error = TA_sfnt_split_glyf_table(sfnt, font);
520 if (error)
521 goto Err;
523 else
525 if (font->pre_hinting)
526 error = TA_sfnt_create_glyf_data(sfnt, font);
527 else
528 error = TA_sfnt_split_glyf_table(sfnt, font);
529 if (error)
530 goto Err;
532 /* this call creates a `globals' object... */
533 error = TA_sfnt_handle_coverage(sfnt, font);
534 if (error)
535 goto Err;
537 /* ... so that we now can initialize its properties */
538 TA_sfnt_set_properties(sfnt, font);
542 if (!font->dehint)
544 for (i = 0; i < font->num_sfnts; i++)
546 SFNT* sfnt = &font->sfnts[i];
549 if (TA_sfnt_adjust_master_coverage(sfnt, font))
550 break;
554 #if 0
555 /* this code is here for completeness -- */
556 /* right now, `glyf' tables get hinted only once, */
557 /* and referring subfonts simply reuse it, */
558 /* but this might change in the future */
560 if (!font->dehint)
562 for (i = 0; i < font->num_sfnts; i++)
564 SFNT* sfnt = &font->sfnts[i];
567 TA_sfnt_copy_master_coverage(sfnt, font);
570 #endif
572 /* loop again over subfonts */
573 for (i = 0; i < font->num_sfnts; i++)
575 SFNT* sfnt = &font->sfnts[i];
578 error = ta_loader_init(font);
579 if (error)
580 goto Err;
582 error = TA_sfnt_build_gasp_table(sfnt, font);
583 if (error)
584 goto Err;
585 if (!font->dehint)
587 error = TA_sfnt_build_cvt_table(sfnt, font);
588 if (error)
589 goto Err;
590 error = TA_sfnt_build_fpgm_table(sfnt, font);
591 if (error)
592 goto Err;
593 error = TA_sfnt_build_prep_table(sfnt, font);
594 if (error)
595 goto Err;
597 error = TA_sfnt_build_glyf_table(sfnt, font);
598 if (error)
599 goto Err;
600 error = TA_sfnt_build_loca_table(sfnt, font);
601 if (error)
602 goto Err;
604 if (font->loader)
605 ta_loader_done(font);
608 for (i = 0; i < font->num_sfnts; i++)
610 SFNT* sfnt = &font->sfnts[i];
613 error = TA_sfnt_update_maxp_table(sfnt, font);
614 if (error)
615 goto Err;
617 if (!font->dehint)
619 /* we add one glyph for composites */
620 if (sfnt->max_components
621 && !font->pre_hinting
622 && font->hint_composites)
624 error = TA_sfnt_update_hmtx_table(sfnt, font);
625 if (error)
626 goto Err;
627 error = TA_sfnt_update_post_table(sfnt, font);
628 if (error)
629 goto Err;
630 error = TA_sfnt_update_GPOS_table(sfnt, font);
631 if (error)
632 goto Err;
636 if (font->info)
638 /* add info about ttfautohint to the version string */
639 error = TA_sfnt_update_name_table(sfnt, font);
640 if (error)
641 goto Err;
645 if (font->num_sfnts == 1)
646 error = TA_font_build_TTF(font);
647 else
648 error = TA_font_build_TTC(font);
649 if (error)
650 goto Err;
652 if (out_file)
654 error = TA_font_file_write(font, out_file);
655 if (error)
656 goto Err;
658 else
660 *out_bufp = (char*)font->out_buf;
661 *out_lenp = font->out_len;
664 error = TA_Err_Ok;
666 Err:
667 TA_font_unload(font, in_buf, out_bufp);
669 Err1:
670 if (error_stringp)
671 *error_stringp = (const unsigned char*)TA_get_error_message(error);
673 return error;
676 /* end of ttfautohint.c */