merge backout b=810274
authorKarl Tomlinson <karlt+@karlt.net>
Thu, 06 Jun 2013 18:04:48 +1200
changeset 145704 fd3eb4b732920eb8538e1900f76c123b6dce7ab2
parent 145702 1ba9dc37c2efb9187e0a1a853fad2bac571112f7 (current diff)
parent 145703 25ab810de6e0f8963a354336c66e0d05905ce3f9 (diff)
child 145705 6a5f8ebc836a6866849daa92aa916427af01aa7d
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs810274
milestone24.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge backout b=810274
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -41,17 +41,16 @@
 #include "nsLayoutUtils.h"
 #include "nsBidiUtils.h"
 #include "nsFrameManager.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/LookAndFeel.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/StandardInteger.h"
 #include "mozilla/Util.h"
-#include "mozilla/MathAlgorithms.h"
 #include "FrameLayerBuilder.h"
 #include "nsSMILKeySpline.h"
 #include "nsSubDocumentFrame.h"
 #include "nsSVGOuterSVGFrame.h"
 #include "mozilla/Attributes.h"
 #include "ScrollbarActivity.h"
 #include "nsRefreshDriver.h"
 #include "nsContentList.h"
@@ -1548,22 +1547,35 @@ nsGfxScrollFrameInner::AsyncScrollCallba
   nsGfxScrollFrameInner* self = static_cast<nsGfxScrollFrameInner*>(anInstance);
   if (!self || !self->mAsyncScroll)
     return;
 
   nsRect range = self->mAsyncScroll->mRange;
   if (self->mAsyncScroll->mIsSmoothScroll) {
     if (!self->mAsyncScroll->IsFinished(aTime)) {
       nsPoint destination = self->mAsyncScroll->PositionAt(aTime);
-      // Allow this scroll operation to land on any pixel boundary between the
-      // current position and the final allowed range.  (We don't want
-      // intermediate steps to be more constrained than the final step!)
-      nsRect intermediateRange =
-        nsRect(self->GetScrollPosition(), nsSize()).UnionEdges(range);
-      self->ScrollToImpl(destination, intermediateRange);
+      nsPoint start = self->mAsyncScroll->mStartPos;
+      // Allow this scroll operation to land on any pixel boundary in the
+      // right direction (as well as anywhere in the final allowed range,
+      // since we don't want intermediate steps to be more constrained than the
+      // final step!).
+      static const int veryLargeDistance = nscoord_MAX/4;
+      nsRect unlimitedRange(0, 0, veryLargeDistance, veryLargeDistance);
+      if (destination.x < start.x) {
+        unlimitedRange.x = -veryLargeDistance;
+      } else if (destination.x == start.x) {
+        unlimitedRange.width = 0;
+      }
+      if (destination.y < start.y) {
+        unlimitedRange.y = -veryLargeDistance;
+      } else if (destination.y == start.y) {
+        unlimitedRange.height = 0;
+      }
+      self->ScrollToImpl(destination,
+                         (unlimitedRange + destination).UnionEdges(range));
       return;
     }
   }
 
   // Apply desired destination range since this is the last step of scrolling.
   self->mAsyncScroll = nullptr;
   self->ScrollToImpl(self->mDestination, range);
   // We are done scrolling, set our destination to wherever we actually ended
@@ -1805,98 +1817,74 @@ void nsGfxScrollFrameInner::ScrollVisual
   if (canScrollWithBlitting) {
     MarkActive();
   }
 
   mOuter->SchedulePaint();
 }
 
 /**
- * Clamp desired scroll position aDesired and range [aDestLower, aDestUpper]
- * to [aBoundLower, aBoundUpper] and then select the appunit value from among
- * aBoundLower, aBoundUpper and those such that (aDesired - aCurrent) *
- * aRes/aAppUnitsPerPixel is an integer (or as close as we can get
- * modulo rounding to appunits) that is in [aDestLower, aDestUpper] and
- * closest to aDesired.  If no such value exists, return the nearest in
- * [aDestLower, aDestUpper].
+ * Return an appunit value close to aDesired and between aLower and aUpper
+ * such that (aDesired - aCurrent)*aRes/aAppUnitsPerPixel is an integer (or
+ * as close as we can get modulo rounding to appunits). If that
+ * can't be done, just returns aDesired.
  */
 static nscoord
-ClampAndAlignWithPixels(nscoord aDesired,
-                        nscoord aBoundLower, nscoord aBoundUpper,
-                        nscoord aDestLower, nscoord aDestUpper,
-                        nscoord aAppUnitsPerPixel, double aRes,
-                        nscoord aCurrent)
+AlignWithLayerPixels(nscoord aDesired, nscoord aLower,
+                     nscoord aUpper, nscoord aAppUnitsPerPixel,
+                     double aRes, nscoord aCurrent)
 {
-  // Intersect scroll range with allowed range, by clamping the ends
-  // of aRange to be within bounds
-  nscoord destLower = clamped(aDestLower, aBoundLower, aBoundUpper);
-  nscoord destUpper = clamped(aDestUpper, aBoundLower, aBoundUpper);
-
-  nscoord desired = clamped(aDesired, destLower, destUpper);
-
   double currentLayerVal = (aRes*aCurrent)/aAppUnitsPerPixel;
-  double desiredLayerVal = (aRes*desired)/aAppUnitsPerPixel;
+  double desiredLayerVal = (aRes*aDesired)/aAppUnitsPerPixel;
   double delta = desiredLayerVal - currentLayerVal;
-  double nearestLayerVal = NS_round(delta) + currentLayerVal;
+  double nearestVal = NS_round(delta) + currentLayerVal;
 
   // Convert back from ThebesLayer space to appunits relative to the top-left
   // of the scrolled frame.
-  nscoord aligned =
-    NSToCoordRoundWithClamp(nearestLayerVal*aAppUnitsPerPixel/aRes);
-
-  // Use a bound if it is within the allowed range and closer to desired than
-  // the nearest pixel-aligned value.
-  if (aBoundUpper == destUpper &&
-      static_cast<decltype(Abs(desired))>(aBoundUpper - desired) <
-      Abs(desired - aligned))
-    return aBoundUpper;
-
-  if (aBoundLower == destLower &&
-      static_cast<decltype(Abs(desired))>(desired - aBoundLower) <
-      Abs(aligned - desired))
-    return aBoundLower;
-
-  // Accept the nearest pixel-aligned value if it is within the allowed range. 
-  if (aligned >= destLower && aligned <= destUpper)
-    return aligned;
-
-  // Check if opposite pixel boundary fits into allowed range.
-  double oppositeLayerVal =
-    nearestLayerVal + ((nearestLayerVal < desiredLayerVal) ? 1.0 : -1.0);
-  nscoord opposite =
-    NSToCoordRoundWithClamp(oppositeLayerVal*aAppUnitsPerPixel/aRes);
-  if (opposite >= destLower && opposite <= destUpper) {
-    return opposite;
+  nscoord nearestAppUnitVal =
+    NSToCoordRoundWithClamp(nearestVal*aAppUnitsPerPixel/aRes);
+
+  // Check if nearest layer pixel result fit into allowed and scroll range
+  if (nearestAppUnitVal >= aLower && nearestAppUnitVal <= aUpper) {
+    return nearestAppUnitVal;
+  } else if (nearestVal != desiredLayerVal) {
+    // Check if opposite pixel boundary fit into scroll range
+    double oppositeVal = nearestVal + ((nearestVal < desiredLayerVal) ? 1 : -1);
+    nscoord oppositeAppUnitVal =
+      NSToCoordRoundWithClamp(oppositeVal*aAppUnitsPerPixel/aRes);
+    if (oppositeAppUnitVal >= aLower && oppositeAppUnitVal <= aUpper) {
+      return oppositeAppUnitVal;
+    }
   }
-
-  // No alignment available.
-  return desired;
+  return aDesired;
 }
 
 /**
  * Clamp desired scroll position aPt to aBounds and then snap
  * it to the same layer pixel edges as aCurrent, keeping it within aRange
  * during snapping. aCurrent is the current scroll position.
  */
 static nsPoint
 ClampAndAlignWithLayerPixels(const nsPoint& aPt,
                              const nsRect& aBounds,
                              const nsRect& aRange,
                              const nsPoint& aCurrent,
                              nscoord aAppUnitsPerPixel,
                              const gfxSize& aScale)
 {
-  return nsPoint(ClampAndAlignWithPixels(aPt.x, aBounds.x, aBounds.XMost(),
-                                         aRange.x, aRange.XMost(),
-                                         aAppUnitsPerPixel, aScale.width,
-                                         aCurrent.x),
-                 ClampAndAlignWithPixels(aPt.y, aBounds.y, aBounds.YMost(),
-                                         aRange.y, aRange.YMost(),
-                                         aAppUnitsPerPixel, aScale.height,
-                                         aCurrent.y));
+  nsPoint pt = aBounds.ClampPoint(aPt);
+  // Intersect scroll range with allowed range, by clamping the corners
+  // of aRange to be within bounds
+  nsPoint rangeTopLeft = aBounds.ClampPoint(aRange.TopLeft());
+  nsPoint rangeBottomRight = aBounds.ClampPoint(aRange.BottomRight());
+
+  return nsPoint(AlignWithLayerPixels(pt.x, rangeTopLeft.x, rangeBottomRight.x,
+                                      aAppUnitsPerPixel, aScale.width, aCurrent.x),
+                 AlignWithLayerPixels(pt.y, rangeTopLeft.y, rangeBottomRight.y,
+                                      aAppUnitsPerPixel, aScale.height, aCurrent.y));
 }
 
 /* static */ void
 nsGfxScrollFrameInner::ScrollActivityCallback(nsITimer *aTimer, void* anInstance)
 {
   nsGfxScrollFrameInner* self = static_cast<nsGfxScrollFrameInner*>(anInstance);
 
   // Fire the synth mouse move.