number_set_new: Avoid memory leak in case of invalid input.
[ttfautohint.git] / lib / tabytecode.c
blob63c573575fd975f063c2f829ef48b90e7d4cabf0
1 /* tabytecode.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 <string.h>
17 #include <stdbool.h> /* for llrb.h */
19 #include "llrb.h" /* a red-black tree implementation */
21 #include "ta.h"
22 #include "tahints.h"
25 #define DEBUGGING
28 #ifdef TA_DEBUG
29 int _ta_debug = 0;
30 int _ta_debug_global = 0;
31 int _ta_debug_disable_horz_hints;
32 int _ta_debug_disable_vert_hints;
33 int _ta_debug_disable_blue_hints;
34 void* _ta_debug_hints;
35 #endif
38 /* node structures for point hints */
40 typedef struct Node1 Node1;
41 struct Node1
43 LLRB_ENTRY(Node1) entry1;
44 FT_UShort point;
47 typedef struct Node2 Node2;
48 struct Node2
50 LLRB_ENTRY(Node2) entry2;
51 FT_UShort edge;
52 FT_UShort point;
55 typedef struct Node3 Node3;
56 struct Node3
58 LLRB_ENTRY(Node3) entry3;
59 FT_UShort before_edge;
60 FT_UShort after_edge;
61 FT_UShort point;
65 /* comparison functions for our red-black trees */
67 static int
68 node1cmp(Node1* e1,
69 Node1* e2)
71 /* sort by points */
72 return e1->point - e2->point;
75 static int
76 node2cmp(Node2* e1,
77 Node2* e2)
79 FT_Int delta;
82 /* sort by edges ... */
83 delta = (FT_Int)e1->edge - (FT_Int)e2->edge;
84 if (delta)
85 return delta;
87 /* ... then by points */
88 return (FT_Int)e1->point - (FT_Int)e2->point;
91 static int
92 node3cmp(Node3* e1,
93 Node3* e2)
95 FT_Int delta;
98 /* sort by `before' edges ... */
99 delta = (FT_Int)e1->before_edge - (FT_Int)e2->before_edge;
100 if (delta)
101 return delta;
103 /* ... then by `after' edges ... */
104 delta = (FT_Int)e1->after_edge - (FT_Int)e2->after_edge;
105 if (delta)
106 return delta;
108 /* ... then by points */
109 return (FT_Int)e1->point - (FT_Int)e2->point;
113 /* the red-black tree function bodies */
114 typedef struct ip_before_points ip_before_points;
115 typedef struct ip_after_points ip_after_points;
116 typedef struct ip_on_points ip_on_points;
117 typedef struct ip_between_points ip_between_points;
119 LLRB_HEAD(ip_before_points, Node1);
120 LLRB_HEAD(ip_after_points, Node1);
121 LLRB_HEAD(ip_on_points, Node2);
122 LLRB_HEAD(ip_between_points, Node3);
124 /* no trailing semicolon in the next four lines */
125 LLRB_GENERATE_STATIC(ip_before_points, Node1, entry1, node1cmp)
126 LLRB_GENERATE_STATIC(ip_after_points, Node1, entry1, node1cmp)
127 LLRB_GENERATE_STATIC(ip_on_points, Node2, entry2, node2cmp)
128 LLRB_GENERATE_STATIC(ip_between_points, Node3, entry3, node3cmp)
131 typedef struct Hints_Record_
133 FT_UInt size;
134 FT_UInt num_actions;
135 FT_Byte* buf;
136 FT_UInt buf_len;
137 } Hints_Record;
139 typedef struct Recorder_
141 SFNT* sfnt;
142 FONT* font;
143 GLYPH* glyph; /* the current glyph */
144 Hints_Record hints_record;
146 /* some segments can `wrap around' */
147 /* a contour's start point like 24-25-26-0-1-2 */
148 /* (there can be at most one such segment per contour); */
149 /* later on we append additional records */
150 /* to split them into 24-26 and 0-2 */
151 FT_UShort* wrap_around_segments;
152 FT_UShort num_wrap_around_segments;
154 FT_UShort num_stack_elements; /* the necessary stack depth so far */
156 /* data necessary for strong point interpolation */
157 ip_before_points ip_before_points_head;
158 ip_after_points ip_after_points_head;
159 ip_on_points ip_on_points_head;
160 ip_between_points ip_between_points_head;
162 FT_UShort num_strong_points;
163 FT_UShort num_segments;
164 } Recorder;
167 /* this is the bytecode of the `.ttfautohint' glyph */
169 FT_Byte ttfautohint_glyph_bytecode[7] =
172 /* increment `cvtl_is_subglyph' counter */
173 PUSHB_3,
174 cvtl_is_subglyph,
175 100,
176 cvtl_is_subglyph,
177 RCVT,
178 ADD,
179 WCVTP,
185 * convert array `args' into a sequence of NPUSHB, NPUSHW, PUSHB_X, and
186 * PUSHW_X instructions to be stored in `bufp' (the latter two instructions
187 * only if `optimize' is not set); if `need_words' is set, NPUSHW and
188 * PUSHW_X gets used
191 FT_Byte*
192 TA_build_push(FT_Byte* bufp,
193 FT_UInt* args,
194 FT_UInt num_args,
195 FT_Bool need_words,
196 FT_Bool optimize)
198 FT_UInt* arg = args;
199 FT_UInt i, j, nargs;
202 if (need_words)
204 for (i = 0; i < num_args; i += 255)
206 nargs = (num_args - i > 255) ? 255 : num_args - i;
208 if (optimize && nargs <= 8)
209 BCI(PUSHW_1 - 1 + nargs);
210 else
212 BCI(NPUSHW);
213 BCI(nargs);
215 for (j = 0; j < nargs; j++)
217 BCI(HIGH(*arg));
218 BCI(LOW(*arg));
219 arg++;
223 else
225 for (i = 0; i < num_args; i += 255)
227 nargs = (num_args - i > 255) ? 255 : num_args - i;
229 if (optimize && nargs <= 8)
230 BCI(PUSHB_1 - 1 + nargs);
231 else
233 BCI(NPUSHB);
234 BCI(nargs);
236 for (j = 0; j < nargs; j++)
238 BCI(*arg);
239 arg++;
244 return bufp;
249 * We optimize two common cases, replacing
251 * NPUSHB A ... NPUSHB B [... NPUSHB C] ... CALL
253 * with
255 * NPUSHB (A+B[+C]) ... CALL
257 * if possible
260 FT_Byte*
261 TA_optimize_push(FT_Byte* buf,
262 FT_Byte** pos)
264 FT_Byte sizes[3];
265 FT_Byte new_size1;
266 FT_Byte new_size2;
268 FT_UInt sum;
269 FT_UInt i;
270 FT_UInt pos_idx;
272 FT_Byte* p;
273 FT_Byte* bufp;
276 /* XXX improve handling of NPUSHW */
277 if (*(pos[0]) == NPUSHW
278 || *(pos[1]) == NPUSHW
279 || *(pos[2]) == NPUSHW)
280 return buf;
282 /* the point hints records block can be missing */
283 if (pos[0] == pos[1])
285 pos[1] = pos[2];
286 pos[2] = NULL;
289 /* there are at least two NPUSHB instructions */
290 /* (one of them directly at the start) */
291 sizes[0] = *(pos[0] + 1);
292 sizes[1] = *(pos[1] + 1);
293 sizes[2] = pos[2] ? *(pos[2] + 1) : 0;
295 sum = sizes[0] + sizes[1] + sizes[2];
297 if (sum > 2 * 0xFF)
298 return buf; /* nothing to do since we need three NPUSHB */
299 else if (!sizes[2] && (sum > 0xFF))
300 return buf; /* nothing to do since we need two NPUSHB */
302 if (sum > 0xFF)
304 /* reduce three NPUSHB to two */
305 new_size1 = 0xFF;
306 new_size2 = sum - 0xFF;
308 else
310 /* reduce two or three NPUSHB to one */
311 new_size1 = sum;
312 new_size2 = 0;
315 /* pack data */
316 p = buf;
317 bufp = buf;
318 pos_idx = 0;
320 if (new_size1 <= 8)
321 BCI(PUSHB_1 - 1 + new_size1);
322 else
324 BCI(NPUSHB);
325 BCI(new_size1);
327 for (i = 0; i < new_size1; i++)
329 if (p == pos[pos_idx])
331 pos_idx++;
332 p += 2; /* skip old NPUSHB */
334 *(bufp++) = *(p++);
337 if (new_size2)
339 if (new_size2 <= 8)
340 BCI(PUSHB_1 - 1 + new_size2);
341 else
343 BCI(NPUSHB);
344 BCI(new_size2);
346 for (i = 0; i < new_size2; i++)
348 if (p == pos[pos_idx])
350 pos_idx++;
351 p += 2;
353 *(bufp++) = *(p++);
357 BCI(CALL);
359 return bufp;
363 /* We add a subglyph for each composite glyph. */
364 /* Since subglyphs must contain at least one point, */
365 /* we have to adjust all point indices accordingly. */
366 /* Using the `pointsums' array of the `GLYPH' structure */
367 /* it is straightforward to do that: */
368 /* Assuming that point with index x is in the interval */
369 /* pointsums[n] <= x < pointsums[n + 1], */
370 /* the new point index is x + n. */
372 static FT_UInt
373 TA_adjust_point_index(Recorder* recorder,
374 FT_UInt idx)
376 FONT* font = recorder->font;
377 GLYPH* glyph = recorder->glyph;
378 FT_UShort i;
381 if (!glyph->num_components || !font->hint_composites)
382 return idx; /* not a composite glyph */
384 for (i = 0; i < glyph->num_pointsums; i++)
385 if (idx < glyph->pointsums[i])
386 break;
388 return idx + i;
392 /* we store the segments in the storage area; */
393 /* each segment record consists of the first and last point */
395 static FT_Byte*
396 TA_sfnt_build_glyph_segments(SFNT* sfnt,
397 Recorder* recorder,
398 FT_Byte* bufp,
399 FT_Bool optimize)
401 FONT* font = recorder->font;
402 TA_GlyphHints hints = &font->loader->hints;
403 TA_AxisHints axis = &hints->axis[TA_DIMENSION_VERT];
404 TA_Point points = hints->points;
405 TA_Segment segments = axis->segments;
406 TA_Segment seg;
407 TA_Segment seg_limit;
409 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
410 glyf_Data* data = (glyf_Data*)glyf_table->data;
412 FT_UInt style_id = data->style_ids
413 [font->loader->metrics->style_class->style];
415 FT_Outline outline = font->loader->gloader->base.outline;
417 FT_UInt* args;
418 FT_UInt* arg;
419 FT_UInt num_args;
420 FT_UShort num_segments;
422 FT_Bool need_words = 0;
424 FT_Int n;
425 FT_UInt base;
426 FT_UShort num_packed_segments;
427 FT_UShort num_storage;
428 FT_UShort num_stack_elements;
429 FT_UShort num_twilight_points;
432 seg_limit = segments + axis->num_segments;
433 num_segments = axis->num_segments;
435 /* to pack the data in the bytecode more tightly, */
436 /* we store up to the first nine segments in nibbles if possible, */
437 /* using delta values */
438 base = 0;
439 num_packed_segments = 0;
440 for (seg = segments; seg < seg_limit; seg++)
442 FT_UInt first = seg->first - points;
443 FT_UInt last = seg->last - points;
446 first = TA_adjust_point_index(recorder, first);
447 last = TA_adjust_point_index(recorder, last);
449 if (first - base >= 16)
450 break;
451 if (first > last || last - first >= 16)
452 break;
453 if (num_packed_segments == 9)
454 break;
455 num_packed_segments++;
456 base = last;
459 /* also handle wrap-around segments */
460 num_segments += recorder->num_wrap_around_segments;
462 /* wrap-around segments are pushed with four arguments; */
463 /* a segment stored in nibbles needs only one byte instead of two */
464 num_args = num_packed_segments
465 + 2 * (num_segments - num_packed_segments)
466 + 2 * recorder->num_wrap_around_segments
467 + 3;
469 /* collect all arguments temporarily in an array (in reverse order) */
470 /* so that we can easily split into chunks of 255 args */
471 /* as needed by NPUSHB and NPUSHW, respectively */
472 args = (FT_UInt*)malloc(num_args * sizeof (FT_UInt));
473 if (!args)
474 return NULL;
476 arg = args + num_args - 1;
478 if (num_segments > 0xFF)
479 need_words = 1;
481 /* the number of packed segments is indicated by the function number */
482 if (recorder->glyph->num_components && font->hint_composites)
483 *(arg--) = bci_create_segments_composite_0 + num_packed_segments;
484 else
485 *(arg--) = bci_create_segments_0 + num_packed_segments;
487 *(arg--) = CVT_SCALING_VALUE_OFFSET(style_id);
488 *(arg--) = num_segments;
490 base = 0;
491 for (seg = segments; seg < segments + num_packed_segments; seg++)
493 FT_UInt first = seg->first - points;
494 FT_UInt last = seg->last - points;
495 FT_UInt low_nibble;
496 FT_UInt high_nibble;
499 first = TA_adjust_point_index(recorder, first);
500 last = TA_adjust_point_index(recorder, last);
502 low_nibble = first - base;
503 high_nibble = last - first;
505 *(arg--) = 16 * high_nibble + low_nibble;
507 base = last;
510 for (seg = segments + num_packed_segments; seg < seg_limit; seg++)
512 FT_UInt first = seg->first - points;
513 FT_UInt last = seg->last - points;
516 *(arg--) = TA_adjust_point_index(recorder, first);
517 *(arg--) = TA_adjust_point_index(recorder, last);
519 /* we push the last and first contour point */
520 /* as a third and fourth argument in wrap-around segments */
521 if (first > last)
523 for (n = 0; n < outline.n_contours; n++)
525 FT_UInt end = (FT_UInt)outline.contours[n];
528 if (first <= end)
530 *(arg--) = TA_adjust_point_index(recorder, end);
531 if (end > 0xFF)
532 need_words = 1;
534 if (n == 0)
535 *(arg--) = TA_adjust_point_index(recorder, 0);
536 else
537 *(arg--) = TA_adjust_point_index(recorder,
538 (FT_UInt)outline.contours[n - 1] + 1);
539 break;
544 if (last > 0xFF)
545 need_words = 1;
548 /* emit the second part of wrap-around segments as separate segments */
549 /* so that edges can easily link to them */
550 for (seg = segments; seg < seg_limit; seg++)
552 FT_UInt first = seg->first - points;
553 FT_UInt last = seg->last - points;
556 if (first > last)
558 for (n = 0; n < outline.n_contours; n++)
560 if (first <= (FT_UInt)outline.contours[n])
562 if (n == 0)
563 *(arg--) = TA_adjust_point_index(recorder, 0);
564 else
565 *(arg--) = TA_adjust_point_index(recorder,
566 (FT_UInt)outline.contours[n - 1] + 1);
567 break;
571 *(arg--) = TA_adjust_point_index(recorder, last);
575 /* with most fonts it is very rare */
576 /* that any of the pushed arguments is larger than 0xFF, */
577 /* thus we refrain from further optimizing this case */
578 bufp = TA_build_push(bufp, args, num_args, need_words, optimize);
580 BCI(CALL);
582 num_storage = sal_segment_offset + num_segments * 2;
583 if (num_storage > sfnt->max_storage)
584 sfnt->max_storage = num_storage;
586 num_twilight_points = num_segments * 2;
587 if (num_twilight_points > sfnt->max_twilight_points)
588 sfnt->max_twilight_points = num_twilight_points;
590 /* both this function and `TA_emit_hints_record' */
591 /* push data onto the stack */
592 num_stack_elements = ADDITIONAL_STACK_ELEMENTS
593 + recorder->num_stack_elements + num_args;
594 if (num_stack_elements > sfnt->max_stack_elements)
595 sfnt->max_stack_elements = num_stack_elements;
597 free(args);
599 return bufp;
603 static void
604 build_delta_exception(const Delta* delta,
605 FT_UInt** delta_args,
606 int* num_delta_args)
608 int offset;
609 int ppem;
610 int x_shift;
611 int y_shift;
614 ppem = delta->ppem - DELTA_PPEM_MIN;
616 if (ppem < 16)
617 offset = 0;
618 else if (ppem < 32)
619 offset = 1;
620 else
621 offset = 2;
623 ppem -= offset << 4;
626 * Using
628 * delta_shift = 3 ,
630 * the possible shift values in the instructions are indexed as follows:
632 * 0 -1px
633 * 1 -7/8px
634 * ...
635 * 7 -1/8px
636 * 8 1/8px
637 * ...
638 * 14 7/8px
639 * 15 1px
641 * (note that there is no index for a zero shift).
644 if (delta->x_shift < 0)
645 x_shift = delta->x_shift + 8;
646 else
647 x_shift = delta->x_shift + 7;
649 if (delta->y_shift < 0)
650 y_shift = delta->y_shift + 8;
651 else
652 y_shift = delta->y_shift + 7;
654 /* add point index and exception specification to appropriate stack */
655 if (delta->x_shift)
657 *(delta_args[offset] + num_delta_args[offset]++) =
658 (ppem << 4) + x_shift;
659 *(delta_args[offset] + num_delta_args[offset]++) =
660 delta->point_idx;
663 if (delta->y_shift)
665 offset += 3;
666 *(delta_args[offset] + num_delta_args[offset]++) =
667 (ppem << 4) + y_shift;
668 *(delta_args[offset] + num_delta_args[offset]++) =
669 delta->point_idx;
674 static FT_Byte*
675 TA_sfnt_build_delta_exceptions(SFNT* sfnt,
676 FONT* font,
677 FT_Long idx,
678 FT_Byte* bufp)
680 FT_Face face = font->loader->face;
682 int num_points;
683 int i;
685 FT_UShort num_stack_elements;
687 /* DELTAP[1-3] stacks for both x and y directions */
688 FT_UInt* delta_args[6] = {NULL, NULL, NULL, NULL, NULL, NULL};
689 int num_delta_args[6] = {0, 0, 0, 0, 0, 0};
690 FT_UInt* args = NULL;
692 FT_Bool need_words = 0;
693 FT_Bool need_word_counts = 0;
694 FT_Bool allocated = 0;
696 const Delta* delta;
699 num_points = font->loader->gloader->base.outline.n_points;
701 /* loop over all fitting delta exceptions */
702 for (;;)
704 delta = TA_deltas_get_delta(font);
706 /* too large values of font and glyph indices in `delta' */
707 /* are handled by later calls of this function */
708 if (!delta
709 || face->face_index < delta->font_idx
710 || idx < delta->glyph_idx)
711 break;
713 if (!allocated)
715 for (i = 0; i < 6; i++)
717 /* see the comment on allocating `ins_buf' in function */
718 /* `TA_sfnt_build_glyph_instructions' for more on the array sizes; */
719 /* we have to increase by 1 for the number of argument pairs */
720 delta_args[i] = (FT_UInt*)malloc((16 * 2 * num_points + 1)
721 * sizeof (FT_UInt));
722 if (!delta_args[i])
724 bufp = NULL;
725 goto Done;
729 allocated = 1;
732 /* since we walk sequentially over all glyphs (with points), */
733 /* and the delta entries have the same order, */
734 /* we don't need to test for equality of font and glyph indices: */
735 /* at this very point in the code we certainly have a hit */
736 build_delta_exception(delta, delta_args, num_delta_args);
738 if (delta->point_idx > 255)
739 need_words = 1;
741 TA_deltas_get_next(font);
744 /* nothing to do if no delta data */
745 if (!allocated)
746 return bufp;
748 /* add number of argument pairs to the stacks */
749 for (i = 0; i < 6; i++)
751 if (num_delta_args[i])
753 int n = num_delta_args[i] >> 1;
756 if (n > 255)
757 need_word_counts = 1;
759 *(delta_args[i] + num_delta_args[i]) = n;
760 num_delta_args[i]++;
764 /* merge delta stacks into a single one */
765 if (need_words
766 || (!need_words && !need_word_counts))
768 FT_UInt num_args = 0;
771 for (i = 0; i < 6; i++)
773 FT_UInt* args_new;
774 FT_UInt num_args_new;
777 if (!num_delta_args[i])
778 continue;
780 num_args_new = num_args + num_delta_args[i];
781 args_new = (FT_UInt*)realloc(args, num_args_new * sizeof (FT_UInt));
782 if (!args_new)
784 bufp = NULL;
785 goto Done;
788 memcpy(args_new + num_args,
789 delta_args[i],
790 num_delta_args[i] * sizeof (FT_UInt));
792 args = args_new;
793 num_args = num_args_new;
796 num_stack_elements = num_args;
798 bufp = TA_build_push(bufp, args, num_args, need_words, 1);
800 else
802 num_stack_elements = 0;
804 /* stack elements are bytes, but counts need words */
805 for (i = 0; i < 6; i++)
807 int num_delta_arg;
810 if (!num_delta_args[i])
811 continue;
813 num_delta_arg = num_delta_args[i] - 1;
815 bufp = TA_build_push(bufp,
816 delta_args[i],
817 num_delta_arg,
818 need_words,
821 num_stack_elements += num_delta_arg + 1;
823 num_delta_arg >>= 1;
824 BCI(PUSHW_1);
825 BCI(HIGH(num_delta_arg));
826 BCI(LOW(num_delta_arg));
830 /* emit the DELTA opcodes */
831 if (num_delta_args[5])
832 BCI(DELTAP3);
833 if (num_delta_args[4])
834 BCI(DELTAP2);
835 if (num_delta_args[3])
836 BCI(DELTAP1);
838 if (num_delta_args[2] || num_delta_args[1] || num_delta_args[0])
839 BCI(SVTCA_x);
841 if (num_delta_args[2])
842 BCI(DELTAP3);
843 if (num_delta_args[1])
844 BCI(DELTAP2);
845 if (num_delta_args[0])
846 BCI(DELTAP1);
848 Done:
849 for (i = 0; i < 6; i++)
850 free(delta_args[i]);
851 free(args);
853 if (num_stack_elements > sfnt->max_stack_elements)
854 sfnt->max_stack_elements = num_stack_elements;
855 return bufp;
859 static FT_Byte*
860 TA_sfnt_build_glyph_scaler(SFNT* sfnt,
861 Recorder* recorder,
862 FT_Byte* bufp)
864 FONT* font = recorder->font;
865 FT_GlyphSlot glyph = sfnt->face->glyph;
866 FT_Vector* points = glyph->outline.points;
867 FT_Int num_contours = glyph->outline.n_contours;
869 FT_UInt* args;
870 FT_UInt* arg;
871 FT_UInt num_args;
873 FT_Bool need_words = 0;
874 FT_Int p, q;
875 FT_Int start, end;
876 FT_UShort num_storage;
877 FT_UShort num_stack_elements;
880 num_args = 2 * num_contours + 2;
882 /* collect all arguments temporarily in an array (in reverse order) */
883 /* so that we can easily split into chunks of 255 args */
884 /* as needed by NPUSHB and NPUSHW, respectively */
885 args = (FT_UInt*)malloc(num_args * sizeof (FT_UInt));
886 if (!args)
887 return NULL;
889 arg = args + num_args - 1;
891 if (num_args > 0xFF)
892 need_words = 1;
894 if (recorder->glyph->num_components && font->hint_composites)
895 *(arg--) = bci_scale_composite_glyph;
896 else
897 *(arg--) = bci_scale_glyph;
898 *(arg--) = num_contours;
900 start = 0;
901 end = 0;
903 for (p = 0; p < num_contours; p++)
905 FT_Int max = start;
906 FT_Int min = start;
909 end = glyph->outline.contours[p];
911 for (q = start; q <= end; q++)
913 if (points[q].y < points[min].y)
914 min = q;
915 if (points[q].y > points[max].y)
916 max = q;
919 if (min > max)
921 *(arg--) = TA_adjust_point_index(recorder, max);
922 *(arg--) = TA_adjust_point_index(recorder, min);
924 else
926 *(arg--) = TA_adjust_point_index(recorder, min);
927 *(arg--) = TA_adjust_point_index(recorder, max);
930 start = end + 1;
933 if (end > 0xFF)
934 need_words = 1;
936 /* with most fonts it is very rare */
937 /* that any of the pushed arguments is larger than 0xFF, */
938 /* thus we refrain from further optimizing this case */
939 bufp = TA_build_push(bufp, args, num_args, need_words, 1);
941 BCI(CALL);
943 num_storage = sal_segment_offset;
944 if (num_storage > sfnt->max_storage)
945 sfnt->max_storage = num_storage;
947 num_stack_elements = ADDITIONAL_STACK_ELEMENTS + num_args;
948 if (num_stack_elements > sfnt->max_stack_elements)
949 sfnt->max_stack_elements = num_stack_elements;
951 free(args);
953 return bufp;
957 static FT_Byte*
958 TA_font_build_subglyph_shifter(FONT* font,
959 FT_Byte* bufp)
961 FT_Face face = font->loader->face;
962 FT_GlyphSlot glyph = face->glyph;
964 TA_GlyphLoader gloader = font->loader->gloader;
966 TA_SubGlyph subglyphs = gloader->base.subglyphs;
967 TA_SubGlyph subglyph_limit = subglyphs + gloader->base.num_subglyphs;
968 TA_SubGlyph subglyph;
970 FT_Int curr_contour = 0;
973 for (subglyph = subglyphs; subglyph < subglyph_limit; subglyph++)
975 FT_Error error;
977 FT_UShort flags = subglyph->flags;
978 FT_Pos y_offset = subglyph->arg2;
980 FT_Int num_contours;
983 /* load subglyph to get the number of contours */
984 error = FT_Load_Glyph(face, subglyph->index, FT_LOAD_NO_SCALE);
985 if (error)
986 return NULL;
987 num_contours = glyph->outline.n_contours;
989 /* nothing to do if there is a point-to-point alignment */
990 if (!(flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES))
991 goto End;
993 /* nothing to do if y offset is zero */
994 if (!y_offset)
995 goto End;
997 /* nothing to do if there are no contours */
998 if (!num_contours)
999 goto End;
1001 /* note that calling `FT_Load_Glyph' without FT_LOAD_NO_RECURSE */
1002 /* ensures that composite subglyphs are represented as simple glyphs */
1004 if (num_contours > 0xFF
1005 || curr_contour > 0xFF)
1007 BCI(PUSHW_2);
1008 BCI(HIGH(curr_contour));
1009 BCI(LOW(curr_contour));
1010 BCI(HIGH(num_contours));
1011 BCI(LOW(num_contours));
1013 else
1015 BCI(PUSHB_2);
1016 BCI(curr_contour);
1017 BCI(num_contours);
1020 /* there are high chances that this value needs PUSHW, */
1021 /* thus we handle it separately */
1022 if (y_offset > 0xFF || y_offset < 0)
1024 BCI(PUSHW_1);
1025 BCI(HIGH(y_offset));
1026 BCI(LOW(y_offset));
1028 else
1030 BCI(PUSHB_1);
1031 BCI(y_offset);
1034 BCI(PUSHB_1);
1035 BCI(bci_shift_subglyph);
1036 BCI(CALL);
1038 End:
1039 curr_contour += num_contours;
1042 return bufp;
1047 * The four `ta_ip_*' actions in the `TA_hints_recorder' callback store its
1048 * data in four arrays (which are simple but waste a lot of memory). The
1049 * function below converts them into bytecode.
1051 * For `ta_ip_before' and `ta_ip_after', the collected points are emitted
1052 * together with the edge they correspond to.
1054 * For both `ta_ip_on' and `ta_ip_between', an outer loop is constructed to
1055 * loop over the edge or edge pairs, respectively, and each edge or edge
1056 * pair contains an inner loop to emit the correponding points.
1059 static void
1060 TA_build_point_hints(Recorder* recorder,
1061 TA_GlyphHints hints)
1063 TA_AxisHints axis = &hints->axis[TA_DIMENSION_VERT];
1064 TA_Segment segments = axis->segments;
1065 TA_Edge edges = axis->edges;
1067 FT_Byte* p = recorder->hints_record.buf;
1069 FT_UShort i;
1070 FT_UShort j;
1072 FT_UShort prev_edge;
1073 FT_UShort prev_before_edge;
1074 FT_UShort prev_after_edge;
1076 Node1* before_node;
1077 Node1* after_node;
1078 Node2* on_node;
1079 Node3* between_node;
1082 /* we store everything as 16bit numbers; */
1083 /* the function numbers (`ta_ip_before', etc.) */
1084 /* reflect the order in the TA_Action enumeration */
1086 /* ip_before_points */
1088 i = 0;
1089 for (before_node = LLRB_MIN(ip_before_points,
1090 &recorder->ip_before_points_head);
1091 before_node;
1092 before_node = LLRB_NEXT(ip_before_points,
1093 &recorder->ip_before_points_head,
1094 before_node))
1096 /* count points */
1097 i++;
1100 if (i)
1102 TA_Edge edge;
1105 recorder->hints_record.num_actions++;
1107 edge = edges;
1109 *(p++) = 0;
1110 *(p++) = (FT_Byte)ta_ip_before + ACTION_OFFSET;
1111 *(p++) = HIGH(edge->first - segments);
1112 *(p++) = LOW(edge->first - segments);
1113 *(p++) = HIGH(i);
1114 *(p++) = LOW(i);
1116 for (before_node = LLRB_MIN(ip_before_points,
1117 &recorder->ip_before_points_head);
1118 before_node;
1119 before_node = LLRB_NEXT(ip_before_points,
1120 &recorder->ip_before_points_head,
1121 before_node))
1123 FT_UInt point;
1126 point = TA_adjust_point_index(recorder, before_node->point);
1127 *(p++) = HIGH(point);
1128 *(p++) = LOW(point);
1132 /* ip_after_points */
1134 i = 0;
1135 for (after_node = LLRB_MIN(ip_after_points,
1136 &recorder->ip_after_points_head);
1137 after_node;
1138 after_node = LLRB_NEXT(ip_after_points,
1139 &recorder->ip_after_points_head,
1140 after_node))
1142 /* count points */
1143 i++;
1146 if (i)
1148 TA_Edge edge;
1151 recorder->hints_record.num_actions++;
1153 edge = edges + axis->num_edges - 1;
1155 *(p++) = 0;
1156 *(p++) = (FT_Byte)ta_ip_after + ACTION_OFFSET;
1157 *(p++) = HIGH(edge->first - segments);
1158 *(p++) = LOW(edge->first - segments);
1159 *(p++) = HIGH(i);
1160 *(p++) = LOW(i);
1162 for (after_node = LLRB_MIN(ip_after_points,
1163 &recorder->ip_after_points_head);
1164 after_node;
1165 after_node = LLRB_NEXT(ip_after_points,
1166 &recorder->ip_after_points_head,
1167 after_node))
1169 FT_UInt point;
1172 point = TA_adjust_point_index(recorder, after_node->point);
1173 *(p++) = HIGH(point);
1174 *(p++) = LOW(point);
1178 /* ip_on_point_array */
1180 prev_edge = 0xFFFF;
1181 i = 0;
1182 for (on_node = LLRB_MIN(ip_on_points,
1183 &recorder->ip_on_points_head);
1184 on_node;
1185 on_node = LLRB_NEXT(ip_on_points,
1186 &recorder->ip_on_points_head,
1187 on_node))
1189 /* count edges */
1190 if (on_node->edge != prev_edge)
1192 i++;
1193 prev_edge = on_node->edge;
1197 if (i)
1199 recorder->hints_record.num_actions++;
1201 *(p++) = 0;
1202 *(p++) = (FT_Byte)ta_ip_on + ACTION_OFFSET;
1203 *(p++) = HIGH(i);
1204 *(p++) = LOW(i);
1206 for (on_node = LLRB_MIN(ip_on_points,
1207 &recorder->ip_on_points_head);
1208 on_node;
1209 on_node = LLRB_NEXT(ip_on_points,
1210 &recorder->ip_on_points_head,
1211 on_node))
1213 Node2* edge_node;
1214 TA_Edge edge;
1217 edge = edges + on_node->edge;
1219 *(p++) = HIGH(edge->first - segments);
1220 *(p++) = LOW(edge->first - segments);
1222 /* save current position */
1223 edge_node = on_node;
1224 j = 0;
1225 for (;
1226 on_node;
1227 on_node = LLRB_NEXT(ip_on_points,
1228 &recorder->ip_on_points_head,
1229 on_node))
1231 /* count points on current edge */
1232 if (on_node->edge != edge_node->edge)
1233 break;
1234 j++;
1237 *(p++) = HIGH(j);
1238 *(p++) = LOW(j);
1240 /* restore current position */
1241 on_node = edge_node;
1242 for (;
1243 on_node;
1244 on_node = LLRB_NEXT(ip_on_points,
1245 &recorder->ip_on_points_head,
1246 on_node))
1248 FT_UInt point;
1251 if (on_node->edge != edge_node->edge)
1252 break;
1254 point = TA_adjust_point_index(recorder, on_node->point);
1255 *(p++) = HIGH(point);
1256 *(p++) = LOW(point);
1258 /* keep track of previous node */
1259 edge_node = on_node;
1262 /* reset loop iterator by one element, then continue */
1263 on_node = edge_node;
1267 /* ip_between_point_array */
1269 prev_before_edge = 0xFFFF;
1270 prev_after_edge = 0xFFFF;
1271 i = 0;
1272 for (between_node = LLRB_MIN(ip_between_points,
1273 &recorder->ip_between_points_head);
1274 between_node;
1275 between_node = LLRB_NEXT(ip_between_points,
1276 &recorder->ip_between_points_head,
1277 between_node))
1279 /* count `(before,after)' edge pairs */
1280 if (between_node->before_edge != prev_before_edge
1281 || between_node->after_edge != prev_after_edge)
1283 i++;
1284 prev_before_edge = between_node->before_edge;
1285 prev_after_edge = between_node->after_edge;
1289 if (i)
1291 recorder->hints_record.num_actions++;
1293 *(p++) = 0;
1294 *(p++) = (FT_Byte)ta_ip_between + ACTION_OFFSET;
1295 *(p++) = HIGH(i);
1296 *(p++) = LOW(i);
1298 for (between_node = LLRB_MIN(ip_between_points,
1299 &recorder->ip_between_points_head);
1300 between_node;
1301 between_node = LLRB_NEXT(ip_between_points,
1302 &recorder->ip_between_points_head,
1303 between_node))
1305 Node3* edge_pair_node;
1306 TA_Edge before;
1307 TA_Edge after;
1310 before = edges + between_node->before_edge;
1311 after = edges + between_node->after_edge;
1313 *(p++) = HIGH(after->first - segments);
1314 *(p++) = LOW(after->first - segments);
1315 *(p++) = HIGH(before->first - segments);
1316 *(p++) = LOW(before->first - segments);
1318 /* save current position */
1319 edge_pair_node = between_node;
1320 j = 0;
1321 for (;
1322 between_node;
1323 between_node = LLRB_NEXT(ip_between_points,
1324 &recorder->ip_between_points_head,
1325 between_node))
1327 /* count points associated with current edge pair */
1328 if (between_node->before_edge != edge_pair_node->before_edge
1329 || between_node->after_edge != edge_pair_node->after_edge)
1330 break;
1331 j++;
1334 *(p++) = HIGH(j);
1335 *(p++) = LOW(j);
1337 /* restore current position */
1338 between_node = edge_pair_node;
1339 for (;
1340 between_node;
1341 between_node = LLRB_NEXT(ip_between_points,
1342 &recorder->ip_between_points_head,
1343 between_node))
1345 FT_UInt point;
1348 if (between_node->before_edge != edge_pair_node->before_edge
1349 || between_node->after_edge != edge_pair_node->after_edge)
1350 break;
1352 point = TA_adjust_point_index(recorder, between_node->point);
1353 *(p++) = HIGH(point);
1354 *(p++) = LOW(point);
1356 /* keep track of previous node */
1357 edge_pair_node = between_node;
1360 /* reset loop iterator by one element, then continue */
1361 between_node = edge_pair_node;
1365 recorder->hints_record.buf = p;
1369 static FT_Bool
1370 TA_hints_record_is_different(Hints_Record* hints_records,
1371 FT_UInt num_hints_records,
1372 FT_Byte* start,
1373 FT_Byte* end)
1375 Hints_Record last_hints_record;
1378 if (!hints_records)
1379 return 1;
1381 /* we only need to compare with the last hints record */
1382 last_hints_record = hints_records[num_hints_records - 1];
1384 if ((FT_UInt)(end - start) != last_hints_record.buf_len)
1385 return 1;
1387 if (memcmp(start, last_hints_record.buf, last_hints_record.buf_len))
1388 return 1;
1390 return 0;
1394 static FT_Error
1395 TA_add_hints_record(Hints_Record** hints_records,
1396 FT_UInt* num_hints_records,
1397 FT_Byte* start,
1398 Hints_Record hints_record)
1400 Hints_Record* hints_records_new;
1401 FT_UInt buf_len;
1402 /* at this point, `hints_record.buf' still points into `ins_buf' */
1403 FT_Byte* end = hints_record.buf;
1406 buf_len = (FT_UInt)(end - start);
1408 /* now fill the structure completely */
1409 hints_record.buf_len = buf_len;
1410 hints_record.buf = (FT_Byte*)malloc(buf_len);
1411 if (!hints_record.buf)
1412 return FT_Err_Out_Of_Memory;
1414 memcpy(hints_record.buf, start, buf_len);
1416 (*num_hints_records)++;
1417 hints_records_new =
1418 (Hints_Record*)realloc(*hints_records, *num_hints_records
1419 * sizeof (Hints_Record));
1420 if (!hints_records_new)
1422 free(hints_record.buf);
1423 (*num_hints_records)--;
1424 return FT_Err_Out_Of_Memory;
1426 else
1427 *hints_records = hints_records_new;
1429 (*hints_records)[*num_hints_records - 1] = hints_record;
1431 return FT_Err_Ok;
1435 static FT_Byte*
1436 TA_emit_hints_record(Recorder* recorder,
1437 Hints_Record* hints_record,
1438 FT_Byte* bufp,
1439 FT_Bool optimize)
1441 FT_Byte* p;
1442 FT_Byte* endp;
1443 FT_Bool need_words = 0;
1445 FT_UInt i, j;
1446 FT_UInt num_arguments;
1447 FT_UInt num_args;
1450 /* check whether any argument is larger than 0xFF */
1451 endp = hints_record->buf + hints_record->buf_len;
1452 for (p = hints_record->buf; p < endp; p += 2)
1453 if (*p)
1455 need_words = 1;
1456 break;
1459 /* with most fonts it is very rare */
1460 /* that any of the pushed arguments is larger than 0xFF, */
1461 /* thus we refrain from further optimizing this case */
1463 num_arguments = hints_record->buf_len / 2;
1464 p = endp - 2;
1466 if (need_words)
1468 for (i = 0; i < num_arguments; i += 255)
1470 num_args = (num_arguments - i > 255) ? 255 : (num_arguments - i);
1472 if (optimize && num_args <= 8)
1473 BCI(PUSHW_1 - 1 + num_args);
1474 else
1476 BCI(NPUSHW);
1477 BCI(num_args);
1479 for (j = 0; j < num_args; j++)
1481 BCI(*p);
1482 BCI(*(p + 1));
1483 p -= 2;
1487 else
1489 /* we only need the lower bytes */
1490 p++;
1492 for (i = 0; i < num_arguments; i += 255)
1494 num_args = (num_arguments - i > 255) ? 255 : (num_arguments - i);
1496 if (optimize && num_args <= 8)
1497 BCI(PUSHB_1 - 1 + num_args);
1498 else
1500 BCI(NPUSHB);
1501 BCI(num_args);
1503 for (j = 0; j < num_args; j++)
1505 BCI(*p);
1506 p -= 2;
1511 /* collect stack depth data */
1512 if (num_arguments > recorder->num_stack_elements)
1513 recorder->num_stack_elements = num_arguments;
1515 return bufp;
1519 static FT_Byte*
1520 TA_emit_hints_records(Recorder* recorder,
1521 Hints_Record* hints_records,
1522 FT_UInt num_hints_records,
1523 FT_Byte* bufp,
1524 FT_Bool optimize)
1526 FT_UInt i;
1527 Hints_Record* hints_record;
1530 hints_record = hints_records;
1532 /* emit hints records in `if' clauses, */
1533 /* with the ppem size as the condition */
1534 for (i = 0; i < num_hints_records - 1; i++)
1536 BCI(MPPEM);
1537 if (hints_record->size > 0xFF)
1539 BCI(PUSHW_1);
1540 BCI(HIGH((hints_record + 1)->size));
1541 BCI(LOW((hints_record + 1)->size));
1543 else
1545 BCI(PUSHB_1);
1546 BCI((hints_record + 1)->size);
1548 BCI(LT);
1549 BCI(IF);
1550 bufp = TA_emit_hints_record(recorder, hints_record, bufp, optimize);
1551 BCI(ELSE);
1553 hints_record++;
1556 bufp = TA_emit_hints_record(recorder, hints_record, bufp, optimize);
1558 for (i = 0; i < num_hints_records - 1; i++)
1559 BCI(EIF);
1561 return bufp;
1565 static void
1566 TA_free_hints_records(Hints_Record* hints_records,
1567 FT_UInt num_hints_records)
1569 FT_UInt i;
1572 for (i = 0; i < num_hints_records; i++)
1573 free(hints_records[i].buf);
1575 free(hints_records);
1579 static FT_Byte*
1580 TA_hints_recorder_handle_segments(FT_Byte* bufp,
1581 TA_AxisHints axis,
1582 TA_Edge edge,
1583 FT_UShort* wraps)
1585 TA_Segment segments = axis->segments;
1586 TA_Segment seg;
1587 FT_UShort seg_idx;
1588 FT_UShort num_segs = 0;
1589 FT_UShort* wrap;
1592 seg_idx = edge->first - segments;
1594 /* we store everything as 16bit numbers */
1595 *(bufp++) = HIGH(seg_idx);
1596 *(bufp++) = LOW(seg_idx);
1598 /* wrap-around segments are stored as two segments */
1599 if (edge->first->first > edge->first->last)
1600 num_segs++;
1602 seg = edge->first->edge_next;
1603 while (seg != edge->first)
1605 num_segs++;
1607 if (seg->first > seg->last)
1608 num_segs++;
1610 seg = seg->edge_next;
1613 *(bufp++) = HIGH(num_segs);
1614 *(bufp++) = LOW(num_segs);
1616 if (edge->first->first > edge->first->last)
1618 /* emit second part of wrap-around segment; */
1619 /* the bytecode positions such segments after `normal' ones */
1620 wrap = wraps;
1621 for (;;)
1623 if (seg_idx == *wrap)
1624 break;
1625 wrap++;
1628 *(bufp++) = HIGH(axis->num_segments + (wrap - wraps));
1629 *(bufp++) = LOW(axis->num_segments + (wrap - wraps));
1632 seg = edge->first->edge_next;
1633 while (seg != edge->first)
1635 seg_idx = seg - segments;
1637 *(bufp++) = HIGH(seg_idx);
1638 *(bufp++) = LOW(seg_idx);
1640 if (seg->first > seg->last)
1642 wrap = wraps;
1643 for (;;)
1645 if (seg_idx == *wrap)
1646 break;
1647 wrap++;
1650 *(bufp++) = HIGH(axis->num_segments + (wrap - wraps));
1651 *(bufp++) = LOW(axis->num_segments + (wrap - wraps));
1654 seg = seg->edge_next;
1657 return bufp;
1661 static void
1662 TA_hints_recorder(TA_Action action,
1663 TA_GlyphHints hints,
1664 TA_Dimension dim,
1665 void* arg1,
1666 TA_Edge arg2,
1667 TA_Edge arg3,
1668 TA_Edge lower_bound,
1669 TA_Edge upper_bound)
1671 TA_AxisHints axis = &hints->axis[dim];
1672 TA_Edge edges = axis->edges;
1673 TA_Segment segments = axis->segments;
1674 TA_Point points = hints->points;
1676 Recorder* recorder = (Recorder*)hints->user;
1677 SFNT* sfnt = recorder->sfnt;
1678 FONT* font = recorder->font;
1679 FT_UShort* wraps = recorder->wrap_around_segments;
1680 FT_Byte* p = recorder->hints_record.buf;
1682 FT_UInt style = font->loader->metrics->style_class->style;
1685 if (dim == TA_DIMENSION_HORZ)
1686 return;
1688 /* we collect point hints for later processing */
1689 switch (action)
1691 case ta_ip_before:
1693 Node1* before_node;
1694 TA_Point point = (TA_Point)arg1;
1697 before_node = (Node1*)malloc(sizeof (Node1));
1698 if (!before_node)
1699 return;
1700 before_node->point = point - points;
1702 LLRB_INSERT(ip_before_points,
1703 &recorder->ip_before_points_head,
1704 before_node);
1706 return;
1708 case ta_ip_after:
1710 Node1* after_node;
1711 TA_Point point = (TA_Point)arg1;
1714 after_node = (Node1*)malloc(sizeof (Node1));
1715 if (!after_node)
1716 return;
1717 after_node->point = point - points;
1719 LLRB_INSERT(ip_after_points,
1720 &recorder->ip_after_points_head,
1721 after_node);
1723 return;
1725 case ta_ip_on:
1727 Node2* on_node;
1728 TA_Point point = (TA_Point)arg1;
1729 TA_Edge edge = arg2;
1732 on_node = (Node2*)malloc(sizeof (Node2));
1733 if (!on_node)
1734 return;
1735 on_node->edge = edge - edges;
1736 on_node->point = point - points;
1738 LLRB_INSERT(ip_on_points,
1739 &recorder->ip_on_points_head,
1740 on_node);
1742 return;
1744 case ta_ip_between:
1746 Node3* between_node;
1747 TA_Point point = (TA_Point)arg1;
1748 TA_Edge before = arg2;
1749 TA_Edge after = arg3;
1752 between_node = (Node3*)malloc(sizeof (Node3));
1753 if (!between_node)
1754 return;
1755 between_node->before_edge = before - edges;
1756 between_node->after_edge = after - edges;
1757 between_node->point = point - points;
1759 LLRB_INSERT(ip_between_points,
1760 &recorder->ip_between_points_head,
1761 between_node);
1763 return;
1765 case ta_bound:
1766 /* we ignore the BOUND action since we signal this information */
1767 /* with the proper function number */
1768 return;
1770 default:
1771 break;
1774 /* some enum values correspond to four or eight bytecode functions; */
1775 /* if the value is n, the function numbers are n, ..., n+7, */
1776 /* to be differentiated with flags */
1778 switch (action)
1780 case ta_link:
1782 TA_Edge base_edge = (TA_Edge)arg1;
1783 TA_Edge stem_edge = arg2;
1786 *(p++) = 0;
1787 *(p++) = (FT_Byte)action + ACTION_OFFSET
1788 + ((stem_edge->flags & TA_EDGE_SERIF) != 0)
1789 + 2 * ((base_edge->flags & TA_EDGE_ROUND) != 0);
1791 *(p++) = HIGH(base_edge->first - segments);
1792 *(p++) = LOW(base_edge->first - segments);
1793 *(p++) = HIGH(stem_edge->first - segments);
1794 *(p++) = LOW(stem_edge->first - segments);
1796 p = TA_hints_recorder_handle_segments(p, axis, stem_edge, wraps);
1798 break;
1800 case ta_anchor:
1802 TA_Edge edge = (TA_Edge)arg1;
1803 TA_Edge edge2 = arg2;
1806 *(p++) = 0;
1807 *(p++) = (FT_Byte)action + ACTION_OFFSET
1808 + ((edge2->flags & TA_EDGE_SERIF) != 0)
1809 + 2 * ((edge->flags & TA_EDGE_ROUND) != 0);
1811 *(p++) = HIGH(edge->first - segments);
1812 *(p++) = LOW(edge->first - segments);
1813 *(p++) = HIGH(edge2->first - segments);
1814 *(p++) = LOW(edge2->first - segments);
1816 p = TA_hints_recorder_handle_segments(p, axis, edge, wraps);
1818 break;
1820 case ta_adjust:
1822 TA_Edge edge = (TA_Edge)arg1;
1823 TA_Edge edge2 = arg2;
1824 TA_Edge edge_minus_one = lower_bound;
1827 *(p++) = 0;
1828 *(p++) = (FT_Byte)action + ACTION_OFFSET
1829 + ((edge2->flags & TA_EDGE_SERIF) != 0)
1830 + 2 * ((edge->flags & TA_EDGE_ROUND) != 0)
1831 + 4 * (edge_minus_one != NULL);
1833 *(p++) = HIGH(edge->first - segments);
1834 *(p++) = LOW(edge->first - segments);
1835 *(p++) = HIGH(edge2->first - segments);
1836 *(p++) = LOW(edge2->first - segments);
1838 if (edge_minus_one)
1840 *(p++) = HIGH(edge_minus_one->first - segments);
1841 *(p++) = LOW(edge_minus_one->first - segments);
1844 p = TA_hints_recorder_handle_segments(p, axis, edge, wraps);
1846 break;
1848 case ta_blue_anchor:
1850 TA_Edge edge = (TA_Edge)arg1;
1851 TA_Edge blue = arg2;
1854 *(p++) = 0;
1855 *(p++) = (FT_Byte)action + ACTION_OFFSET;
1857 *(p++) = HIGH(blue->first - segments);
1858 *(p++) = LOW(blue->first - segments);
1860 if (edge->best_blue_is_shoot)
1862 *(p++) = HIGH(CVT_BLUE_SHOOTS_OFFSET(style) + edge->best_blue_idx);
1863 *(p++) = LOW(CVT_BLUE_SHOOTS_OFFSET(style) + edge->best_blue_idx);
1865 else
1867 *(p++) = HIGH(CVT_BLUE_REFS_OFFSET(style) + edge->best_blue_idx);
1868 *(p++) = LOW(CVT_BLUE_REFS_OFFSET(style) + edge->best_blue_idx);
1871 *(p++) = HIGH(edge->first - segments);
1872 *(p++) = LOW(edge->first - segments);
1874 p = TA_hints_recorder_handle_segments(p, axis, edge, wraps);
1876 break;
1878 case ta_stem:
1880 TA_Edge edge = (TA_Edge)arg1;
1881 TA_Edge edge2 = arg2;
1882 TA_Edge edge_minus_one = lower_bound;
1885 *(p++) = 0;
1886 *(p++) = (FT_Byte)action + ACTION_OFFSET
1887 + ((edge2->flags & TA_EDGE_SERIF) != 0)
1888 + 2 * ((edge->flags & TA_EDGE_ROUND) != 0)
1889 + 4 * (edge_minus_one != NULL);
1891 *(p++) = HIGH(edge->first - segments);
1892 *(p++) = LOW(edge->first - segments);
1893 *(p++) = HIGH(edge2->first - segments);
1894 *(p++) = LOW(edge2->first - segments);
1896 if (edge_minus_one)
1898 *(p++) = HIGH(edge_minus_one->first - segments);
1899 *(p++) = LOW(edge_minus_one->first - segments);
1902 p = TA_hints_recorder_handle_segments(p, axis, edge, wraps);
1903 p = TA_hints_recorder_handle_segments(p, axis, edge2, wraps);
1905 break;
1907 case ta_blue:
1909 TA_Edge edge = (TA_Edge)arg1;
1912 *(p++) = 0;
1913 *(p++) = (FT_Byte)action + ACTION_OFFSET;
1915 if (edge->best_blue_is_shoot)
1917 *(p++) = HIGH(CVT_BLUE_SHOOTS_OFFSET(style) + edge->best_blue_idx);
1918 *(p++) = LOW(CVT_BLUE_SHOOTS_OFFSET(style) + edge->best_blue_idx);
1920 else
1922 *(p++) = HIGH(CVT_BLUE_REFS_OFFSET(style) + edge->best_blue_idx);
1923 *(p++) = LOW(CVT_BLUE_REFS_OFFSET(style) + edge->best_blue_idx);
1926 *(p++) = HIGH(edge->first - segments);
1927 *(p++) = LOW(edge->first - segments);
1929 p = TA_hints_recorder_handle_segments(p, axis, edge, wraps);
1931 break;
1933 case ta_serif:
1935 TA_Edge serif = (TA_Edge)arg1;
1936 TA_Edge base = serif->serif;
1939 *(p++) = 0;
1940 *(p++) = (FT_Byte)action + ACTION_OFFSET
1941 + (lower_bound != NULL)
1942 + 2 * (upper_bound != NULL);
1944 *(p++) = HIGH(serif->first - segments);
1945 *(p++) = LOW(serif->first - segments);
1946 *(p++) = HIGH(base->first - segments);
1947 *(p++) = LOW(base->first - segments);
1949 if (lower_bound)
1951 *(p++) = HIGH(lower_bound->first - segments);
1952 *(p++) = LOW(lower_bound->first - segments);
1954 if (upper_bound)
1956 *(p++) = HIGH(upper_bound->first - segments);
1957 *(p++) = LOW(upper_bound->first - segments);
1960 p = TA_hints_recorder_handle_segments(p, axis, serif, wraps);
1962 break;
1964 case ta_serif_anchor:
1965 case ta_serif_link2:
1967 TA_Edge edge = (TA_Edge)arg1;
1970 *(p++) = 0;
1971 *(p++) = (FT_Byte)action + ACTION_OFFSET
1972 + (lower_bound != NULL)
1973 + 2 * (upper_bound != NULL);
1975 *(p++) = HIGH(edge->first - segments);
1976 *(p++) = LOW(edge->first - segments);
1978 if (lower_bound)
1980 *(p++) = HIGH(lower_bound->first - segments);
1981 *(p++) = LOW(lower_bound->first - segments);
1983 if (upper_bound)
1985 *(p++) = HIGH(upper_bound->first - segments);
1986 *(p++) = LOW(upper_bound->first - segments);
1989 p = TA_hints_recorder_handle_segments(p, axis, edge, wraps);
1991 break;
1993 case ta_serif_link1:
1995 TA_Edge edge = (TA_Edge)arg1;
1996 TA_Edge before = arg2;
1997 TA_Edge after = arg3;
2000 *(p++) = 0;
2001 *(p++) = (FT_Byte)action + ACTION_OFFSET
2002 + (lower_bound != NULL)
2003 + 2 * (upper_bound != NULL);
2005 *(p++) = HIGH(before->first - segments);
2006 *(p++) = LOW(before->first - segments);
2007 *(p++) = HIGH(edge->first - segments);
2008 *(p++) = LOW(edge->first - segments);
2009 *(p++) = HIGH(after->first - segments);
2010 *(p++) = LOW(after->first - segments);
2012 if (lower_bound)
2014 *(p++) = HIGH(lower_bound->first - segments);
2015 *(p++) = LOW(lower_bound->first - segments);
2017 if (upper_bound)
2019 *(p++) = HIGH(upper_bound->first - segments);
2020 *(p++) = LOW(upper_bound->first - segments);
2023 p = TA_hints_recorder_handle_segments(p, axis, edge, wraps);
2025 break;
2027 default:
2028 /* there are more cases in the enumeration */
2029 /* which are handled with flags */
2030 break;
2033 recorder->hints_record.num_actions++;
2034 recorder->hints_record.buf = p;
2038 static FT_Error
2039 TA_init_recorder(Recorder* recorder,
2040 SFNT* sfnt,
2041 FONT* font,
2042 GLYPH* glyph,
2043 TA_GlyphHints hints)
2045 TA_AxisHints axis = &hints->axis[TA_DIMENSION_VERT];
2046 TA_Point points = hints->points;
2047 TA_Point point_limit = points + hints->num_points;
2048 TA_Point point;
2050 TA_Segment segments = axis->segments;
2051 TA_Segment seg_limit = segments + axis->num_segments;
2052 TA_Segment seg;
2054 FT_UShort num_strong_points = 0;
2055 FT_UShort* wrap_around_segment;
2057 recorder->sfnt = sfnt;
2058 recorder->font = font;
2059 recorder->glyph = glyph;
2060 recorder->num_segments = axis->num_segments;
2062 LLRB_INIT(&recorder->ip_before_points_head);
2063 LLRB_INIT(&recorder->ip_after_points_head);
2064 LLRB_INIT(&recorder->ip_on_points_head);
2065 LLRB_INIT(&recorder->ip_between_points_head);
2067 recorder->num_stack_elements = 0;
2069 /* no need to clean up allocated arrays in case of error; */
2070 /* this is handled later by `TA_free_recorder' */
2072 recorder->num_wrap_around_segments = 0;
2073 for (seg = segments; seg < seg_limit; seg++)
2074 if (seg->first > seg->last)
2075 recorder->num_wrap_around_segments++;
2077 recorder->wrap_around_segments =
2078 (FT_UShort*)malloc(recorder->num_wrap_around_segments
2079 * sizeof (FT_UShort));
2080 if (!recorder->wrap_around_segments)
2081 return FT_Err_Out_Of_Memory;
2083 wrap_around_segment = recorder->wrap_around_segments;
2084 for (seg = segments; seg < seg_limit; seg++)
2085 if (seg->first > seg->last)
2086 *(wrap_around_segment++) = seg - segments;
2088 /* get number of strong points */
2089 for (point = points; point < point_limit; point++)
2091 /* actually, we need to test `TA_FLAG_TOUCH_Y' also; */
2092 /* however, this value isn't known yet */
2093 /* (or rather, it can vary between different pixel sizes) */
2094 if (point->flags & TA_FLAG_WEAK_INTERPOLATION)
2095 continue;
2097 num_strong_points++;
2100 recorder->num_strong_points = num_strong_points;
2102 return FT_Err_Ok;
2106 static void
2107 TA_reset_recorder(Recorder* recorder,
2108 FT_Byte* bufp)
2110 recorder->hints_record.buf = bufp;
2111 recorder->hints_record.num_actions = 0;
2115 static void
2116 TA_rewind_recorder(Recorder* recorder,
2117 FT_Byte* bufp,
2118 FT_UInt size)
2120 Node1* before_node;
2121 Node1* after_node;
2122 Node2* on_node;
2123 Node3* between_node;
2125 Node1* next_before_node;
2126 Node1* next_after_node;
2127 Node2* next_on_node;
2128 Node3* next_between_node;
2131 TA_reset_recorder(recorder, bufp);
2133 recorder->hints_record.size = size;
2135 /* deallocate our red-black trees */
2137 for (before_node = LLRB_MIN(ip_before_points,
2138 &recorder->ip_before_points_head);
2139 before_node;
2140 before_node = next_before_node)
2142 next_before_node = LLRB_NEXT(ip_before_points,
2143 &recorder->ip_before_points_head,
2144 before_node);
2145 LLRB_REMOVE(ip_before_points,
2146 &recorder->ip_before_points_head,
2147 before_node);
2148 free(before_node);
2151 for (after_node = LLRB_MIN(ip_after_points,
2152 &recorder->ip_after_points_head);
2153 after_node;
2154 after_node = next_after_node)
2156 next_after_node = LLRB_NEXT(ip_after_points,
2157 &recorder->ip_after_points_head,
2158 after_node);
2159 LLRB_REMOVE(ip_after_points,
2160 &recorder->ip_after_points_head,
2161 after_node);
2162 free(after_node);
2165 for (on_node = LLRB_MIN(ip_on_points,
2166 &recorder->ip_on_points_head);
2167 on_node;
2168 on_node = next_on_node)
2170 next_on_node = LLRB_NEXT(ip_on_points,
2171 &recorder->ip_on_points_head,
2172 on_node);
2173 LLRB_REMOVE(ip_on_points,
2174 &recorder->ip_on_points_head,
2175 on_node);
2176 free(on_node);
2179 for (between_node = LLRB_MIN(ip_between_points,
2180 &recorder->ip_between_points_head);
2181 between_node;
2182 between_node = next_between_node)
2184 next_between_node = LLRB_NEXT(ip_between_points,
2185 &recorder->ip_between_points_head,
2186 between_node);
2187 LLRB_REMOVE(ip_between_points,
2188 &recorder->ip_between_points_head,
2189 between_node);
2190 free(between_node);
2195 static void
2196 TA_free_recorder(Recorder* recorder)
2198 free(recorder->wrap_around_segments);
2200 TA_rewind_recorder(recorder, NULL, 0);
2204 FT_Error
2205 TA_sfnt_build_glyph_instructions(SFNT* sfnt,
2206 FONT* font,
2207 FT_Long idx)
2209 FT_Face face = sfnt->face;
2210 FT_Error error;
2212 FT_Byte* ins_buf;
2213 FT_UInt ins_len;
2214 FT_Byte* bufp;
2215 FT_Byte* p;
2217 SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
2218 glyf_Data* data = (glyf_Data*)glyf_table->data;
2219 /* `idx' is never negative */
2220 GLYPH* glyph = &data->glyphs[idx];
2222 TA_GlyphHints hints;
2224 FT_UInt num_action_hints_records = 0;
2225 FT_UInt num_point_hints_records = 0;
2226 Hints_Record* action_hints_records = NULL;
2227 Hints_Record* point_hints_records = NULL;
2229 Recorder recorder;
2230 FT_UShort num_stack_elements;
2231 FT_Bool optimize = 0;
2233 FT_Int32 load_flags;
2234 FT_UInt size;
2236 FT_Byte* pos[3];
2238 #ifdef TA_DEBUG
2239 int _ta_debug_save;
2240 #endif
2243 /* XXX: right now, we abuse this flag to control */
2244 /* the global behaviour of the auto-hinter */
2245 load_flags = 1 << 29; /* vertical hinting only */
2246 if (!font->adjust_subglyphs)
2248 if (font->hint_composites)
2249 load_flags |= FT_LOAD_NO_SCALE;
2250 else
2251 load_flags |= FT_LOAD_NO_RECURSE;
2254 /* computing the segments is resolution independent, */
2255 /* thus the pixel size in this call is arbitrary -- */
2256 /* however, we avoid unnecessary debugging output */
2257 /* if we use the lowest value of the hinting range */
2258 error = FT_Set_Pixel_Sizes(face,
2259 font->hinting_range_min,
2260 font->hinting_range_min);
2261 if (error)
2262 return error;
2264 #ifdef TA_DEBUG
2265 /* temporarily disable some debugging output */
2266 /* to avoid getting the information twice */
2267 _ta_debug_save = _ta_debug;
2268 _ta_debug = 0;
2269 #endif
2271 ta_loader_register_hints_recorder(font->loader, NULL, NULL);
2272 error = ta_loader_load_glyph(font, face, (FT_UInt)idx, load_flags);
2274 #ifdef TA_DEBUG
2275 _ta_debug = _ta_debug_save;
2276 #endif
2278 if (error)
2279 return error;
2281 /* do nothing if we have an empty glyph */
2282 if (!face->glyph->outline.n_contours)
2283 return FT_Err_Ok;
2285 hints = &font->loader->hints;
2287 /* do nothing if the setup delivered the `none_dflt' style only */
2288 if (!hints->num_points)
2289 return FT_Err_Ok;
2292 * We allocate a buffer which is certainly large enough
2293 * to hold all of the created bytecode instructions;
2294 * later on it gets reallocated to its real size.
2296 * The value `1000' is a very rough guess, not tested well.
2298 * For delta exceptions, we have three DELTA commands,
2299 * covering 3*16 ppem values.
2300 * Since a point index can be larger than 255,
2301 * we assume two bytes everywhere for the necessary PUSH calls.
2302 * This value must be doubled for the other arguments of DELTA.
2303 * Additionally, we have both x and y deltas,
2304 * which need to be handled separately in the bytecode.
2305 * In summary, this is approx. 3*16 * 2*2 * 2 = 400 bytes per point,
2306 * adding some bytes for the necessary overhead.
2308 ins_len = hints->num_points
2309 * (1000 + ((font->deltas_data_head != NULL) ? 400 : 0));
2310 ins_buf = (FT_Byte*)malloc(ins_len);
2311 if (!ins_buf)
2312 return FT_Err_Out_Of_Memory;
2314 /* handle composite glyph */
2315 if (font->loader->gloader->base.num_subglyphs)
2317 bufp = TA_font_build_subglyph_shifter(font, ins_buf);
2318 if (!bufp)
2320 error = FT_Err_Out_Of_Memory;
2321 goto Err;
2324 goto Done1;
2327 /* only scale the glyph if the `none_dflt' style has been used */
2328 if (font->loader->metrics->style_class == &ta_none_dflt_style_class)
2330 /* since `TA_init_recorder' hasn't been called yet, */
2331 /* we manually initialize the `sfnt', `font', and `glyph' fields */
2332 recorder.sfnt = sfnt;
2333 recorder.font = font;
2334 recorder.glyph = glyph;
2336 bufp = TA_sfnt_build_glyph_scaler(sfnt, &recorder, ins_buf);
2337 if (!bufp)
2339 error = FT_Err_Out_Of_Memory;
2340 goto Err;
2343 goto Done1;
2346 error = TA_init_recorder(&recorder, sfnt, font, glyph, hints);
2347 if (error)
2348 goto Err;
2350 /* loop over a large range of pixel sizes */
2351 /* to find hints records which get pushed onto the bytecode stack */
2353 #ifdef DEBUGGING
2354 if (font->debug)
2356 int num_chars, i;
2357 char buf[256];
2360 (void)FT_Get_Glyph_Name(face, idx, buf, 256);
2362 num_chars = fprintf(stderr, "glyph %ld", idx);
2363 if (*buf)
2364 num_chars += fprintf(stderr, " (%s)", buf);
2365 fprintf(stderr, "\n");
2366 for (i = 0; i < num_chars; i++)
2367 putc('=', stderr);
2368 fprintf(stderr, "\n\n");
2371 #endif
2373 /* we temporarily use `ins_buf' to record the current glyph hints */
2374 ta_loader_register_hints_recorder(font->loader,
2375 TA_hints_recorder,
2376 (void*)&recorder);
2378 for (size = font->hinting_range_min;
2379 size <= font->hinting_range_max;
2380 size++)
2382 #ifdef DEBUGGING
2383 int have_dumps = 0;
2384 #endif
2387 TA_rewind_recorder(&recorder, ins_buf, size);
2389 error = FT_Set_Pixel_Sizes(face, size, size);
2390 if (error)
2391 goto Err;
2393 #ifdef DEBUGGING
2394 if (font->debug)
2396 int num_chars, i;
2399 num_chars = fprintf(stderr, "size %d\n", size);
2400 for (i = 0; i < num_chars - 1; i++)
2401 putc('-', stderr);
2402 fprintf(stderr, "\n\n");
2404 #endif
2406 /* calling `ta_loader_load_glyph' uses the */
2407 /* `TA_hints_recorder' function as a callback, */
2408 /* modifying `hints_record' */
2409 error = ta_loader_load_glyph(font, face, idx, load_flags);
2410 if (error)
2411 goto Err;
2413 if (TA_hints_record_is_different(action_hints_records,
2414 num_action_hints_records,
2415 ins_buf, recorder.hints_record.buf))
2417 #ifdef DEBUGGING
2418 if (font->debug)
2420 have_dumps = 1;
2422 ta_glyph_hints_dump_edges((TA_GlyphHints)_ta_debug_hints);
2423 ta_glyph_hints_dump_segments((TA_GlyphHints)_ta_debug_hints);
2424 ta_glyph_hints_dump_points((TA_GlyphHints)_ta_debug_hints);
2426 fprintf(stderr, "action hints record:\n");
2427 if (ins_buf == recorder.hints_record.buf)
2428 fprintf(stderr, " (none)");
2429 else
2431 fprintf(stderr, " ");
2432 for (p = ins_buf; p < recorder.hints_record.buf; p += 2)
2433 fprintf(stderr, " %2d", *p * 256 + *(p + 1));
2435 fprintf(stderr, "\n");
2437 #endif
2439 error = TA_add_hints_record(&action_hints_records,
2440 &num_action_hints_records,
2441 ins_buf, recorder.hints_record);
2442 if (error)
2443 goto Err;
2446 /* now handle point records */
2448 TA_reset_recorder(&recorder, ins_buf);
2450 /* use the point hints data collected in `TA_hints_recorder' */
2451 TA_build_point_hints(&recorder, hints);
2453 if (TA_hints_record_is_different(point_hints_records,
2454 num_point_hints_records,
2455 ins_buf, recorder.hints_record.buf))
2457 #ifdef DEBUGGING
2458 if (font->debug)
2460 if (!have_dumps)
2462 int num_chars, i;
2465 num_chars = fprintf(stderr, "size %d\n", size);
2466 for (i = 0; i < num_chars - 1; i++)
2467 putc('-', stderr);
2468 fprintf(stderr, "\n\n");
2470 ta_glyph_hints_dump_edges((TA_GlyphHints)_ta_debug_hints);
2471 ta_glyph_hints_dump_segments((TA_GlyphHints)_ta_debug_hints);
2472 ta_glyph_hints_dump_points((TA_GlyphHints)_ta_debug_hints);
2475 fprintf(stderr, "point hints record:\n");
2476 if (ins_buf == recorder.hints_record.buf)
2477 fprintf(stderr, " (none)");
2478 else
2480 fprintf(stderr, " ");
2481 for (p = ins_buf; p < recorder.hints_record.buf; p += 2)
2482 fprintf(stderr, " %2d", *p * 256 + *(p + 1));
2484 fprintf(stderr, "\n\n");
2486 #endif
2488 error = TA_add_hints_record(&point_hints_records,
2489 &num_point_hints_records,
2490 ins_buf, recorder.hints_record);
2491 if (error)
2492 goto Err;
2496 if (num_action_hints_records == 1 && !action_hints_records[0].num_actions)
2498 /* since we only have a single empty record we just scale the glyph */
2499 bufp = TA_sfnt_build_glyph_scaler(sfnt, &recorder, ins_buf);
2500 if (!bufp)
2502 error = FT_Err_Out_Of_Memory;
2503 goto Err;
2506 goto Done;
2509 /* if there is only a single record, */
2510 /* we do a global optimization later on */
2511 if (num_action_hints_records > 1)
2512 optimize = 1;
2514 /* store the hints records and handle stack depth */
2515 pos[0] = ins_buf;
2516 bufp = TA_emit_hints_records(&recorder,
2517 point_hints_records,
2518 num_point_hints_records,
2519 ins_buf,
2520 optimize);
2522 num_stack_elements = recorder.num_stack_elements;
2523 recorder.num_stack_elements = 0;
2525 pos[1] = bufp;
2526 bufp = TA_emit_hints_records(&recorder,
2527 action_hints_records,
2528 num_action_hints_records,
2529 bufp,
2530 optimize);
2532 recorder.num_stack_elements += num_stack_elements;
2534 pos[2] = bufp;
2535 bufp = TA_sfnt_build_glyph_segments(sfnt, &recorder, bufp, optimize);
2536 if (!bufp)
2538 error = FT_Err_Out_Of_Memory;
2539 goto Err;
2542 if (num_action_hints_records == 1)
2543 bufp = TA_optimize_push(ins_buf, pos);
2545 Done:
2546 TA_free_hints_records(action_hints_records, num_action_hints_records);
2547 TA_free_hints_records(point_hints_records, num_point_hints_records);
2548 TA_free_recorder(&recorder);
2550 Done1:
2551 /* handle delta exceptions */
2552 if (font->deltas_data_head)
2554 bufp = TA_sfnt_build_delta_exceptions(sfnt, font, idx, bufp);
2555 if (!bufp)
2557 error = FT_Err_Out_Of_Memory;
2558 goto Err;
2562 ins_len = bufp - ins_buf;
2564 if (ins_len > sfnt->max_instructions)
2565 sfnt->max_instructions = ins_len;
2567 glyph->ins_buf = (FT_Byte*)realloc(ins_buf, ins_len);
2568 glyph->ins_len = ins_len;
2570 return FT_Err_Ok;
2572 Err:
2573 TA_free_hints_records(action_hints_records, num_action_hints_records);
2574 TA_free_hints_records(point_hints_records, num_point_hints_records);
2575 TA_free_recorder(&recorder);
2576 free(ins_buf);
2578 return error;
2582 /* end of tabytecode.c */