Bug 847223. Part 3. Factor out the expand the scrollport code so we can use it on individual images later. r=mats
authorTimothy Nikkel <tnikkel@gmail.com>
Sat, 14 Sep 2013 19:05:04 -0500
changeset 147213 15151e852274
parent 147212 cdb5c593fa83
child 147214 890f8c06d8aa
push id33809
push usertnikkel@gmail.com
push dateSun, 15 Sep 2013 00:05:34 +0000
treeherdermozilla-inbound@daa9550337ab [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmats
bugs847223
milestone26.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
Bug 847223. Part 3. Factor out the expand the scrollport code so we can use it on individual images later. r=mats
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGfxScrollFrame.h
layout/generic/nsIScrollableFrame.h
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -1529,16 +1529,18 @@ nsGfxScrollFrameInner::nsGfxScrollFrameI
   , mShouldBuildLayer(false)
   , mHasBeenScrolled(false)
 {
   mScrollingActive = IsAlwaysActive();
 
   if (LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) != 0) {
     mScrollbarActivity = new ScrollbarActivity(do_QueryFrame(aOuter));
   }
+
+  EnsureImageVisPrefsCached();
 }
 
 nsGfxScrollFrameInner::~nsGfxScrollFrameInner()
 {
   if (mActivityExpirationState.IsTracked()) {
     gScrollFrameActivityTracker->RemoveObject(this);
   }
   if (gScrollFrameActivityTracker &&
@@ -1974,29 +1976,16 @@ nsGfxScrollFrameInner::ScrollToImpl(nsPo
                                  appUnitsPerDevPixel,
                                  scale);
   if (pt == curPos) {
     return;
   }
 
   bool needImageVisibilityUpdate = (mLastUpdateImagesPos == nsPoint(-1,-1));
 
-  static bool sImageVisPrefsCached = false;
-  // The fraction of the scrollport we allow to scroll by before we schedule
-  // an update of image visibility.
-  static int32_t sHorzScrollFraction = 2;
-  static int32_t sVertScrollFraction = 2;
-  if (!sImageVisPrefsCached) {
-    Preferences::AddIntVarCache(&sHorzScrollFraction,
-      "layout.imagevisibility.amountscrollbeforeupdatehorizontal", 2);
-    Preferences::AddIntVarCache(&sVertScrollFraction,
-      "layout.imagevisibility.amountscrollbeforeupdatevertical", 2);
-    sImageVisPrefsCached = true;
-  }
-
   nsPoint dist(std::abs(pt.x - mLastUpdateImagesPos.x),
                std::abs(pt.y - mLastUpdateImagesPos.y));
   nscoord horzAllowance = std::max(mScrollPort.width / std::max(sHorzScrollFraction, 1),
                                    nsPresContext::AppUnitsPerCSSPixel());
   nscoord vertAllowance = std::max(mScrollPort.height / std::max(sVertScrollFraction, 1),
                                    nsPresContext::AppUnitsPerCSSPixel());
   if (dist.x >= horzAllowance || dist.y >= vertAllowance) {
     needImageVisibilityUpdate = true;
@@ -2145,16 +2134,48 @@ protected:
   }
 
   intptr_t mCount;
   FrameProperties mProps;
   nsIFrame* mScrollFrame;
   nsIFrame* mScrolledFrame;
 };
 
+/* static */ bool nsGfxScrollFrameInner::sImageVisPrefsCached = false;
+/* static */ uint32_t nsGfxScrollFrameInner::sHorzExpandScrollPort = 0;
+/* static */ uint32_t nsGfxScrollFrameInner::sVertExpandScrollPort = 1;
+/* static */ int32_t nsGfxScrollFrameInner::sHorzScrollFraction = 2;
+/* static */ int32_t nsGfxScrollFrameInner::sVertScrollFraction = 2;
+
+/* static */ void
+nsGfxScrollFrameInner::EnsureImageVisPrefsCached()
+{
+  if (!sImageVisPrefsCached) {
+    Preferences::AddUintVarCache(&sHorzExpandScrollPort,
+      "layout.imagevisibility.numscrollportwidths", (uint32_t)0);
+    Preferences::AddUintVarCache(&sVertExpandScrollPort,
+      "layout.imagevisibility.numscrollportheights", 1);
+
+    Preferences::AddIntVarCache(&sHorzScrollFraction,
+      "layout.imagevisibility.amountscrollbeforeupdatehorizontal", 2);
+    Preferences::AddIntVarCache(&sVertScrollFraction,
+      "layout.imagevisibility.amountscrollbeforeupdatevertical", 2);
+
+    sImageVisPrefsCached = true;
+  }
+}
+
+/* static */ nsRect
+nsGfxScrollFrameInner::ExpandRect(const nsRect& aRect)
+{
+  nsRect rect = aRect;
+  rect.Inflate(sHorzExpandScrollPort * aRect.width, sVertExpandScrollPort * aRect.height);
+  return rect;
+}
+
 void
 nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                         const nsRect&           aDirtyRect,
                                         const nsDisplayListSet& aLists)
 {
   if (aBuilder->IsForImageVisibility()) {
     mLastUpdateImagesPos = GetScrollPosition();
   }
@@ -2221,40 +2242,20 @@ nsGfxScrollFrameInner::BuildDisplayList(
   bool usingDisplayport =
     nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &displayPort) &&
     !aBuilder->IsForEventDelivery();
   if (usingDisplayport) {
     dirtyRect = displayPort;
   }
 
   if (aBuilder->IsForImageVisibility()) {
-    static bool sImageVisPrefsCached = false;
-    // The number of scrollports wide/high to expand when looking for images.
-    static uint32_t sHorzExpandScrollPort = 0;
-    static uint32_t sVertExpandScrollPort = 1;
-    if (!sImageVisPrefsCached) {
-      Preferences::AddUintVarCache(&sHorzExpandScrollPort,
-        "layout.imagevisibility.numscrollportwidths", (uint32_t)0);
-      Preferences::AddUintVarCache(&sVertExpandScrollPort,
-        "layout.imagevisibility.numscrollportheights", 1);
-      sImageVisPrefsCached = true;
-    }
-
     // We expand the dirty rect to catch images just outside of the scroll port.
     // We could be smarter and not expand the dirty rect in a direction in which
     // we are not able to scroll.
-    nsRect dirtyRectBefore = dirtyRect;
-
-    nsPoint vertShift = nsPoint(0, sVertExpandScrollPort * dirtyRectBefore.height);
-    dirtyRect = dirtyRect.Union(dirtyRectBefore - vertShift);
-    dirtyRect = dirtyRect.Union(dirtyRectBefore + vertShift);
-
-    nsPoint horzShift = nsPoint(sHorzExpandScrollPort * dirtyRectBefore.width, 0);
-    dirtyRect = dirtyRect.Union(dirtyRectBefore - horzShift);
-    dirtyRect = dirtyRect.Union(dirtyRectBefore + horzShift);
+    dirtyRect = ExpandRect(dirtyRect);
   }
 
   nsDisplayListCollection set;
   {
     DisplayListClipState::AutoSaveRestore clipState(aBuilder);
 
     if (usingDisplayport) {
       nsRect clip = displayPort + aBuilder->ToReferenceFrame(mOuter);
@@ -2321,16 +2322,22 @@ nsGfxScrollFrameInner::BuildDisplayList(
     aLists.BorderBackground()->AppendNewToBottom(layerItem);
   }
 
   // Now display overlay scrollbars and the resizer, if we have one.
   AppendScrollPartsTo(aBuilder, aDirtyRect, aLists, createLayersForScrollbars,
                       true);
 }
 
+bool
+nsGfxScrollFrameInner::IsRectNearlyVisible(const nsRect& aRect) const
+{
+  return aRect.Intersects(ExpandRect(mScrollPort));
+}
+
 static void HandleScrollPref(nsIScrollable *aScrollable, int32_t aOrientation,
                              uint8_t& aValue)
 {
   int32_t pref;
   aScrollable->GetDefaultScrollbarPreferences(aOrientation, &pref);
   switch (pref) {
     case nsIScrollable::Scrollbar_Auto:
       // leave |aValue| untouched
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -273,16 +273,18 @@ public:
   {
     mScrollPosForLayerPixelAlignment = GetScrollPosition();
   }
 
   bool UpdateOverflow();
 
   void UpdateSticky();
 
+  bool IsRectNearlyVisible(const nsRect& aRect) const;
+
   // adjust the scrollbar rectangle aRect to account for any visible resizer.
   // aHasResizer specifies if there is a content resizer, however this method
   // will also check if a widget resizer is present as well.
   void AdjustScrollbarRectForResizer(nsIFrame* aFrame, nsPresContext* aPresContext,
                                      nsRect& aRect, bool aHasResizer, bool aVertical);
   // returns true if a resizer should be visible
   bool HasResizer() { return mResizerBox && !mCollapsedResizer; }
   void LayoutScrollbars(nsBoxLayoutState& aState,
@@ -394,16 +396,27 @@ public:
 protected:
   /**
    * @note This method might destroy the frame, pres shell and other objects.
    */
   void ScrollToWithOrigin(nsPoint aScrollPosition,
                           nsIScrollableFrame::ScrollMode aMode,
                           nsIAtom *aOrigin, // nullptr indicates "other" origin
                           const nsRect* aRange);
+
+  static nsRect ExpandRect(const nsRect& aRect);
+  static void EnsureImageVisPrefsCached();
+  static bool sImageVisPrefsCached;
+  // The number of scrollports wide/high to expand when looking for images.
+  static uint32_t sHorzExpandScrollPort;
+  static uint32_t sVertExpandScrollPort;
+  // The fraction of the scrollport we allow to scroll by before we schedule
+  // an update of image visibility.
+  static int32_t sHorzScrollFraction;
+  static int32_t sVertScrollFraction;
 };
 
 /**
  * The scroll frame creates and manages the scrolling view
  *
  * It only supports having a single child frame that typically is an area
  * frame, but doesn't have to be. The child frame must have a view, though
  *
@@ -615,16 +628,19 @@ public:
     mInner.ResetScrollPositionForLayerPixelAlignment();
   }
   virtual bool DidHistoryRestore() MOZ_OVERRIDE {
     return mInner.mDidHistoryRestore;
   }
   virtual void ClearDidHistoryRestore() MOZ_OVERRIDE {
     mInner.mDidHistoryRestore = false;
   }
+  virtual bool IsRectNearlyVisible(const nsRect& aRect) MOZ_OVERRIDE {
+    return mInner.IsRectNearlyVisible(aRect);
+  }
 
   // nsIStatefulFrame
   NS_IMETHOD SaveState(nsPresState** aState) MOZ_OVERRIDE {
     NS_ENSURE_ARG_POINTER(aState);
     *aState = mInner.SaveState();
     return NS_OK;
   }
   NS_IMETHOD RestoreState(nsPresState* aState) MOZ_OVERRIDE {
@@ -899,16 +915,19 @@ public:
     mInner.ResetScrollPositionForLayerPixelAlignment();
   }
   virtual bool DidHistoryRestore() MOZ_OVERRIDE {
     return mInner.mDidHistoryRestore;
   }
   virtual void ClearDidHistoryRestore() MOZ_OVERRIDE {
     mInner.mDidHistoryRestore = false;
   }
+  virtual bool IsRectNearlyVisible(const nsRect& aRect) MOZ_OVERRIDE {
+    return mInner.IsRectNearlyVisible(aRect);
+  }
 
   // nsIStatefulFrame
   NS_IMETHOD SaveState(nsPresState** aState) MOZ_OVERRIDE {
     NS_ENSURE_ARG_POINTER(aState);
     *aState = mInner.SaveState();
     return NS_OK;
   }
   NS_IMETHOD RestoreState(nsPresState* aState) MOZ_OVERRIDE {
--- a/layout/generic/nsIScrollableFrame.h
+++ b/layout/generic/nsIScrollableFrame.h
@@ -257,11 +257,16 @@ public:
    */
   virtual bool DidHistoryRestore() = 0;
   /**
    * Clear the flag so that DidHistoryRestore() returns false until the next
    * RestoreState call.
    * @see nsIStatefulFrame::RestoreState
    */
   virtual void ClearDidHistoryRestore() = 0;
+  /**
+   * Determine if the passed in rect is nearly visible according to the image
+   * visibility heuristics for how close it is to the visible scrollport.
+   */
+  virtual bool IsRectNearlyVisible(const nsRect& aRect) = 0;
 };
 
 #endif