Hi Robert,
On Dec 16 you introduced a fix to remove internal use of ref_ptr<>'s.
It contained a bug that would cause freed memory to be written again.
Specifically, in FreeTypeLibrary::~FreeTypeLibrary(), calling
font->setImplementation(0); deletes the content pointed to by the
fontImplementation pointer, while the line the immediately follows
tries to access it.
My fix is to make the second instruction part of an else clause rather
than always executed. This way, the fontImplementation->_facade = 0
instruction is only executed when the font implementation is not set
to 0 before (although I have no idea what it is here for and if this
code path is ever followed, since I don't know the plugin's internals
very well).
Attached is the modified FreeTypeLibrary.cpp file.
Regards
Thibault
/* -*-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.
*/
#include "FreeTypeLibrary.h"
#include <osg/Notify>
//#include <ft2build.h>
//#define PRINT_OUT_FONT_DETAILS
#ifdef PRINT_OUT_FONT_DETAILS
#include <freetype/ftsnames.h>
#endif
#include FT_TRUETYPE_IDS_H
FreeTypeLibrary::FreeTypeLibrary()
{
osg::notify(osg::INFO) << "FreeTypeLibrary::FreeTypeLibrary()" <<
std::endl;
FT_Error error = FT_Init_FreeType( &_ftlibrary );
if (error)
{
osg::notify(osg::WARN)<<"Warning: an error occurred during
FT_Init_FreeType(..) initialisation, error code =
"<<std::hex<<error<<std::dec<<std::endl;
}
}
FreeTypeLibrary::~FreeTypeLibrary()
{
// need to remove the implementations from the Fonts here
// just in case the Fonts continue to have external references
// to them, otherwise they will try to point to an object thats
// definition has been unloaded along with the unload of the FreeType
// plugin.
while(!_fontImplementationSet.empty())
{
FreeTypeFont* fontImplementation = *_fontImplementationSet.begin();
_fontImplementationSet.erase(_fontImplementationSet.begin());
osgText::Font* font = fontImplementation->_facade;
if (font) font->setImplementation(0);
else fontImplementation->_facade = 0;
}
while(!_font3DImplementationSet.empty())
{
FreeTypeFont3D* font3DImplementation =
*_font3DImplementationSet.begin();
_font3DImplementationSet.erase(_font3DImplementationSet.begin());
osgText::Font3D* font3D = font3DImplementation->_facade;
if (font3D) font3D->setImplementation(0);
else font3DImplementation->_facade = 0;
}
FT_Done_FreeType( _ftlibrary);
}
FreeTypeLibrary* FreeTypeLibrary::instance()
{
static osg::ref_ptr<FreeTypeLibrary> s_library = new FreeTypeLibrary;
return s_library.get();
}
bool FreeTypeLibrary::getFace(const std::string& fontfile,unsigned int index,
FT_Face & face)
{
FT_Error error = FT_New_Face( _ftlibrary, fontfile.c_str(), index, &face );
if (error == FT_Err_Unknown_File_Format)
{
osg::notify(osg::WARN)<<" .... the font file could be opened and read,
but it appears"<<std::endl;
osg::notify(osg::WARN)<<" .... that its font format is
unsupported"<<std::endl;
return false;
}
else if (error)
{
osg::notify(osg::WARN)<<" .... another error code means that the font
file could not"<<std::endl;
osg::notify(osg::WARN)<<" .... be opened, read or simply that it is
broken.."<<std::endl;
return false;
}
#ifdef PRINT_OUT_FONT_DETAILS
osg::notify(osg::NOTICE)<<"Face"<<face<<std::endl;
unsigned int count = FT_Get_Sfnt_Name_Count(face);
for(unsigned int i=0; i<count; ++i)
{
FT_SfntName names;
FT_Error error = FT_Get_Sfnt_Name(face, i, &names);
std::string name((char*)names.string, (char*)names.string +
names.string_len);
osg::notify(osg::NOTICE)<<"names "<<name<<std::endl;
}
osg::notify(osg::NOTICE)<<std::endl;
#endif
//
// GT: Fix to handle symbol fonts in MS Windows
//
verifyCharacterMap(face);
return true;
}
FT_Byte* FreeTypeLibrary::getFace(std::istream& fontstream, unsigned int index,
FT_Face & face)
{
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<char*>(buffer), length);
if (!fontstream || (static_cast<std::streampos>(fontstream.gcount()) !=
length))
{
osg::notify(osg::WARN)<<" .... the font file could not be read from its
stream"<<std::endl;
return 0;
}
args.flags = FT_OPEN_MEMORY;
args.memory_base = buffer;
args.memory_size = length;
FT_Error error = FT_Open_Face( _ftlibrary, &args, index, &face );
if (error == FT_Err_Unknown_File_Format)
{
osg::notify(osg::WARN)<<" .... the font file could be opened and read,
but it appears"<<std::endl;
osg::notify(osg::WARN)<<" .... that its font format is
unsupported"<<std::endl;
return 0;
}
else if (error)
{
osg::notify(osg::WARN)<<" .... another error code means that the font
file could not"<<std::endl;
osg::notify(osg::WARN)<<" .... be opened, read or simply that it is
broken..."<<std::endl;
return 0;
}
//
// GT: Fix to handle symbol fonts in MS Windows
//
verifyCharacterMap(face);
return buffer;
}
osgText::Font* FreeTypeLibrary::getFont(const std::string& fontfile, unsigned
int index, unsigned int flags)
{
FT_Face face;
if (getFace(fontfile, index, face) == false) return (0);
FreeTypeFont* fontImp = new FreeTypeFont(fontfile,face,flags);
osgText::Font* font = new osgText::Font(fontImp);
_fontImplementationSet.insert(fontImp);
return font;
}
osgText::Font* FreeTypeLibrary::getFont(std::istream& fontstream, unsigned int
index, unsigned int flags)
{
FT_Face face = 0;
FT_Byte * buffer = getFace(fontstream, index, face);
if (face == 0) return (0);
FreeTypeFont* fontImp = new FreeTypeFont(buffer,face,flags);
osgText::Font* font = new osgText::Font(fontImp);
_fontImplementationSet.insert(fontImp);
return font;
}
osgText::Font3D* FreeTypeLibrary::getFont3D(const std::string& fontfile,
unsigned int index, unsigned int flags)
{
FT_Face face;
if (getFace(fontfile, index, face) == false) return (0);
FreeTypeFont3D* font3DImp = new FreeTypeFont3D(fontfile,face,flags);
osgText::Font3D* font3D = new osgText::Font3D(font3DImp);
_font3DImplementationSet.insert(font3DImp);
return font3D;
}
osgText::Font3D* FreeTypeLibrary::getFont3D(std::istream& fontstream, unsigned
int index, unsigned int flags)
{
FT_Face face = 0;
FT_Byte * buffer = getFace(fontstream, index, face);
if (face == 0) return (0);
FreeTypeFont3D* font3DImp = new FreeTypeFont3D(buffer,face,flags);
osgText::Font3D* font3D = new osgText::Font3D(font3DImp);
_font3DImplementationSet.insert(font3DImp);
return font3D;
}
void FreeTypeLibrary::verifyCharacterMap(FT_Face face)
{
//
// GT: Verify the correct character mapping for MS windows
// as symbol fonts were being returned incorrectly
//
FT_CharMap charmap;
if (face->charmap == NULL)
{
for (int n = 0; n < face->num_charmaps; n++)
{
charmap = face->charmaps[n];
if (charmap->platform_id == TT_PLATFORM_MICROSOFT)
{
FT_Set_Charmap(face, charmap);
break;
}
}
}
}
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org