Use this file to discover all available pages before exploring further.
Every Paper element has two optional drawing hooks that give you direct access to the underlying Prowl.Quill.Canvas at render time. Inside these callbacks you can draw anything the canvas supports — paths, filled shapes, gradients, images, and even custom shaders — without leaving the immediate-mode flow. The canvas is hardware-accelerated, anti-aliased, and scissor-aware, so your custom artwork clips and layers exactly like styled elements do.
paper.Draw() registers a callback that fires before the element’s children are rendered. Use it for custom backgrounds, data visualisations, or decorations that should sit beneath child content.
// Attach to the current parent elementpaper.Draw((canvas, rect) =>{ // rect is the element's layout rectangle in logical coordinates canvas.SetFillColor(Color.CornflowerBlue); canvas.CircleFilled(rect.Center.X, rect.Center.Y, rect.Size.X * 0.4f, 32);});
You can also target a specific ElementHandle directly:
paper.DrawForeground() fires after all children have been rendered. Use it for overlays, highlight borders, tooltips, or any decoration that must appear on top of child content.
paper.DrawForeground((canvas, rect) =>{ // Draw a selection ring over all children canvas.BeginPath(); canvas.RoundedRect(rect.Min.X + 1, rect.Min.Y + 1, rect.Size.X - 2, rect.Size.Y - 2, 6, 6, 6, 6); canvas.SetStrokeColor(Color.DodgerBlue); canvas.SetStrokeWidth(2); canvas.Stroke();});
The canvas state (transform, scissor, fill/stroke settings) is not automatically saved and restored around custom draw callbacks. Call canvas.SaveState() at the start and canvas.RestoreState() at the end if your callback changes state that must not leak into sibling elements.
Before calling Fill(), set a gradient brush to replace the flat fill colour. Gradients use element-relative coordinates (0–1 range maps to the element’s width/height) when created through Gradient factory methods, but you pass raw canvas coordinates when calling the canvas brush setters directly.
Linear
Blends from one point to another along a straight axis.
Radial
Radiates from an inner circle to an outer circle around a centre point.
Box
Like a radial gradient but shaped to a rounded rectangle for soft glow effects.
You can also attach gradient backgrounds to elements via the ElementBuilder style API, which uses normalised (0–1) coordinates relative to the element’s bounding box.
paper.Box("GradientPanel") .Width(300).Height(120) .BackgroundLinearGradient(0, 0, 1, 0, // left → right Color.MidnightBlue, Color.DeepSkyBlue) .Rounded(8);
Attach a drop shadow to any element with .BoxShadow(). The shadow is rendered as a blurred box before the element’s background, so it appears to lift the element off the canvas.
For frosted-glass effects, set a backdrop blur radius before drawing. The renderer captures and blurs whatever has been rendered behind the shape, then composites your fill on top as a tint.
Replace the default fragment shader for a single element using .CustomShader() on the ElementBuilder. The element’s layout rectangle is drawn with RectFilled using the custom shader, and you can push uniform values into it each frame via a ShaderUniforms callback.
The shader parameter type is object — pass the backend-specific handle directly (e.g. an OpenGL program int boxed as object, or a Raylib Shader struct). The renderer you implemented receives it back in DrawCall.Shader and can cast it safely.
The following example draws a segmented progress ring inside a Draw callback, compositing it behind a centred percentage label that is a regular Paper text element.