aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/style/gecko/values.rs71
-rw-r--r--components/style/properties/gecko.mako.rs2
-rw-r--r--components/style/properties/helpers/animated_properties.mako.rs29
-rw-r--r--components/style/properties/longhand/position.mako.rs47
-rw-r--r--components/style/values/computed/length.rs112
-rw-r--r--components/style/values/computed/mod.rs1
-rw-r--r--components/style/values/mod.rs8
-rw-r--r--components/style/values/specified/length.rs95
-rw-r--r--components/style/values/specified/mod.rs1
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")]