mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
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 -->
This commit is contained in:
commit
d5fb0666d1
74 changed files with 1153 additions and 1534 deletions
|
@ -58,7 +58,7 @@ use style::properties::{style_structs, ComputedValues};
|
||||||
use style::servo::restyle_damage::ServoRestyleDamage;
|
use style::servo::restyle_damage::ServoRestyleDamage;
|
||||||
use style::values::computed::effects::SimpleShadow;
|
use style::values::computed::effects::SimpleShadow;
|
||||||
use style::values::computed::image::Image as ComputedImage;
|
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::background::BackgroundSize;
|
||||||
use style::values::generics::image::{GradientKind, Image, PaintWorklet};
|
use style::values::generics::image::{GradientKind, Image, PaintWorklet};
|
||||||
use style::values::specified::ui::CursorKind;
|
use style::values::specified::ui::CursorKind;
|
||||||
|
@ -2627,19 +2627,22 @@ impl BlockFlow {
|
||||||
_ => return,
|
_ => 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(
|
let clip_origin = Point2D::new(
|
||||||
stacking_relative_border_box.origin.x +
|
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 +
|
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
|
let right = extract_clip_component(&style_clip_rect.right)
|
||||||
.right
|
|
||||||
.map(Au::from)
|
|
||||||
.unwrap_or(stacking_relative_border_box.size.width);
|
.unwrap_or(stacking_relative_border_box.size.width);
|
||||||
let bottom = style_clip_rect
|
let bottom = extract_clip_component(&style_clip_rect.bottom)
|
||||||
.bottom
|
|
||||||
.map(Au::from)
|
|
||||||
.unwrap_or(stacking_relative_border_box.size.height);
|
.unwrap_or(stacking_relative_border_box.size.height);
|
||||||
let clip_size = Size2D::new(right - clip_origin.x, bottom - clip_origin.y);
|
let clip_size = Size2D::new(right - clip_origin.x, bottom - clip_origin.y);
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,7 @@ use style::values::computed::counters::ContentItem;
|
||||||
use style::values::computed::{LengthPercentage, LengthPercentageOrAuto, Size};
|
use style::values::computed::{LengthPercentage, LengthPercentageOrAuto, Size};
|
||||||
use style::values::generics::box_::{Perspective, VerticalAlign};
|
use style::values::generics::box_::{Perspective, VerticalAlign};
|
||||||
use style::values::generics::transform;
|
use style::values::generics::transform;
|
||||||
|
use style::Zero;
|
||||||
use webrender_api::{self, LayoutTransform};
|
use webrender_api::{self, LayoutTransform};
|
||||||
|
|
||||||
// From gfxFontConstants.h in Firefox.
|
// From gfxFontConstants.h in Firefox.
|
||||||
|
|
|
@ -19,7 +19,7 @@ use std::fmt;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use style::logical_geometry::LogicalSize;
|
use style::logical_geometry::LogicalSize;
|
||||||
use style::properties::ComputedValues;
|
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::generics::column::ColumnCount;
|
||||||
use style::values::Either;
|
use style::values::Either;
|
||||||
|
|
||||||
|
@ -114,7 +114,9 @@ impl Flow for MulticolFlow {
|
||||||
|
|
||||||
let column_style = style.get_column();
|
let column_style = style.get_column();
|
||||||
let mut column_count;
|
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);
|
let column_width = Au::from(column_width);
|
||||||
column_count = max(
|
column_count = max(
|
||||||
1,
|
1,
|
||||||
|
|
|
@ -14,7 +14,6 @@ use gfx::font::{FontMetrics, FontRef, RunMetrics, ShapingFlags, ShapingOptions};
|
||||||
use gfx::text::glyph::ByteIndex;
|
use gfx::text::glyph::ByteIndex;
|
||||||
use gfx::text::text_run::TextRun;
|
use gfx::text::text_run::TextRun;
|
||||||
use gfx::text::util::{self, CompressionMode};
|
use gfx::text::util::{self, CompressionMode};
|
||||||
use ordered_float::NotNan;
|
|
||||||
use range::Range;
|
use range::Range;
|
||||||
use servo_atoms::Atom;
|
use servo_atoms::Atom;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
|
@ -196,11 +195,7 @@ impl TextRunScanner {
|
||||||
};
|
};
|
||||||
text_transform = inherited_text_style.text_transform;
|
text_transform = inherited_text_style.text_transform;
|
||||||
letter_spacing = inherited_text_style.letter_spacing;
|
letter_spacing = inherited_text_style.letter_spacing;
|
||||||
word_spacing = inherited_text_style
|
word_spacing = inherited_text_style.word_spacing.to_hash_key();
|
||||||
.word_spacing
|
|
||||||
.value()
|
|
||||||
.map(|lop| lop.to_hash_key())
|
|
||||||
.unwrap_or((Au(0), NotNan::new(0.0).unwrap()));
|
|
||||||
text_rendering = inherited_text_style.text_rendering;
|
text_rendering = inherited_text_style.text_rendering;
|
||||||
word_break = inherited_text_style.word_break;
|
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
|
// example, `finally` with a wide `letter-spacing` renders as `f i n a l l y` and not
|
||||||
// `fi n a l l y`.
|
// `fi n a l l y`.
|
||||||
let mut flags = ShapingFlags::empty();
|
let mut flags = ShapingFlags::empty();
|
||||||
if let Some(v) = letter_spacing.value() {
|
if letter_spacing.0.px() != 0. {
|
||||||
if v.px() != 0. {
|
flags.insert(ShapingFlags::IGNORE_LIGATURES_SHAPING_FLAG);
|
||||||
flags.insert(ShapingFlags::IGNORE_LIGATURES_SHAPING_FLAG);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if text_rendering == TextRendering::Optimizespeed {
|
if text_rendering == TextRendering::Optimizespeed {
|
||||||
flags.insert(ShapingFlags::IGNORE_LIGATURES_SHAPING_FLAG);
|
flags.insert(ShapingFlags::IGNORE_LIGATURES_SHAPING_FLAG);
|
||||||
|
@ -334,8 +327,12 @@ impl TextRunScanner {
|
||||||
flags.insert(ShapingFlags::KEEP_ALL_FLAG);
|
flags.insert(ShapingFlags::KEEP_ALL_FLAG);
|
||||||
}
|
}
|
||||||
let options = ShapingOptions {
|
let options = ShapingOptions {
|
||||||
letter_spacing: letter_spacing.value().cloned().map(Au::from),
|
letter_spacing: if letter_spacing.0.px() == 0. {
|
||||||
word_spacing: word_spacing,
|
None
|
||||||
|
} else {
|
||||||
|
Some(Au::from(letter_spacing.0))
|
||||||
|
},
|
||||||
|
word_spacing,
|
||||||
script: Script::Common,
|
script: Script::Common,
|
||||||
flags: flags,
|
flags: flags,
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,6 +13,7 @@ autogen_warning = """/* DO NOT MODIFY THIS MANUALLY! This file was generated usi
|
||||||
class nsAtom;
|
class nsAtom;
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
class WritingMode;
|
class WritingMode;
|
||||||
|
enum HalfCorner : uint8_t;
|
||||||
enum LogicalSide : uint8_t;
|
enum LogicalSide : uint8_t;
|
||||||
namespace css {
|
namespace css {
|
||||||
struct URLValue;
|
struct URLValue;
|
||||||
|
@ -39,8 +40,13 @@ include = ["cssparser", "style_traits"]
|
||||||
derive_eq = true
|
derive_eq = true
|
||||||
derive_neq = true
|
derive_neq = true
|
||||||
|
|
||||||
|
[macro_expansion]
|
||||||
|
bitflags = true
|
||||||
|
|
||||||
[enum]
|
[enum]
|
||||||
derive_helper_methods = true
|
derive_helper_methods = true
|
||||||
|
derive_const_casts = true
|
||||||
|
cast_assert_name = "MOZ_ASSERT"
|
||||||
|
|
||||||
[export]
|
[export]
|
||||||
prefix = "Style"
|
prefix = "Style"
|
||||||
|
@ -77,8 +83,10 @@ include = [
|
||||||
"Resize",
|
"Resize",
|
||||||
"Overflow",
|
"Overflow",
|
||||||
"LengthPercentage",
|
"LengthPercentage",
|
||||||
|
"LetterSpacing",
|
||||||
"NonNegativeLengthPercentage",
|
"NonNegativeLengthPercentage",
|
||||||
"LengthPercentageOrAuto",
|
"LengthPercentageOrAuto",
|
||||||
|
"LineHeight",
|
||||||
"NonNegativeLengthPercentageOrAuto",
|
"NonNegativeLengthPercentageOrAuto",
|
||||||
"Rect",
|
"Rect",
|
||||||
"IntersectionObserverRootMargin",
|
"IntersectionObserverRootMargin",
|
||||||
|
@ -88,16 +96,20 @@ include = [
|
||||||
"Position",
|
"Position",
|
||||||
"BackgroundSize",
|
"BackgroundSize",
|
||||||
"BorderImageSlice",
|
"BorderImageSlice",
|
||||||
|
"BorderSpacing",
|
||||||
|
"BorderRadius",
|
||||||
"NonNegativeLengthOrNumberRect",
|
"NonNegativeLengthOrNumberRect",
|
||||||
"Perspective",
|
"Perspective",
|
||||||
"ZIndex",
|
"ZIndex",
|
||||||
"TransformOrigin",
|
"TransformOrigin",
|
||||||
|
"WordBreak",
|
||||||
]
|
]
|
||||||
item_types = ["enums", "structs", "typedefs"]
|
item_types = ["enums", "structs", "typedefs"]
|
||||||
|
|
||||||
[export.body]
|
[export.body]
|
||||||
"CSSPixelLength" = """
|
"CSSPixelLength" = """
|
||||||
inline nscoord ToAppUnits() const;
|
inline nscoord ToAppUnits() const;
|
||||||
|
inline bool IsZero() const;
|
||||||
"""
|
"""
|
||||||
|
|
||||||
"LengthPercentage" = """
|
"LengthPercentage" = """
|
||||||
|
@ -114,6 +126,7 @@ item_types = ["enums", "structs", "typedefs"]
|
||||||
inline bool ConvertsToPercentage() const;
|
inline bool ConvertsToPercentage() const;
|
||||||
inline bool HasLengthAndPercentage() const;
|
inline bool HasLengthAndPercentage() const;
|
||||||
inline float ToPercentage() const;
|
inline float ToPercentage() const;
|
||||||
|
inline bool IsDefinitelyZero() const;
|
||||||
inline CSSCoord ResolveToCSSPixels(CSSCoord aPercentageBasisInCSSPixels) const;
|
inline CSSCoord ResolveToCSSPixels(CSSCoord aPercentageBasisInCSSPixels) const;
|
||||||
template<typename T> inline CSSCoord ResolveToCSSPixelsWith(T aPercentageGetter) const;
|
template<typename T> inline CSSCoord ResolveToCSSPixelsWith(T aPercentageGetter) const;
|
||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
|
@ -125,7 +138,6 @@ item_types = ["enums", "structs", "typedefs"]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
"GenericLengthPercentageOrAuto" = """
|
"GenericLengthPercentageOrAuto" = """
|
||||||
inline const StyleLengthPercentage& AsLengthPercentage() const;
|
|
||||||
inline bool ConvertsToLength() const;
|
inline bool ConvertsToLength() const;
|
||||||
inline nscoord ToLength() const;
|
inline nscoord ToLength() const;
|
||||||
inline bool ConvertsToPercentage() const;
|
inline bool ConvertsToPercentage() const;
|
||||||
|
@ -135,8 +147,6 @@ item_types = ["enums", "structs", "typedefs"]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
"GenericSize" = """
|
"GenericSize" = """
|
||||||
inline const StyleLengthPercentage& AsLengthPercentage() const;
|
|
||||||
inline StyleExtremumLength AsExtremumLength() const;
|
|
||||||
inline bool ConvertsToLength() const;
|
inline bool ConvertsToLength() const;
|
||||||
inline nscoord ToLength() const;
|
inline nscoord ToLength() const;
|
||||||
inline bool ConvertsToPercentage() const;
|
inline bool ConvertsToPercentage() const;
|
||||||
|
@ -148,12 +158,9 @@ item_types = ["enums", "structs", "typedefs"]
|
||||||
|
|
||||||
"GenericFlexBasis" = """
|
"GenericFlexBasis" = """
|
||||||
inline bool IsAuto() const;
|
inline bool IsAuto() const;
|
||||||
inline const StyleSize& AsSize() const;
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
"GenericMaxSize" = """
|
"GenericMaxSize" = """
|
||||||
inline const StyleLengthPercentage& AsLengthPercentage() const;
|
|
||||||
inline StyleExtremumLength AsExtremumLength() const;
|
|
||||||
inline bool ConvertsToLength() const;
|
inline bool ConvertsToLength() const;
|
||||||
inline nscoord ToLength() const;
|
inline nscoord ToLength() const;
|
||||||
inline bool ConvertsToPercentage() const;
|
inline bool ConvertsToPercentage() const;
|
||||||
|
@ -185,3 +192,7 @@ item_types = ["enums", "structs", "typedefs"]
|
||||||
inline const T& GetIEnd(mozilla::WritingMode) const;
|
inline const T& GetIEnd(mozilla::WritingMode) const;
|
||||||
inline const T& GetBEnd(mozilla::WritingMode) const;
|
inline const T& GetBEnd(mozilla::WritingMode) const;
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
"GenericBorderRadius" = """
|
||||||
|
inline const StyleLengthPercentage& Get(mozilla::HalfCorner) const;
|
||||||
|
"""
|
||||||
|
|
|
@ -7,8 +7,9 @@
|
||||||
//! [custom]: https://drafts.csswg.org/css-variables/
|
//! [custom]: https://drafts.csswg.org/css-variables/
|
||||||
|
|
||||||
use crate::hash::map::Entry;
|
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::selector_map::{PrecomputedHashMap, PrecomputedHashSet, PrecomputedHasher};
|
||||||
|
use crate::stylesheets::{Origin, PerOrigin};
|
||||||
use crate::Atom;
|
use crate::Atom;
|
||||||
use cssparser::{Delimiter, Parser, ParserInput, SourcePosition, Token, TokenSerializationType};
|
use cssparser::{Delimiter, Parser, ParserInput, SourcePosition, Token, TokenSerializationType};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
@ -490,6 +491,7 @@ fn parse_env_function<'i, 't>(
|
||||||
/// properties.
|
/// properties.
|
||||||
pub struct CustomPropertiesBuilder<'a> {
|
pub struct CustomPropertiesBuilder<'a> {
|
||||||
seen: PrecomputedHashSet<&'a Name>,
|
seen: PrecomputedHashSet<&'a Name>,
|
||||||
|
reverted: PerOrigin<PrecomputedHashSet<&'a Name>>,
|
||||||
may_have_cycles: bool,
|
may_have_cycles: bool,
|
||||||
custom_properties: Option<CustomPropertiesMap>,
|
custom_properties: Option<CustomPropertiesMap>,
|
||||||
inherited: Option<&'a Arc<CustomPropertiesMap>>,
|
inherited: Option<&'a Arc<CustomPropertiesMap>>,
|
||||||
|
@ -504,6 +506,7 @@ impl<'a> CustomPropertiesBuilder<'a> {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
seen: PrecomputedHashSet::default(),
|
seen: PrecomputedHashSet::default(),
|
||||||
|
reverted: Default::default(),
|
||||||
may_have_cycles: false,
|
may_have_cycles: false,
|
||||||
custom_properties: None,
|
custom_properties: None,
|
||||||
inherited,
|
inherited,
|
||||||
|
@ -512,13 +515,22 @@ impl<'a> CustomPropertiesBuilder<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cascade a given custom property declaration.
|
/// 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);
|
let was_already_present = !self.seen.insert(name);
|
||||||
if was_already_present {
|
if was_already_present {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.value_may_affect_style(name, specified_value) {
|
if !self.value_may_affect_style(name, value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,7 +542,7 @@ impl<'a> CustomPropertiesBuilder<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let map = self.custom_properties.as_mut().unwrap();
|
let map = self.custom_properties.as_mut().unwrap();
|
||||||
match *specified_value {
|
match *value {
|
||||||
CustomDeclarationValue::Value(ref unparsed_value) => {
|
CustomDeclarationValue::Value(ref unparsed_value) => {
|
||||||
let has_references = !unparsed_value.references.is_empty();
|
let has_references = !unparsed_value.references.is_empty();
|
||||||
self.may_have_cycles |= has_references;
|
self.may_have_cycles |= has_references;
|
||||||
|
@ -554,6 +566,12 @@ impl<'a> CustomPropertiesBuilder<'a> {
|
||||||
map.insert(name.clone(), value);
|
map.insert(name.clone(), value);
|
||||||
},
|
},
|
||||||
CustomDeclarationValue::CSSWideKeyword(keyword) => match keyword {
|
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 => {
|
CSSWideKeyword::Initial => {
|
||||||
map.remove(name);
|
map.remove(name);
|
||||||
},
|
},
|
||||||
|
@ -587,10 +605,10 @@ impl<'a> CustomPropertiesBuilder<'a> {
|
||||||
// not existing in the map.
|
// not existing in the map.
|
||||||
return false;
|
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
|
// Don't bother overwriting an existing inherited value with
|
||||||
// the same specified value.
|
// the same specified value.
|
||||||
if existing_value == specified_value {
|
if existing_value == value {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -27,6 +27,7 @@ use crate::values::generics::box_::VerticalAlign;
|
||||||
use crate::values::generics::grid::{TrackListValue, TrackSize};
|
use crate::values::generics::grid::{TrackListValue, TrackSize};
|
||||||
use crate::values::generics::image::{CompatMode, GradientItem, Image as GenericImage};
|
use crate::values::generics::image::{CompatMode, GradientItem, Image as GenericImage};
|
||||||
use crate::values::generics::rect::Rect;
|
use crate::values::generics::rect::Rect;
|
||||||
|
use crate::Zero;
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
use style_traits::values::specified::AllowedNumericType;
|
use style_traits::values::specified::AllowedNumericType;
|
||||||
|
@ -575,17 +576,15 @@ pub mod basic_shape {
|
||||||
//! Conversions from and to CSS shape representations.
|
//! Conversions from and to CSS shape representations.
|
||||||
|
|
||||||
use crate::gecko::values::GeckoStyleCoordConvertible;
|
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::{StyleBasicShape, StyleBasicShapeType};
|
||||||
use crate::gecko_bindings::structs::{
|
use crate::gecko_bindings::structs::{
|
||||||
StyleGeometryBox, StyleShapeSource, StyleShapeSourceType,
|
StyleGeometryBox, StyleShapeSource, StyleShapeSourceType,
|
||||||
};
|
};
|
||||||
use crate::gecko_bindings::sugar::ns_style_coord::{CoordDataMut, CoordDataValue};
|
|
||||||
use crate::gecko_bindings::sugar::refptr::RefPtr;
|
use crate::gecko_bindings::sugar::refptr::RefPtr;
|
||||||
use crate::values::computed::basic_shape::{
|
use crate::values::computed::basic_shape::{
|
||||||
BasicShape, ClippingShape, FloatAreaShape, ShapeRadius,
|
BasicShape, ClippingShape, FloatAreaShape, ShapeRadius,
|
||||||
};
|
};
|
||||||
use crate::values::computed::border::{BorderCornerRadius, BorderRadius};
|
|
||||||
use crate::values::computed::length::LengthPercentage;
|
use crate::values::computed::length::LengthPercentage;
|
||||||
use crate::values::computed::motion::OffsetPath;
|
use crate::values::computed::motion::OffsetPath;
|
||||||
use crate::values::computed::url::ComputedUrl;
|
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::{Circle, Ellipse, Path, PolygonCoord};
|
||||||
use crate::values::generics::basic_shape::{GeometryBox, ShapeBox, ShapeSource};
|
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::rect::Rect;
|
||||||
use crate::values::generics::NonNegative;
|
|
||||||
use crate::values::specified::SVGPathData;
|
use crate::values::specified::SVGPathData;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
|
|
||||||
|
@ -706,8 +703,7 @@ pub mod basic_shape {
|
||||||
let r = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[1]);
|
let r = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[1]);
|
||||||
let b = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[2]);
|
let b = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[2]);
|
||||||
let l = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[3]);
|
let l = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[3]);
|
||||||
let round: BorderRadius = (&other.mRadius).into();
|
let round = other.mRadius;
|
||||||
let round = if round.all_zero() { None } else { Some(round) };
|
|
||||||
let rect = Rect::new(
|
let rect = Rect::new(
|
||||||
t.expect("inset() offset should be a length, percentage, or calc value"),
|
t.expect("inset() offset should be a length, percentage, or calc value"),
|
||||||
r.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 {
|
impl<'a> From<&'a nsStyleCoord> for ShapeRadius {
|
||||||
fn from(other: &'a nsStyleCoord) -> Self {
|
fn from(other: &'a nsStyleCoord) -> Self {
|
||||||
let other = other.borrow();
|
let other = other.borrow();
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
use crate::context::QuirksMode;
|
use crate::context::QuirksMode;
|
||||||
use crate::dom::TElement;
|
use crate::dom::TElement;
|
||||||
use crate::gecko_bindings::bindings::{self, RawServoStyleSet};
|
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::structs::{StyleSheet as DomStyleSheet, StyleSheetInfo};
|
||||||
use crate::gecko_bindings::sugar::ownership::{HasArcFFI, HasBoxFFI, HasFFI, HasSimpleFFI};
|
use crate::gecko_bindings::sugar::ownership::{HasArcFFI, HasBoxFFI, HasFFI, HasSimpleFFI};
|
||||||
use crate::invalidation::media_queries::{MediaListKey, ToMediaListKey};
|
use crate::invalidation::media_queries::{MediaListKey, ToMediaListKey};
|
||||||
|
@ -142,15 +142,15 @@ pub struct PerDocumentStyleDataImpl {
|
||||||
pub struct PerDocumentStyleData(AtomicRefCell<PerDocumentStyleDataImpl>);
|
pub struct PerDocumentStyleData(AtomicRefCell<PerDocumentStyleDataImpl>);
|
||||||
|
|
||||||
impl PerDocumentStyleData {
|
impl PerDocumentStyleData {
|
||||||
/// Create a dummy `PerDocumentStyleData`.
|
/// Create a `PerDocumentStyleData`.
|
||||||
pub fn new(pres_context: RawGeckoPresContextBorrowed) -> Self {
|
pub fn new(document: *const structs::Document) -> Self {
|
||||||
let device = Device::new(pres_context);
|
let device = Device::new(document);
|
||||||
|
|
||||||
// FIXME(emilio, tlin): How is this supposed to work with XBL? This is
|
// FIXME(emilio, tlin): How is this supposed to work with XBL? This is
|
||||||
// right now not always honored, see bug 1405543...
|
// right now not always honored, see bug 1405543...
|
||||||
//
|
//
|
||||||
// Should we just force XBL Stylists to be NoQuirks?
|
// 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 {
|
PerDocumentStyleData(AtomicRefCell::new(PerDocumentStyleDataImpl {
|
||||||
stylist: Stylist::new(device, quirks_mode.into()),
|
stylist: Stylist::new(device, quirks_mode.into()),
|
||||||
|
@ -191,8 +191,7 @@ impl PerDocumentStyleDataImpl {
|
||||||
/// Returns whether visited styles are enabled.
|
/// Returns whether visited styles are enabled.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn visited_styles_enabled(&self) -> bool {
|
pub fn visited_styles_enabled(&self) -> bool {
|
||||||
let doc = self.stylist.device().pres_context().mDocument.mRawPtr;
|
unsafe { bindings::Gecko_VisitedStylesEnabled(self.stylist.device().document()) }
|
||||||
unsafe { bindings::Gecko_VisitedStylesEnabled(doc) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Measure heap usage.
|
/// Measure heap usage.
|
||||||
|
|
|
@ -17,12 +17,13 @@ use app_units::Au;
|
||||||
use euclid::Size2D;
|
use euclid::Size2D;
|
||||||
|
|
||||||
fn viewport_size(device: &Device) -> Size2D<Au> {
|
fn viewport_size(device: &Device) -> Size2D<Au> {
|
||||||
let pc = device.pres_context();
|
if let Some(pc) = device.pres_context() {
|
||||||
if pc.mIsRootPaginatedDocument() != 0 {
|
if pc.mIsRootPaginatedDocument() != 0 {
|
||||||
// We want the page size, including unprintable areas and margins.
|
// We want the page size, including unprintable areas and margins.
|
||||||
// FIXME(emilio, bug 1414600): Not quite!
|
// FIXME(emilio, bug 1414600): Not quite!
|
||||||
let area = &pc.mPageSize;
|
let area = &pc.mPageSize;
|
||||||
return Size2D::new(Au(area.width), Au(area.height));
|
return Size2D::new(Au(area.width), Au(area.height));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
device.au_viewport_size()
|
device.au_viewport_size()
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ use crate::custom_properties::CssEnvironment;
|
||||||
use crate::gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
|
use crate::gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
|
||||||
use crate::gecko_bindings::bindings;
|
use crate::gecko_bindings::bindings;
|
||||||
use crate::gecko_bindings::structs;
|
use crate::gecko_bindings::structs;
|
||||||
use crate::gecko_bindings::structs::{nsPresContext, RawGeckoPresContextBorrowed};
|
|
||||||
use crate::media_queries::MediaType;
|
use crate::media_queries::MediaType;
|
||||||
use crate::properties::ComputedValues;
|
use crate::properties::ComputedValues;
|
||||||
use crate::string_cache::Atom;
|
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,
|
/// The `Device` in Gecko wraps a pres context, has a default values computed,
|
||||||
/// and contains all the viewport rule state.
|
/// and contains all the viewport rule state.
|
||||||
pub struct Device {
|
pub struct Device {
|
||||||
/// NB: The pres context lifetime is tied to the styleset, who owns the
|
/// NB: The document owns the styleset, who owns the stylist, and thus the
|
||||||
/// stylist, and thus the `Device`, so having a raw pres context pointer
|
/// `Device`, so having a raw document pointer here is fine.
|
||||||
/// here is fine.
|
document: *const structs::Document,
|
||||||
pres_context: RawGeckoPresContextBorrowed,
|
|
||||||
default_values: Arc<ComputedValues>,
|
default_values: Arc<ComputedValues>,
|
||||||
/// The font size of the root element
|
/// The font size of the root element
|
||||||
/// This is set when computing the style of the root
|
/// This is set when computing the style of the root
|
||||||
|
@ -81,16 +79,16 @@ unsafe impl Send for Device {}
|
||||||
|
|
||||||
impl Device {
|
impl Device {
|
||||||
/// Trivially constructs a new `Device`.
|
/// Trivially constructs a new `Device`.
|
||||||
pub fn new(pres_context: RawGeckoPresContextBorrowed) -> Self {
|
pub fn new(document: *const structs::Document) -> Self {
|
||||||
assert!(!pres_context.is_null());
|
assert!(!document.is_null());
|
||||||
|
let doc = unsafe { &*document };
|
||||||
|
let prefs = unsafe { &*bindings::Gecko_GetPrefSheetPrefs(doc) };
|
||||||
Device {
|
Device {
|
||||||
pres_context,
|
document,
|
||||||
default_values: ComputedValues::default_values(unsafe {
|
default_values: ComputedValues::default_values(doc),
|
||||||
&*(*pres_context).mDocument.mRawPtr
|
|
||||||
}),
|
|
||||||
// FIXME(bz): Seems dubious?
|
// FIXME(bz): Seems dubious?
|
||||||
root_font_size: AtomicIsize::new(FontSize::medium().size().0 as isize),
|
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_root_font_size: AtomicBool::new(false),
|
||||||
used_viewport_size: AtomicBool::new(false),
|
used_viewport_size: AtomicBool::new(false),
|
||||||
environment: CssEnvironment,
|
environment: CssEnvironment,
|
||||||
|
@ -112,11 +110,13 @@ impl Device {
|
||||||
/// Whether any animation name may be referenced from the style of any
|
/// Whether any animation name may be referenced from the style of any
|
||||||
/// element.
|
/// element.
|
||||||
pub fn animation_name_may_be_referenced(&self, name: &KeyframesName) -> bool {
|
pub fn animation_name_may_be_referenced(&self, name: &KeyframesName) -> bool {
|
||||||
|
let pc = match self.pres_context() {
|
||||||
|
Some(pc) => pc,
|
||||||
|
None => return false,
|
||||||
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
bindings::Gecko_AnimationNameMayBeReferencedFromStyle(
|
bindings::Gecko_AnimationNameMayBeReferencedFromStyle(pc, name.as_atom().as_ptr())
|
||||||
self.pres_context(),
|
|
||||||
name.as_atom().as_ptr(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,16 +156,29 @@ impl Device {
|
||||||
convert_nscolor_to_rgba(self.body_text_color.load(Ordering::Relaxed) as u32)
|
convert_nscolor_to_rgba(self.body_text_color.load(Ordering::Relaxed) as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the pres context associated with this document.
|
|
||||||
#[inline]
|
|
||||||
pub fn pres_context(&self) -> &nsPresContext {
|
|
||||||
unsafe { &*self.pres_context }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the document pointer.
|
/// Gets the document pointer.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn document(&self) -> &structs::Document {
|
pub fn document(&self) -> &structs::Document {
|
||||||
unsafe { &*self.pres_context().mDocument.mRawPtr }
|
unsafe { &*self.document }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the pres context associated with this document.
|
||||||
|
#[inline]
|
||||||
|
pub fn pres_context(&self) -> Option<&structs::nsPresContext> {
|
||||||
|
unsafe {
|
||||||
|
self.document()
|
||||||
|
.mPresShell
|
||||||
|
.as_ref()?
|
||||||
|
.mPresContext
|
||||||
|
.mRawPtr
|
||||||
|
.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the preference stylesheet prefs for our document.
|
||||||
|
#[inline]
|
||||||
|
pub fn pref_sheet_prefs(&self) -> &structs::PreferenceSheet_Prefs {
|
||||||
|
unsafe { &*bindings::Gecko_GetPrefSheetPrefs(self.document()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recreates the default computed values.
|
/// Recreates the default computed values.
|
||||||
|
@ -195,13 +208,17 @@ impl Device {
|
||||||
|
|
||||||
/// Returns the current media type of the device.
|
/// Returns the current media type of the device.
|
||||||
pub fn media_type(&self) -> MediaType {
|
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
|
// Gecko allows emulating random media with mIsEmulatingMedia and
|
||||||
// mMediaEmulated.
|
// mMediaEmulated.
|
||||||
let context = self.pres_context();
|
let medium_to_use = if pc.mIsEmulatingMedia() != 0 {
|
||||||
let medium_to_use = if context.mIsEmulatingMedia() != 0 {
|
pc.mMediaEmulated.mRawPtr
|
||||||
context.mMediaEmulated.mRawPtr
|
|
||||||
} else {
|
} else {
|
||||||
context.mMedium
|
pc.mMedium
|
||||||
};
|
};
|
||||||
|
|
||||||
MediaType(CustomIdent(unsafe { Atom::from_raw(medium_to_use) }))
|
MediaType(CustomIdent(unsafe { Atom::from_raw(medium_to_use) }))
|
||||||
|
@ -209,7 +226,11 @@ impl Device {
|
||||||
|
|
||||||
/// Returns the current viewport size in app units.
|
/// Returns the current viewport size in app units.
|
||||||
pub fn au_viewport_size(&self) -> Size2D<Au> {
|
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))
|
Size2D::new(Au(area.width), Au(area.height))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,34 +248,62 @@ impl Device {
|
||||||
|
|
||||||
/// Returns the device pixel ratio.
|
/// Returns the device pixel ratio.
|
||||||
pub fn device_pixel_ratio(&self) -> TypedScale<f32, CSSPixel, DevicePixel> {
|
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 {
|
if override_dppx > 0.0 {
|
||||||
return TypedScale::new(override_dppx);
|
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;
|
let au_per_px = AU_PER_PX as f32;
|
||||||
TypedScale::new(au_per_px / au_per_dpx)
|
TypedScale::new(au_per_px / au_per_dpx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether document colors are enabled.
|
/// Returns whether document colors are enabled.
|
||||||
|
#[inline]
|
||||||
pub fn use_document_colors(&self) -> bool {
|
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.
|
/// Returns the default background color.
|
||||||
pub fn default_background_color(&self) -> RGBA {
|
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).
|
/// Applies text zoom to a font-size or line-height value (see nsStyleFont::ZoomText).
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn zoom_text(&self, size: Au) -> Au {
|
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.
|
/// Un-apply text zoom.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn unzoom_text(&self, size: Au) -> Au {
|
pub fn unzoom_text(&self, size: Au) -> Au {
|
||||||
size.scale_by(1. / self.pres_context().mEffectiveTextZoom)
|
size.scale_by(1. / self.effective_text_zoom())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ use crate::values::generics::grid::{TrackBreadth, TrackKeyword};
|
||||||
use crate::values::generics::length::LengthPercentageOrAuto;
|
use crate::values::generics::length::LengthPercentageOrAuto;
|
||||||
use crate::values::generics::{CounterStyleOrNone, NonNegative};
|
use crate::values::generics::{CounterStyleOrNone, NonNegative};
|
||||||
use crate::values::{Auto, Either, None_, Normal};
|
use crate::values::{Auto, Either, None_, Normal};
|
||||||
use crate::Atom;
|
use crate::{Atom, Zero};
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use cssparser::RGBA;
|
use cssparser::RGBA;
|
||||||
use nsstring::{nsACString, nsCStr};
|
use nsstring::{nsACString, nsCStr};
|
||||||
|
|
|
@ -1044,9 +1044,13 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
|
||||||
device: &Device,
|
device: &Device,
|
||||||
) -> FontMetricsQueryResult {
|
) -> FontMetricsQueryResult {
|
||||||
use crate::gecko_bindings::bindings::Gecko_GetFontMetrics;
|
use crate::gecko_bindings::bindings::Gecko_GetFontMetrics;
|
||||||
|
let pc = match device.pres_context() {
|
||||||
|
Some(pc) => pc,
|
||||||
|
None => return FontMetricsQueryResult::NotAvailable,
|
||||||
|
};
|
||||||
let gecko_metrics = unsafe {
|
let gecko_metrics = unsafe {
|
||||||
Gecko_GetFontMetrics(
|
Gecko_GetFontMetrics(
|
||||||
device.pres_context(),
|
pc,
|
||||||
wm.is_vertical() && !wm.is_sideways(),
|
wm.is_vertical() && !wm.is_sideways(),
|
||||||
font.gecko(),
|
font.gecko(),
|
||||||
font_size.0,
|
font_size.0,
|
||||||
|
@ -1242,8 +1246,7 @@ impl<'le> TElement for GeckoElement<'le> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn owner_doc_matches_for_testing(&self, device: &Device) -> bool {
|
fn owner_doc_matches_for_testing(&self, device: &Device) -> bool {
|
||||||
self.as_node().owner_doc().0 as *const structs::Document ==
|
self.as_node().owner_doc().0 as *const structs::Document == device.document() as *const _
|
||||||
device.pres_context().mDocument.mRawPtr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style_attribute(&self) -> Option<ArcBorrow<Locked<PropertyDeclarationBlock>>> {
|
fn style_attribute(&self) -> Option<ArcBorrow<Locked<PropertyDeclarationBlock>>> {
|
||||||
|
|
|
@ -10,6 +10,7 @@ use crate::gecko_bindings::structs::{nsCSSUnit, nsCSSValue};
|
||||||
use crate::gecko_bindings::structs::{nsCSSValueList, nsCSSValue_Array};
|
use crate::gecko_bindings::structs::{nsCSSValueList, nsCSSValue_Array};
|
||||||
use crate::gecko_string_cache::Atom;
|
use crate::gecko_string_cache::Atom;
|
||||||
use crate::values::computed::{Angle, Length, LengthPercentage, Percentage};
|
use crate::values::computed::{Angle, Length, LengthPercentage, Percentage};
|
||||||
|
use crate::Zero;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
//! Rust helpers for Gecko's `nsStyleCoord`.
|
//! Rust helpers for Gecko's `nsStyleCoord`.
|
||||||
|
|
||||||
use crate::gecko_bindings::bindings;
|
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::{nsStyleCoord, nsStyleCoord_Calc, nsStyleCoord_CalcValue};
|
||||||
use crate::gecko_bindings::structs::{nsStyleCorners, nsStyleSides};
|
|
||||||
use crate::gecko_bindings::structs::{nsStyleUnion, nsStyleUnit, nscoord};
|
use crate::gecko_bindings::structs::{nsStyleUnion, nsStyleUnit, nscoord};
|
||||||
use std::mem;
|
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.
|
/// Enum representing the tagged union that is CoordData.
|
||||||
///
|
///
|
||||||
/// In release mode this should never actually exist in the code, and will be
|
/// In release mode this should never actually exist in the code, and will be
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -21,9 +21,8 @@ use crate::stylesheets::Origin;
|
||||||
use crate::values::computed::{self, ToComputedValue};
|
use crate::values::computed::{self, ToComputedValue};
|
||||||
use crate::values::specified::{Integer, Length, Number, Resolution};
|
use crate::values::specified::{Integer, Length, Number, Resolution};
|
||||||
use crate::values::{serialize_atom_identifier, CSSFloat};
|
use crate::values::{serialize_atom_identifier, CSSFloat};
|
||||||
use crate::Atom;
|
use crate::{Atom, Zero};
|
||||||
use cssparser::{Parser, Token};
|
use cssparser::{Parser, Token};
|
||||||
use num_traits::Zero;
|
|
||||||
use std::cmp::{Ordering, PartialOrd};
|
use std::cmp::{Ordering, PartialOrd};
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
||||||
|
|
|
@ -11,12 +11,13 @@ use crate::font_metrics::FontMetricsProvider;
|
||||||
use crate::logical_geometry::WritingMode;
|
use crate::logical_geometry::WritingMode;
|
||||||
use crate::media_queries::Device;
|
use crate::media_queries::Device;
|
||||||
use crate::properties::{ComputedValues, StyleBuilder};
|
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::{PropertyDeclaration, PropertyDeclarationId, DeclarationImportanceIterator};
|
||||||
use crate::properties::CASCADE_PROPERTY;
|
use crate::properties::CASCADE_PROPERTY;
|
||||||
use crate::rule_cache::{RuleCache, RuleCacheConditions};
|
use crate::rule_cache::{RuleCache, RuleCacheConditions};
|
||||||
use crate::rule_tree::{CascadeLevel, StrongRuleNode};
|
use crate::rule_tree::{CascadeLevel, StrongRuleNode};
|
||||||
use crate::selector_parser::PseudoElement;
|
use crate::selector_parser::PseudoElement;
|
||||||
|
use crate::stylesheets::{Origin, PerOrigin};
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use crate::shared_lock::StylesheetGuards;
|
use crate::shared_lock::StylesheetGuards;
|
||||||
use smallbitvec::SmallBitVec;
|
use smallbitvec::SmallBitVec;
|
||||||
|
@ -251,7 +252,7 @@ where
|
||||||
for (declaration, cascade_level) in iter_declarations() {
|
for (declaration, cascade_level) in iter_declarations() {
|
||||||
declarations.push((declaration, cascade_level));
|
declarations.push((declaration, cascade_level));
|
||||||
if let PropertyDeclaration::Custom(ref declaration) = *declaration {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_ua_or_user_rule = matches!(
|
let is_ua_or_user_rule =
|
||||||
cascade_level,
|
matches!(cascade_level.origin(), Origin::User | Origin::UserAgent);
|
||||||
CascadeLevel::UANormal |
|
|
||||||
CascadeLevel::UserNormal |
|
|
||||||
CascadeLevel::UserImportant |
|
|
||||||
CascadeLevel::UAImportant
|
|
||||||
);
|
|
||||||
|
|
||||||
if is_ua_or_user_rule {
|
if is_ua_or_user_rule {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -388,6 +383,7 @@ struct Cascade<'a, 'b: 'a> {
|
||||||
context: &'a mut computed::Context<'b>,
|
context: &'a mut computed::Context<'b>,
|
||||||
cascade_mode: CascadeMode<'a>,
|
cascade_mode: CascadeMode<'a>,
|
||||||
seen: LonghandIdSet,
|
seen: LonghandIdSet,
|
||||||
|
reverted: PerOrigin<LonghandIdSet>,
|
||||||
saved_font_size: Option<PropertyDeclaration>,
|
saved_font_size: Option<PropertyDeclaration>,
|
||||||
saved_font_family: Option<PropertyDeclaration>,
|
saved_font_family: Option<PropertyDeclaration>,
|
||||||
}
|
}
|
||||||
|
@ -398,6 +394,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
||||||
context,
|
context,
|
||||||
cascade_mode,
|
cascade_mode,
|
||||||
seen: LonghandIdSet::default(),
|
seen: LonghandIdSet::default(),
|
||||||
|
reverted: Default::default(),
|
||||||
saved_font_size: None,
|
saved_font_size: None,
|
||||||
saved_font_family: None,
|
saved_font_family: None,
|
||||||
}
|
}
|
||||||
|
@ -488,6 +485,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
||||||
|
|
||||||
for (declaration, cascade_level) in declarations {
|
for (declaration, cascade_level) in declarations {
|
||||||
let declaration_id = declaration.id();
|
let declaration_id = declaration.id();
|
||||||
|
let origin = cascade_level.origin();
|
||||||
let longhand_id = match declaration_id {
|
let longhand_id = match declaration_id {
|
||||||
PropertyDeclarationId::Longhand(id) => id,
|
PropertyDeclarationId::Longhand(id) => id,
|
||||||
PropertyDeclarationId::Custom(..) => continue,
|
PropertyDeclarationId::Custom(..) => continue,
|
||||||
|
@ -513,6 +511,10 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
||||||
continue;
|
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
|
// Only a few properties are allowed to depend on the visited state
|
||||||
// of links. When cascading visited styles, we can save time by
|
// of links. When cascading visited styles, we can save time by
|
||||||
// only processing these properties.
|
// 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);
|
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
|
// FIXME(emilio): We should avoid generating code for logical
|
||||||
// longhands and just use the physical ones, then rename
|
// longhands and just use the physical ones, then rename
|
||||||
// physical_longhand_id to just longhand_id.
|
// 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::MozMinFontSizeRatio) ||
|
||||||
self.seen.contains(LonghandId::FontFamily)
|
self.seen.contains(LonghandId::FontFamily)
|
||||||
{
|
{
|
||||||
use crate::properties::{CSSWideKeyword, WideKeywordDeclaration};
|
use crate::values::computed::FontSize;
|
||||||
|
|
||||||
// font-size must be explicitly inherited to handle lang
|
// font-size must be explicitly inherited to handle lang
|
||||||
// changes and scriptlevel changes.
|
// changes and scriptlevel changes.
|
||||||
//
|
//
|
||||||
// FIXME(emilio): That looks a bit bogus...
|
// FIXME(emilio): That looks a bit bogus...
|
||||||
let inherit = PropertyDeclaration::CSSWideKeyword(WideKeywordDeclaration {
|
self.context.for_non_inherited_property = None;
|
||||||
id: LonghandId::FontSize,
|
FontSize::cascade_inherit_font_size(&mut self.context);
|
||||||
keyword: CSSWideKeyword::Inherit,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.apply_declaration_ignoring_phase(LonghandId::FontSize, &inherit);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -347,6 +347,7 @@ class Longhand(object):
|
||||||
"TouchAction",
|
"TouchAction",
|
||||||
"TransformStyle",
|
"TransformStyle",
|
||||||
"UserSelect",
|
"UserSelect",
|
||||||
|
"WordBreak",
|
||||||
"XSpan",
|
"XSpan",
|
||||||
"XTextZoom",
|
"XTextZoom",
|
||||||
"ZIndex",
|
"ZIndex",
|
||||||
|
|
|
@ -849,7 +849,7 @@ impl PropertyDeclarationBlock {
|
||||||
|
|
||||||
for declaration in self.normal_declaration_iter() {
|
for declaration in self.normal_declaration_iter() {
|
||||||
if let PropertyDeclaration::Custom(ref declaration) = *declaration {
|
if let PropertyDeclaration::Custom(ref declaration) = *declaration {
|
||||||
builder.cascade(&declaration.name, &declaration.value);
|
builder.cascade(declaration, Origin::Author);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ use crate::rule_tree::StrongRuleNode;
|
||||||
use crate::selector_parser::PseudoElement;
|
use crate::selector_parser::PseudoElement;
|
||||||
use servo_arc::{Arc, RawOffsetArc};
|
use servo_arc::{Arc, RawOffsetArc};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem::{forget, uninitialized, transmute, zeroed};
|
use std::mem::{forget, uninitialized, zeroed};
|
||||||
use std::{cmp, ops, ptr};
|
use std::{cmp, ops, ptr};
|
||||||
use crate::values::{self, CustomIdent, Either, KeyframesName, None_};
|
use crate::values::{self, CustomIdent, Either, KeyframesName, None_};
|
||||||
use crate::values::computed::{NonNegativeLength, Percentage, TransitionProperty};
|
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.
|
// 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) {
|
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;
|
use crate::gecko_bindings::structs::nsStyleSVG_${ident.upper()}_CONTEXT as CONTEXT_VALUE;
|
||||||
let length = match v {
|
let length = match v {
|
||||||
SVGLength::Length(length) => {
|
SVGLength::LengthPercentage(length) => {
|
||||||
self.gecko.mContextFlags &= !CONTEXT_VALUE;
|
self.gecko.mContextFlags &= !CONTEXT_VALUE;
|
||||||
length
|
length
|
||||||
}
|
}
|
||||||
SVGLength::ContextValue => {
|
SVGLength::ContextValue => {
|
||||||
self.gecko.mContextFlags |= CONTEXT_VALUE;
|
self.gecko.mContextFlags |= CONTEXT_VALUE;
|
||||||
match longhands::${ident}::get_initial_value() {
|
match longhands::${ident}::get_initial_value() {
|
||||||
SVGLength::Length(length) => length,
|
SVGLength::LengthPercentage(length) => length,
|
||||||
_ => unreachable!("Initial value should not be context-value"),
|
_ => unreachable!("Initial value should not be context-value"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match length {
|
self.gecko.${gecko_ffi_name} = 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())),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
||||||
use crate::gecko_bindings::structs::nsStyleSVG_${ident.upper()}_CONTEXT as CONTEXT_VALUE;
|
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 =
|
||||||
(self.gecko.mContextFlags & !CONTEXT_VALUE) |
|
(self.gecko.mContextFlags & !CONTEXT_VALUE) |
|
||||||
(other.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 {
|
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
|
||||||
use crate::values::generics::svg::{SVGLength, SvgLengthPercentageOrNumber};
|
use crate::values::generics::svg::SVGLength;
|
||||||
use crate::values::computed::LengthPercentage;
|
|
||||||
use crate::gecko_bindings::structs::nsStyleSVG_${ident.upper()}_CONTEXT as CONTEXT_VALUE;
|
use crate::gecko_bindings::structs::nsStyleSVG_${ident.upper()}_CONTEXT as CONTEXT_VALUE;
|
||||||
if (self.gecko.mContextFlags & CONTEXT_VALUE) != 0 {
|
if (self.gecko.mContextFlags & CONTEXT_VALUE) != 0 {
|
||||||
return SVGLength::ContextValue;
|
return SVGLength::ContextValue;
|
||||||
}
|
}
|
||||||
let length = match self.gecko.${gecko_ffi_name}.as_value() {
|
SVGLength::LengthPercentage(self.gecko.${gecko_ffi_name})
|
||||||
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())
|
|
||||||
}
|
}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
@ -817,34 +792,23 @@ def set_gecko_property(ffi_name, expr):
|
||||||
}
|
}
|
||||||
</%def>
|
</%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)]
|
#[allow(non_snake_case)]
|
||||||
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
|
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}));
|
self.gecko.${gecko_ffi_name}.${corner} = v;
|
||||||
v.0.height().to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${y_index}));
|
|
||||||
}
|
}
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
||||||
self.gecko.${gecko_ffi_name}.data_at_mut(${x_index})
|
self.gecko.${gecko_ffi_name}.${corner} =
|
||||||
.copy_from(&other.gecko.${gecko_ffi_name}.data_at(${x_index}));
|
other.gecko.${gecko_ffi_name}.${corner};
|
||||||
self.gecko.${gecko_ffi_name}.data_at_mut(${y_index})
|
|
||||||
.copy_from(&other.gecko.${gecko_ffi_name}.data_at(${y_index}));
|
|
||||||
}
|
}
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn reset_${ident}(&mut self, other: &Self) {
|
pub fn reset_${ident}(&mut self, other: &Self) {
|
||||||
self.copy_${ident}_from(other)
|
self.copy_${ident}_from(other)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
|
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
|
||||||
use crate::values::computed::border::BorderCornerRadius;
|
self.gecko.${gecko_ffi_name}.${corner}
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
@ -891,13 +855,13 @@ def set_gecko_property(ffi_name, expr):
|
||||||
transform_functions = [
|
transform_functions = [
|
||||||
("Matrix3D", "matrix3d", ["number"] * 16),
|
("Matrix3D", "matrix3d", ["number"] * 16),
|
||||||
("Matrix", "matrix", ["number"] * 6),
|
("Matrix", "matrix", ["number"] * 6),
|
||||||
("Translate", "translate", ["lp", "optional_lp"]),
|
("Translate", "translate", ["lp", "lp"]),
|
||||||
("Translate3D", "translate3d", ["lp", "lp", "length"]),
|
("Translate3D", "translate3d", ["lp", "lp", "length"]),
|
||||||
("TranslateX", "translatex", ["lp"]),
|
("TranslateX", "translatex", ["lp"]),
|
||||||
("TranslateY", "translatey", ["lp"]),
|
("TranslateY", "translatey", ["lp"]),
|
||||||
("TranslateZ", "translatez", ["length"]),
|
("TranslateZ", "translatez", ["length"]),
|
||||||
("Scale3D", "scale3d", ["number"] * 3),
|
("Scale3D", "scale3d", ["number"] * 3),
|
||||||
("Scale", "scale", ["number", "optional_number"]),
|
("Scale", "scale", ["number", "number"]),
|
||||||
("ScaleX", "scalex", ["number"]),
|
("ScaleX", "scalex", ["number"]),
|
||||||
("ScaleY", "scaley", ["number"]),
|
("ScaleY", "scaley", ["number"]),
|
||||||
("ScaleZ", "scalez", ["number"]),
|
("ScaleZ", "scalez", ["number"]),
|
||||||
|
@ -906,7 +870,7 @@ transform_functions = [
|
||||||
("RotateX", "rotatex", ["angle"]),
|
("RotateX", "rotatex", ["angle"]),
|
||||||
("RotateY", "rotatey", ["angle"]),
|
("RotateY", "rotatey", ["angle"]),
|
||||||
("RotateZ", "rotatez", ["angle"]),
|
("RotateZ", "rotatez", ["angle"]),
|
||||||
("Skew", "skew", ["angle", "optional_angle"]),
|
("Skew", "skew", ["angle", "angle"]),
|
||||||
("SkewX", "skewx", ["angle"]),
|
("SkewX", "skewx", ["angle"]),
|
||||||
("SkewY", "skewy", ["angle"]),
|
("SkewY", "skewy", ["angle"]),
|
||||||
("Perspective", "perspective", ["length"]),
|
("Perspective", "perspective", ["length"]),
|
||||||
|
@ -917,7 +881,6 @@ transform_functions = [
|
||||||
|
|
||||||
<%def name="transform_function_arm(name, keyword, items)">
|
<%def name="transform_function_arm(name, keyword, items)">
|
||||||
<%
|
<%
|
||||||
has_optional = items[-1].startswith("optional_")
|
|
||||||
pattern = None
|
pattern = None
|
||||||
if keyword == "matrix3d":
|
if keyword == "matrix3d":
|
||||||
# m11: number1, m12: number2, ..
|
# m11: number1, m12: number2, ..
|
||||||
|
@ -955,36 +918,20 @@ transform_functions = [
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
crate::values::generics::transform::TransformOperation::${name}${pattern} => {
|
crate::values::generics::transform::TransformOperation::${name}${pattern} => {
|
||||||
% if has_optional:
|
let len = ${len(items) + 1};
|
||||||
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
|
|
||||||
bindings::Gecko_CSSValue_SetFunction(gecko_value, len);
|
bindings::Gecko_CSSValue_SetFunction(gecko_value, len);
|
||||||
bindings::Gecko_CSSValue_SetKeyword(
|
bindings::Gecko_CSSValue_SetKeyword(
|
||||||
bindings::Gecko_CSSValue_GetArrayItem(gecko_value, 0),
|
bindings::Gecko_CSSValue_GetArrayItem(gecko_value, 0),
|
||||||
structs::nsCSSKeyword::eCSSKeyword_${keyword}
|
structs::nsCSSKeyword::eCSSKeyword_${keyword}
|
||||||
);
|
);
|
||||||
% for index, item in enumerate(items):
|
% 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":
|
% if item == "list":
|
||||||
debug_assert!(!${item}${index + 1}.0.is_empty());
|
debug_assert!(!${item}${index + 1}.0.is_empty());
|
||||||
% endif
|
% endif
|
||||||
${css_value_setters[replaced_item] % (
|
${css_value_setters[item] % (
|
||||||
"bindings::Gecko_CSSValue_GetArrayItem(gecko_value, %d)" % (index + 1),
|
"bindings::Gecko_CSSValue_GetArrayItem(gecko_value, %d)" % (index + 1),
|
||||||
replaced_item + str(index + 1)
|
item + str(index + 1)
|
||||||
)};
|
)};
|
||||||
% if item.startswith("optional"):
|
|
||||||
}
|
|
||||||
% endif
|
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
</%def>
|
</%def>
|
||||||
|
@ -995,8 +942,6 @@ transform_functions = [
|
||||||
css_value_getters = {
|
css_value_getters = {
|
||||||
"length" : "Length::new(bindings::Gecko_CSSValue_GetNumber(%s))",
|
"length" : "Length::new(bindings::Gecko_CSSValue_GetNumber(%s))",
|
||||||
"lp" : "%s.get_length_percentage()",
|
"lp" : "%s.get_length_percentage()",
|
||||||
"lpon" : "Either::Second(%s.get_length_percentage())",
|
|
||||||
"lon" : "Either::First(%s.get_length())",
|
|
||||||
"angle" : "%s.get_angle()",
|
"angle" : "%s.get_angle()",
|
||||||
"number" : "bindings::Gecko_CSSValue_GetNumber(%s)",
|
"number" : "bindings::Gecko_CSSValue_GetNumber(%s)",
|
||||||
"percentage" : "Percentage(bindings::Gecko_CSSValue_GetPercentage(%s))",
|
"percentage" : "Percentage(bindings::Gecko_CSSValue_GetPercentage(%s))",
|
||||||
|
@ -1034,20 +979,11 @@ transform_functions = [
|
||||||
${field_names[index]}:
|
${field_names[index]}:
|
||||||
% endif
|
% endif
|
||||||
<%
|
<%
|
||||||
getter = css_value_getters[item.replace("optional_", "")] % (
|
getter = css_value_getters[item] % (
|
||||||
"bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, %d)" % (index + 1)
|
"bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, %d)" % (index + 1)
|
||||||
)
|
)
|
||||||
%>
|
%>
|
||||||
% if item.startswith("optional_"):
|
${getter},
|
||||||
if (**gecko_value.mValue.mArray.as_ref()).mCount == ${index + 1} {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(${getter})
|
|
||||||
}
|
|
||||||
% else:
|
|
||||||
${getter}
|
|
||||||
% endif
|
|
||||||
,
|
|
||||||
% endfor
|
% endfor
|
||||||
${post_symbols}
|
${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.
|
# Types used with predefined_type()-defined properties that we can auto-generate.
|
||||||
predefined_types = {
|
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,
|
"Color": impl_color,
|
||||||
"ColorOrAuto": impl_color,
|
"ColorOrAuto": impl_color,
|
||||||
"GreaterThanOrEqualToOneNumber": impl_simple,
|
|
||||||
"Integer": impl_simple,
|
|
||||||
"length::LengthOrAuto": impl_style_coord,
|
"length::LengthOrAuto": impl_style_coord,
|
||||||
"length::LengthOrNormal": impl_style_coord,
|
"length::LengthOrNormal": impl_style_coord,
|
||||||
"length::NonNegativeLengthOrAuto": impl_style_coord,
|
"length::NonNegativeLengthOrAuto": impl_style_coord,
|
||||||
"length::NonNegativeLengthPercentageOrNormal": impl_style_coord,
|
"length::NonNegativeLengthPercentageOrNormal": impl_style_coord,
|
||||||
"FillRule": impl_simple,
|
|
||||||
"FlexBasis": impl_simple,
|
|
||||||
"Length": impl_absolute_length,
|
"Length": impl_absolute_length,
|
||||||
"LengthOrNormal": impl_style_coord,
|
"LengthOrNormal": impl_style_coord,
|
||||||
"LengthPercentage": impl_simple,
|
|
||||||
"LengthPercentageOrAuto": impl_style_coord,
|
"LengthPercentageOrAuto": impl_style_coord,
|
||||||
"MaxSize": impl_simple,
|
|
||||||
"Size": impl_simple,
|
|
||||||
"MozScriptMinSize": impl_absolute_length,
|
"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,
|
"RGBAColor": impl_rgba_color,
|
||||||
"SVGLength": impl_svg_length,
|
"SVGLength": impl_svg_length,
|
||||||
"SVGOpacity": impl_svg_opacity,
|
"SVGOpacity": impl_svg_opacity,
|
||||||
"SVGPaint": impl_svg_paint,
|
"SVGPaint": impl_svg_paint,
|
||||||
"SVGWidth": impl_svg_length,
|
"SVGWidth": impl_svg_length,
|
||||||
"Transform": impl_transform,
|
"Transform": impl_transform,
|
||||||
"TransformOrigin": impl_simple,
|
|
||||||
"UserSelect": impl_simple,
|
|
||||||
"url::UrlOrNone": impl_css_url,
|
"url::UrlOrNone": impl_css_url,
|
||||||
"ZIndex": impl_simple,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def longhand_method(longhand):
|
def longhand_method(longhand):
|
||||||
|
@ -1354,15 +1258,12 @@ impl Clone for ${style_struct.gecko_struct_name} {
|
||||||
args.update(keyword=longhand.keyword)
|
args.update(keyword=longhand.keyword)
|
||||||
if "font" in longhand.ident:
|
if "font" in longhand.ident:
|
||||||
args.update(cast_type=longhand.cast_type)
|
args.update(cast_type=longhand.cast_type)
|
||||||
else:
|
elif longhand.predefined_type in predefined_types:
|
||||||
method = predefined_types[longhand.predefined_type]
|
method = predefined_types[longhand.predefined_type]
|
||||||
|
else:
|
||||||
|
method = impl_simple
|
||||||
|
|
||||||
method(**args)
|
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} {
|
impl ${style_struct.gecko_struct_name} {
|
||||||
/*
|
/*
|
||||||
|
@ -1374,7 +1275,7 @@ impl ${style_struct.gecko_struct_name} {
|
||||||
* Auto-Generated Methods.
|
* Auto-Generated Methods.
|
||||||
*/
|
*/
|
||||||
<%
|
<%
|
||||||
for longhand in picked_longhands:
|
for longhand in longhands:
|
||||||
longhand_method(longhand)
|
longhand_method(longhand)
|
||||||
%>
|
%>
|
||||||
}
|
}
|
||||||
|
@ -1387,14 +1288,6 @@ class Side(object):
|
||||||
self.ident = name.lower()
|
self.ident = name.lower()
|
||||||
self.index = index
|
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):
|
class GridLine(object):
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.ident = "grid-" + name.lower()
|
self.ident = "grid-" + name.lower()
|
||||||
|
@ -1402,19 +1295,12 @@ class GridLine(object):
|
||||||
self.gecko = "m" + to_camel_case(self.ident)
|
self.gecko = "m" + to_camel_case(self.ident)
|
||||||
|
|
||||||
SIDES = [Side("Top", 0), Side("Right", 1), Side("Bottom", 2), Side("Left", 3)]
|
SIDES = [Side("Top", 0), Side("Right", 1), Side("Bottom", 2), Side("Left", 3)]
|
||||||
CORNERS = [Corner("Top", "Left", 0), Corner("Top", "Right", 1),
|
CORNERS = ["top_left", "top_right", "bottom_right", "bottom_left"]
|
||||||
Corner("Bottom", "Right", 2), Corner("Bottom", "Left", 3)]
|
|
||||||
GRID_LINES = map(GridLine, ["row-start", "row-end", "column-start", "column-end"])
|
GRID_LINES = map(GridLine, ["row-start", "row-end", "column-start", "column-end"])
|
||||||
%>
|
%>
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn static_assert() {
|
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.
|
// Note: using the above technique with an enum hits a rust bug when |structs| is in a different crate.
|
||||||
% for side in SIDES:
|
% for side in SIDES:
|
||||||
{ const DETAIL: u32 = [0][(structs::Side::eSide${side.name} as usize != ${side.index}) as usize]; let _ = DETAIL; }
|
{ 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)
|
<% skip_border_longhands = " ".join(["border-{0}-{1}".format(x.ident, y)
|
||||||
for x in SIDES
|
for x in SIDES
|
||||||
for y in ["color", "style", "width"]] +
|
for y in ["color", "style", "width"]] +
|
||||||
["border-{0}-radius".format(x.ident.replace("_", "-"))
|
["border-{0}-radius".format(x.replace("_", "-"))
|
||||||
for x in CORNERS]) %>
|
for x in CORNERS]) %>
|
||||||
|
|
||||||
<%self:impl_trait style_struct_name="Border"
|
<%self:impl_trait style_struct_name="Border"
|
||||||
|
@ -1494,10 +1380,9 @@ fn static_assert() {
|
||||||
% endfor
|
% endfor
|
||||||
|
|
||||||
% for corner in CORNERS:
|
% for corner in CORNERS:
|
||||||
<% impl_corner_style_coord("border_%s_radius" % corner.ident,
|
<% impl_corner_style_coord("border_%s_radius" % corner,
|
||||||
"mBorderRadius",
|
"mBorderRadius",
|
||||||
corner.x_index,
|
corner) %>
|
||||||
corner.y_index) %>
|
|
||||||
% endfor
|
% endfor
|
||||||
|
|
||||||
pub fn set_border_image_source(&mut self, image: longhands::border_image_source::computed_value::T) {
|
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>
|
</%self:impl_trait>
|
||||||
|
|
||||||
<% skip_outline_longhands = " ".join("outline-style outline-width".split() +
|
<% 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]) %>
|
for x in CORNERS]) %>
|
||||||
<%self:impl_trait style_struct_name="Outline"
|
<%self:impl_trait style_struct_name="Outline"
|
||||||
skip_longhands="${skip_outline_longhands}">
|
skip_longhands="${skip_outline_longhands}">
|
||||||
|
@ -2059,10 +1944,9 @@ fn static_assert() {
|
||||||
round_to_pixels=True) %>
|
round_to_pixels=True) %>
|
||||||
|
|
||||||
% for corner in CORNERS:
|
% 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",
|
"mOutlineRadius",
|
||||||
corner.x_index,
|
corner) %>
|
||||||
corner.y_index) %>
|
|
||||||
% endfor
|
% endfor
|
||||||
|
|
||||||
pub fn outline_has_nonzero_width(&self) -> bool {
|
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
|
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-synthesis -x-lang font-variant-alternates
|
||||||
font-variant-east-asian font-variant-ligatures
|
font-variant-east-asian font-variant-ligatures
|
||||||
font-variant-numeric font-language-override
|
font-variant-numeric font-language-override
|
||||||
|
@ -2863,6 +2748,7 @@ fn static_assert() {
|
||||||
animation-iteration-count animation-timing-function
|
animation-iteration-count animation-timing-function
|
||||||
clear transition-duration transition-delay
|
clear transition-duration transition-delay
|
||||||
transition-timing-function transition-property
|
transition-timing-function transition-property
|
||||||
|
transform-style
|
||||||
rotate scroll-snap-points-x scroll-snap-points-y
|
rotate scroll-snap-points-x scroll-snap-points-y
|
||||||
scroll-snap-coordinate -moz-binding will-change
|
scroll-snap-coordinate -moz-binding will-change
|
||||||
offset-path shape-outside contain touch-action
|
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_CONTENT;
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_SIZE;
|
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_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_PAINT;
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_ALL_BITS;
|
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_ALL_BITS;
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_CONTENT_BITS;
|
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_CONTENT_BITS;
|
||||||
|
@ -3315,9 +3200,6 @@ fn static_assert() {
|
||||||
if v.contains(SpecifiedValue::LAYOUT) {
|
if v.contains(SpecifiedValue::LAYOUT) {
|
||||||
bitfield |= NS_STYLE_CONTAIN_LAYOUT;
|
bitfield |= NS_STYLE_CONTAIN_LAYOUT;
|
||||||
}
|
}
|
||||||
if v.contains(SpecifiedValue::STYLE) {
|
|
||||||
bitfield |= NS_STYLE_CONTAIN_STYLE;
|
|
||||||
}
|
|
||||||
if v.contains(SpecifiedValue::PAINT) {
|
if v.contains(SpecifiedValue::PAINT) {
|
||||||
bitfield |= NS_STYLE_CONTAIN_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_CONTENT;
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_SIZE;
|
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_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_PAINT;
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_ALL_BITS;
|
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_ALL_BITS;
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_CONTENT_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 {
|
if gecko_flags & (NS_STYLE_CONTAIN_LAYOUT as u8) != 0 {
|
||||||
servo_flags.insert(SpecifiedValue::LAYOUT);
|
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 {
|
if gecko_flags & (NS_STYLE_CONTAIN_PAINT as u8) != 0 {
|
||||||
servo_flags.insert(SpecifiedValue::PAINT);
|
servo_flags.insert(SpecifiedValue::PAINT);
|
||||||
}
|
}
|
||||||
|
@ -3870,6 +3748,7 @@ fn static_assert() {
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn set__moz_image_region(&mut self, v: longhands::_moz_image_region::computed_value::T) {
|
pub fn set__moz_image_region(&mut self, v: longhands::_moz_image_region::computed_value::T) {
|
||||||
use crate::values::Either;
|
use crate::values::Either;
|
||||||
|
use crate::values::generics::length::LengthPercentageOrAuto::*;
|
||||||
|
|
||||||
match v {
|
match v {
|
||||||
Either::Second(_auto) => {
|
Either::Second(_auto) => {
|
||||||
|
@ -3879,15 +3758,21 @@ fn static_assert() {
|
||||||
self.gecko.mImageRegion.height = 0;
|
self.gecko.mImageRegion.height = 0;
|
||||||
}
|
}
|
||||||
Either::First(rect) => {
|
Either::First(rect) => {
|
||||||
self.gecko.mImageRegion.x = rect.left.map(Au::from).unwrap_or(Au(0)).0;
|
self.gecko.mImageRegion.x = match rect.left {
|
||||||
self.gecko.mImageRegion.y = rect.top.map(Au::from).unwrap_or(Au(0)).0;
|
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 {
|
self.gecko.mImageRegion.height = match rect.bottom {
|
||||||
Some(value) => (Au::from(value) - Au(self.gecko.mImageRegion.y)).0,
|
LengthPercentage(value) => (Au::from(value) - Au(self.gecko.mImageRegion.y)).0,
|
||||||
None => 0,
|
Auto => 0,
|
||||||
};
|
};
|
||||||
self.gecko.mImageRegion.width = match rect.right {
|
self.gecko.mImageRegion.width = match rect.right {
|
||||||
Some(value) => (Au::from(value) - Au(self.gecko.mImageRegion.x)).0,
|
LengthPercentage(value) => (Au::from(value) - Au(self.gecko.mImageRegion.x)).0,
|
||||||
None => 0,
|
Auto => 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3896,6 +3781,7 @@ fn static_assert() {
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn clone__moz_image_region(&self) -> longhands::_moz_image_region::computed_value::T {
|
pub fn clone__moz_image_region(&self) -> longhands::_moz_image_region::computed_value::T {
|
||||||
use crate::values::{Auto, Either};
|
use crate::values::{Auto, Either};
|
||||||
|
use crate::values::generics::length::LengthPercentageOrAuto::*;
|
||||||
use crate::values::computed::ClipRect;
|
use crate::values::computed::ClipRect;
|
||||||
|
|
||||||
// There is no ideal way to detect auto type for structs::nsRect and its components, so
|
// 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 {
|
Either::First(ClipRect {
|
||||||
top: Some(Au(self.gecko.mImageRegion.y).into()),
|
top: LengthPercentage(Au(self.gecko.mImageRegion.y).into()),
|
||||||
right: Some(Au(self.gecko.mImageRegion.width + self.gecko.mImageRegion.x).into()),
|
right: LengthPercentage(Au(self.gecko.mImageRegion.width + self.gecko.mImageRegion.x).into()),
|
||||||
bottom: Some(Au(self.gecko.mImageRegion.height + self.gecko.mImageRegion.y).into()),
|
bottom: LengthPercentage(Au(self.gecko.mImageRegion.height + self.gecko.mImageRegion.y).into()),
|
||||||
left: Some(Au(self.gecko.mImageRegion.x).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_TOP_AUTO;
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CLIP_RIGHT_AUTO;
|
use crate::gecko_bindings::structs::NS_STYLE_CLIP_RIGHT_AUTO;
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CLIP_BOTTOM_AUTO;
|
use crate::gecko_bindings::structs::NS_STYLE_CLIP_BOTTOM_AUTO;
|
||||||
|
use crate::values::generics::length::LengthPercentageOrAuto::*;
|
||||||
use crate::values::Either;
|
use crate::values::Either;
|
||||||
|
|
||||||
match v {
|
match v {
|
||||||
Either::First(rect) => {
|
Either::First(rect) => {
|
||||||
self.gecko.mClipFlags = NS_STYLE_CLIP_RECT as u8;
|
self.gecko.mClipFlags = NS_STYLE_CLIP_RECT as u8;
|
||||||
if let Some(left) = rect.left {
|
self.gecko.mClip.x = match rect.left {
|
||||||
self.gecko.mClip.x = left.to_i32_au();
|
LengthPercentage(l) => l.to_i32_au(),
|
||||||
} else {
|
Auto => {
|
||||||
self.gecko.mClip.x = 0;
|
self.gecko.mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO as u8;
|
||||||
self.gecko.mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO as u8;
|
0
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(top) = rect.top {
|
self.gecko.mClip.y = match rect.top {
|
||||||
self.gecko.mClip.y = top.to_i32_au();
|
LengthPercentage(l) => l.to_i32_au(),
|
||||||
} else {
|
Auto => {
|
||||||
self.gecko.mClip.y = 0;
|
self.gecko.mClipFlags |= NS_STYLE_CLIP_TOP_AUTO as u8;
|
||||||
self.gecko.mClipFlags |= NS_STYLE_CLIP_TOP_AUTO as u8;
|
0
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(bottom) = rect.bottom {
|
self.gecko.mClip.height = match rect.bottom {
|
||||||
self.gecko.mClip.height = (Au::from(bottom) - Au(self.gecko.mClip.y)).0;
|
LengthPercentage(l) => (Au::from(l) - Au(self.gecko.mClip.y)).0,
|
||||||
} else {
|
Auto => {
|
||||||
self.gecko.mClip.height = 1 << 30; // NS_MAXSIZE
|
self.gecko.mClipFlags |= NS_STYLE_CLIP_BOTTOM_AUTO as u8;
|
||||||
self.gecko.mClipFlags |= NS_STYLE_CLIP_BOTTOM_AUTO as u8;
|
1 << 30 // NS_MAXSIZE
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(right) = rect.right {
|
self.gecko.mClip.width = match rect.right {
|
||||||
self.gecko.mClip.width = (Au::from(right) - Au(self.gecko.mClip.x)).0;
|
LengthPercentage(l) => (Au::from(l) - Au(self.gecko.mClip.x)).0,
|
||||||
} else {
|
Auto => {
|
||||||
self.gecko.mClip.width = 1 << 30; // NS_MAXSIZE
|
self.gecko.mClipFlags |= NS_STYLE_CLIP_RIGHT_AUTO as u8;
|
||||||
self.gecko.mClipFlags |= NS_STYLE_CLIP_RIGHT_AUTO as u8;
|
1 << 30 // NS_MAXSIZE
|
||||||
}
|
}
|
||||||
|
};
|
||||||
},
|
},
|
||||||
Either::Second(_auto) => {
|
Either::Second(_auto) => {
|
||||||
self.gecko.mClipFlags = NS_STYLE_CLIP_AUTO as u8;
|
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_LEFT_AUTO;
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CLIP_RIGHT_AUTO;
|
use crate::gecko_bindings::structs::NS_STYLE_CLIP_RIGHT_AUTO;
|
||||||
use crate::gecko_bindings::structs::NS_STYLE_CLIP_TOP_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::computed::{ClipRect, ClipRectOrAuto};
|
||||||
use crate::values::Either;
|
use crate::values::Either;
|
||||||
|
|
||||||
if self.gecko.mClipFlags == NS_STYLE_CLIP_AUTO as u8 {
|
if self.gecko.mClipFlags == NS_STYLE_CLIP_AUTO as u8 {
|
||||||
ClipRectOrAuto::auto()
|
return ClipRectOrAuto::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())
|
|
||||||
};
|
|
||||||
|
|
||||||
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 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 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())
|
|
||||||
};
|
|
||||||
|
|
||||||
Either::First(ClipRect { top, right, bottom, left })
|
|
||||||
}
|
}
|
||||||
|
let left = if self.gecko.mClipFlags & NS_STYLE_CLIP_LEFT_AUTO as u8 != 0 {
|
||||||
|
debug_assert_eq!(self.gecko.mClip.x, 0);
|
||||||
|
Auto
|
||||||
|
} else {
|
||||||
|
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);
|
||||||
|
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
|
||||||
|
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
|
||||||
|
Auto
|
||||||
|
} else {
|
||||||
|
LengthPercentage(Au(self.gecko.mClip.x + self.gecko.mClip.width).into())
|
||||||
|
};
|
||||||
|
|
||||||
|
Either::First(ClipRect { top, right, bottom, left })
|
||||||
}
|
}
|
||||||
|
|
||||||
<%
|
<%
|
||||||
|
@ -4238,7 +4129,7 @@ fn static_assert() {
|
||||||
|
|
||||||
|
|
||||||
<%self:impl_trait style_struct_name="InheritedText"
|
<%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">
|
-webkit-text-stroke-width text-emphasis-position">
|
||||||
|
|
||||||
<% text_align_keyword = Keyword("text-align",
|
<% text_align_keyword = Keyword("text-align",
|
||||||
|
@ -4270,78 +4161,6 @@ fn static_assert() {
|
||||||
longhands::text_shadow::computed_value::List(buf)
|
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) {
|
fn clear_text_emphasis_style_if_string(&mut self) {
|
||||||
if self.gecko.mTextEmphasisStyle == structs::NS_STYLE_TEXT_EMPHASIS_STYLE_STRING as u8 {
|
if self.gecko.mTextEmphasisStyle == structs::NS_STYLE_TEXT_EMPHASIS_STYLE_STRING as u8 {
|
||||||
self.gecko.mTextEmphasisStyleString.truncate();
|
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::bindings::{Gecko_NewBasicShape, Gecko_DestroyShapeSource};
|
||||||
use crate::gecko_bindings::structs::{StyleBasicShape, StyleBasicShapeType, StyleShapeSourceType};
|
use crate::gecko_bindings::structs::{StyleBasicShape, StyleBasicShapeType, StyleShapeSourceType};
|
||||||
use crate::gecko_bindings::structs::{StyleGeometryBox, StyleShapeSource};
|
use crate::gecko_bindings::structs::{StyleGeometryBox, StyleShapeSource};
|
||||||
use crate::gecko::conversions::basic_shape::set_corners_from_radius;
|
|
||||||
use crate::gecko::values::GeckoStyleCoordConvertible;
|
use crate::gecko::values::GeckoStyleCoordConvertible;
|
||||||
use crate::values::generics::basic_shape::{BasicShape, ShapeSource};
|
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]);
|
inset.rect.2.to_gecko_style_coord(&mut shape.mCoordinates[2]);
|
||||||
shape.mCoordinates[3].leaky_set_null();
|
shape.mCoordinates[3].leaky_set_null();
|
||||||
inset.rect.3.to_gecko_style_coord(&mut shape.mCoordinates[3]);
|
inset.rect.3.to_gecko_style_coord(&mut shape.mCoordinates[3]);
|
||||||
|
shape.mRadius = inset.round;
|
||||||
set_corners_from_radius(inset.round, &mut shape.mRadius);
|
|
||||||
}
|
}
|
||||||
BasicShape::Circle(circ) => {
|
BasicShape::Circle(circ) => {
|
||||||
let shape = init_shape(${ident}, StyleBasicShapeType::Circle);
|
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) {
|
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::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 {
|
match v {
|
||||||
SVGStrokeDashArray::Values(v) => {
|
SVGStrokeDashArray::Values(v) => {
|
||||||
|
@ -4757,12 +4574,7 @@ clip-path
|
||||||
bindings::Gecko_nsStyleSVG_SetDashArrayLength(&mut self.gecko, v.len() as u32);
|
bindings::Gecko_nsStyleSVG_SetDashArrayLength(&mut self.gecko, v.len() as u32);
|
||||||
}
|
}
|
||||||
for (gecko, servo) in self.gecko.mStrokeDasharray.iter_mut().zip(v) {
|
for (gecko, servo) in self.gecko.mStrokeDasharray.iter_mut().zip(v) {
|
||||||
match servo {
|
*gecko = servo;
|
||||||
SvgLengthPercentageOrNumber::LengthPercentage(lp) =>
|
|
||||||
gecko.set(lp),
|
|
||||||
SvgLengthPercentageOrNumber::Number(num) =>
|
|
||||||
gecko.set_value(CoordDataValue::Factor(num.into())),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SVGStrokeDashArray::ContextValue => {
|
SVGStrokeDashArray::ContextValue => {
|
||||||
|
@ -4790,32 +4602,13 @@ clip-path
|
||||||
|
|
||||||
pub fn clone_stroke_dasharray(&self) -> longhands::stroke_dasharray::computed_value::T {
|
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::gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE;
|
||||||
use crate::values::computed::LengthPercentage;
|
use crate::values::generics::svg::SVGStrokeDashArray;
|
||||||
use crate::values::generics::NonNegative;
|
|
||||||
use crate::values::generics::svg::{SVGStrokeDashArray, SvgLengthPercentageOrNumber};
|
|
||||||
|
|
||||||
if self.gecko.mContextFlags & CONTEXT_VALUE != 0 {
|
if self.gecko.mContextFlags & CONTEXT_VALUE != 0 {
|
||||||
debug_assert_eq!(self.gecko.mStrokeDasharray.len(), 0);
|
debug_assert_eq!(self.gecko.mStrokeDasharray.len(), 0);
|
||||||
return SVGStrokeDashArray::ContextValue;
|
return SVGStrokeDashArray::ContextValue;
|
||||||
}
|
}
|
||||||
let mut vec = vec![];
|
SVGStrokeDashArray::Values(self.gecko.mStrokeDasharray.iter().cloned().collect())
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use crate::values::specified::AllowQuirks;
|
use crate::values::specified::AllowQuirks;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
|
use crate::Zero;
|
||||||
|
#[allow(unused_imports)]
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
pub use crate::values::specified::${type} as SpecifiedValue;
|
pub use crate::values::specified::${type} as SpecifiedValue;
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
|
@ -324,29 +326,32 @@
|
||||||
PropertyDeclaration::CSSWideKeyword(ref declaration) => {
|
PropertyDeclaration::CSSWideKeyword(ref declaration) => {
|
||||||
debug_assert_eq!(declaration.id, LonghandId::${property.camel_case});
|
debug_assert_eq!(declaration.id, LonghandId::${property.camel_case});
|
||||||
match declaration.keyword {
|
match declaration.keyword {
|
||||||
% if not data.current_style_struct.inherited:
|
% if not property.style_struct.inherited:
|
||||||
CSSWideKeyword::Unset |
|
CSSWideKeyword::Unset |
|
||||||
% endif
|
% endif
|
||||||
CSSWideKeyword::Initial => {
|
CSSWideKeyword::Initial => {
|
||||||
% if property.ident == "font_size":
|
% if not property.style_struct.inherited:
|
||||||
computed::FontSize::cascade_initial_font_size(context);
|
debug_assert!(false, "Should be handled in apply_properties");
|
||||||
% else:
|
% else:
|
||||||
|
% if property.name == "font-size":
|
||||||
|
computed::FontSize::cascade_initial_font_size(context);
|
||||||
|
% else:
|
||||||
context.builder.reset_${property.ident}();
|
context.builder.reset_${property.ident}();
|
||||||
|
% endif
|
||||||
% endif
|
% endif
|
||||||
},
|
},
|
||||||
% if data.current_style_struct.inherited:
|
% if property.style_struct.inherited:
|
||||||
CSSWideKeyword::Unset |
|
CSSWideKeyword::Unset |
|
||||||
% endif
|
% endif
|
||||||
CSSWideKeyword::Inherit => {
|
CSSWideKeyword::Inherit => {
|
||||||
% if not property.style_struct.inherited:
|
% if property.style_struct.inherited:
|
||||||
context.rule_cache_conditions.borrow_mut().set_uncacheable();
|
debug_assert!(false, "Should be handled in apply_properties");
|
||||||
% endif
|
|
||||||
% if property.ident == "font_size":
|
|
||||||
computed::FontSize::cascade_inherit_font_size(context);
|
|
||||||
% else:
|
% else:
|
||||||
|
context.rule_cache_conditions.borrow_mut().set_uncacheable();
|
||||||
context.builder.inherit_${property.ident}();
|
context.builder.inherit_${property.ident}();
|
||||||
% endif
|
% endif
|
||||||
}
|
}
|
||||||
|
CSSWideKeyword::Revert => unreachable!("Should never get here"),
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -452,14 +452,23 @@ impl AnimationValue {
|
||||||
% for prop in data.longhands:
|
% for prop in data.longhands:
|
||||||
% if prop.animatable:
|
% if prop.animatable:
|
||||||
LonghandId::${prop.camel_case} => {
|
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 {
|
let style_struct = match declaration.keyword {
|
||||||
% if not prop.style_struct.inherited:
|
% if not prop.style_struct.inherited:
|
||||||
|
CSSWideKeyword::Revert |
|
||||||
CSSWideKeyword::Unset |
|
CSSWideKeyword::Unset |
|
||||||
% endif
|
% endif
|
||||||
CSSWideKeyword::Initial => {
|
CSSWideKeyword::Initial => {
|
||||||
initial.get_${prop.style_struct.name_lower}()
|
initial.get_${prop.style_struct.name_lower}()
|
||||||
},
|
},
|
||||||
% if prop.style_struct.inherited:
|
% if prop.style_struct.inherited:
|
||||||
|
CSSWideKeyword::Revert |
|
||||||
CSSWideKeyword::Unset |
|
CSSWideKeyword::Unset |
|
||||||
% endif
|
% endif
|
||||||
CSSWideKeyword::Inherit => {
|
CSSWideKeyword::Inherit => {
|
||||||
|
@ -802,29 +811,29 @@ impl ToAnimatedZero for Visibility {
|
||||||
impl Animate for ClipRect {
|
impl Animate for ClipRect {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||||
use crate::values::computed::Length;
|
use crate::values::computed::LengthOrAuto;
|
||||||
let animate_component = |this: &Option<Length>, other: &Option<Length>| {
|
let animate_component = |this: &LengthOrAuto, other: &LengthOrAuto| {
|
||||||
match (this.animate(other, procedure)?, procedure) {
|
let result = this.animate(other, procedure)?;
|
||||||
(None, Procedure::Interpolate { .. }) => Ok(None),
|
if let Procedure::Interpolate { .. } = procedure {
|
||||||
(None, _) => Err(()),
|
return Ok(result);
|
||||||
(result, _) => 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 {
|
Ok(ClipRect {
|
||||||
top: animate_component(&self.top, &other.top)?,
|
top: animate_component(&self.top, &other.top)?,
|
||||||
right: animate_component(&self.right, &other.right)?,
|
right: animate_component(&self.right, &other.right)?,
|
||||||
bottom: animate_component(&self.bottom, &other.bottom)?,
|
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',
|
FILTER_FUNCTIONS = [ 'Blur', 'Brightness', 'Contrast', 'Grayscale',
|
||||||
'HueRotate', 'Invert', 'Opacity', 'Saturate',
|
'HueRotate', 'Invert', 'Opacity', 'Saturate',
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
"column-width",
|
"column-width",
|
||||||
"length::NonNegativeLengthOrAuto",
|
"length::NonNegativeLengthOrAuto",
|
||||||
"Either::Second(Auto)",
|
"computed::length::NonNegativeLengthOrAuto::auto()",
|
||||||
initial_specified_value="Either::Second(Auto)",
|
initial_specified_value="specified::length::NonNegativeLengthOrAuto::auto()",
|
||||||
extra_prefixes="moz",
|
extra_prefixes="moz",
|
||||||
animation_value_type="NonNegativeLengthOrAuto",
|
animation_value_type="NonNegativeLengthOrAuto",
|
||||||
servo_pref="layout.columns.enabled",
|
servo_pref="layout.columns.enabled",
|
||||||
|
|
|
@ -84,7 +84,8 @@ ${helpers.predefined_type(
|
||||||
)}
|
)}
|
||||||
|
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
"stroke-width", "SVGWidth",
|
"stroke-width",
|
||||||
|
"SVGWidth",
|
||||||
"computed::SVGWidth::one()",
|
"computed::SVGWidth::one()",
|
||||||
products="gecko",
|
products="gecko",
|
||||||
animation_value_type="crate::values::computed::SVGWidth",
|
animation_value_type="crate::values::computed::SVGWidth",
|
||||||
|
@ -109,11 +110,11 @@ ${helpers.single_keyword(
|
||||||
|
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
"stroke-miterlimit",
|
"stroke-miterlimit",
|
||||||
"GreaterThanOrEqualToOneNumber",
|
"NonNegativeNumber",
|
||||||
"From::from(4.0)",
|
"From::from(4.0)",
|
||||||
products="gecko",
|
products="gecko",
|
||||||
animation_value_type="crate::values::computed::GreaterThanOrEqualToOneNumber",
|
animation_value_type="crate::values::computed::NonNegativeNumber",
|
||||||
spec="https://www.w3.org/TR/SVG11/painting.html#StrokeMiterlimitProperty",
|
spec="https://www.w3.org/TR/SVG2/painting.html#StrokeMiterlimitProperty",
|
||||||
)}
|
)}
|
||||||
|
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
|
|
|
@ -74,13 +74,13 @@ ${helpers.predefined_type(
|
||||||
servo_restyle_damage="rebuild_and_reflow",
|
servo_restyle_damage="rebuild_and_reflow",
|
||||||
)}
|
)}
|
||||||
|
|
||||||
// TODO(pcwalton): Support `word-break: keep-all` once we have better CJK support.
|
${helpers.predefined_type(
|
||||||
${helpers.single_keyword(
|
|
||||||
"word-break",
|
"word-break",
|
||||||
"normal break-all keep-all",
|
"WordBreak",
|
||||||
gecko_constant_prefix="NS_STYLE_WORDBREAK",
|
"computed::WordBreak::Normal",
|
||||||
animation_value_type="discrete",
|
animation_value_type="discrete",
|
||||||
spec="https://drafts.csswg.org/css-text/#propdef-word-break",
|
spec="https://drafts.csswg.org/css-text/#propdef-word-break",
|
||||||
|
needs_context=False,
|
||||||
servo_restyle_damage="rebuild_and_reflow",
|
servo_restyle_damage="rebuild_and_reflow",
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ ${helpers.predefined_type(
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
"word-spacing",
|
"word-spacing",
|
||||||
"WordSpacing",
|
"WordSpacing",
|
||||||
"computed::WordSpacing::normal()",
|
"computed::WordSpacing::zero()",
|
||||||
animation_value_type="ComputedValue",
|
animation_value_type="ComputedValue",
|
||||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||||
spec="https://drafts.csswg.org/css-text/#propdef-word-spacing",
|
spec="https://drafts.csswg.org/css-text/#propdef-word-spacing",
|
||||||
|
|
|
@ -39,6 +39,6 @@
|
||||||
logical=side[1],
|
logical=side[1],
|
||||||
logical_group="scroll-padding",
|
logical_group="scroll-padding",
|
||||||
spec="https://drafts.csswg.org/css-scroll-snap-1/#propdef-scroll-padding-%s" % side[0],
|
spec="https://drafts.csswg.org/css-scroll-snap-1/#propdef-scroll-padding-%s" % side[0],
|
||||||
animation_value_type="ComputedValue",
|
animation_value_type="NonNegativeLengthPercentageOrAuto",
|
||||||
)}
|
)}
|
||||||
% endfor
|
% endfor
|
||||||
|
|
|
@ -42,6 +42,7 @@ use crate::values::computed;
|
||||||
use crate::values::computed::NonNegativeLength;
|
use crate::values::computed::NonNegativeLength;
|
||||||
use crate::values::serialize_atom_name;
|
use crate::values::serialize_atom_name;
|
||||||
use crate::rule_tree::StrongRuleNode;
|
use crate::rule_tree::StrongRuleNode;
|
||||||
|
use crate::Zero;
|
||||||
use self::computed_value_flags::*;
|
use self::computed_value_flags::*;
|
||||||
use crate::str::{CssString, CssStringBorrow, CssStringWriter};
|
use crate::str::{CssString, CssStringBorrow, CssStringWriter};
|
||||||
|
|
||||||
|
@ -899,6 +900,8 @@ pub enum CSSWideKeyword {
|
||||||
Inherit,
|
Inherit,
|
||||||
/// The `unset` keyword.
|
/// The `unset` keyword.
|
||||||
Unset,
|
Unset,
|
||||||
|
/// The `revert` keyword.
|
||||||
|
Revert,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CSSWideKeyword {
|
impl CSSWideKeyword {
|
||||||
|
@ -907,6 +910,7 @@ impl CSSWideKeyword {
|
||||||
CSSWideKeyword::Initial => "initial",
|
CSSWideKeyword::Initial => "initial",
|
||||||
CSSWideKeyword::Inherit => "inherit",
|
CSSWideKeyword::Inherit => "inherit",
|
||||||
CSSWideKeyword::Unset => "unset",
|
CSSWideKeyword::Unset => "unset",
|
||||||
|
CSSWideKeyword::Revert => "revert",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -920,6 +924,7 @@ impl CSSWideKeyword {
|
||||||
"initial" => CSSWideKeyword::Initial,
|
"initial" => CSSWideKeyword::Initial,
|
||||||
"inherit" => CSSWideKeyword::Inherit,
|
"inherit" => CSSWideKeyword::Inherit,
|
||||||
"unset" => CSSWideKeyword::Unset,
|
"unset" => CSSWideKeyword::Unset,
|
||||||
|
"revert" => CSSWideKeyword::Revert,
|
||||||
_ => return Err(()),
|
_ => return Err(()),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2102,6 +2107,7 @@ impl PropertyDeclaration {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a CSS-wide keyword if the declaration's value is one.
|
/// Returns a CSS-wide keyword if the declaration's value is one.
|
||||||
|
#[inline]
|
||||||
pub fn get_css_wide_keyword(&self) -> Option<CSSWideKeyword> {
|
pub fn get_css_wide_keyword(&self) -> Option<CSSWideKeyword> {
|
||||||
match *self {
|
match *self {
|
||||||
PropertyDeclaration::CSSWideKeyword(ref declaration) => {
|
PropertyDeclaration::CSSWideKeyword(ref declaration) => {
|
||||||
|
@ -2585,7 +2591,8 @@ pub mod style_structs {
|
||||||
/// Whether the border-${side} property has nonzero width.
|
/// Whether the border-${side} property has nonzero width.
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn border_${side}_has_nonzero_width(&self) -> bool {
|
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
|
% endfor
|
||||||
% elif style_struct.name == "Font":
|
% elif style_struct.name == "Font":
|
||||||
|
@ -2624,7 +2631,8 @@ pub mod style_structs {
|
||||||
/// Whether the outline-width property is non-zero.
|
/// Whether the outline-width property is non-zero.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn outline_has_nonzero_width(&self) -> bool {
|
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":
|
% elif style_struct.name == "Text":
|
||||||
/// Whether the text decoration has an underline.
|
/// Whether the text decoration has an underline.
|
||||||
|
@ -2718,11 +2726,7 @@ pub mod style_structs {
|
||||||
/// Whether this is a multicol style.
|
/// Whether this is a multicol style.
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
pub fn is_multicol(&self) -> bool {
|
pub fn is_multicol(&self) -> bool {
|
||||||
use crate::values::Either;
|
!self.column_width.is_auto() || !self.column_count.is_auto()
|
||||||
match self.column_width {
|
|
||||||
Either::First(_width) => true,
|
|
||||||
Either::Second(_auto) => !self.column_count.is_auto(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
% endif
|
% endif
|
||||||
}
|
}
|
||||||
|
@ -3435,22 +3439,16 @@ impl<'a> StyleBuilder<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
% for property in data.longhands:
|
% for property in data.longhands:
|
||||||
% if property.ident != "font_size":
|
% if not property.style_struct.inherited:
|
||||||
/// Inherit `${property.ident}` from our parent style.
|
/// Inherit `${property.ident}` from our parent style.
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn inherit_${property.ident}(&mut self) {
|
pub fn inherit_${property.ident}(&mut self) {
|
||||||
let inherited_struct =
|
let inherited_struct =
|
||||||
% if property.style_struct.inherited:
|
|
||||||
self.inherited_style.get_${property.style_struct.name_lower}();
|
|
||||||
% else:
|
|
||||||
self.inherited_style_ignoring_first_line
|
self.inherited_style_ignoring_first_line
|
||||||
.get_${property.style_struct.name_lower}();
|
.get_${property.style_struct.name_lower}();
|
||||||
% endif
|
|
||||||
|
|
||||||
% if not property.style_struct.inherited:
|
|
||||||
self.flags.insert(ComputedValueFlags::INHERITS_RESET_STYLE);
|
|
||||||
self.modified_reset = true;
|
self.modified_reset = true;
|
||||||
% endif
|
self.flags.insert(ComputedValueFlags::INHERITS_RESET_STYLE);
|
||||||
|
|
||||||
% if property.ident == "content":
|
% if property.ident == "content":
|
||||||
self.flags.insert(ComputedValueFlags::INHERITS_CONTENT);
|
self.flags.insert(ComputedValueFlags::INHERITS_CONTENT);
|
||||||
|
@ -3472,17 +3470,13 @@ impl<'a> StyleBuilder<'a> {
|
||||||
% endif
|
% endif
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
% elif property.name != "font-size":
|
||||||
/// Reset `${property.ident}` to the initial value.
|
/// Reset `${property.ident}` to the initial value.
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn reset_${property.ident}(&mut self) {
|
pub fn reset_${property.ident}(&mut self) {
|
||||||
let reset_struct =
|
let reset_struct =
|
||||||
self.reset_style.get_${property.style_struct.name_lower}();
|
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) {
|
if self.${property.style_struct.ident}.ptr_eq(reset_struct) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3495,6 +3489,7 @@ impl<'a> StyleBuilder<'a> {
|
||||||
% endif
|
% endif
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
% endif
|
||||||
|
|
||||||
% if not property.is_vector:
|
% if not property.is_vector:
|
||||||
/// Set the `${property.ident}` to the computed value `value`.
|
/// Set the `${property.ident}` to the computed value `value`.
|
||||||
|
@ -3516,7 +3511,6 @@ impl<'a> StyleBuilder<'a> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
% endif
|
% endif
|
||||||
% endif
|
|
||||||
% endfor
|
% endfor
|
||||||
<% del property %>
|
<% del property %>
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use crate::applicable_declarations::ApplicableDeclarationList;
|
||||||
use crate::gecko::selector_parser::PseudoElement;
|
use crate::gecko::selector_parser::PseudoElement;
|
||||||
use crate::properties::{Importance, LonghandIdSet, PropertyDeclarationBlock};
|
use crate::properties::{Importance, LonghandIdSet, PropertyDeclarationBlock};
|
||||||
use crate::shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
|
use crate::shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
|
||||||
use crate::stylesheets::StyleRule;
|
use crate::stylesheets::{Origin, StyleRule};
|
||||||
use crate::thread_state;
|
use crate::thread_state;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
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.
|
/// Returns whether this cascade level represents an animation rules.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_animation(&self) -> bool {
|
pub fn is_animation(&self) -> bool {
|
||||||
|
|
|
@ -36,6 +36,25 @@ impl Origin {
|
||||||
_ => return None,
|
_ => 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! {
|
bitflags! {
|
||||||
|
@ -57,7 +76,11 @@ impl OriginSet {
|
||||||
/// See the `OriginSet` documentation for information about the order
|
/// See the `OriginSet` documentation for information about the order
|
||||||
/// origins are iterated.
|
/// origins are iterated.
|
||||||
pub fn iter(&self) -> OriginSetIterator {
|
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 {
|
pub struct OriginSetIterator {
|
||||||
set: OriginSet,
|
set: OriginSet,
|
||||||
cur: i8,
|
cur: i8,
|
||||||
|
rev: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for OriginSetIterator {
|
impl Iterator for OriginSetIterator {
|
||||||
|
@ -88,7 +112,11 @@ impl Iterator for OriginSetIterator {
|
||||||
loop {
|
loop {
|
||||||
let origin = Origin::from_index(self.cur)?;
|
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()) {
|
if self.set.contains(origin.into()) {
|
||||||
return Some(origin);
|
return Some(origin);
|
||||||
|
|
|
@ -686,7 +686,7 @@ where
|
||||||
// sibling or cousin. Otherwise, recascading a bunch of identical
|
// sibling or cousin. Otherwise, recascading a bunch of identical
|
||||||
// elements would unnecessarily flood the cache with identical entries.
|
// 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
|
// got a hit in the style sharing cache" behavior in the MatchAndCascade
|
||||||
// handling above.
|
// handling above.
|
||||||
//
|
//
|
||||||
|
|
|
@ -16,7 +16,7 @@ use crate::values::computed::Image;
|
||||||
use crate::values::specified::SVGPathData;
|
use crate::values::specified::SVGPathData;
|
||||||
use crate::values::CSSFloat;
|
use crate::values::CSSFloat;
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use euclid::{Point2D, Size2D};
|
use euclid::Point2D;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::cmp;
|
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>
|
impl<T> Animate for Point2D<T>
|
||||||
where
|
where
|
||||||
T: Animate,
|
T: Animate,
|
||||||
|
@ -397,16 +384,13 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ToAnimatedZero for Size2D<T>
|
impl<T> ToAnimatedZero for Vec<T>
|
||||||
where
|
where
|
||||||
T: ToAnimatedZero,
|
T: ToAnimatedZero,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_animated_zero(&self) -> Result<Self, ()> {
|
fn to_animated_zero(&self) -> Result<Self, ()> {
|
||||||
Ok(Size2D::new(
|
self.iter().map(|v| v.to_animated_zero()).collect()
|
||||||
self.width.to_animated_zero()?,
|
|
||||||
self.height.to_animated_zero()?,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,8 @@ use super::{Animate, Procedure, ToAnimatedZero};
|
||||||
use crate::properties::animated_properties::ListAnimation;
|
use crate::properties::animated_properties::ListAnimation;
|
||||||
use crate::values::animated::color::Color as AnimatedColor;
|
use crate::values::animated::color::Color as AnimatedColor;
|
||||||
use crate::values::computed::url::ComputedUrl;
|
use crate::values::computed::url::ComputedUrl;
|
||||||
use crate::values::computed::{LengthPercentage, Number, NumberOrPercentage};
|
|
||||||
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
|
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||||
use crate::values::generics::svg::{SVGLength, SVGPaint, SvgLengthPercentageOrNumber};
|
use crate::values::generics::svg::{SVGPaint, SVGStrokeDashArray};
|
||||||
use crate::values::generics::svg::{SVGOpacity, SVGStrokeDashArray};
|
|
||||||
|
|
||||||
/// Animated SVGPaint.
|
/// Animated SVGPaint.
|
||||||
pub type IntermediateSVGPaint = SVGPaint<AnimatedColor, ComputedUrl>;
|
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>
|
/// <https://www.w3.org/TR/SVG11/painting.html#StrokeDasharrayProperty>
|
||||||
impl<L> Animate for SVGStrokeDashArray<L>
|
impl<L> Animate for SVGStrokeDashArray<L>
|
||||||
where
|
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(()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||||
use crate::values::generics::transform::{self, Transform, TransformOperation};
|
use crate::values::generics::transform::{self, Transform, TransformOperation};
|
||||||
use crate::values::generics::transform::{Rotate, Scale, Translate};
|
use crate::values::generics::transform::{Rotate, Scale, Translate};
|
||||||
use crate::values::CSSFloat;
|
use crate::values::CSSFloat;
|
||||||
use num_traits::Zero;
|
use crate::Zero;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
|
@ -1003,18 +1003,12 @@ impl Animate for ComputedTransformOperation {
|
||||||
(&TransformOperation::Matrix(ref this), &TransformOperation::Matrix(ref other)) => {
|
(&TransformOperation::Matrix(ref this), &TransformOperation::Matrix(ref other)) => {
|
||||||
Ok(TransformOperation::Matrix(this.animate(other, procedure)?))
|
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 fx, ref fy),
|
||||||
&TransformOperation::Skew(ref tx, ref ty),
|
&TransformOperation::Skew(ref tx, ref ty),
|
||||||
) => Ok(TransformOperation::Skew(
|
) => Ok(TransformOperation::Skew(
|
||||||
fx.animate(tx, procedure)?,
|
fx.animate(tx, procedure)?,
|
||||||
Some(
|
fy.animate(ty, procedure)?,
|
||||||
fy.unwrap_or(Angle::zero())
|
|
||||||
.animate(&ty.unwrap_or(Angle::zero()), procedure)?,
|
|
||||||
),
|
|
||||||
)),
|
)),
|
||||||
(&TransformOperation::SkewX(ref f), &TransformOperation::SkewX(ref t)) => {
|
(&TransformOperation::SkewX(ref f), &TransformOperation::SkewX(ref t)) => {
|
||||||
Ok(TransformOperation::SkewX(f.animate(t, procedure)?))
|
Ok(TransformOperation::SkewX(f.animate(t, procedure)?))
|
||||||
|
@ -1030,22 +1024,12 @@ impl Animate for ComputedTransformOperation {
|
||||||
fy.animate(ty, procedure)?,
|
fy.animate(ty, procedure)?,
|
||||||
fz.animate(tz, procedure)?,
|
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 fx, ref fy),
|
||||||
&TransformOperation::Translate(ref tx, ref ty),
|
&TransformOperation::Translate(ref tx, ref ty),
|
||||||
) => Ok(TransformOperation::Translate(
|
) => Ok(TransformOperation::Translate(
|
||||||
fx.animate(tx, procedure)?,
|
fx.animate(tx, procedure)?,
|
||||||
Some(
|
fy.animate(ty, procedure)?,
|
||||||
fy.unwrap_or(LengthPercentage::zero())
|
|
||||||
.animate(&ty.unwrap_or(LengthPercentage::zero()), procedure)?,
|
|
||||||
),
|
|
||||||
)),
|
)),
|
||||||
(&TransformOperation::TranslateX(ref f), &TransformOperation::TranslateX(ref t)) => {
|
(&TransformOperation::TranslateX(ref f), &TransformOperation::TranslateX(ref t)) => {
|
||||||
Ok(TransformOperation::TranslateX(f.animate(t, procedure)?))
|
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(ref f), &TransformOperation::ScaleZ(ref t)) => Ok(
|
||||||
TransformOperation::ScaleZ(animate_multiplicative_factor(*f, *t, procedure)?),
|
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 fx, ref fy),
|
||||||
&TransformOperation::Scale(ref tx, ref ty),
|
&TransformOperation::Scale(ref tx, ref ty),
|
||||||
) => Ok(TransformOperation::Scale(
|
) => Ok(TransformOperation::Scale(
|
||||||
animate_multiplicative_factor(*fx, *tx, procedure)?,
|
animate_multiplicative_factor(*fx, *tx, procedure)?,
|
||||||
Some(animate_multiplicative_factor(
|
animate_multiplicative_factor(*fy, *ty, procedure)?,
|
||||||
fy.unwrap_or(*fx),
|
|
||||||
ty.unwrap_or(*tx),
|
|
||||||
procedure,
|
|
||||||
)?),
|
|
||||||
)),
|
)),
|
||||||
(
|
(
|
||||||
&TransformOperation::Rotate3D(fx, fy, fz, fa),
|
&TransformOperation::Rotate3D(fx, fy, fz, fa),
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
|
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||||
use crate::values::CSSFloat;
|
use crate::values::CSSFloat;
|
||||||
use num_traits::Zero;
|
use crate::Zero;
|
||||||
use std::f64::consts::PI;
|
use std::f64::consts::PI;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use std::{f32, f64};
|
use std::{f32, f64};
|
||||||
|
|
|
@ -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::BorderRadius as GenericBorderRadius;
|
||||||
use crate::values::generics::border::BorderSpacing as GenericBorderSpacing;
|
use crate::values::generics::border::BorderSpacing as GenericBorderSpacing;
|
||||||
use crate::values::generics::rect::Rect;
|
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::values::generics::NonNegative;
|
||||||
|
use crate::Zero;
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
|
|
||||||
pub use crate::values::specified::border::BorderImageRepeat;
|
pub use crate::values::specified::border::BorderImageRepeat;
|
||||||
|
@ -59,7 +60,7 @@ impl BorderImageSlice {
|
||||||
impl BorderSpacing {
|
impl BorderSpacing {
|
||||||
/// Returns `0 0`.
|
/// Returns `0 0`.
|
||||||
pub fn zero() -> Self {
|
pub fn zero() -> Self {
|
||||||
GenericBorderSpacing(Size::new(
|
GenericBorderSpacing(Size2D::new(
|
||||||
NonNegativeLength::zero(),
|
NonNegativeLength::zero(),
|
||||||
NonNegativeLength::zero(),
|
NonNegativeLength::zero(),
|
||||||
))
|
))
|
||||||
|
@ -75,29 +76,3 @@ impl BorderSpacing {
|
||||||
Au::from(*self.0.height())
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -12,11 +12,11 @@ use crate::values::generics::length as generics;
|
||||||
use crate::values::generics::length::{
|
use crate::values::generics::length::{
|
||||||
GenericLengthOrNumber, MaxSize as GenericMaxSize, Size as GenericSize,
|
GenericLengthOrNumber, MaxSize as GenericMaxSize, Size as GenericSize,
|
||||||
};
|
};
|
||||||
use crate::values::generics::transform::IsZeroLength;
|
|
||||||
use crate::values::generics::NonNegative;
|
use crate::values::generics::NonNegative;
|
||||||
use crate::values::specified::length::ViewportPercentageLength;
|
use crate::values::specified::length::ViewportPercentageLength;
|
||||||
use crate::values::specified::length::{AbsoluteLength, FontBaseSize, FontRelativeLength};
|
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 app_units::Au;
|
||||||
use ordered_float::NotNan;
|
use ordered_float::NotNan;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
|
@ -203,12 +203,7 @@ impl LengthPercentage {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.clamping_mode.clamp(self.percentage.0) != self.percentage.0 {
|
Some(Percentage(self.clamping_mode.clamp(self.percentage.0)))
|
||||||
debug_assert!(self.was_calc);
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(self.percentage)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert the computed value into used value.
|
/// Convert the computed value into used value.
|
||||||
|
@ -347,12 +342,6 @@ impl ToComputedValue for specified::CalcLengthPercentage {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LengthPercentage {
|
impl LengthPercentage {
|
||||||
#[inline]
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
pub fn zero() -> LengthPercentage {
|
|
||||||
LengthPercentage::new(Length::new(0.), None)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 1px length value for SVG defaults
|
/// 1px length value for SVG defaults
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn one() -> LengthPercentage {
|
pub fn one() -> LengthPercentage {
|
||||||
|
@ -433,14 +422,13 @@ impl ToComputedValue for specified::LengthPercentage {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_computed_value(computed: &LengthPercentage) -> Self {
|
fn from_computed_value(computed: &LengthPercentage) -> Self {
|
||||||
let length = computed.unclamped_length();
|
|
||||||
if let Some(p) = computed.as_percentage() {
|
if let Some(p) = computed.as_percentage() {
|
||||||
return specified::LengthPercentage::Percentage(p);
|
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(
|
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]
|
#[inline]
|
||||||
fn is_zero_length(&self) -> bool {
|
fn is_zero(&self) -> bool {
|
||||||
self.is_definitely_zero()
|
self.is_definitely_zero()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -459,12 +451,6 @@ impl IsZeroLength for LengthPercentage {
|
||||||
/// length-percentage or auto.
|
/// length-percentage or auto.
|
||||||
macro_rules! computed_length_percentage_or_auto {
|
macro_rules! computed_length_percentage_or_auto {
|
||||||
($inner:ty) => {
|
($inner:ty) => {
|
||||||
/// Returns the `0` value.
|
|
||||||
#[inline]
|
|
||||||
pub fn zero() -> Self {
|
|
||||||
generics::LengthPercentageOrAuto::LengthPercentage(<$inner>::zero())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the used value.
|
/// Returns the used value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_used_value(&self, percentage_basis: Au) -> Option<Au> {
|
pub fn to_used_value(&self, percentage_basis: Au) -> Option<Au> {
|
||||||
|
@ -553,12 +539,6 @@ impl From<Au> for LengthPercentage {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NonNegativeLengthPercentage {
|
impl NonNegativeLengthPercentage {
|
||||||
/// Get zero value.
|
|
||||||
#[inline]
|
|
||||||
pub fn zero() -> Self {
|
|
||||||
NonNegative(LengthPercentage::zero())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if the computed value is absolute 0 or 0%.
|
/// Returns true if the computed value is absolute 0 or 0%.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_definitely_zero(&self) -> bool {
|
pub fn is_definitely_zero(&self) -> bool {
|
||||||
|
@ -662,12 +642,16 @@ impl CSSPixelLength {
|
||||||
pub fn clamp_to_non_negative(self) -> Self {
|
pub fn clamp_to_non_negative(self) -> Self {
|
||||||
CSSPixelLength::new(self.0.max(0.))
|
CSSPixelLength::new(self.0.max(0.))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Zero value
|
impl Zero for CSSPixelLength {
|
||||||
#[inline]
|
fn zero() -> Self {
|
||||||
pub fn zero() -> Self {
|
|
||||||
CSSPixelLength::new(0.)
|
CSSPixelLength::new(0.)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_zero(&self) -> bool {
|
||||||
|
self.px() == 0.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for CSSPixelLength {
|
impl ToCss for CSSPixelLength {
|
||||||
|
@ -717,7 +701,10 @@ impl From<Au> for CSSPixelLength {
|
||||||
pub type Length = CSSPixelLength;
|
pub type Length = CSSPixelLength;
|
||||||
|
|
||||||
/// Either a computed `<length>` or the `auto` keyword.
|
/// 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.
|
/// Either a computed `<length>` or a `<number>` value.
|
||||||
pub type LengthOrNumber = GenericLengthOrNumber<Length, Number>;
|
pub type LengthOrNumber = GenericLengthOrNumber<Length, Number>;
|
||||||
|
@ -749,12 +736,6 @@ impl NonNegativeLength {
|
||||||
NonNegative(Length::new(px.max(0.)))
|
NonNegative(Length::new(px.max(0.)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a zero value.
|
|
||||||
#[inline]
|
|
||||||
pub fn zero() -> Self {
|
|
||||||
Self::new(0.)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the pixel value of |NonNegativeLength|.
|
/// Return the pixel value of |NonNegativeLength|.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn px(&self) -> CSSFloat {
|
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.
|
/// Either a computed NonNegativeLength or the `normal` keyword.
|
||||||
pub type NonNegativeLengthOrNormal = Either<NonNegativeLength, Normal>;
|
pub type NonNegativeLengthOrNormal = Either<NonNegativeLength, Normal>;
|
||||||
|
|
||||||
|
|
|
@ -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::{GridLine as GenericGridLine, TrackBreadth as GenericTrackBreadth};
|
||||||
use super::generics::grid::{TrackList as GenericTrackList, TrackSize as GenericTrackSize};
|
use super::generics::grid::{TrackList as GenericTrackList, TrackSize as GenericTrackSize};
|
||||||
use super::generics::transform::IsParallelTo;
|
use super::generics::transform::IsParallelTo;
|
||||||
use super::generics::{GreaterThanOrEqualToOne, NonNegative};
|
use super::generics::{self, GreaterThanOrEqualToOne, NonNegative};
|
||||||
use super::specified;
|
use super::specified;
|
||||||
use super::{CSSFloat, CSSInteger};
|
use super::{CSSFloat, CSSInteger};
|
||||||
use crate::context::QuirksMode;
|
use crate::context::QuirksMode;
|
||||||
|
@ -27,8 +27,6 @@ use euclid::Size2D;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::f32;
|
use std::f32;
|
||||||
use std::fmt::{self, Write};
|
|
||||||
use style_traits::{CssWriter, ToCss};
|
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub use self::align::{AlignContent, AlignItems, JustifyContent, JustifyItems, SelfAlignment};
|
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::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection, MozImageRect};
|
||||||
pub use self::length::{CSSPixelLength, ExtremumLength, NonNegativeLength};
|
pub use self::length::{CSSPixelLength, ExtremumLength, NonNegativeLength};
|
||||||
pub use self::length::{Length, LengthOrNumber, LengthPercentage, NonNegativeLengthOrNumber};
|
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};
|
pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto};
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub use self::list::ListStyleType;
|
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::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
|
||||||
pub use self::table::XSpan;
|
pub use self::table::XSpan;
|
||||||
pub use self::text::{InitialLetter, LetterSpacing, LineHeight};
|
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::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle};
|
||||||
pub use self::time::Time;
|
pub use self::time::Time;
|
||||||
pub use self::transform::{Rotate, Scale, Transform, TransformOperation};
|
pub use self::transform::{Rotate, Scale, Transform, TransformOperation};
|
||||||
|
@ -637,52 +635,8 @@ impl From<CSSInteger> for PositiveInteger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
/// rect(...)
|
||||||
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
|
pub type ClipRect = generics::ClipRect<LengthOrAuto>;
|
||||||
#[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(...) | auto
|
/// rect(...) | auto
|
||||||
pub type ClipRectOrAuto = Either<ClipRect, Auto>;
|
pub type ClipRectOrAuto = Either<ClipRect, Auto>;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
use crate::values::animated::ToAnimatedValue;
|
use crate::values::animated::ToAnimatedValue;
|
||||||
use crate::values::generics::NonNegative;
|
use crate::values::generics::NonNegative;
|
||||||
use crate::values::{serialize_percentage, CSSFloat};
|
use crate::values::{serialize_percentage, CSSFloat};
|
||||||
|
use crate::Zero;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::{CssWriter, ToCss};
|
use style_traits::{CssWriter, ToCss};
|
||||||
|
|
||||||
|
@ -31,12 +32,6 @@ use style_traits::{CssWriter, ToCss};
|
||||||
pub struct Percentage(pub CSSFloat);
|
pub struct Percentage(pub CSSFloat);
|
||||||
|
|
||||||
impl Percentage {
|
impl Percentage {
|
||||||
/// 0%
|
|
||||||
#[inline]
|
|
||||||
pub fn zero() -> Self {
|
|
||||||
Percentage(0.)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 100%
|
/// 100%
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn hundred() -> Self {
|
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 {
|
impl ToCss for Percentage {
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
where
|
where
|
||||||
|
@ -69,12 +74,6 @@ impl ToCss for Percentage {
|
||||||
pub type NonNegativePercentage = NonNegative<Percentage>;
|
pub type NonNegativePercentage = NonNegative<Percentage>;
|
||||||
|
|
||||||
impl NonNegativePercentage {
|
impl NonNegativePercentage {
|
||||||
/// 0%
|
|
||||||
#[inline]
|
|
||||||
pub fn zero() -> Self {
|
|
||||||
NonNegative(Percentage::zero())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 100%
|
/// 100%
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn hundred() -> Self {
|
pub fn hundred() -> Self {
|
||||||
|
|
|
@ -11,6 +11,7 @@ use crate::values::computed::{Integer, LengthPercentage, Percentage};
|
||||||
use crate::values::generics::position::Position as GenericPosition;
|
use crate::values::generics::position::Position as GenericPosition;
|
||||||
use crate::values::generics::position::ZIndex as GenericZIndex;
|
use crate::values::generics::position::ZIndex as GenericZIndex;
|
||||||
pub use crate::values::specified::position::{GridAutoFlow, GridTemplateAreas};
|
pub use crate::values::specified::position::{GridAutoFlow, GridTemplateAreas};
|
||||||
|
use crate::Zero;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::{CssWriter, ToCss};
|
use style_traits::{CssWriter, ToCss};
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
|
|
||||||
use crate::values::computed::color::Color;
|
use crate::values::computed::color::Color;
|
||||||
use crate::values::computed::url::ComputedUrl;
|
use crate::values::computed::url::ComputedUrl;
|
||||||
use crate::values::computed::{LengthPercentage, NonNegativeLengthPercentage};
|
use crate::values::computed::{LengthPercentage, NonNegativeLengthPercentage, Opacity};
|
||||||
use crate::values::computed::{NonNegativeNumber, Number, Opacity};
|
|
||||||
use crate::values::generics::svg as generic;
|
use crate::values::generics::svg as generic;
|
||||||
use crate::values::RGBA;
|
use crate::values::RGBA;
|
||||||
|
use crate::Zero;
|
||||||
|
|
||||||
pub use crate::values::specified::SVGPaintOrder;
|
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
|
/// <length> | <percentage> | <number> | context-value
|
||||||
pub type SVGLength = generic::SVGLength<SvgLengthPercentageOrNumber>;
|
pub type SVGLength = generic::SVGLength<LengthPercentage>;
|
||||||
|
|
||||||
impl SVGLength {
|
impl SVGLength {
|
||||||
/// `0px`
|
/// `0px`
|
||||||
pub fn zero() -> Self {
|
pub fn zero() -> Self {
|
||||||
generic::SVGLength::Length(generic::SvgLengthPercentageOrNumber::LengthPercentage(
|
generic::SVGLength::LengthPercentage(LengthPercentage::zero())
|
||||||
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())
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An non-negative wrapper of SVGLength.
|
/// An non-negative wrapper of SVGLength.
|
||||||
pub type SVGWidth = generic::SVGLength<NonNegativeSvgLengthPercentageOrNumber>;
|
pub type SVGWidth = generic::SVGLength<NonNegativeLengthPercentage>;
|
||||||
|
|
||||||
impl SVGWidth {
|
impl SVGWidth {
|
||||||
/// `1px`.
|
/// `1px`.
|
||||||
pub fn one() -> Self {
|
pub fn one() -> Self {
|
||||||
use crate::values::generics::NonNegative;
|
use crate::values::generics::NonNegative;
|
||||||
generic::SVGLength::Length(generic::SvgLengthPercentageOrNumber::LengthPercentage(
|
generic::SVGLength::LengthPercentage(NonNegative(LengthPercentage::one()))
|
||||||
NonNegative(LengthPercentage::one()),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [ <length> | <percentage> | <number> ]# | context-value
|
/// [ <length> | <percentage> | <number> ]# | context-value
|
||||||
pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeSvgLengthPercentageOrNumber>;
|
pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeLengthPercentage>;
|
||||||
|
|
||||||
impl Default for SVGStrokeDashArray {
|
impl Default for SVGStrokeDashArray {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
|
|
@ -7,28 +7,97 @@
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
use crate::properties::StyleBuilder;
|
use crate::properties::StyleBuilder;
|
||||||
use crate::values::computed::length::{Length, LengthPercentage};
|
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::InitialLetter as GenericInitialLetter;
|
||||||
use crate::values::generics::text::LineHeight as GenericLineHeight;
|
use crate::values::generics::text::LineHeight as GenericLineHeight;
|
||||||
use crate::values::generics::text::Spacing;
|
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::specified::text::{TextEmphasisFillMode, TextEmphasisShapeKeyword};
|
||||||
use crate::values::{CSSFloat, CSSInteger};
|
use crate::values::{CSSFloat, CSSInteger};
|
||||||
|
use crate::Zero;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::{CssWriter, ToCss};
|
use style_traits::{CssWriter, ToCss};
|
||||||
|
|
||||||
pub use crate::values::specified::OverflowWrap;
|
|
||||||
pub use crate::values::specified::TextAlignKeyword as TextAlign;
|
pub use crate::values::specified::TextAlignKeyword as TextAlign;
|
||||||
pub use crate::values::specified::TextEmphasisPosition;
|
pub use crate::values::specified::TextEmphasisPosition;
|
||||||
|
pub use crate::values::specified::{OverflowWrap, WordBreak};
|
||||||
|
|
||||||
/// A computed value for the `initial-letter` property.
|
/// A computed value for the `initial-letter` property.
|
||||||
pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>;
|
pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>;
|
||||||
|
|
||||||
/// A computed value for the `letter-spacing` property.
|
/// 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.
|
/// 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.
|
/// A computed value for the `line-height` property.
|
||||||
pub type LineHeight = GenericLineHeight<NonNegativeNumber, NonNegativeLength>;
|
pub type LineHeight = GenericLineHeight<NonNegativeNumber, NonNegativeLength>;
|
||||||
|
|
|
@ -9,8 +9,8 @@ use crate::values::animated::transform::{Perspective, Scale3D, Translate3D};
|
||||||
use crate::values::animated::ToAnimatedZero;
|
use crate::values::animated::ToAnimatedZero;
|
||||||
use crate::values::computed::{Angle, Integer, Length, LengthPercentage, Number, Percentage};
|
use crate::values::computed::{Angle, Integer, Length, LengthPercentage, Number, Percentage};
|
||||||
use crate::values::generics::transform as generic;
|
use crate::values::generics::transform as generic;
|
||||||
|
use crate::Zero;
|
||||||
use euclid::{Transform3D, Vector3D};
|
use euclid::{Transform3D, Vector3D};
|
||||||
use num_traits::Zero;
|
|
||||||
|
|
||||||
pub use crate::values::generics::transform::TransformStyle;
|
pub use crate::values::generics::transform::TransformStyle;
|
||||||
|
|
||||||
|
@ -371,15 +371,14 @@ impl TransformOperation {
|
||||||
pub fn to_translate_3d(&self) -> Self {
|
pub fn to_translate_3d(&self) -> Self {
|
||||||
match *self {
|
match *self {
|
||||||
generic::TransformOperation::Translate3D(..) => self.clone(),
|
generic::TransformOperation::Translate3D(..) => self.clone(),
|
||||||
generic::TransformOperation::TranslateX(ref x) |
|
generic::TransformOperation::TranslateX(ref x) => {
|
||||||
generic::TransformOperation::Translate(ref x, None) => {
|
|
||||||
generic::TransformOperation::Translate3D(
|
generic::TransformOperation::Translate3D(
|
||||||
x.clone(),
|
x.clone(),
|
||||||
LengthPercentage::zero(),
|
LengthPercentage::zero(),
|
||||||
Length::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::Translate3D(x.clone(), y.clone(), Length::zero())
|
||||||
},
|
},
|
||||||
generic::TransformOperation::TranslateY(ref y) => {
|
generic::TransformOperation::TranslateY(ref y) => {
|
||||||
|
@ -426,10 +425,7 @@ impl TransformOperation {
|
||||||
pub fn to_scale_3d(&self) -> Self {
|
pub fn to_scale_3d(&self) -> Self {
|
||||||
match *self {
|
match *self {
|
||||||
generic::TransformOperation::Scale3D(..) => self.clone(),
|
generic::TransformOperation::Scale3D(..) => self.clone(),
|
||||||
generic::TransformOperation::Scale(s, None) => {
|
generic::TransformOperation::Scale(x, y) => {
|
||||||
generic::TransformOperation::Scale3D(s, s, 1.)
|
|
||||||
},
|
|
||||||
generic::TransformOperation::Scale(x, Some(y)) => {
|
|
||||||
generic::TransformOperation::Scale3D(x, y, 1.)
|
generic::TransformOperation::Scale3D(x, y, 1.)
|
||||||
},
|
},
|
||||||
generic::TransformOperation::ScaleX(x) => {
|
generic::TransformOperation::ScaleX(x) => {
|
||||||
|
@ -494,7 +490,7 @@ impl ToAnimatedZero for TransformOperation {
|
||||||
Ok(generic::TransformOperation::Scale3D(1.0, 1.0, 1.0))
|
Ok(generic::TransformOperation::Scale3D(1.0, 1.0, 1.0))
|
||||||
},
|
},
|
||||||
generic::TransformOperation::Scale(_, _) => {
|
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::ScaleX(..) => Ok(generic::TransformOperation::ScaleX(1.0)),
|
||||||
generic::TransformOperation::ScaleY(..) => Ok(generic::TransformOperation::ScaleY(1.0)),
|
generic::TransformOperation::ScaleY(..) => Ok(generic::TransformOperation::ScaleY(1.0)),
|
||||||
|
@ -585,7 +581,7 @@ impl Translate {
|
||||||
match *self {
|
match *self {
|
||||||
generic::Translate::None => None,
|
generic::Translate::None => None,
|
||||||
generic::Translate::Translate(tx, ty) => {
|
generic::Translate::Translate(tx, ty) => {
|
||||||
Some(generic::TransformOperation::Translate(tx, Some(ty)))
|
Some(generic::TransformOperation::Translate(tx, ty))
|
||||||
},
|
},
|
||||||
generic::Translate::Translate3D(tx, ty, tz) => {
|
generic::Translate::Translate3D(tx, ty, tz) => {
|
||||||
Some(generic::TransformOperation::Translate3D(tx, ty, tz))
|
Some(generic::TransformOperation::Translate3D(tx, ty, tz))
|
||||||
|
@ -596,9 +592,7 @@ impl Translate {
|
||||||
/// Convert Translate to TransformOperation.
|
/// Convert Translate to TransformOperation.
|
||||||
pub fn from_transform_operation(operation: &TransformOperation) -> Translate {
|
pub fn from_transform_operation(operation: &TransformOperation) -> Translate {
|
||||||
match *operation {
|
match *operation {
|
||||||
generic::TransformOperation::Translate(tx, Some(ty)) => {
|
generic::TransformOperation::Translate(tx, ty) => generic::Translate::Translate(tx, ty),
|
||||||
generic::Translate::Translate(tx, ty)
|
|
||||||
},
|
|
||||||
generic::TransformOperation::Translate3D(tx, ty, tz) => {
|
generic::TransformOperation::Translate3D(tx, ty, tz) => {
|
||||||
generic::Translate::Translate3D(tx, ty, tz)
|
generic::Translate::Translate3D(tx, ty, tz)
|
||||||
},
|
},
|
||||||
|
@ -615,7 +609,7 @@ impl Scale {
|
||||||
pub fn to_transform_operation(&self) -> Option<TransformOperation> {
|
pub fn to_transform_operation(&self) -> Option<TransformOperation> {
|
||||||
match *self {
|
match *self {
|
||||||
generic::Scale::None => None,
|
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) => {
|
generic::Scale::Scale3D(sx, sy, sz) => {
|
||||||
Some(generic::TransformOperation::Scale3D(sx, sy, sz))
|
Some(generic::TransformOperation::Scale3D(sx, sy, sz))
|
||||||
},
|
},
|
||||||
|
@ -625,8 +619,7 @@ impl Scale {
|
||||||
/// Convert Scale to TransformOperation.
|
/// Convert Scale to TransformOperation.
|
||||||
pub fn from_transform_operation(operation: &TransformOperation) -> Scale {
|
pub fn from_transform_operation(operation: &TransformOperation) -> Scale {
|
||||||
match *operation {
|
match *operation {
|
||||||
generic::TransformOperation::Scale(sx, Some(sy)) => generic::Scale::Scale(sx, sy),
|
generic::TransformOperation::Scale(sx, sy) => generic::Scale::Scale(sx, sy),
|
||||||
generic::TransformOperation::Scale(sx, None) => generic::Scale::Scale(sx, sx),
|
|
||||||
generic::TransformOperation::Scale3D(sx, sy, sz) => generic::Scale::Scale3D(sx, sy, sz),
|
generic::TransformOperation::Scale3D(sx, sy, sz) => generic::Scale::Scale3D(sx, sy, sz),
|
||||||
_ => unreachable!("Found unexpected value for scale"),
|
_ => unreachable!("Found unexpected value for scale"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,13 @@
|
||||||
//! Generic types for CSS values related to backgrounds.
|
//! Generic types for CSS values related to backgrounds.
|
||||||
|
|
||||||
use crate::values::generics::length::{GenericLengthPercentageOrAuto, LengthPercentageOrAuto};
|
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.
|
/// A generic value for the `background-size` property.
|
||||||
#[derive(
|
#[derive(
|
||||||
|
@ -21,6 +26,7 @@ use style_traits::{CssWriter, ToCss};
|
||||||
ToAnimatedValue,
|
ToAnimatedValue,
|
||||||
ToAnimatedZero,
|
ToAnimatedZero,
|
||||||
ToComputedValue,
|
ToComputedValue,
|
||||||
|
ToCss,
|
||||||
)]
|
)]
|
||||||
#[repr(C, u8)]
|
#[repr(C, u8)]
|
||||||
pub enum GenericBackgroundSize<LengthPercent> {
|
pub enum GenericBackgroundSize<LengthPercent> {
|
||||||
|
@ -29,6 +35,10 @@ pub enum GenericBackgroundSize<LengthPercent> {
|
||||||
/// Explicit width.
|
/// Explicit width.
|
||||||
width: GenericLengthPercentageOrAuto<LengthPercent>,
|
width: GenericLengthPercentageOrAuto<LengthPercent>,
|
||||||
/// Explicit height.
|
/// 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>,
|
height: GenericLengthPercentageOrAuto<LengthPercent>,
|
||||||
},
|
},
|
||||||
/// `cover`
|
/// `cover`
|
||||||
|
@ -41,32 +51,6 @@ pub enum GenericBackgroundSize<LengthPercent> {
|
||||||
|
|
||||||
pub use self::GenericBackgroundSize as BackgroundSize;
|
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> {
|
impl<LengthPercentage> BackgroundSize<LengthPercentage> {
|
||||||
/// Returns `auto auto`.
|
/// Returns `auto auto`.
|
||||||
pub fn auto() -> Self {
|
pub fn auto() -> Self {
|
||||||
|
|
|
@ -11,6 +11,7 @@ use crate::values::generics::border::BorderRadius;
|
||||||
use crate::values::generics::position::Position;
|
use crate::values::generics::position::Position;
|
||||||
use crate::values::generics::rect::Rect;
|
use crate::values::generics::rect::Rect;
|
||||||
use crate::values::specified::SVGPathData;
|
use crate::values::specified::SVGPathData;
|
||||||
|
use crate::Zero;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::{CssWriter, ToCss};
|
use style_traits::{CssWriter, ToCss};
|
||||||
|
|
||||||
|
@ -127,7 +128,7 @@ pub enum BasicShape<H, V, LengthPercentage, NonNegativeLengthPercentage> {
|
||||||
)]
|
)]
|
||||||
pub struct InsetRect<LengthPercentage, NonNegativeLengthPercentage> {
|
pub struct InsetRect<LengthPercentage, NonNegativeLengthPercentage> {
|
||||||
pub rect: Rect<LengthPercentage>,
|
pub rect: Rect<LengthPercentage>,
|
||||||
pub round: Option<BorderRadius<NonNegativeLengthPercentage>>,
|
pub round: BorderRadius<NonNegativeLengthPercentage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://drafts.csswg.org/css-shapes/#funcdef-circle>
|
/// <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>
|
impl<Length, NonNegativeLength> ToCss for InsetRect<Length, NonNegativeLength>
|
||||||
where
|
where
|
||||||
Length: ToCss + PartialEq,
|
Length: ToCss + PartialEq,
|
||||||
NonNegativeLength: ToCss + PartialEq,
|
NonNegativeLength: ToCss + PartialEq + Zero,
|
||||||
{
|
{
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
where
|
where
|
||||||
|
@ -319,9 +320,9 @@ where
|
||||||
{
|
{
|
||||||
dest.write_str("inset(")?;
|
dest.write_str("inset(")?;
|
||||||
self.rect.to_css(dest)?;
|
self.rect.to_css(dest)?;
|
||||||
if let Some(ref radius) = self.round {
|
if !self.round.is_zero() {
|
||||||
dest.write_str(" round ")?;
|
dest.write_str(" round ")?;
|
||||||
radius.to_css(dest)?;
|
self.round.to_css(dest)?;
|
||||||
}
|
}
|
||||||
dest.write_str(")")
|
dest.write_str(")")
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
//! Generic types for CSS values related to borders.
|
//! Generic types for CSS values related to borders.
|
||||||
|
|
||||||
use crate::values::generics::rect::Rect;
|
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 std::fmt::{self, Write};
|
||||||
use style_traits::{CssWriter, ToCss};
|
use style_traits::{CssWriter, ToCss};
|
||||||
|
|
||||||
|
@ -53,12 +54,25 @@ pub use self::GenericBorderImageSlice as BorderImageSlice;
|
||||||
ToComputedValue,
|
ToComputedValue,
|
||||||
ToCss,
|
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> {
|
impl<L> BorderCornerRadius<L> {
|
||||||
/// Trivially create a `BorderCornerRadius`.
|
/// Trivially create a `BorderCornerRadius`.
|
||||||
pub fn new(w: L, h: L) -> Self {
|
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,
|
ToComputedValue,
|
||||||
ToCss,
|
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> {
|
impl<L> BorderSpacing<L> {
|
||||||
/// Trivially create a `BorderCornerRadius`.
|
/// Trivially create a `BorderCornerRadius`.
|
||||||
pub fn new(w: L, h: L) -> Self {
|
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,
|
ToAnimatedValue,
|
||||||
ToComputedValue,
|
ToComputedValue,
|
||||||
)]
|
)]
|
||||||
pub struct BorderRadius<LengthPercentage> {
|
#[repr(C)]
|
||||||
|
pub struct GenericBorderRadius<LengthPercentage> {
|
||||||
/// The top left radius.
|
/// The top left radius.
|
||||||
pub top_left: BorderCornerRadius<LengthPercentage>,
|
pub top_left: GenericBorderCornerRadius<LengthPercentage>,
|
||||||
/// The top right radius.
|
/// The top right radius.
|
||||||
pub top_right: BorderCornerRadius<LengthPercentage>,
|
pub top_right: GenericBorderCornerRadius<LengthPercentage>,
|
||||||
/// The bottom right radius.
|
/// The bottom right radius.
|
||||||
pub bottom_right: BorderCornerRadius<LengthPercentage>,
|
pub bottom_right: GenericBorderCornerRadius<LengthPercentage>,
|
||||||
/// The bottom left radius.
|
/// The bottom left radius.
|
||||||
pub bottom_left: BorderCornerRadius<LengthPercentage>,
|
pub bottom_left: GenericBorderCornerRadius<LengthPercentage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub use self::GenericBorderRadius as BorderRadius;
|
||||||
|
|
||||||
impl<L> BorderRadius<L> {
|
impl<L> BorderRadius<L> {
|
||||||
/// Returns a new `BorderRadius<L>`.
|
/// Returns a new `BorderRadius<L>`.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -128,12 +146,7 @@ impl<L> BorderRadius<L> {
|
||||||
bottom_left: bl,
|
bottom_left: bl,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<L> BorderRadius<L>
|
|
||||||
where
|
|
||||||
L: PartialEq + ToCss,
|
|
||||||
{
|
|
||||||
/// Serialises two given rects following the syntax of the `border-radius``
|
/// Serialises two given rects following the syntax of the `border-radius``
|
||||||
/// property.
|
/// property.
|
||||||
pub fn serialize_rects<W>(
|
pub fn serialize_rects<W>(
|
||||||
|
@ -142,14 +155,11 @@ where
|
||||||
dest: &mut CssWriter<W>,
|
dest: &mut CssWriter<W>,
|
||||||
) -> fmt::Result
|
) -> fmt::Result
|
||||||
where
|
where
|
||||||
|
L: PartialEq + ToCss,
|
||||||
W: Write,
|
W: Write,
|
||||||
{
|
{
|
||||||
widths.to_css(dest)?;
|
widths.to_css(dest)?;
|
||||||
if widths.0 != heights.0 ||
|
if widths != heights {
|
||||||
widths.1 != heights.1 ||
|
|
||||||
widths.2 != heights.2 ||
|
|
||||||
widths.3 != heights.3
|
|
||||||
{
|
|
||||||
dest.write_str(" / ")?;
|
dest.write_str(" / ")?;
|
||||||
heights.to_css(dest)?;
|
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>
|
impl<L> ToCss for BorderRadius<L>
|
||||||
where
|
where
|
||||||
L: PartialEq + ToCss,
|
L: PartialEq + ToCss,
|
||||||
|
@ -172,8 +200,8 @@ where
|
||||||
bottom_left: BorderCornerRadius(ref bl),
|
bottom_left: BorderCornerRadius(ref bl),
|
||||||
} = *self;
|
} = *self;
|
||||||
|
|
||||||
let widths = Rect::new(&tl.0.width, &tr.0.width, &br.0.width, &bl.0.width);
|
let widths = Rect::new(&tl.width, &tr.width, &br.width, &bl.width);
|
||||||
let heights = Rect::new(&tl.0.height, &tr.0.height, &br.0.height, &bl.0.height);
|
let heights = Rect::new(&tl.height, &tr.height, &br.height, &bl.height);
|
||||||
|
|
||||||
Self::serialize_rects(widths, heights, dest)
|
Self::serialize_rects(widths, heights, dest)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
use crate::parser::{Parse, ParserContext};
|
use crate::parser::{Parse, ParserContext};
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use crate::values::computed::ExtremumLength;
|
use crate::values::computed::ExtremumLength;
|
||||||
|
use crate::Zero;
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use num_traits::Zero;
|
|
||||||
use style_traits::ParseError;
|
use style_traits::ParseError;
|
||||||
|
|
||||||
/// A `<length-percentage> | auto` value.
|
/// 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> {
|
impl<LengthPercentage: Parse> Parse for LengthPercentageOrAuto<LengthPercentage> {
|
||||||
fn parse<'i, 't>(
|
fn parse<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
|
@ -186,12 +199,15 @@ pub enum GenericLengthOrNumber<L, N> {
|
||||||
|
|
||||||
pub use self::GenericLengthOrNumber as LengthOrNumber;
|
pub use self::GenericLengthOrNumber as LengthOrNumber;
|
||||||
|
|
||||||
impl<L, N> LengthOrNumber<L, N> {
|
impl<L, N: Zero> Zero for LengthOrNumber<L, N> {
|
||||||
/// Returns `0`.
|
fn zero() -> Self {
|
||||||
pub fn zero() -> Self
|
LengthOrNumber::Number(Zero::zero())
|
||||||
where
|
}
|
||||||
N: Zero,
|
|
||||||
{
|
fn is_zero(&self) -> bool {
|
||||||
LengthOrNumber::Number(num_traits::Zero::zero())
|
match *self {
|
||||||
|
LengthOrNumber::Number(ref n) => n.is_zero(),
|
||||||
|
LengthOrNumber::Length(..) => false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
use super::CustomIdent;
|
use super::CustomIdent;
|
||||||
use crate::counter_style::{parse_counter_style_name, Symbols};
|
use crate::counter_style::{parse_counter_style_name, Symbols};
|
||||||
use crate::parser::{Parse, ParserContext};
|
use crate::parser::{Parse, ParserContext};
|
||||||
|
use crate::Zero;
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use num_traits::Zero;
|
|
||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
use style_traits::{KeywordsCollectFn, ParseError};
|
use style_traits::{KeywordsCollectFn, ParseError};
|
||||||
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind};
|
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind};
|
||||||
|
@ -212,3 +212,26 @@ impl<T: Zero> Zero for NonNegative<T> {
|
||||||
ToCss,
|
ToCss,
|
||||||
)]
|
)]
|
||||||
pub struct GreaterThanOrEqualToOne<T>(pub T);
|
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,
|
||||||
|
}
|
||||||
|
|
|
@ -5,11 +5,10 @@
|
||||||
//! Generic type for CSS properties that are composed by two dimensions.
|
//! Generic type for CSS properties that are composed by two dimensions.
|
||||||
|
|
||||||
use crate::parser::ParserContext;
|
use crate::parser::ParserContext;
|
||||||
use crate::values::animated::ToAnimatedValue;
|
use crate::Zero;
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use euclid::Size2D;
|
|
||||||
use std::fmt::{self, Write};
|
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
|
/// A generic size, for `border-*-radius` longhand properties, or
|
||||||
/// `border-spacing`.
|
/// `border-spacing`.
|
||||||
|
@ -21,29 +20,36 @@ use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, ToCss};
|
||||||
Debug,
|
Debug,
|
||||||
MallocSizeOf,
|
MallocSizeOf,
|
||||||
PartialEq,
|
PartialEq,
|
||||||
|
SpecifiedValueInfo,
|
||||||
ToAnimatedZero,
|
ToAnimatedZero,
|
||||||
|
ToAnimatedValue,
|
||||||
ToComputedValue,
|
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]
|
#[inline]
|
||||||
/// Create a new `Size` for an area of given width and height.
|
/// Create a new `Size2D` for an area of given width and height.
|
||||||
pub fn new(width: L, height: L) -> Size<L> {
|
pub fn new(width: L, height: L) -> Self {
|
||||||
Size(Size2D::new(width, height))
|
Self { width, height }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the width component.
|
/// Returns the width component.
|
||||||
pub fn width(&self) -> &L {
|
pub fn width(&self) -> &L {
|
||||||
&self.0.width
|
&self.width
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the height component.
|
/// Returns the height component.
|
||||||
pub fn height(&self) -> &L {
|
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>(
|
pub fn parse_with<'i, 't, F>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
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
|
where
|
||||||
L: ToCss + PartialEq,
|
L: ToCss + PartialEq,
|
||||||
{
|
{
|
||||||
|
@ -69,40 +75,23 @@ where
|
||||||
where
|
where
|
||||||
W: Write,
|
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(" ")?;
|
dest.write_str(" ")?;
|
||||||
self.0.height.to_css(dest)?;
|
self.height.to_css(dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L> ToAnimatedValue for Size<L>
|
impl<L: Zero> Zero for Size2D<L> {
|
||||||
where
|
fn zero() -> Self {
|
||||||
L: ToAnimatedValue,
|
Self::new(L::zero(), L::zero())
|
||||||
{
|
|
||||||
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(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
fn is_zero(&self) -> bool {
|
||||||
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
self.width.is_zero() && self.height.is_zero()
|
||||||
Size(Size2D::new(
|
|
||||||
L::from_animated_value(animated.0.width),
|
|
||||||
L::from_animated_value(animated.0.height),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L: SpecifiedValueInfo> SpecifiedValueInfo for Size<L> {
|
|
||||||
const SUPPORTED_TYPES: u8 = L::SUPPORTED_TYPES;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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.
|
/// An SVG length value supports `context-value` in addition to length.
|
||||||
#[derive(
|
#[derive(
|
||||||
|
Animate,
|
||||||
Clone,
|
Clone,
|
||||||
ComputeSquaredDistance,
|
ComputeSquaredDistance,
|
||||||
Copy,
|
Copy,
|
||||||
Debug,
|
Debug,
|
||||||
MallocSizeOf,
|
MallocSizeOf,
|
||||||
PartialEq,
|
PartialEq,
|
||||||
Parse,
|
|
||||||
SpecifiedValueInfo,
|
SpecifiedValueInfo,
|
||||||
ToAnimatedValue,
|
ToAnimatedValue,
|
||||||
ToAnimatedZero,
|
ToAnimatedZero,
|
||||||
ToComputedValue,
|
ToComputedValue,
|
||||||
ToCss,
|
ToCss,
|
||||||
)]
|
)]
|
||||||
pub enum SVGLength<LengthType> {
|
pub enum SVGLength<L> {
|
||||||
/// `<length> | <percentage> | <number>`
|
/// `<length> | <percentage> | <number>`
|
||||||
Length(LengthType),
|
LengthPercentage(L),
|
||||||
/// `context-value`
|
/// `context-value`
|
||||||
#[parse(condition = "is_context_value_enabled")]
|
#[animation(error)]
|
||||||
ContextValue,
|
ContextValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,13 +159,14 @@ pub enum SVGLength<LengthType> {
|
||||||
PartialEq,
|
PartialEq,
|
||||||
SpecifiedValueInfo,
|
SpecifiedValueInfo,
|
||||||
ToAnimatedValue,
|
ToAnimatedValue,
|
||||||
|
ToAnimatedZero,
|
||||||
ToComputedValue,
|
ToComputedValue,
|
||||||
ToCss,
|
ToCss,
|
||||||
)]
|
)]
|
||||||
pub enum SVGStrokeDashArray<LengthType> {
|
pub enum SVGStrokeDashArray<L> {
|
||||||
/// `[ <length> | <percentage> | <number> ]#`
|
/// `[ <length> | <percentage> | <number> ]#`
|
||||||
#[css(comma)]
|
#[css(comma)]
|
||||||
Values(#[css(if_empty = "none", iterable)] Vec<LengthType>),
|
Values(#[css(if_empty = "none", iterable)] Vec<L>),
|
||||||
/// `context-value`
|
/// `context-value`
|
||||||
ContextValue,
|
ContextValue,
|
||||||
}
|
}
|
||||||
|
@ -211,6 +174,7 @@ pub enum SVGStrokeDashArray<LengthType> {
|
||||||
/// An SVG opacity value accepts `context-{fill,stroke}-opacity` in
|
/// An SVG opacity value accepts `context-{fill,stroke}-opacity` in
|
||||||
/// addition to opacity value.
|
/// addition to opacity value.
|
||||||
#[derive(
|
#[derive(
|
||||||
|
Animate,
|
||||||
Clone,
|
Clone,
|
||||||
ComputeSquaredDistance,
|
ComputeSquaredDistance,
|
||||||
Copy,
|
Copy,
|
||||||
|
@ -227,7 +191,9 @@ pub enum SVGOpacity<OpacityType> {
|
||||||
/// `<opacity-value>`
|
/// `<opacity-value>`
|
||||||
Opacity(OpacityType),
|
Opacity(OpacityType),
|
||||||
/// `context-fill-opacity`
|
/// `context-fill-opacity`
|
||||||
|
#[animation(error)]
|
||||||
ContextFillOpacity,
|
ContextFillOpacity,
|
||||||
/// `context-stroke-opacity`
|
/// `context-stroke-opacity`
|
||||||
|
#[animation(error)]
|
||||||
ContextStrokeOpacity,
|
ContextStrokeOpacity,
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,7 @@
|
||||||
//! Generic types for text properties.
|
//! Generic types for text properties.
|
||||||
|
|
||||||
use crate::parser::ParserContext;
|
use crate::parser::ParserContext;
|
||||||
use crate::values::animated::{Animate, Procedure, ToAnimatedZero};
|
use crate::values::animated::ToAnimatedZero;
|
||||||
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
|
|
||||||
use app_units::Au;
|
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use style_traits::ParseError;
|
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.
|
/// A generic spacing value for the `letter-spacing` and `word-spacing` properties.
|
||||||
#[derive(
|
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
|
||||||
Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
|
|
||||||
)]
|
|
||||||
pub enum Spacing<Value> {
|
pub enum Spacing<Value> {
|
||||||
/// `normal`
|
/// `normal`
|
||||||
Normal,
|
Normal,
|
||||||
|
@ -63,51 +59,6 @@ impl<Value> Spacing<Value> {
|
||||||
}
|
}
|
||||||
parse(context, input).map(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.
|
/// A generic value for the `line-height` property.
|
||||||
|
@ -123,18 +74,21 @@ impl<V> ToAnimatedZero for Spacing<V> {
|
||||||
ToAnimatedValue,
|
ToAnimatedValue,
|
||||||
ToCss,
|
ToCss,
|
||||||
)]
|
)]
|
||||||
pub enum LineHeight<Number, LengthPercentage> {
|
#[repr(C, u8)]
|
||||||
|
pub enum GenericLineHeight<N, L> {
|
||||||
/// `normal`
|
/// `normal`
|
||||||
Normal,
|
Normal,
|
||||||
/// `-moz-block-height`
|
/// `-moz-block-height`
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
MozBlockHeight,
|
MozBlockHeight,
|
||||||
/// `<number>`
|
/// `<number>`
|
||||||
Number(Number),
|
Number(N),
|
||||||
/// `<length-or-percentage>`
|
/// `<length-percentage>`
|
||||||
Length(LengthPercentage),
|
Length(L),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub use self::GenericLineHeight as LineHeight;
|
||||||
|
|
||||||
impl<N, L> ToAnimatedZero for LineHeight<N, L> {
|
impl<N, L> ToAnimatedZero for LineHeight<N, L> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_animated_zero(&self) -> Result<Self, ()> {
|
fn to_animated_zero(&self) -> Result<Self, ()> {
|
||||||
|
|
|
@ -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::Length as SpecifiedLength;
|
||||||
use crate::values::specified::length::LengthPercentage as SpecifiedLengthPercentage;
|
use crate::values::specified::length::LengthPercentage as SpecifiedLengthPercentage;
|
||||||
use crate::values::{computed, CSSFloat};
|
use crate::values::{computed, CSSFloat};
|
||||||
|
use crate::Zero;
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use euclid::{self, Rect, Transform3D};
|
use euclid::{self, Rect, Transform3D};
|
||||||
use num_traits::Zero;
|
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::{CssWriter, ToCss};
|
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)]
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
|
||||||
/// A single operation in the list of a `transform` value
|
/// 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.
|
/// Represents a 2D 2x3 matrix.
|
||||||
Matrix(Matrix<Number>),
|
Matrix(Matrix<Number>),
|
||||||
/// Represents a 3D 4x4 matrix.
|
/// 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)
|
/// Syntax can be skew(angle) or skew(angle, angle)
|
||||||
#[css(comma, function)]
|
#[css(comma, function)]
|
||||||
Skew(Angle, Option<Angle>),
|
Skew(Angle, #[css(skip_if = "Zero::is_zero")] Angle),
|
||||||
/// skewX(angle)
|
/// skewX(angle)
|
||||||
#[css(function = "skewX")]
|
#[css(function = "skewX")]
|
||||||
SkewX(Angle),
|
SkewX(Angle),
|
||||||
|
@ -128,7 +137,10 @@ pub enum TransformOperation<Angle, Number, Length, Integer, LengthPercentage> {
|
||||||
SkewY(Angle),
|
SkewY(Angle),
|
||||||
/// translate(x, y) or translate(x)
|
/// translate(x, y) or translate(x)
|
||||||
#[css(comma, function)]
|
#[css(comma, function)]
|
||||||
Translate(LengthPercentage, Option<LengthPercentage>),
|
Translate(
|
||||||
|
LengthPercentage,
|
||||||
|
#[css(skip_if = "Zero::is_zero")] LengthPercentage,
|
||||||
|
),
|
||||||
/// translateX(x)
|
/// translateX(x)
|
||||||
#[css(function = "translateX")]
|
#[css(function = "translateX")]
|
||||||
TranslateX(LengthPercentage),
|
TranslateX(LengthPercentage),
|
||||||
|
@ -143,14 +155,9 @@ pub enum TransformOperation<Angle, Number, Length, Integer, LengthPercentage> {
|
||||||
Translate3D(LengthPercentage, LengthPercentage, Length),
|
Translate3D(LengthPercentage, LengthPercentage, Length),
|
||||||
/// A 2D scaling factor.
|
/// 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)
|
/// Syntax can be scale(factor) or scale(factor, factor)
|
||||||
#[css(comma, function)]
|
#[css(comma, function)]
|
||||||
Scale(Number, Option<Number>),
|
Scale(Number, #[css(contextual_skip_if = "is_same")] Number),
|
||||||
/// scaleX(factor)
|
/// scaleX(factor)
|
||||||
#[css(function = "scaleX")]
|
#[css(function = "scaleX")]
|
||||||
ScaleX(Number),
|
ScaleX(Number),
|
||||||
|
@ -214,6 +221,10 @@ pub struct Transform<T>(#[css(if_empty = "none", iterable)] pub Vec<T>);
|
||||||
|
|
||||||
impl<Angle, Number, Length, Integer, LengthPercentage>
|
impl<Angle, Number, Length, Integer, LengthPercentage>
|
||||||
TransformOperation<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.
|
/// Check if it is any rotate function.
|
||||||
pub fn is_rotate(&self) -> bool {
|
pub fn is_rotate(&self) -> bool {
|
||||||
|
@ -333,10 +344,10 @@ impl ToRadians for SpecifiedAngle {
|
||||||
impl<Angle, Number, Length, Integer, LoP> ToMatrix
|
impl<Angle, Number, Length, Integer, LoP> ToMatrix
|
||||||
for TransformOperation<Angle, Number, Length, Integer, LoP>
|
for TransformOperation<Angle, Number, Length, Integer, LoP>
|
||||||
where
|
where
|
||||||
Angle: ToRadians + Copy,
|
Angle: Zero + ToRadians + Copy,
|
||||||
Number: Copy + Into<f32> + Into<f64>,
|
Number: PartialEq + Copy + Into<f32> + Into<f64>,
|
||||||
Length: ToAbsoluteLength,
|
Length: ToAbsoluteLength,
|
||||||
LoP: ToAbsoluteLength,
|
LoP: Zero + ToAbsoluteLength,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_3d(&self) -> bool {
|
fn is_3d(&self) -> bool {
|
||||||
|
@ -389,7 +400,7 @@ where
|
||||||
m.cast()
|
m.cast()
|
||||||
},
|
},
|
||||||
Scale3D(sx, sy, sz) => Transform3D::create_scale(sx.into(), sy.into(), sz.into()),
|
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.),
|
ScaleX(s) => Transform3D::create_scale(s.into(), 1., 1.),
|
||||||
ScaleY(s) => Transform3D::create_scale(1., s.into(), 1.),
|
ScaleY(s) => Transform3D::create_scale(1., s.into(), 1.),
|
||||||
ScaleZ(s) => Transform3D::create_scale(1., 1., s.into()),
|
ScaleZ(s) => Transform3D::create_scale(1., 1., s.into()),
|
||||||
|
@ -398,12 +409,12 @@ where
|
||||||
let ty = ty.to_pixel_length(reference_height)? as f64;
|
let ty = ty.to_pixel_length(reference_height)? as f64;
|
||||||
Transform3D::create_translation(tx, ty, tz.to_pixel_length(None)? 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 tx = tx.to_pixel_length(reference_width)? as f64;
|
||||||
let ty = ty.to_pixel_length(reference_height)? as f64;
|
let ty = ty.to_pixel_length(reference_height)? as f64;
|
||||||
Transform3D::create_translation(tx, ty, 0.)
|
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;
|
let t = t.to_pixel_length(reference_width)? as f64;
|
||||||
Transform3D::create_translation(t, 0., 0.)
|
Transform3D::create_translation(t, 0., 0.)
|
||||||
},
|
},
|
||||||
|
@ -416,7 +427,7 @@ where
|
||||||
},
|
},
|
||||||
Skew(theta_x, theta_y) => Transform3D::create_skew(
|
Skew(theta_x, theta_y) => Transform3D::create_skew(
|
||||||
euclid::Angle::radians(theta_x.radians64()),
|
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(
|
SkewX(theta) => Transform3D::create_skew(
|
||||||
euclid::Angle::radians(theta.radians64()),
|
euclid::Angle::radians(theta.radians64()),
|
||||||
|
@ -629,64 +640,44 @@ impl<Number: ToCss + PartialEq> ToCss for Scale<Number> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[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>
|
/// <https://drafts.csswg.org/css-transforms-2/#individual-transforms>
|
||||||
pub enum Translate<LengthPercentage, Length> {
|
pub enum Translate<LengthPercentage, Length>
|
||||||
|
where
|
||||||
|
LengthPercentage: Zero,
|
||||||
|
{
|
||||||
/// 'none'
|
/// 'none'
|
||||||
None,
|
None,
|
||||||
/// '<length-percentage>' or '<length-percentage> <length-percentage>'
|
/// '<length-percentage>' or '<length-percentage> <length-percentage>'
|
||||||
Translate(LengthPercentage, LengthPercentage),
|
Translate(
|
||||||
|
LengthPercentage,
|
||||||
|
#[css(skip_if = "Zero::is_zero")] LengthPercentage,
|
||||||
|
),
|
||||||
/// '<length-percentage> <length-percentage> <length>'
|
/// '<length-percentage> <length-percentage> <length>'
|
||||||
Translate3D(LengthPercentage, LengthPercentage, 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)]
|
#[allow(missing_docs)]
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
|
Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss,
|
||||||
|
|
|
@ -160,7 +160,7 @@ impl CustomIdent {
|
||||||
excluding: &[&str],
|
excluding: &[&str],
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
let valid = match_ignore_ascii_case! { ident,
|
let valid = match_ignore_ascii_case! { ident,
|
||||||
"initial" | "inherit" | "unset" | "default" => false,
|
"initial" | "inherit" | "unset" | "default" | "revert" => false,
|
||||||
_ => true
|
_ => true
|
||||||
};
|
};
|
||||||
if !valid {
|
if !valid {
|
||||||
|
|
|
@ -9,6 +9,7 @@ use crate::values::computed::angle::Angle as ComputedAngle;
|
||||||
use crate::values::computed::{Context, ToComputedValue};
|
use crate::values::computed::{Context, ToComputedValue};
|
||||||
use crate::values::specified::calc::CalcNode;
|
use crate::values::specified::calc::CalcNode;
|
||||||
use crate::values::CSSFloat;
|
use crate::values::CSSFloat;
|
||||||
|
use crate::Zero;
|
||||||
use cssparser::{Parser, Token};
|
use cssparser::{Parser, Token};
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
|
@ -32,6 +33,21 @@ pub enum AngleDimension {
|
||||||
Turn(CSSFloat),
|
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 {
|
impl AngleDimension {
|
||||||
/// Returns the amount of degrees this angle represents.
|
/// Returns the amount of degrees this angle represents.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -58,6 +74,19 @@ pub struct Angle {
|
||||||
was_calc: bool,
|
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 {
|
impl ToCss for Angle {
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
where
|
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()`.
|
/// Returns the value of the angle in degrees, mostly for `calc()`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn degrees(&self) -> CSSFloat {
|
pub fn degrees(&self) -> CSSFloat {
|
||||||
|
@ -113,12 +147,6 @@ impl Angle {
|
||||||
self.was_calc
|
self.was_calc
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `0deg`.
|
|
||||||
#[inline]
|
|
||||||
pub fn zero() -> Self {
|
|
||||||
Self::from_degrees(0.0, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an `Angle` parsed from a `calc()` expression.
|
/// Returns an `Angle` parsed from a `calc()` expression.
|
||||||
pub fn from_calc(degrees: CSSFloat) -> Self {
|
pub fn from_calc(degrees: CSSFloat) -> Self {
|
||||||
Angle {
|
Angle {
|
||||||
|
|
|
@ -18,6 +18,7 @@ use crate::values::specified::position::{HorizontalPosition, Position, VerticalP
|
||||||
use crate::values::specified::url::SpecifiedUrl;
|
use crate::values::specified::url::SpecifiedUrl;
|
||||||
use crate::values::specified::SVGPathData;
|
use crate::values::specified::SVGPathData;
|
||||||
use crate::values::specified::{LengthPercentage, NonNegativeLengthPercentage};
|
use crate::values::specified::{LengthPercentage, NonNegativeLengthPercentage};
|
||||||
|
use crate::Zero;
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
||||||
|
@ -202,9 +203,9 @@ impl InsetRect {
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
let rect = Rect::parse_with(context, input, LengthPercentage::parse)?;
|
let rect = Rect::parse_with(context, input, LengthPercentage::parse)?;
|
||||||
let round = if input.try(|i| i.expect_ident_matching("round")).is_ok() {
|
let round = if input.try(|i| i.expect_ident_matching("round")).is_ok() {
|
||||||
Some(BorderRadius::parse(context, input)?)
|
BorderRadius::parse(context, input)?
|
||||||
} else {
|
} else {
|
||||||
None
|
BorderRadius::zero()
|
||||||
};
|
};
|
||||||
Ok(generic::InsetRect { rect, round })
|
Ok(generic::InsetRect { rect, round })
|
||||||
}
|
}
|
||||||
|
|
|
@ -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::BorderRadius as GenericBorderRadius;
|
||||||
use crate::values::generics::border::BorderSpacing as GenericBorderSpacing;
|
use crate::values::generics::border::BorderSpacing as GenericBorderSpacing;
|
||||||
use crate::values::generics::rect::Rect;
|
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::length::{NonNegativeLength, NonNegativeLengthPercentage};
|
||||||
use crate::values::specified::{AllowQuirks, NonNegativeNumber, NonNegativeNumberOrPercentage};
|
use crate::values::specified::{AllowQuirks, NonNegativeNumber, NonNegativeNumberOrPercentage};
|
||||||
|
use crate::Zero;
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::{CssWriter, ParseError, ToCss};
|
use style_traits::{CssWriter, ParseError, ToCss};
|
||||||
|
@ -228,7 +229,7 @@ impl Parse for BorderCornerRadius {
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
Size::parse_with(context, input, NonNegativeLengthPercentage::parse)
|
Size2D::parse_with(context, input, NonNegativeLengthPercentage::parse)
|
||||||
.map(GenericBorderCornerRadius)
|
.map(GenericBorderCornerRadius)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,7 +239,7 @@ impl Parse for BorderSpacing {
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> 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)
|
NonNegativeLength::parse_quirky(context, input, AllowQuirks::Yes).map(From::from)
|
||||||
})
|
})
|
||||||
.map(GenericBorderSpacing)
|
.map(GenericBorderSpacing)
|
||||||
|
|
|
@ -752,25 +752,23 @@ pub fn assert_touch_action_matches() {
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue)]
|
#[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
|
/// Constants for contain: https://drafts.csswg.org/css-contain/#contain-property
|
||||||
pub struct Contain: u8 {
|
pub struct Contain: u8 {
|
||||||
/// 'size' variant, turns on size containment
|
/// 'size' variant, turns on size containment
|
||||||
const SIZE = 0x01;
|
const SIZE = 0x01;
|
||||||
/// `layout` variant, turns on layout containment
|
/// `layout` variant, turns on layout containment
|
||||||
const LAYOUT = 0x02;
|
const LAYOUT = 0x02;
|
||||||
/// `style` variant, turns on style containment
|
|
||||||
const STYLE = 0x04;
|
|
||||||
/// `paint` variant, turns on paint containment
|
/// `paint` variant, turns on paint containment
|
||||||
const PAINT = 0x08;
|
const PAINT = 0x04;
|
||||||
/// `strict` variant, turns on all types of containment
|
/// `strict` variant, turns on all types of containment
|
||||||
const STRICT = 0x10;
|
const STRICT = 0x08;
|
||||||
/// 'content' variant, turns on style, layout, and paint containment
|
/// 'content' variant, turns on layout and paint containment
|
||||||
const CONTENT = 0x20;
|
const CONTENT = 0x10;
|
||||||
/// variant with all the bits that contain: strict turns on
|
/// 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
|
/// 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::SIZE => "size");
|
||||||
maybe_write_value!(Contain::LAYOUT => "layout");
|
maybe_write_value!(Contain::LAYOUT => "layout");
|
||||||
maybe_write_value!(Contain::STYLE => "style");
|
|
||||||
maybe_write_value!(Contain::PAINT => "paint");
|
maybe_write_value!(Contain::PAINT => "paint");
|
||||||
|
|
||||||
debug_assert!(has_any);
|
debug_assert!(has_any);
|
||||||
|
@ -812,7 +809,7 @@ impl ToCss for Contain {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Contain {
|
impl Parse for Contain {
|
||||||
/// none | strict | content | [ size || layout || style || paint ]
|
/// none | strict | content | [ size || layout || paint ]
|
||||||
fn parse<'i, 't>(
|
fn parse<'i, 't>(
|
||||||
_context: &ParserContext,
|
_context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
|
@ -822,7 +819,6 @@ impl Parse for Contain {
|
||||||
let flag = match_ignore_ascii_case! { &name,
|
let flag = match_ignore_ascii_case! { &name,
|
||||||
"size" => Some(Contain::SIZE),
|
"size" => Some(Contain::SIZE),
|
||||||
"layout" => Some(Contain::LAYOUT),
|
"layout" => Some(Contain::LAYOUT),
|
||||||
"style" => Some(Contain::STYLE),
|
|
||||||
"paint" => Some(Contain::PAINT),
|
"paint" => Some(Contain::PAINT),
|
||||||
"strict" if result.is_empty() => return Ok(Contain::STRICT | Contain::STRICT_BITS),
|
"strict" if result.is_empty() => return Ok(Contain::STRICT | Contain::STRICT_BITS),
|
||||||
"content" if result.is_empty() => return Ok(Contain::CONTENT | Contain::CONTENT_BITS),
|
"content" if result.is_empty() => return Ok(Contain::CONTENT | Contain::CONTENT_BITS),
|
||||||
|
|
|
@ -351,13 +351,13 @@ impl Color {
|
||||||
Color::Special(special) => {
|
Color::Special(special) => {
|
||||||
use self::gecko::SpecialColorKeyword as Keyword;
|
use self::gecko::SpecialColorKeyword as Keyword;
|
||||||
_context.map(|context| {
|
_context.map(|context| {
|
||||||
let pres_context = context.device().pres_context();
|
let prefs = context.device().pref_sheet_prefs();
|
||||||
convert_nscolor_to_computedcolor(match special {
|
convert_nscolor_to_computedcolor(match special {
|
||||||
Keyword::MozDefaultColor => pres_context.mDefaultColor,
|
Keyword::MozDefaultColor => prefs.mDefaultColor,
|
||||||
Keyword::MozDefaultBackgroundColor => pres_context.mBackgroundColor,
|
Keyword::MozDefaultBackgroundColor => prefs.mDefaultBackgroundColor,
|
||||||
Keyword::MozHyperlinktext => pres_context.mLinkColor,
|
Keyword::MozHyperlinktext => prefs.mLinkColor,
|
||||||
Keyword::MozActivehyperlinktext => pres_context.mActiveLinkColor,
|
Keyword::MozActivehyperlinktext => prefs.mActiveLinkColor,
|
||||||
Keyword::MozVisitedhyperlinktext => pres_context.mVisitedLinkColor,
|
Keyword::MozVisitedhyperlinktext => prefs.mVisitedLinkColor,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
@ -20,6 +20,7 @@ use crate::values::specified::url::SpecifiedUrl;
|
||||||
use crate::values::specified::{Angle, NumberOrPercentage};
|
use crate::values::specified::{Angle, NumberOrPercentage};
|
||||||
#[cfg(not(feature = "gecko"))]
|
#[cfg(not(feature = "gecko"))]
|
||||||
use crate::values::Impossible;
|
use crate::values::Impossible;
|
||||||
|
use crate::Zero;
|
||||||
use cssparser::{self, BasicParseErrorKind, Parser, Token};
|
use cssparser::{self, BasicParseErrorKind, Parser, Token};
|
||||||
use style_traits::{ParseError, StyleParseErrorKind, ValueParseErrorKind};
|
use style_traits::{ParseError, StyleParseErrorKind, ValueParseErrorKind};
|
||||||
|
|
||||||
|
|
|
@ -14,11 +14,11 @@ use crate::values::generics::length as generics;
|
||||||
use crate::values::generics::length::{
|
use crate::values::generics::length::{
|
||||||
GenericLengthOrNumber, MaxSize as GenericMaxSize, Size as GenericSize,
|
GenericLengthOrNumber, MaxSize as GenericMaxSize, Size as GenericSize,
|
||||||
};
|
};
|
||||||
use crate::values::generics::transform::IsZeroLength;
|
|
||||||
use crate::values::generics::NonNegative;
|
use crate::values::generics::NonNegative;
|
||||||
use crate::values::specified::calc::CalcNode;
|
use crate::values::specified::calc::CalcNode;
|
||||||
use crate::values::specified::NonNegativeNumber;
|
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 app_units::Au;
|
||||||
use cssparser::{Parser, Token};
|
use cssparser::{Parser, Token};
|
||||||
use euclid::Size2D;
|
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.
|
/// Get a px value without context.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_computed_pixel_length_without_context(&self) -> Result<CSSFloat, ()> {
|
pub fn to_computed_pixel_length_without_context(&self) -> Result<CSSFloat, ()> {
|
||||||
|
@ -510,9 +495,12 @@ impl NoCalcLength {
|
||||||
|
|
||||||
impl SpecifiedValueInfo for NoCalcLength {}
|
impl SpecifiedValueInfo for NoCalcLength {}
|
||||||
|
|
||||||
impl IsZeroLength for NoCalcLength {
|
impl Zero for NoCalcLength {
|
||||||
#[inline]
|
fn zero() -> Self {
|
||||||
fn is_zero_length(&self) -> bool {
|
NoCalcLength::Absolute(AbsoluteLength::Px(0.))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_zero(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
NoCalcLength::Absolute(v) => v.is_zero(),
|
NoCalcLength::Absolute(v) => v.is_zero(),
|
||||||
NoCalcLength::FontRelative(v) => v.is_zero(),
|
NoCalcLength::FontRelative(v) => v.is_zero(),
|
||||||
|
@ -584,12 +572,6 @@ impl Mul<CSSFloat> for ViewportPercentageLength {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Length {
|
impl Length {
|
||||||
#[inline]
|
|
||||||
/// Returns a `zero` length.
|
|
||||||
pub fn zero() -> Length {
|
|
||||||
Length::NoCalc(NoCalcLength::zero())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn parse_internal<'i, 't>(
|
fn parse_internal<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
|
@ -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 {
|
impl Length {
|
||||||
/// Parses a length, with quirks.
|
/// Parses a length, with quirks.
|
||||||
pub fn parse_quirky<'i, 't>(
|
pub fn parse_quirky<'i, 't>(
|
||||||
|
@ -711,12 +708,6 @@ impl From<Length> for NonNegativeLength {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NonNegativeLength {
|
impl NonNegativeLength {
|
||||||
/// Returns a `zero` length.
|
|
||||||
#[inline]
|
|
||||||
pub fn zero() -> Self {
|
|
||||||
Length::zero().into()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get an absolute length from a px value.
|
/// Get an absolute length from a px value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_px(px_value: CSSFloat) -> Self {
|
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
|
/// A `<length-percentage>` value. This can be either a `<length>`, a
|
||||||
/// `<percentage>`, or a combination of both via `calc()`.
|
/// `<percentage>`, or a combination of both via `calc()`.
|
||||||
///
|
///
|
||||||
|
@ -801,12 +789,6 @@ impl Parse for LengthPercentage {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LengthPercentage {
|
impl LengthPercentage {
|
||||||
#[inline]
|
|
||||||
/// Returns a `zero` length.
|
|
||||||
pub fn zero() -> LengthPercentage {
|
|
||||||
LengthPercentage::Length(NoCalcLength::zero())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Returns a `0%` value.
|
/// Returns a `0%` value.
|
||||||
pub fn zero_percent() -> LengthPercentage {
|
pub fn zero_percent() -> LengthPercentage {
|
||||||
|
@ -898,11 +880,14 @@ impl LengthPercentage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IsZeroLength for LengthPercentage {
|
impl Zero for LengthPercentage {
|
||||||
#[inline]
|
fn zero() -> Self {
|
||||||
fn is_zero_length(&self) -> bool {
|
LengthPercentage::Length(NoCalcLength::zero())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_zero(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
LengthPercentage::Length(l) => l.is_zero_length(),
|
LengthPercentage::Length(l) => l.is_zero(),
|
||||||
LengthPercentage::Percentage(p) => p.0 == 0.0,
|
LengthPercentage::Percentage(p) => p.0 == 0.0,
|
||||||
LengthPercentage::Calc(_) => false,
|
LengthPercentage::Calc(_) => false,
|
||||||
}
|
}
|
||||||
|
@ -913,11 +898,6 @@ impl IsZeroLength for LengthPercentage {
|
||||||
pub type LengthPercentageOrAuto = generics::LengthPercentageOrAuto<LengthPercentage>;
|
pub type LengthPercentageOrAuto = generics::LengthPercentageOrAuto<LengthPercentage>;
|
||||||
|
|
||||||
impl LengthPercentageOrAuto {
|
impl LengthPercentageOrAuto {
|
||||||
/// Returns a value representing a `0` length.
|
|
||||||
pub fn zero() -> Self {
|
|
||||||
generics::LengthPercentageOrAuto::LengthPercentage(LengthPercentage::zero())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a value representing `0%`.
|
/// Returns a value representing `0%`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn zero_percent() -> Self {
|
pub fn zero_percent() -> Self {
|
||||||
|
@ -943,11 +923,6 @@ pub type NonNegativeLengthPercentageOrAuto =
|
||||||
generics::LengthPercentageOrAuto<NonNegativeLengthPercentage>;
|
generics::LengthPercentageOrAuto<NonNegativeLengthPercentage>;
|
||||||
|
|
||||||
impl NonNegativeLengthPercentageOrAuto {
|
impl NonNegativeLengthPercentageOrAuto {
|
||||||
/// Returns a value representing a `0` length.
|
|
||||||
pub fn zero() -> Self {
|
|
||||||
generics::LengthPercentageOrAuto::LengthPercentage(NonNegativeLengthPercentage::zero())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a value representing `0%`.
|
/// Returns a value representing `0%`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn zero_percent() -> Self {
|
pub fn zero_percent() -> Self {
|
||||||
|
@ -997,12 +972,6 @@ impl Parse for NonNegativeLengthPercentage {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NonNegativeLengthPercentage {
|
impl NonNegativeLengthPercentage {
|
||||||
#[inline]
|
|
||||||
/// Returns a `zero` length.
|
|
||||||
pub fn zero() -> Self {
|
|
||||||
NonNegative(LengthPercentage::zero())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Returns a `0%` value.
|
/// Returns a `0%` value.
|
||||||
pub fn zero_percent() -> Self {
|
pub fn zero_percent() -> Self {
|
||||||
|
@ -1025,7 +994,29 @@ impl NonNegativeLengthPercentage {
|
||||||
pub type LengthOrNormal = Either<Length, Normal>;
|
pub type LengthOrNormal = Either<Length, Normal>;
|
||||||
|
|
||||||
/// Either a `<length>` or the `auto` keyword.
|
/// 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>`.
|
/// Either a `<length>` or a `<number>`.
|
||||||
pub type LengthOrNumber = GenericLengthOrNumber<Length, Number>;
|
pub type LengthOrNumber = GenericLengthOrNumber<Length, Number>;
|
||||||
|
|
|
@ -11,7 +11,7 @@ use super::computed::{Context, ToComputedValue};
|
||||||
use super::generics::grid::{GridLine as GenericGridLine, TrackBreadth as GenericTrackBreadth};
|
use super::generics::grid::{GridLine as GenericGridLine, TrackBreadth as GenericTrackBreadth};
|
||||||
use super::generics::grid::{TrackList as GenericTrackList, TrackSize as GenericTrackSize};
|
use super::generics::grid::{TrackList as GenericTrackList, TrackSize as GenericTrackSize};
|
||||||
use super::generics::transform::IsParallelTo;
|
use super::generics::transform::IsParallelTo;
|
||||||
use super::generics::{GreaterThanOrEqualToOne, NonNegative};
|
use super::generics::{self, GreaterThanOrEqualToOne, NonNegative};
|
||||||
use super::{Auto, CSSFloat, CSSInteger, Either};
|
use super::{Auto, CSSFloat, CSSInteger, Either};
|
||||||
use crate::context::QuirksMode;
|
use crate::context::QuirksMode;
|
||||||
use crate::parser::{Parse, ParserContext};
|
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::image::{GradientItem, GradientKind, Image, ImageLayer, MozImageRect};
|
||||||
pub use self::length::{AbsoluteLength, CalcLengthPercentage, CharacterWidth};
|
pub use self::length::{AbsoluteLength, CalcLengthPercentage, CharacterWidth};
|
||||||
pub use self::length::{FontRelativeLength, Length, LengthOrNumber, NonNegativeLengthOrNumber};
|
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::{MaxSize, Size};
|
||||||
pub use self::length::{NoCalcLength, ViewportPercentageLength};
|
pub use self::length::{NoCalcLength, ViewportPercentageLength};
|
||||||
pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageOrAuto};
|
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::svg_path::SVGPathData;
|
||||||
pub use self::table::XSpan;
|
pub use self::table::XSpan;
|
||||||
pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextAlign};
|
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::text::{TextAlignKeyword, TextDecorationLine, TextOverflow, WordSpacing};
|
||||||
pub use self::time::Time;
|
pub use self::time::Time;
|
||||||
pub use self::transform::{Rotate, Scale, Transform};
|
pub use self::transform::{Rotate, Scale, Transform};
|
||||||
|
@ -605,99 +605,8 @@ pub type GridLine = GenericGridLine<Integer>;
|
||||||
/// `<grid-template-rows> | <grid-template-columns>`
|
/// `<grid-template-rows> | <grid-template-columns>`
|
||||||
pub type GridTemplateComponent = GenericGridTemplateComponent<LengthPercentage, Integer>;
|
pub type GridTemplateComponent = GenericGridTemplateComponent<LengthPercentage, Integer>;
|
||||||
|
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo)]
|
/// rect(...)
|
||||||
/// rect(<top>, <left>, <bottom>, <right>) used by clip and image-region
|
pub type ClipRect = generics::ClipRect<LengthOrAuto>;
|
||||||
#[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)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Parse for ClipRect {
|
impl Parse for ClipRect {
|
||||||
fn parse<'i, 't>(
|
fn parse<'i, 't>(
|
||||||
|
@ -715,25 +624,16 @@ impl ClipRect {
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks,
|
allow_quirks: AllowQuirks,
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
use crate::values::specified::Length;
|
input.expect_function_matching("rect")?;
|
||||||
|
|
||||||
fn parse_argument<'i, 't>(
|
fn parse_argument<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks,
|
allow_quirks: AllowQuirks,
|
||||||
) -> Result<Option<Length>, ParseError<'i>> {
|
) -> Result<LengthOrAuto, ParseError<'i>> {
|
||||||
if input
|
LengthOrAuto::parse_quirky(context, input, allow_quirks)
|
||||||
.try(|input| input.expect_ident_matching("auto"))
|
|
||||||
.is_ok()
|
|
||||||
{
|
|
||||||
Ok(None)
|
|
||||||
} else {
|
|
||||||
Length::parse_quirky(context, input, allow_quirks).map(Some)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input.expect_function_matching("rect")?;
|
|
||||||
|
|
||||||
input.parse_nested_block(|input| {
|
input.parse_nested_block(|input| {
|
||||||
let top = parse_argument(context, input, allow_quirks)?;
|
let top = parse_argument(context, input, allow_quirks)?;
|
||||||
let right;
|
let right;
|
||||||
|
@ -751,11 +651,12 @@ impl ClipRect {
|
||||||
bottom = parse_argument(context, input, allow_quirks)?;
|
bottom = parse_argument(context, input, allow_quirks)?;
|
||||||
left = parse_argument(context, input, allow_quirks)?;
|
left = parse_argument(context, input, allow_quirks)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ClipRect {
|
Ok(ClipRect {
|
||||||
top: top,
|
top,
|
||||||
right: right,
|
right,
|
||||||
bottom: bottom,
|
bottom,
|
||||||
left: left,
|
left,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -782,16 +683,22 @@ impl ClipRectOrAuto {
|
||||||
/// Whether quirks are allowed in this context.
|
/// Whether quirks are allowed in this context.
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
pub enum AllowQuirks {
|
pub enum AllowQuirks {
|
||||||
/// Quirks are allowed.
|
|
||||||
Yes,
|
|
||||||
/// Quirks are not allowed.
|
/// Quirks are not allowed.
|
||||||
No,
|
No,
|
||||||
|
/// Quirks are allowed, in quirks mode.
|
||||||
|
Yes,
|
||||||
|
/// Quirks are always allowed, used for SVG lengths.
|
||||||
|
Always,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AllowQuirks {
|
impl AllowQuirks {
|
||||||
/// Returns `true` if quirks are allowed in this context.
|
/// Returns `true` if quirks are allowed in this context.
|
||||||
pub fn allowed(self, quirks_mode: QuirksMode) -> bool {
|
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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ use crate::values::generics::position::ZIndex as GenericZIndex;
|
||||||
use crate::values::specified::transform::OriginComponent;
|
use crate::values::specified::transform::OriginComponent;
|
||||||
use crate::values::specified::{AllowQuirks, Integer, LengthPercentage};
|
use crate::values::specified::{AllowQuirks, Integer, LengthPercentage};
|
||||||
use crate::values::{Either, None_};
|
use crate::values::{Either, None_};
|
||||||
|
use crate::Zero;
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use selectors::parser::SelectorParseErrorKind;
|
use selectors::parser::SelectorParseErrorKind;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
|
|
|
@ -8,9 +8,9 @@ use crate::parser::{Parse, ParserContext};
|
||||||
use crate::values::generics::svg as generic;
|
use crate::values::generics::svg as generic;
|
||||||
use crate::values::specified::color::Color;
|
use crate::values::specified::color::Color;
|
||||||
use crate::values::specified::url::SpecifiedUrl;
|
use crate::values::specified::url::SpecifiedUrl;
|
||||||
|
use crate::values::specified::AllowQuirks;
|
||||||
use crate::values::specified::LengthPercentage;
|
use crate::values::specified::LengthPercentage;
|
||||||
use crate::values::specified::{NonNegativeLengthPercentage, NonNegativeNumber};
|
use crate::values::specified::{NonNegativeLengthPercentage, Opacity};
|
||||||
use crate::values::specified::{Number, Opacity};
|
|
||||||
use crate::values::CustomIdent;
|
use crate::values::CustomIdent;
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
|
@ -23,36 +23,52 @@ pub type SVGPaint = generic::SVGPaint<Color, SpecifiedUrl>;
|
||||||
/// Specified SVG Paint Kind value
|
/// Specified SVG Paint Kind value
|
||||||
pub type SVGPaintKind = generic::SVGPaintKind<Color, SpecifiedUrl>;
|
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
|
/// <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 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>;
|
|
||||||
|
|
||||||
/// A non-negative version of SVGLength.
|
/// A non-negative version of SVGLength.
|
||||||
pub type SVGWidth = generic::SVGLength<NonNegativeSvgLengthPercentageOrNumber>;
|
pub type SVGWidth = generic::SVGLength<NonNegativeLengthPercentage>;
|
||||||
|
|
||||||
impl From<NonNegativeSvgLengthPercentageOrNumber> for SVGWidth {
|
|
||||||
fn from(length: NonNegativeSvgLengthPercentageOrNumber) -> Self {
|
|
||||||
generic::SVGLength::Length(length)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// [ <length> | <percentage> | <number> ]# | context-value
|
/// [ <length> | <percentage> | <number> ]# | context-value
|
||||||
pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeSvgLengthPercentageOrNumber>;
|
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 }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether the `context-value` value is enabled.
|
||||||
|
#[cfg(not(feature = "gecko"))]
|
||||||
|
pub fn is_context_value_enabled() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
try_match_ident_ignore_ascii_case! { input,
|
||||||
|
"context-value" if is_context_value_enabled() => {
|
||||||
|
Ok(generic::SVGLength::ContextValue)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_svg_length!(SVGLength, LengthPercentage);
|
||||||
|
parse_svg_length!(SVGWidth, NonNegativeLengthPercentage);
|
||||||
|
|
||||||
impl Parse for SVGStrokeDashArray {
|
impl Parse for SVGStrokeDashArray {
|
||||||
fn parse<'i, 't>(
|
fn parse<'i, 't>(
|
||||||
|
@ -61,14 +77,14 @@ impl Parse for SVGStrokeDashArray {
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(values) = input.try(|i| {
|
if let Ok(values) = input.try(|i| {
|
||||||
CommaWithSpace::parse(i, |i| {
|
CommaWithSpace::parse(i, |i| {
|
||||||
NonNegativeSvgLengthPercentageOrNumber::parse(context, i)
|
NonNegativeLengthPercentage::parse_quirky(context, i, AllowQuirks::Always)
|
||||||
})
|
})
|
||||||
}) {
|
}) {
|
||||||
return Ok(generic::SVGStrokeDashArray::Values(values));
|
return Ok(generic::SVGStrokeDashArray::Values(values));
|
||||||
}
|
}
|
||||||
|
|
||||||
try_match_ident_ignore_ascii_case! { input,
|
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)
|
Ok(generic::SVGStrokeDashArray::ContextValue)
|
||||||
},
|
},
|
||||||
"none" => Ok(generic::SVGStrokeDashArray::Values(vec![])),
|
"none" => Ok(generic::SVGStrokeDashArray::Values(vec![])),
|
||||||
|
|
|
@ -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.
|
/// Values for the `overflow-wrap` property.
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(
|
#[derive(
|
||||||
|
|
|
@ -11,6 +11,7 @@ use crate::values::generics::transform as generic;
|
||||||
use crate::values::generics::transform::{Matrix, Matrix3D};
|
use crate::values::generics::transform::{Matrix, Matrix3D};
|
||||||
use crate::values::specified::position::{Side, X, Y};
|
use crate::values::specified::position::{Side, X, Y};
|
||||||
use crate::values::specified::{self, Angle, Integer, Length, LengthPercentage, Number};
|
use crate::values::specified::{self, Angle, Integer, Length, LengthPercentage, Number};
|
||||||
|
use crate::Zero;
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use style_traits::{ParseError, StyleParseErrorKind};
|
use style_traits::{ParseError, StyleParseErrorKind};
|
||||||
|
|
||||||
|
@ -108,9 +109,9 @@ impl Transform {
|
||||||
let sx = specified::LengthPercentage::parse(context, input)?;
|
let sx = specified::LengthPercentage::parse(context, input)?;
|
||||||
if input.try(|input| input.expect_comma()).is_ok() {
|
if input.try(|input| input.expect_comma()).is_ok() {
|
||||||
let sy = specified::LengthPercentage::parse(context, input)?;
|
let sy = specified::LengthPercentage::parse(context, input)?;
|
||||||
Ok(generic::TransformOperation::Translate(sx, Some(sy)))
|
Ok(generic::TransformOperation::Translate(sx, sy))
|
||||||
} else {
|
} else {
|
||||||
Ok(generic::TransformOperation::Translate(sx, None))
|
Ok(generic::TransformOperation::Translate(sx, Zero::zero()))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"translatex" => {
|
"translatex" => {
|
||||||
|
@ -137,9 +138,9 @@ impl Transform {
|
||||||
let sx = Number::parse(context, input)?;
|
let sx = Number::parse(context, input)?;
|
||||||
if input.try(|input| input.expect_comma()).is_ok() {
|
if input.try(|input| input.expect_comma()).is_ok() {
|
||||||
let sy = Number::parse(context, input)?;
|
let sy = Number::parse(context, input)?;
|
||||||
Ok(generic::TransformOperation::Scale(sx, Some(sy)))
|
Ok(generic::TransformOperation::Scale(sx, sy))
|
||||||
} else {
|
} else {
|
||||||
Ok(generic::TransformOperation::Scale(sx, None))
|
Ok(generic::TransformOperation::Scale(sx, sx))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scalex" => {
|
"scalex" => {
|
||||||
|
@ -193,9 +194,9 @@ impl Transform {
|
||||||
let ax = specified::Angle::parse_with_unitless(context, input)?;
|
let ax = specified::Angle::parse_with_unitless(context, input)?;
|
||||||
if input.try(|input| input.expect_comma()).is_ok() {
|
if input.try(|input| input.expect_comma()).is_ok() {
|
||||||
let ay = specified::Angle::parse_with_unitless(context, input)?;
|
let ay = specified::Angle::parse_with_unitless(context, input)?;
|
||||||
Ok(generic::TransformOperation::Skew(ax, Some(ay)))
|
Ok(generic::TransformOperation::Skew(ax, ay))
|
||||||
} else {
|
} else {
|
||||||
Ok(generic::TransformOperation::Skew(ax, None))
|
Ok(generic::TransformOperation::Skew(ax, Zero::zero()))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"skewx" => {
|
"skewx" => {
|
||||||
|
|
|
@ -12,6 +12,70 @@ use syn::{TypeParam, TypeParen, TypePath, TypeSlice, TypeTuple};
|
||||||
use syn::{Variant, WherePredicate};
|
use syn::{Variant, WherePredicate};
|
||||||
use synstructure::{self, BindStyle, BindingInfo, VariantAst, VariantInfo};
|
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) {
|
pub fn add_predicate(where_clause: &mut Option<syn::WhereClause>, pred: WherePredicate) {
|
||||||
where_clause
|
where_clause
|
||||||
.get_or_insert(parse_quote!(where))
|
.get_or_insert(parse_quote!(where))
|
||||||
|
|
|
@ -9,6 +9,12 @@ use synstructure::BindStyle;
|
||||||
|
|
||||||
pub fn derive(mut input: DeriveInput) -> TokenStream {
|
pub fn derive(mut input: DeriveInput) -> TokenStream {
|
||||||
let mut where_clause = input.generics.where_clause.take();
|
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() {
|
for param in input.generics.type_params() {
|
||||||
cg::add_predicate(
|
cg::add_predicate(
|
||||||
&mut where_clause,
|
&mut where_clause,
|
||||||
|
|
|
@ -9,6 +9,12 @@ use synstructure::BindStyle;
|
||||||
|
|
||||||
pub fn derive(mut input: DeriveInput) -> TokenStream {
|
pub fn derive(mut input: DeriveInput) -> TokenStream {
|
||||||
let mut where_clause = input.generics.where_clause.take();
|
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 (to_body, from_body) = {
|
||||||
let params = input.generics.type_params().collect::<Vec<_>>();
|
let params = input.generics.type_params().collect::<Vec<_>>();
|
||||||
for param in ¶ms {
|
for param in ¶ms {
|
||||||
|
|
|
@ -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;
|
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 {
|
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! {{
|
quote! {{
|
||||||
|
@ -167,6 +175,7 @@ fn derive_single_field_expr(
|
||||||
field: &BindingInfo,
|
field: &BindingInfo,
|
||||||
attrs: CssFieldAttrs,
|
attrs: CssFieldAttrs,
|
||||||
where_clause: &mut Option<WhereClause>,
|
where_clause: &mut Option<WhereClause>,
|
||||||
|
bindings: &[BindingInfo],
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let mut expr = if attrs.iterable {
|
let mut expr = if attrs.iterable {
|
||||||
if let Some(if_empty) = attrs.if_empty {
|
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
|
expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,5 +266,6 @@ pub struct CssFieldAttrs {
|
||||||
pub iterable: bool,
|
pub iterable: bool,
|
||||||
pub skip: bool,
|
pub skip: bool,
|
||||||
pub represents_keyword: bool,
|
pub represents_keyword: bool,
|
||||||
|
pub contextual_skip_if: Option<Path>,
|
||||||
pub skip_if: Option<Path>,
|
pub skip_if: Option<Path>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,10 @@ use std::fmt::{self, Write};
|
||||||
/// * if `#[css(skip_if = "function")]` is found on a field, the `ToCss` call
|
/// * 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
|
/// for that field is skipped if `function` returns true. This function is
|
||||||
/// provided the field as an argument;
|
/// 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
|
/// * `#[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
|
/// serialize the field name if the field is true, or nothing otherwise. It
|
||||||
/// also collects those keywords for `SpecifiedValueInfo`.
|
/// also collects those keywords for `SpecifiedValueInfo`.
|
||||||
|
|
|
@ -92,53 +92,3 @@ fn test_transform_interpolation_on_scale() {
|
||||||
Transform(vec![TransformOperation::Scale3D(1.5, 3.0, 1.5)])
|
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)),
|
|
||||||
)])
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,30 +7,30 @@ use servo_arc::Arc;
|
||||||
use style::custom_properties::{
|
use style::custom_properties::{
|
||||||
CssEnvironment, CustomPropertiesBuilder, CustomPropertiesMap, Name, SpecifiedValue,
|
CssEnvironment, CustomPropertiesBuilder, CustomPropertiesMap, Name, SpecifiedValue,
|
||||||
};
|
};
|
||||||
use style::properties::CustomDeclarationValue;
|
use style::properties::{CustomDeclaration, CustomDeclarationValue};
|
||||||
|
use style::stylesheets::Origin;
|
||||||
use test::{self, Bencher};
|
use test::{self, Bencher};
|
||||||
|
|
||||||
fn cascade(
|
fn cascade(
|
||||||
name_and_value: &[(&str, &str)],
|
name_and_value: &[(&str, &str)],
|
||||||
inherited: Option<&Arc<CustomPropertiesMap>>,
|
inherited: Option<&Arc<CustomPropertiesMap>>,
|
||||||
) -> Option<Arc<CustomPropertiesMap>> {
|
) -> Option<Arc<CustomPropertiesMap>> {
|
||||||
let values = name_and_value
|
let declarations = name_and_value
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&(name, value)| {
|
.map(|&(name, value)| {
|
||||||
let mut input = ParserInput::new(value);
|
let mut input = ParserInput::new(value);
|
||||||
let mut parser = Parser::new(&mut input);
|
let mut parser = Parser::new(&mut input);
|
||||||
(
|
let name = Name::from(name);
|
||||||
Name::from(name),
|
let value = CustomDeclarationValue::Value(SpecifiedValue::parse(&mut parser).unwrap());
|
||||||
SpecifiedValue::parse(&mut parser).unwrap(),
|
CustomDeclaration { name, value }
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let env = CssEnvironment;
|
let env = CssEnvironment;
|
||||||
let mut builder = CustomPropertiesBuilder::new(inherited, &env);
|
let mut builder = CustomPropertiesBuilder::new(inherited, &env);
|
||||||
|
|
||||||
for &(ref name, ref val) in &values {
|
for declaration in &declarations {
|
||||||
builder.cascade(name, &CustomDeclarationValue::Value(val.clone()));
|
builder.cascade(declaration, Origin::Author);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.build()
|
builder.build()
|
||||||
|
|
|
@ -2,6 +2,3 @@
|
||||||
[Property text-justify inherits]
|
[Property text-justify inherits]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Property word-spacing has initial value 0px]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
[variable-definition-keywords.html]
|
|
||||||
[specified style revert]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[computed style revert]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -110,9 +110,6 @@
|
||||||
[Testing 'visibility'.]
|
[Testing 'visibility'.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Testing 'word-spacing'.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Testing 'writing-mode'.]
|
[Testing 'writing-mode'.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue