Bug 385635. Make text min-width calculation clear out old value of trimmable whitespace when the text contains non-collapsible whitespace. Also, set skipWhitespace to skip subsequent whitespace only if the trailing whitespace in the text is not preformatted. r=smontagu
authorroc+@cs.cmu.edu
Tue, 02 Oct 2007 01:52:09 -0700
changeset 6529 bd545ad3fca0dd138774de165cbf57f98878de21
parent 6528 2d3d79d9a112b1736d40f9401e32af72a94db547
child 6530 727c9af50db9110a6aeaa69f8916df0d0a2f13cc
push idunknown
push userunknown
push dateunknown
reviewerssmontagu
bugs385635
milestone1.9a9pre
Bug 385635. Make text min-width calculation clear out old value of trimmable whitespace when the text contains non-collapsible whitespace. Also, set skipWhitespace to skip subsequent whitespace only if the trailing whitespace in the text is not preformatted. r=smontagu
layout/generic/nsTextFrameThebes.cpp
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -498,16 +498,24 @@ static PRBool IsTrimmableSpace(const nsT
 {
   NS_ASSERTION(aPos < aFrag->GetLength(), "No text for IsSpace!");
   PRUnichar ch = aFrag->CharAt(aPos);
   if (ch == ' ')
     return !IsSpaceCombiningSequenceTail(aFrag, aPos + 1);
   return ch == '\t' || ch == '\n' || ch == '\f';
 }
 
+static PRBool IsTrimmableSpace(const nsTextFragment* aFrag,
+                               const nsStyleText* aText, PRUint32 aPos)
+{
+  if (aText->WhiteSpaceIsSignificant())
+    return PR_FALSE;
+  return IsTrimmableSpace(aFrag, aPos);
+}
+
 static PRBool IsSelectionSpace(const nsTextFragment* aFrag, PRUint32 aPos)
 {
   NS_ASSERTION(aPos < aFrag->GetLength(), "No text for IsSpace!");
   PRUnichar ch = aFrag->CharAt(aPos);
   if (ch == ' ' || ch == CH_NBSP)
     return !IsSpaceCombiningSequenceTail(aFrag, aPos + 1);
   return ch == '\t' || ch == '\n' || ch == '\f';
 }
@@ -4770,40 +4778,42 @@ nsTextFrame::AddInlineMinWidthForFlow(ns
         NSToCoordCeil(mTextRun->GetAdvanceWidth(wordStart, i - wordStart, &provider));
       aData->currentLine += width;
       aData->atStartOfLine = PR_FALSE;
 
       if (collapseWhitespace) {
         nscoord trailingWhitespaceWidth;
         PRUint32 trimStart = GetEndOfTrimmedText(frag, wordStart, i, &iter);
         if (trimStart == start) {
-          trailingWhitespaceWidth = width;
+          // This is *all* trimmable whitespace, so whatever trailingWhitespace
+          // we saw previously is still trailing...
+          aData->trailingWhitespace += width;
         } else {
-          trailingWhitespaceWidth =
+          // Some non-whitespace so the old trailingWhitespace is no longer trailing
+          aData->trailingWhitespace =
             NSToCoordCeil(mTextRun->GetAdvanceWidth(trimStart, i - trimStart, &provider));
         }
-        aData->trailingWhitespace += trailingWhitespaceWidth;
       } else {
         aData->trailingWhitespace = 0;
       }
     }
 
     if (i < flowEndInTextRun) {
       if (preformattedNewline) {
         aData->ForceBreak(aRenderingContext);
       } else {
         aData->OptionallyBreak(aRenderingContext);
       }
       wordStart = i;
     }
   }
 
-  // Check if we have whitespace at the end
+  // Check if we have collapsible whitespace at the end
   aData->skipWhitespace =
-    IsTrimmableSpace(provider.GetFragment(),
+    IsTrimmableSpace(provider.GetFragment(), provider.GetStyleText(),
                      iter.ConvertSkippedToOriginal(flowEndInTextRun - 1));
 }
 
 // XXX Need to do something here to avoid incremental reflow bugs due to
 // first-line and first-letter changing min-width
 /* virtual */ void
 nsTextFrame::AddInlineMinWidth(nsIRenderingContext *aRenderingContext,
                                nsIFrame::InlineMinWidthData *aData)
@@ -4846,30 +4856,30 @@ nsTextFrame::AddInlinePrefWidthForFlow(n
     FindStartAfterSkippingWhitespace(&provider, aData, collapseWhitespace,
                                      &iter, flowEndInTextRun);
   if (start >= flowEndInTextRun)
     return;
 
   if (collapseWhitespace) {
     // \n line breaks are not honoured, so everything would like to go
     // onto one line, so just measure it
-    aData->currentLine +=
+    nscoord width =
       NSToCoordCeil(mTextRun->GetAdvanceWidth(start, flowEndInTextRun - start, &provider));
+    aData->currentLine += width;
 
     PRUint32 trimStart = GetEndOfTrimmedText(provider.GetFragment(), start,
                                              flowEndInTextRun, &iter);
-    nscoord trimWidth =
-      NSToCoordCeil(mTextRun->GetAdvanceWidth(trimStart, flowEndInTextRun - trimStart, &provider));
     if (trimStart == start) {
       // This is *all* trimmable whitespace, so whatever trailingWhitespace
       // we saw previously is still trailing...
-      aData->trailingWhitespace += trimWidth;
+      aData->trailingWhitespace += width;
     } else {
       // Some non-whitespace so the old trailingWhitespace is no longer trailing
-      aData->trailingWhitespace = trimWidth;
+      aData->trailingWhitespace =
+        NSToCoordCeil(mTextRun->GetAdvanceWidth(trimStart, flowEndInTextRun - trimStart, &provider));
     }
   } else {
     // We respect line breaks, so measure off each line (or part of line).
     aData->trailingWhitespace = 0;
     PRUint32 i;
     PRUint32 startRun = start;
     for (i = start; i <= flowEndInTextRun; ++i) {
       if (i < flowEndInTextRun && mTextRun->GetChar(i) != '\n')
@@ -4879,19 +4889,19 @@ nsTextFrame::AddInlinePrefWidthForFlow(n
         NSToCoordCeil(mTextRun->GetAdvanceWidth(startRun, i - startRun, &provider));
       if (i < flowEndInTextRun) {
         aData->ForceBreak(aRenderingContext);
         startRun = i;
       }
     }
   }
 
-  // Check if we have whitespace at the end
+  // Check if we have collapsible whitespace at the end
   aData->skipWhitespace =
-    IsTrimmableSpace(provider.GetFragment(),
+    IsTrimmableSpace(provider.GetFragment(), provider.GetStyleText(),
                      iter.ConvertSkippedToOriginal(flowEndInTextRun - 1));
 }
 
 // XXX Need to do something here to avoid incremental reflow bugs due to
 // first-line and first-letter changing pref-width
 /* virtual */ void
 nsTextFrame::AddInlinePrefWidth(nsIRenderingContext *aRenderingContext,
                                 nsIFrame::InlinePrefWidthData *aData)