Bug 795592 - Stop calling nsIFrame::FinishAndStoreOverflow on NS_STATE_SVG_NONDISPLAY_CHILD frames. r=mattwoodrow, a=lsblakk
authorJonathan Watt <jwatt@jwatt.org>
Fri, 26 Oct 2012 11:56:48 +0100
changeset 116534 563063ce23e6e0777e472ed71ca117db6103f6f5
parent 116533 1e93f23070ab89f7f98c88a937e2abaf3fbd24ae
child 116535 f912173e885c967b8b47c88c2813e3edcf25f3b3
push id1708
push userakeybl@mozilla.com
push dateMon, 19 Nov 2012 21:10:21 +0000
treeherdermozilla-beta@27b14fe50103 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow, lsblakk
bugs795592
milestone18.0a2
Bug 795592 - Stop calling nsIFrame::FinishAndStoreOverflow on NS_STATE_SVG_NONDISPLAY_CHILD frames. r=mattwoodrow, a=lsblakk
layout/base/nsCSSFrameConstructor.cpp
layout/generic/nsFrame.cpp
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -8125,16 +8125,25 @@ nsCSSFrameConstructor::ProcessRestyledFr
       // If we ever start passing true here, be careful of restyles
       // that involve a reframe and animations.  In particular, if the
       // restyle we're processing here is an animation restyle, but
       // the style resolution we will do for the frame construction
       // happens async when we're not in an animation restyle already,
       // problems could arise.
       RecreateFramesForContent(content, false);
     } else {
+      if ((frame->GetStateBits() & NS_FRAME_SVG_LAYOUT) &&
+          (frame->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
+        // frame does not maintain overflow rects, so avoid calling
+        // FinishAndStoreOverflow on it:
+        hint = NS_SubtractHint(hint,
+                 NS_CombineHint(nsChangeHint_UpdateOverflow,
+                                nsChangeHint_ChildrenOnlyTransform));
+      }
+
       NS_ASSERTION(frame, "This shouldn't happen");
       if (hint & nsChangeHint_UpdateEffects) {
         nsSVGEffects::UpdateEffects(frame);
       }
       if (hint & nsChangeHint_NeedReflow) {
         StyleChangeReflow(frame, hint);
         didReflow = true;
       }
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -6847,16 +6847,20 @@ IsInlineFrame(nsIFrame *aFrame)
   nsIAtom *type = aFrame->GetType();
   return type == nsGkAtoms::inlineFrame;
 }
 
 bool
 nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
                                  nsSize aNewSize)
 {
+  NS_ASSERTION(!((GetStateBits() & NS_FRAME_SVG_LAYOUT) &&
+                 (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)),
+               "Don't call - overflow rects not maintain on these SVG frames");
+
   nsRect bounds(nsPoint(0, 0), aNewSize);
   // Store the passed in overflow area if we are a preserve-3d frame,
   // and it's not just the frame bounds.
   if ((Preserves3D() || HasPerspective()) && (!aOverflowAreas.VisualOverflow().IsEqualEdges(bounds) ||
                         !aOverflowAreas.ScrollableOverflow().IsEqualEdges(bounds))) {
     nsOverflowAreas* initial =
       static_cast<nsOverflowAreas*>(Properties().Get(nsIFrame::InitialOverflowProperty()));
     if (!initial) {
@@ -7023,31 +7027,38 @@ nsIFrame::RecomputePerspectiveChildrenOv
   if (aBounds) {
     SetSize(aBounds->Size());
   }
   nsIFrame::ChildListIterator lists(this);
   for (; !lists.IsDone(); lists.Next()) {
     nsFrameList::Enumerator childFrames(lists.CurrentList());
     for (; !childFrames.AtEnd(); childFrames.Next()) {
       nsIFrame* child = childFrames.get();
+      if ((child->GetStateBits() & NS_FRAME_SVG_LAYOUT) &&
+          (child->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
+        continue; // frame does not maintain overflow rects
+      }
       if (child->HasPerspective()) {
         nsOverflowAreas* overflow = 
           static_cast<nsOverflowAreas*>(child->Properties().Get(nsIFrame::InitialOverflowProperty()));
         nsRect bounds(nsPoint(0, 0), child->GetSize());
         if (overflow) {
           child->FinishAndStoreOverflow(*overflow, bounds.Size());
         } else {
           nsOverflowAreas boundsOverflow;
           boundsOverflow.SetAllTo(bounds);
           child->FinishAndStoreOverflow(boundsOverflow, bounds.Size());
         }
       } else if (child->GetStyleContext()->GetParent() == aStartStyle ||
                  child->GetStyleContext() == aStartStyle) {
-        // Recurse into frames with the same style context, or a direct
-        // child style context.
+        // If a frame is using perspective, then the size used to compute
+        // perspective-origin is the size of the frame belonging to its parent
+        // style context. We must find any descendant frames using our size
+        // (by recurse into frames with the same style context, or a direct
+        // child style context) to update their overflow rects too.
         child->RecomputePerspectiveChildrenOverflow(aStartStyle, nullptr);
       }
     }
   }
   // Restore our old size just in case something depends on this elesewhere.
   SetSize(oldSize);
 }
 
@@ -7065,16 +7076,20 @@ RecomputePreserve3DChildrenOverflow(nsIF
   if (aBounds) {
     aFrame->SetSize(aBounds->Size());
   }
   nsIFrame::ChildListIterator lists(aFrame);
   for (; !lists.IsDone(); lists.Next()) {
     nsFrameList::Enumerator childFrames(lists.CurrentList());
     for (; !childFrames.AtEnd(); childFrames.Next()) {
       nsIFrame* child = childFrames.get();
+      if ((child->GetStateBits() & NS_FRAME_SVG_LAYOUT) &&
+          (child->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
+        continue; // frame does not maintain overflow rects
+      }
       if (child->Preserves3DChildren()) {
         RecomputePreserve3DChildrenOverflow(child, NULL);
       } else if (child->Preserves3D()) {
         nsOverflowAreas* overflow = 
           static_cast<nsOverflowAreas*>(child->Properties().Get(nsIFrame::InitialOverflowProperty()));
         nsRect bounds(nsPoint(0, 0), child->GetSize());
         if (overflow) {
           child->FinishAndStoreOverflow(*overflow, bounds.Size());