<!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 <dburkart@apple.com>
</span><span class="cx">
</span><ins>+ Merge r176473.
+
+ 2014-11-21 Glenn Adams <glenn@skynav.com> and Myles C. Maxfield <mmaxfield@apple.com>
+
+ 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 <dburkart@apple.com>
+
</ins><span class="cx"> Merged r180278. <rdar://problem/19878813>
</span><span class="cx">
</span><span class="cx"> 2015-02-18 Myles C. Maxfield <mmaxfield@apple.com>
</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 <dburkart@apple.com>
</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 <glenn@skynav.com> and Myles C. Maxfield <mmaxfield@apple.com>
+
+ 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 "@break=" +
+ "loose"|"normal"|"strict" 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 <dburkart@apple.com>
+
</ins><span class="cx"> Merged r180278. <rdar://problem/19878813>
</span><span class="cx">
</span><span class="cx"> 2015-02-18 Myles C. Maxfield <mmaxfield@apple.com>
</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 "TextBreakIterator.h"
</ins><span class="cx"> #include "TextBreakIteratorInternalICU.h"
</span><span class="cx"> #include <unicode/ubrk.h>
</span><span class="cx"> #include <wtf/Assertions.h>
</span><span class="lines">@@ -34,6 +35,7 @@
</span><span class="cx"> #include <wtf/ThreadSpecific.h>
</span><span class="cx"> #include <wtf/text/AtomicString.h>
</span><span class="cx"> #include <wtf/text/CString.h>
</span><ins>+#include <wtf/text/StringBuilder.h>
</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<LineBreakIteratorPool> create() { return adoptPtr(new LineBreakIteratorPool); }
</span><span class="cx">
</span><del>- UBreakIterator* take(const AtomicString& locale)
</del><ins>+ static String makeLocaleWithBreakKeyword(const AtomicString& locale, LineBreakIteratorMode mode)
</ins><span class="cx"> {
</span><del>- UBreakIterator* iterator = 0;
</del><ins>+ StringBuilder localeWithKeyword;
+ localeWithKeyword.append(locale);
+ localeWithKeyword.appendLiteral("@break=");
+ switch (mode) {
+ case LineBreakIteratorModeUAX14:
+ ASSERT_NOT_REACHED();
+ break;
+ case LineBreakIteratorModeUAX14Loose:
+ localeWithKeyword.appendLiteral("loose");
+ break;
+ case LineBreakIteratorModeUAX14Normal:
+ localeWithKeyword.appendLiteral("normal");
+ break;
+ case LineBreakIteratorModeUAX14Strict:
+ localeWithKeyword.appendLiteral("strict");
+ break;
+ }
+ return localeWithKeyword.toString();
+ }
+
+ TextBreakIterator* take(const AtomicString& 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 < 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, &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 && U_FAILURE(openStatus)) {
- openStatus = U_ZERO_ERROR;
- iterator = ubrk_open(UBRK_LINE, currentTextBreakLocaleID(), 0, 0, &openStatus);
- }
-
- if (U_FAILURE(openStatus)) {
- LOG_ERROR("ubrk_open failed with status %d", 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<AtomicString, UBreakIterator*> Entry;
</del><ins>+ typedef std::pair<AtomicString, TextBreakIterator*> Entry;
</ins><span class="cx"> typedef Vector<Entry, capacity> Pool;
</span><span class="cx"> Pool m_pool;
</span><del>- HashMap<UBreakIterator*, AtomicString> m_vendedIterators;
</del><ins>+ HashMap<TextBreakIterator*, AtomicString> m_vendedIterators;
</ins><span class="cx">
</span><span class="cx"> friend WTF::ThreadSpecific<LineBreakIteratorPool>::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& locale, const UChar* priorContext, unsigned priorContextLength)
</del><ins>+TextBreakIterator* acquireLineBreakIterator(StringView string, const AtomicString& locale, const UChar* priorContext, unsigned priorContextLength, LineBreakIteratorMode mode, bool isCJK)
</ins><span class="cx"> {
</span><del>- TextBreakIterator* iterator = reinterpret_cast<TextBreakIterator*>(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<UBreakIterator*>(iterator));
</del><ins>+ LineBreakIteratorPool::sharedPool().put(iterator);
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+static const char* uax14Prologue =
+ "!!chain;"
+ "!!LBCMNoChain;"
+ "!!lookAheadHardBreak;";
+
+static const char* uax14AssignmentsBefore =
+ // explicitly enumerate $CJ since ICU versions prior to 49 don't support :LineBreak=Conditional_Japanese_Starter:
+ "$CJ = ["
+#if (U_ICU_VERSION_MAJOR_NUM >= 4) && (U_ICU_VERSION_MINOR_NUM >= 9)
+ ":LineBreak=Conditional_Japanese_Starter:"
+#else
+ "\\u3041\\u3043\\u3045\\u3047\\u3049\\u3063\\u3083\\u3085\\u3087\\u308E\\u3095\\u3096\\u30A1\\u30A3\\u30A5\\u30A7"
+ "\\u30A9\\u30C3\\u30E3\\u30E5\\u30E7\\u30EE\\u30F5\\u30F6\\u30FC"
+ "\\u31F0\\u31F1\\u31F2\\u31F3\\u31F4\\u31F5\\u31F6\\u31F7\\u31F8\\u31F9\\u31FA\\u31FB\\u31FC\\u31FD\\u31FE\\u31FF"
+ "\\uFF67\\uFF68\\uFF69\\uFF6A\\uFF6B\\uFF6C\\uFF6D\\uFF6E\\uFF6F\\uFF70"
+#endif
+ "];";
+
+static const char* uax14AssignmentsCustomLooseCJK =
+ "$BA_SUB = [\\u2010\\u2013];"
+ "$EX_SUB = [\\u0021\\u003F\\uFF01\\uFF1F];"
+ "$ID_SUB = '';"
+ "$IN_SUB = [\\u2025\\u2026];"
+ "$IS_SUB = [\\u003A\\u003B];"
+ "$NS_SUB = [\\u203C\\u2047\\u2048\\u2049\\u3005\\u301C\\u303B\\u309D\\u309E\\u30A0\\u30FB\\u30FD\\u30FE\\uFF1A\\uFF1B\\uFF65];"
+ "$PO_SUB = [\\u0025\\u00A2\\u00B0\\u2030\\u2032\\u2033\\u2103\\uFF05\\uFFE0];"
+ "$PR_SUB = [\\u0024\\u00A3\\u00A5\\u20AC\\u2116\\uFF04\\uFFE1\\uFFE5];"
+ "$ID_ADD = [$CJ $BA_SUB $EX_SUB $IN_SUB $IS_SUB $NS_SUB $PO_SUB $PR_SUB];"
+ "$NS_ADD = '';";
+
+static const char* uax14AssignmentsCustomLooseNonCJK =
+ "$BA_SUB = '';"
+ "$EX_SUB = '';"
+ "$ID_SUB = '';"
+ "$IN_SUB = [\\u2025\\u2026];"
+ "$IS_SUB = '';"
+ "$NS_SUB = [\\u3005\\u303B\\u309D\\u309E\\u30FD\\u30FE];"
+ "$PO_SUB = '';"
+ "$PR_SUB = '';"
+ "$ID_ADD = [$CJ $IN_SUB $NS_SUB];"
+ "$NS_ADD = '';";
+
+static const char* uax14AssignmentsCustomNormalCJK =
+ "$BA_SUB = [\\u2010\\u2013];"
+ "$EX_SUB = '';"
+ "$IN_SUB = '';"
+ "$ID_SUB = '';"
+ "$IS_SUB = '';"
+ "$NS_SUB = [\\u301C\\u30A0];"
+ "$PO_SUB = '';"
+ "$PR_SUB = '';"
+ "$ID_ADD = [$CJ $BA_SUB $NS_SUB];"
+ "$NS_ADD = '';";
+
+static const char* uax14AssignmentsCustomNormalNonCJK =
+ "$BA_SUB = '';"
+ "$EX_SUB = '';"
+ "$ID_SUB = '';"
+ "$IN_SUB = '';"
+ "$IS_SUB = '';"
+ "$NS_SUB = '';"
+ "$PO_SUB = '';"
+ "$PR_SUB = '';"
+ "$ID_ADD = [$CJ];"
+ "$NS_ADD = '';";
+
+static const char* uax14AssignmentsCustomStrictCJK =
+ "$BA_SUB = '';"
+ "$EX_SUB = '';"
+ "$ID_SUB = '';"
+ "$IN_SUB = '';"
+ "$IS_SUB = '';"
+ "$NS_SUB = '';"
+ "$PO_SUB = '';"
+ "$PR_SUB = '';"
+ "$ID_ADD = '';"
+ "$NS_ADD = [$CJ];";
+
+#define uax14AssignmentsCustomStrictNonCJK uax14AssignmentsCustomStrictCJK
+#define uax14AssignmentsCustomDefaultCJK uax14AssignmentsCustomNormalCJK
+#define uax14AssignmentsCustomDefaultNonCJK uax14AssignmentsCustomStrictNonCJK
+
+static const char* uax14AssignmentsAfter =
+ "$AI = [:LineBreak = Ambiguous:];"
+ "$AL = [:LineBreak = Alphabetic:];"
+ "$BA = [[:LineBreak = Break_After:] - $BA_SUB];"
+ "$BB = [:LineBreak = Break_Before:];"
+ "$BK = [:LineBreak = Mandatory_Break:];"
+ "$B2 = [:LineBreak = Break_Both:];"
+ "$CB = [:LineBreak = Contingent_Break:];"
+ "$CL = [:LineBreak = Close_Punctuation:];"
+ "$CM = [:LineBreak = Combining_Mark:];"
+ "$CP = [:LineBreak = Close_Parenthesis:];"
+ "$CR = [:LineBreak = Carriage_Return:];"
+ "$EX = [[:LineBreak = Exclamation:] - $EX_SUB];"
+ "$GL = [:LineBreak = Glue:];"
+#if (U_ICU_VERSION_MAJOR_NUM >= 4) && (U_ICU_VERSION_MINOR_NUM >= 9)
+ "$HL = [:LineBreak = Hebrew_Letter:];"
+#else
+ "$HL = [[:Hebrew:] & [:Letter:]];"
+#endif
+ "$HY = [:LineBreak = Hyphen:];"
+ "$H2 = [:LineBreak = H2:];"
+ "$H3 = [:LineBreak = H3:];"
+ "$ID = [[[[:LineBreak = Ideographic:] - $CJ] $ID_ADD] - $ID_SUB];"
+ "$IN = [[:LineBreak = Inseparable:] - $IN_SUB];"
+ "$IS = [[:LineBreak = Infix_Numeric:] - $IS_SUB];"
+ "$JL = [:LineBreak = JL:];"
+ "$JV = [:LineBreak = JV:];"
+ "$JT = [:LineBreak = JT:];"
+ "$LF = [:LineBreak = Line_Feed:];"
+ "$NL = [:LineBreak = Next_Line:];"
+ "$NS = [[[[:LineBreak = Nonstarter:] - $CJ] $NS_ADD] - $NS_SUB];"
+ "$NU = [:LineBreak = Numeric:];"
+ "$OP = [:LineBreak = Open_Punctuation:];"
+ "$PO = [[:LineBreak = Postfix_Numeric:] - $PO_SUB];"
+ "$PR = [[:LineBreak = Prefix_Numeric:] - $PR_SUB];"
+ "$QU = [:LineBreak = Quotation:];"
+ "$SA = [:LineBreak = Complex_Context:];"
+ "$SG = [:LineBreak = Surrogate:];"
+ "$SP = [:LineBreak = Space:];"
+ "$SY = [:LineBreak = Break_Symbols:];"
+ "$WJ = [:LineBreak = Word_Joiner:];"
+ "$XX = [:LineBreak = Unknown:];"
+ "$ZW = [:LineBreak = ZWSpace:];"
+ "$dictionary = [:LineBreak = Complex_Context:];"
+ "$ALPlus = [$AL $AI $SA $SG $XX];"
+ "$ALcm = $ALPlus $CM*;"
+ "$BAcm = $BA $CM*;"
+ "$BBcm = $BB $CM*;"
+ "$B2cm = $B2 $CM*;"
+ "$CLcm = $CL $CM*;"
+ "$CPcm = $CP $CM*;"
+ "$EXcm = $EX $CM*;"
+ "$GLcm = $GL $CM*;"
+ "$HLcm = $HL $CM*;"
+ "$HYcm = $HY $CM*;"
+ "$H2cm = $H2 $CM*;"
+ "$H3cm = $H3 $CM*;"
+ "$IDcm = $ID $CM*;"
+ "$INcm = $IN $CM*;"
+ "$IScm = $IS $CM*;"
+ "$JLcm = $JL $CM*;"
+ "$JVcm = $JV $CM*;"
+ "$JTcm = $JT $CM*;"
+ "$NScm = $NS $CM*;"
+ "$NUcm = $NU $CM*;"
+ "$OPcm = $OP $CM*;"
+ "$POcm = $PO $CM*;"
+ "$PRcm = $PR $CM*;"
+ "$QUcm = $QU $CM*;"
+ "$SYcm = $SY $CM*;"
+ "$WJcm = $WJ $CM*;";
+
+static const char* uax14Forward =
+ "!!forward;"
+ "$CAN_CM = [^$SP $BK $CR $LF $NL $ZW $CM];"
+ "$CANT_CM = [$SP $BK $CR $LF $NL $ZW $CM];"
+ "$AL_FOLLOW_NOCM = [$BK $CR $LF $NL $ZW $SP];"
+ "$AL_FOLLOW_CM = [$CL $CP $EX $HL $IS $SY $WJ $GL $OP $QU $BA $HY $NS $IN $NU $ALPlus];"
+ "$AL_FOLLOW = [$AL_FOLLOW_NOCM $AL_FOLLOW_CM];"
+ "$LB4Breaks = [$BK $CR $LF $NL];"
+ "$LB4NonBreaks = [^$BK $CR $LF $NL];"
+ "$LB8Breaks = [$LB4Breaks $ZW];"
+ "$LB8NonBreaks = [[$LB4NonBreaks] - [$ZW]];"
+ "$LB18NonBreaks = [$LB8NonBreaks - [$SP]];"
+ "$LB18Breaks = [$LB8Breaks $SP];"
+ "$LB20NonBreaks = [$LB18NonBreaks - $CB];"
+ "$ALPlus $CM+;"
+ "$BA $CM+;"
+ "$BB $CM+;"
+ "$B2 $CM+;"
+ "$CL $CM+;"
+ "$CP $CM+;"
+ "$EX $CM+;"
+ "$GL $CM+;"
+ "$HL $CM+;"
+ "$HY $CM+;"
+ "$H2 $CM+;"
+ "$H3 $CM+;"
+ "$ID $CM+;"
+ "$IN $CM+;"
+ "$IS $CM+;"
+ "$JL $CM+;"
+ "$JV $CM+;"
+ "$JT $CM+;"
+ "$NS $CM+;"
+ "$NU $CM+;"
+ "$OP $CM+;"
+ "$PO $CM+;"
+ "$PR $CM+;"
+ "$QU $CM+;"
+ "$SY $CM+;"
+ "$WJ $CM+;"
+ "$CR $LF {100};"
+ "$LB4NonBreaks? $LB4Breaks {100};"
+ "$CAN_CM $CM* $LB4Breaks {100};"
+ "$CM+ $LB4Breaks {100};"
+ "$LB4NonBreaks [$SP $ZW];"
+ "$CAN_CM $CM* [$SP $ZW];"
+ "$CM+ [$SP $ZW];"
+ "$CAN_CM $CM+;"
+ "$CM+;"
+ "$CAN_CM $CM* $WJcm;"
+ "$LB8NonBreaks $WJcm;"
+ "$CM+ $WJcm;"
+ "$WJcm $CANT_CM;"
+ "$WJcm $CAN_CM $CM*;"
+ "$GLcm $CAN_CM $CM*;"
+ "$GLcm $CANT_CM;"
+ "[[$LB8NonBreaks] - [$SP $BA $HY]] $CM* $GLcm;"
+ "$CM+ GLcm;"
+ "$LB8NonBreaks $CL;"
+ "$CAN_CM $CM* $CL;"
+ "$CM+ $CL;"
+ "$LB8NonBreaks $CP;"
+ "$CAN_CM $CM* $CP;"
+ "$CM+ $CP;"
+ "$LB8NonBreaks $EX;"
+ "$CAN_CM $CM* $EX;"
+ "$CM+ $EX;"
+ "$LB8NonBreaks $IS;"
+ "$CAN_CM $CM* $IS;"
+ "$CM+ $IS;"
+ "$LB8NonBreaks $SY;"
+ "$CAN_CM $CM* $SY;"
+ "$CM+ $SY;"
+ "$OPcm $SP* $CAN_CM $CM*;"
+ "$OPcm $SP* $CANT_CM;"
+ "$OPcm $SP+ $CM+ $AL_FOLLOW?;"
+ "$QUcm $SP* $OPcm;"
+ "($CLcm | $CPcm) $SP* $NScm;"
+ "$B2cm $SP* $B2cm;"
+ "$LB18NonBreaks $CM* $QUcm;"
+ "$CM+ $QUcm;"
+ "$QUcm .?;"
+ "$QUcm $LB18NonBreaks $CM*;"
+ "$LB20NonBreaks $CM* ($BAcm | $HYcm | $NScm); "
+ "$BBcm [^$CB];"
+ "$BBcm $LB20NonBreaks $CM*;"
+ "$HLcm ($HYcm | $BAcm) [^$CB]?;"
+ "($ALcm | $HLcm) $INcm;"
+ "$CM+ $INcm;"
+ "$IDcm $INcm;"
+ "$INcm $INcm;"
+ "$NUcm $INcm;"
+ "$IDcm $POcm;"
+ "$ALcm $NUcm;"
+ "$HLcm $NUcm;"
+ "$CM+ $NUcm;"
+ "$NUcm $ALcm;"
+ "$NUcm $HLcm;"
+ "$PRcm $IDcm;"
+ "$PRcm ($ALcm | $HLcm);"
+ "$POcm ($ALcm | $HLcm);"
+ "($PRcm | $POcm)? ($OPcm | $HYcm)? $NUcm ($NUcm | $SYcm | $IScm)* ($CLcm | $CPcm)? ($PRcm | $POcm)?;"
+ "$JLcm ($JLcm | $JVcm | $H2cm | $H3cm);"
+ "($JVcm | $H2cm) ($JVcm | $JTcm);"
+ "($JTcm | $H3cm) $JTcm;"
+ "($JLcm | $JVcm | $JTcm | $H2cm | $H3cm) $INcm;"
+ "($JLcm | $JVcm | $JTcm | $H2cm | $H3cm) $POcm;"
+ "$PRcm ($JLcm | $JVcm | $JTcm | $H2cm | $H3cm);"
+ "($ALcm | $HLcm) ($ALcm | $HLcm);"
+ "$CM+ ($ALcm | $HLcm);"
+ "$IScm ($ALcm | $HLcm);"
+ "($ALcm | $HLcm | $NUcm) $OPcm;"
+ "$CM+ $OPcm;"
+ "$CPcm ($ALcm | $HLcm | $NUcm);";
+
+static const char* uax14Reverse =
+ "!!reverse;"
+ "$CM+ $ALPlus;"
+ "$CM+ $BA;"
+ "$CM+ $BB;"
+ "$CM+ $B2;"
+ "$CM+ $CL;"
+ "$CM+ $CP;"
+ "$CM+ $EX;"
+ "$CM+ $GL;"
+ "$CM+ $HL;"
+ "$CM+ $HY;"
+ "$CM+ $H2;"
+ "$CM+ $H3;"
+ "$CM+ $ID;"
+ "$CM+ $IN;"
+ "$CM+ $IS;"
+ "$CM+ $JL;"
+ "$CM+ $JV;"
+ "$CM+ $JT;"
+ "$CM+ $NS;"
+ "$CM+ $NU;"
+ "$CM+ $OP;"
+ "$CM+ $PO;"
+ "$CM+ $PR;"
+ "$CM+ $QU;"
+ "$CM+ $SY;"
+ "$CM+ $WJ;"
+ "$CM+;"
+ "$AL_FOLLOW $CM+ / ([$BK $CR $LF $NL $ZW {eof}] | $SP+ $CM+ $SP | $SP+ $CM* ([^$OP $CM $SP] | [$AL {eof}]));"
+ "[$PR] / $CM+ [$BK $CR $LF $NL $ZW $SP {eof}];"
+ "$LB4Breaks [$LB4NonBreaks-$CM];"
+ "$LB4Breaks $CM+ $CAN_CM;"
+ "$LF $CR;"
+ "[$SP $ZW] [$LB4NonBreaks-$CM];"
+ "[$SP $ZW] $CM+ $CAN_CM;"
+ "$CM+ $CAN_CM;"
+ "$CM* $WJ $CM* $CAN_CM;"
+ "$CM* $WJ [$LB8NonBreaks-$CM];"
+ "$CANT_CM $CM* $WJ;"
+ "$CM* $CAN_CM $CM* $WJ;"
+ "$CM* $GL $CM* [$LB8NonBreaks-[$CM $SP $BA $HY]];"
+ "$CANT_CM $CM* $GL;"
+ "$CM* $CAN_CM $CM* $GL;"
+ "$CL $CM+ $CAN_CM;"
+ "$CP $CM+ $CAN_CM;"
+ "$EX $CM+ $CAN_CM;"
+ "$IS $CM+ $CAN_CM;"
+ "$SY $CM+ $CAN_CM;"
+ "$CL [$LB8NonBreaks-$CM];"
+ "$CP [$LB8NonBreaks-$CM];"
+ "$EX [$LB8NonBreaks-$CM];"
+ "$IS [$LB8NonBreaks-$CM];"
+ "$SY [$LB8NonBreaks-$CM];"
+ "[$CL $CP $EX $IS $SY] $CM+ $SP+ $CM* $OP; "
+ "$CM* $CAN_CM $SP* $CM* $OP;"
+ "$CANT_CM $SP* $CM* $OP;"
+ "$AL_FOLLOW? $CM+ $SP $SP* $CM* $OP;"
+ "$AL_FOLLOW_NOCM $CM+ $SP+ $CM* $OP;"
+ "$CM* $AL_FOLLOW_CM $CM+ $SP+ $CM* $OP;"
+ "$SY $CM $SP+ $OP;"
+ "$CM* $OP $SP* $CM* $QU;"
+ "$CM* $NS $SP* $CM* ($CL | $CP);"
+ "$CM* $B2 $SP* $CM* $B2;"
+ "$CM* $QU $CM* $CAN_CM;"
+ "$CM* $QU $LB18NonBreaks;"
+ "$CM* $CAN_CM $CM* $QU;"
+ "$CANT_CM $CM* $QU;"
+ "$CM* ($BA | $HY | $NS) $CM* [$LB20NonBreaks-$CM];"
+ "$CM* [$LB20NonBreaks-$CM] $CM* $BB;"
+ "[^$CB] $CM* $BB;"
+ "[^$CB] $CM* ($HY | $BA) $CM* $HL;"
+ "$CM* $IN $CM* ($ALPlus | $HL);"
+ "$CM* $IN $CM* $ID;"
+ "$CM* $IN $CM* $IN;"
+ "$CM* $IN $CM* $NU;"
+ "$CM* $PO $CM* $ID;"
+ "$CM* $NU $CM* ($ALPlus | $HL);"
+ "$CM* ($ALPlus | $HL) $CM* $NU;"
+ "$CM* $ID $CM* $PR;"
+ "$CM* ($ALPlus | $HL) $CM* $PR;"
+ "$CM* ($ALPlus | $HL) $CM* $PO;"
+ "($CM* ($PR | $PO))? ($CM* ($CL | $CP))? ($CM* ($NU | $IS | $SY))* $CM* $NU ($CM* ($OP | $HY))? ($CM* ($PR | $PO))?;"
+ "$CM* ($H3 | $H2 | $JV | $JL) $CM* $JL;"
+ "$CM* ($JT | $JV) $CM* ($H2 | $JV);"
+ "$CM* $JT $CM* ($H3 | $JT);"
+ "$CM* $IN $CM* ($H3 | $H2 | $JT | $JV | $JL);"
+ "$CM* $PO $CM* ($H3 | $H2 | $JT | $JV | $JL);"
+ "$CM* ($H3 | $H2 | $JT | $JV | $JL) $CM* $PR;"
+ "$CM* ($ALPlus | $HL) $CM* ($ALPlus | $HL);"
+ "$CM* ($ALPlus | $HL) $CM* $IS;"
+ "$CM* $OP $CM* ($ALPlus | $HL | $NU);"
+ "$CM* ($ALPlus | $HL | $NU) $CM* $CP;";
+
+static const char* uax14SafeForward =
+ "!!safe_forward;"
+ "[$CM $OP $QU $CL $CP $B2 $PR $HY $BA $SP $dictionary]+ [^$CM $OP $QU $CL $CP $B2 $PR $HY $BA $dictionary];"
+ "$dictionary $dictionary;";
+
+static const char* uax14SafeReverse =
+ "!!safe_reverse;"
+ "$CM+ [^$CM $BK $CR $LF $NL $ZW $SP];"
+ "$CM+ $SP / .;"
+ "$SP+ $CM* $OP;"
+ "$SP+ $CM* $QU;"
+ "$SP+ $CM* ($CL | $CP);"
+ "$SP+ $CM* $B2;"
+ "$CM* ($HY | $BA) $CM* $HL;"
+ "($CM* ($IS | $SY))+ $CM* $NU;"
+ "($CL | $CP) $CM* ($NU | $IS | $SY);"
+ "$dictionary $dictionary;";
+
+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& locale)
+{
+ size_t length = locale.length();
+ if (length < 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& 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, &openStatus);
+ else {
+ UParseError parseStatus;
+ auto rules = mapLineIteratorModeToRules(mode, isCJK);
+ ubrkIter = ubrk_openRules(StringView(rules).upconvertedCharacters(), rules.length(), 0, 0, &parseStatus, &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 && U_FAILURE(openStatus)) {
+ openStatus = U_ZERO_ERROR;
+ ubrkIter = ubrk_open(UBRK_LINE, currentTextBreakLocaleID(), 0, 0, &openStatus);
+ }
+
+ if (U_FAILURE(openStatus)) {
+ LOG_ERROR("ubrk_open failed with status %d", openStatus);
+ return nullptr;
+ }
+
+ return reinterpret_cast<TextBreakIterator*>(ubrkIter);
+}
+
+void closeLineBreakIterator(TextBreakIterator*& iterator)
+{
+ UBreakIterator* ubrkIter = reinterpret_cast<UBreakIterator*>(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& locale, const UChar* priorContext, unsigned priorContextLength);
</del><ins>+TextBreakIterator* acquireLineBreakIterator(StringView, const AtomicString& locale, const UChar* priorContext, unsigned priorContextLength, LineBreakIteratorMode, bool isCJK);
</ins><span class="cx"> void releaseLineBreakIterator(TextBreakIterator*);
</span><ins>+TextBreakIterator* openLineBreakIterator(const AtomicString& locale, LineBreakIteratorMode, bool isCJK);
+void closeLineBreakIterator(TextBreakIterator*&);
</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&);
+
</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& locale = AtomicString())
</del><ins>+ LazyLineBreakIterator(String string, const AtomicString& 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 && 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 <= priorContextCapacity);
</span><span class="cx"> const UChar* priorContext = priorContextLength ? &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->resetStringAndReleaseIterator(m_string, m_locale);
</del><ins>+ resetStringAndReleaseIterator(m_string, m_locale, m_mode);
</ins><span class="cx"> return this->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& locale)
</del><ins>+
+ void resetStringAndReleaseIterator(String string, const AtomicString& 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 "extended grapheme clusters", 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<const SimpleFontData*> fallbackFonts;
</span><span class="lines">@@ -674,7 +690,7 @@
</span><span class="cx"> const Font& 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() && style.nbspMode() == SPACE;
</span><span class="cx"> bool breakAll = (style.wordBreak() == BreakAllWordBreak || style.wordBreak() == BreakWordBreak) && style.autoWrap();
</span><ins>+ bool isLooseCJKMode = breakIterator.isLooseCJKMode();
</ins><span class="cx">
</span><span class="cx"> for (int i = 0; i < 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' && !isSpaceAccordingToStyle(c, style) && c != '\t' && (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) && characterAt(j - 1) != softHyphen)
</del><ins>+ if (isBreakable(breakIterator, j, nextBreakable, breakNBSP, isLooseCJKMode) && 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 "RenderTextLineBoxes.h"
</span><span class="cx"> #include "SimpleLineLayout.h"
</span><span class="cx"> #include "Text.h"
</span><ins>+#include "TextBreakIterator.h"
</ins><span class="cx"> #include <wtf/Forward.h>
</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&, String&, 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& 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 && isWhitespace(text[wordStart], style.preserveNewline))
</span><span class="cx"> wordEnd = wordStart + 1;
</span><span class="cx"> else
</span><del>- wordEnd = nextBreakablePosition<CharacterType, false>(lineBreakIterator, text, textLength, wordStart + 1);
</del><ins>+ wordEnd = nextBreakablePositionNonLoosely<CharacterType, NBSPBehavior::IgnoreNBSP>(lineBreakIterator, text, textLength, wordStart + 1);
</ins><span class="cx">
</span><span class="cx"> bool wordIsPrecededByWhitespace = style.collapseWhitespace && wordStart > lineStart && 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&, int pos);
-int nextBreakablePosition(LazyLineBreakIterator&, int pos);
</del><ins>+enum class NBSPBehavior {
+ IgnoreNBSP,
+ TreatNBSPAsBreak,
+};
</ins><span class="cx">
</span><del>-template<bool treatNoBreakSpaceAsBreak>
</del><ins>+template<NBSPBehavior nbspBehavior>
</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<bool treatNoBreakSpaceAsBreak>
</del><ins>+template<NBSPBehavior nbspBehavior>
</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 > asciiLineBreakTableLastChar;
</span><span class="cx"> return ch > asciiLineBreakTableLastChar && ch != noBreakSpace;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-template<typename CharacterType, bool treatNoBreakSpaceAsBreak>
-inline int nextBreakablePosition(LazyLineBreakIterator& lazyBreakIterator, const CharacterType* str, unsigned length, int pos)
</del><ins>+// When in non-loose mode, we can use the ASCII shortcut table.
+template<typename CharacterType, NBSPBehavior nbspBehavior>
+inline int nextBreakablePositionNonLoosely(LazyLineBreakIterator& lazyBreakIterator, const CharacterType* str, unsigned length, int pos)
</ins><span class="cx"> {
</span><span class="cx"> int len = static_cast<int>(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 < len; i++) {
</span><span class="cx"> CharacterType ch = str[i];
</span><span class="cx">
</span><del>- if (isBreakableSpace<treatNoBreakSpaceAsBreak>(ch) || shouldBreakAfter(lastLastCh, lastCh, ch))
</del><ins>+ // Non-loose mode, so use ASCII shortcut (shouldBreakAfter) if not breakable space.
+ if (isBreakableSpace<nbspBehavior>(ch) || shouldBreakAfter(lastLastCh, lastCh, ch))
</ins><span class="cx"> return i;
</span><span class="cx">
</span><del>- if (needsLineBreakIterator<treatNoBreakSpaceAsBreak>(ch) || needsLineBreakIterator<treatNoBreakSpaceAsBreak>(lastCh)) {
</del><ins>+ // Non-loose mode, so conditionally use break iterator.
+ if (needsLineBreakIterator<nbspBehavior>(ch) || needsLineBreakIterator<nbspBehavior>(lastCh)) {
</ins><span class="cx"> if (nextBreak < 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 && !isBreakableSpace<treatNoBreakSpaceAsBreak>(lastCh))
</del><ins>+ if (i == nextBreak && !isBreakableSpace<nbspBehavior>(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 "$100" 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<typename CharacterType, NBSPBehavior nbspBehavior>
+static inline int nextBreakablePositionLoosely(LazyLineBreakIterator& lazyBreakIterator, const CharacterType* str, unsigned length, int pos)
+{
+ int len = static_cast<int>(length);
+ int nextBreak = -1;
+
+ CharacterType lastCh = pos > 0 ? str[pos - 1] : static_cast<CharacterType>(lazyBreakIterator.lastCharacter());
+ unsigned priorContextLength = lazyBreakIterator.priorContextLength();
+ for (int i = pos; i < len; i++) {
+ CharacterType ch = str[i];
+
+ // Always loose mode, so don't use ASCII shortcut (shouldBreakAfter).
+ if (isBreakableSpace<nbspBehavior>(ch))
+ return i;
+
+ // Always use line break iterator in loose mode.
+ if (nextBreak < 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 >= 0)
+ nextBreak -= priorContextLength;
+ }
+ }
+ }
+ if (i == nextBreak && !isBreakableSpace<nbspBehavior>(lastCh))
+ return i;
+
+ lastCh = ch;
+ }
+
+ return len;
+}
+
+inline int nextBreakablePosition(LazyLineBreakIterator& lazyBreakIterator, int pos)
+{
+ String string = lazyBreakIterator.string();
+ if (string.is8Bit())
+ return nextBreakablePositionNonLoosely<LChar, NBSPBehavior::TreatNBSPAsBreak>(lazyBreakIterator, string.characters8(), string.length(), pos);
+ return nextBreakablePositionNonLoosely<UChar, NBSPBehavior::TreatNBSPAsBreak>(lazyBreakIterator, string.characters16(), string.length(), pos);
+}
+
</ins><span class="cx"> inline int nextBreakablePositionIgnoringNBSP(LazyLineBreakIterator& 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<LChar, false>(lazyBreakIterator, string.characters8(), string.length(), pos);
- return nextBreakablePosition<UChar, false>(lazyBreakIterator, string.characters16(), string.length(), pos);
</del><ins>+ return nextBreakablePositionNonLoosely<LChar, NBSPBehavior::IgnoreNBSP>(lazyBreakIterator, string.characters8(), string.length(), pos);
+ return nextBreakablePositionNonLoosely<UChar, NBSPBehavior::IgnoreNBSP>(lazyBreakIterator, string.characters16(), string.length(), pos);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-inline int nextBreakablePosition(LazyLineBreakIterator& lazyBreakIterator, int pos)
</del><ins>+inline int nextBreakablePositionLoose(LazyLineBreakIterator& 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<LChar, true>(lazyBreakIterator, string.characters8(), string.length(), pos);
- return nextBreakablePosition<UChar, true>(lazyBreakIterator, string.characters16(), string.length(), pos);
</del><ins>+ return nextBreakablePositionLoosely<LChar, NBSPBehavior::TreatNBSPAsBreak>(lazyBreakIterator, string.characters8(), string.length(), pos);
+ return nextBreakablePositionLoosely<UChar, NBSPBehavior::TreatNBSPAsBreak>(lazyBreakIterator, string.characters16(), string.length(), pos);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-inline bool isBreakable(LazyLineBreakIterator& lazyBreakIterator, int pos, int& nextBreakable, bool breakNBSP)
</del><ins>+inline int nextBreakablePositionIgnoringNBSPLoose(LazyLineBreakIterator& lazyBreakIterator, int pos)
</ins><span class="cx"> {
</span><del>- if (pos > nextBreakable) {
</del><ins>+ String string = lazyBreakIterator.string();
+ if (string.is8Bit())
+ return nextBreakablePositionLoosely<LChar, NBSPBehavior::IgnoreNBSP>(lazyBreakIterator, string.characters8(), string.length(), pos);
+ return nextBreakablePositionLoosely<UChar, NBSPBehavior::IgnoreNBSP>(lazyBreakIterator, string.characters16(), string.length(), pos);
+}
+
+inline bool isBreakable(LazyLineBreakIterator& lazyBreakIterator, int pos, int& nextBreakable, bool breakNBSP, bool isLooseMode)
+{
+ if (pos <= 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->wordBreak() == BreakAllWordBreak && 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 = &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->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 && m_renderTextInfo.m_font != &font) {
</span><span class="cx"> m_renderTextInfo.m_font = &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 && !m_atStart && isBreakable(m_renderTextInfo.m_lineBreakIterator, m_current.offset(), nextBreakablePosition, breakNBSP)
</del><ins>+ bool betweenWords = c == '\n' || (m_currWS != PRE && !m_atStart && isBreakable(m_renderTextInfo.m_lineBreakIterator, m_current.offset(), nextBreakablePosition, breakNBSP, isLooseCJKMode)
</ins><span class="cx"> && (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>