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 file,
5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef mozilla_ComputedTimingFunction_h
8 #define mozilla_ComputedTimingFunction_h
9 
10 #include "nsDebug.h"
11 #include "nsStringFwd.h"
12 #include "nsTimingFunction.h"
13 
14 #include "mozilla/Assertions.h"
15 #include "mozilla/Maybe.h"
16 #include "mozilla/SMILKeySpline.h"
17 
18 namespace mozilla {
19 
20 class ComputedTimingFunction {
21  public:
22   enum class Type : uint8_t {
23     Ease = uint8_t(StyleTimingKeyword::Ease),            // ease
24     Linear = uint8_t(StyleTimingKeyword::Linear),        // linear
25     EaseIn = uint8_t(StyleTimingKeyword::EaseIn),        // ease-in
26     EaseOut = uint8_t(StyleTimingKeyword::EaseOut),      // ease-out
27     EaseInOut = uint8_t(StyleTimingKeyword::EaseInOut),  // ease-in-out
28     CubicBezier,                                         // cubic-bezier()
29     Step,  // step-start | step-end | steps()
30   };
31 
32   struct StepFunc {
33     uint32_t mSteps;
34     StyleStepPosition mPos;
35     bool operator==(const StepFunc& aOther) const {
36       return mSteps == aOther.mSteps && mPos == aOther.mPos;
37     }
38   };
39 
CubicBezier(double x1,double y1,double x2,double y2)40   static ComputedTimingFunction CubicBezier(double x1, double y1, double x2,
41                                             double y2) {
42     return ComputedTimingFunction(x1, y1, x2, y2);
43   }
Steps(uint32_t aSteps,StyleStepPosition aPos)44   static ComputedTimingFunction Steps(uint32_t aSteps, StyleStepPosition aPos) {
45     MOZ_ASSERT(aSteps > 0, "The number of steps should be 1 or more");
46     return ComputedTimingFunction(aSteps, aPos);
47   }
48 
49   ComputedTimingFunction() = default;
ComputedTimingFunction(const nsTimingFunction & aFunction)50   explicit ComputedTimingFunction(const nsTimingFunction& aFunction) {
51     Init(aFunction);
52   }
53   void Init(const nsTimingFunction& aFunction);
54 
55   // BeforeFlag is used in step timing function.
56   // https://drafts.csswg.org/css-easing/#before-flag
57   enum class BeforeFlag { Unset, Set };
58   double GetValue(double aPortion, BeforeFlag aBeforeFlag) const;
GetFunction()59   const SMILKeySpline* GetFunction() const {
60     NS_ASSERTION(HasSpline(), "Type mismatch");
61     return &mTimingFunction;
62   }
GetType()63   Type GetType() const { return mType; }
HasSpline()64   bool HasSpline() const { return mType != Type::Step; }
GetSteps()65   const StepFunc& GetSteps() const {
66     MOZ_ASSERT(mType == Type::Step);
67     return mSteps;
68   }
69   bool operator==(const ComputedTimingFunction& aOther) const {
70     return mType == aOther.mType &&
71            (HasSpline() ? mTimingFunction == aOther.mTimingFunction
72                         : mSteps == aOther.mSteps);
73   }
74   bool operator!=(const ComputedTimingFunction& aOther) const {
75     return !(*this == aOther);
76   }
77   bool operator==(const nsTimingFunction& aOther) const {
78     switch (aOther.mTiming.tag) {
79       case StyleComputedTimingFunction::Tag::Keyword:
80         return uint8_t(mType) == uint8_t(aOther.mTiming.keyword._0);
81       case StyleComputedTimingFunction::Tag::CubicBezier:
82         return mTimingFunction.X1() == aOther.mTiming.cubic_bezier.x1 &&
83                mTimingFunction.Y1() == aOther.mTiming.cubic_bezier.y1 &&
84                mTimingFunction.X2() == aOther.mTiming.cubic_bezier.x2 &&
85                mTimingFunction.Y2() == aOther.mTiming.cubic_bezier.y2;
86       case StyleComputedTimingFunction::Tag::Steps:
87         return mSteps.mSteps == uint32_t(aOther.mTiming.steps._0) &&
88                mSteps.mPos == aOther.mTiming.steps._1;
89       default:
90         return false;
91     }
92   }
93   bool operator!=(const nsTimingFunction& aOther) const {
94     return !(*this == aOther);
95   }
96   int32_t Compare(const ComputedTimingFunction& aRhs) const;
97   void AppendToString(nsACString& aResult) const;
98 
GetPortion(const Maybe<ComputedTimingFunction> & aFunction,double aPortion,BeforeFlag aBeforeFlag)99   static double GetPortion(const Maybe<ComputedTimingFunction>& aFunction,
100                            double aPortion, BeforeFlag aBeforeFlag) {
101     return aFunction ? aFunction->GetValue(aPortion, aBeforeFlag) : aPortion;
102   }
103   static int32_t Compare(const Maybe<ComputedTimingFunction>& aLhs,
104                          const Maybe<ComputedTimingFunction>& aRhs);
105 
106  private:
ComputedTimingFunction(double x1,double y1,double x2,double y2)107   ComputedTimingFunction(double x1, double y1, double x2, double y2)
108       : mType(Type::CubicBezier), mTimingFunction(x1, y1, x2, y2) {}
ComputedTimingFunction(uint32_t aSteps,StyleStepPosition aPos)109   ComputedTimingFunction(uint32_t aSteps, StyleStepPosition aPos)
110       : mType(Type::Step), mSteps{aSteps, aPos} {}
111 
112   Type mType;
113   SMILKeySpline mTimingFunction;
114   StepFunc mSteps;
115 };
116 
117 inline bool operator==(const Maybe<ComputedTimingFunction>& aLHS,
118                        const nsTimingFunction& aRHS) {
119   if (aLHS.isNothing()) {
120     return aRHS.IsLinear();
121   }
122   return aLHS.value() == aRHS;
123 }
124 
125 inline bool operator!=(const Maybe<ComputedTimingFunction>& aLHS,
126                        const nsTimingFunction& aRHS) {
127   return !(aLHS == aRHS);
128 }
129 
130 }  // namespace mozilla
131 
132 #endif  // mozilla_ComputedTimingFunction_h
133