Bug 1359341 part 3 - Propagate AreAllEarlierInFlowFramesEmpty() state on placeholders down the line. We can stop iterating siblings if we find a placeholder with a stored state. r=jfkthame
authorMats Palmgren <mats@mozilla.com>
Tue, 23 May 2017 19:09:27 +0200
changeset 360203 08e64a7a749562b2b857c51930d666e5bdda87e1
parent 360202 18e3dfae96fa6d6981f97311f33627b7b932bd59
child 360204 3cc5123e91476e84629230ede146c67ec60ecb6d
push id90599
push usermpalmgren@mozilla.com
push dateTue, 23 May 2017 17:09:38 +0000
treeherdermozilla-inbound@3cc5123e9147 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjfkthame
bugs1359341
milestone55.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 1359341 part 3 - Propagate AreAllEarlierInFlowFramesEmpty() state on placeholders down the line. We can stop iterating siblings if we find a placeholder with a stored state. r=jfkthame MozReview-Commit-ID: DNtcNIEwA5P
layout/generic/ReflowInput.cpp
layout/generic/nsBlockFrame.cpp
--- a/layout/generic/ReflowInput.cpp
+++ b/layout/generic/ReflowInput.cpp
@@ -1219,30 +1219,39 @@ ReflowInput::CalculateBorderPaddingMargi
   *aOutsideBoxSizing = outside;
   return;
 }
 
 /**
  * Returns true iff a pre-order traversal of the normal child
  * frames rooted at aFrame finds no non-empty frame before aDescendant.
  */
-static bool AreAllEarlierInFlowFramesEmpty(nsIFrame* aFrame,
-  nsIFrame* aDescendant, bool* aFound) {
+static bool
+AreAllEarlierInFlowFramesEmpty(nsIFrame* aFrame,
+                               nsIFrame* aDescendant,
+                               bool* aFound)
+{
   if (aFrame == aDescendant) {
     *aFound = true;
     return true;
   }
-  if (!aFrame->IsSelfEmpty()) {
-    *aFound = false;
-    return false;
-  }
-  for (nsIFrame* f : aFrame->PrincipalChildList()) {
-    bool allEmpty = AreAllEarlierInFlowFramesEmpty(f, aDescendant, aFound);
-    if (*aFound || !allEmpty) {
-      return allEmpty;
+  if (aFrame->IsPlaceholderFrame()) {
+    auto ph = static_cast<nsPlaceholderFrame*>(aFrame);
+    MOZ_ASSERT(ph->IsSelfEmpty() && ph->PrincipalChildList().IsEmpty());
+    ph->SetLineIsEmptySoFar(true);
+  } else {
+    if (!aFrame->IsSelfEmpty()) {
+      *aFound = false;
+      return false;
+    }
+    for (nsIFrame* f : aFrame->PrincipalChildList()) {
+      bool allEmpty = AreAllEarlierInFlowFramesEmpty(f, aDescendant, aFound);
+      if (*aFound || !allEmpty) {
+        return allEmpty;
+      }
     }
   }
   *aFound = false;
   return true;
 }
 
 // Calculate the position of the hypothetical box that the element would have
 // if it were in the flow.
@@ -1384,25 +1393,41 @@ ReflowInput::CalculateHypotheticalPositi
       } else {
         // The element would have been block-level which means it would
         // be below the line containing the placeholder frame, unless
         // all the frames before it are empty.  In that case, it would
         // have been just before this line.
         // XXXbz the line box is not fully reflowed yet if our
         // containing block is relatively positioned...
         if (lineBox != iter.End()) {
-          nsIFrame * firstFrame = lineBox->mFirstChild;
-          bool found = false;
-          bool allEmpty = true;
-          while (firstFrame) { // See bug 223064
-            allEmpty = AreAllEarlierInFlowFramesEmpty(firstFrame,
-              aPlaceholderFrame, &found);
-            if (found || !allEmpty)
-              break;
-            firstFrame = firstFrame->GetNextSibling();
+          nsIFrame* firstFrame = lineBox->mFirstChild;
+          bool allEmpty = false;
+          if (firstFrame == aPlaceholderFrame) {
+            aPlaceholderFrame->SetLineIsEmptySoFar(true);
+            allEmpty = true;
+          } else {
+            auto prev = aPlaceholderFrame->GetPrevSibling();
+            if (prev && prev->IsPlaceholderFrame()) {
+              auto ph = static_cast<nsPlaceholderFrame*>(prev);
+              if (ph->GetLineIsEmptySoFar(&allEmpty)) {
+                aPlaceholderFrame->SetLineIsEmptySoFar(allEmpty);
+              }
+            }
+          }
+          if (!allEmpty) {
+            bool found = false;
+            while (firstFrame) { // See bug 223064
+              allEmpty = AreAllEarlierInFlowFramesEmpty(firstFrame,
+                aPlaceholderFrame, &found);
+              if (found || !allEmpty) {
+                break;
+              }
+              firstFrame = firstFrame->GetNextSibling();
+            }
+            aPlaceholderFrame->SetLineIsEmptySoFar(allEmpty);
           }
           NS_ASSERTION(firstFrame, "Couldn't find placeholder!");
 
           if (allEmpty) {
             // The top of the hypothetical box is the top of the line
             // containing the placeholder, since there is nothing in the
             // line before our placeholder except empty frames.
             aHypotheticalPos.mBStart =
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -4204,16 +4204,21 @@ nsBlockFrame::ReflowInlineFrame(BlockRef
 #ifdef NOISY_FIRST_LETTER
   ListTag(stdout);
   printf(": reflowing ");
   nsFrame::ListTag(stdout, aFrame);
   printf(" reflowingFirstLetter=%s\n",
          aLineLayout.GetFirstLetterStyleOK() ? "on" : "off");
 #endif
 
+  if (aFrame->IsPlaceholderFrame()) {
+    auto ph = static_cast<nsPlaceholderFrame*>(aFrame);
+    ph->ForgetLineIsEmptySoFar();
+  }
+
   // Reflow the inline frame
   nsReflowStatus frameReflowStatus;
   bool           pushedFrame;
   aLineLayout.ReflowFrame(aFrame, frameReflowStatus, nullptr, pushedFrame);
 
   if (frameReflowStatus.NextInFlowNeedsReflow()) {
     aLineLayout.SetDirtyNextLine();
   }