forked from mirrors/0ad
Fix FreeType font loading from zipped mods
The FreeType font loader was directly passing filesystem-style paths (e.g., mod.zip/...) to FT_New_Face, which does not support paths inside ZIP archives. As a result, FreeType failed to open the font, triggering a crash when the engine attempted to use an invalid face object. This patch changes the font loading logic to: Use the VFS to read the .ttf font file into memory (shared_ptr<u8> and size). Load the font using FT_New_Memory_Face with the in-memory buffer, ensuring compatibility with zipped mods.
This commit is contained in:
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "graphics/TextureManager.h"
|
#include "graphics/TextureManager.h"
|
||||||
#include "ps/CLogger.h"
|
#include "ps/CLogger.h"
|
||||||
|
#include "ps/Filesystem.h"
|
||||||
#include "ps/Profile.h"
|
#include "ps/Profile.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -167,18 +168,35 @@ bool CFont::AddFontFromPath(const OsPath& fontPath)
|
|||||||
{
|
{
|
||||||
ENSURE(m_FontSize > 0);
|
ENSURE(m_FontSize > 0);
|
||||||
|
|
||||||
|
if (!VfsFileExists(fontPath))
|
||||||
|
{
|
||||||
|
LOGERROR("Font file does not exist: %s", fontPath.string8());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<u8> fontData;
|
||||||
|
size_t fontDataSize;
|
||||||
|
if (g_VFS->LoadFile(fontPath, fontData, fontDataSize) != 0)
|
||||||
|
{
|
||||||
|
LOGERROR("Failed to load font file: %s", fontPath.string8());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
if (FT_Error error{FT_New_Face(m_FreeType, fontPath.string8().c_str(), 0, &face)}; error == FT_Err_Unknown_File_Format)
|
if (FT_Error error{FT_New_Memory_Face(m_FreeType, fontData.get(), static_cast<FT_Long>(fontDataSize), 0, &face)}; error == FT_Err_Unknown_File_Format)
|
||||||
{
|
{
|
||||||
LOGERROR("Font file format is not supported: %s", fontPath.string8());
|
LOGERROR("Font file format is not supported: %s", fontPath.string8());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (error)
|
else if (error)
|
||||||
{
|
{
|
||||||
LOGERROR("Failed to load font %s: %d", fontPath.string8(), error);
|
LOGERROR("Failed to load font %s: %d", fontPath.string8(), error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keep the font data alive.
|
||||||
|
m_FontsData.push_back(fontData);
|
||||||
|
|
||||||
// Set the font size.
|
// Set the font size.
|
||||||
if (FT_Error error{FT_Set_Char_Size(face, 0, FloatToF26Dot6(m_FontSize), 0 , 0)})
|
if (FT_Error error{FT_Set_Char_Size(face, 0, FloatToF26Dot6(m_FontSize), 0 , 0)})
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -159,6 +159,7 @@ private:
|
|||||||
std::shared_ptr<std::array<float, 256>> m_GammaCorrectionLUT{nullptr};
|
std::shared_ptr<std::array<float, 256>> m_GammaCorrectionLUT{nullptr};
|
||||||
|
|
||||||
FT_Library m_FreeType;
|
FT_Library m_FreeType;
|
||||||
|
std::vector<std::shared_ptr<u8>> m_FontsData;
|
||||||
std::vector<UniqueFTFace> m_Faces;
|
std::vector<UniqueFTFace> m_Faces;
|
||||||
UniqueFTStroker m_Stroker{nullptr, &ftStrokerDeleter};
|
UniqueFTStroker m_Stroker{nullptr, &ftStrokerDeleter};
|
||||||
|
|
||||||
|
|||||||
@@ -186,17 +186,9 @@ std::shared_ptr<CFont> CFontManager::LoadFont(CStrIntern fontName)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
OsPath realPath;
|
if (!font->AddFontFromPath(fntPath))
|
||||||
g_VFS->GetOriginalPath(fntPath, realPath);
|
|
||||||
if (realPath.empty())
|
|
||||||
{
|
{
|
||||||
LOGERROR("Font file %s not found", fontPath.c_str());
|
LOGERROR("Failed to load font %s", fntPath.string8());
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!font->AddFontFromPath(realPath))
|
|
||||||
{
|
|
||||||
LOGERROR("Failed to load font %s", realPath.string8());
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user