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
+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.
--- /dev/null
+<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>
--- /dev/null
+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}"
+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.
#ifndef TextBreakIterator_h
#define TextBreakIterator_h
+#include <wtf/text/AtomicString.h>
#include <wtf/unicode/Unicode.h>
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);
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)
{
}
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;
};
#include "TextBreakIteratorInternalICU.h"
#include <unicode/ubrk.h>
#include <wtf/Assertions.h>
+#include <wtf/HashMap.h>
+#include <wtf/text/CString.h>
using namespace std;
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)
static TextBreakIterator* staticLineBreakIterator;
-TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length)
+TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length, const AtomicString&)
{
TextBreakIterator* lineBreakIterator = 0;
if (staticLineBreakIterator) {
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) {
static TextBreakIterator* staticLineBreakIterator;
- TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length)
+ TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length, const AtomicString&)
{
TextBreakIterator* lineBreakIterator = 0;
if (staticLineBreakIterator) {
static TextBreakIterator* staticLineBreakIterator;
-TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length)
+TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length, const AtomicString&)
{
TextBreakIterator* lineBreakIterator = 0;
if (staticLineBreakIterator) {
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)
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;