style: Cleanup gradient parsing by removing the simple-moz-gradient parsing pref.

It looks like bug 1547939 will stick, given how fast the other regressions came
in for bug 1337655.

We haven't seen any regression from this, and it seems unlikely that we'd want
this code back.

This blocks further improvements to the style system. Simplifying this code
allows me to remove all the conversion code for gradients.

Let me know if you think it's premature and I'm happy to wait, but I really want
to see this code gone :)

Differential Revision: https://phabricator.services.mozilla.com/D33820
This commit is contained in:
Emilio Cobos Álvarez 2019-06-06 04:08:52 +00:00
parent e9b0d54a95
commit 3980dc31cd
No known key found for this signature in database
GPG key ID: E1152D0994E4BF8A
5 changed files with 50 additions and 443 deletions

View file

@ -8,16 +8,12 @@
//! [image]: https://drafts.csswg.org/css-images/#image-values
use crate::custom_properties::SpecifiedValue;
#[cfg(feature = "gecko")]
use crate::gecko_bindings::structs;
use crate::parser::{Parse, ParserContext};
use crate::stylesheets::CorsMode;
#[cfg(feature = "gecko")]
use crate::values::computed::{Context, Position as ComputedPosition, ToComputedValue};
use crate::values::generics::image::PaintWorklet;
use crate::values::generics::image::{self as generic, Circle, CompatMode, Ellipse, ShapeExtent};
use crate::values::generics::position::Position as GenericPosition;
use crate::values::specified::position::{LegacyPosition, Position, PositionComponent, Side, X, Y};
use crate::values::specified::position::{Position, PositionComponent, Side, X, Y};
use crate::values::specified::url::SpecifiedImageUrl;
use crate::values::specified::{Angle, Color, Length, LengthPercentage};
use crate::values::specified::{Number, NumberOrPercentage, Percentage};
@ -55,15 +51,7 @@ pub type Image = generic::Image<Gradient, MozImageRect, SpecifiedImageUrl>;
/// Specified values for a CSS gradient.
/// <https://drafts.csswg.org/css-images/#gradients>
#[cfg(not(feature = "gecko"))]
pub type Gradient =
generic::Gradient<LineDirection, Length, LengthPercentage, Position, Color, Angle>;
/// Specified values for a CSS gradient.
/// <https://drafts.csswg.org/css-images/#gradients>
#[cfg(feature = "gecko")]
pub type Gradient =
generic::Gradient<LineDirection, Length, LengthPercentage, GradientPosition, Color, Angle>;
pub type Gradient = generic::Gradient<LineDirection, Length, LengthPercentage, Position, Color>;
impl SpecifiedValueInfo for Gradient {
const SUPPORTED_TYPES: u8 = CssType::GRADIENT;
@ -89,16 +77,11 @@ impl SpecifiedValueInfo for Gradient {
}
/// A specified gradient kind.
#[cfg(not(feature = "gecko"))]
pub type GradientKind =
generic::GradientKind<LineDirection, Length, LengthPercentage, Position, Angle>;
/// A specified gradient kind.
#[cfg(feature = "gecko")]
pub type GradientKind =
generic::GradientKind<LineDirection, Length, LengthPercentage, GradientPosition, Angle>;
pub type GradientKind = generic::GradientKind<LineDirection, Length, LengthPercentage, Position>;
/// A specified gradient line direction.
///
/// FIXME(emilio): This should be generic over Angle.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
pub enum LineDirection {
/// An angular direction.
@ -109,22 +92,6 @@ pub enum LineDirection {
Vertical(Y),
/// A direction towards a corner of a box.
Corner(X, Y),
/// A Position and an Angle for legacy `-moz-` prefixed gradient.
/// `-moz-` prefixed linear gradient can contain both a position and an angle but it
/// uses legacy syntax for position. That means we can't specify both keyword and
/// length for each horizontal/vertical components.
#[cfg(feature = "gecko")]
MozPosition(Option<LegacyPosition>, Option<Angle>),
}
/// A binary enum to hold either Position or LegacyPosition.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss, ToShmem)]
#[cfg(feature = "gecko")]
pub enum GradientPosition {
/// 1, 2, 3, 4-valued <position>.
Modern(Position),
/// 1, 2-valued <position>.
Legacy(LegacyPosition),
}
/// A specified ending shape.
@ -434,18 +401,8 @@ impl Gradient {
let shape = generic::EndingShape::Circle(rad);
let position: Position = point.into();
#[cfg(feature = "gecko")]
{
let pos = GradientPosition::Modern(position);
let kind = generic::GradientKind::Radial(shape, pos, None);
(kind, reverse_stops)
}
#[cfg(not(feature = "gecko"))]
{
let kind = generic::GradientKind::Radial(shape, position, None);
(kind, reverse_stops)
}
let kind = generic::GradientKind::Radial(shape, position);
(kind, reverse_stops)
},
_ => {
let e = SelectorParseErrorKind::UnexpectedIdent(ident.clone());
@ -544,16 +501,6 @@ impl Gradient {
}
}
#[inline]
fn simple_moz_gradient() -> bool {
#[cfg(feature = "gecko")]
unsafe {
return structs::StaticPrefs_sVarCache_layout_css_simple_moz_gradient_enabled;
}
#[cfg(not(feature = "gecko"))]
return false;
}
impl GradientKind {
/// Parses a linear gradient.
/// CompatMode can change during `-moz-` prefixed gradient parsing if it come across a `to` keyword.
@ -574,46 +521,19 @@ impl GradientKind {
};
Ok(generic::GradientKind::Linear(direction))
}
fn parse_radial<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
compat_mode: &mut CompatMode,
) -> Result<Self, ParseError<'i>> {
let (shape, position, angle, moz_position) = match *compat_mode {
let (shape, position) = match *compat_mode {
CompatMode::Modern => {
let shape = input.try(|i| EndingShape::parse(context, i, *compat_mode));
let position = input.try(|i| {
i.expect_ident_matching("at")?;
Position::parse(context, i)
});
(shape, position.ok(), None, None)
},
// The syntax of `-moz-` prefixed radial gradient is:
// -moz-radial-gradient(
// [ [ <position> || <angle> ]? [ ellipse | [ <length> | <percentage> ]{2} ] , |
// [ <position> || <angle> ]? [ [ circle | ellipse ] | <extent-keyword> ] , |
// ]?
// <color-stop> [ , <color-stop> ]+
// )
// where <extent-keyword> = closest-corner | closest-side | farthest-corner | farthest-side |
// cover | contain
// and <color-stop> = <color> [ <percentage> | <length> ]?
CompatMode::Moz if !simple_moz_gradient() => {
let mut position = input.try(|i| LegacyPosition::parse(context, i));
let angle = input.try(|i| Angle::parse(context, i)).ok();
if position.is_err() {
position = input.try(|i| LegacyPosition::parse(context, i));
}
let shape = input.try(|i| {
if position.is_ok() || angle.is_some() {
i.expect_comma()?;
}
EndingShape::parse(context, i, *compat_mode)
});
(shape, None, angle, position.ok())
(shape, position.ok())
},
_ => {
let position = input.try(|i| Position::parse(context, i));
@ -623,11 +543,11 @@ impl GradientKind {
}
EndingShape::parse(context, i, *compat_mode)
});
(shape, position.ok(), None, None)
(shape, position.ok())
},
};
if shape.is_ok() || position.is_some() || angle.is_some() || moz_position.is_some() {
if shape.is_ok() || position.is_some() {
input.expect_comma()?;
}
@ -635,35 +555,8 @@ impl GradientKind {
generic::EndingShape::Ellipse(Ellipse::Extent(ShapeExtent::FarthestCorner))
});
#[cfg(feature = "gecko")]
{
if *compat_mode == CompatMode::Moz && !simple_moz_gradient() {
// If this form can be represented in Modern mode, then convert the compat_mode to Modern.
if angle.is_none() {
*compat_mode = CompatMode::Modern;
}
let position = moz_position.unwrap_or(LegacyPosition::center());
return Ok(generic::GradientKind::Radial(
shape,
GradientPosition::Legacy(position),
angle,
));
}
}
let position = position.unwrap_or(Position::center());
#[cfg(feature = "gecko")]
{
return Ok(generic::GradientKind::Radial(
shape,
GradientPosition::Modern(position),
angle,
));
}
#[cfg(not(feature = "gecko"))]
{
return Ok(generic::GradientKind::Radial(shape, position, angle));
}
Ok(generic::GradientKind::Radial(shape, position))
}
}
@ -673,35 +566,6 @@ impl generic::LineDirection for LineDirection {
LineDirection::Angle(ref angle) => angle.degrees() == 180.0,
LineDirection::Vertical(Y::Bottom) if compat_mode == CompatMode::Modern => true,
LineDirection::Vertical(Y::Top) if compat_mode != CompatMode::Modern => true,
#[cfg(feature = "gecko")]
LineDirection::MozPosition(
Some(LegacyPosition {
horizontal: ref x,
vertical: ref y,
}),
None,
) => {
use crate::values::computed::Percentage as ComputedPercentage;
use crate::values::specified::transform::OriginComponent;
// `50% 0%` is the default value for line direction.
// These percentage values can also be keywords.
let x = match *x {
OriginComponent::Center => true,
OriginComponent::Length(LengthPercentage::Percentage(ComputedPercentage(
val,
))) => val == 0.5,
_ => false,
};
let y = match *y {
OriginComponent::Side(Y::Top) => true,
OriginComponent::Length(LengthPercentage::Percentage(ComputedPercentage(
val,
))) => val == 0.0,
_ => false,
};
x && y
},
_ => false,
}
}
@ -732,21 +596,6 @@ impl generic::LineDirection for LineDirection {
dest.write_str(" ")?;
y.to_css(dest)
},
#[cfg(feature = "gecko")]
LineDirection::MozPosition(ref position, ref angle) => {
let mut need_space = false;
if let Some(ref position) = *position {
position.to_css(dest)?;
need_space = true;
}
if let Some(ref angle) = *angle {
if need_space {
dest.write_str(" ")?;
}
angle.to_css(dest)?;
}
Ok(())
},
}
}
}
@ -757,16 +606,11 @@ impl LineDirection {
input: &mut Parser<'i, 't>,
compat_mode: &mut CompatMode,
) -> Result<Self, ParseError<'i>> {
let mut _angle = if *compat_mode == CompatMode::Moz && !simple_moz_gradient() {
input.try(|i| Angle::parse(context, i)).ok()
} else {
// Gradients allow unitless zero angles as an exception, see:
// https://github.com/w3c/csswg-drafts/issues/1162
if let Ok(angle) = input.try(|i| Angle::parse_with_unitless(context, i)) {
return Ok(LineDirection::Angle(angle));
}
None
};
// Gradients allow unitless zero angles as an exception, see:
// https://github.com/w3c/csswg-drafts/issues/1162
if let Ok(angle) = input.try(|i| Angle::parse_with_unitless(context, i)) {
return Ok(LineDirection::Angle(angle));
}
input.try(|i| {
let to_ident = i.try(|i| i.expect_ident_matching("to"));
@ -787,22 +631,6 @@ impl LineDirection {
_ => {},
}
#[cfg(feature = "gecko")]
{
// `-moz-` prefixed linear gradient can be both Angle and Position.
if *compat_mode == CompatMode::Moz && !simple_moz_gradient() {
let position = i.try(|i| LegacyPosition::parse(context, i)).ok();
if _angle.is_none() {
_angle = i.try(|i| Angle::parse(context, i)).ok();
};
if _angle.is_none() && position.is_none() {
return Err(i.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
return Ok(LineDirection::MozPosition(position, _angle));
}
}
if let Ok(x) = i.try(X::parse) {
if let Ok(y) = i.try(Y::parse) {
return Ok(LineDirection::Corner(x, y));
@ -818,22 +646,6 @@ impl LineDirection {
}
}
#[cfg(feature = "gecko")]
impl ToComputedValue for GradientPosition {
type ComputedValue = ComputedPosition;
fn to_computed_value(&self, context: &Context) -> ComputedPosition {
match *self {
GradientPosition::Modern(ref pos) => pos.to_computed_value(context),
GradientPosition::Legacy(ref pos) => pos.to_computed_value(context),
}
}
fn from_computed_value(computed: &ComputedPosition) -> Self {
GradientPosition::Modern(ToComputedValue::from_computed_value(computed))
}
}
impl EndingShape {
fn parse<'i, 't>(
context: &ParserContext,
@ -878,35 +690,31 @@ impl EndingShape {
ShapeExtent::FarthestCorner,
)));
}
// -moz- prefixed radial gradient doesn't allow EndingShape's Length or LengthPercentage
// to come before shape keyword. Otherwise it conflicts with <position>.
if compat_mode != CompatMode::Moz || simple_moz_gradient() {
if let Ok(length) = input.try(|i| Length::parse(context, i)) {
if let Ok(y) = input.try(|i| LengthPercentage::parse(context, i)) {
if compat_mode == CompatMode::Modern {
let _ = input.try(|i| i.expect_ident_matching("ellipse"));
}
if let Ok(length) = input.try(|i| Length::parse(context, i)) {
if let Ok(y) = input.try(|i| LengthPercentage::parse(context, i)) {
if compat_mode == CompatMode::Modern {
let _ = input.try(|i| i.expect_ident_matching("ellipse"));
}
return Ok(generic::EndingShape::Ellipse(Ellipse::Radii(
length.into(),
y,
)));
}
if compat_mode == CompatMode::Modern {
let y = input.try(|i| {
i.expect_ident_matching("ellipse")?;
LengthPercentage::parse(context, i)
});
if let Ok(y) = y {
return Ok(generic::EndingShape::Ellipse(Ellipse::Radii(
length.into(),
y,
)));
}
if compat_mode == CompatMode::Modern {
let y = input.try(|i| {
i.expect_ident_matching("ellipse")?;
LengthPercentage::parse(context, i)
});
if let Ok(y) = y {
return Ok(generic::EndingShape::Ellipse(Ellipse::Radii(
length.into(),
y,
)));
}
let _ = input.try(|i| i.expect_ident_matching("circle"));
}
return Ok(generic::EndingShape::Circle(Circle::Radius(length)));
let _ = input.try(|i| i.expect_ident_matching("circle"));
}
return Ok(generic::EndingShape::Circle(Circle::Radius(length)));
}
input.try(|i| {
let x = Percentage::parse(context, i)?;