From 2773d45f2a9146996ac716bd466a643233631b6e Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 7 Nov 2005 11:05:16 +0000 Subject: [PATCH] From Wang Lam,"The changes allow users of OpenSceneGraph to call a new function readFontStream() to load fonts from a std::istream, rather than from the local filesystem by name. Such a call may be used, for example, if the user has a font fetched over a network, or a font available in memory without a correspondng filename. The changes implement the new function by following the corresponding code for readFontFile(). readFontStream() reads a stream into memory, and holds that memory for FreeType. As a basic test, I mangled the osgtext example to use readFontStream(std::ifstream("font")) in lieu of a readFontFile call, and the modified example ran completely." --- include/osgText/Font | 5 ++ src/osgPlugins/freetype/FreeTypeFont.cpp | 15 ++++++ src/osgPlugins/freetype/FreeTypeFont.h | 2 + src/osgPlugins/freetype/FreeTypeLibrary.cpp | 46 +++++++++++++++++++ src/osgPlugins/freetype/FreeTypeLibrary.h | 2 + .../freetype/ReaderWriterFreeType.cpp | 12 +++++ src/osgText/Font.cpp | 27 +++++++++++ 7 files changed, 109 insertions(+) diff --git a/include/osgText/Font b/include/osgText/Font index d2a2bffaa..ae00c1ef9 100644 --- a/include/osgText/Font +++ b/include/osgText/Font @@ -15,6 +15,7 @@ #define OSGTEXT_FONT 1 #include +#include #include #include @@ -57,6 +58,10 @@ enum KerningType * the file will be searched again in the OS specific directories. */ extern OSGTEXT_EXPORT Font* readFontFile(const std::string& filename); + +/** read a font from specified stream.*/ +extern OSGTEXT_EXPORT Font* readFontStream(std::istream& stream); + extern OSGTEXT_EXPORT std::string findFontFile(const std::string& str); /** Pure virtual base class for fonts. diff --git a/src/osgPlugins/freetype/FreeTypeFont.cpp b/src/osgPlugins/freetype/FreeTypeFont.cpp index fa4477741..7d0fc1580 100644 --- a/src/osgPlugins/freetype/FreeTypeFont.cpp +++ b/src/osgPlugins/freetype/FreeTypeFont.cpp @@ -19,6 +19,14 @@ FreeTypeFont::FreeTypeFont(const std::string& filename, FT_Face face): _filename(filename), + _buffer(0), + _face(face) +{ +} + +FreeTypeFont::FreeTypeFont(FT_Byte* buffer, FT_Face face): + _filename(""), + _buffer(buffer), _face(face) { } @@ -37,6 +45,13 @@ FreeTypeFont::~FreeTypeFont() // free the freetype font face itself FT_Done_Face(_face); _face = 0; + + // release memory held for FT_Face to work + if (_buffer) + { + delete [] _buffer; + _buffer = 0; + } } } } diff --git a/src/osgPlugins/freetype/FreeTypeFont.h b/src/osgPlugins/freetype/FreeTypeFont.h index 3609b6741..0945240ed 100644 --- a/src/osgPlugins/freetype/FreeTypeFont.h +++ b/src/osgPlugins/freetype/FreeTypeFont.h @@ -25,6 +25,7 @@ class FreeTypeFont : public osgText::Font::FontImplementation public: FreeTypeFont(const std::string& filename, FT_Face face); + FreeTypeFont(FT_Byte* buffer, FT_Face face); virtual ~FreeTypeFont(); @@ -41,6 +42,7 @@ public: protected: std::string _filename; + FT_Byte* _buffer; FT_Face _face; }; diff --git a/src/osgPlugins/freetype/FreeTypeLibrary.cpp b/src/osgPlugins/freetype/FreeTypeLibrary.cpp index 0061e54cd..1fb107971 100644 --- a/src/osgPlugins/freetype/FreeTypeLibrary.cpp +++ b/src/osgPlugins/freetype/FreeTypeLibrary.cpp @@ -74,3 +74,49 @@ osgText::Font* FreeTypeLibrary::getFont(const std::string& fontfile,unsigned int return font; } + +osgText::Font* FreeTypeLibrary::getFont(std::istream& fontstream, unsigned int index) +{ + FT_Face face; /* handle to face object */ + FT_Open_Args args; + + std::streampos start = fontstream.tellg(); + fontstream.seekg(0, std::ios::end); + std::streampos end = fontstream.tellg(); + fontstream.seekg(start, std::ios::beg); + std::streampos length = end - start; + + /* empty stream into memory, open that, and keep the pointer in a FreeTypeFont for cleanup */ + FT_Byte *buffer = new FT_Byte[length]; + fontstream.read(reinterpret_cast(buffer), length); + if (!fontstream || (fontstream.gcount() != length)) + { + osg::notify(osg::WARN)<<" .... the font file could not be read from its stream"< #include +#include class FreeTypeLibrary : public osg::Referenced { @@ -29,6 +30,7 @@ public: static FreeTypeLibrary* instance(); osgText::Font* getFont(const std::string& fontfile,unsigned int index=0); + osgText::Font* getFont(std::istream& fontstream, unsigned int index=0); void removeFontImplmentation(FreeTypeFont* fontImpl) { _fontImplementationSet.erase(fontImpl); } diff --git a/src/osgPlugins/freetype/ReaderWriterFreeType.cpp b/src/osgPlugins/freetype/ReaderWriterFreeType.cpp index 812a2475d..2b2d333d3 100644 --- a/src/osgPlugins/freetype/ReaderWriterFreeType.cpp +++ b/src/osgPlugins/freetype/ReaderWriterFreeType.cpp @@ -40,6 +40,18 @@ class ReaderWriterFreeType : public osgDB::ReaderWriter return freeTypeLibrary->getFont(fileName,0); } + + virtual ReadResult readObject(std::istream& stream, const osgDB::ReaderWriter::Options*) const + { + FreeTypeLibrary* freeTypeLibrary = FreeTypeLibrary::instance(); + if (!freeTypeLibrary) + { + osg::notify(osg::WARN)<<"Warning:: cannot create freetype font after freetype library has been deleted."<getFont(stream, 0); + } }; // now register with Registry to instantiate the above diff --git a/src/osgText/Font.cpp b/src/osgText/Font.cpp index ea64814ad..4149e045d 100644 --- a/src/osgText/Font.cpp +++ b/src/osgText/Font.cpp @@ -93,6 +93,33 @@ osgText::Font* osgText::readFontFile(const std::string& filename) return 0; } +osgText::Font* osgText::readFontStream(std::istream& stream) +{ + osg::ref_ptr options = new osgDB::ReaderWriter::Options; + options->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_OBJECTS); + + // there should be a better way to get the FreeType ReaderWriter by name... + osgDB::ReaderWriter *reader = osgDB::Registry::instance()->getReaderWriterForExtension("ttf"); + if (reader == 0) return 0; + osgDB::ReaderWriter::ReadResult rr = reader->readObject(stream, options.get()); + if (rr.error()) + { + osg::notify(osg::WARN) << rr.message() << std::endl; + return 0; + } + if (!rr.validObject()) return 0; + + osg::Object *object = rr.takeObject(); + + // if the object is a font then return it. + osgText::Font* font = dynamic_cast(object); + if (font) return font; + + // otherwise if the object has zero references then delete it by doing another unref(). + if (object && object->referenceCount()==0) object->unref(); + return 0; +} + Font::Font(FontImplementation* implementation): _width(16),