Add SVGLengthOrPercentageOrNumber for stroke-*.

We need to use enum instead of Either since we can't interpolate stroke-* between
unitless length and unit length(e.g. '5' -> '10px').

This coomit make following:

 * Introduce SVGLengthOrPercentageOrNumber on computed and specified values.
 * Make SVGLengthOrPercentageOrNumber animatable.
 * Make stroke-dasharray not-accumulate.
This commit is contained in:
Mantaroh Yoshinaga 2017-07-12 13:37:53 +09:00
parent 6988c7424d
commit 1c574cf93b
6 changed files with 286 additions and 45 deletions

View file

@ -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")) {