<!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>[180444] branches/safari-600.5-branch</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/180444">180444</a></dd>
<dt>Author</dt> <dd>dburkart@apple.com</dd>
<dt>Date</dt> <dd>2015-02-20 12:13:09 -0800 (Fri, 20 Feb 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/176473">r176473</a>. rdar://problem/19451285</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari6005branchLayoutTestsChangeLog">branches/safari-600.5-branch/LayoutTests/ChangeLog</a></li>
<li><a href="#branchessafari6005branchLayoutTestsplatformmacTestExpectations">branches/safari-600.5-branch/LayoutTests/platform/mac/TestExpectations</a></li>
<li><a href="#branchessafari6005branchSourceWebCoreChangeLog">branches/safari-600.5-branch/Source/WebCore/ChangeLog</a></li>
<li><a href="#branchessafari6005branchSourceWebCoreWebCoreexpin">branches/safari-600.5-branch/Source/WebCore/WebCore.exp.in</a></li>
<li><a href="#branchessafari6005branchSourceWebCoreplatformtextLineBreakIteratorPoolICUh">branches/safari-600.5-branch/Source/WebCore/platform/text/LineBreakIteratorPoolICU.h</a></li>
<li><a href="#branchessafari6005branchSourceWebCoreplatformtextTextBreakIteratorcpp">branches/safari-600.5-branch/Source/WebCore/platform/text/TextBreakIterator.cpp</a></li>
<li><a href="#branchessafari6005branchSourceWebCoreplatformtextTextBreakIteratorh">branches/safari-600.5-branch/Source/WebCore/platform/text/TextBreakIterator.h</a></li>
<li><a href="#branchessafari6005branchSourceWebCorerenderingRenderTextcpp">branches/safari-600.5-branch/Source/WebCore/rendering/RenderText.cpp</a></li>
<li><a href="#branchessafari6005branchSourceWebCorerenderingRenderTexth">branches/safari-600.5-branch/Source/WebCore/rendering/RenderText.h</a></li>
<li><a href="#branchessafari6005branchSourceWebCorerenderingSimpleLineLayoutcpp">branches/safari-600.5-branch/Source/WebCore/rendering/SimpleLineLayout.cpp</a></li>
<li><a href="#branchessafari6005branchSourceWebCorerenderingbreak_linesh">branches/safari-600.5-branch/Source/WebCore/rendering/break_lines.h</a></li>
<li><a href="#branchessafari6005branchSourceWebCorerenderinglineBreakingContextInlineHeadersh">branches/safari-600.5-branch/Source/WebCore/rendering/line/BreakingContextInlineHeaders.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari6005branchLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-600.5-branch/LayoutTests/ChangeLog (180443 => 180444)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-600.5-branch/LayoutTests/ChangeLog        2015-02-20 20:10:35 UTC (rev 180443)
+++ branches/safari-600.5-branch/LayoutTests/ChangeLog        2015-02-20 20:13:09 UTC (rev 180444)
</span><span class="lines">@@ -1,5 +1,18 @@
</span><span class="cx"> 2015-02-20  Dana Burkart  &lt;dburkart@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r176473.
+
+    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.
+
+2015-02-20  Dana Burkart  &lt;dburkart@apple.com&gt;
+
</ins><span class="cx">         Merged r180278. &lt;rdar://problem/19878813&gt;
</span><span class="cx"> 
</span><span class="cx">     2015-02-18  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari6005branchLayoutTestsplatformmacTestExpectations"></a>
<div class="modfile"><h4>Modified: branches/safari-600.5-branch/LayoutTests/platform/mac/TestExpectations (180443 => 180444)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-600.5-branch/LayoutTests/platform/mac/TestExpectations        2015-02-20 20:10:35 UTC (rev 180443)
+++ branches/safari-600.5-branch/LayoutTests/platform/mac/TestExpectations        2015-02-20 20:13:09 UTC (rev 180444)
</span><span class="lines">@@ -1494,3 +1494,8 @@
</span><span class="cx"> 
</span><span class="cx"> # Passing Media Source tests
</span><span class="cx"> [ Yosemite+ ] http/tests/media/media-source/mediasource-sourcebuffer-mode.html [ Pass ]
</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="branchessafari6005branchSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-600.5-branch/Source/WebCore/ChangeLog (180443 => 180444)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-600.5-branch/Source/WebCore/ChangeLog        2015-02-20 20:10:35 UTC (rev 180443)
+++ branches/safari-600.5-branch/Source/WebCore/ChangeLog        2015-02-20 20:13:09 UTC (rev 180444)
</span><span class="lines">@@ -1,5 +1,163 @@
</span><span class="cx"> 2015-02-20  Dana Burkart  &lt;dburkart@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r176473.
+
+        * rendering/SimpleLineLayout.cpp:
+        (WebCore::SimpleLineLayout::canUseFor): Change from
+        r176473 not listed in that ChangeLog.
+        (WebCore::SimpleLineLayout::createLineRuns): Call
+        nextBreakablePositionNonLoosely() in place of
+        nextBreakablePosition().
+
+    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.
+
+2015-02-20  Dana Burkart  &lt;dburkart@apple.com&gt;
+
</ins><span class="cx">         Merged r180278. &lt;rdar://problem/19878813&gt;
</span><span class="cx"> 
</span><span class="cx">     2015-02-18  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari6005branchSourceWebCoreWebCoreexpin"></a>
<div class="modfile"><h4>Modified: branches/safari-600.5-branch/Source/WebCore/WebCore.exp.in (180443 => 180444)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-600.5-branch/Source/WebCore/WebCore.exp.in        2015-02-20 20:10:35 UTC (rev 180443)
+++ branches/safari-600.5-branch/Source/WebCore/WebCore.exp.in        2015-02-20 20:13:09 UTC (rev 180444)
</span><span class="lines">@@ -2603,6 +2603,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">@@ -2721,7 +2722,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="branchessafari6005branchSourceWebCoreplatformtextLineBreakIteratorPoolICUh"></a>
<div class="modfile"><h4>Modified: branches/safari-600.5-branch/Source/WebCore/platform/text/LineBreakIteratorPoolICU.h (180443 => 180444)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-600.5-branch/Source/WebCore/platform/text/LineBreakIteratorPoolICU.h        2015-02-20 20:10:35 UTC (rev 180443)
+++ branches/safari-600.5-branch/Source/WebCore/platform/text/LineBreakIteratorPoolICU.h        2015-02-20 20:13:09 UTC (rev 180444)
</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="branchessafari6005branchSourceWebCoreplatformtextTextBreakIteratorcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-600.5-branch/Source/WebCore/platform/text/TextBreakIterator.cpp (180443 => 180444)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-600.5-branch/Source/WebCore/platform/text/TextBreakIterator.cpp        2015-02-20 20:10:35 UTC (rev 180443)
+++ branches/safari-600.5-branch/Source/WebCore/platform/text/TextBreakIterator.cpp        2015-02-20 20:13:09 UTC (rev 180444)
</span><span class="lines">@@ -264,9 +264,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">@@ -277,9 +277,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="branchessafari6005branchSourceWebCoreplatformtextTextBreakIteratorh"></a>
<div class="modfile"><h4>Modified: branches/safari-600.5-branch/Source/WebCore/platform/text/TextBreakIterator.h (180443 => 180444)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-600.5-branch/Source/WebCore/platform/text/TextBreakIterator.h        2015-02-20 20:10:35 UTC (rev 180443)
+++ branches/safari-600.5-branch/Source/WebCore/platform/text/TextBreakIterator.h        2015-02-20 20:13:09 UTC (rev 180444)
</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>-TextBreakIterator* acquireLineBreakIterator(StringView, const AtomicString&amp; locale, const UChar* priorContext, unsigned priorContextLength);
</del><ins>+TextBreakIterator* acquireLineBreakIterator(StringView, const AtomicString&amp; locale, const UChar* priorContext, unsigned priorContextLength, LineBreakIteratorMode, bool isCJK);
</ins><span class="cx"> 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="branchessafari6005branchSourceWebCorerenderingRenderTextcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-600.5-branch/Source/WebCore/rendering/RenderText.cpp (180443 => 180444)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-600.5-branch/Source/WebCore/rendering/RenderText.cpp        2015-02-20 20:10:35 UTC (rev 180443)
+++ branches/safari-600.5-branch/Source/WebCore/rendering/RenderText.cpp        2015-02-20 20:13:09 UTC (rev 180444)
</span><span class="lines">@@ -598,6 +598,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">@@ -674,7 +690,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">@@ -709,6 +725,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">@@ -756,7 +773,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">@@ -764,7 +781,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="branchessafari6005branchSourceWebCorerenderingRenderTexth"></a>
<div class="modfile"><h4>Modified: branches/safari-600.5-branch/Source/WebCore/rendering/RenderText.h (180443 => 180444)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-600.5-branch/Source/WebCore/rendering/RenderText.h        2015-02-20 20:10:35 UTC (rev 180443)
+++ branches/safari-600.5-branch/Source/WebCore/rendering/RenderText.h        2015-02-20 20:13:09 UTC (rev 180444)
</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">@@ -253,6 +254,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="branchessafari6005branchSourceWebCorerenderingSimpleLineLayoutcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-600.5-branch/Source/WebCore/rendering/SimpleLineLayout.cpp (180443 => 180444)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-600.5-branch/Source/WebCore/rendering/SimpleLineLayout.cpp        2015-02-20 20:10:35 UTC (rev 180443)
+++ branches/safari-600.5-branch/Source/WebCore/rendering/SimpleLineLayout.cpp        2015-02-20 20:13:09 UTC (rev 180444)
</span><span class="lines">@@ -162,6 +162,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 = toRenderText(*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 class="lines">@@ -283,7 +285,7 @@
</span><span class="cx">         if (!style.collapseWhitespace &amp;&amp; isWhitespace(text[wordStart], style.preserveNewline))
</span><span class="cx">             wordEnd = wordStart + 1;
</span><span class="cx">         else
</span><del>-            wordEnd = nextBreakablePosition&lt;CharacterType, false&gt;(lineBreakIterator, text, textLength, wordStart + 1);
</del><ins>+            wordEnd = nextBreakablePositionNonLoosely&lt;CharacterType, NBSPBehavior::IgnoreNBSP&gt;(lineBreakIterator, text, textLength, wordStart + 1);
</ins><span class="cx"> 
</span><span class="cx">         bool wordIsPrecededByWhitespace = style.collapseWhitespace &amp;&amp; wordStart &gt; lineStart &amp;&amp; isWhitespace(text[wordStart - 1], style.preserveNewline);
</span><span class="cx">         if (wordIsPrecededByWhitespace)
</span></span></pre></div>
<a id="branchessafari6005branchSourceWebCorerenderingbreak_linesh"></a>
<div class="modfile"><h4>Modified: branches/safari-600.5-branch/Source/WebCore/rendering/break_lines.h (180443 => 180444)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-600.5-branch/Source/WebCore/rendering/break_lines.h        2015-02-20 20:10:35 UTC (rev 180443)
+++ branches/safari-600.5-branch/Source/WebCore/rendering/break_lines.h        2015-02-20 20:13:09 UTC (rev 180444)
</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="branchessafari6005branchSourceWebCorerenderinglineBreakingContextInlineHeadersh"></a>
<div class="modfile"><h4>Modified: branches/safari-600.5-branch/Source/WebCore/rendering/line/BreakingContextInlineHeaders.h (180443 => 180444)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-600.5-branch/Source/WebCore/rendering/line/BreakingContextInlineHeaders.h        2015-02-20 20:10:35 UTC (rev 180443)
+++ branches/safari-600.5-branch/Source/WebCore/rendering/line/BreakingContextInlineHeaders.h        2015-02-20 20:13:09 UTC (rev 180444)
</span><span class="lines">@@ -628,6 +628,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">@@ -639,7 +640,8 @@
</span><span class="cx">         m_renderTextInfo.m_text = renderText;
</span><span class="cx">         m_renderTextInfo.m_font = &amp;font;
</span><span class="cx">         m_renderTextInfo.m_layout = font.createLayout(renderText, m_width.currentWidth(), m_collapseWhiteSpace);
</span><del>-        m_renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(renderText-&gt;text(), style.locale());
</del><ins>+        m_renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(renderText-&gt;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(renderText, m_width.currentWidth(), m_collapseWhiteSpace);
</span><span class="lines">@@ -680,7 +682,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>