Add code to properly scale glyphs not handled by the autohinter.
[ttfautohint.git] / src / taprep.c
blobcb6405c18f4082d267af87146ebf2188eb642291
1 /* taprep.c */
3 /* written 2011 by Werner Lemberg <wl@gnu.org> */
5 #include "tabytecode.h"
8 #define PREP(snippet_name) prep_ ## snippet_name
10 /* we often need 0x10000 which can't be pushed directly onto the stack, */
11 /* thus we provide it in the storage area */
13 unsigned char PREP(store_0x10000) [] = {
15 PUSHB_1,
16 sal_0x10000,
17 PUSHW_2,
18 0x08, /* 0x800 */
19 0x00,
20 0x08, /* 0x800 */
21 0x00,
22 MUL, /* 0x10000 */
23 WS,
27 unsigned char PREP(align_top_a) [] = {
29 /* optimize the alignment of the top of small letters to the pixel grid */
31 PUSHB_1,
35 /* %c, index of alignment blue zone */
37 unsigned char PREP(align_top_b) [] = {
39 RCVT,
40 DUP,
41 DUP,
42 PUSHB_1,
43 40,
44 ADD,
45 FLOOR, /* fitted = FLOOR(scaled + 40) */
46 DUP, /* s: scaled scaled fitted fitted */
47 ROLL,
48 NEQ,
49 IF, /* s: scaled fitted */
50 PUSHB_1,
51 sal_0x10000,
52 RS,
53 MUL, /* scaled in 16.16 format */
54 SWAP,
55 DIV, /* (fitted / scaled) in 16.16 format */
57 PUSHB_1,
58 sal_scale,
59 SWAP,
60 WS,
64 unsigned char PREP(loop_cvt_a) [] = {
66 /* loop over vertical CVT entries */
67 PUSHB_4,
71 /* %c, first vertical index */
72 /* %c, last vertical index */
74 unsigned char PREP(loop_cvt_b) [] = {
76 bci_cvt_rescale,
77 bci_loop,
78 CALL,
80 /* loop over blue refs */
81 PUSHB_4,
85 /* %c, first blue ref index */
86 /* %c, last blue ref index */
88 unsigned char PREP(loop_cvt_c) [] = {
90 bci_cvt_rescale,
91 bci_loop,
92 CALL,
94 /* loop over blue shoots */
95 PUSHB_4,
99 /* %c, first blue shoot index */
100 /* %c, last blue shoot index */
102 unsigned char PREP(loop_cvt_d) [] = {
104 bci_cvt_rescale,
105 bci_loop,
106 CALL,
108 ELSE,
109 PUSHB_2,
110 sal_scale,
111 sal_0x10000,
114 EIF,
118 unsigned char PREP(compute_extra_light_a) [] = {
120 /* compute (vertical) `extra_light' flag */
121 PUSHB_3,
122 sal_is_extra_light,
127 /* %c, index of vertical standard_width */
129 unsigned char PREP(compute_extra_light_b) [] = {
131 RCVT,
132 GT, /* standard_width < 40 */
137 unsigned char PREP(round_blues_a) [] = {
139 /* use discrete values for blue zone widths */
140 PUSHB_4,
144 /* %c, first blue ref index */
145 /* %c, last blue ref index */
147 unsigned char PREP(round_blues_b) [] = {
149 bci_blue_round,
150 bci_loop,
151 CALL
156 #define COPY_PREP(snippet_name) \
157 memcpy(buf_p, prep_ ## snippet_name, \
158 sizeof (prep_ ## snippet_name)); \
159 buf_p += sizeof (prep_ ## snippet_name);
161 static FT_Error
162 TA_table_build_prep(FT_Byte** prep,
163 FT_ULong* prep_len,
164 FONT* font)
166 TA_LatinAxis vaxis;
167 TA_LatinBlue blue_adjustment;
168 FT_UInt i;
170 FT_UInt buf_len;
171 FT_UInt len;
172 FT_Byte* buf;
173 FT_Byte* buf_p;
176 vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1];
177 blue_adjustment = NULL;
179 for (i = 0; i < vaxis->blue_count; i++)
181 if (vaxis->blues[i].flags & TA_LATIN_BLUE_ADJUSTMENT)
183 blue_adjustment = &vaxis->blues[i];
184 break;
188 buf_len = sizeof (PREP(store_0x10000));
190 if (blue_adjustment)
191 buf_len += sizeof (PREP(align_top_a))
193 + sizeof (PREP(align_top_b))
194 + sizeof (PREP(loop_cvt_a))
196 + sizeof (PREP(loop_cvt_b))
198 + sizeof (PREP(loop_cvt_c))
200 + sizeof (PREP(loop_cvt_d));
202 buf_len += sizeof (PREP(compute_extra_light_a))
204 + sizeof (PREP(compute_extra_light_b));
206 if (CVT_BLUES_SIZE(font))
207 buf_len += sizeof (PREP(round_blues_a))
209 + sizeof (PREP(round_blues_b));
211 /* buffer length must be a multiple of four */
212 len = (buf_len + 3) & ~3;
213 buf = (FT_Byte*)malloc(len);
214 if (!buf)
215 return FT_Err_Out_Of_Memory;
217 /* pad end of buffer with zeros */
218 buf[len - 1] = 0x00;
219 buf[len - 2] = 0x00;
220 buf[len - 3] = 0x00;
222 /* copy cvt program into buffer and fill in the missing variables */
223 buf_p = buf;
225 COPY_PREP(store_0x10000);
227 if (blue_adjustment)
229 COPY_PREP(align_top_a);
230 *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font)
231 + blue_adjustment - vaxis->blues);
232 COPY_PREP(align_top_b);
234 COPY_PREP(loop_cvt_a);
235 *(buf_p++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font);
236 *(buf_p++) = (unsigned char)(CVT_VERT_WIDTHS_OFFSET(font)
237 + CVT_VERT_WIDTHS_SIZE(font) - 1);
238 COPY_PREP(loop_cvt_b);
239 *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
240 *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font)
241 + CVT_BLUES_SIZE(font) - 1);
242 COPY_PREP(loop_cvt_c);
243 *(buf_p++) = (unsigned char)CVT_BLUE_SHOOTS_OFFSET(font);
244 *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font)
245 + CVT_BLUES_SIZE(font) - 1);
246 COPY_PREP(loop_cvt_d);
249 COPY_PREP(compute_extra_light_a);
250 *(buf_p++) = (unsigned char)CVT_VERT_STANDARD_WIDTH_OFFSET(font);
251 COPY_PREP(compute_extra_light_b);
253 if (CVT_BLUES_SIZE(font))
255 COPY_PREP(round_blues_a);
256 *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
257 *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font)
258 + CVT_BLUES_SIZE(font) - 1);
259 COPY_PREP(round_blues_b);
262 *prep = buf;
263 *prep_len = buf_len;
265 return FT_Err_Ok;
269 FT_Error
270 TA_sfnt_build_prep_table(SFNT* sfnt,
271 FONT* font)
273 FT_Error error;
275 FT_Byte* prep_buf;
276 FT_ULong prep_len;
279 error = TA_sfnt_add_table_info(sfnt);
280 if (error)
281 return error;
283 error = TA_table_build_prep(&prep_buf, &prep_len, font);
284 if (error)
285 return error;
287 /* in case of success, `prep_buf' gets linked */
288 /* and is eventually freed in `TA_font_unload' */
289 error = TA_font_add_table(font,
290 &sfnt->table_infos[sfnt->num_table_infos - 1],
291 TTAG_prep, prep_len, prep_buf);
292 if (error)
294 free(prep_buf);
295 return error;
298 return FT_Err_Ok;
301 /* end of taprep.c */