Gradient::repeat: Fix floating-point error in stop calculation (#5837)

This commit is contained in:
+merlan #flirora 2025-02-12 07:38:40 -05:00 committed by GitHub
parent 83ad407d3c
commit 02cd43e27f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 11 additions and 4 deletions

View File

@ -582,12 +582,11 @@ impl Gradient {
let mut stops = stops let mut stops = stops
.iter() .iter()
.map(move |&(color, offset)| { .map(move |&(color, offset)| {
let t = i as f64 / n as f64;
let r = offset.get(); let r = offset.get();
if i % 2 == 1 && mirror { if i % 2 == 1 && mirror {
(color, Ratio::new(t + (1.0 - r) / n as f64)) (color, Ratio::new((i as f64 + 1.0 - r) / n as f64))
} else { } else {
(color, Ratio::new(t + r / n as f64)) (color, Ratio::new((i as f64 + r) / n as f64))
} }
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -1230,7 +1229,7 @@ fn process_stops(stops: &[Spanned<GradientStop>]) -> SourceResult<Vec<(Color, Ra
}; };
if stop.get() < last_stop { if stop.get() < last_stop {
bail!(*span, "offsets must be in strictly monotonic order"); bail!(*span, "offsets must be in monotonic order");
} }
last_stop = stop.get(); last_stop = stop.get();

View File

@ -658,3 +658,11 @@ $ A = mat(
height: 10pt, height: 10pt,
fill: gradient.linear(violet, blue, space: cmyk) fill: gradient.linear(violet, blue, space: cmyk)
) )
--- issue-5819-gradient-repeat ---
// Ensure the gradient constructor generates monotonic stops which can be fed
// back into the gradient constructor itself.
#let my-gradient = gradient.linear(red, blue).repeat(5)
#let _ = gradient.linear(..my-gradient.stops())
#let my-gradient2 = gradient.linear(red, blue).repeat(5, mirror: true)
#let _ = gradient.linear(..my-gradient2.stops())