mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-02 06:22:20 +00:00
servo: Merge #16440 - Implement webkit-prefixed linear gradients (from nox:webkit-gradients); r=emilio
This is half of #15441. Source-Repo: https://github.com/servo/servo Source-Revision: 842ff5f978f341b1929f16cbdcac2b1edbe1482e --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : cb6a36b0376dbdbe483ae9c411804e33720ca0b5
This commit is contained in:
parent
7bab97b6fd
commit
0257b6738b
@ -15,6 +15,7 @@ use style_traits::ToCss;
|
||||
use values::computed::{Angle, Context, Length, LengthOrPercentage, NumberOrPercentage, ToComputedValue};
|
||||
use values::computed::position::Position;
|
||||
use values::specified::{self, HorizontalDirection, SizeKeyword, VerticalDirection};
|
||||
use values::specified::image::CompatMode;
|
||||
use values::specified::url::SpecifiedUrl;
|
||||
|
||||
|
||||
@ -124,17 +125,22 @@ pub struct Gradient {
|
||||
pub repeating: bool,
|
||||
/// Gradient kind can be linear or radial.
|
||||
pub gradient_kind: GradientKind,
|
||||
/// Compatibility mode.
|
||||
pub compat_mode: CompatMode,
|
||||
}
|
||||
|
||||
impl ToCss for Gradient {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
if self.compat_mode == CompatMode::WebKit {
|
||||
try!(dest.write_str("-webkit-"));
|
||||
}
|
||||
if self.repeating {
|
||||
try!(dest.write_str("repeating-"));
|
||||
}
|
||||
match self.gradient_kind {
|
||||
GradientKind::Linear(angle_or_corner) => {
|
||||
try!(dest.write_str("linear-gradient("));
|
||||
try!(angle_or_corner.to_css(dest));
|
||||
try!(angle_or_corner.to_css(dest, self.compat_mode));
|
||||
},
|
||||
GradientKind::Radial(ref shape, position) => {
|
||||
try!(dest.write_str("radial-gradient("));
|
||||
@ -178,25 +184,30 @@ impl ToComputedValue for specified::Gradient {
|
||||
let specified::Gradient {
|
||||
ref stops,
|
||||
repeating,
|
||||
ref gradient_kind
|
||||
ref gradient_kind,
|
||||
compat_mode,
|
||||
} = *self;
|
||||
Gradient {
|
||||
stops: stops.iter().map(|s| s.to_computed_value(context)).collect(),
|
||||
repeating: repeating,
|
||||
gradient_kind: gradient_kind.to_computed_value(context),
|
||||
compat_mode: compat_mode,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &Gradient) -> Self {
|
||||
let Gradient {
|
||||
ref stops,
|
||||
repeating,
|
||||
ref gradient_kind
|
||||
ref gradient_kind,
|
||||
compat_mode,
|
||||
} = *computed;
|
||||
specified::Gradient {
|
||||
stops: stops.iter().map(ToComputedValue::from_computed_value).collect(),
|
||||
repeating: repeating,
|
||||
gradient_kind: ToComputedValue::from_computed_value(gradient_kind),
|
||||
compat_mode: compat_mode,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -602,12 +613,14 @@ impl ToComputedValue for specified::AngleOrCorner {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for AngleOrCorner {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
impl AngleOrCorner {
|
||||
fn to_css<W>(&self, dest: &mut W, mode: CompatMode) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
AngleOrCorner::Angle(angle) => angle.to_css(dest),
|
||||
AngleOrCorner::Corner(horizontal, vertical) => {
|
||||
try!(dest.write_str("to "));
|
||||
if mode == CompatMode::Modern {
|
||||
try!(dest.write_str("to "));
|
||||
}
|
||||
try!(horizontal.to_css(dest));
|
||||
try!(dest.write_str(" "));
|
||||
try!(vertical.to_css(dest));
|
||||
|
@ -98,10 +98,15 @@ pub struct Gradient {
|
||||
pub repeating: bool,
|
||||
/// Gradients can be linear or radial.
|
||||
pub gradient_kind: GradientKind,
|
||||
/// Compatibility mode.
|
||||
pub compat_mode: CompatMode,
|
||||
}
|
||||
|
||||
impl ToCss for Gradient {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
if self.compat_mode == CompatMode::WebKit {
|
||||
try!(dest.write_str("-webkit-"));
|
||||
}
|
||||
if self.repeating {
|
||||
try!(dest.write_str("repeating-"));
|
||||
}
|
||||
@ -109,7 +114,7 @@ impl ToCss for Gradient {
|
||||
match self.gradient_kind {
|
||||
GradientKind::Linear(angle_or_corner) => {
|
||||
try!(dest.write_str("linear-gradient("));
|
||||
try!(angle_or_corner.to_css(dest));
|
||||
try!(angle_or_corner.to_css(dest, self.compat_mode));
|
||||
if angle_or_corner == AngleOrCorner::None {
|
||||
skipcomma = true;
|
||||
}
|
||||
@ -136,41 +141,45 @@ impl ToCss for Gradient {
|
||||
impl Gradient {
|
||||
/// Parses a gradient from the given arguments.
|
||||
pub fn parse_function(context: &ParserContext, input: &mut Parser) -> Result<Gradient, ()> {
|
||||
let parse_linear_gradient = |input: &mut Parser, mode| {
|
||||
input.parse_nested_block(|input| {
|
||||
let kind = try!(GradientKind::parse_linear(context, input, mode));
|
||||
let stops = try!(input.parse_comma_separated(|i| ColorStop::parse(context, i)));
|
||||
Ok((kind, stops))
|
||||
})
|
||||
};
|
||||
let parse_radial_gradient = |input: &mut Parser| {
|
||||
input.parse_nested_block(|input| {
|
||||
let kind = try!(GradientKind::parse_radial(context, input));
|
||||
let stops = try!(input.parse_comma_separated(|i| ColorStop::parse(context, i)));
|
||||
Ok((kind, stops))
|
||||
})
|
||||
};
|
||||
let mut repeating = false;
|
||||
let mut compat_mode = CompatMode::Modern;
|
||||
let (gradient_kind, stops) = match_ignore_ascii_case! { &try!(input.expect_function()),
|
||||
"linear-gradient" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let kind = try!(GradientKind::parse_linear(context, input));
|
||||
let stops = try!(input.parse_comma_separated(|i| ColorStop::parse(context, i)));
|
||||
Ok((kind, stops))
|
||||
})
|
||||
)
|
||||
try!(parse_linear_gradient(input, compat_mode))
|
||||
},
|
||||
"-webkit-linear-gradient" => {
|
||||
compat_mode = CompatMode::WebKit;
|
||||
try!(parse_linear_gradient(input, compat_mode))
|
||||
},
|
||||
"repeating-linear-gradient" => {
|
||||
repeating = true;
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let kind = try!(GradientKind::parse_linear(context, input));
|
||||
let stops = try!(input.parse_comma_separated(|i| ColorStop::parse(context, i)));
|
||||
Ok((kind, stops))
|
||||
})
|
||||
)
|
||||
try!(parse_linear_gradient(input, compat_mode))
|
||||
},
|
||||
"-webkit-repeating-linear-gradient" => {
|
||||
repeating = true;
|
||||
compat_mode = CompatMode::WebKit;
|
||||
try!(parse_linear_gradient(input, compat_mode))
|
||||
},
|
||||
"radial-gradient" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let kind = try!(GradientKind::parse_radial(context, input));
|
||||
let stops = try!(input.parse_comma_separated(|i| ColorStop::parse(context, i)));
|
||||
Ok((kind, stops))
|
||||
})
|
||||
)
|
||||
try!(parse_radial_gradient(input))
|
||||
},
|
||||
"repeating-radial-gradient" => {
|
||||
repeating = true;
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let kind = try!(GradientKind::parse_radial(context, input));
|
||||
let stops = try!(input.parse_comma_separated(|i| ColorStop::parse(context, i)));
|
||||
Ok((kind, stops))
|
||||
})
|
||||
)
|
||||
try!(parse_radial_gradient(input))
|
||||
},
|
||||
_ => { return Err(()); }
|
||||
};
|
||||
@ -184,6 +193,7 @@ impl Gradient {
|
||||
stops: stops,
|
||||
repeating: repeating,
|
||||
gradient_kind: gradient_kind,
|
||||
compat_mode: compat_mode,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -204,10 +214,20 @@ pub enum GradientKind {
|
||||
Radial(EndingShape, Position),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
/// Whether we used the modern notation or the compatibility `-webkit` prefix.
|
||||
pub enum CompatMode {
|
||||
/// Modern syntax.
|
||||
Modern,
|
||||
/// `-webkit` prefix.
|
||||
WebKit,
|
||||
}
|
||||
|
||||
impl GradientKind {
|
||||
/// Parses a linear gradient kind from the given arguments.
|
||||
pub fn parse_linear(context: &ParserContext, input: &mut Parser) -> Result<GradientKind, ()> {
|
||||
let angle_or_corner = try!(AngleOrCorner::parse(context, input));
|
||||
fn parse_linear(context: &ParserContext, input: &mut Parser, mode: CompatMode) -> Result<GradientKind, ()> {
|
||||
let angle_or_corner = try!(AngleOrCorner::parse(context, input, mode));
|
||||
Ok(GradientKind::Linear(angle_or_corner))
|
||||
}
|
||||
|
||||
@ -348,13 +368,15 @@ pub enum AngleOrCorner {
|
||||
None,
|
||||
}
|
||||
|
||||
impl ToCss for AngleOrCorner {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
impl AngleOrCorner {
|
||||
fn to_css<W>(&self, dest: &mut W, compat_mode: CompatMode) -> 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 "));
|
||||
if compat_mode == CompatMode::Modern {
|
||||
try!(dest.write_str("to "));
|
||||
}
|
||||
let mut horizontal_present = false;
|
||||
if let Some(horizontal) = horizontal {
|
||||
try!(horizontal.to_css(dest));
|
||||
@ -372,21 +394,22 @@ impl ToCss for AngleOrCorner {
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for AngleOrCorner {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
if input.try(|input| input.expect_ident_matching("to")).is_ok() {
|
||||
impl AngleOrCorner {
|
||||
fn parse(context: &ParserContext, input: &mut Parser, mode: CompatMode) -> Result<Self, ()> {
|
||||
if let Ok(angle) = input.try(|i| Angle::parse_with_unitless(context, i)) {
|
||||
try!(input.expect_comma());
|
||||
return Ok(AngleOrCorner::Angle(angle))
|
||||
}
|
||||
if mode == CompatMode::WebKit || input.try(|input| input.expect_ident_matching("to")).is_ok() {
|
||||
let (horizontal, vertical) =
|
||||
if let Ok(value) = input.try(HorizontalDirection::parse) {
|
||||
(Some(value), input.try(VerticalDirection::parse).ok())
|
||||
} else {
|
||||
let value = try!(VerticalDirection::parse(input));
|
||||
(input.try(HorizontalDirection::parse).ok(), Some(value))
|
||||
};
|
||||
if let Ok(value) = input.try(HorizontalDirection::parse) {
|
||||
(Some(value), input.try(VerticalDirection::parse).ok())
|
||||
} else {
|
||||
let value = try!(VerticalDirection::parse(input));
|
||||
(input.try(HorizontalDirection::parse).ok(), Some(value))
|
||||
};
|
||||
try!(input.expect_comma());
|
||||
Ok(AngleOrCorner::Corner(horizontal, vertical))
|
||||
} else if let Ok(angle) = input.try(|i| Angle::parse(context, i)) {
|
||||
try!(input.expect_comma());
|
||||
Ok(AngleOrCorner::Angle(angle))
|
||||
} else {
|
||||
Ok(AngleOrCorner::None)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user