Split `tabytecode.c' into `tacvt.c', `tafpgm.c', and `taprep.c'.
[ttfautohint.git] / src / taprep.c
blob664695d2682fe95a698b7e038b304de2523e3a98
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,
107 EIF,
111 unsigned char PREP(compute_extra_light_a) [] = {
113 /* compute (vertical) `extra_light' flag */
114 PUSHB_3,
115 sal_is_extra_light,
120 /* %c, index of vertical standard_width */
122 unsigned char PREP(compute_extra_light_b) [] = {
124 RCVT,
125 GT, /* standard_width < 40 */
130 unsigned char PREP(round_blues_a) [] = {
132 /* use discrete values for blue zone widths */
133 PUSHB_4,
137 /* %c, first blue ref index */
138 /* %c, last blue ref index */
140 unsigned char PREP(round_blues_b) [] = {
142 bci_blue_round,
143 bci_loop,
144 CALL
149 #define COPY_PREP(snippet_name) \
150 memcpy(buf_p, prep_ ## snippet_name, \
151 sizeof (prep_ ## snippet_name)); \
152 buf_p += sizeof (prep_ ## snippet_name);
154 static FT_Error
155 TA_table_build_prep(FT_Byte** prep,
156 FT_ULong* prep_len,
157 FONT* font)
159 TA_LatinAxis vaxis;
160 TA_LatinBlue blue_adjustment;
161 FT_UInt i;
163 FT_UInt buf_len;
164 FT_UInt len;
165 FT_Byte* buf;
166 FT_Byte* buf_p;
169 vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1];
170 blue_adjustment = NULL;
172 for (i = 0; i < vaxis->blue_count; i++)
174 if (vaxis->blues[i].flags & TA_LATIN_BLUE_ADJUSTMENT)
176 blue_adjustment = &vaxis->blues[i];
177 break;
181 buf_len = sizeof (PREP(store_0x10000));
183 if (blue_adjustment)
184 buf_len += sizeof (PREP(align_top_a))
186 + sizeof (PREP(align_top_b))
187 + sizeof (PREP(loop_cvt_a))
189 + sizeof (PREP(loop_cvt_b))
191 + sizeof (PREP(loop_cvt_c))
193 + sizeof (PREP(loop_cvt_d));
195 buf_len += sizeof (PREP(compute_extra_light_a))
197 + sizeof (PREP(compute_extra_light_b));
199 if (CVT_BLUES_SIZE(font))
200 buf_len += sizeof (PREP(round_blues_a))
202 + sizeof (PREP(round_blues_b));
204 /* buffer length must be a multiple of four */
205 len = (buf_len + 3) & ~3;
206 buf = (FT_Byte*)malloc(len);
207 if (!buf)
208 return FT_Err_Out_Of_Memory;
210 /* pad end of buffer with zeros */
211 buf[len - 1] = 0x00;
212 buf[len - 2] = 0x00;
213 buf[len - 3] = 0x00;
215 /* copy cvt program into buffer and fill in the missing variables */
216 buf_p = buf;
218 COPY_PREP(store_0x10000);
220 if (blue_adjustment)
222 COPY_PREP(align_top_a);
223 *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font)
224 + blue_adjustment - vaxis->blues);
225 COPY_PREP(align_top_b);
227 COPY_PREP(loop_cvt_a);
228 *(buf_p++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font);
229 *(buf_p++) = (unsigned char)(CVT_VERT_WIDTHS_OFFSET(font)
230 + CVT_VERT_WIDTHS_SIZE(font) - 1);
231 COPY_PREP(loop_cvt_b);
232 *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
233 *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font)
234 + CVT_BLUES_SIZE(font) - 1);
235 COPY_PREP(loop_cvt_c);
236 *(buf_p++) = (unsigned char)CVT_BLUE_SHOOTS_OFFSET(font);
237 *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font)
238 + CVT_BLUES_SIZE(font) - 1);
239 COPY_PREP(loop_cvt_d);
242 COPY_PREP(compute_extra_light_a);
243 *(buf_p++) = (unsigned char)CVT_VERT_STANDARD_WIDTH_OFFSET(font);
244 COPY_PREP(compute_extra_light_b);
246 if (CVT_BLUES_SIZE(font))
248 COPY_PREP(round_blues_a);
249 *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
250 *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font)
251 + CVT_BLUES_SIZE(font) - 1);
252 COPY_PREP(round_blues_b);
255 *prep = buf;
256 *prep_len = buf_len;
258 return FT_Err_Ok;
262 FT_Error
263 TA_sfnt_build_prep_table(SFNT* sfnt,
264 FONT* font)
266 FT_Error error;
268 FT_Byte* prep_buf;
269 FT_ULong prep_len;
272 error = TA_sfnt_add_table_info(sfnt);
273 if (error)
274 return error;
276 error = TA_table_build_prep(&prep_buf, &prep_len, font);
277 if (error)
278 return error;
280 /* in case of success, `prep_buf' gets linked */
281 /* and is eventually freed in `TA_font_unload' */
282 error = TA_font_add_table(font,
283 &sfnt->table_infos[sfnt->num_table_infos - 1],
284 TTAG_prep, prep_len, prep_buf);
285 if (error)
287 free(prep_buf);
288 return error;
291 return FT_Err_Ok;
294 /* end of taprep.c */