|
|
|
@ -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 |
|
|
|
|
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
/* */ |
|
|
|
|