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. */
26 #define COMPARE(str) (len == (sizeof (str) - 1) \
27 && !strncmp(start, str, sizeof (str) - 1))
31 TTF_autohint(const char* options
,
41 FILE* out_file
= NULL
;
43 const char* in_buf
= NULL
;
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
;
57 FT_Bool ignore_permissions
= 0;
58 FT_Bool pre_hinting
= 0;
59 FT_Bool increase_x_height
= 0;
60 FT_UInt fallback_script
= 0;
65 if (!options
|| !*options
)
67 error
= FT_Err_Invalid_Argument
;
72 va_start(ap
, options
);
85 while (*op
&& *op
!= ',')
88 /* remove leading whitespace */
89 while (isspace(*start
))
92 /* check for empty option */
98 /* the `COMPARE' macro uses `len' and `start' */
101 if (COMPARE("error-string"))
102 error_stringp
= va_arg(ap
, const unsigned char**);
103 else if (COMPARE("fallback-script"))
104 fallback_script
= va_arg(ap
, FT_UInt
);
105 else if (COMPARE("hinting-limit"))
106 hinting_limit
= (FT_Long
)va_arg(ap
, FT_UInt
);
107 else if (COMPARE("hinting-range-max"))
108 hinting_range_max
= (FT_Long
)va_arg(ap
, FT_UInt
);
109 else if (COMPARE("hinting-range-min"))
110 hinting_range_min
= (FT_Long
)va_arg(ap
, FT_UInt
);
111 else if (COMPARE("ignore-permissions"))
112 ignore_permissions
= (FT_Bool
)va_arg(ap
, FT_Int
);
113 else if (COMPARE("in-buffer"))
116 in_buf
= va_arg(ap
, const char*);
118 else if (COMPARE("in-buffer-len"))
121 in_len
= va_arg(ap
, size_t);
123 else if (COMPARE("in-file"))
125 in_file
= va_arg(ap
, FILE*);
129 else if (COMPARE("increase-x-height"))
130 increase_x_height
= (FT_Bool
)va_arg(ap
, FT_Int
);
131 else if (COMPARE("out-buffer"))
134 out_bufp
= va_arg(ap
, char**);
136 else if (COMPARE("out-buffer-len"))
139 out_lenp
= va_arg(ap
, size_t*);
141 else if (COMPARE("out-file"))
143 out_file
= va_arg(ap
, FILE*);
147 else if (COMPARE("pre-hinting"))
148 pre_hinting
= (FT_Bool
)va_arg(ap
, FT_Int
);
149 else if (COMPARE("progress-callback"))
150 progress
= va_arg(ap
, TA_Progress_Func
);
151 else if (COMPARE("progress-callback-data"))
152 progress_data
= va_arg(ap
, void*);
155 x-height-snapping-exceptions
169 || (in_buf
&& in_len
)))
171 error
= FT_Err_Invalid_Argument
;
176 || (out_bufp
&& out_lenp
)))
178 error
= FT_Err_Invalid_Argument
;
182 font
= (FONT
*)calloc(1, sizeof (FONT
));
185 error
= FT_Err_Out_Of_Memory
;
189 if (hinting_range_min
>= 0 && hinting_range_min
< 2)
191 error
= FT_Err_Invalid_Argument
;
194 if (hinting_range_min
< 0)
195 hinting_range_min
= TA_HINTING_RANGE_MIN
;
197 if (hinting_range_max
>= 0 && hinting_range_max
< hinting_range_min
)
199 error
= FT_Err_Invalid_Argument
;
202 if (hinting_range_max
< 0)
203 hinting_range_max
= TA_HINTING_RANGE_MAX
;
205 /* value 0 is valid */
206 if (hinting_limit
> 0 && hinting_limit
< hinting_range_max
)
208 error
= FT_Err_Invalid_Argument
;
211 if (hinting_limit
< 0)
212 hinting_limit
= TA_HINTING_LIMIT
;
214 font
->hinting_range_min
= (FT_UInt
)hinting_range_min
;
215 font
->hinting_range_max
= (FT_UInt
)hinting_range_max
;
216 font
->hinting_limit
= (FT_UInt
)hinting_limit
;
218 font
->progress
= progress
;
219 font
->progress_data
= progress_data
;
221 font
->ignore_permissions
= ignore_permissions
;
222 font
->pre_hinting
= pre_hinting
;
223 font
->increase_x_height
= increase_x_height
;
224 /* restrict value to two bits */
225 font
->fallback_script
= fallback_script
& 3;
227 /* now start with processing the data */
231 error
= TA_font_file_read(font
, in_file
);
237 /* a valid TTF can never be that small */
240 error
= FT_Err_Invalid_Argument
;
243 font
->in_buf
= (FT_Byte
*)in_buf
;
244 font
->in_len
= in_len
;
247 error
= TA_font_init(font
);
251 /* loop over subfonts */
252 for (i
= 0; i
< font
->num_sfnts
; i
++)
254 SFNT
* sfnt
= &font
->sfnts
[i
];
258 error
= FT_New_Memory_Face(font
->lib
, font
->in_buf
, font
->in_len
,
261 /* assure that the font hasn't been already processed by ttfautohint */
262 idx
= FT_Get_Name_Index(sfnt
->face
, TTFAUTOHINT_GLYPH
);
265 error
= TA_Err_Already_Processed
;
272 error
= TA_sfnt_split_into_SFNT_tables(sfnt
, font
);
276 if (font
->pre_hinting
)
277 error
= TA_sfnt_create_glyf_data(sfnt
, font
);
279 error
= TA_sfnt_split_glyf_table(sfnt
, font
);
283 /* check permission */
284 if (sfnt
->OS2_idx
!= MISSING
)
286 SFNT_Table
* OS2_table
= &font
->tables
[sfnt
->OS2_idx
];
289 /* check lower byte of the `fsType' field */
290 if (OS2_table
->buf
[OS2_FSTYPE_OFFSET
+ 1] == 0x02
291 && !font
->ignore_permissions
)
293 error
= TA_Err_Missing_Legal_Permission
;
299 /* build `gasp' table */
300 error
= TA_sfnt_build_gasp_table(&font
->sfnts
[0], font
);
304 /* XXX handle subfonts for bytecode tables */
306 /* build `cvt ' table */
307 error
= TA_sfnt_build_cvt_table(&font
->sfnts
[0], font
);
311 /* build `fpgm' table */
312 error
= TA_sfnt_build_fpgm_table(&font
->sfnts
[0], font
);
316 /* build `prep' table */
317 error
= TA_sfnt_build_prep_table(&font
->sfnts
[0], font
);
321 /* hint the glyphs and build bytecode */
322 error
= TA_sfnt_build_glyf_hints(&font
->sfnts
[0], font
);
326 /* loop again over subfonts */
327 for (i
= 0; i
< font
->num_sfnts
; i
++)
329 SFNT
* sfnt
= &font
->sfnts
[i
];
332 error
= TA_sfnt_build_glyf_table(sfnt
, font
);
335 error
= TA_sfnt_build_loca_table(sfnt
, font
);
338 error
= TA_sfnt_update_maxp_table(sfnt
, font
);
342 /* we add one glyph for composites */
343 if (sfnt
->max_components
&& !font
->pre_hinting
)
345 error
= TA_sfnt_update_hmtx_table(sfnt
, font
);
348 error
= TA_sfnt_update_post_table(sfnt
, font
);
351 error
= TA_sfnt_update_GPOS_table(sfnt
, font
);
357 if (font
->num_sfnts
== 1)
358 error
= TA_font_build_TTF(font
);
360 error
= TA_font_build_TTC(font
);
366 error
= TA_font_file_write(font
, out_file
);
372 *out_bufp
= (char*)font
->out_buf
;
373 *out_lenp
= font
->out_len
;
379 TA_font_unload(font
, in_buf
, out_bufp
);
383 *error_stringp
= (const unsigned char*)TA_get_error_message(error
);
388 /* end of ttfautohint.c */