[osg-users] Is text thread safe in 2.0.0?

sherman wilcox wilcox.sherman at gmail.com
Sun Sep 2 13:16:27 PDT 2007


I spent a few moments digging into the crash I was having...looks like
a race condition in DefaultFont* DefaultFont::instance(). I wasn't
sure about the best course, but I thought the simplest solution was to
wrap that call with a mutex, which I did. After doing that, no more
crashes when I run --mt 10 in Release mode. I've attached the changes
defaultfont.h/.cpp.

BUT...I still get crashes in debug mode @ --mt 10 The crashes are
easily reproduced. I left the code running for quite a while in
Release mode, didn't crash. Debug dies immediatly.


I've attached the changes defaultfont.h/.cpp.


Here's a call stack from the new crashes...in void
Font::GlyphTexture::apply(osg::State& state)  I noticed that the
elements in the _glyphs container had bad _font objects...these _font
objects had addresses of 0xcdcdcdcd. Not sure at what point things
went off into the weeds.

Stack trace from most recent crash:

>	osgTextd.dll!std::_Vector_const_iterator<osg::ref_ptr<osgText::Font::Glyph>,std::allocator<osg::ref_ptr<osgText::Font::Glyph>
> >::operator++()  Line 117 + 0x33 bytes	C++
 	osgTextd.dll!osgText::Font::GlyphTexture::apply(osg::State &
state={...})  Line 653 + 0x8 bytes	C++
 	osgd.dll!osg::State::applyAttribute(const osg::StateAttribute *
attribute=0x0195c730, osg::State::AttributeStack & as={...})  Line
1158 + 0x13 bytes	C++
 	osgd.dll!osg::State::applyTextureAttribute(unsigned int unit=0,
const osg::StateAttribute * attribute=0x0195c730)  Line 337 + 0x10
bytes	C++
 	osgTextd.dll!osgText::Text::renderOnlyForegroundText(osg::State &
state={...}, const osg::Vec4f & colorMultiplier={...})  Line 1971 +
0x1d bytes	C++
 	osgTextd.dll!osgText::Text::drawImplementation(osg::State &
state={...}, const osg::Vec4f & colorMultiplier={...})  Line 1587	C++
 	osgTextd.dll!osgText::Text::drawImplementation(osg::RenderInfo &
renderInfo={...})  Line 1471	C++
 	osgd.dll!osg::Drawable::draw(osg::RenderInfo & renderInfo={...})
Line 868 + 0x13 bytes	C++
 	osgUtild.dll!osgUtil::RenderLeaf::render(osg::RenderInfo &
renderInfo={...}, osgUtil::RenderLeaf * previous=0x09837b28)  Line 60
+ 0x19 bytes	C++
 	osgUtild.dll!osgUtil::RenderBin::drawImplementation(osg::RenderInfo
& renderInfo={...}, osgUtil::RenderLeaf * & previous=0x09837b28)  Line
408 + 0x19 bytes	C++
 	osgUtild.dll!osgUtil::RenderBin::draw(osg::RenderInfo &
renderInfo={...}, osgUtil::RenderLeaf * & previous=0x09837b28)  Line
373 + 0x17 bytes	C++
 	osgUtild.dll!osgUtil::RenderBin::drawImplementation(osg::RenderInfo
& renderInfo={...}, osgUtil::RenderLeaf * & previous=0x09837b28)  Line
458 + 0x35 bytes	C++
 	osgUtild.dll!osgUtil::RenderStage::drawImplementation(osg::RenderInfo
& renderInfo={...}, osgUtil::RenderLeaf * & previous=0x09837b28)  Line
1053	C++
 	osgUtild.dll!osgUtil::RenderBin::draw(osg::RenderInfo &
renderInfo={...}, osgUtil::RenderLeaf * & previous=0x09837b28)  Line
373 + 0x17 bytes	C++
 	osgUtild.dll!osgUtil::RenderStage::drawInner(osg::RenderInfo &
renderInfo={...}, osgUtil::RenderLeaf * & previous=0x09837b28, bool &
doCopyTexture=false)  Line 722	C++
 	osgUtild.dll!osgUtil::RenderStage::draw(osg::RenderInfo &
renderInfo={...}, osgUtil::RenderLeaf * & previous=0x09837b28)  Line
913 + 0x1b bytes	C++
 	osgUtild.dll!osgUtil::SceneView::draw()  Line 1456 + 0x34 bytes	C++
 	osgViewerd.dll!osgViewer::Renderer::draw()  Line 382 + 0xf bytes	C++
 	osgViewerd.dll!osgViewer::Renderer::operator()(osg::GraphicsContext
* context=0x01926430)  Line 573	C++
 	osgd.dll!osg::GraphicsContext::runOperations()  Line 671 + 0x33 bytes	C++
 	osgd.dll!osg::RunOperations::operator()(osg::GraphicsContext *
context=0x01926430)  Line 135	C++
 	osgd.dll!osg::GraphicsOperation::operator()(osg::Object *
object=0x01926430)  Line 50 + 0x19 bytes	C++
 	osgd.dll!osg::OperationThread::run()  Line 413 + 0x26 bytes	C++
 	osgd.dll!osg::GraphicsThread::run()  Line 40	C++
 	OpenThreadsd.dll!OpenThreads::ThreadPrivateActions::StartThread(void
* data=0x018f9740)  Line 106 + 0xf bytes	C++
 	msvcr80d.dll!__beginthreadex()  + 0x221 bytes	
 	msvcr80d.dll!__beginthreadex()  + 0x1c7 bytes	
 	kernel32.dll!@BaseThreadInitThunk at 12()  + 0xe bytes	
 	ntdll.dll!__RtlUserThreadStart at 8()  + 0x23 bytes	






Here's the debug call stack of the original crash:

osgTextd.dll!osg::ref_ptr<osg::StateSet>::get()  Line 71 + 0x11 bytes C++
osgTextd.dll!osgText::Font::getStateSet()  Line 97 + 0x19 bytes C++
> osgTextd.dll!osgText::Text::Text()  Line 61 + 0xc bytes C++
osgtest.exe!UpdateTextOperation::load()  Line 556 + 0x2e bytes C++
osgtest.exe!UpdateTextOperation::operator()(osg::Object *
callingObject=0x00000000)  Line 499 C++
osgd.dll!osg::OperationThread::run()  Line 413 + 0x26 bytes C++
OpenThreadsd.dll!OpenThreads::ThreadPrivateActions::StartThread(void *
data=0x0174cdb8)  Line 106 + 0xf bytes C++
msvcr80d.dll!_callthreadstartex()  Line 348 + 0xf bytes C
msvcr80d.dll!_threadstartex(void * ptd=0x0174da48)  Line 331 C
kernel32.dll!7c80b683()
[Frames below may be incorrect and/or missing, no symbols loaded for
kernel32.dll]


On 9/2/07, Robert Osfield <robert.osfield at gmail.com> wrote:
> Hi Sherman,
>
> On 9/1/07, sherman wilcox <wilcox.sherman at gmail.com> wrote:
> > If I run with --mt 1 it runs for a bit....however if I change that to --mt
> > 10 it crashes immediately. Tried this on an old dual-proc and a new
> > quad-core system. Here's the stack from the quad-core:
> >
> > > osgText.dll!osgText::Text::Text()  Line 61 + 0x5 bytes C++
> >   osgtest.exe!UpdateTextOperation::load()  Line 556 + 0x24
> > bytes C++
> >   osgtest.exe!UpdateTextOperation::operator()(osg::Object *
> > callingObject=0x00000000)  Line 498 + 0x5 bytes C++
> >   osg.dll!osg::OperationThread::run()  Line 416 C++
> >
> > OpenThreads.dll!OpenThreads::ThreadPrivateActions::StartThread(void
> > * data=0x00f7cda8)  Line 120 C++
> >   msvcr80.dll!__endthreadex()  + 0x3b bytes
> >   msvcr80.dll!__endthreadex ()  + 0xc7 bytes
> >   kernel32.dll!@BaseThreadInitThunk at 12()  + 0xe bytes
> >   ntdll.dll!__RtlUserThreadStart at 8 ()  + 0x23 bytes
> >
> > I'm grabbed a copy out of SVN about 30 minutes after you posted. So, I
> > believe I have the right code. If you want me to perform any further
> > testing/changes just yell.
>
> Originally I was getting crashes in the Text constructor to the lack
> of thread safety on Node,Drawable and StateSet addParent.  This is now
> mutexed so "shouldn't" be giving problems.. at least I don't get
> problems with it any more.
>
> I'll test it once again to see if I can knock it over.  Perhaps its a
> different problems to the addParent.  Could you try with a debug
> version so we can get where abouts within the Text constructor its
> crashing.
>
> Thanks,
> Robert.
> _______________________________________________
> osg-users mailing list
> osg-users at lists.openscenegraph.org
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>
-------------- next part --------------
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 
 *
 * This library is open source and may be redistributed and/or modified under  
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY{
}

 without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 * OpenSceneGraph Public License for more details.
*/

#include "DefaultFont.h"

#include <osg/Notify>

using namespace osgText;

OpenThreads::Mutex DefaultFont::_mutex;    

DefaultFont::DefaultFont()
{
    _minFilterHint = osg::Texture::LINEAR_MIPMAP_LINEAR;
    _magFilterHint = osg::Texture::NEAREST;
    constructGlyphs();
}

DefaultFont::~DefaultFont()
{
}

DefaultFont* DefaultFont::instance()
{
	OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
    static osg::ref_ptr<DefaultFont> s_defaultFont = new DefaultFont;
    return s_defaultFont.get();
}

void DefaultFont::setSize(unsigned int, unsigned int)
{
    osg::notify(osg::INFO)<<"DefaultFont::setSize(,) call is ignored."<<std::endl;
}



Font::Glyph* DefaultFont::getGlyph(unsigned int charcode)
{
    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((int)_width-(int)itr->first.first)+
                           abs((int)_height-(int)itr->first.second);
        SizeGlyphMap::iterator sitr=itr;
        ++sitr;
        for(;
            sitr!=_sizeGlyphMap.end();
            ++sitr)
        {
            int deviation = abs((int)_width-(int)sitr->first.first)+
                            abs((int)_height-(int)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;
}


osg::Vec2 DefaultFont::getKerning(unsigned int,unsigned int, KerningType)
{
    // no kerning on default font.
    return osg::Vec2(0.0f,0.0f);
}

bool DefaultFont::hasVertical() const
{
    return true;
}

void DefaultFont::constructGlyphs()
{
   static GLubyte rasters[][12] = { // ascii symbols 32-127, small font
        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00},
        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x14, 0x14, 0x00},
        {0x00, 0x00, 0x28, 0x28, 0x7e, 0x14, 0x14, 0x14, 0x3f, 0x0a, 0x0a, 0x00},
        {0x00, 0x00, 0x08, 0x1c, 0x22, 0x02, 0x1c, 0x20, 0x22, 0x1c, 0x08, 0x00},
        {0x00, 0x00, 0x02, 0x45, 0x22, 0x10, 0x08, 0x04, 0x22, 0x51, 0x20, 0x00},
        {0x00, 0x00, 0x3b, 0x44, 0x4a, 0x49, 0x30, 0x10, 0x20, 0x20, 0x18, 0x00},
        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x00},
        {0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00},
        {0x10, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08, 0x10, 0x00},
        {0x00, 0x00, 0x00, 0x00, 0x36, 0x1c, 0x7f, 0x1c, 0x36, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00},
        {0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00},
        {0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x00},
        {0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x08, 0x00},
        {0x00, 0x00, 0x3e, 0x20, 0x10, 0x08, 0x04, 0x02, 0x02, 0x22, 0x1c, 0x00},
        {0x00, 0x00, 0x1c, 0x22, 0x02, 0x02, 0x0c, 0x02, 0x02, 0x22, 0x1c, 0x00},
        {0x00, 0x00, 0x0e, 0x04, 0x3e, 0x24, 0x14, 0x14, 0x0c, 0x0c, 0x04, 0x00},
        {0x00, 0x00, 0x1c, 0x22, 0x02, 0x02, 0x3c, 0x20, 0x20, 0x20, 0x3e, 0x00},
        {0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x10, 0x0c, 0x00},
        {0x00, 0x00, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x22, 0x3e, 0x00},
        {0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00},
        {0x00, 0x00, 0x18, 0x04, 0x02, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x1c, 0x00},
        {0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x04, 0x02, 0x02, 0x22, 0x1c, 0x00},
        {0x00, 0x00, 0x1c, 0x20, 0x4e, 0x55, 0x55, 0x55, 0x4d, 0x21, 0x1e, 0x00},
        {0x00, 0x00, 0x77, 0x22, 0x3e, 0x22, 0x14, 0x14, 0x08, 0x08, 0x18, 0x00},
        {0x00, 0x00, 0x7e, 0x21, 0x21, 0x21, 0x3e, 0x21, 0x21, 0x21, 0x7e, 0x00},
        {0x00, 0x00, 0x1e, 0x21, 0x40, 0x40, 0x40, 0x40, 0x40, 0x21, 0x1e, 0x00},
        {0x00, 0x00, 0x7c, 0x22, 0x21, 0x21, 0x21, 0x21, 0x21, 0x22, 0x7c, 0x00},
        {0x00, 0x00, 0x7f, 0x21, 0x20, 0x24, 0x3c, 0x24, 0x20, 0x21, 0x7f, 0x00},
        {0x00, 0x00, 0x78, 0x20, 0x20, 0x24, 0x3c, 0x24, 0x20, 0x21, 0x7f, 0x00},
        {0x00, 0x00, 0x1e, 0x21, 0x41, 0x47, 0x40, 0x40, 0x40, 0x21, 0x1e, 0x00},
        {0x00, 0x00, 0x77, 0x22, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x22, 0x77, 0x00},
        {0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00},
        {0x00, 0x00, 0x38, 0x44, 0x44, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1e, 0x00},
        {0x00, 0x00, 0x73, 0x22, 0x24, 0x38, 0x28, 0x24, 0x24, 0x22, 0x73, 0x00},
        {0x00, 0x00, 0x7f, 0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00},
        {0x00, 0x00, 0x77, 0x22, 0x22, 0x2a, 0x2a, 0x36, 0x36, 0x22, 0x63, 0x00},
        {0x00, 0x00, 0x72, 0x22, 0x26, 0x26, 0x2a, 0x32, 0x32, 0x22, 0x67, 0x00},
        {0x00, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00},
        {0x00, 0x00, 0x78, 0x20, 0x20, 0x20, 0x3e, 0x21, 0x21, 0x21, 0x7e, 0x00},
        {0x00, 0x1b, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00},
        {0x00, 0x00, 0x73, 0x22, 0x24, 0x24, 0x3e, 0x21, 0x21, 0x21, 0x7e, 0x00},
        {0x00, 0x00, 0x3e, 0x41, 0x01, 0x01, 0x3e, 0x40, 0x40, 0x41, 0x3e, 0x00},
        {0x00, 0x00, 0x1c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x49, 0x7f, 0x00},
        {0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x77, 0x00},
        {0x00, 0x00, 0x08, 0x08, 0x14, 0x14, 0x14, 0x22, 0x22, 0x22, 0x77, 0x00},
        {0x00, 0x00, 0x14, 0x14, 0x2a, 0x2a, 0x2a, 0x22, 0x22, 0x22, 0x77, 0x00},
        {0x00, 0x00, 0x77, 0x22, 0x14, 0x14, 0x08, 0x14, 0x14, 0x22, 0x77, 0x00},
        {0x00, 0x00, 0x1c, 0x08, 0x08, 0x08, 0x14, 0x14, 0x22, 0x22, 0x77, 0x00},
        {0x00, 0x00, 0x7f, 0x21, 0x10, 0x10, 0x08, 0x04, 0x04, 0x42, 0x7f, 0x00},
        {0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1c, 0x00},
        {0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00},
        {0x1c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1c, 0x00},
        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x14, 0x08},
        {0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00},
        {0x00, 0x00, 0x3d, 0x42, 0x42, 0x3e, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x7e, 0x21, 0x21, 0x21, 0x21, 0x3e, 0x20, 0x20, 0x60, 0x00},
        {0x00, 0x00, 0x3e, 0x41, 0x40, 0x40, 0x41, 0x3e, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x3f, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x06, 0x00},
        {0x00, 0x00, 0x3e, 0x41, 0x40, 0x7f, 0x41, 0x3e, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x3c, 0x10, 0x10, 0x10, 0x10, 0x3c, 0x10, 0x10, 0x0c, 0x00},
        {0x3c, 0x02, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x3f, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x77, 0x22, 0x22, 0x22, 0x32, 0x2c, 0x20, 0x20, 0x60, 0x00},
        {0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x08, 0x00},
        {0x38, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x3c, 0x00, 0x00, 0x04, 0x00},
        {0x00, 0x00, 0x63, 0x24, 0x38, 0x28, 0x24, 0x26, 0x20, 0x20, 0x60, 0x00},
        {0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x18, 0x00},
        {0x00, 0x00, 0x6b, 0x2a, 0x2a, 0x2a, 0x2a, 0x74, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x77, 0x22, 0x22, 0x22, 0x32, 0x6c, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x3e, 0x41, 0x41, 0x41, 0x41, 0x3e, 0x00, 0x00, 0x00, 0x00},
        {0x70, 0x20, 0x3e, 0x21, 0x21, 0x21, 0x21, 0x7e, 0x00, 0x00, 0x00, 0x00},
        {0x07, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x3f, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x19, 0x76, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x3e, 0x41, 0x06, 0x38, 0x41, 0x3e, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x0c, 0x12, 0x10, 0x10, 0x10, 0x3c, 0x10, 0x10, 0x00, 0x00},
        {0x00, 0x00, 0x1b, 0x26, 0x22, 0x22, 0x22, 0x66, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x08, 0x14, 0x14, 0x22, 0x22, 0x77, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x14, 0x14, 0x2a, 0x2a, 0x22, 0x77, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x77, 0x22, 0x1c, 0x1c, 0x22, 0x77, 0x00, 0x00, 0x00, 0x00},
        {0x30, 0x08, 0x08, 0x14, 0x14, 0x22, 0x22, 0x77, 0x00, 0x00, 0x00, 0x00},
        {0x00, 0x00, 0x7e, 0x22, 0x10, 0x08, 0x44, 0x7e, 0x00, 0x00, 0x00, 0x00},
        {0x06, 0x08, 0x08, 0x08, 0x08, 0x30, 0x08, 0x08, 0x08, 0x08, 0x06, 0x00},
        {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08},
        {0x30, 0x08, 0x08, 0x08, 0x08, 0x06, 0x08, 0x08, 0x08, 0x08, 0x30, 0x00},
        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x49, 0x31, 0x00, 0x00},
        {0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x00}
    };
    
    unsigned int sourceWidth = 8;
    unsigned int sourceHeight = 12;
    
    _width = sourceWidth;
    _height = sourceHeight;

    // populate the glyph mp
    for(unsigned int i=32;i<127;i++)
    {
        osg::ref_ptr<Glyph> glyph = new Glyph;
        
        unsigned int dataSize = _width*_height;
        unsigned char* data = new unsigned char[dataSize];

        // clear the image to zeros.
        for(unsigned char* p=data;p<data+dataSize;) { *p++ = 0; }
        
        glyph->setImage(_width,_height,1,
                        GL_ALPHA,
                        GL_ALPHA,GL_UNSIGNED_BYTE,
                        data,
                        osg::Image::USE_NEW_DELETE,
                        1);

        glyph->setInternalTextureFormat(GL_ALPHA);

        // now populate data arry by converting bitmap into a luminance_alpha map.
        unsigned char* ptr = rasters[i-32];
        unsigned char value_on = 255;
        unsigned char value_off = 0;

        for(unsigned int row=0;row<sourceHeight;++row,++ptr)
        {
            (*data++)=((*ptr)&128)?value_on:value_off;
            (*data++)=((*ptr)&64)?value_on:value_off;
            (*data++)=((*ptr)&32)?value_on:value_off;
            (*data++)=((*ptr)&16)?value_on:value_off;            
            (*data++)=((*ptr)&8)?value_on:value_off;
            (*data++)=((*ptr)&4)?value_on:value_off;
            (*data++)=((*ptr)&2)?value_on:value_off;
            (*data++)=((*ptr)&1)?value_on:value_off;
        }
                        
        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(_width,_height,i,glyph.get());
    }
}

-------------- next part --------------
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 
 *
 * This library is open source and may be redistributed and/or modified under  
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 * OpenSceneGraph Public License for more details.
*/

#ifndef NEWTEXT_DEFAULTFONT_H
#define NEWTEXT_DEFAULTFONT_H 1

#include <map>

#include <osg/ref_ptr>

#include <osgText/Font>

namespace osgText {

class DefaultFont : public Font
{
public:

    static DefaultFont* instance();

    virtual std::string getFileName() const { return ""; }

    /** NOP with DefaultFont since it only supports a single fixed sized font. */
    virtual void setSize(unsigned int width, unsigned int height);

    virtual Font::Glyph* getGlyph(unsigned int charcode);
    
    virtual osg::Vec2 getKerning(unsigned int leftcharcode,unsigned int rightcharcode, KerningType kerningType);
    
    virtual bool hasVertical() const;

protected:

    DefaultFont();
    virtual ~DefaultFont();
    
    void constructGlyphs();
	static OpenThreads::Mutex _mutex;    
	
};

}

#endif


More information about the osg-users mailing list