1
0
mirror of synced 2025-02-02 12:27:25 +01:00
ImHex/plugins/fonts/source/font_loader.cpp

109 lines
4.1 KiB
C++
Raw Normal View History

2024-06-16 22:41:16 +02:00
#include <imgui.h>
#include <imgui_internal.h>
#include <list>
2024-06-18 22:10:02 +02:00
2024-06-16 22:41:16 +02:00
#include <hex/api/imhex_api.hpp>
2024-06-18 22:10:02 +02:00
#include <hex/api/content_registry.hpp>
2024-06-18 22:10:02 +02:00
#include <hex/helpers/logger.hpp>
#include <hex/helpers/fs.hpp>
#include <hex/helpers/utils.hpp>
#include <wolv/utils/string.hpp>
2024-06-16 22:41:16 +02:00
#include <font_atlas.hpp>
2024-06-16 22:41:16 +02:00
namespace hex::fonts {
bool buildFontAtlas(FontAtlas *fontAtlas, std::fs::path fontPath, bool pixelPerfectFont, float fontSize, bool loadUnicodeCharacters, bool bold, bool italic, bool antialias) {
if (fontAtlas == nullptr) {
return false;
2024-06-16 22:41:16 +02:00
}
fontAtlas->reset();
2024-06-16 22:41:16 +02:00
// Check if Unicode support is enabled in the settings and that the user doesn't use the No GPU version on Windows
// The Mesa3D software renderer on Windows identifies itself as "VMware, Inc."
bool shouldLoadUnicode =
ContentRegistry::Settings::read<bool>("hex.fonts.setting.font", "hex.builtin.fonts.font.load_all_unicode_chars", false) &&
2024-06-16 22:41:16 +02:00
ImHexApi::System::getGPUVendor() != "VMware, Inc.";
if (!loadUnicodeCharacters)
shouldLoadUnicode = false;
fontAtlas->enableUnicodeCharacters(shouldLoadUnicode);
2025-01-18 19:03:55 +01:00
2024-06-16 22:41:16 +02:00
// If a custom font is set in the settings, load the rest of the settings as well
2025-01-18 19:03:55 +01:00
if (!pixelPerfectFont) {
fontAtlas->setBold(bold);
fontAtlas->setItalic(italic);
fontAtlas->setAntiAliasing(antialias);
} else {
fontPath.clear();
2024-06-16 22:41:16 +02:00
}
// Try to load the custom font if one was set
std::optional<Font> defaultFont;
if (!fontPath.empty()) {
defaultFont = fontAtlas->addFontFromFile(fontPath, fontSize, true, ImVec2());
if (!fontAtlas->build()) {
log::error("Failed to load custom font '{}'! Falling back to default font", wolv::util::toUTF8String(fontPath));
2024-06-16 22:41:16 +02:00
defaultFont.reset();
}
}
// If there's no custom font set, or it failed to load, fall back to the default font
if (!defaultFont.has_value()) {
if (pixelPerfectFont) {
defaultFont = fontAtlas->addDefaultFont();
fontSize = std::floor(fontAtlas->getAdjustedFontSize(ImHexApi::System::getGlobalScale() * 13.0F));
} else
defaultFont = fontAtlas->addFontFromRomFs("fonts/JetBrainsMono.ttf", fontSize, true, ImVec2());
if (!fontAtlas->build()) {
2024-06-16 22:41:16 +02:00
log::fatal("Failed to load default font!");
return false;
}
}
// Add all the built-in fonts
{
static std::list<ImVector<ImWchar>> glyphRanges;
glyphRanges.clear();
for (auto &font : ImHexApi::Fonts::impl::getFonts()) {
// Construct the glyph range for the font
ImVector<ImWchar> glyphRange;
if (!font.glyphRanges.empty()) {
for (const auto &range : font.glyphRanges) {
glyphRange.push_back(range.begin);
glyphRange.push_back(range.end);
}
glyphRange.push_back(0x00);
}
glyphRanges.push_back(glyphRange);
// Calculate the glyph offset for the font
const ImVec2 offset = { font.offset.x, font.offset.y - (defaultFont->getDescent() - fontAtlas->calculateFontDescend(font, fontSize)) };
2024-06-16 22:41:16 +02:00
// Load the font
fontAtlas->addFontFromMemory(font.fontData, font.defaultSize.value_or(fontSize), !font.defaultSize.has_value(), offset, glyphRanges.back());
2024-06-16 22:41:16 +02:00
}
}
// Build the font atlas
if (fontAtlas->build()) {
2024-06-16 22:41:16 +02:00
return true;
}
// If the build wasn't successful and Unicode characters are enabled, try again without them
// If they were disabled already, something went wrong, and we can't recover from it
if (!shouldLoadUnicode) {
2024-06-16 22:41:16 +02:00
return false;
} else {
return buildFontAtlas(fontAtlas, fontPath, pixelPerfectFont, fontSize, false, bold, italic, antialias);
}
2024-06-16 22:41:16 +02:00
}
}