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