Chromium Code Reviews| Index: cc/CCLayerTreeHostImpl.cpp |
| =================================================================== |
| --- cc/CCLayerTreeHostImpl.cpp (revision 158825) |
| +++ cc/CCLayerTreeHostImpl.cpp (working copy) |
| @@ -49,6 +49,85 @@ |
| namespace cc { |
| +float CCPinchZoomViewport::totalPageScaleFactor() const |
| +{ |
| + return m_pageScaleFactor * m_pageScaleDelta; |
| +} |
| + |
| +void CCPinchZoomViewport::setPageScaleDelta(float delta) |
| +{ |
| + // Clamp to the current min/max limits. |
| + float finalMagnifyScale = m_pageScaleFactor * delta; |
|
aelias_OOO_until_Jul13
2012/09/26 23:15:09
Rename "finalMagnifyScale" to "totalPageScaleFacto
Jeff Timanus
2012/10/01 21:42:36
Done.
|
| + 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; |
| + |
| + m_pageScaleDelta = delta; |
| +} |
| + |
| +bool CCPinchZoomViewport::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor) |
| +{ |
| + if (!pageScaleFactor) |
|
aelias_OOO_until_Jul13
2012/09/26 23:15:09
Replace this with ASSERT(pageScaleFactor); since i
Jeff Timanus
2012/10/01 21:42:36
Done.
|
| + return false; |
| + |
| + if (m_sentPageScaleDelta == 1 && pageScaleFactor == m_pageScaleFactor && minPageScaleFactor == m_minPageScaleFactor && maxPageScaleFactor == m_maxPageScaleFactor) |
| + return false; |
| + |
| + m_minPageScaleFactor = minPageScaleFactor; |
| + m_maxPageScaleFactor = maxPageScaleFactor; |
| + |
| + m_pageScaleFactor = pageScaleFactor; |
| + return true; |
| +} |
| + |
| +FloatRect CCPinchZoomViewport::bounds() const |
| +{ |
| + FloatSize scaledBounds = m_unpinchedBounds; |
| + float totalScale = totalPageScaleFactor(); |
|
aelias_OOO_until_Jul13
2012/09/26 23:15:09
No need for this local variable.
Jeff Timanus
2012/10/01 21:42:36
Done.
|
| + if (totalScale > 1) |
|
aelias_OOO_until_Jul13
2012/09/26 23:15:09
Remove this if(). It's correct in the == 1 or < 1
aelias_OOO_until_Jul13
2012/09/26 23:19:04
Actually, maybe it's not. As I suggested in my co
|
| + scaledBounds.scale(1 / totalScale); |
| + |
| + FloatRect bounds; |
| + bounds.setSize(scaledBounds); |
|
aelias_OOO_until_Jul13
2012/09/26 23:15:09
Use the FloatRect constructor instead.
Jeff Timanus
2012/10/01 21:42:36
Done.
|
| + 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()); |
|
aelias_OOO_until_Jul13
2012/09/26 23:15:09
Looks like a bug here. Seems overflow values shou
Jeff Timanus
2012/10/01 21:42:36
Good catch. I'm surprised that this wasn't causin
Jeff Timanus
2012/10/01 21:42:36
Good catch. Fixed.
|
| + } |
| + |
| + 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: |
| @@ -116,11 +195,6 @@ |
| , m_visible(true) |
| , m_contentsTexturesPurged(false) |
| , m_memoryAllocationLimitBytes(CCPrioritizedTextureManager::defaultMemoryAllocationLimit()) |
| - , m_pageScale(1) |
| - , m_pageScaleDelta(1) |
| - , m_sentPageScaleDelta(1) |
| - , m_minPageScale(0) |
| - , m_maxPageScale(0) |
| , m_backgroundColor(0) |
| , m_hasTransparentBackground(false) |
| , m_needsAnimateLayers(false) |
| @@ -196,10 +270,10 @@ |
| return; |
| IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta()); |
| - scrollTotal.scale(m_pageScaleDelta); |
| - float scaleTotal = m_pageScale * m_pageScaleDelta; |
| + scrollTotal.scale(m_pinchZoomViewport.pageScaleDelta()); |
| + float scaleTotal = m_pinchZoomViewport.totalPageScaleFactor(); |
| IntSize scaledContentSize = contentSize(); |
| - scaledContentSize.scale(m_pageScaleDelta); |
| + scaledContentSize.scale(m_pinchZoomViewport.pageScaleDelta()); |
| m_pageScaleAnimation = CCPageScaleAnimation::create(scrollTotal, scaleTotal, m_deviceViewportSize, scaledContentSize, startTime); |
| @@ -234,6 +308,13 @@ |
| } |
| } |
| +void CCLayerTreeHostImpl::updateRootScrollLayerImplTransform() |
| +{ |
| + if (m_rootScrollLayerImpl) { |
| + m_rootScrollLayerImpl->setImplTransform(implTransform()); |
| + } |
| +} |
| + |
| void CCLayerTreeHostImpl::calculateRenderSurfaceLayerList(CCLayerList& renderSurfaceLayerList) |
| { |
| ASSERT(renderSurfaceLayerList.isEmpty()); |
| @@ -241,6 +322,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); |
| @@ -769,6 +852,8 @@ |
| m_layoutViewportSize = layoutViewportSize; |
| m_deviceViewportSize = deviceViewportSize; |
| + m_pinchZoomViewport.setUnpinchedBounds(FloatSize(layoutViewportSize)); |
| + |
| updateMaxScrollPosition(); |
| if (m_renderer) |
| @@ -802,48 +887,34 @@ |
| updateMaxScrollPosition(); |
| } |
| +float CCLayerTreeHostImpl::pageScaleFactor() const |
| +{ |
| + return m_pinchZoomViewport.pageScaleFactor(); |
| +} |
| -void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScale, float minPageScale, float maxPageScale) |
| +void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor) |
| { |
| - if (!pageScale) |
| - return; |
| + if (!pageScaleFactor) |
| + return; |
| - if (m_sentPageScaleDelta == 1 && pageScale == m_pageScale && minPageScale == m_minPageScale && maxPageScale == m_maxPageScale) |
| - return; |
| + float pageScaleChange = pageScaleFactor / m_pinchZoomViewport.pageScaleFactor(); |
| + m_pinchZoomViewport.setPageScaleFactorAndLimits(pageScaleFactor, minPageScaleFactor, maxPageScaleFactor); |
| - m_minPageScale = minPageScale; |
| - m_maxPageScale = maxPageScale; |
| + if (!CCSettings::pageScalePinchZoomEnabled()) { |
| + if (pageScaleChange != 1) |
| + adjustScrollsForPageScaleChange(m_rootScrollLayerImpl, pageScaleChange); |
| + } |
| - float pageScaleChange = pageScale / m_pageScale; |
| - m_pageScale = pageScale; |
| - |
| - 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); |
| + setPageScaleDelta(m_pinchZoomViewport.pageScaleDelta() / m_pinchZoomViewport.sentPageScaleDelta()); |
| + m_pinchZoomViewport.setSentPageScaleDelta(1); |
| } |
| 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; |
| + m_pinchZoomViewport.setPageScaleDelta(delta); |
| - if (delta == m_pageScaleDelta) |
| - return; |
| - |
| - m_pageScaleDelta = delta; |
| - |
| updateMaxScrollPosition(); |
| - if (m_rootScrollLayerImpl) |
| - m_rootScrollLayerImpl->setPageScaleDelta(m_pageScaleDelta); |
| } |
| void CCLayerTreeHostImpl::updateMaxScrollPosition() |
| @@ -859,11 +930,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. |
| + float pageScaleFactor = m_pinchZoomViewport.pageScaleFactor(); |
| + contentBounds.setWidth(contentBounds.width() / pageScaleFactor); |
| + contentBounds.setHeight(contentBounds.height() / pageScaleFactor); |
| + } else { |
| + viewBounds.scale(1 / m_pinchZoomViewport.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(); |
| @@ -946,7 +1028,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. |
| @@ -968,8 +1050,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); |
| @@ -1000,9 +1085,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); |
| @@ -1067,15 +1153,24 @@ |
| // Keep the center-of-pinch anchor specified by (x, y) in a stable |
| // position over the course of the magnify. |
| - FloatPoint previousScaleAnchor(m_previousPinchAnchor.x() / m_pageScaleDelta, m_previousPinchAnchor.y() / m_pageScaleDelta); |
| - setPageScaleDelta(m_pageScaleDelta * magnifyDelta); |
| - FloatPoint newScaleAnchor(anchor.x() / m_pageScaleDelta, anchor.y() / m_pageScaleDelta); |
| + float pageScaleDelta = m_pinchZoomViewport.pageScaleDelta(); |
| + FloatPoint previousScaleAnchor(m_previousPinchAnchor.x() / pageScaleDelta, |
| + m_previousPinchAnchor.y() / pageScaleDelta); |
| + setPageScaleDelta(pageScaleDelta * magnifyDelta); |
| + pageScaleDelta = m_pinchZoomViewport.pageScaleDelta(); |
| + FloatPoint newScaleAnchor(anchor.x() / pageScaleDelta, anchor.y() / pageScaleDelta); |
| FloatSize move = previousScaleAnchor - newScaleAnchor; |
| m_previousPinchAnchor = anchor; |
| - 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_pinchZoomViewport.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(); |
| @@ -1097,7 +1192,7 @@ |
| { |
| float pageScale = m_pageScaleAnimation->finalPageScale(); |
| IntSize scrollOffset = m_pageScaleAnimation->finalScrollOffset(); |
| - scrollOffset.scale(m_pageScale / pageScale); |
| + scrollOffset.scale(m_pinchZoomViewport.pageScaleFactor() / pageScale); |
| makeScrollAndScaleSet(scrollInfo, scrollOffset, pageScale); |
| } |
| @@ -1110,27 +1205,27 @@ |
| // significant amount. This also ensures only one fake delta set will be |
| // sent. |
| const float pinchZoomOutSensitivity = 0.95f; |
| - if (m_pageScaleDelta > pinchZoomOutSensitivity) |
| + if (m_pinchZoomViewport.pageScaleDelta() > pinchZoomOutSensitivity) |
| return; |
| // Compute where the scroll offset/page scale would be if fully pinch-zoomed |
| // 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; |
| + scrollBegin.scale(m_pinchZoomViewport.pageScaleDelta()); |
| + float scaleBegin = m_pinchZoomViewport.totalPageScaleFactor(); |
| + float pageScaleDeltaToSend = m_pinchZoomViewport.minPageScaleFactor() / m_pinchZoomViewport.pageScaleFactor(); |
| FloatSize scaledContentsSize = contentSize(); |
| scaledContentsSize.scale(pageScaleDeltaToSend); |
| FloatSize anchor = toSize(m_previousPinchAnchor); |
| FloatSize scrollEnd = scrollBegin + anchor; |
| - scrollEnd.scale(m_minPageScale / scaleBegin); |
| + scrollEnd.scale(m_pinchZoomViewport.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_pinchZoomViewport.minPageScaleFactor()); |
| } |
| void CCLayerTreeHostImpl::makeScrollAndScaleSet(CCScrollAndScaleSet* scrollInfo, const IntSize& scrollOffset, float pageScale) |
| @@ -1143,7 +1238,8 @@ |
| scroll.scrollDelta = scrollOffset - toSize(m_rootScrollLayerImpl->scrollPosition()); |
| scrollInfo->scrolls.append(scroll); |
| m_rootScrollLayerImpl->setSentScrollDelta(scroll.scrollDelta); |
| - m_sentPageScaleDelta = scrollInfo->pageScaleDelta = pageScale / m_pageScale; |
| + scrollInfo->pageScaleDelta = pageScale / m_pinchZoomViewport.pageScaleFactor(); |
| + m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta); |
| } |
| static void collectScrollDeltas(CCScrollAndScaleSet* scrollInfo, CCLayerImpl* layerImpl) |
| @@ -1169,20 +1265,42 @@ |
| OwnPtr<CCScrollAndScaleSet> scrollInfo = adoptPtr(new CCScrollAndScaleSet()); |
| if (m_pinchGestureActive || m_pageScaleAnimation) { |
| - m_sentPageScaleDelta = scrollInfo->pageScaleDelta = 1; |
| - if (m_pinchGestureActive) |
| - computePinchZoomDeltas(scrollInfo.get()); |
| - else if (m_pageScaleAnimation.get()) |
| - computeDoubleTapZoomDeltas(scrollInfo.get()); |
| + scrollInfo->pageScaleDelta = 1; |
| + m_pinchZoomViewport.setSentPageScaleDelta(1); |
| + // If pinch zoom is applied in the impl thread, then there is no need to |
|
aelias_OOO_until_Jul13
2012/09/26 23:15:09
There is still a need for this in some form. It's
Jeff Timanus
2012/10/01 21:42:36
Done.
|
| + // 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(); |
| } |
| collectScrollDeltas(scrollInfo.get(), m_rootLayerImpl.get()); |
| - m_sentPageScaleDelta = scrollInfo->pageScaleDelta = m_pageScaleDelta; |
| + scrollInfo->pageScaleDelta = m_pinchZoomViewport.pageScaleDelta(); |
| + m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta); |
| return scrollInfo.release(); |
| } |
| +WebTransformationMatrix CCLayerTreeHostImpl::implTransform() const |
|
aelias_OOO_until_Jul13
2012/09/26 23:15:09
Move this method into CCPinchZoomViewport.
Jeff Timanus
2012/10/01 21:42:36
Done.
|
| +{ |
| + WebTransformationMatrix transform; |
| + transform.scale(m_pinchZoomViewport.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_pinchZoomViewport.pageScaleFactor()); |
| + transform.translate(-m_pinchZoomViewport.scrollDelta().x(), |
| + -m_pinchZoomViewport.scrollDelta().y()); |
| + } |
| + |
| + return transform; |
| +} |
| + |
| void CCLayerTreeHostImpl::setFullRootLayerDamage() |
| { |
| if (m_rootLayerImpl) { |
| @@ -1199,9 +1317,9 @@ |
| IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta()); |
| - setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_pageScale); |
| + setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_pinchZoomViewport.pageScaleFactor()); |
| IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime); |
| - nextScroll.scale(1 / m_pageScaleDelta); |
| + nextScroll.scale(1 / m_pinchZoomViewport.pageScaleDelta()); |
| m_rootScrollLayerImpl->scrollBy(nextScroll - scrollTotal); |
| m_client->setNeedsRedrawOnImplThread(); |