an update to FT_Outline_Funcs used to improve
the accuracy of outline decomposition
This commit is contained in:
parent
08c3875589
commit
c136b409eb
@ -467,6 +467,9 @@
|
||||
FT_Outline_ConicTo_Func conic_to;
|
||||
FT_Outline_CubicTo_Func cubic_to;
|
||||
|
||||
int shift;
|
||||
FT_Pos delta;
|
||||
|
||||
} FT_Outline_Funcs;
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user