diff options
author | Konstantin Tokarev <annulen@yandex.ru> | 2016-08-25 19:20:41 +0300 |
---|---|---|
committer | Konstantin Tokarev <annulen@yandex.ru> | 2017-02-02 12:30:55 +0000 |
commit | 6882a04fb36642862b11efe514251d32070c3d65 (patch) | |
tree | b7959826000b061fd5ccc7512035c7478742f7b0 /Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.cpp | |
parent | ab6df191029eeeb0b0f16f127d553265659f739e (diff) | |
download | qtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz |
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f
Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.cpp')
-rw-r--r-- | Source/WebKit2/Shared/CoordinatedGraphics/SimpleViewportController.cpp | 201 |
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) |