autotroll.m4: Clean up Qt path stuff.
[ttfautohint.git] / lib / taprep.c
blob8f5021b7f10e0673c4edf4e388fe79d868485187
1 /* taprep.c */
3 /*
4 * Copyright (C) 2011-2017 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) [] =
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 PUSHB_2,
273 cvtl_use_strong_functions, /* target: grayscale rendering */
277 /* %c, either 0 or 100 */
279 static const unsigned char PREP(set_smooth_or_strong_b) [] =
282 WCVTP,
284 /* get rasterizer version (bit 0) */
285 PUSHB_2,
287 0x01,
288 GETINFO,
290 /* `(old) GDI ClearType': version >= 36 || version <= 38 */
291 LTEQ,
293 /* check whether ClearType is enabled (bit 6) */
294 PUSHB_1,
295 0x40,
296 GETINFO,
298 PUSHB_2,
299 cvtl_use_strong_functions, /* target: GDI ClearType */
302 /* %c, either 0 or 100 */
304 static const unsigned char PREP(set_smooth_or_strong_c) [] =
307 WCVTP,
309 /* get rasterizer version (bit 0) */
310 PUSHB_2,
312 0x01,
313 GETINFO,
315 /* `DW ClearType': version >= 40 */
316 LTEQ,
318 /* check whether symmetric rendering is enabled (bit 11) */
319 PUSHW_1,
320 0x08,
321 0x00,
322 GETINFO,
324 PUSHB_2,
325 cvtl_use_strong_functions, /* target: DirectWrite ClearType */
329 /* %c, either 0 or 100 */
331 static const unsigned char PREP(set_smooth_or_strong_d) [] =
334 WCVTP,
335 EIF,
337 ELSE,
338 /* get rasterizer version (bit 0) */
339 PUSHB_2,
341 0x01,
342 GETINFO,
344 /* `DW ClearType': version == 39 */
345 LTEQ,
347 /* check whether sub-pixel positioning is enabled (bit 10) -- */
348 /* due to a bug in FreeType 2.5.0 and earlier, */
349 /* bit 6 must be set also to get the correct information, */
350 /* so we test that both return values (in bits 13 and 17) are set */
351 PUSHW_3,
352 0x08, /* bits 13 and 17 right-shifted by 6 bits */
353 0x80,
354 0x00, /* we do `MUL' with value 1, */
355 0x01, /* which is essentially a division by 64 */
356 0x04, /* bits 6 and 10 */
357 0x40,
358 GETINFO,
359 MUL,
362 PUSHB_2,
363 cvtl_use_strong_functions, /* target: DirectWrite ClearType */
367 /* %c, either 0 or 100 */
369 static const unsigned char PREP(set_smooth_or_strong_e) [] =
372 WCVTP,
373 EIF,
374 EIF,
375 EIF,
376 EIF,
377 EIF,
381 /*PUSHB (2*num_used_styles + 2) */
382 /* ... */
383 /* %c, style 1's first blue ref index */
384 /* %c, style 1's number of blue ref indices */
385 /* %c, style 0's first blue ref index */
386 /* %c, style 0's number of blue ref indices */
387 /* %c, num_used_styles */
389 static const unsigned char PREP(round_blues) [] =
392 bci_blue_round_range,
393 LOOPCALL,
397 static const unsigned char PREP(set_dropout_mode) [] =
400 PUSHW_1,
401 0x01, /* 0x01FF, activate dropout handling unconditionally */
402 0xFF,
403 SCANCTRL,
404 PUSHB_1,
405 4, /* smart dropout include stubs */
406 SCANTYPE,
410 static const unsigned char PREP(reset_component_counter) [] =
413 /* In case an application tries to render `.ttfautohint' */
414 /* (which it should never do), */
415 /* hinting of all glyphs rendered afterwards is disabled */
416 /* because the `cvtl_is_subglyph' counter gets incremented, */
417 /* but there is no counterpart to decrement it. */
418 /* Font inspection tools like the FreeType demo programs */
419 /* are an exception to that rule, however, */
420 /* since they can directly access a font by glyph indices. */
421 /* The following guard alleviates the problem a bit: */
422 /* Any change of the graphics state */
423 /* (for example, rendering at a different size or with a different mode) */
424 /* resets the counter to zero. */
425 PUSHB_2,
426 cvtl_is_subglyph,
428 WCVTP,
432 static const unsigned char PREP(adjust_delta_exceptions) [] =
435 /* set delta base */
436 PUSHB_1,
437 CONTROL_DELTA_PPEM_MIN,
438 SDB,
443 static const unsigned char PREP(set_default_cvs_values) [] =
446 /* We set a default value for `cvtl_do_iup_y'. */
447 /* If we have delta exceptions before IUP_y, */
448 /* the glyph's bytecode sets this CVT value temporarily to zero */
449 /* and manually inserts IUP_y afterwards. */
451 /* We set a default value for `cvtl_ignore_std_width'. */
452 /* As the name implies, the stem width computation routines */
453 /* ignore the standard width(s) if this flag gets set. */
455 /* It would be more elegant to use storage area locations instead, */
456 /* however, it is not possible to have default values for them */
457 /* since storage area locations might be reset on a per-glyph basis */
458 /* (this is dependent on the bytecode interpreter implementation). */
460 PUSHB_4,
461 cvtl_do_iup_y,
462 100,
463 cvtl_ignore_std_width,
465 WCVTP,
466 WCVTP,
471 /* this function allocates `buf', parsing `number_set' to create bytecode */
472 /* which eventually sets CVT index `cvtl_is_element' */
473 /* (in functions `bci_number_set_is_element' and */
474 /* `bci_number_set_is_element2') */
476 static FT_Byte*
477 TA_sfnt_build_number_set(SFNT* sfnt,
478 FT_Byte** buf,
479 number_range* number_set)
481 FT_Byte* bufp = NULL;
482 number_range* nr;
484 FT_UInt num_singles2 = 0;
485 FT_UInt* single2_args;
486 FT_UInt* single2_arg;
487 FT_UInt num_singles = 0;
488 FT_UInt* single_args;
489 FT_UInt* single_arg;
491 FT_UInt num_ranges2 = 0;
492 FT_UInt* range2_args;
493 FT_UInt* range2_arg;
494 FT_UInt num_ranges = 0;
495 FT_UInt* range_args;
496 FT_UInt* range_arg;
498 FT_UInt have_single = 0;
499 FT_UInt have_range = 0;
501 FT_UShort num_stack_elements;
504 /* build up four stacks to stay as compact as possible */
505 nr = number_set;
506 while (nr)
508 if (nr->start == nr->end)
510 if (nr->start < 256)
511 num_singles++;
512 else
513 num_singles2++;
515 else
517 if (nr->start < 256 && nr->end < 256)
518 num_ranges++;
519 else
520 num_ranges2++;
522 nr = nr->next;
525 /* collect all arguments temporarily in arrays (in reverse order) */
526 /* so that we can easily split into chunks of 255 args */
527 /* as needed by NPUSHB and friends; */
528 /* for simplicity, always allocate an extra slot */
529 single2_args = (FT_UInt*)malloc((num_singles2 + 1) * sizeof (FT_UInt));
530 single_args = (FT_UInt*)malloc((num_singles + 1) * sizeof (FT_UInt));
531 range2_args = (FT_UInt*)malloc((2 * num_ranges2 + 1) * sizeof (FT_UInt));
532 range_args = (FT_UInt*)malloc((2 * num_ranges + 1) * sizeof (FT_UInt));
533 if (!single2_args || !single_args
534 || !range2_args || !range_args)
535 goto Fail;
537 /* check whether we need the extra slot for the argument to CALL */
538 if (num_singles || num_singles2)
539 have_single = 1;
540 if (num_ranges || num_ranges2)
541 have_range = 1;
543 /* set function indices outside of argument loop (using the extra slot) */
544 if (have_single)
545 single_args[num_singles] = bci_number_set_is_element;
546 if (have_range)
547 range_args[2 * num_ranges] = bci_number_set_is_element2;
549 single2_arg = single2_args + num_singles2 - 1;
550 single_arg = single_args + num_singles - 1;
551 range2_arg = range2_args + 2 * num_ranges2 - 1;
552 range_arg = range_args + 2 * num_ranges - 1;
554 nr = number_set;
555 while (nr)
557 FT_UInt start = (FT_UInt)nr->start;
558 FT_UInt end = (FT_UInt)nr->end;
561 if (start == end)
563 if (start < 256)
564 *(single_arg--) = start;
565 else
566 *(single2_arg--) = start;
568 else
570 if (start < 256 && end < 256)
572 *(range_arg--) = start;
573 *(range_arg--) = end;
575 else
577 *(range2_arg--) = start;
578 *(range2_arg--) = end;
581 nr = nr->next;
584 /* this rough estimate of the buffer size gets adjusted later on */
585 *buf = (FT_Byte*)malloc((2 + 1) * num_singles2
586 + (1 + 1) * num_singles
587 + (4 + 1) * num_ranges2
588 + (2 + 1) * num_ranges
589 + 10);
590 if (!*buf)
591 goto Fail;
592 bufp = *buf;
594 BCI(PUSHB_2);
595 BCI(cvtl_is_element);
596 BCI(0);
597 BCI(WCVTP);
599 bufp = TA_build_push(bufp, single2_args, num_singles2, 1, 1);
600 bufp = TA_build_push(bufp, single_args, num_singles + have_single, 0, 1);
601 if (have_single)
602 BCI(CALL);
604 bufp = TA_build_push(bufp, range2_args, 2 * num_ranges2, 1, 1);
605 bufp = TA_build_push(bufp, range_args, 2 * num_ranges + have_range, 0, 1);
606 if (have_range)
607 BCI(CALL);
609 num_stack_elements = (FT_UShort)(num_singles + num_singles2);
610 if (num_stack_elements > num_ranges + num_ranges2)
611 num_stack_elements = (FT_UShort)(num_ranges + num_ranges2);
612 num_stack_elements += ADDITIONAL_STACK_ELEMENTS;
613 if (num_stack_elements > sfnt->max_stack_elements)
614 sfnt->max_stack_elements = num_stack_elements;
616 Fail:
617 free(single2_args);
618 free(single_args);
619 free(range2_args);
620 free(range_args);
622 return bufp;
626 #define COPY_PREP(snippet_name) \
627 do \
629 memcpy(bufp, prep_ ## snippet_name, \
630 sizeof (prep_ ## snippet_name)); \
631 bufp += sizeof (prep_ ## snippet_name); \
632 } while (0)
634 static FT_Error
635 TA_table_build_prep(FT_Byte** prep,
636 FT_ULong* prep_len,
637 SFNT* sfnt,
638 FONT* font)
640 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
641 glyf_Data* data = (glyf_Data*)glyf_table->data;
642 /* XXX: make this work for more than 256 styles */
643 FT_Byte num_used_styles = (FT_Byte)data->num_used_styles;
645 FT_Int i;
647 FT_Byte* buf = NULL;
648 FT_Byte* buf_new;
649 FT_UInt buf_len;
650 FT_UInt buf_new_len;
652 FT_UInt len;
653 FT_Byte* bufp = NULL;
656 if (font->x_height_snapping_exceptions)
658 bufp = TA_sfnt_build_number_set(sfnt, &buf,
659 font->x_height_snapping_exceptions);
660 if (!bufp)
661 return FT_Err_Out_Of_Memory;
664 buf_len = (FT_UInt)(bufp - buf);
665 buf_new_len = buf_len;
667 if (font->hinting_limit)
668 buf_new_len += sizeof (PREP(hinting_limit_a))
670 + sizeof (PREP(hinting_limit_b));
672 buf_new_len += sizeof (PREP(store_funits_to_pixels));
674 if (font->x_height_snapping_exceptions)
675 buf_new_len += sizeof (PREP(test_exception_a));
677 buf_new_len += sizeof (PREP(align_x_height_a))
678 + (num_used_styles > 6 ? num_used_styles + 3
679 : num_used_styles + 2)
680 + sizeof (PREP(align_x_height_b));
681 buf_new_len += sizeof (PREP(loop_cvt_a))
682 + (num_used_styles > 3 ? 2 * num_used_styles + 3
683 : 2 * num_used_styles + 2)
684 + sizeof (PREP(loop_cvt_b))
685 + (num_used_styles > 3 ? 2 * num_used_styles + 3
686 : 2 * num_used_styles + 2)
687 + sizeof (PREP(loop_cvt_c));
689 if (font->x_height_snapping_exceptions)
690 buf_new_len += sizeof (PREP(test_exception_b));
692 buf_new_len += sizeof (PREP(store_vwidth_data_a))
694 + sizeof (PREP(store_vwidth_data_b))
695 + (num_used_styles > 6 ? 2 * (num_used_styles + 1) + 2
696 : 2 * (num_used_styles + 1) + 1)
697 + sizeof (PREP(store_vwidth_data_c))
699 + sizeof (PREP(store_vwidth_data_d))
700 + (num_used_styles > 6 ? 2 * (num_used_styles + 1) + 2
701 : 2 * (num_used_styles + 1) + 1)
702 + sizeof (PREP(store_vwidth_data_e));
703 buf_new_len += sizeof (PREP(set_smooth_or_strong_a))
705 + sizeof (PREP(set_smooth_or_strong_b))
707 + sizeof (PREP(set_smooth_or_strong_c))
709 + sizeof (PREP(set_smooth_or_strong_d))
711 + sizeof (PREP(set_smooth_or_strong_e));
712 buf_new_len += (num_used_styles > 3 ? 2 * num_used_styles + 3
713 : 2 * num_used_styles + 2)
714 + sizeof (PREP(round_blues));
715 buf_new_len += sizeof (PREP(set_dropout_mode));
716 buf_new_len += sizeof (PREP(reset_component_counter));
717 if (font->control_data_head)
718 buf_new_len += sizeof (PREP(adjust_delta_exceptions));
719 buf_new_len += sizeof (PREP(set_default_cvs_values));
721 /* buffer length must be a multiple of four */
722 len = (buf_new_len + 3) & ~3U;
723 buf_new = (FT_Byte*)realloc(buf, len);
724 if (!buf_new)
726 free(buf);
727 return FT_Err_Out_Of_Memory;
729 buf = buf_new;
731 /* pad end of buffer with zeros */
732 buf[len - 1] = 0x00;
733 buf[len - 2] = 0x00;
734 buf[len - 3] = 0x00;
736 /* copy remaining cvt program into buffer */
737 /* and fill in the missing variables */
738 bufp = buf + buf_len;
740 if (font->hinting_limit)
742 COPY_PREP(hinting_limit_a);
743 *(bufp++) = HIGH(font->hinting_limit);
744 *(bufp++) = LOW(font->hinting_limit);
745 COPY_PREP(hinting_limit_b);
748 COPY_PREP(store_funits_to_pixels);
750 if (font->x_height_snapping_exceptions)
751 COPY_PREP(test_exception_a);
753 COPY_PREP(align_x_height_a);
754 if (num_used_styles > 6)
756 BCI(NPUSHB);
757 BCI(num_used_styles + 2);
759 else
760 BCI(PUSHB_1 - 1 + num_used_styles + 2);
761 /* XXX: make this work for offsets > 255 */
762 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
764 if (data->style_ids[i] == 0xFFFFU)
765 continue;
767 *(bufp++) = CVT_X_HEIGHT_BLUE_OFFSET(i) >= 0xFFFFU
769 : (unsigned char)CVT_X_HEIGHT_BLUE_OFFSET(i);
771 *(bufp++) = num_used_styles;
772 COPY_PREP(align_x_height_b);
774 COPY_PREP(loop_cvt_a);
775 if (num_used_styles > 3)
777 BCI(NPUSHB);
778 BCI(2 * num_used_styles + 2);
780 else
781 BCI(PUSHB_1 - 1 + 2 * num_used_styles + 2);
782 /* XXX: make this work for offsets > 255 */
783 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
785 if (data->style_ids[i] == 0xFFFFU)
786 continue;
788 /* don't loop over artificial blue zones */
789 *(bufp++) = (unsigned char)CVT_VERT_STANDARD_WIDTH_OFFSET(i);
790 *(bufp++) = (unsigned char)(
792 + CVT_VERT_WIDTHS_SIZE(i)
793 + (CVT_BLUES_SIZE(i) > 1
794 ? CVT_BLUES_SIZE(i) - (font->windows_compatibility ? 2
795 : 0)
796 : 0));
798 *(bufp++) = num_used_styles;
799 COPY_PREP(loop_cvt_b);
800 if (num_used_styles > 3)
802 BCI(NPUSHB);
803 BCI(2 * num_used_styles + 2);
805 else
806 BCI(PUSHB_1 - 1 + 2 * num_used_styles + 2);
807 /* XXX: make this work for offsets > 255 */
808 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
810 if (data->style_ids[i] == 0xFFFFU)
811 continue;
813 /* don't loop over artificial blue zones */
814 *(bufp++) = (unsigned char)CVT_BLUE_SHOOTS_OFFSET(i);
815 *(bufp++) = (unsigned char)(
816 CVT_BLUES_SIZE(i) > 1
817 ? CVT_BLUES_SIZE(i) - (font->windows_compatibility ? 2
818 : 0)
819 : 0);
821 *(bufp++) = num_used_styles;
822 COPY_PREP(loop_cvt_c);
824 if (font->x_height_snapping_exceptions)
825 COPY_PREP(test_exception_b);
827 COPY_PREP(store_vwidth_data_a);
828 *(bufp++) = (unsigned char)CVT_VWIDTH_OFFSET_DATA(0);
829 COPY_PREP(store_vwidth_data_b);
830 if (num_used_styles > 6)
832 BCI(NPUSHW);
833 BCI(num_used_styles + 2);
835 else
836 BCI(PUSHW_1 - 1 + num_used_styles + 2);
837 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
839 if (data->style_ids[i] == 0xFFFFU)
840 continue;
842 *(bufp++) = HIGH(CVT_VERT_WIDTHS_OFFSET(i) * 64);
843 *(bufp++) = LOW(CVT_VERT_WIDTHS_OFFSET(i) * 64);
845 *(bufp++) = HIGH(num_used_styles);
846 *(bufp++) = LOW(num_used_styles);
847 COPY_PREP(store_vwidth_data_c);
848 *(bufp++) = (unsigned char)CVT_VWIDTH_SIZE_DATA(0);
849 COPY_PREP(store_vwidth_data_d);
850 if (num_used_styles > 6)
852 BCI(NPUSHW);
853 BCI(num_used_styles + 2);
855 else
856 BCI(PUSHW_1 - 1 + num_used_styles + 2);
857 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
859 if (data->style_ids[i] == 0xFFFFU)
860 continue;
862 *(bufp++) = HIGH(CVT_VERT_WIDTHS_SIZE(i) * 64);
863 *(bufp++) = LOW(CVT_VERT_WIDTHS_SIZE(i) * 64);
865 *(bufp++) = HIGH(num_used_styles);
866 *(bufp++) = LOW(num_used_styles);
867 COPY_PREP(store_vwidth_data_e);
869 COPY_PREP(set_smooth_or_strong_a);
870 *(bufp++) = font->gray_strong_stem_width ? 100 : 0;
871 COPY_PREP(set_smooth_or_strong_b);
872 *(bufp++) = font->gdi_cleartype_strong_stem_width ? 100 : 0;
873 COPY_PREP(set_smooth_or_strong_c);
874 *(bufp++) = font->dw_cleartype_strong_stem_width ? 100 : 0;
875 COPY_PREP(set_smooth_or_strong_d);
876 *(bufp++) = font->dw_cleartype_strong_stem_width ? 100 : 0;
877 COPY_PREP(set_smooth_or_strong_e);
879 if (num_used_styles > 3)
881 BCI(NPUSHB);
882 BCI(2 * num_used_styles + 2);
884 else
885 BCI(PUSHB_1 - 1 + 2 * num_used_styles + 2);
886 /* XXX: make this work for offsets > 255 */
887 for (i = TA_STYLE_MAX - 1; i >= 0; i--)
889 if (data->style_ids[i] == 0xFFFFU)
890 continue;
892 *(bufp++) = (unsigned char)CVT_BLUE_REFS_OFFSET(i);
893 *(bufp++) = (unsigned char)CVT_BLUES_SIZE(i);
895 *(bufp++) = num_used_styles;
896 COPY_PREP(round_blues);
898 COPY_PREP(set_dropout_mode);
899 COPY_PREP(reset_component_counter);
900 if (font->control_data_head)
901 COPY_PREP(adjust_delta_exceptions);
902 COPY_PREP(set_default_cvs_values);
904 *prep = buf;
905 *prep_len = buf_new_len;
907 return FT_Err_Ok;
911 FT_Error
912 TA_sfnt_build_prep_table(SFNT* sfnt,
913 FONT* font)
915 FT_Error error;
917 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
918 glyf_Data* data = (glyf_Data*)glyf_table->data;
920 FT_Byte* prep_buf;
921 FT_ULong prep_len;
924 error = TA_sfnt_add_table_info(sfnt);
925 if (error)
926 goto Exit;
928 /* `glyf', `cvt', `fpgm', and `prep' are always used in parallel */
929 if (glyf_table->processed)
931 sfnt->table_infos[sfnt->num_table_infos - 1] = data->prep_idx;
932 goto Exit;
935 error = TA_table_build_prep(&prep_buf, &prep_len, sfnt, font);
936 if (error)
937 goto Exit;
939 #if 0
940 /* ttfautohint's bytecode in `fpgm' is larger */
941 /* than the bytecode in `prep'; */
942 /* this commented out code here is just for completeness */
943 if (prep_len > sfnt->max_instructions)
944 sfnt->max_instructions = prep_len;
945 #endif
947 /* in case of success, `prep_buf' gets linked */
948 /* and is eventually freed in `TA_font_unload' */
949 error = TA_font_add_table(font,
950 &sfnt->table_infos[sfnt->num_table_infos - 1],
951 TTAG_prep, prep_len, prep_buf);
952 if (error)
953 free(prep_buf);
954 else
955 data->prep_idx = sfnt->table_infos[sfnt->num_table_infos - 1];
957 Exit:
958 return error;
961 /* end of taprep.c */