Initialize properties of `globals' object.
[ttfautohint.git] / lib / taprep.c
blob8602e49df426ff0c3c1e624c9580d3d5bb37b89d
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 PUSHW_1,
107 /* %d, 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 \
390 memcpy(buf_p, prep_ ## snippet_name, \
391 sizeof (prep_ ## snippet_name)); \
392 buf_p += sizeof (prep_ ## snippet_name); \
393 } while (0)
395 static FT_Error
396 TA_table_build_prep(FT_Byte** prep,
397 FT_ULong* prep_len,
398 FONT* font)
400 TA_LatinAxis vaxis;
401 TA_LatinBlue blue_adjustment = NULL;
402 FT_UInt i;
404 FT_UInt buf_len = 0;
405 FT_UInt len;
406 FT_Byte* buf;
407 FT_Byte* buf_p;
410 if (font->loader->hints.metrics->clazz->script == TA_SCRIPT_NONE)
411 vaxis = NULL;
412 else
414 vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1];
416 for (i = 0; i < vaxis->blue_count; i++)
418 if (vaxis->blues[i].flags & TA_LATIN_BLUE_ADJUSTMENT)
420 blue_adjustment = &vaxis->blues[i];
421 break;
426 if (font->hinting_limit)
427 buf_len += sizeof (PREP(hinting_limit_a))
429 + sizeof (PREP(hinting_limit_b));
431 buf_len += sizeof (PREP(store_0x10000));
433 if (blue_adjustment)
434 buf_len += sizeof (PREP(align_top_a))
436 + sizeof (PREP(align_top_b))
437 + (font->increase_x_height ? (sizeof (PREP(align_top_c1a))
439 + sizeof (PREP(align_top_c1b)))
440 : sizeof (PREP(align_top_c2)))
441 + sizeof (PREP(align_top_d))
442 + sizeof (PREP(loop_cvt_a))
444 + sizeof (PREP(loop_cvt_b))
446 + sizeof (PREP(loop_cvt_c))
448 + sizeof (PREP(loop_cvt_d));
450 buf_len += sizeof (PREP(compute_extra_light_a))
452 + sizeof (PREP(compute_extra_light_b));
454 if (CVT_BLUES_SIZE(font))
455 buf_len += sizeof (PREP(round_blues_a))
457 + sizeof (PREP(round_blues_b));
459 buf_len += sizeof (PREP(set_stem_width_handling_a))
461 + sizeof (PREP(set_stem_width_handling_b))
463 + sizeof (PREP(set_stem_width_handling_c))
465 + sizeof (PREP(set_stem_width_handling_d));
466 buf_len += sizeof (PREP(set_dropout_mode));
467 buf_len += sizeof (PREP(reset_component_counter));
469 /* buffer length must be a multiple of four */
470 len = (buf_len + 3) & ~3;
471 buf = (FT_Byte*)malloc(len);
472 if (!buf)
473 return FT_Err_Out_Of_Memory;
475 /* pad end of buffer with zeros */
476 buf[len - 1] = 0x00;
477 buf[len - 2] = 0x00;
478 buf[len - 3] = 0x00;
480 /* copy cvt program into buffer and fill in the missing variables */
481 buf_p = buf;
483 if (font->hinting_limit)
485 COPY_PREP(hinting_limit_a);
486 *(buf_p++) = HIGH(font->hinting_limit);
487 *(buf_p++) = LOW(font->hinting_limit);
488 COPY_PREP(hinting_limit_b);
491 COPY_PREP(store_0x10000);
493 if (blue_adjustment)
495 COPY_PREP(align_top_a);
496 *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font)
497 + blue_adjustment - vaxis->blues);
498 COPY_PREP(align_top_b);
499 if (font->increase_x_height)
501 COPY_PREP(align_top_c1a);
502 *(buf_p++) = HIGH(font->increase_x_height);
503 *(buf_p++) = LOW(font->increase_x_height);
504 COPY_PREP(align_top_c1b);
506 else
507 COPY_PREP(align_top_c2);
508 COPY_PREP(align_top_d);
510 COPY_PREP(loop_cvt_a);
511 *(buf_p++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font);
512 *(buf_p++) = (unsigned char)(CVT_VERT_WIDTHS_OFFSET(font)
513 + CVT_VERT_WIDTHS_SIZE(font) - 1);
514 /* don't loop over the artificial blue zones */
515 COPY_PREP(loop_cvt_b);
516 *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
517 *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font)
518 + CVT_BLUES_SIZE(font) - 1 - 2);
519 COPY_PREP(loop_cvt_c);
520 *(buf_p++) = (unsigned char)CVT_BLUE_SHOOTS_OFFSET(font);
521 *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font)
522 + CVT_BLUES_SIZE(font) - 1 - 2);
523 COPY_PREP(loop_cvt_d);
526 COPY_PREP(compute_extra_light_a);
527 *(buf_p++) = (unsigned char)CVT_VERT_STANDARD_WIDTH_OFFSET(font);
528 COPY_PREP(compute_extra_light_b);
530 if (CVT_BLUES_SIZE(font))
532 COPY_PREP(round_blues_a);
533 *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
534 *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font)
535 + CVT_BLUES_SIZE(font) - 1);
536 COPY_PREP(round_blues_b);
539 COPY_PREP(set_stem_width_handling_a);
540 *(buf_p++) = font->gray_strong_stem_width ? bci_strong_stem_width
541 : bci_smooth_stem_width;
542 COPY_PREP(set_stem_width_handling_b);
543 *(buf_p++) = font->gdi_cleartype_strong_stem_width ? bci_strong_stem_width
544 : bci_smooth_stem_width;
545 COPY_PREP(set_stem_width_handling_c);
546 *(buf_p++) = font->dw_cleartype_strong_stem_width ? bci_strong_stem_width
547 : bci_smooth_stem_width;
548 COPY_PREP(set_stem_width_handling_d);
549 COPY_PREP(set_dropout_mode);
550 COPY_PREP(reset_component_counter);
552 *prep = buf;
553 *prep_len = buf_len;
555 return FT_Err_Ok;
559 FT_Error
560 TA_sfnt_build_prep_table(SFNT* sfnt,
561 FONT* font)
563 FT_Error error = FT_Err_Ok;
565 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
566 glyf_Data* data = (glyf_Data*)glyf_table->data;
568 FT_Byte* prep_buf;
569 FT_ULong prep_len;
572 error = TA_sfnt_add_table_info(sfnt);
573 if (error)
574 goto Exit;
576 /* `glyf', `cvt', `fpgm', and `prep' are always used in parallel */
577 if (glyf_table->processed)
579 sfnt->table_infos[sfnt->num_table_infos - 1] = data->prep_idx;
580 goto Exit;
583 error = TA_table_build_prep(&prep_buf, &prep_len, font);
584 if (error)
585 goto Exit;
587 #if 0
588 /* ttfautohint's bytecode in `fpgm' is larger */
589 /* than the bytecode in `prep'; */
590 /* this commented out code here is just for completeness */
591 if (prep_len > sfnt->max_instructions)
592 sfnt->max_instructions = prep_len;
593 #endif
595 /* in case of success, `prep_buf' gets linked */
596 /* and is eventually freed in `TA_font_unload' */
597 error = TA_font_add_table(font,
598 &sfnt->table_infos[sfnt->num_table_infos - 1],
599 TTAG_prep, prep_len, prep_buf);
600 if (error)
601 free(prep_buf);
602 else
603 data->prep_idx = sfnt->table_infos[sfnt->num_table_infos - 1];
605 Exit:
606 return error;
609 /* end of taprep.c */