Bug 501847 part 2. Make various consumers deal with more than 2 inlines in an {ib} split. r=tn, sr=roc
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 18 Sep 2009 14:00:21 -0400
changeset 34460 61febc552982947a427f065b4b9e470638b9fa9e
parent 34459 35ba5ef187786693ff4fce55530c63158ac79109
child 34461 ce946663a30ae4855fa79d7e54476f4d3f6694e1
push id10058
push userbzbarsky@mozilla.com
push dateMon, 02 Nov 2009 03:43:27 +0000
treeherdermozilla-central@0f12f3edad42 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstn, roc
bugs501847
milestone1.9.3a1pre
Bug 501847 part 2. Make various consumers deal with more than 2 inlines in an {ib} split. r=tn, sr=roc
layout/base/nsBidiPresUtils.cpp
layout/base/nsFrameManager.cpp
layout/base/nsLayoutUtils.h
layout/generic/nsInlineFrame.cpp
layout/generic/nsLineLayout.cpp
--- a/layout/base/nsBidiPresUtils.cpp
+++ b/layout/base/nsBidiPresUtils.cpp
@@ -913,28 +913,29 @@ nsBidiPresUtils::IsLeftOrRightMost(nsIFr
   }
 
   aIsRightMost = (firstFrameState->mFrameCount == 1) &&
                  (isLTR ? !firstFrameState->mHasContOnNextLines
                         : !firstFrameState->mHasContOnPrevLines);
 
   if ((aIsLeftMost || aIsRightMost) &&
       (aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL)) {
-    // For ib splits, don't treat the first part as endmost or the
-    // last part as startmost.
-    if (nsLayoutUtils::FrameIsInFirstPartOfIBSplit(aFrame)) {
+    // For ib splits, don't treat anything except the last part as
+    // endmost or anything except the first part as startmost.
+    // As an optimization, only get the first continuation once.
+    nsIFrame* firstContinuation = aFrame->GetFirstContinuation();
+    if (nsLayoutUtils::FrameIsNonLastInIBSplit(firstContinuation)) {
       // We are not endmost
       if (isLTR) {
         aIsRightMost = PR_FALSE;
       } else {
         aIsLeftMost = PR_FALSE;
       }
-    } else {
-      NS_ASSERTION(nsLayoutUtils::FrameIsInLastPartOfIBSplit(aFrame),
-                   "How did that happen?");
+    }
+    if (nsLayoutUtils::FrameIsNonFirstInIBSplit(firstContinuation)) {
       // We are not startmost
       if (isLTR) {
         aIsLeftMost = PR_FALSE;
       } else {
         aIsRightMost = PR_FALSE;
       }
     }
   }
@@ -1057,17 +1058,17 @@ nsBidiPresUtils::RepositionInlineFrames(
   PRBool isLTR = (NS_STYLE_DIRECTION_LTR == vis->mDirection);
   nscoord leftSpace = 0;
 
   // This method is called from nsBlockFrame::PlaceLine via the call to
   // bidiUtils->ReorderFrames, so this is guaranteed to be after the inlines
   // have been reflowed, which is required for GetUsedMargin/Border/Padding
   nsMargin margin = aFirstChild->GetUsedMargin();
   if (!aFirstChild->GetPrevContinuation() &&
-      !nsLayoutUtils::FrameIsInLastPartOfIBSplit(aFirstChild))
+      !nsLayoutUtils::FrameIsNonFirstInIBSplit(aFirstChild))
     leftSpace = isLTR ? margin.left : margin.right;
 
   nscoord left = aFirstChild->GetPosition().x - leftSpace;
   nsIFrame* frame;
   PRInt32 count = mVisualFrames.Length();
   PRInt32 index;
   nsContinuationStates continuationStates;
 
--- a/layout/base/nsFrameManager.cpp
+++ b/layout/base/nsFrameManager.cpp
@@ -984,21 +984,21 @@ nsFrameManager::ReParentStyleContext(nsI
       newParentContext = providerFrame->GetStyleContext();
       providerChild = providerFrame;
     } else if (providerFrame) {
       newParentContext = providerFrame->GetStyleContext();
     } else {
       NS_NOTREACHED("Reparenting something that has no usable parent? "
                     "Shouldn't happen!");
     }
-    // XXX need to do something here to produce the correct style context
-    // for an IB split whose first inline part is inside a first-line frame.
-    // Currently the IB anonymous block's style context takes the first part's
-    // style context as parent, which is wrong since first-line style should
-    // not apply to the anonymous block.
+    // XXX need to do something here to produce the correct style context for
+    // an IB split whose first inline part is inside a first-line frame.
+    // Currently the first IB anonymous block's style context takes the first
+    // part's style context as parent, which is wrong since first-line style
+    // should not apply to the anonymous block.
 
 #ifdef DEBUG
     {
       // Check that our assumption that continuations of the same
       // pseudo-type and with the same style context parent have the
       // same style context is valid before the reresolution.  (We need
       // to check the pseudo-type and style context parent because of
       // :first-letter and :first-line, where we create styled and
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -1057,32 +1057,32 @@ public:
 
   /**
    * Returns the text fragment, which aFrame should use for printing.
    * @param aFrame The nsIFrame object, which uses text fragment data.
    */
   static nsTextFragment* GetTextFragmentForPrinting(const nsIFrame* aFrame);
 
   /**
-   * Return whether aFrame is an inline frame in the first part of an {ib}
-   * split.
+   * Return true if aFrame is in an {ib} split and is NOT one of the
+   * continuations of the first inline in it.
    */
-  static PRBool FrameIsInFirstPartOfIBSplit(const nsIFrame* aFrame) {
+  static PRBool FrameIsNonFirstInIBSplit(const nsIFrame* aFrame) {
     return (aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL) &&
-      !aFrame->GetFirstContinuation()->
+      aFrame->GetFirstContinuation()->
         GetProperty(nsGkAtoms::IBSplitSpecialPrevSibling);
   }
 
   /**
-   * Return whether aFrame is an inline frame in the last part of an {ib}
-   * split.
+   * Return true if aFrame is in an {ib} split and is NOT one of the
+   * continuations of the last inline in it.
    */
-  static PRBool FrameIsInLastPartOfIBSplit(const nsIFrame* aFrame) {
+  static PRBool FrameIsNonLastInIBSplit(const nsIFrame* aFrame) {
     return (aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL) &&
-      !aFrame->GetFirstContinuation()->
+      aFrame->GetFirstContinuation()->
         GetProperty(nsGkAtoms::IBSplitSpecialSibling);
   }
 
   /**
    * Obtain a gfxASurface from the given DOM element, if possible.
    * This obtains the most natural surface from the element; that
    * is, the one that can be obtained with the fewest conversions.
    *
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -429,19 +429,19 @@ nsInlineFrame::ReflowFrames(nsPresContex
 {
   nsresult rv = NS_OK;
   aStatus = NS_FRAME_COMPLETE;
 
   nsLineLayout* lineLayout = aReflowState.mLineLayout;
   PRBool ltr = (NS_STYLE_DIRECTION_LTR == aReflowState.mStyleVisibility->mDirection);
   nscoord leftEdge = 0;
   // Don't offset by our start borderpadding if we have a prev continuation or
-  // if we're in the last part of an {ib} split.
+  // if we're in a part of an {ib} split other than the first one.
   if (!GetPrevContinuation() &&
-      !nsLayoutUtils::FrameIsInLastPartOfIBSplit(this)) {
+      !nsLayoutUtils::FrameIsNonFirstInIBSplit(this)) {
     leftEdge = ltr ? aReflowState.mComputedBorderPadding.left
                    : aReflowState.mComputedBorderPadding.right;
   }
   nscoord availableWidth = aReflowState.availableWidth;
   NS_ASSERTION(availableWidth != NS_UNCONSTRAINEDSIZE,
                "should no longer use available widths");
   // Subtract off left and right border+padding from availableWidth
   availableWidth -= leftEdge;
@@ -580,32 +580,34 @@ nsInlineFrame::ReflowFrames(nsPresContex
   // line-height calculations. However, continuations of an inline
   // that are empty we force to empty so that things like collapsed
   // whitespace in an inline element don't affect the line-height.
   aMetrics.width = lineLayout->EndSpan(this);
 
   // Compute final width.
 
   // Make sure to not include our start border and padding if we have a prev
-  // continuation or if we're in the last part of an {ib} split.
+  // continuation or if we're in a part of an {ib} split other than the first
+  // one.
   if (!GetPrevContinuation() &&
-      !nsLayoutUtils::FrameIsInLastPartOfIBSplit(this)) {
+      !nsLayoutUtils::FrameIsNonFirstInIBSplit(this)) {
     aMetrics.width += ltr ? aReflowState.mComputedBorderPadding.left
                           : aReflowState.mComputedBorderPadding.right;
   }
 
   /*
    * We want to only apply the end border and padding if we're the last
-   * continuation and not in the first part of an {ib} split.  To be the last
-   * continuation we have to be complete (so that we won't get a next-in-flow)
-   * and have no non-fluid continuations on our continuation chain.
+   * continuation and either not in an {ib} split or the last part of it.  To
+   * be the last continuation we have to be complete (so that we won't get a
+   * next-in-flow) and have no non-fluid continuations on our continuation
+   * chain.
    */
   if (NS_FRAME_IS_COMPLETE(aStatus) &&
       !GetLastInFlow()->GetNextContinuation() &&
-      !nsLayoutUtils::FrameIsInFirstPartOfIBSplit(this)) {
+      !nsLayoutUtils::FrameIsNonLastInIBSplit(this)) {
     aMetrics.width += ltr ? aReflowState.mComputedBorderPadding.right
                           : aReflowState.mComputedBorderPadding.left;
   }
 
   nsLayoutUtils::SetFontFromStyle(aReflowState.rendContext, mStyleContext);
   nsCOMPtr<nsIFontMetrics> fm;
   aReflowState.rendContext->GetFontMetrics(*getter_AddRefs(fm));
 
@@ -826,31 +828,32 @@ nsInlineFrame::GetSkipSides() const
     }
     else {
       // If the next continuation is empty, then go ahead and let our right
       // edge border render.
     }
   }
 
   if (GetStateBits() & NS_FRAME_IS_SPECIAL) {
-    // The first part of an {ib} split should always skip the "end" side (as
-    // determined by this frame's direction) and the last part of such a split
-    // should alwas skip the "start" side.  But figuring out which part of the
-    // split we are involves getting our first continuation, which might be
+    // All but the last part of an {ib} split should skip the "end" side (as
+    // determined by this frame's direction) and all but the first part of such
+    // a split should skip the "start" side.  But figuring out which part of
+    // the split we are involves getting our first continuation, which might be
     // expensive.  So don't bother if we already have the relevant bits set.
     PRBool ltr = (NS_STYLE_DIRECTION_LTR == GetStyleVisibility()->mDirection);
     PRIntn startBit = (1 << (ltr ? NS_SIDE_LEFT : NS_SIDE_RIGHT));
     PRIntn endBit = (1 << (ltr ? NS_SIDE_RIGHT : NS_SIDE_LEFT));
     if (((startBit | endBit) & skip) != (startBit | endBit)) {
       // We're missing one of the skip bits, so check whether we need to set it.
-      if (nsLayoutUtils::FrameIsInFirstPartOfIBSplit(this)) {
+      // Only get the first continuation once, as an optimization.
+      nsIFrame* firstContinuation = GetFirstContinuation();
+      if (nsLayoutUtils::FrameIsNonLastInIBSplit(firstContinuation)) {
         skip |= endBit;
-      } else {
-        NS_ASSERTION(nsLayoutUtils::FrameIsInLastPartOfIBSplit(this),
-                     "How did that happen?");
+      }
+      if (nsLayoutUtils::FrameIsNonFirstInIBSplit(firstContinuation)) {
         skip |= startBit;
       }
     }
   }
 
   return skip;
 }
 
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -1079,22 +1079,22 @@ nsLineLayout::ApplyStartMargin(PerFrameD
   NS_ASSERTION(aReflowState.mStyleDisplay->mFloats == NS_STYLE_FLOAT_NONE,
                "How'd we get a floated inline frame? "
                "The frame ctor should've dealt with this.");
 
   // XXXwaterson probably not the right way to get this; e.g., embeddings, etc.
   PRBool ltr = (NS_STYLE_DIRECTION_LTR == aReflowState.mStyleVisibility->mDirection);
 
   // Only apply start-margin on the first-in flow for inline frames,
-  // and make sure to not apply it to the last part of an ib split.
-  // Note that the ib special sibling annotations only live on the
-  // first continuation, but we don't want to apply the start margin
-  // for later continuations anyway.
+  // and make sure to not apply it to any inline other than the first
+  // in an ib split.  Note that the ib special sibling annotations
+  // only live on the first continuation, but we don't want to apply
+  // the start margin for later continuations anyway.
   if (pfd->mFrame->GetPrevContinuation() ||
-      nsLayoutUtils::FrameIsInLastPartOfIBSplit(pfd->mFrame)) {
+      nsLayoutUtils::FrameIsNonFirstInIBSplit(pfd->mFrame)) {
     // Zero this out so that when we compute the max-element-width of
     // the frame we will properly avoid adding in the starting margin.
     if (ltr)
       pfd->mMargin.left = 0;
     else
       pfd->mMargin.right = 0;
   }
   else {
@@ -1154,30 +1154,31 @@ nsLineLayout::CanPlaceFrame(PerFrameData
                  "How'd we get a floated inline frame? "
                  "The frame ctor should've dealt with this.");
 
     // XXXwaterson this is probably not exactly right; e.g., embeddings, etc.
     PRBool ltr = (NS_STYLE_DIRECTION_LTR == aReflowState.mStyleVisibility->mDirection);
 
     /*
      * We want to only apply the end margin if we're the last continuation and
-     * not in the first part of an {ib} split.  In all other cases we want to
-     * zero it out.  That means zeroing it out if any of these conditions hold:
+     * either not in an {ib} split or the last inline in it.  In all other
+     * cases we want to zero it out.  That means zeroing it out if any of these
+     * conditions hold:
      * 1) The frame is not complete (in this case it will get a next-in-flow)
      * 2) The frame is complete but has a non-fluid continuation on its
      *    continuation chain.  Note that if it has a fluid continuation, that
      *    continuation will get destroyed later, so we don't want to drop the
      *    end-margin in that case.
-     * 3) The frame is in the first part of an {ib} split.
+     * 3) The frame is in an {ib} split and is not the last part.
      *
      * However, none of that applies if this is a letter frame (XXXbz why?)
      */
     if ((NS_FRAME_IS_NOT_COMPLETE(aStatus) ||
          pfd->mFrame->GetLastInFlow()->GetNextContinuation() ||
-         nsLayoutUtils::FrameIsInFirstPartOfIBSplit(pfd->mFrame))
+         nsLayoutUtils::FrameIsNonLastInIBSplit(pfd->mFrame))
         && !pfd->GetFlag(PFD_ISLETTERFRAME)) {
       if (ltr)
         pfd->mMargin.right = 0;
       else
         pfd->mMargin.left = 0;
     }
   }
   else {