From b9b880a5deff2acda1aa36415ecfa64115edb2e6 Mon Sep 17 00:00:00 2001 From: bflatastic Date: Sat, 10 Oct 2026 09:46:43 +0700 Subject: [PATCH] Review fixes for #765: the glow outside a shape keeps the edge's colour The output multiplied the glow's colour by its opacity a second time, so outside the shape (where the glow sets the opacity) it darkened as it faded and showed as a grey rim over a light background. The test now checks that the fading glow keeps the edge's colour. Co-Authored-By: Claude Opus 5.5 --- crates/effects/src/pixel/edges.rs | 8 +++++--- crates/effects/src/pixel/tests.rs | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/crates/effects/src/pixel/edges.rs b/crates/effects/src/pixel/edges.rs index d63b2421..25812fff 100644 --- a/crates/effects/src/pixel/edges.rs +++ b/crates/effects/src/pixel/edges.rs @@ -74,11 +74,13 @@ pub(super) fn glow(px: &mut [[u8; 4]], w: usize, h: usize, width: f64, brightnes let glow = if peak > 0.0 { (edge / peak * brightness as f32 / 6.0).clamp(0.0, 1.0) } else { 0.0 }; let colour_weight = colours[0][index].max(colours[1][index]).max(colours[2][index]); let straight = if colour_weight > 1e-6 { std::array::from_fn(|channel| colours[channel][index] / colour_weight) } else { [0.0; 3] }; + // Premultiplied: the glow is light of the edge's colour, so outside the shape it keeps that + // colour at the glow's opacity instead of darkening as it fades. let a = alpha.max(glow); *out = [ - (straight[0] * glow * a * 255.0).round().clamp(0.0, 255.0) as u8, - (straight[1] * glow * a * 255.0).round().clamp(0.0, 255.0) as u8, - (straight[2] * glow * a * 255.0).round().clamp(0.0, 255.0) as u8, + (straight[0] * glow * 255.0).round().clamp(0.0, 255.0) as u8, + (straight[1] * glow * 255.0).round().clamp(0.0, 255.0) as u8, + (straight[2] * glow * 255.0).round().clamp(0.0, 255.0) as u8, (a * 255.0).round() as u8, ]; } diff --git a/crates/effects/src/pixel/tests.rs b/crates/effects/src/pixel/tests.rs index 883a5cbc..92768009 100644 --- a/crates/effects/src/pixel/tests.rs +++ b/crates/effects/src/pixel/tests.rs @@ -155,6 +155,8 @@ fn glowing_edges_defaults_keep_the_outline_bright_and_use_source_colour() { let outside = at(&out, w, 3, 8); assert_eq!(outside[1], 0, "transparent halo must not be grey: {outside:?}"); assert_eq!(outside[2], 0, "transparent halo must retain source hue: {outside:?}"); + // The glow outside keeps the edge's colour as it fades, rather than darkening towards grey. + assert!(outside[3] > 0 && u32::from(outside[0]) * 255 >= 240 * u32::from(outside[3]), "{outside:?}"); assert!(out.as_chunks::<4>().0.iter().all(|p| p[0] <= p[3] && p[1] <= p[3] && p[2] <= p[3])); }