mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
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:
parent
6988c7424d
commit
1c574cf93b
6 changed files with 286 additions and 45 deletions
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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")) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue