Bug 880676 - Replace a couple of Rect scaling functions with strongly typed operators. r=BenWa
authorKartikaya Gupta <kgupta@mozilla.com>
Fri, 14 Jun 2013 16:11:31 -0400
changeset 135125 1e0c4309ec6aa835bddf52d7109972e649e38f2e
parent 135124 6e2cfc657c74f6b6af36a47dfdfab0d78ace4392
child 135126 8050296faa271ea6adea360104624129c0cf3fea
push idunknown
push userunknown
push dateunknown
reviewersBenWa
bugs880676
milestone24.0a1
Bug 880676 - Replace a couple of Rect scaling functions with strongly typed operators. r=BenWa
gfx/layers/client/ClientLayerManager.cpp
gfx/layers/composite/AsyncCompositionManager.cpp
gfx/layers/composite/ThebesLayerComposite.cpp
layout/base/Units.h
widget/android/AndroidJavaWrappers.cpp
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -390,26 +390,25 @@ ClientLayerManager::ProgressiveUpdateCal
 #ifdef MOZ_WIDGET_ANDROID
   Layer* primaryScrollable = GetPrimaryScrollableLayer();
   if (primaryScrollable) {
     const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
 
     // This is derived from the code in
     // gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree.
     const gfx3DMatrix& rootTransform = GetRoot()->GetTransform();
-    float devPixelRatioX = 1 / rootTransform.GetXScale();
-    float devPixelRatioY = 1 / rootTransform.GetYScale();
+    CSSToLayerScale paintScale = LayerToCSSScale(rootTransform.GetXScale(),
+                                                 rootTransform.GetYScale()).Inverse();
     const CSSRect& metricsDisplayPort =
       (aDrawingCritical && !metrics.mCriticalDisplayPort.IsEmpty()) ?
         metrics.mCriticalDisplayPort : metrics.mDisplayPort;
-    LayerRect displayPort = LayerRect::FromCSSRect(metricsDisplayPort + metrics.mScrollOffset,
-                                                   devPixelRatioX, devPixelRatioY);
+    LayerRect displayPort = (metricsDisplayPort + metrics.mScrollOffset) * paintScale;
 
     return AndroidBridge::Bridge()->ProgressiveUpdateCallback(
-      aHasPendingNewThebesContent, displayPort, devPixelRatioX, aDrawingCritical,
+      aHasPendingNewThebesContent, displayPort, paintScale.scale, aDrawingCritical,
       aViewport, aScaleX, aScaleY);
   }
 #endif
 
   return false;
 }
 
 ClientLayer::~ClientLayer()
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -399,103 +399,95 @@ AsyncCompositionManager::TransformScroll
 
   const FrameMetrics& metrics = container->GetFrameMetrics();
   // We must apply the resolution scale before a pan/zoom transform, so we call
   // GetTransform here.
   const gfx3DMatrix& currentTransform = aLayer->GetTransform();
 
   gfx3DMatrix treeTransform;
 
-  float layerPixelRatioX = 1 / aRootTransform.GetXScale(),
-        layerPixelRatioY = 1 / aRootTransform.GetYScale();
+  CSSToLayerScale geckoZoom = LayerToCSSScale(aRootTransform.GetXScale(),
+                                              aRootTransform.GetYScale()).Inverse();
 
-  LayerIntPoint scrollOffsetLayerPixels = LayerIntPoint::FromCSSPointRounded(
-    metrics.mScrollOffset, layerPixelRatioX, layerPixelRatioY);
+  LayerIntPoint scrollOffsetLayerPixels = RoundedToInt(metrics.mScrollOffset * geckoZoom);
 
   if (mIsFirstPaint) {
     mContentRect = metrics.mScrollableRect;
     SetFirstPaintViewport(scrollOffsetLayerPixels,
-                          layerPixelRatioX,
+                          geckoZoom.scale,
                           mContentRect);
     mIsFirstPaint = false;
   } else if (!metrics.mScrollableRect.IsEqualEdges(mContentRect)) {
     mContentRect = metrics.mScrollableRect;
     SetPageRect(mContentRect);
   }
 
   // We synchronise the viewport information with Java after sending the above
   // notifications, so that Java can take these into account in its response.
   // Calculate the absolute display port to send to Java
-  LayerIntRect displayPort =
-    LayerIntRect::FromCSSRectRounded(metrics.mCriticalDisplayPort.IsEmpty()
-                                       ? metrics.mDisplayPort
-                                       : metrics.mCriticalDisplayPort,
-                                     layerPixelRatioX, layerPixelRatioY);
+  LayerIntRect displayPort = RoundedToInt(
+    (metrics.mCriticalDisplayPort.IsEmpty()
+      ? metrics.mDisplayPort
+      : metrics.mCriticalDisplayPort
+    ) * geckoZoom);
   displayPort += scrollOffsetLayerPixels;
 
   gfx::Margin fixedLayerMargins(0, 0, 0, 0);
   ScreenPoint offset(0, 0);
-  ScreenPoint scrollOffset(0, 0);
-  float scaleX = 1.0,
-        scaleY = 1.0;
-  SyncViewportInfo(displayPort, layerPixelRatioX, mLayersUpdated,
-                   scrollOffset, scaleX, scaleY, fixedLayerMargins,
+  ScreenPoint userScroll(0, 0);
+  CSSToScreenScale userZoom;
+  SyncViewportInfo(displayPort, geckoZoom.scale, mLayersUpdated,
+                   userScroll, userZoom.scale, userZoom.scale, fixedLayerMargins,
                    offset);
   mLayersUpdated = false;
 
   // Apply the render offset
   mLayerManager->GetCompositor()->SetScreenRenderOffset(offset);
 
   // Handle transformations for asynchronous panning and zooming. We determine the
   // zoom used by Gecko from the transformation set on the root layer, and we
   // determine the scroll offset used by Gecko from the frame metrics of the
-  // primary scrollable layer. We compare this to the desired zoom and scroll
+  // primary scrollable layer. We compare this to the user zoom and scroll
   // offset in the view transform we obtained from Java in order to compute the
   // transformation we need to apply.
-  float tempScaleDiffX = aRootTransform.GetXScale() * scaleX;
-  float tempScaleDiffY = aRootTransform.GetYScale() * scaleY;
+  LayerToScreenScale zoomAdjust = userZoom / geckoZoom;
 
-  LayerIntPoint metricsScrollOffset(0, 0);
+  LayerIntPoint geckoScroll(0, 0);
   if (metrics.IsScrollable()) {
-    metricsScrollOffset = scrollOffsetLayerPixels;
+    geckoScroll = scrollOffsetLayerPixels;
   }
 
-  LayerPoint scrollCompensation(
-    (scrollOffset.x / tempScaleDiffX - metricsScrollOffset.x),
-    (scrollOffset.y / tempScaleDiffY - metricsScrollOffset.y));
-  treeTransform = gfx3DMatrix(ViewTransform(-scrollCompensation,
-                                            CSSToScreenScale(scaleX, scaleY)));
+  LayerPoint translation = (userScroll / zoomAdjust) - geckoScroll;
+  treeTransform = gfx3DMatrix(ViewTransform(-translation, userZoom));
 
   // Translate fixed position layers so that they stay in the correct position
-  // when scrollOffset and metricsScrollOffset differ.
+  // when userScroll and geckoScroll differ.
   gfxPoint fixedOffset;
   gfxSize scaleDiff;
 
-  LayerRect content = LayerRect::FromCSSRect(mContentRect,
-                                             1 / aRootTransform.GetXScale(),
-                                             1 / aRootTransform.GetYScale());
+  LayerRect content = mContentRect * geckoZoom;
   // If the contents can fit entirely within the widget area on a particular
   // dimension, we need to translate and scale so that the fixed layers remain
   // within the page boundaries.
-  if (mContentRect.width * scaleX < metrics.mCompositionBounds.width) {
-    fixedOffset.x = -metricsScrollOffset.x;
+  if (mContentRect.width * userZoom.scale < metrics.mCompositionBounds.width) {
+    fixedOffset.x = -geckoScroll.x;
     scaleDiff.width = std::min(1.0f, metrics.mCompositionBounds.width / content.width);
   } else {
-    fixedOffset.x = clamped(scrollOffset.x / tempScaleDiffX, content.x,
-        content.XMost() - metrics.mCompositionBounds.width / tempScaleDiffX) - metricsScrollOffset.x;
-    scaleDiff.width = tempScaleDiffX;
+    fixedOffset.x = clamped(userScroll.x / zoomAdjust.scale, content.x,
+        content.XMost() - metrics.mCompositionBounds.width / zoomAdjust.scale) - geckoScroll.x;
+    scaleDiff.width = zoomAdjust.scale;
   }
 
-  if (mContentRect.height * scaleY < metrics.mCompositionBounds.height) {
-    fixedOffset.y = -metricsScrollOffset.y;
+  if (mContentRect.height * userZoom.scale < metrics.mCompositionBounds.height) {
+    fixedOffset.y = -geckoScroll.y;
     scaleDiff.height = std::min(1.0f, metrics.mCompositionBounds.height / content.height);
   } else {
-    fixedOffset.y = clamped(scrollOffset.y / tempScaleDiffY, content.y,
-        content.YMost() - metrics.mCompositionBounds.height / tempScaleDiffY) - metricsScrollOffset.y;
-    scaleDiff.height = tempScaleDiffY;
+    fixedOffset.y = clamped(userScroll.y / zoomAdjust.scale, content.y,
+        content.YMost() - metrics.mCompositionBounds.height / zoomAdjust.scale) - geckoScroll.y;
+    scaleDiff.height = zoomAdjust.scale;
   }
 
   // The transform already takes the resolution scale into account.  Since we
   // will apply the resolution scale again when computing the effective
   // transform, we must apply the inverse resolution scale here.
   gfx3DMatrix computedTransform = treeTransform * currentTransform;
   computedTransform.Scale(1.0f/container->GetPreXScale(),
                           1.0f/container->GetPreYScale(),
--- a/gfx/layers/composite/ThebesLayerComposite.cpp
+++ b/gfx/layers/composite/ThebesLayerComposite.cpp
@@ -241,27 +241,25 @@ ThebesLayerComposite::GetCompositionBoun
                                   parentMetrics.mCompositionBounds.y,
                                   parentMetrics.mCompositionBounds.width,
                                   parentMetrics.mCompositionBounds.height);
 
       // Calculate the scale transform applied to the root layer to determine
       // the content resolution.
       Layer* rootLayer = Manager()->GetRoot();
       const gfx3DMatrix& rootTransform = rootLayer->GetTransform();
-      float scaleX = rootTransform.GetXScale();
-      float scaleY = rootTransform.GetYScale();
+      LayerToCSSScale scale(rootTransform.GetXScale(),
+                            rootTransform.GetYScale());
 
       // Get the content document bounds, in screen-space.
       const FrameMetrics& metrics = scrollableLayer->GetFrameMetrics();
-      const LayerIntRect content = LayerIntRect::FromCSSRectRounded(metrics.mScrollableRect,
-                                                                    1 / scaleX,
-                                                                    1 / scaleY);
+      const LayerIntRect content = RoundedToInt(metrics.mScrollableRect / scale);
       gfx::Point scrollOffset =
-        gfx::Point((metrics.mScrollOffset.x * metrics.LayersPixelsPerCSSPixel().width) / scaleX,
-                   (metrics.mScrollOffset.y * metrics.LayersPixelsPerCSSPixel().height) / scaleY);
+        gfx::Point((metrics.mScrollOffset.x * metrics.LayersPixelsPerCSSPixel().width) / scale.scale,
+                   (metrics.mScrollOffset.y * metrics.LayersPixelsPerCSSPixel().height) / scale.scale);
       const nsIntPoint contentOrigin(
         content.x - NS_lround(scrollOffset.x),
         content.y - NS_lround(scrollOffset.y));
       gfxRect contentRect = gfxRect(contentOrigin.x, contentOrigin.y,
                                     content.width, content.height);
       gfxRect contentBounds = scrollableLayer->GetEffectiveTransform().
         TransformBounds(contentRect);
 
--- a/layout/base/Units.h
+++ b/layout/base/Units.h
@@ -101,34 +101,16 @@ struct CSSPixel {
  * The pixels that layout rasterizes and delivers to the graphics code.
  * These are generally referred to as "device pixels" in layout code. Layer
  * pixels are affected by:
  * 1) the "display resolution" (see nsIPresShell::SetResolution)
  * 2) the "full zoom" (see nsPresContext::SetFullZoom)
  * 3) the "widget scale" (nsIWidget::GetDefaultScale)
  */
 struct LayerPixel {
-
-  // Conversions from CSS units
-
-  static LayerIntPoint FromCSSPointRounded(const CSSPoint& aPoint, float aResolutionX, float aResolutionY) {
-    return LayerIntPoint(NS_lround(aPoint.x * aResolutionX),
-                         NS_lround(aPoint.y * aResolutionY));
-  }
-
-  static LayerRect FromCSSRect(const CSSRect& aRect, float aResolutionX, float aResolutionY) {
-    return LayerRect(aRect.x * aResolutionX,
-                     aRect.y * aResolutionY,
-                     aRect.width * aResolutionX,
-                     aRect.height * aResolutionY);
-  }
-
-  static LayerIntRect FromCSSRectRounded(const CSSRect& aRect, float aResolutionX, float aResolutionY) {
-    return gfx::RoundedToInt(FromCSSRect(aRect, aResolutionX, aResolutionY));
-  }
 };
 
 /*
  * The pixels that are displayed on the screen.
  * On non-OMTC platforms this should be equivalent to LayerPixel units.
  * On OMTC platforms these may diverge from LayerPixel units temporarily,
  * while an asynchronous zoom is happening, but should eventually converge
  * back to LayerPixel units. Some variables (such as those representing
@@ -141,25 +123,41 @@ struct ScreenPixel {
 
   static CSSIntRect ToCSSIntRectRoundIn(const ScreenIntRect& aRect, float aResolutionX, float aResolutionY) {
     CSSIntRect ret(aRect.x, aRect.y, aRect.width, aRect.height);
     ret.ScaleInverseRoundIn(aResolutionX, aResolutionY);
     return ret;
   }
 };
 
-// Operators to apply ScaleFactors directly to Points
+// Operators to apply ScaleFactors directly to Points and Rects
 
 template<class src, class dst>
 gfx::PointTyped<dst> operator*(const gfx::PointTyped<src>& aPoint, const gfx::ScaleFactor<src, dst>& aScale) {
   return gfx::PointTyped<dst>(aPoint.x * aScale.scale,
                               aPoint.y * aScale.scale);
 }
 
 template<class src, class dst>
 gfx::PointTyped<dst> operator/(const gfx::PointTyped<src>& aPoint, const gfx::ScaleFactor<dst, src>& aScale) {
   return gfx::PointTyped<dst>(aPoint.x / aScale.scale,
                               aPoint.y / aScale.scale);
 }
 
+template<class src, class dst>
+gfx::RectTyped<dst> operator*(const gfx::RectTyped<src>& aRect, const gfx::ScaleFactor<src, dst>& aScale) {
+  return gfx::RectTyped<dst>(aRect.x * aScale.scale,
+                             aRect.y * aScale.scale,
+                             aRect.width * aScale.scale,
+                             aRect.height * aScale.scale);
+}
+
+template<class src, class dst>
+gfx::RectTyped<dst> operator/(const gfx::RectTyped<src>& aRect, const gfx::ScaleFactor<dst, src>& aScale) {
+  return gfx::RectTyped<dst>(aRect.x / aScale.scale,
+                             aRect.y / aScale.scale,
+                             aRect.width / aScale.scale,
+                             aRect.height / aScale.scale);
+}
+
 };
 
 #endif
--- a/widget/android/AndroidJavaWrappers.cpp
+++ b/widget/android/AndroidJavaWrappers.cpp
@@ -932,17 +932,17 @@ AndroidGeckoLayerClient::SyncFrameMetric
     NS_ASSERTION(!isNull(), "SyncFrameMetrics called on null layer client!");
     JNIEnv *env = GetJNIForThread();    // this is called on the compositor thread
     if (!env)
         return;
 
     AutoLocalJNIFrame jniFrame(env);
 
     // convert the displayport rect from scroll-relative CSS pixels to document-relative device pixels
-    LayerRect dpUnrounded = LayerRect::FromCSSRect(aDisplayPort, aDisplayResolution, aDisplayResolution);
+    LayerRect dpUnrounded = aDisplayPort * CSSToLayerScale(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,
             aIsFirstPaint);