From fe9fc4d69ccf2a0387d831384698e3fb88dac537 Mon Sep 17 00:00:00 2001 From: Simon Hardt Date: Sun, 6 Mar 2022 20:15:57 +0100 Subject: [PATCH] add: Font registry --- frame/CMakeLists.txt | 3 ++ frame/src/font/Font.cpp | 17 +++++++++ frame/src/font/Font.hpp | 4 +++ frame/src/font/FontRegistry.cpp | 57 ++++++++++++++++++++++++++++++ frame/src/font/FontRegistry.hpp | 26 ++++++++++++++ frame/src/main.cpp | 4 ++- frame/src/render/RenderTarget.cpp | 18 ++++++++-- frame/src/render/RenderTarget.hpp | 9 +++++ frame/src/widgets/clock/Analog.cpp | 38 +++++++++++++++++--- 9 files changed, 169 insertions(+), 7 deletions(-) create mode 100644 frame/src/font/FontRegistry.cpp create mode 100644 frame/src/font/FontRegistry.hpp diff --git a/frame/CMakeLists.txt b/frame/CMakeLists.txt index a9eb341..9fbaefe 100644 --- a/frame/CMakeLists.txt +++ b/frame/CMakeLists.txt @@ -33,6 +33,9 @@ set(src src/font/Font.cpp src/font/Glyph.hpp src/font/Glyph.cpp + src/font/FontRegistry.hpp + src/font/FontRegistry.cpp + src/widgets/Widget.hpp src/widgets/Widget.cpp diff --git a/frame/src/font/Font.cpp b/frame/src/font/Font.cpp index 9f32d57..e276c31 100644 --- a/frame/src/font/Font.cpp +++ b/frame/src/font/Font.cpp @@ -65,6 +65,23 @@ namespace frame::font return y_offset; } + uint32_t Font::getOptimalSize(std::string_view text, Rect rect) const + { + auto best_size = 0; + + for(auto const& [size, value] : sizes) + { + auto width = getLength(text, size); + auto height = getHeight(text, size); + + if(rect.width < width || rect.height < height) + break; + else + best_size = size; + } + return best_size; + } + void Font::LoadFromStream(std::istream& os) { json file_data = json::parse(os); diff --git a/frame/src/font/Font.hpp b/frame/src/font/Font.hpp index ca1fe80..3ef8ef6 100644 --- a/frame/src/font/Font.hpp +++ b/frame/src/font/Font.hpp @@ -1,11 +1,13 @@ #pragma once +#include "../Rect.hpp" #include "Glyph.hpp" #include #include #include + namespace frame::font { using Glyphs = std::map; @@ -27,6 +29,8 @@ namespace frame::font uint32_t getHeight(std::string_view text, uint32_t size) const; int32_t getMaxYOffset(std::string_view text, uint32_t size) const; + uint32_t getOptimalSize(std::string_view text, Rect rect) const; + uint32_t getLineSpacing(uint32_t size) const { return lineSpacing.at(size); diff --git a/frame/src/font/FontRegistry.cpp b/frame/src/font/FontRegistry.cpp new file mode 100644 index 0000000..5023af3 --- /dev/null +++ b/frame/src/font/FontRegistry.cpp @@ -0,0 +1,57 @@ +#include "FontRegistry.hpp" + +#include + +namespace frame::font +{ + std::shared_ptr GetFont(std::string_view name) + { + return Service::get()->Get(name); + } + + bool LoadFont(std::string_view name) + { + return Service::get()->Load(name); + } + + FontRegistry::FontRegistry() + : IService("FontRegistry") + { + } + + bool FontRegistry::Load(std::string_view name) + { + if(fonts.find(std::string{name}) != fonts.end()) + { + fmt::print("Font {} allready loaded!\n", name); + return true; + } else + { + fmt::print("Loading font \"{}\": ", name); + auto ptr = Font::LoadFromFile(fmt::format("{}.json", name)); + + if(ptr == nullptr) + { + fmt::print("Error not found!\n"); + } else + { + fonts[std::string{name}] = ptr; + fmt::print("OK\n"); + return true; + } + } + return false; + } + + std::shared_ptr FontRegistry::Get(std::string_view name) + { + auto it = fonts.find({std::string{name}}); + if(it == fonts.end()) + { + if(!Load(name)) + return nullptr; + it = fonts.find({std::string{name}}); + } + return it->second; + } +} // namespace frame::font \ No newline at end of file diff --git a/frame/src/font/FontRegistry.hpp b/frame/src/font/FontRegistry.hpp new file mode 100644 index 0000000..913867d --- /dev/null +++ b/frame/src/font/FontRegistry.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "../ServiceLocator.hpp" +#include "Font.hpp" + +#include +#include + +namespace frame::font +{ + + std::shared_ptr GetFont(std::string_view name); + bool LoadFont(std::string_view name); + + class FontRegistry : public IService + { + std::unordered_map> fonts; + + public: + FontRegistry(); + + bool Load(std::string_view name); + std::shared_ptr Get(std::string_view name); + }; + +} // namespace frame::font diff --git a/frame/src/main.cpp b/frame/src/main.cpp index affe3e4..e11dfc6 100644 --- a/frame/src/main.cpp +++ b/frame/src/main.cpp @@ -8,7 +8,7 @@ using namespace std::chrono_literals; #include "ScreenManager.hpp" #include "display/Display.hpp" -#include "font/Font.hpp" +#include "font/FontRegistry.hpp" //#include "render/RenderTarget.hpp" //#include "widgets/clock/Analog.hpp" #include "widgets/WidgetRegistry.hpp" @@ -24,6 +24,8 @@ int main() display->Init(); + frame::font::LoadFont("Fira Code"); + frame::ScreenManager screen(std::move(display)); auto const& widgets = frame::Service::get(); diff --git a/frame/src/render/RenderTarget.cpp b/frame/src/render/RenderTarget.cpp index d4406eb..fe1bba4 100644 --- a/frame/src/render/RenderTarget.cpp +++ b/frame/src/render/RenderTarget.cpp @@ -20,7 +20,12 @@ namespace frame::render || (position.x + current.left) >= root_size.width || (position.y + current.top) >= root_size.height) return; - image.at(position.x + current.left, position.y + current.top) = color; + if(!invert) + image.at(position.x + current.left, position.y + current.top) = + color; + else + image.at(position.x + current.left, position.y + current.top) ^= + color; } void RenderTarget::DrawLine(Vector const& start, @@ -154,6 +159,15 @@ namespace frame::render {BottomRight.x, BottomRight.y - lw}); } + void + RenderTarget::DrawRect(Rect const& rect, uint8_t LineWidth, Color color) + { + DrawRect(Vector{rect.left, rect.top}, + Vector{rect.left + rect.width, rect.top + rect.height}, + LineWidth, + color); + } + void RenderTarget::DrawImage(Vector topLeft, Image const& image) { auto pos = topLeft; @@ -204,7 +218,7 @@ namespace frame::render auto const lineSpacing = pFont.getLineSpacing(size); auto const lineSpacing_3 = lineSpacing / 3; - Vector start{rect.top, rect.left}; + Vector start{rect.left, rect.top}; auto text_height = pFont.getHeight(pText, size); auto length = pFont.getLength(pText, size); auto y_offset = pFont.getMaxYOffset(pText, size); diff --git a/frame/src/render/RenderTarget.hpp b/frame/src/render/RenderTarget.hpp index 40a8112..6505544 100644 --- a/frame/src/render/RenderTarget.hpp +++ b/frame/src/render/RenderTarget.hpp @@ -24,6 +24,8 @@ namespace frame::render Rect root_size; std::stack Scissor; + bool invert = false; + public: RenderTarget(Size size); @@ -47,6 +49,8 @@ namespace frame::render uint8_t LineWidth, Color color = BLACK); + void DrawRect(Rect const& rect, uint8_t LineWidth, Color color = BLACK); + void DrawImage(Vector topLeft, Image const& image); Vector DrawGlyph(Vector centerLine, @@ -81,6 +85,11 @@ namespace frame::render void pushViewport(Rect rect); void popViewport(); + void setInvert(bool pInvert) + { + invert = pInvert; + } + private: void DrawPointsMirrorCircle(Vector const& center, Vector const& pos, diff --git a/frame/src/widgets/clock/Analog.cpp b/frame/src/widgets/clock/Analog.cpp index 62119cb..6462245 100644 --- a/frame/src/widgets/clock/Analog.cpp +++ b/frame/src/widgets/clock/Analog.cpp @@ -1,15 +1,14 @@ #include "Analog.hpp" +#include "../../font/FontRegistry.hpp" + #include +#include #include constexpr double pi = 3.14159; #include "../WidgetRegistry.hpp" -/* -static bool registerd = - frame::Service::get() - ->Register("AnalogClock");*/ REGISTER_WIDGET(frame::widgets::AnalogClock, "AnalogClock"); @@ -97,6 +96,37 @@ namespace frame::widgets center.y + int32_t(std::sin(hour_rad) * radius * 0.6)}); setClear(); + + // Text + + auto font = font::GetFont("Fira Code"); + + if(!font) + return; + + auto text = fmt::format("{:%d.%m.%Y}", fmt::localtime(t)); + + auto text_center = center; + text_center.y += radius / 2; + + auto const text_height_h = radius / 4; + auto const text_width_h = radius / 2; + + Rect text_box{text_center.y - text_height_h, + text_center.x - text_width_h, + text_width_h * 2, + text_height_h * 2}; + + auto font_size = font->getOptimalSize(text, text_box); + + rt.setInvert(true); + rt.DrawText(text_box, + text, + *font, + font_size, + AlignHorizontal::CENTER, + AlignVertical::CENTER); + rt.setInvert(false); } } // namespace frame::widgets \ No newline at end of file