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

@ -65,7 +65,6 @@ impl From<Angle> for CoordDataValue {
} }
fn line_direction(horizontal: LengthPercentage, vertical: LengthPercentage) -> LineDirection { fn line_direction(horizontal: LengthPercentage, vertical: LengthPercentage) -> LineDirection {
use crate::values::computed::position::Position;
use crate::values::specified::position::{X, Y}; use crate::values::specified::position::{X, Y};
let horizontal_percentage = horizontal.as_percentage(); let horizontal_percentage = horizontal.as_percentage();
@ -107,13 +106,7 @@ fn line_direction(horizontal: LengthPercentage, vertical: LengthPercentage) -> L
} }
} }
LineDirection::MozPosition( unreachable!("Unexpected line direction");
Some(Position {
horizontal,
vertical,
}),
None,
)
} }
impl nsStyleImage { impl nsStyleImage {
@ -241,20 +234,10 @@ impl nsStyleImage {
.set_value(CoordDataValue::Percent(percent_y)); .set_value(CoordDataValue::Percent(percent_y));
} }
}, },
#[cfg(feature = "gecko")]
LineDirection::MozPosition(position, angle) => unsafe {
if let Some(position) = position {
(*gecko_gradient).mBgPosX.set(position.horizontal);
(*gecko_gradient).mBgPosY.set(position.vertical);
}
if let Some(angle) = angle {
(*gecko_gradient).mAngle.set(angle);
}
},
} }
gecko_gradient gecko_gradient
}, },
GradientKind::Radial(shape, position, angle) => { GradientKind::Radial(shape, position) => {
let keyword_to_gecko_size = |keyword| match keyword { let keyword_to_gecko_size = |keyword| match keyword {
ShapeExtent::ClosestSide => CLOSEST_SIDE, ShapeExtent::ClosestSide => CLOSEST_SIDE,
ShapeExtent::FarthestSide => FARTHEST_SIDE, ShapeExtent::FarthestSide => FARTHEST_SIDE,
@ -294,13 +277,6 @@ impl nsStyleImage {
) )
}; };
// Clear mBgPos field and set mAngle if angle is set. Otherwise clear it.
unsafe {
if let Some(angle) = angle {
(*gecko_gradient).mAngle.set(angle);
}
}
// Setting radius values depending shape // Setting radius values depending shape
match shape { match shape {
EndingShape::Circle(Circle::Radius(length)) => unsafe { EndingShape::Circle(Circle::Radius(length)) => unsafe {
@ -405,30 +381,19 @@ impl nsStyleImage {
let gecko_gradient = bindings::Gecko_GetGradientImageValue(self) let gecko_gradient = bindings::Gecko_GetGradientImageValue(self)
.as_ref() .as_ref()
.unwrap(); .unwrap();
let angle = Angle::from_gecko_style_coord(&gecko_gradient.mAngle);
let horizontal_style = LengthPercentage::from_gecko_style_coord(&gecko_gradient.mBgPosX); let horizontal_style = LengthPercentage::from_gecko_style_coord(&gecko_gradient.mBgPosX);
let vertical_style = LengthPercentage::from_gecko_style_coord(&gecko_gradient.mBgPosY); let vertical_style = LengthPercentage::from_gecko_style_coord(&gecko_gradient.mBgPosY);
let kind = match gecko_gradient.mShape as u32 { let kind = match gecko_gradient.mShape as u32 {
structs::NS_STYLE_GRADIENT_SHAPE_LINEAR => { structs::NS_STYLE_GRADIENT_SHAPE_LINEAR => {
let angle = Angle::from_gecko_style_coord(&gecko_gradient.mAngle);
let line_direction = match (angle, horizontal_style, vertical_style) { let line_direction = match (angle, horizontal_style, vertical_style) {
(Some(a), None, None) => LineDirection::Angle(a), (Some(a), None, None) => LineDirection::Angle(a),
(None, Some(horizontal), Some(vertical)) => { (None, Some(horizontal), Some(vertical)) => {
line_direction(horizontal, vertical) line_direction(horizontal, vertical)
}, },
(Some(_), Some(horizontal), Some(vertical)) => LineDirection::MozPosition(
Some(Position {
horizontal,
vertical,
}),
angle,
),
_ => { _ => {
debug_assert!( unreachable!("unexpected line direction for linear gradient direction");
horizontal_style.is_none() && vertical_style.is_none(),
"Unexpected linear gradient direction"
);
LineDirection::MozPosition(None, None)
}, },
}; };
GradientKind::Linear(line_direction) GradientKind::Linear(line_direction)
@ -507,7 +472,7 @@ impl nsStyleImage {
}, },
}; };
GradientKind::Radial(shape, position, angle) GradientKind::Radial(shape, position)
}, },
}; };

View file

@ -29,11 +29,11 @@ pub type Image = generic::Image<Gradient, MozImageRect, ComputedImageUrl>;
/// Computed values for a CSS gradient. /// Computed values for a CSS gradient.
/// <https://drafts.csswg.org/css-images/#gradients> /// <https://drafts.csswg.org/css-images/#gradients>
pub type Gradient = pub type Gradient =
generic::Gradient<LineDirection, Length, LengthPercentage, Position, Color, Angle>; generic::Gradient<LineDirection, Length, LengthPercentage, Position, Color>;
/// A computed gradient kind. /// A computed gradient kind.
pub type GradientKind = pub type GradientKind =
generic::GradientKind<LineDirection, Length, LengthPercentage, Position, Angle>; generic::GradientKind<LineDirection, Length, LengthPercentage, Position>;
/// A computed gradient line direction. /// A computed gradient line direction.
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToResolvedValue)] #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToResolvedValue)]
@ -46,9 +46,6 @@ pub enum LineDirection {
Vertical(Y), Vertical(Y),
/// A corner. /// A corner.
Corner(X, Y), Corner(X, Y),
/// A Position and an Angle for legacy `-moz-` prefixed gradient.
#[cfg(feature = "gecko")]
MozPosition(Option<Position>, Option<Angle>),
} }
/// A computed radial gradient ending shape. /// A computed radial gradient ending shape.
@ -69,19 +66,6 @@ impl generic::LineDirection for LineDirection {
LineDirection::Angle(angle) => angle.radians() == PI, LineDirection::Angle(angle) => angle.radians() == PI,
LineDirection::Vertical(Y::Bottom) if compat_mode == CompatMode::Modern => true, LineDirection::Vertical(Y::Bottom) if compat_mode == CompatMode::Modern => true,
LineDirection::Vertical(Y::Top) if compat_mode != CompatMode::Modern => true, LineDirection::Vertical(Y::Top) if compat_mode != CompatMode::Modern => true,
LineDirection::Corner(..) => false,
#[cfg(feature = "gecko")]
LineDirection::MozPosition(
Some(Position {
ref vertical,
ref horizontal,
}),
None,
) => {
// `50% 0%` is the default value for line direction.
horizontal.as_percentage().map_or(false, |p| p.0 == 0.5) &&
vertical.as_percentage().map_or(false, |p| p.0 == 0.0)
},
_ => false, _ => false,
} }
} }
@ -112,21 +96,6 @@ impl generic::LineDirection for LineDirection {
dest.write_str(" ")?; dest.write_str(" ")?;
y.to_css(dest) y.to_css(dest)
}, },
#[cfg(feature = "gecko")]
LineDirection::MozPosition(position, angle) => {
let mut need_space = false;
if let Some(position) = position {
position.to_css(dest)?;
need_space = true;
}
if let Some(angle) = angle {
if need_space {
dest.write_str(" ")?;
}
angle.to_css(dest)?;
}
Ok(())
},
} }
} }
} }
@ -142,13 +111,6 @@ impl ToComputedValue for SpecifiedLineDirection {
SpecifiedLineDirection::Horizontal(x) => LineDirection::Horizontal(x), SpecifiedLineDirection::Horizontal(x) => LineDirection::Horizontal(x),
SpecifiedLineDirection::Vertical(y) => LineDirection::Vertical(y), SpecifiedLineDirection::Vertical(y) => LineDirection::Vertical(y),
SpecifiedLineDirection::Corner(x, y) => LineDirection::Corner(x, y), SpecifiedLineDirection::Corner(x, y) => LineDirection::Corner(x, y),
#[cfg(feature = "gecko")]
SpecifiedLineDirection::MozPosition(ref position, ref angle) => {
LineDirection::MozPosition(
position.to_computed_value(context),
angle.to_computed_value(context),
)
},
} }
} }
@ -160,13 +122,6 @@ impl ToComputedValue for SpecifiedLineDirection {
LineDirection::Horizontal(x) => SpecifiedLineDirection::Horizontal(x), LineDirection::Horizontal(x) => SpecifiedLineDirection::Horizontal(x),
LineDirection::Vertical(y) => SpecifiedLineDirection::Vertical(y), LineDirection::Vertical(y) => SpecifiedLineDirection::Vertical(y),
LineDirection::Corner(x, y) => SpecifiedLineDirection::Corner(x, y), LineDirection::Corner(x, y) => SpecifiedLineDirection::Corner(x, y),
#[cfg(feature = "gecko")]
LineDirection::MozPosition(ref position, ref angle) => {
SpecifiedLineDirection::MozPosition(
ToComputedValue::from_computed_value(position),
ToComputedValue::from_computed_value(angle),
)
},
} }
} }
} }

View file

@ -39,9 +39,9 @@ pub enum Image<Gradient, MozImageRect, ImageUrl> {
/// A CSS gradient. /// A CSS gradient.
/// <https://drafts.csswg.org/css-images/#gradients> /// <https://drafts.csswg.org/css-images/#gradients>
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)]
pub struct Gradient<LineDirection, Length, LengthPercentage, Position, Color, Angle> { pub struct Gradient<LineDirection, Length, LengthPercentage, Position, Color> {
/// Gradients can be linear or radial. /// Gradients can be linear or radial.
pub kind: GradientKind<LineDirection, Length, LengthPercentage, Position, Angle>, pub kind: GradientKind<LineDirection, Length, LengthPercentage, Position>,
/// The color stops and interpolation hints. /// The color stops and interpolation hints.
pub items: Vec<GradientItem<Color, LengthPercentage>>, pub items: Vec<GradientItem<Color, LengthPercentage>>,
/// True if this is a repeating gradient. /// True if this is a repeating gradient.
@ -63,15 +63,11 @@ pub enum CompatMode {
/// A gradient kind. /// A gradient kind.
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)] #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)]
pub enum GradientKind<LineDirection, Length, LengthPercentage, Position, Angle> { pub enum GradientKind<LineDirection, Length, LengthPercentage, Position> {
/// A linear gradient. /// A linear gradient.
Linear(LineDirection), Linear(LineDirection),
/// A radial gradient. /// A radial gradient.
Radial( Radial(EndingShape<Length, LengthPercentage>, Position),
EndingShape<Length, LengthPercentage>,
Position,
Option<Angle>,
),
} }
/// A radial gradient's ending shape. /// A radial gradient's ending shape.
@ -268,14 +264,13 @@ where
} }
} }
impl<D, L, LoP, P, C, A> ToCss for Gradient<D, L, LoP, P, C, A> impl<D, L, LoP, P, C> ToCss for Gradient<D, L, LoP, P, C>
where where
D: LineDirection, D: LineDirection,
L: ToCss, L: ToCss,
LoP: ToCss, LoP: ToCss,
P: ToCss, P: ToCss,
C: ToCss, C: ToCss,
A: ToCss,
{ {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where where
@ -300,7 +295,7 @@ where
direction.to_css(dest, self.compat_mode)?; direction.to_css(dest, self.compat_mode)?;
false false
}, },
GradientKind::Radial(ref shape, ref position, ref angle) => { GradientKind::Radial(ref shape, ref position) => {
let omit_shape = match *shape { let omit_shape = match *shape {
EndingShape::Ellipse(Ellipse::Extent(ShapeExtent::Cover)) | EndingShape::Ellipse(Ellipse::Extent(ShapeExtent::Cover)) |
EndingShape::Ellipse(Ellipse::Extent(ShapeExtent::FarthestCorner)) => true, EndingShape::Ellipse(Ellipse::Extent(ShapeExtent::FarthestCorner)) => true,
@ -315,10 +310,6 @@ where
position.to_css(dest)?; position.to_css(dest)?;
} else { } else {
position.to_css(dest)?; position.to_css(dest)?;
if let Some(ref a) = *angle {
dest.write_str(" ")?;
a.to_css(dest)?;
}
if !omit_shape { if !omit_shape {
dest.write_str(", ")?; dest.write_str(", ")?;
shape.to_css(dest)?; shape.to_css(dest)?;
@ -338,7 +329,7 @@ where
} }
} }
impl<D, L, LoP, P, A> GradientKind<D, L, LoP, P, A> { impl<D, L, LoP, P> GradientKind<D, L, LoP, P> {
fn label(&self) -> &str { fn label(&self) -> &str {
match *self { match *self {
GradientKind::Linear(..) => "linear", GradientKind::Linear(..) => "linear",

View file

@ -8,16 +8,12 @@
//! [image]: https://drafts.csswg.org/css-images/#image-values //! [image]: https://drafts.csswg.org/css-images/#image-values
use crate::custom_properties::SpecifiedValue; use crate::custom_properties::SpecifiedValue;
#[cfg(feature = "gecko")]
use crate::gecko_bindings::structs;
use crate::parser::{Parse, ParserContext}; use crate::parser::{Parse, ParserContext};
use crate::stylesheets::CorsMode; 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::PaintWorklet;
use crate::values::generics::image::{self as generic, Circle, CompatMode, Ellipse, ShapeExtent}; use crate::values::generics::image::{self as generic, Circle, CompatMode, Ellipse, ShapeExtent};
use crate::values::generics::position::Position as GenericPosition; 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::url::SpecifiedImageUrl;
use crate::values::specified::{Angle, Color, Length, LengthPercentage}; use crate::values::specified::{Angle, Color, Length, LengthPercentage};
use crate::values::specified::{Number, NumberOrPercentage, Percentage}; 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. /// Specified values for a CSS gradient.
/// <https://drafts.csswg.org/css-images/#gradients> /// <https://drafts.csswg.org/css-images/#gradients>
#[cfg(not(feature = "gecko"))] pub type Gradient = generic::Gradient<LineDirection, Length, LengthPercentage, Position, Color>;
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>;
impl SpecifiedValueInfo for Gradient { impl SpecifiedValueInfo for Gradient {
const SUPPORTED_TYPES: u8 = CssType::GRADIENT; const SUPPORTED_TYPES: u8 = CssType::GRADIENT;
@ -89,16 +77,11 @@ impl SpecifiedValueInfo for Gradient {
} }
/// A specified gradient kind. /// A specified gradient kind.
#[cfg(not(feature = "gecko"))] pub type GradientKind = generic::GradientKind<LineDirection, Length, LengthPercentage, Position>;
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>;
/// A specified gradient line direction. /// A specified gradient line direction.
///
/// FIXME(emilio): This should be generic over Angle.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
pub enum LineDirection { pub enum LineDirection {
/// An angular direction. /// An angular direction.
@ -109,22 +92,6 @@ pub enum LineDirection {
Vertical(Y), Vertical(Y),
/// A direction towards a corner of a box. /// A direction towards a corner of a box.
Corner(X, Y), 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. /// A specified ending shape.
@ -434,18 +401,8 @@ impl Gradient {
let shape = generic::EndingShape::Circle(rad); let shape = generic::EndingShape::Circle(rad);
let position: Position = point.into(); let position: Position = point.into();
#[cfg(feature = "gecko")] let kind = generic::GradientKind::Radial(shape, position);
{
let pos = GradientPosition::Modern(position);
let kind = generic::GradientKind::Radial(shape, pos, None);
(kind, reverse_stops) (kind, reverse_stops)
}
#[cfg(not(feature = "gecko"))]
{
let kind = generic::GradientKind::Radial(shape, position, None);
(kind, reverse_stops)
}
}, },
_ => { _ => {
let e = SelectorParseErrorKind::UnexpectedIdent(ident.clone()); 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 { impl GradientKind {
/// Parses a linear gradient. /// Parses a linear gradient.
/// CompatMode can change during `-moz-` prefixed gradient parsing if it come across a `to` keyword. /// 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)) Ok(generic::GradientKind::Linear(direction))
} }
fn parse_radial<'i, 't>( fn parse_radial<'i, 't>(
context: &ParserContext, context: &ParserContext,
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
compat_mode: &mut CompatMode, compat_mode: &mut CompatMode,
) -> Result<Self, ParseError<'i>> { ) -> Result<Self, ParseError<'i>> {
let (shape, position, angle, moz_position) = match *compat_mode { let (shape, position) = match *compat_mode {
CompatMode::Modern => { CompatMode::Modern => {
let shape = input.try(|i| EndingShape::parse(context, i, *compat_mode)); let shape = input.try(|i| EndingShape::parse(context, i, *compat_mode));
let position = input.try(|i| { let position = input.try(|i| {
i.expect_ident_matching("at")?; i.expect_ident_matching("at")?;
Position::parse(context, i) Position::parse(context, i)
}); });
(shape, position.ok(), None, None) (shape, position.ok())
},
// 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())
}, },
_ => { _ => {
let position = input.try(|i| Position::parse(context, i)); let position = input.try(|i| Position::parse(context, i));
@ -623,11 +543,11 @@ impl GradientKind {
} }
EndingShape::parse(context, i, *compat_mode) 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()?; input.expect_comma()?;
} }
@ -635,35 +555,8 @@ impl GradientKind {
generic::EndingShape::Ellipse(Ellipse::Extent(ShapeExtent::FarthestCorner)) 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()); let position = position.unwrap_or(Position::center());
#[cfg(feature = "gecko")] Ok(generic::GradientKind::Radial(shape, position))
{
return Ok(generic::GradientKind::Radial(
shape,
GradientPosition::Modern(position),
angle,
));
}
#[cfg(not(feature = "gecko"))]
{
return Ok(generic::GradientKind::Radial(shape, position, angle));
}
} }
} }
@ -673,35 +566,6 @@ impl generic::LineDirection for LineDirection {
LineDirection::Angle(ref angle) => angle.degrees() == 180.0, LineDirection::Angle(ref angle) => angle.degrees() == 180.0,
LineDirection::Vertical(Y::Bottom) if compat_mode == CompatMode::Modern => true, LineDirection::Vertical(Y::Bottom) if compat_mode == CompatMode::Modern => true,
LineDirection::Vertical(Y::Top) 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, _ => false,
} }
} }
@ -732,21 +596,6 @@ impl generic::LineDirection for LineDirection {
dest.write_str(" ")?; dest.write_str(" ")?;
y.to_css(dest) 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>, input: &mut Parser<'i, 't>,
compat_mode: &mut CompatMode, compat_mode: &mut CompatMode,
) -> Result<Self, ParseError<'i>> { ) -> 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: // Gradients allow unitless zero angles as an exception, see:
// https://github.com/w3c/csswg-drafts/issues/1162 // https://github.com/w3c/csswg-drafts/issues/1162
if let Ok(angle) = input.try(|i| Angle::parse_with_unitless(context, i)) { if let Ok(angle) = input.try(|i| Angle::parse_with_unitless(context, i)) {
return Ok(LineDirection::Angle(angle)); return Ok(LineDirection::Angle(angle));
} }
None
};
input.try(|i| { input.try(|i| {
let to_ident = i.try(|i| i.expect_ident_matching("to")); 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(x) = i.try(X::parse) {
if let Ok(y) = i.try(Y::parse) { if let Ok(y) = i.try(Y::parse) {
return Ok(LineDirection::Corner(x, y)); 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 { impl EndingShape {
fn parse<'i, 't>( fn parse<'i, 't>(
context: &ParserContext, context: &ParserContext,
@ -878,9 +690,6 @@ impl EndingShape {
ShapeExtent::FarthestCorner, 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(length) = input.try(|i| Length::parse(context, i)) {
if let Ok(y) = input.try(|i| LengthPercentage::parse(context, i)) { if let Ok(y) = input.try(|i| LengthPercentage::parse(context, i)) {
if compat_mode == CompatMode::Modern { if compat_mode == CompatMode::Modern {
@ -907,7 +716,6 @@ impl EndingShape {
return Ok(generic::EndingShape::Circle(Circle::Radius(length))); return Ok(generic::EndingShape::Circle(Circle::Radius(length)));
} }
}
input.try(|i| { input.try(|i| {
let x = Percentage::parse(context, i)?; let x = Percentage::parse(context, i)?;
let y = if let Ok(y) = i.try(|i| LengthPercentage::parse(context, i)) { let y = if let Ok(y) = i.try(|i| LengthPercentage::parse(context, i)) {

View file

@ -14,7 +14,6 @@ use crate::values::computed::LengthPercentage as ComputedLengthPercentage;
use crate::values::computed::{Context, Percentage, ToComputedValue}; use crate::values::computed::{Context, Percentage, ToComputedValue};
use crate::values::generics::position::Position as GenericPosition; use crate::values::generics::position::Position as GenericPosition;
use crate::values::generics::position::ZIndex as GenericZIndex; use crate::values::generics::position::ZIndex as GenericZIndex;
use crate::values::specified::transform::OriginComponent;
use crate::values::specified::{AllowQuirks, Integer, LengthPercentage}; use crate::values::specified::{AllowQuirks, Integer, LengthPercentage};
use crate::values::{Either, None_}; use crate::values::{Either, None_};
use crate::Zero; use crate::Zero;
@ -326,117 +325,6 @@ impl Side for Y {
} }
} }
/// The specified value of a legacy CSS `<position>`
/// Modern position syntax supports 3 and 4-value syntax. That means:
/// If three or four values are given, then each <percentage> or <length> represents an offset
/// and must be preceded by a keyword, which specifies from which edge the offset is given.
/// For example, `bottom 10px right 20px` represents a `10px` vertical
/// offset up from the bottom edge and a `20px` horizontal offset leftward from the right edge.
/// If three values are given, the missing offset is assumed to be zero.
/// But for some historical reasons we need to keep CSS Level 2 syntax which only supports up to
/// 2-value. This type represents this 2-value syntax.
pub type LegacyPosition = GenericPosition<LegacyHPosition, LegacyVPosition>;
/// The specified value of a horizontal position.
pub type LegacyHPosition = OriginComponent<X>;
/// The specified value of a vertical position.
pub type LegacyVPosition = OriginComponent<Y>;
impl Parse for LegacyPosition {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Self::parse_quirky(context, input, AllowQuirks::No)
}
}
impl LegacyPosition {
/// Parses a `<position>`, with quirks.
pub fn parse_quirky<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> {
match input.try(|i| OriginComponent::parse(context, i)) {
Ok(x_pos @ OriginComponent::Center) => {
if let Ok(y_pos) = input.try(|i| OriginComponent::parse(context, i)) {
return Ok(Self::new(x_pos, y_pos));
}
let x_pos = input
.try(|i| OriginComponent::parse(context, i))
.unwrap_or(x_pos);
let y_pos = OriginComponent::Center;
return Ok(Self::new(x_pos, y_pos));
},
Ok(OriginComponent::Side(x_keyword)) => {
if let Ok(y_keyword) = input.try(Y::parse) {
let x_pos = OriginComponent::Side(x_keyword);
let y_pos = OriginComponent::Side(y_keyword);
return Ok(Self::new(x_pos, y_pos));
}
let x_pos = OriginComponent::Side(x_keyword);
if let Ok(y_lp) =
input.try(|i| LengthPercentage::parse_quirky(context, i, allow_quirks))
{
return Ok(Self::new(x_pos, OriginComponent::Length(y_lp)));
}
let _ = input.try(|i| i.expect_ident_matching("center"));
return Ok(Self::new(x_pos, OriginComponent::Center));
},
Ok(x_pos @ OriginComponent::Length(_)) => {
if let Ok(y_keyword) = input.try(Y::parse) {
let y_pos = OriginComponent::Side(y_keyword);
return Ok(Self::new(x_pos, y_pos));
}
if let Ok(y_lp) =
input.try(|i| LengthPercentage::parse_quirky(context, i, allow_quirks))
{
let y_pos = OriginComponent::Length(y_lp);
return Ok(Self::new(x_pos, y_pos));
}
let _ = input.try(|i| i.expect_ident_matching("center"));
return Ok(Self::new(x_pos, OriginComponent::Center));
},
Err(_) => {},
}
let y_keyword = Y::parse(input)?;
let x_pos: Result<_, ParseError> = input.try(|i| {
if let Ok(x_keyword) = i.try(X::parse) {
let x_pos = OriginComponent::Side(x_keyword);
return Ok(x_pos);
}
i.expect_ident_matching("center")?;
Ok(OriginComponent::Center)
});
if let Ok(x_pos) = x_pos {
let y_pos = OriginComponent::Side(y_keyword);
return Ok(Self::new(x_pos, y_pos));
}
let x_pos = OriginComponent::Center;
let y_pos = OriginComponent::Side(y_keyword);
Ok(Self::new(x_pos, y_pos))
}
/// `center center`
#[inline]
pub fn center() -> Self {
Self::new(OriginComponent::Center, OriginComponent::Center)
}
}
impl ToCss for LegacyPosition {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
self.horizontal.to_css(dest)?;
dest.write_str(" ")?;
self.vertical.to_css(dest)
}
}
#[derive( #[derive(
Clone, Clone,
Copy, Copy,