mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
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 -->
This commit is contained in:
commit
d17f27640b
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.
|
// 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 values::generics::svg::SVGLength;
|
use values::generics::svg::{SVGLength, SvgLengthOrPercentageOrNumber};
|
||||||
use gecko_bindings::structs::nsStyleSVG_${ident.upper()}_CONTEXT as CONTEXT_VALUE;
|
use gecko_bindings::structs::nsStyleSVG_${ident.upper()}_CONTEXT as CONTEXT_VALUE;
|
||||||
let length = match v {
|
let length = match v {
|
||||||
SVGLength::Length(length) => {
|
SVGLength::Length(length) => {
|
||||||
|
@ -604,9 +604,10 @@ def set_gecko_property(ffi_name, expr):
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match length {
|
match length {
|
||||||
Either::First(number) =>
|
SvgLengthOrPercentageOrNumber::LengthOrPercentage(lop) =>
|
||||||
self.gecko.${gecko_ffi_name}.set_value(CoordDataValue::Factor(From::from(number))),
|
self.gecko.${gecko_ffi_name}.set(lop),
|
||||||
Either::Second(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 {
|
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 values::computed::LengthOrPercentage;
|
||||||
use gecko_bindings::structs::nsStyleSVG_${ident.upper()}_CONTEXT as CONTEXT_VALUE;
|
use 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() {
|
let length = match self.gecko.${gecko_ffi_name}.as_value() {
|
||||||
CoordDataValue::Factor(number) => Either::First(From::from(number)),
|
CoordDataValue::Factor(number) =>
|
||||||
CoordDataValue::Coord(coord) => Either::Second(From::from(LengthOrPercentage::Length(Au(coord)))),
|
SvgLengthOrPercentageOrNumber::Number(number),
|
||||||
CoordDataValue::Percent(p) => Either::Second(From::from(LengthOrPercentage::Percentage(Percentage(p)))),
|
CoordDataValue::Coord(coord) =>
|
||||||
CoordDataValue::Calc(calc) => Either::Second(From::from(LengthOrPercentage::Calc(calc.into()))),
|
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}",
|
_ => unreachable!("Unexpected coordinate {:?} in ${ident}",
|
||||||
self.gecko.${gecko_ffi_name}.as_value()),
|
self.gecko.${gecko_ffi_name}.as_value()),
|
||||||
};
|
};
|
||||||
SVGLength::Length(length)
|
SVGLength::Length(length.into())
|
||||||
}
|
}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
@ -5141,7 +5149,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 gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE;
|
use gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE;
|
||||||
use values::generics::svg::SVGStrokeDashArray;
|
use values::generics::svg::{SVGStrokeDashArray, SvgLengthOrPercentageOrNumber};
|
||||||
|
|
||||||
match v {
|
match v {
|
||||||
SVGStrokeDashArray::Values(v) => {
|
SVGStrokeDashArray::Values(v) => {
|
||||||
|
@ -5152,8 +5160,10 @@ clip-path
|
||||||
}
|
}
|
||||||
for (gecko, servo) in self.gecko.mStrokeDasharray.iter_mut().zip(v) {
|
for (gecko, servo) in self.gecko.mStrokeDasharray.iter_mut().zip(v) {
|
||||||
match servo {
|
match servo {
|
||||||
Either::First(number) => gecko.set_value(CoordDataValue::Factor(number.into())),
|
SvgLengthOrPercentageOrNumber::LengthOrPercentage(lop) =>
|
||||||
Either::Second(lop) => gecko.set(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 {
|
pub fn clone_stroke_dasharray(&self) -> longhands::stroke_dasharray::computed_value::T {
|
||||||
use gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE;
|
use gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE;
|
||||||
use values::computed::LengthOrPercentage;
|
use values::computed::LengthOrPercentage;
|
||||||
use values::generics::svg::SVGStrokeDashArray;
|
use values::generics::svg::{SVGStrokeDashArray, SvgLengthOrPercentageOrNumber};
|
||||||
|
|
||||||
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);
|
||||||
|
@ -5192,13 +5202,17 @@ clip-path
|
||||||
let mut vec = vec![];
|
let mut vec = vec![];
|
||||||
for gecko in self.gecko.mStrokeDasharray.iter() {
|
for gecko in self.gecko.mStrokeDasharray.iter() {
|
||||||
match gecko.as_value() {
|
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) =>
|
CoordDataValue::Coord(coord) =>
|
||||||
vec.push(Either::Second(LengthOrPercentage::Length(Au(coord)).into())),
|
vec.push(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
|
||||||
|
LengthOrPercentage::Length(Au(coord)).into())),
|
||||||
CoordDataValue::Percent(p) =>
|
CoordDataValue::Percent(p) =>
|
||||||
vec.push(Either::Second(LengthOrPercentage::Percentage(Percentage(p)).into())),
|
vec.push(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
|
||||||
|
LengthOrPercentage::Percentage(Percentage(p)).into())),
|
||||||
CoordDataValue::Calc(calc) =>
|
CoordDataValue::Calc(calc) =>
|
||||||
vec.push(Either::Second(LengthOrPercentage::Calc(calc.into()).into())),
|
vec.push(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
|
||||||
|
LengthOrPercentage::Calc(calc.into()).into())),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,18 +43,20 @@ use values::animated::effects::BoxShadowList as AnimatedBoxShadowList;
|
||||||
use values::animated::effects::Filter as AnimatedFilter;
|
use values::animated::effects::Filter as AnimatedFilter;
|
||||||
use values::animated::effects::FilterList as AnimatedFilterList;
|
use values::animated::effects::FilterList as AnimatedFilterList;
|
||||||
use values::animated::effects::TextShadowList as AnimatedTextShadowList;
|
use values::animated::effects::TextShadowList as AnimatedTextShadowList;
|
||||||
use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
|
use values::computed::{Angle, BorderCornerRadius, CalcLengthOrPercentage};
|
||||||
use values::computed::{BorderCornerRadius, ClipRect};
|
use values::computed::{ClipRect, Context, ComputedUrl, ComputedValueAsSpecified};
|
||||||
use values::computed::{CalcLengthOrPercentage, Context, ComputedValueAsSpecified, ComputedUrl};
|
use values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||||
use values::computed::{LengthOrPercentage, MaxLength, MozLength, Percentage, ToComputedValue};
|
use values::computed::{LengthOrPercentageOrNone, MaxLength, MozLength, NonNegativeAu};
|
||||||
use values::computed::{NonNegativeAu, NonNegativeNumber, PositiveIntegerOrAuto};
|
use values::computed::{NonNegativeNumber, Number, NumberOrPercentage, Percentage};
|
||||||
|
use values::computed::{PositiveIntegerOrAuto, ToComputedValue};
|
||||||
use values::computed::length::{NonNegativeLengthOrAuto, NonNegativeLengthOrNormal};
|
use values::computed::length::{NonNegativeLengthOrAuto, NonNegativeLengthOrNormal};
|
||||||
use values::computed::length::NonNegativeLengthOrPercentage;
|
use values::computed::length::NonNegativeLengthOrPercentage;
|
||||||
use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||||
use values::generics::{GreaterThanOrEqualToOne, NonNegative};
|
use values::generics::{GreaterThanOrEqualToOne, NonNegative};
|
||||||
use values::generics::effects::Filter;
|
use values::generics::effects::Filter;
|
||||||
use values::generics::position as generic_position;
|
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.
|
/// A trait used to implement various procedures used during animation.
|
||||||
pub trait Animatable: Sized {
|
pub trait Animatable: Sized {
|
||||||
|
@ -781,6 +783,7 @@ impl ToAnimatedZero for AnimationValue {
|
||||||
impl RepeatableListAnimatable for LengthOrPercentage {}
|
impl RepeatableListAnimatable for LengthOrPercentage {}
|
||||||
impl RepeatableListAnimatable for Either<f32, LengthOrPercentage> {}
|
impl RepeatableListAnimatable for Either<f32, LengthOrPercentage> {}
|
||||||
impl RepeatableListAnimatable for Either<NonNegativeNumber, NonNegativeLengthOrPercentage> {}
|
impl RepeatableListAnimatable for Either<NonNegativeNumber, NonNegativeLengthOrPercentage> {}
|
||||||
|
impl RepeatableListAnimatable for SvgLengthOrPercentageOrNumber<NonNegativeLengthOrPercentage, NonNegativeNumber> {}
|
||||||
|
|
||||||
macro_rules! repeated_vec_impl {
|
macro_rules! repeated_vec_impl {
|
||||||
($($ty:ty),*) => {
|
($($ty:ty),*) => {
|
||||||
|
@ -1016,7 +1019,12 @@ impl Animatable for LengthOrPercentage {
|
||||||
impl ToAnimatedZero for LengthOrPercentage {
|
impl ToAnimatedZero for LengthOrPercentage {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_animated_zero(&self) -> Result<Self, ()> {
|
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>
|
impl<LengthType> Animatable for SVGLength<LengthType>
|
||||||
where LengthType: Animatable + Clone
|
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>
|
impl<LengthType> Animatable for SVGStrokeDashArray<LengthType>
|
||||||
where LengthType : RepeatableListAnimatable + Clone
|
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>
|
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 {
|
impl NonNegativeLengthOrPercentage {
|
||||||
/// Get zero value.
|
/// Get zero value.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
//! Computed types for SVG properties.
|
//! Computed types for SVG properties.
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use values::{Either, RGBA};
|
use values::RGBA;
|
||||||
use values::computed::{LengthOrPercentageOrNumber, Opacity};
|
use values::computed::{ComputedUrl, LengthOrPercentage, NonNegativeAu};
|
||||||
use values::computed::{NonNegativeAu, NonNegativeLengthOrPercentageOrNumber};
|
use values::computed::{NonNegativeNumber, NonNegativeLengthOrPercentage, Number};
|
||||||
use values::computed::ComputedUrl;
|
use values::computed::Opacity;
|
||||||
use values::generics::svg as generic;
|
use values::generics::svg as generic;
|
||||||
|
|
||||||
/// Computed SVG Paint value
|
/// 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
|
/// <length> | <percentage> | <number> | context-value
|
||||||
pub type SVGLength = generic::SVGLength<LengthOrPercentageOrNumber>;
|
pub type SVGLength = generic::SVGLength<SvgLengthOrPercentageOrNumber>;
|
||||||
|
|
||||||
impl From<Au> for SVGLength {
|
impl From<Au> for SVGLength {
|
||||||
fn from(length: Au) -> Self {
|
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.
|
/// An non-negative wrapper of SVGLength.
|
||||||
pub type SVGWidth = generic::SVGLength<NonNegativeLengthOrPercentageOrNumber>;
|
pub type SVGWidth = generic::SVGLength<NonNegativeSvgLengthOrPercentageOrNumber>;
|
||||||
|
|
||||||
impl From<NonNegativeAu> for SVGWidth {
|
impl From<NonNegativeAu> for SVGWidth {
|
||||||
fn from(length: NonNegativeAu) -> Self {
|
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
|
/// [ <length> | <percentage> | <number> ]# | context-value
|
||||||
pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeLengthOrPercentageOrNumber>;
|
pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeSvgLengthOrPercentageOrNumber>;
|
||||||
|
|
||||||
impl Default for SVGStrokeDashArray {
|
impl Default for SVGStrokeDashArray {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
|
|
@ -8,6 +8,8 @@ use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::{ParseError, StyleParseError, ToCss};
|
use style_traits::{ParseError, StyleParseError, ToCss};
|
||||||
|
use values::computed::length::LengthOrPercentage;
|
||||||
|
|
||||||
|
|
||||||
/// An SVG paint value
|
/// 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.
|
/// An SVG length value supports `context-value` in addition to length.
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, PartialEq)]
|
#[derive(Clone, ComputeSquaredDistance, Copy, Debug, PartialEq)]
|
||||||
|
|
|
@ -8,7 +8,8 @@ use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
use style_traits::{CommaWithSpace, ParseError, Separator, StyleParseError};
|
use style_traits::{CommaWithSpace, ParseError, Separator, StyleParseError};
|
||||||
use values::generics::svg as generic;
|
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;
|
use values::specified::color::RGBAColor;
|
||||||
|
|
||||||
/// Specified SVG Paint value
|
/// 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())
|
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
|
/// <length> | <percentage> | <number> | context-value
|
||||||
pub type SVGLength = generic::SVGLength<LengthOrPercentageOrNumber>;
|
pub type SVGLength = generic::SVGLength<SvgLengthOrPercentageOrNumber>;
|
||||||
|
|
||||||
impl Parse for SVGLength {
|
impl Parse for SVGLength {
|
||||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
-> Result<Self, ParseError<'i>> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
input.try(|i| LengthOrPercentageOrNumber::parse(context, i))
|
input.try(|i| SvgLengthOrPercentageOrNumber::parse(context, i))
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
.or_else(|_| parse_context_value(input, generic::SVGLength::ContextValue))
|
.or_else(|_| parse_context_value(input, generic::SVGLength::ContextValue))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<LengthOrPercentageOrNumber> for SVGLength {
|
impl From<SvgLengthOrPercentageOrNumber> for SVGLength {
|
||||||
fn from(length: LengthOrPercentageOrNumber) -> Self {
|
fn from(length: SvgLengthOrPercentageOrNumber) -> Self {
|
||||||
generic::SVGLength::Length(length)
|
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.
|
/// A non-negative version of SVGLength.
|
||||||
pub type SVGWidth = generic::SVGLength<NonNegativeLengthOrPercentageOrNumber>;
|
pub type SVGWidth = generic::SVGLength<NonNegativeSvgLengthOrPercentageOrNumber>;
|
||||||
|
|
||||||
impl Parse for SVGWidth {
|
impl Parse for SVGWidth {
|
||||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
-> Result<Self, ParseError<'i>> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
input.try(|i| NonNegativeLengthOrPercentageOrNumber::parse(context, i))
|
input.try(|i| NonNegativeSvgLengthOrPercentageOrNumber::parse(context, i))
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
.or_else(|_| parse_context_value(input, generic::SVGLength::ContextValue))
|
.or_else(|_| parse_context_value(input, generic::SVGLength::ContextValue))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NonNegativeLengthOrPercentageOrNumber> for SVGWidth {
|
impl From<NonNegativeSvgLengthOrPercentageOrNumber> for SVGWidth {
|
||||||
fn from(length: NonNegativeLengthOrPercentageOrNumber) -> Self {
|
fn from(length: NonNegativeSvgLengthOrPercentageOrNumber) -> Self {
|
||||||
generic::SVGLength::Length(length)
|
generic::SVGLength::Length(length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [ <length> | <percentage> | <number> ]# | context-value
|
/// [ <length> | <percentage> | <number> ]# | context-value
|
||||||
pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeLengthOrPercentageOrNumber>;
|
pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeSvgLengthOrPercentageOrNumber>;
|
||||||
|
|
||||||
impl Parse for SVGStrokeDashArray {
|
impl Parse for SVGStrokeDashArray {
|
||||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
-> Result<Self, ParseError<'i>> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(values) = input.try(|i| CommaWithSpace::parse(i, |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))
|
Ok(generic::SVGStrokeDashArray::Values(values))
|
||||||
} else if let Ok(_) = input.try(|i| i.expect_ident_matching("none")) {
|
} else if let Ok(_) = input.try(|i| i.expect_ident_matching("none")) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue