diff options
Diffstat (limited to 'components/style')
151 files changed, 5051 insertions, 2758 deletions
diff --git a/components/style/animation.rs b/components/style/animation.rs index 2d421ce06a9..3e501781987 100644 --- a/components/style/animation.rs +++ b/components/style/animation.rs @@ -213,7 +213,12 @@ pub enum Animation { /// node-dependent state (i.e. iteration count, etc.). /// /// TODO(emilio): The animation object could be refcounted. - Keyframes(OpaqueNode, KeyframesAnimation, Atom, KeyframesAnimationState), + Keyframes( + OpaqueNode, + KeyframesAnimation, + Atom, + KeyframesAnimationState, + ), } impl Animation { @@ -304,8 +309,7 @@ impl PropertyAnimation { let duration = box_style.transition_duration_mod(transition_index); match transition_property { - TransitionProperty::Custom(..) | - TransitionProperty::Unsupported(..) => result, + TransitionProperty::Custom(..) | TransitionProperty::Unsupported(..) => result, TransitionProperty::Shorthand(ref shorthand_id) => shorthand_id .longhands() .filter_map(|longhand| { @@ -316,8 +320,7 @@ impl PropertyAnimation { old_style, new_style, ) - }) - .collect(), + }).collect(), TransitionProperty::Longhand(longhand_id) => { let animation = PropertyAnimation::from_longhand( longhand_id, @@ -455,8 +458,7 @@ pub fn start_transitions_if_applicable( property_animation: property_animation, }, /* is_expired = */ false, - )) - .unwrap(); + )).unwrap(); had_animations = true; } @@ -505,7 +507,9 @@ where Some(previous_style), Some(previous_style), font_metrics_provider, - CascadeMode::Unvisited { visited_rules: None }, + CascadeMode::Unvisited { + visited_rules: None, + }, context.quirks_mode(), /* rule_cache = */ None, &mut Default::default(), @@ -596,8 +600,7 @@ where expired: false, cascade_style: new_style.clone(), }, - )) - .unwrap(); + )).unwrap(); had_animations = true; } } @@ -735,8 +738,7 @@ pub fn update_style_for_animation<E>( } else { None } - }) - .unwrap_or(animation.steps.len() - 1); + }).unwrap_or(animation.steps.len() - 1); }, _ => unreachable!(), } diff --git a/components/style/applicable_declarations.rs b/components/style/applicable_declarations.rs index a1476917fcb..986dc04c371 100644 --- a/components/style/applicable_declarations.rs +++ b/components/style/applicable_declarations.rs @@ -38,7 +38,8 @@ const SOURCE_ORDER_MASK: u32 = SOURCE_ORDER_MAX << SOURCE_ORDER_SHIFT; const SHADOW_CASCADE_ORDER_SHIFT: usize = SOURCE_ORDER_BITS; const SHADOW_CASCADE_ORDER_BITS: usize = 4; const SHADOW_CASCADE_ORDER_MAX: u8 = (1 << SHADOW_CASCADE_ORDER_BITS) - 1; -const SHADOW_CASCADE_ORDER_MASK: u32 = (SHADOW_CASCADE_ORDER_MAX as u32) << SHADOW_CASCADE_ORDER_SHIFT; +const SHADOW_CASCADE_ORDER_MASK: u32 = + (SHADOW_CASCADE_ORDER_MAX as u32) << SHADOW_CASCADE_ORDER_SHIFT; const CASCADE_LEVEL_SHIFT: usize = SOURCE_ORDER_BITS + SHADOW_CASCADE_ORDER_BITS; const CASCADE_LEVEL_BITS: usize = 4; @@ -61,7 +62,8 @@ impl ApplicableDeclarationBits { "Gotta find more bits!" ); let mut bits = ::std::cmp::min(source_order, SOURCE_ORDER_MAX); - bits |= ((shadow_cascade_order & SHADOW_CASCADE_ORDER_MAX) as u32) << SHADOW_CASCADE_ORDER_SHIFT; + bits |= ((shadow_cascade_order & SHADOW_CASCADE_ORDER_MAX) as u32) << + SHADOW_CASCADE_ORDER_SHIFT; bits |= (cascade_level as u8 as u32) << CASCADE_LEVEL_SHIFT; ApplicableDeclarationBits(bits) } diff --git a/components/style/attr.rs b/components/style/attr.rs index 5f335472f32..a3b119c3a97 100644 --- a/components/style/attr.rs +++ b/components/style/attr.rs @@ -158,15 +158,15 @@ pub fn parse_double(string: &str) -> Result<f64, ()> { impl AttrValue { pub fn from_serialized_tokenlist(tokens: String) -> AttrValue { - let atoms = split_html_space_chars(&tokens).map(Atom::from).fold( - vec![], - |mut acc, atom| { - if !acc.contains(&atom) { - acc.push(atom) - } - acc - }, - ); + let atoms = + split_html_space_chars(&tokens) + .map(Atom::from) + .fold(vec![], |mut acc, atom| { + if !acc.contains(&atom) { + acc.push(atom) + } + acc + }); AttrValue::TokenList(tokens, atoms) } diff --git a/components/style/author_styles.rs b/components/style/author_styles.rs index e8ec621bd92..837569078c0 100644 --- a/components/style/author_styles.rs +++ b/components/style/author_styles.rs @@ -60,7 +60,8 @@ where E: TElement, S: ToMediaListKey, { - let flusher = self.stylesheets + let flusher = self + .stylesheets .flush::<E>(/* host = */ None, /* snapshot_map = */ None); if flusher.sheets.dirty() { @@ -68,7 +69,8 @@ where } // Ignore OOM. - let _ = self.data + let _ = self + .data .rebuild(device, quirks_mode, flusher.sheets, guard); } } diff --git a/components/style/build_gecko.rs b/components/style/build_gecko.rs index 8387f6513a6..1ecc7ec6fc3 100644 --- a/components/style/build_gecko.rs +++ b/components/style/build_gecko.rs @@ -322,13 +322,11 @@ mod bindings { .expect(&format!( "Unrecognized line in ServoArcTypeList.h: '{}'", line - )) - .get(1) + )).get(1) .unwrap() .as_str() .to_string() - }) - .collect() + }).collect() } struct BuilderWithConfig<'a> { @@ -406,11 +404,7 @@ mod bindings { fn generate_structs() { let builder = Builder::get_initial_builder() .enable_cxx_namespaces() - .with_codegen_config(CodegenConfig { - types: true, - vars: true, - ..CodegenConfig::nothing() - }); + .with_codegen_config(CodegenConfig::TYPES | CodegenConfig::VARS); let mut fixups = vec![]; let builder = BuilderWithConfig::new(builder, CONFIG["structs"].as_table().unwrap()) .handle_common(&mut fixups) @@ -440,8 +434,7 @@ mod bindings { servo, if generic { "<T>" } else { "" } )) - }) - .get_builder(); + }).get_builder(); write_binding_file(builder, STRUCTS_FILE, &fixups); } @@ -500,10 +493,7 @@ mod bindings { fn generate_bindings() { let builder = Builder::get_initial_builder() .disable_name_namespacing() - .with_codegen_config(CodegenConfig { - functions: true, - ..CodegenConfig::nothing() - }); + .with_codegen_config(CodegenConfig::FUNCTIONS); let config = CONFIG["bindings"].as_table().unwrap(); let mut structs_types = HashSet::new(); let mut fixups = vec![]; @@ -560,8 +550,7 @@ mod bindings { .raw_line(format!( "pub type {0}Strong = ::gecko_bindings::sugar::ownership::Strong<{0}>;", ty - )) - .borrowed_type(ty) + )).borrowed_type(ty) .zero_size_type(ty, &structs_types); } write_binding_file(builder, BINDINGS_FILE, &fixups); diff --git a/components/style/cbindgen.toml b/components/style/cbindgen.toml index 5a0e5e19ea7..46162e43db5 100644 --- a/components/style/cbindgen.toml +++ b/components/style/cbindgen.toml @@ -7,6 +7,7 @@ autogen_warning = """/* DO NOT MODIFY THIS MANUALLY! This file was generated usi * a. Alternatively, you can clone `https://github.com/eqrion/cbindgen` and use a tagged release * 2. Run `rustup run nightly cbindgen toolkit/library/rust/ --lockfile Cargo.lock --crate style -o layout/style/ServoStyleConsts.h` */""" +include_guard = "mozilla_ServoStyleConsts_h" include_version = true braces = "SameLine" line_length = 80 @@ -22,5 +23,11 @@ derive_helper_methods = true [export] prefix = "Style" -include = ["StyleDisplay", "StyleAppearance", "StyleDisplayMode"] -item_types = ["enums"] +include = [ + "StyleAppearance", + "StyleDisplay", + "StyleDisplayMode", + "StyleFillRule", + "StylePathCommand" +] +item_types = ["enums", "structs", "typedefs"] diff --git a/components/style/counter_style/mod.rs b/components/style/counter_style/mod.rs index 2542dee3625..653d199545c 100644 --- a/components/style/counter_style/mod.rs +++ b/components/style/counter_style/mod.rs @@ -91,8 +91,7 @@ pub fn parse_counter_style_body<'i, 't>( if let Err((error, slice)) = declaration { let location = error.location; let error = ContextualParseError::UnsupportedCounterStyleDescriptorDeclaration( - slice, - error, + slice, error, ); context.log_css_error(location, error) } @@ -103,7 +102,8 @@ pub fn parse_counter_style_body<'i, 't>( ref system @ System::Fixed { .. } | ref system @ System::Symbolic | ref system @ System::Alphabetic | - ref system @ System::Numeric if rule.symbols.is_none() => + ref system @ System::Numeric + if rule.symbols.is_none() => { let system = system.to_css_string(); Some(ContextualParseError::InvalidCounterStyleWithoutSymbols( @@ -496,12 +496,13 @@ impl Parse for Ranges { (opt_start, opt_end) { if start > end { - return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); + return Err( + input.new_custom_error(StyleParseErrorKind::UnspecifiedError) + ); } } Ok(opt_start..opt_end) - }) - .map(Ranges) + }).map(Ranges) } } } diff --git a/components/style/custom_properties.rs b/components/style/custom_properties.rs index d79a27c5c4d..985179db025 100644 --- a/components/style/custom_properties.rs +++ b/components/style/custom_properties.rs @@ -243,7 +243,8 @@ impl VariableValue { self.first_token_type.set_if_nothing(css_first_token_type); // If self.first_token_type was nothing, // self.last_token_type is also nothing and this will be false: - if self.last_token_type + if self + .last_token_type .needs_separator_when_before(css_first_token_type) { self.css.push_str("/**/") @@ -569,7 +570,8 @@ impl<'a> CustomPropertiesBuilder<'a> { _ => {}, } - let existing_value = self.custom_properties + let existing_value = self + .custom_properties .as_ref() .and_then(|m| m.get(name)) .or_else(|| self.inherited.and_then(|m| m.get(name))); diff --git a/components/style/data.rs b/components/style/data.rs index 71a0ac23320..4a9b0c53940 100644 --- a/components/style/data.rs +++ b/components/style/data.rs @@ -272,12 +272,8 @@ impl ElementData { return InvalidationResult::empty(); } - let mut processor = StateAndAttrInvalidationProcessor::new( - shared_context, - element, - self, - nth_index_cache, - ); + let mut processor = + StateAndAttrInvalidationProcessor::new(shared_context, element, self, nth_index_cache); let invalidator = TreeStyleInvalidator::new(element, stack_limit_checker, &mut processor); @@ -305,7 +301,8 @@ impl ElementData { /// Returns this element's primary style as a resolved style to use for sharing. pub fn share_primary_style(&self) -> PrimaryStyle { - let reused_via_rule_node = self.flags + let reused_via_rule_node = self + .flags .contains(ElementDataFlags::PRIMARY_STYLE_REUSED_VIA_RULE_NODE); PrimaryStyle { @@ -390,7 +387,8 @@ impl ElementData { guards: &StylesheetGuards, ) -> bool { debug_assert!(self.has_styles()); - let (important_rules, _custom) = self.styles + let (important_rules, _custom) = self + .styles .primary() .rules() .get_properties_overriding_animations(&guards); diff --git a/components/style/dom.rs b/components/style/dom.rs index 42f6e9ba0c0..872a55a54b2 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -19,7 +19,7 @@ use element_state::ElementState; use font_metrics::FontMetricsProvider; use media_queries::Device; use properties::{AnimationRules, ComputedValues, PropertyDeclarationBlock}; -use selector_parser::{AttrValue, PseudoClassStringArg, PseudoElement, SelectorImpl}; +use selector_parser::{AttrValue, Lang, PseudoElement, SelectorImpl}; use selectors::Element as SelectorsElement; use selectors::matching::{ElementSelectorFlags, QuirksMode, VisitedHandlingMode}; use selectors::sink::Push; @@ -42,7 +42,10 @@ use traversal_flags::TraversalFlags; /// data structures. Also, layout code tends to be faster when the DOM is not being accessed, for /// locality reasons. Using `OpaqueNode` enforces this invariant. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -#[cfg_attr(feature = "servo", derive(MallocSizeOf, Deserialize, Serialize))] +#[cfg_attr( + feature = "servo", + derive(MallocSizeOf, Deserialize, Serialize) +)] pub struct OpaqueNode(pub usize); impl OpaqueNode { @@ -342,7 +345,7 @@ pub trait TShadowRoot: Sized + Copy + Clone + PartialEq { fn host(&self) -> <Self::ConcreteNode as TNode>::ConcreteElement; /// Get the style data for this ShadowRoot. - fn style_data<'a>(&self) -> &'a CascadeData + fn style_data<'a>(&self) -> Option<&'a CascadeData> where Self: 'a; @@ -459,7 +462,9 @@ pub trait TElement: fn is_svg_element(&self) -> bool; /// Return whether this element is an element in the XUL namespace. - fn is_xul_element(&self) -> bool { false } + fn is_xul_element(&self) -> bool { + false + } /// Return the list of slotted nodes of this node. fn slotted_nodes(&self) -> &[Self::ConcreteNode] { @@ -824,30 +829,36 @@ pub trait TElement: if let Some(shadow) = self.containing_shadow() { doc_rules_apply = false; - f( - shadow.style_data(), - self.as_node().owner_doc().quirks_mode(), - Some(shadow.host()), - ); + if let Some(data) = shadow.style_data() { + f( + data, + self.as_node().owner_doc().quirks_mode(), + Some(shadow.host()), + ); + } } if let Some(shadow) = self.shadow_root() { - f( - shadow.style_data(), - self.as_node().owner_doc().quirks_mode(), - Some(shadow.host()), - ); + if let Some(data) = shadow.style_data() { + f( + data, + self.as_node().owner_doc().quirks_mode(), + Some(shadow.host()), + ); + } } let mut current = self.assigned_slot(); while let Some(slot) = current { // Slots can only have assigned nodes when in a shadow tree. let shadow = slot.containing_shadow().unwrap(); - f( - shadow.style_data(), - self.as_node().owner_doc().quirks_mode(), - Some(shadow.host()), - ); + if let Some(data) = shadow.style_data() { + f( + data, + self.as_node().owner_doc().quirks_mode(), + Some(shadow.host()), + ); + } current = slot.assigned_slot(); } @@ -886,11 +897,7 @@ pub trait TElement: /// of the `xml:lang=""` or `lang=""` attribute to use in place of /// looking at the element and its ancestors. (This argument is used /// to implement matching of `:lang()` against snapshots.) - fn match_element_lang( - &self, - override_lang: Option<Option<AttrValue>>, - value: &PseudoClassStringArg, - ) -> bool; + fn match_element_lang(&self, override_lang: Option<Option<AttrValue>>, value: &Lang) -> bool; /// Returns whether this element is the main body element of the HTML /// document it is on. diff --git a/components/style/dom_apis.rs b/components/style/dom_apis.rs index 393fb6e119e..9d7ab917a91 100644 --- a/components/style/dom_apis.rs +++ b/components/style/dom_apis.rs @@ -426,8 +426,7 @@ where return Ok(()); } - let elements = - fast_connected_elements_with_id(root, id, quirks_mode)?; + let elements = fast_connected_elements_with_id(root, id, quirks_mode)?; if elements.is_empty() { return Ok(()); } diff --git a/components/style/font_face.rs b/components/style/font_face.rs index d7501c1cca7..fde25f08f6f 100644 --- a/components/style/font_face.rs +++ b/components/style/font_face.rs @@ -104,8 +104,9 @@ impl Parse for FontWeight { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { let first = AbsoluteFontWeight::parse(context, input)?; - let second = - input.try(|input| AbsoluteFontWeight::parse(context, input)).ok(); + let second = input + .try(|input| AbsoluteFontWeight::parse(context, input)) + .ok(); Ok(FontWeight(first, second)) } } @@ -122,8 +123,9 @@ impl Parse for FontStretch { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { let first = SpecifiedFontStretch::parse(context, input)?; - let second = - input.try(|input| SpecifiedFontStretch::parse(context, input)).ok(); + let second = input + .try(|input| SpecifiedFontStretch::parse(context, input)) + .ok(); Ok(FontStretch(first, second)) } } @@ -149,12 +151,12 @@ impl Parse for FontStyle { GenericFontStyle::Normal => FontStyle::Normal, GenericFontStyle::Italic => FontStyle::Italic, GenericFontStyle::Oblique(angle) => { - let second_angle = input.try(|input| { - SpecifiedFontStyle::parse_angle(context, input) - }).unwrap_or_else(|_| angle.clone()); + let second_angle = input + .try(|input| SpecifiedFontStyle::parse_angle(context, input)) + .unwrap_or_else(|_| angle.clone()); FontStyle::Oblique(angle, second_angle) - } + }, }) } } @@ -178,7 +180,7 @@ impl ToCss for FontStyle { second.to_css(dest)?; } Ok(()) - } + }, } } } @@ -235,15 +237,13 @@ impl<'a> FontFace<'a> { // We support only opentype fonts and truetype is an alias for // that format. Sources without format hints need to be // downloaded in case we support them. - hints.is_empty() || - hints.iter().any(|hint| { - hint == "truetype" || hint == "opentype" || hint == "woff" - }) + hints.is_empty() || hints + .iter() + .any(|hint| hint == "truetype" || hint == "opentype" || hint == "woff") } else { true } - }) - .cloned() + }).cloned() .collect(), ) } diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index 3b1f31a1b08..c6009c96dee 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -19,6 +19,7 @@ use stylesheets::{Origin, RulesMutateError}; use values::computed::{Angle, CalcLengthOrPercentage, Gradient, Image}; use values::computed::{Integer, LengthOrPercentage, LengthOrPercentageOrAuto}; use values::computed::{Percentage, TextAlign}; +use values::computed::image::LineDirection; use values::computed::url::ComputedImageUrl; use values::generics::box_::VerticalAlign; use values::generics::grid::{TrackListValue, TrackSize}; @@ -139,6 +140,65 @@ impl Angle { } } +fn line_direction(horizontal: LengthOrPercentage, vertical: LengthOrPercentage) -> LineDirection { + use values::computed::position::Position; + use values::specified::position::{X, Y}; + + let horizontal_percentage = match horizontal { + LengthOrPercentage::Percentage(percentage) => Some(percentage.0), + _ => None, + }; + + let vertical_percentage = match vertical { + LengthOrPercentage::Percentage(percentage) => Some(percentage.0), + _ => None, + }; + + let horizontal_as_corner = horizontal_percentage.and_then(|percentage| { + if percentage == 0.0 { + Some(X::Left) + } else if percentage == 1.0 { + Some(X::Right) + } else { + None + } + }); + + let vertical_as_corner = vertical_percentage.and_then(|percentage| { + if percentage == 0.0 { + Some(Y::Top) + } else if percentage == 1.0 { + Some(Y::Bottom) + } else { + None + } + }); + + if let (Some(hc), Some(vc)) = (horizontal_as_corner, vertical_as_corner) { + return LineDirection::Corner(hc, vc); + } + + if let Some(hc) = horizontal_as_corner { + if vertical_percentage == Some(0.5) { + return LineDirection::Horizontal(hc); + } + } + + if let Some(vc) = vertical_as_corner { + if horizontal_percentage == Some(0.5) { + return LineDirection::Vertical(vc); + } + } + + LineDirection::MozPosition( + Some(Position { + horizontal, + vertical, + }), + None, + ) +} + impl nsStyleImage { /// Set a given Servo `Image` value into this `nsStyleImage`. pub fn set(&mut self, image: Image) { @@ -149,7 +209,10 @@ impl nsStyleImage { }, GenericImage::Rect(ref image_rect) => { unsafe { - bindings::Gecko_SetLayerImageImageValue(self, image_rect.url.0.image_value.get()); + bindings::Gecko_SetLayerImageImageValue( + self, + image_rect.url.0.image_value.get(), + ); bindings::Gecko_InitializeImageCropRect(self); // Set CropRect @@ -174,13 +237,13 @@ impl nsStyleImage { } } + // FIXME(emilio): This is really complex, we should use cbindgen for this. fn set_gradient(&mut self, gradient: Gradient) { use self::structs::NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER as CLOSEST_CORNER; use self::structs::NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE as CLOSEST_SIDE; use self::structs::NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER as FARTHEST_CORNER; use self::structs::NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE as FARTHEST_SIDE; use self::structs::nsStyleCoord; - use values::computed::image::LineDirection; use values::generics::image::{Circle, Ellipse, EndingShape, GradientKind, ShapeExtent}; use values::specified::position::{X, Y}; @@ -428,7 +491,8 @@ impl nsStyleImage { unsafe fn get_image_url(&self) -> ComputedImageUrl { let image_request = bindings::Gecko_GetImageRequest(self) - .as_ref().expect("Null image request?"); + .as_ref() + .expect("Null image request?"); ComputedImageUrl::from_image_request(image_request) } @@ -437,12 +501,11 @@ impl nsStyleImage { use self::structs::NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE as CLOSEST_SIDE; use self::structs::NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER as FARTHEST_CORNER; use self::structs::NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE as FARTHEST_SIDE; - use values::computed::{Length, LengthOrPercentage}; + use values::computed::Length; use values::computed::image::LineDirection; use values::computed::position::Position; use values::generics::image::{Circle, ColorStop, CompatMode, Ellipse}; use values::generics::image::{EndingShape, GradientKind, ShapeExtent}; - use values::specified::position::{X, Y}; let gecko_gradient = bindings::Gecko_GetGradientImageValue(self) .as_ref() @@ -456,41 +519,7 @@ impl nsStyleImage { let line_direction = match (angle, horizontal_style, vertical_style) { (Some(a), None, None) => LineDirection::Angle(a), (None, Some(horizontal), Some(vertical)) => { - let horizontal_as_corner = match horizontal { - LengthOrPercentage::Percentage(percentage) => { - if percentage.0 == 0.0 { - Some(X::Left) - } else if percentage.0 == 1.0 { - Some(X::Right) - } else { - None - } - }, - _ => None, - }; - let vertical_as_corner = match vertical { - LengthOrPercentage::Percentage(percentage) => { - if percentage.0 == 0.0 { - Some(Y::Top) - } else if percentage.0 == 1.0 { - Some(Y::Bottom) - } else { - None - } - }, - _ => None, - }; - - match (horizontal_as_corner, vertical_as_corner) { - (Some(hc), Some(vc)) => LineDirection::Corner(hc, vc), - _ => LineDirection::MozPosition( - Some(Position { - horizontal, - vertical, - }), - None, - ), - } + line_direction(horizontal, vertical) }, (Some(_), Some(horizontal), Some(vertical)) => LineDirection::MozPosition( Some(Position { @@ -527,9 +556,9 @@ impl nsStyleImage { structs::NS_STYLE_GRADIENT_SHAPE_CIRCULAR => { let circle = match gecko_gradient.mSize as u32 { structs::NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE => { - let radius = Length::from_gecko_style_coord( - &gecko_gradient.mRadiusX, - ).expect("mRadiusX could not convert to Length"); + let radius = + Length::from_gecko_style_coord(&gecko_gradient.mRadiusX) + .expect("mRadiusX could not convert to Length"); debug_assert_eq!( radius, Length::from_gecko_style_coord(&gecko_gradient.mRadiusY) @@ -604,8 +633,7 @@ impl nsStyleImage { position: LengthOrPercentage::from_gecko_style_coord(&stop.mLocation), }) } - }) - .collect(); + }).collect(); let compat_mode = if gecko_gradient.mMozLegacySyntax { CompatMode::Moz @@ -638,13 +666,15 @@ pub mod basic_shape { use values::computed::basic_shape::{BasicShape, ClippingShape, FloatAreaShape, ShapeRadius}; use values::computed::border::{BorderCornerRadius, BorderRadius}; use values::computed::length::LengthOrPercentage; + use values::computed::motion::OffsetPath; use values::computed::position; use values::computed::url::ComputedUrl; use values::generics::basic_shape::{BasicShape as GenericBasicShape, InsetRect, Polygon}; - use values::generics::basic_shape::{Circle, Ellipse, FillRule}; + use values::generics::basic_shape::{Circle, Ellipse, FillRule, Path, PolygonCoord}; use values::generics::basic_shape::{GeometryBox, ShapeBox, ShapeSource}; use values::generics::border::BorderRadius as GenericBorderRadius; use values::generics::rect::Rect; + use values::specified::SVGPathData; impl StyleShapeSource { /// Convert StyleShapeSource to ShapeSource except URL and Image @@ -669,6 +699,36 @@ pub mod basic_shape { Some(ShapeSource::Shape(shape, reference_box)) }, StyleShapeSourceType::URL | StyleShapeSourceType::Image => None, + StyleShapeSourceType::Path => { + let path = self.to_svg_path().expect("expect an SVGPathData"); + let gecko_path = unsafe { &*self.__bindgen_anon_1.mSVGPath.as_ref().mPtr }; + let fill = if gecko_path.mFillRule == StyleFillRule::Evenodd { + FillRule::Evenodd + } else { + FillRule::Nonzero + }; + Some(ShapeSource::Path(Path { fill, path })) + }, + } + } + + /// Generate a SVGPathData from StyleShapeSource if possible. + fn to_svg_path(&self) -> Option<SVGPathData> { + use gecko_bindings::structs::StylePathCommand; + use values::specified::svg_path::PathCommand; + match self.mType { + StyleShapeSourceType::Path => { + let gecko_path = unsafe { &*self.__bindgen_anon_1.mSVGPath.as_ref().mPtr }; + let result: Vec<PathCommand> = gecko_path + .mPath + .iter() + .map(|gecko: &StylePathCommand| { + // unsafe: cbindgen ensures the representation is the same. + unsafe { ::std::mem::transmute(*gecko) } + }).collect(); + Some(SVGPathData::new(result.into_boxed_slice())) + }, + _ => None, } } } @@ -710,6 +770,21 @@ pub mod basic_shape { } } + impl<'a> From<&'a StyleShapeSource> for OffsetPath { + fn from(other: &'a StyleShapeSource) -> Self { + match other.mType { + StyleShapeSourceType::Path => { + OffsetPath::Path(other.to_svg_path().expect("Cannot convert to SVGPathData")) + }, + StyleShapeSourceType::None => OffsetPath::none(), + StyleShapeSourceType::Shape | + StyleShapeSourceType::Box | + StyleShapeSourceType::URL | + StyleShapeSourceType::Image => unreachable!("Unsupported offset-path type"), + } + } + } + impl<'a> From<&'a StyleBasicShape> for BasicShape { fn from(other: &'a StyleBasicShape) -> Self { match other.mType { @@ -718,17 +793,15 @@ pub mod basic_shape { let r = LengthOrPercentage::from_gecko_style_coord(&other.mCoordinates[1]); let b = LengthOrPercentage::from_gecko_style_coord(&other.mCoordinates[2]); let l = LengthOrPercentage::from_gecko_style_coord(&other.mCoordinates[3]); - let round = (&other.mRadius).into(); + let round: BorderRadius = (&other.mRadius).into(); + let round = if round.all_zero() { None } else { Some(round) }; let rect = Rect::new( t.expect("inset() offset should be a length, percentage, or calc value"), r.expect("inset() offset should be a length, percentage, or calc value"), b.expect("inset() offset should be a length, percentage, or calc value"), l.expect("inset() offset should be a length, percentage, or calc value"), ); - GenericBasicShape::Inset(InsetRect { - rect: rect, - round: Some(round), - }) + GenericBasicShape::Inset(InsetRect { rect, round }) }, StyleBasicShapeType::Circle => GenericBasicShape::Circle(Circle { radius: (&other.mCoordinates[0]).into(), @@ -749,11 +822,18 @@ pub mod basic_shape { for i in 0..(other.mCoordinates.len() / 2) { let x = 2 * i; let y = x + 1; - coords.push((LengthOrPercentage::from_gecko_style_coord(&other.mCoordinates[x]) - .expect("polygon() coordinate should be a length, percentage, or calc value"), - LengthOrPercentage::from_gecko_style_coord(&other.mCoordinates[y]) - .expect("polygon() coordinate should be a length, percentage, or calc value") - )) + coords.push(PolygonCoord( + LengthOrPercentage::from_gecko_style_coord(&other.mCoordinates[x]) + .expect( + "polygon() coordinate should be a length, percentage, \ + or calc value", + ), + LengthOrPercentage::from_gecko_style_coord(&other.mCoordinates[y]) + .expect( + "polygon() coordinate should be a length, percentage, \ + or calc value", + ), + )) } GenericBasicShape::Polygon(Polygon { fill: fill_rule, diff --git a/components/style/gecko/data.rs b/components/style/gecko/data.rs index 0bd938c67e8..d737167c28a 100644 --- a/components/style/gecko/data.rs +++ b/components/style/gecko/data.rs @@ -29,7 +29,8 @@ pub struct GeckoStyleSheet(*const DomStyleSheet); impl fmt::Debug for GeckoStyleSheet { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let contents = self.contents(); - formatter.debug_struct("GeckoStyleSheet") + formatter + .debug_struct("GeckoStyleSheet") .field("origin", &contents.origin) .field("url_data", &*contents.url_data.read()) .finish() @@ -66,9 +67,7 @@ impl GeckoStyleSheet { } fn inner(&self) -> &StyleSheetInfo { - unsafe { - &*(self.raw().mInner as *const StyleSheetInfo) - } + unsafe { &*(self.raw().mInner as *const StyleSheetInfo) } } /// Gets the StylesheetContents for this stylesheet. @@ -193,7 +192,8 @@ impl PerDocumentStyleDataImpl { /// Returns whether visited styles are enabled. #[inline] pub fn visited_styles_enabled(&self) -> bool { - let doc = self.stylist + let doc = self + .stylist .device() .pres_context() .mDocument diff --git a/components/style/gecko/media_features.rs b/components/style/gecko/media_features.rs index 386d0ad5b43..85f0ba27d43 100644 --- a/components/style/gecko/media_features.rs +++ b/components/style/gecko/media_features.rs @@ -21,7 +21,7 @@ fn viewport_size(device: &Device) -> Size2D<Au> { // We want the page size, including unprintable areas and margins. // FIXME(emilio, bug 1414600): Not quite! let area = &pc.mPageSize; - return Size2D::new(Au(area.width), Au(area.height)) + return Size2D::new(Au(area.width), Au(area.height)); } device.au_viewport_size() } @@ -30,11 +30,7 @@ fn device_size(device: &Device) -> Size2D<Au> { let mut width = 0; let mut height = 0; unsafe { - bindings::Gecko_MediaFeatures_GetDeviceSize( - device.document(), - &mut width, - &mut height, - ); + bindings::Gecko_MediaFeatures_GetDeviceSize(device.document(), &mut width, &mut height); } Size2D::new(Au(width), Au(height)) } @@ -152,11 +148,7 @@ enum Orientation { Portrait, } -fn eval_orientation_for<F>( - device: &Device, - value: Option<Orientation>, - get_size: F, -) -> bool +fn eval_orientation_for<F>(device: &Device, value: Option<Orientation>, get_size: F) -> bool where F: FnOnce(&Device) -> Size2D<Au>, { @@ -176,18 +168,12 @@ where } /// https://drafts.csswg.org/mediaqueries-4/#orientation -fn eval_orientation( - device: &Device, - value: Option<Orientation>, -) -> bool { +fn eval_orientation(device: &Device, value: Option<Orientation>) -> bool { eval_orientation_for(device, value, viewport_size) } /// FIXME: There's no spec for `-moz-device-orientation`. -fn eval_device_orientation( - device: &Device, - value: Option<Orientation>, -) -> bool { +fn eval_device_orientation(device: &Device, value: Option<Orientation>) -> bool { eval_orientation_for(device, value, device_size) } @@ -196,25 +182,21 @@ fn eval_device_orientation( #[repr(u8)] #[allow(missing_docs)] pub enum DisplayMode { - Browser = 0, - MinimalUi, - Standalone, - Fullscreen, + Browser = 0, + MinimalUi, + Standalone, + Fullscreen, } /// https://w3c.github.io/manifest/#the-display-mode-media-feature -fn eval_display_mode( - device: &Device, - query_value: Option<DisplayMode>, -) -> bool { +fn eval_display_mode(device: &Device, query_value: Option<DisplayMode>) -> bool { let query_value = match query_value { Some(v) => v, None => return true, }; - let gecko_display_mode = unsafe { - bindings::Gecko_MediaFeatures_GetDisplayMode(device.document()) - }; + let gecko_display_mode = + unsafe { bindings::Gecko_MediaFeatures_GetDisplayMode(device.document()) }; // NOTE: cbindgen guarantees the same representation. gecko_display_mode as u8 == query_value as u8 @@ -229,11 +211,7 @@ fn eval_grid(_: &Device, query_value: Option<bool>, _: Option<RangeOrOperator>) } /// https://compat.spec.whatwg.org/#css-media-queries-webkit-transform-3d -fn eval_transform_3d( - _: &Device, - query_value: Option<bool>, - _: Option<RangeOrOperator>, -) -> bool { +fn eval_transform_3d(_: &Device, query_value: Option<bool>, _: Option<RangeOrOperator>) -> bool { let supports_transforms = true; query_value.map_or(supports_transforms, |v| v == supports_transforms) } @@ -260,11 +238,7 @@ fn eval_color( ) -> bool { let color_bits_per_channel = unsafe { bindings::Gecko_MediaFeatures_GetColorDepth(device.document()) }; - RangeOrOperator::evaluate( - range_or_operator, - query_value, - color_bits_per_channel, - ) + RangeOrOperator::evaluate(range_or_operator, query_value, color_bits_per_channel) } /// https://drafts.csswg.org/mediaqueries-4/#color-index @@ -275,11 +249,7 @@ fn eval_color_index( ) -> bool { // We should return zero if the device does not use a color lookup table. let index = 0; - RangeOrOperator::evaluate( - range_or_operator, - query_value, - index, - ) + RangeOrOperator::evaluate(range_or_operator, query_value, index) } /// https://drafts.csswg.org/mediaqueries-4/#monochrome @@ -291,11 +261,7 @@ fn eval_monochrome( // For color devices we should return 0. // FIXME: On a monochrome device, return the actual color depth, not 0! let depth = 0; - RangeOrOperator::evaluate( - range_or_operator, - query_value, - depth, - ) + RangeOrOperator::evaluate(range_or_operator, query_value, depth) } /// https://drafts.csswg.org/mediaqueries-4/#resolution @@ -304,8 +270,7 @@ fn eval_resolution( query_value: Option<Resolution>, range_or_operator: Option<RangeOrOperator>, ) -> bool { - let resolution_dppx = - unsafe { bindings::Gecko_MediaFeatures_GetResolution(device.document()) }; + let resolution_dppx = unsafe { bindings::Gecko_MediaFeatures_GetResolution(device.document()) }; RangeOrOperator::evaluate( range_or_operator, query_value.map(|r| r.dppx()), @@ -321,10 +286,7 @@ enum PrefersReducedMotion { } /// https://drafts.csswg.org/mediaqueries-5/#prefers-reduced-motion -fn eval_prefers_reduced_motion( - device: &Device, - query_value: Option<PrefersReducedMotion>, -) -> bool { +fn eval_prefers_reduced_motion(device: &Device, query_value: Option<PrefersReducedMotion>) -> bool { let prefers_reduced = unsafe { bindings::Gecko_MediaFeatures_PrefersReducedMotion(device.document()) }; let query_value = match query_value { @@ -352,9 +314,8 @@ fn eval_moz_is_resource_document( query_value: Option<bool>, _: Option<RangeOrOperator>, ) -> bool { - let is_resource_doc = unsafe { - bindings::Gecko_MediaFeatures_IsResourceDocument(device.document()) - }; + let is_resource_doc = + unsafe { bindings::Gecko_MediaFeatures_IsResourceDocument(device.document()) }; query_value.map_or(is_resource_doc, |v| v == is_resource_doc) } @@ -397,37 +358,30 @@ fn eval_moz_os_version( None => return false, }; - let os_version = unsafe { - bindings::Gecko_MediaFeatures_GetOperatingSystemVersion(device.document()) - }; + let os_version = + unsafe { bindings::Gecko_MediaFeatures_GetOperatingSystemVersion(device.document()) }; query_value.as_ptr() == os_version } macro_rules! system_metric_feature { - ($feature_name:expr) => { - { - fn __eval( - device: &Device, - query_value: Option<bool>, - _: Option<RangeOrOperator>, - ) -> bool { - eval_system_metric( - device, - query_value, - $feature_name, - /* accessible_from_content = */ false, - ) - } - - feature!( + ($feature_name:expr) => {{ + fn __eval(device: &Device, query_value: Option<bool>, _: Option<RangeOrOperator>) -> bool { + eval_system_metric( + device, + query_value, $feature_name, - AllowsRanges::No, - Evaluator::BoolInteger(__eval), - ParsingRequirements::CHROME_AND_UA_ONLY, + /* accessible_from_content = */ false, ) } - } + + feature!( + $feature_name, + AllowsRanges::No, + Evaluator::BoolInteger(__eval), + ParsingRequirements::CHROME_AND_UA_ONLY, + ) + }}; } lazy_static! { diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs index c41bc4ffd73..ccf5b7a5180 100644 --- a/components/style/gecko/media_queries.rs +++ b/components/style/gecko/media_queries.rs @@ -126,7 +126,8 @@ impl Device { /// Set the font size of the root element (for rem) pub fn set_root_font_size(&self, size: Au) { - self.root_font_size.store(size.0 as isize, Ordering::Relaxed) + self.root_font_size + .store(size.0 as isize, Ordering::Relaxed) } /// Sets the body text color for the "inherit color from body" quirk. diff --git a/components/style/gecko/non_ts_pseudo_class_list.rs b/components/style/gecko/non_ts_pseudo_class_list.rs index 04f57b73885..813250e4383 100644 --- a/components/style/gecko/non_ts_pseudo_class_list.rs +++ b/components/style/gecko/non_ts_pseudo_class_list.rs @@ -12,22 +12,13 @@ * Expected usage is as follows: * ``` * macro_rules! pseudo_class_macro{ - * (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*], - * string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => { - * keyword: [$(($k_css:expr, $k_name:ident, $k_gecko_type:tt, $k_state:tt, $k_flags:tt),)*]) => { + * ([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => { * // do stuff * } * } * apply_non_ts_list!(pseudo_class_macro) * ``` * - * The `string` and `keyword` variables will be applied to pseudoclasses that are of the form of - * functions with string or keyword arguments. - * - * Pending pseudo-classes: - * - * :scope -> <style scoped>, pending discussion. - * * $gecko_type can be either "_" or an ident in Gecko's CSSPseudoClassType. * $state can be either "_" or an expression of type ElementState. If present, * the semantics are that the pseudo-class matches if any of the bits in @@ -39,7 +30,7 @@ macro_rules! apply_non_ts_list { ($apply_macro:ident) => { $apply_macro! { - bare: [ + [ ("-moz-table-border-nonzero", MozTableBorderNonzero, mozTableBorderNonzero, _, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS), ("-moz-browser-frame", MozBrowserFrame, mozBrowserFrame, _, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME), ("link", Link, link, IN_UNVISITED_STATE, _), @@ -111,9 +102,6 @@ macro_rules! apply_non_ts_list { ("-moz-lwtheme-brighttext", MozLWThemeBrightText, mozLWThemeBrightText, _, _), ("-moz-lwtheme-darktext", MozLWThemeDarkText, mozLWThemeDarkText, _, _), ("-moz-window-inactive", MozWindowInactive, mozWindowInactive, _, _), - ], - string: [ - ("lang", Lang, lang, _, _), ] } } diff --git a/components/style/gecko/pseudo_element.rs b/components/style/gecko/pseudo_element.rs index a08da8d40f1..70b0e112cee 100644 --- a/components/style/gecko/pseudo_element.rs +++ b/components/style/gecko/pseudo_element.rs @@ -14,6 +14,7 @@ use properties::{ComputedValues, PropertyFlags}; use properties::longhands::display::computed_value::T as Display; use selector_parser::{NonTSPseudoClass, PseudoElementCascadeType, SelectorImpl}; use std::fmt; +use str::{starts_with_ignore_ascii_case, string_as_ascii_lowercase}; use string_cache::Atom; use thin_slice::ThinBoxedSlice; use values::serialize_atom_identifier; @@ -61,7 +62,9 @@ impl PseudoElement { /// /// This is used in Servo for anonymous boxes, though it's likely broken. #[inline] - pub fn inherits_all(&self) -> bool { false } + pub fn inherits_all(&self) -> bool { + false + } /// Whether the pseudo-element should inherit from the default computed /// values instead of from the parent element. diff --git a/components/style/gecko/pseudo_element_definition.mako.rs b/components/style/gecko/pseudo_element_definition.mako.rs index be0318eadea..7c45ee8bfb7 100644 --- a/components/style/gecko/pseudo_element_definition.mako.rs +++ b/components/style/gecko/pseudo_element_definition.mako.rs @@ -13,6 +13,9 @@ pub enum PseudoElement { ${pseudo.capitalized_pseudo()}, % endif % endfor + /// ::-webkit-* that we don't recognize + /// https://github.com/whatwg/compat/issues/103 + UnknownWebkit(Atom), } /// Important: If you change this, you should also update Gecko's @@ -47,11 +50,12 @@ PseudoElement::${pseudo.capitalized_pseudo()}${"({})".format(tree_arg) if pseudo impl PseudoElement { /// Get the pseudo-element as an atom. #[inline] - pub fn atom(&self) -> Atom { + fn atom(&self) -> Atom { match *self { % for pseudo in PSEUDOS: ${pseudo_element_variant(pseudo)} => atom!("${pseudo.value}"), % endfor + PseudoElement::UnknownWebkit(..) => unreachable!(), } } @@ -62,6 +66,7 @@ impl PseudoElement { % for i, pseudo in enumerate(PSEUDOS): ${pseudo_element_variant(pseudo)} => ${i}, % endfor + PseudoElement::UnknownWebkit(..) => unreachable!(), } } @@ -105,6 +110,12 @@ impl PseudoElement { } } + /// Whether this pseudo-element is an unknown Webkit-prefixed pseudo-element. + #[inline] + pub fn is_unknown_webkit_pseudo_element(&self) -> bool { + matches!(*self, PseudoElement::UnknownWebkit(..)) + } + /// Gets the flags associated to this pseudo-element, or 0 if it's an /// anonymous box. pub fn flags(&self) -> u32 { @@ -123,6 +134,7 @@ impl PseudoElement { structs::SERVO_CSS_PSEUDO_ELEMENT_FLAGS_${pseudo.pseudo_ident}, % endif % endfor + PseudoElement::UnknownWebkit(..) => 0, } } @@ -143,7 +155,7 @@ impl PseudoElement { /// Construct a `CSSPseudoElementType` from a pseudo-element #[inline] - pub fn pseudo_type(&self) -> CSSPseudoElementType { + fn pseudo_type(&self) -> CSSPseudoElementType { use gecko_bindings::structs::CSSPseudoElementType_InheritingAnonBox; match *self { @@ -158,6 +170,7 @@ impl PseudoElement { PseudoElement::${pseudo.capitalized_pseudo()} => CSSPseudoElementType::NonInheritingAnonBox, % endif % endfor + PseudoElement::UnknownWebkit(..) => unreachable!(), } } @@ -242,11 +255,18 @@ impl PseudoElement { return Some(PseudoElement::Placeholder); } _ => { - // FIXME: -moz-tree check should probably be - // ascii-case-insensitive. - if name.starts_with("-moz-tree-") { + 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 + } { + const WEBKIT_PREFIX: &str = "-webkit-"; + if starts_with_ignore_ascii_case(name, WEBKIT_PREFIX) { + let part = string_as_ascii_lowercase(&name[WEBKIT_PREFIX.len()..]); + return Some(PseudoElement::UnknownWebkit(part.into())); + } + } } } @@ -259,7 +279,7 @@ impl PseudoElement { /// Returns `None` if the pseudo-element is not recognized. #[inline] pub fn tree_pseudo_element(name: &str, args: Box<[Atom]>) -> Option<Self> { - debug_assert!(name.starts_with("-moz-tree-")); + debug_assert!(starts_with_ignore_ascii_case(name, "-moz-tree-")); let tree_part = &name[10..]; % for pseudo in TREE_PSEUDOS: if tree_part.eq_ignore_ascii_case("${pseudo.value[11:]}") { @@ -277,6 +297,10 @@ impl ToCss for PseudoElement { % for pseudo in PSEUDOS: ${pseudo_element_variant(pseudo)} => dest.write_str("${pseudo.value}")?, % endfor + PseudoElement::UnknownWebkit(ref atom) => { + dest.write_str(":-webkit-")?; + serialize_atom_identifier(atom, dest)?; + } } if let Some(args) = self.tree_pseudo_args() { if !args.is_empty() { diff --git a/components/style/gecko/rules.rs b/components/style/gecko/rules.rs index a57314a418c..233b1757ef5 100644 --- a/components/style/gecko/rules.rs +++ b/components/style/gecko/rules.rs @@ -88,7 +88,7 @@ macro_rules! descriptor_range_conversion { None => { nscssvalue.set_from(first); return; - } + }, Some(ref second) => second, }; @@ -101,7 +101,7 @@ macro_rules! descriptor_range_conversion { nscssvalue.set_pair(&a, &b); } } - } + }; } descriptor_range_conversion!(FontWeight); @@ -120,7 +120,7 @@ impl<'a> ToNsCssValue for &'a FontStyle { b.set_font_style(SpecifiedFontStyle::compute_angle(second).degrees()); nscssvalue.set_pair(&a, &b); - } + }, } } } diff --git a/components/style/gecko/selector_parser.rs b/components/style/gecko/selector_parser.rs index fa514835e8c..2365356f2f8 100644 --- a/components/style/gecko/selector_parser.rs +++ b/components/style/gecko/selector_parser.rs @@ -17,9 +17,11 @@ use selectors::parser::{SelectorParseErrorKind, Visit}; use selectors::parser::{self as selector_parser, Selector}; use selectors::visitor::SelectorVisitor; use std::fmt; +use str::starts_with_ignore_ascii_case; use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace}; use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss as ToCss_}; use thin_slice::ThinBoxedSlice; +use values::serialize_atom_identifier; pub use gecko::pseudo_element::{PseudoElement, EAGER_PSEUDOS, EAGER_PSEUDO_COUNT, PSEUDO_COUNT}; pub use gecko::snapshot::SnapshotMap; @@ -35,12 +37,11 @@ bitflags! { } } -/// The type used for storing pseudo-class string arguments. -pub type PseudoClassStringArg = ThinBoxedSlice<u16>; +/// The type used to store the language argument to the `:lang` pseudo-class. +pub type Lang = Atom; macro_rules! pseudo_class_name { - (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*], - string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => { + ([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => { /// Our representation of a non tree-structural pseudo-class. #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)] pub enum NonTSPseudoClass { @@ -48,19 +49,17 @@ macro_rules! pseudo_class_name { #[doc = $css] $name, )* - $( - #[doc = $s_css] - $s_name(PseudoClassStringArg), - )* + /// The `:lang` pseudo-class. + Lang(Lang), /// The `:dir` pseudo-class. - Dir(Box<Direction>), + Dir(Direction), /// The non-standard `:-moz-any` pseudo-class. /// /// TODO(emilio): We disallow combinators and pseudos here, so we /// should use SimpleSelector instead MozAny(ThinBoxedSlice<Selector<SelectorImpl>>), /// The non-standard `:-moz-locale-dir` pseudo-class. - MozLocaleDir(Box<Direction>), + MozLocaleDir(Direction), } } } @@ -71,25 +70,15 @@ impl ToCss for NonTSPseudoClass { where W: fmt::Write, { - use cssparser::CssStringWriter; - use std::fmt::Write; macro_rules! pseudo_class_serialize { - (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*], - string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => { + ([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => { match *self { $(NonTSPseudoClass::$name => concat!(":", $css),)* - $(NonTSPseudoClass::$s_name(ref s) => { - dest.write_str(concat!(":", $s_css, "("))?; - { - // FIXME(emilio): Avoid the extra allocation! - let mut css = CssStringWriter::new(dest); - - // Discount the null char in the end from the - // string. - css.write_str(&String::from_utf16(&s[..s.len() - 1]).unwrap())?; - } - return dest.write_str(")") - }, )* + NonTSPseudoClass::Lang(ref s) => { + dest.write_str(":lang(")?; + serialize_atom_identifier(s, dest)?; + return dest.write_char(')'); + }, NonTSPseudoClass::MozLocaleDir(ref dir) => { dest.write_str(":-moz-locale-dir(")?; dir.to_css(&mut CssWriter::new(dest))?; @@ -109,7 +98,7 @@ impl ToCss for NonTSPseudoClass { dest.write_str(", ")?; selector.to_css(dest)?; } - return dest.write_str(")") + return dest.write_char(')') } } } @@ -144,8 +133,7 @@ impl NonTSPseudoClass { /// in a particular state. pub fn parse_non_functional(name: &str) -> Option<Self> { macro_rules! pseudo_class_parse { - (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*], - string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => { + ([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => { match_ignore_ascii_case! { &name, $($css => Some(NonTSPseudoClass::$name),)* _ => None, @@ -166,12 +154,11 @@ impl NonTSPseudoClass { }; } macro_rules! pseudo_class_check_is_enabled_in { - (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*], - string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => { + ([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => { match *self { $(NonTSPseudoClass::$name => check_flag!($flags),)* - $(NonTSPseudoClass::$s_name(..) => check_flag!($s_flags),)* NonTSPseudoClass::MozLocaleDir(_) | + NonTSPseudoClass::Lang(_) | NonTSPseudoClass::Dir(_) | NonTSPseudoClass::MozAny(_) => false, } @@ -194,9 +181,8 @@ impl NonTSPseudoClass { }, // Otherwise, a pseudo-class is enabled in content when it // doesn't have any enabled flag. - _ => !self.has_any_flag( - NonTSPseudoClassFlag::PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, - ), + _ => !self + .has_any_flag(NonTSPseudoClassFlag::PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME), } } @@ -221,13 +207,12 @@ impl NonTSPseudoClass { }; } macro_rules! pseudo_class_state { - (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*], - string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => { + ([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => { match *self { $(NonTSPseudoClass::$name => flag!($state),)* - $(NonTSPseudoClass::$s_name(..) => flag!($s_state),)* NonTSPseudoClass::Dir(..) | NonTSPseudoClass::MozLocaleDir(..) | + NonTSPseudoClass::Lang(..) | NonTSPseudoClass::MozAny(..) => ElementState::empty(), } } @@ -247,8 +232,7 @@ impl NonTSPseudoClass { /// Returns true if the given pseudoclass should trigger style sharing cache /// revalidation. pub fn needs_cache_revalidation(&self) -> bool { - self.state_flag().is_empty() && - !matches!(*self, + self.state_flag().is_empty() && !matches!(*self, // :-moz-any is handled by the revalidation visitor walking // the things inside it; it does not need to cause // revalidation on its own. @@ -282,7 +266,8 @@ impl NonTSPseudoClass { pub fn is_attr_based(&self) -> bool { matches!( *self, - NonTSPseudoClass::MozTableBorderNonzero | NonTSPseudoClass::MozBrowserFrame | + NonTSPseudoClass::MozTableBorderNonzero | + NonTSPseudoClass::MozBrowserFrame | NonTSPseudoClass::Lang(..) ) } @@ -398,42 +383,29 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { name: CowRcStr<'i>, parser: &mut Parser<'i, 't>, ) -> Result<NonTSPseudoClass, ParseError<'i>> { - macro_rules! pseudo_class_string_parse { - (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*], - string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => { - match_ignore_ascii_case! { &name, - $($s_css => { - let name = parser.expect_ident_or_string()?; - // convert to null terminated utf16 string - // since that's what Gecko deals with - let utf16: Vec<u16> = name.encode_utf16().chain(Some(0u16)).collect(); - NonTSPseudoClass::$s_name(utf16.into_boxed_slice().into()) - }, )* - "-moz-locale-dir" => { - NonTSPseudoClass::MozLocaleDir( - Box::new(Direction::parse(parser)?) - ) - }, - "dir" => { - NonTSPseudoClass::Dir( - Box::new(Direction::parse(parser)?) - ) - }, - "-moz-any" => { - NonTSPseudoClass::MozAny( - selector_parser::parse_compound_selector_list( - self, - parser, - )?.into() - ) - } - _ => return Err(parser.new_custom_error( - SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name.clone()) - )) - } + let pseudo_class = match_ignore_ascii_case! { &name, + "lang" => { + let name = parser.expect_ident_or_string()?; + NonTSPseudoClass::Lang(Atom::from(name.as_ref())) + }, + "-moz-locale-dir" => { + NonTSPseudoClass::MozLocaleDir(Direction::parse(parser)?) + }, + "dir" => { + NonTSPseudoClass::Dir(Direction::parse(parser)?) + }, + "-moz-any" => { + NonTSPseudoClass::MozAny( + selector_parser::parse_compound_selector_list( + self, + parser, + )?.into() + ) } - } - let pseudo_class = apply_non_ts_list!(pseudo_class_string_parse); + _ => return Err(parser.new_custom_error( + SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name.clone()) + )) + }; if self.is_pseudo_class_enabled(&pseudo_class) { Ok(pseudo_class) } else { @@ -468,8 +440,7 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { name: CowRcStr<'i>, parser: &mut Parser<'i, 't>, ) -> Result<PseudoElement, ParseError<'i>> { - // FIXME: -moz-tree check should probably be ascii-case-insensitive. - if name.starts_with("-moz-tree-") { + if starts_with_ignore_ascii_case(&name, "-moz-tree-") { // Tree pseudo-elements can have zero or more arguments, separated // by either comma or space. let mut args = Vec::new(); diff --git a/components/style/gecko/snapshot_helpers.rs b/components/style/gecko/snapshot_helpers.rs index 6c40f242d5f..371a2b78da1 100644 --- a/components/style/gecko/snapshot_helpers.rs +++ b/components/style/gecko/snapshot_helpers.rs @@ -41,15 +41,26 @@ unsafe fn get_class_from_attr(attr: &structs::nsAttrValue) -> Class { debug_assert_eq!(base_type, structs::nsAttrValue_ValueBaseType_eOtherBase); let container = ptr::<structs::MiscContainer>(attr); - debug_assert_eq!((*container).mType, structs::nsAttrValue_ValueType_eAtomArray); - let array = - (*container).__bindgen_anon_1.mValue.as_ref().__bindgen_anon_1.mAtomArray.as_ref(); + debug_assert_eq!( + (*container).mType, + structs::nsAttrValue_ValueType_eAtomArray + ); + let array = (*container) + .__bindgen_anon_1 + .mValue + .as_ref() + .__bindgen_anon_1 + .mAtomArray + .as_ref(); Class::More(&***array) } #[inline(always)] unsafe fn get_id_from_attr(attr: &structs::nsAttrValue) -> &WeakAtom { - debug_assert_eq!(base_type(attr), structs::nsAttrValue_ValueBaseType_eAtomBase); + debug_assert_eq!( + base_type(attr), + structs::nsAttrValue_ValueBaseType_eAtomBase + ); WeakAtom::new(ptr::<nsAtom>(attr)) } @@ -59,7 +70,8 @@ pub fn find_attr<'a>( attrs: &'a [structs::AttrArray_InternalAttr], name: &Atom, ) -> Option<&'a structs::nsAttrValue> { - attrs.iter() + attrs + .iter() .find(|attr| attr.mName.mBits == name.as_ptr() as usize) .map(|attr| &attr.mValue) } @@ -80,19 +92,17 @@ pub fn has_class( ) -> bool { match unsafe { get_class_from_attr(attr) } { Class::None => false, - Class::One(atom) => unsafe { - case_sensitivity.eq_atom(name, WeakAtom::new(atom)) + Class::One(atom) => unsafe { case_sensitivity.eq_atom(name, WeakAtom::new(atom)) }, + Class::More(atoms) => match case_sensitivity { + CaseSensitivity::CaseSensitive => { + atoms.iter().any(|atom| atom.mRawPtr == name.as_ptr()) + }, + CaseSensitivity::AsciiCaseInsensitive => unsafe { + atoms + .iter() + .any(|atom| WeakAtom::new(atom.mRawPtr).eq_ignore_ascii_case(name)) + }, }, - Class::More(atoms) => { - match case_sensitivity { - CaseSensitivity::CaseSensitive => { - atoms.iter().any(|atom| atom.mRawPtr == name.as_ptr()) - } - CaseSensitivity::AsciiCaseInsensitive => unsafe { - atoms.iter().any(|atom| WeakAtom::new(atom.mRawPtr).eq_ignore_ascii_case(name)) - } - } - } } } @@ -111,7 +121,7 @@ where for atom in atoms { Atom::with(atom.mRawPtr, &mut callback) } - } + }, } } } diff --git a/components/style/gecko/url.rs b/components/style/gecko/url.rs index b94d2139764..8d785cae679 100644 --- a/components/style/gecko/url.rs +++ b/components/style/gecko/url.rs @@ -55,8 +55,7 @@ impl CssUrl { /// Convert from URLValueData to SpecifiedUrl. unsafe fn from_url_value_data(url: &URLValueData) -> Self { - let arc_type = - &url.mString as *const _ as *const RawOffsetArc<String>; + let arc_type = &url.mString as *const _ as *const RawOffsetArc<String>; CssUrl { serialization: Arc::from_raw_offset((*arc_type).clone()), extra_data: UrlExtraData(url.mExtraData.to_safe()), @@ -140,7 +139,6 @@ impl SpecifiedUrl { } } - impl PartialEq for SpecifiedUrl { fn eq(&self, other: &Self) -> bool { self.url.eq(&other.url) @@ -255,10 +253,7 @@ impl ToComputedValue for SpecifiedImageUrl { } } -fn serialize_computed_url<W>( - url_value_data: &URLValueData, - dest: &mut CssWriter<W>, -) -> fmt::Result +fn serialize_computed_url<W>(url_value_data: &URLValueData, dest: &mut CssWriter<W>) -> fmt::Result where W: Write, { @@ -281,7 +276,7 @@ pub struct ComputedUrl(pub SpecifiedUrl); impl ToCss for ComputedUrl { fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where - W: Write + W: Write, { serialize_computed_url(&self.0.url_value._base, dest) } @@ -302,7 +297,7 @@ pub struct ComputedImageUrl(pub SpecifiedImageUrl); impl ToCss for ComputedImageUrl { fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where - W: Write + W: Write, { serialize_computed_url(&self.0.image_value._base, dest) } diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs index 3bb22947211..fed9dc161c0 100644 --- a/components/style/gecko/values.rs +++ b/components/style/gecko/values.rs @@ -488,7 +488,9 @@ where /// Convert a given RGBA value to `nscolor`. pub fn convert_rgba_to_nscolor(rgba: &RGBA) -> u32 { - ((rgba.alpha as u32) << 24) | ((rgba.blue as u32) << 16) | ((rgba.green as u32) << 8) | + ((rgba.alpha as u32) << 24) | + ((rgba.blue as u32) << 16) | + ((rgba.green as u32) << 8) | (rgba.red as u32) } @@ -537,8 +539,7 @@ impl CounterStyleOrNone { .map(|symbol| match *symbol { Symbol::String(ref s) => nsCStr::from(s), Symbol::Ident(_) => unreachable!("Should not have identifier in symbols()"), - }) - .collect(); + }).collect(); let symbols: Vec<_> = symbols .iter() .map(|symbol| symbol as &nsACString as *const _) diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 1ba850696d1..efe37e647c5 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -69,7 +69,7 @@ use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock}; use properties::animated_properties::{AnimationValue, AnimationValueMap}; use properties::style_structs::Font; use rule_tree::CascadeLevel as ServoCascadeLevel; -use selector_parser::{AttrValue, Direction, PseudoClassStringArg}; +use selector_parser::{AttrValue, HorizontalDirection, Lang}; use selectors::{Element, OpaqueElement}; use selectors::attr::{AttrSelectorOperation, AttrSelectorOperator}; use selectors::attr::{CaseSensitivity, NamespaceConstraint}; @@ -86,7 +86,6 @@ use std::ptr; use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace}; use stylist::CascadeData; - #[inline] fn elements_with_id<'a, 'le>( array: *const structs::nsTArray<*mut RawGeckoElement>, @@ -167,18 +166,16 @@ impl<'lr> TShadowRoot for GeckoShadowRoot<'lr> { } #[inline] - fn style_data<'a>(&self) -> &'a CascadeData + fn style_data<'a>(&self) -> Option<&'a CascadeData> where Self: 'a, { - debug_assert!(!self.0.mServoStyles.mPtr.is_null()); - let author_styles = unsafe { - &*(self.0.mServoStyles.mPtr as *const structs::RawServoAuthorStyles + (self.0.mServoStyles.mPtr as *const structs::RawServoAuthorStyles as *const bindings::RawServoAuthorStyles) + .as_ref()? }; - let author_styles = AuthorStyles::<GeckoStyleSheet>::from_ffi(author_styles); debug_assert!( @@ -187,7 +184,7 @@ impl<'lr> TShadowRoot for GeckoShadowRoot<'lr> { author_styles.stylesheets.dirty() ); - &author_styles.data + Some(&author_styles.data) } #[inline] @@ -376,7 +373,8 @@ impl<'ln> TNode for GeckoNode<'ln> { fn first_child(&self) -> Option<Self> { unsafe { self.0 - .mFirstChild.raw::<nsIContent>() + .mFirstChild + .raw::<nsIContent>() .as_ref() .map(GeckoNode::from_content) } @@ -396,7 +394,8 @@ impl<'ln> TNode for GeckoNode<'ln> { fn next_sibling(&self) -> Option<Self> { unsafe { self.0 - .mNextSibling.raw::<nsIContent>() + .mNextSibling + .raw::<nsIContent>() .as_ref() .map(GeckoNode::from_content) } @@ -601,7 +600,7 @@ impl<'le> GeckoElement<'le> { if self.is_svg_element() { let svg_class = unsafe { bindings::Gecko_GetSVGAnimatedClass(self.0).as_ref() }; if let Some(c) = svg_class { - return Some(c) + return Some(c); } } @@ -673,8 +672,7 @@ impl<'le> GeckoElement<'le> { // For the bit usage, see nsContentSlots::GetExtendedSlots. let e_slots = s._base.mExtendedSlots & !structs::nsIContent_nsContentSlots_sNonOwningExtendedSlotsFlag; - (e_slots as *const structs::FragmentOrElement_nsExtendedDOMSlots) - .as_ref() + (e_slots as *const structs::FragmentOrElement_nsExtendedDOMSlots).as_ref() }) } @@ -720,9 +718,8 @@ impl<'le> GeckoElement<'le> { .and_then(|n| n.as_element()); debug_assert!( - binding_parent == unsafe { - bindings::Gecko_GetBindingParent(self.0).map(GeckoElement) - } + binding_parent == + unsafe { bindings::Gecko_GetBindingParent(self.0).map(GeckoElement) } ); binding_parent } @@ -731,8 +728,9 @@ impl<'le> GeckoElement<'le> { #[inline] fn non_xul_xbl_binding_parent_raw_content(&self) -> *mut nsIContent { debug_assert!(!self.is_xul_element()); - self.extended_slots() - .map_or(ptr::null_mut(), |slots| slots._base.mBindingParent.raw::<nsIContent>()) + self.extended_slots().map_or(ptr::null_mut(), |slots| { + slots._base.mBindingParent.raw::<nsIContent>() + }) } #[inline] @@ -748,7 +746,8 @@ impl<'le> GeckoElement<'le> { #[inline] fn state_internal(&self) -> u64 { - if !self.as_node() + if !self + .as_node() .get_bool_flag(nsINode_BooleanFlag::ElementHasLockedStyleStates) { return self.0.mState.mStates; @@ -879,9 +878,7 @@ impl<'le> GeckoElement<'le> { return false; } match self.containing_shadow_host() { - Some(e) => { - e.is_svg_element() && e.local_name() == &*local_name!("use") - }, + Some(e) => e.is_svg_element() && e.local_name() == &*local_name!("use"), None => false, } } @@ -935,13 +932,12 @@ impl<'le> GeckoElement<'le> { debug_assert_eq!(to.is_some(), from.is_some()); - combined_duration > 0.0f32 && from != to && - from.unwrap() - .animate( - to.as_ref().unwrap(), - Procedure::Interpolate { progress: 0.5 }, - ) - .is_ok() + combined_duration > 0.0f32 && from != to && from + .unwrap() + .animate( + to.as_ref().unwrap(), + Procedure::Interpolate { progress: 0.5 }, + ).is_ok() } } @@ -981,7 +977,9 @@ fn get_animation_rule( let effect_count = unsafe { Gecko_GetAnimationEffectCount(element.0) }; // Also, we should try to reuse the PDB, to avoid creating extra rule nodes. let mut animation_values = AnimationValueMap::with_capacity_and_hasher( - effect_count.min(ANIMATABLE_PROPERTY_COUNT), Default::default()); + effect_count.min(ANIMATABLE_PROPERTY_COUNT), + Default::default(), + ); if unsafe { Gecko_GetAnimationRule( element.0, @@ -1085,10 +1083,12 @@ impl<'le> TElement for GeckoElement<'le> { fn inheritance_parent(&self) -> Option<Self> { if self.implemented_pseudo_element().is_some() { - return self.pseudo_element_originating_element() + return self.pseudo_element_originating_element(); } - self.as_node().flattened_tree_parent().and_then(|n| n.as_element()) + self.as_node() + .flattened_tree_parent() + .and_then(|n| n.as_element()) } fn traversal_children(&self) -> LayoutIterator<GeckoChildrenIterator<'le>> { @@ -1096,8 +1096,10 @@ impl<'le> TElement for GeckoElement<'le> { // StyleChildrenIterator::IsNeeded does, except that it might return // true if we used to (but no longer) have anonymous content from // ::before/::after, XBL bindings, or nsIAnonymousContentCreators. - if self.is_in_anonymous_subtree() || self.has_xbl_binding_with_content() || - self.is_html_slot_element() || self.shadow_root().is_some() || + if self.is_in_anonymous_subtree() || + self.has_xbl_binding_with_content() || + self.is_html_slot_element() || + self.shadow_root().is_some() || self.may_have_anonymous_children() { unsafe { @@ -1158,17 +1160,16 @@ impl<'le> TElement for GeckoElement<'le> { // Bug 1466580 tracks running the Android layout tests on automation. // // The actual bindgen bug still needs reduction. - let assigned_nodes: &[structs::RefPtr<structs::nsINode>] = - if !cfg!(target_os = "android") { - debug_assert_eq!( - unsafe { bindings::Gecko_GetAssignedNodes(self.0) }, - &slot.mAssignedNodes as *const _, - ); + let assigned_nodes: &[structs::RefPtr<structs::nsINode>] = if !cfg!(target_os = "android") { + debug_assert_eq!( + unsafe { bindings::Gecko_GetAssignedNodes(self.0) }, + &slot.mAssignedNodes as *const _, + ); - &*slot.mAssignedNodes - } else { - unsafe { &**bindings::Gecko_GetAssignedNodes(self.0) } - }; + &*slot.mAssignedNodes + } else { + unsafe { &**bindings::Gecko_GetAssignedNodes(self.0) } + }; debug_assert_eq!( mem::size_of::<structs::RefPtr<structs::nsINode>>(), @@ -1240,11 +1241,10 @@ impl<'le> TElement for GeckoElement<'le> { } fn owner_doc_matches_for_testing(&self, device: &Device) -> bool { - self.as_node().owner_doc().0 as *const structs::nsIDocument == - device - .pres_context() - .mDocument - .raw::<structs::nsIDocument>() + self.as_node().owner_doc().0 as *const structs::nsIDocument == device + .pres_context() + .mDocument + .raw::<structs::nsIDocument>() } fn style_attribute(&self) -> Option<ArcBorrow<Locked<PropertyDeclarationBlock>>> { @@ -1379,7 +1379,8 @@ impl<'le> TElement for GeckoElement<'le> { self.unset_flags( ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32 | ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO as u32 | - NODE_DESCENDANTS_NEED_FRAMES as u32 | NODE_NEEDS_FRAME as u32, + NODE_DESCENDANTS_NEED_FRAMES as u32 | + NODE_NEEDS_FRAME as u32, ) } @@ -1439,8 +1440,10 @@ impl<'le> TElement for GeckoElement<'le> { unsafe fn clear_data(&self) { let ptr = self.0.mServoData.get(); self.unset_flags( - ELEMENT_HAS_SNAPSHOT as u32 | ELEMENT_HANDLED_SNAPSHOT as u32 | - structs::Element_kAllServoDescendantBits | NODE_NEEDS_FRAME as u32, + ELEMENT_HAS_SNAPSHOT as u32 | + ELEMENT_HANDLED_SNAPSHOT as u32 | + structs::Element_kAllServoDescendantBits | + NODE_NEEDS_FRAME as u32, ); if !ptr.is_null() { debug!("Dropping ElementData for {:?}", self); @@ -1669,8 +1672,7 @@ impl<'le> TElement for GeckoElement<'le> { let transition_property: TransitionProperty = property.into(); let mut property_check_helper = |property: LonghandId| -> bool { - let property = - property.to_physical(after_change_style.writing_mode); + let property = property.to_physical(after_change_style.writing_mode); transitions_to_keep.insert(property); self.needs_transitions_update_per_property( property, @@ -1682,8 +1684,7 @@ impl<'le> TElement for GeckoElement<'le> { }; match transition_property { - TransitionProperty::Custom(..) | - TransitionProperty::Unsupported(..) => {}, + TransitionProperty::Custom(..) | TransitionProperty::Unsupported(..) => {}, TransitionProperty::Shorthand(ref shorthand) => { if shorthand.longhands().any(property_check_helper) { return true; @@ -1714,18 +1715,10 @@ impl<'le> TElement for GeckoElement<'le> { } } - fn match_element_lang( - &self, - override_lang: Option<Option<AttrValue>>, - value: &PseudoClassStringArg, - ) -> bool { + fn match_element_lang(&self, override_lang: Option<Option<AttrValue>>, value: &Lang) -> bool { // Gecko supports :lang() from CSS Selectors 3, which only accepts a // single language tag, and which performs simple dash-prefix matching // on it. - debug_assert!( - value.len() > 0 && value[value.len() - 1] == 0, - "expected value to be null terminated" - ); let override_lang_ptr = match &override_lang { &Some(Some(ref atom)) => atom.as_ptr(), _ => ptr::null_mut(), @@ -1735,7 +1728,7 @@ impl<'le> TElement for GeckoElement<'le> { self.0, override_lang_ptr, override_lang.is_some(), - value.as_ptr(), + value.as_slice().as_ptr(), ) } } @@ -1865,7 +1858,8 @@ impl<'le> TElement for GeckoElement<'le> { )); } - let active = self.state() + let active = self + .state() .intersects(NonTSPseudoClass::Active.state_flag()); if active { let declarations = unsafe { Gecko_GetActiveLinkAttrDeclarationBlock(self.0) }; @@ -2075,7 +2069,10 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { #[inline] fn is_root(&self) -> bool { - if self.as_node().get_bool_flag(nsINode_BooleanFlag::ParentIsContent) { + if self + .as_node() + .get_bool_flag(nsINode_BooleanFlag::ParentIsContent) + { return false; } @@ -2083,12 +2080,17 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { return false; } - debug_assert!(self.as_node().parent_node().map_or(false, |p| p.is_document())); + debug_assert!( + self.as_node() + .parent_node() + .map_or(false, |p| p.is_document()) + ); unsafe { bindings::Gecko_IsRootElement(self.0) } } fn is_empty(&self) -> bool { - !self.as_node() + !self + .as_node() .dom_children() .any(|child| unsafe { Gecko_IsSignificantChild(child.0, true) }) } @@ -2199,7 +2201,8 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { }, NonTSPseudoClass::MozOnlyWhitespace => { flags_setter(self, ElementSelectorFlags::HAS_EMPTY_SELECTOR); - if self.as_node() + if self + .as_node() .dom_children() .any(|c| c.contains_non_whitespace_content()) { @@ -2238,24 +2241,20 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { NonTSPseudoClass::MozLocaleDir(ref dir) => { let state_bit = DocumentState::NS_DOCUMENT_STATE_RTL_LOCALE; if context.extra_data.document_state.intersects(state_bit) { - // NOTE(emilio): We could still return false for - // Direction::Other(..), but we don't bother. + // NOTE(emilio): We could still return false for values + // other than "ltr" and "rtl", but we don't bother. return !context.in_negation(); } let doc_is_rtl = self.document_state().contains(state_bit); - match **dir { - Direction::Ltr => !doc_is_rtl, - Direction::Rtl => doc_is_rtl, - Direction::Other(..) => false, + match dir.as_horizontal_direction() { + Some(HorizontalDirection::Ltr) => !doc_is_rtl, + Some(HorizontalDirection::Rtl) => doc_is_rtl, + None => false, } }, - NonTSPseudoClass::Dir(ref dir) => match **dir { - Direction::Ltr => self.state().intersects(ElementState::IN_LTR_STATE), - Direction::Rtl => self.state().intersects(ElementState::IN_RTL_STATE), - Direction::Other(..) => false, - }, + NonTSPseudoClass::Dir(ref dir) => self.state().intersects(dir.element_state()), } } diff --git a/components/style/gecko_bindings/mod.rs b/components/style/gecko_bindings/mod.rs index eb3f0d220bf..166e2f66fd5 100644 --- a/components/style/gecko_bindings/mod.rs +++ b/components/style/gecko_bindings/mod.rs @@ -4,7 +4,12 @@ //! Gecko's C++ bindings, along with some rust helpers to ease its use. -#[allow(dead_code, improper_ctypes, non_camel_case_types, missing_docs)] +#[allow( + dead_code, + improper_ctypes, + non_camel_case_types, + missing_docs +)] pub mod bindings { include!(concat!(env!("OUT_DIR"), "/gecko/bindings.rs")); } @@ -13,8 +18,14 @@ pub mod bindings { // foreign structs to have `PhantomData`. We should remove this once the lint // ignores this case. -#[allow(dead_code, improper_ctypes, non_camel_case_types, non_snake_case, non_upper_case_globals, - missing_docs)] +#[allow( + dead_code, + improper_ctypes, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + missing_docs +)] pub mod structs { include!(concat!(env!("OUT_DIR"), "/gecko/structs.rs")); } diff --git a/components/style/gecko_bindings/sugar/ns_style_coord.rs b/components/style/gecko_bindings/sugar/ns_style_coord.rs index 3825c5520ec..bc3b195524d 100644 --- a/components/style/gecko_bindings/sugar/ns_style_coord.rs +++ b/components/style/gecko_bindings/sugar/ns_style_coord.rs @@ -52,7 +52,8 @@ impl nsStyleCoord_CalcValue { impl PartialEq for nsStyleCoord_CalcValue { fn eq(&self, other: &Self) -> bool { - self.mLength == other.mLength && self.mPercent == other.mPercent && + self.mLength == other.mLength && + self.mPercent == other.mPercent && self.mHasPercent == other.mHasPercent } } @@ -409,9 +410,12 @@ pub unsafe trait CoordData { unsafe fn get_float(&self) -> f32 { use gecko_bindings::structs::nsStyleUnit::*; debug_assert!( - self.unit() == eStyleUnit_Percent || self.unit() == eStyleUnit_Factor || - self.unit() == eStyleUnit_Degree || self.unit() == eStyleUnit_Grad || - self.unit() == eStyleUnit_Radian || self.unit() == eStyleUnit_Turn || + self.unit() == eStyleUnit_Percent || + self.unit() == eStyleUnit_Factor || + self.unit() == eStyleUnit_Degree || + self.unit() == eStyleUnit_Grad || + self.unit() == eStyleUnit_Radian || + self.unit() == eStyleUnit_Turn || self.unit() == eStyleUnit_FlexFraction ); *self.union().mFloat.as_ref() @@ -422,7 +426,8 @@ pub unsafe trait CoordData { unsafe fn get_integer(&self) -> i32 { use gecko_bindings::structs::nsStyleUnit::*; debug_assert!( - self.unit() == eStyleUnit_Coord || self.unit() == eStyleUnit_Integer || + self.unit() == eStyleUnit_Coord || + self.unit() == eStyleUnit_Integer || self.unit() == eStyleUnit_Enumerated ); *self.union().mInt.as_ref() diff --git a/components/style/gecko_bindings/sugar/ownership.rs b/components/style/gecko_bindings/sugar/ownership.rs index 2bc85f53ff7..91c7a504eb1 100644 --- a/components/style/gecko_bindings/sugar/ownership.rs +++ b/components/style/gecko_bindings/sugar/ownership.rs @@ -305,6 +305,15 @@ pub struct OwnedOrNull<GeckoType> { } impl<GeckoType> OwnedOrNull<GeckoType> { + /// Returns a null pointer. + #[inline] + pub fn null() -> Self { + Self { + ptr: ptr::null_mut(), + _marker: PhantomData, + } + } + /// Returns whether this pointer is null. #[inline] pub fn is_null(&self) -> bool { diff --git a/components/style/gecko_bindings/sugar/refptr.rs b/components/style/gecko_bindings/sugar/refptr.rs index 6a32b81430e..835e77098c9 100644 --- a/components/style/gecko_bindings/sugar/refptr.rs +++ b/components/style/gecko_bindings/sugar/refptr.rs @@ -321,8 +321,4 @@ unsafe fn addref_atom(atom: *mut structs::nsAtom) { unsafe fn release_atom(atom: *mut structs::nsAtom) { let _ = Atom::from_addrefed(atom); } -impl_threadsafe_refcount!( - structs::nsAtom, - addref_atom, - release_atom -); +impl_threadsafe_refcount!(structs::nsAtom, addref_atom, release_atom); diff --git a/components/style/gecko_bindings/sugar/style_complex_color.rs b/components/style/gecko_bindings/sugar/style_complex_color.rs index 90e93b72fd0..c2b3b1c6270 100644 --- a/components/style/gecko_bindings/sugar/style_complex_color.rs +++ b/components/style/gecko_bindings/sugar/style_complex_color.rs @@ -59,7 +59,7 @@ impl From<ComputedColor> for StyleComplexColor { mFgRatio: ratios.fg, mTag: Tag::eComplex, } - } + }, } } } @@ -70,11 +70,11 @@ impl From<StyleComplexColor> for ComputedColor { Tag::eNumeric => { debug_assert!(other.mBgRatio == 1. && other.mFgRatio == 0.); GenericColor::Numeric(convert_nscolor_to_rgba(other.mColor)) - } + }, Tag::eForeground => { debug_assert!(other.mBgRatio == 0. && other.mFgRatio == 1.); GenericColor::Foreground - } + }, Tag::eComplex => { debug_assert!(other.mBgRatio != 1. || other.mFgRatio != 0.); debug_assert!(other.mBgRatio != 0. || other.mFgRatio != 1.); @@ -85,7 +85,7 @@ impl From<StyleComplexColor> for ComputedColor { fg: other.mFgRatio, }, ) - } + }, Tag::eAuto => unreachable!("Unsupport StyleComplexColor with tag eAuto"), } } diff --git a/components/style/invalidation/element/element_wrapper.rs b/components/style/invalidation/element/element_wrapper.rs index cb4f79e92e1..cd1b1d13a25 100644 --- a/components/style/invalidation/element/element_wrapper.rs +++ b/components/style/invalidation/element/element_wrapper.rs @@ -46,7 +46,9 @@ pub trait ElementSnapshot: Sized { /// Gets the attribute information of the snapshot as a string. /// /// Only for debugging purposes. - fn debug_list_attributes(&self) -> String { String::new() } + fn debug_list_attributes(&self) -> String { + String::new() + } /// The ID attribute per this snapshot. Should only be called if /// `has_attrs()` returns true. @@ -188,8 +190,7 @@ where // support we don't forget to update this code? #[cfg(feature = "gecko")] NonTSPseudoClass::Dir(ref dir) => { - use invalidation::element::invalidation_map::dir_selector_to_state; - let selector_flag = dir_selector_to_state(dir); + let selector_flag = dir.element_state(); if selector_flag.is_empty() { // :dir() with some random argument; does not match. return false; @@ -234,7 +235,8 @@ where // :lang() needs to match using the closest ancestor xml:lang="" or // lang="" attribtue from snapshots. NonTSPseudoClass::Lang(ref lang_arg) => { - return self.element + return self + .element .match_element_lang(Some(self.get_lang()), lang_arg); }, @@ -243,12 +245,14 @@ where let flag = pseudo_class.state_flag(); if flag.is_empty() { - return self.element + return self + .element .match_non_ts_pseudo_class(pseudo_class, context, &mut |_, _| {}); } match self.snapshot().and_then(|s| s.state()) { Some(snapshot_state) => snapshot_state.intersects(flag), - None => self.element + None => self + .element .match_non_ts_pseudo_class(pseudo_class, context, &mut |_, _| {}), } } diff --git a/components/style/invalidation/element/invalidation_map.rs b/components/style/invalidation/element/invalidation_map.rs index 67849d89627..038852a6dd4 100644 --- a/components/style/invalidation/element/invalidation_map.rs +++ b/components/style/invalidation/element/invalidation_map.rs @@ -10,8 +10,6 @@ use element_state::{DocumentState, ElementState}; use fallible::FallibleVec; use hashglobe::FailedAllocationError; use selector_map::{MaybeCaseInsensitiveHashMap, SelectorMap, SelectorMapEntry}; -#[cfg(feature = "gecko")] -use selector_parser::Direction; use selector_parser::SelectorImpl; use selectors::attr::NamespaceConstraint; use selectors::parser::{Combinator, Component}; @@ -19,20 +17,6 @@ use selectors::parser::{Selector, SelectorIter, Visit}; use selectors::visitor::SelectorVisitor; use smallvec::SmallVec; -#[cfg(feature = "gecko")] -/// Gets the element state relevant to the given `:dir` pseudo-class selector. -pub fn dir_selector_to_state(dir: &Direction) -> ElementState { - match *dir { - Direction::Ltr => ElementState::IN_LTR_STATE, - Direction::Rtl => ElementState::IN_RTL_STATE, - Direction::Other(_) => { - // :dir(something-random) is a valid selector, but shouldn't - // match anything. - ElementState::empty() - }, - } -} - /// Mapping between (partial) CompoundSelectors (and the combinator to their /// right) and the states and attributes they depend on. /// @@ -54,8 +38,10 @@ pub fn dir_selector_to_state(dir: &Direction) -> ElementState { #[derive(Clone, Debug, MallocSizeOf)] pub struct Dependency { /// The dependency selector. - #[cfg_attr(feature = "gecko", - ignore_malloc_size_of = "CssRules have primary refs, we measure there")] + #[cfg_attr( + feature = "gecko", + ignore_malloc_size_of = "CssRules have primary refs, we measure there" + )] #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")] pub selector: Selector<SelectorImpl>, @@ -143,8 +129,10 @@ impl SelectorMapEntry for StateDependency { pub struct DocumentStateDependency { /// The selector that is affected. We don't need to track an offset, since /// when it changes it changes for the whole document anyway. - #[cfg_attr(feature = "gecko", - ignore_malloc_size_of = "CssRules have primary refs, we measure there")] + #[cfg_attr( + feature = "gecko", + ignore_malloc_size_of = "CssRules have primary refs, we measure there" + )] #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")] pub selector: Selector<SelectorImpl>, /// The state this dependency is affected by. @@ -201,7 +189,8 @@ impl InvalidationMap { /// Returns the number of dependencies stored in the invalidation map. pub fn len(&self) -> usize { - self.state_affecting_selectors.len() + self.document_state_selectors.len() + + self.state_affecting_selectors.len() + + self.document_state_selectors.len() + self.other_attribute_affecting_selectors.len() + self.id_to_selector .iter() @@ -382,7 +371,7 @@ impl<'a> SelectorVisitor for CompoundSelectorDependencyCollector<'a> { self.other_attributes |= pc.is_attr_based(); self.state |= match *pc { #[cfg(feature = "gecko")] - NonTSPseudoClass::Dir(ref dir) => dir_selector_to_state(dir), + NonTSPseudoClass::Dir(ref dir) => dir.element_state(), _ => pc.state_flag(), }; *self.document_state |= pc.document_state_flag(); diff --git a/components/style/invalidation/element/restyle_hints.rs b/components/style/invalidation/element/restyle_hints.rs index 4ac06c8b163..18e2f96470a 100644 --- a/components/style/invalidation/element/restyle_hints.rs +++ b/components/style/invalidation/element/restyle_hints.rs @@ -67,7 +67,8 @@ impl RestyleHint { /// Returns whether we need to restyle this element. pub fn has_non_animation_invalidations(&self) -> bool { self.intersects( - RestyleHint::RESTYLE_SELF | RestyleHint::RECASCADE_SELF | + RestyleHint::RESTYLE_SELF | + RestyleHint::RECASCADE_SELF | (Self::replacements() & !Self::for_animations()), ) } @@ -119,7 +120,8 @@ impl RestyleHint { /// The replacements for the animation cascade levels. #[inline] pub fn for_animations() -> Self { - RestyleHint::RESTYLE_SMIL | RestyleHint::RESTYLE_CSS_ANIMATIONS | + RestyleHint::RESTYLE_SMIL | + RestyleHint::RESTYLE_CSS_ANIMATIONS | RestyleHint::RESTYLE_CSS_TRANSITIONS } diff --git a/components/style/invalidation/element/state_and_attributes.rs b/components/style/invalidation/element/state_and_attributes.rs index 1eb022b298a..bf259bb6f02 100644 --- a/components/style/invalidation/element/state_and_attributes.rs +++ b/components/style/invalidation/element/state_and_attributes.rs @@ -155,17 +155,11 @@ where return false; } - // If we are sensitive to visitedness and the visited state changed, we - // force a restyle here. Matching doesn't depend on the actual visited - // state at all, so we can't look at matching results to decide what to - // do for this case. + // If we the visited state changed, we force a restyle here. Matching + // doesn't depend on the actual visited state at all, so we can't look + // at matching results to decide what to do for this case. if state_changes.intersects(ElementState::IN_VISITED_OR_UNVISITED_STATE) { trace!(" > visitedness change, force subtree restyle"); - // If we get here with visited links disabled, we should probably - // just avoid the restyle and remove the state change here, not only - // as an optimization, but also because it kind of would kill the - // point of disabling visited links. - debug_assert!(self.shared_context.visited_styles_enabled); // We can't just return here because there may also be attribute // changes as well that imply additional hints for siblings. self.data.hint.insert(RestyleHint::restyle_subtree()); @@ -206,17 +200,12 @@ where debug!(" > state: {:?}", state_changes); } if snapshot.id_changed() { - debug!( - " > id changed: +{:?} -{:?}", - id_added, - id_removed - ); + debug!(" > id changed: +{:?} -{:?}", id_added, id_removed); } if snapshot.class_changed() { debug!( " > class changed: +{:?} -{:?}", - classes_added, - classes_removed + classes_added, classes_removed ); } if snapshot.other_attr_changed() { @@ -239,7 +228,6 @@ where shadow_rule_datas.push((data, quirks_mode, host.map(|h| h.opaque()))) }); - let invalidated_self = { let mut collector = Collector { wrapper, @@ -416,10 +404,7 @@ where } /// Check whether a dependency should be taken into account. - fn check_dependency( - &mut self, - dependency: &Dependency, - ) -> bool { + fn check_dependency(&mut self, dependency: &Dependency) -> bool { let element = &self.element; let wrapper = &self.wrapper; let matches_now = matches_selector( diff --git a/components/style/lib.rs b/components/style/lib.rs index 1c3630b0986..57d507a4ab4 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -157,6 +157,7 @@ pub mod thread_state; pub mod timer; pub mod traversal; pub mod traversal_flags; +pub mod use_counters; #[macro_use] #[allow(non_camel_case_types)] pub mod values; @@ -199,7 +200,6 @@ pub mod gecko; #[allow(unsafe_code)] pub mod servo; - #[cfg(feature = "gecko")] #[allow(unsafe_code, missing_docs)] pub mod gecko_properties { diff --git a/components/style/logical_geometry.rs b/components/style/logical_geometry.rs index b345c2ad375..8c677c210bf 100644 --- a/components/style/logical_geometry.rs +++ b/components/style/logical_geometry.rs @@ -957,8 +957,10 @@ impl<T: Copy> LogicalMargin<T> { impl<T: PartialEq + Zero> LogicalMargin<T> { #[inline] pub fn is_zero(&self) -> bool { - self.block_start == Zero::zero() && self.inline_end == Zero::zero() && - self.block_end == Zero::zero() && self.inline_start == Zero::zero() + self.block_start == Zero::zero() && + self.inline_end == Zero::zero() && + self.block_end == Zero::zero() && + self.inline_start == Zero::zero() } } diff --git a/components/style/macros.rs b/components/style/macros.rs index 671ba35b8bc..58889389336 100644 --- a/components/style/macros.rs +++ b/components/style/macros.rs @@ -68,9 +68,19 @@ macro_rules! try_match_ident_ignore_ascii_case { macro_rules! define_keyword_type { ($name:ident, $css:expr) => { #[allow(missing_docs)] - #[derive(Animate, Clone, ComputeSquaredDistance, Copy, MallocSizeOf, - PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, - ToComputedValue, ToCss)] + #[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToCss, + )] pub struct $name; impl fmt::Debug for $name { diff --git a/components/style/matching.rs b/components/style/matching.rs index 6f239d361d8..922ecad9eb4 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -356,10 +356,9 @@ trait PrivateMatchMethods: TElement { tasks.insert(UpdateAnimationsTasks::CSS_ANIMATIONS); } - let before_change_style = if self.might_need_transitions_update( - old_values.as_ref().map(|s| &**s), - new_values, - ) { + let before_change_style = if self + .might_need_transitions_update(old_values.as_ref().map(|s| &**s), new_values) + { let after_change_style = if self.has_css_transitions() { self.after_change_style(context, new_values) } else { @@ -469,9 +468,11 @@ trait PrivateMatchMethods: TElement { pseudo: Option<&PseudoElement>, ) -> ChildCascadeRequirement { debug!("accumulate_damage_for: {:?}", self); - debug_assert!(!shared_context - .traversal_flags - .contains(TraversalFlags::Forgetful)); + debug_assert!( + !shared_context + .traversal_flags + .contains(TraversalFlags::Forgetful) + ); let difference = self.compute_style_difference(old_values, new_values, pseudo); diff --git a/components/style/media_queries/media_condition.rs b/components/style/media_queries/media_condition.rs index dbd677d0aee..78252db8c0b 100644 --- a/components/style/media_queries/media_condition.rs +++ b/components/style/media_queries/media_condition.rs @@ -53,12 +53,12 @@ impl ToCss for MediaCondition { MediaCondition::Not(ref c) => { dest.write_str("not ")?; c.to_css(dest) - } + }, MediaCondition::InParens(ref c) => { dest.write_char('(')?; c.to_css(dest)?; dest.write_char(')') - } + }, MediaCondition::Operation(ref list, op) => { let mut iter = list.iter(); iter.next().unwrap().to_css(dest)?; @@ -69,7 +69,7 @@ impl ToCss for MediaCondition { item.to_css(dest)?; } Ok(()) - } + }, } } } @@ -104,14 +104,12 @@ impl MediaCondition { let is_negation = match *input.next()? { Token::ParenthesisBlock => false, Token::Ident(ref ident) if ident.eq_ignore_ascii_case("not") => true, - ref t => { - return Err(location.new_unexpected_token_error(t.clone())) - } + ref t => return Err(location.new_unexpected_token_error(t.clone())), }; if is_negation { let inner_condition = Self::parse_in_parens(context, input)?; - return Ok(MediaCondition::Not(Box::new(inner_condition))) + return Ok(MediaCondition::Not(Box::new(inner_condition))); } // ParenthesisBlock. @@ -162,7 +160,7 @@ impl MediaCondition { input.parse_nested_block(|input| { // Base case. if let Ok(inner) = input.try(|i| Self::parse(context, i)) { - return Ok(MediaCondition::InParens(Box::new(inner))) + return Ok(MediaCondition::InParens(Box::new(inner))); } let expr = MediaFeatureExpression::parse_in_parenthesis_block(context, input)?; Ok(MediaCondition::Feature(expr)) @@ -178,14 +176,10 @@ impl MediaCondition { MediaCondition::Operation(ref conditions, op) => { let mut iter = conditions.iter(); match op { - Operator::And => { - iter.all(|c| c.matches(device, quirks_mode)) - } - Operator::Or => { - iter.any(|c| c.matches(device, quirks_mode)) - } + Operator::And => iter.all(|c| c.matches(device, quirks_mode)), + Operator::Or => iter.any(|c| c.matches(device, quirks_mode)), } - } + }, } } } diff --git a/components/style/media_queries/media_feature.rs b/components/style/media_queries/media_feature.rs index 5a5bc88863e..771a11e8fbb 100644 --- a/components/style/media_queries/media_feature.rs +++ b/components/style/media_queries/media_feature.rs @@ -30,10 +30,9 @@ type MediaFeatureEvaluator<T> = fn( pub type KeywordSerializer = fn(KeywordDiscriminant) -> String; /// Parses a given identifier. -pub type KeywordParser = for <'a, 'i, 't> fn( - context: &'a ParserContext, - input: &'a mut Parser<'i, 't>, -) -> Result<KeywordDiscriminant, ParseError<'i>>; +pub type KeywordParser = + for<'a, 'i, 't> fn(context: &'a ParserContext, input: &'a mut Parser<'i, 't>) + -> Result<KeywordDiscriminant, ParseError<'i>>; /// An evaluator for a given media feature. /// @@ -70,50 +69,49 @@ pub enum Evaluator { /// asserts if that's not true. As of today there's nothing like that (does that /// even make sense?). macro_rules! keyword_evaluator { - ($actual_evaluator:ident, $keyword_type:ty) => { - { - fn __parse<'i, 't>( - context: &$crate::parser::ParserContext, - input: &mut $crate::cssparser::Parser<'i, 't>, - ) -> Result< - $crate::media_queries::media_feature::KeywordDiscriminant, - ::style_traits::ParseError<'i>, - > { - let kw = <$keyword_type as $crate::parser::Parse>::parse(context, input)?; - Ok(kw as $crate::media_queries::media_feature::KeywordDiscriminant) - } - - fn __serialize(kw: $crate::media_queries::media_feature::KeywordDiscriminant) -> String { - // This unwrap is ok because the only discriminants that get - // back to us is the ones that `parse` produces. - let value: $keyword_type = - ::num_traits::cast::FromPrimitive::from_u8(kw).unwrap(); - <$keyword_type as ::style_traits::ToCss>::to_css_string(&value) - } - - fn __evaluate( - device: &$crate::media_queries::Device, - value: Option<$crate::media_queries::media_feature::KeywordDiscriminant>, - range_or_operator: Option<$crate::media_queries::media_feature_expression::RangeOrOperator>, - ) -> bool { - debug_assert!( - range_or_operator.is_none(), - "Since when do keywords accept ranges?" - ); - // This unwrap is ok because the only discriminants that get - // back to us is the ones that `parse` produces. - let value: Option<$keyword_type> = - value.map(|kw| ::num_traits::cast::FromPrimitive::from_u8(kw).unwrap()); - $actual_evaluator(device, value) - } - - $crate::media_queries::media_feature::Evaluator::Enumerated { - parser: __parse, - serializer: __serialize, - evaluator: __evaluate, - } + ($actual_evaluator:ident, $keyword_type:ty) => {{ + fn __parse<'i, 't>( + context: &$crate::parser::ParserContext, + input: &mut $crate::cssparser::Parser<'i, 't>, + ) -> Result< + $crate::media_queries::media_feature::KeywordDiscriminant, + ::style_traits::ParseError<'i>, + > { + let kw = <$keyword_type as $crate::parser::Parse>::parse(context, input)?; + Ok(kw as $crate::media_queries::media_feature::KeywordDiscriminant) } - } + + fn __serialize(kw: $crate::media_queries::media_feature::KeywordDiscriminant) -> String { + // This unwrap is ok because the only discriminants that get + // back to us is the ones that `parse` produces. + let value: $keyword_type = ::num_traits::cast::FromPrimitive::from_u8(kw).unwrap(); + <$keyword_type as ::style_traits::ToCss>::to_css_string(&value) + } + + fn __evaluate( + device: &$crate::media_queries::Device, + value: Option<$crate::media_queries::media_feature::KeywordDiscriminant>, + range_or_operator: Option< + $crate::media_queries::media_feature_expression::RangeOrOperator, + >, + ) -> bool { + debug_assert!( + range_or_operator.is_none(), + "Since when do keywords accept ranges?" + ); + // This unwrap is ok because the only discriminants that get + // back to us is the ones that `parse` produces. + let value: Option<$keyword_type> = + value.map(|kw| ::num_traits::cast::FromPrimitive::from_u8(kw).unwrap()); + $actual_evaluator(device, value) + } + + $crate::media_queries::media_feature::Evaluator::Enumerated { + parser: __parse, + serializer: __serialize, + evaluator: __evaluate, + } + }}; } bitflags! { @@ -169,7 +167,7 @@ macro_rules! feature { evaluator: $evaluator, requirements: $reqs, } - } + }; } impl fmt::Debug for MediaFeatureDescription { diff --git a/components/style/media_queries/media_feature_expression.rs b/components/style/media_queries/media_feature_expression.rs index f07b8cc27e4..64406218e88 100644 --- a/components/style/media_queries/media_feature_expression.rs +++ b/components/style/media_queries/media_feature_expression.rs @@ -102,13 +102,9 @@ pub enum RangeOrOperator { impl RangeOrOperator { /// Evaluate a given range given an optional query value and a value from /// the browser. - pub fn evaluate<T>( - range_or_op: Option<Self>, - query_value: Option<T>, - value: T, - ) -> bool + pub fn evaluate<T>(range_or_op: Option<Self>, query_value: Option<T>, value: T) -> bool where - T: PartialOrd + Zero + T: PartialOrd + Zero, { match query_value { Some(v) => Self::evaluate_with_query_value(range_or_op, v, value), @@ -118,11 +114,7 @@ impl RangeOrOperator { /// Evaluate a given range given a non-optional query value and a value from /// the browser. - pub fn evaluate_with_query_value<T>( - range_or_op: Option<Self>, - query_value: T, - value: T, - ) -> bool + pub fn evaluate_with_query_value<T>(range_or_op: Option<Self>, query_value: T, value: T) -> bool where T: PartialOrd, { @@ -142,20 +134,14 @@ impl RangeOrOperator { Range::Min => cmp == Ordering::Greater, Range::Max => cmp == Ordering::Less, } - } - RangeOrOperator::Operator(op) => { - match op { - Operator::Equal => cmp == Ordering::Equal, - Operator::GreaterThan => cmp == Ordering::Greater, - Operator::GreaterThanEqual => { - cmp == Ordering::Equal || cmp == Ordering::Greater - } - Operator::LessThan => cmp == Ordering::Less, - Operator::LessThanEqual => { - cmp == Ordering::Equal || cmp == Ordering::Less - } - } - } + }, + RangeOrOperator::Operator(op) => match op { + Operator::Equal => cmp == Ordering::Equal, + Operator::GreaterThan => cmp == Ordering::Greater, + Operator::GreaterThanEqual => cmp == Ordering::Equal || cmp == Ordering::Greater, + Operator::LessThan => cmp == Ordering::Less, + Operator::LessThanEqual => cmp == Ordering::Equal || cmp == Ordering::Less, + }, } } } @@ -172,8 +158,8 @@ pub struct MediaFeatureExpression { impl PartialEq for MediaFeatureExpression { fn eq(&self, other: &Self) -> bool { self.feature as *const _ == other.feature as *const _ && - self.value == other.value && - self.range_or_operator == other.range_or_operator + self.value == other.value && + self.range_or_operator == other.range_or_operator } } @@ -184,7 +170,11 @@ impl ToCss for MediaFeatureExpression { { dest.write_str("(")?; - if self.feature.requirements.contains(ParsingRequirements::WEBKIT_PREFIX) { + if self + .feature + .requirements + .contains(ParsingRequirements::WEBKIT_PREFIX) + { dest.write_str("-webkit-")?; } @@ -215,9 +205,7 @@ impl ToCss for MediaFeatureExpression { } /// Consumes an operation or a colon, or returns an error. -fn consume_operation_or_colon( - input: &mut Parser, -) -> Result<Option<Operator>, ()> { +fn consume_operation_or_colon(input: &mut Parser) -> Result<Option<Operator>, ()> { let first_delim = { let next_token = match input.next() { Ok(t) => t, @@ -238,14 +226,14 @@ fn consume_operation_or_colon( } else { Operator::GreaterThan } - } + }, '<' => { if input.try(|i| i.expect_delim('=')).is_ok() { Operator::LessThanEqual } else { Operator::LessThan } - } + }, _ => return Err(()), })) } @@ -256,7 +244,11 @@ impl MediaFeatureExpression { value: Option<MediaExpressionValue>, range_or_operator: Option<RangeOrOperator>, ) -> Self { - Self { feature, value, range_or_operator } + Self { + feature, + value, + range_or_operator, + } } /// Parse a media expression of the form: @@ -269,9 +261,7 @@ impl MediaFeatureExpression { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { input.expect_parenthesis_block()?; - input.parse_nested_block(|input| { - Self::parse_in_parenthesis_block(context, input) - }) + input.parse_nested_block(|input| Self::parse_in_parenthesis_block(context, input)) } /// Parse a media feature expression where we've already consumed the @@ -294,9 +284,7 @@ impl MediaFeatureExpression { let mut requirements = ParsingRequirements::empty(); - if context.chrome_rules_enabled() || - context.stylesheet_origin == Origin::UserAgent - { + if context.chrome_rules_enabled() || context.stylesheet_origin == Origin::UserAgent { requirements.insert(ParsingRequirements::CHROME_AND_UA_ONLY); } @@ -313,7 +301,9 @@ impl MediaFeatureExpression { if unsafe { structs::StaticPrefs_sVarCache_layout_css_prefixes_device_pixel_ratio_webkit } { - requirements.insert(ParsingRequirements::WEBKIT_DEVICE_PIXEL_RATIO_PREF_ENABLED); + requirements.insert( + ParsingRequirements::WEBKIT_DEVICE_PIXEL_RATIO_PREF_ENABLED, + ); } } } @@ -370,45 +360,41 @@ impl MediaFeatureExpression { // Gecko doesn't allow ranged expressions without a // value, so just reject them here too. if range.is_some() { - return Err(input.new_custom_error( - StyleParseErrorKind::RangedExpressionWithNoValue - )); + return Err( + input.new_custom_error(StyleParseErrorKind::RangedExpressionWithNoValue) + ); } return Ok(Self::new(feature, None, None)); - } + }, Ok(operator) => operator, }; let range_or_operator = match range { Some(range) => { if operator.is_some() { - return Err(input.new_custom_error( - StyleParseErrorKind::MediaQueryUnexpectedOperator - )); + return Err( + input.new_custom_error(StyleParseErrorKind::MediaQueryUnexpectedOperator) + ); } Some(RangeOrOperator::Range(range)) - } - None => { - match operator { - Some(operator) => { - if !feature.allows_ranges() { - return Err(input.new_custom_error( - StyleParseErrorKind::MediaQueryUnexpectedOperator - )); - } - Some(RangeOrOperator::Operator(operator)) + }, + None => match operator { + Some(operator) => { + if !feature.allows_ranges() { + return Err(input + .new_custom_error(StyleParseErrorKind::MediaQueryUnexpectedOperator)); } - None => None, - } - } + Some(RangeOrOperator::Operator(operator)) + }, + None => None, + }, }; - let value = - MediaExpressionValue::parse(feature, context, input).map_err(|err| { - err.location - .new_custom_error(StyleParseErrorKind::MediaQueryExpectedFeatureValue) - })?; + let value = MediaExpressionValue::parse(feature, context, input).map_err(|err| { + err.location + .new_custom_error(StyleParseErrorKind::MediaQueryExpectedFeatureValue) + })?; Ok(Self::new(feature, Some(value), range_or_operator)) } @@ -419,13 +405,11 @@ impl MediaFeatureExpression { macro_rules! expect { ($variant:ident) => { - value.map(|value| { - match *value { - MediaExpressionValue::$variant(ref v) => v, - _ => unreachable!("Unexpected MediaExpressionValue"), - } + value.map(|value| match *value { + MediaExpressionValue::$variant(ref v) => v, + _ => unreachable!("Unexpected MediaExpressionValue"), }) - } + }; } match self.feature.evaluator { @@ -436,13 +420,11 @@ impl MediaFeatureExpression { }) }); eval(device, computed, self.range_or_operator) - } + }, Evaluator::Integer(eval) => { eval(device, expect!(Integer).cloned(), self.range_or_operator) - } - Evaluator::Float(eval) => { - eval(device, expect!(Float).cloned(), self.range_or_operator) - } + }, + Evaluator::Float(eval) => eval(device, expect!(Float).cloned(), self.range_or_operator), Evaluator::IntRatio(eval) => { eval(device, expect!(IntRatio).cloned(), self.range_or_operator) }, @@ -453,20 +435,16 @@ impl MediaFeatureExpression { }) }); eval(device, computed, self.range_or_operator) - } + }, Evaluator::Enumerated { evaluator, .. } => { - evaluator( - device, - expect!(Enumerated).cloned(), - self.range_or_operator, - ) - } - Evaluator::Ident(eval) => { - eval(device, expect!(Ident).cloned(), self.range_or_operator) - } - Evaluator::BoolInteger(eval) => { - eval(device, expect!(BoolInteger).cloned(), self.range_or_operator) - } + evaluator(device, expect!(Enumerated).cloned(), self.range_or_operator) + }, + Evaluator::Ident(eval) => eval(device, expect!(Ident).cloned(), self.range_or_operator), + Evaluator::BoolInteger(eval) => eval( + device, + expect!(BoolInteger).cloned(), + self.range_or_operator, + ), } } } @@ -502,11 +480,7 @@ pub enum MediaExpressionValue { } impl MediaExpressionValue { - fn to_css<W>( - &self, - dest: &mut CssWriter<W>, - for_expr: &MediaFeatureExpression, - ) -> fmt::Result + fn to_css<W>(&self, dest: &mut CssWriter<W>, for_expr: &MediaFeatureExpression) -> fmt::Result where W: fmt::Write, { @@ -515,18 +489,12 @@ impl MediaExpressionValue { MediaExpressionValue::Integer(v) => v.to_css(dest), MediaExpressionValue::Float(v) => v.to_css(dest), MediaExpressionValue::BoolInteger(v) => dest.write_str(if v { "1" } else { "0" }), - MediaExpressionValue::IntRatio(ratio) => { - ratio.to_css(dest) - }, + MediaExpressionValue::IntRatio(ratio) => ratio.to_css(dest), MediaExpressionValue::Resolution(ref r) => r.to_css(dest), MediaExpressionValue::Ident(ref ident) => serialize_atom_identifier(ident, dest), - MediaExpressionValue::Enumerated(value) => { - match for_expr.feature.evaluator { - Evaluator::Enumerated { serializer, .. } => { - dest.write_str(&*serializer(value)) - } - _ => unreachable!(), - } + MediaExpressionValue::Enumerated(value) => match for_expr.feature.evaluator { + Evaluator::Enumerated { serializer, .. } => dest.write_str(&*serializer(value)), + _ => unreachable!(), }, } } @@ -540,11 +508,11 @@ impl MediaExpressionValue { Evaluator::Length(..) => { let length = Length::parse_non_negative(context, input)?; MediaExpressionValue::Length(length) - } + }, Evaluator::Integer(..) => { let integer = Integer::parse_non_negative(context, input)?; MediaExpressionValue::Integer(integer.value() as u32) - } + }, Evaluator::BoolInteger(..) => { let integer = Integer::parse_non_negative(context, input)?; let value = integer.value(); @@ -552,29 +520,26 @@ impl MediaExpressionValue { return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } MediaExpressionValue::BoolInteger(value == 1) - } + }, Evaluator::Float(..) => { let number = Number::parse(context, input)?; MediaExpressionValue::Float(number.get()) - } + }, Evaluator::IntRatio(..) => { let a = Integer::parse_positive(context, input)?; input.expect_delim('/')?; let b = Integer::parse_positive(context, input)?; - MediaExpressionValue::IntRatio(AspectRatio( - a.value() as u32, - b.value() as u32 - )) - } + MediaExpressionValue::IntRatio(AspectRatio(a.value() as u32, b.value() as u32)) + }, Evaluator::Resolution(..) => { MediaExpressionValue::Resolution(Resolution::parse(context, input)?) - } + }, Evaluator::Enumerated { parser, .. } => { MediaExpressionValue::Enumerated(parser(context, input)?) - } + }, Evaluator::Ident(..) => { MediaExpressionValue::Ident(Atom::from(input.expect_ident()?.as_ref())) - } + }, }) } } diff --git a/components/style/media_queries/media_list.rs b/components/style/media_queries/media_list.rs index f8d15df7257..168671288cf 100644 --- a/components/style/media_queries/media_list.rs +++ b/components/style/media_queries/media_list.rs @@ -30,10 +30,7 @@ impl MediaList { /// "not all", see: /// /// <https://drafts.csswg.org/mediaqueries/#error-handling> - pub fn parse( - context: &ParserContext, - input: &mut Parser, - ) -> Self { + pub fn parse(context: &ParserContext, input: &mut Parser) -> Self { if input.is_exhausted() { return Self::empty(); } @@ -48,8 +45,10 @@ impl MediaList { Err(err) => { media_queries.push(MediaQuery::never_matching()); let location = err.location; - let error = - ContextualParseError::InvalidMediaRule(input.slice_from(start_position), err); + let error = ContextualParseError::InvalidMediaRule( + input.slice_from(start_position), + err, + ); context.log_css_error(location, error); }, } @@ -79,8 +78,10 @@ impl MediaList { let media_match = mq.media_type.matches(device.media_type()); // Check if the media condition match. - let query_match = media_match && - mq.condition.as_ref().map_or(true, |c| c.matches(device, quirks_mode)); + let query_match = media_match && mq + .condition + .as_ref() + .map_or(true, |c| c.matches(device, quirks_mode)); // Apply the logical NOT qualifier to the result match mq.qualifier { diff --git a/components/style/media_queries/media_query.rs b/components/style/media_queries/media_query.rs index 089fc9412b2..46c35618b22 100644 --- a/components/style/media_queries/media_query.rs +++ b/components/style/media_queries/media_query.rs @@ -15,7 +15,6 @@ use style_traits::{CssWriter, ParseError, ToCss}; use super::media_condition::MediaCondition; use values::CustomIdent; - /// <https://drafts.csswg.org/mediaqueries/#mq-prefix> #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)] pub enum Qualifier { @@ -125,12 +124,13 @@ impl MediaQuery { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - let (qualifier, explicit_media_type) = input.try(|input| -> Result<_, ()> { - let qualifier = input.try(Qualifier::parse).ok(); - let ident = input.expect_ident().map_err(|_| ())?; - let media_type = MediaQueryType::parse(&ident)?; - Ok((qualifier, Some(media_type))) - }).unwrap_or_default(); + let (qualifier, explicit_media_type) = input + .try(|input| -> Result<_, ()> { + let qualifier = input.try(Qualifier::parse).ok(); + let ident = input.expect_ident().map_err(|_| ())?; + let media_type = MediaQueryType::parse(&ident)?; + Ok((qualifier, Some(media_type))) + }).unwrap_or_default(); let condition = if explicit_media_type.is_none() { Some(MediaCondition::parse(context, input)?) @@ -141,7 +141,11 @@ impl MediaQuery { }; let media_type = explicit_media_type.unwrap_or(MediaQueryType::All); - Ok(Self { qualifier, media_type, condition }) + Ok(Self { + qualifier, + media_type, + condition, + }) } } diff --git a/components/style/parser.rs b/components/style/parser.rs index a4b7d816203..2d667f3f343 100644 --- a/components/style/parser.rs +++ b/components/style/parser.rs @@ -9,6 +9,7 @@ use cssparser::{Parser, SourceLocation, UnicodeRange}; use error_reporting::{ContextualParseError, ParseErrorReporter}; use style_traits::{OneOrMoreSeparated, ParseError, ParsingMode, Separator}; use stylesheets::{CssRuleType, Namespaces, Origin, UrlExtraData}; +use use_counters::UseCounters; /// Asserts that all ParsingMode flags have a matching ParsingMode value in gecko. #[cfg(feature = "gecko")] @@ -53,6 +54,8 @@ pub struct ParserContext<'a> { error_reporter: Option<&'a ParseErrorReporter>, /// The currently active namespaces. pub namespaces: Option<&'a Namespaces>, + /// The use counters we want to record while parsing style rules, if any. + pub use_counters: Option<&'a UseCounters>, } impl<'a> ParserContext<'a> { @@ -65,8 +68,9 @@ impl<'a> ParserContext<'a> { parsing_mode: ParsingMode, quirks_mode: QuirksMode, error_reporter: Option<&'a ParseErrorReporter>, + use_counters: Option<&'a UseCounters>, ) -> Self { - ParserContext { + Self { stylesheet_origin, url_data, rule_type, @@ -74,6 +78,7 @@ impl<'a> ParserContext<'a> { quirks_mode, error_reporter, namespaces: None, + use_counters, } } @@ -85,6 +90,7 @@ impl<'a> ParserContext<'a> { parsing_mode: ParsingMode, quirks_mode: QuirksMode, error_reporter: Option<&'a ParseErrorReporter>, + use_counters: Option<&'a UseCounters>, ) -> Self { Self::new( Origin::Author, @@ -93,17 +99,19 @@ impl<'a> ParserContext<'a> { parsing_mode, quirks_mode, error_reporter, + use_counters, ) } - /// Create a parser context based on a previous context, but with a modified rule type. + /// Create a parser context based on a previous context, but with a modified + /// rule type. #[inline] pub fn new_with_rule_type( context: &'a ParserContext, rule_type: CssRuleType, namespaces: &'a Namespaces, ) -> ParserContext<'a> { - ParserContext { + Self { stylesheet_origin: context.stylesheet_origin, url_data: context.url_data, rule_type: Some(rule_type), @@ -111,6 +119,7 @@ impl<'a> ParserContext<'a> { quirks_mode: context.quirks_mode, namespaces: Some(namespaces), error_reporter: context.error_reporter, + use_counters: context.use_counters, } } @@ -128,11 +137,7 @@ impl<'a> ParserContext<'a> { } /// Record a CSS parse error with this context’s error reporting. - pub fn log_css_error( - &self, - location: SourceLocation, - error: ContextualParseError, - ) { + pub fn log_css_error(&self, location: SourceLocation, error: ContextualParseError) { let error_reporter = match self.error_reporter { Some(r) => r, None => return, diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs index ad5aa75e8f2..56aa2fde4f4 100644 --- a/components/style/properties/declaration_block.rs +++ b/components/style/properties/declaration_block.rs @@ -138,56 +138,9 @@ impl<'a> DoubleEndedIterator for DeclarationImportanceIterator<'a> { } } -/// Iterator over `PropertyDeclaration` for Importance::Normal. -/// -/// TODO(emilio): This should be replaced by `impl Trait`, returning a -/// filter()ed iterator when available instead, and all the boilerplate below -/// should go. -pub struct NormalDeclarationIterator<'a>(DeclarationImportanceIterator<'a>); - -impl<'a> NormalDeclarationIterator<'a> { - #[inline] - fn new(declarations: &'a [PropertyDeclaration], important: &'a SmallBitVec) -> Self { - NormalDeclarationIterator( - DeclarationImportanceIterator::new(declarations, important) - ) - } -} - -impl<'a> Iterator for NormalDeclarationIterator<'a> { - type Item = &'a PropertyDeclaration; - - #[inline] - fn next(&mut self) -> Option<Self::Item> { - loop { - let (decl, importance) = self.0.iter.next()?; - if !importance { - return Some(decl); - } - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - self.0.iter.size_hint() - } -} - -impl<'a> DoubleEndedIterator for NormalDeclarationIterator<'a> { - #[inline] - fn next_back(&mut self) -> Option<Self::Item> { - loop { - let (decl, importance) = self.0.iter.next_back()?; - if !importance { - return Some(decl); - } - } - } -} - /// Iterator for AnimationValue to be generated from PropertyDeclarationBlock. pub struct AnimationValueIterator<'a, 'cx, 'cx_a:'cx> { - iter: NormalDeclarationIterator<'a>, + iter: DeclarationImportanceIterator<'a>, context: &'cx mut Context<'cx_a>, default_values: &'a ComputedValues, /// Custom properties in a keyframe if exists. @@ -202,7 +155,7 @@ impl<'a, 'cx, 'cx_a:'cx> AnimationValueIterator<'a, 'cx, 'cx_a> { extra_custom_properties: Option<&'a Arc<::custom_properties::CustomPropertiesMap>>, ) -> AnimationValueIterator<'a, 'cx, 'cx_a> { AnimationValueIterator { - iter: declarations.normal_declaration_iter(), + iter: declarations.declaration_importance_iter(), context, default_values, extra_custom_properties, @@ -215,7 +168,11 @@ impl<'a, 'cx, 'cx_a:'cx> Iterator for AnimationValueIterator<'a, 'cx, 'cx_a> { #[inline] fn next(&mut self) -> Option<Self::Item> { loop { - let decl = self.iter.next()?; + let (decl, importance) = self.iter.next()?; + + if importance.important() { + continue; + } let animation = AnimationValue::from_declaration( decl, @@ -287,8 +244,12 @@ impl PropertyDeclarationBlock { /// Iterate over `PropertyDeclaration` for Importance::Normal #[inline] - pub fn normal_declaration_iter(&self) -> NormalDeclarationIterator { - NormalDeclarationIterator::new(&self.declarations, &self.declarations_importance) + pub fn normal_declaration_iter<'a>( + &'a self, + ) -> impl DoubleEndedIterator<Item = &'a PropertyDeclaration> { + self.declaration_importance_iter() + .filter(|(_, importance)| !importance.important()) + .map(|(declaration, _)| declaration) } /// Return an iterator of (AnimatableLonghand, AnimationValue). @@ -344,14 +305,8 @@ impl PropertyDeclarationBlock { } } - self.declarations.iter().enumerate().find(|&(_, decl)| decl.id() == property).map(|(i, decl)| { - let importance = if self.declarations_importance[i] { - Importance::Important - } else { - Importance::Normal - }; - (decl, importance) - }) + self.declaration_importance_iter() + .find(|(declaration, _)| declaration.id() == property) } fn shorthand_to_css( @@ -1248,6 +1203,7 @@ pub fn parse_style_attribute( ParsingMode::DEFAULT, quirks_mode, error_reporter, + None, ); let mut input = ParserInput::new(input); @@ -1275,6 +1231,7 @@ pub fn parse_one_declaration_into( parsing_mode, quirks_mode, error_reporter, + None, ); let mut input = ParserInput::new(input); diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 33a66498b2d..9e9a6835a42 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -3053,7 +3053,7 @@ fn static_assert() { scroll-snap-points-x scroll-snap-points-y scroll-snap-type-x scroll-snap-type-y scroll-snap-coordinate perspective-origin -moz-binding will-change - overscroll-behavior-x overscroll-behavior-y + offset-path overscroll-behavior-x overscroll-behavior-y overflow-clip-box-inline overflow-clip-box-block perspective-origin -moz-binding will-change shape-outside contain touch-action translate @@ -3681,6 +3681,40 @@ fn static_assert() { ${impl_simple_copy("contain", "mContain")} ${impl_simple_type_with_conversion("touch_action")} + + pub fn set_offset_path(&mut self, v: longhands::offset_path::computed_value::T) { + use gecko_bindings::bindings::{Gecko_NewStyleMotion, Gecko_SetStyleMotion}; + use gecko_bindings::structs::StyleShapeSourceType; + use values::generics::basic_shape::FillRule; + use values::specified::OffsetPath; + + let motion = unsafe { Gecko_NewStyleMotion().as_mut().unwrap() }; + match v { + OffsetPath::None => motion.mOffsetPath.mType = StyleShapeSourceType::None, + OffsetPath::Path(p) => { + set_style_svg_path(&mut motion.mOffsetPath, &p, FillRule::Nonzero) + }, + } + unsafe { Gecko_SetStyleMotion(&mut self.gecko.mMotion, motion) }; + } + + pub fn clone_offset_path(&self) -> longhands::offset_path::computed_value::T { + use values::specified::OffsetPath; + match unsafe { self.gecko.mMotion.mPtr.as_ref() } { + None => OffsetPath::none(), + Some(v) => (&v.mOffsetPath).into() + } + } + + pub fn copy_offset_path_from(&mut self, other: &Self) { + use gecko_bindings::bindings::Gecko_CopyStyleMotions; + unsafe { Gecko_CopyStyleMotions(&mut self.gecko.mMotion, other.gecko.mMotion.mPtr) }; + } + + pub fn reset_offset_path(&mut self, other: &Self) { + self.copy_offset_path_from(other); + } + </%self:impl_trait> <%def name="simple_image_array_property(name, shorthand, field_name)"> @@ -4937,14 +4971,43 @@ fn static_assert() { } </%self:impl_trait> +// Set SVGPathData to StyleShapeSource. +fn set_style_svg_path( + shape_source: &mut structs::mozilla::StyleShapeSource, + servo_path: &values::specified::svg_path::SVGPathData, + fill: values::generics::basic_shape::FillRule, +) { + use gecko_bindings::bindings::Gecko_NewStyleSVGPath; + use gecko_bindings::structs::StyleShapeSourceType; + + // Setup type. + shape_source.mType = StyleShapeSourceType::Path; + + // Setup path. + let gecko_path = unsafe { + Gecko_NewStyleSVGPath(shape_source); + &mut shape_source.__bindgen_anon_1.mSVGPath.as_mut().mPtr.as_mut().unwrap() + }; + unsafe { gecko_path.mPath.set_len(servo_path.commands().len() as u32) }; + debug_assert_eq!(gecko_path.mPath.len(), servo_path.commands().len()); + for (servo, gecko) in servo_path.commands().iter().zip(gecko_path.mPath.iter_mut()) { + // unsafe: cbindgen ensures the representation is the same. + *gecko = unsafe { transmute(*servo) }; + } + + // Setup fill-rule. + // unsafe: cbindgen ensures the representation is the same. + gecko_path.mFillRule = unsafe { transmute(fill) }; +} + <%def name="impl_shape_source(ident, gecko_ffi_name)"> pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { use gecko_bindings::bindings::{Gecko_NewBasicShape, Gecko_DestroyShapeSource}; use gecko_bindings::structs::{StyleBasicShape, StyleBasicShapeType, StyleShapeSourceType}; - use gecko_bindings::structs::{StyleFillRule, StyleGeometryBox, StyleShapeSource}; + use gecko_bindings::structs::{StyleGeometryBox, StyleShapeSource}; use gecko::conversions::basic_shape::set_corners_from_radius; use gecko::values::GeckoStyleCoordConvertible; - use values::generics::basic_shape::{BasicShape, FillRule, ShapeSource}; + use values::generics::basic_shape::{BasicShape, ShapeSource}; let ref mut ${ident} = self.gecko.${gecko_ffi_name}; @@ -4976,6 +5039,7 @@ fn static_assert() { ${ident}.mReferenceBox = reference.into(); ${ident}.mType = StyleShapeSourceType::Box; } + ShapeSource::Path(p) => set_style_svg_path(${ident}, &p.path, p.fill), ShapeSource::Shape(servo_shape, maybe_box) => { fn init_shape(${ident}: &mut StyleShapeSource, basic_shape_type: StyleBasicShapeType) -> &mut StyleBasicShape { @@ -5038,11 +5102,8 @@ fn static_assert() { coord.0.to_gecko_style_coord(&mut shape.mCoordinates[2 * i]); coord.1.to_gecko_style_coord(&mut shape.mCoordinates[2 * i + 1]); } - shape.mFillRule = if poly.fill == FillRule::Evenodd { - StyleFillRule::Evenodd - } else { - StyleFillRule::Nonzero - }; + // unsafe: cbindgen ensures the representation is the same. + shape.mFillRule = unsafe { transmute(poly.fill) }; } } diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index f6277a21271..437232d386a 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -1296,9 +1296,27 @@ impl Animate for ComputedTransformOperation { &TransformOperation::Perspective(ref fd), &TransformOperation::Perspective(ref td), ) => { - Ok(TransformOperation::Perspective( - fd.animate(td, procedure)? - )) + use values::computed::CSSPixelLength; + use values::generics::transform::create_perspective_matrix; + + // From https://drafts.csswg.org/css-transforms-2/#interpolation-of-transform-functions: + // + // The transform functions matrix(), matrix3d() and + // perspective() get converted into 4x4 matrices first and + // interpolated as defined in section Interpolation of + // Matrices afterwards. + // + let from = create_perspective_matrix(fd.px()); + let to = create_perspective_matrix(td.px()); + + let interpolated = + Matrix3D::from(from).animate(&Matrix3D::from(to), procedure)?; + + let decomposed = decompose_3d_matrix(interpolated)?; + let perspective_z = decomposed.perspective.2; + let used_value = + if perspective_z == 0. { 0. } else { -1. / perspective_z }; + Ok(TransformOperation::Perspective(CSSPixelLength::new(used_value))) }, _ if self.is_translate() && other.is_translate() => { self.to_translate_3d().animate(&other.to_translate_3d(), procedure) diff --git a/components/style/properties/longhands/background.mako.rs b/components/style/properties/longhands/background.mako.rs index 9bb4e03e523..65df61a2e71 100644 --- a/components/style/properties/longhands/background.mako.rs +++ b/components/style/properties/longhands/background.mako.rs @@ -18,14 +18,17 @@ ${helpers.predefined_type( flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", )} -${helpers.predefined_type("background-image", "ImageLayer", +${helpers.predefined_type( + "background-image", + "ImageLayer", initial_value="Either::First(None_)", initial_specified_value="Either::First(None_)", spec="https://drafts.csswg.org/css-backgrounds/#the-background-image", vector="True", animation_value_type="discrete", ignored_when_colors_disabled="True", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER")} + flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", +)} % for (axis, direction, initial) in [("x", "Horizontal", "left"), ("y", "Vertical", "top")]: ${helpers.predefined_type( @@ -52,13 +55,15 @@ ${helpers.predefined_type( flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", )} -${helpers.single_keyword("background-attachment", - "scroll fixed" + (" local" if product == "gecko" else ""), - vector=True, - gecko_enum_prefix="StyleImageLayerAttachment", - spec="https://drafts.csswg.org/css-backgrounds/#the-background-attachment", - animation_value_type="discrete", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER")} +${helpers.single_keyword( + "background-attachment", + "scroll fixed" + (" local" if product == "gecko" else ""), + vector=True, + gecko_enum_prefix="StyleImageLayerAttachment", + spec="https://drafts.csswg.org/css-backgrounds/#the-background-attachment", + animation_value_type="discrete", + flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", +)} ${helpers.single_keyword( "background-clip", @@ -96,12 +101,14 @@ ${helpers.predefined_type( extra_prefixes="webkit")} // https://drafts.fxtf.org/compositing/#background-blend-mode -${helpers.single_keyword("background-blend-mode", - """normal multiply screen overlay darken lighten color-dodge - color-burn hard-light soft-light difference exclusion hue - saturation color luminosity""", - gecko_constant_prefix="NS_STYLE_BLEND", - gecko_pref="layout.css.background-blend-mode.enabled", - vector=True, products="gecko", animation_value_type="discrete", - spec="https://drafts.fxtf.org/compositing/#background-blend-mode", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER")} +${helpers.single_keyword( + "background-blend-mode", + """normal multiply screen overlay darken lighten color-dodge + color-burn hard-light soft-light difference exclusion hue + saturation color luminosity""", + gecko_constant_prefix="NS_STYLE_BLEND", + gecko_pref="layout.css.background-blend-mode.enabled", + vector=True, products="gecko", animation_value_type="discrete", + spec="https://drafts.fxtf.org/compositing/#background-blend-mode", + flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", +)} diff --git a/components/style/properties/longhands/border.mako.rs b/components/style/properties/longhands/border.mako.rs index 901d29728b1..1066dbbc619 100644 --- a/components/style/properties/longhands/border.mako.rs +++ b/components/style/properties/longhands/border.mako.rs @@ -61,51 +61,70 @@ )} % endfor -${helpers.gecko_keyword_conversion(Keyword('border-style', - "none solid double dotted dashed hidden groove ridge inset outset"), - type="::values::specified::BorderStyle")} +${helpers.gecko_keyword_conversion( + Keyword('border-style', + "none solid double dotted dashed hidden groove ridge inset outset"), + type="::values::specified::BorderStyle", +)} // FIXME(#4126): when gfx supports painting it, make this Size2D<LengthOrPercentage> % for corner in ["top-left", "top-right", "bottom-right", "bottom-left"]: - ${helpers.predefined_type("border-" + corner + "-radius", "BorderCornerRadius", - "computed::BorderCornerRadius::zero()", - "parse", extra_prefixes="webkit", - spec="https://drafts.csswg.org/css-backgrounds/#border-%s-radius" % corner, - boxed=True, - flags="APPLIES_TO_FIRST_LETTER", - animation_value_type="BorderCornerRadius")} + ${helpers.predefined_type( + "border-" + corner + "-radius", + "BorderCornerRadius", + "computed::BorderCornerRadius::zero()", + "parse", + extra_prefixes="webkit", + spec="https://drafts.csswg.org/css-backgrounds/#border-%s-radius" % corner, + boxed=True, + flags="APPLIES_TO_FIRST_LETTER", + animation_value_type="BorderCornerRadius", + )} % endfor -${helpers.single_keyword("box-decoration-break", "slice clone", - gecko_enum_prefix="StyleBoxDecorationBreak", - gecko_pref="layout.css.box-decoration-break.enabled", - spec="https://drafts.csswg.org/css-break/#propdef-box-decoration-break", - products="gecko", animation_value_type="discrete")} +${helpers.single_keyword( + "box-decoration-break", + "slice clone", + gecko_enum_prefix="StyleBoxDecorationBreak", + gecko_pref="layout.css.box-decoration-break.enabled", + spec="https://drafts.csswg.org/css-break/#propdef-box-decoration-break", + products="gecko", + animation_value_type="discrete", +)} -${helpers.single_keyword("-moz-float-edge", "content-box margin-box", - gecko_ffi_name="mFloatEdge", - gecko_enum_prefix="StyleFloatEdge", - products="gecko", - spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-float-edge)", - animation_value_type="discrete")} +${helpers.single_keyword( + "-moz-float-edge", + "content-box margin-box", + gecko_ffi_name="mFloatEdge", + gecko_enum_prefix="StyleFloatEdge", + products="gecko", + spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-float-edge)", + animation_value_type="discrete", +)} -${helpers.predefined_type("border-image-source", "ImageLayer", +${helpers.predefined_type( + "border-image-source", + "ImageLayer", initial_value="Either::First(None_)", initial_specified_value="Either::First(None_)", spec="https://drafts.csswg.org/css-backgrounds/#the-background-image", vector=False, animation_value_type="discrete", flags="APPLIES_TO_FIRST_LETTER", - boxed=True)} + boxed=True, +)} -${helpers.predefined_type("border-image-outset", "LengthOrNumberRect", +${helpers.predefined_type( + "border-image-outset", + "LengthOrNumberRect", parse_method="parse_non_negative", initial_value="computed::LengthOrNumberRect::all(computed::LengthOrNumber::zero())", initial_specified_value="specified::LengthOrNumberRect::all(specified::LengthOrNumber::zero())", spec="https://drafts.csswg.org/css-backgrounds/#border-image-outset", animation_value_type="discrete", flags="APPLIES_TO_FIRST_LETTER", - boxed=True)} + boxed=True, +)} ${helpers.predefined_type( "border-image-repeat", @@ -117,21 +136,27 @@ ${helpers.predefined_type( flags="APPLIES_TO_FIRST_LETTER", )} -${helpers.predefined_type("border-image-width", "BorderImageWidth", +${helpers.predefined_type( + "border-image-width", + "BorderImageWidth", initial_value="computed::BorderImageWidth::all(computed::BorderImageSideWidth::one())", initial_specified_value="specified::BorderImageWidth::all(specified::BorderImageSideWidth::one())", spec="https://drafts.csswg.org/css-backgrounds/#border-image-width", animation_value_type="discrete", flags="APPLIES_TO_FIRST_LETTER", - boxed=True)} + boxed=True, +)} -${helpers.predefined_type("border-image-slice", "BorderImageSlice", +${helpers.predefined_type( + "border-image-slice", + "BorderImageSlice", initial_value="computed::NumberOrPercentage::Percentage(computed::Percentage(1.)).into()", initial_specified_value="specified::NumberOrPercentage::Percentage(specified::Percentage::new(1.)).into()", spec="https://drafts.csswg.org/css-backgrounds/#border-image-slice", animation_value_type="discrete", flags="APPLIES_TO_FIRST_LETTER", - boxed=True)} + boxed=True, +)} #[cfg(feature = "gecko")] impl ::values::computed::BorderImageWidth { @@ -155,8 +180,9 @@ impl ::values::computed::BorderImageWidth { % endfor } - pub fn from_gecko_rect(sides: &::gecko_bindings::structs::nsStyleSides) - -> Option<::values::computed::BorderImageWidth> { + pub fn from_gecko_rect( + sides: &::gecko_bindings::structs::nsStyleSides, + ) -> Option<::values::computed::BorderImageWidth> { use gecko_bindings::structs::nsStyleUnit::{eStyleUnit_Factor, eStyleUnit_Auto}; use gecko_bindings::sugar::ns_style_coord::CoordData; use gecko::values::GeckoStyleCoordConvertible; diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs index 6b6bcf9cbe3..ed7839360d9 100644 --- a/components/style/properties/longhands/box.mako.rs +++ b/components/style/properties/longhands/box.mako.rs @@ -23,36 +23,25 @@ ${helpers.predefined_type( needs_context=product == "gecko" )} -// FIXME(emilio): Listing all the display values here is very unfortunate, we should teach C++ to use the -// Rust enum directly, or generate the conversions to `StyleDisplay`. -${helpers.gecko_keyword_conversion( - Keyword('display', """ - inline block inline-block - table inline-table table-row-group table-header-group table-footer-group - table-row table-column-group table-column table-cell table-caption - list-item none flex inline-flex grid inline-grid ruby ruby-base ruby-base-container - ruby-text ruby-text-container contents flow-root -webkit-box - -webkit-inline-box -moz-box -moz-inline-box -moz-grid -moz-inline-grid - -moz-grid-group -moz-grid-line -moz-stack -moz-inline-stack -moz-deck - -moz-popup -moz-groupbox - """, - gecko_enum_prefix='StyleDisplay', - gecko_strip_moz_prefix=False), - type="::values::specified::Display" -)} - -${helpers.single_keyword("-moz-top-layer", "none top", - gecko_constant_prefix="NS_STYLE_TOP_LAYER", - gecko_ffi_name="mTopLayer", - products="gecko", animation_value_type="none", - enabled_in="ua", - spec="Internal (not web-exposed)")} - -${helpers.single_keyword("position", "static absolute relative fixed sticky", - animation_value_type="discrete", - flags="CREATES_STACKING_CONTEXT ABSPOS_CB", - spec="https://drafts.csswg.org/css-position/#position-property", - servo_restyle_damage="rebuild_and_reflow")} +${helpers.single_keyword( + "-moz-top-layer", + "none top", + gecko_constant_prefix="NS_STYLE_TOP_LAYER", + gecko_ffi_name="mTopLayer", + products="gecko", + animation_value_type="none", + enabled_in="ua", + spec="Internal (not web-exposed)", +)} + +${helpers.single_keyword( + "position", + "static absolute relative fixed sticky", + animation_value_type="discrete", + flags="CREATES_STACKING_CONTEXT ABSPOS_CB", + spec="https://drafts.csswg.org/css-position/#position-property", + servo_restyle_damage="rebuild_and_reflow", +)} ${helpers.predefined_type( "float", @@ -64,7 +53,7 @@ ${helpers.predefined_type( needs_context=False, flags="APPLIES_TO_FIRST_LETTER", servo_restyle_damage="rebuild_and_reflow", - gecko_ffi_name="mFloat" + gecko_ffi_name="mFloat", )} ${helpers.predefined_type( @@ -75,7 +64,7 @@ ${helpers.predefined_type( needs_context=False, gecko_ffi_name="mBreakType", spec="https://drafts.csswg.org/css-box/#propdef-clear", - servo_restyle_damage="rebuild_and_reflow" + servo_restyle_damage="rebuild_and_reflow", )} ${helpers.predefined_type( @@ -85,7 +74,7 @@ ${helpers.predefined_type( animation_value_type="ComputedValue", flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", spec="https://www.w3.org/TR/CSS2/visudet.html#propdef-vertical-align", - servo_restyle_damage = "reflow" + servo_restyle_damage = "reflow", )} // CSS 2.1, Section 11 - Visual effects @@ -118,14 +107,17 @@ ${helpers.single_keyword("-servo-overflow-clip-box", "padding-box content-box", // FIXME(pcwalton, #2742): Implement scrolling for `scroll` and `auto`. // // We allow it to apply to placeholders for UA sheets, which set it !important. -${helpers.single_keyword("overflow-x", "visible hidden scroll auto", - animation_value_type="discrete", - extra_gecko_values="-moz-hidden-unscrollable", - custom_consts=overflow_custom_consts, - gecko_constant_prefix="NS_STYLE_OVERFLOW", - flags="APPLIES_TO_PLACEHOLDER", - spec="https://drafts.csswg.org/css-overflow/#propdef-overflow-x", - servo_restyle_damage = "reflow")} +${helpers.single_keyword( + "overflow-x", + "visible hidden scroll auto", + animation_value_type="discrete", + extra_gecko_values="-moz-hidden-unscrollable", + custom_consts=overflow_custom_consts, + gecko_constant_prefix="NS_STYLE_OVERFLOW", + flags="APPLIES_TO_PLACEHOLDER", + spec="https://drafts.csswg.org/css-overflow/#propdef-overflow-x", + servo_restyle_damage = "reflow", +)} // FIXME(pcwalton, #2742): Implement scrolling for `scroll` and `auto`. // @@ -139,26 +131,30 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto", <% transition_extra_prefixes = "moz:layout.css.prefixes.transitions webkit" %> -${helpers.predefined_type("transition-duration", - "Time", - "computed::Time::zero()", - initial_specified_value="specified::Time::zero()", - parse_method="parse_non_negative", - vector=True, - need_index=True, - animation_value_type="none", - extra_prefixes=transition_extra_prefixes, - spec="https://drafts.csswg.org/css-transitions/#propdef-transition-duration")} - -${helpers.predefined_type("transition-timing-function", - "TimingFunction", - "computed::TimingFunction::ease()", - initial_specified_value="specified::TimingFunction::ease()", - vector=True, - need_index=True, - animation_value_type="none", - extra_prefixes=transition_extra_prefixes, - spec="https://drafts.csswg.org/css-transitions/#propdef-transition-timing-function")} +${helpers.predefined_type( + "transition-duration", + "Time", + "computed::Time::zero()", + initial_specified_value="specified::Time::zero()", + parse_method="parse_non_negative", + vector=True, + need_index=True, + animation_value_type="none", + extra_prefixes=transition_extra_prefixes, + spec="https://drafts.csswg.org/css-transitions/#propdef-transition-duration", +)} + +${helpers.predefined_type( + "transition-timing-function", + "TimingFunction", + "computed::TimingFunction::ease()", + initial_specified_value="specified::TimingFunction::ease()", + vector=True, + need_index=True, + animation_value_type="none", + extra_prefixes=transition_extra_prefixes, + spec="https://drafts.csswg.org/css-transitions/#propdef-transition-timing-function", +)} ${helpers.predefined_type( "transition-property", @@ -173,16 +169,17 @@ ${helpers.predefined_type( spec="https://drafts.csswg.org/css-transitions/#propdef-transition-property", )} -${helpers.predefined_type("transition-delay", - "Time", - "computed::Time::zero()", - initial_specified_value="specified::Time::zero()", - vector=True, - need_index=True, - animation_value_type="none", - extra_prefixes=transition_extra_prefixes, - spec="https://drafts.csswg.org/css-transitions/#propdef-transition-delay")} - +${helpers.predefined_type( + "transition-delay", + "Time", + "computed::Time::zero()", + initial_specified_value="specified::Time::zero()", + vector=True, + need_index=True, + animation_value_type="none", + extra_prefixes=transition_extra_prefixes, + spec="https://drafts.csswg.org/css-transitions/#propdef-transition-delay", +)} <% animation_extra_prefixes = "moz:layout.css.prefixes.animations webkit" %> @@ -199,29 +196,33 @@ ${helpers.predefined_type( spec="https://drafts.csswg.org/css-animations/#propdef-animation-name", )} -${helpers.predefined_type("animation-duration", - "Time", - "computed::Time::zero()", - initial_specified_value="specified::Time::zero()", - parse_method="parse_non_negative", - vector=True, - need_index=True, - animation_value_type="none", - extra_prefixes=animation_extra_prefixes, - spec="https://drafts.csswg.org/css-transitions/#propdef-transition-duration")} +${helpers.predefined_type( + "animation-duration", + "Time", + "computed::Time::zero()", + initial_specified_value="specified::Time::zero()", + parse_method="parse_non_negative", + vector=True, + need_index=True, + animation_value_type="none", + extra_prefixes=animation_extra_prefixes, + spec="https://drafts.csswg.org/css-transitions/#propdef-transition-duration", +)} // animation-timing-function is the exception to the rule for allowed_in_keyframe_block: // https://drafts.csswg.org/css-animations/#keyframes -${helpers.predefined_type("animation-timing-function", - "TimingFunction", - "computed::TimingFunction::ease()", - initial_specified_value="specified::TimingFunction::ease()", - vector=True, - need_index=True, - animation_value_type="none", - extra_prefixes=animation_extra_prefixes, - allowed_in_keyframe_block=True, - spec="https://drafts.csswg.org/css-transitions/#propdef-animation-timing-function")} +${helpers.predefined_type( + "animation-timing-function", + "TimingFunction", + "computed::TimingFunction::ease()", + initial_specified_value="specified::TimingFunction::ease()", + vector=True, + need_index=True, + animation_value_type="none", + extra_prefixes=animation_extra_prefixes, + allowed_in_keyframe_block=True, + spec="https://drafts.csswg.org/css-transitions/#propdef-animation-timing-function", +)} ${helpers.predefined_type( "animation-iteration-count", @@ -237,46 +238,54 @@ ${helpers.predefined_type( )} <% animation_direction_custom_consts = { "alternate-reverse": "Alternate_reverse" } %> -${helpers.single_keyword("animation-direction", - "normal reverse alternate alternate-reverse", - need_index=True, - animation_value_type="none", - vector=True, - gecko_enum_prefix="PlaybackDirection", - custom_consts=animation_direction_custom_consts, - extra_prefixes=animation_extra_prefixes, - spec="https://drafts.csswg.org/css-animations/#propdef-animation-direction", - allowed_in_keyframe_block=False)} - -${helpers.single_keyword("animation-play-state", - "running paused", - need_index=True, - animation_value_type="none", - vector=True, - extra_prefixes=animation_extra_prefixes, - spec="https://drafts.csswg.org/css-animations/#propdef-animation-play-state", - allowed_in_keyframe_block=False)} - -${helpers.single_keyword("animation-fill-mode", - "none forwards backwards both", - need_index=True, - animation_value_type="none", - vector=True, - gecko_enum_prefix="FillMode", - extra_prefixes=animation_extra_prefixes, - spec="https://drafts.csswg.org/css-animations/#propdef-animation-fill-mode", - allowed_in_keyframe_block=False)} - -${helpers.predefined_type("animation-delay", - "Time", - "computed::Time::zero()", - initial_specified_value="specified::Time::zero()", - vector=True, - need_index=True, - animation_value_type="none", - extra_prefixes=animation_extra_prefixes, - spec="https://drafts.csswg.org/css-animations/#propdef-animation-delay", - allowed_in_keyframe_block=False)} +${helpers.single_keyword( + "animation-direction", + "normal reverse alternate alternate-reverse", + need_index=True, + animation_value_type="none", + vector=True, + gecko_enum_prefix="PlaybackDirection", + custom_consts=animation_direction_custom_consts, + extra_prefixes=animation_extra_prefixes, + spec="https://drafts.csswg.org/css-animations/#propdef-animation-direction", + allowed_in_keyframe_block=False, +)} + +${helpers.single_keyword( + "animation-play-state", + "running paused", + need_index=True, + animation_value_type="none", + vector=True, + extra_prefixes=animation_extra_prefixes, + spec="https://drafts.csswg.org/css-animations/#propdef-animation-play-state", + allowed_in_keyframe_block=False, +)} + +${helpers.single_keyword( + "animation-fill-mode", + "none forwards backwards both", + need_index=True, + animation_value_type="none", + vector=True, + gecko_enum_prefix="FillMode", + extra_prefixes=animation_extra_prefixes, + spec="https://drafts.csswg.org/css-animations/#propdef-animation-fill-mode", + allowed_in_keyframe_block=False, +)} + +${helpers.predefined_type( + "animation-delay", + "Time", + "computed::Time::zero()", + initial_specified_value="specified::Time::zero()", + vector=True, + need_index=True, + animation_value_type="none", + extra_prefixes=animation_extra_prefixes, + spec="https://drafts.csswg.org/css-animations/#propdef-animation-delay", + allowed_in_keyframe_block=False, +)} % for axis in ["x", "y"]: ${helpers.predefined_type( @@ -290,14 +299,16 @@ ${helpers.predefined_type("animation-delay", )} % endfor -${helpers.predefined_type("scroll-snap-destination", - "Position", - "computed::Position::zero()", - products="gecko", - gecko_pref="layout.css.scroll-snap.enabled", - boxed=True, - spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-destination)", - animation_value_type="discrete")} +${helpers.predefined_type( + "scroll-snap-destination", + "Position", + "computed::Position::zero()", + products="gecko", + gecko_pref="layout.css.scroll-snap.enabled", + boxed=True, + spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-destination)", + animation_value_type="discrete", +)} ${helpers.predefined_type( "scroll-snap-coordinate", @@ -308,7 +319,7 @@ ${helpers.predefined_type( gecko_pref="layout.css.scroll-snap.enabled", spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-destination)", animation_value_type="discrete", - allow_empty="NotInitial" + allow_empty="NotInitial", )} <% transform_extra_prefixes = "moz:layout.css.prefixes.transforms webkit" %> @@ -323,26 +334,32 @@ ${helpers.predefined_type( flags="CREATES_STACKING_CONTEXT FIXPOS_CB \ GETCS_NEEDS_LAYOUT_FLUSH CAN_ANIMATE_ON_COMPOSITOR", spec="https://drafts.csswg.org/css-transforms/#propdef-transform", - servo_restyle_damage="reflow_out_of_flow" + servo_restyle_damage="reflow_out_of_flow", )} -${helpers.predefined_type("rotate", "Rotate", - "generics::transform::Rotate::None", - animation_value_type="ComputedValue", - boxed=True, - flags="CREATES_STACKING_CONTEXT FIXPOS_CB", - gecko_pref="layout.css.individual-transform.enabled", - spec="https://drafts.csswg.org/css-transforms-2/#individual-transforms", - servo_restyle_damage = "reflow_out_of_flow")} +${helpers.predefined_type( + "rotate", + "Rotate", + "generics::transform::Rotate::None", + animation_value_type="ComputedValue", + boxed=True, + flags="CREATES_STACKING_CONTEXT FIXPOS_CB", + gecko_pref="layout.css.individual-transform.enabled", + spec="https://drafts.csswg.org/css-transforms-2/#individual-transforms", + servo_restyle_damage = "reflow_out_of_flow", +)} -${helpers.predefined_type("scale", "Scale", - "generics::transform::Scale::None", - animation_value_type="ComputedValue", - boxed=True, - flags="CREATES_STACKING_CONTEXT FIXPOS_CB", - gecko_pref="layout.css.individual-transform.enabled", - spec="https://drafts.csswg.org/css-transforms-2/#individual-transforms", - servo_restyle_damage = "reflow_out_of_flow")} +${helpers.predefined_type( + "scale", + "Scale", + "generics::transform::Scale::None", + animation_value_type="ComputedValue", + boxed=True, + flags="CREATES_STACKING_CONTEXT FIXPOS_CB", + gecko_pref="layout.css.individual-transform.enabled", + spec="https://drafts.csswg.org/css-transforms-2/#individual-transforms", + servo_restyle_damage = "reflow_out_of_flow", +)} ${helpers.predefined_type( "translate", @@ -353,17 +370,31 @@ ${helpers.predefined_type( flags="CREATES_STACKING_CONTEXT FIXPOS_CB GETCS_NEEDS_LAYOUT_FLUSH", gecko_pref="layout.css.individual-transform.enabled", spec="https://drafts.csswg.org/css-transforms-2/#individual-transforms", - servo_restyle_damage="reflow_out_of_flow" + servo_restyle_damage="reflow_out_of_flow", +)} + +// Motion Path Module Level 1 +${helpers.predefined_type( + "offset-path", + "OffsetPath", + "computed::OffsetPath::none()", + products="gecko", + animation_value_type="ComputedValue", + gecko_pref="layout.css.motion-path.enabled", + flags="CREATES_STACKING_CONTEXT FIXPOS_CB", + spec="https://drafts.fxtf.org/motion-1/#offset-path-property", )} // CSSOM View Module // https://www.w3.org/TR/cssom-view-1/ -${helpers.single_keyword("scroll-behavior", - "auto smooth", - gecko_pref="layout.css.scroll-behavior.property-enabled", - products="gecko", - spec="https://drafts.csswg.org/cssom-view/#propdef-scroll-behavior", - animation_value_type="discrete")} +${helpers.single_keyword( + "scroll-behavior", + "auto smooth", + gecko_pref="layout.css.scroll-behavior.property-enabled", + products="gecko", + spec="https://drafts.csswg.org/cssom-view/#propdef-scroll-behavior", + animation_value_type="discrete", +)} % for axis in ["x", "y"]: ${helpers.predefined_type( @@ -374,7 +405,7 @@ ${helpers.single_keyword("scroll-behavior", needs_context=False, gecko_pref="layout.css.scroll-snap.enabled", spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-type-x)", - animation_value_type="discrete" + animation_value_type="discrete", )} % endfor @@ -387,38 +418,48 @@ ${helpers.single_keyword("scroll-behavior", needs_context=False, gecko_pref="layout.css.overscroll-behavior.enabled", spec="https://wicg.github.io/overscroll-behavior/#overscroll-behavior-properties", - animation_value_type="discrete" + animation_value_type="discrete", )} % endfor // Compositing and Blending Level 1 // http://www.w3.org/TR/compositing-1/ -${helpers.single_keyword("isolation", - "auto isolate", - products="gecko", - gecko_pref="layout.css.isolation.enabled", - spec="https://drafts.fxtf.org/compositing/#isolation", - flags="CREATES_STACKING_CONTEXT", - animation_value_type="discrete")} +${helpers.single_keyword( + "isolation", + "auto isolate", + products="gecko", + gecko_pref="layout.css.isolation.enabled", + spec="https://drafts.fxtf.org/compositing/#isolation", + flags="CREATES_STACKING_CONTEXT", + animation_value_type="discrete", +)} // TODO add support for logical values recto and verso -${helpers.single_keyword("page-break-after", - "auto always avoid left right", - products="gecko", - spec="https://drafts.csswg.org/css2/page.html#propdef-page-break-after", - animation_value_type="discrete")} -${helpers.single_keyword("page-break-before", - "auto always avoid left right", - products="gecko", - spec="https://drafts.csswg.org/css2/page.html#propdef-page-break-before", - animation_value_type="discrete")} -${helpers.single_keyword("page-break-inside", - "auto avoid", - products="gecko", - gecko_ffi_name="mBreakInside", - gecko_constant_prefix="NS_STYLE_PAGE_BREAK", - spec="https://drafts.csswg.org/css2/page.html#propdef-page-break-inside", - animation_value_type="discrete")} +${helpers.single_keyword( + "page-break-after", + "auto always avoid left right", + products="gecko", + spec="https://drafts.csswg.org/css2/page.html#propdef-page-break-after", + animation_value_type="discrete", +)} + +${helpers.single_keyword( + "page-break-before", + "auto always avoid left right", + products="gecko", + spec="https://drafts.csswg.org/css2/page.html#propdef-page-break-before", + animation_value_type="discrete", +)} + +${helpers.single_keyword( + "page-break-inside", + "auto avoid", + products="gecko", + gecko_ffi_name="mBreakInside", + gecko_constant_prefix="NS_STYLE_PAGE_BREAK", + spec="https://drafts.csswg.org/css2/page.html#propdef-page-break-inside", + animation_value_type="discrete", +)} // CSS Basic User Interface Module Level 3 // http://dev.w3.org/csswg/css-ui @@ -462,20 +503,24 @@ ${helpers.predefined_type( servo_restyle_damage="reflow_out_of_flow" )} -${helpers.single_keyword("backface-visibility", - "visible hidden", - spec="https://drafts.csswg.org/css-transforms/#backface-visibility-property", - extra_prefixes=transform_extra_prefixes, - animation_value_type="discrete")} +${helpers.single_keyword( + "backface-visibility", + "visible hidden", + spec="https://drafts.csswg.org/css-transforms/#backface-visibility-property", + extra_prefixes=transform_extra_prefixes, + animation_value_type="discrete", +)} -${helpers.single_keyword("transform-box", - "border-box fill-box view-box", - gecko_enum_prefix="StyleGeometryBox", - products="gecko", - gecko_pref="svg.transform-box.enabled", - spec="https://drafts.csswg.org/css-transforms/#transform-box", - gecko_inexhaustive="True", - animation_value_type="discrete")} +${helpers.single_keyword( + "transform-box", + "border-box fill-box view-box", + gecko_enum_prefix="StyleGeometryBox", + products="gecko", + gecko_pref="svg.transform-box.enabled", + spec="https://drafts.csswg.org/css-transforms/#transform-box", + gecko_inexhaustive="True", + animation_value_type="discrete", +)} ${helpers.predefined_type( "transform-style", @@ -499,17 +544,19 @@ ${helpers.predefined_type( boxed=True, flags="GETCS_NEEDS_LAYOUT_FLUSH", spec="https://drafts.csswg.org/css-transforms/#transform-origin-property", - servo_restyle_damage="reflow_out_of_flow" + servo_restyle_damage="reflow_out_of_flow", )} -${helpers.predefined_type("contain", - "Contain", - "specified::Contain::empty()", - animation_value_type="discrete", - products="gecko", - flags="CREATES_STACKING_CONTEXT FIXPOS_CB", - gecko_pref="layout.css.contain.enabled", - spec="https://drafts.csswg.org/css-contain/#contain-property")} +${helpers.predefined_type( + "contain", + "Contain", + "specified::Contain::empty()", + animation_value_type="none", + products="gecko", + flags="CREATES_STACKING_CONTEXT FIXPOS_CB", + gecko_pref="layout.css.contain.enabled", + spec="https://drafts.csswg.org/css-contain/#contain-property", +)} // Non-standard ${helpers.predefined_type( @@ -522,27 +569,33 @@ ${helpers.predefined_type( animation_value_type="discrete", )} -${helpers.predefined_type("-moz-binding", "url::UrlOrNone", "computed::url::UrlOrNone::none()", - products="gecko", - animation_value_type="none", - gecko_ffi_name="mBinding", - spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-binding)")} +${helpers.predefined_type( + "-moz-binding", + "url::UrlOrNone", + "computed::url::UrlOrNone::none()", + products="gecko", + animation_value_type="none", + gecko_ffi_name="mBinding", + spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-binding)", +)} -${helpers.single_keyword("-moz-orient", - "inline block horizontal vertical", - products="gecko", - gecko_ffi_name="mOrient", - gecko_enum_prefix="StyleOrient", - spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-orient)", - animation_value_type="discrete")} +${helpers.single_keyword( + "-moz-orient", + "inline block horizontal vertical", + products="gecko", + gecko_ffi_name="mOrient", + gecko_enum_prefix="StyleOrient", + spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-orient)", + animation_value_type="discrete", +)} ${helpers.predefined_type( "will-change", "WillChange", "computed::WillChange::auto()", products="gecko", - animation_value_type="discrete", - spec="https://drafts.csswg.org/css-will-change/#will-change" + animation_value_type="none", + spec="https://drafts.csswg.org/css-will-change/#will-change", )} ${helpers.predefined_type( diff --git a/components/style/properties/longhands/color.mako.rs b/components/style/properties/longhands/color.mako.rs index a4d1830190a..d53632835b6 100644 --- a/components/style/properties/longhands/color.mako.rs +++ b/components/style/properties/longhands/color.mako.rs @@ -15,7 +15,7 @@ ${helpers.predefined_type( animation_value_type="AnimatedRGBA", flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", ignored_when_colors_disabled="True", - spec="https://drafts.csswg.org/css-color/#color" + spec="https://drafts.csswg.org/css-color/#color", )} // FIXME(#15973): Add servo support for system colors @@ -96,8 +96,10 @@ pub mod system_colors { #[inline] fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue { unsafe { - Gecko_GetLookAndFeelSystemColor(*self as i32, - cx.device().pres_context()) + Gecko_GetLookAndFeelSystemColor( + *self as i32, + cx.device().pres_context(), + ) } } diff --git a/components/style/properties/longhands/column.mako.rs b/components/style/properties/longhands/column.mako.rs index e7305e5b4f3..adc9371e99f 100644 --- a/components/style/properties/longhands/column.mako.rs +++ b/components/style/properties/longhands/column.mako.rs @@ -6,16 +6,17 @@ <% data.new_style_struct("Column", inherited=False) %> -${helpers.predefined_type("column-width", - "length::NonNegativeLengthOrAuto", - "Either::Second(Auto)", - initial_specified_value="Either::Second(Auto)", - extra_prefixes="moz", - animation_value_type="NonNegativeLengthOrAuto", - servo_pref="layout.columns.enabled", - spec="https://drafts.csswg.org/css-multicol/#propdef-column-width", - servo_restyle_damage="rebuild_and_reflow")} - +${helpers.predefined_type( + "column-width", + "length::NonNegativeLengthOrAuto", + "Either::Second(Auto)", + initial_specified_value="Either::Second(Auto)", + extra_prefixes="moz", + animation_value_type="NonNegativeLengthOrAuto", + servo_pref="layout.columns.enabled", + spec="https://drafts.csswg.org/css-multicol/#propdef-column-width", + servo_restyle_damage="rebuild_and_reflow", +)} ${helpers.predefined_type( "column-count", @@ -29,22 +30,27 @@ ${helpers.predefined_type( servo_restyle_damage="rebuild_and_reflow", )} +${helpers.single_keyword( + "column-fill", + "balance auto", + extra_prefixes="moz", + products="gecko", + animation_value_type="discrete", + gecko_enum_prefix="StyleColumnFill", + spec="https://drafts.csswg.org/css-multicol/#propdef-column-fill", +)} - -${helpers.single_keyword("column-fill", "balance auto", extra_prefixes="moz", - products="gecko", animation_value_type="discrete", - gecko_enum_prefix="StyleColumnFill", - spec="https://drafts.csswg.org/css-multicol/#propdef-column-fill")} - -${helpers.predefined_type("column-rule-width", - "BorderSideWidth", - "::values::computed::NonNegativeLength::new(3.)", - initial_specified_value="specified::BorderSideWidth::Medium", - computed_type="::values::computed::NonNegativeLength", - products="gecko", - spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-width", - animation_value_type="NonNegativeLength", - extra_prefixes="moz")} +${helpers.predefined_type( + "column-rule-width", + "BorderSideWidth", + "::values::computed::NonNegativeLength::new(3.)", + initial_specified_value="specified::BorderSideWidth::Medium", + computed_type="::values::computed::NonNegativeLength", + products="gecko", + spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-width", + animation_value_type="NonNegativeLength", + extra_prefixes="moz", +)} // https://drafts.csswg.org/css-multicol-1/#crc ${helpers.predefined_type( @@ -59,16 +65,23 @@ ${helpers.predefined_type( spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-color", )} -${helpers.single_keyword("column-span", "none all", - products="gecko", animation_value_type="discrete", - gecko_enum_prefix="StyleColumnSpan", - gecko_pref="layout.css.column-span.enabled", - spec="https://drafts.csswg.org/css-multicol/#propdef-column-span", - extra_prefixes="moz:layout.css.column-span.enabled")} +${helpers.single_keyword( + "column-span", + "none all", + products="gecko", + animation_value_type="discrete", + gecko_enum_prefix="StyleColumnSpan", + gecko_pref="layout.css.column-span.enabled", + spec="https://drafts.csswg.org/css-multicol/#propdef-column-span", + extra_prefixes="moz:layout.css.column-span.enabled", +)} -${helpers.single_keyword("column-rule-style", - "none hidden dotted dashed solid double groove ridge inset outset", - products="gecko", extra_prefixes="moz", - gecko_constant_prefix="NS_STYLE_BORDER_STYLE", - animation_value_type="discrete", - spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-style")} +${helpers.single_keyword( + "column-rule-style", + "none hidden dotted dashed solid double groove ridge inset outset", + products="gecko", + extra_prefixes="moz", + gecko_constant_prefix="NS_STYLE_BORDER_STYLE", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-style", +)} diff --git a/components/style/properties/longhands/counters.mako.rs b/components/style/properties/longhands/counters.mako.rs index ececf58310f..4a8fd0bb6d1 100644 --- a/components/style/properties/longhands/counters.mako.rs +++ b/components/style/properties/longhands/counters.mako.rs @@ -6,13 +6,15 @@ <% data.new_style_struct("Counters", inherited=False, gecko_name="Content") %> -${helpers.predefined_type("content", - "Content", - "computed::Content::normal()", - initial_specified_value="specified::Content::normal()", - animation_value_type="discrete", - spec="https://drafts.csswg.org/css-content/#propdef-content", - servo_restyle_damage="rebuild_and_reflow")} +${helpers.predefined_type( + "content", + "Content", + "computed::Content::normal()", + initial_specified_value="specified::Content::normal()", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-content/#propdef-content", + servo_restyle_damage="rebuild_and_reflow", +)} ${helpers.predefined_type( "counter-increment", @@ -20,7 +22,7 @@ ${helpers.predefined_type( initial_value="Default::default()", animation_value_type="discrete", spec="https://drafts.csswg.org/css-lists/#propdef-counter-increment", - servo_restyle_damage="rebuild_and_reflow" + servo_restyle_damage="rebuild_and_reflow", )} ${helpers.predefined_type( @@ -29,5 +31,5 @@ ${helpers.predefined_type( initial_value="Default::default()", animation_value_type="discrete", spec="https://drafts.csswg.org/css-lists-3/#propdef-counter-reset", - servo_restyle_damage="rebuild_and_reflow" + servo_restyle_damage="rebuild_and_reflow", )} diff --git a/components/style/properties/longhands/effects.mako.rs b/components/style/properties/longhands/effects.mako.rs index 674340c391a..6649dc4d55b 100644 --- a/components/style/properties/longhands/effects.mako.rs +++ b/components/style/properties/longhands/effects.mako.rs @@ -15,7 +15,7 @@ ${helpers.predefined_type( flags="CREATES_STACKING_CONTEXT APPLIES_TO_PLACEHOLDER \ CAN_ANIMATE_ON_COMPOSITOR", spec="https://drafts.csswg.org/css-color/#opacity", - servo_restyle_damage = "reflow_out_of_flow" + servo_restyle_damage = "reflow_out_of_flow", )} ${helpers.predefined_type( @@ -31,13 +31,15 @@ ${helpers.predefined_type( spec="https://drafts.csswg.org/css-backgrounds/#box-shadow", )} -${helpers.predefined_type("clip", - "ClipRectOrAuto", - "computed::ClipRectOrAuto::auto()", - animation_value_type="ComputedValue", - boxed=True, - allow_quirks=True, - spec="https://drafts.fxtf.org/css-masking/#clip-property")} +${helpers.predefined_type( + "clip", + "ClipRectOrAuto", + "computed::ClipRectOrAuto::auto()", + animation_value_type="ComputedValue", + boxed=True, + allow_quirks=True, + spec="https://drafts.fxtf.org/css-masking/#clip-property", +)} ${helpers.predefined_type( "filter", @@ -52,11 +54,14 @@ ${helpers.predefined_type( spec="https://drafts.fxtf.org/filters/#propdef-filter", )} -${helpers.single_keyword("mix-blend-mode", - """normal multiply screen overlay darken lighten color-dodge - color-burn hard-light soft-light difference exclusion hue - saturation color luminosity""", gecko_constant_prefix="NS_STYLE_BLEND", - animation_value_type="discrete", - flags="CREATES_STACKING_CONTEXT", - gecko_pref="layout.css.mix-blend-mode.enabled", - spec="https://drafts.fxtf.org/compositing/#propdef-mix-blend-mode")} +${helpers.single_keyword( + "mix-blend-mode", + """normal multiply screen overlay darken lighten color-dodge + color-burn hard-light soft-light difference exclusion hue + saturation color luminosity""", + gecko_constant_prefix="NS_STYLE_BLEND", + animation_value_type="discrete", + flags="CREATES_STACKING_CONTEXT", + gecko_pref="layout.css.mix-blend-mode.enabled", + spec="https://drafts.fxtf.org/compositing/#propdef-mix-blend-mode", +)} diff --git a/components/style/properties/longhands/inherited_box.mako.rs b/components/style/properties/longhands/inherited_box.mako.rs index 4482931fd7a..d810ec3d29a 100644 --- a/components/style/properties/longhands/inherited_box.mako.rs +++ b/components/style/properties/longhands/inherited_box.mako.rs @@ -40,15 +40,12 @@ ${helpers.single_keyword( servo_restyle_damage="rebuild_and_reflow", )} -// TODO(emilio): Should text-orientation be non-animatable? It affects the -// WritingMode value, but not the logical -> physical mapping of properties, -// which is the reason direction / writing-mode are non-animatable. ${helpers.single_keyword( "text-orientation", "mixed upright sideways", extra_gecko_aliases="sideways-right=sideways", products="gecko", - animation_value_type="discrete", + animation_value_type="none", spec="https://drafts.csswg.org/css-writing-modes/#propdef-text-orientation", )} diff --git a/components/style/properties/longhands/inherited_svg.mako.rs b/components/style/properties/longhands/inherited_svg.mako.rs index b3bc12b1367..40c61b10129 100644 --- a/components/style/properties/longhands/inherited_svg.mako.rs +++ b/components/style/properties/longhands/inherited_svg.mako.rs @@ -6,61 +6,81 @@ // SVG 1.1 (Second Edition) // https://www.w3.org/TR/SVG/ -<% data.new_style_struct("InheritedSVG", - inherited=True, - gecko_name="SVG") %> +<% data.new_style_struct("InheritedSVG", inherited=True, gecko_name="SVG") %> // Section 10 - Text -${helpers.single_keyword("text-anchor", - "start middle end", - products="gecko", - animation_value_type="discrete", - spec="https://www.w3.org/TR/SVG/text.html#TextAnchorProperty")} +${helpers.single_keyword( + "text-anchor", + "start middle end", + products="gecko", + animation_value_type="discrete", + spec="https://www.w3.org/TR/SVG/text.html#TextAnchorProperty", +)} // Section 11 - Painting: Filling, Stroking and Marker Symbols -${helpers.single_keyword("color-interpolation", - "srgb auto linearrgb", - products="gecko", - animation_value_type="discrete", - spec="https://www.w3.org/TR/SVG11/painting.html#ColorInterpolationProperty")} - -${helpers.single_keyword("color-interpolation-filters", "linearrgb auto srgb", - products="gecko", - gecko_constant_prefix="NS_STYLE_COLOR_INTERPOLATION", - animation_value_type="discrete", - spec="https://www.w3.org/TR/SVG11/painting.html#ColorInterpolationFiltersProperty")} +${helpers.single_keyword( + "color-interpolation", + "srgb auto linearrgb", + products="gecko", + animation_value_type="discrete", + spec="https://www.w3.org/TR/SVG11/painting.html#ColorInterpolationProperty", +)} + +${helpers.single_keyword( + "color-interpolation-filters", + "linearrgb auto srgb", + products="gecko", + gecko_constant_prefix="NS_STYLE_COLOR_INTERPOLATION", + animation_value_type="discrete", + spec="https://www.w3.org/TR/SVG11/painting.html#ColorInterpolationFiltersProperty", +)} ${helpers.predefined_type( - "fill", "SVGPaint", + "fill", + "SVGPaint", "::values::computed::SVGPaint::black()", products="gecko", animation_value_type="IntermediateSVGPaint", boxed=True, - spec="https://www.w3.org/TR/SVG2/painting.html#SpecifyingFillPaint")} + spec="https://www.w3.org/TR/SVG2/painting.html#SpecifyingFillPaint", +)} -${helpers.predefined_type("fill-opacity", "SVGOpacity", "Default::default()", - products="gecko", animation_value_type="ComputedValue", - spec="https://www.w3.org/TR/SVG11/painting.html#FillOpacityProperty")} +${helpers.predefined_type( + "fill-opacity", + "SVGOpacity", + "Default::default()", + products="gecko", + animation_value_type="ComputedValue", + spec="https://www.w3.org/TR/SVG11/painting.html#FillOpacityProperty", +)} -${helpers.single_keyword("fill-rule", "nonzero evenodd", - gecko_enum_prefix="StyleFillRule", - products="gecko", animation_value_type="discrete", - spec="https://www.w3.org/TR/SVG11/painting.html#FillRuleProperty")} +${helpers.single_keyword( + "fill-rule", + "nonzero evenodd", + gecko_enum_prefix="StyleFillRule", + products="gecko", + animation_value_type="discrete", + spec="https://www.w3.org/TR/SVG11/painting.html#FillRuleProperty", +)} -${helpers.single_keyword("shape-rendering", - "auto optimizespeed crispedges geometricprecision", - products="gecko", - animation_value_type="discrete", - spec="https://www.w3.org/TR/SVG11/painting.html#ShapeRenderingProperty")} +${helpers.single_keyword( + "shape-rendering", + "auto optimizespeed crispedges geometricprecision", + products="gecko", + animation_value_type="discrete", + spec="https://www.w3.org/TR/SVG11/painting.html#ShapeRenderingProperty", +)} ${helpers.predefined_type( - "stroke", "SVGPaint", + "stroke", + "SVGPaint", "Default::default()", products="gecko", animation_value_type="IntermediateSVGPaint", boxed=True, - spec="https://www.w3.org/TR/SVG2/painting.html#SpecifyingStrokePaint")} + spec="https://www.w3.org/TR/SVG2/painting.html#SpecifyingStrokePaint", +)} ${helpers.predefined_type( "stroke-width", "SVGWidth", @@ -70,23 +90,39 @@ ${helpers.predefined_type( spec="https://www.w3.org/TR/SVG2/painting.html#StrokeWidth", )} -${helpers.single_keyword("stroke-linecap", "butt round square", - products="gecko", animation_value_type="discrete", - spec="https://www.w3.org/TR/SVG11/painting.html#StrokeLinecapProperty")} +${helpers.single_keyword( + "stroke-linecap", + "butt round square", + products="gecko", + animation_value_type="discrete", + spec="https://www.w3.org/TR/SVG11/painting.html#StrokeLinecapProperty", +)} -${helpers.single_keyword("stroke-linejoin", "miter round bevel", - products="gecko", animation_value_type="discrete", - spec="https://www.w3.org/TR/SVG11/painting.html#StrokeLinejoinProperty")} +${helpers.single_keyword( + "stroke-linejoin", + "miter round bevel", + products="gecko", + animation_value_type="discrete", + spec="https://www.w3.org/TR/SVG11/painting.html#StrokeLinejoinProperty", +)} -${helpers.predefined_type("stroke-miterlimit", "GreaterThanOrEqualToOneNumber", - "From::from(4.0)", - products="gecko", - animation_value_type="::values::computed::GreaterThanOrEqualToOneNumber", - spec="https://www.w3.org/TR/SVG11/painting.html#StrokeMiterlimitProperty")} +${helpers.predefined_type( + "stroke-miterlimit", + "GreaterThanOrEqualToOneNumber", + "From::from(4.0)", + products="gecko", + animation_value_type="::values::computed::GreaterThanOrEqualToOneNumber", + spec="https://www.w3.org/TR/SVG11/painting.html#StrokeMiterlimitProperty", +)} -${helpers.predefined_type("stroke-opacity", "SVGOpacity", "Default::default()", - products="gecko", animation_value_type="ComputedValue", - spec="https://www.w3.org/TR/SVG11/painting.html#StrokeOpacityProperty")} +${helpers.predefined_type( + "stroke-opacity", + "SVGOpacity", + "Default::default()", + products="gecko", + animation_value_type="ComputedValue", + spec="https://www.w3.org/TR/SVG11/painting.html#StrokeOpacityProperty", +)} ${helpers.predefined_type( "stroke-dasharray", @@ -106,38 +142,59 @@ ${helpers.predefined_type( )} // Section 14 - Clipping, Masking and Compositing -${helpers.single_keyword("clip-rule", "nonzero evenodd", - products="gecko", - gecko_enum_prefix="StyleFillRule", - animation_value_type="discrete", - spec="https://www.w3.org/TR/SVG11/masking.html#ClipRuleProperty")} - -${helpers.predefined_type("marker-start", "url::UrlOrNone", "computed::url::UrlOrNone::none()", - products="gecko", - animation_value_type="discrete", - spec="https://www.w3.org/TR/SVG2/painting.html#VertexMarkerProperties")} - -${helpers.predefined_type("marker-mid", "url::UrlOrNone", "computed::url::UrlOrNone::none()", - products="gecko", - animation_value_type="discrete", - spec="https://www.w3.org/TR/SVG2/painting.html#VertexMarkerProperties")} - -${helpers.predefined_type("marker-end", "url::UrlOrNone", "computed::url::UrlOrNone::none()", - products="gecko", - animation_value_type="discrete", - spec="https://www.w3.org/TR/SVG2/painting.html#VertexMarkerProperties")} - -${helpers.predefined_type("paint-order", "SVGPaintOrder", "computed::SVGPaintOrder::normal()", - products="gecko", - animation_value_type="discrete", - spec="https://www.w3.org/TR/SVG2/painting.html#PaintOrder")} - -${helpers.predefined_type("-moz-context-properties", - "MozContextProperties", - initial_value=None, - vector=True, - need_index=True, - animation_value_type="none", - products="gecko", - spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-context-properties)", - allow_empty=True)} +${helpers.single_keyword( + "clip-rule", + "nonzero evenodd", + products="gecko", + gecko_enum_prefix="StyleFillRule", + animation_value_type="discrete", + spec="https://www.w3.org/TR/SVG11/masking.html#ClipRuleProperty", +)} + +${helpers.predefined_type( + "marker-start", + "url::UrlOrNone", + "computed::url::UrlOrNone::none()", + products="gecko", + animation_value_type="discrete", + spec="https://www.w3.org/TR/SVG2/painting.html#VertexMarkerProperties", +)} + +${helpers.predefined_type( + "marker-mid", + "url::UrlOrNone", + "computed::url::UrlOrNone::none()", + products="gecko", + animation_value_type="discrete", + spec="https://www.w3.org/TR/SVG2/painting.html#VertexMarkerProperties", +)} + +${helpers.predefined_type( + "marker-end", + "url::UrlOrNone", + "computed::url::UrlOrNone::none()", + products="gecko", + animation_value_type="discrete", + spec="https://www.w3.org/TR/SVG2/painting.html#VertexMarkerProperties", +)} + +${helpers.predefined_type( + "paint-order", + "SVGPaintOrder", + "computed::SVGPaintOrder::normal()", + products="gecko", + animation_value_type="discrete", + spec="https://www.w3.org/TR/SVG2/painting.html#PaintOrder", +)} + +${helpers.predefined_type( + "-moz-context-properties", + "MozContextProperties", + initial_value=None, + vector=True, + need_index=True, + animation_value_type="none", + products="gecko", + spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-context-properties)", + allow_empty=True, +)} diff --git a/components/style/properties/longhands/inherited_table.mako.rs b/components/style/properties/longhands/inherited_table.mako.rs index 4f55d9b1fa5..177907dc8f7 100644 --- a/components/style/properties/longhands/inherited_table.mako.rs +++ b/components/style/properties/longhands/inherited_table.mako.rs @@ -6,27 +6,40 @@ <% data.new_style_struct("InheritedTable", inherited=True, gecko_name="TableBorder") %> -${helpers.single_keyword("border-collapse", "separate collapse", - gecko_constant_prefix="NS_STYLE_BORDER", - animation_value_type="discrete", - spec="https://drafts.csswg.org/css-tables/#propdef-border-collapse", - servo_restyle_damage = "reflow")} -${helpers.single_keyword("empty-cells", "show hide", - gecko_constant_prefix="NS_STYLE_TABLE_EMPTY_CELLS", - animation_value_type="discrete", - spec="https://drafts.csswg.org/css-tables/#propdef-empty-cells", - servo_restyle_damage="rebuild_and_reflow")} -${helpers.single_keyword("caption-side", "top bottom", - extra_gecko_values="right left top-outside bottom-outside", - needs_conversion="True", - animation_value_type="discrete", - spec="https://drafts.csswg.org/css-tables/#propdef-caption-side", - servo_restyle_damage="rebuild_and_reflow")} +${helpers.single_keyword( + "border-collapse", + "separate collapse", + gecko_constant_prefix="NS_STYLE_BORDER", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-tables/#propdef-border-collapse", + servo_restyle_damage = "reflow", +)} -${helpers.predefined_type("border-spacing", - "BorderSpacing", - "computed::BorderSpacing::zero()", - animation_value_type="BorderSpacing", - boxed=True, - spec="https://drafts.csswg.org/css-tables/#propdef-border-spacing", - servo_restyle_damage = "reflow")} +${helpers.single_keyword( + "empty-cells", + "show hide", + gecko_constant_prefix="NS_STYLE_TABLE_EMPTY_CELLS", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-tables/#propdef-empty-cells", + servo_restyle_damage="rebuild_and_reflow", +)} + +${helpers.single_keyword( + "caption-side", + "top bottom", + extra_gecko_values="right left top-outside bottom-outside", + needs_conversion="True", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-tables/#propdef-caption-side", + servo_restyle_damage="rebuild_and_reflow", +)} + +${helpers.predefined_type( + "border-spacing", + "BorderSpacing", + "computed::BorderSpacing::zero()", + animation_value_type="BorderSpacing", + boxed=True, + spec="https://drafts.csswg.org/css-tables/#propdef-border-spacing", + servo_restyle_damage = "reflow", +)} diff --git a/components/style/properties/longhands/inherited_text.mako.rs b/components/style/properties/longhands/inherited_text.mako.rs index 62819a78cbc..de7b613a183 100644 --- a/components/style/properties/longhands/inherited_text.mako.rs +++ b/components/style/properties/longhands/inherited_text.mako.rs @@ -20,51 +20,68 @@ ${helpers.predefined_type( // CSS Text Module Level 3 // TODO(pcwalton): `full-width` -${helpers.single_keyword("text-transform", - "none capitalize uppercase lowercase", - extra_gecko_values="full-width", - animation_value_type="discrete", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", - spec="https://drafts.csswg.org/css-text/#propdef-text-transform", - servo_restyle_damage="rebuild_and_reflow")} - -${helpers.single_keyword("hyphens", "manual none auto", - gecko_enum_prefix="StyleHyphens", - products="gecko", animation_value_type="discrete", extra_prefixes="moz", - spec="https://drafts.csswg.org/css-text/#propdef-hyphens")} +${helpers.single_keyword( + "text-transform", + "none capitalize uppercase lowercase", + extra_gecko_values="full-width", + animation_value_type="discrete", + flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + spec="https://drafts.csswg.org/css-text/#propdef-text-transform", + servo_restyle_damage="rebuild_and_reflow", +)} + +${helpers.single_keyword( + "hyphens", + "manual none auto", + gecko_enum_prefix="StyleHyphens", + products="gecko", + animation_value_type="discrete", + extra_prefixes="moz", + spec="https://drafts.csswg.org/css-text/#propdef-hyphens", +)} // TODO: Support <percentage> -${helpers.single_keyword("-moz-text-size-adjust", "auto none", - gecko_constant_prefix="NS_STYLE_TEXT_SIZE_ADJUST", - gecko_ffi_name="mTextSizeAdjust", - products="gecko", animation_value_type="discrete", - spec="https://drafts.csswg.org/css-size-adjust/#adjustment-control", - alias="-webkit-text-size-adjust")} - -${helpers.predefined_type("text-indent", - "LengthOrPercentage", - "computed::LengthOrPercentage::Length(computed::Length::new(0.))", - animation_value_type="ComputedValue", - spec="https://drafts.csswg.org/css-text/#propdef-text-indent", - allow_quirks=True, servo_restyle_damage = "reflow")} +${helpers.single_keyword( + "-moz-text-size-adjust", + "auto none", + gecko_constant_prefix="NS_STYLE_TEXT_SIZE_ADJUST", + gecko_ffi_name="mTextSizeAdjust", + products="gecko", animation_value_type="discrete", + spec="https://drafts.csswg.org/css-size-adjust/#adjustment-control", + alias="-webkit-text-size-adjust", +)} + +${helpers.predefined_type( + "text-indent", + "LengthOrPercentage", + "computed::LengthOrPercentage::Length(computed::Length::new(0.))", + animation_value_type="ComputedValue", + spec="https://drafts.csswg.org/css-text/#propdef-text-indent", + allow_quirks=True, + servo_restyle_damage = "reflow", +)} // Also known as "word-wrap" (which is more popular because of IE), but this is the preferred // name per CSS-TEXT 6.2. -${helpers.single_keyword("overflow-wrap", - "normal break-word", - gecko_constant_prefix="NS_STYLE_OVERFLOWWRAP", - animation_value_type="discrete", - spec="https://drafts.csswg.org/css-text/#propdef-overflow-wrap", - alias="word-wrap", - servo_restyle_damage="rebuild_and_reflow")} +${helpers.single_keyword( + "overflow-wrap", + "normal break-word", + gecko_constant_prefix="NS_STYLE_OVERFLOWWRAP", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-text/#propdef-overflow-wrap", + alias="word-wrap", + servo_restyle_damage="rebuild_and_reflow", +)} // TODO(pcwalton): Support `word-break: keep-all` once we have better CJK support. -${helpers.single_keyword("word-break", - "normal break-all keep-all", - gecko_constant_prefix="NS_STYLE_WORDBREAK", - animation_value_type="discrete", - spec="https://drafts.csswg.org/css-text/#propdef-word-break", - servo_restyle_damage="rebuild_and_reflow")} +${helpers.single_keyword( + "word-break", + "normal break-all keep-all", + gecko_constant_prefix="NS_STYLE_WORDBREAK", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-text/#propdef-word-break", + servo_restyle_damage="rebuild_and_reflow", +)} // TODO(pcwalton): Support `text-justify: distribute`. <%helpers:single_keyword @@ -106,39 +123,45 @@ ${helpers.single_keyword("word-break", % endif </%helpers:single_keyword> -${helpers.single_keyword("text-align-last", - "auto start end left right center justify", - products="gecko", - gecko_constant_prefix="NS_STYLE_TEXT_ALIGN", - animation_value_type="discrete", - spec="https://drafts.csswg.org/css-text/#propdef-text-align-last")} +${helpers.single_keyword( + "text-align-last", + "auto start end left right center justify", + products="gecko", + gecko_constant_prefix="NS_STYLE_TEXT_ALIGN", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-text/#propdef-text-align-last", +)} // TODO make this a shorthand and implement text-align-last/text-align-all -// -// FIXME(emilio): This can't really be that complicated. -${helpers.predefined_type("text-align", - "TextAlign", - "computed::TextAlign::start()", - animation_value_type="discrete", - flags="APPLIES_TO_PLACEHOLDER", - spec="https://drafts.csswg.org/css-text/#propdef-text-align", - servo_restyle_damage = "reflow")} - -${helpers.predefined_type("letter-spacing", - "LetterSpacing", - "computed::LetterSpacing::normal()", - animation_value_type="ComputedValue", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", - spec="https://drafts.csswg.org/css-text/#propdef-letter-spacing", - servo_restyle_damage="rebuild_and_reflow")} - -${helpers.predefined_type("word-spacing", - "WordSpacing", - "computed::WordSpacing::normal()", - animation_value_type="ComputedValue", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", - spec="https://drafts.csswg.org/css-text/#propdef-word-spacing", - servo_restyle_damage="rebuild_and_reflow")} +${helpers.predefined_type( + "text-align", + "TextAlign", + "computed::TextAlign::start()", + animation_value_type="discrete", + flags="APPLIES_TO_PLACEHOLDER", + spec="https://drafts.csswg.org/css-text/#propdef-text-align", + servo_restyle_damage = "reflow", +)} + +${helpers.predefined_type( + "letter-spacing", + "LetterSpacing", + "computed::LetterSpacing::normal()", + animation_value_type="ComputedValue", + flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + spec="https://drafts.csswg.org/css-text/#propdef-letter-spacing", + servo_restyle_damage="rebuild_and_reflow", +)} + +${helpers.predefined_type( + "word-spacing", + "WordSpacing", + "computed::WordSpacing::normal()", + animation_value_type="ComputedValue", + flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + spec="https://drafts.csswg.org/css-text/#propdef-word-spacing", + servo_restyle_damage="rebuild_and_reflow", +)} <%helpers:single_keyword name="white-space" @@ -267,47 +290,65 @@ ${helpers.predefined_type( spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-color", )} -${helpers.predefined_type("-webkit-text-stroke-width", - "BorderSideWidth", - "::values::computed::NonNegativeLength::new(0.)", - initial_specified_value="specified::BorderSideWidth::Length(specified::Length::zero())", - computed_type="::values::computed::NonNegativeLength", - products="gecko", - gecko_pref="layout.css.prefixes.webkit", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", - spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-width", - animation_value_type="discrete")} +${helpers.predefined_type( + "-webkit-text-stroke-width", + "BorderSideWidth", + "::values::computed::NonNegativeLength::new(0.)", + initial_specified_value="specified::BorderSideWidth::Length(specified::Length::zero())", + computed_type="::values::computed::NonNegativeLength", + products="gecko", + gecko_pref="layout.css.prefixes.webkit", + flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-width", + animation_value_type="discrete", +)} // CSS Ruby Layout Module Level 1 // https://drafts.csswg.org/css-ruby/ -${helpers.single_keyword("ruby-align", "space-around start center space-between", - products="gecko", animation_value_type="discrete", - spec="https://drafts.csswg.org/css-ruby/#ruby-align-property")} +${helpers.single_keyword( + "ruby-align", + "space-around start center space-between", + products="gecko", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-ruby/#ruby-align-property", +)} -${helpers.single_keyword("ruby-position", "over under", - products="gecko", animation_value_type="discrete", - spec="https://drafts.csswg.org/css-ruby/#ruby-position-property")} +${helpers.single_keyword( + "ruby-position", + "over under", + products="gecko", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-ruby/#ruby-position-property", +)} // CSS Writing Modes Module Level 3 // https://drafts.csswg.org/css-writing-modes-3/ -${helpers.single_keyword("text-combine-upright", "none all", - products="gecko", animation_value_type="discrete", - spec="https://drafts.csswg.org/css-writing-modes-3/#text-combine-upright")} +${helpers.single_keyword( + "text-combine-upright", + "none all", + products="gecko", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-writing-modes-3/#text-combine-upright", +)} // SVG 1.1: Section 11 - Painting: Filling, Stroking and Marker Symbols -${helpers.single_keyword("text-rendering", - "auto optimizespeed optimizelegibility geometricprecision", - animation_value_type="discrete", - spec="https://www.w3.org/TR/SVG11/painting.html#TextRenderingProperty", - servo_restyle_damage="rebuild_and_reflow")} +${helpers.single_keyword( + "text-rendering", + "auto optimizespeed optimizelegibility geometricprecision", + animation_value_type="discrete", + spec="https://www.w3.org/TR/SVG11/painting.html#TextRenderingProperty", + servo_restyle_damage="rebuild_and_reflow", +)} // FIXME Firefox expects the initial value of this property to change depending // on the value of the layout.css.control-characters.visible pref. -${helpers.single_keyword("-moz-control-character-visibility", - "hidden visible", - gecko_constant_prefix="NS_STYLE_CONTROL_CHARACTER_VISIBILITY", - gecko_ffi_name="mControlCharacterVisibility", - animation_value_type="none", - products="gecko", - spec="Nonstandard")} +${helpers.single_keyword( + "-moz-control-character-visibility", + "hidden visible", + gecko_constant_prefix="NS_STYLE_CONTROL_CHARACTER_VISIBILITY", + gecko_ffi_name="mControlCharacterVisibility", + animation_value_type="none", + products="gecko", + spec="Nonstandard", +)} diff --git a/components/style/properties/longhands/inherited_ui.mako.rs b/components/style/properties/longhands/inherited_ui.mako.rs index e597f97ce8c..0b2b590cf7f 100644 --- a/components/style/properties/longhands/inherited_ui.mako.rs +++ b/components/style/properties/longhands/inherited_ui.mako.rs @@ -6,40 +6,56 @@ <% data.new_style_struct("InheritedUI", inherited=True, gecko_name="UI") %> -${helpers.predefined_type("cursor", - "Cursor", - "computed::Cursor::auto()", - initial_specified_value="specified::Cursor::auto()", - animation_value_type="discrete", - spec="https://drafts.csswg.org/css-ui/#cursor")} +${helpers.predefined_type( + "cursor", + "Cursor", + "computed::Cursor::auto()", + initial_specified_value="specified::Cursor::auto()", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-ui/#cursor", +)} // NB: `pointer-events: auto` (and use of `pointer-events` in anything that isn't SVG, in fact) // is nonstandard, slated for CSS4-UI. // TODO(pcwalton): SVG-only values. -${helpers.single_keyword("pointer-events", "auto none", animation_value_type="discrete", - extra_gecko_values="visiblepainted visiblefill visiblestroke visible painted fill stroke all", - flags="APPLIES_TO_PLACEHOLDER", - spec="https://www.w3.org/TR/SVG11/interact.html#PointerEventsProperty")} +${helpers.single_keyword( + "pointer-events", + "auto none", + animation_value_type="discrete", + extra_gecko_values="visiblepainted visiblefill visiblestroke visible painted fill stroke all", + flags="APPLIES_TO_PLACEHOLDER", + spec="https://www.w3.org/TR/SVG11/interact.html#PointerEventsProperty", +)} -${helpers.single_keyword("-moz-user-input", "auto none", - products="gecko", gecko_ffi_name="mUserInput", - gecko_enum_prefix="StyleUserInput", - animation_value_type="discrete", - spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-input)")} +${helpers.single_keyword( + "-moz-user-input", + "auto none", + products="gecko", + gecko_ffi_name="mUserInput", + gecko_enum_prefix="StyleUserInput", + animation_value_type="discrete", + spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-input)", +)} -${helpers.single_keyword("-moz-user-modify", "read-only read-write write-only", - products="gecko", gecko_ffi_name="mUserModify", - gecko_enum_prefix="StyleUserModify", - needs_conversion=True, - animation_value_type="discrete", - spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-modify)")} +${helpers.single_keyword( + "-moz-user-modify", + "read-only read-write write-only", + products="gecko", + gecko_ffi_name="mUserModify", + gecko_enum_prefix="StyleUserModify", + needs_conversion=True, + animation_value_type="discrete", + spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-modify)", +)} -${helpers.single_keyword("-moz-user-focus", - "none ignore normal select-after select-before select-menu select-same select-all", - products="gecko", gecko_ffi_name="mUserFocus", - gecko_enum_prefix="StyleUserFocus", - animation_value_type="discrete", - spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-focus)")} +${helpers.single_keyword( + "-moz-user-focus", + "none ignore normal select-after select-before select-menu select-same select-all", + products="gecko", gecko_ffi_name="mUserFocus", + gecko_enum_prefix="StyleUserFocus", + animation_value_type="discrete", + spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-focus)", +)} ${helpers.predefined_type( "caret-color", diff --git a/components/style/properties/longhands/list.mako.rs b/components/style/properties/longhands/list.mako.rs index 5ed1ea44831..732275fb03e 100644 --- a/components/style/properties/longhands/list.mako.rs +++ b/components/style/properties/longhands/list.mako.rs @@ -40,25 +40,31 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu )} % endif -${helpers.predefined_type("list-style-image", - "url::ImageUrlOrNone", - initial_value="computed::url::ImageUrlOrNone::none()", - initial_specified_value="specified::url::ImageUrlOrNone::none()", - animation_value_type="discrete", - spec="https://drafts.csswg.org/css-lists/#propdef-list-style-image", - servo_restyle_damage="rebuild_and_reflow")} +${helpers.predefined_type( + "list-style-image", + "url::ImageUrlOrNone", + initial_value="computed::url::ImageUrlOrNone::none()", + initial_specified_value="specified::url::ImageUrlOrNone::none()", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-lists/#propdef-list-style-image", + servo_restyle_damage="rebuild_and_reflow", +)} -${helpers.predefined_type("quotes", - "Quotes", - "computed::Quotes::get_initial_value()", - animation_value_type="discrete", - spec="https://drafts.csswg.org/css-content/#propdef-quotes", - servo_restyle_damage="rebuild_and_reflow")} +${helpers.predefined_type( + "quotes", + "Quotes", + "computed::Quotes::get_initial_value()", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-content/#propdef-quotes", + servo_restyle_damage="rebuild_and_reflow", +)} -${helpers.predefined_type("-moz-image-region", - "ClipRectOrAuto", - "computed::ClipRectOrAuto::auto()", - animation_value_type="ComputedValue", - products="gecko", - boxed=True, - spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-image-region)")} +${helpers.predefined_type( + "-moz-image-region", + "ClipRectOrAuto", + "computed::ClipRectOrAuto::auto()", + animation_value_type="ComputedValue", + products="gecko", + boxed=True, + spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-image-region)", +)} diff --git a/components/style/properties/longhands/outline.mako.rs b/components/style/properties/longhands/outline.mako.rs index 9446745ec3e..a61aae06d7c 100644 --- a/components/style/properties/longhands/outline.mako.rs +++ b/components/style/properties/longhands/outline.mako.rs @@ -29,24 +29,34 @@ ${helpers.predefined_type( spec="https://drafts.csswg.org/css-ui/#propdef-outline-style", )} -${helpers.predefined_type("outline-width", - "BorderSideWidth", - "::values::computed::NonNegativeLength::new(3.)", - initial_specified_value="specified::BorderSideWidth::Medium", - computed_type="::values::computed::NonNegativeLength", - animation_value_type="NonNegativeLength", - spec="https://drafts.csswg.org/css-ui/#propdef-outline-width")} +${helpers.predefined_type( + "outline-width", + "BorderSideWidth", + "::values::computed::NonNegativeLength::new(3.)", + initial_specified_value="specified::BorderSideWidth::Medium", + computed_type="::values::computed::NonNegativeLength", + animation_value_type="NonNegativeLength", + spec="https://drafts.csswg.org/css-ui/#propdef-outline-width", +)} // The -moz-outline-radius-* properties are non-standard and not on a standards track. % for corner in ["topleft", "topright", "bottomright", "bottomleft"]: - ${helpers.predefined_type("-moz-outline-radius-" + corner, "BorderCornerRadius", + ${helpers.predefined_type( + "-moz-outline-radius-" + corner, + "BorderCornerRadius", "computed::BorderCornerRadius::zero()", products="gecko", boxed=True, animation_value_type="BorderCornerRadius", - spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-outline-radius)")} + spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-outline-radius)", + )} % endfor -${helpers.predefined_type("outline-offset", "Length", "::values::computed::Length::new(0.)", - products="servo gecko", animation_value_type="ComputedValue", - spec="https://drafts.csswg.org/css-ui/#propdef-outline-offset")} +${helpers.predefined_type( + "outline-offset", + "Length", + "::values::computed::Length::new(0.)", + products="servo gecko", + animation_value_type="ComputedValue", + spec="https://drafts.csswg.org/css-ui/#propdef-outline-offset", +)} diff --git a/components/style/properties/longhands/position.mako.rs b/components/style/properties/longhands/position.mako.rs index 957335d32b2..5ec34961d22 100644 --- a/components/style/properties/longhands/position.mako.rs +++ b/components/style/properties/longhands/position.mako.rs @@ -68,73 +68,93 @@ ${helpers.predefined_type( // http://www.w3.org/TR/css3-flexbox/ // Flex container properties -${helpers.single_keyword("flex-direction", "row row-reverse column column-reverse", - spec="https://drafts.csswg.org/css-flexbox/#flex-direction-property", - extra_prefixes="webkit", - animation_value_type="discrete", - servo_restyle_damage = "reflow")} - -${helpers.single_keyword("flex-wrap", "nowrap wrap wrap-reverse", - spec="https://drafts.csswg.org/css-flexbox/#flex-wrap-property", - extra_prefixes="webkit", - animation_value_type="discrete", - servo_restyle_damage = "reflow")} +${helpers.single_keyword( + "flex-direction", + "row row-reverse column column-reverse", + spec="https://drafts.csswg.org/css-flexbox/#flex-direction-property", + extra_prefixes="webkit", + animation_value_type="discrete", + servo_restyle_damage = "reflow", +)} + +${helpers.single_keyword( + "flex-wrap", + "nowrap wrap wrap-reverse", + spec="https://drafts.csswg.org/css-flexbox/#flex-wrap-property", + extra_prefixes="webkit", + animation_value_type="discrete", + servo_restyle_damage = "reflow", +)} % if product == "servo": // FIXME: Update Servo to support the same Syntax as Gecko. - ${helpers.single_keyword("justify-content", "flex-start stretch flex-end center space-between space-around", - extra_prefixes="webkit", - spec="https://drafts.csswg.org/css-align/#propdef-justify-content", - animation_value_type="discrete", - servo_restyle_damage = "reflow")} + ${helpers.single_keyword( + "justify-content", + "flex-start stretch flex-end center space-between space-around", + extra_prefixes="webkit", + spec="https://drafts.csswg.org/css-align/#propdef-justify-content", + animation_value_type="discrete", + servo_restyle_damage = "reflow", + )} % else: - ${helpers.predefined_type(name="justify-content", - type="JustifyContent", - initial_value="specified::JustifyContent(specified::ContentDistribution::normal())", - spec="https://drafts.csswg.org/css-align/#propdef-justify-content", - extra_prefixes="webkit", - animation_value_type="discrete", - servo_restyle_damage = "reflow")} + ${helpers.predefined_type( + "justify-content", + "JustifyContent", + "specified::JustifyContent(specified::ContentDistribution::normal())", + spec="https://drafts.csswg.org/css-align/#propdef-justify-content", + extra_prefixes="webkit", + animation_value_type="discrete", + servo_restyle_damage="reflow", + )} % endif % if product == "servo": // FIXME: Update Servo to support the same Syntax as Gecko. - ${helpers.single_keyword("align-content", "stretch flex-start flex-end center space-between space-around", - extra_prefixes="webkit", - spec="https://drafts.csswg.org/css-align/#propdef-align-content", - animation_value_type="discrete", - servo_restyle_damage = "reflow")} - - ${helpers.single_keyword("align-items", - "stretch flex-start flex-end center baseline", - extra_prefixes="webkit", - spec="https://drafts.csswg.org/css-flexbox/#align-items-property", - animation_value_type="discrete", - servo_restyle_damage = "reflow")} + ${helpers.single_keyword( + "align-content", + "stretch flex-start flex-end center space-between space-around", + extra_prefixes="webkit", + spec="https://drafts.csswg.org/css-align/#propdef-align-content", + animation_value_type="discrete", + servo_restyle_damage="reflow", + )} + + ${helpers.single_keyword( + "align-items", + "stretch flex-start flex-end center baseline", + extra_prefixes="webkit", + spec="https://drafts.csswg.org/css-flexbox/#align-items-property", + animation_value_type="discrete", + servo_restyle_damage="reflow", + )} % else: - ${helpers.predefined_type(name="align-content", - type="AlignContent", - initial_value="specified::AlignContent(specified::ContentDistribution::normal())", - spec="https://drafts.csswg.org/css-align/#propdef-align-content", - extra_prefixes="webkit", - animation_value_type="discrete", - servo_restyle_damage = "reflow")} - - ${helpers.predefined_type(name="align-items", - type="AlignItems", - initial_value="specified::AlignItems::normal()", - spec="https://drafts.csswg.org/css-align/#propdef-align-items", - extra_prefixes="webkit", - animation_value_type="discrete", - servo_restyle_damage = "reflow")} + ${helpers.predefined_type( + "align-content", + "AlignContent", + "specified::AlignContent(specified::ContentDistribution::normal())", + spec="https://drafts.csswg.org/css-align/#propdef-align-content", + extra_prefixes="webkit", + animation_value_type="discrete", + servo_restyle_damage="reflow", + )} + + ${helpers.predefined_type( + "align-items", + "AlignItems", + "specified::AlignItems::normal()", + spec="https://drafts.csswg.org/css-align/#propdef-align-items", + extra_prefixes="webkit", + animation_value_type="discrete", + servo_restyle_damage="reflow", + )} #[cfg(feature = "gecko")] impl_align_conversions!(::values::specified::align::AlignItems); ${helpers.predefined_type( - name="justify-items", - type="JustifyItems", - initial_value="computed::JustifyItems::legacy()", + "justify-items", + "JustifyItems", + "computed::JustifyItems::legacy()", spec="https://drafts.csswg.org/css-align/#propdef-justify-items", animation_value_type="discrete", )} @@ -144,52 +164,69 @@ ${helpers.single_keyword("flex-wrap", "nowrap wrap wrap-reverse", % endif // Flex item properties -${helpers.predefined_type("flex-grow", "NonNegativeNumber", - "From::from(0.0)", - spec="https://drafts.csswg.org/css-flexbox/#flex-grow-property", - extra_prefixes="webkit", - animation_value_type="NonNegativeNumber", - servo_restyle_damage = "reflow")} - -${helpers.predefined_type("flex-shrink", "NonNegativeNumber", - "From::from(1.0)", - spec="https://drafts.csswg.org/css-flexbox/#flex-shrink-property", - extra_prefixes="webkit", - animation_value_type="NonNegativeNumber", - servo_restyle_damage = "reflow")} +${helpers.predefined_type( + "flex-grow", + "NonNegativeNumber", + "From::from(0.0)", + spec="https://drafts.csswg.org/css-flexbox/#flex-grow-property", + extra_prefixes="webkit", + animation_value_type="NonNegativeNumber", + servo_restyle_damage="reflow", +)} + +${helpers.predefined_type( + "flex-shrink", + "NonNegativeNumber", + "From::from(1.0)", + spec="https://drafts.csswg.org/css-flexbox/#flex-shrink-property", + extra_prefixes="webkit", + animation_value_type="NonNegativeNumber", + servo_restyle_damage = "reflow", +)} // https://drafts.csswg.org/css-align/#align-self-property % if product == "servo": // FIXME: Update Servo to support the same syntax as Gecko. - ${helpers.single_keyword("align-self", "auto stretch flex-start flex-end center baseline", - extra_prefixes="webkit", - spec="https://drafts.csswg.org/css-flexbox/#propdef-align-self", - animation_value_type="discrete", - servo_restyle_damage = "reflow")} + ${helpers.single_keyword( + "align-self", + "auto stretch flex-start flex-end center baseline", + extra_prefixes="webkit", + spec="https://drafts.csswg.org/css-flexbox/#propdef-align-self", + animation_value_type="discrete", + servo_restyle_damage = "reflow", + )} % else: - ${helpers.predefined_type(name="align-self", - type="AlignSelf", - initial_value="specified::AlignSelf(specified::SelfAlignment::auto())", - spec="https://drafts.csswg.org/css-align/#align-self-property", - extra_prefixes="webkit", - animation_value_type="discrete")} - - ${helpers.predefined_type(name="justify-self", - type="JustifySelf", - initial_value="specified::JustifySelf(specified::SelfAlignment::auto())", - spec="https://drafts.csswg.org/css-align/#justify-self-property", - animation_value_type="discrete")} + ${helpers.predefined_type( + "align-self", + "AlignSelf", + "specified::AlignSelf(specified::SelfAlignment::auto())", + spec="https://drafts.csswg.org/css-align/#align-self-property", + extra_prefixes="webkit", + animation_value_type="discrete", + )} + + ${helpers.predefined_type( + "justify-self", + "JustifySelf", + "specified::JustifySelf(specified::SelfAlignment::auto())", + spec="https://drafts.csswg.org/css-align/#justify-self-property", + animation_value_type="discrete", + )} #[cfg(feature = "gecko")] impl_align_conversions!(::values::specified::align::SelfAlignment); % endif // https://drafts.csswg.org/css-flexbox/#propdef-order -${helpers.predefined_type("order", "Integer", "0", - extra_prefixes="webkit", - animation_value_type="ComputedValue", - spec="https://drafts.csswg.org/css-flexbox/#order-property", - servo_restyle_damage = "reflow")} +${helpers.predefined_type( + "order", + "Integer", + "0", + extra_prefixes="webkit", + animation_value_type="ComputedValue", + spec="https://drafts.csswg.org/css-flexbox/#order-property", + servo_restyle_damage = "reflow", +)} ${helpers.predefined_type( "flex-basis", @@ -198,7 +235,7 @@ ${helpers.predefined_type( spec="https://drafts.csswg.org/css-flexbox/#flex-basis-property", extra_prefixes="webkit", animation_value_type="FlexBasis", - servo_restyle_damage = "reflow" + servo_restyle_damage = "reflow", )} % for (size, logical) in ALL_SIZES: @@ -228,7 +265,7 @@ ${helpers.predefined_type( spec=spec % size, animation_value_type="MozLength", flags="GETCS_NEEDS_LAYOUT_FLUSH", - servo_restyle_damage="reflow" + servo_restyle_damage="reflow", )} // min-width, min-height, min-block-size, min-inline-size, ${helpers.predefined_type( @@ -241,7 +278,7 @@ ${helpers.predefined_type( allow_quirks=not logical, spec=spec % size, animation_value_type="MozLength", - servo_restyle_damage = "reflow" + servo_restyle_damage="reflow", )} ${helpers.predefined_type( "max-%s" % size, @@ -253,7 +290,7 @@ ${helpers.predefined_type( allow_quirks=not logical, spec=spec % size, animation_value_type="MaxLength", - servo_restyle_damage = "reflow" + servo_restyle_damage="reflow", )} % else: // servo versions (no keyword support) @@ -266,7 +303,7 @@ ${helpers.predefined_type( logical_group="size", allow_quirks=not logical, animation_value_type="ComputedValue", logical = logical, - servo_restyle_damage = "reflow", + servo_restyle_damage="reflow", )} ${helpers.predefined_type( "min-%s" % size, @@ -278,7 +315,7 @@ ${helpers.predefined_type( animation_value_type="ComputedValue", logical=logical, allow_quirks=not logical, - servo_restyle_damage = "reflow", + servo_restyle_damage="reflow", )} ${helpers.predefined_type( "max-%s" % size, @@ -290,52 +327,64 @@ ${helpers.predefined_type( animation_value_type="ComputedValue", logical=logical, allow_quirks=not logical, - servo_restyle_damage = "reflow", + servo_restyle_damage="reflow", )} % endif % endfor -${helpers.single_keyword("box-sizing", - "content-box border-box", - extra_prefixes="moz:layout.css.prefixes.box-sizing webkit", - spec="https://drafts.csswg.org/css-ui/#propdef-box-sizing", - gecko_enum_prefix="StyleBoxSizing", - custom_consts={ "content-box": "Content", "border-box": "Border" }, - animation_value_type="discrete", - servo_restyle_damage = "reflow")} - -${helpers.single_keyword("object-fit", "fill contain cover none scale-down", - products="gecko", animation_value_type="discrete", - spec="https://drafts.csswg.org/css-images/#propdef-object-fit")} - -${helpers.predefined_type("object-position", - "Position", - "computed::Position::zero()", - products="gecko", - boxed=True, - spec="https://drafts.csswg.org/css-images-3/#the-object-position", - animation_value_type="ComputedValue")} +${helpers.single_keyword( + "box-sizing", + "content-box border-box", + extra_prefixes="moz:layout.css.prefixes.box-sizing webkit", + spec="https://drafts.csswg.org/css-ui/#propdef-box-sizing", + gecko_enum_prefix="StyleBoxSizing", + custom_consts={ "content-box": "Content", "border-box": "Border" }, + animation_value_type="discrete", + servo_restyle_damage = "reflow", +)} + +${helpers.single_keyword( + "object-fit", + "fill contain cover none scale-down", + products="gecko", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-images/#propdef-object-fit", +)} + +${helpers.predefined_type( + "object-position", + "Position", + "computed::Position::zero()", + products="gecko", + boxed=True, + spec="https://drafts.csswg.org/css-images-3/#the-object-position", + animation_value_type="ComputedValue", +)} % for kind in ["row", "column"]: % for range in ["start", "end"]: - ${helpers.predefined_type("grid-%s-%s" % (kind, range), - "GridLine", - "Default::default()", - animation_value_type="discrete", - spec="https://drafts.csswg.org/css-grid/#propdef-grid-%s-%s" % (kind, range), - products="gecko", - boxed=True)} + ${helpers.predefined_type( + "grid-%s-%s" % (kind, range), + "GridLine", + "Default::default()", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-grid/#propdef-grid-%s-%s" % (kind, range), + products="gecko", + boxed=True, + )} % 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", - "Default::default()", - animation_value_type="discrete", - spec="https://drafts.csswg.org/css-grid/#propdef-grid-auto-%ss" % kind, - products="gecko", - boxed=True)} + ${helpers.predefined_type( + "grid-auto-%ss" % kind, + "TrackSize", + "Default::default()", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-grid/#propdef-grid-auto-%ss" % kind, + products="gecko", + boxed=True, + )} ${helpers.predefined_type( "grid-template-%ss" % kind, @@ -345,41 +394,49 @@ ${helpers.predefined_type("object-position", spec="https://drafts.csswg.org/css-grid/#propdef-grid-template-%ss" % kind, boxed=True, flags="GETCS_NEEDS_LAYOUT_FLUSH", - animation_value_type="discrete" + animation_value_type="discrete", )} % endfor -${helpers.predefined_type("grid-auto-flow", - "GridAutoFlow", - initial_value="computed::GridAutoFlow::row()", - products="gecko", - animation_value_type="discrete", - spec="https://drafts.csswg.org/css-grid/#propdef-grid-auto-flow")} - -${helpers.predefined_type("grid-template-areas", - "GridTemplateAreas", - initial_value="computed::GridTemplateAreas::none()", - products="gecko", - animation_value_type="discrete", - spec="https://drafts.csswg.org/css-grid/#propdef-grid-template-areas")} - -${helpers.predefined_type("column-gap", - "length::NonNegativeLengthOrPercentageOrNormal", - "Either::Second(Normal)", - alias="grid-column-gap" if product == "gecko" else "", - extra_prefixes="moz", - servo_pref="layout.columns.enabled", - spec="https://drafts.csswg.org/css-align-3/#propdef-column-gap", - animation_value_type="NonNegativeLengthOrPercentageOrNormal", - servo_restyle_damage = "reflow")} +${helpers.predefined_type( + "grid-auto-flow", + "GridAutoFlow", + "computed::GridAutoFlow::row()", + products="gecko", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-grid/#propdef-grid-auto-flow", +)} + +${helpers.predefined_type( + "grid-template-areas", + "GridTemplateAreas", + "computed::GridTemplateAreas::none()", + products="gecko", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-grid/#propdef-grid-template-areas", +)} + +${helpers.predefined_type( + "column-gap", + "length::NonNegativeLengthOrPercentageOrNormal", + "Either::Second(Normal)", + alias="grid-column-gap" if product == "gecko" else "", + extra_prefixes="moz", + servo_pref="layout.columns.enabled", + spec="https://drafts.csswg.org/css-align-3/#propdef-column-gap", + animation_value_type="NonNegativeLengthOrPercentageOrNormal", + servo_restyle_damage="reflow", +)} // no need for -moz- prefixed alias for this property -${helpers.predefined_type("row-gap", - "length::NonNegativeLengthOrPercentageOrNormal", - "Either::Second(Normal)", - alias="grid-row-gap", - products="gecko", - spec="https://drafts.csswg.org/css-align-3/#propdef-row-gap", - animation_value_type="NonNegativeLengthOrPercentageOrNormal", - servo_restyle_damage = "reflow")} +${helpers.predefined_type( + "row-gap", + "length::NonNegativeLengthOrPercentageOrNormal", + "Either::Second(Normal)", + alias="grid-row-gap", + products="gecko", + spec="https://drafts.csswg.org/css-align-3/#propdef-row-gap", + animation_value_type="NonNegativeLengthOrPercentageOrNormal", + servo_restyle_damage="reflow", +)} diff --git a/components/style/properties/longhands/svg.mako.rs b/components/style/properties/longhands/svg.mako.rs index 6d7bf803f1e..36105247676 100644 --- a/components/style/properties/longhands/svg.mako.rs +++ b/components/style/properties/longhands/svg.mako.rs @@ -6,16 +6,22 @@ <% data.new_style_struct("SVG", inherited=False, gecko_name="SVGReset") %> -${helpers.single_keyword("dominant-baseline", - """auto use-script no-change reset-size ideographic alphabetic hanging - mathematical central middle text-after-edge text-before-edge""", - products="gecko", - animation_value_type="discrete", - spec="https://www.w3.org/TR/SVG11/text.html#DominantBaselineProperty")} +${helpers.single_keyword( + "dominant-baseline", + """auto use-script no-change reset-size ideographic alphabetic hanging + mathematical central middle text-after-edge text-before-edge""", + products="gecko", + animation_value_type="discrete", + spec="https://www.w3.org/TR/SVG11/text.html#DominantBaselineProperty", +)} -${helpers.single_keyword("vector-effect", "none non-scaling-stroke", - products="gecko", animation_value_type="discrete", - spec="https://www.w3.org/TR/SVGTiny12/painting.html#VectorEffectProperty")} +${helpers.single_keyword( + "vector-effect", + "none non-scaling-stroke", + products="gecko", + animation_value_type="discrete", + spec="https://www.w3.org/TR/SVGTiny12/painting.html#VectorEffectProperty", +)} // Section 13 - Gradients and Patterns @@ -28,10 +34,14 @@ ${helpers.predefined_type( spec="https://www.w3.org/TR/SVGTiny12/painting.html#StopColorProperty", )} -${helpers.predefined_type("stop-opacity", "Opacity", "1.0", - products="gecko", - animation_value_type="ComputedValue", - spec="https://www.w3.org/TR/SVGTiny12/painting.html#propdef-stop-opacity")} +${helpers.predefined_type( + "stop-opacity", + "Opacity", + "1.0", + products="gecko", + animation_value_type="ComputedValue", + spec="https://www.w3.org/TR/SVGTiny12/painting.html#propdef-stop-opacity", +)} // Section 15 - Filter Effects @@ -44,9 +54,14 @@ ${helpers.predefined_type( spec="https://www.w3.org/TR/SVG/filters.html#FloodColorProperty", )} -${helpers.predefined_type("flood-opacity", "Opacity", - "1.0", products="gecko", animation_value_type="ComputedValue", - spec="https://www.w3.org/TR/SVG/filters.html#FloodOpacityProperty")} +${helpers.predefined_type( + "flood-opacity", + "Opacity", + "1.0", + products="gecko", + animation_value_type="ComputedValue", + spec="https://www.w3.org/TR/SVG/filters.html#FloodOpacityProperty", +)} ${helpers.predefined_type( "lighting-color", @@ -59,9 +74,13 @@ ${helpers.predefined_type( // CSS Masking Module Level 1 // https://drafts.fxtf.org/css-masking -${helpers.single_keyword("mask-type", "luminance alpha", - products="gecko", animation_value_type="discrete", - spec="https://drafts.fxtf.org/css-masking/#propdef-mask-type")} +${helpers.single_keyword( + "mask-type", + "luminance alpha", + products="gecko", + animation_value_type="discrete", + spec="https://drafts.fxtf.org/css-masking/#propdef-mask-type", +)} ${helpers.predefined_type( "clip-path", @@ -74,12 +93,14 @@ ${helpers.predefined_type( spec="https://drafts.fxtf.org/css-masking/#propdef-clip-path", )} -${helpers.single_keyword("mask-mode", - "match-source alpha luminance", - vector=True, - products="gecko", - animation_value_type="discrete", - spec="https://drafts.fxtf.org/css-masking/#propdef-mask-mode")} +${helpers.single_keyword( + "mask-mode", + "match-source alpha luminance", + vector=True, + products="gecko", + animation_value_type="discrete", + spec="https://drafts.fxtf.org/css-masking/#propdef-mask-mode", +)} ${helpers.predefined_type( "mask-repeat", @@ -97,9 +118,9 @@ ${helpers.predefined_type( ${helpers.predefined_type( "mask-position-" + axis, "position::" + direction + "Position", + "computed::LengthOrPercentage::zero()", products="gecko", extra_prefixes="webkit", - initial_value="computed::LengthOrPercentage::zero()", initial_specified_value="specified::PositionComponent::Center", spec="https://drafts.fxtf.org/css-masking/#propdef-mask-position", animation_value_type="ComputedValue", @@ -147,20 +168,25 @@ ${helpers.predefined_type( vector_animation_type="repeatable_list", )} -${helpers.single_keyword("mask-composite", - "add subtract intersect exclude", - vector=True, - products="gecko", - extra_prefixes="webkit", - animation_value_type="discrete", - spec="https://drafts.fxtf.org/css-masking/#propdef-mask-composite")} +${helpers.single_keyword( + "mask-composite", + "add subtract intersect exclude", + vector=True, + products="gecko", + extra_prefixes="webkit", + animation_value_type="discrete", + spec="https://drafts.fxtf.org/css-masking/#propdef-mask-composite", +)} -${helpers.predefined_type("mask-image", "ImageLayer", - initial_value="Either::First(None_)", +${helpers.predefined_type( + "mask-image", + "ImageLayer", + "Either::First(None_)", initial_specified_value="Either::First(None_)", spec="https://drafts.fxtf.org/css-masking/#propdef-mask-image", vector=True, products="gecko", extra_prefixes="webkit", animation_value_type="discrete", - flags="CREATES_STACKING_CONTEXT")} + flags="CREATES_STACKING_CONTEXT", +)} diff --git a/components/style/properties/longhands/table.mako.rs b/components/style/properties/longhands/table.mako.rs index 2af39e1d6e3..8a371f269a6 100644 --- a/components/style/properties/longhands/table.mako.rs +++ b/components/style/properties/longhands/table.mako.rs @@ -6,15 +6,21 @@ <% data.new_style_struct("Table", inherited=False) %> -${helpers.single_keyword("table-layout", "auto fixed", - gecko_ffi_name="mLayoutStrategy", animation_value_type="discrete", - spec="https://drafts.csswg.org/css-tables/#propdef-table-layout", - servo_restyle_damage = "reflow")} +${helpers.single_keyword( + "table-layout", + "auto fixed", + gecko_ffi_name="mLayoutStrategy", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-tables/#propdef-table-layout", + servo_restyle_damage="reflow", +)} -${helpers.predefined_type("-x-span", - "XSpan", - "computed::XSpan(1)", - products="gecko", - spec="Internal-only (for `<col span>` pres attr)", - animation_value_type="none", - enabled_in="")} +${helpers.predefined_type( + "-x-span", + "XSpan", + "computed::XSpan(1)", + products="gecko", + spec="Internal-only (for `<col span>` pres attr)", + animation_value_type="none", + enabled_in="", +)} diff --git a/components/style/properties/longhands/text.mako.rs b/components/style/properties/longhands/text.mako.rs index 613ed6c5f67..715019f9c08 100644 --- a/components/style/properties/longhands/text.mako.rs +++ b/components/style/properties/longhands/text.mako.rs @@ -5,43 +5,55 @@ <%namespace name="helpers" file="/helpers.mako.rs" /> <% from data import Method %> -<% data.new_style_struct("Text", - inherited=False, - gecko_name="TextReset", - additional_methods=[Method("has_underline", "bool"), - Method("has_overline", "bool"), - Method("has_line_through", "bool")]) %> +<% data.new_style_struct( + "Text", + inherited=False, + gecko_name="TextReset", + additional_methods=[ + Method("has_underline", "bool"), + Method("has_overline", "bool"), + Method("has_line_through", "bool"), + ] +) %> -${helpers.predefined_type("text-overflow", - "TextOverflow", - "computed::TextOverflow::get_initial_value()", - animation_value_type="discrete", - boxed=True, - flags="APPLIES_TO_PLACEHOLDER", - spec="https://drafts.csswg.org/css-ui/#propdef-text-overflow", - servo_restyle_damage="rebuild_and_reflow")} +${helpers.predefined_type( + "text-overflow", + "TextOverflow", + "computed::TextOverflow::get_initial_value()", + animation_value_type="discrete", + boxed=True, + flags="APPLIES_TO_PLACEHOLDER", + spec="https://drafts.csswg.org/css-ui/#propdef-text-overflow", + servo_restyle_damage="rebuild_and_reflow", +)} -${helpers.single_keyword("unicode-bidi", - "normal embed isolate bidi-override isolate-override plaintext", - animation_value_type="discrete", - spec="https://drafts.csswg.org/css-writing-modes/#propdef-unicode-bidi", - servo_restyle_damage="rebuild_and_reflow")} +${helpers.single_keyword( + "unicode-bidi", + "normal embed isolate bidi-override isolate-override plaintext", + animation_value_type="none", + spec="https://drafts.csswg.org/css-writing-modes/#propdef-unicode-bidi", + servo_restyle_damage="rebuild_and_reflow", +)} -${helpers.predefined_type("text-decoration-line", - "TextDecorationLine", - "specified::TextDecorationLine::none()", - initial_specified_value="specified::TextDecorationLine::none()", - animation_value_type="discrete", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", - spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-line", - servo_restyle_damage="rebuild_and_reflow")} +${helpers.predefined_type( + "text-decoration-line", + "TextDecorationLine", + "specified::TextDecorationLine::none()", + initial_specified_value="specified::TextDecorationLine::none()", + animation_value_type="discrete", + flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-line", + servo_restyle_damage="rebuild_and_reflow", +)} -${helpers.single_keyword("text-decoration-style", - "solid double dotted dashed wavy -moz-none", - products="gecko", - animation_value_type="discrete", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", - spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-style")} +${helpers.single_keyword( + "text-decoration-style", + "solid double dotted dashed wavy -moz-none", + products="gecko", + animation_value_type="discrete", + flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-style", +)} ${helpers.predefined_type( "text-decoration-color", @@ -64,4 +76,5 @@ ${helpers.predefined_type( products="gecko", flags="APPLIES_TO_FIRST_LETTER", gecko_pref="layout.css.initial-letter.enabled", - spec="https://drafts.csswg.org/css-inline/#sizing-drop-initials")} + spec="https://drafts.csswg.org/css-inline/#sizing-drop-initials", +)} diff --git a/components/style/properties/longhands/ui.mako.rs b/components/style/properties/longhands/ui.mako.rs index 419024862d4..b8a188d896b 100644 --- a/components/style/properties/longhands/ui.mako.rs +++ b/components/style/properties/longhands/ui.mako.rs @@ -11,10 +11,14 @@ // TODO spec says that UAs should not support this // we should probably remove from gecko (https://bugzilla.mozilla.org/show_bug.cgi?id=1328331) -${helpers.single_keyword("ime-mode", "auto normal active disabled inactive", - products="gecko", gecko_ffi_name="mIMEMode", - animation_value_type="discrete", - spec="https://drafts.csswg.org/css-ui/#input-method-editor")} +${helpers.single_keyword( + "ime-mode", + "auto normal active disabled inactive", + products="gecko", + gecko_ffi_name="mIMEMode", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-ui/#input-method-editor", +)} ${helpers.single_keyword( "scrollbar-width", @@ -27,30 +31,40 @@ ${helpers.single_keyword( spec="https://drafts.csswg.org/css-scrollbars-1/#scrollbar-width" )} -${helpers.single_keyword("-moz-user-select", "auto text none all element elements" + - " toggle tri-state -moz-all -moz-text", - products="gecko", - alias="-webkit-user-select", - gecko_ffi_name="mUserSelect", - gecko_enum_prefix="StyleUserSelect", - gecko_strip_moz_prefix=False, - aliases="-moz-none=none", - animation_value_type="discrete", - spec="https://drafts.csswg.org/css-ui-4/#propdef-user-select")} +${helpers.single_keyword( + "-moz-user-select", + "auto text none all element elements toggle tri-state -moz-all -moz-text", + products="gecko", + alias="-webkit-user-select", + gecko_ffi_name="mUserSelect", + gecko_enum_prefix="StyleUserSelect", + gecko_strip_moz_prefix=False, + aliases="-moz-none=none", + animation_value_type="discrete", + spec="https://drafts.csswg.org/css-ui-4/#propdef-user-select", +)} // TODO(emilio): This probably should be hidden from content. -${helpers.single_keyword("-moz-window-dragging", "default drag no-drag", products="gecko", - gecko_ffi_name="mWindowDragging", - gecko_enum_prefix="StyleWindowDragging", - animation_value_type="discrete", - spec="None (Nonstandard Firefox-only property)")} +${helpers.single_keyword( + "-moz-window-dragging", + "default drag no-drag", + products="gecko", + gecko_ffi_name="mWindowDragging", + gecko_enum_prefix="StyleWindowDragging", + animation_value_type="discrete", + spec="None (Nonstandard Firefox-only property)", +)} -${helpers.single_keyword("-moz-window-shadow", "none default menu tooltip sheet", products="gecko", - gecko_ffi_name="mWindowShadow", - gecko_constant_prefix="NS_STYLE_WINDOW_SHADOW", - animation_value_type="discrete", - enabled_in="chrome", - spec="None (Nonstandard internal property)")} +${helpers.single_keyword( + "-moz-window-shadow", + "none default menu tooltip sheet", + products="gecko", + gecko_ffi_name="mWindowShadow", + gecko_constant_prefix="NS_STYLE_WINDOW_SHADOW", + animation_value_type="discrete", + enabled_in="chrome", + spec="None (Nonstandard internal property)", +)} ${helpers.predefined_type( "-moz-window-opacity", @@ -89,9 +103,11 @@ ${helpers.predefined_type( )} // TODO(emilio): Probably also should be hidden from content. -${helpers.predefined_type("-moz-force-broken-image-icon", - "MozForceBrokenImageIcon", - "computed::MozForceBrokenImageIcon::false_value()", - animation_value_type="discrete", - products="gecko", - spec="None (Nonstandard Firefox-only property)")} +${helpers.predefined_type( + "-moz-force-broken-image-icon", + "MozForceBrokenImageIcon", + "computed::MozForceBrokenImageIcon::false_value()", + animation_value_type="discrete", + products="gecko", + spec="None (Nonstandard Firefox-only property)", +)} diff --git a/components/style/properties/longhands/xul.mako.rs b/components/style/properties/longhands/xul.mako.rs index 15b8a695411..5089bbf985b 100644 --- a/components/style/properties/longhands/xul.mako.rs +++ b/components/style/properties/longhands/xul.mako.rs @@ -8,51 +8,79 @@ // Non-standard properties that Gecko uses for XUL elements. <% data.new_style_struct("XUL", inherited=False) %> -${helpers.single_keyword("-moz-box-align", "stretch start center baseline end", - products="gecko", gecko_ffi_name="mBoxAlign", - gecko_enum_prefix="StyleBoxAlign", - animation_value_type="discrete", - alias="-webkit-box-align", - spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/box-align)")} - -${helpers.single_keyword("-moz-box-direction", "normal reverse", - products="gecko", gecko_ffi_name="mBoxDirection", - gecko_enum_prefix="StyleBoxDirection", - animation_value_type="discrete", - alias="-webkit-box-direction", - spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/box-direction)")} - -${helpers.predefined_type("-moz-box-flex", "NonNegativeNumber", "From::from(0.)", - products="gecko", gecko_ffi_name="mBoxFlex", - animation_value_type="NonNegativeNumber", - alias="-webkit-box-flex", - spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/box-flex)")} - -${helpers.single_keyword("-moz-box-orient", "horizontal vertical", - products="gecko", gecko_ffi_name="mBoxOrient", - extra_gecko_aliases="inline-axis=horizontal block-axis=vertical", - gecko_enum_prefix="StyleBoxOrient", - animation_value_type="discrete", - alias="-webkit-box-orient", - spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/box-orient)")} - -${helpers.single_keyword("-moz-box-pack", "start center end justify", - products="gecko", gecko_ffi_name="mBoxPack", - gecko_enum_prefix="StyleBoxPack", - animation_value_type="discrete", - alias="-webkit-box-pack", - spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/box-pack)")} - -${helpers.single_keyword("-moz-stack-sizing", "stretch-to-fit ignore ignore-horizontal ignore-vertical", - products="gecko", gecko_ffi_name="mStackSizing", - gecko_enum_prefix="StyleStackSizing", - animation_value_type="discrete", - spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-stack-sizing)")} - -${helpers.predefined_type("-moz-box-ordinal-group", "Integer", "0", - parse_method="parse_non_negative", - products="gecko", - alias="-webkit-box-ordinal-group", - gecko_ffi_name="mBoxOrdinal", - animation_value_type="discrete", - spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-box-ordinal-group)")} +${helpers.single_keyword( + "-moz-box-align", + "stretch start center baseline end", + products="gecko", + gecko_ffi_name="mBoxAlign", + gecko_enum_prefix="StyleBoxAlign", + animation_value_type="discrete", + alias="-webkit-box-align", + spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/box-align)", +)} + +${helpers.single_keyword( + "-moz-box-direction", + "normal reverse", + products="gecko", + gecko_ffi_name="mBoxDirection", + gecko_enum_prefix="StyleBoxDirection", + animation_value_type="discrete", + alias="-webkit-box-direction", + spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/box-direction)", +)} + +${helpers.predefined_type( + "-moz-box-flex", + "NonNegativeNumber", + "From::from(0.)", + products="gecko", + gecko_ffi_name="mBoxFlex", + animation_value_type="NonNegativeNumber", + alias="-webkit-box-flex", + spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/box-flex)", +)} + +${helpers.single_keyword( + "-moz-box-orient", + "horizontal vertical", + products="gecko", + gecko_ffi_name="mBoxOrient", + extra_gecko_aliases="inline-axis=horizontal block-axis=vertical", + gecko_enum_prefix="StyleBoxOrient", + animation_value_type="discrete", + alias="-webkit-box-orient", + spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/box-orient)", +)} + +${helpers.single_keyword( + "-moz-box-pack", + "start center end justify", + products="gecko", gecko_ffi_name="mBoxPack", + gecko_enum_prefix="StyleBoxPack", + animation_value_type="discrete", + alias="-webkit-box-pack", + spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/box-pack)", +)} + +${helpers.single_keyword( + "-moz-stack-sizing", + "stretch-to-fit ignore ignore-horizontal ignore-vertical", + products="gecko", + gecko_ffi_name="mStackSizing", + gecko_enum_prefix="StyleStackSizing", + animation_value_type="discrete", + spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-stack-sizing)", +)} + +${helpers.predefined_type( + "-moz-box-ordinal-group", + "Integer", + "0", + parse_method="parse_non_negative", + products="gecko", + alias="-webkit-box-ordinal-group", + gecko_ffi_name="mBoxOrdinal", + animation_value_type="discrete", + spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-box-ordinal-group)", +)} diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 64e99ba205d..681e9556653 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -425,6 +425,10 @@ pub mod animated_properties { #[derive(Clone, Copy, Debug)] pub struct NonCustomPropertyId(usize); +/// The length of all the non-custom properties. +pub const NON_CUSTOM_PROPERTY_ID_COUNT: usize = + ${len(data.longhands) + len(data.shorthands) + len(data.all_aliases())}; + % if product == "gecko": #[allow(dead_code)] unsafe fn static_assert_nscsspropertyid() { @@ -435,6 +439,11 @@ unsafe fn static_assert_nscsspropertyid() { % endif impl NonCustomPropertyId { + /// Returns the underlying index, used for use counter. + pub fn bit(self) -> usize { + self.0 + } + #[cfg(feature = "gecko")] #[inline] fn to_nscsspropertyid(self) -> nsCSSPropertyID { @@ -450,7 +459,7 @@ impl NonCustomPropertyId { if prop < 0 { return Err(()); } - if prop >= ${len(data.longhands) + len(data.shorthands) + len(data.all_aliases())} { + if prop >= NON_CUSTOM_PROPERTY_ID_COUNT as i32 { return Err(()); } // unsafe: guaranteed by static_assert_nscsspropertyid above. @@ -460,7 +469,7 @@ impl NonCustomPropertyId { /// Get the property name. #[inline] pub fn name(self) -> &'static str { - static MAP: [&'static str; ${len(data.longhands) + len(data.shorthands) + len(data.all_aliases())}] = [ + static MAP: [&'static str; NON_CUSTOM_PROPERTY_ID_COUNT] = [ % for property in data.longhands + data.shorthands + data.all_aliases(): "${property.name}", % endfor @@ -635,7 +644,7 @@ impl NonCustomPropertyId { PropertyId::Shorthand(transmute((self.0 - ${len(data.longhands)}) as u16)) } } - assert!(self.0 < ${len(data.longhands) + len(data.shorthands) + len(data.all_aliases())}); + assert!(self.0 < NON_CUSTOM_PROPERTY_ID_COUNT); let alias_id: AliasId = unsafe { transmute((self.0 - ${len(data.longhands) + len(data.shorthands)}) as u16) }; @@ -671,7 +680,7 @@ impl From<AliasId> for NonCustomPropertyId { /// A set of all properties #[derive(Clone, PartialEq)] pub struct NonCustomPropertyIdSet { - storage: [u32; (${len(data.longhands) + len(data.shorthands) + len(data.all_aliases())} - 1 + 32) / 32] + storage: [u32; (NON_CUSTOM_PROPERTY_ID_COUNT - 1 + 32) / 32] } impl NonCustomPropertyIdSet { @@ -1554,6 +1563,7 @@ impl UnparsedValue { ParsingMode::DEFAULT, quirks_mode, None, + None, ); let mut input = ParserInput::new(&css); @@ -1853,7 +1863,8 @@ impl PropertyId { } } - fn non_custom_id(&self) -> Option<NonCustomPropertyId> { + /// Returns the `NonCustomPropertyId` corresponding to this property id. + pub fn non_custom_id(&self) -> Option<NonCustomPropertyId> { Some(match *self { PropertyId::Custom(_) => return None, PropertyId::Shorthand(shorthand_id) => shorthand_id.into(), @@ -2198,7 +2209,7 @@ impl PropertyDeclaration { // FIXME: fully implement https://github.com/w3c/csswg-drafts/issues/774 // before adding skip_whitespace here. // This probably affects some test results. - let value = match input.try(|i| CSSWideKeyword::parse(i)) { + let value = match input.try(CSSWideKeyword::parse) { Ok(keyword) => DeclaredValueOwned::CSSWideKeyword(keyword), Err(()) => match ::custom_properties::SpecifiedValue::parse(input) { Ok(value) => DeclaredValueOwned::Value(value), @@ -2212,12 +2223,12 @@ impl PropertyDeclaration { name: property_name, value, })); - Ok(()) + return Ok(()); } PropertyId::LonghandAlias(id, _) | PropertyId::Longhand(id) => { input.skip_whitespace(); // Unnecessary for correctness, but may help try() rewind less. - input.try(|i| CSSWideKeyword::parse(i)).map(|keyword| { + input.try(CSSWideKeyword::parse).map(|keyword| { PropertyDeclaration::CSSWideKeyword( WideKeywordDeclaration { id, keyword }, ) @@ -2253,12 +2264,12 @@ impl PropertyDeclaration { }) }).map(|declaration| { declarations.push(declaration) - }) + })?; } PropertyId::ShorthandAlias(id, _) | PropertyId::Shorthand(id) => { input.skip_whitespace(); // Unnecessary for correctness, but may help try() rewind less. - if let Ok(keyword) = input.try(|i| CSSWideKeyword::parse(i)) { + if let Ok(keyword) = input.try(CSSWideKeyword::parse) { if id == ShorthandId::All { declarations.all_shorthand = AllShorthand::CSSWideKeyword(keyword) } else { @@ -2271,51 +2282,55 @@ impl PropertyDeclaration { )) } } - Ok(()) } else { input.look_for_var_functions(); // Not using parse_entirely here: each ${shorthand.ident}::parse_into function // needs to do so *before* pushing to `declarations`. id.parse_into(declarations, context, input).or_else(|err| { while let Ok(_) = input.next() {} // Look for var() after the error. - if input.seen_var_functions() { - input.reset(&start); - let (first_token_type, css) = - ::custom_properties::parse_non_custom_with_var(input).map_err(|e| { - StyleParseErrorKind::new_invalid( - non_custom_id.unwrap().name(), - e, - ) - })?; - let unparsed = Arc::new(UnparsedValue { - css: css.into_owned(), - first_token_type: first_token_type, - url_data: context.url_data.clone(), - from_shorthand: Some(id), - }); - if id == ShorthandId::All { - declarations.all_shorthand = AllShorthand::WithVariables(unparsed) - } else { - for id in id.longhands() { - declarations.push( - PropertyDeclaration::WithVariables(VariableDeclaration { - id, - value: unparsed.clone(), - }) - ) - } - } - Ok(()) - } else { - Err(StyleParseErrorKind::new_invalid( + if !input.seen_var_functions() { + return Err(StyleParseErrorKind::new_invalid( non_custom_id.unwrap().name(), err, - )) + )); } - }) + + input.reset(&start); + let (first_token_type, css) = + ::custom_properties::parse_non_custom_with_var(input).map_err(|e| { + StyleParseErrorKind::new_invalid( + non_custom_id.unwrap().name(), + e, + ) + })?; + let unparsed = Arc::new(UnparsedValue { + css: css.into_owned(), + first_token_type: first_token_type, + url_data: context.url_data.clone(), + from_shorthand: Some(id), + }); + if id == ShorthandId::All { + declarations.all_shorthand = AllShorthand::WithVariables(unparsed) + } else { + for id in id.longhands() { + declarations.push( + PropertyDeclaration::WithVariables(VariableDeclaration { + id, + value: unparsed.clone(), + }) + ) + } + } + Ok(()) + })?; } } } + debug_assert!(non_custom_id.is_some(), "Custom properties should've returned earlier"); + if let Some(use_counters) = context.use_counters { + use_counters.non_custom_properties.record(non_custom_id.unwrap()); + } + Ok(()) } } diff --git a/components/style/rule_tree/mod.rs b/components/style/rule_tree/mod.rs index 5414b254aae..d4fb0d00925 100644 --- a/components/style/rule_tree/mod.rs +++ b/components/style/rule_tree/mod.rs @@ -488,7 +488,8 @@ impl RuleTree { return path.clone(); } - let iter = path.self_and_ancestors() + let iter = path + .self_and_ancestors() .take_while(|node| node.cascade_level() >= CascadeLevel::SMILOverride); let mut last = path; let mut children = SmallVec::<[_; 10]>::new(); @@ -1452,7 +1453,8 @@ impl StrongRuleNode { // transitions and animations are present for a given element and // property, transitions are suppressed so that they don't actually // override animations. - let iter = self.self_and_ancestors() + let iter = self + .self_and_ancestors() .skip_while(|node| node.cascade_level() == CascadeLevel::Transitions) .take_while(|node| node.cascade_level() > CascadeLevel::Animations); let mut result = (LonghandIdSet::new(), false); diff --git a/components/style/selector_map.rs b/components/style/selector_map.rs index 3ab78ce2d87..1e35f748917 100644 --- a/components/style/selector_map.rs +++ b/components/style/selector_map.rs @@ -287,7 +287,9 @@ impl SelectorMap<Rule> { context, flags_setter, ) { - matching_rules.push(rule.to_applicable_declaration_block(cascade_level, shadow_cascade_order)); + matching_rules.push( + rule.to_applicable_declaration_block(cascade_level, shadow_cascade_order), + ); } } } @@ -305,10 +307,12 @@ impl<T: SelectorMapEntry> SelectorMap<T> { let vector = match find_bucket(entry.selector()) { Bucket::Root => &mut self.root, - Bucket::ID(id) => self.id_hash + Bucket::ID(id) => self + .id_hash .try_entry(id.clone(), quirks_mode)? .or_insert_with(SmallVec::new), - Bucket::Class(class) => self.class_hash + Bucket::Class(class) => self + .class_hash .try_entry(class.clone(), quirks_mode)? .or_insert_with(SmallVec::new), Bucket::LocalName { name, lower_name } => { @@ -333,7 +337,8 @@ impl<T: SelectorMapEntry> SelectorMap<T> { .try_entry(name.clone())? .or_insert_with(SmallVec::new) }, - Bucket::Namespace(url) => self.namespace_hash + Bucket::Namespace(url) => self + .namespace_hash .try_entry(url.clone())? .or_insert_with(SmallVec::new), Bucket::Universal => &mut self.other, @@ -490,8 +495,9 @@ fn specific_bucket_for<'a>(component: &'a Component<SelectorImpl>) -> Bucket<'a> name: &selector.name, lower_name: &selector.lower_name, }, - Component::Namespace(_, ref url) | - Component::DefaultNamespace(ref url) => Bucket::Namespace(url), + Component::Namespace(_, ref url) | Component::DefaultNamespace(ref url) => { + Bucket::Namespace(url) + }, // ::slotted(..) isn't a normal pseudo-element, so we can insert it on // the rule hash normally without much problem. For example, in a // selector like: @@ -534,7 +540,7 @@ fn find_bucket<'a>(mut iter: SelectorIter<'a, SelectorImpl>) -> Bucket<'a> { Bucket::Root => return new_bucket, Bucket::ID(..) => { current_bucket = new_bucket; - } + }, Bucket::Class(..) => { if !matches!(current_bucket, Bucket::ID(..)) { current_bucket = new_bucket; @@ -549,7 +555,7 @@ fn find_bucket<'a>(mut iter: SelectorIter<'a, SelectorImpl>) -> Bucket<'a> { if matches!(current_bucket, Bucket::Universal) { current_bucket = new_bucket; } - } + }, Bucket::Universal => {}, } } diff --git a/components/style/selector_parser.rs b/components/style/selector_parser.rs index 7250502b1ad..5d6ddbb0e3f 100644 --- a/components/style/selector_parser.rs +++ b/components/style/selector_parser.rs @@ -6,11 +6,14 @@ #![deny(missing_docs)] +use Atom; use cssparser::{Parser as CssParser, ParserInput}; +use element_state::ElementState; use selectors::parser::SelectorList; use std::fmt::{self, Debug, Write}; use style_traits::{CssWriter, ParseError, ToCss}; use stylesheets::{Namespaces, Origin, UrlExtraData}; +use values::serialize_atom_identifier; /// A convenient alias for the type that represents an attribute value used for /// selector parser implementation. @@ -172,27 +175,49 @@ impl<T> PerPseudoElementMap<T> { } /// Values for the :dir() pseudo class +/// +/// "ltr" and "rtl" values are normalized to lowercase. #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)] -pub enum Direction { - /// left-to-right semantic directionality +pub struct Direction(pub Atom); + +/// Horizontal values for the :dir() pseudo class +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum HorizontalDirection { + /// :dir(ltr) Ltr, - /// right-to-left semantic directionality + /// :dir(rtl) Rtl, - /// Some other provided directionality value - /// - /// TODO(emilio): If we atomize we can then unbox in NonTSPseudoClass. - Other(Box<str>), } impl Direction { /// Parse a direction value. pub fn parse<'i, 't>(parser: &mut CssParser<'i, 't>) -> Result<Self, ParseError<'i>> { let ident = parser.expect_ident()?; - Ok(match_ignore_ascii_case! { &ident, - "rtl" => Direction::Rtl, - "ltr" => Direction::Ltr, - _ => Direction::Other(Box::from(ident.as_ref())), - }) + Ok(Direction(match_ignore_ascii_case! { &ident, + "rtl" => atom!("rtl"), + "ltr" => atom!("ltr"), + _ => Atom::from(ident.as_ref()), + })) + } + + /// Convert this Direction into a HorizontalDirection, if applicable + pub fn as_horizontal_direction(&self) -> Option<HorizontalDirection> { + if self.0 == atom!("ltr") { + Some(HorizontalDirection::Ltr) + } else if self.0 == atom!("rtl") { + Some(HorizontalDirection::Rtl) + } else { + None + } + } + + /// Gets the element state relevant to this :dir() selector. + pub fn element_state(&self) -> ElementState { + match self.as_horizontal_direction() { + Some(HorizontalDirection::Ltr) => ElementState::IN_LTR_STATE, + Some(HorizontalDirection::Rtl) => ElementState::IN_RTL_STATE, + None => ElementState::empty(), + } } } @@ -201,12 +226,6 @@ impl ToCss for Direction { where W: Write, { - let dir_str = match *self { - Direction::Rtl => "rtl", - Direction::Ltr => "ltr", - // FIXME: This should be escaped as an identifier; see #19231 - Direction::Other(ref other) => other, - }; - dest.write_str(dir_str) + serialize_atom_identifier(&self.0, dest) } } diff --git a/components/style/servo/restyle_damage.rs b/components/style/servo/restyle_damage.rs index 5cde20c9658..7b49a592751 100644 --- a/components/style/servo/restyle_damage.rs +++ b/components/style/servo/restyle_damage.rs @@ -80,9 +80,12 @@ impl ServoRestyleDamage { /// FIXME(bholley): Do we ever actually need this? Shouldn't /// RECONSTRUCT_FLOW imply everything else? pub fn rebuild_and_reflow() -> ServoRestyleDamage { - ServoRestyleDamage::REPAINT | ServoRestyleDamage::REPOSITION | - ServoRestyleDamage::STORE_OVERFLOW | ServoRestyleDamage::BUBBLE_ISIZES | - ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::REFLOW | + ServoRestyleDamage::REPAINT | + ServoRestyleDamage::REPOSITION | + ServoRestyleDamage::STORE_OVERFLOW | + ServoRestyleDamage::BUBBLE_ISIZES | + ServoRestyleDamage::REFLOW_OUT_OF_FLOW | + ServoRestyleDamage::REFLOW | ServoRestyleDamage::RECONSTRUCT_FLOW } @@ -95,12 +98,14 @@ impl ServoRestyleDamage { /// returns the damage that we should add to the *parent* of this flow. pub fn damage_for_parent(self, child_is_absolutely_positioned: bool) -> ServoRestyleDamage { if child_is_absolutely_positioned { - self & (ServoRestyleDamage::REPAINT | ServoRestyleDamage::REPOSITION | + self & (ServoRestyleDamage::REPAINT | + ServoRestyleDamage::REPOSITION | ServoRestyleDamage::STORE_OVERFLOW | ServoRestyleDamage::REFLOW_OUT_OF_FLOW | ServoRestyleDamage::RESOLVE_GENERATED_CONTENT) } else { - self & (ServoRestyleDamage::REPAINT | ServoRestyleDamage::REPOSITION | + self & (ServoRestyleDamage::REPAINT | + ServoRestyleDamage::REPOSITION | ServoRestyleDamage::STORE_OVERFLOW | ServoRestyleDamage::REFLOW | ServoRestyleDamage::REFLOW_OUT_OF_FLOW | @@ -136,7 +141,8 @@ impl ServoRestyleDamage { }, _ => { // TODO(pcwalton): Take floatedness into account. - self & (ServoRestyleDamage::REPAINT | ServoRestyleDamage::REPOSITION | + self & (ServoRestyleDamage::REPAINT | + ServoRestyleDamage::REPOSITION | ServoRestyleDamage::REFLOW) }, } @@ -205,22 +211,21 @@ fn compute_damage(old: &ComputedValues, new: &ComputedValues) -> ServoRestyleDam ServoRestyleDamage::REFLOW, ServoRestyleDamage::RECONSTRUCT_FLOW ] - ) || - (new.get_box().display == Display::Inline && - restyle_damage_rebuild_and_reflow_inline!( - old, - new, - damage, - [ - ServoRestyleDamage::REPAINT, - ServoRestyleDamage::REPOSITION, - ServoRestyleDamage::STORE_OVERFLOW, - ServoRestyleDamage::BUBBLE_ISIZES, - ServoRestyleDamage::REFLOW_OUT_OF_FLOW, - ServoRestyleDamage::REFLOW, - ServoRestyleDamage::RECONSTRUCT_FLOW - ] - )) || + ) || (new.get_box().display == Display::Inline && + restyle_damage_rebuild_and_reflow_inline!( + old, + new, + damage, + [ + ServoRestyleDamage::REPAINT, + ServoRestyleDamage::REPOSITION, + ServoRestyleDamage::STORE_OVERFLOW, + ServoRestyleDamage::BUBBLE_ISIZES, + ServoRestyleDamage::REFLOW_OUT_OF_FLOW, + ServoRestyleDamage::REFLOW, + ServoRestyleDamage::RECONSTRUCT_FLOW + ] + )) || restyle_damage_reflow!( old, new, @@ -244,7 +249,8 @@ fn compute_damage(old: &ComputedValues, new: &ComputedValues) -> ServoRestyleDam ServoRestyleDamage::STORE_OVERFLOW, ServoRestyleDamage::REFLOW_OUT_OF_FLOW ] - ) || restyle_damage_repaint!(old, new, damage, [ServoRestyleDamage::REPAINT]); + ) || + restyle_damage_repaint!(old, new, damage, [ServoRestyleDamage::REPAINT]); // Paint worklets may depend on custom properties, // so if they have changed we should repaint. diff --git a/components/style/servo/selector_parser.rs b/components/style/servo/selector_parser.rs index 2083539f51b..7c1e082022d 100644 --- a/components/style/servo/selector_parser.rs +++ b/components/style/servo/selector_parser.rs @@ -135,6 +135,12 @@ impl PseudoElement { self.is_before() || self.is_after() } + /// Whether this is an unknown ::-webkit- pseudo-element. + #[inline] + pub fn is_unknown_webkit_pseudo_element(&self) -> bool { + false + } + /// Whether this pseudo-element is the ::before pseudo. #[inline] pub fn is_before(&self) -> bool { @@ -284,8 +290,8 @@ impl PseudoElement { } } -/// The type used for storing pseudo-class string arguments. -pub type PseudoClassStringArg = Box<str>; +/// The type used for storing `:lang` arguments. +pub type Lang = Box<str>; /// A non tree-structural pseudo-class. /// See https://drafts.csswg.org/selectors-4/#structural-pseudos @@ -302,7 +308,7 @@ pub enum NonTSPseudoClass { Fullscreen, Hover, Indeterminate, - Lang(PseudoClassStringArg), + Lang(Lang), Link, PlaceholderShown, ReadWrite, @@ -762,7 +768,8 @@ impl ServoElementSnapshot { operation: &AttrSelectorOperation<&String>, ) -> bool { match *ns { - NamespaceConstraint::Specific(ref ns) => self.get_attr(ns, local_name) + NamespaceConstraint::Specific(ref ns) => self + .get_attr(ns, local_name) .map_or(false, |value| value.eval_selector(operation)), NamespaceConstraint::Any => { self.any_attr_ignore_ns(local_name, |value| value.eval_selector(operation)) diff --git a/components/style/sharing/mod.rs b/components/style/sharing/mod.rs index d6148d16b49..b3177216f64 100644 --- a/components/style/sharing/mod.rs +++ b/components/style/sharing/mod.rs @@ -197,8 +197,7 @@ impl ValidationData { let values = OpaqueComputedValues::from(parent.borrow_data().unwrap().styles.primary()); values - }) - .clone() + }).clone() } /// Computes the revalidation results if needed, and returns it. diff --git a/components/style/style_adjuster.rs b/components/style/style_adjuster.rs index 704c875a932..7c65798286e 100644 --- a/components/style/style_adjuster.rs +++ b/components/style/style_adjuster.rs @@ -64,10 +64,21 @@ where // FIXME(emilio): This should be an actual static. lazy_static! { static ref SPECIAL_HTML_ELEMENTS: [Atom; 16] = [ - atom!("br"), atom!("wbr"), atom!("meter"), atom!("progress"), - atom!("canvas"), atom!("embed"), atom!("object"), atom!("audio"), - atom!("iframe"), atom!("img"), atom!("video"), atom!("frame"), - atom!("frameset"), atom!("input"), atom!("textarea"), + atom!("br"), + atom!("wbr"), + atom!("meter"), + atom!("progress"), + atom!("canvas"), + atom!("embed"), + atom!("object"), + atom!("audio"), + atom!("iframe"), + atom!("img"), + atom!("video"), + atom!("frame"), + atom!("frameset"), + atom!("input"), + atom!("textarea"), atom!("select"), ]; } @@ -79,15 +90,21 @@ where // UA implements this either. lazy_static! { static ref SPECIAL_SVG_ELEMENTS: [Atom; 6] = [ - atom!("svg"), atom!("a"), atom!("g"), atom!("use"), - atom!("tspan"), atom!("textPath"), + atom!("svg"), + atom!("a"), + atom!("g"), + atom!("use"), + atom!("tspan"), + atom!("textPath"), ]; } // https://drafts.csswg.org/css-display/#unbox-html if element.is_html_element() { let local_name = element.local_name(); - return SPECIAL_HTML_ELEMENTS.iter().any(|name| &**name == local_name); + return SPECIAL_HTML_ELEMENTS + .iter() + .any(|name| &**name == local_name); } // https://drafts.csswg.org/css-display/#unbox-svg @@ -96,7 +113,9 @@ where return true; } let local_name = element.local_name(); - return !SPECIAL_SVG_ELEMENTS.iter().any(|name| &**name == local_name); + return !SPECIAL_SVG_ELEMENTS + .iter() + .any(|name| &**name == local_name); } // https://drafts.csswg.org/css-display/#unbox-mathml @@ -201,11 +220,11 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { pub fn set_bits(&mut self) { let display = self.style.get_box().clone_display(); - if !display.is_contents() && - !self.style - .get_text() - .clone_text_decoration_line() - .is_empty() + if !display.is_contents() && !self + .style + .get_text() + .clone_text_decoration_line() + .is_empty() { self.style .flags @@ -280,10 +299,10 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { #[cfg(feature = "gecko")] fn adjust_for_text_in_ruby(&mut self) { let parent_display = self.style.get_parent_box().clone_display(); - if parent_display.is_ruby_type() || - self.style - .get_parent_flags() - .contains(ComputedValueFlags::SHOULD_SUPPRESS_LINEBREAK) + if parent_display.is_ruby_type() || self + .style + .get_parent_flags() + .contains(ComputedValueFlags::SHOULD_SUPPRESS_LINEBREAK) { self.style .flags @@ -370,10 +389,12 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { /// The initial value of outline-width may be changed at computed value time. fn adjust_for_outline(&mut self) { - if self.style + if self + .style .get_outline() .clone_outline_style() - .none_or_hidden() && self.style.get_outline().outline_has_nonzero_width() + .none_or_hidden() && + self.style.get_outline().outline_has_nonzero_width() { self.style.mutate_outline().set_outline_width(Au(0).into()); } @@ -517,7 +538,9 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { let decorations_in_effect = TextDecorationsInEffect::from_style(&self.style); if self.style.get_inherited_text().text_decorations_in_effect != decorations_in_effect { - self.style.mutate_inherited_text().text_decorations_in_effect = decorations_in_effect; + self.style + .mutate_inherited_text() + .text_decorations_in_effect = decorations_in_effect; } } @@ -677,11 +700,8 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { /// When comparing to Gecko, this is similar to the work done by /// `ComputedStyle::ApplyStyleFixups`, plus some parts of /// `nsStyleSet::GetContext`. - pub fn adjust<E>( - &mut self, - layout_parent_style: &ComputedValues, - element: Option<E>, - ) where + pub fn adjust<E>(&mut self, layout_parent_style: &ComputedValues, element: Option<E>) + where E: TElement, { if cfg!(debug_assertions) { diff --git a/components/style/style_resolver.rs b/components/style/style_resolver.rs index b31beff7460..0899faa9ce7 100644 --- a/components/style/style_resolver.rs +++ b/components/style/style_resolver.rs @@ -190,8 +190,7 @@ where ) -> PrimaryStyle { // Before doing the cascade, check the sharing cache and see if we can // reuse the style via rule node identity. - let may_reuse = - !self.element.is_in_native_anonymous_subtree() && + let may_reuse = !self.element.is_in_native_anonymous_subtree() && parent_style.is_some() && inputs.rules.is_some(); @@ -485,7 +484,8 @@ where let stylist = &self.context.shared.stylist; - if !self.element + if !self + .element .may_generate_pseudo(pseudo_element, originating_element_style) { return None; diff --git a/components/style/stylesheet_set.rs b/components/style/stylesheet_set.rs index a3b6e5cdc17..19790aba957 100644 --- a/components/style/stylesheet_set.rs +++ b/components/style/stylesheet_set.rs @@ -324,7 +324,8 @@ where fn insert_before(&mut self, sheet: S, before_sheet: &S) { debug_assert!(!self.contains(&sheet)); - let index = self.entries + let index = self + .entries .iter() .position(|entry| entry.sheet == *before_sheet) .expect("`before_sheet` stylesheet not found"); diff --git a/components/style/stylesheets/document_rule.rs b/components/style/stylesheets/document_rule.rs index 56750ae7b66..9598763e438 100644 --- a/components/style/stylesheets/document_rule.rs +++ b/components/style/stylesheets/document_rule.rs @@ -109,7 +109,7 @@ pub enum DocumentMatchingFunction { Regexp(String), /// Matching function for a media document. #[css(function)] - MediaDocument(MediaDocumentKind) + MediaDocument(MediaDocumentKind), } macro_rules! parse_quoted_or_unquoted_string { @@ -120,8 +120,7 @@ macro_rules! parse_quoted_or_unquoted_string { .parse_entirely(|input| { let string = input.expect_string()?; Ok($url_matching_function(string.as_ref().to_owned())) - }) - .or_else(|_: ParseError| { + }).or_else(|_: ParseError| { while let Ok(_) = input.next() {} Ok($url_matching_function(input.slice_from(start).to_string())) }) @@ -136,7 +135,7 @@ impl DocumentMatchingFunction { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { if let Ok(url) = input.try(|input| CssUrl::parse(context, input)) { - return Ok(DocumentMatchingFunction::Url(url)) + return Ok(DocumentMatchingFunction::Url(url)); } let location = input.current_source_location(); @@ -181,7 +180,9 @@ impl DocumentMatchingFunction { DocumentMatchingFunction::UrlPrefix(_) => GeckoDocumentMatchingFunction::URLPrefix, DocumentMatchingFunction::Domain(_) => GeckoDocumentMatchingFunction::Domain, DocumentMatchingFunction::Regexp(_) => GeckoDocumentMatchingFunction::RegExp, - DocumentMatchingFunction::MediaDocument(_) => GeckoDocumentMatchingFunction::MediaDocument, + DocumentMatchingFunction::MediaDocument(_) => { + GeckoDocumentMatchingFunction::MediaDocument + }, }; let pattern = nsCStr::from(match *self { @@ -189,14 +190,12 @@ impl DocumentMatchingFunction { DocumentMatchingFunction::UrlPrefix(ref pat) | DocumentMatchingFunction::Domain(ref pat) | DocumentMatchingFunction::Regexp(ref pat) => pat, - DocumentMatchingFunction::MediaDocument(kind) => { - match kind { - MediaDocumentKind::All => "all", - MediaDocumentKind::Image => "image", - MediaDocumentKind::Plugin => "plugin", - MediaDocumentKind::Video => "video", - } - } + DocumentMatchingFunction::MediaDocument(kind) => match kind { + MediaDocumentKind::All => "all", + MediaDocumentKind::Image => "image", + MediaDocumentKind::Plugin => "plugin", + MediaDocumentKind::Video => "video", + }, }); unsafe { Gecko_DocumentRule_UseForPresentation(device.pres_context(), &*pattern, func) } } diff --git a/components/style/stylesheets/font_feature_values_rule.rs b/components/style/stylesheets/font_feature_values_rule.rs index c70a46c1c9d..76170151c67 100644 --- a/components/style/stylesheets/font_feature_values_rule.rs +++ b/components/style/stylesheets/font_feature_values_rule.rs @@ -70,7 +70,8 @@ impl Parse for SingleValue { match *input.next()? { Token::Number { int_value: Some(v), .. - } if v >= 0 => + } + if v >= 0 => { Ok(SingleValue(v as u32)) }, @@ -102,7 +103,8 @@ impl Parse for PairValues { let first = match *input.next()? { Token::Number { int_value: Some(a), .. - } if a >= 0 => + } + if a >= 0 => { a as u32 }, @@ -112,7 +114,8 @@ impl Parse for PairValues { match input.next() { Ok(&Token::Number { int_value: Some(b), .. - }) if b >= 0 => + }) + if b >= 0 => { Ok(PairValues(first, Some(b as u32))) }, @@ -154,7 +157,8 @@ impl Parse for VectorValues { match input.next() { Ok(&Token::Number { int_value: Some(a), .. - }) if a >= 0 => + }) + if a >= 0 => { vec.push(a as u32); } diff --git a/components/style/stylesheets/keyframes_rule.rs b/components/style/stylesheets/keyframes_rule.rs index 91bc14be5b5..50c61047e52 100644 --- a/components/style/stylesheets/keyframes_rule.rs +++ b/components/style/stylesheets/keyframes_rule.rs @@ -82,16 +82,14 @@ impl DeepCloneWithLock for KeyframesRule { ) -> Self { KeyframesRule { name: self.name.clone(), - keyframes: self.keyframes + keyframes: self + .keyframes .iter() .map(|x| { - Arc::new(lock.wrap(x.read_with(guard).deep_clone_with_lock( - lock, - guard, - params, - ))) - }) - .collect(), + Arc::new( + lock.wrap(x.read_with(guard).deep_clone_with_lock(lock, guard, params)), + ) + }).collect(), vendor_prefix: self.vendor_prefix.clone(), source_location: self.source_location.clone(), } @@ -142,7 +140,8 @@ impl KeyframePercentage { Token::Percentage { unit_value: percentage, .. - } if percentage >= 0. && percentage <= 1. => + } + if percentage >= 0. && percentage <= 1. => { Ok(KeyframePercentage::new(percentage)) }, @@ -219,6 +218,7 @@ impl Keyframe { ParsingMode::DEFAULT, parent_stylesheet_contents.quirks_mode, None, + None, ); context.namespaces = Some(&*namespaces); let mut input = ParserInput::new(css); @@ -260,8 +260,10 @@ pub enum KeyframesStepValue { /// A step formed by a declaration block specified by the CSS. Declarations { /// The declaration block per se. - #[cfg_attr(feature = "gecko", - ignore_malloc_size_of = "XXX: Primary ref, measure if DMD says it's worthwhile")] + #[cfg_attr( + feature = "gecko", + ignore_malloc_size_of = "XXX: Primary ref, measure if DMD says it's worthwhile" + )] #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")] block: Arc<Locked<PropertyDeclarationBlock>>, }, @@ -325,8 +327,7 @@ impl KeyframesStep { let (declaration, _) = guard .get(PropertyDeclarationId::Longhand( LonghandId::AnimationTimingFunction, - )) - .unwrap(); + )).unwrap(); match *declaration { PropertyDeclaration::AnimationTimingFunction(ref value) => { // Use the first value. @@ -499,7 +500,7 @@ pub fn parse_keyframe_list( declarations: &mut declarations, }, ).filter_map(Result::ok) - .collect() + .collect() } impl<'a, 'i> AtRuleParser<'i> for KeyframeListParser<'a> { @@ -524,7 +525,7 @@ impl<'a, 'i> QualifiedRuleParser<'i> for KeyframeListParser<'a> { let error = ContextualParseError::InvalidKeyframeRule( input.slice_from(start_position), e.clone(), - ); + ); self.context.log_css_error(location, error); e }) @@ -551,10 +552,7 @@ impl<'a, 'i> QualifiedRuleParser<'i> for KeyframeListParser<'a> { while let Some(declaration) = iter.next() { match declaration { Ok(()) => { - block.extend( - iter.parser.declarations.drain(), - Importance::Normal, - ); + block.extend(iter.parser.declarations.drain(), Importance::Normal); }, Err((error, slice)) => { iter.parser.declarations.clear(); @@ -598,9 +596,9 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for KeyframeDeclarationParser<'a, 'b> { ) -> Result<(), ParseError<'i>> { let id = match PropertyId::parse(&name, self.context) { Ok(id) => id, - Err(()) => return Err(input.new_custom_error( - StyleParseErrorKind::UnknownProperty(name) - )), + Err(()) => { + return Err(input.new_custom_error(StyleParseErrorKind::UnknownProperty(name))) + }, }; // TODO(emilio): Shouldn't this use parse_entirely? diff --git a/components/style/stylesheets/mod.rs b/components/style/stylesheets/mod.rs index e3641f3e515..5058ad94e80 100644 --- a/components/style/stylesheets/mod.rs +++ b/components/style/stylesheets/mod.rs @@ -63,7 +63,7 @@ pub type UrlExtraData = ::servo_url::ServoUrl; #[cfg(feature = "gecko")] #[derive(Clone, PartialEq)] pub struct UrlExtraData( - pub ::gecko_bindings::sugar::refptr::RefPtr<::gecko_bindings::structs::URLExtraData> + pub ::gecko_bindings::sugar::refptr::RefPtr<::gecko_bindings::structs::URLExtraData>, ); #[cfg(feature = "gecko")] @@ -102,11 +102,14 @@ impl fmt::Debug for UrlExtraData { } } - formatter.debug_struct("URLExtraData") + formatter + .debug_struct("URLExtraData") .field("is_chrome", &self.is_chrome()) .field("base", &DebugURI(self.0.mBaseURI.raw::<structs::nsIURI>())) - .field("referrer", &DebugURI(self.0.mReferrer.raw::<structs::nsIURI>())) - .finish() + .field( + "referrer", + &DebugURI(self.0.mReferrer.raw::<structs::nsIURI>()), + ).finish() } } @@ -264,6 +267,7 @@ impl CssRule { ParsingMode::DEFAULT, parent_stylesheet_contents.quirks_mode, None, + None, ); let mut input = ParserInput::new(css); @@ -284,9 +288,7 @@ impl CssRule { }; parse_one_rule(&mut input, &mut rule_parser) - .map_err(|_| { - rule_parser.dom_error.unwrap_or(RulesMutateError::Syntax) - }) + .map_err(|_| rule_parser.dom_error.unwrap_or(RulesMutateError::Syntax)) } } @@ -304,25 +306,22 @@ impl DeepCloneWithLock for CssRule { CssRule::Namespace(Arc::new(lock.wrap(rule.clone()))) }, CssRule::Import(ref arc) => { - let rule = arc.read_with(guard) + let rule = arc + .read_with(guard) .deep_clone_with_lock(lock, guard, params); CssRule::Import(Arc::new(lock.wrap(rule))) }, CssRule::Style(ref arc) => { let rule = arc.read_with(guard); - CssRule::Style(Arc::new(lock.wrap(rule.deep_clone_with_lock( - lock, - guard, - params, - )))) + CssRule::Style(Arc::new( + lock.wrap(rule.deep_clone_with_lock(lock, guard, params)), + )) }, CssRule::Media(ref arc) => { let rule = arc.read_with(guard); - CssRule::Media(Arc::new(lock.wrap(rule.deep_clone_with_lock( - lock, - guard, - params, - )))) + CssRule::Media(Arc::new( + lock.wrap(rule.deep_clone_with_lock(lock, guard, params)), + )) }, CssRule::FontFace(ref arc) => { let rule = arc.read_with(guard); @@ -342,35 +341,27 @@ impl DeepCloneWithLock for CssRule { }, CssRule::Keyframes(ref arc) => { let rule = arc.read_with(guard); - CssRule::Keyframes(Arc::new(lock.wrap(rule.deep_clone_with_lock( - lock, - guard, - params, - )))) + CssRule::Keyframes(Arc::new( + lock.wrap(rule.deep_clone_with_lock(lock, guard, params)), + )) }, CssRule::Supports(ref arc) => { let rule = arc.read_with(guard); - CssRule::Supports(Arc::new(lock.wrap(rule.deep_clone_with_lock( - lock, - guard, - params, - )))) + CssRule::Supports(Arc::new( + lock.wrap(rule.deep_clone_with_lock(lock, guard, params)), + )) }, CssRule::Page(ref arc) => { let rule = arc.read_with(guard); - CssRule::Page(Arc::new(lock.wrap(rule.deep_clone_with_lock( - lock, - guard, - params, - )))) + CssRule::Page(Arc::new( + lock.wrap(rule.deep_clone_with_lock(lock, guard, params)), + )) }, CssRule::Document(ref arc) => { let rule = arc.read_with(guard); - CssRule::Document(Arc::new(lock.wrap(rule.deep_clone_with_lock( - lock, - guard, - params, - )))) + CssRule::Document(Arc::new( + lock.wrap(rule.deep_clone_with_lock(lock, guard, params)), + )) }, } } diff --git a/components/style/stylesheets/rule_list.rs b/components/style/stylesheets/rule_list.rs index 35edc22b3da..cfbf62ea721 100644 --- a/components/style/stylesheets/rule_list.rs +++ b/components/style/stylesheets/rule_list.rs @@ -156,7 +156,11 @@ impl CssRulesHelpers for RawOffsetArc<Locked<CssRules>> { } else if index == 0 { State::Start } else { - rules.0.get(index - 1).map(CssRule::rule_state).unwrap_or(State::Body) + rules + .0 + .get(index - 1) + .map(CssRule::rule_state) + .unwrap_or(State::Body) }; let insert_rule_context = InsertRuleContext { diff --git a/components/style/stylesheets/rule_parser.rs b/components/style/stylesheets/rule_parser.rs index d2f9b691ad4..683378b9b96 100644 --- a/components/style/stylesheets/rule_parser.rs +++ b/components/style/stylesheets/rule_parser.rs @@ -110,8 +110,9 @@ impl<'b> TopLevelRuleParser<'b> { // If there's anything that isn't a namespace rule (or import rule, but // we checked that already at the beginning), reject with a // StateError. - if new_state == State::Namespaces && - ctx.rule_list[ctx.index..].iter().any(|r| !matches!(*r, CssRule::Namespace(..))) + if new_state == State::Namespaces && ctx.rule_list[ctx.index..] + .iter() + .any(|r| !matches!(*r, CssRule::Namespace(..))) { self.dom_error = Some(RulesMutateError::InvalidState); return false; @@ -227,7 +228,7 @@ impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> { } if !self.check_state(State::Body) { - return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) + return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } AtRuleParser::parse_prelude(&mut self.nested(), name, input) @@ -254,7 +255,8 @@ impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> { ) -> CssRule { match prelude { AtRuleNonBlockPrelude::Import(url, media) => { - let loader = self.loader + let loader = self + .loader .expect("Expected a stylesheet loader for @import"); let import_rule = loader.request_stylesheet( @@ -299,7 +301,7 @@ impl<'a, 'i> QualifiedRuleParser<'i> for TopLevelRuleParser<'a> { input: &mut Parser<'i, 't>, ) -> Result<Self::Prelude, ParseError<'i>> { if !self.check_state(State::Body) { - return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) + return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } QualifiedRuleParser::parse_prelude(&mut self.nested(), input) @@ -312,15 +314,12 @@ impl<'a, 'i> QualifiedRuleParser<'i> for TopLevelRuleParser<'a> { location: SourceLocation, input: &mut Parser<'i, 't>, ) -> Result<CssRule, ParseError<'i>> { - QualifiedRuleParser::parse_block( - &mut self.nested(), - prelude, - location, - input, - ).map(|result| { - self.state = State::Body; - result - }) + QualifiedRuleParser::parse_block(&mut self.nested(), prelude, location, input).map( + |result| { + self.state = State::Body; + result + }, + ) } } @@ -338,11 +337,7 @@ impl<'a, 'b> NestedRuleParser<'a, 'b> { input: &mut Parser, rule_type: CssRuleType, ) -> Arc<Locked<CssRules>> { - let context = ParserContext::new_with_rule_type( - self.context, - rule_type, - self.namespaces, - ); + let context = ParserContext::new_with_rule_type(self.context, rule_type, self.namespaces); let nested_parser = NestedRuleParser { stylesheet_origin: self.stylesheet_origin, @@ -478,12 +473,7 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> { ); Ok(CssRule::FontFeatureValues(Arc::new(self.shared_lock.wrap( - FontFeatureValuesRule::parse( - &context, - input, - family_names, - source_location, - ), + FontFeatureValuesRule::parse(&context, input, family_names, source_location), )))) }, AtRuleBlockPrelude::CounterStyle(name) => { @@ -493,16 +483,9 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> { self.namespaces, ); - Ok(CssRule::CounterStyle(Arc::new( - self.shared_lock.wrap( - parse_counter_style_body( - name, - &context, - input, - source_location, - )?.into(), - ), - ))) + Ok(CssRule::CounterStyle(Arc::new(self.shared_lock.wrap( + parse_counter_style_body(name, &context, input, source_location)?.into(), + )))) }, AtRuleBlockPrelude::Media(media_queries) => { Ok(CssRule::Media(Arc::new(self.shared_lock.wrap(MediaRule { @@ -535,9 +518,9 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> { self.namespaces, ); - Ok(CssRule::Viewport(Arc::new(self.shared_lock.wrap( - ViewportRule::parse(&context, input)?, - )))) + Ok(CssRule::Viewport(Arc::new( + self.shared_lock.wrap(ViewportRule::parse(&context, input)?), + ))) }, AtRuleBlockPrelude::Keyframes(name, vendor_prefix) => { let context = ParserContext::new_with_rule_type( @@ -549,11 +532,7 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> { Ok(CssRule::Keyframes(Arc::new(self.shared_lock.wrap( KeyframesRule { name, - keyframes: parse_keyframe_list( - &context, - input, - self.shared_lock, - ), + keyframes: parse_keyframe_list(&context, input, self.shared_lock), vendor_prefix, source_location, }, @@ -566,8 +545,7 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> { self.namespaces, ); - let declarations = - parse_property_declaration_list(&context, input); + let declarations = parse_property_declaration_list(&context, input); Ok(CssRule::Page(Arc::new(self.shared_lock.wrap(PageRule { block: Arc::new(self.shared_lock.wrap(declarations)), source_location, diff --git a/components/style/stylesheets/rules_iterator.rs b/components/style/stylesheets/rules_iterator.rs index b46e24c22c7..eac6d2084e2 100644 --- a/components/style/stylesheets/rules_iterator.rs +++ b/components/style/stylesheets/rules_iterator.rs @@ -100,10 +100,7 @@ where ) { continue; } - import_rule - .stylesheet - .rules(self.guard) - .iter() + import_rule.stylesheet.rules(self.guard).iter() }, CssRule::Document(ref doc_rule) => { let doc_rule = doc_rule.read_with(self.guard); diff --git a/components/style/stylesheets/stylesheet.rs b/components/style/stylesheets/stylesheet.rs index 02730f7090d..e1359cb3722 100644 --- a/components/style/stylesheets/stylesheet.rs +++ b/components/style/stylesheets/stylesheet.rs @@ -24,6 +24,7 @@ use stylesheets::loader::StylesheetLoader; use stylesheets::rule_parser::{State, TopLevelRuleParser}; use stylesheets::rules_iterator::{EffectiveRules, EffectiveRulesIterator}; use stylesheets::rules_iterator::{NestedRuleIterationCondition, RulesIterator}; +use use_counters::UseCounters; /// This structure holds the user-agent and user stylesheets. pub struct UserAgentStylesheets { @@ -78,6 +79,7 @@ impl StylesheetContents { error_reporter: Option<&ParseErrorReporter>, quirks_mode: QuirksMode, line_number_offset: u32, + use_counters: Option<&UseCounters>, ) -> Self { let namespaces = RwLock::new(Namespaces::default()); let (rules, source_map_url, source_url) = Stylesheet::parse_rules( @@ -90,6 +92,7 @@ impl StylesheetContents { error_reporter, quirks_mode, line_number_offset, + use_counters, ); Self { @@ -126,7 +129,8 @@ impl DeepCloneWithLock for StylesheetContents { params: &DeepCloneParams, ) -> Self { // Make a deep clone of the rules, using the new lock. - let rules = self.rules + let rules = self + .rules .read_with(guard) .deep_clone_with_lock(lock, guard, params); @@ -176,7 +180,7 @@ macro_rules! rule_filter { } /// A trait to represent a given stylesheet in a document. -pub trait StylesheetInDocument : ::std::fmt::Debug { +pub trait StylesheetInDocument: ::std::fmt::Debug { /// Get the stylesheet origin. fn origin(&self, guard: &SharedRwLockReadGuard) -> Origin; @@ -315,6 +319,8 @@ impl Stylesheet { line_number_offset: u32, ) { let namespaces = RwLock::new(Namespaces::default()); + + // FIXME: Consider adding use counters to Servo? let (rules, source_map_url, source_url) = Self::parse_rules( css, &url_data, @@ -325,6 +331,7 @@ impl Stylesheet { error_reporter, existing.contents.quirks_mode, line_number_offset, + /* use_counters = */ None, ); *existing.contents.url_data.write() = url_data; @@ -350,6 +357,7 @@ impl Stylesheet { error_reporter: Option<&ParseErrorReporter>, quirks_mode: QuirksMode, line_number_offset: u32, + use_counters: Option<&UseCounters>, ) -> (Vec<CssRule>, Option<String>, Option<String>) { let mut rules = Vec::new(); let mut input = ParserInput::new_with_line_number_offset(css, line_number_offset); @@ -362,6 +370,7 @@ impl Stylesheet { ParsingMode::DEFAULT, quirks_mode, error_reporter, + use_counters, ); let rule_parser = TopLevelRuleParser { @@ -391,10 +400,7 @@ impl Stylesheet { Err((error, slice)) => { let location = error.location; let error = ContextualParseError::InvalidRule(slice, error); - iter.parser.context.log_css_error( - location, - error, - ); + iter.parser.context.log_css_error(location, error); }, } } @@ -421,6 +427,7 @@ impl Stylesheet { quirks_mode: QuirksMode, line_number_offset: u32, ) -> Self { + // FIXME: Consider adding use counters to Servo? let contents = StylesheetContents::from_str( css, url_data, @@ -430,6 +437,7 @@ impl Stylesheet { error_reporter, quirks_mode, line_number_offset, + /* use_counters = */ None, ); Stylesheet { @@ -468,7 +476,8 @@ impl Clone for Stylesheet { // Make a deep clone of the media, using the new lock. let media = self.media.read_with(&guard).clone(); let media = Arc::new(lock.wrap(media)); - let contents = self.contents + let contents = self + .contents .deep_clone_with_lock(&lock, &guard, &DeepCloneParams); Stylesheet { diff --git a/components/style/stylesheets/supports_rule.rs b/components/style/stylesheets/supports_rule.rs index f8c3235f295..2851d8914dd 100644 --- a/components/style/stylesheets/supports_rule.rs +++ b/components/style/stylesheets/supports_rule.rs @@ -168,9 +168,7 @@ impl SupportsCondition { i.expect_string() .map(|s| s.to_string()) .map_err(CssParseError::<()>::from) - }).and_then(|s| { - CString::new(s).map_err(|_| location.new_custom_error(())) - }) + }).and_then(|s| CString::new(s).map_err(|_| location.new_custom_error(()))) }) { return Ok(SupportsCondition::MozBoolPref(name)); } @@ -315,24 +313,21 @@ impl Declaration { let mut input = ParserInput::new(&self.0); let mut input = Parser::new(&mut input); - input.parse_entirely(|input| -> Result<(), CssParseError<()>> { - let prop = input.expect_ident_cloned().unwrap(); - input.expect_colon().unwrap(); + input + .parse_entirely(|input| -> Result<(), CssParseError<()>> { + let prop = input.expect_ident_cloned().unwrap(); + input.expect_colon().unwrap(); - let id = PropertyId::parse(&prop, context) - .map_err(|_| input.new_custom_error(()))?; + let id = + PropertyId::parse(&prop, context).map_err(|_| input.new_custom_error(()))?; - let mut declarations = SourcePropertyDeclaration::new(); - input.parse_until_before(Delimiter::Bang, |input| { - PropertyDeclaration::parse_into( - &mut declarations, - id, - &context, - input, - ).map_err(|_| input.new_custom_error(())) - })?; - let _ = input.try(parse_important); - Ok(()) - }).is_ok() + let mut declarations = SourcePropertyDeclaration::new(); + input.parse_until_before(Delimiter::Bang, |input| { + PropertyDeclaration::parse_into(&mut declarations, id, &context, input) + .map_err(|_| input.new_custom_error(())) + })?; + let _ = input.try(parse_important); + Ok(()) + }).is_ok() } } diff --git a/components/style/stylesheets/viewport_rule.rs b/components/style/stylesheets/viewport_rule.rs index 1fc6a988c7c..16bffd14ab2 100644 --- a/components/style/stylesheets/viewport_rule.rs +++ b/components/style/stylesheets/viewport_rule.rs @@ -375,8 +375,7 @@ impl ViewportRule { Err((error, slice)) => { let location = error.location; let error = ContextualParseError::UnsupportedViewportDescriptorDeclaration( - slice, - error, + slice, error, ); context.log_css_error(location, error); }, @@ -760,9 +759,9 @@ impl MaybeNew for ViewportConstraints { Some(initial_viewport.$dimension.scale_by(value.0)) }, LengthOrPercentageOrAuto::Auto => None, - LengthOrPercentageOrAuto::Calc(ref calc) => calc.to_computed_value( - &context, - ).to_used_value(Some(initial_viewport.$dimension)), + LengthOrPercentageOrAuto::Calc(ref calc) => calc + .to_computed_value(&context) + .to_used_value(Some(initial_viewport.$dimension)), }, ViewportLength::ExtendToZoom => { // $extend_to will be 'None' if 'extend-to-zoom' is 'auto' diff --git a/components/style/stylist.rs b/components/style/stylist.rs index 1fbf493667f..c933897f858 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -24,11 +24,11 @@ use properties::{self, CascadeMode, ComputedValues}; use properties::{AnimationRules, PropertyDeclarationBlock}; use rule_cache::{RuleCache, RuleCacheConditions}; use rule_tree::{CascadeLevel, RuleTree, ShadowCascadeOrder, StrongRuleNode, StyleSource}; -use selector_map::{PrecomputedHashMap, SelectorMap, SelectorMapEntry}; +use selector_map::{PrecomputedHashMap, PrecomputedHashSet, SelectorMap, SelectorMapEntry}; use selector_parser::{PerPseudoElementMap, PseudoElement, SelectorImpl, SnapshotMap}; use selectors::NthIndexCache; use selectors::attr::{CaseSensitivity, NamespaceConstraint}; -use selectors::bloom::{BloomFilter, NonCountingBloomFilter}; +use selectors::bloom::BloomFilter; use selectors::matching::{matches_selector, ElementSelectorFlags, MatchingContext, MatchingMode}; use selectors::matching::VisitedHandlingMode; use selectors::parser::{AncestorHashes, Combinator, Component, Selector}; @@ -184,8 +184,10 @@ impl UserAgentCascadeData { #[derive(Default)] #[cfg_attr(feature = "servo", derive(MallocSizeOf))] struct DocumentCascadeData { - #[cfg_attr(feature = "servo", - ignore_malloc_size_of = "Arc, owned by UserAgentCascadeDataCache")] + #[cfg_attr( + feature = "servo", + ignore_malloc_size_of = "Arc, owned by UserAgentCascadeDataCache" + )] user_agent: Arc<UserAgentCascadeData>, user: CascadeData, author: CascadeData, @@ -350,7 +352,10 @@ pub struct Stylist { stylesheets: StylistStylesheetSet, /// If true, the quirks-mode stylesheet is applied. - #[cfg_attr(feature = "servo", ignore_malloc_size_of = "defined in selectors")] + #[cfg_attr( + feature = "servo", + ignore_malloc_size_of = "defined in selectors" + )] quirks_mode: QuirksMode, /// Selector maps for all of the style sheets in the stylist, after @@ -681,7 +686,8 @@ impl Stylist { extra_declarations: Option<Vec<ApplicableDeclarationBlock>>, ) -> StrongRuleNode { let mut decl; - let declarations = match self.cascade_data + let declarations = match self + .cascade_data .user_agent .precomputed_pseudo_element_decls .get(pseudo) @@ -852,7 +858,7 @@ impl Stylist { } else { None } - } + }, }; // Read the comment on `precomputed_values_for_pseudo` to see why it's @@ -1129,11 +1135,10 @@ impl Stylist { let rule_hash_target = element.rule_hash_target(); let matches_user_rules = rule_hash_target.matches_user_and_author_rules(); - let matches_author_rules = - matches_user_rules && self.author_styles_enabled == AuthorStylesEnabled::Yes; // Normal user-agent rules. - if let Some(map) = self.cascade_data + if let Some(map) = self + .cascade_data .user_agent .cascade_data .normal_rules(pseudo_element) @@ -1195,7 +1200,11 @@ impl Stylist { } } - let mut match_document_author_rules = matches_author_rules; + if self.author_styles_enabled == AuthorStylesEnabled::No { + return; + } + + let mut match_document_author_rules = matches_user_rules; let mut shadow_cascade_order = 0; // XBL / Shadow DOM rules, which are author rules too. @@ -1204,95 +1213,107 @@ impl Stylist { // particular, normally document rules override ::slotted() rules, but // for !important it should be the other way around. So probably we need // to add some sort of AuthorScoped cascade level or something. - if matches_author_rules { - if let Some(shadow) = rule_hash_target.shadow_root() { - if let Some(map) = shadow.style_data().host_rules(pseudo_element) { - context.with_shadow_host(Some(rule_hash_target), |context| { - map.get_all_matching_rules( - element, - rule_hash_target, - applicable_declarations, - context, - flags_setter, - CascadeLevel::InnerShadowNormal, - shadow_cascade_order, - ); - }); - shadow_cascade_order += 1; - } + if let Some(shadow) = rule_hash_target.shadow_root() { + if let Some(map) = shadow + .style_data() + .and_then(|data| data.host_rules(pseudo_element)) + { + context.with_shadow_host(Some(rule_hash_target), |context| { + map.get_all_matching_rules( + element, + rule_hash_target, + applicable_declarations, + context, + flags_setter, + CascadeLevel::InnerShadowNormal, + shadow_cascade_order, + ); + }); + shadow_cascade_order += 1; } + } - // Match slotted rules in reverse order, so that the outer slotted - // rules come before the inner rules (and thus have less priority). - let mut slots = SmallVec::<[_; 3]>::new(); - let mut current = rule_hash_target.assigned_slot(); - while let Some(slot) = current { - slots.push(slot); - current = slot.assigned_slot(); - } + // Match slotted rules in reverse order, so that the outer slotted + // rules come before the inner rules (and thus have less priority). + let mut slots = SmallVec::<[_; 3]>::new(); + let mut current = rule_hash_target.assigned_slot(); + while let Some(slot) = current { + slots.push(slot); + current = slot.assigned_slot(); + } - for slot in slots.iter().rev() { - let shadow = slot.containing_shadow().unwrap(); - let styles = shadow.style_data(); - if let Some(map) = styles.slotted_rules(pseudo_element) { - context.with_shadow_host(Some(shadow.host()), |context| { - map.get_all_matching_rules( - element, - rule_hash_target, - applicable_declarations, - context, - flags_setter, - CascadeLevel::InnerShadowNormal, - shadow_cascade_order, - ); - }); - shadow_cascade_order += 1; - } + for slot in slots.iter().rev() { + let shadow = slot.containing_shadow().unwrap(); + if let Some(map) = shadow + .style_data() + .and_then(|data| data.slotted_rules(pseudo_element)) + { + context.with_shadow_host(Some(shadow.host()), |context| { + map.get_all_matching_rules( + element, + rule_hash_target, + applicable_declarations, + context, + flags_setter, + CascadeLevel::InnerShadowNormal, + shadow_cascade_order, + ); + }); + shadow_cascade_order += 1; } + } - if let Some(containing_shadow) = rule_hash_target.containing_shadow() { - let cascade_data = containing_shadow.style_data(); - let host = containing_shadow.host(); - if let Some(map) = cascade_data.normal_rules(pseudo_element) { - context.with_shadow_host(Some(host), |context| { - map.get_all_matching_rules( - element, - rule_hash_target, - applicable_declarations, - context, - flags_setter, - CascadeLevel::SameTreeAuthorNormal, - shadow_cascade_order, - ); - }); - shadow_cascade_order += 1; - } + let mut current_containing_shadow = rule_hash_target.containing_shadow(); + while let Some(containing_shadow) = current_containing_shadow { + let cascade_data = containing_shadow.style_data(); + let host = containing_shadow.host(); + if let Some(map) = cascade_data.and_then(|data| data.normal_rules(pseudo_element)) { + context.with_shadow_host(Some(host), |context| { + map.get_all_matching_rules( + element, + rule_hash_target, + applicable_declarations, + context, + flags_setter, + CascadeLevel::SameTreeAuthorNormal, + shadow_cascade_order, + ); + }); + shadow_cascade_order += 1; + } - // NOTE(emilio): Hack so <svg:use> matches document rules as - // expected. - // - // This is not a problem for invalidation and that kind of stuff - // because they still don't match rules based on elements - // outside of the shadow tree, and because the <svg:use> subtree - // is immutable and recreated each time the source tree changes. - // - // See: https://github.com/w3c/svgwg/issues/504 - // - // Note that we always resolve URLs against the document, so we - // can't get into a nested shadow situation here. - // - // See: https://github.com/w3c/svgwg/issues/505 - // - let host_is_svg_use = - host.is_svg_element() && - host.local_name() == &*local_name!("use"); + let host_is_svg_use_element = + host.is_svg_element() && host.local_name() == &*local_name!("use"); - match_document_author_rules = host_is_svg_use; + if !host_is_svg_use_element { + match_document_author_rules = false; + break; } + + debug_assert!( + cascade_data.is_none(), + "We allow no stylesheets in <svg:use> subtrees" + ); + + // NOTE(emilio): Hack so <svg:use> matches the rules of the + // enclosing tree. + // + // This is not a problem for invalidation and that kind of stuff + // because they still don't match rules based on elements + // outside of the shadow tree, and because the <svg:use> + // subtrees are immutable and recreated each time the source + // tree changes. + // + // We historically allow cross-document <svg:use> to have these + // rules applied, but I think that's not great. Gecko is the + // only engine supporting that. + // + // See https://github.com/w3c/svgwg/issues/504 for the relevant + // spec discussion. + current_containing_shadow = host.containing_shadow(); + match_document_author_rules = current_containing_shadow.is_none(); } - // FIXME(emilio): This doesn't account for the author_styles_enabled - // stuff... let cut_xbl_binding_inheritance = element.each_xbl_cascade_data(|cascade_data, quirks_mode| { if let Some(map) = cascade_data.normal_rules(pseudo_element) { @@ -1392,17 +1413,12 @@ impl Stylist { CaseSensitivity::CaseSensitive => {}, } - let hash = id.get_hash(); - self.any_applicable_rule_data(element, |data| data.mapped_ids.might_contain_hash(hash)) + self.any_applicable_rule_data(element, |data| data.mapped_ids.contains(id)) } /// Returns the registered `@keyframes` animation for the specified name. #[inline] - pub fn get_animation<'a, E>( - &'a self, - name: &Atom, - element: E, - ) -> Option<&'a KeyframesAnimation> + pub fn get_animation<'a, E>(&'a self, name: &Atom, element: E) -> Option<&'a KeyframesAnimation> where E: TElement + 'a, { @@ -1411,7 +1427,7 @@ impl Stylist { if let Some(animation) = $data.animations.get(name) { return Some(animation); } - } + }; } // NOTE(emilio): We implement basically what Blink does for this case, @@ -1431,11 +1447,15 @@ impl Stylist { // [2]: https://github.com/w3c/csswg-drafts/issues/1995 // [3]: https://bugzil.la/1458189 if let Some(shadow) = element.shadow_root() { - try_find_in!(shadow.style_data()); + if let Some(data) = shadow.style_data() { + try_find_in!(data); + } } if let Some(shadow) = element.containing_shadow() { - try_find_in!(shadow.style_data()); + if let Some(data) = shadow.style_data() { + try_find_in!(data); + } } else { try_find_in!(self.cascade_data.author); } @@ -1535,10 +1555,12 @@ impl Stylist { let block = declarations.read_with(guards.author); let iter_declarations = || { - block.declaration_importance_iter().map(|(declaration, importance)| { - debug_assert!(!importance.important()); - (declaration, CascadeLevel::StyleAttributeNormal) - }) + block + .declaration_importance_iter() + .map(|(declaration, importance)| { + debug_assert!(!importance.important()); + (declaration, CascadeLevel::StyleAttributeNormal) + }) }; let metrics = get_metrics_provider_for_product(); @@ -1555,7 +1577,9 @@ impl Stylist { Some(parent_style), Some(parent_style), &metrics, - CascadeMode::Unvisited { visited_rules: None }, + CascadeMode::Unvisited { + visited_rules: None, + }, self.quirks_mode, /* rule_cache = */ None, &mut Default::default(), @@ -1691,8 +1715,10 @@ impl MallocSizeOf for ExtraStyleData { #[cfg_attr(feature = "gecko", derive(MallocSizeOf))] #[derive(Clone, Debug)] struct RevalidationSelectorAndHashes { - #[cfg_attr(feature = "gecko", - ignore_malloc_size_of = "CssRules have primary refs, we measure there")] + #[cfg_attr( + feature = "gecko", + ignore_malloc_size_of = "CssRules have primary refs, we measure there" + )] selector: Selector<SelectorImpl>, selector_offset: usize, hashes: AncestorHashes, @@ -1745,11 +1771,9 @@ struct StylistSelectorVisitor<'a> { passed_rightmost_selector: bool, /// The filter with all the id's getting referenced from rightmost /// selectors. - mapped_ids: &'a mut NonCountingBloomFilter, + mapped_ids: &'a mut PrecomputedHashSet<Atom>, /// The filter with the local names of attributes there are selectors for. - attribute_dependencies: &'a mut NonCountingBloomFilter, - /// Whether there's any attribute selector for the [style] attribute. - style_attribute_dependency: &'a mut bool, + attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>, /// All the states selectors in the page reference. state_dependencies: &'a mut ElementState, /// All the document states selectors in the page reference. @@ -1802,8 +1826,9 @@ impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> { // Also, note that this call happens before we visit any of the simple // selectors in the next ComplexSelector, so we can use this to skip // looking at them. - self.passed_rightmost_selector = self.passed_rightmost_selector || - !matches!(combinator, None | Some(Combinator::PseudoElement)); + self.passed_rightmost_selector = + self.passed_rightmost_selector || + !matches!(combinator, None | Some(Combinator::PseudoElement)); true } @@ -1814,19 +1839,15 @@ impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> { name: &LocalName, lower_name: &LocalName, ) -> bool { - if *lower_name == local_name!("style") { - *self.style_attribute_dependency = true; - } else { - self.attribute_dependencies.insert_hash(name.get_hash()); - self.attribute_dependencies - .insert_hash(lower_name.get_hash()); - } + self.attribute_dependencies.insert(name.clone()); + self.attribute_dependencies.insert(lower_name.clone()); true } fn visit_simple_selector(&mut self, s: &Component<SelectorImpl>) -> bool { - self.needs_revalidation = self.needs_revalidation || - component_needs_revalidation(s, self.passed_rightmost_selector); + self.needs_revalidation = + self.needs_revalidation || + component_needs_revalidation(s, self.passed_rightmost_selector); match *s { Component::NonTSPseudoClass(ref p) => { @@ -1846,7 +1867,7 @@ impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> { // // NOTE(emilio): See the comment regarding on when this may // break in visit_complex_selector. - self.mapped_ids.insert_hash(id.get_hash()); + self.mapped_ids.insert(id.clone()); }, _ => {}, } @@ -1878,11 +1899,15 @@ impl ElementAndPseudoRules { pseudo_element: Option<&PseudoElement>, quirks_mode: QuirksMode, ) -> Result<(), FailedAllocationError> { - debug_assert!(pseudo_element.map_or(true, |pseudo| !pseudo.is_precomputed())); + debug_assert!( + pseudo_element.map_or(true, |pseudo| !pseudo.is_precomputed() && + !pseudo.is_unknown_webkit_pseudo_element()) + ); let map = match pseudo_element { None => &mut self.element_map, - Some(pseudo) => self.pseudos_map + Some(pseudo) => self + .pseudos_map .get_or_insert_with(pseudo, || Box::new(SelectorMap::new())), }; @@ -1944,18 +1969,9 @@ pub struct CascadeData { /// The attribute local names that appear in attribute selectors. Used /// to avoid taking element snapshots when an irrelevant attribute changes. - /// (We don't bother storing the namespace, since namespaced attributes - /// are rare.) - #[ignore_malloc_size_of = "just an array"] - attribute_dependencies: NonCountingBloomFilter, - - /// Whether `"style"` appears in an attribute selector. This is not common, - /// and by tracking this explicitly, we can avoid taking an element snapshot - /// in the common case of style=""` changing due to modifying - /// `element.style`. (We could track this in `attribute_dependencies`, like - /// all other attributes, but we should probably not risk incorrectly - /// returning `true` for `"style"` just due to a hash collision.) - style_attribute_dependency: bool, + /// (We don't bother storing the namespace, since namespaced attributes are + /// rare.) + attribute_dependencies: PrecomputedHashSet<LocalName>, /// The element state bits that are relied on by selectors. Like /// `attribute_dependencies`, this is used to avoid taking element snapshots @@ -1971,8 +1987,7 @@ pub struct CascadeData { /// hence in our selector maps). Used to determine when sharing styles is /// safe: we disallow style sharing for elements whose id matches this /// filter, and hence might be in one of our selector maps. - #[ignore_malloc_size_of = "just an array"] - mapped_ids: NonCountingBloomFilter, + mapped_ids: PrecomputedHashSet<Atom>, /// Selectors that require explicit cache revalidation (i.e. which depend /// on state that is not otherwise visible to the cache, like attributes or @@ -2009,11 +2024,10 @@ impl CascadeData { host_rules: None, slotted_rules: None, invalidation_map: InvalidationMap::new(), - attribute_dependencies: NonCountingBloomFilter::new(), - style_attribute_dependency: false, + attribute_dependencies: PrecomputedHashSet::default(), state_dependencies: ElementState::empty(), document_state_dependencies: DocumentState::empty(), - mapped_ids: NonCountingBloomFilter::new(), + mapped_ids: PrecomputedHashSet::default(), selectors_for_cache_revalidation: SelectorMap::new(), animations: Default::default(), extra_data: ExtraStyleData::default(), @@ -2078,13 +2092,9 @@ impl CascadeData { /// selector of some rule. #[inline] pub fn might_have_attribute_dependency(&self, local_name: &LocalName) -> bool { - if *local_name == local_name!("style") { - return self.style_attribute_dependency; - } - - self.attribute_dependencies - .might_contain_hash(local_name.get_hash()) + self.attribute_dependencies.contains(local_name) } + #[inline] fn normal_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> { self.normal_rules.rules(pseudo) @@ -2191,6 +2201,9 @@ impl CascadeData { )); continue; } + if pseudo.is_unknown_webkit_pseudo_element() { + continue; + } } let hashes = AncestorHashes::new(&selector, quirks_mode); @@ -2208,7 +2221,6 @@ impl CascadeData { needs_revalidation: false, passed_rightmost_selector: false, attribute_dependencies: &mut self.attribute_dependencies, - style_attribute_dependency: &mut self.style_attribute_dependency, state_dependencies: &mut self.state_dependencies, document_state_dependencies: &mut self.document_state_dependencies, mapped_ids: &mut self.mapped_ids, @@ -2265,10 +2277,10 @@ impl CascadeData { debug!("Found valid keyframes rule: {:?}", *keyframes_rule); // Don't let a prefixed keyframes animation override a non-prefixed one. - let needs_insertion = keyframes_rule.vendor_prefix.is_none() || - self.animations - .get(keyframes_rule.name.as_atom()) - .map_or(true, |rule| rule.vendor_prefix.is_some()); + let needs_insertion = keyframes_rule.vendor_prefix.is_none() || self + .animations + .get(keyframes_rule.name.as_atom()) + .map_or(true, |rule| rule.vendor_prefix.is_some()); if needs_insertion { let animation = KeyframesAnimation::from_keyframes( &keyframes_rule.keyframes, @@ -2358,7 +2370,8 @@ impl CascadeData { let effective_now = import_rule .stylesheet .is_effective_for_device(&device, guard); - let effective_then = self.effective_media_query_results + let effective_then = self + .effective_media_query_results .was_effective(import_rule); if effective_now != effective_then { debug!( @@ -2384,9 +2397,7 @@ impl CascadeData { if effective_now != effective_then { debug!( " > @media rule {:?} changed {} -> {}", - mq, - effective_then, - effective_now + mq, effective_then, effective_now ); return false; } @@ -2418,7 +2429,6 @@ impl CascadeData { self.clear_cascade_data(); self.invalidation_map.clear(); self.attribute_dependencies.clear(); - self.style_attribute_dependency = false; self.state_dependencies = ElementState::empty(); self.document_state_dependencies = DocumentState::empty(); self.mapped_ids.clear(); @@ -2467,8 +2477,10 @@ pub struct Rule { pub source_order: u32, /// The actual style rule. - #[cfg_attr(feature = "gecko", - ignore_malloc_size_of = "Secondary ref. Primary ref is in StyleRule under Stylesheet.")] + #[cfg_attr( + feature = "gecko", + ignore_malloc_size_of = "Secondary ref. Primary ref is in StyleRule under Stylesheet." + )] #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")] pub style_rule: Arc<Locked<StyleRule>>, } @@ -2493,7 +2505,13 @@ impl Rule { shadow_cascade_order: ShadowCascadeOrder, ) -> ApplicableDeclarationBlock { let source = StyleSource::from_rule(self.style_rule.clone()); - ApplicableDeclarationBlock::new(source, self.source_order, level, self.specificity(), shadow_cascade_order) + ApplicableDeclarationBlock::new( + source, + self.source_order, + level, + self.specificity(), + shadow_cascade_order, + ) } /// Creates a new Rule. @@ -2514,16 +2532,14 @@ impl Rule { /// A function to be able to test the revalidation stuff. pub fn needs_revalidation_for_testing(s: &Selector<SelectorImpl>) -> bool { - let mut attribute_dependencies = NonCountingBloomFilter::new(); - let mut mapped_ids = NonCountingBloomFilter::new(); - let mut style_attribute_dependency = false; + let mut attribute_dependencies = Default::default(); + let mut mapped_ids = Default::default(); let mut state_dependencies = ElementState::empty(); let mut document_state_dependencies = DocumentState::empty(); let mut visitor = StylistSelectorVisitor { needs_revalidation: false, passed_rightmost_selector: false, attribute_dependencies: &mut attribute_dependencies, - style_attribute_dependency: &mut style_attribute_dependency, state_dependencies: &mut state_dependencies, document_state_dependencies: &mut document_state_dependencies, mapped_ids: &mut mapped_ids, diff --git a/components/style/traversal.rs b/components/style/traversal.rs index 0bffd39819c..5f81f3544a9 100644 --- a/components/style/traversal.rs +++ b/components/style/traversal.rs @@ -208,11 +208,11 @@ pub trait DomTraversal<E: TElement>: Sync { // animation-only restyle hint or recascade. if traversal_flags.for_animation_only() { return data.map_or(false, |d| d.has_styles()) && - (el.has_animation_only_dirty_descendants() || - data.as_ref() - .unwrap() - .hint - .has_animation_hint_or_recascade()); + (el.has_animation_only_dirty_descendants() || data + .as_ref() + .unwrap() + .hint + .has_animation_hint_or_recascade()); } // Non-incremental layout visits every node. @@ -279,7 +279,8 @@ pub trait DomTraversal<E: TElement>: Sync { // likely to load valid bindings, we avoid wasted work here, which may // be a very big perf hit when elements with bindings are nested // heavily. - if cfg!(feature = "gecko") && is_initial_style && + if cfg!(feature = "gecko") && + is_initial_style && parent_data.styles.primary().has_moz_binding() { debug!("Parent {:?} has XBL binding, deferring traversal", parent); @@ -384,8 +385,7 @@ where ).resolve_style( style.as_ref().map(|s| &**s), layout_parent_style.as_ref().map(|s| &**s), - ) - .into() + ).into() } /// Calculates the style for a single node. @@ -411,7 +411,8 @@ pub fn recalc_style_at<E, D, F>( context.thread_local.statistics.elements_traversed += 1; debug_assert!( - flags.intersects(TraversalFlags::AnimationOnly) || !element.has_snapshot() || + flags.intersects(TraversalFlags::AnimationOnly) || + !element.has_snapshot() || element.handled_snapshot(), "Should've handled snapshots here already" ); @@ -512,8 +513,9 @@ pub fn recalc_style_at<E, D, F>( !child_cascade_requirement.can_skip_cascade() || is_servo_nonincremental_layout(); - traverse_children = traverse_children && - !traversal.should_cull_subtree(context, element, &data, is_initial_style); + traverse_children = + traverse_children && + !traversal.should_cull_subtree(context, element, &data, is_initial_style); // Examine our children, and enqueue the appropriate ones for traversal. if traverse_children { @@ -535,7 +537,8 @@ pub fn recalc_style_at<E, D, F>( } debug_assert!( - flags.for_animation_only() || !flags.contains(TraversalFlags::ClearDirtyBits) || + flags.for_animation_only() || + !flags.contains(TraversalFlags::ClearDirtyBits) || !element.has_animation_only_dirty_descendants(), "Should have cleared animation bits already" ); diff --git a/components/style/use_counters/mod.rs b/components/style/use_counters/mod.rs new file mode 100644 index 00000000000..49c77ae714d --- /dev/null +++ b/components/style/use_counters/mod.rs @@ -0,0 +1,88 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! Various stuff for CSS property use counters. + +#[cfg(feature = "gecko")] +use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI}; +use properties::{NonCustomPropertyId, NON_CUSTOM_PROPERTY_ID_COUNT}; +use std::cell::Cell; + +#[cfg(target_pointer_width = "64")] +const BITS_PER_ENTRY: usize = 64; + +#[cfg(target_pointer_width = "32")] +const BITS_PER_ENTRY: usize = 32; + +/// One bit per each non-custom CSS property. +#[derive(Default)] +pub struct NonCustomPropertyUseCounters { + storage: [Cell<usize>; (NON_CUSTOM_PROPERTY_ID_COUNT - 1 + BITS_PER_ENTRY) / BITS_PER_ENTRY], +} + +impl NonCustomPropertyUseCounters { + /// Returns the bucket a given property belongs in, and the bitmask for that + /// property. + #[inline(always)] + fn bucket_and_pattern(id: NonCustomPropertyId) -> (usize, usize) { + let bit = id.bit(); + let bucket = bit / BITS_PER_ENTRY; + let bit_in_bucket = bit % BITS_PER_ENTRY; + (bucket, 1 << bit_in_bucket) + } + + /// Record that a given non-custom property ID has been parsed. + #[inline] + pub fn record(&self, id: NonCustomPropertyId) { + let (bucket, pattern) = Self::bucket_and_pattern(id); + let bucket = &self.storage[bucket]; + bucket.set(bucket.get() | pattern) + } + + /// Returns whether a given non-custom property ID has been recorded + /// earlier. + #[inline] + pub fn recorded(&self, id: NonCustomPropertyId) -> bool { + let (bucket, pattern) = Self::bucket_and_pattern(id); + self.storage[bucket].get() & pattern != 0 + } + + /// Merge `other` into `self`. + #[inline] + fn merge(&self, other: &Self) { + for (bucket, other_bucket) in self.storage.iter().zip(other.storage.iter()) { + bucket.set(bucket.get() | other_bucket.get()) + } + } +} + +/// The use-counter data related to a given document we want to store. +#[derive(Default)] +pub struct UseCounters { + /// The counters for non-custom properties that have been parsed in the + /// document's stylesheets. + pub non_custom_properties: NonCustomPropertyUseCounters, +} + +impl UseCounters { + /// Merge the use counters. + /// + /// Used for parallel parsing, where we parse off-main-thread. + #[inline] + pub fn merge(&self, other: &Self) { + self.non_custom_properties + .merge(&other.non_custom_properties) + } +} + +#[cfg(feature = "gecko")] +unsafe impl HasFFI for UseCounters { + type FFIType = ::gecko_bindings::structs::StyleUseCounters; +} + +#[cfg(feature = "gecko")] +unsafe impl HasSimpleFFI for UseCounters {} + +#[cfg(feature = "gecko")] +unsafe impl HasBoxFFI for UseCounters {} diff --git a/components/style/values/animated/color.rs b/components/style/values/animated/color.rs index 4356c5a3d9b..afffce1c767 100644 --- a/components/style/values/animated/color.rs +++ b/components/style/values/animated/color.rs @@ -61,7 +61,8 @@ impl Animate for RGBA { let red = (self.red * self.alpha).animate(&(other.red * other.alpha), procedure)? * 1. / alpha; let green = (self.green * self.alpha).animate(&(other.green * other.alpha), procedure)? * - 1. / alpha; + 1. / + alpha; let blue = (self.blue * self.alpha).animate(&(other.blue * other.alpha), procedure)? * 1. / alpha; @@ -223,7 +224,7 @@ impl Animate for Color { let fg = fg1.animate(&fg2, procedure)?; Self::with_ratios(bg_color, ComplexColorRatios { bg: 1., fg }) - } + }, }) } } @@ -239,19 +240,19 @@ impl ComputeSquaredDistance for Color { (Numeric(c1), Numeric(c2)) => c1.compute_squared_distance(&c2)?, (Foreground, Numeric(color)) | (Numeric(color), Foreground) => { // `computed_squared_distance` is symmetric. - color.compute_squared_distance(&RGBA::transparent())? - + SquaredDistance::from_sqrt(1.) - } + color.compute_squared_distance(&RGBA::transparent())? + + SquaredDistance::from_sqrt(1.) + }, (_, _) => { let self_color = self.effective_intermediate_rgba(); let other_color = other.effective_intermediate_rgba(); let self_ratios = self.effective_ratios(); let other_ratios = other.effective_ratios(); - self_color.compute_squared_distance(&other_color)? - + self_ratios.bg.compute_squared_distance(&other_ratios.bg)? - + self_ratios.fg.compute_squared_distance(&other_ratios.fg)? - } + self_color.compute_squared_distance(&other_color)? + + self_ratios.bg.compute_squared_distance(&other_ratios.bg)? + + self_ratios.fg.compute_squared_distance(&other_ratios.fg)? + }, }) } } diff --git a/components/style/values/animated/mod.rs b/components/style/values/animated/mod.rs index 53d3719b021..b70ef7d6639 100644 --- a/components/style/values/animated/mod.rs +++ b/components/style/values/animated/mod.rs @@ -392,3 +392,17 @@ where )) } } + +impl<T> ToAnimatedZero for Box<[T]> +where + T: ToAnimatedZero, +{ + #[inline] + fn to_animated_zero(&self) -> Result<Self, ()> { + let v = self + .iter() + .map(|v| v.to_animated_zero()) + .collect::<Result<Vec<_>, _>>()?; + Ok(v.into_boxed_slice()) + } +} diff --git a/components/style/values/computed/angle.rs b/components/style/values/computed/angle.rs index 67ea5d1231b..e162b7a2499 100644 --- a/components/style/values/computed/angle.rs +++ b/components/style/values/computed/angle.rs @@ -15,7 +15,9 @@ use values::distance::{ComputeSquaredDistance, SquaredDistance}; /// A computed angle. #[animate(fallback = "Self::animate_fallback")] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Animate, Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, ToAnimatedZero, ToCss)] +#[derive( + Animate, Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, ToAnimatedZero, ToCss, +)] pub enum Angle { /// An angle with degree unit. #[css(dimension)] @@ -73,7 +75,9 @@ impl Angle { /// <https://drafts.csswg.org/css-transitions/#animtype-number> #[inline] fn animate_fallback(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> { - Ok(Angle::from_radians(self.radians().animate(&other.radians(), procedure)?)) + Ok(Angle::from_radians( + self.radians().animate(&other.radians(), procedure)?, + )) } } diff --git a/components/style/values/computed/border.rs b/components/style/values/computed/border.rs index cf97a96ad73..8c54aeba43b 100644 --- a/components/style/values/computed/border.rs +++ b/components/style/values/computed/border.rs @@ -81,3 +81,19 @@ impl ToAnimatedZero for BorderCornerRadius { Err(()) } } + +impl BorderRadius { + /// Returns whether all the values are `0px`. + pub fn all_zero(&self) -> bool { + fn all(corner: &BorderCornerRadius) -> bool { + fn is_zero(l: &LengthOrPercentage) -> bool { + *l == LengthOrPercentage::zero() + } + is_zero(corner.0.width()) && is_zero(corner.0.height()) + } + all(&self.top_left) && + all(&self.top_right) && + all(&self.bottom_left) && + all(&self.bottom_right) + } +} diff --git a/components/style/values/computed/box.rs b/components/style/values/computed/box.rs index 15e447ea415..002583b2c21 100644 --- a/components/style/values/computed/box.rs +++ b/components/style/values/computed/box.rs @@ -34,13 +34,14 @@ pub type Perspective = GenericPerspective<NonNegativeLength>; #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToCss)] +#[derive( + Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, +)] /// A computed value for the `float` property. pub enum Float { Left, Right, - None + None, } impl ToComputedValue for SpecifiedFloat { @@ -52,7 +53,9 @@ impl ToComputedValue for SpecifiedFloat { // https://drafts.csswg.org/css-logical-props/#float-clear match *self { SpecifiedFloat::InlineStart => { - context.rule_cache_conditions.borrow_mut() + context + .rule_cache_conditions + .borrow_mut() .set_writing_mode_dependency(context.builder.writing_mode); if ltr { Float::Left @@ -61,7 +64,9 @@ impl ToComputedValue for SpecifiedFloat { } }, SpecifiedFloat::InlineEnd => { - context.rule_cache_conditions.borrow_mut() + context + .rule_cache_conditions + .borrow_mut() .set_writing_mode_dependency(context.builder.writing_mode); if ltr { Float::Right @@ -71,7 +76,7 @@ impl ToComputedValue for SpecifiedFloat { }, SpecifiedFloat::Left => Float::Left, SpecifiedFloat::Right => Float::Right, - SpecifiedFloat::None => Float::None + SpecifiedFloat::None => Float::None, } } @@ -80,21 +85,22 @@ impl ToComputedValue for SpecifiedFloat { match *computed { Float::Left => SpecifiedFloat::Left, Float::Right => SpecifiedFloat::Right, - Float::None => SpecifiedFloat::None + Float::None => SpecifiedFloat::None, } } } #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, -SpecifiedValueInfo, ToCss)] +#[derive( + Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, +)] /// A computed value for the `clear` property. pub enum Clear { None, Left, Right, - Both + Both, } impl ToComputedValue for SpecifiedClear { @@ -106,7 +112,9 @@ impl ToComputedValue for SpecifiedClear { // https://drafts.csswg.org/css-logical-props/#float-clear match *self { SpecifiedClear::InlineStart => { - context.rule_cache_conditions.borrow_mut() + context + .rule_cache_conditions + .borrow_mut() .set_writing_mode_dependency(context.builder.writing_mode); if ltr { Clear::Left @@ -115,7 +123,9 @@ impl ToComputedValue for SpecifiedClear { } }, SpecifiedClear::InlineEnd => { - context.rule_cache_conditions.borrow_mut() + context + .rule_cache_conditions + .borrow_mut() .set_writing_mode_dependency(context.builder.writing_mode); if ltr { Clear::Right @@ -126,7 +136,7 @@ impl ToComputedValue for SpecifiedClear { SpecifiedClear::None => Clear::None, SpecifiedClear::Left => Clear::Left, SpecifiedClear::Right => Clear::Right, - SpecifiedClear::Both => Clear::Both + SpecifiedClear::Both => Clear::Both, } } @@ -160,23 +170,27 @@ impl ToComputedValue for specified::Resize { let is_vertical = context.style().writing_mode.is_vertical(); match self { specified::Resize::Inline => { - context.rule_cache_conditions.borrow_mut() + context + .rule_cache_conditions + .borrow_mut() .set_writing_mode_dependency(context.builder.writing_mode); if is_vertical { Resize::Vertical } else { Resize::Horizontal } - } + }, specified::Resize::Block => { - context.rule_cache_conditions.borrow_mut() + context + .rule_cache_conditions + .borrow_mut() .set_writing_mode_dependency(context.builder.writing_mode); if is_vertical { Resize::Horizontal } else { Resize::Vertical } - } + }, specified::Resize::None => Resize::None, specified::Resize::Both => Resize::Both, specified::Resize::Horizontal => Resize::Horizontal, diff --git a/components/style/values/computed/counters.rs b/components/style/values/computed/counters.rs index fd8d7763f1c..211ca6753e7 100644 --- a/components/style/values/computed/counters.rs +++ b/components/style/values/computed/counters.rs @@ -20,4 +20,3 @@ pub type Content = generics::Content<ComputedImageUrl>; /// A computed content item. pub type ContentItem = generics::ContentItem<ComputedImageUrl>; - diff --git a/components/style/values/computed/effects.rs b/components/style/values/computed/effects.rs index 07ac6441b6c..b7e8315a6ac 100644 --- a/components/style/values/computed/effects.rs +++ b/components/style/values/computed/effects.rs @@ -20,11 +20,13 @@ pub type BoxShadow = GenericBoxShadow<Color, Length, NonNegativeLength, Length>; /// A computed value for a single `filter`. #[cfg(feature = "gecko")] -pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, SimpleShadow, ComputedUrl>; +pub type Filter = + GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, SimpleShadow, ComputedUrl>; /// A computed value for a single `filter`. #[cfg(not(feature = "gecko"))] -pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, Impossible, Impossible>; +pub type Filter = + GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, Impossible, Impossible>; /// A computed value for the `drop-shadow()` filter. pub type SimpleShadow = GenericSimpleShadow<Color, Length, NonNegativeLength>; diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index 8db4bd7e917..2c3d2853e5c 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -35,8 +35,7 @@ pub use values::specified::font::{FontSynthesis, MozScriptSizeMultiplier, XLang, /// https://drafts.csswg.org/css-fonts-4/#propdef-font-weight /// /// This is effectively just a `Number`. -#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, - ToCss)] +#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, ToCss)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] pub struct FontWeight(pub Number); @@ -60,8 +59,17 @@ impl ToAnimatedValue for FontWeight { } } -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, - ToAnimatedZero, ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + ToAnimatedZero, + ToCss, +)] /// The computed value of font-size pub struct FontSize { /// The size. @@ -217,9 +225,9 @@ impl FontFamily { #[inline] /// Get default font family as `serif` which is a generic font-family pub fn serif() -> Self { - FontFamily(FontFamilyList::new(Box::new([ - SingleFontFamily::Generic(atom!("serif")), - ]))) + FontFamily(FontFamilyList::new(Box::new([SingleFontFamily::Generic( + atom!("serif"), + )]))) } } @@ -473,9 +481,7 @@ impl SingleFontFamily { FontFamilyType::eFamily_monospace => SingleFontFamily::Generic(atom!("monospace")), FontFamilyType::eFamily_cursive => SingleFontFamily::Generic(atom!("cursive")), FontFamilyType::eFamily_fantasy => SingleFontFamily::Generic(atom!("fantasy")), - FontFamilyType::eFamily_moz_fixed => { - SingleFontFamily::Generic(atom!("-moz-fixed")) - }, + FontFamilyType::eFamily_moz_fixed => SingleFontFamily::Generic(atom!("-moz-fixed")), FontFamilyType::eFamily_named => { let name = Atom::from(&*family.mName); SingleFontFamily::FamilyName(FamilyName { @@ -851,9 +857,10 @@ impl ToAnimatedValue for FontStyleAngle { #[inline] fn from_animated_value(animated: Self::AnimatedValue) -> Self { FontStyleAngle(Angle::Deg( - animated.degrees() + animated + .degrees() .min(specified::FONT_STYLE_OBLIQUE_MAX_ANGLE_DEGREES) - .max(specified::FONT_STYLE_OBLIQUE_MIN_ANGLE_DEGREES) + .max(specified::FONT_STYLE_OBLIQUE_MIN_ANGLE_DEGREES), )) } } @@ -882,10 +889,11 @@ impl FontStyle { /// https://drafts.csswg.org/css-fonts-4/#valdef-font-style-oblique-angle #[inline] pub fn default_angle() -> FontStyleAngle { - FontStyleAngle(Angle::Deg(specified::DEFAULT_FONT_STYLE_OBLIQUE_ANGLE_DEGREES)) + FontStyleAngle(Angle::Deg( + specified::DEFAULT_FONT_STYLE_OBLIQUE_ANGLE_DEGREES, + )) } - /// Get the font style from Gecko's nsFont struct. #[cfg(feature = "gecko")] pub fn from_gecko(style: structs::FontSlantStyle) -> Self { @@ -923,7 +931,7 @@ impl ToCss for FontStyle { angle.to_css(dest)?; } Ok(()) - } + }, } } } diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs index 0ff99a08a3f..f2d43e2ada9 100644 --- a/components/style/values/computed/length.rs +++ b/components/style/values/computed/length.rs @@ -80,7 +80,8 @@ impl ComputeSquaredDistance for CalcLengthOrPercentage { fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> { // FIXME(nox): This looks incorrect to me, to add a distance between lengths // with a distance between percentages. - Ok(self.unclamped_length() + Ok(self + .unclamped_length() .compute_squared_distance(&other.unclamped_length())? + self.percentage() .compute_squared_distance(&other.percentage())?) @@ -285,9 +286,15 @@ impl specified::CalcLengthOrPercentage { /// Compute the value into pixel length as CSSFloat without context, /// so it returns Err(()) if there is any non-absolute unit. pub fn to_computed_pixel_length_without_context(&self) -> Result<CSSFloat, ()> { - if self.vw.is_some() || self.vh.is_some() || self.vmin.is_some() || self.vmax.is_some() || - self.em.is_some() || self.ex.is_some() || self.ch.is_some() || - self.rem.is_some() || self.percentage.is_some() + if self.vw.is_some() || + self.vh.is_some() || + self.vmin.is_some() || + self.vmax.is_some() || + self.em.is_some() || + self.ex.is_some() || + self.ch.is_some() || + self.rem.is_some() || + self.percentage.is_some() { return Err(()); } @@ -324,8 +331,17 @@ impl ToComputedValue for specified::CalcLengthOrPercentage { #[allow(missing_docs)] #[animate(fallback = "Self::animate_fallback")] #[css(derive_debug)] -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, MallocSizeOf, PartialEq, - ToAnimatedValue, ToAnimatedZero, ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + MallocSizeOf, + PartialEq, + ToAnimatedValue, + ToAnimatedZero, + ToCss, +)] #[distance(fallback = "Self::compute_squared_distance_fallback")] pub enum LengthOrPercentage { Length(Length), @@ -483,11 +499,9 @@ impl LengthOrPercentageOrAuto { fn animate_fallback(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> { let this = <Option<CalcLengthOrPercentage>>::from(*self); let other = <Option<CalcLengthOrPercentage>>::from(*other); - Ok(LengthOrPercentageOrAuto::Calc(this.animate( - &other, - procedure, - )? - .ok_or(())?)) + Ok(LengthOrPercentageOrAuto::Calc( + this.animate(&other, procedure)?.ok_or(())?, + )) } #[inline] @@ -602,11 +616,9 @@ impl LengthOrPercentageOrNone { fn animate_fallback(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> { let this = <Option<CalcLengthOrPercentage>>::from(*self); let other = <Option<CalcLengthOrPercentage>>::from(*other); - Ok(LengthOrPercentageOrNone::Calc(this.animate( - &other, - procedure, - )? - .ok_or(())?)) + Ok(LengthOrPercentageOrNone::Calc( + this.animate(&other, procedure)?.ok_or(())?, + )) } fn compute_squared_distance_fallback(&self, other: &Self) -> Result<SquaredDistance, ()> { @@ -727,8 +739,18 @@ impl NonNegativeLengthOrPercentage { /// The computed `<length>` value. #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, - PartialOrd, ToAnimatedValue, ToAnimatedZero)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + PartialOrd, + ToAnimatedValue, + ToAnimatedZero, +)] pub struct CSSPixelLength(CSSFloat); impl CSSPixelLength { @@ -916,8 +938,7 @@ pub type NonNegativeLengthOrPercentageOrNormal = Either<NonNegativeLengthOrPerce /// block-size, and inline-size. #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToCss)] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss)] pub enum ExtremumLength { MozMaxContent, MozMinContent, diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 9a6b5fd76b5..d8cc938c1f3 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -65,6 +65,7 @@ pub use self::length::{NonNegativeLengthOrPercentage, NonNegativeLengthOrPercent pub use self::list::Quotes; #[cfg(feature = "gecko")] pub use self::list::ListStyleType; +pub use self::motion::OffsetPath; pub use self::outline::OutlineStyle; pub use self::percentage::{Percentage, NonNegativePercentage}; pub use self::position::{GridAutoFlow, GridTemplateAreas, Position, ZIndex}; @@ -100,6 +101,7 @@ pub mod gecko; pub mod image; pub mod length; pub mod list; +pub mod motion; pub mod outline; pub mod percentage; pub mod position; diff --git a/components/style/values/computed/motion.rs b/components/style/values/computed/motion.rs new file mode 100644 index 00000000000..352363ab491 --- /dev/null +++ b/components/style/values/computed/motion.rs @@ -0,0 +1,10 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! Computed types for CSS values that are related to motion path. + +/// A computed offset-path. The computed value is as specified value. +/// +/// https://drafts.fxtf.org/motion-1/#offset-path-property +pub use values::specified::motion::OffsetPath; diff --git a/components/style/values/computed/percentage.rs b/components/style/values/computed/percentage.rs index 718d74335b7..4e9ae6172a9 100644 --- a/components/style/values/computed/percentage.rs +++ b/components/style/values/computed/percentage.rs @@ -12,9 +12,21 @@ use values::generics::NonNegative; /// A computed percentage. #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, Default, - MallocSizeOf, PartialEq, PartialOrd, SpecifiedValueInfo, - ToAnimatedValue, ToAnimatedZero, ToComputedValue)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + Default, + MallocSizeOf, + PartialEq, + PartialOrd, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, +)] pub struct Percentage(pub CSSFloat); impl Percentage { diff --git a/components/style/values/computed/transform.rs b/components/style/values/computed/transform.rs index bbf710c4295..a83495a09b5 100644 --- a/components/style/values/computed/transform.rs +++ b/components/style/values/computed/transform.rs @@ -42,6 +42,7 @@ impl TransformOrigin { /// computed value of matrix3d() pub type Matrix3D = generic::Matrix3D<Number>; + /// computed value of matrix() pub type Matrix = generic::Matrix<Number>; @@ -161,13 +162,13 @@ impl TransformOperation { generic::TransformOperation::RotateZ(ref angle) | generic::TransformOperation::Rotate(ref angle) => { generic::TransformOperation::Rotate3D(0., 0., 1., angle.clone()) - } + }, generic::TransformOperation::RotateX(ref angle) => { generic::TransformOperation::Rotate3D(1., 0., 0., angle.clone()) - } + }, generic::TransformOperation::RotateY(ref angle) => { generic::TransformOperation::Rotate3D(0., 1., 0., angle.clone()) - } + }, _ => unreachable!(), } } @@ -272,9 +273,9 @@ impl ToAnimatedZero for TransformOperation { generic::TransformOperation::Rotate(_) => { Ok(generic::TransformOperation::Rotate(Angle::zero())) }, - generic::TransformOperation::Perspective(ref l) => { - Ok(generic::TransformOperation::Perspective(l.to_animated_zero()?)) - }, + generic::TransformOperation::Perspective(ref l) => Ok( + generic::TransformOperation::Perspective(l.to_animated_zero()?), + ), generic::TransformOperation::AccumulateMatrix { .. } | generic::TransformOperation::InterpolateMatrix { .. } => { // AccumulateMatrix/InterpolateMatrix: We do interpolation on @@ -292,10 +293,12 @@ impl ToAnimatedZero for TransformOperation { impl ToAnimatedZero for Transform { #[inline] fn to_animated_zero(&self) -> Result<Self, ()> { - Ok(generic::Transform(self.0 - .iter() - .map(|op| op.to_animated_zero()) - .collect::<Result<Vec<_>, _>>()?)) + Ok(generic::Transform( + self.0 + .iter() + .map(|op| op.to_animated_zero()) + .collect::<Result<Vec<_>, _>>()?, + )) } } diff --git a/components/style/values/generics/background.rs b/components/style/values/generics/background.rs index b25b00514d0..a4f4c58d8cd 100644 --- a/components/style/values/generics/background.rs +++ b/components/style/values/generics/background.rs @@ -5,9 +5,20 @@ //! Generic types for CSS values related to backgrounds. /// A generic value for the `background-size` property. -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, - PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, - ToComputedValue, ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] pub enum BackgroundSize<LengthOrPercentageOrAuto> { /// `<width> <height>` Explicit { diff --git a/components/style/values/generics/basic_shape.rs b/components/style/values/generics/basic_shape.rs index 3bad738c1e6..513e5de0e2b 100644 --- a/components/style/values/generics/basic_shape.rs +++ b/components/style/values/generics/basic_shape.rs @@ -12,14 +12,16 @@ use values::distance::{ComputeSquaredDistance, SquaredDistance}; use values::generics::border::BorderRadius; use values::generics::position::Position; use values::generics::rect::Rect; +use values::specified::SVGPathData; /// A clipping shape, for `clip-path`. pub type ClippingShape<BasicShape, Url> = ShapeSource<BasicShape, GeometryBox, Url>; /// <https://drafts.fxtf.org/css-masking-1/#typedef-geometry-box> #[allow(missing_docs)] -#[derive(Animate, Clone, Copy, Debug, MallocSizeOf, PartialEq, - SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Animate, Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, +)] pub enum GeometryBox { FillBox, StrokeBox, @@ -33,8 +35,19 @@ pub type FloatAreaShape<BasicShape, Image> = ShapeSource<BasicShape, ShapeBox, I /// https://drafts.csswg.org/css-shapes-1/#typedef-shape-box #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Animate, Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Animate, + Clone, + Copy, + Debug, + Eq, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] pub enum ShapeBox { MarginBox, BorderBox, @@ -45,21 +58,33 @@ pub enum ShapeBox { /// A shape source, for some reference box. #[allow(missing_docs)] #[animation(no_bound(ImageOrUrl))] -#[derive(Animate, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive( + Animate, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, +)] pub enum ShapeSource<BasicShape, ReferenceBox, ImageOrUrl> { #[animation(error)] ImageOrUrl(ImageOrUrl), Shape(BasicShape, Option<ReferenceBox>), #[animation(error)] Box(ReferenceBox), + #[css(function)] + Path(Path), #[animation(error)] None, } #[allow(missing_docs)] -#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, - SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] pub enum BasicShape<H, V, LengthOrPercentage> { Inset(#[css(field_bound)] InsetRect<LengthOrPercentage>), Circle(#[css(field_bound)] Circle<H, V, LengthOrPercentage>), @@ -70,8 +95,16 @@ pub enum BasicShape<H, V, LengthOrPercentage> { /// <https://drafts.csswg.org/css-shapes/#funcdef-inset> #[allow(missing_docs)] #[css(function = "inset")] -#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, - SpecifiedValueInfo, ToComputedValue)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, +)] pub struct InsetRect<LengthOrPercentage> { pub rect: Rect<LengthOrPercentage>, pub round: Option<BorderRadius<LengthOrPercentage>>, @@ -80,8 +113,17 @@ pub struct InsetRect<LengthOrPercentage> { /// <https://drafts.csswg.org/css-shapes/#funcdef-circle> #[allow(missing_docs)] #[css(function)] -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, - PartialEq, SpecifiedValueInfo, ToComputedValue)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, +)] pub struct Circle<H, V, LengthOrPercentage> { pub position: Position<H, V>, pub radius: ShapeRadius<LengthOrPercentage>, @@ -90,8 +132,17 @@ pub struct Circle<H, V, LengthOrPercentage> { /// <https://drafts.csswg.org/css-shapes/#funcdef-ellipse> #[allow(missing_docs)] #[css(function)] -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, - PartialEq, SpecifiedValueInfo, ToComputedValue)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, +)] pub struct Ellipse<H, V, LengthOrPercentage> { pub position: Position<H, V>, pub semiaxis_x: ShapeRadius<LengthOrPercentage>, @@ -100,8 +151,18 @@ pub struct Ellipse<H, V, LengthOrPercentage> { /// <https://drafts.csswg.org/css-shapes/#typedef-shape-radius> #[allow(missing_docs)] -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, - PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] pub enum ShapeRadius<LengthOrPercentage> { Length(LengthOrPercentage), #[animation(error)] @@ -113,29 +174,61 @@ pub enum ShapeRadius<LengthOrPercentage> { /// A generic type for representing the `polygon()` function /// /// <https://drafts.csswg.org/css-shapes/#funcdef-polygon> -#[css(function)] -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue)] +#[css(comma, function)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] pub struct Polygon<LengthOrPercentage> { /// The filling rule for a polygon. + #[css(skip_if = "fill_is_default")] pub fill: FillRule, /// A collection of (x, y) coordinates to draw the polygon. - pub coordinates: Vec<(LengthOrPercentage, LengthOrPercentage)>, + #[css(iterable)] + pub coordinates: Vec<PolygonCoord<LengthOrPercentage>>, } +/// Coordinates for Polygon. +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] +pub struct PolygonCoord<LengthOrPercentage>(pub LengthOrPercentage, pub LengthOrPercentage); + // https://drafts.csswg.org/css-shapes/#typedef-fill-rule // NOTE: Basic shapes spec says that these are the only two values, however // https://www.w3.org/TR/SVG/painting.html#FillRuleProperty // says that it can also be `inherit` #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Clone, + Copy, + Debug, + Eq, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] +#[repr(u8)] pub enum FillRule { Nonzero, Evenodd, } +/// The path function defined in css-shape-2. +/// +/// https://drafts.csswg.org/css-shapes-2/#funcdef-path +#[css(comma)] +#[derive( + Animate, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, +)] +pub struct Path { + /// The filling rule for the svg path. + #[css(skip_if = "fill_is_default")] + #[animation(constant)] + pub fill: FillRule, + /// The svg path data. + pub path: SVGPathData, +} + // FIXME(nox): Implement ComputeSquaredDistance for T types and stop // using PartialEq here, this will let us derive this impl. impl<B, T, U> ComputeSquaredDistance for ShapeSource<B, T, U> @@ -148,10 +241,16 @@ where ( &ShapeSource::Shape(ref this, ref this_box), &ShapeSource::Shape(ref other, ref other_box), - ) if this_box == other_box => + ) + if this_box == other_box => { this.compute_squared_distance(other) }, + (&ShapeSource::Path(ref this), &ShapeSource::Path(ref other)) + if this.fill == other.fill => + { + this.path.compute_squared_distance(&other.path) + }, _ => Err(()), } } @@ -199,16 +298,16 @@ where if self.coordinates.len() != other.coordinates.len() { return Err(()); } - let coordinates = self.coordinates + let coordinates = self + .coordinates .iter() .zip(other.coordinates.iter()) .map(|(this, other)| { - Ok(( + Ok(PolygonCoord( this.0.animate(&other.0, procedure)?, this.1.animate(&other.1, procedure)?, )) - }) - .collect::<Result<Vec<_>, _>>()?; + }).collect::<Result<Vec<_>, _>>()?; Ok(Polygon { fill: self.fill, coordinates, @@ -234,33 +333,7 @@ where let d1 = this.0.compute_squared_distance(&other.0)?; let d2 = this.1.compute_squared_distance(&other.1)?; Ok(d1 + d2) - }) - .sum() - } -} - -impl<L: ToCss> ToCss for Polygon<L> { - fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result - where - W: Write, - { - dest.write_str("polygon(")?; - if self.fill != FillRule::default() { - self.fill.to_css(dest)?; - dest.write_str(", ")?; - } - - for (i, coord) in self.coordinates.iter().enumerate() { - if i > 0 { - dest.write_str(", ")?; - } - - coord.0.to_css(dest)?; - dest.write_str(" ")?; - coord.1.to_css(dest)?; - } - - dest.write_str(")") + }).sum() } } @@ -270,3 +343,8 @@ impl Default for FillRule { FillRule::Nonzero } } + +#[inline] +fn fill_is_default(fill: &FillRule) -> bool { + *fill == FillRule::default() +} diff --git a/components/style/values/generics/border.rs b/components/style/values/generics/border.rs index c25560ed0f1..4f40409843a 100644 --- a/components/style/values/generics/border.rs +++ b/components/style/values/generics/border.rs @@ -10,8 +10,9 @@ use values::generics::rect::Rect; use values::generics::size::Size; /// A generic value for a single side of a `border-image-width` property. -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive( + Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, +)] pub enum BorderImageSideWidth<LengthOrPercentage, Number> { /// `<length-or-percentage>` Length(LengthOrPercentage), @@ -22,8 +23,9 @@ pub enum BorderImageSideWidth<LengthOrPercentage, Number> { } /// A generic value for the `border-image-slice` property. -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive( + Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, +)] pub struct BorderImageSlice<NumberOrPercentage> { /// The offsets. #[css(field_bound)] @@ -34,8 +36,18 @@ pub struct BorderImageSlice<NumberOrPercentage> { } /// A generic value for the `border-*-radius` longhand properties. -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, - PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] pub struct BorderCornerRadius<L>(#[css(field_bound)] pub Size<L>); impl<L> BorderCornerRadius<L> { @@ -46,9 +58,20 @@ impl<L> BorderCornerRadius<L> { } /// A generic value for the `border-spacing` property. -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, - PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, - ToComputedValue, ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] pub struct BorderSpacing<L>(#[css(field_bound)] pub Size<L>); impl<L> BorderSpacing<L> { @@ -61,8 +84,17 @@ impl<L> BorderSpacing<L> { /// A generic value for `border-radius`, `outline-radius` and `inset()`. /// /// <https://drafts.csswg.org/css-backgrounds-3/#border-radius> -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, - PartialEq, SpecifiedValueInfo, ToComputedValue)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, +)] pub struct BorderRadius<LengthOrPercentage> { /// The top left radius. pub top_left: BorderCornerRadius<LengthOrPercentage>, @@ -120,7 +152,9 @@ where W: Write, { widths.to_css(dest)?; - if widths.0 != heights.0 || widths.1 != heights.1 || widths.2 != heights.2 || + if widths.0 != heights.0 || + widths.1 != heights.1 || + widths.2 != heights.2 || widths.3 != heights.3 { dest.write_str(" / ")?; diff --git a/components/style/values/generics/box.rs b/components/style/values/generics/box.rs index ea79e98eefb..0b525974288 100644 --- a/components/style/values/generics/box.rs +++ b/components/style/values/generics/box.rs @@ -7,8 +7,18 @@ use values::animated::ToAnimatedZero; /// A generic value for the `vertical-align` property. -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, - PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] pub enum VerticalAlign<LengthOrPercentage> { /// `baseline` Baseline, @@ -48,8 +58,7 @@ impl<L> ToAnimatedZero for VerticalAlign<L> { } /// https://drafts.csswg.org/css-animations/#animation-iteration-count -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] pub enum AnimationIterationCount<Number> { /// A `<number>` value. Number(Number), @@ -58,9 +67,20 @@ pub enum AnimationIterationCount<Number> { } /// A generic value for the `perspective` property. -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, - PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, - ToComputedValue, ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] pub enum Perspective<NonNegativeLength> { /// A non-negative length. Length(NonNegativeLength), diff --git a/components/style/values/generics/column.rs b/components/style/values/generics/column.rs index 1d76f6cb552..5f96650d3e8 100644 --- a/components/style/values/generics/column.rs +++ b/components/style/values/generics/column.rs @@ -5,9 +5,20 @@ //! Generic types for the column properties. /// A generic type for `column-count` values. -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, - PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, - ToComputedValue, ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] pub enum ColumnCount<PositiveInteger> { /// A positive integer. Integer(PositiveInteger), diff --git a/components/style/values/generics/counters.rs b/components/style/values/generics/counters.rs index 779d56d65ee..4bbf728d457 100644 --- a/components/style/values/generics/counters.rs +++ b/components/style/values/generics/counters.rs @@ -14,8 +14,7 @@ use values::generics::CounterStyleOrNone; use values::specified::Attr; /// A name / value pair for counters. -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] pub struct CounterPair<Integer> { /// The name of the counter. pub name: CustomIdent, @@ -24,8 +23,9 @@ pub struct CounterPair<Integer> { } /// A generic value for the `counter-increment` property. -#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive( + Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, +)] pub struct CounterIncrement<I>(Counters<I>); impl<I> CounterIncrement<I> { @@ -46,8 +46,9 @@ impl<I> Deref for CounterIncrement<I> { } /// A generic value for the `counter-reset` property. -#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive( + Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, +)] pub struct CounterReset<I>(Counters<I>); impl<I> CounterReset<I> { @@ -70,8 +71,7 @@ impl<I> Deref for CounterReset<I> { /// A generic value for lists of counters. /// /// Keyword `none` is represented by an empty vector. -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] pub struct Counters<I>(#[css(iterable, if_empty = "none")] Box<[CounterPair<I>]>); impl<I> Default for Counters<I> { @@ -102,8 +102,7 @@ fn is_decimal(counter_type: &CounterStyleType) -> bool { /// The specified value for the `content` property. /// /// https://drafts.csswg.org/css-content/#propdef-content -#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] pub enum Content<ImageUrl> { /// `normal` reserved keyword. Normal, @@ -125,8 +124,7 @@ impl<ImageUrl> Content<ImageUrl> { } /// Items for the `content` property. -#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] pub enum ContentItem<ImageUrl> { /// Literal string content. String(Box<str>), diff --git a/components/style/values/generics/effects.rs b/components/style/values/generics/effects.rs index f05dfe82d66..7c7e3f4bef3 100644 --- a/components/style/values/generics/effects.rs +++ b/components/style/values/generics/effects.rs @@ -5,8 +5,17 @@ //! Generic types for CSS values related to effects. /// A generic value for a single `box-shadow`. -#[derive(Animate, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToAnimatedValue, ToAnimatedZero, ToCss)] +#[derive( + Animate, + Clone, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToCss, +)] pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> { /// The base shadow. pub base: SimpleShadow<Color, SizeLength, BlurShapeLength>, @@ -21,8 +30,17 @@ pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> { /// A generic value for a single `filter`. #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[animation(no_bound(Url))] -#[derive(Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, - SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToCss)] +#[derive( + Clone, + ComputeSquaredDistance, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToComputedValue, + ToCss, +)] pub enum Filter<Angle, Factor, Length, DropShadow, Url> { /// `blur(<length>)` #[css(function)] @@ -63,8 +81,18 @@ pub enum Filter<Angle, Factor, Length, DropShadow, Url> { /// /// Contrary to the canonical order from the spec, the color is serialised /// first, like in Gecko and Webkit. -#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, - SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToCss, +)] pub struct SimpleShadow<Color, SizeLength, ShapeLength> { /// Color. pub color: Color, diff --git a/components/style/values/generics/flex.rs b/components/style/values/generics/flex.rs index 1ab53233c44..9cbece2e1bc 100644 --- a/components/style/values/generics/flex.rs +++ b/components/style/values/generics/flex.rs @@ -6,9 +6,19 @@ /// A generic value for the `flex-basis` property. #[cfg_attr(feature = "servo", derive(MallocSizeOf))] -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, - SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, ToComputedValue, - ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] pub enum FlexBasis<Width> { /// `content` Content, diff --git a/components/style/values/generics/font.rs b/components/style/values/generics/font.rs index 02df291065f..03a76c5a32d 100644 --- a/components/style/values/generics/font.rs +++ b/components/style/values/generics/font.rs @@ -16,8 +16,7 @@ use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss}; use values::distance::{ComputeSquaredDistance, SquaredDistance}; /// https://drafts.csswg.org/css-fonts-4/#feature-tag-value -#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue)] +#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)] pub struct FeatureTagValue<Integer> { /// A four-character tag, packed into a u32 (one byte per character). pub tag: FontTag, @@ -47,8 +46,9 @@ where /// Variation setting for a single feature, see: /// /// https://drafts.csswg.org/css-fonts-4/#font-variation-settings-def -#[derive(Animate, Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive( + Animate, Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, +)] pub struct VariationValue<Number> { /// A four-character tag, packed into a u32 (one byte per character). #[animation(constant)] @@ -72,8 +72,7 @@ where /// A value both for font-variation-settings and font-feature-settings. #[css(comma)] -#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] pub struct FontSettings<T>(#[css(if_empty = "normal", iterable)] pub Box<[T]>); impl<T> FontSettings<T> { @@ -109,8 +108,7 @@ impl<T: Parse> Parse for FontSettings<T> { /// https://drafts.csswg.org/css-fonts-4/#font-variation-settings-def /// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-feature-settings /// -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue)] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)] pub struct FontTag(pub u32); impl ToCss for FontTag { @@ -145,8 +143,18 @@ impl Parse for FontTag { } } -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, - ToAnimatedValue, ToAnimatedZero, ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + ToAnimatedValue, + ToAnimatedZero, + ToCss, +)] /// Additional information for keyword-derived font sizes. pub struct KeywordInfo<Length> { /// The keyword used @@ -189,9 +197,20 @@ impl<L> SpecifiedValueInfo for KeywordInfo<L> { } /// CSS font keywords -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, - Parse, PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, - ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToCss, +)] #[allow(missing_docs)] pub enum KeywordSize { #[css(keyword = "xx-small")] @@ -228,8 +247,19 @@ impl Default for KeywordSize { /// https://drafts.csswg.org/css-fonts-4/#font-style-prop #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, Hash, MallocSizeOf, - PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + Hash, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, +)] pub enum FontStyle<Angle> { #[animation(error)] Normal, diff --git a/components/style/values/generics/gecko.rs b/components/style/values/generics/gecko.rs index 72a8b71d073..d56158750b6 100644 --- a/components/style/values/generics/gecko.rs +++ b/components/style/values/generics/gecko.rs @@ -7,8 +7,7 @@ /// A generic value for scroll snap points. #[cfg_attr(feature = "gecko", derive(MallocSizeOf))] -#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToComputedValue, - ToCss)] +#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] pub enum ScrollSnapPoint<LengthOrPercentage> { /// `none` None, diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index b9ec85ace22..56b6f463691 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -18,8 +18,7 @@ use values::specified::grid::parse_line_names; /// A `<grid-line>` type. /// /// <https://drafts.csswg.org/css-grid/#typedef-grid-row-start-grid-line> -#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue)] +#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)] pub struct GridLine<Integer> { /// Flag to check whether it's a `span` keyword. pub is_span: bool, @@ -149,8 +148,18 @@ impl Parse for GridLine<specified::Integer> { #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Clone, + Copy, + Debug, + Eq, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] pub enum TrackKeyword { Auto, MaxContent, @@ -161,8 +170,7 @@ pub enum TrackKeyword { /// avoid re-implementing it for the computed type. /// /// <https://drafts.csswg.org/css-grid/#typedef-track-breadth> -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] pub enum TrackBreadth<L> { /// The generic type is almost always a non-negative `<length-percentage>` Breadth(L), @@ -383,8 +391,7 @@ impl Parse for RepeatCount<specified::Integer> { /// /// It can also hold `repeat()` function parameters, which expands into the respective /// values in its computed form. -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)] #[css(function = "repeat")] pub struct TrackRepeat<L, I> { /// The number of times for the value to be repeated (could also be `auto-fit` or `auto-fill`) @@ -409,7 +416,8 @@ impl<L: ToCss, I: ToCss> ToCss for TrackRepeat<L, I> { dest.write_str(", ")?; let mut line_names_iter = self.line_names.iter(); - for (i, (ref size, ref names)) in self.track_sizes + for (i, (ref size, ref names)) in self + .track_sizes .iter() .zip(&mut line_names_iter) .enumerate() @@ -471,8 +479,7 @@ impl<L: Clone> TrackRepeat<L, specified::Integer> { } /// Track list values. Can be <track-size> or <track-repeat> -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] pub enum TrackListValue<LengthOrPercentage, Integer> { /// A <track-size> value. TrackSize(TrackSize<LengthOrPercentage>), @@ -578,8 +585,7 @@ impl<L: ToCss, I: ToCss> ToCss for TrackList<L, I> { /// /// `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 -#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue)] +#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)] pub struct LineNameList { /// The optional `<line-name-list>` pub names: Box<[Box<[CustomIdent]>]>, @@ -624,7 +630,9 @@ impl Parse for LineNameList { RepeatCount::AutoFill if fill_idx.is_none() => { // `repeat(autof-fill, ..)` should have just one line name. if names_list.len() != 1 { - return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); + return Err( + input.new_custom_error(StyleParseErrorKind::UnspecifiedError) + ); } let names = names_list.pop().unwrap(); @@ -682,8 +690,7 @@ 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. -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] pub enum GridTemplateComponent<L, I> { /// `none` value. None, diff --git a/components/style/values/generics/image.rs b/components/style/values/generics/image.rs index 2da4d290039..16d348ac47e 100644 --- a/components/style/values/generics/image.rs +++ b/components/style/values/generics/image.rs @@ -145,7 +145,7 @@ pub struct PaintWorklet { pub arguments: Vec<Arc<custom_properties::SpecifiedValue>>, } -impl ::style_traits::SpecifiedValueInfo for PaintWorklet { } +impl ::style_traits::SpecifiedValueInfo for PaintWorklet {} impl ToCss for PaintWorklet { fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result @@ -167,8 +167,7 @@ impl ToCss for PaintWorklet { /// `-moz-image-rect(<uri>, top, right, bottom, left);` #[allow(missing_docs)] #[css(comma, function)] -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] pub struct MozImageRect<NumberOrPercentage, MozImageRectUrl> { pub url: MozImageRectUrl, pub top: NumberOrPercentage, diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index e6c1befea9f..32ea771cf15 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -157,14 +157,37 @@ impl SpecifiedValueInfo for CounterStyleOrNone { /// A wrapper of Non-negative values. #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, Hash, MallocSizeOf, - PartialEq, PartialOrd, SpecifiedValueInfo, ToAnimatedZero, - ToComputedValue, ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + Hash, + MallocSizeOf, + PartialEq, + PartialOrd, + SpecifiedValueInfo, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] pub struct NonNegative<T>(pub T); /// A wrapper of greater-than-or-equal-to-one values. #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, - PartialEq, PartialOrd, SpecifiedValueInfo, ToAnimatedZero, - ToComputedValue, ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + PartialOrd, + SpecifiedValueInfo, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] pub struct GreaterThanOrEqualToOne<T>(pub T); diff --git a/components/style/values/generics/position.rs b/components/style/values/generics/position.rs index 67c167c41ab..83dc48d0905 100644 --- a/components/style/values/generics/position.rs +++ b/components/style/values/generics/position.rs @@ -6,8 +6,18 @@ //! [`position`](https://drafts.csswg.org/css-backgrounds-3/#position) /// A generic type for representing a CSS [position](https://drafts.csswg.org/css-values/#position). -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, - PartialEq, SpecifiedValueInfo, ToAnimatedZero, ToComputedValue)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedZero, + ToComputedValue, +)] pub struct Position<H, V> { /// The horizontal component of position. pub horizontal: H, @@ -26,8 +36,19 @@ impl<H, V> Position<H, V> { } /// A generic value for the `z-index` property. -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, - PartialEq, SpecifiedValueInfo, ToAnimatedZero, ToComputedValue, ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] pub enum ZIndex<Integer> { /// An integer value. Integer(Integer), diff --git a/components/style/values/generics/rect.rs b/components/style/values/generics/rect.rs index fb67e48a395..510cb75a6f8 100644 --- a/components/style/values/generics/rect.rs +++ b/components/style/values/generics/rect.rs @@ -11,8 +11,17 @@ use style_traits::{CssWriter, ParseError, ToCss}; /// A CSS value made of four components, where its `ToCss` impl will try to /// serialize as few components as possible, like for example in `border-width`. -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, - PartialEq, SpecifiedValueInfo, ToComputedValue)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, +)] pub struct Rect<T>(pub T, pub T, pub T, pub T); impl<T> Rect<T> { diff --git a/components/style/values/generics/size.rs b/components/style/values/generics/size.rs index ad93b94e65e..d7ef5810f05 100644 --- a/components/style/values/generics/size.rs +++ b/components/style/values/generics/size.rs @@ -13,8 +13,17 @@ use values::animated::ToAnimatedValue; /// A generic size, for `border-*-radius` longhand properties, or /// `border-spacing`. -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, - ToAnimatedZero, ToComputedValue)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + ToAnimatedZero, + ToComputedValue, +)] pub struct Size<L>(pub Size2D<L>); impl<L> Size<L> { diff --git a/components/style/values/generics/svg.rs b/components/style/values/generics/svg.rs index 0fbaacf2283..8b8fa786e8f 100644 --- a/components/style/values/generics/svg.rs +++ b/components/style/values/generics/svg.rs @@ -16,8 +16,18 @@ use values::distance::{ComputeSquaredDistance, SquaredDistance}; /// /// <https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint> #[animation(no_bound(UrlPaintServer))] -#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, - SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToComputedValue, + ToCss, +)] pub struct SVGPaint<ColorType, UrlPaintServer> { /// The paint source pub kind: SVGPaintKind<ColorType, UrlPaintServer>, @@ -31,9 +41,19 @@ pub struct SVGPaint<ColorType, UrlPaintServer> { /// to have a fallback, Gecko lets the context /// properties have a fallback as well. #[animation(no_bound(UrlPaintServer))] -#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, - SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, ToComputedValue, - ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] pub enum SVGPaintKind<ColorType, UrlPaintServer> { /// `none` #[animation(error)] @@ -113,8 +133,18 @@ impl<ColorType: Parse, UrlPaintServer: Parse> Parse for SVGPaint<ColorType, UrlP /// A value of <length> | <percentage> | <number> for svg which allow unitless length. /// <https://www.w3.org/TR/SVG11/painting.html#StrokeProperties> -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss)] +#[derive( + Clone, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] pub enum SvgLengthOrPercentageOrNumber<LengthOrPercentage, Number> { /// <length> | <percentage> LengthOrPercentage(LengthOrPercentage), @@ -191,9 +221,19 @@ impl<LengthOrPercentageType: Parse, NumberType: Parse> Parse } /// An SVG length value supports `context-value` in addition to length. -#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, - SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, ToComputedValue, - ToCss)] +#[derive( + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] pub enum SVGLength<LengthType> { /// `<length> | <percentage> | <number>` Length(LengthType), @@ -202,23 +242,38 @@ pub enum SVGLength<LengthType> { } /// Generic value for stroke-dasharray. -#[derive(Clone, Debug, MallocSizeOf, PartialEq, - SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToCss)] +#[derive( + Clone, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToComputedValue, + ToCss, +)] pub enum SVGStrokeDashArray<LengthType> { /// `[ <length> | <percentage> | <number> ]#` #[css(comma)] - Values( - #[css(if_empty = "none", iterable)] - Vec<LengthType>, - ), + Values(#[css(if_empty = "none", iterable)] Vec<LengthType>), /// `context-value` ContextValue, } /// An SVG opacity value accepts `context-{fill,stroke}-opacity` in /// addition to opacity value. -#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, - SpecifiedValueInfo, ToAnimatedZero, ToComputedValue, ToCss)] +#[derive( + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] pub enum SVGOpacity<OpacityType> { /// `<opacity-value>` Opacity(OpacityType), diff --git a/components/style/values/generics/text.rs b/components/style/values/generics/text.rs index 6cc5caaac77..e85c444a695 100644 --- a/components/style/values/generics/text.rs +++ b/components/style/values/generics/text.rs @@ -12,8 +12,9 @@ use values::animated::{Animate, Procedure, ToAnimatedZero}; use values::distance::{ComputeSquaredDistance, SquaredDistance}; /// A generic value for the `initial-letter` property. -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive( + Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, +)] pub enum InitialLetter<Number, Integer> { /// `normal` Normal, @@ -30,8 +31,9 @@ impl<N, I> InitialLetter<N, I> { } /// A generic spacing value for the `letter-spacing` and `word-spacing` properties. -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive( + Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, +)] pub enum Spacing<Value> { /// `normal` Normal, @@ -112,8 +114,18 @@ where } /// A generic value for the `line-height` property. -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, - PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToCss, +)] pub enum LineHeight<Number, LengthOrPercentage> { /// `normal` Normal, @@ -142,9 +154,20 @@ impl<N, L> LineHeight<N, L> { } /// A generic value for the `-moz-tab-size` property. -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, - PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, - ToComputedValue, ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] pub enum MozTabSize<Number, Length> { /// A number. Number(Number), diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index a0cbc57d6b4..cce0464d2ac 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -15,8 +15,9 @@ use values::specified::length::LengthOrPercentage as SpecifiedLengthOrPercentage /// A generic 2D transformation matrix. #[allow(missing_docs)] -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive( + Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, +)] #[css(comma, function)] pub struct Matrix<T> { pub a: T, @@ -66,8 +67,19 @@ impl<T: Into<f64>> From<Matrix3D<T>> for Transform3D<f64> { } /// A generic transform origin. -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, - PartialEq, SpecifiedValueInfo, ToAnimatedZero, ToComputedValue, ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] pub struct TransformOrigin<H, V, Depth> { /// The horizontal origin. pub horizontal: H, @@ -80,8 +92,7 @@ pub struct TransformOrigin<H, V, Depth> { /// A generic timing function. /// /// <https://drafts.csswg.org/css-timing-1/#single-timing-function-production> -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToCss)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)] #[value_info(ty = "TIMING_FUNCTION")] pub enum TimingFunction<Integer, Number> { /// `linear | ease | ease-in | ease-out | ease-in-out` @@ -106,8 +117,18 @@ pub enum TimingFunction<Integer, Number> { #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Clone, + Copy, + Debug, + Eq, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] pub enum TimingKeyword { Linear, Ease, @@ -163,8 +184,7 @@ impl TimingKeyword { } } -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] /// A single operation in the list of a `transform` value pub enum TransformOperation<Angle, Number, Length, Integer, LengthOrPercentage> { /// Represents a 2D 2x3 matrix. @@ -268,8 +288,7 @@ pub enum TransformOperation<Angle, Number, Length, Integer, LengthOrPercentage> }, } -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] /// A value of the `transform` property pub struct Transform<T>(#[css(if_empty = "none", iterable)] pub Vec<T>); @@ -281,11 +300,7 @@ impl<Angle, Number, Length, Integer, LengthOrPercentage> use self::TransformOperation::*; matches!( *self, - Rotate(..) | - Rotate3D(..) | - RotateX(..) | - RotateY(..) | - RotateZ(..) + Rotate(..) | Rotate3D(..) | RotateX(..) | RotateY(..) | RotateZ(..) ) } @@ -574,8 +589,18 @@ pub fn get_normalized_vector_and_angle<T: Zero>( } } -#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, - SpecifiedValueInfo, ToAnimatedZero, ToComputedValue, ToCss)] +#[derive( + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] /// A value of the `Rotate` property /// /// <https://drafts.csswg.org/css-transforms-2/#individual-transforms> @@ -588,8 +613,18 @@ pub enum Rotate<Number, Angle> { Rotate3D(Number, Number, Number, Angle), } -#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, - SpecifiedValueInfo, ToAnimatedZero, ToComputedValue, ToCss)] +#[derive( + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] /// A value of the `Scale` property /// /// <https://drafts.csswg.org/css-transforms-2/#individual-transforms> @@ -604,8 +639,17 @@ pub enum Scale<Number> { Scale3D(Number, Number, Number), } -#[derive(Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, - SpecifiedValueInfo, ToAnimatedZero, ToComputedValue, ToCss)] +#[derive( + Clone, + ComputeSquaredDistance, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] /// A value of the `Translate` property /// /// <https://drafts.csswg.org/css-transforms-2/#individual-transforms> @@ -621,8 +665,9 @@ pub enum Translate<LengthOrPercentage, Length> { } #[allow(missing_docs)] -#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive( + Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, +)] pub enum TransformStyle { #[cfg(feature = "servo")] Auto, diff --git a/components/style/values/generics/ui.rs b/components/style/values/generics/ui.rs index 9ccf1f80d53..bef1926bc90 100644 --- a/components/style/values/generics/ui.rs +++ b/components/style/values/generics/ui.rs @@ -11,8 +11,7 @@ use style_traits::cursor::CursorKind; /// A generic value for the `cursor` property. /// /// https://drafts.csswg.org/css-ui/#cursor -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)] pub struct Cursor<Image> { /// The parsed images for the cursor. pub images: Box<[Image]>, @@ -45,8 +44,7 @@ impl<Image: ToCss> ToCss for Cursor<Image> { } /// A generic value for item of `image cursors`. -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)] pub struct CursorImage<ImageUrl, Number> { /// The url to parse images from. pub url: ImageUrl, diff --git a/components/style/values/generics/url.rs b/components/style/values/generics/url.rs index 5da74a7b087..ff9fa16d665 100644 --- a/components/style/values/generics/url.rs +++ b/components/style/values/generics/url.rs @@ -9,9 +9,19 @@ use parser::{Parse, ParserContext}; use style_traits::ParseError; /// An image url or none, used for example in list-style-image -#[derive(Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, - SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, ToComputedValue, - ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] pub enum UrlOrNone<Url> { /// `none` None, diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs index a5f8d0abd32..d3ae6a83971 100644 --- a/components/style/values/mod.rs +++ b/components/style/values/mod.rs @@ -92,8 +92,13 @@ where } /// Convenience void type to disable some properties and values through types. -#[cfg_attr(feature = "servo", derive(Deserialize, MallocSizeOf, Serialize))] -#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToCss)] +#[cfg_attr( + feature = "servo", + derive(Deserialize, MallocSizeOf, Serialize) +)] +#[derive( + Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToCss, +)] pub enum Impossible {} // FIXME(nox): This should be derived but the derive code cannot cope @@ -115,9 +120,19 @@ impl Parse for Impossible { } /// A struct representing one of two kinds of values. -#[derive(Animate, Clone, ComputeSquaredDistance, Copy, MallocSizeOf, PartialEq, - SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, ToComputedValue, - ToCss)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] pub enum Either<A, B> { /// The first value. First(A), @@ -148,8 +163,7 @@ impl<A: Parse, B: Parse> Parse for Either<A, B> { } /// <https://drafts.csswg.org/css-values-4/#custom-idents> -#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue)] +#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)] pub struct CustomIdent(pub Atom); impl CustomIdent { @@ -164,7 +178,9 @@ impl CustomIdent { _ => true }; if !valid { - return Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone()))); + return Err( + location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone())) + ); } if excluding.iter().any(|s| ident.eq_ignore_ascii_case(s)) { Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)) diff --git a/components/style/values/specified/align.rs b/components/style/values/specified/align.rs index 731844bcb52..858ecce065d 100644 --- a/components/style/values/specified/align.rs +++ b/components/style/values/specified/align.rs @@ -683,8 +683,13 @@ fn parse_self_position<'i, 't>( fn list_self_position_keywords(f: KeywordsCollectFn, axis: AxisDirection) { f(&[ - "start", "end", "flex-start", "flex-end", - "center", "self-start", "self-end", + "start", + "end", + "flex-start", + "flex-end", + "center", + "self-start", + "self-end", ]); if axis == AxisDirection::Inline { f(&["left", "right"]); diff --git a/components/style/values/specified/background.rs b/components/style/values/specified/background.rs index d7c4ec629ca..6c85d6ec5a6 100644 --- a/components/style/values/specified/background.rs +++ b/components/style/values/specified/background.rs @@ -43,8 +43,18 @@ impl BackgroundSize { } /// One of the keywords for `background-repeat`. -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Clone, + Copy, + Debug, + Eq, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] #[allow(missing_docs)] pub enum BackgroundRepeatKeyword { Repeat, @@ -56,8 +66,7 @@ pub enum BackgroundRepeatKeyword { /// The specified value for the `background-repeat` property. /// /// https://drafts.csswg.org/css-backgrounds/#the-background-repeat -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToCss)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)] pub enum BackgroundRepeat { /// `repeat-x` RepeatX, @@ -91,7 +100,9 @@ impl Parse for BackgroundRepeat { let horizontal = match BackgroundRepeatKeyword::from_ident(&ident) { Ok(h) => h, Err(()) => { - return Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone()))); + return Err( + input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone())) + ); }, }; diff --git a/components/style/values/specified/basic_shape.rs b/components/style/values/specified/basic_shape.rs index 23ae91d564e..cdafbf14b37 100644 --- a/components/style/values/specified/basic_shape.rs +++ b/components/style/values/specified/basic_shape.rs @@ -14,9 +14,11 @@ use std::fmt::{self, Write}; use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; use values::computed::Percentage; use values::generics::basic_shape as generic; -use values::generics::basic_shape::{FillRule, GeometryBox, ShapeBox, ShapeSource}; +use values::generics::basic_shape::{FillRule, GeometryBox, Path, PolygonCoord}; +use values::generics::basic_shape::{ShapeBox, ShapeSource}; use values::generics::rect::Rect; use values::specified::LengthOrPercentage; +use values::specified::SVGPathData; use values::specified::border::BorderRadius; use values::specified::image::Image; use values::specified::position::{HorizontalPosition, Position, PositionComponent}; @@ -47,12 +49,49 @@ pub type ShapeRadius = generic::ShapeRadius<LengthOrPercentage>; /// The specified value of `Polygon` pub type Polygon = generic::Polygon<LengthOrPercentage>; -impl<ReferenceBox, ImageOrUrl> Parse for ShapeSource<BasicShape, ReferenceBox, ImageOrUrl> +#[cfg(feature = "gecko")] +fn is_clip_path_path_enabled(context: &ParserContext) -> bool { + use gecko_bindings::structs::mozilla; + context.chrome_rules_enabled() || + unsafe { mozilla::StaticPrefs_sVarCache_layout_css_clip_path_path_enabled } +} +#[cfg(feature = "servo")] +fn is_clip_path_path_enabled(_: &ParserContext) -> bool { + false +} + +impl Parse for ClippingShape { + #[inline] + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Self, ParseError<'i>> { + if is_clip_path_path_enabled(context) { + if let Ok(p) = input.try(|i| Path::parse(context, i)) { + return Ok(ShapeSource::Path(p)); + } + } + Self::parse_internal(context, input) + } +} + +impl Parse for FloatAreaShape { + #[inline] + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Self, ParseError<'i>> { + Self::parse_internal(context, input) + } +} + +impl<ReferenceBox, ImageOrUrl> ShapeSource<BasicShape, ReferenceBox, ImageOrUrl> where ReferenceBox: Parse, ImageOrUrl: Parse, { - fn parse<'i, 't>( + /// The internal parser for ShapeSource. + fn parse_internal<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { @@ -229,8 +268,7 @@ impl Ellipse { ShapeRadius::parse(context, i)?, ShapeRadius::parse(context, i)?, )) - }) - .unwrap_or_default(); + }).unwrap_or_default(); let position = if input.try(|i| i.expect_ident_matching("at")).is_ok() { Position::parse(context, input)? } else { @@ -377,11 +415,10 @@ impl Polygon { let fill = FillRule::parse(i)?; i.expect_comma()?; // only eat the comma if there is something before it Ok(fill) - }) - .unwrap_or_default(); + }).unwrap_or_default(); let buf = input.parse_comma_separated(|i| { - Ok(( + Ok(PolygonCoord( LengthOrPercentage::parse(context, i)?, LengthOrPercentage::parse(context, i)?, )) @@ -393,3 +430,30 @@ impl Polygon { }) } } + +impl Parse for Path { + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Self, ParseError<'i>> { + input.expect_function_matching("path")?; + input.parse_nested_block(|i| Self::parse_function_arguments(context, i)) + } +} + +impl Path { + /// Parse the inner arguments of a `path` function. + fn parse_function_arguments<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Self, ParseError<'i>> { + let fill = input + .try(|i| -> Result<_, ParseError> { + let fill = FillRule::parse(i)?; + i.expect_comma()?; + Ok(fill) + }).unwrap_or_default(); + let path = SVGPathData::parse(context, input)?; + Ok(Path { fill, path }) + } +} diff --git a/components/style/values/specified/border.rs b/components/style/values/specified/border.rs index 0713ed99eb9..7a681c2ef2c 100644 --- a/components/style/values/specified/border.rs +++ b/components/style/values/specified/border.rs @@ -189,8 +189,7 @@ impl Parse for BorderSpacing { /// A single border-image-repeat keyword. #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToCss)] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss)] pub enum BorderImageRepeatKeyword { Stretch, Repeat, @@ -201,8 +200,7 @@ pub enum BorderImageRepeatKeyword { /// The specified value for the `border-image-repeat` property. /// /// https://drafts.csswg.org/css-backgrounds/#the-border-image-repeat -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)] pub struct BorderImageRepeat(pub BorderImageRepeatKeyword, pub BorderImageRepeatKeyword); impl ToCss for BorderImageRepeat { diff --git a/components/style/values/specified/box.rs b/components/style/values/specified/box.rs index 6b474689df3..e23ec4a745a 100644 --- a/components/style/values/specified/box.rs +++ b/components/style/values/specified/box.rs @@ -21,26 +21,23 @@ use values::specified::length::{LengthOrPercentage, NonNegativeLength}; fn in_ua_or_chrome_sheet(context: &ParserContext) -> bool { use stylesheets::Origin; - context.stylesheet_origin == Origin::UserAgent || - context.chrome_rules_enabled() + context.stylesheet_origin == Origin::UserAgent || context.chrome_rules_enabled() } #[cfg(feature = "gecko")] fn moz_display_values_enabled(context: &ParserContext) -> bool { use gecko_bindings::structs; in_ua_or_chrome_sheet(context) || - unsafe { - structs::StaticPrefs_sVarCache_layout_css_xul_display_values_content_enabled - } + unsafe { structs::StaticPrefs_sVarCache_layout_css_xul_display_values_content_enabled } } #[cfg(feature = "gecko")] fn moz_box_display_values_enabled(context: &ParserContext) -> bool { use gecko_bindings::structs; in_ua_or_chrome_sheet(context) || - unsafe { - structs::StaticPrefs_sVarCache_layout_css_xul_box_display_values_content_enabled - } + unsafe { + structs::StaticPrefs_sVarCache_layout_css_xul_box_display_values_content_enabled + } } /// Defines an element’s display type, which consists of @@ -57,8 +54,20 @@ fn moz_box_display_values_enabled(context: &ParserContext) -> bool { /// Also, when you change this from Gecko you may need to regenerate the /// C++-side bindings (see components/style/cbindgen.toml). #[allow(missing_docs)] -#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Clone, + Copy, + Debug, + Eq, + FromPrimitive, + Hash, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[repr(u8)] pub enum Display { @@ -200,7 +209,10 @@ impl Display { pub fn is_ruby_type(&self) -> bool { matches!( *self, - Display::Ruby | Display::RubyBase | Display::RubyText | Display::RubyBaseContainer | + Display::Ruby | + Display::RubyBase | + Display::RubyText | + Display::RubyBaseContainer | Display::RubyTextContainer ) } @@ -346,8 +358,7 @@ impl AnimationIterationCount { } /// A value for the `animation-name` property. -#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue)] +#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)] #[value_info(other_values = "none")] pub struct AnimationName(pub Option<KeyframesName>); @@ -391,8 +402,18 @@ impl Parse for AnimationName { #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Clone, + Copy, + Debug, + Eq, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] pub enum ScrollSnapType { None, Mandatory, @@ -401,8 +422,18 @@ pub enum ScrollSnapType { #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Clone, + Copy, + Debug, + Eq, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] pub enum OverscrollBehavior { Auto, Contain, @@ -411,15 +442,24 @@ pub enum OverscrollBehavior { #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Clone, + Copy, + Debug, + Eq, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] pub enum OverflowClipBox { PaddingBox, ContentBox, } -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] /// Provides a rendering hint to the user agent, /// stating what kinds of changes the author expects /// to perform on the element @@ -497,11 +537,11 @@ fn change_bits_for_maybe_property(ident: &str, context: &ParserContext) -> WillC }; match id.as_shorthand() { - Ok(shorthand) => { - shorthand.longhands().fold(WillChangeBits::empty(), |flags, p| { + Ok(shorthand) => shorthand + .longhands() + .fold(WillChangeBits::empty(), |flags, p| { flags | change_bits_for_longhand(p) - }) - } + }), Err(PropertyDeclarationId::Longhand(longhand)) => change_bits_for_longhand(longhand), Err(PropertyDeclarationId::Custom(..)) => WillChangeBits::empty(), } @@ -581,9 +621,8 @@ impl ToCss for TouchAction { TouchAction::TOUCH_ACTION_NONE => dest.write_str("none"), TouchAction::TOUCH_ACTION_AUTO => dest.write_str("auto"), TouchAction::TOUCH_ACTION_MANIPULATION => dest.write_str("manipulation"), - _ if self.contains( - TouchAction::TOUCH_ACTION_PAN_X | TouchAction::TOUCH_ACTION_PAN_Y, - ) => + _ if self + .contains(TouchAction::TOUCH_ACTION_PAN_X | TouchAction::TOUCH_ACTION_PAN_Y) => { dest.write_str("pan-x pan-y") }, @@ -756,8 +795,7 @@ impl Parse for Perspective { return Ok(GenericPerspective::None); } Ok(GenericPerspective::Length(NonNegativeLength::parse( - context, - input, + context, input, )?)) } } @@ -789,7 +827,7 @@ impl ToCss for TransitionProperty { TransitionProperty::Custom(ref name) => { dest.write_str("--")?; serialize_atom_name(name, dest) - } + }, TransitionProperty::Unsupported(ref i) => i.to_css(dest), } } @@ -805,21 +843,21 @@ impl Parse for TransitionProperty { let id = match PropertyId::parse_ignoring_rule_type(&ident, context) { Ok(id) => id, - Err(..) => return Ok(TransitionProperty::Unsupported( - CustomIdent::from_ident(location, ident, &["none"])?, - )), + Err(..) => { + return Ok(TransitionProperty::Unsupported(CustomIdent::from_ident( + location, + ident, + &["none"], + )?)) + }, }; Ok(match id.as_shorthand() { Ok(s) => TransitionProperty::Shorthand(s), - Err(longhand_or_custom) => { - match longhand_or_custom { - PropertyDeclarationId::Longhand(id) => TransitionProperty::Longhand(id), - PropertyDeclarationId::Custom(custom) => { - TransitionProperty::Custom(custom.clone()) - } - } - } + Err(longhand_or_custom) => match longhand_or_custom { + PropertyDeclarationId::Longhand(id) => TransitionProperty::Longhand(id), + PropertyDeclarationId::Custom(custom) => TransitionProperty::Custom(custom.clone()), + }, }) } } @@ -846,19 +884,19 @@ impl TransitionProperty { Ok(match *self { TransitionProperty::Shorthand(ShorthandId::All) => { ::gecko_bindings::structs::nsCSSPropertyID::eCSSPropertyExtra_all_properties - } + }, TransitionProperty::Shorthand(ref id) => id.to_nscsspropertyid(), TransitionProperty::Longhand(ref id) => id.to_nscsspropertyid(), - TransitionProperty::Custom(..) | - TransitionProperty::Unsupported(..) => return Err(()), + TransitionProperty::Custom(..) | TransitionProperty::Unsupported(..) => return Err(()), }) } } #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToCss)] +#[derive( + Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, +)] /// https://drafts.csswg.org/css-box/#propdef-float pub enum Float { Left, @@ -866,13 +904,14 @@ pub enum Float { None, // https://drafts.csswg.org/css-logical-props/#float-clear InlineStart, - InlineEnd + InlineEnd, } #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToCss)] +#[derive( + Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, +)] /// https://drafts.csswg.org/css-box/#propdef-clear pub enum Clear { None, @@ -881,14 +920,15 @@ pub enum Clear { Both, // https://drafts.csswg.org/css-logical-props/#float-clear InlineStart, - InlineEnd + InlineEnd, } /// https://drafts.csswg.org/css-ui/#propdef-resize #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToCss)] +#[derive( + Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, +)] pub enum Resize { None, Both, @@ -906,8 +946,19 @@ pub enum Resize { /// NOTE(emilio): When changing this you may want to regenerate the C++ bindings /// (see components/style/cbindgen.toml) #[allow(missing_docs)] -#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToCss, ToComputedValue)] +#[derive( + Clone, + Copy, + Debug, + Eq, + Hash, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToCss, + ToComputedValue, +)] #[repr(u8)] pub enum Appearance { /// No appearance at all. diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index c05f0ddce0e..cce8f381806 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -89,11 +89,11 @@ impl<'a, 'b: 'a, 'i: 'a> ::cssparser::ColorComponentParser<'i> for ColorComponen }; Ok(AngleOrNumber::Angle { degrees }) - } + }, Token::Number { value, .. } => Ok(AngleOrNumber::Number { value }), Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { input.parse_nested_block(|i| CalcNode::parse_angle_or_number(self.0, i)) - } + }, t => return Err(location.new_unexpected_token_error(t)), } } @@ -120,10 +120,10 @@ impl<'a, 'b: 'a, 'i: 'a> ::cssparser::ColorComponentParser<'i> for ColorComponen Token::Number { value, .. } => Ok(NumberOrPercentage::Number { value }), Token::Percentage { unit_value, .. } => { Ok(NumberOrPercentage::Percentage { unit_value }) - } + }, Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { input.parse_nested_block(|i| CalcNode::parse_number_or_percentage(self.0, i)) - } + }, t => return Err(location.new_unexpected_token_error(t)), } } @@ -169,10 +169,10 @@ impl Parse for Color { Err(e.location.new_custom_error(StyleParseErrorKind::ValueError( ValueParseErrorKind::InvalidColor(t), ))) - } + }, _ => Err(e), } - } + }, } } } @@ -276,10 +276,10 @@ impl Color { } return parse_hash_color(ident.as_bytes()) .map_err(|()| location.new_custom_error(StyleParseErrorKind::UnspecifiedError)); - } + }, ref t => { return Err(location.new_unexpected_token_error(t.clone())); - } + }, }; if value < 0 { return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)); @@ -359,11 +359,11 @@ impl Color { Keyword::MozVisitedhyperlinktext => pres_context.mVisitedLinkColor, }) }) - } + }, #[cfg(feature = "gecko")] Color::InheritFromBodyQuirk => { _context.map(|context| ComputedColor::rgba(context.device().body_text_color())) - } + }, } } } diff --git a/components/style/values/specified/column.rs b/components/style/values/specified/column.rs index d065835423d..4cd8ad0777f 100644 --- a/components/style/values/specified/column.rs +++ b/components/style/values/specified/column.rs @@ -22,8 +22,7 @@ impl Parse for ColumnCount { return Ok(GenericColumnCount::Auto); } Ok(GenericColumnCount::Integer(PositiveInteger::parse( - context, - input, + context, input, )?)) } } diff --git a/components/style/values/specified/counters.rs b/components/style/values/specified/counters.rs index ea369f9dec7..ce7e3991227 100644 --- a/components/style/values/specified/counters.rs +++ b/components/style/values/specified/counters.rs @@ -93,8 +93,7 @@ impl Content { .try(|input| { input.expect_comma()?; ListStyleType::parse(input) - }) - .unwrap_or(ListStyleType::Decimal) + }).unwrap_or(ListStyleType::Decimal) } #[cfg(feature = "gecko")] @@ -103,8 +102,7 @@ impl Content { .try(|input| { input.expect_comma()?; CounterStyleOrNone::parse(context, input) - }) - .unwrap_or(CounterStyleOrNone::decimal()) + }).unwrap_or(CounterStyleOrNone::decimal()) } } diff --git a/components/style/values/specified/effects.rs b/components/style/values/specified/effects.rs index c3304b05af0..861414ca756 100644 --- a/components/style/values/specified/effects.rs +++ b/components/style/values/specified/effects.rs @@ -118,9 +118,9 @@ impl Parse for BoxShadow { let value = input.try::<_, _, ParseError>(|i| { let horizontal = Length::parse(context, i)?; let vertical = Length::parse(context, i)?; - let (blur, spread) = match i.try::<_, _, ParseError>(|i| { - Length::parse_non_negative(context, i) - }) { + let (blur, spread) = match i + .try::<_, _, ParseError>(|i| Length::parse_non_negative(context, i)) + { Ok(blur) => { let spread = i.try(|i| Length::parse(context, i)).ok(); (Some(blur.into()), spread) @@ -143,7 +143,8 @@ impl Parse for BoxShadow { break; } - let lengths = lengths.ok_or(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))?; + let lengths = + lengths.ok_or(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))?; Ok(BoxShadow { base: SimpleShadow { color: color, @@ -164,7 +165,8 @@ impl ToComputedValue for BoxShadow { fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { ComputedBoxShadow { base: self.base.to_computed_value(context), - spread: self.spread + spread: self + .spread .as_ref() .unwrap_or(&Length::zero()) .to_computed_value(context), @@ -271,13 +273,15 @@ impl ToComputedValue for SimpleShadow { #[inline] fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { ComputedSimpleShadow { - color: self.color + color: self + .color .as_ref() .unwrap_or(&Color::currentcolor()) .to_computed_value(context), horizontal: self.horizontal.to_computed_value(context), vertical: self.vertical.to_computed_value(context), - blur: self.blur + blur: self + .blur .as_ref() .unwrap_or(&NonNegativeLength::zero()) .to_computed_value(context), diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index 8d8355821e8..d9cf921bca5 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -148,9 +148,9 @@ impl ToComputedValue for FontWeight { #[inline] fn from_computed_value(computed: &computed::FontWeight) -> Self { - FontWeight::Absolute(AbsoluteFontWeight::Weight( - Number::from_computed_value(&computed.0) - )) + FontWeight::Absolute(AbsoluteFontWeight::Weight(Number::from_computed_value( + &computed.0, + ))) } } @@ -174,9 +174,7 @@ impl AbsoluteFontWeight { pub fn compute(&self) -> computed::FontWeight { match *self { AbsoluteFontWeight::Weight(weight) => { - computed::FontWeight( - weight.get().max(MIN_FONT_WEIGHT).min(MAX_FONT_WEIGHT) - ) + computed::FontWeight(weight.get().max(MIN_FONT_WEIGHT).min(MAX_FONT_WEIGHT)) }, AbsoluteFontWeight::Normal => computed::FontWeight::normal(), AbsoluteFontWeight::Bold => computed::FontWeight::bold(), @@ -194,12 +192,11 @@ impl Parse for AbsoluteFontWeight { // seem worth it just for a single property with such a weird range, // so we do the clamping here manually. if !number.was_calc() && - (number.get() < MIN_FONT_WEIGHT || number.get() > MAX_FONT_WEIGHT) { - return Err(input.new_custom_error( - StyleParseErrorKind::UnspecifiedError - )) + (number.get() < MIN_FONT_WEIGHT || number.get() > MAX_FONT_WEIGHT) + { + return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } - return Ok(AbsoluteFontWeight::Weight(number)) + return Ok(AbsoluteFontWeight::Weight(number)); } Ok(try_match_ident_ignore_ascii_case! { input, @@ -228,7 +225,7 @@ impl ToCss for SpecifiedFontStyle { angle.to_css(dest)?; } Ok(()) - } + }, } } } @@ -260,7 +257,7 @@ impl ToComputedValue for SpecifiedFontStyle { generics::FontStyle::Italic => generics::FontStyle::Italic, generics::FontStyle::Oblique(ref angle) => { generics::FontStyle::Oblique(FontStyleAngle(Self::compute_angle(angle))) - } + }, } } @@ -270,12 +267,11 @@ impl ToComputedValue for SpecifiedFontStyle { generics::FontStyle::Italic => generics::FontStyle::Italic, generics::FontStyle::Oblique(ref angle) => { generics::FontStyle::Oblique(Angle::from_computed_value(&angle.0)) - } + }, } } } - /// The default angle for `font-style: oblique`. /// /// NOTE(emilio): As of right now this diverges from the spec, which specifies @@ -299,9 +295,10 @@ impl SpecifiedFontStyle { /// Gets a clamped angle from a specified Angle. pub fn compute_angle(angle: &Angle) -> ComputedAngle { ComputedAngle::Deg( - angle.degrees() + angle + .degrees() .max(FONT_STYLE_OBLIQUE_MIN_ANGLE_DEGREES) - .min(FONT_STYLE_OBLIQUE_MAX_ANGLE_DEGREES) + .min(FONT_STYLE_OBLIQUE_MAX_ANGLE_DEGREES), ) } @@ -319,11 +316,9 @@ impl SpecifiedFontStyle { if degrees < FONT_STYLE_OBLIQUE_MIN_ANGLE_DEGREES || degrees > FONT_STYLE_OBLIQUE_MAX_ANGLE_DEGREES { - return Err(input.new_custom_error( - StyleParseErrorKind::UnspecifiedError - )); + return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } - return Ok(angle) + return Ok(angle); } /// The default angle for `font-style: oblique`. @@ -336,8 +331,7 @@ impl SpecifiedFontStyle { } /// The specified value of the `font-style` property. -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToCss)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)] #[allow(missing_docs)] pub enum FontStyle { Specified(SpecifiedFontStyle), @@ -375,7 +369,9 @@ impl Parse for FontStyle { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - Ok(FontStyle::Specified(SpecifiedFontStyle::parse(context, input)?)) + Ok(FontStyle::Specified(SpecifiedFontStyle::parse( + context, input, + )?)) } } @@ -383,8 +379,7 @@ impl Parse for FontStyle { /// /// https://drafts.csswg.org/css-fonts-4/#font-stretch-prop #[allow(missing_docs)] -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToCss)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)] pub enum FontStretch { Stretch(Percentage), Keyword(FontStretchKeyword), @@ -393,8 +388,7 @@ pub enum FontStretch { } /// A keyword value for `font-stretch`. -#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, - ToCss)] +#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss)] #[allow(missing_docs)] pub enum FontStretchKeyword { Normal, @@ -497,9 +491,7 @@ impl ToComputedValue for FontStretch { FontStretch::Stretch(ref percentage) => { computed::FontStretch(NonNegative(percentage.to_computed_value(context))) }, - FontStretch::Keyword(ref kw) => { - computed::FontStretch(NonNegative(kw.compute())) - }, + FontStretch::Keyword(ref kw) => computed::FontStretch(NonNegative(kw.compute())), FontStretch::System(_) => self.compute_system(context), } } @@ -690,8 +682,7 @@ impl Parse for FontSizeAdjust { } Ok(FontSizeAdjust::Number(Number::parse_non_negative( - context, - input, + context, input, )?)) } } @@ -906,10 +897,11 @@ impl FontSize { // new ones. // // This is enough of an edge case to not really matter. - let abs = calc.to_computed_value_zoomed( - context, - FontBaseSize::InheritedStyleButStripEmUnits, - ).length_component(); + let abs = calc + .to_computed_value_zoomed( + context, + FontBaseSize::InheritedStyleButStripEmUnits, + ).length_component(); info = parent.keyword_info.map(|i| i.compose(ratio, abs.into())); } @@ -1939,8 +1931,7 @@ impl Parse for FontFeatureSettings { } } -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)] /// Whether user agents are allowed to synthesize bold or oblique font faces /// when a font family lacks bold or italic faces pub struct FontSynthesis { @@ -2217,8 +2208,9 @@ impl Parse for VariationValue<Number> { } } -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive( + Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, +)] /// text-zoom. Enable if true, disable if false pub struct XTextZoom(#[css(skip)] pub bool); @@ -2235,8 +2227,7 @@ impl Parse for XTextZoom { } } -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] /// Internal property that reflects the lang attribute pub struct XLang(#[css(skip)] pub Atom); @@ -2324,8 +2315,7 @@ impl Parse for MozScriptLevel { } #[cfg_attr(feature = "gecko", derive(MallocSizeOf))] -#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToComputedValue, - ToCss)] +#[derive(Clone, Copy, Debug, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] /// Specifies the multiplier to be used to adjust font size /// due to changes in scriptlevel. /// diff --git a/components/style/values/specified/grid.rs b/components/style/values/specified/grid.rs index 830cccaf2e2..ad95264c595 100644 --- a/components/style/values/specified/grid.rs +++ b/components/style/values/specified/grid.rs @@ -22,7 +22,8 @@ pub fn parse_flex<'i, 't>(input: &mut Parser<'i, 't>) -> Result<CSSFloat, ParseE match *input.next()? { Token::Dimension { value, ref unit, .. - } if unit.eq_ignore_ascii_case("fr") && value.is_sign_positive() => + } + if unit.eq_ignore_ascii_case("fr") && value.is_sign_positive() => { Ok(value) }, @@ -76,7 +77,8 @@ impl Parse for TrackSize<LengthOrPercentage> { } input.expect_function_matching("fit-content")?; - let lop = input.parse_nested_block(|i| LengthOrPercentage::parse_non_negative(context, i))?; + let lop = + input.parse_nested_block(|i| LengthOrPercentage::parse_non_negative(context, i))?; Ok(TrackSize::FitContent(lop)) } } @@ -175,7 +177,9 @@ impl TrackRepeat<LengthOrPercentage, Integer> { } else { if values.is_empty() { // expecting at least one <track-size> - return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); + return Err( + input.new_custom_error(StyleParseErrorKind::UnspecifiedError) + ); } names.push(current_names); // final `<line-names>` @@ -217,9 +221,11 @@ impl Parse for TrackList<LengthOrPercentage, Integer> { // assume that everything is <fixed-size>. This flag is useful when we encounter <auto-repeat> let mut atleast_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(vec![].into_boxed_slice()), + ); if let Ok(track_size) = input.try(|i| TrackSize::parse(context, i)) { if !track_size.is_fixed() { atleast_one_not_fixed = true; @@ -244,13 +250,17 @@ impl Parse for TrackList<LengthOrPercentage, Integer> { atleast_one_not_fixed = true; if auto_repeat.is_some() { // only <fixed-repeat> - return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); + return Err( + input.new_custom_error(StyleParseErrorKind::UnspecifiedError) + ); } }, RepeatType::Auto => { if auto_repeat.is_some() || atleast_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)); + return Err( + input.new_custom_error(StyleParseErrorKind::UnspecifiedError) + ); } list_type = TrackListType::Auto(values.len() as u16 + auto_offset); @@ -342,7 +352,8 @@ impl ToComputedValue for TrackList<LengthOrPercentage, Integer> { list_type: self.list_type.to_computed_value(context), values: values, line_names: line_names.into_boxed_slice(), - auto_repeat: self.auto_repeat + auto_repeat: self + .auto_repeat .clone() .map(|repeat| repeat.to_computed_value(context)), } diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs index 64d24573f4a..1c0a613e488 100644 --- a/components/style/values/specified/image.rs +++ b/components/style/values/specified/image.rs @@ -55,19 +55,19 @@ impl SpecifiedValueInfo for Gradient { fn collect_completion_keywords(f: KeywordsCollectFn) { // This list here should keep sync with that in Gradient::parse. f(&[ - "linear-gradient", - "-webkit-linear-gradient", - "-moz-linear-gradient", - "repeating-linear-gradient", - "-webkit-repeating-linear-gradient", - "-moz-repeating-linear-gradient", - "radial-gradient", - "-webkit-radial-gradient", - "-moz-radial-gradient", - "repeating-radial-gradient", - "-webkit-repeating-radial-gradient", - "-moz-repeating-radial-gradient", - "-webkit-gradient", + "linear-gradient", + "-webkit-linear-gradient", + "-moz-linear-gradient", + "repeating-linear-gradient", + "-webkit-repeating-linear-gradient", + "-moz-repeating-linear-gradient", + "radial-gradient", + "-webkit-radial-gradient", + "-moz-radial-gradient", + "repeating-radial-gradient", + "-webkit-repeating-radial-gradient", + "-moz-repeating-radial-gradient", + "-webkit-gradient", ]); } } @@ -239,9 +239,9 @@ impl Parse for Gradient { #[cfg(feature = "gecko")] { use gecko_bindings::structs; - if compat_mode == CompatMode::Moz && !unsafe { - structs::StaticPrefs_sVarCache_layout_css_prefixes_gradients - } { + if compat_mode == CompatMode::Moz && + !unsafe { structs::StaticPrefs_sVarCache_layout_css_prefixes_gradients } + { return Err(input.new_custom_error(StyleParseErrorKind::UnexpectedFunction(func))); } } @@ -760,9 +760,9 @@ impl LineDirection { // There is no `to` keyword in webkit prefixed syntax. If it's consumed, // parsing should throw an error. CompatMode::WebKit if to_ident.is_ok() => { - return Err(i.new_custom_error(SelectorParseErrorKind::UnexpectedIdent( - "to".into(), - ))) + return Err( + i.new_custom_error(SelectorParseErrorKind::UnexpectedIdent("to".into())) + ) }, _ => {}, } @@ -969,8 +969,7 @@ impl Parse for PaintWorklet { .try(|input| { input.expect_comma()?; input.parse_comma_separated(|input| SpecifiedValue::parse(input)) - }) - .unwrap_or(vec![]); + }).unwrap_or(vec![]); Ok(PaintWorklet { name, arguments }) }) } diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index b6fe9bc2346..1b4efc4f00d 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -566,14 +566,16 @@ impl Length { match *token { Token::Dimension { value, ref unit, .. - } if num_context.is_ok(context.parsing_mode, value) => + } + if num_context.is_ok(context.parsing_mode, value) => { return NoCalcLength::parse_dimension(context, value, unit) .map(Length::NoCalc) .map_err(|()| location.new_unexpected_token_error(token.clone())) }, Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => { - if value != 0. && !context.parsing_mode.allows_unitless_lengths() && + if value != 0. && + !context.parsing_mode.allows_unitless_lengths() && !allow_quirks.allowed(context.quirks_mode) { return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)); @@ -753,7 +755,8 @@ impl LengthOrPercentage { match *token { Token::Dimension { value, ref unit, .. - } if num_context.is_ok(context.parsing_mode, value) => + } + if num_context.is_ok(context.parsing_mode, value) => { return NoCalcLength::parse_dimension(context, value, unit) .map(LengthOrPercentage::Length) @@ -767,7 +770,8 @@ impl LengthOrPercentage { ))) }, Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => { - if value != 0. && !context.parsing_mode.allows_unitless_lengths() && + if value != 0. && + !context.parsing_mode.allows_unitless_lengths() && !allow_quirks.allowed(context.quirks_mode) { return Err(location.new_unexpected_token_error(token.clone())); @@ -780,8 +784,9 @@ impl LengthOrPercentage { } } - let calc = input - .parse_nested_block(|i| CalcNode::parse_length_or_percentage(context, i, num_context))?; + let calc = input.parse_nested_block(|i| { + CalcNode::parse_length_or_percentage(context, i, num_context) + })?; Ok(LengthOrPercentage::Calc(Box::new(calc))) } @@ -871,7 +876,8 @@ impl LengthOrPercentageOrAuto { match *token { Token::Dimension { value, ref unit, .. - } if num_context.is_ok(context.parsing_mode, value) => + } + if num_context.is_ok(context.parsing_mode, value) => { return NoCalcLength::parse_dimension(context, value, unit) .map(LengthOrPercentageOrAuto::Length) @@ -885,7 +891,8 @@ impl LengthOrPercentageOrAuto { ))) }, Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => { - if value != 0. && !context.parsing_mode.allows_unitless_lengths() && + if value != 0. && + !context.parsing_mode.allows_unitless_lengths() && !allow_quirks.allowed(context.quirks_mode) { return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)); @@ -902,8 +909,9 @@ impl LengthOrPercentageOrAuto { } } - let calc = input - .parse_nested_block(|i| CalcNode::parse_length_or_percentage(context, i, num_context))?; + let calc = input.parse_nested_block(|i| { + CalcNode::parse_length_or_percentage(context, i, num_context) + })?; Ok(LengthOrPercentageOrAuto::Calc(Box::new(calc))) } @@ -998,8 +1006,7 @@ impl Parse for NonNegativeLengthOrPercentageOrAuto { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { Ok(NonNegative(LengthOrPercentageOrAuto::parse_non_negative( - context, - input, + context, input, )?)) } } @@ -1028,7 +1035,8 @@ impl LengthOrPercentageOrNone { match *token { Token::Dimension { value, ref unit, .. - } if num_context.is_ok(context.parsing_mode, value) => + } + if num_context.is_ok(context.parsing_mode, value) => { return NoCalcLength::parse_dimension(context, value, unit) .map(LengthOrPercentageOrNone::Length) @@ -1042,7 +1050,8 @@ impl LengthOrPercentageOrNone { ))) }, Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => { - if value != 0. && !context.parsing_mode.allows_unitless_lengths() && + if value != 0. && + !context.parsing_mode.allows_unitless_lengths() && !allow_quirks.allowed(context.quirks_mode) { return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)); @@ -1059,8 +1068,9 @@ impl LengthOrPercentageOrNone { } } - let calc = input - .parse_nested_block(|i| CalcNode::parse_length_or_percentage(context, i, num_context))?; + let calc = input.parse_nested_block(|i| { + CalcNode::parse_length_or_percentage(context, i, num_context) + })?; Ok(LengthOrPercentageOrNone::Calc(Box::new(calc))) } diff --git a/components/style/values/specified/list.rs b/components/style/values/specified/list.rs index ae61bb1ae9c..f1fba44b080 100644 --- a/components/style/values/specified/list.rs +++ b/components/style/values/specified/list.rs @@ -15,8 +15,7 @@ use values::generics::CounterStyleOrNone; /// Specified and computed `list-style-type` property. #[cfg(feature = "gecko")] -#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] pub enum ListStyleType { /// <counter-style> | none CounterStyle(CounterStyleOrNone), @@ -79,8 +78,7 @@ impl Parse for ListStyleType { /// FIXME(emilio): It's a shame that this allocates all the time it's computed, /// probably should just be refcounted. /// FIXME This can probably derive ToCss. -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)] pub struct Quotes(#[css(if_empty = "none")] pub Box<[(Box<str>, Box<str>)]>); impl ToCss for Quotes { diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 2da4c7e93d3..b8c2cd01fe9 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -58,6 +58,7 @@ pub use self::length::{NonNegativeLengthOrPercentage, NonNegativeLengthOrPercent pub use self::list::Quotes; #[cfg(feature = "gecko")] pub use self::list::ListStyleType; +pub use self::motion::OffsetPath; pub use self::outline::OutlineStyle; pub use self::rect::LengthOrNumberRect; pub use self::resolution::Resolution; @@ -67,6 +68,7 @@ pub use self::position::{PositionComponent, ZIndex}; pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind}; pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth}; pub use self::svg::MozContextProperties; +pub use self::svg_path::SVGPathData; pub use self::table::XSpan; pub use self::text::{InitialLetter, LetterSpacing, LineHeight, MozTabSize, TextAlign}; pub use self::text::{TextEmphasisPosition, TextEmphasisStyle}; @@ -100,6 +102,7 @@ pub mod grid; pub mod image; pub mod length; pub mod list; +pub mod motion; pub mod outline; pub mod percentage; pub mod position; @@ -107,6 +110,7 @@ pub mod rect; pub mod resolution; pub mod source_size_list; pub mod svg; +pub mod svg_path; pub mod table; pub mod text; pub mod time; @@ -147,8 +151,20 @@ fn parse_number_with_clamping_mode<'i, 't>( // FIXME(emilio): Should move to border.rs #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Ord, Parse, PartialEq, - PartialOrd, SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Clone, + Copy, + Debug, + Eq, + MallocSizeOf, + Ord, + Parse, + PartialEq, + PartialOrd, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] pub enum BorderStyle { None = -1, Solid = 6, @@ -326,8 +342,7 @@ impl Parse for GreaterThanOrEqualToOneNumber { /// /// FIXME(emilio): Should probably use Either. #[allow(missing_docs)] -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToCss)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)] pub enum NumberOrPercentage { Percentage(Percentage), Number(Number), @@ -365,8 +380,7 @@ impl Parse for NumberOrPercentage { } #[allow(missing_docs)] -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, - SpecifiedValueInfo, ToCss)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, SpecifiedValueInfo, ToCss)] pub struct Opacity(Number); impl Parse for Opacity { @@ -626,13 +640,16 @@ impl ToComputedValue for ClipRect { fn to_computed_value(&self, context: &Context) -> super::computed::ClipRect { super::computed::ClipRect { top: self.top.as_ref().map(|top| top.to_computed_value(context)), - right: self.right + right: self + .right .as_ref() .map(|right| right.to_computed_value(context)), - bottom: self.bottom + bottom: self + .bottom .as_ref() .map(|bottom| bottom.to_computed_value(context)), - left: self.left + left: self + .left .as_ref() .map(|left| left.to_computed_value(context)), } @@ -756,8 +773,7 @@ impl AllowQuirks { /// An attr(...) rule /// /// `[namespace? `|`]? ident` -#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue)] +#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)] #[css(function)] pub struct Attr { /// Optional namespace prefix and URL. @@ -810,7 +826,10 @@ impl Attr { let prefix = Prefix::from(ns.as_ref()); let ns = match get_namespace_for_prefix(&prefix, context) { Some(ns) => ns, - None => return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)), + None => { + return Err(location + .new_custom_error(StyleParseErrorKind::UnspecifiedError)) + }, }; Some((prefix, ns)) } else { diff --git a/components/style/values/specified/motion.rs b/components/style/values/specified/motion.rs new file mode 100644 index 00000000000..b591d43a2bb --- /dev/null +++ b/components/style/values/specified/motion.rs @@ -0,0 +1,73 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! Specified types for CSS values that are related to motion path. + +use cssparser::Parser; +use parser::{Parse, ParserContext}; +use style_traits::{ParseError, StyleParseErrorKind}; +use values::specified::SVGPathData; + +/// The offset-path value. +/// +/// https://drafts.fxtf.org/motion-1/#offset-path-property +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedZero, + ToComputedValue, + ToCss, +)] +pub enum OffsetPath { + // We could merge SVGPathData into ShapeSource, so we could reuse them. However, + // we don't want to support other value for offset-path, so use SVGPathData only for now. + /// Path value for path(<string>). + #[css(function)] + Path(SVGPathData), + /// None value. + #[animation(error)] + None, + // Bug 1186329: Implement ray(), <basic-shape>, <geometry-box>, and <url>. +} + +impl OffsetPath { + /// Return None. + #[inline] + pub fn none() -> Self { + OffsetPath::None + } +} + +impl Parse for OffsetPath { + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Self, ParseError<'i>> { + // Parse none. + if input.try(|i| i.expect_ident_matching("none")).is_ok() { + return Ok(OffsetPath::none()); + } + + // Parse possible functions. + let location = input.current_source_location(); + let function = input.expect_function()?.clone(); + input.parse_nested_block(move |i| { + match_ignore_ascii_case! { &function, + // Bug 1186329: Implement the parser for ray(), <basic-shape>, <geometry-box>, + // and <url>. + "path" => SVGPathData::parse(context, i).map(OffsetPath::Path), + _ => { + Err(location.new_custom_error( + StyleParseErrorKind::UnexpectedFunction(function.clone()) + )) + }, + } + }) + } +} diff --git a/components/style/values/specified/outline.rs b/components/style/values/specified/outline.rs index c3357f87ec2..afe74dc39f3 100644 --- a/components/style/values/specified/outline.rs +++ b/components/style/values/specified/outline.rs @@ -10,8 +10,19 @@ use selectors::parser::SelectorParseErrorKind; use style_traits::ParseError; use values::specified::BorderStyle; -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Ord, PartialEq, PartialOrd, - SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Clone, + Copy, + Debug, + Eq, + MallocSizeOf, + Ord, + PartialEq, + PartialOrd, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] /// <https://drafts.csswg.org/css-ui/#propdef-outline-style> pub enum OutlineStyle { /// auto diff --git a/components/style/values/specified/position.rs b/components/style/values/specified/position.rs index fcfa07ae1d8..6117436695f 100644 --- a/components/style/values/specified/position.rs +++ b/components/style/values/specified/position.rs @@ -45,8 +45,19 @@ pub enum PositionComponent<S> { } /// A keyword for the X direction. -#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Clone, + Copy, + Debug, + Eq, + Hash, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] #[allow(missing_docs)] pub enum X { Left, @@ -54,8 +65,19 @@ pub enum X { } /// A keyword for the Y direction. -#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Clone, + Copy, + Debug, + Eq, + Hash, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] #[allow(missing_docs)] pub enum Y { Top, @@ -128,10 +150,12 @@ impl Position { } let y_keyword = Y::parse(input)?; let lop_and_x_pos: Result<_, ParseError> = input.try(|i| { - let y_lop = i.try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) + let y_lop = i + .try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) .ok(); if let Ok(x_keyword) = i.try(X::parse) { - let x_lop = i.try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) + let x_lop = i + .try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) .ok(); let x_pos = PositionComponent::Side(x_keyword, x_lop); return Ok((y_lop, x_pos)); @@ -411,8 +435,9 @@ impl ToCss for LegacyPosition { } } -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive( + Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, +)] /// Auto-placement algorithm Option pub enum AutoFlow { /// The auto-placement algorithm places items by filling each row in turn, @@ -423,8 +448,9 @@ pub enum AutoFlow { Column, } -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive( + Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, +)] /// Controls how the auto-placement algorithm works /// specifying exactly how auto-placed items get flowed into the grid pub struct GridAutoFlow { @@ -630,8 +656,7 @@ impl Parse for TemplateAreas { } /// Arc type for `Arc<TemplateAreas>` -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] pub struct TemplateAreasArc(#[ignore_malloc_size_of = "Arc"] pub Arc<TemplateAreas>); impl Parse for TemplateAreasArc { @@ -685,8 +710,12 @@ impl<'a> Iterator for TemplateAreasTokenizer<'a> { } fn is_name_code_point(c: char) -> bool { - c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c >= '\u{80}' || c == '_' || - c >= '0' && c <= '9' || c == '-' + c >= 'A' && c <= 'Z' || + c >= 'a' && c <= 'z' || + c >= '\u{80}' || + c == '_' || + c >= '0' && c <= '9' || + c == '-' } /// This property specifies named grid areas. diff --git a/components/style/values/specified/resolution.rs b/components/style/values/specified/resolution.rs index 77a269c251b..0878c776272 100644 --- a/components/style/values/specified/resolution.rs +++ b/components/style/values/specified/resolution.rs @@ -32,8 +32,7 @@ impl Resolution { /// Convert this resolution value to dppx units. pub fn to_dppx(&self) -> CSSFloat { match *self { - Resolution::X(f) | - Resolution::Dppx(f) => f, + Resolution::X(f) | Resolution::Dppx(f) => f, _ => self.to_dpi() / 96.0, } } @@ -42,8 +41,7 @@ impl Resolution { pub fn to_dpi(&self) -> CSSFloat { match *self { Resolution::Dpi(f) => f, - Resolution::X(f) | - Resolution::Dppx(f) => f * 96.0, + Resolution::X(f) | Resolution::Dppx(f) => f * 96.0, Resolution::Dpcm(f) => f * 2.54, } } diff --git a/components/style/values/specified/source_size_list.rs b/components/style/values/specified/source_size_list.rs index 33078c06484..2d86d5a058f 100644 --- a/components/style/values/specified/source_size_list.rs +++ b/components/style/values/specified/source_size_list.rs @@ -61,7 +61,8 @@ impl SourceSizeList { /// Evaluate this <source-size-list> to get the final viewport length. pub fn evaluate(&self, device: &Device, quirks_mode: QuirksMode) -> Au { - let matching_source_size = self.source_sizes + let matching_source_size = self + .source_sizes .iter() .find(|source_size| source_size.condition.matches(device, quirks_mode)); diff --git a/components/style/values/specified/svg.rs b/components/style/values/specified/svg.rs index e55442d7da8..f91ac511af1 100644 --- a/components/style/values/specified/svg.rs +++ b/components/style/values/specified/svg.rs @@ -173,8 +173,7 @@ const PAINT_ORDER_MASK: u8 = 0b11; /// /// Higher priority values, i.e. the values specified first, /// will be painted first (and may be covered by paintings of lower priority) -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)] pub struct SVGPaintOrder(pub u8); impl SVGPaintOrder { @@ -281,8 +280,7 @@ impl ToCss for SVGPaintOrder { /// Specified MozContextProperties value. /// Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-context-properties) -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] pub struct MozContextProperties(pub CustomIdent); impl Parse for MozContextProperties { diff --git a/components/style/values/specified/svg_path.rs b/components/style/values/specified/svg_path.rs new file mode 100644 index 00000000000..f0973b545a5 --- /dev/null +++ b/components/style/values/specified/svg_path.rs @@ -0,0 +1,863 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! Specified types for SVG Path. + +use cssparser::Parser; +use parser::{Parse, ParserContext}; +use std::fmt::{self, Write}; +use std::iter::{Cloned, Peekable}; +use std::ops::AddAssign; +use std::slice; +use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; +use style_traits::values::SequenceWriter; +use values::CSSFloat; +use values::animated::{Animate, Procedure}; +use values::distance::{ComputeSquaredDistance, SquaredDistance}; + +/// The SVG path data. +/// +/// https://www.w3.org/TR/SVG11/paths.html#PathData +#[derive( + Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToAnimatedZero, ToComputedValue, +)] +pub struct SVGPathData(Box<[PathCommand]>); + +impl SVGPathData { + /// Return SVGPathData by a slice of PathCommand. + #[inline] + pub fn new(cmd: Box<[PathCommand]>) -> Self { + debug_assert!(!cmd.is_empty()); + SVGPathData(cmd) + } + + /// Get the array of PathCommand. + #[inline] + pub fn commands(&self) -> &[PathCommand] { + debug_assert!(!self.0.is_empty()); + &self.0 + } + + /// Create a normalized copy of this path by converting each relative command to an absolute + /// command. + fn normalize(&self) -> Self { + let mut state = PathTraversalState { + subpath_start: CoordPair::new(0.0, 0.0), + pos: CoordPair::new(0.0, 0.0), + }; + let result = self + .0 + .iter() + .map(|seg| seg.normalize(&mut state)) + .collect::<Vec<_>>(); + SVGPathData(result.into_boxed_slice()) + } +} + +impl ToCss for SVGPathData { + #[inline] + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result + where + W: fmt::Write, + { + dest.write_char('"')?; + { + let mut writer = SequenceWriter::new(dest, " "); + for command in self.0.iter() { + writer.item(command)?; + } + } + dest.write_char('"') + } +} + +impl Parse for SVGPathData { + // We cannot use cssparser::Parser to parse a SVG path string because the spec wants to make + // the SVG path string as compact as possible. (i.e. The whitespaces may be dropped.) + // e.g. "M100 200L100 200" is a valid SVG path string. If we use tokenizer, the first ident + // is "M100", instead of "M", and this is not correct. Therefore, we use a Peekable + // str::Char iterator to check each character. + fn parse<'i, 't>( + _context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Self, ParseError<'i>> { + let location = input.current_source_location(); + let path_string = input.expect_string()?.as_ref(); + if path_string.is_empty() { + // Treat an empty string as invalid, so we will not set it. + return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)); + } + + // Parse the svg path string as multiple sub-paths. + let mut path_parser = PathParser::new(path_string); + while skip_wsp(&mut path_parser.chars) { + if path_parser.parse_subpath().is_err() { + return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)); + } + } + + Ok(SVGPathData::new(path_parser.path.into_boxed_slice())) + } +} + +impl Animate for SVGPathData { + fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> { + if self.0.len() != other.0.len() { + return Err(()); + } + + let result = self + .normalize() + .0 + .iter() + .zip(other.normalize().0.iter()) + .map(|(a, b)| a.animate(&b, procedure)) + .collect::<Result<Vec<_>, _>>()?; + Ok(SVGPathData::new(result.into_boxed_slice())) + } +} + +impl ComputeSquaredDistance for SVGPathData { + fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> { + if self.0.len() != other.0.len() { + return Err(()); + } + self.normalize() + .0 + .iter() + .zip(other.normalize().0.iter()) + .map(|(this, other)| this.compute_squared_distance(&other)) + .sum() + } +} + +/// The SVG path command. +/// The fields of these commands are self-explanatory, so we skip the documents. +/// Note: the index of the control points, e.g. control1, control2, are mapping to the control +/// points of the Bézier curve in the spec. +/// +/// https://www.w3.org/TR/SVG11/paths.html#PathData +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedZero, +)] +#[allow(missing_docs)] +#[repr(C, u8)] +pub enum PathCommand { + /// The unknown type. + /// https://www.w3.org/TR/SVG/paths.html#__svg__SVGPathSeg__PATHSEG_UNKNOWN + Unknown, + /// The "moveto" command. + MoveTo { + point: CoordPair, + absolute: IsAbsolute, + }, + /// The "lineto" command. + LineTo { + point: CoordPair, + absolute: IsAbsolute, + }, + /// The horizontal "lineto" command. + HorizontalLineTo { x: CSSFloat, absolute: IsAbsolute }, + /// The vertical "lineto" command. + VerticalLineTo { y: CSSFloat, absolute: IsAbsolute }, + /// The cubic Bézier curve command. + CurveTo { + control1: CoordPair, + control2: CoordPair, + point: CoordPair, + absolute: IsAbsolute, + }, + /// The smooth curve command. + SmoothCurveTo { + control2: CoordPair, + point: CoordPair, + absolute: IsAbsolute, + }, + /// The quadratic Bézier curve command. + QuadBezierCurveTo { + control1: CoordPair, + point: CoordPair, + absolute: IsAbsolute, + }, + /// The smooth quadratic Bézier curve command. + SmoothQuadBezierCurveTo { + point: CoordPair, + absolute: IsAbsolute, + }, + /// The elliptical arc curve command. + EllipticalArc { + rx: CSSFloat, + ry: CSSFloat, + angle: CSSFloat, + #[animation(constant)] + large_arc_flag: ArcFlag, + #[animation(constant)] + sweep_flag: ArcFlag, + point: CoordPair, + absolute: IsAbsolute, + }, + /// The "closepath" command. + ClosePath, +} + +/// For internal SVGPath normalization. +#[allow(missing_docs)] +struct PathTraversalState { + subpath_start: CoordPair, + pos: CoordPair, +} + +impl PathCommand { + /// Create a normalized copy of this PathCommand. Absolute commands will be copied as-is while + /// for relative commands an equivalent absolute command will be returned. + /// + /// See discussion: https://github.com/w3c/svgwg/issues/321 + fn normalize(&self, state: &mut PathTraversalState) -> Self { + use self::PathCommand::*; + match *self { + Unknown => Unknown, + ClosePath => { + state.pos = state.subpath_start; + ClosePath + }, + MoveTo { + mut point, + absolute, + } => { + if !absolute.is_yes() { + point += state.pos; + } + state.pos = point; + state.subpath_start = point; + MoveTo { + point, + absolute: IsAbsolute::Yes, + } + }, + LineTo { + mut point, + absolute, + } => { + if !absolute.is_yes() { + point += state.pos; + } + state.pos = point; + LineTo { + point, + absolute: IsAbsolute::Yes, + } + }, + HorizontalLineTo { mut x, absolute } => { + if !absolute.is_yes() { + x += state.pos.0; + } + state.pos.0 = x; + HorizontalLineTo { + x, + absolute: IsAbsolute::Yes, + } + }, + VerticalLineTo { mut y, absolute } => { + if !absolute.is_yes() { + y += state.pos.1; + } + state.pos.1 = y; + VerticalLineTo { + y, + absolute: IsAbsolute::Yes, + } + }, + CurveTo { + mut control1, + mut control2, + mut point, + absolute, + } => { + if !absolute.is_yes() { + control1 += state.pos; + control2 += state.pos; + point += state.pos; + } + state.pos = point; + CurveTo { + control1, + control2, + point, + absolute: IsAbsolute::Yes, + } + }, + SmoothCurveTo { + mut control2, + mut point, + absolute, + } => { + if !absolute.is_yes() { + control2 += state.pos; + point += state.pos; + } + state.pos = point; + SmoothCurveTo { + control2, + point, + absolute: IsAbsolute::Yes, + } + }, + QuadBezierCurveTo { + mut control1, + mut point, + absolute, + } => { + if !absolute.is_yes() { + control1 += state.pos; + point += state.pos; + } + state.pos = point; + QuadBezierCurveTo { + control1, + point, + absolute: IsAbsolute::Yes, + } + }, + SmoothQuadBezierCurveTo { + mut point, + absolute, + } => { + if !absolute.is_yes() { + point += state.pos; + } + state.pos = point; + SmoothQuadBezierCurveTo { + point, + absolute: IsAbsolute::Yes, + } + }, + EllipticalArc { + rx, + ry, + angle, + large_arc_flag, + sweep_flag, + mut point, + absolute, + } => { + if !absolute.is_yes() { + point += state.pos; + } + state.pos = point; + EllipticalArc { + rx, + ry, + angle, + large_arc_flag, + sweep_flag, + point, + absolute: IsAbsolute::Yes, + } + }, + } + } +} + +impl ToCss for PathCommand { + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result + where + W: fmt::Write, + { + use self::PathCommand::*; + match *self { + Unknown => dest.write_char('X'), + ClosePath => dest.write_char('Z'), + MoveTo { point, absolute } => { + dest.write_char(if absolute.is_yes() { 'M' } else { 'm' })?; + dest.write_char(' ')?; + point.to_css(dest) + }, + LineTo { point, absolute } => { + dest.write_char(if absolute.is_yes() { 'L' } else { 'l' })?; + dest.write_char(' ')?; + point.to_css(dest) + }, + CurveTo { + control1, + control2, + point, + absolute, + } => { + dest.write_char(if absolute.is_yes() { 'C' } else { 'c' })?; + dest.write_char(' ')?; + control1.to_css(dest)?; + dest.write_char(' ')?; + control2.to_css(dest)?; + dest.write_char(' ')?; + point.to_css(dest) + }, + QuadBezierCurveTo { + control1, + point, + absolute, + } => { + dest.write_char(if absolute.is_yes() { 'Q' } else { 'q' })?; + dest.write_char(' ')?; + control1.to_css(dest)?; + dest.write_char(' ')?; + point.to_css(dest) + }, + EllipticalArc { + rx, + ry, + angle, + large_arc_flag, + sweep_flag, + point, + absolute, + } => { + dest.write_char(if absolute.is_yes() { 'A' } else { 'a' })?; + dest.write_char(' ')?; + rx.to_css(dest)?; + dest.write_char(' ')?; + ry.to_css(dest)?; + dest.write_char(' ')?; + angle.to_css(dest)?; + dest.write_char(' ')?; + large_arc_flag.to_css(dest)?; + dest.write_char(' ')?; + sweep_flag.to_css(dest)?; + dest.write_char(' ')?; + point.to_css(dest) + }, + HorizontalLineTo { x, absolute } => { + dest.write_char(if absolute.is_yes() { 'H' } else { 'h' })?; + dest.write_char(' ')?; + x.to_css(dest) + }, + VerticalLineTo { y, absolute } => { + dest.write_char(if absolute.is_yes() { 'V' } else { 'v' })?; + dest.write_char(' ')?; + y.to_css(dest) + }, + SmoothCurveTo { + control2, + point, + absolute, + } => { + dest.write_char(if absolute.is_yes() { 'S' } else { 's' })?; + dest.write_char(' ')?; + control2.to_css(dest)?; + dest.write_char(' ')?; + point.to_css(dest) + }, + SmoothQuadBezierCurveTo { point, absolute } => { + dest.write_char(if absolute.is_yes() { 'T' } else { 't' })?; + dest.write_char(' ')?; + point.to_css(dest) + }, + } + } +} + +/// The path command absolute type. +#[allow(missing_docs)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedZero, +)] +#[repr(u8)] +pub enum IsAbsolute { + Yes, + No, +} + +impl IsAbsolute { + /// Return true if this is IsAbsolute::Yes. + #[inline] + pub fn is_yes(&self) -> bool { + *self == IsAbsolute::Yes + } +} + +/// The path coord type. +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedZero, + ToCss, +)] +#[repr(C)] +pub struct CoordPair(CSSFloat, CSSFloat); + +impl CoordPair { + /// Create a CoordPair. + #[inline] + pub fn new(x: CSSFloat, y: CSSFloat) -> Self { + CoordPair(x, y) + } +} + +impl AddAssign for CoordPair { + #[inline] + fn add_assign(&mut self, other: Self) { + self.0 += other.0; + self.1 += other.1; + } +} + +/// The EllipticalArc flag type. +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo)] +#[repr(C)] +pub struct ArcFlag(bool); + +impl ToCss for ArcFlag { + #[inline] + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result + where + W: fmt::Write, + { + (self.0 as i32).to_css(dest) + } +} + +impl ComputeSquaredDistance for ArcFlag { + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> { + (self.0 as i32).compute_squared_distance(&(other.0 as i32)) + } +} + +/// SVG Path parser. +struct PathParser<'a> { + chars: Peekable<Cloned<slice::Iter<'a, u8>>>, + path: Vec<PathCommand>, +} + +macro_rules! parse_arguments { + ( + $parser:ident, + $abs:ident, + $enum:ident, + [ $para:ident => $func:ident $(, $other_para:ident => $other_func:ident)* ] + ) => { + { + loop { + let $para = $func(&mut $parser.chars)?; + $( + skip_comma_wsp(&mut $parser.chars); + let $other_para = $other_func(&mut $parser.chars)?; + )* + $parser.path.push(PathCommand::$enum { $para $(, $other_para)*, $abs }); + + // End of string or the next character is a possible new command. + if !skip_wsp(&mut $parser.chars) || + $parser.chars.peek().map_or(true, |c| c.is_ascii_alphabetic()) { + break; + } + skip_comma_wsp(&mut $parser.chars); + } + Ok(()) + } + } +} + +impl<'a> PathParser<'a> { + /// Return a PathParser. + #[inline] + fn new(string: &'a str) -> Self { + PathParser { + chars: string.as_bytes().iter().cloned().peekable(), + path: Vec::new(), + } + } + + /// Parse a sub-path. + fn parse_subpath(&mut self) -> Result<(), ()> { + // Handle "moveto" Command first. If there is no "moveto", this is not a valid sub-path + // (i.e. not a valid moveto-drawto-command-group). + self.parse_moveto()?; + + // Handle other commands. + loop { + skip_wsp(&mut self.chars); + if self.chars.peek().map_or(true, |&m| m == b'M' || m == b'm') { + 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. + } + } + Ok(()) + } + + /// Parse "moveto" command. + fn parse_moveto(&mut self) -> Result<(), ()> { + let command = match self.chars.next() { + Some(c) if c == b'M' || c == b'm' => c, + _ => return Err(()), + }; + + skip_wsp(&mut self.chars); + let point = parse_coord(&mut self.chars)?; + let absolute = if command == b'M' { + IsAbsolute::Yes + } else { + IsAbsolute::No + }; + self.path.push(PathCommand::MoveTo { point, absolute }); + + // End of string or the next character is a possible new command. + if !skip_wsp(&mut self.chars) || self.chars.peek().map_or(true, |c| c.is_ascii_alphabetic()) + { + return Ok(()); + } + skip_comma_wsp(&mut self.chars); + + // If a moveto is followed by multiple pairs of coordinates, the subsequent + // pairs are treated as implicit lineto commands. + self.parse_lineto(absolute) + } + + /// Parse "closepath" command. + fn parse_closepath(&mut self, _absolute: IsAbsolute) -> Result<(), ()> { + self.path.push(PathCommand::ClosePath); + Ok(()) + } + + /// Parse "lineto" command. + fn parse_lineto(&mut self, absolute: IsAbsolute) -> Result<(), ()> { + parse_arguments!(self, absolute, LineTo, [ point => parse_coord ]) + } + + /// Parse horizontal "lineto" command. + fn parse_h_lineto(&mut self, absolute: IsAbsolute) -> Result<(), ()> { + parse_arguments!(self, absolute, HorizontalLineTo, [ x => parse_number ]) + } + + /// Parse vertical "lineto" command. + fn parse_v_lineto(&mut self, absolute: IsAbsolute) -> Result<(), ()> { + parse_arguments!(self, absolute, VerticalLineTo, [ y => parse_number ]) + } + + /// Parse cubic Bézier curve command. + fn parse_curveto(&mut self, absolute: IsAbsolute) -> Result<(), ()> { + parse_arguments!(self, absolute, CurveTo, [ + control1 => parse_coord, control2 => parse_coord, point => parse_coord + ]) + } + + /// Parse smooth "curveto" command. + fn parse_smooth_curveto(&mut self, absolute: IsAbsolute) -> Result<(), ()> { + parse_arguments!(self, absolute, SmoothCurveTo, [ + control2 => parse_coord, point => parse_coord + ]) + } + + /// Parse quadratic Bézier curve command. + fn parse_quadratic_bezier_curveto(&mut self, absolute: IsAbsolute) -> Result<(), ()> { + parse_arguments!(self, absolute, QuadBezierCurveTo, [ + control1 => parse_coord, point => parse_coord + ]) + } + + /// Parse smooth quadratic Bézier curveto command. + fn parse_smooth_quadratic_bezier_curveto(&mut self, absolute: IsAbsolute) -> Result<(), ()> { + parse_arguments!(self, absolute, SmoothQuadBezierCurveTo, [ point => parse_coord ]) + } + + /// Parse elliptical arc curve command. + fn parse_elliptical_arc(&mut self, absolute: IsAbsolute) -> Result<(), ()> { + // Parse a flag whose value is '0' or '1'; otherwise, return Err(()). + let parse_flag = |iter: &mut Peekable<Cloned<slice::Iter<u8>>>| match iter.next() { + Some(c) if c == b'0' || c == b'1' => Ok(ArcFlag(c == b'1')), + _ => Err(()), + }; + parse_arguments!(self, absolute, EllipticalArc, [ + rx => parse_number, + ry => parse_number, + angle => parse_number, + large_arc_flag => parse_flag, + sweep_flag => parse_flag, + point => parse_coord + ]) + } +} + +/// Parse a pair of numbers into CoordPair. +fn parse_coord(iter: &mut Peekable<Cloned<slice::Iter<u8>>>) -> Result<CoordPair, ()> { + let x = parse_number(iter)?; + skip_comma_wsp(iter); + let y = parse_number(iter)?; + Ok(CoordPair::new(x, y)) +} + +/// This is a special version which parses the number for SVG Path. e.g. "M 0.6.5" should be parsed +/// as MoveTo with a coordinate of ("0.6", ".5"), instead of treating 0.6.5 as a non-valid floating +/// point number. In other words, the logic here is similar with that of +/// tokenizer::consume_numeric, which also consumes the number as many as possible, but here the +/// input is a Peekable and we only accept an integer of a floating point number. +/// +/// The "number" syntax in https://www.w3.org/TR/SVG/paths.html#PathDataBNF +fn parse_number(iter: &mut Peekable<Cloned<slice::Iter<u8>>>) -> Result<CSSFloat, ()> { + // 1. Check optional sign. + let sign = if iter + .peek() + .map_or(false, |&sign| sign == b'+' || sign == b'-') + { + if iter.next().unwrap() == b'-' { + -1. + } else { + 1. + } + } else { + 1. + }; + + // 2. Check integer part. + let mut integral_part: f64 = 0.; + let got_dot = if !iter.peek().map_or(false, |&n| n == b'.') { + // If the first digit in integer part is neither a dot nor a digit, this is not a number. + if iter.peek().map_or(true, |n| !n.is_ascii_digit()) { + return Err(()); + } + + while iter.peek().map_or(false, |n| n.is_ascii_digit()) { + integral_part = integral_part * 10. + (iter.next().unwrap() - b'0') as f64; + } + + iter.peek().map_or(false, |&n| n == b'.') + } else { + true + }; + + // 3. Check fractional part. + let mut fractional_part: f64 = 0.; + if got_dot { + // Consume '.'. + iter.next(); + // If the first digit in fractional part is not a digit, this is not a number. + if iter.peek().map_or(true, |n| !n.is_ascii_digit()) { + return Err(()); + } + + let mut factor = 0.1; + while iter.peek().map_or(false, |n| n.is_ascii_digit()) { + fractional_part += (iter.next().unwrap() - b'0') as f64 * factor; + factor *= 0.1; + } + } + + let mut value = sign * (integral_part + fractional_part); + + // 4. Check exp part. The segment name of SVG Path doesn't include 'E' or 'e', so it's ok to + // treat the numbers after 'E' or 'e' are in the exponential part. + if iter.peek().map_or(false, |&exp| exp == b'E' || exp == b'e') { + // Consume 'E' or 'e'. + iter.next(); + let exp_sign = if iter + .peek() + .map_or(false, |&sign| sign == b'+' || sign == b'-') + { + if iter.next().unwrap() == b'-' { + -1. + } else { + 1. + } + } else { + 1. + }; + + let mut exp: f64 = 0.; + while iter.peek().map_or(false, |n| n.is_ascii_digit()) { + exp = exp * 10. + (iter.next().unwrap() - b'0') as f64; + } + + value *= f64::powf(10., exp * exp_sign); + } + + if value.is_finite() { + Ok(value + .min(::std::f32::MAX as f64) + .max(::std::f32::MIN as f64) as CSSFloat) + } else { + Err(()) + } +} + +/// Skip all svg whitespaces, and return true if |iter| hasn't finished. +#[inline] +fn skip_wsp(iter: &mut Peekable<Cloned<slice::Iter<u8>>>) -> bool { + // Note: SVG 1.1 defines the whitespaces as \u{9}, \u{20}, \u{A}, \u{D}. + // However, SVG 2 has one extra whitespace: \u{C}. + // Therefore, we follow the newest spec for the definition of whitespace, + // i.e. \u{9}, \u{20}, \u{A}, \u{C}, \u{D}. + while iter.peek().map_or(false, |c| c.is_ascii_whitespace()) { + iter.next(); + } + iter.peek().is_some() +} + +/// Skip all svg whitespaces and one comma, and return true if |iter| hasn't finished. +#[inline] +fn skip_comma_wsp(iter: &mut Peekable<Cloned<slice::Iter<u8>>>) -> bool { + if !skip_wsp(iter) { + return false; + } + + if *iter.peek().unwrap() != b',' { + return true; + } + iter.next(); + + skip_wsp(iter) +} diff --git a/components/style/values/specified/table.rs b/components/style/values/specified/table.rs index 085c9adc9d8..0dd0755f95a 100644 --- a/components/style/values/specified/table.rs +++ b/components/style/values/specified/table.rs @@ -8,8 +8,9 @@ use cssparser::Parser; use parser::{Parse, ParserContext}; use style_traits::{ParseError, StyleParseErrorKind}; -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive( + Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, +)] /// span. for `<col span>` pres attr pub struct XSpan(#[css(skip)] pub i32); diff --git a/components/style/values/specified/text.rs b/components/style/values/specified/text.rs index ae01040e45f..adeab96c984 100644 --- a/components/style/values/specified/text.rs +++ b/components/style/values/specified/text.rs @@ -94,7 +94,10 @@ impl Parse for LineHeight { { Ok(GenericLineHeight::MozBlockHeight) }, - ident => Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone()))), + ident => { + Err(location + .new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone()))) + }, } } } @@ -587,8 +590,7 @@ impl TextEmphasisKeywordValue { } /// Fill mode for the text-emphasis-style property -#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, - ToCss)] +#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss)] pub enum TextEmphasisFillMode { /// `filled` Filled, @@ -597,8 +599,7 @@ pub enum TextEmphasisFillMode { } /// Shape keyword for the text-emphasis-style property -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToCss)] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss)] pub enum TextEmphasisShapeKeyword { /// `dot` Dot, @@ -724,8 +725,18 @@ impl Parse for TextEmphasisStyle { } /// The allowed horizontal values for the `text-emphasis-position` property. -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Clone, + Copy, + Debug, + Eq, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] pub enum TextEmphasisHorizontalWritingModeValue { /// Draw marks over the text in horizontal writing mode. Over, @@ -734,8 +745,18 @@ pub enum TextEmphasisHorizontalWritingModeValue { } /// The allowed vertical values for the `text-emphasis-position` property. -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, - SpecifiedValueInfo, ToComputedValue, ToCss)] +#[derive( + Clone, + Copy, + Debug, + Eq, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, +)] pub enum TextEmphasisVerticalWritingModeValue { /// Draws marks to the right of the text in vertical writing mode. Right, @@ -744,8 +765,9 @@ pub enum TextEmphasisVerticalWritingModeValue { } /// Specified value of `text-emphasis-position` property. -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss)] +#[derive( + Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, +)] pub struct TextEmphasisPosition( pub TextEmphasisHorizontalWritingModeValue, pub TextEmphasisVerticalWritingModeValue, @@ -846,8 +868,7 @@ impl Parse for MozTabSize { return Ok(GenericMozTabSize::Number(number)); } Ok(GenericMozTabSize::Length(NonNegativeLength::parse( - context, - input, + context, input, )?)) } } diff --git a/components/style/values/specified/time.rs b/components/style/values/specified/time.rs index 107c45b2d48..6895a918346 100644 --- a/components/style/values/specified/time.rs +++ b/components/style/values/specified/time.rs @@ -92,7 +92,8 @@ impl Time { // ParsingMode::DEFAULT directly. Ok(&Token::Dimension { value, ref unit, .. - }) if clamping_mode.is_ok(ParsingMode::DEFAULT, value) => + }) + if clamping_mode.is_ok(ParsingMode::DEFAULT, value) => { return Time::parse_dimension(value, unit, /* from_calc = */ false) .map_err(|()| location.new_custom_error(StyleParseErrorKind::UnspecifiedError)); diff --git a/components/style/values/specified/ui.rs b/components/style/values/specified/ui.rs index e912c24b808..7dc1e0fe1d3 100644 --- a/components/style/values/specified/ui.rs +++ b/components/style/values/specified/ui.rs @@ -52,9 +52,8 @@ impl Parse for CursorKind { ) -> Result<Self, ParseError<'i>> { let location = input.current_source_location(); let ident = input.expect_ident()?; - CursorKind::from_css_keyword(&ident).map_err(|_| { - location.new_custom_error(StyleParseErrorKind::UnspecifiedError) - }) + CursorKind::from_css_keyword(&ident) + .map_err(|_| location.new_custom_error(StyleParseErrorKind::UnspecifiedError)) } } @@ -74,8 +73,7 @@ impl Parse for CursorImage { } /// Specified value of `-moz-force-broken-image-icon` -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, - ToComputedValue)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)] pub struct MozForceBrokenImageIcon(pub bool); impl MozForceBrokenImageIcon { |