Added caching for string dimensions in BasicRenderer2D

This commit is contained in:
OmniaX-Dev 2026-05-04 19:51:15 +02:00
parent 012f26f5f5
commit 424574a2e6
27 changed files with 143 additions and 61 deletions

View file

@ -28,6 +28,7 @@
***FIX: ToolBar::AddButton not consistent order
***FIX: KeyPress crash on TreeView
***FIX: Animated icons not working in TreeView
***Check if possible, then change all WindowCore& refs to Window&
Implement cursors in Stylesheet
FIX: Window getting exponentially bigger when Desktop scale changes
FIX: Refreshing scroll when content extent changes
@ -55,7 +56,6 @@ FIX: ContextMenu rendering partly outside the screen when showing it close to th
Add ToolBar::addButton overload that takes a ogfx::Icon wrapper
Redesign theme overrides to be more robust
Add modifiers to Event.keyboard path
Check if possible, then change all WindowCore& refs to Window&

View file

@ -304,7 +304,7 @@ namespace ogfx
push_panel(m_data.entries, pos, false);
m_visible = true;
m_animClock.startCount(ostd::eTimeUnits::Milliseconds);
cast<Window&>(m_window).getFocusManager().clearFocus();
m_window.getFocusManager().clearFocus();
}
void ContextMenu::hide(void)

View file

@ -114,7 +114,7 @@ namespace ogfx
f32 animProgress { 0 }; // 0.0 = collapsed, 1.0 = fully open
};
public:
inline ContextMenu(WindowCore& window) : m_window(window) { create(); }
inline ContextMenu(Window& window) : m_window(window) { create(); }
ContextMenu& create(void);
void applyTheme(const ostd::Stylesheet& theme);
void draw(BasicRenderer2D& gfx);
@ -155,7 +155,7 @@ namespace ogfx
void relayout_panels(void);
private:
WindowCore& m_window;
Window& m_window;
bool m_visible { false };
Instance m_data;
f32 m_entryHeight { 0 };

View file

@ -149,6 +149,13 @@ namespace ogfx
{
if (isTabNavigationEnabled() && event.keyboard->keyCode == KeyCode::Tab)
focusNext();
else if (event.keyboard->keyCode == KeyCode::Space || event.keyboard->keyCode == KeyCode::Return || event.keyboard->keyCode == KeyCode::Return2 || event.keyboard->keyCode == KeyCode::KpEnter)
{
if (!m_focused)
return;
if (m_focused->callback_onActionPerformed)
m_focused->callback_onActionPerformed(event);
}
}
}
}

View file

@ -36,7 +36,7 @@ namespace ogfx
setRootChild();
setStylesheetCategoryName("toolbar");
setTypeName("ogfx::gui::ToolBar");
auto& win = cast<Window&>(getWindow());
auto& win = getWindow();
w = win.getWindowWidth();
h = m_height;
disableBorder();
@ -69,7 +69,7 @@ namespace ogfx
void ToolBar::onWindowResized(const Event& event)
{
auto& win = cast<Window&>(getWindow());
auto& win = getWindow();
w = win.getWindowWidth();
h = m_height;
f32 offset_y = 0;
@ -82,7 +82,7 @@ namespace ogfx
void ToolBar::applyTheme(const ostd::Stylesheet& theme)
{
auto& win = cast<Window&>(getWindow());
auto& win = getWindow();
setHeight(getThemeValue<f32>(theme, "height", getHeight()));
setSize(win.getWindowWidth(), m_height);
enableBottomBorder(isBorderEnabled());

View file

@ -28,7 +28,7 @@ namespace ogfx
{
namespace gui
{
WidgetManager::WidgetManager(WindowCore& window, Widget& owner) : m_window(window), m_owner(owner)
WidgetManager::WidgetManager(Window& window, Widget& owner) : m_window(window), m_owner(owner)
{
//
}
@ -101,7 +101,7 @@ namespace ogfx
if (!w->contains(event.mouse->position_x, event.mouse->position_y, true))
continue;
event.mouse->mousePressedOnWidget = w;
cast<Window&>(m_window).getFocusManager().requestFocus(*w);
m_window.getFocusManager().requestFocus(*w);
w->__onMousePressed(event);
m_mousePressedOnWidget = w;
if (event.isHandled() || w->m_stopEvents)
@ -219,14 +219,14 @@ namespace ogfx
void WidgetManager::onKeyPressed(const Event& event)
{
auto focused = cast<Window&>(m_window).getFocusManager().getFocused();
auto focused = m_window.getFocusManager().getFocused();
if (!focused || !focused->isVisible()) return;
focused->__onKeyPressed(event);
}
void WidgetManager::onKeyReleased(const Event& event)
{
auto focus = cast<Window&>(m_window).getFocusManager();
auto focus = m_window.getFocusManager();
auto focused = focus.getFocused();
if (!focused || !focused->isVisible()) return;
focused->__onKeyReleased(event);
@ -234,7 +234,7 @@ namespace ogfx
void WidgetManager::onTextEntered(const Event& event)
{
auto focused = cast<Window&>(m_window).getFocusManager().getFocused();
auto focused = m_window.getFocusManager().getFocused();
if (!focused || !focused->isVisible()) return;
focused->__onTextEntered(event);
}

View file

@ -29,15 +29,15 @@ namespace ostd
namespace ogfx
{
class BasicRenderer2D;
class WindowCore;
namespace gui
{
class Event;
class Widget;
class Window;
class WidgetManager
{
public:
WidgetManager(WindowCore& window, Widget& owner);
WidgetManager(Window& window, Widget& owner);
bool hasWidget(Widget& widget);
bool addWidget(Widget& widget);
bool removeWidget(Widget& widget);
@ -59,14 +59,14 @@ namespace ogfx
void onWindowFocusLost(const Event& event);
inline i32 widgetCount(void) const { return m_widgetList.size(); }
inline WindowCore& getWindow(void) { return m_window; }
inline Window& getWindow(void) { return m_window; }
inline const stdvec<Widget*>& getWidgets(void) const { return m_widgetList; }
private:
void processDragAndDrop(Widget* widget, const Event& event);
private:
WindowCore& m_window;
Window& m_window;
Widget& m_owner;
stdvec<Widget*> m_widgetList;
Widget* m_mousePressedOnWidget { nullptr };

View file

@ -56,8 +56,8 @@ namespace ogfx
class Button : public Widget
{
public:
inline Button(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); }
inline Button(WindowCore& window, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); }
inline Button(Window& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); }
inline Button(Window& window, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); }
Button& create(const String& text);
void onDraw(ogfx::BasicRenderer2D& gfx) override;

View file

@ -30,8 +30,8 @@ namespace ogfx
class CheckBox : public Widget
{
public:
inline CheckBox(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); }
inline CheckBox(WindowCore& window, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); }
inline CheckBox(Window& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); }
inline CheckBox(Window& window, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); }
CheckBox& create(const String& text);
void applyTheme(const ostd::Stylesheet& theme) override;
void onDraw(ogfx::BasicRenderer2D& gfx) override;

View file

@ -115,7 +115,7 @@ namespace ogfx
setThemeQualifier("active", true);
m_dropDownShown = true;
Vec2 anchor = getGlobalPosition() + Vec2 { 0, geth() };
cast<Window&>(getWindow()).showContextMenu(m_menu, anchor);
getWindow().showContextMenu(m_menu, anchor);
}
}

View file

@ -30,7 +30,7 @@ namespace ogfx
class ComboBox : public Widget
{
public:
inline ComboBox(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
inline ComboBox(Window& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
ComboBox& create(void);
i32 addMenuItem(const String& text);
bool removeMenuItem(const String& text);

View file

@ -47,7 +47,7 @@ namespace ogfx
m_titlebarHeight = getThemeValue<f32>(theme, "titlebarHeight", 30);
m_titlebarBorderWidth = getThemeValue<i32>(theme, "titlebarBorderWidth", 1);
m_titlebarFontSize = getThemeValue<i32>(theme, "titlebarFontSize", 26);
m_titleTextAlign = getThemeValue<i32>(theme, "titlebarTextAlign", cast<i32>(WindowCore::eTextAlign::Left));
m_titleTextAlign = getThemeValue<i32>(theme, "titlebarTextAlign", cast<i32>(Window::eTextAlign::Left));
setTitlebarType(getThemeValue<String>(theme, "titlebarType", TitleBarTypes::None));
}
@ -137,7 +137,7 @@ namespace ogfx
{
gfx.outlinedRoundRect(titleBarBounds, m_titlebarColor, m_titlebarColor, { cast<f32>(getBorderRadius()), cast<f32>(getBorderRadius()), 0, 0 }, getBorderWidth());
gfx.drawLine({ getGlobalPosition() + Vec2 { 0, m_titlebarHeight - 2 }, getGlobalPosition() + Vec2 { getGlobalBounds().w, m_titlebarHeight - 2 } }, m_titlebarBorderColor, m_titlebarBorderWidth);
if (m_titleTextAlign == cast<i32>(WindowCore::eTextAlign::Center))
if (m_titleTextAlign == cast<i32>(Window::eTextAlign::Center))
gfx.drawCenteredString(m_title, titleBarBounds, m_titleColor, m_titlebarFontSize);
else
gfx.drawString(m_title, titleBarBounds.getPosition() + Vec2 { 10, 5 }, m_titleColor, m_titlebarFontSize);
@ -145,7 +145,7 @@ namespace ogfx
}
case TitleBarTypes::MinimalValue:
{
if (m_titleTextAlign == cast<i32>(WindowCore::eTextAlign::Center))
if (m_titleTextAlign == cast<i32>(Window::eTextAlign::Center))
gfx.drawCenteredString(m_title, titleBarBounds, m_titleColor, m_titlebarFontSize);
else
gfx.drawString(m_title, titleBarBounds.getPosition() + Vec2 { 10, 5 }, m_titleColor, m_titlebarFontSize);
@ -268,6 +268,8 @@ namespace ogfx
auto it = std::find_if(m_tabs.begin(), m_tabs.end(), [&](const std::unique_ptr<Panel>& p) { return p->getTitle() == title; });
if (it == m_tabs.end())
return false;
if (m_currentTab == it->get())
prepare_for_current_tab_removal();
m_tabs.erase(it);
return true;
}
@ -289,6 +291,7 @@ namespace ogfx
auto curr = m_tabs[index].get();
if (!ignore_same_tab && curr == m_currentTab && m_currentTab != nullptr)
return false;
getWindow().getFocusManager().clearFocus();
removeWidget(*m_currentTab);
m_currentTabIndex = index;
m_currentTab = curr;
@ -320,6 +323,7 @@ namespace ogfx
return;
if (m_tabs.size() < 2)
{
getWindow().getFocusManager().clearFocus();
m_currentTab = nullptr;
return;
}
@ -328,6 +332,8 @@ namespace ogfx
if (it == m_tabs.end())
return; // shouldn't happen but defensive
getWindow().getFocusManager().clearFocus();
if (it != m_tabs.begin())
m_currentTab = (it - 1)->get(); // tab to the left
else

View file

@ -41,7 +41,7 @@ namespace ogfx
inline static constexpr i32 MinimalValue = 2;
};
public:
inline Panel(WindowCore& window) : ScrollableWidget(window) { create(); }
inline Panel(Window& window) : ScrollableWidget(window) { create(); }
Panel& create(void);
void applyTheme(const ostd::Stylesheet& theme) override;
void afterDraw(ogfx::BasicRenderer2D& gfx) override;
@ -78,7 +78,7 @@ namespace ogfx
class TabPanel : public Widget
{
public:
inline TabPanel(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
inline TabPanel(Window& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
TabPanel& create(void);
void applyTheme(const ostd::Stylesheet& theme) override;
void onMousePressed(const Event& event) override;

View file

@ -41,8 +41,8 @@ namespace ogfx
class Label : public Widget
{
public:
inline Label(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); }
inline Label(WindowCore& window, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); }
inline Label(Window& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); }
inline Label(Window& window, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); }
Label& create(const String& text);
void onDraw(ogfx::BasicRenderer2D& gfx) override;
@ -94,8 +94,8 @@ namespace ogfx
class ImageLabel : public Widget
{
public:
inline ImageLabel(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); }
inline ImageLabel(WindowCore& window, const String& filePath) : Widget({ 0, 0, 0, 0 }, window) { create(filePath); }
inline ImageLabel(Window& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); }
inline ImageLabel(Window& window, const String& filePath) : Widget({ 0, 0, 0, 0 }, window) { create(filePath); }
ImageLabel& create(const String& filePath);
void applyTheme(const ostd::Stylesheet& theme) override;

View file

@ -30,7 +30,7 @@ namespace ogfx
class ProgressBar : public Widget
{
public:
inline ProgressBar(WindowCore& window, f32 min = 0.0f, f32 max = 1.0f, f32 start = 0.0f) : Widget({ 0, 0, 0, 0 }, window), m_progress(std::clamp(start, min, max)), m_min(min), m_max(max) { create(); }
inline ProgressBar(Window& window, f32 min = 0.0f, f32 max = 1.0f, f32 start = 0.0f) : Widget({ 0, 0, 0, 0 }, window), m_progress(std::clamp(start, min, max)), m_min(min), m_max(max) { create(); }
ProgressBar& create(void);
void applyTheme(const ostd::Stylesheet& theme) override;
void onDraw(ogfx::BasicRenderer2D& gfx) override;

View file

@ -41,7 +41,7 @@ namespace ogfx
OSTD_PARAM_GETSET(Color, OuterCircleColor, m_outerCircleColor);
private:
inline RadioButton(WindowCore& window, RadioButtonGroup& group, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(group, text); }
inline RadioButton(Window& window, RadioButtonGroup& group, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(group, text); }
RadioButton& create(RadioButtonGroup& group, const String& text);
void __update_size(ogfx::BasicRenderer2D& gfx);
void __set_selected(bool selected);

View file

@ -26,7 +26,7 @@ namespace ogfx
{
namespace gui
{
RootWidget::RootWidget(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window)
RootWidget::RootWidget(Window& window) : Widget({ 0, 0, 0, 0 }, window)
{
setRootChild();
disableFocus();
@ -37,7 +37,7 @@ namespace ogfx
void RootWidget::onWindowResized(const Event& event)
{
Window& win = cast<Window&>(getWindow()); //TODO: Potentially unsage?
Window& win = getWindow();
f32 offset_y = 0;
if (win.m_menubar.isVisible())
offset_y += win.m_menubar.geth();

View file

@ -29,7 +29,7 @@ namespace ogfx
class RootWidget : public Widget
{
public:
RootWidget(WindowCore& window);
RootWidget(Window& window);
void onWindowResized(const Event& event) override;
void applyTheme(const ostd::Stylesheet& theme) override;
void onDraw(ogfx::BasicRenderer2D& gfx) override;

View file

@ -30,7 +30,7 @@ namespace ogfx
class VerticalScrollBar : public Widget
{
public:
inline VerticalScrollBar(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
inline VerticalScrollBar(Window& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
VerticalScrollBar& create(void);
void applyTheme(const ostd::Stylesheet& theme) override;
void afterDraw(ogfx::BasicRenderer2D& gfx) override;
@ -68,7 +68,7 @@ namespace ogfx
class HorizontalScrollbar : public Widget
{
public:
inline HorizontalScrollbar(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
inline HorizontalScrollbar(Window& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
HorizontalScrollbar& create(void);
void applyTheme(const ostd::Stylesheet& theme) override;
void afterDraw(ogfx::BasicRenderer2D& gfx) override;
@ -106,7 +106,7 @@ namespace ogfx
class ScrollableWidget : public Widget
{
public:
inline ScrollableWidget(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
inline ScrollableWidget(Window& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
ScrollableWidget& create(void);
virtual void onUpdate(void) override;
void drawScrollbars(ogfx::BasicRenderer2D& gfx);

View file

@ -29,7 +29,7 @@ namespace ogfx
class Slider : public Widget
{
public:
inline Slider(WindowCore& window, bool vertical = false, f32 min = 0.0f, f32 max = 1.0f, f32 step = 0.1f) : Widget({ 0, 0, 0, 0 }, window) { create(vertical, min, max, step); }
inline Slider(Window& window, bool vertical = false, f32 min = 0.0f, f32 max = 1.0f, f32 step = 0.1f) : Widget({ 0, 0, 0, 0 }, window) { create(vertical, min, max, step); }
Slider& create(bool vertical, f32 min, f32 max, f32 step);
void applyTheme(const ostd::Stylesheet& theme) override;
void onMouseReleased(const Event& event) override;

View file

@ -86,7 +86,7 @@ namespace ogfx
public:
using ChevronDrawCallback = std::function<void(TreeView& sender, const Item& item, const Rectangle& bounds, BasicRenderer2D& gfx)>;
inline TreeView(WindowCore& window) : ScrollableWidget(window) { create(); }
inline TreeView(Window& window) : ScrollableWidget(window) { create(); }
TreeView& create(void);
void applyTheme(const ostd::Stylesheet& theme) override;
void onDraw(ogfx::BasicRenderer2D& gfx) override;

View file

@ -31,7 +31,7 @@ namespace ogfx
ostd::BaseObject* Widget::s_dragAndDropData { nullptr };
bool Widget::s_hasDragAndDropData { false };
Widget::Widget(const Rectangle& bounds, WindowCore& window) : Rectangle(bounds), m_widgets(window, *this)
Widget::Widget(const Rectangle& bounds, Window& window) : Rectangle(bounds), m_widgets(window, *this)
{
m_window = &window;
}
@ -39,8 +39,8 @@ namespace ogfx
Widget::~Widget(void)
{
if (m_window && m_tabIndex >= 0)
cast<Window&>(*m_window).getFocusManager().unregisterTabIndex(*this);
auto& fm = cast<Window&>(*m_window).getFocusManager();
m_window->getFocusManager().unregisterTabIndex(*this);
auto& fm = m_window->getFocusManager();
if (fm.getFocused() == this)
fm.clearFocus(); // you'd add this method
}
@ -240,7 +240,7 @@ namespace ogfx
bool Widget::setTabIndex(i32 index)
{
if (cast<Window&>(getWindow()).getFocusManager().registerTabIndex(*this, index))
if (getWindow().getFocusManager().registerTabIndex(*this, index))
{
m_tabIndex = index;
return true;

View file

@ -36,6 +36,7 @@ namespace ogfx
{
namespace gui
{
class Window;
class Widget : public ostd::BaseObject, public Rectangle
{
private: struct ThemeOverride
@ -65,7 +66,7 @@ namespace ogfx
public: using EventCallback = std::function<void(const Event&)>;
public:
// ================================== MAIN =================================
Widget(const Rectangle& bounds, WindowCore& window);
Widget(const Rectangle& bounds, Window& window);
Widget(Widget&&) = default;
Widget& operator=(Widget&&) = delete;
Widget(const Widget&) = delete;
@ -161,7 +162,7 @@ namespace ogfx
inline static void clearDragAndDropData(void) { s_dragAndDropData = nullptr; }
inline static ostd::BaseObject* getDragAndDropData(void) { return s_dragAndDropData; }
inline i32 getTabIndex(void) const { return m_tabIndex; }
inline WindowCore& getWindow(void) { return *m_window; }
inline Window& getWindow(void) { return *m_window; }
inline Widget* getParent(void) { return m_parent; }
inline const Widget* getParent(void) const { return m_parent; }
inline ogfx::MouseEventData::eButton getPressedMouseButton(void) const { return m_pressedButton; }
@ -235,7 +236,7 @@ namespace ogfx
private:
// ======= CORE =======
WindowCore* m_window { nullptr };
Window* m_window { nullptr };
Widget* m_parent { nullptr };
WidgetManager m_widgets;
std::unique_ptr<Layout> m_layout;

View file

@ -232,28 +232,64 @@ namespace ogfx
Vec2 BasicRenderer2D::getStringDimensions(const String& message, i32 fontSize, TTF_Font* font)
{
if (!isValid()) return { 0, 0 };
auto dimensions = getStringDimensionsPerCharacter(message, fontSize, font);
if (dimensions.empty())
return { 0, 0 };
f32 totalWidth = 0;
for (const auto& d : dimensions)
totalWidth += d.x;
return { totalWidth, dimensions[0].y };
}
stdvec<Vec2> BasicRenderer2D::getStringDimensionsPerCharacter(const String& message, i32 fontSize, TTF_Font* font)
{
if (!isValid()) return { };
if (fontSize <= 0) fontSize = m_fontSize;
if (!font) font = m_font;
auto l_buildCacheKey = [&](void) -> String {
return String("").add(message).add(fontSize).add(reinterpret_cast<uintptr_t>(font));
};
String cacheKey = l_buildCacheKey();
auto it = m_strDimsCache.find(cacheKey);
if (it != m_strDimsCache.end())
{
m_cacheHitCount++;
return it->second;
}
i32 oldFontSize = getFontSize();
setFontSize(fontSize);
auto glyphs = m_fontGlyphAtlas.processString(message, font, fontSize);
if (glyphs.empty()) return { 0, 0 };
if (glyphs.empty()) return { };
f32 totalWidth = 0;
stdvec<Vec2> dimensions;
dimensions.reserve(message.len());
f32 charWidth = 0;
for (size_t i = 0; i < glyphs.size(); i++)
{
totalWidth += glyphs[i]->advance;
charWidth += glyphs[i]->advance;
if (i > 0)
{
i32 kern = 0;
TTF_GetGlyphKerning(font, glyphs[i - 1]->codepoint, glyphs[i]->codepoint, &kern);
totalWidth += kern;
charWidth += kern;
}
dimensions.push_back({ charWidth, glyphs[0]->size.y });
charWidth = 0;
}
setFontSize(oldFontSize);
return { totalWidth, glyphs[0]->size.y };
if (m_strDimsCache.size() >= MaxStringDimsCacheSize)
m_strDimsCache.pop_back();
m_strDimsCache.insert(cacheKey, dimensions);
m_cacheMissCount++;
return dimensions;
}
// ===================================================== UTILS =====================================================

View file

@ -26,6 +26,7 @@
#include <ogfx/resources/Image.hpp>
#include <ostd/io/IOHandlers.hpp>
#include <ogfx/render/FontGlyphAtlas.hpp>
#include <ostd/io/StaticHashMap.hpp>
namespace ogfx
{
@ -70,8 +71,11 @@ namespace ogfx
i32 openFont(const ostd::UByte resource_data[], u32 data_size, i32 fontSize = 0);
i32 setFontSize(i32 fontSize);
Vec2 getStringDimensions(const String& message, i32 fontSize = 0, TTF_Font* font = nullptr);
stdvec<Vec2> getStringDimensionsPerCharacter(const String& message, i32 fontSize = 0, TTF_Font* font = nullptr);
inline u32 getDrawCallCount(void) { return m_lastFrameDrawCallCount; }
inline u32 getCacheHitCount(void) { return m_cacheHitCount; }
inline u32 getCacheMissCount(void) { return m_cacheMissCount; }
inline bool hasOpenFont(void) { return m_fontOpen; }
inline TTF_Font* getSDLFont(void) { return m_font; }
inline bool isValid(void) const { return m_initialized && m_fontOpen && (m_font != nullptr || m_fontFromMemory); }
@ -164,6 +168,11 @@ namespace ogfx
SDL_Texture* m_lastUsedGlyphAtlasTex { nullptr };
SignalHandler m_sigHandler { *this };
ostd::StaticHashMap<String, stdvec<Vec2>> m_strDimsCache;
i32 m_cacheHitCount { 0 };
i32 m_cacheMissCount { 0 };
inline static constexpr i32 DefaultFontSize { 16 };
inline static constexpr i32 MaxStringDimsCacheSize { 512 };
};
}

View file

@ -251,6 +251,17 @@ namespace ostd
m_entries.pop_back();
}
// Removes the first element
void pop_front(void)
{
if (m_entries.empty()) return;
m_index.erase(m_entries.front().first);
m_entries.pop_front();
// Rebuild all remaining indices (everything shifted by 1)
for (i32 i = 0; i < size(); i++)
m_index[m_entries[cast<u32>(i)].first] = i;
}
// ============================================================
// Removal
// ============================================================

View file

@ -24,7 +24,7 @@
#include <ogfx/ogfx.hpp>
#include <ostd/utils/Async.hpp>
ogfx::WindowCore::FileDialogFilterList filters = {
ogfx::gui::Window::FileDialogFilterList filters = {
{ "Image files", { "png", "jpg", "jpeg", "bmp" } },
{ "All files", { "*" } }
};
@ -279,6 +279,14 @@ class TestWindow : public Window
m_drawCallsLbl.addThemeOverride("@.label.padding", ostd::Rectangle { 10, 5, 0, 0 });
getStatusBar().addWidget(m_drawCallsLbl, { 0, 0 });
m_cacheHitsLbl.addThemeOverride("@.label.fontSize", 20);
m_cacheHitsLbl.addThemeOverride("@.label.padding", ostd::Rectangle { 10, 5, 0, 0 });
getStatusBar().addWidget(m_cacheHitsLbl, { 200, 0 });
m_cacheMissesLbl.addThemeOverride("@.label.fontSize", 20);
m_cacheMissesLbl.addThemeOverride("@.label.padding", ostd::Rectangle { 10, 5, 0, 0 });
getStatusBar().addWidget(m_cacheMissesLbl, { 400, 0 });
m_progressJob.start([this] {
while (true)
{
@ -352,6 +360,8 @@ class TestWindow : public Window
{
// gfx.fillRect(m_tabs.getGlobalPureContentBounds(), { 0, 255, 0, 100 });
m_drawCallsLbl.setText(String("DrawCalls: ").add(gfx.getDrawCallCount()));
m_cacheHitsLbl.setText(String("Cache Hits: ").add(gfx.getCacheHitCount()));
m_cacheMissesLbl.setText(String("Cache Miss: ").add(gfx.getCacheMissCount()));
}
void onFixedUpdate(void) override
@ -377,6 +387,8 @@ class TestWindow : public Window
Label m_slideLbl { *this };
TreeView m_list { *this };
Label m_drawCallsLbl { *this };
Label m_cacheHitsLbl { *this };
Label m_cacheMissesLbl { *this };
ComboBox m_combo { *this };
enum MenuId : i32 { New = 1, Open, Save, SaveAs, Exit, CopyRaw, CopyFormatted };
@ -501,7 +513,7 @@ i32 main(i32 argc, char** argv)
window.initialize(1200, 900, "OmniaFramework - Test Window");
window.setClearColor({ 0, 0, 0 });
window.setPosition({ 50, 50 });
// window.setWindowState(ogfx::WindowCore::eWindowState::Maximized);
// window.setWindowState(ogfx::gui::Window::eWindowState::Maximized);
window.mainLoop();
return 0;
}