Back to index

extremetuxracer  0.5beta
FTGLTextureFont.cpp
Go to the documentation of this file.
00001 #include <cassert>
00002 #include <string> // For memset
00003 
00004 #include "FTGLTextureFont.h"
00005 #include "FTTextureGlyph.h"
00006 
00007 
00008 inline GLuint NextPowerOf2( GLuint in)
00009 {
00010      in -= 1;
00011 
00012      in |= in >> 16;
00013      in |= in >> 8;
00014      in |= in >> 4;
00015      in |= in >> 2;
00016      in |= in >> 1;
00017 
00018      return in + 1;
00019 }
00020 
00021 
00022 FTGLTextureFont::FTGLTextureFont( const char* fontFilePath)
00023 :   FTFont( fontFilePath),
00024     maximumGLTextureSize(0),
00025     textureWidth(0),
00026     textureHeight(0),
00027     glyphHeight(0),
00028     glyphWidth(0),
00029     padding(3),
00030     xOffset(0),
00031     yOffset(0)
00032 {
00033     remGlyphs = numGlyphs = face.GlyphCount();
00034 }
00035 
00036 
00037 FTGLTextureFont::FTGLTextureFont( const unsigned char *pBufferBytes, size_t bufferSizeInBytes)
00038 :   FTFont( pBufferBytes, bufferSizeInBytes),
00039     maximumGLTextureSize(0),
00040     textureWidth(0),
00041     textureHeight(0),
00042     glyphHeight(0),
00043     glyphWidth(0),
00044     padding(3),
00045     xOffset(0),
00046     yOffset(0)
00047 {
00048     remGlyphs = numGlyphs = face.GlyphCount();
00049 }
00050 
00051 
00052 FTGLTextureFont::~FTGLTextureFont()
00053 {
00054     glDeleteTextures( textureIDList.size(), (const GLuint*)&textureIDList[0]);
00055 }
00056 
00057 
00058 FTGlyph* FTGLTextureFont::MakeGlyph( unsigned int glyphIndex)
00059 {
00060     FT_GlyphSlot ftGlyph = face.Glyph( glyphIndex, FT_LOAD_NO_HINTING);
00061     
00062     if( ftGlyph)
00063     {
00064         glyphHeight = static_cast<int>( charSize.Height());
00065         glyphWidth = static_cast<int>( charSize.Width());
00066         
00067         if( textureIDList.empty())
00068         {
00069             textureIDList.push_back( CreateTexture());
00070             xOffset = yOffset = padding;
00071         }
00072         
00073         if( xOffset > ( textureWidth - glyphWidth))
00074         {
00075             xOffset = padding;
00076             yOffset += glyphHeight;
00077             
00078             if( yOffset > ( textureHeight - glyphHeight))
00079             {
00080                 textureIDList.push_back( CreateTexture());
00081                 yOffset = padding;
00082             }
00083         }
00084         
00085         FTTextureGlyph* tempGlyph = new FTTextureGlyph( ftGlyph, textureIDList[textureIDList.size() - 1],
00086                                                         xOffset, yOffset, textureWidth, textureHeight);
00087         xOffset += static_cast<int>( tempGlyph->BBox().upperX - tempGlyph->BBox().lowerX + padding);
00088         
00089         --remGlyphs;
00090         return tempGlyph;
00091     }
00092     
00093     err = face.Error();
00094     return NULL;
00095 }
00096 
00097 
00098 void FTGLTextureFont::CalculateTextureSize()
00099 {
00100     if( !maximumGLTextureSize)
00101     {
00102         glGetIntegerv( GL_MAX_TEXTURE_SIZE, (GLint*)&maximumGLTextureSize);
00103         assert(maximumGLTextureSize); // If you hit this then you have an invalid OpenGL context.
00104     }
00105     
00106     textureWidth = NextPowerOf2( (remGlyphs * glyphWidth) + ( padding * 2));
00107     textureWidth = textureWidth > maximumGLTextureSize ? maximumGLTextureSize : textureWidth;
00108     
00109     int h = static_cast<int>( (textureWidth - ( padding * 2)) / glyphWidth);
00110         
00111     textureHeight = NextPowerOf2( (( numGlyphs / h) + 1) * glyphHeight);
00112     textureHeight = textureHeight > maximumGLTextureSize ? maximumGLTextureSize : textureHeight;
00113 }
00114 
00115 
00116 GLuint FTGLTextureFont::CreateTexture()
00117 {   
00118     CalculateTextureSize();
00119     
00120     int totalMemory = textureWidth * textureHeight;
00121     unsigned char* textureMemory = new unsigned char[totalMemory];
00122     memset( textureMemory, 0, totalMemory);
00123 
00124     GLuint textID;
00125     glGenTextures( 1, (GLuint*)&textID);
00126 
00127     glBindTexture( GL_TEXTURE_2D, textID);
00128     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00129     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00130     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00131     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00132 
00133     glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, textureWidth, textureHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, textureMemory);
00134 
00135     delete [] textureMemory;
00136 
00137     return textID;
00138 }
00139 
00140 
00141 bool FTGLTextureFont::FaceSize( const unsigned int size, const unsigned int res)
00142 {
00143     if( !textureIDList.empty())
00144     {
00145         glDeleteTextures( textureIDList.size(), (const GLuint*)&textureIDList[0]);
00146         textureIDList.clear();
00147         remGlyphs = numGlyphs = face.GlyphCount();
00148     }
00149 
00150     return FTFont::FaceSize( size, res);
00151 }
00152 
00153 
00154 void FTGLTextureFont::Render( const char* string)
00155 {   
00156     glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
00157     
00158     glEnable(GL_BLEND);
00159     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
00160 
00161     FTTextureGlyph::ResetActiveTexture();
00162     
00163     FTFont::Render( string);
00164 
00165     glPopAttrib();
00166 }
00167 
00168 
00169 void FTGLTextureFont::Render( const wchar_t* string)
00170 {   
00171     glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
00172     
00173     glEnable(GL_BLEND);
00174     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
00175     
00176     FTTextureGlyph::ResetActiveTexture();
00177     
00178     FTFont::Render( string);
00179     
00180     glPopAttrib();
00181 }
00182