s/lower_upper/upper_lower/.
[ttfautohint.git] / lib / taprep.c
blob85c19d9bfe3af5d1649fe3b7bdef8814a4076d9e
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
22 unsigned char PREP(hinting_limit_a) [] =
25 /* first of all, check whether we do hinting at all */
27 MPPEM,
28 PUSHW_1,
32 /* %d, hinting size limit */
34 unsigned char PREP(hinting_limit_b) [] =
37 GT,
38 IF,
39 PUSHB_2,
40 1, /* switch off hinting */
42 INSTCTRL,
43 EIF,
47 /* we often need 0x10000 which can't be pushed directly onto the stack, */
48 /* thus we provide it in the CVT as `cvtl_0x10000'; */
49 /* at the same time, we store it in CVT index `cvtl_funits_to_pixels' also */
50 /* as a scaled value to have a conversion factor from FUnits to pixels */
52 unsigned char PREP(store_0x10000) [] =
55 PUSHW_2,
56 0x08, /* 0x800 */
57 0x00,
58 0x08, /* 0x800 */
59 0x00,
60 MUL, /* 0x10000 */
62 DUP,
63 PUSHB_1,
64 cvtl_0x10000,
65 SWAP,
66 WCVTP,
68 DUP,
69 PUSHB_1,
70 cvtl_funits_to_pixels,
71 SWAP,
72 WCVTF, /* store value 1 in 16.16 format, scaled */
76 unsigned char PREP(align_top_a) [] =
79 /* optimize the alignment of the top of small letters to the pixel grid */
81 PUSHB_1,
85 /* %c, index of alignment blue zone */
87 unsigned char PREP(align_top_b) [] =
90 RCVT,
91 DUP,
92 DUP,
96 unsigned char PREP(align_top_c1) [] =
99 /* this is for option `increase_x_height': */
100 /* apply much `stronger' rounding up of x height for 5 < PPEM < 15 */
101 MPPEM,
102 PUSHB_1,
105 MPPEM,
106 PUSHB_1,
109 AND,
111 PUSHB_1,
112 52, /* threshold = 52 */
114 ELSE,
115 PUSHB_1,
116 40, /* threshold = 40 */
118 EIF,
119 ADD,
120 FLOOR, /* fitted = FLOOR(scaled + threshold) */
124 unsigned char PREP(align_top_c2) [] =
127 PUSHB_1,
129 ADD,
130 FLOOR, /* fitted = FLOOR(scaled + 40) */
134 unsigned char PREP(align_top_d) [] =
137 DUP, /* s: scaled scaled fitted fitted */
138 ROLL,
139 NEQ,
140 IF, /* s: scaled fitted */
141 PUSHB_1,
143 CINDEX,
144 SUB, /* s: scaled (fitted-scaled) */
145 PUSHB_1,
146 cvtl_0x10000,
147 RCVT,
148 MUL, /* (fitted-scaled) in 16.16 format */
149 SWAP,
150 DIV, /* ((fitted-scaled) / scaled) in 16.16 format */
152 PUSHB_1,
153 cvtl_scale,
154 SWAP,
155 WCVTP,
159 unsigned char PREP(loop_cvt_a) [] =
162 /* loop over vertical CVT entries */
163 PUSHB_4,
167 /* %c, first vertical index */
168 /* %c, last vertical index */
170 unsigned char PREP(loop_cvt_b) [] =
173 bci_cvt_rescale,
174 bci_loop,
175 CALL,
177 /* loop over blue refs */
178 PUSHB_4,
182 /* %c, first blue ref index */
183 /* %c, last blue ref index */
185 unsigned char PREP(loop_cvt_c) [] =
188 bci_cvt_rescale,
189 bci_loop,
190 CALL,
192 /* loop over blue shoots */
193 PUSHB_4,
197 /* %c, first blue shoot index */
198 /* %c, last blue shoot index */
200 unsigned char PREP(loop_cvt_d) [] =
203 bci_cvt_rescale,
204 bci_loop,
205 CALL,
206 EIF,
210 unsigned char PREP(compute_extra_light_a) [] =
213 /* compute (vertical) `extra_light' flag */
214 PUSHB_3,
215 cvtl_is_extra_light,
220 /* %c, index of vertical standard_width */
222 unsigned char PREP(compute_extra_light_b) [] =
225 RCVT,
226 GT, /* standard_width < 40 */
227 WCVTP,
231 unsigned char PREP(round_blues_a) [] =
234 /* use discrete values for blue zone widths */
235 PUSHB_4,
239 /* %c, first blue ref index */
240 /* %c, last blue ref index */
242 unsigned char PREP(round_blues_b) [] =
245 bci_blue_round,
246 bci_loop,
247 CALL
251 unsigned char PREP(set_dropout_mode) [] =
254 PUSHW_1,
255 0x01, /* 0x01FF, activate dropout handling unconditionally */
256 0xFF,
257 SCANCTRL,
258 PUSHB_1,
259 4, /* smart dropout include stubs */
260 SCANTYPE,
264 unsigned char PREP(reset_component_counter) [] =
267 /* In case an application tries to render `.ttfautohint' */
268 /* (which it should never do), */
269 /* hinting of all glyphs rendered afterwards is disabled */
270 /* because the `cvtl_is_subglyph' counter gets incremented, */
271 /* but there is no counterpart to decrement it. */
272 /* Font inspection tools like the FreeType demo programs */
273 /* are an exception to that rule, however, */
274 /* since they can directly access a font by glyph indices. */
275 /* The following guard alleviates the problem a bit: */
276 /* Any change of the graphics state */
277 /* (for example, rendering at a different size or with a different mode) */
278 /* resets the counter to zero. */
279 PUSHB_2,
280 cvtl_is_subglyph,
282 WCVTP,
287 #define COPY_PREP(snippet_name) \
288 do { \
289 memcpy(buf_p, prep_ ## snippet_name, \
290 sizeof (prep_ ## snippet_name)); \
291 buf_p += sizeof (prep_ ## snippet_name); \
292 } while (0)
294 static FT_Error
295 TA_table_build_prep(FT_Byte** prep,
296 FT_ULong* prep_len,
297 FONT* font)
299 TA_LatinAxis vaxis;
300 TA_LatinBlue blue_adjustment = NULL;
301 FT_UInt i;
303 FT_UInt buf_len = 0;
304 FT_UInt len;
305 FT_Byte* buf;
306 FT_Byte* buf_p;
309 if (font->loader->hints.metrics->clazz->script == TA_SCRIPT_NONE)
310 vaxis = NULL;
311 else
313 vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1];
315 for (i = 0; i < vaxis->blue_count; i++)
317 if (vaxis->blues[i].flags & TA_LATIN_BLUE_ADJUSTMENT)
319 blue_adjustment = &vaxis->blues[i];
320 break;
325 if (font->hinting_limit)
326 buf_len += sizeof (PREP(hinting_limit_a))
328 + sizeof (PREP(hinting_limit_b));
330 buf_len += sizeof (PREP(store_0x10000));
332 if (blue_adjustment)
333 buf_len += sizeof (PREP(align_top_a))
335 + sizeof (PREP(align_top_b))
336 + (font->increase_x_height ? sizeof (PREP(align_top_c1))
337 : sizeof (PREP(align_top_c2)))
338 + sizeof (PREP(align_top_d))
339 + sizeof (PREP(loop_cvt_a))
341 + sizeof (PREP(loop_cvt_b))
343 + sizeof (PREP(loop_cvt_c))
345 + sizeof (PREP(loop_cvt_d));
347 buf_len += sizeof (PREP(compute_extra_light_a))
349 + sizeof (PREP(compute_extra_light_b));
351 if (CVT_BLUES_SIZE(font))
352 buf_len += sizeof (PREP(round_blues_a))
354 + sizeof (PREP(round_blues_b));
356 buf_len += sizeof (PREP(set_dropout_mode));
357 buf_len += sizeof (PREP(reset_component_counter));
359 /* buffer length must be a multiple of four */
360 len = (buf_len + 3) & ~3;
361 buf = (FT_Byte*)malloc(len);
362 if (!buf)
363 return FT_Err_Out_Of_Memory;
365 /* pad end of buffer with zeros */
366 buf[len - 1] = 0x00;
367 buf[len - 2] = 0x00;
368 buf[len - 3] = 0x00;
370 /* copy cvt program into buffer and fill in the missing variables */
371 buf_p = buf;
373 if (font->hinting_limit)
375 COPY_PREP(hinting_limit_a);
376 *(buf_p++) = HIGH(font->hinting_limit);
377 *(buf_p++) = LOW(font->hinting_limit);
378 COPY_PREP(hinting_limit_b);
381 COPY_PREP(store_0x10000);
383 if (blue_adjustment)
385 COPY_PREP(align_top_a);
386 *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font)
387 + blue_adjustment - vaxis->blues);
388 COPY_PREP(align_top_b);
389 if (font->increase_x_height)
390 COPY_PREP(align_top_c1);
391 else
392 COPY_PREP(align_top_c2);
393 COPY_PREP(align_top_d);
395 COPY_PREP(loop_cvt_a);
396 *(buf_p++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font);
397 *(buf_p++) = (unsigned char)(CVT_VERT_WIDTHS_OFFSET(font)
398 + CVT_VERT_WIDTHS_SIZE(font) - 1);
399 COPY_PREP(loop_cvt_b);
400 *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
401 *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font)
402 + CVT_BLUES_SIZE(font) - 1);
403 COPY_PREP(loop_cvt_c);
404 *(buf_p++) = (unsigned char)CVT_BLUE_SHOOTS_OFFSET(font);
405 *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font)
406 + CVT_BLUES_SIZE(font) - 1);
407 COPY_PREP(loop_cvt_d);
410 COPY_PREP(compute_extra_light_a);
411 *(buf_p++) = (unsigned char)CVT_VERT_STANDARD_WIDTH_OFFSET(font);
412 COPY_PREP(compute_extra_light_b);
414 if (CVT_BLUES_SIZE(font))
416 COPY_PREP(round_blues_a);
417 *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
418 *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font)
419 + CVT_BLUES_SIZE(font) - 1);
420 COPY_PREP(round_blues_b);
423 COPY_PREP(set_dropout_mode);
424 COPY_PREP(reset_component_counter);
426 *prep = buf;
427 *prep_len = buf_len;
429 return FT_Err_Ok;
433 FT_Error
434 TA_sfnt_build_prep_table(SFNT* sfnt,
435 FONT* font)
437 FT_Error error;
439 FT_Byte* prep_buf;
440 FT_ULong prep_len;
443 error = TA_sfnt_add_table_info(sfnt);
444 if (error)
445 return error;
447 error = TA_table_build_prep(&prep_buf, &prep_len, font);
448 if (error)
449 return error;
451 #if 0
452 /* ttfautohint's bytecode in `fpgm' is larger */
453 /* than the bytecode in `prep'; */
454 /* this commented out code here is just for completeness */
455 if (prep_len > sfnt->max_instructions)
456 sfnt->max_instructions = prep_len;
457 #endif
459 /* in case of success, `prep_buf' gets linked */
460 /* and is eventually freed in `TA_font_unload' */
461 error = TA_font_add_table(font,
462 &sfnt->table_infos[sfnt->num_table_infos - 1],
463 TTAG_prep, prep_len, prep_buf);
464 if (error)
466 free(prep_buf);
467 return error;
470 return FT_Err_Ok;
473 /* end of taprep.c */