diff options
Diffstat (limited to 'Source/WebCore/platform/text')
-rw-r--r-- | Source/WebCore/platform/text/BidiContext.cpp | 50 | ||||
-rw-r--r-- | Source/WebCore/platform/text/BidiContext.h | 25 | ||||
-rw-r--r-- | Source/WebCore/platform/text/BidiResolver.h | 375 | ||||
-rw-r--r-- | Source/WebCore/platform/text/LocalizedNumber.h | 4 | ||||
-rw-r--r-- | Source/WebCore/platform/text/LocalizedNumberICU.cpp | 4 | ||||
-rw-r--r-- | Source/WebCore/platform/text/LocalizedNumberNone.cpp | 2 | ||||
-rw-r--r-- | Source/WebCore/platform/text/TextCheckerClient.h | 4 | ||||
-rw-r--r-- | Source/WebCore/platform/text/TextChecking.h | 47 | ||||
-rw-r--r-- | Source/WebCore/platform/text/TextCodec.h | 2 | ||||
-rw-r--r-- | Source/WebCore/platform/text/TextCodecICU.cpp | 7 | ||||
-rw-r--r-- | Source/WebCore/platform/text/TextEncodingRegistry.cpp | 2 | ||||
-rw-r--r-- | Source/WebCore/platform/text/TextOrientation.h | 35 | ||||
-rw-r--r-- | Source/WebCore/platform/text/mac/LocalizedNumberMac.mm | 6 | ||||
-rw-r--r-- | Source/WebCore/platform/text/qt/TextBreakIteratorQt.cpp | 3 |
14 files changed, 360 insertions, 206 deletions
diff --git a/Source/WebCore/platform/text/BidiContext.cpp b/Source/WebCore/platform/text/BidiContext.cpp index fb6b8cf..f507514 100644 --- a/Source/WebCore/platform/text/BidiContext.cpp +++ b/Source/WebCore/platform/text/BidiContext.cpp @@ -21,48 +21,80 @@ #include "config.h" #include "BidiContext.h" +#include <wtf/Vector.h> namespace WebCore { using namespace WTF::Unicode; -inline PassRefPtr<BidiContext> BidiContext::createUncached(unsigned char level, Direction direction, bool override, BidiContext* parent) +inline PassRefPtr<BidiContext> BidiContext::createUncached(unsigned char level, Direction direction, bool override, BidiEmbeddingSource source, BidiContext* parent) { - return adoptRef(new BidiContext(level, direction, override, parent)); + return adoptRef(new BidiContext(level, direction, override, source, parent)); } -PassRefPtr<BidiContext> BidiContext::create(unsigned char level, Direction direction, bool override, BidiContext* parent) +PassRefPtr<BidiContext> BidiContext::create(unsigned char level, Direction direction, bool override, BidiEmbeddingSource source, BidiContext* parent) { ASSERT(direction == (level % 2 ? RightToLeft : LeftToRight)); if (parent) - return createUncached(level, direction, override, parent); + return createUncached(level, direction, override, source, parent); ASSERT(level <= 1); if (!level) { if (!override) { - static BidiContext* ltrContext = createUncached(0, LeftToRight, false, 0).releaseRef(); + static BidiContext* ltrContext = createUncached(0, LeftToRight, false, FromStyleOrDOM, 0).releaseRef(); return ltrContext; } - static BidiContext* ltrOverrideContext = createUncached(0, LeftToRight, true, 0).releaseRef(); + static BidiContext* ltrOverrideContext = createUncached(0, LeftToRight, true, FromStyleOrDOM, 0).releaseRef(); return ltrOverrideContext; } if (!override) { - static BidiContext* rtlContext = createUncached(1, RightToLeft, false, 0).releaseRef(); + static BidiContext* rtlContext = createUncached(1, RightToLeft, false, FromStyleOrDOM, 0).releaseRef(); return rtlContext; } - static BidiContext* rtlOverrideContext = createUncached(1, RightToLeft, true, 0).releaseRef(); + static BidiContext* rtlOverrideContext = createUncached(1, RightToLeft, true, FromStyleOrDOM, 0).releaseRef(); return rtlOverrideContext; } +static inline PassRefPtr<BidiContext> copyContextAndRebaselineLevel(BidiContext* context, BidiContext* parent) +{ + ASSERT(context); + unsigned char newLevel = parent ? parent->level() : 0; + if (context->dir() == RightToLeft) + newLevel = nextGreaterOddLevel(newLevel); + else if (parent) + newLevel = nextGreaterEvenLevel(newLevel); + + return BidiContext::create(newLevel, context->dir(), context->override(), context->source(), parent); +} + +// The BidiContext stack must be immutable -- they're re-used for re-layout after +// DOM modification/editing -- so we copy all the non-unicode contexts, and +// recalculate their levels. +PassRefPtr<BidiContext> BidiContext::copyStackRemovingUnicodeEmbeddingContexts() +{ + Vector<BidiContext*, 64> contexts; + for (BidiContext* iter = this; iter; iter = iter->parent()) { + if (iter->source() != FromUnicode) + contexts.append(iter); + } + ASSERT(contexts.size()); + + RefPtr<BidiContext> topContext = copyContextAndRebaselineLevel(contexts.last(), 0); + for (int i = contexts.size() - 1; i > 0; --i) + topContext = copyContextAndRebaselineLevel(contexts[i - 1], topContext.get()); + + return topContext.release(); +} + bool operator==(const BidiContext& c1, const BidiContext& c2) { if (&c1 == &c2) return true; - if (c1.level() != c2.level() || c1.override() != c2.override() || c1.dir() != c2.dir()) + if (c1.level() != c2.level() || c1.override() != c2.override() || c1.dir() != c2.dir() || c1.source() != c2.source()) return false; if (!c1.parent()) return !c2.parent(); diff --git a/Source/WebCore/platform/text/BidiContext.h b/Source/WebCore/platform/text/BidiContext.h index b52815f..9f45d65 100644 --- a/Source/WebCore/platform/text/BidiContext.h +++ b/Source/WebCore/platform/text/BidiContext.h @@ -30,33 +30,52 @@ namespace WebCore { +enum BidiEmbeddingSource { + FromStyleOrDOM, + FromUnicode +}; + // Used to keep track of explicit embeddings. class BidiContext : public RefCounted<BidiContext> { public: - static PassRefPtr<BidiContext> create(unsigned char level, WTF::Unicode::Direction direction, bool override = false, BidiContext* parent = 0); + static PassRefPtr<BidiContext> create(unsigned char level, WTF::Unicode::Direction, bool override = false, BidiEmbeddingSource = FromStyleOrDOM, BidiContext* parent = 0); BidiContext* parent() const { return m_parent.get(); } unsigned char level() const { return m_level; } WTF::Unicode::Direction dir() const { return static_cast<WTF::Unicode::Direction>(m_direction); } bool override() const { return m_override; } + BidiEmbeddingSource source() const { return static_cast<BidiEmbeddingSource>(m_source); } + PassRefPtr<BidiContext> copyStackRemovingUnicodeEmbeddingContexts(); private: - BidiContext(unsigned char level, WTF::Unicode::Direction direction, bool override, BidiContext* parent) + BidiContext(unsigned char level, WTF::Unicode::Direction direction, bool override, BidiEmbeddingSource source, BidiContext* parent) : m_level(level) , m_direction(direction) , m_override(override) + , m_source(source) , m_parent(parent) { } - static PassRefPtr<BidiContext> createUncached(unsigned char level, WTF::Unicode::Direction, bool override, BidiContext* parent); + static PassRefPtr<BidiContext> createUncached(unsigned char level, WTF::Unicode::Direction, bool override, BidiEmbeddingSource, BidiContext* parent); unsigned char m_level; unsigned m_direction : 5; // Direction bool m_override : 1; + unsigned m_source : 1; // BidiEmbeddingSource RefPtr<BidiContext> m_parent; }; +inline unsigned char nextGreaterOddLevel(unsigned char level) +{ + return (level + 1) | 1; +} + +inline unsigned char nextGreaterEvenLevel(unsigned char level) +{ + return (level + 2) & ~1; +} + bool operator==(const BidiContext&, const BidiContext&); } // namespace WebCore diff --git a/Source/WebCore/platform/text/BidiResolver.h b/Source/WebCore/platform/text/BidiResolver.h index 07e9274..5b92ee2 100644 --- a/Source/WebCore/platform/text/BidiResolver.h +++ b/Source/WebCore/platform/text/BidiResolver.h @@ -75,6 +75,21 @@ struct BidiStatus { RefPtr<BidiContext> context; }; +class BidiEmbedding { +public: + BidiEmbedding(WTF::Unicode::Direction direction, BidiEmbeddingSource source) + : m_direction(direction) + , m_source(source) + { + } + + WTF::Unicode::Direction direction() const { return m_direction; } + BidiEmbeddingSource source() const { return m_source; } +private: + WTF::Unicode::Direction m_direction; + BidiEmbeddingSource m_source; +}; + inline bool operator==(const BidiStatus& status1, const BidiStatus& status2) { return status1.eor == status2.eor && status1.last == status2.last && status1.lastStrong == status2.lastStrong && *(status1.context) == *(status2.context); @@ -134,10 +149,10 @@ enum VisualDirectionOverride { template <class Iterator, class Run> class BidiResolver { WTF_MAKE_NONCOPYABLE(BidiResolver); -public : +public: BidiResolver() : m_direction(WTF::Unicode::OtherNeutral) - , reachedEndOfLine(false) + , m_reachedEndOfLine(false) , emptyRun(true) , m_firstRun(0) , m_lastRun(0) @@ -146,10 +161,10 @@ public : { } - const Iterator& position() const { return current; } - void setPosition(const Iterator& position) { current = position; } + const Iterator& position() const { return m_current; } + void setPosition(const Iterator& position) { m_current = position; } - void increment() { current.increment(); } + void increment() { m_current.increment(); } BidiContext* context() const { return m_status.context.get(); } void setContext(PassRefPtr<BidiContext> c) { m_status.context = c; } @@ -166,7 +181,7 @@ public : MidpointState<Iterator>& midpointState() { return m_midpointState; } - void embed(WTF::Unicode::Direction); + void embed(WTF::Unicode::Direction, BidiEmbeddingSource); bool commitExplicitEmbedding(); void createBidiRunsForLine(const Iterator& end, VisualDirectionOverride = NoVisualOverride, bool hardLineBreak = false); @@ -188,14 +203,16 @@ protected: void appendRun(); void reverseRuns(unsigned start, unsigned end); - Iterator current; - Iterator sor; - Iterator eor; - Iterator last; + Iterator m_current; + // sor and eor are "start of run" and "end of run" respectively and correpond + // to abreviations used in UBA spec: http://unicode.org/reports/tr9/#BD7 + Iterator m_sor; + Iterator m_eor; + Iterator m_last; BidiStatus m_status; WTF::Unicode::Direction m_direction; Iterator endOfLine; - bool reachedEndOfLine; + bool m_reachedEndOfLine; Iterator lastBeforeET; bool emptyRun; @@ -210,7 +227,10 @@ private: void lowerExplicitEmbeddingLevel(WTF::Unicode::Direction from); void checkDirectionInLowerRaiseEmbeddingLevel(); - Vector<WTF::Unicode::Direction, 8> m_currentExplicitEmbeddingSequence; + void updateStatusLastFromCurrentDirection(WTF::Unicode::Direction); + void reorderRunsFromLevels(); + + Vector<BidiEmbedding, 8> m_currentExplicitEmbeddingSequence; }; template <class Iterator, class Run> @@ -286,20 +306,20 @@ inline void BidiResolver<Iterator, Run>::moveRunToBeginning(Run* run) template <class Iterator, class Run> void BidiResolver<Iterator, Run>::appendRun() { - if (!emptyRun && !eor.atEnd()) { - unsigned startOffset = sor.offset(); - unsigned endOffset = eor.offset(); + if (!emptyRun && !m_eor.atEnd()) { + unsigned startOffset = m_sor.offset(); + unsigned endOffset = m_eor.offset(); if (!endOfLine.atEnd() && endOffset >= endOfLine.offset()) { - reachedEndOfLine = true; + m_reachedEndOfLine = true; endOffset = endOfLine.offset(); } if (endOffset >= startOffset) addRun(new Run(startOffset, endOffset + 1, context(), m_direction)); - eor.increment(); - sor = eor; + m_eor.increment(); + m_sor = m_eor; } m_direction = WTF::Unicode::OtherNeutral; @@ -307,12 +327,12 @@ void BidiResolver<Iterator, Run>::appendRun() } template <class Iterator, class Run> -void BidiResolver<Iterator, Run>::embed(WTF::Unicode::Direction d) +void BidiResolver<Iterator, Run>::embed(WTF::Unicode::Direction dir, BidiEmbeddingSource source) { using namespace WTF::Unicode; - ASSERT(d == PopDirectionalFormat || d == LeftToRightEmbedding || d == LeftToRightOverride || d == RightToLeftEmbedding || d == RightToLeftOverride); - m_currentExplicitEmbeddingSequence.append(d); + ASSERT(dir == PopDirectionalFormat || dir == LeftToRightEmbedding || dir == LeftToRightOverride || dir == RightToLeftEmbedding || dir == RightToLeftOverride); + m_currentExplicitEmbeddingSequence.append(BidiEmbedding(dir, source)); } template <class Iterator, class Run> @@ -320,7 +340,7 @@ void BidiResolver<Iterator, Run>::checkDirectionInLowerRaiseEmbeddingLevel() { using namespace WTF::Unicode; - ASSERT(m_status.eor != OtherNeutral || eor.atEnd()); + ASSERT(m_status.eor != OtherNeutral || m_eor.atEnd()); ASSERT(m_status.last != NonSpacingMark && m_status.last != BoundaryNeutral && m_status.last != RightToLeftEmbedding @@ -337,7 +357,7 @@ void BidiResolver<Iterator, Run>::lowerExplicitEmbeddingLevel(WTF::Unicode::Dire { using namespace WTF::Unicode; - if (!emptyRun && eor != last) { + if (!emptyRun && m_eor != m_last) { checkDirectionInLowerRaiseEmbeddingLevel(); // bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-bidi.eor run or extend it through bidi.last if (from == LeftToRight) { @@ -358,14 +378,14 @@ void BidiResolver<Iterator, Run>::lowerExplicitEmbeddingLevel(WTF::Unicode::Dire appendRun(); m_direction = RightToLeft; } - eor = last; + m_eor = m_last; } appendRun(); emptyRun = true; // sor for the new run is determined by the higher level (rule X10) setLastDir(from); setLastStrongDir(from); - eor = Iterator(); + m_eor = Iterator(); } template <class Iterator, class Run> @@ -373,7 +393,7 @@ void BidiResolver<Iterator, Run>::raiseExplicitEmbeddingLevel(WTF::Unicode::Dire { using namespace WTF::Unicode; - if (!emptyRun && eor != last) { + if (!emptyRun && m_eor != m_last) { checkDirectionInLowerRaiseEmbeddingLevel(); // bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-bidi.eor run or extend it through bidi.last if (to == LeftToRight) { @@ -396,13 +416,13 @@ void BidiResolver<Iterator, Run>::raiseExplicitEmbeddingLevel(WTF::Unicode::Dire appendRun(); m_direction = RightToLeft; } - eor = last; + m_eor = m_last; } appendRun(); emptyRun = true; setLastDir(to); setLastStrongDir(to); - eor = Iterator(); + m_eor = Iterator(); } template <class Iterator, class Run> @@ -414,25 +434,20 @@ bool BidiResolver<Iterator, Run>::commitExplicitEmbedding() RefPtr<BidiContext> toContext = context(); for (size_t i = 0; i < m_currentExplicitEmbeddingSequence.size(); ++i) { - Direction embedding = m_currentExplicitEmbeddingSequence[i]; - if (embedding == PopDirectionalFormat) { + BidiEmbedding embedding = m_currentExplicitEmbeddingSequence[i]; + if (embedding.direction() == PopDirectionalFormat) { if (BidiContext* parentContext = toContext->parent()) toContext = parentContext; } else { - Direction direction = (embedding == RightToLeftEmbedding || embedding == RightToLeftOverride) ? RightToLeft : LeftToRight; - bool override = embedding == LeftToRightOverride || embedding == RightToLeftOverride; + Direction direction = (embedding.direction() == RightToLeftEmbedding || embedding.direction() == RightToLeftOverride) ? RightToLeft : LeftToRight; + bool override = embedding.direction() == LeftToRightOverride || embedding.direction() == RightToLeftOverride; unsigned char level = toContext->level(); - if (direction == RightToLeft) { - // Go to the least greater odd integer - level += 1; - level |= 1; - } else { - // Go to the least greater even integer - level += 2; - level &= ~1; - } + if (direction == RightToLeft) + level = nextGreaterOddLevel(level); + else + level = nextGreaterEvenLevel(level); if (level < 61) - toContext = BidiContext::create(level, direction, override, toContext.get()); + toContext = BidiContext::create(level, direction, override, embedding.source(), toContext.get()); } } @@ -520,6 +535,85 @@ void BidiResolver<Iterator, Run>::reverseRuns(unsigned start, unsigned end) } template <class Iterator, class Run> +inline void BidiResolver<Iterator, Run>::updateStatusLastFromCurrentDirection(WTF::Unicode::Direction dirCurrent) +{ + using namespace WTF::Unicode; + switch (dirCurrent) { + case EuropeanNumberTerminator: + if (m_status.last != EuropeanNumber) + m_status.last = EuropeanNumberTerminator; + break; + case EuropeanNumberSeparator: + case CommonNumberSeparator: + case SegmentSeparator: + case WhiteSpaceNeutral: + case OtherNeutral: + switch (m_status.last) { + case LeftToRight: + case RightToLeft: + case RightToLeftArabic: + case EuropeanNumber: + case ArabicNumber: + m_status.last = dirCurrent; + break; + default: + m_status.last = OtherNeutral; + } + break; + case NonSpacingMark: + case BoundaryNeutral: + case RightToLeftEmbedding: + case LeftToRightEmbedding: + case RightToLeftOverride: + case LeftToRightOverride: + case PopDirectionalFormat: + // ignore these + break; + case EuropeanNumber: + // fall through + default: + m_status.last = dirCurrent; + } +} + +template <class Iterator, class Run> +inline void BidiResolver<Iterator, Run>::reorderRunsFromLevels() +{ + unsigned char levelLow = 128; + unsigned char levelHigh = 0; + for (Run* run = firstRun(); run; run = run->next()) { + levelHigh = std::max(run->level(), levelHigh); + levelLow = std::min(run->level(), levelLow); + } + + // This implements reordering of the line (L2 according to Bidi spec): + // http://unicode.org/reports/tr9/#L2 + // L2. From the highest level found in the text to the lowest odd level on each line, + // reverse any contiguous sequence of characters that are at that level or higher. + + // Reversing is only done up to the lowest odd level. + if (!(levelLow % 2)) + levelLow++; + + unsigned count = runCount() - 1; + + while (levelHigh >= levelLow) { + unsigned i = 0; + Run* run = firstRun(); + while (i < count) { + for (;i < count && run && run->level() < levelHigh; i++) + run = run->next(); + unsigned start = i; + for (;i <= count && run && run->level() >= levelHigh; i++) + run = run->next(); + unsigned end = i - 1; + reverseRuns(start, end); + } + levelHigh--; + } +} + +template <class Iterator, class Run> void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, VisualDirectionOverride override, bool hardLineBreak) { using namespace WTF::Unicode; @@ -528,10 +622,10 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis if (override != NoVisualOverride) { emptyRun = false; - sor = current; - eor = Iterator(); - while (current != end && !current.atEnd()) { - eor = current; + m_sor = m_current; + m_eor = Iterator(); + while (m_current != end && !m_current.atEnd()) { + m_eor = m_current; increment(); } m_direction = override == VisualLeftToRightOverride ? LeftToRight : RightToLeft; @@ -544,29 +638,34 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis emptyRun = true; - eor = Iterator(); + m_eor = Iterator(); - last = current; + m_last = m_current; bool pastEnd = false; BidiResolver<Iterator, Run> stateAtEnd; while (true) { Direction dirCurrent; - if (pastEnd && (hardLineBreak || current.atEnd())) { + if (pastEnd && (hardLineBreak || m_current.atEnd())) { BidiContext* c = context(); - while (c->parent()) - c = c->parent(); - dirCurrent = c->dir(); if (hardLineBreak) { // A deviation from the Unicode Bidi Algorithm in order to match - // Mac OS X text and WinIE: a hard line break resets bidi state. - stateAtEnd.setContext(c); + // WinIE and user expectations: hard line breaks reset bidi state + // coming from unicode bidi control characters, but not those from + // DOM nodes with specified directionality + stateAtEnd.setContext(c->copyStackRemovingUnicodeEmbeddingContexts()); + + dirCurrent = stateAtEnd.context()->dir(); stateAtEnd.setEorDir(dirCurrent); stateAtEnd.setLastDir(dirCurrent); stateAtEnd.setLastStrongDir(dirCurrent); + } else { + while (c->parent()) + c = c->parent(); + dirCurrent = c->dir(); } } else { - dirCurrent = current.direction(); + dirCurrent = m_current.direction(); if (context()->override() && dirCurrent != RightToLeftEmbedding && dirCurrent != LeftToRightEmbedding @@ -578,7 +677,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis dirCurrent = m_status.last; } - ASSERT(m_status.eor != OtherNeutral || eor.atEnd()); + ASSERT(m_status.eor != OtherNeutral || m_eor.atEnd()); switch (dirCurrent) { // embedding and overrides (X1-X9 in the Bidi specs) @@ -587,7 +686,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis case RightToLeftOverride: case LeftToRightOverride: case PopDirectionalFormat: - embed(dirCurrent); + embed(dirCurrent, FromUnicode); commitExplicitEmbedding(); break; @@ -618,7 +717,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis appendRun(); if (context()->dir() != LeftToRight) { // the neutrals take the embedding direction, which is R - eor = last; + m_eor = m_last; m_direction = RightToLeft; appendRun(); } @@ -629,14 +728,14 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis appendRun(); if (context()->dir() != LeftToRight) { // the neutrals take the embedding direction, which is R - eor = last; + m_eor = m_last; m_direction = RightToLeft; appendRun(); } } else if (m_status.lastStrong != LeftToRight) { //last stuff takes embedding dir if (context()->dir() == RightToLeft) { - eor = last; + m_eor = m_last; m_direction = RightToLeft; } appendRun(); @@ -644,7 +743,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis default: break; } - eor = current; + m_eor = m_current; m_status.eor = LeftToRight; m_status.lastStrong = LeftToRight; m_direction = LeftToRight; @@ -669,19 +768,19 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis case OtherNeutral: if (m_status.eor == EuropeanNumber) { if (m_status.lastStrong == LeftToRight && context()->dir() == LeftToRight) - eor = last; + m_eor = m_last; appendRun(); } else if (m_status.eor == ArabicNumber) appendRun(); else if (m_status.lastStrong == LeftToRight) { if (context()->dir() == LeftToRight) - eor = last; + m_eor = m_last; appendRun(); } default: break; } - eor = current; + m_eor = m_current; m_status.eor = RightToLeft; m_status.lastStrong = dirCurrent; m_direction = RightToLeft; @@ -699,7 +798,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis case RightToLeft: case RightToLeftArabic: case ArabicNumber: - eor = last; + m_eor = m_last; appendRun(); m_direction = EuropeanNumber; break; @@ -719,7 +818,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis // Terminate the EN run. appendRun(); // Make an R run. - eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : last; + m_eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : m_last; m_direction = RightToLeft; appendRun(); // Begin a new EN run. @@ -730,7 +829,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis appendRun(); if (m_status.lastStrong == RightToLeft || context()->dir() == RightToLeft) { // Make an R run. - eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : last; + m_eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : m_last; m_direction = RightToLeft; appendRun(); // Begin a new EN run. @@ -738,7 +837,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis } } else if (m_status.lastStrong == RightToLeft) { // Extend the R run to include the neutrals. - eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : last; + m_eor = m_status.last == EuropeanNumberTerminator ? lastBeforeET : m_last; m_direction = RightToLeft; appendRun(); // Begin a new EN run. @@ -747,7 +846,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis default: break; } - eor = current; + m_eor = m_current; m_status.eor = EuropeanNumber; if (m_direction == OtherNeutral) m_direction = LeftToRight; @@ -765,7 +864,7 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis case RightToLeft: case RightToLeftArabic: case EuropeanNumber: - eor = last; + m_eor = m_last; appendRun(); break; case CommonNumberSeparator: @@ -787,12 +886,12 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis m_direction = RightToLeft; } else if (m_direction == OtherNeutral) m_direction = m_status.lastStrong == LeftToRight ? LeftToRight : RightToLeft; - eor = last; + m_eor = m_last; appendRun(); default: break; } - eor = current; + m_eor = m_current; m_status.eor = ArabicNumber; if (m_direction == OtherNeutral) m_direction = ArabicNumber; @@ -803,16 +902,16 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis case EuropeanNumberTerminator: if (m_status.last == EuropeanNumber) { dirCurrent = EuropeanNumber; - eor = current; + m_eor = m_current; m_status.eor = dirCurrent; } else if (m_status.last != EuropeanNumberTerminator) - lastBeforeET = emptyRun ? eor : last; + lastBeforeET = emptyRun ? m_eor : m_last; break; // boundary neutrals should be ignored case BoundaryNeutral: - if (eor == last) - eor = current; + if (m_eor == m_last) + m_eor = m_current; break; // neutrals case BlockSeparator: @@ -829,9 +928,9 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis break; } - if (pastEnd && eor == current) { - if (!reachedEndOfLine) { - eor = endOfLine; + if (pastEnd && m_eor == m_current) { + if (!m_reachedEndOfLine) { + m_eor = endOfLine; switch (m_status.eor) { case LeftToRight: case RightToLeft: @@ -846,60 +945,23 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis } appendRun(); } - current = end; + m_current = end; m_status = stateAtEnd.m_status; - sor = stateAtEnd.sor; - eor = stateAtEnd.eor; - last = stateAtEnd.last; - reachedEndOfLine = stateAtEnd.reachedEndOfLine; + m_sor = stateAtEnd.m_sor; + m_eor = stateAtEnd.m_eor; + m_last = stateAtEnd.m_last; + m_reachedEndOfLine = stateAtEnd.m_reachedEndOfLine; lastBeforeET = stateAtEnd.lastBeforeET; emptyRun = stateAtEnd.emptyRun; m_direction = OtherNeutral; break; } - // set m_status.last as needed. - switch (dirCurrent) { - case EuropeanNumberTerminator: - if (m_status.last != EuropeanNumber) - m_status.last = EuropeanNumberTerminator; - break; - case EuropeanNumberSeparator: - case CommonNumberSeparator: - case SegmentSeparator: - case WhiteSpaceNeutral: - case OtherNeutral: - switch(m_status.last) { - case LeftToRight: - case RightToLeft: - case RightToLeftArabic: - case EuropeanNumber: - case ArabicNumber: - m_status.last = dirCurrent; - break; - default: - m_status.last = OtherNeutral; - } - break; - case NonSpacingMark: - case BoundaryNeutral: - case RightToLeftEmbedding: - case LeftToRightEmbedding: - case RightToLeftOverride: - case LeftToRightOverride: - case PopDirectionalFormat: - // ignore these - break; - case EuropeanNumber: - // fall through - default: - m_status.last = dirCurrent; - } - - last = current; + updateStatusLastFromCurrentDirection(dirCurrent); + m_last = m_current; if (emptyRun) { - sor = current; + m_sor = m_current; emptyRun = false; } @@ -907,12 +969,12 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis if (!m_currentExplicitEmbeddingSequence.isEmpty()) { bool committed = commitExplicitEmbedding(); if (committed && pastEnd) { - current = end; + m_current = end; m_status = stateAtEnd.m_status; - sor = stateAtEnd.sor; - eor = stateAtEnd.eor; - last = stateAtEnd.last; - reachedEndOfLine = stateAtEnd.reachedEndOfLine; + m_sor = stateAtEnd.m_sor; + m_eor = stateAtEnd.m_eor; + m_last = stateAtEnd.m_last; + m_reachedEndOfLine = stateAtEnd.m_reachedEndOfLine; lastBeforeET = stateAtEnd.lastBeforeET; emptyRun = stateAtEnd.emptyRun; m_direction = OtherNeutral; @@ -920,64 +982,23 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, Vis } } - if (!pastEnd && (current == end || current.atEnd())) { + if (!pastEnd && (m_current == end || m_current.atEnd())) { if (emptyRun) break; stateAtEnd.m_status = m_status; - stateAtEnd.sor = sor; - stateAtEnd.eor = eor; - stateAtEnd.last = last; - stateAtEnd.reachedEndOfLine = reachedEndOfLine; + stateAtEnd.m_sor = m_sor; + stateAtEnd.m_eor = m_eor; + stateAtEnd.m_last = m_last; + stateAtEnd.m_reachedEndOfLine = m_reachedEndOfLine; stateAtEnd.lastBeforeET = lastBeforeET; stateAtEnd.emptyRun = emptyRun; - endOfLine = last; + endOfLine = m_last; pastEnd = true; } } m_logicallyLastRun = m_lastRun; - - // reorder line according to run structure... - // first find highest and lowest levels - unsigned char levelLow = 128; - unsigned char levelHigh = 0; - Run* r = firstRun(); - while (r) { - if (r->m_level > levelHigh) - levelHigh = r->m_level; - if (r->m_level < levelLow) - levelLow = r->m_level; - r = r->next(); - } - - // implements reordering of the line (L2 according to Bidi spec): - // L2. From the highest level found in the text to the lowest odd level on each line, - // reverse any contiguous sequence of characters that are at that level or higher. - - // reversing is only done up to the lowest odd level - if (!(levelLow % 2)) - levelLow++; - - unsigned count = runCount() - 1; - - while (levelHigh >= levelLow) { - unsigned i = 0; - Run* currRun = firstRun(); - while (i < count) { - while (i < count && currRun && currRun->m_level < levelHigh) { - i++; - currRun = currRun->next(); - } - unsigned start = i; - while (i <= count && currRun && currRun->m_level >= levelHigh) { - i++; - currRun = currRun->next(); - } - unsigned end = i - 1; - reverseRuns(start, end); - } - levelHigh--; - } + reorderRunsFromLevels(); endOfLine = Iterator(); } diff --git a/Source/WebCore/platform/text/LocalizedNumber.h b/Source/WebCore/platform/text/LocalizedNumber.h index d70541f..01d2553 100644 --- a/Source/WebCore/platform/text/LocalizedNumber.h +++ b/Source/WebCore/platform/text/LocalizedNumber.h @@ -47,7 +47,9 @@ double parseLocalizedNumber(const String&); // current locale. If an implementation doesn't support localized // numbers or the input value is NaN or Infinitiy, the function should // return an empty string. -String formatLocalizedNumber(double); +// fractionDigits is the maximum length of the fractional parts of the +// resultant string. +String formatLocalizedNumber(double, unsigned fractionDigits); } // namespace WebCore diff --git a/Source/WebCore/platform/text/LocalizedNumberICU.cpp b/Source/WebCore/platform/text/LocalizedNumberICU.cpp index 189151e..7c4b1cb 100644 --- a/Source/WebCore/platform/text/LocalizedNumberICU.cpp +++ b/Source/WebCore/platform/text/LocalizedNumberICU.cpp @@ -34,6 +34,7 @@ #include <limits> #include <unicode/numfmt.h> #include <unicode/parsepos.h> +#include <wtf/MathExtras.h> #include <wtf/PassOwnPtr.h> using namespace std; @@ -73,12 +74,13 @@ double parseLocalizedNumber(const String& numberString) return U_SUCCESS(status) ? numericResult : numeric_limits<double>::quiet_NaN(); } -String formatLocalizedNumber(double number) +String formatLocalizedNumber(double number, unsigned fractionDigits) { NumberFormat* formatter = numberFormatter(); if (!formatter) return String(); UnicodeString result; + formatter->setMaximumFractionDigits(clampToInteger(fractionDigits)); formatter->format(number, result); return String(result.getBuffer(), result.length()); } diff --git a/Source/WebCore/platform/text/LocalizedNumberNone.cpp b/Source/WebCore/platform/text/LocalizedNumberNone.cpp index 729f2f1..c7a8ed2 100644 --- a/Source/WebCore/platform/text/LocalizedNumberNone.cpp +++ b/Source/WebCore/platform/text/LocalizedNumberNone.cpp @@ -42,7 +42,7 @@ double parseLocalizedNumber(const String&) return numeric_limits<double>::quiet_NaN(); } -String formatLocalizedNumber(double) +String formatLocalizedNumber(double, unsigned) { return String(); } diff --git a/Source/WebCore/platform/text/TextCheckerClient.h b/Source/WebCore/platform/text/TextCheckerClient.h index acaa02c..8abbed4 100644 --- a/Source/WebCore/platform/text/TextCheckerClient.h +++ b/Source/WebCore/platform/text/TextCheckerClient.h @@ -28,6 +28,8 @@ #ifndef TextCheckerClient_h #define TextCheckerClient_h +#include "TextChecking.h" + #include <wtf/Forward.h> #include <wtf/Vector.h> #include <wtf/text/WTFString.h> @@ -70,7 +72,7 @@ public: virtual void checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength) = 0; virtual String getAutoCorrectSuggestionForMisspelledWord(const String& misspelledWord) = 0; virtual void checkGrammarOfString(const UChar*, int length, Vector<GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength) = 0; -#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) +#if USE(UNIFIED_TEXT_CHECKING) virtual void checkTextOfParagraph(const UChar* text, int length, uint64_t checkingTypes, Vector<TextCheckingResult>& results) = 0; #endif diff --git a/Source/WebCore/platform/text/TextChecking.h b/Source/WebCore/platform/text/TextChecking.h new file mode 100644 index 0000000..022fb82 --- /dev/null +++ b/Source/WebCore/platform/text/TextChecking.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TextChecking_h +#define TextChecking_h + +namespace WebCore { + +#if !defined(BUILDING_ON_TIGER) +#define WTF_USE_GRAMMAR_CHECKING 1 +#endif + +#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) +#define WTF_USE_UNIFIED_TEXT_CHECKING 1 +#define WTF_USE_AUTOMATIC_TEXT_REPLACEMENT 1 +#endif + +} + +#endif // TextChecking_h diff --git a/Source/WebCore/platform/text/TextCodec.h b/Source/WebCore/platform/text/TextCodec.h index 35229a3..0c2a38a 100644 --- a/Source/WebCore/platform/text/TextCodec.h +++ b/Source/WebCore/platform/text/TextCodec.h @@ -52,7 +52,7 @@ namespace WebCore { // Encodes the character as en entity as above, but escaped // non-alphanumeric characters. This is used in URLs. // For example, U+6DE would be "%26%231758%3B". - URLEncodedEntitiesForUnencodables, + URLEncodedEntitiesForUnencodables }; typedef char UnencodableReplacementArray[32]; diff --git a/Source/WebCore/platform/text/TextCodecICU.cpp b/Source/WebCore/platform/text/TextCodecICU.cpp index d07b50e..0d99196 100644 --- a/Source/WebCore/platform/text/TextCodecICU.cpp +++ b/Source/WebCore/platform/text/TextCodecICU.cpp @@ -149,13 +149,6 @@ void TextCodecICU::registerEncodingNames(EncodingNameRegistrar registrar) registrar("x-windows-949", "windows-949"); registrar("x-uhc", "windows-949"); registrar("shift-jis", "Shift_JIS"); -#if !USE(BUILTIN_UTF8_CODEC) - registrar("unicode11utf8", "UTF-8"); - registrar("unicode20utf8", "UTF-8"); - registrar("x-unicode20utf8", "UTF-8"); - registrar("utf8", "UTF-8"); - registrar("UTF-8", "UTF-8"); -#endif // These aliases are present in modern versions of ICU, but use different codecs, and have no standard names. // They are not present in ICU 3.2. diff --git a/Source/WebCore/platform/text/TextEncodingRegistry.cpp b/Source/WebCore/platform/text/TextEncodingRegistry.cpp index f604227..d6450b1 100644 --- a/Source/WebCore/platform/text/TextEncodingRegistry.cpp +++ b/Source/WebCore/platform/text/TextEncodingRegistry.cpp @@ -223,10 +223,8 @@ static void buildBaseTextCodecMaps() TextCodecLatin1::registerEncodingNames(addToTextEncodingNameMap); TextCodecLatin1::registerCodecs(addToTextCodecMap); -#if USE(BUILTIN_UTF8_CODEC) TextCodecUTF8::registerEncodingNames(addToTextEncodingNameMap); TextCodecUTF8::registerCodecs(addToTextCodecMap); -#endif TextCodecUTF16::registerEncodingNames(addToTextEncodingNameMap); TextCodecUTF16::registerCodecs(addToTextCodecMap); diff --git a/Source/WebCore/platform/text/TextOrientation.h b/Source/WebCore/platform/text/TextOrientation.h new file mode 100644 index 0000000..e229f1e --- /dev/null +++ b/Source/WebCore/platform/text/TextOrientation.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2011 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TextOrientation_h +#define TextOrientation_h + +namespace WebCore { + +enum TextOrientation { TextOrientationVerticalRight, TextOrientationUpright }; + +} + +#endif diff --git a/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm b/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm index 8cfe200..826f707 100644 --- a/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm +++ b/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm @@ -65,10 +65,12 @@ double parseLocalizedNumber(const String& numberString) return [number doubleValue]; } -String formatLocalizedNumber(double inputNumber) +String formatLocalizedNumber(double inputNumber, unsigned fractionDigits) { RetainPtr<NSNumber> number(AdoptNS, [[NSNumber alloc] initWithDouble:inputNumber]); - return String([numberFormatter() stringFromNumber:number.get()]); + RetainPtr<NSNumberFormatter> formatter = numberFormatter(); + [formatter.get() setMaximumFractionDigits:fractionDigits]; + return String([formatter.get() stringFromNumber:number.get()]); } } // namespace WebCore diff --git a/Source/WebCore/platform/text/qt/TextBreakIteratorQt.cpp b/Source/WebCore/platform/text/qt/TextBreakIteratorQt.cpp index 3fae657..1fe400c 100644 --- a/Source/WebCore/platform/text/qt/TextBreakIteratorQt.cpp +++ b/Source/WebCore/platform/text/qt/TextBreakIteratorQt.cpp @@ -22,6 +22,7 @@ #include "TextBreakIterator.h" #include <QtCore/qtextboundaryfinder.h> +#include <algorithm> #include <qdebug.h> // #define DEBUG_TEXT_ITERATORS @@ -89,7 +90,7 @@ const char* currentTextBreakLocaleID() TextBreakIterator* lineBreakIterator = 0; if (staticLineBreakIterator) { setUpIterator(*staticLineBreakIterator, QTextBoundaryFinder::Line, string, length); - swap(staticLineBreakIterator, lineBreakIterator); + std::swap(staticLineBreakIterator, lineBreakIterator); } if (!lineBreakIterator && string && length) |