OpenSceneGraph/include/osgText/Font3D
Robert Osfield 9643c15346 From David Callu, "Problem:
osgText::Text and osgText::Text3D use the same font file.
     The first really load the file and obtain an osgText::Font object,
     the second use the cache created during the first load of the
     font file, and so obtain an osgText::Font object instead of
     osgText::Font3D object. To obtain an osgText::Font3D object,
     osgText::Text3D call osgDB::readObjectFile(...) with an option
     to specify the plugin we want an osgText::Font3D instead of
     osgText::Font.

Generalised Problem:
    In osgDB::Registry, loaded file cache is referenced by the name
    of this file, so if I load a file with some options, and the cache
    already contain object for this filename, I obtain an object
    potentially not loaded with my options.

Behaviours:
    Cache management is delegate to osgDB::Registry, but cache
    coherence (load a file with option then reuse it, deactivate the
    cache when load a specific file or don't cached the loaded file)
    is user's responsibility.

Text3D solution:
    Postfix the font file name by .text3d or something similar and then have the freetype plugin return
    osgText::Font3D when it detects this.
    This operation is done by osgText::readFont3DFile() which unsure the filename have .text3d as extension.
    This is totaly transparent for user, and backward compatible.


BTW, I fix the bug about the Normal of 3D text. Currently, the front and wall face have
the same normal (0,0,1) in the Text3D object coordinate. Now the wall face have its own
normal array computed by the plugin.

BTW 2, I implement
- void Text3D::accept(osg::Drawable::ConstAttributeFunctor& af) const
- void Text3D::accept(osg::PrimitiveFunctor& pf) const
so now statistics are well reported.
"
2009-03-10 10:56:00 +00:00

284 lines
10 KiB
C++

/* -*-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 OSGTEXT_FONT3D
#define OSGTEXT_FONT3D 1
#include <string>
#include <istream>
#include <osg/Vec2>
#include <osg/Geometry>
#include <osgDB/ReaderWriter>
#include <osgText/Export>
#include <osgText/KerningType>
#include <OpenThreads/Mutex>
namespace osgText {
class Font3D;
class Text3D;
/** Read a font from specified file. The filename may contain a path.
* It will search for the font file in the following places in this order:
* - In the current directory
* - All paths defined in OSG_FILE_PATH or OSGFILEPATH environment variable
* - Filename with path stripped: In the current directory
* - Filename with path stripped: All paths defined in OSG_FILE_PATH or OSGFILEPATH
*
* Then the file will be searched in OS specific directories in the following order:
* - Again in the current directory
* - Windows: In C:/winnt/fonts
* - Windows: In C:/windows/fonts
* - Windows: In the fonts directory of the windows install directory
* - Other OS: In /usr/share/fonts/ttf
* - Other OS: In /usr/share/fonts/ttf/western
* - Other OS: In /usr/share/fonts/ttf/decoratives
*
* If the given file could not be found, the path part will be stripped and
* the file will be searched again in the OS specific directories.
*/
extern OSGTEXT_EXPORT Font3D* readFont3DFile(const std::string& filename, const osgDB::ReaderWriter::Options* userOptions = 0);
/** read a font from specified stream.*/
extern OSGTEXT_EXPORT Font3D* readFont3DStream(std::istream& stream, const osgDB::ReaderWriter::Options* userOptions = 0);
extern OSGTEXT_EXPORT osg::ref_ptr<Font3D> readRefFont3DFile(const std::string& filename, const osgDB::ReaderWriter::Options* userOptions = 0);
extern OSGTEXT_EXPORT osg::ref_ptr<Font3D> readRefFont3DStream(std::istream& stream, const osgDB::ReaderWriter::Options* userOptions = 0);
extern OSGTEXT_EXPORT std::string findFont3DFile(const std::string& str);
/** Pure virtual base class for fonts.
* Concrete implementation are the DefaultFont found in src/osgText/DefaultFont.cpp
* and FreeTypeFont found in src/osgPlugins/freetype/FreeTypeFont.cpp*/
class OSGTEXT_EXPORT Font3D : public osg::Object
{
// declare the interface to a font.
public:
// forward declare nested classes.
class Glyph3D;
class Font3DImplementation;
public:
Font3D(Font3DImplementation* implementation=0);
virtual osg::Object* cloneType() const { return 0; } // cloneType() not appropriate
virtual osg::Object* clone(const osg::CopyOp&) const { return 0; } // clone() not appropriate
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const Font3D*>(obj)!=NULL; }
virtual const char* className() const { return "Font3D"; }
virtual const char* libraryName() const { return "osgText"; }
virtual std::string getFileName() const;
unsigned int getFontWidth() const { return _width; }
unsigned int getFontHeight() const { return _height; }
unsigned int getFontDepth() const { return _depth; }
/** Get a kerning (adjustment of spacing of two adjacent character) for specified charcodes, w.r.t the current font size hint.*/
virtual osg::Vec2 getKerning(unsigned int leftcharcode,unsigned int rightcharcode, KerningType kerningType);
/** Get a Glyph for specified charcode, and the font size nearest to the current font size hint.*/
virtual Glyph3D* getGlyph(unsigned int charcode);
/** Return true if this font provides vertical alignments and spacing or glyphs.*/
virtual bool hasVertical() const;
/** Return the scale to apply on the glyph to have a charactere size equal to 1 */
virtual float getScale() const { return _implementation->getScale(); };
// make Text a friend to allow it add and remove its entry in the Font's _textList.
friend class Font3DImplementation;
void setImplementation(Font3DImplementation* implementation);
Font3DImplementation* getImplementation();
const Font3DImplementation* getImplementation() const;
/** Set whether to use a mutex to ensure ref() and unref() */
virtual void setThreadSafeRefUnref(bool threadSafe);
typedef OpenThreads::Mutex Font3DMutex;
protected:
virtual ~Font3D();
// void addGlyph(unsigned int width, unsigned int height, unsigned int charcode, Glyph* glyph);
void addGlyph(unsigned int charcode, Glyph3D* glyph);
// current active size of font
unsigned int _depth;
unsigned int _width;
unsigned int _height;
// unsigned int _margin;
// float _marginRatio;
typedef std::map<char, osg::ref_ptr<Glyph3D> > Glyph3DMap;
Glyph3DMap _glyph3DMap;
osg::ref_ptr<Font3DImplementation> _implementation;
// declare the nested classes.
public:
class Font3DImplementation : public osg::Referenced
{
public:
Font3DImplementation():
osg::Referenced(true),
_facade(0) {}
virtual std::string getFileName() const = 0;
/** Get a Glyph for specified charcode, and the font size nearest to the current font size hint.*/
virtual Glyph3D* getGlyph(unsigned int charcode) = 0;
/** Get a kerning (adjustment of spacing of two adjacent character) for specified charcodes, w.r.t the current font size hint.*/
virtual osg::Vec2 getKerning(unsigned int leftcharcode,unsigned int rightcharcode, KerningType kerningType) = 0;
/** Return true if this font provides vertical alignments and spacing or glyphs.*/
virtual bool hasVertical() const = 0;
virtual float getScale() const = 0;
void setFontWidth(unsigned int width) { _facade->_width = width; }
void setFontHeight(unsigned int height) { _facade->_height = height; }
void setFontDepth(unsigned int depth) { _facade->_depth = depth; }
// void addGlyph(unsigned int width, unsigned int height, unsigned int charcode, Glyph3D* glyph)
// {
// _facade->addGlyph(width, height, charcode, glyph);
// }
//
// void addGlyph(unsigned int charcode, Glyph3D* glyph)
// {
// _facade->addGlyph(charcode, glyph);
// }
Font3D* _facade;
};
class OSGTEXT_EXPORT Glyph3D : public osg::Referenced
{
public:
Glyph3D(unsigned int glyphCode):
osg::Referenced(true),
_glyphCode(glyphCode),
_horizontalBearing(0,0),
_horizontalAdvance(0),
_verticalBearing(0,0),
_verticalAdvance(0)
{}
/** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs.*/
// virtual int compare(const osg::StateAttribute& rhs) const;
//
// virtual void apply(osg::State& state) const;
unsigned int getGlyphCode() const { return _glyphCode; }
void setHorizontalBearing(const osg::Vec2& bearing) { _horizontalBearing=bearing; }
const osg::Vec2 & getHorizontalBearing() const { return _horizontalBearing; }
void setHorizontalAdvance(float advance) { _horizontalAdvance=advance; }
float getHorizontalAdvance() const { return _horizontalAdvance; }
void setVerticalBearing(const osg::Vec2& bearing) { _verticalBearing=bearing; }
const osg::Vec2& getVerticalBearing() const { return _verticalBearing; }
void setVerticalAdvance(float advance) { _verticalAdvance=advance; }
float getVerticalAdvance() const { return _verticalAdvance; }
void setBoundingBox(osg::BoundingBox & bb) { _bb=bb; }
const osg::BoundingBox & getBoundingBox() const { return _bb; }
/** Set whether to use a mutex to ensure ref() and unref() are thread safe.*/
virtual void setThreadSafeRefUnref(bool threadSafe);
/** Get the PrimitiveSetList for the front face. */
osg::Geometry::PrimitiveSetList & getFrontPrimitiveSetList() { return _frontPrimitiveSetList; }
/** Get the PrimitiveSetList for the wall face. */
osg::Geometry::PrimitiveSetList & getWallPrimitiveSetList() { return _wallPrimitiveSetList; }
/** Get et the PrimitiveSetList for the back face. */
osg::Geometry::PrimitiveSetList & getBackPrimitiveSetList() { return _backPrimitiveSetList; }
/** Set the VertexArray of the glyph. */
void setVertexArray(osg::Vec3Array * va) { _vertexArray = va; }
/** Get the VertexArray of the glyph. */
osg::Vec3Array * getVertexArray() { return _vertexArray.get(); }
/** Set the VertexArray of the glyph. */
void setNormalArray(osg::Vec3Array * na) { _normalArray = na; }
/** Get the NormalArray for the wall face. */
osg::Vec3Array * getNormalArray() { return _normalArray.get(); }
float getHorizontalWidth() { return (-_horizontalBearing.x() + _horizontalAdvance); }
float getHorizontalHeight() { return (-_horizontalBearing.y() + _bb.yMax()); }
float getVerticalWidth() { return (-_verticalBearing.x() + _bb.xMax()); }
float getVerticalHeight() { return (-_verticalBearing.y() + _verticalAdvance); }
void setWidth(float width) { _width = width; }
float getWidth() { return _width; }
void setHeight(float height) { _height = height; }
float getHeight() { return _height; }
protected:
virtual ~Glyph3D() {}
unsigned int _glyphCode;
osg::Vec2 _horizontalBearing;
float _horizontalAdvance;
osg::Vec2 _verticalBearing;
float _verticalAdvance;
osg::BoundingBox _bb;
// osg::Vec2 _advance;
float _width;
float _height;
osg::ref_ptr<osg::Vec3Array> _vertexArray;
osg::ref_ptr<osg::Vec3Array> _normalArray;
osg::Geometry::PrimitiveSetList _frontPrimitiveSetList;
osg::Geometry::PrimitiveSetList _wallPrimitiveSetList;
osg::Geometry::PrimitiveSetList _backPrimitiveSetList;
};
};
}
#endif