aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/layout/display_list/background.rs8
-rw-r--r--components/script/dom/css.rs30
-rw-r--r--components/script/dom/csssupportsrule.rs12
-rw-r--r--components/selectors/parser.rs17
-rw-r--r--components/style/build_gecko.rs139
-rw-r--r--components/style/gecko/arc_types.rs5
-rw-r--r--components/style/gecko/conversions.rs36
-rw-r--r--components/style/gecko/data.rs4
-rw-r--r--components/style/gecko/media_queries.rs6
-rw-r--r--components/style/gecko/pseudo_element.rs9
-rwxr-xr-xcomponents/style/gecko/regen_atoms.py7
-rw-r--r--components/style/gecko/url.rs223
-rw-r--r--components/style/gecko/values.rs14
-rw-r--r--components/style/gecko_bindings/sugar/ns_css_value.rs14
-rw-r--r--components/style/gecko_bindings/sugar/ns_style_coord.rs24
-rw-r--r--components/style/gecko_bindings/sugar/ns_t_array.rs19
-rw-r--r--components/style/gecko_bindings/sugar/refptr.rs5
-rw-r--r--components/style/properties/gecko.mako.rs83
-rw-r--r--components/style/properties/helpers/animated_properties.mako.rs9
-rw-r--r--components/style/properties/longhands/border.mako.rs2
-rw-r--r--components/style/properties/longhands/inherited_text.mako.rs2
-rw-r--r--components/style/properties/properties.mako.rs99
-rw-r--r--components/style/servo/selector_parser.rs5
-rw-r--r--components/style/servo/url.rs3
-rw-r--r--components/style/stylesheets/font_feature_values_rule.rs7
-rw-r--r--components/style/stylesheets/mod.rs1
-rw-r--r--components/style/stylesheets/rule_parser.rs11
-rw-r--r--components/style/stylesheets/stylesheet.rs1
-rw-r--r--components/style/stylesheets/supports_rule.rs198
-rw-r--r--components/style/stylist.rs14
-rw-r--r--components/style/values/animated/mod.rs10
-rw-r--r--components/style/values/computed/angle.rs93
-rw-r--r--components/style/values/computed/font.rs6
-rw-r--r--components/style/values/computed/length.rs155
-rw-r--r--components/style/values/generics/length.rs54
-rw-r--r--components/style/values/generics/mod.rs1
-rw-r--r--components/style/values/generics/transform.rs39
-rw-r--r--components/style/values/specified/angle.rs126
-rw-r--r--components/style/values/specified/box.rs91
-rw-r--r--components/style/values/specified/calc.rs10
-rw-r--r--components/style/values/specified/font.rs2
-rw-r--r--components/style/values/specified/image.rs3
-rw-r--r--components/style/values/specified/length.rs40
-rw-r--r--tests/unit/style/properties/serialization.rs54
-rw-r--r--tests/wpt/metadata/css/css-conditional/at-supports-040.html.ini2
-rw-r--r--tests/wpt/metadata/css/cssom/CSS.html.ini4
-rw-r--r--tests/wpt/mozilla/meta/MANIFEST.json2
-rw-r--r--tests/wpt/mozilla/tests/css/transform_skew_ref.html6
48 files changed, 801 insertions, 904 deletions
diff --git a/components/layout/display_list/background.rs b/components/layout/display_list/background.rs
index 19976a3bf83..7da2bff68d6 100644
--- a/components/layout/display_list/background.rs
+++ b/components/layout/display_list/background.rs
@@ -553,12 +553,12 @@ pub fn convert_linear_gradient(
let angle = match direction {
LineDirection::Angle(angle) => angle.radians(),
LineDirection::Horizontal(x) => match x {
- X::Left => Angle::Deg(270.).radians(),
- X::Right => Angle::Deg(90.).radians(),
+ X::Left => Angle::from_degrees(270.).radians(),
+ X::Right => Angle::from_degrees(90.).radians(),
},
LineDirection::Vertical(y) => match y {
- Y::Top => Angle::Deg(0.).radians(),
- Y::Bottom => Angle::Deg(180.).radians(),
+ Y::Top => Angle::from_degrees(0.).radians(),
+ Y::Bottom => Angle::from_degrees(180.).radians(),
},
LineDirection::Corner(horizontal, vertical) => {
// This the angle for one of the diagonals of the box. Our angle
diff --git a/components/script/dom/css.rs b/components/script/dom/css.rs
index 7a42d6b6e68..0f3c929460e 100644
--- a/components/script/dom/css.rs
+++ b/components/script/dom/css.rs
@@ -53,21 +53,21 @@ impl CSS {
pub fn Supports_(win: &Window, condition: DOMString) -> bool {
let mut input = ParserInput::new(&condition);
let mut input = Parser::new(&mut input);
- let cond = parse_condition_or_declaration(&mut input);
- if let Ok(cond) = cond {
- let url = win.Document().url();
- let context = ParserContext::new_for_cssom(
- &url,
- Some(CssRuleType::Style),
- ParsingMode::DEFAULT,
- QuirksMode::NoQuirks,
- None,
- None,
- );
- cond.eval(&context)
- } else {
- false
- }
+ let cond = match parse_condition_or_declaration(&mut input) {
+ Ok(c) => c,
+ Err(..) => return false,
+ };
+
+ let url = win.Document().url();
+ let context = ParserContext::new_for_cssom(
+ &url,
+ Some(CssRuleType::Style),
+ ParsingMode::DEFAULT,
+ QuirksMode::NoQuirks,
+ None,
+ None,
+ );
+ cond.eval(&context, &Default::default())
}
/// <https://drafts.css-houdini.org/css-paint-api-1/#paint-worklet>
diff --git a/components/script/dom/csssupportsrule.rs b/components/script/dom/csssupportsrule.rs
index 136a742e0e7..030a6c56be9 100644
--- a/components/script/dom/csssupportsrule.rs
+++ b/components/script/dom/csssupportsrule.rs
@@ -81,7 +81,17 @@ impl CSSSupportsRule {
None,
None,
);
- let enabled = cond.eval(&context);
+ let enabled = {
+ let namespaces =
+ self
+ .cssconditionrule
+ .parent_stylesheet()
+ .style_stylesheet()
+ .contents
+ .namespaces
+ .read();
+ cond.eval(&context, &namespaces)
+ };
let mut guard = self.cssconditionrule.shared_lock().write();
let rule = self.supportsrule.write_with(&mut guard);
rule.condition = cond;
diff --git a/components/selectors/parser.rs b/components/selectors/parser.rs
index 8e26ff63d8a..fc4b26bb3a3 100644
--- a/components/selectors/parser.rs
+++ b/components/selectors/parser.rs
@@ -259,8 +259,13 @@ where
Impl: SelectorImpl,
{
let location = input.current_source_location();
- let selector = Selector::parse(parser, input)?;
- // Ensure they're actually all compound selectors.
+ let selector = parse_selector(parser, input)?;
+
+ // Ensure they're actually all compound selectors without pseudo-elements.
+ if selector.has_pseudo_element() {
+ return Err(location.new_custom_error(SelectorParseErrorKind::PseudoElementInComplexSelector));
+ }
+
if selector.iter_raw_match_order().any(|s| s.is_combinator()) {
return Err(location.new_custom_error(SelectorParseErrorKind::NonCompoundSelector));
}
@@ -1397,6 +1402,7 @@ where
impl<Impl: SelectorImpl> Selector<Impl> {
/// Parse a selector, without any pseudo-element.
+ #[inline]
pub fn parse<'i, 't, P>(
parser: &P,
input: &mut CssParser<'i, 't>,
@@ -1404,12 +1410,7 @@ impl<Impl: SelectorImpl> Selector<Impl> {
where
P: Parser<'i, Impl = Impl>,
{
- let selector = parse_selector(parser, input)?;
- if selector.has_pseudo_element() {
- let e = SelectorParseErrorKind::PseudoElementInComplexSelector;
- return Err(input.new_custom_error(e));
- }
- Ok(selector)
+ parse_selector(parser, input)
}
}
diff --git a/components/style/build_gecko.rs b/components/style/build_gecko.rs
index 1ecc7ec6fc3..bee061fcc21 100644
--- a/components/style/build_gecko.rs
+++ b/components/style/build_gecko.rs
@@ -17,7 +17,7 @@ mod bindings {
use bindgen::{Builder, CodegenConfig};
use regex::Regex;
use std::cmp;
- use std::collections::{HashMap, HashSet};
+ use std::collections::HashSet;
use std::env;
use std::fs::{self, File};
use std::io::{Read, Write};
@@ -43,7 +43,7 @@ mod bindings {
.expect("Failed to open config file")
.read_to_string(&mut contents)
.expect("Failed to read config file");
- match toml::from_str::<toml::value::Table>(&contents) {
+ match toml::from_str::<Table>(&contents) {
Ok(result) => result,
Err(e) => panic!("Failed to parse config file: {}", e),
}
@@ -58,22 +58,10 @@ mod bindings {
};
static ref BUILD_CONFIG: Table = {
// Load build-specific config overrides.
- // FIXME: We should merge with CONFIG above instead of
- // forcing callers to do it.
let path = PathBuf::from(env::var_os("MOZ_TOPOBJDIR").unwrap())
.join("layout/style/bindgen.toml");
read_config(&path)
};
- static ref TARGET_INFO: HashMap<String, String> = {
- const TARGET_PREFIX: &'static str = "CARGO_CFG_TARGET_";
- let mut result = HashMap::new();
- for (k, v) in env::vars() {
- if k.starts_with(TARGET_PREFIX) {
- result.insert(k[TARGET_PREFIX.len()..].to_lowercase(), v);
- }
- }
- result
- };
static ref INCLUDE_RE: Regex = Regex::new(r#"#include\s*"(.+?)""#).unwrap();
static ref DISTDIR_PATH: PathBuf = {
let path = PathBuf::from(env::var_os("MOZ_DIST").unwrap());
@@ -145,35 +133,6 @@ mod bindings {
fn mutable_borrowed_type(self, ty: &str) -> Builder;
}
- fn add_clang_args(mut builder: Builder, config: &Table, matched_os: &mut bool) -> Builder {
- fn add_args(mut builder: Builder, values: &[toml::Value]) -> Builder {
- for item in values.iter() {
- builder = builder.clang_arg(item.as_str().expect("Expect string in list"));
- }
- builder
- }
- for (k, v) in config.iter() {
- if k == "args" {
- builder = add_args(builder, v.as_array().unwrap().as_slice());
- continue;
- }
- let equal_idx = k.find('=').expect(&format!("Invalid key: {}", k));
- let (target_type, target_value) = k.split_at(equal_idx);
- if TARGET_INFO[target_type] != target_value[1..] {
- continue;
- }
- if target_type == "os" {
- *matched_os = true;
- }
- builder = match *v {
- toml::Value::Table(ref table) => add_clang_args(builder, table, matched_os),
- toml::Value::Array(ref array) => add_args(builder, array),
- _ => panic!("Unknown type"),
- };
- }
- builder
- }
-
impl BuilderExt for Builder {
fn get_initial_builder() -> Builder {
use bindgen::RustTarget;
@@ -207,16 +166,14 @@ mod bindings {
builder = builder.clang_arg("-DDEBUG=1").clang_arg("-DJS_DEBUG=1");
}
- let mut matched_os = false;
- let build_config = CONFIG["build"].as_table().expect("Malformed config file");
- builder = add_clang_args(builder, build_config, &mut matched_os);
let build_config = BUILD_CONFIG["build"]
.as_table()
.expect("Malformed config file");
- builder = add_clang_args(builder, build_config, &mut matched_os);
- if !matched_os {
- panic!("Unknown platform");
+ let extra_bindgen_flags = build_config["args"].as_array().unwrap().as_slice();
+ for item in extra_bindgen_flags.iter() {
+ builder = builder.clang_arg(item.as_str().expect("Expect string in list"));
}
+
builder
}
fn include<T: Into<String>>(self, file: T) -> Builder {
@@ -300,35 +257,57 @@ mod bindings {
.expect("Unable to write output");
}
- fn get_arc_types() -> Vec<String> {
+ fn get_types(filename: &str, macro_pat: &str) -> Vec<(String, String)> {
// Read the file
- let mut list_file = File::open(DISTDIR_PATH.join("include/mozilla/ServoArcTypeList.h"))
- .expect("Unable to open ServoArcTypeList.h");
+ let path = DISTDIR_PATH.join("include/mozilla/").join(filename);
+ let mut list_file = File::open(path).expect(&format!("Unable to open {}", filename));
let mut content = String::new();
list_file
.read_to_string(&mut content)
- .expect("Fail to read ServoArcTypeList.h");
+ .expect(&format!("Failed to read {}", filename));
// Remove comments
let block_comment_re = Regex::new(r#"(?s)/\*.*?\*/"#).unwrap();
+ let line_comment_re = Regex::new(r#"//.*"#).unwrap();
let content = block_comment_re.replace_all(&content, "");
+ let content = line_comment_re.replace_all(&content, "");
// Extract the list
- let re = Regex::new(r#"^SERVO_ARC_TYPE\(\w+,\s*(\w+)\)$"#).unwrap();
+ let re_string = format!(r#"^({})\(.+,\s*(\w+)\)$"#, macro_pat);
+ let re = Regex::new(&re_string).unwrap();
content
.lines()
.map(|line| line.trim())
.filter(|line| !line.is_empty())
.map(|line| {
- re.captures(&line)
- .expect(&format!(
- "Unrecognized line in ServoArcTypeList.h: '{}'",
- line
- )).get(1)
- .unwrap()
- .as_str()
- .to_string()
+ let captures = re
+ .captures(&line)
+ .expect(&format!("Unrecognized line in {}: '{}'", filename, line));
+ let macro_name = captures.get(1).unwrap().as_str().to_string();
+ let type_name = captures.get(2).unwrap().as_str().to_string();
+ (macro_name, type_name)
}).collect()
}
+ fn get_borrowed_types() -> Vec<(bool, String)> {
+ get_types("BorrowedTypeList.h", "GECKO_BORROWED_TYPE(?:_MUT)?")
+ .into_iter()
+ .map(|(macro_name, type_name)| (macro_name.ends_with("MUT"), type_name))
+ .collect()
+ }
+
+ fn get_arc_types() -> Vec<String> {
+ get_types("ServoArcTypeList.h", "SERVO_ARC_TYPE")
+ .into_iter()
+ .map(|(_, type_name)| type_name)
+ .collect()
+ }
+
+ fn get_boxed_types() -> Vec<String> {
+ get_types("ServoBoxedTypeList.h", "SERVO_BOXED_TYPE")
+ .into_iter()
+ .map(|(_, type_name)| type_name)
+ .collect()
+ }
+
struct BuilderWithConfig<'a> {
builder: Builder,
config: &'a Table,
@@ -524,19 +503,6 @@ mod bindings {
"&'a mut ::gecko_bindings::structs::nsTArray<{}>;"),
cpp_type, rust_type))
})
- .handle_table_items("servo-owned-types", |mut builder, item| {
- let name = item["name"].as_str().unwrap();
- builder = builder.blacklist_type(format!("{}Owned", name))
- .raw_line(format!("pub type {0}Owned = ::gecko_bindings::sugar::ownership::Owned<{0}>;", name))
- .blacklist_type(format!("{}OwnedOrNull", name))
- .raw_line(format!(concat!("pub type {0}OwnedOrNull = ",
- "::gecko_bindings::sugar::ownership::OwnedOrNull<{0}>;"), name))
- .mutable_borrowed_type(name);
- if item["opaque"].as_bool().unwrap() {
- builder = builder.zero_size_type(name, &structs_types);
- }
- builder
- })
.handle_str_items("servo-immutable-borrow-types", |b, ty| b.borrowed_type(ty))
// Right now the only immutable borrow types are ones which we import
// from the |structs| module. As such, we don't need to create an opaque
@@ -544,6 +510,13 @@ mod bindings {
// which _do_ need to be opaque, we'll need a separate mode.
.handle_str_items("servo-borrow-types", |b, ty| b.mutable_borrowed_type(ty))
.get_builder();
+ for (is_mut, ty) in get_borrowed_types().iter() {
+ if *is_mut {
+ builder = builder.mutable_borrowed_type(ty);
+ } else {
+ builder = builder.borrowed_type(ty);
+ }
+ }
for ty in get_arc_types().iter() {
builder = builder
.blacklist_type(format!("{}Strong", ty))
@@ -553,6 +526,22 @@ mod bindings {
)).borrowed_type(ty)
.zero_size_type(ty, &structs_types);
}
+ for ty in get_boxed_types().iter() {
+ builder = builder
+ .blacklist_type(format!("{}Owned", ty))
+ .raw_line(format!(
+ "pub type {0}Owned = ::gecko_bindings::sugar::ownership::Owned<{0}>;",
+ ty
+ )).blacklist_type(format!("{}OwnedOrNull", ty))
+ .raw_line(format!(
+ concat!(
+ "pub type {0}OwnedOrNull = ",
+ "::gecko_bindings::sugar::ownership::OwnedOrNull<{0}>;"
+ ),
+ ty
+ )).mutable_borrowed_type(ty)
+ .zero_size_type(ty, &structs_types);
+ }
write_binding_file(builder, BINDINGS_FILE, &fixups);
}
diff --git a/components/style/gecko/arc_types.rs b/components/style/gecko/arc_types.rs
index 7351cbfeac4..0a9bf4d5ccc 100644
--- a/components/style/gecko/arc_types.rs
+++ b/components/style/gecko/arc_types.rs
@@ -8,6 +8,7 @@
#![allow(non_snake_case, missing_docs)]
+use gecko::url::CssUrlData;
use gecko_bindings::bindings::RawServoCounterStyleRule;
use gecko_bindings::bindings::RawServoFontFeatureValuesRule;
use gecko_bindings::bindings::RawServoImportRule;
@@ -22,6 +23,7 @@ use gecko_bindings::bindings::RawServoRuleNodeStrong;
use gecko_bindings::bindings::RawServoSupportsRule;
use gecko_bindings::bindings::ServoCssRules;
use gecko_bindings::structs::RawServoAnimationValue;
+use gecko_bindings::structs::RawServoCssUrlData;
use gecko_bindings::structs::RawServoDeclarationBlock;
use gecko_bindings::structs::RawServoFontFaceRule;
use gecko_bindings::structs::RawServoMediaList;
@@ -110,6 +112,9 @@ impl_arc_ffi!(Locked<FontFaceRule> => RawServoFontFaceRule
impl_arc_ffi!(Locked<CounterStyleRule> => RawServoCounterStyleRule
[Servo_CounterStyleRule_AddRef, Servo_CounterStyleRule_Release]);
+impl_arc_ffi!(CssUrlData => RawServoCssUrlData
+ [Servo_CssUrlData_AddRef, Servo_CssUrlData_Release]);
+
// RuleNode is a Arc-like type but it does not use Arc.
impl StrongRuleNode {
diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs
index 846f2113f77..10b177558fa 100644
--- a/components/style/gecko/conversions.rs
+++ b/components/style/gecko/conversions.rs
@@ -11,7 +11,7 @@
use app_units::Au;
use gecko::values::GeckoStyleCoordConvertible;
use gecko_bindings::bindings;
-use gecko_bindings::structs::{self, nsCSSUnit, nsStyleCoord_CalcValue};
+use gecko_bindings::structs::{self, nsStyleCoord_CalcValue};
use gecko_bindings::structs::{nsresult, SheetType, nsStyleImage};
use gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue};
use std::f32::consts::PI;
@@ -128,35 +128,7 @@ impl From<nsStyleCoord_CalcValue> for NonNegativeLengthOrPercentageOrAuto {
impl From<Angle> for CoordDataValue {
fn from(reference: Angle) -> Self {
- match reference {
- Angle::Deg(val) => CoordDataValue::Degree(val),
- Angle::Grad(val) => CoordDataValue::Grad(val),
- Angle::Rad(val) => CoordDataValue::Radian(val),
- Angle::Turn(val) => CoordDataValue::Turn(val),
- }
- }
-}
-
-impl Angle {
- /// Converts Angle struct into (value, unit) pair.
- pub fn to_gecko_values(&self) -> (f32, nsCSSUnit) {
- match *self {
- Angle::Deg(val) => (val, nsCSSUnit::eCSSUnit_Degree),
- Angle::Grad(val) => (val, nsCSSUnit::eCSSUnit_Grad),
- Angle::Rad(val) => (val, nsCSSUnit::eCSSUnit_Radian),
- Angle::Turn(val) => (val, nsCSSUnit::eCSSUnit_Turn),
- }
- }
-
- /// Converts gecko (value, unit) pair into Angle struct
- pub fn from_gecko_values(value: f32, unit: nsCSSUnit) -> Angle {
- match unit {
- nsCSSUnit::eCSSUnit_Degree => Angle::Deg(value),
- nsCSSUnit::eCSSUnit_Grad => Angle::Grad(value),
- nsCSSUnit::eCSSUnit_Radian => Angle::Rad(value),
- nsCSSUnit::eCSSUnit_Turn => Angle::Turn(value),
- _ => panic!("Unexpected unit for angle"),
- }
+ CoordDataValue::Degree(reference.degrees())
}
}
@@ -225,13 +197,13 @@ impl nsStyleImage {
match image {
GenericImage::Gradient(boxed_gradient) => self.set_gradient(*boxed_gradient),
GenericImage::Url(ref url) => unsafe {
- bindings::Gecko_SetLayerImageImageValue(self, url.0.image_value.get());
+ bindings::Gecko_SetLayerImageImageValue(self, (url.0).0.url_value.get());
},
GenericImage::Rect(ref image_rect) => {
unsafe {
bindings::Gecko_SetLayerImageImageValue(
self,
- image_rect.url.0.image_value.get(),
+ (image_rect.url.0).0.url_value.get(),
);
bindings::Gecko_InitializeImageCropRect(self);
diff --git a/components/style/gecko/data.rs b/components/style/gecko/data.rs
index d737167c28a..2ede2f5b81f 100644
--- a/components/style/gecko/data.rs
+++ b/components/style/gecko/data.rs
@@ -8,7 +8,7 @@ use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
use context::QuirksMode;
use dom::TElement;
use gecko_bindings::bindings::{self, RawServoStyleSet};
-use gecko_bindings::structs::{RawGeckoPresContextOwned, ServoStyleSetSizes, StyleSheet as DomStyleSheet};
+use gecko_bindings::structs::{RawGeckoPresContextBorrowed, ServoStyleSetSizes, StyleSheet as DomStyleSheet};
use gecko_bindings::structs::{StyleSheetInfo, nsIDocument};
use gecko_bindings::sugar::ownership::{HasArcFFI, HasBoxFFI, HasFFI, HasSimpleFFI};
use invalidation::media_queries::{MediaListKey, ToMediaListKey};
@@ -143,7 +143,7 @@ pub struct PerDocumentStyleData(AtomicRefCell<PerDocumentStyleDataImpl>);
impl PerDocumentStyleData {
/// Create a dummy `PerDocumentStyleData`.
- pub fn new(pres_context: RawGeckoPresContextOwned) -> Self {
+ pub fn new(pres_context: RawGeckoPresContextBorrowed) -> Self {
let device = Device::new(pres_context);
// FIXME(emilio, tlin): How is this supposed to work with XBL? This is
diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs
index 65855b0a8a3..d95c8df7028 100644
--- a/components/style/gecko/media_queries.rs
+++ b/components/style/gecko/media_queries.rs
@@ -12,7 +12,7 @@ use euclid::TypedScale;
use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
use gecko_bindings::bindings;
use gecko_bindings::structs;
-use gecko_bindings::structs::{nsPresContext, RawGeckoPresContextOwned};
+use gecko_bindings::structs::{nsPresContext, RawGeckoPresContextBorrowed};
use media_queries::MediaType;
use properties::ComputedValues;
use servo_arc::Arc;
@@ -30,7 +30,7 @@ pub struct Device {
/// NB: The pres context lifetime is tied to the styleset, who owns the
/// stylist, and thus the `Device`, so having a raw pres context pointer
/// here is fine.
- pres_context: RawGeckoPresContextOwned,
+ pres_context: RawGeckoPresContextBorrowed,
default_values: Arc<ComputedValues>,
/// The font size of the root element
/// This is set when computing the style of the root
@@ -77,7 +77,7 @@ unsafe impl Send for Device {}
impl Device {
/// Trivially constructs a new `Device`.
- pub fn new(pres_context: RawGeckoPresContextOwned) -> Self {
+ pub fn new(pres_context: RawGeckoPresContextBorrowed) -> Self {
assert!(!pres_context.is_null());
Device {
pres_context,
diff --git a/components/style/gecko/pseudo_element.rs b/components/style/gecko/pseudo_element.rs
index 70b0e112cee..23fea10189f 100644
--- a/components/style/gecko/pseudo_element.rs
+++ b/components/style/gecko/pseudo_element.rs
@@ -57,15 +57,6 @@ impl PseudoElement {
PseudoElementCascadeType::Lazy
}
- /// Whether cascading this pseudo-element makes it inherit all properties,
- /// even reset ones.
- ///
- /// This is used in Servo for anonymous boxes, though it's likely broken.
- #[inline]
- pub fn inherits_all(&self) -> bool {
- false
- }
-
/// Whether the pseudo-element should inherit from the default computed
/// values instead of from the parent element.
///
diff --git a/components/style/gecko/regen_atoms.py b/components/style/gecko/regen_atoms.py
index 097e2d6be37..36ec0f70434 100755
--- a/components/style/gecko/regen_atoms.py
+++ b/components/style/gecko/regen_atoms.py
@@ -35,10 +35,11 @@ class Atom:
self.original_ident = ident
self.value = value
self.hash = hash
- # The Gecko type: "nsStaticAtom", "nsICSSPseudoElement", or "nsIAnonBoxPseudo"
+ # The Gecko type: "nsStaticAtom", "nsCSSPseudoElementStaticAtom", or
+ # "nsAnonBoxPseudoStaticAtom".
self.ty = ty
# The type of atom: "Atom", "PseudoElement", "NonInheritingAnonBox",
- # or "InheritingAnonBox"
+ # or "InheritingAnonBox".
self.atom_type = atom_type
if self.is_pseudo() or self.is_anon_box():
self.pseudo_ident = (ident.split("_", 1))[1]
@@ -205,7 +206,7 @@ def write_atom_macro(atoms, file_name):
def write_pseudo_elements(atoms, target_filename):
pseudos = []
for atom in atoms:
- if atom.type() == "nsICSSPseudoElement" or atom.type() == "nsICSSAnonBoxPseudo":
+ if atom.type() == "nsCSSPseudoElementStaticAtom" or atom.type() == "nsCSSAnonBoxPseudoStaticAtom":
pseudos.append(atom)
pseudo_definition_template = os.path.join(GECKO_DIR, "pseudo_element_definition.mako.rs")
diff --git a/components/style/gecko/url.rs b/components/style/gecko/url.rs
index 8390196c523..64ea654ba0c 100644
--- a/components/style/gecko/url.rs
+++ b/components/style/gecko/url.rs
@@ -6,18 +6,16 @@
use cssparser::Parser;
use gecko_bindings::bindings;
-use gecko_bindings::structs::ServoBundledURI;
-use gecko_bindings::structs::mozilla::css::URLValueData;
-use gecko_bindings::structs::root::{RustString, nsStyleImageRequest};
use gecko_bindings::structs::root::mozilla::CORSMode;
-use gecko_bindings::structs::root::mozilla::css::{ImageValue, URLValue};
+use gecko_bindings::structs::root::mozilla::css::URLValue;
+use gecko_bindings::structs::root::nsStyleImageRequest;
+use gecko_bindings::sugar::ownership::{HasArcFFI, FFIArcHelpers};
use gecko_bindings::sugar::refptr::RefPtr;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use nsstring::nsCString;
use parser::{Parse, ParserContext};
-use servo_arc::{Arc, RawOffsetArc};
+use servo_arc::Arc;
use std::fmt::{self, Write};
-use std::mem;
use style_traits::{CssWriter, ParseError, ToCss};
use stylesheets::UrlExtraData;
use values::computed::{Context, ToComputedValue};
@@ -25,12 +23,13 @@ use values::computed::{Context, ToComputedValue};
/// A CSS url() value for gecko.
#[css(function = "url")]
#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
-pub struct CssUrl {
+pub struct CssUrl(pub Arc<CssUrlData>);
+
+/// Data shared between CssUrls.
+#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
+pub struct CssUrlData {
/// The URL in unresolved string form.
- ///
- /// Refcounted since cloning this should be cheap and data: uris can be
- /// really large.
- serialization: Arc<String>,
+ serialization: String,
/// The URL extra data.
#[css(skip)]
@@ -38,13 +37,12 @@ pub struct CssUrl {
}
impl CssUrl {
- /// Try to parse a URL from a string value that is a valid CSS token for a
- /// URL.
+ /// Parse a URL from a string value that is a valid CSS token for a URL.
pub fn parse_from_string(url: String, context: &ParserContext) -> Self {
- CssUrl {
- serialization: Arc::new(url),
+ CssUrl(Arc::new(CssUrlData {
+ serialization: url,
extra_data: context.url_data.clone(),
- }
+ }))
}
/// Returns true if the URL is definitely invalid. We don't eagerly resolve
@@ -54,43 +52,32 @@ impl CssUrl {
false
}
- /// Convert from URLValueData to SpecifiedUrl.
- unsafe fn from_url_value_data(url: &URLValueData) -> Self {
- let arc_type = &url.mString as *const _ as *const RawOffsetArc<String>;
- CssUrl {
- serialization: Arc::from_raw_offset((*arc_type).clone()),
- extra_data: UrlExtraData(url.mExtraData.to_safe()),
- }
- }
-
/// Returns true if this URL looks like a fragment.
/// See https://drafts.csswg.org/css-values/#local-urls
+ #[inline]
pub fn is_fragment(&self) -> bool {
- self.as_str().chars().next().map_or(false, |c| c == '#')
+ self.0.is_fragment()
}
/// Return the unresolved url as string, or the empty string if it's
/// invalid.
+ #[inline]
pub fn as_str(&self) -> &str {
- &*self.serialization
+ self.0.as_str()
}
+}
- /// Little helper for Gecko's ffi.
- pub fn as_slice_components(&self) -> (*const u8, usize) {
- (
- self.serialization.as_str().as_ptr(),
- self.serialization.as_str().len(),
- )
+impl CssUrlData {
+ /// Returns true if this URL looks like a fragment.
+ /// See https://drafts.csswg.org/css-values/#local-urls
+ pub fn is_fragment(&self) -> bool {
+ self.as_str().chars().next().map_or(false, |c| c == '#')
}
- /// Create a bundled URI suitable for sending to Gecko
- /// to be constructed into a css::URLValue
- pub fn for_ffi(&self) -> ServoBundledURI {
- let arc_offset = Arc::into_raw_offset(self.serialization.clone());
- ServoBundledURI {
- mURLString: unsafe { mem::transmute::<_, RawOffsetArc<RustString>>(arc_offset) },
- mExtraData: self.extra_data.0.get(),
- }
+ /// Return the unresolved url as string, or the empty string if it's
+ /// invalid.
+ pub fn as_str(&self) -> &str {
+ &*self.serialization
}
}
@@ -117,7 +104,7 @@ impl MallocSizeOf for CssUrl {
}
}
-/// A specified url() value for general usage.
+/// A specified non-image `url()` value.
#[derive(Clone, Debug, SpecifiedValueInfo, ToCss)]
pub struct SpecifiedUrl {
/// The specified url value.
@@ -129,72 +116,22 @@ pub struct SpecifiedUrl {
}
impl SpecifiedUrl {
- fn from_css_url(url: CssUrl) -> Self {
- let url_value = unsafe {
- let ptr = bindings::Gecko_NewURLValue(url.for_ffi());
- // We do not expect Gecko_NewURLValue returns null.
- debug_assert!(!ptr.is_null());
- RefPtr::from_addrefed(ptr)
- };
- Self { url, url_value }
- }
-}
-
-impl PartialEq for SpecifiedUrl {
- fn eq(&self, other: &Self) -> bool {
- self.url.eq(&other.url)
- }
-}
-
-impl Eq for SpecifiedUrl {}
-
-impl Parse for SpecifiedUrl {
- fn parse<'i, 't>(
- context: &ParserContext,
- input: &mut Parser<'i, 't>,
- ) -> Result<Self, ParseError<'i>> {
- CssUrl::parse(context, input).map(Self::from_css_url)
- }
-}
-
-impl MallocSizeOf for SpecifiedUrl {
- fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
- let mut n = self.url.size_of(ops);
- // Although this is a RefPtr, this is the primary reference because
- // SpecifiedUrl is responsible for creating the url_value. So we
- // measure unconditionally here.
- n += unsafe { bindings::Gecko_URLValue_SizeOfIncludingThis(self.url_value.get()) };
- n
- }
-}
-
-/// A specified url() value for image.
-///
-/// This exists so that we can construct `ImageValue` and reuse it.
-#[derive(Clone, Debug, SpecifiedValueInfo, ToCss)]
-pub struct SpecifiedImageUrl {
- /// The specified url value.
- pub url: CssUrl,
- /// Gecko's ImageValue so that we can reuse it while rematching a
- /// property with this specified value.
- #[css(skip)]
- pub image_value: RefPtr<ImageValue>,
-}
-
-impl SpecifiedImageUrl {
- /// Parse a URL from a string value. See SpecifiedUrl::parse_from_string.
+ /// Parse a URL from a string value.
pub fn parse_from_string(url: String, context: &ParserContext) -> Self {
Self::from_css_url(CssUrl::parse_from_string(url, context))
}
fn from_css_url_with_cors(url: CssUrl, cors: CORSMode) -> Self {
- let image_value = unsafe {
- let ptr = bindings::Gecko_ImageValue_Create(url.for_ffi(), cors);
- // We do not expect Gecko_ImageValue_Create returns null.
+ let url_value = unsafe {
+ let ptr = bindings::Gecko_URLValue_Create(
+ url.0.clone().into_strong(),
+ cors,
+ );
+ // We do not expect Gecko_URLValue_Create returns null.
debug_assert!(!ptr.is_null());
RefPtr::from_addrefed(ptr)
};
- Self { url, image_value }
+ Self { url, url_value }
}
fn from_css_url(url: CssUrl) -> Self {
@@ -206,18 +143,9 @@ impl SpecifiedImageUrl {
use gecko_bindings::structs::root::mozilla::CORSMode_CORS_ANONYMOUS;
Self::from_css_url_with_cors(url, CORSMode_CORS_ANONYMOUS)
}
-
- /// Provides an alternate method for parsing that associates the URL
- /// with anonymous CORS headers.
- pub fn parse_with_cors_anonymous<'i, 't>(
- context: &ParserContext,
- input: &mut Parser<'i, 't>,
- ) -> Result<Self, ParseError<'i>> {
- CssUrl::parse(context, input).map(Self::from_css_url_with_cors_anonymous)
- }
}
-impl Parse for SpecifiedImageUrl {
+impl Parse for SpecifiedUrl {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
@@ -226,21 +154,21 @@ impl Parse for SpecifiedImageUrl {
}
}
-impl PartialEq for SpecifiedImageUrl {
+impl PartialEq for SpecifiedUrl {
fn eq(&self, other: &Self) -> bool {
self.url.eq(&other.url)
}
}
-impl Eq for SpecifiedImageUrl {}
+impl Eq for SpecifiedUrl {}
-impl MallocSizeOf for SpecifiedImageUrl {
+impl MallocSizeOf for SpecifiedUrl {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
let mut n = self.url.size_of(ops);
// Although this is a RefPtr, this is the primary reference because
- // SpecifiedUrl is responsible for creating the image_value. So we
+ // SpecifiedUrl is responsible for creating the url_value. So we
// measure unconditionally here.
- n += unsafe { bindings::Gecko_ImageValue_SizeOfIncludingThis(self.image_value.get()) };
+ n += unsafe { bindings::Gecko_URLValue_SizeOfIncludingThis(self.url_value.get()) };
n
}
}
@@ -259,6 +187,37 @@ impl ToComputedValue for SpecifiedUrl {
}
}
+/// A specified image `url()` value.
+#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
+pub struct SpecifiedImageUrl(pub SpecifiedUrl);
+
+impl SpecifiedImageUrl {
+ /// Parse a URL from a string value that is a valid CSS token for a URL.
+ pub fn parse_from_string(url: String, context: &ParserContext) -> Self {
+ SpecifiedImageUrl(SpecifiedUrl::parse_from_string(url, context))
+ }
+
+ /// Provides an alternate method for parsing that associates the URL
+ /// with anonymous CORS headers.
+ pub fn parse_with_cors_anonymous<'i, 't>(
+ context: &ParserContext,
+ input: &mut Parser<'i, 't>,
+ ) -> Result<Self, ParseError<'i>> {
+ CssUrl::parse(context, input)
+ .map(SpecifiedUrl::from_css_url_with_cors_anonymous)
+ .map(SpecifiedImageUrl)
+ }
+}
+
+impl Parse for SpecifiedImageUrl {
+ fn parse<'i, 't>(
+ context: &ParserContext,
+ input: &mut Parser<'i, 't>,
+ ) -> Result<Self, ParseError<'i>> {
+ SpecifiedUrl::parse(context, input).map(SpecifiedImageUrl)
+ }
+}
+
impl ToComputedValue for SpecifiedImageUrl {
type ComputedValue = ComputedImageUrl;
@@ -274,9 +233,9 @@ impl ToComputedValue for SpecifiedImageUrl {
}
fn serialize_computed_url<W>(
- url_value_data: &URLValueData,
+ url_value: &URLValue,
dest: &mut CssWriter<W>,
- get_url: unsafe extern "C" fn(*const URLValueData, *mut nsCString),
+ get_url: unsafe extern "C" fn(*const URLValue, *mut nsCString),
) -> fmt::Result
where
W: Write,
@@ -284,13 +243,13 @@ where
dest.write_str("url(")?;
unsafe {
let mut string = nsCString::new();
- get_url(url_value_data, &mut string);
+ get_url(url_value, &mut string);
string.as_str_unchecked().to_css(dest)?;
}
dest.write_char(')')
}
-/// The computed value of a CSS `url()`.
+/// The computed value of a CSS non-image `url()`.
///
/// The only difference between specified and computed URLs is the
/// serialization.
@@ -303,7 +262,7 @@ impl ToCss for ComputedUrl {
W: Write,
{
serialize_computed_url(
- &self.0.url_value._base,
+ &self.0.url_value,
dest,
bindings::Gecko_GetComputedURLSpec,
)
@@ -313,12 +272,18 @@ impl ToCss for ComputedUrl {
impl ComputedUrl {
/// Convert from RefPtr<URLValue> to ComputedUrl.
pub unsafe fn from_url_value(url_value: RefPtr<URLValue>) -> Self {
- let url = CssUrl::from_url_value_data(&url_value._base);
+ let css_url = &*url_value.mCssUrl.mRawPtr;
+ let url = CssUrl(CssUrlData::as_arc(&css_url).clone_arc());
ComputedUrl(SpecifiedUrl { url, url_value })
}
+
+ /// Get a raw pointer to the URLValue held by this ComputedUrl, for FFI.
+ pub fn url_value_ptr(&self) -> *mut URLValue {
+ self.0.url_value.get()
+ }
}
-/// The computed value of a CSS `url()` for image.
+/// The computed value of a CSS image `url()`.
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)]
pub struct ComputedImageUrl(pub SpecifiedImageUrl);
@@ -328,7 +293,7 @@ impl ToCss for ComputedImageUrl {
W: Write,
{
serialize_computed_url(
- &self.0.image_value._base,
+ &(self.0).0.url_value,
dest,
bindings::Gecko_GetComputedImageURLSpec,
)
@@ -338,8 +303,14 @@ impl ToCss for ComputedImageUrl {
impl ComputedImageUrl {
/// Convert from nsStyleImageReques to ComputedImageUrl.
pub unsafe fn from_image_request(image_request: &nsStyleImageRequest) -> Self {
- let image_value = image_request.mImageValue.to_safe();
- let url = CssUrl::from_url_value_data(&image_value._base);
- ComputedImageUrl(SpecifiedImageUrl { url, image_value })
+ let url_value = image_request.mImageValue.to_safe();
+ let css_url = &*url_value.mCssUrl.mRawPtr;
+ let url = CssUrl(CssUrlData::as_arc(&css_url).clone_arc());
+ ComputedImageUrl(SpecifiedImageUrl(SpecifiedUrl { url, url_value }))
+ }
+
+ /// Get a raw pointer to the URLValue held by this ComputedImageUrl, for FFI.
+ pub fn url_value_ptr(&self) -> *mut URLValue {
+ (self.0).0.url_value.get()
}
}
diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs
index fed9dc161c0..4b982404809 100644
--- a/components/style/gecko/values.rs
+++ b/components/style/gecko/values.rs
@@ -19,7 +19,7 @@ use std::cmp::max;
use values::{Auto, Either, None_, Normal};
use values::computed::{Angle, ExtremumLength, Length, LengthOrPercentage, LengthOrPercentageOrAuto};
use values::computed::{LengthOrPercentageOrNone, Number, NumberOrPercentage};
-use values::computed::{MaxLength, MozLength, Percentage};
+use values::computed::{MaxLength as ComputedMaxLength, MozLength as ComputedMozLength, Percentage};
use values::computed::{NonNegativeLength, NonNegativeLengthOrPercentage, NonNegativeNumber};
use values::computed::FlexBasis as ComputedFlexBasis;
use values::computed::basic_shape::ShapeRadius as ComputedShapeRadius;
@@ -29,6 +29,7 @@ use values::generics::box_::Perspective;
use values::generics::flex::FlexBasis;
use values::generics::gecko::ScrollSnapPoint;
use values::generics::grid::{TrackBreadth, TrackKeyword};
+use values::generics::length::{MaxLength, MozLength};
/// A trait that defines an interface to convert from and to `nsStyleCoord`s.
pub trait GeckoStyleCoordConvertible: Sized {
@@ -74,7 +75,7 @@ impl GeckoStyleCoordConvertible for ComputedFlexBasis {
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
- if let Some(width) = MozLength::from_gecko_style_coord(coord) {
+ if let Some(width) = ComputedMozLength::from_gecko_style_coord(coord) {
return Some(FlexBasis::Width(width));
}
@@ -325,10 +326,7 @@ impl GeckoStyleCoordConvertible for Angle {
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
match coord.as_value() {
- CoordDataValue::Degree(val) => Some(Angle::Deg(val)),
- CoordDataValue::Grad(val) => Some(Angle::Grad(val)),
- CoordDataValue::Radian(val) => Some(Angle::Rad(val)),
- CoordDataValue::Turn(val) => Some(Angle::Turn(val)),
+ CoordDataValue::Degree(val) => Some(Angle::from_degrees(val)),
_ => None,
}
}
@@ -409,7 +407,7 @@ impl GeckoStyleCoordConvertible for ExtremumLength {
}
}
-impl GeckoStyleCoordConvertible for MozLength {
+impl GeckoStyleCoordConvertible for ComputedMozLength {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self {
MozLength::LengthOrPercentageOrAuto(ref lopoa) => lopoa.to_gecko_style_coord(coord),
@@ -426,7 +424,7 @@ impl GeckoStyleCoordConvertible for MozLength {
}
}
-impl GeckoStyleCoordConvertible for MaxLength {
+impl GeckoStyleCoordConvertible for ComputedMaxLength {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self {
MaxLength::LengthOrPercentageOrNone(ref lopon) => lopon.to_gecko_style_coord(coord),
diff --git a/components/style/gecko_bindings/sugar/ns_css_value.rs b/components/style/gecko_bindings/sugar/ns_css_value.rs
index ed8892028fe..f41150712b3 100644
--- a/components/style/gecko_bindings/sugar/ns_css_value.rs
+++ b/components/style/gecko_bindings/sugar/ns_css_value.rs
@@ -60,7 +60,7 @@ impl nsCSSValue {
pub unsafe fn array_unchecked(&self) -> &nsCSSValue_Array {
debug_assert!(
nsCSSUnit::eCSSUnit_Array as u32 <= self.mUnit as u32 &&
- self.mUnit as u32 <= nsCSSUnit::eCSSUnit_Calc_Divided as u32
+ self.mUnit as u32 <= nsCSSUnit::eCSSUnit_Calc_Plus as u32
);
let array = *self.mValue.mArray.as_ref();
debug_assert!(!array.is_null());
@@ -198,19 +198,19 @@ impl nsCSSValue {
/// Returns an `Angle` value from this `nsCSSValue`.
///
- /// Panics if the unit is not `eCSSUnit_Degree` `eCSSUnit_Grad`, `eCSSUnit_Turn`
- /// or `eCSSUnit_Radian`.
+ /// Panics if the unit is not `eCSSUnit_Degree`.
+ #[inline]
pub fn get_angle(&self) -> Angle {
- Angle::from_gecko_values(self.float_unchecked(), self.mUnit)
+ debug_assert_eq!(self.mUnit, nsCSSUnit::eCSSUnit_Degree);
+ Angle::from_degrees(self.float_unchecked())
}
/// Sets Angle value to this nsCSSValue.
pub fn set_angle(&mut self, angle: Angle) {
debug_assert_eq!(self.mUnit, nsCSSUnit::eCSSUnit_Null);
- let (value, unit) = angle.to_gecko_values();
- self.mUnit = unit;
+ self.mUnit = nsCSSUnit::eCSSUnit_Degree;
unsafe {
- *self.mValue.mFloat.as_mut() = value;
+ *self.mValue.mFloat.as_mut() = angle.degrees();
}
}
diff --git a/components/style/gecko_bindings/sugar/ns_style_coord.rs b/components/style/gecko_bindings/sugar/ns_style_coord.rs
index bc3b195524d..a4220f8c53c 100644
--- a/components/style/gecko_bindings/sugar/ns_style_coord.rs
+++ b/components/style/gecko_bindings/sugar/ns_style_coord.rs
@@ -200,12 +200,6 @@ pub enum CoordDataValue {
Factor(f32),
/// eStyleUnit_Degree
Degree(f32),
- /// eStyleUnit_Grad
- Grad(f32),
- /// eStyleUnit_Radian
- Radian(f32),
- /// eStyleUnit_Turn
- Turn(f32),
/// eStyleUnit_FlexFraction
FlexFraction(f32),
/// eStyleUnit_Coord
@@ -317,18 +311,6 @@ pub unsafe trait CoordDataMut: CoordData {
*unit = eStyleUnit_Degree;
*union.mFloat.as_mut() = f;
},
- Grad(f) => {
- *unit = eStyleUnit_Grad;
- *union.mFloat.as_mut() = f;
- },
- Radian(f) => {
- *unit = eStyleUnit_Radian;
- *union.mFloat.as_mut() = f;
- },
- Turn(f) => {
- *unit = eStyleUnit_Turn;
- *union.mFloat.as_mut() = f;
- },
FlexFraction(f) => {
*unit = eStyleUnit_FlexFraction;
*union.mFloat.as_mut() = f;
@@ -393,9 +375,6 @@ pub unsafe trait CoordData {
eStyleUnit_Percent => Percent(self.get_float()),
eStyleUnit_Factor => Factor(self.get_float()),
eStyleUnit_Degree => Degree(self.get_float()),
- eStyleUnit_Grad => Grad(self.get_float()),
- eStyleUnit_Radian => Radian(self.get_float()),
- eStyleUnit_Turn => Turn(self.get_float()),
eStyleUnit_FlexFraction => FlexFraction(self.get_float()),
eStyleUnit_Coord => Coord(self.get_integer()),
eStyleUnit_Integer => Integer(self.get_integer()),
@@ -413,9 +392,6 @@ pub unsafe trait CoordData {
self.unit() == eStyleUnit_Percent ||
self.unit() == eStyleUnit_Factor ||
self.unit() == eStyleUnit_Degree ||
- self.unit() == eStyleUnit_Grad ||
- self.unit() == eStyleUnit_Radian ||
- self.unit() == eStyleUnit_Turn ||
self.unit() == eStyleUnit_FlexFraction
);
*self.union().mFloat.as_ref()
diff --git a/components/style/gecko_bindings/sugar/ns_t_array.rs b/components/style/gecko_bindings/sugar/ns_t_array.rs
index bf5e168b5ef..72a7481fe96 100644
--- a/components/style/gecko_bindings/sugar/ns_t_array.rs
+++ b/components/style/gecko_bindings/sugar/ns_t_array.rs
@@ -82,9 +82,9 @@ impl<T> nsTArray<T> {
/// Resize and set the length of the array to `len`.
///
- /// unsafe because the array may contain uninitialized members.
+ /// unsafe because this may leave the array with uninitialized elements.
///
- /// This will not call constructors, if you need that, either manually add
+ /// This will not call constructors. If you need that, either manually add
/// bindings or run the typed `EnsureCapacity` call on the gecko side.
pub unsafe fn set_len(&mut self, len: u32) {
// this can leak
@@ -96,6 +96,8 @@ impl<T> nsTArray<T> {
/// Resizes an array containing only POD elements
///
+ /// unsafe because this may leave the array with uninitialized elements.
+ ///
/// This will not leak since it only works on POD types (and thus doesn't assert)
pub unsafe fn set_len_pod(&mut self, len: u32)
where
@@ -105,4 +107,17 @@ impl<T> nsTArray<T> {
let header = self.header_mut();
header.mLength = len;
}
+
+ /// Collects the given iterator into this array.
+ ///
+ /// Not unsafe because we won't leave uninitialized elements in the array.
+ pub fn assign_from_iter_pod<I>(&mut self, iter: I)
+ where
+ T: Copy,
+ I: ExactSizeIterator + Iterator<Item = T>,
+ {
+ debug_assert!(iter.len() <= 0xFFFFFFFF);
+ unsafe { self.set_len_pod(iter.len() as u32); }
+ self.iter_mut().zip(iter).for_each(|(r, v)| *r = v);
+ }
}
diff --git a/components/style/gecko_bindings/sugar/refptr.rs b/components/style/gecko_bindings/sugar/refptr.rs
index 835e77098c9..d7e7141e602 100644
--- a/components/style/gecko_bindings/sugar/refptr.rs
+++ b/components/style/gecko_bindings/sugar/refptr.rs
@@ -298,11 +298,6 @@ impl_threadsafe_refcount!(
bindings::Gecko_ReleaseGridTemplateAreasValueArbitraryThread
);
impl_threadsafe_refcount!(
- structs::ImageValue,
- bindings::Gecko_AddRefImageValueArbitraryThread,
- bindings::Gecko_ReleaseImageValueArbitraryThread
-);
-impl_threadsafe_refcount!(
structs::SharedFontList,
bindings::Gecko_AddRefSharedFontListArbitraryThread,
bindings::Gecko_ReleaseSharedFontListArbitraryThread
diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs
index 8b6298b01d2..04e65b5fa7f 100644
--- a/components/style/properties/gecko.mako.rs
+++ b/components/style/properties/gecko.mako.rs
@@ -689,7 +689,10 @@ def set_gecko_property(ffi_name, expr):
}
SVGPaintKind::PaintServer(url) => {
unsafe {
- bindings::Gecko_nsStyleSVGPaint_SetURLValue(paint, url.0.url_value.get());
+ bindings::Gecko_nsStyleSVGPaint_SetURLValue(
+ paint,
+ url.url_value_ptr(),
+ )
}
}
SVGPaintKind::Color(color) => {
@@ -1370,35 +1373,22 @@ impl Clone for ${style_struct.gecko_struct_name} {
}
</%def>
-<%def name="impl_font_settings(ident, tag_type, value_type, gecko_value_type)">
+<%def name="impl_font_settings(ident, gecko_type, tag_type, value_type, gecko_value_type)">
<%
gecko_ffi_name = to_camel_case_lower(ident)
%>
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
- let current_settings = &mut self.gecko.mFont.${gecko_ffi_name};
- current_settings.clear_pod();
-
- unsafe { current_settings.set_len_pod(v.0.len() as u32) };
-
- for (current, other) in current_settings.iter_mut().zip(v.0.iter()) {
- current.mTag = other.tag.0;
- current.mValue = other.value as ${gecko_value_type};
- }
+ let iter = v.0.iter().map(|other| structs::${gecko_type} {
+ mTag: other.tag.0,
+ mValue: other.value as ${gecko_value_type},
+ });
+ self.gecko.mFont.${gecko_ffi_name}.assign_from_iter_pod(iter);
}
pub fn copy_${ident}_from(&mut self, other: &Self) {
- let current_settings = &mut self.gecko.mFont.${gecko_ffi_name};
- let other_settings = &other.gecko.mFont.${gecko_ffi_name};
- let settings_length = other_settings.len() as u32;
-
- current_settings.clear_pod();
- unsafe { current_settings.set_len_pod(settings_length) };
-
- for (current, other) in current_settings.iter_mut().zip(other_settings.iter()) {
- current.mTag = other.mTag;
- current.mValue = other.mValue;
- }
+ let iter = other.gecko.mFont.${gecko_ffi_name}.iter().map(|s| *s);
+ self.gecko.mFont.${gecko_ffi_name}.assign_from_iter_pod(iter);
}
pub fn reset_${ident}(&mut self, other: &Self) {
@@ -2271,8 +2261,8 @@ fn static_assert() {
// Negative numbers are invalid at parse time, but <integer> is still an
// i32.
- <% impl_font_settings("font_feature_settings", "FeatureTagValue", "i32", "u32") %>
- <% impl_font_settings("font_variation_settings", "VariationValue", "f32", "f32") %>
+ <% impl_font_settings("font_feature_settings", "gfxFontFeature", "FeatureTagValue", "i32", "u32") %>
+ <% impl_font_settings("font_variation_settings", "gfxFontVariation", "VariationValue", "f32", "f32") %>
pub fn fixup_none_generic(&mut self, device: &Device) {
self.gecko.mFont.systemFont = false;
@@ -3210,28 +3200,16 @@ fn static_assert() {
where I: IntoIterator<Item = longhands::scroll_snap_coordinate::computed_value::single_value::T>,
I::IntoIter: ExactSizeIterator
{
- let v = v.into_iter();
-
- unsafe { self.gecko.mScrollSnapCoordinate.set_len_pod(v.len() as u32); }
- for (gecko, servo) in self.gecko.mScrollSnapCoordinate
- .iter_mut()
- .zip(v) {
- gecko.mXPosition = servo.horizontal.into();
- gecko.mYPosition = servo.vertical.into();
- }
+ let iter = v.into_iter().map(|c| structs::mozilla::Position {
+ mXPosition: c.horizontal.into(),
+ mYPosition: c.vertical.into(),
+ });
+ self.gecko.mScrollSnapCoordinate.assign_from_iter_pod(iter);
}
pub fn copy_scroll_snap_coordinate_from(&mut self, other: &Self) {
- unsafe {
- self.gecko.mScrollSnapCoordinate
- .set_len_pod(other.gecko.mScrollSnapCoordinate.len() as u32);
- }
-
- for (this, that) in self.gecko.mScrollSnapCoordinate
- .iter_mut()
- .zip(other.gecko.mScrollSnapCoordinate.iter()) {
- *this = *that;
- }
+ let iter = other.gecko.mScrollSnapCoordinate.iter().map(|c| *c);
+ self.gecko.mScrollSnapCoordinate.assign_from_iter_pod(iter);
}
pub fn reset_scroll_snap_coordinate(&mut self, other: &Self) {
@@ -4153,7 +4131,10 @@ fn static_assert() {
}
UrlOrNone::Url(ref url) => {
unsafe {
- Gecko_SetListStyleImageImageValue(&mut self.gecko, url.0.image_value.get());
+ Gecko_SetListStyleImageImageValue(
+ &mut self.gecko,
+ url.url_value_ptr(),
+ );
}
}
}
@@ -4989,12 +4970,12 @@ fn set_style_svg_path(
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()) {
+
+ let iter = servo_path.commands().iter().map(|command| {
// unsafe: cbindgen ensures the representation is the same.
- *gecko = unsafe { transmute(*servo) };
- }
+ unsafe { transmute(*command) }
+ });
+ gecko_path.mPath.assign_from_iter_pod(iter);
// Setup fill-rule.
// unsafe: cbindgen ensures the representation is the same.
@@ -5358,7 +5339,7 @@ clip-path
unsafe {
Gecko_SetCursorImageValue(
&mut self.gecko.mCursorImages[i],
- v.images[i].url.0.image_value.get(),
+ v.images[i].url.url_value_ptr(),
);
}
@@ -5659,7 +5640,7 @@ clip-path
unsafe {
bindings::Gecko_SetContentDataImageValue(
&mut self.gecko.mContents[i],
- url.0.image_value.get(),
+ url.url_value_ptr(),
)
}
}
diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs
index 98a74854b8d..5259f66107d 100644
--- a/components/style/properties/helpers/animated_properties.mako.rs
+++ b/components/style/properties/helpers/animated_properties.mako.rs
@@ -9,7 +9,7 @@
from itertools import groupby
%>
-#[cfg(feature = "gecko")] use gecko_bindings::bindings::RawServoAnimationValueMap;
+#[cfg(feature = "gecko")] use gecko_bindings::structs::RawServoAnimationValueMap;
#[cfg(feature = "gecko")] use gecko_bindings::structs::RawGeckoGfxMatrix4x4;
#[cfg(feature = "gecko")] use gecko_bindings::structs::nsCSSPropertyID;
#[cfg(feature = "gecko")] use gecko_bindings::sugar::ownership::{HasFFI, HasSimpleFFI};
@@ -35,7 +35,7 @@ use values::animated::effects::Filter as AnimatedFilter;
use values::computed::{Angle, CalcLengthOrPercentage};
use values::computed::{ClipRect, Context};
use values::computed::{Length, LengthOrPercentage, LengthOrPercentageOrAuto};
-use values::computed::{LengthOrPercentageOrNone, MaxLength};
+use values::computed::LengthOrPercentageOrNone;
use values::computed::{NonNegativeNumber, Number, NumberOrPercentage, Percentage};
use values::computed::length::NonNegativeLengthOrPercentage;
use values::computed::ToComputedValue;
@@ -893,11 +893,6 @@ impl ToAnimatedZero for LengthOrPercentageOrNone {
}
}
-impl ToAnimatedZero for MaxLength {
- #[inline]
- fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
-}
-
impl ToAnimatedZero for FontWeight {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
diff --git a/components/style/properties/longhands/border.mako.rs b/components/style/properties/longhands/border.mako.rs
index 1066dbbc619..f4b9187b88a 100644
--- a/components/style/properties/longhands/border.mako.rs
+++ b/components/style/properties/longhands/border.mako.rs
@@ -111,7 +111,7 @@ ${helpers.predefined_type(
vector=False,
animation_value_type="discrete",
flags="APPLIES_TO_FIRST_LETTER",
- boxed=True,
+ boxed=product == "servo",
)}
${helpers.predefined_type(
diff --git a/components/style/properties/longhands/inherited_text.mako.rs b/components/style/properties/longhands/inherited_text.mako.rs
index de7b613a183..164f8a7dea1 100644
--- a/components/style/properties/longhands/inherited_text.mako.rs
+++ b/components/style/properties/longhands/inherited_text.mako.rs
@@ -23,7 +23,7 @@ ${helpers.predefined_type(
${helpers.single_keyword(
"text-transform",
"none capitalize uppercase lowercase",
- extra_gecko_values="full-width",
+ extra_gecko_values="full-width full-size-kana",
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",
diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs
index 5968d84bd33..330ceea7f84 100644
--- a/components/style/properties/properties.mako.rs
+++ b/components/style/properties/properties.mako.rs
@@ -1671,53 +1671,30 @@ impl PropertyId {
///
/// Returns Err(()) for unknown non-custom properties.
fn parse_unchecked(property_name: &str) -> Result<Self, ()> {
- // FIXME(https://github.com/rust-lang/rust/issues/33156): remove this
- // enum and use PropertyId when stable Rust allows destructors in
- // statics.
- //
- // ShorthandAlias is not used in the Servo build.
- // That's why we need to allow dead_code.
- #[allow(dead_code)]
- pub enum StaticId {
- Longhand(LonghandId),
- Shorthand(ShorthandId),
- LonghandAlias(LonghandId, AliasId),
- ShorthandAlias(ShorthandId, AliasId),
- }
ascii_case_insensitive_phf_map! {
- static_id -> StaticId = {
+ property_id -> PropertyId = {
% for (kind, properties) in [("Longhand", data.longhands), ("Shorthand", data.shorthands)]:
- % for property in properties:
- "${property.name}" => StaticId::${kind}(${kind}Id::${property.camel_case}),
- % for alias in property.alias:
- "${alias.name}" => {
- StaticId::${kind}Alias(${kind}Id::${property.camel_case},
- AliasId::${alias.camel_case})
- },
- % endfor
- % endfor
+ % for property in properties:
+ "${property.name}" => PropertyId::${kind}(${kind}Id::${property.camel_case}),
+ % for alias in property.alias:
+ "${alias.name}" => {
+ PropertyId::${kind}Alias(
+ ${kind}Id::${property.camel_case},
+ AliasId::${alias.camel_case},
+ )
+ },
+ % endfor
+ % endfor
% endfor
}
}
- Ok(match static_id(property_name) {
- Some(&StaticId::Longhand(id)) => {
- PropertyId::Longhand(id)
- },
- Some(&StaticId::Shorthand(id)) => {
- PropertyId::Shorthand(id)
- },
- Some(&StaticId::LonghandAlias(id, alias)) => {
- PropertyId::LonghandAlias(id, alias)
- },
- Some(&StaticId::ShorthandAlias(id, alias)) => {
- PropertyId::ShorthandAlias(id, alias)
- },
- None => {
- let name = ::custom_properties::parse_name(property_name)?;
- PropertyId::Custom(::custom_properties::Name::from(name))
- },
- })
+ if let Some(id) = property_id(property_name) {
+ return Ok(id.clone())
+ }
+
+ let name = ::custom_properties::parse_name(property_name)?;
+ Ok(PropertyId::Custom(::custom_properties::Name::from(name)))
}
/// Parses a property name, and returns an error if it's unknown or isn't
@@ -3137,7 +3114,8 @@ pub enum StyleStructRef<'a, T: 'static> {
}
impl<'a, T: 'a> StyleStructRef<'a, T>
- where T: Clone,
+where
+ T: Clone,
{
/// Ensure a mutable reference of this value exists, either cloning the
/// borrowed value, or returning the owned one.
@@ -3153,6 +3131,22 @@ impl<'a, T: 'a> StyleStructRef<'a, T>
}
}
+ /// Whether this is pointer-equal to the struct we're going to copy the
+ /// value from.
+ ///
+ /// This is used to avoid allocations when people write stuff like `font:
+ /// inherit` or such `all: initial`.
+ #[inline]
+ pub fn ptr_eq(&self, struct_to_copy_from: &T) -> bool {
+ match *self {
+ StyleStructRef::Owned(..) => false,
+ StyleStructRef::Borrowed(arc) => {
+ &**arc as *const T == struct_to_copy_from as *const T
+ }
+ StyleStructRef::Vacated => panic!("Accessed vacated style struct")
+ }
+ }
+
/// Extract a unique Arc from this struct, vacating it.
///
/// The vacated state is a transient one, please put the Arc back
@@ -3281,15 +3275,6 @@ impl<'a> StyleBuilder<'a> {
let reset_style = device.default_computed_values();
let inherited_style = parent_style.unwrap_or(reset_style);
let inherited_style_ignoring_first_line = parent_style_ignoring_first_line.unwrap_or(reset_style);
- // FIXME(bz): inherits_all seems like a fundamentally broken idea. I'm
- // 99% sure it should give incorrect behavior for table anonymous box
- // backgrounds, for example. This code doesn't attempt to make it play
- // nice with inherited_style_ignoring_first_line.
- let reset_style = if pseudo.map_or(false, |p| p.inherits_all()) {
- inherited_style
- } else {
- reset_style
- };
let flags = inherited_style.flags.inherited();
@@ -3388,6 +3373,10 @@ impl<'a> StyleBuilder<'a> {
self.flags.insert(ComputedValueFlags::INHERITS_DISPLAY);
% endif
+ if self.${property.style_struct.ident}.ptr_eq(inherited_struct) {
+ return;
+ }
+
self.${property.style_struct.ident}.mutate()
.copy_${property.ident}_from(
inherited_struct,
@@ -3407,10 +3396,10 @@ impl<'a> StyleBuilder<'a> {
self.modified_reset = true;
% endif
- // TODO(emilio): There's a maybe-worth it optimization here: We should
- // avoid allocating a new reset struct if `reset_struct` and our struct
- // is the same pointer. Would remove a bunch of stupid allocations if
- // you did something like `* { all: initial }` or what not.
+ if self.${property.style_struct.ident}.ptr_eq(reset_struct) {
+ return;
+ }
+
self.${property.style_struct.ident}.mutate()
.reset_${property.ident}(
reset_struct,
diff --git a/components/style/servo/selector_parser.rs b/components/style/servo/selector_parser.rs
index 7b2c06019a4..de8257dcc4c 100644
--- a/components/style/servo/selector_parser.rs
+++ b/components/style/servo/selector_parser.rs
@@ -221,11 +221,6 @@ impl PseudoElement {
}
}
- /// To be removed.
- pub fn inherits_all(&self) -> bool {
- false
- }
-
/// Covert non-canonical pseudo-element to canonical one, and keep a
/// canonical one as it is.
pub fn canonical(&self) -> PseudoElement {
diff --git a/components/style/servo/url.rs b/components/style/servo/url.rs
index 91521c8a120..56213e4978e 100644
--- a/components/style/servo/url.rs
+++ b/components/style/servo/url.rs
@@ -23,6 +23,9 @@ use values::computed::{Context, ToComputedValue};
///
/// However, this approach is still not necessarily optimal: See
/// <https://bugzilla.mozilla.org/show_bug.cgi?id=1347435#c6>
+///
+/// TODO(emilio): This should be shrunk by making CssUrl a wrapper type of an
+/// arc, and keep the serialization in that Arc. See gecko/url.rs for example.
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize, SpecifiedValueInfo)]
pub struct CssUrl {
/// The original URI. This might be optional since we may insert computed
diff --git a/components/style/stylesheets/font_feature_values_rule.rs b/components/style/stylesheets/font_feature_values_rule.rs
index 76170151c67..f1353744f08 100644
--- a/components/style/stylesheets/font_feature_values_rule.rs
+++ b/components/style/stylesheets/font_feature_values_rule.rs
@@ -179,12 +179,7 @@ impl Parse for VectorValues {
#[cfg(feature = "gecko")]
impl ToGeckoFontFeatureValues for VectorValues {
fn to_gecko_font_feature_values(&self, array: &mut nsTArray<u32>) {
- unsafe {
- array.set_len_pod(self.0.len() as u32);
- }
- for (dest, value) in array.iter_mut().zip(self.0.iter()) {
- *dest = *value;
- }
+ array.assign_from_iter_pod(self.0.iter().map(|v| *v));
}
}
diff --git a/components/style/stylesheets/mod.rs b/components/style/stylesheets/mod.rs
index 5058ad94e80..81726950665 100644
--- a/components/style/stylesheets/mod.rs
+++ b/components/style/stylesheets/mod.rs
@@ -277,7 +277,6 @@ impl CssRule {
// nested rules are in the body state
let mut rule_parser = TopLevelRuleParser {
- stylesheet_origin: parent_stylesheet_contents.origin,
context,
shared_lock: &shared_lock,
loader,
diff --git a/components/style/stylesheets/rule_parser.rs b/components/style/stylesheets/rule_parser.rs
index 683378b9b96..aa449c70e93 100644
--- a/components/style/stylesheets/rule_parser.rs
+++ b/components/style/stylesheets/rule_parser.rs
@@ -19,7 +19,7 @@ use servo_arc::Arc;
use shared_lock::{Locked, SharedRwLock};
use str::starts_with_ignore_ascii_case;
use style_traits::{ParseError, StyleParseErrorKind};
-use stylesheets::{CssRule, CssRuleType, CssRules, Origin, RulesMutateError, StylesheetLoader};
+use stylesheets::{CssRule, CssRuleType, CssRules, RulesMutateError, StylesheetLoader};
use stylesheets::{DocumentRule, FontFeatureValuesRule, KeyframesRule, MediaRule};
use stylesheets::{NamespaceRule, PageRule, StyleRule, SupportsRule, ViewportRule};
use stylesheets::document_rule::DocumentCondition;
@@ -41,8 +41,6 @@ pub struct InsertRuleContext<'a> {
/// The parser for the top-level rules in a stylesheet.
pub struct TopLevelRuleParser<'a> {
- /// The origin of the stylesheet we're parsing.
- pub stylesheet_origin: Origin,
/// A reference to the lock we need to use to create rules.
pub shared_lock: &'a SharedRwLock,
/// A reference to a stylesheet loader if applicable, for `@import` rules.
@@ -69,7 +67,6 @@ pub struct TopLevelRuleParser<'a> {
impl<'b> TopLevelRuleParser<'b> {
fn nested<'a: 'b>(&'a self) -> NestedRuleParser<'a, 'b> {
NestedRuleParser {
- stylesheet_origin: self.stylesheet_origin,
shared_lock: self.shared_lock,
context: &self.context,
namespaces: &self.namespaces,
@@ -325,7 +322,6 @@ impl<'a, 'i> QualifiedRuleParser<'i> for TopLevelRuleParser<'a> {
#[derive(Clone)] // shallow, relatively cheap .clone
struct NestedRuleParser<'a, 'b: 'a> {
- stylesheet_origin: Origin,
shared_lock: &'a SharedRwLock,
context: &'a ParserContext<'b>,
namespaces: &'a Namespaces,
@@ -340,7 +336,6 @@ impl<'a, 'b> NestedRuleParser<'a, 'b> {
let context = ParserContext::new_with_rule_type(self.context, rule_type, self.namespaces);
let nested_parser = NestedRuleParser {
- stylesheet_origin: self.stylesheet_origin,
shared_lock: self.shared_lock,
context: &context,
namespaces: self.namespaces,
@@ -501,7 +496,7 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> {
self.namespaces,
);
- let enabled = condition.eval(&eval_context);
+ let enabled = condition.eval(&eval_context, self.namespaces);
Ok(CssRule::Supports(Arc::new(self.shared_lock.wrap(
SupportsRule {
condition,
@@ -577,7 +572,7 @@ impl<'a, 'b, 'i> QualifiedRuleParser<'i> for NestedRuleParser<'a, 'b> {
input: &mut Parser<'i, 't>,
) -> Result<Self::Prelude, ParseError<'i>> {
let selector_parser = SelectorParser {
- stylesheet_origin: self.stylesheet_origin,
+ stylesheet_origin: self.context.stylesheet_origin,
namespaces: self.namespaces,
url_data: Some(self.context.url_data),
};
diff --git a/components/style/stylesheets/stylesheet.rs b/components/style/stylesheets/stylesheet.rs
index e1359cb3722..ac1d810a05b 100644
--- a/components/style/stylesheets/stylesheet.rs
+++ b/components/style/stylesheets/stylesheet.rs
@@ -374,7 +374,6 @@ impl Stylesheet {
);
let rule_parser = TopLevelRuleParser {
- stylesheet_origin: origin,
shared_lock,
loader: stylesheet_loader,
context,
diff --git a/components/style/stylesheets/supports_rule.rs b/components/style/stylesheets/supports_rule.rs
index 2851d8914dd..06a7807e41d 100644
--- a/components/style/stylesheets/supports_rule.rs
+++ b/components/style/stylesheets/supports_rule.rs
@@ -11,7 +11,8 @@ use cssparser::parse_important;
use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
use parser::ParserContext;
use properties::{PropertyDeclaration, PropertyId, SourcePropertyDeclaration};
-use selectors::parser::SelectorParseErrorKind;
+use selector_parser::{SelectorImpl, SelectorParser};
+use selectors::parser::{Selector, SelectorParseErrorKind};
use servo_arc::Arc;
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked};
use shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
@@ -19,8 +20,8 @@ use std::ffi::{CStr, CString};
use std::fmt::{self, Write};
use std::str;
use str::CssStringWriter;
-use style_traits::{CssWriter, ParseError, ToCss};
-use stylesheets::{CssRuleType, CssRules};
+use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
+use stylesheets::{CssRuleType, CssRules, Namespaces};
/// An [`@supports`][supports] rule.
///
@@ -87,6 +88,8 @@ pub enum SupportsCondition {
Or(Vec<SupportsCondition>),
/// `property-ident: value` (value can be any tokens)
Declaration(Declaration),
+ /// A `selector()` function.
+ Selector(RawSelector),
/// `-moz-bool-pref("pref-name")`
/// Since we need to pass it through FFI to get the pref value,
/// we store it as CString directly.
@@ -99,8 +102,8 @@ impl SupportsCondition {
/// Parse a condition
///
/// <https://drafts.csswg.org/css-conditional/#supports_condition>
- pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<SupportsCondition, ParseError<'i>> {
- if let Ok(_) = input.try(|i| i.expect_ident_matching("not")) {
+ pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
+ if input.try(|i| i.expect_ident_matching("not")).is_ok() {
let inner = SupportsCondition::parse_in_parens(input)?;
return Ok(SupportsCondition::Not(Box::new(inner)));
}
@@ -109,10 +112,8 @@ impl SupportsCondition {
let location = input.current_source_location();
let (keyword, wrapper) = match input.next() {
- Err(_) => {
- // End of input
- return Ok(in_parens);
- },
+ // End of input
+ Err(..) => return Ok(in_parens),
Ok(&Token::Ident(ref ident)) => {
match_ignore_ascii_case! { &ident,
"and" => ("and", SupportsCondition::And as fn(_) -> _),
@@ -132,17 +133,48 @@ impl SupportsCondition {
.is_err()
{
// Did not find the expected keyword.
- // If we found some other token,
- // it will be rejected by `Parser::parse_entirely` somewhere up the stack.
+ // If we found some other token, it will be rejected by
+ // `Parser::parse_entirely` somewhere up the stack.
return Ok(wrapper(conditions));
}
}
}
+ /// Parses a functional supports condition.
+ fn parse_functional<'i, 't>(
+ function: &str,
+ input: &mut Parser<'i, 't>,
+ ) -> Result<Self, ParseError<'i>> {
+ match_ignore_ascii_case!{ function,
+ // Although this is an internal syntax, it is not necessary
+ // to check parsing context as far as we accept any
+ // unexpected token as future syntax, and evaluate it to
+ // false when not in chrome / ua sheet.
+ // See https://drafts.csswg.org/css-conditional-3/#general_enclosed
+ "-moz-bool-pref" => {
+ let name = {
+ let name = input.expect_string()?;
+ CString::new(name.as_bytes())
+ }.map_err(|_| input.new_custom_error(StyleParseErrorKind::UnspecifiedError))?;
+ Ok(SupportsCondition::MozBoolPref(name))
+ }
+ "selector" => {
+ let pos = input.position();
+ consume_any_value(input)?;
+ Ok(SupportsCondition::Selector(RawSelector(
+ input.slice_from(pos).to_owned()
+ )))
+ }
+ _ => {
+ Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
+ }
+ }
+ }
+
/// <https://drafts.csswg.org/css-conditional-3/#supports_condition_in_parens>
fn parse_in_parens<'i, 't>(
input: &mut Parser<'i, 't>,
- ) -> Result<SupportsCondition, ParseError<'i>> {
+ ) -> Result<Self, ParseError<'i>> {
// Whitespace is normally taken care of in `Parser::next`,
// but we want to not include it in `pos` for the SupportsCondition::FutureSyntax cases.
while input.try(Parser::expect_whitespace).is_ok() {}
@@ -151,46 +183,45 @@ impl SupportsCondition {
// FIXME: remove clone() when lifetimes are non-lexical
match input.next()?.clone() {
Token::ParenthesisBlock => {
- let nested = input
- .try(|input| input.parse_nested_block(|i| parse_condition_or_declaration(i)));
+ let nested = input.try(|input| {
+ input.parse_nested_block(parse_condition_or_declaration)
+ });
if nested.is_ok() {
return nested;
}
},
Token::Function(ident) => {
- // Although this is an internal syntax, it is not necessary to check
- // parsing context as far as we accept any unexpected token as future
- // syntax, and evaluate it to false when not in chrome / ua sheet.
- // See https://drafts.csswg.org/css-conditional-3/#general_enclosed
- if ident.eq_ignore_ascii_case("-moz-bool-pref") {
- if let Ok(name) = input.try(|i| {
- i.parse_nested_block(|i| {
- i.expect_string()
- .map(|s| s.to_string())
- .map_err(CssParseError::<()>::from)
- }).and_then(|s| CString::new(s).map_err(|_| location.new_custom_error(())))
- }) {
- return Ok(SupportsCondition::MozBoolPref(name));
- }
+ let nested = input.try(|input| {
+ input.parse_nested_block(|input| {
+ SupportsCondition::parse_functional(&ident, input)
+ })
+ });
+ if nested.is_ok() {
+ return nested;
}
},
t => return Err(location.new_unexpected_token_error(t)),
}
- input.parse_nested_block(|i| consume_any_value(i))?;
+ input.parse_nested_block(consume_any_value)?;
Ok(SupportsCondition::FutureSyntax(
input.slice_from(pos).to_owned(),
))
}
/// Evaluate a supports condition
- pub fn eval(&self, cx: &ParserContext) -> bool {
+ pub fn eval(
+ &self,
+ cx: &ParserContext,
+ namespaces: &Namespaces,
+ ) -> bool {
match *self {
- SupportsCondition::Not(ref cond) => !cond.eval(cx),
- SupportsCondition::Parenthesized(ref cond) => cond.eval(cx),
- SupportsCondition::And(ref vec) => vec.iter().all(|c| c.eval(cx)),
- SupportsCondition::Or(ref vec) => vec.iter().any(|c| c.eval(cx)),
+ SupportsCondition::Not(ref cond) => !cond.eval(cx, namespaces),
+ SupportsCondition::Parenthesized(ref cond) => cond.eval(cx, namespaces),
+ SupportsCondition::And(ref vec) => vec.iter().all(|c| c.eval(cx, namespaces)),
+ SupportsCondition::Or(ref vec) => vec.iter().any(|c| c.eval(cx, namespaces)),
SupportsCondition::Declaration(ref decl) => decl.eval(cx),
SupportsCondition::MozBoolPref(ref name) => eval_moz_bool_pref(name, cx),
+ SupportsCondition::Selector(ref selector) => selector.eval(cx, namespaces),
SupportsCondition::FutureSyntax(_) => false,
}
}
@@ -265,6 +296,11 @@ impl ToCss for SupportsCondition {
decl.to_css(dest)?;
dest.write_str(")")
},
+ SupportsCondition::Selector(ref selector) => {
+ dest.write_str("selector(")?;
+ selector.to_css(dest)?;
+ dest.write_str(")")
+ }
SupportsCondition::MozBoolPref(ref name) => {
dest.write_str("-moz-bool-pref(")?;
let name =
@@ -278,6 +314,69 @@ impl ToCss for SupportsCondition {
}
#[derive(Clone, Debug)]
+/// A possibly-invalid CSS selector.
+pub struct RawSelector(pub String);
+
+impl ToCss for RawSelector {
+ fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
+ where
+ W: Write,
+ {
+ dest.write_str(&self.0)
+ }
+}
+
+impl RawSelector {
+ /// Tries to evaluate a `selector()` function.
+ pub fn eval(
+ &self,
+ context: &ParserContext,
+ namespaces: &Namespaces,
+ ) -> bool {
+ #[cfg(feature = "gecko")]
+ {
+ if unsafe { !::gecko_bindings::structs::StaticPrefs_sVarCache_layout_css_supports_selector_enabled } {
+ return false;
+ }
+ }
+
+ let mut input = ParserInput::new(&self.0);
+ let mut input = Parser::new(&mut input);
+ input.parse_entirely(|input| -> Result<(), CssParseError<()>> {
+ let parser = SelectorParser {
+ namespaces,
+ stylesheet_origin: context.stylesheet_origin,
+ url_data: Some(context.url_data),
+ };
+
+ #[allow(unused_variables)]
+ let selector = Selector::<SelectorImpl>::parse(&parser, input)
+ .map_err(|_| input.new_custom_error(()))?;
+
+ #[cfg(feature = "gecko")]
+ {
+ use selector_parser::PseudoElement;
+ use selectors::parser::Component;
+
+ let has_any_unknown_webkit_pseudo =
+ selector.has_pseudo_element() &&
+ selector.iter_raw_match_order().any(|component| {
+ matches!(
+ *component,
+ Component::PseudoElement(PseudoElement::UnknownWebkit(..))
+ )
+ });
+ if has_any_unknown_webkit_pseudo {
+ return Err(input.new_custom_error(()));
+ }
+ }
+
+ Ok(())
+ }).is_ok()
+ }
+}
+
+#[derive(Clone, Debug)]
/// A possibly-invalid property declaration
pub struct Declaration(pub String);
@@ -313,21 +412,20 @@ impl Declaration {
let mut input = ParserInput::new(&self.0);
let mut input = Parser::new(&mut input);
- input
- .parse_entirely(|input| -> Result<(), CssParseError<()>> {
- let prop = input.expect_ident_cloned().unwrap();
- input.expect_colon().unwrap();
-
- let id =
- PropertyId::parse(&prop, context).map_err(|_| input.new_custom_error(()))?;
-
- let mut declarations = SourcePropertyDeclaration::new();
- input.parse_until_before(Delimiter::Bang, |input| {
- PropertyDeclaration::parse_into(&mut declarations, id, &context, input)
- .map_err(|_| input.new_custom_error(()))
- })?;
- let _ = input.try(parse_important);
- Ok(())
- }).is_ok()
+ input.parse_entirely(|input| -> Result<(), CssParseError<()>> {
+ let prop = input.expect_ident_cloned().unwrap();
+ input.expect_colon().unwrap();
+
+ let id =
+ PropertyId::parse(&prop, context).map_err(|_| input.new_custom_error(()))?;
+
+ let mut declarations = SourcePropertyDeclaration::new();
+ input.parse_until_before(Delimiter::Bang, |input| {
+ PropertyDeclaration::parse_into(&mut declarations, id, &context, input)
+ .map_err(|_| input.new_custom_error(()))
+ })?;
+ let _ = input.try(parse_important);
+ Ok(())
+ }).is_ok()
}
}
diff --git a/components/style/stylist.rs b/components/style/stylist.rs
index df7a55c6f18..fe96fd78ad8 100644
--- a/components/style/stylist.rs
+++ b/components/style/stylist.rs
@@ -614,14 +614,6 @@ impl Stylist {
/// Computes the style for a given "precomputed" pseudo-element, taking the
/// universal rules and applying them.
- ///
- /// If `inherit_all` is true, then all properties are inherited from the
- /// parent; otherwise, non-inherited properties are reset to their initial
- /// values. The flow constructor uses this flag when constructing anonymous
- /// flows.
- ///
- /// TODO(emilio): The type parameter could go away with a void type
- /// implementing TElement.
pub fn precomputed_values_for_pseudo<E>(
&self,
guards: &StylesheetGuards,
@@ -2423,6 +2415,9 @@ impl CascadeData {
if let Some(ref mut slotted_rules) = self.slotted_rules {
slotted_rules.clear();
}
+ if let Some(ref mut host_rules) = self.host_rules {
+ host_rules.clear();
+ }
self.animations.clear();
self.extra_data.clear();
self.rules_source_order = 0;
@@ -2448,6 +2443,9 @@ impl CascadeData {
if let Some(ref slotted_rules) = self.slotted_rules {
slotted_rules.add_size_of(ops, sizes);
}
+ if let Some(ref host_rules) = self.host_rules {
+ host_rules.add_size_of(ops, sizes);
+ }
sizes.mInvalidationMap += self.invalidation_map.size_of(ops);
sizes.mRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops);
sizes.mOther += self.animations.size_of(ops);
diff --git a/components/style/values/animated/mod.rs b/components/style/values/animated/mod.rs
index b70ef7d6639..8944f3fc5f4 100644
--- a/components/style/values/animated/mod.rs
+++ b/components/style/values/animated/mod.rs
@@ -292,8 +292,9 @@ impl ToAnimatedValue for ComputedMaxLength {
#[inline]
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
use values::computed::{Length, LengthOrPercentageOrNone, Percentage};
+ use values::generics::length::MaxLength as GenericMaxLength;
match animated {
- ComputedMaxLength::LengthOrPercentageOrNone(lopn) => {
+ GenericMaxLength::LengthOrPercentageOrNone(lopn) => {
let result = match lopn {
LengthOrPercentageOrNone::Length(px) => {
LengthOrPercentageOrNone::Length(Length::new(px.px().max(0.)))
@@ -303,7 +304,7 @@ impl ToAnimatedValue for ComputedMaxLength {
},
_ => lopn,
};
- ComputedMaxLength::LengthOrPercentageOrNone(result)
+ GenericMaxLength::LengthOrPercentageOrNone(result)
},
_ => animated,
}
@@ -321,8 +322,9 @@ impl ToAnimatedValue for ComputedMozLength {
#[inline]
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
use values::computed::{Length, LengthOrPercentageOrAuto, Percentage};
+ use values::generics::length::MozLength as GenericMozLength;
match animated {
- ComputedMozLength::LengthOrPercentageOrAuto(lopa) => {
+ GenericMozLength::LengthOrPercentageOrAuto(lopa) => {
let result = match lopa {
LengthOrPercentageOrAuto::Length(px) => {
LengthOrPercentageOrAuto::Length(Length::new(px.px().max(0.)))
@@ -332,7 +334,7 @@ impl ToAnimatedValue for ComputedMozLength {
},
_ => lopa,
};
- ComputedMozLength::LengthOrPercentageOrAuto(result)
+ GenericMozLength::LengthOrPercentageOrAuto(result)
},
_ => animated,
}
diff --git a/components/style/values/computed/angle.rs b/components/style/values/computed/angle.rs
index e162b7a2499..1c66498f7bd 100644
--- a/components/style/values/computed/angle.rs
+++ b/components/style/values/computed/angle.rs
@@ -7,36 +7,39 @@
use num_traits::Zero;
use std::{f32, f64};
use std::f64::consts::PI;
+use std::fmt::{self, Write};
use std::ops::Add;
+use style_traits::{CssWriter, ToCss};
use values::CSSFloat;
-use values::animated::{Animate, Procedure};
use values::distance::{ComputeSquaredDistance, SquaredDistance};
-/// A computed angle.
-#[animate(fallback = "Self::animate_fallback")]
+/// A computed angle in degrees.
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
-#[derive(
- Animate, Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, ToAnimatedZero, ToCss,
-)]
-pub enum Angle {
- /// An angle with degree unit.
- #[css(dimension)]
- Deg(CSSFloat),
- /// An angle with gradian unit.
- #[css(dimension)]
- Grad(CSSFloat),
- /// An angle with radian unit.
- #[css(dimension)]
- Rad(CSSFloat),
- /// An angle with turn unit.
- #[css(dimension)]
- Turn(CSSFloat),
+#[derive(Animate, Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, ToAnimatedZero)]
+pub struct Angle(CSSFloat);
+
+impl ToCss for Angle {
+ fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
+ where
+ W: Write,
+ {
+ self.degrees().to_css(dest)?;
+ dest.write_str("deg")
+ }
}
+const RAD_PER_DEG: f64 = PI / 180.0;
+
impl Angle {
/// Creates a computed `Angle` value from a radian amount.
pub fn from_radians(radians: CSSFloat) -> Self {
- Angle::Rad(radians)
+ Angle(radians / RAD_PER_DEG as f32)
+ }
+
+ /// Creates a computed `Angle` value from a degrees amount.
+ #[inline]
+ pub fn from_degrees(degrees: CSSFloat) -> Self {
+ Angle(degrees)
}
/// Returns the amount of radians this angle represents.
@@ -48,43 +51,18 @@ impl Angle {
/// Returns the amount of radians this angle represents as a `f64`.
///
/// Gecko stores angles as singles, but does this computation using doubles.
- /// See nsCSSValue::GetAngleValueInRadians.
+ ///
/// This is significant enough to mess up rounding to the nearest
/// quarter-turn for 225 degrees, for example.
#[inline]
pub fn radians64(&self) -> f64 {
- const RAD_PER_DEG: f64 = PI / 180.0;
- const RAD_PER_GRAD: f64 = PI / 200.0;
- const RAD_PER_TURN: f64 = PI * 2.0;
-
- let radians = match *self {
- Angle::Deg(val) => val as f64 * RAD_PER_DEG,
- Angle::Grad(val) => val as f64 * RAD_PER_GRAD,
- Angle::Turn(val) => val as f64 * RAD_PER_TURN,
- Angle::Rad(val) => val as f64,
- };
- radians.min(f64::MAX).max(f64::MIN)
+ self.0 as f64 * RAD_PER_DEG
}
/// Return the value in degrees.
- pub fn degrees(&self) -> f32 {
- use std::f32::consts::PI;
- self.radians() * 360. / (2. * PI)
- }
-
- /// <https://drafts.csswg.org/css-transitions/#animtype-number>
- #[inline]
- fn animate_fallback(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
- Ok(Angle::from_radians(
- self.radians().animate(&other.radians(), procedure)?,
- ))
- }
-}
-
-impl AsRef<Angle> for Angle {
#[inline]
- fn as_ref(&self) -> &Self {
- self
+ pub fn degrees(&self) -> CSSFloat {
+ self.0
}
}
@@ -93,27 +71,19 @@ impl Add for Angle {
#[inline]
fn add(self, rhs: Self) -> Self {
- match (self, rhs) {
- (Angle::Deg(x), Angle::Deg(y)) => Angle::Deg(x + y),
- (Angle::Grad(x), Angle::Grad(y)) => Angle::Grad(x + y),
- (Angle::Turn(x), Angle::Turn(y)) => Angle::Turn(x + y),
- (Angle::Rad(x), Angle::Rad(y)) => Angle::Rad(x + y),
- _ => Angle::from_radians(self.radians() + rhs.radians()),
- }
+ Angle(self.0 + rhs.0)
}
}
impl Zero for Angle {
#[inline]
fn zero() -> Self {
- Angle::from_radians(0.0)
+ Angle(0.0)
}
#[inline]
fn is_zero(&self) -> bool {
- match *self {
- Angle::Deg(val) | Angle::Grad(val) | Angle::Turn(val) | Angle::Rad(val) => val == 0.,
- }
+ self.0 == 0.
}
}
@@ -122,7 +92,6 @@ impl ComputeSquaredDistance for Angle {
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
// Use the formula for calculating the distance between angles defined in SVG:
// https://www.w3.org/TR/SVG/animate.html#complexDistances
- self.radians64()
- .compute_squared_distance(&other.radians64())
+ self.radians64().compute_squared_distance(&other.radians64())
}
}
diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs
index 911193b0c0b..e83f4b3f6b8 100644
--- a/components/style/values/computed/font.rs
+++ b/components/style/values/computed/font.rs
@@ -866,7 +866,7 @@ impl ToAnimatedValue for FontStyleAngle {
#[inline]
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
- FontStyleAngle(Angle::Deg(
+ FontStyleAngle(Angle::from_degrees(
animated
.degrees()
.min(specified::FONT_STYLE_OBLIQUE_MAX_ANGLE_DEGREES)
@@ -899,7 +899,7 @@ impl FontStyle {
/// https://drafts.csswg.org/css-fonts-4/#valdef-font-style-oblique-angle
#[inline]
pub fn default_angle() -> FontStyleAngle {
- FontStyleAngle(Angle::Deg(
+ FontStyleAngle(Angle::from_degrees(
specified::DEFAULT_FONT_STYLE_OBLIQUE_ANGLE_DEGREES,
))
}
@@ -919,7 +919,7 @@ impl FontStyle {
if italic {
return generics::FontStyle::Italic;
}
- generics::FontStyle::Oblique(FontStyleAngle(Angle::Deg(angle)))
+ generics::FontStyle::Oblique(FontStyleAngle(Angle::from_degrees(angle)))
}
}
diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs
index d3bc0b5ebd0..d32ddcfafa0 100644
--- a/components/style/values/computed/length.rs
+++ b/components/style/values/computed/length.rs
@@ -5,9 +5,7 @@
//! `<length>` computed values, and related ones.
use app_units::Au;
-use logical_geometry::WritingMode;
use ordered_float::NotNan;
-use properties::LonghandId;
use std::fmt::{self, Write};
use std::ops::{Add, Neg};
use style_traits::{CssWriter, ToCss};
@@ -17,6 +15,7 @@ use values::{specified, Auto, CSSFloat, Either, Normal};
use values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
use values::distance::{ComputeSquaredDistance, SquaredDistance};
use values::generics::NonNegative;
+use values::generics::length::{MaxLength as GenericMaxLength, MozLength as GenericMozLength};
use values::specified::length::{AbsoluteLength, FontBaseSize, FontRelativeLength};
use values::specified::length::ViewportPercentageLength;
@@ -951,7 +950,8 @@ pub type NonNegativeLengthOrPercentageOrNormal = Either<NonNegativeLengthOrPerce
/// block-size, and inline-size.
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss)]
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo,
+ ToComputedValue, ToCss)]
pub enum ExtremumLength {
MozMaxContent,
MozMinContent,
@@ -959,161 +959,24 @@ pub enum ExtremumLength {
MozAvailable,
}
-impl ExtremumLength {
- /// Returns whether this size keyword can be used for the given writing-mode
- /// and property.
- ///
- /// TODO: After these values are supported for both axes (and maybe
- /// unprefixed, see bug 1322780) all this complexity can go away, and
- /// everything can be derived (no need for uncacheable stuff).
- fn valid_for(wm: WritingMode, longhand: LonghandId) -> bool {
- // We only make sense on the inline axis.
- match longhand {
- // FIXME(emilio): The flex-basis thing is not quite clear...
- LonghandId::FlexBasis |
- LonghandId::MinWidth |
- LonghandId::MaxWidth |
- LonghandId::Width => !wm.is_vertical(),
-
- LonghandId::MinHeight | LonghandId::MaxHeight | LonghandId::Height => wm.is_vertical(),
-
- LonghandId::MinInlineSize | LonghandId::MaxInlineSize | LonghandId::InlineSize => true,
- // The block-* properties are rejected at parse-time, so they're
- // unexpected here.
- _ => {
- debug_assert!(
- false,
- "Unexpected property using ExtremumLength: {:?}",
- longhand,
- );
- false
- },
- }
- }
-}
-
-/// A value suitable for a `min-width`, `min-height`, `width` or `height`
-/// property.
-///
-/// See values/specified/length.rs for more details.
-#[allow(missing_docs)]
-#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
-#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, ToAnimatedZero, ToCss)]
-pub enum MozLength {
- LengthOrPercentageOrAuto(LengthOrPercentageOrAuto),
- #[animation(error)]
- ExtremumLength(ExtremumLength),
-}
+/// A computed value for `min-width`, `min-height`, `width` or `height` property.
+pub type MozLength = GenericMozLength<LengthOrPercentageOrAuto>;
impl MozLength {
/// Returns the `auto` value.
#[inline]
pub fn auto() -> Self {
- MozLength::LengthOrPercentageOrAuto(LengthOrPercentageOrAuto::Auto)
- }
-}
-
-impl ToComputedValue for specified::MozLength {
- type ComputedValue = MozLength;
-
- #[inline]
- fn to_computed_value(&self, context: &Context) -> MozLength {
- debug_assert!(
- context.for_non_inherited_property.is_some(),
- "Someone added a MozLength to an inherited property? Evil!"
- );
- match *self {
- specified::MozLength::LengthOrPercentageOrAuto(ref lopoa) => {
- MozLength::LengthOrPercentageOrAuto(lopoa.to_computed_value(context))
- },
- specified::MozLength::ExtremumLength(ext) => {
- context
- .rule_cache_conditions
- .borrow_mut()
- .set_writing_mode_dependency(context.builder.writing_mode);
- if !ExtremumLength::valid_for(
- context.builder.writing_mode,
- context.for_non_inherited_property.unwrap(),
- ) {
- MozLength::auto()
- } else {
- MozLength::ExtremumLength(ext)
- }
- },
- }
- }
-
- #[inline]
- fn from_computed_value(computed: &MozLength) -> Self {
- match *computed {
- MozLength::LengthOrPercentageOrAuto(ref lopoa) => {
- specified::MozLength::LengthOrPercentageOrAuto(
- specified::LengthOrPercentageOrAuto::from_computed_value(lopoa),
- )
- },
- MozLength::ExtremumLength(ext) => specified::MozLength::ExtremumLength(ext),
- }
+ GenericMozLength::LengthOrPercentageOrAuto(LengthOrPercentageOrAuto::Auto)
}
}
-/// A value suitable for a `max-width` or `max-height` property.
-/// See values/specified/length.rs for more details.
-#[allow(missing_docs)]
-#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
-#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, ToCss)]
-pub enum MaxLength {
- LengthOrPercentageOrNone(LengthOrPercentageOrNone),
- #[animation(error)]
- ExtremumLength(ExtremumLength),
-}
+/// A computed value for `max-width` or `min-height` property.
+pub type MaxLength = GenericMaxLength<LengthOrPercentageOrNone>;
impl MaxLength {
/// Returns the `none` value.
#[inline]
pub fn none() -> Self {
- MaxLength::LengthOrPercentageOrNone(LengthOrPercentageOrNone::None)
- }
-}
-
-impl ToComputedValue for specified::MaxLength {
- type ComputedValue = MaxLength;
-
- #[inline]
- fn to_computed_value(&self, context: &Context) -> MaxLength {
- debug_assert!(
- context.for_non_inherited_property.is_some(),
- "Someone added a MaxLength to an inherited property? Evil!"
- );
- match *self {
- specified::MaxLength::LengthOrPercentageOrNone(ref lopon) => {
- MaxLength::LengthOrPercentageOrNone(lopon.to_computed_value(context))
- },
- specified::MaxLength::ExtremumLength(ext) => {
- context
- .rule_cache_conditions
- .borrow_mut()
- .set_writing_mode_dependency(context.builder.writing_mode);
- if !ExtremumLength::valid_for(
- context.builder.writing_mode,
- context.for_non_inherited_property.unwrap(),
- ) {
- MaxLength::none()
- } else {
- MaxLength::ExtremumLength(ext)
- }
- },
- }
- }
-
- #[inline]
- fn from_computed_value(computed: &MaxLength) -> Self {
- match *computed {
- MaxLength::LengthOrPercentageOrNone(ref lopon) => {
- specified::MaxLength::LengthOrPercentageOrNone(
- specified::LengthOrPercentageOrNone::from_computed_value(&lopon),
- )
- },
- MaxLength::ExtremumLength(ref ext) => specified::MaxLength::ExtremumLength(ext.clone()),
- }
+ GenericMaxLength::LengthOrPercentageOrNone(LengthOrPercentageOrNone::None)
}
}
diff --git a/components/style/values/generics/length.rs b/components/style/values/generics/length.rs
new file mode 100644
index 00000000000..99976be493e
--- /dev/null
+++ b/components/style/values/generics/length.rs
@@ -0,0 +1,54 @@
+/* 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/. */
+
+//! Generic types for CSS values related to length.
+
+use values::computed::ExtremumLength;
+
+/// A generic value for the `width`, `height`, `min-width`, or `min-height` property.
+///
+/// Unlike `max-width` or `max-height` properties, a MozLength can be `auto`,
+/// and cannot be `none`.
+///
+/// Note that it only accepts non-negative values.
+#[allow(missing_docs)]
+#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
+#[derive(
+ Animate,
+ Clone,
+ ComputeSquaredDistance,
+ Copy,
+ Debug,
+ PartialEq,
+ SpecifiedValueInfo,
+ ToAnimatedZero,
+ ToComputedValue,
+ ToCss,
+)]
+pub enum MozLength<LengthOrPercentageOrAuto> {
+ LengthOrPercentageOrAuto(LengthOrPercentageOrAuto),
+ #[animation(error)]
+ ExtremumLength(ExtremumLength),
+}
+
+/// A generic value for the `max-width` or `max-height` property.
+#[allow(missing_docs)]
+#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
+#[derive(
+ Animate,
+ Clone,
+ ComputeSquaredDistance,
+ Copy,
+ Debug,
+ PartialEq,
+ SpecifiedValueInfo,
+ ToAnimatedZero,
+ ToComputedValue,
+ ToCss
+)]
+pub enum MaxLength<LengthOrPercentageOrNone> {
+ LengthOrPercentageOrNone(LengthOrPercentageOrNone),
+ #[animation(error)]
+ ExtremumLength(ExtremumLength),
+}
diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs
index 32ea771cf15..32e389512e4 100644
--- a/components/style/values/generics/mod.rs
+++ b/components/style/values/generics/mod.rs
@@ -27,6 +27,7 @@ pub mod font;
pub mod gecko;
pub mod grid;
pub mod image;
+pub mod length;
pub mod position;
pub mod rect;
pub mod size;
diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs
index cce0464d2ac..d398b40c3f1 100644
--- a/components/style/values/generics/transform.rs
+++ b/components/style/values/generics/transform.rs
@@ -10,6 +10,7 @@ use num_traits::Zero;
use values::{computed, CSSFloat};
use values::computed::length::Length as ComputedLength;
use values::computed::length::LengthOrPercentage as ComputedLengthOrPercentage;
+use values::specified::angle::Angle as SpecifiedAngle;
use values::specified::length::Length as SpecifiedLength;
use values::specified::length::LengthOrPercentage as SpecifiedLengthOrPercentage;
@@ -394,10 +395,30 @@ pub trait ToMatrix {
fn to_3d_matrix(&self, reference_box: Option<&Rect<Au>>) -> Result<Transform3D<f64>, ()>;
}
+/// A little helper to deal with both specified and computed angles.
+pub trait ToRadians {
+ /// Return the radians value as a 64-bit floating point value.
+ fn radians64(&self) -> f64;
+}
+
+impl ToRadians for computed::angle::Angle {
+ #[inline]
+ fn radians64(&self) -> f64 {
+ computed::angle::Angle::radians64(self)
+ }
+}
+
+impl ToRadians for SpecifiedAngle {
+ #[inline]
+ fn radians64(&self) -> f64 {
+ computed::angle::Angle::from_degrees(self.degrees()).radians64()
+ }
+}
+
impl<Angle, Number, Length, Integer, LoP> ToMatrix
for TransformOperation<Angle, Number, Length, Integer, LoP>
where
- Angle: Copy + AsRef<computed::angle::Angle>,
+ Angle: ToRadians + Copy,
Number: Copy + Into<f32> + Into<f64>,
Length: ToAbsoluteLength,
LoP: ToAbsoluteLength,
@@ -426,7 +447,7 @@ where
let reference_height = reference_box.map(|v| v.size.height);
let matrix = match *self {
Rotate3D(ax, ay, az, theta) => {
- let theta = TWO_PI - theta.as_ref().radians64();
+ let theta = TWO_PI - theta.radians64();
let (ax, ay, az, theta) =
get_normalized_vector_and_angle(ax.into(), ay.into(), az.into(), theta);
Transform3D::create_rotation(
@@ -437,15 +458,15 @@ where
)
},
RotateX(theta) => {
- let theta = euclid::Angle::radians(TWO_PI - theta.as_ref().radians64());
+ let theta = euclid::Angle::radians(TWO_PI - theta.radians64());
Transform3D::create_rotation(1., 0., 0., theta)
},
RotateY(theta) => {
- let theta = euclid::Angle::radians(TWO_PI - theta.as_ref().radians64());
+ let theta = euclid::Angle::radians(TWO_PI - theta.radians64());
Transform3D::create_rotation(0., 1., 0., theta)
},
RotateZ(theta) | Rotate(theta) => {
- let theta = euclid::Angle::radians(TWO_PI - theta.as_ref().radians64());
+ let theta = euclid::Angle::radians(TWO_PI - theta.radians64());
Transform3D::create_rotation(0., 0., 1., theta)
},
Perspective(ref d) => {
@@ -479,16 +500,16 @@ where
Transform3D::create_translation(0., 0., z.to_pixel_length(None)? as f64)
},
Skew(theta_x, theta_y) => Transform3D::create_skew(
- euclid::Angle::radians(theta_x.as_ref().radians64()),
- euclid::Angle::radians(theta_y.map_or(0., |a| a.as_ref().radians64())),
+ euclid::Angle::radians(theta_x.radians64()),
+ euclid::Angle::radians(theta_y.map_or(0., |a| a.radians64())),
),
SkewX(theta) => Transform3D::create_skew(
- euclid::Angle::radians(theta.as_ref().radians64()),
+ euclid::Angle::radians(theta.radians64()),
euclid::Angle::radians(0.),
),
SkewY(theta) => Transform3D::create_skew(
euclid::Angle::radians(0.),
- euclid::Angle::radians(theta.as_ref().radians64()),
+ euclid::Angle::radians(theta.radians64()),
),
Matrix3D(m) => m.into(),
Matrix(m) => m.into(),
diff --git a/components/style/values/specified/angle.rs b/components/style/values/specified/angle.rs
index 040ea9d9a7c..b634756d89f 100644
--- a/components/style/values/specified/angle.rs
+++ b/components/style/values/specified/angle.rs
@@ -6,6 +6,7 @@
use cssparser::{Parser, Token};
use parser::{Parse, ParserContext};
+use std::f32::consts::PI;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, ToCss};
use values::CSSFloat;
@@ -13,15 +14,47 @@ use values::computed::{Context, ToComputedValue};
use values::computed::angle::Angle as ComputedAngle;
use values::specified::calc::CalcNode;
-/// A specified angle.
-///
-/// Computed angles are essentially same as specified ones except for `calc()`
-/// value serialization. Therefore we are storing a computed angle inside
-/// to hold the actual value and its unit.
+/// A specified angle dimension.
+#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, ToCss)]
+pub enum AngleDimension {
+ /// An angle with degree unit.
+ #[css(dimension)]
+ Deg(CSSFloat),
+ /// An angle with gradian unit.
+ #[css(dimension)]
+ Grad(CSSFloat),
+ /// An angle with radian unit.
+ #[css(dimension)]
+ Rad(CSSFloat),
+ /// An angle with turn unit.
+ #[css(dimension)]
+ Turn(CSSFloat),
+}
+
+impl AngleDimension {
+ /// Returns the amount of degrees this angle represents.
+ #[inline]
+ fn degrees(&self) -> CSSFloat {
+ const DEG_PER_RAD: f32 = 180.0 / PI;
+ const DEG_PER_TURN: f32 = 360.0;
+ const DEG_PER_GRAD: f32 = 180.0 / 200.0;
+
+ match *self {
+ AngleDimension::Deg(d) => d,
+ AngleDimension::Rad(rad) => rad * DEG_PER_RAD,
+ AngleDimension::Turn(turns) => turns * DEG_PER_TURN,
+ AngleDimension::Grad(gradians) => gradians * DEG_PER_GRAD,
+ }
+ }
+}
+
+/// A specified Angle value, which is just the angle dimension, plus whether it
+/// was specified as `calc()` or not.
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq)]
pub struct Angle {
- value: ComputedAngle,
+ value: AngleDimension,
was_calc: bool,
}
@@ -41,22 +74,18 @@ impl ToCss for Angle {
}
}
-// FIXME(emilio): Probably computed angles shouldn't preserve the unit and
-// should serialize to degrees per:
-//
-// https://drafts.csswg.org/css-values/#compat
impl ToComputedValue for Angle {
type ComputedValue = ComputedAngle;
#[inline]
fn to_computed_value(&self, _context: &Context) -> Self::ComputedValue {
- self.value
+ ComputedAngle::from_degrees(self.degrees())
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
Angle {
- value: *computed,
+ value: AngleDimension::Deg(computed.degrees()),
was_calc: false,
}
}
@@ -64,35 +93,18 @@ impl ToComputedValue for Angle {
impl Angle {
/// Creates an angle with the given value in degrees.
+ #[inline]
pub fn from_degrees(value: CSSFloat, was_calc: bool) -> Self {
Angle {
- value: ComputedAngle::Deg(value),
- was_calc,
- }
- }
-
- /// Creates an angle with the given value in gradians.
- pub fn from_gradians(value: CSSFloat, was_calc: bool) -> Self {
- Angle {
- value: ComputedAngle::Grad(value),
- was_calc,
- }
- }
-
- /// Creates an angle with the given value in turns.
- pub fn from_turns(value: CSSFloat, was_calc: bool) -> Self {
- Angle {
- value: ComputedAngle::Turn(value),
+ value: AngleDimension::Deg(value),
was_calc,
}
}
- /// Creates an angle with the given value in radians.
- pub fn from_radians(value: CSSFloat, was_calc: bool) -> Self {
- Angle {
- value: ComputedAngle::Rad(value),
- was_calc,
- }
+ /// Returns the value of the angle in degrees, mostly for `calc()`.
+ #[inline]
+ pub fn degrees(&self) -> CSSFloat {
+ self.value.degrees()
}
/// Whether this specified angle came from a `calc()` expression.
@@ -101,39 +113,21 @@ impl Angle {
self.was_calc
}
- /// Returns the amount of radians this angle represents.
- #[inline]
- pub fn radians(self) -> f32 {
- self.value.radians()
- }
-
- /// Returns the amount of degrees this angle represents.
- #[inline]
- pub fn degrees(self) -> f32 {
- self.value.degrees()
- }
-
/// Returns `0deg`.
+ #[inline]
pub fn zero() -> Self {
Self::from_degrees(0.0, false)
}
/// Returns an `Angle` parsed from a `calc()` expression.
- pub fn from_calc(radians: CSSFloat) -> Self {
+ pub fn from_calc(degrees: CSSFloat) -> Self {
Angle {
- value: ComputedAngle::Rad(radians),
+ value: AngleDimension::Deg(degrees),
was_calc: true,
}
}
}
-impl AsRef<ComputedAngle> for Angle {
- #[inline]
- fn as_ref(&self) -> &ComputedAngle {
- &self.value
- }
-}
-
/// Whether to allow parsing an unitless zero as a valid angle.
///
/// This should always be `No`, except for exceptions like:
@@ -158,20 +152,26 @@ impl Parse for Angle {
impl Angle {
/// Parse an `<angle>` value given a value and an unit.
- pub fn parse_dimension(value: CSSFloat, unit: &str, from_calc: bool) -> Result<Angle, ()> {
- let angle = match_ignore_ascii_case! { unit,
- "deg" => Angle::from_degrees(value, from_calc),
- "grad" => Angle::from_gradians(value, from_calc),
- "turn" => Angle::from_turns(value, from_calc),
- "rad" => Angle::from_radians(value, from_calc),
+ pub fn parse_dimension(
+ value: CSSFloat,
+ unit: &str,
+ was_calc: bool,
+ ) -> Result<Angle, ()> {
+ let value = match_ignore_ascii_case! { unit,
+ "deg" => AngleDimension::Deg(value),
+ "grad" => AngleDimension::Grad(value),
+ "turn" => AngleDimension::Turn(value),
+ "rad" => AngleDimension::Rad(value),
_ => return Err(())
};
- Ok(angle)
+
+ Ok(Self { value, was_calc })
}
/// Parse an `<angle>` allowing unitless zero to represent a zero angle.
///
/// See the comment in `AllowUnitlessZeroAngle` for why.
+ #[inline]
pub fn parse_with_unitless<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
diff --git a/components/style/values/specified/box.rs b/components/style/values/specified/box.rs
index e23ec4a745a..7e79fc892a5 100644
--- a/components/style/values/specified/box.rs
+++ b/components/style/values/specified/box.rs
@@ -966,20 +966,27 @@ pub enum Appearance {
/// A typical dialog button.
Button,
/// Various arrows that go in buttons
+ #[parse(condition = "in_ua_or_chrome_sheet")]
ButtonArrowDown,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
ButtonArrowNext,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
ButtonArrowPrevious,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
ButtonArrowUp,
/// A rectangular button that contains complex content
/// like images (e.g. HTML <button> elements)
ButtonBevel,
/// The focus outline box inside of a button.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
ButtonFocus,
/// The caret of a text area
Caret,
/// A dual toolbar button (e.g., a Back button with a dropdown)
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Dualbutton,
/// A groupbox.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Groupbox,
/// A inner-spin button.
InnerSpinButton,
@@ -988,12 +995,17 @@ pub enum Appearance {
/// A listbox item.
Listitem,
/// Menu Bar background
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Menubar,
/// <menu> and <menuitem> appearances
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Menuitem,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Checkmenuitem,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Radiomenuitem,
/// For text on non-iconic menuitems only
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Menuitemtext,
/// A dropdown list.
Menulist,
@@ -1004,13 +1016,19 @@ pub enum Appearance {
/// An editable textfield with a dropdown list (a combobox).
MenulistTextfield,
/// Menu Popup background.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Menupopup,
/// menu checkbox/radio appearances
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Menucheckbox,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Menuradio,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Menuseparator,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Menuarrow,
/// An image in the menu gutter, like in bookmarks or history.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Menuimage,
/// A horizontal meter bar.
Meterbar,
@@ -1035,19 +1053,25 @@ pub enum Appearance {
Radio,
/// A generic container that always repaints on state changes. This is a
/// hack to make XUL checkboxes and radio buttons work.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
CheckboxContainer,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
RadioContainer,
/// The label part of a checkbox or radio button, used for painting a focus
/// outline.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
CheckboxLabel,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
RadioLabel,
/// nsRangeFrame and its subparts
Range,
RangeThumb,
/// The resizer background area in a status bar for the resizer widget in
/// the corner of a window.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Resizerpanel,
/// The resizer itself.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Resizer,
/// A slider.
ScaleHorizontal,
@@ -1061,18 +1085,26 @@ pub enum Appearance {
/// The ticks for a slider.
Scalethumbtick,
/// A scrollbar.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Scrollbar,
/// A small scrollbar.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
ScrollbarSmall,
/// The scrollbar slider
+ #[parse(condition = "in_ua_or_chrome_sheet")]
ScrollbarHorizontal,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
ScrollbarVertical,
/// A scrollbar button (up/down/left/right).
/// Keep these in order (some code casts these values to `int` in order to
/// compare them against each other).
+ #[parse(condition = "in_ua_or_chrome_sheet")]
ScrollbarbuttonUp,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
ScrollbarbuttonDown,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
ScrollbarbuttonLeft,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
ScrollbarbuttonRight,
/// The scrollbar thumb.
ScrollbarthumbHorizontal,
@@ -1081,107 +1113,166 @@ pub enum Appearance {
ScrollbartrackHorizontal,
ScrollbartrackVertical,
/// The scroll corner
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Scrollcorner,
/// A searchfield.
Searchfield,
/// A separator. Can be horizontal or vertical.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Separator,
/// A spin control (up/down control for time/date pickers).
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Spinner,
/// The up button of a spin control.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
SpinnerUpbutton,
/// The down button of a spin control.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
SpinnerDownbutton,
/// The textfield of a spin control
+ #[parse(condition = "in_ua_or_chrome_sheet")]
SpinnerTextfield,
/// A splitter. Can be horizontal or vertical.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Splitter,
/// A status bar in a main application window.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Statusbar,
/// A single pane of a status bar.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Statusbarpanel,
/// A single tab in a tab widget.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Tab,
/// A single pane (inside the tabpanels container).
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Tabpanel,
/// The tab panels container.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Tabpanels,
/// The tabs scroll arrows (left/right).
+ #[parse(condition = "in_ua_or_chrome_sheet")]
TabScrollArrowBack,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
TabScrollArrowForward,
/// A textfield or text area.
Textfield,
/// A multiline text field.
TextfieldMultiline,
/// A toolbar in an application window.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Toolbar,
/// A single toolbar button (with no associated dropdown).
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Toolbarbutton,
/// The dropdown portion of a toolbar button
+ #[parse(condition = "in_ua_or_chrome_sheet")]
ToolbarbuttonDropdown,
/// The gripper for a toolbar.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Toolbargripper,
/// The toolbox that contains the toolbars.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Toolbox,
/// A tooltip.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Tooltip,
/// A listbox or tree widget header
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Treeheader,
/// An individual header cell
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Treeheadercell,
/// The sort arrow for a header.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Treeheadersortarrow,
/// A tree item.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Treeitem,
/// A tree widget branch line
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Treeline,
/// A tree widget twisty.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Treetwisty,
/// Open tree widget twisty.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Treetwistyopen,
/// A tree widget.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Treeview,
/// Window and dialog backgrounds.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Window,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
Dialog,
/// Vista Rebars.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozWinCommunicationsToolbox,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozWinMediaToolbox,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozWinBrowsertabbarToolbox,
/// Vista glass.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozWinGlass,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozWinBorderlessGlass,
/// -moz-apperance style used in setting proper glass margins.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozWinExcludeGlass,
/// Titlebar elements on the Mac.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozMacFullscreenButton,
/// Mac help button.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozMacHelpButton,
/// Windows themed window frame elements.
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozWindowButtonBox,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozWindowButtonBoxMaximized,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozWindowButtonClose,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozWindowButtonMaximize,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozWindowButtonMinimize,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozWindowButtonRestore,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozWindowFrameBottom,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozWindowFrameLeft,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozWindowFrameRight,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozWindowTitlebar,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozWindowTitlebarMaximized,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozGtkInfoBar,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozMacActiveSourceListSelection,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozMacDisclosureButtonClosed,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozMacDisclosureButtonOpen,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozMacSourceList,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozMacSourceListSelection,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozMacVibrancyDark,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozMacVibrancyLight,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozMacVibrantTitlebarDark,
+ #[parse(condition = "in_ua_or_chrome_sheet")]
MozMacVibrantTitlebarLight,
/// A non-disappearing scrollbar.
diff --git a/components/style/values/specified/calc.rs b/components/style/values/specified/calc.rs
index 69631069990..3a28d42223c 100644
--- a/components/style/values/specified/calc.rs
+++ b/components/style/values/specified/calc.rs
@@ -469,22 +469,22 @@ impl CalcNode {
CalcNode::Sub(ref a, ref b) => {
let lhs = a.to_angle()?;
let rhs = b.to_angle()?;
- Angle::from_calc(lhs.radians() - rhs.radians())
+ Angle::from_calc(lhs.degrees() - rhs.degrees())
},
CalcNode::Sum(ref a, ref b) => {
let lhs = a.to_angle()?;
let rhs = b.to_angle()?;
- Angle::from_calc(lhs.radians() + rhs.radians())
+ Angle::from_calc(lhs.degrees() + rhs.degrees())
},
CalcNode::Mul(ref a, ref b) => match a.to_angle() {
Ok(lhs) => {
let rhs = b.to_number()?;
- Angle::from_calc(lhs.radians() * rhs)
+ Angle::from_calc(lhs.degrees() * rhs)
},
Err(..) => {
let lhs = a.to_number()?;
let rhs = b.to_angle()?;
- Angle::from_calc(lhs * rhs.radians())
+ Angle::from_calc(lhs * rhs.degrees())
},
},
CalcNode::Div(ref a, ref b) => {
@@ -493,7 +493,7 @@ impl CalcNode {
if rhs == 0. {
return Err(());
}
- Angle::from_calc(lhs.radians() / rhs)
+ Angle::from_calc(lhs.degrees() / rhs)
},
CalcNode::Number(..) |
CalcNode::Length(..) |
diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs
index cdfe3228c8b..b7bc40b116e 100644
--- a/components/style/values/specified/font.rs
+++ b/components/style/values/specified/font.rs
@@ -301,7 +301,7 @@ impl SpecifiedFontStyle {
}
fn compute_angle(angle: &Angle) -> ComputedAngle {
- ComputedAngle::Deg(Self::compute_angle_degrees(angle))
+ ComputedAngle::from_degrees(Self::compute_angle_degrees(angle))
}
/// Parse a suitable angle for font-style: oblique.
diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs
index 0a3a402e9ec..73cec6da7b1 100644
--- a/components/style/values/specified/image.rs
+++ b/components/style/values/specified/image.rs
@@ -15,7 +15,6 @@ use selectors::parser::SelectorParseErrorKind;
#[cfg(feature = "servo")]
use servo_url::ServoUrl;
use std::cmp::Ordering;
-use std::f32::consts::PI;
use std::fmt::{self, Write};
use style_traits::{CssType, CssWriter, KeywordsCollectFn, ParseError};
use style_traits::{StyleParseErrorKind, SpecifiedValueInfo, ToCss};
@@ -679,7 +678,7 @@ impl GradientKind {
impl generic::LineDirection for LineDirection {
fn points_downwards(&self, compat_mode: CompatMode) -> bool {
match *self {
- LineDirection::Angle(ref angle) => angle.radians() == PI,
+ LineDirection::Angle(ref angle) => angle.degrees() == 180.0,
LineDirection::Vertical(Y::Bottom) if compat_mode == CompatMode::Modern => true,
LineDirection::Vertical(Y::Top) if compat_mode != CompatMode::Modern => true,
#[cfg(feature = "gecko")]
diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs
index 1b4efc4f00d..128ab9959a5 100644
--- a/components/style/values/specified/length.rs
+++ b/components/style/values/specified/length.rs
@@ -19,6 +19,7 @@ use super::{AllowQuirks, Number, Percentage, ToComputedValue};
use values::{Auto, CSSFloat, Either, Normal};
use values::computed::{self, CSSPixelLength, Context, ExtremumLength};
use values::generics::NonNegative;
+use values::generics::length::{MaxLength as GenericMaxLength, MozLength as GenericMozLength};
use values::specified::calc::CalcNode;
pub use values::specified::calc::CalcLengthOrPercentage;
@@ -1188,18 +1189,8 @@ impl LengthOrNumber {
}
}
-/// A value suitable for a `min-width` or `min-height` property.
-///
-/// Unlike `max-width` or `max-height` properties, a MozLength can be `auto`,
-/// and cannot be `none`.
-///
-/// Note that it only accepts non-negative values.
-#[allow(missing_docs)]
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
-pub enum MozLength {
- LengthOrPercentageOrAuto(LengthOrPercentageOrAuto),
- ExtremumLength(ExtremumLength),
-}
+/// A specified value for `min-width`, `min-height`, `width` or `height` property.
+pub type MozLength = GenericMozLength<LengthOrPercentageOrAuto>;
impl Parse for MozLength {
fn parse<'i, 't>(
@@ -1219,7 +1210,7 @@ impl MozLength {
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let length = LengthOrPercentageOrAuto::parse_non_negative(context, input)?;
- Ok(MozLength::LengthOrPercentageOrAuto(length))
+ Ok(GenericMozLength::LengthOrPercentageOrAuto(length))
}
/// Parses, with quirks.
@@ -1229,34 +1220,29 @@ impl MozLength {
allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> {
if let Ok(l) = input.try(ExtremumLength::parse) {
- return Ok(MozLength::ExtremumLength(l));
+ return Ok(GenericMozLength::ExtremumLength(l));
}
let length =
LengthOrPercentageOrAuto::parse_non_negative_quirky(context, input, allow_quirks)?;
- Ok(MozLength::LengthOrPercentageOrAuto(length))
+ Ok(GenericMozLength::LengthOrPercentageOrAuto(length))
}
/// Returns `auto`.
#[inline]
pub fn auto() -> Self {
- MozLength::LengthOrPercentageOrAuto(LengthOrPercentageOrAuto::auto())
+ GenericMozLength::LengthOrPercentageOrAuto(LengthOrPercentageOrAuto::auto())
}
/// Returns `0%`.
#[inline]
pub fn zero_percent() -> Self {
- MozLength::LengthOrPercentageOrAuto(LengthOrPercentageOrAuto::zero_percent())
+ GenericMozLength::LengthOrPercentageOrAuto(LengthOrPercentageOrAuto::zero_percent())
}
}
-/// A value suitable for a `max-width` or `max-height` property.
-#[allow(missing_docs)]
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
-pub enum MaxLength {
- LengthOrPercentageOrNone(LengthOrPercentageOrNone),
- ExtremumLength(ExtremumLength),
-}
+/// A specified value for `max-width` or `max-height` property.
+pub type MaxLength = GenericMaxLength<LengthOrPercentageOrNone>;
impl Parse for MaxLength {
fn parse<'i, 't>(
@@ -1276,7 +1262,7 @@ impl MaxLength {
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let length = LengthOrPercentageOrNone::parse_non_negative(context, input)?;
- Ok(MaxLength::LengthOrPercentageOrNone(length))
+ Ok(GenericMaxLength::LengthOrPercentageOrNone(length))
}
/// Parses, with quirks.
@@ -1286,11 +1272,11 @@ impl MaxLength {
allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> {
if let Ok(l) = input.try(ExtremumLength::parse) {
- return Ok(MaxLength::ExtremumLength(l));
+ return Ok(GenericMaxLength::ExtremumLength(l));
}
let length =
LengthOrPercentageOrNone::parse_non_negative_quirky(context, input, allow_quirks)?;
- Ok(MaxLength::LengthOrPercentageOrNone(length))
+ Ok(GenericMaxLength::LengthOrPercentageOrNone(length))
}
}
diff --git a/tests/unit/style/properties/serialization.rs b/tests/unit/style/properties/serialization.rs
index 4ab79d25a2f..2c5892f1e63 100644
--- a/tests/unit/style/properties/serialization.rs
+++ b/tests/unit/style/properties/serialization.rs
@@ -611,60 +611,6 @@ mod shorthand_serialization {
}
}
- mod transform {
- pub use super::*;
- use style::values::generics::transform::TransformOperation;
- use style::values::specified::{Angle, Number};
- use style::values::specified::transform::TransformOperation as SpecifiedOperation;
-
- #[test]
- fn should_serialize_none_correctly() {
- use style::properties::longhands::transform;
-
- assert_roundtrip_with_context!(transform::parse, "none");
- }
-
- #[inline(always)]
- fn validate_serialization(op: &SpecifiedOperation, expected_string: &'static str) {
- let css_string = op.to_css_string();
- assert_eq!(css_string, expected_string);
- }
-
- #[test]
- fn transform_scale() {
- validate_serialization(&TransformOperation::Scale(Number::new(1.3), None), "scale(1.3)");
- validate_serialization(
- &TransformOperation::Scale(Number::new(2.0), Some(Number::new(2.0))),
- "scale(2, 2)");
- validate_serialization(&TransformOperation::ScaleX(Number::new(42.0)), "scaleX(42)");
- validate_serialization(&TransformOperation::ScaleY(Number::new(0.3)), "scaleY(0.3)");
- validate_serialization(&TransformOperation::ScaleZ(Number::new(1.0)), "scaleZ(1)");
- validate_serialization(
- &TransformOperation::Scale3D(Number::new(4.0), Number::new(5.0), Number::new(6.0)),
- "scale3d(4, 5, 6)");
- }
-
- #[test]
- fn transform_skew() {
- validate_serialization(
- &TransformOperation::Skew(Angle::from_degrees(42.3, false), None),
- "skew(42.3deg)");
- validate_serialization(
- &TransformOperation::Skew(Angle::from_gradians(-50.0, false), Some(Angle::from_turns(0.73, false))),
- "skew(-50grad, 0.73turn)");
- validate_serialization(
- &TransformOperation::SkewX(Angle::from_radians(0.31, false)), "skewX(0.31rad)");
- }
-
- #[test]
- fn transform_rotate() {
- validate_serialization(
- &TransformOperation::Rotate(Angle::from_turns(35.0, false)),
- "rotate(35turn)"
- )
- }
- }
-
mod quotes {
pub use super::*;
diff --git a/tests/wpt/metadata/css/css-conditional/at-supports-040.html.ini b/tests/wpt/metadata/css/css-conditional/at-supports-040.html.ini
deleted file mode 100644
index 6869e67b552..00000000000
--- a/tests/wpt/metadata/css/css-conditional/at-supports-040.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[at-supports-040.html]
- expected: FAIL
diff --git a/tests/wpt/metadata/css/cssom/CSS.html.ini b/tests/wpt/metadata/css/cssom/CSS.html.ini
deleted file mode 100644
index 279da1f4d89..00000000000
--- a/tests/wpt/metadata/css/cssom/CSS.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[CSS.html]
- [CSS.supports, selector function]
- expected: FAIL
-
diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json
index 48be8bbb3bb..824d9a03ef9 100644
--- a/tests/wpt/mozilla/meta/MANIFEST.json
+++ b/tests/wpt/mozilla/meta/MANIFEST.json
@@ -26166,7 +26166,7 @@
"reftest"
],
"css/transform_skew_ref.html": [
- "caf92ca6f50d1cfe27f9202ebf79d76dead03ba0",
+ "b6ef9bb8fe9c129b02f5f3213865673a42638190",
"support"
],
"css/transform_stacking_context_a.html": [
diff --git a/tests/wpt/mozilla/tests/css/transform_skew_ref.html b/tests/wpt/mozilla/tests/css/transform_skew_ref.html
index caf92ca6f50..b6ef9bb8fe9 100644
--- a/tests/wpt/mozilla/tests/css/transform_skew_ref.html
+++ b/tests/wpt/mozilla/tests/css/transform_skew_ref.html
@@ -17,15 +17,15 @@ div>div {
}
.transformed1_ref {
- transform: matrix(1, 0, 0.25534192122, 1, 0, 0);
+ transform: matrix(1, 0, 0.255342, 1, 0, 0);
}
.transformed2_ref {
- transform: matrix(1, 0.54630248984, 0, 1, 0, 0);
+ transform: matrix(1, 0.546302, 0, 1, 0, 0);
}
.transformed3_ref {
- transform: matrix(1, 0.54630248984, 0.25534192122, 1, 0, 0);
+ transform: matrix(1, 0.546302, 0.255342, 1, 0, 0);
}
</style>