mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-06-20 23:24:16 +00:00
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 "ps/CLogger.h"
|
||||
#include "ps/Filesystem.h"
|
||||
#include "ps/Profile.h"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -167,18 +168,35 @@ bool CFont::AddFontFromPath(const OsPath& fontPath)
|
||||
{
|
||||
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;
|
||||
if (FT_Error error{FT_New_Face(m_FreeType, fontPath.string8().c_str(), 0, &face)}; error == FT_Err_Unknown_File_Format)
|
||||
{
|
||||
LOGERROR("Font file format is not supported: %s", fontPath.string8());
|
||||
return false;
|
||||
}
|
||||
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());
|
||||
return false;
|
||||
}
|
||||
else if (error)
|
||||
{
|
||||
LOGERROR("Failed to load font %s: %d", fontPath.string8(), error);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Keep the font data alive.
|
||||
m_FontsData.push_back(fontData);
|
||||
|
||||
// Set the font size.
|
||||
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};
|
||||
|
||||
FT_Library m_FreeType;
|
||||
std::vector<std::shared_ptr<u8>> m_FontsData;
|
||||
std::vector<UniqueFTFace> m_Faces;
|
||||
UniqueFTStroker m_Stroker{nullptr, &ftStrokerDeleter};
|
||||
|
||||
|
||||
@@ -186,17 +186,9 @@ std::shared_ptr<CFont> CFontManager::LoadFont(CStrIntern fontName)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
OsPath realPath;
|
||||
g_VFS->GetOriginalPath(fntPath, realPath);
|
||||
if (realPath.empty())
|
||||
if (!font->AddFontFromPath(fntPath))
|
||||
{
|
||||
LOGERROR("Font file %s not found", fontPath.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!font->AddFontFromPath(realPath))
|
||||
{
|
||||
LOGERROR("Failed to load font %s", realPath.string8());
|
||||
LOGERROR("Failed to load font %s", fntPath.string8());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user