Changeset 93682 in webkit


Ignore:
Timestamp:
Aug 23, 2011 6:36:50 PM (13 years ago)
Author:
commit-queue@webkit.org
Message:

ScrollAnimatorNone coasting implementation
https://bugs.webkit.org/show_bug.cgi?id=66258

Source/WebCore:

Increase the animation time based on the velocity of the scroll, up to a
maximum amount. Fix bugs found by additional unit testing.

Patch by Scott Byer <scottbyer@chromium.org> on 2011-08-23
Reviewed by James Robinson.

Additional tests in ScrollAnimatorNoneTest: CurveMathQuartic, CurveMathCoast,
ScrollOnceQuartic, ScrollTwiceCubic, ScrollLotsCubic, ScrollLotsCubicSmoothed,
ScrollUpToBumperCoast, ScrollDownToBumperCoast, VaryingInputsEquivalency,
VaryingInputsEquivalencyCoast, VaryingInputsEquivalencyCoastLarge,
VaryingInputsEquivalencyCoastSteep

  • platform/ScrollAnimatorNone.cpp:

(WebCore::ScrollAnimatorNone::Parameters::Parameters):
(WebCore::ScrollAnimatorNone::PerAxisData::curveAt):
(WebCore::ScrollAnimatorNone::PerAxisData::coastCurve):
(WebCore::ScrollAnimatorNone::PerAxisData::curveIntegralAt):
(WebCore::ScrollAnimatorNone::PerAxisData::attackArea):
(WebCore::ScrollAnimatorNone::PerAxisData::releaseArea):
(WebCore::ScrollAnimatorNone::PerAxisData::PerAxisData):
(WebCore::ScrollAnimatorNone::PerAxisData::updateDataFromParameters):
(WebCore::ScrollAnimatorNone::PerAxisData::updateVisibleLength):
(WebCore::ScrollAnimatorNone::ScrollAnimatorNone):
(WebCore::ScrollAnimatorNone::scroll):
(WebCore::ScrollAnimatorNone::willEndLiveResize):
(WebCore::ScrollAnimatorNone::didAddVerticalScrollbar):
(WebCore::ScrollAnimatorNone::didAddHorizontalScrollbar):
(WebCore::ScrollAnimatorNone::updateVisibleLengths):

  • platform/ScrollAnimatorNone.h:

Source/WebKit/chromium:

Patch by Scott Byer <scottbyer@chromium.org> on 2011-08-23
Reviewed by James Robinson.

  • tests/ScrollAnimatorNoneTest.cpp:

(MockScrollableArea::visibleHeight):
(MockScrollableArea::visibleWidth):
(ScrollAnimatorNoneTest::SavePerAxisData::SavePerAxisData):
(ScrollAnimatorNoneTest::SavePerAxisData::operator==):
(ScrollAnimatorNoneTest::SetUp):
(ScrollAnimatorNoneTest::updateDataFromParameters):
(ScrollAnimatorNoneTest::animateScroll):
(ScrollAnimatorNoneTest::attackArea):
(ScrollAnimatorNoneTest::releaseArea):
(ScrollAnimatorNoneTest::coastCurve):
(ScrollAnimatorNoneTest::curveTestInner):
(TEST_F):

Location:
trunk/Source
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r93681 r93682  
     12011-08-23  Scott Byer  <scottbyer@chromium.org>
     2
     3        ScrollAnimatorNone coasting implementation
     4        https://bugs.webkit.org/show_bug.cgi?id=66258
     5
     6        Increase the animation time based on the velocity of the scroll, up to a
     7        maximum amount. Fix bugs found by additional unit testing.
     8
     9        Reviewed by James Robinson.
     10
     11        Additional tests in ScrollAnimatorNoneTest: CurveMathQuartic, CurveMathCoast,
     12        ScrollOnceQuartic, ScrollTwiceCubic, ScrollLotsCubic, ScrollLotsCubicSmoothed,
     13        ScrollUpToBumperCoast, ScrollDownToBumperCoast, VaryingInputsEquivalency,
     14        VaryingInputsEquivalencyCoast, VaryingInputsEquivalencyCoastLarge,
     15        VaryingInputsEquivalencyCoastSteep
     16
     17        * platform/ScrollAnimatorNone.cpp:
     18        (WebCore::ScrollAnimatorNone::Parameters::Parameters):
     19        (WebCore::ScrollAnimatorNone::PerAxisData::curveAt):
     20        (WebCore::ScrollAnimatorNone::PerAxisData::coastCurve):
     21        (WebCore::ScrollAnimatorNone::PerAxisData::curveIntegralAt):
     22        (WebCore::ScrollAnimatorNone::PerAxisData::attackArea):
     23        (WebCore::ScrollAnimatorNone::PerAxisData::releaseArea):
     24        (WebCore::ScrollAnimatorNone::PerAxisData::PerAxisData):
     25        (WebCore::ScrollAnimatorNone::PerAxisData::updateDataFromParameters):
     26        (WebCore::ScrollAnimatorNone::PerAxisData::updateVisibleLength):
     27        (WebCore::ScrollAnimatorNone::ScrollAnimatorNone):
     28        (WebCore::ScrollAnimatorNone::scroll):
     29        (WebCore::ScrollAnimatorNone::willEndLiveResize):
     30        (WebCore::ScrollAnimatorNone::didAddVerticalScrollbar):
     31        (WebCore::ScrollAnimatorNone::didAddHorizontalScrollbar):
     32        (WebCore::ScrollAnimatorNone::updateVisibleLengths):
     33        * platform/ScrollAnimatorNone.h:
     34
    1352011-08-23  James Robinson  <jamesr@chromium.org>
    236
  • trunk/Source/WebCore/platform/ScrollAnimatorNone.cpp

    r93328 r93682  
    6565}
    6666
    67 ScrollAnimatorNone::Parameters::Parameters(bool isEnabled, double animationTime, double repeatMinimumSustainTime, Curve attackCurve, double attackTime, Curve releaseCurve, double releaseTime)
     67ScrollAnimatorNone::Parameters::Parameters(bool isEnabled, double animationTime, double repeatMinimumSustainTime, Curve attackCurve, double attackTime, Curve releaseCurve, double releaseTime, Curve coastTimeCurve, double maximumCoastTime)
    6868    : m_isEnabled(isEnabled)
    6969    , m_animationTime(animationTime)
     
    7373    , m_releaseCurve(releaseCurve)
    7474    , m_releaseTime(releaseTime)
     75    , m_coastTimeCurve(coastTimeCurve)
     76    , m_maximumCoastTime(maximumCoastTime)
    7577{
    7678}
     
    8082    switch (curve) {
    8183    case Linear:
     84        return t;
     85    case Quadratic:
    8286        return t * t;
    83     case Quadratic:
     87    case Cubic:
    8488        return t * t * t;
    85     case Cubic:
     89    case Quartic:
    8690        return t * t * t * t;
    8791    case Bounce:
    88         if (t < 1 / 2.75)
    89             return 7.5625 * t * t;
    90         if (t < 2 / 2.75) {
    91             double t1 = t - 1.5 / 2.75;
    92             return 7.5625 * t1 * t1 + .75;
     92        // Time base is chosen to keep the bounce points simpler:
     93        // 1 (half bounce coming in) + 1 + .5 + .25
     94        const double kTimeBase = 2.75;
     95        const double kTimeBaseSquared = kTimeBase * kTimeBase;
     96        if (t < 1 / kTimeBase)
     97            return kTimeBaseSquared * t * t;
     98        if (t < 2 / kTimeBase) {
     99            // Invert a [-.5,.5] quadratic parabola, center it in [1,2].
     100            double t1 = t - 1.5 / kTimeBase;
     101            const double kParabolaAtEdge = 1 - .5 * .5;
     102            return kTimeBaseSquared * t1 * t1 + kParabolaAtEdge;
    93103        }
    94         if (t < 2.5 / 2.75) {
    95             double t2 = t - 2.25 / 2.75;
    96             return 7.5625 * t2 * t2 + .9375;
     104        if (t < 2.5 / kTimeBase) {
     105            // Invert a [-.25,.25] quadratic parabola, center it in [2,2.5].
     106            double t2 = t - 2.25 / kTimeBase;
     107            const double kParabolaAtEdge = 1 - .25 * .25;
     108            return kTimeBaseSquared * t2 * t2 + kParabolaAtEdge;
    97109        }
    98         t -= 2.625 / 2.75;
    99         return 7.5625 * t * t + .984375;
    100     }
     110            // Invert a [-.125,.125] quadratic parabola, center it in [2.5,2.75].
     111        const double kParabolaAtEdge = 1 - .125 * .125;
     112        t -= 2.625 / kTimeBase;
     113        return kTimeBaseSquared * t * t + kParabolaAtEdge;
     114    }
     115    ASSERT_NOT_REACHED();
    101116    return 0;
    102117}
     
    116131}
    117132
    118 double ScrollAnimatorNone::PerAxisData::curveDerivativeAt(Curve curve, double t)
     133double ScrollAnimatorNone::PerAxisData::coastCurve(Curve curve, double factor)
     134{
     135    return 1 - curveAt(curve, 1 - factor);
     136}
     137
     138double ScrollAnimatorNone::PerAxisData::curveIntegralAt(Curve curve, double t)
    119139{
    120140    switch (curve) {
    121141    case Linear:
    122         return t * 2;
     142        return t * t / 2;
    123143    case Quadratic:
    124         return t * t * 3;
     144        return t * t * t / 3;
    125145    case Cubic:
    126         return t * t * t * 4;
     146        return t * t * t * t / 4;
     147    case Quartic:
     148        return t * t * t * t * t / 5;
    127149    case Bounce:
    128         return t;
    129     }
     150        const double kTimeBase = 2.75;
     151        const double kTimeBaseSquared = kTimeBase * kTimeBase;
     152        const double kTimeBaseSquaredOverThree = kTimeBaseSquared / 3;
     153        double area;
     154        double t1 = min(t, 1 / kTimeBase);
     155        area = kTimeBaseSquaredOverThree * t1 * t1 * t1;
     156        if (t < 1 / kTimeBase)
     157            return area;
     158
     159        t1 = min(t - 1 / kTimeBase, 1 / kTimeBase);
     160        // The integral of kTimeBaseSquared * (t1 - .5 / kTimeBase) * (t1 - .5 / kTimeBase) + kParabolaAtEdge
     161        const double kSecondInnerOffset = kTimeBaseSquared * .5 / kTimeBase;
     162        double bounceArea = t1 * (t1 * (kTimeBaseSquaredOverThree * t1 - kSecondInnerOffset) + 1);
     163        area += bounceArea;
     164        if (t < 2 / kTimeBase)
     165            return area;
     166
     167        t1 = min(t - 2 / kTimeBase, 0.5 / kTimeBase);
     168        // The integral of kTimeBaseSquared * (t1 - .25 / kTimeBase) * (t1 - .25 / kTimeBase) + kParabolaAtEdge
     169        const double kThirdInnerOffset = kTimeBaseSquared * .25 / kTimeBase;
     170        bounceArea =  t1 * (t1 * (kTimeBaseSquaredOverThree * t1 - kThirdInnerOffset) + 1);
     171        area += bounceArea;
     172        if (t < 2.5 / kTimeBase)
     173            return area;
     174
     175        t1 = t - 2.5 / kTimeBase;
     176        // The integral of kTimeBaseSquared * (t1 - .125 / kTimeBase) * (t1 - .125 / kTimeBase) + kParabolaAtEdge
     177        const double kFourthInnerOffset = kTimeBaseSquared * .125 / kTimeBase;
     178        bounceArea = t1 * (t1 * (kTimeBaseSquaredOverThree * t1 - kFourthInnerOffset) + 1);
     179        area += bounceArea;
     180        return area;
     181    }
     182    ASSERT_NOT_REACHED();
    130183    return 0;
    131184}
    132185
    133 ScrollAnimatorNone::PerAxisData::PerAxisData(ScrollAnimatorNone* parent, float* currentPosition)
     186double ScrollAnimatorNone::PerAxisData::attackArea(Curve curve, double startT, double endT)
     187{
     188    double startValue = curveIntegralAt(curve, startT);
     189    double endValue = curveIntegralAt(curve, endT);
     190    return endValue - startValue;
     191}
     192
     193double ScrollAnimatorNone::PerAxisData::releaseArea(Curve curve, double startT, double endT)
     194{
     195    double startValue = curveIntegralAt(curve, 1 - endT);
     196    double endValue = curveIntegralAt(curve, 1 - startT);
     197    return endValue - startValue;
     198}
     199
     200ScrollAnimatorNone::PerAxisData::PerAxisData(ScrollAnimatorNone* parent, float* currentPosition, LayoutUnit visibleLength)
    134201    : m_currentPosition(currentPosition)
     202    , m_visibleLength(visibleLength)
    135203{
    136204    reset();
     
    163231bool ScrollAnimatorNone::PerAxisData::updateDataFromParameters(float step, float multiplier, float scrollableSize, double currentTime, Parameters* parameters)
    164232{
    165     if (parameters->m_animationTime > m_animationTime)
    166         m_animationTime = parameters->m_animationTime;
    167     m_attackTime = parameters->m_attackTime;
     233    if (!m_startTime)
     234        m_desiredPosition = *m_currentPosition;
     235    float newPosition = m_desiredPosition + (step * multiplier);
     236
     237    if (newPosition < 0 || newPosition > scrollableSize)
     238        newPosition = max(min(newPosition, scrollableSize), 0.0f);
     239
     240    if (newPosition == m_desiredPosition)
     241        return false;
     242
     243    m_desiredPosition = newPosition;
     244
     245    if (!m_startTime) {
     246        m_attackTime = parameters->m_attackTime;
     247        m_attackCurve = parameters->m_attackCurve;
     248    }
     249    m_animationTime = parameters->m_animationTime;
    168250    m_releaseTime = parameters->m_releaseTime;
    169     m_attackCurve = parameters->m_attackCurve;
    170251    m_releaseCurve = parameters->m_releaseCurve;
    171252
     
    176257        m_attackTime = m_animationTime - m_releaseTime;
    177258    }
    178 
    179     if (!m_startTime)
    180         m_desiredPosition = *m_currentPosition;
    181     float newPosition = m_desiredPosition + (step * multiplier);
    182 
    183     if (newPosition < 0 || newPosition > scrollableSize)
    184         newPosition = max(min(newPosition, scrollableSize), 0.0f);
    185 
    186     if (newPosition == m_desiredPosition)
    187         return false;
    188 
    189     m_desiredPosition = newPosition;
    190259
    191260    if (!m_startTime) {
     
    210279    }
    211280
     281    if (parameters->m_maximumCoastTime > (parameters->m_repeatMinimumSustainTime + parameters->m_releaseTime)) {
     282        double targetMaxCoastVelocity = m_visibleLength * .25 * kFrameRate;
     283        // This needs to be as minimal as possible while not being intrusive to page up/down.
     284        double minCoastDelta = m_visibleLength;
     285
     286        if (abs(remainingDelta) > minCoastDelta) {
     287            double maxCoastDelta = parameters->m_maximumCoastTime * targetMaxCoastVelocity;
     288            double coastFactor = min(1., (abs(remainingDelta) - minCoastDelta) / (maxCoastDelta - minCoastDelta));
     289
     290            // We could play with the curve here - linear seems a little soft. Initial testing makes me want to feed into the sustain time more aggressively.
     291            double coastMinTimeLeft = min(parameters->m_maximumCoastTime, minTimeLeft + coastCurve(parameters->m_coastTimeCurve, coastFactor) * (parameters->m_maximumCoastTime - minTimeLeft));
     292
     293            double additionalTime = max(0., coastMinTimeLeft - minTimeLeft);
     294            if (additionalTime) {
     295                double additionalReleaseTime = min(additionalTime, parameters->m_releaseTime / (parameters->m_releaseTime + parameters->m_repeatMinimumSustainTime) * additionalTime);
     296                m_releaseTime = parameters->m_releaseTime + additionalReleaseTime;
     297                m_animationTime = deltaTime + coastMinTimeLeft;
     298                timeLeft = coastMinTimeLeft;
     299            }
     300        }
     301    }
     302
    212303    double releaseTimeLeft = min(timeLeft, m_releaseTime);
    213304    double sustainTimeLeft = max(0., timeLeft - releaseTimeLeft - attackTimeLeft);
     
    215306    if (attackTimeLeft) {
    216307        double attackSpot = deltaTime / m_attackTime;
    217         attackAreaLeft = attackTimeLeft / (curveDerivativeAt(m_attackCurve, 1) - curveDerivativeAt(m_attackCurve, attackSpot));
     308        attackAreaLeft = attackArea(m_attackCurve, attackSpot, 1) * m_attackTime;
    218309    }
    219310
    220311    double releaseSpot = (m_releaseTime - releaseTimeLeft) / m_releaseTime;
    221     double releaseAreaLeft  = releaseTimeLeft / (curveDerivativeAt(m_releaseCurve, 1) - curveDerivativeAt(m_releaseCurve, releaseSpot));
     312    double releaseAreaLeft  = releaseArea(m_releaseCurve, releaseSpot, 1) * m_releaseTime;
    222313
    223314    m_desiredVelocity = remainingDelta / (attackAreaLeft + sustainTimeLeft + releaseAreaLeft);
     
    271362}
    272363
     364void ScrollAnimatorNone::PerAxisData::updateVisibleLength(LayoutUnit visibleLength)
     365{
     366    m_visibleLength = visibleLength;
     367}
     368
    273369ScrollAnimatorNone::ScrollAnimatorNone(ScrollableArea* scrollableArea)
    274370    : ScrollAnimator(scrollableArea)
    275     , m_horizontalData(this, &m_currentPosX)
    276     , m_verticalData(this, &m_currentPosY)
     371    , m_horizontalData(this, &m_currentPosX, scrollableArea->visibleWidth())
     372    , m_verticalData(this, &m_currentPosY, scrollableArea->visibleHeight())
    277373    , m_animationTimer(this, &ScrollAnimatorNone::animationTimerFired)
    278374{
     
    294390    switch (granularity) {
    295391    case ScrollByDocument:
     392        parameters = Parameters(true, 20 * kTickTime, 10 * kTickTime, Cubic, 10 * kTickTime, Cubic, 10 * kTickTime, Linear, 1);
    296393        break;
    297394    case ScrollByLine:
    298         parameters = Parameters(true, 10 * kTickTime, 7 * kTickTime, Quadratic, 3 * kTickTime, Quadratic, 3 * kTickTime);
     395        parameters = Parameters(true, 10 * kTickTime, 7 * kTickTime, Cubic, 3 * kTickTime, Cubic, 3 * kTickTime, Linear, 1);
    299396        break;
    300397    case ScrollByPage:
    301         parameters = Parameters(true, 15 * kTickTime, 10 * kTickTime, Quadratic, 5 * kTickTime, Quadratic, 5 * kTickTime);
     398        parameters = Parameters(true, 15 * kTickTime, 10 * kTickTime, Cubic, 5 * kTickTime, Cubic, 5 * kTickTime, Linear, 1);
    302399        break;
    303400    case ScrollByPixel:
    304         parameters = Parameters(true, 11 * kTickTime, 2 * kTickTime, Quadratic, 3 * kTickTime, Quadratic, 3 * kTickTime);
     401        parameters = Parameters(true, 11 * kTickTime, 2 * kTickTime, Cubic, 3 * kTickTime, Cubic, 3 * kTickTime, Quadratic, 1.25);
    305402        break;
    306403    default:
     
    337434
    338435    notifyPositionChanged();
     436}
     437
     438void ScrollAnimatorNone::willEndLiveResize()
     439{
     440    updateVisibleLengths();
     441}
     442
     443void ScrollAnimatorNone::didAddVerticalScrollbar(Scrollbar*)
     444{
     445    updateVisibleLengths();
     446}
     447
     448void ScrollAnimatorNone::didAddHorizontalScrollbar(Scrollbar*)
     449{
     450    updateVisibleLengths();
     451}
     452
     453void ScrollAnimatorNone::updateVisibleLengths()
     454{
     455    m_horizontalData.updateVisibleLength(scrollableArea()->visibleWidth());
     456    m_verticalData.updateVisibleLength(scrollableArea()->visibleHeight());
    339457}
    340458
  • trunk/Source/WebCore/platform/ScrollAnimatorNone.h

    r93262 r93682  
    3434#if ENABLE(SMOOTH_SCROLLING)
    3535
     36#include "LayoutTypes.h"
    3637#include "ScrollAnimator.h"
    3738#include "Timer.h"
     
    5152    virtual void scrollToOffsetWithoutAnimation(const FloatPoint&);
    5253
     54    virtual void willEndLiveResize();
     55    virtual void didAddVerticalScrollbar(Scrollbar*);
     56    virtual void didAddHorizontalScrollbar(Scrollbar*);
     57
    5358    enum Curve {
    5459        Linear,
    5560        Quadratic,
    5661        Cubic,
     62        Quartic,
    5763        Bounce
    5864    };
     
    6066    struct Parameters {
    6167        Parameters();
    62         Parameters(bool isEnabled, double animationTime, double repeatMinimumSustainTime, Curve attackCurve, double attackTime, Curve releaseCurve, double releaseTime);
     68        Parameters(bool isEnabled, double animationTime, double repeatMinimumSustainTime, Curve attackCurve, double attackTime, Curve releaseCurve, double releaseTime, Curve coastTimeCurve, double maximumCoastTime);
    6369
    6470        // Note that the times can be overspecified such that releaseTime or releaseTime and attackTime are greater
     
    7480        Curve m_releaseCurve;
    7581        double m_releaseTime;
     82
     83        Curve m_coastTimeCurve;
     84        double m_maximumCoastTime;
    7685    };
    7786
     
    8089
    8190    struct PerAxisData {
    82         PerAxisData(ScrollAnimatorNone* parent, float* currentPos);
     91        PerAxisData(ScrollAnimatorNone* parent, float* currentPos, LayoutUnit visibleLength);
    8392        void reset();
    8493        bool updateDataFromParameters(float step, float multiplier, float scrollableSize, double currentTime, Parameters*);
    8594        bool animateScroll(double currentTime);
     95        void updateVisibleLength(LayoutUnit visibleLength);
    8696
    8797        static double curveAt(Curve, double t);
    88         static double curveDerivativeAt(Curve, double t);
    89 
    9098        static double attackCurve(Curve, double deltaT, double curveT, double startPos, double attackPos);
    9199        static double releaseCurve(Curve, double deltaT, double curveT, double releasePos, double desiredPos);
     100        static double coastCurve(Curve, double factor);
     101
     102        static double curveIntegralAt(Curve, double t);
     103        static double attackArea(Curve, double startT, double endT);
     104        static double releaseArea(Curve, double startT, double endT);
    92105
    93106        float* m_currentPosition;
     
    111124        double m_releaseTime;
    112125        Curve m_releaseCurve;
     126
     127        LayoutUnit m_visibleLength;
    113128    };
    114129
    115130    void animationTimerFired(Timer<ScrollAnimatorNone>*);
    116131    void stopAnimationTimerIfNeeded();
     132    void updateVisibleLengths();
    117133
    118134    PerAxisData m_horizontalData;
  • trunk/Source/WebKit/chromium/ChangeLog

    r93681 r93682  
     12011-08-23  Scott Byer  <scottbyer@chromium.org>
     2
     3        ScrollAnimatorNone coasting implementation
     4        https://bugs.webkit.org/show_bug.cgi?id=66258
     5
     6        Reviewed by James Robinson.
     7
     8        * tests/ScrollAnimatorNoneTest.cpp:
     9        (MockScrollableArea::visibleHeight):
     10        (MockScrollableArea::visibleWidth):
     11        (ScrollAnimatorNoneTest::SavePerAxisData::SavePerAxisData):
     12        (ScrollAnimatorNoneTest::SavePerAxisData::operator==):
     13        (ScrollAnimatorNoneTest::SetUp):
     14        (ScrollAnimatorNoneTest::updateDataFromParameters):
     15        (ScrollAnimatorNoneTest::animateScroll):
     16        (ScrollAnimatorNoneTest::attackArea):
     17        (ScrollAnimatorNoneTest::releaseArea):
     18        (ScrollAnimatorNoneTest::coastCurve):
     19        (ScrollAnimatorNoneTest::curveTestInner):
     20        (TEST_F):
     21
    1222011-08-23  James Robinson  <jamesr@chromium.org>
    223
  • trunk/Source/WebKit/chromium/tests/ScrollAnimatorNoneTest.cpp

    r93262 r93682  
    4141#include <gtest/gtest.h>
    4242
     43using namespace std;
    4344using namespace WebCore;
    4445
     
    6465    MOCK_CONST_METHOD0(enclosingScrollableArea, ScrollableArea*());
    6566
     67    virtual LayoutUnit visibleHeight() const { return 768; }
     68    virtual LayoutUnit visibleWidth() const { return 1024; }
     69
    6670    bool scrollAnimatorEnabled() const { return m_scrollAnimatorEnabled; }
    6771    bool m_scrollAnimatorEnabled;
     
    148152class ScrollAnimatorNoneTest : public testing::Test {
    149153public:
     154    struct SavePerAxisData : public ScrollAnimatorNone::PerAxisData {
     155        SavePerAxisData(const ScrollAnimatorNone::PerAxisData& data)
     156            : ScrollAnimatorNone::PerAxisData(&m_mockScrollAnimatorNone, 0, 768)
     157        {
     158            this->m_currentVelocity = data.m_currentVelocity;
     159            this->m_desiredPosition = data.m_desiredPosition;
     160            this->m_desiredVelocity = data.m_desiredVelocity;
     161            this->m_startPosition = data.m_startPosition;
     162            this->m_startTime = data.m_startTime;
     163            this->m_startVelocity = data.m_startVelocity;
     164            this->m_animationTime = data.m_animationTime;
     165            this->m_lastAnimationTime = data.m_lastAnimationTime;
     166            this->m_attackPosition = data.m_attackPosition;
     167            this->m_attackTime = data.m_attackTime;
     168            this->m_attackCurve = data.m_attackCurve;
     169            this->m_releasePosition = data.m_releasePosition;
     170            this->m_releaseTime = data.m_releaseTime;
     171            this->m_releaseCurve = data.m_releaseCurve;
     172        }
     173
     174        bool operator==(const SavePerAxisData& other) const
     175        {
     176            return m_currentVelocity == other.m_currentVelocity && m_desiredPosition == other.m_desiredPosition && m_desiredVelocity == other.m_desiredVelocity && m_startPosition == other.m_startPosition && m_startTime == other.m_startTime && m_startVelocity == other.m_startVelocity && m_animationTime == other.m_animationTime && m_lastAnimationTime == other.m_lastAnimationTime && m_attackPosition == other.m_attackPosition && m_attackTime == other.m_attackTime && m_attackCurve == other.m_attackCurve && m_releasePosition == other.m_releasePosition && m_releaseTime == other.m_releaseTime && m_releaseCurve == other.m_releaseCurve;
     177        }
     178        MockScrollAnimatorNone m_mockScrollAnimatorNone;
     179    };
     180
    150181    ScrollAnimatorNoneTest()
    151182    {
     
    155186    {
    156187        m_currentPosition = 100;
    157         m_data = new ScrollAnimatorNone::PerAxisData(&m_mockScrollAnimatorNone, &m_currentPosition);
     188        m_data = new ScrollAnimatorNone::PerAxisData(&m_mockScrollAnimatorNone, &m_currentPosition, 768);
    158189    }
    159190    virtual void TearDown()
     
    166197    bool animateScroll(double currentTime);
    167198
    168     double curveIntegralAt(ScrollAnimatorNone::Curve, double t);
    169199    double attackArea(ScrollAnimatorNone::Curve, double startT, double endT);
    170200    double releaseArea(ScrollAnimatorNone::Curve, double startT, double endT);
    171201    double attackCurve(ScrollAnimatorNone::Curve, double deltaT, double curveT, double startPosition, double attackPosition);
    172202    double releaseCurve(ScrollAnimatorNone::Curve, double deltaT, double curveT, double releasePosition, double desiredPosition);
    173     double curveDerivativeAt(ScrollAnimatorNone::Curve, double unitTime);
     203    double coastCurve(ScrollAnimatorNone::Curve, double factor);
    174204
    175205    void curveTestInner(ScrollAnimatorNone::Curve, double step, double time);
     
    215245    double deltaTime = m_data->m_lastAnimationTime - m_data->m_startTime;
    216246    double timeLeft = m_data->m_animationTime - deltaTime;
    217     double releaseTimeLeft = std::min(timeLeft, m_data->m_releaseTime);
    218     double attackTimeLeft = std::max(0., m_data->m_attackTime - deltaTime);
    219     double sustainTimeLeft = std::max(0., timeLeft - releaseTimeLeft - attackTimeLeft);
     247    double releaseTimeLeft = min(timeLeft, m_data->m_releaseTime);
     248    double attackTimeLeft = max(0., m_data->m_attackTime - deltaTime);
     249    double sustainTimeLeft = max(0., timeLeft - releaseTimeLeft - attackTimeLeft);
    220250
    221251    // If we're getting near the finish, the desired velocity can decrease since the time left gets increased.
     
    227257        EXPECT_GE(oldDesiredVelocity * allowedVelocityDecreaseFactor, m_data->m_desiredVelocity);
    228258
    229     double startPosition = m_scrollingDown ? std::max<double>(m_currentPosition, m_data->m_attackPosition) : std::min<double>(m_currentPosition, m_data->m_attackPosition);
     259    double startPosition = attackTimeLeft ? m_data->m_attackPosition : m_currentPosition;
    230260    double expectedReleasePosition = startPosition + sustainTimeLeft * m_data->m_desiredVelocity;
    231     if (result)
    232         EXPECT_DOUBLE_EQ(expectedReleasePosition, m_data->m_releasePosition);
    233     else
    234         EXPECT_NEAR(expectedReleasePosition, m_data->m_releasePosition, 1);
     261    EXPECT_NEAR(expectedReleasePosition, m_data->m_releasePosition, result ? .0001 : 1);
    235262
    236263    return result;
     
    246273    double deltaTime = m_data->m_lastAnimationTime - m_data->m_startTime;
    247274    double timeLeft = m_data->m_animationTime - deltaTime;
    248     double releaseTimeLeft = std::min(timeLeft, m_data->m_releaseTime);
    249     double attackTimeLeft = std::max(0., m_data->m_attackTime - deltaTime);
    250     double sustainTimeLeft = std::max(0., timeLeft - releaseTimeLeft - attackTimeLeft);
     275    double releaseTimeLeft = min(timeLeft, m_data->m_releaseTime);
     276    double attackTimeLeft = max(0., m_data->m_attackTime - deltaTime);
     277    double sustainTimeLeft = max(0., timeLeft - releaseTimeLeft - attackTimeLeft);
    251278    double distanceLeft = m_data->m_desiredPosition - *m_data->m_currentPosition;
    252279
     
    265292}
    266293
    267 double ScrollAnimatorNoneTest::curveIntegralAt(ScrollAnimatorNone::Curve curve, double t)
    268 {
    269     switch (curve) {
    270     case ScrollAnimatorNone::Linear:
    271         return t * t * t / 3;
    272     case ScrollAnimatorNone::Quadratic:
    273         return t * t * t * t / 4;
    274     case ScrollAnimatorNone::Cubic:
    275         return t * t * t * t * t / 5;
    276     case ScrollAnimatorNone::Bounce:
    277         double area;
    278         double t1 = std::min(t, 1 / 2.75);
    279         area = 2.52083 * t1 * t1 * t1;
    280         if (t < 1 / 2.75)
    281             return area;
    282         t1 = std::min(t - 1 / 2.75, 1 / 2.75);
    283         double bounceArea = t1 * (t1 * (2.52083 * t1 - 1.375) + 1);
    284         area += bounceArea;
    285         if (t < 2 / 2.75)
    286             return area;
    287         t1 = std::min(t - 2 / 2.75, 0.5 / 2.75);
    288         bounceArea =  t1 * (t1 * (2.52083 * t1 - 0.6875) + 1);
    289         area += bounceArea;
    290         if (t < 2.5 / 2.75)
    291             return area;
    292         t1 = t - 2.5 / 2.75;
    293         bounceArea = t1 * (t1 * (2.52083 * t1 - 0.34375) + 1);
    294         area += bounceArea;
    295         return area;
    296     }
    297 }
    298 
    299294double ScrollAnimatorNoneTest::attackArea(ScrollAnimatorNone::Curve curve, double startT, double endT)
    300295{
    301     double startValue = curveIntegralAt(curve, startT);
    302     double endValue = curveIntegralAt(curve, endT);
    303     return endValue - startValue;
     296    return ScrollAnimatorNone::PerAxisData::attackArea(curve, startT, endT);
    304297}
    305298
    306299double ScrollAnimatorNoneTest::releaseArea(ScrollAnimatorNone::Curve curve, double startT, double endT)
    307300{
    308     double startValue = curveIntegralAt(curve, 1 - endT);
    309     double endValue = curveIntegralAt(curve, 1 - startT);
    310     return endValue - startValue;
     301    return ScrollAnimatorNone::PerAxisData::releaseArea(curve, startT, endT);
    311302}
    312303
     
    321312}
    322313
    323 double ScrollAnimatorNoneTest::curveDerivativeAt(ScrollAnimatorNone::Curve curve, double unitTime)
    324 {
    325     return ScrollAnimatorNone::PerAxisData::curveDerivativeAt(curve, unitTime);
     314double ScrollAnimatorNoneTest::coastCurve(ScrollAnimatorNone::Curve curve, double factor)
     315{
     316    return ScrollAnimatorNone::PerAxisData::coastCurve(curve, factor);
    326317}
    327318
     
    344335        oldVelocity = velocity;
    345336        if (curve != ScrollAnimatorNone::Bounce) {
    346             EXPECT_LE(0, velocityDelta);
     337            EXPECT_LE(-.0001, velocityDelta);
    347338            EXPECT_LT(0, delta);
    348339        }
     
    355346    oldPos = 0;
    356347    oldVelocity *= 2;
    357     accumulate = attackArea(curve, 0, 1) * kPosition;
     348    accumulate = releaseArea(curve, 0, 1) * kPosition;
    358349    for (double t = step ; t <= time ; t += step) {
    359350        double newPos = releaseCurve(curve, t, time, 0, kPosition);
     
    411402}
    412403
     404TEST_F(ScrollAnimatorNoneTest, CurveMathQuartic)
     405{
     406    curveTest(ScrollAnimatorNone::Quartic);
     407}
     408
    413409TEST_F(ScrollAnimatorNoneTest, CurveMathBounce)
    414410{
     
    416412}
    417413
     414TEST_F(ScrollAnimatorNoneTest, CurveMathCoast)
     415{
     416    for (double t = .25; t < 1; t += .25) {
     417        EXPECT_EQ(t, coastCurve(ScrollAnimatorNone::Linear, t));
     418        EXPECT_LT(t, coastCurve(ScrollAnimatorNone::Quadratic, t));
     419        EXPECT_LT(t, coastCurve(ScrollAnimatorNone::Cubic, t));
     420        EXPECT_LT(coastCurve(ScrollAnimatorNone::Quadratic, t), coastCurve(ScrollAnimatorNone::Cubic, t));
     421        EXPECT_LT(t, coastCurve(ScrollAnimatorNone::Quartic, t));
     422        EXPECT_LT(coastCurve(ScrollAnimatorNone::Cubic, t), coastCurve(ScrollAnimatorNone::Quartic, t));
     423    }
     424}
     425
    418426TEST_F(ScrollAnimatorNoneTest, ScrollOnceLinear)
    419427{
    420     ScrollAnimatorNone::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimatorNone::Linear, 3 * kTickTime, ScrollAnimatorNone::Linear, 3 * kTickTime);
     428    ScrollAnimatorNone::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimatorNone::Linear, 3 * kTickTime, ScrollAnimatorNone::Linear, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
    421429
    422430    updateDataFromParameters(1, 40, 1000, kStartTime, &parameters);
     
    428436TEST_F(ScrollAnimatorNoneTest, ScrollOnceQuadratic)
    429437{
    430     ScrollAnimatorNone::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime);
     438    ScrollAnimatorNone::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
    431439
    432440    updateDataFromParameters(1, 40, 1000, kStartTime, &parameters);
     
    438446TEST_F(ScrollAnimatorNoneTest, ScrollLongQuadratic)
    439447{
    440     ScrollAnimatorNone::Parameters parameters(true, 20 * kTickTime, 0, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime);
     448    ScrollAnimatorNone::Parameters parameters(true, 20 * kTickTime, 0, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
    441449
    442450    updateDataFromParameters(1, 40, 1000, kStartTime, &parameters);
     
    448456TEST_F(ScrollAnimatorNoneTest, ScrollQuadraticNoSustain)
    449457{
    450     ScrollAnimatorNone::Parameters parameters(true, 8 * kTickTime, 0, ScrollAnimatorNone::Quadratic, 4 * kTickTime, ScrollAnimatorNone::Quadratic, 4 * kTickTime);
     458    ScrollAnimatorNone::Parameters parameters(true, 8 * kTickTime, 0, ScrollAnimatorNone::Quadratic, 4 * kTickTime, ScrollAnimatorNone::Quadratic, 4 * kTickTime, ScrollAnimatorNone::Linear, 0);
    451459
    452460    updateDataFromParameters(1, 40, 1000, kStartTime, &parameters);
     
    458466TEST_F(ScrollAnimatorNoneTest, ScrollQuadraticSmoothed)
    459467{
    460     ScrollAnimatorNone::Parameters parameters(true, 8 * kTickTime, 8 * kTickTime, ScrollAnimatorNone::Quadratic, 4 * kTickTime, ScrollAnimatorNone::Quadratic, 4 * kTickTime);
     468    ScrollAnimatorNone::Parameters parameters(true, 8 * kTickTime, 8 * kTickTime, ScrollAnimatorNone::Quadratic, 4 * kTickTime, ScrollAnimatorNone::Quadratic, 4 * kTickTime, ScrollAnimatorNone::Linear, 0);
    461469
    462470    updateDataFromParameters(1, 40, 1000, kStartTime, &parameters);
     
    468476TEST_F(ScrollAnimatorNoneTest, ScrollOnceCubic)
    469477{
    470     ScrollAnimatorNone::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime);
     478    ScrollAnimatorNone::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
    471479
    472480    updateDataFromParameters(1, 40, 1000, kStartTime, &parameters);
     
    476484}
    477485
     486TEST_F(ScrollAnimatorNoneTest, ScrollOnceQuartic)
     487{
     488    ScrollAnimatorNone::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimatorNone::Quartic, 3 * kTickTime, ScrollAnimatorNone::Quartic, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
     489
     490    updateDataFromParameters(1, 40, 1000, kStartTime, &parameters);
     491    bool result = true;
     492    for (double t = kStartTime; result && t < kEndTime; t += kAnimationTime)
     493        result = animateScroll(t);
     494}
     495
    478496TEST_F(ScrollAnimatorNoneTest, ScrollOnceShort)
    479497{
    480     ScrollAnimatorNone::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime);
     498    ScrollAnimatorNone::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
    481499
    482500    updateDataFromParameters(1, 40, 1000, kStartTime, &parameters);
     
    488506TEST_F(ScrollAnimatorNoneTest, ScrollTwiceQuadratic)
    489507{
    490     ScrollAnimatorNone::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime);
     508    ScrollAnimatorNone::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
    491509
    492510    updateDataFromParameters(1, 40, 1000, kStartTime, &parameters);
     
    519537TEST_F(ScrollAnimatorNoneTest, ScrollLotsQuadratic)
    520538{
    521     ScrollAnimatorNone::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime);
    522 
    523     updateDataFromParameters(1, 40, 1000, kStartTime, &parameters);
     539    ScrollAnimatorNone::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
     540
     541    updateDataFromParameters(1, 40, 10000, kStartTime, &parameters);
    524542    bool result = true;
    525543    double t;
     
    540558TEST_F(ScrollAnimatorNoneTest, ScrollLotsQuadraticSmoothed)
    541559{
    542     ScrollAnimatorNone::Parameters parameters(true, 10 * kTickTime, 6 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime);
    543 
    544     updateDataFromParameters(1, 40, 1000, kStartTime, &parameters);
     560    ScrollAnimatorNone::Parameters parameters(true, 10 * kTickTime, 6 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
     561
     562    updateDataFromParameters(1, 40, 10000, kStartTime, &parameters);
    545563    bool result = true;
    546564    double t;
     
    559577}
    560578
     579TEST_F(ScrollAnimatorNoneTest, ScrollTwiceCubic)
     580{
     581    ScrollAnimatorNone::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
     582
     583    updateDataFromParameters(1, 40, 1000, kStartTime, &parameters);
     584    bool result = true;
     585    double t;
     586    for (t = kStartTime; result && t < kStartTime + 1.5 * kTickTime; t += kAnimationTime)
     587        result = animateScroll(t);
     588
     589    result = result && animateScroll(t);
     590    double before = m_currentPosition;
     591    result = result && updateDataFromParameters(1, 40, 1000, t, &parameters);
     592    result = result && animateScroll(t);
     593    double after = m_currentPosition;
     594    EXPECT_NEAR(before, after, 10);
     595
     596    t += kAnimationTime;
     597
     598    result = result && animateScroll(t);
     599    before = m_currentPosition;
     600    result = result && updateDataFromParameters(1, 40, 1000, t, &parameters);
     601    result = result && animateScroll(t);
     602    after = m_currentPosition;
     603    EXPECT_NEAR(before, after, 10);
     604
     605    t += kAnimationTime;
     606    for (; result && t < kEndTime; t += kAnimationTime)
     607        result = animateScroll(t);
     608}
     609
     610TEST_F(ScrollAnimatorNoneTest, ScrollLotsCubic)
     611{
     612    ScrollAnimatorNone::Parameters parameters(true, 7 * kTickTime, 0, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
     613
     614    updateDataFromParameters(1, 40, 10000, kStartTime, &parameters);
     615    bool result = true;
     616    double t;
     617    for (t = kStartTime; result && t < kStartTime + 1.5 * kTickTime; t += kAnimationTime)
     618        result = animateScroll(t);
     619
     620    for (int i = 0; i < 20; ++i) {
     621        t += kAnimationTime;
     622        result = result && animateScroll(t);
     623        result = result && updateDataFromParameters(3, 40, 10000, t, &parameters);
     624    }
     625
     626    t += kAnimationTime;
     627    for (; result && t < kEndTime; t += kAnimationTime)
     628        result = result && animateScroll(t);
     629}
     630
     631TEST_F(ScrollAnimatorNoneTest, ScrollLotsCubicSmoothed)
     632{
     633    ScrollAnimatorNone::Parameters parameters(true, 10 * kTickTime, 6 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
     634
     635    updateDataFromParameters(1, 40, 10000, kStartTime, &parameters);
     636    bool result = true;
     637    double t;
     638    for (t = kStartTime; result && t < kStartTime + 1.5 * kTickTime; t += kAnimationTime)
     639        result = animateScroll(t);
     640
     641    for (int i = 0; i < 20; ++i) {
     642        t += kAnimationTime;
     643        result = result && animateScroll(t);
     644        result = result && updateDataFromParameters(3, 40, 10000, t, &parameters);
     645    }
     646
     647    t += kAnimationTime;
     648    for (; result && t < kEndTime; t += kAnimationTime)
     649        result = result && animateScroll(t);
     650}
     651
    561652TEST_F(ScrollAnimatorNoneTest, ScrollWheelTrace)
    562653{
    563     ScrollAnimatorNone::Parameters parameters(true, 11 * kTickTime, 0, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime);
     654    ScrollAnimatorNone::Parameters parameters(true, 11 * kTickTime, 0, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
    564655
    565656    // Constructed from an actual scroll wheel trace that exhibited a glitch.
     
    585676TEST_F(ScrollAnimatorNoneTest, ScrollWheelTraceSmoothed)
    586677{
    587     ScrollAnimatorNone::Parameters parameters(true, 11 * kTickTime, 7 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime);
     678    ScrollAnimatorNone::Parameters parameters(true, 11 * kTickTime, 7 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
    588679
    589680    // Constructed from an actual scroll wheel trace that exhibited a glitch.
     
    609700TEST_F(ScrollAnimatorNoneTest, LinuxTrackPadTrace)
    610701{
    611     ScrollAnimatorNone::Parameters parameters(true, 11 * kTickTime, 0, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime);
     702    ScrollAnimatorNone::Parameters parameters(true, 11 * kTickTime, 0, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
    612703
    613704    bool result = updateDataFromParameters(1.00, 60.00, 1000, 100.6863, &parameters);
     
    639730TEST_F(ScrollAnimatorNoneTest, LinuxTrackPadTraceSmoothed)
    640731{
    641     ScrollAnimatorNone::Parameters parameters(true, 11 * kTickTime, 7 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime);
     732    ScrollAnimatorNone::Parameters parameters(true, 11 * kTickTime, 7 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
    642733
    643734    bool result = updateDataFromParameters(1.00, 60.00, 1000, 100.6863, &parameters);
     
    669760TEST_F(ScrollAnimatorNoneTest, ScrollDownToBumper)
    670761{
    671     ScrollAnimatorNone::Parameters parameters(true, 10 * kTickTime, 7 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime);
     762    ScrollAnimatorNone::Parameters parameters(true, 10 * kTickTime, 7 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
    672763
    673764    updateDataFromParameters(1, 20, 200, kStartTime, &parameters);
     
    687778}
    688779
    689 
    690780TEST_F(ScrollAnimatorNoneTest, ScrollUpToBumper)
    691781{
    692     ScrollAnimatorNone::Parameters parameters(true, 10 * kTickTime, 7 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime, ScrollAnimatorNone::Quadratic, 3 * kTickTime);
     782    ScrollAnimatorNone::Parameters parameters(true, 10 * kTickTime, 7 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Linear, 0);
    693783
    694784    updateDataFromParameters(1, -20, 200, kStartTime, &parameters);
     
    708798}
    709799
     800TEST_F(ScrollAnimatorNoneTest, ScrollUpToBumperCoast)
     801{
     802    ScrollAnimatorNone::Parameters parameters(true, 11 * kTickTime, 2 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Linear, 1);
     803
     804    m_currentPosition = 40000;
     805    updateDataFromParameters(1, -10000, 50000, kStartTime, &parameters);
     806    bool result = true;
     807    double t = kStartTime;
     808    for (int i = 0; i < 10; ++i) {
     809        t += kAnimationTime;
     810        result = result && animateScroll(t);
     811        updateDataFromParameters(1, -10000, 50000, t, &parameters);
     812    }
     813    checkDesiredPosition(0);
     814
     815    t += kAnimationTime;
     816    for (; result && t < kEndTime; t += kAnimationTime)
     817        result = result && animateScroll(t);
     818    checkSoftLanding(0);
     819}
     820
     821TEST_F(ScrollAnimatorNoneTest, ScrollDownToBumperCoast)
     822{
     823    ScrollAnimatorNone::Parameters parameters(true, 11 * kTickTime, 2 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Cubic, 3 * kTickTime, ScrollAnimatorNone::Linear, 1);
     824
     825    m_currentPosition = 10000;
     826    updateDataFromParameters(1, 10000, 50000, kStartTime, &parameters);
     827    bool result = true;
     828    double t = kStartTime;
     829    for (int i = 0; i < 10; ++i) {
     830        t += kAnimationTime;
     831        result = result && animateScroll(t);
     832        updateDataFromParameters(1, 10000, 50000, t, &parameters);
     833    }
     834    checkDesiredPosition(50000);
     835
     836    t += kAnimationTime;
     837    for (; result && t < kEndTime; t += kAnimationTime)
     838        result = result && animateScroll(t);
     839    checkSoftLanding(50000);
     840}
     841
     842TEST_F(ScrollAnimatorNoneTest, VaryingInputsEquivalency)
     843{
     844    ScrollAnimatorNone::Parameters parameters(true, 15 * kTickTime, 10 * kTickTime, ScrollAnimatorNone::Cubic, 5 * kTickTime, ScrollAnimatorNone::Cubic, 5 * kTickTime, ScrollAnimatorNone::Linear, 0);
     845
     846    reset();
     847    updateDataFromParameters(1, 300, 50000, kStartTime, &parameters);
     848    SavePerAxisData dataSingle(*m_data);
     849
     850    reset();
     851    updateDataFromParameters(1, 150, 50000, kStartTime, &parameters);
     852    updateDataFromParameters(1, 150, 50000, kStartTime, &parameters);
     853    SavePerAxisData dataDouble(*m_data);
     854
     855    reset();
     856    updateDataFromParameters(1, 100, 50000, kStartTime, &parameters);
     857    updateDataFromParameters(1, 100, 50000, kStartTime, &parameters);
     858    updateDataFromParameters(1, 100, 50000, kStartTime, &parameters);
     859    SavePerAxisData dataTriple(*m_data);
     860
     861    reset();
     862    updateDataFromParameters(1, 50, 50000, kStartTime, &parameters);
     863    updateDataFromParameters(1, 50, 50000, kStartTime, &parameters);
     864    updateDataFromParameters(1, 50, 50000, kStartTime, &parameters);
     865    updateDataFromParameters(1, 50, 50000, kStartTime, &parameters);
     866    updateDataFromParameters(1, 50, 50000, kStartTime, &parameters);
     867    updateDataFromParameters(1, 50, 50000, kStartTime, &parameters);
     868    SavePerAxisData dataMany(*m_data);
     869
     870    EXPECT_EQ(dataSingle, dataDouble);
     871    EXPECT_EQ(dataSingle, dataTriple);
     872    EXPECT_EQ(dataSingle, dataMany);
     873}
     874
     875TEST_F(ScrollAnimatorNoneTest, VaryingInputsEquivalencyCoast)
     876{
     877    ScrollAnimatorNone::Parameters parameters(true, 15 * kTickTime, 10 * kTickTime, ScrollAnimatorNone::Cubic, 5 * kTickTime, ScrollAnimatorNone::Cubic, 5 * kTickTime, ScrollAnimatorNone::Linear, 1);
     878
     879    reset();
     880    updateDataFromParameters(1, 300, 50000, kStartTime, &parameters);
     881    SavePerAxisData dataSingle(*m_data);
     882
     883    reset();
     884    updateDataFromParameters(1, 150, 50000, kStartTime, &parameters);
     885    updateDataFromParameters(1, 150, 50000, kStartTime, &parameters);
     886    SavePerAxisData dataDouble(*m_data);
     887
     888    reset();
     889    updateDataFromParameters(1, 100, 50000, kStartTime, &parameters);
     890    updateDataFromParameters(1, 100, 50000, kStartTime, &parameters);
     891    updateDataFromParameters(1, 100, 50000, kStartTime, &parameters);
     892    SavePerAxisData dataTriple(*m_data);
     893
     894    reset();
     895    updateDataFromParameters(1, 50, 50000, kStartTime, &parameters);
     896    updateDataFromParameters(1, 50, 50000, kStartTime, &parameters);
     897    updateDataFromParameters(1, 50, 50000, kStartTime, &parameters);
     898    updateDataFromParameters(1, 50, 50000, kStartTime, &parameters);
     899    updateDataFromParameters(1, 50, 50000, kStartTime, &parameters);
     900    updateDataFromParameters(1, 50, 50000, kStartTime, &parameters);
     901    SavePerAxisData dataMany(*m_data);
     902
     903    EXPECT_EQ(dataSingle, dataDouble);
     904    EXPECT_EQ(dataSingle, dataTriple);
     905    EXPECT_EQ(dataSingle, dataMany);
     906}
     907
     908TEST_F(ScrollAnimatorNoneTest, VaryingInputsEquivalencyCoastLarge)
     909{
     910    ScrollAnimatorNone::Parameters parameters(true, 15 * kTickTime, 10 * kTickTime, ScrollAnimatorNone::Cubic, 5 * kTickTime, ScrollAnimatorNone::Cubic, 5 * kTickTime, ScrollAnimatorNone::Linear, 1);
     911
     912    reset();
     913    updateDataFromParameters(1, 30000, 50000, kStartTime, &parameters);
     914    SavePerAxisData dataSingle(*m_data);
     915
     916    reset();
     917    updateDataFromParameters(1, 15000, 50000, kStartTime, &parameters);
     918    updateDataFromParameters(1, 15000, 50000, kStartTime, &parameters);
     919    SavePerAxisData dataDouble(*m_data);
     920
     921    reset();
     922    updateDataFromParameters(1, 10000, 50000, kStartTime, &parameters);
     923    updateDataFromParameters(1, 10000, 50000, kStartTime, &parameters);
     924    updateDataFromParameters(1, 10000, 50000, kStartTime, &parameters);
     925    SavePerAxisData dataTriple(*m_data);
     926
     927    reset();
     928    updateDataFromParameters(1, 5000, 50000, kStartTime, &parameters);
     929    updateDataFromParameters(1, 5000, 50000, kStartTime, &parameters);
     930    updateDataFromParameters(1, 5000, 50000, kStartTime, &parameters);
     931    updateDataFromParameters(1, 5000, 50000, kStartTime, &parameters);
     932    updateDataFromParameters(1, 5000, 50000, kStartTime, &parameters);
     933    updateDataFromParameters(1, 5000, 50000, kStartTime, &parameters);
     934    SavePerAxisData dataMany(*m_data);
     935
     936    EXPECT_EQ(dataSingle, dataDouble);
     937    EXPECT_EQ(dataSingle, dataTriple);
     938    EXPECT_EQ(dataSingle, dataMany);
     939}
     940
     941TEST_F(ScrollAnimatorNoneTest, VaryingInputsEquivalencyCoastSteep)
     942{
     943    ScrollAnimatorNone::Parameters parameters(true, 15 * kTickTime, 10 * kTickTime, ScrollAnimatorNone::Cubic, 5 * kTickTime, ScrollAnimatorNone::Cubic, 5 * kTickTime, ScrollAnimatorNone::Quadratic, 1);
     944
     945    reset();
     946    updateDataFromParameters(1, 30000, 50000, kStartTime, &parameters);
     947    SavePerAxisData dataSingle(*m_data);
     948
     949    reset();
     950    updateDataFromParameters(1, 15000, 50000, kStartTime, &parameters);
     951    updateDataFromParameters(1, 15000, 50000, kStartTime, &parameters);
     952    SavePerAxisData dataDouble(*m_data);
     953
     954    reset();
     955    updateDataFromParameters(1, 10000, 50000, kStartTime, &parameters);
     956    updateDataFromParameters(1, 10000, 50000, kStartTime, &parameters);
     957    updateDataFromParameters(1, 10000, 50000, kStartTime, &parameters);
     958    SavePerAxisData dataTriple(*m_data);
     959
     960    reset();
     961    updateDataFromParameters(1, 5000, 50000, kStartTime, &parameters);
     962    updateDataFromParameters(1, 5000, 50000, kStartTime, &parameters);
     963    updateDataFromParameters(1, 5000, 50000, kStartTime, &parameters);
     964    updateDataFromParameters(1, 5000, 50000, kStartTime, &parameters);
     965    updateDataFromParameters(1, 5000, 50000, kStartTime, &parameters);
     966    updateDataFromParameters(1, 5000, 50000, kStartTime, &parameters);
     967    SavePerAxisData dataMany(*m_data);
     968
     969    EXPECT_EQ(dataSingle, dataDouble);
     970    EXPECT_EQ(dataSingle, dataTriple);
     971    EXPECT_EQ(dataSingle, dataMany);
     972}
     973
     974
    710975#endif // ENABLE(SMOOTH_SCROLLING)
Note: See TracChangeset for help on using the changeset viewer.