184 lines
4.7 KiB
C++
184 lines
4.7 KiB
C++
#include <cassert>
|
|
#include <string> // For memset
|
|
|
|
#include "FTGLTextureFont.h"
|
|
#include "FTTextureGlyph.h"
|
|
|
|
|
|
inline GLuint NextPowerOf2( GLuint in)
|
|
{
|
|
in -= 1;
|
|
|
|
in |= in >> 16;
|
|
in |= in >> 8;
|
|
in |= in >> 4;
|
|
in |= in >> 2;
|
|
in |= in >> 1;
|
|
|
|
return in + 1;
|
|
}
|
|
|
|
|
|
FTGLTextureFont::FTGLTextureFont( const char* fontFilePath)
|
|
: FTFont( fontFilePath),
|
|
maximumGLTextureSize(0),
|
|
textureWidth(0),
|
|
textureHeight(0),
|
|
glyphHeight(0),
|
|
glyphWidth(0),
|
|
padding(3),
|
|
xOffset(0),
|
|
yOffset(0)
|
|
{
|
|
remGlyphs = numGlyphs = face.GlyphCount();
|
|
}
|
|
|
|
|
|
FTGLTextureFont::FTGLTextureFont( const unsigned char *pBufferBytes, size_t bufferSizeInBytes, bool _hinting)
|
|
: FTFont( pBufferBytes, bufferSizeInBytes),
|
|
maximumGLTextureSize(0),
|
|
textureWidth(0),
|
|
textureHeight(0),
|
|
glyphHeight(0),
|
|
glyphWidth(0),
|
|
padding(3),
|
|
xOffset(0),
|
|
yOffset(0),
|
|
hinting( _hinting )
|
|
{
|
|
remGlyphs = numGlyphs = face.GlyphCount();
|
|
}
|
|
|
|
|
|
FTGLTextureFont::~FTGLTextureFont()
|
|
{
|
|
glDeleteTextures( textureIDList.size(), (const GLuint*)&textureIDList[0]);
|
|
}
|
|
|
|
|
|
FTGlyph* FTGLTextureFont::MakeGlyph( unsigned int glyphIndex)
|
|
{
|
|
FT_GlyphSlot ftGlyph = face.Glyph( glyphIndex, hinting ? 0 : FT_LOAD_NO_HINTING );
|
|
|
|
if( ftGlyph)
|
|
{
|
|
glyphHeight = static_cast<int>( charSize.Height());
|
|
glyphWidth = static_cast<int>( charSize.Width());
|
|
|
|
if( textureIDList.empty())
|
|
{
|
|
textureIDList.push_back( CreateTexture());
|
|
xOffset = yOffset = padding;
|
|
}
|
|
|
|
if( xOffset > ( textureWidth - glyphWidth))
|
|
{
|
|
xOffset = padding;
|
|
yOffset += glyphHeight;
|
|
|
|
if( yOffset > ( textureHeight - glyphHeight))
|
|
{
|
|
textureIDList.push_back( CreateTexture());
|
|
yOffset = padding;
|
|
}
|
|
}
|
|
|
|
FTTextureGlyph* tempGlyph = new FTTextureGlyph( ftGlyph, textureIDList[textureIDList.size() - 1],
|
|
xOffset, yOffset, textureWidth, textureHeight);
|
|
xOffset += static_cast<int>( tempGlyph->BBox().upperX - tempGlyph->BBox().lowerX + padding);
|
|
|
|
--remGlyphs;
|
|
return tempGlyph;
|
|
}
|
|
|
|
err = face.Error();
|
|
return NULL;
|
|
}
|
|
|
|
|
|
void FTGLTextureFont::CalculateTextureSize()
|
|
{
|
|
if( !maximumGLTextureSize)
|
|
{
|
|
glGetIntegerv( GL_MAX_TEXTURE_SIZE, (GLint*)&maximumGLTextureSize);
|
|
assert(maximumGLTextureSize); // If you hit this then you have an invalid OpenGL context.
|
|
}
|
|
|
|
textureWidth = NextPowerOf2( (remGlyphs * glyphWidth) + ( padding * 2));
|
|
textureWidth = textureWidth > maximumGLTextureSize ? maximumGLTextureSize : textureWidth;
|
|
|
|
int h = static_cast<int>( (textureWidth - ( padding * 2)) / glyphWidth);
|
|
|
|
textureHeight = NextPowerOf2( (( numGlyphs / h) + 1) * glyphHeight);
|
|
textureHeight = textureHeight > maximumGLTextureSize ? maximumGLTextureSize : textureHeight;
|
|
}
|
|
|
|
|
|
GLuint FTGLTextureFont::CreateTexture()
|
|
{
|
|
CalculateTextureSize();
|
|
|
|
int totalMemory = textureWidth * textureHeight;
|
|
unsigned char* textureMemory = new unsigned char[totalMemory];
|
|
memset( textureMemory, 0, totalMemory);
|
|
|
|
GLuint textID;
|
|
glGenTextures( 1, (GLuint*)&textID);
|
|
|
|
glBindTexture( GL_TEXTURE_2D, textID);
|
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, textureWidth, textureHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, textureMemory);
|
|
|
|
delete [] textureMemory;
|
|
|
|
return textID;
|
|
}
|
|
|
|
|
|
bool FTGLTextureFont::FaceSize( const unsigned int size, const unsigned int res)
|
|
{
|
|
if( !textureIDList.empty())
|
|
{
|
|
glDeleteTextures( textureIDList.size(), (const GLuint*)&textureIDList[0]);
|
|
textureIDList.clear();
|
|
remGlyphs = numGlyphs = face.GlyphCount();
|
|
}
|
|
|
|
return FTFont::FaceSize( size, res);
|
|
}
|
|
|
|
|
|
void FTGLTextureFont::Render( const char* string)
|
|
{
|
|
glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
|
|
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
|
|
|
|
FTTextureGlyph::ResetActiveTexture();
|
|
|
|
FTFont::Render( string);
|
|
|
|
glPopAttrib();
|
|
}
|
|
|
|
|
|
void FTGLTextureFont::Render( const wchar_t* string)
|
|
{
|
|
glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
|
|
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
|
|
|
|
FTTextureGlyph::ResetActiveTexture();
|
|
|
|
FTFont::Render( string);
|
|
|
|
glPopAttrib();
|
|
}
|
|
|