#include #include #include namespace psemek::ui::impl { label_base::label_base() : font_(react::value(nullptr)) , glyphs_(react::value>(std::vector{})) , size_(react::map([](std::vector const & glyphs, fonts::font * font){ if (!font) return geom::vector{0.f, 0.f}; geom::box bbox; for (auto const & glyph : glyphs) bbox |= glyph.position; return geom::vector{bbox[0].length(), font->size()[1]}; }, react::join(glyphs_), react::join(font_))) , size_constraints_(react::map([](geom::vector const & size){ geom::box result; result[0].min = size[0]; result[0].max = size_constraints::infinity; result[1].min = size[1]; result[1].max = size_constraints::infinity; return impl::size_constraints{result}; }, size_)) {} react::value label_base::size_constraints() const { return size_constraints_; } void label_base::draw(renderer & renderer) { if (!glyphs_ || !*glyphs_) return; auto const size = *size_; auto const shape = this->shape(); geom::vector origin; origin[0] = std::round(geom::lerp(shape[0].min, shape[0].max - size[0], lerp_factor(*halign_))); origin[1] = std::round(geom::lerp(shape[1].min, shape[1].max - size[1], lerp_factor(*valign_))); origin[1] += std::round((size[1] + (**font_)->xheight()) / 2.f); for (auto const & glyph : **glyphs_) renderer.draw_glyph(*glyph.texture, glyph.position + origin, glyph.texcoords, *color_); } void label_base::update(label const & value) { font_.set(value.font); glyphs_.set(react::map([](std::string const & str, fonts::font * font) -> std::vector { if (!font) return {}; return font->shape(str, {}); }, value.text, value.font)); color_ = value.color; halign_ = value.halign; valign_ = value.valign; } }