1 /***************************************************************************/
5 /* Auto-fitter hinting routines (body). */
7 /* Copyright 2003, 2004, 2005, 2006, 2007, 2009 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
16 /***************************************************************************/
21 #include FT_INTERNAL_CALC_H
24 FT_LOCAL_DEF( FT_Error
)
25 af_axis_hints_new_segment( AF_AxisHints axis
,
27 AF_Segment
*asegment
)
29 FT_Error error
= AF_Err_Ok
;
30 AF_Segment segment
= NULL
;
33 if ( axis
->num_segments
>= axis
->max_segments
)
35 FT_Int old_max
= axis
->max_segments
;
36 FT_Int new_max
= old_max
;
37 FT_Int big_max
= (FT_Int
)( FT_INT_MAX
/ sizeof ( *segment
) );
40 if ( old_max
>= big_max
)
42 error
= AF_Err_Out_Of_Memory
;
46 new_max
+= ( new_max
>> 2 ) + 4;
47 if ( new_max
< old_max
|| new_max
> big_max
)
50 if ( FT_RENEW_ARRAY( axis
->segments
, old_max
, new_max
) )
53 axis
->max_segments
= new_max
;
56 segment
= axis
->segments
+ axis
->num_segments
++;
65 af_axis_hints_new_edge( AF_AxisHints axis
,
71 FT_Error error
= AF_Err_Ok
;
76 if ( axis
->num_edges
>= axis
->max_edges
)
78 FT_Int old_max
= axis
->max_edges
;
79 FT_Int new_max
= old_max
;
80 FT_Int big_max
= (FT_Int
)( FT_INT_MAX
/ sizeof ( *edge
) );
83 if ( old_max
>= big_max
)
85 error
= AF_Err_Out_Of_Memory
;
89 new_max
+= ( new_max
>> 2 ) + 4;
90 if ( new_max
< old_max
|| new_max
> big_max
)
93 if ( FT_RENEW_ARRAY( axis
->edges
, old_max
, new_max
) )
96 axis
->max_edges
= new_max
;
100 edge
= edges
+ axis
->num_edges
;
102 while ( edge
> edges
)
104 if ( edge
[-1].fpos
< fpos
)
107 /* we want the edge with same position and minor direction */
108 /* to appear before those in the major one in the list */
109 if ( edge
[-1].fpos
== fpos
&& dir
== axis
->major_dir
)
119 edge
->fpos
= (FT_Short
)fpos
;
120 edge
->dir
= (FT_Char
)dir
;
130 #include FT_CONFIG_STANDARD_LIBRARY_H
133 af_dir_str( AF_Direction dir
)
160 #define AF_INDEX_NUM( ptr, base ) ( (ptr) ? ( (ptr) - (base) ) : -1 )
164 af_glyph_hints_dump_points( AF_GlyphHints hints
)
166 AF_Point points
= hints
->points
;
167 AF_Point limit
= points
+ hints
->num_points
;
171 printf( "Table of points:\n" );
172 printf( " [ index | xorg | yorg | xscale | yscale "
173 "| xfit | yfit | flags ]\n" );
175 for ( point
= points
; point
< limit
; point
++ )
177 printf( " [ %5d | %5d | %5d | %-5.2f | %-5.2f "
178 "| %-5.2f | %-5.2f | %c%c%c%c%c%c ]\n",
186 ( point
->flags
& AF_FLAG_WEAK_INTERPOLATION
) ? 'w' : ' ',
187 ( point
->flags
& AF_FLAG_INFLECTION
) ? 'i' : ' ',
188 ( point
->flags
& AF_FLAG_EXTREMA_X
) ? '<' : ' ',
189 ( point
->flags
& AF_FLAG_EXTREMA_Y
) ? 'v' : ' ',
190 ( point
->flags
& AF_FLAG_ROUND_X
) ? '(' : ' ',
191 ( point
->flags
& AF_FLAG_ROUND_Y
) ? 'u' : ' ');
198 af_edge_flags_to_string( AF_Edge_Flags flags
)
200 static char temp
[32];
204 if ( flags
& AF_EDGE_ROUND
)
206 ft_memcpy( temp
+ pos
, "round", 5 );
209 if ( flags
& AF_EDGE_SERIF
)
213 ft_memcpy( temp
+ pos
, "serif", 5 );
225 /* A function to dump the array of linked segments. */
227 af_glyph_hints_dump_segments( AF_GlyphHints hints
)
232 for ( dimension
= 1; dimension
>= 0; dimension
-- )
234 AF_AxisHints axis
= &hints
->axis
[dimension
];
235 AF_Segment segments
= axis
->segments
;
236 AF_Segment limit
= segments
+ axis
->num_segments
;
240 printf ( "Table of %s segments:\n",
241 dimension
== AF_DIMENSION_HORZ
? "vertical" : "horizontal" );
242 printf ( " [ index | pos | dir | link | serif |"
243 " height | extra | flags ]\n" );
245 for ( seg
= segments
; seg
< limit
; seg
++ )
247 printf ( " [ %5d | %5.2g | %5s | %4d | %5d | %5d | %5d | %s ]\n",
249 dimension
== AF_DIMENSION_HORZ
? (int)seg
->first
->ox
/ 64.0
250 : (int)seg
->first
->oy
/ 64.0,
251 af_dir_str( (AF_Direction
)seg
->dir
),
252 AF_INDEX_NUM( seg
->link
, segments
),
253 AF_INDEX_NUM( seg
->serif
, segments
),
255 seg
->height
- ( seg
->max_coord
- seg
->min_coord
),
256 af_edge_flags_to_string( seg
->flags
) );
264 af_glyph_hints_dump_edges( AF_GlyphHints hints
)
269 for ( dimension
= 1; dimension
>= 0; dimension
-- )
271 AF_AxisHints axis
= &hints
->axis
[dimension
];
272 AF_Edge edges
= axis
->edges
;
273 AF_Edge limit
= edges
+ axis
->num_edges
;
278 * note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
279 * since they have constant a X coordinate.
281 printf ( "Table of %s edges:\n",
282 dimension
== AF_DIMENSION_HORZ
? "vertical" : "horizontal" );
283 printf ( " [ index | pos | dir | link |"
284 " serif | blue | opos | pos | flags ]\n" );
286 for ( edge
= edges
; edge
< limit
; edge
++ )
288 printf ( " [ %5d | %5.2g | %5s | %4d |"
289 " %5d | %c | %5.2f | %5.2f | %s ]\n",
291 (int)edge
->opos
/ 64.0,
292 af_dir_str( (AF_Direction
)edge
->dir
),
293 AF_INDEX_NUM( edge
->link
, edges
),
294 AF_INDEX_NUM( edge
->serif
, edges
),
295 edge
->blue_edge
? 'y' : 'n',
298 af_edge_flags_to_string( edge
->flags
) );
304 #else /* !AF_DEBUG */
306 /* these empty stubs are only used to link the `ftgrid' test program */
307 /* when debugging is disabled */
310 af_glyph_hints_dump_points( AF_GlyphHints hints
)
317 af_glyph_hints_dump_segments( AF_GlyphHints hints
)
324 af_glyph_hints_dump_edges( AF_GlyphHints hints
)
329 #endif /* !AF_DEBUG */
332 /* compute the direction value of a given vector */
333 FT_LOCAL_DEF( AF_Direction
)
334 af_direction_compute( FT_Pos dx
,
337 FT_Pos ll
, ss
; /* long and short arm lengths */
338 AF_Direction dir
; /* candidate direction */
373 if ( FT_ABS( ll
) <= FT_ABS( ss
) )
380 /* compute all inflex points in a given glyph */
383 af_glyph_hints_compute_inflections( AF_GlyphHints hints
)
385 AF_Point
* contour
= hints
->contours
;
386 AF_Point
* contour_limit
= contour
+ hints
->num_contours
;
389 /* do each contour separately */
390 for ( ; contour
< contour_limit
; contour
++ )
392 AF_Point point
= contour
[0];
393 AF_Point first
= point
;
394 AF_Point start
= point
;
395 AF_Point end
= point
;
398 FT_Pos in_x
, in_y
, out_x
, out_y
;
399 AF_Angle orient_prev
, orient_cur
;
403 /* compute first segment in contour */
413 in_x
= end
->fx
- start
->fx
;
414 in_y
= end
->fy
- start
->fy
;
416 } while ( in_x
== 0 && in_y
== 0 );
418 /* extend the segment start whenever possible */
425 before
= before
->prev
;
426 if ( before
== first
)
429 out_x
= start
->fx
- before
->fx
;
430 out_y
= start
->fy
- before
->fy
;
432 } while ( out_x
== 0 && out_y
== 0 );
434 orient_prev
= ft_corner_orientation( in_x
, in_y
, out_x
, out_y
);
436 } while ( orient_prev
== 0 );
443 /* now process all segments in the contour */
446 /* first, extend current segment's end whenever possible */
454 if ( after
== first
)
457 out_x
= after
->fx
- end
->fx
;
458 out_y
= after
->fy
- end
->fy
;
460 } while ( out_x
== 0 && out_y
== 0 );
462 orient_cur
= ft_corner_orientation( in_x
, in_y
, out_x
, out_y
);
464 } while ( orient_cur
== 0 );
466 if ( ( orient_prev
+ orient_cur
) == 0 )
468 /* we have an inflection point here */
471 start
->flags
|= AF_FLAG_INFLECTION
;
474 } while ( start
!= end
);
476 start
->flags
|= AF_FLAG_INFLECTION
;
482 orient_prev
= orient_cur
;
486 } while ( !finished
);
495 af_glyph_hints_init( AF_GlyphHints hints
,
499 hints
->memory
= memory
;
504 af_glyph_hints_done( AF_GlyphHints hints
)
506 if ( hints
&& hints
->memory
)
508 FT_Memory memory
= hints
->memory
;
513 * note that we don't need to free the segment and edge
514 * buffers, since they are really within the hints->points array
516 for ( dim
= 0; dim
< AF_DIMENSION_MAX
; dim
++ )
518 AF_AxisHints axis
= &hints
->axis
[dim
];
521 axis
->num_segments
= 0;
522 axis
->max_segments
= 0;
523 FT_FREE( axis
->segments
);
527 FT_FREE( axis
->edges
);
530 FT_FREE( hints
->contours
);
531 hints
->max_contours
= 0;
532 hints
->num_contours
= 0;
534 FT_FREE( hints
->points
);
535 hints
->num_points
= 0;
536 hints
->max_points
= 0;
538 hints
->memory
= NULL
;
544 af_glyph_hints_rescale( AF_GlyphHints hints
,
545 AF_ScriptMetrics metrics
)
547 hints
->metrics
= metrics
;
548 hints
->scaler_flags
= metrics
->scaler
.flags
;
552 FT_LOCAL_DEF( FT_Error
)
553 af_glyph_hints_reload( AF_GlyphHints hints
,
555 FT_Bool get_inflections
)
557 FT_Error error
= AF_Err_Ok
;
559 FT_UInt old_max
, new_max
;
560 FT_Fixed x_scale
= hints
->x_scale
;
561 FT_Fixed y_scale
= hints
->y_scale
;
562 FT_Pos x_delta
= hints
->x_delta
;
563 FT_Pos y_delta
= hints
->y_delta
;
564 FT_Memory memory
= hints
->memory
;
567 hints
->num_points
= 0;
568 hints
->num_contours
= 0;
570 hints
->axis
[0].num_segments
= 0;
571 hints
->axis
[0].num_edges
= 0;
572 hints
->axis
[1].num_segments
= 0;
573 hints
->axis
[1].num_edges
= 0;
575 /* first of all, reallocate the contours array when necessary */
576 new_max
= (FT_UInt
)outline
->n_contours
;
577 old_max
= hints
->max_contours
;
578 if ( new_max
> old_max
)
580 new_max
= ( new_max
+ 3 ) & ~3;
582 if ( FT_RENEW_ARRAY( hints
->contours
, old_max
, new_max
) )
585 hints
->max_contours
= new_max
;
589 * then reallocate the points arrays if necessary --
590 * note that we reserve two additional point positions, used to
591 * hint metrics appropriately
593 new_max
= (FT_UInt
)( outline
->n_points
+ 2 );
594 old_max
= hints
->max_points
;
595 if ( new_max
> old_max
)
597 new_max
= ( new_max
+ 2 + 7 ) & ~7;
599 if ( FT_RENEW_ARRAY( hints
->points
, old_max
, new_max
) )
602 hints
->max_points
= new_max
;
605 hints
->num_points
= outline
->n_points
;
606 hints
->num_contours
= outline
->n_contours
;
608 /* We can't rely on the value of `FT_Outline.flags' to know the fill */
609 /* direction used for a glyph, given that some fonts are broken (e.g., */
610 /* the Arphic ones). We thus recompute it each time we need to. */
612 hints
->axis
[AF_DIMENSION_HORZ
].major_dir
= AF_DIR_UP
;
613 hints
->axis
[AF_DIMENSION_VERT
].major_dir
= AF_DIR_LEFT
;
615 if ( FT_Outline_Get_Orientation( outline
) == FT_ORIENTATION_POSTSCRIPT
)
617 hints
->axis
[AF_DIMENSION_HORZ
].major_dir
= AF_DIR_DOWN
;
618 hints
->axis
[AF_DIMENSION_VERT
].major_dir
= AF_DIR_RIGHT
;
621 hints
->x_scale
= x_scale
;
622 hints
->y_scale
= y_scale
;
623 hints
->x_delta
= x_delta
;
624 hints
->y_delta
= y_delta
;
626 hints
->xmin_delta
= 0;
627 hints
->xmax_delta
= 0;
629 points
= hints
->points
;
630 if ( hints
->num_points
== 0 )
635 AF_Point point_limit
= points
+ hints
->num_points
;
638 /* compute coordinates & Bezier flags, next and prev */
640 FT_Vector
* vec
= outline
->points
;
641 char* tag
= outline
->tags
;
642 AF_Point first
= points
;
643 AF_Point end
= points
+ outline
->contours
[0];
645 FT_Int contour_index
= 0;
649 for ( point
= points
; point
< point_limit
; point
++, vec
++, tag
++ )
651 point
->fx
= (FT_Short
)vec
->x
;
652 point
->fy
= (FT_Short
)vec
->y
;
653 point
->ox
= point
->x
= FT_MulFix( vec
->x
, x_scale
) + x_delta
;
654 point
->oy
= point
->y
= FT_MulFix( vec
->y
, y_scale
) + y_delta
;
656 switch ( FT_CURVE_TAG( *tag
) )
658 case FT_CURVE_TAG_CONIC
:
659 point
->flags
= AF_FLAG_CONIC
;
661 case FT_CURVE_TAG_CUBIC
:
662 point
->flags
= AF_FLAG_CUBIC
;
674 if ( ++contour_index
< outline
->n_contours
)
677 end
= points
+ outline
->contours
[contour_index
];
684 /* set-up the contours array */
686 AF_Point
* contour
= hints
->contours
;
687 AF_Point
* contour_limit
= contour
+ hints
->num_contours
;
688 short* end
= outline
->contours
;
692 for ( ; contour
< contour_limit
; contour
++, end
++ )
694 contour
[0] = points
+ idx
;
695 idx
= (short)( end
[0] + 1 );
699 /* compute directions of in & out vectors */
701 AF_Point first
= points
;
702 AF_Point prev
= NULL
;
705 AF_Direction in_dir
= AF_DIR_NONE
;
708 for ( point
= points
; point
< point_limit
; point
++ )
714 if ( point
== first
)
717 in_x
= first
->fx
- prev
->fx
;
718 in_y
= first
->fy
- prev
->fy
;
719 in_dir
= af_direction_compute( in_x
, in_y
);
723 point
->in_dir
= (FT_Char
)in_dir
;
726 out_x
= next
->fx
- point
->fx
;
727 out_y
= next
->fy
- point
->fy
;
729 in_dir
= af_direction_compute( out_x
, out_y
);
730 point
->out_dir
= (FT_Char
)in_dir
;
732 if ( point
->flags
& ( AF_FLAG_CONIC
| AF_FLAG_CUBIC
) )
735 point
->flags
|= AF_FLAG_WEAK_INTERPOLATION
;
737 else if ( point
->out_dir
== point
->in_dir
)
739 if ( point
->out_dir
!= AF_DIR_NONE
)
742 if ( ft_corner_is_flat( in_x
, in_y
, out_x
, out_y
) )
745 else if ( point
->in_dir
== -point
->out_dir
)
755 /* compute inflection points -- */
756 /* disabled due to no longer perceived benefits */
757 if ( 0 && get_inflections
)
758 af_glyph_hints_compute_inflections( hints
);
766 af_glyph_hints_save( AF_GlyphHints hints
,
767 FT_Outline
* outline
)
769 AF_Point point
= hints
->points
;
770 AF_Point limit
= point
+ hints
->num_points
;
771 FT_Vector
* vec
= outline
->points
;
772 char* tag
= outline
->tags
;
775 for ( ; point
< limit
; point
++, vec
++, tag
++ )
780 if ( point
->flags
& AF_FLAG_CONIC
)
781 tag
[0] = FT_CURVE_TAG_CONIC
;
782 else if ( point
->flags
& AF_FLAG_CUBIC
)
783 tag
[0] = FT_CURVE_TAG_CUBIC
;
785 tag
[0] = FT_CURVE_TAG_ON
;
790 /****************************************************************
792 * EDGE POINT GRID-FITTING
794 ****************************************************************/
798 af_glyph_hints_align_edge_points( AF_GlyphHints hints
,
801 AF_AxisHints axis
= & hints
->axis
[dim
];
802 AF_Segment segments
= axis
->segments
;
803 AF_Segment segment_limit
= segments
+ axis
->num_segments
;
807 if ( dim
== AF_DIMENSION_HORZ
)
809 for ( seg
= segments
; seg
< segment_limit
; seg
++ )
811 AF_Edge edge
= seg
->edge
;
812 AF_Point point
, first
, last
;
823 point
->x
= edge
->pos
;
824 point
->flags
|= AF_FLAG_TOUCH_X
;
836 for ( seg
= segments
; seg
< segment_limit
; seg
++ )
838 AF_Edge edge
= seg
->edge
;
839 AF_Point point
, first
, last
;
850 point
->y
= edge
->pos
;
851 point
->flags
|= AF_FLAG_TOUCH_Y
;
863 /****************************************************************
865 * STRONG POINT INTERPOLATION
867 ****************************************************************/
870 /* hint the strong points -- this is equivalent to the TrueType `IP' */
871 /* hinting instruction */
874 af_glyph_hints_align_strong_points( AF_GlyphHints hints
,
877 AF_Point points
= hints
->points
;
878 AF_Point point_limit
= points
+ hints
->num_points
;
879 AF_AxisHints axis
= &hints
->axis
[dim
];
880 AF_Edge edges
= axis
->edges
;
881 AF_Edge edge_limit
= edges
+ axis
->num_edges
;
885 if ( dim
== AF_DIMENSION_HORZ
)
886 touch_flag
= AF_FLAG_TOUCH_X
;
888 touch_flag
= AF_FLAG_TOUCH_Y
;
890 if ( edges
< edge_limit
)
896 for ( point
= points
; point
< point_limit
; point
++ )
898 FT_Pos u
, ou
, fu
; /* point position */
902 if ( point
->flags
& touch_flag
)
905 /* if this point is candidate to weak interpolation, we */
906 /* interpolate it after all strong points have been processed */
908 if ( ( point
->flags
& AF_FLAG_WEAK_INTERPOLATION
) &&
909 !( point
->flags
& AF_FLAG_INFLECTION
) )
912 if ( dim
== AF_DIMENSION_VERT
)
925 /* is the point before the first edge? */
927 delta
= edge
->fpos
- u
;
930 u
= edge
->pos
- ( edge
->opos
- ou
);
934 /* is the point after the last edge? */
935 edge
= edge_limit
- 1;
936 delta
= u
- edge
->fpos
;
939 u
= edge
->pos
+ ( ou
- edge
->opos
);
944 FT_PtrDist min
, max
, mid
;
948 /* find enclosing edges */
950 max
= edge_limit
- edges
;
953 /* for small edge counts, a linear search is better */
958 for ( nn
= 0; nn
< max
; nn
++ )
959 if ( edges
[nn
].fpos
>= u
)
962 if ( edges
[nn
].fpos
== u
)
973 mid
= ( max
+ min
) >> 1;
983 /* we are on the edge */
990 AF_Edge before
= edges
+ min
- 1;
991 AF_Edge after
= edges
+ min
+ 0;
994 /* assert( before && after && before != after ) */
995 if ( before
->scale
== 0 )
996 before
->scale
= FT_DivFix( after
->pos
- before
->pos
,
997 after
->fpos
- before
->fpos
);
999 u
= before
->pos
+ FT_MulFix( fu
- before
->fpos
,
1005 /* save the point position */
1006 if ( dim
== AF_DIMENSION_HORZ
)
1011 point
->flags
|= touch_flag
;
1017 /****************************************************************
1019 * WEAK POINT INTERPOLATION
1021 ****************************************************************/
1025 af_iup_shift( AF_Point p1
,
1030 FT_Pos delta
= ref
->u
- ref
->v
;
1035 for ( p
= p1
; p
< ref
; p
++ )
1036 p
->u
= p
->v
+ delta
;
1038 for ( p
= ref
+ 1; p
<= p2
; p
++ )
1039 p
->u
= p
->v
+ delta
;
1044 af_iup_interp( AF_Point p1
,
1051 FT_Pos v1
= ref1
->v
;
1052 FT_Pos v2
= ref2
->v
;
1053 FT_Pos d1
= ref1
->u
- v1
;
1054 FT_Pos d2
= ref2
->u
- v2
;
1062 for ( p
= p1
; p
<= p2
; p
++ )
1078 for ( p
= p1
; p
<= p2
; p
++ )
1087 u
= ref1
->u
+ FT_MulDiv( u
- v1
, ref2
->u
- ref1
->u
, v2
- v1
);
1094 for ( p
= p1
; p
<= p2
; p
++ )
1103 u
= ref1
->u
+ FT_MulDiv( u
- v1
, ref2
->u
- ref1
->u
, v2
- v1
);
1111 FT_LOCAL_DEF( void )
1112 af_glyph_hints_align_weak_points( AF_GlyphHints hints
,
1115 AF_Point points
= hints
->points
;
1116 AF_Point point_limit
= points
+ hints
->num_points
;
1117 AF_Point
* contour
= hints
->contours
;
1118 AF_Point
* contour_limit
= contour
+ hints
->num_contours
;
1119 AF_Flags touch_flag
;
1122 AF_Point first_point
;
1125 /* PASS 1: Move segment points to edge positions */
1127 if ( dim
== AF_DIMENSION_HORZ
)
1129 touch_flag
= AF_FLAG_TOUCH_X
;
1131 for ( point
= points
; point
< point_limit
; point
++ )
1133 point
->u
= point
->x
;
1134 point
->v
= point
->ox
;
1139 touch_flag
= AF_FLAG_TOUCH_Y
;
1141 for ( point
= points
; point
< point_limit
; point
++ )
1143 point
->u
= point
->y
;
1144 point
->v
= point
->oy
;
1150 for ( ; contour
< contour_limit
; contour
++ )
1152 AF_Point first_touched
, last_touched
;
1156 end_point
= point
->prev
;
1157 first_point
= point
;
1159 /* find first touched point */
1162 if ( point
> end_point
) /* no touched point in contour */
1165 if ( point
->flags
& touch_flag
)
1171 first_touched
= point
;
1172 last_touched
= point
;
1176 FT_ASSERT( point
<= end_point
&&
1177 ( point
->flags
& touch_flag
) != 0 );
1179 /* skip any touched neighbhours */
1180 while ( point
< end_point
&& ( point
[1].flags
& touch_flag
) != 0 )
1183 last_touched
= point
;
1185 /* find the next touched point, if any */
1189 if ( point
> end_point
)
1192 if ( ( point
->flags
& touch_flag
) != 0 )
1198 /* interpolate between last_touched and point */
1199 af_iup_interp( last_touched
+ 1, point
- 1,
1200 last_touched
, point
);
1204 /* special case: only one point was touched */
1205 if ( last_touched
== first_touched
)
1207 af_iup_shift( first_point
, end_point
, first_touched
);
1209 else /* interpolate the last part */
1211 if ( last_touched
< end_point
)
1212 af_iup_interp( last_touched
+ 1, end_point
,
1213 last_touched
, first_touched
);
1215 if ( first_touched
> points
)
1216 af_iup_interp( first_point
, first_touched
- 1,
1217 last_touched
, first_touched
);
1224 /* now save the interpolated values back to x/y */
1225 if ( dim
== AF_DIMENSION_HORZ
)
1227 for ( point
= points
; point
< point_limit
; point
++ )
1228 point
->x
= point
->u
;
1232 for ( point
= points
; point
< point_limit
; point
++ )
1233 point
->y
= point
->u
;
1238 #ifdef AF_USE_WARPER
1240 FT_LOCAL_DEF( void )
1241 af_glyph_hints_scale_dim( AF_GlyphHints hints
,
1246 AF_Point points
= hints
->points
;
1247 AF_Point points_limit
= points
+ hints
->num_points
;
1251 if ( dim
== AF_DIMENSION_HORZ
)
1253 for ( point
= points
; point
< points_limit
; point
++ )
1254 point
->x
= FT_MulFix( point
->fx
, scale
) + delta
;
1258 for ( point
= points
; point
< points_limit
; point
++ )
1259 point
->y
= FT_MulFix( point
->fy
, scale
) + delta
;
1263 #endif /* AF_USE_WARPER */