| Index: Source/web/ViewportAnchor.cpp
|
| diff --git a/Source/web/ViewportAnchor.cpp b/Source/web/ViewportAnchor.cpp
|
| index 4a6a3d40164d5d6fb0f61dfd69c1936e049087c7..d4ec6563f8a3836166a1195d519d4b83b74429c0 100644
|
| --- a/Source/web/ViewportAnchor.cpp
|
| +++ b/Source/web/ViewportAnchor.cpp
|
| @@ -35,6 +35,7 @@
|
| #include "core/dom/Node.h"
|
| #include "core/page/EventHandler.h"
|
| #include "core/rendering/HitTestResult.h"
|
| +#include "platform/scroll/ScrollView.h"
|
|
|
| namespace blink {
|
|
|
| @@ -68,31 +69,76 @@
|
| return node;
|
| }
|
|
|
| +void moveToEncloseRect(IntRect& outer, const FloatRect& inner)
|
| +{
|
| + IntPoint minimumPosition = ceiledIntPoint(inner.location() + inner.size() - FloatSize(outer.size()));
|
| + IntPoint maximumPosition = flooredIntPoint(inner.location());
|
| +
|
| + IntPoint outerOrigin = outer.location();
|
| + outerOrigin = outerOrigin.expandedTo(minimumPosition);
|
| + outerOrigin = outerOrigin.shrunkTo(maximumPosition);
|
| +
|
| + outer.setLocation(outerOrigin);
|
| +}
|
| +
|
| +void moveIntoRect(FloatRect& inner, const IntRect& outer)
|
| +{
|
| + FloatPoint minimumPosition = FloatPoint(outer.location());
|
| + FloatPoint maximumPosition = minimumPosition + outer.size() - inner.size();
|
| +
|
| + // Adjust maximumPosition to the nearest lower integer because
|
| + // PinchViewport::maximumScrollPosition() does the same.
|
| + // The value of minumumPosition is already adjusted since it is
|
| + // constructed from an integer point.
|
| + maximumPosition = flooredIntPoint(maximumPosition);
|
| +
|
| + FloatPoint innerOrigin = inner.location();
|
| + innerOrigin = innerOrigin.expandedTo(minimumPosition);
|
| + innerOrigin = innerOrigin.shrunkTo(maximumPosition);
|
| +
|
| + inner.setLocation(innerOrigin);
|
| +}
|
| +
|
| } // namespace
|
|
|
| ViewportAnchor::ViewportAnchor(EventHandler* eventHandler)
|
| : m_eventHandler(eventHandler) { }
|
|
|
| -void ViewportAnchor::setAnchor(const IntRect& viewRect, const FloatSize& anchorInViewCoords)
|
| +void ViewportAnchor::setAnchor(const IntRect& outerViewRect, const IntRect& innerViewRect,
|
| + const FloatSize& anchorInInnerViewCoords)
|
| {
|
| - m_viewRect = viewRect;
|
| + // Preserve the inner viewport position in document in case we won't find the anchor
|
| + m_pinchViewportInDocument = innerViewRect.location();
|
| +
|
| m_anchorNode.clear();
|
| m_anchorNodeBounds = LayoutRect();
|
| m_anchorInNodeCoords = FloatSize();
|
| - m_anchorInViewCoords = anchorInViewCoords;
|
| + m_anchorInInnerViewCoords = anchorInInnerViewCoords;
|
| + m_normalizedPinchViewportOffset = FloatSize();
|
|
|
| - if (viewRect.isEmpty())
|
| + if (innerViewRect.isEmpty())
|
| return;
|
|
|
| // Preserve origins at the absolute screen origin
|
| - if (viewRect.location() == IntPoint::zero())
|
| + if (innerViewRect.location() == IntPoint::zero())
|
| return;
|
|
|
| - FloatSize anchorOffset = viewRect.size();
|
| - anchorOffset.scale(anchorInViewCoords.width(), anchorInViewCoords.height());
|
| - const FloatPoint anchorPoint = FloatPoint(viewRect.location()) + anchorOffset;
|
| + // Inner rectangle should be within the outer one.
|
| + ASSERT(outerViewRect.contains(innerViewRect));
|
|
|
| - Node* node = findNonEmptyAnchorNode(flooredIntPoint(anchorPoint), viewRect, m_eventHandler);
|
| + // Outer rectangle is used as a scale, we need positive width and height.
|
| + ASSERT(!outerViewRect.isEmpty());
|
| +
|
| + m_normalizedPinchViewportOffset = innerViewRect.location() - outerViewRect.location();
|
| +
|
| + // Normalize by the size of the outer rect
|
| + m_normalizedPinchViewportOffset.scale(1.0 / outerViewRect.width(), 1.0 / outerViewRect.height());
|
| +
|
| + FloatSize anchorOffset = innerViewRect.size();
|
| + anchorOffset.scale(anchorInInnerViewCoords.width(), anchorInInnerViewCoords.height());
|
| + const FloatPoint anchorPoint = FloatPoint(innerViewRect.location()) + anchorOffset;
|
| +
|
| + Node* node = findNonEmptyAnchorNode(flooredIntPoint(anchorPoint), innerViewRect, m_eventHandler);
|
| if (!node)
|
| return;
|
|
|
| @@ -102,14 +148,39 @@
|
| m_anchorInNodeCoords.scale(1.f / m_anchorNodeBounds.width(), 1.f / m_anchorNodeBounds.height());
|
| }
|
|
|
| -IntPoint ViewportAnchor::computeOrigin(const IntSize& currentViewSize) const
|
| +void ViewportAnchor::computeOrigins(const ScrollView& scrollView, const FloatSize& innerSize,
|
| + IntPoint& mainFrameOffset, FloatPoint& pinchViewportOffset) const
|
| +{
|
| + IntSize outerSize = scrollView.visibleContentRect().size();
|
| +
|
| + // Compute the viewport origins in CSS pixels relative to the document.
|
| + FloatSize absPinchViewportOffset = m_normalizedPinchViewportOffset;
|
| + absPinchViewportOffset.scale(outerSize.width(), outerSize.height());
|
| +
|
| + FloatPoint innerOrigin = getInnerOrigin(innerSize);
|
| + FloatPoint outerOrigin = innerOrigin - absPinchViewportOffset;
|
| +
|
| + IntRect outerRect = IntRect(flooredIntPoint(outerOrigin), outerSize);
|
| + FloatRect innerRect = FloatRect(innerOrigin, innerSize);
|
| +
|
| + moveToEncloseRect(outerRect, innerRect);
|
| +
|
| + outerRect.setLocation(scrollView.adjustScrollPositionWithinRange(outerRect.location()));
|
| +
|
| + moveIntoRect(innerRect, outerRect);
|
| +
|
| + mainFrameOffset = outerRect.location();
|
| + pinchViewportOffset = FloatPoint(innerRect.location() - outerRect.location());
|
| +}
|
| +
|
| +FloatPoint ViewportAnchor::getInnerOrigin(const FloatSize& innerSize) const
|
| {
|
| if (!m_anchorNode || !m_anchorNode->inDocument())
|
| - return m_viewRect.location();
|
| + return m_pinchViewportInDocument;
|
|
|
| const LayoutRect currentNodeBounds = m_anchorNode->boundingBox();
|
| if (m_anchorNodeBounds == currentNodeBounds)
|
| - return m_viewRect.location();
|
| + return m_pinchViewportInDocument;
|
|
|
| // Compute the new anchor point relative to the node position
|
| FloatSize anchorOffsetFromNode = currentNodeBounds.size();
|
| @@ -117,9 +188,9 @@
|
| FloatPoint anchorPoint = currentNodeBounds.location() + anchorOffsetFromNode;
|
|
|
| // Compute the new origin point relative to the new anchor point
|
| - FloatSize anchorOffsetFromOrigin = currentViewSize;
|
| - anchorOffsetFromOrigin.scale(m_anchorInViewCoords.width(), m_anchorInViewCoords.height());
|
| - return flooredIntPoint(anchorPoint - anchorOffsetFromOrigin);
|
| + FloatSize anchorOffsetFromOrigin = innerSize;
|
| + anchorOffsetFromOrigin.scale(m_anchorInInnerViewCoords.width(), m_anchorInInnerViewCoords.height());
|
| + return anchorPoint - anchorOffsetFromOrigin;
|
| }
|
|
|
| } // namespace blink
|
|
|