Refactored osgText::Font so that it now supports both 2D and 3D glyphs.

Added TextNode.h and TextNode.cpp to examples/osgtext3D in prep for introducing the new node to osgText library
This commit is contained in:
Robert Osfield
2010-09-03 08:26:46 +00:00
parent d1e90b6878
commit 8c3e3055e7
26 changed files with 1396 additions and 398 deletions

View File

@@ -14,16 +14,178 @@
#include "FreeTypeFont.h"
#include "FreeTypeLibrary.h"
#include <freetype/ftoutln.h>
#include <freetype/ftbbox.h>
#include <osg/Notify>
#include <osgDB/WriteFile>
#include <osgUtil/SmoothingVisitor>
#include <osgUtil/Tessellator>
namespace FreeType
{
struct Char3DInfo
{
Char3DInfo(int numSteps):
_verts( new osg::Vec3Array ),
_geometry( new osg::Geometry ),
_idx(0),
_numSteps(numSteps),
_maxY(-FLT_MAX),
_maxX(-FLT_MAX),
_minX(FLT_MAX),
_minY(FLT_MAX)
{
}
~Char3DInfo()
{
}
osg::Geometry* get()
{
int len = _verts->size()-_idx;
if (len)
{
_geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::POLYGON, _idx, len ) );
_idx = _verts->size();
}
_geometry->setVertexArray(_verts.get());
return _geometry.get();
}
void addVertex(const osg::Vec3& pos)
{
if (!_verts->empty() && _verts->back()==pos)
{
// OSG_NOTICE<<"addVertex("<<pos<<") duplicate, ignoring"<<std::endl;
return;
}
_verts->push_back( pos );
setMinMax(pos);
}
void moveTo(const osg::Vec2& pos)
{
if (_verts->size())
{
int len = _verts->size()-_idx;
_geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::POLYGON, _idx, len ) );
}
_idx = _verts->size();
addVertex( osg::Vec3(pos.x(),pos.y(),0) );
}
void lineTo(const osg::Vec2& pos)
{
addVertex( osg::Vec3(pos.x(),pos.y(),0) );
}
void conicTo(const osg::Vec2& control, const osg::Vec2& pos)
{
osg::Vec3 p0 = _verts->back();
osg::Vec3 p1 = osg::Vec3(control.x(),control.y(),0);
osg::Vec3 p2 = osg::Vec3(pos.x(),pos.y(),0);
double dt = 1.0/_numSteps;
double u=0;
for (int i=0; i<=_numSteps; ++i)
{
double w = 1;
double bs = 1.0/( (1-u)*(1-u)+2*(1-u)*u*w +u*u );
osg::Vec3 p = (p0*((1-u)*(1-u)) + p1*(2*(1-u)*u*w) + p2*(u*u))*bs;
addVertex( p );
u += dt;
}
}
void cubicTo(const osg::Vec2& control1, const osg::Vec2& control2, const osg::Vec2& pos)
{
osg::Vec3 p0 = _verts->back();
osg::Vec3 p1 = osg::Vec3(control1.x(),control1.y(),0);
osg::Vec3 p2 = osg::Vec3(control2.x(),control2.y(),0);
osg::Vec3 p3 = osg::Vec3(pos.x(),pos.y(),0);
double cx = 3*(p1.x() - p0.x());
double bx = 3*(p2.x() - p1.x()) - cx;
double ax = p3.x() - p0.x() - cx - bx;
double cy = 3*(p1.y() - p0.y());
double by = 3*(p2.y() - p1.y()) - cy;
double ay = p3.y() - p0.y() - cy - by;
double dt = 1.0/_numSteps;
double u=0;
for (int i=0; i<=_numSteps; ++i)
{
osg::Vec3 p = osg::Vec3( ax*u*u*u + bx*u*u + cx*u + p0.x(),ay*u*u*u + by*u*u + cy*u + p0.y(),0 );
addVertex( p );
u += dt;
}
}
void setMinMax(const osg::Vec3& pos)
{
_maxY = std::max(_maxY, (double) pos.y());
_minY = std::min(_minY, (double) pos.y());
_maxX = std::max(_maxX, (double) pos.x());
_minX = std::min(_minX, (double) pos.x());
}
osg::ref_ptr<osg::Vec3Array> _verts;
osg::ref_ptr<osg::Geometry> _geometry;
int _idx;
int _numSteps;
double _maxY;
double _maxX;
double _minX;
double _minY;
};
#define FT_NUM(x) (x/64.0)
int moveTo( const FT_Vector* to, void* user )
{
Char3DInfo* char3d = (Char3DInfo*)user;
char3d->moveTo( osg::Vec2(FT_NUM(to->x),FT_NUM(to->y)) );
return 0;
}
int lineTo( const FT_Vector* to, void* user )
{
Char3DInfo* char3d = (Char3DInfo*)user;
char3d->lineTo( osg::Vec2(FT_NUM(to->x),FT_NUM(to->y)) );
return 0;
}
int conicTo( const FT_Vector* control,const FT_Vector* to, void* user )
{
Char3DInfo* char3d = (Char3DInfo*)user;
char3d->conicTo( osg::Vec2(FT_NUM(control->x),FT_NUM(control->y)), osg::Vec2(FT_NUM(to->x),FT_NUM(to->y)) );
return 0;
}
int cubicTo( const FT_Vector* control1,const FT_Vector* control2,const FT_Vector* to, void* user )
{
Char3DInfo* char3d = (Char3DInfo*)user;
char3d->cubicTo(
osg::Vec2(FT_NUM(control1->x),FT_NUM(control1->y)),
osg::Vec2(FT_NUM(control2->x),FT_NUM(control2->y)),
osg::Vec2(FT_NUM(to->x),FT_NUM(to->y)) );
return 0;
}
#undef FT_NUM
}
FreeTypeFont::FreeTypeFont(const std::string& filename, FT_Face face, unsigned int flags):
_currentRes(osgText::FontResolution(0,0)),
_filename(filename),
_buffer(0),
_face(face),
_flags(flags)
_flags(flags),
_scale(1.0f)
{
init();
}
FreeTypeFont::FreeTypeFont(FT_Byte* buffer, FT_Face face, unsigned int flags):
@@ -31,8 +193,10 @@ FreeTypeFont::FreeTypeFont(FT_Byte* buffer, FT_Face face, unsigned int flags):
_filename(""),
_buffer(buffer),
_face(face),
_flags(flags)
_flags(flags),
_scale(1.0f)
{
init();
}
FreeTypeFont::~FreeTypeFont()
@@ -60,6 +224,65 @@ FreeTypeFont::~FreeTypeFont()
}
}
void FreeTypeFont::init()
{
FT_Error _error = FT_Set_Pixel_Sizes(_face, 32, 32);
if (_error)
{
OSG_NOTICE << "FreeTypeFont3D: set pixel sizes failed ..." << std::endl;
return;
}
FT_Set_Char_Size( _face, 64*64, 64*64, 600, 600);
int glyphIndex = FT_Get_Char_Index( _face, 'M' );
_error = FT_Load_Glyph( _face, glyphIndex, FT_LOAD_DEFAULT );
if (_error)
{
OSG_NOTICE << "FreeTypeFont3D: initial glyph load failed ..." << std::endl;
return;
}
if (_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
{
OSG_NOTICE << "FreeTypeFont3D: not a vector font" << std::endl;
return;
}
{
FreeType::Char3DInfo char3d(10);
FT_Outline outline = _face->glyph->outline;
FT_Outline_Funcs funcs;
funcs.conic_to = (FT_Outline_ConicToFunc)&FreeType::conicTo;
funcs.line_to = (FT_Outline_LineToFunc)&FreeType::lineTo;
funcs.cubic_to = (FT_Outline_CubicToFunc)&FreeType::cubicTo;
funcs.move_to = (FT_Outline_MoveToFunc)&FreeType::moveTo;
funcs.shift = 0;
funcs.delta = 0;
_error = FT_Outline_Decompose(&outline,&funcs,&char3d);
if (_error)
{
OSG_NOTICE << "FreeTypeFont3D: - outline decompose failed ..." << std::endl;
return;
}
FT_BBox bb;
FT_Outline_Get_BBox(&outline,&bb);
long ymin = ft_floor( bb.yMin );
long ymax = ft_ceiling( bb.yMax );
double height = double(ymax - ymin)/64.0;
// long xmin = ft_floor( bb.xMin );
// long xmax = ft_ceiling( bb.xMax );
// double width = (xmax - xmin)/64.0;
_scale = 1.0/height;
}
}
void FreeTypeFont::setFontResolution(const osgText::FontResolution& fontSize)
{
if (fontSize==_currentRes) return;
@@ -95,7 +318,7 @@ void FreeTypeFont::setFontResolution(const osgText::FontResolution& fontSize)
}
osgText::Font::Glyph* FreeTypeFont::getGlyph(const osgText::FontResolution& fontRes, unsigned int charcode)
osgText::Glyph* FreeTypeFont::getGlyph(const osgText::FontResolution& fontRes, unsigned int charcode)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(FreeTypeLibrary::instance()->getMutex());
@@ -135,7 +358,7 @@ osgText::Font::Glyph* FreeTypeFont::getGlyph(const osgText::FontResolution& font
unsigned int width = sourceWidth;
unsigned int height = sourceHeight;
osg::ref_ptr<osgText::Font::Glyph> glyph = new osgText::Font::Glyph(charcode);
osg::ref_ptr<osgText::Glyph> glyph = new osgText::Glyph(charcode);
unsigned int dataSize = width*height;
unsigned char* data = new unsigned char[dataSize];
@@ -191,14 +414,212 @@ osgText::Font::Glyph* FreeTypeFont::getGlyph(const osgText::FontResolution& font
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(fontRes,charcode,glyph.get());
// cout << " in getGlyph() implementation="<<this<<" "<<_filename<<" facade="<<_facade<<endl;
return glyph.get();
return glyph.release();
}
osgText::Glyph3D * FreeTypeFont::getGlyph3D(unsigned int charcode)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(FreeTypeLibrary::instance()->getMutex());
//
// GT: fix for symbol fonts (i.e. the Webdings font) as the wrong character are being
// returned, for symbol fonts in windows (FT_ENCONDING_MS_SYMBOL in freetype) the correct
// values are from 0xF000 to 0xF0FF not from 0x000 to 0x00FF (0 to 255) as you would expect.
// Microsoft uses a private field for its symbol fonts
//
unsigned int charindex = charcode;
if (_face->charmap != NULL)
{
if (_face->charmap->encoding == FT_ENCODING_MS_SYMBOL)
{
charindex |= 0xF000;
}
}
FT_Error error = FT_Load_Char( _face, charindex, FT_LOAD_DEFAULT|_flags );
if (error)
{
OSG_WARN << "FT_Load_Char(...) error 0x"<<std::hex<<error<<std::dec<<std::endl;
return 0;
}
if (_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
{
OSG_WARN << "FreeTypeFont3D::getGlyph : not a vector font" << std::endl;
return 0;
}
// ** init FreeType to describe the glyph
FreeType::Char3DInfo char3d(_facade->getNumberCurveSamples());
FT_Outline outline = _face->glyph->outline;
FT_Outline_Funcs funcs;
funcs.conic_to = (FT_Outline_ConicToFunc)&FreeType::conicTo;
funcs.line_to = (FT_Outline_LineToFunc)&FreeType::lineTo;
funcs.cubic_to = (FT_Outline_CubicToFunc)&FreeType::cubicTo;
funcs.move_to = (FT_Outline_MoveToFunc)&FreeType::moveTo;
funcs.shift = 0;
funcs.delta = 0;
// ** record description
FT_Error _error = FT_Outline_Decompose(&outline, &funcs, &char3d);
if (_error)
{
OSG_WARN << "FreeTypeFont3D::getGlyph : - outline decompose failed ..." << std::endl;
return 0;
}
// ** create geometry for each part of the glyph
osg::ref_ptr<osg::Geometry> frontGeo(new osg::Geometry);
osg::ref_ptr<osg::Vec3Array> rawVertices = new osg::Vec3Array(*(char3d._verts));
osg::Geometry::PrimitiveSetList rawPrimitives;
for(osg::Geometry::PrimitiveSetList::iterator itr = char3d.get()->getPrimitiveSetList().begin();
itr != char3d.get()->getPrimitiveSetList().end();
++itr)
{
rawPrimitives.push_back(dynamic_cast<osg::PrimitiveSet*>((*itr)->clone(osg::CopyOp::DEEP_COPY_ALL)));
}
frontGeo->setVertexArray(char3d.get()->getVertexArray());
frontGeo->setPrimitiveSetList(char3d.get()->getPrimitiveSetList());
osg::ref_ptr<osg::Geometry> wallGeo(new osg::Geometry);
wallGeo->setVertexArray(frontGeo->getVertexArray());
osg::ref_ptr<osg::Geometry> backGeo(new osg::Geometry);
backGeo->setVertexArray(frontGeo->getVertexArray());
// ** for convenience.
osg::Vec3Array * vertices = char3d._verts.get();
// ** duplicate the vertex for the back face
// ** with a depth equal to the font depth
std::size_t len = vertices->size();
std::size_t dlen = len * 2;
vertices->reserve(dlen);
osg::Vec3Array::iterator begin = vertices->begin();
osg::Vec3Array::iterator it = vertices->begin();
for (std::size_t i = 0; i != len; ++i, ++it)
vertices->push_back(*it);
// std::copy(begin, begin + len, begin + len + 1); TOCHECK
// ** and decal new vertices
unsigned int depth = _facade->getFontDepth();
for (std::size_t i = len; i != dlen; ++i)
{
(*vertices)[i].z() -= depth;
}
osg::Vec3Array::iterator end;
// ** create wall and back face from the front polygon
// ** then accumulate them in the appropriate geometry wallGeo and backGeo
for (std::size_t i=0; i < frontGeo->getNumPrimitiveSets(); ++i)
{
// ** get the front polygon
osg::ref_ptr<osg::DrawArrays> daFront(dynamic_cast<osg::DrawArrays*>(frontGeo->getPrimitiveSet(i)));
unsigned int idx = daFront->getFirst();
unsigned int cnt = daFront->getCount();
// ** reverse vertices to draw the front face in the CCW
std::reverse(begin + idx, begin + idx + cnt);
// ** create the back polygon
osg::ref_ptr<osg::DrawArrays> daBack(new osg::DrawArrays(osg::PrimitiveSet::POLYGON, idx + len, cnt));
backGeo->addPrimitiveSet(daBack.get());
// ** create the wall triangle strip
osg::ref_ptr<osg::DrawElementsUInt> deWall(new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLE_STRIP));
wallGeo->addPrimitiveSet(deWall.get());
// ** link triangle strip
deWall->push_back(idx + len);
for (unsigned int j = 1; j < cnt; ++j)
{
deWall->push_back(idx + cnt - j);
deWall->push_back(idx + len + j);
}
deWall->push_back(idx);
deWall->push_back(idx + len);
deWall->push_back(idx + cnt - 1);
}
// ** tesselate front and back face
{
osgUtil::Tessellator ts;
ts.setWindingType(osgUtil::Tessellator::TESS_WINDING_POSITIVE);
ts.setTessellationType(osgUtil::Tessellator::TESS_TYPE_GEOMETRY);
ts.retessellatePolygons(*frontGeo);
}
{
osgUtil::Tessellator ts;
ts.setWindingType(osgUtil::Tessellator::TESS_WINDING_POSITIVE);
ts.setTessellationType(osgUtil::Tessellator::TESS_TYPE_GEOMETRY);
ts.retessellatePolygons(*backGeo);
}
// ** generate normal
{
osgUtil::SmoothingVisitor sm;
osg::ref_ptr<osg::Geode> geode(new osg::Geode);
geode->addDrawable(wallGeo.get());
geode->accept(sm);
}
// ** save vertices and PrimitiveSetList of each face in the Glyph3D PrimitiveSet face list
osg::ref_ptr<osgText::Glyph3D> glyph3D = new osgText::Glyph3D(charcode);
// copy the raw primitive set list before we tessellate it.
glyph3D->getRawFacePrimitiveSetList() = rawPrimitives;
glyph3D->setRawVertexArray(rawVertices.get());
glyph3D->setVertexArray(dynamic_cast<osg::Vec3Array*>(frontGeo->getVertexArray()));
glyph3D->setNormalArray(dynamic_cast<osg::Vec3Array*>(wallGeo->getNormalArray()));
glyph3D->getFrontPrimitiveSetList() = frontGeo->getPrimitiveSetList();
glyph3D->getWallPrimitiveSetList() = wallGeo->getPrimitiveSetList();
glyph3D->getBackPrimitiveSetList() = backGeo->getPrimitiveSetList();
FT_Glyph_Metrics* metrics = &(_face->glyph->metrics);
glyph3D->setHorizontalBearing(osg::Vec2((float)metrics->horiBearingX/64.0f,(float)(metrics->horiBearingY-metrics->height)/64.0f)); // bottom left.
glyph3D->setHorizontalAdvance((float)metrics->horiAdvance/64.0f);
glyph3D->setVerticalBearing(osg::Vec2((float)metrics->vertBearingX/64.0f,(float)(metrics->vertBearingY-metrics->height)/64.0f)); // top middle.
glyph3D->setVerticalAdvance((float)metrics->vertAdvance/64.0f);
glyph3D->setWidth((float)metrics->width / 64.0f);
glyph3D->setHeight((float)metrics->height / 64.0f);
FT_BBox ftbb;
FT_Outline_Get_BBox(&outline, &ftbb);
long xmin = ft_floor( ftbb.xMin );
long xmax = ft_ceiling( ftbb.xMax );
long ymin = ft_floor( ftbb.yMin );
long ymax = ft_ceiling( ftbb.yMax );
osg::BoundingBox bb(xmin / 64.0f, ymin / 64.0f, 0.0f, xmax / 64.0f, ymax / 64.0f, 0.0f);
glyph3D->setBoundingBox(bb);
return glyph3D.release();
}
osg::Vec2 FreeTypeFont::getKerning(const osgText::FontResolution& fontRes, unsigned int leftcharcode,unsigned int rightcharcode, osgText::KerningType kerningType)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(FreeTypeLibrary::instance()->getMutex());

View File

@@ -31,22 +31,33 @@ public:
virtual std::string getFileName() const { return _filename; }
virtual osgText::Font::Glyph* getGlyph(const osgText::FontResolution& fontRes,unsigned int charcode);
virtual osgText::Glyph* getGlyph(const osgText::FontResolution& fontRes,unsigned int charcode);
virtual osgText::Glyph3D* getGlyph3D(unsigned int charcode);
virtual osg::Vec2 getKerning(const osgText::FontResolution& fontRes, unsigned int leftcharcode,unsigned int rightcharcode, osgText::KerningType _kerningType);
virtual bool hasVertical() const;
virtual float getScale() const { return _scale; }
protected:
void init();
void setFontResolution(const osgText::FontResolution& fontSize);
osgText::FontResolution _currentRes;
long ft_round( long x ) { return (( x + 32 ) & -64); }
long ft_floor( long x ) { return (x & -64); }
long ft_ceiling( long x ){ return (( x + 63 ) & -64); }
std::string _filename;
FT_Byte* _buffer;
FT_Face _face;
unsigned int _flags;
float _scale;
};
#endif

View File

@@ -14,6 +14,9 @@
#include "FreeTypeFont3D.h"
#include "FreeTypeLibrary.h"
#include <freetype/ftoutln.h>
#include <freetype/ftbbox.h>
#include <limits.h>
#include <fstream>
@@ -26,12 +29,6 @@
#include <osgUtil/Tessellator>
#include <ft2build.h>
#include FT_FREETYPE_H
#include <freetype/ftoutln.h>
#include <freetype/ftbbox.h>
#include <osg/io_utils>
namespace
@@ -195,10 +192,7 @@ FreeTypeFont3D::FreeTypeFont3D(const std::string& filename, FT_Face face, unsign
_buffer(0),
_face(face),
_flags(flags),
_scale(1.0),
_shiftY(0.0),
_shiftX(0.0),
_charScale(1.0)
_scale(1.0)
{
init();
}
@@ -208,10 +202,7 @@ FreeTypeFont3D::FreeTypeFont3D(FT_Byte* buffer, FT_Face face, unsigned int flags
_buffer(buffer),
_face(face),
_flags(flags),
_scale(1.0),
_shiftY(0.0),
_shiftX(0.0),
_charScale(1.0)
_scale(1.0)
{
init();
}
@@ -263,26 +254,15 @@ void FreeTypeFont3D::init()
FT_BBox bb;
FT_Outline_Get_BBox(&outline,&bb);
long xmin = ft_floor( bb.xMin );
long xmax = ft_ceiling( bb.xMax );
long ymin = ft_floor( bb.yMin );
long ymax = ft_ceiling( bb.yMax );
double height = double(ymax - ymin)/64.0;
double width = (xmax - xmin)/64.0;
double height = (ymax - ymin)/64.0;
// long xmin = ft_floor( bb.xMin );
// long xmax = ft_ceiling( bb.xMax );
// double width = (xmax - xmin)/64.0;
_scale = 1.0/height;
double charHeight = char3d._maxY-char3d._minY;
double charWidth = char3d._maxX-char3d._minX;
double dh = fabs(bb.yMin/64.0)/height;
double dw = fabs(bb.xMin/64.0)/width;
_shiftY = char3d._minY + dh*charHeight;
_shiftX = char3d._minX + dw*charWidth;
_charScale = 1/charHeight;
}
}
@@ -312,7 +292,7 @@ FreeTypeFont3D::~FreeTypeFont3D()
}
osgText::Font3D::Glyph3D * FreeTypeFont3D::getGlyph(unsigned int charcode)
osgText::Glyph3D * FreeTypeFont3D::getGlyph(unsigned int charcode)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(FreeTypeLibrary::instance()->getMutex());
@@ -472,7 +452,7 @@ osgText::Font3D::Glyph3D * FreeTypeFont3D::getGlyph(unsigned int charcode)
}
// ** save vertices and PrimitiveSetList of each face in the Glyph3D PrimitiveSet face list
osgText::Font3D::Glyph3D * glyph3D = new osgText::Font3D::Glyph3D(charcode);
osgText::Glyph3D * glyph3D = new osgText::Glyph3D(charcode);
// copy the raw primitive set list before we tessellate it.
glyph3D->getRawFacePrimitiveSetList() = rawPrimitives;

View File

@@ -29,7 +29,7 @@ public:
virtual std::string getFileName() const { return _filename; }
virtual osgText::Font3D::Glyph3D * getGlyph(unsigned int charcode);
virtual osgText::Glyph3D * getGlyph(unsigned int charcode);
virtual osg::Vec2 getKerning(unsigned int leftcharcode,unsigned int rightcharcode, osgText::KerningType _kerningType);
@@ -52,11 +52,7 @@ protected:
FT_Face _face;
unsigned int _flags;
double _scale;
double _shiftY;
double _shiftX;
double _charScale;
};
#endif

View File

@@ -81,8 +81,7 @@ TXFFont::getFileName() const
return _filename;
}
osgText::Font::Glyph*
TXFFont::getGlyph(const osgText::FontResolution&, unsigned int charcode)
osgText::Glyph* TXFFont::getGlyph(const osgText::FontResolution&, unsigned int charcode)
{
GlyphMap::iterator i = _chars.find(charcode);
if (i != _chars.end())
@@ -96,7 +95,6 @@ TXFFont::getGlyph(const osgText::FontResolution&, unsigned int charcode)
if (i != _chars.end())
{
_chars[charcode] = i->second;
addGlyph(osgText::FontResolution(i->second->s(), i->second->t()), charcode, i->second.get());
return i->second.get();
}
}
@@ -106,7 +104,6 @@ TXFFont::getGlyph(const osgText::FontResolution&, unsigned int charcode)
if (i != _chars.end())
{
_chars[charcode] = i->second;
addGlyph(osgText::FontResolution(i->second->s(), i->second->t()), charcode, i->second.get());
return i->second.get();
}
}
@@ -230,7 +227,7 @@ TXFFont::loadFont(std::istream& stream)
continue;
// add the characters ...
osgText::Font::Glyph* glyph = new osgText::Font::Glyph(glyphs[i].ch);
osgText::Glyph* glyph = new osgText::Glyph(glyphs[i].ch);
unsigned sourceWidth = glyphs[i].width;
unsigned sourceHeight = glyphs[i].height;
@@ -267,11 +264,12 @@ TXFFont::loadFont(std::istream& stream)
- glyphs[i].height*texToVertY));
_chars[glyphs[i].ch] = glyph;
addGlyph(fontResolution, glyphs[i].ch, glyph);
}
// insert a trivial blank character
osgText::Font::Glyph* glyph = new osgText::Font::Glyph(' ');
osgText::Glyph* glyph = new osgText::Glyph(' ');
unsigned width = 1;
unsigned height = 1;

View File

@@ -28,16 +28,20 @@ public:
virtual std::string getFileName() const;
virtual osgText::Font::Glyph* getGlyph(const osgText::FontResolution& fontRes, unsigned int charcode);
virtual osgText::Glyph* getGlyph(const osgText::FontResolution& fontRes, unsigned int charcode);
virtual osgText::Glyph3D* getGlyph3D(unsigned int) { return 0; }
virtual bool hasVertical() const;
virtual osg::Vec2 getKerning(const osgText::FontResolution& fontRes, unsigned int leftcharcode,unsigned int rightcharcode, osgText::KerningType kerningType);
virtual float getScale() const { return 1.0; }
bool loadFont(std::istream& stream);
protected:
typedef std::map<unsigned int, osg::ref_ptr<osgText::Font::Glyph> > GlyphMap;
typedef std::map<unsigned int, osg::ref_ptr<osgText::Glyph> > GlyphMap;
std::string _filename;
GlyphMap _chars;