Back to index

extremetuxracer  0.5beta
FTVectoriser.cpp
Go to the documentation of this file.
00001 #include    "FTVectoriser.h"
00002 #include    "FTGL.h"
00003 
00004 #ifndef CALLBACK
00005 #define CALLBACK
00006 #endif
00007 
00008 #ifdef __APPLE_CC__    
00009     typedef GLvoid (*GLUTesselatorFunction)(...);
00010 #elif defined( __mips ) || defined( __linux__ ) || defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __sun ) || defined (__CYGWIN__)
00011     typedef GLvoid (*GLUTesselatorFunction)();
00012 #elif defined ( WIN32)
00013     typedef GLvoid (CALLBACK *GLUTesselatorFunction)( );
00014 #else
00015     #error "Error - need to define type GLUTesselatorFunction for this platform/compiler"
00016 #endif
00017 
00018 
00019 void CALLBACK ftglError( GLenum errCode, FTMesh* mesh)
00020 {
00021     mesh->Error( errCode);
00022 }
00023 
00024 
00025 void CALLBACK ftglVertex( void* data, FTMesh* mesh)
00026 {
00027     FTGL_DOUBLE* vertex = static_cast<FTGL_DOUBLE*>(data);
00028     mesh->AddPoint( vertex[0], vertex[1], vertex[2]);
00029 }
00030 
00031 
00032 void CALLBACK ftglCombine( FTGL_DOUBLE coords[3], void* vertex_data[4], GLfloat weight[4], void** outData, FTMesh* mesh)
00033 {
00034     const FTGL_DOUBLE* vertex = static_cast<const FTGL_DOUBLE*>(coords);
00035     *outData = const_cast<FTGL_DOUBLE*>(mesh->Combine( vertex[0], vertex[1], vertex[2]));
00036 }
00037         
00038 
00039 void CALLBACK ftglBegin( GLenum type, FTMesh* mesh)
00040 {
00041     mesh->Begin( type);
00042 }
00043 
00044 
00045 void CALLBACK ftglEnd( FTMesh* mesh)
00046 {
00047     mesh->End();
00048 }
00049 
00050 
00051 FTMesh::FTMesh()
00052 :      currentTesselation(0),
00053     err(0)
00054 {
00055     tesselationList.reserve( 16);
00056 }
00057 
00058 
00059 FTMesh::~FTMesh()
00060 {
00061     for( size_t t = 0; t < tesselationList.size(); ++t)
00062     {
00063         delete tesselationList[t];
00064     }
00065     
00066     tesselationList.clear();
00067 }
00068 
00069 
00070 void FTMesh::AddPoint( const FTGL_DOUBLE x, const FTGL_DOUBLE y, const FTGL_DOUBLE z)
00071 {
00072     currentTesselation->AddPoint( x, y, z);
00073 }
00074 
00075 
00076 const FTGL_DOUBLE* FTMesh::Combine( const FTGL_DOUBLE x, const FTGL_DOUBLE y, const FTGL_DOUBLE z)
00077 {
00078     tempPointList.push_back( FTPoint( x, y,z));
00079     return static_cast<const FTGL_DOUBLE*>(tempPointList.back());
00080 }
00081 
00082 
00083 void FTMesh::Begin( GLenum meshType)
00084 {
00085     currentTesselation = new FTTesselation( meshType);
00086 }
00087 
00088 
00089 void FTMesh::End()
00090 {
00091     tesselationList.push_back( currentTesselation);
00092 }
00093 
00094 
00095 const FTTesselation* const FTMesh::Tesselation( unsigned int index) const
00096 {
00097     return ( index < tesselationList.size()) ? tesselationList[index] : NULL;
00098 }
00099 
00100 
00101 FTVectoriser::FTVectoriser( const FT_GlyphSlot glyph)
00102 :   contourList(0),
00103     mesh(0),
00104     ftContourCount(0),
00105     contourFlag(0)
00106 {
00107     if( glyph)
00108     {
00109         outline = glyph->outline;
00110         
00111         ftContourCount = outline.n_contours;
00112         contourList = 0;
00113         contourFlag = outline.flags;
00114         
00115         ProcessContours();
00116     }
00117 }
00118 
00119 
00120 FTVectoriser::~FTVectoriser()
00121 {
00122     for( size_t c = 0; c < ContourCount(); ++c)
00123     {
00124         delete contourList[c];
00125     }
00126 
00127     delete [] contourList;
00128     delete mesh;
00129 }
00130 
00131 
00132 void FTVectoriser::ProcessContours()
00133 {
00134     short contourLength = 0;
00135     short startIndex = 0;
00136     short endIndex = 0;
00137     
00138     contourList = new FTContour*[ftContourCount];
00139     
00140     for( short contourIndex = 0; contourIndex < ftContourCount; ++contourIndex)
00141     {
00142         FT_Vector* pointList = &outline.points[startIndex];
00143         char* tagList = &outline.tags[startIndex];
00144         
00145         endIndex = outline.contours[contourIndex];
00146         contourLength =  ( endIndex - startIndex) + 1;
00147 
00148         FTContour* contour = new FTContour( pointList, tagList, contourLength);
00149         
00150         contourList[contourIndex] = contour;
00151         
00152         startIndex = endIndex + 1;
00153     }
00154 }
00155 
00156 
00157 size_t FTVectoriser::PointCount()
00158 {
00159     size_t s = 0;
00160     for( size_t c = 0; c < ContourCount(); ++c)
00161     {
00162         s += contourList[c]->PointCount();
00163     }
00164     
00165     return s;
00166 }
00167 
00168 
00169 const FTContour* const FTVectoriser::Contour( unsigned int index) const
00170 {
00171     return ( index < ContourCount()) ? contourList[index] : NULL;
00172 }
00173 
00174 
00175 void FTVectoriser::MakeMesh( FTGL_DOUBLE zNormal)
00176 {
00177     if( mesh)
00178     {
00179         delete mesh;
00180     }
00181         
00182     mesh = new FTMesh;
00183     
00184     GLUtesselator* tobj = gluNewTess();
00185 
00186     gluTessCallback( tobj, GLU_TESS_BEGIN_DATA,     (GLUTesselatorFunction)ftglBegin);
00187     gluTessCallback( tobj, GLU_TESS_VERTEX_DATA,    (GLUTesselatorFunction)ftglVertex);
00188     gluTessCallback( tobj, GLU_TESS_COMBINE_DATA,   (GLUTesselatorFunction)ftglCombine);
00189     gluTessCallback( tobj, GLU_TESS_END_DATA,       (GLUTesselatorFunction)ftglEnd);
00190     gluTessCallback( tobj, GLU_TESS_ERROR_DATA,     (GLUTesselatorFunction)ftglError);
00191     
00192     if( contourFlag & ft_outline_even_odd_fill) // ft_outline_reverse_fill
00193     {
00194         gluTessProperty( tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
00195     }
00196     else
00197     {
00198         gluTessProperty( tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
00199     }
00200     
00201     
00202     gluTessProperty( tobj, GLU_TESS_TOLERANCE, 0);
00203     gluTessNormal( tobj, 0.0f, 0.0f, zNormal);
00204     gluTessBeginPolygon( tobj, mesh);
00205     
00206         for( size_t c = 0; c < ContourCount(); ++c)
00207         {
00208             const FTContour* contour = contourList[c];
00209 
00210             gluTessBeginContour( tobj);
00211             
00212                 for( size_t p = 0; p < contour->PointCount(); ++p)
00213                 {
00214                     const FTGL_DOUBLE* d = contour->Point(p);
00215                     gluTessVertex( tobj, (GLdouble*)d, (GLdouble*)d);
00216                 }
00217 
00218             gluTessEndContour( tobj);
00219         }
00220         
00221     gluTessEndPolygon( tobj);
00222 
00223     gluDeleteTess( tobj);
00224 }
00225