LCOV - code coverage report
Current view: top level - layout/generic - AsyncScrollBase.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 60 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 8 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "AsyncScrollBase.h"
       7             : #include "gfxPrefs.h"
       8             : 
       9             : using namespace mozilla;
      10             : 
      11           0 : AsyncScrollBase::AsyncScrollBase(nsPoint aStartPos)
      12             :  : mIsFirstIteration(true)
      13           0 :  , mStartPos(aStartPos)
      14             : {
      15           0 : }
      16             : 
      17             : void
      18           0 : AsyncScrollBase::Update(TimeStamp aTime,
      19             :                         nsPoint aDestination,
      20             :                         const nsSize& aCurrentVelocity)
      21             : {
      22           0 :   TimeDuration duration = ComputeDuration(aTime);
      23           0 :   nsSize currentVelocity = aCurrentVelocity;
      24             : 
      25           0 :   if (!mIsFirstIteration) {
      26             :     // If an additional event has not changed the destination, then do not let
      27             :     // another minimum duration reset slow things down.  If it would then
      28             :     // instead continue with the existing timing function.
      29           0 :     if (aDestination == mDestination &&
      30           0 :         aTime + duration > mStartTime + mDuration)
      31             :     {
      32           0 :       return;
      33             :     }
      34             : 
      35           0 :     currentVelocity = VelocityAt(aTime);
      36           0 :     mStartPos = PositionAt(aTime);
      37             :   }
      38             : 
      39           0 :   mStartTime = aTime;
      40           0 :   mDuration = duration;
      41           0 :   mDestination = aDestination;
      42           0 :   InitTimingFunction(mTimingFunctionX, mStartPos.x, currentVelocity.width,
      43           0 :                      aDestination.x);
      44           0 :   InitTimingFunction(mTimingFunctionY, mStartPos.y, currentVelocity.height,
      45           0 :                      aDestination.y);
      46           0 :   mIsFirstIteration = false;
      47             : }
      48             : 
      49             : TimeDuration
      50           0 : AsyncScrollBase::ComputeDuration(TimeStamp aTime)
      51             : {
      52             :   // Average last 3 delta durations (rounding errors up to 2ms are negligible for us)
      53           0 :   int32_t eventsDeltaMs = (aTime - mPrevEventTime[2]).ToMilliseconds() / 3;
      54           0 :   mPrevEventTime[2] = mPrevEventTime[1];
      55           0 :   mPrevEventTime[1] = mPrevEventTime[0];
      56           0 :   mPrevEventTime[0] = aTime;
      57             : 
      58             :   // Modulate duration according to events rate (quicker events -> shorter durations).
      59             :   // The desired effect is to use longer duration when scrolling slowly, such that
      60             :   // it's easier to follow, but reduce the duration to make it feel more snappy when
      61             :   // scrolling quickly. To reduce fluctuations of the duration, we average event
      62             :   // intervals using the recent 4 timestamps (now + three prev -> 3 intervals).
      63           0 :   int32_t durationMS = clamped<int32_t>(eventsDeltaMs * mIntervalRatio, mOriginMinMS, mOriginMaxMS);
      64             : 
      65           0 :   return TimeDuration::FromMilliseconds(durationMS);
      66             : }
      67             : 
      68             : void
      69           0 : AsyncScrollBase::InitializeHistory(TimeStamp aTime)
      70             : {
      71             :   // Starting a new scroll (i.e. not when extending an existing scroll animation),
      72             :   // create imaginary prev timestamps with maximum relevant intervals between them.
      73             : 
      74             :   // Longest relevant interval (which results in maximum duration)
      75           0 :   TimeDuration maxDelta = TimeDuration::FromMilliseconds(mOriginMaxMS / mIntervalRatio);
      76           0 :   mPrevEventTime[0] = aTime              - maxDelta;
      77           0 :   mPrevEventTime[1] = mPrevEventTime[0]  - maxDelta;
      78           0 :   mPrevEventTime[2] = mPrevEventTime[1]  - maxDelta;
      79           0 : }
      80             : 
      81             : void
      82           0 : AsyncScrollBase::InitTimingFunction(nsSMILKeySpline& aTimingFunction,
      83             :                                     nscoord aCurrentPos,
      84             :                                     nscoord aCurrentVelocity,
      85             :                                     nscoord aDestination)
      86             : {
      87           0 :   if (aDestination == aCurrentPos || gfxPrefs::SmoothScrollCurrentVelocityWeighting() == 0) {
      88           0 :     aTimingFunction.Init(0, 0, 1 - gfxPrefs::SmoothScrollStopDecelerationWeighting(), 1);
      89           0 :     return;
      90             :   }
      91             : 
      92           0 :   const TimeDuration oneSecond = TimeDuration::FromSeconds(1);
      93           0 :   double slope = aCurrentVelocity * (mDuration / oneSecond) / (aDestination - aCurrentPos);
      94           0 :   double normalization = sqrt(1.0 + slope * slope);
      95           0 :   double dt = 1.0 / normalization * gfxPrefs::SmoothScrollCurrentVelocityWeighting();
      96           0 :   double dxy = slope / normalization * gfxPrefs::SmoothScrollCurrentVelocityWeighting();
      97           0 :   aTimingFunction.Init(dt, dxy, 1 - gfxPrefs::SmoothScrollStopDecelerationWeighting(), 1);
      98             : }
      99             : 
     100             : nsPoint
     101           0 : AsyncScrollBase::PositionAt(TimeStamp aTime) const
     102             : {
     103           0 :   double progressX = mTimingFunctionX.GetSplineValue(ProgressAt(aTime));
     104           0 :   double progressY = mTimingFunctionY.GetSplineValue(ProgressAt(aTime));
     105           0 :   return nsPoint(NSToCoordRound((1 - progressX) * mStartPos.x + progressX * mDestination.x),
     106           0 :                  NSToCoordRound((1 - progressY) * mStartPos.y + progressY * mDestination.y));
     107             : }
     108             : 
     109             : nsSize
     110           0 : AsyncScrollBase::VelocityAt(TimeStamp aTime) const
     111             : {
     112           0 :   double timeProgress = ProgressAt(aTime);
     113           0 :   return nsSize(VelocityComponent(timeProgress, mTimingFunctionX,
     114           0 :                                   mStartPos.x, mDestination.x),
     115             :                 VelocityComponent(timeProgress, mTimingFunctionY,
     116           0 :                                   mStartPos.y, mDestination.y));
     117             : }
     118             : 
     119             : nscoord
     120           0 : AsyncScrollBase::VelocityComponent(double aTimeProgress,
     121             :                                    const nsSMILKeySpline& aTimingFunction,
     122             :                                    nscoord aStart,
     123             :                                    nscoord aDestination) const
     124             : {
     125             :   double dt, dxy;
     126           0 :   aTimingFunction.GetSplineDerivativeValues(aTimeProgress, dt, dxy);
     127           0 :   if (dt == 0)
     128           0 :     return dxy >= 0 ? nscoord_MAX : nscoord_MIN;
     129             : 
     130           0 :   const TimeDuration oneSecond = TimeDuration::FromSeconds(1);
     131           0 :   double slope = dxy / dt;
     132           0 :   return NSToCoordRound(slope * (aDestination - aStart) / (mDuration / oneSecond));
     133             : }

Generated by: LCOV version 1.13