Bug 447776 – Hang with word-wrap: break-word and width: 0px
authorIan Neal <iann_cvs@blueyonder.co.uk>
Sun, 27 Jul 2008 17:43:07 +0100
changeset 16246 7429393f48c1954ea166120a22a420d900997c3c
parent 16245 cf5f9b3fd1b18ac704f9879aecc0e8978ab48c1c
child 16247 409570e09968032028bad082dfb7ae5d62fbe6e5
push id867
push useriann_cvs@blueyonder.co.uk
push dateSun, 27 Jul 2008 16:43:42 +0000
treeherdermozilla-central@7429393f48c1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs447776
milestone1.9.1a2pre
Bug 447776 – Hang with word-wrap: break-word and width: 0px with testcase and crashtests p=smontagu r/sr=roc
gfx/thebes/src/gfxFont.cpp
layout/reftests/text/reftest.list
layout/reftests/text/wordwrap-07-ref.html
layout/reftests/text/wordwrap-07.html
layout/style/crashtests/447776-1.html
layout/style/crashtests/447783-1.html
layout/style/crashtests/crashtests.list
--- a/gfx/thebes/src/gfxFont.cpp
+++ b/gfx/thebes/src/gfxFont.cpp
@@ -1737,42 +1737,48 @@ gfxTextRun::BreakAndMeasureText(PRUint32
                                    spacingBuffer);
             }
             if (haveHyphenation) {
                 aProvider->GetHyphenationBreaks(bufferStart, bufferLength,
                                                 hyphenBuffer);
             }
         }
 
-        PRBool lineBreakHere = mCharacterGlyphs[i].CanBreakBefore() &&
-            (!aSuppressInitialBreak || i > aStart);
-        PRBool hyphenation = haveHyphenation && hyphenBuffer[i - bufferStart];
-        PRBool wordWrapping = aCanWordWrap && *aBreakPriority <= eWordWrapBreak;
-        if (lineBreakHere || hyphenation || wordWrapping) {
-            gfxFloat hyphenatedAdvance = advance;
-            if (!lineBreakHere && !wordWrapping) {
-                hyphenatedAdvance += aProvider->GetHyphenWidth();
-            }
+        // There can't be a word-wrap break opportunity at the beginning of the
+        // line: if the width is too small for even one character to fit, it 
+        // could be the first and last break opportunity on the line, and that
+        // would trigger an infinite loop.
+        if (!aSuppressInitialBreak || i > aStart) {
+            PRBool lineBreakHere = mCharacterGlyphs[i].CanBreakBefore();
+            PRBool hyphenation = haveHyphenation && hyphenBuffer[i - bufferStart];
+            PRBool wordWrapping = aCanWordWrap && *aBreakPriority <= eWordWrapBreak;
+
+            if (lineBreakHere || hyphenation || wordWrapping) {
+                gfxFloat hyphenatedAdvance = advance;
+                if (!lineBreakHere && !wordWrapping) {
+                    hyphenatedAdvance += aProvider->GetHyphenWidth();
+                }
             
-            if (lastBreak < 0 || width + hyphenatedAdvance - trimmableAdvance <= aWidth) {
-                // We can break here.
-                lastBreak = i;
-                lastBreakTrimmableChars = trimmableChars;
-                lastBreakTrimmableAdvance = trimmableAdvance;
-                lastBreakUsedHyphenation = !lineBreakHere && !wordWrapping;
-                *aBreakPriority = hyphenation || lineBreakHere ?
-                                   eNormalBreak : eWordWrapBreak;
-            }
+                if (lastBreak < 0 || width + hyphenatedAdvance - trimmableAdvance <= aWidth) {
+                    // We can break here.
+                    lastBreak = i;
+                    lastBreakTrimmableChars = trimmableChars;
+                    lastBreakTrimmableAdvance = trimmableAdvance;
+                    lastBreakUsedHyphenation = !lineBreakHere && !wordWrapping;
+                    *aBreakPriority = hyphenation || lineBreakHere ?
+                        eNormalBreak : eWordWrapBreak;
+                }
 
-            width += advance;
-            advance = 0;
-            if (width - trimmableAdvance > aWidth) {
-                // No more text fits. Abort
-                aborted = PR_TRUE;
-                break;
+                width += advance;
+                advance = 0;
+                if (width - trimmableAdvance > aWidth) {
+                    // No more text fits. Abort
+                    aborted = PR_TRUE;
+                    break;
+                }
             }
         }
         
         gfxFloat charAdvance;
         if (i >= ligatureRunStart && i < ligatureRunEnd) {
             charAdvance = GetAdvanceForGlyphs(this, i, i + 1);
             if (haveSpacing) {
                 PropertyProvider::Spacing *space = &spacingBuffer[i - bufferStart];
--- a/layout/reftests/text/reftest.list
+++ b/layout/reftests/text/reftest.list
@@ -6,12 +6,13 @@ random == soft-hyphens-1c.html soft-hyph
 == white-space-1b.html white-space-1-ref.html
 == white-space-2.html white-space-2-ref.html
 == wordwrap-01.html wordwrap-01-ref.html
 random == wordwrap-02.html wordwrap-02-ref.html # bad fonts on test boxes
 random-if(MOZ_WIDGET_TOOLKIT=="gtk2") == wordwrap-03.html wordwrap-03-ref.html # Bad fonts on test boxes
 == wordwrap-04.html wordwrap-04-ref.html
 == wordwrap-05.html wordwrap-05-ref.html
 == wordwrap-06.html wordwrap-06-ref.html
+== wordwrap-07.html wordwrap-07-ref.html
 == zwnj-01.html zwnj-01-ref.html
 == zwnj-02.html zwnj-02-ref.html
 random-if(MOZ_WIDGET_TOOLKIT=="gtk2") != zwnj-01.html zwnj-02-ref.html # Bad fonts on the tinderbox -- works locally
 random == 444656.html 444656-ref.html # bug 406299
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/wordwrap-07-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+  <title>Test Wordwrap</title>
+ </head>
+ <body>
+  <div><em>H<br>e<br>l<br>l<br>o</em><br>K<br>i<br>t<br>t<br>y</div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/wordwrap-07.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+  <style type="text/css">
+div { width: 0px; word-wrap: break-word; }
+  </style>
+  <title>Test Wordwrap</title>
+ </head>
+ <body>
+  <div><em>Hello</em>Kitty</div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/style/crashtests/447776-1.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>Hang with zero width and word-wrap</title>
+</head><body>
+<div style="width: 0px; word-wrap: break-word;">abc</div>
+</body></html>
new file mode 100644
--- /dev/null
+++ b/layout/style/crashtests/447783-1.html
@@ -0,0 +1,8 @@
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>Hang with -moz-column-count and word-wrap</title>
+</head><body>
+<div style="border: 1px solid black; word-wrap: normal; -moz-column-count: 2; width: 110px;">
+a<span style="word-wrap: break-word;">abcde</span>
+</div>
+</body></html>
--- a/layout/style/crashtests/crashtests.list
+++ b/layout/style/crashtests/crashtests.list
@@ -11,8 +11,10 @@ load 397022-1.html
 load 399289-1.svg
 load 404470-1.html
 load 411603-1.html
 load 413274-1.xhtml
 load 437170-1.html
 skip load 439184-1.html # skip until we figure out how to test this
 load 444237-1.html
 load 444848-1.html 
+load 447776-1.html
+load 447783-1.html