* src/pshinter/pshalgo.c: major speed improvements to the Postscript
hinter, more than 100% speed increase on my machine
This commit is contained in:
parent
b9e6d69a96
commit
e140f14232
@ -1,3 +1,8 @@
|
||||
2006-10-23 David Turner <david@freetype.org>
|
||||
|
||||
* src/pshinter/pshalgo.c: major speed improvements to the Postscript
|
||||
hinter, more than 100% speed increase on my machine
|
||||
|
||||
2006-10-15 suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
|
||||
|
||||
* src/base/ftmac.c (FT_New_Face_From_FOND): Initialize variable
|
||||
@ -65,7 +70,7 @@
|
||||
auto-hinting shall be used or not.
|
||||
|
||||
* src/truetype/ttobjs.c (tt_face_init): Ditto.
|
||||
|
||||
|
||||
2006-09-30 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
* src/base/rules.mk (BASE_SRC): Remove `ftapi.c' (which is no longer
|
||||
@ -95,7 +100,7 @@
|
||||
* include/freetype/freetype.h (FT_FREETYPE_PATCH): Set to 2.
|
||||
|
||||
|
||||
Add a new API to support color filtering of subpixel glyph bitmaps.
|
||||
Add a new API to support color filtering of subpixel glyph bitmaps.
|
||||
In a default build, the function `FT_Library_SetLcdFilter' returns
|
||||
`FT_Err_Unimplemented_Feature'; you need to #define
|
||||
FT_CONFIG_OPTION_SUBPIXEL_RENDERING in ftoption.h to compile the
|
||||
|
@ -879,8 +879,96 @@
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
||||
FT_LOCAL_DEF( FT_Int )
|
||||
psh_corner_is_flat( FT_Pos x_in,
|
||||
FT_Pos y_in,
|
||||
FT_Pos x_out,
|
||||
FT_Pos y_out )
|
||||
{
|
||||
FT_Pos ax = x_in;
|
||||
FT_Pos ay = y_in;
|
||||
|
||||
FT_Pos d_in, d_out, d_corner;
|
||||
|
||||
|
||||
if ( ax < 0 )
|
||||
ax = -ax;
|
||||
if ( ay < 0 )
|
||||
ay = -ay;
|
||||
d_in = ax + ay;
|
||||
|
||||
ax = x_out;
|
||||
if ( ax < 0 )
|
||||
ax = -ax;
|
||||
ay = y_out;
|
||||
if ( ay < 0 )
|
||||
ay = -ay;
|
||||
d_out = ax + ay;
|
||||
|
||||
ax = x_out + x_in;
|
||||
if ( ax < 0 )
|
||||
ax = -ax;
|
||||
ay = y_out + y_in;
|
||||
if ( ay < 0 )
|
||||
ay = -ay;
|
||||
d_corner = ax + ay;
|
||||
|
||||
return ( d_in + d_out - d_corner ) < ( d_corner >> 4 );
|
||||
}
|
||||
|
||||
|
||||
#ifdef COMPUTE_INFLEXS
|
||||
|
||||
static FT_Int
|
||||
psh_corner_orientation( FT_Pos in_x,
|
||||
FT_Pos in_y,
|
||||
FT_Pos out_x,
|
||||
FT_Pos out_y )
|
||||
{
|
||||
FT_Int result;
|
||||
|
||||
/* deal with the trivial cases quickly */
|
||||
if ( in_y == 0 )
|
||||
{
|
||||
if ( in_x >= 0 )
|
||||
result = out_y;
|
||||
else
|
||||
result = -out_y;
|
||||
}
|
||||
else if ( in_x == 0 )
|
||||
{
|
||||
if ( in_y >= 0 )
|
||||
result = -out_x;
|
||||
else
|
||||
result = out_x;
|
||||
}
|
||||
else if ( out_y == 0 )
|
||||
{
|
||||
if ( out_x >= 0 )
|
||||
result = in_y;
|
||||
else
|
||||
result = -in_y;
|
||||
}
|
||||
else if ( out_x == 0 )
|
||||
{
|
||||
if ( out_y >= 0 )
|
||||
result = -in_x;
|
||||
else
|
||||
result = in_x;
|
||||
}
|
||||
else /* general case */
|
||||
{
|
||||
long long delta = (long long)in_x*out_y - (long long)in_y*out_x;
|
||||
|
||||
if ( delta == 0 )
|
||||
result = 0;
|
||||
else
|
||||
result = 1 - 2*(delta < 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* compute all inflex points in a given glyph */
|
||||
static void
|
||||
psh_glyph_compute_inflections( PSH_Glyph glyph )
|
||||
@ -891,8 +979,8 @@
|
||||
for ( n = 0; n < glyph->num_contours; n++ )
|
||||
{
|
||||
PSH_Point first, start, end, before, after;
|
||||
FT_Angle angle_in, angle_seg, angle_out;
|
||||
FT_Angle diff_in, diff_out;
|
||||
FT_Pos in_x, in_y, out_x, out_y;
|
||||
FT_Int orient_prev, orient_cur;
|
||||
FT_Int finished = 0;
|
||||
|
||||
|
||||
@ -910,9 +998,10 @@
|
||||
if ( end == first )
|
||||
goto Skip;
|
||||
|
||||
} while ( PSH_POINT_EQUAL_ORG( end, first ) );
|
||||
in_x = end->org_u - start->org_u;
|
||||
in_y = end->org_v - start->org_v;
|
||||
|
||||
angle_seg = PSH_POINT_ANGLE( start, end );
|
||||
} while ( in_x == 0 && out_x == 0 );
|
||||
|
||||
/* extend the segment start whenever possible */
|
||||
before = start;
|
||||
@ -925,14 +1014,18 @@
|
||||
if ( before == first )
|
||||
goto Skip;
|
||||
|
||||
} while ( PSH_POINT_EQUAL_ORG( before, start ) );
|
||||
out_x = start->org_u - before->org_u;
|
||||
out_y = start->org_v - before->org_v;
|
||||
|
||||
angle_in = PSH_POINT_ANGLE( before, start );
|
||||
} while ( out_x == 0 && out_y == 0 );
|
||||
|
||||
} while ( angle_in == angle_seg );
|
||||
orient_prev = psh_corner_orientation( in_x, in_y, out_x, out_y );
|
||||
|
||||
} while ( orient_prev != 0 );
|
||||
|
||||
first = start;
|
||||
diff_in = FT_Angle_Diff( angle_in, angle_seg );
|
||||
in_x = out_x;
|
||||
in_y = out_y;
|
||||
|
||||
/* now, process all segments in the contour */
|
||||
do
|
||||
@ -948,19 +1041,17 @@
|
||||
if ( after == first )
|
||||
finished = 1;
|
||||
|
||||
} while ( PSH_POINT_EQUAL_ORG( end, after ) );
|
||||
out_x = after->org_u - end->org_u;
|
||||
out_y = after->org_v - end->org_v;
|
||||
|
||||
angle_out = PSH_POINT_ANGLE( end, after );
|
||||
} while ( out_x == 0 && out_y == 0 );
|
||||
|
||||
} while ( angle_out == angle_seg );
|
||||
orient_cur = psh_corner_orientation( in_x, in_y, out_x, out_y );
|
||||
|
||||
diff_out = FT_Angle_Diff( angle_seg, angle_out );
|
||||
} while ( orient_cur == 0 );
|
||||
|
||||
if ( ( diff_in ^ diff_out ) < 0 )
|
||||
if ( (orient_cur ^ orient_prev) < 0 )
|
||||
{
|
||||
/* diff_in and diff_out have different signs, we have */
|
||||
/* inflection points here... */
|
||||
|
||||
do
|
||||
{
|
||||
psh_point_set_inflex( start );
|
||||
@ -971,10 +1062,11 @@
|
||||
psh_point_set_inflex( start );
|
||||
}
|
||||
|
||||
start = end;
|
||||
end = after;
|
||||
angle_seg = angle_out;
|
||||
diff_in = diff_out;
|
||||
start = end;
|
||||
end = after;
|
||||
orient_prev = orient_cur;
|
||||
in_x = out_x;
|
||||
in_y = out_y;
|
||||
|
||||
} while ( !finished );
|
||||
|
||||
@ -1199,29 +1291,14 @@
|
||||
/* detect smooth points */
|
||||
if ( point->flags & PSH_POINT_OFF )
|
||||
point->flags |= PSH_POINT_SMOOTH;
|
||||
else if ( point->dir_in != PSH_DIR_NONE ||
|
||||
point->dir_out != PSH_DIR_NONE )
|
||||
|
||||
else if ( point->dir_in == point->dir_out )
|
||||
{
|
||||
if ( point->dir_in == point->dir_out )
|
||||
point->flags |= PSH_POINT_SMOOTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
FT_Angle angle_in, angle_out, diff;
|
||||
|
||||
|
||||
angle_in = FT_Atan2( dxi, dyi );
|
||||
angle_out = FT_Atan2( dxo, dyo );
|
||||
|
||||
diff = angle_in - angle_out;
|
||||
if ( diff < 0 )
|
||||
diff = -diff;
|
||||
|
||||
if ( diff > FT_ANGLE_PI )
|
||||
diff = FT_ANGLE_2PI - diff;
|
||||
|
||||
if ( diff < FT_ANGLE_PI / 16 )
|
||||
if ( point->dir_out != PSH_DIR_NONE ||
|
||||
psh_corner_is_flat( dxi, dyi, dxo, dyo ) )
|
||||
{
|
||||
point->flags |= PSH_POINT_SMOOTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1382,115 +1459,138 @@
|
||||
/* -major_dir. */
|
||||
|
||||
static void
|
||||
psh_hint_table_find_strong_point( PSH_Hint_Table table,
|
||||
PSH_Point point,
|
||||
FT_Int threshold,
|
||||
FT_Int major_dir )
|
||||
psh_hint_table_find_strong_points( PSH_Hint_Table table,
|
||||
PSH_Point point,
|
||||
FT_UInt count,
|
||||
FT_Int threshold,
|
||||
FT_Int major_dir )
|
||||
{
|
||||
PSH_Hint* sort = table->sort;
|
||||
FT_UInt num_hints = table->num_hints;
|
||||
FT_Int point_dir = 0;
|
||||
|
||||
|
||||
if ( PSH_DIR_COMPARE( point->dir_in, major_dir ) )
|
||||
point_dir = point->dir_in;
|
||||
|
||||
else if ( PSH_DIR_COMPARE( point->dir_out, major_dir ) )
|
||||
point_dir = point->dir_out;
|
||||
|
||||
if ( point_dir )
|
||||
for ( ; count > 0; count--, point++ )
|
||||
{
|
||||
FT_UInt flag;
|
||||
FT_Int point_dir = 0;
|
||||
FT_Pos org_u = point->org_u;
|
||||
|
||||
if ( psh_point_is_strong( point ) )
|
||||
continue;
|
||||
|
||||
for ( ; num_hints > 0; num_hints--, sort++ )
|
||||
if ( PSH_DIR_COMPARE( point->dir_in, major_dir ) )
|
||||
point_dir = point->dir_in;
|
||||
|
||||
else if ( PSH_DIR_COMPARE( point->dir_out, major_dir ) )
|
||||
point_dir = point->dir_out;
|
||||
|
||||
if ( point_dir )
|
||||
{
|
||||
PSH_Hint hint = sort[0];
|
||||
FT_Pos d;
|
||||
|
||||
|
||||
if ( point_dir == major_dir )
|
||||
{
|
||||
flag = PSH_POINT_EDGE_MIN;
|
||||
d = point->org_u - hint->org_pos;
|
||||
FT_UInt nn;
|
||||
|
||||
if ( FT_ABS( d ) < threshold )
|
||||
for ( nn = 0; nn < num_hints; nn++ )
|
||||
{
|
||||
Is_Strong:
|
||||
psh_point_set_strong( point );
|
||||
point->flags2 |= flag;
|
||||
point->hint = hint;
|
||||
break;
|
||||
PSH_Hint hint = sort[nn];
|
||||
FT_Pos d = org_u - hint->org_pos;
|
||||
|
||||
if ( d < threshold && -d < threshold )
|
||||
{
|
||||
psh_point_set_strong( point );
|
||||
point->flags2 |= PSH_POINT_EDGE_MIN;
|
||||
point->hint = hint;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( point_dir == -major_dir )
|
||||
{
|
||||
flag = PSH_POINT_EDGE_MAX;
|
||||
d = point->org_u - hint->org_pos - hint->org_len;
|
||||
FT_UInt nn;
|
||||
|
||||
if ( FT_ABS( d ) < threshold )
|
||||
goto Is_Strong;
|
||||
for ( nn = 0; nn < num_hints; nn++ )
|
||||
{
|
||||
PSH_Hint hint = sort[nn];
|
||||
FT_Pos d = org_u - hint->org_pos - hint->org_len;
|
||||
|
||||
if ( d < threshold && -d < threshold )
|
||||
{
|
||||
psh_point_set_strong( point );
|
||||
point->flags2 |= PSH_POINT_EDGE_MAX;
|
||||
point->hint = hint;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
else if ( psh_point_is_extremum( point ) )
|
||||
{
|
||||
/* treat extrema as special cases for stem edge alignment */
|
||||
FT_UInt min_flag, max_flag;
|
||||
|
||||
|
||||
if ( major_dir == PSH_DIR_HORIZONTAL )
|
||||
else if ( psh_point_is_extremum( point ) )
|
||||
{
|
||||
min_flag = PSH_POINT_POSITIVE;
|
||||
max_flag = PSH_POINT_NEGATIVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
min_flag = PSH_POINT_NEGATIVE;
|
||||
max_flag = PSH_POINT_POSITIVE;
|
||||
}
|
||||
/* treat extrema as special cases for stem edge alignment */
|
||||
FT_UInt nn, min_flag, max_flag;
|
||||
|
||||
for ( ; num_hints > 0; num_hints--, sort++ )
|
||||
{
|
||||
PSH_Hint hint = sort[0];
|
||||
FT_Pos d;
|
||||
FT_Int flag;
|
||||
|
||||
if ( major_dir == PSH_DIR_HORIZONTAL )
|
||||
{
|
||||
min_flag = PSH_POINT_POSITIVE;
|
||||
max_flag = PSH_POINT_NEGATIVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
min_flag = PSH_POINT_NEGATIVE;
|
||||
max_flag = PSH_POINT_POSITIVE;
|
||||
}
|
||||
|
||||
if ( point->flags2 & min_flag )
|
||||
{
|
||||
flag = PSH_POINT_EDGE_MIN;
|
||||
d = point->org_u - hint->org_pos;
|
||||
|
||||
if ( FT_ABS( d ) < threshold )
|
||||
for ( nn = 0; nn < num_hints; nn++ )
|
||||
{
|
||||
Is_Strong2:
|
||||
point->flags2 |= flag;
|
||||
point->hint = hint;
|
||||
psh_point_set_strong( point );
|
||||
break;
|
||||
PSH_Hint hint = sort[nn];
|
||||
FT_Pos d = org_u - hint->org_pos;
|
||||
|
||||
if ( d < threshold && -d < threshold )
|
||||
{
|
||||
point->flags2 |= PSH_POINT_EDGE_MIN;
|
||||
point->hint = hint;
|
||||
psh_point_set_strong( point );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( point->flags2 & max_flag )
|
||||
{
|
||||
flag = PSH_POINT_EDGE_MAX;
|
||||
d = point->org_u - hint->org_pos - hint->org_len;
|
||||
for ( nn = 0; nn < num_hints; nn++ )
|
||||
{
|
||||
PSH_Hint hint = sort[nn];
|
||||
FT_Pos d = org_u - hint->org_pos - hint->org_len;
|
||||
|
||||
if ( FT_ABS( d ) < threshold )
|
||||
goto Is_Strong2;
|
||||
if ( d < threshold && -d < threshold )
|
||||
{
|
||||
point->flags2 |= PSH_POINT_EDGE_MAX;
|
||||
point->hint = hint;
|
||||
psh_point_set_strong( point );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( point->org_u >= hint->org_pos &&
|
||||
point->org_u <= hint->org_pos + hint->org_len )
|
||||
if ( point->hint == NULL )
|
||||
{
|
||||
point->hint = hint;
|
||||
for ( nn = 0; nn < num_hints; nn++ )
|
||||
{
|
||||
PSH_Hint hint = sort[nn];
|
||||
|
||||
if ( org_u >= hint->org_pos &&
|
||||
org_u <= hint->org_pos + hint->org_len )
|
||||
{
|
||||
point->hint = hint;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* 1 */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1544,9 +1644,8 @@
|
||||
|
||||
psh_hint_table_activate_mask( table, mask );
|
||||
|
||||
for ( ; count > 0; count--, point++ )
|
||||
psh_hint_table_find_strong_point( table, point,
|
||||
threshold, major_dir );
|
||||
psh_hint_table_find_strong_points( table, point, count,
|
||||
threshold, major_dir );
|
||||
}
|
||||
first = next;
|
||||
}
|
||||
@ -1560,12 +1659,9 @@
|
||||
|
||||
|
||||
psh_hint_table_activate_mask( table, table->hint_masks->masks );
|
||||
for ( ; count > 0; count--, point++ )
|
||||
{
|
||||
if ( !psh_point_is_strong( point ) )
|
||||
psh_hint_table_find_strong_point( table, point,
|
||||
threshold, major_dir );
|
||||
}
|
||||
|
||||
psh_hint_table_find_strong_points( table, point, count,
|
||||
threshold, major_dir );
|
||||
}
|
||||
|
||||
/* now, certain points may have been attached to a hint and */
|
||||
@ -1710,6 +1806,8 @@
|
||||
}
|
||||
|
||||
|
||||
#define PSH_MAX_STRONG_INTERNAL 16
|
||||
|
||||
static void
|
||||
psh_glyph_interpolate_normal_points( PSH_Glyph glyph,
|
||||
FT_Int dimension )
|
||||
@ -1718,14 +1816,60 @@
|
||||
#if 1
|
||||
/* first technique: a point is strong if it is a local extremum */
|
||||
|
||||
PSH_Dimension dim = &glyph->globals->dimension[dimension];
|
||||
FT_Fixed scale = dim->scale_mult;
|
||||
PSH_Dimension dim = &glyph->globals->dimension[dimension];
|
||||
FT_Fixed scale = dim->scale_mult;
|
||||
FT_Memory memory = glyph->memory;
|
||||
|
||||
FT_UInt count = glyph->num_points;
|
||||
PSH_Point point = glyph->points;
|
||||
PSH_Point* strongs = NULL;
|
||||
PSH_Point strongs_0[ PSH_MAX_STRONG_INTERNAL ];
|
||||
FT_UInt num_strongs = 0;
|
||||
|
||||
PSH_Point points = glyph->points;
|
||||
PSH_Point points_end = points + glyph->num_points;
|
||||
PSH_Point point;
|
||||
|
||||
for ( ; count > 0; count--, point++ )
|
||||
/* first count the number of strong points */
|
||||
for ( point = points; point < points_end; point++ )
|
||||
{
|
||||
if ( psh_point_is_strong( point ) )
|
||||
num_strongs++;
|
||||
}
|
||||
|
||||
if ( num_strongs == 0 ) /* nothing to do here */
|
||||
return;
|
||||
|
||||
/* allocate an array to store a list of points, stored in increasing org_u order */
|
||||
if ( num_strongs <= PSH_MAX_STRONG_INTERNAL )
|
||||
strongs = strongs_0;
|
||||
else
|
||||
{
|
||||
FT_Error error;
|
||||
|
||||
if ( !FT_NEW_ARRAY( strongs, num_strongs ) )
|
||||
return;
|
||||
}
|
||||
|
||||
num_strongs = 0;
|
||||
for ( point = points; point < points_end; point++ )
|
||||
{
|
||||
PSH_Point* insert;
|
||||
|
||||
if ( !psh_point_is_strong( point ) )
|
||||
continue;
|
||||
|
||||
for ( insert = strongs + num_strongs; insert > strongs; insert-- )
|
||||
{
|
||||
if ( insert[-1]->org_u <= point->org_u )
|
||||
break;
|
||||
|
||||
insert[0] = insert[-1];
|
||||
}
|
||||
insert[0] = point;
|
||||
num_strongs++;
|
||||
}
|
||||
|
||||
/* now try to interpolate all normal points */
|
||||
for ( point = points; point < points_end; point++ )
|
||||
{
|
||||
if ( psh_point_is_strong( point ) )
|
||||
continue;
|
||||
@ -1744,82 +1888,65 @@
|
||||
point->flags &= ~PSH_POINT_SMOOTH;
|
||||
}
|
||||
|
||||
/* find best enclosing point coordinates */
|
||||
/* find best enclosing point coordinates then interpolate */
|
||||
{
|
||||
PSH_Point before = 0;
|
||||
PSH_Point after = 0;
|
||||
PSH_Point before, after;
|
||||
FT_UInt nn;
|
||||
|
||||
FT_Pos diff_before = -32000;
|
||||
FT_Pos diff_after = 32000;
|
||||
FT_Pos u = point->org_u;
|
||||
for ( nn = 0; nn < num_strongs; nn++ )
|
||||
if ( strongs[nn]->org_u > point->org_u )
|
||||
break;
|
||||
|
||||
FT_Int count2 = glyph->num_points;
|
||||
PSH_Point cur = glyph->points;
|
||||
|
||||
|
||||
for ( ; count2 > 0; count2--, cur++ )
|
||||
if ( nn == 0 ) /* point before the first strong point */
|
||||
{
|
||||
if ( psh_point_is_strong( cur ) )
|
||||
{
|
||||
FT_Pos diff = cur->org_u - u;
|
||||
after = strongs[0];
|
||||
|
||||
|
||||
if ( diff <= 0 )
|
||||
{
|
||||
if ( diff > diff_before )
|
||||
{
|
||||
diff_before = diff;
|
||||
before = cur;
|
||||
}
|
||||
}
|
||||
|
||||
else if ( diff >= 0 )
|
||||
{
|
||||
if ( diff < diff_after )
|
||||
{
|
||||
diff_after = diff;
|
||||
after = cur;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !before )
|
||||
{
|
||||
if ( !after )
|
||||
continue;
|
||||
|
||||
/* we are before the first strong point coordinate; */
|
||||
/* simply translate the point */
|
||||
point->cur_u = after->cur_u +
|
||||
FT_MulFix( point->org_u - after->org_u, scale );
|
||||
}
|
||||
else if ( !after )
|
||||
{
|
||||
/* we are after the last strong point coordinate; */
|
||||
/* simply translate the point */
|
||||
point->cur_u = before->cur_u +
|
||||
FT_MulFix( point->org_u - before->org_u, scale );
|
||||
FT_MulFix( point->org_u - after->org_u, scale );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( diff_before == 0 )
|
||||
point->cur_u = before->cur_u;
|
||||
before = strongs[nn-1];
|
||||
|
||||
else if ( diff_after == 0 )
|
||||
point->cur_u = after->cur_u;
|
||||
for ( nn = num_strongs; nn > 0; nn-- )
|
||||
if ( strongs[nn-1]->org_u < point->org_u )
|
||||
break;
|
||||
|
||||
if ( nn == num_strongs ) /* point is after last strong point */
|
||||
{
|
||||
before = strongs[nn-1];
|
||||
|
||||
else
|
||||
point->cur_u = before->cur_u +
|
||||
FT_MulDiv( u - before->org_u,
|
||||
after->cur_u - before->cur_u,
|
||||
after->org_u - before->org_u );
|
||||
}
|
||||
FT_MulFix( point->org_u - before->org_u, scale );
|
||||
}
|
||||
else
|
||||
{
|
||||
FT_Pos u;
|
||||
|
||||
after = strongs[nn];
|
||||
|
||||
/* now interpolate point between before and after */
|
||||
u = point->org_u;
|
||||
|
||||
if ( u == before->org_u )
|
||||
point->cur_u = before->cur_u;
|
||||
|
||||
else if ( u == after->org_u )
|
||||
point->cur_u = after->cur_u;
|
||||
|
||||
else
|
||||
point->cur_u = before->cur_u +
|
||||
FT_MulDiv( u - before->org_u,
|
||||
after->cur_u - before->cur_u,
|
||||
after->org_u - before->org_u );
|
||||
}
|
||||
}
|
||||
psh_point_set_fitted( point );
|
||||
}
|
||||
}
|
||||
|
||||
if ( strongs != strongs_0 )
|
||||
FT_FREE( strongs );
|
||||
#endif /* 1 */
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user