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* fontname)
00022 : FTFont( fontname),
00023 maxTextSize(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 maxTextSize(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( !maxTextSize)
00100 {
00101 glGetIntegerv( GL_MAX_TEXTURE_SIZE, (GLint*)&maxTextSize);
00102 }
00103
00104 textureWidth = NextPowerOf2( (remGlyphs * glyphWidth) + ( padding * 2));
00105 if( textureWidth > maxTextSize)
00106 {
00107 textureWidth = maxTextSize;
00108 }
00109
00110 int h = static_cast<int>( (textureWidth - ( padding * 2)) / glyphWidth);
00111
00112 textureHeight = NextPowerOf2( (( numGlyphs / h) + 1) * glyphHeight);
00113 textureHeight = textureHeight > maxTextSize ? maxTextSize : textureHeight;
00114 }
00115
00116
00117 GLuint FTGLTextureFont::CreateTexture()
00118 {
00119 CalculateTextureSize();
00120
00121 int totalMemory = textureWidth * textureHeight;
00122 unsigned char* textureMemory = new unsigned char[totalMemory];
00123 memset( textureMemory, 0, totalMemory);
00124
00125 GLuint textID;
00126 glGenTextures( 1, (GLuint*)&textID);
00127
00128 glBindTexture( GL_TEXTURE_2D, textID);
00129 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00130 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00131 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00132 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00133
00134 glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, textureWidth, textureHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, textureMemory);
00135
00136 delete [] textureMemory;
00137
00138 return textID;
00139 }
00140
00141
00142 bool FTGLTextureFont::FaceSize( const unsigned int size, const unsigned int res)
00143 {
00144 if( !textureIDList.empty())
00145 {
00146 glDeleteTextures( textureIDList.size(), (const GLuint*)&textureIDList[0]);
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);
00160
00161 FTFont::Render( string);
00162
00163 glPopAttrib();
00164 }
00165
00166
00167 void FTGLTextureFont::Render( const wchar_t* string)
00168 {
00169 glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
00170
00171 glEnable(GL_BLEND);
00172 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00173
00174 FTFont::Render( string);
00175
00176 glPopAttrib();
00177 }
00178