mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
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 -->
This commit is contained in:
commit
d8446f85a9
68 changed files with 2673 additions and 1363 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -81,6 +81,7 @@ impl CSSMediaRule {
|
|||
ParsingMode::DEFAULT,
|
||||
quirks_mode,
|
||||
window.css_error_reporter(),
|
||||
None,
|
||||
);
|
||||
|
||||
let new_medialist = StyleMediaList::parse(&context, &mut input);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -287,6 +287,7 @@ impl HTMLLinkElement {
|
|||
ParsingMode::DEFAULT,
|
||||
document.quirks_mode(),
|
||||
window.css_error_reporter(),
|
||||
None,
|
||||
);
|
||||
let media = MediaList::parse(&context, &mut css_parser);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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![];
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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, _, _),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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",
|
||||
)}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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("-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(
|
||||
"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-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-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-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-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.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.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(
|
||||
|
|
|
@ -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(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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",
|
||||
)}
|
||||
|
|
|
@ -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",
|
||||
)}
|
||||
|
|
|
@ -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",
|
||||
)}
|
||||
|
|
|
@ -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",
|
||||
)}
|
||||
|
||||
|
|
|
@ -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",
|
||||
"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-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")}
|
||||
|
||||
${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("shape-rendering",
|
||||
"auto optimizespeed crispedges geometricprecision",
|
||||
products="gecko",
|
||||
animation_value_type="discrete",
|
||||
spec="https://www.w3.org/TR/SVG11/painting.html#ShapeRenderingProperty")}
|
||||
spec="https://www.w3.org/TR/SVG2/painting.html#SpecifyingFillPaint",
|
||||
)}
|
||||
|
||||
${helpers.predefined_type(
|
||||
"stroke", "SVGPaint",
|
||||
"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(
|
||||
"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",
|
||||
"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.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-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-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(
|
||||
"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(
|
||||
"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.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,
|
||||
)}
|
||||
|
|
|
@ -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",
|
||||
)}
|
||||
|
|
|
@ -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(
|
||||
"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(
|
||||
"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.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.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(
|
||||
"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(
|
||||
"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(
|
||||
"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",
|
||||
)}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)",
|
||||
)}
|
||||
|
|
|
@ -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",
|
||||
)}
|
||||
|
|
|
@ -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-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-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-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-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(
|
||||
"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(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-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-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-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(
|
||||
"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(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(
|
||||
"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(
|
||||
"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.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.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-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",
|
||||
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(
|
||||
"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")}
|
||||
${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",
|
||||
)}
|
||||
|
|
|
@ -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",
|
||||
)}
|
||||
|
|
|
@ -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="",
|
||||
)}
|
||||
|
|
|
@ -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",
|
||||
)}
|
||||
|
|
|
@ -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)",
|
||||
)}
|
||||
|
|
|
@ -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-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.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.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-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-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.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.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)",
|
||||
)}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -264,6 +264,7 @@ impl CssRule {
|
|||
ParsingMode::DEFAULT,
|
||||
parent_stylesheet_contents.quirks_mode,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
||||
let mut input = ParserInput::new(css);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
87
components/style/use_counters/mod.rs
Normal file
87
components/style/use_counters/mod.rs
Normal file
|
@ -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 {}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
10
components/style/values/computed/motion.rs
Normal file
10
components/style/values/computed/motion.rs
Normal file
|
@ -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;
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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 })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
61
components/style/values/specified/motion.rs
Normal file
61
components/style/values/specified/motion.rs
Normal file
|
@ -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())
|
||||
))
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
515
components/style/values/specified/svg_path.rs
Normal file
515
components/style/values/specified/svg_path.rs
Normal file
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue