Commit 739dac83b2fb5f1c1a28fa09e440fe03d6ea8ec4

henry 2002-12-08T04:37:28

Moved from FTVectoriser to own file

diff --git a/include/FTContour.h b/include/FTContour.h
new file mode 100644
index 0000000..2fdf779
--- /dev/null
+++ b/include/FTContour.h
@@ -0,0 +1,131 @@
+#ifndef     __FTContour__
+#define     __FTContour__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_GLYPH_H
+
+#include "FTPoint.h"
+#include "FTVector.h"
+#include "FTGL.h"
+
+
+struct ContourPoint
+{
+    ContourPoint(){}
+    
+    ContourPoint( FTPoint p, char t)
+    :   point(p),
+        tag(t)
+    {}
+    
+    FTPoint point;
+    char tag;
+};
+
+/**
+ * FTContour class is a container of points that describe a vector font
+ * outline. It is used as a container for the output of the bezier curve
+ * evaluator in FTVectoriser.
+ *
+ * @see FTOutlineGlyph
+ * @see FTPolyGlyph
+ * @see FTPoint
+ */
+class FTGL_EXPORT FTContour
+{
+    public:
+        /**
+         *  Constructor
+         *
+         * @param contour
+         * @param pointTags
+         * @param numberOfPoints
+         */
+        FTContour( FT_Vector* contour, char* pointTags, unsigned int numberOfPoints);
+
+        /**
+         *  Destructor
+         */
+        ~FTContour()
+        {
+            pointList.clear();
+        }
+
+        /**
+         * How many points define this contour
+         *
+         * @return the number of points in this contour
+         */
+        size_t size() const { return pointList.size();}
+        
+        /**
+         * How many points define this contour
+         *
+         * @return the number of points in this contour
+         */
+        size_t Points() const { return size();}
+
+        // FIXME make private
+        /**
+         *  The list of points in this contour
+         */
+        typedef FTVector<FTPoint> PointVector;
+        PointVector pointList;
+        
+    private:
+        /**
+         * Add a point to this contour. This functional tests for duplicate
+         * points.
+         *
+         * @param point The point to be added to the contour.
+         */
+        void AddPoint( FTPoint point);
+
+        /**
+         * Process a conic (second order) bezier curve.
+         *
+         * @param index
+         * @param pointList
+         */
+        void EvaluateConicCurve( const int index, const FTVector<ContourPoint>& pointList);
+
+        /**
+         * Process a cubic (third order) bezier curve.
+         *
+         * @param index
+         * @param pointList
+         */
+        void EvaluateCubicCurve( const int index, const FTVector<ContourPoint>& pointList);
+        
+        /**
+         * De Casteljau (bezier) algorithm contributed by Jed Soane
+         *
+         * @param t 
+         * @param curveOrder The order of the curve to be evaluated.
+         * <code>2</code> equals conic (quadratic) and <code>3</code> equals cubic
+         */
+        void deCasteljau( const float t, const int curveOrder);
+
+        /**
+         * De Casteljau (bezier) algorithm contributed by Jed Soane
+         *
+         * @param curveOrder The order of the curve to be evaluated.
+         * <code>2</code> equals conic (quadratic) and <code>3</code> equals cubic
+         */
+        void evaluateCurve( const int curveOrder);
+
+        /**
+         */
+         // Magic numbers -- #define MAX_DEG 4
+        float bValues[4][4][2];  //3D array storing values of de Casteljau algorithm.
+        float ctrlPtArray[4][2]; // Magic numbers
+        
+        /**
+         * Parameterisation step size for De Casteljau algorithm
+         */
+        const float kBSTEPSIZE;
+
+};
+
+#endif // __FTContour__
diff --git a/src/FTContour.cpp b/src/FTContour.cpp
new file mode 100644
index 0000000..724e8ba
--- /dev/null
+++ b/src/FTContour.cpp
@@ -0,0 +1,166 @@
+#include "FTContour.h"
+
+static const unsigned int SECOND_ORDER_CURVE = 2;
+static const unsigned int THIRD_ORDER_CURVE = 3;
+
+
+FTContour::FTContour( FT_Vector* contour, char* pointTags, unsigned int numberOfPoints)
+:   kBSTEPSIZE( 0.2f)
+{   
+    FTVector<ContourPoint> tempPointList;
+    
+    for( unsigned int pointIndex = 0; pointIndex < numberOfPoints; ++ pointIndex)
+    {
+        if( pointIndex == numberOfPoints - 1)
+        {
+            if( pointTags[pointIndex] == FT_Curve_Tag_Conic && pointTags[0] == FT_Curve_Tag_Conic)
+            {
+                tempPointList.push_back( ContourPoint( FTPoint( contour[pointIndex]), pointTags[pointIndex]));
+    
+                FTPoint implicitPoint( static_cast<float>( contour[pointIndex].x + contour[0].x) * 0.5f,
+                                       static_cast<float>( contour[pointIndex].y + contour[0].y) * 0.5f,
+                                       0);
+                tempPointList.push_back( ContourPoint( implicitPoint, FT_Curve_Tag_On));
+            }
+            else
+            {
+                tempPointList.push_back( ContourPoint( FTPoint( contour[pointIndex]), pointTags[pointIndex]));
+            }
+        }
+        else if( pointTags[pointIndex] == FT_Curve_Tag_Conic && pointTags[pointIndex + 1] == FT_Curve_Tag_Conic)
+        {
+            tempPointList.push_back( ContourPoint( FTPoint( contour[pointIndex]), pointTags[pointIndex]));
+
+            FTPoint implicitPoint( static_cast<float>( contour[pointIndex].x + contour[pointIndex + 1].x) * 0.5f,
+                                   static_cast<float>( contour[pointIndex].y + contour[pointIndex + 1].y) * 0.5f,
+                                   0);
+            tempPointList.push_back( ContourPoint( implicitPoint, FT_Curve_Tag_On));
+        }
+        else
+        {
+            tempPointList.push_back( ContourPoint( FTPoint( contour[pointIndex]), pointTags[pointIndex]));
+        }
+    }
+
+    for( unsigned int pointIndex = 0; pointIndex < tempPointList.size();)
+    {
+        switch( tempPointList[pointIndex].tag)
+        {
+            case FT_Curve_Tag_Conic:
+                EvaluateConicCurve( pointIndex, tempPointList);
+                ++pointIndex;
+                break;
+            case FT_Curve_Tag_Cubic:
+                EvaluateCubicCurve( pointIndex, tempPointList);
+                pointIndex += 2;
+                break;
+            case FT_Curve_Tag_On:
+            default:
+                AddPoint( tempPointList[pointIndex].point);
+                ++pointIndex;
+                break;
+        }
+    }
+    
+}
+
+
+void FTContour::AddPoint( FTPoint point)
+{
+    if( pointList.empty() || point != pointList[pointList.size() - 1])
+    {
+        pointList.push_back( point);
+    }
+}
+
+
+void FTContour::EvaluateConicCurve( const int index, const FTVector<ContourPoint>& pointList)
+{
+    unsigned int controlPoint = index;
+    unsigned int startPoint = index -1;
+    unsigned int endPoint = index + 1;
+    
+    if( 0 == controlPoint)
+    {
+        startPoint = pointList.size() - 1;
+    }
+    else if( pointList.size() - 1 == controlPoint)
+    {
+        endPoint = 0;
+    }
+    
+    ctrlPtArray[0][0] = pointList[startPoint].point.x;   ctrlPtArray[0][1] = pointList[startPoint].point.y;
+    ctrlPtArray[1][0] = pointList[controlPoint].point.x; ctrlPtArray[1][1] = pointList[controlPoint].point.y;
+    ctrlPtArray[2][0] = pointList[endPoint].point.x;     ctrlPtArray[2][1] = pointList[endPoint].point.y;
+    
+    evaluateCurve( SECOND_ORDER_CURVE);
+}
+
+
+void FTContour::EvaluateCubicCurve( const int index, const FTVector<ContourPoint>& pointList)
+{
+    unsigned int controlPointOne = index;
+    unsigned int controlPointTwo = index + 1;
+    unsigned int startPoint = index -1;
+    
+    if( controlPointOne == pointList.size() - 1)
+    {
+        controlPointTwo = 0; 
+    }
+    
+    unsigned int endPoint = controlPointTwo + 1;
+    
+    if( controlPointTwo == pointList.size() - 1)
+    {
+        endPoint = 0;
+    }
+    
+    if( 0 == controlPointOne)
+    {
+        startPoint = pointList.size() - 1; 
+    }
+
+    ctrlPtArray[0][0] = pointList[startPoint].point.x;      ctrlPtArray[0][1] = pointList[startPoint].point.y;
+    ctrlPtArray[1][0] = pointList[controlPointOne].point.x; ctrlPtArray[1][1] = pointList[controlPointOne].point.y;
+    ctrlPtArray[2][0] = pointList[controlPointTwo].point.x; ctrlPtArray[2][1] = pointList[controlPointTwo].point.y;
+    ctrlPtArray[3][0] = pointList[endPoint].point.x;        ctrlPtArray[3][1] = pointList[endPoint].point.y;
+
+    evaluateCurve( THIRD_ORDER_CURVE);
+}
+
+
+void FTContour::deCasteljau( const float t, const int n)
+{
+    //Calculating successive b(i)'s using de Casteljau algorithm.
+    for( int i = 1; i <= n; i++)
+    {
+        for( int k = 0; k <= (n - i); k++)
+        {
+            bValues[i][k][0] = (1 - t) * bValues[i - 1][k][0] + t * bValues[i - 1][k + 1][0];
+            bValues[i][k][1] = (1 - t) * bValues[i - 1][k][1] + t * bValues[i - 1][k + 1][1];
+        }
+    }
+       
+    //Specify next vertex to be included on curve
+    AddPoint( FTPoint( bValues[n][0][0], bValues[n][0][1], 0));
+}
+
+
+void FTContour::evaluateCurve( const int n)
+{
+    // setting the b(0) equal to the control points
+    for( int i = 0; i <= n; i++)
+    {
+        bValues[0][i][0] = ctrlPtArray[i][0];
+        bValues[0][i][1] = ctrlPtArray[i][1];
+    }
+
+    float t; //parameter for curve point calc. [0.0, 1.0]
+
+    for( int m = 0; m <= ( 1 / kBSTEPSIZE); m++)
+    {
+        t = m * kBSTEPSIZE;
+        deCasteljau( t, n);  //calls to evaluate point on curve at t.
+    }
+}
+