summaryrefslogtreecommitdiffstats
path: root/layout/style/StyleAnimationValue.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'layout/style/StyleAnimationValue.cpp')
-rw-r--r--layout/style/StyleAnimationValue.cpp284
1 files changed, 284 insertions, 0 deletions
diff --git a/layout/style/StyleAnimationValue.cpp b/layout/style/StyleAnimationValue.cpp
new file mode 100644
index 0000000000..b87fb5f21b
--- /dev/null
+++ b/layout/style/StyleAnimationValue.cpp
@@ -0,0 +1,284 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/* Utilities for animation of computed style values */
+
+#include "mozilla/StyleAnimationValue.h"
+
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/MathAlgorithms.h"
+#include "mozilla/PresShell.h"
+#include "mozilla/PresShellInlines.h"
+#include "mozilla/ServoStyleSet.h"
+
+#include "mozilla/UniquePtr.h"
+#include "nsCOMArray.h"
+#include "nsString.h"
+#include "mozilla/ComputedStyle.h"
+#include "nsComputedDOMStyle.h"
+#include "nsCSSPseudoElements.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/FloatingPoint.h"
+#include "mozilla/Likely.h"
+#include "mozilla/ServoBindings.h" // StyleLockedDeclarationBlock
+#include "mozilla/ServoCSSParser.h"
+#include "gfxMatrix.h"
+#include "gfxQuaternion.h"
+#include "mozilla/dom/Document.h"
+#include "nsIFrame.h"
+#include "gfx2DGlue.h"
+#include "mozilla/ComputedStyleInlines.h"
+#include "mozilla/layers/LayersMessages.h"
+
+using namespace mozilla;
+using namespace mozilla::css;
+using namespace mozilla::dom;
+using namespace mozilla::gfx;
+
+bool AnimationValue::operator==(const AnimationValue& aOther) const {
+ if (mServo && aOther.mServo) {
+ return Servo_AnimationValue_DeepEqual(mServo, aOther.mServo);
+ }
+ if (!mServo && !aOther.mServo) {
+ return true;
+ }
+ return false;
+}
+
+bool AnimationValue::operator!=(const AnimationValue& aOther) const {
+ return !operator==(aOther);
+}
+
+float AnimationValue::GetOpacity() const {
+ MOZ_ASSERT(mServo);
+ return Servo_AnimationValue_GetOpacity(mServo);
+}
+
+nscolor AnimationValue::GetColor(nscolor aForegroundColor) const {
+ MOZ_ASSERT(mServo);
+ return Servo_AnimationValue_GetColor(mServo, aForegroundColor);
+}
+
+bool AnimationValue::IsCurrentColor() const {
+ MOZ_ASSERT(mServo);
+ return Servo_AnimationValue_IsCurrentColor(mServo);
+}
+
+const StyleTranslate& AnimationValue::GetTranslateProperty() const {
+ MOZ_ASSERT(mServo);
+ return *Servo_AnimationValue_GetTranslate(mServo);
+}
+
+const StyleRotate& AnimationValue::GetRotateProperty() const {
+ MOZ_ASSERT(mServo);
+ return *Servo_AnimationValue_GetRotate(mServo);
+}
+
+const StyleScale& AnimationValue::GetScaleProperty() const {
+ MOZ_ASSERT(mServo);
+ return *Servo_AnimationValue_GetScale(mServo);
+}
+
+const StyleTransform& AnimationValue::GetTransformProperty() const {
+ MOZ_ASSERT(mServo);
+ return *Servo_AnimationValue_GetTransform(mServo);
+}
+
+void AnimationValue::GetOffsetPathProperty(StyleOffsetPath& aOffsetPath) const {
+ MOZ_ASSERT(mServo);
+ Servo_AnimationValue_GetOffsetPath(mServo, &aOffsetPath);
+}
+
+const mozilla::LengthPercentage& AnimationValue::GetOffsetDistanceProperty()
+ const {
+ MOZ_ASSERT(mServo);
+ return *Servo_AnimationValue_GetOffsetDistance(mServo);
+}
+
+const mozilla::StyleOffsetRotate& AnimationValue::GetOffsetRotateProperty()
+ const {
+ MOZ_ASSERT(mServo);
+ return *Servo_AnimationValue_GetOffsetRotate(mServo);
+}
+
+const mozilla::StylePositionOrAuto& AnimationValue::GetOffsetAnchorProperty()
+ const {
+ MOZ_ASSERT(mServo);
+ return *Servo_AnimationValue_GetOffsetAnchor(mServo);
+}
+
+const mozilla::StyleOffsetPosition& AnimationValue::GetOffsetPositionProperty()
+ const {
+ MOZ_ASSERT(mServo);
+ return *Servo_AnimationValue_GetOffsetPosition(mServo);
+}
+
+bool AnimationValue::IsOffsetPathUrl() const {
+ return mServo && Servo_AnimationValue_IsOffsetPathUrl(mServo);
+}
+
+MatrixScales AnimationValue::GetScaleValue(const nsIFrame* aFrame) const {
+ using namespace nsStyleTransformMatrix;
+
+ AnimatedPropertyID property(eCSSProperty_UNKNOWN);
+ Servo_AnimationValue_GetPropertyId(mServo, &property);
+ switch (property.mID) {
+ case eCSSProperty_scale: {
+ const StyleScale& scale = GetScaleProperty();
+ return scale.IsNone()
+ ? MatrixScales()
+ : MatrixScales(scale.AsScale()._0, scale.AsScale()._1);
+ }
+ case eCSSProperty_rotate:
+ case eCSSProperty_translate:
+ return MatrixScales();
+ case eCSSProperty_transform:
+ break;
+ default:
+ MOZ_ASSERT_UNREACHABLE(
+ "Should only need to check in transform properties");
+ return MatrixScales();
+ }
+
+ TransformReferenceBox refBox(aFrame);
+ Matrix4x4 t =
+ ReadTransforms(StyleTranslate::None(), StyleRotate::None(),
+ StyleScale::None(), nullptr, GetTransformProperty(),
+ refBox, aFrame->PresContext()->AppUnitsPerDevPixel());
+ Matrix transform2d;
+ bool canDraw2D = t.CanDraw2D(&transform2d);
+ if (!canDraw2D) {
+ return MatrixScales(0, 0);
+ }
+ return transform2d.ScaleFactors();
+}
+
+void AnimationValue::SerializeSpecifiedValue(
+ const AnimatedPropertyID& aProperty,
+ const StylePerDocumentStyleData* aRawData, nsACString& aString) const {
+ MOZ_ASSERT(mServo);
+ Servo_AnimationValue_Serialize(mServo, &aProperty, aRawData, &aString);
+}
+
+bool AnimationValue::IsInterpolableWith(const AnimatedPropertyID& aProperty,
+ const AnimationValue& aToValue) const {
+ if (IsNull() || aToValue.IsNull()) {
+ return false;
+ }
+
+ MOZ_ASSERT(mServo);
+ MOZ_ASSERT(aToValue.mServo);
+ return Servo_AnimationValues_IsInterpolable(mServo, aToValue.mServo);
+}
+
+double AnimationValue::ComputeDistance(const AnimationValue& aOther) const {
+ if (IsNull() || aOther.IsNull()) {
+ return 0.0;
+ }
+
+ MOZ_ASSERT(mServo);
+ MOZ_ASSERT(aOther.mServo);
+
+ double distance =
+ Servo_AnimationValues_ComputeDistance(mServo, aOther.mServo);
+ return distance < 0.0 ? 0.0 : distance;
+}
+
+/* static */
+AnimationValue AnimationValue::FromString(AnimatedPropertyID& aProperty,
+ const nsACString& aValue,
+ Element* aElement) {
+ MOZ_ASSERT(aElement);
+
+ AnimationValue result;
+
+ nsCOMPtr<Document> doc = aElement->GetComposedDoc();
+ if (!doc) {
+ return result;
+ }
+
+ RefPtr<PresShell> presShell = doc->GetPresShell();
+ if (!presShell) {
+ return result;
+ }
+
+ // GetComputedStyle() flushes style, so we shouldn't assume that any
+ // non-owning references we have are still valid.
+ RefPtr<const ComputedStyle> computedStyle =
+ nsComputedDOMStyle::GetComputedStyle(aElement);
+ MOZ_ASSERT(computedStyle);
+
+ RefPtr<StyleLockedDeclarationBlock> declarations =
+ ServoCSSParser::ParseProperty(aProperty, aValue,
+ ServoCSSParser::GetParsingEnvironment(doc),
+ StyleParsingMode::DEFAULT);
+
+ if (!declarations) {
+ return result;
+ }
+
+ result.mServo = presShell->StyleSet()->ComputeAnimationValue(
+ aElement, declarations, computedStyle);
+ return result;
+}
+
+/* static */
+already_AddRefed<StyleAnimationValue> AnimationValue::FromAnimatable(
+ nsCSSPropertyID aProperty, const layers::Animatable& aAnimatable) {
+ switch (aAnimatable.type()) {
+ case layers::Animatable::Tnull_t:
+ break;
+ case layers::Animatable::TStyleTransform: {
+ const StyleTransform& transform = aAnimatable.get_StyleTransform();
+ MOZ_ASSERT(!transform.HasPercent(),
+ "Received transform operations should have been resolved.");
+ return Servo_AnimationValue_Transform(&transform).Consume();
+ }
+ case layers::Animatable::Tfloat:
+ return Servo_AnimationValue_Opacity(aAnimatable.get_float()).Consume();
+ case layers::Animatable::Tnscolor:
+ return Servo_AnimationValue_Color(aProperty, aAnimatable.get_nscolor())
+ .Consume();
+ case layers::Animatable::TStyleRotate:
+ return Servo_AnimationValue_Rotate(&aAnimatable.get_StyleRotate())
+ .Consume();
+ case layers::Animatable::TStyleScale:
+ return Servo_AnimationValue_Scale(&aAnimatable.get_StyleScale())
+ .Consume();
+ case layers::Animatable::TStyleTranslate:
+ MOZ_ASSERT(
+ aAnimatable.get_StyleTranslate().IsNone() ||
+ (!aAnimatable.get_StyleTranslate()
+ .AsTranslate()
+ ._0.HasPercent() &&
+ !aAnimatable.get_StyleTranslate().AsTranslate()._1.HasPercent()),
+ "Should have been resolved already");
+ return Servo_AnimationValue_Translate(&aAnimatable.get_StyleTranslate())
+ .Consume();
+ case layers::Animatable::TStyleOffsetPath:
+ return Servo_AnimationValue_OffsetPath(&aAnimatable.get_StyleOffsetPath())
+ .Consume();
+ case layers::Animatable::TLengthPercentage:
+ return Servo_AnimationValue_OffsetDistance(
+ &aAnimatable.get_LengthPercentage())
+ .Consume();
+ case layers::Animatable::TStyleOffsetRotate:
+ return Servo_AnimationValue_OffsetRotate(
+ &aAnimatable.get_StyleOffsetRotate())
+ .Consume();
+ case layers::Animatable::TStylePositionOrAuto:
+ return Servo_AnimationValue_OffsetAnchor(
+ &aAnimatable.get_StylePositionOrAuto())
+ .Consume();
+ case layers::Animatable::TStyleOffsetPosition:
+ return Servo_AnimationValue_OffsetPosition(
+ &aAnimatable.get_StyleOffsetPosition())
+ .Consume();
+ default:
+ MOZ_ASSERT_UNREACHABLE("Unsupported type");
+ }
+ return nullptr;
+}