Chromium Code Reviews| Index: Source/web/ViewportAnchor.cpp |
| diff --git a/Source/web/ViewportAnchor.cpp b/Source/web/ViewportAnchor.cpp |
| index 4a6a3d40164d5d6fb0f61dfd69c1936e049087c7..ac6f5bc2c47d5f5d34483ed39f2d748dd19805fc 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,80 @@ Node* findNonEmptyAnchorNode(const IntPoint& point, const IntRect& viewRect, Eve |
| return node; |
| } |
| +void moveToEncloseRect(IntRect * outer, const FloatRect & inner) |
| +{ |
| + ASSERT(outer); |
| + |
| + 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) |
| +{ |
| + ASSERT(inner); |
| + |
| + FloatPoint minimumPosition = FloatPoint(outer.location()); |
| + FloatPoint maximumPosition = minimumPosition + outer.size() - inner->size(); |
| + |
| + // Adjust maximumPosition to the nearest lower integer because |
| + // PinchViewport::maximimScrollPosition() does the same. |
|
bokan
2014/09/15 21:02:20
nit: typo on maximim -> maximum
timav
2014/09/15 21:42:55
Done.
|
| + // 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 +152,44 @@ void ViewportAnchor::setAnchor(const IntRect& viewRect, const FloatSize& anchorI |
| 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* frameView, |
| + const IntSize& outerSize, const FloatSize& innerSize, |
|
bokan
2014/09/15 21:02:21
You can get outerSize from frameView. Remove the o
timav
2014/09/15 21:42:55
Done.
|
| + IntPoint* mainFrameOffset, FloatPoint* pinchViewportOffset) const |
| +{ |
| + // 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; |
| + |
| + // Create the outer and inner rectangles that represent the viewports. |
| + IntRect outerRect = IntRect(flooredIntPoint(outerOrigin), outerSize); |
| + FloatRect innerRect = FloatRect(innerOrigin, innerSize); |
| + |
| + // Move outer viewport to enclose inner viewport. |
| + moveToEncloseRect(&outerRect, innerRect); |
| + |
| + // Move outer viewport again to fit the scroll view constraints. |
| + ASSERT(frameView); |
| + outerRect.setLocation(frameView->adjustScrollPositionWithinRange(outerRect.location())); |
| + |
| + // Push inner viewport inside the outer. |
| + moveIntoRect(&innerRect, outerRect); |
| + |
| + // Return the final results. |
| + *mainFrameOffset = outerRect.location(); |
| + *pinchViewportOffset = FloatPoint(innerRect.location() - FloatPoint(outerRect.location())); |
|
bokan
2014/09/15 21:02:20
You can remove the outer-most FloatPoint(...)
timav
2014/09/15 21:42:55
FloatPoint - FloatPoint = FloatSize, but pinchView
|
| +} |
| + |
| +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 +197,9 @@ IntPoint ViewportAnchor::computeOrigin(const IntSize& currentViewSize) const |
| 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 |