Add renderer probe elements
diff --git a/vello_common/assets/probe_blurred_rounded_rect.png b/vello_common/assets/probe_blurred_rounded_rect.png new file mode 100644 index 0000000..927d59a --- /dev/null +++ b/vello_common/assets/probe_blurred_rounded_rect.png Binary files differ
diff --git a/vello_common/assets/probe_blurred_rounded_rect.rgba b/vello_common/assets/probe_blurred_rounded_rect.rgba new file mode 100644 index 0000000..1c9326b --- /dev/null +++ b/vello_common/assets/probe_blurred_rounded_rect.rgba
@@ -0,0 +1 @@ +ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúøüÿëåòÿåÜíÿåÜíÿåÜíÿåÜíÿëåòÿúøüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúøüÿʸÛÿi´ÿV«ÿV«ÿV«ÿV«ÿi´ÿʸÛÿúøüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëåòÿi´ÿh6ÿf3ÿf3ÿf3ÿf3ÿh6ÿi´ÿëåòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿåÜíÿV«ÿf3ÿf3ÿf3ÿf3ÿf3ÿf3ÿV«ÿåÜíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿåÜíÿV«ÿf3ÿf3ÿf3ÿf3ÿf3ÿf3ÿV«ÿåÜíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿåÜíÿV«ÿf3ÿf3ÿf3ÿf3ÿf3ÿf3ÿV«ÿåÜíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿåÜíÿV«ÿf3ÿf3ÿf3ÿf3ÿf3ÿf3ÿV«ÿåÜíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëåòÿi´ÿh6ÿf3ÿf3ÿf3ÿf3ÿh6ÿi´ÿëåòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúøüÿʸÛÿi´ÿV«ÿV«ÿV«ÿV«ÿi´ÿʸÛÿúøüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúøüÿëåòÿåÜíÿåÜíÿåÜíÿåÜíÿëåòÿúøüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ \ No newline at end of file
diff --git a/vello_common/assets/probe_drop_shadow.png b/vello_common/assets/probe_drop_shadow.png new file mode 100644 index 0000000..5098c6b --- /dev/null +++ b/vello_common/assets/probe_drop_shadow.png Binary files differ
diff --git a/vello_common/assets/probe_drop_shadow.rgba b/vello_common/assets/probe_drop_shadow.rgba new file mode 100644 index 0000000..248f1d3 --- /dev/null +++ b/vello_common/assets/probe_drop_shadow.rgba Binary files differ
diff --git a/vello_common/assets/probe_image_bicubic.png b/vello_common/assets/probe_image_bicubic.png new file mode 100644 index 0000000..8b6fc59 --- /dev/null +++ b/vello_common/assets/probe_image_bicubic.png Binary files differ
diff --git a/vello_common/assets/probe_image_bicubic.rgba b/vello_common/assets/probe_image_bicubic.rgba new file mode 100644 index 0000000..1815fe2 --- /dev/null +++ b/vello_common/assets/probe_image_bicubic.rgba Binary files differ
diff --git a/vello_common/assets/probe_gradient.png b/vello_common/assets/probe_linear_gradient.png similarity index 100% rename from vello_common/assets/probe_gradient.png rename to vello_common/assets/probe_linear_gradient.png Binary files differ
diff --git a/vello_common/assets/probe_gradient.rgba b/vello_common/assets/probe_linear_gradient.rgba similarity index 100% rename from vello_common/assets/probe_gradient.rgba rename to vello_common/assets/probe_linear_gradient.rgba Binary files differ
diff --git a/vello_common/assets/probe_radial_gradient.png b/vello_common/assets/probe_radial_gradient.png new file mode 100644 index 0000000..ff684ee --- /dev/null +++ b/vello_common/assets/probe_radial_gradient.png Binary files differ
diff --git a/vello_common/assets/probe_radial_gradient.rgba b/vello_common/assets/probe_radial_gradient.rgba new file mode 100644 index 0000000..4ca0719 --- /dev/null +++ b/vello_common/assets/probe_radial_gradient.rgba Binary files differ
diff --git a/vello_common/assets/probe_sweep_gradient.png b/vello_common/assets/probe_sweep_gradient.png new file mode 100644 index 0000000..8d328b1 --- /dev/null +++ b/vello_common/assets/probe_sweep_gradient.png Binary files differ
diff --git a/vello_common/assets/probe_sweep_gradient.rgba b/vello_common/assets/probe_sweep_gradient.rgba new file mode 100644 index 0000000..517d855 --- /dev/null +++ b/vello_common/assets/probe_sweep_gradient.rgba Binary files differ
diff --git a/vello_common/src/probe.rs b/vello_common/src/probe.rs index ff1c2e0..ea02158 100644 --- a/vello_common/src/probe.rs +++ b/vello_common/src/probe.rs
@@ -8,7 +8,7 @@ use crate::filter_effects::{EdgeMode, Filter, FilterPrimitive}; #[cfg(not(feature = "std"))] use crate::kurbo::common::FloatFuncs as _; -use crate::kurbo::{Affine, BezPath, Circle, Point, Rect, Shape}; +use crate::kurbo::{Affine, BezPath, Circle, Point, Rect, Shape, Vec2}; use crate::paint::{Image, ImageSource, PaintType}; use crate::peniko::{ BlendMode, ColorStop, ColorStops, Compose, Extend, Gradient, ImageAlphaType, ImageQuality, @@ -35,7 +35,7 @@ pub const ALL_PROBE_ELEMENTS: &[ProbeFeature] = &[ ProbeFeature::SolidRect, ProbeFeature::AlphaBlending, - ProbeFeature::Gradient, + ProbeFeature::LinearGradient, ProbeFeature::ImageNearest, ProbeFeature::Filter, ProbeFeature::ImageBilinear, @@ -43,6 +43,11 @@ ProbeFeature::Blending, ProbeFeature::Transformed, ProbeFeature::DepthBuffer, + ProbeFeature::DropShadow, + ProbeFeature::BlurredRoundedRect, + ProbeFeature::RadialGradient, + ProbeFeature::SweepGradient, + ProbeFeature::ImageBicubic, ]; /// Per-channel absolute tolerance used when comparing probe pixels. @@ -76,7 +81,7 @@ /// Alpha blending overlapping shapes. AlphaBlending, /// Drawing a linear gradient. - Gradient, + LinearGradient, /// Drawing an image with nearest-neighbor sampling. ImageNearest, /// Applying a filter effect. @@ -91,6 +96,16 @@ Transformed, /// Layering opaque draws and a transparent foreground to exercise depth buffering. DepthBuffer, + /// Applying an offset, blurred drop shadow to a shape. + DropShadow, + /// Drawing a blurred rounded rectangle. + BlurredRoundedRect, + /// Drawing a radial gradient. + RadialGradient, + /// Drawing a sweep gradient. + SweepGradient, + /// Drawing an image with bicubic sampling. + ImageBicubic, } /// Summary of the differences between one expected and actual probe cell. @@ -180,6 +195,7 @@ fn set_paint(&mut self, paint: PaintType); fn fill_path(&mut self, path: &BezPath); fn fill_rect(&mut self, rect: &Rect); + fn fill_blurred_rounded_rect(&mut self, rect: &Rect, radius: f32, std_dev: f32, invert: bool); fn push_layer(&mut self, blend_mode: Option<BlendMode>, opacity: Option<f32>); fn push_filter_layer(&mut self, filter: Filter); fn pop_layer(&mut self); @@ -229,7 +245,7 @@ match feature { ProbeFeature::SolidRect => include_bytes!("../assets/probe_solid_rect.rgba"), ProbeFeature::AlphaBlending => include_bytes!("../assets/probe_alpha_blending.rgba"), - ProbeFeature::Gradient => include_bytes!("../assets/probe_gradient.rgba"), + ProbeFeature::LinearGradient => include_bytes!("../assets/probe_linear_gradient.rgba"), ProbeFeature::ImageNearest => include_bytes!("../assets/probe_image_nearest.rgba"), ProbeFeature::Filter => include_bytes!("../assets/probe_filter.rgba"), ProbeFeature::ImageBilinear => include_bytes!("../assets/probe_image_bilinear.rgba"), @@ -237,6 +253,13 @@ ProbeFeature::Blending => include_bytes!("../assets/probe_blending.rgba"), ProbeFeature::Transformed => include_bytes!("../assets/probe_transformed.rgba"), ProbeFeature::DepthBuffer => include_bytes!("../assets/probe_depth_buffer.rgba"), + ProbeFeature::DropShadow => include_bytes!("../assets/probe_drop_shadow.rgba"), + ProbeFeature::BlurredRoundedRect => { + include_bytes!("../assets/probe_blurred_rounded_rect.rgba") + } + ProbeFeature::RadialGradient => include_bytes!("../assets/probe_radial_gradient.rgba"), + ProbeFeature::SweepGradient => include_bytes!("../assets/probe_sweep_gradient.rgba"), + ProbeFeature::ImageBicubic => include_bytes!("../assets/probe_image_bicubic.rgba"), } } @@ -327,7 +350,8 @@ pub fn draw_scene<T: ProbeRenderer>(ctx: &mut T, image: ImageSource, elements: &[ProbeFeature]) { let layout = GridLayout::from_elements(elements); let image_nearest = image_paint(image.clone(), ImageQuality::Low); - let image_bilinear = image_paint(image, ImageQuality::Medium); + let image_bilinear = image_paint(image.clone(), ImageQuality::Medium); + let image_bicubic = image_paint(image, ImageQuality::High); ctx.set_transform(Affine::IDENTITY); for (index, element) in elements.iter().copied().enumerate() { @@ -337,6 +361,7 @@ element, &image_nearest, &image_bilinear, + &image_bicubic, ); } } @@ -347,6 +372,7 @@ element: ProbeFeature, image_nearest: &PaintType, image_bilinear: &PaintType, + image_bicubic: &PaintType, ) { match element { ProbeFeature::SolidRect => { @@ -376,7 +402,7 @@ .to_path(PATH_TOLERANCE), ); } - ProbeFeature::Gradient => { + ProbeFeature::LinearGradient => { let rect = centered_rect(cell, RECT_SIZE, RECT_SIZE); ctx.set_paint(linear_gradient(&rect).into()); ctx.fill_rect(&rect); @@ -391,6 +417,35 @@ } ProbeFeature::Blending => draw_layered_difference_circles(ctx, cell), ProbeFeature::DepthBuffer => draw_depth_buffer_rects(ctx, cell), + ProbeFeature::DropShadow => draw_drop_shadow_rect(ctx, cell), + ProbeFeature::BlurredRoundedRect => { + ctx.set_paint(css::REBECCA_PURPLE.into()); + ctx.fill_blurred_rounded_rect(¢ered_rect(cell, 8.0, 8.0), 2.0, 0.75, false); + } + ProbeFeature::RadialGradient => { + let rect = centered_rect(cell, RECT_SIZE, RECT_SIZE); + let gradient = Gradient::new_radial(rect.center(), (RECT_SIZE * 0.5) as f32) + .with_stops([css::BLUE, css::RED]); + ctx.set_paint(gradient.into()); + ctx.fill_rect(&rect); + } + ProbeFeature::SweepGradient => { + let rect = centered_rect(cell, RECT_SIZE, RECT_SIZE); + let gradient = Gradient::new_sweep(rect.center(), 0.0, core::f32::consts::TAU) + .with_stops([css::BLUE, css::RED]); + ctx.set_paint(gradient.into()); + ctx.fill_rect(&rect); + } + ProbeFeature::ImageBicubic => { + let rect = centered_rect(cell, RECT_SIZE, RECT_SIZE); + ctx.set_paint(image_bicubic.clone()); + ctx.set_paint_transform( + Affine::translate((rect.x0, rect.y0)) + * Affine::scale(RECT_SIZE / IMAGE_SOURCE_SIZE), + ); + ctx.fill_rect(&rect); + ctx.reset_paint_transform(); + } } } @@ -439,6 +494,24 @@ ctx.pop_layer(); } +fn draw_drop_shadow_rect(ctx: &mut impl ProbeRenderer, cell: Rect) { + let offset = 1.5; + let std_deviation = 0.5; + let centering_offset = f64::from(offset) * 0.5 + f64::from(std_deviation); + let rect = centered_rect(cell, 8.0, 8.0) - Vec2::new(centering_offset, centering_offset); + let shadow = Filter::from_primitive(FilterPrimitive::DropShadow { + dx: offset, + dy: offset, + std_deviation, + color: css::BLACK.with_alpha(0.75), + edge_mode: EdgeMode::None, + }); + ctx.push_filter_layer(shadow); + ctx.set_paint(css::BLUE.into()); + ctx.fill_rect(&rect); + ctx.pop_layer(); +} + fn draw_opacity_layer_rect(ctx: &mut impl ProbeRenderer, rect: Rect) { ctx.push_layer(None, Some(0.5)); ctx.set_paint(css::ORANGE_RED.into());
diff --git a/vello_gpu/src/render/webgl/probe.rs b/vello_gpu/src/render/webgl/probe.rs index e648e90..1357e3c 100644 --- a/vello_gpu/src/render/webgl/probe.rs +++ b/vello_gpu/src/render/webgl/probe.rs
@@ -335,6 +335,10 @@ Self::fill_rect(self, rect); } + fn fill_blurred_rounded_rect(&mut self, rect: &Rect, radius: f32, std_dev: f32, invert: bool) { + Self::fill_blurred_rounded_rect(self, rect, radius, std_dev, invert); + } + fn push_layer(&mut self, blend_mode: Option<BlendMode>, opacity: Option<f32>) { Self::push_layer(self, None, blend_mode, opacity, None, None); }
diff --git a/vello_tests/src/regenerate_probe_reference.rs b/vello_tests/src/regenerate_probe_reference.rs index 0c6ed74..ca01cae 100644 --- a/vello_tests/src/regenerate_probe_reference.rs +++ b/vello_tests/src/regenerate_probe_reference.rs
@@ -23,7 +23,7 @@ let name = match element { probe::ProbeFeature::SolidRect => "probe_solid_rect", probe::ProbeFeature::AlphaBlending => "probe_alpha_blending", - probe::ProbeFeature::Gradient => "probe_gradient", + probe::ProbeFeature::LinearGradient => "probe_linear_gradient", probe::ProbeFeature::ImageNearest => "probe_image_nearest", probe::ProbeFeature::Filter => "probe_filter", probe::ProbeFeature::ImageBilinear => "probe_image_bilinear", @@ -31,6 +31,11 @@ probe::ProbeFeature::Blending => "probe_blending", probe::ProbeFeature::Transformed => "probe_transformed", probe::ProbeFeature::DepthBuffer => "probe_depth_buffer", + probe::ProbeFeature::DropShadow => "probe_drop_shadow", + probe::ProbeFeature::BlurredRoundedRect => "probe_blurred_rounded_rect", + probe::ProbeFeature::RadialGradient => "probe_radial_gradient", + probe::ProbeFeature::SweepGradient => "probe_sweep_gradient", + probe::ProbeFeature::ImageBicubic => "probe_image_bicubic", }; PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("../vello_common/assets") @@ -56,6 +61,11 @@ self.0.fill_rect(rect); } + fn fill_blurred_rounded_rect(&mut self, rect: &Rect, radius: f32, std_dev: f32, invert: bool) { + self.0 + .fill_blurred_rounded_rect(rect, radius, std_dev, invert); + } + fn push_layer(&mut self, blend_mode: Option<BlendMode>, opacity: Option<f32>) { self.0.push_layer(None, blend_mode, opacity, None, None); } @@ -161,7 +171,7 @@ fn probe_failure_reports_statistics_per_cell() { let elements = [ probe::ProbeFeature::SolidRect, - probe::ProbeFeature::Gradient, + probe::ProbeFeature::LinearGradient, ]; let mut actual = render_probe_pixmap(&elements); actual.set_pixel(0, 0, css::BLACK.premultiply().to_rgba8()); @@ -173,7 +183,7 @@ assert_eq!(statistics.len(), 2); assert_eq!(statistics[0].feature, probe::ProbeFeature::SolidRect); assert_eq!(statistics[0].different_pixel_count, 1); - assert_eq!(statistics[1].feature, probe::ProbeFeature::Gradient); + assert_eq!(statistics[1].feature, probe::ProbeFeature::LinearGradient); assert_eq!(statistics[1].different_pixel_count, 0); } @@ -192,7 +202,7 @@ fn full_probe_row_matches_reference() { assert_elements_match_reference(&[ probe::ProbeFeature::SolidRect, - probe::ProbeFeature::Gradient, + probe::ProbeFeature::LinearGradient, probe::ProbeFeature::DepthBuffer, ]); }