Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an animated value for SvgLengthOrPercentageOrNumber. #18198

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -43,21 +43,21 @@ 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::animated::svg::SvgLengthOrPercentageOrNumber as AnimatedSvgLengthOrPercentageOrNumber;
use values::computed::{Angle, BorderCornerRadius, CalcLengthOrPercentage};
use values::computed::{ClipRect, Context, ComputedUrl, ComputedValueAsSpecified};
use values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
use values::computed::{LengthOrPercentageOrNone, MaxLength, NonNegativeAu};
use values::computed::{NonNegativeNumber, Number, NumberOrPercentage, Percentage};
use values::computed::{PositiveIntegerOrAuto, ToComputedValue};
#[cfg(feature = "gecko")] use values::computed::MozLength;
use values::computed::{NonNegativeNumber, Percentage, PositiveIntegerOrAuto};
use values::computed::ToComputedValue;
use values::computed::length::{NonNegativeLengthOrAuto, NonNegativeLengthOrNormal};
use values::computed::length::NonNegativeLengthOrPercentage;
use values::computed::transform::DirectionVector;
use values::distance::{ComputeSquaredDistance, SquaredDistance};
use values::generics::NonNegative;
use values::generics::effects::Filter;
use values::generics::position as generic_position;
use values::generics::svg::{SVGLength, SvgLengthOrPercentageOrNumber, SVGPaint};
use values::generics::svg::{SVGLength, SVGPaint};
use values::generics::svg::{SVGPaintKind, SVGStrokeDashArray, SVGOpacity};

/// https://drafts.csswg.org/css-transitions/#animtype-repeatable-list
@@ -713,7 +713,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> {}
impl RepeatableListAnimatable for AnimatedSvgLengthOrPercentageOrNumber {}

macro_rules! repeated_vec_impl {
($($ty:ty),*) => {
@@ -2277,106 +2277,6 @@ impl ToAnimatedZero for IntermediateSVGPaint {
}
}

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 <L, N> Animate for SvgLengthOrPercentageOrNumber<L, N>
where
L: Animate + From<LengthOrPercentage> + Into<NumberOrPercentage> + Copy,
N: Animate + From<Number> + Into<NumberOrPercentage>,
LengthOrPercentage: From<L>,
Self: Copy,
{
#[inline]
fn animate(&self, other: &Self, procedure: Procedure) -> 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 this = convert_to_number_or_percentage(*self);
let other = convert_to_number_or_percentage(*other);

match (this, other) {
(
NumberOrPercentage::Number(ref this),
NumberOrPercentage::Number(ref other),
) => {
Ok(convert_from_number_or_percentage(
NumberOrPercentage::Number(this.animate(other, procedure)?)
))
},
(
NumberOrPercentage::Percentage(ref this),
NumberOrPercentage::Percentage(ref other),
) => {
Ok(convert_from_number_or_percentage(
NumberOrPercentage::Percentage(this.animate(other, procedure)?)
))
},
_ => Err(()),
}
}
}

impl<L> Animate for SVGLength<L>
where
@@ -68,7 +68,7 @@ ${helpers.predefined_type(
"::values::computed::NonNegativeAu::from_px(1).into()",
products="gecko",
boxed="True",
animation_value_type="::values::computed::SVGWidth",
animation_value_type="<::values::computed::SVGWidth as ToAnimatedValue>::AnimatedValue",
spec="https://www.w3.org/TR/SVG2/painting.html#StrokeWidth")}

${helpers.single_keyword("stroke-linecap", "butt round square",
@@ -94,7 +94,7 @@ ${helpers.predefined_type(
"SVGStrokeDashArray",
"Default::default()",
products="gecko",
animation_value_type="::values::computed::SVGStrokeDashArray",
animation_value_type="<::values::computed::SVGStrokeDashArray as ToAnimatedValue>::AnimatedValue",
spec="https://www.w3.org/TR/SVG2/painting.html#StrokeDashing",
)}

@@ -103,7 +103,7 @@ ${helpers.predefined_type(
"Au(0).into()",
products="gecko",
boxed="True",
animation_value_type="ComputedValue",
animation_value_type="<::values::computed::SVGLength as ToAnimatedValue>::AnimatedValue",
spec="https://www.w3.org/TR/SVG2/painting.html#StrokeDashing")}

// Section 14 - Clipping, Masking and Compositing
@@ -27,6 +27,7 @@ use values::specified::url::SpecifiedUrl;

pub mod color;
pub mod effects;
pub mod svg;

/// Animate from one value to another.
///
@@ -0,0 +1,25 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Animated types for CSS values in SVG

use values::computed::{Number, Percentage};
use values::computed::length::CalcLengthOrPercentage;

/// Stroke-* value support unit less value, so servo interpolate length value as
/// number unlike computed value and specified value.
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, ToAnimatedZero)]
pub enum SvgLengthOrPercentageOrNumber {
/// Real number value.
Number(Number),
/// Percentage value.
Percentage(Percentage),
/// Calc value, this type can hold percentage value. For present, percentage
/// value store the Percentage type.(i.e. Servo doesn't use CalcLengthOrPercentage
/// for storing the percentage value)
/// TODO: We need to support interpolation of calc value.
/// https://bugzilla.mozilla.org/show_bug.cgi?id=1386967
#[animation(error)]
Calc(CalcLengthOrPercentage),
}
@@ -4,13 +4,16 @@

//! Generic types for CSS values in SVG

use app_units::Au;
use cssparser::Parser;
use parser::{Parse, ParserContext};
use std::fmt;
use style_traits::{ParseError, StyleParseError, ToCss};
use values::computed::NumberOrPercentage;
use values::computed::length::LengthOrPercentage;
use values::distance::{ComputeSquaredDistance, SquaredDistance};
use values::animated::ToAnimatedValue;
use values::animated::svg::SvgLengthOrPercentageOrNumber as AnimatedSvgLengthOrPercentageOrNumber;
use values::computed::{NonNegativeNumber, Number};
use values::computed::length::{CalcLengthOrPercentage, LengthOrPercentage};
use values::computed::length::NonNegativeLengthOrPercentage;

/// An SVG paint value
///
@@ -104,80 +107,111 @@ 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, ToAnimatedValue)]
#[derive(ToAnimatedZero, ToComputedValue, ToCss)]
pub enum SvgLengthOrPercentageOrNumber<LengthOrPercentage, Number> {
#[derive(Clone, Copy, Debug, PartialEq, ToComputedValue, ToCss)]
pub enum SvgLengthOrPercentageOrNumber<L, N> {
/// <length> | <percentage>
LengthOrPercentage(LengthOrPercentage),
LengthOrPercentage(L),
/// <number>
Number(Number),
Number(N),
}

impl<L, N> ComputeSquaredDistance for SvgLengthOrPercentageOrNumber<L, N>
/// Following From implements use for converting animated value.
impl<L, N> ToAnimatedValue for SvgLengthOrPercentageOrNumber<L, N>
where
L: ComputeSquaredDistance + Copy + Into<NumberOrPercentage>,
N: ComputeSquaredDistance + Copy + Into<NumberOrPercentage>
L: Into<AnimatedSvgLengthOrPercentageOrNumber> + From<LengthOrPercentage>,
N: Into<AnimatedSvgLengthOrPercentageOrNumber> + From<Number>
{
type AnimatedValue = AnimatedSvgLengthOrPercentageOrNumber;

#[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
match (self, other) {
(
&SvgLengthOrPercentageOrNumber::LengthOrPercentage(ref from),
&SvgLengthOrPercentageOrNumber::LengthOrPercentage(ref to)
) => {
from.compute_squared_distance(to)
},
(
&SvgLengthOrPercentageOrNumber::Number(ref from),
&SvgLengthOrPercentageOrNumber::Number(ref to)
) => {
from.compute_squared_distance(to)
fn to_animated_value(self) -> Self::AnimatedValue {
match self {
SvgLengthOrPercentageOrNumber::LengthOrPercentage(lop) => lop.into(),
SvgLengthOrPercentageOrNumber::Number(num) => num.into(),
}
}

#[inline]
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
match animated {
AnimatedSvgLengthOrPercentageOrNumber::Number(num) =>
{
SvgLengthOrPercentageOrNumber::Number(From::from(num))
},
(
&SvgLengthOrPercentageOrNumber::LengthOrPercentage(from),
&SvgLengthOrPercentageOrNumber::Number(to)
) => {
from.into().compute_squared_distance(&to.into())
AnimatedSvgLengthOrPercentageOrNumber::Percentage(p) =>
{
SvgLengthOrPercentageOrNumber::LengthOrPercentage(
From::from(LengthOrPercentage::Percentage(p)))
},
(
&SvgLengthOrPercentageOrNumber::Number(from),
&SvgLengthOrPercentageOrNumber::LengthOrPercentage(to)
) => {
from.into().compute_squared_distance(&to.into())
AnimatedSvgLengthOrPercentageOrNumber::Calc(calc) =>
{
SvgLengthOrPercentageOrNumber::LengthOrPercentage(
From::from(LengthOrPercentage::Calc(calc)))
},
}
}
}

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,
}
/// We need to a following conversion bounds for converting to an animated
/// value of SvgLengthOrPercentageOrNumber.
impl From<NonNegativeLengthOrPercentage> for AnimatedSvgLengthOrPercentageOrNumber {
fn from(lop: NonNegativeLengthOrPercentage) -> AnimatedSvgLengthOrPercentageOrNumber {
lop.0.into()
}
}

impl From<NonNegativeNumber> for AnimatedSvgLengthOrPercentageOrNumber {
fn from(num: NonNegativeNumber) -> AnimatedSvgLengthOrPercentageOrNumber {
num.0.into()
}
}

impl From<LengthOrPercentage> for AnimatedSvgLengthOrPercentageOrNumber {
fn from(lop: LengthOrPercentage) -> AnimatedSvgLengthOrPercentageOrNumber {
match lop {
LengthOrPercentage::Length(len) => {
AnimatedSvgLengthOrPercentageOrNumber::Number(len.to_f32_px())
},
LengthOrPercentage::Percentage(p) => {
AnimatedSvgLengthOrPercentageOrNumber::Percentage(p)
},
_ => false,
LengthOrPercentage::Calc(calc) => {
AnimatedSvgLengthOrPercentageOrNumber::Calc(calc.into())
},
}
}

}

impl From<Number> for AnimatedSvgLengthOrPercentageOrNumber {
fn from(num: Number) -> AnimatedSvgLengthOrPercentageOrNumber {
AnimatedSvgLengthOrPercentageOrNumber::Number(num)
}
}

impl From<AnimatedSvgLengthOrPercentageOrNumber> for CalcLengthOrPercentage {
fn from(nopoc: AnimatedSvgLengthOrPercentageOrNumber) -> CalcLengthOrPercentage {
match nopoc {
AnimatedSvgLengthOrPercentageOrNumber::Number(num) =>
CalcLengthOrPercentage::new(Au::from_f32_px(num), None),
AnimatedSvgLengthOrPercentageOrNumber::Percentage(p) =>
CalcLengthOrPercentage::new(Au(0), Some(p)),
AnimatedSvgLengthOrPercentageOrNumber::Calc(calc) =>
calc.into(),
}
}
}

/// 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> {
impl <L: Parse, N: Parse> Parse for SvgLengthOrPercentageOrNumber<L, N> {
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)) {
if let Ok(num) = input.try(|i| N::parse(context, i)) {
return Ok(SvgLengthOrPercentageOrNumber::Number(num));
}

if let Ok(lop) = input.try(|i| LengthOrPercentageType::parse(context, i)) {
if let Ok(lop) = input.try(|i| L::parse(context, i)) {
return Ok(SvgLengthOrPercentageOrNumber::LengthOrPercentage(lop));
}
Err(StyleParseError::UnspecifiedError.into())
@@ -198,7 +232,8 @@ pub enum SVGLength<LengthType> {

/// Generic value for stroke-dasharray.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, ComputeSquaredDistance, Debug, PartialEq, ToAnimatedValue, ToComputedValue)]
#[derive(Clone, ComputeSquaredDistance, Debug, PartialEq)]
#[derive(ToAnimatedValue, ToComputedValue)]
pub enum SVGStrokeDashArray<LengthType> {
/// `[ <length> | <percentage> | <number> ]#`
Values(Vec<LengthType>),
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.