aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock38
-rw-r--r--components/layout/display_list/border.rs9
-rw-r--r--components/malloc_size_of/Cargo.toml2
-rw-r--r--components/script/dom/element.rs6
-rw-r--r--components/style/Cargo.toml4
-rw-r--r--components/style/build_gecko.rs4
-rw-r--r--components/style/cbindgen.toml1
-rw-r--r--components/style/element_state.rs2
-rw-r--r--components/style/gecko/conversions.rs20
-rw-r--r--components/style/gecko/data.rs13
-rw-r--r--components/style/gecko/media_features.rs69
-rw-r--r--components/style/gecko/media_queries.rs4
-rw-r--r--components/style/gecko/pseudo_element_definition.mako.rs4
-rw-r--r--components/style/gecko/restyle_damage.rs2
-rw-r--r--components/style/gecko/values.rs83
-rw-r--r--components/style/gecko/wrapper.rs24
-rw-r--r--components/style/gecko_bindings/sugar/origin_flags.rs12
-rw-r--r--components/style/invalidation/element/restyle_hints.rs41
-rw-r--r--components/style/properties/data.py8
-rw-r--r--components/style/properties/gecko.mako.rs7
-rw-r--r--components/style/properties/longhands/background.mako.rs1
-rw-r--r--components/style/properties/longhands/border.mako.rs17
-rw-r--r--components/style/properties/longhands/box.mako.rs5
-rw-r--r--components/style/properties/longhands/effects.mako.rs1
-rw-r--r--components/style/properties/longhands/inherited_box.mako.rs3
-rw-r--r--components/style/properties/longhands/inherited_text.mako.rs2
-rw-r--r--components/style/properties/longhands/position.mako.rs11
-rw-r--r--components/style/properties/longhands/svg.mako.rs2
-rw-r--r--components/style/rule_collector.rs84
-rw-r--r--components/style/stylist.rs6
-rw-r--r--components/style/values/animated/mod.rs33
-rw-r--r--components/style/values/computed/basic_shape.rs20
-rw-r--r--components/style/values/computed/border.rs44
-rw-r--r--components/style/values/computed/length.rs8
-rw-r--r--components/style/values/computed/mod.rs36
-rw-r--r--components/style/values/generics/basic_shape.rs91
-rw-r--r--components/style/values/generics/border.rs16
-rw-r--r--components/style/values/generics/position.rs1
-rw-r--r--components/style/values/generics/rect.rs1
-rw-r--r--components/style/values/specified/basic_shape.rs26
-rw-r--r--components/style/values/specified/border.rs64
-rw-r--r--components/style/values/specified/length.rs36
-rw-r--r--components/style/values/specified/mod.rs22
-rw-r--r--tests/unit/style/properties/serialization.rs404
44 files changed, 512 insertions, 775 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 25d1dd886b9..9d5b7d5f676 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -684,7 +684,7 @@ dependencies = [
"crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -772,7 +772,7 @@ dependencies = [
"procedural-masquerade 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
- "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1123,7 +1123,7 @@ name = "fallible"
version = "0.0.1"
dependencies = [
"hashglobe 0.1.0",
- "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1287,7 +1287,7 @@ dependencies = [
"servo_arc 0.1.1",
"servo_atoms 0.0.1",
"servo_url 0.0.1",
- "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"style 0.0.1",
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"truetype 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2012,7 +2012,7 @@ dependencies = [
"servo_geometry 0.0.1",
"servo_url 0.0.1",
"size_of_test 0.0.1",
- "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"style 0.0.1",
"style_traits 0.0.1",
"unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2136,7 +2136,7 @@ dependencies = [
"libservo 0.0.1",
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -2275,8 +2275,8 @@ dependencies = [
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_arc 0.1.1",
- "smallbitvec 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallbitvec 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2850,7 +2850,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -3284,7 +3284,7 @@ dependencies = [
"servo_geometry 0.0.1",
"servo_rand 0.0.1",
"servo_url 0.0.1",
- "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"style 0.0.1",
"style_traits 0.0.1",
"swapper 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3400,7 +3400,7 @@ dependencies = [
"phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)",
"precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_arc 0.1.1",
- "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -3528,7 +3528,7 @@ dependencies = [
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_media_derive 0.1.0 (git+https://github.com/servo/media)",
- "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -3762,12 +3762,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "smallbitvec"
-version = "2.1.1"
+version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "smallvec"
-version = "0.6.3"
+version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3894,8 +3894,8 @@ dependencies = [
"servo_atoms 0.0.1",
"servo_config 0.0.1",
"servo_url 0.0.1",
- "smallbitvec 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallbitvec 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"style_derive 0.0.1",
"style_traits 0.0.1",
@@ -4575,7 +4575,7 @@ dependencies = [
"ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_profiler 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.57.2 (git+https://github.com/servo/webrender)",
@@ -5115,8 +5115,8 @@ dependencies = [
"checksum signpost 0.1.0 (git+https://github.com/pcwalton/signpost.git)" = "<none>"
"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d"
-"checksum smallbitvec 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c63726029f0069f88467873e47f392575f28f9f16b72ac65465263db4b3a13c"
-"checksum smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "26df3bb03ca5eac2e64192b723d51f56c1b1e0860e7c766281f4598f181acdc8"
+"checksum smallbitvec 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1764fe2b30ee783bfe3b9b37b2649d8d590b3148bb12e0079715d4d5c673562e"
+"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db"
"checksum smithay-client-toolkit 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ef227bd9251cf8f8e54f8dd9a4b164307e515f5312cd632ebc87b56f723893a2"
"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
"checksum stb_truetype 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "48fa7d3136d8645909de1f7c7eb5416cc43057a75ace08fc39ae736bc9da8af1"
diff --git a/components/layout/display_list/border.rs b/components/layout/display_list/border.rs
index 265b25a2805..d5909abee84 100644
--- a/components/layout/display_list/border.rs
+++ b/components/layout/display_list/border.rs
@@ -14,6 +14,7 @@ use style::values::computed::{BorderCornerRadius, BorderImageWidth};
use style::values::computed::{BorderImageSideWidth, LengthOrNumber};
use style::values::generics::border::BorderImageSideWidth as GenericBorderImageSideWidth;
use style::values::generics::rect::Rect as StyleRect;
+use style::values::generics::NonNegative;
use style::values::Either;
use webrender_api::{BorderRadius, BorderSide, BorderStyle, ColorF};
use webrender_api::{LayoutSideOffsets, LayoutSize, NormalBorder};
@@ -163,7 +164,7 @@ fn side_image_width(
) -> f32 {
match border_image_width {
GenericBorderImageSideWidth::Length(v) => v.to_used_value(total_length).to_f32_px(),
- GenericBorderImageSideWidth::Number(x) => border_width * x,
+ GenericBorderImageSideWidth::Number(x) => border_width * x.0,
GenericBorderImageSideWidth::Auto => border_width,
}
}
@@ -181,15 +182,15 @@ pub fn image_width(
)
}
-fn resolve_percentage(value: NumberOrPercentage, length: i32) -> i32 {
- match value {
+fn resolve_percentage(value: NonNegative<NumberOrPercentage>, length: i32) -> i32 {
+ match value.0 {
NumberOrPercentage::Percentage(p) => (p.0 * length as f32).round() as i32,
NumberOrPercentage::Number(n) => n.round() as i32,
}
}
pub fn image_slice(
- border_image_slice: &StyleRect<NumberOrPercentage>,
+ border_image_slice: &StyleRect<NonNegative<NumberOrPercentage>>,
width: i32,
height: i32,
) -> SideOffsets2D<i32> {
diff --git a/components/malloc_size_of/Cargo.toml b/components/malloc_size_of/Cargo.toml
index 22840c89d8a..92b3db44c15 100644
--- a/components/malloc_size_of/Cargo.toml
+++ b/components/malloc_size_of/Cargo.toml
@@ -37,7 +37,7 @@ selectors = { path = "../selectors" }
serde = { version = "1.0.27", optional = true }
serde_bytes = { version = "0.10", optional = true }
servo_arc = { path = "../servo_arc" }
-smallbitvec = "2.1.0"
+smallbitvec = "2.3.0"
smallvec = "0.6"
string_cache = { version = "0.7", optional = true }
thin-slice = "0.1.0"
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index 91cc8939590..233d4a01bb3 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -128,6 +128,7 @@ use style::selector_parser::{
};
use style::shared_lock::{Locked, SharedRwLock};
use style::thread_state;
+use style::values::generics::NonNegative;
use style::values::{computed, specified};
use style::values::{CSSFloat, Either};
use style::CaseSensitivityExt;
@@ -847,8 +848,9 @@ impl LayoutElementHelpers for LayoutDom<Element> {
};
if let Some(border) = border {
- let width_value =
- specified::BorderSideWidth::Length(specified::Length::from_px(border as f32));
+ let width_value = specified::BorderSideWidth::Length(NonNegative(
+ specified::Length::from_px(border as f32),
+ ));
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::BorderTopWidth(width_value.clone()),
diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml
index 9ae935c0e4d..17612eff900 100644
--- a/components/style/Cargo.toml
+++ b/components/style/Cargo.toml
@@ -60,8 +60,8 @@ serde = {version = "1.0", optional = true, features = ["derive"]}
servo_arc = { path = "../servo_arc" }
servo_atoms = {path = "../atoms", optional = true}
servo_config = {path = "../config", optional = true}
-smallbitvec = "2.1.1"
-smallvec = "0.6"
+smallbitvec = "2.3.0"
+smallvec = "0.6.6"
string_cache = { version = "0.7", optional = true }
style_derive = {path = "../style_derive"}
style_traits = {path = "../style_traits"}
diff --git a/components/style/build_gecko.rs b/components/style/build_gecko.rs
index 9b627a4a82e..734d09569f5 100644
--- a/components/style/build_gecko.rs
+++ b/components/style/build_gecko.rs
@@ -139,7 +139,9 @@ mod bindings {
// Disable rust unions, because we replace some types inside of
// them.
- let mut builder = Builder::default().rust_target(RustTarget::Stable_1_0);
+ 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
diff --git a/components/style/cbindgen.toml b/components/style/cbindgen.toml
index 6005126fb27..27ad7bc80a1 100644
--- a/components/style/cbindgen.toml
+++ b/components/style/cbindgen.toml
@@ -50,6 +50,7 @@ include = [
"ComputedTimingFunction",
"Display",
"DisplayMode",
+ "ExtremumLength",
"FillRule",
"FontDisplay",
"FontFaceSourceListComponent",
diff --git a/components/style/element_state.rs b/components/style/element_state.rs
index a646a2a37bf..8165c73ef14 100644
--- a/components/style/element_state.rs
+++ b/components/style/element_state.rs
@@ -144,7 +144,7 @@ bitflags! {
/// Event-based document states.
///
/// NB: Is important for this to remain in sync with Gecko's
- /// dom/base/nsIDocument.h.
+ /// dom/base/Document.h.
#[derive(MallocSizeOf)]
pub struct DocumentState: u64 {
/// RTL locale: specific to the XUL localedir attribute
diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs
index c48d56f56e1..266ebbd750a 100644
--- a/components/style/gecko/conversions.rs
+++ b/components/style/gecko/conversions.rs
@@ -5,6 +5,8 @@
//! This module contains conversion helpers between Servo and Gecko types
//! Ideally, it would be in geckolib itself, but coherence
//! forces us to keep the traits and implementations here
+//!
+//! FIXME(emilio): This file should generally just die.
#![allow(unsafe_code)]
@@ -26,6 +28,7 @@ use crate::values::generics::box_::VerticalAlign;
use crate::values::generics::grid::{TrackListValue, TrackSize};
use crate::values::generics::image::{CompatMode, GradientItem, Image as GenericImage};
use crate::values::generics::rect::Rect;
+use crate::values::generics::NonNegative;
use app_units::Au;
use std::f32::consts::PI;
@@ -113,7 +116,6 @@ impl From<nsStyleCoord_CalcValue> for LengthOrPercentageOrAuto {
// disappear as we move more stuff to cbindgen.
impl From<nsStyleCoord_CalcValue> for NonNegativeLengthOrPercentageOrAuto {
fn from(other: nsStyleCoord_CalcValue) -> Self {
- use crate::values::generics::NonNegative;
use style_traits::values::specified::AllowedNumericType;
NonNegative(if other.mLength < 0 || other.mPercent < 0. {
LengthOrPercentageOrAuto::Calc(CalcLengthOrPercentage::with_clamping_mode(
@@ -679,6 +681,7 @@ pub mod basic_shape {
use crate::values::generics::basic_shape::{GeometryBox, ShapeBox, ShapeSource};
use crate::values::generics::border::BorderRadius as GenericBorderRadius;
use crate::values::generics::rect::Rect;
+ use crate::values::generics::NonNegative;
use crate::values::specified::SVGPathData;
use std::borrow::Borrow;
@@ -838,10 +841,17 @@ pub mod basic_shape {
fn from(other: &'a nsStyleCorners) -> Self {
let get_corner = |index| {
BorderCornerRadius::new(
- LengthOrPercentage::from_gecko_style_coord(&other.data_at(index))
- .expect("<border-radius> should be a length, percentage, or calc value"),
- LengthOrPercentage::from_gecko_style_coord(&other.data_at(index + 1))
- .expect("<border-radius> should be a length, percentage, or calc value"),
+ NonNegative(
+ LengthOrPercentage::from_gecko_style_coord(&other.data_at(index)).expect(
+ "<border-radius> should be a length, percentage, or calc value",
+ ),
+ ),
+ NonNegative(
+ LengthOrPercentage::from_gecko_style_coord(&other.data_at(index + 1))
+ .expect(
+ "<border-radius> should be a length, percentage, or calc value",
+ ),
+ ),
)
};
diff --git a/components/style/gecko/data.rs b/components/style/gecko/data.rs
index d4c976cc2a6..80e34fe2e7e 100644
--- a/components/style/gecko/data.rs
+++ b/components/style/gecko/data.rs
@@ -7,9 +7,8 @@
use crate::context::QuirksMode;
use crate::dom::TElement;
use crate::gecko_bindings::bindings::{self, RawServoStyleSet};
-use crate::gecko_bindings::structs::StyleSheet as DomStyleSheet;
-use crate::gecko_bindings::structs::{nsIDocument, StyleSheetInfo};
use crate::gecko_bindings::structs::{RawGeckoPresContextBorrowed, ServoStyleSetSizes};
+use crate::gecko_bindings::structs::{StyleSheet as DomStyleSheet, StyleSheetInfo};
use crate::gecko_bindings::sugar::ownership::{HasArcFFI, HasBoxFFI, HasFFI, HasSimpleFFI};
use crate::invalidation::media_queries::{MediaListKey, ToMediaListKey};
use crate::media_queries::{Device, MediaList};
@@ -151,8 +150,7 @@ impl PerDocumentStyleData {
// right now not always honored, see bug 1405543...
//
// Should we just force XBL Stylists to be NoQuirks?
- let quirks_mode =
- unsafe { (*device.pres_context().mDocument.raw::<nsIDocument>()).mCompatMode };
+ let quirks_mode = unsafe { (*device.pres_context().mDocument.mRawPtr).mCompatMode };
PerDocumentStyleData(AtomicRefCell::new(PerDocumentStyleDataImpl {
stylist: Stylist::new(device, quirks_mode.into()),
@@ -193,12 +191,7 @@ impl PerDocumentStyleDataImpl {
/// Returns whether visited styles are enabled.
#[inline]
pub fn visited_styles_enabled(&self) -> bool {
- let doc = self
- .stylist
- .device()
- .pres_context()
- .mDocument
- .raw::<nsIDocument>();
+ let doc = self.stylist.device().pres_context().mDocument.mRawPtr;
unsafe { bindings::Gecko_VisitedStylesEnabled(doc) }
}
diff --git a/components/style/gecko/media_features.rs b/components/style/gecko/media_features.rs
index 25355c45d70..82613c9e245 100644
--- a/components/style/gecko/media_features.rs
+++ b/components/style/gecko/media_features.rs
@@ -9,7 +9,7 @@ use crate::gecko_bindings::structs;
use crate::media_queries::media_feature::{AllowsRanges, ParsingRequirements};
use crate::media_queries::media_feature::{Evaluator, MediaFeatureDescription};
use crate::media_queries::media_feature_expression::{AspectRatio, RangeOrOperator};
-use crate::media_queries::Device;
+use crate::media_queries::{Device, MediaType};
use crate::values::computed::CSSPixelLength;
use crate::values::computed::Resolution;
use crate::Atom;
@@ -295,6 +295,59 @@ fn eval_prefers_reduced_motion(device: &Device, query_value: Option<PrefersReduc
}
}
+#[derive(Clone, Copy, Debug, FromPrimitive, Parse, ToCss)]
+#[repr(u8)]
+enum OverflowBlock {
+ None,
+ Scroll,
+ OptionalPaged,
+ Paged,
+}
+
+/// https://drafts.csswg.org/mediaqueries-4/#mf-overflow-block
+fn eval_overflow_block(device: &Device, query_value: Option<OverflowBlock>) -> bool {
+ // For the time being, assume that printing (including previews)
+ // is the only time when we paginate, and we are otherwise always
+ // scrolling. This is true at the moment in Firefox, but may need
+ // updating in the future (e.g., ebook readers built with Stylo, a
+ // billboard mode that doesn't support overflow at all).
+ //
+ // If this ever changes, don't forget to change eval_overflow_inline too.
+ let scrolling = device.media_type() != MediaType::print();
+ let query_value = match query_value {
+ Some(v) => v,
+ None => return true,
+ };
+
+ match query_value {
+ OverflowBlock::None | OverflowBlock::OptionalPaged => false,
+ OverflowBlock::Scroll => scrolling,
+ OverflowBlock::Paged => !scrolling,
+ }
+}
+
+#[derive(Clone, Copy, Debug, FromPrimitive, Parse, ToCss)]
+#[repr(u8)]
+enum OverflowInline {
+ None,
+ Scroll,
+}
+
+/// https://drafts.csswg.org/mediaqueries-4/#mf-overflow-inline
+fn eval_overflow_inline(device: &Device, query_value: Option<OverflowInline>) -> bool {
+ // See the note in eval_overflow_block.
+ let scrolling = device.media_type() != MediaType::print();
+ let query_value = match query_value {
+ Some(v) => v,
+ None => return scrolling,
+ };
+
+ match query_value {
+ OverflowInline::None => !scrolling,
+ OverflowInline::Scroll => scrolling,
+ }
+}
+
/// https://drafts.csswg.org/mediaqueries-4/#mf-interaction
bitflags! {
struct PointerCapabilities: u8 {
@@ -473,7 +526,7 @@ lazy_static! {
/// to support new types in these entries and (2) ensuring that either
/// nsPresContext::MediaFeatureValuesChanged is called when the value that
/// would be returned by the evaluator function could change.
- pub static ref MEDIA_FEATURES: [MediaFeatureDescription; 48] = [
+ pub static ref MEDIA_FEATURES: [MediaFeatureDescription; 50] = [
feature!(
atom!("width"),
AllowsRanges::Yes,
@@ -593,6 +646,18 @@ lazy_static! {
ParsingRequirements::empty(),
),
feature!(
+ atom!("overflow-block"),
+ AllowsRanges::No,
+ keyword_evaluator!(eval_overflow_block, OverflowBlock),
+ ParsingRequirements::empty(),
+ ),
+ feature!(
+ atom!("overflow-inline"),
+ AllowsRanges::No,
+ keyword_evaluator!(eval_overflow_inline, OverflowInline),
+ ParsingRequirements::empty(),
+ ),
+ feature!(
atom!("pointer"),
AllowsRanges::No,
keyword_evaluator!(eval_pointer, Pointer),
diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs
index ab3f3a0de80..851422467ce 100644
--- a/components/style/gecko/media_queries.rs
+++ b/components/style/gecko/media_queries.rs
@@ -162,8 +162,8 @@ impl Device {
/// Gets the document pointer.
#[inline]
- pub fn document(&self) -> *mut structs::nsIDocument {
- self.pres_context().mDocument.raw::<structs::nsIDocument>()
+ pub fn document(&self) -> *mut structs::Document {
+ self.pres_context().mDocument.mRawPtr
}
/// Recreates the default computed values.
diff --git a/components/style/gecko/pseudo_element_definition.mako.rs b/components/style/gecko/pseudo_element_definition.mako.rs
index aaa3d7c8c99..613bbd281ee 100644
--- a/components/style/gecko/pseudo_element_definition.mako.rs
+++ b/components/style/gecko/pseudo_element_definition.mako.rs
@@ -156,8 +156,6 @@ impl PseudoElement {
/// Construct a `CSSPseudoElementType` from a pseudo-element
#[inline]
fn pseudo_type(&self) -> CSSPseudoElementType {
- use crate::gecko_bindings::structs::CSSPseudoElementType_InheritingAnonBox;
-
match *self {
% for pseudo in PSEUDOS:
% if not pseudo.is_anon_box():
@@ -165,7 +163,7 @@ impl PseudoElement {
% elif pseudo.is_tree_pseudo_element():
PseudoElement::${pseudo.capitalized_pseudo()}(..) => CSSPseudoElementType::XULTree,
% elif pseudo.is_inheriting_anon_box():
- PseudoElement::${pseudo.capitalized_pseudo()} => CSSPseudoElementType_InheritingAnonBox,
+ PseudoElement::${pseudo.capitalized_pseudo()} => CSSPseudoElementType::InheritingAnonBox,
% else:
PseudoElement::${pseudo.capitalized_pseudo()} => CSSPseudoElementType::NonInheritingAnonBox,
% endif
diff --git a/components/style/gecko/restyle_damage.rs b/components/style/gecko/restyle_damage.rs
index b2b14b413e3..9c9d07b7112 100644
--- a/components/style/gecko/restyle_damage.rs
+++ b/components/style/gecko/restyle_damage.rs
@@ -83,7 +83,7 @@ impl GeckoRestyleDamage {
/// Gets restyle damage to reconstruct the entire frame, subsuming all
/// other damage.
pub fn reconstruct() -> Self {
- GeckoRestyleDamage(structs::nsChangeHint_nsChangeHint_ReconstructFrame)
+ GeckoRestyleDamage(structs::nsChangeHint::nsChangeHint_ReconstructFrame)
}
}
diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs
index 98dafcd070f..39a5ac2de89 100644
--- a/components/style/gecko/values.rs
+++ b/components/style/gecko/values.rs
@@ -13,12 +13,10 @@ use crate::gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, Coor
use crate::media_queries::Device;
use crate::values::computed::basic_shape::ShapeRadius as ComputedShapeRadius;
use crate::values::computed::FlexBasis as ComputedFlexBasis;
-use crate::values::computed::NonNegativeNumber;
use crate::values::computed::{Angle, ExtremumLength, Length, LengthOrPercentage};
use crate::values::computed::{LengthOrPercentageOrAuto, Percentage};
use crate::values::computed::{LengthOrPercentageOrNone, Number, NumberOrPercentage};
use crate::values::computed::{MaxLength as ComputedMaxLength, MozLength as ComputedMozLength};
-use crate::values::computed::{NonNegativeLength, NonNegativeLengthOrPercentage};
use crate::values::generics::basic_shape::ShapeRadius;
use crate::values::generics::box_::Perspective;
use crate::values::generics::flex::FlexBasis;
@@ -34,6 +32,9 @@ use nsstring::{nsACString, nsCStr};
use std::cmp::max;
/// A trait that defines an interface to convert from and to `nsStyleCoord`s.
+///
+/// TODO(emilio): Almost everything that is in this file should be somehow
+/// switched to cbindgen.
pub trait GeckoStyleCoordConvertible: Sized {
/// Convert this to a `nsStyleCoord`.
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T);
@@ -66,6 +67,19 @@ impl<A: GeckoStyleCoordConvertible, B: GeckoStyleCoordConvertible> GeckoStyleCoo
}
}
+impl<Inner> GeckoStyleCoordConvertible for NonNegative<Inner>
+where
+ Inner: GeckoStyleCoordConvertible,
+{
+ fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
+ self.0.to_gecko_style_coord(coord)
+ }
+
+ fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
+ Some(NonNegative(Inner::from_gecko_style_coord(coord)?))
+ }
+}
+
impl GeckoStyleCoordConvertible for ComputedFlexBasis {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
match *self {
@@ -152,16 +166,6 @@ impl GeckoStyleCoordConvertible for LengthOrPercentage {
}
}
-impl GeckoStyleCoordConvertible for NonNegativeLengthOrPercentage {
- fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
- self.0.to_gecko_style_coord(coord);
- }
-
- fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
- LengthOrPercentage::from_gecko_style_coord(coord).map(NonNegative::<LengthOrPercentage>)
- }
-}
-
impl GeckoStyleCoordConvertible for Length {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
coord.set_value(CoordDataValue::Coord(self.to_i32_au()));
@@ -175,26 +179,6 @@ impl GeckoStyleCoordConvertible for Length {
}
}
-impl GeckoStyleCoordConvertible for NonNegativeLength {
- fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
- self.0.to_gecko_style_coord(coord);
- }
-
- fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
- Length::from_gecko_style_coord(coord).map(NonNegative::<Length>)
- }
-}
-
-impl GeckoStyleCoordConvertible for NonNegativeNumber {
- fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
- self.0.to_gecko_style_coord(coord);
- }
-
- fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
- Number::from_gecko_style_coord(coord).map(NonNegative::<Number>)
- }
-}
-
impl GeckoStyleCoordConvertible for LengthOrPercentageOrAuto {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
let value = match *self {
@@ -302,7 +286,7 @@ impl GeckoStyleCoordConvertible for ComputedShapeRadius {
None
}
},
- _ => LengthOrPercentage::from_gecko_style_coord(coord).map(ShapeRadius::Length),
+ _ => GeckoStyleCoordConvertible::from_gecko_style_coord(coord).map(ShapeRadius::Length),
}
}
}
@@ -378,40 +362,13 @@ impl GeckoStyleCoordConvertible for Normal {
impl GeckoStyleCoordConvertible for ExtremumLength {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
- use crate::gecko_bindings::structs::{
- NS_STYLE_WIDTH_AVAILABLE, NS_STYLE_WIDTH_FIT_CONTENT,
- };
- use crate::gecko_bindings::structs::{
- NS_STYLE_WIDTH_MAX_CONTENT, NS_STYLE_WIDTH_MIN_CONTENT,
- };
- coord.set_value(CoordDataValue::Enumerated(match *self {
- ExtremumLength::MozMaxContent => NS_STYLE_WIDTH_MAX_CONTENT,
- ExtremumLength::MozMinContent => NS_STYLE_WIDTH_MIN_CONTENT,
- ExtremumLength::MozFitContent => NS_STYLE_WIDTH_FIT_CONTENT,
- ExtremumLength::MozAvailable => NS_STYLE_WIDTH_AVAILABLE,
- }))
+ coord.set_value(CoordDataValue::Enumerated(*self as u32));
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
- use crate::gecko_bindings::structs::{
- NS_STYLE_WIDTH_AVAILABLE, NS_STYLE_WIDTH_FIT_CONTENT,
- };
- use crate::gecko_bindings::structs::{
- NS_STYLE_WIDTH_MAX_CONTENT, NS_STYLE_WIDTH_MIN_CONTENT,
- };
+ use num_traits::FromPrimitive;
match coord.as_value() {
- CoordDataValue::Enumerated(NS_STYLE_WIDTH_MAX_CONTENT) => {
- Some(ExtremumLength::MozMaxContent)
- },
- CoordDataValue::Enumerated(NS_STYLE_WIDTH_MIN_CONTENT) => {
- Some(ExtremumLength::MozMinContent)
- },
- CoordDataValue::Enumerated(NS_STYLE_WIDTH_FIT_CONTENT) => {
- Some(ExtremumLength::MozFitContent)
- },
- CoordDataValue::Enumerated(NS_STYLE_WIDTH_AVAILABLE) => {
- Some(ExtremumLength::MozAvailable)
- },
+ CoordDataValue::Enumerated(v) => ExtremumLength::from_u32(v),
_ => None,
}
}
diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs
index 0768e9e26af..97f0f887a00 100644
--- a/components/style/gecko/wrapper.rs
+++ b/components/style/gecko/wrapper.rs
@@ -22,7 +22,6 @@ use crate::dom::{LayoutIterator, NodeInfo, OpaqueNode, TDocument, TElement, TNod
use crate::element_state::{DocumentState, ElementState};
use crate::font_metrics::{FontMetrics, FontMetricsProvider, FontMetricsQueryResult};
use crate::gecko::data::GeckoStyleSheet;
-use crate::gecko::global_style_data::GLOBAL_STYLE_DATA;
use crate::gecko::selector_parser::{NonTSPseudoClass, PseudoElement, SelectorImpl};
use crate::gecko::snapshot_helpers;
use crate::gecko_bindings::bindings;
@@ -45,8 +44,8 @@ use crate::gecko_bindings::bindings::{Gecko_ElementState, Gecko_GetDocumentLWThe
use crate::gecko_bindings::bindings::{Gecko_SetNodeFlags, Gecko_UnsetNodeFlags};
use crate::gecko_bindings::structs;
use crate::gecko_bindings::structs::nsChangeHint;
-use crate::gecko_bindings::structs::nsIDocument_DocumentTheme as DocumentTheme;
use crate::gecko_bindings::structs::nsRestyleHint;
+use crate::gecko_bindings::structs::Document_DocumentTheme as DocumentTheme;
use crate::gecko_bindings::structs::EffectCompositor_CascadeLevel as CascadeLevel;
use crate::gecko_bindings::structs::ELEMENT_HANDLED_SNAPSHOT;
use crate::gecko_bindings::structs::ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO;
@@ -57,6 +56,7 @@ use crate::gecko_bindings::structs::NODE_NEEDS_FRAME;
use crate::gecko_bindings::structs::{nsAtom, nsIContent, nsINode_BooleanFlag};
use crate::gecko_bindings::structs::{RawGeckoElement, RawGeckoNode, RawGeckoXBLBinding};
use crate::gecko_bindings::sugar::ownership::{HasArcFFI, HasSimpleFFI};
+use crate::global_style_data::GLOBAL_STYLE_DATA;
use crate::hash::FxHashMap;
use crate::logical_geometry::WritingMode;
use crate::media_queries::Device;
@@ -107,9 +107,9 @@ fn elements_with_id<'a, 'le>(
}
}
-/// A simple wrapper over `nsIDocument`.
+/// A simple wrapper over `Document`.
#[derive(Clone, Copy)]
-pub struct GeckoDocument<'ld>(pub &'ld structs::nsIDocument);
+pub struct GeckoDocument<'ld>(pub &'ld structs::Document);
impl<'ld> TDocument for GeckoDocument<'ld> {
type ConcreteNode = GeckoNode<'ld>;
@@ -121,7 +121,7 @@ impl<'ld> TDocument for GeckoDocument<'ld> {
#[inline]
fn is_html_document(&self) -> bool {
- self.0.mType == structs::root::nsIDocument_Type::eHTML
+ self.0.mType == structs::Document_Type::eHTML
}
#[inline]
@@ -1242,11 +1242,8 @@ impl<'le> TElement for GeckoElement<'le> {
}
fn owner_doc_matches_for_testing(&self, device: &Device) -> bool {
- self.as_node().owner_doc().0 as *const structs::nsIDocument ==
- device
- .pres_context()
- .mDocument
- .raw::<structs::nsIDocument>()
+ self.as_node().owner_doc().0 as *const structs::Document ==
+ device.pres_context().mDocument.mRawPtr
}
fn style_attribute(&self) -> Option<ArcBorrow<Locked<PropertyDeclarationBlock>>> {
@@ -1501,9 +1498,6 @@ impl<'le> TElement for GeckoElement<'le> {
/// Process various tasks that are a result of animation-only restyle.
fn process_post_animation(&self, tasks: PostAnimationTasks) {
- use crate::gecko_bindings::structs::nsChangeHint_nsChangeHint_Empty;
- use crate::gecko_bindings::structs::nsRestyleHint_eRestyle_Subtree;
-
debug_assert!(!tasks.is_empty(), "Should be involved a task");
// If display style was changed from none to other, we need to resolve
@@ -1519,8 +1513,8 @@ impl<'le> TElement for GeckoElement<'le> {
);
unsafe {
self.note_explicit_hints(
- nsRestyleHint_eRestyle_Subtree,
- nsChangeHint_nsChangeHint_Empty,
+ nsRestyleHint::eRestyle_Subtree,
+ nsChangeHint::nsChangeHint_Empty,
);
}
}
diff --git a/components/style/gecko_bindings/sugar/origin_flags.rs b/components/style/gecko_bindings/sugar/origin_flags.rs
index b7250b53930..e0f0981c5d8 100644
--- a/components/style/gecko_bindings/sugar/origin_flags.rs
+++ b/components/style/gecko_bindings/sugar/origin_flags.rs
@@ -5,17 +5,17 @@
//! Helper to iterate over `OriginFlags` bits.
use crate::gecko_bindings::structs::OriginFlags;
-use crate::gecko_bindings::structs::OriginFlags_Author;
-use crate::gecko_bindings::structs::OriginFlags_User;
-use crate::gecko_bindings::structs::OriginFlags_UserAgent;
use crate::stylesheets::OriginSet;
/// Checks that the values for OriginFlags are the ones we expect.
pub fn assert_flags_match() {
use crate::stylesheets::origin::*;
- debug_assert_eq!(OriginFlags_UserAgent.0, OriginSet::ORIGIN_USER_AGENT.bits());
- debug_assert_eq!(OriginFlags_Author.0, OriginSet::ORIGIN_AUTHOR.bits());
- debug_assert_eq!(OriginFlags_User.0, OriginSet::ORIGIN_USER.bits());
+ debug_assert_eq!(
+ OriginFlags::UserAgent.0,
+ OriginSet::ORIGIN_USER_AGENT.bits()
+ );
+ debug_assert_eq!(OriginFlags::Author.0, OriginSet::ORIGIN_AUTHOR.bits());
+ debug_assert_eq!(OriginFlags::User.0, OriginSet::ORIGIN_USER.bits());
}
impl From<OriginFlags> for OriginSet {
diff --git a/components/style/invalidation/element/restyle_hints.rs b/components/style/invalidation/element/restyle_hints.rs
index 1d8a7f5bd14..de84fe56c85 100644
--- a/components/style/invalidation/element/restyle_hints.rs
+++ b/components/style/invalidation/element/restyle_hints.rs
@@ -193,38 +193,35 @@ impl Default for RestyleHint {
#[cfg(feature = "gecko")]
impl From<nsRestyleHint> for RestyleHint {
fn from(mut raw: nsRestyleHint) -> Self {
- use crate::gecko_bindings::structs::nsRestyleHint_eRestyle_Force as eRestyle_Force;
- use crate::gecko_bindings::structs::nsRestyleHint_eRestyle_ForceDescendants as eRestyle_ForceDescendants;
- use crate::gecko_bindings::structs::nsRestyleHint_eRestyle_LaterSiblings as eRestyle_LaterSiblings;
- use crate::gecko_bindings::structs::nsRestyleHint_eRestyle_Self as eRestyle_Self;
- use crate::gecko_bindings::structs::nsRestyleHint_eRestyle_SomeDescendants as eRestyle_SomeDescendants;
- use crate::gecko_bindings::structs::nsRestyleHint_eRestyle_Subtree as eRestyle_Subtree;
-
let mut hint = RestyleHint::empty();
debug_assert!(
- raw.0 & eRestyle_LaterSiblings.0 == 0,
+ raw.0 & nsRestyleHint::eRestyle_LaterSiblings.0 == 0,
"Handle later siblings manually if necessary plz."
);
- if (raw.0 & (eRestyle_Self.0 | eRestyle_Subtree.0)) != 0 {
- raw.0 &= !eRestyle_Self.0;
+ if (raw.0 & (nsRestyleHint::eRestyle_Self.0 | nsRestyleHint::eRestyle_Subtree.0)) != 0 {
+ raw.0 &= !nsRestyleHint::eRestyle_Self.0;
hint.insert(RestyleHint::RESTYLE_SELF);
}
- if (raw.0 & (eRestyle_Subtree.0 | eRestyle_SomeDescendants.0)) != 0 {
- raw.0 &= !eRestyle_Subtree.0;
- raw.0 &= !eRestyle_SomeDescendants.0;
+ if (raw.0 & (nsRestyleHint::eRestyle_Subtree.0 | nsRestyleHint::eRestyle_SomeDescendants.0)) !=
+ 0
+ {
+ raw.0 &= !nsRestyleHint::eRestyle_Subtree.0;
+ raw.0 &= !nsRestyleHint::eRestyle_SomeDescendants.0;
hint.insert(RestyleHint::RESTYLE_DESCENDANTS);
}
- if (raw.0 & (eRestyle_ForceDescendants.0 | eRestyle_Force.0)) != 0 {
- raw.0 &= !eRestyle_Force.0;
+ if (raw.0 & (nsRestyleHint::eRestyle_ForceDescendants.0 | nsRestyleHint::eRestyle_Force.0)) !=
+ 0
+ {
+ raw.0 &= !nsRestyleHint::eRestyle_Force.0;
hint.insert(RestyleHint::RECASCADE_SELF);
}
- if (raw.0 & eRestyle_ForceDescendants.0) != 0 {
- raw.0 &= !eRestyle_ForceDescendants.0;
+ if (raw.0 & nsRestyleHint::eRestyle_ForceDescendants.0) != 0 {
+ raw.0 &= !nsRestyleHint::eRestyle_ForceDescendants.0;
hint.insert(RestyleHint::RECASCADE_DESCENDANTS);
}
@@ -248,7 +245,7 @@ pub fn assert_restyle_hints_match() {
if cfg!(debug_assertions) {
let mut replacements = RestyleHint::replacements();
$(
- assert_eq!(structs::$a.0 as usize, $b.bits() as usize, stringify!($b));
+ assert_eq!(structs::nsRestyleHint::$a.0 as usize, $b.bits() as usize, stringify!($b));
replacements.remove($b);
)*
assert_eq!(replacements, RestyleHint::empty(),
@@ -259,9 +256,9 @@ pub fn assert_restyle_hints_match() {
}
check_restyle_hints! {
- nsRestyleHint_eRestyle_CSSTransitions => RestyleHint::RESTYLE_CSS_TRANSITIONS,
- nsRestyleHint_eRestyle_CSSAnimations => RestyleHint::RESTYLE_CSS_ANIMATIONS,
- nsRestyleHint_eRestyle_StyleAttribute => RestyleHint::RESTYLE_STYLE_ATTRIBUTE,
- nsRestyleHint_eRestyle_StyleAttribute_Animations => RestyleHint::RESTYLE_SMIL,
+ eRestyle_CSSTransitions => RestyleHint::RESTYLE_CSS_TRANSITIONS,
+ eRestyle_CSSAnimations => RestyleHint::RESTYLE_CSS_ANIMATIONS,
+ eRestyle_StyleAttribute => RestyleHint::RESTYLE_STYLE_ATTRIBUTE,
+ eRestyle_StyleAttribute_Animations => RestyleHint::RESTYLE_SMIL,
}
}
diff --git a/components/style/properties/data.py b/components/style/properties/data.py
index 8faaa163823..4d980039d1e 100644
--- a/components/style/properties/data.py
+++ b/components/style/properties/data.py
@@ -388,12 +388,12 @@ class Shorthand(object):
and allowed_in_keyframe_block != "False"
def get_animatable(self):
- animatable = False
+ if self.ident == "all":
+ return False
for sub in self.sub_properties:
if sub.animatable:
- animatable = True
- break
- return animatable
+ return True
+ return False
def get_transitionable(self):
transitionable = False
diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs
index 5f96b42c10a..d969f14f54a 100644
--- a/components/style/properties/gecko.mako.rs
+++ b/components/style/properties/gecko.mako.rs
@@ -39,7 +39,6 @@ use crate::gecko_bindings::bindings::RawGeckoPresContextBorrowed;
use crate::gecko_bindings::structs;
use crate::gecko_bindings::structs::nsCSSPropertyID;
use crate::gecko_bindings::structs::mozilla::CSSPseudoElementType;
-use crate::gecko_bindings::structs::mozilla::CSSPseudoElementType_InheritingAnonBox;
use crate::gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
use crate::gecko_bindings::sugar::refptr::RefPtr;
use crate::gecko::values::convert_nscolor_to_rgba;
@@ -138,7 +137,7 @@ impl ComputedValues {
#[inline]
pub fn is_anon_box(&self) -> bool {
let our_type = self.get_pseudo_type();
- return our_type == CSSPseudoElementType_InheritingAnonBox ||
+ return our_type == CSSPseudoElementType::InheritingAnonBox ||
our_type == CSSPseudoElementType::NonInheritingAnonBox;
}
@@ -1687,8 +1686,8 @@ fn static_assert() {
pub fn clone_border_image_slice(&self) -> longhands::border_image_slice::computed_value::T {
use crate::gecko_bindings::structs::NS_STYLE_BORDER_IMAGE_SLICE_FILL;
- use crate::values::computed::{BorderImageSlice, NumberOrPercentage};
- type NumberOrPercentageRect = crate::values::generics::rect::Rect<NumberOrPercentage>;
+ use crate::values::computed::{BorderImageSlice, NonNegativeNumberOrPercentage};
+ type NumberOrPercentageRect = crate::values::generics::rect::Rect<NonNegativeNumberOrPercentage>;
BorderImageSlice {
offsets:
diff --git a/components/style/properties/longhands/background.mako.rs b/components/style/properties/longhands/background.mako.rs
index 934814567ba..b97545898c2 100644
--- a/components/style/properties/longhands/background.mako.rs
+++ b/components/style/properties/longhands/background.mako.rs
@@ -108,7 +108,6 @@ ${helpers.single_keyword(
color-burn hard-light soft-light difference exclusion hue
saturation color luminosity""",
gecko_constant_prefix="NS_STYLE_BLEND",
- gecko_pref="layout.css.background-blend-mode.enabled",
vector=True, products="gecko", animation_value_type="discrete",
spec="https://drafts.fxtf.org/compositing/#background-blend-mode",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
diff --git a/components/style/properties/longhands/border.mako.rs b/components/style/properties/longhands/border.mako.rs
index 5a5cdbeb552..3fcf73bf2f4 100644
--- a/components/style/properties/longhands/border.mako.rs
+++ b/components/style/properties/longhands/border.mako.rs
@@ -88,7 +88,6 @@ ${helpers.single_keyword(
"box-decoration-break",
"slice clone",
gecko_enum_prefix="StyleBoxDecorationBreak",
- gecko_pref="layout.css.box-decoration-break.enabled",
spec="https://drafts.csswg.org/css-break/#propdef-box-decoration-break",
products="gecko",
animation_value_type="discrete",
@@ -153,14 +152,15 @@ ${helpers.predefined_type(
${helpers.predefined_type(
"border-image-slice",
"BorderImageSlice",
- initial_value="computed::NumberOrPercentage::Percentage(computed::Percentage(1.)).into()",
- initial_specified_value="specified::NumberOrPercentage::Percentage(specified::Percentage::new(1.)).into()",
+ initial_value="computed::BorderImageSlice::hundred_percent()",
+ 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,
)}
+// FIXME(emilio): Why does this live here? ;_;
#[cfg(feature = "gecko")]
impl crate::values::computed::BorderImageWidth {
pub fn to_gecko_rect(&self, sides: &mut crate::gecko_bindings::structs::nsStyleSides) {
@@ -177,7 +177,7 @@ impl crate::values::computed::BorderImageWidth {
l.to_gecko_style_coord(&mut sides.data_at_mut(${i}))
},
BorderImageSideWidth::Number(n) => {
- sides.data_at_mut(${i}).set_value(CoordDataValue::Factor(n))
+ sides.data_at_mut(${i}).set_value(CoordDataValue::Factor(n.0))
},
}
% endfor
@@ -191,6 +191,7 @@ impl crate::values::computed::BorderImageWidth {
use crate::gecko::values::GeckoStyleCoordConvertible;
use crate::values::computed::{LengthOrPercentage, Number};
use crate::values::generics::border::BorderImageSideWidth;
+ use crate::values::generics::NonNegative;
Some(
crate::values::computed::BorderImageWidth::new(
@@ -201,13 +202,13 @@ impl crate::values::computed::BorderImageWidth {
},
eStyleUnit_Factor => {
BorderImageSideWidth::Number(
- Number::from_gecko_style_coord(&sides.data_at(${i}))
- .expect("sides[${i}] could not convert to Number"))
+ NonNegative(Number::from_gecko_style_coord(&sides.data_at(${i}))
+ .expect("sides[${i}] could not convert to Number")))
},
_ => {
BorderImageSideWidth::Length(
- LengthOrPercentage::from_gecko_style_coord(&sides.data_at(${i}))
- .expect("sides[${i}] could not convert to LengthOrPercentager"))
+ NonNegative(LengthOrPercentage::from_gecko_style_coord(&sides.data_at(${i}))
+ .expect("sides[${i}] could not convert to LengthOrPercentage")))
},
},
% endfor
diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs
index 1e0629861e4..48b83271d9b 100644
--- a/components/style/properties/longhands/box.mako.rs
+++ b/components/style/properties/longhands/box.mako.rs
@@ -389,7 +389,6 @@ ${helpers.predefined_type(
${helpers.single_keyword(
"scroll-behavior",
"auto smooth",
- gecko_pref="layout.css.scroll-behavior.property-enabled",
products="gecko",
spec="https://drafts.csswg.org/cssom-view/#propdef-scroll-behavior",
animation_value_type="discrete",
@@ -427,7 +426,6 @@ ${helpers.single_keyword(
"isolation",
"auto isolate",
products="gecko",
- gecko_pref="layout.css.isolation.enabled",
spec="https://drafts.fxtf.org/compositing/#isolation",
flags="CREATES_STACKING_CONTEXT",
animation_value_type="discrete",
@@ -559,6 +557,7 @@ ${helpers.predefined_type(
flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
gecko_pref="layout.css.contain.enabled",
spec="https://drafts.csswg.org/css-contain/#contain-property",
+ enabled_in="chrome",
)}
// Non-standard
@@ -626,7 +625,7 @@ ${helpers.predefined_type(
"generics::basic_shape::ShapeSource::None",
products="gecko",
boxed=True,
- animation_value_type="ComputedValue",
+ animation_value_type="basic_shape::FloatAreaShape",
flags="APPLIES_TO_FIRST_LETTER",
spec="https://drafts.csswg.org/css-shapes/#shape-outside-property",
)}
diff --git a/components/style/properties/longhands/effects.mako.rs b/components/style/properties/longhands/effects.mako.rs
index 066ac4ca02a..0b3f96f0dde 100644
--- a/components/style/properties/longhands/effects.mako.rs
+++ b/components/style/properties/longhands/effects.mako.rs
@@ -62,6 +62,5 @@ ${helpers.single_keyword(
gecko_constant_prefix="NS_STYLE_BLEND",
animation_value_type="discrete",
flags="CREATES_STACKING_CONTEXT",
- gecko_pref="layout.css.mix-blend-mode.enabled",
spec="https://drafts.fxtf.org/compositing/#propdef-mix-blend-mode",
)}
diff --git a/components/style/properties/longhands/inherited_box.mako.rs b/components/style/properties/longhands/inherited_box.mako.rs
index 65d5727f11a..0e3799f6c46 100644
--- a/components/style/properties/longhands/inherited_box.mako.rs
+++ b/components/style/properties/longhands/inherited_box.mako.rs
@@ -54,7 +54,7 @@ ${helpers.single_keyword(
${helpers.single_keyword(
"color-adjust",
"economy exact", products="gecko",
- gecko_pref="layout.css.color-adjust.enabled",
+ gecko_enum_prefix="StyleColorAdjust",
animation_value_type="discrete",
spec="https://drafts.csswg.org/css-color/#propdef-color-adjust",
)}
@@ -77,6 +77,5 @@ ${helpers.single_keyword(
products="gecko",
gecko_enum_prefix="StyleImageOrientation",
animation_value_type="discrete",
- gecko_pref="layout.css.image-orientation.enabled",
spec="https://drafts.csswg.org/css-images/#propdef-image-orientation",
)}
diff --git a/components/style/properties/longhands/inherited_text.mako.rs b/components/style/properties/longhands/inherited_text.mako.rs
index f751b29ae68..5a7b88e3823 100644
--- a/components/style/properties/longhands/inherited_text.mako.rs
+++ b/components/style/properties/longhands/inherited_text.mako.rs
@@ -295,7 +295,7 @@ ${helpers.predefined_type(
"-webkit-text-stroke-width",
"BorderSideWidth",
"crate::values::computed::NonNegativeLength::new(0.)",
- initial_specified_value="specified::BorderSideWidth::Length(specified::Length::zero())",
+ initial_specified_value="specified::BorderSideWidth::zero()",
computed_type="crate::values::computed::NonNegativeLength",
products="gecko",
gecko_pref="layout.css.prefixes.webkit",
diff --git a/components/style/properties/longhands/position.mako.rs b/components/style/properties/longhands/position.mako.rs
index c5e507da10e..53a3acf81ec 100644
--- a/components/style/properties/longhands/position.mako.rs
+++ b/components/style/properties/longhands/position.mako.rs
@@ -244,21 +244,12 @@ ${helpers.predefined_type(
if logical:
spec = "https://drafts.csswg.org/css-logical-props/#propdef-%s"
%>
- // NOTE: Block-size doesn't support -moz-*-content keywords, since they make
- // no sense on the block axis, but it simplifies things the have that it has
- // the same type as the other properties, since otherwise we'd need to
- // handle logical props where the types are different, which looks like a
- // pain.
% if product == "gecko":
- <%
- parse_function = "parse" if size != "block-size" else "parse_disallow_keyword"
- %>
// width, height, block-size, inline-size
${helpers.predefined_type(
size,
"MozLength",
"computed::MozLength::auto()",
- parse_function,
logical=logical,
logical_group="size",
allow_quirks=not logical,
@@ -272,7 +263,6 @@ ${helpers.predefined_type(
"min-%s" % size,
"MozLength",
"computed::MozLength::auto()",
- parse_function,
logical=logical,
logical_group="min-size",
allow_quirks=not logical,
@@ -284,7 +274,6 @@ ${helpers.predefined_type(
"max-%s" % size,
"MaxLength",
"computed::MaxLength::none()",
- parse_function,
logical=logical,
logical_group="max-size",
allow_quirks=not logical,
diff --git a/components/style/properties/longhands/svg.mako.rs b/components/style/properties/longhands/svg.mako.rs
index d6e76f6f1f6..43a8952d86e 100644
--- a/components/style/properties/longhands/svg.mako.rs
+++ b/components/style/properties/longhands/svg.mako.rs
@@ -88,7 +88,7 @@ ${helpers.predefined_type(
"generics::basic_shape::ShapeSource::None",
products="gecko",
boxed=True,
- animation_value_type="ComputedValue",
+ animation_value_type="basic_shape::ClippingShape",
flags="CREATES_STACKING_CONTEXT",
spec="https://drafts.fxtf.org/css-masking/#propdef-clip-path",
)}
diff --git a/components/style/rule_collector.rs b/components/style/rule_collector.rs
index 6424cc237db..ba602ddca83 100644
--- a/components/style/rule_collector.rs
+++ b/components/style/rule_collector.rs
@@ -5,7 +5,7 @@
//! Collects a series of applicable rules for a given element.
use crate::applicable_declarations::{ApplicableDeclarationBlock, ApplicableDeclarationList};
-use crate::dom::{TElement, TShadowRoot};
+use crate::dom::{TElement, TNode, TShadowRoot};
use crate::properties::{AnimationRules, PropertyDeclarationBlock};
use crate::rule_tree::{CascadeLevel, ShadowCascadeOrder};
use crate::selector_map::SelectorMap;
@@ -17,6 +17,43 @@ use selectors::matching::{ElementSelectorFlags, MatchingContext};
use servo_arc::ArcBorrow;
use smallvec::SmallVec;
+/// This is a bit of a hack so <svg:use> matches the rules of the enclosing
+/// tree.
+///
+/// This function returns the containing shadow host ignoring <svg:use> shadow
+/// trees, since those match the enclosing tree's rules.
+///
+/// Only a handful of places need to really care about this. This is not a
+/// problem for invalidation and that kind of stuff because they still don't
+/// match rules based on elements outside of the shadow tree, and because the
+/// <svg:use> subtrees are immutable and recreated each time the source tree
+/// changes.
+///
+/// We historically allow cross-document <svg:use> to have these rules applied,
+/// but I think that's not great. Gecko is the only engine supporting that.
+///
+/// See https://github.com/w3c/svgwg/issues/504 for the relevant spec
+/// discussion.
+#[inline]
+pub fn containing_shadow_ignoring_svg_use<E: TElement>(
+ element: E,
+) -> Option<<E::ConcreteNode as TNode>::ConcreteShadowRoot> {
+ let mut shadow = element.containing_shadow()?;
+ loop {
+ let host = shadow.host();
+ let host_is_svg_use_element =
+ host.is_svg_element() && host.local_name() == &*local_name!("use");
+ if !host_is_svg_use_element {
+ return Some(shadow);
+ }
+ debug_assert!(
+ shadow.style_data().is_none(),
+ "We allow no stylesheets in <svg:use> subtrees"
+ );
+ shadow = host.containing_shadow()?;
+ }
+}
+
/// An object that we use with all the intermediate state needed for the
/// cascade.
///
@@ -213,43 +250,18 @@ where
return;
}
- let mut current_containing_shadow = self.rule_hash_target.containing_shadow();
- while let Some(containing_shadow) = current_containing_shadow {
- let cascade_data = containing_shadow.style_data();
- let host = containing_shadow.host();
- if let Some(map) = cascade_data.and_then(|data| data.normal_rules(self.pseudo_element))
- {
- self.collect_rules_in_shadow_tree(host, map, CascadeLevel::SameTreeAuthorNormal);
- }
- let host_is_svg_use_element =
- host.is_svg_element() && host.local_name() == &*local_name!("use");
- if !host_is_svg_use_element {
- self.matches_document_author_rules = false;
- break;
- }
+ let containing_shadow = containing_shadow_ignoring_svg_use(self.rule_hash_target);
+ let containing_shadow = match containing_shadow {
+ Some(s) => s,
+ None => return,
+ };
- debug_assert!(
- cascade_data.is_none(),
- "We allow no stylesheets in <svg:use> subtrees"
- );
+ self.matches_document_author_rules = false;
- // NOTE(emilio): Hack so <svg:use> matches the rules of the
- // enclosing tree.
- //
- // This is not a problem for invalidation and that kind of stuff
- // because they still don't match rules based on elements
- // outside of the shadow tree, and because the <svg:use>
- // subtrees are immutable and recreated each time the source
- // tree changes.
- //
- // We historically allow cross-document <svg:use> to have these
- // rules applied, but I think that's not great. Gecko is the
- // only engine supporting that.
- //
- // See https://github.com/w3c/svgwg/issues/504 for the relevant
- // spec discussion.
- current_containing_shadow = host.containing_shadow();
- self.matches_document_author_rules = current_containing_shadow.is_none();
+ let cascade_data = containing_shadow.style_data();
+ let host = containing_shadow.host();
+ if let Some(map) = cascade_data.and_then(|data| data.normal_rules(self.pseudo_element)) {
+ self.collect_rules_in_shadow_tree(host, map, CascadeLevel::SameTreeAuthorNormal);
}
}
diff --git a/components/style/stylist.rs b/components/style/stylist.rs
index 592e4e81081..74b055e099b 100644
--- a/components/style/stylist.rs
+++ b/components/style/stylist.rs
@@ -17,7 +17,7 @@ use crate::media_queries::Device;
use crate::properties::{self, CascadeMode, ComputedValues};
use crate::properties::{AnimationRules, PropertyDeclarationBlock};
use crate::rule_cache::{RuleCache, RuleCacheConditions};
-use crate::rule_collector::RuleCollector;
+use crate::rule_collector::{containing_shadow_ignoring_svg_use, RuleCollector};
use crate::rule_tree::{CascadeLevel, RuleTree, ShadowCascadeOrder, StrongRuleNode, StyleSource};
use crate::selector_map::{PrecomputedHashMap, PrecomputedHashSet, SelectorMap, SelectorMapEntry};
use crate::selector_parser::{PerPseudoElementMap, PseudoElement, SelectorImpl, SnapshotMap};
@@ -1187,7 +1187,9 @@ impl Stylist {
}
}
- if let Some(shadow) = element.containing_shadow() {
+ // Use the same rules to look for the containing host as we do for rule
+ // collection.
+ if let Some(shadow) = containing_shadow_ignoring_svg_use(element) {
if let Some(data) = shadow.style_data() {
try_find_in!(data);
}
diff --git a/components/style/values/animated/mod.rs b/components/style/values/animated/mod.rs
index 38de8a359a1..a7c947f810a 100644
--- a/components/style/values/animated/mod.rs
+++ b/components/style/values/animated/mod.rs
@@ -12,7 +12,8 @@ use crate::properties::PropertyId;
use crate::values::computed::length::CalcLengthOrPercentage;
use crate::values::computed::url::ComputedUrl;
use crate::values::computed::Angle as ComputedAngle;
-use crate::values::computed::BorderCornerRadius as ComputedBorderCornerRadius;
+use crate::values::computed::Image;
+use crate::values::specified::SVGPathData;
use crate::values::CSSFloat;
use app_units::Au;
use euclid::{Point2D, Size2D};
@@ -339,23 +340,19 @@ trivial_to_animated_value!(ComputedAngle);
trivial_to_animated_value!(ComputedUrl);
trivial_to_animated_value!(bool);
trivial_to_animated_value!(f32);
-
-impl ToAnimatedValue for ComputedBorderCornerRadius {
- type AnimatedValue = Self;
-
- #[inline]
- fn to_animated_value(self) -> Self {
- self
- }
-
- #[inline]
- fn from_animated_value(animated: Self::AnimatedValue) -> Self {
- ComputedBorderCornerRadius::new(
- (animated.0).0.width.clamp_to_non_negative(),
- (animated.0).0.height.clamp_to_non_negative(),
- )
- }
-}
+// Note: This implementation is for ToAnimatedValue of ShapeSource.
+//
+// SVGPathData uses Box<[T]>. If we want to derive ToAnimatedValue for all the
+// types, we have to do "impl ToAnimatedValue for Box<[T]>" first.
+// However, the general version of "impl ToAnimatedValue for Box<[T]>" needs to
+// clone |T| and convert it into |T::AnimatedValue|. However, for SVGPathData
+// that is unnecessary--moving |T| is sufficient. So here, we implement this
+// trait manually.
+trivial_to_animated_value!(SVGPathData);
+// FIXME: Bug 1514342, Image is not animatable, but we still need to implement
+// this to avoid adding this derive to generic::Image and all its arms. We can
+// drop this after landing Bug 1514342.
+trivial_to_animated_value!(Image);
impl ToAnimatedZero for Au {
#[inline]
diff --git a/components/style/values/computed/basic_shape.rs b/components/style/values/computed/basic_shape.rs
index 6a7b02cadcd..f808e0bf9f5 100644
--- a/components/style/values/computed/basic_shape.rs
+++ b/components/style/values/computed/basic_shape.rs
@@ -8,7 +8,7 @@
//! [basic-shape]: https://drafts.csswg.org/css-shapes/#typedef-basic-shape
use crate::values::computed::url::ComputedUrl;
-use crate::values::computed::{Image, LengthOrPercentage};
+use crate::values::computed::{Image, LengthOrPercentage, NonNegativeLengthOrPercentage};
use crate::values::generics::basic_shape as generic;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};
@@ -23,20 +23,26 @@ pub type ClippingShape = generic::ClippingShape<BasicShape, ComputedUrl>;
pub type FloatAreaShape = generic::FloatAreaShape<BasicShape, Image>;
/// A computed basic shape.
-pub type BasicShape =
- generic::BasicShape<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;
+pub type BasicShape = generic::BasicShape<
+ LengthOrPercentage,
+ LengthOrPercentage,
+ LengthOrPercentage,
+ NonNegativeLengthOrPercentage,
+>;
/// The computed value of `inset()`
-pub type InsetRect = generic::InsetRect<LengthOrPercentage>;
+pub type InsetRect = generic::InsetRect<LengthOrPercentage, NonNegativeLengthOrPercentage>;
/// A computed circle.
-pub type Circle = generic::Circle<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;
+pub type Circle =
+ generic::Circle<LengthOrPercentage, LengthOrPercentage, NonNegativeLengthOrPercentage>;
/// A computed ellipse.
-pub type Ellipse = generic::Ellipse<LengthOrPercentage, LengthOrPercentage, LengthOrPercentage>;
+pub type Ellipse =
+ generic::Ellipse<LengthOrPercentage, LengthOrPercentage, NonNegativeLengthOrPercentage>;
/// The computed value of `ShapeRadius`
-pub type ShapeRadius = generic::ShapeRadius<LengthOrPercentage>;
+pub type ShapeRadius = generic::ShapeRadius<NonNegativeLengthOrPercentage>;
impl ToCss for Circle {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
diff --git a/components/style/values/computed/border.rs b/components/style/values/computed/border.rs
index 676e8c1b6be..c6ab4abc5a5 100644
--- a/components/style/values/computed/border.rs
+++ b/components/style/values/computed/border.rs
@@ -4,9 +4,8 @@
//! Computed types for CSS values related to borders.
-use crate::values::animated::ToAnimatedZero;
-use crate::values::computed::length::{LengthOrPercentage, NonNegativeLength};
-use crate::values::computed::{Number, NumberOrPercentage};
+use crate::values::computed::length::{NonNegativeLength, NonNegativeLengthOrPercentage};
+use crate::values::computed::{NonNegativeNumber, NonNegativeNumberOrPercentage};
use crate::values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
use crate::values::generics::border::BorderImageSideWidth as GenericBorderImageSideWidth;
use crate::values::generics::border::BorderImageSlice as GenericBorderImageSlice;
@@ -14,6 +13,7 @@ use crate::values::generics::border::BorderRadius as GenericBorderRadius;
use crate::values::generics::border::BorderSpacing as GenericBorderSpacing;
use crate::values::generics::rect::Rect;
use crate::values::generics::size::Size;
+use crate::values::generics::NonNegative;
use app_units::Au;
pub use crate::values::specified::border::BorderImageRepeat;
@@ -22,16 +22,17 @@ pub use crate::values::specified::border::BorderImageRepeat;
pub type BorderImageWidth = Rect<BorderImageSideWidth>;
/// A computed value for a single side of a `border-image-width` property.
-pub type BorderImageSideWidth = GenericBorderImageSideWidth<LengthOrPercentage, Number>;
+pub type BorderImageSideWidth =
+ GenericBorderImageSideWidth<NonNegativeLengthOrPercentage, NonNegativeNumber>;
/// A computed value for the `border-image-slice` property.
-pub type BorderImageSlice = GenericBorderImageSlice<NumberOrPercentage>;
+pub type BorderImageSlice = GenericBorderImageSlice<NonNegativeNumberOrPercentage>;
/// A computed value for the `border-radius` property.
-pub type BorderRadius = GenericBorderRadius<LengthOrPercentage>;
+pub type BorderRadius = GenericBorderRadius<NonNegativeLengthOrPercentage>;
/// A computed value for the `border-*-radius` longhand properties.
-pub type BorderCornerRadius = GenericBorderCornerRadius<LengthOrPercentage>;
+pub type BorderCornerRadius = GenericBorderCornerRadius<NonNegativeLengthOrPercentage>;
/// A computed value for the `border-spacing` longhand property.
pub type BorderSpacing = GenericBorderSpacing<NonNegativeLength>;
@@ -40,7 +41,18 @@ impl BorderImageSideWidth {
/// Returns `1`.
#[inline]
pub fn one() -> Self {
- GenericBorderImageSideWidth::Number(1.)
+ GenericBorderImageSideWidth::Number(NonNegative(1.))
+ }
+}
+
+impl BorderImageSlice {
+ /// Returns the `100%` value.
+ #[inline]
+ pub fn hundred_percent() -> Self {
+ GenericBorderImageSlice {
+ offsets: Rect::all(NonNegativeNumberOrPercentage::hundred_percent()),
+ fill: false,
+ }
}
}
@@ -68,26 +80,18 @@ impl BorderCornerRadius {
/// Returns `0 0`.
pub fn zero() -> Self {
GenericBorderCornerRadius(Size::new(
- LengthOrPercentage::zero(),
- LengthOrPercentage::zero(),
+ NonNegativeLengthOrPercentage::zero(),
+ NonNegativeLengthOrPercentage::zero(),
))
}
}
-impl ToAnimatedZero for BorderCornerRadius {
- #[inline]
- fn to_animated_zero(&self) -> Result<Self, ()> {
- // FIXME(nox): Why?
- Err(())
- }
-}
-
impl BorderRadius {
/// Returns whether all the values are `0px`.
pub fn all_zero(&self) -> bool {
fn all(corner: &BorderCornerRadius) -> bool {
- fn is_zero(l: &LengthOrPercentage) -> bool {
- *l == LengthOrPercentage::zero()
+ fn is_zero(l: &NonNegativeLengthOrPercentage) -> bool {
+ *l == NonNegativeLengthOrPercentage::zero()
}
is_zero(corner.0.width()) && is_zero(corner.0.height())
}
diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs
index 96886e9096a..240b5ceb1ee 100644
--- a/components/style/values/computed/length.rs
+++ b/components/style/values/computed/length.rs
@@ -975,6 +975,7 @@ pub type NonNegativeLengthOrPercentageOrNormal = Either<NonNegativeLengthOrPerce
Copy,
Debug,
Eq,
+ FromPrimitive,
MallocSizeOf,
Parse,
PartialEq,
@@ -982,9 +983,12 @@ pub type NonNegativeLengthOrPercentageOrNormal = Either<NonNegativeLengthOrPerce
ToComputedValue,
ToCss,
)]
+#[repr(u8)]
pub enum ExtremumLength {
- MozMaxContent,
- MozMinContent,
+ #[parse(aliases = "-moz-max-content")]
+ MaxContent,
+ #[parse(aliases = "-moz-min-content")]
+ MinContent,
MozFitContent,
MozAvailable,
}
diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs
index 93ee3e73cc1..4051511e28e 100644
--- a/components/style/values/computed/mod.rs
+++ b/components/style/values/computed/mod.rs
@@ -543,6 +543,17 @@ pub enum NumberOrPercentage {
Number(Number),
}
+impl NumberOrPercentage {
+ fn clamp_to_non_negative(self) -> Self {
+ match self {
+ NumberOrPercentage::Percentage(p) => {
+ NumberOrPercentage::Percentage(p.clamp_to_non_negative())
+ },
+ NumberOrPercentage::Number(n) => NumberOrPercentage::Number(n.max(0.)),
+ }
+ }
+}
+
impl ToComputedValue for specified::NumberOrPercentage {
type ComputedValue = NumberOrPercentage;
@@ -572,6 +583,31 @@ impl ToComputedValue for specified::NumberOrPercentage {
}
}
+/// A non-negative <number-percentage>.
+pub type NonNegativeNumberOrPercentage = NonNegative<NumberOrPercentage>;
+
+impl NonNegativeNumberOrPercentage {
+ /// Returns the `100%` value.
+ #[inline]
+ pub fn hundred_percent() -> Self {
+ NonNegative(NumberOrPercentage::Percentage(Percentage::hundred()))
+ }
+}
+
+impl ToAnimatedValue for NonNegativeNumberOrPercentage {
+ type AnimatedValue = NumberOrPercentage;
+
+ #[inline]
+ fn to_animated_value(self) -> Self::AnimatedValue {
+ self.0
+ }
+
+ #[inline]
+ fn from_animated_value(animated: Self::AnimatedValue) -> Self {
+ NonNegative(animated.clamp_to_non_negative())
+ }
+}
+
/// A type used for opacity.
pub type Opacity = CSSFloat;
diff --git a/components/style/values/generics/basic_shape.rs b/components/style/values/generics/basic_shape.rs
index cbcdadd055f..bfe709ceb4b 100644
--- a/components/style/values/generics/basic_shape.rs
+++ b/components/style/values/generics/basic_shape.rs
@@ -20,7 +20,16 @@ pub type ClippingShape<BasicShape, Url> = ShapeSource<BasicShape, GeometryBox, U
/// <https://drafts.fxtf.org/css-masking-1/#typedef-geometry-box>
#[allow(missing_docs)]
#[derive(
- Animate, Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
+ Animate,
+ Clone,
+ Copy,
+ Debug,
+ MallocSizeOf,
+ PartialEq,
+ SpecifiedValueInfo,
+ ToAnimatedValue,
+ ToComputedValue,
+ ToCss,
)]
pub enum GeometryBox {
FillBox,
@@ -45,6 +54,7 @@ pub type FloatAreaShape<BasicShape, Image> = ShapeSource<BasicShape, ShapeBox, I
Parse,
PartialEq,
SpecifiedValueInfo,
+ ToAnimatedValue,
ToComputedValue,
ToCss,
)]
@@ -59,7 +69,15 @@ pub enum ShapeBox {
#[allow(missing_docs)]
#[animation(no_bound(ImageOrUrl))]
#[derive(
- Animate, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
+ Animate,
+ Clone,
+ Debug,
+ MallocSizeOf,
+ PartialEq,
+ SpecifiedValueInfo,
+ ToAnimatedValue,
+ ToComputedValue,
+ ToCss,
)]
pub enum ShapeSource<BasicShape, ReferenceBox, ImageOrUrl> {
#[animation(error)]
@@ -82,13 +100,14 @@ pub enum ShapeSource<BasicShape, ReferenceBox, ImageOrUrl> {
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
+ ToAnimatedValue,
ToComputedValue,
ToCss,
)]
-pub enum BasicShape<H, V, LengthOrPercentage> {
- Inset(#[css(field_bound)] InsetRect<LengthOrPercentage>),
- Circle(#[css(field_bound)] Circle<H, V, LengthOrPercentage>),
- Ellipse(#[css(field_bound)] Ellipse<H, V, LengthOrPercentage>),
+pub enum BasicShape<H, V, LengthOrPercentage, NonNegativeLengthOrPercentage> {
+ Inset(#[css(field_bound)] InsetRect<LengthOrPercentage, NonNegativeLengthOrPercentage>),
+ Circle(#[css(field_bound)] Circle<H, V, NonNegativeLengthOrPercentage>),
+ Ellipse(#[css(field_bound)] Ellipse<H, V, NonNegativeLengthOrPercentage>),
Polygon(Polygon<LengthOrPercentage>),
}
@@ -103,11 +122,12 @@ pub enum BasicShape<H, V, LengthOrPercentage> {
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
+ ToAnimatedValue,
ToComputedValue,
)]
-pub struct InsetRect<LengthOrPercentage> {
+pub struct InsetRect<LengthOrPercentage, NonNegativeLengthOrPercentage> {
pub rect: Rect<LengthOrPercentage>,
- pub round: Option<BorderRadius<LengthOrPercentage>>,
+ pub round: Option<BorderRadius<NonNegativeLengthOrPercentage>>,
}
/// <https://drafts.csswg.org/css-shapes/#funcdef-circle>
@@ -122,11 +142,12 @@ pub struct InsetRect<LengthOrPercentage> {
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
+ ToAnimatedValue,
ToComputedValue,
)]
-pub struct Circle<H, V, LengthOrPercentage> {
+pub struct Circle<H, V, NonNegativeLengthOrPercentage> {
pub position: Position<H, V>,
- pub radius: ShapeRadius<LengthOrPercentage>,
+ pub radius: ShapeRadius<NonNegativeLengthOrPercentage>,
}
/// <https://drafts.csswg.org/css-shapes/#funcdef-ellipse>
@@ -141,12 +162,13 @@ pub struct Circle<H, V, LengthOrPercentage> {
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
+ ToAnimatedValue,
ToComputedValue,
)]
-pub struct Ellipse<H, V, LengthOrPercentage> {
+pub struct Ellipse<H, V, NonNegativeLengthOrPercentage> {
pub position: Position<H, V>,
- pub semiaxis_x: ShapeRadius<LengthOrPercentage>,
- pub semiaxis_y: ShapeRadius<LengthOrPercentage>,
+ pub semiaxis_x: ShapeRadius<NonNegativeLengthOrPercentage>,
+ pub semiaxis_y: ShapeRadius<NonNegativeLengthOrPercentage>,
}
/// <https://drafts.csswg.org/css-shapes/#typedef-shape-radius>
@@ -160,11 +182,12 @@ pub struct Ellipse<H, V, LengthOrPercentage> {
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
+ ToAnimatedValue,
ToComputedValue,
ToCss,
)]
-pub enum ShapeRadius<LengthOrPercentage> {
- Length(LengthOrPercentage),
+pub enum ShapeRadius<NonNegativeLengthOrPercentage> {
+ Length(NonNegativeLengthOrPercentage),
#[animation(error)]
ClosestSide,
#[animation(error)]
@@ -175,7 +198,16 @@ pub enum ShapeRadius<LengthOrPercentage> {
///
/// <https://drafts.csswg.org/css-shapes/#funcdef-polygon>
#[css(comma, function)]
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(
+ Clone,
+ Debug,
+ MallocSizeOf,
+ PartialEq,
+ SpecifiedValueInfo,
+ ToAnimatedValue,
+ ToComputedValue,
+ ToCss,
+)]
pub struct Polygon<LengthOrPercentage> {
/// The filling rule for a polygon.
#[css(skip_if = "fill_is_default")]
@@ -186,7 +218,16 @@ pub struct Polygon<LengthOrPercentage> {
}
/// Coordinates for Polygon.
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
+#[derive(
+ Clone,
+ Debug,
+ MallocSizeOf,
+ PartialEq,
+ SpecifiedValueInfo,
+ ToAnimatedValue,
+ ToComputedValue,
+ ToCss,
+)]
pub struct PolygonCoord<LengthOrPercentage>(pub LengthOrPercentage, pub LengthOrPercentage);
// https://drafts.csswg.org/css-shapes/#typedef-fill-rule
@@ -204,6 +245,7 @@ pub struct PolygonCoord<LengthOrPercentage>(pub LengthOrPercentage, pub LengthOr
Parse,
PartialEq,
SpecifiedValueInfo,
+ ToAnimatedValue,
ToComputedValue,
ToCss,
)]
@@ -218,7 +260,15 @@ pub enum FillRule {
/// https://drafts.csswg.org/css-shapes-2/#funcdef-path
#[css(comma)]
#[derive(
- Animate, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
+ Animate,
+ Clone,
+ Debug,
+ MallocSizeOf,
+ PartialEq,
+ SpecifiedValueInfo,
+ ToAnimatedValue,
+ ToComputedValue,
+ ToCss,
)]
pub struct Path {
/// The filling rule for the svg path.
@@ -258,9 +308,10 @@ impl<B, T, U> ToAnimatedZero for ShapeSource<B, T, U> {
}
}
-impl<L> ToCss for InsetRect<L>
+impl<Length, NonNegativeLength> ToCss for InsetRect<Length, NonNegativeLength>
where
- L: ToCss + PartialEq,
+ Length: ToCss + PartialEq,
+ NonNegativeLength: ToCss + PartialEq,
{
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
diff --git a/components/style/values/generics/border.rs b/components/style/values/generics/border.rs
index 0a50721bcda..20274816615 100644
--- a/components/style/values/generics/border.rs
+++ b/components/style/values/generics/border.rs
@@ -45,6 +45,8 @@ pub struct BorderImageSlice<NumberOrPercentage> {
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
+ ToAnimatedValue,
+ ToAnimatedZero,
ToComputedValue,
ToCss,
)]
@@ -93,6 +95,7 @@ impl<L> BorderSpacing<L> {
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
+ ToAnimatedValue,
ToComputedValue,
)]
pub struct BorderRadius<LengthOrPercentage> {
@@ -106,19 +109,6 @@ pub struct BorderRadius<LengthOrPercentage> {
pub bottom_left: BorderCornerRadius<LengthOrPercentage>,
}
-impl<N> From<N> for BorderImageSlice<N>
-where
- N: Clone,
-{
- #[inline]
- fn from(value: N) -> Self {
- Self {
- offsets: Rect::all(value),
- fill: false,
- }
- }
-}
-
impl<L> BorderRadius<L> {
/// Returns a new `BorderRadius<L>`.
#[inline]
diff --git a/components/style/values/generics/position.rs b/components/style/values/generics/position.rs
index 0bde0067def..07612913c0a 100644
--- a/components/style/values/generics/position.rs
+++ b/components/style/values/generics/position.rs
@@ -15,6 +15,7 @@
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
+ ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
)]
diff --git a/components/style/values/generics/rect.rs b/components/style/values/generics/rect.rs
index dfffb3a4834..985a9c4a320 100644
--- a/components/style/values/generics/rect.rs
+++ b/components/style/values/generics/rect.rs
@@ -20,6 +20,7 @@ use style_traits::{CssWriter, ParseError, ToCss};
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
+ ToAnimatedValue,
ToComputedValue,
)]
pub struct Rect<T>(pub T, pub T, pub T, pub T);
diff --git a/components/style/values/specified/basic_shape.rs b/components/style/values/specified/basic_shape.rs
index 981cad00aaa..84624671ffe 100644
--- a/components/style/values/specified/basic_shape.rs
+++ b/components/style/values/specified/basic_shape.rs
@@ -16,8 +16,8 @@ use crate::values::specified::border::BorderRadius;
use crate::values::specified::image::Image;
use crate::values::specified::position::{HorizontalPosition, Position, VerticalPosition};
use crate::values::specified::url::SpecifiedUrl;
-use crate::values::specified::LengthOrPercentage;
use crate::values::specified::SVGPathData;
+use crate::values::specified::{LengthOrPercentage, NonNegativeLengthOrPercentage};
use cssparser::Parser;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
@@ -32,19 +32,26 @@ pub type ClippingShape = generic::ClippingShape<BasicShape, SpecifiedUrl>;
pub type FloatAreaShape = generic::FloatAreaShape<BasicShape, Image>;
/// A specified basic shape.
-pub type BasicShape = generic::BasicShape<HorizontalPosition, VerticalPosition, LengthOrPercentage>;
+pub type BasicShape = generic::BasicShape<
+ HorizontalPosition,
+ VerticalPosition,
+ LengthOrPercentage,
+ NonNegativeLengthOrPercentage,
+>;
/// The specified value of `inset()`
-pub type InsetRect = generic::InsetRect<LengthOrPercentage>;
+pub type InsetRect = generic::InsetRect<LengthOrPercentage, NonNegativeLengthOrPercentage>;
/// A specified circle.
-pub type Circle = generic::Circle<HorizontalPosition, VerticalPosition, LengthOrPercentage>;
+pub type Circle =
+ generic::Circle<HorizontalPosition, VerticalPosition, NonNegativeLengthOrPercentage>;
/// A specified ellipse.
-pub type Ellipse = generic::Ellipse<HorizontalPosition, VerticalPosition, LengthOrPercentage>;
+pub type Ellipse =
+ generic::Ellipse<HorizontalPosition, VerticalPosition, NonNegativeLengthOrPercentage>;
/// The specified value of `ShapeRadius`
-pub type ShapeRadius = generic::ShapeRadius<LengthOrPercentage>;
+pub type ShapeRadius = generic::ShapeRadius<NonNegativeLengthOrPercentage>;
/// The specified value of `Polygon`
pub type Polygon = generic::Polygon<LengthOrPercentage>;
@@ -199,10 +206,7 @@ impl InsetRect {
} else {
None
};
- Ok(generic::InsetRect {
- rect: rect,
- round: round,
- })
+ Ok(generic::InsetRect { rect, round })
}
}
@@ -312,7 +316,7 @@ impl Parse for ShapeRadius {
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
- if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
+ if let Ok(lop) = input.try(|i| NonNegativeLengthOrPercentage::parse(context, i)) {
return Ok(generic::ShapeRadius::Length(lop));
}
diff --git a/components/style/values/specified/border.rs b/components/style/values/specified/border.rs
index cf60c91b329..acd38ea5ba4 100644
--- a/components/style/values/specified/border.rs
+++ b/components/style/values/specified/border.rs
@@ -13,8 +13,8 @@ use crate::values::generics::border::BorderRadius as GenericBorderRadius;
use crate::values::generics::border::BorderSpacing as GenericBorderSpacing;
use crate::values::generics::rect::Rect;
use crate::values::generics::size::Size;
-use crate::values::specified::length::{Length, LengthOrPercentage, NonNegativeLength};
-use crate::values::specified::{AllowQuirks, Number, NumberOrPercentage};
+use crate::values::specified::length::{NonNegativeLength, NonNegativeLengthOrPercentage};
+use crate::values::specified::{AllowQuirks, NonNegativeNumber, NonNegativeNumberOrPercentage};
use cssparser::Parser;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, ToCss};
@@ -71,36 +71,53 @@ pub enum BorderSideWidth {
/// `thick`
Thick,
/// `<length>`
- Length(Length),
+ Length(NonNegativeLength),
}
/// A specified value for the `border-image-width` property.
pub type BorderImageWidth = Rect<BorderImageSideWidth>;
/// A specified value for a single side of a `border-image-width` property.
-pub type BorderImageSideWidth = GenericBorderImageSideWidth<LengthOrPercentage, Number>;
+pub type BorderImageSideWidth =
+ GenericBorderImageSideWidth<NonNegativeLengthOrPercentage, NonNegativeNumber>;
/// A specified value for the `border-image-slice` property.
-pub type BorderImageSlice = GenericBorderImageSlice<NumberOrPercentage>;
+pub type BorderImageSlice = GenericBorderImageSlice<NonNegativeNumberOrPercentage>;
/// A specified value for the `border-radius` property.
-pub type BorderRadius = GenericBorderRadius<LengthOrPercentage>;
+pub type BorderRadius = GenericBorderRadius<NonNegativeLengthOrPercentage>;
/// A specified value for the `border-*-radius` longhand properties.
-pub type BorderCornerRadius = GenericBorderCornerRadius<LengthOrPercentage>;
+pub type BorderCornerRadius = GenericBorderCornerRadius<NonNegativeLengthOrPercentage>;
/// A specified value for the `border-spacing` longhand properties.
pub type BorderSpacing = GenericBorderSpacing<NonNegativeLength>;
+impl BorderImageSlice {
+ /// Returns the `100%` value.
+ #[inline]
+ pub fn hundred_percent() -> Self {
+ GenericBorderImageSlice {
+ offsets: Rect::all(NonNegativeNumberOrPercentage::hundred_percent()),
+ fill: false,
+ }
+ }
+}
+
impl BorderSideWidth {
+ /// Returns the `0px` value.
+ #[inline]
+ pub fn zero() -> Self {
+ BorderSideWidth::Length(NonNegativeLength::zero())
+ }
+
/// Parses, with quirks.
pub fn parse_quirky<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> {
- if let Ok(length) =
- input.try(|i| Length::parse_non_negative_quirky(context, i, allow_quirks))
+ if let Ok(length) = input.try(|i| NonNegativeLength::parse_quirky(context, i, allow_quirks))
{
return Ok(BorderSideWidth::Length(length));
}
@@ -130,9 +147,9 @@ impl ToComputedValue for BorderSideWidth {
// Spec: https://drafts.csswg.org/css-backgrounds-3/#line-width
// Gecko: https://bugzilla.mozilla.org/show_bug.cgi?id=1312155#c0
match *self {
- BorderSideWidth::Thin => Length::from_px(1.).to_computed_value(context),
- BorderSideWidth::Medium => Length::from_px(3.).to_computed_value(context),
- BorderSideWidth::Thick => Length::from_px(5.).to_computed_value(context),
+ BorderSideWidth::Thin => NonNegativeLength::from_px(1.).to_computed_value(context),
+ BorderSideWidth::Medium => NonNegativeLength::from_px(3.).to_computed_value(context),
+ BorderSideWidth::Thick => NonNegativeLength::from_px(5.).to_computed_value(context),
BorderSideWidth::Length(ref length) => length.to_computed_value(context),
}
.into()
@@ -140,7 +157,7 @@ impl ToComputedValue for BorderSideWidth {
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
- BorderSideWidth::Length(ToComputedValue::from_computed_value(&computed.0))
+ BorderSideWidth::Length(ToComputedValue::from_computed_value(computed))
}
}
@@ -148,7 +165,7 @@ impl BorderImageSideWidth {
/// Returns `1`.
#[inline]
pub fn one() -> Self {
- GenericBorderImageSideWidth::Number(Number::new(1.))
+ GenericBorderImageSideWidth::Number(NonNegativeNumber::new(1.))
}
}
@@ -161,11 +178,11 @@ impl Parse for BorderImageSideWidth {
return Ok(GenericBorderImageSideWidth::Auto);
}
- if let Ok(len) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
+ if let Ok(len) = input.try(|i| NonNegativeLengthOrPercentage::parse(context, i)) {
return Ok(GenericBorderImageSideWidth::Length(len));
}
- let num = Number::parse_non_negative(context, input)?;
+ let num = NonNegativeNumber::parse(context, input)?;
Ok(GenericBorderImageSideWidth::Number(num))
}
}
@@ -176,14 +193,11 @@ impl Parse for BorderImageSlice {
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let mut fill = input.try(|i| i.expect_ident_matching("fill")).is_ok();
- let offsets = Rect::parse_with(context, input, NumberOrPercentage::parse_non_negative)?;
+ let offsets = Rect::parse_with(context, input, NonNegativeNumberOrPercentage::parse)?;
if !fill {
fill = input.try(|i| i.expect_ident_matching("fill")).is_ok();
}
- Ok(GenericBorderImageSlice {
- offsets: offsets,
- fill: fill,
- })
+ Ok(GenericBorderImageSlice { offsets, fill })
}
}
@@ -192,9 +206,9 @@ impl Parse for BorderRadius {
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
- let widths = Rect::parse_with(context, input, LengthOrPercentage::parse_non_negative)?;
+ let widths = Rect::parse_with(context, input, NonNegativeLengthOrPercentage::parse)?;
let heights = if input.try(|i| i.expect_delim('/')).is_ok() {
- Rect::parse_with(context, input, LengthOrPercentage::parse_non_negative)?
+ Rect::parse_with(context, input, NonNegativeLengthOrPercentage::parse)?
} else {
widths.clone()
};
@@ -213,7 +227,7 @@ impl Parse for BorderCornerRadius {
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
- Size::parse_with(context, input, LengthOrPercentage::parse_non_negative)
+ Size::parse_with(context, input, NonNegativeLengthOrPercentage::parse)
.map(GenericBorderCornerRadius)
}
}
@@ -224,7 +238,7 @@ impl Parse for BorderSpacing {
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
Size::parse_with(context, input, |context, input| {
- Length::parse_non_negative_quirky(context, input, AllowQuirks::Yes).map(From::from)
+ NonNegativeLength::parse_quirky(context, input, AllowQuirks::Yes).map(From::from)
})
.map(GenericBorderSpacing)
}
diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs
index 13877dbe594..e64385472a0 100644
--- a/components/style/values/specified/length.rs
+++ b/components/style/values/specified/length.rs
@@ -717,6 +717,20 @@ impl NonNegativeLength {
pub fn from_px(px_value: CSSFloat) -> Self {
Length::from_px(px_value.max(0.)).into()
}
+
+ /// Parses a non-negative length, optionally with quirks.
+ #[inline]
+ pub fn parse_quirky<'i, 't>(
+ context: &ParserContext,
+ input: &mut Parser<'i, 't>,
+ allow_quirks: AllowQuirks,
+ ) -> Result<Self, ParseError<'i>> {
+ Ok(NonNegative(Length::parse_non_negative_quirky(
+ context,
+ input,
+ allow_quirks,
+ )?))
+ }
}
/// Either a NonNegativeLength or the `auto` keyword.
@@ -1246,17 +1260,6 @@ impl Parse for MozLength {
}
impl MozLength {
- /// Parses, without quirks, and disallowing ExtremumLength values.
- ///
- /// Used for logical props in the block direction.
- pub fn parse_disallow_keyword<'i, 't>(
- context: &ParserContext,
- input: &mut Parser<'i, 't>,
- ) -> Result<Self, ParseError<'i>> {
- let length = LengthOrPercentageOrAuto::parse_non_negative(context, input)?;
- Ok(GenericMozLength::LengthOrPercentageOrAuto(length))
- }
-
/// Parses, with quirks.
pub fn parse_quirky<'i, 't>(
context: &ParserContext,
@@ -1298,17 +1301,6 @@ impl Parse for MaxLength {
}
impl MaxLength {
- /// Parses, without quirks, and disallowing ExtremumLength values.
- ///
- /// Used for logical props in the block direction.
- pub fn parse_disallow_keyword<'i, 't>(
- context: &ParserContext,
- input: &mut Parser<'i, 't>,
- ) -> Result<Self, ParseError<'i>> {
- let length = LengthOrPercentageOrNone::parse_non_negative(context, input)?;
- Ok(GenericMaxLength::LengthOrPercentageOrNone(length))
- }
-
/// Parses, with quirks.
pub fn parse_quirky<'i, 't>(
context: &ParserContext,
diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs
index d3df66a0eea..17d1ea04186 100644
--- a/components/style/values/specified/mod.rs
+++ b/components/style/values/specified/mod.rs
@@ -359,6 +359,28 @@ impl Parse for NumberOrPercentage {
}
}
+/// A non-negative <number> | <percentage>.
+pub type NonNegativeNumberOrPercentage = NonNegative<NumberOrPercentage>;
+
+impl NonNegativeNumberOrPercentage {
+ /// Returns the `100%` value.
+ #[inline]
+ pub fn hundred_percent() -> Self {
+ NonNegative(NumberOrPercentage::Percentage(Percentage::hundred()))
+ }
+}
+
+impl Parse for NonNegativeNumberOrPercentage {
+ fn parse<'i, 't>(
+ context: &ParserContext,
+ input: &mut Parser<'i, 't>,
+ ) -> Result<Self, ParseError<'i>> {
+ Ok(NonNegative(NumberOrPercentage::parse_non_negative(
+ context, input,
+ )?))
+ }
+}
+
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, SpecifiedValueInfo, ToCss)]
pub struct Opacity(Number);
diff --git a/tests/unit/style/properties/serialization.rs b/tests/unit/style/properties/serialization.rs
index 38326dcd1fd..035f9a9385c 100644
--- a/tests/unit/style/properties/serialization.rs
+++ b/tests/unit/style/properties/serialization.rs
@@ -10,9 +10,7 @@ use style::properties::parse_property_declaration_list;
use style::properties::{Importance, PropertyDeclaration};
use style::values::specified::url::SpecifiedUrl;
use style::values::specified::NoCalcLength;
-use style::values::specified::{BorderSideWidth, BorderStyle, Color};
use style::values::specified::{Length, LengthOrPercentage, LengthOrPercentageOrAuto};
-use style::values::RGBA;
use style_traits::ToCss;
trait ToCssString {
@@ -83,408 +81,6 @@ mod shorthand_serialization {
block.to_css_string()
}
- mod four_sides_shorthands {
- pub use super::*;
-
- // we can use margin as a base to test out the different combinations
- // but afterwards, we only need to to one test per "four sides shorthand"
- #[test]
- fn all_equal_properties_should_serialize_to_one_value() {
- let mut properties = Vec::new();
-
- let px_70 = LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(70f32));
- properties.push(PropertyDeclaration::MarginTop(px_70.clone()));
- properties.push(PropertyDeclaration::MarginRight(px_70.clone()));
- properties.push(PropertyDeclaration::MarginBottom(px_70.clone()));
- properties.push(PropertyDeclaration::MarginLeft(px_70));
-
- let serialization = shorthand_properties_to_string(properties);
- assert_eq!(serialization, "margin: 70px;");
- }
-
- #[test]
- fn equal_vertical_and_equal_horizontal_properties_should_serialize_to_two_value() {
- let mut properties = Vec::new();
-
- let vertical_px = LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(10f32));
- let horizontal_px = LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(5f32));
-
- properties.push(PropertyDeclaration::MarginTop(vertical_px.clone()));
- properties.push(PropertyDeclaration::MarginRight(horizontal_px.clone()));
- properties.push(PropertyDeclaration::MarginBottom(vertical_px));
- properties.push(PropertyDeclaration::MarginLeft(horizontal_px));
-
- let serialization = shorthand_properties_to_string(properties);
- assert_eq!(serialization, "margin: 10px 5px;");
- }
-
- #[test]
- fn different_vertical_and_equal_horizontal_properties_should_serialize_to_three_values() {
- let mut properties = Vec::new();
-
- let top_px = LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(8f32));
- let bottom_px = LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(10f32));
- let horizontal_px = LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(5f32));
-
- properties.push(PropertyDeclaration::MarginTop(top_px));
- properties.push(PropertyDeclaration::MarginRight(horizontal_px.clone()));
- properties.push(PropertyDeclaration::MarginBottom(bottom_px));
- properties.push(PropertyDeclaration::MarginLeft(horizontal_px));
-
- let serialization = shorthand_properties_to_string(properties);
- assert_eq!(serialization, "margin: 8px 5px 10px;");
- }
-
- #[test]
- fn different_properties_should_serialize_to_four_values() {
- let mut properties = Vec::new();
-
- let top_px = LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(8f32));
- let right_px = LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(12f32));
- let bottom_px = LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(10f32));
- let left_px = LengthOrPercentageOrAuto::Length(NoCalcLength::from_px(14f32));
-
- properties.push(PropertyDeclaration::MarginTop(top_px));
- properties.push(PropertyDeclaration::MarginRight(right_px));
- properties.push(PropertyDeclaration::MarginBottom(bottom_px));
- properties.push(PropertyDeclaration::MarginLeft(left_px));
-
- let serialization = shorthand_properties_to_string(properties);
- assert_eq!(serialization, "margin: 8px 12px 10px 14px;");
- }
-
- #[test]
- fn different_longhands_should_serialize_to_long_form() {
- let mut properties = Vec::new();
-
- let solid = BorderStyle::Solid;
-
- properties.push(PropertyDeclaration::BorderTopStyle(solid.clone()));
- properties.push(PropertyDeclaration::BorderRightStyle(solid.clone()));
- properties.push(PropertyDeclaration::BorderBottomStyle(solid.clone()));
- properties.push(PropertyDeclaration::BorderLeftStyle(solid.clone()));
-
- let px_30 = BorderSideWidth::Length(Length::from_px(30f32));
- let px_10 = BorderSideWidth::Length(Length::from_px(10f32));
-
- properties.push(PropertyDeclaration::BorderTopWidth(px_30.clone()));
- properties.push(PropertyDeclaration::BorderRightWidth(px_30.clone()));
- properties.push(PropertyDeclaration::BorderBottomWidth(px_30.clone()));
- properties.push(PropertyDeclaration::BorderLeftWidth(px_10.clone()));
-
- let blue = Color::rgba(RGBA::new(0, 0, 255, 255));
-
- properties.push(PropertyDeclaration::BorderTopColor(blue.clone()));
- properties.push(PropertyDeclaration::BorderRightColor(blue.clone()));
- properties.push(PropertyDeclaration::BorderBottomColor(blue.clone()));
- properties.push(PropertyDeclaration::BorderLeftColor(blue.clone()));
-
- let serialization = shorthand_properties_to_string(properties);
- assert_eq!(serialization,
- "border-style: solid; border-width: 30px 30px 30px 10px; border-color: rgb(0, 0, 255);");
- }
-
- #[test]
- fn same_longhands_should_serialize_correctly() {
- let mut properties = Vec::new();
-
- let solid = BorderStyle::Solid;
-
- properties.push(PropertyDeclaration::BorderTopStyle(solid.clone()));
- properties.push(PropertyDeclaration::BorderRightStyle(solid.clone()));
- properties.push(PropertyDeclaration::BorderBottomStyle(solid.clone()));
- properties.push(PropertyDeclaration::BorderLeftStyle(solid.clone()));
-
- let px_30 = BorderSideWidth::Length(Length::from_px(30f32));
-
- properties.push(PropertyDeclaration::BorderTopWidth(px_30.clone()));
- properties.push(PropertyDeclaration::BorderRightWidth(px_30.clone()));
- properties.push(PropertyDeclaration::BorderBottomWidth(px_30.clone()));
- properties.push(PropertyDeclaration::BorderLeftWidth(px_30.clone()));
-
- let blue = Color::rgba(RGBA::new(0, 0, 255, 255));
-
- properties.push(PropertyDeclaration::BorderTopColor(blue.clone()));
- properties.push(PropertyDeclaration::BorderRightColor(blue.clone()));
- properties.push(PropertyDeclaration::BorderBottomColor(blue.clone()));
- properties.push(PropertyDeclaration::BorderLeftColor(blue.clone()));
-
- let serialization = shorthand_properties_to_string(properties);
- assert_eq!(
- serialization,
- "border-style: solid; border-width: 30px; border-color: rgb(0, 0, 255);"
- );
- }
-
- #[test]
- fn padding_should_serialize_correctly() {
- use style::values::specified::NonNegativeLengthOrPercentage;
-
- let mut properties = Vec::new();
-
- let px_10: NonNegativeLengthOrPercentage = NoCalcLength::from_px(10f32).into();
- let px_15: NonNegativeLengthOrPercentage = NoCalcLength::from_px(15f32).into();
- properties.push(PropertyDeclaration::PaddingTop(px_10.clone()));
- properties.push(PropertyDeclaration::PaddingRight(px_15.clone()));
- properties.push(PropertyDeclaration::PaddingBottom(px_10));
- properties.push(PropertyDeclaration::PaddingLeft(px_15));
-
- let serialization = shorthand_properties_to_string(properties);
- assert_eq!(serialization, "padding: 10px 15px;");
- }
-
- #[test]
- fn border_width_should_serialize_correctly() {
- let mut properties = Vec::new();
-
- let top_px = BorderSideWidth::Length(Length::from_px(10f32));
- let bottom_px = BorderSideWidth::Length(Length::from_px(10f32));
-
- let right_px = BorderSideWidth::Length(Length::from_px(15f32));
- let left_px = BorderSideWidth::Length(Length::from_px(15f32));
-
- properties.push(PropertyDeclaration::BorderTopWidth(top_px));
- properties.push(PropertyDeclaration::BorderRightWidth(right_px));
- properties.push(PropertyDeclaration::BorderBottomWidth(bottom_px));
- properties.push(PropertyDeclaration::BorderLeftWidth(left_px));
-
- let serialization = shorthand_properties_to_string(properties);
- assert_eq!(serialization, "border-width: 10px 15px;");
- }
-
- #[test]
- fn border_width_with_keywords_should_serialize_correctly() {
- let mut properties = Vec::new();
-
- let top_px = BorderSideWidth::Thin;
- let right_px = BorderSideWidth::Medium;
- let bottom_px = BorderSideWidth::Thick;
- let left_px = BorderSideWidth::Length(Length::from_px(15f32));
-
- properties.push(PropertyDeclaration::BorderTopWidth(top_px));
- properties.push(PropertyDeclaration::BorderRightWidth(right_px));
- properties.push(PropertyDeclaration::BorderBottomWidth(bottom_px));
- properties.push(PropertyDeclaration::BorderLeftWidth(left_px));
-
- let serialization = shorthand_properties_to_string(properties);
- assert_eq!(serialization, "border-width: thin medium thick 15px;");
- }
-
- #[test]
- fn border_color_should_serialize_correctly() {
- let mut properties = Vec::new();
-
- let red = Color::rgba(RGBA::new(255, 0, 0, 255));
- let blue = Color::rgba(RGBA::new(0, 0, 255, 255));
-
- properties.push(PropertyDeclaration::BorderTopColor(blue.clone()));
- properties.push(PropertyDeclaration::BorderRightColor(red.clone()));
- properties.push(PropertyDeclaration::BorderBottomColor(blue));
- properties.push(PropertyDeclaration::BorderLeftColor(red));
-
- let serialization = shorthand_properties_to_string(properties);
-
- // TODO: Make the rgb test show border-color as blue red instead of below tuples
- assert_eq!(
- serialization,
- "border-color: rgb(0, 0, 255) rgb(255, 0, 0);"
- );
- }
-
- #[test]
- fn border_style_should_serialize_correctly() {
- let mut properties = Vec::new();
-
- let solid = BorderStyle::Solid;
- let dotted = BorderStyle::Dotted;
- properties.push(PropertyDeclaration::BorderTopStyle(solid.clone()));
- properties.push(PropertyDeclaration::BorderRightStyle(dotted.clone()));
- properties.push(PropertyDeclaration::BorderBottomStyle(solid));
- properties.push(PropertyDeclaration::BorderLeftStyle(dotted));
-
- let serialization = shorthand_properties_to_string(properties);
- assert_eq!(serialization, "border-style: solid dotted;");
- }
-
- use style::values::specified::{BorderCornerRadius, Percentage};
-
- #[test]
- fn border_radius_should_serialize_correctly() {
- let mut properties = Vec::new();
- properties.push(PropertyDeclaration::BorderTopLeftRadius(Box::new(
- BorderCornerRadius::new(Percentage::new(0.01).into(), Percentage::new(0.05).into()),
- )));
- properties.push(PropertyDeclaration::BorderTopRightRadius(Box::new(
- BorderCornerRadius::new(Percentage::new(0.02).into(), Percentage::new(0.06).into()),
- )));
- properties.push(PropertyDeclaration::BorderBottomRightRadius(Box::new(
- BorderCornerRadius::new(Percentage::new(0.03).into(), Percentage::new(0.07).into()),
- )));
- properties.push(PropertyDeclaration::BorderBottomLeftRadius(Box::new(
- BorderCornerRadius::new(Percentage::new(0.04).into(), Percentage::new(0.08).into()),
- )));
-
- let serialization = shorthand_properties_to_string(properties);
- assert_eq!(serialization, "border-radius: 1% 2% 3% 4% / 5% 6% 7% 8%;");
- }
- }
-
- mod border_shorthands {
- use super::*;
-
- #[test]
- fn border_top_and_color() {
- let mut properties = Vec::new();
- properties.push(PropertyDeclaration::BorderTopWidth(
- BorderSideWidth::Length(Length::from_px(1.)),
- ));
- properties.push(PropertyDeclaration::BorderTopStyle(BorderStyle::Solid));
- let c = Color::Numeric {
- parsed: RGBA::new(255, 0, 0, 255),
- authored: Some("green".to_string().into_boxed_str()),
- };
- properties.push(PropertyDeclaration::BorderTopColor(c));
- let c = Color::Numeric {
- parsed: RGBA::new(0, 255, 0, 255),
- authored: Some("red".to_string().into_boxed_str()),
- };
- properties.push(PropertyDeclaration::BorderTopColor(c.clone()));
- properties.push(PropertyDeclaration::BorderBottomColor(c.clone()));
- properties.push(PropertyDeclaration::BorderLeftColor(c.clone()));
- properties.push(PropertyDeclaration::BorderRightColor(c.clone()));
-
- let serialization = shorthand_properties_to_string(properties);
- assert_eq!(
- serialization,
- "border-top: 1px solid red; border-color: red;"
- );
- }
-
- #[test]
- fn border_color_and_top() {
- let mut properties = Vec::new();
- let c = Color::Numeric {
- parsed: RGBA::new(0, 255, 0, 255),
- authored: Some("red".to_string().into_boxed_str()),
- };
- properties.push(PropertyDeclaration::BorderTopColor(c.clone()));
- properties.push(PropertyDeclaration::BorderBottomColor(c.clone()));
- properties.push(PropertyDeclaration::BorderLeftColor(c.clone()));
- properties.push(PropertyDeclaration::BorderRightColor(c.clone()));
-
- properties.push(PropertyDeclaration::BorderTopWidth(
- BorderSideWidth::Length(Length::from_px(1.)),
- ));
- properties.push(PropertyDeclaration::BorderTopStyle(BorderStyle::Solid));
- let c = Color::Numeric {
- parsed: RGBA::new(255, 0, 0, 255),
- authored: Some("green".to_string().into_boxed_str()),
- };
- properties.push(PropertyDeclaration::BorderTopColor(c));
-
- let serialization = shorthand_properties_to_string(properties);
- assert_eq!(
- serialization,
- "border-color: green red red; border-top: 1px solid green;"
- );
- }
-
- // we can use border-top as a base to test out the different combinations
- // but afterwards, we only need to to one test per "directional border shorthand"
-
- #[test]
- fn directional_border_should_show_all_properties_when_values_are_set() {
- let mut properties = Vec::new();
-
- let width = BorderSideWidth::Length(Length::from_px(4f32));
- let style = BorderStyle::Solid;
- let color = RGBA::new(255, 0, 0, 255).into();
-
- properties.push(PropertyDeclaration::BorderTopWidth(width));
- properties.push(PropertyDeclaration::BorderTopStyle(style));
- properties.push(PropertyDeclaration::BorderTopColor(color));
-
- let serialization = shorthand_properties_to_string(properties);
- assert_eq!(serialization, "border-top: 4px solid rgb(255, 0, 0);");
- }
-
- fn get_border_property_values() -> (BorderSideWidth, BorderStyle, Color) {
- (
- BorderSideWidth::Length(Length::from_px(4f32)),
- BorderStyle::Solid,
- Color::currentcolor(),
- )
- }
-
- #[test]
- fn border_top_should_serialize_correctly() {
- let mut properties = Vec::new();
- let (width, style, color) = get_border_property_values();
- properties.push(PropertyDeclaration::BorderTopWidth(width));
- properties.push(PropertyDeclaration::BorderTopStyle(style));
- properties.push(PropertyDeclaration::BorderTopColor(color));
-
- let serialization = shorthand_properties_to_string(properties);
- assert_eq!(serialization, "border-top: 4px solid;");
- }
-
- #[test]
- fn border_right_should_serialize_correctly() {
- let mut properties = Vec::new();
- let (width, style, color) = get_border_property_values();
- properties.push(PropertyDeclaration::BorderRightWidth(width));
- properties.push(PropertyDeclaration::BorderRightStyle(style));
- properties.push(PropertyDeclaration::BorderRightColor(color));
-
- let serialization = shorthand_properties_to_string(properties);
- assert_eq!(serialization, "border-right: 4px solid;");
- }
-
- #[test]
- fn border_bottom_should_serialize_correctly() {
- let mut properties = Vec::new();
- let (width, style, color) = get_border_property_values();
- properties.push(PropertyDeclaration::BorderBottomWidth(width));
- properties.push(PropertyDeclaration::BorderBottomStyle(style));
- properties.push(PropertyDeclaration::BorderBottomColor(color));
-
- let serialization = shorthand_properties_to_string(properties);
- assert_eq!(serialization, "border-bottom: 4px solid;");
- }
-
- #[test]
- fn border_left_should_serialize_correctly() {
- let mut properties = Vec::new();
- let (width, style, color) = get_border_property_values();
- properties.push(PropertyDeclaration::BorderLeftWidth(width));
- properties.push(PropertyDeclaration::BorderLeftStyle(style));
- properties.push(PropertyDeclaration::BorderLeftColor(color));
-
- let serialization = shorthand_properties_to_string(properties);
- assert_eq!(serialization, "border-left: 4px solid;");
- }
-
- #[test]
- fn border_should_serialize_correctly() {
- // According to https://drafts.csswg.org/css-backgrounds-3/#the-border-shorthands,
- // the ‘border’ shorthand resets ‘border-image’ to its initial value. To verify the
- // serialization of 'border' shorthand, we need to set 'border-image' as well.
- let block_text = "\
- border-top: 4px solid; \
- border-right: 4px solid; \
- border-bottom: 4px solid; \
- border-left: 4px solid; \
- border-image: none;";
-
- let block =
- parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
-
- let serialization = block.to_css_string();
-
- assert_eq!(serialization, "border: 4px solid;");
- }
- }
-
mod list_style {
use super::*;
use style::properties::longhands::list_style_position::SpecifiedValue as ListStylePosition;