[Threaded Compositor] Initialize the threaded compositor with the current size
[WebKit-https.git] / Source / WebKit2 / Shared / CoordinatedGraphics / SimpleViewportController.cpp
1 /*
2  * Copyright (C) 2011, 2012 Nokia Corporation and/or its subsidiary(-ies)
3  * Copyright (C) 2011 Benjamin Poulain <benjamin@webkit.org>
4  * Copyright (C) 2014 Igalia S.L.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this program; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 #include "config.h"
23 #include "SimpleViewportController.h"
24
25 #if USE(COORDINATED_GRAPHICS_THREADED)
26
27 using namespace WebCore;
28
29 namespace WebKit {
30
31 SimpleViewportController::SimpleViewportController(const IntSize& size)
32     : m_viewportSize(size)
33 {
34     resetViewportToDefaultState();
35 }
36
37 void SimpleViewportController::didChangeViewportSize(const IntSize& newSize)
38 {
39     if (newSize.isEmpty())
40         return;
41
42     m_viewportSize = newSize;
43     updateMinimumScaleToFit();
44 }
45
46 void SimpleViewportController::didChangeContentsSize(const IntSize& newSize)
47 {
48     m_contentsSize = newSize;
49
50     updateMinimumScaleToFit();
51
52     if (m_initiallyFitToViewport) {
53         // Restrict scale factors to m_minimumScaleToFit.
54         ASSERT(m_minimumScaleToFit > 0);
55         m_rawAttributes.initialScale = m_minimumScaleToFit;
56         restrictScaleFactorToInitialScaleIfNotUserScalable(m_rawAttributes);
57     }
58 }
59
60 void SimpleViewportController::didChangeViewportAttributes(const ViewportAttributes& newAttributes)
61 {
62     if (newAttributes.layoutSize.isEmpty()) {
63         resetViewportToDefaultState();
64         return;
65     }
66
67     m_hasViewportAttribute = true;
68
69     m_rawAttributes = newAttributes;
70     m_allowsUserScaling = m_rawAttributes.userScalable;
71     m_initiallyFitToViewport = m_rawAttributes.initialScale < 0;
72
73     if (!m_initiallyFitToViewport)
74         restrictScaleFactorToInitialScaleIfNotUserScalable(m_rawAttributes);
75
76     updateMinimumScaleToFit();
77 }
78
79 void SimpleViewportController::didScroll(const IntPoint& position)
80 {
81     m_contentsPosition = position;
82 }
83
84 FloatRect SimpleViewportController::visibleContentsRect() const
85 {
86     if (m_viewportSize.isEmpty() || m_contentsSize.isEmpty())
87         return { };
88
89     FloatRect visibleContentsRect(boundContentsPosition(m_contentsPosition), visibleContentsSize());
90     visibleContentsRect.intersect(FloatRect(FloatPoint::zero(), m_contentsSize));
91     return visibleContentsRect;
92 }
93
94 FloatSize SimpleViewportController::visibleContentsSize() const
95 {
96     return FloatSize(m_viewportSize.width() / m_pageScaleFactor, m_viewportSize.height() / m_pageScaleFactor);
97 }
98
99 FloatPoint SimpleViewportController::boundContentsPositionAtScale(const FloatPoint& framePosition, float scale) const
100 {
101     // We need to floor the viewport here as to allow aligning the content in device units. If not,
102     // it might not be possible to scroll the last pixel and that affects fixed position elements.
103     return FloatPoint(
104         clampTo(framePosition.x(), .0f, std::max(.0f, m_contentsSize.width() - floorf(m_viewportSize.width() / scale))),
105         clampTo(framePosition.y(), .0f, std::max(.0f, m_contentsSize.height() - floorf(m_viewportSize.height() / scale))));
106 }
107
108 FloatPoint SimpleViewportController::boundContentsPosition(const FloatPoint& framePosition) const
109 {
110     return boundContentsPositionAtScale(framePosition, m_pageScaleFactor);
111 }
112
113 bool fuzzyCompare(float a, float b, float epsilon)
114 {
115     return std::abs(a - b) < epsilon;
116 }
117
118 bool SimpleViewportController::updateMinimumScaleToFit()
119 {
120     if (m_viewportSize.isEmpty() || m_contentsSize.isEmpty() || !m_hasViewportAttribute)
121         return false;
122
123     bool currentlyScaledToFit = fuzzyCompare(m_pageScaleFactor, m_minimumScaleToFit, 0.0001);
124
125     float minimumScale = computeMinimumScaleFactorForContentContained(m_rawAttributes, roundedIntSize(m_viewportSize), roundedIntSize(m_contentsSize));
126
127     if (minimumScale <= 0)
128         return false;
129
130     if (!fuzzyCompare(minimumScale, m_minimumScaleToFit, 0.0001)) {
131         m_minimumScaleToFit = minimumScale;
132
133         if (currentlyScaledToFit)
134             m_pageScaleFactor = m_minimumScaleToFit;
135         else {
136             // Ensure the effective scale stays within bounds.
137             float boundedScale = innerBoundedViewportScale(m_pageScaleFactor);
138             if (!fuzzyCompare(boundedScale, m_pageScaleFactor, 0.0001))
139                 m_pageScaleFactor = boundedScale;
140         }
141
142         return true;
143     }
144     return false;
145 }
146
147 float SimpleViewportController::innerBoundedViewportScale(float viewportScale) const
148 {
149     return clampTo(viewportScale, m_minimumScaleToFit, m_rawAttributes.maximumScale);
150 }
151
152 void SimpleViewportController::resetViewportToDefaultState()
153 {
154     m_hasViewportAttribute = false;
155     m_pageScaleFactor = 1;
156     m_minimumScaleToFit = 1;
157
158     // Initializing Viewport Raw Attributes to avoid random negative or infinity scale factors
159     // if there is a race condition between the first layout and setting the viewport attributes for the first time.
160     m_rawAttributes.minimumScale = 1;
161     m_rawAttributes.maximumScale = 1;
162     m_rawAttributes.userScalable = m_allowsUserScaling;
163
164     // The initial scale might be implicit and set to -1, in this case we have to infer it
165     // using the viewport size and the final layout size.
166     // To be able to assert for valid scale we initialize it to -1.
167     m_rawAttributes.initialScale = -1;
168 }
169
170 } // namespace WebCore
171
172 #endif // USE(COORDINATED_GRAPHICS_THREADED)