Some comments.
[ttfautohint.git] / lib / taprep.c
bloba13892aadc688bd99c697c21cc6c60344b05b4fe
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) [] =
29 PUSHW_2,
30 0x08, /* 0x800 */
31 0x00,
32 0x08, /* 0x800 */
33 0x00,
34 MUL, /* 0x10000 */
36 DUP,
37 PUSHB_1,
38 cvtl_0x10000,
39 SWAP,
40 WCVTP,
42 DUP,
43 PUSHB_1,
44 cvtl_funits_to_pixels,
45 SWAP,
46 WCVTF, /* store value 1 in 16.16 format, scaled */
50 unsigned char PREP(align_top_a) [] =
53 /* optimize the alignment of the top of small letters to the pixel grid */
55 PUSHB_1,
59 /* %c, index of alignment blue zone */
61 unsigned char PREP(align_top_b) [] =
64 RCVT,
65 DUP,
66 DUP,
70 unsigned char PREP(align_top_c1) [] =
73 /* this is for option `increase_x_height': */
74 /* apply much `stronger' rounding up of x height for 5 < PPEM < 15 */
75 MPPEM,
76 PUSHB_1,
77 15,
78 LT,
79 MPPEM,
80 PUSHB_1,
82 GT,
83 AND,
84 IF,
85 PUSHB_1,
86 52, /* threshold = 52 */
88 ELSE,
89 PUSHB_1,
90 40, /* threshold = 40 */
92 EIF,
93 ADD,
94 FLOOR, /* fitted = FLOOR(scaled + threshold) */
98 unsigned char PREP(align_top_c2) [] =
101 PUSHB_1,
103 ADD,
104 FLOOR, /* fitted = FLOOR(scaled + 40) */
108 unsigned char PREP(align_top_d) [] =
111 DUP, /* s: scaled scaled fitted fitted */
112 ROLL,
113 NEQ,
114 IF, /* s: scaled fitted */
115 PUSHB_1,
117 CINDEX,
118 SUB, /* s: scaled (fitted-scaled) */
119 PUSHB_1,
120 cvtl_0x10000,
121 RCVT,
122 MUL, /* (fitted-scaled) in 16.16 format */
123 SWAP,
124 DIV, /* ((fitted-scaled) / scaled) in 16.16 format */
126 PUSHB_1,
127 cvtl_scale,
128 SWAP,
129 WCVTP,
133 unsigned char PREP(loop_cvt_a) [] =
136 /* loop over vertical CVT entries */
137 PUSHB_4,
141 /* %c, first vertical index */
142 /* %c, last vertical index */
144 unsigned char PREP(loop_cvt_b) [] =
147 bci_cvt_rescale,
148 bci_loop,
149 CALL,
151 /* loop over blue refs */
152 PUSHB_4,
156 /* %c, first blue ref index */
157 /* %c, last blue ref index */
159 unsigned char PREP(loop_cvt_c) [] =
162 bci_cvt_rescale,
163 bci_loop,
164 CALL,
166 /* loop over blue shoots */
167 PUSHB_4,
171 /* %c, first blue shoot index */
172 /* %c, last blue shoot index */
174 unsigned char PREP(loop_cvt_d) [] =
177 bci_cvt_rescale,
178 bci_loop,
179 CALL,
180 EIF,
184 unsigned char PREP(compute_extra_light_a) [] =
187 /* compute (vertical) `extra_light' flag */
188 PUSHB_3,
189 cvtl_is_extra_light,
194 /* %c, index of vertical standard_width */
196 unsigned char PREP(compute_extra_light_b) [] =
199 RCVT,
200 GT, /* standard_width < 40 */
201 WCVTP,
205 unsigned char PREP(round_blues_a) [] =
208 /* use discrete values for blue zone widths */
209 PUSHB_4,
213 /* %c, first blue ref index */
214 /* %c, last blue ref index */
216 unsigned char PREP(round_blues_b) [] =
219 bci_blue_round,
220 bci_loop,
221 CALL
225 unsigned char PREP(set_dropout_mode) [] =
228 PUSHW_1,
229 0x01, /* 0x01FF, activate dropout handling unconditionally */
230 0xFF,
231 SCANCTRL,
232 PUSHB_1,
233 4, /* smart dropout include stubs */
234 SCANTYPE,
238 unsigned char PREP(reset_component_counter) [] =
241 /* In case an application tries to render `.ttfautohint' */
242 /* (which it should never do), */
243 /* hinting of all glyphs rendered afterwards is disabled */
244 /* because the `cvtl_is_subglyph' counter gets incremented, */
245 /* but there is no counterpart to decrement it. */
246 /* Font inspection tools like the FreeType demo programs */
247 /* are an exception to that rule, however, */
248 /* since they can directly access a font by glyph indices. */
249 /* The following guard alleviates the problem a bit: */
250 /* Any change of the graphics state */
251 /* (for example, rendering at a different size or with a different mode) */
252 /* resets the counter to zero. */
253 PUSHB_2,
254 cvtl_is_subglyph,
256 WCVTP,
261 #define COPY_PREP(snippet_name) \
262 do { \
263 memcpy(buf_p, prep_ ## snippet_name, \
264 sizeof (prep_ ## snippet_name)); \
265 buf_p += sizeof (prep_ ## snippet_name); \
266 } while (0)
268 static FT_Error
269 TA_table_build_prep(FT_Byte** prep,
270 FT_ULong* prep_len,
271 FONT* font)
273 TA_LatinAxis vaxis;
274 TA_LatinBlue blue_adjustment;
275 FT_UInt i;
277 FT_UInt buf_len;
278 FT_UInt len;
279 FT_Byte* buf;
280 FT_Byte* buf_p;
283 vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1];
284 blue_adjustment = NULL;
286 for (i = 0; i < vaxis->blue_count; i++)
288 if (vaxis->blues[i].flags & TA_LATIN_BLUE_ADJUSTMENT)
290 blue_adjustment = &vaxis->blues[i];
291 break;
295 buf_len = sizeof (PREP(store_0x10000));
297 if (blue_adjustment)
298 buf_len += sizeof (PREP(align_top_a))
300 + sizeof (PREP(align_top_b))
301 + (font->increase_x_height ? sizeof (PREP(align_top_c1))
302 : sizeof (PREP(align_top_c2)))
303 + sizeof (PREP(align_top_d))
304 + sizeof (PREP(loop_cvt_a))
306 + sizeof (PREP(loop_cvt_b))
308 + sizeof (PREP(loop_cvt_c))
310 + sizeof (PREP(loop_cvt_d));
312 buf_len += sizeof (PREP(compute_extra_light_a))
314 + sizeof (PREP(compute_extra_light_b));
316 if (CVT_BLUES_SIZE(font))
317 buf_len += sizeof (PREP(round_blues_a))
319 + sizeof (PREP(round_blues_b));
321 buf_len += sizeof (PREP(set_dropout_mode));
322 buf_len += sizeof (PREP(reset_component_counter));
324 /* buffer length must be a multiple of four */
325 len = (buf_len + 3) & ~3;
326 buf = (FT_Byte*)malloc(len);
327 if (!buf)
328 return FT_Err_Out_Of_Memory;
330 /* pad end of buffer with zeros */
331 buf[len - 1] = 0x00;
332 buf[len - 2] = 0x00;
333 buf[len - 3] = 0x00;
335 /* copy cvt program into buffer and fill in the missing variables */
336 buf_p = buf;
338 COPY_PREP(store_0x10000);
340 if (blue_adjustment)
342 COPY_PREP(align_top_a);
343 *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font)
344 + blue_adjustment - vaxis->blues);
345 COPY_PREP(align_top_b);
346 if (font->increase_x_height)
347 COPY_PREP(align_top_c1);
348 else
349 COPY_PREP(align_top_c2);
350 COPY_PREP(align_top_d);
352 COPY_PREP(loop_cvt_a);
353 *(buf_p++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font);
354 *(buf_p++) = (unsigned char)(CVT_VERT_WIDTHS_OFFSET(font)
355 + CVT_VERT_WIDTHS_SIZE(font) - 1);
356 COPY_PREP(loop_cvt_b);
357 *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
358 *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font)
359 + CVT_BLUES_SIZE(font) - 1);
360 COPY_PREP(loop_cvt_c);
361 *(buf_p++) = (unsigned char)CVT_BLUE_SHOOTS_OFFSET(font);
362 *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font)
363 + CVT_BLUES_SIZE(font) - 1);
364 COPY_PREP(loop_cvt_d);
367 COPY_PREP(compute_extra_light_a);
368 *(buf_p++) = (unsigned char)CVT_VERT_STANDARD_WIDTH_OFFSET(font);
369 COPY_PREP(compute_extra_light_b);
371 if (CVT_BLUES_SIZE(font))
373 COPY_PREP(round_blues_a);
374 *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
375 *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font)
376 + CVT_BLUES_SIZE(font) - 1);
377 COPY_PREP(round_blues_b);
380 COPY_PREP(set_dropout_mode);
381 COPY_PREP(reset_component_counter);
383 *prep = buf;
384 *prep_len = buf_len;
386 return FT_Err_Ok;
390 FT_Error
391 TA_sfnt_build_prep_table(SFNT* sfnt,
392 FONT* font)
394 FT_Error error;
396 FT_Byte* prep_buf;
397 FT_ULong prep_len;
400 error = TA_sfnt_add_table_info(sfnt);
401 if (error)
402 return error;
404 error = TA_table_build_prep(&prep_buf, &prep_len, font);
405 if (error)
406 return error;
408 #if 0
409 /* ttfautohint's bytecode in `fpgm' is larger */
410 /* than the bytecode in `prep'; */
411 /* this commented out code here is just for completeness */
412 if (prep_len > sfnt->max_instructions)
413 sfnt->max_instructions = prep_len;
414 #endif
416 /* in case of success, `prep_buf' gets linked */
417 /* and is eventually freed in `TA_font_unload' */
418 error = TA_font_add_table(font,
419 &sfnt->table_infos[sfnt->num_table_infos - 1],
420 TTAG_prep, prep_len, prep_buf);
421 if (error)
423 free(prep_buf);
424 return error;
427 return FT_Err_Ok;
430 /* end of taprep.c */