diff --git a/gfx/layers/AnimationHelper.cpp b/gfx/layers/AnimationHelper.cpp index d91d9c540d8e..781dcf0d7302 100644 --- a/gfx/layers/AnimationHelper.cpp +++ b/gfx/layers/AnimationHelper.cpp @@ -20,9 +20,11 @@ #include "mozilla/layers/APZSampler.h" // for APZSampler #include "mozilla/layers/CompositorThread.h" // for CompositorThreadHolder #include "mozilla/LayerAnimationInfo.h" // for GetCSSPropertiesFor() +#include "mozilla/Maybe.h" // for Maybe<> #include "mozilla/MotionPathUtils.h" // for ResolveMotionPath() #include "mozilla/ServoBindings.h" // for Servo_ComposeAnimationSegment, etc #include "mozilla/StyleAnimationValue.h" // for StyleAnimationValue, etc +#include "nsCSSPropertyID.h" // for eCSSProperty_offset_path, etc #include "nsDeviceContext.h" // for AppUnitsPerCSSPixel #include "nsDisplayList.h" // for nsDisplayTransform, etc @@ -498,8 +500,8 @@ AnimationStorageData AnimationHelper::ExtractAnimations( "Fixed offset-path should have base style"); MOZ_ASSERT(HasTransformLikeAnimations(aAnimations)); - AnimationValue value{currData->mBaseStyle}; - const StyleOffsetPath& offsetPath = value.GetOffsetPathProperty(); + const StyleOffsetPath& offsetPath = + animation.baseStyle().get_StyleOffsetPath(); // FIXME: Bug 1837042. Cache all basic shapes. if (offsetPath.IsOffsetPath() && offsetPath.AsOffsetPath().path->IsShape() && @@ -618,7 +620,7 @@ gfx::Matrix4x4 AnimationHelper::ServoAnimationValueToMatrix4x4( const StyleRotate* rotate = nullptr; const StyleScale* scale = nullptr; const StyleTransform* transform = nullptr; - const StyleOffsetPath* path = nullptr; + Maybe path; const StyleLengthPercentage* distance = nullptr; const StyleOffsetRotate* offsetRotate = nullptr; const StylePositionOrAuto* anchor = nullptr; @@ -646,7 +648,8 @@ gfx::Matrix4x4 AnimationHelper::ServoAnimationValueToMatrix4x4( break; case eCSSProperty_offset_path: MOZ_ASSERT(!path); - path = Servo_AnimationValue_GetOffsetPath(value); + path.emplace(StyleOffsetPath::None()); + Servo_AnimationValue_GetOffsetPath(value, path.ptr()); break; case eCSSProperty_offset_distance: MOZ_ASSERT(!distance); @@ -671,7 +674,7 @@ gfx::Matrix4x4 AnimationHelper::ServoAnimationValueToMatrix4x4( TransformReferenceBox refBox(nullptr, aTransformData.bounds()); Maybe motion = MotionPathUtils::ResolveMotionPath( - path, distance, offsetRotate, anchor, position, + path.ptrOr(nullptr), distance, offsetRotate, anchor, position, aTransformData.motionPathData(), refBox, aCachedMotionPath); // We expect all our transform data to arrive in device pixels diff --git a/gfx/layers/AnimationInfo.cpp b/gfx/layers/AnimationInfo.cpp index 2e08be90bd34..e56d5dabf076 100644 --- a/gfx/layers/AnimationInfo.cpp +++ b/gfx/layers/AnimationInfo.cpp @@ -333,18 +333,6 @@ static Maybe GetScrollTimelineOptions( return Some(ScrollTimelineOptions(source, timeline->Axis())); } -static StyleOffsetPath NormalizeOffsetPath(const StyleOffsetPath& aOffsetPath) { - // Named Return Value Optimization. - StyleOffsetPath result(aOffsetPath); - if (aOffsetPath.IsOffsetPath() && - aOffsetPath.AsOffsetPath().path->IsShape() && - aOffsetPath.AsOffsetPath().path->AsShape().IsPath()) { - result.UpdateShapePath(MotionPathUtils::NormalizeSVGPathData( - aOffsetPath.AsOffsetPath().path->AsShape().AsPath().path)); - } - return result; -} - static void SetAnimatable(nsCSSPropertyID aProperty, const AnimationValue& aAnimationValue, nsIFrame* aFrame, TransformReferenceBox& aRefBox, @@ -383,8 +371,8 @@ static void SetAnimatable(nsCSSPropertyID aProperty, aAnimationValue.GetTransformProperty(), aRefBox); break; case eCSSProperty_offset_path: - aAnimatable = - NormalizeOffsetPath(aAnimationValue.GetOffsetPathProperty()); + aAnimatable = StyleOffsetPath::None(); + aAnimationValue.GetOffsetPathProperty(aAnimatable.get_StyleOffsetPath()); break; case eCSSProperty_offset_distance: aAnimatable = aAnimationValue.GetOffsetDistanceProperty(); @@ -866,7 +854,7 @@ void AnimationInfo::AddNonAnimatingTransformLikePropertiesStyles( break; case eCSSProperty_offset_path: if (!display->mOffsetPath.IsNone()) { - appendFakeAnimation(id, NormalizeOffsetPath(display->mOffsetPath)); + appendFakeAnimation(id, display->mOffsetPath); } break; case eCSSProperty_offset_distance: diff --git a/layout/base/MotionPathUtils.cpp b/layout/base/MotionPathUtils.cpp index 2349d68d5020..aef3e345f798 100644 --- a/layout/base/MotionPathUtils.cpp +++ b/layout/base/MotionPathUtils.cpp @@ -486,14 +486,6 @@ Maybe MotionPathUtils::ResolveMotionPath( aRefBox, aMotionPathData->anchorAdjustment()); } -/* static */ -StyleSVGPathData MotionPathUtils::NormalizeSVGPathData( - const StyleSVGPathData& aPath) { - StyleSVGPathData n; - Servo_SVGPathData_Normalize(&aPath, &n); - return n; -} - /* static */ already_AddRefed MotionPathUtils::BuildPath( const StyleSVGPathData& aPath, gfx::PathBuilder* aPathBuilder) { diff --git a/layout/base/MotionPathUtils.h b/layout/base/MotionPathUtils.h index 6af102ca5198..e808b0dd6060 100644 --- a/layout/base/MotionPathUtils.h +++ b/layout/base/MotionPathUtils.h @@ -204,17 +204,6 @@ class MotionPathUtils final { const Maybe& aMotionPathData, TransformReferenceBox&, gfx::Path* aCachedMotionPath); - /** - * Normalize StyleSVGPathData. - * - * The algorithm of normalization is the same as normalize() in - * servo/components/style/values/specified/svg_path.rs - * FIXME: Bug 1489392: We don't have to normalize the path here if we accept - * the spec issue which would like to normalize svg paths at computed time. - * https://github.com/w3c/svgwg/issues/321 - */ - static StyleSVGPathData NormalizeSVGPathData(const StyleSVGPathData& aPath); - /** * Build a gfx::Path from the computed svg path. We should give it a path * builder. If |aPathBuilder| is nullptr, we return null path. diff --git a/layout/style/StyleAnimationValue.cpp b/layout/style/StyleAnimationValue.cpp index f461368ce2c5..bdb351b0b4bc 100644 --- a/layout/style/StyleAnimationValue.cpp +++ b/layout/style/StyleAnimationValue.cpp @@ -87,9 +87,9 @@ const StyleTransform& AnimationValue::GetTransformProperty() const { return *Servo_AnimationValue_GetTransform(mServo); } -const mozilla::StyleOffsetPath& AnimationValue::GetOffsetPathProperty() const { +void AnimationValue::GetOffsetPathProperty(StyleOffsetPath& aOffsetPath) const { MOZ_ASSERT(mServo); - return *Servo_AnimationValue_GetOffsetPath(mServo); + Servo_AnimationValue_GetOffsetPath(mServo, &aOffsetPath); } const mozilla::LengthPercentage& AnimationValue::GetOffsetDistanceProperty() diff --git a/layout/style/StyleAnimationValue.h b/layout/style/StyleAnimationValue.h index 6d03d30e6ee6..a55ac455b566 100644 --- a/layout/style/StyleAnimationValue.h +++ b/layout/style/StyleAnimationValue.h @@ -77,7 +77,10 @@ struct AnimationValue { const mozilla::StyleRotate& GetRotateProperty() const; // Motion path properties. - const mozilla::StyleOffsetPath& GetOffsetPathProperty() const; + // Note: This clones the StyleOffsetPath object from its AnimatedValue, so + // this may be expensive if the path is a complex SVG path or polygon. The + // caller should be aware of this performance impact. + void GetOffsetPathProperty(StyleOffsetPath& aOffsetPath) const; const mozilla::LengthPercentage& GetOffsetDistanceProperty() const; const mozilla::StyleOffsetRotate& GetOffsetRotateProperty() const; const mozilla::StylePositionOrAuto& GetOffsetAnchorProperty() const; diff --git a/servo/components/style/properties/longhands/box.mako.rs b/servo/components/style/properties/longhands/box.mako.rs index 5aff6673b872..4c5d8f83c27f 100644 --- a/servo/components/style/properties/longhands/box.mako.rs +++ b/servo/components/style/properties/longhands/box.mako.rs @@ -216,7 +216,7 @@ ${helpers.predefined_type( "OffsetPath", "computed::OffsetPath::none()", engines="gecko", - animation_value_type="ComputedValue", + animation_value_type="motion::OffsetPath", gecko_pref="layout.css.motion-path.enabled", flags="CAN_ANIMATE_ON_COMPOSITOR", spec="https://drafts.fxtf.org/motion-1/#offset-path-property", diff --git a/servo/components/style/values/generics/basic_shape.rs b/servo/components/style/values/generics/basic_shape.rs index f5eb0c5788f5..175a0f75eb00 100644 --- a/servo/components/style/values/generics/basic_shape.rs +++ b/servo/components/style/values/generics/basic_shape.rs @@ -367,7 +367,9 @@ pub struct PolygonCoord(pub LengthPercentage, pub LengthPercen #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[derive( + Animate, Clone, + ComputeSquaredDistance, Copy, Debug, Deserialize, @@ -413,7 +415,6 @@ pub enum FillRule { pub struct Path { /// The filling rule for the svg path. #[css(skip_if = "is_default")] - #[animation(constant)] pub fill: FillRule, /// The svg path data. pub path: SVGPathData, diff --git a/servo/components/style/values/generics/motion.rs b/servo/components/style/values/generics/motion.rs index a5ac34ba3291..c7f675c36d7e 100644 --- a/servo/components/style/values/generics/motion.rs +++ b/servo/components/style/values/generics/motion.rs @@ -26,6 +26,7 @@ use style_traits::{CssWriter, ToCss}; PartialEq, Serialize, SpecifiedValueInfo, + ToAnimatedValue, ToComputedValue, ToCss, ToResolvedValue, @@ -53,6 +54,7 @@ pub enum RaySize { PartialEq, Serialize, SpecifiedValueInfo, + ToAnimatedValue, ToComputedValue, ToResolvedValue, ToShmem, @@ -118,6 +120,7 @@ where PartialEq, Serialize, SpecifiedValueInfo, + ToAnimatedValue, ToComputedValue, ToCss, ToResolvedValue, @@ -150,6 +153,7 @@ pub use self::GenericOffsetPathFunction as OffsetPathFunction; PartialEq, Serialize, SpecifiedValueInfo, + ToAnimatedValue, ToComputedValue, ToCss, ToResolvedValue, diff --git a/servo/components/style/values/specified/motion.rs b/servo/components/style/values/specified/motion.rs index 751c5bbf3653..40f5d588c424 100644 --- a/servo/components/style/values/specified/motion.rs +++ b/servo/components/style/values/specified/motion.rs @@ -45,6 +45,7 @@ pub type OffsetPosition = generics::GenericOffsetPositionToAddRefed())}; } """ - -"GenericOffsetPath" = """ - void UpdateShapePath(const StyleSVGPathData& aPath) { - MOZ_ASSERT(IsOffsetPath() && AsOffsetPath().path->IsShape() && - AsOffsetPath().path->AsShape().IsPath(), - "Only for path()"); - offset_path.path->shape._0.path._0.path = aPath; - } -""" diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs index 6dfdf04f386d..39e62b786fe4 100644 --- a/servo/ports/geckolib/glue.rs +++ b/servo/ports/geckolib/glue.rs @@ -816,9 +816,13 @@ pub unsafe extern "C" fn Servo_AnimationValue_GetTransform( #[no_mangle] pub unsafe extern "C" fn Servo_AnimationValue_GetOffsetPath( value: &AnimationValue, -) -> *const computed::motion::OffsetPath { + output: &mut computed::motion::OffsetPath, +) { + use style::values::animated::ToAnimatedValue; match *value { - AnimationValue::OffsetPath(ref value) => value, + AnimationValue::OffsetPath(ref value) => { + *output = ToAnimatedValue::from_animated_value(value.clone()) + }, _ => unreachable!("Expected offset-path"), } } @@ -893,7 +897,8 @@ pub unsafe extern "C" fn Servo_AnimationValue_Transform( pub unsafe extern "C" fn Servo_AnimationValue_OffsetPath( p: &computed::motion::OffsetPath, ) -> Strong { - Arc::new(AnimationValue::OffsetPath(p.clone())).into() + use style::values::animated::ToAnimatedValue; + Arc::new(AnimationValue::OffsetPath(p.clone().to_animated_value())).into() } #[no_mangle] @@ -1054,14 +1059,6 @@ impl_basic_serde_funcs!( ComputedTimingFunction ); -#[no_mangle] -pub extern "C" fn Servo_SVGPathData_Normalize( - input: &specified::SVGPathData, - output: &mut specified::SVGPathData, -) { - *output = input.normalize(); -} - // Return the ComputedValues by a base ComputedValues and the rules. fn resolve_rules_for_element_with_context<'a>( element: GeckoElement<'a>, diff --git a/testing/web-platform/meta/css/motion/animation/offset-path-interpolation-006.html.ini b/testing/web-platform/meta/css/motion/animation/offset-path-interpolation-006.html.ini index 99998afb5e92..6423c9683aaa 100644 --- a/testing/web-platform/meta/css/motion/animation/offset-path-interpolation-006.html.ini +++ b/testing/web-platform/meta/css/motion/animation/offset-path-interpolation-006.html.ini @@ -26,18 +26,6 @@ [CSS Transitions: property from [initial\] to [ellipse()\] at (0.3) should be [initial\]] expected: FAIL - [CSS Transitions: property from [inherit\] to [ellipse(40% 50% at 25% 25%)\] at (-0.3) should be [ellipse(1% 0% at 57.5% 57.5%)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [inherit\] to [ellipse(40% 50% at 25% 25%)\] at (-0.3) should be [ellipse(1% 0% at 57.5% 57.5%)\]] - expected: FAIL - - [CSS Animations: property from [inherit\] to [ellipse(40% 50% at 25% 25%)\] at (-0.3) should be [ellipse(1% 0% at 57.5% 57.5%)\]] - expected: FAIL - - [Web Animations: property from [inherit\] to [ellipse(40% 50% at 25% 25%)\] at (-0.3) should be [ellipse(1% 0% at 57.5% 57.5%)\]] - expected: FAIL - [CSS Transitions: property from [unset\] to [inset(10%)\] at (-0.3) should be [unset\]] expected: FAIL @@ -131,18 +119,6 @@ [Web Animations: property from [none\] to [rect(10px 10px 10px 10px)\] at (1.5) should be [rect(10px 10px 10px 10px)\]] expected: FAIL - [CSS Transitions: property from [inset(10px)\] to [inset(20px round 50%)\] at (-1) should be [inset(0px round 0%)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [inset(10px)\] to [inset(20px round 50%)\] at (-1) should be [inset(0px round 0%)\]] - expected: FAIL - - [CSS Animations: property from [inset(10px)\] to [inset(20px round 50%)\] at (-1) should be [inset(0px round 0%)\]] - expected: FAIL - - [Web Animations: property from [inset(10px)\] to [inset(20px round 50%)\] at (-1) should be [inset(0px round 0%)\]] - expected: FAIL - [CSS Transitions: property from [xywh(5px 5px 150% 150%)\] to [xywh(10px 10px 100% 100%)\] at (-1) should be [xywh(0px 0px 200% 200%)\]] expected: FAIL