mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Auto merge of #14598 - DominoTree:master, r=canaltinova
Fix linear gradient's specified form #13892 <!-- Please describe your changes on the following line: --> WIP for #13892 --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #13892 (github issue number if applicable). <!-- Either: --> - [x] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/14598) <!-- Reviewable:end -->
This commit is contained in:
commit
9d2b98e6f8
6 changed files with 113 additions and 49 deletions
|
@ -54,8 +54,8 @@ use style::properties::{self, ServoComputedValues};
|
||||||
use style::properties::style_structs;
|
use style::properties::style_structs;
|
||||||
use style::servo::restyle_damage::REPAINT;
|
use style::servo::restyle_damage::REPAINT;
|
||||||
use style::values::{self, Either, RGBA, computed};
|
use style::values::{self, Either, RGBA, computed};
|
||||||
use style::values::computed::{Gradient, GradientKind, LengthOrPercentage, LengthOrPercentageOrAuto};
|
use style::values::computed::{AngleOrCorner, Gradient, GradientKind, LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||||
use style::values::specified::{AngleOrCorner, HorizontalDirection, VerticalDirection};
|
use style::values::specified::{HorizontalDirection, VerticalDirection};
|
||||||
use style_traits::cursor::Cursor;
|
use style_traits::cursor::Cursor;
|
||||||
use table_cell::CollapsedBordersForCell;
|
use table_cell::CollapsedBordersForCell;
|
||||||
use webrender_traits::{ColorF, GradientStop};
|
use webrender_traits::{ColorF, GradientStop};
|
||||||
|
|
|
@ -160,10 +160,9 @@ impl nsStyleImage {
|
||||||
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE, NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE};
|
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE, NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE};
|
||||||
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER, NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE};
|
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER, NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE};
|
||||||
use gecko_bindings::structs::nsStyleCoord;
|
use gecko_bindings::structs::nsStyleCoord;
|
||||||
use values::computed::{GradientKind, GradientShape, LengthOrKeyword};
|
use values::computed::{AngleOrCorner, GradientKind, GradientShape, LengthOrKeyword};
|
||||||
use values::computed::LengthOrPercentageOrKeyword;
|
use values::computed::LengthOrPercentageOrKeyword;
|
||||||
use values::specified::{AngleOrCorner, HorizontalDirection};
|
use values::specified::{HorizontalDirection, SizeKeyword, VerticalDirection};
|
||||||
use values::specified::{SizeKeyword, VerticalDirection};
|
|
||||||
|
|
||||||
let stop_count = gradient.stops.len();
|
let stop_count = gradient.stops.len();
|
||||||
if stop_count >= ::std::u32::MAX as usize {
|
if stop_count >= ::std::u32::MAX as usize {
|
||||||
|
|
|
@ -8,11 +8,12 @@
|
||||||
//! [image]: https://drafts.csswg.org/css-images/#image-values
|
//! [image]: https://drafts.csswg.org/css-images/#image-values
|
||||||
|
|
||||||
use cssparser::Color as CSSColor;
|
use cssparser::Color as CSSColor;
|
||||||
|
use std::f32::consts::PI;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use values::computed::{Context, Length, LengthOrPercentage, ToComputedValue};
|
use values::computed::{Angle, Context, Length, LengthOrPercentage, ToComputedValue};
|
||||||
use values::computed::position::Position;
|
use values::computed::position::Position;
|
||||||
use values::specified::{self, AngleOrCorner, SizeKeyword};
|
use values::specified::{self, HorizontalDirection, SizeKeyword, VerticalDirection};
|
||||||
use values::specified::url::SpecifiedUrl;
|
use values::specified::url::SpecifiedUrl;
|
||||||
|
|
||||||
|
|
||||||
|
@ -185,7 +186,7 @@ impl ToComputedValue for specified::GradientKind {
|
||||||
fn to_computed_value(&self, context: &Context) -> GradientKind {
|
fn to_computed_value(&self, context: &Context) -> GradientKind {
|
||||||
match *self {
|
match *self {
|
||||||
specified::GradientKind::Linear(angle_or_corner) => {
|
specified::GradientKind::Linear(angle_or_corner) => {
|
||||||
GradientKind::Linear(angle_or_corner)
|
GradientKind::Linear(angle_or_corner.to_computed_value(context))
|
||||||
},
|
},
|
||||||
specified::GradientKind::Radial(ref shape, position) => {
|
specified::GradientKind::Radial(ref shape, position) => {
|
||||||
GradientKind::Radial(shape.to_computed_value(context),
|
GradientKind::Radial(shape.to_computed_value(context),
|
||||||
|
@ -454,3 +455,75 @@ impl ToComputedValue for specified::LengthOrPercentageOrKeyword {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
pub enum AngleOrCorner {
|
||||||
|
Angle(Angle),
|
||||||
|
Corner(HorizontalDirection, VerticalDirection)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToComputedValue for specified::AngleOrCorner {
|
||||||
|
type ComputedValue = AngleOrCorner;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn to_computed_value(&self, _: &Context) -> AngleOrCorner {
|
||||||
|
match *self {
|
||||||
|
specified::AngleOrCorner::None => {
|
||||||
|
AngleOrCorner::Angle(Angle(0.0))
|
||||||
|
},
|
||||||
|
specified::AngleOrCorner::Angle(angle) => {
|
||||||
|
AngleOrCorner::Angle(angle)
|
||||||
|
},
|
||||||
|
specified::AngleOrCorner::Corner(horizontal, vertical) => {
|
||||||
|
match (horizontal, vertical) {
|
||||||
|
(None, Some(VerticalDirection::Top)) => {
|
||||||
|
AngleOrCorner::Angle(Angle(0.0))
|
||||||
|
},
|
||||||
|
(Some(HorizontalDirection::Right), None) => {
|
||||||
|
AngleOrCorner::Angle(Angle(PI * 0.5))
|
||||||
|
},
|
||||||
|
(None, Some(VerticalDirection::Bottom)) => {
|
||||||
|
AngleOrCorner::Angle(Angle(PI))
|
||||||
|
},
|
||||||
|
(Some(HorizontalDirection::Left), None) => {
|
||||||
|
AngleOrCorner::Angle(Angle(PI * 1.5))
|
||||||
|
},
|
||||||
|
(Some(horizontal), Some(vertical)) => {
|
||||||
|
AngleOrCorner::Corner(horizontal, vertical)
|
||||||
|
},
|
||||||
|
(None, None) => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn from_computed_value(computed: &AngleOrCorner) -> Self {
|
||||||
|
match *computed {
|
||||||
|
AngleOrCorner::Angle(angle) => {
|
||||||
|
specified::AngleOrCorner::Angle(angle)
|
||||||
|
},
|
||||||
|
AngleOrCorner::Corner(horizontal, vertical) => {
|
||||||
|
specified::AngleOrCorner::Corner(Some(horizontal), Some(vertical))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for AngleOrCorner {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match *self {
|
||||||
|
AngleOrCorner::Angle(angle) => angle.to_css(dest),
|
||||||
|
AngleOrCorner::Corner(horizontal, vertical) => {
|
||||||
|
try!(dest.write_str("to "));
|
||||||
|
try!(horizontal.to_css(dest));
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
try!(vertical.to_css(dest));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use style_traits::ToCss;
|
||||||
use super::{CSSFloat, specified};
|
use super::{CSSFloat, specified};
|
||||||
|
|
||||||
pub use cssparser::Color as CSSColor;
|
pub use cssparser::Color as CSSColor;
|
||||||
pub use self::image::{EndingShape as GradientShape, Gradient, GradientKind, Image};
|
pub use self::image::{AngleOrCorner, EndingShape as GradientShape, Gradient, GradientKind, Image};
|
||||||
pub use self::image::{LengthOrKeyword, LengthOrPercentageOrKeyword};
|
pub use self::image::{LengthOrKeyword, LengthOrPercentageOrKeyword};
|
||||||
pub use super::{Either, None_};
|
pub use super::{Either, None_};
|
||||||
pub use super::specified::{Angle, BorderStyle, GridLine, Time, UrlOrNone};
|
pub use super::specified::{Angle, BorderStyle, GridLine, Time, UrlOrNone};
|
||||||
|
|
|
@ -10,10 +10,8 @@
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::f32::consts::PI;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use values::computed::ComputedValueAsSpecified;
|
|
||||||
use values::specified::{Angle, CSSColor, Length, LengthOrPercentage};
|
use values::specified::{Angle, CSSColor, Length, LengthOrPercentage};
|
||||||
use values::specified::position::Position;
|
use values::specified::position::Position;
|
||||||
use values::specified::url::{SpecifiedUrl, UrlExtraData};
|
use values::specified::url::{SpecifiedUrl, UrlExtraData};
|
||||||
|
@ -70,10 +68,14 @@ impl ToCss for Gradient {
|
||||||
if self.repeating {
|
if self.repeating {
|
||||||
try!(dest.write_str("repeating-"));
|
try!(dest.write_str("repeating-"));
|
||||||
}
|
}
|
||||||
|
let mut skipcomma = false;
|
||||||
match self.gradient_kind {
|
match self.gradient_kind {
|
||||||
GradientKind::Linear(angle_or_corner) => {
|
GradientKind::Linear(angle_or_corner) => {
|
||||||
try!(dest.write_str("linear-gradient("));
|
try!(dest.write_str("linear-gradient("));
|
||||||
try!(angle_or_corner.to_css(dest));
|
try!(angle_or_corner.to_css(dest));
|
||||||
|
if angle_or_corner == AngleOrCorner::None {
|
||||||
|
skipcomma = true;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
GradientKind::Radial(ref shape, position) => {
|
GradientKind::Radial(ref shape, position) => {
|
||||||
try!(dest.write_str("radial-gradient("));
|
try!(dest.write_str("radial-gradient("));
|
||||||
|
@ -83,7 +85,11 @@ impl ToCss for Gradient {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for stop in &self.stops {
|
for stop in &self.stops {
|
||||||
try!(dest.write_str(", "));
|
if !skipcomma {
|
||||||
|
try!(dest.write_str(", "));
|
||||||
|
} else {
|
||||||
|
skipcomma = false;
|
||||||
|
}
|
||||||
try!(stop.to_css(dest));
|
try!(stop.to_css(dest));
|
||||||
}
|
}
|
||||||
dest.write_str(")")
|
dest.write_str(")")
|
||||||
|
@ -230,18 +236,28 @@ fn parse_position(context: &ParserContext, input: &mut Parser) -> Result<Positio
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub enum AngleOrCorner {
|
pub enum AngleOrCorner {
|
||||||
Angle(Angle),
|
Angle(Angle),
|
||||||
Corner(HorizontalDirection, VerticalDirection),
|
Corner(Option<HorizontalDirection>, Option<VerticalDirection>),
|
||||||
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for AngleOrCorner {
|
impl ToCss for AngleOrCorner {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
match *self {
|
match *self {
|
||||||
|
AngleOrCorner::None => Ok(()),
|
||||||
AngleOrCorner::Angle(angle) => angle.to_css(dest),
|
AngleOrCorner::Angle(angle) => angle.to_css(dest),
|
||||||
AngleOrCorner::Corner(horizontal, vertical) => {
|
AngleOrCorner::Corner(horizontal, vertical) => {
|
||||||
try!(dest.write_str("to "));
|
try!(dest.write_str("to "));
|
||||||
try!(horizontal.to_css(dest));
|
let mut horizontal_present = false;
|
||||||
try!(dest.write_str(" "));
|
if let Some(horizontal) = horizontal {
|
||||||
try!(vertical.to_css(dest));
|
try!(horizontal.to_css(dest));
|
||||||
|
horizontal_present = true;
|
||||||
|
}
|
||||||
|
if let Some(vertical) = vertical {
|
||||||
|
if horizontal_present {
|
||||||
|
try!(dest.write_str(" "));
|
||||||
|
}
|
||||||
|
try!(vertical.to_css(dest));
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,35 +275,16 @@ impl Parse for AngleOrCorner {
|
||||||
(input.try(HorizontalDirection::parse).ok(), Some(value))
|
(input.try(HorizontalDirection::parse).ok(), Some(value))
|
||||||
};
|
};
|
||||||
try!(input.expect_comma());
|
try!(input.expect_comma());
|
||||||
match (horizontal, vertical) {
|
Ok(AngleOrCorner::Corner(horizontal, vertical))
|
||||||
(None, Some(VerticalDirection::Top)) => {
|
|
||||||
Ok(AngleOrCorner::Angle(Angle(0.0)))
|
|
||||||
},
|
|
||||||
(Some(HorizontalDirection::Right), None) => {
|
|
||||||
Ok(AngleOrCorner::Angle(Angle(PI * 0.5)))
|
|
||||||
},
|
|
||||||
(None, Some(VerticalDirection::Bottom)) => {
|
|
||||||
Ok(AngleOrCorner::Angle(Angle(PI)))
|
|
||||||
},
|
|
||||||
(Some(HorizontalDirection::Left), None) => {
|
|
||||||
Ok(AngleOrCorner::Angle(Angle(PI * 1.5)))
|
|
||||||
},
|
|
||||||
(Some(horizontal), Some(vertical)) => {
|
|
||||||
Ok(AngleOrCorner::Corner(horizontal, vertical))
|
|
||||||
}
|
|
||||||
(None, None) => unreachable!(),
|
|
||||||
}
|
|
||||||
} else if let Ok(angle) = input.try(|i| Angle::parse(context, i)) {
|
} else if let Ok(angle) = input.try(|i| Angle::parse(context, i)) {
|
||||||
try!(input.expect_comma());
|
try!(input.expect_comma());
|
||||||
Ok(AngleOrCorner::Angle(angle))
|
Ok(AngleOrCorner::Angle(angle))
|
||||||
} else {
|
} else {
|
||||||
Ok(AngleOrCorner::Angle(Angle(PI)))
|
Ok(AngleOrCorner::None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ComputedValueAsSpecified for AngleOrCorner {}
|
|
||||||
|
|
||||||
/// Specified values for one color stop in a linear gradient.
|
/// Specified values for one color stop in a linear gradient.
|
||||||
/// https://drafts.csswg.org/css-images/#typedef-color-stop-list
|
/// https://drafts.csswg.org/css-images/#typedef-color-stop-list
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
|
|
|
@ -12,12 +12,10 @@ use style_traits::ToCss;
|
||||||
#[test]
|
#[test]
|
||||||
fn test_linear_gradient() {
|
fn test_linear_gradient() {
|
||||||
// Parsing from the right
|
// Parsing from the right
|
||||||
assert_roundtrip_with_context!(Image::parse, "linear-gradient(to left, red, green)",
|
assert_roundtrip_with_context!(Image::parse, "linear-gradient(to left, red, green)");
|
||||||
"linear-gradient(4.712389rad, red, green)");
|
|
||||||
|
|
||||||
// Parsing from the left
|
// Parsing from the left
|
||||||
assert_roundtrip_with_context!(Image::parse, "linear-gradient(to right, red, green)",
|
assert_roundtrip_with_context!(Image::parse, "linear-gradient(to right, red, green)");
|
||||||
"linear-gradient(1.5707964rad, red, green)");
|
|
||||||
|
|
||||||
// Parsing with two values for <side-or-corner>
|
// Parsing with two values for <side-or-corner>
|
||||||
assert_roundtrip_with_context!(Image::parse, "linear-gradient(to right top, red, green)");
|
assert_roundtrip_with_context!(Image::parse, "linear-gradient(to right top, red, green)");
|
||||||
|
@ -26,17 +24,14 @@ fn test_linear_gradient() {
|
||||||
assert_roundtrip_with_context!(Image::parse, "linear-gradient(45deg, red, green)",
|
assert_roundtrip_with_context!(Image::parse, "linear-gradient(45deg, red, green)",
|
||||||
"linear-gradient(0.7853982rad, red, green)");
|
"linear-gradient(0.7853982rad, red, green)");
|
||||||
|
|
||||||
// Parsing with more than two entries in <color-stop-list>
|
// Parsing with more than two entries in <color-stop-list>
|
||||||
assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, yellow, green)",
|
assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, yellow, green)");
|
||||||
"linear-gradient(3.1415927rad, red, yellow, green)");
|
|
||||||
|
|
||||||
// Parsing with percentage in the <color-stop-list>
|
// Parsing with percentage in the <color-stop-list>
|
||||||
assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, green, yellow 50%)",
|
assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, green, yellow 50%)");
|
||||||
"linear-gradient(3.1415927rad, red, green, yellow 50%)");
|
|
||||||
|
|
||||||
// Parsing without <angle> and <side-or-corner>
|
// Parsing without <angle> and <side-or-corner>
|
||||||
assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, green)",
|
assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, green)");
|
||||||
"linear-gradient(3.1415927rad, red, green)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue