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"
16 #include "mozilla/Tuple.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" // RawServoDeclarationBlock
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 const mozilla::StyleOffsetPath
& AnimationValue::GetOffsetPathProperty() const {
92 return *Servo_AnimationValue_GetOffsetPath(mServo
);
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 Size
AnimationValue::GetScaleValue(const nsIFrame
* aFrame
) const {
114 using namespace nsStyleTransformMatrix
;
116 switch (Servo_AnimationValue_GetPropertyId(mServo
)) {
117 case eCSSProperty_scale
: {
118 const StyleScale
& scale
= GetScaleProperty();
119 return scale
.IsNone() ? Size(1.0, 1.0)
120 : Size(scale
.AsScale()._0
, scale
.AsScale()._1
);
122 case eCSSProperty_rotate
:
123 case eCSSProperty_translate
:
124 return Size(1.0, 1.0);
125 case eCSSProperty_transform
:
128 MOZ_ASSERT_UNREACHABLE(
129 "Should only need to check in transform properties");
130 return Size(1.0, 1.0);
133 TransformReferenceBox
refBox(aFrame
);
135 ReadTransforms(StyleTranslate::None(), StyleRotate::None(),
136 StyleScale::None(), Nothing(), GetTransformProperty(),
137 refBox
, aFrame
->PresContext()->AppUnitsPerDevPixel());
139 bool canDraw2D
= t
.CanDraw2D(&transform2d
);
143 return transform2d
.ScaleFactors();
146 void AnimationValue::SerializeSpecifiedValue(nsCSSPropertyID aProperty
,
147 const RawServoStyleSet
* aRawSet
,
148 nsACString
& aString
) const {
150 Servo_AnimationValue_Serialize(mServo
, aProperty
, aRawSet
, &aString
);
153 bool AnimationValue::IsInterpolableWith(nsCSSPropertyID aProperty
,
154 const AnimationValue
& aToValue
) const {
155 if (IsNull() || aToValue
.IsNull()) {
160 MOZ_ASSERT(aToValue
.mServo
);
161 return Servo_AnimationValues_IsInterpolable(mServo
, aToValue
.mServo
);
164 double AnimationValue::ComputeDistance(nsCSSPropertyID aProperty
,
165 const AnimationValue
& aOther
) const {
166 if (IsNull() || aOther
.IsNull()) {
171 MOZ_ASSERT(aOther
.mServo
);
174 Servo_AnimationValues_ComputeDistance(mServo
, aOther
.mServo
);
175 return distance
< 0.0 ? 0.0 : distance
;
179 AnimationValue
AnimationValue::FromString(nsCSSPropertyID aProperty
,
180 const nsACString
& aValue
,
182 MOZ_ASSERT(aElement
);
184 AnimationValue result
;
186 nsCOMPtr
<Document
> doc
= aElement
->GetComposedDoc();
191 RefPtr
<PresShell
> presShell
= doc
->GetPresShell();
196 // GetComputedStyle() flushes style, so we shouldn't assume that any
197 // non-owning references we have are still valid.
198 RefPtr
<ComputedStyle
> computedStyle
=
199 nsComputedDOMStyle::GetComputedStyle(aElement
);
200 MOZ_ASSERT(computedStyle
);
202 RefPtr
<RawServoDeclarationBlock
> declarations
= ServoCSSParser::ParseProperty(
203 aProperty
, aValue
, ServoCSSParser::GetParsingEnvironment(doc
));
209 result
.mServo
= presShell
->StyleSet()->ComputeAnimationValue(
210 aElement
, declarations
, computedStyle
);
215 already_AddRefed
<RawServoAnimationValue
> AnimationValue::FromAnimatable(
216 nsCSSPropertyID aProperty
, const layers::Animatable
& aAnimatable
) {
217 switch (aAnimatable
.type()) {
218 case layers::Animatable::Tnull_t
:
220 case layers::Animatable::TStyleTransform
: {
221 const StyleTransform
& transform
= aAnimatable
.get_StyleTransform();
222 MOZ_ASSERT(!transform
.HasPercent(),
223 "Received transform operations should have been resolved.");
224 return Servo_AnimationValue_Transform(&transform
).Consume();
226 case layers::Animatable::Tfloat
:
227 return Servo_AnimationValue_Opacity(aAnimatable
.get_float()).Consume();
228 case layers::Animatable::Tnscolor
:
229 return Servo_AnimationValue_Color(aProperty
, aAnimatable
.get_nscolor())
231 case layers::Animatable::TStyleRotate
:
232 return Servo_AnimationValue_Rotate(&aAnimatable
.get_StyleRotate())
234 case layers::Animatable::TStyleScale
:
235 return Servo_AnimationValue_Scale(&aAnimatable
.get_StyleScale())
237 case layers::Animatable::TStyleTranslate
:
239 aAnimatable
.get_StyleTranslate().IsNone() ||
240 (!aAnimatable
.get_StyleTranslate()
243 !aAnimatable
.get_StyleTranslate().AsTranslate()._1
.HasPercent()),
244 "Should have been resolved already");
245 return Servo_AnimationValue_Translate(&aAnimatable
.get_StyleTranslate())
247 case layers::Animatable::TStyleOffsetPath
:
248 return Servo_AnimationValue_OffsetPath(&aAnimatable
.get_StyleOffsetPath())
250 case layers::Animatable::TLengthPercentage
:
251 return Servo_AnimationValue_OffsetDistance(
252 &aAnimatable
.get_LengthPercentage())
254 case layers::Animatable::TStyleOffsetRotate
:
255 return Servo_AnimationValue_OffsetRotate(
256 &aAnimatable
.get_StyleOffsetRotate())
258 case layers::Animatable::TStylePositionOrAuto
:
259 return Servo_AnimationValue_OffsetAnchor(
260 &aAnimatable
.get_StylePositionOrAuto())
263 MOZ_ASSERT_UNREACHABLE("Unsupported type");