00001 #include <cassert>
00002 #include <string>
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);
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::PreRender()
00155 {
00156 FTFont::PreRender();
00157 glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
00158
00159 glEnable(GL_BLEND);
00160 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00161 glEnable(GL_ALPHA_TEST);
00162 glAlphaFunc(GL_GEQUAL, 0.0625);
00163
00164 FTTextureGlyph::ResetActiveTexture();
00165 }
00166
00167
00168 void FTGLTextureFont::PostRender()
00169 {
00170 glPopAttrib();
00171 FTFont::PostRender();
00172 }