<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[176473] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/176473">176473</a></dd>
<dt>Author</dt> <dd>mmaxfield@apple.com</dd>
<dt>Date</dt> <dd>2014-11-21 14:33:17 -0800 (Fri, 21 Nov 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Source/WebCore:
Add support to -webkit-line-break property for CSS3 Text line-break property values and semantics.
https://bugs.webkit.org/show_bug.cgi?id=89235

Reviewed by Eric Seidel and Dave Hyatt.

This patch adds semantic support for the CSS3 line-break property (qua -webkit-line-break),
and enables testing on (apple) mac ports. Follow on patches will enable these tests on
other ports as they are incrementally verified.

See also wiki documentation at:
[1] http://trac.webkit.org/wiki/LineBreaking
[2] http://trac.webkit.org/wiki/LineBreakingCSS3Mapping

Tests: css3/line-break/line-break-auto-centered.html
       css3/line-break/line-break-auto-half-kana.html
       css3/line-break/line-break-auto-hyphens.html
       css3/line-break/line-break-auto-inseparables.html
       css3/line-break/line-break-auto-iteration-marks.html
       css3/line-break/line-break-auto-postfixes.html
       css3/line-break/line-break-auto-prefixes.html
       css3/line-break/line-break-auto-sound-marks.html
       css3/line-break/line-break-loose-centered.html
       css3/line-break/line-break-loose-half-kana.html
       css3/line-break/line-break-loose-hyphens.html
       css3/line-break/line-break-loose-inseparables.html
       css3/line-break/line-break-loose-iteration-marks.html
       css3/line-break/line-break-loose-postfixes.html
       css3/line-break/line-break-loose-prefixes.html
       css3/line-break/line-break-loose-sound-marks.html
       css3/line-break/line-break-normal-centered.html
       css3/line-break/line-break-normal-half-kana.html
       css3/line-break/line-break-normal-hyphens.html
       css3/line-break/line-break-normal-inseparables.html
       css3/line-break/line-break-normal-iteration-marks.html
       css3/line-break/line-break-normal-postfixes.html
       css3/line-break/line-break-normal-prefixes.html
       css3/line-break/line-break-normal-sound-marks.html
       css3/line-break/line-break-strict-centered.html
       css3/line-break/line-break-strict-half-kana.html
       css3/line-break/line-break-strict-hyphens.html
       css3/line-break/line-break-strict-inseparables.html
       css3/line-break/line-break-strict-iteration-marks.html
       css3/line-break/line-break-strict-postfixes.html
       css3/line-break/line-break-strict-prefixes.html
       css3/line-break/line-break-strict-sound-marks.html

These tests were previously added in http://trac.webkit.org/changeset/143378, but skipped
in generic TestExpectations. In this patch, they are marked as Pass for the (apple) mac ports.

* platform/text/LineBreakIteratorPoolICU.h:
(WebCore::LineBreakIteratorPool::makeLocaleWithBreakKeyword):
Add static function to construct ICU locale argument (also used as pool key) with additional
break keyword.
(LineBreakIteratorPool):
(WebCore::LineBreakIteratorPool::take):
(WebCore::LineBreakIteratorPool::put):
Remove direct dependency from ICU library (and types), moving that dependency into
new {open,close}LineBreakIterator() functions (defined in TextBreakIteratorICU.cpp).
Update to take line break mode into account.
Create (and cache) different break iterators depending on line break mode (in addition to locale),
which entails expanding pool entry key format to optionally append &quot;@break=&quot; +
&quot;loose&quot;|&quot;normal&quot;|&quot;strict&quot; keyword to locale string.

* platform/text/TextBreakIterator.h:
(WebCore::LazyLineBreakIterator::LazyLineBreakIterator):
(WebCore::LazyLineBreakIterator::isLooseCJKMode):
(WebCore::LazyLineBreakIterator::get):
(WebCore::LazyLineBreakIterator::reset):
(LazyLineBreakIterator):
Define LineBreakIteratorMode enumeration for use in TextBreakIterator et al.
Add state member to indicate line break mode.

* platform/text/TextBreakIteratorICU.cpp:
(WebCore::acquireLineBreakIterator):
Use new line break mode when making iterator from pool.
Handle change of return type of LineBreakIteratorPool::take() to non-ICU type,
i.e., TextBreakIterator* instead of ICU's UBreakIterator*.
(WebCore::releaseLineBreakIterator):
Handle change of parameter type of LineBreakIteratorPool::put() to non-ICU type,
i.e., TextBreakIterator* instead of ICU's UBreakIterator*.
(WebCore):
(WebCore::isCJKLocale):
New functions for determining if CJK rules apply.
(WebCore::openLineBreakIterator):
New function for abstracting opening of ICU style line break iterator. This is now
used in LineBreakIteratorPoolICU.h rather than having direct ICU API dependency there.
This function also takes into account the line break mode.

Note that this function only calls ubrk_openRules() when the author has opted-in via
using the -webkit-line-break CSS property. Eventually, we would like to be able to
customize the rules that ICU's line breaking algorithm uses (especially for CJK text);
however, ubrk_openRules() currently parses its input string to create a DFA and is
therefore very slow. In fact, it's so slow that increasing our cache size in
LineBreakIteratorPool doesn't actually help enough. Also note that the default value
for the line-break CSS property is 'auto'.
(WebCore::closeLineBreakIterator):
(WebCore::mapLineIteratorModeToRules):
New function for abstracting closing of ICU style line break iterator. This is now
used in LineBreakIteratorPoolICU.h rather than having direct ICU API dependency there.

* rendering/RenderBlockLineLayout.cpp:
(WebCore::RenderBlock::LineBreaker::nextSegmentBreak):
Pass line break iterator mode flag when reseting LazyLineBreakIterator.
Add looseMode local variable to prevent need for computing under isBreakable().

* rendering/RenderText.cpp:
(WebCore::mapLineBreakToIteratorMode):
Add implementation for mapLineBreakToIteratorMode(), used by both RenderText::computePreferredLogicalWidths
and RenderBlock::LineBreaker::nextLineBreak.
(WebCore):
(WebCore::RenderText::computePreferredLogicalWidths):
Ensure (lazy line) breakIterator is initialized for line break mode.
Ensure isBreakable() is passed loose mode flag to match behavior in RenderBlock::LineBreaker::nextLineBreak.

* rendering/RenderText.h:
(WebCore):
Add declaration for mapLineBreakToIteratorMode(), used by both RenderText::computePreferredLogicalWidths
and RenderBlock::LineBreaker::nextLineBreak.

* rendering/break_lines.cpp:
(WebCore):
Introduce (local) enum NBSPBehavior for expanding template on nextBreakablePosition.
(WebCore::isBreakableSpace):
Add externally specified loose mode parameter to prevent need to invoke line break iterator
accessor method on each invocation. Use new loose mode flavors off NBP functions.
(WebCore::needsLineBreakIterator):
Use enum NBSP behavior template parameter rather than boolean.
(WebCore::nextBreakablePositionNonLoosely):
Extend name to distinguish from loose flavor of this function.
(WebCore::nextBreakablePositionLoosely):
Add loose flavor of NBP invoked only when loose mode applies, in which case ASCII shortcut
table cannot be used.
(WebCore::nextBreakablePosition):
(WebCore::nextBreakablePositionIgnoringNBSP):
Use (renamed) non-loose flavor of NBP.
(WebCore::nextBreakablePositionLoose):
(WebCore::nextBreakablePositionIgnoringNBSPLoose):
Introduce loose flavor of NBP template expansions.

* rendering/break_lines.h:
(WebCore):
(WebCore::isBreakable):
Add externally specified loose mode parameter to prevent need to invoke line break iterator
accessor method on each invocation.

LayoutTests:
CSS3: line-break property support
https://bugs.webkit.org/show_bug.cgi?id=89235

Reviewed by Eric Seidel and Dave Hyatt.

* platform/mac/TestExpectations: Mark css3/line-break tests as passing.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsplatformmacTestExpectations">trunk/LayoutTests/platform/mac/TestExpectations</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCoreexpin">trunk/Source/WebCore/WebCore.exp.in</a></li>
<li><a href="#trunkSourceWebCoreplatformtextLineBreakIteratorPoolICUh">trunk/Source/WebCore/platform/text/LineBreakIteratorPoolICU.h</a></li>
<li><a href="#trunkSourceWebCoreplatformtextTextBreakIteratorcpp">trunk/Source/WebCore/platform/text/TextBreakIterator.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformtextTextBreakIteratorh">trunk/Source/WebCore/platform/text/TextBreakIterator.h</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderTextcpp">trunk/Source/WebCore/rendering/RenderText.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderTexth">trunk/Source/WebCore/rendering/RenderText.h</a></li>
<li><a href="#trunkSourceWebCorerenderingSimpleLineLayoutcpp">trunk/Source/WebCore/rendering/SimpleLineLayout.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingSimpleLineLayoutFlowContentscpp">trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingbreak_linesh">trunk/Source/WebCore/rendering/break_lines.h</a></li>
<li><a href="#trunkSourceWebCorerenderinglineBreakingContextInlineHeadersh">trunk/Source/WebCore/rendering/line/BreakingContextInlineHeaders.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (176472 => 176473)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-11-21 21:34:30 UTC (rev 176472)
+++ trunk/LayoutTests/ChangeLog        2014-11-21 22:33:17 UTC (rev 176473)
</span><span class="lines">@@ -1,3 +1,12 @@
</span><ins>+2014-11-21  Glenn Adams  &lt;glenn@skynav.com&gt; and Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
+
+        CSS3: line-break property support
+        https://bugs.webkit.org/show_bug.cgi?id=89235
+
+        Reviewed by Eric Seidel and Dave Hyatt.
+
+        * platform/mac/TestExpectations: Mark css3/line-break tests as passing.
+
</ins><span class="cx"> 2014-11-21  Zalan Bujtas  &lt;zalan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         REGRESSION(r175259) Simple line layout text measuring behavior changed.
</span></span></pre></div>
<a id="trunkLayoutTestsplatformmacTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/mac/TestExpectations (176472 => 176473)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/TestExpectations        2014-11-21 21:34:30 UTC (rev 176472)
+++ trunk/LayoutTests/platform/mac/TestExpectations        2014-11-21 22:33:17 UTC (rev 176473)
</span><span class="lines">@@ -1429,3 +1429,8 @@
</span><span class="cx"> webkit.org/b/138075 [ Yosemite ] fast/text/international/hindi-spacing.html [ Pass Failure ]
</span><span class="cx"> 
</span><span class="cx"> webkit.org/b/82980 http/tests/navigation/back-twice-without-commit.html [ Timeout ]
</span><ins>+
+# Verified passing, so override generic skip
+webkit.org/b/89235 css3/line-break [ Pass ]
+webkit.org/b/138115 css3/line-break/line-break-auto-hyphens.html [ ImageOnlyFailure ]
+webkit.org/b/138115 css3/line-break/line-break-auto-sound-marks.html [ ImageOnlyFailure ]
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (176472 => 176473)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-11-21 21:34:30 UTC (rev 176472)
+++ trunk/Source/WebCore/ChangeLog        2014-11-21 22:33:17 UTC (rev 176473)
</span><span class="lines">@@ -1,3 +1,150 @@
</span><ins>+2014-11-21  Glenn Adams  &lt;glenn@skynav.com&gt; and Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
+
+        Add support to -webkit-line-break property for CSS3 Text line-break property values and semantics.
+        https://bugs.webkit.org/show_bug.cgi?id=89235
+
+        Reviewed by Eric Seidel and Dave Hyatt.
+
+        This patch adds semantic support for the CSS3 line-break property (qua -webkit-line-break),
+        and enables testing on (apple) mac ports. Follow on patches will enable these tests on
+        other ports as they are incrementally verified.
+
+        See also wiki documentation at:
+        [1] http://trac.webkit.org/wiki/LineBreaking
+        [2] http://trac.webkit.org/wiki/LineBreakingCSS3Mapping
+
+        Tests: css3/line-break/line-break-auto-centered.html
+               css3/line-break/line-break-auto-half-kana.html
+               css3/line-break/line-break-auto-hyphens.html
+               css3/line-break/line-break-auto-inseparables.html
+               css3/line-break/line-break-auto-iteration-marks.html
+               css3/line-break/line-break-auto-postfixes.html
+               css3/line-break/line-break-auto-prefixes.html
+               css3/line-break/line-break-auto-sound-marks.html
+               css3/line-break/line-break-loose-centered.html
+               css3/line-break/line-break-loose-half-kana.html
+               css3/line-break/line-break-loose-hyphens.html
+               css3/line-break/line-break-loose-inseparables.html
+               css3/line-break/line-break-loose-iteration-marks.html
+               css3/line-break/line-break-loose-postfixes.html
+               css3/line-break/line-break-loose-prefixes.html
+               css3/line-break/line-break-loose-sound-marks.html
+               css3/line-break/line-break-normal-centered.html
+               css3/line-break/line-break-normal-half-kana.html
+               css3/line-break/line-break-normal-hyphens.html
+               css3/line-break/line-break-normal-inseparables.html
+               css3/line-break/line-break-normal-iteration-marks.html
+               css3/line-break/line-break-normal-postfixes.html
+               css3/line-break/line-break-normal-prefixes.html
+               css3/line-break/line-break-normal-sound-marks.html
+               css3/line-break/line-break-strict-centered.html
+               css3/line-break/line-break-strict-half-kana.html
+               css3/line-break/line-break-strict-hyphens.html
+               css3/line-break/line-break-strict-inseparables.html
+               css3/line-break/line-break-strict-iteration-marks.html
+               css3/line-break/line-break-strict-postfixes.html
+               css3/line-break/line-break-strict-prefixes.html
+               css3/line-break/line-break-strict-sound-marks.html
+
+        These tests were previously added in http://trac.webkit.org/changeset/143378, but skipped
+        in generic TestExpectations. In this patch, they are marked as Pass for the (apple) mac ports.
+
+        * platform/text/LineBreakIteratorPoolICU.h:
+        (WebCore::LineBreakIteratorPool::makeLocaleWithBreakKeyword):
+        Add static function to construct ICU locale argument (also used as pool key) with additional
+        break keyword.
+        (LineBreakIteratorPool):
+        (WebCore::LineBreakIteratorPool::take):
+        (WebCore::LineBreakIteratorPool::put):
+        Remove direct dependency from ICU library (and types), moving that dependency into
+        new {open,close}LineBreakIterator() functions (defined in TextBreakIteratorICU.cpp).
+        Update to take line break mode into account.
+        Create (and cache) different break iterators depending on line break mode (in addition to locale),
+        which entails expanding pool entry key format to optionally append &quot;@break=&quot; +
+        &quot;loose&quot;|&quot;normal&quot;|&quot;strict&quot; keyword to locale string.
+
+        * platform/text/TextBreakIterator.h:
+        (WebCore::LazyLineBreakIterator::LazyLineBreakIterator):
+        (WebCore::LazyLineBreakIterator::isLooseCJKMode):
+        (WebCore::LazyLineBreakIterator::get):
+        (WebCore::LazyLineBreakIterator::reset):
+        (LazyLineBreakIterator):
+        Define LineBreakIteratorMode enumeration for use in TextBreakIterator et al.
+        Add state member to indicate line break mode.
+
+        * platform/text/TextBreakIteratorICU.cpp:
+        (WebCore::acquireLineBreakIterator):
+        Use new line break mode when making iterator from pool.
+        Handle change of return type of LineBreakIteratorPool::take() to non-ICU type,
+        i.e., TextBreakIterator* instead of ICU's UBreakIterator*.
+        (WebCore::releaseLineBreakIterator):
+        Handle change of parameter type of LineBreakIteratorPool::put() to non-ICU type,
+        i.e., TextBreakIterator* instead of ICU's UBreakIterator*.
+        (WebCore):
+        (WebCore::isCJKLocale):
+        New functions for determining if CJK rules apply.
+        (WebCore::openLineBreakIterator):
+        New function for abstracting opening of ICU style line break iterator. This is now
+        used in LineBreakIteratorPoolICU.h rather than having direct ICU API dependency there.
+        This function also takes into account the line break mode.
+
+        Note that this function only calls ubrk_openRules() when the author has opted-in via
+        using the -webkit-line-break CSS property. Eventually, we would like to be able to
+        customize the rules that ICU's line breaking algorithm uses (especially for CJK text);
+        however, ubrk_openRules() currently parses its input string to create a DFA and is
+        therefore very slow. In fact, it's so slow that increasing our cache size in
+        LineBreakIteratorPool doesn't actually help enough. Also note that the default value
+        for the line-break CSS property is 'auto'.
+        (WebCore::closeLineBreakIterator):
+        (WebCore::mapLineIteratorModeToRules):
+        New function for abstracting closing of ICU style line break iterator. This is now
+        used in LineBreakIteratorPoolICU.h rather than having direct ICU API dependency there.
+
+        * rendering/RenderBlockLineLayout.cpp:
+        (WebCore::RenderBlock::LineBreaker::nextSegmentBreak):
+        Pass line break iterator mode flag when reseting LazyLineBreakIterator.
+        Add looseMode local variable to prevent need for computing under isBreakable().
+
+        * rendering/RenderText.cpp:
+        (WebCore::mapLineBreakToIteratorMode):
+        Add implementation for mapLineBreakToIteratorMode(), used by both RenderText::computePreferredLogicalWidths
+        and RenderBlock::LineBreaker::nextLineBreak.
+        (WebCore):
+        (WebCore::RenderText::computePreferredLogicalWidths):
+        Ensure (lazy line) breakIterator is initialized for line break mode.
+        Ensure isBreakable() is passed loose mode flag to match behavior in RenderBlock::LineBreaker::nextLineBreak.
+
+        * rendering/RenderText.h:
+        (WebCore):
+        Add declaration for mapLineBreakToIteratorMode(), used by both RenderText::computePreferredLogicalWidths
+        and RenderBlock::LineBreaker::nextLineBreak.
+
+        * rendering/break_lines.cpp:
+        (WebCore):
+        Introduce (local) enum NBSPBehavior for expanding template on nextBreakablePosition.
+        (WebCore::isBreakableSpace):
+        Add externally specified loose mode parameter to prevent need to invoke line break iterator
+        accessor method on each invocation. Use new loose mode flavors off NBP functions.
+        (WebCore::needsLineBreakIterator):
+        Use enum NBSP behavior template parameter rather than boolean.
+        (WebCore::nextBreakablePositionNonLoosely):
+        Extend name to distinguish from loose flavor of this function.
+        (WebCore::nextBreakablePositionLoosely):
+        Add loose flavor of NBP invoked only when loose mode applies, in which case ASCII shortcut
+        table cannot be used.
+        (WebCore::nextBreakablePosition):
+        (WebCore::nextBreakablePositionIgnoringNBSP):
+        Use (renamed) non-loose flavor of NBP.
+        (WebCore::nextBreakablePositionLoose):
+        (WebCore::nextBreakablePositionIgnoringNBSPLoose):
+        Introduce loose flavor of NBP template expansions.
+
+        * rendering/break_lines.h:
+        (WebCore):
+        (WebCore::isBreakable):
+        Add externally specified loose mode parameter to prevent need to invoke line break iterator
+        accessor method on each invocation.
+
</ins><span class="cx"> 2014-11-21  Anders Carlsson  &lt;andersca@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         More build fixes.
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCoreexpin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.exp.in (176472 => 176473)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.exp.in        2014-11-21 21:34:30 UTC (rev 176472)
+++ trunk/Source/WebCore/WebCore.exp.in        2014-11-21 22:33:17 UTC (rev 176473)
</span><span class="lines">@@ -2593,6 +2593,7 @@
</span><span class="cx"> __ZN7WebCore11MathMLNames4initEv
</span><span class="cx"> __ZN7WebCore11MemoryCache18pruneDeadResourcesEv
</span><span class="cx"> __ZN7WebCore11MemoryCache18pruneLiveResourcesEb
</span><ins>+__ZN7WebCore11isCJKLocaleERKN3WTF12AtomicStringE
</ins><span class="cx"> __ZN7WebCore11isEndOfLineERKNS_15VisiblePositionE
</span><span class="cx"> __ZN7WebCore11prefetchDNSERKN3WTF6StringE
</span><span class="cx"> __ZN7WebCore12AudioSession11setCategoryENS0_12CategoryTypeE
</span><span class="lines">@@ -2705,7 +2706,7 @@
</span><span class="cx"> __ZN7WebCore24FloatingPointEnvironment21enableDenormalSupportEv
</span><span class="cx"> __ZN7WebCore24FloatingPointEnvironment25saveMainThreadEnvironmentEv
</span><span class="cx"> __ZN7WebCore24FloatingPointEnvironment6sharedEv
</span><del>-__ZN7WebCore24acquireLineBreakIteratorEN3WTF10StringViewERKNS0_12AtomicStringEPKtj
</del><ins>+__ZN7WebCore24acquireLineBreakIteratorEN3WTF10StringViewERKNS0_12AtomicStringEPKtjNS_21LineBreakIteratorModeEb
</ins><span class="cx"> __ZN7WebCore24charactersAroundPositionERKNS_15VisiblePositionERiS3_S3_
</span><span class="cx"> __ZN7WebCore24createTemporaryDirectoryEP8NSString
</span><span class="cx"> __ZN7WebCore24distanceBetweenPositionsERKNS_15VisiblePositionES2_
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformtextLineBreakIteratorPoolICUh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/text/LineBreakIteratorPoolICU.h (176472 => 176473)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/text/LineBreakIteratorPoolICU.h        2014-11-21 21:34:30 UTC (rev 176472)
+++ trunk/Source/WebCore/platform/text/LineBreakIteratorPoolICU.h        2014-11-21 22:33:17 UTC (rev 176473)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #ifndef LineBreakIteratorPoolICU_h
</span><span class="cx"> #define LineBreakIteratorPoolICU_h
</span><span class="cx"> 
</span><ins>+#include &quot;TextBreakIterator.h&quot;
</ins><span class="cx"> #include &quot;TextBreakIteratorInternalICU.h&quot;
</span><span class="cx"> #include &lt;unicode/ubrk.h&gt;
</span><span class="cx"> #include &lt;wtf/Assertions.h&gt;
</span><span class="lines">@@ -34,6 +35,7 @@
</span><span class="cx"> #include &lt;wtf/ThreadSpecific.h&gt;
</span><span class="cx"> #include &lt;wtf/text/AtomicString.h&gt;
</span><span class="cx"> #include &lt;wtf/text/CString.h&gt;
</span><ins>+#include &lt;wtf/text/StringBuilder.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -48,11 +50,39 @@
</span><span class="cx"> 
</span><span class="cx">     static PassOwnPtr&lt;LineBreakIteratorPool&gt; create() { return adoptPtr(new LineBreakIteratorPool); }
</span><span class="cx"> 
</span><del>-    UBreakIterator* take(const AtomicString&amp; locale)
</del><ins>+    static String makeLocaleWithBreakKeyword(const AtomicString&amp; locale, LineBreakIteratorMode mode)
</ins><span class="cx">     {
</span><del>-        UBreakIterator* iterator = 0;
</del><ins>+        StringBuilder localeWithKeyword;
+        localeWithKeyword.append(locale);
+        localeWithKeyword.appendLiteral(&quot;@break=&quot;);
+        switch (mode) {
+        case LineBreakIteratorModeUAX14:
+            ASSERT_NOT_REACHED();
+            break;
+        case LineBreakIteratorModeUAX14Loose:
+            localeWithKeyword.appendLiteral(&quot;loose&quot;);
+            break;
+        case LineBreakIteratorModeUAX14Normal:
+            localeWithKeyword.appendLiteral(&quot;normal&quot;);
+            break;
+        case LineBreakIteratorModeUAX14Strict:
+            localeWithKeyword.appendLiteral(&quot;strict&quot;);
+            break;
+        }
+        return localeWithKeyword.toString();
+    }
+
+    TextBreakIterator* take(const AtomicString&amp; locale, LineBreakIteratorMode mode, bool isCJK)
+    {
+        AtomicString localeWithOptionalBreakKeyword;
+        if (mode == LineBreakIteratorModeUAX14)
+            localeWithOptionalBreakKeyword = locale;
+        else
+            localeWithOptionalBreakKeyword = makeLocaleWithBreakKeyword(locale, mode);
+
+        TextBreakIterator* iterator = 0;
</ins><span class="cx">         for (size_t i = 0; i &lt; m_pool.size(); ++i) {
</span><del>-            if (m_pool[i].first == locale) {
</del><ins>+            if (m_pool[i].first == localeWithOptionalBreakKeyword) {
</ins><span class="cx">                 iterator = m_pool[i].second;
</span><span class="cx">                 m_pool.remove(i);
</span><span class="cx">                 break;
</span><span class="lines">@@ -60,33 +90,22 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (!iterator) {
</span><del>-            UErrorCode openStatus = U_ZERO_ERROR;
-            bool localeIsEmpty = locale.isEmpty();
-            iterator = ubrk_open(UBRK_LINE, localeIsEmpty ? currentTextBreakLocaleID() : locale.string().utf8().data(), 0, 0, &amp;openStatus);
-            // locale comes from a web page and it can be invalid, leading ICU
-            // to fail, in which case we fall back to the default locale.
-            if (!localeIsEmpty &amp;&amp; U_FAILURE(openStatus)) {
-                openStatus = U_ZERO_ERROR;
-                iterator = ubrk_open(UBRK_LINE, currentTextBreakLocaleID(), 0, 0, &amp;openStatus);
-            }
-                
-            if (U_FAILURE(openStatus)) {
-                LOG_ERROR(&quot;ubrk_open failed with status %d&quot;, openStatus);
</del><ins>+            iterator = openLineBreakIterator(localeWithOptionalBreakKeyword, mode, isCJK);
+            if (!iterator)
</ins><span class="cx">                 return 0;
</span><del>-            }
</del><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         ASSERT(!m_vendedIterators.contains(iterator));
</span><del>-        m_vendedIterators.set(iterator, locale);
</del><ins>+        m_vendedIterators.set(iterator, localeWithOptionalBreakKeyword);
</ins><span class="cx">         return iterator;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void put(UBreakIterator* iterator)
</del><ins>+    void put(TextBreakIterator* iterator)
</ins><span class="cx">     {
</span><span class="cx">         ASSERT_ARG(iterator, m_vendedIterators.contains(iterator));
</span><span class="cx"> 
</span><span class="cx">         if (m_pool.size() == capacity) {
</span><del>-            ubrk_close(m_pool[0].second);
</del><ins>+            closeLineBreakIterator(m_pool[0].second);
</ins><span class="cx">             m_pool.remove(0);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -98,10 +117,10 @@
</span><span class="cx"> 
</span><span class="cx">     static const size_t capacity = 4;
</span><span class="cx"> 
</span><del>-    typedef std::pair&lt;AtomicString, UBreakIterator*&gt; Entry;
</del><ins>+    typedef std::pair&lt;AtomicString, TextBreakIterator*&gt; Entry;
</ins><span class="cx">     typedef Vector&lt;Entry, capacity&gt; Pool;
</span><span class="cx">     Pool m_pool;
</span><del>-    HashMap&lt;UBreakIterator*, AtomicString&gt; m_vendedIterators;
</del><ins>+    HashMap&lt;TextBreakIterator*, AtomicString&gt; m_vendedIterators;
</ins><span class="cx"> 
</span><span class="cx">     friend WTF::ThreadSpecific&lt;LineBreakIteratorPool&gt;::operator LineBreakIteratorPool*();
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformtextTextBreakIteratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/text/TextBreakIterator.cpp (176472 => 176473)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/text/TextBreakIterator.cpp        2014-11-21 21:34:30 UTC (rev 176472)
+++ trunk/Source/WebCore/platform/text/TextBreakIterator.cpp        2014-11-21 22:33:17 UTC (rev 176473)
</span><span class="lines">@@ -256,9 +256,9 @@
</span><span class="cx">     return setTextForIterator(*staticCursorMovementIterator, string);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-TextBreakIterator* acquireLineBreakIterator(StringView string, const AtomicString&amp; locale, const UChar* priorContext, unsigned priorContextLength)
</del><ins>+TextBreakIterator* acquireLineBreakIterator(StringView string, const AtomicString&amp; locale, const UChar* priorContext, unsigned priorContextLength, LineBreakIteratorMode mode, bool isCJK)
</ins><span class="cx"> {
</span><del>-    TextBreakIterator* iterator = reinterpret_cast&lt;TextBreakIterator*&gt;(LineBreakIteratorPool::sharedPool().take(locale));
</del><ins>+    TextBreakIterator* iterator = LineBreakIteratorPool::sharedPool().take(locale, mode, isCJK);
</ins><span class="cx">     if (!iterator)
</span><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><span class="lines">@@ -269,9 +269,475 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT_ARG(iterator, iterator);
</span><span class="cx"> 
</span><del>-    LineBreakIteratorPool::sharedPool().put(reinterpret_cast&lt;UBreakIterator*&gt;(iterator));
</del><ins>+    LineBreakIteratorPool::sharedPool().put(iterator);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static const char* uax14Prologue =
+    &quot;!!chain;&quot;
+    &quot;!!LBCMNoChain;&quot;
+    &quot;!!lookAheadHardBreak;&quot;;
+
+static const char* uax14AssignmentsBefore =
+    // explicitly enumerate $CJ since ICU versions prior to 49 don't support :LineBreak=Conditional_Japanese_Starter:
+    &quot;$CJ = [&quot;
+#if (U_ICU_VERSION_MAJOR_NUM &gt;= 4) &amp;&amp; (U_ICU_VERSION_MINOR_NUM &gt;= 9)
+    &quot;:LineBreak=Conditional_Japanese_Starter:&quot;
+#else
+    &quot;\\u3041\\u3043\\u3045\\u3047\\u3049\\u3063\\u3083\\u3085\\u3087\\u308E\\u3095\\u3096\\u30A1\\u30A3\\u30A5\\u30A7&quot;
+    &quot;\\u30A9\\u30C3\\u30E3\\u30E5\\u30E7\\u30EE\\u30F5\\u30F6\\u30FC&quot;
+    &quot;\\u31F0\\u31F1\\u31F2\\u31F3\\u31F4\\u31F5\\u31F6\\u31F7\\u31F8\\u31F9\\u31FA\\u31FB\\u31FC\\u31FD\\u31FE\\u31FF&quot;
+    &quot;\\uFF67\\uFF68\\uFF69\\uFF6A\\uFF6B\\uFF6C\\uFF6D\\uFF6E\\uFF6F\\uFF70&quot;
+#endif
+    &quot;];&quot;;
+
+static const char* uax14AssignmentsCustomLooseCJK =
+    &quot;$BA_SUB = [\\u2010\\u2013];&quot;
+    &quot;$EX_SUB = [\\u0021\\u003F\\uFF01\\uFF1F];&quot;
+    &quot;$ID_SUB = '';&quot;
+    &quot;$IN_SUB = [\\u2025\\u2026];&quot;
+    &quot;$IS_SUB = [\\u003A\\u003B];&quot;
+    &quot;$NS_SUB = [\\u203C\\u2047\\u2048\\u2049\\u3005\\u301C\\u303B\\u309D\\u309E\\u30A0\\u30FB\\u30FD\\u30FE\\uFF1A\\uFF1B\\uFF65];&quot;
+    &quot;$PO_SUB = [\\u0025\\u00A2\\u00B0\\u2030\\u2032\\u2033\\u2103\\uFF05\\uFFE0];&quot;
+    &quot;$PR_SUB = [\\u0024\\u00A3\\u00A5\\u20AC\\u2116\\uFF04\\uFFE1\\uFFE5];&quot;
+    &quot;$ID_ADD = [$CJ $BA_SUB $EX_SUB $IN_SUB $IS_SUB $NS_SUB $PO_SUB $PR_SUB];&quot;
+    &quot;$NS_ADD = '';&quot;;
+
+static const char* uax14AssignmentsCustomLooseNonCJK =
+    &quot;$BA_SUB = '';&quot;
+    &quot;$EX_SUB = '';&quot;
+    &quot;$ID_SUB = '';&quot;
+    &quot;$IN_SUB = [\\u2025\\u2026];&quot;
+    &quot;$IS_SUB = '';&quot;
+    &quot;$NS_SUB = [\\u3005\\u303B\\u309D\\u309E\\u30FD\\u30FE];&quot;
+    &quot;$PO_SUB = '';&quot;
+    &quot;$PR_SUB = '';&quot;
+    &quot;$ID_ADD = [$CJ $IN_SUB $NS_SUB];&quot;
+    &quot;$NS_ADD = '';&quot;;
+
+static const char* uax14AssignmentsCustomNormalCJK =
+    &quot;$BA_SUB = [\\u2010\\u2013];&quot;
+    &quot;$EX_SUB = '';&quot;
+    &quot;$IN_SUB = '';&quot;
+    &quot;$ID_SUB = '';&quot;
+    &quot;$IS_SUB = '';&quot;
+    &quot;$NS_SUB = [\\u301C\\u30A0];&quot;
+    &quot;$PO_SUB = '';&quot;
+    &quot;$PR_SUB = '';&quot;
+    &quot;$ID_ADD = [$CJ $BA_SUB $NS_SUB];&quot;
+    &quot;$NS_ADD = '';&quot;;
+
+static const char* uax14AssignmentsCustomNormalNonCJK =
+    &quot;$BA_SUB = '';&quot;
+    &quot;$EX_SUB = '';&quot;
+    &quot;$ID_SUB = '';&quot;
+    &quot;$IN_SUB = '';&quot;
+    &quot;$IS_SUB = '';&quot;
+    &quot;$NS_SUB = '';&quot;
+    &quot;$PO_SUB = '';&quot;
+    &quot;$PR_SUB = '';&quot;
+    &quot;$ID_ADD = [$CJ];&quot;
+    &quot;$NS_ADD = '';&quot;;
+
+static const char* uax14AssignmentsCustomStrictCJK =
+    &quot;$BA_SUB = '';&quot;
+    &quot;$EX_SUB = '';&quot;
+    &quot;$ID_SUB = '';&quot;
+    &quot;$IN_SUB = '';&quot;
+    &quot;$IS_SUB = '';&quot;
+    &quot;$NS_SUB = '';&quot;
+    &quot;$PO_SUB = '';&quot;
+    &quot;$PR_SUB = '';&quot;
+    &quot;$ID_ADD = '';&quot;
+    &quot;$NS_ADD = [$CJ];&quot;;
+
+#define uax14AssignmentsCustomStrictNonCJK      uax14AssignmentsCustomStrictCJK
+#define uax14AssignmentsCustomDefaultCJK        uax14AssignmentsCustomNormalCJK
+#define uax14AssignmentsCustomDefaultNonCJK     uax14AssignmentsCustomStrictNonCJK
+
+static const char* uax14AssignmentsAfter =
+    &quot;$AI = [:LineBreak = Ambiguous:];&quot;
+    &quot;$AL = [:LineBreak = Alphabetic:];&quot;
+    &quot;$BA = [[:LineBreak = Break_After:] - $BA_SUB];&quot;
+    &quot;$BB = [:LineBreak = Break_Before:];&quot;
+    &quot;$BK = [:LineBreak = Mandatory_Break:];&quot;
+    &quot;$B2 = [:LineBreak = Break_Both:];&quot;
+    &quot;$CB = [:LineBreak = Contingent_Break:];&quot;
+    &quot;$CL = [:LineBreak = Close_Punctuation:];&quot;
+    &quot;$CM = [:LineBreak = Combining_Mark:];&quot;
+    &quot;$CP = [:LineBreak = Close_Parenthesis:];&quot;
+    &quot;$CR = [:LineBreak = Carriage_Return:];&quot;
+    &quot;$EX = [[:LineBreak = Exclamation:] - $EX_SUB];&quot;
+    &quot;$GL = [:LineBreak = Glue:];&quot;
+#if (U_ICU_VERSION_MAJOR_NUM &gt;= 4) &amp;&amp; (U_ICU_VERSION_MINOR_NUM &gt;= 9)
+    &quot;$HL = [:LineBreak = Hebrew_Letter:];&quot;
+#else
+    &quot;$HL = [[:Hebrew:] &amp; [:Letter:]];&quot;
+#endif
+    &quot;$HY = [:LineBreak = Hyphen:];&quot;
+    &quot;$H2 = [:LineBreak = H2:];&quot;
+    &quot;$H3 = [:LineBreak = H3:];&quot;
+    &quot;$ID = [[[[:LineBreak = Ideographic:] - $CJ] $ID_ADD] - $ID_SUB];&quot;
+    &quot;$IN = [[:LineBreak = Inseparable:] - $IN_SUB];&quot;
+    &quot;$IS = [[:LineBreak = Infix_Numeric:] - $IS_SUB];&quot;
+    &quot;$JL = [:LineBreak = JL:];&quot;
+    &quot;$JV = [:LineBreak = JV:];&quot;
+    &quot;$JT = [:LineBreak = JT:];&quot;
+    &quot;$LF = [:LineBreak = Line_Feed:];&quot;
+    &quot;$NL = [:LineBreak = Next_Line:];&quot;
+    &quot;$NS = [[[[:LineBreak = Nonstarter:] - $CJ] $NS_ADD] - $NS_SUB];&quot;
+    &quot;$NU = [:LineBreak = Numeric:];&quot;
+    &quot;$OP = [:LineBreak = Open_Punctuation:];&quot;
+    &quot;$PO = [[:LineBreak = Postfix_Numeric:] - $PO_SUB];&quot;
+    &quot;$PR = [[:LineBreak = Prefix_Numeric:] - $PR_SUB];&quot;
+    &quot;$QU = [:LineBreak = Quotation:];&quot;
+    &quot;$SA = [:LineBreak = Complex_Context:];&quot;
+    &quot;$SG = [:LineBreak = Surrogate:];&quot;
+    &quot;$SP = [:LineBreak = Space:];&quot;
+    &quot;$SY = [:LineBreak = Break_Symbols:];&quot;
+    &quot;$WJ = [:LineBreak = Word_Joiner:];&quot;
+    &quot;$XX = [:LineBreak = Unknown:];&quot;
+    &quot;$ZW = [:LineBreak = ZWSpace:];&quot;
+    &quot;$dictionary = [:LineBreak = Complex_Context:];&quot;
+    &quot;$ALPlus = [$AL $AI $SA $SG $XX];&quot;
+    &quot;$ALcm = $ALPlus $CM*;&quot;
+    &quot;$BAcm = $BA $CM*;&quot;
+    &quot;$BBcm = $BB $CM*;&quot;
+    &quot;$B2cm = $B2 $CM*;&quot;
+    &quot;$CLcm = $CL $CM*;&quot;
+    &quot;$CPcm = $CP $CM*;&quot;
+    &quot;$EXcm = $EX $CM*;&quot;
+    &quot;$GLcm = $GL $CM*;&quot;
+    &quot;$HLcm = $HL $CM*;&quot;
+    &quot;$HYcm = $HY $CM*;&quot;
+    &quot;$H2cm = $H2 $CM*;&quot;
+    &quot;$H3cm = $H3 $CM*;&quot;
+    &quot;$IDcm = $ID $CM*;&quot;
+    &quot;$INcm = $IN $CM*;&quot;
+    &quot;$IScm = $IS $CM*;&quot;
+    &quot;$JLcm = $JL $CM*;&quot;
+    &quot;$JVcm = $JV $CM*;&quot;
+    &quot;$JTcm = $JT $CM*;&quot;
+    &quot;$NScm = $NS $CM*;&quot;
+    &quot;$NUcm = $NU $CM*;&quot;
+    &quot;$OPcm = $OP $CM*;&quot;
+    &quot;$POcm = $PO $CM*;&quot;
+    &quot;$PRcm = $PR $CM*;&quot;
+    &quot;$QUcm = $QU $CM*;&quot;
+    &quot;$SYcm = $SY $CM*;&quot;
+    &quot;$WJcm = $WJ $CM*;&quot;;
+
+static const char* uax14Forward =
+    &quot;!!forward;&quot;
+    &quot;$CAN_CM = [^$SP $BK $CR $LF $NL $ZW $CM];&quot;
+    &quot;$CANT_CM = [$SP $BK $CR $LF $NL $ZW $CM];&quot;
+    &quot;$AL_FOLLOW_NOCM = [$BK $CR $LF $NL $ZW $SP];&quot;
+    &quot;$AL_FOLLOW_CM = [$CL $CP $EX $HL $IS $SY $WJ $GL $OP $QU $BA $HY $NS $IN $NU $ALPlus];&quot;
+    &quot;$AL_FOLLOW = [$AL_FOLLOW_NOCM $AL_FOLLOW_CM];&quot;
+    &quot;$LB4Breaks = [$BK $CR $LF $NL];&quot;
+    &quot;$LB4NonBreaks = [^$BK $CR $LF $NL];&quot;
+    &quot;$LB8Breaks = [$LB4Breaks $ZW];&quot;
+    &quot;$LB8NonBreaks = [[$LB4NonBreaks] - [$ZW]];&quot;
+    &quot;$LB18NonBreaks = [$LB8NonBreaks - [$SP]];&quot;
+    &quot;$LB18Breaks = [$LB8Breaks $SP];&quot;
+    &quot;$LB20NonBreaks = [$LB18NonBreaks - $CB];&quot;
+    &quot;$ALPlus $CM+;&quot;
+    &quot;$BA $CM+;&quot;
+    &quot;$BB $CM+;&quot;
+    &quot;$B2 $CM+;&quot;
+    &quot;$CL $CM+;&quot;
+    &quot;$CP $CM+;&quot;
+    &quot;$EX $CM+;&quot;
+    &quot;$GL $CM+;&quot;
+    &quot;$HL $CM+;&quot;
+    &quot;$HY $CM+;&quot;
+    &quot;$H2 $CM+;&quot;
+    &quot;$H3 $CM+;&quot;
+    &quot;$ID $CM+;&quot;
+    &quot;$IN $CM+;&quot;
+    &quot;$IS $CM+;&quot;
+    &quot;$JL $CM+;&quot;
+    &quot;$JV $CM+;&quot;
+    &quot;$JT $CM+;&quot;
+    &quot;$NS $CM+;&quot;
+    &quot;$NU $CM+;&quot;
+    &quot;$OP $CM+;&quot;
+    &quot;$PO $CM+;&quot;
+    &quot;$PR $CM+;&quot;
+    &quot;$QU $CM+;&quot;
+    &quot;$SY $CM+;&quot;
+    &quot;$WJ $CM+;&quot;
+    &quot;$CR $LF {100};&quot;
+    &quot;$LB4NonBreaks? $LB4Breaks {100};&quot;
+    &quot;$CAN_CM $CM* $LB4Breaks {100};&quot;
+    &quot;$CM+ $LB4Breaks {100};&quot;
+    &quot;$LB4NonBreaks [$SP $ZW];&quot;
+    &quot;$CAN_CM $CM* [$SP $ZW];&quot;
+    &quot;$CM+ [$SP $ZW];&quot;
+    &quot;$CAN_CM $CM+;&quot;
+    &quot;$CM+;&quot;
+    &quot;$CAN_CM $CM* $WJcm;&quot;
+    &quot;$LB8NonBreaks $WJcm;&quot;
+    &quot;$CM+ $WJcm;&quot;
+    &quot;$WJcm $CANT_CM;&quot;
+    &quot;$WJcm $CAN_CM $CM*;&quot;
+    &quot;$GLcm $CAN_CM $CM*;&quot;
+    &quot;$GLcm $CANT_CM;&quot;
+    &quot;[[$LB8NonBreaks] - [$SP $BA $HY]] $CM* $GLcm;&quot;
+    &quot;$CM+ GLcm;&quot;
+    &quot;$LB8NonBreaks $CL;&quot;
+    &quot;$CAN_CM $CM* $CL;&quot;
+    &quot;$CM+ $CL;&quot;
+    &quot;$LB8NonBreaks $CP;&quot;
+    &quot;$CAN_CM $CM* $CP;&quot;
+    &quot;$CM+ $CP;&quot;
+    &quot;$LB8NonBreaks $EX;&quot;
+    &quot;$CAN_CM $CM* $EX;&quot;
+    &quot;$CM+ $EX;&quot;
+    &quot;$LB8NonBreaks $IS;&quot;
+    &quot;$CAN_CM $CM* $IS;&quot;
+    &quot;$CM+ $IS;&quot;
+    &quot;$LB8NonBreaks $SY;&quot;
+    &quot;$CAN_CM $CM* $SY;&quot;
+    &quot;$CM+ $SY;&quot;
+    &quot;$OPcm $SP* $CAN_CM $CM*;&quot;
+    &quot;$OPcm $SP* $CANT_CM;&quot;
+    &quot;$OPcm $SP+ $CM+ $AL_FOLLOW?;&quot;
+    &quot;$QUcm $SP* $OPcm;&quot;
+    &quot;($CLcm | $CPcm) $SP* $NScm;&quot;
+    &quot;$B2cm $SP* $B2cm;&quot;
+    &quot;$LB18NonBreaks $CM* $QUcm;&quot;
+    &quot;$CM+ $QUcm;&quot;
+    &quot;$QUcm .?;&quot;
+    &quot;$QUcm $LB18NonBreaks $CM*;&quot;
+    &quot;$LB20NonBreaks $CM* ($BAcm | $HYcm | $NScm); &quot;
+    &quot;$BBcm [^$CB];&quot;
+    &quot;$BBcm $LB20NonBreaks $CM*;&quot;
+    &quot;$HLcm ($HYcm | $BAcm) [^$CB]?;&quot;
+    &quot;($ALcm | $HLcm) $INcm;&quot;
+    &quot;$CM+ $INcm;&quot;
+    &quot;$IDcm $INcm;&quot;
+    &quot;$INcm $INcm;&quot;
+    &quot;$NUcm $INcm;&quot;
+    &quot;$IDcm $POcm;&quot;
+    &quot;$ALcm $NUcm;&quot;
+    &quot;$HLcm $NUcm;&quot;
+    &quot;$CM+ $NUcm;&quot;
+    &quot;$NUcm $ALcm;&quot;
+    &quot;$NUcm $HLcm;&quot;
+    &quot;$PRcm $IDcm;&quot;
+    &quot;$PRcm ($ALcm | $HLcm);&quot;
+    &quot;$POcm ($ALcm | $HLcm);&quot;
+    &quot;($PRcm | $POcm)? ($OPcm | $HYcm)? $NUcm ($NUcm | $SYcm | $IScm)* ($CLcm | $CPcm)? ($PRcm | $POcm)?;&quot;
+    &quot;$JLcm ($JLcm | $JVcm | $H2cm | $H3cm);&quot;
+    &quot;($JVcm | $H2cm) ($JVcm | $JTcm);&quot;
+    &quot;($JTcm | $H3cm) $JTcm;&quot;
+    &quot;($JLcm | $JVcm | $JTcm | $H2cm | $H3cm) $INcm;&quot;
+    &quot;($JLcm | $JVcm | $JTcm | $H2cm | $H3cm) $POcm;&quot;
+    &quot;$PRcm ($JLcm | $JVcm | $JTcm | $H2cm | $H3cm);&quot;
+    &quot;($ALcm | $HLcm) ($ALcm | $HLcm);&quot;
+    &quot;$CM+ ($ALcm | $HLcm);&quot;
+    &quot;$IScm ($ALcm | $HLcm);&quot;
+    &quot;($ALcm | $HLcm | $NUcm) $OPcm;&quot;
+    &quot;$CM+ $OPcm;&quot;
+    &quot;$CPcm ($ALcm | $HLcm | $NUcm);&quot;;
+
+static const char* uax14Reverse =
+    &quot;!!reverse;&quot;
+    &quot;$CM+ $ALPlus;&quot;
+    &quot;$CM+ $BA;&quot;
+    &quot;$CM+ $BB;&quot;
+    &quot;$CM+ $B2;&quot;
+    &quot;$CM+ $CL;&quot;
+    &quot;$CM+ $CP;&quot;
+    &quot;$CM+ $EX;&quot;
+    &quot;$CM+ $GL;&quot;
+    &quot;$CM+ $HL;&quot;
+    &quot;$CM+ $HY;&quot;
+    &quot;$CM+ $H2;&quot;
+    &quot;$CM+ $H3;&quot;
+    &quot;$CM+ $ID;&quot;
+    &quot;$CM+ $IN;&quot;
+    &quot;$CM+ $IS;&quot;
+    &quot;$CM+ $JL;&quot;
+    &quot;$CM+ $JV;&quot;
+    &quot;$CM+ $JT;&quot;
+    &quot;$CM+ $NS;&quot;
+    &quot;$CM+ $NU;&quot;
+    &quot;$CM+ $OP;&quot;
+    &quot;$CM+ $PO;&quot;
+    &quot;$CM+ $PR;&quot;
+    &quot;$CM+ $QU;&quot;
+    &quot;$CM+ $SY;&quot;
+    &quot;$CM+ $WJ;&quot;
+    &quot;$CM+;&quot;
+    &quot;$AL_FOLLOW $CM+ / ([$BK $CR $LF $NL $ZW {eof}] | $SP+ $CM+ $SP | $SP+ $CM* ([^$OP $CM $SP] | [$AL {eof}]));&quot;
+    &quot;[$PR] / $CM+ [$BK $CR $LF $NL $ZW $SP {eof}];&quot;
+    &quot;$LB4Breaks [$LB4NonBreaks-$CM];&quot;
+    &quot;$LB4Breaks $CM+ $CAN_CM;&quot;
+    &quot;$LF $CR;&quot;
+    &quot;[$SP $ZW] [$LB4NonBreaks-$CM];&quot;
+    &quot;[$SP $ZW] $CM+ $CAN_CM;&quot;
+    &quot;$CM+ $CAN_CM;&quot;
+    &quot;$CM* $WJ $CM* $CAN_CM;&quot;
+    &quot;$CM* $WJ [$LB8NonBreaks-$CM];&quot;
+    &quot;$CANT_CM $CM* $WJ;&quot;
+    &quot;$CM* $CAN_CM $CM* $WJ;&quot;
+    &quot;$CM* $GL $CM* [$LB8NonBreaks-[$CM $SP $BA $HY]];&quot;
+    &quot;$CANT_CM $CM* $GL;&quot;
+    &quot;$CM* $CAN_CM $CM* $GL;&quot;
+    &quot;$CL $CM+ $CAN_CM;&quot;
+    &quot;$CP $CM+ $CAN_CM;&quot;
+    &quot;$EX $CM+ $CAN_CM;&quot;
+    &quot;$IS $CM+ $CAN_CM;&quot;
+    &quot;$SY $CM+ $CAN_CM;&quot;
+    &quot;$CL [$LB8NonBreaks-$CM];&quot;
+    &quot;$CP [$LB8NonBreaks-$CM];&quot;
+    &quot;$EX [$LB8NonBreaks-$CM];&quot;
+    &quot;$IS [$LB8NonBreaks-$CM];&quot;
+    &quot;$SY [$LB8NonBreaks-$CM];&quot;
+    &quot;[$CL $CP $EX $IS $SY] $CM+ $SP+ $CM* $OP; &quot;
+    &quot;$CM* $CAN_CM $SP* $CM* $OP;&quot;
+    &quot;$CANT_CM $SP* $CM* $OP;&quot;
+    &quot;$AL_FOLLOW? $CM+ $SP $SP* $CM* $OP;&quot;
+    &quot;$AL_FOLLOW_NOCM $CM+ $SP+ $CM* $OP;&quot;
+    &quot;$CM* $AL_FOLLOW_CM $CM+ $SP+ $CM* $OP;&quot;
+    &quot;$SY $CM $SP+ $OP;&quot;
+    &quot;$CM* $OP $SP* $CM* $QU;&quot;
+    &quot;$CM* $NS $SP* $CM* ($CL | $CP);&quot;
+    &quot;$CM* $B2 $SP* $CM* $B2;&quot;
+    &quot;$CM* $QU $CM* $CAN_CM;&quot;
+    &quot;$CM* $QU $LB18NonBreaks;&quot;
+    &quot;$CM* $CAN_CM $CM* $QU;&quot;
+    &quot;$CANT_CM $CM* $QU;&quot;
+    &quot;$CM* ($BA | $HY | $NS) $CM* [$LB20NonBreaks-$CM];&quot;
+    &quot;$CM* [$LB20NonBreaks-$CM] $CM* $BB;&quot;
+    &quot;[^$CB] $CM* $BB;&quot;
+    &quot;[^$CB] $CM* ($HY | $BA) $CM* $HL;&quot;
+    &quot;$CM* $IN $CM* ($ALPlus | $HL);&quot;
+    &quot;$CM* $IN $CM* $ID;&quot;
+    &quot;$CM* $IN $CM* $IN;&quot;
+    &quot;$CM* $IN $CM* $NU;&quot;
+    &quot;$CM* $PO $CM* $ID;&quot;
+    &quot;$CM* $NU $CM* ($ALPlus | $HL);&quot;
+    &quot;$CM* ($ALPlus | $HL) $CM* $NU;&quot;
+    &quot;$CM* $ID $CM* $PR;&quot;
+    &quot;$CM* ($ALPlus | $HL) $CM* $PR;&quot;
+    &quot;$CM* ($ALPlus | $HL) $CM* $PO;&quot;
+    &quot;($CM* ($PR | $PO))? ($CM* ($CL | $CP))? ($CM* ($NU | $IS | $SY))* $CM* $NU ($CM* ($OP | $HY))? ($CM* ($PR | $PO))?;&quot;
+    &quot;$CM* ($H3 | $H2 | $JV | $JL) $CM* $JL;&quot;
+    &quot;$CM* ($JT | $JV) $CM* ($H2 | $JV);&quot;
+    &quot;$CM* $JT $CM* ($H3 | $JT);&quot;
+    &quot;$CM* $IN $CM* ($H3 | $H2 | $JT | $JV | $JL);&quot;
+    &quot;$CM* $PO $CM* ($H3 | $H2 | $JT | $JV | $JL);&quot;
+    &quot;$CM* ($H3 | $H2 | $JT | $JV | $JL) $CM* $PR;&quot;
+    &quot;$CM* ($ALPlus | $HL) $CM* ($ALPlus | $HL);&quot;
+    &quot;$CM* ($ALPlus | $HL) $CM* $IS;&quot;
+    &quot;$CM* $OP $CM* ($ALPlus | $HL | $NU);&quot;
+    &quot;$CM* ($ALPlus | $HL | $NU) $CM* $CP;&quot;;
+
+static const char* uax14SafeForward =
+    &quot;!!safe_forward;&quot;
+    &quot;[$CM $OP $QU $CL $CP $B2 $PR $HY $BA $SP $dictionary]+ [^$CM $OP $QU $CL $CP $B2 $PR $HY $BA $dictionary];&quot;
+    &quot;$dictionary $dictionary;&quot;;
+
+static const char* uax14SafeReverse =
+    &quot;!!safe_reverse;&quot;
+    &quot;$CM+ [^$CM $BK $CR $LF $NL $ZW $SP];&quot;
+    &quot;$CM+ $SP / .;&quot;
+    &quot;$SP+ $CM* $OP;&quot;
+    &quot;$SP+ $CM* $QU;&quot;
+    &quot;$SP+ $CM* ($CL | $CP);&quot;
+    &quot;$SP+ $CM* $B2;&quot;
+    &quot;$CM* ($HY | $BA) $CM* $HL;&quot;
+    &quot;($CM* ($IS | $SY))+ $CM* $NU;&quot;
+    &quot;($CL | $CP) $CM* ($NU | $IS | $SY);&quot;
+    &quot;$dictionary $dictionary;&quot;;
+
+static String mapLineIteratorModeToRules(LineBreakIteratorMode mode, bool isCJK)
+{
+    StringBuilder rulesBuilder;
+    rulesBuilder.append(uax14Prologue);
+    rulesBuilder.append(uax14AssignmentsBefore);
+    switch (mode) {
+    case LineBreakIteratorModeUAX14:
+        rulesBuilder.append(isCJK ? uax14AssignmentsCustomDefaultCJK : uax14AssignmentsCustomDefaultNonCJK);
+        break;
+    case LineBreakIteratorModeUAX14Loose:
+        rulesBuilder.append(isCJK ? uax14AssignmentsCustomLooseCJK : uax14AssignmentsCustomLooseNonCJK);
+        break;
+    case LineBreakIteratorModeUAX14Normal:
+        rulesBuilder.append(isCJK ? uax14AssignmentsCustomNormalCJK : uax14AssignmentsCustomNormalNonCJK);
+        break;
+    case LineBreakIteratorModeUAX14Strict:
+        rulesBuilder.append(isCJK ? uax14AssignmentsCustomStrictCJK : uax14AssignmentsCustomStrictNonCJK);
+        break;
+    }
+    rulesBuilder.append(uax14AssignmentsAfter);
+    rulesBuilder.append(uax14Forward);
+    rulesBuilder.append(uax14Reverse);
+    rulesBuilder.append(uax14SafeForward);
+    rulesBuilder.append(uax14SafeReverse);
+    return rulesBuilder.toString();
+}
+
+// Recognize BCP47 compliant primary language values of 'zh', 'ja', 'ko'
+// (in any combination of case), optionally followed by subtags. Don't
+// recognize 3-letter variants 'chi'/'zho', 'jpn', or 'kor' since BCP47
+// requires use of shortest language tag.
+bool isCJKLocale(const AtomicString&amp; locale)
+{
+    size_t length = locale.length();
+    if (length &lt; 2)
+        return false;
+    auto c1 = locale[0];
+    auto c2 = locale[1];
+    auto c3 = length == 2 ? 0 : locale[2];
+    if (!c3 || c3 == '-' || c3 == '_' || c3 == '@') {
+        if (c1 == 'z' || c1 == 'Z')
+            return c2 == 'h' || c2 == 'H';
+        if (c1 == 'j' || c1 == 'J')
+            return c2 == 'a' || c2 == 'A';
+        if (c1 == 'k' || c1 == 'K')
+            return c2 == 'o' || c2 == 'O';
+    }
+    return false;
+}
+
+TextBreakIterator* openLineBreakIterator(const AtomicString&amp; locale, LineBreakIteratorMode mode, bool isCJK)
+{
+    UBreakIterator* ubrkIter;
+    UErrorCode openStatus = U_ZERO_ERROR;
+    bool localeIsEmpty = locale.isEmpty();
+    if (mode == LineBreakIteratorModeUAX14)
+        ubrkIter = ubrk_open(UBRK_LINE, localeIsEmpty ? currentTextBreakLocaleID() : locale.string().utf8().data(), 0, 0, &amp;openStatus);
+    else {
+        UParseError parseStatus;
+        auto rules = mapLineIteratorModeToRules(mode, isCJK);
+        ubrkIter = ubrk_openRules(StringView(rules).upconvertedCharacters(), rules.length(), 0, 0, &amp;parseStatus, &amp;openStatus);
+    }
+    // locale comes from a web page and it can be invalid, leading ICU
+    // to fail, in which case we fall back to the default locale.
+    if (!localeIsEmpty &amp;&amp; U_FAILURE(openStatus)) {
+        openStatus = U_ZERO_ERROR;
+        ubrkIter = ubrk_open(UBRK_LINE, currentTextBreakLocaleID(), 0, 0, &amp;openStatus);
+    }
+
+    if (U_FAILURE(openStatus)) {
+        LOG_ERROR(&quot;ubrk_open failed with status %d&quot;, openStatus);
+        return nullptr;
+    }
+
+    return reinterpret_cast&lt;TextBreakIterator*&gt;(ubrkIter);
+}
+
+void closeLineBreakIterator(TextBreakIterator*&amp; iterator)
+{
+    UBreakIterator* ubrkIter = reinterpret_cast&lt;UBreakIterator*&gt;(iterator);
+    ASSERT(ubrkIter);
+    ubrk_close(ubrkIter);
+    iterator = nullptr;
+}
+
</ins><span class="cx"> static TextBreakIterator* nonSharedCharacterBreakIterator;
</span><span class="cx"> 
</span><span class="cx"> static inline bool compareAndSwapNonSharedCharacterBreakIterator(TextBreakIterator* expected, TextBreakIterator* newValue)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformtextTextBreakIteratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/text/TextBreakIterator.h (176472 => 176473)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/text/TextBreakIterator.h        2014-11-21 21:34:30 UTC (rev 176472)
+++ trunk/Source/WebCore/platform/text/TextBreakIterator.h        2014-11-21 22:33:17 UTC (rev 176473)
</span><span class="lines">@@ -31,6 +31,13 @@
</span><span class="cx"> 
</span><span class="cx"> // Note: The returned iterator is good only until you get another iterator, with the exception of acquireLineBreakIterator.
</span><span class="cx"> 
</span><ins>+enum LineBreakIteratorMode {
+    LineBreakIteratorModeUAX14,
+    LineBreakIteratorModeUAX14Loose,
+    LineBreakIteratorModeUAX14Normal,
+    LineBreakIteratorModeUAX14Strict,
+};
+
</ins><span class="cx"> // This is similar to character break iterator in most cases, but is subject to
</span><span class="cx"> // platform UI conventions. One notable example where this can be different
</span><span class="cx"> // from character break iterator is Thai prepend characters, see bug 24342.
</span><span class="lines">@@ -40,8 +47,10 @@
</span><span class="cx"> TextBreakIterator* wordBreakIterator(StringView);
</span><span class="cx"> TextBreakIterator* sentenceBreakIterator(StringView);
</span><span class="cx"> 
</span><del>-WEBCORE_EXPORT TextBreakIterator* acquireLineBreakIterator(StringView, const AtomicString&amp; locale, const UChar* priorContext, unsigned priorContextLength);
</del><ins>+WEBCORE_EXPORT TextBreakIterator* acquireLineBreakIterator(StringView, const AtomicString&amp; locale, const UChar* priorContext, unsigned priorContextLength, LineBreakIteratorMode, bool isCJK);
</ins><span class="cx"> WEBCORE_EXPORT void releaseLineBreakIterator(TextBreakIterator*);
</span><ins>+TextBreakIterator* openLineBreakIterator(const AtomicString&amp; locale, LineBreakIteratorMode, bool isCJK);
+void closeLineBreakIterator(TextBreakIterator*&amp;);
</ins><span class="cx"> 
</span><span class="cx"> int textBreakFirst(TextBreakIterator*);
</span><span class="cx"> int textBreakLast(TextBreakIterator*);
</span><span class="lines">@@ -55,24 +64,30 @@
</span><span class="cx"> 
</span><span class="cx"> const int TextBreakDone = -1;
</span><span class="cx"> 
</span><ins>+bool isCJKLocale(const AtomicString&amp;);
+
</ins><span class="cx"> class LazyLineBreakIterator {
</span><span class="cx"> public:
</span><span class="cx">     LazyLineBreakIterator()
</span><del>-        : m_iterator(0)
-        , m_cachedPriorContext(0)
</del><ins>+        : m_iterator(nullptr)
+        , m_cachedPriorContext(nullptr)
+        , m_mode(LineBreakIteratorModeUAX14)
</ins><span class="cx">         , m_cachedPriorContextLength(0)
</span><ins>+        , m_isCJK(false)
</ins><span class="cx">     {
</span><span class="cx">         resetPriorContext();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    LazyLineBreakIterator(String string, const AtomicString&amp; locale = AtomicString())
</del><ins>+    LazyLineBreakIterator(String string, const AtomicString&amp; locale = AtomicString(), LineBreakIteratorMode mode = LineBreakIteratorModeUAX14)
</ins><span class="cx">         : m_string(string)
</span><span class="cx">         , m_locale(locale)
</span><del>-        , m_iterator(0)
-        , m_cachedPriorContext(0)
</del><ins>+        , m_iterator(nullptr)
+        , m_cachedPriorContext(nullptr)
+        , m_mode(mode)
</ins><span class="cx">         , m_cachedPriorContextLength(0)
</span><span class="cx">     {
</span><span class="cx">         resetPriorContext();
</span><ins>+        m_isCJK = isCJKLocale(locale);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ~LazyLineBreakIterator()
</span><span class="lines">@@ -82,35 +97,41 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     String string() const { return m_string; }
</span><ins>+    bool isLooseCJKMode() const { return m_isCJK &amp;&amp; m_mode == LineBreakIteratorModeUAX14Loose; }
</ins><span class="cx"> 
</span><span class="cx">     UChar lastCharacter() const
</span><span class="cx">     {
</span><span class="cx">         COMPILE_ASSERT(WTF_ARRAY_LENGTH(m_priorContext) == 2, TextBreakIterator_unexpected_prior_context_length);
</span><span class="cx">         return m_priorContext[1];
</span><span class="cx">     }
</span><ins>+
</ins><span class="cx">     UChar secondToLastCharacter() const
</span><span class="cx">     {
</span><span class="cx">         COMPILE_ASSERT(WTF_ARRAY_LENGTH(m_priorContext) == 2, TextBreakIterator_unexpected_prior_context_length);
</span><span class="cx">         return m_priorContext[0];
</span><span class="cx">     }
</span><ins>+
</ins><span class="cx">     void setPriorContext(UChar last, UChar secondToLast)
</span><span class="cx">     {
</span><span class="cx">         COMPILE_ASSERT(WTF_ARRAY_LENGTH(m_priorContext) == 2, TextBreakIterator_unexpected_prior_context_length);
</span><span class="cx">         m_priorContext[0] = secondToLast;
</span><span class="cx">         m_priorContext[1] = last;
</span><span class="cx">     }
</span><ins>+
</ins><span class="cx">     void updatePriorContext(UChar last)
</span><span class="cx">     {
</span><span class="cx">         COMPILE_ASSERT(WTF_ARRAY_LENGTH(m_priorContext) == 2, TextBreakIterator_unexpected_prior_context_length);
</span><span class="cx">         m_priorContext[0] = m_priorContext[1];
</span><span class="cx">         m_priorContext[1] = last;
</span><span class="cx">     }
</span><ins>+
</ins><span class="cx">     void resetPriorContext()
</span><span class="cx">     {
</span><span class="cx">         COMPILE_ASSERT(WTF_ARRAY_LENGTH(m_priorContext) == 2, TextBreakIterator_unexpected_prior_context_length);
</span><span class="cx">         m_priorContext[0] = 0;
</span><span class="cx">         m_priorContext[1] = 0;
</span><span class="cx">     }
</span><ins>+
</ins><span class="cx">     unsigned priorContextLength() const
</span><span class="cx">     {
</span><span class="cx">         unsigned priorContextLength = 0;
</span><span class="lines">@@ -122,6 +143,7 @@
</span><span class="cx">         }
</span><span class="cx">         return priorContextLength;
</span><span class="cx">     }
</span><ins>+
</ins><span class="cx">     // Obtain text break iterator, possibly previously cached, where this iterator is (or has been)
</span><span class="cx">     // initialized to use the previously stored string as the primary breaking context and using
</span><span class="cx">     // previously stored prior context if non-empty.
</span><span class="lines">@@ -130,23 +152,26 @@
</span><span class="cx">         ASSERT(priorContextLength &lt;= priorContextCapacity);
</span><span class="cx">         const UChar* priorContext = priorContextLength ? &amp;m_priorContext[priorContextCapacity - priorContextLength] : 0;
</span><span class="cx">         if (!m_iterator) {
</span><del>-            m_iterator = acquireLineBreakIterator(m_string, m_locale, priorContext, priorContextLength);
</del><ins>+            m_iterator = acquireLineBreakIterator(m_string, m_locale, priorContext, priorContextLength, m_mode, m_isCJK);
</ins><span class="cx">             m_cachedPriorContext = priorContext;
</span><span class="cx">             m_cachedPriorContextLength = priorContextLength;
</span><span class="cx">         } else if (priorContext != m_cachedPriorContext || priorContextLength != m_cachedPriorContextLength) {
</span><del>-            this-&gt;resetStringAndReleaseIterator(m_string, m_locale);
</del><ins>+            resetStringAndReleaseIterator(m_string, m_locale, m_mode);
</ins><span class="cx">             return this-&gt;get(priorContextLength);
</span><span class="cx">         }
</span><span class="cx">         return m_iterator;
</span><span class="cx">     }
</span><del>-    void resetStringAndReleaseIterator(String string, const AtomicString&amp; locale)
</del><ins>+
+    void resetStringAndReleaseIterator(String string, const AtomicString&amp; locale, LineBreakIteratorMode mode)
</ins><span class="cx">     {
</span><span class="cx">         if (m_iterator)
</span><span class="cx">             releaseLineBreakIterator(m_iterator);
</span><span class="cx">         m_string = string;
</span><span class="cx">         m_locale = locale;
</span><del>-        m_iterator = 0;
-        m_cachedPriorContext = 0;
</del><ins>+        m_iterator = nullptr;
+        m_cachedPriorContext = nullptr;
+        m_mode = mode;
+        m_isCJK = isCJKLocale(locale);
</ins><span class="cx">         m_cachedPriorContextLength = 0;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -155,9 +180,11 @@
</span><span class="cx">     String m_string;
</span><span class="cx">     AtomicString m_locale;
</span><span class="cx">     TextBreakIterator* m_iterator;
</span><del>-    UChar m_priorContext[priorContextCapacity];
</del><span class="cx">     const UChar* m_cachedPriorContext;
</span><ins>+    LineBreakIteratorMode m_mode;
</ins><span class="cx">     unsigned m_cachedPriorContextLength;
</span><ins>+    UChar m_priorContext[priorContextCapacity];
+    bool m_isCJK;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> // Iterates over &quot;extended grapheme clusters&quot;, as defined in UAX #29.
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderTextcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderText.cpp (176472 => 176473)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderText.cpp        2014-11-21 21:34:30 UTC (rev 176472)
+++ trunk/Source/WebCore/rendering/RenderText.cpp        2014-11-21 22:33:17 UTC (rev 176473)
</span><span class="lines">@@ -597,6 +597,22 @@
</span><span class="cx">     return m_maxWidth;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+LineBreakIteratorMode mapLineBreakToIteratorMode(LineBreak lineBreak)
+{
+    switch (lineBreak) {
+    case LineBreakAuto:
+    case LineBreakAfterWhiteSpace:
+        return LineBreakIteratorModeUAX14;
+    case LineBreakLoose:
+        return LineBreakIteratorModeUAX14Loose;
+    case LineBreakNormal:
+        return LineBreakIteratorModeUAX14Normal;
+    case LineBreakStrict:
+        return LineBreakIteratorModeUAX14Strict;
+    }
+    return LineBreakIteratorModeUAX14;
+}
+
</ins><span class="cx"> void RenderText::computePreferredLogicalWidths(float leadWidth)
</span><span class="cx"> {
</span><span class="cx">     HashSet&lt;const SimpleFontData*&gt; fallbackFonts;
</span><span class="lines">@@ -673,7 +689,7 @@
</span><span class="cx">     const Font&amp; font = style.font(); // FIXME: This ignores first-line.
</span><span class="cx">     float wordSpacing = font.wordSpacing();
</span><span class="cx">     int len = textLength();
</span><del>-    LazyLineBreakIterator breakIterator(m_text, style.locale());
</del><ins>+    LazyLineBreakIterator breakIterator(m_text, style.locale(), mapLineBreakToIteratorMode(style.lineBreak()));
</ins><span class="cx">     bool needsWordSpacing = false;
</span><span class="cx">     bool ignoringSpaces = false;
</span><span class="cx">     bool isSpace = false;
</span><span class="lines">@@ -708,6 +724,7 @@
</span><span class="cx"> 
</span><span class="cx">     bool breakNBSP = style.autoWrap() &amp;&amp; style.nbspMode() == SPACE;
</span><span class="cx">     bool breakAll = (style.wordBreak() == BreakAllWordBreak || style.wordBreak() == BreakWordBreak) &amp;&amp; style.autoWrap();
</span><ins>+    bool isLooseCJKMode = breakIterator.isLooseCJKMode();
</ins><span class="cx"> 
</span><span class="cx">     for (int i = 0; i &lt; len; i++) {
</span><span class="cx">         UChar c = uncheckedCharacterAt(i);
</span><span class="lines">@@ -755,7 +772,7 @@
</span><span class="cx">             continue;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        bool hasBreak = breakAll || isBreakable(breakIterator, i, nextBreakable, breakNBSP);
</del><ins>+        bool hasBreak = breakAll || isBreakable(breakIterator, i, nextBreakable, breakNBSP, isLooseCJKMode);
</ins><span class="cx">         bool betweenWords = true;
</span><span class="cx">         int j = i;
</span><span class="cx">         while (c != '\n' &amp;&amp; !isSpaceAccordingToStyle(c, style) &amp;&amp; c != '\t' &amp;&amp; (c != softHyphen || style.hyphens() == HyphensNone)) {
</span><span class="lines">@@ -763,7 +780,7 @@
</span><span class="cx">             if (j == len)
</span><span class="cx">                 break;
</span><span class="cx">             c = uncheckedCharacterAt(j);
</span><del>-            if (isBreakable(breakIterator, j, nextBreakable, breakNBSP) &amp;&amp; characterAt(j - 1) != softHyphen)
</del><ins>+            if (isBreakable(breakIterator, j, nextBreakable, breakNBSP, isLooseCJKMode) &amp;&amp; characterAt(j - 1) != softHyphen)
</ins><span class="cx">                 break;
</span><span class="cx">             if (breakAll) {
</span><span class="cx">                 betweenWords = false;
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderTexth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderText.h (176472 => 176473)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderText.h        2014-11-21 21:34:30 UTC (rev 176472)
+++ trunk/Source/WebCore/rendering/RenderText.h        2014-11-21 22:33:17 UTC (rev 176473)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> #include &quot;RenderTextLineBoxes.h&quot;
</span><span class="cx"> #include &quot;SimpleLineLayout.h&quot;
</span><span class="cx"> #include &quot;Text.h&quot;
</span><ins>+#include &quot;TextBreakIterator.h&quot;
</ins><span class="cx"> #include &lt;wtf/Forward.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="lines">@@ -274,6 +275,7 @@
</span><span class="cx"> 
</span><span class="cx"> void applyTextTransform(const RenderStyle&amp;, String&amp;, UChar);
</span><span class="cx"> void makeCapitalized(String*, UChar previous);
</span><ins>+LineBreakIteratorMode mapLineBreakToIteratorMode(LineBreak);
</ins><span class="cx">     
</span><span class="cx"> inline RenderText* Text::renderer() const
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingSimpleLineLayoutcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/SimpleLineLayout.cpp (176472 => 176473)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/SimpleLineLayout.cpp        2014-11-21 21:34:30 UTC (rev 176472)
+++ trunk/Source/WebCore/rendering/SimpleLineLayout.cpp        2014-11-21 22:33:17 UTC (rev 176473)
</span><span class="lines">@@ -161,6 +161,8 @@
</span><span class="cx">         return false;
</span><span class="cx">     if (style.borderFit() == BorderFitLines)
</span><span class="cx">         return false;
</span><ins>+    if (style.lineBreak() != LineBreakAuto)
+        return false;
</ins><span class="cx">     const RenderText&amp; textRenderer = downcast&lt;RenderText&gt;(*flow.firstChild());
</span><span class="cx">     if (flow.containsFloats()) {
</span><span class="cx">         // We can't use the code path if any lines would need to be shifted below floats. This is because we don't keep per-line y coordinates.
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingSimpleLineLayoutFlowContentscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.cpp (176472 => 176473)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.cpp        2014-11-21 21:34:30 UTC (rev 176472)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.cpp        2014-11-21 22:33:17 UTC (rev 176473)
</span><span class="lines">@@ -53,7 +53,7 @@
</span><span class="cx"> unsigned FlowContents::findNextBreakablePosition(unsigned position) const
</span><span class="cx"> {
</span><span class="cx">     String string = m_lineBreakIterator.string();
</span><del>-    unsigned breakablePosition = nextBreakablePosition&lt;LChar, false&gt;(m_lineBreakIterator, string.characters8(), string.length(), position);
</del><ins>+    unsigned breakablePosition = nextBreakablePositionNonLoosely&lt;LChar, NBSPBehavior::IgnoreNBSP&gt;(m_lineBreakIterator, string.characters8(), string.length(), position);
</ins><span class="cx">     if (appendNextRendererContentIfNeeded(breakablePosition))
</span><span class="cx">         return findNextBreakablePosition(position);
</span><span class="cx">     ASSERT(breakablePosition &gt;= position);
</span><span class="lines">@@ -157,7 +157,7 @@
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     ++m_lastRendererIndex;
</span><del>-    m_lineBreakIterator.resetStringAndReleaseIterator(string + String(nextRenderer-&gt;text()), m_flow.style().locale());
</del><ins>+    m_lineBreakIterator.resetStringAndReleaseIterator(string + String(nextRenderer-&gt;text()), m_flow.style().locale(), LineBreakIteratorModeUAX14);
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingbreak_linesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/break_lines.h (176472 => 176473)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/break_lines.h        2014-11-21 21:34:30 UTC (rev 176472)
+++ trunk/Source/WebCore/rendering/break_lines.h        2014-11-21 22:33:17 UTC (rev 176473)
</span><span class="lines">@@ -35,10 +35,12 @@
</span><span class="cx"> 
</span><span class="cx"> extern const unsigned char asciiLineBreakTable[][asciiLineBreakTableColumnCount];
</span><span class="cx"> 
</span><del>-int nextBreakablePositionIgnoringNBSP(LazyLineBreakIterator&amp;, int pos);
-int nextBreakablePosition(LazyLineBreakIterator&amp;, int pos);
</del><ins>+enum class NBSPBehavior {
+    IgnoreNBSP,
+    TreatNBSPAsBreak,
+};
</ins><span class="cx"> 
</span><del>-template&lt;bool treatNoBreakSpaceAsBreak&gt;
</del><ins>+template&lt;NBSPBehavior nbspBehavior&gt;
</ins><span class="cx"> static inline bool isBreakableSpace(UChar ch)
</span><span class="cx"> {
</span><span class="cx">     switch (ch) {
</span><span class="lines">@@ -47,7 +49,7 @@
</span><span class="cx">     case '\t':
</span><span class="cx">         return true;
</span><span class="cx">     case noBreakSpace:
</span><del>-        return treatNoBreakSpaceAsBreak;
</del><ins>+        return nbspBehavior == NBSPBehavior::TreatNBSPAsBreak;
</ins><span class="cx">     default:
</span><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="lines">@@ -71,16 +73,17 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;bool treatNoBreakSpaceAsBreak&gt;
</del><ins>+template&lt;NBSPBehavior nbspBehavior&gt;
</ins><span class="cx"> inline bool needsLineBreakIterator(UChar ch)
</span><span class="cx"> {
</span><del>-    if (treatNoBreakSpaceAsBreak)
</del><ins>+    if (nbspBehavior == NBSPBehavior::TreatNBSPAsBreak)
</ins><span class="cx">         return ch &gt; asciiLineBreakTableLastChar;
</span><span class="cx">     return ch &gt; asciiLineBreakTableLastChar &amp;&amp; ch != noBreakSpace;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename CharacterType, bool treatNoBreakSpaceAsBreak&gt;
-inline int nextBreakablePosition(LazyLineBreakIterator&amp; lazyBreakIterator, const CharacterType* str, unsigned length, int pos)
</del><ins>+// When in non-loose mode, we can use the ASCII shortcut table.
+template&lt;typename CharacterType, NBSPBehavior nbspBehavior&gt;
+inline int nextBreakablePositionNonLoosely(LazyLineBreakIterator&amp; lazyBreakIterator, const CharacterType* str, unsigned length, int pos)
</ins><span class="cx"> {
</span><span class="cx">     int len = static_cast&lt;int&gt;(length);
</span><span class="cx">     int nextBreak = -1;
</span><span class="lines">@@ -91,10 +94,12 @@
</span><span class="cx">     for (int i = pos; i &lt; len; i++) {
</span><span class="cx">         CharacterType ch = str[i];
</span><span class="cx"> 
</span><del>-        if (isBreakableSpace&lt;treatNoBreakSpaceAsBreak&gt;(ch) || shouldBreakAfter(lastLastCh, lastCh, ch))
</del><ins>+        // Non-loose mode, so use ASCII shortcut (shouldBreakAfter) if not breakable space.
+        if (isBreakableSpace&lt;nbspBehavior&gt;(ch) || shouldBreakAfter(lastLastCh, lastCh, ch))
</ins><span class="cx">             return i;
</span><span class="cx"> 
</span><del>-        if (needsLineBreakIterator&lt;treatNoBreakSpaceAsBreak&gt;(ch) || needsLineBreakIterator&lt;treatNoBreakSpaceAsBreak&gt;(lastCh)) {
</del><ins>+        // Non-loose mode, so conditionally use break iterator.
+        if (needsLineBreakIterator&lt;nbspBehavior&gt;(ch) || needsLineBreakIterator&lt;nbspBehavior&gt;(lastCh)) {
</ins><span class="cx">             if (nextBreak &lt; i) {
</span><span class="cx">                 // Don't break if positioned at start of primary context and there is no prior context.
</span><span class="cx">                 if (i || priorContextLength) {
</span><span class="lines">@@ -106,7 +111,7 @@
</span><span class="cx">                     }
</span><span class="cx">                 }
</span><span class="cx">             }
</span><del>-            if (i == nextBreak &amp;&amp; !isBreakableSpace&lt;treatNoBreakSpaceAsBreak&gt;(lastCh))
</del><ins>+            if (i == nextBreak &amp;&amp; !isBreakableSpace&lt;nbspBehavior&gt;(lastCh))
</ins><span class="cx">                 return i;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -117,26 +122,89 @@
</span><span class="cx">     return len;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+// When in loose mode, we can't use the ASCII shortcut table since loose mode allows &quot;$100&quot; to break after '$' in content marked as CJK.
+// N.B. It should be possible to combine the following with the non-loose version above by adding a LooseBehavior template parameter;
+// however, when doing this, a 10% performance regression appeared on chromium-win (https://bugs.webkit.org/show_bug.cgi?id=89235#c112).
+template&lt;typename CharacterType, NBSPBehavior nbspBehavior&gt;
+static inline int nextBreakablePositionLoosely(LazyLineBreakIterator&amp; lazyBreakIterator, const CharacterType* str, unsigned length, int pos)
+{
+    int len = static_cast&lt;int&gt;(length);
+    int nextBreak = -1;
+
+    CharacterType lastCh = pos &gt; 0 ? str[pos - 1] : static_cast&lt;CharacterType&gt;(lazyBreakIterator.lastCharacter());
+    unsigned priorContextLength = lazyBreakIterator.priorContextLength();
+    for (int i = pos; i &lt; len; i++) {
+        CharacterType ch = str[i];
+
+        // Always loose mode, so don't use ASCII shortcut (shouldBreakAfter).
+        if (isBreakableSpace&lt;nbspBehavior&gt;(ch))
+            return i;
+
+        // Always use line break iterator in loose mode.
+        if (nextBreak &lt; i) {
+            // Don't break if positioned at start of primary context and there is no prior context.
+            if (i || priorContextLength) {
+                TextBreakIterator* breakIterator = lazyBreakIterator.get(priorContextLength);
+                if (breakIterator) {
+                    nextBreak = textBreakFollowing(breakIterator, i - 1 + priorContextLength);
+                    if (nextBreak &gt;= 0)
+                        nextBreak -= priorContextLength;
+                }
+            }
+        }
+        if (i == nextBreak &amp;&amp; !isBreakableSpace&lt;nbspBehavior&gt;(lastCh))
+            return i;
+
+        lastCh = ch;
+    }
+
+    return len;
+}
+
+inline int nextBreakablePosition(LazyLineBreakIterator&amp; lazyBreakIterator, int pos)
+{
+    String string = lazyBreakIterator.string();
+    if (string.is8Bit())
+        return nextBreakablePositionNonLoosely&lt;LChar, NBSPBehavior::TreatNBSPAsBreak&gt;(lazyBreakIterator, string.characters8(), string.length(), pos);
+    return nextBreakablePositionNonLoosely&lt;UChar, NBSPBehavior::TreatNBSPAsBreak&gt;(lazyBreakIterator, string.characters16(), string.length(), pos);
+}
+
</ins><span class="cx"> inline int nextBreakablePositionIgnoringNBSP(LazyLineBreakIterator&amp; lazyBreakIterator, int pos)
</span><span class="cx"> {
</span><span class="cx">     String string = lazyBreakIterator.string();
</span><span class="cx">     if (string.is8Bit())
</span><del>-        return nextBreakablePosition&lt;LChar, false&gt;(lazyBreakIterator, string.characters8(), string.length(), pos);
-    return nextBreakablePosition&lt;UChar, false&gt;(lazyBreakIterator, string.characters16(), string.length(), pos);
</del><ins>+        return nextBreakablePositionNonLoosely&lt;LChar, NBSPBehavior::IgnoreNBSP&gt;(lazyBreakIterator, string.characters8(), string.length(), pos);
+    return nextBreakablePositionNonLoosely&lt;UChar, NBSPBehavior::IgnoreNBSP&gt;(lazyBreakIterator, string.characters16(), string.length(), pos);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline int nextBreakablePosition(LazyLineBreakIterator&amp; lazyBreakIterator, int pos)
</del><ins>+inline int nextBreakablePositionLoose(LazyLineBreakIterator&amp; lazyBreakIterator, int pos)
</ins><span class="cx"> {
</span><span class="cx">     String string = lazyBreakIterator.string();
</span><span class="cx">     if (string.is8Bit())
</span><del>-        return nextBreakablePosition&lt;LChar, true&gt;(lazyBreakIterator, string.characters8(), string.length(), pos);
-    return nextBreakablePosition&lt;UChar, true&gt;(lazyBreakIterator, string.characters16(), string.length(), pos);
</del><ins>+        return nextBreakablePositionLoosely&lt;LChar, NBSPBehavior::TreatNBSPAsBreak&gt;(lazyBreakIterator, string.characters8(), string.length(), pos);
+    return nextBreakablePositionLoosely&lt;UChar, NBSPBehavior::TreatNBSPAsBreak&gt;(lazyBreakIterator, string.characters16(), string.length(), pos);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline bool isBreakable(LazyLineBreakIterator&amp; lazyBreakIterator, int pos, int&amp; nextBreakable, bool breakNBSP)
</del><ins>+inline int nextBreakablePositionIgnoringNBSPLoose(LazyLineBreakIterator&amp; lazyBreakIterator, int pos)
</ins><span class="cx"> {
</span><del>-    if (pos &gt; nextBreakable) {
</del><ins>+    String string = lazyBreakIterator.string();
+    if (string.is8Bit())
+        return nextBreakablePositionLoosely&lt;LChar, NBSPBehavior::IgnoreNBSP&gt;(lazyBreakIterator, string.characters8(), string.length(), pos);
+    return nextBreakablePositionLoosely&lt;UChar, NBSPBehavior::IgnoreNBSP&gt;(lazyBreakIterator, string.characters16(), string.length(), pos);
+}
+
+inline bool isBreakable(LazyLineBreakIterator&amp; lazyBreakIterator, int pos, int&amp; nextBreakable, bool breakNBSP, bool isLooseMode)
+{
+    if (pos &lt;= nextBreakable)
+        return pos == nextBreakable;
+
+    if (isLooseMode) {
</ins><span class="cx">         if (breakNBSP)
</span><ins>+            nextBreakable = nextBreakablePositionLoose(lazyBreakIterator, pos);
+        else
+            nextBreakable = nextBreakablePositionIgnoringNBSPLoose(lazyBreakIterator, pos);
+    } else {
+        if (breakNBSP)
</ins><span class="cx">             nextBreakable = nextBreakablePosition(lazyBreakIterator, pos);
</span><span class="cx">         else
</span><span class="cx">             nextBreakable = nextBreakablePositionIgnoringNBSP(lazyBreakIterator, pos);
</span></span></pre></div>
<a id="trunkSourceWebCorerenderinglineBreakingContextInlineHeadersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/line/BreakingContextInlineHeaders.h (176472 => 176473)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/line/BreakingContextInlineHeaders.h        2014-11-21 21:34:30 UTC (rev 176472)
+++ trunk/Source/WebCore/rendering/line/BreakingContextInlineHeaders.h        2014-11-21 22:33:17 UTC (rev 176473)
</span><span class="lines">@@ -624,6 +624,7 @@
</span><span class="cx">     bool midWordBreak = false;
</span><span class="cx">     bool breakAll = m_currentStyle-&gt;wordBreak() == BreakAllWordBreak &amp;&amp; m_autoWrap;
</span><span class="cx">     float hyphenWidth = 0;
</span><ins>+    bool isLooseCJKMode = false;
</ins><span class="cx"> 
</span><span class="cx">     if (isSVGText) {
</span><span class="cx">         breakWords = false;
</span><span class="lines">@@ -635,7 +636,8 @@
</span><span class="cx">         m_renderTextInfo.m_text = &amp;renderText;
</span><span class="cx">         m_renderTextInfo.m_font = &amp;font;
</span><span class="cx">         m_renderTextInfo.m_layout = font.createLayout(&amp;renderText, m_width.currentWidth(), m_collapseWhiteSpace);
</span><del>-        m_renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(renderText.text(), style.locale());
</del><ins>+        m_renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(renderText.text(), style.locale(), mapLineBreakToIteratorMode(m_blockStyle.lineBreak()));
+        isLooseCJKMode = m_renderTextInfo.m_lineBreakIterator.isLooseCJKMode();
</ins><span class="cx">     } else if (m_renderTextInfo.m_layout &amp;&amp; m_renderTextInfo.m_font != &amp;font) {
</span><span class="cx">         m_renderTextInfo.m_font = &amp;font;
</span><span class="cx">         m_renderTextInfo.m_layout = font.createLayout(&amp;renderText, m_width.currentWidth(), m_collapseWhiteSpace);
</span><span class="lines">@@ -676,7 +678,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         int nextBreakablePosition = m_current.nextBreakablePosition();
</span><del>-        bool betweenWords = c == '\n' || (m_currWS != PRE &amp;&amp; !m_atStart &amp;&amp; isBreakable(m_renderTextInfo.m_lineBreakIterator, m_current.offset(), nextBreakablePosition, breakNBSP)
</del><ins>+        bool betweenWords = c == '\n' || (m_currWS != PRE &amp;&amp; !m_atStart &amp;&amp; isBreakable(m_renderTextInfo.m_lineBreakIterator, m_current.offset(), nextBreakablePosition, breakNBSP, isLooseCJKMode)
</ins><span class="cx">             &amp;&amp; (style.hyphens() != HyphensNone || (m_current.previousInSameNode() != softHyphen)));
</span><span class="cx">         m_current.setNextBreakablePosition(nextBreakablePosition);
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>