From 1cdcbb25fa990cbeb773798ea6c872df4d2bcda6 Mon Sep 17 00:00:00 2001 From: pylbrecht Date: Sat, 7 Dec 2019 17:07:21 +0100 Subject: [PATCH] Handle overlapping gradient stops for linear gradients From `addColorStop(offset, color)`s spec: If multiple stops are added at the same offset on a gradient, they must be placed in the order added, with the first one closest to the start of the gradient, and each subsequent one infinitesimally further along towards the end point (in effect causing all but the first and last stop added at each point to be ignored) https://www.w3.org/html/test/results/2dcontext/annotated-spec/canvas.html#testrefs.2d.gradient.interpolate.overlapu --- components/canvas/raqote_backend.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/components/canvas/raqote_backend.rs b/components/canvas/raqote_backend.rs index 01eaa15632c..7905af3b2a1 100644 --- a/components/canvas/raqote_backend.rs +++ b/components/canvas/raqote_backend.rs @@ -243,15 +243,19 @@ impl GenericDrawTarget for raqote::DrawTarget { dt.get_data_mut().copy_from_slice(s); raqote::DrawTarget::copy_surface(self, &dt, source.to_box2d(), destination); } + // TODO(pylbrecht) + // unused code? fn create_gradient_stops( &self, gradient_stops: Vec, _extend_mode: ExtendMode, ) -> GradientStops { - let stops = gradient_stops + let mut stops = gradient_stops .into_iter() .map(|item| item.as_raqote().clone()) - .collect(); + .collect::>(); + // https://www.w3.org/html/test/results/2dcontext/annotated-spec/canvas.html#testrefs.2d.gradient.interpolate.overlap + stops.sort_by(|a, b| a.position.partial_cmp(&b.position).unwrap()); GradientStops::Raqote(stops) } fn create_path_builder(&self) -> Box { @@ -730,7 +734,10 @@ impl<'a> ToRaqoteSource<'a> for FillOrStrokeStyle { rgba.blue, ))), LinearGradient(style) => { - let stops = style.stops.into_iter().map(|s| s.to_raqote()).collect(); + let mut stops: Vec = + style.stops.into_iter().map(|s| s.to_raqote()).collect(); + // https://www.w3.org/html/test/results/2dcontext/annotated-spec/canvas.html#testrefs.2d.gradient.interpolate.overlap + stops.sort_by(|a, b| a.position.partial_cmp(&b.position).unwrap()); let mut gradient = raqote::Gradient { stops }; let start = Point2D::new(style.x0 as f32, style.y0 as f32); let end = Point2D::new(style.x1 as f32, style.y1 as f32);