aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/layout/construct.rs17
-rw-r--r--components/layout/generated_content.rs5
-rw-r--r--components/style/font_face.rs10
-rw-r--r--components/style/gecko/media_queries.rs17
-rw-r--r--components/style/gecko/pseudo_element.rs4
-rw-r--r--components/style/gecko/pseudo_element_definition.mako.rs6
-rw-r--r--components/style/gecko/selector_parser.rs10
-rw-r--r--components/style/lib.rs2
-rw-r--r--components/style/media_queries/media_feature_expression.rs6
-rw-r--r--components/style/properties/cascade.rs4
-rw-r--r--components/style/properties/data.py3
-rw-r--r--components/style/properties/gecko.mako.rs309
-rw-r--r--components/style/properties/longhands/border.mako.rs1
-rw-r--r--components/style/properties/longhands/box.mako.rs18
-rw-r--r--components/style/properties/longhands/inherited_text.mako.rs6
-rw-r--r--components/style/properties/longhands/margin.mako.rs1
-rw-r--r--components/style/properties/longhands/padding.mako.rs1
-rw-r--r--components/style/properties/longhands/position.mako.rs10
-rw-r--r--components/style/properties/longhands/text.mako.rs5
-rw-r--r--components/style/properties/longhands/ui.mako.rs2
-rw-r--r--components/style/properties/properties.mako.rs5
-rw-r--r--components/style/properties/shorthands/position.mako.rs75
-rw-r--r--components/style/properties/shorthands/text.mako.rs21
-rw-r--r--components/style/style_adjuster.rs14
-rw-r--r--components/style/stylesheets/document_rule.rs8
-rw-r--r--components/style/stylesheets/supports_rule.rs4
-rw-r--r--components/style/values/animated/grid.rs20
-rw-r--r--components/style/values/computed/mod.rs9
-rw-r--r--components/style/values/computed/position.rs4
-rw-r--r--components/style/values/computed/text.rs32
-rw-r--r--components/style/values/generics/easing.rs3
-rw-r--r--components/style/values/generics/font.rs4
-rw-r--r--components/style/values/generics/grid.rs257
-rw-r--r--components/style/values/generics/position.rs37
-rw-r--r--components/style/values/generics/text.rs35
-rw-r--r--components/style/values/resolved/mod.rs1
-rw-r--r--components/style/values/specified/basic_shape.rs4
-rw-r--r--components/style/values/specified/box.rs659
-rw-r--r--components/style/values/specified/grid.rs197
-rw-r--r--components/style/values/specified/mod.rs8
-rw-r--r--components/style/values/specified/position.rs4
-rw-r--r--components/style/values/specified/svg.rs3
-rw-r--r--components/style/values/specified/svg_path.rs56
-rw-r--r--components/style/values/specified/text.rs191
-rw-r--r--components/style/values/specified/ui.rs12
-rw-r--r--components/style_traits/specified_value_info.rs1
-rw-r--r--servo-tidy.toml1
-rw-r--r--tests/wpt/metadata/css/css-fonts/font-weight-xxx-large.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-fonts/parsing/font-size-valid.html.ini4
-rw-r--r--tests/wpt/metadata/html/rendering/widgets/button-layout/display-other.html.ini3
50 files changed, 1035 insertions, 1076 deletions
diff --git a/components/layout/construct.rs b/components/layout/construct.rs
index 072413995b2..856f8dbc52e 100644
--- a/components/layout/construct.rs
+++ b/components/layout/construct.rs
@@ -1847,6 +1847,10 @@ where
node.type_id()
);
+ // FIXME(emilio): This should look at display-outside and
+ // display-inside, but there's so much stuff that goes through the
+ // generic "block" codepath (wrongly).
+ //
// Switch on display and floatedness.
match (display, float, positioning) {
// `display: none` contributes no flow construction result.
@@ -1871,12 +1875,6 @@ where
self.set_flow_construction_result(node, construction_result)
},
- // List items contribute their own special flows.
- (Display::ListItem, float_value, _) => {
- let construction_result = self.build_flow_for_list_item(node, float_value);
- self.set_flow_construction_result(node, construction_result)
- },
-
// Inline items that are absolutely-positioned contribute inline fragment construction
// results with a hypothetical fragment.
(Display::Inline, _, Position::Absolute) |
@@ -1958,7 +1956,12 @@ where
// properties separately.
(_, float_value, _) => {
let float_kind = FloatKind::from_property(float_value);
- let construction_result = self.build_flow_for_block(node, float_kind);
+ // List items contribute their own special flows.
+ let construction_result = if display.is_list_item() {
+ self.build_flow_for_list_item(node, float_value)
+ } else {
+ self.build_flow_for_block(node, float_kind)
+ };
self.set_flow_construction_result(node, construction_result)
},
}
diff --git a/components/layout/generated_content.rs b/components/layout/generated_content.rs
index 683bb316897..d69ddd65991 100644
--- a/components/layout/generated_content.rs
+++ b/components/layout/generated_content.rs
@@ -19,7 +19,6 @@ use crate::traversal::InorderFlowTraversal;
use script_layout_interface::wrapper_traits::PseudoElementType;
use smallvec::SmallVec;
use std::collections::{HashMap, LinkedList};
-use style::computed_values::display::T as Display;
use style::computed_values::list_style_type::T as ListStyleType;
use style::properties::ComputedValues;
use style::selector_parser::RestyleDamage;
@@ -175,7 +174,7 @@ impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> {
}
let mut list_style_type = fragment.style().get_list().list_style_type;
- if fragment.style().get_box().display != Display::ListItem {
+ if !fragment.style().get_box().display.is_list_item() {
list_style_type = ListStyleType::None
}
@@ -291,7 +290,7 @@ impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> {
fn reset_and_increment_counters_as_necessary(&mut self, fragment: &mut Fragment) {
let mut list_style_type = fragment.style().get_list().list_style_type;
- if !self.is_block || fragment.style().get_box().display != Display::ListItem {
+ if !self.is_block || !fragment.style().get_box().display.is_list_item() {
list_style_type = ListStyleType::None
}
diff --git a/components/style/font_face.rs b/components/style/font_face.rs
index 50814c5f5e8..d45cd340c85 100644
--- a/components/style/font_face.rs
+++ b/components/style/font_face.rs
@@ -414,16 +414,10 @@ impl Parse for Source {
macro_rules! is_descriptor_enabled {
("font-display") => {
- unsafe {
- use crate::gecko_bindings::structs::mozilla;
- mozilla::StaticPrefs::sVarCache_layout_css_font_display_enabled
- }
+ static_prefs::pref!("layout.css.font-display.enabled")
};
("font-variation-settings") => {
- unsafe {
- use crate::gecko_bindings::structs::mozilla;
- mozilla::StaticPrefs::sVarCache_layout_css_font_variations_enabled != 0
- }
+ static_prefs::pref!("layout.css.font-variations.enabled")
};
($name:tt) => {
true
diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs
index 556470569db..bb126e16948 100644
--- a/components/style/gecko/media_queries.rs
+++ b/components/style/gecko/media_queries.rs
@@ -213,12 +213,11 @@ impl Device {
None => return MediaType::screen(),
};
- // Gecko allows emulating random media with mIsEmulatingMedia and
- // mMediaEmulated.
- let medium_to_use = if pc.mIsEmulatingMedia() != 0 {
- pc.mMediaEmulated.mRawPtr
+ // Gecko allows emulating random media with mMediaEmulationData.mMedium.
+ let medium_to_use = if !pc.mMediaEmulationData.mMedium.mRawPtr.is_null() {
+ pc.mMediaEmulationData.mMedium.mRawPtr
} else {
- pc.mMedium
+ pc.mMedium as *const structs::nsAtom as *mut _
};
MediaType(CustomIdent(unsafe { Atom::from_raw(medium_to_use) }))
@@ -253,9 +252,8 @@ impl Device {
None => return Scale::new(1.),
};
- let override_dppx = pc.mOverrideDPPX;
- if override_dppx > 0.0 {
- return Scale::new(override_dppx);
+ if pc.mMediaEmulationData.mDPPX > 0.0 {
+ return Scale::new(pc.mMediaEmulationData.mDPPX);
}
let au_per_dpx = pc.mCurAppUnitsPerDevPixel as f32;
@@ -270,8 +268,7 @@ impl Device {
if doc.mIsBeingUsedAsImage() {
return true;
}
- let document_color_use =
- unsafe { structs::StaticPrefs::sVarCache_browser_display_document_color_use };
+ let document_color_use = static_prefs::pref!("browser.display.document_color_use");
let prefs = self.pref_sheet_prefs();
match document_color_use {
1 => true,
diff --git a/components/style/gecko/pseudo_element.rs b/components/style/gecko/pseudo_element.rs
index 501611830ff..aa849ceee02 100644
--- a/components/style/gecko/pseudo_element.rs
+++ b/components/style/gecko/pseudo_element.rs
@@ -187,9 +187,7 @@ impl PseudoElement {
PseudoElement::FirstLine => PropertyFlags::APPLIES_TO_FIRST_LINE,
PseudoElement::Placeholder => PropertyFlags::APPLIES_TO_PLACEHOLDER,
PseudoElement::Cue => PropertyFlags::APPLIES_TO_CUE,
- PseudoElement::Marker
- if unsafe { structs::StaticPrefs::sVarCache_layout_css_marker_restricted } =>
- {
+ PseudoElement::Marker if static_prefs::pref!("layout.css.marker.restricted") => {
PropertyFlags::APPLIES_TO_MARKER
},
_ => return None,
diff --git a/components/style/gecko/pseudo_element_definition.mako.rs b/components/style/gecko/pseudo_element_definition.mako.rs
index 562b4c18444..d8d80d60165 100644
--- a/components/style/gecko/pseudo_element_definition.mako.rs
+++ b/components/style/gecko/pseudo_element_definition.mako.rs
@@ -112,7 +112,7 @@ impl PseudoElement {
% for pseudo in PSEUDOS:
${pseudo_element_variant(pseudo)} =>
% if pseudo.is_tree_pseudo_element():
- if unsafe { structs::StaticPrefs::sVarCache_layout_css_xul_tree_pseudos_content_enabled } {
+ if static_prefs::pref!("layout.css.xul-tree-pseudos.content.enabled") {
0
} else {
structs::CSS_PSEUDO_ELEMENT_ENABLED_IN_UA_SHEETS_AND_CHROME
@@ -209,9 +209,7 @@ impl PseudoElement {
if starts_with_ignore_ascii_case(name, "-moz-tree-") {
return PseudoElement::tree_pseudo_element(name, Box::new([]))
}
- if unsafe {
- structs::StaticPrefs::sVarCache_layout_css_unknown_webkit_pseudo_element
- } {
+ if static_prefs::pref!("layout.css.unknown-webkit-pseudo-element") {
const WEBKIT_PREFIX: &str = "-webkit-";
if starts_with_ignore_ascii_case(name, WEBKIT_PREFIX) {
let part = string_as_ascii_lowercase(&name[WEBKIT_PREFIX.len()..]);
diff --git a/components/style/gecko/selector_parser.rs b/components/style/gecko/selector_parser.rs
index 1da352249d4..2aad41adc9c 100644
--- a/components/style/gecko/selector_parser.rs
+++ b/components/style/gecko/selector_parser.rs
@@ -5,7 +5,7 @@
//! Gecko-specific bits for selector-parsing.
use crate::element_state::{DocumentState, ElementState};
-use crate::gecko_bindings::structs::{self, RawServoSelectorList};
+use crate::gecko_bindings::structs::RawServoSelectorList;
use crate::gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
use crate::invalidation::element::document_state::InvalidationMatchingData;
use crate::selector_parser::{Direction, SelectorParser};
@@ -170,13 +170,10 @@ impl NonTSPseudoClass {
/// Returns whether the pseudo-class is enabled in content sheets.
fn is_enabled_in_content(&self) -> bool {
- use crate::gecko_bindings::structs::mozilla;
match *self {
// For pseudo-classes with pref, the availability in content
// depends on the pref.
- NonTSPseudoClass::Fullscreen => unsafe {
- mozilla::StaticPrefs::sVarCache_full_screen_api_unprefix_enabled
- },
+ NonTSPseudoClass::Fullscreen => static_prefs::pref!("full-screen-api.unprefix.enabled"),
// Otherwise, a pseudo-class is enabled in content when it
// doesn't have any enabled flag.
_ => !self
@@ -354,8 +351,7 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
#[inline]
fn parse_part(&self) -> bool {
- self.chrome_rules_enabled() ||
- unsafe { structs::StaticPrefs::sVarCache_layout_css_shadow_parts_enabled }
+ self.chrome_rules_enabled() || static_prefs::pref!("layout.css.shadow-parts.enabled")
}
fn parse_non_ts_pseudo_class(
diff --git a/components/style/lib.rs b/components/style/lib.rs
index 587b926efc6..35070b0f254 100644
--- a/components/style/lib.rs
+++ b/components/style/lib.rs
@@ -91,6 +91,8 @@ extern crate servo_config;
extern crate servo_url;
extern crate smallbitvec;
extern crate smallvec;
+#[cfg(feature = "gecko")]
+extern crate static_prefs;
#[cfg(feature = "servo")]
extern crate string_cache;
#[macro_use]
diff --git a/components/style/media_queries/media_feature_expression.rs b/components/style/media_queries/media_feature_expression.rs
index 310cbd2b8bb..98c7d59c7e1 100644
--- a/components/style/media_queries/media_feature_expression.rs
+++ b/components/style/media_queries/media_feature_expression.rs
@@ -11,8 +11,6 @@ use super::Device;
use crate::context::QuirksMode;
#[cfg(feature = "gecko")]
use crate::gecko::media_features::MEDIA_FEATURES;
-#[cfg(feature = "gecko")]
-use crate::gecko_bindings::structs;
use crate::parser::{Parse, ParserContext};
#[cfg(feature = "servo")]
use crate::servo::media_queries::MEDIA_FEATURES;
@@ -301,9 +299,7 @@ impl MediaFeatureExpression {
if starts_with_ignore_ascii_case(feature_name, "-webkit-") {
feature_name = &feature_name[8..];
requirements.insert(ParsingRequirements::WEBKIT_PREFIX);
- if unsafe {
- structs::StaticPrefs::sVarCache_layout_css_prefixes_device_pixel_ratio_webkit
- } {
+ if static_prefs::pref!("layout.css.prefixes.device-pixel-ratio-webkit") {
requirements.insert(
ParsingRequirements::WEBKIT_DEVICE_PIXEL_RATIO_PREF_ENABLED,
);
diff --git a/components/style/properties/cascade.rs b/components/style/properties/cascade.rs
index c3ce242eadd..da95840a08a 100644
--- a/components/style/properties/cascade.rs
+++ b/components/style/properties/cascade.rs
@@ -673,7 +673,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
#[inline]
#[cfg(feature = "gecko")]
fn recompute_default_font_family_type_if_needed(&mut self) {
- use crate::gecko_bindings::{bindings, structs};
+ use crate::gecko_bindings::bindings;
use crate::values::computed::font::GenericFontFamily;
if !self.seen.contains(LonghandId::XLang) &&
@@ -681,7 +681,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
return;
}
- let use_document_fonts = unsafe { structs::StaticPrefs::sVarCache_browser_display_use_document_fonts != 0 };
+ let use_document_fonts = static_prefs::pref!("browser.display.use_document_fonts") != 0;
let builder = &mut self.context.builder;
let (default_font_type, prioritize_user_fonts) = {
let font = builder.get_font().gecko();
diff --git a/components/style/properties/data.py b/components/style/properties/data.py
index 46cb724e11d..d1e78e6648c 100644
--- a/components/style/properties/data.py
+++ b/components/style/properties/data.py
@@ -652,9 +652,6 @@ def _remove_common_first_line_and_first_letter_properties(props, engine):
props.remove("text-emphasis-position")
props.remove("text-emphasis-style")
props.remove("text-emphasis-color")
- props.remove("text-decoration-skip-ink")
- props.remove("text-decoration-thickness")
- props.remove("text-underline-offset")
props.remove("overflow-wrap")
props.remove("text-align")
diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs
index f00e5aafced..1f3e862df49 100644
--- a/components/style/properties/gecko.mako.rs
+++ b/components/style/properties/gecko.mako.rs
@@ -973,11 +973,10 @@ fn static_assert() {
<% skip_position_longhands = " ".join(x.ident for x in SIDES) %>
<%self:impl_trait style_struct_name="Position"
- skip_longhands="${skip_position_longhands} order
+ skip_longhands="${skip_position_longhands}
align-content justify-content align-self
justify-self align-items justify-items
- grid-auto-flow grid-template-rows
- grid-template-columns">
+ grid-auto-flow">
% for side in SIDES:
<% impl_split_style_coord(side.ident, "mOffset", side.index) %>
% endfor
@@ -1015,226 +1014,6 @@ fn static_assert() {
}
}
- pub fn set_order(&mut self, v: longhands::order::computed_value::T) {
- self.gecko.mOrder = v;
- }
-
- pub fn clone_order(&self) -> longhands::order::computed_value::T {
- self.gecko.mOrder
- }
-
- ${impl_simple_copy('order', 'mOrder')}
-
- % for kind in ["rows", "columns"]:
- pub fn set_grid_template_${kind}(&mut self, v: longhands::grid_template_${kind}::computed_value::T) {
- <% self_grid = "self.gecko.mGridTemplate%s" % kind.title() %>
- use crate::gecko_bindings::structs::nsTArray;
- use std::usize;
- use crate::values::CustomIdent;
- use crate::values::generics::grid::TrackListType::Auto;
- use crate::values::generics::grid::{GridTemplateComponent, RepeatCount, TrackListValue, MAX_GRID_LINE};
-
- #[inline]
- fn set_line_names(servo_names: &[CustomIdent], gecko_names: &mut nsTArray<structs::RefPtr<structs::nsAtom>>) {
- unsafe {
- bindings::Gecko_ResizeAtomArray(gecko_names, servo_names.len() as u32);
- }
-
- for (servo_name, gecko_name) in servo_names.iter().zip(gecko_names.iter_mut()) {
- gecko_name.set_move(unsafe {
- RefPtr::from_addrefed(servo_name.0.clone().into_addrefed())
- });
- }
- }
-
- let max_lines = MAX_GRID_LINE as usize - 1; // for accounting the final <line-names>
-
- let result = match v {
- GridTemplateComponent::None => ptr::null_mut(),
- GridTemplateComponent::TrackList(track) => {
- let mut num_values = track.values.len();
- if let Auto(_) = track.list_type {
- num_values += 1;
- }
-
- num_values = cmp::min(num_values, max_lines);
- let value = unsafe {
- bindings::Gecko_CreateStyleGridTemplate(num_values as u32,
- (num_values + 1) as u32).as_mut().unwrap()
- };
-
- let mut auto_idx = usize::MAX;
- let mut auto_track_size = None;
- if let Auto(idx) = track.list_type {
- auto_idx = idx as usize;
- let auto_repeat = track.auto_repeat.as_ref().expect("expected <auto-track-repeat> value");
-
- if auto_repeat.count == RepeatCount::AutoFill {
- value.set_mIsAutoFill(true);
- }
-
- value.mRepeatAutoIndex = idx as i16;
- // NOTE: Gecko supports only one set of values in <auto-repeat>
- // i.e., it can only take repeat(auto-fill, [a] 10px [b]), and no more.
- set_line_names(&auto_repeat.line_names[0], &mut value.mRepeatAutoLineNameListBefore);
- set_line_names(&auto_repeat.line_names[1], &mut value.mRepeatAutoLineNameListAfter);
- auto_track_size = Some(auto_repeat.track_sizes.get(0).unwrap().clone());
- } else {
- unsafe {
- bindings::Gecko_ResizeAtomArray(
- &mut value.mRepeatAutoLineNameListBefore, 0);
- bindings::Gecko_ResizeAtomArray(
- &mut value.mRepeatAutoLineNameListAfter, 0);
- }
- }
-
- let mut line_names = track.line_names.into_iter();
- let mut values_iter = track.values.into_iter();
- {
- for (i, track_size) in value.mTrackSizingFunctions.iter_mut().enumerate().take(max_lines) {
- let name_list = line_names.next().expect("expected line-names");
- set_line_names(&name_list, &mut value.mLineNameLists[i]);
- *track_size = if i == auto_idx {
- auto_track_size.take().expect("expected <track-size> for <auto-track-repeat>")
- } else {
- match values_iter.next().expect("expected <track-size> value") {
- TrackListValue::TrackSize(size) => size,
- // FIXME(emilio): This shouldn't be
- // representable in the first place.
- TrackListValue::TrackRepeat(..) => {
- unreachable!("Shouldn't have track-repeats in computed track lists")
- }
- }
- };
- }
- }
-
- let final_names = line_names.next().unwrap();
- set_line_names(&final_names, value.mLineNameLists.last_mut().unwrap());
-
- value
- },
- GridTemplateComponent::Subgrid(list) => {
- let names_length = match list.fill_idx {
- Some(_) => list.names.len() - 1,
- None => list.names.len(),
- };
- let num_values = cmp::min(names_length, max_lines + 1);
- let value = unsafe {
- bindings::Gecko_CreateStyleGridTemplate(0, num_values as u32).as_mut().unwrap()
- };
- value.set_mIsSubgrid(true);
-
- let mut names = list.names.into_vec();
- if let Some(idx) = list.fill_idx {
- value.set_mIsAutoFill(true);
- value.mRepeatAutoIndex = idx as i16;
- set_line_names(&names.swap_remove(idx as usize),
- &mut value.mRepeatAutoLineNameListBefore);
- }
-
- for (servo_names, gecko_names) in names.iter().zip(value.mLineNameLists.iter_mut()) {
- set_line_names(servo_names, gecko_names);
- }
-
- value
- },
- };
-
- unsafe { bindings::Gecko_SetStyleGridTemplate(&mut ${self_grid}, result); }
- }
-
- pub fn copy_grid_template_${kind}_from(&mut self, other: &Self) {
- unsafe {
- bindings::Gecko_CopyStyleGridTemplateValues(&mut ${self_grid},
- other.gecko.mGridTemplate${kind.title()}.mPtr);
- }
- }
-
- pub fn reset_grid_template_${kind}(&mut self, other: &Self) {
- self.copy_grid_template_${kind}_from(other)
- }
-
- pub fn clone_grid_template_${kind}(&self) -> longhands::grid_template_${kind}::computed_value::T {
- <% self_grid = "self.gecko.mGridTemplate%s" % kind.title() %>
- use crate::gecko_bindings::structs::nsTArray;
- use crate::values::CustomIdent;
- use crate::values::generics::grid::{GridTemplateComponent, LineNameList, RepeatCount};
- use crate::values::generics::grid::{TrackList, TrackListType, TrackListValue, TrackRepeat};
-
- let value = match unsafe { ${self_grid}.mPtr.as_ref() } {
- None => return GridTemplateComponent::None,
- Some(value) => value,
- };
-
- #[inline]
- fn to_boxed_customident_slice(gecko_names: &nsTArray<structs::RefPtr<structs::nsAtom>>) -> Box<[CustomIdent]> {
- let idents: Vec<CustomIdent> = gecko_names.iter().map(|gecko_name| {
- CustomIdent(unsafe { Atom::from_raw(gecko_name.mRawPtr) })
- }).collect();
- idents.into_boxed_slice()
- }
-
- #[inline]
- fn to_line_names_vec(
- gecko_line_names: &nsTArray<nsTArray<structs::RefPtr<structs::nsAtom>>>,
- ) -> Vec<Box<[CustomIdent]>> {
- gecko_line_names.iter().map(|gecko_names| {
- to_boxed_customident_slice(gecko_names)
- }).collect()
- }
-
- let repeat_auto_index = value.mRepeatAutoIndex as usize;
- if value.mIsSubgrid() {
- let mut names_vec = to_line_names_vec(&value.mLineNameLists);
- let fill_idx = if value.mIsAutoFill() {
- names_vec.insert(
- repeat_auto_index,
- to_boxed_customident_slice(&value.mRepeatAutoLineNameListBefore));
- Some(repeat_auto_index as u32)
- } else {
- None
- };
- let names = names_vec.into_boxed_slice();
-
- GridTemplateComponent::Subgrid(LineNameList{names, fill_idx})
- } else {
- let mut auto_repeat = None;
- let mut list_type = TrackListType::Normal;
- let line_names = to_line_names_vec(&value.mLineNameLists).into_boxed_slice();
- let mut values = Vec::with_capacity(value.mTrackSizingFunctions.len());
- for (i, track_size) in value.mTrackSizingFunctions.iter().enumerate() {
- if i == repeat_auto_index {
- list_type = TrackListType::Auto(repeat_auto_index as u16);
-
- let count = if value.mIsAutoFill() {
- RepeatCount::AutoFill
- } else {
- RepeatCount::AutoFit
- };
-
- let line_names = {
- let mut vec: Vec<Box<[CustomIdent]>> = Vec::with_capacity(2);
- vec.push(to_boxed_customident_slice(
- &value.mRepeatAutoLineNameListBefore));
- vec.push(to_boxed_customident_slice(
- &value.mRepeatAutoLineNameListAfter));
- vec.into_boxed_slice()
- };
-
- let track_sizes = vec!(track_size.clone());
-
- auto_repeat = Some(TrackRepeat{count, line_names, track_sizes});
- } else {
- values.push(TrackListValue::TrackSize(track_size.clone()));
- }
- }
-
- GridTemplateComponent::TrackList(TrackList{list_type, values, line_names, auto_repeat})
- }
- }
- % endfor
-
${impl_simple_type_with_conversion("grid_auto_flow")}
</%self:impl_trait>
@@ -2799,97 +2578,15 @@ fn static_assert() {
<%self:impl_trait style_struct_name="InheritedText"
- skip_longhands="text-align text-emphasis-style
- -webkit-text-stroke-width text-emphasis-position">
+ skip_longhands="text-align -webkit-text-stroke-width text-emphasis-position">
<% text_align_keyword = Keyword("text-align",
"start end left right center justify -moz-center -moz-left -moz-right char",
gecko_strip_moz_prefix=False) %>
${impl_keyword('text_align', 'mTextAlign', text_align_keyword)}
- fn clear_text_emphasis_style_if_string(&mut self) {
- if self.gecko.mTextEmphasisStyle == structs::NS_STYLE_TEXT_EMPHASIS_STYLE_STRING as u8 {
- self.gecko.mTextEmphasisStyleString.truncate();
- self.gecko.mTextEmphasisStyle = structs::NS_STYLE_TEXT_EMPHASIS_STYLE_NONE as u8;
- }
- }
-
${impl_simple_type_with_conversion("text_emphasis_position")}
- pub fn set_text_emphasis_style(&mut self, v: values::computed::TextEmphasisStyle) {
- use crate::values::computed::TextEmphasisStyle;
- use crate::values::specified::text::{TextEmphasisFillMode, TextEmphasisShapeKeyword};
-
- self.clear_text_emphasis_style_if_string();
- let (te, s) = match v {
- TextEmphasisStyle::None => (structs::NS_STYLE_TEXT_EMPHASIS_STYLE_NONE, ""),
- TextEmphasisStyle::Keyword(ref keyword) => {
- let fill = match keyword.fill {
- TextEmphasisFillMode::Filled => structs::NS_STYLE_TEXT_EMPHASIS_STYLE_FILLED,
- TextEmphasisFillMode::Open => structs::NS_STYLE_TEXT_EMPHASIS_STYLE_OPEN,
- };
- let shape = match keyword.shape {
- TextEmphasisShapeKeyword::Dot => structs::NS_STYLE_TEXT_EMPHASIS_STYLE_DOT,
- TextEmphasisShapeKeyword::Circle => structs::NS_STYLE_TEXT_EMPHASIS_STYLE_CIRCLE,
- TextEmphasisShapeKeyword::DoubleCircle => structs::NS_STYLE_TEXT_EMPHASIS_STYLE_DOUBLE_CIRCLE,
- TextEmphasisShapeKeyword::Triangle => structs::NS_STYLE_TEXT_EMPHASIS_STYLE_TRIANGLE,
- TextEmphasisShapeKeyword::Sesame => structs::NS_STYLE_TEXT_EMPHASIS_STYLE_SESAME,
- };
-
- (shape | fill, keyword.shape.char(keyword.fill))
- },
- TextEmphasisStyle::String(ref s) => {
- (structs::NS_STYLE_TEXT_EMPHASIS_STYLE_STRING, &**s)
- },
- };
- self.gecko.mTextEmphasisStyleString.assign_str(s);
- self.gecko.mTextEmphasisStyle = te as u8;
- }
-
- pub fn copy_text_emphasis_style_from(&mut self, other: &Self) {
- self.clear_text_emphasis_style_if_string();
- if other.gecko.mTextEmphasisStyle == structs::NS_STYLE_TEXT_EMPHASIS_STYLE_STRING as u8 {
- self.gecko.mTextEmphasisStyleString
- .assign(&*other.gecko.mTextEmphasisStyleString)
- }
- self.gecko.mTextEmphasisStyle = other.gecko.mTextEmphasisStyle;
- }
-
- pub fn reset_text_emphasis_style(&mut self, other: &Self) {
- self.copy_text_emphasis_style_from(other)
- }
-
- pub fn clone_text_emphasis_style(&self) -> values::computed::TextEmphasisStyle {
- use crate::values::computed::TextEmphasisStyle;
- use crate::values::computed::text::TextEmphasisKeywordValue;
- use crate::values::specified::text::{TextEmphasisFillMode, TextEmphasisShapeKeyword};
-
- if self.gecko.mTextEmphasisStyle == structs::NS_STYLE_TEXT_EMPHASIS_STYLE_NONE as u8 {
- return TextEmphasisStyle::None;
- }
-
- if self.gecko.mTextEmphasisStyle == structs::NS_STYLE_TEXT_EMPHASIS_STYLE_STRING as u8 {
- return TextEmphasisStyle::String(self.gecko.mTextEmphasisStyleString.to_string());
- }
-
- let fill =
- self.gecko.mTextEmphasisStyle & structs::NS_STYLE_TEXT_EMPHASIS_STYLE_OPEN as u8 == 0;
-
- let fill = if fill { TextEmphasisFillMode::Filled } else { TextEmphasisFillMode::Open };
-
- let shape =
- match self.gecko.mTextEmphasisStyle as u32 & !structs::NS_STYLE_TEXT_EMPHASIS_STYLE_OPEN {
- structs::NS_STYLE_TEXT_EMPHASIS_STYLE_DOT => TextEmphasisShapeKeyword::Dot,
- structs::NS_STYLE_TEXT_EMPHASIS_STYLE_CIRCLE => TextEmphasisShapeKeyword::Circle,
- structs::NS_STYLE_TEXT_EMPHASIS_STYLE_DOUBLE_CIRCLE => TextEmphasisShapeKeyword::DoubleCircle,
- structs::NS_STYLE_TEXT_EMPHASIS_STYLE_TRIANGLE => TextEmphasisShapeKeyword::Triangle,
- structs::NS_STYLE_TEXT_EMPHASIS_STYLE_SESAME => TextEmphasisShapeKeyword::Sesame,
- _ => panic!("Unexpected value in style struct for text-emphasis-style property")
- };
-
- TextEmphasisStyle::Keyword(TextEmphasisKeywordValue { fill, shape })
- }
-
${impl_non_negative_length('_webkit_text_stroke_width',
'mWebkitTextStrokeWidth')}
diff --git a/components/style/properties/longhands/border.mako.rs b/components/style/properties/longhands/border.mako.rs
index 6ac01034bed..4098a94208f 100644
--- a/components/style/properties/longhands/border.mako.rs
+++ b/components/style/properties/longhands/border.mako.rs
@@ -58,7 +58,6 @@
animation_value_type="NonNegativeLength",
logical=is_logical,
logical_group="border-width",
- flags="GETCS_NEEDS_LAYOUT_FLUSH",
allow_quirks="No" if is_logical else "Yes",
servo_restyle_damage="reflow rebuild_and_reflow_inline"
)}
diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs
index 40075a65084..4dcc43aec23 100644
--- a/components/style/properties/longhands/box.mako.rs
+++ b/components/style/properties/longhands/box.mako.rs
@@ -339,8 +339,7 @@ ${helpers.predefined_type(
servo_2020_pref="layout.2020.unimplemented",
extra_prefixes=transform_extra_prefixes,
animation_value_type="ComputedValue",
- flags="CREATES_STACKING_CONTEXT FIXPOS_CB \
- GETCS_NEEDS_LAYOUT_FLUSH CAN_ANIMATE_ON_COMPOSITOR",
+ flags="CREATES_STACKING_CONTEXT FIXPOS_CB CAN_ANIMATE_ON_COMPOSITOR",
spec="https://drafts.csswg.org/css-transforms/#propdef-transform",
servo_restyle_damage="reflow_out_of_flow",
)}
@@ -421,6 +420,19 @@ ${helpers.predefined_type(
servo_restyle_damage="reflow_out_of_flow"
)}
+// Motion Path Module Level 1
+${helpers.predefined_type(
+ "offset-anchor",
+ "PositionOrAuto",
+ "computed::PositionOrAuto::auto()",
+ engines="gecko",
+ animation_value_type="ComputedValue",
+ gecko_pref="layout.css.motion-path.enabled",
+ spec="https://drafts.fxtf.org/motion-1/#offset-anchor-property",
+ servo_restyle_damage="reflow_out_of_flow",
+ boxed=True
+)}
+
// CSSOM View Module
// https://www.w3.org/TR/cssom-view-1/
${helpers.single_keyword(
@@ -539,7 +551,6 @@ ${helpers.predefined_type(
boxed=True,
extra_prefixes=transform_extra_prefixes,
spec="https://drafts.csswg.org/css-transforms-2/#perspective-origin-property",
- flags="GETCS_NEEDS_LAYOUT_FLUSH",
animation_value_type="ComputedValue",
servo_restyle_damage="reflow_out_of_flow"
)}
@@ -587,7 +598,6 @@ ${helpers.predefined_type(
extra_prefixes=transform_extra_prefixes,
gecko_ffi_name="mTransformOrigin",
boxed=True,
- flags="GETCS_NEEDS_LAYOUT_FLUSH",
spec="https://drafts.csswg.org/css-transforms/#transform-origin-property",
servo_restyle_damage="reflow_out_of_flow",
)}
diff --git a/components/style/properties/longhands/inherited_text.mako.rs b/components/style/properties/longhands/inherited_text.mako.rs
index f45369c27c7..18f5c466d1a 100644
--- a/components/style/properties/longhands/inherited_text.mako.rs
+++ b/components/style/properties/longhands/inherited_text.mako.rs
@@ -23,7 +23,6 @@ ${helpers.predefined_type(
engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
animation_value_type="LineHeight",
- flags="GETCS_NEEDS_LAYOUT_FLUSH",
spec="https://drafts.csswg.org/css2/visudet.html#propdef-line-height",
servo_restyle_damage="reflow"
)}
@@ -250,7 +249,6 @@ ${helpers.predefined_type(
None,
engines="gecko",
initial_specified_value="SpecifiedValue::None",
- boxed=True,
animation_value_type="discrete",
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-emphasis-style",
)}
@@ -384,8 +382,8 @@ ${helpers.single_keyword(
// text underline offset
${helpers.predefined_type(
"text-underline-offset",
- "LengthOrAuto",
- "computed::LengthOrAuto::auto()",
+ "TextDecorationLength",
+ "generics::text::GenericTextDecorationLength::Auto",
engines="gecko",
animation_value_type="ComputedValue",
gecko_pref="layout.css.text-underline-offset.enabled",
diff --git a/components/style/properties/longhands/margin.mako.rs b/components/style/properties/longhands/margin.mako.rs
index 820634be995..9ec1e97504c 100644
--- a/components/style/properties/longhands/margin.mako.rs
+++ b/components/style/properties/longhands/margin.mako.rs
@@ -24,7 +24,6 @@
logical=side[1],
logical_group="margin",
spec=spec,
- flags="GETCS_NEEDS_LAYOUT_FLUSH",
allowed_in_page_rule=True,
servo_restyle_damage="reflow"
)}
diff --git a/components/style/properties/longhands/padding.mako.rs b/components/style/properties/longhands/padding.mako.rs
index faa3fb2867c..a91f1238979 100644
--- a/components/style/properties/longhands/padding.mako.rs
+++ b/components/style/properties/longhands/padding.mako.rs
@@ -23,7 +23,6 @@
logical=side[1],
logical_group="padding",
spec=spec,
- flags="GETCS_NEEDS_LAYOUT_FLUSH",
allow_quirks="No" if side[1] else "Yes",
servo_restyle_damage="reflow rebuild_and_reflow_inline"
)}
diff --git a/components/style/properties/longhands/position.mako.rs b/components/style/properties/longhands/position.mako.rs
index 9e67dfb2d80..a63f7637db4 100644
--- a/components/style/properties/longhands/position.mako.rs
+++ b/components/style/properties/longhands/position.mako.rs
@@ -17,7 +17,6 @@
engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
spec="https://www.w3.org/TR/CSS2/visuren.html#propdef-%s" % side,
- flags="GETCS_NEEDS_LAYOUT_FLUSH",
animation_value_type="ComputedValue",
allow_quirks="Yes",
servo_restyle_damage="reflow_out_of_flow",
@@ -33,7 +32,6 @@
engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
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,
animation_value_type="ComputedValue",
logical=True,
@@ -285,7 +283,6 @@ ${helpers.predefined_type(
allow_quirks="No" if logical else "Yes",
spec=spec % size,
animation_value_type="Size",
- flags="GETCS_NEEDS_LAYOUT_FLUSH",
servo_restyle_damage="reflow",
)}
// min-width, min-height, min-block-size, min-inline-size
@@ -360,16 +357,13 @@ ${helpers.predefined_type(
)}
% endfor
- // NOTE: According to the spec, this should handle multiple values of `<track-size>`,
- // but gecko supports only a single value
${helpers.predefined_type(
"grid-auto-%ss" % kind,
- "TrackSize",
+ "ImplicitGridTracks",
"Default::default()",
engines="gecko",
animation_value_type="discrete",
spec="https://drafts.csswg.org/css-grid/#propdef-grid-auto-%ss" % kind,
- boxed=True,
)}
${helpers.predefined_type(
@@ -378,8 +372,6 @@ ${helpers.predefined_type(
"specified::GenericGridTemplateComponent::None",
engines="gecko",
spec="https://drafts.csswg.org/css-grid/#propdef-grid-template-%ss" % kind,
- boxed=True,
- flags="GETCS_NEEDS_LAYOUT_FLUSH",
animation_value_type="ComputedValue",
)}
diff --git a/components/style/properties/longhands/text.mako.rs b/components/style/properties/longhands/text.mako.rs
index a592e2f1290..b77e17dd6b7 100644
--- a/components/style/properties/longhands/text.mako.rs
+++ b/components/style/properties/longhands/text.mako.rs
@@ -71,9 +71,10 @@ ${helpers.predefined_type(
${helpers.predefined_type(
"text-decoration-thickness",
- "LengthOrAuto",
- "computed::LengthOrAuto::auto()",
+ "TextDecorationLength",
+ "generics::text::GenericTextDecorationLength::Auto",
engines="gecko",
+ initial_specified_value="generics::text::GenericTextDecorationLength::Auto",
animation_value_type="ComputedValue",
gecko_pref="layout.css.text-decoration-thickness.enabled",
spec="https://drafts.csswg.org/css-text-decor-4/#text-decoration-width-property"
diff --git a/components/style/properties/longhands/ui.mako.rs b/components/style/properties/longhands/ui.mako.rs
index d59be17a27a..64702855967 100644
--- a/components/style/properties/longhands/ui.mako.rs
+++ b/components/style/properties/longhands/ui.mako.rs
@@ -80,7 +80,6 @@ ${helpers.predefined_type(
"Transform",
"generics::transform::Transform::none()",
engines="gecko",
- flags="GETCS_NEEDS_LAYOUT_FLUSH",
animation_value_type="ComputedValue",
spec="None (Nonstandard internal property)",
enabled_in="chrome",
@@ -94,7 +93,6 @@ ${helpers.predefined_type(
animation_value_type="ComputedValue",
gecko_ffi_name="mWindowTransformOrigin",
boxed=True,
- flags="GETCS_NEEDS_LAYOUT_FLUSH",
spec="None (Nonstandard internal property)",
enabled_in="chrome",
)}
diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs
index c16de38f204..72ae381f5d9 100644
--- a/components/style/properties/properties.mako.rs
+++ b/components/style/properties/properties.mako.rs
@@ -981,13 +981,10 @@ bitflags! {
const APPLIES_TO_CUE = 1 << 6;
/// This longhand property applies to ::marker.
const APPLIES_TO_MARKER = 1 << 7;
- /// This property's getComputedStyle implementation requires layout
- /// to be flushed.
- const GETCS_NEEDS_LAYOUT_FLUSH = 1 << 8;
/// This property is a legacy shorthand.
///
/// https://drafts.csswg.org/css-cascade/#legacy-shorthand
- const IS_LEGACY_SHORTHAND = 1 << 9;
+ const IS_LEGACY_SHORTHAND = 1 << 8;
/* The following flags are currently not used in Rust code, they
* only need to be listed in corresponding properties so that
diff --git a/components/style/properties/shorthands/position.mako.rs b/components/style/properties/shorthands/position.mako.rs
index 8e61f0f6ecd..81a54dbfa57 100644
--- a/components/style/properties/shorthands/position.mako.rs
+++ b/components/style/properties/shorthands/position.mako.rs
@@ -268,7 +268,7 @@
>
use crate::parser::Parse;
use servo_arc::Arc;
- use crate::values::generics::grid::{TrackSize, TrackList, TrackListType};
+ use crate::values::generics::grid::{TrackSize, TrackList};
use crate::values::generics::grid::{TrackListValue, concat_serialize_idents};
use crate::values::specified::{GridTemplateComponent, GenericGridTemplateComponent};
use crate::values::specified::grid::parse_line_names;
@@ -300,26 +300,28 @@
}
% endfor
- let first_line_names = input.try(parse_line_names).unwrap_or(vec![].into_boxed_slice());
+ let first_line_names = input.try(parse_line_names).unwrap_or_default();
if let Ok(mut string) = input.try(|i| i.expect_string().map(|s| s.as_ref().to_owned().into())) {
let mut strings = vec![];
let mut values = vec![];
let mut line_names = vec![];
- let mut names = first_line_names.into_vec();
+ let mut names = first_line_names;
loop {
- line_names.push(names.into_boxed_slice());
+ line_names.push(names);
strings.push(string);
let size = input.try(|i| TrackSize::parse(context, i)).unwrap_or_default();
values.push(TrackListValue::TrackSize(size));
- names = input.try(parse_line_names).unwrap_or(vec![].into_boxed_slice()).into_vec();
+ names = input.try(parse_line_names).unwrap_or_default();
if let Ok(v) = input.try(parse_line_names) {
- names.extend(v.into_vec());
+ let mut names_vec = names.into_vec();
+ names_vec.extend(v.into_iter());
+ names = names_vec.into();
}
string = match input.try(|i| i.expect_string().map(|s| s.as_ref().to_owned().into())) {
Ok(s) => s,
_ => { // only the named area determines whether we should bail out
- line_names.push(names.into_boxed_slice());
+ line_names.push(names.into());
break
},
};
@@ -327,22 +329,21 @@
if line_names.len() == values.len() {
// should be one longer than track sizes
- line_names.push(vec![].into_boxed_slice());
+ line_names.push(Default::default());
}
let template_areas = TemplateAreas::from_vec(strings)
.map_err(|()| input.new_custom_error(StyleParseErrorKind::UnspecifiedError))?;
let template_rows = TrackList {
- list_type: TrackListType::Normal,
- values,
- line_names: line_names.into_boxed_slice(),
- auto_repeat: None,
+ values: values.into(),
+ line_names: line_names.into(),
+ auto_repeat_index: std::usize::MAX,
};
let template_cols = if input.try(|i| i.expect_delim('/')).is_ok() {
let value = GridTemplateComponent::parse_without_none(context, input)?;
if let GenericGridTemplateComponent::TrackList(ref list) = value {
- if list.list_type != TrackListType::Explicit {
+ if !list.is_explicit() {
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
}
}
@@ -352,8 +353,11 @@
GenericGridTemplateComponent::None
};
- Ok((GenericGridTemplateComponent::TrackList(template_rows),
- template_cols, GridTemplateAreas::Areas(TemplateAreasArc(Arc::new(template_areas)))))
+ Ok((
+ GenericGridTemplateComponent::TrackList(Box::new(template_rows)),
+ template_cols,
+ GridTemplateAreas::Areas(TemplateAreasArc(Arc::new(template_areas)))
+ ))
} else {
let mut template_rows = GridTemplateComponent::parse(context, input)?;
if let GenericGridTemplateComponent::TrackList(ref mut list) = template_rows {
@@ -407,13 +411,10 @@
let track_list = match *template_rows {
GenericGridTemplateComponent::TrackList(ref list) => {
- // We should fail if there is a `repeat` function. `grid` and
- // `grid-template` shorthands doesn't accept that. Only longhand accepts.
- if list.auto_repeat.is_some() ||
- list.values.iter().any(|v| match *v {
- TrackListValue::TrackRepeat(_) => true,
- _ => false,
- }) {
+ // We should fail if there is a `repeat` function.
+ // `grid` and `grid-template` shorthands doesn't accept
+ // that. Only longhand accepts.
+ if !list.is_explicit() {
return Ok(());
}
list
@@ -429,11 +430,7 @@
// We should fail if there is a `repeat` function. `grid` and
// `grid-template` shorthands doesn't accept that. Only longhand accepts that.
GenericGridTemplateComponent::TrackList(ref list) => {
- if list.auto_repeat.is_some() ||
- list.values.iter().any(|v| match *v {
- TrackListValue::TrackRepeat(_) => true,
- _ => false,
- }) {
+ if !list.is_explicit() {
return Ok(());
}
},
@@ -498,8 +495,8 @@
>
use crate::parser::Parse;
use crate::properties::longhands::{grid_auto_columns, grid_auto_rows, grid_auto_flow};
- use crate::values::generics::grid::{GridTemplateComponent, TrackListType};
- use crate::values::specified::{GenericGridTemplateComponent, TrackSize};
+ use crate::values::generics::grid::GridTemplateComponent;
+ use crate::values::specified::{GenericGridTemplateComponent, ImplicitGridTracks};
use crate::values::specified::position::{AutoFlow, GridAutoFlow, GridTemplateAreas};
pub fn parse_value<'i, 't>(
@@ -509,8 +506,8 @@
let mut temp_rows = GridTemplateComponent::None;
let mut temp_cols = GridTemplateComponent::None;
let mut temp_areas = GridTemplateAreas::None;
- let mut auto_rows = TrackSize::default();
- let mut auto_cols = TrackSize::default();
+ let mut auto_rows = ImplicitGridTracks::default();
+ let mut auto_cols = ImplicitGridTracks::default();
let mut flow = grid_auto_flow::get_initial_value();
fn parse_auto_flow<'i, 't>(
@@ -571,8 +568,8 @@
/// Returns true if other sub properties except template-{rows,columns} are initial.
fn is_grid_template(&self) -> bool {
*self.grid_template_areas == GridTemplateAreas::None &&
- *self.grid_auto_rows == TrackSize::default() &&
- *self.grid_auto_columns == TrackSize::default() &&
+ self.grid_auto_rows.is_initial() &&
+ self.grid_auto_columns.is_initial() &&
*self.grid_auto_flow == grid_auto_flow::get_initial_value()
}
}
@@ -590,14 +587,14 @@
if self.grid_auto_flow.autoflow == AutoFlow::Column {
// It should fail to serialize if other branch of the if condition's values are set.
- if *self.grid_auto_rows != TrackSize::default() ||
+ if !self.grid_auto_rows.is_initial() ||
*self.grid_template_columns != GridTemplateComponent::None {
return Ok(());
}
// It should fail to serialize if template-rows value is not Explicit.
if let GenericGridTemplateComponent::TrackList(ref list) = *self.grid_template_rows {
- if list.list_type != TrackListType::Explicit {
+ if !list.is_explicit() {
return Ok(());
}
}
@@ -608,20 +605,20 @@
dest.write_str(" dense")?;
}
- if !self.grid_auto_columns.is_default() {
+ if !self.grid_auto_columns.is_initial() {
dest.write_str(" ")?;
self.grid_auto_columns.to_css(dest)?;
}
} else {
// It should fail to serialize if other branch of the if condition's values are set.
- if *self.grid_auto_columns != TrackSize::default() ||
+ if !self.grid_auto_columns.is_initial() ||
*self.grid_template_rows != GridTemplateComponent::None {
return Ok(());
}
// It should fail to serialize if template-column value is not Explicit.
if let GenericGridTemplateComponent::TrackList(ref list) = *self.grid_template_columns {
- if list.list_type != TrackListType::Explicit {
+ if !list.is_explicit() {
return Ok(());
}
}
@@ -631,7 +628,7 @@
dest.write_str(" dense")?;
}
- if !self.grid_auto_rows.is_default() {
+ if !self.grid_auto_rows.is_initial() {
dest.write_str(" ")?;
self.grid_auto_rows.to_css(dest)?;
}
diff --git a/components/style/properties/shorthands/text.mako.rs b/components/style/properties/shorthands/text.mako.rs
index 905512b08df..33b4a074892 100644
--- a/components/style/properties/shorthands/text.mako.rs
+++ b/components/style/properties/shorthands/text.mako.rs
@@ -8,12 +8,13 @@
engines="gecko servo-2013"
flags="SHORTHAND_IN_GETCS"
sub_properties="text-decoration-line
- ${' text-decoration-style text-decoration-color' if engine == 'gecko' else ''}"
+ ${' text-decoration-style text-decoration-color text-decoration-thickness' if engine == 'gecko' else ''}"
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration">
% if engine == "gecko":
use crate::values::specified;
- use crate::properties::longhands::{text_decoration_style, text_decoration_color};
+ use crate::properties::longhands::{text_decoration_style, text_decoration_color, text_decoration_thickness};
+ use crate::properties::{PropertyId, LonghandId};
% endif
use crate::properties::longhands::text_decoration_line;
@@ -22,7 +23,10 @@
input: &mut Parser<'i, 't>,
) -> Result<Longhands, ParseError<'i>> {
% if engine == "gecko":
- let (mut line, mut style, mut color, mut any) = (None, None, None, false);
+ let text_decoration_thickness_enabled =
+ PropertyId::Longhand(LonghandId::TextDecorationThickness).enabled_for_all_content();
+
+ let (mut line, mut style, mut color, mut thickness, mut any) = (None, None, None, None, false);
% else:
let (mut line, mut any) = (None, false);
% endif
@@ -45,6 +49,9 @@
% if engine == "gecko":
parse_component!(style, text_decoration_style);
parse_component!(color, text_decoration_color);
+ if text_decoration_thickness_enabled {
+ parse_component!(thickness, text_decoration_thickness);
+ }
% endif
break;
@@ -60,6 +67,7 @@
% if engine == "gecko":
text_decoration_style: unwrap_or_initial!(text_decoration_style, style),
text_decoration_color: unwrap_or_initial!(text_decoration_color, color),
+ text_decoration_thickness: unwrap_or_initial!(text_decoration_thickness, thickness),
% endif
})
}
@@ -78,6 +86,13 @@
dest.write_str(" ")?;
self.text_decoration_color.to_css(dest)?;
}
+
+ if let Some(text_decoration_thickness) = self.text_decoration_thickness {
+ if !text_decoration_thickness.is_auto() {
+ dest.write_str(" ")?;
+ self.text_decoration_thickness.to_css(dest)?;
+ }
+ }
% endif
Ok(())
diff --git a/components/style/style_adjuster.rs b/components/style/style_adjuster.rs
index 38b908a16c6..041d2f76caf 100644
--- a/components/style/style_adjuster.rs
+++ b/components/style/style_adjuster.rs
@@ -12,6 +12,7 @@ use crate::properties::longhands::float::computed_value::T as Float;
use crate::properties::longhands::overflow_x::computed_value::T as Overflow;
use crate::properties::longhands::position::computed_value::T as Position;
use crate::properties::{self, ComputedValues, StyleBuilder};
+use crate::values::specified::box_::DisplayInside;
use app_units::Au;
/// A struct that implements all the adjustment methods.
@@ -175,7 +176,9 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
/// Apply the blockification rules based on the table in CSS 2.2 section 9.7.
/// <https://drafts.csswg.org/css2/visuren.html#dis-pos-flo>
/// A ::marker pseudo-element with 'list-style-position:outside' needs to
- /// have its 'display' blockified.
+ /// have its 'display' blockified, unless the ::marker is for an inline
+ /// list-item (for which 'list-style-position:outside' behaves as 'inside').
+ /// https://drafts.csswg.org/css-lists-3/#list-style-position-property
fn blockify_if_necessary<E>(&mut self, layout_parent_style: &ComputedValues, element: Option<E>)
where
E: TElement,
@@ -194,10 +197,8 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
let is_root = self.style.pseudo.is_none() && element.map_or(false, |e| e.is_root());
blockify_if!(is_root);
if !self.skip_item_display_fixup(element) {
- blockify_if!(layout_parent_style
- .get_box()
- .clone_display()
- .is_item_container());
+ let parent_display = layout_parent_style.get_box().clone_display();
+ blockify_if!(parent_display.is_item_container());
}
let is_item_or_root = blockify;
@@ -207,7 +208,8 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
blockify_if!(
self.style.pseudo.map_or(false, |p| p.is_marker()) &&
self.style.get_parent_list().clone_list_style_position() ==
- ListStylePosition::Outside
+ ListStylePosition::Outside &&
+ layout_parent_style.get_box().clone_display().inside() != DisplayInside::Inline
);
if !blockify {
diff --git a/components/style/stylesheets/document_rule.rs b/components/style/stylesheets/document_rule.rs
index 62e814ac48b..942d60a7d17 100644
--- a/components/style/stylesheets/document_rule.rs
+++ b/components/style/stylesheets/document_rule.rs
@@ -253,20 +253,18 @@ impl DocumentCondition {
#[cfg(feature = "gecko")]
fn allowed_in(&self, context: &ParserContext) -> bool {
- use crate::gecko_bindings::structs;
use crate::stylesheets::Origin;
+ use static_prefs::pref;
if context.stylesheet_origin != Origin::Author {
return true;
}
- if unsafe { structs::StaticPrefs::sVarCache_layout_css_moz_document_content_enabled } {
+ if pref!("layout.css.moz-document.content.enabled") {
return true;
}
- if !unsafe {
- structs::StaticPrefs::sVarCache_layout_css_moz_document_url_prefix_hack_enabled
- } {
+ if !pref!("layout.css.moz-document.url-prefix-hack.enabled") {
return false;
}
diff --git a/components/style/stylesheets/supports_rule.rs b/components/style/stylesheets/supports_rule.rs
index 4b709974c7d..9ef3558bd1c 100644
--- a/components/style/stylesheets/supports_rule.rs
+++ b/components/style/stylesheets/supports_rule.rs
@@ -323,9 +323,7 @@ impl RawSelector {
pub fn eval(&self, context: &ParserContext, namespaces: &Namespaces) -> bool {
#[cfg(feature = "gecko")]
{
- if unsafe {
- !crate::gecko_bindings::structs::StaticPrefs::sVarCache_layout_css_supports_selector_enabled
- } {
+ if !static_prefs::pref!("layout.css.supports-selector.enabled") {
return false;
}
}
diff --git a/components/style/values/animated/grid.rs b/components/style/values/animated/grid.rs
index d1f6be1a32b..7b9417a08c6 100644
--- a/components/style/values/animated/grid.rs
+++ b/components/style/values/animated/grid.rs
@@ -101,7 +101,7 @@ impl Animate for generics::TrackRepeat<LengthPercentage, Integer> {
Ok(generics::TrackRepeat {
count,
line_names,
- track_sizes,
+ track_sizes: track_sizes.into(),
})
}
}
@@ -117,20 +117,19 @@ impl Animate for TrackList {
return Err(());
}
- if self.list_type != other.list_type {
+ if self.is_explicit() != other.is_explicit() {
return Err(());
}
- // For now, repeat(auto-fill/auto-fit, ...) is not animatable. TrackRepeat will
- // return Err(()) if we use keywords. Therefore, we can early return here to avoid
- // traversing |values| in <auto-track-list>. This may be updated in the future.
+ // For now, repeat(auto-fill/auto-fit, ...) is not animatable.
+ // TrackRepeat will return Err(()) if we use keywords. Therefore, we can
+ // early return here to avoid traversing |values| in <auto-track-list>.
+ // This may be updated in the future.
// https://github.com/w3c/csswg-drafts/issues/3503
- if let generics::TrackListType::Auto(_) = self.list_type {
+ if self.has_auto_repeat() || other.has_auto_repeat() {
return Err(());
}
- let list_type = self.list_type;
- let auto_repeat = self.auto_repeat.animate(&other.auto_repeat, procedure)?;
let values = self
.values
.iter()
@@ -142,10 +141,9 @@ impl Animate for TrackList {
let line_names = discrete(&self.line_names, &other.line_names, procedure)?;
Ok(TrackList {
- list_type,
- values,
+ values: values.into(),
line_names,
- auto_repeat,
+ auto_repeat_index: self.auto_repeat_index,
})
}
}
diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs
index 7cfe0de6d8d..bd78d376b35 100644
--- a/components/style/values/computed/mod.rs
+++ b/components/style/values/computed/mod.rs
@@ -7,6 +7,7 @@
use self::transform::DirectionVector;
use super::animated::ToAnimatedValue;
use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent;
+use super::generics::grid::ImplicitGridTracks as GenericImplicitGridTracks;
use super::generics::grid::{GenericGridLine, GenericTrackBreadth};
use super::generics::grid::{GenericTrackSize, TrackList as GenericTrackList};
use super::generics::transform::IsParallelTo;
@@ -68,17 +69,17 @@ pub use self::list::Quotes;
pub use self::motion::{OffsetPath, OffsetRotate};
pub use self::outline::OutlineStyle;
pub use self::percentage::{NonNegativePercentage, Percentage};
-pub use self::position::{GridAutoFlow, GridTemplateAreas, Position, ZIndex};
+pub use self::position::{GridAutoFlow, GridTemplateAreas, Position, PositionOrAuto, ZIndex};
pub use self::rect::NonNegativeLengthOrNumberRect;
pub use self::resolution::Resolution;
pub use self::svg::MozContextProperties;
pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind};
pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
pub use self::table::XSpan;
-pub use self::text::TextDecorationSkipInk;
pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight};
pub use self::text::{OverflowWrap, TextOverflow, WordBreak, WordSpacing};
pub use self::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle};
+pub use self::text::{TextDecorationLength, TextDecorationSkipInk};
pub use self::time::Time;
pub use self::transform::{Rotate, Scale, Transform, TransformOperation};
pub use self::transform::{TransformOrigin, TransformStyle, Translate};
@@ -467,6 +468,7 @@ trivial_to_computed_value!(i32);
trivial_to_computed_value!(u8);
trivial_to_computed_value!(u16);
trivial_to_computed_value!(u32);
+trivial_to_computed_value!(usize);
trivial_to_computed_value!(Atom);
#[cfg(feature = "servo")]
trivial_to_computed_value!(Prefix);
@@ -695,6 +697,9 @@ pub type TrackBreadth = GenericTrackBreadth<LengthPercentage>;
/// The computed value of a grid `<track-size>`
pub type TrackSize = GenericTrackSize<LengthPercentage>;
+/// The computed value of a grid `<track-size>+`
+pub type ImplicitGridTracks = GenericImplicitGridTracks<TrackSize>;
+
/// The computed value of a grid `<track-list>`
/// (could also be `<auto-track-list>` or `<explicit-track-list>`)
pub type TrackList = GenericTrackList<LengthPercentage, Integer>;
diff --git a/components/style/values/computed/position.rs b/components/style/values/computed/position.rs
index f0f8fe198a6..7b22c37f73f 100644
--- a/components/style/values/computed/position.rs
+++ b/components/style/values/computed/position.rs
@@ -9,6 +9,7 @@
use crate::values::computed::{Integer, LengthPercentage, Percentage};
use crate::values::generics::position::Position as GenericPosition;
+use crate::values::generics::position::PositionOrAuto as GenericPositionOrAuto;
use crate::values::generics::position::ZIndex as GenericZIndex;
pub use crate::values::specified::position::{GridAutoFlow, GridTemplateAreas};
use crate::Zero;
@@ -18,6 +19,9 @@ use style_traits::{CssWriter, ToCss};
/// The computed value of a CSS `<position>`
pub type Position = GenericPosition<HorizontalPosition, VerticalPosition>;
+/// The computed value of an `auto | <position>`
+pub type PositionOrAuto = GenericPositionOrAuto<Position>;
+
/// The computed value of a CSS horizontal position.
pub type HorizontalPosition = LengthPercentage;
diff --git a/components/style/values/computed/text.rs b/components/style/values/computed/text.rs
index 7201c1aff61..bdb2ac507bc 100644
--- a/components/style/values/computed/text.rs
+++ b/components/style/values/computed/text.rs
@@ -10,7 +10,7 @@ use crate::values::computed::length::{Length, LengthPercentage};
use crate::values::computed::{Context, NonNegativeLength, NonNegativeNumber, ToComputedValue};
use crate::values::generics::text::InitialLetter as GenericInitialLetter;
use crate::values::generics::text::LineHeight as GenericLineHeight;
-use crate::values::generics::text::Spacing;
+use crate::values::generics::text::{GenericTextDecorationLength, Spacing};
use crate::values::specified::text::{self as specified, TextOverflowSide};
use crate::values::specified::text::{TextEmphasisFillMode, TextEmphasisShapeKeyword};
use crate::values::{CSSFloat, CSSInteger};
@@ -26,6 +26,9 @@ pub use crate::values::specified::{TextDecorationSkipInk, TextTransform};
/// A computed value for the `initial-letter` property.
pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>;
+/// Implements type for `text-underline-offset` and `text-decoration-thickness` properties
+pub type TextDecorationLength = GenericTextDecorationLength<Length>;
+
/// A computed value for the `letter-spacing` property.
#[repr(transparent)]
#[derive(
@@ -194,22 +197,21 @@ impl TextDecorationsInEffect {
}
}
-/// computed value for the text-emphasis-style property
+/// Computed value for the text-emphasis-style property
+///
+/// cbindgen:derive-tagged-enum-copy-constructor=true
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue)]
+#[allow(missing_docs)]
+#[repr(C, u8)]
pub enum TextEmphasisStyle {
- /// Keyword value for the text-emphasis-style property (`filled` `open`)
- Keyword(TextEmphasisKeywordValue),
+ /// [ <fill> || <shape> ]
+ Keyword {
+ #[css(skip_if = "TextEmphasisFillMode::is_filled")]
+ fill: TextEmphasisFillMode,
+ shape: TextEmphasisShapeKeyword,
+ },
/// `none`
None,
- /// String (will be used only first grapheme cluster) for the text-emphasis-style property
- String(String),
-}
-
-/// Keyword value for the text-emphasis-style property
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue)]
-pub struct TextEmphasisKeywordValue {
- /// fill for the text-emphasis-style property
- pub fill: TextEmphasisFillMode,
- /// shape for the text-emphasis-style property
- pub shape: TextEmphasisShapeKeyword,
+ /// `<string>` (of which only the first grapheme cluster will be used).
+ String(crate::OwnedStr),
}
diff --git a/components/style/values/generics/easing.rs b/components/style/values/generics/easing.rs
index aab2ef547ba..b234b6a54e0 100644
--- a/components/style/values/generics/easing.rs
+++ b/components/style/values/generics/easing.rs
@@ -69,8 +69,7 @@ pub enum TimingKeyword {
#[cfg(feature = "gecko")]
fn step_position_jump_enabled(_context: &ParserContext) -> bool {
- use crate::gecko_bindings::structs;
- unsafe { structs::StaticPrefs::sVarCache_layout_css_step_position_jump_enabled }
+ static_prefs::pref!("layout.css.step-position-jump.enabled")
}
#[cfg(feature = "servo")]
diff --git a/components/style/values/generics/font.rs b/components/style/values/generics/font.rs
index 59907ff7920..eb8eac191f0 100644
--- a/components/style/values/generics/font.rs
+++ b/components/style/values/generics/font.rs
@@ -253,9 +253,7 @@ pub enum KeywordSize {
XLarge,
#[css(keyword = "xx-large")]
XXLarge,
- // This is not a real font keyword and will not parse
- // HTML font-size 7 corresponds to this value
- #[css(skip)]
+ #[css(keyword = "xxx-large")]
XXXLarge,
}
diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs
index 7de109141fe..b9e173ea50f 100644
--- a/components/style/values/generics/grid.rs
+++ b/components/style/values/generics/grid.rs
@@ -12,7 +12,7 @@ use crate::values::{CSSFloat, CustomIdent};
use crate::{Atom, Zero};
use cssparser::Parser;
use std::fmt::{self, Write};
-use std::{cmp, mem, usize};
+use std::{cmp, usize};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
/// These are the limits that we choose to clamp grid line numbers to.
@@ -290,16 +290,17 @@ impl<L> TrackSize<L> {
}
}
-impl<L> Default for TrackSize<L> {
- fn default() -> Self {
- TrackSize::Breadth(TrackBreadth::Auto)
+impl<L: PartialEq> TrackSize<L> {
+ /// Return true if it is `auto`.
+ #[inline]
+ pub fn is_auto(&self) -> bool {
+ *self == TrackSize::Breadth(TrackBreadth::Auto)
}
}
-impl<L: PartialEq> TrackSize<L> {
- /// Returns true if current TrackSize is same as default.
- pub fn is_default(&self) -> bool {
- *self == TrackSize::default()
+impl<L> Default for TrackSize<L> {
+ fn default() -> Self {
+ TrackSize::Breadth(TrackBreadth::Auto)
}
}
@@ -334,6 +335,39 @@ impl<L: ToCss> ToCss for TrackSize<L> {
}
}
+/// A `<track-size>+`.
+/// We use the empty slice as `auto`, and always parse `auto` as an empty slice.
+/// This means it's impossible to have a slice containing only one auto item.
+#[derive(
+ Clone,
+ Debug,
+ Default,
+ MallocSizeOf,
+ PartialEq,
+ SpecifiedValueInfo,
+ ToComputedValue,
+ ToCss,
+ ToResolvedValue,
+ ToShmem,
+)]
+#[repr(transparent)]
+pub struct GenericImplicitGridTracks<T>(
+ #[css(if_empty = "auto", iterable)] pub crate::OwnedSlice<T>,
+);
+
+pub use self::GenericImplicitGridTracks as ImplicitGridTracks;
+
+impl<T: fmt::Debug + Default + PartialEq> ImplicitGridTracks<T> {
+ /// Returns true if current value is same as its initial value (i.e. auto).
+ pub fn is_initial(&self) -> bool {
+ debug_assert_ne!(
+ *self,
+ ImplicitGridTracks(crate::OwnedSlice::from(vec![Default::default()]))
+ );
+ self.0.is_empty()
+ }
+}
+
/// Helper function for serializing identifiers with a prefix and suffix, used
/// for serializing <line-names> (in grid).
pub fn concat_serialize_idents<W>(
@@ -366,6 +400,7 @@ where
#[derive(
Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToResolvedValue, ToShmem,
)]
+#[repr(C, u8)]
pub enum RepeatCount<Integer> {
/// A positive integer. This is allowed only for `<track-repeat>` and `<fixed-repeat>`
Number(Integer),
@@ -380,18 +415,15 @@ impl Parse for RepeatCount<specified::Integer> {
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
- // Maximum number of repeat is 10000. The greater numbers should be clamped.
- const MAX_LINE: i32 = 10000;
if let Ok(mut i) = input.try(|i| specified::Integer::parse_positive(context, i)) {
- if i.value() > MAX_LINE {
- i = specified::Integer::new(MAX_LINE);
- }
- Ok(RepeatCount::Number(i))
- } else {
- try_match_ident_ignore_ascii_case! { input,
- "auto-fill" => Ok(RepeatCount::AutoFill),
- "auto-fit" => Ok(RepeatCount::AutoFit),
+ if i.value() > MAX_GRID_LINE {
+ i = specified::Integer::new(MAX_GRID_LINE);
}
+ return Ok(RepeatCount::Number(i));
+ }
+ try_match_ident_ignore_ascii_case! { input,
+ "auto-fill" => Ok(RepeatCount::AutoFill),
+ "auto-fit" => Ok(RepeatCount::AutoFit),
}
}
}
@@ -411,7 +443,8 @@ impl Parse for RepeatCount<specified::Integer> {
ToShmem,
)]
#[css(function = "repeat")]
-pub struct TrackRepeat<L, I> {
+#[repr(C)]
+pub struct GenericTrackRepeat<L, I> {
/// The number of times for the value to be repeated (could also be `auto-fit` or `auto-fill`)
pub count: RepeatCount<I>,
/// `<line-names>` accompanying `<track_size>` values.
@@ -419,11 +452,13 @@ pub struct TrackRepeat<L, I> {
/// If there's no `<line-names>`, then it's represented by an empty vector.
/// For N `<track-size>` values, there will be N+1 `<line-names>`, and so this vector's
/// length is always one value more than that of the `<track-size>`.
- pub line_names: Box<[Box<[CustomIdent]>]>,
+ pub line_names: crate::OwnedSlice<crate::OwnedSlice<CustomIdent>>,
/// `<track-size>` values.
- pub track_sizes: Vec<TrackSize<L>>,
+ pub track_sizes: crate::OwnedSlice<GenericTrackSize<L>>,
}
+pub use self::GenericTrackRepeat as TrackRepeat;
+
impl<L: ToCss, I: ToCss> ToCss for TrackRepeat<L, I> {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
@@ -457,46 +492,10 @@ impl<L: ToCss, I: ToCss> ToCss for TrackRepeat<L, I> {
Ok(())
}
}
-impl<L: Clone> TrackRepeat<L, specified::Integer> {
- /// If the repeat count is numeric, then expand the values and merge accordingly.
- pub fn expand(&self) -> Self {
- if let RepeatCount::Number(num) = self.count {
- let mut line_names = vec![];
- let mut track_sizes = vec![];
- let mut prev_names = vec![];
-
- for _ in 0..num.value() {
- let mut names_iter = self.line_names.iter();
- for (size, names) in self.track_sizes.iter().zip(&mut names_iter) {
- prev_names.extend_from_slice(&names);
- let vec = mem::replace(&mut prev_names, vec![]);
- line_names.push(vec.into_boxed_slice());
- track_sizes.push(size.clone());
- }
-
- if let Some(names) = names_iter.next() {
- prev_names.extend_from_slice(&names);
- }
- }
-
- line_names.push(prev_names.into_boxed_slice());
- TrackRepeat {
- count: self.count,
- track_sizes: track_sizes,
- line_names: line_names.into_boxed_slice(),
- }
- } else {
- // if it's auto-fit/auto-fill, then it's left to the layout.
- TrackRepeat {
- count: self.count,
- track_sizes: self.track_sizes.clone(),
- line_names: self.line_names.clone(),
- }
- }
- }
-}
/// Track list values. Can be <track-size> or <track-repeat>
+///
+/// cbindgen:derive-tagged-enum-copy-constructor=true
#[derive(
Animate,
Clone,
@@ -509,56 +508,63 @@ impl<L: Clone> TrackRepeat<L, specified::Integer> {
ToResolvedValue,
ToShmem,
)]
-pub enum TrackListValue<LengthPercentage, Integer> {
+#[repr(C, u8)]
+pub enum GenericTrackListValue<LengthPercentage, Integer> {
/// A <track-size> value.
- TrackSize(#[animation(field_bound)] TrackSize<LengthPercentage>),
+ TrackSize(#[animation(field_bound)] GenericTrackSize<LengthPercentage>),
/// A <track-repeat> value.
- TrackRepeat(#[animation(field_bound)] TrackRepeat<LengthPercentage, Integer>),
+ TrackRepeat(#[animation(field_bound)] GenericTrackRepeat<LengthPercentage, Integer>),
}
-/// The type of a `<track-list>` as determined during parsing.
-///
-/// <https://drafts.csswg.org/css-grid/#typedef-track-list>
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)]
-pub enum TrackListType {
- /// [`<auto-track-list>`](https://drafts.csswg.org/css-grid/#typedef-auto-track-list)
- ///
- /// If this type exists, then the value at the index in `line_names` field in `TrackList`
- /// has the `<line-names>?` list that comes before `<auto-repeat>`. If it's a specified value,
- /// then the `repeat()` function (that follows the line names list) is also at the given index
- /// in `values` field. On the contrary, if it's a computed value, then the `repeat()` function
- /// is in the `auto_repeat` field.
- Auto(u16),
- /// [`<track-list>`](https://drafts.csswg.org/css-grid/#typedef-track-list)
- Normal,
- /// [`<explicit-track-list>`](https://drafts.csswg.org/css-grid/#typedef-explicit-track-list)
- ///
- /// Note that this is a subset of the normal `<track-list>`, and so it could be used in place
- /// of the latter.
- Explicit,
+pub use self::GenericTrackListValue as TrackListValue;
+
+impl<L, I> TrackListValue<L, I> {
+ fn is_repeat(&self) -> bool {
+ matches!(*self, TrackListValue::TrackRepeat(..))
+ }
}
/// A grid `<track-list>` type.
///
/// <https://drafts.csswg.org/css-grid/#typedef-track-list>
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToResolvedValue, ToShmem)]
-pub struct TrackList<LengthPercentage, Integer> {
- /// The type of this `<track-list>` (auto, explicit or general).
- ///
- /// In order to avoid parsing the same value multiple times, this does a single traversal
- /// and arrives at the type of value it has parsed (or bails out gracefully with an error).
+#[derive(
+ Clone,
+ Debug,
+ MallocSizeOf,
+ PartialEq,
+ SpecifiedValueInfo,
+ ToComputedValue,
+ ToResolvedValue,
+ ToShmem,
+)]
+#[repr(C)]
+pub struct GenericTrackList<LengthPercentage, Integer> {
+ /// The index in `values` where our `<auto-repeat>` value is, if in bounds.
#[css(skip)]
- pub list_type: TrackListType,
+ pub auto_repeat_index: usize,
/// A vector of `<track-size> | <track-repeat>` values.
- pub values: Vec<TrackListValue<LengthPercentage, Integer>>,
+ pub values: crate::OwnedSlice<GenericTrackListValue<LengthPercentage, Integer>>,
/// `<line-names>` accompanying `<track-size> | <track-repeat>` values.
///
/// If there's no `<line-names>`, then it's represented by an empty vector.
/// For N values, there will be N+1 `<line-names>`, and so this vector's
/// length is always one value more than that of the `<track-size>`.
- pub line_names: Box<[Box<[CustomIdent]>]>,
- /// `<auto-repeat>` value. There can only be one `<auto-repeat>` in a TrackList.
- pub auto_repeat: Option<TrackRepeat<LengthPercentage, Integer>>,
+ pub line_names: crate::OwnedSlice<crate::OwnedSlice<CustomIdent>>,
+}
+
+pub use self::GenericTrackList as TrackList;
+
+impl<L, I> TrackList<L, I> {
+ /// Whether this track list is an explicit track list (that is, doesn't have
+ /// any repeat values).
+ pub fn is_explicit(&self) -> bool {
+ !self.values.iter().any(|v| v.is_repeat())
+ }
+
+ /// Whether this track list has an `<auto-repeat>` value.
+ pub fn has_auto_repeat(&self) -> bool {
+ self.auto_repeat_index < self.values.len()
+ }
}
impl<L: ToCss, I: ToCss> ToCss for TrackList<L, I> {
@@ -566,11 +572,6 @@ impl<L: ToCss, I: ToCss> ToCss for TrackList<L, I> {
where
W: Write,
{
- let auto_idx = match self.list_type {
- TrackListType::Auto(i) => i as usize,
- _ => usize::MAX,
- };
-
let mut values_iter = self.values.iter().peekable();
let mut line_names_iter = self.line_names.iter().peekable();
@@ -578,29 +579,20 @@ impl<L: ToCss, I: ToCss> ToCss for TrackList<L, I> {
let names = line_names_iter.next().unwrap(); // This should exist!
concat_serialize_idents("[", "]", names, " ", dest)?;
- match self.auto_repeat {
- Some(ref repeat) if idx == auto_idx => {
+ match values_iter.next() {
+ Some(value) => {
if !names.is_empty() {
dest.write_str(" ")?;
}
- repeat.to_css(dest)?;
- },
- _ => match values_iter.next() {
- Some(value) => {
- if !names.is_empty() {
- dest.write_str(" ")?;
- }
-
- value.to_css(dest)?;
- },
- None => break,
+ value.to_css(dest)?;
},
+ None => break,
}
if values_iter.peek().is_some() ||
line_names_iter.peek().map_or(false, |v| !v.is_empty()) ||
- (idx + 1 == auto_idx)
+ (idx + 1 == self.auto_repeat_index)
{
dest.write_str(" ")?;
}
@@ -613,7 +605,8 @@ impl<L: ToCss, I: ToCss> ToCss for TrackList<L, I> {
/// The `<line-name-list>` for subgrids.
///
/// `subgrid [ <line-names> | repeat(<positive-integer> | auto-fill, <line-names>+) ]+`
-/// Old spec: https://www.w3.org/TR/2015/WD-css-grid-1-20150917/#typedef-line-name-list
+///
+/// https://drafts.csswg.org/css-grid-2/#typedef-line-name-list
#[derive(
Clone,
Debug,
@@ -625,11 +618,12 @@ impl<L: ToCss, I: ToCss> ToCss for TrackList<L, I> {
ToResolvedValue,
ToShmem,
)]
+#[repr(C)]
pub struct LineNameList {
/// The optional `<line-name-list>`
- pub names: Box<[Box<[CustomIdent]>]>,
- /// Indicates the line name that requires `auto-fill`
- pub fill_idx: Option<u32>,
+ pub names: crate::OwnedSlice<crate::OwnedSlice<CustomIdent>>,
+ /// Indicates the line name that requires `auto-fill`, if in bounds.
+ pub fill_idx: usize,
}
impl Parse for LineNameList {
@@ -652,13 +646,17 @@ impl Parse for LineNameList {
while let Ok(names) = input.try(parse_line_names) {
names_list.push(names);
}
-
Ok((names_list, count))
})
});
if let Ok((mut names_list, count)) = repeat_parse_result {
match count {
+ // FIXME(emilio): we probably shouldn't expand repeat() at
+ // parse time for subgrid.
+ //
+ // Also this doesn't have the merging semantics that
+ // non-subgrid has... But maybe that's ok?
RepeatCount::Number(num) => line_names.extend(
names_list
.iter()
@@ -676,7 +674,7 @@ impl Parse for LineNameList {
let names = names_list.pop().unwrap();
line_names.push(names);
- fill_idx = Some(line_names.len() as u32 - 1);
+ fill_idx = Some(line_names.len() - 1);
},
_ => return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
}
@@ -687,9 +685,13 @@ impl Parse for LineNameList {
}
}
+ if line_names.len() > MAX_GRID_LINE as usize {
+ line_names.truncate(MAX_GRID_LINE as usize);
+ }
+
Ok(LineNameList {
- names: line_names.into_boxed_slice(),
- fill_idx: fill_idx,
+ names: line_names.into(),
+ fill_idx: fill_idx.unwrap_or(usize::MAX),
})
}
}
@@ -700,7 +702,7 @@ impl ToCss for LineNameList {
W: Write,
{
dest.write_str("subgrid")?;
- let fill_idx = self.fill_idx.map(|v| v as usize).unwrap_or(usize::MAX);
+ let fill_idx = self.fill_idx;
for (i, names) in self.names.iter().enumerate() {
if i == fill_idx {
dest.write_str(" repeat(auto-fill,")?;
@@ -727,8 +729,8 @@ impl ToCss for LineNameList {
}
/// Variants for `<grid-template-rows> | <grid-template-columns>`
-/// Subgrid deferred to Level 2 spec due to lack of implementation.
-/// But it's implemented in gecko, so we have to as well.
+///
+/// cbindgen:derive-tagged-enum-copy-constructor=true
#[derive(
Animate,
Clone,
@@ -741,7 +743,8 @@ impl ToCss for LineNameList {
ToResolvedValue,
ToShmem,
)]
-pub enum GridTemplateComponent<L, I> {
+#[repr(C, u8)]
+pub enum GenericGridTemplateComponent<L, I> {
/// `none` value.
None,
/// The grid `<track-list>`
@@ -750,14 +753,16 @@ pub enum GridTemplateComponent<L, I> {
#[compute(field_bound)]
#[resolve(field_bound)]
#[shmem(field_bound)]
- TrackList<L, I>,
+ Box<GenericTrackList<L, I>>,
),
/// A `subgrid <line-name-list>?`
/// TODO: Support animations for this after subgrid is addressed in [grid-2] spec.
#[animation(error)]
- Subgrid(LineNameList),
+ Subgrid(Box<LineNameList>),
}
+pub use self::GenericGridTemplateComponent as GridTemplateComponent;
+
impl<L, I> GridTemplateComponent<L, I> {
/// Returns length of the <track-list>s <track-size>
pub fn track_list_len(&self) -> usize {
diff --git a/components/style/values/generics/position.rs b/components/style/values/generics/position.rs
index 7e43f439793..2742dd87913 100644
--- a/components/style/values/generics/position.rs
+++ b/components/style/values/generics/position.rs
@@ -41,6 +41,43 @@ impl<H, V> Position<H, V> {
}
}
+/// A generic type for representing an `Auto | <position>`.
+/// This is used by <offset-anchor> for now.
+/// https://drafts.fxtf.org/motion-1/#offset-anchor-property
+#[derive(
+ Animate,
+ Clone,
+ ComputeSquaredDistance,
+ Copy,
+ Debug,
+ MallocSizeOf,
+ Parse,
+ PartialEq,
+ SpecifiedValueInfo,
+ ToAnimatedZero,
+ ToComputedValue,
+ ToCss,
+ ToResolvedValue,
+ ToShmem,
+)]
+#[repr(C, u8)]
+pub enum GenericPositionOrAuto<Pos> {
+ /// The <position> value.
+ Position(Pos),
+ /// The keyword `auto`.
+ Auto,
+}
+
+pub use self::GenericPositionOrAuto as PositionOrAuto;
+
+impl<Pos> PositionOrAuto<Pos> {
+ /// Return `auto`.
+ #[inline]
+ pub fn auto() -> Self {
+ PositionOrAuto::Auto
+ }
+}
+
/// A generic value for the `z-index` property.
#[derive(
Animate,
diff --git a/components/style/values/generics/text.rs b/components/style/values/generics/text.rs
index b55a9ad62dc..fd434cc1273 100644
--- a/components/style/values/generics/text.rs
+++ b/components/style/values/generics/text.rs
@@ -72,11 +72,8 @@ impl<Value> Spacing<Value> {
#[cfg(feature = "gecko")]
fn line_height_moz_block_height_enabled(context: &ParserContext) -> bool {
- use crate::gecko_bindings::structs;
context.in_ua_sheet() ||
- unsafe {
- structs::StaticPrefs::sVarCache_layout_css_line_height_moz_block_height_content_enabled
- }
+ static_prefs::pref!("layout.css.line-height-moz-block-height.content.enabled")
}
/// A generic value for the `line-height` property.
@@ -125,3 +122,33 @@ impl<N, L> LineHeight<N, L> {
LineHeight::Normal
}
}
+
+/// Implements type for text-underline-offset and text-decoration-thickness
+/// which take the grammar of auto | from-font | <length>
+///
+/// https://drafts.csswg.org/css-text-decor-4/
+#[repr(C, u8)]
+#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
+#[derive(
+ Animate,
+ Clone,
+ Copy,
+ ComputeSquaredDistance,
+ ToAnimatedZero,
+ Debug,
+ Eq,
+ MallocSizeOf,
+ Parse,
+ PartialEq,
+ SpecifiedValueInfo,
+ ToComputedValue,
+ ToCss,
+ ToResolvedValue,
+ ToShmem,
+)]
+#[allow(missing_docs)]
+pub enum GenericTextDecorationLength<L> {
+ Length(L),
+ Auto,
+ FromFont,
+}
diff --git a/components/style/values/resolved/mod.rs b/components/style/values/resolved/mod.rs
index 379ea83ec6b..e64178a1c95 100644
--- a/components/style/values/resolved/mod.rs
+++ b/components/style/values/resolved/mod.rs
@@ -65,6 +65,7 @@ trivial_to_resolved_value!(u8);
trivial_to_resolved_value!(i8);
trivial_to_resolved_value!(u16);
trivial_to_resolved_value!(u32);
+trivial_to_resolved_value!(usize);
trivial_to_resolved_value!(String);
trivial_to_resolved_value!(Box<str>);
trivial_to_resolved_value!(cssparser::RGBA);
diff --git a/components/style/values/specified/basic_shape.rs b/components/style/values/specified/basic_shape.rs
index 8dccf4594f0..3c32144e71c 100644
--- a/components/style/values/specified/basic_shape.rs
+++ b/components/style/values/specified/basic_shape.rs
@@ -58,9 +58,7 @@ pub type Polygon = generic::GenericPolygon<LengthPercentage>;
#[cfg(feature = "gecko")]
fn is_clip_path_path_enabled(context: &ParserContext) -> bool {
- use crate::gecko_bindings::structs::mozilla;
- context.chrome_rules_enabled() ||
- unsafe { mozilla::StaticPrefs::sVarCache_layout_css_clip_path_path_enabled }
+ context.chrome_rules_enabled() || static_prefs::pref!("layout.css.clip-path-path.enabled")
}
#[cfg(feature = "servo")]
fn is_clip_path_path_enabled(_: &ParserContext) -> bool {
diff --git a/components/style/values/specified/box.rs b/components/style/values/specified/box.rs
index 0811a48be1a..f481b940e05 100644
--- a/components/style/values/specified/box.rs
+++ b/components/style/values/specified/box.rs
@@ -16,6 +16,7 @@ use crate::values::specified::{AllowQuirks, Number};
use crate::values::{CustomIdent, KeyframesName};
use crate::Atom;
use cssparser::Parser;
+use num_traits::FromPrimitive;
use selectors::parser::SelectorParseErrorKind;
use std::fmt::{self, Write};
use style_traits::{CssWriter, KeywordsCollectFn, ParseError};
@@ -23,102 +24,55 @@ use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
#[cfg(feature = "gecko")]
fn moz_display_values_enabled(context: &ParserContext) -> bool {
- use crate::gecko_bindings::structs;
context.in_ua_or_chrome_sheet() ||
- unsafe { structs::StaticPrefs::sVarCache_layout_css_xul_display_values_content_enabled }
+ static_prefs::pref!("layout.css.xul-display-values.content.enabled")
}
#[cfg(feature = "gecko")]
fn moz_box_display_values_enabled(context: &ParserContext) -> bool {
- use crate::gecko_bindings::structs;
context.in_ua_or_chrome_sheet() ||
- unsafe {
- structs::StaticPrefs::sVarCache_layout_css_xul_box_display_values_content_enabled
- }
-}
-
-#[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
-fn parse_unimplemented_in_servo_2020(_context: &ParserContext) -> bool {
- true
-}
-
-#[cfg(feature = "servo-layout-2020")]
-fn parse_unimplemented_in_servo_2020(_context: &ParserContext) -> bool {
- servo_config::prefs::pref_map()
- .get("layout.2020.unimplemented")
- .as_bool()
- .unwrap_or(false)
+ static_prefs::pref!("layout.css.xul-box-display-values.content.enabled")
}
/// Defines an element’s display type, which consists of
/// the two basic qualities of how an element generates boxes
/// <https://drafts.csswg.org/css-display/#propdef-display>
-///
-///
-/// NOTE(emilio): Order is important in Gecko!
-///
-/// If you change it, make sure to take a look at the
-/// FrameConstructionDataByDisplay stuff (both the XUL and non-XUL version), and
-/// ensure it's still correct!
#[allow(missing_docs)]
-#[derive(
- Clone,
- Copy,
- Debug,
- Eq,
- FromPrimitive,
- Hash,
- MallocSizeOf,
- Parse,
- PartialEq,
- SpecifiedValueInfo,
- ToComputedValue,
- ToCss,
- ToResolvedValue,
- ToShmem,
-)]
-#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
+#[derive(Clone, Copy, Debug, Eq, FromPrimitive, Hash, MallocSizeOf, PartialEq, ToCss, ToShmem)]
#[repr(u8)]
-pub enum Display {
+pub enum DisplayOutside {
None = 0,
+ Inline,
Block,
+ TableCaption,
+ InternalTable,
+ #[cfg(feature = "gecko")]
+ InternalRuby,
#[cfg(feature = "gecko")]
+ XUL,
+}
+
+#[allow(missing_docs)]
+#[derive(Clone, Copy, Debug, Eq, FromPrimitive, Hash, MallocSizeOf, PartialEq, ToCss, ToShmem)]
+#[repr(u8)]
+pub enum DisplayInside {
+ None = 0,
+ #[cfg(feature = "gecko")]
+ Contents,
+ Block,
FlowRoot,
Inline,
- #[parse(condition = "parse_unimplemented_in_servo_2020")]
- InlineBlock,
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
- ListItem,
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
+ Flex,
+ #[cfg(feature = "gecko")]
+ Grid,
Table,
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
- InlineTable,
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
TableRowGroup,
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
TableColumn,
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
TableColumnGroup,
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
TableHeaderGroup,
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
TableFooterGroup,
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
TableRow,
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
TableCell,
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
- TableCaption,
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
- #[parse(aliases = "-webkit-flex")]
- Flex,
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
- #[parse(aliases = "-webkit-inline-flex")]
- InlineFlex,
- #[cfg(feature = "gecko")]
- Grid,
- #[cfg(feature = "gecko")]
- InlineGrid,
#[cfg(feature = "gecko")]
Ruby,
#[cfg(feature = "gecko")]
@@ -130,46 +84,216 @@ pub enum Display {
#[cfg(feature = "gecko")]
RubyTextContainer,
#[cfg(feature = "gecko")]
- Contents,
- #[cfg(feature = "gecko")]
WebkitBox,
#[cfg(feature = "gecko")]
- WebkitInlineBox,
- #[cfg(feature = "gecko")]
- #[parse(condition = "moz_box_display_values_enabled")]
MozBox,
#[cfg(feature = "gecko")]
- #[parse(condition = "moz_box_display_values_enabled")]
MozInlineBox,
#[cfg(feature = "gecko")]
- #[parse(condition = "moz_display_values_enabled")]
MozGrid,
#[cfg(feature = "gecko")]
- #[parse(condition = "moz_display_values_enabled")]
MozInlineGrid,
#[cfg(feature = "gecko")]
- #[parse(condition = "moz_display_values_enabled")]
MozGridGroup,
#[cfg(feature = "gecko")]
- #[parse(condition = "moz_display_values_enabled")]
MozGridLine,
#[cfg(feature = "gecko")]
- #[parse(condition = "moz_display_values_enabled")]
MozStack,
#[cfg(feature = "gecko")]
- #[parse(condition = "moz_display_values_enabled")]
MozInlineStack,
#[cfg(feature = "gecko")]
- #[parse(condition = "moz_display_values_enabled")]
MozDeck,
#[cfg(feature = "gecko")]
- #[parse(condition = "moz_display_values_enabled")]
MozGroupbox,
#[cfg(feature = "gecko")]
- #[parse(condition = "moz_display_values_enabled")]
MozPopup,
+ Flow, // only used for parsing, not computed value
+}
+
+#[allow(missing_docs)]
+#[derive(
+ Clone,
+ Copy,
+ Debug,
+ Eq,
+ FromPrimitive,
+ Hash,
+ MallocSizeOf,
+ PartialEq,
+ ToComputedValue,
+ ToResolvedValue,
+ ToShmem,
+)]
+#[repr(transparent)]
+pub struct Display(u16);
+
+/// Gecko-only impl block for Display (shared stuff later in this file):
+#[allow(missing_docs)]
+#[allow(non_upper_case_globals)]
+impl Display {
+ // Our u16 bits are used as follows: LOOOOOOOIIIIIIII
+ const LIST_ITEM_BIT: u16 = 0x8000; //^
+ const DISPLAY_OUTSIDE_BITS: u16 = 7; // ^^^^^^^
+ const DISPLAY_INSIDE_BITS: u16 = 8; // ^^^^^^^^
+
+ /// https://drafts.csswg.org/css-display/#the-display-properties
+ pub const None: Self = Self::new(DisplayOutside::None, DisplayInside::None);
+ #[cfg(feature = "gecko")]
+ pub const Contents: Self = Self::new(DisplayOutside::None, DisplayInside::Contents);
+ pub const Inline: Self = Self::new(DisplayOutside::Inline, DisplayInside::Inline);
+ pub const InlineBlock: Self = Self::new(DisplayOutside::Inline, DisplayInside::FlowRoot);
+ pub const Block: Self = Self::new(DisplayOutside::Block, DisplayInside::Block);
+ #[cfg(feature = "gecko")]
+ pub const FlowRoot: Self = Self::new(DisplayOutside::Block, DisplayInside::FlowRoot);
+ pub const Flex: Self = Self::new(DisplayOutside::Block, DisplayInside::Flex);
+ pub const InlineFlex: Self = Self::new(DisplayOutside::Inline, DisplayInside::Flex);
+ #[cfg(feature = "gecko")]
+ pub const Grid: Self = Self::new(DisplayOutside::Block, DisplayInside::Grid);
+ #[cfg(feature = "gecko")]
+ pub const InlineGrid: Self = Self::new(DisplayOutside::Inline, DisplayInside::Grid);
+ pub const Table: Self = Self::new(DisplayOutside::Block, DisplayInside::Table);
+ pub const InlineTable: Self = Self::new(DisplayOutside::Inline, DisplayInside::Table);
+ pub const TableCaption: Self = Self::new(DisplayOutside::TableCaption, DisplayInside::Block);
+ #[cfg(feature = "gecko")]
+ pub const Ruby: Self = Self::new(DisplayOutside::Inline, DisplayInside::Ruby);
+ #[cfg(feature = "gecko")]
+ pub const WebkitBox: Self = Self::new(DisplayOutside::Block, DisplayInside::WebkitBox);
+ #[cfg(feature = "gecko")]
+ pub const WebkitInlineBox: Self = Self::new(DisplayOutside::Inline, DisplayInside::WebkitBox);
+ /// Internal table boxes.
+ pub const TableRowGroup: Self =
+ Self::new(DisplayOutside::InternalTable, DisplayInside::TableRowGroup);
+ pub const TableHeaderGroup: Self = Self::new(
+ DisplayOutside::InternalTable,
+ DisplayInside::TableHeaderGroup,
+ );
+ pub const TableFooterGroup: Self = Self::new(
+ DisplayOutside::InternalTable,
+ DisplayInside::TableFooterGroup,
+ );
+ pub const TableColumn: Self =
+ Self::new(DisplayOutside::InternalTable, DisplayInside::TableColumn);
+ pub const TableColumnGroup: Self = Self::new(
+ DisplayOutside::InternalTable,
+ DisplayInside::TableColumnGroup,
+ );
+ pub const TableRow: Self = Self::new(DisplayOutside::InternalTable, DisplayInside::TableRow);
+
+ pub const TableCell: Self = Self::new(DisplayOutside::InternalTable, DisplayInside::TableCell);
+
+ /// Internal ruby boxes.
+ #[cfg(feature = "gecko")]
+ pub const RubyBase: Self = Self::new(DisplayOutside::InternalRuby, DisplayInside::RubyBase);
+ #[cfg(feature = "gecko")]
+ pub const RubyBaseContainer: Self = Self::new(
+ DisplayOutside::InternalRuby,
+ DisplayInside::RubyBaseContainer,
+ );
+ #[cfg(feature = "gecko")]
+ pub const RubyText: Self = Self::new(DisplayOutside::InternalRuby, DisplayInside::RubyText);
+ #[cfg(feature = "gecko")]
+ pub const RubyTextContainer: Self = Self::new(
+ DisplayOutside::InternalRuby,
+ DisplayInside::RubyTextContainer,
+ );
+
+ /// XUL boxes.
+ #[cfg(feature = "gecko")]
+ pub const MozBox: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozBox);
+ #[cfg(feature = "gecko")]
+ pub const MozInlineBox: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozInlineBox);
+ #[cfg(feature = "gecko")]
+ pub const MozGrid: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozGrid);
+ #[cfg(feature = "gecko")]
+ pub const MozInlineGrid: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozInlineGrid);
+ #[cfg(feature = "gecko")]
+ pub const MozGridGroup: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozGridGroup);
+ #[cfg(feature = "gecko")]
+ pub const MozGridLine: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozGridLine);
+ #[cfg(feature = "gecko")]
+ pub const MozStack: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozStack);
+ #[cfg(feature = "gecko")]
+ pub const MozInlineStack: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozInlineStack);
+ #[cfg(feature = "gecko")]
+ pub const MozDeck: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozDeck);
+ #[cfg(feature = "gecko")]
+ pub const MozGroupbox: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozGroupbox);
+ #[cfg(feature = "gecko")]
+ pub const MozPopup: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozPopup);
+
+ /// Make a raw display value from <display-outside> and <display-inside> values.
+ #[inline]
+ const fn new(outside: DisplayOutside, inside: DisplayInside) -> Self {
+ let o: u16 = ((outside as u8) as u16) << Self::DISPLAY_INSIDE_BITS;
+ let i: u16 = (inside as u8) as u16;
+ Self(o | i)
+ }
+
+ /// Make a display enum value from <display-outside> and <display-inside> values.
+ /// We store `flow` as a synthetic `block` or `inline` inside-value to simplify
+ /// our layout code.
+ #[inline]
+ fn from3(outside: DisplayOutside, inside: DisplayInside, list_item: bool) -> Self {
+ let inside = match inside {
+ DisplayInside::Flow => match outside {
+ DisplayOutside::Inline => DisplayInside::Inline,
+ _ => DisplayInside::Block,
+ },
+ _ => inside,
+ };
+ let v = Self::new(outside, inside);
+ if !list_item {
+ return v;
+ }
+ Self(v.0 | Self::LIST_ITEM_BIT)
+ }
+
+ /// Accessor for the <display-inside> value.
+ #[inline]
+ pub fn inside(&self) -> DisplayInside {
+ DisplayInside::from_u16(self.0 & ((1 << Self::DISPLAY_INSIDE_BITS) - 1)).unwrap()
+ }
+
+ /// Accessor for the <display-outside> value.
+ #[inline]
+ pub fn outside(&self) -> DisplayOutside {
+ DisplayOutside::from_u16(
+ (self.0 >> Self::DISPLAY_INSIDE_BITS) & ((1 << Self::DISPLAY_OUTSIDE_BITS) - 1),
+ )
+ .unwrap()
+ }
+
+ /// Returns whether this `display` value is some kind of list-item.
+ #[inline]
+ pub const fn is_list_item(&self) -> bool {
+ (self.0 & Self::LIST_ITEM_BIT) != 0
+ }
+
+ /// Returns whether this `display` value is a ruby level container.
+ pub fn is_ruby_level_container(&self) -> bool {
+ match *self {
+ #[cfg(feature = "gecko")]
+ Display::RubyBaseContainer | Display::RubyTextContainer => true,
+ _ => false,
+ }
+ }
+
+ /// Returns whether this `display` value is one of the types for ruby.
+ pub fn is_ruby_type(&self) -> bool {
+ match self.inside() {
+ #[cfg(feature = "gecko")]
+ DisplayInside::Ruby |
+ DisplayInside::RubyBase |
+ DisplayInside::RubyText |
+ DisplayInside::RubyBaseContainer |
+ DisplayInside::RubyTextContainer => true,
+ _ => false,
+ }
+ }
}
+/// Shared Display impl for both Gecko and Servo.
+#[allow(non_upper_case_globals)]
impl Display {
/// The initial display value.
#[inline]
@@ -183,22 +307,20 @@ impl Display {
pub fn is_atomic_inline_level(&self) -> bool {
match *self {
Display::InlineBlock => true,
- #[cfg(feature = "servo-layout-2013")]
Display::InlineFlex | Display::InlineTable => true,
_ => false,
}
}
- /// Returns whether this "display" value is the display of a flex or
+ /// 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 {
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
- Display::Flex | Display::InlineFlex => true,
+ match self.inside() {
+ DisplayInside::Flex => true,
#[cfg(feature = "gecko")]
- Display::Grid | Display::InlineGrid => true,
+ DisplayInside::Grid => true,
_ => false,
}
}
@@ -215,80 +337,50 @@ impl Display {
}
}
- /// 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.
+ /// Also used for :root style adjustments.
pub fn equivalent_block_display(&self, _is_root_element: bool) -> Self {
- match *self {
- // Values that have a corresponding block-outside version.
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
- Display::InlineTable => Display::Table,
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
- 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 => *self,
- #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))]
- Display::Flex | Display::ListItem | Display::Table => *self,
-
- #[cfg(feature = "gecko")]
- Display::Contents | Display::FlowRoot | Display::Grid | Display::WebkitBox => *self,
+ #[cfg(feature = "gecko")]
+ {
+ // Special handling for `contents` and `list-item`s on the root element.
+ if _is_root_element && (self.is_contents() || self.is_list_item()) {
+ return Display::Block;
+ }
+ }
- // Everything else becomes block.
+ match self.outside() {
+ DisplayOutside::Inline => {
+ let inside = match self.inside() {
+ DisplayInside::Inline | DisplayInside::FlowRoot => DisplayInside::Block,
+ inside => inside,
+ };
+ Display::from3(DisplayOutside::Block, inside, self.is_list_item())
+ },
+ DisplayOutside::Block | DisplayOutside::None => *self,
_ => 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.
+ /// Convert this display into an equivalent inline-outside display.
+ /// https://drafts.csswg.org/css-display/#inlinify
#[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,
- // XXX bug 1105868 this should probably be InlineListItem:
- Display::ListItem => Display::Inline,
- Display::MozBox => Display::MozInlineBox,
- Display::MozStack => Display::MozInlineStack,
- Display::WebkitBox => Display::WebkitInlineBox,
- other => other,
+ match self.outside() {
+ DisplayOutside::Block => {
+ let inside = match self.inside() {
+ DisplayInside::Block => DisplayInside::FlowRoot,
+ inside => inside,
+ };
+ Display::from3(DisplayOutside::Inline, inside, self.is_list_item())
+ },
+ #[cfg(feature = "gecko")]
+ DisplayOutside::XUL => match self.inside() {
+ DisplayInside::MozBox => Display::MozInlineBox,
+ DisplayInside::MozStack => Display::MozInlineStack,
+ _ => *self,
+ },
+ _ => *self,
}
}
@@ -309,6 +401,263 @@ impl Display {
}
}
+impl ToCss for Display {
+ fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
+ where
+ W: fmt::Write,
+ {
+ debug_assert_ne!(
+ self.inside(),
+ DisplayInside::Flow,
+ "`flow` never appears in `display` computed value"
+ );
+ let outside = self.outside();
+ let inside = match self.inside() {
+ DisplayInside::Block | DisplayInside::Inline => DisplayInside::Flow,
+ inside => inside,
+ };
+ match *self {
+ Display::Block | Display::Inline => outside.to_css(dest),
+ Display::InlineBlock => dest.write_str("inline-block"),
+ #[cfg(feature = "gecko")]
+ Display::WebkitInlineBox => dest.write_str("-webkit-inline-box"),
+ #[cfg(feature = "gecko")]
+ Display::MozInlineBox => dest.write_str("-moz-inline-box"),
+ #[cfg(feature = "gecko")]
+ Display::MozInlineGrid => dest.write_str("-moz-inline-grid"),
+ #[cfg(feature = "gecko")]
+ Display::MozInlineStack => dest.write_str("-moz-inline-stack"),
+ Display::TableCaption => dest.write_str("table-caption"),
+ _ => match (outside, inside) {
+ #[cfg(feature = "gecko")]
+ (DisplayOutside::Inline, DisplayInside::Grid) => dest.write_str("inline-grid"),
+ (DisplayOutside::Inline, DisplayInside::Flex) |
+ (DisplayOutside::Inline, DisplayInside::Table) => {
+ dest.write_str("inline-")?;
+ inside.to_css(dest)
+ },
+ #[cfg(feature = "gecko")]
+ (DisplayOutside::Block, DisplayInside::Ruby) => dest.write_str("block ruby"),
+ (_, inside) => {
+ if self.is_list_item() {
+ if outside != DisplayOutside::Block {
+ outside.to_css(dest)?;
+ dest.write_str(" ")?;
+ }
+ if inside != DisplayInside::Flow {
+ inside.to_css(dest)?;
+ dest.write_str(" ")?;
+ }
+ dest.write_str("list-item")
+ } else {
+ inside.to_css(dest)
+ }
+ },
+ },
+ }
+ }
+}
+
+/// <display-inside> = flow | flow-root | table | flex | grid | ruby
+/// https://drafts.csswg.org/css-display/#typedef-display-inside
+fn parse_display_inside<'i, 't>(
+ input: &mut Parser<'i, 't>,
+) -> Result<DisplayInside, ParseError<'i>> {
+ Ok(try_match_ident_ignore_ascii_case! { input,
+ "flow" => DisplayInside::Flow,
+ #[cfg(feature = "gecko")]
+ "flow-root" => DisplayInside::FlowRoot,
+ "table" => DisplayInside::Table,
+ "flex" => DisplayInside::Flex,
+ #[cfg(feature = "gecko")]
+ "grid" => DisplayInside::Grid,
+ #[cfg(feature = "gecko")]
+ "ruby" => DisplayInside::Ruby,
+ })
+}
+
+/// <display-outside> = block | inline | run-in
+/// https://drafts.csswg.org/css-display/#typedef-display-outside
+fn parse_display_outside<'i, 't>(
+ input: &mut Parser<'i, 't>,
+) -> Result<DisplayOutside, ParseError<'i>> {
+ Ok(try_match_ident_ignore_ascii_case! { input,
+ "block" => DisplayOutside::Block,
+ "inline" => DisplayOutside::Inline,
+ // FIXME(bug 2056): not supported in layout yet:
+ //"run-in" => DisplayOutside::RunIn,
+ })
+}
+
+/// (flow | flow-root)?
+fn parse_display_inside_for_list_item<'i, 't>(
+ input: &mut Parser<'i, 't>,
+) -> Result<DisplayInside, ParseError<'i>> {
+ Ok(try_match_ident_ignore_ascii_case! { input,
+ "flow" => DisplayInside::Flow,
+ #[cfg(feature = "gecko")]
+ "flow-root" => DisplayInside::FlowRoot,
+ })
+}
+/// Test a <display-inside> Result for same values as above.
+fn is_valid_inside_for_list_item<'i>(inside: &Result<DisplayInside, ParseError<'i>>) -> bool {
+ match inside {
+ Ok(DisplayInside::Flow) => true,
+ #[cfg(feature = "gecko")]
+ Ok(DisplayInside::FlowRoot) => true,
+ _ => false,
+ }
+}
+
+/// Parse `list-item`.
+fn parse_list_item<'i, 't>(input: &mut Parser<'i, 't>) -> Result<(), ParseError<'i>> {
+ Ok(try_match_ident_ignore_ascii_case! { input,
+ "list-item" => (),
+ })
+}
+
+impl Parse for Display {
+ #[allow(unused)] // `context` isn't used for servo-2020 for now
+ fn parse<'i, 't>(
+ context: &ParserContext,
+ input: &mut Parser<'i, 't>,
+ ) -> Result<Display, ParseError<'i>> {
+ // Parse all combinations of <display-inside/outside>? and `list-item`? first.
+ let mut got_list_item = input.try(parse_list_item).is_ok();
+ let mut inside = if got_list_item {
+ input.try(parse_display_inside_for_list_item)
+ } else {
+ input.try(parse_display_inside)
+ };
+ // <display-listitem> = <display-outside>? && [ flow | flow-root ]? && list-item
+ // https://drafts.csswg.org/css-display/#typedef-display-listitem
+ if !got_list_item && is_valid_inside_for_list_item(&inside) {
+ got_list_item = input.try(parse_list_item).is_ok();
+ }
+ let outside = input.try(parse_display_outside);
+ if outside.is_ok() {
+ if !got_list_item && (inside.is_err() || is_valid_inside_for_list_item(&inside)) {
+ got_list_item = input.try(parse_list_item).is_ok();
+ }
+ if inside.is_err() {
+ inside = if got_list_item {
+ input.try(parse_display_inside_for_list_item)
+ } else {
+ input.try(parse_display_inside)
+ };
+ if !got_list_item && is_valid_inside_for_list_item(&inside) {
+ got_list_item = input.try(parse_list_item).is_ok();
+ }
+ }
+ }
+ if got_list_item || inside.is_ok() || outside.is_ok() {
+ let inside = inside.unwrap_or(DisplayInside::Flow);
+ let outside = outside.unwrap_or(match inside {
+ // "If <display-outside> is omitted, the element’s outside display type
+ // defaults to block — except for ruby, which defaults to inline."
+ // https://drafts.csswg.org/css-display/#inside-model
+ #[cfg(feature = "gecko")]
+ DisplayInside::Ruby => DisplayOutside::Inline,
+ _ => DisplayOutside::Block,
+ });
+ return Ok(Display::from3(outside, inside, got_list_item));
+ }
+
+ // Now parse the single-keyword `display` values.
+ Ok(try_match_ident_ignore_ascii_case! { input,
+ "none" => Display::None,
+ #[cfg(feature = "gecko")]
+ "contents" => Display::Contents,
+ "inline-block" => Display::InlineBlock,
+ "inline-table" => Display::InlineTable,
+ "-webkit-flex" => Display::Flex,
+ "inline-flex" | "-webkit-inline-flex" => Display::InlineFlex,
+ #[cfg(feature = "gecko")]
+ "inline-grid" => Display::InlineGrid,
+ "table-caption" => Display::TableCaption,
+ "table-row-group" => Display::TableRowGroup,
+ "table-header-group" => Display::TableHeaderGroup,
+ "table-footer-group" => Display::TableFooterGroup,
+ "table-column" => Display::TableColumn,
+ "table-column-group" => Display::TableColumnGroup,
+ "table-row" => Display::TableRow,
+ "table-cell" => Display::TableCell,
+ #[cfg(feature = "gecko")]
+ "ruby-base" => Display::RubyBase,
+ #[cfg(feature = "gecko")]
+ "ruby-base-container" => Display::RubyBaseContainer,
+ #[cfg(feature = "gecko")]
+ "ruby-text" => Display::RubyText,
+ #[cfg(feature = "gecko")]
+ "ruby-text-container" => Display::RubyTextContainer,
+ #[cfg(feature = "gecko")]
+ "-webkit-box" => Display::WebkitBox,
+ #[cfg(feature = "gecko")]
+ "-webkit-inline-box" => Display::WebkitInlineBox,
+ #[cfg(feature = "gecko")]
+ "-moz-box" if moz_box_display_values_enabled(context) => Display::MozBox,
+ #[cfg(feature = "gecko")]
+ "-moz-inline-box" if moz_box_display_values_enabled(context) => Display::MozInlineBox,
+ #[cfg(feature = "gecko")]
+ "-moz-grid" if moz_display_values_enabled(context) => Display::MozGrid,
+ #[cfg(feature = "gecko")]
+ "-moz-inline-grid" if moz_display_values_enabled(context) => Display::MozInlineGrid,
+ #[cfg(feature = "gecko")]
+ "-moz-grid-group" if moz_display_values_enabled(context) => Display::MozGridGroup,
+ #[cfg(feature = "gecko")]
+ "-moz-grid-line" if moz_display_values_enabled(context) => Display::MozGridLine,
+ #[cfg(feature = "gecko")]
+ "-moz-stack" if moz_display_values_enabled(context) => Display::MozStack,
+ #[cfg(feature = "gecko")]
+ "-moz-inline-stack" if moz_display_values_enabled(context) => Display::MozInlineStack,
+ #[cfg(feature = "gecko")]
+ "-moz-deck" if moz_display_values_enabled(context) => Display::MozDeck,
+ #[cfg(feature = "gecko")]
+ "-moz-groupbox" if moz_display_values_enabled(context) => Display::MozGroupbox,
+ #[cfg(feature = "gecko")]
+ "-moz-popup" if moz_display_values_enabled(context) => Display::MozPopup,
+ })
+ }
+}
+
+impl SpecifiedValueInfo for Display {
+ fn collect_completion_keywords(f: KeywordsCollectFn) {
+ f(&[
+ "block",
+ "contents",
+ "flex",
+ "flow-root",
+ "grid",
+ "inline",
+ "inline-block",
+ "inline-flex",
+ "inline-grid",
+ "inline-table",
+ "inline list-item",
+ "inline flow-root list-item",
+ "list-item",
+ "none",
+ "block ruby",
+ "ruby",
+ "ruby-base",
+ "ruby-base-container",
+ "ruby-text",
+ "ruby-text-container",
+ "table",
+ "table-caption",
+ "table-cell",
+ "table-column",
+ "table-column-group",
+ "table-footer-group",
+ "table-header-group",
+ "table-row",
+ "table-row-group",
+ "-webkit-box",
+ "-webkit-inline-box",
+ ]);
+ }
+}
+
/// A specified value for the `vertical-align` property.
pub type VerticalAlign = GenericVerticalAlign<LengthPercentage>;
diff --git a/components/style/values/specified/grid.rs b/components/style/values/specified/grid.rs
index 3e7f8f72a00..b75e97aca99 100644
--- a/components/style/values/specified/grid.rs
+++ b/components/style/values/specified/grid.rs
@@ -6,10 +6,9 @@
//! [grids](https://drafts.csswg.org/css-grid/)
use crate::parser::{Parse, ParserContext};
-use crate::values::computed::{self, Context, ToComputedValue};
-use crate::values::generics::grid::{GridTemplateComponent, RepeatCount, TrackBreadth};
-use crate::values::generics::grid::{LineNameList, TrackRepeat, TrackSize};
-use crate::values::generics::grid::{TrackList, TrackListType, TrackListValue};
+use crate::values::generics::grid::{GridTemplateComponent, ImplicitGridTracks, RepeatCount};
+use crate::values::generics::grid::{LineNameList, TrackBreadth, TrackRepeat, TrackSize};
+use crate::values::generics::grid::{TrackList, TrackListValue};
use crate::values::specified::{Integer, LengthPercentage};
use crate::values::{CSSFloat, CustomIdent};
use cssparser::{ParseError as CssParseError, Parser, Token};
@@ -96,12 +95,27 @@ impl Parse for TrackSize<LengthPercentage> {
}
}
+impl Parse for ImplicitGridTracks<TrackSize<LengthPercentage>> {
+ fn parse<'i, 't>(
+ context: &ParserContext,
+ input: &mut Parser<'i, 't>,
+ ) -> Result<Self, ParseError<'i>> {
+ use style_traits::{Separator, Space};
+ let track_sizes = Space::parse(input, |i| TrackSize::parse(context, i))?;
+ if track_sizes.len() == 1 && track_sizes[0].is_auto() {
+ //`auto`, which is the initial value, is always represented by an empty slice.
+ return Ok(Default::default());
+ }
+ return Ok(ImplicitGridTracks(track_sizes.into()));
+ }
+}
+
/// Parse the grid line names into a vector of owned strings.
///
/// <https://drafts.csswg.org/css-grid/#typedef-line-names>
pub fn parse_line_names<'i, 't>(
input: &mut Parser<'i, 't>,
-) -> Result<Box<[CustomIdent]>, ParseError<'i>> {
+) -> Result<crate::OwnedSlice<CustomIdent>, ParseError<'i>> {
input.expect_square_bracket_block()?;
input.parse_nested_block(|input| {
let mut values = vec![];
@@ -112,7 +126,7 @@ pub fn parse_line_names<'i, 't>(
values.push(ident);
}
- Ok(values.into_boxed_slice())
+ Ok(values.into())
})
}
@@ -155,9 +169,7 @@ impl TrackRepeat<LengthPercentage, Integer> {
let mut current_names;
loop {
- current_names = input
- .try(parse_line_names)
- .unwrap_or(vec![].into_boxed_slice());
+ current_names = input.try(parse_line_names).unwrap_or_default();
if let Ok(track_size) = input.try(|i| TrackSize::parse(context, i)) {
if !track_size.is_fixed() {
if is_auto {
@@ -180,11 +192,7 @@ impl TrackRepeat<LengthPercentage, Integer> {
// one `TrackSize`. But in current version of the spec, this is deprecated
// but we are adding this for gecko parity. We should remove this when
// gecko implements new spec.
- names.push(
- input
- .try(parse_line_names)
- .unwrap_or(vec![].into_boxed_slice()),
- );
+ names.push(input.try(parse_line_names).unwrap_or_default());
break;
}
} else {
@@ -201,9 +209,9 @@ impl TrackRepeat<LengthPercentage, Integer> {
}
let repeat = TrackRepeat {
- count: count,
- track_sizes: values,
- line_names: names.into_boxed_slice(),
+ count,
+ track_sizes: values.into(),
+ line_names: names.into(),
};
Ok((repeat, repeat_type))
@@ -221,47 +229,31 @@ impl Parse for TrackList<LengthPercentage, Integer> {
let mut names = vec![];
let mut values = vec![];
- // assume it's the simplest case.
- let mut list_type = TrackListType::Explicit;
- // holds <auto-repeat> value. It can only be only one in a TrackList.
- let mut auto_repeat = None;
- // if there is any <auto-repeat> the list will be of type TrackListType::Auto(idx)
- // where idx points to the position of the <auto-repeat> in the track list. If there
- // is any repeat before <auto-repeat>, we need to take the number of repetitions into
- // account to set the position of <auto-repeat> so it remains the same while computing
- // values.
- let mut auto_offset = 0;
+ // Whether we've parsed an `<auto-repeat>` value.
+ let mut auto_repeat_index = None;
// assume that everything is <fixed-size>. This flag is useful when we encounter <auto-repeat>
- let mut atleast_one_not_fixed = false;
+ let mut at_least_one_not_fixed = false;
loop {
- current_names.extend_from_slice(
- &mut input
- .try(parse_line_names)
- .unwrap_or(vec![].into_boxed_slice()),
- );
+ current_names.extend_from_slice(&mut input.try(parse_line_names).unwrap_or_default());
if let Ok(track_size) = input.try(|i| TrackSize::parse(context, i)) {
if !track_size.is_fixed() {
- atleast_one_not_fixed = true;
- if auto_repeat.is_some() {
+ at_least_one_not_fixed = true;
+ if auto_repeat_index.is_some() {
// <auto-track-list> only accepts <fixed-size> and <fixed-repeat>
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
}
let vec = mem::replace(&mut current_names, vec![]);
- names.push(vec.into_boxed_slice());
+ names.push(vec.into());
values.push(TrackListValue::TrackSize(track_size));
} else if let Ok((repeat, type_)) =
input.try(|i| TrackRepeat::parse_with_repeat_type(context, i))
{
- if list_type == TrackListType::Explicit {
- list_type = TrackListType::Normal; // <explicit-track-list> doesn't contain repeat()
- }
-
match type_ {
RepeatType::Normal => {
- atleast_one_not_fixed = true;
- if auto_repeat.is_some() {
+ at_least_one_not_fixed = true;
+ if auto_repeat_index.is_some() {
// only <fixed-repeat>
return Err(
input.new_custom_error(StyleParseErrorKind::UnspecifiedError)
@@ -269,137 +261,42 @@ impl Parse for TrackList<LengthPercentage, Integer> {
}
},
RepeatType::Auto => {
- if auto_repeat.is_some() || atleast_one_not_fixed {
+ if auto_repeat_index.is_some() || at_least_one_not_fixed {
// We've either seen <auto-repeat> earlier, or there's at least one non-fixed value
return Err(
input.new_custom_error(StyleParseErrorKind::UnspecifiedError)
);
}
-
- list_type = TrackListType::Auto(values.len() as u16 + auto_offset);
- auto_repeat = Some(repeat);
- let vec = mem::replace(&mut current_names, vec![]);
- names.push(vec.into_boxed_slice());
- continue;
+ auto_repeat_index = Some(values.len());
},
- RepeatType::Fixed => (),
+ RepeatType::Fixed => {},
}
let vec = mem::replace(&mut current_names, vec![]);
- names.push(vec.into_boxed_slice());
- if let RepeatCount::Number(num) = repeat.count {
- auto_offset += (num.value() - 1) as u16;
- }
+ names.push(vec.into());
values.push(TrackListValue::TrackRepeat(repeat));
} else {
- if values.is_empty() && auto_repeat.is_none() {
+ if values.is_empty() && auto_repeat_index.is_none() {
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
- names.push(current_names.into_boxed_slice());
+ names.push(current_names.into());
break;
}
}
Ok(TrackList {
- list_type: list_type,
- values: values,
- line_names: names.into_boxed_slice(),
- auto_repeat: auto_repeat,
+ auto_repeat_index: auto_repeat_index.unwrap_or(std::usize::MAX),
+ values: values.into(),
+ line_names: names.into(),
})
}
}
-impl ToComputedValue for TrackList<LengthPercentage, Integer> {
- type ComputedValue = TrackList<computed::LengthPercentage, computed::Integer>;
-
- #[inline]
- fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
- // Merge the line names while computing values. The resulting values will
- // all be bunch of `<track-size>` and one <auto-repeat>.
- //
- // For example,
- // `[a b] 100px [c d] repeat(1, 30px [g]) [h]` will be merged as `[a b] 100px [c d] 30px [g h]`
- // whereas, `[a b] repeat(2, [c] 50px [d]) [e f] repeat(auto-fill, [g] 12px) 10px [h]` will be merged as
- // `[a b c] 50px [d c] 50px [d e f] repeat(auto-fill, [g] 12px) 10px [h]`, with the `<auto-repeat>` value
- // set in the `auto_repeat` field, and the `idx` in TrackListType::Auto pointing to the values after
- // `<auto-repeat>` (in this case, `10px [h]`).
- let mut prev_names = vec![];
- let mut line_names = Vec::with_capacity(self.line_names.len() + 1);
- let mut values = Vec::with_capacity(self.values.len() + 1);
- for (pos, names) in self.line_names.iter().enumerate() {
- prev_names.extend_from_slice(&names);
- if pos >= self.values.len() {
- let vec = mem::replace(&mut prev_names, vec![]);
- line_names.push(vec.into_boxed_slice());
- continue;
- }
-
- match self.values[pos] {
- TrackListValue::TrackSize(ref size) => {
- let vec = mem::replace(&mut prev_names, vec![]);
- line_names.push(vec.into_boxed_slice());
- values.push(TrackListValue::TrackSize(size.to_computed_value(context)));
- },
- TrackListValue::TrackRepeat(ref repeat) => {
- // If the repeat count is numeric, we expand and merge the values.
- let mut repeat = repeat.expand();
- let mut repeat_names_iter = repeat.line_names.iter();
- for (size, repeat_names) in
- repeat.track_sizes.drain(..).zip(&mut repeat_names_iter)
- {
- prev_names.extend_from_slice(&repeat_names);
- let vec = mem::replace(&mut prev_names, vec![]);
- line_names.push(vec.into_boxed_slice());
- values.push(TrackListValue::TrackSize(size.to_computed_value(context)));
- }
-
- if let Some(names) = repeat_names_iter.next() {
- prev_names.extend_from_slice(&names);
- }
- },
- }
- }
-
- TrackList {
- list_type: self.list_type.to_computed_value(context),
- values: values,
- line_names: line_names.into_boxed_slice(),
- auto_repeat: self
- .auto_repeat
- .clone()
- .map(|repeat| repeat.to_computed_value(context)),
- }
- }
-
- #[inline]
- fn from_computed_value(computed: &Self::ComputedValue) -> Self {
- let mut values = Vec::with_capacity(computed.values.len() + 1);
- for value in computed
- .values
- .iter()
- .map(ToComputedValue::from_computed_value)
- {
- values.push(value);
- }
-
- TrackList {
- list_type: computed.list_type,
- values: values,
- line_names: computed.line_names.clone(),
- auto_repeat: computed
- .auto_repeat
- .clone()
- .map(|ref repeat| TrackRepeat::from_computed_value(repeat)),
- }
- }
-}
-
#[cfg(feature = "gecko")]
#[inline]
fn allow_grid_template_subgrids() -> bool {
- use crate::gecko_bindings::structs::mozilla;
- unsafe { mozilla::StaticPrefs::sVarCache_layout_css_grid_template_subgrid_value_enabled }
+ static_prefs::pref!("layout.css.grid-template-subgrid-value.enabled")
}
#[cfg(feature = "servo")]
@@ -409,7 +306,6 @@ fn allow_grid_template_subgrids() -> bool {
}
impl Parse for GridTemplateComponent<LengthPercentage, Integer> {
- // FIXME: Derive Parse (probably with None_)
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
@@ -430,10 +326,11 @@ impl GridTemplateComponent<LengthPercentage, Integer> {
) -> Result<Self, ParseError<'i>> {
if allow_grid_template_subgrids() {
if let Ok(t) = input.try(|i| LineNameList::parse(context, i)) {
- return Ok(GridTemplateComponent::Subgrid(t));
+ return Ok(GridTemplateComponent::Subgrid(Box::new(t)));
}
}
- TrackList::parse(context, input).map(GridTemplateComponent::TrackList)
+ let track_list = TrackList::parse(context, input)?;
+ Ok(GridTemplateComponent::TrackList(Box::new(track_list)))
}
}
diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs
index f33a191c277..16897043da9 100644
--- a/components/style/values/specified/mod.rs
+++ b/components/style/values/specified/mod.rs
@@ -8,6 +8,7 @@
use super::computed::transform::DirectionVector;
use super::computed::{Context, ToComputedValue};
+use super::generics::grid::ImplicitGridTracks as GenericImplicitGridTracks;
use super::generics::grid::{GridLine as GenericGridLine, TrackBreadth as GenericTrackBreadth};
use super::generics::grid::{TrackList as GenericTrackList, TrackSize as GenericTrackSize};
use super::generics::transform::IsParallelTo;
@@ -69,7 +70,7 @@ pub use self::list::Quotes;
pub use self::motion::{OffsetPath, OffsetRotate};
pub use self::outline::OutlineStyle;
pub use self::percentage::Percentage;
-pub use self::position::{GridAutoFlow, GridTemplateAreas, Position};
+pub use self::position::{GridAutoFlow, GridTemplateAreas, Position, PositionOrAuto};
pub use self::position::{PositionComponent, ZIndex};
pub use self::rect::NonNegativeLengthOrNumberRect;
pub use self::resolution::Resolution;
@@ -81,7 +82,7 @@ pub use self::table::XSpan;
pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight, TextAlign};
pub use self::text::{OverflowWrap, TextEmphasisPosition, TextEmphasisStyle, WordBreak};
pub use self::text::{TextAlignKeyword, TextDecorationLine, TextOverflow, WordSpacing};
-pub use self::text::{TextDecorationSkipInk, TextTransform};
+pub use self::text::{TextDecorationLength, TextDecorationSkipInk, TextTransform};
pub use self::time::Time;
pub use self::transform::{Rotate, Scale, Transform};
pub use self::transform::{TransformOrigin, TransformStyle, Translate};
@@ -626,6 +627,9 @@ pub type TrackBreadth = GenericTrackBreadth<LengthPercentage>;
/// The specified value of a grid `<track-size>`
pub type TrackSize = GenericTrackSize<LengthPercentage>;
+/// The specified value of a grid `<track-size>+`
+pub type ImplicitGridTracks = GenericImplicitGridTracks<TrackSize>;
+
/// The specified value of a grid `<track-list>`
/// (could also be `<auto-track-list>` or `<explicit-track-list>`)
pub type TrackList = GenericTrackList<LengthPercentage, Integer>;
diff --git a/components/style/values/specified/position.rs b/components/style/values/specified/position.rs
index 4e6a71ec2ca..ce3bab1047b 100644
--- a/components/style/values/specified/position.rs
+++ b/components/style/values/specified/position.rs
@@ -13,6 +13,7 @@ use crate::str::HTML_SPACE_CHARACTERS;
use crate::values::computed::LengthPercentage as ComputedLengthPercentage;
use crate::values::computed::{Context, Percentage, ToComputedValue};
use crate::values::generics::position::Position as GenericPosition;
+use crate::values::generics::position::PositionOrAuto as GenericPositionOrAuto;
use crate::values::generics::position::ZIndex as GenericZIndex;
use crate::values::specified::{AllowQuirks, Integer, LengthPercentage};
use crate::Atom;
@@ -26,6 +27,9 @@ use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
/// The specified value of a CSS `<position>`
pub type Position = GenericPosition<HorizontalPosition, VerticalPosition>;
+/// The specified value of an `auto | <position>`.
+pub type PositionOrAuto = GenericPositionOrAuto<Position>;
+
/// The specified value of a horizontal position.
pub type HorizontalPosition = PositionComponent<HorizontalPositionKeyword>;
diff --git a/components/style/values/specified/svg.rs b/components/style/values/specified/svg.rs
index 9279707935f..4858fbaec6b 100644
--- a/components/style/values/specified/svg.rs
+++ b/components/style/values/specified/svg.rs
@@ -32,8 +32,7 @@ pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeLengthPerce
/// Whether the `context-value` value is enabled.
#[cfg(feature = "gecko")]
pub fn is_context_value_enabled() -> bool {
- use crate::gecko_bindings::structs::mozilla;
- unsafe { mozilla::StaticPrefs::sVarCache_gfx_font_rendering_opentype_svg_enabled }
+ static_prefs::pref!("gfx.font_rendering.opentype_svg.enabled")
}
/// Whether the `context-value` value is enabled.
diff --git a/components/style/values/specified/svg_path.rs b/components/style/values/specified/svg_path.rs
index e5282e0a164..4f49029b51e 100644
--- a/components/style/values/specified/svg_path.rs
+++ b/components/style/values/specified/svg_path.rs
@@ -625,40 +625,26 @@ impl<'a> PathParser<'a> {
break;
}
- match self.chars.next() {
- Some(command) => {
- let abs = if command.is_ascii_uppercase() {
- IsAbsolute::Yes
- } else {
- IsAbsolute::No
- };
- macro_rules! parse_command {
- ( $($($p:pat)|+ => $parse_func:ident,)* ) => {
- match command {
- $(
- $($p)|+ => {
- skip_wsp(&mut self.chars);
- self.$parse_func(abs)?;
- },
- )*
- _ => return Err(()),
- }
- }
- }
- parse_command!(
- b'Z' | b'z' => parse_closepath,
- b'L' | b'l' => parse_lineto,
- b'H' | b'h' => parse_h_lineto,
- b'V' | b'v' => parse_v_lineto,
- b'C' | b'c' => parse_curveto,
- b'S' | b's' => parse_smooth_curveto,
- b'Q' | b'q' => parse_quadratic_bezier_curveto,
- b'T' | b't' => parse_smooth_quadratic_bezier_curveto,
- b'A' | b'a' => parse_elliptical_arc,
- );
- },
- _ => break, // no more commands.
- }
+ let command = self.chars.next().unwrap();
+ let abs = if command.is_ascii_uppercase() {
+ IsAbsolute::Yes
+ } else {
+ IsAbsolute::No
+ };
+
+ skip_wsp(&mut self.chars);
+ match command {
+ b'Z' | b'z' => self.parse_closepath(),
+ b'L' | b'l' => self.parse_lineto(abs),
+ b'H' | b'h' => self.parse_h_lineto(abs),
+ b'V' | b'v' => self.parse_v_lineto(abs),
+ b'C' | b'c' => self.parse_curveto(abs),
+ b'S' | b's' => self.parse_smooth_curveto(abs),
+ b'Q' | b'q' => self.parse_quadratic_bezier_curveto(abs),
+ b'T' | b't' => self.parse_smooth_quadratic_bezier_curveto(abs),
+ b'A' | b'a' => self.parse_elliptical_arc(abs),
+ _ => return Err(()),
+ }?;
}
Ok(())
}
@@ -692,7 +678,7 @@ impl<'a> PathParser<'a> {
}
/// Parse "closepath" command.
- fn parse_closepath(&mut self, _absolute: IsAbsolute) -> Result<(), ()> {
+ fn parse_closepath(&mut self) -> Result<(), ()> {
self.path.push(PathCommand::ClosePath);
Ok(())
}
diff --git a/components/style/values/specified/text.rs b/components/style/values/specified/text.rs
index c66e93803f6..1686b9f424d 100644
--- a/components/style/values/specified/text.rs
+++ b/components/style/values/specified/text.rs
@@ -7,13 +7,12 @@
use crate::parser::{Parse, ParserContext};
use crate::properties::longhands::writing_mode::computed_value::T as SpecifiedWritingMode;
use crate::values::computed::text::LineHeight as ComputedLineHeight;
-use crate::values::computed::text::TextEmphasisKeywordValue as ComputedTextEmphasisKeywordValue;
use crate::values::computed::text::TextEmphasisStyle as ComputedTextEmphasisStyle;
use crate::values::computed::text::TextOverflow as ComputedTextOverflow;
use crate::values::computed::{Context, ToComputedValue};
use crate::values::generics::text::InitialLetter as GenericInitialLetter;
use crate::values::generics::text::LineHeight as GenericLineHeight;
-use crate::values::generics::text::Spacing;
+use crate::values::generics::text::{GenericTextDecorationLength, Spacing};
use crate::values::specified::length::NonNegativeLengthPercentage;
use crate::values::specified::length::{FontRelativeLength, Length};
use crate::values::specified::length::{LengthPercentage, NoCalcLength};
@@ -645,48 +644,34 @@ impl ToComputedValue for TextAlign {
}
}
+fn fill_mode_is_default_and_shape_exists(
+ fill: &TextEmphasisFillMode,
+ shape: &Option<TextEmphasisShapeKeyword>,
+) -> bool {
+ shape.is_some() && fill.is_filled()
+}
+
/// Specified value of text-emphasis-style property.
+///
+/// https://drafts.csswg.org/css-text-decor/#propdef-text-emphasis-style
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
+#[allow(missing_docs)]
pub enum TextEmphasisStyle {
- /// <fill> <shape>
- Keyword(TextEmphasisKeywordValue),
+ /// [ <fill> || <shape> ]
+ Keyword {
+ #[css(contextual_skip_if = "fill_mode_is_default_and_shape_exists")]
+ fill: TextEmphasisFillMode,
+ shape: Option<TextEmphasisShapeKeyword>,
+ },
/// `none`
None,
- /// String (will be used only first grapheme cluster) for the text-emphasis-style property
- String(String),
-}
-
-/// Keyword value for the text-emphasis-style property
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
-pub enum TextEmphasisKeywordValue {
- /// <fill>
- Fill(TextEmphasisFillMode),
- /// <shape>
- Shape(TextEmphasisShapeKeyword),
- /// <fill> <shape>
- FillAndShape(TextEmphasisFillMode, TextEmphasisShapeKeyword),
-}
-
-impl TextEmphasisKeywordValue {
- fn fill(&self) -> Option<TextEmphasisFillMode> {
- match *self {
- TextEmphasisKeywordValue::Fill(fill) |
- TextEmphasisKeywordValue::FillAndShape(fill, _) => Some(fill),
- _ => None,
- }
- }
-
- fn shape(&self) -> Option<TextEmphasisShapeKeyword> {
- match *self {
- TextEmphasisKeywordValue::Shape(shape) |
- TextEmphasisKeywordValue::FillAndShape(_, shape) => Some(shape),
- _ => None,
- }
- }
+ /// `<string>` (of which only the first grapheme cluster will be used).
+ String(crate::OwnedStr),
}
/// Fill mode for the text-emphasis-style property
#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
+#[repr(u8)]
pub enum TextEmphasisFillMode {
/// `filled`
Filled,
@@ -694,10 +679,19 @@ pub enum TextEmphasisFillMode {
Open,
}
+impl TextEmphasisFillMode {
+ /// Whether the value is `filled`.
+ #[inline]
+ pub fn is_filled(&self) -> bool {
+ matches!(*self, TextEmphasisFillMode::Filled)
+ }
+}
+
/// Shape keyword for the text-emphasis-style property
#[derive(
Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem,
)]
+#[repr(u8)]
pub enum TextEmphasisShapeKeyword {
/// `dot`
Dot,
@@ -711,77 +705,39 @@ pub enum TextEmphasisShapeKeyword {
Sesame,
}
-impl TextEmphasisShapeKeyword {
- /// converts fill mode to a unicode char
- pub fn char(&self, fill: TextEmphasisFillMode) -> &str {
- let fill = fill == TextEmphasisFillMode::Filled;
- match *self {
- TextEmphasisShapeKeyword::Dot => {
- if fill {
- "\u{2022}"
- } else {
- "\u{25e6}"
- }
- },
- TextEmphasisShapeKeyword::Circle => {
- if fill {
- "\u{25cf}"
- } else {
- "\u{25cb}"
- }
- },
- TextEmphasisShapeKeyword::DoubleCircle => {
- if fill {
- "\u{25c9}"
- } else {
- "\u{25ce}"
- }
- },
- TextEmphasisShapeKeyword::Triangle => {
- if fill {
- "\u{25b2}"
- } else {
- "\u{25b3}"
- }
- },
- TextEmphasisShapeKeyword::Sesame => {
- if fill {
- "\u{fe45}"
- } else {
- "\u{fe46}"
- }
- },
- }
- }
-}
-
impl ToComputedValue for TextEmphasisStyle {
type ComputedValue = ComputedTextEmphasisStyle;
#[inline]
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
match *self {
- TextEmphasisStyle::Keyword(ref keyword) => {
- // FIXME(emilio): This should set the rule_cache_conditions
- // properly.
- let default_shape = if context.style().get_inherited_box().clone_writing_mode() ==
- SpecifiedWritingMode::HorizontalTb
- {
- TextEmphasisShapeKeyword::Circle
- } else {
- TextEmphasisShapeKeyword::Sesame
- };
- ComputedTextEmphasisStyle::Keyword(ComputedTextEmphasisKeywordValue {
- fill: keyword.fill().unwrap_or(TextEmphasisFillMode::Filled),
- shape: keyword.shape().unwrap_or(default_shape),
- })
+ TextEmphasisStyle::Keyword { fill, shape } => {
+ let shape = shape.unwrap_or_else(|| {
+ // FIXME(emilio, bug 1572958): This should set the
+ // rule_cache_conditions properly.
+ //
+ // Also should probably use WritingMode::is_vertical rather
+ // than the computed value of the `writing-mode` property.
+ if context.style().get_inherited_box().clone_writing_mode() ==
+ SpecifiedWritingMode::HorizontalTb
+ {
+ TextEmphasisShapeKeyword::Circle
+ } else {
+ TextEmphasisShapeKeyword::Sesame
+ }
+ });
+ ComputedTextEmphasisStyle::Keyword { fill, shape }
},
TextEmphasisStyle::None => ComputedTextEmphasisStyle::None,
TextEmphasisStyle::String(ref s) => {
// Passing `true` to iterate over extended grapheme clusters, following
// recommendation at http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries
- let string = s.graphemes(true).next().unwrap_or("").to_string();
- ComputedTextEmphasisStyle::String(string)
+ //
+ // FIXME(emilio): Doing this at computed value time seems wrong.
+ // The spec doesn't say that this should be a computed-value
+ // time operation. This is observable from getComputedStyle().
+ let s = s.graphemes(true).next().unwrap_or("").to_string();
+ ComputedTextEmphasisStyle::String(s.into())
},
}
}
@@ -789,9 +745,10 @@ impl ToComputedValue for TextEmphasisStyle {
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
match *computed {
- ComputedTextEmphasisStyle::Keyword(ref keyword) => TextEmphasisStyle::Keyword(
- TextEmphasisKeywordValue::FillAndShape(keyword.fill, keyword.shape),
- ),
+ ComputedTextEmphasisStyle::Keyword { fill, shape } => TextEmphasisStyle::Keyword {
+ fill,
+ shape: Some(shape),
+ },
ComputedTextEmphasisStyle::None => TextEmphasisStyle::None,
ComputedTextEmphasisStyle::String(ref string) => {
TextEmphasisStyle::String(string.clone())
@@ -814,7 +771,7 @@ impl Parse for TextEmphasisStyle {
if let Ok(s) = input.try(|i| i.expect_string().map(|s| s.as_ref().to_owned())) {
// Handle <string>
- return Ok(TextEmphasisStyle::String(s));
+ return Ok(TextEmphasisStyle::String(s.into()));
}
// Handle a pair of keywords
@@ -824,14 +781,17 @@ impl Parse for TextEmphasisStyle {
shape = input.try(TextEmphasisShapeKeyword::parse).ok();
}
- // At least one of shape or fill must be handled
- let keyword_value = match (fill, shape) {
- (Some(fill), Some(shape)) => TextEmphasisKeywordValue::FillAndShape(fill, shape),
- (Some(fill), None) => TextEmphasisKeywordValue::Fill(fill),
- (None, Some(shape)) => TextEmphasisKeywordValue::Shape(shape),
- _ => return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
- };
- Ok(TextEmphasisStyle::Keyword(keyword_value))
+ if shape.is_none() && fill.is_none() {
+ return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
+ }
+
+ // If a shape keyword is specified but neither filled nor open is
+ // specified, filled is assumed.
+ let fill = fill.unwrap_or(TextEmphasisFillMode::Filled);
+
+ // We cannot do the same because the default `<shape>` depends on the
+ // computed writing-mode.
+ Ok(TextEmphasisStyle::Keyword { fill, shape })
}
}
@@ -1079,3 +1039,20 @@ pub enum TextDecorationSkipInk {
Auto,
None,
}
+
+/// Implements type for `text-underline-offset` and `text-decoration-thickness` properties
+pub type TextDecorationLength = GenericTextDecorationLength<Length>;
+
+impl TextDecorationLength {
+ /// `Auto` value.
+ #[inline]
+ pub fn auto() -> Self {
+ GenericTextDecorationLength::Auto
+ }
+
+ /// Whether this is the `Auto` value.
+ #[inline]
+ pub fn is_auto(&self) -> bool {
+ matches!(*self, GenericTextDecorationLength::Auto)
+ }
+}
diff --git a/components/style/values/specified/ui.rs b/components/style/values/specified/ui.rs
index 0cc20d960c6..46272b2ae85 100644
--- a/components/style/values/specified/ui.rs
+++ b/components/style/values/specified/ui.rs
@@ -199,7 +199,9 @@ pub enum CursorKind {
Move,
NoDrop,
NotAllowed,
+ #[parse(aliases = "-moz-grab")]
Grab,
+ #[parse(aliases = "-moz-grabbing")]
Grabbing,
EResize,
NResize,
@@ -216,15 +218,9 @@ pub enum CursorKind {
ColResize,
RowResize,
AllScroll,
+ #[parse(aliases = "-moz-zoom-in")]
ZoomIn,
+ #[parse(aliases = "-moz-zoom-out")]
ZoomOut,
Auto,
- #[cfg(feature = "gecko")]
- MozGrab,
- #[cfg(feature = "gecko")]
- MozGrabbing,
- #[cfg(feature = "gecko")]
- MozZoomIn,
- #[cfg(feature = "gecko")]
- MozZoomOut,
}
diff --git a/components/style_traits/specified_value_info.rs b/components/style_traits/specified_value_info.rs
index 39740bc7262..1dd368d36e9 100644
--- a/components/style_traits/specified_value_info.rs
+++ b/components/style_traits/specified_value_info.rs
@@ -82,6 +82,7 @@ impl SpecifiedValueInfo for i32 {}
impl SpecifiedValueInfo for u8 {}
impl SpecifiedValueInfo for u16 {}
impl SpecifiedValueInfo for u32 {}
+impl SpecifiedValueInfo for usize {}
impl SpecifiedValueInfo for str {}
impl SpecifiedValueInfo for String {}
impl SpecifiedValueInfo for crate::owned_str::OwnedStr {}
diff --git a/servo-tidy.toml b/servo-tidy.toml
index 42a253b1aa7..cedd07f2711 100644
--- a/servo-tidy.toml
+++ b/servo-tidy.toml
@@ -56,6 +56,7 @@ files = [
"./components/net/tests/parsable_mime/text",
# Mako does not lend itself easily to splitting long lines
"./components/style/properties/helpers/animated_properties.mako.rs",
+ "./components/style/properties/shorthands/text.mako.rs",
# Long regexes are long.
"./components/style/gecko/regen_atoms.py",
# Helper macro where actually a pseudo-element per line makes sense.
diff --git a/tests/wpt/metadata/css/css-fonts/font-weight-xxx-large.html.ini b/tests/wpt/metadata/css/css-fonts/font-weight-xxx-large.html.ini
deleted file mode 100644
index 86fcb0cf546..00000000000
--- a/tests/wpt/metadata/css/css-fonts/font-weight-xxx-large.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[font-weight-xxx-large.html]
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-fonts/parsing/font-size-valid.html.ini b/tests/wpt/metadata/css/css-fonts/parsing/font-size-valid.html.ini
deleted file mode 100644
index 4b1533148fc..00000000000
--- a/tests/wpt/metadata/css/css-fonts/parsing/font-size-valid.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[font-size-valid.html]
- [e.style['font-size'\] = "xxx-large" should set the property value]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/rendering/widgets/button-layout/display-other.html.ini b/tests/wpt/metadata/html/rendering/widgets/button-layout/display-other.html.ini
index 95591d2929c..e8cfab84493 100644
--- a/tests/wpt/metadata/html/rendering/widgets/button-layout/display-other.html.ini
+++ b/tests/wpt/metadata/html/rendering/widgets/button-layout/display-other.html.ini
@@ -44,9 +44,6 @@
[display: table-row-group]
expected: FAIL
- [display: flow]
- expected: FAIL
-
[display: table-column-group]
expected: FAIL