4 * Copyright (C) 2011-2013 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.
21 #define MISSING (FT_UShort)~0
29 int _ta_debug_disable_horz_hints
;
30 int _ta_debug_disable_vert_hints
;
31 int _ta_debug_disable_blue_hints
;
32 void* _ta_debug_hints
;
36 typedef struct Hints_Record_
44 typedef struct Recorder_
47 GLYPH
* glyph
; /* the current glyph */
48 Hints_Record hints_record
;
50 /* some segments can `wrap around' */
51 /* a contour's start point like 24-25-26-0-1-2 */
52 /* (there can be at most one such segment per contour); */
53 /* later on we append additional records */
54 /* to split them into 24-26 and 0-2 */
55 FT_UShort
* wrap_around_segments
;
56 FT_UShort num_wrap_around_segments
;
58 FT_UShort num_stack_elements
; /* the necessary stack depth so far */
60 /* data necessary for strong point interpolation */
61 FT_UShort
* ip_before_points
;
62 FT_UShort
* ip_after_points
;
63 FT_UShort
* ip_on_point_array
;
64 FT_UShort
* ip_between_point_array
;
66 FT_UShort num_strong_points
;
67 FT_UShort num_segments
;
71 /* this is the bytecode of the `.ttfautohint' glyph */
73 FT_Byte ttfautohint_glyph_bytecode
[7] =
76 /* increment `cvtl_is_subglyph' counter */
89 * convert array `args' into a sequence of NPUSHB, NPUSHW, PUSHB_X, and
90 * PUSHW_X instructions to be stored in `bufp' (the latter two instructions
91 * only if `optimize' is not set); if `need_words' is set, NPUSHW and
96 TA_build_push(FT_Byte
* bufp
,
108 for (i
= 0; i
< num_args
; i
+= 255)
110 nargs
= (num_args
- i
> 255) ? 255 : num_args
- i
;
112 if (optimize
&& nargs
<= 8)
113 BCI(PUSHW_1
- 1 + nargs
);
119 for (j
= 0; j
< nargs
; j
++)
129 for (i
= 0; i
< num_args
; i
+= 255)
131 nargs
= (num_args
- i
> 255) ? 255 : num_args
- i
;
133 if (optimize
&& nargs
<= 8)
134 BCI(PUSHB_1
- 1 + nargs
);
140 for (j
= 0; j
< nargs
; j
++)
152 /* We add a subglyph for each composite glyph. */
153 /* Since subglyphs must contain at least one point, */
154 /* we have to adjust all point indices accordingly. */
155 /* Using the `pointsums' array of the `GLYPH' structure */
156 /* it is straightforward to do that: */
157 /* Assuming that point with index x is in the interval */
158 /* pointsums[n] <= x < pointsums[n + 1], */
159 /* the new point index is x + n. */
162 TA_adjust_point_index(Recorder
* recorder
,
165 FONT
* font
= recorder
->font
;
166 GLYPH
* glyph
= recorder
->glyph
;
170 if (!glyph
->num_components
|| !font
->hint_composites
)
171 return idx
; /* not a composite glyph */
173 for (i
= 0; i
< glyph
->num_pointsums
; i
++)
174 if (idx
< glyph
->pointsums
[i
])
181 /* we store the segments in the storage area; */
182 /* each segment record consists of the first and last point */
185 TA_sfnt_build_glyph_segments(SFNT
* sfnt
,
190 FONT
* font
= recorder
->font
;
191 TA_GlyphHints hints
= &font
->loader
->hints
;
192 TA_AxisHints axis
= &hints
->axis
[TA_DIMENSION_VERT
];
193 TA_Point points
= hints
->points
;
194 TA_Segment segments
= axis
->segments
;
196 TA_Segment seg_limit
;
198 FT_Outline outline
= font
->loader
->gloader
->base
.outline
;
203 FT_UShort num_segments
;
205 FT_Bool need_words
= 0;
209 FT_UShort num_packed_segments
;
210 FT_UShort num_storage
;
211 FT_UShort num_stack_elements
;
212 FT_UShort num_twilight_points
;
215 seg_limit
= segments
+ axis
->num_segments
;
216 num_segments
= axis
->num_segments
;
218 /* to pack the data in the bytecode more tightly, */
219 /* we store up to the first nine segments in nibbles if possible, */
220 /* using delta values */
222 num_packed_segments
= 0;
223 for (seg
= segments
; seg
< seg_limit
; seg
++)
225 FT_UInt first
= seg
->first
- points
;
226 FT_UInt last
= seg
->last
- points
;
229 first
= TA_adjust_point_index(recorder
, first
);
230 last
= TA_adjust_point_index(recorder
, last
);
232 if (first
- base
>= 16)
234 if (first
> last
|| last
- first
>= 16)
236 if (num_packed_segments
== 9)
238 num_packed_segments
++;
242 /* also handle wrap-around segments */
243 num_segments
+= recorder
->num_wrap_around_segments
;
245 /* wrap-around segments are pushed with four arguments; */
246 /* a segment stored in nibbles needs only one byte instead of two */
247 num_args
= num_packed_segments
248 + 2 * (num_segments
- num_packed_segments
)
249 + 2 * recorder
->num_wrap_around_segments
252 /* collect all arguments temporarily in an array (in reverse order) */
253 /* so that we can easily split into chunks of 255 args */
254 /* as needed by NPUSHB and NPUSHW, respectively */
255 args
= (FT_UInt
*)malloc(num_args
* sizeof (FT_UInt
));
259 arg
= args
+ num_args
- 1;
261 if (num_segments
> 0xFF)
264 /* the number of packed segments is indicated by the function number */
265 if (recorder
->glyph
->num_components
&& font
->hint_composites
)
266 *(arg
--) = bci_create_segments_composite_0
+ num_packed_segments
;
268 *(arg
--) = bci_create_segments_0
+ num_packed_segments
;
269 *(arg
--) = num_segments
;
272 for (seg
= segments
; seg
< segments
+ num_packed_segments
; seg
++)
274 FT_UInt first
= seg
->first
- points
;
275 FT_UInt last
= seg
->last
- points
;
280 first
= TA_adjust_point_index(recorder
, first
);
281 last
= TA_adjust_point_index(recorder
, last
);
283 low_nibble
= first
- base
;
284 high_nibble
= last
- first
;
286 *(arg
--) = 16 * high_nibble
+ low_nibble
;
291 for (seg
= segments
+ num_packed_segments
; seg
< seg_limit
; seg
++)
293 FT_UInt first
= seg
->first
- points
;
294 FT_UInt last
= seg
->last
- points
;
297 *(arg
--) = TA_adjust_point_index(recorder
, first
);
298 *(arg
--) = TA_adjust_point_index(recorder
, last
);
300 /* we push the last and first contour point */
301 /* as a third and fourth argument in wrap-around segments */
304 for (n
= 0; n
< outline
.n_contours
; n
++)
306 FT_UInt end
= (FT_UInt
)outline
.contours
[n
];
311 *(arg
--) = TA_adjust_point_index(recorder
, end
);
316 *(arg
--) = TA_adjust_point_index(recorder
, 0);
318 *(arg
--) = TA_adjust_point_index(recorder
,
319 (FT_UInt
)outline
.contours
[n
- 1] + 1);
329 /* emit the second part of wrap-around segments as separate segments */
330 /* so that edges can easily link to them */
331 for (seg
= segments
; seg
< seg_limit
; seg
++)
333 FT_UInt first
= seg
->first
- points
;
334 FT_UInt last
= seg
->last
- points
;
339 for (n
= 0; n
< outline
.n_contours
; n
++)
341 if (first
<= (FT_UInt
)outline
.contours
[n
])
344 *(arg
--) = TA_adjust_point_index(recorder
, 0);
346 *(arg
--) = TA_adjust_point_index(recorder
,
347 (FT_UInt
)outline
.contours
[n
- 1] + 1);
352 *(arg
--) = TA_adjust_point_index(recorder
, last
);
356 /* with most fonts it is very rare */
357 /* that any of the pushed arguments is larger than 0xFF, */
358 /* thus we refrain from further optimizing this case */
359 bufp
= TA_build_push(bufp
, args
, num_args
, need_words
, optimize
);
363 num_storage
= sal_segment_offset
+ num_segments
* 2;
364 if (num_storage
> sfnt
->max_storage
)
365 sfnt
->max_storage
= num_storage
;
367 num_twilight_points
= num_segments
* 2;
368 if (num_twilight_points
> sfnt
->max_twilight_points
)
369 sfnt
->max_twilight_points
= num_twilight_points
;
371 /* both this function and `TA_emit_hints_record' */
372 /* push data onto the stack */
373 num_stack_elements
= ADDITIONAL_STACK_ELEMENTS
374 + recorder
->num_stack_elements
+ num_args
;
375 if (num_stack_elements
> sfnt
->max_stack_elements
)
376 sfnt
->max_stack_elements
= num_stack_elements
;
385 TA_sfnt_build_glyph_scaler(SFNT
* sfnt
,
389 FONT
* font
= recorder
->font
;
390 FT_GlyphSlot glyph
= sfnt
->face
->glyph
;
391 FT_Vector
* points
= glyph
->outline
.points
;
392 FT_Int num_contours
= glyph
->outline
.n_contours
;
398 FT_Bool need_words
= 0;
401 FT_UShort num_stack_elements
;
404 num_args
= 2 * num_contours
+ 2;
406 /* collect all arguments temporarily in an array (in reverse order) */
407 /* so that we can easily split into chunks of 255 args */
408 /* as needed by NPUSHB and NPUSHW, respectively */
409 args
= (FT_UInt
*)malloc(num_args
* sizeof (FT_UInt
));
413 arg
= args
+ num_args
- 1;
418 if (recorder
->glyph
->num_components
&& font
->hint_composites
)
419 *(arg
--) = bci_scale_composite_glyph
;
421 *(arg
--) = bci_scale_glyph
;
422 *(arg
--) = num_contours
;
427 for (p
= 0; p
< num_contours
; p
++)
433 end
= glyph
->outline
.contours
[p
];
435 for (q
= start
; q
<= end
; q
++)
437 if (points
[q
].y
< points
[min
].y
)
439 if (points
[q
].y
> points
[max
].y
)
445 *(arg
--) = TA_adjust_point_index(recorder
, max
);
446 *(arg
--) = TA_adjust_point_index(recorder
, min
);
450 *(arg
--) = TA_adjust_point_index(recorder
, min
);
451 *(arg
--) = TA_adjust_point_index(recorder
, max
);
460 /* with most fonts it is very rare */
461 /* that any of the pushed arguments is larger than 0xFF, */
462 /* thus we refrain from further optimizing this case */
463 bufp
= TA_build_push(bufp
, args
, num_args
, need_words
, 1);
467 num_stack_elements
= ADDITIONAL_STACK_ELEMENTS
+ num_args
;
468 if (num_stack_elements
> sfnt
->max_stack_elements
)
469 sfnt
->max_stack_elements
= num_stack_elements
;
478 TA_font_build_subglyph_shifter(FONT
* font
,
481 FT_Face face
= font
->loader
->face
;
482 FT_GlyphSlot glyph
= face
->glyph
;
484 TA_GlyphLoader gloader
= font
->loader
->gloader
;
486 TA_SubGlyph subglyphs
= gloader
->base
.subglyphs
;
487 TA_SubGlyph subglyph_limit
= subglyphs
+ gloader
->base
.num_subglyphs
;
488 TA_SubGlyph subglyph
;
490 FT_Int curr_contour
= 0;
493 for (subglyph
= subglyphs
; subglyph
< subglyph_limit
; subglyph
++)
497 FT_UShort flags
= subglyph
->flags
;
498 FT_Pos y_offset
= subglyph
->arg2
;
503 /* load subglyph to get the number of contours */
504 error
= FT_Load_Glyph(face
, subglyph
->index
, FT_LOAD_NO_SCALE
);
507 num_contours
= glyph
->outline
.n_contours
;
509 /* nothing to do if there is a point-to-point alignment */
510 if (!(flags
& FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES
))
513 /* nothing to do if y offset is zero */
517 /* nothing to do if there are no contours */
521 /* note that calling `FT_Load_Glyph' without FT_LOAD_NO_RECURSE */
522 /* ensures that composite subglyphs are represented as simple glyphs */
524 if (num_contours
> 0xFF
525 || curr_contour
> 0xFF)
528 BCI(HIGH(curr_contour
));
529 BCI(LOW(curr_contour
));
530 BCI(HIGH(num_contours
));
531 BCI(LOW(num_contours
));
540 /* there are high chances that this value needs PUSHW, */
541 /* thus we handle it separately */
542 if (y_offset
> 0xFF || y_offset
< 0)
555 BCI(bci_shift_subglyph
);
559 curr_contour
+= num_contours
;
567 * The four `ta_ip_*' actions in the `TA_hints_recorder' callback store its
568 * data in four arrays (which are simple but waste a lot of memory). The
569 * function below converts them into bytecode.
571 * For `ta_ip_before' and `ta_ip_after', the collected points are emitted
572 * together with the edge they correspond to.
574 * For both `ta_ip_on' and `ta_ip_between', an outer loop is constructed to
575 * loop over the edge or edge pairs, respectively, and each edge or edge
576 * pair contains an inner loop to emit the correponding points.
580 TA_build_point_hints(Recorder
* recorder
,
583 TA_AxisHints axis
= &hints
->axis
[TA_DIMENSION_VERT
];
584 TA_Segment segments
= axis
->segments
;
585 TA_Edge edges
= axis
->edges
;
589 FT_Byte
* p
= recorder
->hints_record
.buf
;
590 FT_UShort num_edges
= axis
->num_edges
;
591 FT_UShort num_strong_points
= recorder
->num_strong_points
;
605 /* we store everything as 16bit numbers; */
606 /* the function numbers (`ta_ip_before', etc.) */
607 /* reflect the order in the TA_Action enumeration */
609 /* ip_before_points */
612 ip
= recorder
->ip_before_points
;
613 ip_limit
= ip
+ num_strong_points
;
614 for (; ip
< ip_limit
; ip
++)
624 recorder
->hints_record
.num_actions
++;
629 *(p
++) = (FT_Byte
)ta_ip_before
+ ACTION_OFFSET
;
630 *(p
++) = HIGH(edge
->first
- segments
);
631 *(p
++) = LOW(edge
->first
- segments
);
635 ip
= recorder
->ip_before_points
;
637 for (; ip
< ip_limit
; ip
++)
639 FT_UInt point
= TA_adjust_point_index(recorder
, *ip
);
642 *(p
++) = HIGH(point
);
647 /* ip_after_points */
650 ip
= recorder
->ip_after_points
;
651 ip_limit
= ip
+ num_strong_points
;
652 for (; ip
< ip_limit
; ip
++)
662 recorder
->hints_record
.num_actions
++;
664 edge
= edges
+ axis
->num_edges
- 1;
667 *(p
++) = (FT_Byte
)ta_ip_after
+ ACTION_OFFSET
;
668 *(p
++) = HIGH(edge
->first
- segments
);
669 *(p
++) = LOW(edge
->first
- segments
);
673 ip
= recorder
->ip_after_points
;
675 for (; ip
< ip_limit
; ip
++)
677 FT_UInt point
= TA_adjust_point_index(recorder
, *ip
);
680 *(p
++) = HIGH(point
);
685 /* ip_on_point_array */
688 ip
= recorder
->ip_on_point_array
;
689 ip_limit
= ip
+ num_edges
* num_strong_points
;
690 for (; ip
< ip_limit
; ip
+= num_strong_points
)
696 recorder
->hints_record
.num_actions
++;
699 *(p
++) = (FT_Byte
)ta_ip_on
+ ACTION_OFFSET
;
704 ip
= recorder
->ip_on_point_array
;
705 ip_limit
= ip
+ num_edges
* num_strong_points
;
706 for (; ip
< ip_limit
; ip
+= num_strong_points
, i
++)
713 *(p
++) = HIGH(edge
->first
- segments
);
714 *(p
++) = LOW(edge
->first
- segments
);
718 iq_limit
= iq
+ num_strong_points
;
719 for (; iq
< iq_limit
; iq
++)
732 for (; iq
< iq_limit
; iq
++)
734 FT_UInt point
= TA_adjust_point_index(recorder
, *iq
);
737 *(p
++) = HIGH(point
);
743 /* ip_between_point_array */
746 ip
= recorder
->ip_between_point_array
;
747 ip_limit
= ip
+ num_edges
* num_edges
* num_strong_points
;
748 for (; ip
< ip_limit
; ip
+= num_strong_points
)
754 recorder
->hints_record
.num_actions
++;
757 *(p
++) = (FT_Byte
)ta_ip_between
+ ACTION_OFFSET
;
762 ip
= recorder
->ip_between_point_array
;
763 ip_limit
= ip
+ num_edges
* num_edges
* num_strong_points
;
766 ip
+= num_edges
* num_strong_points
, i
++)
776 iq_limit
= iq
+ num_edges
* num_strong_points
;
777 for (; iq
< iq_limit
; iq
+= num_strong_points
, j
++)
784 *(p
++) = HIGH(after
->first
- segments
);
785 *(p
++) = LOW(after
->first
- segments
);
786 *(p
++) = HIGH(before
->first
- segments
);
787 *(p
++) = LOW(before
->first
- segments
);
791 ir_limit
= ir
+ num_strong_points
;
792 for (; ir
< ir_limit
; ir
++)
805 for (; ir
< ir_limit
; ir
++)
807 FT_UInt point
= TA_adjust_point_index(recorder
, *ir
);
810 *(p
++) = HIGH(point
);
817 recorder
->hints_record
.buf
= p
;
822 TA_hints_record_is_different(Hints_Record
* hints_records
,
823 FT_UInt num_hints_records
,
827 Hints_Record last_hints_record
;
833 /* we only need to compare with the last hints record */
834 last_hints_record
= hints_records
[num_hints_records
- 1];
836 if ((FT_UInt
)(end
- start
) != last_hints_record
.buf_len
)
839 if (memcmp(start
, last_hints_record
.buf
, last_hints_record
.buf_len
))
847 TA_add_hints_record(Hints_Record
** hints_records
,
848 FT_UInt
* num_hints_records
,
850 Hints_Record hints_record
)
852 Hints_Record
* hints_records_new
;
854 /* at this point, `hints_record.buf' still points into `ins_buf' */
855 FT_Byte
* end
= hints_record
.buf
;
858 buf_len
= (FT_UInt
)(end
- start
);
860 /* now fill the structure completely */
861 hints_record
.buf_len
= buf_len
;
862 hints_record
.buf
= (FT_Byte
*)malloc(buf_len
);
863 if (!hints_record
.buf
)
864 return FT_Err_Out_Of_Memory
;
866 memcpy(hints_record
.buf
, start
, buf_len
);
868 (*num_hints_records
)++;
870 (Hints_Record
*)realloc(*hints_records
, *num_hints_records
871 * sizeof (Hints_Record
));
872 if (!hints_records_new
)
874 free(hints_record
.buf
);
875 (*num_hints_records
)--;
876 return FT_Err_Out_Of_Memory
;
879 *hints_records
= hints_records_new
;
881 (*hints_records
)[*num_hints_records
- 1] = hints_record
;
888 TA_emit_hints_record(Recorder
* recorder
,
889 Hints_Record
* hints_record
,
895 FT_Bool need_words
= 0;
898 FT_UInt num_arguments
;
902 /* check whether any argument is larger than 0xFF */
903 endp
= hints_record
->buf
+ hints_record
->buf_len
;
904 for (p
= hints_record
->buf
; p
< endp
; p
+= 2)
911 /* with most fonts it is very rare */
912 /* that any of the pushed arguments is larger than 0xFF, */
913 /* thus we refrain from further optimizing this case */
915 num_arguments
= hints_record
->buf_len
/ 2;
920 for (i
= 0; i
< num_arguments
; i
+= 255)
922 num_args
= (num_arguments
- i
> 255) ? 255 : (num_arguments
- i
);
924 if (optimize
&& num_args
<= 8)
925 BCI(PUSHW_1
- 1 + num_args
);
931 for (j
= 0; j
< num_args
; j
++)
941 /* we only need the lower bytes */
944 for (i
= 0; i
< num_arguments
; i
+= 255)
946 num_args
= (num_arguments
- i
> 255) ? 255 : (num_arguments
- i
);
948 if (optimize
&& num_args
<= 8)
949 BCI(PUSHB_1
- 1 + num_args
);
955 for (j
= 0; j
< num_args
; j
++)
963 /* collect stack depth data */
964 if (num_arguments
> recorder
->num_stack_elements
)
965 recorder
->num_stack_elements
= num_arguments
;
972 TA_emit_hints_records(Recorder
* recorder
,
973 Hints_Record
* hints_records
,
974 FT_UInt num_hints_records
,
979 Hints_Record
* hints_record
;
982 hints_record
= hints_records
;
984 /* emit hints records in `if' clauses, */
985 /* with the ppem size as the condition */
986 for (i
= 0; i
< num_hints_records
- 1; i
++)
989 if (hints_record
->size
> 0xFF)
992 BCI(HIGH((hints_record
+ 1)->size
));
993 BCI(LOW((hints_record
+ 1)->size
));
998 BCI((hints_record
+ 1)->size
);
1002 bufp
= TA_emit_hints_record(recorder
, hints_record
, bufp
, optimize
);
1008 bufp
= TA_emit_hints_record(recorder
, hints_record
, bufp
, optimize
);
1010 for (i
= 0; i
< num_hints_records
- 1; i
++)
1018 TA_free_hints_records(Hints_Record
* hints_records
,
1019 FT_UInt num_hints_records
)
1024 for (i
= 0; i
< num_hints_records
; i
++)
1025 free(hints_records
[i
].buf
);
1027 free(hints_records
);
1032 TA_hints_recorder_handle_segments(FT_Byte
* bufp
,
1037 TA_Segment segments
= axis
->segments
;
1040 FT_UShort num_segs
= 0;
1044 seg_idx
= edge
->first
- segments
;
1046 /* we store everything as 16bit numbers */
1047 *(bufp
++) = HIGH(seg_idx
);
1048 *(bufp
++) = LOW(seg_idx
);
1050 /* wrap-around segments are stored as two segments */
1051 if (edge
->first
->first
> edge
->first
->last
)
1054 seg
= edge
->first
->edge_next
;
1055 while (seg
!= edge
->first
)
1059 if (seg
->first
> seg
->last
)
1062 seg
= seg
->edge_next
;
1065 *(bufp
++) = HIGH(num_segs
);
1066 *(bufp
++) = LOW(num_segs
);
1068 if (edge
->first
->first
> edge
->first
->last
)
1070 /* emit second part of wrap-around segment; */
1071 /* the bytecode positions such segments after `normal' ones */
1075 if (seg_idx
== *wrap
)
1080 *(bufp
++) = HIGH(axis
->num_segments
+ (wrap
- wraps
));
1081 *(bufp
++) = LOW(axis
->num_segments
+ (wrap
- wraps
));
1084 seg
= edge
->first
->edge_next
;
1085 while (seg
!= edge
->first
)
1087 seg_idx
= seg
- segments
;
1089 *(bufp
++) = HIGH(seg_idx
);
1090 *(bufp
++) = LOW(seg_idx
);
1092 if (seg
->first
> seg
->last
)
1097 if (seg_idx
== *wrap
)
1102 *(bufp
++) = HIGH(axis
->num_segments
+ (wrap
- wraps
));
1103 *(bufp
++) = LOW(axis
->num_segments
+ (wrap
- wraps
));
1106 seg
= seg
->edge_next
;
1114 TA_hints_recorder(TA_Action action
,
1115 TA_GlyphHints hints
,
1120 TA_Edge lower_bound
,
1121 TA_Edge upper_bound
)
1123 TA_AxisHints axis
= &hints
->axis
[dim
];
1124 TA_Edge edges
= axis
->edges
;
1125 TA_Segment segments
= axis
->segments
;
1126 TA_Point points
= hints
->points
;
1128 Recorder
* recorder
= (Recorder
*)hints
->user
;
1129 FONT
* font
= recorder
->font
;
1130 FT_UShort
* wraps
= recorder
->wrap_around_segments
;
1131 FT_Byte
* p
= recorder
->hints_record
.buf
;
1137 if (dim
== TA_DIMENSION_HORZ
)
1140 /* we collect point hints for later processing */
1145 TA_Point point
= (TA_Point
)arg1
;
1148 ip
= recorder
->ip_before_points
;
1149 limit
= ip
+ recorder
->num_strong_points
;
1150 for (; ip
< limit
; ip
++)
1154 *ip
= point
- points
;
1163 TA_Point point
= (TA_Point
)arg1
;
1166 ip
= recorder
->ip_after_points
;
1167 limit
= ip
+ recorder
->num_strong_points
;
1168 for (; ip
< limit
; ip
++)
1172 *ip
= point
- points
;
1181 TA_Point point
= (TA_Point
)arg1
;
1182 TA_Edge edge
= arg2
;
1185 ip
= recorder
->ip_on_point_array
1186 + recorder
->num_strong_points
1188 limit
= ip
+ recorder
->num_strong_points
;
1189 for (; ip
< limit
; ip
++)
1193 *ip
= point
- points
;
1202 TA_Point point
= (TA_Point
)arg1
;
1203 TA_Edge before
= arg2
;
1204 TA_Edge after
= arg3
;
1207 /* note that `recorder->num_segments' has been used for allocation, */
1208 /* but `axis->num_edges' is used for accessing this array */
1209 ip
= recorder
->ip_between_point_array
1210 + recorder
->num_strong_points
* axis
->num_edges
1212 + recorder
->num_strong_points
1214 limit
= ip
+ recorder
->num_strong_points
;
1215 for (; ip
< limit
; ip
++)
1219 *ip
= point
- points
;
1227 /* we ignore the BOUND action since we signal this information */
1228 /* with the proper function number */
1235 /* some enum values correspond to four or eight bytecode functions; */
1236 /* if the value is n, the function numbers are n, ..., n+7, */
1237 /* to be differentiated with flags */
1243 TA_Edge base_edge
= (TA_Edge
)arg1
;
1244 TA_Edge stem_edge
= arg2
;
1248 *(p
++) = (FT_Byte
)action
+ ACTION_OFFSET
1249 + ((stem_edge
->flags
& TA_EDGE_SERIF
) != 0)
1250 + 2 * ((base_edge
->flags
& TA_EDGE_ROUND
) != 0);
1252 *(p
++) = HIGH(base_edge
->first
- segments
);
1253 *(p
++) = LOW(base_edge
->first
- segments
);
1254 *(p
++) = HIGH(stem_edge
->first
- segments
);
1255 *(p
++) = LOW(stem_edge
->first
- segments
);
1257 p
= TA_hints_recorder_handle_segments(p
, axis
, stem_edge
, wraps
);
1263 TA_Edge edge
= (TA_Edge
)arg1
;
1264 TA_Edge edge2
= arg2
;
1268 *(p
++) = (FT_Byte
)action
+ ACTION_OFFSET
1269 + ((edge2
->flags
& TA_EDGE_SERIF
) != 0)
1270 + 2 * ((edge
->flags
& TA_EDGE_ROUND
) != 0);
1272 *(p
++) = HIGH(edge
->first
- segments
);
1273 *(p
++) = LOW(edge
->first
- segments
);
1274 *(p
++) = HIGH(edge2
->first
- segments
);
1275 *(p
++) = LOW(edge2
->first
- segments
);
1277 p
= TA_hints_recorder_handle_segments(p
, axis
, edge
, wraps
);
1283 TA_Edge edge
= (TA_Edge
)arg1
;
1284 TA_Edge edge2
= arg2
;
1285 TA_Edge edge_minus_one
= lower_bound
;
1289 *(p
++) = (FT_Byte
)action
+ ACTION_OFFSET
1290 + ((edge2
->flags
& TA_EDGE_SERIF
) != 0)
1291 + 2 * ((edge
->flags
& TA_EDGE_ROUND
) != 0)
1292 + 4 * (edge_minus_one
!= NULL
);
1294 *(p
++) = HIGH(edge
->first
- segments
);
1295 *(p
++) = LOW(edge
->first
- segments
);
1296 *(p
++) = HIGH(edge2
->first
- segments
);
1297 *(p
++) = LOW(edge2
->first
- segments
);
1301 *(p
++) = HIGH(edge_minus_one
->first
- segments
);
1302 *(p
++) = LOW(edge_minus_one
->first
- segments
);
1305 p
= TA_hints_recorder_handle_segments(p
, axis
, edge
, wraps
);
1309 case ta_blue_anchor
:
1311 TA_Edge edge
= (TA_Edge
)arg1
;
1312 TA_Edge blue
= arg2
;
1316 *(p
++) = (FT_Byte
)action
+ ACTION_OFFSET
;
1318 *(p
++) = HIGH(blue
->first
- segments
);
1319 *(p
++) = LOW(blue
->first
- segments
);
1321 if (edge
->best_blue_is_shoot
)
1323 *(p
++) = HIGH(CVT_BLUE_SHOOTS_OFFSET
+ edge
->best_blue_idx
);
1324 *(p
++) = LOW(CVT_BLUE_SHOOTS_OFFSET
+ edge
->best_blue_idx
);
1328 *(p
++) = HIGH(CVT_BLUE_REFS_OFFSET
+ edge
->best_blue_idx
);
1329 *(p
++) = LOW(CVT_BLUE_REFS_OFFSET
+ edge
->best_blue_idx
);
1332 *(p
++) = HIGH(edge
->first
- segments
);
1333 *(p
++) = LOW(edge
->first
- segments
);
1335 p
= TA_hints_recorder_handle_segments(p
, axis
, edge
, wraps
);
1341 TA_Edge edge
= (TA_Edge
)arg1
;
1342 TA_Edge edge2
= arg2
;
1343 TA_Edge edge_minus_one
= lower_bound
;
1347 *(p
++) = (FT_Byte
)action
+ ACTION_OFFSET
1348 + ((edge2
->flags
& TA_EDGE_SERIF
) != 0)
1349 + 2 * ((edge
->flags
& TA_EDGE_ROUND
) != 0)
1350 + 4 * (edge_minus_one
!= NULL
);
1352 *(p
++) = HIGH(edge
->first
- segments
);
1353 *(p
++) = LOW(edge
->first
- segments
);
1354 *(p
++) = HIGH(edge2
->first
- segments
);
1355 *(p
++) = LOW(edge2
->first
- segments
);
1359 *(p
++) = HIGH(edge_minus_one
->first
- segments
);
1360 *(p
++) = LOW(edge_minus_one
->first
- segments
);
1363 p
= TA_hints_recorder_handle_segments(p
, axis
, edge
, wraps
);
1364 p
= TA_hints_recorder_handle_segments(p
, axis
, edge2
, wraps
);
1370 TA_Edge edge
= (TA_Edge
)arg1
;
1374 *(p
++) = (FT_Byte
)action
+ ACTION_OFFSET
;
1376 if (edge
->best_blue_is_shoot
)
1378 *(p
++) = HIGH(CVT_BLUE_SHOOTS_OFFSET
+ edge
->best_blue_idx
);
1379 *(p
++) = LOW(CVT_BLUE_SHOOTS_OFFSET
+ edge
->best_blue_idx
);
1383 *(p
++) = HIGH(CVT_BLUE_REFS_OFFSET
+ edge
->best_blue_idx
);
1384 *(p
++) = LOW(CVT_BLUE_REFS_OFFSET
+ edge
->best_blue_idx
);
1387 *(p
++) = HIGH(edge
->first
- segments
);
1388 *(p
++) = LOW(edge
->first
- segments
);
1390 p
= TA_hints_recorder_handle_segments(p
, axis
, edge
, wraps
);
1396 TA_Edge serif
= (TA_Edge
)arg1
;
1397 TA_Edge base
= serif
->serif
;
1401 *(p
++) = (FT_Byte
)action
+ ACTION_OFFSET
1402 + (lower_bound
!= NULL
)
1403 + 2 * (upper_bound
!= NULL
);
1405 *(p
++) = HIGH(serif
->first
- segments
);
1406 *(p
++) = LOW(serif
->first
- segments
);
1407 *(p
++) = HIGH(base
->first
- segments
);
1408 *(p
++) = LOW(base
->first
- segments
);
1412 *(p
++) = HIGH(lower_bound
->first
- segments
);
1413 *(p
++) = LOW(lower_bound
->first
- segments
);
1417 *(p
++) = HIGH(upper_bound
->first
- segments
);
1418 *(p
++) = LOW(upper_bound
->first
- segments
);
1421 p
= TA_hints_recorder_handle_segments(p
, axis
, serif
, wraps
);
1425 case ta_serif_anchor
:
1426 case ta_serif_link2
:
1428 TA_Edge edge
= (TA_Edge
)arg1
;
1432 *(p
++) = (FT_Byte
)action
+ ACTION_OFFSET
1433 + (lower_bound
!= NULL
)
1434 + 2 * (upper_bound
!= NULL
);
1436 *(p
++) = HIGH(edge
->first
- segments
);
1437 *(p
++) = LOW(edge
->first
- segments
);
1441 *(p
++) = HIGH(lower_bound
->first
- segments
);
1442 *(p
++) = LOW(lower_bound
->first
- segments
);
1446 *(p
++) = HIGH(upper_bound
->first
- segments
);
1447 *(p
++) = LOW(upper_bound
->first
- segments
);
1450 p
= TA_hints_recorder_handle_segments(p
, axis
, edge
, wraps
);
1454 case ta_serif_link1
:
1456 TA_Edge edge
= (TA_Edge
)arg1
;
1457 TA_Edge before
= arg2
;
1458 TA_Edge after
= arg3
;
1462 *(p
++) = (FT_Byte
)action
+ ACTION_OFFSET
1463 + (lower_bound
!= NULL
)
1464 + 2 * (upper_bound
!= NULL
);
1466 *(p
++) = HIGH(before
->first
- segments
);
1467 *(p
++) = LOW(before
->first
- segments
);
1468 *(p
++) = HIGH(edge
->first
- segments
);
1469 *(p
++) = LOW(edge
->first
- segments
);
1470 *(p
++) = HIGH(after
->first
- segments
);
1471 *(p
++) = LOW(after
->first
- segments
);
1475 *(p
++) = HIGH(lower_bound
->first
- segments
);
1476 *(p
++) = LOW(lower_bound
->first
- segments
);
1480 *(p
++) = HIGH(upper_bound
->first
- segments
);
1481 *(p
++) = LOW(upper_bound
->first
- segments
);
1484 p
= TA_hints_recorder_handle_segments(p
, axis
, edge
, wraps
);
1489 /* there are more cases in the enumeration */
1490 /* which are handled with flags */
1494 recorder
->hints_record
.num_actions
++;
1495 recorder
->hints_record
.buf
= p
;
1500 TA_init_recorder(Recorder
* recorder
,
1503 TA_GlyphHints hints
)
1505 TA_AxisHints axis
= &hints
->axis
[TA_DIMENSION_VERT
];
1506 TA_Point points
= hints
->points
;
1507 TA_Point point_limit
= points
+ hints
->num_points
;
1510 TA_Segment segments
= axis
->segments
;
1511 TA_Segment seg_limit
= segments
+ axis
->num_segments
;
1514 FT_UShort num_strong_points
= 0;
1515 FT_UShort
* wrap_around_segment
;
1517 recorder
->font
= font
;
1518 recorder
->glyph
= glyph
;
1519 recorder
->num_segments
= axis
->num_segments
;
1521 recorder
->ip_before_points
= NULL
;
1522 recorder
->ip_after_points
= NULL
;
1523 recorder
->ip_on_point_array
= NULL
;
1524 recorder
->ip_between_point_array
= NULL
;
1526 recorder
->num_stack_elements
= 0;
1528 /* no need to clean up allocated arrays in case of error; */
1529 /* this is handled later by `TA_free_recorder' */
1531 recorder
->num_wrap_around_segments
= 0;
1532 for (seg
= segments
; seg
< seg_limit
; seg
++)
1533 if (seg
->first
> seg
->last
)
1534 recorder
->num_wrap_around_segments
++;
1536 recorder
->wrap_around_segments
=
1537 (FT_UShort
*)malloc(recorder
->num_wrap_around_segments
1538 * sizeof (FT_UShort
));
1539 if (!recorder
->wrap_around_segments
)
1540 return FT_Err_Out_Of_Memory
;
1542 wrap_around_segment
= recorder
->wrap_around_segments
;
1543 for (seg
= segments
; seg
< seg_limit
; seg
++)
1544 if (seg
->first
> seg
->last
)
1545 *(wrap_around_segment
++) = seg
- segments
;
1547 /* get number of strong points */
1548 for (point
= points
; point
< point_limit
; point
++)
1550 /* actually, we need to test `TA_FLAG_TOUCH_Y' also; */
1551 /* however, this value isn't known yet */
1552 /* (or rather, it can vary between different pixel sizes) */
1553 if (point
->flags
& TA_FLAG_WEAK_INTERPOLATION
)
1556 num_strong_points
++;
1559 recorder
->num_strong_points
= num_strong_points
;
1561 recorder
->ip_before_points
=
1562 (FT_UShort
*)malloc(num_strong_points
* sizeof (FT_UShort
));
1563 if (!recorder
->ip_before_points
)
1564 return FT_Err_Out_Of_Memory
;
1566 recorder
->ip_after_points
=
1567 (FT_UShort
*)malloc(num_strong_points
* sizeof (FT_UShort
));
1568 if (!recorder
->ip_after_points
)
1569 return FT_Err_Out_Of_Memory
;
1571 /* actually, we need `hints->num_edges' for the array sizes; */
1572 /* however, this value isn't known yet */
1573 /* (or rather, it can vary between different pixel sizes) */
1574 recorder
->ip_on_point_array
=
1575 (FT_UShort
*)malloc(axis
->num_segments
1576 * num_strong_points
* sizeof (FT_UShort
));
1577 if (!recorder
->ip_on_point_array
)
1578 return FT_Err_Out_Of_Memory
;
1580 recorder
->ip_between_point_array
=
1581 (FT_UShort
*)malloc(axis
->num_segments
* axis
->num_segments
1582 * num_strong_points
* sizeof (FT_UShort
));
1583 if (!recorder
->ip_between_point_array
)
1584 return FT_Err_Out_Of_Memory
;
1591 TA_reset_recorder(Recorder
* recorder
,
1594 recorder
->hints_record
.buf
= bufp
;
1595 recorder
->hints_record
.num_actions
= 0;
1600 TA_rewind_recorder(Recorder
* recorder
,
1604 TA_reset_recorder(recorder
, bufp
);
1606 recorder
->hints_record
.size
= size
;
1608 /* We later check with MISSING (which expands to 0xFF bytes) */
1610 memset(recorder
->ip_before_points
, 0xFF,
1611 recorder
->num_strong_points
* sizeof (FT_UShort
));
1612 memset(recorder
->ip_after_points
, 0xFF,
1613 recorder
->num_strong_points
* sizeof (FT_UShort
));
1615 memset(recorder
->ip_on_point_array
, 0xFF,
1616 recorder
->num_segments
1617 * recorder
->num_strong_points
* sizeof (FT_UShort
));
1618 memset(recorder
->ip_between_point_array
, 0xFF,
1619 recorder
->num_segments
* recorder
->num_segments
1620 * recorder
->num_strong_points
* sizeof (FT_UShort
));
1625 TA_free_recorder(Recorder
* recorder
)
1627 free(recorder
->wrap_around_segments
);
1629 free(recorder
->ip_before_points
);
1630 free(recorder
->ip_after_points
);
1631 free(recorder
->ip_on_point_array
);
1632 free(recorder
->ip_between_point_array
);
1637 TA_sfnt_build_glyph_instructions(SFNT
* sfnt
,
1641 FT_Face face
= sfnt
->face
;
1649 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
1650 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
1651 /* `idx' is never negative */
1652 GLYPH
* glyph
= &data
->glyphs
[idx
];
1654 TA_GlyphHints hints
;
1656 FT_UInt num_action_hints_records
= 0;
1657 FT_UInt num_point_hints_records
= 0;
1658 Hints_Record
* action_hints_records
= NULL
;
1659 Hints_Record
* point_hints_records
= NULL
;
1662 FT_UShort num_stack_elements
;
1663 FT_Bool optimize
= 0;
1665 FT_Int32 load_flags
;
1675 /* XXX: right now, we abuse this flag to control */
1676 /* the global behaviour of the auto-hinter */
1677 load_flags
= 1 << 29; /* vertical hinting only */
1678 if (!font
->pre_hinting
)
1680 if (font
->hint_composites
)
1681 load_flags
|= FT_LOAD_NO_SCALE
;
1683 load_flags
|= FT_LOAD_NO_RECURSE
;
1686 /* computing the segments is resolution independent, */
1687 /* thus the pixel size in this call is arbitrary */
1688 error
= FT_Set_Pixel_Sizes(face
, 20, 20);
1693 /* temporarily disable debugging output */
1694 /* to avoid getting the information twice */
1695 _ta_debug_save
= _ta_debug
;
1699 ta_loader_register_hints_recorder(font
->loader
, NULL
, NULL
);
1700 error
= ta_loader_load_glyph(font
, face
, (FT_UInt
)idx
, load_flags
);
1703 _ta_debug
= _ta_debug_save
;
1709 /* do nothing if we have an empty glyph */
1710 if (!face
->glyph
->outline
.n_contours
)
1713 hints
= &font
->loader
->hints
;
1715 /* do nothing if the setup delivered the `dflt' script only */
1716 if (!hints
->num_points
)
1719 /* we allocate a buffer which is certainly large enough */
1720 /* to hold all of the created bytecode instructions; */
1721 /* later on it gets reallocated to its real size */
1722 ins_len
= hints
->num_points
* 1000;
1723 ins_buf
= (FT_Byte
*)malloc(ins_len
);
1725 return FT_Err_Out_Of_Memory
;
1727 /* initialize array with an invalid bytecode */
1728 /* so that we can easily find the array length at reallocation time */
1729 memset(ins_buf
, INS_A0
, ins_len
);
1731 /* handle composite glyph */
1732 if (font
->loader
->gloader
->base
.num_subglyphs
)
1734 bufp
= TA_font_build_subglyph_shifter(font
, ins_buf
);
1737 error
= FT_Err_Out_Of_Memory
;
1744 /* only scale the glyph if the `dflt' script has been used */
1745 if (font
->loader
->metrics
->script_class
== &ta_dflt_script_class
)
1747 /* since `TA_init_recorder' hasn't been called yet, */
1748 /* we manually initialize the `font' and `glyph' fields */
1749 recorder
.font
= font
;
1750 recorder
.glyph
= glyph
;
1752 bufp
= TA_sfnt_build_glyph_scaler(sfnt
, &recorder
, ins_buf
);
1755 error
= FT_Err_Out_Of_Memory
;
1762 error
= TA_init_recorder(&recorder
, font
, glyph
, hints
);
1766 /* loop over a large range of pixel sizes */
1767 /* to find hints records which get pushed onto the bytecode stack */
1776 (void)FT_Get_Glyph_Name(face
, idx
, buf
, 256);
1778 num_chars
= fprintf(stderr
, "glyph %ld", idx
);
1780 num_chars
+= fprintf(stderr
, " (%s)", buf
);
1781 fprintf(stderr
, "\n");
1782 for (i
= 0; i
< num_chars
; i
++)
1784 fprintf(stderr
, "\n\n");
1789 /* we temporarily use `ins_buf' to record the current glyph hints */
1790 ta_loader_register_hints_recorder(font
->loader
,
1794 for (size
= font
->hinting_range_min
;
1795 size
<= font
->hinting_range_max
;
1803 TA_rewind_recorder(&recorder
, ins_buf
, size
);
1805 error
= FT_Set_Pixel_Sizes(face
, size
, size
);
1815 num_chars
= fprintf(stderr
, "size %d\n", size
);
1816 for (i
= 0; i
< num_chars
- 1; i
++)
1818 fprintf(stderr
, "\n\n");
1822 /* calling `ta_loader_load_glyph' uses the */
1823 /* `TA_hints_recorder' function as a callback, */
1824 /* modifying `hints_record' */
1825 error
= ta_loader_load_glyph(font
, face
, idx
, load_flags
);
1829 if (TA_hints_record_is_different(action_hints_records
,
1830 num_action_hints_records
,
1831 ins_buf
, recorder
.hints_record
.buf
))
1838 ta_glyph_hints_dump_edges(_ta_debug_hints
);
1839 ta_glyph_hints_dump_segments(_ta_debug_hints
);
1840 ta_glyph_hints_dump_points(_ta_debug_hints
);
1842 fprintf(stderr
, "action hints record:\n");
1843 if (ins_buf
== recorder
.hints_record
.buf
)
1844 fprintf(stderr
, " (none)");
1847 fprintf(stderr
, " ");
1848 for (p
= ins_buf
; p
< recorder
.hints_record
.buf
; p
+= 2)
1849 fprintf(stderr
, " %2d", *p
* 256 + *(p
+ 1));
1851 fprintf(stderr
, "\n");
1855 error
= TA_add_hints_record(&action_hints_records
,
1856 &num_action_hints_records
,
1857 ins_buf
, recorder
.hints_record
);
1862 /* now handle point records */
1864 TA_reset_recorder(&recorder
, ins_buf
);
1866 /* use the point hints data collected in `TA_hints_recorder' */
1867 TA_build_point_hints(&recorder
, hints
);
1869 if (TA_hints_record_is_different(point_hints_records
,
1870 num_point_hints_records
,
1871 ins_buf
, recorder
.hints_record
.buf
))
1881 num_chars
= fprintf(stderr
, "size %d\n", size
);
1882 for (i
= 0; i
< num_chars
- 1; i
++)
1884 fprintf(stderr
, "\n\n");
1886 ta_glyph_hints_dump_edges(_ta_debug_hints
);
1887 ta_glyph_hints_dump_segments(_ta_debug_hints
);
1888 ta_glyph_hints_dump_points(_ta_debug_hints
);
1891 fprintf(stderr
, "point hints record:\n");
1892 if (ins_buf
== recorder
.hints_record
.buf
)
1893 fprintf(stderr
, " (none)");
1896 fprintf(stderr
, " ");
1897 for (p
= ins_buf
; p
< recorder
.hints_record
.buf
; p
+= 2)
1898 fprintf(stderr
, " %2d", *p
* 256 + *(p
+ 1));
1900 fprintf(stderr
, "\n\n");
1904 error
= TA_add_hints_record(&point_hints_records
,
1905 &num_point_hints_records
,
1906 ins_buf
, recorder
.hints_record
);
1912 if (num_action_hints_records
== 1 && !action_hints_records
[0].num_actions
)
1914 /* since we only have a single empty record we just scale the glyph */
1915 bufp
= TA_sfnt_build_glyph_scaler(sfnt
, &recorder
, ins_buf
);
1918 error
= FT_Err_Out_Of_Memory
;
1922 /* clear the rest of the temporarily used part of `ins_buf' */
1924 while (*p
!= INS_A0
)
1930 /* if there is only a single record, */
1931 /* we do a global optimization later on */
1932 if (num_action_hints_records
> 1)
1935 /* store the hints records and handle stack depth */
1937 bufp
= TA_emit_hints_records(&recorder
,
1938 point_hints_records
,
1939 num_point_hints_records
,
1943 num_stack_elements
= recorder
.num_stack_elements
;
1944 recorder
.num_stack_elements
= 0;
1947 bufp
= TA_emit_hints_records(&recorder
,
1948 action_hints_records
,
1949 num_action_hints_records
,
1953 recorder
.num_stack_elements
+= num_stack_elements
;
1956 bufp
= TA_sfnt_build_glyph_segments(sfnt
, &recorder
, bufp
, optimize
);
1959 error
= FT_Err_Out_Of_Memory
;
1963 /* XXX improve handling of NPUSHW */
1964 if (num_action_hints_records
== 1
1965 && *(pos
[0]) != NPUSHW
&& *(pos
[1]) != NPUSHW
&& *(pos
[2]) != NPUSHW
)
1968 * we optimize two common cases, replacing
1970 * NPUSHB A ... NPUSHB B [... NPUSHB C] ... CALL
1974 * NPUSHB (A+B[+C]) ... CALL
1987 /* the point hints records block can be missing */
1988 if (pos
[0] == pos
[1])
1994 /* there are at least two NPUSHB instructions */
1995 /* (one of them directly at the start) */
1996 sizes
[0] = *(pos
[0] + 1);
1997 sizes
[1] = *(pos
[1] + 1);
1998 sizes
[2] = pos
[2] ? *(pos
[2] + 1) : 0;
2000 sum
= sizes
[0] + sizes
[1] + sizes
[2];
2003 goto Done2
; /* nothing to do since we need three NPUSHB */
2004 else if (!sizes
[2] && (sum
> 0xFF))
2005 goto Done2
; /* nothing to do since we need two NPUSHB */
2009 /* reduce three NPUSHB to two */
2011 new_size2
= sum
- 0xFF;
2015 /* reduce two or three NPUSHB to one */
2026 BCI(PUSHB_1
- 1 + new_size1
);
2032 for (i
= 0; i
< new_size1
; i
++)
2034 if (p
== pos
[pos_idx
])
2037 p
+= 2; /* skip old NPUSHB */
2045 BCI(PUSHB_1
- 1 + new_size2
);
2051 for (i
= 0; i
< new_size2
; i
++)
2053 if (p
== pos
[pos_idx
])
2066 /* clear the rest of the temporarily used part of `ins_buf' */
2068 while (*p
!= INS_A0
)
2072 TA_free_hints_records(action_hints_records
, num_action_hints_records
);
2073 TA_free_hints_records(point_hints_records
, num_point_hints_records
);
2074 TA_free_recorder(&recorder
);
2076 /* we are done, so reallocate the instruction array to its real size */
2077 if (*bufp
== INS_A0
)
2079 /* search backwards */
2080 while (*bufp
== INS_A0
)
2086 /* search forwards */
2087 while (*bufp
!= INS_A0
)
2092 ins_len
= bufp
- ins_buf
;
2094 if (ins_len
> sfnt
->max_instructions
)
2095 sfnt
->max_instructions
= ins_len
;
2097 glyph
->ins_buf
= (FT_Byte
*)realloc(ins_buf
, ins_len
);
2098 glyph
->ins_len
= ins_len
;
2103 TA_free_hints_records(action_hints_records
, num_action_hints_records
);
2104 TA_free_hints_records(point_hints_records
, num_point_hints_records
);
2105 TA_free_recorder(&recorder
);
2112 /* end of tabytecode.c */