Synchronize with FreeType. [2/2]
[ttfautohint.git] / lib / taprep.c
blob8de42b0d0b2d6e202246cb5919769439c2446173
1 /* taprep.c */
3 /*
4 * Copyright (C) 2011-2013 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 PUSHB_1,
69 cvtl_funits_to_pixels,
70 SWAP,
71 WCVTF, /* store value 1 in 16.16 format, scaled */
75 unsigned char PREP(test_exception_a) [] =
78 PUSHB_1,
79 cvtl_is_element,
80 RCVT,
81 NOT,
82 IF,
86 unsigned char PREP(align_top_a) [] =
89 /* optimize the alignment of the top of small letters to the pixel grid */
91 PUSHB_1,
95 /* %c, index of alignment blue zone */
97 unsigned char PREP(align_top_b) [] =
100 RCVT,
101 DUP,
102 DUP,
106 unsigned char PREP(align_top_c1a) [] =
109 /* use this if option `increase_x_height' > 0 */
110 /* apply much `stronger' rounding up of x height for */
111 /* 6 <= PPEM <= increase_x_height */
112 MPPEM,
113 PUSHW_1,
117 /* %d, x height increase limit */
119 unsigned char PREP(align_top_c1b) [] =
122 LTEQ,
123 MPPEM,
124 PUSHB_1,
126 GTEQ,
127 AND,
129 PUSHB_1,
130 52, /* threshold = 52 */
132 ELSE,
133 PUSHB_1,
134 40, /* threshold = 40 */
136 EIF,
137 ADD,
138 FLOOR, /* fitted = FLOOR(scaled + threshold) */
142 unsigned char PREP(align_top_c2) [] =
145 PUSHB_1,
147 ADD,
148 FLOOR, /* fitted = FLOOR(scaled + 40) */
152 unsigned char PREP(align_top_d) [] =
155 DUP, /* s: scaled scaled fitted fitted */
156 ROLL,
157 NEQ,
158 IF, /* s: scaled fitted */
159 PUSHB_1,
161 CINDEX,
162 SUB, /* s: scaled (fitted-scaled) */
163 PUSHB_1,
164 cvtl_0x10000,
165 RCVT,
166 MUL, /* (fitted-scaled) in 16.16 format */
167 SWAP,
168 DIV, /* ((fitted-scaled) / scaled) in 16.16 format */
170 PUSHB_1,
171 cvtl_scale,
172 SWAP,
173 WCVTP,
177 unsigned char PREP(loop_cvt_a) [] =
180 /* loop over vertical CVT entries */
181 PUSHB_3,
185 /* %c, first vertical index */
186 /* %c, number of vertical indices */
188 unsigned char PREP(loop_cvt_b) [] =
191 bci_cvt_rescale,
192 LOOPCALL,
194 /* loop over blue refs */
195 PUSHB_3,
199 /* %c, first blue ref index */
200 /* %c, number of blue ref indices */
202 unsigned char PREP(loop_cvt_c) [] =
205 bci_cvt_rescale,
206 LOOPCALL,
208 /* loop over blue shoots */
209 PUSHB_3,
213 /* %c, first blue shoot index */
214 /* %c, number of blue shoot indices */
216 unsigned char PREP(loop_cvt_d) [] =
219 bci_cvt_rescale,
220 LOOPCALL,
221 EIF,
225 unsigned char PREP(test_exception_b) [] =
228 EIF,
232 unsigned char PREP(compute_extra_light_a) [] =
235 /* compute (vertical) `extra_light' flag */
236 PUSHB_3,
237 cvtl_is_extra_light,
242 /* %c, index of vertical standard_width */
244 unsigned char PREP(compute_extra_light_b) [] =
247 RCVT,
248 GT, /* standard_width < 40 */
249 WCVTP,
253 unsigned char PREP(round_blues_a) [] =
256 /* use discrete values for blue zone widths */
257 PUSHB_3,
261 /* %c, first blue ref index */
262 /* %c, number of blue ref indices */
264 unsigned char PREP(round_blues_b) [] =
267 bci_blue_round,
268 LOOPCALL,
272 unsigned char PREP(set_stem_width_handling_a) [] =
276 * There are two ClearType flavours available on Windows: The older GDI
277 * ClearType, introduced in 2000, and the recent DW ClearType, introduced
278 * in 2008. The main difference is that the older incarnation behaves
279 * like a B/W renderer along the y axis, while the newer version does
280 * vertical smoothing also.
282 * The only possibility to differentiate between GDI and DW ClearType is
283 * testing bit 10 in the GETINFO instruction (with return value in bit 17;
284 * this works for TrueType version >= 38), checking whether sub-pixel
285 * positioning is available.
287 * If GDI ClearType is active, we use a different stem width function
288 * which snaps to integer pixels as much as possible.
291 /* set default positioning */
292 PUSHB_2,
293 cvtl_stem_width_function,
297 /* %d, either bci_smooth_stem_width or bci_strong_stem_width */
299 unsigned char PREP(set_stem_width_handling_b) [] =
302 WCVTP,
304 /* get rasterizer version (bit 0) */
305 PUSHB_2,
307 0x01,
308 GETINFO,
310 /* `GDI ClearType': */
311 /* version >= 36 and version < 38, ClearType enabled */
312 LTEQ,
314 /* check whether ClearType is enabled (bit 6) */
315 PUSHB_1,
316 0x40,
317 GETINFO,
319 PUSHB_2,
320 cvtl_stem_width_function,
323 /* %d, either bci_smooth_stem_width or bci_strong_stem_width */
325 unsigned char PREP(set_stem_width_handling_c) [] =
328 WCVTP,
330 /* get rasterizer version (bit 0) */
331 PUSHB_2,
333 0x01,
334 GETINFO,
336 /* `DW ClearType': */
337 /* version >= 38, sub-pixel positioning is enabled */
338 LTEQ,
340 /* check whether sub-pixel positioning is enabled (bit 10) */
341 PUSHW_1,
342 0x04,
343 0x00,
344 GETINFO,
346 PUSHB_2,
347 cvtl_stem_width_function,
351 /* %d, either bci_smooth_stem_width or bci_strong_stem_width */
353 unsigned char PREP(set_stem_width_handling_d) [] =
356 WCVTP,
357 EIF,
358 EIF,
359 EIF,
360 EIF,
364 unsigned char PREP(set_dropout_mode) [] =
367 PUSHW_1,
368 0x01, /* 0x01FF, activate dropout handling unconditionally */
369 0xFF,
370 SCANCTRL,
371 PUSHB_1,
372 4, /* smart dropout include stubs */
373 SCANTYPE,
377 unsigned char PREP(reset_component_counter) [] =
380 /* In case an application tries to render `.ttfautohint' */
381 /* (which it should never do), */
382 /* hinting of all glyphs rendered afterwards is disabled */
383 /* because the `cvtl_is_subglyph' counter gets incremented, */
384 /* but there is no counterpart to decrement it. */
385 /* Font inspection tools like the FreeType demo programs */
386 /* are an exception to that rule, however, */
387 /* since they can directly access a font by glyph indices. */
388 /* The following guard alleviates the problem a bit: */
389 /* Any change of the graphics state */
390 /* (for example, rendering at a different size or with a different mode) */
391 /* resets the counter to zero. */
392 PUSHB_2,
393 cvtl_is_subglyph,
395 WCVTP,
400 /* this function allocates `buf', parsing `number_set' to create bytecode */
401 /* which eventually sets CVT index `cvtl_is_element' */
402 /* (in functions `bci_number_set_is_element' and */
403 /* `bci_number_set_is_element2') */
405 static FT_Byte*
406 TA_sfnt_build_number_set(SFNT* sfnt,
407 FT_Byte** buf,
408 number_range* number_set)
410 FT_Byte* bufp = NULL;
411 number_range* nr;
413 FT_UInt num_singles2 = 0;
414 FT_UInt* single2_args;
415 FT_UInt* single2_arg;
416 FT_UInt num_singles = 0;
417 FT_UInt* single_args;
418 FT_UInt* single_arg;
420 FT_UInt num_ranges2 = 0;
421 FT_UInt* range2_args;
422 FT_UInt* range2_arg;
423 FT_UInt num_ranges = 0;
424 FT_UInt* range_args;
425 FT_UInt* range_arg;
427 FT_UInt have_single = 0;
428 FT_UInt have_range = 0;
430 FT_UShort num_stack_elements;
433 /* build up four stacks to stay as compact as possible */
434 nr = number_set;
435 while (nr)
437 if (nr->start == nr->end)
439 if (nr->start < 256)
440 num_singles++;
441 else
442 num_singles2++;
444 else
446 if (nr->start < 256 && nr->end < 256)
447 num_ranges++;
448 else
449 num_ranges2++;
451 nr = nr->next;
454 /* collect all arguments temporarily in arrays (in reverse order) */
455 /* so that we can easily split into chunks of 255 args */
456 /* as needed by NPUSHB and friends; */
457 /* for simplicity, always allocate an extra slot */
458 single2_args = (FT_UInt*)malloc((num_singles2 + 1) * sizeof (FT_UInt));
459 single_args = (FT_UInt*)malloc((num_singles + 1) * sizeof (FT_UInt));
460 range2_args = (FT_UInt*)malloc((2 * num_ranges2 + 1) * sizeof (FT_UInt));
461 range_args = (FT_UInt*)malloc((2 * num_ranges + 1) * sizeof (FT_UInt));
462 if (!single2_args || !single_args
463 || !range2_args || !range_args)
464 goto Fail;
466 /* check whether we need the extra slot for the argument to CALL */
467 if (num_singles || num_singles2)
468 have_single = 1;
469 if (num_ranges || num_ranges2)
470 have_range = 1;
472 /* set function indices outside of argument loop (using the extra slot) */
473 if (have_single)
474 single_args[num_singles] = bci_number_set_is_element;
475 if (have_range)
476 range_args[2 * num_ranges] = bci_number_set_is_element2;
478 single2_arg = single2_args + num_singles2 - 1;
479 single_arg = single_args + num_singles - 1;
480 range2_arg = range2_args + 2 * num_ranges2 - 1;
481 range_arg = range_args + 2 * num_ranges - 1;
483 nr = number_set;
484 while (nr)
486 if (nr->start == nr->end)
488 if (nr->start < 256)
489 *(single_arg--) = nr->start;
490 else
491 *(single2_arg--) = nr->start;
493 else
495 if (nr->start < 256 && nr->end < 256)
497 *(range_arg--) = nr->start;
498 *(range_arg--) = nr->end;
500 else
502 *(range2_arg--) = nr->start;
503 *(range2_arg--) = nr->end;
506 nr = nr->next;
509 /* this rough estimate of the buffer size gets adjusted later on */
510 *buf = (FT_Byte*)malloc((2 + 1) * num_singles2
511 + (1 + 1) * num_singles
512 + (4 + 1) * num_ranges2
513 + (2 + 1) * num_ranges
514 + 10);
515 if (!*buf)
516 goto Fail;
517 bufp = *buf;
519 BCI(PUSHB_2);
520 BCI(cvtl_is_element);
521 BCI(0);
522 BCI(WCVTP);
524 bufp = TA_build_push(bufp, single2_args, num_singles2, 1, 1);
525 bufp = TA_build_push(bufp, single_args, num_singles + have_single, 0, 1);
526 if (have_single)
527 BCI(CALL);
529 bufp = TA_build_push(bufp, range2_args, 2 * num_ranges2, 1, 1);
530 bufp = TA_build_push(bufp, range_args, 2 * num_ranges + have_range, 0, 1);
531 if (have_range)
532 BCI(CALL);
534 num_stack_elements = num_singles + num_singles2;
535 if (num_stack_elements > num_ranges + num_ranges2)
536 num_stack_elements = num_ranges + num_ranges2;
537 num_stack_elements += ADDITIONAL_STACK_ELEMENTS;
538 if (num_stack_elements > sfnt->max_stack_elements)
539 sfnt->max_stack_elements = num_stack_elements;
541 Fail:
542 free(single2_args);
543 free(single_args);
544 free(range2_args);
545 free(range_args);
547 return bufp;
551 #define COPY_PREP(snippet_name) \
552 do \
554 memcpy(buf_p, prep_ ## snippet_name, \
555 sizeof (prep_ ## snippet_name)); \
556 buf_p += sizeof (prep_ ## snippet_name); \
557 } while (0)
559 static FT_Error
560 TA_table_build_prep(FT_Byte** prep,
561 FT_ULong* prep_len,
562 SFNT* sfnt,
563 FONT* font)
565 TA_LatinAxis vaxis;
566 TA_LatinBlue blue_adjustment = NULL;
567 FT_UInt i;
569 FT_Byte* buf = NULL;
570 FT_Byte* buf_new;
571 FT_UInt buf_len;
572 FT_UInt buf_new_len;
574 FT_UInt len;
575 FT_Byte* buf_p = NULL;
578 if (font->loader->hints.metrics->script_class->script == TA_SCRIPT_NONE)
579 vaxis = NULL;
580 else
582 vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1];
584 for (i = 0; i < vaxis->blue_count; i++)
586 if (vaxis->blues[i].flags & TA_LATIN_BLUE_ADJUSTMENT)
588 blue_adjustment = &vaxis->blues[i];
589 break;
594 if (blue_adjustment && font->x_height_snapping_exceptions)
596 buf_p = TA_sfnt_build_number_set(sfnt, &buf,
597 font->x_height_snapping_exceptions);
598 if (!buf_p)
599 return FT_Err_Out_Of_Memory;
602 buf_len = buf_p - buf;
603 buf_new_len = buf_len;
605 if (font->hinting_limit)
606 buf_new_len += sizeof (PREP(hinting_limit_a))
608 + sizeof (PREP(hinting_limit_b));
610 buf_new_len += sizeof (PREP(store_0x10000));
612 if (blue_adjustment)
614 if (font->x_height_snapping_exceptions)
615 buf_new_len += sizeof (PREP(test_exception_a));
616 buf_new_len += sizeof (PREP(align_top_a))
618 + sizeof (PREP(align_top_b))
619 + (font->increase_x_height
620 ? (sizeof (PREP(align_top_c1a))
622 + sizeof (PREP(align_top_c1b)))
623 : sizeof (PREP(align_top_c2)))
624 + sizeof (PREP(align_top_d))
625 + sizeof (PREP(loop_cvt_a))
627 + sizeof (PREP(loop_cvt_b))
629 + sizeof (PREP(loop_cvt_c))
631 + sizeof (PREP(loop_cvt_d));
632 if (font->x_height_snapping_exceptions)
633 buf_new_len += sizeof (PREP(test_exception_b));
636 buf_new_len += sizeof (PREP(compute_extra_light_a))
638 + sizeof (PREP(compute_extra_light_b));
640 if (CVT_BLUES_SIZE(font))
641 buf_new_len += sizeof (PREP(round_blues_a))
643 + sizeof (PREP(round_blues_b));
645 buf_new_len += sizeof (PREP(set_stem_width_handling_a))
647 + sizeof (PREP(set_stem_width_handling_b))
649 + sizeof (PREP(set_stem_width_handling_c))
651 + sizeof (PREP(set_stem_width_handling_d));
652 buf_new_len += sizeof (PREP(set_dropout_mode));
653 buf_new_len += sizeof (PREP(reset_component_counter));
655 /* buffer length must be a multiple of four */
656 len = (buf_new_len + 3) & ~3;
657 buf_new = (FT_Byte*)realloc(buf, len);
658 if (!buf_new)
660 free(buf);
661 return FT_Err_Out_Of_Memory;
663 buf = buf_new;
665 /* pad end of buffer with zeros */
666 buf[len - 1] = 0x00;
667 buf[len - 2] = 0x00;
668 buf[len - 3] = 0x00;
670 /* copy remaining cvt program into buffer */
671 /* and fill in the missing variables */
672 buf_p = buf + buf_len;
674 if (font->hinting_limit)
676 COPY_PREP(hinting_limit_a);
677 *(buf_p++) = HIGH(font->hinting_limit);
678 *(buf_p++) = LOW(font->hinting_limit);
679 COPY_PREP(hinting_limit_b);
682 COPY_PREP(store_0x10000);
684 if (blue_adjustment)
686 if (font->x_height_snapping_exceptions)
687 COPY_PREP(test_exception_a);
689 COPY_PREP(align_top_a);
690 *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font)
691 + blue_adjustment - vaxis->blues);
692 COPY_PREP(align_top_b);
693 if (font->increase_x_height)
695 COPY_PREP(align_top_c1a);
696 *(buf_p++) = HIGH(font->increase_x_height);
697 *(buf_p++) = LOW(font->increase_x_height);
698 COPY_PREP(align_top_c1b);
700 else
701 COPY_PREP(align_top_c2);
702 COPY_PREP(align_top_d);
704 COPY_PREP(loop_cvt_a);
705 *(buf_p++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font);
706 *(buf_p++) = (unsigned char)CVT_VERT_WIDTHS_SIZE(font);
707 /* don't loop over the artificial blue zones */
708 COPY_PREP(loop_cvt_b);
709 *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
710 *(buf_p++) = (unsigned char)(CVT_BLUES_SIZE(font) - 2);
711 COPY_PREP(loop_cvt_c);
712 *(buf_p++) = (unsigned char)CVT_BLUE_SHOOTS_OFFSET(font);
713 *(buf_p++) = (unsigned char)(CVT_BLUES_SIZE(font) - 2);
714 COPY_PREP(loop_cvt_d);
716 if (font->x_height_snapping_exceptions)
717 COPY_PREP(test_exception_b);
720 COPY_PREP(compute_extra_light_a);
721 *(buf_p++) = (unsigned char)CVT_VERT_STANDARD_WIDTH_OFFSET(font);
722 COPY_PREP(compute_extra_light_b);
724 if (CVT_BLUES_SIZE(font))
726 COPY_PREP(round_blues_a);
727 *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
728 *(buf_p++) = (unsigned char)CVT_BLUES_SIZE(font);
729 COPY_PREP(round_blues_b);
732 COPY_PREP(set_stem_width_handling_a);
733 *(buf_p++) = font->gray_strong_stem_width ? bci_strong_stem_width
734 : bci_smooth_stem_width;
735 COPY_PREP(set_stem_width_handling_b);
736 *(buf_p++) = font->gdi_cleartype_strong_stem_width ? bci_strong_stem_width
737 : bci_smooth_stem_width;
738 COPY_PREP(set_stem_width_handling_c);
739 *(buf_p++) = font->dw_cleartype_strong_stem_width ? bci_strong_stem_width
740 : bci_smooth_stem_width;
741 COPY_PREP(set_stem_width_handling_d);
742 COPY_PREP(set_dropout_mode);
743 COPY_PREP(reset_component_counter);
745 *prep = buf;
746 *prep_len = buf_new_len;
748 return FT_Err_Ok;
752 FT_Error
753 TA_sfnt_build_prep_table(SFNT* sfnt,
754 FONT* font)
756 FT_Error error;
758 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
759 glyf_Data* data = (glyf_Data*)glyf_table->data;
761 FT_Byte* prep_buf;
762 FT_ULong prep_len;
765 error = TA_sfnt_add_table_info(sfnt);
766 if (error)
767 goto Exit;
769 /* `glyf', `cvt', `fpgm', and `prep' are always used in parallel */
770 if (glyf_table->processed)
772 sfnt->table_infos[sfnt->num_table_infos - 1] = data->prep_idx;
773 goto Exit;
776 error = TA_table_build_prep(&prep_buf, &prep_len, sfnt, font);
777 if (error)
778 goto Exit;
780 #if 0
781 /* ttfautohint's bytecode in `fpgm' is larger */
782 /* than the bytecode in `prep'; */
783 /* this commented out code here is just for completeness */
784 if (prep_len > sfnt->max_instructions)
785 sfnt->max_instructions = prep_len;
786 #endif
788 /* in case of success, `prep_buf' gets linked */
789 /* and is eventually freed in `TA_font_unload' */
790 error = TA_font_add_table(font,
791 &sfnt->table_infos[sfnt->num_table_infos - 1],
792 TTAG_prep, prep_len, prep_buf);
793 if (error)
794 free(prep_buf);
795 else
796 data->prep_idx = sfnt->table_infos[sfnt->num_table_infos - 1];
798 Exit:
799 return error;
802 /* end of taprep.c */