diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index e9d7f02bad3..8e1d10424db 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -592,36 +592,42 @@ impl FragmentDisplayListBuilding for Fragment { let mut clip = clip.clone(); clip.intersect_rect(absolute_bounds); - // This is the distance between the center and the ending point; i.e. half of the distance - // between the starting point and the ending point. - let delta = match gradient.angle_or_corner { - AngleOrCorner::Angle(angle) => { - // Get correct gradient line length, based on: - // https://drafts.csswg.org/css-images-3/#linear-gradients - let dir = Point2D::new(angle.radians().sin(), -angle.radians().cos()); - let line_length = (dir.x * absolute_bounds.size.width.to_f32_px()).abs() + - (dir.y * absolute_bounds.size.height.to_f32_px()).abs(); - - let inv_dir_length = 1.0 / (dir.x * dir.x + dir.y * dir.y).sqrt(); - - Point2D::new(Au::from_f32_px(dir.x * inv_dir_length * line_length / 2.0), - Au::from_f32_px(dir.y * inv_dir_length * line_length / 2.0)) - } + let angle = match gradient.angle_or_corner { + AngleOrCorner::Angle(angle) => angle.radians(), AngleOrCorner::Corner(horizontal, vertical) => { - let x_factor = match horizontal { - HorizontalDirection::Left => -1, - HorizontalDirection::Right => 1, - }; - let y_factor = match vertical { - VerticalDirection::Top => -1, - VerticalDirection::Bottom => 1, - }; - Point2D::new(absolute_bounds.size.width * x_factor / 2, - absolute_bounds.size.height * y_factor / 2) + // This the angle for one of the diagonals of the box. Our angle + // will either be this one, this one + PI, or one of the other + // two perpendicular angles. + let atan = (absolute_bounds.size.height.to_f32_px() / + absolute_bounds.size.width.to_f32_px()).atan(); + match (horizontal, vertical) { + (HorizontalDirection::Right, VerticalDirection::Bottom) + => f32::consts::PI - atan, + (HorizontalDirection::Left, VerticalDirection::Bottom) + => f32::consts::PI + atan, + (HorizontalDirection::Right, VerticalDirection::Top) + => atan, + (HorizontalDirection::Left, VerticalDirection::Top) + => -atan, + } } }; + // Get correct gradient line length, based on: + // https://drafts.csswg.org/css-images-3/#linear-gradients + let dir = Point2D::new(angle.sin(), -angle.cos()); + + let line_length = (dir.x * absolute_bounds.size.width.to_f32_px()).abs() + + (dir.y * absolute_bounds.size.height.to_f32_px()).abs(); + + let inv_dir_length = 1.0 / (dir.x * dir.x + dir.y * dir.y).sqrt(); + + // This is the vector between the center and the ending point; i.e. half + // of the distance between the starting point and the ending point. + let delta = Point2D::new(Au::from_f32_px(dir.x * inv_dir_length * line_length / 2.0), + Au::from_f32_px(dir.y * inv_dir_length * line_length / 2.0)); + // This is the length of the gradient line. let length = Au::from_f32_px( (delta.x.to_f32_px() * 2.0).hypot(delta.y.to_f32_px() * 2.0)); @@ -629,7 +635,8 @@ impl FragmentDisplayListBuilding for Fragment { // Determine the position of each stop per CSS-IMAGES ยง 3.4. // // FIXME(#3908, pcwalton): Make sure later stops can't be behind earlier stops. - let (mut stops, mut stop_run) = (Vec::new(), None); + let mut stops = Vec::with_capacity(gradient.stops.len()); + let mut stop_run = None; for (i, stop) in gradient.stops.iter().enumerate() { let offset = match stop.position { None => { diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index 784c0ba7451..05e8dc4ad7e 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -3120,6 +3120,18 @@ "url": "/_mozilla/css/linear_gradients_lengths_a.html" } ], + "css/linear_gradients_non_square_a.html": [ + { + "path": "css/linear_gradients_non_square_a.html", + "references": [ + [ + "/_mozilla/css/linear_gradients_non_square_ref.html", + "==" + ] + ], + "url": "/_mozilla/css/linear_gradients_non_square_a.html" + } + ], "css/linear_gradients_parsing_a.html": [ { "path": "css/linear_gradients_parsing_a.html", @@ -10124,6 +10136,18 @@ "url": "/_mozilla/css/linear_gradients_lengths_a.html" } ], + "css/linear_gradients_non_square_a.html": [ + { + "path": "css/linear_gradients_non_square_a.html", + "references": [ + [ + "/_mozilla/css/linear_gradients_non_square_ref.html", + "==" + ] + ], + "url": "/_mozilla/css/linear_gradients_non_square_a.html" + } + ], "css/linear_gradients_parsing_a.html": [ { "path": "css/linear_gradients_parsing_a.html", diff --git a/tests/wpt/mozilla/tests/css/linear_gradients_non_square_a.html b/tests/wpt/mozilla/tests/css/linear_gradients_non_square_a.html new file mode 100644 index 00000000000..2edd6cbaa46 --- /dev/null +++ b/tests/wpt/mozilla/tests/css/linear_gradients_non_square_a.html @@ -0,0 +1,29 @@ + + +