Bug 911786 - Part 2: Reapply relative positioning when moving frames without reflowing them. r=dholbert
authorCorey Ford <cford@mozilla.com>
Wed, 11 Sep 2013 11:51:42 -0700
changeset 146766 bf930e7d61d388f864f9e22d5446d672dc0b5870
parent 146765 f304767ded19005e9d08c2e427a001b22006f381
child 146767 3a27531afc85b22031e1ba6b7febdb9951b75a0b
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersdholbert
bugs911786
milestone26.0a1
Bug 911786 - Part 2: Reapply relative positioning when moving frames without reflowing them. r=dholbert
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockReflowState.cpp
layout/generic/nsFrame.cpp
layout/generic/nsIFrame.h
layout/generic/nsLineLayout.cpp
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -2577,35 +2577,31 @@ nsBlockFrame::SlideLine(nsBlockReflowSta
   // Adjust the frames in the line
   nsIFrame* kid = aLine->mFirstChild;
   if (!kid) {
     return;
   }
 
   if (aLine->IsBlock()) {
     if (aDY) {
-      nsPoint p = kid->GetPosition();
-      p.y += aDY;
-      kid->SetPosition(p);
+      kid->MovePositionBy(nsPoint(0, aDY));
     }
 
     // Make sure the frame's view and any child views are updated
     ::PlaceFrameView(kid);
   }
   else {
     // Adjust the Y coordinate of the frames in the line.
     // Note: we need to re-position views even if aDY is 0, because
     // one of our parent frames may have moved and so the view's position
     // relative to its parent may have changed
     int32_t n = aLine->GetChildCount();
     while (--n >= 0) {
       if (aDY) {
-        nsPoint p = kid->GetPosition();
-        p.y += aDY;
-        kid->SetPosition(p);
+        kid->MovePositionBy(nsPoint(0, aDY));
       }
       // Make sure the frame's view and any child views are updated
       ::PlaceFrameView(kid);
       kid = kid->GetNextSibling();
     }
   }
 }
 
--- a/layout/generic/nsBlockReflowState.cpp
+++ b/layout/generic/nsBlockReflowState.cpp
@@ -381,18 +381,17 @@ nsBlockReflowState::RecoverFloats(nsLine
 {
   if (aLine->HasFloats()) {
     // Place the floats into the space-manager again. Also slide
     // them, just like the regular frames on the line.
     nsFloatCache* fc = aLine->GetFirstFloat();
     while (fc) {
       nsIFrame* floatFrame = fc->mFloat;
       if (aDeltaY != 0) {
-        nsPoint p = floatFrame->GetPosition();
-        floatFrame->SetPosition(nsPoint(p.x, p.y + aDeltaY));
+        floatFrame->MovePositionBy(nsPoint(0, aDeltaY));
         nsContainerFrame::PositionFrameView(floatFrame);
         nsContainerFrame::PositionChildViews(floatFrame);
       }
 #ifdef DEBUG
       if (nsBlockFrame::gNoisyReflow || nsBlockFrame::gNoisyFloatManager) {
         nscoord tx, ty;
         mFloatManager->GetTranslation(tx, ty);
         nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -5065,16 +5065,32 @@ ComputeOutlineAndEffectsRect(nsIFrame* a
         Set(nsIFrame::PreEffectsBBoxProperty(), new nsRect(r));
     }
     r = nsSVGIntegrationUtils::ComputePostEffectsVisualOverflowRect(aFrame, r);
   }
 
   return r;
 }
 
+void
+nsIFrame::MovePositionBy(const nsPoint& aTranslation)
+{
+  nsPoint position = GetNormalPosition() + aTranslation;
+
+  const nsMargin* computedOffsets = nullptr;
+  if (IsRelativelyPositioned()) {
+    computedOffsets = static_cast<nsMargin*>
+      (Properties().Get(nsIFrame::ComputedOffsetProperty()));
+  }
+  nsHTMLReflowState::ApplyRelativePositioning(this, computedOffsets ?
+                                              *computedOffsets : nsMargin(),
+                                              &position);
+  SetPosition(position);
+}
+
 nsPoint
 nsIFrame::GetNormalPosition() const
 {
   // It might be faster to first check
   // StyleDisplay()->IsRelativelyPositionedStyle().
   nsPoint* normalPosition = static_cast<nsPoint*>
     (Properties().Get(NormalPositionProperty()));
   if (normalPosition) {
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -862,16 +862,23 @@ public:
     }
   }
   void SetSize(const nsSize& aSize) {
     SetRect(nsRect(mRect.TopLeft(), aSize));
   }
   void SetPosition(const nsPoint& aPt) { mRect.MoveTo(aPt); }
 
   /**
+   * Move the frame, accounting for relative positioning. Use this when
+   * adjusting the frame's position by a known amount, to properly update its
+   * saved normal position (see GetNormalPosition below).
+   */
+  void MovePositionBy(const nsPoint& aTranslation);
+
+  /**
    * Return frame's position without relative positioning
    */
   nsPoint GetNormalPosition() const;
 
   virtual nsPoint GetPositionOfChildIgnoringScrolling(nsIFrame* aChild)
   { return aChild->GetPosition(); }
   
   nsPoint GetPositionIgnoringScrolling() {
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -2191,19 +2191,17 @@ nsLineLayout::VerticalAlignFrames(PerSpa
   }
   if (maxBottomBoxHeight > mMaxBottomBoxHeight) {
     mMaxBottomBoxHeight = maxBottomBoxHeight;
   }
 }
 
 static void SlideSpanFrameRect(nsIFrame* aFrame, nscoord aDeltaWidth)
 {
-  nsRect r = aFrame->GetRect();
-  r.x -= aDeltaWidth;
-  aFrame->SetRect(r);
+  aFrame->MovePositionBy(nsPoint(-aDeltaWidth, 0));
 }
 
 bool
 nsLineLayout::TrimTrailingWhiteSpaceIn(PerSpanData* psd,
                                        nscoord* aDeltaWidth)
 {
 #ifndef IBMBIDI
 // XXX what about NS_STYLE_DIRECTION_RTL?