1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-03-27 12:40:25 +00:00

Cleanup fonts loading

This commit is contained in:
Andrei Kortunov 2022-08-20 15:07:23 +04:00
parent ab2931223e
commit 9e1ab590f1
9 changed files with 115 additions and 140 deletions

View file

@ -208,7 +208,7 @@ namespace MWGui
// Load fonts // Load fonts
mFontLoader = std::make_unique<Gui::FontLoader>(encoding, resourceSystem->getVFS(), mScalingFactor); mFontLoader = std::make_unique<Gui::FontLoader>(encoding, resourceSystem->getVFS(), mScalingFactor);
mFontLoader->loadBitmapFonts(); mFontLoader->loadFonts();
//Register own widgets with MyGUI //Register own widgets with MyGUI
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSkill>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSkill>("Widget");
@ -236,7 +236,6 @@ namespace MWGui
MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer"); MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer");
MyGUI::FactoryManager::getInstance().registerFactory<AutoSizedResourceSkin>("Resource", "AutoSizedResourceSkin"); MyGUI::FactoryManager::getInstance().registerFactory<AutoSizedResourceSkin>("Resource", "AutoSizedResourceSkin");
MyGUI::ResourceManager::getInstance().load("core.xml"); MyGUI::ResourceManager::getInstance().load("core.xml");
mFontLoader->loadTrueTypeFonts();
bool keyboardNav = Settings::Manager::getBool("keyboard navigation", "GUI"); bool keyboardNav = Settings::Manager::getBool("keyboard navigation", "GUI");
mKeyboardNavigation = std::make_unique<KeyboardNavigation>(); mKeyboardNavigation = std::make_unique<KeyboardNavigation>();
@ -1175,9 +1174,6 @@ namespace MWGui
for (WindowBase* window : mWindows) for (WindowBase* window : mWindows)
window->onResChange(x, y); window->onResChange(x, y);
// We should reload TrueType fonts to fit new resolution
mFontLoader->loadTrueTypeFonts();
// TODO: check if any windows are now off-screen and move them back if so // TODO: check if any windows are now off-screen and move them back if so
} }

View file

@ -10,6 +10,7 @@
#include <MyGUI_ResourceManager.h> #include <MyGUI_ResourceManager.h>
#include <MyGUI_ResourceManualFont.h> #include <MyGUI_ResourceManualFont.h>
#include <MyGUI_ResourceTrueTypeFont.h>
#include <MyGUI_XmlDocument.h> #include <MyGUI_XmlDocument.h>
#include <MyGUI_FactoryManager.h> #include <MyGUI_FactoryManager.h>
#include <MyGUI_RenderManager.h> #include <MyGUI_RenderManager.h>
@ -163,37 +164,109 @@ namespace Gui
mEncoding = encoding; mEncoding = encoding;
MyGUI::ResourceManager::getInstance().unregisterLoadXmlDelegate("Resource"); MyGUI::ResourceManager::getInstance().unregisterLoadXmlDelegate("Resource");
MyGUI::ResourceManager::getInstance().registerLoadXmlDelegate("Resource") = MyGUI::newDelegate(this, &FontLoader::loadFontFromXml); MyGUI::ResourceManager::getInstance().registerLoadXmlDelegate("Resource") = MyGUI::newDelegate(this, &FontLoader::overrideLineHeight);
} }
void FontLoader::loadBitmapFonts() void FontLoader::loadFonts()
{ {
for (const auto& path : mVFS->getRecursiveDirectoryIterator("Fonts/")) std::string defaultFont = Fallback::Map::getString("Fonts_Font_0");
{ std::string scrollFont = Fallback::Map::getString("Fonts_Font_2");
if (Misc::getFileExtension(path) == "fnt") loadFont(defaultFont, "DefaultFont");
loadBitmapFont(path); loadFont(scrollFont, "ScrollFont");
} loadFont("DejaVuLGCSansMono", "MonoFont"); // We need to use a TrueType monospace font to display debug texts properly.
// Use our TrueType fonts as a fallback.
if (!MyGUI::ResourceManager::getInstance().isExist("DefaultFont") && !Misc::StringUtils::ciEqual(defaultFont, "Pelagiad"))
loadFont("Pelagiad", "DefaultFont");
if (!MyGUI::ResourceManager::getInstance().isExist("ScrollFont") && !Misc::StringUtils::ciEqual(scrollFont, "OMWAyembedt"))
loadFont("OMWAyembedt", "ScrollFont");
} }
void FontLoader::loadTrueTypeFonts() void FontLoader::loadFont(const std::string& fileName, const std::string& fontId)
{ {
if (mVFS->exists("fonts/" + fileName + ".fnt"))
loadBitmapFont(fileName + ".fnt", fontId);
else if (mVFS->exists("fonts/" + fileName + ".omwfont"))
loadTrueTypeFont(fileName + ".omwfont", fontId);
else
Log(Debug::Error) << "Font '" << fileName << "' is not found.";
}
void FontLoader::loadTrueTypeFont(const std::string& fileName, const std::string& fontId)
{
Log(Debug::Info) << "Loading font file " << fileName;
osgMyGUI::DataManager* dataManager = dynamic_cast<osgMyGUI::DataManager*>(&osgMyGUI::DataManager::getInstance()); osgMyGUI::DataManager* dataManager = dynamic_cast<osgMyGUI::DataManager*>(&osgMyGUI::DataManager::getInstance());
if (!dataManager) if (!dataManager)
{ {
Log(Debug::Error) << "Can not load TrueType fonts: osgMyGUI::DataManager is not available."; Log(Debug::Error) << "Can not load TrueType font " << fontId << ": osgMyGUI::DataManager is not available.";
return; return;
} }
std::string oldDataPath = dataManager->getDataPath(""); std::string oldDataPath = dataManager->getDataPath("");
dataManager->setResourcePath("fonts"); dataManager->setResourcePath("fonts");
std::unique_ptr<MyGUI::IDataStream> dataStream(dataManager->getData(fileName));
for (const auto& path : mVFS->getRecursiveDirectoryIterator("Fonts/")) MyGUI::xml::Document xmlDocument;
xmlDocument.open(dataStream.get());
MyGUI::xml::ElementPtr root = xmlDocument.getRoot();
MyGUI::xml::ElementEnumerator resourceNode = root->getElementEnumerator();
bool valid = false;
if (resourceNode.next("Resource"))
{ {
if (Misc::getFileExtension(path) == "omwfont") std::string type = resourceNode->findAttribute("type");
MyGUI::ResourceManager::getInstance().load(std::string(Misc::getFileName(path))); valid = (type == "ResourceTrueTypeFont");
} }
if (valid == false)
{
dataManager->setResourcePath(oldDataPath);
Log(Debug::Error) << "Can not load TrueType font " << fontId << ": " << fileName << " is invalid.";
return;
}
// For TrueType fonts we should override Size and Resolution properties
// to allow to configure font size via config file, without need to edit XML files.
// Also we should take UI scaling factor in account.
int resolution = Settings::Manager::getInt("ttf resolution", "GUI");
resolution = std::clamp(resolution, 50, 125) * mScalingFactor;
MyGUI::xml::ElementPtr resolutionNode = resourceNode->createChild("Property");
resolutionNode->addAttribute("key", "Resolution");
resolutionNode->addAttribute("value", std::to_string(resolution));
MyGUI::xml::ElementPtr sizeNode = resourceNode->createChild("Property");
sizeNode->addAttribute("key", "Size");
sizeNode->addAttribute("value", std::to_string(mFontHeight));
MyGUI::ResourceTrueTypeFont* font = static_cast<MyGUI::ResourceTrueTypeFont*>(
MyGUI::FactoryManager::getInstance().createObject("Resource", "ResourceTrueTypeFont"));
font->deserialization(resourceNode.current(), MyGUI::Version(3,2,0));
font->setResourceName(fontId);
MyGUI::ResourceManager::getInstance().addResource(font);
float currentX = Settings::Manager::getInt("resolution x", "Video");
float currentY = Settings::Manager::getInt("resolution y", "Video");
// TODO: read size from openmw_layout.xml somehow
// TODO: it may be worth to take in account resolution change, but it is not safe to replace used assets
float heightScale = (currentY / 520);
float widthScale = (currentX / 600);
float uiScale = std::min(widthScale, heightScale);
resolution = Settings::Manager::getInt("ttf resolution", "GUI");
resolution = std::clamp(resolution, 50, 125) * uiScale;
resolutionNode->setAttribute("value", std::to_string(resolution));
MyGUI::ResourceTrueTypeFont* bookFont = static_cast<MyGUI::ResourceTrueTypeFont*>(
MyGUI::FactoryManager::getInstance().createObject("Resource", "ResourceTrueTypeFont"));
bookFont->deserialization(resourceNode.current(), MyGUI::Version(3,2,0));
bookFont->setResourceName("Journalbook " + fontId);
MyGUI::ResourceManager::getInstance().addResource(bookFont);
dataManager->setResourcePath(oldDataPath); dataManager->setResourcePath(oldDataPath);
if (resourceNode.next("Resource"))
Log(Debug::Warning) << "Font file " << fileName << " contains multiple Resource entries, only first one will be used.";
} }
typedef struct typedef struct
@ -216,9 +289,11 @@ namespace Gui
float ascent; float ascent;
} GlyphInfo; } GlyphInfo;
void FontLoader::loadBitmapFont(const std::string &fileName) void FontLoader::loadBitmapFont(const std::string &fileName, const std::string& fontId)
{ {
Files::IStreamPtr file = mVFS->get(fileName); Log(Debug::Info) << "Loading font file " << fileName;
Files::IStreamPtr file = mVFS->get("fonts/" + fileName);
float fontSize; float fontSize;
file->read((char*)&fontSize, sizeof(fontSize)); file->read((char*)&fontSize, sizeof(fontSize));
@ -254,7 +329,7 @@ namespace Gui
file.reset(); file.reset();
// Create the font texture // Create the font texture
std::string bitmapFilename = "Fonts/" + std::string(name) + ".tex"; std::string bitmapFilename = "fonts/" + std::string(name) + ".tex";
Files::IStreamPtr bitmapFile = mVFS->get(bitmapFilename); Files::IStreamPtr bitmapFile = mVFS->get(bitmapFilename);
@ -285,8 +360,7 @@ namespace Gui
MyGUI::xml::Document xmlDocument; MyGUI::xml::Document xmlDocument;
MyGUI::xml::ElementPtr root = xmlDocument.createRoot("ResourceManualFont"); MyGUI::xml::ElementPtr root = xmlDocument.createRoot("ResourceManualFont");
std::string baseName(Misc::stemFile(fileName)); root->addAttribute("name", fontId);
root->addAttribute("name", getInternalFontName(baseName));
MyGUI::xml::ElementPtr defaultHeight = root->createChild("Property"); MyGUI::xml::ElementPtr defaultHeight = root->createChild("Property");
defaultHeight->addAttribute("key", "DefaultHeight"); defaultHeight->addAttribute("key", "DefaultHeight");
@ -444,48 +518,21 @@ namespace Gui
MyGUI::ResourceManualFont* bookFont = static_cast<MyGUI::ResourceManualFont*>( MyGUI::ResourceManualFont* bookFont = static_cast<MyGUI::ResourceManualFont*>(
MyGUI::FactoryManager::getInstance().createObject("Resource", "ResourceManualFont")); MyGUI::FactoryManager::getInstance().createObject("Resource", "ResourceManualFont"));
mFonts.push_back(bookFont);
bookFont->deserialization(root, MyGUI::Version(3,2,0)); bookFont->deserialization(root, MyGUI::Version(3,2,0));
bookFont->setResourceName("Journalbook " + getInternalFontName(baseName)); bookFont->setResourceName("Journalbook " + fontId);
MyGUI::ResourceManager::getInstance().addResource(font); MyGUI::ResourceManager::getInstance().addResource(font);
MyGUI::ResourceManager::getInstance().addResource(bookFont); MyGUI::ResourceManager::getInstance().addResource(bookFont);
} }
void FontLoader::loadFontFromXml(MyGUI::xml::ElementPtr _node, const std::string& _file, MyGUI::Version _version) void FontLoader::overrideLineHeight(MyGUI::xml::ElementPtr _node, const std::string& _file, MyGUI::Version _version)
{ {
MyGUI::xml::ElementEnumerator resourceNode = _node->getElementEnumerator(); MyGUI::xml::ElementEnumerator resourceNode = _node->getElementEnumerator();
bool createCopy = false;
while (resourceNode.next("Resource")) while (resourceNode.next("Resource"))
{ {
std::string type, name; std::string type = resourceNode->findAttribute("type");
resourceNode->findAttribute("type", type);
resourceNode->findAttribute("name", name);
if (name.empty()) if (Misc::StringUtils::ciEqual(type, "ResourceSkin") ||
continue;
if (Misc::StringUtils::ciEqual(type, "ResourceTrueTypeFont"))
{
createCopy = true;
// For TrueType fonts we should override Size and Resolution properties
// to allow to configure font size via config file, without need to edit XML files.
// Also we should take UI scaling factor in account.
int resolution = Settings::Manager::getInt("ttf resolution", "GUI");
resolution = std::clamp(resolution, 50, 125) * mScalingFactor;
MyGUI::xml::ElementPtr resolutionNode = resourceNode->createChild("Property");
resolutionNode->addAttribute("key", "Resolution");
resolutionNode->addAttribute("value", std::to_string(resolution));
MyGUI::xml::ElementPtr sizeNode = resourceNode->createChild("Property");
sizeNode->addAttribute("key", "Size");
sizeNode->addAttribute("value", std::to_string(mFontHeight));
resourceNode->setAttribute("name", getInternalFontName(name));
}
else if (Misc::StringUtils::ciEqual(type, "ResourceSkin") ||
Misc::StringUtils::ciEqual(type, "AutoSizedResourceSkin")) Misc::StringUtils::ciEqual(type, "AutoSizedResourceSkin"))
{ {
// We should adjust line height for MyGUI widgets depending on font size // We should adjust line height for MyGUI widgets depending on font size
@ -496,47 +543,6 @@ namespace Gui
} }
MyGUI::ResourceManager::getInstance().loadFromXmlNode(_node, _file, _version); MyGUI::ResourceManager::getInstance().loadFromXmlNode(_node, _file, _version);
if (createCopy)
{
std::unique_ptr<MyGUI::xml::Element> copy{_node->createCopy()};
MyGUI::xml::ElementEnumerator copyFont = copy->getElementEnumerator();
while (copyFont.next("Resource"))
{
std::string type, name;
copyFont->findAttribute("type", type);
copyFont->findAttribute("name", name);
if (name.empty())
continue;
if (Misc::StringUtils::ciEqual(type, "ResourceTrueTypeFont"))
{
// Since the journal and books use the custom scaling factor depending on resolution,
// setup separate fonts with different Resolution to fit these windows.
// These fonts have an internal prefix.
int resolution = Settings::Manager::getInt("ttf resolution", "GUI");
resolution = std::clamp(resolution, 50, 125);
float currentX = Settings::Manager::getInt("resolution x", "Video");
float currentY = Settings::Manager::getInt("resolution y", "Video");
// TODO: read size from openmw_layout.xml somehow
float heightScale = (currentY / 520);
float widthScale = (currentX / 600);
float uiScale = std::min(widthScale, heightScale);
resolution *= uiScale;
MyGUI::xml::ElementPtr resolutionNode = copyFont->createChild("Property");
resolutionNode->addAttribute("key", "Resolution");
resolutionNode->addAttribute("value", std::to_string(resolution));
copyFont->setAttribute("name", "Journalbook " + getInternalFontName(name));
}
}
MyGUI::ResourceManager::getInstance().loadFromXmlNode(copy.get(), _file, _version);
}
} }
int FontLoader::getFontHeight() int FontLoader::getFontHeight()
@ -544,26 +550,6 @@ namespace Gui
return mFontHeight; return mFontHeight;
} }
std::string FontLoader::getInternalFontName(const std::string& name)
{
const std::string lowerName = Misc::StringUtils::lowerCase(name);
if (lowerName == Misc::StringUtils::lowerCase(Fallback::Map::getString("Fonts_Font_0")))
return "DefaultFont";
if (lowerName == Misc::StringUtils::lowerCase(Fallback::Map::getString("Fonts_Font_2")))
return "ScrollFont";
if (lowerName == "dejavusansmono")
return "MonoFont"; // We need to use a TrueType monospace font to display debug texts properly.
// Use our TrueType fonts as a fallback.
if (!MyGUI::ResourceManager::getInstance().isExist("DefaultFont") && name == "pelagiad")
return "DefaultFont";
if (!MyGUI::ResourceManager::getInstance().isExist("ScrollFont") && name == "ayembedt")
return "ScrollFont";
return name;
}
std::string FontLoader::getFontForFace(const std::string& face) std::string FontLoader::getFontForFace(const std::string& face)
{ {
const std::string lowerFace = Misc::StringUtils::lowerCase(face); const std::string lowerFace = Misc::StringUtils::lowerCase(face);

View file

@ -27,10 +27,9 @@ namespace Gui
public: public:
FontLoader (ToUTF8::FromType encoding, const VFS::Manager* vfs, float scalingFactor); FontLoader (ToUTF8::FromType encoding, const VFS::Manager* vfs, float scalingFactor);
void loadBitmapFonts (); void loadFonts();
void loadTrueTypeFonts ();
void loadFontFromXml(MyGUI::xml::ElementPtr _node, const std::string& _file, MyGUI::Version _version); void overrideLineHeight(MyGUI::xml::ElementPtr _node, const std::string& _file, MyGUI::Version _version);
int getFontHeight(); int getFontHeight();
@ -42,11 +41,10 @@ namespace Gui
int mFontHeight; int mFontHeight;
float mScalingFactor; float mScalingFactor;
std::vector<MyGUI::ResourceManualFont*> mFonts; void loadFont(const std::string& fontName, const std::string& fontId);
std::string getInternalFontName(const std::string& name); void loadBitmapFont (const std::string& fileName, const std::string& fontId);
void loadTrueTypeFont(const std::string& fileName, const std::string& fontId);
void loadBitmapFont (const std::string& fileName);
FontLoader(const FontLoader&); FontLoader(const FontLoader&);
void operator=(const FontLoader&); void operator=(const FontLoader&);

View file

@ -3,8 +3,8 @@ Fonts
Default UI font and font used in magic scrolls are defined in ``openmw.cfg``: Default UI font and font used in magic scrolls are defined in ``openmw.cfg``:
fallback=Fonts_Font_0,pelagiad fallback=Fonts_Font_0,Pelagiad
fallback=Fonts_Font_2,ayembedt fallback=Fonts_Font_2,OMWAyembedt
When there are no ``Fonts_Font_*`` lines in user's ``openmw.cfg``, built-in TrueType fonts are used. When there are no ``Fonts_Font_*`` lines in user's ``openmw.cfg``, built-in TrueType fonts are used.
Font used by console and another debug windows is not configurable (so ``Fonts_Font_1`` is unused). Font used by console and another debug windows is not configurable (so ``Fonts_Font_1`` is unused).
@ -33,13 +33,11 @@ Unlike vanilla Morrowind, OpenMW directly supports TrueType (``.ttf``) fonts. Th
OpenMW has build-in TrueType fonts: Pelagiad, OMWAyembedt and DejaVuLGCSansMono, which are used by default. OpenMW has build-in TrueType fonts: Pelagiad, OMWAyembedt and DejaVuLGCSansMono, which are used by default.
TrueType fonts are configured via ``openmw.cfg`` too: TrueType fonts are configured via ``openmw.cfg`` too:
fallback=Fonts_Font_0,pelagiad fallback=Fonts_Font_0,Pelagiad
fallback=Fonts_Font_2,ayembedt fallback=Fonts_Font_2,OMWAyembedt
In this example, OpenMW will scan ``Fonts`` folder in data directories for ``.omwfont`` files. In this example, OpenMW will scan ``Fonts`` folder in data directories for ``.omwfont`` files.
These files are XML files wich schema used by MyGUI. OpenMW uses files which ``name`` tag matches ``openmw.cfg`` entries: These files are XML files with schema provided by MyGUI. OpenMW uses ``.omwfont`` files which name (without extension) matches ``openmw.cfg`` entries.
<Resource type="ResourceTrueTypeFont" name="pelagiad">
It is also possible to adjust the font size and resolution via ``settings.cfg`` file:: It is also possible to adjust the font size and resolution via ``settings.cfg`` file::

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Resource" version="1.1"> <MyGUI type="Resource" version="1.1">
<Resource type="ResourceTrueTypeFont" name="dejavusansmono"> <Resource type="ResourceTrueTypeFont">
<Property key="Source" value="DejaVuLGCSansMono.ttf"/> <Property key="Source" value="DejaVuLGCSansMono.ttf"/>
<Property key="Antialias" value="false"/> <Property key="Antialias" value="false"/>
<Property key="TabWidth" value="8"/> <Property key="TabWidth" value="8"/>

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Resource" version="1.1"> <MyGUI type="Resource" version="1.1">
<Resource type="ResourceTrueTypeFont" name="ayembedt"> <Resource type="ResourceTrueTypeFont">
<Property key="Source" value="OMWAyembedt.ttf"/> <Property key="Source" value="OMWAyembedt.ttf"/>
<Property key="Antialias" value="false"/> <Property key="Antialias" value="false"/>
<Property key="TabWidth" value="8"/> <Property key="TabWidth" value="8"/>

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Resource" version="1.1"> <MyGUI type="Resource" version="1.1">
<Resource type="ResourceTrueTypeFont" name="pelagiad"> <Resource type="ResourceTrueTypeFont">
<Property key="Source" value="Pelagiad.ttf"/> <Property key="Source" value="Pelagiad.ttf"/>
<Property key="Antialias" value="false"/> <Property key="Antialias" value="false"/>
<Property key="TabWidth" value="8"/> <Property key="TabWidth" value="8"/>

View file

@ -71,9 +71,9 @@ fallback=Water_UnderwaterColor,012,030,037
fallback=Water_UnderwaterColorWeight,0.85 fallback=Water_UnderwaterColorWeight,0.85
# fonts # fonts
fallback=Fonts_Font_0,pelagiad fallback=Fonts_Font_0,Pelagiad
fallback=Fonts_Font_1,dejavusansmono fallback=Fonts_Font_1,DejaVuLGCSansMono
fallback=Fonts_Font_2,ayembedt fallback=Fonts_Font_2,OMWAyembedt
fallback=FontColor_color_normal,202,165,96 fallback=FontColor_color_normal,202,165,96
fallback=FontColor_color_normal_over,223,201,159 fallback=FontColor_color_normal_over,223,201,159
fallback=FontColor_color_normal_pressed,243,237,221 fallback=FontColor_color_normal_pressed,243,237,221

View file

@ -71,9 +71,9 @@ fallback=Water_UnderwaterColor,012,030,037
fallback=Water_UnderwaterColorWeight,0.85 fallback=Water_UnderwaterColorWeight,0.85
# fonts # fonts
fallback=Fonts_Font_0,pelagiad fallback=Fonts_Font_0,Pelagiad
fallback=Fonts_Font_1,dejavusansmono fallback=Fonts_Font_1,DejaVuLGCSansMono
fallback=Fonts_Font_2,ayembedt fallback=Fonts_Font_2,OMWAyembedt
fallback=FontColor_color_normal,202,165,96 fallback=FontColor_color_normal,202,165,96
fallback=FontColor_color_normal_over,223,201,159 fallback=FontColor_color_normal_over,223,201,159
fallback=FontColor_color_normal_pressed,243,237,221 fallback=FontColor_color_normal_pressed,243,237,221