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/. */
6 
7 #ifndef mozilla_layout_ScrollAnimationBezierPhysics_h_
8 #define mozilla_layout_ScrollAnimationBezierPhysics_h_
9 
10 #include "ScrollAnimationPhysics.h"
11 #include "nsSMILKeySpline.h"
12 
13 namespace mozilla {
14 
15 struct ScrollAnimationBezierPhysicsSettings {
16   // These values are minimum and maximum animation duration per event,
17   // and a global ratio which defines how longer is the animation's duration
18   // compared to the average recent events intervals (such that for a relatively
19   // consistent events rate, the next event arrives before current animation
20   // ends)
21   int32_t mMinMS;
22   int32_t mMaxMS;
23   double mIntervalRatio;
24 };
25 
26 // This class implements a cubic bezier timing function and automatically
27 // adapts the animation duration based on the scrolling rate.
28 class ScrollAnimationBezierPhysics : public ScrollAnimationPhysics {
29  public:
30   explicit ScrollAnimationBezierPhysics(
31       const nsPoint& aStartPos,
32       const ScrollAnimationBezierPhysicsSettings& aSettings);
33 
34   void Update(const TimeStamp& aTime, const nsPoint& aDestination,
35               const nsSize& aCurrentVelocity) override;
36 
37   // Get the velocity at a point in time in nscoords/sec.
38   nsSize VelocityAt(const TimeStamp& aTime) override;
39 
40   // Returns the expected scroll position at a given point in time, in app
41   // units, relative to the scroll frame.
42   nsPoint PositionAt(const TimeStamp& aTime) override;
43 
IsFinished(const TimeStamp & aTime)44   bool IsFinished(const TimeStamp& aTime) override {
45     return aTime > mStartTime + mDuration;
46   }
47 
48  protected:
ProgressAt(const TimeStamp & aTime)49   double ProgressAt(const TimeStamp& aTime) const {
50     return clamped((aTime - mStartTime) / mDuration, 0.0, 1.0);
51   }
52 
53   nscoord VelocityComponent(double aTimeProgress,
54                             const nsSMILKeySpline& aTimingFunction,
55                             nscoord aStart, nscoord aDestination) const;
56 
57   // Calculate duration, possibly dynamically according to events rate and
58   // event origin. (also maintain previous timestamps - which are only used
59   // here).
60   TimeDuration ComputeDuration(const TimeStamp& aTime);
61 
62   // Initializes the timing function in such a way that the current velocity is
63   // preserved.
64   void InitTimingFunction(nsSMILKeySpline& aTimingFunction, nscoord aCurrentPos,
65                           nscoord aCurrentVelocity, nscoord aDestination);
66 
67   // Initialize event history.
68   void InitializeHistory(const TimeStamp& aTime);
69 
70   // Cached Preferences values.
71   ScrollAnimationBezierPhysicsSettings mSettings;
72 
73   // mPrevEventTime holds previous 3 timestamps for intervals averaging (to
74   // reduce duration fluctuations). When AsyncScroll is constructed and no
75   // previous timestamps are available (indicated with mIsFirstIteration),
76   // initialize mPrevEventTime using imaginary previous timestamps with maximum
77   // relevant intervals between them.
78   TimeStamp mPrevEventTime[3];
79 
80   TimeStamp mStartTime;
81 
82   nsPoint mStartPos;
83   nsPoint mDestination;
84   TimeDuration mDuration;
85   nsSMILKeySpline mTimingFunctionX;
86   nsSMILKeySpline mTimingFunctionY;
87   bool mIsFirstIteration;
88 };
89 
90 }  // namespace mozilla
91 
92 #endif  // mozilla_layout_ScrollAnimationBezierPhysics_h_
93