diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 944cb3ee635f..0350fb570be5 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -346,15 +346,19 @@ TabChild::Observe(nsISupports *aSubject, // Calculate a really simple resolution that we probably won't // be keeping, as well as putting the scroll offset back to // the top-left of the page. - mLastMetrics.mZoom = gfxSize(1.0, 1.0); + mLastMetrics.mZoom = ScreenToScreenScale(1.0); mLastMetrics.mViewport = CSSRect(CSSPoint(), kDefaultViewportSize); mLastMetrics.mCompositionBounds = ScreenIntRect(ScreenIntPoint(), mInnerSize); CSSToScreenScale resolution = AsyncPanZoomController::CalculateResolution(mLastMetrics); - mLastMetrics.mResolution = gfxSize(resolution.scale, resolution.scale); + // We use ScreenToLayerScale(1) below in order to ask gecko to render + // what's currently visible on the screen. This is effectively turning + // the async zoom amount into the gecko zoom amount. + mLastMetrics.mResolution = + resolution / mLastMetrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1); mLastMetrics.mScrollOffset = CSSPoint(0, 0); - utils->SetResolution(mLastMetrics.mResolution.width, - mLastMetrics.mResolution.height); + utils->SetResolution(mLastMetrics.mResolution.scale, + mLastMetrics.mResolution.scale); HandlePossibleViewportChange(); } @@ -597,13 +601,13 @@ TabChild::HandlePossibleViewportChange() nsresult rv = utils->GetIsFirstPaint(&isFirstPaint); MOZ_ASSERT(NS_SUCCEEDED(rv)); if (NS_FAILED(rv) || isFirstPaint) { - gfxSize intrinsicScale = + CSSToScreenScale intrinsicScale = AsyncPanZoomController::CalculateIntrinsicScale(metrics); // FIXME/bug 799585(?): GetViewportInfo() returns a defaultZoom of // 0.0 to mean "did not calculate a zoom". In that case, we default // it to the intrinsic scale. if (viewportInfo.GetDefaultZoom() < 0.01f) { - viewportInfo.SetDefaultZoom(intrinsicScale.width); + viewportInfo.SetDefaultZoom(intrinsicScale.scale); } double defaultZoom = viewportInfo.GetDefaultZoom(); @@ -611,8 +615,7 @@ TabChild::HandlePossibleViewportChange() defaultZoom <= viewportInfo.GetMaxZoom()); // GetViewportInfo() returns a resolution-dependent scale factor. // Convert that to a resolution-indepedent zoom. - metrics.mZoom = gfxSize(defaultZoom / intrinsicScale.width, - defaultZoom / intrinsicScale.height); + metrics.mZoom = ScreenToScreenScale(defaultZoom / intrinsicScale.scale); } metrics.mDisplayPort = AsyncPanZoomController::CalculatePendingDisplayPort( @@ -621,9 +624,8 @@ TabChild::HandlePossibleViewportChange() // we have no idea how long painting will take. metrics, gfx::Point(0.0f, 0.0f), gfx::Point(0.0f, 0.0f), 0.0); CSSToScreenScale resolution = AsyncPanZoomController::CalculateResolution(metrics); - metrics.mResolution = gfxSize(resolution.scale / metrics.mDevPixelsPerCSSPixel, - resolution.scale / metrics.mDevPixelsPerCSSPixel); - utils->SetResolution(metrics.mResolution.width, metrics.mResolution.height); + metrics.mResolution = resolution / metrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1); + utils->SetResolution(metrics.mResolution.scale, metrics.mResolution.scale); // Force a repaint with these metrics. This, among other things, sets the // displayport, so we start with async painting. diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index 22f9d9ffe5f5..937de42e667d 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -290,7 +290,7 @@ public: void GetDPI(float* aDPI); void GetDefaultScale(double *aScale); - gfxSize GetZoom() { return mLastMetrics.mZoom; } + ScreenToScreenScale GetZoom() { return mLastMetrics.mZoom; } ScreenOrientation GetOrientation() { return mOrientation; } diff --git a/gfx/2d/ScaleFactor.h b/gfx/2d/ScaleFactor.h index ceef86f51d05..d7eec8275dd0 100644 --- a/gfx/2d/ScaleFactor.h +++ b/gfx/2d/ScaleFactor.h @@ -55,10 +55,20 @@ struct ScaleFactor { return ScaleFactor(scale / aOther.scale); } + template + ScaleFactor operator/(const ScaleFactor& aOther) const { + return ScaleFactor(scale / aOther.scale); + } + template ScaleFactor operator*(const ScaleFactor& aOther) const { return ScaleFactor(scale * aOther.scale); } + + template + ScaleFactor operator*(const ScaleFactor& aOther) const { + return ScaleFactor(scale * aOther.scale); + } }; } diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h index 24b9e5e6b71c..2d392f27a3af 100644 --- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -38,8 +38,8 @@ public: , mScrollOffset(0, 0) , mScrollId(NULL_SCROLL_ID) , mScrollableRect(0, 0, 0, 0) - , mResolution(1, 1) - , mZoom(1, 1) + , mResolution(1) + , mZoom(1) , mDevPixelsPerCSSPixel(1) , mMayHaveTouchListeners(false) , mPresShellId(-1) @@ -84,18 +84,14 @@ public: return mScrollId != NULL_SCROLL_ID; } - gfxSize LayersPixelsPerCSSPixel() const + CSSToLayerScale LayersPixelsPerCSSPixel() const { return mResolution * mDevPixelsPerCSSPixel; } - gfx::Point GetScrollOffsetInLayerPixels() const + LayerPoint GetScrollOffsetInLayerPixels() const { - return gfx::Point( - static_cast( - mScrollOffset.x * LayersPixelsPerCSSPixel().width), - static_cast( - mScrollOffset.y * LayersPixelsPerCSSPixel().height)); + return mScrollOffset * LayersPixelsPerCSSPixel(); } // --------------------------------------------------------------------------- @@ -172,8 +168,8 @@ public: // // It is required that the rect: // { x = mScrollOffset.x, y = mScrollOffset.y, - // width = mCompositionBounds.x / mResolution.width, - // height = mCompositionBounds.y / mResolution.height } + // width = mCompositionBounds.x / mResolution.scale, + // height = mCompositionBounds.y / mResolution.scale } // Be within |mScrollableRect|. // // This is valid for any layer, but is always relative to this frame and @@ -209,7 +205,7 @@ public: // post-multiplied into the parent's transform. Since this only happens when // we walk the layer tree, the resulting transform isn't stored here. Thus the // resolution of parent layers is opaque to this metric. - gfxSize mResolution; + LayoutDeviceToLayerScale mResolution; // The resolution-independent "user zoom". For example, if a page // configures the viewport to a zoom value of 2x, then this member @@ -224,13 +220,13 @@ public: // // When this is not true, we're probably asynchronously sampling a // zoom animation for content. - gfxSize mZoom; + ScreenToScreenScale mZoom; // The conversion factor between CSS pixels and device pixels for this frame. // This can vary based on a variety of things, such as reflowing-zoom. The // conversion factor for device pixels to layers pixels is just the // resolution. - float mDevPixelsPerCSSPixel; + CSSToLayoutDeviceScale mDevPixelsPerCSSPixel; // Whether or not this frame may have touch listeners. bool mMayHaveTouchListeners; diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp index c3fa7b91f1b7..90a55496e044 100644 --- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -408,8 +408,8 @@ ClientLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, // This is derived from the code in // gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree. const gfx3DMatrix& rootTransform = GetRoot()->GetTransform(); - CSSToLayerScale paintScale(metrics.mDevPixelsPerCSSPixel / rootTransform.GetXScale(), - metrics.mDevPixelsPerCSSPixel / rootTransform.GetYScale()); + CSSToLayerScale paintScale = metrics.mDevPixelsPerCSSPixel + / LayerToLayoutDeviceScale(rootTransform.GetXScale(), rootTransform.GetYScale()); const CSSRect& metricsDisplayPort = (aDrawingCritical && !metrics.mCriticalDisplayPort.IsEmpty()) ? metrics.mCriticalDisplayPort : metrics.mDisplayPort; diff --git a/gfx/layers/client/ClientTiledThebesLayer.cpp b/gfx/layers/client/ClientTiledThebesLayer.cpp index ec8a2346f8b7..fdfa3946f11a 100644 --- a/gfx/layers/client/ClientTiledThebesLayer.cpp +++ b/gfx/layers/client/ClientTiledThebesLayer.cpp @@ -75,8 +75,8 @@ ClientTiledThebesLayer::BeginPaint() mPaintData.mResolution.SizeTo(1, 1); for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) { const FrameMetrics& metrics = parent->GetFrameMetrics(); - mPaintData.mResolution.width *= metrics.mResolution.width; - mPaintData.mResolution.height *= metrics.mResolution.height; + mPaintData.mResolution.width *= metrics.mResolution.scale; + mPaintData.mResolution.height *= metrics.mResolution.scale; } // Calculate the scroll offset since the last transaction, and the diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index e66d54206eb8..310e4fdcdd94 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -351,7 +351,8 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFram const gfx3DMatrix& rootTransform = mLayerManager->GetRoot()->GetTransform(); const FrameMetrics& metrics = container->GetFrameMetrics(); - float paintScale = metrics.mDevPixelsPerCSSPixel / rootTransform.GetXScale(); + CSSToLayerScale paintScale = metrics.mDevPixelsPerCSSPixel + / LayerToLayoutDeviceScale(rootTransform.GetXScale(), rootTransform.GetYScale()); CSSRect displayPort(metrics.mCriticalDisplayPort.IsEmpty() ? metrics.mDisplayPort : metrics.mCriticalDisplayPort); gfx::Margin fixedLayerMargins(0, 0, 0, 0); @@ -405,15 +406,15 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer, const gfx3DMatr gfx3DMatrix treeTransform; - CSSToLayerScale geckoZoom(metrics.mDevPixelsPerCSSPixel / aRootTransform.GetXScale(), - metrics.mDevPixelsPerCSSPixel / aRootTransform.GetYScale()); + CSSToLayerScale geckoZoom = metrics.mDevPixelsPerCSSPixel / + LayerToLayoutDeviceScale(aRootTransform.GetXScale(), aRootTransform.GetYScale()); LayerIntPoint scrollOffsetLayerPixels = RoundedToInt(metrics.mScrollOffset * geckoZoom); if (mIsFirstPaint) { mContentRect = metrics.mScrollableRect; SetFirstPaintViewport(scrollOffsetLayerPixels, - geckoZoom.scale, + geckoZoom, mContentRect); mIsFirstPaint = false; } else if (!metrics.mScrollableRect.IsEqualEdges(mContentRect)) { @@ -435,8 +436,8 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer, const gfx3DMatr ScreenPoint offset(0, 0); ScreenPoint userScroll(0, 0); CSSToScreenScale userZoom; - SyncViewportInfo(displayPort, geckoZoom.scale, mLayersUpdated, - userScroll, userZoom.scale, userZoom.scale, fixedLayerMargins, + SyncViewportInfo(displayPort, geckoZoom, mLayersUpdated, + userScroll, userZoom, fixedLayerMargins, offset); mLayersUpdated = false; @@ -544,7 +545,7 @@ AsyncCompositionManager::TransformShadowTree(TimeStamp aCurrentFrame) void AsyncCompositionManager::SetFirstPaintViewport(const LayerIntPoint& aOffset, - float aZoom, + const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect) { #ifdef MOZ_WIDGET_ANDROID @@ -562,10 +563,10 @@ AsyncCompositionManager::SetPageRect(const CSSRect& aCssPageRect) void AsyncCompositionManager::SyncViewportInfo(const LayerIntRect& aDisplayPort, - float aDisplayResolution, + const CSSToLayerScale& aDisplayResolution, bool aLayersUpdated, ScreenPoint& aScrollOffset, - float& aScaleX, float& aScaleY, + CSSToScreenScale& aScale, gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset) { @@ -574,7 +575,7 @@ AsyncCompositionManager::SyncViewportInfo(const LayerIntRect& aDisplayPort, aDisplayResolution, aLayersUpdated, aScrollOffset, - aScaleX, aScaleY, + aScale, aFixedLayerMargins, aOffset); #endif @@ -586,7 +587,7 @@ AsyncCompositionManager::SyncFrameMetrics(const ScreenPoint& aScrollOffset, const CSSRect& aCssPageRect, bool aLayersUpdated, const CSSRect& aDisplayPort, - float aDisplayResolution, + const CSSToLayerScale& aDisplayResolution, bool aIsFirstPaint, gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset) diff --git a/gfx/layers/composite/AsyncCompositionManager.h b/gfx/layers/composite/AsyncCompositionManager.h index 99ec81989a4f..830484fec551 100644 --- a/gfx/layers/composite/AsyncCompositionManager.h +++ b/gfx/layers/composite/AsyncCompositionManager.h @@ -115,14 +115,14 @@ private: bool* aWantNextFrame); void SetFirstPaintViewport(const LayerIntPoint& aOffset, - float aZoom, + const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect); void SetPageRect(const CSSRect& aCssPageRect); void SyncViewportInfo(const LayerIntRect& aDisplayPort, - float aDisplayResolution, + const CSSToLayerScale& aDisplayResolution, bool aLayersUpdated, ScreenPoint& aScrollOffset, - float& aScaleX, float& aScaleY, + CSSToScreenScale& aScale, gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset); void SyncFrameMetrics(const ScreenPoint& aScrollOffset, @@ -130,7 +130,7 @@ private: const CSSRect& aCssPageRect, bool aLayersUpdated, const CSSRect& aDisplayPort, - float aDisplayResolution, + const CSSToLayerScale& aDisplayResolution, bool aIsFirstPaint, gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset); diff --git a/gfx/layers/composite/ThebesLayerComposite.cpp b/gfx/layers/composite/ThebesLayerComposite.cpp index f91861933b66..8f1f09b85fb8 100644 --- a/gfx/layers/composite/ThebesLayerComposite.cpp +++ b/gfx/layers/composite/ThebesLayerComposite.cpp @@ -165,8 +165,8 @@ ThebesLayerComposite::GetEffectiveResolution() gfxSize resolution(1, 1); for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) { const FrameMetrics& metrics = parent->GetFrameMetrics(); - resolution.width *= metrics.mResolution.width; - resolution.height *= metrics.mResolution.height; + resolution.width *= metrics.mResolution.scale; + resolution.height *= metrics.mResolution.scale; } return resolution; @@ -199,8 +199,8 @@ ThebesLayerComposite::GetDisplayPort() metrics.mDisplayPort.height); displayPort.ScaleRoundOut(parentResolution.width, parentResolution.height); } - parentResolution.width /= metrics.mResolution.width; - parentResolution.height /= metrics.mResolution.height; + parentResolution.width /= metrics.mResolution.scale; + parentResolution.height /= metrics.mResolution.scale; } if (parent->UseIntermediateSurface()) { transform.PreMultiply(parent->GetTransform()); @@ -252,9 +252,10 @@ ThebesLayerComposite::GetCompositionBounds() // Get the content document bounds, in screen-space. const FrameMetrics& metrics = scrollableLayer->GetFrameMetrics(); const LayerIntRect content = RoundedToInt(metrics.mScrollableRect / scale); + // !!! WTF. this code is just wrong. See bug 881451. gfx::Point scrollOffset = - gfx::Point((metrics.mScrollOffset.x * metrics.LayersPixelsPerCSSPixel().width) / scale.scale, - (metrics.mScrollOffset.y * metrics.LayersPixelsPerCSSPixel().height) / scale.scale); + gfx::Point((metrics.mScrollOffset.x * metrics.LayersPixelsPerCSSPixel().scale) / scale.scale, + (metrics.mScrollOffset.y * metrics.LayersPixelsPerCSSPixel().scale) / scale.scale); const nsIntPoint contentOrigin( content.x - NS_lround(scrollOffset.x), content.y - NS_lround(scrollOffset.y)); diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 7289e04fe6f1..d362cbcb6207 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -391,7 +391,7 @@ nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent { MonitorAutoLock monitor(mMonitor); // Bring the resolution back in sync with the zoom. - SetZoomAndResolution(mFrameMetrics.mZoom.width); + SetZoomAndResolution(mFrameMetrics.mZoom); RequestContentRepaint(); ScheduleComposite(); } @@ -545,7 +545,7 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) { MonitorAutoLock monitor(mMonitor); CSSToScreenScale resolution = CalculateResolution(mFrameMetrics); - gfxFloat userZoom = mFrameMetrics.mZoom.width; + gfxFloat userZoom = mFrameMetrics.mZoom.scale; ScreenPoint focusPoint = aEvent.mFocusPoint; CSSPoint focusChange = (mLastZoomFocus - focusPoint) / resolution; @@ -564,8 +564,8 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) { // either axis such that we don't overscroll the boundaries when zooming. gfx::Point neededDisplacement; - float maxZoom = mMaxZoom / CalculateIntrinsicScale(mFrameMetrics).width; - float minZoom = mMinZoom / CalculateIntrinsicScale(mFrameMetrics).width; + float maxZoom = mMaxZoom / CalculateIntrinsicScale(mFrameMetrics).scale; + float minZoom = mMinZoom / CalculateIntrinsicScale(mFrameMetrics).scale; bool doScale = (spanRatio > 1.0 && userZoom < maxZoom) || (spanRatio < 1.0 && userZoom > minZoom); @@ -785,7 +785,7 @@ bool AsyncPanZoomController::DoFling(const TimeDuration& aDelta) { if (!shouldContinueFlingX && !shouldContinueFlingY) { // Bring the resolution back in sync with the zoom, in case we scaled down // the zoom while accelerating. - SetZoomAndResolution(mFrameMetrics.mZoom.width); + SetZoomAndResolution(mFrameMetrics.mZoom); SendAsyncScrollEvent(); RequestContentRepaint(); mState = NOTHING; @@ -825,10 +825,10 @@ void AsyncPanZoomController::ScrollBy(const CSSPoint& aOffset) { void AsyncPanZoomController::ScaleWithFocus(float aZoom, const ScreenPoint& aFocus) { - float zoomFactor = aZoom / mFrameMetrics.mZoom.width; + float zoomFactor = aZoom / mFrameMetrics.mZoom.scale; CSSToScreenScale resolution = CalculateResolution(mFrameMetrics); - SetZoomAndResolution(aZoom); + SetZoomAndResolution(ScreenToScreenScale(aZoom)); // If the new scale is very small, we risk multiplying in huge rounding // errors, so don't bother adjusting the scroll offset. @@ -958,21 +958,17 @@ const CSSRect AsyncPanZoomController::CalculatePendingDisplayPort( return scrollableRect.ClampRect(shiftedDisplayPort) - scrollOffset; } -/*static*/ gfxSize +/*static*/ CSSToScreenScale AsyncPanZoomController::CalculateIntrinsicScale(const FrameMetrics& aMetrics) { - gfxFloat intrinsicScale = (gfxFloat(aMetrics.mCompositionBounds.width) / - gfxFloat(aMetrics.mViewport.width)); - return gfxSize(intrinsicScale, intrinsicScale); + return CSSToScreenScale(gfxFloat(aMetrics.mCompositionBounds.width) / + gfxFloat(aMetrics.mViewport.width)); } /*static*/ CSSToScreenScale AsyncPanZoomController::CalculateResolution(const FrameMetrics& aMetrics) { - gfxSize intrinsicScale = CalculateIntrinsicScale(aMetrics); - gfxSize userZoom = aMetrics.mZoom; - return CSSToScreenScale(intrinsicScale.width * userZoom.width, - intrinsicScale.height * userZoom.height); + return CalculateIntrinsicScale(aMetrics) * aMetrics.mZoom; } /*static*/ CSSRect @@ -1031,7 +1027,7 @@ void AsyncPanZoomController::RequestContentRepaint() { mFrameMetrics.mScrollOffset.x) < EPSILON && fabsf(mLastPaintRequestMetrics.mScrollOffset.y - mFrameMetrics.mScrollOffset.y) < EPSILON && - mFrameMetrics.mResolution.width == mLastPaintRequestMetrics.mResolution.width) { + mFrameMetrics.mResolution == mLastPaintRequestMetrics.mResolution) { return; } @@ -1039,14 +1035,13 @@ void AsyncPanZoomController::RequestContentRepaint() { // Cache the zoom since we're temporarily changing it for // acceleration-scaled painting. - gfxFloat actualZoom = mFrameMetrics.mZoom.width; + ScreenToScreenScale actualZoom = mFrameMetrics.mZoom; // Calculate the factor of acceleration based on the faster of the two axes. float accelerationFactor = clamped(std::max(mX.GetAccelerationFactor(), mY.GetAccelerationFactor()), MIN_ZOOM / 2.0f, MAX_ZOOM); // Scale down the resolution a bit based on acceleration. - mFrameMetrics.mZoom.width = mFrameMetrics.mZoom.height = - actualZoom / accelerationFactor; + mFrameMetrics.mZoom.scale /= accelerationFactor; // This message is compressed, so fire whether or not we already have a paint // queued up. We need to know whether or not a paint was requested anyways, @@ -1061,7 +1056,7 @@ void AsyncPanZoomController::RequestContentRepaint() { mWaitingForContentToPaint = true; // Set the zoom back to what it was for the purpose of logic control. - mFrameMetrics.mZoom = gfxSize(actualZoom, actualZoom); + mFrameMetrics.mZoom = actualZoom; } void @@ -1107,11 +1102,10 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa // will affect the final computed resolution. double sampledPosition = gComputedTimingFunction->GetValue(animPosition); - gfxFloat startZoom = mStartZoomToMetrics.mZoom.width; - gfxFloat endZoom = mEndZoomToMetrics.mZoom.width; - gfxFloat sampledZoom = (endZoom * sampledPosition + - startZoom * (1 - sampledPosition)); - mFrameMetrics.mZoom = gfxSize(sampledZoom, sampledZoom); + ScreenToScreenScale startZoom = mStartZoomToMetrics.mZoom; + ScreenToScreenScale endZoom = mEndZoomToMetrics.mZoom; + mFrameMetrics.mZoom = ScreenToScreenScale(endZoom.scale * sampledPosition + + startZoom.scale * (1 - sampledPosition)); mFrameMetrics.mScrollOffset = CSSPoint::FromUnknownPoint(gfx::Point( mEndZoomToMetrics.mScrollOffset.x * sampledPosition + @@ -1124,7 +1118,7 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa if (aSampleTime - mAnimationStartTime >= ZOOM_TO_DURATION) { // Bring the resolution in sync with the zoom. - SetZoomAndResolution(mFrameMetrics.mZoom.width); + SetZoomAndResolution(mFrameMetrics.mZoom); mState = NOTHING; SendAsyncScrollEvent(); RequestContentRepaint(); @@ -1143,8 +1137,7 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa localScale = CalculateResolution(mFrameMetrics); if (frame.IsScrollable()) { - metricsScrollOffset = LayerPoint::FromUnknownPoint( - frame.GetScrollOffsetInLayerPixels()); + metricsScrollOffset = frame.GetScrollOffsetInLayerPixels(); } scrollOffset = mFrameMetrics.mScrollOffset; @@ -1180,10 +1173,10 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa // Scales on the root layer, on what's currently painted. const gfx3DMatrix& currentTransform = aLayer->GetTransform(); - LayerToCSSScale rootScale(currentTransform.GetXScale() / frame.mDevPixelsPerCSSPixel, - currentTransform.GetYScale() / frame.mDevPixelsPerCSSPixel); + CSSToLayerScale rootScale = frame.mDevPixelsPerCSSPixel + / LayerToLayoutDeviceScale(currentTransform.GetXScale(), currentTransform.GetYScale()); - LayerPoint translation = (scrollOffset / rootScale) - metricsScrollOffset; + LayerPoint translation = (scrollOffset * rootScale) - metricsScrollOffset; *aNewTransform = ViewTransform(-translation, localScale); aScrollOffset = scrollOffset * localScale; @@ -1274,7 +1267,7 @@ void AsyncPanZoomController::UpdateCompositionBounds(const ScreenIntRect& aCompo // has gone out of view, the buffer will be cleared elsewhere anyways. if (aCompositionBounds.width && aCompositionBounds.height && oldCompositionBounds.width && oldCompositionBounds.height) { - SetZoomAndResolution(mFrameMetrics.mZoom.width); + SetZoomAndResolution(mFrameMetrics.mZoom); // Repaint on a rotation so that our new resolution gets properly updated. RequestContentRepaint(); @@ -1303,9 +1296,9 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) { ScreenIntRect compositionBounds = mFrameMetrics.mCompositionBounds; CSSRect cssPageRect = mFrameMetrics.mScrollableRect; CSSPoint scrollOffset = mFrameMetrics.mScrollOffset; - gfxSize currentZoom = mFrameMetrics.mZoom; + float currentZoom = mFrameMetrics.mZoom.scale; float targetZoom; - float intrinsicScale = CalculateIntrinsicScale(mFrameMetrics).width; + float intrinsicScale = CalculateIntrinsicScale(mFrameMetrics).scale; // The minimum zoom to prevent over-zoom-out. // If the zoom factor is lower than this (i.e. we are zoomed more into the page), @@ -1331,8 +1324,8 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) { // 3. currentZoom is equal to localMinZoom and user still double-tapping it // Treat these three cases as a request to zoom out as much as possible. if (zoomToRect.IsEmpty() || - (currentZoom.width == localMaxZoom && targetZoom >= localMaxZoom) || - (currentZoom.width == localMinZoom && targetZoom <= localMinZoom)) { + (currentZoom == localMaxZoom && targetZoom >= localMaxZoom) || + (currentZoom == localMinZoom && targetZoom <= localMinZoom)) { CSSRect compositedRect = CalculateCompositedRectInCssPixels(mFrameMetrics); float y = scrollOffset.y; float newHeight = @@ -1351,7 +1344,7 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) { } targetZoom = clamped(targetZoom, localMinZoom, localMaxZoom); - mEndZoomToMetrics.mZoom = gfxSize(targetZoom, targetZoom); + mEndZoomToMetrics.mZoom = ScreenToScreenScale(targetZoom); // Adjust the zoomToRect to a sensible position to prevent overscrolling. FrameMetrics metricsAfterZoom = mFrameMetrics; @@ -1434,12 +1427,14 @@ void AsyncPanZoomController::TimeoutTouchListeners() { ContentReceivedTouch(false); } -void AsyncPanZoomController::SetZoomAndResolution(float aZoom) { +void AsyncPanZoomController::SetZoomAndResolution(const ScreenToScreenScale& aZoom) { mMonitor.AssertCurrentThreadOwns(); - mFrameMetrics.mZoom = gfxSize(aZoom, aZoom); + mFrameMetrics.mZoom = aZoom; CSSToScreenScale resolution = CalculateResolution(mFrameMetrics); - mFrameMetrics.mResolution = gfxSize(resolution.scale / mFrameMetrics.mDevPixelsPerCSSPixel, - resolution.scale / mFrameMetrics.mDevPixelsPerCSSPixel); + // We use ScreenToLayerScale(1) below in order to ask gecko to render + // what's currently visible on the screen. This is effectively turning + // the async zoom amount into the gecko zoom amount. + mFrameMetrics.mResolution = resolution / mFrameMetrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1); } void AsyncPanZoomController::UpdateZoomConstraints(bool aAllowZoom, diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index 246a7037d0e6..9f52f7a62365 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -227,7 +227,7 @@ public: * Return the scale factor needed to fit the viewport in |aMetrics| * into its composition bounds. */ - static gfxSize CalculateIntrinsicScale(const FrameMetrics& aMetrics); + static CSSToScreenScale CalculateIntrinsicScale(const FrameMetrics& aMetrics); /** * Return the resolution that content should be rendered at given @@ -456,7 +456,7 @@ protected: * * *** The monitor must be held while calling this. */ - void SetZoomAndResolution(float aScale); + void SetZoomAndResolution(const ScreenToScreenScale& aZoom); /** * Timeout function for mozbrowserasyncscroll event. Because we throttle diff --git a/gfx/layers/ipc/Axis.cpp b/gfx/layers/ipc/Axis.cpp index 4e8686e8ef27..0e77215b3129 100644 --- a/gfx/layers/ipc/Axis.cpp +++ b/gfx/layers/ipc/Axis.cpp @@ -318,7 +318,7 @@ bool Axis::ScaleWillOverscrollBothSides(float aScale) { CSSRect cssContentRect = metrics.mScrollableRect; - CSSToScreenScale scale(metrics.mZoom.width * aScale); + CSSToScreenScale scale(metrics.mZoom.scale * aScale); CSSIntRect cssCompositionBounds = RoundedIn(metrics.mCompositionBounds / scale); return GetRectLength(cssContentRect) < GetRectLength(CSSRect(cssCompositionBounds)); diff --git a/ipc/glue/IPCMessageUtils.h b/ipc/glue/IPCMessageUtils.h index d11c689a6597..cf274a7c9ea3 100644 --- a/ipc/glue/IPCMessageUtils.h +++ b/ipc/glue/IPCMessageUtils.h @@ -788,6 +788,22 @@ struct ParamTraits } }; +template +struct ParamTraits< mozilla::gfx::ScaleFactor > +{ + typedef mozilla::gfx::ScaleFactor paramType; + + static void Write(Message* msg, const paramType& param) + { + WriteParam(msg, param.scale); + } + + static bool Read(const Message* msg, void** iter, paramType* result) + { + return (ReadParam(msg, iter, &result->scale)); + } +}; + template struct ParamTraits< mozilla::gfx::PointTyped > { diff --git a/layout/base/Units.h b/layout/base/Units.h index aba11128d62c..a1484a470853 100644 --- a/layout/base/Units.h +++ b/layout/base/Units.h @@ -57,6 +57,7 @@ typedef gfx::ScaleFactor LayoutDeviceToLayerScale typedef gfx::ScaleFactor LayerToLayoutDeviceScale; typedef gfx::ScaleFactor LayerToScreenScale; typedef gfx::ScaleFactor ScreenToLayerScale; +typedef gfx::ScaleFactor ScreenToScreenScale; /* * The pixels that content authors use to specify sizes in. diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index ce0f550d35f2..84944dafed41 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -631,9 +631,10 @@ static void RecordFrameMetrics(nsIFrame* aForFrame, bool aMayHaveTouchListeners) { nsPresContext* presContext = aForFrame->PresContext(); int32_t auPerDevPixel = presContext->AppUnitsPerDevPixel(); + LayoutDeviceToLayerScale resolution(aContainerParameters.mXScale, aContainerParameters.mYScale); nsIntRect visible = aVisibleRect.ScaleToNearestPixels( - aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel); + resolution.scale, resolution.scale, auPerDevPixel); aRoot->SetVisibleRegion(nsIntRegion(visible)); FrameMetrics metrics; @@ -668,10 +669,10 @@ static void RecordFrameMetrics(nsIFrame* aForFrame, if (TabChild *tc = GetTabChildFrom(presShell)) { metrics.mZoom = tc->GetZoom(); } - metrics.mResolution = gfxSize(presShell->GetXResolution(), presShell->GetYResolution()); + metrics.mResolution = resolution; - metrics.mDevPixelsPerCSSPixel = - (float)nsPresContext::AppUnitsPerCSSPixel() / auPerDevPixel; + metrics.mDevPixelsPerCSSPixel = CSSToLayoutDeviceScale( + (float)nsPresContext::AppUnitsPerCSSPixel() / auPerDevPixel); metrics.mMayHaveTouchListeners = aMayHaveTouchListeners; diff --git a/layout/ipc/RenderFrameParent.cpp b/layout/ipc/RenderFrameParent.cpp index a443d412d518..1cd5242193c6 100644 --- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -167,10 +167,7 @@ ComputeShadowTreeTransform(nsIFrame* aContainerFrame, nscoord auPerDevPixel = aContainerFrame->PresContext()->AppUnitsPerDevPixel(); nsIntPoint scrollOffset = aConfig.mScrollOffset.ToNearestPixels(auPerDevPixel); - // metricsScrollOffset is in layer coordinates. - gfx::Point metricsScrollOffset = aMetrics->GetScrollOffsetInLayerPixels(); - nsIntPoint roundedMetricsScrollOffset = - nsIntPoint(NS_lround(metricsScrollOffset.x), NS_lround(metricsScrollOffset.y)); + LayerIntPoint metricsScrollOffset = RoundedToInt(aMetrics->GetScrollOffsetInLayerPixels()); if (aRootFrameLoader->AsyncScrollEnabled() && !aMetrics->mDisplayPort.IsEmpty()) { // Only use asynchronous scrolling if it is enabled and there is a @@ -178,8 +175,8 @@ ComputeShadowTreeTransform(nsIFrame* aContainerFrame, // synchronously scrolled for identifying a scroll area before it is // being actively scrolled. nsIntPoint scrollCompensation( - (scrollOffset.x / aTempScaleX - roundedMetricsScrollOffset.x), - (scrollOffset.y / aTempScaleY - roundedMetricsScrollOffset.y)); + (scrollOffset.x / aTempScaleX - metricsScrollOffset.x), + (scrollOffset.y / aTempScaleY - metricsScrollOffset.y)); return ViewTransform(-scrollCompensation, aConfig.mXScale, aConfig.mYScale); } else { @@ -371,7 +368,7 @@ BuildViewMap(ViewMap& oldContentViews, ViewMap& newContentViews, if (metrics.IsScrollable()) { nscoord auPerDevPixel = aFrameLoader->GetPrimaryFrameOfOwningContent() ->PresContext()->AppUnitsPerDevPixel(); - nscoord auPerCSSPixel = auPerDevPixel * metrics.mDevPixelsPerCSSPixel; + nscoord auPerCSSPixel = auPerDevPixel * metrics.mDevPixelsPerCSSPixel.scale; nsContentView* view = FindViewForId(oldContentViews, scrollId); if (view) { // View already exists. Be sure to propagate scales for any values diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp index 9d3470703dd4..5ee78d95015b 100644 --- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -2114,7 +2114,7 @@ AndroidBridge::IsTablet() } void -AndroidBridge::SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const CSSRect& aCssPageRect) +AndroidBridge::SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect) { AndroidGeckoLayerClient *client = mLayerClient; if (!client) @@ -2134,8 +2134,8 @@ AndroidBridge::SetPageRect(const CSSRect& aCssPageRect) } void -AndroidBridge::SyncViewportInfo(const LayerIntRect& aDisplayPort, float aDisplayResolution, bool aLayersUpdated, - ScreenPoint& aScrollOffset, float& aScaleX, float& aScaleY, +AndroidBridge::SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, + bool aLayersUpdated, ScreenPoint& aScrollOffset, CSSToScreenScale& aScale, gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset) { AndroidGeckoLayerClient *client = mLayerClient; @@ -2143,12 +2143,12 @@ AndroidBridge::SyncViewportInfo(const LayerIntRect& aDisplayPort, float aDisplay return; client->SyncViewportInfo(aDisplayPort, aDisplayResolution, aLayersUpdated, - aScrollOffset, aScaleX, aScaleY, aFixedLayerMargins, + aScrollOffset, aScale, aFixedLayerMargins, aOffset); } void AndroidBridge::SyncFrameMetrics(const ScreenPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect, - bool aLayersUpdated, const CSSRect& aDisplayPort, float aDisplayResolution, + bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, bool aIsFirstPaint, gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset) { AndroidGeckoLayerClient *client = mLayerClient; diff --git a/widget/android/AndroidBridge.h b/widget/android/AndroidBridge.h index 51a0a158a585..973beef4701f 100644 --- a/widget/android/AndroidBridge.h +++ b/widget/android/AndroidBridge.h @@ -371,13 +371,13 @@ public: void EnableNetworkNotifications(); void DisableNetworkNotifications(); - void SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const CSSRect& aCssPageRect); + void SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect); void SetPageRect(const CSSRect& aCssPageRect); - void SyncViewportInfo(const LayerIntRect& aDisplayPort, float aDisplayResolution, bool aLayersUpdated, - ScreenPoint& aScrollOffset, float& aScaleX, float& aScaleY, + void SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, + bool aLayersUpdated, ScreenPoint& aScrollOffset, CSSToScreenScale& aScale, gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset); void SyncFrameMetrics(const ScreenPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect, - bool aLayersUpdated, const CSSRect& aDisplayPort, float aDisplayResolution, + bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, bool aIsFirstPaint, gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset); void AddPluginView(jobject view, const gfxRect& rect, bool isFullScreen); diff --git a/widget/android/AndroidJavaWrappers.cpp b/widget/android/AndroidJavaWrappers.cpp index 9827c34e994f..46642c4e38ba 100644 --- a/widget/android/AndroidJavaWrappers.cpp +++ b/widget/android/AndroidJavaWrappers.cpp @@ -905,7 +905,7 @@ AndroidProgressiveUpdateData::Init(jobject jobj) } void -AndroidGeckoLayerClient::SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const CSSRect& aCssPageRect) +AndroidGeckoLayerClient::SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect) { NS_ASSERTION(!isNull(), "SetFirstPaintViewport called on null layer client!"); JNIEnv *env = GetJNIForThread(); // this is called on the compositor thread @@ -913,7 +913,7 @@ AndroidGeckoLayerClient::SetFirstPaintViewport(const LayerIntPoint& aOffset, flo return; AutoLocalJNIFrame jniFrame(env, 0); - return env->CallVoidMethod(wrapped_obj, jSetFirstPaintViewport, (float)aOffset.x, (float)aOffset.y, aZoom, + return env->CallVoidMethod(wrapped_obj, jSetFirstPaintViewport, (float)aOffset.x, (float)aOffset.y, aZoom.scale, aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost()); } @@ -931,8 +931,8 @@ AndroidGeckoLayerClient::SetPageRect(const CSSRect& aCssPageRect) } void -AndroidGeckoLayerClient::SyncViewportInfo(const LayerIntRect& aDisplayPort, float aDisplayResolution, bool aLayersUpdated, - ScreenPoint& aScrollOffset, float& aScaleX, float& aScaleY, +AndroidGeckoLayerClient::SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, + bool aLayersUpdated, ScreenPoint& aScrollOffset, CSSToScreenScale& aScale, gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset) { NS_ASSERTION(!isNull(), "SyncViewportInfo called on null layer client!"); @@ -945,7 +945,7 @@ AndroidGeckoLayerClient::SyncViewportInfo(const LayerIntRect& aDisplayPort, floa jobject viewTransformJObj = env->CallObjectMethod(wrapped_obj, jSyncViewportInfoMethod, aDisplayPort.x, aDisplayPort.y, aDisplayPort.width, aDisplayPort.height, - aDisplayResolution, aLayersUpdated); + aDisplayResolution.scale, aLayersUpdated); if (jniFrame.CheckForException()) return; @@ -955,7 +955,7 @@ AndroidGeckoLayerClient::SyncViewportInfo(const LayerIntRect& aDisplayPort, floa viewTransform.Init(viewTransformJObj); aScrollOffset = ScreenPoint(viewTransform.GetX(env), viewTransform.GetY(env)); - aScaleX = aScaleY = viewTransform.GetScale(env); + aScale.scale = viewTransform.GetScale(env); viewTransform.GetFixedLayerMargins(env, aFixedLayerMargins); aOffset.x = viewTransform.GetOffsetX(env); @@ -964,7 +964,7 @@ AndroidGeckoLayerClient::SyncViewportInfo(const LayerIntRect& aDisplayPort, floa void AndroidGeckoLayerClient::SyncFrameMetrics(const ScreenPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect, - bool aLayersUpdated, const CSSRect& aDisplayPort, float aDisplayResolution, + bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, bool aIsFirstPaint, gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset) { NS_ASSERTION(!isNull(), "SyncFrameMetrics called on null layer client!"); @@ -975,14 +975,14 @@ AndroidGeckoLayerClient::SyncFrameMetrics(const ScreenPoint& aScrollOffset, floa AutoLocalJNIFrame jniFrame(env); // convert the displayport rect from scroll-relative CSS pixels to document-relative device pixels - LayerRect dpUnrounded = aDisplayPort * CSSToLayerScale(aDisplayResolution); + LayerRect dpUnrounded = aDisplayPort * aDisplayResolution; dpUnrounded += LayerPoint::FromUnknownPoint(aScrollOffset.ToUnknownPoint()); LayerIntRect dp = gfx::RoundedToInt(dpUnrounded); jobject viewTransformJObj = env->CallObjectMethod(wrapped_obj, jSyncFrameMetricsMethod, aScrollOffset.x, aScrollOffset.y, aZoom, aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost(), - aLayersUpdated, dp.x, dp.y, dp.width, dp.height, aDisplayResolution, + aLayersUpdated, dp.x, dp.y, dp.width, dp.height, aDisplayResolution.scale, aIsFirstPaint); if (jniFrame.CheckForException()) diff --git a/widget/android/AndroidJavaWrappers.h b/widget/android/AndroidJavaWrappers.h index 4d01b488deb2..f31ea59eee28 100644 --- a/widget/android/AndroidJavaWrappers.h +++ b/widget/android/AndroidJavaWrappers.h @@ -269,13 +269,13 @@ public: AndroidGeckoLayerClient() {} AndroidGeckoLayerClient(jobject jobj) { Init(jobj); } - void SetFirstPaintViewport(const LayerIntPoint& aOffset, float aZoom, const CSSRect& aCssPageRect); + void SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect); void SetPageRect(const CSSRect& aCssPageRect); - void SyncViewportInfo(const LayerIntRect& aDisplayPort, float aDisplayResolution, bool aLayersUpdated, - ScreenPoint& aScrollOffset, float& aScaleX, float& aScaleY, + void SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, + bool aLayersUpdated, ScreenPoint& aScrollOffset, CSSToScreenScale& aScale, gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset); void SyncFrameMetrics(const ScreenPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect, - bool aLayersUpdated, const CSSRect& aDisplayPort, float aDisplayResolution, + bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, bool aIsFirstPaint, gfx::Margin& aFixedLayerMargins, ScreenPoint& aOffset); bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY); bool CreateFrame(AutoLocalJNIFrame *jniFrame, AndroidLayerRendererFrame& aFrame);