Skip to content

ui::TextMeasurer

Header: winui/render/Text.hpp.

Measures text. The on-screen implementation measures with the real fonts, and the headless one (HeadlessTextMeasurer) uses a deterministic approximation. Because measurement sits behind this interface, layout runs without a window: Element::measure() takes a measurer and passes it down the tree.

Call it through MeasureContext::measurer. The library implements it.

Parallel layout (ParallelLayout) calls one measurer from several threads at once, so an implementation keeps no unsynchronized state: both shipped ones keep none at all.

Example:

// An element is handed the measurer when it is measured, and never keeps it:
class Caption : public ui::Element
{
protected:
    ui::Size measure_override(ui::Size available, const ui::MeasureContext& context) const override
    {
        const ui::TextStyle style{.font_size = 14.0f, .wrapping = ui::TextWrapping::Wrap};
        // Wrapped to a bounded width; an unbounded one (ui::Unbounded) keeps it on one line.
        return context.measurer.measure_wrapped(text_, style, available.width);
    }

private:
    std::string text_;
};

~TextMeasurer

virtual ~TextMeasurer() = default

measure

virtual TextMetrics measure(std::string_view text, const TextStyle& style) const = 0

One line, whatever style.wrapping says: the natural, unbroken extent of the run, in DIPs. text is UTF-8.

measure_wrapped

virtual TextMetrics measure_wrapped(std::string_view text, const TextStyle& style, float) const

The run broken into lines no wider than max_width per style.wrapping: the widest line's width and the height of all lines together. A width of 0 or less, an infinite one (ui::Unbounded), or a NoWrap style, is measure(). The default ignores wrapping altogether; both shipped measurers override it.