diff --git a/intl/unicharutil/util/nsUnicodeProperties.cpp b/intl/unicharutil/util/nsUnicodeProperties.cpp index 562013959a..5b9f5b9058 100644 --- a/intl/unicharutil/util/nsUnicodeProperties.cpp +++ b/intl/unicharutil/util/nsUnicodeProperties.cpp @@ -180,6 +180,8 @@ GetHangulSyllableType(uint32_t aCh) return HSType(u_getIntPropertyValue(aCh, UCHAR_HANGUL_SYLLABLE_TYPE)); } +static const uint32_t kZWJ = 0x200d; + void ClusterIterator::Next() { @@ -233,7 +235,6 @@ ClusterIterator::Next() } } - const uint32_t kZWJ = 0x200d; uint32_t aNextCh = 0; if (mPos + 1 < mLimit) { aNextCh = *mPos; @@ -299,19 +300,55 @@ ClusterReverseIterator::Next() } uint32_t ch; - do { - ch = *--mPos; - if (NS_IS_LOW_SURROGATE(ch) && mPos > mLimit && - NS_IS_HIGH_SURROGATE(*(mPos - 1))) { - ch = SURROGATE_TO_UCS4(*--mPos, ch); + bool nextWasComponent = false; + size_t tRel = 0; + size_t tPos = 0; + size_t chLen = 0; + + do { + tRel++; + ch = *(mPos - tRel); + + if (NS_IS_LOW_SURROGATE(ch) && (mPos - tRel) > mLimit && + NS_IS_HIGH_SURROGATE(*(mPos - (tRel + 1)))) { + tRel++; + ch = SURROGATE_TO_UCS4(*(mPos - tRel), ch); + if (chLen == 0) { + chLen = 2; + } + } else if (chLen == 0) { + chLen = 1; } - // TODO: Full extendCluster support. - if (!(IsClusterExtender(ch) || IsEmojiClusterExtender(ch))) { + bool prevWillBeZwj = false; + bool validEmoji = + (GetEmojiPresentation(ch) == EmojiDefault) || + (GetEmojiPresentation(ch) == EmojiComponent) || + ((GetEmojiPresentation(ch) == TextDefault) && nextWasComponent); + if (validEmoji) { + tPos = tRel; + + uint32_t aPrevCh = *(mPos - (tRel + 1)); + if (NS_IS_LOW_SURROGATE(aPrevCh) && (mPos - (tRel + 1)) > mLimit) { + uint32_t aHighCh = *(mPos - (tRel + 2)); + if (NS_IS_HIGH_SURROGATE(aHighCh)) { + aPrevCh = SURROGATE_TO_UCS4(aHighCh, aPrevCh); + } + } + prevWillBeZwj = (aPrevCh == kZWJ); + } + if (!(IsClusterExtender(ch) || + IsEmojiClusterExtender(ch) || + prevWillBeZwj)) { + if (tPos == 0) { + tPos = chLen; + } break; } - } while (mPos > mLimit); + nextWasComponent = (GetEmojiPresentation(ch) == EmojiComponent); + } while ((mPos - tRel) > mLimit); + mPos -= tPos; // XXX May need to handle conjoining Jamo