Edit

kc3-lang/ftgl/src/FTVectoriser.cpp

Branch :

  • Show log

    Commit

  • Author : henry
    Date : 2001-08-05 22:28:29
    Hash : a1ed83ae
    Message : const rampage:) added next2 to curve code

  • src/FTVectoriser.cpp
  • #include	"FTVectoriser.h"
    #include	"FTGL.h"
    
    
    FTContour::FTContour()
    {	
    	pointList.reserve( 1000); // FIXME magic number
    }
    
    
    FTContour::~FTContour()
    {
    	pointList.clear();
    }
    
    
    void FTContour::AddPoint( const int x, const int y)
    {
    	ftPoint point( static_cast<float>( x), static_cast<float>( y), 0.0); 
    	
    	// Eliminate duplicate points.
    	if( ( pointList[pointList.size() - 1] != point) && pointList[0] != point)
    	{
    		pointList.push_back( point);
    	}
    }
    
    
    // De Casteljau algorithm supplied by Jed Soane
    void FTVectoriser::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
    	contour->AddPoint( bValues[n][0][0], bValues[n][0][1]);
    }
    
    
    // De Casteljau algorithm supplied by Jed Soane
    void FTVectoriser::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];
        } //end for(i..)
    
        float t;            					//parameter for curve point calc. [0.0, 1.0]
        const float stepSize = 0.2; // FIXME variable
    
        for( int m = 0; m <= (1 / stepSize); m++)
        {
        	t = m * stepSize;
            deCasteljau( t, n);  //calls to evaluate point on curve att.
        } //end for(m...)
    }
    
    
    FTVectoriser::FTVectoriser( const FT_Glyph glyph)
    :	contourFlag(0),
    	contour(0)
    {
    	FT_OutlineGlyph outline = (FT_OutlineGlyph)glyph;
    	ftOutline = outline->outline;
    	
    	contourList.reserve( ftOutline.n_contours);
    }
    
    
    FTVectoriser::~FTVectoriser()
    {
    	for( int c = 0; c < contours(); ++c)
    	{
    		delete contourList[c];
    	}
    
    	contourList.clear();
    }
    
    
    int FTVectoriser::points()
    {
    	int s = 0;
    	for( int c = 0; c < contours(); ++c)
    	{
    		s += contourList[c]->size();
    	}
    	
    	return s;
    }
    
    
    bool FTVectoriser::Ingest()
    {
        if ( ( ftOutline.n_contours < 1) || ( ftOutline.n_points < 3)) //FIXME check this
    		return false;
    
    	short first = 0;
    	short last;
    	const short cont = ftOutline.n_contours;
    	
    	for( short c = 0; c < cont; ++c)
    	{
    		contour = new FTContour;
    		contourFlag = ftOutline.flags;
    		last = ftOutline.contours[c];
    
    		for( short p = first; p <= last; ++p)
    		{
    			switch( ftOutline.tags[p])
    			{
    				case FT_Curve_Tag_Conic:
    					p += Conic( p, first, last);
    					break;
    				case FT_Curve_Tag_Cubic:
    					p += Cubic( p, first, last);
    					break;
    				case FT_Curve_Tag_On:
    				default:
     					contour->AddPoint( ftOutline.points[p].x, ftOutline.points[p].y);
    			}
    		}
    		
    		contourList.push_back( contour);
    		first = last + 1;
    	}
    	
    	return true;
    }
    
    
    int FTVectoriser::Conic( const int index, const int first, const int last)
    {
    	int next = index + 1;
    	int prev = index - 1;
    	
    	if( index == last)
    		next = first; 
    	
    	if( index == first)
    		prev = last; 
    	
    	if( ftOutline.tags[next] != FT_Curve_Tag_Conic)
    	{
    		ctrlPtArray[0][0] = ftOutline.points[prev].x;	ctrlPtArray[0][1] = ftOutline.points[prev].y;
    		ctrlPtArray[1][0] = ftOutline.points[index].x;	ctrlPtArray[1][1] = ftOutline.points[index].y;
    		ctrlPtArray[2][0] = ftOutline.points[next].x;	ctrlPtArray[2][1] = ftOutline.points[next].y;
    		
    		evaluateCurve( 2);
    		return 1;
    	}
    	else
    	{
    		int next2 = next + 1;
    		if( next == last)
    			next2 = first;
    		
    		//create a phantom point
    		float x = ( ftOutline.points[index].x + ftOutline.points[next].x) / 2;
    		float y = ( ftOutline.points[index].y + ftOutline.points[next].y) / 2;
    		
    		// process first curve
    		ctrlPtArray[0][0] = ftOutline.points[prev].x;	ctrlPtArray[0][1] = ftOutline.points[prev].y;
    		ctrlPtArray[1][0] = ftOutline.points[index].x;	ctrlPtArray[1][1] = ftOutline.points[index].y;
    		ctrlPtArray[2][0] = x;							ctrlPtArray[2][1] = y;
    		
    		evaluateCurve( 2);
    		
    		// process second curve
    		ctrlPtArray[0][0] = x;							ctrlPtArray[0][1] = y;
    		ctrlPtArray[1][0] = ftOutline.points[next].x;	ctrlPtArray[1][1] = ftOutline.points[next].y;
    		ctrlPtArray[2][0] = ftOutline.points[next2].x;	ctrlPtArray[2][1] = ftOutline.points[next2].y;
    		evaluateCurve( 2);
    		
    		return 2;
    	}
    }
    
    
    int FTVectoriser::Cubic( const int index, const int first, const int last)
    {
    	int next = index + 1;
    	int prev = index - 1;
    	
    	if( index == last)
    		next = first; 
    	
    	int next2 = next + 1;
    	
    	if( next == last)
    		next2 = first;
    	
    	if( index == first)
    		prev = last; 
    
    	ctrlPtArray[0][0] = ftOutline.points[prev].x;		ctrlPtArray[0][1] = ftOutline.points[prev].y;
    	ctrlPtArray[1][0] = ftOutline.points[index].x;		ctrlPtArray[1][1] = ftOutline.points[index].y;
    	ctrlPtArray[2][0] = ftOutline.points[next].x;		ctrlPtArray[2][1] = ftOutline.points[next].y;
    	ctrlPtArray[3][0] = ftOutline.points[next2].x;		ctrlPtArray[3][1] = ftOutline.points[next2].y;
    
    	evaluateCurve( 3);
    	return 2;
    }
    
    
    void FTVectoriser::Output( double* data)
    {
    	int i = 0;
    	
    	for( int c= 0; c < contours(); ++c)
    	{
    		const FTContour* contour = contourList[c];
    		
    		for( int p = 0; p < contour->size(); ++p)
    		{
    			data[i] = static_cast<double>(contour->pointList[p].x / 64.0f); // is 64 correct?
    			data[i + 1] = static_cast<double>(contour->pointList[p].y / 64.0f);
    			data[i + 2] = 0.0; // static_cast<double>(contour->pointList[p].z / 64.0f);
    			i += 3;
    		}
    	}
    }