[osg-users] ANN: osgPango (alpha)

Jeremy Moles jeremy at emperorlinux.com
Fri Sep 12 11:54:17 PDT 2008

On Fri, 2008-09-12 at 12:50 -0400, Jean-Sébastien Guay wrote:
> Hi Jeremy,
> > I'd like to quickly post a message here about (another! yikes!) NodeKit
> > I'm working on that ties closely with osgWidget and my original
> > intentions a year ago when I started working on osgWidget in my free
> > time. :)
> Very nice! Is there anything you can't do? :-)

Well, for the moment I'm just good at middleware. :) Still trying to
hone my math and Open GL skills...

> I'm curious about the performance - I'd be interested to know if you've 
> benchmarked the startup time and the runtime, when lots of text objects 
> are created and visible, in both osgText and osgPango.

Well, this is an interesting question, so I'll break it down here (which
will also help me outline the process used); maybe someone can point out
some places where high-level optimization can be had.

	1. A UTF-8 string is fed to the Pango library.

	2. My installed draw_glyphs callback is called by Pango; it is given an
array of GlyphInfo objects which tell me exactly what glyph should be
placed and where.

	3. My callback queries the osgPango::GlyphCache object assigned to the
font being used (there is a different font object per font and per size;
this is necessary for maximum quality). If the glyph has not been
previously rendered to the texture, it is done so now and the GlyphCache
object keeps track of it's size, origin, and texture coordinates.
osg::Image::dirty() is called, and the texture is updated internally
(more specifically, the texture cache is a vector of
osgCairo::SurfaceImage objects, which inherit from osg::Image and
provide the full Cairo vector-based API on top of the underlying data).

	3.a. If the font has requested an outline, it is rendered to a separate
texture, which will later be multitextured on to the same quad using the
same UV coordinates.

	4. A object representing the newly created (or perhaps previously
created) glyph is returned to the draw_glyphs callback. This information
is used to create one osg::Geometry-derived object per texture. For
example, if your font is small enough so that all glyphs fit on one
texture, only one osg::Geometry object will be created. If your font
cache spans multiple textures, one Geometry object per font will be
created and added to the encompassing Geode.

	5. The quads are textured, aligned, and pushed onto the Geode. All
layouts, ligatures, etc. are handled by Pango; we simply interpret the
information provided by it (thousands of lines of code determine how to
best "layout" a bit of text inside Pango; it's a MASSIVE problem to
tackle, and fortunately we don't have to bother. :))

I've added a neat function to the GlyphCache
object--writeImagesAsFiles--which dumps your internal texture cache to
disk for viewing. Furthermore, since the fonts are actually "rendered"
by Cairo, there is no limit to how they can be styled or sheared.

As an aside, the texture data is stored internally as 8-bit GL_ALPHA, so
this keeps the image data small. Also, the texture cache size is
configurable (default is 512x512), so further optimizations are possible
if you feel confident your application will only use a small set of
characters. Pre-caching font textures will also be available,

> There are lots of nice features in this, and it looks very nice! I'll 
> try to get it compiled at home when I have a chance. (to try it out 
> myself and to give you a bit of testing on Windows :-)

Thanks! As soon as I finish basic font shadow support, I'm going to
create quick osgPango::Label and osgPango::Input prototypes and get back
to hacking on osgWidget; there is still so much work to be done there.

> Thanks for all your hard work!
> J-S

More information about the osg-users mailing list