Synchronize with FreeType.
[ttfautohint.git] / lib / taprep.c
blob91b58618dd91fb64972ccc07f0404b2463923ed6
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_c1a) [] =
99 /* use this if option `increase_x_height' > 0 */
100 /* apply much `stronger' rounding up of x height for */
101 /* 6 <= PPEM <= increase_x_height */
102 MPPEM,
103 PUSHB_1,
107 /* %c, x height increase limit */
109 unsigned char PREP(align_top_c1b) [] =
112 LTEQ,
113 MPPEM,
114 PUSHB_1,
116 GTEQ,
117 AND,
119 PUSHB_1,
120 52, /* threshold = 52 */
122 ELSE,
123 PUSHB_1,
124 40, /* threshold = 40 */
126 EIF,
127 ADD,
128 FLOOR, /* fitted = FLOOR(scaled + threshold) */
132 unsigned char PREP(align_top_c2) [] =
135 PUSHB_1,
137 ADD,
138 FLOOR, /* fitted = FLOOR(scaled + 40) */
142 unsigned char PREP(align_top_d) [] =
145 DUP, /* s: scaled scaled fitted fitted */
146 ROLL,
147 NEQ,
148 IF, /* s: scaled fitted */
149 PUSHB_1,
151 CINDEX,
152 SUB, /* s: scaled (fitted-scaled) */
153 PUSHB_1,
154 cvtl_0x10000,
155 RCVT,
156 MUL, /* (fitted-scaled) in 16.16 format */
157 SWAP,
158 DIV, /* ((fitted-scaled) / scaled) in 16.16 format */
160 PUSHB_1,
161 cvtl_scale,
162 SWAP,
163 WCVTP,
167 unsigned char PREP(loop_cvt_a) [] =
170 /* loop over vertical CVT entries */
171 PUSHB_4,
175 /* %c, first vertical index */
176 /* %c, last vertical index */
178 unsigned char PREP(loop_cvt_b) [] =
181 bci_cvt_rescale,
182 bci_loop,
183 CALL,
185 /* loop over blue refs */
186 PUSHB_4,
190 /* %c, first blue ref index */
191 /* %c, last blue ref index */
193 unsigned char PREP(loop_cvt_c) [] =
196 bci_cvt_rescale,
197 bci_loop,
198 CALL,
200 /* loop over blue shoots */
201 PUSHB_4,
205 /* %c, first blue shoot index */
206 /* %c, last blue shoot index */
208 unsigned char PREP(loop_cvt_d) [] =
211 bci_cvt_rescale,
212 bci_loop,
213 CALL,
214 EIF,
218 unsigned char PREP(compute_extra_light_a) [] =
221 /* compute (vertical) `extra_light' flag */
222 PUSHB_3,
223 cvtl_is_extra_light,
228 /* %c, index of vertical standard_width */
230 unsigned char PREP(compute_extra_light_b) [] =
233 RCVT,
234 GT, /* standard_width < 40 */
235 WCVTP,
239 unsigned char PREP(round_blues_a) [] =
242 /* use discrete values for blue zone widths */
243 PUSHB_4,
247 /* %c, first blue ref index */
248 /* %c, last blue ref index */
250 unsigned char PREP(round_blues_b) [] =
253 bci_blue_round,
254 bci_loop,
255 CALL
259 unsigned char PREP(set_stem_width_handling_a) [] =
263 * There are two ClearType flavours available on Windows: The older GDI
264 * ClearType, introduced in 2000, and the recent DW ClearType, introduced
265 * in 2008. The main difference is that the older incarnation behaves
266 * like a B/W renderer along the y axis, while the newer version does
267 * vertical smoothing also.
269 * The only possibility to differentiate between GDI and DW ClearType is
270 * testing bit 10 in the GETINFO instruction (with return value in bit 17;
271 * this works for TrueType version >= 38), checking whether sub-pixel
272 * positioning is available.
274 * If GDI ClearType is active, we use a different stem width function
275 * which snaps to integer pixels as much as possible.
278 /* set default positioning */
279 PUSHB_2,
280 cvtl_stem_width_function,
284 /* %d, either bci_smooth_stem_width or bci_strong_stem_width */
286 unsigned char PREP(set_stem_width_handling_b) [] =
289 WCVTP,
291 /* get rasterizer version (bit 0) */
292 PUSHB_2,
294 0x01,
295 GETINFO,
297 /* `GDI ClearType': */
298 /* version >= 36 and version < 38, ClearType enabled */
299 LTEQ,
301 /* check whether ClearType is enabled (bit 6) */
302 PUSHB_1,
303 0x40,
304 GETINFO,
306 PUSHB_2,
307 cvtl_stem_width_function,
310 /* %d, either bci_smooth_stem_width or bci_strong_stem_width */
312 unsigned char PREP(set_stem_width_handling_c) [] =
315 WCVTP,
317 /* get rasterizer version (bit 0) */
318 PUSHB_2,
320 0x01,
321 GETINFO,
323 /* `DW ClearType': */
324 /* version >= 38, sub-pixel positioning is enabled */
325 LTEQ,
327 /* check whether sub-pixel positioning is enabled (bit 10) */
328 PUSHW_1,
329 0x04,
330 0x00,
331 GETINFO,
333 PUSHB_2,
334 cvtl_stem_width_function,
338 /* %d, either bci_smooth_stem_width or bci_strong_stem_width */
340 unsigned char PREP(set_stem_width_handling_d) [] =
343 WCVTP,
344 EIF,
345 EIF,
346 EIF,
347 EIF,
351 unsigned char PREP(set_dropout_mode) [] =
354 PUSHW_1,
355 0x01, /* 0x01FF, activate dropout handling unconditionally */
356 0xFF,
357 SCANCTRL,
358 PUSHB_1,
359 4, /* smart dropout include stubs */
360 SCANTYPE,
364 unsigned char PREP(reset_component_counter) [] =
367 /* In case an application tries to render `.ttfautohint' */
368 /* (which it should never do), */
369 /* hinting of all glyphs rendered afterwards is disabled */
370 /* because the `cvtl_is_subglyph' counter gets incremented, */
371 /* but there is no counterpart to decrement it. */
372 /* Font inspection tools like the FreeType demo programs */
373 /* are an exception to that rule, however, */
374 /* since they can directly access a font by glyph indices. */
375 /* The following guard alleviates the problem a bit: */
376 /* Any change of the graphics state */
377 /* (for example, rendering at a different size or with a different mode) */
378 /* resets the counter to zero. */
379 PUSHB_2,
380 cvtl_is_subglyph,
382 WCVTP,
387 #define COPY_PREP(snippet_name) \
388 do { \
389 memcpy(buf_p, prep_ ## snippet_name, \
390 sizeof (prep_ ## snippet_name)); \
391 buf_p += sizeof (prep_ ## snippet_name); \
392 } while (0)
394 static FT_Error
395 TA_table_build_prep(FT_Byte** prep,
396 FT_ULong* prep_len,
397 FONT* font)
399 TA_LatinAxis vaxis;
400 TA_LatinBlue blue_adjustment = NULL;
401 FT_UInt i;
403 FT_UInt buf_len = 0;
404 FT_UInt len;
405 FT_Byte* buf;
406 FT_Byte* buf_p;
409 if (font->loader->hints.metrics->clazz->script == TA_SCRIPT_NONE)
410 vaxis = NULL;
411 else
413 vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1];
415 for (i = 0; i < vaxis->blue_count; i++)
417 if (vaxis->blues[i].flags & TA_LATIN_BLUE_ADJUSTMENT)
419 blue_adjustment = &vaxis->blues[i];
420 break;
425 if (font->hinting_limit)
426 buf_len += sizeof (PREP(hinting_limit_a))
428 + sizeof (PREP(hinting_limit_b));
430 buf_len += sizeof (PREP(store_0x10000));
432 if (blue_adjustment)
433 buf_len += sizeof (PREP(align_top_a))
435 + sizeof (PREP(align_top_b))
436 + (font->increase_x_height ? (sizeof (PREP(align_top_c1a))
438 + sizeof (PREP(align_top_c1b)))
439 : sizeof (PREP(align_top_c2)))
440 + sizeof (PREP(align_top_d))
441 + sizeof (PREP(loop_cvt_a))
443 + sizeof (PREP(loop_cvt_b))
445 + sizeof (PREP(loop_cvt_c))
447 + sizeof (PREP(loop_cvt_d));
449 buf_len += sizeof (PREP(compute_extra_light_a))
451 + sizeof (PREP(compute_extra_light_b));
453 if (CVT_BLUES_SIZE(font))
454 buf_len += sizeof (PREP(round_blues_a))
456 + sizeof (PREP(round_blues_b));
458 buf_len += sizeof (PREP(set_stem_width_handling_a))
460 + sizeof (PREP(set_stem_width_handling_b))
462 + sizeof (PREP(set_stem_width_handling_c))
464 + sizeof (PREP(set_stem_width_handling_d));
465 buf_len += sizeof (PREP(set_dropout_mode));
466 buf_len += sizeof (PREP(reset_component_counter));
468 /* buffer length must be a multiple of four */
469 len = (buf_len + 3) & ~3;
470 buf = (FT_Byte*)malloc(len);
471 if (!buf)
472 return FT_Err_Out_Of_Memory;
474 /* pad end of buffer with zeros */
475 buf[len - 1] = 0x00;
476 buf[len - 2] = 0x00;
477 buf[len - 3] = 0x00;
479 /* copy cvt program into buffer and fill in the missing variables */
480 buf_p = buf;
482 if (font->hinting_limit)
484 COPY_PREP(hinting_limit_a);
485 *(buf_p++) = HIGH(font->hinting_limit);
486 *(buf_p++) = LOW(font->hinting_limit);
487 COPY_PREP(hinting_limit_b);
490 COPY_PREP(store_0x10000);
492 if (blue_adjustment)
494 COPY_PREP(align_top_a);
495 *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font)
496 + blue_adjustment - vaxis->blues);
497 COPY_PREP(align_top_b);
498 if (font->increase_x_height)
500 COPY_PREP(align_top_c1a);
501 *(buf_p++) = (unsigned char)font->increase_x_height;
502 COPY_PREP(align_top_c1b);
504 else
505 COPY_PREP(align_top_c2);
506 COPY_PREP(align_top_d);
508 COPY_PREP(loop_cvt_a);
509 *(buf_p++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font);
510 *(buf_p++) = (unsigned char)(CVT_VERT_WIDTHS_OFFSET(font)
511 + CVT_VERT_WIDTHS_SIZE(font) - 1);
512 COPY_PREP(loop_cvt_b);
513 *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
514 *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font)
515 + CVT_BLUES_SIZE(font) - 1);
516 COPY_PREP(loop_cvt_c);
517 *(buf_p++) = (unsigned char)CVT_BLUE_SHOOTS_OFFSET(font);
518 *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font)
519 + CVT_BLUES_SIZE(font) - 1);
520 COPY_PREP(loop_cvt_d);
523 COPY_PREP(compute_extra_light_a);
524 *(buf_p++) = (unsigned char)CVT_VERT_STANDARD_WIDTH_OFFSET(font);
525 COPY_PREP(compute_extra_light_b);
527 if (CVT_BLUES_SIZE(font))
529 COPY_PREP(round_blues_a);
530 *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
531 *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font)
532 + CVT_BLUES_SIZE(font) - 1);
533 COPY_PREP(round_blues_b);
536 COPY_PREP(set_stem_width_handling_a);
537 *(buf_p++) = font->gray_strong_stem_width ? bci_strong_stem_width
538 : bci_smooth_stem_width;
539 COPY_PREP(set_stem_width_handling_b);
540 *(buf_p++) = font->gdi_cleartype_strong_stem_width ? bci_strong_stem_width
541 : bci_smooth_stem_width;
542 COPY_PREP(set_stem_width_handling_c);
543 *(buf_p++) = font->dw_cleartype_strong_stem_width ? bci_strong_stem_width
544 : bci_smooth_stem_width;
545 COPY_PREP(set_stem_width_handling_d);
546 COPY_PREP(set_dropout_mode);
547 COPY_PREP(reset_component_counter);
549 *prep = buf;
550 *prep_len = buf_len;
552 return FT_Err_Ok;
556 FT_Error
557 TA_sfnt_build_prep_table(SFNT* sfnt,
558 FONT* font)
560 FT_Error error;
562 FT_Byte* prep_buf;
563 FT_ULong prep_len;
566 error = TA_sfnt_add_table_info(sfnt);
567 if (error)
568 return error;
570 error = TA_table_build_prep(&prep_buf, &prep_len, font);
571 if (error)
572 return error;
574 #if 0
575 /* ttfautohint's bytecode in `fpgm' is larger */
576 /* than the bytecode in `prep'; */
577 /* this commented out code here is just for completeness */
578 if (prep_len > sfnt->max_instructions)
579 sfnt->max_instructions = prep_len;
580 #endif
582 /* in case of success, `prep_buf' gets linked */
583 /* and is eventually freed in `TA_font_unload' */
584 error = TA_font_add_table(font,
585 &sfnt->table_infos[sfnt->num_table_infos - 1],
586 TTAG_prep, prep_len, prep_buf);
587 if (error)
589 free(prep_buf);
590 return error;
593 return FT_Err_Ok;
596 /* end of taprep.c */