Chromium Code Reviews| Index: cc/CCLayerTreeHostImpl.cpp |
| =================================================================== |
| --- cc/CCLayerTreeHostImpl.cpp (revision 158365) |
| +++ cc/CCLayerTreeHostImpl.cpp (working copy) |
| @@ -48,6 +48,49 @@ |
| namespace cc { |
| +FloatRect CCPinchZoomViewport::bounds() const |
| +{ |
| + FloatSize scaledBounds = m_unpinchedBounds; |
| + if (m_pageScaleFactor > 1) |
| + scaledBounds.scale(1 / m_pageScaleFactor); |
|
aelias_OOO_until_Jul13
2012/09/25 03:53:29
On Android, < 1 pageScaleFactors are common.
I th
|
| + |
| + FloatRect bounds; |
| + bounds.setSize(scaledBounds); |
| + bounds.setLocation(m_pinchViewportScrollDelta); |
| + |
| + return bounds; |
| +} |
| + |
| +FloatSize CCPinchZoomViewport::applyScroll(FloatSize& delta) |
| +{ |
| + FloatSize overflow; |
| + FloatRect pinchedBounds = bounds(); |
| + |
| + pinchedBounds.move(delta); |
| + if (pinchedBounds.x() < 0) { |
| + pinchedBounds.setX(0); |
| + overflow.setWidth(pinchedBounds.x()); |
| + } |
| + |
| + if (pinchedBounds.y() < 0) { |
| + pinchedBounds.setY(0); |
| + overflow.setHeight(pinchedBounds.y()); |
| + } |
| + |
| + if (pinchedBounds.maxX() > m_unpinchedBounds.width()) { |
| + pinchedBounds.move(m_unpinchedBounds.width() - pinchedBounds.maxX(), 0); |
| + overflow.setWidth(pinchedBounds.maxX() - m_unpinchedBounds.width()); |
| + } |
| + |
| + if (pinchedBounds.maxY() > m_unpinchedBounds.height()) { |
| + pinchedBounds.move(0, m_unpinchedBounds.height() - pinchedBounds.maxY()); |
| + overflow.setHeight(pinchedBounds.maxY() - m_unpinchedBounds.height()); |
| + } |
| + m_pinchViewportScrollDelta = pinchedBounds.location(); |
| + |
| + return overflow; |
| +} |
| + |
| class CCLayerTreeHostImplTimeSourceAdapter : public CCTimeSourceClient { |
| WTF_MAKE_NONCOPYABLE(CCLayerTreeHostImplTimeSourceAdapter); |
| public: |
| @@ -115,11 +158,11 @@ |
| , m_visible(true) |
| , m_contentsTexturesPurged(false) |
| , m_memoryAllocationLimitBytes(CCPrioritizedTextureManager::defaultMemoryAllocationLimit()) |
| - , m_pageScale(1) |
| + , m_pageScaleFactor(1) |
| , m_pageScaleDelta(1) |
| , m_sentPageScaleDelta(1) |
| - , m_minPageScale(0) |
| - , m_maxPageScale(0) |
| + , m_minPageScaleFactor(0) |
| + , m_maxPageScaleFactor(0) |
| , m_backgroundColor(0) |
| , m_hasTransparentBackground(false) |
| , m_needsAnimateLayers(false) |
| @@ -196,7 +239,7 @@ |
| IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta()); |
| scrollTotal.scale(m_pageScaleDelta); |
| - float scaleTotal = m_pageScale * m_pageScaleDelta; |
| + float scaleTotal = m_pageScaleFactor * m_pageScaleDelta; |
| IntSize scaledContentSize = contentSize(); |
| scaledContentSize.scale(m_pageScaleDelta); |
| @@ -233,6 +276,13 @@ |
| } |
| } |
| +void CCLayerTreeHostImpl::updateRootScrollLayerImplTransform() |
| +{ |
| + if (m_rootScrollLayerImpl) { |
| + m_rootScrollLayerImpl->setImplTransform(implTransform()); |
| + } |
| +} |
| + |
| void CCLayerTreeHostImpl::calculateRenderSurfaceLayerList(CCLayerList& renderSurfaceLayerList) |
| { |
| ASSERT(renderSurfaceLayerList.isEmpty()); |
| @@ -240,6 +290,8 @@ |
| ASSERT(m_renderer); // For maxTextureSize. |
| { |
| + updateRootScrollLayerImplTransform(); |
| + |
| TRACE_EVENT0("cc", "CCLayerTreeHostImpl::calcDrawEtc"); |
| CCLayerTreeHostCommon::calculateDrawTransforms(m_rootLayerImpl.get(), deviceViewportSize(), m_deviceScaleFactor, &m_layerSorter, rendererCapabilities().maxTextureSize, renderSurfaceLayerList); |
| CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList); |
| @@ -767,6 +819,8 @@ |
| m_layoutViewportSize = layoutViewportSize; |
| m_deviceViewportSize = deviceViewportSize; |
| + m_pinchZoomViewport.setUnpinchedBounds(FloatSize(layoutViewportSize)); |
| + |
| updateMaxScrollPosition(); |
| if (m_renderer) |
| @@ -801,38 +855,38 @@ |
| } |
| -void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScale, float minPageScale, float maxPageScale) |
| +void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor) |
| { |
| - if (!pageScale) |
| + if (!pageScaleFactor) |
| return; |
| - if (m_sentPageScaleDelta == 1 && pageScale == m_pageScale && minPageScale == m_minPageScale && maxPageScale == m_maxPageScale) |
| + if (m_sentPageScaleDelta == 1 && pageScaleFactor == m_pageScaleFactor && minPageScaleFactor == m_minPageScaleFactor && maxPageScaleFactor == m_maxPageScaleFactor) |
| return; |
| - m_minPageScale = minPageScale; |
| - m_maxPageScale = maxPageScale; |
| + m_minPageScaleFactor = minPageScaleFactor; |
| + m_maxPageScaleFactor = maxPageScaleFactor; |
| - float pageScaleChange = pageScale / m_pageScale; |
| - m_pageScale = pageScale; |
| + float pageScaleChange = pageScaleFactor / m_pageScaleFactor; |
| + m_pageScaleFactor = pageScaleFactor; |
| - if (pageScaleChange != 1) |
| - adjustScrollsForPageScaleChange(m_rootScrollLayerImpl, pageScaleChange); |
| + if (!CCSettings::pageScalePinchZoomEnabled()) { |
| + if (pageScaleChange != 1) |
| + adjustScrollsForPageScaleChange(m_rootScrollLayerImpl, pageScaleChange); |
| + } |
| // Clamp delta to limits and refresh display matrix. |
| setPageScaleDelta(m_pageScaleDelta / m_sentPageScaleDelta); |
| m_sentPageScaleDelta = 1; |
| - if (m_rootScrollLayerImpl) |
| - m_rootScrollLayerImpl->setPageScaleDelta(m_pageScaleDelta); |
| } |
| void CCLayerTreeHostImpl::setPageScaleDelta(float delta) |
| { |
| // Clamp to the current min/max limits. |
| - float finalMagnifyScale = m_pageScale * delta; |
| - if (m_minPageScale && finalMagnifyScale < m_minPageScale) |
| - delta = m_minPageScale / m_pageScale; |
| - else if (m_maxPageScale && finalMagnifyScale > m_maxPageScale) |
| - delta = m_maxPageScale / m_pageScale; |
| + float finalMagnifyScale = m_pageScaleFactor * delta; |
| + if (m_minPageScaleFactor && finalMagnifyScale < m_minPageScaleFactor) |
| + delta = m_minPageScaleFactor / m_pageScaleFactor; |
| + else if (m_maxPageScaleFactor && finalMagnifyScale > m_maxPageScaleFactor) |
| + delta = m_maxPageScaleFactor / m_pageScaleFactor; |
| if (delta == m_pageScaleDelta) |
| return; |
| @@ -840,8 +894,6 @@ |
| m_pageScaleDelta = delta; |
| updateMaxScrollPosition(); |
| - if (m_rootScrollLayerImpl) |
| - m_rootScrollLayerImpl->setPageScaleDelta(m_pageScaleDelta); |
| } |
| void CCLayerTreeHostImpl::updateMaxScrollPosition() |
| @@ -857,11 +909,22 @@ |
| viewBounds.scale(m_deviceScaleFactor); |
| } |
| } |
| - viewBounds.scale(1 / m_pageScaleDelta); |
| - // maxScroll is computed in physical pixels, but scroll positions are in layout pixels. |
| - IntSize maxScroll = contentSize() - expandedIntSize(viewBounds); |
| + |
| + IntSize contentBounds = contentSize(); |
| + if (CCSettings::pageScalePinchZoomEnabled()) { |
| + // Pinch with pageScale scrolls entirely in layout space. contentSize |
| + // returns the bounds including the page scale factor, so calculate the |
| + // pre page-scale layout size here. |
| + contentBounds.setWidth(contentBounds.width() / m_pageScaleFactor); |
| + contentBounds.setHeight(contentBounds.height() / m_pageScaleFactor); |
| + } else { |
| + viewBounds.scale(1 / m_pageScaleDelta); |
| + } |
| + |
| + IntSize maxScroll = contentBounds - expandedIntSize(viewBounds); |
| maxScroll.scale(1 / m_deviceScaleFactor); |
| + |
| // The viewport may be larger than the contents in some cases, such as |
| // having a vertical scrollbar but no horizontal overflow. |
| maxScroll.clampNegativeToZero(); |
| @@ -944,7 +1007,7 @@ |
| return ScrollIgnored; |
| } |
| -static FloatSize scrollLayerWithScreenSpaceDelta(CCLayerImpl& layerImpl, const FloatPoint& screenSpacePoint, const FloatSize& screenSpaceDelta) |
| +static FloatSize scrollLayerWithScreenSpaceDelta(CCPinchZoomViewport* viewport, CCLayerImpl& layerImpl, const FloatPoint& screenSpacePoint, const FloatSize& screenSpaceDelta) |
| { |
| // Layers with non-invertible screen space transforms should not have passed the scroll hit |
| // test in the first place. |
| @@ -966,8 +1029,11 @@ |
| // Apply the scroll delta. |
| FloatSize previousDelta(layerImpl.scrollDelta()); |
| - layerImpl.scrollBy(localEndPoint - localStartPoint); |
| + FloatSize unscrolled = layerImpl.scrollBy(localEndPoint - localStartPoint); |
| + if (viewport) |
| + viewport->applyScroll(unscrolled); |
| + |
| // Calculate the applied scroll delta in screen space coordinates. |
| FloatPoint actualLocalEndPoint = localStartPoint + layerImpl.scrollDelta() - previousDelta; |
| FloatPoint actualScreenSpaceEndPoint = CCMathUtil::mapPoint(layerImpl.screenSpaceTransform(), actualLocalEndPoint, endClipped); |
| @@ -998,9 +1064,10 @@ |
| if (!layerImpl->scrollable()) |
| continue; |
| + CCPinchZoomViewport* viewport = layerImpl == m_rootScrollLayerImpl ? &m_pinchZoomViewport : 0; |
| FloatSize appliedDelta; |
| if (m_scrollDeltaIsInScreenSpace) |
| - appliedDelta = scrollLayerWithScreenSpaceDelta(*layerImpl, viewportPoint, pendingDelta); |
| + appliedDelta = scrollLayerWithScreenSpaceDelta(viewport, *layerImpl, viewportPoint, pendingDelta); |
| else |
| appliedDelta = scrollLayerWithLocalDelta(*layerImpl, pendingDelta); |
| @@ -1071,9 +1138,16 @@ |
| FloatSize move = previousScaleAnchor - newScaleAnchor; |
| m_previousPinchAnchor = anchor; |
| + m_pinchZoomViewport.setTotalPageScaleFactor(m_pageScaleFactor * m_pageScaleDelta); |
|
aelias_OOO_until_Jul13
2012/09/25 03:53:29
This needs to be updated whenever m_pageScaleFacto
|
| - m_rootScrollLayerImpl->scrollBy(roundedIntSize(move)); |
| + if (CCSettings::pageScalePinchZoomEnabled()) { |
| + // Compute the application of the delta with respect to the current page zoom of the page. |
| + move.scale(1 / (m_pageScaleFactor * m_deviceScaleFactor)); |
| + } |
| + FloatSize scrollOverflow = CCSettings::pageScalePinchZoomEnabled()? m_pinchZoomViewport.applyScroll(move) : move; |
| + m_rootScrollLayerImpl->scrollBy(roundedIntSize(scrollOverflow)); |
| + |
| if (m_rootScrollLayerImpl->scrollbarAnimationController()) |
| m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureUpdate(); |
| @@ -1095,7 +1169,7 @@ |
| { |
| float pageScale = m_pageScaleAnimation->finalPageScale(); |
| IntSize scrollOffset = m_pageScaleAnimation->finalScrollOffset(); |
| - scrollOffset.scale(m_pageScale / pageScale); |
| + scrollOffset.scale(m_pageScaleFactor / pageScale); |
| makeScrollAndScaleSet(scrollInfo, scrollOffset, pageScale); |
| } |
| @@ -1115,20 +1189,20 @@ |
| // out from the anchor point. |
| IntSize scrollBegin = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta()); |
| scrollBegin.scale(m_pageScaleDelta); |
| - float scaleBegin = m_pageScale * m_pageScaleDelta; |
| - float pageScaleDeltaToSend = m_minPageScale / m_pageScale; |
| + float scaleBegin = m_pageScaleFactor * m_pageScaleDelta; |
| + float pageScaleDeltaToSend = m_minPageScaleFactor / m_pageScaleFactor; |
| FloatSize scaledContentsSize = contentSize(); |
| scaledContentsSize.scale(pageScaleDeltaToSend); |
| FloatSize anchor = toSize(m_previousPinchAnchor); |
| FloatSize scrollEnd = scrollBegin + anchor; |
| - scrollEnd.scale(m_minPageScale / scaleBegin); |
| + scrollEnd.scale(m_minPageScaleFactor / scaleBegin); |
| scrollEnd -= anchor; |
| scrollEnd = scrollEnd.shrunkTo(roundedIntSize(scaledContentsSize - m_deviceViewportSize)).expandedTo(FloatSize(0, 0)); |
| scrollEnd.scale(1 / pageScaleDeltaToSend); |
| scrollEnd.scale(m_deviceScaleFactor); |
| - makeScrollAndScaleSet(scrollInfo, roundedIntSize(scrollEnd), m_minPageScale); |
| + makeScrollAndScaleSet(scrollInfo, roundedIntSize(scrollEnd), m_minPageScaleFactor); |
| } |
| void CCLayerTreeHostImpl::makeScrollAndScaleSet(CCScrollAndScaleSet* scrollInfo, const IntSize& scrollOffset, float pageScale) |
| @@ -1141,7 +1215,7 @@ |
| scroll.scrollDelta = scrollOffset - toSize(m_rootScrollLayerImpl->scrollPosition()); |
| scrollInfo->scrolls.append(scroll); |
| m_rootScrollLayerImpl->setSentScrollDelta(scroll.scrollDelta); |
| - m_sentPageScaleDelta = scrollInfo->pageScaleDelta = pageScale / m_pageScale; |
| + m_sentPageScaleDelta = scrollInfo->pageScaleDelta = pageScale / m_pageScaleFactor; |
| } |
| static void collectScrollDeltas(CCScrollAndScaleSet* scrollInfo, CCLayerImpl* layerImpl) |
| @@ -1168,10 +1242,14 @@ |
| if (m_pinchGestureActive || m_pageScaleAnimation) { |
| m_sentPageScaleDelta = scrollInfo->pageScaleDelta = 1; |
| - if (m_pinchGestureActive) |
| - computePinchZoomDeltas(scrollInfo.get()); |
| - else if (m_pageScaleAnimation.get()) |
| - computeDoubleTapZoomDeltas(scrollInfo.get()); |
| + // If pinch zoom is applied in the impl thread, then there is no need to |
| + // calculate these intermediate scale deltas. |
| + if (!CCSettings::pageScalePinchZoomEnabled()) { |
| + if (m_pinchGestureActive) |
| + computePinchZoomDeltas(scrollInfo.get()); |
| + else if (m_pageScaleAnimation.get()) |
| + computeDoubleTapZoomDeltas(scrollInfo.get()); |
| + } |
| return scrollInfo.release(); |
| } |
| @@ -1181,6 +1259,22 @@ |
| return scrollInfo.release(); |
| } |
| +WebTransformationMatrix CCLayerTreeHostImpl::implTransform() const |
| +{ |
| + WebTransformationMatrix transform; |
| + transform.scale(m_pageScaleDelta); |
| + |
| + // If the pinch state is applied in the impl, then push it to the |
| + // impl transform, otherwise the scale is handled by WebCore. |
| + if (CCSettings::pageScalePinchZoomEnabled()) { |
| + transform.scale(m_pageScaleFactor); |
| + transform.translate(-m_pinchZoomViewport.scrollDelta().x(), |
| + -m_pinchZoomViewport.scrollDelta().y()); |
| + } |
| + |
| + return transform; |
| +} |
| + |
| void CCLayerTreeHostImpl::setFullRootLayerDamage() |
| { |
| if (m_rootLayerImpl) { |
| @@ -1197,7 +1291,7 @@ |
| IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta()); |
| - setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_pageScale); |
| + setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_pageScaleFactor); |
| IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime); |
| nextScroll.scale(1 / m_pageScaleDelta); |
| m_rootScrollLayerImpl->scrollBy(nextScroll - scrollTotal); |