diff options
-rw-r--r-- | components/style/gecko/values.rs | 71 | ||||
-rw-r--r-- | components/style/properties/gecko.mako.rs | 2 | ||||
-rw-r--r-- | components/style/properties/helpers/animated_properties.mako.rs | 29 | ||||
-rw-r--r-- | components/style/properties/longhand/position.mako.rs | 47 | ||||
-rw-r--r-- | components/style/values/computed/length.rs | 112 | ||||
-rw-r--r-- | components/style/values/computed/mod.rs | 1 | ||||
-rw-r--r-- | components/style/values/mod.rs | 8 | ||||
-rw-r--r-- | components/style/values/specified/length.rs | 95 | ||||
-rw-r--r-- | components/style/values/specified/mod.rs | 1 |
9 files changed, 349 insertions, 17 deletions
diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs index 6d3f374c430..cccb5ca697f 100644 --- a/components/style/gecko/values.rs +++ b/components/style/gecko/values.rs @@ -11,9 +11,10 @@ use cssparser::RGBA; use gecko_bindings::structs::{nsStyleCoord, StyleGridTrackBreadth, StyleShapeRadius}; use gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue}; use std::cmp::max; -use values::{Auto, Either, None_, Normal}; +use values::{Auto, Either, ExtremumLength, None_, Normal}; use values::computed::{Angle, LengthOrPercentageOrNone, Number}; use values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto}; +use values::computed::{MaxLength, MinLength}; use values::computed::basic_shape::ShapeRadius; use values::specified::grid::{TrackBreadth, TrackKeyword}; @@ -271,6 +272,74 @@ impl GeckoStyleCoordConvertible for Normal { } } +impl GeckoStyleCoordConvertible for ExtremumLength { + fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) { + use gecko_bindings::structs::{NS_STYLE_WIDTH_AVAILABLE, NS_STYLE_WIDTH_FIT_CONTENT}; + use gecko_bindings::structs::{NS_STYLE_WIDTH_MAX_CONTENT, NS_STYLE_WIDTH_MIN_CONTENT}; + coord.set_value(CoordDataValue::Enumerated( + match *self { + ExtremumLength::MaxContent => NS_STYLE_WIDTH_MAX_CONTENT, + ExtremumLength::MinContent => NS_STYLE_WIDTH_MIN_CONTENT, + ExtremumLength::FitContent => NS_STYLE_WIDTH_FIT_CONTENT, + ExtremumLength::FillAvailable => NS_STYLE_WIDTH_AVAILABLE, + } + )) + } + + fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> { + use gecko_bindings::structs::{NS_STYLE_WIDTH_AVAILABLE, NS_STYLE_WIDTH_FIT_CONTENT}; + use gecko_bindings::structs::{NS_STYLE_WIDTH_MAX_CONTENT, NS_STYLE_WIDTH_MIN_CONTENT}; + match coord.as_value() { + CoordDataValue::Enumerated(NS_STYLE_WIDTH_MAX_CONTENT) => + Some(ExtremumLength::MaxContent), + CoordDataValue::Enumerated(NS_STYLE_WIDTH_MIN_CONTENT) => + Some(ExtremumLength::MinContent), + CoordDataValue::Enumerated(NS_STYLE_WIDTH_FIT_CONTENT) => + Some(ExtremumLength::FitContent), + CoordDataValue::Enumerated(NS_STYLE_WIDTH_AVAILABLE) => Some(ExtremumLength::FillAvailable), + _ => None, + } + } +} + +impl GeckoStyleCoordConvertible for MinLength { + fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) { + match *self { + MinLength::LengthOrPercentage(ref lop) => lop.to_gecko_style_coord(coord), + MinLength::Auto => coord.set_value(CoordDataValue::Auto), + MinLength::ExtremumLength(ref e) => e.to_gecko_style_coord(coord), + } + } + + fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> { + LengthOrPercentage::from_gecko_style_coord(coord).map(MinLength::LengthOrPercentage) + .or_else(|| ExtremumLength::from_gecko_style_coord(coord).map(MinLength::ExtremumLength)) + .or_else(|| match coord.as_value() { + CoordDataValue::Auto => Some(MinLength::Auto), + _ => None, + }) + } +} + +impl GeckoStyleCoordConvertible for MaxLength { + fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) { + match *self { + MaxLength::LengthOrPercentage(ref lop) => lop.to_gecko_style_coord(coord), + MaxLength::None => coord.set_value(CoordDataValue::None), + MaxLength::ExtremumLength(ref e) => e.to_gecko_style_coord(coord), + } + } + + fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> { + LengthOrPercentage::from_gecko_style_coord(coord).map(MaxLength::LengthOrPercentage) + .or_else(|| ExtremumLength::from_gecko_style_coord(coord).map(MaxLength::ExtremumLength)) + .or_else(|| match coord.as_value() { + CoordDataValue::None => Some(MaxLength::None), + _ => None, + }) + } +} + /// Convert a given RGBA value to `nscolor`. pub fn convert_rgba_to_nscolor(rgba: &RGBA) -> u32 { ((rgba.alpha as u32) << 24) | diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index c50c51e75b9..ba834f0141a 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -635,6 +635,8 @@ impl Debug for ${style_struct.gecko_struct_name} { "LengthOrPercentageOrAuto": impl_style_coord, "LengthOrPercentageOrNone": impl_style_coord, "LengthOrNone": impl_style_coord, + "MaxLength": impl_style_coord, + "MinLength": impl_style_coord, "Number": impl_simple, "Opacity": impl_simple, "CSSColor": impl_color, diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index 0c2b59eb2da..e145420befd 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -33,6 +33,7 @@ use values::Either; use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone}; use values::computed::{BorderRadiusSize, ClipRect, LengthOrNone}; use values::computed::{CalcLengthOrPercentage, Context, LengthOrPercentage}; +use values::computed::{MaxLength, MinLength}; use values::computed::position::{HorizontalPosition, Position, VerticalPosition}; use values::computed::ToComputedValue; use values::specified::Angle as SpecifiedAngle; @@ -630,6 +631,34 @@ impl Interpolate for LengthOrPercentageOrNone { } } +/// https://drafts.csswg.org/css-transitions/#animtype-lpcalc +impl Interpolate for MinLength { + #[inline] + fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> { + match (*self, *other) { + (MinLength::LengthOrPercentage(ref this), + MinLength::LengthOrPercentage(ref other)) => { + this.interpolate(other, progress).map(MinLength::LengthOrPercentage) + } + _ => Err(()), + } + } +} + +/// https://drafts.csswg.org/css-transitions/#animtype-lpcalc +impl Interpolate for MaxLength { + #[inline] + fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> { + match (*self, *other) { + (MaxLength::LengthOrPercentage(ref this), + MaxLength::LengthOrPercentage(ref other)) => { + this.interpolate(other, progress).map(MaxLength::LengthOrPercentage) + } + _ => Err(()), + } + } +} + /// https://drafts.csswg.org/css-transitions/#animtype-number /// https://drafts.csswg.org/css-transitions/#animtype-length impl Interpolate for LineHeight { diff --git a/components/style/properties/longhand/position.mako.rs b/components/style/properties/longhand/position.mako.rs index 97b8d150365..c9431031b3f 100644 --- a/components/style/properties/longhand/position.mako.rs +++ b/components/style/properties/longhand/position.mako.rs @@ -218,23 +218,40 @@ ${helpers.predefined_type("flex-basis", spec=spec % size, animatable=True, logical = logical)} - // min-width, min-height, min-block-size, min-inline-size - ${helpers.predefined_type("min-%s" % size, - "LengthOrPercentage", - "computed::LengthOrPercentage::Length(Au(0))", - "parse_non_negative", - needs_context=False, - spec=spec % ("min-%s" % size), - animatable=True, logical = logical)} + % if product == "gecko": + // min-width, min-height, min-block-size, min-inline-size + ${helpers.predefined_type("min-%s" % size, + "MinLength", + "computed::MinLength::LengthOrPercentage(" + + "computed::LengthOrPercentage::Length(Au(0)))", + spec=spec % ("min-%s" % size), + animatable=True, logical = logical)} + % else: + ${helpers.predefined_type("min-%s" % size, + "LengthOrPercentage", + "computed::LengthOrPercentage::Length(Au(0))", + "parse_non_negative", + needs_context=False, + spec=spec % ("min-%s" % size), + animatable=True, logical = logical)} + % endif // max-width, max-height, max-block-size, max-inline-size - ${helpers.predefined_type("max-%s" % size, - "LengthOrPercentageOrNone", - "computed::LengthOrPercentageOrNone::None", - "parse_non_negative", - needs_context=False, - spec=spec % ("max-%s" % size), - animatable=True, logical = logical)} + % if product == "gecko": + ${helpers.predefined_type("max-%s" % size, + "MaxLength", + "computed::MaxLength::None", + spec=spec % ("max-%s" % size), + animatable=True, logical = logical)} + % else: + ${helpers.predefined_type("max-%s" % size, + "LengthOrPercentageOrNone", + "computed::LengthOrPercentageOrNone::None", + "parse_non_negative", + needs_context=False, + spec=spec % ("max-%s" % size), + animatable=True, logical = logical)} + % endif % endfor ${helpers.single_keyword("box-sizing", diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs index 492bbfb4bc0..e512a623492 100644 --- a/components/style/values/computed/length.rs +++ b/components/style/values/computed/length.rs @@ -9,7 +9,7 @@ use ordered_float::NotNaN; use std::fmt; use style_traits::ToCss; use super::{Number, ToComputedValue, Context}; -use values::{Auto, CSSFloat, Either, None_, Normal, specified}; +use values::{Auto, CSSFloat, Either, ExtremumLength, None_, Normal, specified}; use values::specified::length::{FontRelativeLength, ViewportPercentageLength}; pub use cssparser::Color as CSSColor; @@ -546,3 +546,113 @@ pub type LengthOrNumber = Either<Length, Number>; /// Either a computed `<length>` or the `normal` keyword. pub type LengthOrNormal = Either<Length, Normal>; + +/// A value suitable for a `min-width` or `min-height` property. +/// See specified/values/length.rs for more details. +#[derive(Debug, Copy, Clone, PartialEq)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[allow(missing_docs)] +pub enum MinLength { + LengthOrPercentage(LengthOrPercentage), + Auto, + ExtremumLength(ExtremumLength), +} + +impl ToComputedValue for specified::MinLength { + type ComputedValue = MinLength; + + #[inline] + fn to_computed_value(&self, context: &Context) -> MinLength { + match *self { + specified::MinLength::LengthOrPercentage(ref lop) => { + MinLength::LengthOrPercentage(lop.to_computed_value(context)) + } + specified::MinLength::Auto => { + MinLength::Auto + } + specified::MinLength::ExtremumLength(ref ext) => { + MinLength::ExtremumLength(ext.clone()) + } + } + } + + #[inline] + fn from_computed_value(computed: &MinLength) -> Self { + match *computed { + MinLength::Auto => + specified::MinLength::Auto, + MinLength::LengthOrPercentage(ref lop) => + specified::MinLength::LengthOrPercentage(specified::LengthOrPercentage::from_computed_value(&lop)), + MinLength::ExtremumLength(ref ext) => + specified::MinLength::ExtremumLength(ext.clone()), + } + } +} + +impl ToCss for MinLength { + fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + match *self { + MinLength::LengthOrPercentage(lop) => + lop.to_css(dest), + MinLength::Auto => + dest.write_str("auto"), + MinLength::ExtremumLength(ext) => + ext.to_css(dest), + } + } +} + +/// A value suitable for a `max-width` or `max-height` property. +/// See specified/values/length.rs for more details. +#[derive(Debug, Copy, Clone, PartialEq)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[allow(missing_docs)] +pub enum MaxLength { + LengthOrPercentage(LengthOrPercentage), + None, + ExtremumLength(ExtremumLength), +} + +impl ToComputedValue for specified::MaxLength { + type ComputedValue = MaxLength; + + #[inline] + fn to_computed_value(&self, context: &Context) -> MaxLength { + match *self { + specified::MaxLength::LengthOrPercentage(ref lop) => { + MaxLength::LengthOrPercentage(lop.to_computed_value(context)) + } + specified::MaxLength::None => { + MaxLength::None + } + specified::MaxLength::ExtremumLength(ref ext) => { + MaxLength::ExtremumLength(ext.clone()) + } + } + } + + #[inline] + fn from_computed_value(computed: &MaxLength) -> Self { + match *computed { + MaxLength::None => + specified::MaxLength::None, + MaxLength::LengthOrPercentage(ref lop) => + specified::MaxLength::LengthOrPercentage(specified::LengthOrPercentage::from_computed_value(&lop)), + MaxLength::ExtremumLength(ref ext) => + specified::MaxLength::ExtremumLength(ext.clone()), + } + } +} + +impl ToCss for MaxLength { + fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + match *self { + MaxLength::LengthOrPercentage(lop) => + lop.to_css(dest), + MaxLength::None => + dest.write_str("none"), + MaxLength::ExtremumLength(ext) => + ext.to_css(dest), + } + } +} diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index dbc537c621a..7a52ebd1d7f 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -23,6 +23,7 @@ pub use super::specified::{Angle, BorderStyle, GridLine, Time, UrlOrNone}; pub use super::specified::url::{SpecifiedUrl, UrlExtraData}; pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrAuto}; pub use self::length::{LengthOrPercentageOrAutoOrContent, LengthOrPercentageOrNone, LengthOrNone}; +pub use self::length::{MaxLength, MinLength}; pub use self::position::Position; pub mod basic_shape; diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs index 88867af58f9..f30c3e2f44b 100644 --- a/components/style/values/mod.rs +++ b/components/style/values/mod.rs @@ -185,3 +185,11 @@ impl<A: ToComputedValue, B: ToComputedValue> ToComputedValue for Either<A, B> { } } } + +// A type for possible values for min- and max- flavors of width, +// height, block-size, and inline-size. +define_css_keyword_enum!(ExtremumLength: + "max-content" => MaxContent, + "min-content" => MinContent, + "fit-content" => FitContent, + "fill-available" => FillAvailable); diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index 0744aa9aafb..ba344eff300 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -18,6 +18,7 @@ use style_traits::ToCss; use style_traits::values::specified::AllowedNumericType; use super::{Angle, Number, SimplifiedValueNode, SimplifiedSumNode, Time}; use values::{Auto, CSSFloat, Either, FONT_MEDIUM_PX, HasViewportPercentage, None_, Normal}; +use values::ExtremumLength; use values::computed::Context; pub use super::image::{AngleOrCorner, ColorStop, EndingShape as GradientEndingShape, Gradient}; @@ -1304,3 +1305,97 @@ impl LengthOrNumber { } } } + +/// A value suitable for a `min-width` or `min-height` property. +/// Unlike `max-width` or `max-height` properties, a MinLength can be +/// `auto`, and cannot be `none`. +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[allow(missing_docs)] +pub enum MinLength { + LengthOrPercentage(LengthOrPercentage), + Auto, + ExtremumLength(ExtremumLength), +} + +impl HasViewportPercentage for MinLength { + fn has_viewport_percentage(&self) -> bool { + match *self { + MinLength::LengthOrPercentage(ref lop) => lop.has_viewport_percentage(), + _ => false + } + } +} + +impl ToCss for MinLength { + fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + match *self { + MinLength::LengthOrPercentage(ref lop) => + lop.to_css(dest), + MinLength::Auto => + dest.write_str("auto"), + MinLength::ExtremumLength(ref ext) => + ext.to_css(dest), + } + } +} + +impl Parse for MinLength { + fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { + input.try(ExtremumLength::parse).map(MinLength::ExtremumLength) + .or_else(|()| input.try(LengthOrPercentage::parse_non_negative).map(MinLength::LengthOrPercentage)) + .or_else(|()| { + match_ignore_ascii_case! { try!(input.expect_ident()), + "auto" => + Ok(MinLength::Auto), + _ => Err(()) + } + }) + } +} + +/// A value suitable for a `max-width` or `max-height` property. +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[allow(missing_docs)] +pub enum MaxLength { + LengthOrPercentage(LengthOrPercentage), + None, + ExtremumLength(ExtremumLength), +} + +impl HasViewportPercentage for MaxLength { + fn has_viewport_percentage(&self) -> bool { + match *self { + MaxLength::LengthOrPercentage(ref lop) => lop.has_viewport_percentage(), + _ => false + } + } +} + +impl ToCss for MaxLength { + fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + match *self { + MaxLength::LengthOrPercentage(ref lop) => + lop.to_css(dest), + MaxLength::None => + dest.write_str("none"), + MaxLength::ExtremumLength(ref ext) => + ext.to_css(dest), + } + } +} + +impl Parse for MaxLength { + fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { + input.try(ExtremumLength::parse).map(MaxLength::ExtremumLength) + .or_else(|()| input.try(LengthOrPercentage::parse_non_negative).map(MaxLength::LengthOrPercentage)) + .or_else(|()| { + match_ignore_ascii_case! { try!(input.expect_ident()), + "none" => + Ok(MaxLength::None), + _ => Err(()) + } + }) + } +} diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index d440636138c..81c3f5e7a79 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -30,6 +30,7 @@ pub use self::image::{SizeKeyword, VerticalDirection}; pub use self::length::{FontRelativeLength, ViewportPercentageLength, CharacterWidth, Length, CalcLengthOrPercentage}; pub use self::length::{Percentage, LengthOrNone, LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrAuto}; pub use self::length::{LengthOrPercentageOrNone, LengthOrPercentageOrAutoOrContent, NoCalcLength, CalcUnit}; +pub use self::length::{MaxLength, MinLength}; pub use self::position::{HorizontalPosition, Position, VerticalPosition}; #[cfg(feature = "gecko")] |