#include "FTContour.h" static const float BEZIER_STEP_SIZE = 0.2f; void FTContour::AddPoint( FTPoint point) { if( pointList.empty() || point != pointList[pointList.size() - 1]) { pointList.push_back( point); } } void FTContour::AddPoint( float x, float y) { AddPoint( FTPoint( x, y, 0.0f)); } void FTContour::evaluateQuadraticCurve() { for( unsigned int i = 0; i <= ( 1.0f / BEZIER_STEP_SIZE); i++) { float bezierValues[2][2]; float t = static_cast(i) * BEZIER_STEP_SIZE; bezierValues[0][0] = (1.0f - t) * controlPoints[0][0] + t * controlPoints[1][0]; bezierValues[0][1] = (1.0f - t) * controlPoints[0][1] + t * controlPoints[1][1]; bezierValues[1][0] = (1.0f - t) * controlPoints[1][0] + t * controlPoints[2][0]; bezierValues[1][1] = (1.0f - t) * controlPoints[1][1] + t * controlPoints[2][1]; bezierValues[0][0] = (1.0f - t) * bezierValues[0][0] + t * bezierValues[1][0]; bezierValues[0][1] = (1.0f - t) * bezierValues[0][1] + t * bezierValues[1][1]; AddPoint( bezierValues[0][0], bezierValues[0][1]); } } void FTContour::evaluateCubicCurve() { for( unsigned int i = 0; i <= ( 1.0f / BEZIER_STEP_SIZE); i++) { float bezierValues[3][2]; float t = static_cast(i) * BEZIER_STEP_SIZE; bezierValues[0][0] = (1.0f - t) * controlPoints[0][0] + t * controlPoints[1][0]; bezierValues[0][1] = (1.0f - t) * controlPoints[0][1] + t * controlPoints[1][1]; bezierValues[1][0] = (1.0f - t) * controlPoints[1][0] + t * controlPoints[2][0]; bezierValues[1][1] = (1.0f - t) * controlPoints[1][1] + t * controlPoints[2][1]; bezierValues[2][0] = (1.0f - t) * controlPoints[2][0] + t * controlPoints[3][0]; bezierValues[2][1] = (1.0f - t) * controlPoints[2][1] + t * controlPoints[3][1]; bezierValues[0][0] = (1.0f - t) * bezierValues[0][0] + t * bezierValues[1][0]; bezierValues[0][1] = (1.0f - t) * bezierValues[0][1] + t * bezierValues[1][1]; bezierValues[1][0] = (1.0f - t) * bezierValues[1][0] + t * bezierValues[2][0]; bezierValues[1][1] = (1.0f - t) * bezierValues[1][1] + t * bezierValues[2][1]; bezierValues[0][0] = (1.0f - t) * bezierValues[0][0] + t * bezierValues[1][0]; bezierValues[0][1] = (1.0f - t) * bezierValues[0][1] + t * bezierValues[1][1]; AddPoint( bezierValues[0][0], bezierValues[0][1]); } } FTContour::FTContour( FT_Vector* contour, char* pointTags, unsigned int numberOfPoints) { for( unsigned int pointIndex = 0; pointIndex < numberOfPoints; ++ pointIndex) { char pointTag = pointTags[pointIndex]; if( pointTag == FT_Curve_Tag_On || numberOfPoints < 2) { AddPoint( contour[pointIndex].x, contour[pointIndex].y); continue; } FTPoint controlPoint( contour[pointIndex]); FTPoint previousPoint = ( 0 == pointIndex) ? FTPoint( contour[numberOfPoints - 1]) : pointList[pointList.size() - 1]; FTPoint nextPoint = ( pointIndex == numberOfPoints - 1) ? pointList[0] : FTPoint( contour[pointIndex + 1]); if( pointTag == FT_Curve_Tag_Conic) { char nextPointTag = ( pointIndex == numberOfPoints - 1) ? pointTags[0] : pointTags[pointIndex + 1]; while( nextPointTag == FT_Curve_Tag_Conic) { nextPoint = ( controlPoint + nextPoint) * 0.5f; controlPoints[0][0] = previousPoint.X(); controlPoints[0][1] = previousPoint.Y(); controlPoints[1][0] = controlPoint.X(); controlPoints[1][1] = controlPoint.Y(); controlPoints[2][0] = nextPoint.X(); controlPoints[2][1] = nextPoint.Y(); evaluateQuadraticCurve(); ++pointIndex; previousPoint = nextPoint; controlPoint = FTPoint( contour[pointIndex]); nextPoint = ( pointIndex == numberOfPoints - 1) ? pointList[0] : FTPoint( contour[pointIndex + 1]); nextPointTag = ( pointIndex == numberOfPoints - 1) ? pointTags[0] : pointTags[pointIndex + 1]; } controlPoints[0][0] = previousPoint.X(); controlPoints[0][1] = previousPoint.Y(); controlPoints[1][0] = controlPoint.X(); controlPoints[1][1] = controlPoint.Y(); controlPoints[2][0] = nextPoint.X(); controlPoints[2][1] = nextPoint.Y(); evaluateQuadraticCurve(); continue; } if( pointTag == FT_Curve_Tag_Cubic) { FTPoint controlPoint2 = nextPoint; FTPoint nextPoint = ( pointIndex == numberOfPoints - 2) ? pointList[0] : FTPoint( contour[pointIndex + 2]); controlPoints[0][0] = previousPoint.X(); controlPoints[0][1] = previousPoint.Y(); controlPoints[1][0] = controlPoint.X(); controlPoints[1][1] = controlPoint.Y(); controlPoints[2][0] = controlPoint2.X(); controlPoints[2][1] = controlPoint2.Y(); controlPoints[3][0] = nextPoint.X(); controlPoints[3][1] = nextPoint.Y(); evaluateCubicCurve(); ++pointIndex; continue; } } }