LavaUI docs GitHub

class DrawList

Swift

final class DrawList

Reused arena: draw commands plus the shaped glyphs they reference. Shaping itself is cached per line on UIFont, so re-emission is cheap.

Sources/LavaUI/DrawList.swift:156

Constructors

convenience init(editor: Editor, window: WindowID = .main)

Creates a list that writes into window's draw arena.

Sources/LavaUI/DrawList.swift:273

Properties

var commandCount: Int { get }

Public so a harness outside LavaUI (LavaBench) can assert on the shape of a frame — command/glyph counts are exact where timings are noisy. See PerfCounters.

Sources/LavaUI/DrawList.swift:172

var displayScale: Float { get }

The output scale this list's window is drawn at — see DisplayScale. Set by the window from its Scale events; 1 for a list that goes anywhere else (a drag chip).

Sources/LavaUI/DrawList.swift:166

var glyphCount: Int { get }

How many shaped glyphs this frame has emitted so far.

Sources/LavaUI/DrawList.swift:180

var gradientCount: Int { get }

How many gradients this frame has emitted so far.

Sources/LavaUI/DrawList.swift:195

var meshVertexCount: Int { get }

How many mesh vertices this frame has emitted so far.

Sources/LavaUI/DrawList.swift:187

var spatialVertexCount: Int { get }

How many 3D (Scene3D) vertices this frame has emitted so far.

Sources/LavaUI/DrawList.swift:191

Methods

func animateNode(opacity: Float? = nil, translateX: Float? = nil, translateY: Float? = nil, timeConstant: Float = 0, duration: Float? = nil)

States where the enclosing node should end up. The renderer takes it there — at the display rate, without this process being scheduled again, and without stopping if this process gets busy.

A property left nil is not stated, and keeps whatever target it had. The first frame a node states one it snaps rather than eases: a node that has just appeared has nothing to have moved from. To animate an entrance, state the start on one frame and the end on the next. Pass duration instead of timeConstant when several nodes have to arrive together: a decay from a longer distance takes visibly longer to settle, so a group easing with one time constant lands raggedly, while a group sharing a duration lands on one frame.

Sources/LavaUI/DrawList.swift:932

func beginBackdropBlur(x: Float, y: Float, w: Float, h: Float, radius: Float, cornerRadius: Float = 0, adaptation: Float = 1)

Barrier: engine flushes UI drawn so far, blurs under this rect, composites. The colour's RGB is unused by the engine (tint the glass with a following fill); its alpha carries adaptation.

cornerRadius is the radius of the surface that will be drawn over the frost. The composite is the one piece of a rounded glass panel the panel's own fill cannot hide — it is underneath it — so a square one shows as four bright tabs around the shape.

adaptation (0…1) is how far a bright backdrop is pulled down toward light grey, per pixel, so glass over a white page still separates from it. It travels as the command colour's alpha.

Sources/LavaUI/DrawList.swift:1041

func beginContentBlur(x: Float, y: Float, w: Float, h: Float, radius: Float)

Barrier: engine draws everything until endContentBlur into an offscreen target, blurs it, and composites it back over this rect.

Sources/LavaUI/DrawList.swift:1118

func beginNode(_ node: NodeID, x: Float, y: Float, w: Float, h: Float, flags: SceneNodeFlags = [])

Opens a node for a view, taking its scene id from its NodeID.

The overload views should use: reconciliation already keeps NodeID stable across frames, and SceneNodeIdentity is what makes the number the renderer sees stable and safe to hand on when the node is gone.

Sources/LavaUI/DrawList.swift:847

func beginNode(id: UInt32, x: Float, y: Float, w: Float, h: Float, flags: SceneNodeFlags = [])

Opens a scene node — a subtree the renderer can move on its own.

id is yours to assign and must be stable across frames: it is what the renderer keys its retained state on, so an id that changes between frames scrolls back to the top on every one. Close it with endNode.

Not routed through append, unlike every primitive: color here is a flags bitfield, and append exists to put a colour through the opacity multiplier. Fading a node would turn scrollY into clip.

Sources/LavaUI/DrawList.swift:866

func circle(cx: Float, cy: Float, radius: Float, color: Color)

Fills a circle centred on cx,cy.

Sources/LavaUI/DrawList.swift:716

func clear()

Starts a frame: resets the counts and claims storage for it.

Claiming here rather than once at init is what a shared arena needs — it is triple buffered, so the slot a frame is written into is chosen per frame and the pointers move with it. The in-process sink hands back the same buffers every time, so nothing changes for a windowed app.

Sources/LavaUI/DrawList.swift:310

func emitTree(_ root: any AnyViewNode, originX: Float = 0, originY: Float = 0, viewportW: Float, viewportH: Float)

Emit chrome from a laid-out retained tree. originX/Y shift the tree (e.g. below ImGui menu). Viewport seeds the cull stack; ScrollView further intersects so long lists skip off-screen subtrees entirely (not only leaves).

Sources/LavaUI/DrawList.swift:1284

func endBackdropBlur()

Closes the scope a beginBackdropBlur opened.

Sources/LavaUI/DrawList.swift:1109

func endContentBlur()

Ends the content blur scope beginContentBlur opened: everything drawn since is blurred and composited back.

Sources/LavaUI/DrawList.swift:1130

func endNode(contentW: Float, contentH: Float, emittedTop: Float = 0, emittedBottom: Float = 0, hoverTint: Color? = nil, pressTint: Color? = nil, cornerRadius: Float = 0)

Closes the innermost node. contentW/contentH are how big its children turned out to be, which is what bounds a scroll.

emittedTop/emittedBottom are the vertical span actually drawn, for a virtualized node that declares more content than it emits. Left at zero they mean "all of it", which is the truth for anything that draws its whole content. hoverTint/pressTint are drawn over the node while the pointer is inside it, and while it is additionally being pressed. The renderer applies them without asking, which is the point: hover is the most frequent state change in an interface and recomputing it here would cost a round trip per mouse move to reach an answer the renderer already had.

Sources/LavaUI/DrawList.swift:894

@discardableResult func frostDesktop(x: Float, y: Float, w: Float, h: Float, radius: Float, cornerRadius: Float = 0) -> Bool

Frost the desktop under this rect, when a compositor is there to do it. Returns false when there is not (a windowed app), and the caller falls back to beginBackdropBlur.

For glass that is not an overlay: a dock's shelf, a panel's strip. On those surfaces the framebuffer behind the shape is empty, and in-window backdrop blur would only smear that. x,y,w,h are window space.

Sources/LavaUI/DrawList.swift:1073

func image(textureId: UInt32, x: Float, y: Float, w: Float, h: Float, tint: Color = Color(r: 1, g: 1, b: 1))

Textured quad. param = engine texture id; color = RGBA tint.

Sources/LavaUI/DrawList.swift:997

func image(_ image: UIImage, x: Float, y: Float, w: Float, h: Float, tint: Color = Color(r: 1, g: 1, b: 1))

Textured quad from a UIImage, including compositor surface posters.

Sources/LavaUI/DrawList.swift:1010

func line(x1: Float, y1: Float, x2: Float, y2: Float, color: Color, width: Float = 1.5)

Stroke from (x1,y1) to (x2,y2). width is in pixels (capsule).

Sources/LavaUI/DrawList.swift:721

func linearGradientRect(x: Float, y: Float, w: Float, h: Float, from: Color, to: Color, angle: Float = .pi / 2, radius: Float = 0)

A rect filled with a two-stop linear ramp.

angle is in radians from +x towards +y, so 0 runs left to right and .pi / 2 runs top to bottom. The ramp spans the rect exactly whatever the angle and whatever the aspect ratio, and both stops carry their own alpha — a fade to transparent is to: with alpha 0, not a separate mechanism.

Falls back to a flat from fill if the frame has no room left for another gradient, which is the same shape as every other truncation here: draw less than was asked for rather than nothing.

Sources/LavaUI/DrawList.swift:666

func opaqueBounds(x: Float, y: Float, w: Float, h: Float)

Promises that x,y,w,h of this frame is fully opaque, so a compositor showing it can skip blending there — and skip drawing whatever is behind it entirely.

Only worth saying for a compositor surface; a windowed app is pasted onto a swapchain and nobody asks. Emit before the tree, at the top level: the renderer ignores a claim made inside a scene node or a faded subtree, because those are about pixels the frame may not own.

Claiming too little costs a blend. Claiming too much punches a hole through to the desktop, so anything uncertain — a translucent wash, a backdrop blur, a rounded corner the client drew itself — is a reason not to call this. The window's own rounding needs no allowance; the renderer insets for that, since it is the one that cuts the corners.

Sources/LavaUI/DrawList.swift:619

func pieSlice(cx: Float, cy: Float, innerRadius: Float, outerRadius: Float, startAngle: Float, endAngle: Float, color: Color, segments: Int? = nil)

Filled pie or donut wedge. innerRadius <= 0 draws a solid slice (fanned from the centre); innerRadius > 0 draws a ring segment. segments defaults to a density that keeps the arc looking smooth without over-tessellating short spans.

Sources/LavaUI/DrawList.swift:780

func polygon(_ points: [(x: Float, y: Float)], color: Color)

Fills a custom region fanned from its first point. Correct for any convex polygon, or any shape star-shaped from points[0] (able to see its whole boundary from there) — a wedge fanned from its centre, for instance. Concave shapes that are not star-shaped from the first point will self-intersect; that triangulation isn't supported.

Sources/LavaUI/DrawList.swift:755

func polyline(_ points: [(x: Float, y: Float)], color: Color)

Draws connected points with one non-indexed LINE_STRIP GPU draw.

This is intentionally 1px: portable Vulkan does not guarantee wide native lines. A future thick-polyline API should expand joins/caps into triangles rather than depend on the optional wideLines device feature.

Sources/LavaUI/DrawList.swift:732

func popClip()

Ends the innermost pushClip.

Sources/LavaUI/DrawList.swift:992

@discardableResult func publish() -> Bool

Hands the frame to its sink. Returns whether anything was published — false when no storage was claimed, which is a frame skipped rather than a failure.

Sources/LavaUI/DrawList.swift:349

func pushClip(x: Float, y: Float, w: Float, h: Float)

Clips everything drawn until the matching popClip to this rectangle, intersected with any clip already in force.

A rectangle with no area clears the clip to the whole window instead of hiding everything, so check for an empty rectangle before calling this.

Sources/LavaUI/DrawList.swift:987

func rect(x: Float, y: Float, w: Float, h: Float, color: Color)

Fills a rectangle. Coordinates are window pixels.

Sources/LavaUI/DrawList.swift:601

func ring(inner: [(x: Float, y: Float)], outer: [(x: Float, y: Float)], color: Color)

Fills a ring segment (annulus sector) between two arcs of equal point count — the shape a donut-chart wedge needs, where a hole in the middle means no single point can fan to the whole boundary.

Sources/LavaUI/DrawList.swift:763

func roundedRect(x: Float, y: Float, w: Float, h: Float, color: Color, radius: Float = 4)

Fills a rectangle with rounded corners.

radius is the corner radius in pixels; the edges are anti-aliased.

Sources/LavaUI/DrawList.swift:649

func strokedRect(x: Float, y: Float, w: Float, h: Float, color: Color, radius: Float = 0, width: Float = 1)

An outline of width pixels lying inside x,y,w,h, with the outer edge rounded by radius.

Inside, not centred on the edge, so a bordered view occupies exactly the rect it was laid out in — which is what .border() promises and what lets this take the same rect and radius as the fill underneath it.

The width crosses to the renderer as 24.8 fixed point because the command struct has no float field left. A hairline is 1.25 or 1.5 physical pixels on a fractional-scale output, so rounding it to whole pixels is the difference between a border and none at all.

Sources/LavaUI/DrawList.swift:634

func text(_ string: String, x: Float, y: Float, w: Float, h: Float, color: Color, font: UIFont? = nil)

Shapes string (cached on the font) and appends its glyphs at absolute positions. y is the line box top; the pen sits at the baseline, i.e. y + ascent.

Sources/LavaUI/DrawList.swift:687