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 "mozilla/SMILKeySpline.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 final : 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   void ApplyContentShift(const CSSPoint& aShiftDelta) override;
38 
39   // Get the velocity at a point in time in nscoords/sec.
40   nsSize VelocityAt(const TimeStamp& aTime) override;
41 
42   // Returns the expected scroll position at a given point in time, in app
43   // units, relative to the scroll frame.
44   nsPoint PositionAt(const TimeStamp& aTime) override;
45 
IsFinished(const TimeStamp & aTime)46   bool IsFinished(const TimeStamp& aTime) override {
47     return aTime > mStartTime + mDuration;
48   }
49 
50  protected:
ProgressAt(const TimeStamp & aTime)51   double ProgressAt(const TimeStamp& aTime) const {
52     return clamped((aTime - mStartTime) / mDuration, 0.0, 1.0);
53   }
54 
55   nscoord VelocityComponent(double aTimeProgress,
56                             const SMILKeySpline& aTimingFunction,
57                             nscoord aStart, nscoord aDestination) const;
58 
59   // Calculate duration, possibly dynamically according to events rate and
60   // event origin. (also maintain previous timestamps - which are only used
61   // here).
62   TimeDuration ComputeDuration(const TimeStamp& aTime);
63 
64   // Initializes the timing function in such a way that the current velocity is
65   // preserved.
66   void InitTimingFunction(SMILKeySpline& aTimingFunction, nscoord aCurrentPos,
67                           nscoord aCurrentVelocity, nscoord aDestination);
68 
69   // Initialize event history.
70   void InitializeHistory(const TimeStamp& aTime);
71 
72   // Cached Preferences values.
73   ScrollAnimationBezierPhysicsSettings mSettings;
74 
75   // mPrevEventTime holds previous 3 timestamps for intervals averaging (to
76   // reduce duration fluctuations). When AsyncScroll is constructed and no
77   // previous timestamps are available (indicated with mIsFirstIteration),
78   // initialize mPrevEventTime using imaginary previous timestamps with maximum
79   // relevant intervals between them.
80   TimeStamp mPrevEventTime[3];
81 
82   TimeStamp mStartTime;
83 
84   nsPoint mStartPos;
85   nsPoint mDestination;
86   TimeDuration mDuration;
87   SMILKeySpline mTimingFunctionX;
88   SMILKeySpline mTimingFunctionY;
89   bool mIsFirstIteration;
90 };
91 
92 }  // namespace mozilla
93 
94 #endif  // mozilla_layout_ScrollAnimationBezierPhysics_h_
95