Further improvements to osgText and the freetype plugin, handling different

font sizes better and plugin removal safely.
This commit is contained in:
Robert Osfield
2003-03-04 12:34:42 +00:00
parent 09d0d0e887
commit 1c34c0981e
13 changed files with 125 additions and 29 deletions

View File

@@ -79,7 +79,7 @@ osg::Node* createHUD()
geode->addDrawable( text );
text->setFont(timesFont);
text->setText("Then place a osg::Projection node above the subgraph\nto create an othrograph projection.");
text->setText("Then place a osg::Projection node above the subgraph\nto create an orthographic projection.");
text->setPosition(position);
position += delta;

View File

@@ -13,6 +13,7 @@
#include <osgUtil/Optimizer>
#include <osgDB/ReadFile>
#include <osgDB/Registry>
#include <osgProducer/Viewer>
#include <osg/Material>
@@ -49,7 +50,7 @@ osg::Group* createHUDText()
osgText::Text* text4 = new osgText::Text;
text4->setFont(osgText::readFontFile("fonts/times.ttf"));
text4->setFontSize(64,64);
text4->setFontSize(128,128);
text4->setPosition(osg::Vec3(200.0f,200.0f,0.0f));
text4->setLayout(osgText::Text::RIGHT_TO_LEFT);
text4->setDrawMode(osgText::Text::TEXT|osgText::Text::ALIGNMENT|osgText::Text::BOUNDINGBOX);
@@ -126,7 +127,6 @@ osg::Group* create3DText()
int main( int argc, char **argv )
{
// use an ArgumentParser object to manage the program arguments.
osg::ArgumentParser arguments(&argc,argv);
@@ -211,7 +211,7 @@ int main( int argc, char **argv )
// set the scene to render
viewer.setSceneData(rootNode.get());
// create the windows and run the threads.
viewer.realize(Producer::CameraGroup::ThreadPerCamera);
@@ -228,6 +228,6 @@ int main( int argc, char **argv )
viewer.frame();
}
return 0;
}

View File

@@ -108,7 +108,9 @@ class ref_ptr
* return the pointer to the object.
* Note, do not use this unless you are 100% sure your code handles the deletion of the object correctly, and
* only use when absolutely required.*/
inline T* take() { T* tmp=_ptr; if (_ptr) _ptr->unref_nodelete(); _ptr=0; return tmp;}
inline T* take() { return release();}
inline T* release() { T* tmp=_ptr; if (_ptr) _ptr->unref_nodelete(); _ptr=0; return tmp;}
private:
T* _ptr;

View File

@@ -23,10 +23,12 @@
#include <osgText/Export>
#include <string>
#include <set>
namespace osgText {
class Font;
class Text;
/** read a font from specified file.*/
extern OSGTEXT_EXPORT Font* readFontFile(const std::string& filename);
@@ -66,21 +68,30 @@ public:
virtual bool hasVertical() const = 0;
// make Text a friend to allow it add and remove its entry in the Font's _textList.
friend Text;
protected:
virtual ~Font();
void addGlyph(unsigned int charcode, Glyph* glyph);
void addGlyph(unsigned int width, unsigned int height, unsigned int charcode, Glyph* glyph);
typedef std::vector< osg::ref_ptr<GlyphTexture> > GlyphTextureList;
typedef std::vector< osg::ref_ptr<osg::StateSet> > StateSetList;
typedef std::map< unsigned int, osg::ref_ptr<Glyph> > GlyphMap;
GlyphMap _glyphMap;
typedef std::pair< unsigned int, unsigned int > SizePair;
typedef std::map< SizePair, GlyphMap > SizeGlyphMap;
typedef std::set< Text* > TextList;
SizeGlyphMap _sizeGlyphMap;
GlyphTextureList _glyphTextureList;
StateSetList _stateSetList;
// list of text object to contact when Font is forcebly removed.
TextList _textList;
// current active size of font
unsigned int _width;
unsigned int _height;
@@ -135,9 +146,6 @@ public:
unsigned int getGlyphCode() const;
void setFont(Font* font);
Font* getFont() const;
void setHorizontalBearing(const osg::Vec2& bearing);
const osg::Vec2& getHorizontalBearing() const;

View File

@@ -182,6 +182,10 @@ public:
/** Draw the text.*/
virtual void drawImplementation(osg::State& state) const;
// make Font a friend to allow it set the _font to 0 if the font is
// forcefully unloaded.
friend Font;
protected:
virtual ~Text();

View File

@@ -109,7 +109,7 @@ osg::Node* createHUD()
geode->addDrawable( text );
text->setFont(timesFont);
text->setText("Then place a osg::Projection node above the subgraph\nto create an othrograph projection.");
text->setText("Then place a osg::Projection node above the subgraph\nto create an orthographic projection.");
text->setPosition(position);
position += delta;

View File

@@ -22,6 +22,10 @@ FreeTypeFont::FreeTypeFont(const std::string& filename, FT_Face face):
{
}
FreeTypeFont::~FreeTypeFont()
{
}
void FreeTypeFont::setSize(unsigned int width, unsigned int height)
{
FT_Error error = FT_Set_Pixel_Sizes( _face, /* handle to face object */
@@ -42,9 +46,13 @@ void FreeTypeFont::setSize(unsigned int width, unsigned int height)
osgText::Font::Glyph* FreeTypeFont::getGlyph(unsigned int charcode)
{
// search for glyph amoungst existing glyphs.
GlyphMap::iterator itr = _glyphMap.find(charcode);
if (itr!=_glyphMap.end()) return itr->second.get();
SizeGlyphMap::iterator itr = _sizeGlyphMap.find(SizePair(_width,_height));
if (itr!=_sizeGlyphMap.end())
{
GlyphMap& glyphmap = itr->second;
GlyphMap::iterator gitr = glyphmap.find(charcode);
if (gitr!=glyphmap.end()) return gitr->second.get();
}
FT_Error error = FT_Load_Char( _face, charcode, FT_LOAD_RENDER|FT_LOAD_NO_BITMAP );
if (error)
@@ -83,13 +91,12 @@ osgText::Font::Glyph* FreeTypeFont::getGlyph(unsigned int charcode)
FT_Glyph_Metrics* metrics = &(glyphslot->metrics);
glyph->setFont(this);
glyph->setHorizontalBearing(osg::Vec2((float)metrics->horiBearingX/64.0f,(float)(metrics->horiBearingY-metrics->height)/64.0f)); // bottom left.
glyph->setHorizontalAdvance((float)metrics->horiAdvance/64.0f);
glyph->setVerticalBearing(osg::Vec2((float)metrics->vertBearingX/64.0f,(float)(metrics->vertBearingY-metrics->height)/64.0f)); // top middle.
glyph->setVerticalAdvance((float)metrics->vertAdvance/64.0f);
addGlyph(charcode,glyph.get());
addGlyph(_width,_height,charcode,glyph.get());
return glyph.get();

View File

@@ -26,6 +26,8 @@ public:
FreeTypeFont(const std::string& filename, FT_Face face);
virtual ~FreeTypeFont();
virtual std::string getFileName() const { return _filename; }
virtual void setSize(unsigned int width, unsigned int height);

View File

@@ -26,6 +26,26 @@ FreeTypeLibrary::FreeTypeLibrary()
FreeTypeLibrary::~FreeTypeLibrary()
{
for(FontMap::iterator itr=_fontMap.begin();
itr!=_fontMap.end();
++itr)
{
FreeTypeFont* freetypefont = itr->second.get();
if (freetypefont->referenceCount()>1)
{
// external references must exist...
itr->second = 0;
delete freetypefont;
}
else
{
// no external references exist so its safe to delete via set the ref_ptr to 0.
itr->second = 0;
}
}
FT_Done_FreeType( _ftlibrary);
}
@@ -37,6 +57,10 @@ FreeTypeLibrary* FreeTypeLibrary::instance()
FreeTypeFont* FreeTypeLibrary::getFont(const std::string& fontfile,unsigned int index)
{
FontMap::iterator itr = _fontMap.find(fontfile);
if (itr!=_fontMap.end()) return itr->second.get();
FT_Face face; /* handle to face object */
FT_Error error = FT_New_Face( _ftlibrary, fontfile.c_str(), index, &face );
if (error == FT_Err_Unknown_File_Format)
@@ -52,6 +76,8 @@ FreeTypeFont* FreeTypeLibrary::getFont(const std::string& fontfile,unsigned int
return 0;
}
return new FreeTypeFont(fontfile,face);
FreeTypeFont* font = new FreeTypeFont(fontfile,face);
_fontMap[fontfile]=font;
return font;
}

View File

@@ -34,8 +34,11 @@ protected:
* library is via the singleton instance method.*/
FreeTypeLibrary();
typedef std::map< std::string, osg::ref_ptr<FreeTypeFont> > FontMap;
FT_Library _ftlibrary;
FontMap _fontMap;
};

View File

@@ -44,8 +44,36 @@ void DefaultFont::setSize(unsigned int, unsigned int)
Font::Glyph* DefaultFont::getGlyph(unsigned int charcode)
{
GlyphMap::iterator itr = _glyphMap.find(charcode);
if (itr!=_glyphMap.end()) return itr->second.get();
if (_sizeGlyphMap.empty()) return 0;
SizeGlyphMap::iterator itr = _sizeGlyphMap.find(SizePair(_width,_height));
if (itr==_sizeGlyphMap.end())
{
// no font found of correct size, will need to find the nearest.
itr = _sizeGlyphMap.begin();
int mindeviation = abs(_width-itr->first.first)+
abs(_height-itr->first.second);
SizeGlyphMap::iterator sitr=itr;
++sitr;
for(;
sitr!=_sizeGlyphMap.end();
++sitr)
{
int deviation = abs(_width-sitr->first.first)+
abs(_height-sitr->first.second);
if (deviation<mindeviation)
{
mindeviation = deviation;
itr = sitr;
}
}
}
// new find the glyph for the required charcode.
GlyphMap& glyphmap = itr->second;
GlyphMap::iterator gitr = glyphmap.find(charcode);
if (gitr!=glyphmap.end()) return gitr->second.get();
else return 0;
}
@@ -203,13 +231,12 @@ void DefaultFont::constructGlyphs()
}
glyph->setFont(this);
glyph->setHorizontalBearing(osg::Vec2(0.0f,0.0f)); // bottom left.
glyph->setHorizontalAdvance((float)_width);
glyph->setVerticalBearing(osg::Vec2((float)_width*0.5f,(float)_height)); // top middle.
glyph->setVerticalAdvance((float)_height);
addGlyph(i,glyph.get());
addGlyph(_width,_height,i,glyph.get());
}
}

View File

@@ -12,6 +12,7 @@
*/
#include <osgText/Font>
#include <osgText/Text>
#include <osg/State>
#include <osg/Notify>
@@ -82,11 +83,18 @@ Font::Font():
Font::~Font()
{
for(TextList::iterator itr=_textList.begin();
itr!=_textList.end();
++itr)
{
Text* text = *itr;
text->_font.release();
}
}
void Font::addGlyph(unsigned int charcode, Glyph* glyph)
void Font::addGlyph(unsigned int width, unsigned int height, unsigned int charcode, Glyph* glyph)
{
_glyphMap[charcode]=glyph;
_sizeGlyphMap[SizePair(width,height)][charcode]=glyph;
int posX=0,posY=0;
@@ -297,8 +305,8 @@ Font::Glyph::~Glyph() {}
unsigned int Font::Glyph::getGlyphCode() const { return _glyphCode; }
void Font::Glyph::setFont(Font* font) { _font = font; }
Font* Font::Glyph::getFont() const { return _font; }
// void Font::Glyph::setFont(Font* font) { _font = font; }
// Font* Font::Glyph::getFont() const { return _font; }
void Font::Glyph::setHorizontalBearing(const osg::Vec2& bearing) { _horizontalBearing=bearing; }
const osg::Vec2& Font::Glyph::getHorizontalBearing() const { return _horizontalBearing; }

View File

@@ -51,15 +51,26 @@ Text::Text(const Text& text,const osg::CopyOp& copyop):
_color(text._color),
_drawMode(text._drawMode)
{
if (_font.valid()) _font->_textList.insert(this);
}
Text::~Text()
{
if (_font.valid()) _font->_textList.erase(this);
}
void Text::setFont(Font* font)
{
if (_font==font) return;
// unregister from the old font.
if (_font.valid()) _font->_textList.erase(this);
_font = font;
// register with the new font.
if (_font.valid()) _font->_textList.insert(this);
computeGlyphRepresentation();
}
@@ -393,8 +404,6 @@ void Text::computePositions()
void Text::drawImplementation(osg::State& state) const
{
glPushMatrix();
// draw part.
@@ -424,7 +433,7 @@ void Text::drawImplementation(osg::State& state) const
if (_drawMode & TEXT)
{
bool first = true;
bool first = false;
for(TextureGlyphQuadMap::const_iterator titr=_textureGlyphQuadMap.begin();
titr!=_textureGlyphQuadMap.end();