pub trait DrawCtx {
Show 77 methods
// Required methods
fn set_fill_color(&mut self, color: Color);
fn set_stroke_color(&mut self, color: Color);
fn set_line_width(&mut self, w: f64);
fn set_line_join(&mut self, join: LineJoin);
fn set_line_cap(&mut self, cap: LineCap);
fn set_miter_limit(&mut self, limit: f64);
fn set_line_dash(&mut self, dashes: &[f64], offset: f64);
fn set_blend_mode(&mut self, mode: CompOp);
fn set_global_alpha(&mut self, alpha: f64);
fn set_fill_rule(&mut self, rule: FillRule);
fn set_font(&mut self, font: Arc<Font>);
fn set_font_size(&mut self, size: f64);
fn clip_rect(&mut self, x: f64, y: f64, w: f64, h: f64);
fn reset_clip(&mut self);
fn clear(&mut self, color: Color);
fn begin_path(&mut self);
fn move_to(&mut self, x: f64, y: f64);
fn line_to(&mut self, x: f64, y: f64);
fn cubic_to(
&mut self,
cx1: f64,
cy1: f64,
cx2: f64,
cy2: f64,
x: f64,
y: f64,
);
fn quad_to(&mut self, cx: f64, cy: f64, x: f64, y: f64);
fn arc_to(
&mut self,
cx: f64,
cy: f64,
r: f64,
start_angle: f64,
end_angle: f64,
ccw: bool,
);
fn circle(&mut self, cx: f64, cy: f64, r: f64);
fn rect(&mut self, x: f64, y: f64, w: f64, h: f64);
fn rounded_rect(&mut self, x: f64, y: f64, w: f64, h: f64, r: f64);
fn close_path(&mut self);
fn fill(&mut self);
fn stroke(&mut self);
fn fill_and_stroke(&mut self);
fn draw_triangles_aa(
&mut self,
vertices: &[[f32; 3]],
indices: &[u32],
color: Color,
);
fn fill_text(&mut self, text: &str, x: f64, y: f64);
fn fill_text_gsv(&mut self, text: &str, x: f64, y: f64, size: f64);
fn measure_text(&self, text: &str) -> Option<TextMetrics>;
fn transform(&self) -> TransAffine;
fn save(&mut self);
fn restore(&mut self);
fn translate(&mut self, tx: f64, ty: f64);
fn rotate(&mut self, radians: f64);
fn scale(&mut self, sx: f64, sy: f64);
fn set_transform(&mut self, m: TransAffine);
fn reset_transform(&mut self);
// Provided methods
fn as_any_mut(&mut self) -> Option<&mut dyn Any> { ... }
fn set_fill_linear_gradient(&mut self, _gradient: LinearGradientPaint) { ... }
fn set_fill_radial_gradient(&mut self, _gradient: RadialGradientPaint) { ... }
fn set_fill_pattern(&mut self, _pattern: PatternPaint) { ... }
fn set_stroke_linear_gradient(&mut self, _gradient: LinearGradientPaint) { ... }
fn set_stroke_radial_gradient(&mut self, _gradient: RadialGradientPaint) { ... }
fn set_stroke_pattern(&mut self, _pattern: PatternPaint) { ... }
fn supports_fill_linear_gradient(&self) -> bool { ... }
fn supports_fill_radial_gradient(&self) -> bool { ... }
fn supports_fill_pattern(&self) -> bool { ... }
fn supports_stroke_linear_gradient(&self) -> bool { ... }
fn supports_stroke_radial_gradient(&self) -> bool { ... }
fn supports_stroke_pattern(&self) -> bool { ... }
fn root_transform(&self) -> TransAffine { ... }
fn snap_to_pixel(&mut self) { ... }
fn push_layer(&mut self, _width: f64, _height: f64) { ... }
fn supports_compositing_layers(&self) -> bool { ... }
fn supports_retained_layers(&self) -> bool { ... }
fn push_layer_with_alpha(&mut self, width: f64, height: f64, _alpha: f64) { ... }
fn set_layer_rounded_clip(
&mut self,
_x: f64,
_y: f64,
_w: f64,
_h: f64,
_r: f64,
) { ... }
fn composite_retained_layer(
&mut self,
_key: u64,
_width: f64,
_height: f64,
_alpha: f64,
) -> bool { ... }
fn push_retained_layer_with_alpha(
&mut self,
_key: u64,
width: f64,
height: f64,
alpha: f64,
) { ... }
fn pop_layer(&mut self) { ... }
fn gl_paint(&mut self, _screen_rect: Rect, _painter: &mut dyn GlPaint) { ... }
fn draw_lcd_mask(
&mut self,
_mask: &[u8],
_mask_w: u32,
_mask_h: u32,
_src_color: Color,
_dst_x: f64,
_dst_y: f64,
) { ... }
fn draw_lcd_mask_arc(
&mut self,
mask: &Arc<Vec<u8>>,
mask_w: u32,
mask_h: u32,
src_color: Color,
dst_x: f64,
dst_y: f64,
) { ... }
fn has_lcd_mask_composite(&self) -> bool { ... }
fn has_image_blit(&self) -> bool { ... }
fn draw_image_rgba(
&mut self,
data: &[u8],
img_w: u32,
img_h: u32,
dst_x: f64,
dst_y: f64,
dst_w: f64,
dst_h: f64,
) { ... }
fn draw_image_rgba_arc(
&mut self,
data: &Arc<Vec<u8>>,
img_w: u32,
img_h: u32,
dst_x: f64,
dst_y: f64,
dst_w: f64,
dst_h: f64,
) { ... }
fn draw_lcd_backbuffer_arc(
&mut self,
color: &Arc<Vec<u8>>,
alpha: &Arc<Vec<u8>>,
w: u32,
h: u32,
dst_x: f64,
dst_y: f64,
dst_w: f64,
dst_h: f64,
) { ... }
fn capture_screenshot(&mut self) -> bool { ... }
fn has_captured_screenshot(&self) -> bool { ... }
fn captured_screenshot_size(&self) -> Option<(u32, u32)> { ... }
fn draw_captured_screenshot(
&mut self,
_dst_x: f64,
_dst_y: f64,
_dst_w: f64,
_dst_h: f64,
) -> bool { ... }
fn read_captured_screenshot(&mut self) -> (Vec<u8>, u32, u32) { ... }
fn visuals(&self) -> Visuals { ... }
}Expand description
Unified 2-D drawing context.
All coordinate parameters use the Y-up, first-quadrant convention:
origin at the bottom-left, positive-Y upward. This matches GfxCtx and
the widget tree layout invariant.
Required Methods§
fn set_fill_color(&mut self, color: Color)
fn set_stroke_color(&mut self, color: Color)
fn set_line_width(&mut self, w: f64)
fn set_line_join(&mut self, join: LineJoin)
fn set_line_cap(&mut self, cap: LineCap)
fn set_miter_limit(&mut self, limit: f64)
fn set_line_dash(&mut self, dashes: &[f64], offset: f64)
fn set_blend_mode(&mut self, mode: CompOp)
fn set_global_alpha(&mut self, alpha: f64)
fn set_fill_rule(&mut self, rule: FillRule)
fn set_font(&mut self, font: Arc<Font>)
fn set_font_size(&mut self, size: f64)
fn clip_rect(&mut self, x: f64, y: f64, w: f64, h: f64)
fn reset_clip(&mut self)
Sourcefn clear(&mut self, color: Color)
fn clear(&mut self, color: Color)
Fill the entire render target with color, ignoring the current clip.
fn begin_path(&mut self)
fn move_to(&mut self, x: f64, y: f64)
fn line_to(&mut self, x: f64, y: f64)
fn cubic_to(&mut self, cx1: f64, cy1: f64, cx2: f64, cy2: f64, x: f64, y: f64)
fn quad_to(&mut self, cx: f64, cy: f64, x: f64, y: f64)
fn arc_to( &mut self, cx: f64, cy: f64, r: f64, start_angle: f64, end_angle: f64, ccw: bool, )
Sourcefn rect(&mut self, x: f64, y: f64, w: f64, h: f64)
fn rect(&mut self, x: f64, y: f64, w: f64, h: f64)
Add an axis-aligned rectangle contour to the current path.
Sourcefn rounded_rect(&mut self, x: f64, y: f64, w: f64, h: f64, r: f64)
fn rounded_rect(&mut self, x: f64, y: f64, w: f64, h: f64, r: f64)
Add a rounded-rectangle contour to the current path.
fn close_path(&mut self)
fn fill(&mut self)
fn stroke(&mut self)
fn fill_and_stroke(&mut self)
Sourcefn draw_triangles_aa(
&mut self,
vertices: &[[f32; 3]],
indices: &[u32],
color: Color,
)
fn draw_triangles_aa( &mut self, vertices: &[[f32; 3]], indices: &[u32], color: Color, )
Submit pre-tessellated AA triangles with per-vertex coverage
(x, y, alpha) and triangle indices.
This is the fast path for callers that tessellate their geometry
ONCE at load time (e.g. the Lion demo, SVG icons): they do the
tessellate_path_aa pass themselves, cache the vertex+index
buffers, then submit them every frame with only a cheap CPU
transform applied to the x/y components. Compared to issuing
move_to / line_to / fill every frame, this keeps the polygon
set deterministic (no tess2 re-running on subtly-different
coordinates), avoids thousands of re-tessellations per frame, and
produces identical output regardless of the widget’s transform.
Vertices are (x_logical_pixels, y_logical_pixels, alpha_0_to_1).
alpha is multiplied into the supplied color.a in the AA shader
so halo-strip edge AA survives this fast path.
The software GfxCtx ignores the alpha attribute and rasterises
each triangle as a solid fill — correct but without edge AA, which
matches the software path’s existing stroke/fill behaviour.
Sourcefn fill_text(&mut self, text: &str, x: f64, y: f64)
fn fill_text(&mut self, text: &str, x: f64, y: f64)
Draw text with the bottom of the baseline at (x, y).
Sourcefn fill_text_gsv(&mut self, text: &str, x: f64, y: f64, size: f64)
fn fill_text_gsv(&mut self, text: &str, x: f64, y: f64, size: f64)
Draw text using the built-in AGG Glyph-Stroke-Vector font at size
pixels. Useful before a proper font is loaded.
Sourcefn measure_text(&self, text: &str) -> Option<TextMetrics>
fn measure_text(&self, text: &str) -> Option<TextMetrics>
Measure text with the current font and font-size settings.
Sourcefn transform(&self) -> TransAffine
fn transform(&self) -> TransAffine
Current accumulated transform (CTM).
fn save(&mut self)
fn restore(&mut self)
fn translate(&mut self, tx: f64, ty: f64)
fn rotate(&mut self, radians: f64)
fn scale(&mut self, sx: f64, sy: f64)
fn set_transform(&mut self, m: TransAffine)
fn reset_transform(&mut self)
Provided Methods§
Sourcefn as_any_mut(&mut self) -> Option<&mut dyn Any>
fn as_any_mut(&mut self) -> Option<&mut dyn Any>
Optional escape hatch for widgets that need direct access to a backend-specific concrete context (e.g. to push a custom GPU draw command into the deferred command stream).
The default returns None; backends that opt in override to return
Some(self). Callers must handle the None case gracefully — if a
widget falls back through gl_paint it works on every backend.
fn set_fill_linear_gradient(&mut self, _gradient: LinearGradientPaint)
fn set_fill_radial_gradient(&mut self, _gradient: RadialGradientPaint)
fn set_fill_pattern(&mut self, _pattern: PatternPaint)
fn set_stroke_linear_gradient(&mut self, _gradient: LinearGradientPaint)
fn set_stroke_radial_gradient(&mut self, _gradient: RadialGradientPaint)
fn set_stroke_pattern(&mut self, _pattern: PatternPaint)
fn supports_fill_linear_gradient(&self) -> bool
fn supports_fill_radial_gradient(&self) -> bool
fn supports_fill_pattern(&self) -> bool
fn supports_stroke_linear_gradient(&self) -> bool
fn supports_stroke_radial_gradient(&self) -> bool
fn supports_stroke_pattern(&self) -> bool
Sourcefn root_transform(&self) -> TransAffine
fn root_transform(&self) -> TransAffine
Current transform expressed in the root render target’s coordinate space, even when drawing inside an offscreen layer whose local CTM was reset to identity. Global overlays use this to submit app-level bounds.
Sourcefn snap_to_pixel(&mut self)
fn snap_to_pixel(&mut self)
Opt-in pixel snapping. Strips the fractional part of the current
CTM translation so subsequent integer-coordinate rect / fill /
stroke / draw_image_rgba* calls land exactly on the physical pixel
grid — no AA fringe on edges, no LINEAR-filter blur on 1:1 texture
blits.
Call this ONLY when the widget genuinely wants pixel-aligned drawing (text backbuffers, pixel-alignment diagnostics, crisp UI strokes). Sub-pixel positioning remains the default — e.g. a smooth-scrolling panel or an animated marker may legitimately want a fractional offset. Typical usage:
ctx.save();
ctx.snap_to_pixel();
ctx.rect(0.0, 0.0, 10.0, 10.0);
ctx.fill();
ctx.restore();Only the translation component is affected; rotations and non-uniform scales pass through untouched (pixel alignment under those transforms isn’t well defined, and forcing a snap would visibly jitter rotated content).
Sourcefn push_layer(&mut self, _width: f64, _height: f64)
fn push_layer(&mut self, _width: f64, _height: f64)
Begin a new transparent compositing layer of the given pixel dimensions.
All subsequent drawing (by this widget and its descendants) is redirected
into the new layer until [pop_layer] is called. Layers nest: each
push_layer must be matched by exactly one pop_layer.
The current accumulated transform records the layer’s screen-space origin; drawing inside the layer uses a fresh local-space transform (origin 0,0).
Implementations that do not support layers (e.g. the GL path) may leave this as a no-op — the widget renders pass-through into the parent target.
Sourcefn supports_compositing_layers(&self) -> bool
fn supports_compositing_layers(&self) -> bool
Whether this backend implements real offscreen compositing layers.
The default is false so widgets can opt into layer-based rendering
without forcing every backend to pay for, or emulate, that feature.
Sourcefn supports_retained_layers(&self) -> bool
fn supports_retained_layers(&self) -> bool
Whether this backend can retain named offscreen layers across frames.
Generic compositing support is enough for isolated opacity groups, but retained widget backbuffers need a backend-owned surface keyed by ID.
Sourcefn push_layer_with_alpha(&mut self, width: f64, height: f64, _alpha: f64)
fn push_layer_with_alpha(&mut self, width: f64, height: f64, _alpha: f64)
Begin a new transparent compositing layer that will be multiplied by
alpha when composited back into the parent target.
Backends that do not support layer alpha can fall back to push_layer;
callers gate this through [supports_compositing_layers].
Sourcefn set_layer_rounded_clip(
&mut self,
_x: f64,
_y: f64,
_w: f64,
_h: f64,
_r: f64,
)
fn set_layer_rounded_clip( &mut self, _x: f64, _y: f64, _w: f64, _h: f64, _r: f64, )
Constrain subsequent drawing in the current layer to a rounded-rect mask. Used by window layers after shadows are drawn so chrome/content cannot write into rounded transparent corners.
This is a containment clip, not the visual antialiasing edge. Backends should leave enough room for partially-transparent edge pixels so the caller’s normal alpha coverage can feather corners and edges.
Sourcefn composite_retained_layer(
&mut self,
_key: u64,
_width: f64,
_height: f64,
_alpha: f64,
) -> bool
fn composite_retained_layer( &mut self, _key: u64, _width: f64, _height: f64, _alpha: f64, ) -> bool
Composite a previously retained backend layer. Returns true when
the backend had a retained surface for key and drew it.
Sourcefn push_retained_layer_with_alpha(
&mut self,
_key: u64,
width: f64,
height: f64,
alpha: f64,
)
fn push_retained_layer_with_alpha( &mut self, _key: u64, width: f64, height: f64, alpha: f64, )
Begin rendering into a retained backend layer identified by key.
Backends that do not retain layers may fall back to a transient layer.
Sourcefn pop_layer(&mut self)
fn pop_layer(&mut self)
Composite the current layer back into the previous render target using SrcOver alpha blending, then discard the layer.
Must be called after a matching push_layer. Unmatched calls are ignored.
Sourcefn gl_paint(&mut self, _screen_rect: Rect, _painter: &mut dyn GlPaint)
fn gl_paint(&mut self, _screen_rect: Rect, _painter: &mut dyn GlPaint)
Render GPU content (3-D scene, video frame, etc.) inline at the correct painter-order position.
screen_rect is the widget’s screen-space rect in Y-up coordinates
(i.e. ctx.transform() origin + widget.bounds().size).
The GL implementation executes painter.gl_paint() immediately so that
any 2-D widgets painted after this call naturally overdraw the GPU
content — correct back-to-front ordering with no post-frame fixup.
The software (GfxCtx) path is a no-op: widgets should draw a 2-D
placeholder before calling this method so the software render has
something visible.
Sourcefn draw_lcd_mask(
&mut self,
_mask: &[u8],
_mask_w: u32,
_mask_h: u32,
_src_color: Color,
_dst_x: f64,
_dst_y: f64,
)
fn draw_lcd_mask( &mut self, _mask: &[u8], _mask_w: u32, _mask_h: u32, _src_color: Color, _dst_x: f64, _dst_y: f64, )
Composite a pre-rasterized LCD subpixel mask onto the current
render target, mixing src_color into the destination through
per-channel coverage.
mask is three bytes per pixel (cov_r, cov_g, cov_b) as
produced by [crate::text_lcd::rasterize_lcd_mask]. The caller
specifies (dst_x, dst_y) in local coordinates (Y-up in our
convention) and mask_w × mask_h to tell the backend the mask’s
dimensions.
Per-channel source-over blend:
dst.r = src.r * mask.r + dst.r * (1 - mask.r)
dst.g = src.g * mask.g + dst.g * (1 - mask.g)
dst.b = src.b * mask.b + dst.b * (1 - mask.b)This is the universal “composite LCD text onto arbitrary bg” primitive — it replaces the prior walk / sample / pre-fill approach. Software ctx implements it as an inner-loop blend; the GL ctx implements it via a dual-source-blend fragment shader. Backends that haven’t wired it yet use the default no-op, which makes callers fall back to grayscale AA.
Sourcefn draw_lcd_mask_arc(
&mut self,
mask: &Arc<Vec<u8>>,
mask_w: u32,
mask_h: u32,
src_color: Color,
dst_x: f64,
dst_y: f64,
)
fn draw_lcd_mask_arc( &mut self, mask: &Arc<Vec<u8>>, mask_w: u32, mask_h: u32, src_color: Color, dst_x: f64, dst_y: f64, )
Arc-keyed variant so GL backends can cache the uploaded texture
on the Arc’s pointer identity — one glTexImage2D per unique
raster, lifetime tied to the mask’s strong-ref count. Software
backends fall through to the slice path.
Sourcefn has_lcd_mask_composite(&self) -> bool
fn has_lcd_mask_composite(&self) -> bool
Returns true if this backend supports [draw_lcd_mask] — i.e.
it can composite per-channel LCD coverage onto the active target.
Label queries this to decide between the LCD and grayscale AA
paths; a backend that returns false will never see LCD text.
Sourcefn has_image_blit(&self) -> bool
fn has_image_blit(&self) -> bool
Returns true if this context implements draw_image_rgba with actual
pixel blitting. Label (and any other widget that uses a software
backbuffer) gates its cache path on this method so it can fall back to
direct fill_text() on render targets that don’t support blitting
(e.g. the GL path).
Default: false. Override to true in GfxCtx.
Sourcefn draw_image_rgba(
&mut self,
data: &[u8],
img_w: u32,
img_h: u32,
dst_x: f64,
dst_y: f64,
dst_w: f64,
dst_h: f64,
)
fn draw_image_rgba( &mut self, data: &[u8], img_w: u32, img_h: u32, dst_x: f64, dst_y: f64, dst_w: f64, dst_h: f64, )
Draw raw RGBA pixel data into dst_rect (Y-up local coordinates).
data must be img_w * img_h * 4 bytes of tightly-packed RGBA8 data
in row-major order, top-row first (Y-down image storage convention).
The image is scaled to fit (dst_x, dst_y, dst_w, dst_h).
Default implementation: no-op (GL path or software paths that do not implement blitting can leave this as a placeholder).
Sourcefn draw_image_rgba_arc(
&mut self,
data: &Arc<Vec<u8>>,
img_w: u32,
img_h: u32,
dst_x: f64,
dst_y: f64,
dst_w: f64,
dst_h: f64,
)
fn draw_image_rgba_arc( &mut self, data: &Arc<Vec<u8>>, img_w: u32, img_h: u32, dst_x: f64, dst_y: f64, dst_w: f64, dst_h: f64, )
Same as [draw_image_rgba] but accepts an Arc<Vec<u8>> so the GL
backend can key its texture cache on the Arc’s pointer identity and
hold a Weak ref for automatic cleanup when the underlying buffer is
dropped — the pattern MatterCAD implements with C# ConditionalWeakTable.
Used by Label (and future glyph-atlas consumers) in tandem with the
crate-level image_cache so that rebuilt widget
trees with unchanged content never re-rasterize OR re-upload.
Default implementation: forward to [draw_image_rgba] via slice
borrow. Software backends don’t benefit from GPU texture caching so
the default is usually fine; the GL backend overrides.
Sourcefn draw_lcd_backbuffer_arc(
&mut self,
color: &Arc<Vec<u8>>,
alpha: &Arc<Vec<u8>>,
w: u32,
h: u32,
dst_x: f64,
dst_y: f64,
dst_w: f64,
dst_h: f64,
)
fn draw_lcd_backbuffer_arc( &mut self, color: &Arc<Vec<u8>>, alpha: &Arc<Vec<u8>>, w: u32, h: u32, dst_x: f64, dst_y: f64, dst_w: f64, dst_h: f64, )
Composite a two-plane LcdCoverage-mode backbuffer onto the active
render target at (dst_x, dst_y) with size (dst_w, dst_h) (in
local coords). Inputs are two Arc<Vec<u8>>, each 3 bytes per
pixel, top-row-first:
color: premultiplied per-channel RGB.alpha: per-channel alpha (coverage).
The compositor applies per-channel premultiplied src-over:
dst.ch := src.color_ch + dst.ch * (1 - src.alpha_ch)which preserves LCD subpixel chroma through the cache round-trip.
Used by [crate::widget::paint_subtree_backbuffered] when a widget’s
crate::widget::BackbufferMode::LcdCoverage cache is ready to
composite onto its parent.
Default: collapses the two planes into a single straight-alpha
RGBA8 image (max of channel alphas, divided back to straight colour)
and forwards to [draw_image_rgba]. Correct for any content where
the three channel alphas agree; lossy of LCD chroma where they
diverge. Backends that want full subpixel quality through the
cache override this with a two-texture shader path.
Sourcefn capture_screenshot(&mut self) -> bool
fn capture_screenshot(&mut self) -> bool
Snapshot the current frame’s surface into the backend’s internal
screenshot texture (allocating / resizing as needed). Must be
called inside the active frame, after end_frame has flushed the
2-D render but before the platform shell calls present.
Returns true if the backend supports the capture path.
Sourcefn has_captured_screenshot(&self) -> bool
fn has_captured_screenshot(&self) -> bool
True if a previously-captured screenshot is held by the backend
and available for Self::draw_captured_screenshot.
Sourcefn captured_screenshot_size(&self) -> Option<(u32, u32)>
fn captured_screenshot_size(&self) -> Option<(u32, u32)>
Dimensions of the held capture, or None when no capture exists.
Sourcefn draw_captured_screenshot(
&mut self,
_dst_x: f64,
_dst_y: f64,
_dst_w: f64,
_dst_h: f64,
) -> bool
fn draw_captured_screenshot( &mut self, _dst_x: f64, _dst_y: f64, _dst_w: f64, _dst_h: f64, ) -> bool
Draw the held capture into (dst_x, dst_y, dst_w, dst_h) using the
backend’s preferred filtered sampling. Returns true if the
capture exists and was drawn.
Sourcefn read_captured_screenshot(&mut self) -> (Vec<u8>, u32, u32)
fn read_captured_screenshot(&mut self) -> (Vec<u8>, u32, u32)
Read the held capture’s pixels back to CPU memory as Y-down RGBA8 —
for Save / Copy. This is intentionally a single-shot synchronous
readback; widgets should NOT call this every frame. Returns
(empty, 0, 0) on backends without a capture or without GPU
readback support.
Sourcefn visuals(&self) -> Visuals
fn visuals(&self) -> Visuals
Return the currently-active Visuals palette.
Delegates to crate::theme::current_visuals, which reads the
thread-local set by crate::theme::set_visuals. Widget paint()
implementations call this to get colours instead of hardcoding them.