diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c index be832ab..a0bc4a2 100644 --- a/src/autofit/afhints.c +++ b/src/autofit/afhints.c @@ -453,7 +453,8 @@ FT_LOCAL_DEF( AF_Direction ) af_direction_compute( FT_Pos dx, - FT_Pos dy ) + FT_Pos dy, + FT_Int dir_scale ) { FT_Pos ll, ss; /* long and short arm lengths */ AF_Direction dir; /* candidate direction */ @@ -492,7 +493,7 @@ /* return no direction if arm lengths differ too much */ /* (value 14 is heuristic) */ - ss *= 14; + ss *= dir_scale; if ( FT_ABS( ll ) <= FT_ABS( ss ) ) dir = AF_DIR_NONE; @@ -560,6 +561,55 @@ } + /* Find a suitable dir_scale based on distant from next on curve point. */ + + FT_LOCAL_DEF( FT_Int ) + find_dir_scale( AF_Point point, + AF_Point point_limit, + AF_Point head ) + { + FT_Pos dx, dy, ss, ll; + AF_Point next_on; + FT_Int dir_scale = 14; + + /* FIXME: 100 is obviously arbitrary picked. should + * be something like 1.5 ~ 2 times of stem width. */ + FT_Pos stem_width = 100*2; + + if ( point->flags & AF_FLAG_CONTROL ) + return dir_scale; + + for ( next_on = point->next; next_on < point_limit; next_on++ ) + { + if ( ! ( next_on->flags & AF_FLAG_CONTROL ) ) + { + break; + } + } + /*printf( "%p, %p, %p\n", + * (void*)next_on, (void*)point_limit, (void*)head ); + */ + if ( next_on >= point_limit ) + next_on = head; /* return to first point. */ + + dx = FT_ABS( point->fx - next_on->fx ); + dy = FT_ABS( point->fy - next_on->fy ); + ss = FT_MIN( dx, dy ); + ll = FT_MAX( dx, dy ); + + if ( ss*14 < ll && ll < stem_width ) + { + dir_scale = 4; /* 1/4 ~= tan(14 degree) */ + } + + printf( "dir_scale: %2i x,y: %4i,%4i, nx,ny: %4i,%4i ss,ll: %li,%li\n", + dir_scale, point->fx, point->fy, + next_on->fx, next_on->fy, ss, ll ); + + return dir_scale; + } + + /* Recompute all AF_Point in AF_GlyphHints from the definitions */ /* in a source outline. */ @@ -713,6 +763,7 @@ FT_Pos in_x = 0; FT_Pos in_y = 0; AF_Direction in_dir = AF_DIR_NONE; + FT_Int dir_scale = 14; /* 5 degree of direction slop */ for ( point = points; point < point_limit; point++ ) @@ -723,20 +774,34 @@ if ( point == first ) { + AF_Point prev_on; + for ( prev_on = point->prev; prev_on > point; prev_on-- ) + { + if ( ! ( prev_on->flags & AF_FLAG_CONTROL ) ) + { + break; + } + } + dir_scale = find_dir_scale( prev_on, point_limit, points ); + prev = first->prev; in_x = first->fx - prev->fx; in_y = first->fy - prev->fy; - in_dir = af_direction_compute( in_x, in_y ); + in_dir = af_direction_compute( in_x, in_y, dir_scale ); first = prev + 1; } point->in_dir = (FT_Char)in_dir; + /* Use the same dir_scale between on curve points. */ + if ( ! ( point->flags & AF_FLAG_CONTROL ) ) + dir_scale = find_dir_scale( point, point_limit, points ); + next = point->next; out_x = next->fx - point->fx; out_y = next->fy - point->fy; - in_dir = af_direction_compute( out_x, out_y ); + in_dir = af_direction_compute( out_x, out_y, dir_scale ); point->out_dir = (FT_Char)in_dir; /* check for weak points */