mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +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::servo::restyle_damage::REPAINT;
|
||||
use style::values::{self, Either, RGBA, computed};
|
||||
use style::values::computed::{Gradient, GradientKind, LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||
use style::values::specified::{AngleOrCorner, HorizontalDirection, VerticalDirection};
|
||||
use style::values::computed::{AngleOrCorner, Gradient, GradientKind, LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||
use style::values::specified::{HorizontalDirection, VerticalDirection};
|
||||
use style_traits::cursor::Cursor;
|
||||
use table_cell::CollapsedBordersForCell;
|
||||
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_FARTHEST_CORNER, NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE};
|
||||
use gecko_bindings::structs::nsStyleCoord;
|
||||
use values::computed::{GradientKind, GradientShape, LengthOrKeyword};
|
||||
use values::computed::{AngleOrCorner, GradientKind, GradientShape, LengthOrKeyword};
|
||||
use values::computed::LengthOrPercentageOrKeyword;
|
||||
use values::specified::{AngleOrCorner, HorizontalDirection};
|
||||
use values::specified::{SizeKeyword, VerticalDirection};
|
||||
use values::specified::{HorizontalDirection, SizeKeyword, VerticalDirection};
|
||||
|
||||
let stop_count = gradient.stops.len();
|
||||
if stop_count >= ::std::u32::MAX as usize {
|
||||
|
|
|
@ -8,11 +8,12 @@
|
|||
//! [image]: https://drafts.csswg.org/css-images/#image-values
|
||||
|
||||
use cssparser::Color as CSSColor;
|
||||
use std::f32::consts::PI;
|
||||
use std::fmt;
|
||||
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::specified::{self, AngleOrCorner, SizeKeyword};
|
||||
use values::specified::{self, HorizontalDirection, SizeKeyword, VerticalDirection};
|
||||
use values::specified::url::SpecifiedUrl;
|
||||
|
||||
|
||||
|
@ -185,7 +186,7 @@ impl ToComputedValue for specified::GradientKind {
|
|||
fn to_computed_value(&self, context: &Context) -> GradientKind {
|
||||
match *self {
|
||||
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) => {
|
||||
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};
|
||||
|
||||
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 super::{Either, None_};
|
||||
pub use super::specified::{Angle, BorderStyle, GridLine, Time, UrlOrNone};
|
||||
|
|
|
@ -10,10 +10,8 @@
|
|||
use cssparser::Parser;
|
||||
use parser::{Parse, ParserContext};
|
||||
use servo_url::ServoUrl;
|
||||
use std::f32::consts::PI;
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use values::computed::ComputedValueAsSpecified;
|
||||
use values::specified::{Angle, CSSColor, Length, LengthOrPercentage};
|
||||
use values::specified::position::Position;
|
||||
use values::specified::url::{SpecifiedUrl, UrlExtraData};
|
||||
|
@ -70,10 +68,14 @@ impl ToCss for Gradient {
|
|||
if self.repeating {
|
||||
try!(dest.write_str("repeating-"));
|
||||
}
|
||||
let mut skipcomma = false;
|
||||
match self.gradient_kind {
|
||||
GradientKind::Linear(angle_or_corner) => {
|
||||
try!(dest.write_str("linear-gradient("));
|
||||
try!(angle_or_corner.to_css(dest));
|
||||
if angle_or_corner == AngleOrCorner::None {
|
||||
skipcomma = true;
|
||||
}
|
||||
},
|
||||
GradientKind::Radial(ref shape, position) => {
|
||||
try!(dest.write_str("radial-gradient("));
|
||||
|
@ -83,7 +85,11 @@ impl ToCss for Gradient {
|
|||
},
|
||||
}
|
||||
for stop in &self.stops {
|
||||
if !skipcomma {
|
||||
try!(dest.write_str(", "));
|
||||
} else {
|
||||
skipcomma = false;
|
||||
}
|
||||
try!(stop.to_css(dest));
|
||||
}
|
||||
dest.write_str(")")
|
||||
|
@ -230,18 +236,28 @@ fn parse_position(context: &ParserContext, input: &mut Parser) -> Result<Positio
|
|||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum AngleOrCorner {
|
||||
Angle(Angle),
|
||||
Corner(HorizontalDirection, VerticalDirection),
|
||||
Corner(Option<HorizontalDirection>, Option<VerticalDirection>),
|
||||
None,
|
||||
}
|
||||
|
||||
impl ToCss for AngleOrCorner {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
AngleOrCorner::None => Ok(()),
|
||||
AngleOrCorner::Angle(angle) => angle.to_css(dest),
|
||||
AngleOrCorner::Corner(horizontal, vertical) => {
|
||||
try!(dest.write_str("to "));
|
||||
let mut horizontal_present = false;
|
||||
if let Some(horizontal) = horizontal {
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
@ -259,35 +275,16 @@ impl Parse for AngleOrCorner {
|
|||
(input.try(HorizontalDirection::parse).ok(), Some(value))
|
||||
};
|
||||
try!(input.expect_comma());
|
||||
match (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)) {
|
||||
try!(input.expect_comma());
|
||||
Ok(AngleOrCorner::Angle(angle))
|
||||
} else {
|
||||
Ok(AngleOrCorner::Angle(Angle(PI)))
|
||||
Ok(AngleOrCorner::None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputedValueAsSpecified for AngleOrCorner {}
|
||||
|
||||
/// Specified values for one color stop in a linear gradient.
|
||||
/// https://drafts.csswg.org/css-images/#typedef-color-stop-list
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
|
|
|
@ -12,12 +12,10 @@ use style_traits::ToCss;
|
|||
#[test]
|
||||
fn test_linear_gradient() {
|
||||
// Parsing from the right
|
||||
assert_roundtrip_with_context!(Image::parse, "linear-gradient(to left, red, green)",
|
||||
"linear-gradient(4.712389rad, red, green)");
|
||||
assert_roundtrip_with_context!(Image::parse, "linear-gradient(to left, red, green)");
|
||||
|
||||
// Parsing from the left
|
||||
assert_roundtrip_with_context!(Image::parse, "linear-gradient(to right, red, green)",
|
||||
"linear-gradient(1.5707964rad, red, green)");
|
||||
assert_roundtrip_with_context!(Image::parse, "linear-gradient(to right, red, green)");
|
||||
|
||||
// Parsing with two values for <side-or-corner>
|
||||
assert_roundtrip_with_context!(Image::parse, "linear-gradient(to right top, red, green)");
|
||||
|
@ -27,16 +25,13 @@ fn test_linear_gradient() {
|
|||
"linear-gradient(0.7853982rad, red, green)");
|
||||
|
||||
// Parsing with more than two entries in <color-stop-list>
|
||||
assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, yellow, green)",
|
||||
"linear-gradient(3.1415927rad, red, yellow, green)");
|
||||
assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, yellow, green)");
|
||||
|
||||
// Parsing with percentage in the <color-stop-list>
|
||||
assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, green, yellow 50%)",
|
||||
"linear-gradient(3.1415927rad, red, green, yellow 50%)");
|
||||
assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, green, yellow 50%)");
|
||||
|
||||
// Parsing without <angle> and <side-or-corner>
|
||||
assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, green)",
|
||||
"linear-gradient(3.1415927rad, red, green)");
|
||||
assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, green)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue