mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Auto merge of #21982 - emilio:gecko-sync, r=emilio
style: Sync changes from mozilla-central. See each individual commit for details. https://bugzilla.mozilla.org/show_bug.cgi?id=1500260 <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/21982) <!-- Reviewable:end -->
This commit is contained in:
commit
91282778e4
48 changed files with 799 additions and 902 deletions
|
@ -553,12 +553,12 @@ pub fn convert_linear_gradient(
|
||||||
let angle = match direction {
|
let angle = match direction {
|
||||||
LineDirection::Angle(angle) => angle.radians(),
|
LineDirection::Angle(angle) => angle.radians(),
|
||||||
LineDirection::Horizontal(x) => match x {
|
LineDirection::Horizontal(x) => match x {
|
||||||
X::Left => Angle::Deg(270.).radians(),
|
X::Left => Angle::from_degrees(270.).radians(),
|
||||||
X::Right => Angle::Deg(90.).radians(),
|
X::Right => Angle::from_degrees(90.).radians(),
|
||||||
},
|
},
|
||||||
LineDirection::Vertical(y) => match y {
|
LineDirection::Vertical(y) => match y {
|
||||||
Y::Top => Angle::Deg(0.).radians(),
|
Y::Top => Angle::from_degrees(0.).radians(),
|
||||||
Y::Bottom => Angle::Deg(180.).radians(),
|
Y::Bottom => Angle::from_degrees(180.).radians(),
|
||||||
},
|
},
|
||||||
LineDirection::Corner(horizontal, vertical) => {
|
LineDirection::Corner(horizontal, vertical) => {
|
||||||
// This the angle for one of the diagonals of the box. Our angle
|
// This the angle for one of the diagonals of the box. Our angle
|
||||||
|
|
|
@ -53,21 +53,21 @@ impl CSS {
|
||||||
pub fn Supports_(win: &Window, condition: DOMString) -> bool {
|
pub fn Supports_(win: &Window, condition: DOMString) -> bool {
|
||||||
let mut input = ParserInput::new(&condition);
|
let mut input = ParserInput::new(&condition);
|
||||||
let mut input = Parser::new(&mut input);
|
let mut input = Parser::new(&mut input);
|
||||||
let cond = parse_condition_or_declaration(&mut input);
|
let cond = match parse_condition_or_declaration(&mut input) {
|
||||||
if let Ok(cond) = cond {
|
Ok(c) => c,
|
||||||
let url = win.Document().url();
|
Err(..) => return false,
|
||||||
let context = ParserContext::new_for_cssom(
|
};
|
||||||
&url,
|
|
||||||
Some(CssRuleType::Style),
|
let url = win.Document().url();
|
||||||
ParsingMode::DEFAULT,
|
let context = ParserContext::new_for_cssom(
|
||||||
QuirksMode::NoQuirks,
|
&url,
|
||||||
None,
|
Some(CssRuleType::Style),
|
||||||
None,
|
ParsingMode::DEFAULT,
|
||||||
);
|
QuirksMode::NoQuirks,
|
||||||
cond.eval(&context)
|
None,
|
||||||
} else {
|
None,
|
||||||
false
|
);
|
||||||
}
|
cond.eval(&context, &Default::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://drafts.css-houdini.org/css-paint-api-1/#paint-worklet>
|
/// <https://drafts.css-houdini.org/css-paint-api-1/#paint-worklet>
|
||||||
|
|
|
@ -81,7 +81,17 @@ impl CSSSupportsRule {
|
||||||
None,
|
None,
|
||||||
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 mut guard = self.cssconditionrule.shared_lock().write();
|
||||||
let rule = self.supportsrule.write_with(&mut guard);
|
let rule = self.supportsrule.write_with(&mut guard);
|
||||||
rule.condition = cond;
|
rule.condition = cond;
|
||||||
|
|
|
@ -259,8 +259,13 @@ where
|
||||||
Impl: SelectorImpl,
|
Impl: SelectorImpl,
|
||||||
{
|
{
|
||||||
let location = input.current_source_location();
|
let location = input.current_source_location();
|
||||||
let selector = Selector::parse(parser, input)?;
|
let selector = parse_selector(parser, input)?;
|
||||||
// Ensure they're actually all compound selectors.
|
|
||||||
|
// 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()) {
|
if selector.iter_raw_match_order().any(|s| s.is_combinator()) {
|
||||||
return Err(location.new_custom_error(SelectorParseErrorKind::NonCompoundSelector));
|
return Err(location.new_custom_error(SelectorParseErrorKind::NonCompoundSelector));
|
||||||
}
|
}
|
||||||
|
@ -1397,6 +1402,7 @@ where
|
||||||
|
|
||||||
impl<Impl: SelectorImpl> Selector<Impl> {
|
impl<Impl: SelectorImpl> Selector<Impl> {
|
||||||
/// Parse a selector, without any pseudo-element.
|
/// Parse a selector, without any pseudo-element.
|
||||||
|
#[inline]
|
||||||
pub fn parse<'i, 't, P>(
|
pub fn parse<'i, 't, P>(
|
||||||
parser: &P,
|
parser: &P,
|
||||||
input: &mut CssParser<'i, 't>,
|
input: &mut CssParser<'i, 't>,
|
||||||
|
@ -1404,12 +1410,7 @@ impl<Impl: SelectorImpl> Selector<Impl> {
|
||||||
where
|
where
|
||||||
P: Parser<'i, Impl = Impl>,
|
P: Parser<'i, Impl = Impl>,
|
||||||
{
|
{
|
||||||
let selector = parse_selector(parser, input)?;
|
parse_selector(parser, input)
|
||||||
if selector.has_pseudo_element() {
|
|
||||||
let e = SelectorParseErrorKind::PseudoElementInComplexSelector;
|
|
||||||
return Err(input.new_custom_error(e));
|
|
||||||
}
|
|
||||||
Ok(selector)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ mod bindings {
|
||||||
use bindgen::{Builder, CodegenConfig};
|
use bindgen::{Builder, CodegenConfig};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::HashSet;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
@ -43,7 +43,7 @@ mod bindings {
|
||||||
.expect("Failed to open config file")
|
.expect("Failed to open config file")
|
||||||
.read_to_string(&mut contents)
|
.read_to_string(&mut contents)
|
||||||
.expect("Failed to read config file");
|
.expect("Failed to read config file");
|
||||||
match toml::from_str::<toml::value::Table>(&contents) {
|
match toml::from_str::<Table>(&contents) {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(e) => panic!("Failed to parse config file: {}", e),
|
Err(e) => panic!("Failed to parse config file: {}", e),
|
||||||
}
|
}
|
||||||
|
@ -58,22 +58,10 @@ mod bindings {
|
||||||
};
|
};
|
||||||
static ref BUILD_CONFIG: Table = {
|
static ref BUILD_CONFIG: Table = {
|
||||||
// Load build-specific config overrides.
|
// 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())
|
let path = PathBuf::from(env::var_os("MOZ_TOPOBJDIR").unwrap())
|
||||||
.join("layout/style/bindgen.toml");
|
.join("layout/style/bindgen.toml");
|
||||||
read_config(&path)
|
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 INCLUDE_RE: Regex = Regex::new(r#"#include\s*"(.+?)""#).unwrap();
|
||||||
static ref DISTDIR_PATH: PathBuf = {
|
static ref DISTDIR_PATH: PathBuf = {
|
||||||
let path = PathBuf::from(env::var_os("MOZ_DIST").unwrap());
|
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 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 {
|
impl BuilderExt for Builder {
|
||||||
fn get_initial_builder() -> Builder {
|
fn get_initial_builder() -> Builder {
|
||||||
use bindgen::RustTarget;
|
use bindgen::RustTarget;
|
||||||
|
@ -207,16 +166,14 @@ mod bindings {
|
||||||
builder = builder.clang_arg("-DDEBUG=1").clang_arg("-DJS_DEBUG=1");
|
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"]
|
let build_config = BUILD_CONFIG["build"]
|
||||||
.as_table()
|
.as_table()
|
||||||
.expect("Malformed config file");
|
.expect("Malformed config file");
|
||||||
builder = add_clang_args(builder, build_config, &mut matched_os);
|
let extra_bindgen_flags = build_config["args"].as_array().unwrap().as_slice();
|
||||||
if !matched_os {
|
for item in extra_bindgen_flags.iter() {
|
||||||
panic!("Unknown platform");
|
builder = builder.clang_arg(item.as_str().expect("Expect string in list"));
|
||||||
}
|
}
|
||||||
|
|
||||||
builder
|
builder
|
||||||
}
|
}
|
||||||
fn include<T: Into<String>>(self, file: T) -> Builder {
|
fn include<T: Into<String>>(self, file: T) -> Builder {
|
||||||
|
@ -300,35 +257,57 @@ mod bindings {
|
||||||
.expect("Unable to write output");
|
.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
|
// Read the file
|
||||||
let mut list_file = File::open(DISTDIR_PATH.join("include/mozilla/ServoArcTypeList.h"))
|
let path = DISTDIR_PATH.join("include/mozilla/").join(filename);
|
||||||
.expect("Unable to open ServoArcTypeList.h");
|
let mut list_file = File::open(path).expect(&format!("Unable to open {}", filename));
|
||||||
let mut content = String::new();
|
let mut content = String::new();
|
||||||
list_file
|
list_file
|
||||||
.read_to_string(&mut content)
|
.read_to_string(&mut content)
|
||||||
.expect("Fail to read ServoArcTypeList.h");
|
.expect(&format!("Failed to read {}", filename));
|
||||||
// Remove comments
|
// Remove comments
|
||||||
let block_comment_re = Regex::new(r#"(?s)/\*.*?\*/"#).unwrap();
|
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 = block_comment_re.replace_all(&content, "");
|
||||||
|
let content = line_comment_re.replace_all(&content, "");
|
||||||
// Extract the list
|
// 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
|
content
|
||||||
.lines()
|
.lines()
|
||||||
.map(|line| line.trim())
|
.map(|line| line.trim())
|
||||||
.filter(|line| !line.is_empty())
|
.filter(|line| !line.is_empty())
|
||||||
.map(|line| {
|
.map(|line| {
|
||||||
re.captures(&line)
|
let captures = re
|
||||||
.expect(&format!(
|
.captures(&line)
|
||||||
"Unrecognized line in ServoArcTypeList.h: '{}'",
|
.expect(&format!("Unrecognized line in {}: '{}'", filename, line));
|
||||||
line
|
let macro_name = captures.get(1).unwrap().as_str().to_string();
|
||||||
)).get(1)
|
let type_name = captures.get(2).unwrap().as_str().to_string();
|
||||||
.unwrap()
|
(macro_name, type_name)
|
||||||
.as_str()
|
|
||||||
.to_string()
|
|
||||||
}).collect()
|
}).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> {
|
struct BuilderWithConfig<'a> {
|
||||||
builder: Builder,
|
builder: Builder,
|
||||||
config: &'a Table,
|
config: &'a Table,
|
||||||
|
@ -524,19 +503,6 @@ mod bindings {
|
||||||
"&'a mut ::gecko_bindings::structs::nsTArray<{}>;"),
|
"&'a mut ::gecko_bindings::structs::nsTArray<{}>;"),
|
||||||
cpp_type, rust_type))
|
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))
|
.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
|
// 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
|
// 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.
|
// 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))
|
.handle_str_items("servo-borrow-types", |b, ty| b.mutable_borrowed_type(ty))
|
||||||
.get_builder();
|
.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() {
|
for ty in get_arc_types().iter() {
|
||||||
builder = builder
|
builder = builder
|
||||||
.blacklist_type(format!("{}Strong", ty))
|
.blacklist_type(format!("{}Strong", ty))
|
||||||
|
@ -553,6 +526,22 @@ mod bindings {
|
||||||
)).borrowed_type(ty)
|
)).borrowed_type(ty)
|
||||||
.zero_size_type(ty, &structs_types);
|
.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);
|
write_binding_file(builder, BINDINGS_FILE, &fixups);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#![allow(non_snake_case, missing_docs)]
|
#![allow(non_snake_case, missing_docs)]
|
||||||
|
|
||||||
|
use gecko::url::CssUrlData;
|
||||||
use gecko_bindings::bindings::RawServoCounterStyleRule;
|
use gecko_bindings::bindings::RawServoCounterStyleRule;
|
||||||
use gecko_bindings::bindings::RawServoFontFeatureValuesRule;
|
use gecko_bindings::bindings::RawServoFontFeatureValuesRule;
|
||||||
use gecko_bindings::bindings::RawServoImportRule;
|
use gecko_bindings::bindings::RawServoImportRule;
|
||||||
|
@ -22,6 +23,7 @@ use gecko_bindings::bindings::RawServoRuleNodeStrong;
|
||||||
use gecko_bindings::bindings::RawServoSupportsRule;
|
use gecko_bindings::bindings::RawServoSupportsRule;
|
||||||
use gecko_bindings::bindings::ServoCssRules;
|
use gecko_bindings::bindings::ServoCssRules;
|
||||||
use gecko_bindings::structs::RawServoAnimationValue;
|
use gecko_bindings::structs::RawServoAnimationValue;
|
||||||
|
use gecko_bindings::structs::RawServoCssUrlData;
|
||||||
use gecko_bindings::structs::RawServoDeclarationBlock;
|
use gecko_bindings::structs::RawServoDeclarationBlock;
|
||||||
use gecko_bindings::structs::RawServoFontFaceRule;
|
use gecko_bindings::structs::RawServoFontFaceRule;
|
||||||
use gecko_bindings::structs::RawServoMediaList;
|
use gecko_bindings::structs::RawServoMediaList;
|
||||||
|
@ -110,6 +112,9 @@ impl_arc_ffi!(Locked<FontFaceRule> => RawServoFontFaceRule
|
||||||
impl_arc_ffi!(Locked<CounterStyleRule> => RawServoCounterStyleRule
|
impl_arc_ffi!(Locked<CounterStyleRule> => RawServoCounterStyleRule
|
||||||
[Servo_CounterStyleRule_AddRef, Servo_CounterStyleRule_Release]);
|
[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.
|
// RuleNode is a Arc-like type but it does not use Arc.
|
||||||
|
|
||||||
impl StrongRuleNode {
|
impl StrongRuleNode {
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use gecko::values::GeckoStyleCoordConvertible;
|
use gecko::values::GeckoStyleCoordConvertible;
|
||||||
use gecko_bindings::bindings;
|
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::structs::{nsresult, SheetType, nsStyleImage};
|
||||||
use gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue};
|
use gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue};
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
|
@ -128,35 +128,7 @@ impl From<nsStyleCoord_CalcValue> for NonNegativeLengthOrPercentageOrAuto {
|
||||||
|
|
||||||
impl From<Angle> for CoordDataValue {
|
impl From<Angle> for CoordDataValue {
|
||||||
fn from(reference: Angle) -> Self {
|
fn from(reference: Angle) -> Self {
|
||||||
match reference {
|
CoordDataValue::Degree(reference.degrees())
|
||||||
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"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,13 +197,13 @@ impl nsStyleImage {
|
||||||
match image {
|
match image {
|
||||||
GenericImage::Gradient(boxed_gradient) => self.set_gradient(*boxed_gradient),
|
GenericImage::Gradient(boxed_gradient) => self.set_gradient(*boxed_gradient),
|
||||||
GenericImage::Url(ref url) => unsafe {
|
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) => {
|
GenericImage::Rect(ref image_rect) => {
|
||||||
unsafe {
|
unsafe {
|
||||||
bindings::Gecko_SetLayerImageImageValue(
|
bindings::Gecko_SetLayerImageImageValue(
|
||||||
self,
|
self,
|
||||||
image_rect.url.0.image_value.get(),
|
(image_rect.url.0).0.url_value.get(),
|
||||||
);
|
);
|
||||||
bindings::Gecko_InitializeImageCropRect(self);
|
bindings::Gecko_InitializeImageCropRect(self);
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
||||||
use context::QuirksMode;
|
use context::QuirksMode;
|
||||||
use dom::TElement;
|
use dom::TElement;
|
||||||
use gecko_bindings::bindings::{self, RawServoStyleSet};
|
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::structs::{StyleSheetInfo, nsIDocument};
|
||||||
use gecko_bindings::sugar::ownership::{HasArcFFI, HasBoxFFI, HasFFI, HasSimpleFFI};
|
use gecko_bindings::sugar::ownership::{HasArcFFI, HasBoxFFI, HasFFI, HasSimpleFFI};
|
||||||
use invalidation::media_queries::{MediaListKey, ToMediaListKey};
|
use invalidation::media_queries::{MediaListKey, ToMediaListKey};
|
||||||
|
@ -143,7 +143,7 @@ pub struct PerDocumentStyleData(AtomicRefCell<PerDocumentStyleDataImpl>);
|
||||||
|
|
||||||
impl PerDocumentStyleData {
|
impl PerDocumentStyleData {
|
||||||
/// Create a dummy `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);
|
let device = Device::new(pres_context);
|
||||||
|
|
||||||
// FIXME(emilio, tlin): How is this supposed to work with XBL? This is
|
// FIXME(emilio, tlin): How is this supposed to work with XBL? This is
|
||||||
|
|
|
@ -12,7 +12,7 @@ use euclid::TypedScale;
|
||||||
use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
|
use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
|
||||||
use gecko_bindings::bindings;
|
use gecko_bindings::bindings;
|
||||||
use gecko_bindings::structs;
|
use gecko_bindings::structs;
|
||||||
use gecko_bindings::structs::{nsPresContext, RawGeckoPresContextOwned};
|
use gecko_bindings::structs::{nsPresContext, RawGeckoPresContextBorrowed};
|
||||||
use media_queries::MediaType;
|
use media_queries::MediaType;
|
||||||
use properties::ComputedValues;
|
use properties::ComputedValues;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
|
@ -30,7 +30,7 @@ pub struct Device {
|
||||||
/// NB: The pres context lifetime is tied to the styleset, who owns the
|
/// 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
|
/// stylist, and thus the `Device`, so having a raw pres context pointer
|
||||||
/// here is fine.
|
/// here is fine.
|
||||||
pres_context: RawGeckoPresContextOwned,
|
pres_context: RawGeckoPresContextBorrowed,
|
||||||
default_values: Arc<ComputedValues>,
|
default_values: Arc<ComputedValues>,
|
||||||
/// The font size of the root element
|
/// The font size of the root element
|
||||||
/// This is set when computing the style of the root
|
/// This is set when computing the style of the root
|
||||||
|
@ -77,7 +77,7 @@ unsafe impl Send for Device {}
|
||||||
|
|
||||||
impl Device {
|
impl Device {
|
||||||
/// Trivially constructs a new `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());
|
assert!(!pres_context.is_null());
|
||||||
Device {
|
Device {
|
||||||
pres_context,
|
pres_context,
|
||||||
|
|
|
@ -57,15 +57,6 @@ impl PseudoElement {
|
||||||
PseudoElementCascadeType::Lazy
|
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
|
/// Whether the pseudo-element should inherit from the default computed
|
||||||
/// values instead of from the parent element.
|
/// values instead of from the parent element.
|
||||||
///
|
///
|
||||||
|
|
|
@ -35,10 +35,11 @@ class Atom:
|
||||||
self.original_ident = ident
|
self.original_ident = ident
|
||||||
self.value = value
|
self.value = value
|
||||||
self.hash = hash
|
self.hash = hash
|
||||||
# The Gecko type: "nsStaticAtom", "nsICSSPseudoElement", or "nsIAnonBoxPseudo"
|
# The Gecko type: "nsStaticAtom", "nsCSSPseudoElementStaticAtom", or
|
||||||
|
# "nsAnonBoxPseudoStaticAtom".
|
||||||
self.ty = ty
|
self.ty = ty
|
||||||
# The type of atom: "Atom", "PseudoElement", "NonInheritingAnonBox",
|
# The type of atom: "Atom", "PseudoElement", "NonInheritingAnonBox",
|
||||||
# or "InheritingAnonBox"
|
# or "InheritingAnonBox".
|
||||||
self.atom_type = atom_type
|
self.atom_type = atom_type
|
||||||
if self.is_pseudo() or self.is_anon_box():
|
if self.is_pseudo() or self.is_anon_box():
|
||||||
self.pseudo_ident = (ident.split("_", 1))[1]
|
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):
|
def write_pseudo_elements(atoms, target_filename):
|
||||||
pseudos = []
|
pseudos = []
|
||||||
for atom in atoms:
|
for atom in atoms:
|
||||||
if atom.type() == "nsICSSPseudoElement" or atom.type() == "nsICSSAnonBoxPseudo":
|
if atom.type() == "nsCSSPseudoElementStaticAtom" or atom.type() == "nsCSSAnonBoxPseudoStaticAtom":
|
||||||
pseudos.append(atom)
|
pseudos.append(atom)
|
||||||
|
|
||||||
pseudo_definition_template = os.path.join(GECKO_DIR, "pseudo_element_definition.mako.rs")
|
pseudo_definition_template = os.path.join(GECKO_DIR, "pseudo_element_definition.mako.rs")
|
||||||
|
|
|
@ -6,18 +6,16 @@
|
||||||
|
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use gecko_bindings::bindings;
|
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::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 gecko_bindings::sugar::refptr::RefPtr;
|
||||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||||
use nsstring::nsCString;
|
use nsstring::nsCString;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
use servo_arc::{Arc, RawOffsetArc};
|
use servo_arc::Arc;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use std::mem;
|
|
||||||
use style_traits::{CssWriter, ParseError, ToCss};
|
use style_traits::{CssWriter, ParseError, ToCss};
|
||||||
use stylesheets::UrlExtraData;
|
use stylesheets::UrlExtraData;
|
||||||
use values::computed::{Context, ToComputedValue};
|
use values::computed::{Context, ToComputedValue};
|
||||||
|
@ -25,12 +23,13 @@ use values::computed::{Context, ToComputedValue};
|
||||||
/// A CSS url() value for gecko.
|
/// A CSS url() value for gecko.
|
||||||
#[css(function = "url")]
|
#[css(function = "url")]
|
||||||
#[derive(Clone, Debug, PartialEq, SpecifiedValueInfo, ToCss)]
|
#[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.
|
/// The URL in unresolved string form.
|
||||||
///
|
serialization: String,
|
||||||
/// Refcounted since cloning this should be cheap and data: uris can be
|
|
||||||
/// really large.
|
|
||||||
serialization: Arc<String>,
|
|
||||||
|
|
||||||
/// The URL extra data.
|
/// The URL extra data.
|
||||||
#[css(skip)]
|
#[css(skip)]
|
||||||
|
@ -38,13 +37,12 @@ pub struct CssUrl {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CssUrl {
|
impl CssUrl {
|
||||||
/// Try to parse a URL from a string value that is a valid CSS token for a
|
/// Parse a URL from a string value that is a valid CSS token for a URL.
|
||||||
/// URL.
|
|
||||||
pub fn parse_from_string(url: String, context: &ParserContext) -> Self {
|
pub fn parse_from_string(url: String, context: &ParserContext) -> Self {
|
||||||
CssUrl {
|
CssUrl(Arc::new(CssUrlData {
|
||||||
serialization: Arc::new(url),
|
serialization: url,
|
||||||
extra_data: context.url_data.clone(),
|
extra_data: context.url_data.clone(),
|
||||||
}
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the URL is definitely invalid. We don't eagerly resolve
|
/// Returns true if the URL is definitely invalid. We don't eagerly resolve
|
||||||
|
@ -54,15 +52,22 @@ impl CssUrl {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert from URLValueData to SpecifiedUrl.
|
/// Returns true if this URL looks like a fragment.
|
||||||
unsafe fn from_url_value_data(url: &URLValueData) -> Self {
|
/// See https://drafts.csswg.org/css-values/#local-urls
|
||||||
let arc_type = &url.mString as *const _ as *const RawOffsetArc<String>;
|
#[inline]
|
||||||
CssUrl {
|
pub fn is_fragment(&self) -> bool {
|
||||||
serialization: Arc::from_raw_offset((*arc_type).clone()),
|
self.0.is_fragment()
|
||||||
extra_data: UrlExtraData(url.mExtraData.to_safe()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the unresolved url as string, or the empty string if it's
|
||||||
|
/// invalid.
|
||||||
|
#[inline]
|
||||||
|
pub fn as_str(&self) -> &str {
|
||||||
|
self.0.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CssUrlData {
|
||||||
/// Returns true if this URL looks like a fragment.
|
/// Returns true if this URL looks like a fragment.
|
||||||
/// See https://drafts.csswg.org/css-values/#local-urls
|
/// See https://drafts.csswg.org/css-values/#local-urls
|
||||||
pub fn is_fragment(&self) -> bool {
|
pub fn is_fragment(&self) -> bool {
|
||||||
|
@ -74,24 +79,6 @@ impl CssUrl {
|
||||||
pub fn as_str(&self) -> &str {
|
pub fn as_str(&self) -> &str {
|
||||||
&*self.serialization
|
&*self.serialization
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for CssUrl {
|
impl Parse for CssUrl {
|
||||||
|
@ -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)]
|
#[derive(Clone, Debug, SpecifiedValueInfo, ToCss)]
|
||||||
pub struct SpecifiedUrl {
|
pub struct SpecifiedUrl {
|
||||||
/// The specified url value.
|
/// The specified url value.
|
||||||
|
@ -129,72 +116,22 @@ pub struct SpecifiedUrl {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecifiedUrl {
|
impl SpecifiedUrl {
|
||||||
fn from_css_url(url: CssUrl) -> Self {
|
/// Parse a URL from a string value.
|
||||||
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.
|
|
||||||
pub fn parse_from_string(url: String, context: &ParserContext) -> Self {
|
pub fn parse_from_string(url: String, context: &ParserContext) -> Self {
|
||||||
Self::from_css_url(CssUrl::parse_from_string(url, context))
|
Self::from_css_url(CssUrl::parse_from_string(url, context))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_css_url_with_cors(url: CssUrl, cors: CORSMode) -> Self {
|
fn from_css_url_with_cors(url: CssUrl, cors: CORSMode) -> Self {
|
||||||
let image_value = unsafe {
|
let url_value = unsafe {
|
||||||
let ptr = bindings::Gecko_ImageValue_Create(url.for_ffi(), cors);
|
let ptr = bindings::Gecko_URLValue_Create(
|
||||||
// We do not expect Gecko_ImageValue_Create returns null.
|
url.0.clone().into_strong(),
|
||||||
|
cors,
|
||||||
|
);
|
||||||
|
// We do not expect Gecko_URLValue_Create returns null.
|
||||||
debug_assert!(!ptr.is_null());
|
debug_assert!(!ptr.is_null());
|
||||||
RefPtr::from_addrefed(ptr)
|
RefPtr::from_addrefed(ptr)
|
||||||
};
|
};
|
||||||
Self { url, image_value }
|
Self { url, url_value }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_css_url(url: CssUrl) -> Self {
|
fn from_css_url(url: CssUrl) -> Self {
|
||||||
|
@ -206,18 +143,9 @@ impl SpecifiedImageUrl {
|
||||||
use gecko_bindings::structs::root::mozilla::CORSMode_CORS_ANONYMOUS;
|
use gecko_bindings::structs::root::mozilla::CORSMode_CORS_ANONYMOUS;
|
||||||
Self::from_css_url_with_cors(url, 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>(
|
fn parse<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
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 {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.url.eq(&other.url)
|
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 {
|
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||||
let mut n = self.url.size_of(ops);
|
let mut n = self.url.size_of(ops);
|
||||||
// Although this is a RefPtr, this is the primary reference because
|
// 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.
|
// measure unconditionally here.
|
||||||
n += unsafe { bindings::Gecko_ImageValue_SizeOfIncludingThis(self.image_value.get()) };
|
n += unsafe { bindings::Gecko_URLValue_SizeOfIncludingThis(self.url_value.get()) };
|
||||||
n
|
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 {
|
impl ToComputedValue for SpecifiedImageUrl {
|
||||||
type ComputedValue = ComputedImageUrl;
|
type ComputedValue = ComputedImageUrl;
|
||||||
|
|
||||||
|
@ -274,9 +233,9 @@ impl ToComputedValue for SpecifiedImageUrl {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_computed_url<W>(
|
fn serialize_computed_url<W>(
|
||||||
url_value_data: &URLValueData,
|
url_value: &URLValue,
|
||||||
dest: &mut CssWriter<W>,
|
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
|
) -> fmt::Result
|
||||||
where
|
where
|
||||||
W: Write,
|
W: Write,
|
||||||
|
@ -284,13 +243,13 @@ where
|
||||||
dest.write_str("url(")?;
|
dest.write_str("url(")?;
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut string = nsCString::new();
|
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)?;
|
string.as_str_unchecked().to_css(dest)?;
|
||||||
}
|
}
|
||||||
dest.write_char(')')
|
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
|
/// The only difference between specified and computed URLs is the
|
||||||
/// serialization.
|
/// serialization.
|
||||||
|
@ -303,7 +262,7 @@ impl ToCss for ComputedUrl {
|
||||||
W: Write,
|
W: Write,
|
||||||
{
|
{
|
||||||
serialize_computed_url(
|
serialize_computed_url(
|
||||||
&self.0.url_value._base,
|
&self.0.url_value,
|
||||||
dest,
|
dest,
|
||||||
bindings::Gecko_GetComputedURLSpec,
|
bindings::Gecko_GetComputedURLSpec,
|
||||||
)
|
)
|
||||||
|
@ -313,12 +272,18 @@ impl ToCss for ComputedUrl {
|
||||||
impl ComputedUrl {
|
impl ComputedUrl {
|
||||||
/// Convert from RefPtr<URLValue> to ComputedUrl.
|
/// Convert from RefPtr<URLValue> to ComputedUrl.
|
||||||
pub unsafe fn from_url_value(url_value: RefPtr<URLValue>) -> Self {
|
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 })
|
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)]
|
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)]
|
||||||
pub struct ComputedImageUrl(pub SpecifiedImageUrl);
|
pub struct ComputedImageUrl(pub SpecifiedImageUrl);
|
||||||
|
|
||||||
|
@ -328,7 +293,7 @@ impl ToCss for ComputedImageUrl {
|
||||||
W: Write,
|
W: Write,
|
||||||
{
|
{
|
||||||
serialize_computed_url(
|
serialize_computed_url(
|
||||||
&self.0.image_value._base,
|
&(self.0).0.url_value,
|
||||||
dest,
|
dest,
|
||||||
bindings::Gecko_GetComputedImageURLSpec,
|
bindings::Gecko_GetComputedImageURLSpec,
|
||||||
)
|
)
|
||||||
|
@ -338,8 +303,14 @@ impl ToCss for ComputedImageUrl {
|
||||||
impl ComputedImageUrl {
|
impl ComputedImageUrl {
|
||||||
/// Convert from nsStyleImageReques to ComputedImageUrl.
|
/// Convert from nsStyleImageReques to ComputedImageUrl.
|
||||||
pub unsafe fn from_image_request(image_request: &nsStyleImageRequest) -> Self {
|
pub unsafe fn from_image_request(image_request: &nsStyleImageRequest) -> Self {
|
||||||
let image_value = image_request.mImageValue.to_safe();
|
let url_value = image_request.mImageValue.to_safe();
|
||||||
let url = CssUrl::from_url_value_data(&image_value._base);
|
let css_url = &*url_value.mCssUrl.mRawPtr;
|
||||||
ComputedImageUrl(SpecifiedImageUrl { url, image_value })
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ use std::cmp::max;
|
||||||
use values::{Auto, Either, None_, Normal};
|
use values::{Auto, Either, None_, Normal};
|
||||||
use values::computed::{Angle, ExtremumLength, Length, LengthOrPercentage, LengthOrPercentageOrAuto};
|
use values::computed::{Angle, ExtremumLength, Length, LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||||
use values::computed::{LengthOrPercentageOrNone, Number, NumberOrPercentage};
|
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::{NonNegativeLength, NonNegativeLengthOrPercentage, NonNegativeNumber};
|
||||||
use values::computed::FlexBasis as ComputedFlexBasis;
|
use values::computed::FlexBasis as ComputedFlexBasis;
|
||||||
use values::computed::basic_shape::ShapeRadius as ComputedShapeRadius;
|
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::flex::FlexBasis;
|
||||||
use values::generics::gecko::ScrollSnapPoint;
|
use values::generics::gecko::ScrollSnapPoint;
|
||||||
use values::generics::grid::{TrackBreadth, TrackKeyword};
|
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.
|
/// A trait that defines an interface to convert from and to `nsStyleCoord`s.
|
||||||
pub trait GeckoStyleCoordConvertible: Sized {
|
pub trait GeckoStyleCoordConvertible: Sized {
|
||||||
|
@ -74,7 +75,7 @@ impl GeckoStyleCoordConvertible for ComputedFlexBasis {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
|
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));
|
return Some(FlexBasis::Width(width));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,10 +326,7 @@ impl GeckoStyleCoordConvertible for Angle {
|
||||||
|
|
||||||
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
|
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
|
||||||
match coord.as_value() {
|
match coord.as_value() {
|
||||||
CoordDataValue::Degree(val) => Some(Angle::Deg(val)),
|
CoordDataValue::Degree(val) => Some(Angle::from_degrees(val)),
|
||||||
CoordDataValue::Grad(val) => Some(Angle::Grad(val)),
|
|
||||||
CoordDataValue::Radian(val) => Some(Angle::Rad(val)),
|
|
||||||
CoordDataValue::Turn(val) => Some(Angle::Turn(val)),
|
|
||||||
_ => None,
|
_ => 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) {
|
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
|
||||||
match *self {
|
match *self {
|
||||||
MozLength::LengthOrPercentageOrAuto(ref lopoa) => lopoa.to_gecko_style_coord(coord),
|
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) {
|
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
|
||||||
match *self {
|
match *self {
|
||||||
MaxLength::LengthOrPercentageOrNone(ref lopon) => lopon.to_gecko_style_coord(coord),
|
MaxLength::LengthOrPercentageOrNone(ref lopon) => lopon.to_gecko_style_coord(coord),
|
||||||
|
|
|
@ -60,7 +60,7 @@ impl nsCSSValue {
|
||||||
pub unsafe fn array_unchecked(&self) -> &nsCSSValue_Array {
|
pub unsafe fn array_unchecked(&self) -> &nsCSSValue_Array {
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
nsCSSUnit::eCSSUnit_Array as u32 <= self.mUnit as u32 &&
|
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();
|
let array = *self.mValue.mArray.as_ref();
|
||||||
debug_assert!(!array.is_null());
|
debug_assert!(!array.is_null());
|
||||||
|
@ -198,19 +198,19 @@ impl nsCSSValue {
|
||||||
|
|
||||||
/// Returns an `Angle` value from this `nsCSSValue`.
|
/// Returns an `Angle` value from this `nsCSSValue`.
|
||||||
///
|
///
|
||||||
/// Panics if the unit is not `eCSSUnit_Degree` `eCSSUnit_Grad`, `eCSSUnit_Turn`
|
/// Panics if the unit is not `eCSSUnit_Degree`.
|
||||||
/// or `eCSSUnit_Radian`.
|
#[inline]
|
||||||
pub fn get_angle(&self) -> Angle {
|
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.
|
/// Sets Angle value to this nsCSSValue.
|
||||||
pub fn set_angle(&mut self, angle: Angle) {
|
pub fn set_angle(&mut self, angle: Angle) {
|
||||||
debug_assert_eq!(self.mUnit, nsCSSUnit::eCSSUnit_Null);
|
debug_assert_eq!(self.mUnit, nsCSSUnit::eCSSUnit_Null);
|
||||||
let (value, unit) = angle.to_gecko_values();
|
self.mUnit = nsCSSUnit::eCSSUnit_Degree;
|
||||||
self.mUnit = unit;
|
|
||||||
unsafe {
|
unsafe {
|
||||||
*self.mValue.mFloat.as_mut() = value;
|
*self.mValue.mFloat.as_mut() = angle.degrees();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -200,12 +200,6 @@ pub enum CoordDataValue {
|
||||||
Factor(f32),
|
Factor(f32),
|
||||||
/// eStyleUnit_Degree
|
/// eStyleUnit_Degree
|
||||||
Degree(f32),
|
Degree(f32),
|
||||||
/// eStyleUnit_Grad
|
|
||||||
Grad(f32),
|
|
||||||
/// eStyleUnit_Radian
|
|
||||||
Radian(f32),
|
|
||||||
/// eStyleUnit_Turn
|
|
||||||
Turn(f32),
|
|
||||||
/// eStyleUnit_FlexFraction
|
/// eStyleUnit_FlexFraction
|
||||||
FlexFraction(f32),
|
FlexFraction(f32),
|
||||||
/// eStyleUnit_Coord
|
/// eStyleUnit_Coord
|
||||||
|
@ -317,18 +311,6 @@ pub unsafe trait CoordDataMut: CoordData {
|
||||||
*unit = eStyleUnit_Degree;
|
*unit = eStyleUnit_Degree;
|
||||||
*union.mFloat.as_mut() = f;
|
*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) => {
|
FlexFraction(f) => {
|
||||||
*unit = eStyleUnit_FlexFraction;
|
*unit = eStyleUnit_FlexFraction;
|
||||||
*union.mFloat.as_mut() = f;
|
*union.mFloat.as_mut() = f;
|
||||||
|
@ -393,9 +375,6 @@ pub unsafe trait CoordData {
|
||||||
eStyleUnit_Percent => Percent(self.get_float()),
|
eStyleUnit_Percent => Percent(self.get_float()),
|
||||||
eStyleUnit_Factor => Factor(self.get_float()),
|
eStyleUnit_Factor => Factor(self.get_float()),
|
||||||
eStyleUnit_Degree => Degree(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_FlexFraction => FlexFraction(self.get_float()),
|
||||||
eStyleUnit_Coord => Coord(self.get_integer()),
|
eStyleUnit_Coord => Coord(self.get_integer()),
|
||||||
eStyleUnit_Integer => Integer(self.get_integer()),
|
eStyleUnit_Integer => Integer(self.get_integer()),
|
||||||
|
@ -413,9 +392,6 @@ pub unsafe trait CoordData {
|
||||||
self.unit() == eStyleUnit_Percent ||
|
self.unit() == eStyleUnit_Percent ||
|
||||||
self.unit() == eStyleUnit_Factor ||
|
self.unit() == eStyleUnit_Factor ||
|
||||||
self.unit() == eStyleUnit_Degree ||
|
self.unit() == eStyleUnit_Degree ||
|
||||||
self.unit() == eStyleUnit_Grad ||
|
|
||||||
self.unit() == eStyleUnit_Radian ||
|
|
||||||
self.unit() == eStyleUnit_Turn ||
|
|
||||||
self.unit() == eStyleUnit_FlexFraction
|
self.unit() == eStyleUnit_FlexFraction
|
||||||
);
|
);
|
||||||
*self.union().mFloat.as_ref()
|
*self.union().mFloat.as_ref()
|
||||||
|
|
|
@ -82,9 +82,9 @@ impl<T> nsTArray<T> {
|
||||||
|
|
||||||
/// Resize and set the length of the array to `len`.
|
/// 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.
|
/// bindings or run the typed `EnsureCapacity` call on the gecko side.
|
||||||
pub unsafe fn set_len(&mut self, len: u32) {
|
pub unsafe fn set_len(&mut self, len: u32) {
|
||||||
// this can leak
|
// this can leak
|
||||||
|
@ -96,6 +96,8 @@ impl<T> nsTArray<T> {
|
||||||
|
|
||||||
/// Resizes an array containing only POD elements
|
/// 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)
|
/// 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)
|
pub unsafe fn set_len_pod(&mut self, len: u32)
|
||||||
where
|
where
|
||||||
|
@ -105,4 +107,17 @@ impl<T> nsTArray<T> {
|
||||||
let header = self.header_mut();
|
let header = self.header_mut();
|
||||||
header.mLength = len;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -297,11 +297,6 @@ impl_threadsafe_refcount!(
|
||||||
bindings::Gecko_AddRefGridTemplateAreasValueArbitraryThread,
|
bindings::Gecko_AddRefGridTemplateAreasValueArbitraryThread,
|
||||||
bindings::Gecko_ReleaseGridTemplateAreasValueArbitraryThread
|
bindings::Gecko_ReleaseGridTemplateAreasValueArbitraryThread
|
||||||
);
|
);
|
||||||
impl_threadsafe_refcount!(
|
|
||||||
structs::ImageValue,
|
|
||||||
bindings::Gecko_AddRefImageValueArbitraryThread,
|
|
||||||
bindings::Gecko_ReleaseImageValueArbitraryThread
|
|
||||||
);
|
|
||||||
impl_threadsafe_refcount!(
|
impl_threadsafe_refcount!(
|
||||||
structs::SharedFontList,
|
structs::SharedFontList,
|
||||||
bindings::Gecko_AddRefSharedFontListArbitraryThread,
|
bindings::Gecko_AddRefSharedFontListArbitraryThread,
|
||||||
|
|
|
@ -689,7 +689,10 @@ def set_gecko_property(ffi_name, expr):
|
||||||
}
|
}
|
||||||
SVGPaintKind::PaintServer(url) => {
|
SVGPaintKind::PaintServer(url) => {
|
||||||
unsafe {
|
unsafe {
|
||||||
bindings::Gecko_nsStyleSVGPaint_SetURLValue(paint, url.0.url_value.get());
|
bindings::Gecko_nsStyleSVGPaint_SetURLValue(
|
||||||
|
paint,
|
||||||
|
url.url_value_ptr(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SVGPaintKind::Color(color) => {
|
SVGPaintKind::Color(color) => {
|
||||||
|
@ -1370,35 +1373,22 @@ impl Clone for ${style_struct.gecko_struct_name} {
|
||||||
}
|
}
|
||||||
</%def>
|
</%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)
|
gecko_ffi_name = to_camel_case_lower(ident)
|
||||||
%>
|
%>
|
||||||
|
|
||||||
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
|
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
|
||||||
let current_settings = &mut self.gecko.mFont.${gecko_ffi_name};
|
let iter = v.0.iter().map(|other| structs::${gecko_type} {
|
||||||
current_settings.clear_pod();
|
mTag: other.tag.0,
|
||||||
|
mValue: other.value as ${gecko_value_type},
|
||||||
unsafe { current_settings.set_len_pod(v.0.len() as u32) };
|
});
|
||||||
|
self.gecko.mFont.${gecko_ffi_name}.assign_from_iter_pod(iter);
|
||||||
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};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
||||||
let current_settings = &mut self.gecko.mFont.${gecko_ffi_name};
|
let iter = other.gecko.mFont.${gecko_ffi_name}.iter().map(|s| *s);
|
||||||
let other_settings = &other.gecko.mFont.${gecko_ffi_name};
|
self.gecko.mFont.${gecko_ffi_name}.assign_from_iter_pod(iter);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset_${ident}(&mut self, other: &Self) {
|
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
|
// Negative numbers are invalid at parse time, but <integer> is still an
|
||||||
// i32.
|
// i32.
|
||||||
<% impl_font_settings("font_feature_settings", "FeatureTagValue", "i32", "u32") %>
|
<% impl_font_settings("font_feature_settings", "gfxFontFeature", "FeatureTagValue", "i32", "u32") %>
|
||||||
<% impl_font_settings("font_variation_settings", "VariationValue", "f32", "f32") %>
|
<% impl_font_settings("font_variation_settings", "gfxFontVariation", "VariationValue", "f32", "f32") %>
|
||||||
|
|
||||||
pub fn fixup_none_generic(&mut self, device: &Device) {
|
pub fn fixup_none_generic(&mut self, device: &Device) {
|
||||||
self.gecko.mFont.systemFont = false;
|
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>,
|
where I: IntoIterator<Item = longhands::scroll_snap_coordinate::computed_value::single_value::T>,
|
||||||
I::IntoIter: ExactSizeIterator
|
I::IntoIter: ExactSizeIterator
|
||||||
{
|
{
|
||||||
let v = v.into_iter();
|
let iter = v.into_iter().map(|c| structs::mozilla::Position {
|
||||||
|
mXPosition: c.horizontal.into(),
|
||||||
unsafe { self.gecko.mScrollSnapCoordinate.set_len_pod(v.len() as u32); }
|
mYPosition: c.vertical.into(),
|
||||||
for (gecko, servo) in self.gecko.mScrollSnapCoordinate
|
});
|
||||||
.iter_mut()
|
self.gecko.mScrollSnapCoordinate.assign_from_iter_pod(iter);
|
||||||
.zip(v) {
|
|
||||||
gecko.mXPosition = servo.horizontal.into();
|
|
||||||
gecko.mYPosition = servo.vertical.into();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy_scroll_snap_coordinate_from(&mut self, other: &Self) {
|
pub fn copy_scroll_snap_coordinate_from(&mut self, other: &Self) {
|
||||||
unsafe {
|
let iter = other.gecko.mScrollSnapCoordinate.iter().map(|c| *c);
|
||||||
self.gecko.mScrollSnapCoordinate
|
self.gecko.mScrollSnapCoordinate.assign_from_iter_pod(iter);
|
||||||
.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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset_scroll_snap_coordinate(&mut self, other: &Self) {
|
pub fn reset_scroll_snap_coordinate(&mut self, other: &Self) {
|
||||||
|
@ -4153,7 +4131,10 @@ fn static_assert() {
|
||||||
}
|
}
|
||||||
UrlOrNone::Url(ref url) => {
|
UrlOrNone::Url(ref url) => {
|
||||||
unsafe {
|
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);
|
Gecko_NewStyleSVGPath(shape_source);
|
||||||
&mut shape_source.__bindgen_anon_1.mSVGPath.as_mut().mPtr.as_mut().unwrap()
|
&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());
|
let iter = servo_path.commands().iter().map(|command| {
|
||||||
for (servo, gecko) in servo_path.commands().iter().zip(gecko_path.mPath.iter_mut()) {
|
|
||||||
// unsafe: cbindgen ensures the representation is the same.
|
// 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.
|
// Setup fill-rule.
|
||||||
// unsafe: cbindgen ensures the representation is the same.
|
// unsafe: cbindgen ensures the representation is the same.
|
||||||
|
@ -5358,7 +5339,7 @@ clip-path
|
||||||
unsafe {
|
unsafe {
|
||||||
Gecko_SetCursorImageValue(
|
Gecko_SetCursorImageValue(
|
||||||
&mut self.gecko.mCursorImages[i],
|
&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 {
|
unsafe {
|
||||||
bindings::Gecko_SetContentDataImageValue(
|
bindings::Gecko_SetContentDataImageValue(
|
||||||
&mut self.gecko.mContents[i],
|
&mut self.gecko.mContents[i],
|
||||||
url.0.image_value.get(),
|
url.url_value_ptr(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
from itertools import groupby
|
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::RawGeckoGfxMatrix4x4;
|
||||||
#[cfg(feature = "gecko")] use gecko_bindings::structs::nsCSSPropertyID;
|
#[cfg(feature = "gecko")] use gecko_bindings::structs::nsCSSPropertyID;
|
||||||
#[cfg(feature = "gecko")] use gecko_bindings::sugar::ownership::{HasFFI, HasSimpleFFI};
|
#[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::{Angle, CalcLengthOrPercentage};
|
||||||
use values::computed::{ClipRect, Context};
|
use values::computed::{ClipRect, Context};
|
||||||
use values::computed::{Length, LengthOrPercentage, LengthOrPercentageOrAuto};
|
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::{NonNegativeNumber, Number, NumberOrPercentage, Percentage};
|
||||||
use values::computed::length::NonNegativeLengthOrPercentage;
|
use values::computed::length::NonNegativeLengthOrPercentage;
|
||||||
use values::computed::ToComputedValue;
|
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 {
|
impl ToAnimatedZero for FontWeight {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_animated_zero(&self) -> Result<Self, ()> {
|
fn to_animated_zero(&self) -> Result<Self, ()> {
|
||||||
|
|
|
@ -111,7 +111,7 @@ ${helpers.predefined_type(
|
||||||
vector=False,
|
vector=False,
|
||||||
animation_value_type="discrete",
|
animation_value_type="discrete",
|
||||||
flags="APPLIES_TO_FIRST_LETTER",
|
flags="APPLIES_TO_FIRST_LETTER",
|
||||||
boxed=True,
|
boxed=product == "servo",
|
||||||
)}
|
)}
|
||||||
|
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
|
|
|
@ -23,7 +23,7 @@ ${helpers.predefined_type(
|
||||||
${helpers.single_keyword(
|
${helpers.single_keyword(
|
||||||
"text-transform",
|
"text-transform",
|
||||||
"none capitalize uppercase lowercase",
|
"none capitalize uppercase lowercase",
|
||||||
extra_gecko_values="full-width",
|
extra_gecko_values="full-width full-size-kana",
|
||||||
animation_value_type="discrete",
|
animation_value_type="discrete",
|
||||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||||
spec="https://drafts.csswg.org/css-text/#propdef-text-transform",
|
spec="https://drafts.csswg.org/css-text/#propdef-text-transform",
|
||||||
|
|
|
@ -1671,53 +1671,30 @@ impl PropertyId {
|
||||||
///
|
///
|
||||||
/// Returns Err(()) for unknown non-custom properties.
|
/// Returns Err(()) for unknown non-custom properties.
|
||||||
fn parse_unchecked(property_name: &str) -> Result<Self, ()> {
|
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! {
|
ascii_case_insensitive_phf_map! {
|
||||||
static_id -> StaticId = {
|
property_id -> PropertyId = {
|
||||||
% for (kind, properties) in [("Longhand", data.longhands), ("Shorthand", data.shorthands)]:
|
% for (kind, properties) in [("Longhand", data.longhands), ("Shorthand", data.shorthands)]:
|
||||||
% for property in properties:
|
% for property in properties:
|
||||||
"${property.name}" => StaticId::${kind}(${kind}Id::${property.camel_case}),
|
"${property.name}" => PropertyId::${kind}(${kind}Id::${property.camel_case}),
|
||||||
% for alias in property.alias:
|
% for alias in property.alias:
|
||||||
"${alias.name}" => {
|
"${alias.name}" => {
|
||||||
StaticId::${kind}Alias(${kind}Id::${property.camel_case},
|
PropertyId::${kind}Alias(
|
||||||
AliasId::${alias.camel_case})
|
${kind}Id::${property.camel_case},
|
||||||
},
|
AliasId::${alias.camel_case},
|
||||||
% endfor
|
)
|
||||||
% endfor
|
},
|
||||||
|
% endfor
|
||||||
|
% endfor
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(match static_id(property_name) {
|
if let Some(id) = property_id(property_name) {
|
||||||
Some(&StaticId::Longhand(id)) => {
|
return Ok(id.clone())
|
||||||
PropertyId::Longhand(id)
|
}
|
||||||
},
|
|
||||||
Some(&StaticId::Shorthand(id)) => {
|
let name = ::custom_properties::parse_name(property_name)?;
|
||||||
PropertyId::Shorthand(id)
|
Ok(PropertyId::Custom(::custom_properties::Name::from(name)))
|
||||||
},
|
|
||||||
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))
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a property name, and returns an error if it's unknown or isn't
|
/// 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>
|
impl<'a, T: 'a> StyleStructRef<'a, T>
|
||||||
where T: Clone,
|
where
|
||||||
|
T: Clone,
|
||||||
{
|
{
|
||||||
/// Ensure a mutable reference of this value exists, either cloning the
|
/// Ensure a mutable reference of this value exists, either cloning the
|
||||||
/// borrowed value, or returning the owned one.
|
/// 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.
|
/// Extract a unique Arc from this struct, vacating it.
|
||||||
///
|
///
|
||||||
/// The vacated state is a transient one, please put the Arc back
|
/// 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 reset_style = device.default_computed_values();
|
||||||
let inherited_style = parent_style.unwrap_or(reset_style);
|
let inherited_style = parent_style.unwrap_or(reset_style);
|
||||||
let inherited_style_ignoring_first_line = parent_style_ignoring_first_line.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();
|
let flags = inherited_style.flags.inherited();
|
||||||
|
|
||||||
|
@ -3388,6 +3373,10 @@ impl<'a> StyleBuilder<'a> {
|
||||||
self.flags.insert(ComputedValueFlags::INHERITS_DISPLAY);
|
self.flags.insert(ComputedValueFlags::INHERITS_DISPLAY);
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
|
if self.${property.style_struct.ident}.ptr_eq(inherited_struct) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self.${property.style_struct.ident}.mutate()
|
self.${property.style_struct.ident}.mutate()
|
||||||
.copy_${property.ident}_from(
|
.copy_${property.ident}_from(
|
||||||
inherited_struct,
|
inherited_struct,
|
||||||
|
@ -3407,10 +3396,10 @@ impl<'a> StyleBuilder<'a> {
|
||||||
self.modified_reset = true;
|
self.modified_reset = true;
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
// TODO(emilio): There's a maybe-worth it optimization here: We should
|
if self.${property.style_struct.ident}.ptr_eq(reset_struct) {
|
||||||
// avoid allocating a new reset struct if `reset_struct` and our struct
|
return;
|
||||||
// is the same pointer. Would remove a bunch of stupid allocations if
|
}
|
||||||
// you did something like `* { all: initial }` or what not.
|
|
||||||
self.${property.style_struct.ident}.mutate()
|
self.${property.style_struct.ident}.mutate()
|
||||||
.reset_${property.ident}(
|
.reset_${property.ident}(
|
||||||
reset_struct,
|
reset_struct,
|
||||||
|
|
|
@ -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
|
/// Covert non-canonical pseudo-element to canonical one, and keep a
|
||||||
/// canonical one as it is.
|
/// canonical one as it is.
|
||||||
pub fn canonical(&self) -> PseudoElement {
|
pub fn canonical(&self) -> PseudoElement {
|
||||||
|
|
|
@ -23,6 +23,9 @@ use values::computed::{Context, ToComputedValue};
|
||||||
///
|
///
|
||||||
/// However, this approach is still not necessarily optimal: See
|
/// However, this approach is still not necessarily optimal: See
|
||||||
/// <https://bugzilla.mozilla.org/show_bug.cgi?id=1347435#c6>
|
/// <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)]
|
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize, SpecifiedValueInfo)]
|
||||||
pub struct CssUrl {
|
pub struct CssUrl {
|
||||||
/// The original URI. This might be optional since we may insert computed
|
/// The original URI. This might be optional since we may insert computed
|
||||||
|
|
|
@ -179,12 +179,7 @@ impl Parse for VectorValues {
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
impl ToGeckoFontFeatureValues for VectorValues {
|
impl ToGeckoFontFeatureValues for VectorValues {
|
||||||
fn to_gecko_font_feature_values(&self, array: &mut nsTArray<u32>) {
|
fn to_gecko_font_feature_values(&self, array: &mut nsTArray<u32>) {
|
||||||
unsafe {
|
array.assign_from_iter_pod(self.0.iter().map(|v| *v));
|
||||||
array.set_len_pod(self.0.len() as u32);
|
|
||||||
}
|
|
||||||
for (dest, value) in array.iter_mut().zip(self.0.iter()) {
|
|
||||||
*dest = *value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -277,7 +277,6 @@ impl CssRule {
|
||||||
|
|
||||||
// nested rules are in the body state
|
// nested rules are in the body state
|
||||||
let mut rule_parser = TopLevelRuleParser {
|
let mut rule_parser = TopLevelRuleParser {
|
||||||
stylesheet_origin: parent_stylesheet_contents.origin,
|
|
||||||
context,
|
context,
|
||||||
shared_lock: &shared_lock,
|
shared_lock: &shared_lock,
|
||||||
loader,
|
loader,
|
||||||
|
|
|
@ -19,7 +19,7 @@ use servo_arc::Arc;
|
||||||
use shared_lock::{Locked, SharedRwLock};
|
use shared_lock::{Locked, SharedRwLock};
|
||||||
use str::starts_with_ignore_ascii_case;
|
use str::starts_with_ignore_ascii_case;
|
||||||
use style_traits::{ParseError, StyleParseErrorKind};
|
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::{DocumentRule, FontFeatureValuesRule, KeyframesRule, MediaRule};
|
||||||
use stylesheets::{NamespaceRule, PageRule, StyleRule, SupportsRule, ViewportRule};
|
use stylesheets::{NamespaceRule, PageRule, StyleRule, SupportsRule, ViewportRule};
|
||||||
use stylesheets::document_rule::DocumentCondition;
|
use stylesheets::document_rule::DocumentCondition;
|
||||||
|
@ -41,8 +41,6 @@ pub struct InsertRuleContext<'a> {
|
||||||
|
|
||||||
/// The parser for the top-level rules in a stylesheet.
|
/// The parser for the top-level rules in a stylesheet.
|
||||||
pub struct TopLevelRuleParser<'a> {
|
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.
|
/// A reference to the lock we need to use to create rules.
|
||||||
pub shared_lock: &'a SharedRwLock,
|
pub shared_lock: &'a SharedRwLock,
|
||||||
/// A reference to a stylesheet loader if applicable, for `@import` rules.
|
/// A reference to a stylesheet loader if applicable, for `@import` rules.
|
||||||
|
@ -69,7 +67,6 @@ pub struct TopLevelRuleParser<'a> {
|
||||||
impl<'b> TopLevelRuleParser<'b> {
|
impl<'b> TopLevelRuleParser<'b> {
|
||||||
fn nested<'a: 'b>(&'a self) -> NestedRuleParser<'a, 'b> {
|
fn nested<'a: 'b>(&'a self) -> NestedRuleParser<'a, 'b> {
|
||||||
NestedRuleParser {
|
NestedRuleParser {
|
||||||
stylesheet_origin: self.stylesheet_origin,
|
|
||||||
shared_lock: self.shared_lock,
|
shared_lock: self.shared_lock,
|
||||||
context: &self.context,
|
context: &self.context,
|
||||||
namespaces: &self.namespaces,
|
namespaces: &self.namespaces,
|
||||||
|
@ -325,7 +322,6 @@ impl<'a, 'i> QualifiedRuleParser<'i> for TopLevelRuleParser<'a> {
|
||||||
|
|
||||||
#[derive(Clone)] // shallow, relatively cheap .clone
|
#[derive(Clone)] // shallow, relatively cheap .clone
|
||||||
struct NestedRuleParser<'a, 'b: 'a> {
|
struct NestedRuleParser<'a, 'b: 'a> {
|
||||||
stylesheet_origin: Origin,
|
|
||||||
shared_lock: &'a SharedRwLock,
|
shared_lock: &'a SharedRwLock,
|
||||||
context: &'a ParserContext<'b>,
|
context: &'a ParserContext<'b>,
|
||||||
namespaces: &'a Namespaces,
|
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 context = ParserContext::new_with_rule_type(self.context, rule_type, self.namespaces);
|
||||||
|
|
||||||
let nested_parser = NestedRuleParser {
|
let nested_parser = NestedRuleParser {
|
||||||
stylesheet_origin: self.stylesheet_origin,
|
|
||||||
shared_lock: self.shared_lock,
|
shared_lock: self.shared_lock,
|
||||||
context: &context,
|
context: &context,
|
||||||
namespaces: self.namespaces,
|
namespaces: self.namespaces,
|
||||||
|
@ -501,7 +496,7 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> {
|
||||||
self.namespaces,
|
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(
|
Ok(CssRule::Supports(Arc::new(self.shared_lock.wrap(
|
||||||
SupportsRule {
|
SupportsRule {
|
||||||
condition,
|
condition,
|
||||||
|
@ -577,7 +572,7 @@ impl<'a, 'b, 'i> QualifiedRuleParser<'i> for NestedRuleParser<'a, 'b> {
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
) -> Result<Self::Prelude, ParseError<'i>> {
|
) -> Result<Self::Prelude, ParseError<'i>> {
|
||||||
let selector_parser = SelectorParser {
|
let selector_parser = SelectorParser {
|
||||||
stylesheet_origin: self.stylesheet_origin,
|
stylesheet_origin: self.context.stylesheet_origin,
|
||||||
namespaces: self.namespaces,
|
namespaces: self.namespaces,
|
||||||
url_data: Some(self.context.url_data),
|
url_data: Some(self.context.url_data),
|
||||||
};
|
};
|
||||||
|
|
|
@ -374,7 +374,6 @@ impl Stylesheet {
|
||||||
);
|
);
|
||||||
|
|
||||||
let rule_parser = TopLevelRuleParser {
|
let rule_parser = TopLevelRuleParser {
|
||||||
stylesheet_origin: origin,
|
|
||||||
shared_lock,
|
shared_lock,
|
||||||
loader: stylesheet_loader,
|
loader: stylesheet_loader,
|
||||||
context,
|
context,
|
||||||
|
|
|
@ -11,7 +11,8 @@ use cssparser::parse_important;
|
||||||
use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
|
use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
|
||||||
use parser::ParserContext;
|
use parser::ParserContext;
|
||||||
use properties::{PropertyDeclaration, PropertyId, SourcePropertyDeclaration};
|
use properties::{PropertyDeclaration, PropertyId, SourcePropertyDeclaration};
|
||||||
use selectors::parser::SelectorParseErrorKind;
|
use selector_parser::{SelectorImpl, SelectorParser};
|
||||||
|
use selectors::parser::{Selector, SelectorParseErrorKind};
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked};
|
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked};
|
||||||
use shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
use shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
||||||
|
@ -19,8 +20,8 @@ use std::ffi::{CStr, CString};
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use std::str;
|
use std::str;
|
||||||
use str::CssStringWriter;
|
use str::CssStringWriter;
|
||||||
use style_traits::{CssWriter, ParseError, ToCss};
|
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
||||||
use stylesheets::{CssRuleType, CssRules};
|
use stylesheets::{CssRuleType, CssRules, Namespaces};
|
||||||
|
|
||||||
/// An [`@supports`][supports] rule.
|
/// An [`@supports`][supports] rule.
|
||||||
///
|
///
|
||||||
|
@ -87,6 +88,8 @@ pub enum SupportsCondition {
|
||||||
Or(Vec<SupportsCondition>),
|
Or(Vec<SupportsCondition>),
|
||||||
/// `property-ident: value` (value can be any tokens)
|
/// `property-ident: value` (value can be any tokens)
|
||||||
Declaration(Declaration),
|
Declaration(Declaration),
|
||||||
|
/// A `selector()` function.
|
||||||
|
Selector(RawSelector),
|
||||||
/// `-moz-bool-pref("pref-name")`
|
/// `-moz-bool-pref("pref-name")`
|
||||||
/// Since we need to pass it through FFI to get the pref value,
|
/// Since we need to pass it through FFI to get the pref value,
|
||||||
/// we store it as CString directly.
|
/// we store it as CString directly.
|
||||||
|
@ -99,8 +102,8 @@ impl SupportsCondition {
|
||||||
/// Parse a condition
|
/// Parse a condition
|
||||||
///
|
///
|
||||||
/// <https://drafts.csswg.org/css-conditional/#supports_condition>
|
/// <https://drafts.csswg.org/css-conditional/#supports_condition>
|
||||||
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<SupportsCondition, ParseError<'i>> {
|
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(_) = input.try(|i| i.expect_ident_matching("not")) {
|
if input.try(|i| i.expect_ident_matching("not")).is_ok() {
|
||||||
let inner = SupportsCondition::parse_in_parens(input)?;
|
let inner = SupportsCondition::parse_in_parens(input)?;
|
||||||
return Ok(SupportsCondition::Not(Box::new(inner)));
|
return Ok(SupportsCondition::Not(Box::new(inner)));
|
||||||
}
|
}
|
||||||
|
@ -109,10 +112,8 @@ impl SupportsCondition {
|
||||||
|
|
||||||
let location = input.current_source_location();
|
let location = input.current_source_location();
|
||||||
let (keyword, wrapper) = match input.next() {
|
let (keyword, wrapper) = match input.next() {
|
||||||
Err(_) => {
|
// End of input
|
||||||
// End of input
|
Err(..) => return Ok(in_parens),
|
||||||
return Ok(in_parens);
|
|
||||||
},
|
|
||||||
Ok(&Token::Ident(ref ident)) => {
|
Ok(&Token::Ident(ref ident)) => {
|
||||||
match_ignore_ascii_case! { &ident,
|
match_ignore_ascii_case! { &ident,
|
||||||
"and" => ("and", SupportsCondition::And as fn(_) -> _),
|
"and" => ("and", SupportsCondition::And as fn(_) -> _),
|
||||||
|
@ -132,17 +133,48 @@ impl SupportsCondition {
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
// Did not find the expected keyword.
|
// Did not find the expected keyword.
|
||||||
// If we found some other token,
|
// If we found some other token, it will be rejected by
|
||||||
// it will be rejected by `Parser::parse_entirely` somewhere up the stack.
|
// `Parser::parse_entirely` somewhere up the stack.
|
||||||
return Ok(wrapper(conditions));
|
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>
|
/// <https://drafts.csswg.org/css-conditional-3/#supports_condition_in_parens>
|
||||||
fn parse_in_parens<'i, 't>(
|
fn parse_in_parens<'i, 't>(
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
) -> Result<SupportsCondition, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
// Whitespace is normally taken care of in `Parser::next`,
|
// Whitespace is normally taken care of in `Parser::next`,
|
||||||
// but we want to not include it in `pos` for the SupportsCondition::FutureSyntax cases.
|
// but we want to not include it in `pos` for the SupportsCondition::FutureSyntax cases.
|
||||||
while input.try(Parser::expect_whitespace).is_ok() {}
|
while input.try(Parser::expect_whitespace).is_ok() {}
|
||||||
|
@ -151,46 +183,45 @@ impl SupportsCondition {
|
||||||
// FIXME: remove clone() when lifetimes are non-lexical
|
// FIXME: remove clone() when lifetimes are non-lexical
|
||||||
match input.next()?.clone() {
|
match input.next()?.clone() {
|
||||||
Token::ParenthesisBlock => {
|
Token::ParenthesisBlock => {
|
||||||
let nested = input
|
let nested = input.try(|input| {
|
||||||
.try(|input| input.parse_nested_block(|i| parse_condition_or_declaration(i)));
|
input.parse_nested_block(parse_condition_or_declaration)
|
||||||
|
});
|
||||||
if nested.is_ok() {
|
if nested.is_ok() {
|
||||||
return nested;
|
return nested;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Token::Function(ident) => {
|
Token::Function(ident) => {
|
||||||
// Although this is an internal syntax, it is not necessary to check
|
let nested = input.try(|input| {
|
||||||
// parsing context as far as we accept any unexpected token as future
|
input.parse_nested_block(|input| {
|
||||||
// syntax, and evaluate it to false when not in chrome / ua sheet.
|
SupportsCondition::parse_functional(&ident, input)
|
||||||
// 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| {
|
if nested.is_ok() {
|
||||||
i.parse_nested_block(|i| {
|
return nested;
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
t => return Err(location.new_unexpected_token_error(t)),
|
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(
|
Ok(SupportsCondition::FutureSyntax(
|
||||||
input.slice_from(pos).to_owned(),
|
input.slice_from(pos).to_owned(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate a supports condition
|
/// Evaluate a supports condition
|
||||||
pub fn eval(&self, cx: &ParserContext) -> bool {
|
pub fn eval(
|
||||||
|
&self,
|
||||||
|
cx: &ParserContext,
|
||||||
|
namespaces: &Namespaces,
|
||||||
|
) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
SupportsCondition::Not(ref cond) => !cond.eval(cx),
|
SupportsCondition::Not(ref cond) => !cond.eval(cx, namespaces),
|
||||||
SupportsCondition::Parenthesized(ref cond) => cond.eval(cx),
|
SupportsCondition::Parenthesized(ref cond) => cond.eval(cx, namespaces),
|
||||||
SupportsCondition::And(ref vec) => vec.iter().all(|c| c.eval(cx)),
|
SupportsCondition::And(ref vec) => vec.iter().all(|c| c.eval(cx, namespaces)),
|
||||||
SupportsCondition::Or(ref vec) => vec.iter().any(|c| c.eval(cx)),
|
SupportsCondition::Or(ref vec) => vec.iter().any(|c| c.eval(cx, namespaces)),
|
||||||
SupportsCondition::Declaration(ref decl) => decl.eval(cx),
|
SupportsCondition::Declaration(ref decl) => decl.eval(cx),
|
||||||
SupportsCondition::MozBoolPref(ref name) => eval_moz_bool_pref(name, cx),
|
SupportsCondition::MozBoolPref(ref name) => eval_moz_bool_pref(name, cx),
|
||||||
|
SupportsCondition::Selector(ref selector) => selector.eval(cx, namespaces),
|
||||||
SupportsCondition::FutureSyntax(_) => false,
|
SupportsCondition::FutureSyntax(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -265,6 +296,11 @@ impl ToCss for SupportsCondition {
|
||||||
decl.to_css(dest)?;
|
decl.to_css(dest)?;
|
||||||
dest.write_str(")")
|
dest.write_str(")")
|
||||||
},
|
},
|
||||||
|
SupportsCondition::Selector(ref selector) => {
|
||||||
|
dest.write_str("selector(")?;
|
||||||
|
selector.to_css(dest)?;
|
||||||
|
dest.write_str(")")
|
||||||
|
}
|
||||||
SupportsCondition::MozBoolPref(ref name) => {
|
SupportsCondition::MozBoolPref(ref name) => {
|
||||||
dest.write_str("-moz-bool-pref(")?;
|
dest.write_str("-moz-bool-pref(")?;
|
||||||
let name =
|
let name =
|
||||||
|
@ -277,6 +313,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)]
|
#[derive(Clone, Debug)]
|
||||||
/// A possibly-invalid property declaration
|
/// A possibly-invalid property declaration
|
||||||
pub struct Declaration(pub String);
|
pub struct Declaration(pub String);
|
||||||
|
@ -313,21 +412,20 @@ impl Declaration {
|
||||||
|
|
||||||
let mut input = ParserInput::new(&self.0);
|
let mut input = ParserInput::new(&self.0);
|
||||||
let mut input = Parser::new(&mut input);
|
let mut input = Parser::new(&mut input);
|
||||||
input
|
input.parse_entirely(|input| -> Result<(), CssParseError<()>> {
|
||||||
.parse_entirely(|input| -> Result<(), CssParseError<()>> {
|
let prop = input.expect_ident_cloned().unwrap();
|
||||||
let prop = input.expect_ident_cloned().unwrap();
|
input.expect_colon().unwrap();
|
||||||
input.expect_colon().unwrap();
|
|
||||||
|
|
||||||
let id =
|
let id =
|
||||||
PropertyId::parse(&prop, context).map_err(|_| input.new_custom_error(()))?;
|
PropertyId::parse(&prop, context).map_err(|_| input.new_custom_error(()))?;
|
||||||
|
|
||||||
let mut declarations = SourcePropertyDeclaration::new();
|
let mut declarations = SourcePropertyDeclaration::new();
|
||||||
input.parse_until_before(Delimiter::Bang, |input| {
|
input.parse_until_before(Delimiter::Bang, |input| {
|
||||||
PropertyDeclaration::parse_into(&mut declarations, id, &context, input)
|
PropertyDeclaration::parse_into(&mut declarations, id, &context, input)
|
||||||
.map_err(|_| input.new_custom_error(()))
|
.map_err(|_| input.new_custom_error(()))
|
||||||
})?;
|
})?;
|
||||||
let _ = input.try(parse_important);
|
let _ = input.try(parse_important);
|
||||||
Ok(())
|
Ok(())
|
||||||
}).is_ok()
|
}).is_ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -614,14 +614,6 @@ impl Stylist {
|
||||||
|
|
||||||
/// Computes the style for a given "precomputed" pseudo-element, taking the
|
/// Computes the style for a given "precomputed" pseudo-element, taking the
|
||||||
/// universal rules and applying them.
|
/// 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>(
|
pub fn precomputed_values_for_pseudo<E>(
|
||||||
&self,
|
&self,
|
||||||
guards: &StylesheetGuards,
|
guards: &StylesheetGuards,
|
||||||
|
@ -2423,6 +2415,9 @@ impl CascadeData {
|
||||||
if let Some(ref mut slotted_rules) = self.slotted_rules {
|
if let Some(ref mut slotted_rules) = self.slotted_rules {
|
||||||
slotted_rules.clear();
|
slotted_rules.clear();
|
||||||
}
|
}
|
||||||
|
if let Some(ref mut host_rules) = self.host_rules {
|
||||||
|
host_rules.clear();
|
||||||
|
}
|
||||||
self.animations.clear();
|
self.animations.clear();
|
||||||
self.extra_data.clear();
|
self.extra_data.clear();
|
||||||
self.rules_source_order = 0;
|
self.rules_source_order = 0;
|
||||||
|
@ -2448,6 +2443,9 @@ impl CascadeData {
|
||||||
if let Some(ref slotted_rules) = self.slotted_rules {
|
if let Some(ref slotted_rules) = self.slotted_rules {
|
||||||
slotted_rules.add_size_of(ops, sizes);
|
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.mInvalidationMap += self.invalidation_map.size_of(ops);
|
||||||
sizes.mRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops);
|
sizes.mRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops);
|
||||||
sizes.mOther += self.animations.size_of(ops);
|
sizes.mOther += self.animations.size_of(ops);
|
||||||
|
|
|
@ -292,8 +292,9 @@ impl ToAnimatedValue for ComputedMaxLength {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
||||||
use values::computed::{Length, LengthOrPercentageOrNone, Percentage};
|
use values::computed::{Length, LengthOrPercentageOrNone, Percentage};
|
||||||
|
use values::generics::length::MaxLength as GenericMaxLength;
|
||||||
match animated {
|
match animated {
|
||||||
ComputedMaxLength::LengthOrPercentageOrNone(lopn) => {
|
GenericMaxLength::LengthOrPercentageOrNone(lopn) => {
|
||||||
let result = match lopn {
|
let result = match lopn {
|
||||||
LengthOrPercentageOrNone::Length(px) => {
|
LengthOrPercentageOrNone::Length(px) => {
|
||||||
LengthOrPercentageOrNone::Length(Length::new(px.px().max(0.)))
|
LengthOrPercentageOrNone::Length(Length::new(px.px().max(0.)))
|
||||||
|
@ -303,7 +304,7 @@ impl ToAnimatedValue for ComputedMaxLength {
|
||||||
},
|
},
|
||||||
_ => lopn,
|
_ => lopn,
|
||||||
};
|
};
|
||||||
ComputedMaxLength::LengthOrPercentageOrNone(result)
|
GenericMaxLength::LengthOrPercentageOrNone(result)
|
||||||
},
|
},
|
||||||
_ => animated,
|
_ => animated,
|
||||||
}
|
}
|
||||||
|
@ -321,8 +322,9 @@ impl ToAnimatedValue for ComputedMozLength {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
||||||
use values::computed::{Length, LengthOrPercentageOrAuto, Percentage};
|
use values::computed::{Length, LengthOrPercentageOrAuto, Percentage};
|
||||||
|
use values::generics::length::MozLength as GenericMozLength;
|
||||||
match animated {
|
match animated {
|
||||||
ComputedMozLength::LengthOrPercentageOrAuto(lopa) => {
|
GenericMozLength::LengthOrPercentageOrAuto(lopa) => {
|
||||||
let result = match lopa {
|
let result = match lopa {
|
||||||
LengthOrPercentageOrAuto::Length(px) => {
|
LengthOrPercentageOrAuto::Length(px) => {
|
||||||
LengthOrPercentageOrAuto::Length(Length::new(px.px().max(0.)))
|
LengthOrPercentageOrAuto::Length(Length::new(px.px().max(0.)))
|
||||||
|
@ -332,7 +334,7 @@ impl ToAnimatedValue for ComputedMozLength {
|
||||||
},
|
},
|
||||||
_ => lopa,
|
_ => lopa,
|
||||||
};
|
};
|
||||||
ComputedMozLength::LengthOrPercentageOrAuto(result)
|
GenericMozLength::LengthOrPercentageOrAuto(result)
|
||||||
},
|
},
|
||||||
_ => animated,
|
_ => animated,
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,36 +7,39 @@
|
||||||
use num_traits::Zero;
|
use num_traits::Zero;
|
||||||
use std::{f32, f64};
|
use std::{f32, f64};
|
||||||
use std::f64::consts::PI;
|
use std::f64::consts::PI;
|
||||||
|
use std::fmt::{self, Write};
|
||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
|
use style_traits::{CssWriter, ToCss};
|
||||||
use values::CSSFloat;
|
use values::CSSFloat;
|
||||||
use values::animated::{Animate, Procedure};
|
|
||||||
use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||||
|
|
||||||
/// A computed angle.
|
/// A computed angle in degrees.
|
||||||
#[animate(fallback = "Self::animate_fallback")]
|
|
||||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||||
#[derive(
|
#[derive(Animate, Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, ToAnimatedZero)]
|
||||||
Animate, Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, ToAnimatedZero, ToCss,
|
pub struct Angle(CSSFloat);
|
||||||
)]
|
|
||||||
pub enum Angle {
|
impl ToCss for Angle {
|
||||||
/// An angle with degree unit.
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
#[css(dimension)]
|
where
|
||||||
Deg(CSSFloat),
|
W: Write,
|
||||||
/// An angle with gradian unit.
|
{
|
||||||
#[css(dimension)]
|
self.degrees().to_css(dest)?;
|
||||||
Grad(CSSFloat),
|
dest.write_str("deg")
|
||||||
/// An angle with radian unit.
|
}
|
||||||
#[css(dimension)]
|
|
||||||
Rad(CSSFloat),
|
|
||||||
/// An angle with turn unit.
|
|
||||||
#[css(dimension)]
|
|
||||||
Turn(CSSFloat),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RAD_PER_DEG: f64 = PI / 180.0;
|
||||||
|
|
||||||
impl Angle {
|
impl Angle {
|
||||||
/// Creates a computed `Angle` value from a radian amount.
|
/// Creates a computed `Angle` value from a radian amount.
|
||||||
pub fn from_radians(radians: CSSFloat) -> Self {
|
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.
|
/// 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`.
|
/// Returns the amount of radians this angle represents as a `f64`.
|
||||||
///
|
///
|
||||||
/// Gecko stores angles as singles, but does this computation using doubles.
|
/// 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
|
/// This is significant enough to mess up rounding to the nearest
|
||||||
/// quarter-turn for 225 degrees, for example.
|
/// quarter-turn for 225 degrees, for example.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn radians64(&self) -> f64 {
|
pub fn radians64(&self) -> f64 {
|
||||||
const RAD_PER_DEG: f64 = PI / 180.0;
|
self.0 as f64 * RAD_PER_DEG
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the value in degrees.
|
/// 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]
|
#[inline]
|
||||||
fn animate_fallback(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
pub fn degrees(&self) -> CSSFloat {
|
||||||
Ok(Angle::from_radians(
|
self.0
|
||||||
self.radians().animate(&other.radians(), procedure)?,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsRef<Angle> for Angle {
|
|
||||||
#[inline]
|
|
||||||
fn as_ref(&self) -> &Self {
|
|
||||||
self
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,27 +71,19 @@ impl Add for Angle {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add(self, rhs: Self) -> Self {
|
fn add(self, rhs: Self) -> Self {
|
||||||
match (self, rhs) {
|
Angle(self.0 + rhs.0)
|
||||||
(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()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Zero for Angle {
|
impl Zero for Angle {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn zero() -> Self {
|
fn zero() -> Self {
|
||||||
Angle::from_radians(0.0)
|
Angle(0.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_zero(&self) -> bool {
|
fn is_zero(&self) -> bool {
|
||||||
match *self {
|
self.0 == 0.
|
||||||
Angle::Deg(val) | Angle::Grad(val) | Angle::Turn(val) | Angle::Rad(val) => val == 0.,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +92,6 @@ impl ComputeSquaredDistance for Angle {
|
||||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||||
// Use the formula for calculating the distance between angles defined in SVG:
|
// Use the formula for calculating the distance between angles defined in SVG:
|
||||||
// https://www.w3.org/TR/SVG/animate.html#complexDistances
|
// https://www.w3.org/TR/SVG/animate.html#complexDistances
|
||||||
self.radians64()
|
self.radians64().compute_squared_distance(&other.radians64())
|
||||||
.compute_squared_distance(&other.radians64())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -866,7 +866,7 @@ impl ToAnimatedValue for FontStyleAngle {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
||||||
FontStyleAngle(Angle::Deg(
|
FontStyleAngle(Angle::from_degrees(
|
||||||
animated
|
animated
|
||||||
.degrees()
|
.degrees()
|
||||||
.min(specified::FONT_STYLE_OBLIQUE_MAX_ANGLE_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
|
/// https://drafts.csswg.org/css-fonts-4/#valdef-font-style-oblique-angle
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn default_angle() -> FontStyleAngle {
|
pub fn default_angle() -> FontStyleAngle {
|
||||||
FontStyleAngle(Angle::Deg(
|
FontStyleAngle(Angle::from_degrees(
|
||||||
specified::DEFAULT_FONT_STYLE_OBLIQUE_ANGLE_DEGREES,
|
specified::DEFAULT_FONT_STYLE_OBLIQUE_ANGLE_DEGREES,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -919,7 +919,7 @@ impl FontStyle {
|
||||||
if italic {
|
if italic {
|
||||||
return generics::FontStyle::Italic;
|
return generics::FontStyle::Italic;
|
||||||
}
|
}
|
||||||
generics::FontStyle::Oblique(FontStyleAngle(Angle::Deg(angle)))
|
generics::FontStyle::Oblique(FontStyleAngle(Angle::from_degrees(angle)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,7 @@
|
||||||
//! `<length>` computed values, and related ones.
|
//! `<length>` computed values, and related ones.
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use logical_geometry::WritingMode;
|
|
||||||
use ordered_float::NotNan;
|
use ordered_float::NotNan;
|
||||||
use properties::LonghandId;
|
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use std::ops::{Add, Neg};
|
use std::ops::{Add, Neg};
|
||||||
use style_traits::{CssWriter, ToCss};
|
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::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
|
||||||
use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||||
use values::generics::NonNegative;
|
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::{AbsoluteLength, FontBaseSize, FontRelativeLength};
|
||||||
use values::specified::length::ViewportPercentageLength;
|
use values::specified::length::ViewportPercentageLength;
|
||||||
|
|
||||||
|
@ -951,7 +950,8 @@ pub type NonNegativeLengthOrPercentageOrNormal = Either<NonNegativeLengthOrPerce
|
||||||
/// block-size, and inline-size.
|
/// block-size, and inline-size.
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
#[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 {
|
pub enum ExtremumLength {
|
||||||
MozMaxContent,
|
MozMaxContent,
|
||||||
MozMinContent,
|
MozMinContent,
|
||||||
|
@ -959,161 +959,24 @@ pub enum ExtremumLength {
|
||||||
MozAvailable,
|
MozAvailable,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtremumLength {
|
/// A computed value for `min-width`, `min-height`, `width` or `height` property.
|
||||||
/// Returns whether this size keyword can be used for the given writing-mode
|
pub type MozLength = GenericMozLength<LengthOrPercentageOrAuto>;
|
||||||
/// 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),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MozLength {
|
impl MozLength {
|
||||||
/// Returns the `auto` value.
|
/// Returns the `auto` value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn auto() -> Self {
|
pub fn auto() -> Self {
|
||||||
MozLength::LengthOrPercentageOrAuto(LengthOrPercentageOrAuto::Auto)
|
GenericMozLength::LengthOrPercentageOrAuto(LengthOrPercentageOrAuto::Auto)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToComputedValue for specified::MozLength {
|
/// A computed value for `max-width` or `min-height` property.
|
||||||
type ComputedValue = MozLength;
|
pub type MaxLength = GenericMaxLength<LengthOrPercentageOrNone>;
|
||||||
|
|
||||||
#[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),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MaxLength {
|
impl MaxLength {
|
||||||
/// Returns the `none` value.
|
/// Returns the `none` value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn none() -> Self {
|
pub fn none() -> Self {
|
||||||
MaxLength::LengthOrPercentageOrNone(LengthOrPercentageOrNone::None)
|
GenericMaxLength::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()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
54
components/style/values/generics/length.rs
Normal file
54
components/style/values/generics/length.rs
Normal file
|
@ -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),
|
||||||
|
}
|
|
@ -27,6 +27,7 @@ pub mod font;
|
||||||
pub mod gecko;
|
pub mod gecko;
|
||||||
pub mod grid;
|
pub mod grid;
|
||||||
pub mod image;
|
pub mod image;
|
||||||
|
pub mod length;
|
||||||
pub mod position;
|
pub mod position;
|
||||||
pub mod rect;
|
pub mod rect;
|
||||||
pub mod size;
|
pub mod size;
|
||||||
|
|
|
@ -10,6 +10,7 @@ use num_traits::Zero;
|
||||||
use values::{computed, CSSFloat};
|
use values::{computed, CSSFloat};
|
||||||
use values::computed::length::Length as ComputedLength;
|
use values::computed::length::Length as ComputedLength;
|
||||||
use values::computed::length::LengthOrPercentage as ComputedLengthOrPercentage;
|
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::Length as SpecifiedLength;
|
||||||
use values::specified::length::LengthOrPercentage as SpecifiedLengthOrPercentage;
|
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>, ()>;
|
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
|
impl<Angle, Number, Length, Integer, LoP> ToMatrix
|
||||||
for TransformOperation<Angle, Number, Length, Integer, LoP>
|
for TransformOperation<Angle, Number, Length, Integer, LoP>
|
||||||
where
|
where
|
||||||
Angle: Copy + AsRef<computed::angle::Angle>,
|
Angle: ToRadians + Copy,
|
||||||
Number: Copy + Into<f32> + Into<f64>,
|
Number: Copy + Into<f32> + Into<f64>,
|
||||||
Length: ToAbsoluteLength,
|
Length: ToAbsoluteLength,
|
||||||
LoP: ToAbsoluteLength,
|
LoP: ToAbsoluteLength,
|
||||||
|
@ -426,7 +447,7 @@ where
|
||||||
let reference_height = reference_box.map(|v| v.size.height);
|
let reference_height = reference_box.map(|v| v.size.height);
|
||||||
let matrix = match *self {
|
let matrix = match *self {
|
||||||
Rotate3D(ax, ay, az, theta) => {
|
Rotate3D(ax, ay, az, theta) => {
|
||||||
let theta = TWO_PI - theta.as_ref().radians64();
|
let theta = TWO_PI - theta.radians64();
|
||||||
let (ax, ay, az, theta) =
|
let (ax, ay, az, theta) =
|
||||||
get_normalized_vector_and_angle(ax.into(), ay.into(), az.into(), theta);
|
get_normalized_vector_and_angle(ax.into(), ay.into(), az.into(), theta);
|
||||||
Transform3D::create_rotation(
|
Transform3D::create_rotation(
|
||||||
|
@ -437,15 +458,15 @@ where
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
RotateX(theta) => {
|
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)
|
Transform3D::create_rotation(1., 0., 0., theta)
|
||||||
},
|
},
|
||||||
RotateY(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)
|
Transform3D::create_rotation(0., 1., 0., theta)
|
||||||
},
|
},
|
||||||
RotateZ(theta) | Rotate(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)
|
Transform3D::create_rotation(0., 0., 1., theta)
|
||||||
},
|
},
|
||||||
Perspective(ref d) => {
|
Perspective(ref d) => {
|
||||||
|
@ -479,16 +500,16 @@ where
|
||||||
Transform3D::create_translation(0., 0., z.to_pixel_length(None)? as f64)
|
Transform3D::create_translation(0., 0., z.to_pixel_length(None)? as f64)
|
||||||
},
|
},
|
||||||
Skew(theta_x, theta_y) => Transform3D::create_skew(
|
Skew(theta_x, theta_y) => Transform3D::create_skew(
|
||||||
euclid::Angle::radians(theta_x.as_ref().radians64()),
|
euclid::Angle::radians(theta_x.radians64()),
|
||||||
euclid::Angle::radians(theta_y.map_or(0., |a| a.as_ref().radians64())),
|
euclid::Angle::radians(theta_y.map_or(0., |a| a.radians64())),
|
||||||
),
|
),
|
||||||
SkewX(theta) => Transform3D::create_skew(
|
SkewX(theta) => Transform3D::create_skew(
|
||||||
euclid::Angle::radians(theta.as_ref().radians64()),
|
euclid::Angle::radians(theta.radians64()),
|
||||||
euclid::Angle::radians(0.),
|
euclid::Angle::radians(0.),
|
||||||
),
|
),
|
||||||
SkewY(theta) => Transform3D::create_skew(
|
SkewY(theta) => Transform3D::create_skew(
|
||||||
euclid::Angle::radians(0.),
|
euclid::Angle::radians(0.),
|
||||||
euclid::Angle::radians(theta.as_ref().radians64()),
|
euclid::Angle::radians(theta.radians64()),
|
||||||
),
|
),
|
||||||
Matrix3D(m) => m.into(),
|
Matrix3D(m) => m.into(),
|
||||||
Matrix(m) => m.into(),
|
Matrix(m) => m.into(),
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
use cssparser::{Parser, Token};
|
use cssparser::{Parser, Token};
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
|
use std::f32::consts::PI;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, ToCss};
|
use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, ToCss};
|
||||||
use values::CSSFloat;
|
use values::CSSFloat;
|
||||||
|
@ -13,15 +14,47 @@ use values::computed::{Context, ToComputedValue};
|
||||||
use values::computed::angle::Angle as ComputedAngle;
|
use values::computed::angle::Angle as ComputedAngle;
|
||||||
use values::specified::calc::CalcNode;
|
use values::specified::calc::CalcNode;
|
||||||
|
|
||||||
/// A specified angle.
|
/// A specified angle dimension.
|
||||||
///
|
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||||
/// Computed angles are essentially same as specified ones except for `calc()`
|
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, ToCss)]
|
||||||
/// value serialization. Therefore we are storing a computed angle inside
|
pub enum AngleDimension {
|
||||||
/// to hold the actual value and its unit.
|
/// 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))]
|
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||||
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq)]
|
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq)]
|
||||||
pub struct Angle {
|
pub struct Angle {
|
||||||
value: ComputedAngle,
|
value: AngleDimension,
|
||||||
was_calc: bool,
|
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 {
|
impl ToComputedValue for Angle {
|
||||||
type ComputedValue = ComputedAngle;
|
type ComputedValue = ComputedAngle;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, _context: &Context) -> Self::ComputedValue {
|
fn to_computed_value(&self, _context: &Context) -> Self::ComputedValue {
|
||||||
self.value
|
ComputedAngle::from_degrees(self.degrees())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||||
Angle {
|
Angle {
|
||||||
value: *computed,
|
value: AngleDimension::Deg(computed.degrees()),
|
||||||
was_calc: false,
|
was_calc: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,35 +93,18 @@ impl ToComputedValue for Angle {
|
||||||
|
|
||||||
impl Angle {
|
impl Angle {
|
||||||
/// Creates an angle with the given value in degrees.
|
/// Creates an angle with the given value in degrees.
|
||||||
|
#[inline]
|
||||||
pub fn from_degrees(value: CSSFloat, was_calc: bool) -> Self {
|
pub fn from_degrees(value: CSSFloat, was_calc: bool) -> Self {
|
||||||
Angle {
|
Angle {
|
||||||
value: ComputedAngle::Deg(value),
|
value: AngleDimension::Deg(value),
|
||||||
was_calc,
|
was_calc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an angle with the given value in gradians.
|
/// Returns the value of the angle in degrees, mostly for `calc()`.
|
||||||
pub fn from_gradians(value: CSSFloat, was_calc: bool) -> Self {
|
#[inline]
|
||||||
Angle {
|
pub fn degrees(&self) -> CSSFloat {
|
||||||
value: ComputedAngle::Grad(value),
|
self.value.degrees()
|
||||||
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),
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this specified angle came from a `calc()` expression.
|
/// Whether this specified angle came from a `calc()` expression.
|
||||||
|
@ -101,39 +113,21 @@ impl Angle {
|
||||||
self.was_calc
|
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`.
|
/// Returns `0deg`.
|
||||||
|
#[inline]
|
||||||
pub fn zero() -> Self {
|
pub fn zero() -> Self {
|
||||||
Self::from_degrees(0.0, false)
|
Self::from_degrees(0.0, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an `Angle` parsed from a `calc()` expression.
|
/// Returns an `Angle` parsed from a `calc()` expression.
|
||||||
pub fn from_calc(radians: CSSFloat) -> Self {
|
pub fn from_calc(degrees: CSSFloat) -> Self {
|
||||||
Angle {
|
Angle {
|
||||||
value: ComputedAngle::Rad(radians),
|
value: AngleDimension::Deg(degrees),
|
||||||
was_calc: true,
|
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.
|
/// Whether to allow parsing an unitless zero as a valid angle.
|
||||||
///
|
///
|
||||||
/// This should always be `No`, except for exceptions like:
|
/// This should always be `No`, except for exceptions like:
|
||||||
|
@ -158,20 +152,26 @@ impl Parse for Angle {
|
||||||
|
|
||||||
impl Angle {
|
impl Angle {
|
||||||
/// Parse an `<angle>` value given a value and an unit.
|
/// Parse an `<angle>` value given a value and an unit.
|
||||||
pub fn parse_dimension(value: CSSFloat, unit: &str, from_calc: bool) -> Result<Angle, ()> {
|
pub fn parse_dimension(
|
||||||
let angle = match_ignore_ascii_case! { unit,
|
value: CSSFloat,
|
||||||
"deg" => Angle::from_degrees(value, from_calc),
|
unit: &str,
|
||||||
"grad" => Angle::from_gradians(value, from_calc),
|
was_calc: bool,
|
||||||
"turn" => Angle::from_turns(value, from_calc),
|
) -> Result<Angle, ()> {
|
||||||
"rad" => Angle::from_radians(value, from_calc),
|
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(())
|
_ => return Err(())
|
||||||
};
|
};
|
||||||
Ok(angle)
|
|
||||||
|
Ok(Self { value, was_calc })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an `<angle>` allowing unitless zero to represent a zero angle.
|
/// Parse an `<angle>` allowing unitless zero to represent a zero angle.
|
||||||
///
|
///
|
||||||
/// See the comment in `AllowUnitlessZeroAngle` for why.
|
/// See the comment in `AllowUnitlessZeroAngle` for why.
|
||||||
|
#[inline]
|
||||||
pub fn parse_with_unitless<'i, 't>(
|
pub fn parse_with_unitless<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
|
|
|
@ -966,20 +966,27 @@ pub enum Appearance {
|
||||||
/// A typical dialog button.
|
/// A typical dialog button.
|
||||||
Button,
|
Button,
|
||||||
/// Various arrows that go in buttons
|
/// Various arrows that go in buttons
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
ButtonArrowDown,
|
ButtonArrowDown,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
ButtonArrowNext,
|
ButtonArrowNext,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
ButtonArrowPrevious,
|
ButtonArrowPrevious,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
ButtonArrowUp,
|
ButtonArrowUp,
|
||||||
/// A rectangular button that contains complex content
|
/// A rectangular button that contains complex content
|
||||||
/// like images (e.g. HTML <button> elements)
|
/// like images (e.g. HTML <button> elements)
|
||||||
ButtonBevel,
|
ButtonBevel,
|
||||||
/// The focus outline box inside of a button.
|
/// The focus outline box inside of a button.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
ButtonFocus,
|
ButtonFocus,
|
||||||
/// The caret of a text area
|
/// The caret of a text area
|
||||||
Caret,
|
Caret,
|
||||||
/// A dual toolbar button (e.g., a Back button with a dropdown)
|
/// A dual toolbar button (e.g., a Back button with a dropdown)
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Dualbutton,
|
Dualbutton,
|
||||||
/// A groupbox.
|
/// A groupbox.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Groupbox,
|
Groupbox,
|
||||||
/// A inner-spin button.
|
/// A inner-spin button.
|
||||||
InnerSpinButton,
|
InnerSpinButton,
|
||||||
|
@ -988,12 +995,17 @@ pub enum Appearance {
|
||||||
/// A listbox item.
|
/// A listbox item.
|
||||||
Listitem,
|
Listitem,
|
||||||
/// Menu Bar background
|
/// Menu Bar background
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Menubar,
|
Menubar,
|
||||||
/// <menu> and <menuitem> appearances
|
/// <menu> and <menuitem> appearances
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Menuitem,
|
Menuitem,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Checkmenuitem,
|
Checkmenuitem,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Radiomenuitem,
|
Radiomenuitem,
|
||||||
/// For text on non-iconic menuitems only
|
/// For text on non-iconic menuitems only
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Menuitemtext,
|
Menuitemtext,
|
||||||
/// A dropdown list.
|
/// A dropdown list.
|
||||||
Menulist,
|
Menulist,
|
||||||
|
@ -1004,13 +1016,19 @@ pub enum Appearance {
|
||||||
/// An editable textfield with a dropdown list (a combobox).
|
/// An editable textfield with a dropdown list (a combobox).
|
||||||
MenulistTextfield,
|
MenulistTextfield,
|
||||||
/// Menu Popup background.
|
/// Menu Popup background.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Menupopup,
|
Menupopup,
|
||||||
/// menu checkbox/radio appearances
|
/// menu checkbox/radio appearances
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Menucheckbox,
|
Menucheckbox,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Menuradio,
|
Menuradio,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Menuseparator,
|
Menuseparator,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Menuarrow,
|
Menuarrow,
|
||||||
/// An image in the menu gutter, like in bookmarks or history.
|
/// An image in the menu gutter, like in bookmarks or history.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Menuimage,
|
Menuimage,
|
||||||
/// A horizontal meter bar.
|
/// A horizontal meter bar.
|
||||||
Meterbar,
|
Meterbar,
|
||||||
|
@ -1035,19 +1053,25 @@ pub enum Appearance {
|
||||||
Radio,
|
Radio,
|
||||||
/// A generic container that always repaints on state changes. This is a
|
/// A generic container that always repaints on state changes. This is a
|
||||||
/// hack to make XUL checkboxes and radio buttons work.
|
/// hack to make XUL checkboxes and radio buttons work.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
CheckboxContainer,
|
CheckboxContainer,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
RadioContainer,
|
RadioContainer,
|
||||||
/// The label part of a checkbox or radio button, used for painting a focus
|
/// The label part of a checkbox or radio button, used for painting a focus
|
||||||
/// outline.
|
/// outline.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
CheckboxLabel,
|
CheckboxLabel,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
RadioLabel,
|
RadioLabel,
|
||||||
/// nsRangeFrame and its subparts
|
/// nsRangeFrame and its subparts
|
||||||
Range,
|
Range,
|
||||||
RangeThumb,
|
RangeThumb,
|
||||||
/// The resizer background area in a status bar for the resizer widget in
|
/// The resizer background area in a status bar for the resizer widget in
|
||||||
/// the corner of a window.
|
/// the corner of a window.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Resizerpanel,
|
Resizerpanel,
|
||||||
/// The resizer itself.
|
/// The resizer itself.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Resizer,
|
Resizer,
|
||||||
/// A slider.
|
/// A slider.
|
||||||
ScaleHorizontal,
|
ScaleHorizontal,
|
||||||
|
@ -1061,18 +1085,26 @@ pub enum Appearance {
|
||||||
/// The ticks for a slider.
|
/// The ticks for a slider.
|
||||||
Scalethumbtick,
|
Scalethumbtick,
|
||||||
/// A scrollbar.
|
/// A scrollbar.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Scrollbar,
|
Scrollbar,
|
||||||
/// A small scrollbar.
|
/// A small scrollbar.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
ScrollbarSmall,
|
ScrollbarSmall,
|
||||||
/// The scrollbar slider
|
/// The scrollbar slider
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
ScrollbarHorizontal,
|
ScrollbarHorizontal,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
ScrollbarVertical,
|
ScrollbarVertical,
|
||||||
/// A scrollbar button (up/down/left/right).
|
/// A scrollbar button (up/down/left/right).
|
||||||
/// Keep these in order (some code casts these values to `int` in order to
|
/// Keep these in order (some code casts these values to `int` in order to
|
||||||
/// compare them against each other).
|
/// compare them against each other).
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
ScrollbarbuttonUp,
|
ScrollbarbuttonUp,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
ScrollbarbuttonDown,
|
ScrollbarbuttonDown,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
ScrollbarbuttonLeft,
|
ScrollbarbuttonLeft,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
ScrollbarbuttonRight,
|
ScrollbarbuttonRight,
|
||||||
/// The scrollbar thumb.
|
/// The scrollbar thumb.
|
||||||
ScrollbarthumbHorizontal,
|
ScrollbarthumbHorizontal,
|
||||||
|
@ -1081,107 +1113,166 @@ pub enum Appearance {
|
||||||
ScrollbartrackHorizontal,
|
ScrollbartrackHorizontal,
|
||||||
ScrollbartrackVertical,
|
ScrollbartrackVertical,
|
||||||
/// The scroll corner
|
/// The scroll corner
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Scrollcorner,
|
Scrollcorner,
|
||||||
/// A searchfield.
|
/// A searchfield.
|
||||||
Searchfield,
|
Searchfield,
|
||||||
/// A separator. Can be horizontal or vertical.
|
/// A separator. Can be horizontal or vertical.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Separator,
|
Separator,
|
||||||
/// A spin control (up/down control for time/date pickers).
|
/// A spin control (up/down control for time/date pickers).
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Spinner,
|
Spinner,
|
||||||
/// The up button of a spin control.
|
/// The up button of a spin control.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
SpinnerUpbutton,
|
SpinnerUpbutton,
|
||||||
/// The down button of a spin control.
|
/// The down button of a spin control.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
SpinnerDownbutton,
|
SpinnerDownbutton,
|
||||||
/// The textfield of a spin control
|
/// The textfield of a spin control
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
SpinnerTextfield,
|
SpinnerTextfield,
|
||||||
/// A splitter. Can be horizontal or vertical.
|
/// A splitter. Can be horizontal or vertical.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Splitter,
|
Splitter,
|
||||||
/// A status bar in a main application window.
|
/// A status bar in a main application window.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Statusbar,
|
Statusbar,
|
||||||
/// A single pane of a status bar.
|
/// A single pane of a status bar.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Statusbarpanel,
|
Statusbarpanel,
|
||||||
/// A single tab in a tab widget.
|
/// A single tab in a tab widget.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Tab,
|
Tab,
|
||||||
/// A single pane (inside the tabpanels container).
|
/// A single pane (inside the tabpanels container).
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Tabpanel,
|
Tabpanel,
|
||||||
/// The tab panels container.
|
/// The tab panels container.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Tabpanels,
|
Tabpanels,
|
||||||
/// The tabs scroll arrows (left/right).
|
/// The tabs scroll arrows (left/right).
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
TabScrollArrowBack,
|
TabScrollArrowBack,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
TabScrollArrowForward,
|
TabScrollArrowForward,
|
||||||
/// A textfield or text area.
|
/// A textfield or text area.
|
||||||
Textfield,
|
Textfield,
|
||||||
/// A multiline text field.
|
/// A multiline text field.
|
||||||
TextfieldMultiline,
|
TextfieldMultiline,
|
||||||
/// A toolbar in an application window.
|
/// A toolbar in an application window.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Toolbar,
|
Toolbar,
|
||||||
/// A single toolbar button (with no associated dropdown).
|
/// A single toolbar button (with no associated dropdown).
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Toolbarbutton,
|
Toolbarbutton,
|
||||||
/// The dropdown portion of a toolbar button
|
/// The dropdown portion of a toolbar button
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
ToolbarbuttonDropdown,
|
ToolbarbuttonDropdown,
|
||||||
/// The gripper for a toolbar.
|
/// The gripper for a toolbar.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Toolbargripper,
|
Toolbargripper,
|
||||||
/// The toolbox that contains the toolbars.
|
/// The toolbox that contains the toolbars.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Toolbox,
|
Toolbox,
|
||||||
/// A tooltip.
|
/// A tooltip.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Tooltip,
|
Tooltip,
|
||||||
/// A listbox or tree widget header
|
/// A listbox or tree widget header
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Treeheader,
|
Treeheader,
|
||||||
/// An individual header cell
|
/// An individual header cell
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Treeheadercell,
|
Treeheadercell,
|
||||||
/// The sort arrow for a header.
|
/// The sort arrow for a header.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Treeheadersortarrow,
|
Treeheadersortarrow,
|
||||||
/// A tree item.
|
/// A tree item.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Treeitem,
|
Treeitem,
|
||||||
/// A tree widget branch line
|
/// A tree widget branch line
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Treeline,
|
Treeline,
|
||||||
/// A tree widget twisty.
|
/// A tree widget twisty.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Treetwisty,
|
Treetwisty,
|
||||||
/// Open tree widget twisty.
|
/// Open tree widget twisty.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Treetwistyopen,
|
Treetwistyopen,
|
||||||
/// A tree widget.
|
/// A tree widget.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Treeview,
|
Treeview,
|
||||||
/// Window and dialog backgrounds.
|
/// Window and dialog backgrounds.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Window,
|
Window,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
Dialog,
|
Dialog,
|
||||||
|
|
||||||
/// Vista Rebars.
|
/// Vista Rebars.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozWinCommunicationsToolbox,
|
MozWinCommunicationsToolbox,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozWinMediaToolbox,
|
MozWinMediaToolbox,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozWinBrowsertabbarToolbox,
|
MozWinBrowsertabbarToolbox,
|
||||||
/// Vista glass.
|
/// Vista glass.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozWinGlass,
|
MozWinGlass,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozWinBorderlessGlass,
|
MozWinBorderlessGlass,
|
||||||
/// -moz-apperance style used in setting proper glass margins.
|
/// -moz-apperance style used in setting proper glass margins.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozWinExcludeGlass,
|
MozWinExcludeGlass,
|
||||||
|
|
||||||
/// Titlebar elements on the Mac.
|
/// Titlebar elements on the Mac.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozMacFullscreenButton,
|
MozMacFullscreenButton,
|
||||||
/// Mac help button.
|
/// Mac help button.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozMacHelpButton,
|
MozMacHelpButton,
|
||||||
|
|
||||||
/// Windows themed window frame elements.
|
/// Windows themed window frame elements.
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozWindowButtonBox,
|
MozWindowButtonBox,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozWindowButtonBoxMaximized,
|
MozWindowButtonBoxMaximized,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozWindowButtonClose,
|
MozWindowButtonClose,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozWindowButtonMaximize,
|
MozWindowButtonMaximize,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozWindowButtonMinimize,
|
MozWindowButtonMinimize,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozWindowButtonRestore,
|
MozWindowButtonRestore,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozWindowFrameBottom,
|
MozWindowFrameBottom,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozWindowFrameLeft,
|
MozWindowFrameLeft,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozWindowFrameRight,
|
MozWindowFrameRight,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozWindowTitlebar,
|
MozWindowTitlebar,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozWindowTitlebarMaximized,
|
MozWindowTitlebarMaximized,
|
||||||
|
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozGtkInfoBar,
|
MozGtkInfoBar,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozMacActiveSourceListSelection,
|
MozMacActiveSourceListSelection,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozMacDisclosureButtonClosed,
|
MozMacDisclosureButtonClosed,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozMacDisclosureButtonOpen,
|
MozMacDisclosureButtonOpen,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozMacSourceList,
|
MozMacSourceList,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozMacSourceListSelection,
|
MozMacSourceListSelection,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozMacVibrancyDark,
|
MozMacVibrancyDark,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozMacVibrancyLight,
|
MozMacVibrancyLight,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozMacVibrantTitlebarDark,
|
MozMacVibrantTitlebarDark,
|
||||||
|
#[parse(condition = "in_ua_or_chrome_sheet")]
|
||||||
MozMacVibrantTitlebarLight,
|
MozMacVibrantTitlebarLight,
|
||||||
|
|
||||||
/// A non-disappearing scrollbar.
|
/// A non-disappearing scrollbar.
|
||||||
|
|
|
@ -469,22 +469,22 @@ impl CalcNode {
|
||||||
CalcNode::Sub(ref a, ref b) => {
|
CalcNode::Sub(ref a, ref b) => {
|
||||||
let lhs = a.to_angle()?;
|
let lhs = a.to_angle()?;
|
||||||
let rhs = b.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) => {
|
CalcNode::Sum(ref a, ref b) => {
|
||||||
let lhs = a.to_angle()?;
|
let lhs = a.to_angle()?;
|
||||||
let rhs = b.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() {
|
CalcNode::Mul(ref a, ref b) => match a.to_angle() {
|
||||||
Ok(lhs) => {
|
Ok(lhs) => {
|
||||||
let rhs = b.to_number()?;
|
let rhs = b.to_number()?;
|
||||||
Angle::from_calc(lhs.radians() * rhs)
|
Angle::from_calc(lhs.degrees() * rhs)
|
||||||
},
|
},
|
||||||
Err(..) => {
|
Err(..) => {
|
||||||
let lhs = a.to_number()?;
|
let lhs = a.to_number()?;
|
||||||
let rhs = b.to_angle()?;
|
let rhs = b.to_angle()?;
|
||||||
Angle::from_calc(lhs * rhs.radians())
|
Angle::from_calc(lhs * rhs.degrees())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
CalcNode::Div(ref a, ref b) => {
|
CalcNode::Div(ref a, ref b) => {
|
||||||
|
@ -493,7 +493,7 @@ impl CalcNode {
|
||||||
if rhs == 0. {
|
if rhs == 0. {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
Angle::from_calc(lhs.radians() / rhs)
|
Angle::from_calc(lhs.degrees() / rhs)
|
||||||
},
|
},
|
||||||
CalcNode::Number(..) |
|
CalcNode::Number(..) |
|
||||||
CalcNode::Length(..) |
|
CalcNode::Length(..) |
|
||||||
|
|
|
@ -301,7 +301,7 @@ impl SpecifiedFontStyle {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_angle(angle: &Angle) -> ComputedAngle {
|
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.
|
/// Parse a suitable angle for font-style: oblique.
|
||||||
|
|
|
@ -15,7 +15,6 @@ use selectors::parser::SelectorParseErrorKind;
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::f32::consts::PI;
|
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::{CssType, CssWriter, KeywordsCollectFn, ParseError};
|
use style_traits::{CssType, CssWriter, KeywordsCollectFn, ParseError};
|
||||||
use style_traits::{StyleParseErrorKind, SpecifiedValueInfo, ToCss};
|
use style_traits::{StyleParseErrorKind, SpecifiedValueInfo, ToCss};
|
||||||
|
@ -679,7 +678,7 @@ impl GradientKind {
|
||||||
impl generic::LineDirection for LineDirection {
|
impl generic::LineDirection for LineDirection {
|
||||||
fn points_downwards(&self, compat_mode: CompatMode) -> bool {
|
fn points_downwards(&self, compat_mode: CompatMode) -> bool {
|
||||||
match *self {
|
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::Bottom) if compat_mode == CompatMode::Modern => true,
|
||||||
LineDirection::Vertical(Y::Top) if compat_mode != CompatMode::Modern => true,
|
LineDirection::Vertical(Y::Top) if compat_mode != CompatMode::Modern => true,
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
|
|
|
@ -19,6 +19,7 @@ use super::{AllowQuirks, Number, Percentage, ToComputedValue};
|
||||||
use values::{Auto, CSSFloat, Either, Normal};
|
use values::{Auto, CSSFloat, Either, Normal};
|
||||||
use values::computed::{self, CSSPixelLength, Context, ExtremumLength};
|
use values::computed::{self, CSSPixelLength, Context, ExtremumLength};
|
||||||
use values::generics::NonNegative;
|
use values::generics::NonNegative;
|
||||||
|
use values::generics::length::{MaxLength as GenericMaxLength, MozLength as GenericMozLength};
|
||||||
use values::specified::calc::CalcNode;
|
use values::specified::calc::CalcNode;
|
||||||
|
|
||||||
pub use values::specified::calc::CalcLengthOrPercentage;
|
pub use values::specified::calc::CalcLengthOrPercentage;
|
||||||
|
@ -1188,18 +1189,8 @@ impl LengthOrNumber {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A value suitable for a `min-width` or `min-height` property.
|
/// A specified value for `min-width`, `min-height`, `width` or `height` property.
|
||||||
///
|
pub type MozLength = GenericMozLength<LengthOrPercentageOrAuto>;
|
||||||
/// 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),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Parse for MozLength {
|
impl Parse for MozLength {
|
||||||
fn parse<'i, 't>(
|
fn parse<'i, 't>(
|
||||||
|
@ -1219,7 +1210,7 @@ impl MozLength {
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
let length = LengthOrPercentageOrAuto::parse_non_negative(context, input)?;
|
let length = LengthOrPercentageOrAuto::parse_non_negative(context, input)?;
|
||||||
Ok(MozLength::LengthOrPercentageOrAuto(length))
|
Ok(GenericMozLength::LengthOrPercentageOrAuto(length))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses, with quirks.
|
/// Parses, with quirks.
|
||||||
|
@ -1229,34 +1220,29 @@ impl MozLength {
|
||||||
allow_quirks: AllowQuirks,
|
allow_quirks: AllowQuirks,
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(l) = input.try(ExtremumLength::parse) {
|
if let Ok(l) = input.try(ExtremumLength::parse) {
|
||||||
return Ok(MozLength::ExtremumLength(l));
|
return Ok(GenericMozLength::ExtremumLength(l));
|
||||||
}
|
}
|
||||||
|
|
||||||
let length =
|
let length =
|
||||||
LengthOrPercentageOrAuto::parse_non_negative_quirky(context, input, allow_quirks)?;
|
LengthOrPercentageOrAuto::parse_non_negative_quirky(context, input, allow_quirks)?;
|
||||||
Ok(MozLength::LengthOrPercentageOrAuto(length))
|
Ok(GenericMozLength::LengthOrPercentageOrAuto(length))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `auto`.
|
/// Returns `auto`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn auto() -> Self {
|
pub fn auto() -> Self {
|
||||||
MozLength::LengthOrPercentageOrAuto(LengthOrPercentageOrAuto::auto())
|
GenericMozLength::LengthOrPercentageOrAuto(LengthOrPercentageOrAuto::auto())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `0%`.
|
/// Returns `0%`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn zero_percent() -> Self {
|
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.
|
/// A specified value for `max-width` or `max-height` property.
|
||||||
#[allow(missing_docs)]
|
pub type MaxLength = GenericMaxLength<LengthOrPercentageOrNone>;
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
|
|
||||||
pub enum MaxLength {
|
|
||||||
LengthOrPercentageOrNone(LengthOrPercentageOrNone),
|
|
||||||
ExtremumLength(ExtremumLength),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Parse for MaxLength {
|
impl Parse for MaxLength {
|
||||||
fn parse<'i, 't>(
|
fn parse<'i, 't>(
|
||||||
|
@ -1276,7 +1262,7 @@ impl MaxLength {
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
let length = LengthOrPercentageOrNone::parse_non_negative(context, input)?;
|
let length = LengthOrPercentageOrNone::parse_non_negative(context, input)?;
|
||||||
Ok(MaxLength::LengthOrPercentageOrNone(length))
|
Ok(GenericMaxLength::LengthOrPercentageOrNone(length))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses, with quirks.
|
/// Parses, with quirks.
|
||||||
|
@ -1286,11 +1272,11 @@ impl MaxLength {
|
||||||
allow_quirks: AllowQuirks,
|
allow_quirks: AllowQuirks,
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(l) = input.try(ExtremumLength::parse) {
|
if let Ok(l) = input.try(ExtremumLength::parse) {
|
||||||
return Ok(MaxLength::ExtremumLength(l));
|
return Ok(GenericMaxLength::ExtremumLength(l));
|
||||||
}
|
}
|
||||||
|
|
||||||
let length =
|
let length =
|
||||||
LengthOrPercentageOrNone::parse_non_negative_quirky(context, input, allow_quirks)?;
|
LengthOrPercentageOrNone::parse_non_negative_quirky(context, input, allow_quirks)?;
|
||||||
Ok(MaxLength::LengthOrPercentageOrNone(length))
|
Ok(GenericMaxLength::LengthOrPercentageOrNone(length))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
mod quotes {
|
||||||
pub use super::*;
|
pub use super::*;
|
||||||
|
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
[at-supports-040.html]
|
|
||||||
expected: FAIL
|
|
|
@ -1,4 +0,0 @@
|
||||||
[CSS.html]
|
|
||||||
[CSS.supports, selector function]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -26166,7 +26166,7 @@
|
||||||
"reftest"
|
"reftest"
|
||||||
],
|
],
|
||||||
"css/transform_skew_ref.html": [
|
"css/transform_skew_ref.html": [
|
||||||
"caf92ca6f50d1cfe27f9202ebf79d76dead03ba0",
|
"b6ef9bb8fe9c129b02f5f3213865673a42638190",
|
||||||
"support"
|
"support"
|
||||||
],
|
],
|
||||||
"css/transform_stacking_context_a.html": [
|
"css/transform_stacking_context_a.html": [
|
||||||
|
|
|
@ -17,15 +17,15 @@ div>div {
|
||||||
}
|
}
|
||||||
|
|
||||||
.transformed1_ref {
|
.transformed1_ref {
|
||||||
transform: matrix(1, 0, 0.25534192122, 1, 0, 0);
|
transform: matrix(1, 0, 0.255342, 1, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.transformed2_ref {
|
.transformed2_ref {
|
||||||
transform: matrix(1, 0.54630248984, 0, 1, 0, 0);
|
transform: matrix(1, 0.546302, 0, 1, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.transformed3_ref {
|
.transformed3_ref {
|
||||||
transform: matrix(1, 0.54630248984, 0.25534192122, 1, 0, 0);
|
transform: matrix(1, 0.546302, 0.255342, 1, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue