aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2019-03-13 10:26:37 -0400
committerGitHub <noreply@github.com>2019-03-13 10:26:37 -0400
commitd5fb0666d1102dd197e6ca478b3cf730397a7d38 (patch)
treeba85ff8131ef6889c3ae67e629d534d1f931e86f
parentc12e341c0ce9fcd8c3f71905b9b379af802bff04 (diff)
parentb42342a27381d644f5817eb4530252c4c142d4e9 (diff)
downloadservo-d5fb0666d1102dd197e6ca478b3cf730397a7d38.tar.gz
servo-d5fb0666d1102dd197e6ca478b3cf730397a7d38.zip
Auto merge of #23017 - emilio:gecko-sync, r=emilio
style: Sync changes from mozilla-central. See each individual commit for details. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23017) <!-- Reviewable:end -->
-rw-r--r--components/layout/display_list/builder.rs21
-rw-r--r--components/layout/fragment.rs1
-rw-r--r--components/layout/multicol.rs6
-rw-r--r--components/layout/text.rs21
-rw-r--r--components/style/cbindgen.toml23
-rw-r--r--components/style/custom_properties.rs30
-rw-r--r--components/style/gecko/conversions.rs69
-rw-r--r--components/style/gecko/data.rs13
-rw-r--r--components/style/gecko/media_features.rs13
-rw-r--r--components/style/gecko/media_queries.rs113
-rw-r--r--components/style/gecko/values.rs2
-rw-r--r--components/style/gecko/wrapper.rs9
-rw-r--r--components/style/gecko_bindings/sugar/ns_css_value.rs1
-rw-r--r--components/style/gecko_bindings/sugar/ns_style_coord.rs60
-rw-r--r--components/style/lib.rs23
-rw-r--r--components/style/media_queries/media_feature_expression.rs3
-rw-r--r--components/style/properties/cascade.rs58
-rw-r--r--components/style/properties/data.py1
-rw-r--r--components/style/properties/declaration_block.rs2
-rw-r--r--components/style/properties/gecko.mako.rs435
-rw-r--r--components/style/properties/helpers.mako.rs23
-rw-r--r--components/style/properties/helpers/animated_properties.mako.rs37
-rw-r--r--components/style/properties/longhands/column.mako.rs4
-rw-r--r--components/style/properties/longhands/inherited_svg.mako.rs9
-rw-r--r--components/style/properties/longhands/inherited_text.mako.rs10
-rw-r--r--components/style/properties/longhands/padding.mako.rs2
-rw-r--r--components/style/properties/properties.mako.rs36
-rw-r--r--components/style/rule_tree/mod.rs21
-rw-r--r--components/style/stylesheets/origin.rs32
-rw-r--r--components/style/traversal.rs2
-rw-r--r--components/style/values/animated/mod.rs22
-rw-r--r--components/style/values/animated/svg.rs98
-rw-r--r--components/style/values/animated/transform.rs34
-rw-r--r--components/style/values/computed/angle.rs2
-rw-r--r--components/style/values/computed/border.rs31
-rw-r--r--components/style/values/computed/length.rs66
-rw-r--r--components/style/values/computed/mod.rs56
-rw-r--r--components/style/values/computed/percentage.rs23
-rw-r--r--components/style/values/computed/position.rs1
-rw-r--r--components/style/values/computed/svg.rs43
-rw-r--r--components/style/values/computed/text.rs79
-rw-r--r--components/style/values/computed/transform.rs25
-rw-r--r--components/style/values/generics/background.rs40
-rw-r--r--components/style/values/generics/basic_shape.rs9
-rw-r--r--components/style/values/generics/border.rs72
-rw-r--r--components/style/values/generics/length.rs32
-rw-r--r--components/style/values/generics/mod.rs25
-rw-r--r--components/style/values/generics/size.rs63
-rw-r--r--components/style/values/generics/svg.rs54
-rw-r--r--components/style/values/generics/text.rs64
-rw-r--r--components/style/values/generics/transform.rs121
-rw-r--r--components/style/values/mod.rs2
-rw-r--r--components/style/values/specified/angle.rs40
-rw-r--r--components/style/values/specified/basic_shape.rs5
-rw-r--r--components/style/values/specified/border.rs7
-rw-r--r--components/style/values/specified/box.rs20
-rw-r--r--components/style/values/specified/color.rs12
-rw-r--r--components/style/values/specified/effects.rs1
-rw-r--r--components/style/values/specified/length.rs115
-rw-r--r--components/style/values/specified/mod.rs137
-rw-r--r--components/style/values/specified/position.rs1
-rw-r--r--components/style/values/specified/svg.rs68
-rw-r--r--components/style/values/specified/text.rs27
-rw-r--r--components/style/values/specified/transform.rs13
-rw-r--r--components/style_derive/cg.rs64
-rw-r--r--components/style_derive/to_animated_value.rs6
-rw-r--r--components/style_derive/to_computed_value.rs6
-rw-r--r--components/style_derive/to_css.rs22
-rw-r--r--components/style_traits/values.rs4
-rw-r--r--tests/unit/style/animated_properties.rs50
-rw-r--r--tests/unit/style/custom_properties.rs16
-rw-r--r--tests/wpt/metadata/css/css-text/inheritance.html.ini3
-rw-r--r--tests/wpt/metadata/css/css-variables/variable-definition-keywords.html.ini7
-rw-r--r--tests/wpt/metadata/css/css-variables/variable-presentation-attribute.html.ini3
74 files changed, 1144 insertions, 1525 deletions
diff --git a/components/layout/display_list/builder.rs b/components/layout/display_list/builder.rs
index d26cd6b9c32..73343c3a4f2 100644
--- a/components/layout/display_list/builder.rs
+++ b/components/layout/display_list/builder.rs
@@ -58,7 +58,7 @@ use style::properties::{style_structs, ComputedValues};
use style::servo::restyle_damage::ServoRestyleDamage;
use style::values::computed::effects::SimpleShadow;
use style::values::computed::image::Image as ComputedImage;
-use style::values::computed::Gradient;
+use style::values::computed::{Gradient, LengthOrAuto};
use style::values::generics::background::BackgroundSize;
use style::values::generics::image::{GradientKind, Image, PaintWorklet};
use style::values::specified::ui::CursorKind;
@@ -2627,19 +2627,22 @@ impl BlockFlow {
_ => return,
}
+ fn extract_clip_component(p: &LengthOrAuto) -> Option<Au> {
+ match *p {
+ LengthOrAuto::Auto => None,
+ LengthOrAuto::LengthPercentage(ref length) => Some(Au::from(*length)),
+ }
+ }
+
let clip_origin = Point2D::new(
stacking_relative_border_box.origin.x +
- style_clip_rect.left.map(Au::from).unwrap_or(Au(0)),
+ extract_clip_component(&style_clip_rect.left).unwrap_or_default(),
stacking_relative_border_box.origin.y +
- style_clip_rect.top.map(Au::from).unwrap_or(Au(0)),
+ extract_clip_component(&style_clip_rect.top).unwrap_or_default(),
);
- let right = style_clip_rect
- .right
- .map(Au::from)
+ let right = extract_clip_component(&style_clip_rect.right)
.unwrap_or(stacking_relative_border_box.size.width);
- let bottom = style_clip_rect
- .bottom
- .map(Au::from)
+ let bottom = extract_clip_component(&style_clip_rect.bottom)
.unwrap_or(stacking_relative_border_box.size.height);
let clip_size = Size2D::new(right - clip_origin.x, bottom - clip_origin.y);
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index d8183eae1c9..ff62cc79638 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -64,6 +64,7 @@ use style::values::computed::counters::ContentItem;
use style::values::computed::{LengthPercentage, LengthPercentageOrAuto, Size};
use style::values::generics::box_::{Perspective, VerticalAlign};
use style::values::generics::transform;
+use style::Zero;
use webrender_api::{self, LayoutTransform};
// From gfxFontConstants.h in Firefox.
diff --git a/components/layout/multicol.rs b/components/layout/multicol.rs
index ca92c200d40..f8ddfa8200c 100644
--- a/components/layout/multicol.rs
+++ b/components/layout/multicol.rs
@@ -19,7 +19,7 @@ use std::fmt;
use std::sync::Arc;
use style::logical_geometry::LogicalSize;
use style::properties::ComputedValues;
-use style::values::computed::{MaxSize, Size};
+use style::values::computed::length::{MaxSize, NonNegativeLengthOrAuto, Size};
use style::values::generics::column::ColumnCount;
use style::values::Either;
@@ -114,7 +114,9 @@ impl Flow for MulticolFlow {
let column_style = style.get_column();
let mut column_count;
- if let Either::First(column_width) = column_style.column_width {
+ if let NonNegativeLengthOrAuto::LengthPercentage(column_width) =
+ column_style.column_width
+ {
let column_width = Au::from(column_width);
column_count = max(
1,
diff --git a/components/layout/text.rs b/components/layout/text.rs
index aba5703a1c6..b26e531e670 100644
--- a/components/layout/text.rs
+++ b/components/layout/text.rs
@@ -14,7 +14,6 @@ use gfx::font::{FontMetrics, FontRef, RunMetrics, ShapingFlags, ShapingOptions};
use gfx::text::glyph::ByteIndex;
use gfx::text::text_run::TextRun;
use gfx::text::util::{self, CompressionMode};
-use ordered_float::NotNan;
use range::Range;
use servo_atoms::Atom;
use std::borrow::ToOwned;
@@ -196,11 +195,7 @@ impl TextRunScanner {
};
text_transform = inherited_text_style.text_transform;
letter_spacing = inherited_text_style.letter_spacing;
- word_spacing = inherited_text_style
- .word_spacing
- .value()
- .map(|lop| lop.to_hash_key())
- .unwrap_or((Au(0), NotNan::new(0.0).unwrap()));
+ word_spacing = inherited_text_style.word_spacing.to_hash_key();
text_rendering = inherited_text_style.text_rendering;
word_break = inherited_text_style.word_break;
}
@@ -321,10 +316,8 @@ impl TextRunScanner {
// example, `finally` with a wide `letter-spacing` renders as `f i n a l l y` and not
// `fi n a l l y`.
let mut flags = ShapingFlags::empty();
- if let Some(v) = letter_spacing.value() {
- if v.px() != 0. {
- flags.insert(ShapingFlags::IGNORE_LIGATURES_SHAPING_FLAG);
- }
+ if letter_spacing.0.px() != 0. {
+ flags.insert(ShapingFlags::IGNORE_LIGATURES_SHAPING_FLAG);
}
if text_rendering == TextRendering::Optimizespeed {
flags.insert(ShapingFlags::IGNORE_LIGATURES_SHAPING_FLAG);
@@ -334,8 +327,12 @@ impl TextRunScanner {
flags.insert(ShapingFlags::KEEP_ALL_FLAG);
}
let options = ShapingOptions {
- letter_spacing: letter_spacing.value().cloned().map(Au::from),
- word_spacing: word_spacing,
+ letter_spacing: if letter_spacing.0.px() == 0. {
+ None
+ } else {
+ Some(Au::from(letter_spacing.0))
+ },
+ word_spacing,
script: Script::Common,
flags: flags,
};
diff --git a/components/style/cbindgen.toml b/components/style/cbindgen.toml
index 0b8719c4dbf..5de390cc8a6 100644
--- a/components/style/cbindgen.toml
+++ b/components/style/cbindgen.toml
@@ -13,6 +13,7 @@ autogen_warning = """/* DO NOT MODIFY THIS MANUALLY! This file was generated usi
class nsAtom;
namespace mozilla {
class WritingMode;
+ enum HalfCorner : uint8_t;
enum LogicalSide : uint8_t;
namespace css {
struct URLValue;
@@ -39,8 +40,13 @@ include = ["cssparser", "style_traits"]
derive_eq = true
derive_neq = true
+[macro_expansion]
+bitflags = true
+
[enum]
derive_helper_methods = true
+derive_const_casts = true
+cast_assert_name = "MOZ_ASSERT"
[export]
prefix = "Style"
@@ -77,8 +83,10 @@ include = [
"Resize",
"Overflow",
"LengthPercentage",
+ "LetterSpacing",
"NonNegativeLengthPercentage",
"LengthPercentageOrAuto",
+ "LineHeight",
"NonNegativeLengthPercentageOrAuto",
"Rect",
"IntersectionObserverRootMargin",
@@ -88,16 +96,20 @@ include = [
"Position",
"BackgroundSize",
"BorderImageSlice",
+ "BorderSpacing",
+ "BorderRadius",
"NonNegativeLengthOrNumberRect",
"Perspective",
"ZIndex",
"TransformOrigin",
+ "WordBreak",
]
item_types = ["enums", "structs", "typedefs"]
[export.body]
"CSSPixelLength" = """
inline nscoord ToAppUnits() const;
+ inline bool IsZero() const;
"""
"LengthPercentage" = """
@@ -114,6 +126,7 @@ item_types = ["enums", "structs", "typedefs"]
inline bool ConvertsToPercentage() const;
inline bool HasLengthAndPercentage() const;
inline float ToPercentage() const;
+ inline bool IsDefinitelyZero() const;
inline CSSCoord ResolveToCSSPixels(CSSCoord aPercentageBasisInCSSPixels) const;
template<typename T> inline CSSCoord ResolveToCSSPixelsWith(T aPercentageGetter) const;
template<typename T, typename U>
@@ -125,7 +138,6 @@ item_types = ["enums", "structs", "typedefs"]
"""
"GenericLengthPercentageOrAuto" = """
- inline const StyleLengthPercentage& AsLengthPercentage() const;
inline bool ConvertsToLength() const;
inline nscoord ToLength() const;
inline bool ConvertsToPercentage() const;
@@ -135,8 +147,6 @@ item_types = ["enums", "structs", "typedefs"]
"""
"GenericSize" = """
- inline const StyleLengthPercentage& AsLengthPercentage() const;
- inline StyleExtremumLength AsExtremumLength() const;
inline bool ConvertsToLength() const;
inline nscoord ToLength() const;
inline bool ConvertsToPercentage() const;
@@ -148,12 +158,9 @@ item_types = ["enums", "structs", "typedefs"]
"GenericFlexBasis" = """
inline bool IsAuto() const;
- inline const StyleSize& AsSize() const;
"""
"GenericMaxSize" = """
- inline const StyleLengthPercentage& AsLengthPercentage() const;
- inline StyleExtremumLength AsExtremumLength() const;
inline bool ConvertsToLength() const;
inline nscoord ToLength() const;
inline bool ConvertsToPercentage() const;
@@ -185,3 +192,7 @@ item_types = ["enums", "structs", "typedefs"]
inline const T& GetIEnd(mozilla::WritingMode) const;
inline const T& GetBEnd(mozilla::WritingMode) const;
"""
+
+"GenericBorderRadius" = """
+ inline const StyleLengthPercentage& Get(mozilla::HalfCorner) const;
+"""
diff --git a/components/style/custom_properties.rs b/components/style/custom_properties.rs
index f21929c7079..0dbd611820d 100644
--- a/components/style/custom_properties.rs
+++ b/components/style/custom_properties.rs
@@ -7,8 +7,9 @@
//! [custom]: https://drafts.csswg.org/css-variables/
use crate::hash::map::Entry;
-use crate::properties::{CSSWideKeyword, CustomDeclarationValue};
+use crate::properties::{CSSWideKeyword, CustomDeclaration, CustomDeclarationValue};
use crate::selector_map::{PrecomputedHashMap, PrecomputedHashSet, PrecomputedHasher};
+use crate::stylesheets::{Origin, PerOrigin};
use crate::Atom;
use cssparser::{Delimiter, Parser, ParserInput, SourcePosition, Token, TokenSerializationType};
use indexmap::IndexMap;
@@ -490,6 +491,7 @@ fn parse_env_function<'i, 't>(
/// properties.
pub struct CustomPropertiesBuilder<'a> {
seen: PrecomputedHashSet<&'a Name>,
+ reverted: PerOrigin<PrecomputedHashSet<&'a Name>>,
may_have_cycles: bool,
custom_properties: Option<CustomPropertiesMap>,
inherited: Option<&'a Arc<CustomPropertiesMap>>,
@@ -504,6 +506,7 @@ impl<'a> CustomPropertiesBuilder<'a> {
) -> Self {
Self {
seen: PrecomputedHashSet::default(),
+ reverted: Default::default(),
may_have_cycles: false,
custom_properties: None,
inherited,
@@ -512,13 +515,22 @@ impl<'a> CustomPropertiesBuilder<'a> {
}
/// Cascade a given custom property declaration.
- pub fn cascade(&mut self, name: &'a Name, specified_value: &CustomDeclarationValue) {
+ pub fn cascade(&mut self, declaration: &'a CustomDeclaration, origin: Origin) {
+ let CustomDeclaration {
+ ref name,
+ ref value,
+ } = *declaration;
+
+ if self.reverted.borrow_for_origin(&origin).contains(&name) {
+ return;
+ }
+
let was_already_present = !self.seen.insert(name);
if was_already_present {
return;
}
- if !self.value_may_affect_style(name, specified_value) {
+ if !self.value_may_affect_style(name, value) {
return;
}
@@ -530,7 +542,7 @@ impl<'a> CustomPropertiesBuilder<'a> {
}
let map = self.custom_properties.as_mut().unwrap();
- match *specified_value {
+ match *value {
CustomDeclarationValue::Value(ref unparsed_value) => {
let has_references = !unparsed_value.references.is_empty();
self.may_have_cycles |= has_references;
@@ -554,6 +566,12 @@ impl<'a> CustomPropertiesBuilder<'a> {
map.insert(name.clone(), value);
},
CustomDeclarationValue::CSSWideKeyword(keyword) => match keyword {
+ CSSWideKeyword::Revert => {
+ self.seen.remove(name);
+ for origin in origin.following_including() {
+ self.reverted.borrow_mut_for_origin(&origin).insert(name);
+ }
+ },
CSSWideKeyword::Initial => {
map.remove(name);
},
@@ -587,10 +605,10 @@ impl<'a> CustomPropertiesBuilder<'a> {
// not existing in the map.
return false;
},
- (Some(existing_value), &CustomDeclarationValue::Value(ref specified_value)) => {
+ (Some(existing_value), &CustomDeclarationValue::Value(ref value)) => {
// Don't bother overwriting an existing inherited value with
// the same specified value.
- if existing_value == specified_value {
+ if existing_value == value {
return false;
}
},
diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs
index 2a2ae268395..64f0726b21e 100644
--- a/components/style/gecko/conversions.rs
+++ b/components/style/gecko/conversions.rs
@@ -27,6 +27,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::Zero;
use app_units::Au;
use std::f32::consts::PI;
use style_traits::values::specified::AllowedNumericType;
@@ -575,17 +576,15 @@ pub mod basic_shape {
//! Conversions from and to CSS shape representations.
use crate::gecko::values::GeckoStyleCoordConvertible;
- use crate::gecko_bindings::structs::{nsStyleCoord, nsStyleCorners};
+ use crate::gecko_bindings::structs::nsStyleCoord;
use crate::gecko_bindings::structs::{StyleBasicShape, StyleBasicShapeType};
use crate::gecko_bindings::structs::{
StyleGeometryBox, StyleShapeSource, StyleShapeSourceType,
};
- use crate::gecko_bindings::sugar::ns_style_coord::{CoordDataMut, CoordDataValue};
use crate::gecko_bindings::sugar::refptr::RefPtr;
use crate::values::computed::basic_shape::{
BasicShape, ClippingShape, FloatAreaShape, ShapeRadius,
};
- use crate::values::computed::border::{BorderCornerRadius, BorderRadius};
use crate::values::computed::length::LengthPercentage;
use crate::values::computed::motion::OffsetPath;
use crate::values::computed::url::ComputedUrl;
@@ -594,9 +593,7 @@ pub mod basic_shape {
};
use crate::values::generics::basic_shape::{Circle, Ellipse, Path, PolygonCoord};
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;
@@ -706,8 +703,7 @@ pub mod basic_shape {
let r = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[1]);
let b = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[2]);
let l = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[3]);
- let round: BorderRadius = (&other.mRadius).into();
- let round = if round.all_zero() { None } else { Some(round) };
+ let round = other.mRadius;
let rect = Rect::new(
t.expect("inset() offset should be a length, percentage, or calc value"),
r.expect("inset() offset should be a length, percentage, or calc value"),
@@ -752,65 +748,6 @@ pub mod basic_shape {
}
}
- impl<'a> From<&'a nsStyleCorners> for BorderRadius {
- fn from(other: &'a nsStyleCorners) -> Self {
- let get_corner = |index| {
- BorderCornerRadius::new(
- NonNegative(
- LengthPercentage::from_gecko_style_coord(&other.data_at(index)).expect(
- "<border-radius> should be a length, percentage, or calc value",
- ),
- ),
- NonNegative(
- LengthPercentage::from_gecko_style_coord(&other.data_at(index + 1)).expect(
- "<border-radius> should be a length, percentage, or calc value",
- ),
- ),
- )
- };
-
- GenericBorderRadius {
- top_left: get_corner(0),
- top_right: get_corner(2),
- bottom_right: get_corner(4),
- bottom_left: get_corner(6),
- }
- }
- }
-
- // Can't be a From impl since we need to set an existing
- // nsStyleCorners, not create a new one
- impl BorderRadius {
- /// Set this `BorderRadius` into a given `nsStyleCoord`.
- pub fn set_corners(&self, other: &mut nsStyleCorners) {
- let mut set_corner = |field: &BorderCornerRadius, index| {
- field
- .0
- .width()
- .to_gecko_style_coord(&mut other.data_at_mut(index));
- field
- .0
- .height()
- .to_gecko_style_coord(&mut other.data_at_mut(index + 1));
- };
- set_corner(&self.top_left, 0);
- set_corner(&self.top_right, 2);
- set_corner(&self.bottom_right, 4);
- set_corner(&self.bottom_left, 6);
- }
- }
-
- /// We use None for a nonexistant radius, but Gecko uses (0 0 0 0 / 0 0 0 0)
- pub fn set_corners_from_radius(radius: Option<BorderRadius>, other: &mut nsStyleCorners) {
- if let Some(radius) = radius {
- radius.set_corners(other);
- } else {
- for i in 0..8 {
- other.data_at_mut(i).set_value(CoordDataValue::Coord(0));
- }
- }
- }
-
impl<'a> From<&'a nsStyleCoord> for ShapeRadius {
fn from(other: &'a nsStyleCoord) -> Self {
let other = other.borrow();
diff --git a/components/style/gecko/data.rs b/components/style/gecko/data.rs
index 80e34fe2e7e..b70f376d7e6 100644
--- a/components/style/gecko/data.rs
+++ b/components/style/gecko/data.rs
@@ -7,7 +7,7 @@
use crate::context::QuirksMode;
use crate::dom::TElement;
use crate::gecko_bindings::bindings::{self, RawServoStyleSet};
-use crate::gecko_bindings::structs::{RawGeckoPresContextBorrowed, ServoStyleSetSizes};
+use crate::gecko_bindings::structs::{self, 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};
@@ -142,15 +142,15 @@ pub struct PerDocumentStyleDataImpl {
pub struct PerDocumentStyleData(AtomicRefCell<PerDocumentStyleDataImpl>);
impl PerDocumentStyleData {
- /// Create a dummy `PerDocumentStyleData`.
- pub fn new(pres_context: RawGeckoPresContextBorrowed) -> Self {
- let device = Device::new(pres_context);
+ /// Create a `PerDocumentStyleData`.
+ pub fn new(document: *const structs::Document) -> Self {
+ let device = Device::new(document);
// FIXME(emilio, tlin): How is this supposed to work with XBL? This is
// 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.mRawPtr).mCompatMode };
+ let quirks_mode = device.document().mCompatMode;
PerDocumentStyleData(AtomicRefCell::new(PerDocumentStyleDataImpl {
stylist: Stylist::new(device, quirks_mode.into()),
@@ -191,8 +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.mRawPtr;
- unsafe { bindings::Gecko_VisitedStylesEnabled(doc) }
+ unsafe { bindings::Gecko_VisitedStylesEnabled(self.stylist.device().document()) }
}
/// Measure heap usage.
diff --git a/components/style/gecko/media_features.rs b/components/style/gecko/media_features.rs
index 2547f2a45d4..9c48836b4d9 100644
--- a/components/style/gecko/media_features.rs
+++ b/components/style/gecko/media_features.rs
@@ -17,12 +17,13 @@ use app_units::Au;
use euclid::Size2D;
fn viewport_size(device: &Device) -> Size2D<Au> {
- let pc = device.pres_context();
- if pc.mIsRootPaginatedDocument() != 0 {
- // We want the page size, including unprintable areas and margins.
- // FIXME(emilio, bug 1414600): Not quite!
- let area = &pc.mPageSize;
- return Size2D::new(Au(area.width), Au(area.height));
+ if let Some(pc) = device.pres_context() {
+ if pc.mIsRootPaginatedDocument() != 0 {
+ // We want the page size, including unprintable areas and margins.
+ // FIXME(emilio, bug 1414600): Not quite!
+ let area = &pc.mPageSize;
+ return Size2D::new(Au(area.width), Au(area.height));
+ }
}
device.au_viewport_size()
}
diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs
index 8fa2258eaaf..4c04d9573e5 100644
--- a/components/style/gecko/media_queries.rs
+++ b/components/style/gecko/media_queries.rs
@@ -8,7 +8,6 @@ use crate::custom_properties::CssEnvironment;
use crate::gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
use crate::gecko_bindings::bindings;
use crate::gecko_bindings::structs;
-use crate::gecko_bindings::structs::{nsPresContext, RawGeckoPresContextBorrowed};
use crate::media_queries::MediaType;
use crate::properties::ComputedValues;
use crate::string_cache::Atom;
@@ -28,10 +27,9 @@ use style_traits::{CSSPixel, DevicePixel};
/// The `Device` in Gecko wraps a pres context, has a default values computed,
/// and contains all the viewport rule state.
pub struct Device {
- /// NB: The pres context lifetime is tied to the styleset, who owns the
- /// stylist, and thus the `Device`, so having a raw pres context pointer
- /// here is fine.
- pres_context: RawGeckoPresContextBorrowed,
+ /// NB: The document owns the styleset, who owns the stylist, and thus the
+ /// `Device`, so having a raw document pointer here is fine.
+ document: *const structs::Document,
default_values: Arc<ComputedValues>,
/// The font size of the root element
/// This is set when computing the style of the root
@@ -81,16 +79,16 @@ unsafe impl Send for Device {}
impl Device {
/// Trivially constructs a new `Device`.
- pub fn new(pres_context: RawGeckoPresContextBorrowed) -> Self {
- assert!(!pres_context.is_null());
+ pub fn new(document: *const structs::Document) -> Self {
+ assert!(!document.is_null());
+ let doc = unsafe { &*document };
+ let prefs = unsafe { &*bindings::Gecko_GetPrefSheetPrefs(doc) };
Device {
- pres_context,
- default_values: ComputedValues::default_values(unsafe {
- &*(*pres_context).mDocument.mRawPtr
- }),
+ document,
+ default_values: ComputedValues::default_values(doc),
// FIXME(bz): Seems dubious?
root_font_size: AtomicIsize::new(FontSize::medium().size().0 as isize),
- body_text_color: AtomicUsize::new(unsafe { &*pres_context }.mDefaultColor as usize),
+ body_text_color: AtomicUsize::new(prefs.mDefaultColor as usize),
used_root_font_size: AtomicBool::new(false),
used_viewport_size: AtomicBool::new(false),
environment: CssEnvironment,
@@ -112,11 +110,13 @@ impl Device {
/// Whether any animation name may be referenced from the style of any
/// element.
pub fn animation_name_may_be_referenced(&self, name: &KeyframesName) -> bool {
+ let pc = match self.pres_context() {
+ Some(pc) => pc,
+ None => return false,
+ };
+
unsafe {
- bindings::Gecko_AnimationNameMayBeReferencedFromStyle(
- self.pres_context(),
- name.as_atom().as_ptr(),
- )
+ bindings::Gecko_AnimationNameMayBeReferencedFromStyle(pc, name.as_atom().as_ptr())
}
}
@@ -156,16 +156,29 @@ impl Device {
convert_nscolor_to_rgba(self.body_text_color.load(Ordering::Relaxed) as u32)
}
+ /// Gets the document pointer.
+ #[inline]
+ pub fn document(&self) -> &structs::Document {
+ unsafe { &*self.document }
+ }
+
/// Gets the pres context associated with this document.
#[inline]
- pub fn pres_context(&self) -> &nsPresContext {
- unsafe { &*self.pres_context }
+ pub fn pres_context(&self) -> Option<&structs::nsPresContext> {
+ unsafe {
+ self.document()
+ .mPresShell
+ .as_ref()?
+ .mPresContext
+ .mRawPtr
+ .as_ref()
+ }
}
- /// Gets the document pointer.
+ /// Gets the preference stylesheet prefs for our document.
#[inline]
- pub fn document(&self) -> &structs::Document {
- unsafe { &*self.pres_context().mDocument.mRawPtr }
+ pub fn pref_sheet_prefs(&self) -> &structs::PreferenceSheet_Prefs {
+ unsafe { &*bindings::Gecko_GetPrefSheetPrefs(self.document()) }
}
/// Recreates the default computed values.
@@ -195,13 +208,17 @@ impl Device {
/// Returns the current media type of the device.
pub fn media_type(&self) -> MediaType {
+ let pc = match self.pres_context() {
+ Some(pc) => pc,
+ None => return MediaType::screen(),
+ };
+
// Gecko allows emulating random media with mIsEmulatingMedia and
// mMediaEmulated.
- let context = self.pres_context();
- let medium_to_use = if context.mIsEmulatingMedia() != 0 {
- context.mMediaEmulated.mRawPtr
+ let medium_to_use = if pc.mIsEmulatingMedia() != 0 {
+ pc.mMediaEmulated.mRawPtr
} else {
- context.mMedium
+ pc.mMedium
};
MediaType(CustomIdent(unsafe { Atom::from_raw(medium_to_use) }))
@@ -209,7 +226,11 @@ impl Device {
/// Returns the current viewport size in app units.
pub fn au_viewport_size(&self) -> Size2D<Au> {
- let area = &self.pres_context().mVisibleArea;
+ let pc = match self.pres_context() {
+ Some(pc) => pc,
+ None => return Size2D::new(Au(0), Au(0)),
+ };
+ let area = &pc.mVisibleArea;
Size2D::new(Au(area.width), Au(area.height))
}
@@ -227,34 +248,62 @@ impl Device {
/// Returns the device pixel ratio.
pub fn device_pixel_ratio(&self) -> TypedScale<f32, CSSPixel, DevicePixel> {
- let override_dppx = self.pres_context().mOverrideDPPX;
+ let pc = match self.pres_context() {
+ Some(pc) => pc,
+ None => return TypedScale::new(1.),
+ };
+
+ let override_dppx = pc.mOverrideDPPX;
if override_dppx > 0.0 {
return TypedScale::new(override_dppx);
}
- let au_per_dpx = self.pres_context().mCurAppUnitsPerDevPixel as f32;
+
+ let au_per_dpx = pc.mCurAppUnitsPerDevPixel as f32;
let au_per_px = AU_PER_PX as f32;
TypedScale::new(au_per_px / au_per_dpx)
}
/// Returns whether document colors are enabled.
+ #[inline]
pub fn use_document_colors(&self) -> bool {
- self.pres_context().mUseDocumentColors() != 0
+ let doc = self.document();
+ if doc.mIsBeingUsedAsImage() {
+ return true;
+ }
+ let document_color_use =
+ unsafe { structs::StaticPrefs_sVarCache_browser_display_document_color_use };
+ let prefs = self.pref_sheet_prefs();
+ match document_color_use {
+ 1 => true,
+ 2 => prefs.mIsChrome,
+ _ => !prefs.mUseAccessibilityTheme,
+ }
}
/// Returns the default background color.
pub fn default_background_color(&self) -> RGBA {
- convert_nscolor_to_rgba(self.pres_context().mBackgroundColor)
+ convert_nscolor_to_rgba(self.pref_sheet_prefs().mDefaultBackgroundColor)
+ }
+
+ /// Returns the current effective text zoom.
+ #[inline]
+ fn effective_text_zoom(&self) -> f32 {
+ let pc = match self.pres_context() {
+ Some(pc) => pc,
+ None => return 1.,
+ };
+ pc.mEffectiveTextZoom
}
/// Applies text zoom to a font-size or line-height value (see nsStyleFont::ZoomText).
#[inline]
pub fn zoom_text(&self, size: Au) -> Au {
- size.scale_by(self.pres_context().mEffectiveTextZoom)
+ size.scale_by(self.effective_text_zoom())
}
/// Un-apply text zoom.
#[inline]
pub fn unzoom_text(&self, size: Au) -> Au {
- size.scale_by(1. / self.pres_context().mEffectiveTextZoom)
+ size.scale_by(1. / self.effective_text_zoom())
}
}
diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs
index fa1c7d1f6d3..6b3e7a676e0 100644
--- a/components/style/gecko/values.rs
+++ b/components/style/gecko/values.rs
@@ -19,7 +19,7 @@ use crate::values::generics::grid::{TrackBreadth, TrackKeyword};
use crate::values::generics::length::LengthPercentageOrAuto;
use crate::values::generics::{CounterStyleOrNone, NonNegative};
use crate::values::{Auto, Either, None_, Normal};
-use crate::Atom;
+use crate::{Atom, Zero};
use app_units::Au;
use cssparser::RGBA;
use nsstring::{nsACString, nsCStr};
diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs
index 97f0f887a00..f5058fc63c4 100644
--- a/components/style/gecko/wrapper.rs
+++ b/components/style/gecko/wrapper.rs
@@ -1044,9 +1044,13 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
device: &Device,
) -> FontMetricsQueryResult {
use crate::gecko_bindings::bindings::Gecko_GetFontMetrics;
+ let pc = match device.pres_context() {
+ Some(pc) => pc,
+ None => return FontMetricsQueryResult::NotAvailable,
+ };
let gecko_metrics = unsafe {
Gecko_GetFontMetrics(
- device.pres_context(),
+ pc,
wm.is_vertical() && !wm.is_sideways(),
font.gecko(),
font_size.0,
@@ -1242,8 +1246,7 @@ 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::Document ==
- device.pres_context().mDocument.mRawPtr
+ self.as_node().owner_doc().0 as *const structs::Document == device.document() as *const _
}
fn style_attribute(&self) -> Option<ArcBorrow<Locked<PropertyDeclarationBlock>>> {
diff --git a/components/style/gecko_bindings/sugar/ns_css_value.rs b/components/style/gecko_bindings/sugar/ns_css_value.rs
index ef971c669ad..b59732bcc8e 100644
--- a/components/style/gecko_bindings/sugar/ns_css_value.rs
+++ b/components/style/gecko_bindings/sugar/ns_css_value.rs
@@ -10,6 +10,7 @@ use crate::gecko_bindings::structs::{nsCSSUnit, nsCSSValue};
use crate::gecko_bindings::structs::{nsCSSValueList, nsCSSValue_Array};
use crate::gecko_string_cache::Atom;
use crate::values::computed::{Angle, Length, LengthPercentage, Percentage};
+use crate::Zero;
use std::marker::PhantomData;
use std::mem;
use std::ops::{Index, IndexMut};
diff --git a/components/style/gecko_bindings/sugar/ns_style_coord.rs b/components/style/gecko_bindings/sugar/ns_style_coord.rs
index 4f188297d5e..7c6612f35ef 100644
--- a/components/style/gecko_bindings/sugar/ns_style_coord.rs
+++ b/components/style/gecko_bindings/sugar/ns_style_coord.rs
@@ -5,8 +5,8 @@
//! Rust helpers for Gecko's `nsStyleCoord`.
use crate::gecko_bindings::bindings;
+use crate::gecko_bindings::structs::nsStyleSides;
use crate::gecko_bindings::structs::{nsStyleCoord, nsStyleCoord_Calc, nsStyleCoord_CalcValue};
-use crate::gecko_bindings::structs::{nsStyleCorners, nsStyleSides};
use crate::gecko_bindings::structs::{nsStyleUnion, nsStyleUnit, nscoord};
use std::mem;
@@ -123,64 +123,6 @@ unsafe impl<'a> CoordDataMut for SidesDataMut<'a> {
}
}
-impl nsStyleCorners {
- /// Get a `nsStyleCoord` like object representing the given index's value
- /// and unit.
- #[inline]
- pub fn data_at(&self, index: usize) -> CornersData {
- CornersData {
- corners: self,
- index: index,
- }
- }
-
- /// Get a `nsStyleCoord` like object representing the mutable given index's
- /// value and unit.
- #[inline]
- pub fn data_at_mut(&mut self, index: usize) -> CornersDataMut {
- CornersDataMut {
- corners: self,
- index: index,
- }
- }
-}
-
-/// A `nsStyleCoord`-like struct on top of `nsStyleCorners`.
-pub struct CornersData<'a> {
- corners: &'a nsStyleCorners,
- index: usize,
-}
-
-/// A `nsStyleCoord`-like struct on top of a mutable `nsStyleCorners` reference.
-pub struct CornersDataMut<'a> {
- corners: &'a mut nsStyleCorners,
- index: usize,
-}
-
-unsafe impl<'a> CoordData for CornersData<'a> {
- fn unit(&self) -> nsStyleUnit {
- unsafe { self.corners.get_mUnits()[self.index] }
- }
- fn union(&self) -> nsStyleUnion {
- unsafe { self.corners.get_mValues()[self.index] }
- }
-}
-unsafe impl<'a> CoordData for CornersDataMut<'a> {
- fn unit(&self) -> nsStyleUnit {
- unsafe { self.corners.get_mUnits()[self.index] }
- }
- fn union(&self) -> nsStyleUnion {
- unsafe { self.corners.get_mValues()[self.index] }
- }
-}
-unsafe impl<'a> CoordDataMut for CornersDataMut<'a> {
- unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion) {
- let unit = &mut self.corners.get_mUnits_mut()[self.index] as *mut _;
- let value = &mut self.corners.get_mValues_mut()[self.index] as *mut _;
- (&mut *unit, &mut *value)
- }
-}
-
/// Enum representing the tagged union that is CoordData.
///
/// In release mode this should never actually exist in the code, and will be
diff --git a/components/style/lib.rs b/components/style/lib.rs
index 2ea20088ed0..37b464afb47 100644
--- a/components/style/lib.rs
+++ b/components/style/lib.rs
@@ -244,3 +244,26 @@ impl CaseSensitivityExt for selectors::attr::CaseSensitivity {
}
}
}
+
+/// A trait pretty much similar to num_traits::Zero, but without the need of
+/// implementing `Add`.
+pub trait Zero {
+ /// Returns the zero value.
+ fn zero() -> Self;
+
+ /// Returns whether this value is zero.
+ fn is_zero(&self) -> bool;
+}
+
+impl<T> Zero for T
+where
+ T: num_traits::Zero,
+{
+ fn zero() -> Self {
+ <Self as num_traits::Zero>::zero()
+ }
+
+ fn is_zero(&self) -> bool {
+ <Self as num_traits::Zero>::is_zero(self)
+ }
+}
diff --git a/components/style/media_queries/media_feature_expression.rs b/components/style/media_queries/media_feature_expression.rs
index ec864510c72..6a9db93e889 100644
--- a/components/style/media_queries/media_feature_expression.rs
+++ b/components/style/media_queries/media_feature_expression.rs
@@ -21,9 +21,8 @@ use crate::stylesheets::Origin;
use crate::values::computed::{self, ToComputedValue};
use crate::values::specified::{Integer, Length, Number, Resolution};
use crate::values::{serialize_atom_identifier, CSSFloat};
-use crate::Atom;
+use crate::{Atom, Zero};
use cssparser::{Parser, Token};
-use num_traits::Zero;
use std::cmp::{Ordering, PartialOrd};
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
diff --git a/components/style/properties/cascade.rs b/components/style/properties/cascade.rs
index 4a0e07fdcac..23970d64888 100644
--- a/components/style/properties/cascade.rs
+++ b/components/style/properties/cascade.rs
@@ -11,12 +11,13 @@ use crate::font_metrics::FontMetricsProvider;
use crate::logical_geometry::WritingMode;
use crate::media_queries::Device;
use crate::properties::{ComputedValues, StyleBuilder};
-use crate::properties::{LonghandId, LonghandIdSet};
+use crate::properties::{LonghandId, LonghandIdSet, CSSWideKeyword};
use crate::properties::{PropertyDeclaration, PropertyDeclarationId, DeclarationImportanceIterator};
use crate::properties::CASCADE_PROPERTY;
use crate::rule_cache::{RuleCache, RuleCacheConditions};
use crate::rule_tree::{CascadeLevel, StrongRuleNode};
use crate::selector_parser::PseudoElement;
+use crate::stylesheets::{Origin, PerOrigin};
use servo_arc::Arc;
use crate::shared_lock::StylesheetGuards;
use smallbitvec::SmallBitVec;
@@ -251,7 +252,7 @@ where
for (declaration, cascade_level) in iter_declarations() {
declarations.push((declaration, cascade_level));
if let PropertyDeclaration::Custom(ref declaration) = *declaration {
- builder.cascade(&declaration.name, &declaration.value);
+ builder.cascade(declaration, cascade_level.origin());
}
}
@@ -339,14 +340,8 @@ fn should_ignore_declaration_when_ignoring_document_colors(
return false;
}
- let is_ua_or_user_rule = matches!(
- cascade_level,
- CascadeLevel::UANormal |
- CascadeLevel::UserNormal |
- CascadeLevel::UserImportant |
- CascadeLevel::UAImportant
- );
-
+ let is_ua_or_user_rule =
+ matches!(cascade_level.origin(), Origin::User | Origin::UserAgent);
if is_ua_or_user_rule {
return false;
}
@@ -388,6 +383,7 @@ struct Cascade<'a, 'b: 'a> {
context: &'a mut computed::Context<'b>,
cascade_mode: CascadeMode<'a>,
seen: LonghandIdSet,
+ reverted: PerOrigin<LonghandIdSet>,
saved_font_size: Option<PropertyDeclaration>,
saved_font_family: Option<PropertyDeclaration>,
}
@@ -398,6 +394,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
context,
cascade_mode,
seen: LonghandIdSet::default(),
+ reverted: Default::default(),
saved_font_size: None,
saved_font_family: None,
}
@@ -488,6 +485,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
for (declaration, cascade_level) in declarations {
let declaration_id = declaration.id();
+ let origin = cascade_level.origin();
let longhand_id = match declaration_id {
PropertyDeclarationId::Longhand(id) => id,
PropertyDeclarationId::Custom(..) => continue,
@@ -513,6 +511,10 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
continue;
}
+ if self.reverted.borrow_for_origin(&origin).contains(physical_longhand_id) {
+ continue;
+ }
+
// Only a few properties are allowed to depend on the visited state
// of links. When cascading visited styles, we can save time by
// only processing these properties.
@@ -540,8 +542,34 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
}
}
+ let css_wide_keyword = declaration.get_css_wide_keyword();
+ if let Some(CSSWideKeyword::Revert) = css_wide_keyword {
+ // We intentionally don't want to insert it into `self.seen`,
+ // `reverted` takes care of rejecting other declarations as
+ // needed.
+ for origin in origin.following_including() {
+ self.reverted
+ .borrow_mut_for_origin(&origin)
+ .insert(physical_longhand_id);
+ }
+ continue;
+ }
+
self.seen.insert(physical_longhand_id);
+ let unset = css_wide_keyword.map_or(false, |css_wide_keyword| {
+ match css_wide_keyword {
+ CSSWideKeyword::Unset => true,
+ CSSWideKeyword::Inherit => inherited,
+ CSSWideKeyword::Initial => !inherited,
+ CSSWideKeyword::Revert => unreachable!(),
+ }
+ });
+
+ if unset {
+ continue;
+ }
+
// FIXME(emilio): We should avoid generating code for logical
// longhands and just use the physical ones, then rename
// physical_longhand_id to just longhand_id.
@@ -800,18 +828,14 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
self.seen.contains(LonghandId::MozMinFontSizeRatio) ||
self.seen.contains(LonghandId::FontFamily)
{
- use crate::properties::{CSSWideKeyword, WideKeywordDeclaration};
+ use crate::values::computed::FontSize;
// font-size must be explicitly inherited to handle lang
// changes and scriptlevel changes.
//
// FIXME(emilio): That looks a bit bogus...
- let inherit = PropertyDeclaration::CSSWideKeyword(WideKeywordDeclaration {
- id: LonghandId::FontSize,
- keyword: CSSWideKeyword::Inherit,
- });
-
- self.apply_declaration_ignoring_phase(LonghandId::FontSize, &inherit);
+ self.context.for_non_inherited_property = None;
+ FontSize::cascade_inherit_font_size(&mut self.context);
}
}
}
diff --git a/components/style/properties/data.py b/components/style/properties/data.py
index f3b4e43c225..9347d9b9428 100644
--- a/components/style/properties/data.py
+++ b/components/style/properties/data.py
@@ -347,6 +347,7 @@ class Longhand(object):
"TouchAction",
"TransformStyle",
"UserSelect",
+ "WordBreak",
"XSpan",
"XTextZoom",
"ZIndex",
diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs
index d7058d99635..e4396e764a4 100644
--- a/components/style/properties/declaration_block.rs
+++ b/components/style/properties/declaration_block.rs
@@ -849,7 +849,7 @@ impl PropertyDeclarationBlock {
for declaration in self.normal_declaration_iter() {
if let PropertyDeclaration::Custom(ref declaration) = *declaration {
- builder.cascade(&declaration.name, &declaration.value);
+ builder.cascade(declaration, Origin::Author);
}
}
diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs
index b1be315e7a0..6a4d4d87a99 100644
--- a/components/style/properties/gecko.mako.rs
+++ b/components/style/properties/gecko.mako.rs
@@ -52,7 +52,7 @@ use crate::rule_tree::StrongRuleNode;
use crate::selector_parser::PseudoElement;
use servo_arc::{Arc, RawOffsetArc};
use std::marker::PhantomData;
-use std::mem::{forget, uninitialized, transmute, zeroed};
+use std::mem::{forget, uninitialized, zeroed};
use std::{cmp, ops, ptr};
use crate::values::{self, CustomIdent, Either, KeyframesName, None_};
use crate::values::computed::{NonNegativeLength, Percentage, TransitionProperty};
@@ -463,32 +463,27 @@ def set_gecko_property(ffi_name, expr):
// set on mContextFlags, and the length field is set to the initial value.
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
- use crate::values::generics::svg::{SVGLength, SvgLengthPercentageOrNumber};
+ use crate::values::generics::svg::SVGLength;
use crate::gecko_bindings::structs::nsStyleSVG_${ident.upper()}_CONTEXT as CONTEXT_VALUE;
let length = match v {
- SVGLength::Length(length) => {
+ SVGLength::LengthPercentage(length) => {
self.gecko.mContextFlags &= !CONTEXT_VALUE;
length
}
SVGLength::ContextValue => {
self.gecko.mContextFlags |= CONTEXT_VALUE;
match longhands::${ident}::get_initial_value() {
- SVGLength::Length(length) => length,
+ SVGLength::LengthPercentage(length) => length,
_ => unreachable!("Initial value should not be context-value"),
}
}
};
- match length {
- SvgLengthPercentageOrNumber::LengthPercentage(lp) =>
- self.gecko.${gecko_ffi_name}.set(lp),
- SvgLengthPercentageOrNumber::Number(num) =>
- self.gecko.${gecko_ffi_name}.set_value(CoordDataValue::Factor(num.into())),
- }
+ self.gecko.${gecko_ffi_name} = length;
}
pub fn copy_${ident}_from(&mut self, other: &Self) {
use crate::gecko_bindings::structs::nsStyleSVG_${ident.upper()}_CONTEXT as CONTEXT_VALUE;
- self.gecko.${gecko_ffi_name}.copy_from(&other.gecko.${gecko_ffi_name});
+ self.gecko.${gecko_ffi_name} = other.gecko.${gecko_ffi_name};
self.gecko.mContextFlags =
(self.gecko.mContextFlags & !CONTEXT_VALUE) |
(other.gecko.mContextFlags & CONTEXT_VALUE);
@@ -499,32 +494,12 @@ def set_gecko_property(ffi_name, expr):
}
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
- use crate::values::generics::svg::{SVGLength, SvgLengthPercentageOrNumber};
- use crate::values::computed::LengthPercentage;
+ use crate::values::generics::svg::SVGLength;
use crate::gecko_bindings::structs::nsStyleSVG_${ident.upper()}_CONTEXT as CONTEXT_VALUE;
if (self.gecko.mContextFlags & CONTEXT_VALUE) != 0 {
return SVGLength::ContextValue;
}
- let length = match self.gecko.${gecko_ffi_name}.as_value() {
- CoordDataValue::Factor(number) => {
- SvgLengthPercentageOrNumber::Number(number)
- },
- CoordDataValue::Coord(coord) => {
- SvgLengthPercentageOrNumber::LengthPercentage(
- LengthPercentage::new(Au(coord).into(), None)
- )
- },
- CoordDataValue::Percent(p) => {
- SvgLengthPercentageOrNumber::LengthPercentage(
- LengthPercentage::new(Au(0).into(), Some(Percentage(p)))
- )
- },
- CoordDataValue::Calc(calc) => {
- SvgLengthPercentageOrNumber::LengthPercentage(calc.into())
- },
- _ => unreachable!("Unexpected coordinate in ${ident}"),
- };
- SVGLength::Length(length.into())
+ SVGLength::LengthPercentage(self.gecko.${gecko_ffi_name})
}
</%def>
@@ -817,34 +792,23 @@ def set_gecko_property(ffi_name, expr):
}
</%def>
-<%def name="impl_corner_style_coord(ident, gecko_ffi_name, x_index, y_index)">
+<%def name="impl_corner_style_coord(ident, gecko_ffi_name, corner)">
#[allow(non_snake_case)]
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
- v.0.width().to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${x_index}));
- v.0.height().to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${y_index}));
+ self.gecko.${gecko_ffi_name}.${corner} = v;
}
#[allow(non_snake_case)]
pub fn copy_${ident}_from(&mut self, other: &Self) {
- self.gecko.${gecko_ffi_name}.data_at_mut(${x_index})
- .copy_from(&other.gecko.${gecko_ffi_name}.data_at(${x_index}));
- self.gecko.${gecko_ffi_name}.data_at_mut(${y_index})
- .copy_from(&other.gecko.${gecko_ffi_name}.data_at(${y_index}));
+ self.gecko.${gecko_ffi_name}.${corner} =
+ other.gecko.${gecko_ffi_name}.${corner};
}
#[allow(non_snake_case)]
pub fn reset_${ident}(&mut self, other: &Self) {
self.copy_${ident}_from(other)
}
-
#[allow(non_snake_case)]
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
- use crate::values::computed::border::BorderCornerRadius;
- let width = GeckoStyleCoordConvertible::from_gecko_style_coord(
- &self.gecko.${gecko_ffi_name}.data_at(${x_index}))
- .expect("Failed to clone ${ident}");
- let height = GeckoStyleCoordConvertible::from_gecko_style_coord(
- &self.gecko.${gecko_ffi_name}.data_at(${y_index}))
- .expect("Failed to clone ${ident}");
- BorderCornerRadius::new(width, height)
+ self.gecko.${gecko_ffi_name}.${corner}
}
</%def>
@@ -891,13 +855,13 @@ def set_gecko_property(ffi_name, expr):
transform_functions = [
("Matrix3D", "matrix3d", ["number"] * 16),
("Matrix", "matrix", ["number"] * 6),
- ("Translate", "translate", ["lp", "optional_lp"]),
+ ("Translate", "translate", ["lp", "lp"]),
("Translate3D", "translate3d", ["lp", "lp", "length"]),
("TranslateX", "translatex", ["lp"]),
("TranslateY", "translatey", ["lp"]),
("TranslateZ", "translatez", ["length"]),
("Scale3D", "scale3d", ["number"] * 3),
- ("Scale", "scale", ["number", "optional_number"]),
+ ("Scale", "scale", ["number", "number"]),
("ScaleX", "scalex", ["number"]),
("ScaleY", "scaley", ["number"]),
("ScaleZ", "scalez", ["number"]),
@@ -906,7 +870,7 @@ transform_functions = [
("RotateX", "rotatex", ["angle"]),
("RotateY", "rotatey", ["angle"]),
("RotateZ", "rotatez", ["angle"]),
- ("Skew", "skew", ["angle", "optional_angle"]),
+ ("Skew", "skew", ["angle", "angle"]),
("SkewX", "skewx", ["angle"]),
("SkewY", "skewy", ["angle"]),
("Perspective", "perspective", ["length"]),
@@ -917,7 +881,6 @@ transform_functions = [
<%def name="transform_function_arm(name, keyword, items)">
<%
- has_optional = items[-1].startswith("optional_")
pattern = None
if keyword == "matrix3d":
# m11: number1, m12: number2, ..
@@ -955,36 +918,20 @@ transform_functions = [
}
%>
crate::values::generics::transform::TransformOperation::${name}${pattern} => {
- % if has_optional:
- let optional_present = ${items[-1] + str(len(items))}.is_some();
- let len = if optional_present {
- ${len(items) + 1}
- } else {
- ${len(items)}
- };
- % else:
- let len = ${len(items) + 1};
- % endif
+ let len = ${len(items) + 1};
bindings::Gecko_CSSValue_SetFunction(gecko_value, len);
bindings::Gecko_CSSValue_SetKeyword(
bindings::Gecko_CSSValue_GetArrayItem(gecko_value, 0),
structs::nsCSSKeyword::eCSSKeyword_${keyword}
);
% for index, item in enumerate(items):
- <% replaced_item = item.replace("optional_", "") %>
- % if item.startswith("optional"):
- if let Some(${replaced_item + str(index + 1)}) = ${item + str(index + 1)} {
- % endif
% if item == "list":
debug_assert!(!${item}${index + 1}.0.is_empty());
% endif
- ${css_value_setters[replaced_item] % (
+ ${css_value_setters[item] % (
"bindings::Gecko_CSSValue_GetArrayItem(gecko_value, %d)" % (index + 1),
- replaced_item + str(index + 1)
+ item + str(index + 1)
)};
- % if item.startswith("optional"):
- }
- % endif
% endfor
}
</%def>
@@ -995,8 +942,6 @@ transform_functions = [
css_value_getters = {
"length" : "Length::new(bindings::Gecko_CSSValue_GetNumber(%s))",
"lp" : "%s.get_length_percentage()",
- "lpon" : "Either::Second(%s.get_length_percentage())",
- "lon" : "Either::First(%s.get_length())",
"angle" : "%s.get_angle()",
"number" : "bindings::Gecko_CSSValue_GetNumber(%s)",
"percentage" : "Percentage(bindings::Gecko_CSSValue_GetPercentage(%s))",
@@ -1034,20 +979,11 @@ transform_functions = [
${field_names[index]}:
% endif
<%
- getter = css_value_getters[item.replace("optional_", "")] % (
+ getter = css_value_getters[item] % (
"bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, %d)" % (index + 1)
)
%>
- % if item.startswith("optional_"):
- if (**gecko_value.mValue.mArray.as_ref()).mCount == ${index + 1} {
- None
- } else {
- Some(${getter})
- }
- % else:
- ${getter}
- % endif
-,
+ ${getter},
% endfor
${post_symbols}
},
@@ -1291,55 +1227,23 @@ impl Clone for ${style_struct.gecko_struct_name} {
# Types used with predefined_type()-defined properties that we can auto-generate.
predefined_types = {
- "Appearance": impl_simple,
- "OverscrollBehavior": impl_simple,
- "OverflowClipBox": impl_simple,
- "ScrollSnapAlign": impl_simple,
- "ScrollSnapType": impl_simple,
- "Float": impl_simple,
- "Overflow": impl_simple,
- "BreakBetween": impl_simple,
- "BreakWithin": impl_simple,
- "Resize": impl_simple,
"Color": impl_color,
"ColorOrAuto": impl_color,
- "GreaterThanOrEqualToOneNumber": impl_simple,
- "Integer": impl_simple,
"length::LengthOrAuto": impl_style_coord,
"length::LengthOrNormal": impl_style_coord,
"length::NonNegativeLengthOrAuto": impl_style_coord,
"length::NonNegativeLengthPercentageOrNormal": impl_style_coord,
- "FillRule": impl_simple,
- "FlexBasis": impl_simple,
"Length": impl_absolute_length,
"LengthOrNormal": impl_style_coord,
- "LengthPercentage": impl_simple,
"LengthPercentageOrAuto": impl_style_coord,
- "MaxSize": impl_simple,
- "Size": impl_simple,
"MozScriptMinSize": impl_absolute_length,
- "MozScriptSizeMultiplier": impl_simple,
- "NonNegativeLengthPercentage": impl_simple,
- "NonNegativeLengthOrNumber": impl_simple,
- "NonNegativeLengthOrNumberRect": impl_simple,
- "BorderImageSlice": impl_simple,
- "NonNegativeNumber": impl_simple,
- "Number": impl_simple,
- "Opacity": impl_simple,
- "OverflowWrap": impl_simple,
- "OverflowAnchor": impl_simple,
- "Perspective": impl_simple,
- "Position": impl_simple,
"RGBAColor": impl_rgba_color,
"SVGLength": impl_svg_length,
"SVGOpacity": impl_svg_opacity,
"SVGPaint": impl_svg_paint,
"SVGWidth": impl_svg_length,
"Transform": impl_transform,
- "TransformOrigin": impl_simple,
- "UserSelect": impl_simple,
"url::UrlOrNone": impl_css_url,
- "ZIndex": impl_simple,
}
def longhand_method(longhand):
@@ -1354,15 +1258,12 @@ impl Clone for ${style_struct.gecko_struct_name} {
args.update(keyword=longhand.keyword)
if "font" in longhand.ident:
args.update(cast_type=longhand.cast_type)
- else:
+ elif longhand.predefined_type in predefined_types:
method = predefined_types[longhand.predefined_type]
+ else:
+ method = impl_simple
method(**args)
-
- picked_longhands = []
- for x in longhands:
- if x.keyword or x.predefined_type in predefined_types or x.logical:
- picked_longhands.append(x)
%>
impl ${style_struct.gecko_struct_name} {
/*
@@ -1374,7 +1275,7 @@ impl ${style_struct.gecko_struct_name} {
* Auto-Generated Methods.
*/
<%
- for longhand in picked_longhands:
+ for longhand in longhands:
longhand_method(longhand)
%>
}
@@ -1387,14 +1288,6 @@ class Side(object):
self.ident = name.lower()
self.index = index
-class Corner(object):
- def __init__(self, vert, horiz, index):
- self.x_name = "HalfCorner::eCorner" + vert + horiz + "X"
- self.y_name = "HalfCorner::eCorner" + vert + horiz + "Y"
- self.ident = (vert + "_" + horiz).lower()
- self.x_index = 2 * index
- self.y_index = 2 * index + 1
-
class GridLine(object):
def __init__(self, name):
self.ident = "grid-" + name.lower()
@@ -1402,19 +1295,12 @@ class GridLine(object):
self.gecko = "m" + to_camel_case(self.ident)
SIDES = [Side("Top", 0), Side("Right", 1), Side("Bottom", 2), Side("Left", 3)]
-CORNERS = [Corner("Top", "Left", 0), Corner("Top", "Right", 1),
- Corner("Bottom", "Right", 2), Corner("Bottom", "Left", 3)]
+CORNERS = ["top_left", "top_right", "bottom_right", "bottom_left"]
GRID_LINES = map(GridLine, ["row-start", "row-end", "column-start", "column-end"])
%>
#[allow(dead_code)]
fn static_assert() {
- unsafe {
- % for corner in CORNERS:
- transmute::<_, [u32; ${corner.x_index}]>([1; structs::${corner.x_name} as usize]);
- transmute::<_, [u32; ${corner.y_index}]>([1; structs::${corner.y_name} as usize]);
- % endfor
- }
// Note: using the above technique with an enum hits a rust bug when |structs| is in a different crate.
% for side in SIDES:
{ const DETAIL: u32 = [0][(structs::Side::eSide${side.name} as usize != ${side.index}) as usize]; let _ = DETAIL; }
@@ -1425,7 +1311,7 @@ fn static_assert() {
<% skip_border_longhands = " ".join(["border-{0}-{1}".format(x.ident, y)
for x in SIDES
for y in ["color", "style", "width"]] +
- ["border-{0}-radius".format(x.ident.replace("_", "-"))
+ ["border-{0}-radius".format(x.replace("_", "-"))
for x in CORNERS]) %>
<%self:impl_trait style_struct_name="Border"
@@ -1494,10 +1380,9 @@ fn static_assert() {
% endfor
% for corner in CORNERS:
- <% impl_corner_style_coord("border_%s_radius" % corner.ident,
+ <% impl_corner_style_coord("border_%s_radius" % corner,
"mBorderRadius",
- corner.x_index,
- corner.y_index) %>
+ corner) %>
% endfor
pub fn set_border_image_source(&mut self, image: longhands::border_image_source::computed_value::T) {
@@ -2027,7 +1912,7 @@ fn static_assert() {
</%self:impl_trait>
<% skip_outline_longhands = " ".join("outline-style outline-width".split() +
- ["-moz-outline-radius-{0}".format(x.ident.replace("_", ""))
+ ["-moz-outline-radius-{0}".format(x.replace("_", ""))
for x in CORNERS]) %>
<%self:impl_trait style_struct_name="Outline"
skip_longhands="${skip_outline_longhands}">
@@ -2059,10 +1944,9 @@ fn static_assert() {
round_to_pixels=True) %>
% for corner in CORNERS:
- <% impl_corner_style_coord("_moz_outline_radius_%s" % corner.ident.replace("_", ""),
+ <% impl_corner_style_coord("_moz_outline_radius_%s" % corner.replace("_", ""),
"mOutlineRadius",
- corner.x_index,
- corner.y_index) %>
+ corner) %>
% endfor
pub fn outline_has_nonzero_width(&self) -> bool {
@@ -2072,6 +1956,7 @@ fn static_assert() {
<%
skip_font_longhands = """font-family font-size font-size-adjust font-weight
+ font-style font-stretch -moz-script-level
font-synthesis -x-lang font-variant-alternates
font-variant-east-asian font-variant-ligatures
font-variant-numeric font-language-override
@@ -2863,6 +2748,7 @@ fn static_assert() {
animation-iteration-count animation-timing-function
clear transition-duration transition-delay
transition-timing-function transition-property
+ transform-style
rotate scroll-snap-points-x scroll-snap-points-y
scroll-snap-coordinate -moz-binding will-change
offset-path shape-outside contain touch-action
@@ -3291,7 +3177,6 @@ fn static_assert() {
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_CONTENT;
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_SIZE;
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_LAYOUT;
- use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_STYLE;
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_PAINT;
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_ALL_BITS;
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_CONTENT_BITS;
@@ -3315,9 +3200,6 @@ fn static_assert() {
if v.contains(SpecifiedValue::LAYOUT) {
bitfield |= NS_STYLE_CONTAIN_LAYOUT;
}
- if v.contains(SpecifiedValue::STYLE) {
- bitfield |= NS_STYLE_CONTAIN_STYLE;
- }
if v.contains(SpecifiedValue::PAINT) {
bitfield |= NS_STYLE_CONTAIN_PAINT;
}
@@ -3333,7 +3215,6 @@ fn static_assert() {
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_CONTENT;
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_SIZE;
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_LAYOUT;
- use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_STYLE;
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_PAINT;
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_ALL_BITS;
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_CONTENT_BITS;
@@ -3363,9 +3244,6 @@ fn static_assert() {
if gecko_flags & (NS_STYLE_CONTAIN_LAYOUT as u8) != 0 {
servo_flags.insert(SpecifiedValue::LAYOUT);
}
- if gecko_flags & (NS_STYLE_CONTAIN_STYLE as u8) != 0 {
- servo_flags.insert(SpecifiedValue::STYLE);
- }
if gecko_flags & (NS_STYLE_CONTAIN_PAINT as u8) != 0 {
servo_flags.insert(SpecifiedValue::PAINT);
}
@@ -3870,6 +3748,7 @@ fn static_assert() {
#[allow(non_snake_case)]
pub fn set__moz_image_region(&mut self, v: longhands::_moz_image_region::computed_value::T) {
use crate::values::Either;
+ use crate::values::generics::length::LengthPercentageOrAuto::*;
match v {
Either::Second(_auto) => {
@@ -3879,15 +3758,21 @@ fn static_assert() {
self.gecko.mImageRegion.height = 0;
}
Either::First(rect) => {
- self.gecko.mImageRegion.x = rect.left.map(Au::from).unwrap_or(Au(0)).0;
- self.gecko.mImageRegion.y = rect.top.map(Au::from).unwrap_or(Au(0)).0;
+ self.gecko.mImageRegion.x = match rect.left {
+ LengthPercentage(v) => v.to_i32_au(),
+ Auto => 0,
+ };
+ self.gecko.mImageRegion.y = match rect.top {
+ LengthPercentage(v) => v.to_i32_au(),
+ Auto => 0,
+ };
self.gecko.mImageRegion.height = match rect.bottom {
- Some(value) => (Au::from(value) - Au(self.gecko.mImageRegion.y)).0,
- None => 0,
+ LengthPercentage(value) => (Au::from(value) - Au(self.gecko.mImageRegion.y)).0,
+ Auto => 0,
};
self.gecko.mImageRegion.width = match rect.right {
- Some(value) => (Au::from(value) - Au(self.gecko.mImageRegion.x)).0,
- None => 0,
+ LengthPercentage(value) => (Au::from(value) - Au(self.gecko.mImageRegion.x)).0,
+ Auto => 0,
};
}
}
@@ -3896,6 +3781,7 @@ fn static_assert() {
#[allow(non_snake_case)]
pub fn clone__moz_image_region(&self) -> longhands::_moz_image_region::computed_value::T {
use crate::values::{Auto, Either};
+ use crate::values::generics::length::LengthPercentageOrAuto::*;
use crate::values::computed::ClipRect;
// There is no ideal way to detect auto type for structs::nsRect and its components, so
@@ -3908,10 +3794,10 @@ fn static_assert() {
}
Either::First(ClipRect {
- top: Some(Au(self.gecko.mImageRegion.y).into()),
- right: Some(Au(self.gecko.mImageRegion.width + self.gecko.mImageRegion.x).into()),
- bottom: Some(Au(self.gecko.mImageRegion.height + self.gecko.mImageRegion.y).into()),
- left: Some(Au(self.gecko.mImageRegion.x).into()),
+ top: LengthPercentage(Au(self.gecko.mImageRegion.y).into()),
+ right: LengthPercentage(Au(self.gecko.mImageRegion.width + self.gecko.mImageRegion.x).into()),
+ bottom: LengthPercentage(Au(self.gecko.mImageRegion.height + self.gecko.mImageRegion.y).into()),
+ left: LengthPercentage(Au(self.gecko.mImageRegion.x).into()),
})
}
@@ -3968,38 +3854,43 @@ fn static_assert() {
use crate::gecko_bindings::structs::NS_STYLE_CLIP_TOP_AUTO;
use crate::gecko_bindings::structs::NS_STYLE_CLIP_RIGHT_AUTO;
use crate::gecko_bindings::structs::NS_STYLE_CLIP_BOTTOM_AUTO;
+ use crate::values::generics::length::LengthPercentageOrAuto::*;
use crate::values::Either;
match v {
Either::First(rect) => {
self.gecko.mClipFlags = NS_STYLE_CLIP_RECT as u8;
- if let Some(left) = rect.left {
- self.gecko.mClip.x = left.to_i32_au();
- } else {
- self.gecko.mClip.x = 0;
- self.gecko.mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO as u8;
- }
+ self.gecko.mClip.x = match rect.left {
+ LengthPercentage(l) => l.to_i32_au(),
+ Auto => {
+ self.gecko.mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO as u8;
+ 0
+ }
+ };
- if let Some(top) = rect.top {
- self.gecko.mClip.y = top.to_i32_au();
- } else {
- self.gecko.mClip.y = 0;
- self.gecko.mClipFlags |= NS_STYLE_CLIP_TOP_AUTO as u8;
- }
+ self.gecko.mClip.y = match rect.top {
+ LengthPercentage(l) => l.to_i32_au(),
+ Auto => {
+ self.gecko.mClipFlags |= NS_STYLE_CLIP_TOP_AUTO as u8;
+ 0
+ }
+ };
- if let Some(bottom) = rect.bottom {
- self.gecko.mClip.height = (Au::from(bottom) - Au(self.gecko.mClip.y)).0;
- } else {
- self.gecko.mClip.height = 1 << 30; // NS_MAXSIZE
- self.gecko.mClipFlags |= NS_STYLE_CLIP_BOTTOM_AUTO as u8;
- }
+ self.gecko.mClip.height = match rect.bottom {
+ LengthPercentage(l) => (Au::from(l) - Au(self.gecko.mClip.y)).0,
+ Auto => {
+ self.gecko.mClipFlags |= NS_STYLE_CLIP_BOTTOM_AUTO as u8;
+ 1 << 30 // NS_MAXSIZE
+ }
+ };
- if let Some(right) = rect.right {
- self.gecko.mClip.width = (Au::from(right) - Au(self.gecko.mClip.x)).0;
- } else {
- self.gecko.mClip.width = 1 << 30; // NS_MAXSIZE
- self.gecko.mClipFlags |= NS_STYLE_CLIP_RIGHT_AUTO as u8;
- }
+ self.gecko.mClip.width = match rect.right {
+ LengthPercentage(l) => (Au::from(l) - Au(self.gecko.mClip.x)).0,
+ Auto => {
+ self.gecko.mClipFlags |= NS_STYLE_CLIP_RIGHT_AUTO as u8;
+ 1 << 30 // NS_MAXSIZE
+ }
+ };
},
Either::Second(_auto) => {
self.gecko.mClipFlags = NS_STYLE_CLIP_AUTO as u8;
@@ -4026,42 +3917,42 @@ fn static_assert() {
use crate::gecko_bindings::structs::NS_STYLE_CLIP_LEFT_AUTO;
use crate::gecko_bindings::structs::NS_STYLE_CLIP_RIGHT_AUTO;
use crate::gecko_bindings::structs::NS_STYLE_CLIP_TOP_AUTO;
+ use crate::values::generics::length::LengthPercentageOrAuto::*;
use crate::values::computed::{ClipRect, ClipRectOrAuto};
use crate::values::Either;
if self.gecko.mClipFlags == NS_STYLE_CLIP_AUTO as u8 {
- ClipRectOrAuto::auto()
+ return ClipRectOrAuto::auto()
+ }
+ let left = if self.gecko.mClipFlags & NS_STYLE_CLIP_LEFT_AUTO as u8 != 0 {
+ debug_assert_eq!(self.gecko.mClip.x, 0);
+ Auto
} else {
- let left = if self.gecko.mClipFlags & NS_STYLE_CLIP_LEFT_AUTO as u8 != 0 {
- debug_assert_eq!(self.gecko.mClip.x, 0);
- None
- } else {
- Some(Au(self.gecko.mClip.x).into())
- };
+ LengthPercentage(Au(self.gecko.mClip.x).into())
+ };
- let top = if self.gecko.mClipFlags & NS_STYLE_CLIP_TOP_AUTO as u8 != 0 {
- debug_assert_eq!(self.gecko.mClip.y, 0);
- None
- } else {
- Some(Au(self.gecko.mClip.y).into())
- };
+ let top = if self.gecko.mClipFlags & NS_STYLE_CLIP_TOP_AUTO as u8 != 0 {
+ debug_assert_eq!(self.gecko.mClip.y, 0);
+ Auto
+ } else {
+ LengthPercentage(Au(self.gecko.mClip.y).into())
+ };
- let bottom = if self.gecko.mClipFlags & NS_STYLE_CLIP_BOTTOM_AUTO as u8 != 0 {
- debug_assert_eq!(self.gecko.mClip.height, 1 << 30); // NS_MAXSIZE
- None
- } else {
- Some(Au(self.gecko.mClip.y + self.gecko.mClip.height).into())
- };
+ let bottom = if self.gecko.mClipFlags & NS_STYLE_CLIP_BOTTOM_AUTO as u8 != 0 {
+ debug_assert_eq!(self.gecko.mClip.height, 1 << 30); // NS_MAXSIZE
+ Auto
+ } else {
+ LengthPercentage(Au(self.gecko.mClip.y + self.gecko.mClip.height).into())
+ };
- let right = if self.gecko.mClipFlags & NS_STYLE_CLIP_RIGHT_AUTO as u8 != 0 {
- debug_assert_eq!(self.gecko.mClip.width, 1 << 30); // NS_MAXSIZE
- None
- } else {
- Some(Au(self.gecko.mClip.x + self.gecko.mClip.width).into())
- };
+ let right = if self.gecko.mClipFlags & NS_STYLE_CLIP_RIGHT_AUTO as u8 != 0 {
+ debug_assert_eq!(self.gecko.mClip.width, 1 << 30); // NS_MAXSIZE
+ Auto
+ } else {
+ LengthPercentage(Au(self.gecko.mClip.x + self.gecko.mClip.width).into())
+ };
- Either::First(ClipRect { top, right, bottom, left })
- }
+ Either::First(ClipRect { top, right, bottom, left })
}
<%
@@ -4238,7 +4129,7 @@ fn static_assert() {
<%self:impl_trait style_struct_name="InheritedText"
- skip_longhands="text-align text-emphasis-style text-shadow line-height letter-spacing word-spacing
+ skip_longhands="text-align text-emphasis-style text-shadow
-webkit-text-stroke-width text-emphasis-position">
<% text_align_keyword = Keyword("text-align",
@@ -4270,78 +4161,6 @@ fn static_assert() {
longhands::text_shadow::computed_value::List(buf)
}
- pub fn set_line_height(&mut self, v: longhands::line_height::computed_value::T) {
- use crate::values::generics::text::LineHeight;
- // FIXME: Align binary representations and ditch |match| for cast + static_asserts
- let en = match v {
- LineHeight::Normal => CoordDataValue::Normal,
- LineHeight::Length(val) => CoordDataValue::Coord(val.0.to_i32_au()),
- LineHeight::Number(val) => CoordDataValue::Factor(val.0),
- LineHeight::MozBlockHeight =>
- CoordDataValue::Enumerated(structs::NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT),
- };
- self.gecko.mLineHeight.set_value(en);
- }
-
- pub fn clone_line_height(&self) -> longhands::line_height::computed_value::T {
- use crate::values::generics::text::LineHeight;
- return match self.gecko.mLineHeight.as_value() {
- CoordDataValue::Normal => LineHeight::Normal,
- CoordDataValue::Coord(coord) => LineHeight::Length(Au(coord).into()),
- CoordDataValue::Factor(n) => LineHeight::Number(n.into()),
- CoordDataValue::Enumerated(val) if val == structs::NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT =>
- LineHeight::MozBlockHeight,
- _ => panic!("this should not happen"),
- }
- }
-
- <%call expr="impl_coord_copy('line_height', 'mLineHeight')"></%call>
-
- pub fn set_letter_spacing(&mut self, v: longhands::letter_spacing::computed_value::T) {
- use crate::values::generics::text::Spacing;
- match v {
- Spacing::Value(value) => self.gecko.mLetterSpacing.set(value),
- Spacing::Normal => self.gecko.mLetterSpacing.set_value(CoordDataValue::Normal)
- }
- }
-
- pub fn clone_letter_spacing(&self) -> longhands::letter_spacing::computed_value::T {
- use crate::values::computed::Length;
- use crate::values::generics::text::Spacing;
- debug_assert!(
- matches!(self.gecko.mLetterSpacing.as_value(),
- CoordDataValue::Normal |
- CoordDataValue::Coord(_)),
- "Unexpected computed value for letter-spacing");
- Length::from_gecko_style_coord(&self.gecko.mLetterSpacing).map_or(Spacing::Normal, Spacing::Value)
- }
-
- <%call expr="impl_coord_copy('letter_spacing', 'mLetterSpacing')"></%call>
-
- pub fn set_word_spacing(&mut self, v: longhands::word_spacing::computed_value::T) {
- use crate::values::generics::text::Spacing;
- match v {
- Spacing::Value(lp) => self.gecko.mWordSpacing.set(lp),
- // https://drafts.csswg.org/css-text-3/#valdef-word-spacing-normal
- Spacing::Normal => self.gecko.mWordSpacing.set_value(CoordDataValue::Coord(0)),
- }
- }
-
- pub fn clone_word_spacing(&self) -> longhands::word_spacing::computed_value::T {
- use crate::values::computed::LengthPercentage;
- use crate::values::generics::text::Spacing;
- debug_assert!(
- matches!(self.gecko.mWordSpacing.as_value(),
- CoordDataValue::Normal |
- CoordDataValue::Coord(_) |
- CoordDataValue::Percent(_) |
- CoordDataValue::Calc(_)),
- "Unexpected computed value for word-spacing");
- LengthPercentage::from_gecko_style_coord(&self.gecko.mWordSpacing).map_or(Spacing::Normal, Spacing::Value)
- }
-
- <%call expr="impl_coord_copy('word_spacing', 'mWordSpacing')"></%call>
-
fn clear_text_emphasis_style_if_string(&mut self) {
if self.gecko.mTextEmphasisStyle == structs::NS_STYLE_TEXT_EMPHASIS_STYLE_STRING as u8 {
self.gecko.mTextEmphasisStyleString.truncate();
@@ -4593,7 +4412,6 @@ fn set_style_svg_path(
use crate::gecko_bindings::bindings::{Gecko_NewBasicShape, Gecko_DestroyShapeSource};
use crate::gecko_bindings::structs::{StyleBasicShape, StyleBasicShapeType, StyleShapeSourceType};
use crate::gecko_bindings::structs::{StyleGeometryBox, StyleShapeSource};
- use crate::gecko::conversions::basic_shape::set_corners_from_radius;
use crate::gecko::values::GeckoStyleCoordConvertible;
use crate::values::generics::basic_shape::{BasicShape, ShapeSource};
@@ -4658,8 +4476,7 @@ fn set_style_svg_path(
inset.rect.2.to_gecko_style_coord(&mut shape.mCoordinates[2]);
shape.mCoordinates[3].leaky_set_null();
inset.rect.3.to_gecko_style_coord(&mut shape.mCoordinates[3]);
-
- set_corners_from_radius(inset.round, &mut shape.mRadius);
+ shape.mRadius = inset.round;
}
BasicShape::Circle(circ) => {
let shape = init_shape(${ident}, StyleBasicShapeType::Circle);
@@ -4747,7 +4564,7 @@ clip-path
pub fn set_stroke_dasharray(&mut self, v: longhands::stroke_dasharray::computed_value::T) {
use crate::gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE;
- use crate::values::generics::svg::{SVGStrokeDashArray, SvgLengthPercentageOrNumber};
+ use crate::values::generics::svg::SVGStrokeDashArray;
match v {
SVGStrokeDashArray::Values(v) => {
@@ -4757,12 +4574,7 @@ clip-path
bindings::Gecko_nsStyleSVG_SetDashArrayLength(&mut self.gecko, v.len() as u32);
}
for (gecko, servo) in self.gecko.mStrokeDasharray.iter_mut().zip(v) {
- match servo {
- SvgLengthPercentageOrNumber::LengthPercentage(lp) =>
- gecko.set(lp),
- SvgLengthPercentageOrNumber::Number(num) =>
- gecko.set_value(CoordDataValue::Factor(num.into())),
- }
+ *gecko = servo;
}
}
SVGStrokeDashArray::ContextValue => {
@@ -4790,32 +4602,13 @@ clip-path
pub fn clone_stroke_dasharray(&self) -> longhands::stroke_dasharray::computed_value::T {
use crate::gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE;
- use crate::values::computed::LengthPercentage;
- use crate::values::generics::NonNegative;
- use crate::values::generics::svg::{SVGStrokeDashArray, SvgLengthPercentageOrNumber};
+ use crate::values::generics::svg::SVGStrokeDashArray;
if self.gecko.mContextFlags & CONTEXT_VALUE != 0 {
debug_assert_eq!(self.gecko.mStrokeDasharray.len(), 0);
return SVGStrokeDashArray::ContextValue;
}
- let mut vec = vec![];
- for gecko in self.gecko.mStrokeDasharray.iter() {
- match gecko.as_value() {
- CoordDataValue::Factor(number) =>
- vec.push(SvgLengthPercentageOrNumber::Number(number.into())),
- CoordDataValue::Coord(coord) =>
- vec.push(SvgLengthPercentageOrNumber::LengthPercentage(
- NonNegative(LengthPercentage::new(Au(coord).into(), None).into()))),
- CoordDataValue::Percent(p) =>
- vec.push(SvgLengthPercentageOrNumber::LengthPercentage(
- NonNegative(LengthPercentage::new_percent(Percentage(p)).into()))),
- CoordDataValue::Calc(calc) =>
- vec.push(SvgLengthPercentageOrNumber::LengthPercentage(
- NonNegative(LengthPercentage::from(calc).clamp_to_non_negative()))),
- _ => unreachable!(),
- }
- }
- SVGStrokeDashArray::Values(vec)
+ SVGStrokeDashArray::Values(self.gecko.mStrokeDasharray.iter().cloned().collect())
}
#[allow(non_snake_case)]
diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs
index 59c9785292c..81931bc713b 100644
--- a/components/style/properties/helpers.mako.rs
+++ b/components/style/properties/helpers.mako.rs
@@ -19,6 +19,8 @@
#[allow(unused_imports)]
use crate::values::specified::AllowQuirks;
#[allow(unused_imports)]
+ use crate::Zero;
+ #[allow(unused_imports)]
use smallvec::SmallVec;
pub use crate::values::specified::${type} as SpecifiedValue;
pub mod computed_value {
@@ -324,29 +326,32 @@
PropertyDeclaration::CSSWideKeyword(ref declaration) => {
debug_assert_eq!(declaration.id, LonghandId::${property.camel_case});
match declaration.keyword {
- % if not data.current_style_struct.inherited:
+ % if not property.style_struct.inherited:
CSSWideKeyword::Unset |
% endif
CSSWideKeyword::Initial => {
- % if property.ident == "font_size":
- computed::FontSize::cascade_initial_font_size(context);
+ % if not property.style_struct.inherited:
+ debug_assert!(false, "Should be handled in apply_properties");
% else:
+ % if property.name == "font-size":
+ computed::FontSize::cascade_initial_font_size(context);
+ % else:
context.builder.reset_${property.ident}();
+ % endif
% endif
},
- % if data.current_style_struct.inherited:
+ % if property.style_struct.inherited:
CSSWideKeyword::Unset |
% endif
CSSWideKeyword::Inherit => {
- % if not property.style_struct.inherited:
- context.rule_cache_conditions.borrow_mut().set_uncacheable();
- % endif
- % if property.ident == "font_size":
- computed::FontSize::cascade_inherit_font_size(context);
+ % if property.style_struct.inherited:
+ debug_assert!(false, "Should be handled in apply_properties");
% else:
+ context.rule_cache_conditions.borrow_mut().set_uncacheable();
context.builder.inherit_${property.ident}();
% endif
}
+ CSSWideKeyword::Revert => unreachable!("Should never get here"),
}
return;
}
diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs
index fcc6e48b41b..aa2d0247e82 100644
--- a/components/style/properties/helpers/animated_properties.mako.rs
+++ b/components/style/properties/helpers/animated_properties.mako.rs
@@ -452,14 +452,23 @@ impl AnimationValue {
% for prop in data.longhands:
% if prop.animatable:
LonghandId::${prop.camel_case} => {
+ // FIXME(emilio, bug 1533327): I think
+ // CSSWideKeyword::Revert handling is not fine here, but
+ // what to do instead?
+ //
+ // Seems we'd need the computed value as if it was
+ // revert, somehow. Treating it as `unset` seems fine
+ // for now...
let style_struct = match declaration.keyword {
% if not prop.style_struct.inherited:
+ CSSWideKeyword::Revert |
CSSWideKeyword::Unset |
% endif
CSSWideKeyword::Initial => {
initial.get_${prop.style_struct.name_lower}()
},
% if prop.style_struct.inherited:
+ CSSWideKeyword::Revert |
CSSWideKeyword::Unset |
% endif
CSSWideKeyword::Inherit => {
@@ -802,29 +811,29 @@ impl ToAnimatedZero for Visibility {
impl Animate for ClipRect {
#[inline]
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
- use crate::values::computed::Length;
- let animate_component = |this: &Option<Length>, other: &Option<Length>| {
- match (this.animate(other, procedure)?, procedure) {
- (None, Procedure::Interpolate { .. }) => Ok(None),
- (None, _) => Err(()),
- (result, _) => Ok(result),
+ use crate::values::computed::LengthOrAuto;
+ let animate_component = |this: &LengthOrAuto, other: &LengthOrAuto| {
+ let result = this.animate(other, procedure)?;
+ if let Procedure::Interpolate { .. } = procedure {
+ return Ok(result);
}
+ if result.is_auto() {
+ // FIXME(emilio): Why? A couple SMIL tests fail without this,
+ // but it seems extremely fishy.
+ return Err(());
+ }
+ Ok(result)
};
Ok(ClipRect {
- top: animate_component(&self.top, &other.top)?,
- right: animate_component(&self.right, &other.right)?,
+ top: animate_component(&self.top, &other.top)?,
+ right: animate_component(&self.right, &other.right)?,
bottom: animate_component(&self.bottom, &other.bottom)?,
- left: animate_component(&self.left, &other.left)?,
+ left: animate_component(&self.left, &other.left)?,
})
}
}
-impl ToAnimatedZero for ClipRect {
- #[inline]
- fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
-}
-
<%
FILTER_FUNCTIONS = [ 'Blur', 'Brightness', 'Contrast', 'Grayscale',
'HueRotate', 'Invert', 'Opacity', 'Saturate',
diff --git a/components/style/properties/longhands/column.mako.rs b/components/style/properties/longhands/column.mako.rs
index 90c37a9710f..f61b78acf46 100644
--- a/components/style/properties/longhands/column.mako.rs
+++ b/components/style/properties/longhands/column.mako.rs
@@ -9,8 +9,8 @@
${helpers.predefined_type(
"column-width",
"length::NonNegativeLengthOrAuto",
- "Either::Second(Auto)",
- initial_specified_value="Either::Second(Auto)",
+ "computed::length::NonNegativeLengthOrAuto::auto()",
+ initial_specified_value="specified::length::NonNegativeLengthOrAuto::auto()",
extra_prefixes="moz",
animation_value_type="NonNegativeLengthOrAuto",
servo_pref="layout.columns.enabled",
diff --git a/components/style/properties/longhands/inherited_svg.mako.rs b/components/style/properties/longhands/inherited_svg.mako.rs
index fcd16833b5f..2bbdc2794c2 100644
--- a/components/style/properties/longhands/inherited_svg.mako.rs
+++ b/components/style/properties/longhands/inherited_svg.mako.rs
@@ -84,7 +84,8 @@ ${helpers.predefined_type(
)}
${helpers.predefined_type(
- "stroke-width", "SVGWidth",
+ "stroke-width",
+ "SVGWidth",
"computed::SVGWidth::one()",
products="gecko",
animation_value_type="crate::values::computed::SVGWidth",
@@ -109,11 +110,11 @@ ${helpers.single_keyword(
${helpers.predefined_type(
"stroke-miterlimit",
- "GreaterThanOrEqualToOneNumber",
+ "NonNegativeNumber",
"From::from(4.0)",
products="gecko",
- animation_value_type="crate::values::computed::GreaterThanOrEqualToOneNumber",
- spec="https://www.w3.org/TR/SVG11/painting.html#StrokeMiterlimitProperty",
+ animation_value_type="crate::values::computed::NonNegativeNumber",
+ spec="https://www.w3.org/TR/SVG2/painting.html#StrokeMiterlimitProperty",
)}
${helpers.predefined_type(
diff --git a/components/style/properties/longhands/inherited_text.mako.rs b/components/style/properties/longhands/inherited_text.mako.rs
index 97d551120a4..f61c8754b5e 100644
--- a/components/style/properties/longhands/inherited_text.mako.rs
+++ b/components/style/properties/longhands/inherited_text.mako.rs
@@ -74,13 +74,13 @@ ${helpers.predefined_type(
servo_restyle_damage="rebuild_and_reflow",
)}
-// TODO(pcwalton): Support `word-break: keep-all` once we have better CJK support.
-${helpers.single_keyword(
+${helpers.predefined_type(
"word-break",
- "normal break-all keep-all",
- gecko_constant_prefix="NS_STYLE_WORDBREAK",
+ "WordBreak",
+ "computed::WordBreak::Normal",
animation_value_type="discrete",
spec="https://drafts.csswg.org/css-text/#propdef-word-break",
+ needs_context=False,
servo_restyle_damage="rebuild_and_reflow",
)}
@@ -157,7 +157,7 @@ ${helpers.predefined_type(
${helpers.predefined_type(
"word-spacing",
"WordSpacing",
- "computed::WordSpacing::normal()",
+ "computed::WordSpacing::zero()",
animation_value_type="ComputedValue",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-text/#propdef-word-spacing",
diff --git a/components/style/properties/longhands/padding.mako.rs b/components/style/properties/longhands/padding.mako.rs
index 6c4e2b32cf9..a1262aee0fc 100644
--- a/components/style/properties/longhands/padding.mako.rs
+++ b/components/style/properties/longhands/padding.mako.rs
@@ -39,6 +39,6 @@
logical=side[1],
logical_group="scroll-padding",
spec="https://drafts.csswg.org/css-scroll-snap-1/#propdef-scroll-padding-%s" % side[0],
- animation_value_type="ComputedValue",
+ animation_value_type="NonNegativeLengthPercentageOrAuto",
)}
% endfor
diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs
index 7e35d318c30..0153d6fe336 100644
--- a/components/style/properties/properties.mako.rs
+++ b/components/style/properties/properties.mako.rs
@@ -42,6 +42,7 @@ use crate::values::computed;
use crate::values::computed::NonNegativeLength;
use crate::values::serialize_atom_name;
use crate::rule_tree::StrongRuleNode;
+use crate::Zero;
use self::computed_value_flags::*;
use crate::str::{CssString, CssStringBorrow, CssStringWriter};
@@ -899,6 +900,8 @@ pub enum CSSWideKeyword {
Inherit,
/// The `unset` keyword.
Unset,
+ /// The `revert` keyword.
+ Revert,
}
impl CSSWideKeyword {
@@ -907,6 +910,7 @@ impl CSSWideKeyword {
CSSWideKeyword::Initial => "initial",
CSSWideKeyword::Inherit => "inherit",
CSSWideKeyword::Unset => "unset",
+ CSSWideKeyword::Revert => "revert",
}
}
}
@@ -920,6 +924,7 @@ impl CSSWideKeyword {
"initial" => CSSWideKeyword::Initial,
"inherit" => CSSWideKeyword::Inherit,
"unset" => CSSWideKeyword::Unset,
+ "revert" => CSSWideKeyword::Revert,
_ => return Err(()),
}
};
@@ -2102,6 +2107,7 @@ impl PropertyDeclaration {
}
/// Returns a CSS-wide keyword if the declaration's value is one.
+ #[inline]
pub fn get_css_wide_keyword(&self) -> Option<CSSWideKeyword> {
match *self {
PropertyDeclaration::CSSWideKeyword(ref declaration) => {
@@ -2585,7 +2591,8 @@ pub mod style_structs {
/// Whether the border-${side} property has nonzero width.
#[allow(non_snake_case)]
pub fn border_${side}_has_nonzero_width(&self) -> bool {
- self.border_${side}_width != NonNegativeLength::zero()
+ use crate::Zero;
+ !self.border_${side}_width.is_zero()
}
% endfor
% elif style_struct.name == "Font":
@@ -2624,7 +2631,8 @@ pub mod style_structs {
/// Whether the outline-width property is non-zero.
#[inline]
pub fn outline_has_nonzero_width(&self) -> bool {
- self.outline_width != NonNegativeLength::zero()
+ use crate::Zero;
+ !self.outline_width.is_zero()
}
% elif style_struct.name == "Text":
/// Whether the text decoration has an underline.
@@ -2718,11 +2726,7 @@ pub mod style_structs {
/// Whether this is a multicol style.
#[cfg(feature = "servo")]
pub fn is_multicol(&self) -> bool {
- use crate::values::Either;
- match self.column_width {
- Either::First(_width) => true,
- Either::Second(_auto) => !self.column_count.is_auto(),
- }
+ !self.column_width.is_auto() || !self.column_count.is_auto()
}
% endif
}
@@ -3435,22 +3439,16 @@ impl<'a> StyleBuilder<'a> {
}
% for property in data.longhands:
- % if property.ident != "font_size":
+ % if not property.style_struct.inherited:
/// Inherit `${property.ident}` from our parent style.
#[allow(non_snake_case)]
pub fn inherit_${property.ident}(&mut self) {
let inherited_struct =
- % if property.style_struct.inherited:
- self.inherited_style.get_${property.style_struct.name_lower}();
- % else:
self.inherited_style_ignoring_first_line
.get_${property.style_struct.name_lower}();
- % endif
- % if not property.style_struct.inherited:
- self.flags.insert(ComputedValueFlags::INHERITS_RESET_STYLE);
self.modified_reset = true;
- % endif
+ self.flags.insert(ComputedValueFlags::INHERITS_RESET_STYLE);
% if property.ident == "content":
self.flags.insert(ComputedValueFlags::INHERITS_CONTENT);
@@ -3472,17 +3470,13 @@ impl<'a> StyleBuilder<'a> {
% endif
);
}
-
+ % elif property.name != "font-size":
/// Reset `${property.ident}` to the initial value.
#[allow(non_snake_case)]
pub fn reset_${property.ident}(&mut self) {
let reset_struct =
self.reset_style.get_${property.style_struct.name_lower}();
- % if not property.style_struct.inherited:
- self.modified_reset = true;
- % endif
-
if self.${property.style_struct.ident}.ptr_eq(reset_struct) {
return;
}
@@ -3495,6 +3489,7 @@ impl<'a> StyleBuilder<'a> {
% endif
);
}
+ % endif
% if not property.is_vector:
/// Set the `${property.ident}` to the computed value `value`.
@@ -3516,7 +3511,6 @@ impl<'a> StyleBuilder<'a> {
);
}
% endif
- % endif
% endfor
<% del property %>
diff --git a/components/style/rule_tree/mod.rs b/components/style/rule_tree/mod.rs
index a2caba6f9f7..f165e1f455f 100644
--- a/components/style/rule_tree/mod.rs
+++ b/components/style/rule_tree/mod.rs
@@ -11,7 +11,7 @@ use crate::applicable_declarations::ApplicableDeclarationList;
use crate::gecko::selector_parser::PseudoElement;
use crate::properties::{Importance, LonghandIdSet, PropertyDeclarationBlock};
use crate::shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
-use crate::stylesheets::StyleRule;
+use crate::stylesheets::{Origin, StyleRule};
use crate::thread_state;
#[cfg(feature = "gecko")]
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
@@ -659,6 +659,25 @@ impl CascadeLevel {
}
}
+ /// Returns the cascade origin of the rule.
+ #[inline]
+ pub fn origin(&self) -> Origin {
+ match *self {
+ CascadeLevel::UAImportant | CascadeLevel::UANormal => Origin::UserAgent,
+ CascadeLevel::UserImportant | CascadeLevel::UserNormal => Origin::User,
+ CascadeLevel::PresHints |
+ CascadeLevel::InnerShadowNormal |
+ CascadeLevel::SameTreeAuthorNormal |
+ CascadeLevel::StyleAttributeNormal |
+ CascadeLevel::SMILOverride |
+ CascadeLevel::Animations |
+ CascadeLevel::SameTreeAuthorImportant |
+ CascadeLevel::StyleAttributeImportant |
+ CascadeLevel::InnerShadowImportant |
+ CascadeLevel::Transitions => Origin::Author,
+ }
+ }
+
/// Returns whether this cascade level represents an animation rules.
#[inline]
pub fn is_animation(&self) -> bool {
diff --git a/components/style/stylesheets/origin.rs b/components/style/stylesheets/origin.rs
index 69b9b866c86..fc89260abd2 100644
--- a/components/style/stylesheets/origin.rs
+++ b/components/style/stylesheets/origin.rs
@@ -36,6 +36,25 @@ impl Origin {
_ => return None,
})
}
+
+ fn to_index(self) -> i8 {
+ match self {
+ Origin::Author => 0,
+ Origin::User => 1,
+ Origin::UserAgent => 2,
+ }
+ }
+
+ /// Returns an iterator from this origin, towards all the less specific
+ /// origins. So for `UserAgent`, it'd iterate through all origins.
+ #[inline]
+ pub fn following_including(self) -> OriginSetIterator {
+ OriginSetIterator {
+ set: OriginSet::ORIGIN_USER | OriginSet::ORIGIN_AUTHOR | OriginSet::ORIGIN_USER_AGENT,
+ cur: self.to_index(),
+ rev: true,
+ }
+ }
}
bitflags! {
@@ -57,7 +76,11 @@ impl OriginSet {
/// See the `OriginSet` documentation for information about the order
/// origins are iterated.
pub fn iter(&self) -> OriginSetIterator {
- OriginSetIterator { set: *self, cur: 0 }
+ OriginSetIterator {
+ set: *self,
+ cur: 0,
+ rev: false,
+ }
}
}
@@ -79,6 +102,7 @@ impl BitOrAssign<Origin> for OriginSet {
pub struct OriginSetIterator {
set: OriginSet,
cur: i8,
+ rev: bool,
}
impl Iterator for OriginSetIterator {
@@ -88,7 +112,11 @@ impl Iterator for OriginSetIterator {
loop {
let origin = Origin::from_index(self.cur)?;
- self.cur += 1;
+ if self.rev {
+ self.cur -= 1;
+ } else {
+ self.cur += 1;
+ }
if self.set.contains(origin.into()) {
return Some(origin);
diff --git a/components/style/traversal.rs b/components/style/traversal.rs
index f1821900bb4..d5a9a5c5033 100644
--- a/components/style/traversal.rs
+++ b/components/style/traversal.rs
@@ -686,7 +686,7 @@ where
// sibling or cousin. Otherwise, recascading a bunch of identical
// elements would unnecessarily flood the cache with identical entries.
//
- // This is analagous to the obvious "don't insert an element that just
+ // This is analogous to the obvious "don't insert an element that just
// got a hit in the style sharing cache" behavior in the MatchAndCascade
// handling above.
//
diff --git a/components/style/values/animated/mod.rs b/components/style/values/animated/mod.rs
index 6bc7f624e34..3b83c71e6e2 100644
--- a/components/style/values/animated/mod.rs
+++ b/components/style/values/animated/mod.rs
@@ -16,7 +16,7 @@ use crate::values::computed::Image;
use crate::values::specified::SVGPathData;
use crate::values::CSSFloat;
use app_units::Au;
-use euclid::{Point2D, Size2D};
+use euclid::Point2D;
use smallvec::SmallVec;
use std::cmp;
@@ -241,19 +241,6 @@ impl Animate for Au {
}
}
-impl<T> Animate for Size2D<T>
-where
- T: Animate,
-{
- #[inline]
- fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
- Ok(Size2D::new(
- self.width.animate(&other.width, procedure)?,
- self.height.animate(&other.height, procedure)?,
- ))
- }
-}
-
impl<T> Animate for Point2D<T>
where
T: Animate,
@@ -397,16 +384,13 @@ where
}
}
-impl<T> ToAnimatedZero for Size2D<T>
+impl<T> ToAnimatedZero for Vec<T>
where
T: ToAnimatedZero,
{
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
- Ok(Size2D::new(
- self.width.to_animated_zero()?,
- self.height.to_animated_zero()?,
- ))
+ self.iter().map(|v| v.to_animated_zero()).collect()
}
}
diff --git a/components/style/values/animated/svg.rs b/components/style/values/animated/svg.rs
index 4564b787c6d..436bb73d658 100644
--- a/components/style/values/animated/svg.rs
+++ b/components/style/values/animated/svg.rs
@@ -8,10 +8,8 @@ use super::{Animate, Procedure, ToAnimatedZero};
use crate::properties::animated_properties::ListAnimation;
use crate::values::animated::color::Color as AnimatedColor;
use crate::values::computed::url::ComputedUrl;
-use crate::values::computed::{LengthPercentage, Number, NumberOrPercentage};
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
-use crate::values::generics::svg::{SVGLength, SVGPaint, SvgLengthPercentageOrNumber};
-use crate::values::generics::svg::{SVGOpacity, SVGStrokeDashArray};
+use crate::values::generics::svg::{SVGPaint, SVGStrokeDashArray};
/// Animated SVGPaint.
pub type IntermediateSVGPaint = SVGPaint<AnimatedColor, ComputedUrl>;
@@ -26,67 +24,6 @@ impl ToAnimatedZero for IntermediateSVGPaint {
}
}
-// FIXME: We need to handle calc here properly, see
-// https://bugzilla.mozilla.org/show_bug.cgi?id=1386967
-fn to_number_or_percentage(
- value: &SvgLengthPercentageOrNumber<LengthPercentage, Number>,
-) -> Result<NumberOrPercentage, ()> {
- Ok(match *value {
- SvgLengthPercentageOrNumber::LengthPercentage(ref l) => match l.specified_percentage() {
- Some(p) => {
- if l.unclamped_length().px() != 0. {
- return Err(());
- }
- NumberOrPercentage::Percentage(p)
- },
- None => NumberOrPercentage::Number(l.length().px()),
- },
- SvgLengthPercentageOrNumber::Number(ref n) => NumberOrPercentage::Number(*n),
- })
-}
-
-impl Animate for SvgLengthPercentageOrNumber<LengthPercentage, Number> {
- #[inline]
- fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
- let this = to_number_or_percentage(self)?;
- let other = to_number_or_percentage(other)?;
-
- match (this, other) {
- (NumberOrPercentage::Number(ref this), NumberOrPercentage::Number(ref other)) => Ok(
- SvgLengthPercentageOrNumber::Number(this.animate(other, procedure)?),
- ),
- (
- NumberOrPercentage::Percentage(ref this),
- NumberOrPercentage::Percentage(ref other),
- ) => Ok(SvgLengthPercentageOrNumber::LengthPercentage(
- LengthPercentage::new_percent(this.animate(other, procedure)?),
- )),
- _ => Err(()),
- }
- }
-}
-
-impl ComputeSquaredDistance for SvgLengthPercentageOrNumber<LengthPercentage, Number> {
- fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
- to_number_or_percentage(self)?.compute_squared_distance(&to_number_or_percentage(other)?)
- }
-}
-
-impl<L> Animate for SVGLength<L>
-where
- L: Animate + Clone,
-{
- #[inline]
- fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
- match (self, other) {
- (&SVGLength::Length(ref this), &SVGLength::Length(ref other)) => {
- Ok(SVGLength::Length(this.animate(other, procedure)?))
- },
- _ => Err(()),
- }
- }
-}
-
/// <https://www.w3.org/TR/SVG11/painting.html#StrokeDasharrayProperty>
impl<L> Animate for SVGStrokeDashArray<L>
where
@@ -121,36 +58,3 @@ where
}
}
}
-
-impl<L> ToAnimatedZero for SVGStrokeDashArray<L>
-where
- L: ToAnimatedZero,
-{
- #[inline]
- fn to_animated_zero(&self) -> Result<Self, ()> {
- match *self {
- SVGStrokeDashArray::Values(ref values) => Ok(SVGStrokeDashArray::Values(
- values
- .iter()
- .map(ToAnimatedZero::to_animated_zero)
- .collect::<Result<Vec<_>, _>>()?,
- )),
- SVGStrokeDashArray::ContextValue => Ok(SVGStrokeDashArray::ContextValue),
- }
- }
-}
-
-impl<O> Animate for SVGOpacity<O>
-where
- O: Animate + Clone,
-{
- #[inline]
- fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
- match (self, other) {
- (&SVGOpacity::Opacity(ref this), &SVGOpacity::Opacity(ref other)) => {
- Ok(SVGOpacity::Opacity(this.animate(other, procedure)?))
- },
- _ => Err(()),
- }
- }
-}
diff --git a/components/style/values/animated/transform.rs b/components/style/values/animated/transform.rs
index c341ca770ed..0c322d8fccc 100644
--- a/components/style/values/animated/transform.rs
+++ b/components/style/values/animated/transform.rs
@@ -22,7 +22,7 @@ use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
use crate::values::generics::transform::{self, Transform, TransformOperation};
use crate::values::generics::transform::{Rotate, Scale, Translate};
use crate::values::CSSFloat;
-use num_traits::Zero;
+use crate::Zero;
use std::cmp;
// ------------------------------------
@@ -1003,18 +1003,12 @@ impl Animate for ComputedTransformOperation {
(&TransformOperation::Matrix(ref this), &TransformOperation::Matrix(ref other)) => {
Ok(TransformOperation::Matrix(this.animate(other, procedure)?))
},
- (&TransformOperation::Skew(ref fx, None), &TransformOperation::Skew(ref tx, None)) => {
- Ok(TransformOperation::Skew(fx.animate(tx, procedure)?, None))
- },
(
&TransformOperation::Skew(ref fx, ref fy),
&TransformOperation::Skew(ref tx, ref ty),
) => Ok(TransformOperation::Skew(
fx.animate(tx, procedure)?,
- Some(
- fy.unwrap_or(Angle::zero())
- .animate(&ty.unwrap_or(Angle::zero()), procedure)?,
- ),
+ fy.animate(ty, procedure)?,
)),
(&TransformOperation::SkewX(ref f), &TransformOperation::SkewX(ref t)) => {
Ok(TransformOperation::SkewX(f.animate(t, procedure)?))
@@ -1031,21 +1025,11 @@ impl Animate for ComputedTransformOperation {
fz.animate(tz, procedure)?,
)),
(
- &TransformOperation::Translate(ref fx, None),
- &TransformOperation::Translate(ref tx, None),
- ) => Ok(TransformOperation::Translate(
- fx.animate(tx, procedure)?,
- None,
- )),
- (
&TransformOperation::Translate(ref fx, ref fy),
&TransformOperation::Translate(ref tx, ref ty),
) => Ok(TransformOperation::Translate(
fx.animate(tx, procedure)?,
- Some(
- fy.unwrap_or(LengthPercentage::zero())
- .animate(&ty.unwrap_or(LengthPercentage::zero()), procedure)?,
- ),
+ fy.animate(ty, procedure)?,
)),
(&TransformOperation::TranslateX(ref f), &TransformOperation::TranslateX(ref t)) => {
Ok(TransformOperation::TranslateX(f.animate(t, procedure)?))
@@ -1073,22 +1057,12 @@ impl Animate for ComputedTransformOperation {
(&TransformOperation::ScaleZ(ref f), &TransformOperation::ScaleZ(ref t)) => Ok(
TransformOperation::ScaleZ(animate_multiplicative_factor(*f, *t, procedure)?),
),
- (&TransformOperation::Scale(ref f, None), &TransformOperation::Scale(ref t, None)) => {
- Ok(TransformOperation::Scale(
- animate_multiplicative_factor(*f, *t, procedure)?,
- None,
- ))
- },
(
&TransformOperation::Scale(ref fx, ref fy),
&TransformOperation::Scale(ref tx, ref ty),
) => Ok(TransformOperation::Scale(
animate_multiplicative_factor(*fx, *tx, procedure)?,
- Some(animate_multiplicative_factor(
- fy.unwrap_or(*fx),
- ty.unwrap_or(*tx),
- procedure,
- )?),
+ animate_multiplicative_factor(*fy, *ty, procedure)?,
)),
(
&TransformOperation::Rotate3D(fx, fy, fz, fa),
diff --git a/components/style/values/computed/angle.rs b/components/style/values/computed/angle.rs
index d30f02d7200..76e44575dfb 100644
--- a/components/style/values/computed/angle.rs
+++ b/components/style/values/computed/angle.rs
@@ -6,7 +6,7 @@
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
use crate::values::CSSFloat;
-use num_traits::Zero;
+use crate::Zero;
use std::f64::consts::PI;
use std::fmt::{self, Write};
use std::{f32, f64};
diff --git a/components/style/values/computed/border.rs b/components/style/values/computed/border.rs
index e85b5a3e5d6..62c8e3883f6 100644
--- a/components/style/values/computed/border.rs
+++ b/components/style/values/computed/border.rs
@@ -12,8 +12,9 @@ use crate::values::generics::border::BorderImageSlice as GenericBorderImageSlice
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::size::Size2D;
use crate::values::generics::NonNegative;
+use crate::Zero;
use app_units::Au;
pub use crate::values::specified::border::BorderImageRepeat;
@@ -59,7 +60,7 @@ impl BorderImageSlice {
impl BorderSpacing {
/// Returns `0 0`.
pub fn zero() -> Self {
- GenericBorderSpacing(Size::new(
+ GenericBorderSpacing(Size2D::new(
NonNegativeLength::zero(),
NonNegativeLength::zero(),
))
@@ -75,29 +76,3 @@ impl BorderSpacing {
Au::from(*self.0.height())
}
}
-
-impl BorderCornerRadius {
- /// Returns `0 0`.
- pub fn zero() -> Self {
- GenericBorderCornerRadius(Size::new(
- NonNegativeLengthPercentage::zero(),
- NonNegativeLengthPercentage::zero(),
- ))
- }
-}
-
-impl BorderRadius {
- /// Returns whether all the values are `0px`.
- pub fn all_zero(&self) -> bool {
- fn all(corner: &BorderCornerRadius) -> bool {
- fn is_zero(l: &NonNegativeLengthPercentage) -> bool {
- *l == NonNegativeLengthPercentage::zero()
- }
- is_zero(corner.0.width()) && is_zero(corner.0.height())
- }
- all(&self.top_left) &&
- all(&self.top_right) &&
- all(&self.bottom_left) &&
- all(&self.bottom_right)
- }
-}
diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs
index f578bbbd5ce..1262e4dd1d5 100644
--- a/components/style/values/computed/length.rs
+++ b/components/style/values/computed/length.rs
@@ -12,11 +12,11 @@ use crate::values::generics::length as generics;
use crate::values::generics::length::{
GenericLengthOrNumber, MaxSize as GenericMaxSize, Size as GenericSize,
};
-use crate::values::generics::transform::IsZeroLength;
use crate::values::generics::NonNegative;
use crate::values::specified::length::ViewportPercentageLength;
use crate::values::specified::length::{AbsoluteLength, FontBaseSize, FontRelativeLength};
-use crate::values::{specified, Auto, CSSFloat, Either, Normal};
+use crate::values::{specified, CSSFloat, Either, Normal};
+use crate::Zero;
use app_units::Au;
use ordered_float::NotNan;
use std::fmt::{self, Write};
@@ -203,12 +203,7 @@ impl LengthPercentage {
return None;
}
- if self.clamping_mode.clamp(self.percentage.0) != self.percentage.0 {
- debug_assert!(self.was_calc);
- return None;
- }
-
- Some(self.percentage)
+ Some(Percentage(self.clamping_mode.clamp(self.percentage.0)))
}
/// Convert the computed value into used value.
@@ -347,12 +342,6 @@ impl ToComputedValue for specified::CalcLengthPercentage {
}
impl LengthPercentage {
- #[inline]
- #[allow(missing_docs)]
- pub fn zero() -> LengthPercentage {
- LengthPercentage::new(Length::new(0.), None)
- }
-
/// 1px length value for SVG defaults
#[inline]
pub fn one() -> LengthPercentage {
@@ -433,14 +422,13 @@ impl ToComputedValue for specified::LengthPercentage {
}
fn from_computed_value(computed: &LengthPercentage) -> Self {
- let length = computed.unclamped_length();
if let Some(p) = computed.as_percentage() {
return specified::LengthPercentage::Percentage(p);
}
- if !computed.has_percentage && computed.clamping_mode.clamp(length.px()) == length.px() {
+ if !computed.has_percentage {
return specified::LengthPercentage::Length(ToComputedValue::from_computed_value(
- &length,
+ &computed.length(),
));
}
@@ -448,9 +436,13 @@ impl ToComputedValue for specified::LengthPercentage {
}
}
-impl IsZeroLength for LengthPercentage {
+impl Zero for LengthPercentage {
+ fn zero() -> Self {
+ LengthPercentage::new(Length::zero(), None)
+ }
+
#[inline]
- fn is_zero_length(&self) -> bool {
+ fn is_zero(&self) -> bool {
self.is_definitely_zero()
}
}
@@ -459,12 +451,6 @@ impl IsZeroLength for LengthPercentage {
/// length-percentage or auto.
macro_rules! computed_length_percentage_or_auto {
($inner:ty) => {
- /// Returns the `0` value.
- #[inline]
- pub fn zero() -> Self {
- generics::LengthPercentageOrAuto::LengthPercentage(<$inner>::zero())
- }
-
/// Returns the used value.
#[inline]
pub fn to_used_value(&self, percentage_basis: Au) -> Option<Au> {
@@ -553,12 +539,6 @@ impl From<Au> for LengthPercentage {
}
impl NonNegativeLengthPercentage {
- /// Get zero value.
- #[inline]
- pub fn zero() -> Self {
- NonNegative(LengthPercentage::zero())
- }
-
/// Returns true if the computed value is absolute 0 or 0%.
#[inline]
pub fn is_definitely_zero(&self) -> bool {
@@ -662,12 +642,16 @@ impl CSSPixelLength {
pub fn clamp_to_non_negative(self) -> Self {
CSSPixelLength::new(self.0.max(0.))
}
+}
- /// Zero value
- #[inline]
- pub fn zero() -> Self {
+impl Zero for CSSPixelLength {
+ fn zero() -> Self {
CSSPixelLength::new(0.)
}
+
+ fn is_zero(&self) -> bool {
+ self.px() == 0.
+ }
}
impl ToCss for CSSPixelLength {
@@ -717,7 +701,10 @@ impl From<Au> for CSSPixelLength {
pub type Length = CSSPixelLength;
/// Either a computed `<length>` or the `auto` keyword.
-pub type LengthOrAuto = Either<Length, Auto>;
+pub type LengthOrAuto = generics::GenericLengthPercentageOrAuto<Length>;
+
+/// Either a non-negative `<length>` or the `auto` keyword.
+pub type NonNegativeLengthOrAuto = generics::GenericLengthPercentageOrAuto<NonNegativeLength>;
/// Either a computed `<length>` or a `<number>` value.
pub type LengthOrNumber = GenericLengthOrNumber<Length, Number>;
@@ -749,12 +736,6 @@ impl NonNegativeLength {
NonNegative(Length::new(px.max(0.)))
}
- /// Return a zero value.
- #[inline]
- pub fn zero() -> Self {
- Self::new(0.)
- }
-
/// Return the pixel value of |NonNegativeLength|.
#[inline]
pub fn px(&self) -> CSSFloat {
@@ -801,9 +782,6 @@ impl From<NonNegativeLength> for Au {
}
}
-/// Either a computed NonNegativeLength or the `auto` keyword.
-pub type NonNegativeLengthOrAuto = Either<NonNegativeLength, Auto>;
-
/// Either a computed NonNegativeLength or the `normal` keyword.
pub type NonNegativeLengthOrNormal = Either<NonNegativeLength, Normal>;
diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs
index 6fe36d684f2..1f7d1e3eddc 100644
--- a/components/style/values/computed/mod.rs
+++ b/components/style/values/computed/mod.rs
@@ -10,7 +10,7 @@ use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent
use super::generics::grid::{GridLine as GenericGridLine, TrackBreadth as GenericTrackBreadth};
use super::generics::grid::{TrackList as GenericTrackList, TrackSize as GenericTrackSize};
use super::generics::transform::IsParallelTo;
-use super::generics::{GreaterThanOrEqualToOne, NonNegative};
+use super::generics::{self, GreaterThanOrEqualToOne, NonNegative};
use super::specified;
use super::{CSSFloat, CSSInteger};
use crate::context::QuirksMode;
@@ -27,8 +27,6 @@ use euclid::Size2D;
use std::cell::RefCell;
use std::cmp;
use std::f32;
-use std::fmt::{self, Write};
-use style_traits::{CssWriter, ToCss};
#[cfg(feature = "gecko")]
pub use self::align::{AlignContent, AlignItems, JustifyContent, JustifyItems, SelfAlignment};
@@ -62,7 +60,7 @@ pub use self::gecko::ScrollSnapPoint;
pub use self::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection, MozImageRect};
pub use self::length::{CSSPixelLength, ExtremumLength, NonNegativeLength};
pub use self::length::{Length, LengthOrNumber, LengthPercentage, NonNegativeLengthOrNumber};
-pub use self::length::{LengthPercentageOrAuto, MaxSize, Size};
+pub use self::length::{LengthOrAuto, LengthPercentageOrAuto, MaxSize, Size};
pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto};
#[cfg(feature = "gecko")]
pub use self::list::ListStyleType;
@@ -78,7 +76,7 @@ pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind};
pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
pub use self::table::XSpan;
pub use self::text::{InitialLetter, LetterSpacing, LineHeight};
-pub use self::text::{OverflowWrap, TextOverflow, WordSpacing};
+pub use self::text::{OverflowWrap, TextOverflow, WordBreak, WordSpacing};
pub use self::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle};
pub use self::time::Time;
pub use self::transform::{Rotate, Scale, Transform, TransformOperation};
@@ -637,52 +635,8 @@ impl From<CSSInteger> for PositiveInteger {
}
}
-#[allow(missing_docs)]
-#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
-#[derive(Clone, ComputeSquaredDistance, Copy, Debug, PartialEq)]
-/// A computed cliprect for clip and image-region
-pub struct ClipRect {
- pub top: Option<Length>,
- pub right: Option<Length>,
- pub bottom: Option<Length>,
- pub left: Option<Length>,
-}
-
-impl ToCss for ClipRect {
- fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
- where
- W: Write,
- {
- dest.write_str("rect(")?;
- if let Some(top) = self.top {
- top.to_css(dest)?;
- dest.write_str(", ")?;
- } else {
- dest.write_str("auto, ")?;
- }
-
- if let Some(right) = self.right {
- right.to_css(dest)?;
- dest.write_str(", ")?;
- } else {
- dest.write_str("auto, ")?;
- }
-
- if let Some(bottom) = self.bottom {
- bottom.to_css(dest)?;
- dest.write_str(", ")?;
- } else {
- dest.write_str("auto, ")?;
- }
-
- if let Some(left) = self.left {
- left.to_css(dest)?;
- } else {
- dest.write_str("auto")?;
- }
- dest.write_str(")")
- }
-}
+/// rect(...)
+pub type ClipRect = generics::ClipRect<LengthOrAuto>;
/// rect(...) | auto
pub type ClipRectOrAuto = Either<ClipRect, Auto>;
diff --git a/components/style/values/computed/percentage.rs b/components/style/values/computed/percentage.rs
index 67bdda76033..4f39a7a7274 100644
--- a/components/style/values/computed/percentage.rs
+++ b/components/style/values/computed/percentage.rs
@@ -7,6 +7,7 @@
use crate::values::animated::ToAnimatedValue;
use crate::values::generics::NonNegative;
use crate::values::{serialize_percentage, CSSFloat};
+use crate::Zero;
use std::fmt;
use style_traits::{CssWriter, ToCss};
@@ -31,12 +32,6 @@ use style_traits::{CssWriter, ToCss};
pub struct Percentage(pub CSSFloat);
impl Percentage {
- /// 0%
- #[inline]
- pub fn zero() -> Self {
- Percentage(0.)
- }
-
/// 100%
#[inline]
pub fn hundred() -> Self {
@@ -56,6 +51,16 @@ impl Percentage {
}
}
+impl Zero for Percentage {
+ fn zero() -> Self {
+ Percentage(0.)
+ }
+
+ fn is_zero(&self) -> bool {
+ self.0 == 0.
+ }
+}
+
impl ToCss for Percentage {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
@@ -69,12 +74,6 @@ impl ToCss for Percentage {
pub type NonNegativePercentage = NonNegative<Percentage>;
impl NonNegativePercentage {
- /// 0%
- #[inline]
- pub fn zero() -> Self {
- NonNegative(Percentage::zero())
- }
-
/// 100%
#[inline]
pub fn hundred() -> Self {
diff --git a/components/style/values/computed/position.rs b/components/style/values/computed/position.rs
index d6f9161903b..f0f8fe198a6 100644
--- a/components/style/values/computed/position.rs
+++ b/components/style/values/computed/position.rs
@@ -11,6 +11,7 @@ use crate::values::computed::{Integer, LengthPercentage, Percentage};
use crate::values::generics::position::Position as GenericPosition;
use crate::values::generics::position::ZIndex as GenericZIndex;
pub use crate::values::specified::position::{GridAutoFlow, GridTemplateAreas};
+use crate::Zero;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};
diff --git a/components/style/values/computed/svg.rs b/components/style/values/computed/svg.rs
index f3ca86aa5b0..f05e9f836da 100644
--- a/components/style/values/computed/svg.rs
+++ b/components/style/values/computed/svg.rs
@@ -6,10 +6,10 @@
use crate::values::computed::color::Color;
use crate::values::computed::url::ComputedUrl;
-use crate::values::computed::{LengthPercentage, NonNegativeLengthPercentage};
-use crate::values::computed::{NonNegativeNumber, Number, Opacity};
+use crate::values::computed::{LengthPercentage, NonNegativeLengthPercentage, Opacity};
use crate::values::generics::svg as generic;
use crate::values::RGBA;
+use crate::Zero;
pub use crate::values::specified::SVGPaintOrder;
@@ -40,58 +40,29 @@ impl SVGPaint {
}
}
-/// A value of <length> | <percentage> | <number> for stroke-dashoffset.
-/// <https://www.w3.org/TR/SVG11/painting.html#StrokeProperties>
-pub type SvgLengthPercentageOrNumber =
- generic::SvgLengthPercentageOrNumber<LengthPercentage, Number>;
-
/// <length> | <percentage> | <number> | context-value
-pub type SVGLength = generic::SVGLength<SvgLengthPercentageOrNumber>;
+pub type SVGLength = generic::SVGLength<LengthPercentage>;
impl SVGLength {
/// `0px`
pub fn zero() -> Self {
- generic::SVGLength::Length(generic::SvgLengthPercentageOrNumber::LengthPercentage(
- LengthPercentage::zero(),
- ))
- }
-}
-
-/// A value of <length> | <percentage> | <number> for stroke-width/stroke-dasharray.
-/// <https://www.w3.org/TR/SVG11/painting.html#StrokeProperties>
-pub type NonNegativeSvgLengthPercentageOrNumber =
- generic::SvgLengthPercentageOrNumber<NonNegativeLengthPercentage, NonNegativeNumber>;
-
-// FIXME(emilio): This is really hacky, and can go away with a bit of work on
-// the clone_stroke_width code in gecko.mako.rs.
-impl Into<NonNegativeSvgLengthPercentageOrNumber> for SvgLengthPercentageOrNumber {
- fn into(self) -> NonNegativeSvgLengthPercentageOrNumber {
- match self {
- generic::SvgLengthPercentageOrNumber::LengthPercentage(lop) => {
- generic::SvgLengthPercentageOrNumber::LengthPercentage(lop.into())
- },
- generic::SvgLengthPercentageOrNumber::Number(num) => {
- generic::SvgLengthPercentageOrNumber::Number(num.into())
- },
- }
+ generic::SVGLength::LengthPercentage(LengthPercentage::zero())
}
}
/// An non-negative wrapper of SVGLength.
-pub type SVGWidth = generic::SVGLength<NonNegativeSvgLengthPercentageOrNumber>;
+pub type SVGWidth = generic::SVGLength<NonNegativeLengthPercentage>;
impl SVGWidth {
/// `1px`.
pub fn one() -> Self {
use crate::values::generics::NonNegative;
- generic::SVGLength::Length(generic::SvgLengthPercentageOrNumber::LengthPercentage(
- NonNegative(LengthPercentage::one()),
- ))
+ generic::SVGLength::LengthPercentage(NonNegative(LengthPercentage::one()))
}
}
/// [ <length> | <percentage> | <number> ]# | context-value
-pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeSvgLengthPercentageOrNumber>;
+pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeLengthPercentage>;
impl Default for SVGStrokeDashArray {
fn default() -> Self {
diff --git a/components/style/values/computed/text.rs b/components/style/values/computed/text.rs
index 2c9a9593ecc..911891bf33b 100644
--- a/components/style/values/computed/text.rs
+++ b/components/style/values/computed/text.rs
@@ -7,28 +7,97 @@
#[cfg(feature = "servo")]
use crate::properties::StyleBuilder;
use crate::values::computed::length::{Length, LengthPercentage};
-use crate::values::computed::{NonNegativeLength, NonNegativeNumber};
+use crate::values::computed::{Context, NonNegativeLength, NonNegativeNumber, ToComputedValue};
use crate::values::generics::text::InitialLetter as GenericInitialLetter;
use crate::values::generics::text::LineHeight as GenericLineHeight;
use crate::values::generics::text::Spacing;
-use crate::values::specified::text::TextOverflowSide;
+use crate::values::specified::text::{self as specified, TextOverflowSide};
use crate::values::specified::text::{TextEmphasisFillMode, TextEmphasisShapeKeyword};
use crate::values::{CSSFloat, CSSInteger};
+use crate::Zero;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};
-pub use crate::values::specified::OverflowWrap;
pub use crate::values::specified::TextAlignKeyword as TextAlign;
pub use crate::values::specified::TextEmphasisPosition;
+pub use crate::values::specified::{OverflowWrap, WordBreak};
/// A computed value for the `initial-letter` property.
pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>;
/// A computed value for the `letter-spacing` property.
-pub type LetterSpacing = Spacing<Length>;
+#[repr(transparent)]
+#[derive(
+ Animate,
+ Clone,
+ ComputeSquaredDistance,
+ Copy,
+ Debug,
+ MallocSizeOf,
+ PartialEq,
+ ToAnimatedValue,
+ ToAnimatedZero,
+)]
+pub struct LetterSpacing(pub Length);
+
+impl LetterSpacing {
+ /// Return the `normal` computed value, which is just zero.
+ #[inline]
+ pub fn normal() -> Self {
+ LetterSpacing(Length::zero())
+ }
+}
+
+impl ToCss for LetterSpacing {
+ fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
+ where
+ W: Write,
+ {
+ // https://drafts.csswg.org/css-text/#propdef-letter-spacing
+ //
+ // For legacy reasons, a computed letter-spacing of zero yields a
+ // resolved value (getComputedStyle() return value) of normal.
+ if self.0.is_zero() {
+ return dest.write_str("normal");
+ }
+ self.0.to_css(dest)
+ }
+}
+
+impl ToComputedValue for specified::LetterSpacing {
+ type ComputedValue = LetterSpacing;
+ fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
+ match *self {
+ Spacing::Normal => LetterSpacing(Length::zero()),
+ Spacing::Value(ref v) => LetterSpacing(v.to_computed_value(context)),
+ }
+ }
+
+ fn from_computed_value(computed: &Self::ComputedValue) -> Self {
+ if computed.0.is_zero() {
+ return Spacing::Normal;
+ }
+ Spacing::Value(ToComputedValue::from_computed_value(&computed.0))
+ }
+}
/// A computed value for the `word-spacing` property.
-pub type WordSpacing = Spacing<LengthPercentage>;
+pub type WordSpacing = LengthPercentage;
+
+impl ToComputedValue for specified::WordSpacing {
+ type ComputedValue = WordSpacing;
+
+ fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
+ match *self {
+ Spacing::Normal => LengthPercentage::zero(),
+ Spacing::Value(ref v) => v.to_computed_value(context),
+ }
+ }
+
+ fn from_computed_value(computed: &Self::ComputedValue) -> Self {
+ Spacing::Value(ToComputedValue::from_computed_value(computed))
+ }
+}
/// A computed value for the `line-height` property.
pub type LineHeight = GenericLineHeight<NonNegativeNumber, NonNegativeLength>;
diff --git a/components/style/values/computed/transform.rs b/components/style/values/computed/transform.rs
index dd3fe20754c..e23ec1524ff 100644
--- a/components/style/values/computed/transform.rs
+++ b/components/style/values/computed/transform.rs
@@ -9,8 +9,8 @@ use crate::values::animated::transform::{Perspective, Scale3D, Translate3D};
use crate::values::animated::ToAnimatedZero;
use crate::values::computed::{Angle, Integer, Length, LengthPercentage, Number, Percentage};
use crate::values::generics::transform as generic;
+use crate::Zero;
use euclid::{Transform3D, Vector3D};
-use num_traits::Zero;
pub use crate::values::generics::transform::TransformStyle;
@@ -371,15 +371,14 @@ impl TransformOperation {
pub fn to_translate_3d(&self) -> Self {
match *self {
generic::TransformOperation::Translate3D(..) => self.clone(),
- generic::TransformOperation::TranslateX(ref x) |
- generic::TransformOperation::Translate(ref x, None) => {
+ generic::TransformOperation::TranslateX(ref x) => {
generic::TransformOperation::Translate3D(
x.clone(),
LengthPercentage::zero(),
Length::zero(),
)
},
- generic::TransformOperation::Translate(ref x, Some(ref y)) => {
+ generic::TransformOperation::Translate(ref x, ref y) => {
generic::TransformOperation::Translate3D(x.clone(), y.clone(), Length::zero())
},
generic::TransformOperation::TranslateY(ref y) => {
@@ -426,10 +425,7 @@ impl TransformOperation {
pub fn to_scale_3d(&self) -> Self {
match *self {
generic::TransformOperation::Scale3D(..) => self.clone(),
- generic::TransformOperation::Scale(s, None) => {
- generic::TransformOperation::Scale3D(s, s, 1.)
- },
- generic::TransformOperation::Scale(x, Some(y)) => {
+ generic::TransformOperation::Scale(x, y) => {
generic::TransformOperation::Scale3D(x, y, 1.)
},
generic::TransformOperation::ScaleX(x) => {
@@ -494,7 +490,7 @@ impl ToAnimatedZero for TransformOperation {
Ok(generic::TransformOperation::Scale3D(1.0, 1.0, 1.0))
},
generic::TransformOperation::Scale(_, _) => {
- Ok(generic::TransformOperation::Scale(1.0, Some(1.0)))
+ Ok(generic::TransformOperation::Scale(1.0, 1.0))
},
generic::TransformOperation::ScaleX(..) => Ok(generic::TransformOperation::ScaleX(1.0)),
generic::TransformOperation::ScaleY(..) => Ok(generic::TransformOperation::ScaleY(1.0)),
@@ -585,7 +581,7 @@ impl Translate {
match *self {
generic::Translate::None => None,
generic::Translate::Translate(tx, ty) => {
- Some(generic::TransformOperation::Translate(tx, Some(ty)))
+ Some(generic::TransformOperation::Translate(tx, ty))
},
generic::Translate::Translate3D(tx, ty, tz) => {
Some(generic::TransformOperation::Translate3D(tx, ty, tz))
@@ -596,9 +592,7 @@ impl Translate {
/// Convert Translate to TransformOperation.
pub fn from_transform_operation(operation: &TransformOperation) -> Translate {
match *operation {
- generic::TransformOperation::Translate(tx, Some(ty)) => {
- generic::Translate::Translate(tx, ty)
- },
+ generic::TransformOperation::Translate(tx, ty) => generic::Translate::Translate(tx, ty),
generic::TransformOperation::Translate3D(tx, ty, tz) => {
generic::Translate::Translate3D(tx, ty, tz)
},
@@ -615,7 +609,7 @@ impl Scale {
pub fn to_transform_operation(&self) -> Option<TransformOperation> {
match *self {
generic::Scale::None => None,
- generic::Scale::Scale(sx, sy) => Some(generic::TransformOperation::Scale(sx, Some(sy))),
+ generic::Scale::Scale(sx, sy) => Some(generic::TransformOperation::Scale(sx, sy)),
generic::Scale::Scale3D(sx, sy, sz) => {
Some(generic::TransformOperation::Scale3D(sx, sy, sz))
},
@@ -625,8 +619,7 @@ impl Scale {
/// Convert Scale to TransformOperation.
pub fn from_transform_operation(operation: &TransformOperation) -> Scale {
match *operation {
- generic::TransformOperation::Scale(sx, Some(sy)) => generic::Scale::Scale(sx, sy),
- generic::TransformOperation::Scale(sx, None) => generic::Scale::Scale(sx, sx),
+ generic::TransformOperation::Scale(sx, sy) => generic::Scale::Scale(sx, sy),
generic::TransformOperation::Scale3D(sx, sy, sz) => generic::Scale::Scale3D(sx, sy, sz),
_ => unreachable!("Found unexpected value for scale"),
}
diff --git a/components/style/values/generics/background.rs b/components/style/values/generics/background.rs
index 14ac9744b14..3780f9a4fc3 100644
--- a/components/style/values/generics/background.rs
+++ b/components/style/values/generics/background.rs
@@ -5,8 +5,13 @@
//! Generic types for CSS values related to backgrounds.
use crate::values::generics::length::{GenericLengthPercentageOrAuto, LengthPercentageOrAuto};
-use std::fmt::{self, Write};
-use style_traits::{CssWriter, ToCss};
+
+fn width_and_height_are_auto<L>(
+ width: &LengthPercentageOrAuto<L>,
+ height: &LengthPercentageOrAuto<L>,
+) -> bool {
+ width.is_auto() && height.is_auto()
+}
/// A generic value for the `background-size` property.
#[derive(
@@ -21,6 +26,7 @@ use style_traits::{CssWriter, ToCss};
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
+ ToCss,
)]
#[repr(C, u8)]
pub enum GenericBackgroundSize<LengthPercent> {
@@ -29,6 +35,10 @@ pub enum GenericBackgroundSize<LengthPercent> {
/// Explicit width.
width: GenericLengthPercentageOrAuto<LengthPercent>,
/// Explicit height.
+ /// NOTE(emilio): We should probably simplify all these in case `width`
+ /// and `height` are the same, but all other browsers agree on only
+ /// special-casing `auto`.
+ #[css(contextual_skip_if = "width_and_height_are_auto")]
height: GenericLengthPercentageOrAuto<LengthPercent>,
},
/// `cover`
@@ -41,32 +51,6 @@ pub enum GenericBackgroundSize<LengthPercent> {
pub use self::GenericBackgroundSize as BackgroundSize;
-impl<LengthPercentage> ToCss for BackgroundSize<LengthPercentage>
-where
- LengthPercentage: ToCss,
-{
- fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
- where
- W: Write,
- {
- match self {
- BackgroundSize::ExplicitSize { width, height } => {
- width.to_css(dest)?;
- // NOTE(emilio): We should probably simplify all these in case
- // `width == `height`, but all other browsers agree on only
- // special-casing `auto`.
- if !width.is_auto() || !height.is_auto() {
- dest.write_str(" ")?;
- height.to_css(dest)?;
- }
- Ok(())
- },
- BackgroundSize::Cover => dest.write_str("cover"),
- BackgroundSize::Contain => dest.write_str("contain"),
- }
- }
-}
-
impl<LengthPercentage> BackgroundSize<LengthPercentage> {
/// Returns `auto auto`.
pub fn auto() -> Self {
diff --git a/components/style/values/generics/basic_shape.rs b/components/style/values/generics/basic_shape.rs
index f224f936ccb..975fbdb797d 100644
--- a/components/style/values/generics/basic_shape.rs
+++ b/components/style/values/generics/basic_shape.rs
@@ -11,6 +11,7 @@ use crate::values::generics::border::BorderRadius;
use crate::values::generics::position::Position;
use crate::values::generics::rect::Rect;
use crate::values::specified::SVGPathData;
+use crate::Zero;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};
@@ -127,7 +128,7 @@ pub enum BasicShape<H, V, LengthPercentage, NonNegativeLengthPercentage> {
)]
pub struct InsetRect<LengthPercentage, NonNegativeLengthPercentage> {
pub rect: Rect<LengthPercentage>,
- pub round: Option<BorderRadius<NonNegativeLengthPercentage>>,
+ pub round: BorderRadius<NonNegativeLengthPercentage>,
}
/// <https://drafts.csswg.org/css-shapes/#funcdef-circle>
@@ -311,7 +312,7 @@ impl<B, T, U> ToAnimatedZero for ShapeSource<B, T, U> {
impl<Length, NonNegativeLength> ToCss for InsetRect<Length, NonNegativeLength>
where
Length: ToCss + PartialEq,
- NonNegativeLength: ToCss + PartialEq,
+ NonNegativeLength: ToCss + PartialEq + Zero,
{
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
@@ -319,9 +320,9 @@ where
{
dest.write_str("inset(")?;
self.rect.to_css(dest)?;
- if let Some(ref radius) = self.round {
+ if !self.round.is_zero() {
dest.write_str(" round ")?;
- radius.to_css(dest)?;
+ self.round.to_css(dest)?;
}
dest.write_str(")")
}
diff --git a/components/style/values/generics/border.rs b/components/style/values/generics/border.rs
index ffd30e98678..df6427e888f 100644
--- a/components/style/values/generics/border.rs
+++ b/components/style/values/generics/border.rs
@@ -5,7 +5,8 @@
//! Generic types for CSS values related to borders.
use crate::values::generics::rect::Rect;
-use crate::values::generics::size::Size;
+use crate::values::generics::size::Size2D;
+use crate::Zero;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};
@@ -53,12 +54,25 @@ pub use self::GenericBorderImageSlice as BorderImageSlice;
ToComputedValue,
ToCss,
)]
-pub struct BorderCornerRadius<L>(#[css(field_bound)] pub Size<L>);
+#[repr(C)]
+pub struct GenericBorderCornerRadius<L>(#[css(field_bound)] pub Size2D<L>);
+
+pub use self::GenericBorderCornerRadius as BorderCornerRadius;
impl<L> BorderCornerRadius<L> {
/// Trivially create a `BorderCornerRadius`.
pub fn new(w: L, h: L) -> Self {
- BorderCornerRadius(Size::new(w, h))
+ BorderCornerRadius(Size2D::new(w, h))
+ }
+}
+
+impl<L: Zero> Zero for BorderCornerRadius<L> {
+ fn zero() -> Self {
+ BorderCornerRadius(Size2D::zero())
+ }
+
+ fn is_zero(&self) -> bool {
+ self.0.is_zero()
}
}
@@ -77,12 +91,13 @@ impl<L> BorderCornerRadius<L> {
ToComputedValue,
ToCss,
)]
-pub struct BorderSpacing<L>(#[css(field_bound)] pub Size<L>);
+#[repr(transparent)]
+pub struct BorderSpacing<L>(#[css(field_bound)] pub Size2D<L>);
impl<L> BorderSpacing<L> {
/// Trivially create a `BorderCornerRadius`.
pub fn new(w: L, h: L) -> Self {
- BorderSpacing(Size::new(w, h))
+ BorderSpacing(Size2D::new(w, h))
}
}
@@ -101,17 +116,20 @@ impl<L> BorderSpacing<L> {
ToAnimatedValue,
ToComputedValue,
)]
-pub struct BorderRadius<LengthPercentage> {
+#[repr(C)]
+pub struct GenericBorderRadius<LengthPercentage> {
/// The top left radius.
- pub top_left: BorderCornerRadius<LengthPercentage>,
+ pub top_left: GenericBorderCornerRadius<LengthPercentage>,
/// The top right radius.
- pub top_right: BorderCornerRadius<LengthPercentage>,
+ pub top_right: GenericBorderCornerRadius<LengthPercentage>,
/// The bottom right radius.
- pub bottom_right: BorderCornerRadius<LengthPercentage>,
+ pub bottom_right: GenericBorderCornerRadius<LengthPercentage>,
/// The bottom left radius.
- pub bottom_left: BorderCornerRadius<LengthPercentage>,
+ pub bottom_left: GenericBorderCornerRadius<LengthPercentage>,
}
+pub use self::GenericBorderRadius as BorderRadius;
+
impl<L> BorderRadius<L> {
/// Returns a new `BorderRadius<L>`.
#[inline]
@@ -128,12 +146,7 @@ impl<L> BorderRadius<L> {
bottom_left: bl,
}
}
-}
-impl<L> BorderRadius<L>
-where
- L: PartialEq + ToCss,
-{
/// Serialises two given rects following the syntax of the `border-radius``
/// property.
pub fn serialize_rects<W>(
@@ -142,14 +155,11 @@ where
dest: &mut CssWriter<W>,
) -> fmt::Result
where
+ L: PartialEq + ToCss,
W: Write,
{
widths.to_css(dest)?;
- if widths.0 != heights.0 ||
- widths.1 != heights.1 ||
- widths.2 != heights.2 ||
- widths.3 != heights.3
- {
+ if widths != heights {
dest.write_str(" / ")?;
heights.to_css(dest)?;
}
@@ -157,6 +167,24 @@ where
}
}
+impl<L: Zero> Zero for BorderRadius<L> {
+ fn zero() -> Self {
+ Self::new(
+ BorderCornerRadius::<L>::zero(),
+ BorderCornerRadius::<L>::zero(),
+ BorderCornerRadius::<L>::zero(),
+ BorderCornerRadius::<L>::zero(),
+ )
+ }
+
+ fn is_zero(&self) -> bool {
+ self.top_left.is_zero() &&
+ self.top_right.is_zero() &&
+ self.bottom_right.is_zero() &&
+ self.bottom_left.is_zero()
+ }
+}
+
impl<L> ToCss for BorderRadius<L>
where
L: PartialEq + ToCss,
@@ -172,8 +200,8 @@ where
bottom_left: BorderCornerRadius(ref bl),
} = *self;
- let widths = Rect::new(&tl.0.width, &tr.0.width, &br.0.width, &bl.0.width);
- let heights = Rect::new(&tl.0.height, &tr.0.height, &br.0.height, &bl.0.height);
+ let widths = Rect::new(&tl.width, &tr.width, &br.width, &bl.width);
+ let heights = Rect::new(&tl.height, &tr.height, &br.height, &bl.height);
Self::serialize_rects(widths, heights, dest)
}
diff --git a/components/style/values/generics/length.rs b/components/style/values/generics/length.rs
index 1a83f58054c..076a02a4a0f 100644
--- a/components/style/values/generics/length.rs
+++ b/components/style/values/generics/length.rs
@@ -7,8 +7,8 @@
use crate::parser::{Parse, ParserContext};
#[cfg(feature = "gecko")]
use crate::values::computed::ExtremumLength;
+use crate::Zero;
use cssparser::Parser;
-use num_traits::Zero;
use style_traits::ParseError;
/// A `<length-percentage> | auto` value.
@@ -67,6 +67,19 @@ impl<LengthPercentage> LengthPercentageOrAuto<LengthPercentage> {
}
}
+impl<LengthPercentage: Zero> Zero for LengthPercentageOrAuto<LengthPercentage> {
+ fn zero() -> Self {
+ LengthPercentageOrAuto::LengthPercentage(Zero::zero())
+ }
+
+ fn is_zero(&self) -> bool {
+ match *self {
+ LengthPercentageOrAuto::LengthPercentage(ref l) => l.is_zero(),
+ LengthPercentageOrAuto::Auto => false,
+ }
+ }
+}
+
impl<LengthPercentage: Parse> Parse for LengthPercentageOrAuto<LengthPercentage> {
fn parse<'i, 't>(
context: &ParserContext,
@@ -186,12 +199,15 @@ pub enum GenericLengthOrNumber<L, N> {
pub use self::GenericLengthOrNumber as LengthOrNumber;
-impl<L, N> LengthOrNumber<L, N> {
- /// Returns `0`.
- pub fn zero() -> Self
- where
- N: Zero,
- {
- LengthOrNumber::Number(num_traits::Zero::zero())
+impl<L, N: Zero> Zero for LengthOrNumber<L, N> {
+ fn zero() -> Self {
+ LengthOrNumber::Number(Zero::zero())
+ }
+
+ fn is_zero(&self) -> bool {
+ match *self {
+ LengthOrNumber::Number(ref n) => n.is_zero(),
+ LengthOrNumber::Length(..) => false,
+ }
}
}
diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs
index 737c88e7ba7..e054db7281f 100644
--- a/components/style/values/generics/mod.rs
+++ b/components/style/values/generics/mod.rs
@@ -8,8 +8,8 @@
use super::CustomIdent;
use crate::counter_style::{parse_counter_style_name, Symbols};
use crate::parser::{Parse, ParserContext};
+use crate::Zero;
use cssparser::Parser;
-use num_traits::Zero;
use std::ops::Add;
use style_traits::{KeywordsCollectFn, ParseError};
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind};
@@ -212,3 +212,26 @@ impl<T: Zero> Zero for NonNegative<T> {
ToCss,
)]
pub struct GreaterThanOrEqualToOne<T>(pub T);
+
+/// A clip rect for clip and image-region
+#[allow(missing_docs)]
+#[derive(
+ Clone,
+ ComputeSquaredDistance,
+ Copy,
+ Debug,
+ MallocSizeOf,
+ PartialEq,
+ SpecifiedValueInfo,
+ ToAnimatedValue,
+ ToAnimatedZero,
+ ToComputedValue,
+ ToCss,
+)]
+#[css(function = "rect", comma)]
+pub struct ClipRect<LengthOrAuto> {
+ pub top: LengthOrAuto,
+ pub right: LengthOrAuto,
+ pub bottom: LengthOrAuto,
+ pub left: LengthOrAuto,
+}
diff --git a/components/style/values/generics/size.rs b/components/style/values/generics/size.rs
index a5a5c86eac6..96e0003128f 100644
--- a/components/style/values/generics/size.rs
+++ b/components/style/values/generics/size.rs
@@ -5,11 +5,10 @@
//! Generic type for CSS properties that are composed by two dimensions.
use crate::parser::ParserContext;
-use crate::values::animated::ToAnimatedValue;
+use crate::Zero;
use cssparser::Parser;
-use euclid::Size2D;
use std::fmt::{self, Write};
-use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, ToCss};
+use style_traits::{CssWriter, ParseError, ToCss};
/// A generic size, for `border-*-radius` longhand properties, or
/// `border-spacing`.
@@ -21,29 +20,36 @@ use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, ToCss};
Debug,
MallocSizeOf,
PartialEq,
+ SpecifiedValueInfo,
ToAnimatedZero,
+ ToAnimatedValue,
ToComputedValue,
)]
-pub struct Size<L>(pub Size2D<L>);
+#[allow(missing_docs)]
+#[repr(C)]
+pub struct Size2D<L> {
+ pub width: L,
+ pub height: L,
+}
-impl<L> Size<L> {
+impl<L> Size2D<L> {
#[inline]
- /// Create a new `Size` for an area of given width and height.
- pub fn new(width: L, height: L) -> Size<L> {
- Size(Size2D::new(width, height))
+ /// Create a new `Size2D` for an area of given width and height.
+ pub fn new(width: L, height: L) -> Self {
+ Self { width, height }
}
/// Returns the width component.
pub fn width(&self) -> &L {
- &self.0.width
+ &self.width
}
/// Returns the height component.
pub fn height(&self) -> &L {
- &self.0.height
+ &self.height
}
- /// Parse a `Size` with a given parsing function.
+ /// Parse a `Size2D` with a given parsing function.
pub fn parse_with<'i, 't, F>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
@@ -61,7 +67,7 @@ impl<L> Size<L> {
}
}
-impl<L> ToCss for Size<L>
+impl<L> ToCss for Size2D<L>
where
L: ToCss + PartialEq,
{
@@ -69,40 +75,23 @@ where
where
W: Write,
{
- self.0.width.to_css(dest)?;
+ self.width.to_css(dest)?;
- if self.0.height != self.0.width {
+ if self.height != self.width {
dest.write_str(" ")?;
- self.0.height.to_css(dest)?;
+ self.height.to_css(dest)?;
}
Ok(())
}
}
-impl<L> ToAnimatedValue for Size<L>
-where
- L: ToAnimatedValue,
-{
- type AnimatedValue = Size<L::AnimatedValue>;
-
- #[inline]
- fn to_animated_value(self) -> Self::AnimatedValue {
- Size(Size2D::new(
- self.0.width.to_animated_value(),
- self.0.height.to_animated_value(),
- ))
+impl<L: Zero> Zero for Size2D<L> {
+ fn zero() -> Self {
+ Self::new(L::zero(), L::zero())
}
- #[inline]
- fn from_animated_value(animated: Self::AnimatedValue) -> Self {
- Size(Size2D::new(
- L::from_animated_value(animated.0.width),
- L::from_animated_value(animated.0.height),
- ))
+ fn is_zero(&self) -> bool {
+ self.width.is_zero() && self.height.is_zero()
}
}
-
-impl<L: SpecifiedValueInfo> SpecifiedValueInfo for Size<L> {
- const SUPPORTED_TYPES: u8 = L::SUPPORTED_TYPES;
-}
diff --git a/components/style/values/generics/svg.rs b/components/style/values/generics/svg.rs
index 7f52126a748..6a4d2411e76 100644
--- a/components/style/values/generics/svg.rs
+++ b/components/style/values/generics/svg.rs
@@ -128,64 +128,26 @@ impl<ColorType: Parse, UrlPaintServer: Parse> Parse for SVGPaint<ColorType, UrlP
}
}
-/// A value of <length> | <percentage> | <number> for svg which allow unitless length.
-/// <https://www.w3.org/TR/SVG11/painting.html#StrokeProperties>
-#[derive(
- Clone,
- Copy,
- Debug,
- MallocSizeOf,
- PartialEq,
- Parse,
- SpecifiedValueInfo,
- ToAnimatedValue,
- ToAnimatedZero,
- ToComputedValue,
- ToCss,
-)]
-pub enum SvgLengthPercentageOrNumber<LengthPercentage, Number> {
- /// <number>
- ///
- /// Note that this needs to be before, so it gets parsed before the length,
- /// to handle `0` correctly as a number instead of a `<length>`.
- Number(Number),
- /// <length> | <percentage>
- LengthPercentage(LengthPercentage),
-}
-
-/// Whether the `context-value` value is enabled.
-#[cfg(feature = "gecko")]
-pub fn is_context_value_enabled(_: &ParserContext) -> bool {
- use crate::gecko_bindings::structs::mozilla;
- unsafe { mozilla::StaticPrefs_sVarCache_gfx_font_rendering_opentype_svg_enabled }
-}
-
-/// Whether the `context-value` value is enabled.
-#[cfg(not(feature = "gecko"))]
-pub fn is_context_value_enabled(_: &ParserContext) -> bool {
- false
-}
-
/// An SVG length value supports `context-value` in addition to length.
#[derive(
+ Animate,
Clone,
ComputeSquaredDistance,
Copy,
Debug,
MallocSizeOf,
PartialEq,
- Parse,
SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
ToCss,
)]
-pub enum SVGLength<LengthType> {
+pub enum SVGLength<L> {
/// `<length> | <percentage> | <number>`
- Length(LengthType),
+ LengthPercentage(L),
/// `context-value`
- #[parse(condition = "is_context_value_enabled")]
+ #[animation(error)]
ContextValue,
}
@@ -197,13 +159,14 @@ pub enum SVGLength<LengthType> {
PartialEq,
SpecifiedValueInfo,
ToAnimatedValue,
+ ToAnimatedZero,
ToComputedValue,
ToCss,
)]
-pub enum SVGStrokeDashArray<LengthType> {
+pub enum SVGStrokeDashArray<L> {
/// `[ <length> | <percentage> | <number> ]#`
#[css(comma)]
- Values(#[css(if_empty = "none", iterable)] Vec<LengthType>),
+ Values(#[css(if_empty = "none", iterable)] Vec<L>),
/// `context-value`
ContextValue,
}
@@ -211,6 +174,7 @@ pub enum SVGStrokeDashArray<LengthType> {
/// An SVG opacity value accepts `context-{fill,stroke}-opacity` in
/// addition to opacity value.
#[derive(
+ Animate,
Clone,
ComputeSquaredDistance,
Copy,
@@ -227,7 +191,9 @@ pub enum SVGOpacity<OpacityType> {
/// `<opacity-value>`
Opacity(OpacityType),
/// `context-fill-opacity`
+ #[animation(error)]
ContextFillOpacity,
/// `context-stroke-opacity`
+ #[animation(error)]
ContextStrokeOpacity,
}
diff --git a/components/style/values/generics/text.rs b/components/style/values/generics/text.rs
index 029c5681318..7dae932faac 100644
--- a/components/style/values/generics/text.rs
+++ b/components/style/values/generics/text.rs
@@ -5,9 +5,7 @@
//! Generic types for text properties.
use crate::parser::ParserContext;
-use crate::values::animated::{Animate, Procedure, ToAnimatedZero};
-use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
-use app_units::Au;
+use crate::values::animated::ToAnimatedZero;
use cssparser::Parser;
use style_traits::ParseError;
@@ -31,9 +29,7 @@ impl<N, I> InitialLetter<N, I> {
}
/// A generic spacing value for the `letter-spacing` and `word-spacing` properties.
-#[derive(
- Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
-)]
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
pub enum Spacing<Value> {
/// `normal`
Normal,
@@ -63,51 +59,6 @@ impl<Value> Spacing<Value> {
}
parse(context, input).map(Spacing::Value)
}
-
- /// Returns the spacing value, if not `normal`.
- #[inline]
- pub fn value(&self) -> Option<&Value> {
- match *self {
- Spacing::Normal => None,
- Spacing::Value(ref value) => Some(value),
- }
- }
-}
-
-impl<Value> Animate for Spacing<Value>
-where
- Value: Animate + From<Au>,
-{
- #[inline]
- fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
- if let (&Spacing::Normal, &Spacing::Normal) = (self, other) {
- return Ok(Spacing::Normal);
- }
- let zero = Value::from(Au(0));
- let this = self.value().unwrap_or(&zero);
- let other = other.value().unwrap_or(&zero);
- Ok(Spacing::Value(this.animate(other, procedure)?))
- }
-}
-
-impl<V> ComputeSquaredDistance for Spacing<V>
-where
- V: ComputeSquaredDistance + From<Au>,
-{
- #[inline]
- fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
- let zero = V::from(Au(0));
- let this = self.value().unwrap_or(&zero);
- let other = other.value().unwrap_or(&zero);
- this.compute_squared_distance(other)
- }
-}
-
-impl<V> ToAnimatedZero for Spacing<V> {
- #[inline]
- fn to_animated_zero(&self) -> Result<Self, ()> {
- Err(())
- }
}
/// A generic value for the `line-height` property.
@@ -123,18 +74,21 @@ impl<V> ToAnimatedZero for Spacing<V> {
ToAnimatedValue,
ToCss,
)]
-pub enum LineHeight<Number, LengthPercentage> {
+#[repr(C, u8)]
+pub enum GenericLineHeight<N, L> {
/// `normal`
Normal,
/// `-moz-block-height`
#[cfg(feature = "gecko")]
MozBlockHeight,
/// `<number>`
- Number(Number),
- /// `<length-or-percentage>`
- Length(LengthPercentage),
+ Number(N),
+ /// `<length-percentage>`
+ Length(L),
}
+pub use self::GenericLineHeight as LineHeight;
+
impl<N, L> ToAnimatedZero for LineHeight<N, L> {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs
index 6c60e76cbf6..3e091162b2e 100644
--- a/components/style/values/generics/transform.rs
+++ b/components/style/values/generics/transform.rs
@@ -10,9 +10,9 @@ use crate::values::specified::angle::Angle as SpecifiedAngle;
use crate::values::specified::length::Length as SpecifiedLength;
use crate::values::specified::length::LengthPercentage as SpecifiedLengthPercentage;
use crate::values::{computed, CSSFloat};
+use crate::Zero;
use app_units::Au;
use euclid::{self, Rect, Transform3D};
-use num_traits::Zero;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ToCss};
@@ -106,9 +106,18 @@ impl<H, V, D> TransformOrigin<H, V, D> {
}
}
+fn is_same<N: PartialEq>(x: &N, y: &N) -> bool {
+ x == y
+}
+
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
/// A single operation in the list of a `transform` value
-pub enum TransformOperation<Angle, Number, Length, Integer, LengthPercentage> {
+pub enum TransformOperation<Angle, Number, Length, Integer, LengthPercentage>
+where
+ Angle: Zero,
+ LengthPercentage: Zero,
+ Number: PartialEq,
+{
/// Represents a 2D 2x3 matrix.
Matrix(Matrix<Number>),
/// Represents a 3D 4x4 matrix.
@@ -119,7 +128,7 @@ pub enum TransformOperation<Angle, Number, Length, Integer, LengthPercentage> {
///
/// Syntax can be skew(angle) or skew(angle, angle)
#[css(comma, function)]
- Skew(Angle, Option<Angle>),
+ Skew(Angle, #[css(skip_if = "Zero::is_zero")] Angle),
/// skewX(angle)
#[css(function = "skewX")]
SkewX(Angle),
@@ -128,7 +137,10 @@ pub enum TransformOperation<Angle, Number, Length, Integer, LengthPercentage> {
SkewY(Angle),
/// translate(x, y) or translate(x)
#[css(comma, function)]
- Translate(LengthPercentage, Option<LengthPercentage>),
+ Translate(
+ LengthPercentage,
+ #[css(skip_if = "Zero::is_zero")] LengthPercentage,
+ ),
/// translateX(x)
#[css(function = "translateX")]
TranslateX(LengthPercentage),
@@ -143,14 +155,9 @@ pub enum TransformOperation<Angle, Number, Length, Integer, LengthPercentage> {
Translate3D(LengthPercentage, LengthPercentage, Length),
/// A 2D scaling factor.
///
- /// `scale(2)` is parsed as `Scale(Number::new(2.0), None)` and is equivalent to
- /// writing `scale(2, 2)` (`Scale(Number::new(2.0), Some(Number::new(2.0)))`).
- ///
- /// Negative values are allowed and flip the element.
- ///
/// Syntax can be scale(factor) or scale(factor, factor)
#[css(comma, function)]
- Scale(Number, Option<Number>),
+ Scale(Number, #[css(contextual_skip_if = "is_same")] Number),
/// scaleX(factor)
#[css(function = "scaleX")]
ScaleX(Number),
@@ -214,6 +221,10 @@ pub struct Transform<T>(#[css(if_empty = "none", iterable)] pub Vec<T>);
impl<Angle, Number, Length, Integer, LengthPercentage>
TransformOperation<Angle, Number, Length, Integer, LengthPercentage>
+where
+ Angle: Zero,
+ LengthPercentage: Zero,
+ Number: PartialEq,
{
/// Check if it is any rotate function.
pub fn is_rotate(&self) -> bool {
@@ -333,10 +344,10 @@ impl ToRadians for SpecifiedAngle {
impl<Angle, Number, Length, Integer, LoP> ToMatrix
for TransformOperation<Angle, Number, Length, Integer, LoP>
where
- Angle: ToRadians + Copy,
- Number: Copy + Into<f32> + Into<f64>,
+ Angle: Zero + ToRadians + Copy,
+ Number: PartialEq + Copy + Into<f32> + Into<f64>,
Length: ToAbsoluteLength,
- LoP: ToAbsoluteLength,
+ LoP: Zero + ToAbsoluteLength,
{
#[inline]
fn is_3d(&self) -> bool {
@@ -389,7 +400,7 @@ where
m.cast()
},
Scale3D(sx, sy, sz) => Transform3D::create_scale(sx.into(), sy.into(), sz.into()),
- Scale(sx, sy) => Transform3D::create_scale(sx.into(), sy.unwrap_or(sx).into(), 1.),
+ Scale(sx, sy) => Transform3D::create_scale(sx.into(), sy.into(), 1.),
ScaleX(s) => Transform3D::create_scale(s.into(), 1., 1.),
ScaleY(s) => Transform3D::create_scale(1., s.into(), 1.),
ScaleZ(s) => Transform3D::create_scale(1., 1., s.into()),
@@ -398,12 +409,12 @@ where
let ty = ty.to_pixel_length(reference_height)? as f64;
Transform3D::create_translation(tx, ty, tz.to_pixel_length(None)? as f64)
},
- Translate(ref tx, Some(ref ty)) => {
+ Translate(ref tx, ref ty) => {
let tx = tx.to_pixel_length(reference_width)? as f64;
let ty = ty.to_pixel_length(reference_height)? as f64;
Transform3D::create_translation(tx, ty, 0.)
},
- TranslateX(ref t) | Translate(ref t, None) => {
+ TranslateX(ref t) => {
let t = t.to_pixel_length(reference_width)? as f64;
Transform3D::create_translation(t, 0., 0.)
},
@@ -416,7 +427,7 @@ where
},
Skew(theta_x, theta_y) => Transform3D::create_skew(
euclid::Angle::radians(theta_x.radians64()),
- euclid::Angle::radians(theta_y.map_or(0., |a| a.radians64())),
+ euclid::Angle::radians(theta_y.radians64()),
),
SkewX(theta) => Transform3D::create_skew(
euclid::Angle::radians(theta.radians64()),
@@ -629,64 +640,44 @@ impl<Number: ToCss + PartialEq> ToCss for Scale<Number> {
}
#[derive(
- Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToAnimatedZero, ToComputedValue,
+ Clone,
+ Debug,
+ MallocSizeOf,
+ PartialEq,
+ SpecifiedValueInfo,
+ ToAnimatedZero,
+ ToComputedValue,
+ ToCss,
)]
-/// A value of the `Translate` property
+/// A value of the `translate` property
+///
+/// https://drafts.csswg.org/css-transforms-2/#individual-transform-serialization:
+///
+/// If a 2d translation is specified, the property must serialize with only one
+/// or two values (per usual, if the second value is 0px, the default, it must
+/// be omitted when serializing).
+///
+/// If a 3d translation is specified, all three values must be serialized.
+///
+/// We don't omit the 3rd component even if it is 0px for now, and the
+/// related spec issue is https://github.com/w3c/csswg-drafts/issues/3305
///
/// <https://drafts.csswg.org/css-transforms-2/#individual-transforms>
-pub enum Translate<LengthPercentage, Length> {
+pub enum Translate<LengthPercentage, Length>
+where
+ LengthPercentage: Zero,
+{
/// 'none'
None,
/// '<length-percentage>' or '<length-percentage> <length-percentage>'
- Translate(LengthPercentage, LengthPercentage),
+ Translate(
+ LengthPercentage,
+ #[css(skip_if = "Zero::is_zero")] LengthPercentage,
+ ),
/// '<length-percentage> <length-percentage> <length>'
Translate3D(LengthPercentage, LengthPercentage, Length),
}
-/// A trait to check if this is a zero length.
-/// An alternative way is use num_traits::Zero. However, in order to implement num_traits::Zero,
-/// we also have to implement Add, which may be complicated for LengthPercentage::Calc.
-/// We could do this if other types also need it. If so, we could drop this trait.
-pub trait IsZeroLength {
- /// Returns true if this is a zero length.
- fn is_zero_length(&self) -> bool;
-}
-
-impl<LoP: ToCss + IsZeroLength, L: ToCss> ToCss for Translate<LoP, L> {
- fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
- where
- W: fmt::Write,
- {
- // The spec says:
- // 1. If a 2d translation is specified, the property must serialize with only one or two
- // values (per usual, if the second value is 0px, the default, it must be omitted when
- // serializing).
- // 2. If a 3d translation is specified, all three values must be serialized.
- // https://drafts.csswg.org/css-transforms-2/#individual-transform-serialization
- //
- // We don't omit the 3rd component even if it is 0px for now, and the related
- // spec issue is https://github.com/w3c/csswg-drafts/issues/3305
- match *self {
- Translate::None => dest.write_str("none"),
- Translate::Translate(ref x, ref y) => {
- x.to_css(dest)?;
- if !y.is_zero_length() {
- dest.write_char(' ')?;
- y.to_css(dest)?;
- }
- Ok(())
- },
- Translate::Translate3D(ref x, ref y, ref z) => {
- x.to_css(dest)?;
- dest.write_char(' ')?;
- y.to_css(dest)?;
- dest.write_char(' ')?;
- z.to_css(dest)
- },
- }
- }
-}
-
#[allow(missing_docs)]
#[derive(
Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs
index ccda0f290c1..e29b8923af7 100644
--- a/components/style/values/mod.rs
+++ b/components/style/values/mod.rs
@@ -160,7 +160,7 @@ impl CustomIdent {
excluding: &[&str],
) -> Result<Self, ParseError<'i>> {
let valid = match_ignore_ascii_case! { ident,
- "initial" | "inherit" | "unset" | "default" => false,
+ "initial" | "inherit" | "unset" | "default" | "revert" => false,
_ => true
};
if !valid {
diff --git a/components/style/values/specified/angle.rs b/components/style/values/specified/angle.rs
index 35a0944aed5..01eb58368b9 100644
--- a/components/style/values/specified/angle.rs
+++ b/components/style/values/specified/angle.rs
@@ -9,6 +9,7 @@ use crate::values::computed::angle::Angle as ComputedAngle;
use crate::values::computed::{Context, ToComputedValue};
use crate::values::specified::calc::CalcNode;
use crate::values::CSSFloat;
+use crate::Zero;
use cssparser::{Parser, Token};
use std::f32::consts::PI;
use std::fmt::{self, Write};
@@ -32,6 +33,21 @@ pub enum AngleDimension {
Turn(CSSFloat),
}
+impl Zero for AngleDimension {
+ fn zero() -> Self {
+ AngleDimension::Deg(0.)
+ }
+
+ fn is_zero(&self) -> bool {
+ match *self {
+ AngleDimension::Deg(ref f) |
+ AngleDimension::Grad(ref f) |
+ AngleDimension::Rad(ref f) |
+ AngleDimension::Turn(ref f) => *f == 0.,
+ }
+ }
+}
+
impl AngleDimension {
/// Returns the amount of degrees this angle represents.
#[inline]
@@ -58,6 +74,19 @@ pub struct Angle {
was_calc: bool,
}
+impl Zero for Angle {
+ fn zero() -> Self {
+ Self {
+ value: Zero::zero(),
+ was_calc: false,
+ }
+ }
+
+ fn is_zero(&self) -> bool {
+ self.value.is_zero()
+ }
+}
+
impl ToCss for Angle {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
@@ -101,6 +130,11 @@ impl Angle {
}
}
+ /// Return `0deg`.
+ pub fn zero() -> Self {
+ Self::from_degrees(0.0, false)
+ }
+
/// Returns the value of the angle in degrees, mostly for `calc()`.
#[inline]
pub fn degrees(&self) -> CSSFloat {
@@ -113,12 +147,6 @@ impl Angle {
self.was_calc
}
- /// Returns `0deg`.
- #[inline]
- pub fn zero() -> Self {
- Self::from_degrees(0.0, false)
- }
-
/// Returns an `Angle` parsed from a `calc()` expression.
pub fn from_calc(degrees: CSSFloat) -> Self {
Angle {
diff --git a/components/style/values/specified/basic_shape.rs b/components/style/values/specified/basic_shape.rs
index b757c8eec48..014ce439d3c 100644
--- a/components/style/values/specified/basic_shape.rs
+++ b/components/style/values/specified/basic_shape.rs
@@ -18,6 +18,7 @@ use crate::values::specified::position::{HorizontalPosition, Position, VerticalP
use crate::values::specified::url::SpecifiedUrl;
use crate::values::specified::SVGPathData;
use crate::values::specified::{LengthPercentage, NonNegativeLengthPercentage};
+use crate::Zero;
use cssparser::Parser;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
@@ -202,9 +203,9 @@ impl InsetRect {
) -> Result<Self, ParseError<'i>> {
let rect = Rect::parse_with(context, input, LengthPercentage::parse)?;
let round = if input.try(|i| i.expect_ident_matching("round")).is_ok() {
- Some(BorderRadius::parse(context, input)?)
+ BorderRadius::parse(context, input)?
} else {
- None
+ BorderRadius::zero()
};
Ok(generic::InsetRect { rect, round })
}
diff --git a/components/style/values/specified/border.rs b/components/style/values/specified/border.rs
index e16d37b4786..d0ef8126482 100644
--- a/components/style/values/specified/border.rs
+++ b/components/style/values/specified/border.rs
@@ -12,9 +12,10 @@ use crate::values::generics::border::BorderImageSlice as GenericBorderImageSlice
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::size::Size2D;
use crate::values::specified::length::{NonNegativeLength, NonNegativeLengthPercentage};
use crate::values::specified::{AllowQuirks, NonNegativeNumber, NonNegativeNumberOrPercentage};
+use crate::Zero;
use cssparser::Parser;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, ToCss};
@@ -228,7 +229,7 @@ impl Parse for BorderCornerRadius {
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
- Size::parse_with(context, input, NonNegativeLengthPercentage::parse)
+ Size2D::parse_with(context, input, NonNegativeLengthPercentage::parse)
.map(GenericBorderCornerRadius)
}
}
@@ -238,7 +239,7 @@ impl Parse for BorderSpacing {
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
- Size::parse_with(context, input, |context, input| {
+ Size2D::parse_with(context, input, |context, input| {
NonNegativeLength::parse_quirky(context, input, AllowQuirks::Yes).map(From::from)
})
.map(GenericBorderSpacing)
diff --git a/components/style/values/specified/box.rs b/components/style/values/specified/box.rs
index 2495cca3d6c..d4b66e42ab9 100644
--- a/components/style/values/specified/box.rs
+++ b/components/style/values/specified/box.rs
@@ -752,25 +752,23 @@ pub fn assert_touch_action_matches() {
bitflags! {
#[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue)]
- #[value_info(other_values = "none,strict,content,size,layout,style,paint")]
+ #[value_info(other_values = "none,strict,content,size,layout,paint")]
/// Constants for contain: https://drafts.csswg.org/css-contain/#contain-property
pub struct Contain: u8 {
/// 'size' variant, turns on size containment
const SIZE = 0x01;
/// `layout` variant, turns on layout containment
const LAYOUT = 0x02;
- /// `style` variant, turns on style containment
- const STYLE = 0x04;
/// `paint` variant, turns on paint containment
- const PAINT = 0x08;
+ const PAINT = 0x04;
/// `strict` variant, turns on all types of containment
- const STRICT = 0x10;
- /// 'content' variant, turns on style, layout, and paint containment
- const CONTENT = 0x20;
+ const STRICT = 0x08;
+ /// 'content' variant, turns on layout and paint containment
+ const CONTENT = 0x10;
/// variant with all the bits that contain: strict turns on
- const STRICT_BITS = Contain::LAYOUT.bits | Contain::STYLE.bits | Contain::PAINT.bits | Contain::SIZE.bits;
+ const STRICT_BITS = Contain::LAYOUT.bits | Contain::PAINT.bits | Contain::SIZE.bits;
/// variant with all the bits that contain: content turns on
- const CONTENT_BITS = Contain::STYLE.bits | Contain::LAYOUT.bits | Contain::PAINT.bits;
+ const CONTENT_BITS = Contain::LAYOUT.bits | Contain::PAINT.bits;
}
}
@@ -803,7 +801,6 @@ impl ToCss for Contain {
}
maybe_write_value!(Contain::SIZE => "size");
maybe_write_value!(Contain::LAYOUT => "layout");
- maybe_write_value!(Contain::STYLE => "style");
maybe_write_value!(Contain::PAINT => "paint");
debug_assert!(has_any);
@@ -812,7 +809,7 @@ impl ToCss for Contain {
}
impl Parse for Contain {
- /// none | strict | content | [ size || layout || style || paint ]
+ /// none | strict | content | [ size || layout || paint ]
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
@@ -822,7 +819,6 @@ impl Parse for Contain {
let flag = match_ignore_ascii_case! { &name,
"size" => Some(Contain::SIZE),
"layout" => Some(Contain::LAYOUT),
- "style" => Some(Contain::STYLE),
"paint" => Some(Contain::PAINT),
"strict" if result.is_empty() => return Ok(Contain::STRICT | Contain::STRICT_BITS),
"content" if result.is_empty() => return Ok(Contain::CONTENT | Contain::CONTENT_BITS),
diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs
index 7a42e834236..9ef9ab57f0a 100644
--- a/components/style/values/specified/color.rs
+++ b/components/style/values/specified/color.rs
@@ -351,13 +351,13 @@ impl Color {
Color::Special(special) => {
use self::gecko::SpecialColorKeyword as Keyword;
_context.map(|context| {
- let pres_context = context.device().pres_context();
+ let prefs = context.device().pref_sheet_prefs();
convert_nscolor_to_computedcolor(match special {
- Keyword::MozDefaultColor => pres_context.mDefaultColor,
- Keyword::MozDefaultBackgroundColor => pres_context.mBackgroundColor,
- Keyword::MozHyperlinktext => pres_context.mLinkColor,
- Keyword::MozActivehyperlinktext => pres_context.mActiveLinkColor,
- Keyword::MozVisitedhyperlinktext => pres_context.mVisitedLinkColor,
+ Keyword::MozDefaultColor => prefs.mDefaultColor,
+ Keyword::MozDefaultBackgroundColor => prefs.mDefaultBackgroundColor,
+ Keyword::MozHyperlinktext => prefs.mLinkColor,
+ Keyword::MozActivehyperlinktext => prefs.mActiveLinkColor,
+ Keyword::MozVisitedhyperlinktext => prefs.mVisitedLinkColor,
})
})
},
diff --git a/components/style/values/specified/effects.rs b/components/style/values/specified/effects.rs
index 42ec0ce0005..38a53749605 100644
--- a/components/style/values/specified/effects.rs
+++ b/components/style/values/specified/effects.rs
@@ -20,6 +20,7 @@ use crate::values::specified::url::SpecifiedUrl;
use crate::values::specified::{Angle, NumberOrPercentage};
#[cfg(not(feature = "gecko"))]
use crate::values::Impossible;
+use crate::Zero;
use cssparser::{self, BasicParseErrorKind, Parser, Token};
use style_traits::{ParseError, StyleParseErrorKind, ValueParseErrorKind};
diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs
index ffdd8d026ef..acee43f4b38 100644
--- a/components/style/values/specified/length.rs
+++ b/components/style/values/specified/length.rs
@@ -14,11 +14,11 @@ use crate::values::generics::length as generics;
use crate::values::generics::length::{
GenericLengthOrNumber, MaxSize as GenericMaxSize, Size as GenericSize,
};
-use crate::values::generics::transform::IsZeroLength;
use crate::values::generics::NonNegative;
use crate::values::specified::calc::CalcNode;
use crate::values::specified::NonNegativeNumber;
-use crate::values::{Auto, CSSFloat, Either, Normal};
+use crate::values::{CSSFloat, Either, Normal};
+use crate::Zero;
use app_units::Au;
use cssparser::{Parser, Token};
use euclid::Size2D;
@@ -477,21 +477,6 @@ impl NoCalcLength {
})
}
- #[inline]
- /// Returns a `zero` length.
- pub fn zero() -> NoCalcLength {
- NoCalcLength::Absolute(AbsoluteLength::Px(0.))
- }
-
- #[inline]
- /// Checks whether the length value is zero.
- pub fn is_zero(&self) -> bool {
- match *self {
- NoCalcLength::Absolute(length) => length.is_zero(),
- _ => false,
- }
- }
-
/// Get a px value without context.
#[inline]
pub fn to_computed_pixel_length_without_context(&self) -> Result<CSSFloat, ()> {
@@ -510,9 +495,12 @@ impl NoCalcLength {
impl SpecifiedValueInfo for NoCalcLength {}
-impl IsZeroLength for NoCalcLength {
- #[inline]
- fn is_zero_length(&self) -> bool {
+impl Zero for NoCalcLength {
+ fn zero() -> Self {
+ NoCalcLength::Absolute(AbsoluteLength::Px(0.))
+ }
+
+ fn is_zero(&self) -> bool {
match *self {
NoCalcLength::Absolute(v) => v.is_zero(),
NoCalcLength::FontRelative(v) => v.is_zero(),
@@ -585,12 +573,6 @@ impl Mul<CSSFloat> for ViewportPercentageLength {
impl Length {
#[inline]
- /// Returns a `zero` length.
- pub fn zero() -> Length {
- Length::NoCalc(NoCalcLength::zero())
- }
-
- #[inline]
fn parse_internal<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
@@ -672,6 +654,21 @@ impl Parse for Length {
}
}
+impl Zero for Length {
+ fn zero() -> Self {
+ Length::NoCalc(NoCalcLength::zero())
+ }
+
+ fn is_zero(&self) -> bool {
+ // FIXME(emilio): Seems a bit weird to treat calc() unconditionally as
+ // non-zero here?
+ match *self {
+ Length::NoCalc(ref l) => l.is_zero(),
+ Length::Calc(..) => false,
+ }
+ }
+}
+
impl Length {
/// Parses a length, with quirks.
pub fn parse_quirky<'i, 't>(
@@ -711,12 +708,6 @@ impl From<Length> for NonNegativeLength {
}
impl NonNegativeLength {
- /// Returns a `zero` length.
- #[inline]
- pub fn zero() -> Self {
- Length::zero().into()
- }
-
/// Get an absolute length from a px value.
#[inline]
pub fn from_px(px_value: CSSFloat) -> Self {
@@ -738,9 +729,6 @@ impl NonNegativeLength {
}
}
-/// Either a NonNegativeLength or the `auto` keyword.
-pub type NonNegativeLengthOrAuto = Either<NonNegativeLength, Auto>;
-
/// A `<length-percentage>` value. This can be either a `<length>`, a
/// `<percentage>`, or a combination of both via `calc()`.
///
@@ -802,12 +790,6 @@ impl Parse for LengthPercentage {
impl LengthPercentage {
#[inline]
- /// Returns a `zero` length.
- pub fn zero() -> LengthPercentage {
- LengthPercentage::Length(NoCalcLength::zero())
- }
-
- #[inline]
/// Returns a `0%` value.
pub fn zero_percent() -> LengthPercentage {
LengthPercentage::Percentage(computed::Percentage::zero())
@@ -898,11 +880,14 @@ impl LengthPercentage {
}
}
-impl IsZeroLength for LengthPercentage {
- #[inline]
- fn is_zero_length(&self) -> bool {
+impl Zero for LengthPercentage {
+ fn zero() -> Self {
+ LengthPercentage::Length(NoCalcLength::zero())
+ }
+
+ fn is_zero(&self) -> bool {
match *self {
- LengthPercentage::Length(l) => l.is_zero_length(),
+ LengthPercentage::Length(l) => l.is_zero(),
LengthPercentage::Percentage(p) => p.0 == 0.0,
LengthPercentage::Calc(_) => false,
}
@@ -913,11 +898,6 @@ impl IsZeroLength for LengthPercentage {
pub type LengthPercentageOrAuto = generics::LengthPercentageOrAuto<LengthPercentage>;
impl LengthPercentageOrAuto {
- /// Returns a value representing a `0` length.
- pub fn zero() -> Self {
- generics::LengthPercentageOrAuto::LengthPercentage(LengthPercentage::zero())
- }
-
/// Returns a value representing `0%`.
#[inline]
pub fn zero_percent() -> Self {
@@ -943,11 +923,6 @@ pub type NonNegativeLengthPercentageOrAuto =
generics::LengthPercentageOrAuto<NonNegativeLengthPercentage>;
impl NonNegativeLengthPercentageOrAuto {
- /// Returns a value representing a `0` length.
- pub fn zero() -> Self {
- generics::LengthPercentageOrAuto::LengthPercentage(NonNegativeLengthPercentage::zero())
- }
-
/// Returns a value representing `0%`.
#[inline]
pub fn zero_percent() -> Self {
@@ -998,12 +973,6 @@ impl Parse for NonNegativeLengthPercentage {
impl NonNegativeLengthPercentage {
#[inline]
- /// Returns a `zero` length.
- pub fn zero() -> Self {
- NonNegative(LengthPercentage::zero())
- }
-
- #[inline]
/// Returns a `0%` value.
pub fn zero_percent() -> Self {
NonNegative(LengthPercentage::zero_percent())
@@ -1025,7 +994,29 @@ impl NonNegativeLengthPercentage {
pub type LengthOrNormal = Either<Length, Normal>;
/// Either a `<length>` or the `auto` keyword.
-pub type LengthOrAuto = Either<Length, Auto>;
+///
+/// Note that we use LengthPercentage just for convenience, since it pretty much
+/// is everything we care about, but we could just add a similar LengthOrAuto
+/// instead if we think getting rid of this weirdness is worth it.
+pub type LengthOrAuto = generics::LengthPercentageOrAuto<Length>;
+
+impl LengthOrAuto {
+ /// Parses a length, allowing the unitless length quirk.
+ /// <https://quirks.spec.whatwg.org/#the-unitless-length-quirk>
+ #[inline]
+ pub fn parse_quirky<'i, 't>(
+ context: &ParserContext,
+ input: &mut Parser<'i, 't>,
+ allow_quirks: AllowQuirks,
+ ) -> Result<Self, ParseError<'i>> {
+ Self::parse_with(context, input, |context, input| {
+ Length::parse_quirky(context, input, allow_quirks)
+ })
+ }
+}
+
+/// Either a non-negative `<length>` or the `auto` keyword.
+pub type NonNegativeLengthOrAuto = generics::LengthPercentageOrAuto<NonNegativeLength>;
/// Either a `<length>` or a `<number>`.
pub type LengthOrNumber = GenericLengthOrNumber<Length, Number>;
diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs
index 4956d53f177..7295f060697 100644
--- a/components/style/values/specified/mod.rs
+++ b/components/style/values/specified/mod.rs
@@ -11,7 +11,7 @@ use super::computed::{Context, ToComputedValue};
use super::generics::grid::{GridLine as GenericGridLine, TrackBreadth as GenericTrackBreadth};
use super::generics::grid::{TrackList as GenericTrackList, TrackSize as GenericTrackSize};
use super::generics::transform::IsParallelTo;
-use super::generics::{GreaterThanOrEqualToOne, NonNegative};
+use super::generics::{self, GreaterThanOrEqualToOne, NonNegative};
use super::{Auto, CSSFloat, CSSInteger, Either};
use crate::context::QuirksMode;
use crate::parser::{Parse, ParserContext};
@@ -60,7 +60,7 @@ pub use self::image::{ColorStop, EndingShape as GradientEndingShape, Gradient};
pub use self::image::{GradientItem, GradientKind, Image, ImageLayer, MozImageRect};
pub use self::length::{AbsoluteLength, CalcLengthPercentage, CharacterWidth};
pub use self::length::{FontRelativeLength, Length, LengthOrNumber, NonNegativeLengthOrNumber};
-pub use self::length::{LengthPercentage, LengthPercentageOrAuto};
+pub use self::length::{LengthOrAuto, LengthPercentage, LengthPercentageOrAuto};
pub use self::length::{MaxSize, Size};
pub use self::length::{NoCalcLength, ViewportPercentageLength};
pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto};
@@ -80,7 +80,7 @@ pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
pub use self::svg_path::SVGPathData;
pub use self::table::XSpan;
pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextAlign};
-pub use self::text::{OverflowWrap, TextEmphasisPosition, TextEmphasisStyle};
+pub use self::text::{OverflowWrap, TextEmphasisPosition, TextEmphasisStyle, WordBreak};
pub use self::text::{TextAlignKeyword, TextDecorationLine, TextOverflow, WordSpacing};
pub use self::time::Time;
pub use self::transform::{Rotate, Scale, Transform};
@@ -605,99 +605,8 @@ pub type GridLine = GenericGridLine<Integer>;
/// `<grid-template-rows> | <grid-template-columns>`
pub type GridTemplateComponent = GenericGridTemplateComponent<LengthPercentage, Integer>;
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo)]
-/// rect(<top>, <left>, <bottom>, <right>) used by clip and image-region
-#[css(function = "rect")]
-pub struct ClipRect {
- /// <top> (<length> | <auto>)
- pub top: Option<Length>,
- /// <right> (<length> | <auto>)
- pub right: Option<Length>,
- /// <bottom> (<length> | <auto>)
- pub bottom: Option<Length>,
- /// <left> (<length> | <auto>)
- pub left: Option<Length>,
-}
-
-impl ToCss for ClipRect {
- fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
- where
- W: Write,
- {
- dest.write_str("rect(")?;
-
- if let Some(ref top) = self.top {
- top.to_css(dest)?;
- dest.write_str(", ")?;
- } else {
- dest.write_str("auto, ")?;
- }
-
- if let Some(ref right) = self.right {
- right.to_css(dest)?;
- dest.write_str(", ")?;
- } else {
- dest.write_str("auto, ")?;
- }
-
- if let Some(ref bottom) = self.bottom {
- bottom.to_css(dest)?;
- dest.write_str(", ")?;
- } else {
- dest.write_str("auto, ")?;
- }
-
- if let Some(ref left) = self.left {
- left.to_css(dest)?;
- } else {
- dest.write_str("auto")?;
- }
-
- dest.write_str(")")?;
- Ok(())
- }
-}
-
-impl ToComputedValue for ClipRect {
- type ComputedValue = super::computed::ClipRect;
-
- #[inline]
- fn to_computed_value(&self, context: &Context) -> super::computed::ClipRect {
- super::computed::ClipRect {
- top: self.top.as_ref().map(|top| top.to_computed_value(context)),
- right: self
- .right
- .as_ref()
- .map(|right| right.to_computed_value(context)),
- bottom: self
- .bottom
- .as_ref()
- .map(|bottom| bottom.to_computed_value(context)),
- left: self
- .left
- .as_ref()
- .map(|left| left.to_computed_value(context)),
- }
- }
-
- #[inline]
- fn from_computed_value(computed: &super::computed::ClipRect) -> Self {
- ClipRect {
- top: computed
- .top
- .map(|top| ToComputedValue::from_computed_value(&top)),
- right: computed
- .right
- .map(|right| ToComputedValue::from_computed_value(&right)),
- bottom: computed
- .bottom
- .map(|bottom| ToComputedValue::from_computed_value(&bottom)),
- left: computed
- .left
- .map(|left| ToComputedValue::from_computed_value(&left)),
- }
- }
-}
+/// rect(...)
+pub type ClipRect = generics::ClipRect<LengthOrAuto>;
impl Parse for ClipRect {
fn parse<'i, 't>(
@@ -715,25 +624,16 @@ impl ClipRect {
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks,
) -> Result<Self, ParseError<'i>> {
- use crate::values::specified::Length;
+ input.expect_function_matching("rect")?;
fn parse_argument<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
allow_quirks: AllowQuirks,
- ) -> Result<Option<Length>, ParseError<'i>> {
- if input
- .try(|input| input.expect_ident_matching("auto"))
- .is_ok()
- {
- Ok(None)
- } else {
- Length::parse_quirky(context, input, allow_quirks).map(Some)
- }
+ ) -> Result<LengthOrAuto, ParseError<'i>> {
+ LengthOrAuto::parse_quirky(context, input, allow_quirks)
}
- input.expect_function_matching("rect")?;
-
input.parse_nested_block(|input| {
let top = parse_argument(context, input, allow_quirks)?;
let right;
@@ -751,11 +651,12 @@ impl ClipRect {
bottom = parse_argument(context, input, allow_quirks)?;
left = parse_argument(context, input, allow_quirks)?;
}
+
Ok(ClipRect {
- top: top,
- right: right,
- bottom: bottom,
- left: left,
+ top,
+ right,
+ bottom,
+ left,
})
})
}
@@ -782,16 +683,22 @@ impl ClipRectOrAuto {
/// Whether quirks are allowed in this context.
#[derive(Clone, Copy, PartialEq)]
pub enum AllowQuirks {
- /// Quirks are allowed.
- Yes,
/// Quirks are not allowed.
No,
+ /// Quirks are allowed, in quirks mode.
+ Yes,
+ /// Quirks are always allowed, used for SVG lengths.
+ Always,
}
impl AllowQuirks {
/// Returns `true` if quirks are allowed in this context.
pub fn allowed(self, quirks_mode: QuirksMode) -> bool {
- self == AllowQuirks::Yes && quirks_mode == QuirksMode::Quirks
+ match self {
+ AllowQuirks::Always => true,
+ AllowQuirks::No => false,
+ AllowQuirks::Yes => quirks_mode == QuirksMode::Quirks,
+ }
}
}
diff --git a/components/style/values/specified/position.rs b/components/style/values/specified/position.rs
index 0212763ec6d..f60767f1656 100644
--- a/components/style/values/specified/position.rs
+++ b/components/style/values/specified/position.rs
@@ -17,6 +17,7 @@ use crate::values::generics::position::ZIndex as GenericZIndex;
use crate::values::specified::transform::OriginComponent;
use crate::values::specified::{AllowQuirks, Integer, LengthPercentage};
use crate::values::{Either, None_};
+use crate::Zero;
use cssparser::Parser;
use selectors::parser::SelectorParseErrorKind;
use servo_arc::Arc;
diff --git a/components/style/values/specified/svg.rs b/components/style/values/specified/svg.rs
index 98db273e61c..556e995c02f 100644
--- a/components/style/values/specified/svg.rs
+++ b/components/style/values/specified/svg.rs
@@ -8,9 +8,9 @@ use crate::parser::{Parse, ParserContext};
use crate::values::generics::svg as generic;
use crate::values::specified::color::Color;
use crate::values::specified::url::SpecifiedUrl;
+use crate::values::specified::AllowQuirks;
use crate::values::specified::LengthPercentage;
-use crate::values::specified::{NonNegativeLengthPercentage, NonNegativeNumber};
-use crate::values::specified::{Number, Opacity};
+use crate::values::specified::{NonNegativeLengthPercentage, Opacity};
use crate::values::CustomIdent;
use cssparser::Parser;
use std::fmt::{self, Write};
@@ -23,36 +23,52 @@ pub type SVGPaint = generic::SVGPaint<Color, SpecifiedUrl>;
/// Specified SVG Paint Kind value
pub type SVGPaintKind = generic::SVGPaintKind<Color, SpecifiedUrl>;
-/// A value of <length> | <percentage> | <number> for stroke-dashoffset.
-/// <https://www.w3.org/TR/SVG11/painting.html#StrokeProperties>
-pub type SvgLengthPercentageOrNumber =
- generic::SvgLengthPercentageOrNumber<LengthPercentage, Number>;
-
/// <length> | <percentage> | <number> | context-value
-pub type SVGLength = generic::SVGLength<SvgLengthPercentageOrNumber>;
+pub type SVGLength = generic::SVGLength<LengthPercentage>;
-impl From<SvgLengthPercentageOrNumber> for SVGLength {
- fn from(length: SvgLengthPercentageOrNumber) -> Self {
- generic::SVGLength::Length(length)
- }
+/// A non-negative version of SVGLength.
+pub type SVGWidth = generic::SVGLength<NonNegativeLengthPercentage>;
+
+/// [ <length> | <percentage> | <number> ]# | context-value
+pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeLengthPercentage>;
+
+/// Whether the `context-value` value is enabled.
+#[cfg(feature = "gecko")]
+pub fn is_context_value_enabled() -> bool {
+ use crate::gecko_bindings::structs::mozilla;
+ unsafe { mozilla::StaticPrefs_sVarCache_gfx_font_rendering_opentype_svg_enabled }
}
-/// A value of <length> | <percentage> | <number> for stroke-width/stroke-dasharray.
-/// <https://www.w3.org/TR/SVG11/painting.html#StrokeProperties>
-pub type NonNegativeSvgLengthPercentageOrNumber =
- generic::SvgLengthPercentageOrNumber<NonNegativeLengthPercentage, NonNegativeNumber>;
+/// Whether the `context-value` value is enabled.
+#[cfg(not(feature = "gecko"))]
+pub fn is_context_value_enabled() -> bool {
+ false
+}
-/// A non-negative version of SVGLength.
-pub type SVGWidth = generic::SVGLength<NonNegativeSvgLengthPercentageOrNumber>;
+macro_rules! parse_svg_length {
+ ($ty:ty, $lp:ty) => {
+ impl Parse for $ty {
+ fn parse<'i, 't>(
+ context: &ParserContext,
+ input: &mut Parser<'i, 't>,
+ ) -> Result<Self, ParseError<'i>> {
+ if let Ok(lp) = input.try(|i| <$lp>::parse_quirky(context, i, AllowQuirks::Always))
+ {
+ return Ok(generic::SVGLength::LengthPercentage(lp));
+ }
-impl From<NonNegativeSvgLengthPercentageOrNumber> for SVGWidth {
- fn from(length: NonNegativeSvgLengthPercentageOrNumber) -> Self {
- generic::SVGLength::Length(length)
- }
+ try_match_ident_ignore_ascii_case! { input,
+ "context-value" if is_context_value_enabled() => {
+ Ok(generic::SVGLength::ContextValue)
+ },
+ }
+ }
+ }
+ };
}
-/// [ <length> | <percentage> | <number> ]# | context-value
-pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeSvgLengthPercentageOrNumber>;
+parse_svg_length!(SVGLength, LengthPercentage);
+parse_svg_length!(SVGWidth, NonNegativeLengthPercentage);
impl Parse for SVGStrokeDashArray {
fn parse<'i, 't>(
@@ -61,14 +77,14 @@ impl Parse for SVGStrokeDashArray {
) -> Result<Self, ParseError<'i>> {
if let Ok(values) = input.try(|i| {
CommaWithSpace::parse(i, |i| {
- NonNegativeSvgLengthPercentageOrNumber::parse(context, i)
+ NonNegativeLengthPercentage::parse_quirky(context, i, AllowQuirks::Always)
})
}) {
return Ok(generic::SVGStrokeDashArray::Values(values));
}
try_match_ident_ignore_ascii_case! { input,
- "context-value" if generic::is_context_value_enabled(context) => {
+ "context-value" if is_context_value_enabled() => {
Ok(generic::SVGStrokeDashArray::ContextValue)
},
"none" => Ok(generic::SVGStrokeDashArray::Values(vec![])),
diff --git a/components/style/values/specified/text.rs b/components/style/values/specified/text.rs
index 1879dc4159a..883084e649a 100644
--- a/components/style/values/specified/text.rs
+++ b/components/style/values/specified/text.rs
@@ -813,6 +813,33 @@ impl From<TextEmphasisPosition> for u8 {
}
}
+/// Values for the `word-break` property.
+#[repr(u8)]
+#[derive(
+ Clone,
+ Copy,
+ Debug,
+ Eq,
+ MallocSizeOf,
+ Parse,
+ PartialEq,
+ SpecifiedValueInfo,
+ ToComputedValue,
+ ToCss,
+)]
+#[allow(missing_docs)]
+pub enum WordBreak {
+ Normal,
+ BreakAll,
+ KeepAll,
+ /// The break-word value, needed for compat.
+ ///
+ /// Specifying `word-break: break-word` makes `overflow-wrap` behave as
+ /// `anywhere`, and `word-break` behave like `normal`.
+ #[cfg(feature = "gecko")]
+ BreakWord,
+}
+
/// Values for the `overflow-wrap` property.
#[repr(u8)]
#[derive(
diff --git a/components/style/values/specified/transform.rs b/components/style/values/specified/transform.rs
index c4f43735498..92ca953159f 100644
--- a/components/style/values/specified/transform.rs
+++ b/components/style/values/specified/transform.rs
@@ -11,6 +11,7 @@ use crate::values::generics::transform as generic;
use crate::values::generics::transform::{Matrix, Matrix3D};
use crate::values::specified::position::{Side, X, Y};
use crate::values::specified::{self, Angle, Integer, Length, LengthPercentage, Number};
+use crate::Zero;
use cssparser::Parser;
use style_traits::{ParseError, StyleParseErrorKind};
@@ -108,9 +109,9 @@ impl Transform {
let sx = specified::LengthPercentage::parse(context, input)?;
if input.try(|input| input.expect_comma()).is_ok() {
let sy = specified::LengthPercentage::parse(context, input)?;
- Ok(generic::TransformOperation::Translate(sx, Some(sy)))
+ Ok(generic::TransformOperation::Translate(sx, sy))
} else {
- Ok(generic::TransformOperation::Translate(sx, None))
+ Ok(generic::TransformOperation::Translate(sx, Zero::zero()))
}
},
"translatex" => {
@@ -137,9 +138,9 @@ impl Transform {
let sx = Number::parse(context, input)?;
if input.try(|input| input.expect_comma()).is_ok() {
let sy = Number::parse(context, input)?;
- Ok(generic::TransformOperation::Scale(sx, Some(sy)))
+ Ok(generic::TransformOperation::Scale(sx, sy))
} else {
- Ok(generic::TransformOperation::Scale(sx, None))
+ Ok(generic::TransformOperation::Scale(sx, sx))
}
},
"scalex" => {
@@ -193,9 +194,9 @@ impl Transform {
let ax = specified::Angle::parse_with_unitless(context, input)?;
if input.try(|input| input.expect_comma()).is_ok() {
let ay = specified::Angle::parse_with_unitless(context, input)?;
- Ok(generic::TransformOperation::Skew(ax, Some(ay)))
+ Ok(generic::TransformOperation::Skew(ax, ay))
} else {
- Ok(generic::TransformOperation::Skew(ax, None))
+ Ok(generic::TransformOperation::Skew(ax, Zero::zero()))
}
},
"skewx" => {
diff --git a/components/style_derive/cg.rs b/components/style_derive/cg.rs
index 6eeca384bfa..a5f15a0358e 100644
--- a/components/style_derive/cg.rs
+++ b/components/style_derive/cg.rs
@@ -12,6 +12,70 @@ use syn::{TypeParam, TypeParen, TypePath, TypeSlice, TypeTuple};
use syn::{Variant, WherePredicate};
use synstructure::{self, BindStyle, BindingInfo, VariantAst, VariantInfo};
+/// Given an input type which has some where clauses already, like:
+///
+/// struct InputType<T>
+/// where
+/// T: Zero,
+/// {
+/// ...
+/// }
+///
+/// Add the necessary `where` clauses so that the output type of a trait
+/// fulfils them.
+///
+/// For example:
+///
+/// <T as ToComputedValue>::ComputedValue: Zero,
+///
+/// This needs to run before adding other bounds to the type parameters.
+pub fn propagate_clauses_to_output_type(
+ where_clause: &mut Option<syn::WhereClause>,
+ generics: &syn::Generics,
+ trait_path: Path,
+ trait_output: Ident,
+) {
+ let where_clause = match *where_clause {
+ Some(ref mut clause) => clause,
+ None => return,
+ };
+ let mut extra_bounds = vec![];
+ for pred in &where_clause.predicates {
+ let ty = match *pred {
+ syn::WherePredicate::Type(ref ty) => ty,
+ ref predicate => panic!("Unhanded complex where predicate: {:?}", predicate),
+ };
+
+ let path = match ty.bounded_ty {
+ syn::Type::Path(ref p) => &p.path,
+ ref ty => panic!("Unhanded complex where type: {:?}", ty),
+ };
+
+ assert!(
+ ty.lifetimes.is_none(),
+ "Unhanded complex lifetime bound: {:?}",
+ ty,
+ );
+
+ let ident = match path_to_ident(path) {
+ Some(i) => i,
+ None => panic!("Unhanded complex where type path: {:?}", path),
+ };
+
+ if generics.type_params().any(|param| param.ident == *ident) {
+ extra_bounds.push(ty.clone());
+ }
+ }
+
+ for bound in extra_bounds {
+ let ty = bound.bounded_ty;
+ let bounds = bound.bounds;
+ where_clause
+ .predicates
+ .push(parse_quote!(<#ty as #trait_path>::#trait_output: #bounds))
+ }
+}
+
pub fn add_predicate(where_clause: &mut Option<syn::WhereClause>, pred: WherePredicate) {
where_clause
.get_or_insert(parse_quote!(where))
diff --git a/components/style_derive/to_animated_value.rs b/components/style_derive/to_animated_value.rs
index b53cf9c3d41..1aba9b3327e 100644
--- a/components/style_derive/to_animated_value.rs
+++ b/components/style_derive/to_animated_value.rs
@@ -9,6 +9,12 @@ use synstructure::BindStyle;
pub fn derive(mut input: DeriveInput) -> TokenStream {
let mut where_clause = input.generics.where_clause.take();
+ cg::propagate_clauses_to_output_type(
+ &mut where_clause,
+ &input.generics,
+ parse_quote!(crate::values::animated::ToAnimatedValue),
+ parse_quote!(AnimatedValue),
+ );
for param in input.generics.type_params() {
cg::add_predicate(
&mut where_clause,
diff --git a/components/style_derive/to_computed_value.rs b/components/style_derive/to_computed_value.rs
index 68261740502..b0b2aa6af63 100644
--- a/components/style_derive/to_computed_value.rs
+++ b/components/style_derive/to_computed_value.rs
@@ -9,6 +9,12 @@ use synstructure::BindStyle;
pub fn derive(mut input: DeriveInput) -> TokenStream {
let mut where_clause = input.generics.where_clause.take();
+ cg::propagate_clauses_to_output_type(
+ &mut where_clause,
+ &input.generics,
+ parse_quote!(crate::values::computed::ToComputedValue),
+ parse_quote!(ComputedValue),
+ );
let (to_body, from_body) = {
let params = input.generics.type_params().collect::<Vec<_>>();
for param in &params {
diff --git a/components/style_derive/to_css.rs b/components/style_derive/to_css.rs
index 4eabdcb8357..249ff2969cd 100644
--- a/components/style_derive/to_css.rs
+++ b/components/style_derive/to_css.rs
@@ -148,12 +148,20 @@ fn derive_variant_fields_expr(
}
}
}
+
+ if let Some(condition) = attrs.contextual_skip_if {
+ expr = quote! {
+ if !#condition(#(#bindings), *) {
+ #expr
+ }
+ }
+ }
return expr;
}
- let mut expr = derive_single_field_expr(first, attrs, where_clause);
+ let mut expr = derive_single_field_expr(first, attrs, where_clause, bindings);
for (binding, attrs) in iter {
- derive_single_field_expr(binding, attrs, where_clause).to_tokens(&mut expr)
+ derive_single_field_expr(binding, attrs, where_clause, bindings).to_tokens(&mut expr)
}
quote! {{
@@ -167,6 +175,7 @@ fn derive_single_field_expr(
field: &BindingInfo,
attrs: CssFieldAttrs,
where_clause: &mut Option<WhereClause>,
+ bindings: &[BindingInfo],
) -> TokenStream {
let mut expr = if attrs.iterable {
if let Some(if_empty) = attrs.if_empty {
@@ -216,6 +225,14 @@ fn derive_single_field_expr(
}
}
+ if let Some(condition) = attrs.contextual_skip_if {
+ expr = quote! {
+ if !#condition(#(#bindings), *) {
+ #expr
+ }
+ }
+ }
+
expr
}
@@ -249,5 +266,6 @@ pub struct CssFieldAttrs {
pub iterable: bool,
pub skip: bool,
pub represents_keyword: bool,
+ pub contextual_skip_if: Option<Path>,
pub skip_if: Option<Path>,
}
diff --git a/components/style_traits/values.rs b/components/style_traits/values.rs
index 582e34eb3db..46751541319 100644
--- a/components/style_traits/values.rs
+++ b/components/style_traits/values.rs
@@ -37,6 +37,10 @@ use std::fmt::{self, Write};
/// * if `#[css(skip_if = "function")]` is found on a field, the `ToCss` call
/// for that field is skipped if `function` returns true. This function is
/// provided the field as an argument;
+/// * if `#[css(contextual_skip_if = "function")]` is found on a field, the
+/// `ToCss` call for that field is skipped if `function` returns true. This
+/// function is given all the fields in the current struct or variant as an
+/// argument;
/// * `#[css(represents_keyword)]` can be used on bool fields in order to
/// serialize the field name if the field is true, or nothing otherwise. It
/// also collects those keywords for `SpecifiedValueInfo`.
diff --git a/tests/unit/style/animated_properties.rs b/tests/unit/style/animated_properties.rs
index 8fa45a6305f..dd233f01b89 100644
--- a/tests/unit/style/animated_properties.rs
+++ b/tests/unit/style/animated_properties.rs
@@ -92,53 +92,3 @@ fn test_transform_interpolation_on_scale() {
Transform(vec![TransformOperation::Scale3D(1.5, 3.0, 1.5)])
);
}
-
-#[test]
-fn test_transform_interpolation_on_rotate() {
- use style::values::computed::Angle;
-
- let from = Transform(vec![TransformOperation::Rotate3D(
- 0.0,
- 0.0,
- 1.0,
- Angle::from_radians(0.0),
- )]);
- let to = Transform(vec![TransformOperation::Rotate3D(
- 0.0,
- 0.0,
- 1.0,
- Angle::from_radians(100.0),
- )]);
- assert_eq!(
- from.animate(&to, Procedure::Interpolate { progress: 0.5 })
- .unwrap(),
- Transform(vec![TransformOperation::Rotate3D(
- 0.0,
- 0.0,
- 1.0,
- Angle::from_radians(50.0)
- )])
- );
-}
-
-#[test]
-fn test_transform_interpolation_on_skew() {
- use style::values::computed::Angle;
-
- let from = Transform(vec![TransformOperation::Skew(
- Angle::from_radians(0.0),
- Some(Angle::from_radians(100.0)),
- )]);
- let to = Transform(vec![TransformOperation::Skew(
- Angle::from_radians(100.0),
- Some(Angle::from_radians(0.0)),
- )]);
- assert_eq!(
- from.animate(&to, Procedure::Interpolate { progress: 0.5 })
- .unwrap(),
- Transform(vec![TransformOperation::Skew(
- Angle::from_radians(50.0),
- Some(Angle::from_radians(50.0)),
- )])
- );
-}
diff --git a/tests/unit/style/custom_properties.rs b/tests/unit/style/custom_properties.rs
index b24ca3b132a..5b5741d2690 100644
--- a/tests/unit/style/custom_properties.rs
+++ b/tests/unit/style/custom_properties.rs
@@ -7,30 +7,30 @@ use servo_arc::Arc;
use style::custom_properties::{
CssEnvironment, CustomPropertiesBuilder, CustomPropertiesMap, Name, SpecifiedValue,
};
-use style::properties::CustomDeclarationValue;
+use style::properties::{CustomDeclaration, CustomDeclarationValue};
+use style::stylesheets::Origin;
use test::{self, Bencher};
fn cascade(
name_and_value: &[(&str, &str)],
inherited: Option<&Arc<CustomPropertiesMap>>,
) -> Option<Arc<CustomPropertiesMap>> {
- let values = name_and_value
+ let declarations = name_and_value
.iter()
.map(|&(name, value)| {
let mut input = ParserInput::new(value);
let mut parser = Parser::new(&mut input);
- (
- Name::from(name),
- SpecifiedValue::parse(&mut parser).unwrap(),
- )
+ let name = Name::from(name);
+ let value = CustomDeclarationValue::Value(SpecifiedValue::parse(&mut parser).unwrap());
+ CustomDeclaration { name, value }
})
.collect::<Vec<_>>();
let env = CssEnvironment;
let mut builder = CustomPropertiesBuilder::new(inherited, &env);
- for &(ref name, ref val) in &values {
- builder.cascade(name, &CustomDeclarationValue::Value(val.clone()));
+ for declaration in &declarations {
+ builder.cascade(declaration, Origin::Author);
}
builder.build()
diff --git a/tests/wpt/metadata/css/css-text/inheritance.html.ini b/tests/wpt/metadata/css/css-text/inheritance.html.ini
index ea3be987a40..a2715f4fe76 100644
--- a/tests/wpt/metadata/css/css-text/inheritance.html.ini
+++ b/tests/wpt/metadata/css/css-text/inheritance.html.ini
@@ -2,6 +2,3 @@
[Property text-justify inherits]
expected: FAIL
- [Property word-spacing has initial value 0px]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/css/css-variables/variable-definition-keywords.html.ini b/tests/wpt/metadata/css/css-variables/variable-definition-keywords.html.ini
deleted file mode 100644
index 1759114e0b3..00000000000
--- a/tests/wpt/metadata/css/css-variables/variable-definition-keywords.html.ini
+++ /dev/null
@@ -1,7 +0,0 @@
-[variable-definition-keywords.html]
- [specified style revert]
- expected: FAIL
-
- [computed style revert]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/css/css-variables/variable-presentation-attribute.html.ini b/tests/wpt/metadata/css/css-variables/variable-presentation-attribute.html.ini
index bbb64382d67..4e4418a7cce 100644
--- a/tests/wpt/metadata/css/css-variables/variable-presentation-attribute.html.ini
+++ b/tests/wpt/metadata/css/css-variables/variable-presentation-attribute.html.ini
@@ -110,9 +110,6 @@
[Testing 'visibility'.]
expected: FAIL
- [Testing 'word-spacing'.]
- expected: FAIL
-
[Testing 'writing-mode'.]
expected: FAIL