#include #include #include #include using namespace bwidgets; CaptionImpl::CaptionImpl(Widget* parent) noexcept : WidgetImpl {parent} { _font_color_bg = default_font_color_bg; _font_color_fg = default_font_color_fg; } void CaptionImpl::render_mode(const Font::RenderMode m) { if (m != _render_mode) { _text_texture.reset(); _render_mode = m; } } auto CaptionImpl::size() const noexcept -> Size { if (!_font) return {0, 0}; const auto [w, h] = _font->text_size(_text); return {w + 2 * margins.w, h + 2 * margins.h}; } auto CaptionImpl::text() const noexcept -> std::string_view { return _text; } void CaptionImpl::text(std::string t) { if (t != _text) { _text_texture.reset(); _text = std::move(t); } } void CaptionImpl::_handle_font_change(const std::shared_ptr&) { _text_texture.reset(); } void CaptionImpl::_handle_font_color_change(const Color fg, const Color bg) { if (fg != _font_color_fg) { _text_texture.reset(); _font_color_fg = fg; } if (bg != _font_color_bg && _font_render_mode == Font::RenderMode::SHADED) { _text_texture.reset(); _font_color_bg = fg; } } void CaptionImpl::_handle_geometry_change(const SDL_Rect& vp) { if (vp.w != _viewport.w) { _widget_area = rect_margin({0, 0, vp.w, vp.h}, margins); } else if (vp.h != _viewport.h) { _widget_area = rect_margin({0, 0, vp.w, vp.h}, margins); _text_texture.reset(); } } void CaptionImpl::_handle_renderer_change(const std::shared_ptr&) { _text_texture.reset(); } void CaptionImpl::_handle_rendering() { if (!_text_texture) _handle_texture_update(); // fill caption viewport with background color when using // shaded text rendering mode. if (_render_mode == Font::RenderMode::SHADED) { _renderer->draw_color(_font_color_bg) ->fill_rect({0, 0, _viewport.w, _viewport.h}); } const Size size_dst { (int)((float)_text_texture->attributes().w / (float)_text_texture->attributes().h * (float)_widget_area.h), _widget_area.h}; const auto texture_dst = [size_dst, this]() -> SDL_Rect { switch (alignment) { case Alignment::CENTER: return {center_line(_widget_area.w, size_dst.w) + _widget_area.x, margins.h, size_dst.w, size_dst.h}; case Alignment::LEFT: return {margins.w, margins.h, size_dst.w, size_dst.h}; case Alignment::RIGHT: return {_widget_area.w - size_dst.w - margins.w + _widget_area.x, margins.h, size_dst.w, size_dst.h}; default: throw std::logic_error("missing switch case."); } }(); _renderer->copy(*_text_texture, nullptr, texture_dst); } void CaptionImpl::_handle_texture_update() { if (!_font) return; _text_texture.reset(); auto s = [this]() { switch (_render_mode) { case Font::RenderMode::SHADED: return _font->render(_render_mode, _text, _font_color_fg, _font_color_bg); default: return _font->render(_render_mode, _text, _font_color_fg); } }(); _text_texture = std::make_shared(*_renderer, s.get()); }