⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 179734 in webkit


Ignore:
Timestamp:
Feb 5, 2015, 5:40:21 PM (12 years ago)
Author:
Lucas Forschler
Message:

Merge patch from rdar://problem/19432653.

Location:
branches/safari-600.1.4.15-branch
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • branches/safari-600.1.4.15-branch/LayoutTests/ChangeLog

    r179730 r179734  
     12015-02-05  David Kilzer  <ddkilzer@apple.com>
     2
     3        Merge r176473.
     4
     5    2014-11-21  Glenn Adams  <glenn@skynav.com> and Myles C. Maxfield  <mmaxfield@apple.com>
     6
     7        CSS3: line-break property support
     8        https://bugs.webkit.org/show_bug.cgi?id=89235
     9
     10        Reviewed by Eric Seidel and Dave Hyatt.
     11
     12        * platform/mac/TestExpectations: Mark css3/line-break tests as passing.
     13
    1142015-02-05  Lucas Forschler  <lforschler@apple.com>
    215
  • branches/safari-600.1.4.15-branch/LayoutTests/platform/mac/TestExpectations

    r172752 r179734  
    13911391webkit.org/b/133686 media/track/w3c/interfaces/TextTrackCue/startTime.html [ Pass Failure ]
    13921392webkit.org/b/133686 media/track/w3c/interfaces/TextTrackCue/track.html [ Pass Failure ]
     1393
     1394# Verified passing, so override generic skip
     1395webkit.org/b/89235 css3/line-break [ Pass ]
     1396webkit.org/b/138115 css3/line-break/line-break-auto-hyphens.html [ ImageOnlyFailure ]
     1397webkit.org/b/138115 css3/line-break/line-break-auto-sound-marks.html [ ImageOnlyFailure ]
  • branches/safari-600.1.4.15-branch/Source/WebCore/ChangeLog

    r179730 r179734  
     12015-02-05  David Kilzer  <ddkilzer@apple.com>
     2
     3        Merge r176473.
     4
     5        * rendering/SimpleLineLayout.cpp:
     6        (WebCore::SimpleLineLayout::canUseFor): Change from
     7        r176473 not listed in that ChangeLog.
     8        (WebCore::SimpleLineLayout::createLineRuns): Call
     9        nextBreakablePositionNonLoosely() in place of
     10        nextBreakablePosition().
     11
     12    2014-11-21  Glenn Adams  <glenn@skynav.com> and Myles C. Maxfield  <mmaxfield@apple.com>
     13
     14        Add support to -webkit-line-break property for CSS3 Text line-break property values and semantics.
     15        https://bugs.webkit.org/show_bug.cgi?id=89235
     16
     17        Reviewed by Eric Seidel and Dave Hyatt.
     18
     19        This patch adds semantic support for the CSS3 line-break property (qua -webkit-line-break),
     20        and enables testing on (apple) mac ports. Follow on patches will enable these tests on
     21        other ports as they are incrementally verified.
     22
     23        See also wiki documentation at:
     24        [1] http://trac.webkit.org/wiki/LineBreaking
     25        [2] http://trac.webkit.org/wiki/LineBreakingCSS3Mapping
     26
     27        Tests: css3/line-break/line-break-auto-centered.html
     28               css3/line-break/line-break-auto-half-kana.html
     29               css3/line-break/line-break-auto-hyphens.html
     30               css3/line-break/line-break-auto-inseparables.html
     31               css3/line-break/line-break-auto-iteration-marks.html
     32               css3/line-break/line-break-auto-postfixes.html
     33               css3/line-break/line-break-auto-prefixes.html
     34               css3/line-break/line-break-auto-sound-marks.html
     35               css3/line-break/line-break-loose-centered.html
     36               css3/line-break/line-break-loose-half-kana.html
     37               css3/line-break/line-break-loose-hyphens.html
     38               css3/line-break/line-break-loose-inseparables.html
     39               css3/line-break/line-break-loose-iteration-marks.html
     40               css3/line-break/line-break-loose-postfixes.html
     41               css3/line-break/line-break-loose-prefixes.html
     42               css3/line-break/line-break-loose-sound-marks.html
     43               css3/line-break/line-break-normal-centered.html
     44               css3/line-break/line-break-normal-half-kana.html
     45               css3/line-break/line-break-normal-hyphens.html
     46               css3/line-break/line-break-normal-inseparables.html
     47               css3/line-break/line-break-normal-iteration-marks.html
     48               css3/line-break/line-break-normal-postfixes.html
     49               css3/line-break/line-break-normal-prefixes.html
     50               css3/line-break/line-break-normal-sound-marks.html
     51               css3/line-break/line-break-strict-centered.html
     52               css3/line-break/line-break-strict-half-kana.html
     53               css3/line-break/line-break-strict-hyphens.html
     54               css3/line-break/line-break-strict-inseparables.html
     55               css3/line-break/line-break-strict-iteration-marks.html
     56               css3/line-break/line-break-strict-postfixes.html
     57               css3/line-break/line-break-strict-prefixes.html
     58               css3/line-break/line-break-strict-sound-marks.html
     59
     60        These tests were previously added in http://trac.webkit.org/changeset/143378, but skipped
     61        in generic TestExpectations. In this patch, they are marked as Pass for the (apple) mac ports.
     62
     63        * platform/text/LineBreakIteratorPoolICU.h:
     64        (WebCore::LineBreakIteratorPool::makeLocaleWithBreakKeyword):
     65        Add static function to construct ICU locale argument (also used as pool key) with additional
     66        break keyword.
     67        (LineBreakIteratorPool):
     68        (WebCore::LineBreakIteratorPool::take):
     69        (WebCore::LineBreakIteratorPool::put):
     70        Remove direct dependency from ICU library (and types), moving that dependency into
     71        new {open,close}LineBreakIterator() functions (defined in TextBreakIteratorICU.cpp).
     72        Update to take line break mode into account.
     73        Create (and cache) different break iterators depending on line break mode (in addition to locale),
     74        which entails expanding pool entry key format to optionally append "@break=" +
     75        "loose"|"normal"|"strict" keyword to locale string.
     76
     77        * platform/text/TextBreakIterator.h:
     78        (WebCore::LazyLineBreakIterator::LazyLineBreakIterator):
     79        (WebCore::LazyLineBreakIterator::isLooseCJKMode):
     80        (WebCore::LazyLineBreakIterator::get):
     81        (WebCore::LazyLineBreakIterator::reset):
     82        (LazyLineBreakIterator):
     83        Define LineBreakIteratorMode enumeration for use in TextBreakIterator et al.
     84        Add state member to indicate line break mode.
     85
     86        * platform/text/TextBreakIteratorICU.cpp:
     87        (WebCore::acquireLineBreakIterator):
     88        Use new line break mode when making iterator from pool.
     89        Handle change of return type of LineBreakIteratorPool::take() to non-ICU type,
     90        i.e., TextBreakIterator* instead of ICU's UBreakIterator*.
     91        (WebCore::releaseLineBreakIterator):
     92        Handle change of parameter type of LineBreakIteratorPool::put() to non-ICU type,
     93        i.e., TextBreakIterator* instead of ICU's UBreakIterator*.
     94        (WebCore):
     95        (WebCore::isCJKLocale):
     96        New functions for determining if CJK rules apply.
     97        (WebCore::openLineBreakIterator):
     98        New function for abstracting opening of ICU style line break iterator. This is now
     99        used in LineBreakIteratorPoolICU.h rather than having direct ICU API dependency there.
     100        This function also takes into account the line break mode.
     101
     102        Note that this function only calls ubrk_openRules() when the author has opted-in via
     103        using the -webkit-line-break CSS property. Eventually, we would like to be able to
     104        customize the rules that ICU's line breaking algorithm uses (especially for CJK text);
     105        however, ubrk_openRules() currently parses its input string to create a DFA and is
     106        therefore very slow. In fact, it's so slow that increasing our cache size in
     107        LineBreakIteratorPool doesn't actually help enough. Also note that the default value
     108        for the line-break CSS property is 'auto'.
     109        (WebCore::closeLineBreakIterator):
     110        (WebCore::mapLineIteratorModeToRules):
     111        New function for abstracting closing of ICU style line break iterator. This is now
     112        used in LineBreakIteratorPoolICU.h rather than having direct ICU API dependency there.
     113
     114        * rendering/RenderBlockLineLayout.cpp:
     115        (WebCore::RenderBlock::LineBreaker::nextSegmentBreak):
     116        Pass line break iterator mode flag when reseting LazyLineBreakIterator.
     117        Add looseMode local variable to prevent need for computing under isBreakable().
     118
     119        * rendering/RenderText.cpp:
     120        (WebCore::mapLineBreakToIteratorMode):
     121        Add implementation for mapLineBreakToIteratorMode(), used by both RenderText::computePreferredLogicalWidths
     122        and RenderBlock::LineBreaker::nextLineBreak.
     123        (WebCore):
     124        (WebCore::RenderText::computePreferredLogicalWidths):
     125        Ensure (lazy line) breakIterator is initialized for line break mode.
     126        Ensure isBreakable() is passed loose mode flag to match behavior in RenderBlock::LineBreaker::nextLineBreak.
     127
     128        * rendering/RenderText.h:
     129        (WebCore):
     130        Add declaration for mapLineBreakToIteratorMode(), used by both RenderText::computePreferredLogicalWidths
     131        and RenderBlock::LineBreaker::nextLineBreak.
     132
     133        * rendering/break_lines.cpp:
     134        (WebCore):
     135        Introduce (local) enum NBSPBehavior for expanding template on nextBreakablePosition.
     136        (WebCore::isBreakableSpace):
     137        Add externally specified loose mode parameter to prevent need to invoke line break iterator
     138        accessor method on each invocation. Use new loose mode flavors off NBP functions.
     139        (WebCore::needsLineBreakIterator):
     140        Use enum NBSP behavior template parameter rather than boolean.
     141        (WebCore::nextBreakablePositionNonLoosely):
     142        Extend name to distinguish from loose flavor of this function.
     143        (WebCore::nextBreakablePositionLoosely):
     144        Add loose flavor of NBP invoked only when loose mode applies, in which case ASCII shortcut
     145        table cannot be used.
     146        (WebCore::nextBreakablePosition):
     147        (WebCore::nextBreakablePositionIgnoringNBSP):
     148        Use (renamed) non-loose flavor of NBP.
     149        (WebCore::nextBreakablePositionLoose):
     150        (WebCore::nextBreakablePositionIgnoringNBSPLoose):
     151        Introduce loose flavor of NBP template expansions.
     152
     153        * rendering/break_lines.h:
     154        (WebCore):
     155        (WebCore::isBreakable):
     156        Add externally specified loose mode parameter to prevent need to invoke line break iterator
     157        accessor method on each invocation.
     158
    11592015-02-05  Lucas Forschler  <lforschler@apple.com>
    2160
  • branches/safari-600.1.4.15-branch/Source/WebCore/WebCore.exp.in

    r179678 r179734  
    25462546__ZN7WebCore11MemoryCache18pruneDeadResourcesEv
    25472547__ZN7WebCore11MemoryCache18pruneLiveResourcesEb
     2548__ZN7WebCore11isCJKLocaleERKN3WTF12AtomicStringE
    25482549__ZN7WebCore11isEndOfLineERKNS_15VisiblePositionE
    25492550__ZN7WebCore11prefetchDNSERKN3WTF6StringE
     
    26652666__ZN7WebCore24FloatingPointEnvironment25saveMainThreadEnvironmentEv
    26662667__ZN7WebCore24FloatingPointEnvironment6sharedEv
    2667 __ZN7WebCore24acquireLineBreakIteratorEN3WTF10StringViewERKNS0_12AtomicStringEPKtj
     2668__ZN7WebCore24acquireLineBreakIteratorEN3WTF10StringViewERKNS0_12AtomicStringEPKtjNS_21LineBreakIteratorModeEb
    26682669__ZN7WebCore24charactersAroundPositionERKNS_15VisiblePositionERiS3_S3_
    26692670__ZN7WebCore24createTemporaryDirectoryEP8NSString
  • branches/safari-600.1.4.15-branch/Source/WebCore/platform/text/LineBreakIteratorPoolICU.h

    r161309 r179734  
    2727#define LineBreakIteratorPoolICU_h
    2828
     29#include "TextBreakIterator.h"
    2930#include "TextBreakIteratorInternalICU.h"
    3031#include <unicode/ubrk.h>
     
    3536#include <wtf/text/AtomicString.h>
    3637#include <wtf/text/CString.h>
     38#include <wtf/text/StringBuilder.h>
    3739
    3840namespace WebCore {
     
    4951    static PassOwnPtr<LineBreakIteratorPool> create() { return adoptPtr(new LineBreakIteratorPool); }
    5052
    51     UBreakIterator* take(const AtomicString& locale)
     53    static String makeLocaleWithBreakKeyword(const AtomicString& locale, LineBreakIteratorMode mode)
    5254    {
    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;
    5484        for (size_t i = 0; i < m_pool.size(); ++i) {
    55             if (m_pool[i].first == locale) {
     85            if (m_pool[i].first == localeWithOptionalBreakKeyword) {
    5686                iterator = m_pool[i].second;
    5787                m_pool.remove(i);
     
    6191
    6292        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)
    7595                return 0;
    76             }
    7796        }
    7897
    7998        ASSERT(!m_vendedIterators.contains(iterator));
    80         m_vendedIterators.set(iterator, locale);
     99        m_vendedIterators.set(iterator, localeWithOptionalBreakKeyword);
    81100        return iterator;
    82101    }
    83102
    84     void put(UBreakIterator* iterator)
     103    void put(TextBreakIterator* iterator)
    85104    {
    86105        ASSERT_ARG(iterator, m_vendedIterators.contains(iterator));
    87106
    88107        if (m_pool.size() == capacity) {
    89             ubrk_close(m_pool[0].second);
     108            closeLineBreakIterator(m_pool[0].second);
    90109            m_pool.remove(0);
    91110        }
     
    99118    static const size_t capacity = 4;
    100119
    101     typedef std::pair<AtomicString, UBreakIterator*> Entry;
     120    typedef std::pair<AtomicString, TextBreakIterator*> Entry;
    102121    typedef Vector<Entry, capacity> Pool;
    103122    Pool m_pool;
    104     HashMap<UBreakIterator*, AtomicString> m_vendedIterators;
     123    HashMap<TextBreakIterator*, AtomicString> m_vendedIterators;
    105124
    106125    friend WTF::ThreadSpecific<LineBreakIteratorPool>::operator LineBreakIteratorPool*();
  • branches/safari-600.1.4.15-branch/Source/WebCore/platform/text/TextBreakIterator.cpp

    r179730 r179734  
    257257}
    258258
    259 TextBreakIterator* acquireLineBreakIterator(StringView string, const AtomicString& locale, const UChar* priorContext, unsigned priorContextLength)
    260 {
    261     TextBreakIterator* iterator = reinterpret_cast<TextBreakIterator*>(LineBreakIteratorPool::sharedPool().take(locale));
     259TextBreakIterator* 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);
    262262    if (!iterator)
    263263        return nullptr;
     
    270270    ASSERT_ARG(iterator, iterator);
    271271
    272     LineBreakIteratorPool::sharedPool().put(reinterpret_cast<UBreakIterator*>(iterator));
     272    LineBreakIteratorPool::sharedPool().put(iterator);
     273}
     274
     275static const char* uax14Prologue =
     276    "!!chain;"
     277    "!!LBCMNoChain;"
     278    "!!lookAheadHardBreak;";
     279
     280static 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
     293static 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
     305static 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
     317static 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
     329static 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
     341static 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
     357static 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
     429static 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
     544static 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
     638static 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
     643static 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
     656static 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.
     687bool 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
     706TextBreakIterator* 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
     733void closeLineBreakIterator(TextBreakIterator*& iterator)
     734{
     735    UBreakIterator* ubrkIter = reinterpret_cast<UBreakIterator*>(iterator);
     736    ASSERT(ubrkIter);
     737    ubrk_close(ubrkIter);
     738    iterator = nullptr;
    273739}
    274740
  • branches/safari-600.1.4.15-branch/Source/WebCore/platform/text/TextBreakIterator.h

    r163310 r179734  
    3131
    3232// Note: The returned iterator is good only until you get another iterator, with the exception of acquireLineBreakIterator.
     33
     34enum LineBreakIteratorMode {
     35    LineBreakIteratorModeUAX14,
     36    LineBreakIteratorModeUAX14Loose,
     37    LineBreakIteratorModeUAX14Normal,
     38    LineBreakIteratorModeUAX14Strict,
     39};
    3340
    3441// This is similar to character break iterator in most cases, but is subject to
     
    4148TextBreakIterator* sentenceBreakIterator(StringView);
    4249
    43 TextBreakIterator* acquireLineBreakIterator(StringView, const AtomicString& locale, const UChar* priorContext, unsigned priorContextLength);
     50TextBreakIterator* acquireLineBreakIterator(StringView, const AtomicString& locale, const UChar* priorContext, unsigned priorContextLength, LineBreakIteratorMode, bool isCJK);
    4451void releaseLineBreakIterator(TextBreakIterator*);
     52TextBreakIterator* openLineBreakIterator(const AtomicString& locale, LineBreakIteratorMode, bool isCJK);
     53void closeLineBreakIterator(TextBreakIterator*&);
    4554
    4655int textBreakFirst(TextBreakIterator*);
     
    5665const int TextBreakDone = -1;
    5766
     67bool isCJKLocale(const AtomicString&);
     68
    5869class LazyLineBreakIterator {
    5970public:
    6071    LazyLineBreakIterator()
    61         : m_iterator(0)
    62         , m_cachedPriorContext(0)
     72        : m_iterator(nullptr)
     73        , m_cachedPriorContext(nullptr)
     74        , m_mode(LineBreakIteratorModeUAX14)
    6375        , m_cachedPriorContextLength(0)
     76        , m_isCJK(false)
    6477    {
    6578        resetPriorContext();
    6679    }
    6780
    68     LazyLineBreakIterator(String string, const AtomicString& locale = AtomicString())
     81    LazyLineBreakIterator(String string, const AtomicString& locale = AtomicString(), LineBreakIteratorMode mode = LineBreakIteratorModeUAX14)
    6982        : m_string(string)
    7083        , m_locale(locale)
    71         , m_iterator(0)
    72         , m_cachedPriorContext(0)
     84        , m_iterator(nullptr)
     85        , m_cachedPriorContext(nullptr)
     86        , m_mode(mode)
    7387        , m_cachedPriorContextLength(0)
    7488    {
    7589        resetPriorContext();
     90        m_isCJK = isCJKLocale(locale);
    7691    }
    7792
     
    8398
    8499    String string() const { return m_string; }
     100    bool isLooseCJKMode() const { return m_isCJK && m_mode == LineBreakIteratorModeUAX14Loose; }
    85101
    86102    UChar lastCharacter() const
     
    89105        return m_priorContext[1];
    90106    }
     107
    91108    UChar secondToLastCharacter() const
    92109    {
     
    94111        return m_priorContext[0];
    95112    }
     113
    96114    void setPriorContext(UChar last, UChar secondToLast)
    97115    {
     
    100118        m_priorContext[1] = last;
    101119    }
     120
    102121    void updatePriorContext(UChar last)
    103122    {
     
    106125        m_priorContext[1] = last;
    107126    }
     127
    108128    void resetPriorContext()
    109129    {
     
    112132        m_priorContext[1] = 0;
    113133    }
     134
    114135    unsigned priorContextLength() const
    115136    {
     
    123144        return priorContextLength;
    124145    }
     146
    125147    // Obtain text break iterator, possibly previously cached, where this iterator is (or has been)
    126148    // initialized to use the previously stored string as the primary breaking context and using
     
    131153        const UChar* priorContext = priorContextLength ? &m_priorContext[priorContextCapacity - priorContextLength] : 0;
    132154        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);
    134156            m_cachedPriorContext = priorContext;
    135157            m_cachedPriorContextLength = priorContextLength;
    136158        } else if (priorContext != m_cachedPriorContext || priorContextLength != m_cachedPriorContextLength) {
    137             this->resetStringAndReleaseIterator(m_string, m_locale);
     159            resetStringAndReleaseIterator(m_string, m_locale, m_mode);
    138160            return this->get(priorContextLength);
    139161        }
    140162        return m_iterator;
    141163    }
    142     void resetStringAndReleaseIterator(String string, const AtomicString& locale)
     164
     165    void resetStringAndReleaseIterator(String string, const AtomicString& locale, LineBreakIteratorMode mode)
    143166    {
    144167        if (m_iterator)
     
    146169        m_string = string;
    147170        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);
    150175        m_cachedPriorContextLength = 0;
    151176    }
     
    156181    AtomicString m_locale;
    157182    TextBreakIterator* m_iterator;
     183    const UChar* m_cachedPriorContext;
     184    LineBreakIteratorMode m_mode;
     185    unsigned m_cachedPriorContextLength;
    158186    UChar m_priorContext[priorContextCapacity];
    159     const UChar* m_cachedPriorContext;
    160     unsigned m_cachedPriorContextLength;
     187    bool m_isCJK;
    161188};
    162189
  • branches/safari-600.1.4.15-branch/Source/WebCore/rendering/RenderText.cpp

    r179730 r179734  
    598598}
    599599
     600LineBreakIteratorMode 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
    600616void RenderText::computePreferredLogicalWidths(float leadWidth)
    601617{
     
    674690    float wordSpacing = font.wordSpacing();
    675691    int len = textLength();
    676     LazyLineBreakIterator breakIterator(m_text, style.locale());
     692    LazyLineBreakIterator breakIterator(m_text, style.locale(), mapLineBreakToIteratorMode(style.lineBreak()));
    677693    bool needsWordSpacing = false;
    678694    bool ignoringSpaces = false;
     
    709725    bool breakNBSP = style.autoWrap() && style.nbspMode() == SPACE;
    710726    bool breakAll = (style.wordBreak() == BreakAllWordBreak || style.wordBreak() == BreakWordBreak) && style.autoWrap();
     727    bool isLooseCJKMode = breakIterator.isLooseCJKMode();
    711728
    712729    for (int i = 0; i < len; i++) {
     
    756773        }
    757774
    758         bool hasBreak = breakAll || isBreakable(breakIterator, i, nextBreakable, breakNBSP);
     775        bool hasBreak = breakAll || isBreakable(breakIterator, i, nextBreakable, breakNBSP, isLooseCJKMode);
    759776        bool betweenWords = true;
    760777        int j = i;
     
    764781                break;
    765782            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)
    767784                break;
    768785            if (breakAll) {
  • branches/safari-600.1.4.15-branch/Source/WebCore/rendering/RenderText.h

    r179133 r179734  
    2828#include "SimpleLineLayout.h"
    2929#include "Text.h"
     30#include "TextBreakIterator.h"
    3031#include <wtf/Forward.h>
    3132
     
    258259void applyTextTransform(const RenderStyle&, String&, UChar);
    259260void makeCapitalized(String*, UChar previous);
     261LineBreakIteratorMode mapLineBreakToIteratorMode(LineBreak);
    260262   
    261263inline RenderText* Text::renderer() const
  • branches/safari-600.1.4.15-branch/Source/WebCore/rendering/SimpleLineLayout.cpp

    r170871 r179734  
    163163    if (style.borderFit() == BorderFitLines)
    164164        return false;
     165    if (style.lineBreak() != LineBreakAuto)
     166        return false;
    165167    const RenderText& textRenderer = toRenderText(*flow.firstChild());
    166168    if (flow.containsFloats()) {
     
    284286            wordEnd = wordStart + 1;
    285287        else
    286             wordEnd = nextBreakablePosition<CharacterType, false>(lineBreakIterator, text, textLength, wordStart + 1);
     288            wordEnd = nextBreakablePositionNonLoosely<CharacterType, NBSPBehavior::IgnoreNBSP>(lineBreakIterator, text, textLength, wordStart + 1);
    287289
    288290        bool wordIsPrecededByWhitespace = style.collapseWhitespace && wordStart > lineStart && isWhitespace(text[wordStart - 1], style.preserveNewline);
  • branches/safari-600.1.4.15-branch/Source/WebCore/rendering/break_lines.h

    r163310 r179734  
    3636extern const unsigned char asciiLineBreakTable[][asciiLineBreakTableColumnCount];
    3737
    38 int nextBreakablePositionIgnoringNBSP(LazyLineBreakIterator&, int pos);
    39 int nextBreakablePosition(LazyLineBreakIterator&, int pos);
    40 
    41 template<bool treatNoBreakSpaceAsBreak>
     38enum class NBSPBehavior {
     39    IgnoreNBSP,
     40    TreatNBSPAsBreak,
     41};
     42
     43template<NBSPBehavior nbspBehavior>
    4244static inline bool isBreakableSpace(UChar ch)
    4345{
     
    4850        return true;
    4951    case noBreakSpace:
    50         return treatNoBreakSpaceAsBreak;
     52        return nbspBehavior == NBSPBehavior::TreatNBSPAsBreak;
    5153    default:
    5254        return false;
     
    7274}
    7375
    74 template<bool treatNoBreakSpaceAsBreak>
     76template<NBSPBehavior nbspBehavior>
    7577inline bool needsLineBreakIterator(UChar ch)
    7678{
    77     if (treatNoBreakSpaceAsBreak)
     79    if (nbspBehavior == NBSPBehavior::TreatNBSPAsBreak)
    7880        return ch > asciiLineBreakTableLastChar;
    7981    return ch > asciiLineBreakTableLastChar && ch != noBreakSpace;
    8082}
    8183
    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.
     85template<typename CharacterType, NBSPBehavior nbspBehavior>
     86inline int nextBreakablePositionNonLoosely(LazyLineBreakIterator& lazyBreakIterator, const CharacterType* str, unsigned length, int pos)
    8487{
    8588    int len = static_cast<int>(length);
     
    9295        CharacterType ch = str[i];
    9396
    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))
    9599            return i;
    96100
    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)) {
    98103            if (nextBreak < i) {
    99104                // Don't break if positioned at start of primary context and there is no prior context.
     
    107112                }
    108113            }
    109             if (i == nextBreak && !isBreakableSpace<treatNoBreakSpaceAsBreak>(lastCh))
     114            if (i == nextBreak && !isBreakableSpace<nbspBehavior>(lastCh))
    110115                return i;
    111116        }
     
    118123}
    119124
     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).
     128template<typename CharacterType, NBSPBehavior nbspBehavior>
     129static 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
     164inline 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
    120172inline int nextBreakablePositionIgnoringNBSP(LazyLineBreakIterator& lazyBreakIterator, int pos)
    121173{
    122174    String string = lazyBreakIterator.string();
    123175    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
     180inline 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
     188inline 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
     196inline 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 {
    139207        if (breakNBSP)
    140208            nextBreakable = nextBreakablePosition(lazyBreakIterator, pos);
  • branches/safari-600.1.4.15-branch/Source/WebCore/rendering/line/BreakingContextInlineHeaders.h

    r179722 r179734  
    629629    bool breakAll = m_currentStyle->wordBreak() == BreakAllWordBreak && m_autoWrap;
    630630    float hyphenWidth = 0;
     631    bool isLooseCJKMode = false;
    631632
    632633    if (isSVGText) {
     
    640641        m_renderTextInfo.m_font = &font;
    641642        m_renderTextInfo.m_layout = font.createLayout(renderText, m_width.currentWidth(), m_collapseWhiteSpace);
    642         m_renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(renderText->text(), style.locale());
     643        m_renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(renderText->text(), style.locale(), mapLineBreakToIteratorMode(m_blockStyle.lineBreak()));
     644        isLooseCJKMode = m_renderTextInfo.m_lineBreakIterator.isLooseCJKMode();
    643645    } else if (m_renderTextInfo.m_layout && m_renderTextInfo.m_font != &font) {
    644646        m_renderTextInfo.m_font = &font;
     
    681683
    682684        int nextBreakablePosition = m_current.nextBreakablePosition();
    683         bool betweenWords = c == '\n' || (m_currWS != PRE && !m_atStart && isBreakable(m_renderTextInfo.m_lineBreakIterator, m_current.offset(), nextBreakablePosition, breakNBSP)
     685        bool betweenWords = c == '\n' || (m_currWS != PRE && !m_atStart && isBreakable(m_renderTextInfo.m_lineBreakIterator, m_current.offset(), nextBreakablePosition, breakNBSP, isLooseCJKMode)
    684686            && (style.hyphens() != HyphensNone || (m_current.previousInSameNode() != softHyphen)));
    685687        m_current.setNextBreakablePosition(nextBreakablePosition);
Note: See TracChangeset for help on using the changeset viewer.