Skip to content

ui::Renderer

Header: winui/render/Renderer.hpp.

The drawing surface every Element::render() draws through.

A control calls it from render_override(). The library implements it twice: one renderer draws the window on screen, and TestRenderer records each call as a RenderCommand for unit tests and describe(). All coordinates are DIPs in window space. Every push_* must be balanced by its pop_* within the same render() call.

Example:

class SwatchControl final : public ui::Element
{
    ui::Color   color_ = ui::colors::White;
    std::string label_ = "White";

    // ... measure_override() ...
    void render_override(ui::Renderer& r, const ui::RenderContext& context) const override
    {
        const ui::Theme& theme = context.theme;
        r.fill_rounded_rect(bounds(), theme.corner_radius, color_);
        r.stroke_rounded_rect(bounds(), theme.corner_radius, theme.colors().text, 1.0f);

        // Clip and transform calls come in pairs around what they apply to; the scopes
        // (ui::ClipScope, ...) pop at the end of the block.
        r.push_clip(bounds());
        r.draw_text(label_, bounds(), theme.colors().text, theme.type.body);
        r.pop_clip();
    }
};

~Renderer

virtual ~Renderer() = default

fill_rounded_rect

virtual void fill_rounded_rect(const Rect& bounds, float radius, const Color& color) = 0

Fills a rect with rounded corners (radius in DIPs, 0 for square) in a solid color.

stroke_rounded_rect

virtual void stroke_rounded_rect(const Rect& bounds, float radius, const Color& color, float stroke_width) = 0

Strokes a rounded rect's outline, the pen centered on bounds' edge.

draw_text

virtual void draw_text(std::string_view text, const Rect& bounds, const Color& color, const TextStyle& style) = 0

Draws UTF-8 text laid out in bounds per style (font, alignment, wrapping). Text overflowing bounds is not trimmed, and not clipped unless a clip is pushed.

fill_rounded_rect_gradient

virtual void fill_rounded_rect_gradient(const Rect& bounds, float radius, const LinearGradientBrush& brush) = 0

Fills a rounded rect with a gradient along the brush's axis. The XP and Vista themes draw their chrome with it.

stroke_rounded_rect_gradient

virtual void stroke_rounded_rect_gradient(const Rect& bounds, float radius, const LinearGradientBrush& brush, float extent_px, float stroke_width) = 0

Strokes a rounded rect with a gradient spanning extent_px device pixels, for Fluent's elevation border. StrokeRoundedRectGradient explains the sign of extent_px.

stroke_line

virtual void stroke_line(Point from, Point to, const Color& color, float stroke_width) = 0

A straight line; also one edge of a classic raised/sunken bevel (see draw_bevel_border(), which draws a whole border out of these).

stroke_wavy_line

virtual void stroke_wavy_line(Point from, Point to, const Color& color, float stroke_width, float amplitude, float wavelength) = 0

Draws the misspelling squiggle (see StrokeWavyLine).

fill_polygon

virtual void fill_polygon(const FillPolygon& polygon) = 0

Fills a closed polygon with one color (see FillPolygon).

stroke_polyline

virtual void stroke_polyline(const StrokePolyline& polyline) = 0

Strokes straight lines through a list of points (see StrokePolyline).

draw_geometry

virtual void draw_geometry(const DrawGeometry& geometry) = 0

Fills and strokes a PathGeometry (see DrawGeometry). A backend that cannot draw an AcrylicBrush draws its fallback color.

push_clip

virtual void push_clip(const Rect& bounds) = 0

Clips everything drawn until the matching pop_clip() to bounds, intersected with any enclosing clip.

pop_clip

virtual void pop_clip() = 0

Ends the innermost push_clip(), push_clip_ellipse() or push_clip_rounded_rect().

push_clip_ellipse

virtual void push_clip_ellipse(Point center, float radius_x, float radius_y) = 0

An elliptical clip, ended by the same pop_clip() as a rect clip (see PushClipEllipse).

push_clip_rounded_rect

virtual void push_clip_rounded_rect(const Rect& bounds, float radius) = 0

A clip to bounds with corners rounded by radius, ended by the same pop_clip() (see PushClipRoundedRect). A radius of 0 is the same clip as push_clip().

fill_ellipse

virtual void fill_ellipse(Point center, float radius_x, float radius_y, const Color& color) = 0

Fills an ellipse centered on center, radii in DIPs.

stroke_ellipse

virtual void stroke_ellipse(Point center, float radius_x, float radius_y, const Color& color, float stroke_width) = 0

Strokes an ellipse outline centered on center, radii in DIPs.

fill_rect_pattern

virtual void fill_rect_pattern(const Rect& bounds, Pattern pattern, const Color& fg, const Color& bg) = 0

Fills bounds with a two-color stipple (see Pattern).

draw_image_nine_slice

virtual void draw_image_nine_slice(const std::string& image_name, const Rect& bounds, const Thickness& slice_margins)

Optional image-theme chrome (see ImageThemePack). A no-op wherever image_name isn't found in whatever pack the backend was configured with; ImageThemePack::empty() is the common case, and every backend must tolerate it. The default draws nothing, which is what a backend with no pack does.

draw_image

virtual void draw_image(const Bitmap& image, const Rect& bounds, Stretch stretch) = 0

A caller-supplied bitmap, stretched into bounds per stretch (see DrawImage). image need only be valid for the duration of the call.

draw_image_rect

virtual void draw_image_rect(const Bitmap& image, const Rect& source, const Rect& bounds) = 0

Draws the source part of image into bounds (see DrawImageRect). source is in the image's pixels and is clipped to them.

draw_svg

virtual void draw_svg(const SvgImage& svg, const Rect& bounds) = 0

Draws svg into bounds (see DrawSvg). A backend that cannot draw SVG draws nothing.

push_opacity_layer

virtual void push_opacity_layer(float opacity) = 0

Draws everything until the matching pop_opacity_layer() as one layer at opacity (0..1); see PushOpacityLayer.

pop_opacity_layer

virtual void pop_opacity_layer() = 0

Ends the innermost push_opacity_layer().

push_matrix

virtual void push_matrix(const Matrix& transform) = 0

Transforms everything drawn until the matching pop_transform(); nested pushes compose, the inner one applying first (see PushTransform). What every push_transform() overload lands in: a backend implements this one, and callers use push_transform().

push_transform

void push_transform(const Matrix& transform)

Transforms everything drawn until the matching pop_transform() by transform; see push_matrix().

push_transform

void push_transform(float scale_x, float scale_y, Point offset)

Scale by scale_x/scale_y about the origin, then translate by offset.

push_transform

void push_transform(float scale, Point offset)

Uniform scale by scale, then translate by offset.

pop_transform

virtual void pop_transform() = 0

Ends the innermost push_transform().

set_rasterization

virtual void set_rasterization(const SetRasterization& policy) = 0

Sets the theme's rasterization policy (see SetRasterization). Window::render() calls it once per frame, first, from the active Theme. A backend that ignores it draws everything antialiased, which matches the Modern look.

device_scale

virtual float device_scale() const

Device pixels per DIP on the target, the DPI over 96: 1 unless the backend knows better. Everything else stays in DIPs; this is for the few classic marks that are drawn pixel by pixel, like the radio well (draw_classic_radio()) and the solid arrows (draw_classic_arrow()), which pick a mask per device size instead of scaling a 100 % one.