style: Derive more length stuff, and shrink MaxLength / MozLength's repr(C) representation.

This patch:

 * Makes LengthPercentageOrAuto generic, and removes a bunch of code fo
   LengthPercentageOrNone, which was used only for servo and now can use the
   normal MaxLength (with a cfg() guard for the ExtremumLength variant).

 * Shrinks MaxLength / MozLength's repr(C) reperesentation by reducing enum
   nesting. The shrinking is in preparation for using them from C++ too, though
   that'd be a different bug.

 * Moves NonNegative usage to the proper places so that stuff for them can be
   derived.

I did this on top of bug 1523071 to prove both that it could be possible and
that stuff wasn't too messy. It got a bit messy, but just because of a bug I
had fixed in bindgen long time ago already, so this updates bindgen's patch
version to grab a fix instead of ugly workarounds :)

Differential Revision: https://phabricator.services.mozilla.com/D17762
This commit is contained in:
Emilio Cobos Álvarez 2019-01-27 01:03:44 +01:00
parent 8dad956513
commit a68bc29b96
17 changed files with 337 additions and 520 deletions

View file

@ -99,7 +99,7 @@ item_types = ["enums", "structs", "typedefs"]
template<typename T> inline nscoord ResolveWith(T aPercentageGetter) const; template<typename T> inline nscoord ResolveWith(T aPercentageGetter) const;
""" """
"LengthPercentageOrAuto" = """ "GenericLengthPercentageOrAuto" = """
inline const StyleLengthPercentage& AsLengthPercentage() const; inline const StyleLengthPercentage& AsLengthPercentage() const;
inline bool HasPercent() const; inline bool HasPercent() const;
inline bool ConvertsToLength() const; inline bool ConvertsToLength() const;

View file

@ -27,6 +27,7 @@ use crate::values::computed::{LengthPercentageOrAuto, NonNegativeLengthPercentag
use crate::values::generics::box_::VerticalAlign; use crate::values::generics::box_::VerticalAlign;
use crate::values::generics::grid::{TrackListValue, TrackSize}; use crate::values::generics::grid::{TrackListValue, TrackSize};
use crate::values::generics::image::{CompatMode, GradientItem, Image as GenericImage}; use crate::values::generics::image::{CompatMode, GradientItem, Image as GenericImage};
use crate::values::generics::length::LengthPercentageOrAuto as GenericLengthPercentageOrAuto;
use crate::values::generics::rect::Rect; use crate::values::generics::rect::Rect;
use crate::values::generics::NonNegative; use crate::values::generics::NonNegative;
use app_units::Au; use app_units::Au;
@ -62,19 +63,19 @@ impl From<nsStyleCoord_CalcValue> for LengthPercentage {
} }
} }
impl LengthPercentageOrAuto { impl NonNegativeLengthPercentageOrAuto {
/// Convert this value in an appropriate `nsStyleCoord::CalcValue`. /// Convert this value in an appropriate `nsStyleCoord::CalcValue`.
pub fn to_calc_value(&self) -> Option<nsStyleCoord_CalcValue> { pub fn to_calc_value(&self) -> Option<nsStyleCoord_CalcValue> {
match *self { match *self {
LengthPercentageOrAuto::LengthPercentage(len) => Some(From::from(len)), GenericLengthPercentageOrAuto::LengthPercentage(ref len) => Some(From::from(len.0)),
LengthPercentageOrAuto::Auto => None, GenericLengthPercentageOrAuto::Auto => None,
} }
} }
} }
impl From<nsStyleCoord_CalcValue> for LengthPercentageOrAuto { impl From<nsStyleCoord_CalcValue> for LengthPercentageOrAuto {
fn from(other: nsStyleCoord_CalcValue) -> LengthPercentageOrAuto { fn from(other: nsStyleCoord_CalcValue) -> LengthPercentageOrAuto {
LengthPercentageOrAuto::LengthPercentage(LengthPercentage::from(other)) GenericLengthPercentageOrAuto::LengthPercentage(LengthPercentage::from(other))
} }
} }
@ -82,7 +83,7 @@ impl From<nsStyleCoord_CalcValue> for LengthPercentageOrAuto {
// disappear as we move more stuff to cbindgen. // disappear as we move more stuff to cbindgen.
impl From<nsStyleCoord_CalcValue> for NonNegativeLengthPercentageOrAuto { impl From<nsStyleCoord_CalcValue> for NonNegativeLengthPercentageOrAuto {
fn from(other: nsStyleCoord_CalcValue) -> Self { fn from(other: nsStyleCoord_CalcValue) -> Self {
NonNegative(LengthPercentageOrAuto::LengthPercentage( GenericLengthPercentageOrAuto::LengthPercentage(NonNegative(
LengthPercentage::with_clamping_mode( LengthPercentage::with_clamping_mode(
Au(other.mLength).into(), Au(other.mLength).into(),
if other.mHasPercent { if other.mHasPercent {

View file

@ -14,15 +14,15 @@ use crate::media_queries::Device;
use crate::values::computed::basic_shape::ShapeRadius as ComputedShapeRadius; use crate::values::computed::basic_shape::ShapeRadius as ComputedShapeRadius;
use crate::values::computed::FlexBasis as ComputedFlexBasis; use crate::values::computed::FlexBasis as ComputedFlexBasis;
use crate::values::computed::{Angle, ExtremumLength, Length, LengthPercentage}; use crate::values::computed::{Angle, ExtremumLength, Length, LengthPercentage};
use crate::values::computed::{LengthPercentageOrAuto, Percentage};
use crate::values::computed::{LengthPercentageOrNone, Number, NumberOrPercentage};
use crate::values::computed::{MaxLength as ComputedMaxLength, MozLength as ComputedMozLength}; use crate::values::computed::{MaxLength as ComputedMaxLength, MozLength as ComputedMozLength};
use crate::values::computed::{NonNegativeLengthPercentage, Percentage};
use crate::values::computed::{Number, NumberOrPercentage};
use crate::values::generics::basic_shape::ShapeRadius; use crate::values::generics::basic_shape::ShapeRadius;
use crate::values::generics::box_::Perspective; use crate::values::generics::box_::Perspective;
use crate::values::generics::flex::FlexBasis; use crate::values::generics::flex::FlexBasis;
use crate::values::generics::gecko::ScrollSnapPoint; use crate::values::generics::gecko::ScrollSnapPoint;
use crate::values::generics::grid::{TrackBreadth, TrackKeyword}; use crate::values::generics::grid::{TrackBreadth, TrackKeyword};
use crate::values::generics::length::{MaxLength, MozLength}; use crate::values::generics::length::{LengthPercentageOrAuto, MaxLength, MozLength};
use crate::values::generics::{CounterStyleOrNone, NonNegative}; use crate::values::generics::{CounterStyleOrNone, NonNegative};
use crate::values::{Auto, Either, None_, Normal}; use crate::values::{Auto, Either, None_, Normal};
use crate::Atom; use crate::Atom;
@ -183,7 +183,10 @@ impl GeckoStyleCoordConvertible for Length {
} }
} }
impl GeckoStyleCoordConvertible for LengthPercentageOrAuto { impl<LengthPercentage> GeckoStyleCoordConvertible for LengthPercentageOrAuto<LengthPercentage>
where
LengthPercentage: GeckoStyleCoordConvertible,
{
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) { fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self { match *self {
LengthPercentageOrAuto::Auto => coord.set_value(CoordDataValue::Auto), LengthPercentageOrAuto::Auto => coord.set_value(CoordDataValue::Auto),
@ -200,23 +203,6 @@ impl GeckoStyleCoordConvertible for LengthPercentageOrAuto {
} }
} }
impl GeckoStyleCoordConvertible for LengthPercentageOrNone {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self {
LengthPercentageOrNone::None => coord.set_value(CoordDataValue::None),
LengthPercentageOrNone::LengthPercentage(ref lp) => lp.to_gecko_style_coord(coord),
}
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
match coord.as_value() {
CoordDataValue::None => Some(LengthPercentageOrNone::None),
_ => LengthPercentage::from_gecko_style_coord(coord)
.map(LengthPercentageOrNone::LengthPercentage),
}
}
}
impl<L: GeckoStyleCoordConvertible> GeckoStyleCoordConvertible for TrackBreadth<L> { impl<L: GeckoStyleCoordConvertible> GeckoStyleCoordConvertible for TrackBreadth<L> {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) { fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self { match *self {
@ -367,34 +353,40 @@ impl GeckoStyleCoordConvertible for ExtremumLength {
impl GeckoStyleCoordConvertible for ComputedMozLength { impl GeckoStyleCoordConvertible for ComputedMozLength {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) { fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self { match *self {
MozLength::LengthPercentageOrAuto(ref lpoa) => lpoa.to_gecko_style_coord(coord), MozLength::LengthPercentage(ref lpoa) => lpoa.to_gecko_style_coord(coord),
MozLength::Auto => coord.set_value(CoordDataValue::Auto),
MozLength::ExtremumLength(ref e) => e.to_gecko_style_coord(coord), MozLength::ExtremumLength(ref e) => e.to_gecko_style_coord(coord),
} }
} }
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> { fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
LengthPercentageOrAuto::from_gecko_style_coord(coord) if let CoordDataValue::Auto = coord.as_value() {
.map(MozLength::LengthPercentageOrAuto) return Some(MozLength::Auto);
.or_else(|| { }
ExtremumLength::from_gecko_style_coord(coord).map(MozLength::ExtremumLength) if let Some(lp) = NonNegativeLengthPercentage::from_gecko_style_coord(coord) {
}) return Some(MozLength::LengthPercentage(lp));
}
ExtremumLength::from_gecko_style_coord(coord).map(MozLength::ExtremumLength)
} }
} }
impl GeckoStyleCoordConvertible for ComputedMaxLength { impl GeckoStyleCoordConvertible for ComputedMaxLength {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) { fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self { match *self {
MaxLength::LengthPercentageOrNone(ref lpon) => lpon.to_gecko_style_coord(coord), MaxLength::LengthPercentage(ref lpon) => lpon.to_gecko_style_coord(coord),
MaxLength::None => coord.set_value(CoordDataValue::None),
MaxLength::ExtremumLength(ref e) => e.to_gecko_style_coord(coord), MaxLength::ExtremumLength(ref e) => e.to_gecko_style_coord(coord),
} }
} }
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> { fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
LengthPercentageOrNone::from_gecko_style_coord(coord) if let CoordDataValue::None = coord.as_value() {
.map(MaxLength::LengthPercentageOrNone) return Some(MaxLength::None);
.or_else(|| { }
ExtremumLength::from_gecko_style_coord(coord).map(MaxLength::ExtremumLength) if let Some(lp) = NonNegativeLengthPercentage::from_gecko_style_coord(coord) {
}) return Some(MaxLength::LengthPercentage(lp));
}
ExtremumLength::from_gecko_style_coord(coord).map(MaxLength::ExtremumLength)
} }
} }

View file

@ -1390,7 +1390,6 @@ impl Clone for ${style_struct.gecko_struct_name} {
"LengthOrNormal": impl_style_coord, "LengthOrNormal": impl_style_coord,
"LengthPercentage": impl_simple, "LengthPercentage": impl_simple,
"LengthPercentageOrAuto": impl_style_coord, "LengthPercentageOrAuto": impl_style_coord,
"LengthPercentageOrNone": impl_style_coord,
"MaxLength": impl_style_coord, "MaxLength": impl_style_coord,
"MozLength": impl_style_coord, "MozLength": impl_style_coord,
"MozScriptMinSize": impl_absolute_length, "MozScriptMinSize": impl_absolute_length,
@ -3831,11 +3830,11 @@ fn static_assert() {
BackgroundSize::Explicit { width: explicit_width, height: explicit_height } => { BackgroundSize::Explicit { width: explicit_width, height: explicit_height } => {
let mut w_type = nsStyleImageLayers_Size_DimensionType::eAuto; let mut w_type = nsStyleImageLayers_Size_DimensionType::eAuto;
let mut h_type = nsStyleImageLayers_Size_DimensionType::eAuto; let mut h_type = nsStyleImageLayers_Size_DimensionType::eAuto;
if let Some(w) = explicit_width.0.to_calc_value() { if let Some(w) = explicit_width.to_calc_value() {
width = w; width = w;
w_type = nsStyleImageLayers_Size_DimensionType::eLengthPercentage; w_type = nsStyleImageLayers_Size_DimensionType::eLengthPercentage;
} }
if let Some(h) = explicit_height.0.to_calc_value() { if let Some(h) = explicit_height.to_calc_value() {
height = h; height = h;
h_type = nsStyleImageLayers_Size_DimensionType::eLengthPercentage; h_type = nsStyleImageLayers_Size_DimensionType::eLengthPercentage;
} }

View file

@ -13,7 +13,7 @@
${helpers.predefined_type( ${helpers.predefined_type(
side, side,
"LengthPercentageOrAuto", "LengthPercentageOrAuto",
"computed::LengthPercentageOrAuto::Auto", "computed::LengthPercentageOrAuto::auto()",
spec="https://www.w3.org/TR/CSS2/visuren.html#propdef-%s" % side, spec="https://www.w3.org/TR/CSS2/visuren.html#propdef-%s" % side,
flags="GETCS_NEEDS_LAYOUT_FLUSH", flags="GETCS_NEEDS_LAYOUT_FLUSH",
animation_value_type="ComputedValue", animation_value_type="ComputedValue",
@ -27,7 +27,7 @@
${helpers.predefined_type( ${helpers.predefined_type(
"inset-%s" % side, "inset-%s" % side,
"LengthPercentageOrAuto", "LengthPercentageOrAuto",
"computed::LengthPercentageOrAuto::Auto", "computed::LengthPercentageOrAuto::auto()",
spec="https://drafts.csswg.org/css-logical-props/#propdef-inset-%s" % side, spec="https://drafts.csswg.org/css-logical-props/#propdef-inset-%s" % side,
flags="GETCS_NEEDS_LAYOUT_FLUSH", flags="GETCS_NEEDS_LAYOUT_FLUSH",
alias="offset-%s:layout.css.offset-logical-properties.enabled" % side, alias="offset-%s:layout.css.offset-logical-properties.enabled" % side,
@ -270,24 +270,12 @@ ${helpers.predefined_type(
animation_value_type="MozLength", animation_value_type="MozLength",
servo_restyle_damage="reflow", servo_restyle_damage="reflow",
)} )}
${helpers.predefined_type(
"max-%s" % size,
"MaxLength",
"computed::MaxLength::none()",
logical=logical,
logical_group="max-size",
allow_quirks=not logical,
spec=spec % size,
animation_value_type="MaxLength",
servo_restyle_damage="reflow",
)}
% else: % else:
// servo versions (no keyword support) // servo versions (no keyword support)
${helpers.predefined_type( ${helpers.predefined_type(
size, size,
"LengthPercentageOrAuto", "NonNegativeLengthPercentageOrAuto",
"computed::LengthPercentageOrAuto::Auto", "computed::NonNegativeLengthPercentageOrAuto::auto()",
"parse_non_negative",
spec=spec % size, spec=spec % size,
logical_group="size", logical_group="size",
allow_quirks=not logical, allow_quirks=not logical,
@ -296,9 +284,8 @@ ${helpers.predefined_type(
)} )}
${helpers.predefined_type( ${helpers.predefined_type(
"min-%s" % size, "min-%s" % size,
"LengthPercentage", "NonNegativeLengthPercentage",
"computed::LengthPercentage::zero()", "computed::NonNegativeLengthPercentage::zero()",
"parse_non_negative",
spec=spec % ("min-%s" % size), spec=spec % ("min-%s" % size),
logical_group="min-size", logical_group="min-size",
animation_value_type="ComputedValue", animation_value_type="ComputedValue",
@ -306,19 +293,18 @@ ${helpers.predefined_type(
allow_quirks=not logical, allow_quirks=not logical,
servo_restyle_damage="reflow", servo_restyle_damage="reflow",
)} )}
${helpers.predefined_type(
"max-%s" % size,
"LengthPercentageOrNone",
"computed::LengthPercentageOrNone::None",
"parse_non_negative",
spec=spec % ("max-%s" % size),
logical_group="max-size",
animation_value_type="ComputedValue",
logical=logical,
allow_quirks=not logical,
servo_restyle_damage="reflow",
)}
% endif % endif
${helpers.predefined_type(
"max-%s" % size,
"MaxLength",
"computed::MaxLength::none()",
logical=logical,
logical_group="max-size",
allow_quirks=not logical,
spec=spec % size,
animation_value_type="MaxLength",
servo_restyle_damage="reflow",
)}
% endfor % endfor
${helpers.single_keyword( ${helpers.single_keyword(

View file

@ -3016,7 +3016,7 @@ impl ComputedValuesInner {
/// Get the logical computed inline size. /// Get the logical computed inline size.
#[inline] #[inline]
pub fn content_inline_size(&self) -> computed::LengthPercentageOrAuto { pub fn content_inline_size(&self) -> computed::NonNegativeLengthPercentageOrAuto {
let position_style = self.get_position(); let position_style = self.get_position();
if self.writing_mode.is_vertical() { if self.writing_mode.is_vertical() {
position_style.height position_style.height
@ -3027,35 +3027,35 @@ impl ComputedValuesInner {
/// Get the logical computed block size. /// Get the logical computed block size.
#[inline] #[inline]
pub fn content_block_size(&self) -> computed::LengthPercentageOrAuto { pub fn content_block_size(&self) -> computed::NonNegativeLengthPercentageOrAuto {
let position_style = self.get_position(); let position_style = self.get_position();
if self.writing_mode.is_vertical() { position_style.width } else { position_style.height } if self.writing_mode.is_vertical() { position_style.width } else { position_style.height }
} }
/// Get the logical computed min inline size. /// Get the logical computed min inline size.
#[inline] #[inline]
pub fn min_inline_size(&self) -> computed::LengthPercentage { pub fn min_inline_size(&self) -> computed::NonNegativeLengthPercentage {
let position_style = self.get_position(); let position_style = self.get_position();
if self.writing_mode.is_vertical() { position_style.min_height } else { position_style.min_width } if self.writing_mode.is_vertical() { position_style.min_height } else { position_style.min_width }
} }
/// Get the logical computed min block size. /// Get the logical computed min block size.
#[inline] #[inline]
pub fn min_block_size(&self) -> computed::LengthPercentage { pub fn min_block_size(&self) -> computed::NonNegativeLengthPercentage {
let position_style = self.get_position(); let position_style = self.get_position();
if self.writing_mode.is_vertical() { position_style.min_width } else { position_style.min_height } if self.writing_mode.is_vertical() { position_style.min_width } else { position_style.min_height }
} }
/// Get the logical computed max inline size. /// Get the logical computed max inline size.
#[inline] #[inline]
pub fn max_inline_size(&self) -> computed::LengthPercentageOrNone { pub fn max_inline_size(&self) -> computed::MaxLength {
let position_style = self.get_position(); let position_style = self.get_position();
if self.writing_mode.is_vertical() { position_style.max_height } else { position_style.max_width } if self.writing_mode.is_vertical() { position_style.max_height } else { position_style.max_width }
} }
/// Get the logical computed max block size. /// Get the logical computed max block size.
#[inline] #[inline]
pub fn max_block_size(&self) -> computed::LengthPercentageOrNone { pub fn max_block_size(&self) -> computed::MaxLength {
let position_style = self.get_position(); let position_style = self.get_position();
if self.writing_mode.is_vertical() { position_style.max_width } else { position_style.max_height } if self.writing_mode.is_vertical() { position_style.max_width } else { position_style.max_height }
} }

View file

@ -11,16 +11,17 @@ use crate::context::QuirksMode;
use crate::error_reporting::ContextualParseError; use crate::error_reporting::ContextualParseError;
use crate::font_metrics::get_metrics_provider_for_product; use crate::font_metrics::get_metrics_provider_for_product;
use crate::media_queries::Device; use crate::media_queries::Device;
use crate::parser::ParserContext; use crate::parser::{Parse, ParserContext};
use crate::properties::StyleBuilder; use crate::properties::StyleBuilder;
use crate::rule_cache::RuleCacheConditions; use crate::rule_cache::RuleCacheConditions;
use crate::shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard}; use crate::shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard};
use crate::str::CssStringWriter; use crate::str::CssStringWriter;
use crate::stylesheets::{Origin, StylesheetInDocument}; use crate::stylesheets::{Origin, StylesheetInDocument};
use crate::values::computed::{Context, ToComputedValue}; use crate::values::computed::{Context, ToComputedValue};
use crate::values::specified::{ use crate::values::generics::length::LengthPercentageOrAuto;
self, LengthPercentageOrAuto, NoCalcLength, ViewportPercentageLength, use crate::values::generics::NonNegative;
}; use crate::values::specified::{self, NoCalcLength};
use crate::values::specified::{NonNegativeLengthPercentageOrAuto, ViewportPercentageLength};
use app_units::Au; use app_units::Au;
use cssparser::CowRcStr; use cssparser::CowRcStr;
use cssparser::{parse_important, AtRuleParser, DeclarationListParser, DeclarationParser, Parser}; use cssparser::{parse_important, AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
@ -151,7 +152,7 @@ trait FromMeta: Sized {
#[cfg_attr(feature = "servo", derive(MallocSizeOf))] #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
#[derive(Clone, Debug, PartialEq, ToCss)] #[derive(Clone, Debug, PartialEq, ToCss)]
pub enum ViewportLength { pub enum ViewportLength {
Specified(LengthPercentageOrAuto), Specified(NonNegativeLengthPercentageOrAuto),
ExtendToZoom, ExtendToZoom,
} }
@ -159,9 +160,9 @@ impl FromMeta for ViewportLength {
fn from_meta(value: &str) -> Option<ViewportLength> { fn from_meta(value: &str) -> Option<ViewportLength> {
macro_rules! specified { macro_rules! specified {
($value:expr) => { ($value:expr) => {
ViewportLength::Specified(LengthPercentageOrAuto::LengthPercentage( ViewportLength::Specified(LengthPercentageOrAuto::LengthPercentage(NonNegative(
specified::LengthPercentage::Length($value), specified::LengthPercentage::Length($value),
)) )))
}; };
} }
@ -188,7 +189,7 @@ impl ViewportLength {
) -> Result<Self, ParseError<'i>> { ) -> Result<Self, ParseError<'i>> {
// we explicitly do not accept 'extend-to-zoom', since it is a UA // we explicitly do not accept 'extend-to-zoom', since it is a UA
// internal value for <META> viewport translation // internal value for <META> viewport translation
LengthPercentageOrAuto::parse_non_negative(context, input).map(ViewportLength::Specified) NonNegativeLengthPercentageOrAuto::parse(context, input).map(ViewportLength::Specified)
} }
} }

View file

@ -4,10 +4,8 @@
//! Animation implementation for various length-related types. //! Animation implementation for various length-related types.
use super::{Animate, Procedure, ToAnimatedValue}; use super::{Animate, Procedure};
use crate::values::computed::length::LengthPercentage; use crate::values::computed::length::LengthPercentage;
use crate::values::computed::MaxLength as ComputedMaxLength;
use crate::values::computed::MozLength as ComputedMozLength;
use crate::values::computed::Percentage; use crate::values::computed::Percentage;
/// <https://drafts.csswg.org/css-transitions/#animtype-lpcalc> /// <https://drafts.csswg.org/css-transitions/#animtype-lpcalc>
@ -38,51 +36,3 @@ impl Animate for LengthPercentage {
)) ))
} }
} }
// FIXME(emilio): These should use NonNegative<> instead.
impl ToAnimatedValue for ComputedMaxLength {
type AnimatedValue = Self;
#[inline]
fn to_animated_value(self) -> Self {
self
}
#[inline]
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
use crate::values::computed::LengthPercentageOrNone;
use crate::values::generics::length::MaxLength as GenericMaxLength;
match animated {
GenericMaxLength::LengthPercentageOrNone(lpn) => {
let result = match lpn {
LengthPercentageOrNone::LengthPercentage(len) => {
LengthPercentageOrNone::LengthPercentage(len.clamp_to_non_negative())
},
LengthPercentageOrNone::None => lpn,
};
GenericMaxLength::LengthPercentageOrNone(result)
},
_ => animated,
}
}
}
impl ToAnimatedValue for ComputedMozLength {
type AnimatedValue = Self;
#[inline]
fn to_animated_value(self) -> Self {
self
}
#[inline]
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
use crate::values::generics::length::MozLength as GenericMozLength;
match animated {
GenericMozLength::LengthPercentageOrAuto(lpa) => {
GenericMozLength::LengthPercentageOrAuto(lpa.clamp_to_non_negative())
},
_ => animated,
}
}
}

View file

@ -4,20 +4,21 @@
//! Computed types for CSS values related to backgrounds. //! Computed types for CSS values related to backgrounds.
use crate::values::computed::length::NonNegativeLengthPercentageOrAuto; use crate::values::computed::length::NonNegativeLengthPercentage;
use crate::values::generics::background::BackgroundSize as GenericBackgroundSize; use crate::values::generics::background::BackgroundSize as GenericBackgroundSize;
use crate::values::generics::length::LengthPercentageOrAuto;
pub use crate::values::specified::background::BackgroundRepeat; pub use crate::values::specified::background::BackgroundRepeat;
/// A computed value for the `background-size` property. /// A computed value for the `background-size` property.
pub type BackgroundSize = GenericBackgroundSize<NonNegativeLengthPercentageOrAuto>; pub type BackgroundSize = GenericBackgroundSize<NonNegativeLengthPercentage>;
impl BackgroundSize { impl BackgroundSize {
/// Returns `auto auto`. /// Returns `auto auto`.
pub fn auto() -> Self { pub fn auto() -> Self {
GenericBackgroundSize::Explicit { GenericBackgroundSize::Explicit {
width: NonNegativeLengthPercentageOrAuto::auto(), width: LengthPercentageOrAuto::auto(),
height: NonNegativeLengthPercentageOrAuto::auto(), height: LengthPercentageOrAuto::auto(),
} }
} }
} }

View file

@ -7,13 +7,15 @@
use super::{Context, Number, Percentage, ToComputedValue}; use super::{Context, Number, Percentage, ToComputedValue};
use crate::values::animated::ToAnimatedValue; use crate::values::animated::ToAnimatedValue;
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance}; use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
use crate::values::generics::length::MaxLength as GenericMaxLength; use crate::values::generics::length as generics;
use crate::values::generics::length::MozLength as GenericMozLength; use crate::values::generics::length::{
MaxLength as GenericMaxLength, MozLength as GenericMozLength,
};
use crate::values::generics::transform::IsZeroLength; use crate::values::generics::transform::IsZeroLength;
use crate::values::generics::NonNegative; use crate::values::generics::NonNegative;
use crate::values::specified::length::ViewportPercentageLength; use crate::values::specified::length::ViewportPercentageLength;
use crate::values::specified::length::{AbsoluteLength, FontBaseSize, FontRelativeLength}; use crate::values::specified::length::{AbsoluteLength, FontBaseSize, FontRelativeLength};
use crate::values::{specified, Auto, CSSFloat, Either, IsAuto, Normal}; use crate::values::{specified, Auto, CSSFloat, Either, Normal};
use app_units::Au; use app_units::Au;
use ordered_float::NotNan; use ordered_float::NotNan;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
@ -452,151 +454,61 @@ impl IsZeroLength for LengthPercentage {
} }
} }
#[allow(missing_docs)] /// Some boilerplate to share between negative and non-negative
#[css(derive_debug)] /// length-percentage or auto.
#[derive( macro_rules! computed_length_percentage_or_auto {
Animate, Clone, ComputeSquaredDistance, Copy, MallocSizeOf, PartialEq, ToAnimatedZero, ToCss, ($inner:ty) => {
)] /// Returns the `0` value.
#[repr(C, u8)] #[inline]
pub enum LengthPercentageOrAuto { pub fn zero() -> Self {
LengthPercentage(LengthPercentage), generics::LengthPercentageOrAuto::LengthPercentage(<$inner>::zero())
Auto, }
}
impl LengthPercentageOrAuto { /// Returns the used value.
/// Returns the `0` value. #[inline]
#[inline] pub fn to_used_value(&self, percentage_basis: Au) -> Option<Au> {
pub fn zero() -> Self { match *self {
LengthPercentageOrAuto::LengthPercentage(LengthPercentage::zero()) generics::GenericLengthPercentageOrAuto::Auto => None,
} generics::GenericLengthPercentageOrAuto::LengthPercentage(ref lp) => {
} Some(lp.to_used_value(percentage_basis))
}
}
}
/// A wrapper of LengthPercentageOrAuto, whose value must be >= 0. /// Returns true if the computed value is absolute 0 or 0%.
pub type NonNegativeLengthPercentageOrAuto = NonNegative<LengthPercentageOrAuto>; #[inline]
pub fn is_definitely_zero(&self) -> bool {
impl IsAuto for NonNegativeLengthPercentageOrAuto { use values::generics::length::LengthPercentageOrAuto::*;
#[inline] match *self {
fn is_auto(&self) -> bool { LengthPercentage(ref l) => l.is_definitely_zero(),
*self == Self::auto() Auto => false,
} }
}
impl NonNegativeLengthPercentageOrAuto {
/// `auto`
#[inline]
pub fn auto() -> Self {
NonNegative(LengthPercentageOrAuto::Auto)
}
}
impl ToAnimatedValue for NonNegativeLengthPercentageOrAuto {
type AnimatedValue = LengthPercentageOrAuto;
#[inline]
fn to_animated_value(self) -> Self::AnimatedValue {
self.0
}
#[inline]
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
NonNegative(animated.clamp_to_non_negative())
}
}
impl LengthPercentageOrAuto {
/// Returns true if the computed value is absolute 0 or 0%.
#[inline]
pub fn is_definitely_zero(&self) -> bool {
use self::LengthPercentageOrAuto::*;
match *self {
LengthPercentage(ref l) => l.is_definitely_zero(),
Auto => false,
} }
} }
}
/// A computed type for `<length-percentage> | auto`.
pub type LengthPercentageOrAuto = generics::GenericLengthPercentageOrAuto<LengthPercentage>;
impl LengthPercentageOrAuto {
/// Clamps the value to a non-negative value. /// Clamps the value to a non-negative value.
pub fn clamp_to_non_negative(self) -> Self { pub fn clamp_to_non_negative(self) -> Self {
use self::LengthPercentageOrAuto::*; use values::generics::length::LengthPercentageOrAuto::*;
match self { match self {
LengthPercentage(l) => LengthPercentage(l.clamp_to_non_negative()), LengthPercentage(l) => LengthPercentage(l.clamp_to_non_negative()),
Auto => Auto, Auto => Auto,
} }
} }
computed_length_percentage_or_auto!(LengthPercentage);
} }
impl ToComputedValue for specified::LengthPercentageOrAuto { /// A wrapper of LengthPercentageOrAuto, whose value must be >= 0.
type ComputedValue = LengthPercentageOrAuto; pub type NonNegativeLengthPercentageOrAuto =
generics::LengthPercentageOrAuto<NonNegativeLengthPercentage>;
#[inline] impl NonNegativeLengthPercentageOrAuto {
fn to_computed_value(&self, context: &Context) -> LengthPercentageOrAuto { computed_length_percentage_or_auto!(NonNegativeLengthPercentage);
match *self {
specified::LengthPercentageOrAuto::LengthPercentage(ref value) => {
LengthPercentageOrAuto::LengthPercentage(value.to_computed_value(context))
},
specified::LengthPercentageOrAuto::Auto => LengthPercentageOrAuto::Auto,
}
}
#[inline]
fn from_computed_value(computed: &LengthPercentageOrAuto) -> Self {
match *computed {
LengthPercentageOrAuto::Auto => specified::LengthPercentageOrAuto::Auto,
LengthPercentageOrAuto::LengthPercentage(ref value) => {
specified::LengthPercentageOrAuto::LengthPercentage(
ToComputedValue::from_computed_value(value),
)
},
}
}
}
#[allow(missing_docs)]
#[css(derive_debug)]
#[derive(
Animate, Clone, ComputeSquaredDistance, Copy, MallocSizeOf, PartialEq, ToAnimatedZero, ToCss,
)]
pub enum LengthPercentageOrNone {
LengthPercentage(LengthPercentage),
None,
}
impl LengthPercentageOrNone {
/// Returns the used value.
pub fn to_used_value(&self, containing_length: Au) -> Option<Au> {
match *self {
LengthPercentageOrNone::None => None,
LengthPercentageOrNone::LengthPercentage(ref lp) => {
Some(lp.to_used_value(containing_length))
},
}
}
}
// FIXME(emilio): Derive this.
impl ToComputedValue for specified::LengthPercentageOrNone {
type ComputedValue = LengthPercentageOrNone;
#[inline]
fn to_computed_value(&self, context: &Context) -> LengthPercentageOrNone {
match *self {
specified::LengthPercentageOrNone::LengthPercentage(ref value) => {
LengthPercentageOrNone::LengthPercentage(value.to_computed_value(context))
},
specified::LengthPercentageOrNone::None => LengthPercentageOrNone::None,
}
}
#[inline]
fn from_computed_value(computed: &LengthPercentageOrNone) -> Self {
match *computed {
LengthPercentageOrNone::None => specified::LengthPercentageOrNone::None,
LengthPercentageOrNone::LengthPercentage(value) => {
specified::LengthPercentageOrNone::LengthPercentage(
ToComputedValue::from_computed_value(&value),
)
},
}
}
} }
/// A wrapper of LengthPercentage, whose value must be >= 0. /// A wrapper of LengthPercentage, whose value must be >= 0.
@ -630,13 +542,6 @@ impl From<LengthPercentage> for NonNegativeLengthPercentage {
} }
} }
impl From<NonNegativeLengthPercentage> for LengthPercentage {
#[inline]
fn from(lp: NonNegativeLengthPercentage) -> LengthPercentage {
lp.0
}
}
// TODO(emilio): This is a really generic impl which is only needed to implement // TODO(emilio): This is a really generic impl which is only needed to implement
// Animated and co for Spacing<>. Get rid of this, probably? // Animated and co for Spacing<>. Get rid of this, probably?
impl From<Au> for LengthPercentage { impl From<Au> for LengthPercentage {
@ -650,7 +555,7 @@ impl NonNegativeLengthPercentage {
/// Get zero value. /// Get zero value.
#[inline] #[inline]
pub fn zero() -> Self { pub fn zero() -> Self {
NonNegative::<LengthPercentage>(LengthPercentage::zero()) NonNegative(LengthPercentage::zero())
} }
/// Returns true if the computed value is absolute 0 or 0%. /// Returns true if the computed value is absolute 0 or 0%.
@ -662,7 +567,26 @@ impl NonNegativeLengthPercentage {
/// Returns the used value. /// Returns the used value.
#[inline] #[inline]
pub fn to_used_value(&self, containing_length: Au) -> Au { pub fn to_used_value(&self, containing_length: Au) -> Au {
self.0.to_used_value(containing_length) let resolved = self.0.to_used_value(containing_length);
::std::cmp::max(resolved, Au(0))
}
/// Convert the computed value into used value.
#[inline]
pub fn maybe_to_used_value(&self, containing_length: Option<Au>) -> Option<Au> {
let resolved = self.0.maybe_to_used_value(containing_length)?;
Some(::std::cmp::max(resolved, Au(0)))
}
}
#[cfg(feature = "servo")]
impl MaxLength {
/// Convert the computed value into used value.
pub fn to_used_value(&self, percentage_basis: Au) -> Option<Au> {
match *self {
GenericMaxLength::None => None,
GenericMaxLength::LengthPercentage(ref lp) => Some(lp.to_used_value(percentage_basis)),
}
} }
} }
@ -881,6 +805,8 @@ pub type NonNegativeLengthPercentageOrNormal = Either<NonNegativeLengthPercentag
Parse, Parse,
PartialEq, PartialEq,
SpecifiedValueInfo, SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue, ToComputedValue,
ToCss, ToCss,
)] )]
@ -895,23 +821,7 @@ pub enum ExtremumLength {
} }
/// A computed value for `min-width`, `min-height`, `width` or `height` property. /// A computed value for `min-width`, `min-height`, `width` or `height` property.
pub type MozLength = GenericMozLength<LengthPercentageOrAuto>; pub type MozLength = GenericMozLength<NonNegativeLengthPercentage>;
impl MozLength {
/// Returns the `auto` value.
#[inline]
pub fn auto() -> Self {
GenericMozLength::LengthPercentageOrAuto(LengthPercentageOrAuto::Auto)
}
}
/// A computed value for `max-width` or `min-height` property. /// A computed value for `max-width` or `min-height` property.
pub type MaxLength = GenericMaxLength<LengthPercentageOrNone>; pub type MaxLength = GenericMaxLength<NonNegativeLengthPercentage>;
impl MaxLength {
/// Returns the `none` value.
#[inline]
pub fn none() -> Self {
GenericMaxLength::LengthPercentageOrNone(LengthPercentageOrNone::None)
}
}

View file

@ -62,7 +62,7 @@ pub use self::gecko::ScrollSnapPoint;
pub use self::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection, MozImageRect}; pub use self::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection, MozImageRect};
pub use self::length::{CSSPixelLength, ExtremumLength, NonNegativeLength}; pub use self::length::{CSSPixelLength, ExtremumLength, NonNegativeLength};
pub use self::length::{Length, LengthOrNumber, LengthPercentage}; pub use self::length::{Length, LengthOrNumber, LengthPercentage};
pub use self::length::{LengthPercentageOrAuto, LengthPercentageOrNone, MaxLength, MozLength}; pub use self::length::{LengthPercentageOrAuto, MaxLength, MozLength};
pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto}; pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto};
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub use self::list::ListStyleType; pub use self::list::ListStyleType;

View file

@ -4,7 +4,7 @@
//! Generic types for CSS values related to backgrounds. //! Generic types for CSS values related to backgrounds.
use crate::values::IsAuto; use crate::values::generics::length::LengthPercentageOrAuto;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss}; use style_traits::{CssWriter, ToCss};
@ -22,13 +22,13 @@ use style_traits::{CssWriter, ToCss};
ToAnimatedZero, ToAnimatedZero,
ToComputedValue, ToComputedValue,
)] )]
pub enum BackgroundSize<LengthPercentageOrAuto> { pub enum BackgroundSize<LengthPercentage> {
/// `<width> <height>` /// `<width> <height>`
Explicit { Explicit {
/// Explicit width. /// Explicit width.
width: LengthPercentageOrAuto, width: LengthPercentageOrAuto<LengthPercentage>,
/// Explicit height. /// Explicit height.
height: LengthPercentageOrAuto, height: LengthPercentageOrAuto<LengthPercentage>,
}, },
/// `cover` /// `cover`
#[animation(error)] #[animation(error)]
@ -38,9 +38,9 @@ pub enum BackgroundSize<LengthPercentageOrAuto> {
Contain, Contain,
} }
impl<LengthPercentageOrAuto> ToCss for BackgroundSize<LengthPercentageOrAuto> impl<LengthPercentage> ToCss for BackgroundSize<LengthPercentage>
where where
LengthPercentageOrAuto: ToCss + IsAuto, LengthPercentage: 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

View file

@ -4,7 +4,75 @@
//! Generic types for CSS values related to length. //! Generic types for CSS values related to length.
use crate::parser::{Parse, ParserContext};
use crate::values::computed::ExtremumLength; use crate::values::computed::ExtremumLength;
use cssparser::Parser;
use style_traits::ParseError;
/// A `<length-percentage> | auto` value.
#[allow(missing_docs)]
#[derive(
Animate,
Clone,
ComputeSquaredDistance,
Copy,
Debug,
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
ToCss,
)]
#[repr(C, u8)]
pub enum GenericLengthPercentageOrAuto<LengthPercent> {
LengthPercentage(LengthPercent),
Auto,
}
pub use self::GenericLengthPercentageOrAuto as LengthPercentageOrAuto;
impl<LengthPercentage> LengthPercentageOrAuto<LengthPercentage> {
/// `auto` value.
#[inline]
pub fn auto() -> Self {
LengthPercentageOrAuto::Auto
}
/// Whether this is the `auto` value.
#[inline]
pub fn is_auto(&self) -> bool {
matches!(*self, LengthPercentageOrAuto::Auto)
}
/// A helper function to parse this with quirks or not and so forth.
pub fn parse_with<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
parser: impl FnOnce(
&ParserContext,
&mut Parser<'i, 't>,
) -> Result<LengthPercentage, ParseError<'i>>,
) -> Result<Self, ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
return Ok(LengthPercentageOrAuto::Auto);
}
Ok(LengthPercentageOrAuto::LengthPercentage(parser(
context, input,
)?))
}
}
impl<LengthPercentage: Parse> Parse for LengthPercentageOrAuto<LengthPercentage> {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Self::parse_with(context, input, LengthPercentage::parse)
}
}
/// A generic value for the `width`, `height`, `min-width`, or `min-height` property. /// A generic value for the `width`, `height`, `min-width`, or `min-height` property.
/// ///
@ -13,25 +81,35 @@ use crate::values::computed::ExtremumLength;
/// ///
/// Note that it only accepts non-negative values. /// Note that it only accepts non-negative values.
#[allow(missing_docs)] #[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
#[derive( #[derive(
Animate, Animate,
Clone, Clone,
ComputeSquaredDistance, ComputeSquaredDistance,
Copy, Copy,
Debug, Debug,
MallocSizeOf,
PartialEq, PartialEq,
SpecifiedValueInfo, SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero, ToAnimatedZero,
ToComputedValue, ToComputedValue,
ToCss, ToCss,
)] )]
pub enum MozLength<LengthPercentageOrAuto> { pub enum MozLength<LengthPercentage> {
LengthPercentageOrAuto(LengthPercentageOrAuto), LengthPercentage(LengthPercentage),
Auto,
#[animation(error)] #[animation(error)]
ExtremumLength(ExtremumLength), ExtremumLength(ExtremumLength),
} }
impl<LengthPercentage> MozLength<LengthPercentage> {
/// `auto` value.
#[inline]
pub fn auto() -> Self {
MozLength::Auto
}
}
/// A generic value for the `max-width` or `max-height` property. /// A generic value for the `max-width` or `max-height` property.
#[allow(missing_docs)] #[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))] #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
@ -43,12 +121,23 @@ pub enum MozLength<LengthPercentageOrAuto> {
Debug, Debug,
PartialEq, PartialEq,
SpecifiedValueInfo, SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero, ToAnimatedZero,
ToComputedValue, ToComputedValue,
ToCss, ToCss,
)] )]
pub enum MaxLength<LengthPercentageOrNone> { pub enum MaxLength<LengthPercentage> {
LengthPercentageOrNone(LengthPercentageOrNone), LengthPercentage(LengthPercentage),
None,
#[cfg(feature = "gecko")]
#[animation(error)] #[animation(error)]
ExtremumLength(ExtremumLength), ExtremumLength(ExtremumLength),
} }
impl<LengthPercentage> MaxLength<LengthPercentage> {
/// `none` value.
#[inline]
pub fn none() -> Self {
MaxLength::None
}
}

View file

@ -6,14 +6,16 @@
use crate::parser::{Parse, ParserContext}; use crate::parser::{Parse, ParserContext};
use crate::values::generics::background::BackgroundSize as GenericBackgroundSize; use crate::values::generics::background::BackgroundSize as GenericBackgroundSize;
use crate::values::specified::length::NonNegativeLengthPercentageOrAuto; use crate::values::specified::length::{
NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto,
};
use cssparser::Parser; use cssparser::Parser;
use selectors::parser::SelectorParseErrorKind; use selectors::parser::SelectorParseErrorKind;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, ToCss}; use style_traits::{CssWriter, ParseError, ToCss};
/// A specified value for the `background-size` property. /// A specified value for the `background-size` property.
pub type BackgroundSize = GenericBackgroundSize<NonNegativeLengthPercentageOrAuto>; pub type BackgroundSize = GenericBackgroundSize<NonNegativeLengthPercentage>;
impl Parse for BackgroundSize { impl Parse for BackgroundSize {
fn parse<'i, 't>( fn parse<'i, 't>(

View file

@ -5,8 +5,8 @@
//! Specified types for legacy Gecko-only properties. //! Specified types for legacy Gecko-only properties.
use crate::parser::{Parse, ParserContext}; use crate::parser::{Parse, ParserContext};
use crate::values::computed::{self, LengthPercentage};
use crate::values::computed::length::CSSPixelLength; use crate::values::computed::length::CSSPixelLength;
use crate::values::computed::{self, LengthPercentage};
use crate::values::generics::gecko::ScrollSnapPoint as GenericScrollSnapPoint; use crate::values::generics::gecko::ScrollSnapPoint as GenericScrollSnapPoint;
use crate::values::generics::rect::Rect; use crate::values::generics::rect::Rect;
use crate::values::specified::length::LengthPercentage as SpecifiedLengthPercentage; use crate::values::specified::length::LengthPercentage as SpecifiedLengthPercentage;
@ -28,8 +28,8 @@ impl Parse for ScrollSnapPoint {
} }
input.expect_function_matching("repeat")?; input.expect_function_matching("repeat")?;
// FIXME(emilio): This won't clamp properly when animating. // FIXME(emilio): This won't clamp properly when animating.
let length = let length = input
input.parse_nested_block(|i| SpecifiedLengthPercentage::parse_non_negative(context, i))?; .parse_nested_block(|i| SpecifiedLengthPercentage::parse_non_negative(context, i))?;
Ok(GenericScrollSnapPoint::Repeat(length)) Ok(GenericScrollSnapPoint::Repeat(length))
} }
} }
@ -49,9 +49,9 @@ fn parse_pixel_or_percent<'i, 't>(
_ => Err(()), _ => Err(()),
} }
}, },
Token::Percentage { unit_value, .. } => Ok( Token::Percentage { unit_value, .. } => Ok(LengthPercentage::new_percent(
LengthPercentage::new_percent(computed::Percentage(unit_value)) computed::Percentage(unit_value),
), )),
_ => Err(()), _ => Err(()),
}; };
value.map_err(|()| location.new_custom_error(StyleParseErrorKind::UnspecifiedError)) value.map_err(|()| location.new_custom_error(StyleParseErrorKind::UnspecifiedError))

View file

@ -10,12 +10,14 @@ use super::{AllowQuirks, Number, Percentage, ToComputedValue};
use crate::font_metrics::FontMetricsQueryResult; use crate::font_metrics::FontMetricsQueryResult;
use crate::parser::{Parse, ParserContext}; use crate::parser::{Parse, ParserContext};
use crate::values::computed::{self, CSSPixelLength, Context, ExtremumLength}; use crate::values::computed::{self, CSSPixelLength, Context, ExtremumLength};
use crate::values::generics::length::MaxLength as GenericMaxLength; use crate::values::generics::length as generics;
use crate::values::generics::length::MozLength as GenericMozLength; use crate::values::generics::length::{
MaxLength as GenericMaxLength, MozLength as GenericMozLength,
};
use crate::values::generics::transform::IsZeroLength; use crate::values::generics::transform::IsZeroLength;
use crate::values::generics::NonNegative; use crate::values::generics::NonNegative;
use crate::values::specified::calc::CalcNode; use crate::values::specified::calc::CalcNode;
use crate::values::{Auto, CSSFloat, Either, IsAuto, Normal}; use crate::values::{Auto, CSSFloat, Either, Normal};
use app_units::Au; use app_units::Au;
use cssparser::{Parser, Token}; use cssparser::{Parser, Token};
use euclid::Size2D; use euclid::Size2D;
@ -785,6 +787,16 @@ impl From<computed::Percentage> for LengthPercentage {
} }
} }
impl Parse for LengthPercentage {
#[inline]
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Self::parse_quirky(context, input, AllowQuirks::No)
}
}
impl LengthPercentage { impl LengthPercentage {
#[inline] #[inline]
/// Returns a `zero` length. /// Returns a `zero` length.
@ -844,12 +856,26 @@ impl LengthPercentage {
Ok(LengthPercentage::Calc(Box::new(calc))) Ok(LengthPercentage::Calc(Box::new(calc)))
} }
/// Parses allowing the unitless length quirk.
/// <https://quirks.spec.whatwg.org/#the-unitless-length-quirk>
#[inline]
pub fn parse_quirky<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> {
Self::parse_internal(context, input, AllowedNumericType::All, allow_quirks)
}
/// Parse a non-negative length. /// Parse a non-negative length.
///
/// FIXME(emilio): This should be not public and we should use
/// NonNegativeLengthPercentage instead.
#[inline] #[inline]
pub fn parse_non_negative<'i, 't>( pub fn parse_non_negative<'i, 't>(
context: &ParserContext, context: &ParserContext,
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
) -> Result<LengthPercentage, ParseError<'i>> { ) -> Result<Self, ParseError<'i>> {
Self::parse_non_negative_quirky(context, input, AllowQuirks::No) Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
} }
@ -859,7 +885,7 @@ impl LengthPercentage {
context: &ParserContext, context: &ParserContext,
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks, allow_quirks: AllowQuirks,
) -> Result<LengthPercentage, ParseError<'i>> { ) -> Result<Self, ParseError<'i>> {
Self::parse_internal( Self::parse_internal(
context, context,
input, input,
@ -869,29 +895,6 @@ impl LengthPercentage {
} }
} }
impl Parse for LengthPercentage {
#[inline]
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Self::parse_quirky(context, input, AllowQuirks::No)
}
}
impl LengthPercentage {
/// Parses a length or a percentage, allowing the unitless length quirk.
/// <https://quirks.spec.whatwg.org/#the-unitless-length-quirk>
#[inline]
pub fn parse_quirky<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> {
Self::parse_internal(context, input, AllowedNumericType::All, allow_quirks)
}
}
impl IsZeroLength for LengthPercentage { impl IsZeroLength for LengthPercentage {
#[inline] #[inline]
fn is_zero_length(&self) -> bool { fn is_zero_length(&self) -> bool {
@ -903,189 +906,64 @@ impl IsZeroLength for LengthPercentage {
} }
} }
/// Either a `<length>`, a `<percentage>`, or the `auto` keyword. /// A specified type for `<length-percentage> | auto`.
#[allow(missing_docs)] pub type LengthPercentageOrAuto = generics::LengthPercentageOrAuto<LengthPercentage>;
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum LengthPercentageOrAuto {
LengthPercentage(LengthPercentage),
Auto,
}
impl LengthPercentageOrAuto { impl LengthPercentageOrAuto {
fn parse_internal<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
num_context: AllowedNumericType,
allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
return Ok(LengthPercentageOrAuto::Auto);
}
Ok(LengthPercentageOrAuto::LengthPercentage(
LengthPercentage::parse_internal(context, input, num_context, allow_quirks)?,
))
}
/// Parse a non-negative length, percentage, or auto.
#[inline]
pub fn parse_non_negative<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<LengthPercentageOrAuto, ParseError<'i>> {
Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
}
/// Parse a non-negative length, percentage, or auto.
#[inline]
pub fn parse_non_negative_quirky<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> {
Self::parse_internal(
context,
input,
AllowedNumericType::NonNegative,
allow_quirks,
)
}
/// Returns the `auto` value.
pub fn auto() -> Self {
LengthPercentageOrAuto::Auto
}
/// Returns a value representing a `0` length. /// Returns a value representing a `0` length.
pub fn zero() -> Self { pub fn zero() -> Self {
LengthPercentageOrAuto::LengthPercentage(LengthPercentage::zero()) generics::LengthPercentageOrAuto::LengthPercentage(LengthPercentage::zero())
} }
/// Returns a value representing `0%`. /// Returns a value representing `0%`.
#[inline] #[inline]
pub fn zero_percent() -> Self { pub fn zero_percent() -> Self {
LengthPercentageOrAuto::LengthPercentage(LengthPercentage::zero_percent()) generics::LengthPercentageOrAuto::LengthPercentage(LengthPercentage::zero_percent())
} }
/// Parses, with quirks. /// Parses a length or a percentage, allowing the unitless length quirk.
/// <https://quirks.spec.whatwg.org/#the-unitless-length-quirk>
#[inline] #[inline]
pub fn parse_quirky<'i, 't>( pub fn parse_quirky<'i, 't>(
context: &ParserContext, context: &ParserContext,
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks, allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> { ) -> Result<Self, ParseError<'i>> {
Self::parse_internal(context, input, AllowedNumericType::All, allow_quirks) Self::parse_with(context, input, |context, input| {
} LengthPercentage::parse_quirky(context, input, allow_quirks)
} })
impl Parse for LengthPercentageOrAuto {
#[inline]
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Self::parse_quirky(context, input, AllowQuirks::No)
} }
} }
/// A wrapper of LengthPercentageOrAuto, whose value must be >= 0. /// A wrapper of LengthPercentageOrAuto, whose value must be >= 0.
pub type NonNegativeLengthPercentageOrAuto = NonNegative<LengthPercentageOrAuto>; pub type NonNegativeLengthPercentageOrAuto =
generics::LengthPercentageOrAuto<NonNegativeLengthPercentage>;
impl IsAuto for NonNegativeLengthPercentageOrAuto {
#[inline]
fn is_auto(&self) -> bool {
*self == Self::auto()
}
}
impl NonNegativeLengthPercentageOrAuto { impl NonNegativeLengthPercentageOrAuto {
/// 0 /// Returns a value representing a `0` length.
#[inline]
pub fn zero() -> Self { pub fn zero() -> Self {
NonNegative(LengthPercentageOrAuto::zero()) generics::LengthPercentageOrAuto::LengthPercentage(NonNegativeLengthPercentage::zero())
} }
/// 0% /// Returns a value representing `0%`.
#[inline] #[inline]
pub fn zero_percent() -> Self { pub fn zero_percent() -> Self {
NonNegative(LengthPercentageOrAuto::zero_percent()) generics::LengthPercentageOrAuto::LengthPercentage(
} NonNegativeLengthPercentage::zero_percent(),
/// `auto`
#[inline]
pub fn auto() -> Self {
NonNegative(LengthPercentageOrAuto::Auto)
}
}
impl Parse for NonNegativeLengthPercentageOrAuto {
#[inline]
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Ok(NonNegative(LengthPercentageOrAuto::parse_non_negative(
context, input,
)?))
}
}
/// Either a `<length>`, a `<percentage>`, or the `none` keyword.
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
#[allow(missing_docs)]
pub enum LengthPercentageOrNone {
LengthPercentage(LengthPercentage),
None,
}
impl LengthPercentageOrNone {
fn parse_internal<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
num_context: AllowedNumericType,
allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> {
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
return Ok(LengthPercentageOrNone::None);
}
Ok(LengthPercentageOrNone::LengthPercentage(
LengthPercentage::parse_internal(context, input, num_context, allow_quirks)?,
))
}
/// Parse a non-negative LengthPercentageOrNone.
#[inline]
pub fn parse_non_negative<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
}
/// Parse a non-negative LengthPercentageOrNone, with quirks.
#[inline]
pub fn parse_non_negative_quirky<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> {
Self::parse_internal(
context,
input,
AllowedNumericType::NonNegative,
allow_quirks,
) )
} }
}
impl Parse for LengthPercentageOrNone { /// Parses a non-negative length-percentage, allowing the unitless length
/// quirk.
#[inline] #[inline]
fn parse<'i, 't>( pub fn parse_quirky<'i, 't>(
context: &ParserContext, context: &ParserContext,
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> { ) -> Result<Self, ParseError<'i>> {
Self::parse_internal(context, input, AllowedNumericType::All, AllowQuirks::No) Self::parse_with(context, input, |context, input| {
NonNegativeLengthPercentage::parse_quirky(context, input, allow_quirks)
})
} }
} }
@ -1101,7 +979,7 @@ pub type NonNegativeLengthPercentageOrNormal = Either<NonNegativeLengthPercentag
impl From<NoCalcLength> for NonNegativeLengthPercentage { impl From<NoCalcLength> for NonNegativeLengthPercentage {
#[inline] #[inline]
fn from(len: NoCalcLength) -> Self { fn from(len: NoCalcLength) -> Self {
NonNegative::<LengthPercentage>(LengthPercentage::from(len)) NonNegative(LengthPercentage::from(len))
} }
} }
@ -1111,7 +989,7 @@ impl Parse for NonNegativeLengthPercentage {
context: &ParserContext, context: &ParserContext,
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> { ) -> Result<Self, ParseError<'i>> {
LengthPercentage::parse_non_negative(context, input).map(NonNegative::<LengthPercentage>) Self::parse_quirky(context, input, AllowQuirks::No)
} }
} }
@ -1119,7 +997,13 @@ impl NonNegativeLengthPercentage {
#[inline] #[inline]
/// Returns a `zero` length. /// Returns a `zero` length.
pub fn zero() -> Self { pub fn zero() -> Self {
NonNegative::<LengthPercentage>(LengthPercentage::zero()) NonNegative(LengthPercentage::zero())
}
#[inline]
/// Returns a `0%` value.
pub fn zero_percent() -> Self {
NonNegative(LengthPercentage::zero_percent())
} }
/// Parses a length or a percentage, allowing the unitless length quirk. /// Parses a length or a percentage, allowing the unitless length quirk.
@ -1130,8 +1014,7 @@ impl NonNegativeLengthPercentage {
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks, allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> { ) -> Result<Self, ParseError<'i>> {
LengthPercentage::parse_non_negative_quirky(context, input, allow_quirks) LengthPercentage::parse_non_negative_quirky(context, input, allow_quirks).map(NonNegative)
.map(NonNegative::<LengthPercentage>)
} }
} }
@ -1168,7 +1051,7 @@ impl LengthOrNumber {
} }
/// A specified value for `min-width`, `min-height`, `width` or `height` property. /// A specified value for `min-width`, `min-height`, `width` or `height` property.
pub type MozLength = GenericMozLength<LengthPercentageOrAuto>; pub type MozLength = GenericMozLength<NonNegativeLengthPercentage>;
impl Parse for MozLength { impl Parse for MozLength {
fn parse<'i, 't>( fn parse<'i, 't>(
@ -1190,26 +1073,23 @@ impl MozLength {
return Ok(GenericMozLength::ExtremumLength(l)); return Ok(GenericMozLength::ExtremumLength(l));
} }
let length = if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
LengthPercentageOrAuto::parse_non_negative_quirky(context, input, allow_quirks)?; return Ok(GenericMozLength::Auto);
Ok(GenericMozLength::LengthPercentageOrAuto(length)) }
}
/// Returns `auto`. let length = NonNegativeLengthPercentage::parse_quirky(context, input, allow_quirks)?;
#[inline] Ok(GenericMozLength::LengthPercentage(length))
pub fn auto() -> Self {
GenericMozLength::LengthPercentageOrAuto(LengthPercentageOrAuto::auto())
} }
/// Returns `0%`. /// Returns `0%`.
#[inline] #[inline]
pub fn zero_percent() -> Self { pub fn zero_percent() -> Self {
GenericMozLength::LengthPercentageOrAuto(LengthPercentageOrAuto::zero_percent()) GenericMozLength::LengthPercentage(NonNegativeLengthPercentage::zero_percent())
} }
} }
/// A specified value for `max-width` or `max-height` property. /// A specified value for `max-width` or `max-height` property.
pub type MaxLength = GenericMaxLength<LengthPercentageOrNone>; pub type MaxLength = GenericMaxLength<NonNegativeLengthPercentage>;
impl Parse for MaxLength { impl Parse for MaxLength {
fn parse<'i, 't>( fn parse<'i, 't>(
@ -1227,12 +1107,18 @@ impl MaxLength {
input: &mut Parser<'i, 't>, input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks, allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> { ) -> Result<Self, ParseError<'i>> {
if let Ok(l) = input.try(ExtremumLength::parse) { #[cfg(feature = "gecko")]
return Ok(GenericMaxLength::ExtremumLength(l)); {
if let Ok(l) = input.try(ExtremumLength::parse) {
return Ok(GenericMaxLength::ExtremumLength(l));
}
} }
let length = if input.try(|i| i.expect_ident_matching("none")).is_ok() {
LengthPercentageOrNone::parse_non_negative_quirky(context, input, allow_quirks)?; return Ok(GenericMaxLength::None);
Ok(GenericMaxLength::LengthPercentageOrNone(length)) }
let length = NonNegativeLengthPercentage::parse_quirky(context, input, allow_quirks)?;
Ok(GenericMaxLength::LengthPercentage(length))
} }
} }

View file

@ -59,7 +59,7 @@ pub use self::image::{GradientItem, GradientKind, Image, ImageLayer, MozImageRec
pub use self::length::{AbsoluteLength, CalcLengthPercentage, CharacterWidth}; pub use self::length::{AbsoluteLength, CalcLengthPercentage, CharacterWidth};
pub use self::length::{FontRelativeLength, Length, LengthOrNumber}; pub use self::length::{FontRelativeLength, Length, LengthOrNumber};
pub use self::length::{LengthPercentage, LengthPercentageOrAuto}; pub use self::length::{LengthPercentage, LengthPercentageOrAuto};
pub use self::length::{LengthPercentageOrNone, MaxLength, MozLength}; pub use self::length::{MaxLength, MozLength};
pub use self::length::{NoCalcLength, ViewportPercentageLength}; pub use self::length::{NoCalcLength, ViewportPercentageLength};
pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto}; pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto};
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]