RIP, Vernon...
[ttfautohint.git] / lib / taprep.c
blob3444a35fc141a7c5a5ece1b6f6970b26587023a3
1 /* taprep.c */
3 /*
4 * Copyright (C) 2011-2016 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_smooth_or_strong_a) [] =
230 * There are two ClearType flavours available on Windows: The older GDI
231 * ClearType, introduced in 2000, and the recent DW ClearType, introduced
232 * in 2008. The main difference is that the older incarnation behaves
233 * like a B/W renderer along the y axis, while the newer version does
234 * vertical smoothing also.
236 * The only possibility to differentiate between GDI and DW ClearType is
237 * testing bit 10 in the GETINFO instruction (with return value in bit 17;
238 * this works for TrueType version >= 38), checking whether sub-pixel
239 * positioning is available.
241 * If GDI ClearType is active, we use different functions for stem width
242 * computation and blue zone rounding that snap to integer pixels as much
243 * as possible.
246 /* set default value */
247 PUSHB_2,
248 cvtl_use_strong_functions,
252 /* %c, either 0 or 100 */
254 static const unsigned char PREP(set_smooth_or_strong_b) [] =
257 WCVTP,
259 /* get rasterizer version (bit 0) */
260 PUSHB_2,
262 0x01,
263 GETINFO,
265 /* `GDI ClearType': */
266 /* version >= 36 and version < 38, ClearType enabled */
267 LTEQ,
269 /* check whether ClearType is enabled (bit 6) */
270 PUSHB_1,
271 0x40,
272 GETINFO,
274 PUSHB_2,
275 cvtl_use_strong_functions,
278 /* %c, either 0 or 100 */
280 static const unsigned char PREP(set_smooth_or_strong_c) [] =
283 WCVTP,
285 /* get rasterizer version (bit 0) */
286 PUSHB_2,
288 0x01,
289 GETINFO,
291 /* `DW ClearType': */
292 /* version >= 38, sub-pixel positioning is enabled */
293 LTEQ,
295 /* check whether sub-pixel positioning is enabled (bit 10) -- */
296 /* due to a bug in FreeType 2.5.0 and earlier, */
297 /* bit 6 must be set also to get the correct information, */
298 /* so we test that both return values (in bits 13 and 17) are set */
299 PUSHW_3,
300 0x08, /* bits 13 and 17 shifted by 6 bits */
301 0x80,
302 0x00, /* we do `MUL' with value 1, */
303 0x01, /* which is essentially a division by 64 */
304 0x04, /* bits 6 and 10 */
305 0x40,
306 GETINFO,
307 MUL,
310 PUSHB_2,
311 cvtl_use_strong_functions,
315 /* %c, either 0 or 100 */
317 static const unsigned char PREP(set_smooth_or_strong_d) [] =
320 WCVTP,
321 EIF,
322 EIF,
323 EIF,
324 EIF,
328 /*PUSHB (2*num_used_styles + 2) */
329 /* ... */
330 /* %c, style 1's first blue ref index */
331 /* %c, style 1's number of blue ref indices */
332 /* %c, style 0's first blue ref index */
333 /* %c, style 0's number of blue ref indices */
334 /* %c, num_used_styles */
336 static const unsigned char PREP(round_blues) [] =
339 bci_blue_round_range,
340 LOOPCALL,
344 static const unsigned char PREP(set_dropout_mode) [] =
347 PUSHW_1,
348 0x01, /* 0x01FF, activate dropout handling unconditionally */
349 0xFF,
350 SCANCTRL,
351 PUSHB_1,
352 4, /* smart dropout include stubs */
353 SCANTYPE,
357 static const unsigned char PREP(reset_component_counter) [] =
360 /* In case an application tries to render `.ttfautohint' */
361 /* (which it should never do), */
362 /* hinting of all glyphs rendered afterwards is disabled */
363 /* because the `cvtl_is_subglyph' counter gets incremented, */
364 /* but there is no counterpart to decrement it. */
365 /* Font inspection tools like the FreeType demo programs */
366 /* are an exception to that rule, however, */
367 /* since they can directly access a font by glyph indices. */
368 /* The following guard alleviates the problem a bit: */
369 /* Any change of the graphics state */
370 /* (for example, rendering at a different size or with a different mode) */
371 /* resets the counter to zero. */
372 PUSHB_2,
373 cvtl_is_subglyph,
375 WCVTP,
379 static const unsigned char PREP(adjust_delta_exceptions) [] =
382 /* set delta base */
383 PUSHB_1,
384 CONTROL_DELTA_PPEM_MIN,
385 SDB,
390 static const unsigned char PREP(set_default_cvs_values) [] =
393 /* We set a default value for `cvtl_do_iup_y'. */
394 /* If we have delta exceptions before IUP_y, */
395 /* the glyph's bytecode sets this CVT value temporarily to zero */
396 /* and manually inserts IUP_y afterwards. */
398 /* We set a default value for `cvtl_ignore_std_width'. */
399 /* As the name implies, the stem width computation routines */
400 /* ignore the standard width(s) if this flag gets set. */
402 /* It would be more elegant to use storage area locations instead, */
403 /* however, it is not possible to have default values for them */
404 /* since storage area locations might be reset on a per-glyph basis */
405 /* (this is dependent on the bytecode interpreter implementation). */
407 PUSHB_4,
408 cvtl_do_iup_y,
409 100,
410 cvtl_ignore_std_width,
412 WCVTP,
413 WCVTP,
418 /* this function allocates `buf', parsing `number_set' to create bytecode */
419 /* which eventually sets CVT index `cvtl_is_element' */
420 /* (in functions `bci_number_set_is_element' and */
421 /* `bci_number_set_is_element2') */
423 static FT_Byte*
424 TA_sfnt_build_number_set(SFNT* sfnt,
425 FT_Byte** buf,
426 number_range* number_set)
428 FT_Byte* bufp = NULL;
429 number_range* nr;
431 FT_UInt num_singles2 = 0;
432 FT_UInt* single2_args;
433 FT_UInt* single2_arg;
434 FT_UInt num_singles = 0;
435 FT_UInt* single_args;
436 FT_UInt* single_arg;
438 FT_UInt num_ranges2 = 0;
439 FT_UInt* range2_args;
440 FT_UInt* range2_arg;
441 FT_UInt num_ranges = 0;
442 FT_UInt* range_args;
443 FT_UInt* range_arg;
445 FT_UInt have_single = 0;
446 FT_UInt have_range = 0;
448 FT_UShort num_stack_elements;
451 /* build up four stacks to stay as compact as possible */
452 nr = number_set;
453 while (nr)
455 if (nr->start == nr->end)
457 if (nr->start < 256)
458 num_singles++;
459 else
460 num_singles2++;
462 else
464 if (nr->start < 256 && nr->end < 256)
465 num_ranges++;
466 else
467 num_ranges2++;
469 nr = nr->next;
472 /* collect all arguments temporarily in arrays (in reverse order) */
473 /* so that we can easily split into chunks of 255 args */
474 /* as needed by NPUSHB and friends; */
475 /* for simplicity, always allocate an extra slot */
476 single2_args = (FT_UInt*)malloc((num_singles2 + 1) * sizeof (FT_UInt));
477 single_args = (FT_UInt*)malloc((num_singles + 1) * sizeof (FT_UInt));
478 range2_args = (FT_UInt*)malloc((2 * num_ranges2 + 1) * sizeof (FT_UInt));
479 range_args = (FT_UInt*)malloc((2 * num_ranges + 1) * sizeof (FT_UInt));
480 if (!single2_args || !single_args
481 || !range2_args || !range_args)
482 goto Fail;
484 /* check whether we need the extra slot for the argument to CALL */
485 if (num_singles || num_singles2)
486 have_single = 1;
487 if (num_ranges || num_ranges2)
488 have_range = 1;
490 /* set function indices outside of argument loop (using the extra slot) */
491 if (have_single)
492 single_args[num_singles] = bci_number_set_is_element;
493 if (have_range)
494 range_args[2 * num_ranges] = bci_number_set_is_element2;
496 single2_arg = single2_args + num_singles2 - 1;
497 single_arg = single_args + num_singles - 1;
498 range2_arg = range2_args + 2 * num_ranges2 - 1;
499 range_arg = range_args + 2 * num_ranges - 1;
501 nr = number_set;
502 while (nr)
504 FT_UInt start = (FT_UInt)nr->start;
505 FT_UInt end = (FT_UInt)nr->end;
508 if (start == end)
510 if (start < 256)
511 *(single_arg--) = start;
512 else
513 *(single2_arg--) = start;
515 else
517 if (start < 256 && end < 256)
519 *(range_arg--) = start;
520 *(range_arg--) = end;
522 else
524 *(range2_arg--) = start;
525 *(range2_arg--) = end;
528 nr = nr->next;
531 /* this rough estimate of the buffer size gets adjusted later on */
532 *buf = (FT_Byte*)malloc((2 + 1) * num_singles2
533 + (1 + 1) * num_singles
534 + (4 + 1) * num_ranges2
535 + (2 + 1) * num_ranges
536 + 10);
537 if (!*buf)
538 goto Fail;
539 bufp = *buf;
541 BCI(PUSHB_2);
542 BCI(cvtl_is_element);
543 BCI(0);
544 BCI(WCVTP);
546 bufp = TA_build_push(bufp, single2_args, num_singles2, 1, 1);
547 bufp = TA_build_push(bufp, single_args, num_singles + have_single, 0, 1);
548 if (have_single)
549 BCI(CALL);
551 bufp = TA_build_push(bufp, range2_args, 2 * num_ranges2, 1, 1);
552 bufp = TA_build_push(bufp, range_args, 2 * num_ranges + have_range, 0, 1);
553 if (have_range)
554 BCI(CALL);
556 num_stack_elements = (FT_UShort)(num_singles + num_singles2);
557 if (num_stack_elements > num_ranges + num_ranges2)
558 num_stack_elements = (FT_UShort)(num_ranges + num_ranges2);
559 num_stack_elements += ADDITIONAL_STACK_ELEMENTS;
560 if (num_stack_elements > sfnt->max_stack_elements)
561 sfnt->max_stack_elements = num_stack_elements;
563 Fail:
564 free(single2_args);
565 free(single_args);
566 free(range2_args);
567 free(range_args);
569 return bufp;
573 #define COPY_PREP(snippet_name) \
574 do \
576 memcpy(bufp, prep_ ## snippet_name, \
577 sizeof (prep_ ## snippet_name)); \
578 bufp += sizeof (prep_ ## snippet_name); \
579 } while (0)
581 static FT_Error
582 TA_table_build_prep(FT_Byte** prep,
583 FT_ULong* prep_len,
584 SFNT* sfnt,
585 FONT* font)
587 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
588 glyf_Data* data = (glyf_Data*)glyf_table->data;
589 /* XXX: make this work for more than 256 styles */
590 FT_Byte num_used_styles = (FT_Byte)data->num_used_styles;
592 FT_Int i;
594 FT_Byte* buf = NULL;
595 FT_Byte* buf_new;
596 FT_UInt buf_len;
597 FT_UInt buf_new_len;
599 FT_UInt len;
600 FT_Byte* bufp = NULL;
603 if (font->x_height_snapping_exceptions)
605 bufp = TA_sfnt_build_number_set(sfnt, &buf,
606 font->x_height_snapping_exceptions);
607 if (!bufp)
608 return FT_Err_Out_Of_Memory;
611 buf_len = (FT_UInt)(bufp - buf);
612 buf_new_len = buf_len;
614 if (font->hinting_limit)
615 buf_new_len += sizeof (PREP(hinting_limit_a))
617 + sizeof (PREP(hinting_limit_b));
619 buf_new_len += sizeof (PREP(store_funits_to_pixels));
621 if (font->x_height_snapping_exceptions)
622 buf_new_len += sizeof (PREP(test_exception_a));
624 buf_new_len += sizeof (PREP(align_x_height_a))
625 + (num_used_styles > 6 ? num_used_styles + 3
626 : num_used_styles + 2)
627 + sizeof (PREP(align_x_height_b));
628 buf_new_len += sizeof (PREP(loop_cvt_a))
629 + (num_used_styles > 3 ? 2 * num_used_styles + 3
630 : 2 * num_used_styles + 2)
631 + sizeof (PREP(loop_cvt_b))
632 + (num_used_styles > 3 ? 2 * num_used_styles + 3
633 : 2 * num_used_styles + 2)
634 + sizeof (PREP(loop_cvt_c));
636 if (font->x_height_snapping_exceptions)
637 buf_new_len += sizeof (PREP(test_exception_b));
639 buf_new_len += sizeof (PREP(store_vwidth_data_a))
641 + sizeof (PREP(store_vwidth_data_b))
642 + (num_used_styles > 6 ? 2 * (num_used_styles + 1) + 2
643 : 2 * (num_used_styles + 1) + 1)
644 + sizeof (PREP(store_vwidth_data_c))
646 + sizeof (PREP(store_vwidth_data_d))
647 + (num_used_styles > 6 ? 2 * (num_used_styles + 1) + 2
648 : 2 * (num_used_styles + 1) + 1)
649 + sizeof (PREP(store_vwidth_data_e));
650 buf_new_len += sizeof (PREP(set_smooth_or_strong_a))
652 + sizeof (PREP(set_smooth_or_strong_b))
654 + sizeof (PREP(set_smooth_or_strong_c))
656 + sizeof (PREP(set_smooth_or_strong_d));
657 buf_new_len += (num_used_styles > 3 ? 2 * num_used_styles + 3
658 : 2 * num_used_styles + 2)
659 + sizeof (PREP(round_blues));
660 buf_new_len += sizeof (PREP(set_dropout_mode));
661 buf_new_len += sizeof (PREP(reset_component_counter));
662 if (font->control_data_head)
663 buf_new_len += sizeof (PREP(adjust_delta_exceptions));
664 buf_new_len += sizeof (PREP(set_default_cvs_values));
666 /* buffer length must be a multiple of four */
667 len = (buf_new_len + 3) & ~3U;
668 buf_new = (FT_Byte*)realloc(buf, len);
669 if (!buf_new)
671 free(buf);
672 return FT_Err_Out_Of_Memory;
674 buf = buf_new;
676 /* pad end of buffer with zeros */
677 buf[len - 1] = 0x00;
678 buf[len - 2] = 0x00;
679 buf[len - 3] = 0x00;
681 /* copy remaining cvt program into buffer */
682 /* and fill in the missing variables */
683 bufp = buf + buf_len;
685 if (font->hinting_limit)
687 COPY_PREP(hinting_limit_a);
688 *(bufp++) = HIGH(font->hinting_limit);
689 *(bufp++) = LOW(font->hinting_limit);
690 COPY_PREP(hinting_limit_b);
693 COPY_PREP(store_funits_to_pixels);
695 if (font->x_height_snapping_exceptions)
696 COPY_PREP(test_exception_a);
698 COPY_PREP(align_x_height_a);
699 if (num_used_styles > 6)
701 BCI(NPUSHB);
702 BCI(num_used_styles + 2);
704 else
705 BCI(PUSHB_1 - 1 + num_used_styles + 2);
706 /* XXX: make this work for offsets > 255 */
707 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
709 if (data->style_ids[i] == 0xFFFFU)
710 continue;
712 *(bufp++) = CVT_X_HEIGHT_BLUE_OFFSET(i) >= 0xFFFFU
714 : (unsigned char)CVT_X_HEIGHT_BLUE_OFFSET(i);
716 *(bufp++) = num_used_styles;
717 COPY_PREP(align_x_height_b);
719 COPY_PREP(loop_cvt_a);
720 if (num_used_styles > 3)
722 BCI(NPUSHB);
723 BCI(2 * num_used_styles + 2);
725 else
726 BCI(PUSHB_1 - 1 + 2 * num_used_styles + 2);
727 /* XXX: make this work for offsets > 255 */
728 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
730 if (data->style_ids[i] == 0xFFFFU)
731 continue;
733 /* don't loop over artificial blue zones */
734 *(bufp++) = (unsigned char)CVT_VERT_STANDARD_WIDTH_OFFSET(i);
735 *(bufp++) = (unsigned char)(
737 + CVT_VERT_WIDTHS_SIZE(i)
738 + (CVT_BLUES_SIZE(i) > 1
739 ? CVT_BLUES_SIZE(i) - (font->windows_compatibility ? 2
740 : 0)
741 : 0));
743 *(bufp++) = num_used_styles;
744 COPY_PREP(loop_cvt_b);
745 if (num_used_styles > 3)
747 BCI(NPUSHB);
748 BCI(2 * num_used_styles + 2);
750 else
751 BCI(PUSHB_1 - 1 + 2 * num_used_styles + 2);
752 /* XXX: make this work for offsets > 255 */
753 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
755 if (data->style_ids[i] == 0xFFFFU)
756 continue;
758 /* don't loop over artificial blue zones */
759 *(bufp++) = (unsigned char)CVT_BLUE_SHOOTS_OFFSET(i);
760 *(bufp++) = (unsigned char)(
761 CVT_BLUES_SIZE(i) > 1
762 ? CVT_BLUES_SIZE(i) - (font->windows_compatibility ? 2
763 : 0)
764 : 0);
766 *(bufp++) = num_used_styles;
767 COPY_PREP(loop_cvt_c);
769 if (font->x_height_snapping_exceptions)
770 COPY_PREP(test_exception_b);
772 COPY_PREP(store_vwidth_data_a);
773 *(bufp++) = (unsigned char)CVT_VWIDTH_OFFSET_DATA(0);
774 COPY_PREP(store_vwidth_data_b);
775 if (num_used_styles > 6)
777 BCI(NPUSHW);
778 BCI(num_used_styles + 2);
780 else
781 BCI(PUSHW_1 - 1 + num_used_styles + 2);
782 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
784 if (data->style_ids[i] == 0xFFFFU)
785 continue;
787 *(bufp++) = HIGH(CVT_VERT_WIDTHS_OFFSET(i) * 64);
788 *(bufp++) = LOW(CVT_VERT_WIDTHS_OFFSET(i) * 64);
790 *(bufp++) = HIGH(num_used_styles);
791 *(bufp++) = LOW(num_used_styles);
792 COPY_PREP(store_vwidth_data_c);
793 *(bufp++) = (unsigned char)CVT_VWIDTH_SIZE_DATA(0);
794 COPY_PREP(store_vwidth_data_d);
795 if (num_used_styles > 6)
797 BCI(NPUSHW);
798 BCI(num_used_styles + 2);
800 else
801 BCI(PUSHW_1 - 1 + num_used_styles + 2);
802 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
804 if (data->style_ids[i] == 0xFFFFU)
805 continue;
807 *(bufp++) = HIGH(CVT_VERT_WIDTHS_SIZE(i) * 64);
808 *(bufp++) = LOW(CVT_VERT_WIDTHS_SIZE(i) * 64);
810 *(bufp++) = HIGH(num_used_styles);
811 *(bufp++) = LOW(num_used_styles);
812 COPY_PREP(store_vwidth_data_e);
814 COPY_PREP(set_smooth_or_strong_a);
815 *(bufp++) = font->gray_strong_stem_width ? 100 : 0;
816 COPY_PREP(set_smooth_or_strong_b);
817 *(bufp++) = font->gdi_cleartype_strong_stem_width ? 100 : 0;
818 COPY_PREP(set_smooth_or_strong_c);
819 *(bufp++) = font->dw_cleartype_strong_stem_width ? 100 : 0;
820 COPY_PREP(set_smooth_or_strong_d);
822 if (num_used_styles > 3)
824 BCI(NPUSHB);
825 BCI(2 * num_used_styles + 2);
827 else
828 BCI(PUSHB_1 - 1 + 2 * num_used_styles + 2);
829 /* XXX: make this work for offsets > 255 */
830 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
832 if (data->style_ids[i] == 0xFFFFU)
833 continue;
835 *(bufp++) = (unsigned char)CVT_BLUE_REFS_OFFSET(i);
836 *(bufp++) = (unsigned char)CVT_BLUES_SIZE(i);
838 *(bufp++) = num_used_styles;
839 COPY_PREP(round_blues);
841 COPY_PREP(set_dropout_mode);
842 COPY_PREP(reset_component_counter);
843 if (font->control_data_head)
844 COPY_PREP(adjust_delta_exceptions);
845 COPY_PREP(set_default_cvs_values);
847 *prep = buf;
848 *prep_len = buf_new_len;
850 return FT_Err_Ok;
854 FT_Error
855 TA_sfnt_build_prep_table(SFNT* sfnt,
856 FONT* font)
858 FT_Error error;
860 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
861 glyf_Data* data = (glyf_Data*)glyf_table->data;
863 FT_Byte* prep_buf;
864 FT_ULong prep_len;
867 error = TA_sfnt_add_table_info(sfnt);
868 if (error)
869 goto Exit;
871 /* `glyf', `cvt', `fpgm', and `prep' are always used in parallel */
872 if (glyf_table->processed)
874 sfnt->table_infos[sfnt->num_table_infos - 1] = data->prep_idx;
875 goto Exit;
878 error = TA_table_build_prep(&prep_buf, &prep_len, sfnt, font);
879 if (error)
880 goto Exit;
882 #if 0
883 /* ttfautohint's bytecode in `fpgm' is larger */
884 /* than the bytecode in `prep'; */
885 /* this commented out code here is just for completeness */
886 if (prep_len > sfnt->max_instructions)
887 sfnt->max_instructions = prep_len;
888 #endif
890 /* in case of success, `prep_buf' gets linked */
891 /* and is eventually freed in `TA_font_unload' */
892 error = TA_font_add_table(font,
893 &sfnt->table_infos[sfnt->num_table_infos - 1],
894 TTAG_prep, prep_len, prep_buf);
895 if (error)
896 free(prep_buf);
897 else
898 data->prep_idx = sfnt->table_infos[sfnt->num_table_infos - 1];
900 Exit:
901 return error;
904 /* end of taprep.c */