Tizen 2.1 base
[framework/web/webkit-efl.git] / Source / WebKit2 / UIProcess / API / efl / tizen / Zoom.cpp
1 /*
2  * Copyright (C) 2012 Samsung Electronics
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this program; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21 #include "Zoom.h"
22
23 #include "PageClientImpl.h"
24 #include "ewk_view_private.h"
25
26 #if ENABLE(TIZEN_WEBKIT2_TEXT_ZOOM)
27 #include "WebPageGroup.h"
28 #include "WebPreferences.h"
29 #endif
30
31 using namespace WebCore;
32 using namespace WebKit;
33
34 const double Zoom::s_scaleFactorThreshold = 0.01;
35
36 static IntPoint getNewScrollPosition(const IntPoint& scrollPosition, const IntPoint& basisPoint, double baseScaleFactor, double newScaleFactor)
37 {
38     if (!baseScaleFactor)
39         return IntPoint();
40
41     double scaleDifference = newScaleFactor / baseScaleFactor;
42     int newScrollX = (scrollPosition.x() + basisPoint.x()) * scaleDifference - basisPoint.x();
43     int newScrollY = (scrollPosition.y() + basisPoint.y()) * scaleDifference - basisPoint.y();
44
45     return IntPoint(newScrollX, newScrollY);
46 }
47
48 static int getPointDistanceSquare(const IntPoint& point1, const IntPoint& point2)
49 {
50     int xDistance = point1.x() - point2.x();
51     int yDistance = point1.y() - point2.y();
52     return xDistance * xDistance + yDistance * yDistance;
53 }
54
55 Zoom::Zoom(Evas_Object* viewWidget)
56     : m_viewWidget(viewWidget)
57     , m_isZooming(false)
58     , m_isZoomInformationUpdated(false)
59     , m_baseScaleFactor(0)
60     , m_newScaleFactor(0)
61     , m_currentScaleFactor(0)
62     , m_baseScrollPosition()
63     , m_newScrollPosition()
64     , m_basisPoint()
65     , m_centerPoint()
66     , m_viewLocation()
67     , m_zoomAnimator(0)
68 {
69 }
70
71 Zoom::~Zoom()
72 {
73     if (m_zoomAnimator)
74         ecore_animator_del(m_zoomAnimator);
75 }
76
77 void Zoom::start(const IntPoint& centerPoint, const IntPoint& viewLocation)
78 {
79     PageClientImpl* pageClientImpl = ewkViewGetPageClient(m_viewWidget);
80     EINA_SAFETY_ON_NULL_RETURN(pageClientImpl);
81     m_isZooming = true;
82     m_isZoomInformationUpdated = false;
83     m_baseScaleFactor = pageClientImpl->scaleFactor();
84     m_newScaleFactor = m_baseScaleFactor;
85     m_currentScaleFactor = m_baseScaleFactor;
86     m_newScrollPosition = m_baseScrollPosition = pageClientImpl->scrollPosition();
87     m_centerPoint = centerPoint;
88     int viewX, viewY;
89     evas_object_geometry_get(m_viewWidget, &viewX, &viewY, 0, 0);
90     m_viewLocation = IntPoint(viewX, viewY);
91
92     m_basisPoint.setX(centerPoint.x() - m_viewLocation.x());
93     m_basisPoint.setY(centerPoint.y() - m_viewLocation.y());
94
95     if (m_zoomAnimator)
96         ecore_animator_del(m_zoomAnimator);
97     m_zoomAnimator = ecore_animator_add(zoomAnimatorCallback, this);
98
99     // Notify that zoom is started.
100     evas_object_smart_callback_call(m_viewWidget, "zoom,started", 0);
101 }
102
103 void Zoom::stop()
104 {
105     m_isZooming = false;
106 }
107
108 void Zoom::update(const double zoom, const IntPoint& centerPoint)
109 {
110     if (!m_isZooming)
111         start(centerPoint, IntPoint());
112
113     PageClientImpl* pageClientImpl = ewkViewGetPageClient(m_viewWidget);
114     EINA_SAFETY_ON_NULL_RETURN(pageClientImpl);
115 #if ENABLE(TIZEN_WEBKIT2_TEXT_ZOOM)
116     double newScaleFactor = m_baseScaleFactor * zoom;
117     if (!pageClientImpl->page()->pageGroup()->preferences()->textZoomEnabled())
118         newScaleFactor = pageClientImpl->adjustScaleWithViewport(newScaleFactor);
119 #else
120     double newScaleFactor = pageClientImpl->adjustScaleWithViewport(m_baseScaleFactor * zoom);
121 #endif
122
123     if (fabs(newScaleFactor - m_newScaleFactor) > s_scaleFactorThreshold)
124         m_newScaleFactor = newScaleFactor;
125     else if (getPointDistanceSquare(m_centerPoint, centerPoint) <= s_zoomCenterDistanceSquareThreshold)
126         return;
127
128     m_centerPoint = centerPoint;
129     m_isZoomInformationUpdated = true;
130 }
131
132 void Zoom::realStop()
133 {
134     if (m_zoomAnimator) {
135         ecore_animator_del(m_zoomAnimator);
136         m_zoomAnimator = 0;
137     }
138
139     PageClientImpl* pageClientImpl = ewkViewGetPageClient(m_viewWidget);
140     pageClientImpl->page()->scaleImage(m_newScaleFactor, m_newScrollPosition);
141     EINA_SAFETY_ON_NULL_RETURN(pageClientImpl);
142
143 #if ENABLE(TIZEN_WEBKIT2_TEXT_ZOOM)
144     if (pageClientImpl->page()->pageGroup()->preferences()->textZoomEnabled()) {
145         double textScaleFactor = pageClientImpl->adjustScaleWithViewport(pageClientImpl->page()->textZoomFactor() * (m_newScaleFactor / m_baseScaleFactor));
146         pageClientImpl->page()->scale(m_baseScaleFactor, m_baseScrollPosition);
147         pageClientImpl->page()->setTextZoomFactor(textScaleFactor);
148     } else
149         pageClientImpl->page()->scale(m_newScaleFactor, m_newScrollPosition);
150 #else
151     pageClientImpl->page()->scale(m_newScaleFactor, m_newScrollPosition);
152 #endif
153
154 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
155     pageClientImpl->updateTextSelectionHandlesAndContextMenu(true);
156 #endif
157
158     // Notify that zoom is finished.
159     evas_object_smart_callback_call(m_viewWidget, "zoom,finished", 0);
160 }
161
162 Eina_Bool Zoom::zoomAnimatorCallback(void* data)
163 {
164     static_cast<Zoom*>(data)->process();
165     return ECORE_CALLBACK_RENEW;
166 }
167
168 void Zoom::process()
169 {
170     if (!m_isZooming && (m_currentScaleFactor == m_newScaleFactor)) {
171         realStop();
172         return;
173     }
174
175     if (!m_isZoomInformationUpdated)
176         return;
177
178     double scaleStep = m_currentScaleFactor / 6;
179     if (fabs(m_currentScaleFactor - m_newScaleFactor) > scaleStep) {
180         if (m_newScaleFactor > m_currentScaleFactor)
181             m_currentScaleFactor += scaleStep;
182         else
183             m_currentScaleFactor -= scaleStep;
184     } else
185         m_currentScaleFactor = m_newScaleFactor;
186
187     m_newScrollPosition = getNewScrollPosition(m_baseScrollPosition, m_basisPoint, m_baseScaleFactor, m_currentScaleFactor);
188     m_newScrollPosition.setX(m_newScrollPosition.x() + m_basisPoint.x() - (m_centerPoint.x() - m_viewLocation.x()));
189     m_newScrollPosition.setY(m_newScrollPosition.y() + m_basisPoint.y() - (m_centerPoint.y() - m_viewLocation.y()));
190
191     PageClientImpl* pageClientImpl = ewkViewGetPageClient(m_viewWidget);
192     EINA_SAFETY_ON_NULL_RETURN(pageClientImpl);
193     pageClientImpl->page()->scaleImage(m_currentScaleFactor, m_newScrollPosition);
194
195 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
196     pageClientImpl->updateTextSelectionHandlesAndContextMenu(false);
197 #endif
198
199     if (m_currentScaleFactor == m_newScaleFactor)
200         m_isZoomInformationUpdated = false;
201 }