From 9687c0ffc001c57240fe3acdde91c1a41ac3e551 Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Thu, 15 Oct 2026 11:12:25 +0000 Subject: [PATCH] Draw layer blurs up to the documented 10,000 radius Fixes #430 Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Opus 5.5 --- crates/render/src/effects_behaviour_tests.rs | 26 ++++++++++++++++++++ crates/render/src/fx.rs | 7 ++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/crates/render/src/effects_behaviour_tests.rs b/crates/render/src/effects_behaviour_tests.rs index 3feaf077..5a4b6289 100644 --- a/crates/render/src/effects_behaviour_tests.rs +++ b/crates/render/src/effects_behaviour_tests.rs @@ -377,3 +377,29 @@ fn exports_include_what_effects_paint_outside_the_layer() { d.get_mut(f).unwrap().effects = vec![fx(EffectKind::DropShadow(sharp((0.0, 10.0), 0.0)))]; assert!(render_node(&d, f, 1.0).unwrap().height() >= 50, "frame shadow exported"); } + +/// A black 200 × 200 frame with a uniform layer blur of `radius`, drawn on a 512 × 512 view at 1×. +fn blurred_frame(radius: f64) -> Pixmap { + let mut d = Document::new("Blur range"); + let p = d.first_page().unwrap(); + let f = d.create(p, NodeKind::Frame, "Square", 156.0, 156.0, 200.0, 200.0).unwrap(); + let n = d.get_mut(f).unwrap(); + n.fills = vec![Paint::solid(Color::BLACK)]; + n.effects = vec![fx(EffectKind::LayerBlur(Blur::uniform(radius)))]; + let view = View { origin: (0.0, 0.0), scale: 1.0, width: 512, height: 512 }; + render_view(&d, p, &view, &Options::default()).unwrap() +} + +#[test] +fn layer_blur_radii_up_to_the_documented_limit_all_draw() { + // The documented blur range runs to 10,000: a larger radius in it blurs further, it doesn't + // stop at some smaller one. + let differ = |a: &Pixmap, b: &Pixmap| a.data().chunks_exact(4).zip(b.data().chunks_exact(4)).filter(|(a, b)| a != b).count(); + let sharp = blurred_frame(0.0); + let small = blurred_frame(100.0); + let medium = blurred_frame(1_000.0); + let large = blurred_frame(10_000.0); + assert!(differ(&sharp, &small) > 0, "radius 0 draws the sharp shape"); + assert!(differ(&small, &medium) > 0, "100 vs 1000"); + assert!(differ(&medium, &large) > 0, "radii 1000 and 10000 draw the same pixels"); +} diff --git a/crates/render/src/fx.rs b/crates/render/src/fx.rs index 8c769134..5d65667c 100644 --- a/crates/render/src/fx.rs +++ b/crates/render/src/fx.rs @@ -70,8 +70,11 @@ fn transpose(src: &[u8], dst: &mut [u8], w: usize, h: usize) { } } -/// The largest blur standard deviation drawn (pixels): wider blurs look the same. -pub const MAX_SIGMA: f64 = 500.0; +/// The largest blur standard deviation drawn (pixels): far wider than any layer (at most 16,384 +/// pixels a side), so wider blurs look the same (everything averages out to nothing). The box +/// passes cost the same at any radius, so the documented blur radii (up to 10,000 units) draw +/// in full at any zoom. +pub const MAX_SIGMA: f64 = 1_000_000.0; /// Gaussian-like blur of the whole pixmap with standard deviation `sigma` (pixels). pub fn blur(p: &mut Pixmap, sigma: f64) {