Added support for multiple graphics contexts, submission from Max Rhiener.
Alas changed the indenting to use 4 spaces instead of tabs, this irons out differences when working under Windows and Unix, keeping the identing consistent.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#include "FTGLTextureFont.h"
|
||||
#include "FTGlyphContainer.h"
|
||||
#include "FTTextureGlyph.h"
|
||||
#include "FTGLTextureFont.h"
|
||||
#include "FTGlyphContainer.h"
|
||||
#include "FTTextureGlyph.h"
|
||||
|
||||
inline GLuint NextPowerOf2( GLuint in)
|
||||
{
|
||||
@@ -17,188 +17,215 @@ inline GLuint NextPowerOf2( GLuint in)
|
||||
|
||||
|
||||
FTGLTextureFont::FTGLTextureFont()
|
||||
: maxTextSize(0),
|
||||
textureWidth(0),
|
||||
textureHeight(0),
|
||||
numTextures(1),
|
||||
textMem(0),
|
||||
glyphHeight(0),
|
||||
glyphWidth(0),
|
||||
padding(1)
|
||||
: maxTextSize(0),
|
||||
textureWidth(0),
|
||||
textureHeight(0),
|
||||
numTextures(1),
|
||||
textMem(0),
|
||||
glyphHeight(0),
|
||||
glyphWidth(0),
|
||||
padding(1)
|
||||
{}
|
||||
|
||||
FTGLTextureFont::FTGLTextureFont(int textureSize)
|
||||
: maxTextSize(textureSize),
|
||||
textureWidth(0),
|
||||
textureHeight(0),
|
||||
numTextures(1),
|
||||
textMem(0),
|
||||
glyphHeight(0),
|
||||
glyphWidth(0),
|
||||
padding(1)
|
||||
: maxTextSize(textureSize),
|
||||
textureWidth(0),
|
||||
textureHeight(0),
|
||||
numTextures(1),
|
||||
textMem(0),
|
||||
glyphHeight(0),
|
||||
glyphWidth(0),
|
||||
padding(1)
|
||||
{}
|
||||
|
||||
FTGLTextureFont::~FTGLTextureFont()
|
||||
{
|
||||
glDeleteTextures( numTextures, (const GLuint*)glTextureID);
|
||||
ContextTextureId::iterator itr;
|
||||
for(itr=glContextTextureID.begin();itr != glContextTextureID.end(); itr++)
|
||||
{
|
||||
glDeleteTextures( numTextures, (const GLuint*)*itr);
|
||||
delete *itr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool FTGLTextureFont::MakeGlyphList()
|
||||
// mrn@changes
|
||||
bool FTGLTextureFont::MakeGlyphList(unsigned int renderContext)
|
||||
{
|
||||
if( !maxTextSize)
|
||||
glGetIntegerv( GL_MAX_TEXTURE_SIZE, (GLint*)&maxTextSize);
|
||||
|
||||
glyphHeight = ( charSize.Height()) + padding;
|
||||
glyphWidth = ( charSize.Width()) + padding;
|
||||
|
||||
GetSize();
|
||||
GLuint totalMem;
|
||||
FTGlyphContainer* glyphList=_contextGlyphList[renderContext];
|
||||
|
||||
if( textureHeight > (maxTextSize-padding*2))
|
||||
{
|
||||
numTextures = static_cast<int>( textureHeight / (maxTextSize-padding*2)) + 1;
|
||||
if( numTextures > 15) // FIXME
|
||||
numTextures = 15;
|
||||
|
||||
GLsizei heightRemain = NextPowerOf2( textureHeight % (maxTextSize-padding*2));
|
||||
totalMem = ((maxTextSize * ( numTextures - 1)) + heightRemain) * textureWidth;
|
||||
// check the context
|
||||
while (glContextTextureID.size() <= renderContext)
|
||||
glContextTextureID.push_back(NULL);
|
||||
|
||||
unsigned long* glTextureID=glContextTextureID[renderContext];
|
||||
if(glTextureID)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
glTextureID=new unsigned long[16];
|
||||
glContextTextureID[renderContext]=glTextureID;
|
||||
}
|
||||
|
||||
glGenTextures( numTextures, (GLuint*)&glTextureID[0]);
|
||||
|
||||
textMem = new unsigned char[totalMem]; // GL_ALPHA texture;
|
||||
memset( textMem, 0, totalMem);
|
||||
|
||||
unsigned int glyphNum = 0;
|
||||
unsigned char* currTextPtr = textMem;
|
||||
|
||||
for( int x = 0; x < numTextures - 1; ++x)
|
||||
{
|
||||
glyphNum = FillGlyphs( glyphNum, glTextureID[x], textureWidth, maxTextSize, currTextPtr);
|
||||
|
||||
CreateTexture( x, textureWidth, maxTextSize, currTextPtr);
|
||||
|
||||
currTextPtr += ( textureWidth * maxTextSize);
|
||||
++glyphNum;
|
||||
}
|
||||
|
||||
glyphNum = FillGlyphs( glyphNum, glTextureID[numTextures - 1], textureWidth, heightRemain, currTextPtr);
|
||||
CreateTexture( numTextures - 1, textureWidth, heightRemain, currTextPtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
textureHeight = NextPowerOf2( textureHeight+padding*2);
|
||||
totalMem = textureWidth * textureHeight;
|
||||
|
||||
glGenTextures( numTextures, (GLuint*)&glTextureID[0]);
|
||||
|
||||
textMem = new unsigned char[totalMem]; // GL_ALPHA texture;
|
||||
memset( textMem, 0, totalMem);
|
||||
|
||||
FillGlyphs( 0, glTextureID[0], textureWidth, textureHeight, textMem);
|
||||
CreateTexture( 0, textureWidth, textureHeight, textMem);
|
||||
}
|
||||
|
||||
delete [] textMem;
|
||||
return !err;
|
||||
}
|
||||
|
||||
unsigned int FTGLTextureFont::FillGlyphs( unsigned int glyphStart, GLuint id, GLsizei width, GLsizei height, unsigned char* textdata)
|
||||
{
|
||||
int currentTextX = padding;
|
||||
int currentTextY = padding;// + padding;
|
||||
|
||||
float currTextU = (float)padding / (float)width;
|
||||
float currTextV = (float)padding / (float)height;
|
||||
|
||||
unsigned int n;
|
||||
if( !maxTextSize)
|
||||
glGetIntegerv( GL_MAX_TEXTURE_SIZE, (GLint*)&maxTextSize);
|
||||
|
||||
for( n = glyphStart; n <= numGlyphs; ++n)
|
||||
{
|
||||
FT_Glyph* ftGlyph = face.Glyph( n, FT_LOAD_NO_HINTING);
|
||||
|
||||
if( ftGlyph)
|
||||
{
|
||||
unsigned char* data = textdata + (( currentTextY * width) + currentTextX);
|
||||
|
||||
currTextU = (float)currentTextX / (float)width;
|
||||
|
||||
FTTextureGlyph* tempGlyph = new FTTextureGlyph( *ftGlyph, id, data, width, height, currTextU, currTextV);
|
||||
glyphList->Add( tempGlyph);
|
||||
glyphHeight = ( charSize.Height()) + padding;
|
||||
glyphWidth = ( charSize.Width()) + padding;
|
||||
|
||||
GetSize();
|
||||
GLuint totalMem;
|
||||
|
||||
currentTextX += glyphWidth;
|
||||
if( currentTextX > ( width - glyphWidth))
|
||||
{
|
||||
currentTextY += glyphHeight;
|
||||
if( currentTextY > ( height - glyphHeight))
|
||||
return n;
|
||||
|
||||
currentTextX = padding;
|
||||
currTextV = (float)currentTextY / (float)height;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
err = face.Error();
|
||||
}
|
||||
}
|
||||
if( textureHeight > (maxTextSize-padding*2))
|
||||
{
|
||||
numTextures = static_cast<int>( textureHeight / (maxTextSize-padding*2)) + 1;
|
||||
if( numTextures > 15) // FIXME
|
||||
numTextures = 15;
|
||||
|
||||
GLsizei heightRemain = NextPowerOf2( textureHeight % (maxTextSize-padding*2));
|
||||
totalMem = ((maxTextSize * ( numTextures - 1)) + heightRemain) * textureWidth;
|
||||
|
||||
glGenTextures( numTextures, (GLuint*)&glTextureID[0]);
|
||||
|
||||
textMem = new unsigned char[totalMem]; // GL_ALPHA texture;
|
||||
memset( textMem, 0, totalMem);
|
||||
|
||||
unsigned int glyphNum = 0;
|
||||
unsigned char* currTextPtr = textMem;
|
||||
|
||||
for( int x = 0; x < numTextures - 1; ++x)
|
||||
{
|
||||
glyphNum = FillGlyphs( glyphNum, glTextureID[x], textureWidth, maxTextSize, currTextPtr,renderContext);
|
||||
|
||||
CreateTexture( glTextureID[x], textureWidth, maxTextSize, currTextPtr);
|
||||
|
||||
currTextPtr += ( textureWidth * maxTextSize);
|
||||
++glyphNum;
|
||||
}
|
||||
|
||||
glyphNum = FillGlyphs( glyphNum, glTextureID[numTextures - 1], textureWidth, heightRemain, currTextPtr,renderContext);
|
||||
CreateTexture( glTextureID[numTextures - 1], textureWidth, heightRemain, currTextPtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
textureHeight = NextPowerOf2( textureHeight+padding*2);
|
||||
totalMem = textureWidth * textureHeight;
|
||||
|
||||
glGenTextures( numTextures, (GLuint*)&glTextureID[0]);
|
||||
|
||||
textMem = new unsigned char[totalMem]; // GL_ALPHA texture;
|
||||
memset( textMem, 0, totalMem);
|
||||
|
||||
FillGlyphs( 0, glTextureID[0], textureWidth, textureHeight, textMem,renderContext);
|
||||
CreateTexture( glTextureID[0], textureWidth, textureHeight, textMem);
|
||||
}
|
||||
|
||||
delete [] textMem;
|
||||
return !err;
|
||||
}
|
||||
|
||||
// mrn@changes
|
||||
unsigned int FTGLTextureFont::FillGlyphs( unsigned int glyphStart, GLuint id, GLsizei width, GLsizei height, unsigned char* textdata, unsigned int renderContext)
|
||||
{
|
||||
FTGlyphContainer* glyphList=_contextGlyphList[renderContext];
|
||||
|
||||
int currentTextX = padding;
|
||||
int currentTextY = padding;// + padding;
|
||||
|
||||
float currTextU = (float)padding / (float)width;
|
||||
float currTextV = (float)padding / (float)height;
|
||||
|
||||
unsigned int n;
|
||||
|
||||
for( n = glyphStart; n <= numGlyphs; ++n)
|
||||
{
|
||||
FT_Glyph* ftGlyph = face.Glyph( n, FT_LOAD_NO_HINTING);
|
||||
|
||||
if( ftGlyph)
|
||||
{
|
||||
unsigned char* data = textdata + (( currentTextY * width) + currentTextX);
|
||||
|
||||
currTextU = (float)currentTextX / (float)width;
|
||||
|
||||
FTTextureGlyph* tempGlyph = new FTTextureGlyph( *ftGlyph, id, data, width, height, currTextU, currTextV);
|
||||
glyphList->Add( tempGlyph);
|
||||
|
||||
currentTextX += glyphWidth;
|
||||
if( currentTextX > ( width - glyphWidth))
|
||||
{
|
||||
currentTextY += glyphHeight;
|
||||
if( currentTextY > ( height - glyphHeight))
|
||||
return n;
|
||||
|
||||
currentTextX = padding;
|
||||
currTextV = (float)currentTextY / (float)height;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
err = face.Error();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return n;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
void FTGLTextureFont::GetSize()
|
||||
{
|
||||
//work out the max width. Most likely maxTextSize
|
||||
textureWidth = NextPowerOf2( (numGlyphs * glyphWidth) + padding*2);
|
||||
if( textureWidth > maxTextSize)
|
||||
{
|
||||
textureWidth = maxTextSize;
|
||||
}
|
||||
|
||||
int h = static_cast<int>( (textureWidth-padding*2) / glyphWidth);
|
||||
//work out the max width. Most likely maxTextSize
|
||||
textureWidth = NextPowerOf2( (numGlyphs * glyphWidth) + padding*2);
|
||||
if( textureWidth > maxTextSize)
|
||||
{
|
||||
textureWidth = maxTextSize;
|
||||
}
|
||||
|
||||
int h = static_cast<int>( (textureWidth-padding*2) / glyphWidth);
|
||||
|
||||
textureHeight = (( numGlyphs / h) + 1) * glyphHeight;
|
||||
textureHeight = (( numGlyphs / h) + 1) * glyphHeight;
|
||||
}
|
||||
|
||||
|
||||
// mrn@changes
|
||||
void FTGLTextureFont::CreateTexture( GLuint id, GLsizei width, GLsizei height, unsigned char* data)
|
||||
{
|
||||
glPixelStorei( GL_UNPACK_ALIGNMENT, 1); //What does this do exactly?
|
||||
glBindTexture( GL_TEXTURE_2D, glTextureID[id]);
|
||||
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);
|
||||
glPixelStorei( GL_UNPACK_ALIGNMENT, 1); //What does this do exactly?
|
||||
glBindTexture( GL_TEXTURE_2D, id);
|
||||
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, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data);
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
|
||||
|
||||
void FTGLTextureFont::render( const char* string)
|
||||
{
|
||||
glPushAttrib( GL_ENABLE_BIT | GL_HINT_BIT | GL_LINE_BIT | GL_PIXEL_MODE_BIT);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
|
||||
|
||||
FTFont::render( string);
|
||||
// mrn@changes
|
||||
void FTGLTextureFont::render( const char* string, unsigned int renderContext)
|
||||
{
|
||||
glPushAttrib( GL_ENABLE_BIT | GL_HINT_BIT | GL_LINE_BIT | GL_PIXEL_MODE_BIT);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
|
||||
|
||||
FTFont::render( string,renderContext);
|
||||
|
||||
glPopAttrib();
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
|
||||
void FTGLTextureFont::render( const wchar_t* string)
|
||||
{
|
||||
glPushAttrib( GL_ENABLE_BIT | GL_HINT_BIT | GL_LINE_BIT | GL_PIXEL_MODE_BIT);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
|
||||
|
||||
FTFont::render( string);
|
||||
|
||||
glPopAttrib();
|
||||
// mrn@changes
|
||||
void FTGLTextureFont::render( const wchar_t* string, unsigned int renderContext)
|
||||
{
|
||||
glPushAttrib( GL_ENABLE_BIT | GL_HINT_BIT | GL_LINE_BIT | GL_PIXEL_MODE_BIT);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE
|
||||
|
||||
FTFont::render( string,renderContext);
|
||||
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user