<rdar://problem/8881922> Support the hyphenate-limit-lines property
authormitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Sep 2011 20:59:39 +0000 (20:59 +0000)
committermitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Sep 2011 20:59:39 +0000 (20:59 +0000)
https://bugs.webkit.org/show_bug.cgi?id=67730

Reviewed by Dave Hyatt.

Source/WebCore:

Tests: fast/css/parsing-hyphenate-limit-lines.html
       fast/text/hyphenate-limit-lines.html

* css/CSSComputedStyleDeclaration.cpp:
(WebCore::CSSComputedStyleDeclaration::getPropertyCSSValue): Added hyphenate-limit-lines.
* css/CSSParser.cpp:
(WebCore::CSSParser::parseValue): Ditto. Valid values are non-negative integers and the keyword
"no-limit".
* css/CSSPropertyNames.in: Added -webkit-hyphenate-limit-lines.
* css/CSSStyleSelector.cpp:
(WebCore::CSSStyleSelector::applyProperty): Added hyphenate-limit-lines.
* css/CSSValueKeywords.in: Added the "no-limit" value keyword.
* rendering/RenderBlock.h:
* rendering/RenderBlockLineLayout.cpp:
(WebCore::RenderBlock::layoutRunsAndFloats): Count the number of consecutive hyphenated lines
before the start line and pass it to layoutRunsAndFloatsInRange().
(WebCore::RenderBlock::layoutRunsAndFloatsInRange): Keep track of the number of consecutive
hyphenated lines before the current line and pass it to LineBreaker::nextLineBreak().
(WebCore::tryHyphenating): Added parameters for the number of consecutive hyphenated lines before
the current line and the limit on consecutive hyphenated lines, and an early return if the limit
has been reached.
(WebCore::RenderBlock::LineBreaker::nextLineBreak): Added a parameter for the number of consecutive
hyphenated lines before the current line, which is passed through to tryHyphenating, along with
the value of hyphenate-limit-lines.
* rendering/RootInlineBox.cpp:
(WebCore::RootInlineBox::isHyphenated): Added. Returns true if the line was hyphenated.
* rendering/RootInlineBox.h:
* rendering/style/RenderStyle.h:
(WebCore::InheritedFlags::hyphenationLimitLines): Added this getter.
(WebCore::InheritedFlags::setHyphenationLimitLines): Added this setter.
(WebCore::InheritedFlags::initialHyphenationLimitLines): Added. The initial value is -1,
corresponding to "no-limit".
* rendering/style/StyleRareInheritedData.cpp:
(WebCore::StyleRareInheritedData::StyleRareInheritedData): Initialize new member variable.
(WebCore::StyleRareInheritedData::operator==): Compare new member variable.
* rendering/style/StyleRareInheritedData.h:

LayoutTests:

* fast/css/parsing-hyphenate-limit-lines-expected.txt: Added.
* fast/css/parsing-hyphenate-limit-lines.html: Added.
* fast/text/hyphenate-limit-lines.html: Added.
* platform/mac/fast/text/hyphenate-limit-lines-expected.png: Added.
* platform/mac/fast/text/hyphenate-limit-lines-expected.txt: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@94710 268f45cc-cd09-0410-ab3c-d52691b4dbfc

19 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/css/parsing-hyphenate-limit-lines-expected.txt [new file with mode: 0644]
LayoutTests/fast/css/parsing-hyphenate-limit-lines.html [new file with mode: 0644]
LayoutTests/fast/text/hyphenate-limit-lines.html [new file with mode: 0644]
LayoutTests/platform/mac/fast/text/hyphenate-limit-lines-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/text/hyphenate-limit-lines-expected.txt [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/css/CSSComputedStyleDeclaration.cpp
Source/WebCore/css/CSSParser.cpp
Source/WebCore/css/CSSPropertyNames.in
Source/WebCore/css/CSSStyleSelector.cpp
Source/WebCore/css/CSSValueKeywords.in
Source/WebCore/rendering/RenderBlock.h
Source/WebCore/rendering/RenderBlockLineLayout.cpp
Source/WebCore/rendering/RootInlineBox.cpp
Source/WebCore/rendering/RootInlineBox.h
Source/WebCore/rendering/style/RenderStyle.h
Source/WebCore/rendering/style/StyleRareInheritedData.cpp
Source/WebCore/rendering/style/StyleRareInheritedData.h

index 661d1c51128e781c1af0a8dfa7e55a2eac983a33..7c31f3f314bb0ef66c5f42ccc6f8bea05fc6a639 100644 (file)
@@ -1,3 +1,16 @@
+2011-09-07  Dan Bernstein  <mitz@apple.com>
+
+        <rdar://problem/8881922> Support the hyphenate-limit-lines property
+        https://bugs.webkit.org/show_bug.cgi?id=67730
+
+        Reviewed by Dave Hyatt.
+
+        * fast/css/parsing-hyphenate-limit-lines-expected.txt: Added.
+        * fast/css/parsing-hyphenate-limit-lines.html: Added.
+        * fast/text/hyphenate-limit-lines.html: Added.
+        * platform/mac/fast/text/hyphenate-limit-lines-expected.png: Added.
+        * platform/mac/fast/text/hyphenate-limit-lines-expected.txt: Added.
+
 2011-09-07  Csaba Osztrogon√°c  <ossy@webkit.org>
 
         [Qt] Unreviewed gardening after r94697.
diff --git a/LayoutTests/fast/css/parsing-hyphenate-limit-lines-expected.txt b/LayoutTests/fast/css/parsing-hyphenate-limit-lines-expected.txt
new file mode 100644 (file)
index 0000000..8862a16
--- /dev/null
@@ -0,0 +1,10 @@
+PASS: '-webkit-hyphenate-limit-lines: initial;' parsed as 'initial'
+PASS: '-webkit-hyphenate-limit-lines: inherit;' parsed as 'inherit'
+PASS: '-webkit-hyphenate-limit-lines: no-limit;' parsed as 'no-limit'
+PASS: '-webkit-hyphenate-limit-lines: 0;' parsed as '0'
+PASS: '-webkit-hyphenate-limit-lines: 4;' parsed as '4'
+PASS: '-webkit-hyphenate-limit-lines: 2 2;' parsed as ''
+PASS: '-webkit-hyphenate-limit-lines: 2px;' parsed as ''
+PASS: '-webkit-hyphenate-limit-lines: -1;' parsed as ''
+PASS: '-webkit-hyphenate-limit-lines: "1";' parsed as ''
+
diff --git a/LayoutTests/fast/css/parsing-hyphenate-limit-lines.html b/LayoutTests/fast/css/parsing-hyphenate-limit-lines.html
new file mode 100644 (file)
index 0000000..58e6065
--- /dev/null
@@ -0,0 +1,31 @@
+<pre id="console"></pre>
+<script>
+    if (window.layoutTestController)
+        layoutTestController.dumpAsText();
+
+    function log(message)
+    {
+        document.getElementById("console").appendChild(document.createTextNode(message + "\n"));
+    }
+
+    function test(declaration, expectedHyphenateLimit)
+    {
+        var element = document.createElement("div");
+        element.style.cssText = declaration;
+        var hyphenateLimit = element.style.webkitHyphenateLimitLines;
+        if (hyphenateLimit === expectedHyphenateLimit)
+            log("PASS: '" + declaration + "' parsed as '" + hyphenateLimit + "'");
+        else
+            log("FAIL: '" + declaration + "' parsed as '" + hyphenateLimit + "'");
+    }
+
+    test('-webkit-hyphenate-limit-lines: initial;', 'initial');
+    test('-webkit-hyphenate-limit-lines: inherit;', 'inherit');
+    test('-webkit-hyphenate-limit-lines: no-limit;', 'no-limit');
+    test('-webkit-hyphenate-limit-lines: 0;', '0');
+    test('-webkit-hyphenate-limit-lines: 4;', '4');
+    test('-webkit-hyphenate-limit-lines: 2 2;', '');
+    test('-webkit-hyphenate-limit-lines: 2px;', '');
+    test('-webkit-hyphenate-limit-lines: -1;', '');
+    test('-webkit-hyphenate-limit-lines: "1";', '');
+</script>
diff --git a/LayoutTests/fast/text/hyphenate-limit-lines.html b/LayoutTests/fast/text/hyphenate-limit-lines.html
new file mode 100644 (file)
index 0000000..9f66643
--- /dev/null
@@ -0,0 +1,51 @@
+<style>
+    div {
+        width: 200px;
+        font-size: 26px;
+        -webkit-hyphens: auto;
+        text-align: justify;
+        margin: 0 4px;
+        float: left;
+        border: solid thin lightblue;
+        -webkit-locale: "en_US";
+    }
+</style>
+<div style="-webkit-hyphenate-limit-lines: no-limit;">
+    also the division of the mind into the rational, concupiscent, and
+    irascible elements, or of pleasures and desires into necessary and
+    unnecessary&mdash;these and other great forms of thought are all of them
+    to be found in the Republic, and were probably first invented by
+    Plato.
+</div>
+
+<div style="-webkit-hyphenate-limit-lines: 3;">
+    also the division of the mind into the rational, concupiscent, and
+    irascible elements, or of pleasures and desires into necessary and
+    unnecessary&mdash;these and other great forms of thought are all of them
+    to be found in the Republic, and were probably first invented by
+    Plato.
+</div>
+
+<div style="-webkit-hyphenate-limit-lines: 2;">
+    also the division of the mind into the rational, concupiscent, and
+    irascible elements, or of pleasures and desires into necessary and
+    unnecessary&mdash;these and other great forms of thought are all of them
+    to be found in the Republic, and were probably first invented by
+    Plato.
+</div>
+
+<div style="-webkit-hyphenate-limit-lines: 1;">
+    also the division of the mind into the rational, concupiscent, and
+    irascible elements, or of pleasures and desires into necessary and
+    unnecessary&mdash;these and other great forms of thought are all of them
+    to be found in the Republic, and were probably first invented by
+    Plato.
+</div>
+
+<div style="-webkit-hyphenate-limit-lines: 0;">
+    also the division of the mind into the rational, concupiscent, and
+    irascible elements, or of pleasures and desires into necessary and
+    unnecessary&mdash;these and other great forms of thought are all of them
+    to be found in the Republic, and were probably first invented by
+    Plato.
+</div>
diff --git a/LayoutTests/platform/mac/fast/text/hyphenate-limit-lines-expected.png b/LayoutTests/platform/mac/fast/text/hyphenate-limit-lines-expected.png
new file mode 100644 (file)
index 0000000..ab69684
Binary files /dev/null and b/LayoutTests/platform/mac/fast/text/hyphenate-limit-lines-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/text/hyphenate-limit-lines-expected.txt b/LayoutTests/platform/mac/fast/text/hyphenate-limit-lines-expected.txt
new file mode 100644 (file)
index 0000000..f0fe6c5
--- /dev/null
@@ -0,0 +1,111 @@
+layer at (0,0) size 785x1066
+  RenderView at (0,0) size 785x600
+layer at (0,0) size 785x1066
+  RenderBlock {HTML} at (0,0) size 785x1066
+    RenderBody {BODY} at (8,8) size 769x584
+      RenderBlock (floating) {DIV} at (4,0) size 202x498 [border: (1px solid #ADD8E6)]
+        RenderText {#text} at (1,1) size 200x496
+          text run at (1,1) width 200: "also the division of"
+          text run at (1,32) width 200: "the mind into the"
+          text run at (1,63) width 200: "rational, concupis" + hyphen string "-"
+          text run at (1,94) width 111: "cent, and "
+          text run at (112,94) width 89: "irascible"
+          text run at (1,125) width 200: "elements, or of"
+          text run at (1,156) width 200: "pleasures and de" + hyphen string "-"
+          text run at (1,187) width 200: "sires into neces" + hyphen string "-"
+          text run at (1,218) width 106: "sary and "
+          text run at (107,218) width 94: "unneces" + hyphen string "-"
+          text run at (1,249) width 200: "sary\x{2014}these and"
+          text run at (1,280) width 200: "other great forms"
+          text run at (1,311) width 200: "of thought are all"
+          text run at (1,342) width 128: "of them "
+          text run at (129,342) width 72: "to be"
+          text run at (1,373) width 200: "found in the Re" + hyphen string "-"
+          text run at (1,404) width 200: "public, and were"
+          text run at (1,435) width 200: "probably first in" + hyphen string "-"
+          text run at (1,466) width 110: "vented by "
+          text run at (111,466) width 60: "Plato."
+      RenderBlock (floating) {DIV} at (214,0) size 202x498 [border: (1px solid #ADD8E6)]
+        RenderText {#text} at (1,1) size 200x496
+          text run at (1,1) width 200: "also the division of"
+          text run at (1,32) width 200: "the mind into the"
+          text run at (1,63) width 200: "rational, concupis" + hyphen string "-"
+          text run at (1,94) width 111: "cent, and "
+          text run at (112,94) width 89: "irascible"
+          text run at (1,125) width 200: "elements, or of"
+          text run at (1,156) width 200: "pleasures and de" + hyphen string "-"
+          text run at (1,187) width 200: "sires into neces" + hyphen string "-"
+          text run at (1,218) width 106: "sary and "
+          text run at (107,218) width 94: "unneces" + hyphen string "-"
+          text run at (1,249) width 200: "sary\x{2014}these and"
+          text run at (1,280) width 200: "other great forms"
+          text run at (1,311) width 200: "of thought are all"
+          text run at (1,342) width 128: "of them "
+          text run at (129,342) width 72: "to be"
+          text run at (1,373) width 200: "found in the Re" + hyphen string "-"
+          text run at (1,404) width 200: "public, and were"
+          text run at (1,435) width 200: "probably first in" + hyphen string "-"
+          text run at (1,466) width 110: "vented by "
+          text run at (111,466) width 60: "Plato."
+      RenderBlock (floating) {DIV} at (424,0) size 202x529 [border: (1px solid #ADD8E6)]
+        RenderText {#text} at (1,1) size 200x527
+          text run at (1,1) width 200: "also the division of"
+          text run at (1,32) width 200: "the mind into the"
+          text run at (1,63) width 200: "rational, concupis" + hyphen string "-"
+          text run at (1,94) width 111: "cent, and "
+          text run at (112,94) width 89: "irascible"
+          text run at (1,125) width 200: "elements, or of"
+          text run at (1,156) width 200: "pleasures and de" + hyphen string "-"
+          text run at (1,187) width 200: "sires into neces" + hyphen string "-"
+          text run at (1,218) width 200: "sary and"
+          text run at (1,249) width 155: "unnecessary\x{2014}"
+          text run at (1,280) width 200: "these and other"
+          text run at (1,311) width 200: "great forms of"
+          text run at (1,342) width 200: "thought are all of"
+          text run at (1,373) width 66: "them "
+          text run at (67,373) width 134: "to be found"
+          text run at (1,404) width 200: "in the Republic,"
+          text run at (1,435) width 200: "and were probably"
+          text run at (1,466) width 200: "first invented by"
+          text run at (1,497) width 60: "Plato."
+      RenderBlock (floating) {DIV} at (4,529) size 202x529 [border: (1px solid #ADD8E6)]
+        RenderText {#text} at (1,1) size 200x527
+          text run at (1,1) width 200: "also the division of"
+          text run at (1,32) width 200: "the mind into the"
+          text run at (1,63) width 200: "rational, concupis" + hyphen string "-"
+          text run at (1,94) width 111: "cent, and "
+          text run at (112,94) width 89: "irascible"
+          text run at (1,125) width 200: "elements, or of"
+          text run at (1,156) width 200: "pleasures and de" + hyphen string "-"
+          text run at (1,187) width 200: "sires into"
+          text run at (1,218) width 200: "necessary and"
+          text run at (1,249) width 155: "unnecessary\x{2014}"
+          text run at (1,280) width 200: "these and other"
+          text run at (1,311) width 200: "great forms of"
+          text run at (1,342) width 200: "thought are all of"
+          text run at (1,373) width 66: "them "
+          text run at (67,373) width 134: "to be found"
+          text run at (1,404) width 200: "in the Republic,"
+          text run at (1,435) width 200: "and were probably"
+          text run at (1,466) width 200: "first invented by"
+          text run at (1,497) width 60: "Plato."
+      RenderBlock (floating) {DIV} at (214,529) size 202x529 [border: (1px solid #ADD8E6)]
+        RenderText {#text} at (1,1) size 200x527
+          text run at (1,1) width 200: "also the division of"
+          text run at (1,32) width 200: "the mind into the"
+          text run at (1,63) width 87: "rational,"
+          text run at (1,94) width 200: "concupiscent, and"
+          text run at (1,125) width 200: "irascible elements,"
+          text run at (1,156) width 200: "or of pleasures"
+          text run at (1,187) width 200: "and desires into"
+          text run at (1,218) width 200: "necessary and"
+          text run at (1,249) width 155: "unnecessary\x{2014}"
+          text run at (1,280) width 200: "these and other"
+          text run at (1,311) width 200: "great forms of"
+          text run at (1,342) width 200: "thought are all of"
+          text run at (1,373) width 66: "them "
+          text run at (67,373) width 134: "to be found"
+          text run at (1,404) width 200: "in the Republic,"
+          text run at (1,435) width 200: "and were probably"
+          text run at (1,466) width 200: "first invented by"
+          text run at (1,497) width 60: "Plato."
index 19f8810eb60f05ec8ac759c7b82e05a95e367fae..0000ecc3e0d526a7e9f4d77934ed4219a42e2b3e 100644 (file)
@@ -1,3 +1,47 @@
+2011-09-07  Dan Bernstein  <mitz@apple.com>
+
+        <rdar://problem/8881922> Support the hyphenate-limit-lines property
+        https://bugs.webkit.org/show_bug.cgi?id=67730
+
+        Reviewed by Dave Hyatt.
+
+        Tests: fast/css/parsing-hyphenate-limit-lines.html
+               fast/text/hyphenate-limit-lines.html
+
+        * css/CSSComputedStyleDeclaration.cpp:
+        (WebCore::CSSComputedStyleDeclaration::getPropertyCSSValue): Added hyphenate-limit-lines.
+        * css/CSSParser.cpp:
+        (WebCore::CSSParser::parseValue): Ditto. Valid values are non-negative integers and the keyword
+        "no-limit".
+        * css/CSSPropertyNames.in: Added -webkit-hyphenate-limit-lines.
+        * css/CSSStyleSelector.cpp:
+        (WebCore::CSSStyleSelector::applyProperty): Added hyphenate-limit-lines.
+        * css/CSSValueKeywords.in: Added the "no-limit" value keyword.
+        * rendering/RenderBlock.h:
+        * rendering/RenderBlockLineLayout.cpp:
+        (WebCore::RenderBlock::layoutRunsAndFloats): Count the number of consecutive hyphenated lines
+        before the start line and pass it to layoutRunsAndFloatsInRange().
+        (WebCore::RenderBlock::layoutRunsAndFloatsInRange): Keep track of the number of consecutive
+        hyphenated lines before the current line and pass it to LineBreaker::nextLineBreak().
+        (WebCore::tryHyphenating): Added parameters for the number of consecutive hyphenated lines before
+        the current line and the limit on consecutive hyphenated lines, and an early return if the limit
+        has been reached.
+        (WebCore::RenderBlock::LineBreaker::nextLineBreak): Added a parameter for the number of consecutive
+        hyphenated lines before the current line, which is passed through to tryHyphenating, along with
+        the value of hyphenate-limit-lines.
+        * rendering/RootInlineBox.cpp:
+        (WebCore::RootInlineBox::isHyphenated): Added. Returns true if the line was hyphenated.
+        * rendering/RootInlineBox.h:
+        * rendering/style/RenderStyle.h:
+        (WebCore::InheritedFlags::hyphenationLimitLines): Added this getter.
+        (WebCore::InheritedFlags::setHyphenationLimitLines): Added this setter.
+        (WebCore::InheritedFlags::initialHyphenationLimitLines): Added. The initial value is -1,
+        corresponding to "no-limit".
+        * rendering/style/StyleRareInheritedData.cpp:
+        (WebCore::StyleRareInheritedData::StyleRareInheritedData): Initialize new member variable.
+        (WebCore::StyleRareInheritedData::operator==): Compare new member variable.
+        * rendering/style/StyleRareInheritedData.h:
+
 2011-09-02  Ojan Vafai  <ojan@chromium.org>
 
         split overrideSize into overrideHeight and overrideWidth
index c5c17cdee9364e1f4b72ba16f22b1540400ec5b5..61b27dd3dfcec541f404d5f13f216b5918ff691d 100644 (file)
@@ -215,6 +215,7 @@ static const int computedProperties[] = {
     CSSPropertyWebkitHyphenateCharacter,
     CSSPropertyWebkitHyphenateLimitAfter,
     CSSPropertyWebkitHyphenateLimitBefore,
+    CSSPropertyWebkitHyphenateLimitLines,
     CSSPropertyWebkitHyphens,
     CSSPropertyWebkitLineBoxContain,
     CSSPropertyWebkitLineBreak,
@@ -1308,6 +1309,10 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper
             if (style->hyphenationLimitBefore() < 0)
                 return CSSPrimitiveValue::createIdentifier(CSSValueAuto);
             return CSSPrimitiveValue::create(style->hyphenationLimitBefore(), CSSPrimitiveValue::CSS_NUMBER);
+        case CSSPropertyWebkitHyphenateLimitLines:
+            if (style->hyphenationLimitLines() < 0)
+                return CSSPrimitiveValue::createIdentifier(CSSValueNoLimit);
+            return CSSPrimitiveValue::create(style->hyphenationLimitLines(), CSSPrimitiveValue::CSS_NUMBER);
         case CSSPropertyWebkitBorderFit:
             if (style->borderFit() == BorderFitBorder)
                 return primitiveValueCache->createIdentifierValue(CSSValueBorder);
index 579000eb23ccfeab4843cd8bf2a977685d2f4dc1..a6629bdeb5374e6456cb0151db72764871c60229 100644 (file)
@@ -1899,6 +1899,11 @@ bool CSSParser::parseValue(int propId, bool important)
             validPrimitive = true;
         break;
 
+    case CSSPropertyWebkitHyphenateLimitLines:
+        if (id == CSSValueNoLimit || validUnit(value, FInteger | FNonNeg, true))
+            validPrimitive = true;
+        break;
+
     case CSSPropertyWebkitLocale:
         if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
             validPrimitive = true;
index bf95cb86da5cd37d482aa4b082c5ea27aedea944..6e5703bed38c315fd3c58593abe324b47789db4c 100644 (file)
@@ -257,6 +257,7 @@ z-index
 -webkit-hyphenate-character
 -webkit-hyphenate-limit-after
 -webkit-hyphenate-limit-before
+-webkit-hyphenate-limit-lines
 -webkit-hyphens
 -epub-hyphens = -webkit-hyphens
 -webkit-line-box-contain
index 25c527b880095572a1730a15220b90c2afbf775d..167a019a66d267d11e7593add8639034e906a3d5 100644 (file)
@@ -3551,6 +3551,14 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value)
             m_style->setHyphenationLimitBefore(primitiveValue->getValue<short>(CSSPrimitiveValue::CSS_NUMBER));
         return;
     }
+    case CSSPropertyWebkitHyphenateLimitLines: {
+        HANDLE_INHERIT_AND_INITIAL(hyphenationLimitLines, HyphenationLimitLines);
+        if (primitiveValue->getIdent() == CSSValueNoLimit)
+            m_style->setHyphenationLimitLines(-1);
+        else
+            m_style->setHyphenationLimitLines(primitiveValue->getValue<short>(CSSPrimitiveValue::CSS_NUMBER));
+        return;
+    }
     case CSSPropertyWebkitLocale: {
         HANDLE_INHERIT_AND_INITIAL(locale, Locale);
         if (primitiveValue->getIdent() == CSSValueAuto)
index 41b51434527bb77b790e1b4004d487e2dbaed0f6..ba18fb5e3f6640db05b8bb623a271671c34ec3cc 100644 (file)
@@ -776,6 +776,9 @@ maximized
 minimized
 windowed
 
+// -webkit-hyphenate-limit-lines
+no-limit
+
 // -webkit-hyphens
 // none
 manual
index ca6573b614c66949287c28759b37b523e8396793..2a8d653c7be8f02bfb83ecf7e95f2a11a40d9936 100644 (file)
@@ -563,7 +563,7 @@ private:
             reset();
         }
 
-        InlineIterator nextLineBreak(InlineBidiResolver&, LineInfo&, LineBreakIteratorInfo&, FloatingObject* lastFloatFromPreviousLine);
+        InlineIterator nextLineBreak(InlineBidiResolver&, LineInfo&, LineBreakIteratorInfo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines);
 
         bool lineWasHyphenated() { return m_hyphenated; }
         const Vector<RenderBox*>& positionedObjects() { return m_positionedObjects; }
@@ -795,7 +795,7 @@ private:
     // Helper function for layoutInlineChildren()
     RootInlineBox* createLineBoxesFromBidiRuns(BidiRunList<BidiRun>&, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun);
     void layoutRunsAndFloats(LineLayoutState&, bool hasInlineChild);
-    void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus);
+    void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines);
     void linkToEndLineIfNeeded(LineLayoutState&);
     static void repaintDirtyFloats(Vector<FloatWithRect>& floats);
 
index 40a1414771197ced1503ac49c49dd2cad7584e4f..44a484ae0e5dbc257ec037fcc0b5c6f2d56f660e 100644 (file)
@@ -936,6 +936,12 @@ void RenderBlock::layoutRunsAndFloats(LineLayoutState& layoutState, bool hasInli
     InlineBidiResolver resolver;
     RootInlineBox* startLine = determineStartPosition(layoutState, resolver);
 
+    unsigned consecutiveHyphenatedLines = 0;
+    if (startLine) {
+        for (RootInlineBox* line = startLine->prevRootBox(); line && line->isHyphenated(); line = line->prevRootBox())
+            consecutiveHyphenatedLines++;
+    }
+
     // FIXME: This would make more sense outside of this function, but since
     // determineStartPosition can change the fullLayout flag we have to do this here. Failure to call
     // determineStartPosition first will break fast/repaint/line-flow-with-floats-9.html.
@@ -984,12 +990,12 @@ void RenderBlock::layoutRunsAndFloats(LineLayoutState& layoutState, bool hasInli
         }
     }
 
-    layoutRunsAndFloatsInRange(layoutState, resolver, cleanLineStart, cleanLineBidiStatus);
+    layoutRunsAndFloatsInRange(layoutState, resolver, cleanLineStart, cleanLineBidiStatus, consecutiveHyphenatedLines);
     linkToEndLineIfNeeded(layoutState);
     repaintDirtyFloats(layoutState.floats());
 }
 
-void RenderBlock::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, InlineBidiResolver& resolver, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus)
+void RenderBlock::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, InlineBidiResolver& resolver, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines)
 {
     bool paginated = view()->layoutState() && view()->layoutState()->isPaginated();
     LineMidpointState& lineMidpointState = resolver.midpointState();
@@ -1015,7 +1021,7 @@ void RenderBlock::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, Inlin
         InlineIterator oldEnd = end;
         bool isNewUBAParagraph = layoutState.lineInfo().previousLineBrokeCleanly();
         FloatingObject* lastFloatFromPreviousLine = (m_floatingObjects && !m_floatingObjects->set().isEmpty()) ? m_floatingObjects->set().last() : 0;
-        end = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(), lineBreakIteratorInfo, lastFloatFromPreviousLine);
+        end = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(), lineBreakIteratorInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines);
         if (resolver.position().atEnd()) {
             // FIXME: We shouldn't be creating any runs in findNextLineBreak to begin with!
             // Once BidiRunList is separated from BidiResolver this will not be needed.
@@ -1045,8 +1051,11 @@ void RenderBlock::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, Inlin
 
             BidiRun* trailingSpaceRun = !layoutState.lineInfo().previousLineBrokeCleanly() ? handleTrailingSpaces(bidiRuns, resolver.context()) : 0;
 
-            if (bidiRuns.runCount() && lineBreaker.lineWasHyphenated())
+            if (bidiRuns.runCount() && lineBreaker.lineWasHyphenated()) {
                 bidiRuns.logicallyLastRun()->m_hasHyphen = true;
+                consecutiveHyphenatedLines++;
+            } else
+                consecutiveHyphenatedLines = 0;
 
             // Now that the runs have been ordered, we create the line boxes.
             // At the same time we figure out where border/padding/margin should be applied for
@@ -1679,7 +1688,7 @@ static inline float textWidth(RenderText* text, unsigned from, unsigned len, con
     return font.width(run);
 }
 
-static void tryHyphenating(RenderText* text, const Font& font, const AtomicString& localeIdentifier, int minimumPrefixLength, int minimumSuffixLength, int lastSpace, int pos, float xPos, int availableWidth, bool isFixedPitch, bool collapseWhiteSpace, int lastSpaceWordSpacing, InlineIterator& lineBreak, int nextBreakable, bool& hyphenated)
+static void tryHyphenating(RenderText* text, const Font& font, const AtomicString& localeIdentifier, unsigned consecutiveHyphenatedLines, int consecutiveHyphenatedLinesLimit, int minimumPrefixLength, int minimumSuffixLength, int lastSpace, int pos, float xPos, int availableWidth, bool isFixedPitch, bool collapseWhiteSpace, int lastSpaceWordSpacing, InlineIterator& lineBreak, int nextBreakable, bool& hyphenated)
 {
     // Map 'hyphenate-limit-{before,after}: auto;' to 2.
     if (minimumPrefixLength < 0)
@@ -1691,6 +1700,9 @@ static void tryHyphenating(RenderText* text, const Font& font, const AtomicStrin
     if (pos - lastSpace <= minimumSuffixLength)
         return;
 
+    if (consecutiveHyphenatedLinesLimit >= 0 && consecutiveHyphenatedLines >= static_cast<unsigned>(consecutiveHyphenatedLinesLimit))
+        return;
+
     const AtomicString& hyphenString = text->style()->hyphenString();
     int hyphenWidth = font.width(RenderBlock::constructTextRun(text, font, hyphenString.string(), text->style()));
 
@@ -1949,7 +1961,7 @@ void RenderBlock::LineBreaker::reset()
 }
 
 InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resolver, LineInfo& lineInfo,
-    LineBreakIteratorInfo& lineBreakIteratorInfo, FloatingObject* lastFloatFromPreviousLine)
+    LineBreakIteratorInfo& lineBreakIteratorInfo, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines)
 {
     reset();
 
@@ -2268,7 +2280,7 @@ InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resol
                         }
                         if (lineWasTooWide || !width.fitsOnLine()) {
                             if (canHyphenate && !width.fitsOnLine()) {
-                                tryHyphenating(t, f, style->locale(), style->hyphenationLimitBefore(), style->hyphenationLimitAfter(), lastSpace, current.m_pos, width.currentWidth() - additionalTmpW, width.availableWidth(), isFixedPitch, collapseWhiteSpace, lastSpaceWordSpacing, lBreak, current.m_nextBreakablePosition, m_hyphenated);
+                                tryHyphenating(t, f, style->locale(), consecutiveHyphenatedLines, m_block->style()->hyphenationLimitLines(), style->hyphenationLimitBefore(), style->hyphenationLimitAfter(), lastSpace, current.m_pos, width.currentWidth() - additionalTmpW, width.availableWidth(), isFixedPitch, collapseWhiteSpace, lastSpaceWordSpacing, lBreak, current.m_nextBreakablePosition, m_hyphenated);
                                 if (m_hyphenated)
                                     goto end;
                             }
@@ -2386,7 +2398,7 @@ InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resol
 
             if (!width.fitsOnLine()) {
                 if (canHyphenate)
-                    tryHyphenating(t, f, style->locale(), style->hyphenationLimitBefore(), style->hyphenationLimitAfter(), lastSpace, current.m_pos, width.currentWidth() - additionalTmpW, width.availableWidth(), isFixedPitch, collapseWhiteSpace, lastSpaceWordSpacing, lBreak, current.m_nextBreakablePosition, m_hyphenated);
+                    tryHyphenating(t, f, style->locale(), consecutiveHyphenatedLines, m_block->style()->hyphenationLimitLines(), style->hyphenationLimitBefore(), style->hyphenationLimitAfter(), lastSpace, current.m_pos, width.currentWidth() - additionalTmpW, width.availableWidth(), isFixedPitch, collapseWhiteSpace, lastSpaceWordSpacing, lBreak, current.m_nextBreakablePosition, m_hyphenated);
 
                 if (!m_hyphenated && lBreak.previousInSameNode() == softHyphen && style->hyphens() != HyphensNone)
                     m_hyphenated = true;
index df81e424ab4dfd1de59b4808d7a521fb4819eb91..201c22032093af8f43cfb844b4c6278b3545e434 100644 (file)
@@ -88,6 +88,18 @@ void RootInlineBox::clearTruncation()
     }
 }
 
+bool RootInlineBox::isHyphenated() const
+{
+    for (InlineBox* box = firstLeafChild(); box; box = box->nextLeafChild()) {
+        if (box->isInlineTextBox()) {
+            if (toInlineTextBox(box)->hasHyphen())
+                return true;
+        }
+    }
+
+    return false;
+}
+
 bool RootInlineBox::lineCanAccommodateEllipsis(bool ltr, int blockEdge, int lineBoxEdge, int ellipsisWidth)
 {
     // First sanity-check the unoverflowed width of the whole line to see if there is sufficient room.
index e70c6ce283f2d8048c3e98b654dc06ee836e00fe..9c75fca925d8552ee56b99bfc20a1645f5c86c24 100644 (file)
@@ -96,6 +96,8 @@ public:
 
     virtual void clearTruncation();
 
+    bool isHyphenated() const;
+
     virtual int baselinePosition(FontBaseline baselineType) const { return boxModelObject()->baselinePosition(baselineType, m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); }
     virtual int lineHeight() const { return boxModelObject()->lineHeight(m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); }
 
index 85088bfe91071b7cb1b2beb1a5d4351736fb5eb5..970ac20ea22c3920df1d62aaa51a94c17d7ffd96 100644 (file)
@@ -714,6 +714,7 @@ public:
     Hyphens hyphens() const { return static_cast<Hyphens>(rareInheritedData->hyphens); }
     short hyphenationLimitBefore() const { return rareInheritedData->hyphenationLimitBefore; }
     short hyphenationLimitAfter() const { return rareInheritedData->hyphenationLimitAfter; }
+    short hyphenationLimitLines() const { return rareInheritedData->hyphenationLimitLines; }
     const AtomicString& hyphenationString() const { return rareInheritedData->hyphenationString; }
     const AtomicString& locale() const { return rareInheritedData->locale; }
     EBorderFit borderFit() const { return static_cast<EBorderFit>(rareNonInheritedData->m_borderFit); }
@@ -1094,6 +1095,7 @@ public:
     void setHyphens(Hyphens h) { SET_VAR(rareInheritedData, hyphens, h); }
     void setHyphenationLimitBefore(short limit) { SET_VAR(rareInheritedData, hyphenationLimitBefore, limit); }
     void setHyphenationLimitAfter(short limit) { SET_VAR(rareInheritedData, hyphenationLimitAfter, limit); }
+    void setHyphenationLimitLines(short limit) { SET_VAR(rareInheritedData, hyphenationLimitLines, limit); }
     void setHyphenationString(const AtomicString& h) { SET_VAR(rareInheritedData, hyphenationString, h); }
     void setLocale(const AtomicString& locale) { SET_VAR(rareInheritedData, locale, locale); }
     void setBorderFit(EBorderFit b) { SET_VAR(rareNonInheritedData, m_borderFit, b); }
@@ -1376,6 +1378,7 @@ public:
     static Hyphens initialHyphens() { return HyphensManual; }
     static short initialHyphenationLimitBefore() { return -1; }
     static short initialHyphenationLimitAfter() { return -1; }
+    static short initialHyphenationLimitLines() { return -1; }
     static const AtomicString& initialHyphenationString() { return nullAtom; }
     static const AtomicString& initialLocale() { return nullAtom; }
     static EBorderFit initialBorderFit() { return BorderFitBorder; }
index fa09a869f3f416a0105baa344ff4a51fa310bc3f..5386098cba4f29ea10c72a07603d429a10a51ac3 100644 (file)
@@ -55,6 +55,7 @@ StyleRareInheritedData::StyleRareInheritedData()
     , m_imageRendering(RenderStyle::initialImageRendering())
     , hyphenationLimitBefore(-1)
     , hyphenationLimitAfter(-1)
+    , hyphenationLimitLines(-1)
 {
 }
 
@@ -91,6 +92,7 @@ StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o)
     , hyphenationString(o.hyphenationString)
     , hyphenationLimitBefore(o.hyphenationLimitBefore)
     , hyphenationLimitAfter(o.hyphenationLimitAfter)
+    , hyphenationLimitLines(o.hyphenationLimitLines)
     , locale(o.locale)
     , textEmphasisCustomMark(o.textEmphasisCustomMark)
 {
@@ -136,6 +138,7 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const
         && hyphens == o.hyphens
         && hyphenationLimitBefore == o.hyphenationLimitBefore
         && hyphenationLimitAfter == o.hyphenationLimitAfter
+        && hyphenationLimitLines == o.hyphenationLimitLines
         && textEmphasisFill == o.textEmphasisFill
         && textEmphasisMark == o.textEmphasisMark
         && textEmphasisPosition == o.textEmphasisPosition
index b990ef86ee436362f673584a8a29ad74d54f532b..355112af388a15c8950f2c9d0829a13840f29ca7 100644 (file)
@@ -92,6 +92,7 @@ public:
     AtomicString hyphenationString;
     short hyphenationLimitBefore;
     short hyphenationLimitAfter;
+    short hyphenationLimitLines;
 
     AtomicString locale;