Fix incorrect data in `prep' table.
[ttfautohint.git] / lib / taprep.c
blobadecdaaebc20d6da74609c4fc837c257f9a5af4e
1 /* taprep.c */
3 /*
4 * Copyright (C) 2011-2014 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 /* 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 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 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 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 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 unsigned char PREP(align_top_b) [] =
104 bci_align_top,
105 LOOPCALL,
109 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 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 unsigned char PREP(loop_cvt_c) [] =
155 bci_cvt_rescale_range,
156 LOOPCALL,
160 unsigned char PREP(test_exception_b) [] =
163 EIF,
167 unsigned char PREP(store_vwidth_data_a) [] =
170 PUSHB_2,
171 sal_i,
175 /* %c, offset to vertical width offset data in CVT */
177 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 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 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 unsigned char PREP(store_vwidth_data_e) [] =
220 0x00, /* high byte */
221 bci_vwidth_data_store, /* low byte */
222 LOOPCALL,
226 /*PUSHB (2*num_used_styles + 2) */
227 /* ... */
228 /* %c, style 1's first blue ref index */
229 /* %c, style 1's number of blue ref indices */
230 /* %c, style 0's first blue ref index */
231 /* %c, style 0's number of blue ref indices */
232 /* %c, num_used_styles */
234 unsigned char PREP(round_blues) [] =
237 bci_blue_round_range,
238 LOOPCALL,
242 unsigned char PREP(set_stem_width_handling_a) [] =
246 * There are two ClearType flavours available on Windows: The older GDI
247 * ClearType, introduced in 2000, and the recent DW ClearType, introduced
248 * in 2008. The main difference is that the older incarnation behaves
249 * like a B/W renderer along the y axis, while the newer version does
250 * vertical smoothing also.
252 * The only possibility to differentiate between GDI and DW ClearType is
253 * testing bit 10 in the GETINFO instruction (with return value in bit 17;
254 * this works for TrueType version >= 38), checking whether sub-pixel
255 * positioning is available.
257 * If GDI ClearType is active, we use a different stem width function
258 * which snaps to integer pixels as much as possible.
261 /* set default positioning */
262 PUSHB_2,
263 cvtl_use_strong_stem_width_function,
267 /* %c, either 0 or 100 */
269 unsigned char PREP(set_stem_width_handling_b) [] =
272 WCVTP,
274 /* get rasterizer version (bit 0) */
275 PUSHB_2,
277 0x01,
278 GETINFO,
280 /* `GDI ClearType': */
281 /* version >= 36 and version < 38, ClearType enabled */
282 LTEQ,
284 /* check whether ClearType is enabled (bit 6) */
285 PUSHB_1,
286 0x40,
287 GETINFO,
289 PUSHB_2,
290 cvtl_use_strong_stem_width_function,
293 /* %c, either 0 or 100 */
295 unsigned char PREP(set_stem_width_handling_c) [] =
298 WCVTP,
300 /* get rasterizer version (bit 0) */
301 PUSHB_2,
303 0x01,
304 GETINFO,
306 /* `DW ClearType': */
307 /* version >= 38, sub-pixel positioning is enabled */
308 LTEQ,
310 /* check whether sub-pixel positioning is enabled (bit 10) -- */
311 /* due to a bug in FreeType 2.5.0 and earlier, */
312 /* bit 6 must be set also to get the correct information, */
313 /* so we test that both return values (in bits 13 and 17) are set */
314 PUSHW_3,
315 0x08, /* bits 13 and 17 shifted by 6 bits */
316 0x80,
317 0x00, /* we do `MUL' with value 1, */
318 0x01, /* which is essentially a division by 64 */
319 0x04, /* bits 6 and 10 */
320 0x40,
321 GETINFO,
322 MUL,
325 PUSHB_2,
326 cvtl_use_strong_stem_width_function,
330 /* %c, either 0 or 100 */
332 unsigned char PREP(set_stem_width_handling_d) [] =
335 WCVTP,
336 EIF,
337 EIF,
338 EIF,
339 EIF,
343 unsigned char PREP(set_dropout_mode) [] =
346 PUSHW_1,
347 0x01, /* 0x01FF, activate dropout handling unconditionally */
348 0xFF,
349 SCANCTRL,
350 PUSHB_1,
351 4, /* smart dropout include stubs */
352 SCANTYPE,
356 unsigned char PREP(reset_component_counter) [] =
359 /* In case an application tries to render `.ttfautohint' */
360 /* (which it should never do), */
361 /* hinting of all glyphs rendered afterwards is disabled */
362 /* because the `cvtl_is_subglyph' counter gets incremented, */
363 /* but there is no counterpart to decrement it. */
364 /* Font inspection tools like the FreeType demo programs */
365 /* are an exception to that rule, however, */
366 /* since they can directly access a font by glyph indices. */
367 /* The following guard alleviates the problem a bit: */
368 /* Any change of the graphics state */
369 /* (for example, rendering at a different size or with a different mode) */
370 /* resets the counter to zero. */
371 PUSHB_2,
372 cvtl_is_subglyph,
374 WCVTP,
379 /* this function allocates `buf', parsing `number_set' to create bytecode */
380 /* which eventually sets CVT index `cvtl_is_element' */
381 /* (in functions `bci_number_set_is_element' and */
382 /* `bci_number_set_is_element2') */
384 static FT_Byte*
385 TA_sfnt_build_number_set(SFNT* sfnt,
386 FT_Byte** buf,
387 number_range* number_set)
389 FT_Byte* bufp = NULL;
390 number_range* nr;
392 FT_UInt num_singles2 = 0;
393 FT_UInt* single2_args;
394 FT_UInt* single2_arg;
395 FT_UInt num_singles = 0;
396 FT_UInt* single_args;
397 FT_UInt* single_arg;
399 FT_UInt num_ranges2 = 0;
400 FT_UInt* range2_args;
401 FT_UInt* range2_arg;
402 FT_UInt num_ranges = 0;
403 FT_UInt* range_args;
404 FT_UInt* range_arg;
406 FT_UInt have_single = 0;
407 FT_UInt have_range = 0;
409 FT_UShort num_stack_elements;
412 /* build up four stacks to stay as compact as possible */
413 nr = number_set;
414 while (nr)
416 if (nr->start == nr->end)
418 if (nr->start < 256)
419 num_singles++;
420 else
421 num_singles2++;
423 else
425 if (nr->start < 256 && nr->end < 256)
426 num_ranges++;
427 else
428 num_ranges2++;
430 nr = nr->next;
433 /* collect all arguments temporarily in arrays (in reverse order) */
434 /* so that we can easily split into chunks of 255 args */
435 /* as needed by NPUSHB and friends; */
436 /* for simplicity, always allocate an extra slot */
437 single2_args = (FT_UInt*)malloc((num_singles2 + 1) * sizeof (FT_UInt));
438 single_args = (FT_UInt*)malloc((num_singles + 1) * sizeof (FT_UInt));
439 range2_args = (FT_UInt*)malloc((2 * num_ranges2 + 1) * sizeof (FT_UInt));
440 range_args = (FT_UInt*)malloc((2 * num_ranges + 1) * sizeof (FT_UInt));
441 if (!single2_args || !single_args
442 || !range2_args || !range_args)
443 goto Fail;
445 /* check whether we need the extra slot for the argument to CALL */
446 if (num_singles || num_singles2)
447 have_single = 1;
448 if (num_ranges || num_ranges2)
449 have_range = 1;
451 /* set function indices outside of argument loop (using the extra slot) */
452 if (have_single)
453 single_args[num_singles] = bci_number_set_is_element;
454 if (have_range)
455 range_args[2 * num_ranges] = bci_number_set_is_element2;
457 single2_arg = single2_args + num_singles2 - 1;
458 single_arg = single_args + num_singles - 1;
459 range2_arg = range2_args + 2 * num_ranges2 - 1;
460 range_arg = range_args + 2 * num_ranges - 1;
462 nr = number_set;
463 while (nr)
465 if (nr->start == nr->end)
467 if (nr->start < 256)
468 *(single_arg--) = nr->start;
469 else
470 *(single2_arg--) = nr->start;
472 else
474 if (nr->start < 256 && nr->end < 256)
476 *(range_arg--) = nr->start;
477 *(range_arg--) = nr->end;
479 else
481 *(range2_arg--) = nr->start;
482 *(range2_arg--) = nr->end;
485 nr = nr->next;
488 /* this rough estimate of the buffer size gets adjusted later on */
489 *buf = (FT_Byte*)malloc((2 + 1) * num_singles2
490 + (1 + 1) * num_singles
491 + (4 + 1) * num_ranges2
492 + (2 + 1) * num_ranges
493 + 10);
494 if (!*buf)
495 goto Fail;
496 bufp = *buf;
498 BCI(PUSHB_2);
499 BCI(cvtl_is_element);
500 BCI(0);
501 BCI(WCVTP);
503 bufp = TA_build_push(bufp, single2_args, num_singles2, 1, 1);
504 bufp = TA_build_push(bufp, single_args, num_singles + have_single, 0, 1);
505 if (have_single)
506 BCI(CALL);
508 bufp = TA_build_push(bufp, range2_args, 2 * num_ranges2, 1, 1);
509 bufp = TA_build_push(bufp, range_args, 2 * num_ranges + have_range, 0, 1);
510 if (have_range)
511 BCI(CALL);
513 num_stack_elements = num_singles + num_singles2;
514 if (num_stack_elements > num_ranges + num_ranges2)
515 num_stack_elements = num_ranges + num_ranges2;
516 num_stack_elements += ADDITIONAL_STACK_ELEMENTS;
517 if (num_stack_elements > sfnt->max_stack_elements)
518 sfnt->max_stack_elements = num_stack_elements;
520 Fail:
521 free(single2_args);
522 free(single_args);
523 free(range2_args);
524 free(range_args);
526 return bufp;
530 #define COPY_PREP(snippet_name) \
531 do \
533 memcpy(bufp, prep_ ## snippet_name, \
534 sizeof (prep_ ## snippet_name)); \
535 bufp += sizeof (prep_ ## snippet_name); \
536 } while (0)
538 static FT_Error
539 TA_table_build_prep(FT_Byte** prep,
540 FT_ULong* prep_len,
541 SFNT* sfnt,
542 FONT* font)
544 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
545 glyf_Data* data = (glyf_Data*)glyf_table->data;
547 FT_Int i;
549 FT_Byte* buf = NULL;
550 FT_Byte* buf_new;
551 FT_UInt buf_len;
552 FT_UInt buf_new_len;
554 FT_UInt len;
555 FT_Byte* bufp = NULL;
558 if (font->x_height_snapping_exceptions)
560 bufp = TA_sfnt_build_number_set(sfnt, &buf,
561 font->x_height_snapping_exceptions);
562 if (!bufp)
563 return FT_Err_Out_Of_Memory;
566 buf_len = bufp - buf;
567 buf_new_len = buf_len;
569 if (font->hinting_limit)
570 buf_new_len += sizeof (PREP(hinting_limit_a))
572 + sizeof (PREP(hinting_limit_b));
574 buf_new_len += sizeof (PREP(store_funits_to_pixels));
576 if (font->x_height_snapping_exceptions)
577 buf_new_len += sizeof (PREP(test_exception_a));
579 buf_new_len += sizeof (PREP(align_top_a))
580 + (data->num_used_styles > 6
581 ? data->num_used_styles + 3
582 : data->num_used_styles + 2)
583 + sizeof (PREP(align_top_b));
584 buf_new_len += sizeof (PREP(loop_cvt_a))
585 + (data->num_used_styles > 3
586 ? 2 * data->num_used_styles + 3
587 : 2 * data->num_used_styles + 2)
588 + sizeof (PREP(loop_cvt_b))
589 + (data->num_used_styles > 3
590 ? 2 * data->num_used_styles + 3
591 : 2 * data->num_used_styles + 2)
592 + sizeof (PREP(loop_cvt_c));
594 if (font->x_height_snapping_exceptions)
595 buf_new_len += sizeof (PREP(test_exception_b));
597 buf_new_len += sizeof (PREP(store_vwidth_data_a))
599 + sizeof (PREP(store_vwidth_data_b))
600 + (data->num_used_styles > 6
601 ? 2 * (data->num_used_styles + 1) + 2
602 : 2 * (data->num_used_styles + 1) + 1)
603 + sizeof (PREP(store_vwidth_data_c))
605 + sizeof (PREP(store_vwidth_data_d))
606 + (data->num_used_styles > 6
607 ? 2 * (data->num_used_styles + 1) + 2
608 : 2 * (data->num_used_styles + 1) + 1)
609 + sizeof (PREP(store_vwidth_data_e));
610 buf_new_len += (data->num_used_styles > 3
611 ? 2 * data->num_used_styles + 3
612 : 2 * data->num_used_styles + 2)
613 + sizeof (PREP(round_blues));
614 buf_new_len += sizeof (PREP(set_stem_width_handling_a))
616 + sizeof (PREP(set_stem_width_handling_b))
618 + sizeof (PREP(set_stem_width_handling_c))
620 + sizeof (PREP(set_stem_width_handling_d));
621 buf_new_len += sizeof (PREP(set_dropout_mode));
622 buf_new_len += sizeof (PREP(reset_component_counter));
624 /* buffer length must be a multiple of four */
625 len = (buf_new_len + 3) & ~3;
626 buf_new = (FT_Byte*)realloc(buf, len);
627 if (!buf_new)
629 free(buf);
630 return FT_Err_Out_Of_Memory;
632 buf = buf_new;
634 /* pad end of buffer with zeros */
635 buf[len - 1] = 0x00;
636 buf[len - 2] = 0x00;
637 buf[len - 3] = 0x00;
639 /* copy remaining cvt program into buffer */
640 /* and fill in the missing variables */
641 bufp = buf + buf_len;
643 if (font->hinting_limit)
645 COPY_PREP(hinting_limit_a);
646 *(bufp++) = HIGH(font->hinting_limit);
647 *(bufp++) = LOW(font->hinting_limit);
648 COPY_PREP(hinting_limit_b);
651 COPY_PREP(store_funits_to_pixels);
653 if (font->x_height_snapping_exceptions)
654 COPY_PREP(test_exception_a);
656 COPY_PREP(align_top_a);
657 if (data->num_used_styles > 6)
659 BCI(NPUSHB);
660 BCI(data->num_used_styles + 2);
662 else
663 BCI(PUSHB_1 - 1 + data->num_used_styles + 2);
664 /* XXX: make this work for offsets > 255 */
665 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
667 if (data->style_ids[i] == 0xFFFFU)
668 continue;
670 *(bufp++) = CVT_X_HEIGHT_BLUE_OFFSET(i) >= 0xFFFFU
672 : (unsigned char)CVT_X_HEIGHT_BLUE_OFFSET(i);
674 *(bufp++) = data->num_used_styles;
675 COPY_PREP(align_top_b);
677 COPY_PREP(loop_cvt_a);
678 if (data->num_used_styles > 3)
680 BCI(NPUSHB);
681 BCI(2 * data->num_used_styles + 2);
683 else
684 BCI(PUSHB_1 - 1 + 2 * data->num_used_styles + 2);
685 /* XXX: make this work for offsets > 255 */
686 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
688 if (data->style_ids[i] == 0xFFFFU)
689 continue;
691 /* don't loop over artificial blue zones */
692 *(bufp++) = (unsigned char)CVT_VERT_STANDARD_WIDTH_OFFSET(i);
693 *(bufp++) = (unsigned char)(
695 + CVT_VERT_WIDTHS_SIZE(i)
696 + (CVT_BLUES_SIZE(i) > 1 ? CVT_BLUES_SIZE(i) - 2 : 0));
698 *(bufp++) = data->num_used_styles;
699 COPY_PREP(loop_cvt_b);
700 if (data->num_used_styles > 3)
702 BCI(NPUSHB);
703 BCI(2 * data->num_used_styles + 2);
705 else
706 BCI(PUSHB_1 - 1 + 2 * data->num_used_styles + 2);
707 /* XXX: make this work for offsets > 255 */
708 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
710 if (data->style_ids[i] == 0xFFFFU)
711 continue;
713 /* don't loop over artificial blue zones */
714 *(bufp++) = (unsigned char)CVT_BLUE_SHOOTS_OFFSET(i);
715 *(bufp++) = (unsigned char)(
716 CVT_BLUES_SIZE(i) > 1 ? CVT_BLUES_SIZE(i) - 2 : 0);
718 *(bufp++) = data->num_used_styles;
719 COPY_PREP(loop_cvt_c);
721 if (font->x_height_snapping_exceptions)
722 COPY_PREP(test_exception_b);
724 COPY_PREP(store_vwidth_data_a);
725 *(bufp++) = (unsigned char)CVT_VWIDTH_OFFSET_DATA(0);
726 COPY_PREP(store_vwidth_data_b);
727 if (data->num_used_styles > 6)
729 BCI(NPUSHW);
730 BCI(data->num_used_styles + 2);
732 else
733 BCI(PUSHW_1 - 1 + data->num_used_styles + 2);
734 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
736 if (data->style_ids[i] == 0xFFFFU)
737 continue;
739 *(bufp++) = HIGH(CVT_VERT_WIDTHS_OFFSET(i) * 64);
740 *(bufp++) = LOW(CVT_VERT_WIDTHS_OFFSET(i) * 64);
742 *(bufp++) = HIGH(data->num_used_styles);
743 *(bufp++) = LOW(data->num_used_styles);
744 COPY_PREP(store_vwidth_data_c);
745 *(bufp++) = (unsigned char)CVT_VWIDTH_SIZE_DATA(0);
746 COPY_PREP(store_vwidth_data_d);
747 if (data->num_used_styles > 6)
749 BCI(NPUSHW);
750 BCI(data->num_used_styles + 2);
752 else
753 BCI(PUSHW_1 - 1 + data->num_used_styles + 2);
754 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
756 if (data->style_ids[i] == 0xFFFFU)
757 continue;
759 *(bufp++) = HIGH(CVT_VERT_WIDTHS_SIZE(i) * 64);
760 *(bufp++) = LOW(CVT_VERT_WIDTHS_SIZE(i) * 64);
762 *(bufp++) = HIGH(data->num_used_styles);
763 *(bufp++) = LOW(data->num_used_styles);
764 COPY_PREP(store_vwidth_data_e);
766 if (data->num_used_styles > 3)
768 BCI(NPUSHB);
769 BCI(2 * data->num_used_styles + 2);
771 else
772 BCI(PUSHB_1 - 1 + 2 * data->num_used_styles + 2);
773 /* XXX: make this work for offsets > 255 */
774 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
776 if (data->style_ids[i] == 0xFFFFU)
777 continue;
779 *(bufp++) = (unsigned char)CVT_BLUE_REFS_OFFSET(i);
780 *(bufp++) = (unsigned char)CVT_BLUES_SIZE(i);
782 *(bufp++) = data->num_used_styles;
783 COPY_PREP(round_blues);
785 COPY_PREP(set_stem_width_handling_a);
786 *(bufp++) = font->gray_strong_stem_width ? 100 : 0;
787 COPY_PREP(set_stem_width_handling_b);
788 *(bufp++) = font->gdi_cleartype_strong_stem_width ? 100 : 0;
789 COPY_PREP(set_stem_width_handling_c);
790 *(bufp++) = font->dw_cleartype_strong_stem_width ? 100 : 0;
791 COPY_PREP(set_stem_width_handling_d);
792 COPY_PREP(set_dropout_mode);
793 COPY_PREP(reset_component_counter);
795 *prep = buf;
796 *prep_len = buf_new_len;
798 return FT_Err_Ok;
802 FT_Error
803 TA_sfnt_build_prep_table(SFNT* sfnt,
804 FONT* font)
806 FT_Error error;
808 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
809 glyf_Data* data = (glyf_Data*)glyf_table->data;
811 FT_Byte* prep_buf;
812 FT_ULong prep_len;
815 error = TA_sfnt_add_table_info(sfnt);
816 if (error)
817 goto Exit;
819 /* `glyf', `cvt', `fpgm', and `prep' are always used in parallel */
820 if (glyf_table->processed)
822 sfnt->table_infos[sfnt->num_table_infos - 1] = data->prep_idx;
823 goto Exit;
826 error = TA_table_build_prep(&prep_buf, &prep_len, sfnt, font);
827 if (error)
828 goto Exit;
830 #if 0
831 /* ttfautohint's bytecode in `fpgm' is larger */
832 /* than the bytecode in `prep'; */
833 /* this commented out code here is just for completeness */
834 if (prep_len > sfnt->max_instructions)
835 sfnt->max_instructions = prep_len;
836 #endif
838 /* in case of success, `prep_buf' gets linked */
839 /* and is eventually freed in `TA_font_unload' */
840 error = TA_font_add_table(font,
841 &sfnt->table_infos[sfnt->num_table_infos - 1],
842 TTAG_prep, prep_len, prep_buf);
843 if (error)
844 free(prep_buf);
845 else
846 data->prep_idx = sfnt->table_infos[sfnt->num_table_infos - 1];
848 Exit:
849 return error;
852 /* end of taprep.c */