Add suggestion from Eben to the TODO file.
[ttfautohint.git] / lib / tacvt.c
blob13816988e0e433266c587fbb4d7fe8ea9590b84f
1 /* tacvt.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 #include "ta.h"
19 static FT_Error
20 TA_sfnt_compute_global_hints(SFNT* sfnt,
21 FONT* font)
23 FT_Error error;
24 FT_Face face = sfnt->face;
25 FT_UInt idx;
26 FT_Int32 load_flags;
29 error = FT_Select_Charmap(face, FT_ENCODING_UNICODE);
30 if (error)
32 if (font->symbol)
34 error = FT_Select_Charmap(face, FT_ENCODING_MS_SYMBOL);
35 if (error)
36 return TA_Err_Missing_Symbol_CMap;
38 else
39 return TA_Err_Missing_Unicode_CMap;
42 if (font->symbol)
43 idx = 0;
44 else
46 /* load glyph `o' to trigger all initializations */
47 /* XXX make this configurable for non-latin scripts */
48 /* XXX make this configurable to use a different letter */
49 idx = FT_Get_Char_Index(face, 'o');
50 if (!idx)
51 return TA_Err_Missing_Glyph;
54 load_flags = 1 << 29; /* vertical hinting only */
55 error = ta_loader_load_glyph(font, face, idx, load_flags);
57 return error;
61 static FT_Error
62 TA_table_build_cvt(FT_Byte** cvt,
63 FT_ULong* cvt_len,
64 SFNT* sfnt,
65 FONT* font)
67 TA_LatinAxis haxis;
68 TA_LatinAxis vaxis;
70 FT_UInt hwidth_count;
71 FT_UInt vwidth_count;
72 FT_UInt blue_count;
74 FT_UInt i;
75 FT_UInt buf_len;
76 FT_UInt len;
77 FT_Byte* buf;
78 FT_Byte* buf_p;
80 FT_Error error;
83 error = TA_sfnt_compute_global_hints(sfnt, font);
84 if (error)
85 return error;
87 if (font->loader->hints.metrics->clazz->script == TA_SCRIPT_DUMMY)
89 haxis = NULL;
90 vaxis = NULL;
92 hwidth_count = 0;
93 vwidth_count = 0;
94 blue_count = 0;
96 else
98 haxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[0];
99 vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1];
101 hwidth_count = haxis->width_count;
102 vwidth_count = vaxis->width_count;
103 blue_count = vaxis->blue_count + 2; /* with artificial blue zones */
106 buf_len = 2 * (cvtl_max_runtime /* runtime values */
107 + 2 /* vertical and horizontal standard width */
108 + hwidth_count
109 + vwidth_count
110 + 2 * blue_count);
112 /* buffer length must be a multiple of four */
113 len = (buf_len + 3) & ~3;
114 buf = (FT_Byte*)malloc(len);
115 if (!buf)
116 return FT_Err_Out_Of_Memory;
118 /* pad end of buffer with zeros */
119 buf[len - 1] = 0x00;
120 buf[len - 2] = 0x00;
121 buf[len - 3] = 0x00;
123 buf_p = buf;
125 /* some CVT values are initialized (and modified) at runtime; */
126 /* see the `cvtl_xxx' macros in tabytecode.h */
127 for (i = 0; i < cvtl_max_runtime; i++)
129 *(buf_p++) = 0;
130 *(buf_p++) = 0;
133 if (hwidth_count > 0)
135 *(buf_p++) = HIGH(haxis->widths[0].org);
136 *(buf_p++) = LOW(haxis->widths[0].org);
138 else
140 *(buf_p++) = 0;
141 *(buf_p++) = 50;
143 if (vwidth_count > 0)
145 *(buf_p++) = HIGH(vaxis->widths[0].org);
146 *(buf_p++) = LOW(vaxis->widths[0].org);
148 else
150 *(buf_p++) = 0;
151 *(buf_p++) = 50;
154 for (i = 0; i < hwidth_count; i++)
156 if (haxis->widths[i].org > 0xFFFF)
157 goto Err;
158 *(buf_p++) = HIGH(haxis->widths[i].org);
159 *(buf_p++) = LOW(haxis->widths[i].org);
162 for (i = 0; i < vwidth_count; i++)
164 if (vaxis->widths[i].org > 0xFFFF)
165 goto Err;
166 *(buf_p++) = HIGH(vaxis->widths[i].org);
167 *(buf_p++) = LOW(vaxis->widths[i].org);
170 for (i = 0; i < blue_count; i++)
172 if (vaxis->blues[i].ref.org > 0xFFFF)
173 goto Err;
174 *(buf_p++) = HIGH(vaxis->blues[i].ref.org);
175 *(buf_p++) = LOW(vaxis->blues[i].ref.org);
178 for (i = 0; i < blue_count; i++)
180 if (vaxis->blues[i].shoot.org > 0xFFFF)
181 goto Err;
182 *(buf_p++) = HIGH(vaxis->blues[i].shoot.org);
183 *(buf_p++) = LOW(vaxis->blues[i].shoot.org);
186 *cvt = buf;
187 *cvt_len = buf_len;
189 return FT_Err_Ok;
191 Err:
192 free(buf);
193 return TA_Err_Hinter_Overflow;
197 FT_Error
198 TA_sfnt_build_cvt_table(SFNT* sfnt,
199 FONT* font)
201 FT_Error error = FT_Err_Ok;
203 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
204 glyf_Data* data = (glyf_Data*)glyf_table->data;
206 FT_Byte* cvt_buf;
207 FT_ULong cvt_len;
210 error = TA_sfnt_add_table_info(sfnt);
211 if (error)
212 goto Exit;
214 /* `glyf', `cvt', `fpgm', and `prep' are always used in parallel */
215 if (glyf_table->processed)
217 sfnt->table_infos[sfnt->num_table_infos - 1] = data->cvt_idx;
218 goto Exit;
221 error = TA_table_build_cvt(&cvt_buf, &cvt_len, sfnt, font);
222 if (error)
223 goto Exit;
225 /* in case of success, `cvt_buf' gets linked */
226 /* and is eventually freed in `TA_font_unload' */
227 error = TA_font_add_table(font,
228 &sfnt->table_infos[sfnt->num_table_infos - 1],
229 TTAG_cvt, cvt_len, cvt_buf);
230 if (error)
231 free(cvt_buf);
232 else
233 data->cvt_idx = sfnt->table_infos[sfnt->num_table_infos - 1];
235 Exit:
236 return error;
239 /* end of tacvt.c */