Simplify call of `TA_font_dump_parameters'.
[ttfautohint.git] / lib / ttfautohint.c
blobd0fa7504deae4584e614b33aa8ca73c2cea41960
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* deltas_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* deltas_buf = NULL;
68 size_t deltas_len = 0;
70 const unsigned char** error_stringp = NULL;
72 Deltas* deltas = NULL;
74 FT_Long hinting_range_min = -1;
75 FT_Long hinting_range_max = -1;
76 FT_Long hinting_limit = -1;
77 FT_Long increase_x_height = -1;
79 const char* x_height_snapping_exceptions_string = NULL;
80 number_range* x_height_snapping_exceptions = NULL;
82 FT_Long fallback_stem_width = 0;
84 FT_Bool gray_strong_stem_width = 0;
85 FT_Bool gdi_cleartype_strong_stem_width = 1;
86 FT_Bool dw_cleartype_strong_stem_width = 0;
88 TA_Progress_Func progress = NULL;
89 void* progress_data = NULL;
90 TA_Error_Func err = NULL;
91 void* err_data = NULL;
92 TA_Info_Func info = 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;
101 const char* fallback_script_string = NULL;
102 const char* default_script_string = NULL;
103 TA_Style fallback_style = TA_STYLE_NONE_DFLT;
104 TA_Script default_script = TA_SCRIPT_LATN;
106 FT_Bool dehint = 0;
107 FT_Bool debug = 0;
109 const char* op;
111 if (!options || !*options)
113 error = FT_Err_Invalid_Argument;
114 goto Err1;
117 /* XXX */
118 va_start(ap, options);
120 op = options;
122 for(;;)
124 const char* start;
125 size_t len;
128 start = op;
130 /* search comma */
131 while (*op && *op != ',')
132 op++;
134 /* remove leading whitespace */
135 while (isspace(*start))
136 start++;
138 /* check for empty option */
139 if (start == op)
140 goto End;
142 len = op - start;
144 /* the `COMPARE' macro uses `len' and `start' */
146 /* handle options -- don't forget to update parameter dump below! */
147 if (COMPARE("adjust-subglyphs"))
148 adjust_subglyphs = (FT_Bool)va_arg(ap, FT_Int);
149 else if (COMPARE("debug"))
150 debug = (FT_Bool)va_arg(ap, FT_Int);
151 else if (COMPARE("default-script"))
152 default_script_string = va_arg(ap, const char*);
153 else if (COMPARE("dehint"))
154 dehint = (FT_Bool)va_arg(ap, FT_Int);
155 else if (COMPARE("deltas-buffer"))
157 deltas_file = NULL;
158 deltas_buf = va_arg(ap, const char*);
160 else if (COMPARE("deltas-buffer-len"))
162 deltas_file = NULL;
163 deltas_len = va_arg(ap, size_t);
165 else if (COMPARE("deltas-file"))
167 deltas_file = va_arg(ap, FILE*);
168 deltas_buf = NULL;
169 deltas_len = 0;
171 else if (COMPARE("dw-cleartype-strong-stem-width"))
172 dw_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
173 else if (COMPARE("error-callback"))
174 err = va_arg(ap, TA_Error_Func);
175 else if (COMPARE("error-callback-data"))
176 err_data = va_arg(ap, void*);
177 else if (COMPARE("error-string"))
178 error_stringp = va_arg(ap, const unsigned char**);
179 else if (COMPARE("fallback-script"))
180 fallback_script_string = va_arg(ap, const char*);
181 else if (COMPARE("fallback-stem-width"))
182 fallback_stem_width = (FT_Long)va_arg(ap, FT_UInt);
183 else if (COMPARE("gdi-cleartype-strong-stem-width"))
184 gdi_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
185 else if (COMPARE("gray-strong-stem-width"))
186 gray_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
187 else if (COMPARE("hinting-limit"))
188 hinting_limit = (FT_Long)va_arg(ap, FT_UInt);
189 else if (COMPARE("hinting-range-max"))
190 hinting_range_max = (FT_Long)va_arg(ap, FT_UInt);
191 else if (COMPARE("hinting-range-min"))
192 hinting_range_min = (FT_Long)va_arg(ap, FT_UInt);
193 else if (COMPARE("hint-composites"))
194 hint_composites = (FT_Bool)va_arg(ap, FT_Int);
195 else if (COMPARE("ignore-restrictions"))
196 ignore_restrictions = (FT_Bool)va_arg(ap, FT_Int);
197 else if (COMPARE("in-buffer"))
199 in_file = NULL;
200 in_buf = va_arg(ap, const char*);
202 else if (COMPARE("in-buffer-len"))
204 in_file = NULL;
205 in_len = va_arg(ap, size_t);
207 else if (COMPARE("in-file"))
209 in_file = va_arg(ap, FILE*);
210 in_buf = NULL;
211 in_len = 0;
213 else if (COMPARE("increase-x-height"))
214 increase_x_height = (FT_Long)va_arg(ap, FT_UInt);
215 else if (COMPARE("info-callback"))
216 info = va_arg(ap, TA_Info_Func);
217 else if (COMPARE("info-callback-data"))
218 info_data = va_arg(ap, void*);
219 else if (COMPARE("out-buffer"))
221 out_file = NULL;
222 out_bufp = va_arg(ap, char**);
224 else if (COMPARE("out-buffer-len"))
226 out_file = NULL;
227 out_lenp = va_arg(ap, size_t*);
229 else if (COMPARE("out-file"))
231 out_file = va_arg(ap, FILE*);
232 out_bufp = NULL;
233 out_lenp = NULL;
235 else if (COMPARE("pre-hinting"))
236 adjust_subglyphs = (FT_Bool)va_arg(ap, FT_Int);
237 else if (COMPARE("progress-callback"))
238 progress = va_arg(ap, TA_Progress_Func);
239 else if (COMPARE("progress-callback-data"))
240 progress_data = va_arg(ap, void*);
241 else if (COMPARE("symbol"))
242 symbol = (FT_Bool)va_arg(ap, FT_Int);
243 else if (COMPARE("windows-compatibility"))
244 windows_compatibility = (FT_Bool)va_arg(ap, FT_Int);
245 else if (COMPARE("x-height-snapping-exceptions"))
246 x_height_snapping_exceptions_string = va_arg(ap, const char*);
247 else
249 error = TA_Err_Unknown_Argument;
250 goto Err1;
253 End:
254 if (!*op)
255 break;
256 op++;
259 va_end(ap);
261 /* check options */
263 if (!(in_file
264 || (in_buf && in_len)))
266 error = FT_Err_Invalid_Argument;
267 goto Err1;
270 if (!(out_file
271 || (out_bufp && out_lenp)))
273 error = FT_Err_Invalid_Argument;
274 goto Err1;
277 font = (FONT*)calloc(1, sizeof (FONT));
278 if (!font)
280 error = FT_Err_Out_Of_Memory;
281 goto Err1;
284 if (dehint)
285 goto No_check;
287 if (hinting_range_min >= 0 && hinting_range_min < 2)
289 error = FT_Err_Invalid_Argument;
290 goto Err1;
292 if (hinting_range_min < 0)
293 hinting_range_min = TA_HINTING_RANGE_MIN;
295 if (hinting_range_max >= 0 && hinting_range_max < hinting_range_min)
297 error = FT_Err_Invalid_Argument;
298 goto Err1;
300 if (hinting_range_max < 0)
301 hinting_range_max = TA_HINTING_RANGE_MAX;
303 /* value 0 is valid */
304 if (hinting_limit > 0 && hinting_limit < hinting_range_max)
306 error = FT_Err_Invalid_Argument;
307 goto Err1;
309 if (hinting_limit < 0)
310 hinting_limit = TA_HINTING_LIMIT;
312 if (increase_x_height > 0
313 && increase_x_height < TA_PROP_INCREASE_X_HEIGHT_MIN)
315 error = FT_Err_Invalid_Argument;
316 goto Err1;
318 if (increase_x_height < 0)
319 increase_x_height = TA_INCREASE_X_HEIGHT;
321 if (fallback_script_string)
323 int i;
326 for (i = 0; i < TA_STYLE_MAX; i++)
328 TA_StyleClass style_class = ta_style_classes[i];
331 if (style_class->coverage == TA_COVERAGE_DEFAULT
332 && !strcmp(script_names[style_class->script],
333 fallback_script_string))
334 break;
336 if (i == TA_STYLE_MAX)
338 error = FT_Err_Invalid_Argument;
339 goto Err1;
342 fallback_style = (TA_Style)i;
345 if (default_script_string)
347 int i;
350 for (i = 0; i < TA_SCRIPT_MAX; i++)
352 if (!strcmp(script_names[i], default_script_string))
353 break;
355 if (i == TA_SCRIPT_MAX)
357 error = FT_Err_Invalid_Argument;
358 goto Err1;
361 default_script = (TA_Script)i;
364 if (x_height_snapping_exceptions_string)
366 const char* s = number_set_parse(x_height_snapping_exceptions_string,
367 &x_height_snapping_exceptions,
368 TA_PROP_INCREASE_X_HEIGHT_MIN,
369 0x7FFF);
370 if (*s)
372 /* we map numberset.h's error codes to values starting with 0x100 */
373 error = 0x100 - (FT_Error)x_height_snapping_exceptions;
374 errlinenum = 0;
375 errline = (char*)x_height_snapping_exceptions_string;
376 errpos = (char*)s;
378 goto Err1;
382 font->hinting_range_min = (FT_UInt)hinting_range_min;
383 font->hinting_range_max = (FT_UInt)hinting_range_max;
384 font->hinting_limit = (FT_UInt)hinting_limit;
385 font->increase_x_height = increase_x_height;
386 font->x_height_snapping_exceptions = x_height_snapping_exceptions;
387 font->fallback_stem_width = (FT_UInt)fallback_stem_width;
389 font->gray_strong_stem_width = gray_strong_stem_width;
390 font->gdi_cleartype_strong_stem_width = gdi_cleartype_strong_stem_width;
391 font->dw_cleartype_strong_stem_width = dw_cleartype_strong_stem_width;
393 font->windows_compatibility = windows_compatibility;
394 font->ignore_restrictions = ignore_restrictions;
395 font->adjust_subglyphs = adjust_subglyphs;
396 font->hint_composites = hint_composites;
397 font->fallback_style = fallback_style;
398 font->default_script = default_script;
399 font->symbol = symbol;
401 No_check:
402 font->progress = progress;
403 font->progress_data = progress_data;
404 font->info = info;
405 font->info_data = info_data;
407 font->debug = debug;
408 font->dehint = dehint;
410 font->gasp_idx = MISSING;
412 /* start with processing the data */
414 if (in_file)
416 error = TA_font_file_read(font, in_file);
417 if (error)
418 goto Err;
420 else
422 /* a valid TTF can never be that small */
423 if (in_len < 100)
425 error = TA_Err_Invalid_Font_Type;
426 goto Err1;
428 font->in_buf = (FT_Byte*)in_buf;
429 font->in_len = in_len;
432 if (deltas_file)
434 error = TA_deltas_file_read(font, deltas_file);
435 if (error)
436 goto Err;
438 else if (deltas_buf)
440 font->deltas_buf = (char*)deltas_buf;
441 font->deltas_len = deltas_len;
444 error = TA_font_init(font);
445 if (error)
446 goto Err;
448 if (font->debug)
450 _ta_debug = 1;
451 _ta_debug_global = 1;
454 /* we do some loops over all subfonts -- */
455 /* to process options early, just start with loading all of them */
456 for (i = 0; i < font->num_sfnts; i++)
458 SFNT* sfnt = &font->sfnts[i];
459 FT_UInt idx;
462 error = FT_New_Memory_Face(font->lib, font->in_buf, font->in_len,
463 i, &sfnt->face);
465 /* assure that the font hasn't been already processed by ttfautohint; */
466 /* another, more thorough check is done in TA_glyph_parse_simple */
467 idx = FT_Get_Name_Index(sfnt->face, (FT_String*)TTFAUTOHINT_GLYPH);
468 if (idx)
470 error = TA_Err_Already_Processed;
471 goto Err;
474 if (error)
475 goto Err;
478 /* process delta exceptions data */
479 error = TA_deltas_parse_buffer(font,
480 &deltas,
481 &error_string,
482 &errlinenum, &errline, &errpos);
483 if (error)
485 free_errline = 1;
486 free_error_string = 1;
487 goto Err;
490 /* now we are able to dump all parameters */
491 if (debug)
493 char* s;
496 s = TA_font_dump_parameters(font, deltas, 1);
497 if (!s)
499 error = FT_Err_Out_Of_Memory;
500 goto Err;
503 fprintf(stderr, "%s", s);
504 free(s);
507 error = TA_deltas_build_tree(font, deltas);
508 if (error)
509 goto Err;
511 /* loop again over subfonts and continue processing */
512 for (i = 0; i < font->num_sfnts; i++)
514 SFNT* sfnt = &font->sfnts[i];
517 error = TA_sfnt_split_into_SFNT_tables(sfnt, font);
518 if (error)
519 goto Err;
521 /* check permission */
522 if (sfnt->OS2_idx != MISSING)
524 SFNT_Table* OS2_table = &font->tables[sfnt->OS2_idx];
527 /* check lower byte of the `fsType' field */
528 if (OS2_table->buf[OS2_FSTYPE_OFFSET + 1] == 0x02
529 && !font->ignore_restrictions)
531 error = TA_Err_Missing_Legal_Permission;
532 goto Err;
536 if (font->dehint)
538 error = TA_sfnt_split_glyf_table(sfnt, font);
539 if (error)
540 goto Err;
542 else
544 if (font->adjust_subglyphs)
545 error = TA_sfnt_create_glyf_data(sfnt, font);
546 else
547 error = TA_sfnt_split_glyf_table(sfnt, font);
548 if (error)
549 goto Err;
551 /* this call creates a `globals' object... */
552 error = TA_sfnt_handle_coverage(sfnt, font);
553 if (error)
554 goto Err;
556 /* ... so that we now can initialize its properties */
557 TA_sfnt_set_properties(sfnt, font);
561 if (!font->dehint)
563 for (i = 0; i < font->num_sfnts; i++)
565 SFNT* sfnt = &font->sfnts[i];
568 TA_sfnt_adjust_coverage(sfnt, font);
572 #if 0
573 /* this code is here for completeness -- */
574 /* right now, `glyf' tables get hinted only once, */
575 /* and referring subfonts simply reuse it, */
576 /* but this might change in the future */
578 if (!font->dehint)
580 for (i = 0; i < font->num_sfnts; i++)
582 SFNT* sfnt = &font->sfnts[i];
585 TA_sfnt_copy_master_coverage(sfnt, font);
588 #endif
590 /* loop again over subfonts */
591 for (i = 0; i < font->num_sfnts; i++)
593 SFNT* sfnt = &font->sfnts[i];
596 error = ta_loader_init(font);
597 if (error)
598 goto Err;
600 error = TA_sfnt_build_gasp_table(sfnt, font);
601 if (error)
602 goto Err;
603 if (!font->dehint)
605 error = TA_sfnt_build_cvt_table(sfnt, font);
606 if (error)
607 goto Err;
608 error = TA_sfnt_build_fpgm_table(sfnt, font);
609 if (error)
610 goto Err;
611 error = TA_sfnt_build_prep_table(sfnt, font);
612 if (error)
613 goto Err;
615 error = TA_sfnt_build_glyf_table(sfnt, font);
616 if (error)
617 goto Err;
618 error = TA_sfnt_build_loca_table(sfnt, font);
619 if (error)
620 goto Err;
622 if (font->loader)
623 ta_loader_done(font);
626 for (i = 0; i < font->num_sfnts; i++)
628 SFNT* sfnt = &font->sfnts[i];
631 error = TA_sfnt_update_maxp_table(sfnt, font);
632 if (error)
633 goto Err;
635 if (!font->dehint)
637 /* we add one glyph for composites */
638 if (sfnt->max_components
639 && !font->adjust_subglyphs
640 && font->hint_composites)
642 error = TA_sfnt_update_hmtx_table(sfnt, font);
643 if (error)
644 goto Err;
645 error = TA_sfnt_update_post_table(sfnt, font);
646 if (error)
647 goto Err;
648 error = TA_sfnt_update_GPOS_table(sfnt, font);
649 if (error)
650 goto Err;
654 if (font->info)
656 /* add info about ttfautohint to the version string */
657 error = TA_sfnt_update_name_table(sfnt, font);
658 if (error)
659 goto Err;
663 if (font->num_sfnts == 1)
664 error = TA_font_build_TTF(font);
665 else
666 error = TA_font_build_TTC(font);
667 if (error)
668 goto Err;
670 if (out_file)
672 error = TA_font_file_write(font, out_file);
673 if (error)
674 goto Err;
676 else
678 *out_bufp = (char*)font->out_buf;
679 *out_lenp = font->out_len;
682 error = TA_Err_Ok;
684 Err:
685 TA_deltas_free(deltas);
686 TA_deltas_free_tree(font);
687 TA_font_unload(font, in_buf, out_bufp, deltas_buf);
689 Err1:
690 if (!error_string)
691 error_string = (char*)TA_get_error_message(error);
693 /* this must be a static value */
694 if (error_stringp)
695 *error_stringp = (const unsigned char*)TA_get_error_message(error);
697 if (err)
698 err(error,
699 error_string,
700 errlinenum,
701 errline,
702 errpos,
703 err_data);
705 if (free_errline)
706 free(errline);
707 if (free_error_string)
708 free(error_string);
710 return error;
713 /* end of ttfautohint.c */