Version 0.6.1.
[ttfautohint.git] / src / taprep.c
blob6fd936a8c6df8c61c3d009ee086e424e70ba9f60
1 /* taprep.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 #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 CVT 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
174 unsigned char PREP(set_dropout_mode) [] = {
176 PUSHW_1,
177 0x01, /* 0x01FF, activate dropout handling unconditionally */
178 0xFF,
179 SCANCTRL,
180 PUSHB_1,
181 4, /* smart dropout include stubs */
182 SCANTYPE,
186 unsigned char PREP(reset_component_counter) [] = {
188 /* In case an application tries to render `.ttfautohint' */
189 /* (which it should never do), */
190 /* hinting of all glyphs rendered afterwards is disabled */
191 /* because the `cvtl_is_subglyph' counter gets incremented, */
192 /* but there is no counterpart to decrement it. */
193 /* Font inspection tools like the FreeType demo programs */
194 /* are an exception to that rule, however, */
195 /* since they can directly access a font by glyph indices. */
196 /* The following guard alleviates the problem a bit: */
197 /* Any change of the graphics state */
198 /* (for example, rendering at a different size or with a different mode) */
199 /* resets the counter to zero. */
200 PUSHB_2,
201 cvtl_is_subglyph,
203 WCVTP,
208 #define COPY_PREP(snippet_name) \
209 memcpy(buf_p, prep_ ## snippet_name, \
210 sizeof (prep_ ## snippet_name)); \
211 buf_p += sizeof (prep_ ## snippet_name);
213 static FT_Error
214 TA_table_build_prep(FT_Byte** prep,
215 FT_ULong* prep_len,
216 FONT* font)
218 TA_LatinAxis vaxis;
219 TA_LatinBlue blue_adjustment;
220 FT_UInt i;
222 FT_UInt buf_len;
223 FT_UInt len;
224 FT_Byte* buf;
225 FT_Byte* buf_p;
228 vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1];
229 blue_adjustment = NULL;
231 for (i = 0; i < vaxis->blue_count; i++)
233 if (vaxis->blues[i].flags & TA_LATIN_BLUE_ADJUSTMENT)
235 blue_adjustment = &vaxis->blues[i];
236 break;
240 buf_len = sizeof (PREP(store_0x10000));
242 if (blue_adjustment)
243 buf_len += sizeof (PREP(align_top_a))
245 + sizeof (PREP(align_top_b))
246 + sizeof (PREP(loop_cvt_a))
248 + sizeof (PREP(loop_cvt_b))
250 + sizeof (PREP(loop_cvt_c))
252 + sizeof (PREP(loop_cvt_d));
254 buf_len += sizeof (PREP(compute_extra_light_a))
256 + sizeof (PREP(compute_extra_light_b));
258 if (CVT_BLUES_SIZE(font))
259 buf_len += sizeof (PREP(round_blues_a))
261 + sizeof (PREP(round_blues_b));
263 buf_len += sizeof (PREP(set_dropout_mode));
264 buf_len += sizeof (PREP(reset_component_counter));
266 /* buffer length must be a multiple of four */
267 len = (buf_len + 3) & ~3;
268 buf = (FT_Byte*)malloc(len);
269 if (!buf)
270 return FT_Err_Out_Of_Memory;
272 /* pad end of buffer with zeros */
273 buf[len - 1] = 0x00;
274 buf[len - 2] = 0x00;
275 buf[len - 3] = 0x00;
277 /* copy cvt program into buffer and fill in the missing variables */
278 buf_p = buf;
280 COPY_PREP(store_0x10000);
282 if (blue_adjustment)
284 COPY_PREP(align_top_a);
285 *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font)
286 + blue_adjustment - vaxis->blues);
287 COPY_PREP(align_top_b);
289 COPY_PREP(loop_cvt_a);
290 *(buf_p++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font);
291 *(buf_p++) = (unsigned char)(CVT_VERT_WIDTHS_OFFSET(font)
292 + CVT_VERT_WIDTHS_SIZE(font) - 1);
293 COPY_PREP(loop_cvt_b);
294 *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
295 *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font)
296 + CVT_BLUES_SIZE(font) - 1);
297 COPY_PREP(loop_cvt_c);
298 *(buf_p++) = (unsigned char)CVT_BLUE_SHOOTS_OFFSET(font);
299 *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font)
300 + CVT_BLUES_SIZE(font) - 1);
301 COPY_PREP(loop_cvt_d);
304 COPY_PREP(compute_extra_light_a);
305 *(buf_p++) = (unsigned char)CVT_VERT_STANDARD_WIDTH_OFFSET(font);
306 COPY_PREP(compute_extra_light_b);
308 if (CVT_BLUES_SIZE(font))
310 COPY_PREP(round_blues_a);
311 *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
312 *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font)
313 + CVT_BLUES_SIZE(font) - 1);
314 COPY_PREP(round_blues_b);
317 COPY_PREP(set_dropout_mode);
318 COPY_PREP(reset_component_counter);
320 *prep = buf;
321 *prep_len = buf_len;
323 return FT_Err_Ok;
327 FT_Error
328 TA_sfnt_build_prep_table(SFNT* sfnt,
329 FONT* font)
331 FT_Error error;
333 FT_Byte* prep_buf;
334 FT_ULong prep_len;
337 error = TA_sfnt_add_table_info(sfnt);
338 if (error)
339 return error;
341 error = TA_table_build_prep(&prep_buf, &prep_len, font);
342 if (error)
343 return error;
345 #if 0
346 /* ttfautohint's bytecode in `fpgm' is larger */
347 /* than the bytecode in `prep'; */
348 /* this commented out code here is just for completeness */
349 if (prep_len > sfnt->max_instructions)
350 sfnt->max_instructions = prep_len;
351 #endif
353 /* in case of success, `prep_buf' gets linked */
354 /* and is eventually freed in `TA_font_unload' */
355 error = TA_font_add_table(font,
356 &sfnt->table_infos[sfnt->num_table_infos - 1],
357 TTAG_prep, prep_len, prep_buf);
358 if (error)
360 free(prep_buf);
361 return error;
364 return FT_Err_Ok;
367 /* end of taprep.c */