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 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Prev

Add animated value for stroke-*.

SMIL animation which fill mode equal 'freeze' will use the specified from/to value,
current servo use SvgLengthOrPercentageOrNumber, so animated value when an animation
is finished will be LengthOrPercentage value.

i.e.
 If we animate between '20' and '10px'(<animate from='20' to='10px' fill='freeze'>):
    0%   -> 20
    50%  -> 15
    100% -> 10px

 The result of computed value contains unit since smil use specified 'to' value.

SMIL implementation of gecko side will call Servo_ParseProperty when specified
fill='freeze' and animation finished.

So this PR add animated value for stroke-* property. This animated value
contains the calc() value, but gecko side implementation doesn't support calc().
For detail, see https://bugzilla.mozilla.org/show_bug.cgi?id=1386967.
  • Loading branch information
mantaroh committed Sep 1, 2017
commit b375d2c3ea4dd5abde943677c3c72bd7db208f46
@@ -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,112 +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<L, N>(from: SvgLengthOrPercentageOrNumber<L, N>)
-> NumberOrPercentage
where
L: Into<NumberOrPercentage>,
N: Into<NumberOrPercentage>
{
match from {
SvgLengthOrPercentageOrNumber::LengthOrPercentage(lop) =>
{
lop.into()
}
SvgLengthOrPercentageOrNumber::Number(num) =>
{
num.into()
}
}
}

fn convert_from_number_or_percentage<L, N>(from: NumberOrPercentage)
-> SvgLengthOrPercentageOrNumber<L, N>
where
L: From<LengthOrPercentage>,
N: From<Number>
{
match from {
NumberOrPercentage::Number(num) =>
SvgLengthOrPercentageOrNumber::Number(From::from(num)),
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,65 +107,97 @@ 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)]
#[derive(Clone, Copy, Debug, PartialEq, ToComputedValue, ToCss)]
pub enum SvgLengthOrPercentageOrNumber<L, N> {
/// <length> | <percentage>
LengthOrPercentage(L),
/// <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<L, N> SvgLengthOrPercentageOrNumber<L, N>
where
L: Into<LengthOrPercentage> + Copy
{
/// return true if this struct has calc value.
pub fn has_calc(&self) -> bool {
match self {
&SvgLengthOrPercentageOrNumber::LengthOrPercentage(lop) => {
match lop.into() {
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(),
}
}
}
@@ -197,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.