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

@ -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!(),
}
}

View file

@ -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>

View file

@ -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]

View file

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

View file

@ -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)]

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