Bug 1290335: stylo: Hoist OverflowChangedTracker to its own file. draft
authorEmilio Cobos Álvarez <ecoal95@gmail.com>
Wed, 27 Jul 2016 17:22:13 -0700
changeset 396029 dd88b1a74ac93bd70107b10552e8e400264e0c41
parent 395624 6608e5864780589b25d5421c3d3673ab30c4c318
child 396030 6d7c1a0f064761a8dc1d0c600270bce4eac0f9db
push id24900
push userbmo:ealvarez@mozilla.com
push dateWed, 03 Aug 2016 08:06:14 +0000
bugs1290335
milestone51.0a1
Bug 1290335: stylo: Hoist OverflowChangedTracker to its own file. MozReview-Commit-ID: 8QZC1VgKiZs
layout/base/OverflowChangedTracker.h
layout/base/RestyleTracker.h
layout/base/moz.build
new file mode 100644
--- /dev/null
+++ b/layout/base/OverflowChangedTracker.h
@@ -0,0 +1,207 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_OverflowChangedTracker_h
+#define mozilla_OverflowChangedTracker_h
+
+#include "nsIFrame.h"
+#include "nsContainerFrame.h"
+#include "mozilla/SplayTree.h"
+
+namespace mozilla {
+
+/**
+ * Helper class that collects a list of frames that need
+ * UpdateOverflow() called on them, and coalesces them
+ * to avoid walking up the same ancestor tree multiple times.
+ */
+class OverflowChangedTracker
+{
+public:
+  enum ChangeKind {
+    /**
+     * The frame was explicitly added as a result of
+     * nsChangeHint_UpdatePostTransformOverflow and hence may have had a style
+     * change that changes its geometry relative to parent, without reflowing.
+     */
+    TRANSFORM_CHANGED,
+    /**
+     * The overflow areas of children have changed
+     * and we need to call UpdateOverflow on the frame.
+     */
+    CHILDREN_CHANGED,
+  };
+
+  OverflowChangedTracker() :
+    mSubtreeRoot(nullptr)
+  {}
+
+  ~OverflowChangedTracker()
+  {
+    NS_ASSERTION(mEntryList.empty(), "Need to flush before destroying!");
+  }
+
+  /**
+   * Add a frame that has had a style change, and needs its
+   * overflow updated.
+   *
+   * If there are pre-transform overflow areas stored for this
+   * frame, then we will call FinishAndStoreOverflow with those
+   * areas instead of UpdateOverflow().
+   *
+   * If the overflow area changes, then UpdateOverflow will also
+   * be called on the parent.
+   */
+  void AddFrame(nsIFrame* aFrame, ChangeKind aChangeKind) {
+    uint32_t depth = aFrame->GetDepthInFrameTree();
+    Entry *entry = nullptr;
+    if (!mEntryList.empty()) {
+      entry = mEntryList.find(Entry(aFrame, depth));
+    }
+    if (entry == nullptr) {
+      // Add new entry.
+      mEntryList.insert(new Entry(aFrame, depth, aChangeKind));
+    } else {
+      // Update the existing entry if the new value is stronger.
+      entry->mChangeKind = std::max(entry->mChangeKind, aChangeKind);
+    }
+  }
+
+  /**
+   * Remove a frame.
+   */
+  void RemoveFrame(nsIFrame* aFrame) {
+    if (mEntryList.empty()) {
+      return;
+    }
+
+    uint32_t depth = aFrame->GetDepthInFrameTree();
+    if (mEntryList.find(Entry(aFrame, depth))) {
+      delete mEntryList.remove(Entry(aFrame, depth));
+    }
+  }
+
+  /**
+   * Set the subtree root to limit overflow updates. This must be set if and
+   * only if currently reflowing aSubtreeRoot, to ensure overflow changes will
+   * still propagate correctly.
+   */
+  void SetSubtreeRoot(const nsIFrame* aSubtreeRoot) {
+    mSubtreeRoot = aSubtreeRoot;
+  }
+
+  /**
+   * Update the overflow of all added frames, and clear the entry list.
+   *
+   * Start from those deepest in the frame tree and works upwards. This stops
+   * us from processing the same frame twice.
+   */
+  void Flush() {
+    while (!mEntryList.empty()) {
+      Entry *entry = mEntryList.removeMin();
+      nsIFrame *frame = entry->mFrame;
+
+      bool overflowChanged = false;
+      if (entry->mChangeKind == CHILDREN_CHANGED) {
+        // Need to union the overflow areas of the children.
+        // Only update the parent if the overflow changes.
+        overflowChanged = frame->UpdateOverflow();
+      } else {
+        // Take a faster path that doesn't require unioning the overflow areas
+        // of our children.
+
+        NS_ASSERTION(frame->Properties().Get(
+                       nsIFrame::DebugInitialOverflowPropertyApplied()),
+                     "InitialOverflowProperty must be set first.");
+
+        nsOverflowAreas* overflow =
+          frame->Properties().Get(nsIFrame::InitialOverflowProperty());
+        if (overflow) {
+          // FinishAndStoreOverflow will change the overflow areas passed in,
+          // so make a copy.
+          nsOverflowAreas overflowCopy = *overflow;
+          frame->FinishAndStoreOverflow(overflowCopy, frame->GetSize());
+        } else {
+          nsRect bounds(nsPoint(0, 0), frame->GetSize());
+          nsOverflowAreas boundsOverflow;
+          boundsOverflow.SetAllTo(bounds);
+          frame->FinishAndStoreOverflow(boundsOverflow, bounds.Size());
+        }
+
+        // We can't tell if the overflow changed, so be conservative
+        overflowChanged = true;
+      }
+
+      // If the frame style changed (e.g. positioning offsets)
+      // then we need to update the parent with the overflow areas of its
+      // children.
+      if (overflowChanged) {
+        nsIFrame *parent = frame->GetParent();
+        if (parent && parent != mSubtreeRoot) {
+          Entry* parentEntry = mEntryList.find(Entry(parent, entry->mDepth - 1));
+          if (parentEntry) {
+            parentEntry->mChangeKind = std::max(parentEntry->mChangeKind, CHILDREN_CHANGED);
+          } else {
+            mEntryList.insert(new Entry(parent, entry->mDepth - 1, CHILDREN_CHANGED));
+          }
+        }
+      }
+      delete entry;
+    }
+  }
+
+private:
+  struct Entry : SplayTreeNode<Entry>
+  {
+    Entry(nsIFrame* aFrame, uint32_t aDepth, ChangeKind aChangeKind = CHILDREN_CHANGED)
+      : mFrame(aFrame)
+      , mDepth(aDepth)
+      , mChangeKind(aChangeKind)
+    {}
+
+    bool operator==(const Entry& aOther) const
+    {
+      return mFrame == aOther.mFrame;
+    }
+
+    /**
+     * Sort by *reverse* depth in the tree, and break ties with
+     * the frame pointer.
+     */
+    bool operator<(const Entry& aOther) const
+    {
+      if (mDepth == aOther.mDepth) {
+        return mFrame < aOther.mFrame;
+      }
+      return mDepth > aOther.mDepth; /* reverse, want "min" to be deepest */
+    }
+
+    static int compare(const Entry& aOne, const Entry& aTwo)
+    {
+      if (aOne == aTwo) {
+        return 0;
+      } else if (aOne < aTwo) {
+        return -1;
+      } else {
+        return 1;
+      }
+    }
+
+    nsIFrame* mFrame;
+    /* Depth in the frame tree */
+    uint32_t mDepth;
+    ChangeKind mChangeKind;
+  };
+
+  /* A list of frames to process, sorted by their depth in the frame tree */
+  SplayTree<Entry, Entry> mEntryList;
+
+  /* Don't update overflow of this frame or its ancestors. */
+  const nsIFrame* mSubtreeRoot;
+};
+
+} // namespace mozilla
+
+#endif
--- a/layout/base/RestyleTracker.h
+++ b/layout/base/RestyleTracker.h
@@ -7,16 +7,17 @@
  * A class which manages pending restyles.  This handles keeping track
  * of what nodes restyles need to happen on and so forth.
  */
 
 #ifndef mozilla_RestyleTracker_h
 #define mozilla_RestyleTracker_h
 
 #include "mozilla/dom/Element.h"
+#include "mozilla/OverflowChangedTracker.h"
 #include "nsAutoPtr.h"
 #include "nsClassHashtable.h"
 #include "nsContainerFrame.h"
 #include "mozilla/SplayTree.h"
 #include "mozilla/RestyleLogging.h"
 #include "GeckoProfiler.h"
 #include "mozilla/Maybe.h"
 
@@ -24,206 +25,16 @@
 #include "ProfilerBacktrace.h"
 #endif
 
 namespace mozilla {
 
 class RestyleManager;
 class ElementRestyler;
 
-/** 
- * Helper class that collects a list of frames that need
- * UpdateOverflow() called on them, and coalesces them
- * to avoid walking up the same ancestor tree multiple times.
- */
-class OverflowChangedTracker
-{
-public:
-  enum ChangeKind {
-    /**
-     * The frame was explicitly added as a result of
-     * nsChangeHint_UpdatePostTransformOverflow and hence may have had a style
-     * change that changes its geometry relative to parent, without reflowing.
-     */
-    TRANSFORM_CHANGED,
-    /**
-     * The overflow areas of children have changed
-     * and we need to call UpdateOverflow on the frame.
-     */
-    CHILDREN_CHANGED,
-  };
-
-  OverflowChangedTracker() :
-    mSubtreeRoot(nullptr)
-  {}
-
-  ~OverflowChangedTracker()
-  {
-    NS_ASSERTION(mEntryList.empty(), "Need to flush before destroying!");
-  }
-
-  /**
-   * Add a frame that has had a style change, and needs its
-   * overflow updated.
-   *
-   * If there are pre-transform overflow areas stored for this
-   * frame, then we will call FinishAndStoreOverflow with those
-   * areas instead of UpdateOverflow().
-   *
-   * If the overflow area changes, then UpdateOverflow will also
-   * be called on the parent.
-   */
-  void AddFrame(nsIFrame* aFrame, ChangeKind aChangeKind) {
-    uint32_t depth = aFrame->GetDepthInFrameTree();
-    Entry *entry = nullptr;
-    if (!mEntryList.empty()) {
-      entry = mEntryList.find(Entry(aFrame, depth));
-    }
-    if (entry == nullptr) {
-      // Add new entry.
-      mEntryList.insert(new Entry(aFrame, depth, aChangeKind));
-    } else {
-      // Update the existing entry if the new value is stronger.
-      entry->mChangeKind = std::max(entry->mChangeKind, aChangeKind);
-    }
-  }
-
-  /**
-   * Remove a frame.
-   */
-  void RemoveFrame(nsIFrame* aFrame) {
-    if (mEntryList.empty()) {
-      return;
-    }
-
-    uint32_t depth = aFrame->GetDepthInFrameTree();
-    if (mEntryList.find(Entry(aFrame, depth))) {
-      delete mEntryList.remove(Entry(aFrame, depth));
-    }
-  }
-
-  /**
-   * Set the subtree root to limit overflow updates. This must be set if and
-   * only if currently reflowing aSubtreeRoot, to ensure overflow changes will
-   * still propagate correctly.
-   */
-  void SetSubtreeRoot(const nsIFrame* aSubtreeRoot) {
-    mSubtreeRoot = aSubtreeRoot;
-  }
-
-  /**
-   * Update the overflow of all added frames, and clear the entry list.
-   *
-   * Start from those deepest in the frame tree and works upwards. This stops 
-   * us from processing the same frame twice.
-   */
-  void Flush() {
-    while (!mEntryList.empty()) {
-      Entry *entry = mEntryList.removeMin();
-      nsIFrame *frame = entry->mFrame;
-
-      bool overflowChanged = false;
-      if (entry->mChangeKind == CHILDREN_CHANGED) {
-        // Need to union the overflow areas of the children.
-        // Only update the parent if the overflow changes.
-        overflowChanged = frame->UpdateOverflow();
-      } else {
-        // Take a faster path that doesn't require unioning the overflow areas
-        // of our children.
-
-        NS_ASSERTION(frame->Properties().Get(
-                       nsIFrame::DebugInitialOverflowPropertyApplied()),
-                     "InitialOverflowProperty must be set first.");
-
-        nsOverflowAreas* overflow = 
-          frame->Properties().Get(nsIFrame::InitialOverflowProperty());
-        if (overflow) {
-          // FinishAndStoreOverflow will change the overflow areas passed in,
-          // so make a copy.
-          nsOverflowAreas overflowCopy = *overflow;
-          frame->FinishAndStoreOverflow(overflowCopy, frame->GetSize());
-        } else {
-          nsRect bounds(nsPoint(0, 0), frame->GetSize());
-          nsOverflowAreas boundsOverflow;
-          boundsOverflow.SetAllTo(bounds);
-          frame->FinishAndStoreOverflow(boundsOverflow, bounds.Size());
-        }
-
-        // We can't tell if the overflow changed, so be conservative
-        overflowChanged = true;
-      }
-
-      // If the frame style changed (e.g. positioning offsets)
-      // then we need to update the parent with the overflow areas of its
-      // children.
-      if (overflowChanged) {
-        nsIFrame *parent = frame->GetParent();
-        if (parent && parent != mSubtreeRoot) {
-          Entry* parentEntry = mEntryList.find(Entry(parent, entry->mDepth - 1));
-          if (parentEntry) {
-            parentEntry->mChangeKind = std::max(parentEntry->mChangeKind, CHILDREN_CHANGED);
-          } else {
-            mEntryList.insert(new Entry(parent, entry->mDepth - 1, CHILDREN_CHANGED));
-          }
-        }
-      }
-      delete entry;
-    }
-  }
-  
-private:
-  struct Entry : SplayTreeNode<Entry>
-  {
-    Entry(nsIFrame* aFrame, uint32_t aDepth, ChangeKind aChangeKind = CHILDREN_CHANGED)
-      : mFrame(aFrame)
-      , mDepth(aDepth)
-      , mChangeKind(aChangeKind)
-    {}
-
-    bool operator==(const Entry& aOther) const
-    {
-      return mFrame == aOther.mFrame;
-    }
- 
-    /**
-     * Sort by *reverse* depth in the tree, and break ties with
-     * the frame pointer.
-     */
-    bool operator<(const Entry& aOther) const
-    {
-      if (mDepth == aOther.mDepth) {
-        return mFrame < aOther.mFrame;
-      }
-      return mDepth > aOther.mDepth; /* reverse, want "min" to be deepest */
-    }
-
-    static int compare(const Entry& aOne, const Entry& aTwo)
-    {
-      if (aOne == aTwo) {
-        return 0;
-      } else if (aOne < aTwo) {
-        return -1;
-      } else {
-        return 1;
-      }
-    }
-
-    nsIFrame* mFrame;
-    /* Depth in the frame tree */
-    uint32_t mDepth;
-    ChangeKind mChangeKind;
-  };
-
-  /* A list of frames to process, sorted by their depth in the frame tree */
-  SplayTree<Entry, Entry> mEntryList;
-
-  /* Don't update overflow of this frame or its ancestors. */
-  const nsIFrame* mSubtreeRoot;
-};
-
 class RestyleTracker {
 public:
   typedef mozilla::dom::Element Element;
 
   friend class ElementRestyler; // for AddPendingRestyleToTable
 
   explicit RestyleTracker(Element::FlagsType aRestyleBits)
     : mRestyleBits(aRestyleBits)
--- a/layout/base/moz.build
+++ b/layout/base/moz.build
@@ -99,16 +99,17 @@ EXPORTS += [
     'WordMovementType.h',
 ]
 
 EXPORTS.mozilla += [
     'ArenaObjectID.h',
     'ArenaRefPtr.h',
     'ArenaRefPtrInlines.h',
     'GeometryUtils.h',
+    'OverflowChangedTracker.h',
     'PaintTracker.h',
     'RestyleLogging.h',
     'RestyleManager.h',
     'RestyleManagerBase.h',
     'RestyleManagerHandle.h',
     'RestyleManagerHandleInlines.h',
     'ServoRestyleManager.h',
     'StaticPresData.h',