s/--components/--composites/, s/hint-with-components/hint-composites/.
[ttfautohint.git] / lib / ttfautohint.c
blobf5c271817b3e1cdcf520a282a7dc7dc4a437db65
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_UInt fallback_script = TA_SCRIPT_FALLBACK;
92 FT_Bool symbol = 0;
94 FT_Bool dehint = 0;
96 FT_Bool debug = 0;
98 const char* op;
101 if (!options || !*options)
103 error = FT_Err_Invalid_Argument;
104 goto Err1;
107 /* XXX */
108 va_start(ap, options);
110 op = options;
112 for(;;)
114 const char* start;
115 size_t len;
118 start = op;
120 /* search comma */
121 while (*op && *op != ',')
122 op++;
124 /* remove leading whitespace */
125 while (isspace(*start))
126 start++;
128 /* check for empty option */
129 if (start == op)
130 goto End;
132 len = op - start;
134 /* the `COMPARE' macro uses `len' and `start' */
136 /* handle options -- don't forget to update parameter dump below! */
137 if (COMPARE("debug"))
138 debug = (FT_Bool)va_arg(ap, FT_Int);
139 else if (COMPARE("dehint"))
140 dehint = (FT_Bool)va_arg(ap, FT_Int);
141 else if (COMPARE("dw-cleartype-strong-stem-width"))
142 dw_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
143 else if (COMPARE("error-string"))
144 error_stringp = va_arg(ap, const unsigned char**);
145 else if (COMPARE("fallback-script"))
146 fallback_script = va_arg(ap, FT_UInt);
147 else if (COMPARE("gdi-cleartype-strong-stem-width"))
148 gdi_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
149 else if (COMPARE("gray-strong-stem-width"))
150 gray_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
151 else if (COMPARE("hinting-limit"))
152 hinting_limit = (FT_Long)va_arg(ap, FT_UInt);
153 else if (COMPARE("hinting-range-max"))
154 hinting_range_max = (FT_Long)va_arg(ap, FT_UInt);
155 else if (COMPARE("hinting-range-min"))
156 hinting_range_min = (FT_Long)va_arg(ap, FT_UInt);
157 else if (COMPARE("hint-composites"))
158 hint_composites = (FT_Bool)va_arg(ap, FT_Int);
159 else if (COMPARE("ignore-restrictions"))
160 ignore_restrictions = (FT_Bool)va_arg(ap, FT_Int);
161 else if (COMPARE("in-buffer"))
163 in_file = NULL;
164 in_buf = va_arg(ap, const char*);
166 else if (COMPARE("in-buffer-len"))
168 in_file = NULL;
169 in_len = va_arg(ap, size_t);
171 else if (COMPARE("in-file"))
173 in_file = va_arg(ap, FILE*);
174 in_buf = NULL;
175 in_len = 0;
177 else if (COMPARE("increase-x-height"))
178 increase_x_height = (FT_Long)va_arg(ap, FT_UInt);
179 else if (COMPARE("info-callback"))
180 info = va_arg(ap, TA_Info_Func);
181 else if (COMPARE("info-callback-data"))
182 info_data = va_arg(ap, void*);
183 else if (COMPARE("out-buffer"))
185 out_file = NULL;
186 out_bufp = va_arg(ap, char**);
188 else if (COMPARE("out-buffer-len"))
190 out_file = NULL;
191 out_lenp = va_arg(ap, size_t*);
193 else if (COMPARE("out-file"))
195 out_file = va_arg(ap, FILE*);
196 out_bufp = NULL;
197 out_lenp = NULL;
199 else if (COMPARE("pre-hinting"))
200 pre_hinting = (FT_Bool)va_arg(ap, FT_Int);
201 else if (COMPARE("progress-callback"))
202 progress = va_arg(ap, TA_Progress_Func);
203 else if (COMPARE("progress-callback-data"))
204 progress_data = va_arg(ap, void*);
205 else if (COMPARE("symbol"))
206 symbol = (FT_Bool)va_arg(ap, FT_Int);
207 else if (COMPARE("windows-compatibility"))
208 windows_compatibility = (FT_Bool)va_arg(ap, FT_Int);
209 else if (COMPARE("x-height-snapping-exceptions"))
210 x_height_snapping_exceptions_string = va_arg(ap, const char*);
211 else
213 error = TA_Err_Unknown_Argument;
214 goto Err1;
217 End:
218 if (!*op)
219 break;
220 op++;
223 va_end(ap);
225 /* check options */
227 if (!(in_file
228 || (in_buf && in_len)))
230 error = FT_Err_Invalid_Argument;
231 goto Err1;
234 if (!(out_file
235 || (out_bufp && out_lenp)))
237 error = FT_Err_Invalid_Argument;
238 goto Err1;
241 font = (FONT*)calloc(1, sizeof (FONT));
242 if (!font)
244 error = FT_Err_Out_Of_Memory;
245 goto Err1;
248 if (dehint)
249 goto No_check;
251 if (hinting_range_min >= 0 && hinting_range_min < 2)
253 error = FT_Err_Invalid_Argument;
254 goto Err1;
256 if (hinting_range_min < 0)
257 hinting_range_min = TA_HINTING_RANGE_MIN;
259 if (hinting_range_max >= 0 && hinting_range_max < hinting_range_min)
261 error = FT_Err_Invalid_Argument;
262 goto Err1;
264 if (hinting_range_max < 0)
265 hinting_range_max = TA_HINTING_RANGE_MAX;
267 /* value 0 is valid */
268 if (hinting_limit > 0 && hinting_limit < hinting_range_max)
270 error = FT_Err_Invalid_Argument;
271 goto Err1;
273 if (hinting_limit < 0)
274 hinting_limit = TA_HINTING_LIMIT;
276 if (increase_x_height > 0
277 && increase_x_height < TA_PROP_INCREASE_X_HEIGHT_MIN)
279 error = FT_Err_Invalid_Argument;
280 goto Err1;
282 if (increase_x_height < 0)
283 increase_x_height = TA_INCREASE_X_HEIGHT;
285 if (x_height_snapping_exceptions_string)
287 const char* s = number_set_parse(x_height_snapping_exceptions_string,
288 &x_height_snapping_exceptions,
289 TA_PROP_INCREASE_X_HEIGHT_MIN,
290 0x7FFF);
291 if (*s)
293 error = FT_Err_Invalid_Argument;
294 goto Err1;
298 font->hinting_range_min = (FT_UInt)hinting_range_min;
299 font->hinting_range_max = (FT_UInt)hinting_range_max;
300 font->hinting_limit = (FT_UInt)hinting_limit;
301 font->increase_x_height = increase_x_height;
302 font->x_height_snapping_exceptions = x_height_snapping_exceptions;
304 font->gray_strong_stem_width = gray_strong_stem_width;
305 font->gdi_cleartype_strong_stem_width = gdi_cleartype_strong_stem_width;
306 font->dw_cleartype_strong_stem_width = dw_cleartype_strong_stem_width;
308 font->windows_compatibility = windows_compatibility;
309 font->ignore_restrictions = ignore_restrictions;
310 font->pre_hinting = pre_hinting;
311 font->hint_composites = hint_composites;
312 font->fallback_script = fallback_script;
313 font->symbol = symbol;
315 No_check:
316 font->progress = progress;
317 font->progress_data = progress_data;
318 font->info = info;
319 font->info_data = info_data;
321 font->debug = debug;
322 font->dehint = dehint;
324 font->gasp_idx = MISSING;
326 /* dump parameters */
327 if (debug)
329 fprintf(stderr, "TTF_autohint parameters\n"
330 "=======================\n"
331 "\n");
333 if (dehint)
334 DUMPVAL("dehint",
335 font->dehint);
336 else
338 char *s;
341 DUMPVAL("dw-cleartype-strong-stem-width",
342 font->dw_cleartype_strong_stem_width);
343 DUMPVAL("fallback-script",
344 font->fallback_script);
345 DUMPVAL("gdi-cleartype-strong-stem-width",
346 font->gdi_cleartype_strong_stem_width);
347 DUMPVAL("gray-strong-stem-width",
348 font->gray_strong_stem_width);
349 DUMPVAL("hinting-limit",
350 font->hinting_limit);
351 DUMPVAL("hinting-range-max",
352 font->hinting_range_max);
353 DUMPVAL("hinting-range-min",
354 font->hinting_range_min);
355 DUMPVAL("hint-composites",
356 font->hint_composites);
357 DUMPVAL("ignore-restrictions",
358 font->ignore_restrictions);
359 DUMPVAL("increase-x-height",
360 font->increase_x_height);
361 DUMPVAL("pre-hinting",
362 font->pre_hinting);
363 DUMPVAL("symbol",
364 font->symbol);
365 DUMPVAL("windows-compatibility",
366 font->windows_compatibility);
368 s = number_set_show(font->x_height_snapping_exceptions,
369 TA_PROP_INCREASE_X_HEIGHT_MIN, 0x7FFF);
370 DUMPSTR("x-height-snapping-exceptions", s);
371 free(s);
374 fprintf(stderr, "\n");
377 /* now start with processing the data */
379 if (in_file)
381 error = TA_font_file_read(font, in_file);
382 if (error)
383 goto Err;
385 else
387 /* a valid TTF can never be that small */
388 if (in_len < 100)
390 error = TA_Err_Invalid_Font_Type;
391 goto Err1;
393 font->in_buf = (FT_Byte*)in_buf;
394 font->in_len = in_len;
397 error = TA_font_init(font);
398 if (error)
399 goto Err;
401 if (font->debug)
402 _ta_debug = 1;
404 /* we do some loops over all subfonts */
405 for (i = 0; i < font->num_sfnts; i++)
407 SFNT* sfnt = &font->sfnts[i];
408 FT_UInt idx;
411 error = FT_New_Memory_Face(font->lib, font->in_buf, font->in_len,
412 i, &sfnt->face);
414 /* assure that the font hasn't been already processed by ttfautohint; */
415 /* another, more thorough check is done in TA_glyph_parse_simple */
416 idx = FT_Get_Name_Index(sfnt->face, TTFAUTOHINT_GLYPH);
417 if (idx)
419 error = TA_Err_Already_Processed;
420 goto Err;
423 if (error)
424 goto Err;
426 error = TA_sfnt_split_into_SFNT_tables(sfnt, font);
427 if (error)
428 goto Err;
430 /* check permission */
431 if (sfnt->OS2_idx != MISSING)
433 SFNT_Table* OS2_table = &font->tables[sfnt->OS2_idx];
436 /* check lower byte of the `fsType' field */
437 if (OS2_table->buf[OS2_FSTYPE_OFFSET + 1] == 0x02
438 && !font->ignore_restrictions)
440 error = TA_Err_Missing_Legal_Permission;
441 goto Err;
445 if (font->dehint)
447 error = TA_sfnt_split_glyf_table(sfnt, font);
448 if (error)
449 goto Err;
451 else
453 if (font->pre_hinting)
454 error = TA_sfnt_create_glyf_data(sfnt, font);
455 else
456 error = TA_sfnt_split_glyf_table(sfnt, font);
457 if (error)
458 goto Err;
460 /* this call creates a `globals' object... */
461 error = TA_sfnt_handle_coverage(sfnt, font);
462 if (error)
463 goto Err;
465 /* ... so that we now can initialize its properties */
466 TA_sfnt_set_properties(sfnt, font);
470 if (!font->dehint)
472 for (i = 0; i < font->num_sfnts; i++)
474 SFNT* sfnt = &font->sfnts[i];
477 TA_sfnt_adjust_master_coverage(sfnt, font);
481 #if 0
482 /* this code is here for completeness -- */
483 /* right now, `glyf' tables get hinted only once, */
484 /* and referring subfonts simply reuse it, */
485 /* but this might change in the future */
487 if (!font->dehint)
489 for (i = 0; i < font->num_sfnts; i++)
491 SFNT* sfnt = &font->sfnts[i];
494 TA_sfnt_copy_master_coverage(sfnt, font);
497 #endif
499 /* loop again over subfonts */
500 for (i = 0; i < font->num_sfnts; i++)
502 SFNT* sfnt = &font->sfnts[i];
505 error = ta_loader_init(font);
506 if (error)
507 goto Err;
509 error = TA_sfnt_build_gasp_table(sfnt, font);
510 if (error)
511 goto Err;
512 if (!font->dehint)
514 error = TA_sfnt_build_cvt_table(sfnt, font);
515 if (error)
516 goto Err;
517 error = TA_sfnt_build_fpgm_table(sfnt, font);
518 if (error)
519 goto Err;
520 error = TA_sfnt_build_prep_table(sfnt, font);
521 if (error)
522 goto Err;
524 error = TA_sfnt_build_glyf_table(sfnt, font);
525 if (error)
526 goto Err;
527 error = TA_sfnt_build_loca_table(sfnt, font);
528 if (error)
529 goto Err;
531 if (font->loader)
532 ta_loader_done(font);
535 for (i = 0; i < font->num_sfnts; i++)
537 SFNT* sfnt = &font->sfnts[i];
540 error = TA_sfnt_update_maxp_table(sfnt, font);
541 if (error)
542 goto Err;
544 if (!font->dehint)
546 /* we add one glyph for composites */
547 if (sfnt->max_components
548 && !font->pre_hinting
549 && font->hint_composites)
551 error = TA_sfnt_update_hmtx_table(sfnt, font);
552 if (error)
553 goto Err;
554 error = TA_sfnt_update_post_table(sfnt, font);
555 if (error)
556 goto Err;
557 error = TA_sfnt_update_GPOS_table(sfnt, font);
558 if (error)
559 goto Err;
563 if (font->info)
565 /* add info about ttfautohint to the version string */
566 error = TA_sfnt_update_name_table(sfnt, font);
567 if (error)
568 goto Err;
572 if (font->num_sfnts == 1)
573 error = TA_font_build_TTF(font);
574 else
575 error = TA_font_build_TTC(font);
576 if (error)
577 goto Err;
579 if (out_file)
581 error = TA_font_file_write(font, out_file);
582 if (error)
583 goto Err;
585 else
587 *out_bufp = (char*)font->out_buf;
588 *out_lenp = font->out_len;
591 error = TA_Err_Ok;
593 Err:
594 TA_font_unload(font, in_buf, out_bufp);
596 Err1:
597 if (error_stringp)
598 *error_stringp = (const unsigned char*)TA_get_error_message(error);
600 return error;
603 /* end of ttfautohint.c */