From a99b0e920da6a031366ef9ccde57307fd924ca5c Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Sun, 16 Nov 2025 10:42:01 +0300 Subject: [PATCH] Use FontData everywhere --- src/DrawComponents/DrawTextBox.cpp | 2 +- src/FontData.cpp | 26 ++++++++++++-------------- src/FontData.hpp | 5 +++-- src/GUIStuff/Elements/Element.hpp | 6 ++---- src/GUIStuff/Elements/FontPicker.cpp | 10 +++++----- src/GUIStuff/Elements/TextBox.hpp | 4 ++-- src/GUIStuff/GUIManager.cpp | 8 ++++---- src/MainProgram.cpp | 1 + src/MainProgram.hpp | 2 +- src/RichText/TextBox.cpp | 10 ++++++---- src/RichText/TextBox.hpp | 4 ++-- src/RichText/TextStyleModifier.cpp | 6 +++++- src/RichText/TextStyleModifier.hpp | 3 +++ src/Toolbar.cpp | 10 ++++------ 14 files changed, 51 insertions(+), 46 deletions(-) diff --git a/src/DrawComponents/DrawTextBox.cpp b/src/DrawComponents/DrawTextBox.cpp index 41ed81e..4148b66 100644 --- a/src/DrawComponents/DrawTextBox.cpp +++ b/src/DrawComponents/DrawTextBox.cpp @@ -61,7 +61,7 @@ void DrawTextBox::update_from_delayed_ptr(const std::shared_ptr& } void DrawTextBox::init_text_box(DrawingProgram& drawP) { - textBox->set_font_collection(drawP.world.main.fonts.collection); // Getting a segfault relating to the paragraph cache means that the font collection hasn't been set yet + textBox->set_font_data(drawP.world.main.fonts); // Getting a segfault relating to the paragraph cache means that the font collection hasn't been set yet textBox->set_width(d.p2.x() - d.p1.x() - TEXTBOX_PADDING * 2.0f); } diff --git a/src/FontData.cpp b/src/FontData.cpp index a310856..bd73ce5 100644 --- a/src/FontData.cpp +++ b/src/FontData.cpp @@ -17,8 +17,6 @@ #include -bool fallbackOnEmoji = false; - FontData::FontData() { #ifdef __EMSCRIPTEN__ @@ -48,17 +46,7 @@ FontData::FontData() fallbackOnEmoji = !defaultEmojiFallback; } -FontData::~FontData() { -} - -Vector2f get_str_font_bounds(const SkFont& font, const std::string& str) { - SkFontMetrics metrics; - font.getMetrics(&metrics); - float nextText = font.measureText(str.data(), str.length(), SkTextEncoding::kUTF8, nullptr); - return Vector2f{nextText, - metrics.fAscent + metrics.fDescent}; -} - -const std::vector& get_default_font_families() { +const std::vector& FontData::get_default_font_families() const { static std::vector defaultFontFamilies; if(defaultFontFamilies.empty()) { defaultFontFamilies.emplace_back("Roboto"); @@ -69,9 +57,19 @@ const std::vector& get_default_font_families() { return defaultFontFamilies; } -void push_default_font_families(std::vector& fontFamilies) { +void FontData::push_default_font_families(std::vector& fontFamilies) const { fontFamilies.emplace_back("Roboto"); if(fallbackOnEmoji) fontFamilies.emplace_back("Noto Emoji"); fontFamilies.emplace_back("Noto Kufi Arabic"); } + +FontData::~FontData() { +} + +Vector2f get_str_font_bounds(const SkFont& font, const std::string& str) { + SkFontMetrics metrics; + font.getMetrics(&metrics); + float nextText = font.measureText(str.data(), str.length(), SkTextEncoding::kUTF8, nullptr); + return Vector2f{nextText, - metrics.fAscent + metrics.fDescent}; +} diff --git a/src/FontData.hpp b/src/FontData.hpp index 82c9494..4c1e2ef 100644 --- a/src/FontData.hpp +++ b/src/FontData.hpp @@ -14,9 +14,10 @@ struct FontData { sk_sp localFontMgr; sk_sp collection; std::unordered_map> map; + bool fallbackOnEmoji = false; + const std::vector& get_default_font_families() const; + void push_default_font_families(std::vector& fontFamilies) const; ~FontData(); }; Vector2f get_str_font_bounds(const SkFont& font, const std::string& str); -const std::vector& get_default_font_families(); -void push_default_font_families(std::vector& fontFamilies); diff --git a/src/GUIStuff/Elements/Element.hpp b/src/GUIStuff/Elements/Element.hpp index 0b43ccc..72832c4 100644 --- a/src/GUIStuff/Elements/Element.hpp +++ b/src/GUIStuff/Elements/Element.hpp @@ -6,6 +6,7 @@ #include #include #include +#include "../../FontData.hpp" #include #include #include @@ -110,15 +111,12 @@ struct UpdateInputData { uint16_t fontSize = 16; - sk_sp fontCollection; - std::string textInput; bool hoverObstructed = false; bool acceptingTextInput = false; float deltaTime = 0.0f; - sk_sp textFontMgrLocal; - sk_sp textFontMgrFallback; + std::shared_ptr fonts; sk_sp textTypeface; DefaultStringArena* strArena; diff --git a/src/GUIStuff/Elements/FontPicker.cpp b/src/GUIStuff/Elements/FontPicker.cpp index 6a78d09..8c335d6 100644 --- a/src/GUIStuff/Elements/FontPicker.cpp +++ b/src/GUIStuff/Elements/FontPicker.cpp @@ -12,17 +12,17 @@ bool GUIStuff::FontPicker::update(UpdateInputData& io, std::string* fontName, GU auto icu = SkUnicodes::ICU::Make(); std::set sortedFontSet; - for(int i = 0; i < io.textFontMgrLocal->countFamilies(); i++) { + for(int i = 0; i < io.fonts->localFontMgr->countFamilies(); i++) { SkString familyNameSkString; - io.textFontMgrLocal->getFamilyName(i, &familyNameSkString); + io.fonts->localFontMgr->getFamilyName(i, &familyNameSkString); if(familyNameSkString.isEmpty()) continue; std::string familyName(familyNameSkString.c_str(), familyNameSkString.size()); sortedFontSet.emplace(familyName); } - for(int i = 0; i < io.textFontMgrFallback->countFamilies(); i++) { + for(int i = 0; i < io.fonts->defaultFontMgr->countFamilies(); i++) { SkString familyNameSkString; - io.textFontMgrFallback->getFamilyName(i, &familyNameSkString); + io.fonts->defaultFontMgr->getFamilyName(i, &familyNameSkString); if(familyNameSkString.isEmpty()) continue; std::string familyName(familyNameSkString.c_str(), familyNameSkString.size()); @@ -115,7 +115,7 @@ bool GUIStuff::FontPicker::update(UpdateInputData& io, std::string* fontName, GU tStyle.setForegroundColor(SkPaint{io.theme->frontColor1}); pStyle.setTextStyle(tStyle); - skia::textlayout::ParagraphBuilderImpl pBuilder(pStyle, io.fontCollection, SkUnicodes::ICU::Make()); + skia::textlayout::ParagraphBuilderImpl pBuilder(pStyle, io.fonts->collection, SkUnicodes::ICU::Make()); tStyle.setFontStyle(SkFontStyle::Normal()); pBuilder.pushStyle(tStyle); diff --git a/src/GUIStuff/Elements/TextBox.hpp b/src/GUIStuff/Elements/TextBox.hpp index 4a157c6..075dc2b 100644 --- a/src/GUIStuff/Elements/TextBox.hpp +++ b/src/GUIStuff/Elements/TextBox.hpp @@ -86,7 +86,7 @@ template class TextBox : public Element { paintOpts.cursorColor = {io.theme->fillColor1.fR, io.theme->fillColor1.fG, io.theme->fillColor1.fB}; skia::textlayout::TextStyle tStyle; - tStyle.setFontFamilies(get_default_font_families()); + tStyle.setFontFamilies(io.fonts->get_default_font_families()); tStyle.setFontSize(io.fontSize); tStyle.setForegroundPaint(SkPaint{io.theme->frontColor1}); textbox->set_initial_text_style(tStyle); @@ -103,7 +103,7 @@ template class TextBox : public Element { return; textbox = std::make_shared(); - textbox->set_font_collection(io.fontCollection); + textbox->set_font_data(io.fonts); textbox->set_allow_newlines(false); cur = std::make_shared(); diff --git a/src/GUIStuff/GUIManager.cpp b/src/GUIStuff/GUIManager.cpp index 8311e7c..844bda7 100644 --- a/src/GUIStuff/GUIManager.cpp +++ b/src/GUIStuff/GUIManager.cpp @@ -44,10 +44,10 @@ Clay_Dimensions GUIManager::clay_skia_measure_text(Clay_StringSlice str, Clay_Te pStyle.setTextAlign(skia::textlayout::TextAlign::kLeft); skia::textlayout::TextStyle tStyle; tStyle.setFontSize(config->fontSize); - tStyle.setFontFamilies(get_default_font_families()); + tStyle.setFontFamilies(window->io->fonts->get_default_font_families()); pStyle.setTextStyle(tStyle); - skia::textlayout::ParagraphBuilderImpl a(pStyle, window->io->fontCollection, SkUnicodes::ICU::Make()); + skia::textlayout::ParagraphBuilderImpl a(pStyle, window->io->fonts->collection, SkUnicodes::ICU::Make()); a.addText(str.chars, str.length); std::unique_ptr p = a.Build(); p->layout(std::numeric_limits::max()); @@ -117,11 +117,11 @@ void GUIManager::draw(SkCanvas* canvas) { pStyle.setTextAlign(skia::textlayout::TextAlign::kLeft); skia::textlayout::TextStyle tStyle; tStyle.setFontSize(config->fontSize); - tStyle.setFontFamilies(get_default_font_families()); + tStyle.setFontFamilies(io->fonts->get_default_font_families()); tStyle.setColor(convert_vec4(config->textColor).toSkColor()); pStyle.setTextStyle(tStyle); - skia::textlayout::ParagraphBuilderImpl a(pStyle, io->fontCollection, SkUnicodes::ICU::Make()); + skia::textlayout::ParagraphBuilderImpl a(pStyle, io->fonts->collection, SkUnicodes::ICU::Make()); a.addText(config->stringContents.chars, config->stringContents.length); std::unique_ptr p = a.Build(); p->layout(std::numeric_limits::max()); diff --git a/src/MainProgram.cpp b/src/MainProgram.cpp index 3018045..606c07c 100755 --- a/src/MainProgram.cpp +++ b/src/MainProgram.cpp @@ -37,6 +37,7 @@ #include MainProgram::MainProgram(): + fonts(std::make_shared()), toolbar(*this) { displayName = Random::get().alphanumeric_str(10); diff --git a/src/MainProgram.hpp b/src/MainProgram.hpp index 0cca3e8..60d947e 100644 --- a/src/MainProgram.hpp +++ b/src/MainProgram.hpp @@ -63,7 +63,7 @@ class MainProgram { WorldScalar inverseScale; } clipboard; - FontData fonts; + std::shared_ptr fonts; TimePoint deltaTime; Toolbar toolbar; std::shared_ptr world; diff --git a/src/RichText/TextBox.cpp b/src/RichText/TextBox.cpp index c8eef29..add94f2 100644 --- a/src/RichText/TextBox.cpp +++ b/src/RichText/TextBox.cpp @@ -794,9 +794,9 @@ void TextBox::set_allow_newlines(bool allow) { newlinesAllowed = allow; } -void TextBox::set_font_collection(const sk_sp& fC) { - if(fontCollection != fC) { - fontCollection = fC; +void TextBox::set_font_data(const std::shared_ptr& fD) { + if(fontData != fD) { + fontData = fD; inputChangedTextBox = true; needsRebuild = true; } @@ -810,6 +810,8 @@ void TextBox::rebuild() { skia::textlayout::TextStyle tStyle = initialTStyle; + FontFamiliesTextStyleModifier::globalFontData = fontData; + for(size_t pIndex = 0; pIndex < paragraphs.size(); pIndex++) { ParagraphData& pData = paragraphs[pIndex]; skia::textlayout::ParagraphStyle pStyle = pData.pStyleData.get_paragraph_style(); @@ -825,7 +827,7 @@ void TextBox::rebuild() { } size_t tIndex = 0; - skia::textlayout::ParagraphBuilderImpl a(pStyle, fontCollection, SkUnicodes::ICU::Make()); + skia::textlayout::ParagraphBuilderImpl a(pStyle, fontData->collection, SkUnicodes::ICU::Make()); for(;;) { if(nextTStyleModIt == tStyleMods.end() || nextTStyleModIt->pos.fParagraphIndex != pIndex) { diff --git a/src/RichText/TextBox.hpp b/src/RichText/TextBox.hpp index 15e09db..24cadb3 100644 --- a/src/RichText/TextBox.hpp +++ b/src/RichText/TextBox.hpp @@ -96,7 +96,7 @@ class TextBox { void set_width(float newWidth); TextPosition insert(TextPosition pos, std::string_view textToInsert, const std::optional& inputModMap = std::nullopt); TextPosition remove(TextPosition p1, TextPosition p2); - void set_font_collection(const sk_sp& fC); + void set_font_data(const std::shared_ptr& fD); void paint(SkCanvas* canvas, const PaintOpts& paintOpts); void set_allow_newlines(bool allow); float get_height(); @@ -174,7 +174,7 @@ class TextBox { float width = 0.0f; bool needsRebuild = true; unsigned tabWidth = 8; - sk_sp fontCollection; + std::shared_ptr fontData; struct ParagraphData { std::string text; diff --git a/src/RichText/TextStyleModifier.cpp b/src/RichText/TextStyleModifier.cpp index ef1c2f7..f268471 100644 --- a/src/RichText/TextStyleModifier.cpp +++ b/src/RichText/TextStyleModifier.cpp @@ -170,6 +170,7 @@ bool SizeTextStyleModifier::equivalent_data(TextStyleModifier& modifier) const { } +std::shared_ptr FontFamiliesTextStyleModifier::globalFontData = nullptr; FontFamiliesTextStyleModifier::FontFamiliesTextStyleModifier(const std::vector& initFamilies): families(initFamilies) {} @@ -190,8 +191,11 @@ void FontFamiliesTextStyleModifier::load(cereal::PortableBinaryInputArchive& a) } void FontFamiliesTextStyleModifier::modify_text_style(skia::textlayout::TextStyle& style) const { + if(!globalFontData) + throw std::runtime_error("[FontFamiliesTextStyleModifier::modify_text_style] global font data not set"); + auto familiesToPush = families; - push_default_font_families(familiesToPush); + globalFontData->push_default_font_families(familiesToPush); style.setFontFamilies(familiesToPush); } diff --git a/src/RichText/TextStyleModifier.hpp b/src/RichText/TextStyleModifier.hpp index 3d5beff..9d37981 100644 --- a/src/RichText/TextStyleModifier.hpp +++ b/src/RichText/TextStyleModifier.hpp @@ -4,6 +4,7 @@ #include #include "cereal/archives/portable_binary.hpp" #include "../SharedTypes.hpp" +#include "../FontData.hpp" namespace RichText { @@ -108,6 +109,8 @@ class SizeTextStyleModifier : public TextStyleModifier { class FontFamiliesTextStyleModifier : public TextStyleModifier { public: + static std::shared_ptr globalFontData; + FontFamiliesTextStyleModifier() = default; FontFamiliesTextStyleModifier(const std::vector& initFamilies); virtual ModifierType get_type() const override; diff --git a/src/Toolbar.cpp b/src/Toolbar.cpp index fddd181..b3121a6 100644 --- a/src/Toolbar.cpp +++ b/src/Toolbar.cpp @@ -39,10 +39,8 @@ Toolbar::Toolbar(MainProgram& initMain): io(std::make_shared()), main(initMain) { - io->textTypeface = main.fonts.map["Roboto"]; - io->textFontMgrLocal = main.fonts.localFontMgr; - io->textFontMgrFallback = main.fonts.defaultFontMgr; - io->fontCollection = main.fonts.collection; + io->textTypeface = main.fonts->map["Roboto"]; + io->fonts = main.fonts; load_default_palette(); load_default_theme(); @@ -824,12 +822,12 @@ std::unique_ptr Toolbar::build_paragraph_from_chat_ pStyle.setTextAlign(skia::textlayout::TextAlign::kLeft); skia::textlayout::TextStyle tStyle; tStyle.setFontSize(io->fontSize); - tStyle.setFontFamilies(get_default_font_families()); + tStyle.setFontFamilies(main.fonts->get_default_font_families()); tStyle.setFontStyle(SkFontStyle::Bold()); tStyle.setForegroundColor(SkPaint{color_mul_alpha(message.type == ChatMessage::JOIN ? io->theme->warningColor : io->theme->frontColor1, alpha)}); pStyle.setTextStyle(tStyle); - skia::textlayout::ParagraphBuilderImpl a(pStyle, io->fontCollection, SkUnicodes::ICU::Make()); + skia::textlayout::ParagraphBuilderImpl a(pStyle, io->fonts->collection, SkUnicodes::ICU::Make()); if(message.type == ChatMessage::JOIN) { std::string messageName = message.name + " "; a.addText(messageName.c_str(), messageName.length());