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 numTextures(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 maxTextSize(0),
00040 textureWidth(0),
00041 textureHeight(0),
00042 numTextures(0),
00043 glyphHeight(0),
00044 glyphWidth(0),
00045 padding(3),
00046 xOffset(0),
00047 yOffset(0)
00048 {
00049 remGlyphs = numGlyphs = face.GlyphCount();
00050 }
00051
00052
00053 FTGLTextureFont::~FTGLTextureFont()
00054 {
00055 glDeleteTextures( numTextures, (const GLuint*)glTextureID);
00056 }
00057
00058
00059 FTGlyph* FTGLTextureFont::MakeGlyph( unsigned int glyphIndex)
00060 {
00061 FT_Glyph* ftGlyph = face.Glyph( glyphIndex, FT_LOAD_NO_HINTING);
00062
00063 if( ftGlyph)
00064 {
00065 glyphHeight = static_cast<int>( charSize.Height());
00066 glyphWidth = static_cast<int>( charSize.Width());
00067
00068 if( numTextures == 0)
00069 {
00070 glTextureID[0] = CreateTexture();
00071 xOffset = yOffset = padding;
00072 ++numTextures;
00073 }
00074
00075 if( xOffset > ( textureWidth - glyphWidth))
00076 {
00077 xOffset = padding;
00078 yOffset += glyphHeight;
00079
00080 if( yOffset > ( textureHeight - glyphHeight))
00081 {
00082 glTextureID[numTextures] = CreateTexture();
00083 ++numTextures;
00084 yOffset = padding;
00085 }
00086 }
00087
00088 FTTextureGlyph* tempGlyph = new FTTextureGlyph( *ftGlyph, glTextureID[numTextures - 1],
00089 xOffset, yOffset, textureWidth, textureHeight);
00090 xOffset += static_cast<int>( tempGlyph->BBox().upperX - tempGlyph->BBox().lowerX + padding);
00091
00092 --remGlyphs;
00093 return tempGlyph;
00094 }
00095
00096 err = face.Error();
00097 return NULL;
00098 }
00099
00100
00101 void FTGLTextureFont::CalculateTextureSize()
00102 {
00103 if( !maxTextSize)
00104 {
00105 glGetIntegerv( GL_MAX_TEXTURE_SIZE, (GLint*)&maxTextSize);
00106 }
00107
00108 textureWidth = NextPowerOf2( (remGlyphs * glyphWidth) + ( padding * 2));
00109 if( textureWidth > maxTextSize)
00110 {
00111 textureWidth = maxTextSize;
00112 }
00113
00114 int h = static_cast<int>( (textureWidth - ( padding * 2)) / glyphWidth);
00115
00116 textureHeight = NextPowerOf2( (( numGlyphs / h) + 1) * glyphHeight);
00117 textureHeight = textureHeight > maxTextSize ? maxTextSize : textureHeight;
00118 }
00119
00120
00121 GLuint FTGLTextureFont::CreateTexture()
00122 {
00123 CalculateTextureSize();
00124
00125 int totalMemory = textureWidth * textureHeight;
00126 unsigned char* textureMemory = new unsigned char[totalMemory];
00127 memset( textureMemory, 0, totalMemory);
00128
00129 GLuint textID;
00130 glGenTextures( 1, (GLuint*)&textID);
00131
00132 glBindTexture( GL_TEXTURE_2D, textID);
00133 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00134 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00135 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00136 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00137
00138 glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, textureWidth, textureHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, textureMemory);
00139
00140 delete [] textureMemory;
00141
00142 return textID;
00143 }
00144
00145
00146 bool FTGLTextureFont::FaceSize( const unsigned int size, const unsigned int res)
00147 {
00148 if( numTextures)
00149 {
00150 glDeleteTextures( numTextures, (const GLuint*)glTextureID);
00151 numTextures = 0;
00152 remGlyphs = numGlyphs = face.GlyphCount();
00153 }
00154
00155 return FTFont::FaceSize( size, res);
00156 }
00157
00158
00159 void FTGLTextureFont::Render( const char* string)
00160 {
00161 glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
00162
00163 glEnable(GL_BLEND);
00164 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00165
00166 FTFont::Render( string);
00167
00168 glPopAttrib();
00169 }
00170
00171
00172 void FTGLTextureFont::Render( const wchar_t* string)
00173 {
00174 glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
00175
00176 glEnable(GL_BLEND);
00177 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00178
00179 FTFont::Render( string);
00180
00181 glPopAttrib();
00182 }
00183