#include #include #include "FTExtrdGlyph.h" #include "FTVectoriser.h" FTExtrdGlyph::FTExtrdGlyph( FT_GlyphSlot glyph, float depth, bool useDisplayList) : FTGlyph( glyph), glList(0) { bBox.SetDepth( -depth); if( ft_glyph_format_outline != glyph->format) { err = 0x14; // Invalid_Outline return; } FTVectoriser vectoriser( glyph); if( ( vectoriser.ContourCount() < 1) || ( vectoriser.PointCount() < 3)) { return; } unsigned int tesselationIndex; if(useDisplayList) { glList = glGenLists(1); glNewList( glList, GL_COMPILE); } vectoriser.MakeMesh( 1.0); glNormal3d(0.0, 0.0, 1.0); unsigned int horizontalTextureScale = glyph->face->size->metrics.x_ppem * 64; unsigned int verticalTextureScale = glyph->face->size->metrics.y_ppem * 64; const FTMesh* mesh = vectoriser.GetMesh(); for( tesselationIndex = 0; tesselationIndex < mesh->TesselationCount(); ++tesselationIndex) { const FTTesselation* subMesh = mesh->Tesselation( tesselationIndex); unsigned int polyonType = subMesh->PolygonType(); glBegin( polyonType); for( unsigned int pointIndex = 0; pointIndex < subMesh->PointCount(); ++pointIndex) { FTPoint point = subMesh->Point(pointIndex); glTexCoord2f( point.X() / horizontalTextureScale, point.Y() / verticalTextureScale); glVertex3f( point.X() / 64.0f, point.Y() / 64.0f, 0.0f); } glEnd(); } vectoriser.MakeMesh( -1.0); glNormal3d(0.0, 0.0, -1.0); mesh = vectoriser.GetMesh(); for( tesselationIndex = 0; tesselationIndex < mesh->TesselationCount(); ++tesselationIndex) { const FTTesselation* subMesh = mesh->Tesselation( tesselationIndex); unsigned int polyonType = subMesh->PolygonType(); glBegin( polyonType); for( unsigned int pointIndex = 0; pointIndex < subMesh->PointCount(); ++pointIndex) { FTPoint point = subMesh->Point(pointIndex); glTexCoord2f( subMesh->Point(pointIndex).X() / horizontalTextureScale, subMesh->Point(pointIndex).Y() / verticalTextureScale); glVertex3f( subMesh->Point( pointIndex).X() / 64.0f, subMesh->Point( pointIndex).Y() / 64.0f, -depth); } glEnd(); } int contourFlag = vectoriser.ContourFlag(); for( size_t c = 0; c < vectoriser.ContourCount(); ++c) { const FTContour* contour = vectoriser.Contour(c); unsigned int numberOfPoints = contour->PointCount(); glBegin( GL_QUAD_STRIP); for( unsigned int j = 0; j <= numberOfPoints; ++j) { unsigned int pointIndex = ( j == numberOfPoints) ? 0 : j; unsigned int nextPointIndex = ( pointIndex == numberOfPoints - 1) ? 0 : pointIndex + 1; FTPoint point = contour->Point(pointIndex); FTPoint normal = GetNormal( point, contour->Point(nextPointIndex)); if(normal != FTPoint( 0.0f, 0.0f, 0.0f)) { glNormal3dv(static_cast(normal)); } if( contourFlag & ft_outline_reverse_fill) { glTexCoord2f( point.X() / horizontalTextureScale, point.X() / verticalTextureScale); glVertex3f( point.X() / 64.0f, point.Y() / 64.0f, 0.0f); glVertex3f( point.X() / 64.0f, point.Y() / 64.0f, -depth); } else { glTexCoord2f( point.X() / horizontalTextureScale, point.Y() / verticalTextureScale); glVertex3f( point.X() / 64.0f, point.Y() / 64.0f, -depth); glVertex3f( point.X() / 64.0f, point.Y() / 64.0f, 0.0f); } } glEnd(); } if(useDisplayList) { glEndList(); } } FTExtrdGlyph::~FTExtrdGlyph() { glDeleteLists( glList, 1); } const FTPoint& FTExtrdGlyph::Render( const FTPoint& pen) { glTranslatef( pen.X(), pen.Y(), 0); if( glList) { glCallList( glList); } return advance; } FTPoint FTExtrdGlyph::GetNormal( const FTPoint &a, const FTPoint &b) { float vectorX = a.X() - b.X(); float vectorY = a.Y() - b.Y(); float length = sqrt( vectorX * vectorX + vectorY * vectorY ); if( length > 0.01f) { length = 1 / length; } else { length = 0.0f; } return FTPoint( -vectorY * length, vectorX * length, 0.0f); }