Fix panic when sampling across two coincident gradient stops (#6166)

This commit is contained in:
+merlan #flirora 2025-06-27 05:26:15 -04:00 committed by GitHub
parent b9f3a95e03
commit 584dd5fec6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 33 additions and 14 deletions

View File

@ -1285,24 +1285,17 @@ fn process_stops(stops: &[Spanned<GradientStop>]) -> SourceResult<Vec<(Color, Ra
/// Sample the stops at a given position. /// Sample the stops at a given position.
fn sample_stops(stops: &[(Color, Ratio)], mixing_space: ColorSpace, t: f64) -> Color { fn sample_stops(stops: &[(Color, Ratio)], mixing_space: ColorSpace, t: f64) -> Color {
let t = t.clamp(0.0, 1.0); let t = t.clamp(0.0, 1.0);
let mut low = 0; let mut j = stops.partition_point(|(_, ratio)| ratio.get() < t);
let mut high = stops.len();
while low < high { if j == 0 {
let mid = (low + high) / 2; while stops.get(j + 1).is_some_and(|(_, r)| r.is_zero()) {
if stops[mid].1.get() < t { j += 1;
low = mid + 1;
} else {
high = mid;
} }
return stops[j].0;
} }
if low == 0 { let (col_0, pos_0) = stops[j - 1];
low = 1; let (col_1, pos_1) = stops[j];
}
let (col_0, pos_0) = stops[low - 1];
let (col_1, pos_1) = stops[low];
let t = (t - pos_0.get()) / (pos_1.get() - pos_0.get()); let t = (t - pos_0.get()) / (pos_1.get() - pos_0.get());
Color::mix_iter( Color::mix_iter(

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 B

View File

@ -666,3 +666,29 @@ $ A = mat(
#let _ = gradient.linear(..my-gradient.stops()) #let _ = gradient.linear(..my-gradient.stops())
#let my-gradient2 = gradient.linear(red, blue).repeat(5, mirror: true) #let my-gradient2 = gradient.linear(red, blue).repeat(5, mirror: true)
#let _ = gradient.linear(..my-gradient2.stops()) #let _ = gradient.linear(..my-gradient2.stops())
--- issue-6162-coincident-gradient-stops-export-png ---
// Ensure that multiple gradient stops with the same position
// don't cause a panic.
#rect(
fill: gradient.linear(
(red, 0%),
(green, 0%),
(blue, 100%),
)
)
#rect(
fill: gradient.linear(
(red, 0%),
(green, 100%),
(blue, 100%),
)
)
#rect(
fill: gradient.linear(
(white, 0%),
(red, 50%),
(green, 50%),
(blue, 100%),
)
)