Comment formatting, minor improvement.
[ttfautohint.git] / lib / ttfautohint.c
blob6e8784c90629033de34c2fb9db4abf1656fe3cf4
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) (len == (sizeof (str) - 1) \
27 && !strncmp(start, str, sizeof (str) - 1))
30 TA_Error
31 TTF_autohint(const char* options,
32 ...)
34 va_list ap;
36 FONT* font;
37 FT_Error error;
38 FT_Long i;
40 FILE* in_file = NULL;
41 FILE* out_file = NULL;
43 const char* in_buf = NULL;
44 size_t in_len = 0;
45 char** out_bufp = NULL;
46 size_t* out_lenp = NULL;
48 const unsigned char** error_stringp = NULL;
50 FT_Long hinting_range_min = -1;
51 FT_Long hinting_range_max = -1;
52 FT_Long hinting_limit = -1;
54 TA_Progress_Func progress;
55 void* progress_data;
56 TA_Info_Func info;
57 void* info_data;
59 FT_Bool ignore_permissions = 0;
60 FT_Bool pre_hinting = 0;
61 FT_Bool increase_x_height = 0;
62 FT_UInt fallback_script = 0;
63 FT_Bool symbol = 0;
65 const char* op;
68 if (!options || !*options)
70 error = FT_Err_Invalid_Argument;
71 goto Err1;
74 /* XXX */
75 va_start(ap, options);
77 op = options;
79 for(;;)
81 const char* start;
82 size_t len;
85 start = op;
87 /* search comma */
88 while (*op && *op != ',')
89 op++;
91 /* remove leading whitespace */
92 while (isspace(*start))
93 start++;
95 /* check for empty option */
96 if (start == op)
97 goto End;
99 len = op - start;
101 /* the `COMPARE' macro uses `len' and `start' */
103 /* handle option */
104 if (COMPARE("error-string"))
105 error_stringp = va_arg(ap, const unsigned char**);
106 else if (COMPARE("fallback-script"))
107 fallback_script = va_arg(ap, FT_UInt);
108 else if (COMPARE("hinting-limit"))
109 hinting_limit = (FT_Long)va_arg(ap, FT_UInt);
110 else if (COMPARE("hinting-range-max"))
111 hinting_range_max = (FT_Long)va_arg(ap, FT_UInt);
112 else if (COMPARE("hinting-range-min"))
113 hinting_range_min = (FT_Long)va_arg(ap, FT_UInt);
114 else if (COMPARE("ignore-permissions"))
115 ignore_permissions = (FT_Bool)va_arg(ap, FT_Int);
116 else if (COMPARE("in-buffer"))
118 in_file = NULL;
119 in_buf = va_arg(ap, const char*);
121 else if (COMPARE("in-buffer-len"))
123 in_file = NULL;
124 in_len = va_arg(ap, size_t);
126 else if (COMPARE("in-file"))
128 in_file = va_arg(ap, FILE*);
129 in_buf = NULL;
130 in_len = 0;
132 else if (COMPARE("increase-x-height"))
133 increase_x_height = (FT_Bool)va_arg(ap, FT_Int);
134 else if (COMPARE("out-buffer"))
136 out_file = NULL;
137 out_bufp = va_arg(ap, char**);
139 else if (COMPARE("info-callback"))
140 info = va_arg(ap, TA_Info_Func);
141 else if (COMPARE("info-callback-data"))
142 info_data = va_arg(ap, void*);
143 else if (COMPARE("out-buffer-len"))
145 out_file = NULL;
146 out_lenp = va_arg(ap, size_t*);
148 else if (COMPARE("out-file"))
150 out_file = va_arg(ap, FILE*);
151 out_bufp = NULL;
152 out_lenp = NULL;
154 else if (COMPARE("pre-hinting"))
155 pre_hinting = (FT_Bool)va_arg(ap, FT_Int);
156 else if (COMPARE("progress-callback"))
157 progress = va_arg(ap, TA_Progress_Func);
158 else if (COMPARE("progress-callback-data"))
159 progress_data = va_arg(ap, void*);
160 else if (COMPARE("symbol"))
161 symbol = (FT_Bool)va_arg(ap, FT_Int);
164 x-height-snapping-exceptions
167 End:
168 if (!*op)
169 break;
170 op++;
173 va_end(ap);
175 /* check options */
177 if (!(in_file
178 || (in_buf && in_len)))
180 error = FT_Err_Invalid_Argument;
181 goto Err1;
184 if (!(out_file
185 || (out_bufp && out_lenp)))
187 error = FT_Err_Invalid_Argument;
188 goto Err1;
191 font = (FONT*)calloc(1, sizeof (FONT));
192 if (!font)
194 error = FT_Err_Out_Of_Memory;
195 goto Err1;
198 if (hinting_range_min >= 0 && hinting_range_min < 2)
200 error = FT_Err_Invalid_Argument;
201 goto Err1;
203 if (hinting_range_min < 0)
204 hinting_range_min = TA_HINTING_RANGE_MIN;
206 if (hinting_range_max >= 0 && hinting_range_max < hinting_range_min)
208 error = FT_Err_Invalid_Argument;
209 goto Err1;
211 if (hinting_range_max < 0)
212 hinting_range_max = TA_HINTING_RANGE_MAX;
214 /* value 0 is valid */
215 if (hinting_limit > 0 && hinting_limit < hinting_range_max)
217 error = FT_Err_Invalid_Argument;
218 goto Err1;
220 if (hinting_limit < 0)
221 hinting_limit = TA_HINTING_LIMIT;
223 font->hinting_range_min = (FT_UInt)hinting_range_min;
224 font->hinting_range_max = (FT_UInt)hinting_range_max;
225 font->hinting_limit = (FT_UInt)hinting_limit;
227 font->progress = progress;
228 font->progress_data = progress_data;
229 font->info = info;
230 font->info_data = info_data;
232 font->ignore_permissions = ignore_permissions;
233 font->pre_hinting = pre_hinting;
234 font->increase_x_height = increase_x_height;
235 /* restrict value to two bits */
236 font->fallback_script = fallback_script & 3;
237 font->symbol = symbol;
239 /* now start with processing the data */
241 if (in_file)
243 error = TA_font_file_read(font, in_file);
244 if (error)
245 goto Err;
247 else
249 /* a valid TTF can never be that small */
250 if (in_len < 100)
252 error = FT_Err_Invalid_Argument;
253 goto Err1;
255 font->in_buf = (FT_Byte*)in_buf;
256 font->in_len = in_len;
259 error = TA_font_init(font);
260 if (error)
261 goto Err;
263 /* loop over subfonts */
264 for (i = 0; i < font->num_sfnts; i++)
266 SFNT* sfnt = &font->sfnts[i];
267 FT_UInt idx;
270 error = FT_New_Memory_Face(font->lib, font->in_buf, font->in_len,
271 i, &sfnt->face);
273 /* assure that the font hasn't been already processed by ttfautohint */
274 idx = FT_Get_Name_Index(sfnt->face, TTFAUTOHINT_GLYPH);
275 if (idx)
277 error = TA_Err_Already_Processed;
278 goto Err;
281 if (error)
282 goto Err;
284 error = TA_sfnt_split_into_SFNT_tables(sfnt, font);
285 if (error)
286 goto Err;
288 if (font->pre_hinting)
289 error = TA_sfnt_create_glyf_data(sfnt, font);
290 else
291 error = TA_sfnt_split_glyf_table(sfnt, font);
292 if (error)
293 goto Err;
295 /* check permission */
296 if (sfnt->OS2_idx != MISSING)
298 SFNT_Table* OS2_table = &font->tables[sfnt->OS2_idx];
301 /* check lower byte of the `fsType' field */
302 if (OS2_table->buf[OS2_FSTYPE_OFFSET + 1] == 0x02
303 && !font->ignore_permissions)
305 error = TA_Err_Missing_Legal_Permission;
306 goto Err;
311 /* build `gasp' table */
312 error = TA_sfnt_build_gasp_table(&font->sfnts[0], font);
313 if (error)
314 goto Err;
316 /* XXX handle subfonts for bytecode tables */
318 /* build `cvt ' table */
319 error = TA_sfnt_build_cvt_table(&font->sfnts[0], font);
320 if (error)
321 goto Err;
323 /* build `fpgm' table */
324 error = TA_sfnt_build_fpgm_table(&font->sfnts[0], font);
325 if (error)
326 goto Err;
328 /* build `prep' table */
329 error = TA_sfnt_build_prep_table(&font->sfnts[0], font);
330 if (error)
331 goto Err;
333 /* hint the glyphs and build bytecode */
334 error = TA_sfnt_build_glyf_hints(&font->sfnts[0], font);
335 if (error)
336 goto Err;
338 /* loop again over subfonts */
339 for (i = 0; i < font->num_sfnts; i++)
341 SFNT* sfnt = &font->sfnts[i];
344 error = TA_sfnt_build_glyf_table(sfnt, font);
345 if (error)
346 goto Err;
347 error = TA_sfnt_build_loca_table(sfnt, font);
348 if (error)
349 goto Err;
350 error = TA_sfnt_update_maxp_table(sfnt, font);
351 if (error)
352 goto Err;
354 /* we add one glyph for composites */
355 if (sfnt->max_components && !font->pre_hinting)
357 error = TA_sfnt_update_hmtx_table(sfnt, font);
358 if (error)
359 goto Err;
360 error = TA_sfnt_update_post_table(sfnt, font);
361 if (error)
362 goto Err;
363 error = TA_sfnt_update_GPOS_table(sfnt, font);
364 if (error)
365 goto Err;
368 if (font->info)
370 /* add info about ttfautohint to the version string */
371 error = TA_sfnt_update_name_table(sfnt, font);
372 if (error)
373 goto Err;
377 if (font->num_sfnts == 1)
378 error = TA_font_build_TTF(font);
379 else
380 error = TA_font_build_TTC(font);
381 if (error)
382 goto Err;
384 if (out_file)
386 error = TA_font_file_write(font, out_file);
387 if (error)
388 goto Err;
390 else
392 *out_bufp = (char*)font->out_buf;
393 *out_lenp = font->out_len;
396 error = TA_Err_Ok;
398 Err:
399 TA_font_unload(font, in_buf, out_bufp);
401 Err1:
402 if (error_stringp)
403 *error_stringp = (const unsigned char*)TA_get_error_message(error);
405 return error;
408 /* end of ttfautohint.c */