Sort options alphabetically.
[ttfautohint.git] / src / ttfautohint.c
blobe119a0fc7b9417dcb50c5454108301955efe0fe6
1 /* ttfautohint.c */
3 /*
4 * Copyright (C) 2011 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;
53 TA_Progress_Func progress;
54 void* progress_data;
56 FT_Bool ignore_permissions = 0;
57 FT_UInt fallback_script = 0;
59 const char *op;
62 if (!options || !*options)
64 error = FT_Err_Invalid_Argument;
65 goto Err1;
68 /* XXX */
69 va_start(ap, options);
71 op = options;
73 for(;;)
75 const char* start;
76 size_t len;
79 start = op;
81 /* search comma */
82 while (*op && *op != ',')
83 op++;
85 /* remove leading whitespace */
86 while (isspace(*start))
87 start++;
89 /* check for empty option */
90 if (start == op)
91 goto End;
93 len = op - start;
95 /* the `COMPARE' macro uses `len' and `start' */
97 /* handle option */
98 if (COMPARE("error-string"))
99 error_stringp = va_arg(ap, const unsigned char**);
100 else if (COMPARE("fallback-script"))
101 fallback_script = va_arg(ap, FT_UInt);
102 else if (COMPARE("hinting-range-max"))
103 hinting_range_max = (FT_Long)va_arg(ap, FT_UInt);
104 else if (COMPARE("hinting-range-min"))
105 hinting_range_min = (FT_Long)va_arg(ap, FT_UInt);
106 else if (COMPARE("ignore-permissions"))
107 ignore_permissions = (FT_Bool)va_arg(ap, FT_Int);
108 else if (COMPARE("in-buffer"))
110 in_file = NULL;
111 in_buf = va_arg(ap, const char*);
113 else if (COMPARE("in-buffer-len"))
115 in_file = NULL;
116 in_len = va_arg(ap, size_t);
118 else if (COMPARE("in-file"))
120 in_file = va_arg(ap, FILE*);
121 in_buf = NULL;
122 in_len = 0;
124 else if (COMPARE("out-buffer"))
126 out_file = NULL;
127 out_bufp = va_arg(ap, char**);
129 else if (COMPARE("out-buffer-len"))
131 out_file = NULL;
132 out_lenp = va_arg(ap, size_t*);
134 else if (COMPARE("out-file"))
136 out_file = va_arg(ap, FILE*);
137 out_bufp = NULL;
138 out_lenp = NULL;
140 else if (COMPARE("progress-callback"))
141 progress = va_arg(ap, TA_Progress_Func);
142 else if (COMPARE("progress-callback-data"))
143 progress_data = va_arg(ap, void*);
146 pre-hinting
147 x-height-snapping-exceptions
150 End:
151 if (!*op)
152 break;
153 op++;
156 va_end(ap);
158 /* check options */
160 if (!(in_file
161 || (in_buf && in_len)))
163 error = FT_Err_Invalid_Argument;
164 goto Err1;
167 if (!(out_file
168 || (out_bufp && out_lenp)))
170 error = FT_Err_Invalid_Argument;
171 goto Err1;
174 font = (FONT*)calloc(1, sizeof (FONT));
175 if (!font)
177 error = FT_Err_Out_Of_Memory;
178 goto Err1;
181 if (hinting_range_min >= 0 && hinting_range_min < 2)
183 error = FT_Err_Invalid_Argument;
184 goto Err1;
186 if (hinting_range_min < 0)
187 hinting_range_min = 8;
189 if (hinting_range_max >= 0 && hinting_range_max < hinting_range_min)
191 error = FT_Err_Invalid_Argument;
192 goto Err1;
194 if (hinting_range_max < 0)
195 hinting_range_max = 1000;
197 font->hinting_range_min = (FT_UInt)hinting_range_min;
198 font->hinting_range_max = (FT_UInt)hinting_range_max;
200 font->progress = progress;
201 font->progress_data = progress_data;
203 font->ignore_permissions = ignore_permissions;
204 /* restrict value to two bits */
205 font->fallback_script = fallback_script & 3;
207 /* now start with processing the data */
209 if (in_file)
211 error = TA_font_file_read(font, in_file);
212 if (error)
213 goto Err;
215 else
217 /* a valid TTF can never be that small */
218 if (in_len < 100)
220 error = FT_Err_Invalid_Argument;
221 goto Err1;
223 font->in_buf = (FT_Byte*)in_buf;
224 font->in_len = in_len;
227 error = TA_font_init(font);
228 if (error)
229 goto Err;
231 /* loop over subfonts */
232 for (i = 0; i < font->num_sfnts; i++)
234 SFNT* sfnt = &font->sfnts[i];
237 error = FT_New_Memory_Face(font->lib, font->in_buf, font->in_len,
238 i, &sfnt->face);
239 if (error)
240 goto Err;
242 error = TA_sfnt_split_into_SFNT_tables(sfnt, font);
243 if (error)
244 goto Err;
246 error = TA_sfnt_split_glyf_table(sfnt, font);
247 if (error)
248 goto Err;
250 /* check permission */
251 if (sfnt->OS2_idx != MISSING)
253 SFNT_Table* OS2_table = &font->tables[sfnt->OS2_idx];
256 /* check lower byte of the `fsType' field */
257 if (OS2_table->buf[OS2_FSTYPE_OFFSET + 1] == 0x02
258 && !font->ignore_permissions)
260 error = TA_Err_Missing_Legal_Permission;
261 goto Err;
266 /* build `gasp' table */
267 error = TA_sfnt_build_gasp_table(&font->sfnts[0], font);
268 if (error)
269 goto Err;
271 /* XXX handle subfonts for bytecode tables */
273 /* build `cvt ' table */
274 error = TA_sfnt_build_cvt_table(&font->sfnts[0], font);
275 if (error)
276 goto Err;
278 /* build `fpgm' table */
279 error = TA_sfnt_build_fpgm_table(&font->sfnts[0], font);
280 if (error)
281 goto Err;
283 /* build `prep' table */
284 error = TA_sfnt_build_prep_table(&font->sfnts[0], font);
285 if (error)
286 goto Err;
288 /* hint the glyphs and build bytecode */
289 error = TA_sfnt_build_glyf_hints(&font->sfnts[0], font);
290 if (error)
291 goto Err;
293 /* loop again over subfonts */
294 for (i = 0; i < font->num_sfnts; i++)
296 SFNT* sfnt = &font->sfnts[i];
299 error = TA_sfnt_build_glyf_table(sfnt, font);
300 if (error)
301 goto Err;
302 error = TA_sfnt_build_loca_table(sfnt, font);
303 if (error)
304 goto Err;
305 error = TA_sfnt_update_maxp_table(sfnt, font);
306 if (error)
307 goto Err;
310 if (font->num_sfnts == 1)
311 error = TA_font_build_TTF(font);
312 else
313 error = TA_font_build_TTC(font);
314 if (error)
315 goto Err;
317 if (out_file)
319 error = TA_font_file_write(font, out_file);
320 if (error)
321 goto Err;
323 else
325 *out_bufp = (char*)font->out_buf;
326 *out_lenp = font->out_len;
329 error = TA_Err_Ok;
331 Err:
332 TA_font_unload(font, in_buf, out_bufp);
334 Err1:
335 if (error_stringp)
336 *error_stringp = (const unsigned char*)TA_get_error_message(error);
338 return error;
341 /* end of ttfautohint.c */