152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2010 Google Inc. 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com */ 852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 10ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 1152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com#include "SkTouchGesture.h" 1252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com#include "SkMatrix.h" 1352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com#include "SkTime.h" 1452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 1552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com#define DISCRETIZE_TRANSLATE_TO_AVOID_FLICKER true 1652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 1759f46b81f8bdd1b524f5cc43bc27603f9604c71arobertphillips@google.comstatic const SkScalar MAX_FLING_SPEED = SkIntToScalar(1500); 1852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 1959f46b81f8bdd1b524f5cc43bc27603f9604c71arobertphillips@google.comstatic SkScalar pin_max_fling(SkScalar speed) { 2052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (speed > MAX_FLING_SPEED) { 2152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com speed = MAX_FLING_SPEED; 2252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 2352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com return speed; 2452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 2552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 2652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comstatic double getseconds() { 2752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com return SkTime::GetMSecs() * 0.001; 2852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 2952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 3052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com// returns +1 or -1, depending on the sign of x 31647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com// returns +1 if z is zero 32647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.comstatic SkScalar SkScalarSignNonZero(SkScalar x) { 3352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com SkScalar sign = SK_Scalar1; 3452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (x < 0) { 3552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com sign = -sign; 3652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 3752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com return sign; 3852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 3952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 4052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comstatic void unit_axis_align(SkVector* unit) { 4152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com const SkScalar TOLERANCE = SkDoubleToScalar(0.15); 4252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (SkScalarAbs(unit->fX) < TOLERANCE) { 4352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com unit->fX = 0; 44647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com unit->fY = SkScalarSignNonZero(unit->fY); 4552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } else if (SkScalarAbs(unit->fY) < TOLERANCE) { 46647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com unit->fX = SkScalarSignNonZero(unit->fX); 4752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com unit->fY = 0; 4852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 4952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 5052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 5152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comvoid SkFlingState::reset(float sx, float sy) { 5252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fActive = true; 534b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org fDirection.set(sx, sy); 5452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fSpeed0 = SkPoint::Normalize(&fDirection); 5552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fSpeed0 = pin_max_fling(fSpeed0); 5652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fTime0 = getseconds(); 5752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 5852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com unit_axis_align(&fDirection); 5952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com// printf("---- speed %g dir %g %g\n", fSpeed0, fDirection.fX, fDirection.fY); 6052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 6152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 6252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.combool SkFlingState::evaluateMatrix(SkMatrix* matrix) { 6352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (!fActive) { 6452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com return false; 6552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 6652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 67c31a9d6d398336ed094dafcc284282f0102ef7d2reed@google.com const float t = (float)(getseconds() - fTime0); 6852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com const float MIN_SPEED = 2; 69c31a9d6d398336ed094dafcc284282f0102ef7d2reed@google.com const float K0 = 5; 70c31a9d6d398336ed094dafcc284282f0102ef7d2reed@google.com const float K1 = 0.02f; 7152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com const float speed = fSpeed0 * (sk_float_exp(- K0 * t) - K1); 7252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (speed <= MIN_SPEED) { 7352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fActive = false; 7452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com return false; 7552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 7652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com float dist = (fSpeed0 - speed) / K0; 7752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 7852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com// printf("---- time %g speed %g dist %g\n", t, speed, dist); 7952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com float tx = fDirection.fX * dist; 8052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com float ty = fDirection.fY * dist; 8152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (DISCRETIZE_TRANSLATE_TO_AVOID_FLICKER) { 82c31a9d6d398336ed094dafcc284282f0102ef7d2reed@google.com tx = (float)sk_float_round2int(tx); 83c31a9d6d398336ed094dafcc284282f0102ef7d2reed@google.com ty = (float)sk_float_round2int(ty); 8452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 854b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org matrix->setTranslate(tx, ty); 8652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com// printf("---- evaluate (%g %g)\n", tx, ty); 8752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 8852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com return true; 8952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 9052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 9152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com/////////////////////////////////////////////////////////////////////////////// 9252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 9352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comstatic const SkMSec MAX_DBL_TAP_INTERVAL = 300; 9452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comstatic const float MAX_DBL_TAP_DISTANCE = 100; 9552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comstatic const float MAX_JITTER_RADIUS = 2; 9652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 9752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com// if true, then ignore the touch-move, 'cause its probably just jitter 9852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comstatic bool close_enough_for_jitter(float x0, float y0, float x1, float y1) { 9952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com return sk_float_abs(x0 - x1) <= MAX_JITTER_RADIUS && 10052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com sk_float_abs(y0 - y1) <= MAX_JITTER_RADIUS; 10152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 10252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 10352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com/////////////////////////////////////////////////////////////////////////////// 10452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 10552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comSkTouchGesture::SkTouchGesture() { 10652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com this->reset(); 10752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 10852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 10952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comSkTouchGesture::~SkTouchGesture() { 11052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 11152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 11252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comvoid SkTouchGesture::reset() { 11352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fTouches.reset(); 11452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fState = kEmpty_State; 11552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fLocalM.reset(); 11652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fGlobalM.reset(); 11752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 11852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fLastUpT = SkTime::GetMSecs() - 2*MAX_DBL_TAP_INTERVAL; 11952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fLastUpP.set(0, 0); 12052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 12152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 12252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comvoid SkTouchGesture::flushLocalM() { 12352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fGlobalM.postConcat(fLocalM); 12452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fLocalM.reset(); 12552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 12652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 12752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comconst SkMatrix& SkTouchGesture::localM() { 12852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (fFlinger.isActive()) { 12952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (!fFlinger.evaluateMatrix(&fLocalM)) { 13052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com this->flushLocalM(); 13152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 13252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 13352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com return fLocalM; 13452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 13552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 13652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comvoid SkTouchGesture::appendNewRec(void* owner, float x, float y) { 13752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com Rec* rec = fTouches.append(); 13852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com rec->fOwner = owner; 13952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com rec->fStartX = rec->fPrevX = rec->fLastX = x; 14052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com rec->fStartY = rec->fPrevY = rec->fLastY = y; 14152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com rec->fLastT = rec->fPrevT = SkTime::GetMSecs(); 14252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 14352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 14452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comvoid SkTouchGesture::touchBegin(void* owner, float x, float y) { 14538406c82b913350e55fa04af8c1941cd9b4aff52tfarina// SkDebugf("--- %d touchBegin %p %g %g\n", fTouches.count(), owner, x, y); 14652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 14752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com int index = this->findRec(owner); 14852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (index >= 0) { 14952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com this->flushLocalM(); 15052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fTouches.removeShuffle(index); 15152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com SkDebugf("---- already exists, removing\n"); 15252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 15352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 15452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (fTouches.count() == 2) { 15552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com return; 15652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 15752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 15852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com this->flushLocalM(); 15952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fFlinger.stop(); 16052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 16152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com this->appendNewRec(owner, x, y); 16252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 16352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com switch (fTouches.count()) { 16452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com case 1: 16552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fState = kTranslate_State; 16652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com break; 16752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com case 2: 16852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fState = kZoom_State; 16952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com break; 17052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com default: 17152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com break; 17252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 17352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 17452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 17552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comint SkTouchGesture::findRec(void* owner) const { 17652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com for (int i = 0; i < fTouches.count(); i++) { 17752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (owner == fTouches[i].fOwner) { 17852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com return i; 17952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 18052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 18152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com return -1; 18252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 18352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 18459f46b81f8bdd1b524f5cc43bc27603f9604c71arobertphillips@google.comstatic SkScalar center(float pos0, float pos1) { 1854b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org return (pos0 + pos1) * 0.5f; 18652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 18752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 18852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comstatic const float MAX_ZOOM_SCALE = 4; 18952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comstatic const float MIN_ZOOM_SCALE = 0.25f; 19052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 19152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comfloat SkTouchGesture::limitTotalZoom(float scale) const { 19252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com // this query works 'cause we know that we're square-scale w/ no skew/rotation 19359f46b81f8bdd1b524f5cc43bc27603f9604c71arobertphillips@google.com const float curr = SkScalarToFloat(fGlobalM[0]); 194d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 19552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (scale > 1 && curr * scale > MAX_ZOOM_SCALE) { 19652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com scale = MAX_ZOOM_SCALE / curr; 19752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } else if (scale < 1 && curr * scale < MIN_ZOOM_SCALE) { 19852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com scale = MIN_ZOOM_SCALE / curr; 19952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 20052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com return scale; 20152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 20252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 20352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comvoid SkTouchGesture::touchMoved(void* owner, float x, float y) { 20438406c82b913350e55fa04af8c1941cd9b4aff52tfarina// SkDebugf("--- %d touchMoved %p %g %g\n", fTouches.count(), owner, x, y); 20552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 206936b73424f7393994be832376287da988a52b993caryclark if (kEmpty_State == fState) { 207936b73424f7393994be832376287da988a52b993caryclark return; 208936b73424f7393994be832376287da988a52b993caryclark } 20952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 21052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com int index = this->findRec(owner); 21152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (index < 0) { 21252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com // not found, so I guess we should add it... 21352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com SkDebugf("---- add missing begin\n"); 21452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com this->appendNewRec(owner, x, y); 21552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com index = fTouches.count() - 1; 21652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 21752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 21852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com Rec& rec = fTouches[index]; 21952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 22052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com // not sure how valuable this is 22152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (fTouches.count() == 2) { 22252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (close_enough_for_jitter(rec.fLastX, rec.fLastY, x, y)) { 22338406c82b913350e55fa04af8c1941cd9b4aff52tfarina// SkDebugf("--- drop touchMove, withing jitter tolerance %g %g\n", rec.fLastX - x, rec.fLastY - y); 22452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com return; 22552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 22652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 22752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 22852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com rec.fPrevX = rec.fLastX; rec.fLastX = x; 22952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com rec.fPrevY = rec.fLastY; rec.fLastY = y; 23052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com rec.fPrevT = rec.fLastT; rec.fLastT = SkTime::GetMSecs(); 23152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 23252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com switch (fTouches.count()) { 23352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com case 1: { 23452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com float dx = rec.fLastX - rec.fStartX; 23552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com float dy = rec.fLastY - rec.fStartY; 23652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com dx = (float)sk_float_round2int(dx); 23752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com dy = (float)sk_float_round2int(dy); 23852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fLocalM.setTranslate(dx, dy); 23952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } break; 24052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com case 2: { 24152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com SkASSERT(kZoom_State == fState); 24252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com const Rec& rec0 = fTouches[0]; 24352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com const Rec& rec1 = fTouches[1]; 244d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 24552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com float scale = this->computePinch(rec0, rec1); 24652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com scale = this->limitTotalZoom(scale); 24752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 24852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fLocalM.setTranslate(-center(rec0.fStartX, rec1.fStartX), 24952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com -center(rec0.fStartY, rec1.fStartY)); 25052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fLocalM.postScale(scale, scale); 25152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fLocalM.postTranslate(center(rec0.fLastX, rec1.fLastX), 25252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com center(rec0.fLastY, rec1.fLastY)); 25352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } break; 25452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com default: 25552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com break; 25652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 25752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 25852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 25952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comvoid SkTouchGesture::touchEnd(void* owner) { 26038406c82b913350e55fa04af8c1941cd9b4aff52tfarina// SkDebugf("--- %d touchEnd %p\n", fTouches.count(), owner); 26152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 26252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com int index = this->findRec(owner); 26352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (index < 0) { 26452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com SkDebugf("--- not found\n"); 26552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com return; 26652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 26752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 26852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com const Rec& rec = fTouches[index]; 26952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (this->handleDblTap(rec.fLastX, rec.fLastY)) { 27052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com return; 27152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 27252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 27352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com // count() reflects the number before we removed the owner 27452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com switch (fTouches.count()) { 27552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com case 1: { 27652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com this->flushLocalM(); 27752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com float dx = rec.fLastX - rec.fPrevX; 27852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com float dy = rec.fLastY - rec.fPrevY; 27952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com float dur = (rec.fLastT - rec.fPrevT) * 0.001f; 28052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (dur > 0) { 28152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fFlinger.reset(dx / dur, dy / dur); 28252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 28352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fState = kEmpty_State; 28452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } break; 28552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com case 2: 28652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com this->flushLocalM(); 28752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com SkASSERT(kZoom_State == fState); 28852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fState = kEmpty_State; 28952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com break; 29052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com default: 29152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com SkASSERT(kZoom_State == fState); 29252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com break; 29352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 29452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 29552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fTouches.removeShuffle(index); 29652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 29752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 29852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.comfloat SkTouchGesture::computePinch(const Rec& rec0, const Rec& rec1) { 29952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com double dx = rec0.fStartX - rec1.fStartX; 30052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com double dy = rec0.fStartY - rec1.fStartY; 30152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com double dist0 = sqrt(dx*dx + dy*dy); 30252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 30352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com dx = rec0.fLastX - rec1.fLastX; 30452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com dy = rec0.fLastY - rec1.fLastY; 30552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com double dist1 = sqrt(dx*dx + dy*dy); 30652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 30752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com double scale = dist1 / dist0; 30852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com return (float)scale; 30952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 31052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 31152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.combool SkTouchGesture::handleDblTap(float x, float y) { 31252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com bool found = false; 31352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com SkMSec now = SkTime::GetMSecs(); 31452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (now - fLastUpT <= MAX_DBL_TAP_INTERVAL) { 31552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com if (SkPoint::Length(fLastUpP.fX - x, 31652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fLastUpP.fY - y) <= MAX_DBL_TAP_DISTANCE) { 31752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fFlinger.stop(); 31852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fLocalM.reset(); 31952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fGlobalM.reset(); 32052f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fTouches.reset(); 32152f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fState = kEmpty_State; 32252f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com found = true; 32352f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 32452f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com } 32552f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com 32652f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fLastUpT = now; 32752f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com fLastUpP.set(x, y); 32852f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com return found; 32952f57e1d11a00bdc5efb96709446546cdbc1ff9dreed@google.com} 330