105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger/*
205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    Copyright 2010 Google Inc.
305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    Licensed under the Apache License, Version 2.0 (the "License");
505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    you may not use this file except in compliance with the License.
605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    You may obtain a copy of the License at
705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger         http://www.apache.org/licenses/LICENSE-2.0
905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
1005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    Unless required by applicable law or agreed to in writing, software
1105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    distributed under the License is distributed on an "AS IS" BASIS,
1205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    See the License for the specific language governing permissions and
1405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    limitations under the License.
1505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger */
1605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
1705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
1805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "FlingState.h"
1905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "SkMatrix.h"
2005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#include "SkTime.h"
2105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
2205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#define DISCRETIZE_TRANSLATE_TO_AVOID_FLICKER   true
2305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
2405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerstatic const float MAX_FLING_SPEED = 1500;
2505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
2605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerstatic float pin_max_fling(float speed) {
2705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (speed > MAX_FLING_SPEED) {
2805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        speed = MAX_FLING_SPEED;
2905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
3005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    return speed;
3105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
3205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
3305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerstatic double getseconds() {
3405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    return SkTime::GetMSecs() * 0.001;
3505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
3605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
3705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger// returns +1 or -1, depending on the sign of x
3805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger// returns +1 if x is zero
3905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerstatic SkScalar SkScalarSign(SkScalar x) {
4005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    SkScalar sign = SK_Scalar1;
4105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (x < 0) {
4205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        sign = -sign;
4305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
4405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    return sign;
4505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
4605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
4705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerstatic void unit_axis_align(SkVector* unit) {
4805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    const SkScalar TOLERANCE = SkDoubleToScalar(0.15);
4905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (SkScalarAbs(unit->fX) < TOLERANCE) {
5005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        unit->fX = 0;
5105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        unit->fY = SkScalarSign(unit->fY);
5205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    } else if (SkScalarAbs(unit->fY) < TOLERANCE) {
5305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        unit->fX = SkScalarSign(unit->fX);
5405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        unit->fY = 0;
5505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
5605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
5705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
5805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergervoid FlingState::reset(float sx, float sy) {
5905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fActive = true;
6005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fDirection.set(sx, sy);
6105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fSpeed0 = SkPoint::Normalize(&fDirection);
6205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fSpeed0 = pin_max_fling(fSpeed0);
6305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fTime0 = getseconds();
6405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
6505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    unit_axis_align(&fDirection);
6605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger//    printf("---- speed %g dir %g %g\n", fSpeed0, fDirection.fX, fDirection.fY);
6705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
6805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
6905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerbool FlingState::evaluateMatrix(SkMatrix* matrix) {
7005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (!fActive) {
7105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        return false;
7205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
7305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
7405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    const float t =  getseconds() - fTime0;
7505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    const float MIN_SPEED = 2;
7605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    const float K0 = 5.0;
7705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    const float K1 = 0.02;
7805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    const float speed = fSpeed0 * (sk_float_exp(- K0 * t) - K1);
7905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (speed <= MIN_SPEED) {
8005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fActive = false;
8105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        return false;
8205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
8305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    float dist = (fSpeed0 - speed) / K0;
8405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
8505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger//    printf("---- time %g speed %g dist %g\n", t, speed, dist);
8605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    float tx = fDirection.fX * dist;
8705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    float ty = fDirection.fY * dist;
8805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (DISCRETIZE_TRANSLATE_TO_AVOID_FLICKER) {
8905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        tx = sk_float_round2int(tx);
9005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        ty = sk_float_round2int(ty);
9105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
9205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    matrix->setTranslate(tx, ty);
9305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger//    printf("---- evaluate (%g %g)\n", tx, ty);
9405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
9505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    return true;
9605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
9705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
9805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger////////////////////////////////////////
9905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
10005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek SollenbergerGrAnimateFloat::GrAnimateFloat() : fTime0(0) {}
10105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
10205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergervoid GrAnimateFloat::start(float v0, float v1, float duration) {
10305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fValue0 = v0;
10405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fValue1 = v1;
10505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    fDuration = duration;
10605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (duration > 0) {
10705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fTime0 = SkTime::GetMSecs();
10805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        if (!fTime0) {
10905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger            fTime0 = 1;  // time0 is our sentinel
11005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        }
11105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    } else {
11205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fTime0 = 0;
11305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
11405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
11505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
11605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerfloat GrAnimateFloat::evaluate() {
11705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (!fTime0) {
11805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        return fValue1;
11905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
12005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
12105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    double elapsed = (SkTime::GetMSecs() - fTime0) * 0.001;
12205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (elapsed >= fDuration) {
12305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        fTime0 = 0;
12405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        return fValue1;
12505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
12605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
12705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    double t = elapsed / fDuration;
12805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    if (true) {
12905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger        t = (3 - 2 * t) * t * t;
13005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
13105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    return fValue0 + t * (fValue1 - fValue0);
13205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}
13305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
13405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
135