Paint and render scene API
Declared by <huxerui/paint.h> and <huxerui/render_scene.h>.
Fills and image placement
Section titled “Fills and image placement”ImageFit:None,Contain,Cover,Fill, orScaleDown.GradientStop,LinearGradient, andRadialGradient.ImageVariant:ImageResource,ImageAsset, orVectorAsset.ImageFill: source, fit, alignment, sampling, tint, and opacity.Brush: immutable color, linear-gradient, or radial-gradient source paint.VisualFillcombines Brush and ImageFill, also accepting colors, gradients, ImageResource, ImageAsset, and VectorAsset directly.
Paint commands
Section titled “Paint commands”PaintCommand is a variant of:
DrawRectCommandcarrying a Brush, andDrawLineCommandcarrying stroke geometry.DrawTextCommand,TextRun,DrawTextRunsCommand.DrawImageCommand,DrawExternalTextureCommand.DrawCircleCommand,DrawArcCommand,DrawBorderCommand,DrawShadowCommand.FillPathCommand,StrokePathCommand,DrawPathShadowCommand.PushClipCommand,PopClipCommand,PushPathClipCommand.PushTransformCommand,PopTransformCommand.PlacePlatformViewCommand, whose queries expose identity, type, properties/revision, and bounds.
Each command is immutable platform-neutral data with equality. Command fields correspond to the matching PaintContext parameters.
PaintSequence and PaintContext
Section titled “PaintSequence and PaintContext”PaintSequence exposes Commands, conservative Bounds, Revision, and whether it contains external textures. PaintContext(sequence, bounds) records drawing through DrawRect, gradient, text/text-runs, image/image-rect, external texture, circle, arc, border, rect/path shadow, fill/stroke path, clip, and transform methods. Bounds() returns local recording bounds; Finish() validates balanced stacks and closes recording.
Render scene
Section titled “Render scene”RenderClip: rectangular or path clip command.RenderNode: stable ID, parent-local offset, presentation transform, group opacity, descendant clips, child transform, content/foreground sequences, child pointers, visibility, and revision.RenderScene: non-owning root pointer.DamageRegion: full flag or dirty rectangles.RenderFrame: scene, damage, and revision.FrameCommit: render frame, immutable semantic frame, and optional absolute next-frame deadline.
The scene/frame types are the platform renderer boundary. Their non-owning pointers remain valid only until the next runtime frame construction or destruction.
Complete Canvas example
Section titled “Complete Canvas example”#include <huxerui/huxerui.h>
using namespace huxerui;
View StatusCanvas() { return Canvas([](PaintContext& paint, Size size) { const Point center {size.width / 2.0F, size.height / 2.0F}; paint.DrawCircle(center, 36.0F, Color::Rgb(92, 61, 180)); paint.DrawArc(center, 28.0F, -1.57F, 4.2F, Color::Rgb(255, 255, 255), StrokeStyle{.width = 6.0F}); }).With(Frame {.width = 160.0F, .height = 160.0F});}The painter receives local size and emits platform-neutral commands. It does not own a platform canvas or world-coordinate transform.
Source paint versus geometry
Section titled “Source paint versus geometry”A Brush contains Color, LinearGradient, or RadialGradient. A VisualFill additionally permits image-backed surfaces; it is used by Background and component styles. Do not pass an ImageFill to a Brush-only path operation and assume the renderer will resolve a resource there. Resolve an image during composition when drawing it explicitly with PaintContext.
Gradient stops require at least two ordered offsets in [0, 1]; equal offsets intentionally create a hard transition. LinearGradient’s start/end and RadialGradient’s center/radius use normalized destination coordinates. Radial radii must be positive. Their transform changes sampling coordinates, not the geometry being painted. Use PushTransform when the shape itself must move or rotate.
ImageFill contains source, fit, horizontal_alignment, vertical_alignment, sampling, optional tint, and opacity in [0, 1]. Fit defaults to Fill. Vector tint and raster sampling have source-specific rules; see Image.
Drawing overloads and coordinate units
Section titled “Drawing overloads and coordinate units”| Operations | Inputs and important distinction |
|---|---|
DrawRect |
Rect, Brush, and optional CornerRadii. A Color/gradient converts to Brush. |
DrawText |
Rect, string or AttributedText, TextStyle, TextLayoutOptions, optional paragraph offset. |
DrawTextRun / DrawTextRuns |
Explicit run bounds and baseline origins; use when the caller already owns run positioning. |
DrawImage |
Whole ImageAsset, VectorAsset, or shared ExternalTexture into a destination rectangle. |
DrawImageRect |
A source subrectangle into a destination; source coordinates are intrinsic logical units, not encoded pixel coordinates. |
DrawCircle, DrawLine, DrawArc |
Color-based primitives; line/arc take StrokeStyle, arc angles are radians. |
DrawBorder / DrawShadow |
Rectangular border or shadow geometry; shadow offset, blur, and spread are separate values. |
FillPath / StrokePath |
Path plus Brush and fill rule or stroke style; optional explicit brush bounds decouple gradient mapping from path bounds. |
DrawPathShadow |
A path silhouette rather than a rectangular shadow. |
PushClip / PushPathClip |
Intersect the recording clip with a rounded rectangle or path. |
PushTransform |
Compose an affine transform for subsequent commands. |
Raster/texture image overloads accept ImageSampling and opacity; vector overloads accept optional tint and opacity. Drawing an image rectangle does not apply ImageFit automatically: the caller already chose source/destination geometry.
Recording lifecycle
Section titled “Recording lifecycle”Inside a Canvas callback, use the supplied context and balance every push with its corresponding pop. Runtime owns finishing that recording. When an extension/integration explicitly constructs PaintContext(sequence, bounds), it owns one recording and must call Finish once; Finish validates balanced stacks and closes the context. Its bounds do not implicitly clip drawing.
Do not retain a PaintContext beyond the callback, append to a finished one, or mutate resources referenced by immutable commands behind the renderer’s back. PaintSequence’s bounds are conservative damage information, not a per-pixel hit mask. For input, use the View’s geometry and semantics rather than interpreting a sequence as an interactive scene graph.
Platform-renderer boundary
Section titled “Platform-renderer boundary”RenderScene, RenderNode, RenderFrame, and FrameCommit are integration contracts, not values an application edits to move a component. Their borrowed pointers cannot be cached across Runtime frame construction. A renderer must handle every command variant, preserve clipping/transform balance, and respect group opacity and child ordering. Adding a PaintCommand therefore requires every renderer to implement it; ordinary application custom drawing should stay with Canvas, paths, and existing commands.

