diff --git a/examples/osgtext3D/CMakeLists.txt b/examples/osgtext3D/CMakeLists.txt index 27c014f22..755e35466 100644 --- a/examples/osgtext3D/CMakeLists.txt +++ b/examples/osgtext3D/CMakeLists.txt @@ -1,13 +1,9 @@ #this file is automatically generated SET(TARGET_H - GlyphGeometry.h - TextNode.h ) SET(TARGET_SRC - GlyphGeometry.cpp - TextNode.cpp osgtext3D_orig.cpp osgtext3D_test.cpp osgtext3D.cpp diff --git a/examples/osgtext3D/GlyphGeometry.cpp b/examples/osgtext3D/GlyphGeometry.cpp index 0e3e84760..5878b97cc 100644 --- a/examples/osgtext3D/GlyphGeometry.cpp +++ b/examples/osgtext3D/GlyphGeometry.cpp @@ -35,32 +35,48 @@ public: typedef std::pair Segment; typedef std::vector Segments; osg::ref_ptr _vertices; - unsigned int _start; - unsigned int _count; + osg::ref_ptr _elements; Segments _segments; - Boundary(osg::Vec3Array* vertices, unsigned int start, unsigned int count) + Boundary(osg::Vec3Array* vertices, osg::PrimitiveSet* primitiveSet) { - _vertices = vertices; - _start = start; - _count = count; - - if ((*_vertices)[start]==(*_vertices)[start+count-1]) + osg::DrawArrays* drawArrays = dynamic_cast(primitiveSet); + if (drawArrays) { - // OSG_NOTICE<<"Boundary is a line loop"<getFirst(), drawArrays->getCount()); } else { - OSG_NOTICE<<"Boundary is not a line loop"<(primitiveSet); + if (elements) set(vertices, elements); } + } - _segments.reserve(count-1); - for(unsigned int i=start; ipush_back(i); } - _segments.push_back(Segment(start+count-2,start)); + set(vertices, elements); + } + + void set(osg::Vec3Array* vertices, osg::DrawElementsUShort* elements) + { + _vertices = vertices; + _elements = elements; + + _segments.clear(); + + if (elements->empty()) return; + + _segments.reserve(elements->size()-1); + for(unsigned int i=0; isize()-1; ++i) + { + _segments.push_back(Segment((*elements)[i],(*elements)[i+1])); + } } osg::Vec3 computeRayIntersectionPoint(const osg::Vec3& a, const osg::Vec3& an, const osg::Vec3& c, const osg::Vec3& cn) @@ -251,7 +267,7 @@ public: face->setName("face"); // reserve enough space in the vertex array to accomodate the vertices associated with the segments - new_vertices->reserve(new_vertices->size() + _segments.size()+1 + _count); + new_vertices->reserve(new_vertices->size() + _segments.size()+1 + _elements->size()); // create vertices unsigned int previous_second = _segments[0].second; @@ -259,10 +275,13 @@ public: unsigned int first = new_vertices->size(); new_vertices->push_back(newPoint); - if (_segments[0].first != _start) + unsigned int start = (*_elements)[0]; + unsigned int count = _elements->size(); + + if (_segments[0].first != start) { //OSG_NOTICE<<"We have pruned from the start"<push_back(first); } @@ -298,7 +317,7 @@ public: // fill the end of the polygon with repititions of the first index in the polygon to ensure // that the orignal and new boundary polygons have the same number and pairing of indices. // This ensures that the bevel can be created coherently. - while(face->size() < _count) + while(face->size() < count) { face->push_back(first); } @@ -313,11 +332,11 @@ public: osg::DrawElementsUShort* bevel = new osg::DrawElementsUShort(GL_QUAD_STRIP); bevel->setName("bevel"); - bevel->reserve(_count*2); - for(unsigned int i=0; i<_count; ++i) + bevel->reserve(count*2); + for(unsigned int i=0; isize(); - new_vertices->push_back((*_vertices)[_start+i]); + new_vertices->push_back((*_vertices)[(*_elements)[i]]); bevel->push_back(vi); bevel->push_back((*face)[i]); } @@ -328,6 +347,9 @@ public: { if (_segments.empty()) return; + unsigned int start = (*_elements)[0]; + unsigned int count = _elements->size(); + if (geometry->getVertexArray()==0) geometry->setVertexArray(new osg::Vec3Array(*_vertices)); osg::Vec3Array* new_vertices = dynamic_cast(geometry->getVertexArray()); @@ -336,7 +358,7 @@ public: face->setName(faceName); // reserve enough space in the vertex array to accomodate the vertices associated with the segments - new_vertices->reserve(new_vertices->size() + _segments.size()+1 + _count); + new_vertices->reserve(new_vertices->size() + _segments.size()+1 + count); // create vertices unsigned int previous_second = _segments[0].second; @@ -344,10 +366,10 @@ public: unsigned int first = new_vertices->size(); new_vertices->push_back(newPoint); - if (_segments[0].first != _start) + if (_segments[0].first != start) { //OSG_NOTICE<<"We have pruned from the start"<push_back(first); } @@ -383,7 +405,7 @@ public: // fill the end of the polygon with repititions of the first index in the polygon to ensure // that the orignal and new boundary polygons have the same number and pairing of indices. // This ensures that the bevel can be created coherently. - while(face->size() < _count) + while(face->size() < count) { face->push_back(first); } @@ -396,10 +418,10 @@ public: osg::DrawElementsUShort* bevel = new osg::DrawElementsUShort(GL_QUAD_STRIP); bevel->setName(bevelName); - bevel->reserve(_count*2); - for(unsigned int i=0; i<_count; ++i) + bevel->reserve(count*2); + for(unsigned int i=0; ipush_back(_start+i); + bevel->push_back((*_elements)[i]); bevel->push_back((*face)[i]); } geometry->addPrimitiveSet(bevel); @@ -444,24 +466,24 @@ osg::Geometry* computeGlyphGeometry(osgText::Glyph3D* glyph, float bevelThicknes itr != orig_primitives.end(); ++itr) { - osg::DrawArrays* drawArray = dynamic_cast(itr->get()); - if (drawArray && drawArray->getMode()==GL_POLYGON) + if ((*itr)->getMode()==GL_POLYGON) { - Boundary boundaryInner(orig_vertices, drawArray->getFirst(), drawArray->getCount()); + Boundary boundaryInner(orig_vertices, itr->get()); boundaryInner.removeAllSegmentsBelowThickness(bevelThickness); boundaryInner.newAddBoundaryToGeometry(new_geometry, bevelThickness, "face", "bevel"); - Boundary boundaryOuter(orig_vertices, drawArray->getFirst(), drawArray->getCount()); + Boundary boundaryOuter(orig_vertices, itr->get()); boundaryOuter.removeAllSegmentsAboveThickness(-shellThickness); boundaryOuter.newAddBoundaryToGeometry(new_geometry, -shellThickness, "", "shell"); } + } osg::Vec3Array* vertices = dynamic_cast(new_geometry->getVertexArray()); // need to tessellate the inner boundary { - osg::Geometry* face_geometry = new osg::Geometry; + osg::ref_ptr face_geometry = new osg::Geometry; face_geometry->setVertexArray(vertices); osg::CopyOp copyop(osg::CopyOp::DEEP_COPY_ALL); @@ -510,6 +532,123 @@ osg::Geometry* computeGlyphGeometry(osgText::Glyph3D* glyph, float bevelThicknes return new_geometry.release(); } +///////////////////////////////////////////////////////////////////////////////////////// +// +// computeTextGeometry +// +osg::Geometry* computeTextGeometry(osgText::Glyph3D* glyph, float width) +{ + osg::Vec3Array* orig_vertices = glyph->getRawVertexArray(); + osg::Geometry::PrimitiveSetList& orig_primitives = glyph->getRawFacePrimitiveSetList(); + + osg::ref_ptr text_geometry = new osg::Geometry; + osg::ref_ptr vertices = new osg::Vec3Array((*orig_vertices)); + + text_geometry->setVertexArray(vertices.get()); + text_geometry->setPrimitiveSetList(orig_primitives); + + osgUtil::Tessellator ts; + ts.setWindingType(osgUtil::Tessellator::TESS_WINDING_POSITIVE); + ts.setTessellationType(osgUtil::Tessellator::TESS_TYPE_GEOMETRY); + ts.retessellatePolygons(*text_geometry); + + osg::TriangleIndexFunctor ctif; + text_geometry->accept(ctif); + CollectTriangleIndicesFunctor::Indices& indices = ctif._indices; + + // remove the previous primitive sets + text_geometry->getPrimitiveSetList().clear(); + + if (indices.empty()) return 0; + + + // create a front face using triangle indices + osg::DrawElementsUShort* frontFace = new osg::DrawElementsUShort(GL_TRIANGLES); + frontFace->setName("face"); + text_geometry->addPrimitiveSet(frontFace); + for(unsigned int i=0; ipush_back(indices[i]); + } + + typedef std::vector Indices; + const unsigned int NULL_VALUE = UINT_MAX; + Indices back_indices; + back_indices.resize(vertices->size(), NULL_VALUE); + osg::Vec3 forward(0,0,-width); + + // build up the vertices primitives for the back face, and record the indices + // for later use, and to ensure sharing of vertices in the face primitive set + // the order of the triangle indices are flipped to make sure that the triangles are back face + osg::DrawElementsUShort* backFace = new osg::DrawElementsUShort(GL_TRIANGLES); + text_geometry->addPrimitiveSet(backFace); + for(unsigned int i=0; isize(); + vertices->push_back((*vertices)[p1]+forward); + } + + if (back_indices[p2]==NULL_VALUE) + { + back_indices[p2] = vertices->size(); + vertices->push_back((*vertices)[p2]+forward); + } + + if (back_indices[p3]==NULL_VALUE) + { + back_indices[p3] = vertices->size(); + vertices->push_back((*vertices)[p3]+forward); + } + + backFace->push_back(back_indices[p1]); + backFace->push_back(back_indices[p3]); + backFace->push_back(back_indices[p2]); + } + + unsigned int orig_size = orig_vertices->size(); + Indices frontedge_indices, backedge_indices; + frontedge_indices.resize(orig_size, NULL_VALUE); + backedge_indices.resize(orig_size, NULL_VALUE); + + + for(osg::Geometry::PrimitiveSetList::iterator itr = orig_primitives.begin(); + itr != orig_primitives.end(); + ++itr) + { + osg::DrawElementsUShort* edging = new osg::DrawElementsUShort(osg::PrimitiveSet::QUAD_STRIP); + text_geometry->addPrimitiveSet(edging); + + osg::DrawElementsUShort* elements = dynamic_cast(itr->get()); + if (elements) + { + for(unsigned int i=0; isize(); ++i) + { + unsigned int ei = (*elements)[i]; + if (frontedge_indices[ei]==NULL_VALUE) + { + frontedge_indices[ei] = vertices->size(); + vertices->push_back((*orig_vertices)[ei]); + } + if (backedge_indices[ei]==NULL_VALUE) + { + backedge_indices[ei] = vertices->size(); + vertices->push_back((*orig_vertices)[ei]+forward); + } + + edging->push_back(backedge_indices[ei]); + edging->push_back(frontedge_indices[ei]); + } + } + } + + return text_geometry.release(); +} + ///////////////////////////////////////////////////////////////////////////////////////// // // computeTextGeometry diff --git a/examples/osgtext3D/GlyphGeometry.h b/examples/osgtext3D/GlyphGeometry.h index 70545d89a..318a4da02 100644 --- a/examples/osgtext3D/GlyphGeometry.h +++ b/examples/osgtext3D/GlyphGeometry.h @@ -22,6 +22,8 @@ namespace osgText extern osg::Geometry* computeGlyphGeometry(osgText::Glyph3D* glyph, float bevelThickness, float shellThickness); +extern osg::Geometry* computeTextGeometry(osgText::Glyph3D* glyph, float width); + extern osg::Geometry* computeTextGeometry(osg::Geometry* glyphGeometry, const Bevel& profile, float width); extern osg::Geometry* computeShellGeometry(osg::Geometry* glyphGeometry, const Bevel& profile, float width); diff --git a/examples/osgtext3D/TextNode.cpp b/examples/osgtext3D/TextNode.cpp index d64744da1..4b0aff02c 100644 --- a/examples/osgtext3D/TextNode.cpp +++ b/examples/osgtext3D/TextNode.cpp @@ -335,6 +335,14 @@ void TextTechnique::addCharacter(const osg::Vec3& position, const osg::Vec3& siz } else { + osg::ref_ptr textGeometry = osgText::computeTextGeometry(glyph, width); + if (textGeometry.valid()) geode->addDrawable(textGeometry.get()); + + // create the normals + if (smooth && textGeometry.valid()) + { + osgUtil::SmoothingVisitor::smooth(*textGeometry, osg::DegreesToRadians(creaseAngle)); + } } transform->addChild(geode.get()); diff --git a/examples/osgtext3D/osgtext3D.cpp b/examples/osgtext3D/osgtext3D.cpp index 244bb6ff1..224ed1cb1 100644 --- a/examples/osgtext3D/osgtext3D.cpp +++ b/examples/osgtext3D/osgtext3D.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -31,113 +30,11 @@ #include #include -#include "GlyphGeometry.h" -#include "TextNode.h" +#include extern int main_orig(int, char**); extern int main_test(int, char**); -int main_experimental(osg::ArgumentParser& arguments) -{ - std::string fontFile("arial.ttf"); - while(arguments.read("-f",fontFile)) {} - - std::string word("This is a simple test"); - - while(arguments.read("--ascii")) - { - word.clear(); - for(unsigned int c=' '; c<=127;++c) - { - word.push_back(c); - } - } - - while(arguments.read("-w",word)) {} - - osg::ref_ptr font = osgText::readFontFile(fontFile); - if (!font) return 1; - OSG_NOTICE<<"Read font "<setNumberCurveSamples(numSamples); - - profile.print(std::cout); - - - osg::ref_ptr group = new osg::Group; - osg::Vec3 position; - - for(unsigned int i=0; i glyph = font->getGlyph3D(word[i]); - if (!glyph) return 1; - - osg::ref_ptr transform = new osg::PositionAttitudeTransform; - transform->setPosition(position); - transform->setAttitude(osg::Quat(osg::inDegrees(90.0),osg::Vec3d(1.0,0.0,0.0))); - - position.x() += glyph->getHorizontalWidth(); - - osg::ref_ptr geode = new osg::Geode; - - osg::ref_ptr glyphGeometry = osgText::computeGlyphGeometry(glyph.get(), thickness, width); - osg::ref_ptr textGeometry = osgText::computeTextGeometry(glyphGeometry.get(), profile, width); - osg::ref_ptr shellGeometry = outline ? osgText::computeShellGeometry(glyphGeometry.get(), profile, width) : 0; - if (textGeometry.valid()) geode->addDrawable(textGeometry.get()); - if (shellGeometry.valid()) geode->addDrawable(shellGeometry.get()); - - // create the normals - if (smooth && textGeometry.valid()) - { - osgUtil::SmoothingVisitor::smooth(*textGeometry, osg::DegreesToRadians(creaseAngle)); - } - - transform->addChild(geode.get()); - - group->addChild(transform.get()); - } - - std::string filename; - if (arguments.read("-o", filename)) osgDB::writeNodeFile(*group, filename); - - osgViewer::Viewer viewer(arguments); - viewer.setSceneData(group.get()); - viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) ); - viewer.addEventHandler(new osgViewer::StatsHandler); - return viewer.run(); -} - int main(int argc, char** argv) { osg::ArgumentParser arguments(&argc, argv); @@ -150,10 +47,6 @@ int main(int argc, char** argv) { return main_orig(argc,argv); } - else if (arguments.read("--exp")) - { - return main_experimental(arguments); - } osgViewer::Viewer viewer(arguments); @@ -184,6 +77,10 @@ int main(int argc, char** argv) style->setBevel(bevel); + // set up outline. + while(arguments.read("--outline",r)) { style->setOutlineRatio(r); } + + osgText::TextNode* text = new osgText::TextNode; text->setText(word); text->setFont(font.get()); diff --git a/include/osgText/Font b/include/osgText/Font index 6f8013916..66540ddef 100644 --- a/include/osgText/Font +++ b/include/osgText/Font @@ -17,241 +17,16 @@ #include #include -#include -#include -#include -#include -#include #include -#include -#include - -#include -#include +#include +#include #include namespace osgText { +// forward declare Font class Font; -class Text; -class Glyph3D; -class GlyphTexture; - -class OSGTEXT_EXPORT Glyph : public osg::Image -{ -public: - - Glyph(unsigned int glyphCode); - - unsigned int getGlyphCode() const { return _glyphCode; } - - void setHorizontalBearing(const osg::Vec2& bearing); - const osg::Vec2& getHorizontalBearing() const; - - void setHorizontalAdvance(float advance); - float getHorizontalAdvance() const; - - void setVerticalBearing(const osg::Vec2& bearing); - const osg::Vec2& getVerticalBearing() const; - - void setVerticalAdvance(float advance); - float getVerticalAdvance() const; - - void setTexture(GlyphTexture* texture); - GlyphTexture* getTexture(); - const GlyphTexture* getTexture() const; - - void setTexturePosition(int posX,int posY); - int getTexturePositionX() const; - int getTexturePositionY() const; - - void setMinTexCoord(const osg::Vec2& coord); - const osg::Vec2& getMinTexCoord() const; - - void setMaxTexCoord(const osg::Vec2& coord); - const osg::Vec2& getMaxTexCoord() const; - - void subload() const; - -protected: - - virtual ~Glyph(); - - Font* _font; - unsigned int _glyphCode; - - osg::Vec2 _horizontalBearing; - float _horizontalAdvance; - - osg::Vec2 _verticalBearing; - float _verticalAdvance; - - GlyphTexture* _texture; - int _texturePosX; - int _texturePosY; - osg::Vec2 _minTexCoord; - osg::Vec2 _maxTexCoord; - - typedef osg::buffered_value GLObjectList; - mutable GLObjectList _globjList; - -}; - -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) - {} - - 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); - - - void setRawVertexArray(osg::Vec3Array* vertices) { _rawVertexArray = vertices; } - osg::Vec3Array* getRawVertexArray() { return _rawVertexArray.get(); } - - /** Get the PrimitiveSetList for the raw face which hasn't been tessellated. */ - osg::Geometry::PrimitiveSetList & getRawFacePrimitiveSetList() { return _rawFacePrimitiveSetList; } - - /** 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 _vertexArray; - osg::ref_ptr _normalArray; - - - osg::Geometry::PrimitiveSetList _frontPrimitiveSetList; - osg::Geometry::PrimitiveSetList _wallPrimitiveSetList; - osg::Geometry::PrimitiveSetList _backPrimitiveSetList; - - osg::ref_ptr _rawVertexArray; - osg::Geometry::PrimitiveSetList _rawFacePrimitiveSetList; - -}; - - -class OSGTEXT_EXPORT GlyphTexture : public osg::Texture2D -{ -public: - - GlyphTexture(); - - const char* className() const { return "GlyphTexture"; } - - /** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs.*/ - virtual int compare(const osg::StateAttribute& rhs) const; - - /** Set the margin around each glyph, to ensure that texture filtering doesn't bleed adjacent glyph's into each other.*/ - void setGlyphImageMargin(unsigned int margin) { _margin = margin; } - unsigned int getGlyphImageMargin() const { return _margin; } - - void setGlyphImageMarginRatio(float margin) { _marginRatio = margin; } - float getGlyphImageMarginRatio() const { return _marginRatio; } - - bool getSpaceForGlyph(Glyph* glyph, int& posX, int& posY); - - void addGlyph(Glyph* glyph,int posX, int posY); - - virtual void apply(osg::State& state) const; - - /** Set whether to use a mutex to ensure ref() and unref() are thread safe.*/ - virtual void setThreadSafeRefUnref(bool threadSafe); - - /** Resize any per context GLObject buffers to specified size. */ - virtual void resizeGLObjectBuffers(unsigned int maxSize); - -protected: - - virtual ~GlyphTexture(); - - - // parameter used to compute the size and position of empty space - // in the texture which could accommodate new glyphs. - int _margin; - float _marginRatio; - int _usedY; - int _partUsedX; - int _partUsedY; - - typedef std::vector< osg::ref_ptr > GlyphRefList; - typedef std::vector< const Glyph* > GlyphPtrList; - typedef osg::buffered_object< GlyphPtrList > GlyphBuffer; - - GlyphRefList _glyphs; - mutable GlyphBuffer _glyphsToSubload; - - mutable OpenThreads::Mutex _mutex; - -}; /** 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: @@ -272,14 +47,14 @@ protected: * 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 Font* readFontFile(const std::string& filename, const osgDB::ReaderWriter::Options* userOptions = 0); +extern OSGTEXT_EXPORT Font* readFontFile(const std::string& filename, const osgDB::Options* userOptions = 0); /** read a font from specified stream.*/ -extern OSGTEXT_EXPORT Font* readFontStream(std::istream& stream, const osgDB::ReaderWriter::Options* userOptions = 0); +extern OSGTEXT_EXPORT Font* readFontStream(std::istream& stream, const osgDB::Options* userOptions = 0); -extern OSGTEXT_EXPORT osg::ref_ptr readRefFontFile(const std::string& filename, const osgDB::ReaderWriter::Options* userOptions = 0); +extern OSGTEXT_EXPORT osg::ref_ptr readRefFontFile(const std::string& filename, const osgDB::Options* userOptions = 0); -extern OSGTEXT_EXPORT osg::ref_ptr readRefFontStream(std::istream& stream, const osgDB::ReaderWriter::Options* userOptions = 0); +extern OSGTEXT_EXPORT osg::ref_ptr readRefFontStream(std::istream& stream, const osgDB::Options* userOptions = 0); extern OSGTEXT_EXPORT std::string findFontFile(const std::string& str); diff --git a/include/osgText/TextNode b/include/osgText/TextNode new file mode 100644 index 000000000..736322800 --- /dev/null +++ b/include/osgText/TextNode @@ -0,0 +1,229 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 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_TEXTNODE +#define OSGTEXT_TEXTNODE 1 + + +#include +#include +#include + +#include +#include + +namespace osgText { + +// forward declare +class TextNode; +class Glyph; + +class Bevel : public osg::Object +{ + public: + + Bevel(); + Bevel(const Bevel& bevel, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Object(osgText, Bevel) + + void setBevelThickness(float thickness) { _thickness = thickness; } + float getBevelThickness() const { return _thickness; } + + void flatBevel(float width=0.25f); + + void roundedBevel(float width=0.5f, unsigned int numSteps=10); + + void roundedBevel2(float width=0.5f, unsigned int numSteps=10); + + typedef std::vector Vertices; + + void setVertices(const Vertices& vertices) { _vertices = vertices; } + Vertices& getVertices() { return _vertices; } + const Vertices& getVertices() const { return _vertices; } + + void print(std::ostream& fout); + + protected: + + float _thickness; + Vertices _vertices; +}; + + +class Style : public osg::Object +{ + public: + + Style(); + Style(const Style& style, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Object(osgText, Style) + + /// default Layout implementation used if no other is specified on TextNode + static osg::ref_ptr