Bug 871338: Handle NS_BLOCK_LOOK_FOR_DIRTY_FRAMES lazy marking in GetMinWidth and GetPrefWidth in addition to Reflow. r=bzbarsky
authorL. David Baron <dbaron@dbaron.org>
Mon, 13 May 2013 15:37:00 -0700
changeset 131829 cae4d57e0e8b274ea920137b3bb718424105a1a7
parent 131828 3ddc53c35f33ec333f64731341da07508a7f94e7
child 131830 261e3e928ce98b0e6c4e42941d1c5b2c09647277
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersbzbarsky
bugs871338
milestone24.0a1
Bug 871338: Handle NS_BLOCK_LOOK_FOR_DIRTY_FRAMES lazy marking in GetMinWidth and GetPrefWidth in addition to Reflow. r=bzbarsky
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockFrame.h
layout/reftests/bugs/871338-1-ref.html
layout/reftests/bugs/871338-1.html
layout/reftests/bugs/reftest.list
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -636,16 +636,21 @@ nsBlockFrame::GetMinWidth(nsRenderingCon
   if (gNoisyIntrinsic) {
     IndentBy(stdout, gNoiseIndent);
     ListTag(stdout);
     printf(": GetMinWidth\n");
   }
   AutoNoisyIndenter indenter(gNoisyIntrinsic);
 #endif
 
+  for (nsBlockFrame* curFrame = this; curFrame;
+       curFrame = static_cast<nsBlockFrame*>(curFrame->GetNextContinuation())) {
+    curFrame->LazyMarkLinesDirty();
+  }
+
   if (GetStateBits() & NS_BLOCK_NEEDS_BIDI_RESOLUTION)
     ResolveBidi();
   InlineMinWidthData data;
   for (nsBlockFrame* curFrame = this; curFrame;
        curFrame = static_cast<nsBlockFrame*>(curFrame->GetNextContinuation())) {
     for (line_iterator line = curFrame->begin_lines(), line_end = curFrame->end_lines();
       line != line_end; ++line)
     {
@@ -716,16 +721,21 @@ nsBlockFrame::GetPrefWidth(nsRenderingCo
   if (gNoisyIntrinsic) {
     IndentBy(stdout, gNoiseIndent);
     ListTag(stdout);
     printf(": GetPrefWidth\n");
   }
   AutoNoisyIndenter indenter(gNoisyIntrinsic);
 #endif
 
+  for (nsBlockFrame* curFrame = this; curFrame;
+       curFrame = static_cast<nsBlockFrame*>(curFrame->GetNextContinuation())) {
+    curFrame->LazyMarkLinesDirty();
+  }
+
   if (GetStateBits() & NS_BLOCK_NEEDS_BIDI_RESOLUTION)
     ResolveBidi();
   InlinePrefWidthData data;
   for (nsBlockFrame* curFrame = this; curFrame;
        curFrame = static_cast<nsBlockFrame*>(curFrame->GetNextContinuation())) {
     for (line_iterator line = curFrame->begin_lines(), line_end = curFrame->end_lines();
          line != line_end; ++line)
     {
@@ -988,31 +998,17 @@ nsBlockFrame::Reflow(nsPresContext*     
 
   // If we're not dirty (which means we'll mark everything dirty later)
   // and our width has changed, mark the lines dirty that we need to
   // mark dirty for a resize reflow.
   if (!(GetStateBits() & NS_FRAME_IS_DIRTY) && reflowState->mFlags.mHResize) {
     PrepareResizeReflow(state);
   }
 
-  if (GetStateBits() & NS_BLOCK_LOOK_FOR_DIRTY_FRAMES) {
-    for (line_iterator line = begin_lines(), line_end = end_lines();
-         line != line_end; ++line) {
-      int32_t n = line->GetChildCount();
-      for (nsIFrame* lineFrame = line->mFirstChild;
-           n > 0; lineFrame = lineFrame->GetNextSibling(), --n) {
-        if (NS_SUBTREE_DIRTY(lineFrame)) {
-          // NOTE:  MarkLineDirty does more than just marking the line dirty.
-          MarkLineDirty(line, &mLines);
-          break;
-        }
-      }
-    }
-    RemoveStateBits(NS_BLOCK_LOOK_FOR_DIRTY_FRAMES);
-  }
+  LazyMarkLinesDirty();
 
   mState &= ~NS_FRAME_FIRST_REFLOW;
 
   // Now reflow...
   rv = ReflowDirtyLines(state);
 
   // If we have a next-in-flow, and that next-in-flow has pushed floats from
   // this frame from a previous iteration of reflow, then we should not return
@@ -1505,16 +1501,36 @@ nsBlockFrame::UpdateOverflow()
 
     line->SetOverflowAreas(lineAreas);
   }
 
   return nsBlockFrameSuper::UpdateOverflow();
 }
 
 void
+nsBlockFrame::LazyMarkLinesDirty()
+{
+  if (GetStateBits() & NS_BLOCK_LOOK_FOR_DIRTY_FRAMES) {
+    for (line_iterator line = begin_lines(), line_end = end_lines();
+         line != line_end; ++line) {
+      int32_t n = line->GetChildCount();
+      for (nsIFrame* lineFrame = line->mFirstChild;
+           n > 0; lineFrame = lineFrame->GetNextSibling(), --n) {
+        if (NS_SUBTREE_DIRTY(lineFrame)) {
+          // NOTE:  MarkLineDirty does more than just marking the line dirty.
+          MarkLineDirty(line, &mLines);
+          break;
+        }
+      }
+    }
+    RemoveStateBits(NS_BLOCK_LOOK_FOR_DIRTY_FRAMES);
+  }
+}
+
+void
 nsBlockFrame::MarkLineDirty(line_iterator aLine, const nsLineList* aLineList)
 {
   // Mark aLine dirty
   aLine->MarkDirty();
   aLine->SetInvalidateTextRuns(true);
 #ifdef DEBUG
   if (gNoisyReflow) {
     IndentBy(stdout, gNoiseIndent);
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -607,16 +607,22 @@ protected:
                    nsLineLayout&       aLineLayout,
                    line_iterator       aLine,
                    nsFloatManager::SavedState* aFloatStateBeforeLine,
                    nsRect&             aFloatAvailableSpace, /* in-out */
                    nscoord&            aAvailableSpaceHeight, /* in-out */
                    bool*             aKeepReflowGoing);
 
   /**
+    * If NS_BLOCK_LOOK_FOR_DIRTY_FRAMES is set, call MarkLineDirty
+    * on any line with a child frame that is dirty.
+    */
+  void LazyMarkLinesDirty();
+
+  /**
    * Mark |aLine| dirty, and, if necessary because of possible
    * pull-up, mark the previous line dirty as well. Also invalidates textruns
    * on those lines because the text in the lines might have changed due to
    * addition/removal of frames.
    * @param aLine the line to mark dirty
    * @param aLineList the line list containing that line
    */
   void MarkLineDirty(line_iterator aLine, const nsLineList* aLineList);
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/871338-1-ref.html
@@ -0,0 +1,1 @@
+<!DOCTYPE html><body><div style="float: right"><span> <span id="comment-buttons-tools" style="display:inline-block">Report</span></span> <span>HoverMe</span></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/871338-1.html
@@ -0,0 +1,1 @@
+<!DOCTYPE html><body onload="document.getElementById('comment-buttons-tools').style.display='inline-block'"><div style="float: right"><span> <span id="comment-buttons-tools" style="display:none">Report</span></span> <span>HoverMe</span></div>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1753,8 +1753,9 @@ fails-if(Android) == 836844-1.html 83684
 == 844178.html 844178-ref.html
 == 846144-1.html 846144-1-ref.html
 == 847850-1.html 847850-1-ref.html
 == 848421-1.html 848421-1-ref.html
 test-pref(layout.css.flexbox.enabled,true) == 849407-1.html 849407-1-ref.html
 == 849996-1.html 849996-1-ref.html
 == 858803-1.html 858803-1-ref.html
 != 860370.html 860370-notref.html
+== 871338-1.html 871338-1-ref.html