Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ This release has an [MSRV][] of 1.86.
- `register_texture`, a helper for using `wgpu` textures in a Vello `Renderer`. ([#1161][] by [@DJMcNab][])
- `push_luminance_mask_layer`, content within which is used as a luminance mask. ([#1183][] by [@DJMcNab][]).
This is a breaking change to Vello Encoding.
- `push_clip_layer`, which replaces the previous `push_layer` using `Mix::Clip`, and has fewer footguns. ([#1192][] by [@DJMcNab][])
This is not a breaking change, as `Mix::Clip` is still supported (although it is deprecated).

### Changed

Expand Down Expand Up @@ -346,6 +348,7 @@ This release has an [MSRV][] of 1.75.
[#1182]: https://github.com/linebender/vello/pull/1182
[#1183]: https://github.com/linebender/vello/pull/1183
[#1187]: https://github.com/linebender/vello/pull/1187
[#1192]: https://github.com/linebender/vello/pull/1192
[#1224]: https://github.com/linebender/vello/pull/1224
[#1229]: https://github.com/linebender/vello/pull/1229

Expand Down
13 changes: 4 additions & 9 deletions examples/scenes/src/test_scenes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1152,7 +1152,7 @@ mod impls {
const CLIPS_PER_FILL: usize = 3;
for _ in 0..CLIPS_PER_FILL {
let rot = Affine::rotate(rng.random_range(0.0..PI));
scene.push_layer(Mix::Clip, 1.0, translate * rot, &base_tri);
scene.push_clip_layer(translate * rot, &base_tri);
}
let rot = Affine::rotate(rng.random_range(0.0..PI));
let color = Color::new([rng.random(), rng.random(), rng.random(), 1.]);
Expand Down Expand Up @@ -1212,7 +1212,7 @@ mod impls {
PathEl::LineTo((X0, Y1).into()),
PathEl::ClosePath,
];
scene.push_layer(Mix::Clip, 1.0, Affine::IDENTITY, &path);
scene.push_clip_layer(Affine::IDENTITY, &path);
}
let rect = Rect::new(X0, Y0, X1, Y1);
scene.fill(
Expand Down Expand Up @@ -1243,12 +1243,7 @@ mod impls {
None,
&make_diamond(1024.0, 125.0),
);
scene.push_layer(
Mix::Clip,
1.0,
Affine::IDENTITY,
&make_diamond(1024.0, 150.0),
);
scene.push_clip_layer(Affine::IDENTITY, &make_diamond(1024.0, 150.0));
scene.fill(
Fill::NonZero,
Affine::IDENTITY,
Expand Down Expand Up @@ -1584,7 +1579,7 @@ mod impls {
PathEl::ClosePath,
]
};
scene.push_layer(Mix::Clip, 1.0, Affine::IDENTITY, &clip);
scene.push_clip_layer(Affine::IDENTITY, &clip);
{
let text_size = 60.0 + 40.0 * (params.time as f32).sin();
let s = "Some clipped text!";
Expand Down
37 changes: 30 additions & 7 deletions vello/src/scene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,16 @@ impl Scene {
/// previous layers using the specified blend mode.
///
/// Every drawing command after this call will be clipped by the shape
/// until the layer is popped.
/// until the layer is [popped](Self::pop_layer).
/// For layers which are only added for clipping, you should
/// use [`push_clip_layer`](Self::push_clip_layer) instead.
///
/// **However, the transforms are *not* saved or modified by the layer stack.**
/// That is, the `transform` argument to this function only applies a transform to the `clip` shape.
///
/// Clip layers (`blend` = [`Mix::Clip`]) should have an alpha value of 1.0.
/// For an opacity group with non-unity alpha, specify [`Mix::Normal`].
#[track_caller]
pub fn push_layer(
&mut self,
blend: impl Into<BlendMode>,
Expand All @@ -108,15 +112,16 @@ impl Scene {
}

/// Pushes a new layer clipped by the specified shape and treated like a luminance
/// mask for previous layers.
/// mask for the current layer.
///
/// That is, content drawn between this and the next `pop_layer` call will serve
/// as a luminance mask
/// That is, content drawn between this and the matching `pop_layer` call will serve
/// as a luminance mask for the prior content in this layer.
///
/// Every drawing command after this call will be clipped by the shape
/// until the layer is popped.
/// until the layer is [popped](Self::pop_layer).
///
/// **However, the transforms are *not* saved or modified by the layer stack.**
/// That is, the `transform` argument to this function only applies a transform to the `clip` shape.
///
/// # Transparency and premultiplication
///
Expand All @@ -137,6 +142,24 @@ impl Scene {
);
}

/// Pushes a new layer clipped by the specified `clip` shape.
///
/// The pushed layer is intended to not impact the "source" for blending; that is, any blends
/// within this layer will still include content from before this method was called in the "source"
/// of that blend operation.
/// Note that this is not currently implemented correctly -
/// see [#1198](https://github.com/linebender/vello/issues/1198).
/// As such, you should currently not include any blend layers until this layer is popped.
///
/// Every drawing command after this call will be clipped by the shape
/// until the layer is [popped](Self::pop_layer).
///
/// **However, the transforms are *not* saved or modified by the layer stack.**
/// That is, the `transform` argument to this function only applies a transform to the `clip` shape.
pub fn push_clip_layer(&mut self, transform: Affine, clip: &impl Shape) {
self.push_layer_inner(DrawBeginClip::clip(), transform, clip);
}

/// Helper for logic shared between [`Self::push_layer`] and [`Self::push_luminance_mask_layer`]
fn push_layer_inner(
&mut self,
Expand Down Expand Up @@ -872,7 +895,7 @@ impl ColorPainter for DrawColorGlyphs<'_> {
};
self.clip_depth += 1;
self.scene
.push_layer(Mix::Clip, 1.0, self.last_transform().to_kurbo(), &path.0);
.push_clip_layer(self.last_transform().to_kurbo(), &path.0);
}

fn push_clip_box(&mut self, clip_box: skrifa::raw::types::BoundingBox<f32>) {
Expand All @@ -887,7 +910,7 @@ impl ColorPainter for DrawColorGlyphs<'_> {
}
self.clip_depth += 1;
self.scene
.push_layer(Mix::Clip, 1.0, self.last_transform().to_kurbo(), &clip_box);
.push_clip_layer(self.last_transform().to_kurbo(), &clip_box);
}

fn pop_clip(&mut self) {
Expand Down
19 changes: 17 additions & 2 deletions vello_encoding/src/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,14 @@ impl DrawBeginClip {
///
/// The least significant 16 bits are reserved for Mix + Compose
/// combinations.
pub const LUMINANCE_MASK_LAYER: u32 = 0x10000;
pub const LUMINANCE_MASK_BLEND_MODE: u32 = 0x10000;
/// The `blend_mode` used to indicate that a layer should be
/// treated as a clip.
///
/// This is equivalent to `Compose::SrcOver` with a `Mix` of 128,
/// for legacy reasons.
/// We expect this to change in the future.
pub const CLIP_BLEND_MODE: u32 = 0x8003;

/// Creates new clip draw data for a Porter-Duff blend mode.
pub fn new(blend_mode: BlendMode, alpha: f32) -> Self {
Expand All @@ -214,10 +221,18 @@ impl DrawBeginClip {
/// Creates a new clip draw data for a luminance mask.
pub fn luminance_mask(alpha: f32) -> Self {
Self {
blend_mode: Self::LUMINANCE_MASK_LAYER,
blend_mode: Self::LUMINANCE_MASK_BLEND_MODE,
alpha,
}
}

/// Creates the clip draw data for a clip-only layer.
pub fn clip() -> Self {
Self {
blend_mode: Self::CLIP_BLEND_MODE,
alpha: 1.0,
}
}
}

/// Monoid for the draw tag stream.
Expand Down
Loading