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