From c73699374f6f99cda5f3f02fde7028fd6d45ed36 Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Sun, 8 Nov 2026 12:49:47 +0000 Subject: [PATCH] Clamp midpoint in Gradient::expanded_stops like sample does Found while testing crates/color/src/gradient.rs:~101-110 (expanded_stops); the unclamped value comes from crates/idml/src/import/swatches.rs:128-129 Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/color/src/gradient.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/crates/color/src/gradient.rs b/crates/color/src/gradient.rs index 6243101ef..29f710627 100644 --- a/crates/color/src/gradient.rs +++ b/crates/color/src/gradient.rs @@ -100,10 +100,11 @@ impl Gradient { let mut out = Vec::new(); for (i, s) in self.stops.iter().enumerate() { out.push((s.offset, s.color, s.opacity)); + let mid = s.midpoint.clamp(0.01, 0.99); if let Some(n) = self.stops.get(i + 1) - && (s.midpoint - 0.5).abs() > 1e-3 + && (mid - 0.5).abs() > 1e-3 { - let t = s.offset + (n.offset - s.offset) * s.midpoint; + let t = s.offset + (n.offset - s.offset) * mid; let (c, o) = self.sample(t); out.push((t, c, o)); } @@ -217,6 +218,17 @@ impl GradientPaint { mod tests { use super::*; + #[test] + fn expanded_stops_clamp_out_of_range_midpoint() { + for mid in [2.0, -1.0] { + let mut g = Gradient::default(); + g.stops[0].midpoint = mid; + let offsets: Vec = g.expanded_stops().iter().map(|s| s.0).collect(); + assert!(offsets.windows(2).all(|w| w[0] <= w[1]), "{offsets:?}"); + assert!(offsets.iter().all(|o| (0.0..=1.0).contains(o)), "{offsets:?}"); + } + } + #[test] fn sample_endpoints_and_mid() { let g = Gradient::default();