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
@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