aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-08-17 23:39:00 -0500
committerGitHub <noreply@github.com>2017-08-17 23:39:00 -0500
commitd17f27640be455c91daaf8733289dca90eb505c5 (patch)
treee5e111187cbc1c85a09e52ae97e6b5d5efaa8525
parent489b25004bdc1ccd9348f659e6a608656c55c13b (diff)
parent1c574cf93b1aaab41efe56ceedfd8e0c1c63b931 (diff)
downloadservo-d17f27640be455c91daaf8733289dca90eb505c5.tar.gz
servo-d17f27640be455c91daaf8733289dca90eb505c5.zip
Auto merge of #17704 - mantaroh:interpolate-stroke, r=nox
Add animation value related with stroke-dasharray / stroke-dashoffset / stroke-width. <!-- Please describe your changes on the following line: --> This is a PR for https://bugzilla.mozilla.org/show_bug.cgi?id=1369614 This patch will: * Add animation value conversion of LengthOrPercentage in order to interpolate length and number. * Add animation value of Vec<LengthOrPercentage> in order to interpolate the stroke-dasharray. Spec is as follow: https://svgwg.org/svg2-draft/painting.html#StrokeDashing --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors <!-- Either: --> There are tests for these changes, a test case will be landed in wpt in https://bugzilla.mozilla.org/show_bug.cgi?id=1369614. <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- 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/17288) <!-- Reviewable:end -->
-rw-r--r--components/style/properties/gecko.mako.rs50
-rw-r--r--components/style/properties/helpers/animated_properties.mako.rs149
-rw-r--r--components/style/values/computed/length.rs7
-rw-r--r--components/style/values/computed/svg.rs43
-rw-r--r--components/style/values/generics/svg.rs49
-rw-r--r--components/style/values/specified/svg.rs33
6 files changed, 286 insertions, 45 deletions
diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs
index 682e2cfb39a..6f1b0d2a74f 100644
--- a/components/style/properties/gecko.mako.rs
+++ b/components/style/properties/gecko.mako.rs
@@ -588,7 +588,7 @@ def set_gecko_property(ffi_name, expr):
// set on mContextFlags, and the length field is set to the initial value.
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
- use values::generics::svg::SVGLength;
+ use values::generics::svg::{SVGLength, SvgLengthOrPercentageOrNumber};
use gecko_bindings::structs::nsStyleSVG_${ident.upper()}_CONTEXT as CONTEXT_VALUE;
let length = match v {
SVGLength::Length(length) => {
@@ -604,9 +604,10 @@ def set_gecko_property(ffi_name, expr):
}
};
match length {
- Either::First(number) =>
- self.gecko.${gecko_ffi_name}.set_value(CoordDataValue::Factor(From::from(number))),
- Either::Second(lop) => self.gecko.${gecko_ffi_name}.set(lop),
+ SvgLengthOrPercentageOrNumber::LengthOrPercentage(lop) =>
+ self.gecko.${gecko_ffi_name}.set(lop),
+ SvgLengthOrPercentageOrNumber::Number(num) =>
+ self.gecko.${gecko_ffi_name}.set_value(CoordDataValue::Factor(num.into())),
}
}
@@ -623,21 +624,28 @@ def set_gecko_property(ffi_name, expr):
}
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
- use values::generics::svg::SVGLength;
+ use values::generics::svg::{SVGLength, SvgLengthOrPercentageOrNumber};
use values::computed::LengthOrPercentage;
use gecko_bindings::structs::nsStyleSVG_${ident.upper()}_CONTEXT as CONTEXT_VALUE;
if (self.gecko.mContextFlags & CONTEXT_VALUE) != 0 {
return SVGLength::ContextValue;
}
let length = match self.gecko.${gecko_ffi_name}.as_value() {
- CoordDataValue::Factor(number) => Either::First(From::from(number)),
- CoordDataValue::Coord(coord) => Either::Second(From::from(LengthOrPercentage::Length(Au(coord)))),
- CoordDataValue::Percent(p) => Either::Second(From::from(LengthOrPercentage::Percentage(Percentage(p)))),
- CoordDataValue::Calc(calc) => Either::Second(From::from(LengthOrPercentage::Calc(calc.into()))),
+ CoordDataValue::Factor(number) =>
+ SvgLengthOrPercentageOrNumber::Number(number),
+ CoordDataValue::Coord(coord) =>
+ SvgLengthOrPercentageOrNumber::LengthOrPercentage(
+ LengthOrPercentage::Length(Au(coord))),
+ CoordDataValue::Percent(p) =>
+ SvgLengthOrPercentageOrNumber::LengthOrPercentage(
+ LengthOrPercentage::Percentage(Percentage(p))),
+ CoordDataValue::Calc(calc) =>
+ SvgLengthOrPercentageOrNumber::LengthOrPercentage(
+ LengthOrPercentage::Calc(calc.into())),
_ => unreachable!("Unexpected coordinate {:?} in ${ident}",
self.gecko.${gecko_ffi_name}.as_value()),
};
- SVGLength::Length(length)
+ SVGLength::Length(length.into())
}
</%def>
@@ -5141,7 +5149,7 @@ clip-path
pub fn set_stroke_dasharray(&mut self, v: longhands::stroke_dasharray::computed_value::T) {
use gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE;
- use values::generics::svg::SVGStrokeDashArray;
+ use values::generics::svg::{SVGStrokeDashArray, SvgLengthOrPercentageOrNumber};
match v {
SVGStrokeDashArray::Values(v) => {
@@ -5152,8 +5160,10 @@ clip-path
}
for (gecko, servo) in self.gecko.mStrokeDasharray.iter_mut().zip(v) {
match servo {
- Either::First(number) => gecko.set_value(CoordDataValue::Factor(number.into())),
- Either::Second(lop) => gecko.set(lop),
+ SvgLengthOrPercentageOrNumber::LengthOrPercentage(lop) =>
+ gecko.set(lop),
+ SvgLengthOrPercentageOrNumber::Number(num) =>
+ gecko.set_value(CoordDataValue::Factor(num.into())),
}
}
}
@@ -5183,7 +5193,7 @@ clip-path
pub fn clone_stroke_dasharray(&self) -> longhands::stroke_dasharray::computed_value::T {
use gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE;
use values::computed::LengthOrPercentage;
- use values::generics::svg::SVGStrokeDashArray;
+ use values::generics::svg::{SVGStrokeDashArray, SvgLengthOrPercentageOrNumber};
if self.gecko.mContextFlags & CONTEXT_VALUE != 0 {
debug_assert_eq!(self.gecko.mStrokeDasharray.len(), 0);
@@ -5192,13 +5202,17 @@ clip-path
let mut vec = vec![];
for gecko in self.gecko.mStrokeDasharray.iter() {
match gecko.as_value() {
- CoordDataValue::Factor(number) => vec.push(Either::First(number.into())),
+ CoordDataValue::Factor(number) =>
+ vec.push(SvgLengthOrPercentageOrNumber::Number(number.into())),
CoordDataValue::Coord(coord) =>
- vec.push(Either::Second(LengthOrPercentage::Length(Au(coord)).into())),
+ vec.push(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
+ LengthOrPercentage::Length(Au(coord)).into())),
CoordDataValue::Percent(p) =>
- vec.push(Either::Second(LengthOrPercentage::Percentage(Percentage(p)).into())),
+ vec.push(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
+ LengthOrPercentage::Percentage(Percentage(p)).into())),
CoordDataValue::Calc(calc) =>
- vec.push(Either::Second(LengthOrPercentage::Calc(calc.into()).into())),
+ vec.push(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
+ LengthOrPercentage::Calc(calc.into()).into())),
_ => unreachable!(),
}
}
diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs
index 38ac83a941d..1e3558482ec 100644
--- a/components/style/properties/helpers/animated_properties.mako.rs
+++ b/components/style/properties/helpers/animated_properties.mako.rs
@@ -43,18 +43,20 @@ use values::animated::effects::BoxShadowList as AnimatedBoxShadowList;
use values::animated::effects::Filter as AnimatedFilter;
use values::animated::effects::FilterList as AnimatedFilterList;
use values::animated::effects::TextShadowList as AnimatedTextShadowList;
-use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
-use values::computed::{BorderCornerRadius, ClipRect};
-use values::computed::{CalcLengthOrPercentage, Context, ComputedValueAsSpecified, ComputedUrl};
-use values::computed::{LengthOrPercentage, MaxLength, MozLength, Percentage, ToComputedValue};
-use values::computed::{NonNegativeAu, NonNegativeNumber, PositiveIntegerOrAuto};
+use values::computed::{Angle, BorderCornerRadius, CalcLengthOrPercentage};
+use values::computed::{ClipRect, Context, ComputedUrl, ComputedValueAsSpecified};
+use values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
+use values::computed::{LengthOrPercentageOrNone, MaxLength, MozLength, NonNegativeAu};
+use values::computed::{NonNegativeNumber, Number, NumberOrPercentage, Percentage};
+use values::computed::{PositiveIntegerOrAuto, ToComputedValue};
use values::computed::length::{NonNegativeLengthOrAuto, NonNegativeLengthOrNormal};
use values::computed::length::NonNegativeLengthOrPercentage;
use values::distance::{ComputeSquaredDistance, SquaredDistance};
use values::generics::{GreaterThanOrEqualToOne, NonNegative};
use values::generics::effects::Filter;
use values::generics::position as generic_position;
-use values::generics::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind, SVGStrokeDashArray};
+use values::generics::svg::{SVGLength, SvgLengthOrPercentageOrNumber, SVGPaint};
+use values::generics::svg::{SVGPaintKind, SVGStrokeDashArray, SVGOpacity};
/// A trait used to implement various procedures used during animation.
pub trait Animatable: Sized {
@@ -781,6 +783,7 @@ impl ToAnimatedZero for AnimationValue {
impl RepeatableListAnimatable for LengthOrPercentage {}
impl RepeatableListAnimatable for Either<f32, LengthOrPercentage> {}
impl RepeatableListAnimatable for Either<NonNegativeNumber, NonNegativeLengthOrPercentage> {}
+impl RepeatableListAnimatable for SvgLengthOrPercentageOrNumber<NonNegativeLengthOrPercentage, NonNegativeNumber> {}
macro_rules! repeated_vec_impl {
($($ty:ty),*) => {
@@ -1016,7 +1019,12 @@ impl Animatable for LengthOrPercentage {
impl ToAnimatedZero for LengthOrPercentage {
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
- Ok(LengthOrPercentage::zero())
+ match self {
+ &LengthOrPercentage::Length(_) | &LengthOrPercentage::Calc(_) =>
+ Ok(LengthOrPercentage::zero()),
+ &LengthOrPercentage::Percentage(_) =>
+ Ok(LengthOrPercentage::Percentage(Percentage::zero())),
+ }
}
}
@@ -2496,6 +2504,120 @@ impl ToAnimatedZero for IntermediateSVGPaintKind {
}
}
+impl From<NonNegativeLengthOrPercentage> for NumberOrPercentage {
+ fn from(lop: NonNegativeLengthOrPercentage) -> NumberOrPercentage {
+ lop.0.into()
+ }
+}
+
+impl From<NonNegativeNumber> for NumberOrPercentage {
+ fn from(num: NonNegativeNumber) -> NumberOrPercentage {
+ num.0.into()
+ }
+}
+
+impl From<LengthOrPercentage> for NumberOrPercentage {
+ fn from(lop: LengthOrPercentage) -> NumberOrPercentage {
+ match lop {
+ LengthOrPercentage::Length(len) => NumberOrPercentage::Number(len.to_f32_px()),
+ LengthOrPercentage::Percentage(p) => NumberOrPercentage::Percentage(p),
+ LengthOrPercentage::Calc(_) => {
+ panic!("We dont't expected calc interpolation for SvgLengthOrPercentageOrNumber");
+ },
+ }
+ }
+}
+
+impl From<Number> for NumberOrPercentage {
+ fn from(num: Number) -> NumberOrPercentage {
+ NumberOrPercentage::Number(num)
+ }
+}
+
+fn convert_to_number_or_percentage<LengthOrPercentageType, NumberType>(
+ from: SvgLengthOrPercentageOrNumber<LengthOrPercentageType, NumberType>)
+ -> NumberOrPercentage
+ where LengthOrPercentageType: Into<NumberOrPercentage>,
+ NumberType: Into<NumberOrPercentage>
+{
+ match from {
+ SvgLengthOrPercentageOrNumber::LengthOrPercentage(lop) => {
+ lop.into()
+ }
+ SvgLengthOrPercentageOrNumber::Number(num) => {
+ num.into()
+ }
+ }
+}
+
+fn convert_from_number_or_percentage<LengthOrPercentageType, NumberType>(
+ from: NumberOrPercentage)
+ -> SvgLengthOrPercentageOrNumber<LengthOrPercentageType, NumberType>
+ where LengthOrPercentageType: From<LengthOrPercentage>,
+ NumberType: From<Number>
+{
+ match from {
+ NumberOrPercentage::Number(num) =>
+ SvgLengthOrPercentageOrNumber::Number(num.into()),
+ NumberOrPercentage::Percentage(p) =>
+ SvgLengthOrPercentageOrNumber::LengthOrPercentage(
+ (LengthOrPercentage::Percentage(p)).into())
+ }
+}
+
+impl <LengthOrPercentageType, NumberType> Animatable for
+ SvgLengthOrPercentageOrNumber<LengthOrPercentageType, NumberType>
+ where LengthOrPercentageType: Animatable + Into<NumberOrPercentage> + From<LengthOrPercentage> + Copy,
+ NumberType: Animatable + Into<NumberOrPercentage> + From<Number>,
+ SvgLengthOrPercentageOrNumber<LengthOrPercentageType, NumberType>: Copy,
+ LengthOrPercentage: From<LengthOrPercentageType>
+{
+ #[inline]
+ fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
+ if self.has_calc() || other.has_calc() {
+ // TODO: We need to treat calc value.
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1386967
+ return Err(());
+ }
+
+ let from_value = convert_to_number_or_percentage(*self);
+ let to_value = convert_to_number_or_percentage(*other);
+
+ match (from_value, to_value) {
+ (NumberOrPercentage::Number(from),
+ NumberOrPercentage::Number(to)) => {
+ from.add_weighted(&to, self_portion, other_portion)
+ .map(|num| NumberOrPercentage::Number(num))
+ .map(|nop| convert_from_number_or_percentage(nop))
+ },
+ (NumberOrPercentage::Percentage(from),
+ NumberOrPercentage::Percentage(to)) => {
+ from.add_weighted(&to, self_portion, other_portion)
+ .map(|p| NumberOrPercentage::Percentage(p))
+ .map(|nop| convert_from_number_or_percentage(nop))
+ },
+ _ => Err(()),
+ }
+ }
+}
+
+impl <LengthOrPercentageType, NumberType> ToAnimatedZero for
+ SvgLengthOrPercentageOrNumber<LengthOrPercentageType, NumberType>
+ where LengthOrPercentageType: ToAnimatedZero, NumberType: ToAnimatedZero
+{
+ #[inline]
+ fn to_animated_zero(&self) -> Result<Self, ()> {
+ match self {
+ &SvgLengthOrPercentageOrNumber::LengthOrPercentage(ref lop) =>
+ lop.to_animated_zero()
+ .map(SvgLengthOrPercentageOrNumber::LengthOrPercentage),
+ &SvgLengthOrPercentageOrNumber::Number(ref num) =>
+ num.to_animated_zero()
+ .map(SvgLengthOrPercentageOrNumber::Number),
+ }
+ }
+}
+
impl<LengthType> Animatable for SVGLength<LengthType>
where LengthType: Animatable + Clone
{
@@ -2522,6 +2644,7 @@ impl<LengthType> ToAnimatedZero for SVGLength<LengthType> where LengthType : ToA
}
}
+/// https://www.w3.org/TR/SVG11/painting.html#StrokeDasharrayProperty
impl<LengthType> Animatable for SVGStrokeDashArray<LengthType>
where LengthType : RepeatableListAnimatable + Clone
{
@@ -2537,6 +2660,18 @@ impl<LengthType> Animatable for SVGStrokeDashArray<LengthType>
}
}
}
+
+ /// stroke-dasharray is non-additive
+ #[inline]
+ fn add(&self, _other: &Self) -> Result<Self, ()> {
+ Err(())
+ }
+
+ /// stroke-dasharray is non-additive
+ #[inline]
+ fn accumulate(&self, _other: &Self, _count: u64) -> Result<Self, ()> {
+ Err(())
+ }
}
impl<LengthType> ToAnimatedZero for SVGStrokeDashArray<LengthType>
diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs
index fbe3b56e724..a8287fa9991 100644
--- a/components/style/values/computed/length.rs
+++ b/components/style/values/computed/length.rs
@@ -606,6 +606,13 @@ impl From<LengthOrPercentage> for NonNegativeLengthOrPercentage {
}
}
+impl From<NonNegativeLengthOrPercentage> for LengthOrPercentage {
+ #[inline]
+ fn from(lop: NonNegativeLengthOrPercentage) -> LengthOrPercentage {
+ lop.0
+ }
+}
+
impl NonNegativeLengthOrPercentage {
/// Get zero value.
#[inline]
diff --git a/components/style/values/computed/svg.rs b/components/style/values/computed/svg.rs
index 88cdbd5009e..b4d66b3cec5 100644
--- a/components/style/values/computed/svg.rs
+++ b/components/style/values/computed/svg.rs
@@ -5,10 +5,10 @@
//! Computed types for SVG properties.
use app_units::Au;
-use values::{Either, RGBA};
-use values::computed::{LengthOrPercentageOrNumber, Opacity};
-use values::computed::{NonNegativeAu, NonNegativeLengthOrPercentageOrNumber};
-use values::computed::ComputedUrl;
+use values::RGBA;
+use values::computed::{ComputedUrl, LengthOrPercentage, NonNegativeAu};
+use values::computed::{NonNegativeNumber, NonNegativeLengthOrPercentage, Number};
+use values::computed::Opacity;
use values::generics::svg as generic;
/// Computed SVG Paint value
@@ -36,26 +36,51 @@ impl SVGPaint {
}
}
+/// A value of <length> | <percentage> | <number> for stroke-dashoffset.
+/// https://www.w3.org/TR/SVG11/painting.html#StrokeProperties
+pub type SvgLengthOrPercentageOrNumber =
+ generic::SvgLengthOrPercentageOrNumber<LengthOrPercentage, Number>;
+
/// <length> | <percentage> | <number> | context-value
-pub type SVGLength = generic::SVGLength<LengthOrPercentageOrNumber>;
+pub type SVGLength = generic::SVGLength<SvgLengthOrPercentageOrNumber>;
impl From<Au> for SVGLength {
fn from(length: Au) -> Self {
- generic::SVGLength::Length(Either::Second(length.into()))
+ generic::SVGLength::Length(
+ generic::SvgLengthOrPercentageOrNumber::LengthOrPercentage(length.into()))
+ }
+}
+
+/// A value of <length> | <percentage> | <number> for stroke-width/stroke-dasharray.
+/// https://www.w3.org/TR/SVG11/painting.html#StrokeProperties
+pub type NonNegativeSvgLengthOrPercentageOrNumber =
+ generic::SvgLengthOrPercentageOrNumber<NonNegativeLengthOrPercentage, NonNegativeNumber>;
+
+impl Into<NonNegativeSvgLengthOrPercentageOrNumber> for SvgLengthOrPercentageOrNumber {
+ fn into(self) -> NonNegativeSvgLengthOrPercentageOrNumber {
+ match self {
+ generic::SvgLengthOrPercentageOrNumber::LengthOrPercentage(lop) =>{
+ generic::SvgLengthOrPercentageOrNumber::LengthOrPercentage(lop.into())
+ },
+ generic::SvgLengthOrPercentageOrNumber::Number(num) => {
+ generic::SvgLengthOrPercentageOrNumber::Number(num.into())
+ },
+ }
}
}
/// An non-negative wrapper of SVGLength.
-pub type SVGWidth = generic::SVGLength<NonNegativeLengthOrPercentageOrNumber>;
+pub type SVGWidth = generic::SVGLength<NonNegativeSvgLengthOrPercentageOrNumber>;
impl From<NonNegativeAu> for SVGWidth {
fn from(length: NonNegativeAu) -> Self {
- generic::SVGLength::Length(Either::Second(length.into()))
+ generic::SVGLength::Length(
+ generic::SvgLengthOrPercentageOrNumber::LengthOrPercentage(length.into()))
}
}
/// [ <length> | <percentage> | <number> ]# | context-value
-pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeLengthOrPercentageOrNumber>;
+pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeSvgLengthOrPercentageOrNumber>;
impl Default for SVGStrokeDashArray {
fn default() -> Self {
diff --git a/components/style/values/generics/svg.rs b/components/style/values/generics/svg.rs
index 60f76950aee..631e6374e2d 100644
--- a/components/style/values/generics/svg.rs
+++ b/components/style/values/generics/svg.rs
@@ -8,6 +8,8 @@ use cssparser::Parser;
use parser::{Parse, ParserContext};
use std::fmt;
use style_traits::{ParseError, StyleParseError, ToCss};
+use values::computed::length::LengthOrPercentage;
+
/// An SVG paint value
///
@@ -95,6 +97,53 @@ 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
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+#[derive(Clone, Copy, Debug, PartialEq, ToCss, HasViewportPercentage)]
+#[derive(ToComputedValue, ToAnimatedValue, ComputeSquaredDistance)]
+pub enum SvgLengthOrPercentageOrNumber<LengthOrPercentageType, NumberType> {
+ /// <length> | <percentage>
+ LengthOrPercentage(LengthOrPercentageType),
+ /// <number>
+ Number(NumberType),
+}
+
+impl<LengthOrPercentageType, NumberType> SvgLengthOrPercentageOrNumber<LengthOrPercentageType, NumberType>
+ where LengthOrPercentage: From<LengthOrPercentageType>,
+ LengthOrPercentageType: Copy
+{
+ /// return true if this struct has calc value.
+ pub fn has_calc(&self) -> bool {
+ match self {
+ &SvgLengthOrPercentageOrNumber::LengthOrPercentage(lop) => {
+ match LengthOrPercentage::from(lop) {
+ LengthOrPercentage::Calc(_) => true,
+ _ => false,
+ }
+ },
+ _ => false,
+ }
+ }
+}
+
+/// Parsing the SvgLengthOrPercentageOrNumber. At first, we need to parse number
+/// since prevent converting to the length.
+impl <LengthOrPercentageType: Parse, NumberType: Parse> Parse for
+ SvgLengthOrPercentageOrNumber<LengthOrPercentageType, NumberType> {
+ fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
+ -> Result<Self, ParseError<'i>> {
+ if let Ok(num) = input.try(|i| NumberType::parse(context, i)) {
+ return Ok(SvgLengthOrPercentageOrNumber::Number(num));
+ }
+
+ if let Ok(lop) = input.try(|i| LengthOrPercentageType::parse(context, i)) {
+ return Ok(SvgLengthOrPercentageOrNumber::LengthOrPercentage(lop));
+ }
+ Err(StyleParseError::UnspecifiedError.into())
+ }
+}
+
/// An SVG length value supports `context-value` in addition to length.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, PartialEq)]
diff --git a/components/style/values/specified/svg.rs b/components/style/values/specified/svg.rs
index 980162ccd2d..178b6892793 100644
--- a/components/style/values/specified/svg.rs
+++ b/components/style/values/specified/svg.rs
@@ -8,7 +8,8 @@ use cssparser::Parser;
use parser::{Parse, ParserContext};
use style_traits::{CommaWithSpace, ParseError, Separator, StyleParseError};
use values::generics::svg as generic;
-use values::specified::{LengthOrPercentageOrNumber, NonNegativeLengthOrPercentageOrNumber, Opacity, SpecifiedUrl};
+use values::specified::{LengthOrPercentage, NonNegativeLengthOrPercentage, NonNegativeNumber};
+use values::specified::{Number, Opacity, SpecifiedUrl};
use values::specified::color::RGBAColor;
/// Specified SVG Paint value
@@ -42,50 +43,60 @@ fn parse_context_value<'i, 't, T>(input: &mut Parser<'i, 't>, value: T)
Err(StyleParseError::UnspecifiedError.into())
}
+/// A value of <length> | <percentage> | <number> for stroke-dashoffset.
+/// https://www.w3.org/TR/SVG11/painting.html#StrokeProperties
+pub type SvgLengthOrPercentageOrNumber =
+ generic::SvgLengthOrPercentageOrNumber<LengthOrPercentage, Number>;
+
/// <length> | <percentage> | <number> | context-value
-pub type SVGLength = generic::SVGLength<LengthOrPercentageOrNumber>;
+pub type SVGLength = generic::SVGLength<SvgLengthOrPercentageOrNumber>;
impl Parse for SVGLength {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
- input.try(|i| LengthOrPercentageOrNumber::parse(context, i))
+ input.try(|i| SvgLengthOrPercentageOrNumber::parse(context, i))
.map(Into::into)
.or_else(|_| parse_context_value(input, generic::SVGLength::ContextValue))
}
}
-impl From<LengthOrPercentageOrNumber> for SVGLength {
- fn from(length: LengthOrPercentageOrNumber) -> Self {
+impl From<SvgLengthOrPercentageOrNumber> for SVGLength {
+ fn from(length: SvgLengthOrPercentageOrNumber) -> 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 NonNegativeSvgLengthOrPercentageOrNumber =
+ generic::SvgLengthOrPercentageOrNumber<NonNegativeLengthOrPercentage, NonNegativeNumber>;
+
/// A non-negative version of SVGLength.
-pub type SVGWidth = generic::SVGLength<NonNegativeLengthOrPercentageOrNumber>;
+pub type SVGWidth = generic::SVGLength<NonNegativeSvgLengthOrPercentageOrNumber>;
impl Parse for SVGWidth {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
- input.try(|i| NonNegativeLengthOrPercentageOrNumber::parse(context, i))
+ input.try(|i| NonNegativeSvgLengthOrPercentageOrNumber::parse(context, i))
.map(Into::into)
.or_else(|_| parse_context_value(input, generic::SVGLength::ContextValue))
}
}
-impl From<NonNegativeLengthOrPercentageOrNumber> for SVGWidth {
- fn from(length: NonNegativeLengthOrPercentageOrNumber) -> Self {
+impl From<NonNegativeSvgLengthOrPercentageOrNumber> for SVGWidth {
+ fn from(length: NonNegativeSvgLengthOrPercentageOrNumber) -> Self {
generic::SVGLength::Length(length)
}
}
/// [ <length> | <percentage> | <number> ]# | context-value
-pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeLengthOrPercentageOrNumber>;
+pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeSvgLengthOrPercentageOrNumber>;
impl Parse for SVGStrokeDashArray {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
if let Ok(values) = input.try(|i| CommaWithSpace::parse(i, |i| {
- NonNegativeLengthOrPercentageOrNumber::parse(context, i)
+ NonNegativeSvgLengthOrPercentageOrNumber::parse(context, i)
})) {
Ok(generic::SVGStrokeDashArray::Values(values))
} else if let Ok(_) = input.try(|i| i.expect_ident_matching("none")) {