Add Canvas::set_clip_path — anti-aliased arbitrary-path clipping on both backends
Add `Canvas::set_clip_path(&[PathCmd])`, clipping subsequent draws to an arbitrary vector path with an anti-aliased edge, on both the software and GLES backends. It complements the existing rect clip (`set_clip_rects`) and is what an embedder needs to render a shaped clip — a circular avatar, a rounded card, a `VectorDrawable` mask — rather than a bounding box. Kept general rather than tied to any one consumer. Software backend: rasterise the path into an anti-aliased tiny-skia coverage `Mask` (Winding fill) and install it as the active clip mask. Every software primitive already threads `clip_mask` through tiny-skia (fills, strokes, lines, paths, images, text, blit), so the path clip applies uniformly with smooth edges. `clip_bounds` reports the path's bounding box while it is active. GLES backend: a 1-bit stencil would clip exactly but leave a hard, aliased edge, so instead the clipped draws are captured into an offscreen layer and composited back through an anti-aliased coverage mask. `set_clip_path` rasterises the path coverage (tiny-skia, anti-aliased), uploads it as a mask texture, allocates a full-canvas layer FBO on first use, and redirects subsequent draws to it via `activate_target`. Ending the clip (`clear_clip` / `set_clip_rects` / a new `set_clip_path`) composites the layer back onto the canvas FBO with a new two-sampler program (`CLIP_COMPOSITE_FRAG_SRC`) that multiplies the layer colour by the mask coverage and blends it premultiplied-over. The layer attaches to the canvas's own shadow FBO, so it needs no stencil bits in the EGL config; it is freed and reallocated on resize and freed on drop, and shared programs/uniforms are copied to sub-canvases like the rest. Usage: a path clip is bracketed — `set_clip_path` then, after the clipped draws, `clear_clip` or `set_clip_rects` to flush it (on GLES this is when the layer is composited). Snapshot the prior clip with `clip_bounds` beforehand and restore it with `set_clip_rects` to compose with an outer clip without leaking state. Add an `examples/clip_path.rs` demo (rounded rect, circle, triangle — same smooth result on both backends) and software-backend unit tests covering the bounding box, the empty-path clear, and a pixel-level check that a triangular clip masks a fill to the path silhouette rather than its bounding box. The GLES layer-composite path needs a live GL context and is exercised by the example. Also fix three rustdoc intra-doc-link warnings surfaced along the way: a private-item link in `app.rs` (`scroll`) and the new GLES doc (`SoftwareCanvas::set_clip_path`) demoted to code spans, and a redundant explicit link target in `chassis.rs`.
This commit is contained in:
@@ -147,6 +147,30 @@ void main()
|
||||
}
|
||||
"##;
|
||||
|
||||
// Clip-layer composite shader for `set_clip_path`. Path-clipped content is
|
||||
// drawn to an offscreen layer; this composites that layer onto the canvas
|
||||
// multiplied by an anti-aliased coverage mask, giving a smooth clipped edge.
|
||||
// `u_layer` is the full-canvas layer texture (premultiplied), `u_mask` the
|
||||
// path coverage rasterised over `u_bbox` (x, y, w, h in canvas pixels). The
|
||||
// quad is drawn over the bbox; `v_uv` runs 0..1 across it. Both FBO-backed
|
||||
// textures are sampled y-flipped (GL's lower-left origin).
|
||||
pub( super ) const CLIP_COMPOSITE_FRAG_SRC: &str = r##"
|
||||
precision mediump float;
|
||||
varying vec2 v_uv;
|
||||
uniform sampler2D u_layer;
|
||||
uniform sampler2D u_mask;
|
||||
uniform vec2 u_canvas;
|
||||
uniform vec4 u_bbox;
|
||||
void main()
|
||||
{
|
||||
vec2 sp = u_bbox.xy + v_uv * u_bbox.zw;
|
||||
vec2 luv = vec2( sp.x / u_canvas.x, 1.0 - sp.y / u_canvas.y );
|
||||
vec4 col = texture2D( u_layer, luv );
|
||||
float cov = texture2D( u_mask, vec2( v_uv.x, 1.0 - v_uv.y ) ).a;
|
||||
gl_FragColor = col * cov;
|
||||
}
|
||||
"##;
|
||||
|
||||
// Fragment shader for single-channel glyph textures with color tint.
|
||||
//
|
||||
// Glyphs live in a shared GL_LUMINANCE atlas. `u_uv_scale` and `u_uv_offset`
|
||||
|
||||
Reference in New Issue
Block a user