#include namespace psemek::ui { void label::set_text(std::string text) { text_ = std::move(text); on_state_changed(); } void label::set_halign(halignment value) { halign_ = value; on_state_changed(); } void label::set_valign(valignment value) { valign_ = value; on_state_changed(); } void label::set_multiline(multiline_mode value) { multiline_ = value; on_state_changed(); } void label::set_overflow(overflow_mode value) { overflow_ = value; on_state_changed(); } void label::reshape(geom::box const & bbox) { shape_.box = bbox; cached_state_.reset(); } geom::box label::size_constraints() const { if (!cached_state_) update_cached_state(); static float const inf = std::numeric_limits::infinity(); return {{{cached_state_->size[0], inf}, {cached_state_->size[1], inf}}}; } void label::draw(painter & p) const { if (!cached_state_) update_cached_state(); if (!cached_state_->font) return; auto st = style(); if (!st) return; for (auto & g : cached_state_->glyphs) p.draw_glyph(*(cached_state_->font), g.character, g.position, st->text_color); } void label::on_state_changed() { cached_state_.reset(); post_reshape(); } void label::update_cached_state() const { cached_state_ = cached_state{}; if (text_.empty()) return; auto st = style(); if (!st) return; if (!st->font) return; cached_state_->font = st->font.get(); shape_options opts; opts.scale = st->text_scale; cached_state_->glyphs = st->font->shape(text_, opts); geom::box bbox; for (auto const & g : cached_state_->glyphs) bbox |= g.position; geom::vector offset; offset[0] = shape_.box[0].center() - bbox[0].length() / 2.f; offset[1] = shape_.box[1].center() - st->text_scale * st->font->size()[1] / 2.f; for (auto & g : cached_state_->glyphs) g.position += offset; cached_state_->size = bbox.dimensions(); } }