#include // For memset #include "FTGLTextureFont.h" #include "FTTextureGlyph.h" inline GLuint NextPowerOf2( GLuint in) { in -= 1; in |= in >> 16; in |= in >> 8; in |= in >> 4; in |= in >> 2; in |= in >> 1; return in + 1; } FTGLTextureFont::FTGLTextureFont( const char* fontname) : FTFont( fontname), maxTextSize(0), textureWidth(0), textureHeight(0), glyphHeight(0), glyphWidth(0), padding(3), xOffset(0), yOffset(0) { remGlyphs = numGlyphs = face.GlyphCount(); } FTGLTextureFont::FTGLTextureFont( const unsigned char *pBufferBytes, size_t bufferSizeInBytes) : FTFont( pBufferBytes, bufferSizeInBytes), maxTextSize(0), textureWidth(0), textureHeight(0), glyphHeight(0), glyphWidth(0), padding(3), xOffset(0), yOffset(0) { remGlyphs = numGlyphs = face.GlyphCount(); } FTGLTextureFont::~FTGLTextureFont() { glDeleteTextures( textureIDList.size(), (const GLuint*)&textureIDList[0]); } FTGlyph* FTGLTextureFont::MakeGlyph( unsigned int glyphIndex) { FT_GlyphSlot ftGlyph = face.Glyph( glyphIndex, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP); if( ftGlyph) { glyphHeight = static_cast( charSize.Height()); glyphWidth = static_cast( charSize.Width()); if( textureIDList.empty()) { textureIDList.push_back( CreateTexture()); xOffset = yOffset = padding; } if( xOffset > ( textureWidth - glyphWidth)) { xOffset = padding; yOffset += glyphHeight; if( yOffset > ( textureHeight - glyphHeight)) { textureIDList.push_back( CreateTexture()); yOffset = padding; } } FTTextureGlyph* tempGlyph = new FTTextureGlyph( ftGlyph, textureIDList[textureIDList.size() - 1], xOffset, yOffset, textureWidth, textureHeight); xOffset += static_cast( tempGlyph->BBox().upperX - tempGlyph->BBox().lowerX + padding); --remGlyphs; return tempGlyph; } err = face.Error(); return NULL; } void FTGLTextureFont::CalculateTextureSize() { if( !maxTextSize) { glGetIntegerv( GL_MAX_TEXTURE_SIZE, (GLint*)&maxTextSize); } textureWidth = NextPowerOf2( (remGlyphs * glyphWidth) + ( padding * 2)); if( textureWidth > maxTextSize) { textureWidth = maxTextSize; } int h = static_cast( (textureWidth - ( padding * 2)) / glyphWidth); textureHeight = NextPowerOf2( (( numGlyphs / h) + 1) * glyphHeight); textureHeight = textureHeight > maxTextSize ? maxTextSize : textureHeight; } GLuint FTGLTextureFont::CreateTexture() { CalculateTextureSize(); int totalMemory = textureWidth * textureHeight; unsigned char* textureMemory = new unsigned char[totalMemory]; memset( textureMemory, 0, totalMemory); GLuint textID; glGenTextures( 1, (GLuint*)&textID); glBindTexture( GL_TEXTURE_2D, textID); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, textureWidth, textureHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, textureMemory); delete [] textureMemory; return textID; } bool FTGLTextureFont::FaceSize( const unsigned int size, const unsigned int res) { if( !textureIDList.empty()) { glDeleteTextures( textureIDList.size(), (const GLuint*)&textureIDList[0]); remGlyphs = numGlyphs = face.GlyphCount(); } return FTFont::FaceSize( size, res); } void FTGLTextureFont::Render( const char* string) { // glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT); glEnable(GL_BLEND); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE FTFont::Render( string); // glPopAttrib(); } void FTGLTextureFont::Render( const wchar_t* string) { // glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT); glEnable(GL_BLEND); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE FTFont::Render( string); // glPopAttrib(); }