Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for keyword values for min-width and max-width #14740

Merged
merged 2 commits into from Feb 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
71 changes: 70 additions & 1 deletion components/style/gecko/values.rs
Expand Up @@ -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};

Expand Down Expand Up @@ -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) |
Expand Down
2 changes: 2 additions & 0 deletions components/style/properties/gecko.mako.rs
Expand Up @@ -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,
Expand Down
29 changes: 29 additions & 0 deletions components/style/properties/helpers/animated_properties.mako.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down
47 changes: 32 additions & 15 deletions components/style/properties/longhand/position.mako.rs
Expand Up @@ -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",
Expand Down
112 changes: 111 additions & 1 deletion components/style/values/computed/length.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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),
}
}
}
1 change: 1 addition & 0 deletions components/style/values/computed/mod.rs
Expand Up @@ -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;
Expand Down
8 changes: 8 additions & 0 deletions components/style/values/mod.rs
Expand Up @@ -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);