an update to FT_Outline_Funcs used to improve

the accuracy of outline decomposition
This commit is contained in:
David Turner 2000-05-04 17:24:54 +00:00
parent 08c3875589
commit c136b409eb
4 changed files with 199 additions and 3 deletions

View File

@ -467,6 +467,9 @@
FT_Outline_ConicTo_Func conic_to;
FT_Outline_CubicTo_Func cubic_to;
int shift;
FT_Pos delta;
} FT_Outline_Funcs;

View File

@ -1241,7 +1241,9 @@ int check_sort( PCell cells, int count )
(FT_Outline_MoveTo_Func)Move_To,
(FT_Outline_LineTo_Func)Line_To,
(FT_Outline_ConicTo_Func)Conic_To,
(FT_Outline_CubicTo_Func)Cubic_To
(FT_Outline_CubicTo_Func)Cubic_To,
0,
0
};
TBand bands[40], *band;

View File

@ -56,6 +56,195 @@
/* <Return> */
/* Error code. 0 means sucess. */
/* */
#if 1
EXPORT_FUNC
int FT_Outline_Decompose( FT_Outline* outline,
FT_Outline_Funcs* interface,
void* user )
{
#undef SCALED
#define SCALED( x ) ( ((x) << shift) - delta )
FT_Vector v_last;
FT_Vector v_control;
FT_Vector v_start;
FT_Vector* point;
FT_Vector* limit;
char* tags;
int n; /* index of contour in outline */
int first; /* index of first point in contour */
int error;
char tag; /* current point's state */
int shift = interface->shift;
FT_Pos delta = interface->delta;
first = 0;
for ( n = 0; n < outline->n_contours; n++ )
{
int last; /* index of last point in contour */
last = outline->contours[n];
limit = outline->points + last;
v_start = outline->points[first];
v_last = outline->points[last];
v_start.x = SCALED(v_start.x); v_start.y = SCALED(v_start.y);
v_last.x = SCALED(v_last.x); v_last.y = SCALED(v_last.y);
v_control = v_start;
point = outline->points + first;
tags = outline->tags + first;
tag = FT_CURVE_TAG( tags[0] );
/* A contour cannot start with a cubic control point! */
if ( tag == FT_Curve_Tag_Cubic )
goto Invalid_Outline;
/* check first point to determine origin */
if ( tag == FT_Curve_Tag_Conic )
{
/* first point is conic control. Yes, this happens. */
if ( FT_CURVE_TAG( outline->tags[last] ) == FT_Curve_Tag_On )
{
/* start at last point if it is on the curve */
v_start = v_last;
limit--;
}
else
{
/* if both first and last points are conic, */
/* start at their middle and record its position */
/* for closure */
v_start.x = ( v_start.x + v_last.x ) / 2;
v_start.y = ( v_start.y + v_last.y ) / 2;
v_last = v_start;
}
point--;
tags--;
}
error = interface->move_to( &v_start, user );
if (error) goto Exit;
while (point < limit)
{
point++;
tags++;
tag = FT_CURVE_TAG( tags[0] );
switch (tag)
{
case FT_Curve_Tag_On: /* emit a single line_to */
{
FT_Vector vec;
vec.x = SCALED(point->x);
vec.y = SCALED(point->y);
error = interface->line_to( &vec, user );
if (error) goto Exit;
continue;
}
case FT_Curve_Tag_Conic: /* consume conic arcs */
{
v_control.x = SCALED(point->x);
v_control.y = SCALED(point->y);
Do_Conic:
if (point < limit)
{
FT_Vector vec;
FT_Vector v_middle;
point++;
tags++;
tag = FT_CURVE_TAG( tags[0] );
vec.x = SCALED(point->x);
vec.y = SCALED(point->y);
if (tag == FT_Curve_Tag_On)
{
error = interface->conic_to( &v_control, &vec, user );
if (error) goto Exit;
continue;
}
if (tag != FT_Curve_Tag_Conic)
goto Invalid_Outline;
v_middle.x = (v_control.x + vec.x)/2;
v_middle.y = (v_control.y + vec.y)/2;
error = interface->conic_to( &v_control, &v_middle, user );
if (error) goto Exit;
v_control = vec;
goto Do_Conic;
}
error = interface->conic_to( &v_control, &v_start, user );
goto Close;
}
default: /* FT_Curve_Tag_Cubic */
{
FT_Vector vec1, vec2;
if ( point+1 > limit ||
FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic )
goto Invalid_Outline;
point += 2;
tags += 2;
vec1.x = SCALED(point[-2].x); vec1.y = SCALED(point[-2].y);
vec2.x = SCALED(point[-1].x); vec2.y = SCALED(point[-1].y);
if (point <= limit)
{
FT_Vector vec;
vec.x = SCALED(point->x);
vec.y = SCALED(point->y);
error = interface->cubic_to( &vec1, &vec2, &vec, user );
if (error) goto Exit;
continue;
}
error = interface->cubic_to( &vec1, &vec2, &v_start, user );
goto Close;
}
}
}
/* close the contour with a line segment */
error = interface->line_to( &v_start, user );
Close:
if (error) goto Exit;
first = last+1;
}
return 0;
Exit:
return error;
Invalid_Outline:
return -1;
}
#else
EXPORT_FUNC
int FT_Outline_Decompose( FT_Outline* outline,
FT_Outline_Funcs* interface,
@ -224,7 +413,7 @@
Invalid_Outline:
return -1;
}
#endif
/*************************************************************************/
/* */

View File

@ -2283,7 +2283,9 @@
(FT_Outline_MoveTo_Func)Move_To,
(FT_Outline_LineTo_Func)Line_To,
(FT_Outline_ConicTo_Func)Conic_To,
(FT_Outline_CubicTo_Func)Cubic_To
(FT_Outline_CubicTo_Func)Cubic_To,
0,
0
};
/* Set up state in the raster object */