Bug 407111. Correctly set whether a break opportunity after non-text content fits. r+sr=dbaron,a=schrep
authorroc+@cs.cmu.edu
Fri, 07 Dec 2007 01:17:19 -0800
changeset 8806 4958518cc1c4c57ddec32a4fc9a44718bf58861f
parent 8805 fe1a42aacc0be5ed8d62773754eea6a6d0a5d690
child 8807 9481c8be9615f40a0940d73d0f22d1ac6ab83d13
push id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherderautoland@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersschrep
bugs407111
milestone1.9b2pre
Bug 407111. Correctly set whether a break opportunity after non-text content fits. r+sr=dbaron,a=schrep
layout/generic/nsLineLayout.cpp
layout/generic/nsLineLayout.h
layout/reftests/bugs/407111-1-ref.html
layout/reftests/bugs/407111-1.html
layout/reftests/bugs/reftest.list
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -1025,19 +1025,20 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
     }
 
     // Check whether this frame breaks up text runs. All frames break up text
     // runs (hence return false here) except for text frames and inline containers.
     PRBool continuingTextRun = aFrame->CanContinueTextRun();
     
     // See if we can place the frame. If we can't fit it, then we
     // return now.
+    PRBool optionalBreakAfterFits;
     if (CanPlaceFrame(pfd, reflowState, notSafeToBreak, continuingTextRun,
                       savedOptionalBreakContent != nsnull, metrics,
-                      aReflowStatus)) {
+                      aReflowStatus, &optionalBreakAfterFits)) {
       // Place the frame, updating aBounds with the final size and
       // location.  Then apply the bottom+right margins (as
       // appropriate) to the frame.
       PlaceFrame(pfd, metrics);
       PerSpanData* span = pfd->mSpan;
       if (span) {
         // The frame we just finished reflowing is an inline
         // container.  It needs its child frames vertically aligned,
@@ -1048,17 +1049,17 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
       if (!continuingTextRun) {
         if (!pfd->GetFlag(PFD_SKIPWHENTRIMMINGWHITESPACE)) {
           mTrimmableWidth = 0;
         }
         if (!psd->mNoWrap && (!CanPlaceFloatNow() || placedFloat)) {
           // record soft break opportunity after this content that can't be
           // part of a text run. This is not a text frame so we know
           // that offset PR_INT32_MAX means "after the content".
-          if (NotifyOptionalBreakPosition(aFrame->GetContent(), PR_INT32_MAX, PR_TRUE)) {
+          if (NotifyOptionalBreakPosition(aFrame->GetContent(), PR_INT32_MAX, optionalBreakAfterFits)) {
             // If this returns true then we are being told to actually break here.
             aReflowStatus = NS_INLINE_LINE_BREAK_AFTER(aReflowStatus);
           }
         }
       }
     }
     else {
       PushFrame(aFrame);
@@ -1141,19 +1142,22 @@ nsLineLayout::GetCurrentFrameXDistanceFr
  */
 PRBool
 nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
                             const nsHTMLReflowState& aReflowState,
                             PRBool aNotSafeToBreak,
                             PRBool aFrameCanContinueTextRun,
                             PRBool aCanRollBackBeforeFrame,
                             nsHTMLReflowMetrics& aMetrics,
-                            nsReflowStatus& aStatus)
+                            nsReflowStatus& aStatus,
+                            PRBool* aOptionalBreakAfterFits)
 {
   NS_PRECONDITION(pfd && pfd->mFrame, "bad args, null pointers for frame data");
+  
+  *aOptionalBreakAfterFits = PR_TRUE;
   // Compute right margin to use
   if (0 != pfd->mBounds.width) {
     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 this is probably not exactly right; e.g., embeddings, etc.
     PRBool ltr = (NS_STYLE_DIRECTION_LTR == aReflowState.mStyleVisibility->mDirection);
@@ -1200,16 +1204,17 @@ nsLineLayout::CanPlaceFrame(PerFrameData
   PRBool outside = pfd->mBounds.XMost() - mTrimmableWidth + endMargin > psd->mRightEdge;
   if (!outside) {
     // If it fits, it fits
 #ifdef NOISY_CAN_PLACE_FRAME
     printf("   ==> inside\n");
 #endif
     return PR_TRUE;
   }
+  *aOptionalBreakAfterFits = PR_FALSE;
 
   // When it doesn't fit, check for a few special conditions where we
   // allow it to fit anyway.
   if (0 == pfd->mMargin.left + pfd->mBounds.width + pfd->mMargin.right) {
     // Empty frames always fit right where they are
 #ifdef NOISY_CAN_PLACE_FRAME
     printf("   ==> empty frame fits\n");
 #endif
--- a/layout/generic/nsLineLayout.h
+++ b/layout/generic/nsLineLayout.h
@@ -245,18 +245,18 @@ public:
    * 
    * @param aFits set to true if the break position is within the available width.
    * 
    * @return PR_TRUE if we are actually reflowing with forced break position and we
    * should break here
    */
   PRBool NotifyOptionalBreakPosition(nsIContent* aContent, PRInt32 aOffset,
                                      PRBool aFits) {
-    NS_ASSERTION(!GetFlag(LL_NEEDBACKUP),
-                  "Shouldn't be updating the break position after we've already flagged an overrun");
+    NS_ASSERTION(!aFits || !GetFlag(LL_NEEDBACKUP),
+                  "Shouldn't be updating the break position with a break that fits after we've already flagged an overrun");
     // Remember the last break position that fits; if there was no break that fit,
     // just remember the first break
     if (aFits || !mLastOptionalBreakContent) {
       mLastOptionalBreakContent = aContent;
       mLastOptionalBreakContentOffset = aOffset;
     }
     return aContent && mForceBreakContent == aContent &&
       mForceBreakContentOffset == aOffset;
@@ -513,34 +513,34 @@ protected:
                         nsHTMLReflowState& aReflowState);
 
   PRBool CanPlaceFrame(PerFrameData* pfd,
                        const nsHTMLReflowState& aReflowState,
                        PRBool aNotSafeToBreak,
                        PRBool aFrameCanContinueTextRun,
                        PRBool aCanRollBackBeforeFrame,
                        nsHTMLReflowMetrics& aMetrics,
-                       nsReflowStatus& aStatus);
+                       nsReflowStatus& aStatus,
+                       PRBool* aOptionalBreakAfterFits);
 
   void PlaceFrame(PerFrameData* pfd,
                   nsHTMLReflowMetrics& aMetrics);
 
   void UpdateFrames();
 
   void VerticalAlignFrames(PerSpanData* psd);
 
   void PlaceTopBottomFrames(PerSpanData* psd,
                             nscoord aDistanceFromTop,
                             nscoord aLineHeight);
 
   void RelativePositionFrames(PerSpanData* psd, nsRect& aCombinedArea);
 
   PRBool TrimTrailingWhiteSpaceIn(PerSpanData* psd, nscoord* aDeltaWidth);
 
-
   void ComputeJustificationWeights(PerSpanData* psd, PRInt32* numSpaces, PRInt32* numLetters);
 
   struct FrameJustificationState {
     PRInt32 mTotalNumSpaces;
     PRInt32 mTotalNumLetters;
     nscoord mTotalWidthForSpaces;
     nscoord mTotalWidthForLetters;
     PRInt32 mNumSpacesProcessed;
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/407111-1-ref.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<style>
+b { white-space:nowrap; }
+div { border:1px solid black; }
+</style>
+</head>
+<body style="font-size:10px; width:200px; border:1px solid black"><b><img src="mozilla-banner.gif" width="100">T</b><br>
+<b><img src="mozilla-banner.gif" width="100">T</b></body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/407111-1.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<style>
+b { white-space:nowrap; }
+div { border:1px solid black; }
+</style>
+</head>
+<body style="font-size:10px; width:200px; border:1px solid black"><b><img src="mozilla-banner.gif" width="100">T</b>
+<b><img src="mozilla-banner.gif" width="100">T</b></br></body>
+</html>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -504,10 +504,11 @@ random == 403134-1.html 403134-1-ref.htm
 == 404666-1.html 404666-1-ref.html
 == 404666-2.html 404666-2-ref.html
 == 405186-1.xhtml about:blank
 == 405305-1.html 405305-1-ref.html
 == 405577-1.html 405577-1-ref.html
 == 405584-1.html 405584-1-ref.html
 == 406484-1.html 406484-1-ref.html
 == 406568-1.html 406568-1-ref.html
+== 407111-1.html 407111-1-ref.html
 == 407227-1.html 407227-1-ref.html