Bug 1484306 Part 1 - Add nsFrameList::FrameLinkEnumerator::Find(). r=dholbert
authorTing-Yu Lin <tlin@mozilla.com>
Tue, 14 Aug 2018 13:00:48 -0700
changeset 487336 82e6a73d898550923ba779aac4f5c39d4b04dc8d
parent 487335 3575c52180c438aa9689e3522e235272fbd1fc2c
child 487337 3b91ab5a0554cfd1f9aca2ca768a3605cf908cfe
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1484306
milestone63.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 1484306 Part 1 - Add nsFrameList::FrameLinkEnumerator::Find(). r=dholbert Use it to implement FindFirstBlock() and FindFirstNonBlock(). This is a demonstration on how Find() is used. The usage of them will be overhauled in Part 2 and 3. Differential Revision: https://phabricator.services.mozilla.com/D3642
layout/base/nsCSSFrameConstructor.cpp
layout/generic/nsFrameList.h
layout/generic/nsIFrame.h
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -636,35 +636,27 @@ ParentIsWrapperAnonBox(nsIFrame* aParent
 // parent (the inline frames containing block is where it will end up).
 
 // After this function returns, aLink is pointing to the first link at or
 // after its starting position for which the next frame is a block.  If there
 // is no such link, it points to the end of the list.
 static void
 FindFirstBlock(nsFrameList::FrameLinkEnumerator& aLink)
 {
-  for ( ; !aLink.AtEnd(); aLink.Next()) {
-    if (!aLink.NextFrame()->IsInlineOutside()) {
-      return;
-    }
-  }
+  aLink.Find([](nsIFrame* aFrame) { return !aFrame->IsInlineOutside(); });
 }
 
 // This function returns a frame link enumerator pointing to the first link in
 // the list for which the next frame is not block.  If there is no such link,
 // it points to the end of the list.
 static nsFrameList::FrameLinkEnumerator
 FindFirstNonBlock(const nsFrameList& aList)
 {
   nsFrameList::FrameLinkEnumerator link(aList);
-  for (; !link.AtEnd(); link.Next()) {
-    if (link.NextFrame()->IsInlineOutside()) {
-      break;
-    }
-  }
+  link.Find([](nsIFrame* aFrame) { return aFrame->IsInlineOutside(); });
   return link;
 }
 
 inline void
 SetInitialSingleChild(nsContainerFrame* aParent, nsIFrame* aFrame)
 {
   MOZ_ASSERT(!aFrame->GetNextSibling(), "Should be using a frame list");
   nsFrameList temp(aFrame, aFrame);
--- a/layout/generic/nsFrameList.h
+++ b/layout/generic/nsFrameList.h
@@ -460,16 +460,29 @@ public:
     void operator=(const FrameLinkEnumerator& aOther) {
       MOZ_ASSERT(&List() == &aOther.List(), "Different lists?");
       mFrame = aOther.mFrame;
       mPrev = aOther.mPrev;
     }
 
     inline void Next();
 
+    /**
+     * Find the first frame from the current position that satisfies
+     * aPredicate, and stop at it. If no such frame exists, then this method
+     * advances to the end of the list.
+     *
+     * aPredicate should be of this function signature: bool(nsIFrame*).
+     *
+     * Note: Find() needs to see the definition of Next(), so put this
+     * definition in nsIFrame.h.
+     */
+    template<typename Predicate>
+    inline void Find(Predicate&& aPredicate);
+
     bool AtEnd() const { return Enumerator::AtEnd(); }
 
     nsIFrame* PrevFrame() const { return mPrev; }
     nsIFrame* NextFrame() const { return mFrame; }
 
   protected:
     nsIFrame* mPrev;
   };
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -4768,16 +4768,27 @@ FrameLinkEnumerator(const nsFrameList& a
 
 inline void
 nsFrameList::FrameLinkEnumerator::Next()
 {
   mPrev = mFrame;
   Enumerator::Next();
 }
 
+template<typename Predicate>
+inline void
+nsFrameList::FrameLinkEnumerator::Find(Predicate&& aPredicate)
+{
+  for (; !AtEnd(); Next()) {
+    if (aPredicate(mFrame)) {
+      return;
+    }
+  }
+}
+
 // Operators of nsFrameList::Iterator
 // ---------------------------------------------------
 
 inline nsFrameList::Iterator&
 nsFrameList::Iterator::operator++()
 {
   mCurrent = mCurrent->GetNextSibling();
   return *this;