19#define DISCRETIZE_TRANSLATE_TO_AVOID_FLICKER true
55void TouchGesture::FlingState::reset(
float sx,
float sy) {
57 fDirection.set(sx, sy);
66bool TouchGesture::FlingState::evaluateMatrix(
SkMatrix* matrix) {
72 const float MIN_SPEED = 2;
74 const float K1 = 0.02f;
75 const float speed = fSpeed0 * (std::exp(- K0 * t) - K1);
76 if (speed <= MIN_SPEED) {
80 float dist = (fSpeed0 - speed) / K0;
83 float tx = fDirection.fX * dist;
84 float ty = fDirection.fY * dist;
89 matrix->setTranslate(tx, ty);
117 fIsTransLimited =
false;
119 fState = kEmpty_State;
131void TouchGesture::flushLocalM() {
137 if (fFlinger.isActive()) {
138 if (!fFlinger.evaluateMatrix(&fLocalM)) {
145void TouchGesture::appendNewRec(
void* owner,
float x,
float y) {
146 Rec* rec = fTouches.
append();
148 rec->fStartX = rec->fPrevX = rec->fLastX =
x;
149 rec->fStartY = rec->fPrevY = rec->fLastY =
y;
156 int index = this->findRec(owner);
160 SkDebugf(
"---- already exists, removing\n");
163 if (fTouches.
size() == 2) {
170 this->appendNewRec(owner,
x,
y);
172 switch (fTouches.
size()) {
174 fState = kTranslate_State;
184int TouchGesture::findRec(
void* owner)
const {
185 for (
int i = 0; i < fTouches.
size(); i++) {
186 if (owner == fTouches[i].fOwner) {
194 return (pos0 + pos1) * 0.5f;
198 fState = kZoom_State;
210 fState = kEmpty_State;
216 if (kEmpty_State == fState) {
220 int index = this->findRec(owner);
222 SkDebugf(
"---- ignoring move without begin\n");
226 Rec& rec = fTouches[index];
229 if (fTouches.
size() == 2) {
236 rec.fPrevX = rec.fLastX; rec.fLastX =
x;
237 rec.fPrevY = rec.fLastY; rec.fLastY =
y;
238 rec.fPrevT = rec.fLastT;
241 switch (fTouches.
size()) {
243 float dx = rec.fLastX - rec.fStartX;
244 float dy = rec.fLastY - rec.fStartY;
251 const Rec& rec0 = fTouches[0];
252 const Rec& rec1 = fTouches[1];
254 float scale = this->computePinch(rec0, rec1);
256 center(rec0.fStartX, rec1.fStartX),
257 center(rec0.fStartY, rec1.fStartY),
258 center(rec0.fLastX, rec1.fLastX),
259 center(rec0.fLastY, rec1.fLastY));
269 int index = this->findRec(owner);
275 const Rec& rec = fTouches[index];
276 if (this->handleDblTap(rec.fLastX, rec.fLastY)) {
281 switch (fTouches.
size()) {
284 float dx = rec.fLastX - rec.fPrevX;
285 float dy = rec.fLastY - rec.fPrevY;
286 float dur = rec.fLastT - rec.fPrevT;
288 fFlinger.reset(dx / dur, dy / dur);
290 fState = kEmpty_State;
306 if (fFlinger.isActive()) {
308 fFlinger.get(dir, &speed);
316float TouchGesture::computePinch(
const Rec& rec0,
const Rec& rec1) {
317 double dx = rec0.fStartX - rec1.fStartX;
318 double dy = rec0.fStartY - rec1.fStartY;
319 double dist0 = sqrt(dx*dx + dy*dy);
321 dx = rec0.fLastX - rec1.fLastX;
322 dy = rec0.fLastY - rec1.fLastY;
323 double dist1 = sqrt(dx*dx + dy*dy);
325 double scale = dist1 / dist0;
329bool TouchGesture::handleDblTap(
float x,
float y) {
339 fState = kEmpty_State;
351 fIsTransLimited =
true;
352 fContentRect = contentRect;
353 fWindowRect = windowRect;
354 fPreTouchM = preTouchMatrix;
357void TouchGesture::limitTrans() {
358 if (!fIsTransLimited) {
362 SkRect scaledContent = fContentRect;
363 fPreTouchM.
mapRect(&scaledContent);
364 fGlobalM.
mapRect(&scaledContent);
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
#define sk_float_round2int(x)
static int sign(SkScalar x)
#define SkDoubleToScalar(x)
#define DISCRETIZE_TRANSLATE_TO_AVOID_FLICKER
static SkScalar pin_max_fling(SkScalar speed)
static SkScalar SkScalarSignNonZero(SkScalar x)
static const SkScalar MAX_FLING_SPEED
static const float MAX_JITTER_RADIUS
static const float MAX_DBL_TAP_DISTANCE
static void unit_axis_align(SkVector *unit)
static double getseconds()
static SkScalar center(float pos0, float pos1)
static const SkMSec MAX_DBL_TAP_INTERVAL
static bool close_enough_for_jitter(float x0, float y0, float x1, float y1)
SkMatrix & postTranslate(SkScalar dx, SkScalar dy)
SkMatrix & postConcat(const SkMatrix &other)
SkMatrix & postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
SkMatrix & setTranslate(SkScalar dx, SkScalar dy)
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
void removeShuffle(int index)
void setTransLimit(const SkRect &contentRect, const SkRect &windowRect, const SkMatrix &preTouchM)
void touchEnd(void *owner)
bool isFling(SkPoint *dir)
void touchBegin(void *owner, float x, float y)
void touchMoved(void *owner, float x, float y)
const SkMatrix & localM()
void updateZoom(float scale, float startX, float startY, float lastX, float lastY)
unsigned useCenter Optional< SkMatrix > matrix
static float Normalize(SkVector *vec)
void set(float x, float y)
static float Length(float x, float y)
SkScalar fBottom
larger y-axis bounds
SkScalar fLeft
smaller x-axis bounds
SkScalar fRight
larger x-axis bounds
SkScalar fTop
smaller y-axis bounds