Fix OTS warning about `maxp.maxSizeOfInstructions`.
[ttfautohint.git] / lib / taprep.c
blobba7c03fce8bddc24796c99efcb1d73a831f6c918
1 /* taprep.c */
3 /*
4 * Copyright (C) 2011-2022 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 static const unsigned char PREP(hinting_limit_a) [] =
25 /* all our measurements are taken along the y axis, */
26 /* including the ppem and CVT values */
27 SVTCA_y,
29 /* first of all, check whether we do hinting at all */
30 MPPEM,
31 PUSHW_1,
35 /* %d, hinting size limit */
37 static const unsigned char PREP(hinting_limit_b) [] =
40 GT,
41 IF,
42 PUSHB_2,
43 1, /* switch off hinting */
45 INSTCTRL,
46 EIF,
50 /* we store 0x10000 in CVT index `cvtl_funits_to_pixels' as a scaled value */
51 /* to have a conversion factor from FUnits to pixels */
53 static const unsigned char PREP(store_funits_to_pixels) [] =
56 PUSHB_1,
57 cvtl_funits_to_pixels,
59 PUSHW_2,
60 0x08, /* 0x800 */
61 0x00,
62 0x08, /* 0x800 */
63 0x00,
64 MUL, /* 0x10000 */
66 WCVTF, /* store value 1 in 16.16 format, scaled */
70 /* if the current ppem value is an exception, don't apply scaling */
72 static const unsigned char PREP(test_exception_a) [] =
75 PUSHB_1,
76 cvtl_is_element,
77 RCVT,
78 NOT,
79 IF,
83 /* provide scaling factors for all styles */
85 static const unsigned char PREP(align_x_height_a) [] =
88 PUSHB_2,
89 sal_i,
90 CVT_SCALING_VALUE_OFFSET(0),
91 WS,
95 /* PUSHB (num_used_styles + 2) */
96 /* ... */
97 /* %c, style 1's x height blue zone idx */
98 /* %c, style 0's x height blue zone idx */
99 /* %c, num_used_styles */
101 static const unsigned char PREP(align_x_height_b) [] =
104 bci_align_x_height,
105 LOOPCALL,
109 static const unsigned char PREP(loop_cvt_a) [] =
112 /* loop over (almost all) vertical CVT entries of all styles, part 1 */
113 PUSHB_2,
114 sal_i,
115 CVT_SCALING_VALUE_OFFSET(0),
120 /* PUSHB (2*num_used_styles + 2) */
121 /* ... */
122 /* %c, style 1's first vertical index */
123 /* %c, style 1's number of vertical indices */
124 /* (std. width, widths, flat blues zones without artifical ones) */
125 /* %c, style 0's first vertical index */
126 /* %c, style 0's number of vertical indices */
127 /* (std. width, widths, flat blues zones without artifical ones) */
128 /* %c, num_used_styles */
130 static const unsigned char PREP(loop_cvt_b) [] =
133 bci_cvt_rescale_range,
134 LOOPCALL,
136 /* loop over (almost all) vertical CVT entries of all styles, part 2 */
137 PUSHB_2,
138 sal_i,
139 CVT_SCALING_VALUE_OFFSET(0),
144 /* PUSHB (2*num_used_styles + 2) */
145 /* ... */
146 /* %c, style 1's first round blue zone index */
147 /* %c, style 1's number of round blue zones (without artificial ones) */
148 /* %c, style 0's first round blue zone index */
149 /* %c, style 0's number of round blue zones (without artificial ones) */
150 /* %c, num_used_styles */
152 static const unsigned char PREP(loop_cvt_c) [] =
155 bci_cvt_rescale_range,
156 LOOPCALL,
160 static const unsigned char PREP(test_exception_b) [] =
163 EIF,
167 static const unsigned char PREP(store_vwidth_data_a) [] =
170 PUSHB_2,
171 sal_i,
175 /* %c, offset to vertical width offset data in CVT */
177 static const unsigned char PREP(store_vwidth_data_b) [] =
184 /*PUSHW (num_used_styles + 2) */
185 /* ... */
186 /* %d, style 1's first vertical width index (in multiples of 64) */
187 /* %d, style 0's first vertical width index (in multiples of 64) */
188 /* %d, num_used_styles */
190 static const unsigned char PREP(store_vwidth_data_c) [] =
193 0x00, /* high byte */
194 bci_vwidth_data_store, /* low byte */
195 LOOPCALL,
197 PUSHB_2,
198 sal_i,
202 /* %c, offset to vertical width size data in CVT */
204 static const unsigned char PREP(store_vwidth_data_d) [] =
211 /*PUSHW (num_used_styles + 2) */
212 /* ... */
213 /* %d, style 1's number of vertical widths (in multiples of 64) */
214 /* %d, style 0's number of vertical widths (in multiples of 64) */
215 /* %d, num_used_styles */
217 static const unsigned char PREP(store_vwidth_data_e) [] =
220 0x00, /* high byte */
221 bci_vwidth_data_store, /* low byte */
222 LOOPCALL,
226 static const unsigned char PREP(set_stem_width_mode_a) [] =
229 * ttfautohint provides two different functions for stem width computation
230 * and blue zone rounding: `smooth' and `strong'. The former tries to
231 * align stem widths and blue zones to some discrete, possibly non-integer
232 * values. The latter snaps everything to integer pixels as much as
233 * possible.
235 * We test ClearType capabilities to find out which of the two functions
236 * should be used. Due to the various TrueType interpreter versions this
237 * is quite convoluted.
239 * interpreter version action
240 * ---------------------------------------------------------------------
241 * <= 35 this version predates ClearType -> smooth
243 * 36-38 use bit 6 in the GETINFO instruction to check
244 * whether ClearType is enabled; if set, we have
245 * (old) GDI ClearType -> strong, otherwise
246 * grayscale rendering -> smooth
248 * 39 if ClearType is enabled, use bit 10 in the
249 * GETINFO instruction to check whether ClearType
250 * sub-pixel positioning is available; if set, we
251 * have DW ClearType -> smooth, else GDI ClearType
252 * -> strong
254 * >= 40 if ClearType is enabled, use bit 11 in the
255 * GETINFO instruction to check whether ClearType
256 * symmetric rendering is available; if not set,
257 * the engine behaves like a B/W renderer along the
258 * y axis -> strong, else it does vertical
259 * smoothing -> smooth
261 * ClearType on Windows was introduced in 2000 for the GDI framework (no
262 * symmetric rendering, no sub-pixel positioning). In 2008, Windows got
263 * the DirectWrite (DW) framework which uses symmetric rendering and
264 * sub-pixel positioning.
266 * Note that in 2017 GDI on Windows 10 has changed rendering parameters:
267 * it now uses symmetric rendering but no sub-pixel positioning.
268 * Consequently, we treat this as `DW ClearType' also.
271 /* set default value */
272 PUSHW_2,
274 cvtl_stem_width_mode, /* target: grayscale rendering */
278 /* %d, either -100, 0 or 100 */
280 static const unsigned char PREP(set_stem_width_mode_b) [] =
283 WCVTP,
285 /* get rasterizer version (bit 0) */
286 PUSHB_2,
288 0x01,
289 GETINFO,
291 /* `(old) GDI ClearType': version >= 36 || version <= 38 */
292 LTEQ,
294 /* check whether ClearType is enabled (bit 6) */
295 PUSHB_1,
296 0x40,
297 GETINFO,
299 PUSHW_2,
301 cvtl_stem_width_mode, /* target: GDI ClearType */
304 /* %d, either -100, 0 or 100 */
306 static const unsigned char PREP(set_stem_width_mode_c) [] =
309 WCVTP,
311 /* get rasterizer version (bit 0) */
312 PUSHB_2,
314 0x01,
315 GETINFO,
317 /* `DW ClearType': version >= 40 */
318 LTEQ,
320 /* check whether symmetric rendering is enabled (bit 11) */
321 PUSHW_1,
322 0x08,
323 0x00,
324 GETINFO,
326 PUSHW_2,
328 cvtl_stem_width_mode, /* target: DirectWrite ClearType */
332 /* %d, either -100, 0 or 100 */
334 static const unsigned char PREP(set_stem_width_mode_d) [] =
337 WCVTP,
338 EIF,
340 ELSE,
341 /* get rasterizer version (bit 0) */
342 PUSHB_2,
344 0x01,
345 GETINFO,
347 /* `DW ClearType': version == 39 */
348 LTEQ,
350 /* check whether sub-pixel positioning is enabled (bit 10) -- */
351 /* due to a bug in FreeType 2.5.0 and earlier, */
352 /* bit 6 must be set also to get the correct information, */
353 /* so we test that both return values (in bits 13 and 17) are set */
354 PUSHW_3,
355 0x08, /* bits 13 and 17 right-shifted by 6 bits */
356 0x80,
357 0x00, /* we do `MUL' with value 1, */
358 0x01, /* which is essentially a division by 64 */
359 0x04, /* bits 6 and 10 */
360 0x40,
361 GETINFO,
362 MUL,
365 PUSHW_2,
367 cvtl_stem_width_mode, /* target: DirectWrite ClearType */
371 /* %d, either -100, 0 or 100 */
373 static const unsigned char PREP(set_stem_width_mode_e) [] =
376 WCVTP,
377 EIF,
378 EIF,
379 EIF,
380 EIF,
381 EIF,
385 /*PUSHB (2*num_used_styles + 2) */
386 /* ... */
387 /* %c, style 1's first blue ref index */
388 /* %c, style 1's number of blue ref indices */
389 /* %c, style 0's first blue ref index */
390 /* %c, style 0's number of blue ref indices */
391 /* %c, num_used_styles */
393 static const unsigned char PREP(round_blues) [] =
396 bci_blue_round_range,
397 LOOPCALL,
401 static const unsigned char PREP(set_dropout_mode) [] =
404 PUSHW_1,
405 0x01, /* 0x01FF, activate dropout handling unconditionally */
406 0xFF,
407 SCANCTRL,
408 PUSHB_1,
409 4, /* smart dropout include stubs */
410 SCANTYPE,
414 static const unsigned char PREP(reset_component_counter) [] =
417 /* In case an application tries to render `.ttfautohint' */
418 /* (which it should never do), */
419 /* hinting of all glyphs rendered afterwards is disabled */
420 /* because the `cvtl_is_subglyph' counter gets incremented, */
421 /* but there is no counterpart to decrement it. */
422 /* Font inspection tools like the FreeType demo programs */
423 /* are an exception to that rule, however, */
424 /* since they can directly access a font by glyph indices. */
425 /* The following guard alleviates the problem a bit: */
426 /* Any change of the graphics state */
427 /* (for example, rendering at a different size or with a different mode) */
428 /* resets the counter to zero. */
429 PUSHB_2,
430 cvtl_is_subglyph,
432 WCVTP,
436 static const unsigned char PREP(adjust_delta_exceptions) [] =
439 /* set delta base */
440 PUSHB_1,
441 CONTROL_DELTA_PPEM_MIN,
442 SDB,
447 static const unsigned char PREP(set_default_cvs_values) [] =
450 /* We set a default value for `cvtl_do_iup_y'. */
451 /* If we have delta exceptions before IUP_y, */
452 /* the glyph's bytecode sets this CVT value temporarily to zero */
453 /* and manually inserts IUP_y afterwards. */
455 /* We set a default value for `cvtl_ignore_std_width'. */
456 /* As the name implies, the stem width computation routines */
457 /* ignore the standard width(s) if this flag gets set. */
459 /* It would be more elegant to use storage area locations instead, */
460 /* however, it is not possible to have default values for them */
461 /* since storage area locations might be reset on a per-glyph basis */
462 /* (this is dependent on the bytecode interpreter implementation). */
464 PUSHB_4,
465 cvtl_do_iup_y,
466 100,
467 cvtl_ignore_std_width,
469 WCVTP,
470 WCVTP,
475 /* this function allocates `buf', parsing `number_set' to create bytecode */
476 /* which eventually sets CVT index `cvtl_is_element' */
477 /* (in functions `bci_number_set_is_element' and */
478 /* `bci_number_set_is_element2') */
480 static FT_Byte*
481 TA_sfnt_build_number_set(SFNT* sfnt,
482 FT_Byte** buf,
483 number_range* number_set)
485 FT_Byte* bufp = NULL;
486 number_range* nr;
488 FT_UInt num_singles2 = 0;
489 FT_UInt* single2_args;
490 FT_UInt* single2_arg;
491 FT_UInt num_singles = 0;
492 FT_UInt* single_args;
493 FT_UInt* single_arg;
495 FT_UInt num_ranges2 = 0;
496 FT_UInt* range2_args;
497 FT_UInt* range2_arg;
498 FT_UInt num_ranges = 0;
499 FT_UInt* range_args;
500 FT_UInt* range_arg;
502 FT_UInt have_single = 0;
503 FT_UInt have_range = 0;
505 FT_UShort num_stack_elements;
508 /* build up four stacks to stay as compact as possible */
509 nr = number_set;
510 while (nr)
512 if (nr->start == nr->end)
514 if (nr->start < 256)
515 num_singles++;
516 else
517 num_singles2++;
519 else
521 if (nr->start < 256 && nr->end < 256)
522 num_ranges++;
523 else
524 num_ranges2++;
526 nr = nr->next;
529 /* collect all arguments temporarily in arrays (in reverse order) */
530 /* so that we can easily split into chunks of 255 args */
531 /* as needed by NPUSHB and friends; */
532 /* for simplicity, always allocate an extra slot */
533 single2_args = (FT_UInt*)malloc((num_singles2 + 1) * sizeof (FT_UInt));
534 single_args = (FT_UInt*)malloc((num_singles + 1) * sizeof (FT_UInt));
535 range2_args = (FT_UInt*)malloc((2 * num_ranges2 + 1) * sizeof (FT_UInt));
536 range_args = (FT_UInt*)malloc((2 * num_ranges + 1) * sizeof (FT_UInt));
537 if (!single2_args || !single_args
538 || !range2_args || !range_args)
539 goto Fail;
541 /* check whether we need the extra slot for the argument to CALL */
542 if (num_singles || num_singles2)
543 have_single = 1;
544 if (num_ranges || num_ranges2)
545 have_range = 1;
547 /* set function indices outside of argument loop (using the extra slot) */
548 if (have_single)
549 single_args[num_singles] = bci_number_set_is_element;
550 if (have_range)
551 range_args[2 * num_ranges] = bci_number_set_is_element2;
553 single2_arg = single2_args + num_singles2 - 1;
554 single_arg = single_args + num_singles - 1;
555 range2_arg = range2_args + 2 * num_ranges2 - 1;
556 range_arg = range_args + 2 * num_ranges - 1;
558 nr = number_set;
559 while (nr)
561 FT_UInt start = (FT_UInt)nr->start;
562 FT_UInt end = (FT_UInt)nr->end;
565 if (start == end)
567 if (start < 256)
568 *(single_arg--) = start;
569 else
570 *(single2_arg--) = start;
572 else
574 if (start < 256 && end < 256)
576 *(range_arg--) = start;
577 *(range_arg--) = end;
579 else
581 *(range2_arg--) = start;
582 *(range2_arg--) = end;
585 nr = nr->next;
588 /* this rough estimate of the buffer size gets adjusted later on */
589 *buf = (FT_Byte*)malloc((2 + 1) * num_singles2
590 + (1 + 1) * num_singles
591 + (4 + 1) * num_ranges2
592 + (2 + 1) * num_ranges
593 + 10);
594 if (!*buf)
595 goto Fail;
596 bufp = *buf;
598 BCI(PUSHB_2);
599 BCI(cvtl_is_element);
600 BCI(0);
601 BCI(WCVTP);
603 bufp = TA_build_push(bufp, single2_args, num_singles2, 1, 1);
604 bufp = TA_build_push(bufp, single_args, num_singles + have_single, 0, 1);
605 if (have_single)
606 BCI(CALL);
608 bufp = TA_build_push(bufp, range2_args, 2 * num_ranges2, 1, 1);
609 bufp = TA_build_push(bufp, range_args, 2 * num_ranges + have_range, 0, 1);
610 if (have_range)
611 BCI(CALL);
613 num_stack_elements = (FT_UShort)(num_singles + num_singles2);
614 if (num_stack_elements > num_ranges + num_ranges2)
615 num_stack_elements = (FT_UShort)(num_ranges + num_ranges2);
616 num_stack_elements += ADDITIONAL_STACK_ELEMENTS;
617 if (num_stack_elements > sfnt->max_stack_elements)
618 sfnt->max_stack_elements = num_stack_elements;
620 Fail:
621 free(single2_args);
622 free(single_args);
623 free(range2_args);
624 free(range_args);
626 return bufp;
630 #define COPY_PREP(snippet_name) \
631 do \
633 memcpy(bufp, prep_ ## snippet_name, \
634 sizeof (prep_ ## snippet_name)); \
635 bufp += sizeof (prep_ ## snippet_name); \
636 } while (0)
638 static FT_Error
639 TA_table_build_prep(FT_Byte** prep,
640 FT_ULong* prep_len,
641 SFNT* sfnt,
642 FONT* font)
644 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
645 glyf_Data* data = (glyf_Data*)glyf_table->data;
646 /* XXX: make this work for more than 256 styles */
647 FT_Byte num_used_styles = (FT_Byte)data->num_used_styles;
649 FT_Int i;
651 FT_Byte* buf = NULL;
652 FT_Byte* buf_new;
653 FT_UInt buf_len;
654 FT_UInt buf_new_len;
656 FT_UInt len;
657 FT_Byte* bufp = NULL;
660 if (font->x_height_snapping_exceptions)
662 bufp = TA_sfnt_build_number_set(sfnt, &buf,
663 font->x_height_snapping_exceptions);
664 if (!bufp)
665 return FT_Err_Out_Of_Memory;
668 buf_len = (FT_UInt)(bufp - buf);
669 buf_new_len = buf_len;
671 if (font->hinting_limit)
672 buf_new_len += sizeof (PREP(hinting_limit_a))
674 + sizeof (PREP(hinting_limit_b));
676 buf_new_len += sizeof (PREP(store_funits_to_pixels));
678 if (font->x_height_snapping_exceptions)
679 buf_new_len += sizeof (PREP(test_exception_a));
681 buf_new_len += sizeof (PREP(align_x_height_a))
682 + (num_used_styles > 6 ? num_used_styles + 3
683 : num_used_styles + 2)
684 + sizeof (PREP(align_x_height_b));
685 buf_new_len += sizeof (PREP(loop_cvt_a))
686 + (num_used_styles > 3 ? 2 * num_used_styles + 3
687 : 2 * num_used_styles + 2)
688 + sizeof (PREP(loop_cvt_b))
689 + (num_used_styles > 3 ? 2 * num_used_styles + 3
690 : 2 * num_used_styles + 2)
691 + sizeof (PREP(loop_cvt_c));
693 if (font->x_height_snapping_exceptions)
694 buf_new_len += sizeof (PREP(test_exception_b));
696 buf_new_len += sizeof (PREP(store_vwidth_data_a))
698 + sizeof (PREP(store_vwidth_data_b))
699 + (num_used_styles > 6 ? 2 * (num_used_styles + 1) + 2
700 : 2 * (num_used_styles + 1) + 1)
701 + sizeof (PREP(store_vwidth_data_c))
703 + sizeof (PREP(store_vwidth_data_d))
704 + (num_used_styles > 6 ? 2 * (num_used_styles + 1) + 2
705 : 2 * (num_used_styles + 1) + 1)
706 + sizeof (PREP(store_vwidth_data_e));
707 buf_new_len += sizeof (PREP(set_stem_width_mode_a))
709 + sizeof (PREP(set_stem_width_mode_b))
711 + sizeof (PREP(set_stem_width_mode_c))
713 + sizeof (PREP(set_stem_width_mode_d))
715 + sizeof (PREP(set_stem_width_mode_e));
716 buf_new_len += (num_used_styles > 3 ? 2 * num_used_styles + 3
717 : 2 * num_used_styles + 2)
718 + sizeof (PREP(round_blues));
719 buf_new_len += sizeof (PREP(set_dropout_mode));
720 buf_new_len += sizeof (PREP(reset_component_counter));
721 if (font->control_data_head)
722 buf_new_len += sizeof (PREP(adjust_delta_exceptions));
723 buf_new_len += sizeof (PREP(set_default_cvs_values));
725 /* buffer length must be a multiple of four */
726 len = (buf_new_len + 3) & ~3U;
727 buf_new = (FT_Byte*)realloc(buf, len);
728 if (!buf_new)
730 free(buf);
731 return FT_Err_Out_Of_Memory;
733 buf = buf_new;
735 /* pad end of buffer with zeros */
736 buf[len - 1] = 0x00;
737 buf[len - 2] = 0x00;
738 buf[len - 3] = 0x00;
740 /* copy remaining cvt program into buffer */
741 /* and fill in the missing variables */
742 bufp = buf + buf_len;
744 if (font->hinting_limit)
746 COPY_PREP(hinting_limit_a);
747 *(bufp++) = HIGH(font->hinting_limit);
748 *(bufp++) = LOW(font->hinting_limit);
749 COPY_PREP(hinting_limit_b);
752 COPY_PREP(store_funits_to_pixels);
754 if (font->x_height_snapping_exceptions)
755 COPY_PREP(test_exception_a);
757 COPY_PREP(align_x_height_a);
758 if (num_used_styles > 6)
760 BCI(NPUSHB);
761 BCI(num_used_styles + 2);
763 else
764 BCI(PUSHB_1 - 1 + num_used_styles + 2);
765 /* XXX: make this work for offsets > 255 */
766 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
768 if (data->style_ids[i] == 0xFFFFU)
769 continue;
771 *(bufp++) = CVT_X_HEIGHT_BLUE_OFFSET(i) >= 0xFFFFU
773 : (unsigned char)CVT_X_HEIGHT_BLUE_OFFSET(i);
775 *(bufp++) = num_used_styles;
776 COPY_PREP(align_x_height_b);
778 COPY_PREP(loop_cvt_a);
779 if (num_used_styles > 3)
781 BCI(NPUSHB);
782 BCI(2 * num_used_styles + 2);
784 else
785 BCI(PUSHB_1 - 1 + 2 * num_used_styles + 2);
786 /* XXX: make this work for offsets > 255 */
787 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
789 if (data->style_ids[i] == 0xFFFFU)
790 continue;
792 /* don't loop over artificial blue zones */
793 *(bufp++) = (unsigned char)CVT_VERT_STANDARD_WIDTH_OFFSET(i);
794 *(bufp++) = (unsigned char)(
796 + CVT_VERT_WIDTHS_SIZE(i)
797 + (CVT_BLUES_SIZE(i) > 1
798 ? CVT_BLUES_SIZE(i) - (font->windows_compatibility ? 2
799 : 0)
800 : 0));
802 *(bufp++) = num_used_styles;
803 COPY_PREP(loop_cvt_b);
804 if (num_used_styles > 3)
806 BCI(NPUSHB);
807 BCI(2 * num_used_styles + 2);
809 else
810 BCI(PUSHB_1 - 1 + 2 * num_used_styles + 2);
811 /* XXX: make this work for offsets > 255 */
812 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
814 if (data->style_ids[i] == 0xFFFFU)
815 continue;
817 /* don't loop over artificial blue zones */
818 *(bufp++) = (unsigned char)CVT_BLUE_SHOOTS_OFFSET(i);
819 *(bufp++) = (unsigned char)(
820 CVT_BLUES_SIZE(i) > 1
821 ? CVT_BLUES_SIZE(i) - (font->windows_compatibility ? 2
822 : 0)
823 : 0);
825 *(bufp++) = num_used_styles;
826 COPY_PREP(loop_cvt_c);
828 if (font->x_height_snapping_exceptions)
829 COPY_PREP(test_exception_b);
831 COPY_PREP(store_vwidth_data_a);
832 *(bufp++) = (unsigned char)CVT_VWIDTH_OFFSET_DATA(0);
833 COPY_PREP(store_vwidth_data_b);
834 if (num_used_styles > 6)
836 BCI(NPUSHW);
837 BCI(num_used_styles + 2);
839 else
840 BCI(PUSHW_1 - 1 + num_used_styles + 2);
841 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
843 if (data->style_ids[i] == 0xFFFFU)
844 continue;
846 *(bufp++) = HIGH(CVT_VERT_WIDTHS_OFFSET(i) * 64);
847 *(bufp++) = LOW(CVT_VERT_WIDTHS_OFFSET(i) * 64);
849 *(bufp++) = HIGH(num_used_styles);
850 *(bufp++) = LOW(num_used_styles);
851 COPY_PREP(store_vwidth_data_c);
852 *(bufp++) = (unsigned char)CVT_VWIDTH_SIZE_DATA(0);
853 COPY_PREP(store_vwidth_data_d);
854 if (num_used_styles > 6)
856 BCI(NPUSHW);
857 BCI(num_used_styles + 2);
859 else
860 BCI(PUSHW_1 - 1 + num_used_styles + 2);
861 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
863 if (data->style_ids[i] == 0xFFFFU)
864 continue;
866 *(bufp++) = HIGH(CVT_VERT_WIDTHS_SIZE(i) * 64);
867 *(bufp++) = LOW(CVT_VERT_WIDTHS_SIZE(i) * 64);
869 *(bufp++) = HIGH(num_used_styles);
870 *(bufp++) = LOW(num_used_styles);
871 COPY_PREP(store_vwidth_data_e);
873 COPY_PREP(set_stem_width_mode_a);
874 *(bufp++) = HIGH(font->gray_stem_width_mode * 100);
875 *(bufp++) = LOW(font->gray_stem_width_mode * 100);
876 COPY_PREP(set_stem_width_mode_b);
877 *(bufp++) = HIGH(font->gdi_cleartype_stem_width_mode * 100);
878 *(bufp++) = LOW(font->gdi_cleartype_stem_width_mode * 100);
879 COPY_PREP(set_stem_width_mode_c);
880 *(bufp++) = HIGH(font->dw_cleartype_stem_width_mode * 100);
881 *(bufp++) = LOW(font->dw_cleartype_stem_width_mode * 100);
882 COPY_PREP(set_stem_width_mode_d);
883 *(bufp++) = HIGH(font->dw_cleartype_stem_width_mode * 100);
884 *(bufp++) = LOW(font->dw_cleartype_stem_width_mode * 100);
885 COPY_PREP(set_stem_width_mode_e);
887 if (num_used_styles > 3)
889 BCI(NPUSHB);
890 BCI(2 * num_used_styles + 2);
892 else
893 BCI(PUSHB_1 - 1 + 2 * num_used_styles + 2);
894 /* XXX: make this work for offsets > 255 */
895 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
897 if (data->style_ids[i] == 0xFFFFU)
898 continue;
900 *(bufp++) = (unsigned char)CVT_BLUE_REFS_OFFSET(i);
901 *(bufp++) = (unsigned char)CVT_BLUES_SIZE(i);
903 *(bufp++) = num_used_styles;
904 COPY_PREP(round_blues);
906 COPY_PREP(set_dropout_mode);
907 COPY_PREP(reset_component_counter);
908 if (font->control_data_head)
909 COPY_PREP(adjust_delta_exceptions);
910 COPY_PREP(set_default_cvs_values);
912 *prep = buf;
913 *prep_len = buf_new_len;
915 return FT_Err_Ok;
919 FT_Error
920 TA_sfnt_build_prep_table(SFNT* sfnt,
921 FONT* font)
923 FT_Error error;
925 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
926 glyf_Data* data = (glyf_Data*)glyf_table->data;
928 FT_Byte* prep_buf;
929 FT_ULong prep_len;
932 error = TA_sfnt_add_table_info(sfnt);
933 if (error)
934 goto Exit;
936 /* `glyf', `cvt', `fpgm', and `prep' are always used in parallel */
937 if (glyf_table->processed)
939 sfnt->table_infos[sfnt->num_table_infos - 1] = data->prep_idx;
940 goto Exit;
943 error = TA_table_build_prep(&prep_buf, &prep_len, sfnt, font);
944 if (error)
945 goto Exit;
947 #if 0
948 /* ttfautohint's bytecode in `fpgm' is larger */
949 /* than the bytecode in `prep'; */
950 /* this commented out code here is just for completeness */
951 if (prep_len > sfnt->max_instructions)
952 sfnt->max_instructions = prep_len;
953 #endif
955 /* in case of success, `prep_buf' gets linked */
956 /* and is eventually freed in `TA_font_unload' */
957 error = TA_font_add_table(font,
958 &sfnt->table_infos[sfnt->num_table_infos - 1],
959 TTAG_prep, prep_len, prep_buf);
960 if (error)
961 free(prep_buf);
962 else
963 data->prep_idx = sfnt->table_infos[sfnt->num_table_infos - 1];
965 Exit:
966 return error;
969 /* end of taprep.c */