Make line breaking obey the -webkit-locale property
authormitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 23 Jun 2011 18:02:45 +0000 (18:02 +0000)
committermitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 23 Jun 2011 18:02:45 +0000 (18:02 +0000)
https://bugs.webkit.org/show_bug.cgi?id=63209

Reviewed by Alexey Proskuryakov.

Source/WebCore:

Test: platform/mac/fast/text/line-break-locale.html

* platform/text/TextBreakIterator.h:
(WebCore::LazyLineBreakIterator::LazyLineBreakIterator): Take an optional locale identifier and
initialize the m_locale member.
(WebCore::LazyLineBreakIterator::get): Pass the locale to acquireLineBreakIterator().
(WebCore::LazyLineBreakIterator::reset): Pass the locale to releaseLineBreakIterator() and update
the m_locale member.
* platform/text/TextBreakIteratorICU.cpp:
(WebCore::LineBreakIteratorPool::sharedPool): Return a shared instance.
(WebCore::LineBreakIteratorPool::take): Returns a text iterator for the given locale, either a newly-
created one, or an existing one from the pool.
(WebCore::LineBreakIteratorPool::put): Puts an iterator back into the pool, removing the least-recently used
one if needed.
(WebCore::LineBreakIteratorPool::LineBreakIteratorPool):
(WebCore::acquireLineBreakIterator): Changed to take an optional local identifier, and to use the pool.
(WebCore::releaseLineBreakIterator): Changed to use the pool.
* platform/text/brew/TextBreakIteratorBrew.cpp:
(WebCore::acquireLineBreakIterator): Updated for new parameter.
* platform/text/gtk/TextBreakIteratorGtk.cpp:
(WebCore::acquireLineBreakIterator): Ditto.
* platform/text/qt/TextBreakIteratorQt.cpp:
(WebCore::acquireLineBreakIterator): Ditto.
* platform/text/wince/TextBreakIteratorWinCE.cpp:
(WebCore::acquireLineBreakIterator): Ditto.
* rendering/RenderBlockLineLayout.cpp:
(WebCore::RenderBlock::LineBreaker::nextLineBreak): Use the locale from the style for the line break
iterator.
* rendering/RenderText.cpp:
(WebCore::RenderText::computePreferredLogicalWidths): Ditto.

LayoutTests:

* platform/mac/fast/text/line-break-locale.html: Added.
* platform/mac/platform/mac/fast/text/line-break-locale-expected.png: Added.
* platform/mac/platform/mac/fast/text/line-break-locale-expected.txt: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@89592 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/mac/fast/text/line-break-locale.html [new file with mode: 0644]
LayoutTests/platform/mac/platform/mac/fast/text/line-break-locale-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/platform/mac/fast/text/line-break-locale-expected.txt [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/platform/text/TextBreakIterator.h
Source/WebCore/platform/text/TextBreakIteratorICU.cpp
Source/WebCore/platform/text/brew/TextBreakIteratorBrew.cpp
Source/WebCore/platform/text/gtk/TextBreakIteratorGtk.cpp
Source/WebCore/platform/text/qt/TextBreakIteratorQt.cpp
Source/WebCore/platform/text/wince/TextBreakIteratorWinCE.cpp
Source/WebCore/rendering/RenderBlockLineLayout.cpp
Source/WebCore/rendering/RenderText.cpp

index a62db7960af92316242393dbde0b8e9fe746b423..231a9d7d39cb68236468d72e4bc12b9fbaab0a09 100644 (file)
@@ -1,3 +1,14 @@
+2011-06-23  Dan Bernstein  <mitz@apple.com>
+
+        Reviewed by Alexey Proskuryakov.
+
+        Make line breaking obey the -webkit-locale property
+        https://bugs.webkit.org/show_bug.cgi?id=63209
+
+        * platform/mac/fast/text/line-break-locale.html: Added.
+        * platform/mac/platform/mac/fast/text/line-break-locale-expected.png: Added.
+        * platform/mac/platform/mac/fast/text/line-break-locale-expected.txt: Added.
+
 2011-06-23  Chris Fleizach  <cfleizach@apple.com>
 
         Reviewed by Darin Adler.
diff --git a/LayoutTests/platform/mac/fast/text/line-break-locale.html b/LayoutTests/platform/mac/fast/text/line-break-locale.html
new file mode 100644 (file)
index 0000000..a8f2b54
--- /dev/null
@@ -0,0 +1,11 @@
+<meta charset=utf-8>
+<p>
+    This tests that line breaking obeys the <tt>-webkit-locale</tt> property.
+</p>
+<div style="
+    direction: rtl;
+    width: 120px;
+    outline: solid blue;
+    font-size: 24px;
+    -webkit-locale: 'he';
+">קרא ב-ויקיפדיה</div>
diff --git a/LayoutTests/platform/mac/platform/mac/fast/text/line-break-locale-expected.png b/LayoutTests/platform/mac/platform/mac/fast/text/line-break-locale-expected.png
new file mode 100644 (file)
index 0000000..c445b2e
Binary files /dev/null and b/LayoutTests/platform/mac/platform/mac/fast/text/line-break-locale-expected.png differ
diff --git a/LayoutTests/platform/mac/platform/mac/fast/text/line-break-locale-expected.txt b/LayoutTests/platform/mac/platform/mac/fast/text/line-break-locale-expected.txt
new file mode 100644 (file)
index 0000000..736065f
--- /dev/null
@@ -0,0 +1,17 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {P} at (0,0) size 784x18
+        RenderText {#text} at (0,0) size 240x18
+          text run at (0,0) width 240: "This tests that line breaking obeys the "
+        RenderInline {TT} at (0,0) size 112x15
+          RenderText {#text} at (240,2) size 112x15
+            text run at (240,2) width 112: "-webkit-locale"
+        RenderText {#text} at (352,0) size 61x18
+          text run at (352,0) width 61: " property."
+      RenderBlock {DIV} at (0,34) size 120x58
+        RenderText {#text} at (76,1) size 111x57
+          text run at (76,1) width 44 RTL: "\x{5E7}\x{5E8}\x{5D0}"
+          text run at (9,30) width 111 RTL: "\x{5D1}-\x{5D5}\x{5D9}\x{5E7}\x{5D9}\x{5E4}\x{5D3}\x{5D9}\x{5D4}"
index be3a72f4d4b82bd81607780b6bf3151ad86e8b31..89c7ba104a0b6a9aa18c6d816a23ad2774856d21 100644 (file)
@@ -1,3 +1,41 @@
+2011-06-23  Dan Bernstein  <mitz@apple.com>
+
+        Reviewed by Alexey Proskuryakov.
+
+        Make line breaking obey the -webkit-locale property
+        https://bugs.webkit.org/show_bug.cgi?id=63209
+
+        Test: platform/mac/fast/text/line-break-locale.html
+
+        * platform/text/TextBreakIterator.h:
+        (WebCore::LazyLineBreakIterator::LazyLineBreakIterator): Take an optional locale identifier and
+        initialize the m_locale member.
+        (WebCore::LazyLineBreakIterator::get): Pass the locale to acquireLineBreakIterator().
+        (WebCore::LazyLineBreakIterator::reset): Pass the locale to releaseLineBreakIterator() and update
+        the m_locale member.
+        * platform/text/TextBreakIteratorICU.cpp:
+        (WebCore::LineBreakIteratorPool::sharedPool): Return a shared instance.
+        (WebCore::LineBreakIteratorPool::take): Returns a text iterator for the given locale, either a newly-
+        created one, or an existing one from the pool.
+        (WebCore::LineBreakIteratorPool::put): Puts an iterator back into the pool, removing the least-recently used
+        one if needed.
+        (WebCore::LineBreakIteratorPool::LineBreakIteratorPool):
+        (WebCore::acquireLineBreakIterator): Changed to take an optional local identifier, and to use the pool.
+        (WebCore::releaseLineBreakIterator): Changed to use the pool.
+        * platform/text/brew/TextBreakIteratorBrew.cpp:
+        (WebCore::acquireLineBreakIterator): Updated for new parameter.
+        * platform/text/gtk/TextBreakIteratorGtk.cpp:
+        (WebCore::acquireLineBreakIterator): Ditto.
+        * platform/text/qt/TextBreakIteratorQt.cpp:
+        (WebCore::acquireLineBreakIterator): Ditto.
+        * platform/text/wince/TextBreakIteratorWinCE.cpp:
+        (WebCore::acquireLineBreakIterator): Ditto.
+        * rendering/RenderBlockLineLayout.cpp:
+        (WebCore::RenderBlock::LineBreaker::nextLineBreak): Use the locale from the style for the line break
+        iterator.
+        * rendering/RenderText.cpp:
+        (WebCore::RenderText::computePreferredLogicalWidths): Ditto.
+
 2011-06-23  Chris Fleizach  <cfleizach@apple.com>
 
         Reviewed by Darin Adler.
index e4cba7733d99c69a003451ecea07acf1cf3df1ce..521ba8654ca98d5b46023eaaaa922a3c366e10fa 100644 (file)
@@ -22,6 +22,7 @@
 #ifndef TextBreakIterator_h
 #define TextBreakIterator_h
 
+#include <wtf/text/AtomicString.h>
 #include <wtf/unicode/Unicode.h>
 
 namespace WebCore {
@@ -43,7 +44,7 @@ namespace WebCore {
     TextBreakIterator* cursorMovementIterator(const UChar*, int length);
 
     TextBreakIterator* wordBreakIterator(const UChar*, int length);
-    TextBreakIterator* acquireLineBreakIterator(const UChar*, int length);
+    TextBreakIterator* acquireLineBreakIterator(const UChar*, int length, const AtomicString& locale);
     void releaseLineBreakIterator(TextBreakIterator*);
     TextBreakIterator* sentenceBreakIterator(const UChar*, int length);
 
@@ -60,9 +61,10 @@ namespace WebCore {
 
 class LazyLineBreakIterator {
 public:
-    LazyLineBreakIterator(const UChar* string = 0, int length = 0)
+    LazyLineBreakIterator(const UChar* string = 0, int length = 0, const AtomicString& locale = AtomicString())
         : m_string(string)
         , m_length(length)
+        , m_locale(locale)
         , m_iterator(0)
     {
     }
@@ -79,23 +81,25 @@ public:
     TextBreakIterator* get()
     {
         if (!m_iterator)
-            m_iterator = acquireLineBreakIterator(m_string, m_length);
+            m_iterator = acquireLineBreakIterator(m_string, m_length, m_locale);
         return m_iterator;
     }
 
-    void reset(const UChar* string, int length)
+    void reset(const UChar* string, int length, const AtomicString& locale)
     {
         if (m_iterator)
             releaseLineBreakIterator(m_iterator);
 
         m_string = string;
         m_length = length;
+        m_locale = locale;
         m_iterator = 0;
     }
 
 private:
     const UChar* m_string;
     int m_length;
+    AtomicString m_locale;
     TextBreakIterator* m_iterator;
 };
 
index 56aa118ab1ad54a038ec8258b77331e8d325ca0f..2950727adf491b182a66793ea66291c786e54c53 100644 (file)
@@ -26,6 +26,8 @@
 #include "TextBreakIteratorInternalICU.h"
 #include <unicode/ubrk.h>
 #include <wtf/Assertions.h>
+#include <wtf/HashMap.h>
+#include <wtf/text/CString.h>
 
 using namespace std;
 
@@ -70,34 +72,83 @@ TextBreakIterator* wordBreakIterator(const UChar* string, int length)
         staticWordBreakIterator, UBRK_WORD, string, length);
 }
 
-static bool createdLineBreakIterator = false;
-static TextBreakIterator* staticLineBreakIterator;
+class LineBreakIteratorPool {
+WTF_MAKE_NONCOPYABLE(LineBreakIteratorPool);
+public:
+    static LineBreakIteratorPool& sharedPool()
+    {
+        ASSERT(isMainThread());
+        DEFINE_STATIC_LOCAL(LineBreakIteratorPool, pool, ());
+        return pool;
+    }
 
-TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length)
-{
-    TextBreakIterator* lineBreakIterator = 0;
-    if (!createdLineBreakIterator || staticLineBreakIterator) {
-        setUpIterator(createdLineBreakIterator, staticLineBreakIterator, UBRK_LINE, string, length);
-        swap(staticLineBreakIterator, lineBreakIterator);
+    UBreakIterator* take(const AtomicString& locale)
+    {
+        UBreakIterator* iterator = 0;
+        for (size_t i = 0; i < m_pool.size(); ++i) {
+            if (m_pool[i].first == locale) {
+                iterator = m_pool[i].second;
+                m_pool.remove(i);
+                break;
+            }
+        }
+
+        if (!iterator) {
+            UErrorCode openStatus = U_ZERO_ERROR;
+            iterator = ubrk_open(UBRK_LINE, locale.isEmpty() ? currentTextBreakLocaleID() : locale.string().utf8().data(), 0, 0, &openStatus);
+            if (U_FAILURE(openStatus)) {
+                LOG_ERROR("ubrk_open failed with status %d", openStatus);
+                return 0;
+            }
+        }
+
+        ASSERT(!m_vendedIterators.contains(iterator));
+        m_vendedIterators.set(iterator, locale);
+        return iterator;
+    }
+
+    void put(UBreakIterator* iterator)
+    {
+        ASSERT_ARG(iterator, m_vendedIterators.contains(iterator));
+
+        if (m_pool.size() == capacity) {
+            ubrk_close(m_pool[0].second);
+            m_pool.remove(0);
+        }
+
+        m_pool.append(Entry(m_vendedIterators.take(iterator), iterator));
     }
 
-    if (!lineBreakIterator) {
-        bool createdNewLineBreakIterator = false;
-        setUpIterator(createdNewLineBreakIterator, lineBreakIterator, UBRK_LINE, string, length);
+private:
+    LineBreakIteratorPool() { }
+
+    static const size_t capacity = 4;
+
+    typedef pair<AtomicString, UBreakIterator*> Entry;
+    typedef Vector<Entry, capacity> Pool;
+    Pool m_pool;
+    HashMap<UBreakIterator*, AtomicString> m_vendedIterators;
+};
+
+TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length, const AtomicString& locale)
+{
+    UBreakIterator* iterator = LineBreakIteratorPool::sharedPool().take(locale);
+
+    UErrorCode setTextStatus = U_ZERO_ERROR;
+    ubrk_setText(iterator, string, length, &setTextStatus);
+    if (U_FAILURE(setTextStatus)) {
+        LOG_ERROR("ubrk_setText failed with status %d", setTextStatus);
+        return 0;
     }
 
-    return lineBreakIterator;
+    return reinterpret_cast<TextBreakIterator*>(iterator);
 }
 
 void releaseLineBreakIterator(TextBreakIterator* iterator)
 {
-    ASSERT(createdLineBreakIterator);
-    ASSERT(iterator);
+    ASSERT_ARG(iterator, iterator);
 
-    if (!staticLineBreakIterator)
-        staticLineBreakIterator = iterator;
-    else
-        ubrk_close(reinterpret_cast<UBreakIterator*>(iterator));
+    LineBreakIteratorPool::sharedPool().put(reinterpret_cast<UBreakIterator*>(iterator));
 }
 
 TextBreakIterator* sentenceBreakIterator(const UChar* string, int length)
index 3bc1c8ab5e8cd9fd7e885a5c92f3aac923cb3ddd..9a76efc6881555b02b6f39a5788483677f684b2e 100644 (file)
@@ -263,7 +263,7 @@ TextBreakIterator* characterBreakIterator(const UChar* string, int length)
 
 static TextBreakIterator* staticLineBreakIterator;
 
-TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length)
+TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length, const AtomicString&)
 {
     TextBreakIterator* lineBreakIterator = 0;
     if (staticLineBreakIterator) {
index 8f289f3f0e790747ff4c37ce927504b60611ee7c..e067962c2d430f86e037e7759f15cb2fa245ae2a 100644 (file)
@@ -242,7 +242,7 @@ TextBreakIterator* wordBreakIterator(const UChar* string, int length)
 static bool createdLineBreakIterator = false;
 static TextBreakIterator* staticLineBreakIterator;
 
-TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length)
+TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length, const AtomicString&)
 {
     TextBreakIterator* lineBreakIterator = 0;
     if (!createdLineBreakIterator || staticLineBreakIterator) {
index 47f3e818bc64f5cc12cb32da068c258837073487..653ede39ab0a5a54fb57bf09849bf742480cbc0b 100644 (file)
@@ -79,7 +79,7 @@ namespace WebCore {
 
     static TextBreakIterator* staticLineBreakIterator;
 
-    TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length)
+    TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length, const AtomicString&)
     {
         TextBreakIterator* lineBreakIterator = 0;
         if (staticLineBreakIterator) {
index a4d2dbee50e97a6c21adde65c6f142a0d801fd80..7927d77690ceb2cf05a40e7e9ee07be2962335bb 100644 (file)
@@ -244,7 +244,7 @@ TextBreakIterator* characterBreakIterator(const UChar* string, int length)
 
 static TextBreakIterator* staticLineBreakIterator;
 
-TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length)
+TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length, const AtomicString&)
 {
     TextBreakIterator* lineBreakIterator = 0;
     if (staticLineBreakIterator) {
index 311ba55c1f95b7400403d8169b779e42f72c5782..38e53f9f8a76c6a1618314e2d779a770a0a0253d 100644 (file)
@@ -2110,7 +2110,7 @@ InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resol
 
                 if (lineBreakIteratorInfo.first != t) {
                     lineBreakIteratorInfo.first = t;
-                    lineBreakIteratorInfo.second.reset(t->characters(), t->textLength());
+                    lineBreakIteratorInfo.second.reset(t->characters(), t->textLength(), style->locale());
                 }
 
                 bool betweenWords = c == '\n' || (currWS != PRE && !atStart && isBreakable(lineBreakIteratorInfo.second, current.m_pos, current.m_nextBreakablePosition, breakNBSP)
index b92fd6937c4c38ef7beca70c8829bdcac4acb724..e2cba7b4cb22280b2b0f046fe86ba3933295fe93 100644 (file)
@@ -782,7 +782,7 @@ void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
     float wordSpacing = style()->wordSpacing();
     int len = textLength();
     const UChar* txt = characters();
-    LazyLineBreakIterator breakIterator(txt, len);
+    LazyLineBreakIterator breakIterator(txt, len, style()->locale());
     bool needsWordSpacing = false;
     bool ignoringSpaces = false;
     bool isSpace = false;