105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2010 Google Inc.
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger */
805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "FlingState.h"
1205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "SkMatrix.h"
1305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "SkTime.h"
1405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
1505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#define DISCRETIZE_TRANSLATE_TO_AVOID_FLICKER   true
1605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
1705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerstatic const float MAX_FLING_SPEED = 1500;
1805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
1905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerstatic float pin_max_fling(float speed) {
2005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (speed > MAX_FLING_SPEED) {
2105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        speed = MAX_FLING_SPEED;
2205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
2305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    return speed;
2405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
2505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
2605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerstatic double getseconds() {
2705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    return SkTime::GetMSecs() * 0.001;
2805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
2905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
3005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger// returns +1 or -1, depending on the sign of x
3105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger// returns +1 if x is zero
3205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerstatic SkScalar SkScalarSign(SkScalar x) {
3305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    SkScalar sign = SK_Scalar1;
3405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (x < 0) {
3505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        sign = -sign;
3605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
3705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    return sign;
3805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
3905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
4005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerstatic void unit_axis_align(SkVector* unit) {
4105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    const SkScalar TOLERANCE = SkDoubleToScalar(0.15);
4205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (SkScalarAbs(unit->fX) < TOLERANCE) {
4305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        unit->fX = 0;
4405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        unit->fY = SkScalarSign(unit->fY);
4505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    } else if (SkScalarAbs(unit->fY) < TOLERANCE) {
4605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        unit->fX = SkScalarSign(unit->fX);
4705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        unit->fY = 0;
4805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
4905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
5005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
5105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergervoid FlingState::reset(float sx, float sy) {
5205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fActive = true;
5305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fDirection.set(sx, sy);
5405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fSpeed0 = SkPoint::Normalize(&fDirection);
5505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fSpeed0 = pin_max_fling(fSpeed0);
5605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fTime0 = getseconds();
5705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
5805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    unit_axis_align(&fDirection);
5905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger//    printf("---- speed %g dir %g %g\n", fSpeed0, fDirection.fX, fDirection.fY);
6005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
6105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
6205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerbool FlingState::evaluateMatrix(SkMatrix* matrix) {
6305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (!fActive) {
6405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        return false;
6505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
6605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
6705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    const float t =  getseconds() - fTime0;
6805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    const float MIN_SPEED = 2;
6905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    const float K0 = 5.0;
7005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    const float K1 = 0.02;
7105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    const float speed = fSpeed0 * (sk_float_exp(- K0 * t) - K1);
7205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (speed <= MIN_SPEED) {
7305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fActive = false;
7405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        return false;
7505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
7605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    float dist = (fSpeed0 - speed) / K0;
7705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
7805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger//    printf("---- time %g speed %g dist %g\n", t, speed, dist);
7905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    float tx = fDirection.fX * dist;
8005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    float ty = fDirection.fY * dist;
8105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (DISCRETIZE_TRANSLATE_TO_AVOID_FLICKER) {
8205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        tx = sk_float_round2int(tx);
8305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        ty = sk_float_round2int(ty);
8405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
8505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    matrix->setTranslate(tx, ty);
8605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger//    printf("---- evaluate (%g %g)\n", tx, ty);
8705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
8805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    return true;
8905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
9005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
9105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger////////////////////////////////////////
9205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
9305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek SollenbergerGrAnimateFloat::GrAnimateFloat() : fTime0(0) {}
9405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
9505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergervoid GrAnimateFloat::start(float v0, float v1, float duration) {
9605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fValue0 = v0;
9705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fValue1 = v1;
9805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fDuration = duration;
9905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (duration > 0) {
10005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fTime0 = SkTime::GetMSecs();
10105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        if (!fTime0) {
10205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            fTime0 = 1;  // time0 is our sentinel
10305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        }
10405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    } else {
10505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fTime0 = 0;
10605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
10705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
10805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
10905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerfloat GrAnimateFloat::evaluate() {
11005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (!fTime0) {
11105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        return fValue1;
11205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
11305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
11405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    double elapsed = (SkTime::GetMSecs() - fTime0) * 0.001;
11505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (elapsed >= fDuration) {
11605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fTime0 = 0;
11705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        return fValue1;
11805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
11905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
12005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    double t = elapsed / fDuration;
12105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (true) {
12205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        t = (3 - 2 * t) * t * t;
12305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
12405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    return fValue0 + t * (fValue1 - fValue0);
12505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
12605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
12705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
128