Adjust master glyph coverage table only once.
[ttfautohint.git] / lib / ttfautohint.c
blob29fec0a84593d65d66a53a53f9b63d87a1c1d9fd
1 /* ttfautohint.c */
3 /*
4 * Copyright (C) 2011-2013 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_Bool gray_strong_stem_width = 0;
79 FT_Bool gdi_cleartype_strong_stem_width = 1;
80 FT_Bool dw_cleartype_strong_stem_width = 0;
82 TA_Progress_Func progress;
83 void* progress_data;
84 TA_Info_Func info;
85 void* info_data;
87 FT_Bool windows_compatibility = 0;
88 FT_Bool ignore_restrictions = 0;
89 FT_Bool pre_hinting = 0;
90 FT_Bool hint_composites = 0;
91 FT_Bool symbol = 0;
93 const char* fallback_script_string = NULL;
94 TA_Script fallback_script = TA_SCRIPT_DFLT;
96 FT_Bool dehint = 0;
98 FT_Bool debug = 0;
100 const char* op;
102 #undef SCRIPT
103 #define SCRIPT(s, S, d) #s,
105 const char* script_names[] =
108 #include <ttfautohint-scripts.h>
113 if (!options || !*options)
115 error = FT_Err_Invalid_Argument;
116 goto Err1;
119 /* XXX */
120 va_start(ap, options);
122 op = options;
124 for(;;)
126 const char* start;
127 size_t len;
130 start = op;
132 /* search comma */
133 while (*op && *op != ',')
134 op++;
136 /* remove leading whitespace */
137 while (isspace(*start))
138 start++;
140 /* check for empty option */
141 if (start == op)
142 goto End;
144 len = op - start;
146 /* the `COMPARE' macro uses `len' and `start' */
148 /* handle options -- don't forget to update parameter dump below! */
149 if (COMPARE("debug"))
150 debug = (FT_Bool)va_arg(ap, FT_Int);
151 else if (COMPARE("dehint"))
152 dehint = (FT_Bool)va_arg(ap, FT_Int);
153 else if (COMPARE("dw-cleartype-strong-stem-width"))
154 dw_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
155 else if (COMPARE("error-string"))
156 error_stringp = va_arg(ap, const unsigned char**);
157 else if (COMPARE("fallback-script"))
158 fallback_script_string = va_arg(ap, const char*);
159 else if (COMPARE("gdi-cleartype-strong-stem-width"))
160 gdi_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
161 else if (COMPARE("gray-strong-stem-width"))
162 gray_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
163 else if (COMPARE("hinting-limit"))
164 hinting_limit = (FT_Long)va_arg(ap, FT_UInt);
165 else if (COMPARE("hinting-range-max"))
166 hinting_range_max = (FT_Long)va_arg(ap, FT_UInt);
167 else if (COMPARE("hinting-range-min"))
168 hinting_range_min = (FT_Long)va_arg(ap, FT_UInt);
169 else if (COMPARE("hint-composites"))
170 hint_composites = (FT_Bool)va_arg(ap, FT_Int);
171 else if (COMPARE("ignore-restrictions"))
172 ignore_restrictions = (FT_Bool)va_arg(ap, FT_Int);
173 else if (COMPARE("in-buffer"))
175 in_file = NULL;
176 in_buf = va_arg(ap, const char*);
178 else if (COMPARE("in-buffer-len"))
180 in_file = NULL;
181 in_len = va_arg(ap, size_t);
183 else if (COMPARE("in-file"))
185 in_file = va_arg(ap, FILE*);
186 in_buf = NULL;
187 in_len = 0;
189 else if (COMPARE("increase-x-height"))
190 increase_x_height = (FT_Long)va_arg(ap, FT_UInt);
191 else if (COMPARE("info-callback"))
192 info = va_arg(ap, TA_Info_Func);
193 else if (COMPARE("info-callback-data"))
194 info_data = va_arg(ap, void*);
195 else if (COMPARE("out-buffer"))
197 out_file = NULL;
198 out_bufp = va_arg(ap, char**);
200 else if (COMPARE("out-buffer-len"))
202 out_file = NULL;
203 out_lenp = va_arg(ap, size_t*);
205 else if (COMPARE("out-file"))
207 out_file = va_arg(ap, FILE*);
208 out_bufp = NULL;
209 out_lenp = NULL;
211 else if (COMPARE("pre-hinting"))
212 pre_hinting = (FT_Bool)va_arg(ap, FT_Int);
213 else if (COMPARE("progress-callback"))
214 progress = va_arg(ap, TA_Progress_Func);
215 else if (COMPARE("progress-callback-data"))
216 progress_data = va_arg(ap, void*);
217 else if (COMPARE("symbol"))
218 symbol = (FT_Bool)va_arg(ap, FT_Int);
219 else if (COMPARE("windows-compatibility"))
220 windows_compatibility = (FT_Bool)va_arg(ap, FT_Int);
221 else if (COMPARE("x-height-snapping-exceptions"))
222 x_height_snapping_exceptions_string = va_arg(ap, const char*);
223 else
225 error = TA_Err_Unknown_Argument;
226 goto Err1;
229 End:
230 if (!*op)
231 break;
232 op++;
235 va_end(ap);
237 /* check options */
239 if (!(in_file
240 || (in_buf && in_len)))
242 error = FT_Err_Invalid_Argument;
243 goto Err1;
246 if (!(out_file
247 || (out_bufp && out_lenp)))
249 error = FT_Err_Invalid_Argument;
250 goto Err1;
253 font = (FONT*)calloc(1, sizeof (FONT));
254 if (!font)
256 error = FT_Err_Out_Of_Memory;
257 goto Err1;
260 if (dehint)
261 goto No_check;
263 if (hinting_range_min >= 0 && hinting_range_min < 2)
265 error = FT_Err_Invalid_Argument;
266 goto Err1;
268 if (hinting_range_min < 0)
269 hinting_range_min = TA_HINTING_RANGE_MIN;
271 if (hinting_range_max >= 0 && hinting_range_max < hinting_range_min)
273 error = FT_Err_Invalid_Argument;
274 goto Err1;
276 if (hinting_range_max < 0)
277 hinting_range_max = TA_HINTING_RANGE_MAX;
279 /* value 0 is valid */
280 if (hinting_limit > 0 && hinting_limit < hinting_range_max)
282 error = FT_Err_Invalid_Argument;
283 goto Err1;
285 if (hinting_limit < 0)
286 hinting_limit = TA_HINTING_LIMIT;
288 if (increase_x_height > 0
289 && increase_x_height < TA_PROP_INCREASE_X_HEIGHT_MIN)
291 error = FT_Err_Invalid_Argument;
292 goto Err1;
294 if (increase_x_height < 0)
295 increase_x_height = TA_INCREASE_X_HEIGHT;
297 if (fallback_script_string)
299 int i;
302 for (i = 0; i < TA_SCRIPT_MAX; i++)
303 if (!strcmp(script_names[i], fallback_script_string))
304 break;
305 if (i == TA_SCRIPT_MAX)
307 error = FT_Err_Invalid_Argument;
308 goto Err1;
311 fallback_script = i;
314 if (x_height_snapping_exceptions_string)
316 const char* s = number_set_parse(x_height_snapping_exceptions_string,
317 &x_height_snapping_exceptions,
318 TA_PROP_INCREASE_X_HEIGHT_MIN,
319 0x7FFF);
320 if (*s)
322 error = FT_Err_Invalid_Argument;
323 goto Err1;
327 font->hinting_range_min = (FT_UInt)hinting_range_min;
328 font->hinting_range_max = (FT_UInt)hinting_range_max;
329 font->hinting_limit = (FT_UInt)hinting_limit;
330 font->increase_x_height = increase_x_height;
331 font->x_height_snapping_exceptions = x_height_snapping_exceptions;
333 font->gray_strong_stem_width = gray_strong_stem_width;
334 font->gdi_cleartype_strong_stem_width = gdi_cleartype_strong_stem_width;
335 font->dw_cleartype_strong_stem_width = dw_cleartype_strong_stem_width;
337 font->windows_compatibility = windows_compatibility;
338 font->ignore_restrictions = ignore_restrictions;
339 font->pre_hinting = pre_hinting;
340 font->hint_composites = hint_composites;
341 font->fallback_script = fallback_script;
342 font->symbol = symbol;
344 No_check:
345 font->progress = progress;
346 font->progress_data = progress_data;
347 font->info = info;
348 font->info_data = info_data;
350 font->debug = debug;
351 font->dehint = dehint;
353 font->gasp_idx = MISSING;
355 /* dump parameters */
356 if (debug)
358 fprintf(stderr, "TTF_autohint parameters\n"
359 "=======================\n"
360 "\n");
362 if (dehint)
363 DUMPVAL("dehint",
364 font->dehint);
365 else
367 char *s;
370 DUMPVAL("dw-cleartype-strong-stem-width",
371 font->dw_cleartype_strong_stem_width);
372 DUMPSTR("fallback-script",
373 script_names[font->fallback_script]);
374 DUMPVAL("gdi-cleartype-strong-stem-width",
375 font->gdi_cleartype_strong_stem_width);
376 DUMPVAL("gray-strong-stem-width",
377 font->gray_strong_stem_width);
378 DUMPVAL("hinting-limit",
379 font->hinting_limit);
380 DUMPVAL("hinting-range-max",
381 font->hinting_range_max);
382 DUMPVAL("hinting-range-min",
383 font->hinting_range_min);
384 DUMPVAL("hint-composites",
385 font->hint_composites);
386 DUMPVAL("ignore-restrictions",
387 font->ignore_restrictions);
388 DUMPVAL("increase-x-height",
389 font->increase_x_height);
390 DUMPVAL("pre-hinting",
391 font->pre_hinting);
392 DUMPVAL("symbol",
393 font->symbol);
394 DUMPVAL("windows-compatibility",
395 font->windows_compatibility);
397 s = number_set_show(font->x_height_snapping_exceptions,
398 TA_PROP_INCREASE_X_HEIGHT_MIN, 0x7FFF);
399 DUMPSTR("x-height-snapping-exceptions", s);
400 free(s);
403 fprintf(stderr, "\n");
406 /* now start with processing the data */
408 if (in_file)
410 error = TA_font_file_read(font, in_file);
411 if (error)
412 goto Err;
414 else
416 /* a valid TTF can never be that small */
417 if (in_len < 100)
419 error = TA_Err_Invalid_Font_Type;
420 goto Err1;
422 font->in_buf = (FT_Byte*)in_buf;
423 font->in_len = in_len;
426 error = TA_font_init(font);
427 if (error)
428 goto Err;
430 if (font->debug)
432 _ta_debug = 1;
433 _ta_debug_global = 1;
436 /* we do some loops over all subfonts */
437 for (i = 0; i < font->num_sfnts; i++)
439 SFNT* sfnt = &font->sfnts[i];
440 FT_UInt idx;
443 error = FT_New_Memory_Face(font->lib, font->in_buf, font->in_len,
444 i, &sfnt->face);
446 /* assure that the font hasn't been already processed by ttfautohint; */
447 /* another, more thorough check is done in TA_glyph_parse_simple */
448 idx = FT_Get_Name_Index(sfnt->face, TTFAUTOHINT_GLYPH);
449 if (idx)
451 error = TA_Err_Already_Processed;
452 goto Err;
455 if (error)
456 goto Err;
458 error = TA_sfnt_split_into_SFNT_tables(sfnt, font);
459 if (error)
460 goto Err;
462 /* check permission */
463 if (sfnt->OS2_idx != MISSING)
465 SFNT_Table* OS2_table = &font->tables[sfnt->OS2_idx];
468 /* check lower byte of the `fsType' field */
469 if (OS2_table->buf[OS2_FSTYPE_OFFSET + 1] == 0x02
470 && !font->ignore_restrictions)
472 error = TA_Err_Missing_Legal_Permission;
473 goto Err;
477 if (font->dehint)
479 error = TA_sfnt_split_glyf_table(sfnt, font);
480 if (error)
481 goto Err;
483 else
485 if (font->pre_hinting)
486 error = TA_sfnt_create_glyf_data(sfnt, font);
487 else
488 error = TA_sfnt_split_glyf_table(sfnt, font);
489 if (error)
490 goto Err;
492 /* this call creates a `globals' object... */
493 error = TA_sfnt_handle_coverage(sfnt, font);
494 if (error)
495 goto Err;
497 /* ... so that we now can initialize its properties */
498 TA_sfnt_set_properties(sfnt, font);
502 if (!font->dehint)
504 for (i = 0; i < font->num_sfnts; i++)
506 SFNT* sfnt = &font->sfnts[i];
509 if (TA_sfnt_adjust_master_coverage(sfnt, font))
510 break;
514 #if 0
515 /* this code is here for completeness -- */
516 /* right now, `glyf' tables get hinted only once, */
517 /* and referring subfonts simply reuse it, */
518 /* but this might change in the future */
520 if (!font->dehint)
522 for (i = 0; i < font->num_sfnts; i++)
524 SFNT* sfnt = &font->sfnts[i];
527 TA_sfnt_copy_master_coverage(sfnt, font);
530 #endif
532 /* loop again over subfonts */
533 for (i = 0; i < font->num_sfnts; i++)
535 SFNT* sfnt = &font->sfnts[i];
538 error = ta_loader_init(font);
539 if (error)
540 goto Err;
542 error = TA_sfnt_build_gasp_table(sfnt, font);
543 if (error)
544 goto Err;
545 if (!font->dehint)
547 error = TA_sfnt_build_cvt_table(sfnt, font);
548 if (error)
549 goto Err;
550 error = TA_sfnt_build_fpgm_table(sfnt, font);
551 if (error)
552 goto Err;
553 error = TA_sfnt_build_prep_table(sfnt, font);
554 if (error)
555 goto Err;
557 error = TA_sfnt_build_glyf_table(sfnt, font);
558 if (error)
559 goto Err;
560 error = TA_sfnt_build_loca_table(sfnt, font);
561 if (error)
562 goto Err;
564 if (font->loader)
565 ta_loader_done(font);
568 for (i = 0; i < font->num_sfnts; i++)
570 SFNT* sfnt = &font->sfnts[i];
573 error = TA_sfnt_update_maxp_table(sfnt, font);
574 if (error)
575 goto Err;
577 if (!font->dehint)
579 /* we add one glyph for composites */
580 if (sfnt->max_components
581 && !font->pre_hinting
582 && font->hint_composites)
584 error = TA_sfnt_update_hmtx_table(sfnt, font);
585 if (error)
586 goto Err;
587 error = TA_sfnt_update_post_table(sfnt, font);
588 if (error)
589 goto Err;
590 error = TA_sfnt_update_GPOS_table(sfnt, font);
591 if (error)
592 goto Err;
596 if (font->info)
598 /* add info about ttfautohint to the version string */
599 error = TA_sfnt_update_name_table(sfnt, font);
600 if (error)
601 goto Err;
605 if (font->num_sfnts == 1)
606 error = TA_font_build_TTF(font);
607 else
608 error = TA_font_build_TTC(font);
609 if (error)
610 goto Err;
612 if (out_file)
614 error = TA_font_file_write(font, out_file);
615 if (error)
616 goto Err;
618 else
620 *out_bufp = (char*)font->out_buf;
621 *out_lenp = font->out_len;
624 error = TA_Err_Ok;
626 Err:
627 TA_font_unload(font, in_buf, out_bufp);
629 Err1:
630 if (error_stringp)
631 *error_stringp = (const unsigned char*)TA_get_error_message(error);
633 return error;
636 /* end of ttfautohint.c */