Layers
Group draws, apply opacity or a filter once, mask with coverage.
save_layer / saveLayer opens an offscreen target. Children draw into it.
restore composites that texture as one image using the layer paint's alpha,
blend, and filters.
Left: per-draw alpha, so overlaps darken twice. Right: the same shapes inside a layer — the group alpha applies once.
builder.save_layer(None, &Paint::from_color(Color::rgba(0.0, 0.0, 0.0, 0.4)));
builder.draw_circle((200.0, 80.0), 46.0, &opaque);
builder.restore();builder.saveLayer(new Paint(0, 0, 0, 0.4));
builder.drawCircle(200, 80, 46, opaque);
builder.restore();Left: per-draw alpha, so overlaps darken twice. Right: the same shapes inside a layer — the group alpha applies once.
When a layer is skipped
A save-layer whose children are opaque-disjoint and whose paint is only alpha can be elided: children draw in the parent with that alpha on their tint. Depth slots do not change. Backdrop layers never elide — they need a texture to hold the blur.
saveLayerBounds / a bounds hint crops children. Hinted layers also skip
elision.
Mask layers
save_layer_mask composites as coverage (DstIn over the parent), not as a
picture. MaskKind::Luminance uses luma×alpha; MaskKind::Alpha uses
alpha only. A mask whose bounds miss the cull rect still erases the parent
— coverage is zero everywhere.
Rust:
builder.save_layer_mask(None, MaskKind::Luminance);
builder.draw_rect(rect, &Paint::from_color(Color::WHITE));
builder.restore();The JavaScript engine API does not yet expose mask layers; use Rust or wait
for a later valo-web binding.