#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; int lines = 1; geom::vector offset; switch (halign_) { case halignment::left: offset[0] = shape_.box[0].min; break; case halignment::center: offset[0] = shape_.box[0].center() - bbox[0].length() / 2.f; break; case halignment::right: offset[0] = shape_.box[0].max - bbox[0].length(); break; } switch (valign_) { case valignment::top: offset[1] = shape_.box[1].min; break; case valignment::center: offset[1] = shape_.box[1].center() - lines * st->text_scale * st->font->size()[1] / 2.f; break; case valignment::bottom: offset[1] = shape_.box[1].max - lines * st->text_scale * st->font->size()[1]; break; } for (auto & g : cached_state_->glyphs) g.position += offset; cached_state_->size = bbox.dimensions(); } }