Fix thinko in handling composite glyphs.
[ttfautohint.git] / src / taprep.c
blobb2e8594a6559a20a56e1620c2e8c0895897eedef
1 /* taprep.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 #include "ta.h"
19 #define PREP(snippet_name) prep_ ## snippet_name
21 /* we often need 0x10000 which can't be pushed directly onto the stack, */
22 /* thus we provide it in the CVS as `cvtl_0x10000'; */
23 /* at the same time, we store it in CVT index `cvtl_funits_to_pixels' also */
24 /* as a scaled value to have a conversion factor from FUnits to pixels */
26 unsigned char PREP(store_0x10000) [] = {
28 PUSHW_2,
29 0x08, /* 0x800 */
30 0x00,
31 0x08, /* 0x800 */
32 0x00,
33 MUL, /* 0x10000 */
35 DUP,
36 PUSHB_1,
37 cvtl_0x10000,
38 SWAP,
39 WCVTP,
41 DUP,
42 PUSHB_1,
43 cvtl_funits_to_pixels,
44 SWAP,
45 WCVTF, /* store value 1 in 16.16 format, scaled */
49 unsigned char PREP(align_top_a) [] = {
51 /* optimize the alignment of the top of small letters to the pixel grid */
53 PUSHB_1,
57 /* %c, index of alignment blue zone */
59 unsigned char PREP(align_top_b) [] = {
61 RCVT,
62 DUP,
63 DUP,
64 PUSHB_1,
65 40,
66 ADD,
67 FLOOR, /* fitted = FLOOR(scaled + 40) */
68 DUP, /* s: scaled scaled fitted fitted */
69 ROLL,
70 NEQ,
71 IF, /* s: scaled fitted */
72 PUSHB_1,
74 CINDEX,
75 SUB, /* s: scaled (fitted-scaled) */
76 PUSHB_1,
77 cvtl_0x10000,
78 RCVT,
79 MUL, /* (fitted-scaled) in 16.16 format */
80 SWAP,
81 DIV, /* ((fitted-scaled) / scaled) in 16.16 format */
83 PUSHB_1,
84 cvtl_scale,
85 SWAP,
86 WCVTP,
90 unsigned char PREP(loop_cvt_a) [] = {
92 /* loop over vertical CVT entries */
93 PUSHB_4,
97 /* %c, first vertical index */
98 /* %c, last vertical index */
100 unsigned char PREP(loop_cvt_b) [] = {
102 bci_cvt_rescale,
103 bci_loop,
104 CALL,
106 /* loop over blue refs */
107 PUSHB_4,
111 /* %c, first blue ref index */
112 /* %c, last blue ref index */
114 unsigned char PREP(loop_cvt_c) [] = {
116 bci_cvt_rescale,
117 bci_loop,
118 CALL,
120 /* loop over blue shoots */
121 PUSHB_4,
125 /* %c, first blue shoot index */
126 /* %c, last blue shoot index */
128 unsigned char PREP(loop_cvt_d) [] = {
130 bci_cvt_rescale,
131 bci_loop,
132 CALL,
133 EIF,
137 unsigned char PREP(compute_extra_light_a) [] = {
139 /* compute (vertical) `extra_light' flag */
140 PUSHB_3,
141 cvtl_is_extra_light,
146 /* %c, index of vertical standard_width */
148 unsigned char PREP(compute_extra_light_b) [] = {
150 RCVT,
151 GT, /* standard_width < 40 */
152 WCVTP,
156 unsigned char PREP(round_blues_a) [] = {
158 /* use discrete values for blue zone widths */
159 PUSHB_4,
163 /* %c, first blue ref index */
164 /* %c, last blue ref index */
166 unsigned char PREP(round_blues_b) [] = {
168 bci_blue_round,
169 bci_loop,
170 CALL
175 #define COPY_PREP(snippet_name) \
176 memcpy(buf_p, prep_ ## snippet_name, \
177 sizeof (prep_ ## snippet_name)); \
178 buf_p += sizeof (prep_ ## snippet_name);
180 static FT_Error
181 TA_table_build_prep(FT_Byte** prep,
182 FT_ULong* prep_len,
183 FONT* font)
185 TA_LatinAxis vaxis;
186 TA_LatinBlue blue_adjustment;
187 FT_UInt i;
189 FT_UInt buf_len;
190 FT_UInt len;
191 FT_Byte* buf;
192 FT_Byte* buf_p;
195 vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1];
196 blue_adjustment = NULL;
198 for (i = 0; i < vaxis->blue_count; i++)
200 if (vaxis->blues[i].flags & TA_LATIN_BLUE_ADJUSTMENT)
202 blue_adjustment = &vaxis->blues[i];
203 break;
207 buf_len = sizeof (PREP(store_0x10000));
209 if (blue_adjustment)
210 buf_len += sizeof (PREP(align_top_a))
212 + sizeof (PREP(align_top_b))
213 + sizeof (PREP(loop_cvt_a))
215 + sizeof (PREP(loop_cvt_b))
217 + sizeof (PREP(loop_cvt_c))
219 + sizeof (PREP(loop_cvt_d));
221 buf_len += sizeof (PREP(compute_extra_light_a))
223 + sizeof (PREP(compute_extra_light_b));
225 if (CVT_BLUES_SIZE(font))
226 buf_len += sizeof (PREP(round_blues_a))
228 + sizeof (PREP(round_blues_b));
230 /* buffer length must be a multiple of four */
231 len = (buf_len + 3) & ~3;
232 buf = (FT_Byte*)malloc(len);
233 if (!buf)
234 return FT_Err_Out_Of_Memory;
236 /* pad end of buffer with zeros */
237 buf[len - 1] = 0x00;
238 buf[len - 2] = 0x00;
239 buf[len - 3] = 0x00;
241 /* copy cvt program into buffer and fill in the missing variables */
242 buf_p = buf;
244 COPY_PREP(store_0x10000);
246 if (blue_adjustment)
248 COPY_PREP(align_top_a);
249 *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font)
250 + blue_adjustment - vaxis->blues);
251 COPY_PREP(align_top_b);
253 COPY_PREP(loop_cvt_a);
254 *(buf_p++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font);
255 *(buf_p++) = (unsigned char)(CVT_VERT_WIDTHS_OFFSET(font)
256 + CVT_VERT_WIDTHS_SIZE(font) - 1);
257 COPY_PREP(loop_cvt_b);
258 *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
259 *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font)
260 + CVT_BLUES_SIZE(font) - 1);
261 COPY_PREP(loop_cvt_c);
262 *(buf_p++) = (unsigned char)CVT_BLUE_SHOOTS_OFFSET(font);
263 *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font)
264 + CVT_BLUES_SIZE(font) - 1);
265 COPY_PREP(loop_cvt_d);
268 COPY_PREP(compute_extra_light_a);
269 *(buf_p++) = (unsigned char)CVT_VERT_STANDARD_WIDTH_OFFSET(font);
270 COPY_PREP(compute_extra_light_b);
272 if (CVT_BLUES_SIZE(font))
274 COPY_PREP(round_blues_a);
275 *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
276 *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font)
277 + CVT_BLUES_SIZE(font) - 1);
278 COPY_PREP(round_blues_b);
281 *prep = buf;
282 *prep_len = buf_len;
284 return FT_Err_Ok;
288 FT_Error
289 TA_sfnt_build_prep_table(SFNT* sfnt,
290 FONT* font)
292 FT_Error error;
294 FT_Byte* prep_buf;
295 FT_ULong prep_len;
298 error = TA_sfnt_add_table_info(sfnt);
299 if (error)
300 return error;
302 error = TA_table_build_prep(&prep_buf, &prep_len, font);
303 if (error)
304 return error;
306 #if 0
307 /* ttfautohint's bytecode in `fpgm' is larger */
308 /* than the bytecode in `prep'; */
309 /* this commented out code here is just for completeness */
310 if (prep_len > sfnt->max_instructions)
311 sfnt->max_instructions = prep_len;
312 #endif
314 /* in case of success, `prep_buf' gets linked */
315 /* and is eventually freed in `TA_font_unload' */
316 error = TA_font_add_table(font,
317 &sfnt->table_infos[sfnt->num_table_infos - 1],
318 TTAG_prep, prep_len, prep_buf);
319 if (error)
321 free(prep_buf);
322 return error;
325 return FT_Err_Ok;
328 /* end of taprep.c */