From eef9e24e96773a002dc21af1f583f7b47efec58a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 30 Jan 2019 20:55:54 +0000 Subject: [PATCH 1/9] style: Make -moz-binding chrome / UA only. But enable it in all tests because a lot of them rely on using it in the style="" attribute for example, or in inline stylesheets, which will no longer parse this (even in chrome documents), and we don't want to rewrite all the XUL and XBL tests. Differential Revision: https://phabricator.services.mozilla.com/D18027 --- components/style/properties/longhands/box.mako.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs index f956dd2f606..28a3367f477 100644 --- a/components/style/properties/longhands/box.mako.rs +++ b/components/style/properties/longhands/box.mako.rs @@ -602,6 +602,8 @@ ${helpers.predefined_type( products="gecko", animation_value_type="none", gecko_ffi_name="mBinding", + gecko_pref="layout.css.moz-binding.content.enabled", + enabled_in="chrome", spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-binding)", )} From 258217a36904a191490346ea5e706b0eeb048b23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 4 Feb 2019 16:57:12 +0100 Subject: [PATCH 2/9] style: Generate combined transform just once. Differential Revision: https://phabricator.services.mozilla.com/D18567 --- components/style/properties/cascade.rs | 4 ++++ components/style/properties/gecko.mako.rs | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/components/style/properties/cascade.rs b/components/style/properties/cascade.rs index 7fdbb7177e9..d881524deb5 100644 --- a/components/style/properties/cascade.rs +++ b/components/style/properties/cascade.rs @@ -629,6 +629,10 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { #[cfg(feature = "gecko")] { + if let Some(display) = builder.get_box_if_mutated() { + display.generate_combined_transform(); + } + if let Some(bg) = builder.get_background_if_mutated() { bg.fill_arrays(); } diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 9bb95ba9dfe..5dc8a0f6619 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -3023,6 +3023,11 @@ fn static_assert() { will-change shape-outside contain touch-action translate scale""" %> <%self:impl_trait style_struct_name="Box" skip_longhands="${skip_box_longhands}"> + #[inline] + pub fn generate_combined_transform(&mut self) { + unsafe { bindings::Gecko_StyleDisplay_GenerateCombinedTransform(&mut self.gecko) }; + } + #[inline] pub fn set_display(&mut self, v: longhands::display::computed_value::T) { self.gecko.mDisplay = v; From 207ff730c2c48fc626638de182ea11d57cf9f54c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Fri, 8 Feb 2019 22:40:26 +0000 Subject: [PATCH 3/9] style: Cleanup a bit after bug 1525371. Differential Revision: https://phabricator.services.mozilla.com/D19001 --- components/style/properties/gecko.mako.rs | 62 +++++++------------ .../style/properties/properties.mako.rs | 2 - 2 files changed, 22 insertions(+), 42 deletions(-) diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 5dc8a0f6619..2c25a2095af 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -80,7 +80,6 @@ pub struct ComputedValues(crate::gecko_bindings::structs::mozilla::ComputedStyle impl ComputedValues { pub fn new( - device: &Device, pseudo: Option<<&PseudoElement>, custom_properties: Option>, writing_mode: WritingMode, @@ -100,10 +99,7 @@ impl ComputedValues { % for style_struct in data.style_structs: ${style_struct.ident}, % endfor - ).to_outer( - device.pres_context(), - pseudo.map(|p| p.pseudo_info()) - ) + ).to_outer(pseudo) } pub fn default_values(pres_context: RawGeckoPresContextBorrowed) -> Arc { @@ -116,7 +112,7 @@ impl ComputedValues { % for style_struct in data.style_structs: style_structs::${style_struct.name}::default(pres_context), % endfor - ).to_outer(pres_context, None) + ).to_outer(None) } pub fn pseudo(&self) -> Option { @@ -190,24 +186,23 @@ impl Clone for ComputedValuesInner { } } -type PseudoInfo = (*mut structs::nsAtom, structs::CSSPseudoElementType); - impl ComputedValuesInner { - pub fn new(custom_properties: Option>, - writing_mode: WritingMode, - flags: ComputedValueFlags, - rules: Option, - visited_style: Option>, - % for style_struct in data.style_structs: - ${style_struct.ident}: Arc, - % endfor + pub fn new( + custom_properties: Option>, + writing_mode: WritingMode, + flags: ComputedValueFlags, + rules: Option, + visited_style: Option>, + % for style_struct in data.style_structs: + ${style_struct.ident}: Arc, + % endfor ) -> Self { - ComputedValuesInner { - custom_properties: custom_properties, - writing_mode: writing_mode, - rules: rules, - visited_style: visited_style.map(|x| Arc::into_raw_offset(x)), - flags: flags, + Self { + custom_properties, + writing_mode, + rules, + visited_style: visited_style.map(Arc::into_raw_offset), + flags, % for style_struct in data.style_structs: ${style_struct.gecko_name}: Arc::into_raw_offset(${style_struct.ident}), % endfor @@ -216,29 +211,16 @@ impl ComputedValuesInner { fn to_outer( self, - pres_context: RawGeckoPresContextBorrowed, - info: Option + pseudo: Option<<&PseudoElement>, ) -> Arc { - let (tag, ty) = if let Some(info) = info { - info - } else { - (ptr::null_mut(), structs::CSSPseudoElementType::NotPseudo) + let (pseudo_tag, pseudo_ty) = match pseudo { + Some(p) => p.pseudo_info(), + None => (ptr::null_mut(), structs::CSSPseudoElementType::NotPseudo), }; - - unsafe { self.to_outer_helper(pres_context, ty, tag) } - } - - unsafe fn to_outer_helper( - self, - pres_context: bindings::RawGeckoPresContextBorrowed, - pseudo_ty: structs::CSSPseudoElementType, - pseudo_tag: *mut structs::nsAtom - ) -> Arc { - let arc = { + let arc = unsafe { let arc: Arc = Arc::new(uninitialized()); bindings::Gecko_ComputedStyle_Init( &arc.0 as *const _ as *mut _, - pres_context, &self, pseudo_ty, pseudo_tag diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 6a263c8ca35..0e7364d445c 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -2890,7 +2890,6 @@ impl ComputedValues { impl ComputedValues { /// Create a new refcounted `ComputedValues` pub fn new( - _: &Device, _: Option<<&PseudoElement>, custom_properties: Option>, writing_mode: WritingMode, @@ -3655,7 +3654,6 @@ impl<'a> StyleBuilder<'a> { /// Turns this `StyleBuilder` into a proper `ComputedValues` instance. pub fn build(self) -> Arc { ComputedValues::new( - self.device, self.pseudo, self.custom_properties, self.writing_mode, From 15f503d000b5a995b53bf5064f2071fa794ea423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 26 Jan 2019 11:00:06 +0100 Subject: [PATCH 4/9] style: Add bindings for LengthPercentage, and use it for text-indent. Which is the only property that uses LengthPercentage alone. Differential Revision: https://phabricator.services.mozilla.com/D17737 --- components/style/cbindgen.toml | 21 ++++++++++++++++++++- components/style/properties/gecko.mako.rs | 2 +- components/style/values/computed/length.rs | 6 ++++-- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/components/style/cbindgen.toml b/components/style/cbindgen.toml index 25004b2def6..25f88f64b3a 100644 --- a/components/style/cbindgen.toml +++ b/components/style/cbindgen.toml @@ -7,6 +7,8 @@ autogen_warning = """/* DO NOT MODIFY THIS MANUALLY! This file was generated usi * a. Alternatively, you can clone `https://github.com/eqrion/cbindgen` and use a tagged release * 2. Run `rustup run nightly cbindgen toolkit/library/rust/ --lockfile Cargo.lock --crate style -o layout/style/ServoStyleConsts.h` */ +#include "nsCoord.h" +#include "Units.h" class nsAtom; namespace mozilla { namespace css { @@ -27,7 +29,7 @@ namespaces = ["mozilla"] [parse] parse_deps = true -include = ["cssparser"] +include = ["cssparser", "style_traits"] [struct] derive_eq = true @@ -71,3 +73,20 @@ include = [ "LengthPercentage", ] item_types = ["enums", "structs", "typedefs"] + +[export.body] +"LengthPercentage" = """ + // Defined in nsStyleCoord.h + static inline StyleLengthPercentage Zero(); + inline bool HasPercent() const; + inline bool ConvertsToLength() const; + inline nscoord ToLength() const; + inline bool ConvertsToPercentage() const; + inline float ToPercentage() const; + inline CSSCoord LengthInCSSPixels() const; + inline float Percentage() const; + inline CSSCoord ResolveToCSSPixels(CSSCoord aPercentageBasisInCSSPixels) const; + template inline CSSCoord ResolveToCSSPixelsWith(T aPercentageGetter) const; + inline nscoord Resolve(nscoord aPercentageBasis) const; + template inline nscoord ResolveWith(T aPercentageGetter) const; +""" diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 2c25a2095af..970a807f0d9 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -1389,7 +1389,7 @@ impl Clone for ${style_struct.gecko_struct_name} { "FlexBasis": impl_style_coord, "Length": impl_absolute_length, "LengthOrNormal": impl_style_coord, - "LengthPercentage": impl_style_coord, + "LengthPercentage": impl_simple, "LengthPercentageOrAuto": impl_style_coord, "LengthPercentageOrNone": impl_style_coord, "MaxLength": impl_style_coord, diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs index 1fd42301e3b..ae585695506 100644 --- a/components/style/values/computed/length.rs +++ b/components/style/values/computed/length.rs @@ -73,11 +73,12 @@ impl ToComputedValue for specified::Length { /// https://drafts.csswg.org/css-values-4/#typedef-length-percentage #[allow(missing_docs)] #[derive(Clone, Copy, Debug, MallocSizeOf, ToAnimatedZero)] +#[repr(C)] pub struct LengthPercentage { - #[animation(constant)] - pub clamping_mode: AllowedNumericType, length: Length, percentage: Percentage, + #[animation(constant)] + pub clamping_mode: AllowedNumericType, /// Whether we specified a percentage or not. #[animation(constant)] pub has_percentage: bool, @@ -678,6 +679,7 @@ impl NonNegativeLengthPercentage { ToAnimatedValue, ToAnimatedZero, )] +#[repr(C)] pub struct CSSPixelLength(CSSFloat); impl CSSPixelLength { From 13e12d23f3818a68847f28f3a3fac3220d134cd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 26 Jan 2019 11:00:22 +0100 Subject: [PATCH 5/9] style: Use the style system's LengthPercentage for shape-margin. This also makes us pass a few WPTs because we stop losing precision when serializing the computed value. Differential Revision: https://phabricator.services.mozilla.com/D17738 --- components/style/properties/gecko.mako.rs | 2 +- components/style/values/generics/mod.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 970a807f0d9..a11d08ba44f 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -1396,7 +1396,7 @@ impl Clone for ${style_struct.gecko_struct_name} { "MozLength": impl_style_coord, "MozScriptMinSize": impl_absolute_length, "MozScriptSizeMultiplier": impl_simple, - "NonNegativeLengthPercentage": impl_style_coord, + "NonNegativeLengthPercentage": impl_simple, "NonNegativeNumber": impl_simple, "Number": impl_simple, "Opacity": impl_simple, diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index c18eb0e7a88..a5c8c957073 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -174,6 +174,7 @@ impl SpecifiedValueInfo for CounterStyleOrNone { ToComputedValue, ToCss, )] +#[repr(transparent)] pub struct NonNegative(pub T); /// A wrapper of greater-than-or-equal-to-one values. From 8dad956513eba5cea9ce895c6f5351ff9f95c835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 26 Jan 2019 11:00:44 +0100 Subject: [PATCH 6/9] style: Use Rust lengths for margin / padding / inset. Also for the intersection observer root margin, since it was easier to fix it up and clean it up than not doing it. This is the first big step to get rid of nscoord. It duplicates a bit of logic in nsLayoutUtils since for now max/min-width/height are still represented with nsStyleCoord, but I think I prefer to land this incrementally. I didn't add helpers for the physical accessors of the style rect sides that nsStyleSides has (top/bottom/left/right) since I think we generally should encourage the logical versions, but let me know if you want me to do that. Differential Revision: https://phabricator.services.mozilla.com/D17739 --- components/style/cbindgen.toml | 30 +++++++- components/style/properties/gecko.mako.rs | 9 +-- components/style/values/computed/length.rs | 1 + components/style/values/generics/rect.rs | 1 + components/style/values/specified/gecko.rs | 87 ++++++++-------------- 5 files changed, 64 insertions(+), 64 deletions(-) diff --git a/components/style/cbindgen.toml b/components/style/cbindgen.toml index 25f88f64b3a..d76a57c9541 100644 --- a/components/style/cbindgen.toml +++ b/components/style/cbindgen.toml @@ -9,11 +9,15 @@ autogen_warning = """/* DO NOT MODIFY THIS MANUALLY! This file was generated usi */ #include "nsCoord.h" #include "Units.h" +#include "mozilla/gfx/Types.h" class nsAtom; namespace mozilla { + class WritingMode; + enum LogicalSide : uint8_t; namespace css { struct URLValue; } + // Work-around weird cbindgen renaming. typedef css::URLValue StyleURLValue; typedef nsAtom StylensAtom; @@ -71,13 +75,17 @@ include = [ "Resize", "Overflow", "LengthPercentage", + "NonNegativeLengthPercentage", + "LengthPercentageOrAuto", + "Rect", + "IntersectionObserverRootMargin", ] item_types = ["enums", "structs", "typedefs"] [export.body] "LengthPercentage" = """ // Defined in nsStyleCoord.h - static inline StyleLengthPercentage Zero(); + static constexpr inline StyleLengthPercentage Zero(); inline bool HasPercent() const; inline bool ConvertsToLength() const; inline nscoord ToLength() const; @@ -90,3 +98,23 @@ item_types = ["enums", "structs", "typedefs"] inline nscoord Resolve(nscoord aPercentageBasis) const; template inline nscoord ResolveWith(T aPercentageGetter) const; """ + +"LengthPercentageOrAuto" = """ + inline const StyleLengthPercentage& AsLengthPercentage() const; + inline bool HasPercent() const; + inline bool ConvertsToLength() const; +""" + +"Rect" = """ + // Defined in nsStyleCoord.h + template inline bool All(Predicate) const; + template inline bool Any(Predicate) const; + + // Defined in WritingModes.h + inline const T& Get(mozilla::Side) const; + inline const T& Get(mozilla::WritingMode, mozilla::LogicalSide) const; + inline const T& GetIStart(mozilla::WritingMode) const; + inline const T& GetBStart(mozilla::WritingMode) const; + inline const T& GetIEnd(mozilla::WritingMode) const; + inline const T& GetBEnd(mozilla::WritingMode) const; +""" diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index a11d08ba44f..798e39adb27 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -772,11 +772,12 @@ def set_gecko_property(ffi_name, expr): <%def name="impl_split_style_coord(ident, gecko_ffi_name, index)"> #[allow(non_snake_case)] pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { - v.to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${index})); + self.gecko.${gecko_ffi_name}.${index} = v; } #[allow(non_snake_case)] pub fn copy_${ident}_from(&mut self, other: &Self) { - self.gecko.${gecko_ffi_name}.data_at_mut(${index}).copy_from(&other.gecko.${gecko_ffi_name}.data_at(${index})); + self.gecko.${gecko_ffi_name}.${index} = + other.gecko.${gecko_ffi_name}.${index}; } #[allow(non_snake_case)] pub fn reset_${ident}(&mut self, other: &Self) { @@ -785,9 +786,7 @@ def set_gecko_property(ffi_name, expr): #[allow(non_snake_case)] pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { - use crate::properties::longhands::${ident}::computed_value::T; - T::from_gecko_style_coord(&self.gecko.${gecko_ffi_name}.data_at(${index})) - .expect("clone for ${ident} failed") + self.gecko.${gecko_ffi_name}.${index} } diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs index ae585695506..c779594202b 100644 --- a/components/style/values/computed/length.rs +++ b/components/style/values/computed/length.rs @@ -457,6 +457,7 @@ impl IsZeroLength for LengthPercentage { #[derive( Animate, Clone, ComputeSquaredDistance, Copy, MallocSizeOf, PartialEq, ToAnimatedZero, ToCss, )] +#[repr(C, u8)] pub enum LengthPercentageOrAuto { LengthPercentage(LengthPercentage), Auto, diff --git a/components/style/values/generics/rect.rs b/components/style/values/generics/rect.rs index 985a9c4a320..de7237e694d 100644 --- a/components/style/values/generics/rect.rs +++ b/components/style/values/generics/rect.rs @@ -23,6 +23,7 @@ use style_traits::{CssWriter, ParseError, ToCss}; ToAnimatedValue, ToComputedValue, )] +#[repr(C)] pub struct Rect(pub T, pub T, pub T, pub T); impl Rect { diff --git a/components/style/values/specified/gecko.rs b/components/style/values/specified/gecko.rs index 02bd5505123..8259430bf20 100644 --- a/components/style/values/specified/gecko.rs +++ b/components/style/values/specified/gecko.rs @@ -4,21 +4,19 @@ //! Specified types for legacy Gecko-only properties. -use crate::gecko::values::GeckoStyleCoordConvertible; -use crate::gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut}; use crate::parser::{Parse, ParserContext}; -use crate::values::computed; +use crate::values::computed::{self, LengthPercentage}; use crate::values::computed::length::CSSPixelLength; use crate::values::generics::gecko::ScrollSnapPoint as GenericScrollSnapPoint; use crate::values::generics::rect::Rect; -use crate::values::specified::length::LengthPercentage; +use crate::values::specified::length::LengthPercentage as SpecifiedLengthPercentage; use cssparser::{Parser, Token}; use std::fmt; use style_traits::values::SequenceWriter; use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; /// A specified type for scroll snap points. -pub type ScrollSnapPoint = GenericScrollSnapPoint; +pub type ScrollSnapPoint = GenericScrollSnapPoint; impl Parse for ScrollSnapPoint { fn parse<'i, 't>( @@ -29,62 +27,34 @@ impl Parse for ScrollSnapPoint { return Ok(GenericScrollSnapPoint::None); } input.expect_function_matching("repeat")?; + // FIXME(emilio): This won't clamp properly when animating. let length = - input.parse_nested_block(|i| LengthPercentage::parse_non_negative(context, i))?; + input.parse_nested_block(|i| SpecifiedLengthPercentage::parse_non_negative(context, i))?; Ok(GenericScrollSnapPoint::Repeat(length)) } } -/// A component of an IntersectionObserverRootMargin. -#[derive(Clone, Copy, Debug, PartialEq, ToCss)] -pub enum PixelOrPercentage { - /// An absolute length in pixels (px) - Pixel(CSSPixelLength), - /// A percentage (%) - Percentage(computed::Percentage), -} - -impl Parse for PixelOrPercentage { - fn parse<'i, 't>( - _context: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result> { - let location = input.current_source_location(); - let token = input.next()?; - let value = match *token { - Token::Dimension { - value, ref unit, .. - } => { - match_ignore_ascii_case! { unit, - "px" => Ok(PixelOrPercentage::Pixel(CSSPixelLength::new(value))), - _ => Err(()), - } - }, - Token::Percentage { unit_value, .. } => Ok(PixelOrPercentage::Percentage( - computed::Percentage(unit_value), - )), - _ => Err(()), - }; - value.map_err(|()| location.new_custom_error(StyleParseErrorKind::UnspecifiedError)) - } -} - -impl GeckoStyleCoordConvertible for PixelOrPercentage { - fn to_gecko_style_coord(&self, coord: &mut T) { - match *self { - PixelOrPercentage::Pixel(ref l) => l.to_gecko_style_coord(coord), - PixelOrPercentage::Percentage(ref pc) => pc.to_gecko_style_coord(coord), - } - } - - fn from_gecko_style_coord(coord: &T) -> Option { - CSSPixelLength::from_gecko_style_coord(coord) - .map(PixelOrPercentage::Pixel) - .or_else(|| { - computed::Percentage::from_gecko_style_coord(coord) - .map(PixelOrPercentage::Percentage) - }) - } +fn parse_pixel_or_percent<'i, 't>( + _context: &ParserContext, + input: &mut Parser<'i, 't>, +) -> Result> { + let location = input.current_source_location(); + let token = input.next()?; + let value = match *token { + Token::Dimension { + value, ref unit, .. + } => { + match_ignore_ascii_case! { unit, + "px" => Ok(LengthPercentage::new(CSSPixelLength::new(value), None)), + _ => Err(()), + } + }, + Token::Percentage { unit_value, .. } => Ok( + LengthPercentage::new_percent(computed::Percentage(unit_value)) + ), + _ => Err(()), + }; + value.map_err(|()| location.new_custom_error(StyleParseErrorKind::UnspecifiedError)) } /// The value of an IntersectionObserver's rootMargin property. @@ -93,14 +63,15 @@ impl GeckoStyleCoordConvertible for PixelOrPercentage { /// calc() values are not allowed. /// /// -pub struct IntersectionObserverRootMargin(pub Rect); +#[repr(transparent)] +pub struct IntersectionObserverRootMargin(pub Rect); impl Parse for IntersectionObserverRootMargin { fn parse<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result> { - let rect = Rect::parse_with(context, input, PixelOrPercentage::parse)?; + let rect = Rect::parse_with(context, input, parse_pixel_or_percent)?; Ok(IntersectionObserverRootMargin(rect)) } } From a68bc29b96ac1c42d3940434c6c3239ee0f42a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 27 Jan 2019 01:03:44 +0100 Subject: [PATCH 7/9] 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 --- components/style/cbindgen.toml | 2 +- components/style/gecko/conversions.rs | 11 +- components/style/gecko/values.rs | 58 ++-- components/style/properties/gecko.mako.rs | 5 +- .../properties/longhands/position.mako.rs | 48 ++- .../style/properties/properties.mako.rs | 12 +- components/style/stylesheets/viewport_rule.rs | 17 +- components/style/values/animated/length.rs | 52 +--- .../style/values/computed/background.rs | 9 +- components/style/values/computed/length.rs | 230 +++++--------- components/style/values/computed/mod.rs | 2 +- .../style/values/generics/background.rs | 12 +- components/style/values/generics/length.rs | 99 ++++++- .../style/values/specified/background.rs | 6 +- components/style/values/specified/gecko.rs | 12 +- components/style/values/specified/length.rs | 280 ++++++------------ components/style/values/specified/mod.rs | 2 +- 17 files changed, 337 insertions(+), 520 deletions(-) diff --git a/components/style/cbindgen.toml b/components/style/cbindgen.toml index d76a57c9541..4c0b631d31d 100644 --- a/components/style/cbindgen.toml +++ b/components/style/cbindgen.toml @@ -99,7 +99,7 @@ item_types = ["enums", "structs", "typedefs"] template inline nscoord ResolveWith(T aPercentageGetter) const; """ -"LengthPercentageOrAuto" = """ +"GenericLengthPercentageOrAuto" = """ inline const StyleLengthPercentage& AsLengthPercentage() const; inline bool HasPercent() const; inline bool ConvertsToLength() const; diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index 0f6ac89c9f2..ccaa16c844c 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -27,6 +27,7 @@ use crate::values::computed::{LengthPercentageOrAuto, NonNegativeLengthPercentag use crate::values::generics::box_::VerticalAlign; use crate::values::generics::grid::{TrackListValue, TrackSize}; 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::NonNegative; use app_units::Au; @@ -62,19 +63,19 @@ impl From for LengthPercentage { } } -impl LengthPercentageOrAuto { +impl NonNegativeLengthPercentageOrAuto { /// Convert this value in an appropriate `nsStyleCoord::CalcValue`. pub fn to_calc_value(&self) -> Option { match *self { - LengthPercentageOrAuto::LengthPercentage(len) => Some(From::from(len)), - LengthPercentageOrAuto::Auto => None, + GenericLengthPercentageOrAuto::LengthPercentage(ref len) => Some(From::from(len.0)), + GenericLengthPercentageOrAuto::Auto => None, } } } impl From for LengthPercentageOrAuto { fn from(other: nsStyleCoord_CalcValue) -> LengthPercentageOrAuto { - LengthPercentageOrAuto::LengthPercentage(LengthPercentage::from(other)) + GenericLengthPercentageOrAuto::LengthPercentage(LengthPercentage::from(other)) } } @@ -82,7 +83,7 @@ impl From for LengthPercentageOrAuto { // disappear as we move more stuff to cbindgen. impl From for NonNegativeLengthPercentageOrAuto { fn from(other: nsStyleCoord_CalcValue) -> Self { - NonNegative(LengthPercentageOrAuto::LengthPercentage( + GenericLengthPercentageOrAuto::LengthPercentage(NonNegative( LengthPercentage::with_clamping_mode( Au(other.mLength).into(), if other.mHasPercent { diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs index 42177bf0858..ac3495a7504 100644 --- a/components/style/gecko/values.rs +++ b/components/style/gecko/values.rs @@ -14,15 +14,15 @@ use crate::media_queries::Device; use crate::values::computed::basic_shape::ShapeRadius as ComputedShapeRadius; use crate::values::computed::FlexBasis as ComputedFlexBasis; 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::{NonNegativeLengthPercentage, Percentage}; +use crate::values::computed::{Number, NumberOrPercentage}; use crate::values::generics::basic_shape::ShapeRadius; use crate::values::generics::box_::Perspective; use crate::values::generics::flex::FlexBasis; use crate::values::generics::gecko::ScrollSnapPoint; 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::{Auto, Either, None_, Normal}; use crate::Atom; @@ -183,7 +183,10 @@ impl GeckoStyleCoordConvertible for Length { } } -impl GeckoStyleCoordConvertible for LengthPercentageOrAuto { +impl GeckoStyleCoordConvertible for LengthPercentageOrAuto +where + LengthPercentage: GeckoStyleCoordConvertible, +{ fn to_gecko_style_coord(&self, coord: &mut T) { match *self { LengthPercentageOrAuto::Auto => coord.set_value(CoordDataValue::Auto), @@ -200,23 +203,6 @@ impl GeckoStyleCoordConvertible for LengthPercentageOrAuto { } } -impl GeckoStyleCoordConvertible for LengthPercentageOrNone { - fn to_gecko_style_coord(&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(coord: &T) -> Option { - match coord.as_value() { - CoordDataValue::None => Some(LengthPercentageOrNone::None), - _ => LengthPercentage::from_gecko_style_coord(coord) - .map(LengthPercentageOrNone::LengthPercentage), - } - } -} - impl GeckoStyleCoordConvertible for TrackBreadth { fn to_gecko_style_coord(&self, coord: &mut T) { match *self { @@ -367,34 +353,40 @@ impl GeckoStyleCoordConvertible for ExtremumLength { impl GeckoStyleCoordConvertible for ComputedMozLength { fn to_gecko_style_coord(&self, coord: &mut T) { 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), } } fn from_gecko_style_coord(coord: &T) -> Option { - LengthPercentageOrAuto::from_gecko_style_coord(coord) - .map(MozLength::LengthPercentageOrAuto) - .or_else(|| { - ExtremumLength::from_gecko_style_coord(coord).map(MozLength::ExtremumLength) - }) + if let CoordDataValue::Auto = coord.as_value() { + return Some(MozLength::Auto); + } + 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 { fn to_gecko_style_coord(&self, coord: &mut T) { 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), } } fn from_gecko_style_coord(coord: &T) -> Option { - LengthPercentageOrNone::from_gecko_style_coord(coord) - .map(MaxLength::LengthPercentageOrNone) - .or_else(|| { - ExtremumLength::from_gecko_style_coord(coord).map(MaxLength::ExtremumLength) - }) + if let CoordDataValue::None = coord.as_value() { + return Some(MaxLength::None); + } + if let Some(lp) = NonNegativeLengthPercentage::from_gecko_style_coord(coord) { + return Some(MaxLength::LengthPercentage(lp)); + } + ExtremumLength::from_gecko_style_coord(coord).map(MaxLength::ExtremumLength) } } diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 798e39adb27..297357446a2 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -1390,7 +1390,6 @@ impl Clone for ${style_struct.gecko_struct_name} { "LengthOrNormal": impl_style_coord, "LengthPercentage": impl_simple, "LengthPercentageOrAuto": impl_style_coord, - "LengthPercentageOrNone": impl_style_coord, "MaxLength": impl_style_coord, "MozLength": impl_style_coord, "MozScriptMinSize": impl_absolute_length, @@ -3831,11 +3830,11 @@ fn static_assert() { BackgroundSize::Explicit { width: explicit_width, height: explicit_height } => { let mut w_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; 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; h_type = nsStyleImageLayers_Size_DimensionType::eLengthPercentage; } diff --git a/components/style/properties/longhands/position.mako.rs b/components/style/properties/longhands/position.mako.rs index cc5515dbac7..2a0f86d056a 100644 --- a/components/style/properties/longhands/position.mako.rs +++ b/components/style/properties/longhands/position.mako.rs @@ -13,7 +13,7 @@ ${helpers.predefined_type( side, "LengthPercentageOrAuto", - "computed::LengthPercentageOrAuto::Auto", + "computed::LengthPercentageOrAuto::auto()", spec="https://www.w3.org/TR/CSS2/visuren.html#propdef-%s" % side, flags="GETCS_NEEDS_LAYOUT_FLUSH", animation_value_type="ComputedValue", @@ -27,7 +27,7 @@ ${helpers.predefined_type( "inset-%s" % side, "LengthPercentageOrAuto", - "computed::LengthPercentageOrAuto::Auto", + "computed::LengthPercentageOrAuto::auto()", spec="https://drafts.csswg.org/css-logical-props/#propdef-inset-%s" % side, flags="GETCS_NEEDS_LAYOUT_FLUSH", alias="offset-%s:layout.css.offset-logical-properties.enabled" % side, @@ -270,24 +270,12 @@ ${helpers.predefined_type( animation_value_type="MozLength", 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: // servo versions (no keyword support) ${helpers.predefined_type( size, - "LengthPercentageOrAuto", - "computed::LengthPercentageOrAuto::Auto", - "parse_non_negative", + "NonNegativeLengthPercentageOrAuto", + "computed::NonNegativeLengthPercentageOrAuto::auto()", spec=spec % size, logical_group="size", allow_quirks=not logical, @@ -296,9 +284,8 @@ ${helpers.predefined_type( )} ${helpers.predefined_type( "min-%s" % size, - "LengthPercentage", - "computed::LengthPercentage::zero()", - "parse_non_negative", + "NonNegativeLengthPercentage", + "computed::NonNegativeLengthPercentage::zero()", spec=spec % ("min-%s" % size), logical_group="min-size", animation_value_type="ComputedValue", @@ -306,19 +293,18 @@ ${helpers.predefined_type( allow_quirks=not logical, 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 + ${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 ${helpers.single_keyword( diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 0e7364d445c..62d27922ccb 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -3016,7 +3016,7 @@ impl ComputedValuesInner { /// Get the logical computed inline size. #[inline] - pub fn content_inline_size(&self) -> computed::LengthPercentageOrAuto { + pub fn content_inline_size(&self) -> computed::NonNegativeLengthPercentageOrAuto { let position_style = self.get_position(); if self.writing_mode.is_vertical() { position_style.height @@ -3027,35 +3027,35 @@ impl ComputedValuesInner { /// Get the logical computed block size. #[inline] - pub fn content_block_size(&self) -> computed::LengthPercentageOrAuto { + pub fn content_block_size(&self) -> computed::NonNegativeLengthPercentageOrAuto { let position_style = self.get_position(); if self.writing_mode.is_vertical() { position_style.width } else { position_style.height } } /// Get the logical computed min inline size. #[inline] - pub fn min_inline_size(&self) -> computed::LengthPercentage { + pub fn min_inline_size(&self) -> computed::NonNegativeLengthPercentage { let position_style = self.get_position(); if self.writing_mode.is_vertical() { position_style.min_height } else { position_style.min_width } } /// Get the logical computed min block size. #[inline] - pub fn min_block_size(&self) -> computed::LengthPercentage { + pub fn min_block_size(&self) -> computed::NonNegativeLengthPercentage { let position_style = self.get_position(); if self.writing_mode.is_vertical() { position_style.min_width } else { position_style.min_height } } /// Get the logical computed max inline size. #[inline] - pub fn max_inline_size(&self) -> computed::LengthPercentageOrNone { + pub fn max_inline_size(&self) -> computed::MaxLength { let position_style = self.get_position(); if self.writing_mode.is_vertical() { position_style.max_height } else { position_style.max_width } } /// Get the logical computed max block size. #[inline] - pub fn max_block_size(&self) -> computed::LengthPercentageOrNone { + pub fn max_block_size(&self) -> computed::MaxLength { let position_style = self.get_position(); if self.writing_mode.is_vertical() { position_style.max_width } else { position_style.max_height } } diff --git a/components/style/stylesheets/viewport_rule.rs b/components/style/stylesheets/viewport_rule.rs index 862399e065c..8325216519d 100644 --- a/components/style/stylesheets/viewport_rule.rs +++ b/components/style/stylesheets/viewport_rule.rs @@ -11,16 +11,17 @@ use crate::context::QuirksMode; use crate::error_reporting::ContextualParseError; use crate::font_metrics::get_metrics_provider_for_product; use crate::media_queries::Device; -use crate::parser::ParserContext; +use crate::parser::{Parse, ParserContext}; use crate::properties::StyleBuilder; use crate::rule_cache::RuleCacheConditions; use crate::shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard}; use crate::str::CssStringWriter; use crate::stylesheets::{Origin, StylesheetInDocument}; use crate::values::computed::{Context, ToComputedValue}; -use crate::values::specified::{ - self, LengthPercentageOrAuto, NoCalcLength, ViewportPercentageLength, -}; +use crate::values::generics::length::LengthPercentageOrAuto; +use crate::values::generics::NonNegative; +use crate::values::specified::{self, NoCalcLength}; +use crate::values::specified::{NonNegativeLengthPercentageOrAuto, ViewportPercentageLength}; use app_units::Au; use cssparser::CowRcStr; use cssparser::{parse_important, AtRuleParser, DeclarationListParser, DeclarationParser, Parser}; @@ -151,7 +152,7 @@ trait FromMeta: Sized { #[cfg_attr(feature = "servo", derive(MallocSizeOf))] #[derive(Clone, Debug, PartialEq, ToCss)] pub enum ViewportLength { - Specified(LengthPercentageOrAuto), + Specified(NonNegativeLengthPercentageOrAuto), ExtendToZoom, } @@ -159,9 +160,9 @@ impl FromMeta for ViewportLength { fn from_meta(value: &str) -> Option { macro_rules! specified { ($value:expr) => { - ViewportLength::Specified(LengthPercentageOrAuto::LengthPercentage( + ViewportLength::Specified(LengthPercentageOrAuto::LengthPercentage(NonNegative( specified::LengthPercentage::Length($value), - )) + ))) }; } @@ -188,7 +189,7 @@ impl ViewportLength { ) -> Result> { // we explicitly do not accept 'extend-to-zoom', since it is a UA // internal value for viewport translation - LengthPercentageOrAuto::parse_non_negative(context, input).map(ViewportLength::Specified) + NonNegativeLengthPercentageOrAuto::parse(context, input).map(ViewportLength::Specified) } } diff --git a/components/style/values/animated/length.rs b/components/style/values/animated/length.rs index dd678f5c395..73957618cea 100644 --- a/components/style/values/animated/length.rs +++ b/components/style/values/animated/length.rs @@ -4,10 +4,8 @@ //! 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::MaxLength as ComputedMaxLength; -use crate::values::computed::MozLength as ComputedMozLength; use crate::values::computed::Percentage; /// @@ -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, - } - } -} diff --git a/components/style/values/computed/background.rs b/components/style/values/computed/background.rs index 08f10c9c1ec..dc23915a74b 100644 --- a/components/style/values/computed/background.rs +++ b/components/style/values/computed/background.rs @@ -4,20 +4,21 @@ //! 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::length::LengthPercentageOrAuto; pub use crate::values::specified::background::BackgroundRepeat; /// A computed value for the `background-size` property. -pub type BackgroundSize = GenericBackgroundSize; +pub type BackgroundSize = GenericBackgroundSize; impl BackgroundSize { /// Returns `auto auto`. pub fn auto() -> Self { GenericBackgroundSize::Explicit { - width: NonNegativeLengthPercentageOrAuto::auto(), - height: NonNegativeLengthPercentageOrAuto::auto(), + width: LengthPercentageOrAuto::auto(), + height: LengthPercentageOrAuto::auto(), } } } diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs index c779594202b..313b4151d2b 100644 --- a/components/style/values/computed/length.rs +++ b/components/style/values/computed/length.rs @@ -7,13 +7,15 @@ use super::{Context, Number, Percentage, ToComputedValue}; use crate::values::animated::ToAnimatedValue; use crate::values::distance::{ComputeSquaredDistance, SquaredDistance}; -use crate::values::generics::length::MaxLength as GenericMaxLength; -use crate::values::generics::length::MozLength as GenericMozLength; +use crate::values::generics::length as generics; +use crate::values::generics::length::{ + MaxLength as GenericMaxLength, MozLength as GenericMozLength, +}; use crate::values::generics::transform::IsZeroLength; use crate::values::generics::NonNegative; use crate::values::specified::length::ViewportPercentageLength; 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 ordered_float::NotNan; use std::fmt::{self, Write}; @@ -452,151 +454,61 @@ impl IsZeroLength for LengthPercentage { } } -#[allow(missing_docs)] -#[css(derive_debug)] -#[derive( - Animate, Clone, ComputeSquaredDistance, Copy, MallocSizeOf, PartialEq, ToAnimatedZero, ToCss, -)] -#[repr(C, u8)] -pub enum LengthPercentageOrAuto { - LengthPercentage(LengthPercentage), - Auto, -} +/// Some boilerplate to share between negative and non-negative +/// length-percentage or auto. +macro_rules! computed_length_percentage_or_auto { + ($inner:ty) => { + /// Returns the `0` value. + #[inline] + pub fn zero() -> Self { + generics::LengthPercentageOrAuto::LengthPercentage(<$inner>::zero()) + } -impl LengthPercentageOrAuto { - /// Returns the `0` value. - #[inline] - pub fn zero() -> Self { - LengthPercentageOrAuto::LengthPercentage(LengthPercentage::zero()) - } -} + /// Returns the used value. + #[inline] + pub fn to_used_value(&self, percentage_basis: Au) -> Option { + match *self { + 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. -pub type NonNegativeLengthPercentageOrAuto = NonNegative; - -impl IsAuto for NonNegativeLengthPercentageOrAuto { - #[inline] - fn is_auto(&self) -> bool { - *self == Self::auto() - } -} - -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, + /// Returns true if the computed value is absolute 0 or 0%. + #[inline] + pub fn is_definitely_zero(&self) -> bool { + use values::generics::length::LengthPercentageOrAuto::*; + match *self { + LengthPercentage(ref l) => l.is_definitely_zero(), + Auto => false, + } } } +} +/// A computed type for ` | auto`. +pub type LengthPercentageOrAuto = generics::GenericLengthPercentageOrAuto; + +impl LengthPercentageOrAuto { /// Clamps the value to a non-negative value. pub fn clamp_to_non_negative(self) -> Self { - use self::LengthPercentageOrAuto::*; + use values::generics::length::LengthPercentageOrAuto::*; match self { LengthPercentage(l) => LengthPercentage(l.clamp_to_non_negative()), Auto => Auto, } } + + computed_length_percentage_or_auto!(LengthPercentage); } -impl ToComputedValue for specified::LengthPercentageOrAuto { - type ComputedValue = LengthPercentageOrAuto; +/// A wrapper of LengthPercentageOrAuto, whose value must be >= 0. +pub type NonNegativeLengthPercentageOrAuto = + generics::LengthPercentageOrAuto; - #[inline] - fn to_computed_value(&self, context: &Context) -> LengthPercentageOrAuto { - 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 { - 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), - ) - }, - } - } +impl NonNegativeLengthPercentageOrAuto { + computed_length_percentage_or_auto!(NonNegativeLengthPercentage); } /// A wrapper of LengthPercentage, whose value must be >= 0. @@ -630,13 +542,6 @@ impl From for NonNegativeLengthPercentage { } } -impl From for LengthPercentage { - #[inline] - fn from(lp: NonNegativeLengthPercentage) -> LengthPercentage { - lp.0 - } -} - // TODO(emilio): This is a really generic impl which is only needed to implement // Animated and co for Spacing<>. Get rid of this, probably? impl From for LengthPercentage { @@ -650,7 +555,7 @@ impl NonNegativeLengthPercentage { /// Get zero value. #[inline] pub fn zero() -> Self { - NonNegative::(LengthPercentage::zero()) + NonNegative(LengthPercentage::zero()) } /// Returns true if the computed value is absolute 0 or 0%. @@ -662,7 +567,26 @@ impl NonNegativeLengthPercentage { /// Returns the used value. #[inline] 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) -> Option { + 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 { + match *self { + GenericMaxLength::None => None, + GenericMaxLength::LengthPercentage(ref lp) => Some(lp.to_used_value(percentage_basis)), + } } } @@ -881,6 +805,8 @@ pub type NonNegativeLengthPercentageOrNormal = Either; - -impl MozLength { - /// Returns the `auto` value. - #[inline] - pub fn auto() -> Self { - GenericMozLength::LengthPercentageOrAuto(LengthPercentageOrAuto::Auto) - } -} +pub type MozLength = GenericMozLength; /// A computed value for `max-width` or `min-height` property. -pub type MaxLength = GenericMaxLength; - -impl MaxLength { - /// Returns the `none` value. - #[inline] - pub fn none() -> Self { - GenericMaxLength::LengthPercentageOrNone(LengthPercentageOrNone::None) - } -} +pub type MaxLength = GenericMaxLength; diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 02ccf01e25e..ab8edd2b746 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -62,7 +62,7 @@ pub use self::gecko::ScrollSnapPoint; pub use self::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection, MozImageRect}; pub use self::length::{CSSPixelLength, ExtremumLength, NonNegativeLength}; 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}; #[cfg(feature = "gecko")] pub use self::list::ListStyleType; diff --git a/components/style/values/generics/background.rs b/components/style/values/generics/background.rs index 4a7ee4b9b95..d739329e4fc 100644 --- a/components/style/values/generics/background.rs +++ b/components/style/values/generics/background.rs @@ -4,7 +4,7 @@ //! Generic types for CSS values related to backgrounds. -use crate::values::IsAuto; +use crate::values::generics::length::LengthPercentageOrAuto; use std::fmt::{self, Write}; use style_traits::{CssWriter, ToCss}; @@ -22,13 +22,13 @@ use style_traits::{CssWriter, ToCss}; ToAnimatedZero, ToComputedValue, )] -pub enum BackgroundSize { +pub enum BackgroundSize { /// ` ` Explicit { /// Explicit width. - width: LengthPercentageOrAuto, + width: LengthPercentageOrAuto, /// Explicit height. - height: LengthPercentageOrAuto, + height: LengthPercentageOrAuto, }, /// `cover` #[animation(error)] @@ -38,9 +38,9 @@ pub enum BackgroundSize { Contain, } -impl ToCss for BackgroundSize +impl ToCss for BackgroundSize where - LengthPercentageOrAuto: ToCss + IsAuto, + LengthPercentage: ToCss, { fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where diff --git a/components/style/values/generics/length.rs b/components/style/values/generics/length.rs index 006739462aa..61be27e4fd2 100644 --- a/components/style/values/generics/length.rs +++ b/components/style/values/generics/length.rs @@ -4,7 +4,75 @@ //! Generic types for CSS values related to length. +use crate::parser::{Parse, ParserContext}; use crate::values::computed::ExtremumLength; +use cssparser::Parser; +use style_traits::ParseError; + +/// A ` | auto` value. +#[allow(missing_docs)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] +#[repr(C, u8)] +pub enum GenericLengthPercentageOrAuto { + LengthPercentage(LengthPercent), + Auto, +} + +pub use self::GenericLengthPercentageOrAuto as LengthPercentageOrAuto; + +impl LengthPercentageOrAuto { + /// `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>, + ) -> Result> { + if input.try(|i| i.expect_ident_matching("auto")).is_ok() { + return Ok(LengthPercentageOrAuto::Auto); + } + + Ok(LengthPercentageOrAuto::LengthPercentage(parser( + context, input, + )?)) + } +} + +impl Parse for LengthPercentageOrAuto { + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + Self::parse_with(context, input, LengthPercentage::parse) + } +} /// 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. #[allow(missing_docs)] -#[cfg_attr(feature = "servo", derive(MallocSizeOf))] #[derive( Animate, Clone, ComputeSquaredDistance, Copy, Debug, + MallocSizeOf, PartialEq, SpecifiedValueInfo, + ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss, )] -pub enum MozLength { - LengthPercentageOrAuto(LengthPercentageOrAuto), +pub enum MozLength { + LengthPercentage(LengthPercentage), + Auto, #[animation(error)] ExtremumLength(ExtremumLength), } +impl MozLength { + /// `auto` value. + #[inline] + pub fn auto() -> Self { + MozLength::Auto + } +} + /// A generic value for the `max-width` or `max-height` property. #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(MallocSizeOf))] @@ -43,12 +121,23 @@ pub enum MozLength { Debug, PartialEq, SpecifiedValueInfo, + ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss, )] -pub enum MaxLength { - LengthPercentageOrNone(LengthPercentageOrNone), +pub enum MaxLength { + LengthPercentage(LengthPercentage), + None, + #[cfg(feature = "gecko")] #[animation(error)] ExtremumLength(ExtremumLength), } + +impl MaxLength { + /// `none` value. + #[inline] + pub fn none() -> Self { + MaxLength::None + } +} diff --git a/components/style/values/specified/background.rs b/components/style/values/specified/background.rs index 47c66feaef6..b53669abfa8 100644 --- a/components/style/values/specified/background.rs +++ b/components/style/values/specified/background.rs @@ -6,14 +6,16 @@ use crate::parser::{Parse, ParserContext}; 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 selectors::parser::SelectorParseErrorKind; use std::fmt::{self, Write}; use style_traits::{CssWriter, ParseError, ToCss}; /// A specified value for the `background-size` property. -pub type BackgroundSize = GenericBackgroundSize; +pub type BackgroundSize = GenericBackgroundSize; impl Parse for BackgroundSize { fn parse<'i, 't>( diff --git a/components/style/values/specified/gecko.rs b/components/style/values/specified/gecko.rs index 8259430bf20..42ca5e3e2bf 100644 --- a/components/style/values/specified/gecko.rs +++ b/components/style/values/specified/gecko.rs @@ -5,8 +5,8 @@ //! Specified types for legacy Gecko-only properties. use crate::parser::{Parse, ParserContext}; -use crate::values::computed::{self, LengthPercentage}; use crate::values::computed::length::CSSPixelLength; +use crate::values::computed::{self, LengthPercentage}; use crate::values::generics::gecko::ScrollSnapPoint as GenericScrollSnapPoint; use crate::values::generics::rect::Rect; use crate::values::specified::length::LengthPercentage as SpecifiedLengthPercentage; @@ -28,8 +28,8 @@ impl Parse for ScrollSnapPoint { } input.expect_function_matching("repeat")?; // FIXME(emilio): This won't clamp properly when animating. - let length = - input.parse_nested_block(|i| SpecifiedLengthPercentage::parse_non_negative(context, i))?; + let length = input + .parse_nested_block(|i| SpecifiedLengthPercentage::parse_non_negative(context, i))?; Ok(GenericScrollSnapPoint::Repeat(length)) } } @@ -49,9 +49,9 @@ fn parse_pixel_or_percent<'i, 't>( _ => Err(()), } }, - Token::Percentage { unit_value, .. } => Ok( - LengthPercentage::new_percent(computed::Percentage(unit_value)) - ), + Token::Percentage { unit_value, .. } => Ok(LengthPercentage::new_percent( + computed::Percentage(unit_value), + )), _ => Err(()), }; value.map_err(|()| location.new_custom_error(StyleParseErrorKind::UnspecifiedError)) diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index e83abebc37c..9da17990078 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -10,12 +10,14 @@ use super::{AllowQuirks, Number, Percentage, ToComputedValue}; use crate::font_metrics::FontMetricsQueryResult; use crate::parser::{Parse, ParserContext}; use crate::values::computed::{self, CSSPixelLength, Context, ExtremumLength}; -use crate::values::generics::length::MaxLength as GenericMaxLength; -use crate::values::generics::length::MozLength as GenericMozLength; +use crate::values::generics::length as generics; +use crate::values::generics::length::{ + MaxLength as GenericMaxLength, MozLength as GenericMozLength, +}; use crate::values::generics::transform::IsZeroLength; use crate::values::generics::NonNegative; 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 cssparser::{Parser, Token}; use euclid::Size2D; @@ -785,6 +787,16 @@ impl From for LengthPercentage { } } +impl Parse for LengthPercentage { + #[inline] + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + Self::parse_quirky(context, input, AllowQuirks::No) + } +} + impl LengthPercentage { #[inline] /// Returns a `zero` length. @@ -844,12 +856,26 @@ impl LengthPercentage { Ok(LengthPercentage::Calc(Box::new(calc))) } + /// Parses allowing the unitless length quirk. + /// + #[inline] + pub fn parse_quirky<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + allow_quirks: AllowQuirks, + ) -> Result> { + Self::parse_internal(context, input, AllowedNumericType::All, allow_quirks) + } + /// Parse a non-negative length. + /// + /// FIXME(emilio): This should be not public and we should use + /// NonNegativeLengthPercentage instead. #[inline] pub fn parse_non_negative<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, - ) -> Result> { + ) -> Result> { Self::parse_non_negative_quirky(context, input, AllowQuirks::No) } @@ -859,7 +885,7 @@ impl LengthPercentage { context: &ParserContext, input: &mut Parser<'i, 't>, allow_quirks: AllowQuirks, - ) -> Result> { + ) -> Result> { Self::parse_internal( context, 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::parse_quirky(context, input, AllowQuirks::No) - } -} - -impl LengthPercentage { - /// Parses a length or a percentage, allowing the unitless length quirk. - /// - #[inline] - pub fn parse_quirky<'i, 't>( - context: &ParserContext, - input: &mut Parser<'i, 't>, - allow_quirks: AllowQuirks, - ) -> Result> { - Self::parse_internal(context, input, AllowedNumericType::All, allow_quirks) - } -} - impl IsZeroLength for LengthPercentage { #[inline] fn is_zero_length(&self) -> bool { @@ -903,189 +906,64 @@ impl IsZeroLength for LengthPercentage { } } -/// Either a ``, a ``, or the `auto` keyword. -#[allow(missing_docs)] -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)] -pub enum LengthPercentageOrAuto { - LengthPercentage(LengthPercentage), - Auto, -} +/// A specified type for ` | auto`. +pub type LengthPercentageOrAuto = generics::LengthPercentageOrAuto; impl LengthPercentageOrAuto { - fn parse_internal<'i, 't>( - context: &ParserContext, - input: &mut Parser<'i, 't>, - num_context: AllowedNumericType, - allow_quirks: AllowQuirks, - ) -> Result> { - 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> { - 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::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. pub fn zero() -> Self { - LengthPercentageOrAuto::LengthPercentage(LengthPercentage::zero()) + generics::LengthPercentageOrAuto::LengthPercentage(LengthPercentage::zero()) } /// Returns a value representing `0%`. #[inline] 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. + /// #[inline] pub fn parse_quirky<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, allow_quirks: AllowQuirks, ) -> Result> { - Self::parse_internal(context, input, AllowedNumericType::All, allow_quirks) - } -} - -impl Parse for LengthPercentageOrAuto { - #[inline] - fn parse<'i, 't>( - context: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result> { - Self::parse_quirky(context, input, AllowQuirks::No) + Self::parse_with(context, input, |context, input| { + LengthPercentage::parse_quirky(context, input, allow_quirks) + }) } } /// A wrapper of LengthPercentageOrAuto, whose value must be >= 0. -pub type NonNegativeLengthPercentageOrAuto = NonNegative; - -impl IsAuto for NonNegativeLengthPercentageOrAuto { - #[inline] - fn is_auto(&self) -> bool { - *self == Self::auto() - } -} +pub type NonNegativeLengthPercentageOrAuto = + generics::LengthPercentageOrAuto; impl NonNegativeLengthPercentageOrAuto { - /// 0 - #[inline] + /// Returns a value representing a `0` length. pub fn zero() -> Self { - NonNegative(LengthPercentageOrAuto::zero()) + generics::LengthPercentageOrAuto::LengthPercentage(NonNegativeLengthPercentage::zero()) } - /// 0% + /// Returns a value representing `0%`. #[inline] pub fn zero_percent() -> Self { - NonNegative(LengthPercentageOrAuto::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> { - Ok(NonNegative(LengthPercentageOrAuto::parse_non_negative( - context, input, - )?)) - } -} - -/// Either a ``, a ``, 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> { - 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::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::parse_internal( - context, - input, - AllowedNumericType::NonNegative, - allow_quirks, + generics::LengthPercentageOrAuto::LengthPercentage( + NonNegativeLengthPercentage::zero_percent(), ) } -} -impl Parse for LengthPercentageOrNone { + /// Parses a non-negative length-percentage, allowing the unitless length + /// quirk. #[inline] - fn parse<'i, 't>( + pub fn parse_quirky<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, + allow_quirks: AllowQuirks, ) -> Result> { - 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 for NonNegativeLengthPercentage { #[inline] fn from(len: NoCalcLength) -> Self { - NonNegative::(LengthPercentage::from(len)) + NonNegative(LengthPercentage::from(len)) } } @@ -1111,7 +989,7 @@ impl Parse for NonNegativeLengthPercentage { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result> { - LengthPercentage::parse_non_negative(context, input).map(NonNegative::) + Self::parse_quirky(context, input, AllowQuirks::No) } } @@ -1119,7 +997,13 @@ impl NonNegativeLengthPercentage { #[inline] /// Returns a `zero` length. pub fn zero() -> Self { - NonNegative::(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. @@ -1130,8 +1014,7 @@ impl NonNegativeLengthPercentage { input: &mut Parser<'i, 't>, allow_quirks: AllowQuirks, ) -> Result> { - LengthPercentage::parse_non_negative_quirky(context, input, allow_quirks) - .map(NonNegative::) + LengthPercentage::parse_non_negative_quirky(context, input, allow_quirks).map(NonNegative) } } @@ -1168,7 +1051,7 @@ impl LengthOrNumber { } /// A specified value for `min-width`, `min-height`, `width` or `height` property. -pub type MozLength = GenericMozLength; +pub type MozLength = GenericMozLength; impl Parse for MozLength { fn parse<'i, 't>( @@ -1190,26 +1073,23 @@ impl MozLength { return Ok(GenericMozLength::ExtremumLength(l)); } - let length = - LengthPercentageOrAuto::parse_non_negative_quirky(context, input, allow_quirks)?; - Ok(GenericMozLength::LengthPercentageOrAuto(length)) - } + if input.try(|i| i.expect_ident_matching("auto")).is_ok() { + return Ok(GenericMozLength::Auto); + } - /// Returns `auto`. - #[inline] - pub fn auto() -> Self { - GenericMozLength::LengthPercentageOrAuto(LengthPercentageOrAuto::auto()) + let length = NonNegativeLengthPercentage::parse_quirky(context, input, allow_quirks)?; + Ok(GenericMozLength::LengthPercentage(length)) } /// Returns `0%`. #[inline] 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. -pub type MaxLength = GenericMaxLength; +pub type MaxLength = GenericMaxLength; impl Parse for MaxLength { fn parse<'i, 't>( @@ -1227,12 +1107,18 @@ impl MaxLength { input: &mut Parser<'i, 't>, allow_quirks: AllowQuirks, ) -> Result> { - if let Ok(l) = input.try(ExtremumLength::parse) { - return Ok(GenericMaxLength::ExtremumLength(l)); + #[cfg(feature = "gecko")] + { + if let Ok(l) = input.try(ExtremumLength::parse) { + return Ok(GenericMaxLength::ExtremumLength(l)); + } } - let length = - LengthPercentageOrNone::parse_non_negative_quirky(context, input, allow_quirks)?; - Ok(GenericMaxLength::LengthPercentageOrNone(length)) + if input.try(|i| i.expect_ident_matching("none")).is_ok() { + return Ok(GenericMaxLength::None); + } + + let length = NonNegativeLengthPercentage::parse_quirky(context, input, allow_quirks)?; + Ok(GenericMaxLength::LengthPercentage(length)) } } diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 2cb267045ac..b37d2554c34 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -59,7 +59,7 @@ pub use self::image::{GradientItem, GradientKind, Image, ImageLayer, MozImageRec pub use self::length::{AbsoluteLength, CalcLengthPercentage, CharacterWidth}; pub use self::length::{FontRelativeLength, Length, LengthOrNumber}; 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::{NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto}; #[cfg(feature = "gecko")] From 1cb235c81a412548bb650a5f0b0b01aff803fba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 10 Feb 2019 05:04:47 +0100 Subject: [PATCH 8/9] style: Call things by their name. --- components/style/properties/longhands/box.mako.rs | 2 +- resources/user-agent.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs index 28a3367f477..223db1d6e7c 100644 --- a/components/style/properties/longhands/box.mako.rs +++ b/components/style/properties/longhands/box.mako.rs @@ -34,7 +34,7 @@ ${helpers.single_keyword( spec="Internal (not web-exposed)", )} -// An internal-only attribute for elements in a top layer +// An internal-only property for elements in a top layer // https://fullscreen.spec.whatwg.org/#top-layer ${helpers.single_keyword( "-servo-top-layer", diff --git a/resources/user-agent.css b/resources/user-agent.css index fbbc7bef3ea..06410f74b81 100644 --- a/resources/user-agent.css +++ b/resources/user-agent.css @@ -303,7 +303,7 @@ textarea { white-space: pre-wrap; } /* intentionally not !important */ object-fit:contain; - /* The internal-only -servo-top-layer attribute is used + /* The internal-only -servo-top-layer property is used to implement https://fullscreen.spec.whatwg.org/#top-layer */ -servo-top-layer: top; } From 6daebcc5dfc4e57d2f9e9450aa01b8c67dd34986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 10 Feb 2019 06:48:00 +0100 Subject: [PATCH 9/9] Fix servo build. --- components/layout/block.rs | 47 ++++++++------- components/layout/display_list/background.rs | 38 +++++++------ components/layout/display_list/builder.rs | 10 ++-- components/layout/flex.rs | 41 +++++++------ components/layout/floats.rs | 8 +-- components/layout/fragment.rs | 14 +++-- components/layout/lib.rs | 1 + components/layout/model.rs | 31 +++++----- components/layout/multicol.rs | 12 ++-- components/layout/table.rs | 12 ++-- components/layout/table_cell.rs | 20 ++++--- components/layout/table_colgroup.rs | 4 +- components/layout/table_row.rs | 38 ++++++------- components/layout/table_wrapper.rs | 23 ++++---- components/script/devtools.rs | 9 ++- components/script/dom/element.rs | 60 ++++++++++++-------- components/script/lib.rs | 1 + tests/unit/style/viewport.rs | 11 ++-- 18 files changed, 210 insertions(+), 170 deletions(-) diff --git a/components/layout/block.rs b/components/layout/block.rs index 0e4bf140d42..3d19ed1072a 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -67,7 +67,9 @@ use style::context::SharedStyleContext; use style::logical_geometry::{LogicalMargin, LogicalPoint, LogicalRect, LogicalSize, WritingMode}; use style::properties::ComputedValues; use style::servo::restyle_damage::ServoRestyleDamage; -use style::values::computed::{LengthPercentageOrAuto, LengthPercentageOrNone}; +use style::values::computed::{ + LengthPercentageOrAuto, MaxLength, NonNegativeLengthPercentageOrAuto, +}; /// Information specific to floated blocks. #[derive(Clone, Serialize)] @@ -419,15 +421,15 @@ impl CandidateBSizeIterator { // `min-height` and `max-height`, percentage values are ignored. let block_size = match fragment.style.content_block_size() { - LengthPercentageOrAuto::Auto => MaybeAuto::Auto, - LengthPercentageOrAuto::LengthPercentage(ref lp) => { + NonNegativeLengthPercentageOrAuto::Auto => MaybeAuto::Auto, + NonNegativeLengthPercentageOrAuto::LengthPercentage(ref lp) => { MaybeAuto::from_option(lp.maybe_to_used_value(block_container_block_size)) }, }; let max_block_size = match fragment.style.max_block_size() { - LengthPercentageOrNone::None => None, - LengthPercentageOrNone::LengthPercentage(ref lp) => { + MaxLength::None => None, + MaxLength::LengthPercentage(ref lp) => { lp.maybe_to_used_value(block_container_block_size) }, }; @@ -1400,7 +1402,7 @@ impl BlockFlow { let content_block_size = self.fragment.style().content_block_size(); match content_block_size { - LengthPercentageOrAuto::Auto => { + NonNegativeLengthPercentageOrAuto::Auto => { let container_size = containing_block_size?; let (block_start, block_end) = { let position = self.fragment.style().logical_position(); @@ -1435,7 +1437,7 @@ impl BlockFlow { (_, _) => None, } }, - LengthPercentageOrAuto::LengthPercentage(ref lp) => { + NonNegativeLengthPercentageOrAuto::LengthPercentage(ref lp) => { lp.maybe_to_used_value(containing_block_size) }, } @@ -1797,15 +1799,12 @@ impl BlockFlow { .to_used_value(self.base.block_container_inline_size); let specified_inline_size = self.fragment.style().content_inline_size(); let container_size = self.base.block_container_inline_size; - let inline_size = if let MaybeAuto::Specified(size) = - MaybeAuto::from_style(specified_inline_size, container_size) - { - match self.fragment.style().get_position().box_sizing { + let inline_size = match specified_inline_size.to_used_value(container_size) { + Some(size) => match self.fragment.style().get_position().box_sizing { BoxSizing::BorderBox => size, BoxSizing::ContentBox => size + self.fragment.border_padding.inline_start_end(), - } - } else { - max(min_inline_size, min(available_inline_size, max_inline_size)) + }, + None => max(min_inline_size, min(available_inline_size, max_inline_size)), }; self.base.position.size.inline = inline_size + self.fragment.margin.inline_start_end(); @@ -2026,7 +2025,7 @@ impl BlockFlow { // If `max-width` is set, then don't perform this speculation. We guess that the // page set `max-width` in order to avoid hitting floats. The search box on Google // SERPs falls into this category. - if self.fragment.style.max_inline_size() != LengthPercentageOrNone::None { + if self.fragment.style.max_inline_size() != MaxLength::None { return; } @@ -2156,9 +2155,10 @@ impl Flow for BlockFlow { fn bubble_inline_sizes(&mut self) { // If this block has a fixed width, just use that for the minimum and preferred width, // rather than bubbling up children inline width. + // FIXME(emilio): This should probably be writing-mode-aware. let consult_children = match self.fragment.style().get_position().width { - LengthPercentageOrAuto::Auto => true, - LengthPercentageOrAuto::LengthPercentage(ref lp) => { + NonNegativeLengthPercentageOrAuto::Auto => true, + NonNegativeLengthPercentageOrAuto::LengthPercentage(ref lp) => { lp.maybe_to_used_value(None).is_none() }, }; @@ -2846,9 +2846,16 @@ pub trait ISizeAndMarginsComputer { parent_flow_inline_size: Au, shared_context: &SharedStyleContext, ) -> MaybeAuto { - MaybeAuto::from_style( - block.fragment().style().content_inline_size(), - self.containing_block_inline_size(block, parent_flow_inline_size, shared_context), + MaybeAuto::from_option( + block + .fragment() + .style() + .content_inline_size() + .to_used_value(self.containing_block_inline_size( + block, + parent_flow_inline_size, + shared_context, + )), ) } diff --git a/components/layout/display_list/background.rs b/components/layout/display_list/background.rs index d914a97e1bf..368818471d5 100644 --- a/components/layout/display_list/background.rs +++ b/components/layout/display_list/background.rs @@ -5,16 +5,14 @@ // FIXME(rust-lang/rust#26264): Remove GenericBackgroundSize. use crate::display_list::border; -use crate::model::MaybeAuto; use app_units::Au; use euclid::{Point2D, Rect, SideOffsets2D, Size2D}; use style::computed_values::background_attachment::single_value::T as BackgroundAttachment; use style::computed_values::background_clip::single_value::T as BackgroundClip; use style::computed_values::background_origin::single_value::T as BackgroundOrigin; use style::properties::style_structs::Background; -use style::values::computed::{BackgroundSize, LengthPercentageOrAuto}; +use style::values::computed::{BackgroundSize, NonNegativeLengthPercentageOrAuto}; use style::values::generics::background::BackgroundSize as GenericBackgroundSize; -use style::values::generics::NonNegative; use style::values::specified::background::BackgroundRepeatKeyword; use webrender_api::BorderRadius; @@ -60,10 +58,12 @@ fn compute_background_image_size( None => match bg_size { GenericBackgroundSize::Cover | GenericBackgroundSize::Contain => bounds_size, GenericBackgroundSize::Explicit { width, height } => Size2D::new( - MaybeAuto::from_style(width.0, bounds_size.width) - .specified_or_default(bounds_size.width), - MaybeAuto::from_style(height.0, bounds_size.height) - .specified_or_default(bounds_size.height), + width + .to_used_value(bounds_size.width) + .unwrap_or(bounds_size.width), + height + .to_used_value(bounds_size.height) + .unwrap_or(bounds_size.height), ), }, Some(own_size) => { @@ -88,30 +88,34 @@ fn compute_background_image_size( ( GenericBackgroundSize::Explicit { width, - height: NonNegative(LengthPercentageOrAuto::Auto), + height: NonNegativeLengthPercentageOrAuto::Auto, }, _, ) => { - let width = MaybeAuto::from_style(width.0, bounds_size.width) - .specified_or_default(own_size.width); + let width = width + .to_used_value(bounds_size.width) + .unwrap_or(own_size.width); Size2D::new(width, width.scale_by(image_aspect_ratio.recip())) }, ( GenericBackgroundSize::Explicit { - width: NonNegative(LengthPercentageOrAuto::Auto), + width: NonNegativeLengthPercentageOrAuto::Auto, height, }, _, ) => { - let height = MaybeAuto::from_style(height.0, bounds_size.height) - .specified_or_default(own_size.height); + let height = height + .to_used_value(bounds_size.height) + .unwrap_or(own_size.height); Size2D::new(height.scale_by(image_aspect_ratio), height) }, (GenericBackgroundSize::Explicit { width, height }, _) => Size2D::new( - MaybeAuto::from_style(width.0, bounds_size.width) - .specified_or_default(own_size.width), - MaybeAuto::from_style(height.0, bounds_size.height) - .specified_or_default(own_size.height), + width + .to_used_value(bounds_size.width) + .unwrap_or(own_size.width), + height + .to_used_value(bounds_size.height) + .unwrap_or(own_size.height), ), } }, diff --git a/components/layout/display_list/builder.rs b/components/layout/display_list/builder.rs index e348086e39a..6de5ac8498c 100644 --- a/components/layout/display_list/builder.rs +++ b/components/layout/display_list/builder.rs @@ -764,10 +764,12 @@ impl Fragment { get_cyclic(&style.get_background().background_size.0, i).clone(); let size = match background_size { BackgroundSize::Explicit { width, height } => Size2D::new( - MaybeAuto::from_style(width.0, bounding_box_size.width) - .specified_or_default(bounding_box_size.width), - MaybeAuto::from_style(height.0, bounding_box_size.height) - .specified_or_default(bounding_box_size.height), + width + .to_used_value(bounding_box_size.width) + .unwrap_or(bounding_box_size.width), + height + .to_used_value(bounding_box_size.height) + .unwrap_or(bounding_box_size.height), ), _ => bounding_box_size, }; diff --git a/components/layout/flex.rs b/components/layout/flex.rs index fd85b0c24c1..770a02c594b 100644 --- a/components/layout/flex.rs +++ b/components/layout/flex.rs @@ -29,7 +29,9 @@ use style::logical_geometry::{Direction, LogicalSize}; use style::properties::ComputedValues; use style::servo::restyle_damage::ServoRestyleDamage; use style::values::computed::flex::FlexBasis; -use style::values::computed::{LengthPercentage, LengthPercentageOrAuto, LengthPercentageOrNone}; +use style::values::computed::{ + MaxLength, NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto, +}; use style::values::generics::flex::FlexBasis as GenericFlexBasis; /// The size of an axis. May be a specified size, a min/max @@ -45,16 +47,16 @@ impl AxisSize { /// Generate a new available cross or main axis size from the specified size of the container, /// containing block size, min constraint, and max constraint pub fn new( - size: LengthPercentageOrAuto, + size: NonNegativeLengthPercentageOrAuto, content_size: Option, - min: LengthPercentage, - max: LengthPercentageOrNone, + min: NonNegativeLengthPercentage, + max: MaxLength, ) -> AxisSize { match size { - LengthPercentageOrAuto::Auto => { + NonNegativeLengthPercentageOrAuto::Auto => { AxisSize::MinMax(SizeConstraint::new(content_size, min, max, None)) }, - LengthPercentageOrAuto::LengthPercentage(ref lp) => { + NonNegativeLengthPercentageOrAuto::LengthPercentage(ref lp) => { match lp.maybe_to_used_value(content_size) { Some(length) => AxisSize::Definite(length), None => AxisSize::Infinite, @@ -70,7 +72,7 @@ impl AxisSize { /// is definite after flex size resolving. fn from_flex_basis( flex_basis: FlexBasis, - main_length: LengthPercentageOrAuto, + main_length: NonNegativeLengthPercentageOrAuto, containing_length: Au, ) -> MaybeAuto { let width = match flex_basis { @@ -78,9 +80,16 @@ fn from_flex_basis( GenericFlexBasis::Width(width) => width, }; - match width.0 { - LengthPercentageOrAuto::Auto => MaybeAuto::from_style(main_length, containing_length), - other => MaybeAuto::from_style(other, containing_length), + let width = match width { + NonNegativeLengthPercentageOrAuto::Auto => main_length, + _ => width, + }; + + match width { + NonNegativeLengthPercentageOrAuto::Auto => MaybeAuto::Auto, + NonNegativeLengthPercentageOrAuto::LengthPercentage(ref lp) => { + MaybeAuto::Specified(lp.to_used_value(containing_length)) + }, } } @@ -224,18 +233,18 @@ impl FlexItem { let mut margin_count = 0; match direction { Direction::Inline => { - if margin.inline_start == LengthPercentageOrAuto::Auto { + if margin.inline_start.is_auto() { margin_count += 1; } - if margin.inline_end == LengthPercentageOrAuto::Auto { + if margin.inline_end.is_auto() { margin_count += 1; } }, Direction::Block => { - if margin.block_start == LengthPercentageOrAuto::Auto { + if margin.block_start.is_auto() { margin_count += 1; } - if margin.block_end == LengthPercentageOrAuto::Auto { + if margin.block_end.is_auto() { margin_count += 1; } }, @@ -816,7 +825,7 @@ impl FlexFlow { // cross size of item should equal to the line size if any auto margin exists. // https://drafts.csswg.org/css-flexbox/#algo-cross-margins if auto_margin_count > 0 { - if margin.block_start == LengthPercentageOrAuto::Auto { + if margin.block_start.is_auto() { margin_block_start = if free_space < Au(0) { Au(0) } else { @@ -830,7 +839,7 @@ impl FlexFlow { let self_align = block.fragment.style().get_position().align_self; if self_align == AlignSelf::Stretch && - block.fragment.style().content_block_size() == LengthPercentageOrAuto::Auto + block.fragment.style().content_block_size().is_auto() { free_space = Au(0); block.base.block_container_explicit_block_size = Some(line.cross_size); diff --git a/components/layout/floats.rs b/components/layout/floats.rs index 5a58e27f9d1..e3274c1ed91 100644 --- a/components/layout/floats.rs +++ b/components/layout/floats.rs @@ -10,7 +10,7 @@ use std::cmp::{max, min}; use std::fmt; use style::computed_values::float::T as StyleFloat; use style::logical_geometry::{LogicalRect, LogicalSize, WritingMode}; -use style::values::computed::LengthPercentageOrAuto; +use style::values::computed::NonNegativeLengthPercentageOrAuto; /// The kind of float: left or right. #[derive(Clone, Copy, Debug, Serialize)] @@ -549,9 +549,9 @@ impl SpeculatedFloatPlacement { // might flow around this float. let inline_size = flow.as_block().fragment.style.content_inline_size(); let fixed = match inline_size { - LengthPercentageOrAuto::Auto => false, - LengthPercentageOrAuto::LengthPercentage(ref lp) => { - lp.is_definitely_zero() || lp.maybe_to_used_value(None).is_some() + NonNegativeLengthPercentageOrAuto::Auto => false, + NonNegativeLengthPercentageOrAuto::LengthPercentage(ref lp) => { + lp.0.is_definitely_zero() || lp.0.maybe_to_used_value(None).is_some() }, }; if !fixed { diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index db4fd8f4625..1efd40003e6 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -61,7 +61,9 @@ use style::selector_parser::RestyleDamage; use style::servo::restyle_damage::ServoRestyleDamage; use style::str::char_is_whitespace; use style::values::computed::counters::ContentItem; -use style::values::computed::{LengthPercentage, LengthPercentageOrAuto}; +use style::values::computed::{ + LengthPercentage, LengthPercentageOrAuto, NonNegativeLengthPercentageOrAuto, +}; use style::values::generics::box_::{Perspective, VerticalAlign}; use style::values::generics::transform; use webrender_api::{self, LayoutTransform}; @@ -985,8 +987,10 @@ impl Fragment { if flags.contains( QuantitiesIncludedInIntrinsicInlineSizes::INTRINSIC_INLINE_SIZE_INCLUDES_SPECIFIED, ) { - specified = - MaybeAuto::from_style(style.content_inline_size(), Au(0)).specified_or_zero(); + specified = style + .content_inline_size() + .to_used_value(Au(0)) + .unwrap_or(Au(0)); specified = max(style.min_inline_size().to_used_value(Au(0)), specified); if let Some(max) = style.max_inline_size().to_used_value(Au(0)) { specified = min(specified, max) @@ -1611,8 +1615,8 @@ impl Fragment { SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Svg(_) => { let inline_size = match self.style.content_inline_size() { - LengthPercentageOrAuto::Auto => None, - LengthPercentageOrAuto::LengthPercentage(ref lp) => { + NonNegativeLengthPercentageOrAuto::Auto => None, + NonNegativeLengthPercentageOrAuto::LengthPercentage(ref lp) => { lp.maybe_to_used_value(None) }, }; diff --git a/components/layout/lib.rs b/components/layout/lib.rs index f8afdc79190..974ef7c803b 100644 --- a/components/layout/lib.rs +++ b/components/layout/lib.rs @@ -3,6 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #![deny(unsafe_code)] +#![feature(type_alias_enum_variants)] #[macro_use] extern crate bitflags; diff --git a/components/layout/model.rs b/components/layout/model.rs index 0650c8887a1..b5a79d8a383 100644 --- a/components/layout/model.rs +++ b/components/layout/model.rs @@ -11,8 +11,10 @@ use std::cmp::{max, min}; use std::fmt; use style::logical_geometry::{LogicalMargin, WritingMode}; use style::properties::ComputedValues; -use style::values::computed::LengthPercentageOrNone; -use style::values::computed::{LengthPercentage, LengthPercentageOrAuto}; +use style::values::computed::MaxLength; +use style::values::computed::{ + LengthPercentageOrAuto, NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto, +}; /// A collapsible margin. See CSS 2.1 ยง 8.3.1. #[derive(Clone, Copy, Debug)] @@ -135,8 +137,8 @@ impl MarginCollapseInfo { MarginCollapseState::AccumulatingCollapsibleTopMargin => { may_collapse_through = may_collapse_through && match fragment.style().content_block_size() { - LengthPercentageOrAuto::Auto => true, - LengthPercentageOrAuto::LengthPercentage(ref lp) => { + NonNegativeLengthPercentageOrAuto::Auto => true, + NonNegativeLengthPercentageOrAuto::LengthPercentage(ref lp) => { lp.is_definitely_zero() || lp.maybe_to_used_value(containing_block_size).is_none() }, @@ -496,11 +498,14 @@ impl MaybeAuto { /// Receive an optional container size and return used value for width or height. /// /// `style_length`: content size as given in the CSS. -pub fn style_length(style_length: LengthPercentageOrAuto, container_size: Option) -> MaybeAuto { +pub fn style_length( + style_length: NonNegativeLengthPercentageOrAuto, + container_size: Option, +) -> MaybeAuto { match style_length { - LengthPercentageOrAuto::Auto => MaybeAuto::Auto, - LengthPercentageOrAuto::LengthPercentage(ref lp) => { - MaybeAuto::from_option(lp.maybe_to_used_value(container_size)) + NonNegativeLengthPercentageOrAuto::Auto => MaybeAuto::Auto, + NonNegativeLengthPercentageOrAuto::LengthPercentage(ref lp) => { + MaybeAuto::from_option(lp.0.maybe_to_used_value(container_size)) }, } } @@ -566,8 +571,8 @@ impl SizeConstraint { /// Create a `SizeConstraint` for an axis. pub fn new( container_size: Option, - min_size: LengthPercentage, - max_size: LengthPercentageOrNone, + min_size: NonNegativeLengthPercentage, + max_size: MaxLength, border: Option, ) -> SizeConstraint { let mut min_size = min_size @@ -575,10 +580,8 @@ impl SizeConstraint { .unwrap_or(Au(0)); let mut max_size = match max_size { - LengthPercentageOrNone::None => None, - LengthPercentageOrNone::LengthPercentage(ref lp) => { - lp.maybe_to_used_value(container_size) - }, + MaxLength::None => None, + MaxLength::LengthPercentage(ref lp) => lp.maybe_to_used_value(container_size), }; // Make sure max size is not smaller than min size. diff --git a/components/layout/multicol.rs b/components/layout/multicol.rs index 14ea36626f9..feb267103b0 100644 --- a/components/layout/multicol.rs +++ b/components/layout/multicol.rs @@ -19,7 +19,7 @@ use std::fmt; use std::sync::Arc; use style::logical_geometry::LogicalSize; use style::properties::ComputedValues; -use style::values::computed::{LengthPercentageOrAuto, LengthPercentageOrNone}; +use style::values::computed::{MaxLength, NonNegativeLengthPercentageOrAuto}; use style::values::generics::column::ColumnCount; use style::values::Either; @@ -155,16 +155,14 @@ impl Flow for MulticolFlow { available_block_size: { let style = &self.block_flow.fragment.style; let size = match style.content_block_size() { - LengthPercentageOrAuto::Auto => None, - LengthPercentageOrAuto::LengthPercentage(ref lp) => { + NonNegativeLengthPercentageOrAuto::Auto => None, + NonNegativeLengthPercentageOrAuto::LengthPercentage(ref lp) => { lp.maybe_to_used_value(None) }, }; let size = size.or_else(|| match style.max_block_size() { - LengthPercentageOrNone::None => None, - LengthPercentageOrNone::LengthPercentage(ref lp) => { - lp.maybe_to_used_value(None) - }, + MaxLength::None => None, + MaxLength::LengthPercentage(ref lp) => lp.maybe_to_used_value(None), }); size.unwrap_or_else(|| { diff --git a/components/layout/table.rs b/components/layout/table.rs index f7bf902e452..7aa8f2a89d4 100644 --- a/components/layout/table.rs +++ b/components/layout/table.rs @@ -33,7 +33,7 @@ use style::logical_geometry::LogicalSize; use style::properties::style_structs::Background; use style::properties::ComputedValues; use style::servo::restyle_damage::ServoRestyleDamage; -use style::values::computed::LengthPercentageOrAuto; +use style::values::computed::NonNegativeLengthPercentageOrAuto; use style::values::CSSFloat; #[allow(unsafe_code)] @@ -301,15 +301,15 @@ impl Flow for TableFlow { self.column_intrinsic_inline_sizes .push(ColumnIntrinsicInlineSize { minimum_length: match *specified_inline_size { - LengthPercentageOrAuto::Auto => Au(0), - LengthPercentageOrAuto::LengthPercentage(ref lp) => { + NonNegativeLengthPercentageOrAuto::Auto => Au(0), + NonNegativeLengthPercentageOrAuto::LengthPercentage(ref lp) => { lp.maybe_to_used_value(None).unwrap_or(Au(0)) }, }, percentage: match *specified_inline_size { - LengthPercentageOrAuto::Auto => 0.0, - LengthPercentageOrAuto::LengthPercentage(ref lp) => { - lp.as_percentage().map_or(0.0, |p| p.0) + NonNegativeLengthPercentageOrAuto::Auto => 0.0, + NonNegativeLengthPercentageOrAuto::LengthPercentage(ref lp) => { + lp.0.as_percentage().map_or(0.0, |p| p.0) }, }, preferred: Au(0), diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs index d72a6670576..3bcc39f0193 100644 --- a/components/layout/table_cell.rs +++ b/components/layout/table_cell.rs @@ -12,7 +12,6 @@ use crate::display_list::{ use crate::flow::{Flow, FlowClass, FlowFlags, GetBaseFlow, OpaqueFlow}; use crate::fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use crate::layout_debug; -use crate::model::MaybeAuto; use crate::table::InternalTable; use crate::table_row::{CollapsedBorder, CollapsedBorderProvenance}; use app_units::Au; @@ -22,6 +21,7 @@ use script_layout_interface::wrapper_traits::ThreadSafeLayoutNode; use std::fmt; use style::logical_geometry::{LogicalMargin, LogicalRect, LogicalSize, WritingMode}; use style::properties::ComputedValues; +use style::values::computed::length::NonNegativeLengthPercentageOrAuto; use style::values::computed::Color; use style::values::generics::box_::VerticalAlign; use style::values::specified::BorderStyle; @@ -162,8 +162,12 @@ impl TableCellFlow { // Call after block size calculation pub fn total_block_size(&mut self) -> Au { // TODO: Percentage block-size - let specified = MaybeAuto::from_style(self.fragment().style().content_block_size(), Au(0)) - .specified_or_zero(); + let specified = self + .fragment() + .style() + .content_block_size() + .to_used_value(Au(0)) + .unwrap_or(Au(0)); specified + self.fragment().border_padding.block_start_end() } } @@ -198,11 +202,11 @@ impl Flow for TableCellFlow { ); self.block_flow.bubble_inline_sizes_for_block(true); - let specified_inline_size = MaybeAuto::from_style( - self.block_flow.fragment.style().content_inline_size(), - Au(0), - ) - .specified_or_zero(); + let specified_inline_size = match self.block_flow.fragment.style().content_inline_size() { + NonNegativeLengthPercentageOrAuto::Auto => Au(0), + NonNegativeLengthPercentageOrAuto::LengthPercentage(ref lp) => lp.to_used_value(Au(0)), + }; + if self .block_flow .base diff --git a/components/layout/table_colgroup.rs b/components/layout/table_colgroup.rs index 6bb5cbe620b..1097d6dae38 100644 --- a/components/layout/table_colgroup.rs +++ b/components/layout/table_colgroup.rs @@ -14,7 +14,7 @@ use euclid::Point2D; use std::fmt; use style::logical_geometry::LogicalSize; use style::properties::ComputedValues; -use style::values::computed::LengthPercentageOrAuto; +use style::values::computed::NonNegativeLengthPercentageOrAuto; #[allow(unsafe_code)] unsafe impl crate::flow::HasBaseFlow for TableColGroupFlow {} @@ -34,7 +34,7 @@ pub struct TableColGroupFlow { /// The specified inline-sizes of table columns. (We use `LengthPercentageOrAuto` here in /// lieu of `ColumnInlineSize` because column groups do not establish minimum or preferred /// inline sizes.) - pub inline_sizes: Vec, + pub inline_sizes: Vec, } impl TableColGroupFlow { diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs index 22db572c166..78768f5a1ab 100644 --- a/components/layout/table_row.rs +++ b/components/layout/table_row.rs @@ -15,7 +15,6 @@ use crate::flow::{ use crate::flow_list::MutFlowListIterator; use crate::fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use crate::layout_debug; -use crate::model::MaybeAuto; use crate::table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable, VecExt}; use crate::table_cell::{CollapsedBordersForCell, TableCellFlow}; use app_units::Au; @@ -30,7 +29,7 @@ use style::computed_values::border_spacing::T as BorderSpacing; use style::computed_values::border_top_style::T as BorderStyle; use style::logical_geometry::{LogicalSize, PhysicalSide, WritingMode}; use style::properties::ComputedValues; -use style::values::computed::{Color, LengthPercentageOrAuto}; +use style::values::computed::{Color, NonNegativeLengthPercentageOrAuto}; #[allow(unsafe_code)] unsafe impl crate::flow::HasBaseFlow for TableRowFlow {} @@ -208,16 +207,15 @@ impl TableRowFlow { &mut max_block_size, ); - let mut block_size = max_block_size; // TODO: Percentage block-size - block_size = match MaybeAuto::from_style( - self.block_flow.fragment.style().content_block_size(), - Au(0), - ) { - MaybeAuto::Auto => block_size, - MaybeAuto::Specified(value) => max(value, block_size), - }; - block_size + let block_size = self + .block_flow + .fragment + .style() + .content_block_size() + .to_used_value(Au(0)) + .unwrap_or(max_block_size); + max(block_size, max_block_size) } pub fn assign_block_size_to_self_and_children( @@ -431,23 +429,23 @@ impl Flow for TableRowFlow { let child_base = kid.mut_base(); let child_column_inline_size = ColumnIntrinsicInlineSize { minimum_length: match child_specified_inline_size { - LengthPercentageOrAuto::Auto => None, - LengthPercentageOrAuto::LengthPercentage(ref lp) => { - lp.maybe_to_used_value(None) + NonNegativeLengthPercentageOrAuto::Auto => None, + NonNegativeLengthPercentageOrAuto::LengthPercentage(ref lp) => { + lp.0.maybe_to_used_value(None) }, } .unwrap_or(child_base.intrinsic_inline_sizes.minimum_inline_size), percentage: match child_specified_inline_size { - LengthPercentageOrAuto::Auto => 0.0, - LengthPercentageOrAuto::LengthPercentage(ref lp) => { - lp.as_percentage().map_or(0.0, |p| p.0) + NonNegativeLengthPercentageOrAuto::Auto => 0.0, + NonNegativeLengthPercentageOrAuto::LengthPercentage(ref lp) => { + lp.0.as_percentage().map_or(0.0, |p| p.0) }, }, preferred: child_base.intrinsic_inline_sizes.preferred_inline_size, constrained: match child_specified_inline_size { - LengthPercentageOrAuto::Auto => false, - LengthPercentageOrAuto::LengthPercentage(ref lp) => { - lp.maybe_to_used_value(None).is_some() + NonNegativeLengthPercentageOrAuto::Auto => false, + NonNegativeLengthPercentageOrAuto::LengthPercentage(ref lp) => { + lp.0.maybe_to_used_value(None).is_some() }, }, }; diff --git a/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs index 9e8f137e70a..b63da7d56e5 100644 --- a/components/layout/table_wrapper.rs +++ b/components/layout/table_wrapper.rs @@ -33,7 +33,7 @@ use style::computed_values::{position, table_layout}; use style::context::SharedStyleContext; use style::logical_geometry::{LogicalRect, LogicalSize}; use style::properties::ComputedValues; -use style::values::computed::LengthPercentageOrAuto; +use style::values::computed::NonNegativeLengthPercentageOrAuto; use style::values::CSSFloat; #[derive(Clone, Copy, Debug, Serialize)] @@ -201,7 +201,7 @@ impl TableWrapperFlow { // says "the basic idea is the same as the shrink-to-fit width that CSS2.1 defines". So we // just use the shrink-to-fit inline size. let available_inline_size = match self.block_flow.fragment.style().content_inline_size() { - LengthPercentageOrAuto::Auto => { + NonNegativeLengthPercentageOrAuto::Auto => { self.block_flow .get_shrink_to_fit_inline_size(available_inline_size) - table_border_padding @@ -840,12 +840,8 @@ fn initial_computed_inline_size( preferred_width_of_all_columns: Au, table_border_padding: Au, ) -> MaybeAuto { - let inline_size_from_style = MaybeAuto::from_style( - block.fragment.style.content_inline_size(), - containing_block_inline_size, - ); - match inline_size_from_style { - MaybeAuto::Auto => { + match block.fragment.style.content_inline_size() { + NonNegativeLengthPercentageOrAuto::Auto => { if preferred_width_of_all_columns + table_border_padding <= containing_block_inline_size { MaybeAuto::Specified(preferred_width_of_all_columns + table_border_padding) @@ -855,10 +851,13 @@ fn initial_computed_inline_size( MaybeAuto::Auto } }, - MaybeAuto::Specified(inline_size_from_style) => MaybeAuto::Specified(max( - inline_size_from_style - table_border_padding, - minimum_width_of_all_columns, - )), + NonNegativeLengthPercentageOrAuto::LengthPercentage(ref lp) => { + let used = lp.to_used_value(containing_block_inline_size); + MaybeAuto::Specified(max( + used - table_border_padding, + minimum_width_of_all_columns, + )) + }, } } diff --git a/components/script/devtools.rs b/components/script/devtools.rs index 58b0a7d20a7..7a24d959980 100644 --- a/components/script/devtools.rs +++ b/components/script/devtools.rs @@ -29,7 +29,6 @@ use js::rust::wrappers::ObjectClassName; use msg::constellation_msg::PipelineId; use std::ffi::CStr; use std::str; -use style::properties::longhands::{margin_bottom, margin_left, margin_right, margin_top}; use uuid::Uuid; #[allow(unsafe_code)] @@ -178,10 +177,10 @@ fn determine_auto_margins(window: &Window, node: &Node) -> AutoMargins { let style = window.style_query(node.to_trusted_node_address()).unwrap(); let margin = style.get_margin(); AutoMargins { - top: margin.margin_top == margin_top::computed_value::T::Auto, - right: margin.margin_right == margin_right::computed_value::T::Auto, - bottom: margin.margin_bottom == margin_bottom::computed_value::T::Auto, - left: margin.margin_left == margin_left::computed_value::T::Auto, + top: margin.margin_top.is_auto(), + right: margin.margin_right.is_auto(), + bottom: margin.margin_bottom.is_auto(), + left: margin.margin_left.is_auto(), } } diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 234a10f9448..dbcab42f11f 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -718,9 +718,11 @@ impl LayoutElementHelpers for LayoutDom { specified::NoCalcLength::ServoCharacterWidth(specified::CharacterWidth(size)); hints.push(from_declaration( shared_lock, - PropertyDeclaration::Width(specified::LengthPercentageOrAuto::LengthPercentage( - specified::LengthPercentage::Length(value), - )), + PropertyDeclaration::Width( + specified::NonNegativeLengthPercentageOrAuto::LengthPercentage(NonNegative( + specified::LengthPercentage::Length(value), + )), + ), )); } @@ -745,20 +747,22 @@ impl LayoutElementHelpers for LayoutDom { match width { LengthOrPercentageOrAuto::Auto => {}, LengthOrPercentageOrAuto::Percentage(percentage) => { - let width_value = specified::LengthPercentageOrAuto::LengthPercentage( - specified::LengthPercentage::Percentage(computed::Percentage(percentage)), - ); + let width_value = + specified::NonNegativeLengthPercentageOrAuto::LengthPercentage(NonNegative( + specified::LengthPercentage::Percentage(computed::Percentage(percentage)), + )); hints.push(from_declaration( shared_lock, PropertyDeclaration::Width(width_value), )); }, LengthOrPercentageOrAuto::Length(length) => { - let width_value = specified::LengthPercentageOrAuto::LengthPercentage( - specified::LengthPercentage::Length(specified::NoCalcLength::Absolute( - specified::AbsoluteLength::Px(length.to_f32_px()), - )), - ); + let width_value = + specified::NonNegativeLengthPercentageOrAuto::LengthPercentage(NonNegative( + specified::LengthPercentage::Length(specified::NoCalcLength::Absolute( + specified::AbsoluteLength::Px(length.to_f32_px()), + )), + )); hints.push(from_declaration( shared_lock, PropertyDeclaration::Width(width_value), @@ -779,20 +783,22 @@ impl LayoutElementHelpers for LayoutDom { match height { LengthOrPercentageOrAuto::Auto => {}, LengthOrPercentageOrAuto::Percentage(percentage) => { - let height_value = specified::LengthPercentageOrAuto::LengthPercentage( - specified::LengthPercentage::Percentage(computed::Percentage(percentage)), - ); + let height_value = + specified::NonNegativeLengthPercentageOrAuto::LengthPercentage(NonNegative( + specified::LengthPercentage::Percentage(computed::Percentage(percentage)), + )); hints.push(from_declaration( shared_lock, PropertyDeclaration::Height(height_value), )); }, LengthOrPercentageOrAuto::Length(length) => { - let height_value = specified::LengthPercentageOrAuto::LengthPercentage( - specified::LengthPercentage::Length(specified::NoCalcLength::Absolute( - specified::AbsoluteLength::Px(length.to_f32_px()), - )), - ); + let height_value = + specified::NonNegativeLengthPercentageOrAuto::LengthPercentage(NonNegative( + specified::LengthPercentage::Length(specified::NoCalcLength::Absolute( + specified::AbsoluteLength::Px(length.to_f32_px()), + )), + )); hints.push(from_declaration( shared_lock, PropertyDeclaration::Height(height_value), @@ -819,9 +825,11 @@ impl LayoutElementHelpers for LayoutDom { specified::NoCalcLength::ServoCharacterWidth(specified::CharacterWidth(cols)); hints.push(from_declaration( shared_lock, - PropertyDeclaration::Width(specified::LengthPercentageOrAuto::LengthPercentage( - specified::LengthPercentage::Length(value), - )), + PropertyDeclaration::Width( + specified::NonNegativeLengthPercentageOrAuto::LengthPercentage(NonNegative( + specified::LengthPercentage::Length(value), + )), + ), )); } @@ -843,9 +851,11 @@ impl LayoutElementHelpers for LayoutDom { )); hints.push(from_declaration( shared_lock, - PropertyDeclaration::Height(specified::LengthPercentageOrAuto::LengthPercentage( - specified::LengthPercentage::Length(value), - )), + PropertyDeclaration::Height( + specified::NonNegativeLengthPercentageOrAuto::LengthPercentage(NonNegative( + specified::LengthPercentage::Length(value), + )), + ), )); } diff --git a/components/script/lib.rs b/components/script/lib.rs index ce427aa3a56..1332e604fdb 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -8,6 +8,7 @@ #![feature(drain_filter)] #![feature(plugin)] #![feature(try_from)] +#![feature(type_alias_enum_variants)] #![deny(unsafe_code)] #![allow(non_snake_case)] #![doc = "The script crate contains all matters DOM."] diff --git a/tests/unit/style/viewport.rs b/tests/unit/style/viewport.rs index 89f708643b9..b4043038b83 100644 --- a/tests/unit/style/viewport.rs +++ b/tests/unit/style/viewport.rs @@ -14,8 +14,9 @@ use style::parser::ParserContext; use style::shared_lock::{SharedRwLock, StylesheetGuards}; use style::stylesheets::viewport_rule::*; use style::stylesheets::{CssRuleType, Origin, Stylesheet, StylesheetInDocument}; +use style::values::generics::length::LengthPercentageOrAuto::{self, Auto}; +use style::values::generics::NonNegative; use style::values::specified::LengthPercentage; -use style::values::specified::LengthPercentageOrAuto::{self, Auto}; use style::values::specified::NoCalcLength::{self, ViewportPercentage}; use style::values::specified::ViewportPercentageLength::Vw; use style_traits::viewport::*; @@ -97,14 +98,14 @@ macro_rules! assert_decl_len { macro_rules! viewport_length { ($value:expr, px) => { - ViewportLength::Specified(LengthPercentageOrAuto::LengthPercentage( + ViewportLength::Specified(LengthPercentageOrAuto::LengthPercentage(NonNegative( LengthPercentage::Length(NoCalcLength::from_px($value)), - )) + ))) }; ($value:expr, vw) => { - ViewportLength::Specified(LengthPercentageOrAuto::LengthPercentage( + ViewportLength::Specified(LengthPercentageOrAuto::LengthPercentage(NonNegative( LengthPercentage::Length(ViewportPercentage(Vw($value))), - )) + ))) }; }