diff options
Diffstat (limited to 'extern/bFTGL/src/FTVectoriser.cpp')
-rw-r--r-- | extern/bFTGL/src/FTVectoriser.cpp | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/extern/bFTGL/src/FTVectoriser.cpp b/extern/bFTGL/src/FTVectoriser.cpp new file mode 100644 index 00000000000..bb133d025b4 --- /dev/null +++ b/extern/bFTGL/src/FTVectoriser.cpp @@ -0,0 +1,225 @@ +#include "FTVectoriser.h" +#include "FTGL.h" + +#ifndef CALLBACK +#define CALLBACK +#endif + +#ifdef __APPLE_CC__ + typedef GLvoid (*GLUTesselatorFunction)(...); +#elif defined( __mips ) || defined( __linux__ ) || defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __sun ) || defined (__CYGWIN__) + typedef GLvoid (*GLUTesselatorFunction)(); +#elif defined ( WIN32) + typedef GLvoid (CALLBACK *GLUTesselatorFunction)( ); +#else + #error "Error - need to define type GLUTesselatorFunction for this platform/compiler" +#endif + + +void CALLBACK ftglError( GLenum errCode, FTMesh* mesh) +{ + mesh->Error( errCode); +} + + +void CALLBACK ftglVertex( void* data, FTMesh* mesh) +{ + FTGL_DOUBLE* vertex = static_cast<FTGL_DOUBLE*>(data); + mesh->AddPoint( vertex[0], vertex[1], vertex[2]); +} + + +void CALLBACK ftglCombine( FTGL_DOUBLE coords[3], void* vertex_data[4], GLfloat weight[4], void** outData, FTMesh* mesh) +{ + FTGL_DOUBLE* vertex = static_cast<FTGL_DOUBLE*>(coords); + *outData = mesh->Combine( vertex[0], vertex[1], vertex[2]); +} + + +void CALLBACK ftglBegin( GLenum type, FTMesh* mesh) +{ + mesh->Begin( type); +} + + +void CALLBACK ftglEnd( FTMesh* mesh) +{ + mesh->End(); +} + + +FTMesh::FTMesh() +: currentTesselation(0), + err(0) +{ + tesselationList.reserve( 16); +} + + +FTMesh::~FTMesh() +{ + for( size_t t = 0; t < tesselationList.size(); ++t) + { + delete tesselationList[t]; + } + + tesselationList.clear(); +} + + +void FTMesh::AddPoint( const FTGL_DOUBLE x, const FTGL_DOUBLE y, const FTGL_DOUBLE z) +{ + currentTesselation->AddPoint( x, y, z); +} + + +FTGL_DOUBLE* FTMesh::Combine( const FTGL_DOUBLE x, const FTGL_DOUBLE y, const FTGL_DOUBLE z) +{ + tempPointList.push_back( FTPoint( x, y,z)); + return &tempPointList.back().x; +} + + +void FTMesh::Begin( GLenum meshType) +{ + currentTesselation = new FTTesselation( meshType); +} + + +void FTMesh::End() +{ + tesselationList.push_back( currentTesselation); +} + + +const FTTesselation* const FTMesh::Tesselation( unsigned int index) const +{ + return ( index < tesselationList.size()) ? tesselationList[index] : NULL; +} + + +FTVectoriser::FTVectoriser( const FT_GlyphSlot glyph) +: contourList(0), + mesh(0), + ftContourCount(0), + contourFlag(0) +{ + if( glyph) + { + outline = glyph->outline; + + ftContourCount = outline.n_contours;; + contourList = 0; + contourFlag = outline.flags; + + ProcessContours(); + } +} + + +FTVectoriser::~FTVectoriser() +{ + for( size_t c = 0; c < ContourCount(); ++c) + { + delete contourList[c]; + } + + delete [] contourList; + delete mesh; +} + + +void FTVectoriser::ProcessContours() +{ + short contourLength = 0; + short startIndex = 0; + short endIndex = 0; + + contourList = new FTContour*[ftContourCount]; + + for( short contourIndex = 0; contourIndex < ftContourCount; ++contourIndex) + { + FT_Vector* pointList = &outline.points[startIndex]; + char* tagList = &outline.tags[startIndex]; + + endIndex = outline.contours[contourIndex]; + contourLength = ( endIndex - startIndex) + 1; + + FTContour* contour = new FTContour( pointList, tagList, contourLength); + + contourList[contourIndex] = contour; + + startIndex = endIndex + 1; + } +} + + +size_t FTVectoriser::PointCount() +{ + size_t s = 0; + for( size_t c = 0; c < ContourCount(); ++c) + { + s += contourList[c]->PointCount(); + } + + return s; +} + + +const FTContour* const FTVectoriser::Contour( unsigned int index) const +{ + return ( index < ContourCount()) ? contourList[index] : NULL; +} + + +void FTVectoriser::MakeMesh( FTGL_DOUBLE zNormal) +{ + if( mesh) + { + delete mesh; + } + + mesh = new FTMesh; + + GLUtesselator* tobj = gluNewTess(); + + gluTessCallback( tobj, GLU_TESS_BEGIN_DATA, (GLUTesselatorFunction)ftglBegin); + gluTessCallback( tobj, GLU_TESS_VERTEX_DATA, (GLUTesselatorFunction)ftglVertex); + gluTessCallback( tobj, GLU_TESS_COMBINE_DATA, (GLUTesselatorFunction)ftglCombine); + gluTessCallback( tobj, GLU_TESS_END_DATA, (GLUTesselatorFunction)ftglEnd); + gluTessCallback( tobj, GLU_TESS_ERROR_DATA, (GLUTesselatorFunction)ftglError); + + if( contourFlag & ft_outline_even_odd_fill) // ft_outline_reverse_fill + { + gluTessProperty( tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); + } + else + { + gluTessProperty( tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO); + } + + + gluTessProperty( tobj, GLU_TESS_TOLERANCE, 0); + gluTessNormal( tobj, 0.0f, 0.0f, zNormal); + gluTessBeginPolygon( tobj, mesh); + + for( size_t c = 0; c < ContourCount(); ++c) + { + const FTContour* contour = contourList[c]; + + gluTessBeginContour( tobj); + + for( size_t p = 0; p < contour->PointCount(); ++p) + { + FTGL_DOUBLE* d = const_cast<FTGL_DOUBLE*>(&contour->Point(p).x); + gluTessVertex( tobj, d, d); + } + + gluTessEndContour( tobj); + } + + gluTessEndPolygon( tobj); + + gluDeleteTess( tobj); +} + |