84d2d01163
memory manager published at flipcode.com. This can be turned on with the OSG_USE_MEMORY_MANGER option which then uses custom global new and delete operators as well as provide osgNew and osgDelete macro's which add ability to log line and file from which calls are made. Updated osg,osgUtil,osgDB,osgText and osgPlugins/osg to use osgNew/osgDelete, and fixed memory leaks highlighted by the new memory manager.
238 lines
6.7 KiB
C++
238 lines
6.7 KiB
C++
#include "FTGLTextureFont.h"
|
|
#include "FTGlyphContainer.h"
|
|
#include "FTTextureGlyph.h"
|
|
|
|
#include <osg/DisplaySettings>
|
|
|
|
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()
|
|
: maxTextSize(0),
|
|
textureWidth(0),
|
|
textureHeight(0),
|
|
numTextures(1),
|
|
textMem(0),
|
|
glyphHeight(0),
|
|
glyphWidth(0),
|
|
padding(1)
|
|
{
|
|
glContextTextureID.resize(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts(),0);
|
|
}
|
|
|
|
FTGLTextureFont::FTGLTextureFont(int textureSize)
|
|
: maxTextSize(textureSize),
|
|
textureWidth(0),
|
|
textureHeight(0),
|
|
numTextures(1),
|
|
textMem(0),
|
|
glyphHeight(0),
|
|
glyphWidth(0),
|
|
padding(1)
|
|
{
|
|
glContextTextureID.resize(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts(),0);
|
|
}
|
|
|
|
FTGLTextureFont::~FTGLTextureFont()
|
|
{
|
|
ContextTextureId::iterator itr;
|
|
for(itr=glContextTextureID.begin();itr != glContextTextureID.end(); itr++)
|
|
{
|
|
glDeleteTextures( numTextures, (const GLuint*)*itr);
|
|
osgDelete [] *itr;
|
|
}
|
|
}
|
|
|
|
|
|
// mrn@changes
|
|
bool FTGLTextureFont::MakeGlyphList(unsigned int renderContext)
|
|
{
|
|
// FTGlyphContainer* glyphList=_contextGlyphList[renderContext];
|
|
|
|
// check the context
|
|
if (glContextTextureID.size() <= renderContext)
|
|
glContextTextureID.resize(renderContext,0);
|
|
|
|
unsigned long* glTextureID=glContextTextureID[renderContext];
|
|
if(glTextureID)
|
|
return true;
|
|
else
|
|
{
|
|
glTextureID=new unsigned long[16];
|
|
glContextTextureID[renderContext]=glTextureID;
|
|
}
|
|
|
|
if( !maxTextSize)
|
|
glGetIntegerv( GL_MAX_TEXTURE_SIZE, (GLint*)&maxTextSize);
|
|
|
|
glyphHeight = ( charSize.Height()) + padding;
|
|
glyphWidth = ( charSize.Width()) + padding;
|
|
|
|
GetSize();
|
|
GLuint totalMem;
|
|
|
|
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 = osgNew 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 = osgNew unsigned char[totalMem]; // GL_ALPHA texture;
|
|
memset( textMem, 0, totalMem);
|
|
|
|
FillGlyphs( 0, glTextureID[0], textureWidth, textureHeight, textMem,renderContext);
|
|
CreateTexture( glTextureID[0], textureWidth, textureHeight, textMem);
|
|
}
|
|
|
|
osgDelete [] 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 = osgNew 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;
|
|
}
|
|
|
|
|
|
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);
|
|
|
|
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, 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);
|
|
}
|
|
|
|
|
|
// 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();
|
|
}
|
|
|
|
|
|
// 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();
|
|
}
|
|
|