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 )
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 FTGL_DOUBLE* vertex = static_cast<FTGL_DOUBLE*>(coords);
00035 *outData = 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 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 &tempPointList.back().x;
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_Glyph glyph)
00102 : contourList(0),
00103 mesh(0),
00104 ftContourCount(0),
00105 contourFlag(0)
00106 {
00107 if( glyph)
00108 {
00109 FT_OutlineGlyph outline = (FT_OutlineGlyph)glyph;
00110 ftOutline = outline->outline;
00111
00112 ftContourCount = ftOutline.n_contours;;
00113 contourList = 0;
00114 contourFlag = ftOutline.flags;
00115
00116 ProcessContours();
00117 }
00118 }
00119
00120
00121 FTVectoriser::~FTVectoriser()
00122 {
00123 for( size_t c = 0; c < ContourCount(); ++c)
00124 {
00125 delete contourList[c];
00126 }
00127
00128 delete [] contourList;
00129 delete mesh;
00130 }
00131
00132
00133 void FTVectoriser::ProcessContours()
00134 {
00135 short contourLength = 0;
00136 short startIndex = 0;
00137 short endIndex = 0;
00138
00139 contourList = new FTContour*[ftContourCount];
00140
00141 for( short contourIndex = 0; contourIndex < ftContourCount; ++contourIndex)
00142 {
00143 FT_Vector* pointList = &ftOutline.points[startIndex];
00144 char* tagList = &ftOutline.tags[startIndex];
00145
00146 endIndex = ftOutline.contours[contourIndex];
00147 contourLength = ( endIndex - startIndex) + 1;
00148
00149 FTContour* contour = new FTContour( pointList, tagList, contourLength);
00150
00151 contourList[contourIndex] = contour;
00152
00153 startIndex = endIndex + 1;
00154 }
00155 }
00156
00157
00158 size_t FTVectoriser::PointCount()
00159 {
00160 size_t s = 0;
00161 for( size_t c = 0; c < ContourCount(); ++c)
00162 {
00163 s += contourList[c]->PointCount();
00164 }
00165
00166 return s;
00167 }
00168
00169
00170 const FTContour* const FTVectoriser::Contour( unsigned int index) const
00171 {
00172 return ( index < ContourCount()) ? contourList[index] : NULL;
00173 }
00174
00175
00176 void FTVectoriser::MakeMesh( FTGL_DOUBLE zNormal)
00177 {
00178 if( mesh)
00179 {
00180 delete mesh;
00181 }
00182
00183 mesh = new FTMesh;
00184
00185 GLUtesselator* tobj = gluNewTess();
00186
00187 gluTessCallback( tobj, GLU_TESS_BEGIN_DATA, (GLUTesselatorFunction)ftglBegin);
00188 gluTessCallback( tobj, GLU_TESS_VERTEX_DATA, (GLUTesselatorFunction)ftglVertex);
00189 gluTessCallback( tobj, GLU_TESS_COMBINE_DATA, (GLUTesselatorFunction)ftglCombine);
00190 gluTessCallback( tobj, GLU_TESS_END_DATA, (GLUTesselatorFunction)ftglEnd);
00191 gluTessCallback( tobj, GLU_TESS_ERROR_DATA, (GLUTesselatorFunction)ftglError);
00192
00193 if( contourFlag & ft_outline_even_odd_fill)
00194 {
00195 gluTessProperty( tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
00196 }
00197 else
00198 {
00199 gluTessProperty( tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
00200 }
00201
00202
00203 gluTessProperty( tobj, GLU_TESS_TOLERANCE, 0);
00204 gluTessNormal( tobj, 0.0f, 0.0f, zNormal);
00205 gluTessBeginPolygon( tobj, mesh);
00206
00207 for( size_t c = 0; c < ContourCount(); ++c)
00208 {
00209 const FTContour* contour = contourList[c];
00210
00211 gluTessBeginContour( tobj);
00212
00213 for( size_t p = 0; p < contour->PointCount(); ++p)
00214 {
00215 FTGL_DOUBLE* d = const_cast<FTGL_DOUBLE*>(&contour->Point(p).x);
00216 gluTessVertex( tobj, d, d);
00217 }
00218
00219 gluTessEndContour( tobj);
00220 }
00221
00222 gluTessEndPolygon( tobj);
00223
00224 gluDeleteTess( tobj);
00225 }
00226