2011-07-28 14:26:00 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2010 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
2011-03-16 12:10:02 +00:00
|
|
|
*/
|
|
|
|
|
2016-05-20 14:32:19 +00:00
|
|
|
#include <algorithm>
|
2011-07-28 14:26:00 +00:00
|
|
|
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/core/SkMatrix.h"
|
|
|
|
#include "include/core/SkTime.h"
|
|
|
|
#include "tools/viewer/TouchGesture.h"
|
2011-03-16 12:10:02 +00:00
|
|
|
|
|
|
|
#define DISCRETIZE_TRANSLATE_TO_AVOID_FLICKER true
|
|
|
|
|
2012-07-10 17:30:58 +00:00
|
|
|
static const SkScalar MAX_FLING_SPEED = SkIntToScalar(1500);
|
2011-03-16 12:10:02 +00:00
|
|
|
|
2012-07-10 17:30:58 +00:00
|
|
|
static SkScalar pin_max_fling(SkScalar speed) {
|
2011-03-16 12:10:02 +00:00
|
|
|
if (speed > MAX_FLING_SPEED) {
|
|
|
|
speed = MAX_FLING_SPEED;
|
|
|
|
}
|
|
|
|
return speed;
|
|
|
|
}
|
|
|
|
|
|
|
|
static double getseconds() {
|
|
|
|
return SkTime::GetMSecs() * 0.001;
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns +1 or -1, depending on the sign of x
|
2011-08-23 14:39:01 +00:00
|
|
|
// returns +1 if z is zero
|
|
|
|
static SkScalar SkScalarSignNonZero(SkScalar x) {
|
2011-03-16 12:10:02 +00:00
|
|
|
SkScalar sign = SK_Scalar1;
|
|
|
|
if (x < 0) {
|
|
|
|
sign = -sign;
|
|
|
|
}
|
|
|
|
return sign;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void unit_axis_align(SkVector* unit) {
|
|
|
|
const SkScalar TOLERANCE = SkDoubleToScalar(0.15);
|
|
|
|
if (SkScalarAbs(unit->fX) < TOLERANCE) {
|
|
|
|
unit->fX = 0;
|
2011-08-23 14:39:01 +00:00
|
|
|
unit->fY = SkScalarSignNonZero(unit->fY);
|
2011-03-16 12:10:02 +00:00
|
|
|
} else if (SkScalarAbs(unit->fY) < TOLERANCE) {
|
2011-08-23 14:39:01 +00:00
|
|
|
unit->fX = SkScalarSignNonZero(unit->fX);
|
2011-03-16 12:10:02 +00:00
|
|
|
unit->fY = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
void TouchGesture::FlingState::reset(float sx, float sy) {
|
2011-03-16 12:10:02 +00:00
|
|
|
fActive = true;
|
2013-11-25 19:44:07 +00:00
|
|
|
fDirection.set(sx, sy);
|
2011-03-16 12:10:02 +00:00
|
|
|
fSpeed0 = SkPoint::Normalize(&fDirection);
|
|
|
|
fSpeed0 = pin_max_fling(fSpeed0);
|
|
|
|
fTime0 = getseconds();
|
|
|
|
|
|
|
|
unit_axis_align(&fDirection);
|
|
|
|
// printf("---- speed %g dir %g %g\n", fSpeed0, fDirection.fX, fDirection.fY);
|
|
|
|
}
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
bool TouchGesture::FlingState::evaluateMatrix(SkMatrix* matrix) {
|
2011-03-16 12:10:02 +00:00
|
|
|
if (!fActive) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-03-18 20:53:44 +00:00
|
|
|
const float t = (float)(getseconds() - fTime0);
|
2011-03-16 12:10:02 +00:00
|
|
|
const float MIN_SPEED = 2;
|
2011-03-18 20:53:44 +00:00
|
|
|
const float K0 = 5;
|
|
|
|
const float K1 = 0.02f;
|
2011-03-16 12:10:02 +00:00
|
|
|
const float speed = fSpeed0 * (sk_float_exp(- K0 * t) - K1);
|
|
|
|
if (speed <= MIN_SPEED) {
|
|
|
|
fActive = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
float dist = (fSpeed0 - speed) / K0;
|
|
|
|
|
|
|
|
// printf("---- time %g speed %g dist %g\n", t, speed, dist);
|
|
|
|
float tx = fDirection.fX * dist;
|
|
|
|
float ty = fDirection.fY * dist;
|
|
|
|
if (DISCRETIZE_TRANSLATE_TO_AVOID_FLICKER) {
|
2011-03-18 20:53:44 +00:00
|
|
|
tx = (float)sk_float_round2int(tx);
|
|
|
|
ty = (float)sk_float_round2int(ty);
|
2011-03-16 12:10:02 +00:00
|
|
|
}
|
2013-11-25 19:44:07 +00:00
|
|
|
matrix->setTranslate(tx, ty);
|
2011-03-16 12:10:02 +00:00
|
|
|
// printf("---- evaluate (%g %g)\n", tx, ty);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
static const SkMSec MAX_DBL_TAP_INTERVAL = 300;
|
|
|
|
static const float MAX_DBL_TAP_DISTANCE = 100;
|
|
|
|
static const float MAX_JITTER_RADIUS = 2;
|
|
|
|
|
|
|
|
// if true, then ignore the touch-move, 'cause its probably just jitter
|
|
|
|
static bool close_enough_for_jitter(float x0, float y0, float x1, float y1) {
|
|
|
|
return sk_float_abs(x0 - x1) <= MAX_JITTER_RADIUS &&
|
|
|
|
sk_float_abs(y0 - y1) <= MAX_JITTER_RADIUS;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
TouchGesture::TouchGesture() {
|
2011-03-16 12:10:02 +00:00
|
|
|
this->reset();
|
|
|
|
}
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
TouchGesture::~TouchGesture() {
|
2011-03-16 12:10:02 +00:00
|
|
|
}
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
void TouchGesture::resetTouchState() {
|
2016-05-20 14:32:19 +00:00
|
|
|
fIsTransLimited = false;
|
2011-03-16 12:10:02 +00:00
|
|
|
fTouches.reset();
|
|
|
|
fState = kEmpty_State;
|
|
|
|
fLocalM.reset();
|
|
|
|
|
Change SkTime::GetMSecs to double; ensure values stored in SkMSec do not overflow.
The following are currently unused in Android, Google3, Chromium, and Mozilla:
- SkEvent
- SkTime::GetMSecs
- SK_TIME_FACTOR (also unused in Skia)
- SkAutoTime
I left uses of SkMSec more-or-less intact for SkEvent, SkAnimator, and SkInterpolator. SkInterpolator is used in Chromium, so I did not want to change the API. The views/ and animator/ code is crufty, so it didn't seem worthwhile to refactor it. Instead, I added SkEvent::GetMSecsSinceStartup, which is likely to be adequate for use in SampleApp.
I also left SkMSec where it is used to measure a duration rather than a timestamp. With the exception of SkMovie, which is used in Android, all of the uses appear to measure the execution time of a piece of code, which I would hope does not exceed 2^31 milliseconds.
Added skiatest::Timer to support a common idiom in tests where we want to measure the wallclock time in integer milliseconds. (Not used in tests/PathOpsSkpClipTest.cpp because it redefines things in Test.h.)
Removed tabs in tests/StrokerTest.cpp.
BUG=skia:4632
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1811613004
Review URL: https://codereview.chromium.org/1811613004
2016-03-25 19:59:53 +00:00
|
|
|
fLastUpMillis = SkTime::GetMSecs() - 2*MAX_DBL_TAP_INTERVAL;
|
2011-03-16 12:10:02 +00:00
|
|
|
fLastUpP.set(0, 0);
|
|
|
|
}
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
void TouchGesture::reset() {
|
2018-01-05 16:58:16 +00:00
|
|
|
fGlobalM.reset();
|
|
|
|
this->resetTouchState();
|
|
|
|
}
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
void TouchGesture::flushLocalM() {
|
2011-03-16 12:10:02 +00:00
|
|
|
fGlobalM.postConcat(fLocalM);
|
|
|
|
fLocalM.reset();
|
|
|
|
}
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
const SkMatrix& TouchGesture::localM() {
|
2011-03-16 12:10:02 +00:00
|
|
|
if (fFlinger.isActive()) {
|
|
|
|
if (!fFlinger.evaluateMatrix(&fLocalM)) {
|
|
|
|
this->flushLocalM();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return fLocalM;
|
|
|
|
}
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
void TouchGesture::appendNewRec(void* owner, float x, float y) {
|
2011-03-16 12:10:02 +00:00
|
|
|
Rec* rec = fTouches.append();
|
|
|
|
rec->fOwner = owner;
|
|
|
|
rec->fStartX = rec->fPrevX = rec->fLastX = x;
|
|
|
|
rec->fStartY = rec->fPrevY = rec->fLastY = y;
|
Change SkTime::GetMSecs to double; ensure values stored in SkMSec do not overflow.
The following are currently unused in Android, Google3, Chromium, and Mozilla:
- SkEvent
- SkTime::GetMSecs
- SK_TIME_FACTOR (also unused in Skia)
- SkAutoTime
I left uses of SkMSec more-or-less intact for SkEvent, SkAnimator, and SkInterpolator. SkInterpolator is used in Chromium, so I did not want to change the API. The views/ and animator/ code is crufty, so it didn't seem worthwhile to refactor it. Instead, I added SkEvent::GetMSecsSinceStartup, which is likely to be adequate for use in SampleApp.
I also left SkMSec where it is used to measure a duration rather than a timestamp. With the exception of SkMovie, which is used in Android, all of the uses appear to measure the execution time of a piece of code, which I would hope does not exceed 2^31 milliseconds.
Added skiatest::Timer to support a common idiom in tests where we want to measure the wallclock time in integer milliseconds. (Not used in tests/PathOpsSkpClipTest.cpp because it redefines things in Test.h.)
Removed tabs in tests/StrokerTest.cpp.
BUG=skia:4632
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1811613004
Review URL: https://codereview.chromium.org/1811613004
2016-03-25 19:59:53 +00:00
|
|
|
rec->fLastT = rec->fPrevT = static_cast<float>(SkTime::GetSecs());
|
2011-03-16 12:10:02 +00:00
|
|
|
}
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
void TouchGesture::touchBegin(void* owner, float x, float y) {
|
2014-10-31 14:11:12 +00:00
|
|
|
// SkDebugf("--- %d touchBegin %p %g %g\n", fTouches.count(), owner, x, y);
|
2011-03-16 12:10:02 +00:00
|
|
|
|
|
|
|
int index = this->findRec(owner);
|
|
|
|
if (index >= 0) {
|
|
|
|
this->flushLocalM();
|
|
|
|
fTouches.removeShuffle(index);
|
|
|
|
SkDebugf("---- already exists, removing\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fTouches.count() == 2) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this->flushLocalM();
|
|
|
|
fFlinger.stop();
|
|
|
|
|
|
|
|
this->appendNewRec(owner, x, y);
|
|
|
|
|
|
|
|
switch (fTouches.count()) {
|
|
|
|
case 1:
|
|
|
|
fState = kTranslate_State;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
fState = kZoom_State;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
int TouchGesture::findRec(void* owner) const {
|
2011-03-16 12:10:02 +00:00
|
|
|
for (int i = 0; i < fTouches.count(); i++) {
|
|
|
|
if (owner == fTouches[i].fOwner) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-07-10 17:30:58 +00:00
|
|
|
static SkScalar center(float pos0, float pos1) {
|
2013-11-25 19:44:07 +00:00
|
|
|
return (pos0 + pos1) * 0.5f;
|
2011-03-16 12:10:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static const float MAX_ZOOM_SCALE = 4;
|
|
|
|
static const float MIN_ZOOM_SCALE = 0.25f;
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
float TouchGesture::limitTotalZoom(float scale) const {
|
2011-03-16 12:10:02 +00:00
|
|
|
// this query works 'cause we know that we're square-scale w/ no skew/rotation
|
2012-07-10 17:30:58 +00:00
|
|
|
const float curr = SkScalarToFloat(fGlobalM[0]);
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2011-03-16 12:10:02 +00:00
|
|
|
if (scale > 1 && curr * scale > MAX_ZOOM_SCALE) {
|
|
|
|
scale = MAX_ZOOM_SCALE / curr;
|
|
|
|
} else if (scale < 1 && curr * scale < MIN_ZOOM_SCALE) {
|
|
|
|
scale = MIN_ZOOM_SCALE / curr;
|
|
|
|
}
|
|
|
|
return scale;
|
|
|
|
}
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
void TouchGesture::touchMoved(void* owner, float x, float y) {
|
2014-10-31 14:11:12 +00:00
|
|
|
// SkDebugf("--- %d touchMoved %p %g %g\n", fTouches.count(), owner, x, y);
|
2011-03-16 12:10:02 +00:00
|
|
|
|
2014-07-11 19:14:51 +00:00
|
|
|
if (kEmpty_State == fState) {
|
|
|
|
return;
|
|
|
|
}
|
2011-03-16 12:10:02 +00:00
|
|
|
|
|
|
|
int index = this->findRec(owner);
|
|
|
|
if (index < 0) {
|
2017-06-07 14:00:30 +00:00
|
|
|
SkDebugf("---- ignoring move without begin\n");
|
|
|
|
return;
|
2011-03-16 12:10:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Rec& rec = fTouches[index];
|
|
|
|
|
|
|
|
// not sure how valuable this is
|
|
|
|
if (fTouches.count() == 2) {
|
|
|
|
if (close_enough_for_jitter(rec.fLastX, rec.fLastY, x, y)) {
|
2017-06-07 14:00:30 +00:00
|
|
|
// SkDebugf("--- drop touchMove, within jitter tolerance %g %g\n", rec.fLastX - x, rec.fLastY - y);
|
2011-03-16 12:10:02 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rec.fPrevX = rec.fLastX; rec.fLastX = x;
|
|
|
|
rec.fPrevY = rec.fLastY; rec.fLastY = y;
|
Change SkTime::GetMSecs to double; ensure values stored in SkMSec do not overflow.
The following are currently unused in Android, Google3, Chromium, and Mozilla:
- SkEvent
- SkTime::GetMSecs
- SK_TIME_FACTOR (also unused in Skia)
- SkAutoTime
I left uses of SkMSec more-or-less intact for SkEvent, SkAnimator, and SkInterpolator. SkInterpolator is used in Chromium, so I did not want to change the API. The views/ and animator/ code is crufty, so it didn't seem worthwhile to refactor it. Instead, I added SkEvent::GetMSecsSinceStartup, which is likely to be adequate for use in SampleApp.
I also left SkMSec where it is used to measure a duration rather than a timestamp. With the exception of SkMovie, which is used in Android, all of the uses appear to measure the execution time of a piece of code, which I would hope does not exceed 2^31 milliseconds.
Added skiatest::Timer to support a common idiom in tests where we want to measure the wallclock time in integer milliseconds. (Not used in tests/PathOpsSkpClipTest.cpp because it redefines things in Test.h.)
Removed tabs in tests/StrokerTest.cpp.
BUG=skia:4632
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1811613004
Review URL: https://codereview.chromium.org/1811613004
2016-03-25 19:59:53 +00:00
|
|
|
rec.fPrevT = rec.fLastT;
|
|
|
|
rec.fLastT = static_cast<float>(SkTime::GetSecs());
|
2011-03-16 12:10:02 +00:00
|
|
|
|
|
|
|
switch (fTouches.count()) {
|
|
|
|
case 1: {
|
|
|
|
float dx = rec.fLastX - rec.fStartX;
|
|
|
|
float dy = rec.fLastY - rec.fStartY;
|
|
|
|
dx = (float)sk_float_round2int(dx);
|
|
|
|
dy = (float)sk_float_round2int(dy);
|
|
|
|
fLocalM.setTranslate(dx, dy);
|
|
|
|
} break;
|
|
|
|
case 2: {
|
|
|
|
SkASSERT(kZoom_State == fState);
|
|
|
|
const Rec& rec0 = fTouches[0];
|
|
|
|
const Rec& rec1 = fTouches[1];
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2011-03-16 12:10:02 +00:00
|
|
|
float scale = this->computePinch(rec0, rec1);
|
|
|
|
scale = this->limitTotalZoom(scale);
|
|
|
|
|
|
|
|
fLocalM.setTranslate(-center(rec0.fStartX, rec1.fStartX),
|
|
|
|
-center(rec0.fStartY, rec1.fStartY));
|
|
|
|
fLocalM.postScale(scale, scale);
|
|
|
|
fLocalM.postTranslate(center(rec0.fLastX, rec1.fLastX),
|
|
|
|
center(rec0.fLastY, rec1.fLastY));
|
|
|
|
} break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
void TouchGesture::touchEnd(void* owner) {
|
2014-10-31 14:11:12 +00:00
|
|
|
// SkDebugf("--- %d touchEnd %p\n", fTouches.count(), owner);
|
2011-03-16 12:10:02 +00:00
|
|
|
|
|
|
|
int index = this->findRec(owner);
|
|
|
|
if (index < 0) {
|
|
|
|
SkDebugf("--- not found\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Rec& rec = fTouches[index];
|
|
|
|
if (this->handleDblTap(rec.fLastX, rec.fLastY)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// count() reflects the number before we removed the owner
|
|
|
|
switch (fTouches.count()) {
|
|
|
|
case 1: {
|
|
|
|
this->flushLocalM();
|
|
|
|
float dx = rec.fLastX - rec.fPrevX;
|
|
|
|
float dy = rec.fLastY - rec.fPrevY;
|
Change SkTime::GetMSecs to double; ensure values stored in SkMSec do not overflow.
The following are currently unused in Android, Google3, Chromium, and Mozilla:
- SkEvent
- SkTime::GetMSecs
- SK_TIME_FACTOR (also unused in Skia)
- SkAutoTime
I left uses of SkMSec more-or-less intact for SkEvent, SkAnimator, and SkInterpolator. SkInterpolator is used in Chromium, so I did not want to change the API. The views/ and animator/ code is crufty, so it didn't seem worthwhile to refactor it. Instead, I added SkEvent::GetMSecsSinceStartup, which is likely to be adequate for use in SampleApp.
I also left SkMSec where it is used to measure a duration rather than a timestamp. With the exception of SkMovie, which is used in Android, all of the uses appear to measure the execution time of a piece of code, which I would hope does not exceed 2^31 milliseconds.
Added skiatest::Timer to support a common idiom in tests where we want to measure the wallclock time in integer milliseconds. (Not used in tests/PathOpsSkpClipTest.cpp because it redefines things in Test.h.)
Removed tabs in tests/StrokerTest.cpp.
BUG=skia:4632
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1811613004
Review URL: https://codereview.chromium.org/1811613004
2016-03-25 19:59:53 +00:00
|
|
|
float dur = rec.fLastT - rec.fPrevT;
|
2011-03-16 12:10:02 +00:00
|
|
|
if (dur > 0) {
|
|
|
|
fFlinger.reset(dx / dur, dy / dur);
|
|
|
|
}
|
|
|
|
fState = kEmpty_State;
|
|
|
|
} break;
|
|
|
|
case 2:
|
|
|
|
this->flushLocalM();
|
|
|
|
SkASSERT(kZoom_State == fState);
|
|
|
|
fState = kEmpty_State;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
SkASSERT(kZoom_State == fState);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
fTouches.removeShuffle(index);
|
2016-05-20 14:32:19 +00:00
|
|
|
|
|
|
|
limitTrans();
|
2011-03-16 12:10:02 +00:00
|
|
|
}
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
bool TouchGesture::isFling(SkPoint* dir) {
|
2018-07-23 17:46:01 +00:00
|
|
|
if (fFlinger.isActive()) {
|
|
|
|
SkScalar speed;
|
|
|
|
fFlinger.get(dir, &speed);
|
|
|
|
if (speed > 1000) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
float TouchGesture::computePinch(const Rec& rec0, const Rec& rec1) {
|
2011-03-16 12:10:02 +00:00
|
|
|
double dx = rec0.fStartX - rec1.fStartX;
|
|
|
|
double dy = rec0.fStartY - rec1.fStartY;
|
|
|
|
double dist0 = sqrt(dx*dx + dy*dy);
|
|
|
|
|
|
|
|
dx = rec0.fLastX - rec1.fLastX;
|
|
|
|
dy = rec0.fLastY - rec1.fLastY;
|
|
|
|
double dist1 = sqrt(dx*dx + dy*dy);
|
|
|
|
|
|
|
|
double scale = dist1 / dist0;
|
|
|
|
return (float)scale;
|
|
|
|
}
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
bool TouchGesture::handleDblTap(float x, float y) {
|
2011-03-16 12:10:02 +00:00
|
|
|
bool found = false;
|
Change SkTime::GetMSecs to double; ensure values stored in SkMSec do not overflow.
The following are currently unused in Android, Google3, Chromium, and Mozilla:
- SkEvent
- SkTime::GetMSecs
- SK_TIME_FACTOR (also unused in Skia)
- SkAutoTime
I left uses of SkMSec more-or-less intact for SkEvent, SkAnimator, and SkInterpolator. SkInterpolator is used in Chromium, so I did not want to change the API. The views/ and animator/ code is crufty, so it didn't seem worthwhile to refactor it. Instead, I added SkEvent::GetMSecsSinceStartup, which is likely to be adequate for use in SampleApp.
I also left SkMSec where it is used to measure a duration rather than a timestamp. With the exception of SkMovie, which is used in Android, all of the uses appear to measure the execution time of a piece of code, which I would hope does not exceed 2^31 milliseconds.
Added skiatest::Timer to support a common idiom in tests where we want to measure the wallclock time in integer milliseconds. (Not used in tests/PathOpsSkpClipTest.cpp because it redefines things in Test.h.)
Removed tabs in tests/StrokerTest.cpp.
BUG=skia:4632
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1811613004
Review URL: https://codereview.chromium.org/1811613004
2016-03-25 19:59:53 +00:00
|
|
|
double now = SkTime::GetMSecs();
|
|
|
|
if (now - fLastUpMillis <= MAX_DBL_TAP_INTERVAL) {
|
2011-03-16 12:10:02 +00:00
|
|
|
if (SkPoint::Length(fLastUpP.fX - x,
|
|
|
|
fLastUpP.fY - y) <= MAX_DBL_TAP_DISTANCE) {
|
|
|
|
fFlinger.stop();
|
|
|
|
fLocalM.reset();
|
|
|
|
fGlobalM.reset();
|
|
|
|
fTouches.reset();
|
|
|
|
fState = kEmpty_State;
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Change SkTime::GetMSecs to double; ensure values stored in SkMSec do not overflow.
The following are currently unused in Android, Google3, Chromium, and Mozilla:
- SkEvent
- SkTime::GetMSecs
- SK_TIME_FACTOR (also unused in Skia)
- SkAutoTime
I left uses of SkMSec more-or-less intact for SkEvent, SkAnimator, and SkInterpolator. SkInterpolator is used in Chromium, so I did not want to change the API. The views/ and animator/ code is crufty, so it didn't seem worthwhile to refactor it. Instead, I added SkEvent::GetMSecsSinceStartup, which is likely to be adequate for use in SampleApp.
I also left SkMSec where it is used to measure a duration rather than a timestamp. With the exception of SkMovie, which is used in Android, all of the uses appear to measure the execution time of a piece of code, which I would hope does not exceed 2^31 milliseconds.
Added skiatest::Timer to support a common idiom in tests where we want to measure the wallclock time in integer milliseconds. (Not used in tests/PathOpsSkpClipTest.cpp because it redefines things in Test.h.)
Removed tabs in tests/StrokerTest.cpp.
BUG=skia:4632
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1811613004
Review URL: https://codereview.chromium.org/1811613004
2016-03-25 19:59:53 +00:00
|
|
|
fLastUpMillis = now;
|
2011-03-16 12:10:02 +00:00
|
|
|
fLastUpP.set(x, y);
|
|
|
|
return found;
|
|
|
|
}
|
2016-05-20 14:32:19 +00:00
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
void TouchGesture::setTransLimit(const SkRect& contentRect, const SkRect& windowRect,
|
Simplify some Viewer code, and fix a few bugs
The content rect was always identical to the window rect,
so most of the related code did nothing. The translation
limit code is always useful (to avoid dragging the slide
way off-screen with the mouse), so always include it.
The auto-scaling to fit the screen is also still useful,
but just base it on the window rect.
The zoom code has four state variables, only used two of
them, and one was a trivially derived computation. Fold
most of that work into computeMatrix. (The translation
was always zero -- we never changed the zoom center.)
Include fDefaultMatrix in the matrix from computeMatrix,
rather than needing to apply it specially to the canvas.
Don't apply the inverse default matrix to touch or mouse
points. The absolute positions of those touch points is
not important, but because that matrix includes scale
(and sometimes very large or very small scale), it just
had the effect of greatly amplifying or damping the drag
speed. Without it, the slide always pans at the speed of
the touch/mouse drag -- which seems more desirable.
The use of the inverse default matrix was a clever trick,
but it caused the translation (applied to the global mtx)
to be scaled, so the slide was always pinned incorrectly.
Instead, supply the unmodified window rect and the default
matrix, so the trans limit code can do the obvious correct
thing: xform the slide bounds completely, then limit the
translation that will be applied after that. Slides are
now correctly pinned to screen edge regardless of how
much zoom is present in the default matrix.
Note: There are still several bugs related to all of this
code, but given the web of xform state, it's hard to
unravel. The touch gesture still doesn't know about
viewer's zoom, so that's ignored when doing the pinning.
Beyond that, it doesn't even know about window resize -
it only configures the translation limit when setting up
a slide. I had a fix for all of this (doing the
translation limiting in computeMatrix), but then the touch
gesture doesn't know about it, and can accumulate drag
motion that needs to be un-dragged to get back on-screen,
even though the slide is never really translated that far.
SkTouchGesture is in include. No one uses it except viewer:
TBR=bsalomon@google.com
Bug: skia:
Change-Id: I460cc07c3de6d36e63826f57d359faf1facf5ab3
Reviewed-on: https://skia-review.googlesource.com/18524
Reviewed-by: Brian Osman <brianosman@google.com>
Reviewed-by: Yuqian Li <liyuqian@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-06-05 12:46:04 +00:00
|
|
|
const SkMatrix& preTouchMatrix) {
|
2016-05-20 14:32:19 +00:00
|
|
|
fIsTransLimited = true;
|
|
|
|
fContentRect = contentRect;
|
|
|
|
fWindowRect = windowRect;
|
Simplify some Viewer code, and fix a few bugs
The content rect was always identical to the window rect,
so most of the related code did nothing. The translation
limit code is always useful (to avoid dragging the slide
way off-screen with the mouse), so always include it.
The auto-scaling to fit the screen is also still useful,
but just base it on the window rect.
The zoom code has four state variables, only used two of
them, and one was a trivially derived computation. Fold
most of that work into computeMatrix. (The translation
was always zero -- we never changed the zoom center.)
Include fDefaultMatrix in the matrix from computeMatrix,
rather than needing to apply it specially to the canvas.
Don't apply the inverse default matrix to touch or mouse
points. The absolute positions of those touch points is
not important, but because that matrix includes scale
(and sometimes very large or very small scale), it just
had the effect of greatly amplifying or damping the drag
speed. Without it, the slide always pans at the speed of
the touch/mouse drag -- which seems more desirable.
The use of the inverse default matrix was a clever trick,
but it caused the translation (applied to the global mtx)
to be scaled, so the slide was always pinned incorrectly.
Instead, supply the unmodified window rect and the default
matrix, so the trans limit code can do the obvious correct
thing: xform the slide bounds completely, then limit the
translation that will be applied after that. Slides are
now correctly pinned to screen edge regardless of how
much zoom is present in the default matrix.
Note: There are still several bugs related to all of this
code, but given the web of xform state, it's hard to
unravel. The touch gesture still doesn't know about
viewer's zoom, so that's ignored when doing the pinning.
Beyond that, it doesn't even know about window resize -
it only configures the translation limit when setting up
a slide. I had a fix for all of this (doing the
translation limiting in computeMatrix), but then the touch
gesture doesn't know about it, and can accumulate drag
motion that needs to be un-dragged to get back on-screen,
even though the slide is never really translated that far.
SkTouchGesture is in include. No one uses it except viewer:
TBR=bsalomon@google.com
Bug: skia:
Change-Id: I460cc07c3de6d36e63826f57d359faf1facf5ab3
Reviewed-on: https://skia-review.googlesource.com/18524
Reviewed-by: Brian Osman <brianosman@google.com>
Reviewed-by: Yuqian Li <liyuqian@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-06-05 12:46:04 +00:00
|
|
|
fPreTouchM = preTouchMatrix;
|
2016-05-20 14:32:19 +00:00
|
|
|
}
|
|
|
|
|
2018-08-08 15:36:17 +00:00
|
|
|
void TouchGesture::limitTrans() {
|
2016-05-20 14:32:19 +00:00
|
|
|
if (!fIsTransLimited) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
SkRect scaledContent = fContentRect;
|
Simplify some Viewer code, and fix a few bugs
The content rect was always identical to the window rect,
so most of the related code did nothing. The translation
limit code is always useful (to avoid dragging the slide
way off-screen with the mouse), so always include it.
The auto-scaling to fit the screen is also still useful,
but just base it on the window rect.
The zoom code has four state variables, only used two of
them, and one was a trivially derived computation. Fold
most of that work into computeMatrix. (The translation
was always zero -- we never changed the zoom center.)
Include fDefaultMatrix in the matrix from computeMatrix,
rather than needing to apply it specially to the canvas.
Don't apply the inverse default matrix to touch or mouse
points. The absolute positions of those touch points is
not important, but because that matrix includes scale
(and sometimes very large or very small scale), it just
had the effect of greatly amplifying or damping the drag
speed. Without it, the slide always pans at the speed of
the touch/mouse drag -- which seems more desirable.
The use of the inverse default matrix was a clever trick,
but it caused the translation (applied to the global mtx)
to be scaled, so the slide was always pinned incorrectly.
Instead, supply the unmodified window rect and the default
matrix, so the trans limit code can do the obvious correct
thing: xform the slide bounds completely, then limit the
translation that will be applied after that. Slides are
now correctly pinned to screen edge regardless of how
much zoom is present in the default matrix.
Note: There are still several bugs related to all of this
code, but given the web of xform state, it's hard to
unravel. The touch gesture still doesn't know about
viewer's zoom, so that's ignored when doing the pinning.
Beyond that, it doesn't even know about window resize -
it only configures the translation limit when setting up
a slide. I had a fix for all of this (doing the
translation limiting in computeMatrix), but then the touch
gesture doesn't know about it, and can accumulate drag
motion that needs to be un-dragged to get back on-screen,
even though the slide is never really translated that far.
SkTouchGesture is in include. No one uses it except viewer:
TBR=bsalomon@google.com
Bug: skia:
Change-Id: I460cc07c3de6d36e63826f57d359faf1facf5ab3
Reviewed-on: https://skia-review.googlesource.com/18524
Reviewed-by: Brian Osman <brianosman@google.com>
Reviewed-by: Yuqian Li <liyuqian@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-06-05 12:46:04 +00:00
|
|
|
fPreTouchM.mapRect(&scaledContent);
|
2016-05-20 14:32:19 +00:00
|
|
|
fGlobalM.mapRect(&scaledContent);
|
|
|
|
const SkScalar ZERO = 0;
|
|
|
|
|
|
|
|
fGlobalM.postTranslate(ZERO, std::min(ZERO, fWindowRect.fBottom - scaledContent.fTop));
|
|
|
|
fGlobalM.postTranslate(ZERO, std::max(ZERO, fWindowRect.fTop - scaledContent.fBottom));
|
|
|
|
fGlobalM.postTranslate(std::min(ZERO, fWindowRect.fRight - scaledContent.fLeft), ZERO);
|
|
|
|
fGlobalM.postTranslate(std::max(ZERO, fWindowRect.fLeft - scaledContent.fRight), ZERO);
|
|
|
|
}
|