Initialize properties of `globals' object.
[ttfautohint.git] / lib / ttfautohint.c
blob8e299506370c4450acfbbec4162cc1383c70dc68
1 /* ttfautohint.c */
3 /*
4 * Copyright (C) 2011-2012 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))
35 void
36 TA_sfnt_set_properties(SFNT* sfnt,
37 FONT* font)
39 TA_FaceGlobals globals = (TA_FaceGlobals)sfnt->face->autohint.data;
42 globals->increase_x_height = font->increase_x_height;
46 TA_Error
47 TTF_autohint(const char* options,
48 ...)
50 va_list ap;
52 FONT* font;
53 FT_Error error;
54 FT_Long i;
56 FILE* in_file = NULL;
57 FILE* out_file = NULL;
59 const char* in_buf = NULL;
60 size_t in_len = 0;
61 char** out_bufp = NULL;
62 size_t* out_lenp = NULL;
64 const unsigned char** error_stringp = NULL;
66 FT_Long hinting_range_min = -1;
67 FT_Long hinting_range_max = -1;
68 FT_Long hinting_limit = -1;
69 FT_Long increase_x_height = -1;
71 FT_Bool gray_strong_stem_width = 0;
72 FT_Bool gdi_cleartype_strong_stem_width = 1;
73 FT_Bool dw_cleartype_strong_stem_width = 0;
75 TA_Progress_Func progress;
76 void* progress_data;
77 TA_Info_Func info;
78 void* info_data;
80 FT_Bool windows_compatibility = 0;
81 FT_Bool ignore_restrictions = 0;
82 FT_Bool pre_hinting = 0;
83 FT_Bool hint_with_components = 0;
84 FT_UInt fallback_script = TA_SCRIPT_FALLBACK;
85 FT_Bool symbol = 0;
87 FT_Bool debug = 0;
89 const char* op;
92 if (!options || !*options)
94 error = FT_Err_Invalid_Argument;
95 goto Err1;
98 /* XXX */
99 va_start(ap, options);
101 op = options;
103 for(;;)
105 const char* start;
106 size_t len;
109 start = op;
111 /* search comma */
112 while (*op && *op != ',')
113 op++;
115 /* remove leading whitespace */
116 while (isspace(*start))
117 start++;
119 /* check for empty option */
120 if (start == op)
121 goto End;
123 len = op - start;
125 /* the `COMPARE' macro uses `len' and `start' */
127 /* handle options -- don't forget to update parameter dump below! */
128 if (COMPARE("debug"))
129 debug = (FT_Bool)va_arg(ap, FT_Int);
130 else if (COMPARE("dw-cleartype-strong-stem-width"))
131 dw_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
132 else if (COMPARE("error-string"))
133 error_stringp = va_arg(ap, const unsigned char**);
134 else if (COMPARE("fallback-script"))
135 fallback_script = va_arg(ap, FT_UInt);
136 else if (COMPARE("gdi-cleartype-strong-stem-width"))
137 gdi_cleartype_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
138 else if (COMPARE("gray-strong-stem-width"))
139 gray_strong_stem_width = (FT_Bool)va_arg(ap, FT_Int);
140 else if (COMPARE("hinting-limit"))
141 hinting_limit = (FT_Long)va_arg(ap, FT_UInt);
142 else if (COMPARE("hinting-range-max"))
143 hinting_range_max = (FT_Long)va_arg(ap, FT_UInt);
144 else if (COMPARE("hinting-range-min"))
145 hinting_range_min = (FT_Long)va_arg(ap, FT_UInt);
146 else if (COMPARE("hint-with-components"))
147 hint_with_components = (FT_Bool)va_arg(ap, FT_Int);
148 else if (COMPARE("ignore-restrictions"))
149 ignore_restrictions = (FT_Bool)va_arg(ap, FT_Int);
150 else if (COMPARE("in-buffer"))
152 in_file = NULL;
153 in_buf = va_arg(ap, const char*);
155 else if (COMPARE("in-buffer-len"))
157 in_file = NULL;
158 in_len = va_arg(ap, size_t);
160 else if (COMPARE("in-file"))
162 in_file = va_arg(ap, FILE*);
163 in_buf = NULL;
164 in_len = 0;
166 else if (COMPARE("increase-x-height"))
167 increase_x_height = (FT_Long)va_arg(ap, FT_UInt);
168 else if (COMPARE("info-callback"))
169 info = va_arg(ap, TA_Info_Func);
170 else if (COMPARE("info-callback-data"))
171 info_data = va_arg(ap, void*);
172 else if (COMPARE("out-buffer"))
174 out_file = NULL;
175 out_bufp = va_arg(ap, char**);
177 else if (COMPARE("out-buffer-len"))
179 out_file = NULL;
180 out_lenp = va_arg(ap, size_t*);
182 else if (COMPARE("out-file"))
184 out_file = va_arg(ap, FILE*);
185 out_bufp = NULL;
186 out_lenp = NULL;
188 else if (COMPARE("pre-hinting"))
189 pre_hinting = (FT_Bool)va_arg(ap, FT_Int);
190 else if (COMPARE("progress-callback"))
191 progress = va_arg(ap, TA_Progress_Func);
192 else if (COMPARE("progress-callback-data"))
193 progress_data = va_arg(ap, void*);
194 else if (COMPARE("symbol"))
195 symbol = (FT_Bool)va_arg(ap, FT_Int);
196 else if (COMPARE("windows-compatibility"))
197 windows_compatibility = (FT_Bool)va_arg(ap, FT_Int);
198 else
200 error = TA_Err_Unknown_Argument;
201 goto Err1;
205 x-height-snapping-exceptions
208 End:
209 if (!*op)
210 break;
211 op++;
214 va_end(ap);
216 /* check options */
218 if (!(in_file
219 || (in_buf && in_len)))
221 error = FT_Err_Invalid_Argument;
222 goto Err1;
225 if (!(out_file
226 || (out_bufp && out_lenp)))
228 error = FT_Err_Invalid_Argument;
229 goto Err1;
232 font = (FONT*)calloc(1, sizeof (FONT));
233 if (!font)
235 error = FT_Err_Out_Of_Memory;
236 goto Err1;
239 if (hinting_range_min >= 0 && hinting_range_min < 2)
241 error = FT_Err_Invalid_Argument;
242 goto Err1;
244 if (hinting_range_min < 0)
245 hinting_range_min = TA_HINTING_RANGE_MIN;
247 if (hinting_range_max >= 0 && hinting_range_max < hinting_range_min)
249 error = FT_Err_Invalid_Argument;
250 goto Err1;
252 if (hinting_range_max < 0)
253 hinting_range_max = TA_HINTING_RANGE_MAX;
255 /* value 0 is valid */
256 if (hinting_limit > 0 && hinting_limit < hinting_range_max)
258 error = FT_Err_Invalid_Argument;
259 goto Err1;
261 if (hinting_limit < 0)
262 hinting_limit = TA_HINTING_LIMIT;
264 if (increase_x_height > 0 && increase_x_height < 6)
266 error = FT_Err_Invalid_Argument;
267 goto Err1;
269 if (increase_x_height < 0)
270 increase_x_height = TA_INCREASE_X_HEIGHT;
272 font->hinting_range_min = (FT_UInt)hinting_range_min;
273 font->hinting_range_max = (FT_UInt)hinting_range_max;
274 font->hinting_limit = (FT_UInt)hinting_limit;
275 font->increase_x_height = increase_x_height;
277 font->gray_strong_stem_width = gray_strong_stem_width;
278 font->gdi_cleartype_strong_stem_width = gdi_cleartype_strong_stem_width;
279 font->dw_cleartype_strong_stem_width = dw_cleartype_strong_stem_width;
281 font->progress = progress;
282 font->progress_data = progress_data;
283 font->info = info;
284 font->info_data = info_data;
286 font->windows_compatibility = windows_compatibility;
287 font->ignore_restrictions = ignore_restrictions;
288 font->pre_hinting = pre_hinting;
289 font->hint_with_components = hint_with_components;
290 font->fallback_script = fallback_script;
291 font->symbol = symbol;
293 font->gasp_idx = MISSING;
295 font->debug = debug;
297 /* dump parameters */
298 if (debug)
300 fprintf(stderr, "TTF_autohint parameters\n"
301 "=======================\n\n");
303 DUMPVAL("dw-cleartype-strong-stem-width",
304 font->dw_cleartype_strong_stem_width);
305 DUMPVAL("fallback-script",
306 font->fallback_script);
307 DUMPVAL("gdi-cleartype-strong-stem-width",
308 font->gdi_cleartype_strong_stem_width);
309 DUMPVAL("gray-strong-stem-width",
310 font->gray_strong_stem_width);
311 DUMPVAL("hinting-limit",
312 font->hinting_limit);
313 DUMPVAL("hinting-range-max",
314 font->hinting_range_max);
315 DUMPVAL("hinting-range-min",
316 font->hinting_range_min);
317 DUMPVAL("hint-with-components",
318 font->hint_with_components);
319 DUMPVAL("ignore-restrictions",
320 font->ignore_restrictions);
321 DUMPVAL("increase-x-height",
322 font->increase_x_height);
323 DUMPVAL("pre-hinting",
324 font->pre_hinting);
325 DUMPVAL("symbol",
326 font->symbol);
327 DUMPVAL("windows-compatibility",
328 font->windows_compatibility);
330 fprintf(stderr, "\n");
333 /* now start with processing the data */
335 if (in_file)
337 error = TA_font_file_read(font, in_file);
338 if (error)
339 goto Err;
341 else
343 /* a valid TTF can never be that small */
344 if (in_len < 100)
346 error = TA_Err_Invalid_Font_Type;
347 goto Err1;
349 font->in_buf = (FT_Byte*)in_buf;
350 font->in_len = in_len;
353 error = TA_font_init(font);
354 if (error)
355 goto Err;
357 if (font->debug)
358 _ta_debug = 1;
360 /* we do some loops over all subfonts */
361 for (i = 0; i < font->num_sfnts; i++)
363 SFNT* sfnt = &font->sfnts[i];
364 FT_UInt idx;
367 error = FT_New_Memory_Face(font->lib, font->in_buf, font->in_len,
368 i, &sfnt->face);
370 /* assure that the font hasn't been already processed by ttfautohint; */
371 /* another, more thorough check is done in TA_glyph_parse_simple */
372 idx = FT_Get_Name_Index(sfnt->face, TTFAUTOHINT_GLYPH);
373 if (idx)
375 error = TA_Err_Already_Processed;
376 goto Err;
379 if (error)
380 goto Err;
382 error = TA_sfnt_split_into_SFNT_tables(sfnt, font);
383 if (error)
384 goto Err;
386 if (font->pre_hinting)
387 error = TA_sfnt_create_glyf_data(sfnt, font);
388 else
389 error = TA_sfnt_split_glyf_table(sfnt, font);
390 if (error)
391 goto Err;
393 /* this call creates a `globals' object... */
394 error = TA_sfnt_handle_coverage(sfnt, font);
395 if (error)
396 goto Err;
398 /* ... so that we now can initialize its properties */
399 TA_sfnt_set_properties(sfnt, font);
401 /* check permission */
402 if (sfnt->OS2_idx != MISSING)
404 SFNT_Table* OS2_table = &font->tables[sfnt->OS2_idx];
407 /* check lower byte of the `fsType' field */
408 if (OS2_table->buf[OS2_FSTYPE_OFFSET + 1] == 0x02
409 && !font->ignore_restrictions)
411 error = TA_Err_Missing_Legal_Permission;
412 goto Err;
417 for (i = 0; i < font->num_sfnts; i++)
419 SFNT* sfnt = &font->sfnts[i];
422 TA_sfnt_adjust_master_coverage(sfnt, font);
425 #if 0
426 /* this code is here for completeness -- */
427 /* right now, `glyf' tables get hinted only once, */
428 /* and referring subfonts simply reuse it, */
429 /* but this might change in the future */
431 for (i = 0; i < font->num_sfnts; i++)
433 SFNT* sfnt = &font->sfnts[i];
436 TA_sfnt_copy_master_coverage(sfnt, font);
438 #endif
440 /* loop again over subfonts */
441 for (i = 0; i < font->num_sfnts; i++)
443 SFNT* sfnt = &font->sfnts[i];
446 error = ta_loader_init(font);
447 if (error)
448 goto Err;
450 error = TA_sfnt_build_gasp_table(sfnt, font);
451 if (error)
452 goto Err;
453 error = TA_sfnt_build_cvt_table(sfnt, font);
454 if (error)
455 goto Err;
456 error = TA_sfnt_build_fpgm_table(sfnt, font);
457 if (error)
458 goto Err;
459 error = TA_sfnt_build_prep_table(sfnt, font);
460 if (error)
461 goto Err;
462 error = TA_sfnt_build_glyf_table(sfnt, font);
463 if (error)
464 goto Err;
465 error = TA_sfnt_build_loca_table(sfnt, font);
466 if (error)
467 goto Err;
469 if (font->loader)
470 ta_loader_done(font);
473 for (i = 0; i < font->num_sfnts; i++)
475 SFNT* sfnt = &font->sfnts[i];
478 error = TA_sfnt_update_maxp_table(sfnt, font);
479 if (error)
480 goto Err;
482 /* we add one glyph for composites */
483 if (sfnt->max_components
484 && !font->pre_hinting
485 && font->hint_with_components)
487 error = TA_sfnt_update_hmtx_table(sfnt, font);
488 if (error)
489 goto Err;
490 error = TA_sfnt_update_post_table(sfnt, font);
491 if (error)
492 goto Err;
493 error = TA_sfnt_update_GPOS_table(sfnt, font);
494 if (error)
495 goto Err;
498 if (font->info)
500 /* add info about ttfautohint to the version string */
501 error = TA_sfnt_update_name_table(sfnt, font);
502 if (error)
503 goto Err;
507 if (font->num_sfnts == 1)
508 error = TA_font_build_TTF(font);
509 else
510 error = TA_font_build_TTC(font);
511 if (error)
512 goto Err;
514 if (out_file)
516 error = TA_font_file_write(font, out_file);
517 if (error)
518 goto Err;
520 else
522 *out_bufp = (char*)font->out_buf;
523 *out_lenp = font->out_len;
526 error = TA_Err_Ok;
528 Err:
529 TA_font_unload(font, in_buf, out_bufp);
531 Err1:
532 if (error_stringp)
533 *error_stringp = (const unsigned char*)TA_get_error_message(error);
535 return error;
538 /* end of ttfautohint.c */