diff -r 000000000000 -r 4f2f89ce4247 WebCore/page/TouchGestureHandler.cpp --- /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 + +#ifndef M_PI +#define M_PI 3.1415926536 +#endif + +namespace WebCore { + +TouchGestureHandler::TouchGestureHandler() +{ + reset(); +} + +void TouchGestureHandler::updateRefreshNeededState(const Vector& 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& 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& 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); +} + +}