Bug 467487. Use a better and more explicit check for the case where a text frame's textrun doesn't map enough text for the frame. r=smontagu
authorRobert O'Callahan <robert@ocallahan.org>
Wed, 17 Dec 2008 15:14:33 +1300
changeset 22876 62c3545aabadfefe90c98e3fd2e39a7567f48d9f
parent 22875 84cffcb0f3da0ed6cd7578f2ae03ede75db8d4ef
child 22877 bb18fee38c6a8113f82ebed293b1bc90857bb11b
push idunknown
push userunknown
push dateunknown
reviewerssmontagu
bugs467487
milestone1.9.2a1pre
Bug 467487. Use a better and more explicit check for the case where a text frame's textrun doesn't map enough text for the frame. r=smontagu
gfx/thebes/public/gfxSkipChars.h
layout/generic/crashtests/467487-1.html
layout/generic/crashtests/crashtests.list
layout/generic/nsTextFrameThebes.cpp
--- a/gfx/thebes/public/gfxSkipChars.h
+++ b/gfx/thebes/public/gfxSkipChars.h
@@ -309,26 +309,34 @@ public:
      * @return the offset within the skipped string corresponding to the
      * current position in the original string. If the current position
      * in the original string is a character that is skipped, then we return
      * the position corresponding to the first non-skipped character in the
      * original string after the current position, or the length of the skipped
      * string if there is no such character.
      */
     PRUint32 GetSkippedOffset() const { return mSkippedStringOffset; }
-  
+
+    PRInt32 GetOriginalEnd() const {
+        return mSkipChars->GetOriginalCharCount() -
+            mOriginalStringToSkipCharsOffset;
+    }
+
 private:
     void SetOffsets(PRUint32 aOffset, PRBool aInOriginalString);
   
     const gfxSkipChars* mSkipChars;
     PRInt32 mOriginalStringOffset;
     PRUint32 mSkippedStringOffset;
-    
-    PRUint32 mOriginalStringToSkipCharsOffset;
-    
+
+    // This offset is added to map from "skipped+unskipped characters in
+    // the original DOM string" character space to "skipped+unskipped
+    // characters in the textrun's gfxSkipChars" character space
+    PRInt32 mOriginalStringToSkipCharsOffset;
+
     /*
      * This is used to speed up cursor-style traversal. The invariant is that
      * the first mListPrefixLength bytes of mSkipChars.mList sum to
      * mListPrefixCharCount, and the even-indexed bytes in that prefix sum to
      * mListPrefixKeepCharCount.
      * Also, 0 <= mListPrefixLength < mSkipChars.mListLength, or else
      * mSkipChars.mListLength is zero.
      * Also, mListPrefixCharCount <= mOriginalStringOffset (and therefore
new file mode 100644
--- /dev/null
+++ b/layout/generic/crashtests/467487-1.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body onload="document.getElementById('y').style.width = '8000px';">
+
+<div style="white-space: pre-line;"><div id="y"><div style="text-align: justify; font-size: 3300%;">AB CDEF
+ </div></div></div>
+ 
+</body>
+</html>
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -162,8 +162,9 @@ load 448903-1.html
 load 451334-1.html
 load 452157-1.html
 load 452157-2.html
 load 452157-3.html
 load 455171-1.html
 load 455171-2.html
 load 455171-3.html
 load 457375.html
+load 467487-1.html
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -5783,20 +5783,17 @@ nsTextFrame::Reflow(nsPresContext*      
         ClearTextRun();
       }
     } 
   }
 
   gfxSkipCharsIterator iter =
     EnsureTextRun(ctx, lineContainer, lineLayout.GetLine(), &flowEndInTextRun);
 
-  PRInt32 skippedRunLength;
-  if (mTextRun && mTextRun->GetLength() == iter.GetSkippedOffset() &&
-      length > 0 &&
-      (!iter.IsOriginalCharSkipped(&skippedRunLength) || skippedRunLength < length)) {
+  if (mTextRun && iter.GetOriginalEnd() < offset + length) {
     // The textrun does not map enough text for this frame. This can happen
     // when the textrun was ended in the middle of a text node because a
     // preformatted newline was encountered, and prev-in-flow frames have
     // consumed all the text of the textrun. We need a new textrun.
     ClearTextRun();
     iter = EnsureTextRun(ctx, lineContainer,
                          lineLayout.GetLine(), &flowEndInTextRun);
   }