mirror of
https://github.com/SFML/SFML.git
synced 2024-11-29 06:41:05 +08:00
Fix null pointer dereference in Font
This commit is contained in:
parent
d0c63f46fc
commit
53594dfbe7
@ -401,7 +401,7 @@ private:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
std::shared_ptr<FontHandles> m_font; //!< Shared information about the internal font instance
|
std::shared_ptr<FontHandles> m_fontHandles; //!< Shared information about the internal font instance
|
||||||
bool m_isSmooth; //!< Status of the smooth filter
|
bool m_isSmooth; //!< Status of the smooth filter
|
||||||
Info m_info; //!< Information about the font
|
Info m_info; //!< Information about the font
|
||||||
mutable PageTable m_pages; //!< Table containing the glyphs pages by character size
|
mutable PageTable m_pages; //!< Table containing the glyphs pages by character size
|
||||||
|
@ -106,7 +106,7 @@ public:
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Font::Font() :
|
Font::Font() :
|
||||||
m_font (),
|
m_fontHandles(),
|
||||||
m_isSmooth (true),
|
m_isSmooth (true),
|
||||||
m_info ()
|
m_info ()
|
||||||
{
|
{
|
||||||
@ -116,7 +116,7 @@ m_info ()
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Font::Font(const Font& copy) :
|
Font::Font(const Font& copy) :
|
||||||
m_font (copy.m_font),
|
m_fontHandles(copy.m_fontHandles),
|
||||||
m_isSmooth (copy.m_isSmooth),
|
m_isSmooth (copy.m_isSmooth),
|
||||||
m_info (copy.m_info),
|
m_info (copy.m_info),
|
||||||
m_pages (copy.m_pages),
|
m_pages (copy.m_pages),
|
||||||
@ -141,7 +141,7 @@ bool Font::loadFromFile(const std::string& filename)
|
|||||||
// Cleanup the previous resources
|
// Cleanup the previous resources
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|
||||||
auto font = std::make_unique<FontHandles>();
|
auto fontHandles = std::make_unique<FontHandles>();
|
||||||
|
|
||||||
// Initialize FreeType
|
// Initialize FreeType
|
||||||
// Note: we initialize FreeType for every font instance in order to avoid having a single
|
// Note: we initialize FreeType for every font instance in order to avoid having a single
|
||||||
@ -152,7 +152,7 @@ bool Font::loadFromFile(const std::string& filename)
|
|||||||
err() << "Failed to load font \"" << filename << "\" (failed to initialize FreeType)" << std::endl;
|
err() << "Failed to load font \"" << filename << "\" (failed to initialize FreeType)" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
font->library.reset(library);
|
fontHandles->library.reset(library);
|
||||||
|
|
||||||
// Load the new font face from the specified file
|
// Load the new font face from the specified file
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
@ -161,7 +161,7 @@ bool Font::loadFromFile(const std::string& filename)
|
|||||||
err() << "Failed to load font \"" << filename << "\" (failed to create the font face)" << std::endl;
|
err() << "Failed to load font \"" << filename << "\" (failed to create the font face)" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
font->face.reset(face);
|
fontHandles->face.reset(face);
|
||||||
|
|
||||||
// Load the stroker that will be used to outline the font
|
// Load the stroker that will be used to outline the font
|
||||||
FT_Stroker stroker;
|
FT_Stroker stroker;
|
||||||
@ -170,7 +170,7 @@ bool Font::loadFromFile(const std::string& filename)
|
|||||||
err() << "Failed to load font \"" << filename << "\" (failed to create the stroker)" << std::endl;
|
err() << "Failed to load font \"" << filename << "\" (failed to create the stroker)" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
font->stroker.reset(stroker);
|
fontHandles->stroker.reset(stroker);
|
||||||
|
|
||||||
// Select the unicode character map
|
// Select the unicode character map
|
||||||
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0)
|
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0)
|
||||||
@ -180,7 +180,7 @@ bool Font::loadFromFile(const std::string& filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store the loaded font handles
|
// Store the loaded font handles
|
||||||
m_font = std::move(font);
|
m_fontHandles = std::move(fontHandles);
|
||||||
|
|
||||||
// Store the font information
|
// Store the font information
|
||||||
m_info.family = face->family_name ? face->family_name : std::string();
|
m_info.family = face->family_name ? face->family_name : std::string();
|
||||||
@ -202,7 +202,7 @@ bool Font::loadFromMemory(const void* data, std::size_t sizeInBytes)
|
|||||||
// Cleanup the previous resources
|
// Cleanup the previous resources
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|
||||||
auto font = std::make_unique<FontHandles>();
|
auto fontHandles = std::make_unique<FontHandles>();
|
||||||
|
|
||||||
// Initialize FreeType
|
// Initialize FreeType
|
||||||
// Note: we initialize FreeType for every font instance in order to avoid having a single
|
// Note: we initialize FreeType for every font instance in order to avoid having a single
|
||||||
@ -213,7 +213,7 @@ bool Font::loadFromMemory(const void* data, std::size_t sizeInBytes)
|
|||||||
err() << "Failed to load font from memory (failed to initialize FreeType)" << std::endl;
|
err() << "Failed to load font from memory (failed to initialize FreeType)" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
font->library.reset(library);
|
fontHandles->library.reset(library);
|
||||||
|
|
||||||
// Load the new font face from the specified file
|
// Load the new font face from the specified file
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
@ -222,7 +222,7 @@ bool Font::loadFromMemory(const void* data, std::size_t sizeInBytes)
|
|||||||
err() << "Failed to load font from memory (failed to create the font face)" << std::endl;
|
err() << "Failed to load font from memory (failed to create the font face)" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
font->face.reset(face);
|
fontHandles->face.reset(face);
|
||||||
|
|
||||||
// Load the stroker that will be used to outline the font
|
// Load the stroker that will be used to outline the font
|
||||||
FT_Stroker stroker;
|
FT_Stroker stroker;
|
||||||
@ -231,7 +231,7 @@ bool Font::loadFromMemory(const void* data, std::size_t sizeInBytes)
|
|||||||
err() << "Failed to load font from memory (failed to create the stroker)" << std::endl;
|
err() << "Failed to load font from memory (failed to create the stroker)" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
font->stroker.reset(stroker);
|
fontHandles->stroker.reset(stroker);
|
||||||
|
|
||||||
// Select the Unicode character map
|
// Select the Unicode character map
|
||||||
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0)
|
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0)
|
||||||
@ -241,7 +241,7 @@ bool Font::loadFromMemory(const void* data, std::size_t sizeInBytes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store the loaded font handles
|
// Store the loaded font handles
|
||||||
m_font = std::move(font);
|
m_fontHandles = std::move(fontHandles);
|
||||||
|
|
||||||
// Store the font information
|
// Store the font information
|
||||||
m_info.family = face->family_name ? face->family_name : std::string();
|
m_info.family = face->family_name ? face->family_name : std::string();
|
||||||
@ -256,7 +256,7 @@ bool Font::loadFromStream(InputStream& stream)
|
|||||||
// Cleanup the previous resources
|
// Cleanup the previous resources
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|
||||||
auto font = std::make_unique<FontHandles>();
|
auto fontHandles = std::make_unique<FontHandles>();
|
||||||
|
|
||||||
// Initialize FreeType
|
// Initialize FreeType
|
||||||
// Note: we initialize FreeType for every font instance in order to avoid having a single
|
// Note: we initialize FreeType for every font instance in order to avoid having a single
|
||||||
@ -267,7 +267,7 @@ bool Font::loadFromStream(InputStream& stream)
|
|||||||
err() << "Failed to load font from stream (failed to initialize FreeType)" << std::endl;
|
err() << "Failed to load font from stream (failed to initialize FreeType)" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
font->library.reset(library);
|
fontHandles->library.reset(library);
|
||||||
|
|
||||||
// Make sure that the stream's reading position is at the beginning
|
// Make sure that the stream's reading position is at the beginning
|
||||||
if (stream.seek(0) == -1)
|
if (stream.seek(0) == -1)
|
||||||
@ -277,19 +277,19 @@ bool Font::loadFromStream(InputStream& stream)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prepare a wrapper for our stream, that we'll pass to FreeType callbacks
|
// Prepare a wrapper for our stream, that we'll pass to FreeType callbacks
|
||||||
font->streamRec = std::make_unique<FT_StreamRec>();
|
fontHandles->streamRec = std::make_unique<FT_StreamRec>();
|
||||||
std::memset(font->streamRec.get(), 0, sizeof(*font->streamRec));
|
std::memset(fontHandles->streamRec.get(), 0, sizeof(*fontHandles->streamRec));
|
||||||
font->streamRec->base = nullptr;
|
fontHandles->streamRec->base = nullptr;
|
||||||
font->streamRec->size = static_cast<unsigned long>(stream.getSize());
|
fontHandles->streamRec->size = static_cast<unsigned long>(stream.getSize());
|
||||||
font->streamRec->pos = 0;
|
fontHandles->streamRec->pos = 0;
|
||||||
font->streamRec->descriptor.pointer = &stream;
|
fontHandles->streamRec->descriptor.pointer = &stream;
|
||||||
font->streamRec->read = &read;
|
fontHandles->streamRec->read = &read;
|
||||||
font->streamRec->close = &close;
|
fontHandles->streamRec->close = &close;
|
||||||
|
|
||||||
// Setup the FreeType callbacks that will read our stream
|
// Setup the FreeType callbacks that will read our stream
|
||||||
FT_Open_Args args;
|
FT_Open_Args args;
|
||||||
args.flags = FT_OPEN_STREAM;
|
args.flags = FT_OPEN_STREAM;
|
||||||
args.stream = font->streamRec.get();
|
args.stream = fontHandles->streamRec.get();
|
||||||
args.driver = nullptr;
|
args.driver = nullptr;
|
||||||
|
|
||||||
// Load the new font face from the specified stream
|
// Load the new font face from the specified stream
|
||||||
@ -299,7 +299,7 @@ bool Font::loadFromStream(InputStream& stream)
|
|||||||
err() << "Failed to load font from stream (failed to create the font face)" << std::endl;
|
err() << "Failed to load font from stream (failed to create the font face)" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
font->face.reset(face);
|
fontHandles->face.reset(face);
|
||||||
|
|
||||||
// Load the stroker that will be used to outline the font
|
// Load the stroker that will be used to outline the font
|
||||||
FT_Stroker stroker;
|
FT_Stroker stroker;
|
||||||
@ -308,7 +308,7 @@ bool Font::loadFromStream(InputStream& stream)
|
|||||||
err() << "Failed to load font from stream (failed to create the stroker)" << std::endl;
|
err() << "Failed to load font from stream (failed to create the stroker)" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
font->stroker.reset(stroker);
|
fontHandles->stroker.reset(stroker);
|
||||||
|
|
||||||
// Select the Unicode character map
|
// Select the Unicode character map
|
||||||
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0)
|
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0)
|
||||||
@ -318,7 +318,7 @@ bool Font::loadFromStream(InputStream& stream)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store the loaded font handles
|
// Store the loaded font handles
|
||||||
m_font = std::move(font);
|
m_fontHandles = std::move(fontHandles);
|
||||||
|
|
||||||
// Store the font information
|
// Store the font information
|
||||||
m_info.family = face->family_name ? face->family_name : std::string();
|
m_info.family = face->family_name ? face->family_name : std::string();
|
||||||
@ -341,7 +341,7 @@ const Glyph& Font::getGlyph(Uint32 codePoint, unsigned int characterSize, bool b
|
|||||||
GlyphTable& glyphs = m_pages[characterSize].glyphs;
|
GlyphTable& glyphs = m_pages[characterSize].glyphs;
|
||||||
|
|
||||||
// Build the key by combining the glyph index (based on code point), bold flag, and outline thickness
|
// Build the key by combining the glyph index (based on code point), bold flag, and outline thickness
|
||||||
Uint64 key = combine(outlineThickness, bold, FT_Get_Char_Index(m_font->face.get(), codePoint));
|
Uint64 key = combine(outlineThickness, bold, FT_Get_Char_Index(m_fontHandles ? m_fontHandles->face.get() : nullptr, codePoint));
|
||||||
|
|
||||||
// Search the glyph into the cache
|
// Search the glyph into the cache
|
||||||
if (auto it = glyphs.find(key); it != glyphs.end())
|
if (auto it = glyphs.find(key); it != glyphs.end())
|
||||||
@ -361,7 +361,7 @@ const Glyph& Font::getGlyph(Uint32 codePoint, unsigned int characterSize, bool b
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool Font::hasGlyph(Uint32 codePoint) const
|
bool Font::hasGlyph(Uint32 codePoint) const
|
||||||
{
|
{
|
||||||
return FT_Get_Char_Index(m_font->face.get(), codePoint) != 0;
|
return FT_Get_Char_Index(m_fontHandles ? m_fontHandles->face.get() : nullptr, codePoint) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -372,7 +372,7 @@ float Font::getKerning(Uint32 first, Uint32 second, unsigned int characterSize,
|
|||||||
if (first == 0 || second == 0)
|
if (first == 0 || second == 0)
|
||||||
return 0.f;
|
return 0.f;
|
||||||
|
|
||||||
auto face = m_font->face.get();
|
auto face = m_fontHandles ? m_fontHandles->face.get() : nullptr;
|
||||||
|
|
||||||
if (face && setCurrentSize(characterSize))
|
if (face && setCurrentSize(characterSize))
|
||||||
{
|
{
|
||||||
@ -409,7 +409,7 @@ float Font::getKerning(Uint32 first, Uint32 second, unsigned int characterSize,
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
float Font::getLineSpacing(unsigned int characterSize) const
|
float Font::getLineSpacing(unsigned int characterSize) const
|
||||||
{
|
{
|
||||||
auto face = m_font->face.get();
|
auto face = m_fontHandles ? m_fontHandles->face.get() : nullptr;
|
||||||
|
|
||||||
if (face && setCurrentSize(characterSize))
|
if (face && setCurrentSize(characterSize))
|
||||||
{
|
{
|
||||||
@ -425,7 +425,7 @@ float Font::getLineSpacing(unsigned int characterSize) const
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
float Font::getUnderlinePosition(unsigned int characterSize) const
|
float Font::getUnderlinePosition(unsigned int characterSize) const
|
||||||
{
|
{
|
||||||
auto face = m_font->face.get();
|
auto face = m_fontHandles ? m_fontHandles->face.get() : nullptr;
|
||||||
|
|
||||||
if (face && setCurrentSize(characterSize))
|
if (face && setCurrentSize(characterSize))
|
||||||
{
|
{
|
||||||
@ -445,7 +445,7 @@ float Font::getUnderlinePosition(unsigned int characterSize) const
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
float Font::getUnderlineThickness(unsigned int characterSize) const
|
float Font::getUnderlineThickness(unsigned int characterSize) const
|
||||||
{
|
{
|
||||||
auto face = m_font->face.get();
|
auto face = m_fontHandles ? m_fontHandles->face.get() : nullptr;
|
||||||
|
|
||||||
if (face && setCurrentSize(characterSize))
|
if (face && setCurrentSize(characterSize))
|
||||||
{
|
{
|
||||||
@ -494,7 +494,7 @@ Font& Font::operator =(const Font& right)
|
|||||||
{
|
{
|
||||||
Font temp(right);
|
Font temp(right);
|
||||||
|
|
||||||
std::swap(m_font, temp.m_font);
|
std::swap(m_fontHandles, temp.m_fontHandles);
|
||||||
std::swap(m_isSmooth, temp.m_isSmooth);
|
std::swap(m_isSmooth, temp.m_isSmooth);
|
||||||
std::swap(m_info, temp.m_info);
|
std::swap(m_info, temp.m_info);
|
||||||
std::swap(m_pages, temp.m_pages);
|
std::swap(m_pages, temp.m_pages);
|
||||||
@ -512,7 +512,7 @@ Font& Font::operator =(const Font& right)
|
|||||||
void Font::cleanup()
|
void Font::cleanup()
|
||||||
{
|
{
|
||||||
// Drop ownership of shared FreeType pointers
|
// Drop ownership of shared FreeType pointers
|
||||||
m_font.reset();
|
m_fontHandles.reset();
|
||||||
|
|
||||||
// Reset members
|
// Reset members
|
||||||
m_pages.clear();
|
m_pages.clear();
|
||||||
@ -526,8 +526,12 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, f
|
|||||||
// The glyph to return
|
// The glyph to return
|
||||||
Glyph glyph;
|
Glyph glyph;
|
||||||
|
|
||||||
// First, get our FT_Face
|
// Stop if no font is loaded
|
||||||
auto face = m_font->face.get();
|
if (!m_fontHandles)
|
||||||
|
return glyph;
|
||||||
|
|
||||||
|
// Get our FT_Face
|
||||||
|
auto face = m_fontHandles->face.get();
|
||||||
if (!face)
|
if (!face)
|
||||||
return glyph;
|
return glyph;
|
||||||
|
|
||||||
@ -560,7 +564,7 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, f
|
|||||||
|
|
||||||
if (outlineThickness != 0)
|
if (outlineThickness != 0)
|
||||||
{
|
{
|
||||||
auto stroker = m_font->stroker.get();
|
auto stroker = m_fontHandles->stroker.get();
|
||||||
|
|
||||||
FT_Stroker_Set(stroker, static_cast<FT_Fixed>(outlineThickness * static_cast<float>(1 << 6)), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
|
FT_Stroker_Set(stroker, static_cast<FT_Fixed>(outlineThickness * static_cast<float>(1 << 6)), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
|
||||||
FT_Glyph_Stroke(&glyphDesc, stroker, true);
|
FT_Glyph_Stroke(&glyphDesc, stroker, true);
|
||||||
@ -578,7 +582,7 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, f
|
|||||||
if (!outline)
|
if (!outline)
|
||||||
{
|
{
|
||||||
if (bold)
|
if (bold)
|
||||||
FT_Bitmap_Embolden(m_font->library.get(), &bitmap, weight, weight);
|
FT_Bitmap_Embolden(m_fontHandles->library.get(), &bitmap, weight, weight);
|
||||||
|
|
||||||
if (outlineThickness != 0)
|
if (outlineThickness != 0)
|
||||||
err() << "Failed to outline glyph (no fallback available)" << std::endl;
|
err() << "Failed to outline glyph (no fallback available)" << std::endl;
|
||||||
@ -764,7 +768,8 @@ bool Font::setCurrentSize(unsigned int characterSize) const
|
|||||||
// FT_Set_Pixel_Sizes is an expensive function, so we must call it
|
// FT_Set_Pixel_Sizes is an expensive function, so we must call it
|
||||||
// only when necessary to avoid killing performances
|
// only when necessary to avoid killing performances
|
||||||
|
|
||||||
auto face = m_font->face.get();
|
// m_fontHandles and m_fontHandles->face are checked to be non-null before calling this method
|
||||||
|
auto face = m_fontHandles->face.get();
|
||||||
FT_UShort currentSize = face->size->metrics.x_ppem;
|
FT_UShort currentSize = face->size->metrics.x_ppem;
|
||||||
|
|
||||||
if (currentSize != characterSize)
|
if (currentSize != characterSize)
|
||||||
|
Loading…
Reference in New Issue
Block a user