aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2018-09-03 08:12:22 -0400
committerGitHub <noreply@github.com>2018-09-03 08:12:22 -0400
commitd8446f85a95723dec3a18b05bdd30514a57bddab (patch)
tree3e92a0a5fed4315519a34e8cef33c54840ada0d4
parenteb6aec37e9bde5aba2a3dc6b6ce5374579219f31 (diff)
parent1254cbf313243e8879a464538a5c78383ba3bc8b (diff)
downloadservo-d8446f85a95723dec3a18b05bdd30514a57bddab.tar.gz
servo-d8446f85a95723dec3a18b05bdd30514a57bddab.zip
Auto merge of #21588 - emilio:gecko-sync, r=emilio
style: Sync changes from mozilla-central. See each individual commit for details. https://bugzilla.mozilla.org/show_bug.cgi?id=1488172 <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/21588) <!-- Reviewable:end -->
-rw-r--r--components/atoms/static_atoms.txt2
-rw-r--r--components/layout_thread/dom_wrapper.rs6
-rw-r--r--components/malloc_size_of/lib.rs4
-rw-r--r--components/script/dom/css.rs2
-rw-r--r--components/script/dom/cssmediarule.rs1
-rw-r--r--components/script/dom/csssupportsrule.rs1
-rw-r--r--components/script/dom/htmlimageelement.rs19
-rw-r--r--components/script/dom/htmllinkelement.rs1
-rw-r--r--components/script/dom/htmlstyleelement.rs1
-rw-r--r--components/script/dom/medialist.rs3
-rw-r--r--components/script/dom/window.rs1
-rw-r--r--components/style/build_gecko.rs11
-rw-r--r--components/style/cbindgen.toml11
-rw-r--r--components/style/dom.rs42
-rw-r--r--components/style/gecko/conversions.rs172
-rw-r--r--components/style/gecko/non_ts_pseudo_class_list.rs16
-rw-r--r--components/style/gecko/pseudo_element.rs1
-rw-r--r--components/style/gecko/pseudo_element_definition.mako.rs36
-rw-r--r--components/style/gecko/selector_parser.rs116
-rw-r--r--components/style/gecko/wrapper.rs41
-rw-r--r--components/style/gecko_bindings/sugar/ownership.rs9
-rw-r--r--components/style/invalidation/element/element_wrapper.rs3
-rw-r--r--components/style/invalidation/element/invalidation_map.rs18
-rw-r--r--components/style/invalidation/element/state_and_attributes.rs15
-rw-r--r--components/style/lib.rs1
-rw-r--r--components/style/parser.rs15
-rw-r--r--components/style/properties/declaration_block.rs77
-rw-r--r--components/style/properties/gecko.mako.rs77
-rw-r--r--components/style/properties/longhands/background.mako.rs43
-rw-r--r--components/style/properties/longhands/border.mako.rs88
-rw-r--r--components/style/properties/longhands/box.mako.rs505
-rw-r--r--components/style/properties/longhands/color.mako.rs8
-rw-r--r--components/style/properties/longhands/column.mako.rs87
-rw-r--r--components/style/properties/longhands/counters.mako.rs20
-rw-r--r--components/style/properties/longhands/effects.mako.rs37
-rw-r--r--components/style/properties/longhands/inherited_box.mako.rs5
-rw-r--r--components/style/properties/longhands/inherited_svg.mako.rs225
-rw-r--r--components/style/properties/longhands/inherited_table.mako.rs59
-rw-r--r--components/style/properties/longhands/inherited_text.mako.rs241
-rw-r--r--components/style/properties/longhands/inherited_ui.mako.rs70
-rw-r--r--components/style/properties/longhands/list.mako.rs46
-rw-r--r--components/style/properties/longhands/outline.mako.rs34
-rw-r--r--components/style/properties/longhands/position.mako.rs379
-rw-r--r--components/style/properties/longhands/svg.mako.rs98
-rw-r--r--components/style/properties/longhands/table.mako.rs28
-rw-r--r--components/style/properties/longhands/text.mako.rs81
-rw-r--r--components/style/properties/longhands/ui.mako.rs78
-rw-r--r--components/style/properties/longhands/xul.mako.rs124
-rw-r--r--components/style/properties/properties.mako.rs101
-rw-r--r--components/style/selector_parser.rs57
-rw-r--r--components/style/servo/selector_parser.rs10
-rw-r--r--components/style/stylesheets/keyframes_rule.rs1
-rw-r--r--components/style/stylesheets/mod.rs1
-rw-r--r--components/style/stylesheets/stylesheet.rs10
-rw-r--r--components/style/stylist.rs90
-rw-r--r--components/style/use_counters/mod.rs87
-rw-r--r--components/style/values/computed/border.rs16
-rw-r--r--components/style/values/computed/mod.rs2
-rw-r--r--components/style/values/computed/motion.rs10
-rw-r--r--components/style/values/generics/basic_shape.rs63
-rw-r--r--components/style/values/specified/basic_shape.rs66
-rw-r--r--components/style/values/specified/box.rs4
-rw-r--r--components/style/values/specified/mod.rs4
-rw-r--r--components/style/values/specified/motion.rs61
-rw-r--r--components/style/values/specified/svg_path.rs515
-rw-r--r--tests/unit/style/parsing/mod.rs12
-rw-r--r--tests/unit/style/properties/mod.rs12
-rw-r--r--tests/unit/style/viewport.rs12
68 files changed, 2701 insertions, 1391 deletions
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<Option<SelectorAttrValue>>,
- 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)
}
/// <https://html.spec.whatwg.org/multipage/#normalise-the-source-densities>
@@ -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) -> <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;
@@ -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<Option<AttrValue>>,
- 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<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 +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 -> <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..b30d7764d17 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;
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/selector_parser.rs b/components/style/gecko/selector_parser.rs
index fa514835e8c..3f6fee3c30e 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,
}
@@ -221,13 +208,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(),
}
}
@@ -398,42 +384,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 +441,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/wrapper.rs b/components/style/gecko/wrapper.rs
index 1ba850696d1..ff5ae599fcb 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};
@@ -167,15 +167,14 @@ 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
- as *const bindings::RawServoAuthorStyles)
+ (self.0.mServoStyles.mPtr
+ as *const structs::RawServoAuthorStyles
+ as *const bindings::RawServoAuthorStyles).as_ref()?
};
@@ -187,7 +186,7 @@ impl<'lr> TShadowRoot for GeckoShadowRoot<'lr> {
author_styles.stylesheets.dirty()
);
- &author_styles.data
+ Some(&author_styles.data)
}
#[inline]
@@ -1717,15 +1716,11 @@ impl<'le> TElement for GeckoElement<'le> {
fn match_element_lang(
&self,
override_lang: Option<Option<AttrValue>>,
- value: &PseudoClassStringArg,
+ 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 +1730,7 @@ impl<'le> TElement for GeckoElement<'le> {
self.0,
override_lang_ptr,
override_lang.is_some(),
- value.as_ptr(),
+ value.as_slice().as_ptr(),
)
}
}
@@ -2238,24 +2233,22 @@ 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/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/invalidation/element/element_wrapper.rs b/components/style/invalidation/element/element_wrapper.rs
index cb4f79e92e1..e788d2dd876 100644
--- a/components/style/invalidation/element/element_wrapper.rs
+++ b/components/style/invalidation/element/element_wrapper.rs
@@ -188,8 +188,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;
diff --git a/components/style/invalidation/element/invalidation_map.rs b/components/style/invalidation/element/invalidation_map.rs
index 67849d89627..26a4609760f 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.
///
@@ -382,7 +366,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/state_and_attributes.rs b/components/style/invalidation/element/state_and_attributes.rs
index 1eb022b298a..fa0ccdd8be9 100644
--- a/components/style/invalidation/element/state_and_attributes.rs
+++ b/components/style/invalidation/element/state_and_attributes.rs
@@ -159,13 +159,18 @@ where
// 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) {
+ if state_changes.intersects(ElementState::IN_VISITED_OR_UNVISITED_STATE) &&
+ self.shared_context.visited_styles_enabled
+ {
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
+ // We shouldn't get here with visited links disabled, but it's hard
+ // to assert in cases where you record a visitedness change and
+ // afterwards you change some of the stuff (like the pref) that
+ // changes whether visited styles are enabled.
+ //
+ // So just avoid the restyle here, 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());
diff --git a/components/style/lib.rs b/components/style/lib.rs
index 1c3630b0986..03caab33e19 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;
diff --git a/components/style/parser.rs b/components/style/parser.rs
index a4b7d816203..db5b8f1e7f9 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,
}
}
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/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..7dfc15cd14e 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="none",
+ 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/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/selector_parser.rs b/components/style/servo/selector_parser.rs
index 2083539f51b..c608cd8488d 100644
--- a/components/style/servo/selector_parser.rs
+++ b/components/style/servo/selector_parser.rs
@@ -135,6 +135,10 @@ 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 +288,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 +306,7 @@ pub enum NonTSPseudoClass {
Fullscreen,
Hover,
Indeterminate,
- Lang(PseudoClassStringArg),
+ Lang(Lang),
Link,
PlaceholderShown,
ReadWrite,
diff --git a/components/style/stylesheets/keyframes_rule.rs b/components/style/stylesheets/keyframes_rule.rs
index 91bc14be5b5..0246efa6780 100644
--- a/components/style/stylesheets/keyframes_rule.rs
+++ b/components/style/stylesheets/keyframes_rule.rs
@@ -219,6 +219,7 @@ impl Keyframe {
ParsingMode::DEFAULT,
parent_stylesheet_contents.quirks_mode,
None,
+ None,
);
context.namespaces = Some(&*namespaces);
let mut input = ParserInput::new(css);
diff --git a/components/style/stylesheets/mod.rs b/components/style/stylesheets/mod.rs
index e3641f3e515..80766c289f8 100644
--- a/components/style/stylesheets/mod.rs
+++ b/components/style/stylesheets/mod.rs
@@ -264,6 +264,7 @@ impl CssRule {
ParsingMode::DEFAULT,
parent_stylesheet_contents.quirks_mode,
None,
+ None,
);
let mut input = ParserInput::new(css);
diff --git a/components/style/stylesheets/stylesheet.rs b/components/style/stylesheets/stylesheet.rs
index 02730f7090d..1403a1d2547 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 {
@@ -315,6 +318,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 +330,7 @@ impl Stylesheet {
error_reporter,
existing.contents.quirks_mode,
line_number_offset,
+ /* use_counters = */ None,
);
*existing.contents.url_data.write() = url_data;
@@ -350,6 +356,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 +369,7 @@ impl Stylesheet {
ParsingMode::DEFAULT,
quirks_mode,
error_reporter,
+ use_counters,
);
let rule_parser = TopLevelRuleParser {
@@ -421,6 +429,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 +439,7 @@ impl Stylesheet {
error_reporter,
quirks_mode,
line_number_offset,
+ /* use_counters = */ None,
);
Stylesheet {
diff --git a/components/style/stylist.rs b/components/style/stylist.rs
index 1fbf493667f..038c41ab103 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};
@@ -1206,7 +1206,7 @@ impl Stylist {
// 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) {
+ 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,
@@ -1233,8 +1233,7 @@ impl Stylist {
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) {
+ 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,
@@ -1253,7 +1252,7 @@ impl Stylist {
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) {
+ 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,
@@ -1283,6 +1282,11 @@ impl Stylist {
//
// See: https://github.com/w3c/svgwg/issues/505
//
+ // FIXME(emilio, bug 1487259): We now do after bug 1483882, we
+ // should jump out of the <svg:use> shadow tree chain now.
+ //
+ // Unless the used node is cross-doc, I guess, in which case doc
+ // rules are probably ok...
let host_is_svg_use =
host.is_svg_element() &&
host.local_name() == &*local_name!("use");
@@ -1392,8 +1396,7 @@ 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.
@@ -1431,11 +1434,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);
}
@@ -1745,11 +1752,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.
@@ -1814,13 +1819,8 @@ 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
}
@@ -1846,7 +1846,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,7 +1878,9 @@ 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,
@@ -1944,18 +1946,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 +1964,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 +2001,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 +2069,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 +2178,9 @@ impl CascadeData {
));
continue;
}
+ if pseudo.is_unknown_webkit_pseudo_element() {
+ continue;
+ }
}
let hashes = AncestorHashes::new(&selector, quirks_mode);
@@ -2208,7 +2198,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,
@@ -2418,7 +2407,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();
@@ -2514,16 +2502,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/use_counters/mod.rs b/components/style/use_counters/mod.rs
new file mode 100644
index 00000000000..92bc6adb01a
--- /dev/null
+++ b/components/style/use_counters/mod.rs
@@ -0,0 +1,87 @@
+/* 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/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/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..935ba57f845
--- /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 as OffsetPath;
diff --git a/components/style/values/generics/basic_shape.rs b/components/style/values/generics/basic_shape.rs
index 3bad738c1e6..0eccf011c71 100644
--- a/components/style/values/generics/basic_shape.rs
+++ b/components/style/values/generics/basic_shape.rs
@@ -12,6 +12,7 @@ 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>;
@@ -54,6 +55,9 @@ pub enum ShapeSource<BasicShape, ReferenceBox, ImageOrUrl> {
#[animation(error)]
Box(ReferenceBox),
#[animation(error)]
+ #[css(function)]
+ Path(Path),
+ #[animation(error)]
None,
}
@@ -113,16 +117,23 @@ pub enum ShapeRadius<LengthOrPercentage> {
/// A generic type for representing the `polygon()` function
///
/// <https://drafts.csswg.org/css-shapes/#funcdef-polygon>
-#[css(function)]
+#[css(comma, function)]
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
- ToComputedValue)]
+ 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
@@ -131,11 +142,25 @@ pub struct Polygon<LengthOrPercentage> {
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[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(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+pub struct Path {
+ /// The filling rule for the svg path.
+ #[css(skip_if = "fill_is_default")]
+ 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>
@@ -203,7 +228,7 @@ where
.iter()
.zip(other.coordinates.iter())
.map(|(this, other)| {
- Ok((
+ Ok(PolygonCoord(
this.0.animate(&other.0, procedure)?,
this.1.animate(&other.1, procedure)?,
))
@@ -239,34 +264,14 @@ where
}
}
-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(")")
- }
-}
-
impl Default for FillRule {
#[inline]
fn default() -> Self {
FillRule::Nonzero
}
}
+
+#[inline]
+fn fill_is_default(fill: &FillRule) -> bool {
+ *fill == FillRule::default()
+}
diff --git a/components/style/values/specified/basic_shape.rs b/components/style/values/specified/basic_shape.rs
index 23ae91d564e..824c13f1f01 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,42 @@ 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>
+impl Parse for ClippingShape {
+ #[inline]
+ fn parse<'i, 't>(
+ context: &ParserContext,
+ input: &mut Parser<'i, 't>,
+ ) -> Result<Self, ParseError<'i>> {
+ // |clip-path:path()| is a chrome-only property value support for now. `path()` is
+ // defined in css-shape-2, but the spec is not stable enough, and we haven't decided
+ // to make it public yet. However, it has some benefits for the front-end, so we
+ // implement it.
+ if context.chrome_rules_enabled() {
+ 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>> {
@@ -381,7 +413,7 @@ impl Polygon {
.unwrap_or_default();
let buf = input.parse_comma_separated(|i| {
- Ok((
+ Ok(PolygonCoord(
LengthOrPercentage::parse(context, i)?,
LengthOrPercentage::parse(context, i)?,
))
@@ -393,3 +425,29 @@ 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/box.rs b/components/style/values/specified/box.rs
index 6b474689df3..9554d76890c 100644
--- a/components/style/values/specified/box.rs
+++ b/components/style/values/specified/box.rs
@@ -57,8 +57,8 @@ 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 {
diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs
index 2da4c7e93d3..6a395c21e58 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;
diff --git a/components/style/values/specified/motion.rs b/components/style/values/specified/motion.rs
new file mode 100644
index 00000000000..87ff39d9a3a
--- /dev/null
+++ b/components/style/values/specified/motion.rs
@@ -0,0 +1,61 @@
+/* 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(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, 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.
+ 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/svg_path.rs b/components/style/values/specified/svg_path.rs
new file mode 100644
index 00000000000..48ae185477d
--- /dev/null
+++ b/components/style/values/specified/svg_path.rs
@@ -0,0 +1,515 @@
+/* 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::slice;
+use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
+use style_traits::values::SequenceWriter;
+use values::CSSFloat;
+
+
+/// The SVG path data.
+///
+/// https://www.w3.org/TR/SVG11/paths.html#PathData
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, 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
+ }
+}
+
+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()))
+ }
+}
+
+
+/// 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(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo)]
+#[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: bool },
+ /// The "lineto" command.
+ LineTo { point: CoordPair, absolute: bool },
+ /// The horizontal "lineto" command.
+ HorizontalLineTo { x: CSSFloat, absolute: bool },
+ /// The vertical "lineto" command.
+ VerticalLineTo { y: CSSFloat, absolute: bool },
+ /// The cubic Bézier curve command.
+ CurveTo { control1: CoordPair, control2: CoordPair, point: CoordPair, absolute: bool },
+ /// The smooth curve command.
+ SmoothCurveTo { control2: CoordPair, point: CoordPair, absolute: bool },
+ /// The quadratic Bézier curve command.
+ QuadBezierCurveTo { control1: CoordPair, point: CoordPair, absolute: bool },
+ /// The smooth quadratic Bézier curve command.
+ SmoothQuadBezierCurveTo { point: CoordPair, absolute: bool },
+ /// The elliptical arc curve command.
+ EllipticalArc {
+ rx: CSSFloat,
+ ry: CSSFloat,
+ angle: CSSFloat,
+ large_arc_flag: bool,
+ sweep_flag: bool,
+ point: CoordPair,
+ absolute: bool
+ },
+ /// The "closepath" command.
+ ClosePath,
+}
+
+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 { 'M' } else { 'm' })?;
+ dest.write_char(' ')?;
+ point.to_css(dest)
+ }
+ LineTo { point, absolute } => {
+ dest.write_char(if absolute { 'L' } else { 'l' })?;
+ dest.write_char(' ')?;
+ point.to_css(dest)
+ }
+ CurveTo { control1, control2, point, absolute } => {
+ dest.write_char(if absolute { '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 { '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 { '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 as i32).to_css(dest)?;
+ dest.write_char(' ')?;
+ (sweep_flag as i32).to_css(dest)?;
+ dest.write_char(' ')?;
+ point.to_css(dest)
+ },
+ HorizontalLineTo { x, absolute } => {
+ dest.write_char(if absolute { 'H' } else { 'h' })?;
+ dest.write_char(' ')?;
+ x.to_css(dest)
+ },
+ VerticalLineTo { y, absolute } => {
+ dest.write_char(if absolute { 'V' } else { 'v' })?;
+ dest.write_char(' ')?;
+ y.to_css(dest)
+ },
+ SmoothCurveTo { control2, point, absolute } => {
+ dest.write_char(if absolute { '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 { 'T' } else { 't' })?;
+ dest.write_char(' ')?;
+ point.to_css(dest)
+ },
+ }
+ }
+}
+
+
+/// The path coord type.
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, 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)
+ }
+}
+
+
+/// 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 = command.is_ascii_uppercase();
+ 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_elliprical_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 = command == b'M';
+ 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: bool) -> Result<(), ()> {
+ self.path.push(PathCommand::ClosePath);
+ Ok(())
+ }
+
+ /// Parse "lineto" command.
+ fn parse_lineto(&mut self, absolute: bool) -> Result<(), ()> {
+ parse_arguments!(self, absolute, LineTo, [ point => parse_coord ])
+ }
+
+ /// Parse horizontal "lineto" command.
+ fn parse_h_lineto(&mut self, absolute: bool) -> Result<(), ()> {
+ parse_arguments!(self, absolute, HorizontalLineTo, [ x => parse_number ])
+ }
+
+ /// Parse vertical "lineto" command.
+ fn parse_v_lineto(&mut self, absolute: bool) -> Result<(), ()> {
+ parse_arguments!(self, absolute, VerticalLineTo, [ y => parse_number ])
+ }
+
+ /// Parse cubic Bézier curve command.
+ fn parse_curveto(&mut self, absolute: bool) -> 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: bool) -> 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: bool) -> 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: bool) -> Result<(), ()> {
+ parse_arguments!(self, absolute, SmoothQuadBezierCurveTo, [ point => parse_coord ])
+ }
+
+ /// Parse elliptical arc curve command.
+ fn parse_elliprical_arc(&mut self, absolute: bool) -> Result<(), ()> {
+ // Parse a flag whose value is '0' or '1'; otherwise, return Err(()).
+ let parse_flag = |iter: &mut Peekable<Cloned<slice::Iter<u8>>>| -> Result<bool, ()> {
+ match iter.next() {
+ Some(c) if c == b'0' || c == b'1' => Ok(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/tests/unit/style/parsing/mod.rs b/tests/unit/style/parsing/mod.rs
index b75e3a7ce42..6f76b2efea6 100644
--- a/tests/unit/style/parsing/mod.rs
+++ b/tests/unit/style/parsing/mod.rs
@@ -19,9 +19,15 @@ where F: for<'t> Fn(&ParserContext, &mut Parser<'static, 't>) -> Result<T, Parse
fn parse_input<'i: 't, 't, T, F>(f: F, input: &'t mut ParserInput<'i>) -> Result<T, ParseError<'i>>
where F: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>> {
let url = ::servo_url::ServoUrl::parse("http://localhost").unwrap();
- let context = ParserContext::new(Origin::Author, &url, Some(CssRuleType::Style),
- ParsingMode::DEFAULT,
- QuirksMode::NoQuirks, None);
+ let context = ParserContext::new(
+ Origin::Author,
+ &url,
+ Some(CssRuleType::Style),
+ ParsingMode::DEFAULT,
+ QuirksMode::NoQuirks,
+ None,
+ None,
+ );
let mut parser = Parser::new(input);
f(&context, &mut parser)
}
diff --git a/tests/unit/style/properties/mod.rs b/tests/unit/style/properties/mod.rs
index 725aabc42a4..5210b663168 100644
--- a/tests/unit/style/properties/mod.rs
+++ b/tests/unit/style/properties/mod.rs
@@ -24,9 +24,15 @@ where
F: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>>,
{
let url = ::servo_url::ServoUrl::parse("http://localhost").unwrap();
- let context = ParserContext::new(Origin::Author, &url, Some(CssRuleType::Style),
- ParsingMode::DEFAULT,
- QuirksMode::NoQuirks, None);
+ let context = ParserContext::new(
+ Origin::Author,
+ &url,
+ Some(CssRuleType::Style),
+ ParsingMode::DEFAULT,
+ QuirksMode::NoQuirks,
+ None,
+ None,
+ );
let mut parser = Parser::new(input);
f(&context, &mut parser)
}
diff --git a/tests/unit/style/viewport.rs b/tests/unit/style/viewport.rs
index 9243dbcb403..a8d01651c3d 100644
--- a/tests/unit/style/viewport.rs
+++ b/tests/unit/style/viewport.rs
@@ -301,9 +301,15 @@ fn multiple_stylesheets_cascading() {
#[test]
fn constrain_viewport() {
let url = ServoUrl::parse("http://localhost").unwrap();
- let context = ParserContext::new(Origin::Author, &url, Some(CssRuleType::Viewport),
- ParsingMode::DEFAULT,
- QuirksMode::NoQuirks, None);
+ let context = ParserContext::new(
+ Origin::Author,
+ &url,
+ Some(CssRuleType::Viewport),
+ ParsingMode::DEFAULT,
+ QuirksMode::NoQuirks,
+ None,
+ None,
+ );
macro_rules! from_css {
($css:expr) => {