Changeset 176473 in webkit
- Timestamp:
- Nov 21, 2014, 2:33:17 PM (12 years ago)
- Location:
- trunk
- Files:
-
- 13 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/platform/mac/TestExpectations (modified) (1 diff)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/WebCore.exp.in (modified) (2 diffs)
-
Source/WebCore/platform/text/LineBreakIteratorPoolICU.h (modified) (5 diffs)
-
Source/WebCore/platform/text/TextBreakIterator.cpp (modified) (2 diffs)
-
Source/WebCore/platform/text/TextBreakIterator.h (modified) (13 diffs)
-
Source/WebCore/rendering/RenderText.cpp (modified) (5 diffs)
-
Source/WebCore/rendering/RenderText.h (modified) (2 diffs)
-
Source/WebCore/rendering/SimpleLineLayout.cpp (modified) (1 diff)
-
Source/WebCore/rendering/SimpleLineLayoutFlowContents.cpp (modified) (2 diffs)
-
Source/WebCore/rendering/break_lines.h (modified) (6 diffs)
-
Source/WebCore/rendering/line/BreakingContextInlineHeaders.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r176470 r176473 1 2014-11-21 Glenn Adams <glenn@skynav.com> and Myles C. Maxfield <mmaxfield@apple.com> 2 3 CSS3: line-break property support 4 https://bugs.webkit.org/show_bug.cgi?id=89235 5 6 Reviewed by Eric Seidel and Dave Hyatt. 7 8 * platform/mac/TestExpectations: Mark css3/line-break tests as passing. 9 1 10 2014-11-21 Zalan Bujtas <zalan@apple.com> 2 11 -
trunk/LayoutTests/platform/mac/TestExpectations
r176416 r176473 1430 1430 1431 1431 webkit.org/b/82980 http/tests/navigation/back-twice-without-commit.html [ Timeout ] 1432 1433 # Verified passing, so override generic skip 1434 webkit.org/b/89235 css3/line-break [ Pass ] 1435 webkit.org/b/138115 css3/line-break/line-break-auto-hyphens.html [ ImageOnlyFailure ] 1436 webkit.org/b/138115 css3/line-break/line-break-auto-sound-marks.html [ ImageOnlyFailure ] -
trunk/Source/WebCore/ChangeLog
r176472 r176473 1 2014-11-21 Glenn Adams <glenn@skynav.com> and Myles C. Maxfield <mmaxfield@apple.com> 2 3 Add support to -webkit-line-break property for CSS3 Text line-break property values and semantics. 4 https://bugs.webkit.org/show_bug.cgi?id=89235 5 6 Reviewed by Eric Seidel and Dave Hyatt. 7 8 This patch adds semantic support for the CSS3 line-break property (qua -webkit-line-break), 9 and enables testing on (apple) mac ports. Follow on patches will enable these tests on 10 other ports as they are incrementally verified. 11 12 See also wiki documentation at: 13 [1] http://trac.webkit.org/wiki/LineBreaking 14 [2] http://trac.webkit.org/wiki/LineBreakingCSS3Mapping 15 16 Tests: css3/line-break/line-break-auto-centered.html 17 css3/line-break/line-break-auto-half-kana.html 18 css3/line-break/line-break-auto-hyphens.html 19 css3/line-break/line-break-auto-inseparables.html 20 css3/line-break/line-break-auto-iteration-marks.html 21 css3/line-break/line-break-auto-postfixes.html 22 css3/line-break/line-break-auto-prefixes.html 23 css3/line-break/line-break-auto-sound-marks.html 24 css3/line-break/line-break-loose-centered.html 25 css3/line-break/line-break-loose-half-kana.html 26 css3/line-break/line-break-loose-hyphens.html 27 css3/line-break/line-break-loose-inseparables.html 28 css3/line-break/line-break-loose-iteration-marks.html 29 css3/line-break/line-break-loose-postfixes.html 30 css3/line-break/line-break-loose-prefixes.html 31 css3/line-break/line-break-loose-sound-marks.html 32 css3/line-break/line-break-normal-centered.html 33 css3/line-break/line-break-normal-half-kana.html 34 css3/line-break/line-break-normal-hyphens.html 35 css3/line-break/line-break-normal-inseparables.html 36 css3/line-break/line-break-normal-iteration-marks.html 37 css3/line-break/line-break-normal-postfixes.html 38 css3/line-break/line-break-normal-prefixes.html 39 css3/line-break/line-break-normal-sound-marks.html 40 css3/line-break/line-break-strict-centered.html 41 css3/line-break/line-break-strict-half-kana.html 42 css3/line-break/line-break-strict-hyphens.html 43 css3/line-break/line-break-strict-inseparables.html 44 css3/line-break/line-break-strict-iteration-marks.html 45 css3/line-break/line-break-strict-postfixes.html 46 css3/line-break/line-break-strict-prefixes.html 47 css3/line-break/line-break-strict-sound-marks.html 48 49 These tests were previously added in http://trac.webkit.org/changeset/143378, but skipped 50 in generic TestExpectations. In this patch, they are marked as Pass for the (apple) mac ports. 51 52 * platform/text/LineBreakIteratorPoolICU.h: 53 (WebCore::LineBreakIteratorPool::makeLocaleWithBreakKeyword): 54 Add static function to construct ICU locale argument (also used as pool key) with additional 55 break keyword. 56 (LineBreakIteratorPool): 57 (WebCore::LineBreakIteratorPool::take): 58 (WebCore::LineBreakIteratorPool::put): 59 Remove direct dependency from ICU library (and types), moving that dependency into 60 new {open,close}LineBreakIterator() functions (defined in TextBreakIteratorICU.cpp). 61 Update to take line break mode into account. 62 Create (and cache) different break iterators depending on line break mode (in addition to locale), 63 which entails expanding pool entry key format to optionally append "@break=" + 64 "loose"|"normal"|"strict" keyword to locale string. 65 66 * platform/text/TextBreakIterator.h: 67 (WebCore::LazyLineBreakIterator::LazyLineBreakIterator): 68 (WebCore::LazyLineBreakIterator::isLooseCJKMode): 69 (WebCore::LazyLineBreakIterator::get): 70 (WebCore::LazyLineBreakIterator::reset): 71 (LazyLineBreakIterator): 72 Define LineBreakIteratorMode enumeration for use in TextBreakIterator et al. 73 Add state member to indicate line break mode. 74 75 * platform/text/TextBreakIteratorICU.cpp: 76 (WebCore::acquireLineBreakIterator): 77 Use new line break mode when making iterator from pool. 78 Handle change of return type of LineBreakIteratorPool::take() to non-ICU type, 79 i.e., TextBreakIterator* instead of ICU's UBreakIterator*. 80 (WebCore::releaseLineBreakIterator): 81 Handle change of parameter type of LineBreakIteratorPool::put() to non-ICU type, 82 i.e., TextBreakIterator* instead of ICU's UBreakIterator*. 83 (WebCore): 84 (WebCore::isCJKLocale): 85 New functions for determining if CJK rules apply. 86 (WebCore::openLineBreakIterator): 87 New function for abstracting opening of ICU style line break iterator. This is now 88 used in LineBreakIteratorPoolICU.h rather than having direct ICU API dependency there. 89 This function also takes into account the line break mode. 90 91 Note that this function only calls ubrk_openRules() when the author has opted-in via 92 using the -webkit-line-break CSS property. Eventually, we would like to be able to 93 customize the rules that ICU's line breaking algorithm uses (especially for CJK text); 94 however, ubrk_openRules() currently parses its input string to create a DFA and is 95 therefore very slow. In fact, it's so slow that increasing our cache size in 96 LineBreakIteratorPool doesn't actually help enough. Also note that the default value 97 for the line-break CSS property is 'auto'. 98 (WebCore::closeLineBreakIterator): 99 (WebCore::mapLineIteratorModeToRules): 100 New function for abstracting closing of ICU style line break iterator. This is now 101 used in LineBreakIteratorPoolICU.h rather than having direct ICU API dependency there. 102 103 * rendering/RenderBlockLineLayout.cpp: 104 (WebCore::RenderBlock::LineBreaker::nextSegmentBreak): 105 Pass line break iterator mode flag when reseting LazyLineBreakIterator. 106 Add looseMode local variable to prevent need for computing under isBreakable(). 107 108 * rendering/RenderText.cpp: 109 (WebCore::mapLineBreakToIteratorMode): 110 Add implementation for mapLineBreakToIteratorMode(), used by both RenderText::computePreferredLogicalWidths 111 and RenderBlock::LineBreaker::nextLineBreak. 112 (WebCore): 113 (WebCore::RenderText::computePreferredLogicalWidths): 114 Ensure (lazy line) breakIterator is initialized for line break mode. 115 Ensure isBreakable() is passed loose mode flag to match behavior in RenderBlock::LineBreaker::nextLineBreak. 116 117 * rendering/RenderText.h: 118 (WebCore): 119 Add declaration for mapLineBreakToIteratorMode(), used by both RenderText::computePreferredLogicalWidths 120 and RenderBlock::LineBreaker::nextLineBreak. 121 122 * rendering/break_lines.cpp: 123 (WebCore): 124 Introduce (local) enum NBSPBehavior for expanding template on nextBreakablePosition. 125 (WebCore::isBreakableSpace): 126 Add externally specified loose mode parameter to prevent need to invoke line break iterator 127 accessor method on each invocation. Use new loose mode flavors off NBP functions. 128 (WebCore::needsLineBreakIterator): 129 Use enum NBSP behavior template parameter rather than boolean. 130 (WebCore::nextBreakablePositionNonLoosely): 131 Extend name to distinguish from loose flavor of this function. 132 (WebCore::nextBreakablePositionLoosely): 133 Add loose flavor of NBP invoked only when loose mode applies, in which case ASCII shortcut 134 table cannot be used. 135 (WebCore::nextBreakablePosition): 136 (WebCore::nextBreakablePositionIgnoringNBSP): 137 Use (renamed) non-loose flavor of NBP. 138 (WebCore::nextBreakablePositionLoose): 139 (WebCore::nextBreakablePositionIgnoringNBSPLoose): 140 Introduce loose flavor of NBP template expansions. 141 142 * rendering/break_lines.h: 143 (WebCore): 144 (WebCore::isBreakable): 145 Add externally specified loose mode parameter to prevent need to invoke line break iterator 146 accessor method on each invocation. 147 1 148 2014-11-21 Anders Carlsson <andersca@apple.com> 2 149 -
trunk/Source/WebCore/WebCore.exp.in
r176462 r176473 2594 2594 __ZN7WebCore11MemoryCache18pruneDeadResourcesEv 2595 2595 __ZN7WebCore11MemoryCache18pruneLiveResourcesEb 2596 __ZN7WebCore11isCJKLocaleERKN3WTF12AtomicStringE 2596 2597 __ZN7WebCore11isEndOfLineERKNS_15VisiblePositionE 2597 2598 __ZN7WebCore11prefetchDNSERKN3WTF6StringE … … 2706 2707 __ZN7WebCore24FloatingPointEnvironment25saveMainThreadEnvironmentEv 2707 2708 __ZN7WebCore24FloatingPointEnvironment6sharedEv 2708 __ZN7WebCore24acquireLineBreakIteratorEN3WTF10StringViewERKNS0_12AtomicStringEPKtj 2709 __ZN7WebCore24acquireLineBreakIteratorEN3WTF10StringViewERKNS0_12AtomicStringEPKtjNS_21LineBreakIteratorModeEb 2709 2710 __ZN7WebCore24charactersAroundPositionERKNS_15VisiblePositionERiS3_S3_ 2710 2711 __ZN7WebCore24createTemporaryDirectoryEP8NSString -
trunk/Source/WebCore/platform/text/LineBreakIteratorPoolICU.h
r161309 r176473 27 27 #define LineBreakIteratorPoolICU_h 28 28 29 #include "TextBreakIterator.h" 29 30 #include "TextBreakIteratorInternalICU.h" 30 31 #include <unicode/ubrk.h> … … 35 36 #include <wtf/text/AtomicString.h> 36 37 #include <wtf/text/CString.h> 38 #include <wtf/text/StringBuilder.h> 37 39 38 40 namespace WebCore { … … 49 51 static PassOwnPtr<LineBreakIteratorPool> create() { return adoptPtr(new LineBreakIteratorPool); } 50 52 51 UBreakIterator* take(const AtomicString& locale)53 static String makeLocaleWithBreakKeyword(const AtomicString& locale, LineBreakIteratorMode mode) 52 54 { 53 UBreakIterator* iterator = 0; 55 StringBuilder localeWithKeyword; 56 localeWithKeyword.append(locale); 57 localeWithKeyword.appendLiteral("@break="); 58 switch (mode) { 59 case LineBreakIteratorModeUAX14: 60 ASSERT_NOT_REACHED(); 61 break; 62 case LineBreakIteratorModeUAX14Loose: 63 localeWithKeyword.appendLiteral("loose"); 64 break; 65 case LineBreakIteratorModeUAX14Normal: 66 localeWithKeyword.appendLiteral("normal"); 67 break; 68 case LineBreakIteratorModeUAX14Strict: 69 localeWithKeyword.appendLiteral("strict"); 70 break; 71 } 72 return localeWithKeyword.toString(); 73 } 74 75 TextBreakIterator* take(const AtomicString& locale, LineBreakIteratorMode mode, bool isCJK) 76 { 77 AtomicString localeWithOptionalBreakKeyword; 78 if (mode == LineBreakIteratorModeUAX14) 79 localeWithOptionalBreakKeyword = locale; 80 else 81 localeWithOptionalBreakKeyword = makeLocaleWithBreakKeyword(locale, mode); 82 83 TextBreakIterator* iterator = 0; 54 84 for (size_t i = 0; i < m_pool.size(); ++i) { 55 if (m_pool[i].first == locale ) {85 if (m_pool[i].first == localeWithOptionalBreakKeyword) { 56 86 iterator = m_pool[i].second; 57 87 m_pool.remove(i); … … 61 91 62 92 if (!iterator) { 63 UErrorCode openStatus = U_ZERO_ERROR; 64 bool localeIsEmpty = locale.isEmpty(); 65 iterator = ubrk_open(UBRK_LINE, localeIsEmpty ? currentTextBreakLocaleID() : locale.string().utf8().data(), 0, 0, &openStatus); 66 // locale comes from a web page and it can be invalid, leading ICU 67 // to fail, in which case we fall back to the default locale. 68 if (!localeIsEmpty && U_FAILURE(openStatus)) { 69 openStatus = U_ZERO_ERROR; 70 iterator = ubrk_open(UBRK_LINE, currentTextBreakLocaleID(), 0, 0, &openStatus); 71 } 72 73 if (U_FAILURE(openStatus)) { 74 LOG_ERROR("ubrk_open failed with status %d", openStatus); 93 iterator = openLineBreakIterator(localeWithOptionalBreakKeyword, mode, isCJK); 94 if (!iterator) 75 95 return 0; 76 }77 96 } 78 97 79 98 ASSERT(!m_vendedIterators.contains(iterator)); 80 m_vendedIterators.set(iterator, locale );99 m_vendedIterators.set(iterator, localeWithOptionalBreakKeyword); 81 100 return iterator; 82 101 } 83 102 84 void put( UBreakIterator* iterator)103 void put(TextBreakIterator* iterator) 85 104 { 86 105 ASSERT_ARG(iterator, m_vendedIterators.contains(iterator)); 87 106 88 107 if (m_pool.size() == capacity) { 89 ubrk_close(m_pool[0].second);108 closeLineBreakIterator(m_pool[0].second); 90 109 m_pool.remove(0); 91 110 } … … 99 118 static const size_t capacity = 4; 100 119 101 typedef std::pair<AtomicString, UBreakIterator*> Entry;120 typedef std::pair<AtomicString, TextBreakIterator*> Entry; 102 121 typedef Vector<Entry, capacity> Pool; 103 122 Pool m_pool; 104 HashMap< UBreakIterator*, AtomicString> m_vendedIterators;123 HashMap<TextBreakIterator*, AtomicString> m_vendedIterators; 105 124 106 125 friend WTF::ThreadSpecific<LineBreakIteratorPool>::operator LineBreakIteratorPool*(); -
trunk/Source/WebCore/platform/text/TextBreakIterator.cpp
r172513 r176473 257 257 } 258 258 259 TextBreakIterator* acquireLineBreakIterator(StringView string, const AtomicString& locale, const UChar* priorContext, unsigned priorContextLength )260 { 261 TextBreakIterator* iterator = reinterpret_cast<TextBreakIterator*>(LineBreakIteratorPool::sharedPool().take(locale));259 TextBreakIterator* acquireLineBreakIterator(StringView string, const AtomicString& locale, const UChar* priorContext, unsigned priorContextLength, LineBreakIteratorMode mode, bool isCJK) 260 { 261 TextBreakIterator* iterator = LineBreakIteratorPool::sharedPool().take(locale, mode, isCJK); 262 262 if (!iterator) 263 263 return nullptr; … … 270 270 ASSERT_ARG(iterator, iterator); 271 271 272 LineBreakIteratorPool::sharedPool().put(reinterpret_cast<UBreakIterator*>(iterator)); 272 LineBreakIteratorPool::sharedPool().put(iterator); 273 } 274 275 static const char* uax14Prologue = 276 "!!chain;" 277 "!!LBCMNoChain;" 278 "!!lookAheadHardBreak;"; 279 280 static const char* uax14AssignmentsBefore = 281 // explicitly enumerate $CJ since ICU versions prior to 49 don't support :LineBreak=Conditional_Japanese_Starter: 282 "$CJ = [" 283 #if (U_ICU_VERSION_MAJOR_NUM >= 4) && (U_ICU_VERSION_MINOR_NUM >= 9) 284 ":LineBreak=Conditional_Japanese_Starter:" 285 #else 286 "\\u3041\\u3043\\u3045\\u3047\\u3049\\u3063\\u3083\\u3085\\u3087\\u308E\\u3095\\u3096\\u30A1\\u30A3\\u30A5\\u30A7" 287 "\\u30A9\\u30C3\\u30E3\\u30E5\\u30E7\\u30EE\\u30F5\\u30F6\\u30FC" 288 "\\u31F0\\u31F1\\u31F2\\u31F3\\u31F4\\u31F5\\u31F6\\u31F7\\u31F8\\u31F9\\u31FA\\u31FB\\u31FC\\u31FD\\u31FE\\u31FF" 289 "\\uFF67\\uFF68\\uFF69\\uFF6A\\uFF6B\\uFF6C\\uFF6D\\uFF6E\\uFF6F\\uFF70" 290 #endif 291 "];"; 292 293 static const char* uax14AssignmentsCustomLooseCJK = 294 "$BA_SUB = [\\u2010\\u2013];" 295 "$EX_SUB = [\\u0021\\u003F\\uFF01\\uFF1F];" 296 "$ID_SUB = '';" 297 "$IN_SUB = [\\u2025\\u2026];" 298 "$IS_SUB = [\\u003A\\u003B];" 299 "$NS_SUB = [\\u203C\\u2047\\u2048\\u2049\\u3005\\u301C\\u303B\\u309D\\u309E\\u30A0\\u30FB\\u30FD\\u30FE\\uFF1A\\uFF1B\\uFF65];" 300 "$PO_SUB = [\\u0025\\u00A2\\u00B0\\u2030\\u2032\\u2033\\u2103\\uFF05\\uFFE0];" 301 "$PR_SUB = [\\u0024\\u00A3\\u00A5\\u20AC\\u2116\\uFF04\\uFFE1\\uFFE5];" 302 "$ID_ADD = [$CJ $BA_SUB $EX_SUB $IN_SUB $IS_SUB $NS_SUB $PO_SUB $PR_SUB];" 303 "$NS_ADD = '';"; 304 305 static const char* uax14AssignmentsCustomLooseNonCJK = 306 "$BA_SUB = '';" 307 "$EX_SUB = '';" 308 "$ID_SUB = '';" 309 "$IN_SUB = [\\u2025\\u2026];" 310 "$IS_SUB = '';" 311 "$NS_SUB = [\\u3005\\u303B\\u309D\\u309E\\u30FD\\u30FE];" 312 "$PO_SUB = '';" 313 "$PR_SUB = '';" 314 "$ID_ADD = [$CJ $IN_SUB $NS_SUB];" 315 "$NS_ADD = '';"; 316 317 static const char* uax14AssignmentsCustomNormalCJK = 318 "$BA_SUB = [\\u2010\\u2013];" 319 "$EX_SUB = '';" 320 "$IN_SUB = '';" 321 "$ID_SUB = '';" 322 "$IS_SUB = '';" 323 "$NS_SUB = [\\u301C\\u30A0];" 324 "$PO_SUB = '';" 325 "$PR_SUB = '';" 326 "$ID_ADD = [$CJ $BA_SUB $NS_SUB];" 327 "$NS_ADD = '';"; 328 329 static const char* uax14AssignmentsCustomNormalNonCJK = 330 "$BA_SUB = '';" 331 "$EX_SUB = '';" 332 "$ID_SUB = '';" 333 "$IN_SUB = '';" 334 "$IS_SUB = '';" 335 "$NS_SUB = '';" 336 "$PO_SUB = '';" 337 "$PR_SUB = '';" 338 "$ID_ADD = [$CJ];" 339 "$NS_ADD = '';"; 340 341 static const char* uax14AssignmentsCustomStrictCJK = 342 "$BA_SUB = '';" 343 "$EX_SUB = '';" 344 "$ID_SUB = '';" 345 "$IN_SUB = '';" 346 "$IS_SUB = '';" 347 "$NS_SUB = '';" 348 "$PO_SUB = '';" 349 "$PR_SUB = '';" 350 "$ID_ADD = '';" 351 "$NS_ADD = [$CJ];"; 352 353 #define uax14AssignmentsCustomStrictNonCJK uax14AssignmentsCustomStrictCJK 354 #define uax14AssignmentsCustomDefaultCJK uax14AssignmentsCustomNormalCJK 355 #define uax14AssignmentsCustomDefaultNonCJK uax14AssignmentsCustomStrictNonCJK 356 357 static const char* uax14AssignmentsAfter = 358 "$AI = [:LineBreak = Ambiguous:];" 359 "$AL = [:LineBreak = Alphabetic:];" 360 "$BA = [[:LineBreak = Break_After:] - $BA_SUB];" 361 "$BB = [:LineBreak = Break_Before:];" 362 "$BK = [:LineBreak = Mandatory_Break:];" 363 "$B2 = [:LineBreak = Break_Both:];" 364 "$CB = [:LineBreak = Contingent_Break:];" 365 "$CL = [:LineBreak = Close_Punctuation:];" 366 "$CM = [:LineBreak = Combining_Mark:];" 367 "$CP = [:LineBreak = Close_Parenthesis:];" 368 "$CR = [:LineBreak = Carriage_Return:];" 369 "$EX = [[:LineBreak = Exclamation:] - $EX_SUB];" 370 "$GL = [:LineBreak = Glue:];" 371 #if (U_ICU_VERSION_MAJOR_NUM >= 4) && (U_ICU_VERSION_MINOR_NUM >= 9) 372 "$HL = [:LineBreak = Hebrew_Letter:];" 373 #else 374 "$HL = [[:Hebrew:] & [:Letter:]];" 375 #endif 376 "$HY = [:LineBreak = Hyphen:];" 377 "$H2 = [:LineBreak = H2:];" 378 "$H3 = [:LineBreak = H3:];" 379 "$ID = [[[[:LineBreak = Ideographic:] - $CJ] $ID_ADD] - $ID_SUB];" 380 "$IN = [[:LineBreak = Inseparable:] - $IN_SUB];" 381 "$IS = [[:LineBreak = Infix_Numeric:] - $IS_SUB];" 382 "$JL = [:LineBreak = JL:];" 383 "$JV = [:LineBreak = JV:];" 384 "$JT = [:LineBreak = JT:];" 385 "$LF = [:LineBreak = Line_Feed:];" 386 "$NL = [:LineBreak = Next_Line:];" 387 "$NS = [[[[:LineBreak = Nonstarter:] - $CJ] $NS_ADD] - $NS_SUB];" 388 "$NU = [:LineBreak = Numeric:];" 389 "$OP = [:LineBreak = Open_Punctuation:];" 390 "$PO = [[:LineBreak = Postfix_Numeric:] - $PO_SUB];" 391 "$PR = [[:LineBreak = Prefix_Numeric:] - $PR_SUB];" 392 "$QU = [:LineBreak = Quotation:];" 393 "$SA = [:LineBreak = Complex_Context:];" 394 "$SG = [:LineBreak = Surrogate:];" 395 "$SP = [:LineBreak = Space:];" 396 "$SY = [:LineBreak = Break_Symbols:];" 397 "$WJ = [:LineBreak = Word_Joiner:];" 398 "$XX = [:LineBreak = Unknown:];" 399 "$ZW = [:LineBreak = ZWSpace:];" 400 "$dictionary = [:LineBreak = Complex_Context:];" 401 "$ALPlus = [$AL $AI $SA $SG $XX];" 402 "$ALcm = $ALPlus $CM*;" 403 "$BAcm = $BA $CM*;" 404 "$BBcm = $BB $CM*;" 405 "$B2cm = $B2 $CM*;" 406 "$CLcm = $CL $CM*;" 407 "$CPcm = $CP $CM*;" 408 "$EXcm = $EX $CM*;" 409 "$GLcm = $GL $CM*;" 410 "$HLcm = $HL $CM*;" 411 "$HYcm = $HY $CM*;" 412 "$H2cm = $H2 $CM*;" 413 "$H3cm = $H3 $CM*;" 414 "$IDcm = $ID $CM*;" 415 "$INcm = $IN $CM*;" 416 "$IScm = $IS $CM*;" 417 "$JLcm = $JL $CM*;" 418 "$JVcm = $JV $CM*;" 419 "$JTcm = $JT $CM*;" 420 "$NScm = $NS $CM*;" 421 "$NUcm = $NU $CM*;" 422 "$OPcm = $OP $CM*;" 423 "$POcm = $PO $CM*;" 424 "$PRcm = $PR $CM*;" 425 "$QUcm = $QU $CM*;" 426 "$SYcm = $SY $CM*;" 427 "$WJcm = $WJ $CM*;"; 428 429 static const char* uax14Forward = 430 "!!forward;" 431 "$CAN_CM = [^$SP $BK $CR $LF $NL $ZW $CM];" 432 "$CANT_CM = [$SP $BK $CR $LF $NL $ZW $CM];" 433 "$AL_FOLLOW_NOCM = [$BK $CR $LF $NL $ZW $SP];" 434 "$AL_FOLLOW_CM = [$CL $CP $EX $HL $IS $SY $WJ $GL $OP $QU $BA $HY $NS $IN $NU $ALPlus];" 435 "$AL_FOLLOW = [$AL_FOLLOW_NOCM $AL_FOLLOW_CM];" 436 "$LB4Breaks = [$BK $CR $LF $NL];" 437 "$LB4NonBreaks = [^$BK $CR $LF $NL];" 438 "$LB8Breaks = [$LB4Breaks $ZW];" 439 "$LB8NonBreaks = [[$LB4NonBreaks] - [$ZW]];" 440 "$LB18NonBreaks = [$LB8NonBreaks - [$SP]];" 441 "$LB18Breaks = [$LB8Breaks $SP];" 442 "$LB20NonBreaks = [$LB18NonBreaks - $CB];" 443 "$ALPlus $CM+;" 444 "$BA $CM+;" 445 "$BB $CM+;" 446 "$B2 $CM+;" 447 "$CL $CM+;" 448 "$CP $CM+;" 449 "$EX $CM+;" 450 "$GL $CM+;" 451 "$HL $CM+;" 452 "$HY $CM+;" 453 "$H2 $CM+;" 454 "$H3 $CM+;" 455 "$ID $CM+;" 456 "$IN $CM+;" 457 "$IS $CM+;" 458 "$JL $CM+;" 459 "$JV $CM+;" 460 "$JT $CM+;" 461 "$NS $CM+;" 462 "$NU $CM+;" 463 "$OP $CM+;" 464 "$PO $CM+;" 465 "$PR $CM+;" 466 "$QU $CM+;" 467 "$SY $CM+;" 468 "$WJ $CM+;" 469 "$CR $LF {100};" 470 "$LB4NonBreaks? $LB4Breaks {100};" 471 "$CAN_CM $CM* $LB4Breaks {100};" 472 "$CM+ $LB4Breaks {100};" 473 "$LB4NonBreaks [$SP $ZW];" 474 "$CAN_CM $CM* [$SP $ZW];" 475 "$CM+ [$SP $ZW];" 476 "$CAN_CM $CM+;" 477 "$CM+;" 478 "$CAN_CM $CM* $WJcm;" 479 "$LB8NonBreaks $WJcm;" 480 "$CM+ $WJcm;" 481 "$WJcm $CANT_CM;" 482 "$WJcm $CAN_CM $CM*;" 483 "$GLcm $CAN_CM $CM*;" 484 "$GLcm $CANT_CM;" 485 "[[$LB8NonBreaks] - [$SP $BA $HY]] $CM* $GLcm;" 486 "$CM+ GLcm;" 487 "$LB8NonBreaks $CL;" 488 "$CAN_CM $CM* $CL;" 489 "$CM+ $CL;" 490 "$LB8NonBreaks $CP;" 491 "$CAN_CM $CM* $CP;" 492 "$CM+ $CP;" 493 "$LB8NonBreaks $EX;" 494 "$CAN_CM $CM* $EX;" 495 "$CM+ $EX;" 496 "$LB8NonBreaks $IS;" 497 "$CAN_CM $CM* $IS;" 498 "$CM+ $IS;" 499 "$LB8NonBreaks $SY;" 500 "$CAN_CM $CM* $SY;" 501 "$CM+ $SY;" 502 "$OPcm $SP* $CAN_CM $CM*;" 503 "$OPcm $SP* $CANT_CM;" 504 "$OPcm $SP+ $CM+ $AL_FOLLOW?;" 505 "$QUcm $SP* $OPcm;" 506 "($CLcm | $CPcm) $SP* $NScm;" 507 "$B2cm $SP* $B2cm;" 508 "$LB18NonBreaks $CM* $QUcm;" 509 "$CM+ $QUcm;" 510 "$QUcm .?;" 511 "$QUcm $LB18NonBreaks $CM*;" 512 "$LB20NonBreaks $CM* ($BAcm | $HYcm | $NScm); " 513 "$BBcm [^$CB];" 514 "$BBcm $LB20NonBreaks $CM*;" 515 "$HLcm ($HYcm | $BAcm) [^$CB]?;" 516 "($ALcm | $HLcm) $INcm;" 517 "$CM+ $INcm;" 518 "$IDcm $INcm;" 519 "$INcm $INcm;" 520 "$NUcm $INcm;" 521 "$IDcm $POcm;" 522 "$ALcm $NUcm;" 523 "$HLcm $NUcm;" 524 "$CM+ $NUcm;" 525 "$NUcm $ALcm;" 526 "$NUcm $HLcm;" 527 "$PRcm $IDcm;" 528 "$PRcm ($ALcm | $HLcm);" 529 "$POcm ($ALcm | $HLcm);" 530 "($PRcm | $POcm)? ($OPcm | $HYcm)? $NUcm ($NUcm | $SYcm | $IScm)* ($CLcm | $CPcm)? ($PRcm | $POcm)?;" 531 "$JLcm ($JLcm | $JVcm | $H2cm | $H3cm);" 532 "($JVcm | $H2cm) ($JVcm | $JTcm);" 533 "($JTcm | $H3cm) $JTcm;" 534 "($JLcm | $JVcm | $JTcm | $H2cm | $H3cm) $INcm;" 535 "($JLcm | $JVcm | $JTcm | $H2cm | $H3cm) $POcm;" 536 "$PRcm ($JLcm | $JVcm | $JTcm | $H2cm | $H3cm);" 537 "($ALcm | $HLcm) ($ALcm | $HLcm);" 538 "$CM+ ($ALcm | $HLcm);" 539 "$IScm ($ALcm | $HLcm);" 540 "($ALcm | $HLcm | $NUcm) $OPcm;" 541 "$CM+ $OPcm;" 542 "$CPcm ($ALcm | $HLcm | $NUcm);"; 543 544 static const char* uax14Reverse = 545 "!!reverse;" 546 "$CM+ $ALPlus;" 547 "$CM+ $BA;" 548 "$CM+ $BB;" 549 "$CM+ $B2;" 550 "$CM+ $CL;" 551 "$CM+ $CP;" 552 "$CM+ $EX;" 553 "$CM+ $GL;" 554 "$CM+ $HL;" 555 "$CM+ $HY;" 556 "$CM+ $H2;" 557 "$CM+ $H3;" 558 "$CM+ $ID;" 559 "$CM+ $IN;" 560 "$CM+ $IS;" 561 "$CM+ $JL;" 562 "$CM+ $JV;" 563 "$CM+ $JT;" 564 "$CM+ $NS;" 565 "$CM+ $NU;" 566 "$CM+ $OP;" 567 "$CM+ $PO;" 568 "$CM+ $PR;" 569 "$CM+ $QU;" 570 "$CM+ $SY;" 571 "$CM+ $WJ;" 572 "$CM+;" 573 "$AL_FOLLOW $CM+ / ([$BK $CR $LF $NL $ZW {eof}] | $SP+ $CM+ $SP | $SP+ $CM* ([^$OP $CM $SP] | [$AL {eof}]));" 574 "[$PR] / $CM+ [$BK $CR $LF $NL $ZW $SP {eof}];" 575 "$LB4Breaks [$LB4NonBreaks-$CM];" 576 "$LB4Breaks $CM+ $CAN_CM;" 577 "$LF $CR;" 578 "[$SP $ZW] [$LB4NonBreaks-$CM];" 579 "[$SP $ZW] $CM+ $CAN_CM;" 580 "$CM+ $CAN_CM;" 581 "$CM* $WJ $CM* $CAN_CM;" 582 "$CM* $WJ [$LB8NonBreaks-$CM];" 583 "$CANT_CM $CM* $WJ;" 584 "$CM* $CAN_CM $CM* $WJ;" 585 "$CM* $GL $CM* [$LB8NonBreaks-[$CM $SP $BA $HY]];" 586 "$CANT_CM $CM* $GL;" 587 "$CM* $CAN_CM $CM* $GL;" 588 "$CL $CM+ $CAN_CM;" 589 "$CP $CM+ $CAN_CM;" 590 "$EX $CM+ $CAN_CM;" 591 "$IS $CM+ $CAN_CM;" 592 "$SY $CM+ $CAN_CM;" 593 "$CL [$LB8NonBreaks-$CM];" 594 "$CP [$LB8NonBreaks-$CM];" 595 "$EX [$LB8NonBreaks-$CM];" 596 "$IS [$LB8NonBreaks-$CM];" 597 "$SY [$LB8NonBreaks-$CM];" 598 "[$CL $CP $EX $IS $SY] $CM+ $SP+ $CM* $OP; " 599 "$CM* $CAN_CM $SP* $CM* $OP;" 600 "$CANT_CM $SP* $CM* $OP;" 601 "$AL_FOLLOW? $CM+ $SP $SP* $CM* $OP;" 602 "$AL_FOLLOW_NOCM $CM+ $SP+ $CM* $OP;" 603 "$CM* $AL_FOLLOW_CM $CM+ $SP+ $CM* $OP;" 604 "$SY $CM $SP+ $OP;" 605 "$CM* $OP $SP* $CM* $QU;" 606 "$CM* $NS $SP* $CM* ($CL | $CP);" 607 "$CM* $B2 $SP* $CM* $B2;" 608 "$CM* $QU $CM* $CAN_CM;" 609 "$CM* $QU $LB18NonBreaks;" 610 "$CM* $CAN_CM $CM* $QU;" 611 "$CANT_CM $CM* $QU;" 612 "$CM* ($BA | $HY | $NS) $CM* [$LB20NonBreaks-$CM];" 613 "$CM* [$LB20NonBreaks-$CM] $CM* $BB;" 614 "[^$CB] $CM* $BB;" 615 "[^$CB] $CM* ($HY | $BA) $CM* $HL;" 616 "$CM* $IN $CM* ($ALPlus | $HL);" 617 "$CM* $IN $CM* $ID;" 618 "$CM* $IN $CM* $IN;" 619 "$CM* $IN $CM* $NU;" 620 "$CM* $PO $CM* $ID;" 621 "$CM* $NU $CM* ($ALPlus | $HL);" 622 "$CM* ($ALPlus | $HL) $CM* $NU;" 623 "$CM* $ID $CM* $PR;" 624 "$CM* ($ALPlus | $HL) $CM* $PR;" 625 "$CM* ($ALPlus | $HL) $CM* $PO;" 626 "($CM* ($PR | $PO))? ($CM* ($CL | $CP))? ($CM* ($NU | $IS | $SY))* $CM* $NU ($CM* ($OP | $HY))? ($CM* ($PR | $PO))?;" 627 "$CM* ($H3 | $H2 | $JV | $JL) $CM* $JL;" 628 "$CM* ($JT | $JV) $CM* ($H2 | $JV);" 629 "$CM* $JT $CM* ($H3 | $JT);" 630 "$CM* $IN $CM* ($H3 | $H2 | $JT | $JV | $JL);" 631 "$CM* $PO $CM* ($H3 | $H2 | $JT | $JV | $JL);" 632 "$CM* ($H3 | $H2 | $JT | $JV | $JL) $CM* $PR;" 633 "$CM* ($ALPlus | $HL) $CM* ($ALPlus | $HL);" 634 "$CM* ($ALPlus | $HL) $CM* $IS;" 635 "$CM* $OP $CM* ($ALPlus | $HL | $NU);" 636 "$CM* ($ALPlus | $HL | $NU) $CM* $CP;"; 637 638 static const char* uax14SafeForward = 639 "!!safe_forward;" 640 "[$CM $OP $QU $CL $CP $B2 $PR $HY $BA $SP $dictionary]+ [^$CM $OP $QU $CL $CP $B2 $PR $HY $BA $dictionary];" 641 "$dictionary $dictionary;"; 642 643 static const char* uax14SafeReverse = 644 "!!safe_reverse;" 645 "$CM+ [^$CM $BK $CR $LF $NL $ZW $SP];" 646 "$CM+ $SP / .;" 647 "$SP+ $CM* $OP;" 648 "$SP+ $CM* $QU;" 649 "$SP+ $CM* ($CL | $CP);" 650 "$SP+ $CM* $B2;" 651 "$CM* ($HY | $BA) $CM* $HL;" 652 "($CM* ($IS | $SY))+ $CM* $NU;" 653 "($CL | $CP) $CM* ($NU | $IS | $SY);" 654 "$dictionary $dictionary;"; 655 656 static String mapLineIteratorModeToRules(LineBreakIteratorMode mode, bool isCJK) 657 { 658 StringBuilder rulesBuilder; 659 rulesBuilder.append(uax14Prologue); 660 rulesBuilder.append(uax14AssignmentsBefore); 661 switch (mode) { 662 case LineBreakIteratorModeUAX14: 663 rulesBuilder.append(isCJK ? uax14AssignmentsCustomDefaultCJK : uax14AssignmentsCustomDefaultNonCJK); 664 break; 665 case LineBreakIteratorModeUAX14Loose: 666 rulesBuilder.append(isCJK ? uax14AssignmentsCustomLooseCJK : uax14AssignmentsCustomLooseNonCJK); 667 break; 668 case LineBreakIteratorModeUAX14Normal: 669 rulesBuilder.append(isCJK ? uax14AssignmentsCustomNormalCJK : uax14AssignmentsCustomNormalNonCJK); 670 break; 671 case LineBreakIteratorModeUAX14Strict: 672 rulesBuilder.append(isCJK ? uax14AssignmentsCustomStrictCJK : uax14AssignmentsCustomStrictNonCJK); 673 break; 674 } 675 rulesBuilder.append(uax14AssignmentsAfter); 676 rulesBuilder.append(uax14Forward); 677 rulesBuilder.append(uax14Reverse); 678 rulesBuilder.append(uax14SafeForward); 679 rulesBuilder.append(uax14SafeReverse); 680 return rulesBuilder.toString(); 681 } 682 683 // Recognize BCP47 compliant primary language values of 'zh', 'ja', 'ko' 684 // (in any combination of case), optionally followed by subtags. Don't 685 // recognize 3-letter variants 'chi'/'zho', 'jpn', or 'kor' since BCP47 686 // requires use of shortest language tag. 687 bool isCJKLocale(const AtomicString& locale) 688 { 689 size_t length = locale.length(); 690 if (length < 2) 691 return false; 692 auto c1 = locale[0]; 693 auto c2 = locale[1]; 694 auto c3 = length == 2 ? 0 : locale[2]; 695 if (!c3 || c3 == '-' || c3 == '_' || c3 == '@') { 696 if (c1 == 'z' || c1 == 'Z') 697 return c2 == 'h' || c2 == 'H'; 698 if (c1 == 'j' || c1 == 'J') 699 return c2 == 'a' || c2 == 'A'; 700 if (c1 == 'k' || c1 == 'K') 701 return c2 == 'o' || c2 == 'O'; 702 } 703 return false; 704 } 705 706 TextBreakIterator* openLineBreakIterator(const AtomicString& locale, LineBreakIteratorMode mode, bool isCJK) 707 { 708 UBreakIterator* ubrkIter; 709 UErrorCode openStatus = U_ZERO_ERROR; 710 bool localeIsEmpty = locale.isEmpty(); 711 if (mode == LineBreakIteratorModeUAX14) 712 ubrkIter = ubrk_open(UBRK_LINE, localeIsEmpty ? currentTextBreakLocaleID() : locale.string().utf8().data(), 0, 0, &openStatus); 713 else { 714 UParseError parseStatus; 715 auto rules = mapLineIteratorModeToRules(mode, isCJK); 716 ubrkIter = ubrk_openRules(StringView(rules).upconvertedCharacters(), rules.length(), 0, 0, &parseStatus, &openStatus); 717 } 718 // locale comes from a web page and it can be invalid, leading ICU 719 // to fail, in which case we fall back to the default locale. 720 if (!localeIsEmpty && U_FAILURE(openStatus)) { 721 openStatus = U_ZERO_ERROR; 722 ubrkIter = ubrk_open(UBRK_LINE, currentTextBreakLocaleID(), 0, 0, &openStatus); 723 } 724 725 if (U_FAILURE(openStatus)) { 726 LOG_ERROR("ubrk_open failed with status %d", openStatus); 727 return nullptr; 728 } 729 730 return reinterpret_cast<TextBreakIterator*>(ubrkIter); 731 } 732 733 void closeLineBreakIterator(TextBreakIterator*& iterator) 734 { 735 UBreakIterator* ubrkIter = reinterpret_cast<UBreakIterator*>(iterator); 736 ASSERT(ubrkIter); 737 ubrk_close(ubrkIter); 738 iterator = nullptr; 273 739 } 274 740 -
trunk/Source/WebCore/platform/text/TextBreakIterator.h
r172862 r176473 31 31 32 32 // Note: The returned iterator is good only until you get another iterator, with the exception of acquireLineBreakIterator. 33 34 enum LineBreakIteratorMode { 35 LineBreakIteratorModeUAX14, 36 LineBreakIteratorModeUAX14Loose, 37 LineBreakIteratorModeUAX14Normal, 38 LineBreakIteratorModeUAX14Strict, 39 }; 33 40 34 41 // This is similar to character break iterator in most cases, but is subject to … … 41 48 TextBreakIterator* sentenceBreakIterator(StringView); 42 49 43 WEBCORE_EXPORT TextBreakIterator* acquireLineBreakIterator(StringView, const AtomicString& locale, const UChar* priorContext, unsigned priorContextLength );50 WEBCORE_EXPORT TextBreakIterator* acquireLineBreakIterator(StringView, const AtomicString& locale, const UChar* priorContext, unsigned priorContextLength, LineBreakIteratorMode, bool isCJK); 44 51 WEBCORE_EXPORT void releaseLineBreakIterator(TextBreakIterator*); 52 TextBreakIterator* openLineBreakIterator(const AtomicString& locale, LineBreakIteratorMode, bool isCJK); 53 void closeLineBreakIterator(TextBreakIterator*&); 45 54 46 55 int textBreakFirst(TextBreakIterator*); … … 56 65 const int TextBreakDone = -1; 57 66 67 bool isCJKLocale(const AtomicString&); 68 58 69 class LazyLineBreakIterator { 59 70 public: 60 71 LazyLineBreakIterator() 61 : m_iterator(0) 62 , m_cachedPriorContext(0) 72 : m_iterator(nullptr) 73 , m_cachedPriorContext(nullptr) 74 , m_mode(LineBreakIteratorModeUAX14) 63 75 , m_cachedPriorContextLength(0) 76 , m_isCJK(false) 64 77 { 65 78 resetPriorContext(); 66 79 } 67 80 68 LazyLineBreakIterator(String string, const AtomicString& locale = AtomicString() )81 LazyLineBreakIterator(String string, const AtomicString& locale = AtomicString(), LineBreakIteratorMode mode = LineBreakIteratorModeUAX14) 69 82 : m_string(string) 70 83 , m_locale(locale) 71 , m_iterator(0) 72 , m_cachedPriorContext(0) 84 , m_iterator(nullptr) 85 , m_cachedPriorContext(nullptr) 86 , m_mode(mode) 73 87 , m_cachedPriorContextLength(0) 74 88 { 75 89 resetPriorContext(); 90 m_isCJK = isCJKLocale(locale); 76 91 } 77 92 … … 83 98 84 99 String string() const { return m_string; } 100 bool isLooseCJKMode() const { return m_isCJK && m_mode == LineBreakIteratorModeUAX14Loose; } 85 101 86 102 UChar lastCharacter() const … … 89 105 return m_priorContext[1]; 90 106 } 107 91 108 UChar secondToLastCharacter() const 92 109 { … … 94 111 return m_priorContext[0]; 95 112 } 113 96 114 void setPriorContext(UChar last, UChar secondToLast) 97 115 { … … 100 118 m_priorContext[1] = last; 101 119 } 120 102 121 void updatePriorContext(UChar last) 103 122 { … … 106 125 m_priorContext[1] = last; 107 126 } 127 108 128 void resetPriorContext() 109 129 { … … 112 132 m_priorContext[1] = 0; 113 133 } 134 114 135 unsigned priorContextLength() const 115 136 { … … 123 144 return priorContextLength; 124 145 } 146 125 147 // Obtain text break iterator, possibly previously cached, where this iterator is (or has been) 126 148 // initialized to use the previously stored string as the primary breaking context and using … … 131 153 const UChar* priorContext = priorContextLength ? &m_priorContext[priorContextCapacity - priorContextLength] : 0; 132 154 if (!m_iterator) { 133 m_iterator = acquireLineBreakIterator(m_string, m_locale, priorContext, priorContextLength );155 m_iterator = acquireLineBreakIterator(m_string, m_locale, priorContext, priorContextLength, m_mode, m_isCJK); 134 156 m_cachedPriorContext = priorContext; 135 157 m_cachedPriorContextLength = priorContextLength; 136 158 } else if (priorContext != m_cachedPriorContext || priorContextLength != m_cachedPriorContextLength) { 137 this->resetStringAndReleaseIterator(m_string, m_locale);159 resetStringAndReleaseIterator(m_string, m_locale, m_mode); 138 160 return this->get(priorContextLength); 139 161 } 140 162 return m_iterator; 141 163 } 142 void resetStringAndReleaseIterator(String string, const AtomicString& locale) 164 165 void resetStringAndReleaseIterator(String string, const AtomicString& locale, LineBreakIteratorMode mode) 143 166 { 144 167 if (m_iterator) … … 146 169 m_string = string; 147 170 m_locale = locale; 148 m_iterator = 0; 149 m_cachedPriorContext = 0; 171 m_iterator = nullptr; 172 m_cachedPriorContext = nullptr; 173 m_mode = mode; 174 m_isCJK = isCJKLocale(locale); 150 175 m_cachedPriorContextLength = 0; 151 176 } … … 156 181 AtomicString m_locale; 157 182 TextBreakIterator* m_iterator; 183 const UChar* m_cachedPriorContext; 184 LineBreakIteratorMode m_mode; 185 unsigned m_cachedPriorContextLength; 158 186 UChar m_priorContext[priorContextCapacity]; 159 const UChar* m_cachedPriorContext; 160 unsigned m_cachedPriorContextLength; 187 bool m_isCJK; 161 188 }; 162 189 -
trunk/Source/WebCore/rendering/RenderText.cpp
r174875 r176473 598 598 } 599 599 600 LineBreakIteratorMode mapLineBreakToIteratorMode(LineBreak lineBreak) 601 { 602 switch (lineBreak) { 603 case LineBreakAuto: 604 case LineBreakAfterWhiteSpace: 605 return LineBreakIteratorModeUAX14; 606 case LineBreakLoose: 607 return LineBreakIteratorModeUAX14Loose; 608 case LineBreakNormal: 609 return LineBreakIteratorModeUAX14Normal; 610 case LineBreakStrict: 611 return LineBreakIteratorModeUAX14Strict; 612 } 613 return LineBreakIteratorModeUAX14; 614 } 615 600 616 void RenderText::computePreferredLogicalWidths(float leadWidth) 601 617 { … … 674 690 float wordSpacing = font.wordSpacing(); 675 691 int len = textLength(); 676 LazyLineBreakIterator breakIterator(m_text, style.locale() );692 LazyLineBreakIterator breakIterator(m_text, style.locale(), mapLineBreakToIteratorMode(style.lineBreak())); 677 693 bool needsWordSpacing = false; 678 694 bool ignoringSpaces = false; … … 709 725 bool breakNBSP = style.autoWrap() && style.nbspMode() == SPACE; 710 726 bool breakAll = (style.wordBreak() == BreakAllWordBreak || style.wordBreak() == BreakWordBreak) && style.autoWrap(); 727 bool isLooseCJKMode = breakIterator.isLooseCJKMode(); 711 728 712 729 for (int i = 0; i < len; i++) { … … 756 773 } 757 774 758 bool hasBreak = breakAll || isBreakable(breakIterator, i, nextBreakable, breakNBSP );775 bool hasBreak = breakAll || isBreakable(breakIterator, i, nextBreakable, breakNBSP, isLooseCJKMode); 759 776 bool betweenWords = true; 760 777 int j = i; … … 764 781 break; 765 782 c = uncheckedCharacterAt(j); 766 if (isBreakable(breakIterator, j, nextBreakable, breakNBSP ) && characterAt(j - 1) != softHyphen)783 if (isBreakable(breakIterator, j, nextBreakable, breakNBSP, isLooseCJKMode) && characterAt(j - 1) != softHyphen) 767 784 break; 768 785 if (breakAll) { -
trunk/Source/WebCore/rendering/RenderText.h
r176365 r176473 28 28 #include "SimpleLineLayout.h" 29 29 #include "Text.h" 30 #include "TextBreakIterator.h" 30 31 #include <wtf/Forward.h> 31 32 … … 275 276 void applyTextTransform(const RenderStyle&, String&, UChar); 276 277 void makeCapitalized(String*, UChar previous); 278 LineBreakIteratorMode mapLineBreakToIteratorMode(LineBreak); 277 279 278 280 inline RenderText* Text::renderer() const -
trunk/Source/WebCore/rendering/SimpleLineLayout.cpp
r176401 r176473 161 161 return false; 162 162 if (style.borderFit() == BorderFitLines) 163 return false; 164 if (style.lineBreak() != LineBreakAuto) 163 165 return false; 164 166 const RenderText& textRenderer = downcast<RenderText>(*flow.firstChild()); -
trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.cpp
r176470 r176473 54 54 { 55 55 String string = m_lineBreakIterator.string(); 56 unsigned breakablePosition = nextBreakablePosition <LChar, false>(m_lineBreakIterator, string.characters8(), string.length(), position);56 unsigned breakablePosition = nextBreakablePositionNonLoosely<LChar, NBSPBehavior::IgnoreNBSP>(m_lineBreakIterator, string.characters8(), string.length(), position); 57 57 if (appendNextRendererContentIfNeeded(breakablePosition)) 58 58 return findNextBreakablePosition(position); … … 158 158 159 159 ++m_lastRendererIndex; 160 m_lineBreakIterator.resetStringAndReleaseIterator(string + String(nextRenderer->text()), m_flow.style().locale() );160 m_lineBreakIterator.resetStringAndReleaseIterator(string + String(nextRenderer->text()), m_flow.style().locale(), LineBreakIteratorModeUAX14); 161 161 return true; 162 162 } -
trunk/Source/WebCore/rendering/break_lines.h
r163310 r176473 36 36 extern const unsigned char asciiLineBreakTable[][asciiLineBreakTableColumnCount]; 37 37 38 int nextBreakablePositionIgnoringNBSP(LazyLineBreakIterator&, int pos); 39 int nextBreakablePosition(LazyLineBreakIterator&, int pos); 40 41 template<bool treatNoBreakSpaceAsBreak> 38 enum class NBSPBehavior { 39 IgnoreNBSP, 40 TreatNBSPAsBreak, 41 }; 42 43 template<NBSPBehavior nbspBehavior> 42 44 static inline bool isBreakableSpace(UChar ch) 43 45 { … … 48 50 return true; 49 51 case noBreakSpace: 50 return treatNoBreakSpaceAsBreak;52 return nbspBehavior == NBSPBehavior::TreatNBSPAsBreak; 51 53 default: 52 54 return false; … … 72 74 } 73 75 74 template< bool treatNoBreakSpaceAsBreak>76 template<NBSPBehavior nbspBehavior> 75 77 inline bool needsLineBreakIterator(UChar ch) 76 78 { 77 if ( treatNoBreakSpaceAsBreak)79 if (nbspBehavior == NBSPBehavior::TreatNBSPAsBreak) 78 80 return ch > asciiLineBreakTableLastChar; 79 81 return ch > asciiLineBreakTableLastChar && ch != noBreakSpace; 80 82 } 81 83 82 template<typename CharacterType, bool treatNoBreakSpaceAsBreak> 83 inline int nextBreakablePosition(LazyLineBreakIterator& lazyBreakIterator, const CharacterType* str, unsigned length, int pos) 84 // When in non-loose mode, we can use the ASCII shortcut table. 85 template<typename CharacterType, NBSPBehavior nbspBehavior> 86 inline int nextBreakablePositionNonLoosely(LazyLineBreakIterator& lazyBreakIterator, const CharacterType* str, unsigned length, int pos) 84 87 { 85 88 int len = static_cast<int>(length); … … 92 95 CharacterType ch = str[i]; 93 96 94 if (isBreakableSpace<treatNoBreakSpaceAsBreak>(ch) || shouldBreakAfter(lastLastCh, lastCh, ch)) 97 // Non-loose mode, so use ASCII shortcut (shouldBreakAfter) if not breakable space. 98 if (isBreakableSpace<nbspBehavior>(ch) || shouldBreakAfter(lastLastCh, lastCh, ch)) 95 99 return i; 96 100 97 if (needsLineBreakIterator<treatNoBreakSpaceAsBreak>(ch) || needsLineBreakIterator<treatNoBreakSpaceAsBreak>(lastCh)) { 101 // Non-loose mode, so conditionally use break iterator. 102 if (needsLineBreakIterator<nbspBehavior>(ch) || needsLineBreakIterator<nbspBehavior>(lastCh)) { 98 103 if (nextBreak < i) { 99 104 // Don't break if positioned at start of primary context and there is no prior context. … … 107 112 } 108 113 } 109 if (i == nextBreak && !isBreakableSpace< treatNoBreakSpaceAsBreak>(lastCh))114 if (i == nextBreak && !isBreakableSpace<nbspBehavior>(lastCh)) 110 115 return i; 111 116 } … … 118 123 } 119 124 125 // 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. 126 // N.B. It should be possible to combine the following with the non-loose version above by adding a LooseBehavior template parameter; 127 // however, when doing this, a 10% performance regression appeared on chromium-win (https://bugs.webkit.org/show_bug.cgi?id=89235#c112). 128 template<typename CharacterType, NBSPBehavior nbspBehavior> 129 static inline int nextBreakablePositionLoosely(LazyLineBreakIterator& lazyBreakIterator, const CharacterType* str, unsigned length, int pos) 130 { 131 int len = static_cast<int>(length); 132 int nextBreak = -1; 133 134 CharacterType lastCh = pos > 0 ? str[pos - 1] : static_cast<CharacterType>(lazyBreakIterator.lastCharacter()); 135 unsigned priorContextLength = lazyBreakIterator.priorContextLength(); 136 for (int i = pos; i < len; i++) { 137 CharacterType ch = str[i]; 138 139 // Always loose mode, so don't use ASCII shortcut (shouldBreakAfter). 140 if (isBreakableSpace<nbspBehavior>(ch)) 141 return i; 142 143 // Always use line break iterator in loose mode. 144 if (nextBreak < i) { 145 // Don't break if positioned at start of primary context and there is no prior context. 146 if (i || priorContextLength) { 147 TextBreakIterator* breakIterator = lazyBreakIterator.get(priorContextLength); 148 if (breakIterator) { 149 nextBreak = textBreakFollowing(breakIterator, i - 1 + priorContextLength); 150 if (nextBreak >= 0) 151 nextBreak -= priorContextLength; 152 } 153 } 154 } 155 if (i == nextBreak && !isBreakableSpace<nbspBehavior>(lastCh)) 156 return i; 157 158 lastCh = ch; 159 } 160 161 return len; 162 } 163 164 inline int nextBreakablePosition(LazyLineBreakIterator& lazyBreakIterator, int pos) 165 { 166 String string = lazyBreakIterator.string(); 167 if (string.is8Bit()) 168 return nextBreakablePositionNonLoosely<LChar, NBSPBehavior::TreatNBSPAsBreak>(lazyBreakIterator, string.characters8(), string.length(), pos); 169 return nextBreakablePositionNonLoosely<UChar, NBSPBehavior::TreatNBSPAsBreak>(lazyBreakIterator, string.characters16(), string.length(), pos); 170 } 171 120 172 inline int nextBreakablePositionIgnoringNBSP(LazyLineBreakIterator& lazyBreakIterator, int pos) 121 173 { 122 174 String string = lazyBreakIterator.string(); 123 175 if (string.is8Bit()) 124 return nextBreakablePosition<LChar, false>(lazyBreakIterator, string.characters8(), string.length(), pos); 125 return nextBreakablePosition<UChar, false>(lazyBreakIterator, string.characters16(), string.length(), pos); 126 } 127 128 inline int nextBreakablePosition(LazyLineBreakIterator& lazyBreakIterator, int pos) 129 { 130 String string = lazyBreakIterator.string(); 131 if (string.is8Bit()) 132 return nextBreakablePosition<LChar, true>(lazyBreakIterator, string.characters8(), string.length(), pos); 133 return nextBreakablePosition<UChar, true>(lazyBreakIterator, string.characters16(), string.length(), pos); 134 } 135 136 inline bool isBreakable(LazyLineBreakIterator& lazyBreakIterator, int pos, int& nextBreakable, bool breakNBSP) 137 { 138 if (pos > nextBreakable) { 176 return nextBreakablePositionNonLoosely<LChar, NBSPBehavior::IgnoreNBSP>(lazyBreakIterator, string.characters8(), string.length(), pos); 177 return nextBreakablePositionNonLoosely<UChar, NBSPBehavior::IgnoreNBSP>(lazyBreakIterator, string.characters16(), string.length(), pos); 178 } 179 180 inline int nextBreakablePositionLoose(LazyLineBreakIterator& lazyBreakIterator, int pos) 181 { 182 String string = lazyBreakIterator.string(); 183 if (string.is8Bit()) 184 return nextBreakablePositionLoosely<LChar, NBSPBehavior::TreatNBSPAsBreak>(lazyBreakIterator, string.characters8(), string.length(), pos); 185 return nextBreakablePositionLoosely<UChar, NBSPBehavior::TreatNBSPAsBreak>(lazyBreakIterator, string.characters16(), string.length(), pos); 186 } 187 188 inline int nextBreakablePositionIgnoringNBSPLoose(LazyLineBreakIterator& lazyBreakIterator, int pos) 189 { 190 String string = lazyBreakIterator.string(); 191 if (string.is8Bit()) 192 return nextBreakablePositionLoosely<LChar, NBSPBehavior::IgnoreNBSP>(lazyBreakIterator, string.characters8(), string.length(), pos); 193 return nextBreakablePositionLoosely<UChar, NBSPBehavior::IgnoreNBSP>(lazyBreakIterator, string.characters16(), string.length(), pos); 194 } 195 196 inline bool isBreakable(LazyLineBreakIterator& lazyBreakIterator, int pos, int& nextBreakable, bool breakNBSP, bool isLooseMode) 197 { 198 if (pos <= nextBreakable) 199 return pos == nextBreakable; 200 201 if (isLooseMode) { 202 if (breakNBSP) 203 nextBreakable = nextBreakablePositionLoose(lazyBreakIterator, pos); 204 else 205 nextBreakable = nextBreakablePositionIgnoringNBSPLoose(lazyBreakIterator, pos); 206 } else { 139 207 if (breakNBSP) 140 208 nextBreakable = nextBreakablePosition(lazyBreakIterator, pos); -
trunk/Source/WebCore/rendering/line/BreakingContextInlineHeaders.h
r176287 r176473 625 625 bool breakAll = m_currentStyle->wordBreak() == BreakAllWordBreak && m_autoWrap; 626 626 float hyphenWidth = 0; 627 bool isLooseCJKMode = false; 627 628 628 629 if (isSVGText) { … … 636 637 m_renderTextInfo.m_font = &font; 637 638 m_renderTextInfo.m_layout = font.createLayout(&renderText, m_width.currentWidth(), m_collapseWhiteSpace); 638 m_renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(renderText.text(), style.locale()); 639 m_renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(renderText.text(), style.locale(), mapLineBreakToIteratorMode(m_blockStyle.lineBreak())); 640 isLooseCJKMode = m_renderTextInfo.m_lineBreakIterator.isLooseCJKMode(); 639 641 } else if (m_renderTextInfo.m_layout && m_renderTextInfo.m_font != &font) { 640 642 m_renderTextInfo.m_font = &font; … … 677 679 678 680 int nextBreakablePosition = m_current.nextBreakablePosition(); 679 bool betweenWords = c == '\n' || (m_currWS != PRE && !m_atStart && isBreakable(m_renderTextInfo.m_lineBreakIterator, m_current.offset(), nextBreakablePosition, breakNBSP )681 bool betweenWords = c == '\n' || (m_currWS != PRE && !m_atStart && isBreakable(m_renderTextInfo.m_lineBreakIterator, m_current.offset(), nextBreakablePosition, breakNBSP, isLooseCJKMode) 680 682 && (style.hyphens() != HyphensNone || (m_current.previousInSameNode() != softHyphen))); 681 683 m_current.setNextBreakablePosition(nextBreakablePosition);
Note:
See TracChangeset
for help on using the changeset viewer.