mirror of
https://github.com/servo/servo.git
synced 2025-08-09 07:25:35 +01:00
Auto merge of #23827 - emilio:gecko-sync, r=emilio,manishearth
style: Sync changes from mozilla-central, and update euclid See individual commits for details. <!-- 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/23827) <!-- Reviewable:end -->
This commit is contained in:
commit
8f7440f368
175 changed files with 1481 additions and 1441 deletions
|
@ -16,8 +16,7 @@ path = "lib.rs"
|
|||
doctest = false
|
||||
|
||||
[features]
|
||||
gecko = ["style_traits/gecko", "fallible/known_system_malloc"]
|
||||
use_bindgen = ["bindgen", "regex", "toml"]
|
||||
gecko = ["style_traits/gecko", "fallible/known_system_malloc", "bindgen", "regex", "toml"]
|
||||
servo = ["serde", "style_traits/servo", "servo_atoms", "servo_config", "html5ever",
|
||||
"cssparser/serde", "encoding_rs", "malloc_size_of/servo", "arrayvec/use_union",
|
||||
"servo_url", "string_cache", "crossbeam-channel", "to_shmem/servo", "servo_arc/servo"]
|
||||
|
@ -37,7 +36,7 @@ crossbeam-channel = { version = "0.3", optional = true }
|
|||
derive_more = "0.13"
|
||||
new_debug_unreachable = "1.0"
|
||||
encoding_rs = {version = "0.8", optional = true}
|
||||
euclid = "0.19"
|
||||
euclid = "0.20"
|
||||
fallible = { path = "../fallible" }
|
||||
fxhash = "0.2"
|
||||
hashglobe = { path = "../hashglobe" }
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[cfg(feature = "bindgen")]
|
||||
#[cfg(feature = "gecko")]
|
||||
extern crate bindgen;
|
||||
#[cfg(feature = "bindgen")]
|
||||
#[cfg(feature = "gecko")]
|
||||
extern crate log;
|
||||
#[cfg(feature = "bindgen")]
|
||||
#[cfg(feature = "gecko")]
|
||||
extern crate regex;
|
||||
#[cfg(feature = "bindgen")]
|
||||
#[cfg(feature = "gecko")]
|
||||
extern crate toml;
|
||||
extern crate walkdir;
|
||||
|
||||
|
|
|
@ -2,458 +2,406 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
mod common {
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use super::PYTHON;
|
||||
use bindgen::{Builder, CodegenConfig};
|
||||
use regex::Regex;
|
||||
use std::cmp;
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::fs::{self, File};
|
||||
use std::io::{Read, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{exit, Command};
|
||||
use std::slice;
|
||||
use std::sync::Mutex;
|
||||
use std::time::SystemTime;
|
||||
use toml;
|
||||
use toml::value::Table;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref OUTDIR_PATH: PathBuf =
|
||||
PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("gecko");
|
||||
lazy_static! {
|
||||
static ref OUTDIR_PATH: PathBuf = PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("gecko");
|
||||
}
|
||||
|
||||
const STRUCTS_FILE: &'static str = "structs.rs";
|
||||
|
||||
fn read_config(path: &PathBuf) -> Table {
|
||||
println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
|
||||
update_last_modified(&path);
|
||||
|
||||
let mut contents = String::new();
|
||||
File::open(path)
|
||||
.expect("Failed to open config file")
|
||||
.read_to_string(&mut contents)
|
||||
.expect("Failed to read config file");
|
||||
match toml::from_str::<Table>(&contents) {
|
||||
Ok(result) => result,
|
||||
Err(e) => panic!("Failed to parse config file: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "bindgen")]
|
||||
mod bindings {
|
||||
use super::super::PYTHON;
|
||||
use super::common::*;
|
||||
use bindgen::{Builder, CodegenConfig};
|
||||
use regex::Regex;
|
||||
use std::cmp;
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::fs::{self, File};
|
||||
use std::io::{Read, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{exit, Command};
|
||||
use std::slice;
|
||||
use std::sync::Mutex;
|
||||
use std::time::SystemTime;
|
||||
use toml;
|
||||
use toml::value::Table;
|
||||
lazy_static! {
|
||||
static ref CONFIG: Table = {
|
||||
// Load Gecko's binding generator config from the source tree.
|
||||
let path = PathBuf::from(env::var_os("MOZ_SRC").unwrap())
|
||||
.join("layout/style/ServoBindings.toml");
|
||||
read_config(&path)
|
||||
};
|
||||
static ref BUILD_CONFIG: Table = {
|
||||
// Load build-specific config overrides.
|
||||
let path = PathBuf::from(env::var_os("MOZ_TOPOBJDIR").unwrap())
|
||||
.join("layout/style/bindgen.toml");
|
||||
read_config(&path)
|
||||
};
|
||||
static ref INCLUDE_RE: Regex = Regex::new(r#"#include\s*"(.+?)""#).unwrap();
|
||||
static ref DISTDIR_PATH: PathBuf = {
|
||||
let path = PathBuf::from(env::var_os("MOZ_DIST").unwrap());
|
||||
if !path.is_absolute() || !path.is_dir() {
|
||||
panic!("MOZ_DIST must be an absolute directory, was: {}", path.display());
|
||||
}
|
||||
path
|
||||
};
|
||||
static ref SEARCH_PATHS: Vec<PathBuf> = vec![
|
||||
DISTDIR_PATH.join("include"),
|
||||
DISTDIR_PATH.join("include/nspr"),
|
||||
];
|
||||
static ref ADDED_PATHS: Mutex<HashSet<PathBuf>> = Mutex::new(HashSet::new());
|
||||
static ref LAST_MODIFIED: Mutex<SystemTime> =
|
||||
Mutex::new(get_modified_time(&env::current_exe().unwrap())
|
||||
.expect("Failed to get modified time of executable"));
|
||||
}
|
||||
|
||||
const STRUCTS_FILE: &'static str = "structs.rs";
|
||||
fn get_modified_time(file: &Path) -> Option<SystemTime> {
|
||||
file.metadata().and_then(|m| m.modified()).ok()
|
||||
}
|
||||
|
||||
fn read_config(path: &PathBuf) -> Table {
|
||||
println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
|
||||
update_last_modified(&path);
|
||||
fn update_last_modified(file: &Path) {
|
||||
let modified = get_modified_time(file).expect("Couldn't get file modification time");
|
||||
let mut last_modified = LAST_MODIFIED.lock().unwrap();
|
||||
*last_modified = cmp::max(modified, *last_modified);
|
||||
}
|
||||
|
||||
let mut contents = String::new();
|
||||
File::open(path)
|
||||
.expect("Failed to open config file")
|
||||
.read_to_string(&mut contents)
|
||||
.expect("Failed to read config file");
|
||||
match toml::from_str::<Table>(&contents) {
|
||||
Ok(result) => result,
|
||||
Err(e) => panic!("Failed to parse config file: {}", e),
|
||||
fn search_include(name: &str) -> Option<PathBuf> {
|
||||
for path in SEARCH_PATHS.iter() {
|
||||
let file = path.join(name);
|
||||
if file.is_file() {
|
||||
update_last_modified(&file);
|
||||
return Some(file);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref CONFIG: Table = {
|
||||
// Load Gecko's binding generator config from the source tree.
|
||||
let path = PathBuf::from(env::var_os("MOZ_SRC").unwrap())
|
||||
.join("layout/style/ServoBindings.toml");
|
||||
read_config(&path)
|
||||
};
|
||||
static ref BUILD_CONFIG: Table = {
|
||||
// Load build-specific config overrides.
|
||||
let path = PathBuf::from(env::var_os("MOZ_TOPOBJDIR").unwrap())
|
||||
.join("layout/style/bindgen.toml");
|
||||
read_config(&path)
|
||||
};
|
||||
static ref INCLUDE_RE: Regex = Regex::new(r#"#include\s*"(.+?)""#).unwrap();
|
||||
static ref DISTDIR_PATH: PathBuf = {
|
||||
let path = PathBuf::from(env::var_os("MOZ_DIST").unwrap());
|
||||
if !path.is_absolute() || !path.is_dir() {
|
||||
panic!("MOZ_DIST must be an absolute directory, was: {}", path.display());
|
||||
}
|
||||
path
|
||||
};
|
||||
static ref SEARCH_PATHS: Vec<PathBuf> = vec![
|
||||
DISTDIR_PATH.join("include"),
|
||||
DISTDIR_PATH.join("include/nspr"),
|
||||
];
|
||||
static ref ADDED_PATHS: Mutex<HashSet<PathBuf>> = Mutex::new(HashSet::new());
|
||||
static ref LAST_MODIFIED: Mutex<SystemTime> =
|
||||
Mutex::new(get_modified_time(&env::current_exe().unwrap())
|
||||
.expect("Failed to get modified time of executable"));
|
||||
fn add_headers_recursively(path: PathBuf, added_paths: &mut HashSet<PathBuf>) {
|
||||
if added_paths.contains(&path) {
|
||||
return;
|
||||
}
|
||||
|
||||
fn get_modified_time(file: &Path) -> Option<SystemTime> {
|
||||
file.metadata().and_then(|m| m.modified()).ok()
|
||||
}
|
||||
|
||||
fn update_last_modified(file: &Path) {
|
||||
let modified = get_modified_time(file).expect("Couldn't get file modification time");
|
||||
let mut last_modified = LAST_MODIFIED.lock().unwrap();
|
||||
*last_modified = cmp::max(modified, *last_modified);
|
||||
}
|
||||
|
||||
fn search_include(name: &str) -> Option<PathBuf> {
|
||||
for path in SEARCH_PATHS.iter() {
|
||||
let file = path.join(name);
|
||||
if file.is_file() {
|
||||
update_last_modified(&file);
|
||||
return Some(file);
|
||||
}
|
||||
let mut file = File::open(&path).unwrap();
|
||||
let mut content = String::new();
|
||||
file.read_to_string(&mut content).unwrap();
|
||||
added_paths.insert(path);
|
||||
// Find all includes and add them recursively
|
||||
for cap in INCLUDE_RE.captures_iter(&content) {
|
||||
if let Some(path) = search_include(cap.get(1).unwrap().as_str()) {
|
||||
add_headers_recursively(path, added_paths);
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn add_headers_recursively(path: PathBuf, added_paths: &mut HashSet<PathBuf>) {
|
||||
if added_paths.contains(&path) {
|
||||
fn add_include(name: &str) -> String {
|
||||
let mut added_paths = ADDED_PATHS.lock().unwrap();
|
||||
let file = search_include(name).expect("Include not found!");
|
||||
let result = String::from(file.to_str().unwrap());
|
||||
add_headers_recursively(file, &mut *added_paths);
|
||||
result
|
||||
}
|
||||
|
||||
trait BuilderExt {
|
||||
fn get_initial_builder() -> Builder;
|
||||
fn include<T: Into<String>>(self, file: T) -> Builder;
|
||||
}
|
||||
|
||||
impl BuilderExt for Builder {
|
||||
fn get_initial_builder() -> Builder {
|
||||
use bindgen::RustTarget;
|
||||
|
||||
// Disable rust unions, because we replace some types inside of
|
||||
// them.
|
||||
let mut builder = Builder::default()
|
||||
.rust_target(RustTarget::Stable_1_25)
|
||||
.disable_untagged_union();
|
||||
|
||||
let rustfmt_path = env::var_os("RUSTFMT")
|
||||
// This can be replaced with
|
||||
// > .filter(|p| !p.is_empty()).map(PathBuf::from)
|
||||
// once we can use 1.27+.
|
||||
.and_then(|p| {
|
||||
if p.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(PathBuf::from(p))
|
||||
}
|
||||
});
|
||||
if let Some(path) = rustfmt_path {
|
||||
builder = builder.with_rustfmt(path);
|
||||
}
|
||||
|
||||
for dir in SEARCH_PATHS.iter() {
|
||||
builder = builder.clang_arg("-I").clang_arg(dir.to_str().unwrap());
|
||||
}
|
||||
|
||||
builder = builder.include(add_include("mozilla-config.h"));
|
||||
|
||||
if env::var("CARGO_FEATURE_GECKO_DEBUG").is_ok() {
|
||||
builder = builder.clang_arg("-DDEBUG=1").clang_arg("-DJS_DEBUG=1");
|
||||
}
|
||||
|
||||
let build_config = BUILD_CONFIG["build"]
|
||||
.as_table()
|
||||
.expect("Malformed config file");
|
||||
let extra_bindgen_flags = build_config["args"].as_array().unwrap().as_slice();
|
||||
for item in extra_bindgen_flags.iter() {
|
||||
builder = builder.clang_arg(item.as_str().expect("Expect string in list"));
|
||||
}
|
||||
|
||||
builder
|
||||
}
|
||||
fn include<T: Into<String>>(self, file: T) -> Builder {
|
||||
self.clang_arg("-include").clang_arg(file)
|
||||
}
|
||||
}
|
||||
|
||||
struct Fixup {
|
||||
pat: String,
|
||||
rep: String,
|
||||
}
|
||||
|
||||
fn write_binding_file(builder: Builder, file: &str, fixups: &[Fixup]) {
|
||||
let out_file = OUTDIR_PATH.join(file);
|
||||
if let Some(modified) = get_modified_time(&out_file) {
|
||||
// Don't generate the file if nothing it depends on was modified.
|
||||
let last_modified = LAST_MODIFIED.lock().unwrap();
|
||||
if *last_modified <= modified {
|
||||
return;
|
||||
}
|
||||
let mut file = File::open(&path).unwrap();
|
||||
let mut content = String::new();
|
||||
file.read_to_string(&mut content).unwrap();
|
||||
added_paths.insert(path);
|
||||
// Find all includes and add them recursively
|
||||
for cap in INCLUDE_RE.captures_iter(&content) {
|
||||
if let Some(path) = search_include(cap.get(1).unwrap().as_str()) {
|
||||
add_headers_recursively(path, added_paths);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn add_include(name: &str) -> String {
|
||||
let mut added_paths = ADDED_PATHS.lock().unwrap();
|
||||
let file = search_include(name).expect("Include not found!");
|
||||
let result = String::from(file.to_str().unwrap());
|
||||
add_headers_recursively(file, &mut *added_paths);
|
||||
result
|
||||
}
|
||||
|
||||
trait BuilderExt {
|
||||
fn get_initial_builder() -> Builder;
|
||||
fn include<T: Into<String>>(self, file: T) -> Builder;
|
||||
}
|
||||
|
||||
impl BuilderExt for Builder {
|
||||
fn get_initial_builder() -> Builder {
|
||||
use bindgen::RustTarget;
|
||||
|
||||
// Disable rust unions, because we replace some types inside of
|
||||
// them.
|
||||
let mut builder = Builder::default()
|
||||
.rust_target(RustTarget::Stable_1_25)
|
||||
.disable_untagged_union();
|
||||
|
||||
let rustfmt_path = env::var_os("RUSTFMT")
|
||||
// This can be replaced with
|
||||
// > .filter(|p| !p.is_empty()).map(PathBuf::from)
|
||||
// once we can use 1.27+.
|
||||
.and_then(|p| {
|
||||
if p.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(PathBuf::from(p))
|
||||
}
|
||||
});
|
||||
if let Some(path) = rustfmt_path {
|
||||
builder = builder.with_rustfmt(path);
|
||||
}
|
||||
|
||||
for dir in SEARCH_PATHS.iter() {
|
||||
builder = builder.clang_arg("-I").clang_arg(dir.to_str().unwrap());
|
||||
}
|
||||
|
||||
builder = builder.include(add_include("mozilla-config.h"));
|
||||
|
||||
if env::var("CARGO_FEATURE_GECKO_DEBUG").is_ok() {
|
||||
builder = builder.clang_arg("-DDEBUG=1").clang_arg("-DJS_DEBUG=1");
|
||||
}
|
||||
|
||||
let build_config = BUILD_CONFIG["build"]
|
||||
.as_table()
|
||||
.expect("Malformed config file");
|
||||
let extra_bindgen_flags = build_config["args"].as_array().unwrap().as_slice();
|
||||
for item in extra_bindgen_flags.iter() {
|
||||
builder = builder.clang_arg(item.as_str().expect("Expect string in list"));
|
||||
}
|
||||
|
||||
builder
|
||||
}
|
||||
fn include<T: Into<String>>(self, file: T) -> Builder {
|
||||
self.clang_arg("-include").clang_arg(file)
|
||||
}
|
||||
}
|
||||
|
||||
struct Fixup {
|
||||
pat: String,
|
||||
rep: String,
|
||||
}
|
||||
|
||||
fn write_binding_file(builder: Builder, file: &str, fixups: &[Fixup]) {
|
||||
let out_file = OUTDIR_PATH.join(file);
|
||||
if let Some(modified) = get_modified_time(&out_file) {
|
||||
// Don't generate the file if nothing it depends on was modified.
|
||||
let last_modified = LAST_MODIFIED.lock().unwrap();
|
||||
if *last_modified <= modified {
|
||||
return;
|
||||
}
|
||||
}
|
||||
let command_line_opts = builder.command_line_flags();
|
||||
let result = builder.generate();
|
||||
let mut result = match result {
|
||||
Ok(bindings) => bindings.to_string(),
|
||||
Err(_) => {
|
||||
panic!(
|
||||
"Failed to generate bindings, flags: {:?}",
|
||||
command_line_opts
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
for fixup in fixups.iter() {
|
||||
result = Regex::new(&fixup.pat)
|
||||
.unwrap()
|
||||
.replace_all(&result, &*fixup.rep)
|
||||
.into_owned()
|
||||
.into();
|
||||
}
|
||||
let bytes = result.into_bytes();
|
||||
File::create(&out_file)
|
||||
.unwrap()
|
||||
.write_all(&bytes)
|
||||
.expect("Unable to write output");
|
||||
}
|
||||
|
||||
struct BuilderWithConfig<'a> {
|
||||
builder: Builder,
|
||||
config: &'a Table,
|
||||
used_keys: HashSet<&'static str>,
|
||||
}
|
||||
impl<'a> BuilderWithConfig<'a> {
|
||||
fn new(builder: Builder, config: &'a Table) -> Self {
|
||||
BuilderWithConfig {
|
||||
builder,
|
||||
config,
|
||||
used_keys: HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_list<F>(self, key: &'static str, func: F) -> BuilderWithConfig<'a>
|
||||
where
|
||||
F: FnOnce(Builder, slice::Iter<'a, toml::Value>) -> Builder,
|
||||
{
|
||||
let mut builder = self.builder;
|
||||
let config = self.config;
|
||||
let mut used_keys = self.used_keys;
|
||||
if let Some(list) = config.get(key) {
|
||||
used_keys.insert(key);
|
||||
builder = func(builder, list.as_array().unwrap().as_slice().iter());
|
||||
}
|
||||
BuilderWithConfig {
|
||||
builder,
|
||||
config,
|
||||
used_keys,
|
||||
}
|
||||
}
|
||||
fn handle_items<F>(self, key: &'static str, mut func: F) -> BuilderWithConfig<'a>
|
||||
where
|
||||
F: FnMut(Builder, &'a toml::Value) -> Builder,
|
||||
{
|
||||
self.handle_list(key, |b, iter| iter.fold(b, |b, item| func(b, item)))
|
||||
}
|
||||
fn handle_str_items<F>(self, key: &'static str, mut func: F) -> BuilderWithConfig<'a>
|
||||
where
|
||||
F: FnMut(Builder, &'a str) -> Builder,
|
||||
{
|
||||
self.handle_items(key, |b, item| func(b, item.as_str().unwrap()))
|
||||
}
|
||||
fn handle_table_items<F>(self, key: &'static str, mut func: F) -> BuilderWithConfig<'a>
|
||||
where
|
||||
F: FnMut(Builder, &'a Table) -> Builder,
|
||||
{
|
||||
self.handle_items(key, |b, item| func(b, item.as_table().unwrap()))
|
||||
}
|
||||
fn handle_common(self, fixups: &mut Vec<Fixup>) -> BuilderWithConfig<'a> {
|
||||
self.handle_str_items("headers", |b, item| b.header(add_include(item)))
|
||||
.handle_str_items("raw-lines", |b, item| b.raw_line(item))
|
||||
.handle_str_items("hide-types", |b, item| b.blacklist_type(item))
|
||||
.handle_table_items("fixups", |builder, item| {
|
||||
fixups.push(Fixup {
|
||||
pat: item["pat"].as_str().unwrap().into(),
|
||||
rep: item["rep"].as_str().unwrap().into(),
|
||||
});
|
||||
builder
|
||||
})
|
||||
}
|
||||
|
||||
fn get_builder(self) -> Builder {
|
||||
for key in self.config.keys() {
|
||||
if !self.used_keys.contains(key.as_str()) {
|
||||
panic!(format!("Unknown key: {}", key));
|
||||
}
|
||||
}
|
||||
self.builder
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_structs() {
|
||||
let builder = Builder::get_initial_builder()
|
||||
.enable_cxx_namespaces()
|
||||
.with_codegen_config(
|
||||
CodegenConfig::TYPES | CodegenConfig::VARS | CodegenConfig::FUNCTIONS,
|
||||
let command_line_opts = builder.command_line_flags();
|
||||
let result = builder.generate();
|
||||
let mut result = match result {
|
||||
Ok(bindings) => bindings.to_string(),
|
||||
Err(_) => {
|
||||
panic!(
|
||||
"Failed to generate bindings, flags: {:?}",
|
||||
command_line_opts
|
||||
);
|
||||
let mut fixups = vec![];
|
||||
let builder = BuilderWithConfig::new(builder, CONFIG["structs"].as_table().unwrap())
|
||||
.handle_common(&mut fixups)
|
||||
.handle_str_items("whitelist-functions", |b, item| b.whitelist_function(item))
|
||||
.handle_str_items("bitfield-enums", |b, item| b.bitfield_enum(item))
|
||||
.handle_str_items("rusty-enums", |b, item| b.rustified_enum(item))
|
||||
.handle_str_items("whitelist-vars", |b, item| b.whitelist_var(item))
|
||||
.handle_str_items("whitelist-types", |b, item| b.whitelist_type(item))
|
||||
.handle_str_items("opaque-types", |b, item| b.opaque_type(item))
|
||||
.handle_table_items("cbindgen-types", |b, item| {
|
||||
let gecko = item["gecko"].as_str().unwrap();
|
||||
let servo = item["servo"].as_str().unwrap();
|
||||
b.blacklist_type(format!("mozilla::{}", gecko))
|
||||
.module_raw_line("root::mozilla", format!("pub use {} as {};", servo, gecko))
|
||||
})
|
||||
.handle_table_items("mapped-generic-types", |builder, item| {
|
||||
let generic = item["generic"].as_bool().unwrap();
|
||||
let gecko = item["gecko"].as_str().unwrap();
|
||||
let servo = item["servo"].as_str().unwrap();
|
||||
let gecko_name = gecko.rsplit("::").next().unwrap();
|
||||
let gecko = gecko
|
||||
.split("::")
|
||||
.map(|s| format!("\\s*{}\\s*", s))
|
||||
.collect::<Vec<_>>()
|
||||
.join("::");
|
||||
},
|
||||
};
|
||||
|
||||
for fixup in fixups.iter() {
|
||||
result = Regex::new(&fixup.pat)
|
||||
.unwrap()
|
||||
.replace_all(&result, &*fixup.rep)
|
||||
.into_owned()
|
||||
.into();
|
||||
}
|
||||
let bytes = result.into_bytes();
|
||||
File::create(&out_file)
|
||||
.unwrap()
|
||||
.write_all(&bytes)
|
||||
.expect("Unable to write output");
|
||||
}
|
||||
|
||||
struct BuilderWithConfig<'a> {
|
||||
builder: Builder,
|
||||
config: &'a Table,
|
||||
used_keys: HashSet<&'static str>,
|
||||
}
|
||||
impl<'a> BuilderWithConfig<'a> {
|
||||
fn new(builder: Builder, config: &'a Table) -> Self {
|
||||
BuilderWithConfig {
|
||||
builder,
|
||||
config,
|
||||
used_keys: HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_list<F>(self, key: &'static str, func: F) -> BuilderWithConfig<'a>
|
||||
where
|
||||
F: FnOnce(Builder, slice::Iter<'a, toml::Value>) -> Builder,
|
||||
{
|
||||
let mut builder = self.builder;
|
||||
let config = self.config;
|
||||
let mut used_keys = self.used_keys;
|
||||
if let Some(list) = config.get(key) {
|
||||
used_keys.insert(key);
|
||||
builder = func(builder, list.as_array().unwrap().as_slice().iter());
|
||||
}
|
||||
BuilderWithConfig {
|
||||
builder,
|
||||
config,
|
||||
used_keys,
|
||||
}
|
||||
}
|
||||
fn handle_items<F>(self, key: &'static str, mut func: F) -> BuilderWithConfig<'a>
|
||||
where
|
||||
F: FnMut(Builder, &'a toml::Value) -> Builder,
|
||||
{
|
||||
self.handle_list(key, |b, iter| iter.fold(b, |b, item| func(b, item)))
|
||||
}
|
||||
fn handle_str_items<F>(self, key: &'static str, mut func: F) -> BuilderWithConfig<'a>
|
||||
where
|
||||
F: FnMut(Builder, &'a str) -> Builder,
|
||||
{
|
||||
self.handle_items(key, |b, item| func(b, item.as_str().unwrap()))
|
||||
}
|
||||
fn handle_table_items<F>(self, key: &'static str, mut func: F) -> BuilderWithConfig<'a>
|
||||
where
|
||||
F: FnMut(Builder, &'a Table) -> Builder,
|
||||
{
|
||||
self.handle_items(key, |b, item| func(b, item.as_table().unwrap()))
|
||||
}
|
||||
fn handle_common(self, fixups: &mut Vec<Fixup>) -> BuilderWithConfig<'a> {
|
||||
self.handle_str_items("headers", |b, item| b.header(add_include(item)))
|
||||
.handle_str_items("raw-lines", |b, item| b.raw_line(item))
|
||||
.handle_str_items("hide-types", |b, item| b.blacklist_type(item))
|
||||
.handle_table_items("fixups", |builder, item| {
|
||||
fixups.push(Fixup {
|
||||
pat: format!("\\broot\\s*::\\s*{}\\b", gecko),
|
||||
rep: format!("::gecko_bindings::structs::{}", gecko_name),
|
||||
pat: item["pat"].as_str().unwrap().into(),
|
||||
rep: item["rep"].as_str().unwrap().into(),
|
||||
});
|
||||
builder.blacklist_type(gecko).raw_line(format!(
|
||||
"pub type {0}{2} = {1}{2};",
|
||||
gecko_name,
|
||||
servo,
|
||||
if generic { "<T>" } else { "" }
|
||||
))
|
||||
builder
|
||||
})
|
||||
.get_builder();
|
||||
write_binding_file(builder, STRUCTS_FILE, &fixups);
|
||||
}
|
||||
|
||||
fn setup_logging() -> bool {
|
||||
struct BuildLogger {
|
||||
file: Option<Mutex<fs::File>>,
|
||||
filter: String,
|
||||
}
|
||||
|
||||
impl log::Log for BuildLogger {
|
||||
fn enabled(&self, meta: &log::Metadata) -> bool {
|
||||
self.file.is_some() && meta.target().contains(&self.filter)
|
||||
}
|
||||
|
||||
fn log(&self, record: &log::Record) {
|
||||
if !self.enabled(record.metadata()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut file = self.file.as_ref().unwrap().lock().unwrap();
|
||||
let _ = writeln!(
|
||||
file,
|
||||
"{} - {} - {} @ {}:{}",
|
||||
record.level(),
|
||||
record.target(),
|
||||
record.args(),
|
||||
record.file().unwrap_or("<unknown>"),
|
||||
record.line().unwrap_or(0)
|
||||
);
|
||||
}
|
||||
|
||||
fn flush(&self) {
|
||||
if let Some(ref file) = self.file {
|
||||
file.lock().unwrap().flush().unwrap();
|
||||
}
|
||||
fn get_builder(self) -> Builder {
|
||||
for key in self.config.keys() {
|
||||
if !self.used_keys.contains(key.as_str()) {
|
||||
panic!(format!("Unknown key: {}", key));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(path) = env::var_os("STYLO_BUILD_LOG") {
|
||||
log::set_max_level(log::LevelFilter::Debug);
|
||||
log::set_boxed_logger(Box::new(BuildLogger {
|
||||
file: fs::File::create(path).ok().map(Mutex::new),
|
||||
filter: env::var("STYLO_BUILD_FILTER")
|
||||
.ok()
|
||||
.unwrap_or_else(|| "bindgen".to_owned()),
|
||||
}))
|
||||
.expect("Failed to set logger.");
|
||||
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_atoms() {
|
||||
let script = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap())
|
||||
.join("gecko")
|
||||
.join("regen_atoms.py");
|
||||
println!("cargo:rerun-if-changed={}", script.display());
|
||||
let status = Command::new(&*PYTHON)
|
||||
.arg(&script)
|
||||
.arg(DISTDIR_PATH.as_os_str())
|
||||
.arg(OUTDIR_PATH.as_os_str())
|
||||
.status()
|
||||
.unwrap();
|
||||
if !status.success() {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate() {
|
||||
setup_logging();
|
||||
generate_structs();
|
||||
generate_atoms();
|
||||
|
||||
for path in ADDED_PATHS.lock().unwrap().iter() {
|
||||
println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
|
||||
}
|
||||
self.builder
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "bindgen"))]
|
||||
mod bindings {
|
||||
use super::common::*;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{env, fs, io};
|
||||
fn generate_structs() {
|
||||
let builder = Builder::get_initial_builder()
|
||||
.enable_cxx_namespaces()
|
||||
.with_codegen_config(CodegenConfig::TYPES | CodegenConfig::VARS | CodegenConfig::FUNCTIONS);
|
||||
let mut fixups = vec![];
|
||||
let builder = BuilderWithConfig::new(builder, CONFIG["structs"].as_table().unwrap())
|
||||
.handle_common(&mut fixups)
|
||||
.handle_str_items("whitelist-functions", |b, item| b.whitelist_function(item))
|
||||
.handle_str_items("bitfield-enums", |b, item| b.bitfield_enum(item))
|
||||
.handle_str_items("rusty-enums", |b, item| b.rustified_enum(item))
|
||||
.handle_str_items("whitelist-vars", |b, item| b.whitelist_var(item))
|
||||
.handle_str_items("whitelist-types", |b, item| b.whitelist_type(item))
|
||||
.handle_str_items("opaque-types", |b, item| b.opaque_type(item))
|
||||
.handle_table_items("cbindgen-types", |b, item| {
|
||||
let gecko = item["gecko"].as_str().unwrap();
|
||||
let servo = item["servo"].as_str().unwrap();
|
||||
b.blacklist_type(format!("mozilla::{}", gecko))
|
||||
.module_raw_line("root::mozilla", format!("pub use {} as {};", servo, gecko))
|
||||
})
|
||||
.handle_table_items("mapped-generic-types", |builder, item| {
|
||||
let generic = item["generic"].as_bool().unwrap();
|
||||
let gecko = item["gecko"].as_str().unwrap();
|
||||
let servo = item["servo"].as_str().unwrap();
|
||||
let gecko_name = gecko.rsplit("::").next().unwrap();
|
||||
let gecko = gecko
|
||||
.split("::")
|
||||
.map(|s| format!("\\s*{}\\s*", s))
|
||||
.collect::<Vec<_>>()
|
||||
.join("::");
|
||||
|
||||
/// Copy contents of one directory into another.
|
||||
/// It currently only does a shallow copy.
|
||||
fn copy_dir<P, Q, F>(from: P, to: Q, callback: F) -> io::Result<()>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
Q: AsRef<Path>,
|
||||
F: Fn(&Path),
|
||||
{
|
||||
let to = to.as_ref();
|
||||
for entry in from.as_ref().read_dir()? {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
callback(&path);
|
||||
fs::copy(&path, to.join(entry.file_name()))?;
|
||||
}
|
||||
Ok(())
|
||||
fixups.push(Fixup {
|
||||
pat: format!("\\broot\\s*::\\s*{}\\b", gecko),
|
||||
rep: format!("::gecko_bindings::structs::{}", gecko_name),
|
||||
});
|
||||
builder.blacklist_type(gecko).raw_line(format!(
|
||||
"pub type {0}{2} = {1}{2};",
|
||||
gecko_name,
|
||||
servo,
|
||||
if generic { "<T>" } else { "" }
|
||||
))
|
||||
})
|
||||
.get_builder();
|
||||
write_binding_file(builder, STRUCTS_FILE, &fixups);
|
||||
}
|
||||
|
||||
fn setup_logging() -> bool {
|
||||
struct BuildLogger {
|
||||
file: Option<Mutex<fs::File>>,
|
||||
filter: String,
|
||||
}
|
||||
|
||||
pub fn generate() {
|
||||
let dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap()).join("gecko/generated");
|
||||
println!("cargo:rerun-if-changed={}", dir.display());
|
||||
copy_dir(&dir, &*OUTDIR_PATH, |path| {
|
||||
println!("cargo:rerun-if-changed={}", path.display());
|
||||
})
|
||||
.expect("Fail to copy generated files to out dir");
|
||||
impl log::Log for BuildLogger {
|
||||
fn enabled(&self, meta: &log::Metadata) -> bool {
|
||||
self.file.is_some() && meta.target().contains(&self.filter)
|
||||
}
|
||||
|
||||
fn log(&self, record: &log::Record) {
|
||||
if !self.enabled(record.metadata()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut file = self.file.as_ref().unwrap().lock().unwrap();
|
||||
let _ = writeln!(
|
||||
file,
|
||||
"{} - {} - {} @ {}:{}",
|
||||
record.level(),
|
||||
record.target(),
|
||||
record.args(),
|
||||
record.file().unwrap_or("<unknown>"),
|
||||
record.line().unwrap_or(0)
|
||||
);
|
||||
}
|
||||
|
||||
fn flush(&self) {
|
||||
if let Some(ref file) = self.file {
|
||||
file.lock().unwrap().flush().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(path) = env::var_os("STYLO_BUILD_LOG") {
|
||||
log::set_max_level(log::LevelFilter::Debug);
|
||||
log::set_boxed_logger(Box::new(BuildLogger {
|
||||
file: fs::File::create(path).ok().map(Mutex::new),
|
||||
filter: env::var("STYLO_BUILD_FILTER")
|
||||
.ok()
|
||||
.unwrap_or_else(|| "bindgen".to_owned()),
|
||||
}))
|
||||
.expect("Failed to set logger.");
|
||||
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_atoms() {
|
||||
let script = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap())
|
||||
.join("gecko")
|
||||
.join("regen_atoms.py");
|
||||
println!("cargo:rerun-if-changed={}", script.display());
|
||||
let status = Command::new(&*PYTHON)
|
||||
.arg(&script)
|
||||
.arg(DISTDIR_PATH.as_os_str())
|
||||
.arg(OUTDIR_PATH.as_os_str())
|
||||
.status()
|
||||
.unwrap();
|
||||
if !status.success() {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate() {
|
||||
use self::common::*;
|
||||
use std::fs;
|
||||
println!("cargo:rerun-if-changed=build_gecko.rs");
|
||||
fs::create_dir_all(&*OUTDIR_PATH).unwrap();
|
||||
bindings::generate();
|
||||
setup_logging();
|
||||
generate_structs();
|
||||
generate_atoms();
|
||||
|
||||
for path in ADDED_PATHS.lock().unwrap().iter() {
|
||||
println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,8 +31,8 @@ use crate::traversal_flags::TraversalFlags;
|
|||
use app_units::Au;
|
||||
#[cfg(feature = "servo")]
|
||||
use crossbeam_channel::Sender;
|
||||
use euclid::Size2D;
|
||||
use euclid::TypedScale;
|
||||
use euclid::default::Size2D;
|
||||
use euclid::Scale;
|
||||
use fxhash::FxHashMap;
|
||||
#[cfg(feature = "servo")]
|
||||
use parking_lot::RwLock;
|
||||
|
@ -195,7 +195,7 @@ impl<'a> SharedStyleContext<'a> {
|
|||
}
|
||||
|
||||
/// The device pixel ratio
|
||||
pub fn device_pixel_ratio(&self) -> TypedScale<f32, CSSPixel, DevicePixel> {
|
||||
pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
|
||||
self.stylist.device().device_pixel_ratio()
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ use crate::values::computed::CSSPixelLength;
|
|||
use crate::values::computed::Resolution;
|
||||
use crate::Atom;
|
||||
use app_units::Au;
|
||||
use euclid::Size2D;
|
||||
use euclid::default::Size2D;
|
||||
|
||||
fn viewport_size(device: &Device) -> Size2D<Au> {
|
||||
if let Some(pc) = device.pres_context() {
|
||||
|
|
|
@ -16,8 +16,8 @@ use crate::values::{CustomIdent, KeyframesName};
|
|||
use app_units::Au;
|
||||
use app_units::AU_PER_PX;
|
||||
use cssparser::RGBA;
|
||||
use euclid::Size2D;
|
||||
use euclid::TypedScale;
|
||||
use euclid::default::Size2D;
|
||||
use euclid::Scale;
|
||||
use servo_arc::Arc;
|
||||
use std::fmt;
|
||||
use std::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize, Ordering};
|
||||
|
@ -247,20 +247,20 @@ impl Device {
|
|||
}
|
||||
|
||||
/// Returns the device pixel ratio.
|
||||
pub fn device_pixel_ratio(&self) -> TypedScale<f32, CSSPixel, DevicePixel> {
|
||||
pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
|
||||
let pc = match self.pres_context() {
|
||||
Some(pc) => pc,
|
||||
None => return TypedScale::new(1.),
|
||||
None => return Scale::new(1.),
|
||||
};
|
||||
|
||||
let override_dppx = pc.mOverrideDPPX;
|
||||
if override_dppx > 0.0 {
|
||||
return TypedScale::new(override_dppx);
|
||||
return Scale::new(override_dppx);
|
||||
}
|
||||
|
||||
let au_per_dpx = pc.mCurAppUnitsPerDevPixel as f32;
|
||||
let au_per_px = AU_PER_PX as f32;
|
||||
TypedScale::new(au_per_px / au_per_dpx)
|
||||
Scale::new(au_per_px / au_per_dpx)
|
||||
}
|
||||
|
||||
/// Returns whether document colors are enabled.
|
||||
|
|
|
@ -303,6 +303,11 @@ impl_threadsafe_refcount!(
|
|||
bindings::Gecko_AddRefURLExtraDataArbitraryThread,
|
||||
bindings::Gecko_ReleaseURLExtraDataArbitraryThread
|
||||
);
|
||||
impl_threadsafe_refcount!(
|
||||
structs::nsIReferrerInfo,
|
||||
bindings::Gecko_AddRefnsIReferrerInfoArbitraryThread,
|
||||
bindings::Gecko_ReleasensIReferrerInfoArbitraryThread
|
||||
);
|
||||
impl_threadsafe_refcount!(
|
||||
structs::nsIURI,
|
||||
bindings::Gecko_AddRefnsIURIArbitraryThread,
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
//! Geometry in flow-relative space.
|
||||
|
||||
use crate::properties::style_structs;
|
||||
use euclid::default::{Point2D, Rect, SideOffsets2D, Size2D};
|
||||
use euclid::num::Zero;
|
||||
use euclid::{Point2D, Rect, SideOffsets2D, Size2D};
|
||||
use std::cmp::{max, min};
|
||||
use std::fmt::{self, Debug, Error, Formatter};
|
||||
use std::ops::{Add, Sub};
|
||||
|
|
|
@ -240,16 +240,31 @@ trait PrivateMatchMethods: TElement {
|
|||
let new_box_style = new_style.get_box();
|
||||
let new_style_specifies_animations = new_box_style.specifies_animations();
|
||||
|
||||
let old_style = match old_style {
|
||||
Some(old) => old,
|
||||
None => return new_style_specifies_animations,
|
||||
};
|
||||
|
||||
let has_animations = self.has_css_animations();
|
||||
if !new_style_specifies_animations && !has_animations {
|
||||
return false;
|
||||
}
|
||||
|
||||
let old_style = match old_style {
|
||||
Some(old) => old,
|
||||
// If we have no old style but have animations, we may be a
|
||||
// pseudo-element which was re-created without style changes.
|
||||
//
|
||||
// This can happen when we reframe the pseudo-element without
|
||||
// restyling it (due to content insertion on a flex container or
|
||||
// such, for example). See bug 1564366.
|
||||
//
|
||||
// FIXME(emilio): The really right fix for this is keeping the
|
||||
// pseudo-element itself around on reframes, but that's a bit
|
||||
// harder. If we do that we can probably remove quite a lot of the
|
||||
// EffectSet complexity though, since right now it's stored on the
|
||||
// parent element for pseudo-elements given we need to keep it
|
||||
// around...
|
||||
None => {
|
||||
return new_style_specifies_animations || new_style.is_pseudo_style();
|
||||
},
|
||||
};
|
||||
|
||||
let old_box_style = old_style.get_box();
|
||||
|
||||
let keyframes_could_have_changed = context
|
||||
|
|
|
@ -153,7 +153,7 @@ where
|
|||
// longhands are only allowed if they have our
|
||||
// restriction flag set.
|
||||
if let PropertyDeclarationId::Longhand(id) = declaration.id() {
|
||||
if !id.flags().contains(restriction) {
|
||||
if !id.flags().contains(restriction) && cascade_level.origin() != Origin::UserAgent {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -175,6 +175,7 @@ class Longhand(object):
|
|||
predefined_type=None, servo_pref=None, gecko_pref=None,
|
||||
enabled_in="content", need_index=False,
|
||||
gecko_ffi_name=None,
|
||||
has_effect_on_gecko_scrollbars=None,
|
||||
allowed_in_keyframe_block=True, cast_type='u8',
|
||||
logical=False, logical_group=None, alias=None, extra_prefixes=None, boxed=False,
|
||||
flags=None, allowed_in_page_rule=False, allow_quirks="No",
|
||||
|
@ -192,6 +193,14 @@ class Longhand(object):
|
|||
self.style_struct = style_struct
|
||||
self.servo_pref = servo_pref
|
||||
self.gecko_pref = gecko_pref
|
||||
self.has_effect_on_gecko_scrollbars = has_effect_on_gecko_scrollbars
|
||||
assert (
|
||||
has_effect_on_gecko_scrollbars in [None, False, True] and
|
||||
not style_struct.inherited or
|
||||
(gecko_pref is None) == (has_effect_on_gecko_scrollbars is None)), (
|
||||
"Property " + name + ": has_effect_on_gecko_scrollbars must be " +
|
||||
"specified, and must have a value of True or False, iff a " +
|
||||
"property is inherited and is behind a Gecko pref")
|
||||
# For enabled_in, the setup is as follows:
|
||||
# It needs to be one of the four values: ["", "ua", "chrome", "content"]
|
||||
# * "chrome" implies "ua", and implies that they're explicitly
|
||||
|
@ -208,6 +217,7 @@ class Longhand(object):
|
|||
self.logical_group = logical_group
|
||||
if self.logical:
|
||||
assert logical_group, "Property " + name + " must have a logical group"
|
||||
|
||||
self.alias = parse_property_aliases(alias)
|
||||
self.extra_prefixes = parse_property_aliases(extra_prefixes)
|
||||
self.boxed = arg_to_bool(boxed)
|
||||
|
@ -532,8 +542,10 @@ class PropertiesData(object):
|
|||
self.current_style_struct = None
|
||||
self.longhands = []
|
||||
self.longhands_by_name = {}
|
||||
self.longhands_by_logical_group = {}
|
||||
self.longhand_aliases = []
|
||||
self.shorthands = []
|
||||
self.shorthands_by_name = {}
|
||||
self.shorthand_aliases = []
|
||||
|
||||
def new_style_struct(self, *args, **kwargs):
|
||||
|
@ -563,6 +575,8 @@ class PropertiesData(object):
|
|||
self.current_style_struct.longhands.append(longhand)
|
||||
self.longhands.append(longhand)
|
||||
self.longhands_by_name[name] = longhand
|
||||
if longhand.logical_group:
|
||||
self.longhands_by_logical_group.setdefault(longhand.logical_group, []).append(longhand)
|
||||
|
||||
return longhand
|
||||
|
||||
|
@ -577,6 +591,7 @@ class PropertiesData(object):
|
|||
shorthand.alias = list(map(lambda xp: Alias(xp[0], shorthand, xp[1]), shorthand.alias))
|
||||
self.shorthand_aliases += shorthand.alias
|
||||
self.shorthands.append(shorthand)
|
||||
self.shorthands_by_name[name] = shorthand
|
||||
return shorthand
|
||||
|
||||
def shorthands_except_all(self):
|
||||
|
@ -584,3 +599,172 @@ class PropertiesData(object):
|
|||
|
||||
def all_aliases(self):
|
||||
return self.longhand_aliases + self.shorthand_aliases
|
||||
|
||||
|
||||
def _add_logical_props(data, props):
|
||||
groups = set()
|
||||
for prop in props:
|
||||
if prop not in data.longhands_by_name:
|
||||
assert data.product == "servo"
|
||||
continue
|
||||
prop = data.longhands_by_name[prop]
|
||||
if prop.logical_group:
|
||||
groups.add(prop.logical_group)
|
||||
for group in groups:
|
||||
for prop in data.longhands_by_logical_group[group]:
|
||||
props.add(prop.name)
|
||||
|
||||
|
||||
# These are probably Gecko bugs and should be supported per spec.
|
||||
def _remove_common_first_line_and_first_letter_properties(props, product):
|
||||
if product == "gecko":
|
||||
props.remove("-moz-tab-size")
|
||||
props.remove("hyphens")
|
||||
props.remove("line-break")
|
||||
props.remove("text-align-last")
|
||||
props.remove("text-emphasis-position")
|
||||
props.remove("text-emphasis-style")
|
||||
props.remove("text-emphasis-color")
|
||||
props.remove("text-decoration-skip-ink")
|
||||
props.remove("text-decoration-thickness")
|
||||
props.remove("text-underline-offset")
|
||||
|
||||
props.remove("overflow-wrap")
|
||||
props.remove("text-align")
|
||||
props.remove("text-justify")
|
||||
props.remove("white-space")
|
||||
props.remove("word-break")
|
||||
props.remove("text-indent")
|
||||
|
||||
|
||||
class PropertyRestrictions:
|
||||
@staticmethod
|
||||
def logical_group(data, group):
|
||||
return map(lambda p: p.name, data.longhands_by_logical_group[group])
|
||||
|
||||
@staticmethod
|
||||
def shorthand(data, shorthand):
|
||||
return map(lambda p: p.name, data.shorthands_by_name[shorthand].sub_properties)
|
||||
|
||||
@staticmethod
|
||||
def spec(data, spec_path):
|
||||
return map(lambda p: p.name, filter(lambda p: spec_path in p.spec, data.longhands))
|
||||
|
||||
# https://drafts.csswg.org/css-pseudo/#first-letter-styling
|
||||
@staticmethod
|
||||
def first_letter(data):
|
||||
props = set([
|
||||
"color",
|
||||
"float",
|
||||
"initial-letter",
|
||||
|
||||
# Kinda like css-fonts?
|
||||
"-moz-osx-font-smoothing",
|
||||
|
||||
# Kinda like css-text?
|
||||
"-webkit-text-stroke-width",
|
||||
"-webkit-text-fill-color",
|
||||
"-webkit-text-stroke-color",
|
||||
"vertical-align",
|
||||
"line-height",
|
||||
|
||||
# Kinda like css-backgrounds?
|
||||
"background-blend-mode",
|
||||
] + PropertyRestrictions.shorthand(data, "padding")
|
||||
+ PropertyRestrictions.shorthand(data, "margin")
|
||||
+ PropertyRestrictions.spec(data, "css-fonts")
|
||||
+ PropertyRestrictions.spec(data, "css-backgrounds")
|
||||
+ PropertyRestrictions.spec(data, "css-text")
|
||||
+ PropertyRestrictions.spec(data, "css-shapes")
|
||||
+ PropertyRestrictions.spec(data, "css-text-decor"))
|
||||
|
||||
_add_logical_props(data, props)
|
||||
|
||||
_remove_common_first_line_and_first_letter_properties(props, data.product)
|
||||
return props
|
||||
|
||||
# https://drafts.csswg.org/css-pseudo/#first-line-styling
|
||||
@staticmethod
|
||||
def first_line(data):
|
||||
props = set([
|
||||
# Per spec.
|
||||
"color",
|
||||
|
||||
# Kinda like css-fonts?
|
||||
"-moz-osx-font-smoothing",
|
||||
|
||||
# Kinda like css-text?
|
||||
"-webkit-text-stroke-width",
|
||||
"-webkit-text-fill-color",
|
||||
"-webkit-text-stroke-color",
|
||||
"vertical-align",
|
||||
"line-height",
|
||||
|
||||
# Kinda like css-backgrounds?
|
||||
"background-blend-mode",
|
||||
] + PropertyRestrictions.spec(data, "css-fonts")
|
||||
+ PropertyRestrictions.spec(data, "css-backgrounds")
|
||||
+ PropertyRestrictions.spec(data, "css-text")
|
||||
+ PropertyRestrictions.spec(data, "css-text-decor"))
|
||||
|
||||
# These are probably Gecko bugs and should be supported per spec.
|
||||
for prop in PropertyRestrictions.shorthand(data, "border"):
|
||||
props.remove(prop)
|
||||
for prop in PropertyRestrictions.shorthand(data, "border-radius"):
|
||||
props.remove(prop)
|
||||
props.remove("box-shadow")
|
||||
|
||||
_remove_common_first_line_and_first_letter_properties(props, data.product)
|
||||
return props
|
||||
|
||||
# https://drafts.csswg.org/css-pseudo/#placeholder
|
||||
#
|
||||
# The spec says that placeholder and first-line have the same restrictions,
|
||||
# but that's not true in Gecko and we also allow a handful other properties
|
||||
# for ::placeholder.
|
||||
@staticmethod
|
||||
def placeholder(data):
|
||||
props = PropertyRestrictions.first_line(data)
|
||||
props.add("opacity")
|
||||
props.add("white-space")
|
||||
props.add("text-overflow")
|
||||
props.add("text-align")
|
||||
props.add("text-justify")
|
||||
return props
|
||||
|
||||
# https://drafts.csswg.org/css-pseudo/#marker-pseudo
|
||||
@staticmethod
|
||||
def marker(data):
|
||||
return set([
|
||||
"color",
|
||||
"text-combine-upright",
|
||||
"unicode-bidi",
|
||||
"direction",
|
||||
"content",
|
||||
"-moz-osx-font-smoothing",
|
||||
] + PropertyRestrictions.spec(data, "css-fonts"))
|
||||
|
||||
# https://www.w3.org/TR/webvtt1/#the-cue-pseudo-element
|
||||
@staticmethod
|
||||
def cue(data):
|
||||
return set([
|
||||
"color",
|
||||
"opacity",
|
||||
"visibility",
|
||||
"text-shadow",
|
||||
"white-space",
|
||||
"text-combine-upright",
|
||||
"ruby-position",
|
||||
|
||||
# XXX Should these really apply to cue?
|
||||
"font-synthesis",
|
||||
"-moz-osx-font-smoothing",
|
||||
|
||||
# FIXME(emilio): background-blend-mode should be part of the
|
||||
# background shorthand, and get reset, per
|
||||
# https://drafts.fxtf.org/compositing/#background-blend-mode
|
||||
"background-blend-mode",
|
||||
] + PropertyRestrictions.shorthand(data, "text-decoration")
|
||||
+ PropertyRestrictions.shorthand(data, "background")
|
||||
+ PropertyRestrictions.shorthand(data, "outline")
|
||||
+ PropertyRestrictions.shorthand(data, "font"))
|
||||
|
|
|
@ -117,9 +117,14 @@ impl ComputedValues {
|
|||
).to_outer(None)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_pseudo_style(&self) -> bool {
|
||||
self.0.mPseudoType != PseudoStyleType::NotPseudo
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pseudo(&self) -> Option<PseudoElement> {
|
||||
if self.0.mPseudoType == PseudoStyleType::NotPseudo {
|
||||
if !self.is_pseudo_style() {
|
||||
return None;
|
||||
}
|
||||
PseudoElement::from_pseudo_type(self.0.mPseudoType)
|
||||
|
|
|
@ -15,8 +15,7 @@ ${helpers.predefined_type(
|
|||
animation_value_type="AnimatedColor",
|
||||
ignored_when_colors_disabled=True,
|
||||
allow_quirks="Yes",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER \
|
||||
CAN_ANIMATE_ON_COMPOSITOR",
|
||||
flags="CAN_ANIMATE_ON_COMPOSITOR",
|
||||
)}
|
||||
|
||||
${helpers.predefined_type(
|
||||
|
@ -28,7 +27,6 @@ ${helpers.predefined_type(
|
|||
vector="True",
|
||||
animation_value_type="discrete",
|
||||
ignored_when_colors_disabled="True",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
)}
|
||||
|
||||
% for (axis, direction, initial) in [("x", "Horizontal", "left"), ("y", "Vertical", "top")]:
|
||||
|
@ -41,7 +39,6 @@ ${helpers.predefined_type(
|
|||
animation_value_type="ComputedValue",
|
||||
vector=True,
|
||||
vector_animation_type="repeatable_list",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
)}
|
||||
% endfor
|
||||
|
||||
|
@ -53,7 +50,6 @@ ${helpers.predefined_type(
|
|||
animation_value_type="discrete",
|
||||
vector=True,
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#the-background-repeat",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
)}
|
||||
|
||||
${helpers.single_keyword(
|
||||
|
@ -63,7 +59,6 @@ ${helpers.single_keyword(
|
|||
gecko_enum_prefix="StyleImageLayerAttachment",
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#the-background-attachment",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
)}
|
||||
|
||||
${helpers.single_keyword(
|
||||
|
@ -75,7 +70,6 @@ ${helpers.single_keyword(
|
|||
gecko_inexhaustive=True,
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#the-background-clip",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
)}
|
||||
|
||||
${helpers.single_keyword(
|
||||
|
@ -86,7 +80,6 @@ ${helpers.single_keyword(
|
|||
gecko_inexhaustive=True,
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#the-background-origin",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER"
|
||||
)}
|
||||
|
||||
${helpers.predefined_type(
|
||||
|
@ -98,7 +91,6 @@ ${helpers.predefined_type(
|
|||
vector=True,
|
||||
vector_animation_type="repeatable_list",
|
||||
animation_value_type="BackgroundSizeList",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
extra_prefixes="webkit")}
|
||||
|
||||
// https://drafts.fxtf.org/compositing/#background-blend-mode
|
||||
|
@ -110,5 +102,4 @@ ${helpers.single_keyword(
|
|||
gecko_constant_prefix="NS_STYLE_BLEND",
|
||||
vector=True, products="gecko", animation_value_type="discrete",
|
||||
spec="https://drafts.fxtf.org/compositing/#background-blend-mode",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
)}
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
logical=is_logical,
|
||||
logical_group="border-color",
|
||||
allow_quirks="No" if is_logical else "Yes",
|
||||
flags="APPLIES_TO_FIRST_LETTER",
|
||||
ignored_when_colors_disabled=True,
|
||||
)}
|
||||
|
||||
|
@ -38,7 +37,6 @@
|
|||
"specified::BorderStyle::None",
|
||||
alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-style"),
|
||||
spec=maybe_logical_spec(side, "style"),
|
||||
flags="APPLIES_TO_FIRST_LETTER",
|
||||
animation_value_type="discrete" if not is_logical else "none",
|
||||
logical=is_logical,
|
||||
logical_group="border-style",
|
||||
|
@ -55,7 +53,7 @@
|
|||
animation_value_type="NonNegativeLength",
|
||||
logical=is_logical,
|
||||
logical_group="border-width",
|
||||
flags="APPLIES_TO_FIRST_LETTER GETCS_NEEDS_LAYOUT_FLUSH",
|
||||
flags="GETCS_NEEDS_LAYOUT_FLUSH",
|
||||
allow_quirks="No" if is_logical else "Yes",
|
||||
servo_restyle_damage="reflow rebuild_and_reflow_inline"
|
||||
)}
|
||||
|
@ -78,7 +76,6 @@
|
|||
extra_prefixes=prefixes,
|
||||
spec=maybe_logical_spec(corner, "radius"),
|
||||
boxed=True,
|
||||
flags="APPLIES_TO_FIRST_LETTER",
|
||||
animation_value_type="BorderCornerRadius",
|
||||
logical_group="border-radius",
|
||||
logical=is_logical,
|
||||
|
@ -112,7 +109,6 @@ ${helpers.predefined_type(
|
|||
spec="https://drafts.csswg.org/css-backgrounds/#the-background-image",
|
||||
vector=False,
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_FIRST_LETTER",
|
||||
boxed=product == "servo",
|
||||
ignored_when_colors_disabled=True
|
||||
)}
|
||||
|
@ -124,7 +120,6 @@ ${helpers.predefined_type(
|
|||
initial_specified_value="generics::rect::Rect::all(specified::NonNegativeLengthOrNumber::zero())",
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#border-image-outset",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_FIRST_LETTER",
|
||||
boxed=True,
|
||||
)}
|
||||
|
||||
|
@ -135,7 +130,6 @@ ${helpers.predefined_type(
|
|||
initial_specified_value="specified::BorderImageRepeat::stretch()",
|
||||
animation_value_type="discrete",
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#the-border-image-repeat",
|
||||
flags="APPLIES_TO_FIRST_LETTER",
|
||||
)}
|
||||
|
||||
${helpers.predefined_type(
|
||||
|
@ -145,7 +139,6 @@ ${helpers.predefined_type(
|
|||
initial_specified_value="specified::BorderImageWidth::all(specified::BorderImageSideWidth::one())",
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#border-image-width",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_FIRST_LETTER",
|
||||
boxed=True,
|
||||
)}
|
||||
|
||||
|
@ -156,6 +149,5 @@ ${helpers.predefined_type(
|
|||
initial_specified_value="specified::BorderImageSlice::hundred_percent()",
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#border-image-slice",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_FIRST_LETTER",
|
||||
boxed=True,
|
||||
)}
|
||||
|
|
|
@ -9,15 +9,12 @@
|
|||
inherited=False,
|
||||
gecko_name="Display") %>
|
||||
|
||||
// We allow "display" to apply to placeholders because we need to make the
|
||||
// placeholder pseudo-element an inline-block in the UA stylesheet in Gecko.
|
||||
${helpers.predefined_type(
|
||||
"display",
|
||||
"Display",
|
||||
"computed::Display::inline()",
|
||||
initial_specified_value="specified::Display::inline()",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-display/#propdef-display",
|
||||
servo_restyle_damage="rebuild_and_reflow",
|
||||
needs_context=product == "gecko"
|
||||
|
@ -62,7 +59,6 @@ ${helpers.predefined_type(
|
|||
spec="https://drafts.csswg.org/css-box/#propdef-float",
|
||||
animation_value_type="discrete",
|
||||
needs_context=False,
|
||||
flags="APPLIES_TO_FIRST_LETTER",
|
||||
servo_restyle_damage="rebuild_and_reflow",
|
||||
gecko_ffi_name="mFloat",
|
||||
)}
|
||||
|
@ -83,7 +79,6 @@ ${helpers.predefined_type(
|
|||
"VerticalAlign",
|
||||
"computed::VerticalAlign::baseline()",
|
||||
animation_value_type="ComputedValue",
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://www.w3.org/TR/CSS2/visudet.html#propdef-vertical-align",
|
||||
servo_restyle_damage = "reflow",
|
||||
)}
|
||||
|
@ -103,7 +98,6 @@ ${helpers.single_keyword("-servo-overflow-clip-box", "padding-box content-box",
|
|||
products="gecko",
|
||||
enabled_in="ua",
|
||||
needs_context=False,
|
||||
flags="APPLIES_TO_PLACEHOLDER",
|
||||
gecko_pref="layout.css.overflow-clip-box.enabled",
|
||||
animation_value_type="discrete",
|
||||
spec="Internal, may be standardized in the future: \
|
||||
|
@ -111,9 +105,6 @@ ${helpers.single_keyword("-servo-overflow-clip-box", "padding-box content-box",
|
|||
)}
|
||||
% endfor
|
||||
|
||||
// FIXME(pcwalton, #2742): Implement scrolling for `scroll` and `auto`.
|
||||
//
|
||||
// We allow it to apply to placeholders for UA sheets, which set it !important.
|
||||
% for (axis, logical) in ALL_AXES:
|
||||
<% full_name = "overflow-{}".format(axis) %>
|
||||
${helpers.predefined_type(
|
||||
|
@ -123,7 +114,6 @@ ${helpers.single_keyword("-servo-overflow-clip-box", "padding-box content-box",
|
|||
logical_group="overflow",
|
||||
logical=logical,
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-overflow-3/#propdef-{}".format(full_name),
|
||||
needs_context=False,
|
||||
servo_restyle_damage = "reflow",
|
||||
|
@ -477,10 +467,6 @@ ${helpers.predefined_type(
|
|||
|
||||
// CSS Basic User Interface Module Level 3
|
||||
// http://dev.w3.org/csswg/css-ui
|
||||
//
|
||||
// This is APPLIES_TO_PLACEHOLDER so we can override, in the UA sheet, the
|
||||
// 'resize' property we'd inherit from textarea otherwise. Basically, just
|
||||
// makes the UA rules easier to write.
|
||||
${helpers.predefined_type(
|
||||
"resize",
|
||||
"Resize",
|
||||
|
@ -489,7 +475,6 @@ ${helpers.predefined_type(
|
|||
animation_value_type="discrete",
|
||||
needs_context=False,
|
||||
gecko_ffi_name="mResize",
|
||||
flags="APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-ui/#propdef-resize",
|
||||
)}
|
||||
|
||||
|
@ -616,11 +601,12 @@ ${helpers.predefined_type(
|
|||
spec="https://drafts.csswg.org/css-will-change/#will-change",
|
||||
)}
|
||||
|
||||
// The spec issue for the parse_method: https://github.com/w3c/csswg-drafts/issues/4102.
|
||||
${helpers.predefined_type(
|
||||
"shape-image-threshold", "Opacity", "0.0",
|
||||
parse_method="parse_number",
|
||||
products="gecko",
|
||||
animation_value_type="ComputedValue",
|
||||
flags="APPLIES_TO_FIRST_LETTER",
|
||||
spec="https://drafts.csswg.org/css-shapes/#shape-image-threshold-property",
|
||||
)}
|
||||
|
||||
|
@ -630,7 +616,6 @@ ${helpers.predefined_type(
|
|||
"computed::NonNegativeLengthPercentage::zero()",
|
||||
products="gecko",
|
||||
animation_value_type="NonNegativeLengthPercentage",
|
||||
flags="APPLIES_TO_FIRST_LETTER",
|
||||
spec="https://drafts.csswg.org/css-shapes/#shape-margin-property",
|
||||
)}
|
||||
|
||||
|
@ -640,7 +625,6 @@ ${helpers.predefined_type(
|
|||
"generics::basic_shape::ShapeSource::None",
|
||||
products="gecko",
|
||||
animation_value_type="basic_shape::FloatAreaShape",
|
||||
flags="APPLIES_TO_FIRST_LETTER",
|
||||
spec="https://drafts.csswg.org/css-shapes/#shape-outside-property",
|
||||
)}
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ ${helpers.predefined_type(
|
|||
initial_specified_value="specified::Content::normal()",
|
||||
animation_value_type="discrete",
|
||||
spec="https://drafts.csswg.org/css-content/#propdef-content",
|
||||
flags="APPLIES_TO_MARKER",
|
||||
servo_restyle_damage="rebuild_and_reflow",
|
||||
)}
|
||||
|
||||
|
|
|
@ -12,9 +12,8 @@ ${helpers.predefined_type(
|
|||
"Opacity",
|
||||
"1.0",
|
||||
animation_value_type="ComputedValue",
|
||||
flags="APPLIES_TO_CUE CREATES_STACKING_CONTEXT APPLIES_TO_PLACEHOLDER \
|
||||
CAN_ANIMATE_ON_COMPOSITOR",
|
||||
spec="https://drafts.csswg.org/css-color/#opacity",
|
||||
flags="CREATES_STACKING_CONTEXT CAN_ANIMATE_ON_COMPOSITOR",
|
||||
spec="https://drafts.csswg.org/css-color/#transparency",
|
||||
servo_restyle_damage = "reflow_out_of_flow",
|
||||
)}
|
||||
|
||||
|
@ -28,7 +27,6 @@ ${helpers.predefined_type(
|
|||
vector_animation_type="with_zero",
|
||||
extra_prefixes="webkit",
|
||||
ignored_when_colors_disabled=True,
|
||||
flags="APPLIES_TO_FIRST_LETTER",
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#box-shadow",
|
||||
)}
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ ${helpers.predefined_type(
|
|||
"FontFamily",
|
||||
initial_value="computed::FontFamily::serif()",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-family",
|
||||
servo_restyle_damage="rebuild_and_reflow",
|
||||
)}
|
||||
|
@ -23,7 +22,6 @@ ${helpers.predefined_type(
|
|||
initial_value="computed::FontStyle::normal()",
|
||||
initial_specified_value="specified::FontStyle::normal()",
|
||||
animation_value_type="FontStyle",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-style",
|
||||
servo_restyle_damage="rebuild_and_reflow",
|
||||
)}
|
||||
|
@ -42,7 +40,6 @@ ${helpers.single_keyword_system(
|
|||
gecko_ffi_name="mFont.variantCaps",
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-caps",
|
||||
custom_consts=font_variant_caps_custom_consts,
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
animation_value_type="discrete",
|
||||
servo_restyle_damage="rebuild_and_reflow",
|
||||
)}
|
||||
|
@ -53,7 +50,6 @@ ${helpers.predefined_type(
|
|||
initial_value="computed::FontWeight::normal()",
|
||||
initial_specified_value="specified::FontWeight::normal()",
|
||||
animation_value_type="Number",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-weight",
|
||||
servo_restyle_damage="rebuild_and_reflow",
|
||||
)}
|
||||
|
@ -65,7 +61,6 @@ ${helpers.predefined_type(
|
|||
initial_specified_value="specified::FontSize::medium()",
|
||||
animation_value_type="NonNegativeLength",
|
||||
allow_quirks="Yes",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-size",
|
||||
servo_restyle_damage="rebuild_and_reflow",
|
||||
)}
|
||||
|
@ -77,7 +72,6 @@ ${helpers.predefined_type(
|
|||
initial_value="computed::FontSizeAdjust::none()",
|
||||
initial_specified_value="specified::FontSizeAdjust::none()",
|
||||
animation_value_type="ComputedValue",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust",
|
||||
)}
|
||||
|
||||
|
@ -87,7 +81,6 @@ ${helpers.predefined_type(
|
|||
products="gecko",
|
||||
initial_value="specified::FontSynthesis::get_initial_value()",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-synthesis",
|
||||
)}
|
||||
|
||||
|
@ -97,7 +90,6 @@ ${helpers.predefined_type(
|
|||
initial_value="computed::FontStretch::hundred()",
|
||||
initial_specified_value="specified::FontStretch::normal()",
|
||||
animation_value_type="Percentage",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-stretch",
|
||||
servo_restyle_damage="rebuild_and_reflow",
|
||||
)}
|
||||
|
@ -109,7 +101,6 @@ ${helpers.single_keyword_system(
|
|||
gecko_ffi_name="mFont.kerning",
|
||||
gecko_constant_prefix="NS_FONT_KERNING",
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-kerning",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
animation_value_type="discrete",
|
||||
)}
|
||||
|
||||
|
@ -120,7 +111,6 @@ ${helpers.predefined_type(
|
|||
initial_value="computed::FontVariantAlternates::get_initial_value()",
|
||||
initial_specified_value="specified::FontVariantAlternates::get_initial_specified_value()",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-alternates",
|
||||
)}
|
||||
|
||||
|
@ -131,7 +121,6 @@ ${helpers.predefined_type(
|
|||
initial_value="computed::FontVariantEastAsian::empty()",
|
||||
initial_specified_value="specified::FontVariantEastAsian::empty()",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-east-asian",
|
||||
)}
|
||||
|
||||
|
@ -142,7 +131,6 @@ ${helpers.predefined_type(
|
|||
initial_value="computed::FontVariantLigatures::empty()",
|
||||
initial_specified_value="specified::FontVariantLigatures::empty()",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-ligatures",
|
||||
)}
|
||||
|
||||
|
@ -153,7 +141,6 @@ ${helpers.predefined_type(
|
|||
initial_value="computed::FontVariantNumeric::empty()",
|
||||
initial_specified_value="specified::FontVariantNumeric::empty()",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-numeric",
|
||||
)}
|
||||
|
||||
|
@ -164,7 +151,6 @@ ${helpers.single_keyword_system(
|
|||
gecko_ffi_name="mFont.variantPosition",
|
||||
gecko_constant_prefix="NS_FONT_VARIANT_POSITION",
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-position",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
animation_value_type="discrete",
|
||||
)}
|
||||
|
||||
|
@ -176,27 +162,19 @@ ${helpers.predefined_type(
|
|||
initial_specified_value="specified::FontFeatureSettings::normal()",
|
||||
extra_prefixes="moz:layout.css.prefixes.font-features",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-feature-settings",
|
||||
)}
|
||||
|
||||
<%
|
||||
# This spec link is too long to fit elsewhere
|
||||
variation_spec = """\
|
||||
https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-the-font-variation-settings-property\
|
||||
"""
|
||||
%>
|
||||
|
||||
${helpers.predefined_type(
|
||||
"font-variation-settings",
|
||||
"FontVariationSettings",
|
||||
products="gecko",
|
||||
gecko_pref="layout.css.font-variations.enabled",
|
||||
has_effect_on_gecko_scrollbars=False,
|
||||
initial_value="computed::FontVariationSettings::normal()",
|
||||
initial_specified_value="specified::FontVariationSettings::normal()",
|
||||
animation_value_type="ComputedValue",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
spec="${variation_spec}",
|
||||
spec="https://drafts.csswg.org/css-fonts-4/#propdef-font-variation-settings"
|
||||
)}
|
||||
|
||||
${helpers.predefined_type(
|
||||
|
@ -207,7 +185,6 @@ ${helpers.predefined_type(
|
|||
initial_specified_value="specified::FontLanguageOverride::normal()",
|
||||
animation_value_type="discrete",
|
||||
extra_prefixes="moz:layout.css.prefixes.font-features",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
spec="https://drafts.csswg.org/css-fonts-3/#propdef-font-language-override",
|
||||
)}
|
||||
|
||||
|
@ -216,10 +193,10 @@ ${helpers.single_keyword_system(
|
|||
"auto none",
|
||||
products="gecko",
|
||||
gecko_pref="layout.css.font-variations.enabled",
|
||||
has_effect_on_gecko_scrollbars=False,
|
||||
gecko_ffi_name="mFont.opticalSizing",
|
||||
gecko_constant_prefix="NS_FONT_OPTICAL_SIZING",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
spec="https://www.w3.org/TR/css-fonts-4/#font-optical-sizing-def",
|
||||
)}
|
||||
|
||||
|
@ -513,9 +490,9 @@ ${helpers.single_keyword(
|
|||
gecko_constant_prefix="NS_FONT_SMOOTHING",
|
||||
gecko_ffi_name="mFont.smoothing",
|
||||
gecko_pref="layout.css.osx-font-smoothing.enabled",
|
||||
has_effect_on_gecko_scrollbars=False,
|
||||
products="gecko",
|
||||
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/font-smooth)",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
animation_value_type="discrete",
|
||||
)}
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ ${helpers.single_keyword(
|
|||
gecko_ffi_name="mVisible",
|
||||
animation_value_type="ComputedValue",
|
||||
spec="https://drafts.csswg.org/css-box/#propdef-visibility",
|
||||
flags="APPLIES_TO_CUE",
|
||||
)}
|
||||
|
||||
// CSS Writing Modes Level 3
|
||||
|
@ -38,7 +37,6 @@ ${helpers.single_keyword(
|
|||
animation_value_type="none",
|
||||
spec="https://drafts.csswg.org/css-writing-modes/#propdef-direction",
|
||||
needs_conversion=True,
|
||||
flags="APPLIES_TO_MARKER",
|
||||
servo_restyle_damage="rebuild_and_reflow",
|
||||
)}
|
||||
|
||||
|
|
|
@ -10,6 +10,15 @@
|
|||
|
||||
// Section 10 - Text
|
||||
|
||||
${helpers.single_keyword(
|
||||
"dominant-baseline",
|
||||
"""auto ideographic alphabetic hanging mathematical central middle
|
||||
text-after-edge text-before-edge""",
|
||||
products="gecko",
|
||||
animation_value_type="discrete",
|
||||
spec="https://www.w3.org/TR/css-inline-3/#propdef-dominant-baseline",
|
||||
)}
|
||||
|
||||
${helpers.single_keyword(
|
||||
"text-anchor",
|
||||
"start middle end",
|
||||
|
@ -52,7 +61,7 @@ ${helpers.predefined_type(
|
|||
"Default::default()",
|
||||
products="gecko",
|
||||
animation_value_type="ComputedValue",
|
||||
spec="https://www.w3.org/TR/SVG11/painting.html#FillOpacityProperty",
|
||||
spec="https://svgwg.org/svg2-draft/painting.html#FillOpacity",
|
||||
)}
|
||||
|
||||
${helpers.predefined_type(
|
||||
|
@ -123,7 +132,7 @@ ${helpers.predefined_type(
|
|||
"Default::default()",
|
||||
products="gecko",
|
||||
animation_value_type="ComputedValue",
|
||||
spec="https://www.w3.org/TR/SVG11/painting.html#StrokeOpacityProperty",
|
||||
spec="https://svgwg.org/svg2-draft/painting.html#StrokeOpacity",
|
||||
)}
|
||||
|
||||
${helpers.predefined_type(
|
||||
|
|
|
@ -11,7 +11,6 @@ ${helpers.predefined_type(
|
|||
"ColorPropertyValue",
|
||||
"::cssparser::RGBA::new(0, 0, 0, 255)",
|
||||
animation_value_type="AnimatedRGBA",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER",
|
||||
ignored_when_colors_disabled="True",
|
||||
spec="https://drafts.csswg.org/css-color/#color",
|
||||
)}
|
||||
|
@ -21,8 +20,7 @@ ${helpers.predefined_type(
|
|||
"LineHeight",
|
||||
"computed::LineHeight::normal()",
|
||||
animation_value_type="LineHeight",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE \
|
||||
APPLIES_TO_PLACEHOLDER GETCS_NEEDS_LAYOUT_FLUSH",
|
||||
flags="GETCS_NEEDS_LAYOUT_FLUSH",
|
||||
spec="https://drafts.csswg.org/css2/visudet.html#propdef-line-height",
|
||||
servo_restyle_damage="reflow"
|
||||
)}
|
||||
|
@ -34,7 +32,6 @@ ${helpers.predefined_type(
|
|||
"TextTransform",
|
||||
"computed::TextTransform::none()",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-text/#propdef-text-transform",
|
||||
servo_restyle_damage="rebuild_and_reflow",
|
||||
)}
|
||||
|
@ -102,7 +99,7 @@ ${helpers.predefined_type(
|
|||
gecko_enum_prefix="StyleTextJustify"
|
||||
animation_value_type="discrete"
|
||||
gecko_pref="layout.css.text-justify.enabled"
|
||||
flags="APPLIES_TO_PLACEHOLDER",
|
||||
has_effect_on_gecko_scrollbars="False"
|
||||
spec="https://drafts.csswg.org/css-text/#propdef-text-justify"
|
||||
servo_restyle_damage="rebuild_and_reflow"
|
||||
>
|
||||
|
@ -148,7 +145,6 @@ ${helpers.predefined_type(
|
|||
"TextAlign",
|
||||
"computed::TextAlign::Start",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-text/#propdef-text-align",
|
||||
servo_restyle_damage = "reflow",
|
||||
)}
|
||||
|
@ -158,7 +154,6 @@ ${helpers.predefined_type(
|
|||
"LetterSpacing",
|
||||
"computed::LetterSpacing::normal()",
|
||||
animation_value_type="ComputedValue",
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-text/#propdef-letter-spacing",
|
||||
servo_restyle_damage="rebuild_and_reflow",
|
||||
)}
|
||||
|
@ -168,7 +163,6 @@ ${helpers.predefined_type(
|
|||
"WordSpacing",
|
||||
"computed::WordSpacing::zero()",
|
||||
animation_value_type="ComputedValue",
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-text/#propdef-word-spacing",
|
||||
servo_restyle_damage="rebuild_and_reflow",
|
||||
)}
|
||||
|
@ -180,8 +174,6 @@ ${helpers.predefined_type(
|
|||
gecko_enum_prefix="StyleWhiteSpace"
|
||||
needs_conversion="True"
|
||||
animation_value_type="discrete"
|
||||
// Only allowed for UA sheets, which set it !important.
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_PLACEHOLDER"
|
||||
spec="https://drafts.csswg.org/css-text/#propdef-white-space"
|
||||
servo_restyle_damage="rebuild_and_reflow"
|
||||
>
|
||||
|
@ -229,7 +221,6 @@ ${helpers.predefined_type(
|
|||
animation_value_type="AnimatedTextShadowList",
|
||||
ignored_when_colors_disabled=True,
|
||||
simple_vector_bindings=True,
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-text-decor-3/#text-shadow-property",
|
||||
)}
|
||||
|
||||
|
@ -293,7 +284,6 @@ ${helpers.predefined_type(
|
|||
products="gecko",
|
||||
animation_value_type="AnimatedColor",
|
||||
ignored_when_colors_disabled=True,
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://compat.spec.whatwg.org/#the-webkit-text-fill-color",
|
||||
)}
|
||||
|
||||
|
@ -305,7 +295,6 @@ ${helpers.predefined_type(
|
|||
products="gecko",
|
||||
animation_value_type="AnimatedColor",
|
||||
ignored_when_colors_disabled=True,
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-color",
|
||||
)}
|
||||
|
||||
|
@ -316,7 +305,6 @@ ${helpers.predefined_type(
|
|||
initial_specified_value="specified::BorderSideWidth::zero()",
|
||||
computed_type="crate::values::computed::NonNegativeLength",
|
||||
products="gecko",
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-width",
|
||||
animation_value_type="discrete",
|
||||
)}
|
||||
|
@ -337,7 +325,6 @@ ${helpers.single_keyword(
|
|||
products="gecko",
|
||||
animation_value_type="discrete",
|
||||
spec="https://drafts.csswg.org/css-ruby/#ruby-position-property",
|
||||
flags="APPLIES_TO_CUE",
|
||||
)}
|
||||
|
||||
// CSS Writing Modes Module Level 3
|
||||
|
@ -349,7 +336,6 @@ ${helpers.single_keyword(
|
|||
products="gecko",
|
||||
animation_value_type="discrete",
|
||||
spec="https://drafts.csswg.org/css-writing-modes-3/#text-combine-upright",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_MARKER",
|
||||
)}
|
||||
|
||||
// SVG 1.1: Section 11 - Painting: Filling, Stroking and Marker Symbols
|
||||
|
@ -382,6 +368,7 @@ ${helpers.predefined_type(
|
|||
products="gecko",
|
||||
animation_value_type="ComputedValue",
|
||||
gecko_pref="layout.css.text-underline-offset.enabled",
|
||||
has_effect_on_gecko_scrollbars=False,
|
||||
spec="https://drafts.csswg.org/css-text-decor-4/#underline-offset",
|
||||
)}
|
||||
|
||||
|
@ -394,5 +381,6 @@ ${helpers.predefined_type(
|
|||
needs_context=False,
|
||||
animation_value_type="discrete",
|
||||
gecko_pref="layout.css.text-decoration-skip-ink.enabled",
|
||||
has_effect_on_gecko_scrollbars=False,
|
||||
spec="https://drafts.csswg.org/css-text-decor-4/#text-decoration-skip-ink-property",
|
||||
)}
|
||||
|
|
|
@ -23,7 +23,6 @@ ${helpers.single_keyword(
|
|||
"auto none",
|
||||
animation_value_type="discrete",
|
||||
extra_gecko_values="visiblepainted visiblefill visiblestroke visible painted fill stroke all",
|
||||
flags="APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://www.w3.org/TR/SVG11/interact.html#PointerEventsProperty",
|
||||
)}
|
||||
|
||||
|
@ -74,6 +73,10 @@ ${helpers.predefined_type(
|
|||
"Default::default()",
|
||||
spec="https://drafts.csswg.org/css-scrollbars-1/#scrollbar-color",
|
||||
gecko_pref="layout.css.scrollbar-color.enabled",
|
||||
# Surprisingly, yes the computed value of scrollbar-color has no effect on
|
||||
# Gecko scrollbar elements, since the value only matters on the scrollable
|
||||
# element itself.
|
||||
has_effect_on_gecko_scrollbars=False,
|
||||
animation_value_type="ScrollbarColor",
|
||||
boxed=True,
|
||||
ignored_when_colors_disabled=True,
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
logical=side[1],
|
||||
logical_group="margin",
|
||||
spec=spec,
|
||||
flags="APPLIES_TO_FIRST_LETTER GETCS_NEEDS_LAYOUT_FLUSH",
|
||||
flags="GETCS_NEEDS_LAYOUT_FLUSH",
|
||||
allowed_in_page_rule=True,
|
||||
servo_restyle_damage="reflow"
|
||||
)}
|
||||
|
@ -38,7 +38,6 @@
|
|||
logical=side[1],
|
||||
logical_group="scroll-margin",
|
||||
spec="https://drafts.csswg.org/css-scroll-snap-1/#propdef-scroll-margin-%s" % side[0],
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE",
|
||||
animation_value_type="ComputedValue",
|
||||
)}
|
||||
% endfor
|
||||
|
|
|
@ -18,7 +18,6 @@ ${helpers.predefined_type(
|
|||
animation_value_type="AnimatedColor",
|
||||
ignored_when_colors_disabled=True,
|
||||
spec="https://drafts.csswg.org/css-ui/#propdef-outline-color",
|
||||
flags="APPLIES_TO_CUE",
|
||||
)}
|
||||
|
||||
${helpers.predefined_type(
|
||||
|
@ -28,7 +27,6 @@ ${helpers.predefined_type(
|
|||
initial_specified_value="specified::OutlineStyle::none()",
|
||||
animation_value_type="discrete",
|
||||
spec="https://drafts.csswg.org/css-ui/#propdef-outline-style",
|
||||
flags="APPLIES_TO_CUE",
|
||||
)}
|
||||
|
||||
${helpers.predefined_type(
|
||||
|
@ -39,7 +37,6 @@ ${helpers.predefined_type(
|
|||
computed_type="crate::values::computed::NonNegativeLength",
|
||||
animation_value_type="NonNegativeLength",
|
||||
spec="https://drafts.csswg.org/css-ui/#propdef-outline-width",
|
||||
flags="APPLIES_TO_CUE",
|
||||
)}
|
||||
|
||||
// The -moz-outline-radius-* properties are non-standard and not on a standards track.
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
<% from data import ALL_SIDES, maybe_moz_logical_alias %>
|
||||
<% data.new_style_struct("Padding", inherited=False) %>
|
||||
|
||||
// APPLIES_TO_PLACEHOLDER so we can set it in UA stylesheets. But we use a
|
||||
// !important value there, so pages can't set it.
|
||||
% for side in ALL_SIDES:
|
||||
<%
|
||||
spec = "https://drafts.csswg.org/css-box/#propdef-padding-%s" % side[0]
|
||||
|
@ -23,7 +21,7 @@
|
|||
logical=side[1],
|
||||
logical_group="padding",
|
||||
spec=spec,
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_PLACEHOLDER GETCS_NEEDS_LAYOUT_FLUSH",
|
||||
flags="GETCS_NEEDS_LAYOUT_FLUSH",
|
||||
allow_quirks="No" if side[1] else "Yes",
|
||||
servo_restyle_damage="reflow rebuild_and_reflow_inline"
|
||||
)}
|
||||
|
|
|
@ -6,15 +6,6 @@
|
|||
|
||||
<% data.new_style_struct("SVG", inherited=False, gecko_name="SVGReset") %>
|
||||
|
||||
${helpers.single_keyword(
|
||||
"dominant-baseline",
|
||||
"""auto use-script no-change reset-size ideographic alphabetic hanging
|
||||
mathematical central middle text-after-edge text-before-edge""",
|
||||
products="gecko",
|
||||
animation_value_type="discrete",
|
||||
spec="https://www.w3.org/TR/SVG11/text.html#DominantBaselineProperty",
|
||||
)}
|
||||
|
||||
${helpers.single_keyword(
|
||||
"vector-effect",
|
||||
"none non-scaling-stroke",
|
||||
|
@ -40,7 +31,7 @@ ${helpers.predefined_type(
|
|||
"1.0",
|
||||
products="gecko",
|
||||
animation_value_type="ComputedValue",
|
||||
spec="https://www.w3.org/TR/SVGTiny12/painting.html#propdef-stop-opacity",
|
||||
spec="https://svgwg.org/svg2-draft/pservers.html#StopOpacityProperty",
|
||||
)}
|
||||
|
||||
// Section 15 - Filter Effects
|
||||
|
@ -60,7 +51,7 @@ ${helpers.predefined_type(
|
|||
"1.0",
|
||||
products="gecko",
|
||||
animation_value_type="ComputedValue",
|
||||
spec="https://www.w3.org/TR/SVG/filters.html#FloodOpacityProperty",
|
||||
spec="https://drafts.fxtf.org/filter-effects/#FloodOpacityProperty",
|
||||
)}
|
||||
|
||||
${helpers.predefined_type(
|
||||
|
|
|
@ -13,7 +13,6 @@ ${helpers.predefined_type(
|
|||
"computed::TextOverflow::get_initial_value()",
|
||||
animation_value_type="discrete",
|
||||
boxed=True,
|
||||
flags="APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-ui/#propdef-text-overflow",
|
||||
servo_restyle_damage="rebuild_and_reflow",
|
||||
)}
|
||||
|
@ -23,7 +22,6 @@ ${helpers.single_keyword(
|
|||
"normal embed isolate bidi-override isolate-override plaintext",
|
||||
animation_value_type="none",
|
||||
spec="https://drafts.csswg.org/css-writing-modes/#propdef-unicode-bidi",
|
||||
flags="APPLIES_TO_MARKER",
|
||||
servo_restyle_damage="rebuild_and_reflow",
|
||||
)}
|
||||
|
||||
|
@ -33,7 +31,6 @@ ${helpers.predefined_type(
|
|||
"specified::TextDecorationLine::none()",
|
||||
initial_specified_value="specified::TextDecorationLine::none()",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-line",
|
||||
servo_restyle_damage="rebuild_and_reflow",
|
||||
)}
|
||||
|
@ -43,7 +40,6 @@ ${helpers.single_keyword(
|
|||
"solid double dotted dashed wavy -moz-none",
|
||||
products="gecko",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-style",
|
||||
)}
|
||||
|
||||
|
@ -55,7 +51,6 @@ ${helpers.predefined_type(
|
|||
products="gecko",
|
||||
animation_value_type="AnimatedColor",
|
||||
ignored_when_colors_disabled=True,
|
||||
flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-color",
|
||||
)}
|
||||
|
||||
|
@ -66,17 +61,16 @@ ${helpers.predefined_type(
|
|||
initial_specified_value="specified::InitialLetter::normal()",
|
||||
animation_value_type="discrete",
|
||||
products="gecko",
|
||||
flags="APPLIES_TO_FIRST_LETTER",
|
||||
gecko_pref="layout.css.initial-letter.enabled",
|
||||
spec="https://drafts.csswg.org/css-inline/#sizing-drop-initials",
|
||||
)}
|
||||
|
||||
${helpers.predefined_type(
|
||||
"text-decoration-width",
|
||||
"text-decoration-thickness",
|
||||
"LengthOrAuto",
|
||||
"computed::LengthOrAuto::auto()",
|
||||
products="gecko",
|
||||
animation_value_type="ComputedValue",
|
||||
gecko_pref="layout.css.text-decoration-width.enabled",
|
||||
gecko_pref="layout.css.text-decoration-thickness.enabled",
|
||||
spec="https://drafts.csswg.org/css-text-decor-4/#text-decoration-width-property"
|
||||
)}
|
||||
|
|
|
@ -53,7 +53,7 @@ pub use self::cascade::*;
|
|||
|
||||
<%!
|
||||
from collections import defaultdict
|
||||
from data import Method, Keyword, to_rust_ident, to_camel_case, SYSTEM_FONT_LONGHANDS
|
||||
from data import Method, PropertyRestrictions, Keyword, to_rust_ident, to_camel_case, SYSTEM_FONT_LONGHANDS
|
||||
import os.path
|
||||
%>
|
||||
|
||||
|
@ -812,6 +812,22 @@ impl LonghandIdSet {
|
|||
&IGNORED_WHEN_COLORS_DISABLED
|
||||
}
|
||||
|
||||
/// Returns the set of properties that are declared as having no effect on
|
||||
/// Gecko <scrollbar> elements or their descendant scrollbar parts.
|
||||
#[cfg(debug_assertions)]
|
||||
#[cfg(feature = "gecko")]
|
||||
#[inline]
|
||||
pub fn has_no_effect_on_gecko_scrollbars() -> &'static Self {
|
||||
// data.py asserts that has_no_effect_on_gecko_scrollbars is True or
|
||||
// False for properties that are inherited and Gecko pref controlled,
|
||||
// and is None for all other properties.
|
||||
${static_longhand_id_set(
|
||||
"HAS_NO_EFFECT_ON_SCROLLBARS",
|
||||
lambda p: p.has_effect_on_gecko_scrollbars is False
|
||||
)}
|
||||
&HAS_NO_EFFECT_ON_SCROLLBARS
|
||||
}
|
||||
|
||||
/// Iterate over the current longhand id set.
|
||||
pub fn iter(&self) -> LonghandIdSetIterator {
|
||||
LonghandIdSetIterator { longhands: self, cur: 0, }
|
||||
|
@ -987,6 +1003,28 @@ bitflags! {
|
|||
if logical_count * 2 != len(props):
|
||||
raise RuntimeError("Logical group {} has ".format(group) +
|
||||
"unbalanced logical / physical properties")
|
||||
|
||||
FIRST_LINE_RESTRICTIONS = PropertyRestrictions.first_line(data)
|
||||
FIRST_LETTER_RESTRICTIONS = PropertyRestrictions.first_letter(data)
|
||||
MARKER_RESTRICTIONS = PropertyRestrictions.marker(data)
|
||||
PLACEHOLDER_RESTRICTIONS = PropertyRestrictions.placeholder(data)
|
||||
CUE_RESTRICTIONS = PropertyRestrictions.cue(data)
|
||||
|
||||
def restriction_flags(property):
|
||||
name = property.name
|
||||
flags = []
|
||||
if name in FIRST_LINE_RESTRICTIONS:
|
||||
flags.append("APPLIES_TO_FIRST_LINE")
|
||||
if name in FIRST_LETTER_RESTRICTIONS:
|
||||
flags.append("APPLIES_TO_FIRST_LETTER")
|
||||
if name in PLACEHOLDER_RESTRICTIONS:
|
||||
flags.append("APPLIES_TO_PLACEHOLDER")
|
||||
if name in MARKER_RESTRICTIONS:
|
||||
flags.append("APPLIES_TO_MARKER")
|
||||
if name in CUE_RESTRICTIONS:
|
||||
flags.append("APPLIES_TO_CUE")
|
||||
return flags
|
||||
|
||||
%>
|
||||
|
||||
/// A group for properties which may override each other
|
||||
|
@ -1190,7 +1228,7 @@ impl LonghandId {
|
|||
// constant expression support.
|
||||
const FLAGS: [u16; ${len(data.longhands)}] = [
|
||||
% for property in data.longhands:
|
||||
% for flag in property.flags:
|
||||
% for flag in property.flags + restriction_flags(property):
|
||||
PropertyFlags::${flag}.bits |
|
||||
% endfor
|
||||
0,
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
use crate::properties::longhands::background_clip;
|
||||
use crate::properties::longhands::background_clip::single_value::computed_value::T as Clip;
|
||||
use crate::properties::longhands::background_origin::single_value::computed_value::T as Origin;
|
||||
use crate::values::specified::{Color, Position, PositionComponent};
|
||||
use crate::values::specified::{AllowQuirks, Color, Position, PositionComponent};
|
||||
use crate::parser::Parse;
|
||||
|
||||
// FIXME(emilio): Should be the same type!
|
||||
|
@ -64,7 +64,9 @@
|
|||
}
|
||||
}
|
||||
if position.is_none() {
|
||||
if let Ok(value) = input.try(|input| Position::parse(context, input)) {
|
||||
if let Ok(value) = input.try(|input| {
|
||||
Position::parse_three_value_quirky(context, input, AllowQuirks::No)
|
||||
}) {
|
||||
position = Some(value);
|
||||
|
||||
// Parse background size, if applicable.
|
||||
|
@ -211,7 +213,7 @@
|
|||
let mut any = false;
|
||||
|
||||
input.parse_comma_separated(|input| {
|
||||
let value = Position::parse_quirky(context, input, AllowQuirks::Yes)?;
|
||||
let value = Position::parse_three_value_quirky(context, input, AllowQuirks::Yes)?;
|
||||
position_x.push(value.horizontal);
|
||||
position_y.push(value.vertical);
|
||||
any = true;
|
||||
|
|
|
@ -15,7 +15,8 @@ use crate::values::computed::CSSPixelLength;
|
|||
use crate::values::KeyframesName;
|
||||
use app_units::Au;
|
||||
use cssparser::RGBA;
|
||||
use euclid::{Size2D, TypedScale, TypedSize2D};
|
||||
use euclid::default::Size2D as UntypedSize2D;
|
||||
use euclid::{Scale, Size2D};
|
||||
use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
|
||||
use style_traits::viewport::ViewportConstraints;
|
||||
use style_traits::{CSSPixel, DevicePixel};
|
||||
|
@ -29,9 +30,9 @@ pub struct Device {
|
|||
/// The current media type used by de device.
|
||||
media_type: MediaType,
|
||||
/// The current viewport size, in CSS pixels.
|
||||
viewport_size: TypedSize2D<f32, CSSPixel>,
|
||||
viewport_size: Size2D<f32, CSSPixel>,
|
||||
/// The current device pixel ratio, from CSS pixels to device pixels.
|
||||
device_pixel_ratio: TypedScale<f32, CSSPixel, DevicePixel>,
|
||||
device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
|
||||
|
||||
/// The font size of the root element
|
||||
/// This is set when computing the style of the root
|
||||
|
@ -59,8 +60,8 @@ impl Device {
|
|||
/// Trivially construct a new `Device`.
|
||||
pub fn new(
|
||||
media_type: MediaType,
|
||||
viewport_size: TypedSize2D<f32, CSSPixel>,
|
||||
device_pixel_ratio: TypedScale<f32, CSSPixel, DevicePixel>,
|
||||
viewport_size: Size2D<f32, CSSPixel>,
|
||||
device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
|
||||
) -> Device {
|
||||
Device {
|
||||
media_type,
|
||||
|
@ -121,7 +122,7 @@ impl Device {
|
|||
/// Returns the viewport size of the current device in app units, needed,
|
||||
/// among other things, to resolve viewport units.
|
||||
#[inline]
|
||||
pub fn au_viewport_size(&self) -> Size2D<Au> {
|
||||
pub fn au_viewport_size(&self) -> UntypedSize2D<Au> {
|
||||
Size2D::new(
|
||||
Au::from_f32_px(self.viewport_size.width),
|
||||
Au::from_f32_px(self.viewport_size.height),
|
||||
|
@ -129,7 +130,7 @@ impl Device {
|
|||
}
|
||||
|
||||
/// Like the above, but records that we've used viewport units.
|
||||
pub fn au_viewport_size_for_viewport_unit_resolution(&self) -> Size2D<Au> {
|
||||
pub fn au_viewport_size_for_viewport_unit_resolution(&self) -> UntypedSize2D<Au> {
|
||||
self.used_viewport_units.store(true, Ordering::Relaxed);
|
||||
self.au_viewport_size()
|
||||
}
|
||||
|
@ -140,7 +141,7 @@ impl Device {
|
|||
}
|
||||
|
||||
/// Returns the device pixel ratio.
|
||||
pub fn device_pixel_ratio(&self) -> TypedScale<f32, CSSPixel, DevicePixel> {
|
||||
pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
|
||||
self.device_pixel_ratio
|
||||
}
|
||||
|
||||
|
|
|
@ -181,18 +181,29 @@ impl UrlExtraData {
|
|||
#[cfg(feature = "gecko")]
|
||||
impl fmt::Debug for UrlExtraData {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
struct DebugURI(*mut structs::nsIURI);
|
||||
impl fmt::Debug for DebugURI {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
use nsstring::nsCString;
|
||||
let mut spec = nsCString::new();
|
||||
unsafe {
|
||||
bindings::Gecko_nsIURI_Debug(self.0, &mut spec);
|
||||
macro_rules! define_debug_struct {
|
||||
($struct_name:ident, $gecko_class:ident, $debug_fn:ident) => {
|
||||
struct $struct_name(*mut structs::$gecko_class);
|
||||
impl fmt::Debug for $struct_name {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
use nsstring::nsCString;
|
||||
let mut spec = nsCString::new();
|
||||
unsafe {
|
||||
bindings::$debug_fn(self.0, &mut spec);
|
||||
}
|
||||
spec.fmt(formatter)
|
||||
}
|
||||
}
|
||||
spec.fmt(formatter)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
define_debug_struct!(DebugURI, nsIURI, Gecko_nsIURI_Debug);
|
||||
define_debug_struct!(
|
||||
DebugReferrerInfo,
|
||||
nsIReferrerInfo,
|
||||
Gecko_nsIReferrerInfo_Debug
|
||||
);
|
||||
|
||||
formatter
|
||||
.debug_struct("URLExtraData")
|
||||
.field("is_chrome", &self.is_chrome())
|
||||
|
@ -202,7 +213,11 @@ impl fmt::Debug for UrlExtraData {
|
|||
)
|
||||
.field(
|
||||
"referrer",
|
||||
&DebugURI(self.as_ref().mReferrer.raw::<structs::nsIURI>()),
|
||||
&DebugReferrerInfo(
|
||||
self.as_ref()
|
||||
.mReferrerInfo
|
||||
.raw::<structs::nsIReferrerInfo>(),
|
||||
),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ use crate::values::specified::{NonNegativeLengthPercentageOrAuto, ViewportPercen
|
|||
use app_units::Au;
|
||||
use cssparser::CowRcStr;
|
||||
use cssparser::{parse_important, AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
|
||||
use euclid::TypedSize2D;
|
||||
use euclid::Size2D;
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
|
@ -832,7 +832,7 @@ impl MaybeNew for ViewportConstraints {
|
|||
});
|
||||
|
||||
Some(ViewportConstraints {
|
||||
size: TypedSize2D::new(width.to_f32_px(), height.to_f32_px()),
|
||||
size: Size2D::new(width.to_f32_px(), height.to_f32_px()),
|
||||
|
||||
// TODO: compute a zoom factor for 'auto' as suggested by DEVICE-ADAPT § 10.
|
||||
initial_zoom: PinchZoomFactor::new(initial_zoom.unwrap_or(1.)),
|
||||
|
|
|
@ -7,28 +7,12 @@
|
|||
#[cfg(feature = "gecko")]
|
||||
pub use crate::values::specified::list::ListStyleType;
|
||||
pub use crate::values::specified::list::MozListReversed;
|
||||
pub use crate::values::specified::list::{QuotePair, Quotes};
|
||||
|
||||
lazy_static! {
|
||||
static ref INITIAL_QUOTES: crate::ArcSlice<QuotePair> = crate::ArcSlice::from_iter_leaked(
|
||||
vec![
|
||||
QuotePair {
|
||||
opening: "\u{201c}".to_owned().into(),
|
||||
closing: "\u{201d}".to_owned().into(),
|
||||
},
|
||||
QuotePair {
|
||||
opening: "\u{2018}".to_owned().into(),
|
||||
closing: "\u{2019}".to_owned().into(),
|
||||
},
|
||||
]
|
||||
.into_iter()
|
||||
);
|
||||
}
|
||||
pub use crate::values::specified::list::Quotes;
|
||||
|
||||
impl Quotes {
|
||||
/// Initial value for `quotes`.
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> Quotes {
|
||||
Quotes(INITIAL_QUOTES.clone())
|
||||
Quotes::Auto
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ use crate::rule_cache::RuleCacheConditions;
|
|||
use crate::Atom;
|
||||
#[cfg(feature = "servo")]
|
||||
use crate::Prefix;
|
||||
use euclid::Size2D;
|
||||
use euclid::default::Size2D;
|
||||
use std::cell::RefCell;
|
||||
use std::cmp;
|
||||
use std::f32;
|
||||
|
@ -64,7 +64,7 @@ pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageO
|
|||
#[cfg(feature = "gecko")]
|
||||
pub use self::list::ListStyleType;
|
||||
pub use self::list::MozListReversed;
|
||||
pub use self::list::{QuotePair, Quotes};
|
||||
pub use self::list::Quotes;
|
||||
pub use self::motion::{OffsetPath, OffsetRotate};
|
||||
pub use self::outline::OutlineStyle;
|
||||
pub use self::percentage::{NonNegativePercentage, Percentage};
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::values::animated::ToAnimatedZero;
|
|||
use crate::values::computed::{Angle, Integer, Length, LengthPercentage, Number, Percentage};
|
||||
use crate::values::generics::transform as generic;
|
||||
use crate::Zero;
|
||||
use euclid::{Transform3D, Vector3D};
|
||||
use euclid::default::{Transform3D, Vector3D};
|
||||
|
||||
pub use crate::values::generics::transform::TransformStyle;
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
//! Machinery to compute distances between animatable values.
|
||||
|
||||
use app_units::Au;
|
||||
use euclid::Size2D;
|
||||
use euclid::default::Size2D;
|
||||
use std::iter::Sum;
|
||||
use std::ops::Add;
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@ use crate::values::specified::length::LengthPercentage as SpecifiedLengthPercent
|
|||
use crate::values::{computed, CSSFloat};
|
||||
use crate::Zero;
|
||||
use app_units::Au;
|
||||
use euclid::{self, Rect, Transform3D};
|
||||
use euclid;
|
||||
use euclid::default::{Rect, Transform3D};
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::{CssWriter, ToCss};
|
||||
|
||||
|
@ -562,7 +563,7 @@ impl<T: ToMatrix> Transform<T> {
|
|||
for operation in &*self.0 {
|
||||
let matrix = operation.to_3d_matrix(reference_box)?;
|
||||
contain_3d |= operation.is_3d();
|
||||
transform = transform.pre_mul(&matrix);
|
||||
transform = transform.pre_transform(&matrix);
|
||||
}
|
||||
|
||||
Ok((transform, contain_3d))
|
||||
|
|
|
@ -22,7 +22,7 @@ use crate::values::CSSFloat;
|
|||
use crate::Zero;
|
||||
use app_units::Au;
|
||||
use cssparser::{Parser, Token};
|
||||
use euclid::Size2D;
|
||||
use euclid::default::Size2D;
|
||||
use std::cmp;
|
||||
use std::ops::{Add, Mul};
|
||||
use style_traits::values::specified::AllowedNumericType;
|
||||
|
|
|
@ -104,7 +104,7 @@ pub struct QuotePair {
|
|||
pub closing: crate::OwnedStr,
|
||||
}
|
||||
|
||||
/// Specified and computed `quotes` property.
|
||||
/// List of quote pairs for the specified/computed value of `quotes` property.
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
|
@ -117,23 +117,53 @@ pub struct QuotePair {
|
|||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[repr(C)]
|
||||
pub struct Quotes(
|
||||
#[repr(transparent)]
|
||||
pub struct QuoteList(
|
||||
#[css(iterable, if_empty = "none")]
|
||||
#[ignore_malloc_size_of = "Arc"]
|
||||
pub crate::ArcSlice<QuotePair>,
|
||||
);
|
||||
|
||||
/// Specified and computed `quotes` property: `auto`, `none`, or a list
|
||||
/// of characters.
|
||||
///
|
||||
/// cbindgen:derive-tagged-enum-copy-constructor=true
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
MallocSizeOf,
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToComputedValue,
|
||||
ToCss,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[repr(C)]
|
||||
pub enum Quotes {
|
||||
/// list of quote pairs
|
||||
QuoteList(QuoteList),
|
||||
/// auto (use lang-dependent quote marks)
|
||||
Auto,
|
||||
}
|
||||
|
||||
impl Parse for Quotes {
|
||||
fn parse<'i, 't>(
|
||||
_: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Quotes, ParseError<'i>> {
|
||||
if input
|
||||
.try(|input| input.expect_ident_matching("auto"))
|
||||
.is_ok()
|
||||
{
|
||||
return Ok(Quotes::Auto);
|
||||
}
|
||||
|
||||
if input
|
||||
.try(|input| input.expect_ident_matching("none"))
|
||||
.is_ok()
|
||||
{
|
||||
return Ok(Self::default());
|
||||
return Ok(Quotes::QuoteList(QuoteList::default()));
|
||||
}
|
||||
|
||||
let mut quotes = Vec::new();
|
||||
|
@ -150,7 +180,9 @@ impl Parse for Quotes {
|
|||
}
|
||||
|
||||
if !quotes.is_empty() {
|
||||
Ok(Quotes(crate::ArcSlice::from_iter(quotes.into_iter())))
|
||||
Ok(Quotes::QuoteList(QuoteList(crate::ArcSlice::from_iter(
|
||||
quotes.into_iter(),
|
||||
))))
|
||||
} else {
|
||||
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageO
|
|||
#[cfg(feature = "gecko")]
|
||||
pub use self::list::ListStyleType;
|
||||
pub use self::list::MozListReversed;
|
||||
pub use self::list::{QuotePair, Quotes};
|
||||
pub use self::list::Quotes;
|
||||
pub use self::motion::{OffsetPath, OffsetRotate};
|
||||
pub use self::outline::OutlineStyle;
|
||||
pub use self::percentage::Percentage;
|
||||
|
@ -402,14 +402,18 @@ impl Parse for NonNegativeNumberOrPercentage {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
/// The value of Opacity is <alpha-value>, which is "<number> | <percentage>".
|
||||
/// However, we serialize the specified value as number, so it's ok to store
|
||||
/// the Opacity as Number.
|
||||
#[derive(
|
||||
Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, SpecifiedValueInfo, ToCss, ToShmem,
|
||||
)]
|
||||
pub struct Opacity(Number);
|
||||
|
||||
impl Parse for Opacity {
|
||||
fn parse<'i, 't>(
|
||||
impl Opacity {
|
||||
/// Parse number value only.
|
||||
#[inline]
|
||||
pub fn parse_number<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
|
@ -417,6 +421,29 @@ impl Parse for Opacity {
|
|||
}
|
||||
}
|
||||
|
||||
impl Parse for Opacity {
|
||||
/// Opacity accepts <number> | <percentage>, so we parse it as NumberOrPercentage,
|
||||
/// and then convert into an Number if it's a Percentage.
|
||||
/// https://drafts.csswg.org/cssom/#serializing-css-values
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
let number = match NumberOrPercentage::parse(context, input)? {
|
||||
NumberOrPercentage::Percentage(p) => Number {
|
||||
value: p.get(),
|
||||
calc_clamping_mode: if p.is_calc() {
|
||||
Some(AllowedNumericType::All)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
},
|
||||
NumberOrPercentage::Number(n) => n,
|
||||
};
|
||||
Ok(Opacity(number))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for Opacity {
|
||||
type ComputedValue = CSSFloat;
|
||||
|
||||
|
|
|
@ -94,13 +94,17 @@ impl Parse for Position {
|
|||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
Self::parse_quirky(context, input, AllowQuirks::No)
|
||||
let position = Self::parse_three_value_quirky(context, input, AllowQuirks::No)?;
|
||||
if position.is_three_value_syntax() {
|
||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||
}
|
||||
Ok(position)
|
||||
}
|
||||
}
|
||||
|
||||
impl Position {
|
||||
/// Parses a `<position>`, with quirks.
|
||||
pub fn parse_quirky<'i, 't>(
|
||||
/// Parses a `<bg-position>`, with quirks.
|
||||
pub fn parse_three_value_quirky<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
allow_quirks: AllowQuirks,
|
||||
|
@ -183,6 +187,12 @@ impl Position {
|
|||
pub fn center() -> Self {
|
||||
Self::new(PositionComponent::Center, PositionComponent::Center)
|
||||
}
|
||||
|
||||
/// Returns true if this uses a 3 value syntax.
|
||||
#[inline]
|
||||
fn is_three_value_syntax(&self) -> bool {
|
||||
self.horizontal.component_count() != self.vertical.component_count()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for Position {
|
||||
|
@ -252,6 +262,20 @@ impl<S> PositionComponent<S> {
|
|||
pub fn zero() -> Self {
|
||||
PositionComponent::Length(LengthPercentage::Percentage(Percentage::zero()))
|
||||
}
|
||||
|
||||
/// Returns the count of this component.
|
||||
fn component_count(&self) -> usize {
|
||||
match *self {
|
||||
PositionComponent::Length(..) | PositionComponent::Center => 1,
|
||||
PositionComponent::Side(_, ref lp) => {
|
||||
if lp.is_some() {
|
||||
2
|
||||
} else {
|
||||
1
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Side> ToComputedValue for PositionComponent<S> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue