15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (c) 2011, Google Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/scroll/ScrollAnimatorNone.h"
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <algorithm>
36a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/scroll/ScrollableArea.h"
377757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/CurrentTime.h"
387757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/PassOwnPtr.h"
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
401e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/TraceEvent.h"
41926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace std;
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const double kFrameRate = 60;
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const double kTickTime = 1 / kFrameRate;
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const double kMinimumTimerInterval = .001;
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassOwnPtr<ScrollAnimator> ScrollAnimator::create(ScrollableArea* scrollableArea)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (scrollableArea && scrollableArea->scrollAnimatorEnabled())
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return adoptPtr(new ScrollAnimatorNone(scrollableArea));
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return adoptPtr(new ScrollAnimator(scrollableArea));
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ScrollAnimatorNone::Parameters::Parameters()
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_isEnabled(false)
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ScrollAnimatorNone::Parameters::Parameters(bool isEnabled, double animationTime, double repeatMinimumSustainTime, Curve attackCurve, double attackTime, Curve releaseCurve, double releaseTime, Curve coastTimeCurve, double maximumCoastTime)
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_isEnabled(isEnabled)
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_animationTime(animationTime)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_repeatMinimumSustainTime(repeatMinimumSustainTime)
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_attackCurve(attackCurve)
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_attackTime(attackTime)
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_releaseCurve(releaseCurve)
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_releaseTime(releaseTime)
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_coastTimeCurve(coastTimeCurve)
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_maximumCoastTime(maximumCoastTime)
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)double ScrollAnimatorNone::PerAxisData::curveAt(Curve curve, double t)
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (curve) {
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case Linear:
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return t;
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case Quadratic:
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return t * t;
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case Cubic:
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return t * t * t;
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case Quartic:
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return t * t * t * t;
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case Bounce:
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Time base is chosen to keep the bounce points simpler:
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // 1 (half bounce coming in) + 1 + .5 + .25
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const double kTimeBase = 2.75;
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const double kTimeBaseSquared = kTimeBase * kTimeBase;
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (t < 1 / kTimeBase)
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return kTimeBaseSquared * t * t;
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (t < 2 / kTimeBase) {
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Invert a [-.5,.5] quadratic parabola, center it in [1,2].
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            double t1 = t - 1.5 / kTimeBase;
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            const double kParabolaAtEdge = 1 - .5 * .5;
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return kTimeBaseSquared * t1 * t1 + kParabolaAtEdge;
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (t < 2.5 / kTimeBase) {
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Invert a [-.25,.25] quadratic parabola, center it in [2,2.5].
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            double t2 = t - 2.25 / kTimeBase;
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            const double kParabolaAtEdge = 1 - .25 * .25;
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return kTimeBaseSquared * t2 * t2 + kParabolaAtEdge;
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Invert a [-.125,.125] quadratic parabola, center it in [2.5,2.75].
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const double kParabolaAtEdge = 1 - .125 * .125;
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        t -= 2.625 / kTimeBase;
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return kTimeBaseSquared * t * t + kParabolaAtEdge;
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_NOT_REACHED();
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)double ScrollAnimatorNone::PerAxisData::attackCurve(Curve curve, double deltaTime, double curveT, double startPosition, double attackPosition)
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double t = deltaTime / curveT;
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double positionFactor = curveAt(curve, t);
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return startPosition + positionFactor * (attackPosition - startPosition);
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)double ScrollAnimatorNone::PerAxisData::releaseCurve(Curve curve, double deltaTime, double curveT, double releasePosition, double desiredPosition)
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double t = deltaTime / curveT;
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double positionFactor = 1 - curveAt(curve, 1 - t);
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return releasePosition + (positionFactor * (desiredPosition - releasePosition));
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)double ScrollAnimatorNone::PerAxisData::coastCurve(Curve curve, double factor)
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 1 - curveAt(curve, 1 - factor);
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)double ScrollAnimatorNone::PerAxisData::curveIntegralAt(Curve curve, double t)
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (curve) {
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case Linear:
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return t * t / 2;
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case Quadratic:
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return t * t * t / 3;
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case Cubic:
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return t * t * t * t / 4;
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case Quartic:
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return t * t * t * t * t / 5;
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case Bounce:
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const double kTimeBase = 2.75;
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const double kTimeBaseSquared = kTimeBase * kTimeBase;
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const double kTimeBaseSquaredOverThree = kTimeBaseSquared / 3;
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        double area;
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        double t1 = min(t, 1 / kTimeBase);
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        area = kTimeBaseSquaredOverThree * t1 * t1 * t1;
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (t < 1 / kTimeBase)
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return area;
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        t1 = min(t - 1 / kTimeBase, 1 / kTimeBase);
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // The integral of kTimeBaseSquared * (t1 - .5 / kTimeBase) * (t1 - .5 / kTimeBase) + kParabolaAtEdge
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const double kSecondInnerOffset = kTimeBaseSquared * .5 / kTimeBase;
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        double bounceArea = t1 * (t1 * (kTimeBaseSquaredOverThree * t1 - kSecondInnerOffset) + 1);
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        area += bounceArea;
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (t < 2 / kTimeBase)
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return area;
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        t1 = min(t - 2 / kTimeBase, 0.5 / kTimeBase);
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // The integral of kTimeBaseSquared * (t1 - .25 / kTimeBase) * (t1 - .25 / kTimeBase) + kParabolaAtEdge
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const double kThirdInnerOffset = kTimeBaseSquared * .25 / kTimeBase;
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bounceArea =  t1 * (t1 * (kTimeBaseSquaredOverThree * t1 - kThirdInnerOffset) + 1);
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        area += bounceArea;
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (t < 2.5 / kTimeBase)
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return area;
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        t1 = t - 2.5 / kTimeBase;
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // The integral of kTimeBaseSquared * (t1 - .125 / kTimeBase) * (t1 - .125 / kTimeBase) + kParabolaAtEdge
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const double kFourthInnerOffset = kTimeBaseSquared * .125 / kTimeBase;
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bounceArea = t1 * (t1 * (kTimeBaseSquaredOverThree * t1 - kFourthInnerOffset) + 1);
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        area += bounceArea;
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return area;
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_NOT_REACHED();
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)double ScrollAnimatorNone::PerAxisData::attackArea(Curve curve, double startT, double endT)
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double startValue = curveIntegralAt(curve, startT);
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double endValue = curveIntegralAt(curve, endT);
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return endValue - startValue;
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)double ScrollAnimatorNone::PerAxisData::releaseArea(Curve curve, double startT, double endT)
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double startValue = curveIntegralAt(curve, 1 - endT);
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double endValue = curveIntegralAt(curve, 1 - startT);
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return endValue - startValue;
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ScrollAnimatorNone::PerAxisData::PerAxisData(ScrollAnimatorNone* parent, float* currentPosition, int visibleLength)
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_currentPosition(currentPosition)
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_visibleLength(visibleLength)
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    reset();
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ScrollAnimatorNone::PerAxisData::reset()
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_currentVelocity = 0;
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_desiredPosition = 0;
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_desiredVelocity = 0;
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_startPosition = 0;
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_startTime = 0;
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_startVelocity = 0;
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_animationTime = 0;
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_lastAnimationTime = 0;
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_attackPosition = 0;
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_attackTime = 0;
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_attackCurve = Quadratic;
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_releasePosition = 0;
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_releaseTime = 0;
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_releaseCurve = Quadratic;
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
22609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)bool ScrollAnimatorNone::PerAxisData::updateDataFromParameters(float step, float delta, float scrollableSize, double currentTime, Parameters* parameters)
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
22809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    float pixelDelta = step * delta;
22909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!m_startTime || !pixelDelta || (pixelDelta < 0) != (m_desiredPosition - *m_currentPosition < 0)) {
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_desiredPosition = *m_currentPosition;
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_startTime = 0;
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
23309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    float newPosition = m_desiredPosition + pixelDelta;
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (newPosition < 0 || newPosition > scrollableSize)
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        newPosition = max(min(newPosition, scrollableSize), 0.0f);
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (newPosition == m_desiredPosition)
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_desiredPosition = newPosition;
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_startTime) {
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_attackTime = parameters->m_attackTime;
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_attackCurve = parameters->m_attackCurve;
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_animationTime = parameters->m_animationTime;
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_releaseTime = parameters->m_releaseTime;
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_releaseCurve = parameters->m_releaseCurve;
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Prioritize our way out of over constraint.
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_attackTime + m_releaseTime > m_animationTime) {
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_releaseTime > m_animationTime)
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_releaseTime = m_animationTime;
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_attackTime = m_animationTime - m_releaseTime;
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_startTime) {
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: This should be the time from the event that got us here.
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_startTime = currentTime - kTickTime / 2;
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_startPosition = *m_currentPosition;
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_lastAnimationTime = m_startTime;
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_startVelocity = m_currentVelocity;
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double remainingDelta = m_desiredPosition - *m_currentPosition;
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double attackAreaLeft = 0;
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double deltaTime = m_lastAnimationTime - m_startTime;
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double attackTimeLeft = max(0., m_attackTime - deltaTime);
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double timeLeft = m_animationTime - deltaTime;
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double minTimeLeft = m_releaseTime + min(parameters->m_repeatMinimumSustainTime, m_animationTime - m_releaseTime - attackTimeLeft);
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (timeLeft < minTimeLeft) {
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_animationTime = deltaTime + minTimeLeft;
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        timeLeft = minTimeLeft;
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (parameters->m_maximumCoastTime > (parameters->m_repeatMinimumSustainTime + parameters->m_releaseTime)) {
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        double targetMaxCoastVelocity = m_visibleLength * .25 * kFrameRate;
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // This needs to be as minimal as possible while not being intrusive to page up/down.
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        double minCoastDelta = m_visibleLength;
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (fabs(remainingDelta) > minCoastDelta) {
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            double maxCoastDelta = parameters->m_maximumCoastTime * targetMaxCoastVelocity;
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            double coastFactor = min(1., (fabs(remainingDelta) - minCoastDelta) / (maxCoastDelta - minCoastDelta));
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // 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.
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            double coastMinTimeLeft = min(parameters->m_maximumCoastTime, minTimeLeft + coastCurve(parameters->m_coastTimeCurve, coastFactor) * (parameters->m_maximumCoastTime - minTimeLeft));
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            double additionalTime = max(0., coastMinTimeLeft - minTimeLeft);
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (additionalTime) {
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                double additionalReleaseTime = min(additionalTime, parameters->m_releaseTime / (parameters->m_releaseTime + parameters->m_repeatMinimumSustainTime) * additionalTime);
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                m_releaseTime = parameters->m_releaseTime + additionalReleaseTime;
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                m_animationTime = deltaTime + coastMinTimeLeft;
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                timeLeft = coastMinTimeLeft;
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double releaseTimeLeft = min(timeLeft, m_releaseTime);
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double sustainTimeLeft = max(0., timeLeft - releaseTimeLeft - attackTimeLeft);
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (attackTimeLeft) {
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        double attackSpot = deltaTime / m_attackTime;
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        attackAreaLeft = attackArea(m_attackCurve, attackSpot, 1) * m_attackTime;
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double releaseSpot = (m_releaseTime - releaseTimeLeft) / m_releaseTime;
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double releaseAreaLeft  = releaseArea(m_releaseCurve, releaseSpot, 1) * m_releaseTime;
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_desiredVelocity = remainingDelta / (attackAreaLeft + sustainTimeLeft + releaseAreaLeft);
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_releasePosition = m_desiredPosition - m_desiredVelocity * releaseAreaLeft;
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (attackAreaLeft)
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_attackPosition = m_startPosition + m_desiredVelocity * attackAreaLeft;
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_attackPosition = m_releasePosition - (m_animationTime - m_releaseTime - m_attackTime) * m_desiredVelocity;
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (sustainTimeLeft) {
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        double roundOff = m_releasePosition - ((attackAreaLeft ? m_attackPosition : *m_currentPosition) + m_desiredVelocity * sustainTimeLeft);
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_desiredVelocity += roundOff / sustainTimeLeft;
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
32710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdochinline double ScrollAnimatorNone::PerAxisData::newScrollAnimationPosition(double deltaTime)
32810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch{
32910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    if (deltaTime < m_attackTime)
33010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        return attackCurve(m_attackCurve, deltaTime, m_attackTime, m_startPosition, m_attackPosition);
33110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    if (deltaTime < (m_animationTime - m_releaseTime))
33210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        return m_attackPosition + (deltaTime - m_attackTime) * m_desiredVelocity;
33310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    // release is based on targeting the exact final position.
33410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    double releaseDeltaT = deltaTime - (m_animationTime - m_releaseTime);
33510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    return releaseCurve(m_releaseCurve, releaseDeltaT, m_releaseTime, m_releasePosition, m_desiredPosition);
33610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch}
33710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// FIXME: Add in jank detection trace events into this function.
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool ScrollAnimatorNone::PerAxisData::animateScroll(double currentTime)
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double lastScrollInterval = currentTime - m_lastAnimationTime;
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (lastScrollInterval < kMinimumTimerInterval)
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_lastAnimationTime = currentTime;
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double deltaTime = currentTime - m_startTime;
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (deltaTime > m_animationTime) {
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        *m_currentPosition = m_desiredPosition;
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        reset();
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
35410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    double newPosition = newScrollAnimationPosition(deltaTime);
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Normalize velocity to a per second amount. Could be used to check for jank.
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (lastScrollInterval > 0)
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_currentVelocity = (newPosition - *m_currentPosition) / lastScrollInterval;
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    *m_currentPosition = newPosition;
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ScrollAnimatorNone::PerAxisData::updateVisibleLength(int visibleLength)
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_visibleLength = visibleLength;
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ScrollAnimatorNone::ScrollAnimatorNone(ScrollableArea* scrollableArea)
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : ScrollAnimator(scrollableArea)
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_horizontalData(this, &m_currentPosX, scrollableArea->visibleWidth())
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_verticalData(this, &m_currentPosY, scrollableArea->visibleHeight())
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_startTime(0)
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_animationActive(false)
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ScrollAnimatorNone::~ScrollAnimatorNone()
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    stopAnimationTimerIfNeeded();
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ScrollAnimatorNone::Parameters ScrollAnimatorNone::parametersForScrollGranularity(ScrollGranularity granularity) const
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (granularity) {
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case ScrollByDocument:
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return Parameters(true, 20 * kTickTime, 10 * kTickTime, Cubic, 10 * kTickTime, Cubic, 10 * kTickTime, Linear, 1);
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case ScrollByLine:
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return Parameters(true, 10 * kTickTime, 7 * kTickTime, Cubic, 3 * kTickTime, Cubic, 3 * kTickTime, Linear, 1);
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case ScrollByPage:
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return Parameters(true, 15 * kTickTime, 10 * kTickTime, Cubic, 5 * kTickTime, Cubic, 5 * kTickTime, Linear, 1);
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case ScrollByPixel:
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return Parameters(true, 11 * kTickTime, 2 * kTickTime, Cubic, 3 * kTickTime, Cubic, 3 * kTickTime, Quadratic, 1.25);
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    default:
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT_NOT_REACHED();
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return Parameters();
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
39909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)bool ScrollAnimatorNone::scroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float delta)
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_scrollableArea->scrollAnimatorEnabled())
40209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return ScrollAnimator::scroll(orientation, granularity, step, delta);
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    TRACE_EVENT0("webkit", "ScrollAnimatorNone::scroll");
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: get the type passed in. MouseWheel could also be by line, but should still have different
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // animation parameters than the keyboard.
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Parameters parameters;
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (granularity) {
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case ScrollByDocument:
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case ScrollByLine:
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case ScrollByPage:
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case ScrollByPixel:
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        parameters = parametersForScrollGranularity(granularity);
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case ScrollByPrecisePixel:
41709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return ScrollAnimator::scroll(orientation, granularity, step, delta);
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the individual input setting is disabled, bail.
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!parameters.m_isEnabled)
42209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return ScrollAnimator::scroll(orientation, granularity, step, delta);
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This is an animatable scroll. Set the animation in motion using the appropriate parameters.
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float scrollableSize = static_cast<float>(m_scrollableArea->scrollSize(orientation));
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    PerAxisData& data = (orientation == VerticalScrollbar) ? m_verticalData : m_horizontalData;
42809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    bool needToScroll = data.updateDataFromParameters(step, delta, scrollableSize, WTF::monotonicallyIncreasingTime(), &parameters);
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (needToScroll && !animationTimerActive()) {
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_startTime = data.m_startTime;
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        animationWillStart();
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        animationTimerFired();
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return needToScroll;
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ScrollAnimatorNone::scrollToOffsetWithoutAnimation(const FloatPoint& offset)
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    stopAnimationTimerIfNeeded();
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_horizontalData.reset();
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    *m_horizontalData.m_currentPosition = offset.x();
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_horizontalData.m_desiredPosition = offset.x();
444aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    m_currentPosX = offset.x();
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_verticalData.reset();
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    *m_verticalData.m_currentPosition = offset.y();
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_verticalData.m_desiredPosition = offset.y();
449aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    m_currentPosY = offset.y();
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
451aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    notifyPositionChanged();
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ScrollAnimatorNone::cancelAnimations()
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_animationActive = false;
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ScrollAnimatorNone::serviceScrollAnimations()
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_animationActive)
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        animationTimerFired();
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ScrollAnimatorNone::willEndLiveResize()
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateVisibleLengths();
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ScrollAnimatorNone::didAddVerticalScrollbar(Scrollbar*)
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateVisibleLengths();
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ScrollAnimatorNone::didAddHorizontalScrollbar(Scrollbar*)
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateVisibleLengths();
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ScrollAnimatorNone::updateVisibleLengths()
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_horizontalData.updateVisibleLength(scrollableArea()->visibleWidth());
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_verticalData.updateVisibleLength(scrollableArea()->visibleHeight());
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ScrollAnimatorNone::animationTimerFired()
4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    TRACE_EVENT0("webkit", "ScrollAnimatorNone::animationTimerFired");
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double currentTime = WTF::monotonicallyIncreasingTime();
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool continueAnimation = false;
4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_horizontalData.m_startTime && m_horizontalData.animateScroll(currentTime))
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        continueAnimation = true;
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_verticalData.m_startTime && m_verticalData.animateScroll(currentTime))
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        continueAnimation = true;
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (continueAnimation)
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        startNextTimer();
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_animationActive = false;
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    TRACE_EVENT0("webkit", "ScrollAnimatorNone::notifyPositionChanged");
504aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    notifyPositionChanged();
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!continueAnimation)
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        animationDidFinish();
5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ScrollAnimatorNone::startNextTimer()
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (scrollableArea()->scheduleAnimation())
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_animationActive = true;
5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool ScrollAnimatorNone::animationTimerActive()
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_animationActive;
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ScrollAnimatorNone::stopAnimationTimerIfNeeded()
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (animationTimerActive())
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_animationActive = false;
5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore
528