diff --git a/components/atoms/static_atoms.txt b/components/atoms/static_atoms.txt index 0798179c151..7fbd043dc0f 100644 --- a/components/atoms/static_atoms.txt +++ b/components/atoms/static_atoms.txt @@ -36,6 +36,7 @@ invalid keydown keypress left +ltr load loadeddata loadedmetadata @@ -65,6 +66,7 @@ readystatechange reftest-wait reset right +rtl sans-serif scan screen diff --git a/components/layout_thread/dom_wrapper.rs b/components/layout_thread/dom_wrapper.rs index 7b2892f7c9a..4800704fca8 100644 --- a/components/layout_thread/dom_wrapper.rs +++ b/components/layout_thread/dom_wrapper.rs @@ -70,7 +70,7 @@ use style::dom::{TDocument, TElement, TNode, TShadowRoot}; use style::element_state::*; use style::font_metrics::ServoMetricsProvider; use style::properties::{ComputedValues, PropertyDeclarationBlock}; -use style::selector_parser::{AttrValue as SelectorAttrValue, NonTSPseudoClass, PseudoClassStringArg}; +use style::selector_parser::{AttrValue as SelectorAttrValue, NonTSPseudoClass, Lang}; use style::selector_parser::{PseudoElement, SelectorImpl, extended_filtering}; use style::shared_lock::{SharedRwLock as StyleSharedRwLock, Locked as StyleLocked}; use style::str::is_whitespace; @@ -168,7 +168,7 @@ impl<'lr> TShadowRoot for ShadowRoot<'lr> { match self.0 { } } - fn style_data<'a>(&self) -> &'a CascadeData + fn style_data<'a>(&self) -> Option<&'a CascadeData> where Self: 'a, { @@ -531,7 +531,7 @@ impl<'le> TElement for ServoLayoutElement<'le> { fn match_element_lang( &self, override_lang: Option>, - value: &PseudoClassStringArg, + value: &Lang, ) -> bool { // Servo supports :lang() from CSS Selectors 4, which can take a comma- // separated list of language tags in the pseudo-class, and which diff --git a/components/malloc_size_of/lib.rs b/components/malloc_size_of/lib.rs index f4774d66a3e..11e96254172 100644 --- a/components/malloc_size_of/lib.rs +++ b/components/malloc_size_of/lib.rs @@ -845,8 +845,8 @@ macro_rules! malloc_size_of_is_0( ); malloc_size_of_is_0!(bool, char, str); -malloc_size_of_is_0!(u8, u16, u32, u64, usize); -malloc_size_of_is_0!(i8, i16, i32, i64, isize); +malloc_size_of_is_0!(u8, u16, u32, u64, u128, usize); +malloc_size_of_is_0!(i8, i16, i32, i64, i128, isize); malloc_size_of_is_0!(f32, f64); malloc_size_of_is_0!(std::sync::atomic::AtomicBool); diff --git a/components/script/dom/css.rs b/components/script/dom/css.rs index d642b44a19f..7a42d6b6e68 100644 --- a/components/script/dom/css.rs +++ b/components/script/dom/css.rs @@ -44,6 +44,7 @@ impl CSS { ParsingMode::DEFAULT, QuirksMode::NoQuirks, None, + None, ); decl.eval(&context) } @@ -61,6 +62,7 @@ impl CSS { ParsingMode::DEFAULT, QuirksMode::NoQuirks, None, + None, ); cond.eval(&context) } else { diff --git a/components/script/dom/cssmediarule.rs b/components/script/dom/cssmediarule.rs index 23f3c46a251..ccc803e4b42 100644 --- a/components/script/dom/cssmediarule.rs +++ b/components/script/dom/cssmediarule.rs @@ -81,6 +81,7 @@ impl CSSMediaRule { ParsingMode::DEFAULT, quirks_mode, window.css_error_reporter(), + None, ); let new_medialist = StyleMediaList::parse(&context, &mut input); diff --git a/components/script/dom/csssupportsrule.rs b/components/script/dom/csssupportsrule.rs index a96cd706b86..8b66fbe76cf 100644 --- a/components/script/dom/csssupportsrule.rs +++ b/components/script/dom/csssupportsrule.rs @@ -69,6 +69,7 @@ impl CSSSupportsRule { ParsingMode::DEFAULT, quirks_mode, None, + None, ); let enabled = cond.eval(&context); let mut guard = self.cssconditionrule.shared_lock().write(); diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index 62523e61f4e..3aaa7c579cb 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -538,12 +538,17 @@ impl HTMLImageElement { /// https://html.spec.whatwg.org/multipage/#matches-the-environment fn matches_environment(&self, media_query: String) -> bool { let document = document_from_node(self); - let device = document.device(); - if !device.is_some() { - return false; - } + let device = match document.device() { + Some(device) => device, + None => return false, + }; let quirks_mode = document.quirks_mode(); let document_url = &document.url(); + // FIXME(emilio): This should do the same that we do for other media + // lists regarding the rule type and such, though it doesn't really + // matter right now... + // + // Also, ParsingMode::all() is wrong, and should be DEFAULT. let context = ParserContext::new( Origin::Author, document_url, @@ -551,11 +556,12 @@ impl HTMLImageElement { ParsingMode::all(), quirks_mode, None, + None, ); let mut parserInput = ParserInput::new(&media_query); let mut parser = Parser::new(&mut parserInput); let media_list = MediaList::parse(&context, &mut parser); - media_list.evaluate(&device.unwrap(), quirks_mode) + media_list.evaluate(&device, quirks_mode) } /// @@ -1039,9 +1045,12 @@ pub fn parse_a_sizes_attribute(value: DOMString) -> SourceSizeList { Origin::Author, &url, Some(CssRuleType::Style), + // FIXME(emilio): why ::empty() instead of ::DEFAULT? Also, what do + // browsers do regarding quirks-mode in a media list? ParsingMode::empty(), QuirksMode::NoQuirks, None, + None, ); SourceSizeList::parse(&context, &mut parser) } diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs index a86789dcd71..be7b2785ee9 100644 --- a/components/script/dom/htmllinkelement.rs +++ b/components/script/dom/htmllinkelement.rs @@ -287,6 +287,7 @@ impl HTMLLinkElement { ParsingMode::DEFAULT, document.quirks_mode(), window.css_error_reporter(), + None, ); let media = MediaList::parse(&context, &mut css_parser); diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs index 82da9ba6180..bcecab9088b 100644 --- a/components/script/dom/htmlstyleelement.rs +++ b/components/script/dom/htmlstyleelement.rs @@ -91,6 +91,7 @@ impl HTMLStyleElement { ParsingMode::DEFAULT, doc.quirks_mode(), css_error_reporter, + None, ); let shared_lock = node.owner_doc().style_shared_lock().clone(); let mut input = ParserInput::new(&mq_str); diff --git a/components/script/dom/medialist.rs b/components/script/dom/medialist.rs index d43f6d3a710..99800f1beb1 100644 --- a/components/script/dom/medialist.rs +++ b/components/script/dom/medialist.rs @@ -83,6 +83,7 @@ impl MediaListMethods for MediaList { ParsingMode::DEFAULT, quirks_mode, window.css_error_reporter(), + None, ); *media_queries = StyleMediaList::parse(&context, &mut parser); } @@ -123,6 +124,7 @@ impl MediaListMethods for MediaList { ParsingMode::DEFAULT, quirks_mode, win.css_error_reporter(), + None, ); let m = MediaQuery::parse(&context, &mut parser); // Step 2 @@ -156,6 +158,7 @@ impl MediaListMethods for MediaList { ParsingMode::DEFAULT, quirks_mode, win.css_error_reporter(), + None, ); let m = MediaQuery::parse(&context, &mut parser); // Step 2 diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index e125aa87fd9..7ccd828f9e3 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -1089,6 +1089,7 @@ impl WindowMethods for Window { ParsingMode::DEFAULT, quirks_mode, self.css_error_reporter(), + None, ); let media_query_list = media_queries::MediaList::parse(&context, &mut parser); diff --git a/components/style/build_gecko.rs b/components/style/build_gecko.rs index 8387f6513a6..c0655628538 100644 --- a/components/style/build_gecko.rs +++ b/components/style/build_gecko.rs @@ -406,11 +406,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) @@ -500,10 +496,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![]; 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/dom.rs b/components/style/dom.rs index 42f6e9ba0c0..2f65a266f01 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; @@ -342,7 +342,7 @@ pub trait TShadowRoot: Sized + Copy + Clone + PartialEq { fn host(&self) -> ::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; @@ -824,30 +824,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(); } @@ -889,7 +895,7 @@ pub trait TElement: fn match_element_lang( &self, override_lang: Option>, - value: &PseudoClassStringArg, + value: &Lang, ) -> bool; /// Returns whether this element is the main body element of the HTML diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index 3b1f31a1b08..3c1d334f4a8 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,68 @@ 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) { @@ -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}; @@ -437,12 +500,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 +518,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 { @@ -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,34 @@ 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 { + 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 = + 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 +768,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 +791,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 +820,14 @@ 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/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 ->