1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* Utilities for animation of computed style values */
9 #include "mozilla/StyleAnimationValue.h"
11 #include "mozilla/ArrayUtils.h"
12 #include "mozilla/MathAlgorithms.h"
13 #include "mozilla/PresShell.h"
14 #include "mozilla/PresShellInlines.h"
15 #include "mozilla/ServoStyleSet.h"
17 #include "mozilla/UniquePtr.h"
18 #include "nsCOMArray.h"
20 #include "mozilla/ComputedStyle.h"
21 #include "nsComputedDOMStyle.h"
22 #include "nsCSSPseudoElements.h"
23 #include "mozilla/dom/Element.h"
24 #include "mozilla/FloatingPoint.h"
25 #include "mozilla/Likely.h"
26 #include "mozilla/ServoBindings.h" // StyleLockedDeclarationBlock
27 #include "mozilla/ServoCSSParser.h"
28 #include "gfxMatrix.h"
29 #include "gfxQuaternion.h"
30 #include "mozilla/dom/Document.h"
32 #include "gfx2DGlue.h"
33 #include "mozilla/ComputedStyleInlines.h"
34 #include "mozilla/layers/LayersMessages.h"
36 using namespace mozilla
;
37 using namespace mozilla::css
;
38 using namespace mozilla::dom
;
39 using namespace mozilla::gfx
;
41 bool AnimationValue::operator==(const AnimationValue
& aOther
) const {
42 if (mServo
&& aOther
.mServo
) {
43 return Servo_AnimationValue_DeepEqual(mServo
, aOther
.mServo
);
45 if (!mServo
&& !aOther
.mServo
) {
51 bool AnimationValue::operator!=(const AnimationValue
& aOther
) const {
52 return !operator==(aOther
);
55 float AnimationValue::GetOpacity() const {
57 return Servo_AnimationValue_GetOpacity(mServo
);
60 nscolor
AnimationValue::GetColor(nscolor aForegroundColor
) const {
62 return Servo_AnimationValue_GetColor(mServo
, aForegroundColor
);
65 bool AnimationValue::IsCurrentColor() const {
67 return Servo_AnimationValue_IsCurrentColor(mServo
);
70 const StyleTranslate
& AnimationValue::GetTranslateProperty() const {
72 return *Servo_AnimationValue_GetTranslate(mServo
);
75 const StyleRotate
& AnimationValue::GetRotateProperty() const {
77 return *Servo_AnimationValue_GetRotate(mServo
);
80 const StyleScale
& AnimationValue::GetScaleProperty() const {
82 return *Servo_AnimationValue_GetScale(mServo
);
85 const StyleTransform
& AnimationValue::GetTransformProperty() const {
87 return *Servo_AnimationValue_GetTransform(mServo
);
90 void AnimationValue::GetOffsetPathProperty(StyleOffsetPath
& aOffsetPath
) const {
92 Servo_AnimationValue_GetOffsetPath(mServo
, &aOffsetPath
);
95 const mozilla::LengthPercentage
& AnimationValue::GetOffsetDistanceProperty()
98 return *Servo_AnimationValue_GetOffsetDistance(mServo
);
101 const mozilla::StyleOffsetRotate
& AnimationValue::GetOffsetRotateProperty()
104 return *Servo_AnimationValue_GetOffsetRotate(mServo
);
107 const mozilla::StylePositionOrAuto
& AnimationValue::GetOffsetAnchorProperty()
110 return *Servo_AnimationValue_GetOffsetAnchor(mServo
);
113 const mozilla::StyleOffsetPosition
& AnimationValue::GetOffsetPositionProperty()
116 return *Servo_AnimationValue_GetOffsetPosition(mServo
);
119 bool AnimationValue::IsOffsetPathUrl() const {
120 return mServo
&& Servo_AnimationValue_IsOffsetPathUrl(mServo
);
123 MatrixScales
AnimationValue::GetScaleValue(const nsIFrame
* aFrame
) const {
124 using namespace nsStyleTransformMatrix
;
126 AnimatedPropertyID
property(eCSSProperty_UNKNOWN
);
127 Servo_AnimationValue_GetPropertyId(mServo
, &property
);
128 switch (property
.mID
) {
129 case eCSSProperty_scale
: {
130 const StyleScale
& scale
= GetScaleProperty();
131 return scale
.IsNone()
133 : MatrixScales(scale
.AsScale()._0
, scale
.AsScale()._1
);
135 case eCSSProperty_rotate
:
136 case eCSSProperty_translate
:
137 return MatrixScales();
138 case eCSSProperty_transform
:
141 MOZ_ASSERT_UNREACHABLE(
142 "Should only need to check in transform properties");
143 return MatrixScales();
146 TransformReferenceBox
refBox(aFrame
);
148 ReadTransforms(StyleTranslate::None(), StyleRotate::None(),
149 StyleScale::None(), nullptr, GetTransformProperty(),
150 refBox
, aFrame
->PresContext()->AppUnitsPerDevPixel());
152 bool canDraw2D
= t
.CanDraw2D(&transform2d
);
154 return MatrixScales(0, 0);
156 return transform2d
.ScaleFactors();
159 void AnimationValue::SerializeSpecifiedValue(
160 const AnimatedPropertyID
& aProperty
,
161 const StylePerDocumentStyleData
* aRawData
, nsACString
& aString
) const {
163 Servo_AnimationValue_Serialize(mServo
, &aProperty
, aRawData
, &aString
);
166 bool AnimationValue::IsInterpolableWith(const AnimatedPropertyID
& aProperty
,
167 const AnimationValue
& aToValue
) const {
168 if (IsNull() || aToValue
.IsNull()) {
173 MOZ_ASSERT(aToValue
.mServo
);
174 return Servo_AnimationValues_IsInterpolable(mServo
, aToValue
.mServo
);
177 double AnimationValue::ComputeDistance(const AnimationValue
& aOther
) const {
178 if (IsNull() || aOther
.IsNull()) {
183 MOZ_ASSERT(aOther
.mServo
);
186 Servo_AnimationValues_ComputeDistance(mServo
, aOther
.mServo
);
187 return distance
< 0.0 ? 0.0 : distance
;
191 AnimationValue
AnimationValue::FromString(AnimatedPropertyID
& aProperty
,
192 const nsACString
& aValue
,
194 MOZ_ASSERT(aElement
);
196 AnimationValue result
;
198 nsCOMPtr
<Document
> doc
= aElement
->GetComposedDoc();
203 RefPtr
<PresShell
> presShell
= doc
->GetPresShell();
208 // GetComputedStyle() flushes style, so we shouldn't assume that any
209 // non-owning references we have are still valid.
210 RefPtr
<const ComputedStyle
> computedStyle
=
211 nsComputedDOMStyle::GetComputedStyle(aElement
);
212 MOZ_ASSERT(computedStyle
);
214 RefPtr
<StyleLockedDeclarationBlock
> declarations
=
215 ServoCSSParser::ParseProperty(aProperty
, aValue
,
216 ServoCSSParser::GetParsingEnvironment(doc
),
217 StyleParsingMode::DEFAULT
);
223 result
.mServo
= presShell
->StyleSet()->ComputeAnimationValue(
224 aElement
, declarations
, computedStyle
);
229 already_AddRefed
<StyleAnimationValue
> AnimationValue::FromAnimatable(
230 nsCSSPropertyID aProperty
, const layers::Animatable
& aAnimatable
) {
231 switch (aAnimatable
.type()) {
232 case layers::Animatable::Tnull_t
:
234 case layers::Animatable::TStyleTransform
: {
235 const StyleTransform
& transform
= aAnimatable
.get_StyleTransform();
236 MOZ_ASSERT(!transform
.HasPercent(),
237 "Received transform operations should have been resolved.");
238 return Servo_AnimationValue_Transform(&transform
).Consume();
240 case layers::Animatable::Tfloat
:
241 return Servo_AnimationValue_Opacity(aAnimatable
.get_float()).Consume();
242 case layers::Animatable::Tnscolor
:
243 return Servo_AnimationValue_Color(aProperty
, aAnimatable
.get_nscolor())
245 case layers::Animatable::TStyleRotate
:
246 return Servo_AnimationValue_Rotate(&aAnimatable
.get_StyleRotate())
248 case layers::Animatable::TStyleScale
:
249 return Servo_AnimationValue_Scale(&aAnimatable
.get_StyleScale())
251 case layers::Animatable::TStyleTranslate
:
253 aAnimatable
.get_StyleTranslate().IsNone() ||
254 (!aAnimatable
.get_StyleTranslate()
257 !aAnimatable
.get_StyleTranslate().AsTranslate()._1
.HasPercent()),
258 "Should have been resolved already");
259 return Servo_AnimationValue_Translate(&aAnimatable
.get_StyleTranslate())
261 case layers::Animatable::TStyleOffsetPath
:
262 return Servo_AnimationValue_OffsetPath(&aAnimatable
.get_StyleOffsetPath())
264 case layers::Animatable::TLengthPercentage
:
265 return Servo_AnimationValue_OffsetDistance(
266 &aAnimatable
.get_LengthPercentage())
268 case layers::Animatable::TStyleOffsetRotate
:
269 return Servo_AnimationValue_OffsetRotate(
270 &aAnimatable
.get_StyleOffsetRotate())
272 case layers::Animatable::TStylePositionOrAuto
:
273 return Servo_AnimationValue_OffsetAnchor(
274 &aAnimatable
.get_StylePositionOrAuto())
276 case layers::Animatable::TStyleOffsetPosition
:
277 return Servo_AnimationValue_OffsetPosition(
278 &aAnimatable
.get_StyleOffsetPosition())
281 MOZ_ASSERT_UNREACHABLE("Unsupported type");