From 2ff1e2200e85596ac608ddfe034f024a48a62149 Mon Sep 17 00:00:00 2001 From: CYBAI Date: Mon, 1 Jan 2018 12:14:39 -0600 Subject: [PATCH] servo: Merge #19659 - style: Move display outside of mako (from CYBAI:display-out-of-mako); r=emilio This is a sub-PR of #19015 r? emilio --- - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #19658 - [x] These changes do not require tests Source-Repo: https://github.com/servo/servo Source-Revision: 2a139cebacc02b3ae04974e1e5b2b601df5b774c --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 77c791f1c8ee001deef16ed754ca3200ddcbee77 --- .../style/properties/longhand/box.mako.rs | 251 ++---------------- servo/components/style/values/computed/box.rs | 4 +- servo/components/style/values/computed/mod.rs | 2 +- .../components/style/values/specified/box.rs | 216 +++++++++++++++ .../components/style/values/specified/mod.rs | 2 +- 5 files changed, 249 insertions(+), 226 deletions(-) diff --git a/servo/components/style/properties/longhand/box.mako.rs b/servo/components/style/properties/longhand/box.mako.rs index 58520d3cd903..a24c3cb036bc 100644 --- a/servo/components/style/properties/longhand/box.mako.rs +++ b/servo/components/style/properties/longhand/box.mako.rs @@ -13,229 +13,36 @@ // // We allow "display" to apply to placeholders because we need to make the // placeholder pseudo-element an inline-block in the UA stylesheet in Gecko. -<%helpers:longhand name="display" - animation_value_type="discrete" - custom_cascade="${product == 'servo'}" - flags="APPLIES_TO_PLACEHOLDER" - spec="https://drafts.csswg.org/css-display/#propdef-display"> - <% - values = """inline block inline-block - table inline-table table-row-group table-header-group table-footer-group - table-row table-column-group table-column table-cell table-caption - list-item none - """.split() - webkit_prefixed_values = "flex inline-flex".split() - values += webkit_prefixed_values - if product == "gecko": - values += """grid inline-grid ruby ruby-base ruby-base-container - ruby-text ruby-text-container contents flow-root -webkit-box - -webkit-inline-box -moz-box -moz-inline-box -moz-grid -moz-inline-grid - -moz-grid-group -moz-grid-line -moz-stack -moz-inline-stack -moz-deck - -moz-popup -moz-groupbox""".split() - %> - use style_traits::ToCss; +${helpers.predefined_type( + "display", + "Display", + "computed::Display::inline()", + initial_specified_value="specified::Display::inline()", + animation_value_type="discrete", + needs_context=False, + custom_cascade= product == 'servo', + custom_cascade_function="specified::Display::cascade_property_custom", + flags="APPLIES_TO_PLACEHOLDER", + spec="https://drafts.csswg.org/css-display/#propdef-display", +)} - pub mod computed_value { - pub use super::SpecifiedValue as T; - use super::SpecifiedValue as Display; - - impl Display { - /// Returns whether this "display" value is the display of a flex or - /// grid container. - /// - /// This is used to implement various style fixups. - pub fn is_item_container(&self) -> bool { - matches!(*self, - Display::Flex - | Display::InlineFlex - % if product == "gecko": - | Display::Grid - | Display::InlineGrid - % endif - ) - } - - /// Returns whether an element with this display type is a line - /// participant, which means it may lay its children on the same - /// line as itself. - pub fn is_line_participant(&self) -> bool { - matches!(*self, - Display::Inline - % if product == "gecko": - | Display::Contents - | Display::Ruby - | Display::RubyBaseContainer - % endif - ) - } - - /// Whether `new_display` should be ignored, given a previous - /// `old_display` value. - /// - /// This is used to ignore `display: -moz-box` declarations after an - /// equivalent `display: -webkit-box` declaration, since the former - /// has a vastly different meaning. See bug 1107378 and bug 1407701. - /// - /// FIXME(emilio): This is a pretty decent hack, we should try to - /// remove it. - pub fn should_ignore_parsed_value( - _old_display: Self, - _new_display: Self, - ) -> bool { - #[cfg(feature = "gecko")] - { - match (_old_display, _new_display) { - (Display::WebkitBox, Display::MozBox) | - (Display::WebkitInlineBox, Display::MozInlineBox) => { - return true; - } - _ => {}, - } - } - - return false; - } - - /// Returns whether this "display" value is one of the types for - /// ruby. - #[cfg(feature = "gecko")] - pub fn is_ruby_type(&self) -> bool { - matches!(*self, - Display::Ruby | - Display::RubyBase | - Display::RubyText | - Display::RubyBaseContainer | - Display::RubyTextContainer) - } - - /// Returns whether this "display" value is a ruby level container. - #[cfg(feature = "gecko")] - pub fn is_ruby_level_container(&self) -> bool { - matches!(*self, - Display::RubyBaseContainer | - Display::RubyTextContainer) - } - - /// Convert this display into an equivalent block display. - /// - /// Also used for style adjustments. - pub fn equivalent_block_display(&self, _is_root_element: bool) -> Self { - match *self { - // Values that have a corresponding block-outside version. - Display::InlineTable => Display::Table, - Display::InlineFlex => Display::Flex, - - % if product == "gecko": - Display::InlineGrid => Display::Grid, - Display::WebkitInlineBox => Display::WebkitBox, - % endif - - // Special handling for contents and list-item on the root - // element for Gecko. - % if product == "gecko": - Display::Contents | Display::ListItem if _is_root_element => Display::Block, - % endif - - // These are not changed by blockification. - Display::None | - Display::Block | - Display::Flex | - Display::ListItem | - Display::Table => *self, - - % if product == "gecko": - Display::Contents | - Display::FlowRoot | - Display::Grid | - Display::WebkitBox => *self, - % endif - - // Everything else becomes block. - _ => Display::Block, - } - - } - - /// Convert this display into an inline-outside display. - /// - /// Ideally it should implement spec: https://drafts.csswg.org/css-display/#inlinify - /// but the spec isn't stable enough, so we copy what Gecko does for now. - #[cfg(feature = "gecko")] - pub fn inlinify(&self) -> Self { - match *self { - Display::Block | - Display::FlowRoot => Display::InlineBlock, - Display::Table => Display::InlineTable, - Display::Flex => Display::InlineFlex, - Display::Grid => Display::InlineGrid, - Display::MozBox => Display::MozInlineBox, - Display::MozStack => Display::MozInlineStack, - Display::WebkitBox => Display::WebkitInlineBox, - other => other, - } - } - } - } - - // FIXME(emilio): Why does this reinvent the wheel, again? - #[allow(non_camel_case_types)] - #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue)] - #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] - pub enum SpecifiedValue { - % for value in values: - ${to_camel_case(value)}, - % endfor - } - - // TODO(emilio): derive. - impl ToCss for SpecifiedValue { - fn to_css(&self, dest: &mut W) -> ::std::fmt::Result - where W: ::std::fmt::Write, - { - match *self { - % for value in values: - SpecifiedValue::${to_camel_case(value)} => dest.write_str("${value}"), - % endfor - } - } - } - - /// The initial display value. - #[inline] - pub fn get_initial_value() -> computed_value::T { - computed_value::T::${to_camel_case(values[0])} - } - - /// Parse a display value. - pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result> { - try_match_ident_ignore_ascii_case! { input, - % for value in values: - "${value}" => { - Ok(computed_value::T::${to_camel_case(value)}) - }, - % endfor - % for value in webkit_prefixed_values: - "-webkit-${value}" => { - Ok(computed_value::T::${to_camel_case(value)}) - }, - % endfor - } - } - - % if product == "servo": - fn cascade_property_custom(_declaration: &PropertyDeclaration, - context: &mut computed::Context) { - longhands::_servo_display_for_hypothetical_box::derive_from_display(context); - longhands::_servo_text_decorations_in_effect::derive_from_display(context); - } - % endif - - ${helpers.gecko_keyword_conversion(Keyword('display', ' '.join(values), - gecko_enum_prefix='StyleDisplay', - gecko_strip_moz_prefix=False))} - - +// FIXME(emilio): Listing all the display values here is very unfortunate, we should teach C++ to use the +// Rust enum directly, or generate the conversions to `StyleDisplay`. +${helpers.gecko_keyword_conversion( + Keyword('display', """ + inline block inline-block + table inline-table table-row-group table-header-group table-footer-group + table-row table-column-group table-column table-cell table-caption + list-item none flex inline-flex grid inline-grid ruby ruby-base ruby-base-container + ruby-text ruby-text-container contents flow-root -webkit-box + -webkit-inline-box -moz-box -moz-inline-box -moz-grid -moz-inline-grid + -moz-grid-group -moz-grid-line -moz-stack -moz-inline-stack -moz-deck + -moz-popup -moz-groupbox + """, + gecko_enum_prefix='StyleDisplay', + gecko_strip_moz_prefix=False), + type="::values::specified::Display" +)} ${helpers.single_keyword("-moz-top-layer", "none top", gecko_constant_prefix="NS_STYLE_TOP_LAYER", diff --git a/servo/components/style/values/computed/box.rs b/servo/components/style/values/computed/box.rs index 5d606f9fe6ff..2916b3a96955 100644 --- a/servo/components/style/values/computed/box.rs +++ b/servo/components/style/values/computed/box.rs @@ -9,8 +9,8 @@ use values::computed::length::LengthOrPercentage; use values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount; use values::generics::box_::VerticalAlign as GenericVerticalAlign; -pub use values::specified::box_::{AnimationName, OverflowClipBox, OverscrollBehavior}; -pub use values::specified::box_::{ScrollSnapType, TouchAction, WillChange}; +pub use values::specified::box_::{AnimationName, Display, OverflowClipBox}; +pub use values::specified::box_::{OverscrollBehavior, ScrollSnapType, TouchAction, WillChange}; /// A computed value for the `vertical-align` property. pub type VerticalAlign = GenericVerticalAlign; diff --git a/servo/components/style/values/computed/mod.rs b/servo/components/style/values/computed/mod.rs index e81dcfc735f1..08095d8628cd 100644 --- a/servo/components/style/values/computed/mod.rs +++ b/servo/components/style/values/computed/mod.rs @@ -40,7 +40,7 @@ pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, FontVa pub use self::font::{FontFamily, FontLanguageOverride, FontVariantSettings, FontVariantEastAsian}; pub use self::font::{FontVariantLigatures, FontVariantNumeric, FontFeatureSettings}; pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier, XTextZoom, XLang}; -pub use self::box_::{AnimationIterationCount, AnimationName, OverscrollBehavior}; +pub use self::box_::{AnimationIterationCount, AnimationName, Display, OverscrollBehavior}; pub use self::box_::{OverflowClipBox, ScrollSnapType, TouchAction, VerticalAlign, WillChange}; pub use self::color::{Color, ColorPropertyValue, RGBAColor}; pub use self::effects::{BoxShadow, Filter, SimpleShadow}; diff --git a/servo/components/style/values/specified/box.rs b/servo/components/style/values/specified/box.rs index b43ae4886214..9a17db7a4807 100644 --- a/servo/components/style/values/specified/box.rs +++ b/servo/components/style/values/specified/box.rs @@ -7,15 +7,231 @@ use Atom; use cssparser::Parser; use parser::{Parse, ParserContext}; +#[cfg(feature = "servo")] +use properties::{longhands, PropertyDeclaration}; use std::fmt; use style_traits::{ParseError, ToCss}; use values::CustomIdent; use values::KeyframesName; +#[cfg(feature = "servo")] +use values::computed::Context; use values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount; use values::generics::box_::VerticalAlign as GenericVerticalAlign; use values::specified::{AllowQuirks, Number}; use values::specified::length::LengthOrPercentage; +#[allow(missing_docs)] +#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +/// Defines an element’s display type, which consists of +/// the two basic qualities of how an element generates boxes +/// +pub enum Display { + Inline, Block, InlineBlock, + Table, InlineTable, TableRowGroup, TableHeaderGroup, + TableFooterGroup, TableRow, TableColumnGroup, + TableColumn, TableCell, TableCaption, ListItem, None, + #[parse(aliases = "-webkit-flex")] + Flex, + #[parse(aliases = "-webkit-inline-flex")] + InlineFlex, + #[cfg(feature = "gecko")] + Grid, + #[cfg(feature = "gecko")] + InlineGrid, + #[cfg(feature = "gecko")] + Ruby, + #[cfg(feature = "gecko")] + RubyBase, + #[cfg(feature = "gecko")] + RubyBaseContainer, + #[cfg(feature = "gecko")] + RubyText, + #[cfg(feature = "gecko")] + RubyTextContainer, + #[cfg(feature = "gecko")] + Contents, + #[cfg(feature = "gecko")] + FlowRoot, + #[cfg(feature = "gecko")] + WebkitBox, + #[cfg(feature = "gecko")] + WebkitInlineBox, + #[cfg(feature = "gecko")] + MozBox, + #[cfg(feature = "gecko")] + MozInlineBox, + #[cfg(feature = "gecko")] + MozGrid, + #[cfg(feature = "gecko")] + MozInlineGrid, + #[cfg(feature = "gecko")] + MozGridGroup, + #[cfg(feature = "gecko")] + MozGridLine, + #[cfg(feature = "gecko")] + MozStack, + #[cfg(feature = "gecko")] + MozInlineStack, + #[cfg(feature = "gecko")] + MozDeck, + #[cfg(feature = "gecko")] + MozPopup, + #[cfg(feature = "gecko")] + MozGroupbox, +} + +impl Display { + /// The initial display value. + #[inline] + pub fn inline() -> Self { + Display::Inline + } + + /// Returns whether this "display" value is the display of a flex or + /// grid container. + /// + /// This is used to implement various style fixups. + pub fn is_item_container(&self) -> bool { + match *self { + Display::Flex | Display::InlineFlex => true, + #[cfg(feature = "gecko")] + Display::Grid | Display::InlineGrid => true, + _ => false, + } + } + + /// Returns whether an element with this display type is a line + /// participant, which means it may lay its children on the same + /// line as itself. + pub fn is_line_participant(&self) -> bool { + match *self { + Display::Inline => true, + #[cfg(feature = "gecko")] + Display::Contents | + Display::Ruby | + Display::RubyBaseContainer => true, + _ => false, + } + } + + /// Whether `new_display` should be ignored, given a previous + /// `old_display` value. + /// + /// This is used to ignore `display: -moz-box` declarations after an + /// equivalent `display: -webkit-box` declaration, since the former + /// has a vastly different meaning. See bug 1107378 and bug 1407701. + /// + /// FIXME(emilio): This is a pretty decent hack, we should try to + /// remove it. + pub fn should_ignore_parsed_value( + _old_display: Self, + _new_display: Self, + ) -> bool { + #[cfg(feature = "gecko")] { + match (_old_display, _new_display) { + (Display::WebkitBox, Display::MozBox) | + (Display::WebkitInlineBox, Display::MozInlineBox) => { + return true; + } + _ => {}, + } + } + + return false; + } + + /// Returns whether this "display" value is one of the types for + /// ruby. + #[cfg(feature = "gecko")] + pub fn is_ruby_type(&self) -> bool { + matches!(*self, + Display::Ruby | + Display::RubyBase | + Display::RubyText | + Display::RubyBaseContainer | + Display::RubyTextContainer + ) + } + + /// Returns whether this "display" value is a ruby level container. + #[cfg(feature = "gecko")] + pub fn is_ruby_level_container(&self) -> bool { + matches!(*self, + Display::RubyBaseContainer | + Display::RubyTextContainer + ) + } + + /// Convert this display into an equivalent block display. + /// + /// Also used for style adjustments. + pub fn equivalent_block_display(&self, _is_root_element: bool) -> Self { + match *self { + // Values that have a corresponding block-outside version. + Display::InlineTable => Display::Table, + Display::InlineFlex => Display::Flex, + + #[cfg(feature = "gecko")] + Display::InlineGrid => Display::Grid, + #[cfg(feature = "gecko")] + Display::WebkitInlineBox => Display::WebkitBox, + + // Special handling for contents and list-item on the root + // element for Gecko. + #[cfg(feature = "gecko")] + Display::Contents | Display::ListItem if _is_root_element => Display::Block, + + // These are not changed by blockification. + Display::None | + Display::Block | + Display::Flex | + Display::ListItem | + Display::Table => *self, + + #[cfg(feature = "gecko")] + Display::Contents | + Display::FlowRoot | + Display::Grid | + Display::WebkitBox => *self, + + // Everything else becomes block. + _ => Display::Block, + } + + } + + /// Convert this display into an inline-outside display. + /// + /// Ideally it should implement spec: https://drafts.csswg.org/css-display/#inlinify + /// but the spec isn't stable enough, so we copy what Gecko does for now. + #[cfg(feature = "gecko")] + pub fn inlinify(&self) -> Self { + match *self { + Display::Block | + Display::FlowRoot => Display::InlineBlock, + Display::Table => Display::InlineTable, + Display::Flex => Display::InlineFlex, + Display::Grid => Display::InlineGrid, + Display::MozBox => Display::MozInlineBox, + Display::MozStack => Display::MozInlineStack, + Display::WebkitBox => Display::WebkitInlineBox, + other => other, + } + } + + #[cfg(feature = "servo")] + #[inline] + /// Custom cascade for the `display` property in servo + pub fn cascade_property_custom( + _declaration: &PropertyDeclaration, + context: &mut Context + ) { + longhands::_servo_display_for_hypothetical_box::derive_from_display(context); + longhands::_servo_text_decorations_in_effect::derive_from_display(context); + } +} + /// A specified value for the `vertical-align` property. pub type VerticalAlign = GenericVerticalAlign; diff --git a/servo/components/style/values/specified/mod.rs b/servo/components/style/values/specified/mod.rs index b19301166b5b..a750dcab4861 100644 --- a/servo/components/style/values/specified/mod.rs +++ b/servo/components/style/values/specified/mod.rs @@ -34,7 +34,7 @@ pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, FontVa pub use self::font::{FontFamily, FontLanguageOverride, FontVariantSettings, FontVariantEastAsian}; pub use self::font::{FontVariantLigatures, FontVariantNumeric, FontFeatureSettings}; pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier, XTextZoom, XLang}; -pub use self::box_::{AnimationIterationCount, AnimationName, OverscrollBehavior}; +pub use self::box_::{AnimationIterationCount, AnimationName, Display, OverscrollBehavior}; pub use self::box_::{OverflowClipBox, ScrollSnapType, TouchAction, VerticalAlign, WillChange}; pub use self::color::{Color, ColorPropertyValue, RGBAColor}; pub use self::effects::{BoxShadow, Filter, SimpleShadow};