--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/WebCore/page/TouchGestureHandler.cpp Fri Sep 17 09:02:29 2010 +0300
@@ -0,0 +1,143 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "TouchGestureHandler.h"
+
+#include <math.h>
+
+#ifndef M_PI
+#define M_PI 3.1415926536
+#endif
+
+namespace WebCore {
+
+TouchGestureHandler::TouchGestureHandler()
+{
+ reset();
+}
+
+void TouchGestureHandler::updateRefreshNeededState(const Vector<const PlatformTouchPoint*>& touchPoints)
+{
+ // Number of touchpoints changed
+ if (touchPoints.size() != m_prevSize)
+ m_refreshNeeded = true;
+ else {
+ for (int i = 0; i < touchPoints.size(); ++i) {
+ // Touchpoints in pressed state or ids mismatch
+ if (touchPoints[i]->state() == PlatformTouchPoint::TouchPressed
+ || touchPoints[i]->id() != m_prevIds[i]) m_refreshNeeded = true;
+ }
+ }
+
+ m_prevSize = touchPoints.size();
+ for (int i = 0; i < touchPoints.size(); ++i)
+ m_prevIds[i] = touchPoints[i]->id();
+}
+
+void TouchGestureHandler::updateTouchPoints(const Vector<const PlatformTouchPoint*>& touchPoints)
+{
+ if (touchPoints.isEmpty())
+ return;
+
+ updateRefreshNeededState(touchPoints);
+
+ if (m_refreshNeeded) {
+ m_pos = calcPos(touchPoints);
+ IntSize clientOffset = touchPoints[0]->screenPos() - touchPoints[0]->pos();
+ m_screenPos = m_pos + clientOffset;
+
+ if (touchPoints.size() > 1) {
+ m_prevAngle = calcAngle(touchPoints[0]->pos(), touchPoints[1]->pos());
+ m_prevDistance = calcDistance(touchPoints[0]->pos(), touchPoints[1]->pos());
+ }
+ m_refreshNeeded = false;
+ return;
+ }
+
+ // Pan
+ IntPoint nextPos = calcPos(touchPoints);
+ m_translate += (nextPos - m_pos);
+ m_pos = nextPos;
+ IntSize clientOffset = touchPoints[0]->screenPos() - touchPoints[0]->pos();
+ m_screenPos = m_pos + clientOffset;
+
+ if (touchPoints.size() > 1) {
+ // Rotate
+ float angle = calcAngle(touchPoints[0]->pos(), touchPoints[1]->pos());
+ m_rotate += diffAngle(m_prevAngle, angle);
+ m_prevAngle = angle;
+
+ // Pinch
+ float distance = calcDistance(touchPoints[0]->pos(), touchPoints[1]->pos());
+ float nextScale = m_scale * (distance / (m_prevDistance ? m_prevDistance : 0.0001f));
+ m_scale = nextScale;
+ m_prevDistance = distance;
+ }
+}
+
+void TouchGestureHandler::reset()
+{
+ m_refreshNeeded = true;
+ m_scale = 1.0;
+ m_rotate = 0;
+ m_translate = IntPoint(0, 0);
+ m_pos = IntPoint(0, 0);
+ m_screenPos = IntPoint(0, 0);
+ m_prevSize = 0;
+}
+
+float TouchGestureHandler::calcAngle(const IntPoint& p1, const IntPoint& p2) const
+{
+ float deltaX = p1.x() - p2.x();
+ float deltaY = p1.y() - p2.y();
+ return atan2(deltaY, deltaX);
+}
+
+float TouchGestureHandler::diffAngle(float alpha, float beta) const
+{
+ float between = beta - alpha;
+
+ if (between > M_PI)
+ between -= 2 * M_PI;
+ else if (between < -M_PI)
+ between += 2 * M_PI;
+
+ return between;
+}
+
+IntPoint TouchGestureHandler::calcPos(const Vector<const PlatformTouchPoint*>& touchPoints) const
+{
+ if (touchPoints.size() == 1)
+ return touchPoints[0]->pos();
+
+ IntPoint pos;
+ pos.setX((touchPoints[0]->pos().x() + touchPoints[1]->pos().x()) / 2);
+ pos.setY((touchPoints[0]->pos().y() + touchPoints[1]->pos().y()) / 2);
+ return pos;
+}
+
+float TouchGestureHandler::calcDistance(const IntPoint& p1, const IntPoint& p2) const
+{
+ float dx = p1.x() - p2.x();
+ float dy = p1.y() - p2.y();
+ return sqrt(dx * dx + dy * dy);
+}
+
+}