summaryrefslogtreecommitdiff
path: root/Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.cpp
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@qt.io>2017-05-30 12:48:17 +0200
committerOswald Buddenhagen <oswald.buddenhagen@qt.io>2017-05-30 12:48:17 +0200
commit881da28418d380042aa95a97f0cbd42560a64f7c (patch)
treea794dff3274695e99c651902dde93d934ea7a5af /Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.cpp
parent7e104c57a70fdf551bb3d22a5d637cdcbc69dbea (diff)
parent0fcedcd17cc00d3dd44c718b3cb36c1033319671 (diff)
downloadqtwebkit-881da28418d380042aa95a97f0cbd42560a64f7c.tar.gz
Merge 'wip/next' into dev
Change-Id: Iff9ee5e23bb326c4371ec8ed81d56f2f05d680e9
Diffstat (limited to 'Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.cpp')
-rw-r--r--Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.cpp201
1 files changed, 201 insertions, 0 deletions
diff --git a/Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.cpp b/Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.cpp
new file mode 100644
index 000000000..11b55bef7
--- /dev/null
+++ b/Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2011, 2012 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2011 Benjamin Poulain <benjamin@webkit.org>
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * 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 program 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 program; 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"
+
+#if USE(COORDINATED_GRAPHICS_THREADED)
+#include "SimpleViewportController.h"
+
+using namespace WebCore;
+
+namespace WebKit {
+
+SimpleViewportController::SimpleViewportController(Client* client)
+ : m_client(client)
+ , m_contentsPosition(FloatPoint())
+ , m_contentsSize(FloatSize())
+ , m_viewportSize(FloatSize())
+ , m_allowsUserScaling(false)
+ , m_initiallyFitToViewport(true)
+ , m_hasViewportAttribute(false)
+{
+ resetViewportToDefaultState();
+}
+
+void SimpleViewportController::didChangeViewportSize(const FloatSize& newSize)
+{
+ if (newSize.isEmpty())
+ return;
+
+ m_viewportSize = newSize;
+ updateMinimumScaleToFit();
+ syncVisibleContents();
+}
+
+void SimpleViewportController::didChangeContentsSize(const IntSize& newSize)
+{
+ m_contentsSize = newSize;
+
+ updateMinimumScaleToFit();
+
+ if (m_initiallyFitToViewport) {
+ // Restrict scale factors to m_minimumScaleToFit.
+ ASSERT(m_minimumScaleToFit > 0);
+ m_rawAttributes.initialScale = m_minimumScaleToFit;
+ restrictScaleFactorToInitialScaleIfNotUserScalable(m_rawAttributes);
+ }
+
+ syncVisibleContents();
+}
+
+void SimpleViewportController::didChangeViewportAttribute(const ViewportAttributes& newAttributes)
+{
+ if (newAttributes.layoutSize.isEmpty()) {
+ resetViewportToDefaultState();
+ return;
+ }
+
+ m_hasViewportAttribute = true;
+
+ m_rawAttributes = newAttributes;
+ m_allowsUserScaling = m_rawAttributes.userScalable;
+ m_initiallyFitToViewport = m_rawAttributes.initialScale < 0;
+
+ if (!m_initiallyFitToViewport)
+ restrictScaleFactorToInitialScaleIfNotUserScalable(m_rawAttributes);
+
+ updateMinimumScaleToFit();
+
+ syncVisibleContents();
+}
+
+void SimpleViewportController::scrollBy(const IntSize& scrollOffset)
+{
+ m_contentsPosition.move(scrollOffset);
+ m_contentsPosition = boundContentsPosition(m_contentsPosition);
+
+ syncVisibleContents();
+}
+
+void SimpleViewportController::scrollTo(const IntPoint& position)
+{
+ if (m_contentsPosition == boundContentsPosition(position))
+ return;
+
+ m_contentsPosition = boundContentsPosition(position);
+ syncVisibleContents();
+}
+
+void SimpleViewportController::syncVisibleContents()
+{
+ if (m_viewportSize.isEmpty() || m_contentsSize.isEmpty())
+ return;
+
+ m_client->didChangeVisibleRect();
+}
+
+FloatRect SimpleViewportController::visibleContentsRect() const
+{
+ FloatRect visibleContentsRect(boundContentsPosition(m_contentsPosition), visibleContentsSize());
+ visibleContentsRect.intersect(FloatRect(FloatPoint::zero(), m_contentsSize));
+
+ return visibleContentsRect;
+}
+
+FloatSize SimpleViewportController::visibleContentsSize() const
+{
+ return FloatSize(m_viewportSize.width() / m_pageScaleFactor, m_viewportSize.height() / m_pageScaleFactor);
+}
+
+FloatPoint SimpleViewportController::boundContentsPositionAtScale(const FloatPoint& framePosition, float scale) const
+{
+ // We need to floor the viewport here as to allow aligning the content in device units. If not,
+ // it might not be possible to scroll the last pixel and that affects fixed position elements.
+ return FloatPoint(
+ clampTo(framePosition.x(), .0f, std::max(.0f, m_contentsSize.width() - floorf(m_viewportSize.width() / scale))),
+ clampTo(framePosition.y(), .0f, std::max(.0f, m_contentsSize.height() - floorf(m_viewportSize.height() / scale))));
+}
+
+FloatPoint SimpleViewportController::boundContentsPosition(const FloatPoint& framePosition) const
+{
+ return boundContentsPositionAtScale(framePosition, m_pageScaleFactor);
+}
+
+bool fuzzyCompare(float a, float b, float epsilon)
+{
+ return std::abs(a - b) < epsilon;
+}
+
+bool SimpleViewportController::updateMinimumScaleToFit()
+{
+ if (m_viewportSize.isEmpty() || m_contentsSize.isEmpty() || !m_hasViewportAttribute)
+ return false;
+
+ bool currentlyScaledToFit = fuzzyCompare(m_pageScaleFactor, m_minimumScaleToFit, 0.0001);
+
+ float minimumScale = computeMinimumScaleFactorForContentContained(m_rawAttributes, roundedIntSize(m_viewportSize), roundedIntSize(m_contentsSize));
+
+ if (minimumScale <= 0)
+ return false;
+
+ if (!fuzzyCompare(minimumScale, m_minimumScaleToFit, 0.0001)) {
+ m_minimumScaleToFit = minimumScale;
+
+ if (currentlyScaledToFit)
+ m_pageScaleFactor = m_minimumScaleToFit;
+ else {
+ // Ensure the effective scale stays within bounds.
+ float boundedScale = innerBoundedViewportScale(m_pageScaleFactor);
+ if (!fuzzyCompare(boundedScale, m_pageScaleFactor, 0.0001))
+ m_pageScaleFactor = boundedScale;
+ }
+
+ return true;
+ }
+ return false;
+}
+
+float SimpleViewportController::innerBoundedViewportScale(float viewportScale) const
+{
+ return clampTo(viewportScale, m_minimumScaleToFit, m_rawAttributes.maximumScale);
+}
+
+void SimpleViewportController::resetViewportToDefaultState()
+{
+ m_hasViewportAttribute = false;
+ m_pageScaleFactor = 1;
+ m_minimumScaleToFit = 1;
+
+ // Initializing Viewport Raw Attributes to avoid random negative or infinity scale factors
+ // if there is a race condition between the first layout and setting the viewport attributes for the first time.
+ m_rawAttributes.minimumScale = 1;
+ m_rawAttributes.maximumScale = 1;
+ m_rawAttributes.userScalable = m_allowsUserScaling;
+
+ // The initial scale might be implicit and set to -1, in this case we have to infer it
+ // using the viewport size and the final layout size.
+ // To be able to assert for valid scale we initialize it to -1.
+ m_rawAttributes.initialScale = -1;
+}
+
+} // namespace WebCore
+
+#endif // USE(COORDINATED_GRAPHICS_THREADED)