4 * Copyright (C) 2011-2012 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
23 /* we increase the stack depth by this amount */
24 #define ADDITIONAL_STACK_ELEMENTS 20
32 int _ta_debug_disable_horz_hints
;
33 int _ta_debug_disable_vert_hints
;
34 int _ta_debug_disable_blue_hints
;
35 void* _ta_debug_hints
;
39 typedef struct Hints_Record_
47 typedef struct Recorder_
50 GLYPH
* glyph
; /* the current glyph */
51 Hints_Record hints_record
;
53 /* some segments can `wrap around' */
54 /* a contour's start point like 24-25-26-0-1-2 */
55 /* (there can be at most one such segment per contour); */
56 /* later on we append additional records */
57 /* to split them into 24-26 and 0-2 */
58 FT_UShort
* wrap_around_segments
;
59 FT_UShort num_wrap_around_segments
;
61 FT_UShort num_stack_elements
; /* the necessary stack depth so far */
63 /* data necessary for strong point interpolation */
64 FT_UShort
* ip_before_points
;
65 FT_UShort
* ip_after_points
;
66 FT_UShort
* ip_on_point_array
;
67 FT_UShort
* ip_between_point_array
;
69 FT_UShort num_strong_points
;
70 FT_UShort num_segments
;
74 /* this is the bytecode of the `.ttfautohint' glyph */
76 FT_Byte ttfautohint_glyph_bytecode
[7] =
79 /* increment `cvtl_is_subglyph' counter */
92 * convert array `args' into a sequence of NPUSHB, NPUSHW, PUSHB_X, and
93 * PUSHW_X instructions to be stored in `bufp' (the latter two instructions
94 * only if `optimize' is not set); if `need_words' is set, NPUSHW and
99 TA_build_push(FT_Byte
* bufp
,
111 for (i
= 0; i
< num_args
; i
+= 255)
113 nargs
= (num_args
- i
> 255) ? 255 : num_args
- i
;
115 if (optimize
&& nargs
<= 8)
116 BCI(PUSHW_1
- 1 + nargs
);
122 for (j
= 0; j
< nargs
; j
++)
132 for (i
= 0; i
< num_args
; i
+= 255)
134 nargs
= (num_args
- i
> 255) ? 255 : num_args
- i
;
136 if (optimize
&& nargs
<= 8)
137 BCI(PUSHB_1
- 1 + nargs
);
143 for (j
= 0; j
< nargs
; j
++)
155 /* We add a subglyph for each composite glyph. */
156 /* Since subglyphs must contain at least one point, */
157 /* we have to adjust all point indices accordingly. */
158 /* Using the `pointsums' array of the `GLYPH' structure */
159 /* it is straightforward to do that: */
160 /* Assuming that point with index x is in the interval */
161 /* pointsums[n] <= x < pointsums[n + 1], */
162 /* the new point index is x + n. */
165 TA_adjust_point_index(Recorder
* recorder
,
168 FONT
* font
= recorder
->font
;
169 GLYPH
* glyph
= recorder
->glyph
;
173 if (!glyph
->num_components
|| !font
->hint_with_components
)
174 return idx
; /* not a composite glyph */
176 for (i
= 0; i
< glyph
->num_pointsums
; i
++)
177 if (idx
< glyph
->pointsums
[i
])
184 /* we store the segments in the storage area; */
185 /* each segment record consists of the first and last point */
188 TA_sfnt_build_glyph_segments(SFNT
* sfnt
,
193 FONT
* font
= recorder
->font
;
194 TA_GlyphHints hints
= &font
->loader
->hints
;
195 TA_AxisHints axis
= &hints
->axis
[TA_DIMENSION_VERT
];
196 TA_Point points
= hints
->points
;
197 TA_Segment segments
= axis
->segments
;
199 TA_Segment seg_limit
;
201 FT_Outline outline
= font
->loader
->gloader
->base
.outline
;
206 FT_UShort num_segments
;
208 FT_Bool need_words
= 0;
212 FT_UShort num_packed_segments
;
213 FT_UShort num_storage
;
214 FT_UShort num_stack_elements
;
215 FT_UShort num_twilight_points
;
218 seg_limit
= segments
+ axis
->num_segments
;
219 num_segments
= axis
->num_segments
;
221 /* to pack the data in the bytecode more tightly, */
222 /* we store up to the first nine segments in nibbles if possible, */
223 /* using delta values */
225 num_packed_segments
= 0;
226 for (seg
= segments
; seg
< seg_limit
; seg
++)
228 FT_UInt first
= seg
->first
- points
;
229 FT_UInt last
= seg
->last
- points
;
232 first
= TA_adjust_point_index(recorder
, first
);
233 last
= TA_adjust_point_index(recorder
, last
);
235 if (first
- base
>= 16)
237 if (first
> last
|| last
- first
>= 16)
239 if (num_packed_segments
== 9)
241 num_packed_segments
++;
245 /* also handle wrap-around segments */
246 num_segments
+= recorder
->num_wrap_around_segments
;
248 /* wrap-around segments are pushed with four arguments; */
249 /* a segment stored in nibbles needs only one byte instead of two */
250 num_args
= num_packed_segments
251 + 2 * (num_segments
- num_packed_segments
)
252 + 2 * recorder
->num_wrap_around_segments
255 /* collect all arguments temporarily in an array (in reverse order) */
256 /* so that we can easily split into chunks of 255 args */
257 /* as needed by NPUSHB and NPUSHW, respectively */
258 args
= (FT_UInt
*)malloc(num_args
* sizeof (FT_UInt
));
262 arg
= args
+ num_args
- 1;
264 if (num_segments
> 0xFF)
267 /* the number of packed segments is indicated by the function number */
268 if (recorder
->glyph
->num_components
&& font
->hint_with_components
)
269 *(arg
--) = bci_create_segments_composite_0
+ num_packed_segments
;
271 *(arg
--) = bci_create_segments_0
+ num_packed_segments
;
272 *(arg
--) = num_segments
;
275 for (seg
= segments
; seg
< segments
+ num_packed_segments
; seg
++)
277 FT_UInt first
= seg
->first
- points
;
278 FT_UInt last
= seg
->last
- points
;
283 first
= TA_adjust_point_index(recorder
, first
);
284 last
= TA_adjust_point_index(recorder
, last
);
286 low_nibble
= first
- base
;
287 high_nibble
= last
- first
;
289 *(arg
--) = 16 * high_nibble
+ low_nibble
;
294 for (seg
= segments
+ num_packed_segments
; seg
< seg_limit
; seg
++)
296 FT_UInt first
= seg
->first
- points
;
297 FT_UInt last
= seg
->last
- points
;
300 *(arg
--) = TA_adjust_point_index(recorder
, first
);
301 *(arg
--) = TA_adjust_point_index(recorder
, last
);
303 /* we push the last and first contour point */
304 /* as a third and fourth argument in wrap-around segments */
307 for (n
= 0; n
< outline
.n_contours
; n
++)
309 FT_UInt end
= (FT_UInt
)outline
.contours
[n
];
314 *(arg
--) = TA_adjust_point_index(recorder
, end
);
319 *(arg
--) = TA_adjust_point_index(recorder
, 0);
321 *(arg
--) = TA_adjust_point_index(recorder
,
322 (FT_UInt
)outline
.contours
[n
- 1] + 1);
332 /* emit the second part of wrap-around segments as separate segments */
333 /* so that edges can easily link to them */
334 for (seg
= segments
; seg
< seg_limit
; seg
++)
336 FT_UInt first
= seg
->first
- points
;
337 FT_UInt last
= seg
->last
- points
;
342 for (n
= 0; n
< outline
.n_contours
; n
++)
344 if (first
<= (FT_UInt
)outline
.contours
[n
])
347 *(arg
--) = TA_adjust_point_index(recorder
, 0);
349 *(arg
--) = TA_adjust_point_index(recorder
,
350 (FT_UInt
)outline
.contours
[n
- 1] + 1);
355 *(arg
--) = TA_adjust_point_index(recorder
, last
);
359 /* with most fonts it is very rare */
360 /* that any of the pushed arguments is larger than 0xFF, */
361 /* thus we refrain from further optimizing this case */
362 bufp
= TA_build_push(bufp
, args
, num_args
, need_words
, optimize
);
366 num_storage
= sal_segment_offset
+ num_segments
* 2;
367 if (num_storage
> sfnt
->max_storage
)
368 sfnt
->max_storage
= num_storage
;
370 num_twilight_points
= num_segments
* 2;
371 if (num_twilight_points
> sfnt
->max_twilight_points
)
372 sfnt
->max_twilight_points
= num_twilight_points
;
374 /* both this function and `TA_emit_hints_record' */
375 /* push data onto the stack */
376 num_stack_elements
= ADDITIONAL_STACK_ELEMENTS
377 + recorder
->num_stack_elements
+ num_args
;
378 if (num_stack_elements
> sfnt
->max_stack_elements
)
379 sfnt
->max_stack_elements
= num_stack_elements
;
388 TA_sfnt_build_glyph_scaler(SFNT
* sfnt
,
392 FONT
* font
= recorder
->font
;
393 FT_GlyphSlot glyph
= sfnt
->face
->glyph
;
394 FT_Vector
* points
= glyph
->outline
.points
;
395 FT_Int num_contours
= glyph
->outline
.n_contours
;
401 FT_Bool need_words
= 0;
404 FT_UShort num_stack_elements
;
407 num_args
= 2 * num_contours
+ 2;
409 /* collect all arguments temporarily in an array (in reverse order) */
410 /* so that we can easily split into chunks of 255 args */
411 /* as needed by NPUSHB and NPUSHW, respectively */
412 args
= (FT_UInt
*)malloc(num_args
* sizeof (FT_UInt
));
416 arg
= args
+ num_args
- 1;
421 if (recorder
->glyph
->num_components
&& font
->hint_with_components
)
422 *(arg
--) = bci_scale_composite_glyph
;
424 *(arg
--) = bci_scale_glyph
;
425 *(arg
--) = num_contours
;
430 for (p
= 0; p
< num_contours
; p
++)
436 end
= glyph
->outline
.contours
[p
];
438 for (q
= start
; q
<= end
; q
++)
440 if (points
[q
].y
< points
[min
].y
)
442 if (points
[q
].y
> points
[max
].y
)
448 *(arg
--) = TA_adjust_point_index(recorder
, max
);
449 *(arg
--) = TA_adjust_point_index(recorder
, min
);
453 *(arg
--) = TA_adjust_point_index(recorder
, min
);
454 *(arg
--) = TA_adjust_point_index(recorder
, max
);
463 /* with most fonts it is very rare */
464 /* that any of the pushed arguments is larger than 0xFF, */
465 /* thus we refrain from further optimizing this case */
466 bufp
= TA_build_push(bufp
, args
, num_args
, need_words
, 1);
470 num_stack_elements
= ADDITIONAL_STACK_ELEMENTS
+ num_args
;
471 if (num_stack_elements
> sfnt
->max_stack_elements
)
472 sfnt
->max_stack_elements
= num_stack_elements
;
481 TA_font_build_subglyph_shifter(FONT
* font
,
484 FT_Face face
= font
->loader
->face
;
485 FT_GlyphSlot glyph
= face
->glyph
;
487 TA_GlyphLoader gloader
= font
->loader
->gloader
;
489 TA_SubGlyph subglyphs
= gloader
->base
.subglyphs
;
490 TA_SubGlyph subglyph_limit
= subglyphs
+ gloader
->base
.num_subglyphs
;
491 TA_SubGlyph subglyph
;
493 FT_Int curr_contour
= 0;
496 for (subglyph
= subglyphs
; subglyph
< subglyph_limit
; subglyph
++)
500 FT_UShort flags
= subglyph
->flags
;
501 FT_Pos y_offset
= subglyph
->arg2
;
506 /* load subglyph to get the number of contours */
507 error
= FT_Load_Glyph(face
, subglyph
->index
, FT_LOAD_NO_SCALE
);
510 num_contours
= glyph
->outline
.n_contours
;
512 /* nothing to do if there is a point-to-point alignment */
513 if (!(flags
& FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES
))
516 /* nothing to do if y offset is zero */
520 /* nothing to do if there are no contours */
524 /* note that calling `FT_Load_Glyph' without FT_LOAD_NO_RECURSE */
525 /* ensures that composite subglyphs are represented as simple glyphs */
527 if (num_contours
> 0xFF
528 || curr_contour
> 0xFF)
531 BCI(HIGH(curr_contour
));
532 BCI(LOW(curr_contour
));
533 BCI(HIGH(num_contours
));
534 BCI(LOW(num_contours
));
543 /* there are high chances that this value needs PUSHW, */
544 /* thus we handle it separately */
545 if (y_offset
> 0xFF || y_offset
< 0)
558 BCI(bci_shift_subglyph
);
562 curr_contour
+= num_contours
;
570 * The four `ta_ip_*' actions in the `TA_hints_recorder' callback store its
571 * data in four arrays (which are simple but waste a lot of memory). The
572 * function below converts them into bytecode.
574 * For `ta_ip_before' and `ta_ip_after', the collected points are emitted
575 * together with the edge they correspond to.
577 * For both `ta_ip_on' and `ta_ip_between', an outer loop is constructed to
578 * loop over the edge or edge pairs, respectively, and each edge or edge
579 * pair contains an inner loop to emit the correponding points.
583 TA_build_point_hints(Recorder
* recorder
,
586 TA_AxisHints axis
= &hints
->axis
[TA_DIMENSION_VERT
];
587 TA_Segment segments
= axis
->segments
;
588 TA_Edge edges
= axis
->edges
;
594 FT_Byte
* p
= recorder
->hints_record
.buf
;
595 FT_UShort num_edges
= axis
->num_edges
;
596 FT_UShort num_strong_points
= recorder
->num_strong_points
;
610 /* we store everything as 16bit numbers; */
611 /* the function numbers (`ta_ip_before', etc.) */
612 /* reflect the order in the TA_Action enumeration */
614 /* ip_before_points */
617 ip
= recorder
->ip_before_points
;
618 ip_limit
= ip
+ num_strong_points
;
619 for (; ip
< ip_limit
; ip
++)
629 recorder
->hints_record
.num_actions
++;
634 *(p
++) = (FT_Byte
)ta_ip_before
+ ACTION_OFFSET
;
635 *(p
++) = HIGH(edge
->first
- segments
);
636 *(p
++) = LOW(edge
->first
- segments
);
640 ip
= recorder
->ip_before_points
;
642 for (; ip
< ip_limit
; ip
++)
644 FT_UInt point
= TA_adjust_point_index(recorder
, *ip
);
647 *(p
++) = HIGH(point
);
652 /* ip_after_points */
655 ip
= recorder
->ip_after_points
;
656 ip_limit
= ip
+ num_strong_points
;
657 for (; ip
< ip_limit
; ip
++)
667 recorder
->hints_record
.num_actions
++;
669 edge
= edges
+ axis
->num_edges
- 1;
672 *(p
++) = (FT_Byte
)ta_ip_after
+ ACTION_OFFSET
;
673 *(p
++) = HIGH(edge
->first
- segments
);
674 *(p
++) = LOW(edge
->first
- segments
);
678 ip
= recorder
->ip_after_points
;
680 for (; ip
< ip_limit
; ip
++)
682 FT_UInt point
= TA_adjust_point_index(recorder
, *ip
);
685 *(p
++) = HIGH(point
);
690 /* ip_on_point_array */
693 ip
= recorder
->ip_on_point_array
;
694 ip_limit
= ip
+ num_edges
* num_strong_points
;
695 for (; ip
< ip_limit
; ip
+= num_strong_points
)
701 recorder
->hints_record
.num_actions
++;
704 *(p
++) = (FT_Byte
)ta_ip_on
+ ACTION_OFFSET
;
709 ip
= recorder
->ip_on_point_array
;
710 ip_limit
= ip
+ num_edges
* num_strong_points
;
711 for (; ip
< ip_limit
; ip
+= num_strong_points
, i
++)
718 *(p
++) = HIGH(edge
->first
- segments
);
719 *(p
++) = LOW(edge
->first
- segments
);
723 iq_limit
= iq
+ num_strong_points
;
724 for (; iq
< iq_limit
; iq
++)
737 for (; iq
< iq_limit
; iq
++)
739 FT_UInt point
= TA_adjust_point_index(recorder
, *iq
);
742 *(p
++) = HIGH(point
);
748 /* ip_between_point_array */
751 ip
= recorder
->ip_between_point_array
;
752 ip_limit
= ip
+ num_edges
* num_edges
* num_strong_points
;
753 for (; ip
< ip_limit
; ip
+= num_strong_points
)
759 recorder
->hints_record
.num_actions
++;
762 *(p
++) = (FT_Byte
)ta_ip_between
+ ACTION_OFFSET
;
767 ip
= recorder
->ip_between_point_array
;
768 ip_limit
= ip
+ num_edges
* num_edges
* num_strong_points
;
771 ip
+= num_edges
* num_strong_points
, i
++)
777 iq_limit
= iq
+ num_edges
* num_strong_points
;
778 for (; iq
< iq_limit
; iq
+= num_strong_points
, j
++)
785 *(p
++) = HIGH(after
->first
- segments
);
786 *(p
++) = LOW(after
->first
- segments
);
787 *(p
++) = HIGH(before
->first
- segments
);
788 *(p
++) = LOW(before
->first
- segments
);
792 ir_limit
= ir
+ num_strong_points
;
793 for (; ir
< ir_limit
; ir
++)
806 for (; ir
< ir_limit
; ir
++)
808 FT_UInt point
= TA_adjust_point_index(recorder
, *ir
);
811 *(p
++) = HIGH(point
);
818 recorder
->hints_record
.buf
= p
;
823 TA_hints_record_is_different(Hints_Record
* hints_records
,
824 FT_UInt num_hints_records
,
828 Hints_Record last_hints_record
;
834 /* we only need to compare with the last hints record */
835 last_hints_record
= hints_records
[num_hints_records
- 1];
837 if ((FT_UInt
)(end
- start
) != last_hints_record
.buf_len
)
840 if (memcmp(start
, last_hints_record
.buf
, last_hints_record
.buf_len
))
848 TA_add_hints_record(Hints_Record
** hints_records
,
849 FT_UInt
* num_hints_records
,
851 Hints_Record hints_record
)
853 Hints_Record
* hints_records_new
;
855 /* at this point, `hints_record.buf' still points into `ins_buf' */
856 FT_Byte
* end
= hints_record
.buf
;
859 buf_len
= (FT_UInt
)(end
- start
);
861 /* now fill the structure completely */
862 hints_record
.buf_len
= buf_len
;
863 hints_record
.buf
= (FT_Byte
*)malloc(buf_len
);
864 if (!hints_record
.buf
)
865 return FT_Err_Out_Of_Memory
;
867 memcpy(hints_record
.buf
, start
, buf_len
);
869 (*num_hints_records
)++;
871 (Hints_Record
*)realloc(*hints_records
, *num_hints_records
872 * sizeof (Hints_Record
));
873 if (!hints_records_new
)
875 free(hints_record
.buf
);
876 (*num_hints_records
)--;
877 return FT_Err_Out_Of_Memory
;
880 *hints_records
= hints_records_new
;
882 (*hints_records
)[*num_hints_records
- 1] = hints_record
;
889 TA_emit_hints_record(Recorder
* recorder
,
890 Hints_Record
* hints_record
,
896 FT_Bool need_words
= 0;
899 FT_UInt num_arguments
;
903 /* check whether any argument is larger than 0xFF */
904 endp
= hints_record
->buf
+ hints_record
->buf_len
;
905 for (p
= hints_record
->buf
; p
< endp
; p
+= 2)
909 /* with most fonts it is very rare */
910 /* that any of the pushed arguments is larger than 0xFF, */
911 /* thus we refrain from further optimizing this case */
913 num_arguments
= hints_record
->buf_len
/ 2;
918 for (i
= 0; i
< num_arguments
; i
+= 255)
920 num_args
= (num_arguments
- i
> 255) ? 255 : (num_arguments
- i
);
922 if (optimize
&& num_args
<= 8)
923 BCI(PUSHW_1
- 1 + num_args
);
929 for (j
= 0; j
< num_args
; j
++)
939 /* we only need the lower bytes */
942 for (i
= 0; i
< num_arguments
; i
+= 255)
944 num_args
= (num_arguments
- i
> 255) ? 255 : (num_arguments
- i
);
946 if (optimize
&& num_args
<= 8)
947 BCI(PUSHB_1
- 1 + num_args
);
953 for (j
= 0; j
< num_args
; j
++)
961 /* collect stack depth data */
962 if (num_arguments
> recorder
->num_stack_elements
)
963 recorder
->num_stack_elements
= num_arguments
;
970 TA_emit_hints_records(Recorder
* recorder
,
971 Hints_Record
* hints_records
,
972 FT_UInt num_hints_records
,
977 Hints_Record
* hints_record
;
980 hints_record
= hints_records
;
982 for (i
= 0; i
< num_hints_records
- 1; i
++)
985 if (hints_record
->size
> 0xFF)
988 BCI(HIGH((hints_record
+ 1)->size
));
989 BCI(LOW((hints_record
+ 1)->size
));
994 BCI((hints_record
+ 1)->size
);
998 bufp
= TA_emit_hints_record(recorder
, hints_record
, bufp
, optimize
);
1004 bufp
= TA_emit_hints_record(recorder
, hints_record
, bufp
, optimize
);
1006 for (i
= 0; i
< num_hints_records
- 1; i
++)
1014 TA_free_hints_records(Hints_Record
* hints_records
,
1015 FT_UInt num_hints_records
)
1020 for (i
= 0; i
< num_hints_records
; i
++)
1021 free(hints_records
[i
].buf
);
1023 free(hints_records
);
1028 TA_hints_recorder_handle_segments(FT_Byte
* bufp
,
1033 TA_Segment segments
= axis
->segments
;
1036 FT_UShort num_segs
= 0;
1040 seg_idx
= edge
->first
- segments
;
1042 /* we store everything as 16bit numbers */
1043 *(bufp
++) = HIGH(seg_idx
);
1044 *(bufp
++) = LOW(seg_idx
);
1046 /* wrap-around segments are stored as two segments */
1047 if (edge
->first
->first
> edge
->first
->last
)
1050 seg
= edge
->first
->edge_next
;
1051 while (seg
!= edge
->first
)
1055 if (seg
->first
> seg
->last
)
1058 seg
= seg
->edge_next
;
1061 *(bufp
++) = HIGH(num_segs
);
1062 *(bufp
++) = LOW(num_segs
);
1064 if (edge
->first
->first
> edge
->first
->last
)
1066 /* emit second part of wrap-around segment; */
1067 /* the bytecode positions such segments after `normal' ones */
1071 if (seg_idx
== *wrap
)
1076 *(bufp
++) = HIGH(axis
->num_segments
+ (wrap
- wraps
));
1077 *(bufp
++) = LOW(axis
->num_segments
+ (wrap
- wraps
));
1080 seg
= edge
->first
->edge_next
;
1081 while (seg
!= edge
->first
)
1083 seg_idx
= seg
- segments
;
1085 *(bufp
++) = HIGH(seg_idx
);
1086 *(bufp
++) = LOW(seg_idx
);
1088 if (seg
->first
> seg
->last
)
1093 if (seg_idx
== *wrap
)
1098 *(bufp
++) = HIGH(axis
->num_segments
+ (wrap
- wraps
));
1099 *(bufp
++) = LOW(axis
->num_segments
+ (wrap
- wraps
));
1102 seg
= seg
->edge_next
;
1110 TA_hints_recorder(TA_Action action
,
1111 TA_GlyphHints hints
,
1116 TA_Edge lower_bound
,
1117 TA_Edge upper_bound
)
1119 TA_AxisHints axis
= &hints
->axis
[dim
];
1120 TA_Edge edges
= axis
->edges
;
1121 TA_Segment segments
= axis
->segments
;
1122 TA_Point points
= hints
->points
;
1124 Recorder
* recorder
= (Recorder
*)hints
->user
;
1125 FONT
* font
= recorder
->font
;
1126 FT_UShort
* wraps
= recorder
->wrap_around_segments
;
1127 FT_Byte
* p
= recorder
->hints_record
.buf
;
1133 if (dim
== TA_DIMENSION_HORZ
)
1136 /* we collect point hints for later processing */
1141 TA_Point point
= (TA_Point
)arg1
;
1144 ip
= recorder
->ip_before_points
;
1145 limit
= ip
+ recorder
->num_strong_points
;
1146 for (; ip
< limit
; ip
++)
1150 *ip
= point
- points
;
1159 TA_Point point
= (TA_Point
)arg1
;
1162 ip
= recorder
->ip_after_points
;
1163 limit
= ip
+ recorder
->num_strong_points
;
1164 for (; ip
< limit
; ip
++)
1168 *ip
= point
- points
;
1177 TA_Point point
= (TA_Point
)arg1
;
1178 TA_Edge edge
= arg2
;
1181 ip
= recorder
->ip_on_point_array
1182 + recorder
->num_strong_points
1184 limit
= ip
+ recorder
->num_strong_points
;
1185 for (; ip
< limit
; ip
++)
1189 *ip
= point
- points
;
1198 TA_Point point
= (TA_Point
)arg1
;
1199 TA_Edge before
= arg2
;
1200 TA_Edge after
= arg3
;
1203 /* note that `recorder->num_segments' has been used for allocation, */
1204 /* but `axis->num_edges' is used for accessing this array */
1205 ip
= recorder
->ip_between_point_array
1206 + recorder
->num_strong_points
* axis
->num_edges
1208 + recorder
->num_strong_points
1210 limit
= ip
+ recorder
->num_strong_points
;
1211 for (; ip
< limit
; ip
++)
1215 *ip
= point
- points
;
1223 /* we ignore the BOUND action since we signal this information */
1224 /* with the proper function number */
1231 /* some enum values correspond to four or eight bytecode functions; */
1232 /* if the value is n, the function numbers are n, ..., n+7, */
1233 /* to be differentiated with flags */
1239 TA_Edge base_edge
= (TA_Edge
)arg1
;
1240 TA_Edge stem_edge
= arg2
;
1244 *(p
++) = (FT_Byte
)action
+ ACTION_OFFSET
1245 + ((stem_edge
->flags
& TA_EDGE_SERIF
) != 0)
1246 + 2 * ((base_edge
->flags
& TA_EDGE_ROUND
) != 0);
1248 *(p
++) = HIGH(base_edge
->first
- segments
);
1249 *(p
++) = LOW(base_edge
->first
- segments
);
1250 *(p
++) = HIGH(stem_edge
->first
- segments
);
1251 *(p
++) = LOW(stem_edge
->first
- segments
);
1253 p
= TA_hints_recorder_handle_segments(p
, axis
, stem_edge
, wraps
);
1259 TA_Edge edge
= (TA_Edge
)arg1
;
1260 TA_Edge edge2
= arg2
;
1264 *(p
++) = (FT_Byte
)action
+ ACTION_OFFSET
1265 + ((edge2
->flags
& TA_EDGE_SERIF
) != 0)
1266 + 2 * ((edge
->flags
& TA_EDGE_ROUND
) != 0);
1268 *(p
++) = HIGH(edge
->first
- segments
);
1269 *(p
++) = LOW(edge
->first
- segments
);
1270 *(p
++) = HIGH(edge2
->first
- segments
);
1271 *(p
++) = LOW(edge2
->first
- segments
);
1273 p
= TA_hints_recorder_handle_segments(p
, axis
, edge
, wraps
);
1279 TA_Edge edge
= (TA_Edge
)arg1
;
1280 TA_Edge edge2
= arg2
;
1281 TA_Edge edge_minus_one
= lower_bound
;
1285 *(p
++) = (FT_Byte
)action
+ ACTION_OFFSET
1286 + ((edge2
->flags
& TA_EDGE_SERIF
) != 0)
1287 + 2 * ((edge
->flags
& TA_EDGE_ROUND
) != 0)
1288 + 4 * (edge_minus_one
!= NULL
);
1290 *(p
++) = HIGH(edge
->first
- segments
);
1291 *(p
++) = LOW(edge
->first
- segments
);
1292 *(p
++) = HIGH(edge2
->first
- segments
);
1293 *(p
++) = LOW(edge2
->first
- segments
);
1297 *(p
++) = HIGH(edge_minus_one
->first
- segments
);
1298 *(p
++) = LOW(edge_minus_one
->first
- segments
);
1301 p
= TA_hints_recorder_handle_segments(p
, axis
, edge
, wraps
);
1305 case ta_blue_anchor
:
1307 TA_Edge edge
= (TA_Edge
)arg1
;
1308 TA_Edge blue
= arg2
;
1312 *(p
++) = (FT_Byte
)action
+ ACTION_OFFSET
;
1314 *(p
++) = HIGH(blue
->first
- segments
);
1315 *(p
++) = LOW(blue
->first
- segments
);
1317 if (edge
->best_blue_is_shoot
)
1319 *(p
++) = HIGH(CVT_BLUE_SHOOTS_OFFSET(font
) + edge
->best_blue_idx
);
1320 *(p
++) = LOW(CVT_BLUE_SHOOTS_OFFSET(font
) + edge
->best_blue_idx
);
1324 *(p
++) = HIGH(CVT_BLUE_REFS_OFFSET(font
) + edge
->best_blue_idx
);
1325 *(p
++) = LOW(CVT_BLUE_REFS_OFFSET(font
) + edge
->best_blue_idx
);
1328 *(p
++) = HIGH(edge
->first
- segments
);
1329 *(p
++) = LOW(edge
->first
- segments
);
1331 p
= TA_hints_recorder_handle_segments(p
, axis
, edge
, wraps
);
1337 TA_Edge edge
= (TA_Edge
)arg1
;
1338 TA_Edge edge2
= arg2
;
1339 TA_Edge edge_minus_one
= lower_bound
;
1343 *(p
++) = (FT_Byte
)action
+ ACTION_OFFSET
1344 + ((edge2
->flags
& TA_EDGE_SERIF
) != 0)
1345 + 2 * ((edge
->flags
& TA_EDGE_ROUND
) != 0)
1346 + 4 * (edge_minus_one
!= NULL
);
1348 *(p
++) = HIGH(edge
->first
- segments
);
1349 *(p
++) = LOW(edge
->first
- segments
);
1350 *(p
++) = HIGH(edge2
->first
- segments
);
1351 *(p
++) = LOW(edge2
->first
- segments
);
1355 *(p
++) = HIGH(edge_minus_one
->first
- segments
);
1356 *(p
++) = LOW(edge_minus_one
->first
- segments
);
1359 p
= TA_hints_recorder_handle_segments(p
, axis
, edge
, wraps
);
1360 p
= TA_hints_recorder_handle_segments(p
, axis
, edge2
, wraps
);
1366 TA_Edge edge
= (TA_Edge
)arg1
;
1370 *(p
++) = (FT_Byte
)action
+ ACTION_OFFSET
;
1372 if (edge
->best_blue_is_shoot
)
1374 *(p
++) = HIGH(CVT_BLUE_SHOOTS_OFFSET(font
) + edge
->best_blue_idx
);
1375 *(p
++) = LOW(CVT_BLUE_SHOOTS_OFFSET(font
) + edge
->best_blue_idx
);
1379 *(p
++) = HIGH(CVT_BLUE_REFS_OFFSET(font
) + edge
->best_blue_idx
);
1380 *(p
++) = LOW(CVT_BLUE_REFS_OFFSET(font
) + edge
->best_blue_idx
);
1383 *(p
++) = HIGH(edge
->first
- segments
);
1384 *(p
++) = LOW(edge
->first
- segments
);
1386 p
= TA_hints_recorder_handle_segments(p
, axis
, edge
, wraps
);
1392 TA_Edge serif
= (TA_Edge
)arg1
;
1393 TA_Edge base
= serif
->serif
;
1397 *(p
++) = (FT_Byte
)action
+ ACTION_OFFSET
1398 + (lower_bound
!= NULL
)
1399 + 2 * (upper_bound
!= NULL
);
1401 *(p
++) = HIGH(serif
->first
- segments
);
1402 *(p
++) = LOW(serif
->first
- segments
);
1403 *(p
++) = HIGH(base
->first
- segments
);
1404 *(p
++) = LOW(base
->first
- segments
);
1408 *(p
++) = HIGH(lower_bound
->first
- segments
);
1409 *(p
++) = LOW(lower_bound
->first
- segments
);
1413 *(p
++) = HIGH(upper_bound
->first
- segments
);
1414 *(p
++) = LOW(upper_bound
->first
- segments
);
1417 p
= TA_hints_recorder_handle_segments(p
, axis
, serif
, wraps
);
1421 case ta_serif_anchor
:
1422 case ta_serif_link2
:
1424 TA_Edge edge
= (TA_Edge
)arg1
;
1428 *(p
++) = (FT_Byte
)action
+ ACTION_OFFSET
1429 + (lower_bound
!= NULL
)
1430 + 2 * (upper_bound
!= NULL
);
1432 *(p
++) = HIGH(edge
->first
- segments
);
1433 *(p
++) = LOW(edge
->first
- segments
);
1437 *(p
++) = HIGH(lower_bound
->first
- segments
);
1438 *(p
++) = LOW(lower_bound
->first
- segments
);
1442 *(p
++) = HIGH(upper_bound
->first
- segments
);
1443 *(p
++) = LOW(upper_bound
->first
- segments
);
1446 p
= TA_hints_recorder_handle_segments(p
, axis
, edge
, wraps
);
1450 case ta_serif_link1
:
1452 TA_Edge edge
= (TA_Edge
)arg1
;
1453 TA_Edge before
= arg2
;
1454 TA_Edge after
= arg3
;
1458 *(p
++) = (FT_Byte
)action
+ ACTION_OFFSET
1459 + (lower_bound
!= NULL
)
1460 + 2 * (upper_bound
!= NULL
);
1462 *(p
++) = HIGH(before
->first
- segments
);
1463 *(p
++) = LOW(before
->first
- segments
);
1464 *(p
++) = HIGH(edge
->first
- segments
);
1465 *(p
++) = LOW(edge
->first
- segments
);
1466 *(p
++) = HIGH(after
->first
- segments
);
1467 *(p
++) = LOW(after
->first
- segments
);
1471 *(p
++) = HIGH(lower_bound
->first
- segments
);
1472 *(p
++) = LOW(lower_bound
->first
- segments
);
1476 *(p
++) = HIGH(upper_bound
->first
- segments
);
1477 *(p
++) = LOW(upper_bound
->first
- segments
);
1480 p
= TA_hints_recorder_handle_segments(p
, axis
, edge
, wraps
);
1485 /* there are more cases in the enumeration */
1486 /* which are handled with flags */
1490 recorder
->hints_record
.num_actions
++;
1491 recorder
->hints_record
.buf
= p
;
1496 TA_init_recorder(Recorder
* recorder
,
1499 TA_GlyphHints hints
)
1501 TA_AxisHints axis
= &hints
->axis
[TA_DIMENSION_VERT
];
1502 TA_Point points
= hints
->points
;
1503 TA_Point point_limit
= points
+ hints
->num_points
;
1506 TA_Segment segments
= axis
->segments
;
1507 TA_Segment seg_limit
= segments
+ axis
->num_segments
;
1510 FT_UShort num_strong_points
= 0;
1511 FT_UShort
* wrap_around_segment
;
1513 recorder
->font
= font
;
1514 recorder
->glyph
= glyph
;
1515 recorder
->num_segments
= axis
->num_segments
;
1517 recorder
->ip_before_points
= NULL
;
1518 recorder
->ip_after_points
= NULL
;
1519 recorder
->ip_on_point_array
= NULL
;
1520 recorder
->ip_between_point_array
= NULL
;
1522 recorder
->num_stack_elements
= 0;
1524 /* no need to clean up allocated arrays in case of error; */
1525 /* this is handled later by `TA_free_recorder' */
1527 recorder
->num_wrap_around_segments
= 0;
1528 for (seg
= segments
; seg
< seg_limit
; seg
++)
1529 if (seg
->first
> seg
->last
)
1530 recorder
->num_wrap_around_segments
++;
1532 recorder
->wrap_around_segments
=
1533 (FT_UShort
*)malloc(recorder
->num_wrap_around_segments
1534 * sizeof (FT_UShort
));
1535 if (!recorder
->wrap_around_segments
)
1536 return FT_Err_Out_Of_Memory
;
1538 wrap_around_segment
= recorder
->wrap_around_segments
;
1539 for (seg
= segments
; seg
< seg_limit
; seg
++)
1540 if (seg
->first
> seg
->last
)
1541 *(wrap_around_segment
++) = seg
- segments
;
1543 /* get number of strong points */
1544 for (point
= points
; point
< point_limit
; point
++)
1546 /* actually, we need to test `TA_FLAG_TOUCH_Y' also; */
1547 /* however, this value isn't known yet */
1548 /* (or rather, it can vary between different pixel sizes) */
1549 if (point
->flags
& TA_FLAG_WEAK_INTERPOLATION
)
1552 num_strong_points
++;
1555 recorder
->num_strong_points
= num_strong_points
;
1557 recorder
->ip_before_points
=
1558 (FT_UShort
*)malloc(num_strong_points
* sizeof (FT_UShort
));
1559 if (!recorder
->ip_before_points
)
1560 return FT_Err_Out_Of_Memory
;
1562 recorder
->ip_after_points
=
1563 (FT_UShort
*)malloc(num_strong_points
* sizeof (FT_UShort
));
1564 if (!recorder
->ip_after_points
)
1565 return FT_Err_Out_Of_Memory
;
1567 /* actually, we need `hints->num_edges' for the array sizes; */
1568 /* however, this value isn't known yet */
1569 /* (or rather, it can vary between different pixel sizes) */
1570 recorder
->ip_on_point_array
=
1571 (FT_UShort
*)malloc(axis
->num_segments
1572 * num_strong_points
* sizeof (FT_UShort
));
1573 if (!recorder
->ip_on_point_array
)
1574 return FT_Err_Out_Of_Memory
;
1576 recorder
->ip_between_point_array
=
1577 (FT_UShort
*)malloc(axis
->num_segments
* axis
->num_segments
1578 * num_strong_points
* sizeof (FT_UShort
));
1579 if (!recorder
->ip_between_point_array
)
1580 return FT_Err_Out_Of_Memory
;
1587 TA_reset_recorder(Recorder
* recorder
,
1590 recorder
->hints_record
.buf
= bufp
;
1591 recorder
->hints_record
.num_actions
= 0;
1596 TA_rewind_recorder(Recorder
* recorder
,
1600 TA_reset_recorder(recorder
, bufp
);
1602 recorder
->hints_record
.size
= size
;
1604 /* We later check with MISSING (which expands to 0xFF bytes) */
1606 memset(recorder
->ip_before_points
, 0xFF,
1607 recorder
->num_strong_points
* sizeof (FT_UShort
));
1608 memset(recorder
->ip_after_points
, 0xFF,
1609 recorder
->num_strong_points
* sizeof (FT_UShort
));
1611 memset(recorder
->ip_on_point_array
, 0xFF,
1612 recorder
->num_segments
1613 * recorder
->num_strong_points
* sizeof (FT_UShort
));
1614 memset(recorder
->ip_between_point_array
, 0xFF,
1615 recorder
->num_segments
* recorder
->num_segments
1616 * recorder
->num_strong_points
* sizeof (FT_UShort
));
1621 TA_free_recorder(Recorder
* recorder
)
1623 free(recorder
->wrap_around_segments
);
1625 free(recorder
->ip_before_points
);
1626 free(recorder
->ip_after_points
);
1627 free(recorder
->ip_on_point_array
);
1628 free(recorder
->ip_between_point_array
);
1633 TA_sfnt_build_glyph_instructions(SFNT
* sfnt
,
1637 FT_Face face
= sfnt
->face
;
1645 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
1646 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
1647 /* `idx' is never negative */
1648 GLYPH
* glyph
= &data
->glyphs
[idx
];
1650 TA_GlyphHints hints
;
1652 FT_UInt num_action_hints_records
= 0;
1653 FT_UInt num_point_hints_records
= 0;
1654 Hints_Record
* action_hints_records
= NULL
;
1655 Hints_Record
* point_hints_records
= NULL
;
1658 FT_UShort num_stack_elements
;
1659 FT_Bool optimize
= 0;
1661 FT_Int32 load_flags
;
1671 /* XXX: right now, we abuse this flag to control */
1672 /* the global behaviour of the auto-hinter */
1673 load_flags
= 1 << 29; /* vertical hinting only */
1674 if (!font
->pre_hinting
)
1676 if (font
->hint_with_components
)
1677 load_flags
|= FT_LOAD_NO_SCALE
;
1679 load_flags
|= FT_LOAD_NO_RECURSE
;
1682 /* computing the segments is resolution independent, */
1683 /* thus the pixel size in this call is arbitrary */
1684 error
= FT_Set_Pixel_Sizes(face
, 20, 20);
1689 /* temporarily disable debugging output */
1690 /* to avoid getting the information twice */
1691 _ta_debug_save
= _ta_debug
;
1695 ta_loader_register_hints_recorder(font
->loader
, NULL
, NULL
);
1696 error
= ta_loader_load_glyph(font
, face
, (FT_UInt
)idx
, load_flags
);
1699 _ta_debug
= _ta_debug_save
;
1705 /* do nothing if we have an empty glyph */
1706 if (!face
->glyph
->outline
.n_contours
)
1709 hints
= &font
->loader
->hints
;
1711 /* do nothing if the setup delivered the dummy module only */
1712 if (!hints
->num_points
)
1715 /* we allocate a buffer which is certainly large enough */
1716 /* to hold all of the created bytecode instructions; */
1717 /* later on it gets reallocated to its real size */
1718 ins_len
= hints
->num_points
* 1000;
1719 ins_buf
= (FT_Byte
*)malloc(ins_len
);
1721 return FT_Err_Out_Of_Memory
;
1723 /* initialize array with an invalid bytecode */
1724 /* so that we can easily find the array length at reallocation time */
1725 memset(ins_buf
, INS_A0
, ins_len
);
1727 /* handle composite glyph */
1728 if (font
->loader
->gloader
->base
.num_subglyphs
)
1730 bufp
= TA_font_build_subglyph_shifter(font
, ins_buf
);
1733 error
= FT_Err_Out_Of_Memory
;
1740 /* only scale the glyph if the dummy hinter has been used */
1741 if (font
->loader
->metrics
->clazz
== &ta_dummy_script_class
)
1743 /* since `TA_init_recorder' hasn't been called yet, */
1744 /* we manually initialize the `font' and `glyph' fields */
1745 recorder
.font
= font
;
1746 recorder
.glyph
= glyph
;
1748 bufp
= TA_sfnt_build_glyph_scaler(sfnt
, &recorder
, ins_buf
);
1751 error
= FT_Err_Out_Of_Memory
;
1758 error
= TA_init_recorder(&recorder
, font
, glyph
, hints
);
1762 /* loop over a large range of pixel sizes */
1763 /* to find hints records which get pushed onto the bytecode stack */
1772 (void)FT_Get_Glyph_Name(face
, idx
, buf
, 256);
1774 num_chars
= fprintf(stderr
, "glyph %ld", idx
);
1776 num_chars
+= fprintf(stderr
, " (%s)", buf
);
1777 fprintf(stderr
, "\n");
1778 for (i
= 0; i
< num_chars
; i
++)
1780 fprintf(stderr
, "\n\n");
1785 /* we temporarily use `ins_buf' to record the current glyph hints */
1786 ta_loader_register_hints_recorder(font
->loader
,
1790 for (size
= font
->hinting_range_min
;
1791 size
<= font
->hinting_range_max
;
1799 TA_rewind_recorder(&recorder
, ins_buf
, size
);
1801 error
= FT_Set_Pixel_Sizes(face
, size
, size
);
1811 num_chars
= fprintf(stderr
, "size %d\n", size
);
1812 for (i
= 0; i
< num_chars
- 1; i
++)
1814 fprintf(stderr
, "\n\n");
1818 /* calling `ta_loader_load_glyph' uses the */
1819 /* `TA_hints_recorder' function as a callback, */
1820 /* modifying `hints_record' */
1821 error
= ta_loader_load_glyph(font
, face
, idx
, load_flags
);
1825 if (TA_hints_record_is_different(action_hints_records
,
1826 num_action_hints_records
,
1827 ins_buf
, recorder
.hints_record
.buf
))
1834 ta_glyph_hints_dump_edges(_ta_debug_hints
);
1835 ta_glyph_hints_dump_segments(_ta_debug_hints
);
1836 ta_glyph_hints_dump_points(_ta_debug_hints
);
1838 fprintf(stderr
, "action hints record:\n");
1839 if (ins_buf
== recorder
.hints_record
.buf
)
1840 fprintf(stderr
, " (none)");
1843 fprintf(stderr
, " ");
1844 for (p
= ins_buf
; p
< recorder
.hints_record
.buf
; p
+= 2)
1845 fprintf(stderr
, " %2d", *p
* 256 + *(p
+ 1));
1847 fprintf(stderr
, "\n");
1851 error
= TA_add_hints_record(&action_hints_records
,
1852 &num_action_hints_records
,
1853 ins_buf
, recorder
.hints_record
);
1858 /* now handle point records */
1860 TA_reset_recorder(&recorder
, ins_buf
);
1862 /* use the point hints data collected in `TA_hints_recorder' */
1863 TA_build_point_hints(&recorder
, hints
);
1865 if (TA_hints_record_is_different(point_hints_records
,
1866 num_point_hints_records
,
1867 ins_buf
, recorder
.hints_record
.buf
))
1877 num_chars
= fprintf(stderr
, "size %d\n", size
);
1878 for (i
= 0; i
< num_chars
- 1; i
++)
1880 fprintf(stderr
, "\n\n");
1882 ta_glyph_hints_dump_edges(_ta_debug_hints
);
1883 ta_glyph_hints_dump_segments(_ta_debug_hints
);
1884 ta_glyph_hints_dump_points(_ta_debug_hints
);
1887 fprintf(stderr
, "point hints record:\n");
1888 if (ins_buf
== recorder
.hints_record
.buf
)
1889 fprintf(stderr
, " (none)");
1892 fprintf(stderr
, " ");
1893 for (p
= ins_buf
; p
< recorder
.hints_record
.buf
; p
+= 2)
1894 fprintf(stderr
, " %2d", *p
* 256 + *(p
+ 1));
1896 fprintf(stderr
, "\n\n");
1900 error
= TA_add_hints_record(&point_hints_records
,
1901 &num_point_hints_records
,
1902 ins_buf
, recorder
.hints_record
);
1908 if (num_action_hints_records
== 1 && !action_hints_records
[0].num_actions
)
1910 /* since we only have a single empty record we just scale the glyph */
1911 bufp
= TA_sfnt_build_glyph_scaler(sfnt
, &recorder
, ins_buf
);
1914 error
= FT_Err_Out_Of_Memory
;
1918 /* clear the rest of the temporarily used part of `ins_buf' */
1920 while (*p
!= INS_A0
)
1926 /* if there is only a single record, */
1927 /* we do a global optimization later on */
1928 if (num_action_hints_records
> 1)
1931 /* store the hints records and handle stack depth */
1933 bufp
= TA_emit_hints_records(&recorder
,
1934 point_hints_records
,
1935 num_point_hints_records
,
1939 num_stack_elements
= recorder
.num_stack_elements
;
1940 recorder
.num_stack_elements
= 0;
1943 bufp
= TA_emit_hints_records(&recorder
,
1944 action_hints_records
,
1945 num_action_hints_records
,
1949 recorder
.num_stack_elements
+= num_stack_elements
;
1952 bufp
= TA_sfnt_build_glyph_segments(sfnt
, &recorder
, bufp
, optimize
);
1955 error
= FT_Err_Out_Of_Memory
;
1959 /* XXX improve handling of NPUSHW */
1960 if (num_action_hints_records
== 1
1961 && *(pos
[0]) != NPUSHW
&& *(pos
[1]) != NPUSHW
&& *(pos
[2]) != NPUSHW
)
1964 * we optimize two common cases, replacing
1966 * NPUSHB A ... NPUSHB B [... NPUSHB C] ... CALL
1970 * NPUSHB (A+B[+C]) ... CALL
1983 /* the point hints records block can be missing */
1984 if (pos
[0] == pos
[1])
1990 /* there are at least two NPUSHB instructions */
1991 /* (one of them directly at the start) */
1992 sizes
[0] = *(pos
[0] + 1);
1993 sizes
[1] = *(pos
[1] + 1);
1994 sizes
[2] = pos
[2] ? *(pos
[2] + 1) : 0;
1996 sum
= sizes
[0] + sizes
[1] + sizes
[2];
1999 goto Done2
; /* nothing to do since we need three NPUSHB */
2000 else if (!sizes
[2] && (sum
> 0xFF))
2001 goto Done2
; /* nothing to do since we need two NPUSHB */
2005 /* reduce three NPUSHB to two */
2007 new_size2
= sum
- 0xFF;
2011 /* reduce two or three NPUSHB to one */
2022 BCI(PUSHB_1
- 1 + new_size1
);
2028 for (i
= 0; i
< new_size1
; i
++)
2030 if (p
== pos
[pos_idx
])
2033 p
+= 2; /* skip old NPUSHB */
2041 BCI(PUSHB_1
- 1 + new_size2
);
2047 for (i
= 0; i
< new_size2
; i
++)
2049 if (p
== pos
[pos_idx
])
2062 /* clear the rest of the temporarily used part of `ins_buf' */
2064 while (*p
!= INS_A0
)
2068 TA_free_hints_records(action_hints_records
, num_action_hints_records
);
2069 TA_free_hints_records(point_hints_records
, num_point_hints_records
);
2070 TA_free_recorder(&recorder
);
2072 /* we are done, so reallocate the instruction array to its real size */
2073 if (*bufp
== INS_A0
)
2075 /* search backwards */
2076 while (*bufp
== INS_A0
)
2082 /* search forwards */
2083 while (*bufp
!= INS_A0
)
2088 ins_len
= bufp
- ins_buf
;
2090 if (ins_len
> sfnt
->max_instructions
)
2091 sfnt
->max_instructions
= ins_len
;
2093 glyph
->ins_buf
= (FT_Byte
*)realloc(ins_buf
, ins_len
);
2094 glyph
->ins_len
= ins_len
;
2099 TA_free_hints_records(action_hints_records
, num_action_hints_records
);
2100 TA_free_hints_records(point_hints_records
, num_point_hints_records
);
2101 TA_free_recorder(&recorder
);
2108 /* end of tabytecode.c */