• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011, The Android Open Source Project
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *  * Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 #include "ZoomManager.h"
28 
29 #include "GLWebViewState.h"
30 
31 #if USE(ACCELERATED_COMPOSITING)
32 
33 #include <wtf/CurrentTime.h>
34 
35 #include <cutils/log.h>
36 #include <wtf/text/CString.h>
37 
38 #undef XLOGC
39 #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "ZoomManager", __VA_ARGS__)
40 
41 #ifdef DEBUG
42 
43 #undef XLOG
44 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "ZoomManager", __VA_ARGS__)
45 
46 #else
47 
48 #undef XLOG
49 #define XLOG(...)
50 
51 #endif // DEBUG
52 
53 namespace WebCore {
54 
55 using namespace android;
56 
ZoomManager(GLWebViewState * state)57 ZoomManager::ZoomManager(GLWebViewState* state)
58     : m_scaleRequestState(kNoScaleRequest)
59     , m_currentScale(-1)
60     , m_futureScale(-1)
61     , m_layersScale(-1)
62     , m_updateTime(-1)
63     , m_transitionTime(-1)
64     , m_glWebViewState(state)
65 {
66 }
67 
scheduleUpdate(const double & currentTime,const SkIRect & viewport,float scale)68 void ZoomManager::scheduleUpdate(const double& currentTime,
69                                  const SkIRect& viewport, float scale)
70 {
71     // if no update time, set it
72     if (updateTime() == -1) {
73         m_scaleRequestState = kWillScheduleRequest;
74         setUpdateTime(currentTime + s_updateInitialDelay);
75         setFutureScale(scale);
76         m_glWebViewState->setFutureViewport(viewport);
77         return;
78     }
79 
80     if (currentTime < updateTime())
81         return;
82 
83     // we reached the scheduled update time, check if we can update
84     if (futureScale() == scale) {
85         // we are still with the previous scale, let's go
86         // with the update
87         m_scaleRequestState = kRequestNewScale;
88         setUpdateTime(-1);
89     } else {
90         // we reached the update time, but the planned update was for
91         // a different scale factor -- meaning the user is still probably
92         // in the process of zooming. Let's push the update time a bit.
93         setUpdateTime(currentTime + s_updateDelay);
94         setFutureScale(scale);
95         m_glWebViewState->setFutureViewport(viewport);
96     }
97 }
98 
zoomInTransitionTime(double currentTime)99 double ZoomManager::zoomInTransitionTime(double currentTime)
100 {
101     if (m_transitionTime == -1)
102         m_transitionTime = currentTime + s_zoomInTransitionDelay;
103     return m_transitionTime;
104 }
105 
zoomOutTransitionTime(double currentTime)106 double ZoomManager::zoomOutTransitionTime(double currentTime)
107 {
108     if (m_transitionTime == -1)
109         m_transitionTime = currentTime + s_zoomOutTransitionDelay;
110     return m_transitionTime;
111 }
112 
zoomInTransparency(double currentTime)113 float ZoomManager::zoomInTransparency(double currentTime)
114 {
115     float t = zoomInTransitionTime(currentTime) - currentTime;
116     t *= s_invZoomInTransitionDelay;
117     return fmin(1, fmax(0, t));
118 }
119 
zoomOutTransparency(double currentTime)120 float ZoomManager::zoomOutTransparency(double currentTime)
121 {
122     float t = zoomOutTransitionTime(currentTime) - currentTime;
123     t *= s_invZoomOutTransitionDelay;
124     return fmin(1, fmax(0, t));
125 }
126 
swapPages()127 bool ZoomManager::swapPages()
128 {
129     bool reset = m_scaleRequestState != kNoScaleRequest;
130     m_scaleRequestState = kNoScaleRequest;
131     return reset;
132 }
133 
processNewScale(double currentTime,float scale)134 void ZoomManager::processNewScale(double currentTime, float scale)
135 {
136     m_prepareNextTiledPage = false;
137     m_zooming = false;
138     const SkIRect& viewportTileBounds = m_glWebViewState->viewportTileBounds();
139 
140     if (scale == m_currentScale
141         || m_glWebViewState->preZoomBounds().isEmpty())
142       m_glWebViewState->setPreZoomBounds(viewportTileBounds);
143 
144     // If we have a different scale than the current one, we have to
145     // decide what to do. The current behaviour is to delay an update,
146     // so that we do not slow down zooming unnecessarily.
147     if ((m_currentScale != scale
148         && (m_scaleRequestState == ZoomManager::kNoScaleRequest
149             || m_futureScale != scale))
150         || m_scaleRequestState == ZoomManager::kWillScheduleRequest) {
151 
152         // schedule the new Zoom request
153         scheduleUpdate(currentTime, viewportTileBounds, scale);
154 
155         // If it's a new request, we will have to prepare the page.
156         if (m_scaleRequestState == ZoomManager::kRequestNewScale)
157             m_prepareNextTiledPage = true;
158     }
159 
160     // If the viewport has changed since we scheduled the request, we also need
161     // to prepare.
162     if ((m_scaleRequestState == ZoomManager::kRequestNewScale
163          || m_scaleRequestState == ZoomManager::kReceivedNewScale)
164         && m_glWebViewState->futureViewport() != viewportTileBounds)
165         m_prepareNextTiledPage = true;
166 
167     // Checking if we are zooming...
168     if (m_scaleRequestState != ZoomManager::kNoScaleRequest) {
169         m_prepareNextTiledPage = true;
170         m_zooming = true;
171     }
172 
173     // Get the current scale; if we are zooming, we don't change the scale
174     // factor immediately (see BaseLayerAndroid::drawBasePictureInGL()), but
175     // we change the scaleRequestState. When the state is kReceivedNewScale
176     // (see setReceivedRequest()), we can use the future scale instead of
177     // the current scale to request new textures. After a transition time,
178     // the scaleRequestState will be reset and the current scale will be set
179     // to the future scale.
180     m_layersScale = m_currentScale;
181 }
182 
processTransition(double currentTime,float scale,bool * doSwap,float * backPageTransparency,float * frontPageTransparency)183 void ZoomManager::processTransition(double currentTime, float scale,
184                                      bool* doSwap, float* backPageTransparency,
185                                      float* frontPageTransparency)
186 {
187     if (scale < m_currentScale)
188         *backPageTransparency = 1 - zoomOutTransparency(currentTime);
189     else
190         *frontPageTransparency = zoomInTransparency(currentTime);
191 
192     // The transition between the two page is finished
193     if (currentTime > transitionTime(currentTime, scale)) {
194         resetTransitionTime();
195         *doSwap = true;
196     }
197 }
198 
199 } // namespace WebCore
200 
201 #endif // USE(ACCELERATED_COMPOSITING)
202