Add missing file to `make dist'.
[ttfautohint.git] / lib / taprep.c
blob34d623b71ec455a04913dd86db526594985ad561
1 /* taprep.c */
3 /*
4 * Copyright (C) 2011-2015 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 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 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 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 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 const unsigned char PREP(align_top_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 const unsigned char PREP(align_top_b) [] =
104 bci_align_top,
105 LOOPCALL,
109 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 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 const unsigned char PREP(loop_cvt_c) [] =
155 bci_cvt_rescale_range,
156 LOOPCALL,
160 const unsigned char PREP(test_exception_b) [] =
163 EIF,
167 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 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 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 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 const unsigned char PREP(store_vwidth_data_e) [] =
220 0x00, /* high byte */
221 bci_vwidth_data_store, /* low byte */
222 LOOPCALL,
226 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 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 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 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 const unsigned char PREP(round_blues) [] =
339 bci_blue_round_range,
340 LOOPCALL,
344 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 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 const unsigned char PREP(adjust_delta_exceptions) [] =
382 /* set delta base */
383 PUSHB_1,
384 CONTROL_DELTA_PPEM_MIN,
385 SDB,
390 const unsigned char PREP(do_iup_y) [] =
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. */
397 /* It would be more elegant to use a storage area location instead, */
398 /* however, it is not possible to have a default value for them */
399 /* since storage area locations might be reset on a per-glyph basis */
400 /* (this is dependent on the bytecode interpreter implementation). */
401 PUSHB_2,
402 cvtl_do_iup_y,
403 100,
404 WCVTP,
409 /* this function allocates `buf', parsing `number_set' to create bytecode */
410 /* which eventually sets CVT index `cvtl_is_element' */
411 /* (in functions `bci_number_set_is_element' and */
412 /* `bci_number_set_is_element2') */
414 static FT_Byte*
415 TA_sfnt_build_number_set(SFNT* sfnt,
416 FT_Byte** buf,
417 number_range* number_set)
419 FT_Byte* bufp = NULL;
420 number_range* nr;
422 FT_UInt num_singles2 = 0;
423 FT_UInt* single2_args;
424 FT_UInt* single2_arg;
425 FT_UInt num_singles = 0;
426 FT_UInt* single_args;
427 FT_UInt* single_arg;
429 FT_UInt num_ranges2 = 0;
430 FT_UInt* range2_args;
431 FT_UInt* range2_arg;
432 FT_UInt num_ranges = 0;
433 FT_UInt* range_args;
434 FT_UInt* range_arg;
436 FT_UInt have_single = 0;
437 FT_UInt have_range = 0;
439 FT_UShort num_stack_elements;
442 /* build up four stacks to stay as compact as possible */
443 nr = number_set;
444 while (nr)
446 if (nr->start == nr->end)
448 if (nr->start < 256)
449 num_singles++;
450 else
451 num_singles2++;
453 else
455 if (nr->start < 256 && nr->end < 256)
456 num_ranges++;
457 else
458 num_ranges2++;
460 nr = nr->next;
463 /* collect all arguments temporarily in arrays (in reverse order) */
464 /* so that we can easily split into chunks of 255 args */
465 /* as needed by NPUSHB and friends; */
466 /* for simplicity, always allocate an extra slot */
467 single2_args = (FT_UInt*)malloc((num_singles2 + 1) * sizeof (FT_UInt));
468 single_args = (FT_UInt*)malloc((num_singles + 1) * sizeof (FT_UInt));
469 range2_args = (FT_UInt*)malloc((2 * num_ranges2 + 1) * sizeof (FT_UInt));
470 range_args = (FT_UInt*)malloc((2 * num_ranges + 1) * sizeof (FT_UInt));
471 if (!single2_args || !single_args
472 || !range2_args || !range_args)
473 goto Fail;
475 /* check whether we need the extra slot for the argument to CALL */
476 if (num_singles || num_singles2)
477 have_single = 1;
478 if (num_ranges || num_ranges2)
479 have_range = 1;
481 /* set function indices outside of argument loop (using the extra slot) */
482 if (have_single)
483 single_args[num_singles] = bci_number_set_is_element;
484 if (have_range)
485 range_args[2 * num_ranges] = bci_number_set_is_element2;
487 single2_arg = single2_args + num_singles2 - 1;
488 single_arg = single_args + num_singles - 1;
489 range2_arg = range2_args + 2 * num_ranges2 - 1;
490 range_arg = range_args + 2 * num_ranges - 1;
492 nr = number_set;
493 while (nr)
495 if (nr->start == nr->end)
497 if (nr->start < 256)
498 *(single_arg--) = nr->start;
499 else
500 *(single2_arg--) = nr->start;
502 else
504 if (nr->start < 256 && nr->end < 256)
506 *(range_arg--) = nr->start;
507 *(range_arg--) = nr->end;
509 else
511 *(range2_arg--) = nr->start;
512 *(range2_arg--) = nr->end;
515 nr = nr->next;
518 /* this rough estimate of the buffer size gets adjusted later on */
519 *buf = (FT_Byte*)malloc((2 + 1) * num_singles2
520 + (1 + 1) * num_singles
521 + (4 + 1) * num_ranges2
522 + (2 + 1) * num_ranges
523 + 10);
524 if (!*buf)
525 goto Fail;
526 bufp = *buf;
528 BCI(PUSHB_2);
529 BCI(cvtl_is_element);
530 BCI(0);
531 BCI(WCVTP);
533 bufp = TA_build_push(bufp, single2_args, num_singles2, 1, 1);
534 bufp = TA_build_push(bufp, single_args, num_singles + have_single, 0, 1);
535 if (have_single)
536 BCI(CALL);
538 bufp = TA_build_push(bufp, range2_args, 2 * num_ranges2, 1, 1);
539 bufp = TA_build_push(bufp, range_args, 2 * num_ranges + have_range, 0, 1);
540 if (have_range)
541 BCI(CALL);
543 num_stack_elements = num_singles + num_singles2;
544 if (num_stack_elements > num_ranges + num_ranges2)
545 num_stack_elements = num_ranges + num_ranges2;
546 num_stack_elements += ADDITIONAL_STACK_ELEMENTS;
547 if (num_stack_elements > sfnt->max_stack_elements)
548 sfnt->max_stack_elements = num_stack_elements;
550 Fail:
551 free(single2_args);
552 free(single_args);
553 free(range2_args);
554 free(range_args);
556 return bufp;
560 #define COPY_PREP(snippet_name) \
561 do \
563 memcpy(bufp, prep_ ## snippet_name, \
564 sizeof (prep_ ## snippet_name)); \
565 bufp += sizeof (prep_ ## snippet_name); \
566 } while (0)
568 static FT_Error
569 TA_table_build_prep(FT_Byte** prep,
570 FT_ULong* prep_len,
571 SFNT* sfnt,
572 FONT* font)
574 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
575 glyf_Data* data = (glyf_Data*)glyf_table->data;
577 FT_Int i;
579 FT_Byte* buf = NULL;
580 FT_Byte* buf_new;
581 FT_UInt buf_len;
582 FT_UInt buf_new_len;
584 FT_UInt len;
585 FT_Byte* bufp = NULL;
588 if (font->x_height_snapping_exceptions)
590 bufp = TA_sfnt_build_number_set(sfnt, &buf,
591 font->x_height_snapping_exceptions);
592 if (!bufp)
593 return FT_Err_Out_Of_Memory;
596 buf_len = bufp - buf;
597 buf_new_len = buf_len;
599 if (font->hinting_limit)
600 buf_new_len += sizeof (PREP(hinting_limit_a))
602 + sizeof (PREP(hinting_limit_b));
604 buf_new_len += sizeof (PREP(store_funits_to_pixels));
606 if (font->x_height_snapping_exceptions)
607 buf_new_len += sizeof (PREP(test_exception_a));
609 buf_new_len += sizeof (PREP(align_top_a))
610 + (data->num_used_styles > 6
611 ? data->num_used_styles + 3
612 : data->num_used_styles + 2)
613 + sizeof (PREP(align_top_b));
614 buf_new_len += sizeof (PREP(loop_cvt_a))
615 + (data->num_used_styles > 3
616 ? 2 * data->num_used_styles + 3
617 : 2 * data->num_used_styles + 2)
618 + sizeof (PREP(loop_cvt_b))
619 + (data->num_used_styles > 3
620 ? 2 * data->num_used_styles + 3
621 : 2 * data->num_used_styles + 2)
622 + sizeof (PREP(loop_cvt_c));
624 if (font->x_height_snapping_exceptions)
625 buf_new_len += sizeof (PREP(test_exception_b));
627 buf_new_len += sizeof (PREP(store_vwidth_data_a))
629 + sizeof (PREP(store_vwidth_data_b))
630 + (data->num_used_styles > 6
631 ? 2 * (data->num_used_styles + 1) + 2
632 : 2 * (data->num_used_styles + 1) + 1)
633 + sizeof (PREP(store_vwidth_data_c))
635 + sizeof (PREP(store_vwidth_data_d))
636 + (data->num_used_styles > 6
637 ? 2 * (data->num_used_styles + 1) + 2
638 : 2 * (data->num_used_styles + 1) + 1)
639 + sizeof (PREP(store_vwidth_data_e));
640 buf_new_len += sizeof (PREP(set_smooth_or_strong_a))
642 + sizeof (PREP(set_smooth_or_strong_b))
644 + sizeof (PREP(set_smooth_or_strong_c))
646 + sizeof (PREP(set_smooth_or_strong_d));
647 buf_new_len += (data->num_used_styles > 3
648 ? 2 * data->num_used_styles + 3
649 : 2 * data->num_used_styles + 2)
650 + sizeof (PREP(round_blues));
651 buf_new_len += sizeof (PREP(set_dropout_mode));
652 buf_new_len += sizeof (PREP(reset_component_counter));
653 if (font->control_data_head)
654 buf_new_len += sizeof (PREP(adjust_delta_exceptions));
655 buf_new_len += sizeof (PREP(do_iup_y));
657 /* buffer length must be a multiple of four */
658 len = (buf_new_len + 3) & ~3;
659 buf_new = (FT_Byte*)realloc(buf, len);
660 if (!buf_new)
662 free(buf);
663 return FT_Err_Out_Of_Memory;
665 buf = buf_new;
667 /* pad end of buffer with zeros */
668 buf[len - 1] = 0x00;
669 buf[len - 2] = 0x00;
670 buf[len - 3] = 0x00;
672 /* copy remaining cvt program into buffer */
673 /* and fill in the missing variables */
674 bufp = buf + buf_len;
676 if (font->hinting_limit)
678 COPY_PREP(hinting_limit_a);
679 *(bufp++) = HIGH(font->hinting_limit);
680 *(bufp++) = LOW(font->hinting_limit);
681 COPY_PREP(hinting_limit_b);
684 COPY_PREP(store_funits_to_pixels);
686 if (font->x_height_snapping_exceptions)
687 COPY_PREP(test_exception_a);
689 COPY_PREP(align_top_a);
690 if (data->num_used_styles > 6)
692 BCI(NPUSHB);
693 BCI(data->num_used_styles + 2);
695 else
696 BCI(PUSHB_1 - 1 + data->num_used_styles + 2);
697 /* XXX: make this work for offsets > 255 */
698 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
700 if (data->style_ids[i] == 0xFFFFU)
701 continue;
703 *(bufp++) = CVT_X_HEIGHT_BLUE_OFFSET(i) >= 0xFFFFU
705 : (unsigned char)CVT_X_HEIGHT_BLUE_OFFSET(i);
707 *(bufp++) = data->num_used_styles;
708 COPY_PREP(align_top_b);
710 COPY_PREP(loop_cvt_a);
711 if (data->num_used_styles > 3)
713 BCI(NPUSHB);
714 BCI(2 * data->num_used_styles + 2);
716 else
717 BCI(PUSHB_1 - 1 + 2 * data->num_used_styles + 2);
718 /* XXX: make this work for offsets > 255 */
719 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
721 if (data->style_ids[i] == 0xFFFFU)
722 continue;
724 /* don't loop over artificial blue zones */
725 *(bufp++) = (unsigned char)CVT_VERT_STANDARD_WIDTH_OFFSET(i);
726 *(bufp++) = (unsigned char)(
728 + CVT_VERT_WIDTHS_SIZE(i)
729 + (CVT_BLUES_SIZE(i) > 1 ? CVT_BLUES_SIZE(i) - 2 : 0));
731 *(bufp++) = data->num_used_styles;
732 COPY_PREP(loop_cvt_b);
733 if (data->num_used_styles > 3)
735 BCI(NPUSHB);
736 BCI(2 * data->num_used_styles + 2);
738 else
739 BCI(PUSHB_1 - 1 + 2 * data->num_used_styles + 2);
740 /* XXX: make this work for offsets > 255 */
741 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
743 if (data->style_ids[i] == 0xFFFFU)
744 continue;
746 /* don't loop over artificial blue zones */
747 *(bufp++) = (unsigned char)CVT_BLUE_SHOOTS_OFFSET(i);
748 *(bufp++) = (unsigned char)(
749 CVT_BLUES_SIZE(i) > 1 ? CVT_BLUES_SIZE(i) - 2 : 0);
751 *(bufp++) = data->num_used_styles;
752 COPY_PREP(loop_cvt_c);
754 if (font->x_height_snapping_exceptions)
755 COPY_PREP(test_exception_b);
757 COPY_PREP(store_vwidth_data_a);
758 *(bufp++) = (unsigned char)CVT_VWIDTH_OFFSET_DATA(0);
759 COPY_PREP(store_vwidth_data_b);
760 if (data->num_used_styles > 6)
762 BCI(NPUSHW);
763 BCI(data->num_used_styles + 2);
765 else
766 BCI(PUSHW_1 - 1 + data->num_used_styles + 2);
767 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
769 if (data->style_ids[i] == 0xFFFFU)
770 continue;
772 *(bufp++) = HIGH(CVT_VERT_WIDTHS_OFFSET(i) * 64);
773 *(bufp++) = LOW(CVT_VERT_WIDTHS_OFFSET(i) * 64);
775 *(bufp++) = HIGH(data->num_used_styles);
776 *(bufp++) = LOW(data->num_used_styles);
777 COPY_PREP(store_vwidth_data_c);
778 *(bufp++) = (unsigned char)CVT_VWIDTH_SIZE_DATA(0);
779 COPY_PREP(store_vwidth_data_d);
780 if (data->num_used_styles > 6)
782 BCI(NPUSHW);
783 BCI(data->num_used_styles + 2);
785 else
786 BCI(PUSHW_1 - 1 + data->num_used_styles + 2);
787 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
789 if (data->style_ids[i] == 0xFFFFU)
790 continue;
792 *(bufp++) = HIGH(CVT_VERT_WIDTHS_SIZE(i) * 64);
793 *(bufp++) = LOW(CVT_VERT_WIDTHS_SIZE(i) * 64);
795 *(bufp++) = HIGH(data->num_used_styles);
796 *(bufp++) = LOW(data->num_used_styles);
797 COPY_PREP(store_vwidth_data_e);
799 COPY_PREP(set_smooth_or_strong_a);
800 *(bufp++) = font->gray_strong_stem_width ? 100 : 0;
801 COPY_PREP(set_smooth_or_strong_b);
802 *(bufp++) = font->gdi_cleartype_strong_stem_width ? 100 : 0;
803 COPY_PREP(set_smooth_or_strong_c);
804 *(bufp++) = font->dw_cleartype_strong_stem_width ? 100 : 0;
805 COPY_PREP(set_smooth_or_strong_d);
807 if (data->num_used_styles > 3)
809 BCI(NPUSHB);
810 BCI(2 * data->num_used_styles + 2);
812 else
813 BCI(PUSHB_1 - 1 + 2 * data->num_used_styles + 2);
814 /* XXX: make this work for offsets > 255 */
815 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
817 if (data->style_ids[i] == 0xFFFFU)
818 continue;
820 *(bufp++) = (unsigned char)CVT_BLUE_REFS_OFFSET(i);
821 *(bufp++) = (unsigned char)CVT_BLUES_SIZE(i);
823 *(bufp++) = data->num_used_styles;
824 COPY_PREP(round_blues);
826 COPY_PREP(set_dropout_mode);
827 COPY_PREP(reset_component_counter);
828 if (font->control_data_head)
829 COPY_PREP(adjust_delta_exceptions);
830 COPY_PREP(do_iup_y);
832 *prep = buf;
833 *prep_len = buf_new_len;
835 return FT_Err_Ok;
839 FT_Error
840 TA_sfnt_build_prep_table(SFNT* sfnt,
841 FONT* font)
843 FT_Error error;
845 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
846 glyf_Data* data = (glyf_Data*)glyf_table->data;
848 FT_Byte* prep_buf;
849 FT_ULong prep_len;
852 error = TA_sfnt_add_table_info(sfnt);
853 if (error)
854 goto Exit;
856 /* `glyf', `cvt', `fpgm', and `prep' are always used in parallel */
857 if (glyf_table->processed)
859 sfnt->table_infos[sfnt->num_table_infos - 1] = data->prep_idx;
860 goto Exit;
863 error = TA_table_build_prep(&prep_buf, &prep_len, sfnt, font);
864 if (error)
865 goto Exit;
867 #if 0
868 /* ttfautohint's bytecode in `fpgm' is larger */
869 /* than the bytecode in `prep'; */
870 /* this commented out code here is just for completeness */
871 if (prep_len > sfnt->max_instructions)
872 sfnt->max_instructions = prep_len;
873 #endif
875 /* in case of success, `prep_buf' gets linked */
876 /* and is eventually freed in `TA_font_unload' */
877 error = TA_font_add_table(font,
878 &sfnt->table_infos[sfnt->num_table_infos - 1],
879 TTAG_prep, prep_len, prep_buf);
880 if (error)
881 free(prep_buf);
882 else
883 data->prep_idx = sfnt->table_infos[sfnt->num_table_infos - 1];
885 Exit:
886 return error;
889 /* end of taprep.c */