ref: c136b409eb0a9a9e5ffeb27ee0488ea4c7e0f09b
parent: 08c3875589d6cc419be17050d39c8e3641d64373
author: David Turner <[email protected]>
date: Thu May 4 13:24:54 EDT 2000
an update to FT_Outline_Funcs used to improve the accuracy of outline decomposition
--- a/include/ftimage.h
+++ b/include/ftimage.h
@@ -467,6 +467,9 @@
FT_Outline_ConicTo_Func conic_to;
FT_Outline_CubicTo_Func cubic_to;
+ int shift;
+ FT_Pos delta;
+
} FT_Outline_Funcs;
--- a/src/base/ftgrays.c
+++ b/src/base/ftgrays.c
@@ -1241,7 +1241,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
};
TBand bands[40], *band;
--- a/src/base/ftoutln.c
+++ b/src/base/ftoutln.c
@@ -56,11 +56,200 @@
/* <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,
+ void* user )
+ {
typedef enum _phases
{
phase_point,
@@ -224,7 +413,7 @@
Invalid_Outline:
return -1;
}
-
+#endif
/*************************************************************************/
/* */
--- a/src/base/ftraster.c
+++ b/src/base/ftraster.c
@@ -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 */