Skip to content
Open
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
5 changes: 5 additions & 0 deletions research/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ Subheadings to categorize changes are `added, changed, deprecated, removed, fixe

This release has an [MSRV][] of 1.89.

### Changed

- Breaking change: `Scene::draw_blurred_rounded_rect_in` now has an `invert` parameter for painting the inverse (`1 - alpha`) of the blur coverage, enabling inset box shadows. Use `false` to preserve the previous behavior. `vello_encoding::Encoding::encode_blurred_rounded_rect` has the same new parameter. ([#1718][] by [@nicoburns][])

## [0.11.0][] - 2026-10-02

This release has an [MSRV][] of 1.89.
Expand Down Expand Up @@ -478,6 +482,7 @@ This release has an [MSRV][] of 1.75.
[#1638]: https://github.com/linebender/vello/pull/1638
[#1643]: https://github.com/linebender/vello/pull/1643
[#1700]: https://github.com/linebender/vello/pull/1700
[#1718]: https://github.com/linebender/vello/pull/1718
[#1774]: https://github.com/linebender/vello/pull/1774
[#1777]: https://github.com/linebender/vello/pull/1777
[#1847]: https://github.com/linebender/vello/pull/1847
Expand Down
1 change: 1 addition & 0 deletions research/examples/scenes/src/test_scenes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2048,6 +2048,7 @@ mod impls {
palette::css::BLACK,
radius,
std_dev,
false,
);
}

Expand Down
8 changes: 8 additions & 0 deletions research/vello_encoding/src/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,14 @@ pub struct DrawBlurRoundedRect {
/// Rectangle corner radius.
pub radius: f32,
/// Standard deviation of gaussian filter.
///
/// The magnitude is the standard deviation; the sign bit encodes whether to paint the
/// inverse (`1 - alpha`) of the blur coverage (sign bit clear = normal, set = inverse).
/// Note that this means that an inverse blur with a standard deviation of zero is
/// encoded as `-0.0`.
///
/// [`Encoding::encode_blurred_rounded_rect`](crate::Encoding::encode_blurred_rounded_rect)
/// produces this encoding from a standard deviation and an `invert` flag.
pub std_dev: f32,
}

Expand Down
16 changes: 15 additions & 1 deletion research/vello_encoding/src/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,15 +456,29 @@ impl Encoding {
})));
}

// Encodes a blurred rounded rectangle brush.
/// Encodes a blurred rounded rectangle brush.
///
/// Negative values of `std_dev` are treated as zero.
///
/// When `invert` is `true`, the inverse (`1 - alpha`) of the blur coverage is painted.
pub fn encode_blurred_rounded_rect(
&mut self,
color: impl Into<DrawColor>,
width: f32,
height: f32,
radius: f32,
std_dev: f32,
invert: bool,
) {
// A standard deviation is a magnitude, so negative (and NaN) values are clamped to
// zero. That leaves the sign bit of the encoded `std_dev` free to carry the `invert`
// flag (see `DrawBlurRoundedRect::std_dev`). This also works for a standard deviation
// of zero, as `-0.0` has its sign bit set.
let std_dev = if invert {
-std_dev.max(0.0)
} else {
std_dev.max(0.0)
};
self.draw_tags.push(DrawTag::BLUR_RECT);
self.draw_data
.extend_from_slice(bytemuck::cast_slice(bytemuck::bytes_of(
Expand Down
27 changes: 22 additions & 5 deletions research/vello_research/src/scene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,19 +254,34 @@ impl Scene {
let kernel_size = 2.5 * std_dev;

let shape: Rect = rect.inflate(kernel_size, kernel_size);
self.draw_blurred_rounded_rect_in(&shape, transform, rect, brush, radius, std_dev);
self.draw_blurred_rounded_rect_in(&shape, transform, rect, brush, radius, std_dev, false);
}

/// Draw a rounded rectangle blurred with a gaussian filter in `shape`.
///
/// For performance reasons, `shape` should not extend more than approximately 2.5 times
/// `std_dev` away from the edges of `rect` (as any such points will not be perceptably painted to,
/// but calculations will still be performed for them).
///
/// This method effectively draws the blurred rounded rectangle clipped to the given shape.
/// If just the blurred rounded rectangle is desired without clipping,
/// use the simpler [`Self::draw_blurred_rounded_rect`].
/// For many users, that method will be easier to use.
///
/// The blurred rounded rectangle is `rect` with its corners rounded by `radius`, blurred by
/// a gaussian filter with a standard deviation of `std_dev`. Negative values of `std_dev`
/// are treated as zero.
///
/// When `invert` is `false`, `brush` is painted with the coverage (`alpha`) of the blurred
/// rounded rectangle. Points which are more than approximately 2.5 times `std_dev` outside
/// of the edges of `rect` will not be perceptibly painted to, but calculations will still
/// be performed for them. So for performance reasons, `shape` should not extend further
/// than that.
///
/// When `invert` is `true`, the inverse (`1 - alpha`) of that coverage is painted instead.
/// The coverage then falls off towards the inside of `rect`, and is effectively full at
/// all points of `shape` which are more than approximately 2.5 times `std_dev` outside of
/// the edges of `rect`. This means that the extent of the painted area is determined only
/// by `shape`, which can extend as far beyond `rect` as is needed.
/// This can be used to implement inset box shadows, by using the box as `shape`, the box
/// shrunk by the spread of the shadow and translated by its offset as `rect`, and the
/// corner radius of the box reduced by the spread as `radius`.
pub fn draw_blurred_rounded_rect_in(
&mut self,
shape: &impl Shape,
Expand All @@ -275,6 +290,7 @@ impl Scene {
brush: Color,
radius: f64,
std_dev: f64,
invert: bool,
) {
let t = Transform::from_kurbo(&transform);
self.encoding.encode_transform(t);
Expand All @@ -292,6 +308,7 @@ impl Scene {
rect.height() as _,
radius as _,
std_dev as _,
invert,
);
}
}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading