Finish dynamic load GetImGuiFont function

This commit is contained in:
Dan Paulat 2023-10-02 23:57:19 -05:00
parent aead8e7264
commit e4ab1e8c19
4 changed files with 59 additions and 35 deletions

View file

@ -30,16 +30,15 @@ struct FontRecord
std::string filename_ {};
};
typedef std::pair<FontRecord, units::font_size::pixels<int>> FontRecordPair;
template<class Key>
struct FontRecordHash;
template<class Key>
struct FontRecordKeyEqual;
template<>
struct FontRecordHash<std::pair<FontRecord, int>>
struct FontRecordHash<FontRecordPair>
{
size_t operator()(const std::pair<FontRecord, int>& x) const;
size_t operator()(const FontRecordPair& x) const;
};
class FontManager::Impl
@ -65,9 +64,9 @@ public:
std::shared_mutex imguiFontAtlasMutex_ {};
boost::unordered_flat_map<std::pair<FontRecord, int>,
boost::unordered_flat_map<FontRecordPair,
std::shared_ptr<types::ImGuiFont>,
FontRecordHash<std::pair<FontRecord, int>>>
FontRecordHash<FontRecordPair>>
imguiFonts_ {};
std::shared_mutex imguiFontsMutex_ {};
@ -88,7 +87,8 @@ std::shared_mutex& FontManager::imgui_font_atlas_mutex()
std::shared_ptr<types::ImGuiFont>
FontManager::GetImGuiFont(const std::string& family,
const std::vector<std::string>& styles,
units::font_size::points<double> size)
units::font_size::points<double> size,
bool loadIfNotFound)
{
const std::string styleString = fmt::format("{}", fmt::join(styles, " "));
const std::string fontString =
@ -100,14 +100,16 @@ FontManager::GetImGuiFont(const std::string& family,
// Only allow whole pixels, and clamp to 6-72 pt
units::font_size::pixels<double> pixels {size};
int imFontSize = std::clamp(static_cast<int>(pixels.value()), 8, 96);
units::font_size::pixels<int> imFontSize {
std::clamp(static_cast<int>(pixels.value()), 8, 96)};
auto imguiFontKey = std::make_pair(fontRecord, imFontSize);
// Search for a loaded ImGui font
{
std::shared_lock imguiFontLock {p->imguiFontsMutex_};
// Search for the associated ImGui font
auto it = p->imguiFonts_.find(std::make_pair(fontRecord, imFontSize));
auto it = p->imguiFonts_.find(imguiFontKey);
if (it != p->imguiFonts_.end())
{
return it->second;
@ -116,17 +118,38 @@ FontManager::GetImGuiFont(const std::string& family,
// No ImGui font was found, we need to create one
}
// No font was found, return an empty shared pointer if not loading
if (!loadIfNotFound)
{
return nullptr;
}
// Get raw font data
const auto& rawFontData = p->GetRawFontData(fontRecord.filename_);
// TODO: Create an ImGui font
// TODO: imguiFontLock could be acquired during a render loop, when the font
// atlas is already locked. Lock the font atlas first. Unless it's already
// locked. It might need to be reentrant?
// TODO: Search for font once more, to prevent loading the same font twice
Q_UNUSED(rawFontData);
// The font atlas mutex might already be locked within an ImGui render frame.
// Lock the font atlas mutex before the fonts mutex to prevent deadlock.
std::unique_lock imguiFontAtlasLock {p->imguiFontAtlasMutex_};
std::unique_lock imguiFontsLock {p->imguiFontsMutex_};
return nullptr;
// Search for the associated ImGui font again, to prevent loading the same
// font twice
auto it = p->imguiFonts_.find(imguiFontKey);
if (it != p->imguiFonts_.end())
{
return it->second;
}
// Create an ImGui font
std::shared_ptr<types::ImGuiFont> imguiFont =
std::make_shared<types::ImGuiFont>(
fontRecord.filename_, rawFontData, imFontSize);
// Store the ImGui font
p->imguiFonts_.insert_or_assign(imguiFontKey, imguiFont);
// Return the ImGui font
return imguiFont;
}
const std::vector<std::uint8_t>&
@ -311,14 +334,13 @@ FontManager& FontManager::Instance()
return instance_;
}
size_t FontRecordHash<std::pair<FontRecord, int>>::operator()(
const std::pair<FontRecord, int>& x) const
size_t FontRecordHash<FontRecordPair>::operator()(const FontRecordPair& x) const
{
size_t seed = 0;
boost::hash_combine(seed, x.first.family_);
boost::hash_combine(seed, x.first.style_);
boost::hash_combine(seed, x.first.filename_);
boost::hash_combine(seed, x.second);
boost::hash_combine(seed, x.second.value());
return seed;
}

View file

@ -26,7 +26,8 @@ public:
std::shared_ptr<types::ImGuiFont>
GetImGuiFont(const std::string& family,
const std::vector<std::string>& styles,
units::font_size::points<double> size);
units::font_size::points<double> size,
bool loadIfNotFound = false);
void LoadApplicationFont(const std::string& filename);

View file

@ -23,9 +23,9 @@ static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
class ImGuiFont::Impl
{
public:
explicit Impl(const std::string& fontName,
const std::string& fontData,
units::pixels<double> size) :
explicit Impl(const std::string& fontName,
const std::vector<std::uint8_t>& fontData,
units::font_size::pixels<int> size) :
fontName_ {fontName}, size_ {size}
{
CreateImGuiFont(fontData);
@ -33,23 +33,23 @@ public:
~Impl() {}
void CreateImGuiFont(const std::string& fontData);
void CreateImGuiFont(const std::vector<std::uint8_t>& fontData);
const std::string fontName_;
const units::pixels<double> size_;
const std::string fontName_;
const units::font_size::pixels<int> size_;
ImFont* imFont_ {nullptr};
};
ImGuiFont::ImGuiFont(const std::string& fontName,
const std::string& fontData,
units::pixels<double> size) :
ImGuiFont::ImGuiFont(const std::string& fontName,
const std::vector<std::uint8_t>& fontData,
units::font_size::pixels<int> size) :
p(std::make_unique<Impl>(fontName, fontData, size))
{
}
ImGuiFont::~ImGuiFont() = default;
void ImGuiFont::Impl::CreateImGuiFont(const std::string& fontData)
void ImGuiFont::Impl::CreateImGuiFont(const std::vector<std::uint8_t>& fontData)
{
logger_->debug("Creating Font: {}", fontName_);
@ -66,7 +66,7 @@ void ImGuiFont::Impl::CreateImGuiFont(const std::string& fontData)
fontConfig.Name[sizeof(fontConfig.Name) - 1] = 0;
imFont_ = fontAtlas->AddFontFromMemoryTTF(
const_cast<void*>(static_cast<const void*>(fontData.c_str())),
const_cast<void*>(static_cast<const void*>(fontData.data())),
static_cast<int>(std::clamp<std::size_t>(
fontData.size(), 0, std::numeric_limits<int>::max())),
sizePixels,

View file

@ -2,6 +2,7 @@
#include <memory>
#include <string>
#include <vector>
#include <scwx/qt/types/font_types.hpp>
@ -17,9 +18,9 @@ namespace types
class ImGuiFont
{
public:
explicit ImGuiFont(const std::string& fontName,
const std::string& fontData,
units::pixels<double> size);
explicit ImGuiFont(const std::string& fontName,
const std::vector<std::uint8_t>& fontData,
units::font_size::pixels<int> size);
~ImGuiFont();
ImGuiFont(const ImGuiFont&) = delete;