From d92356ce28b09c4309350a64f7364eb257ad0a9f Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 12 May 2015 18:01:49 +0300 Subject: [PATCH] improved emoji text replaces --- Telegram/SourceFiles/boxes/emojibox.cpp | 16 ++++++++- Telegram/SourceFiles/gui/emoji_config.h | 42 ++++++++++++++++++++--- Telegram/SourceFiles/gui/flattextarea.cpp | 2 +- Telegram/SourceFiles/gui/text.cpp | 29 +++------------- Telegram/SourceFiles/gui/text.h | 2 -- Telegram/SourceFiles/history.cpp | 2 +- 6 files changed, 59 insertions(+), 34 deletions(-) diff --git a/Telegram/SourceFiles/boxes/emojibox.cpp b/Telegram/SourceFiles/boxes/emojibox.cpp index c38fe9068..747c4b135 100644 --- a/Telegram/SourceFiles/boxes/emojibox.cpp +++ b/Telegram/SourceFiles/boxes/emojibox.cpp @@ -84,7 +84,21 @@ void EmojiBox::fillBlocks() { BlockRow currentRow; currentRow.reserve(replacesInRow); for (uint32 i = 0; i < replacesCount; ++i) { - Block block(emojiGet(replaces[i].code), QString::fromUtf8(replaces[i].replace)); + EmojiPtr emoji = emojiGet(replaces[i].code); + if (!emoji || emoji == TwoSymbolEmoji) continue; + if (emoji->color) { + EmojiColorVariants::const_iterator it = cEmojiVariants().constFind(emoji->code); + if (it != cEmojiVariants().cend()) { + EmojiPtr replace = emojiFromKey(it.value()); + if (replace) { + if (replace != TwoSymbolEmoji && replace->code == emoji->code && replace->code2 == emoji->code2) { + emoji = replace; + } + } + } + } + + Block block(emoji, QString::fromUtf8(replaces[i].replace)); currentRow.push_back(block); if (uint32(currentRow.size()) == replacesInRow) { _blocks.push_back(currentRow); diff --git a/Telegram/SourceFiles/gui/emoji_config.h b/Telegram/SourceFiles/gui/emoji_config.h index 958c89886..7d8ec88ca 100644 --- a/Telegram/SourceFiles/gui/emoji_config.h +++ b/Telegram/SourceFiles/gui/emoji_config.h @@ -26,6 +26,31 @@ EmojiPtr emojiGet(EmojiPtr emoji, uint32 color); EmojiPtr emojiGet(const QChar *from, const QChar *end); QString emojiGetSequence(int index); +inline QString emojiString(EmojiPtr emoji) { + if ((emoji->code & 0xFFFF0000U) == 0xFFFF0000U) { // sequence + return emojiGetSequence(emoji->code & 0xFFFFU); + } + + QString result; + result.reserve(emoji->len + (emoji->postfix ? 1 : 0)); + if (!(emoji->code >> 16)) { + result.append(QChar(emoji->code & 0xFFFF)); + } else { + result.append(QChar((emoji->code >> 16) & 0xFFFF)); + result.append(QChar(emoji->code & 0xFFFF)); + if (emoji->code2) { + result.append(QChar((emoji->code2 >> 16) & 0xFFFF)); + result.append(QChar(emoji->code2 & 0xFFFF)); + } + } + if (emoji->color && ((emoji->color & 0xFFFF0000U) != 0xFFFF0000U)) { + result.append(QChar((emoji->color >> 16) & 0xFFFF)); + result.append(QChar(emoji->color & 0xFFFF)); + } + if (emoji->postfix) result.append(QChar(emoji->postfix)); + return result; +} + inline uint64 emojiKey(EmojiPtr emoji) { uint64 key = emoji->code; if (emoji->code2) { @@ -138,7 +163,8 @@ inline QString replaceEmojis(const QString &text) { while (currentLink < lnkCount && ch >= lnkRanges[currentLink].from + lnkRanges[currentLink].len) { ++currentLink; } - if (emojiCode && + EmojiPtr emoji = emojiCode ? emojiGet(emojiCode) : 0; + if (emoji && emoji != TwoSymbolEmoji && (ch == emojiStart || !ch->isLetterOrNumber() || !(ch - 1)->isLetterOrNumber()) && (newEmojiEnd == e || !newEmojiEnd->isLetterOrNumber() || newEmojiEnd == emojiStart || !(newEmojiEnd - 1)->isLetterOrNumber()) && (currentLink >= lnkCount || (ch < lnkRanges[currentLink].from && newEmojiEnd <= lnkRanges[currentLink].from) || (ch >= lnkRanges[currentLink].from + lnkRanges[currentLink].len && newEmojiEnd > lnkRanges[currentLink].from + lnkRanges[currentLink].len)) @@ -148,10 +174,18 @@ inline QString replaceEmojis(const QString &text) { if (ch > emojiEnd + (consumePrevious ? 1 : 0)) { result.append(emojiEnd, ch - emojiEnd - (consumePrevious ? 1 : 0)); } - if (emojiCode > 65535) { - result.append(QChar((emojiCode >> 16) & 0xFFFF)); + if (emoji->color) { + EmojiColorVariants::const_iterator it = cEmojiVariants().constFind(emoji->code); + if (it != cEmojiVariants().cend()) { + EmojiPtr replace = emojiFromKey(it.value()); + if (replace) { + if (replace != TwoSymbolEmoji && replace->code == emoji->code && replace->code2 == emoji->code2) { + emoji = replace; + } + } + } } - result.append(QChar(emojiCode & 0xFFFF)); + result.append(emojiString(emoji)); ch = emojiEnd = newEmojiEnd; canFindEmoji = true; diff --git a/Telegram/SourceFiles/gui/flattextarea.cpp b/Telegram/SourceFiles/gui/flattextarea.cpp index 03c6f98b0..7ddb227f1 100644 --- a/Telegram/SourceFiles/gui/flattextarea.cpp +++ b/Telegram/SourceFiles/gui/flattextarea.cpp @@ -373,7 +373,7 @@ QString FlatTextarea::getText(int32 start, int32 end) const { QString imageName = static_cast(&f)->name(); if (imageName.startsWith(QLatin1String("emoji://e."))) { if (EmojiPtr emoji = emojiFromUrl(imageName)) { - emojiText = textEmojiString(emoji); + emojiText = emojiString(emoji); } } } diff --git a/Telegram/SourceFiles/gui/text.cpp b/Telegram/SourceFiles/gui/text.cpp index a53aa098e..41229b795 100644 --- a/Telegram/SourceFiles/gui/text.cpp +++ b/Telegram/SourceFiles/gui/text.cpp @@ -239,31 +239,6 @@ const QChar *textSkipCommand(const QChar *from, const QChar *end, bool canLink) return (result < end && *result == TextCommand) ? (result + 1) : from; } -QString textEmojiString(EmojiPtr emoji) { - if ((emoji->code & 0xFFFF0000U) == 0xFFFF0000U) { // sequence - return emojiGetSequence(emoji->code & 0xFFFFU); - } - - QString result; - result.reserve(emoji->len + (emoji->postfix ? 1 : 0)); - if (!(emoji->code >> 16)) { - result.append(QChar(emoji->code & 0xFFFF)); - } else { - result.append(QChar((emoji->code >> 16) & 0xFFFF)); - result.append(QChar(emoji->code & 0xFFFF)); - if (emoji->code2) { - result.append(QChar((emoji->code2 >> 16) & 0xFFFF)); - result.append(QChar(emoji->code2 & 0xFFFF)); - } - } - if (emoji->color && ((emoji->color & 0xFFFF0000U) != 0xFFFF0000U)) { - result.append(QChar((emoji->color >> 16) & 0xFFFF)); - result.append(QChar(emoji->color & 0xFFFF)); - } - if (emoji->postfix) result.append(QChar(emoji->postfix)); - return result; -} - class TextParser { public: @@ -527,6 +502,10 @@ public: for (int l = len - skipped - 1; l > 0; --l) { _t->_text.push_back(*++ptr); } + if (e->postfix && _t->_text.at(_t->_text.size() - 1).unicode() != e->postfix) { + _t->_text.push_back(e->postfix); + ++len; + } createBlock(-len); emoji = e; diff --git a/Telegram/SourceFiles/gui/text.h b/Telegram/SourceFiles/gui/text.h index ea50274e8..5d72eaf24 100644 --- a/Telegram/SourceFiles/gui/text.h +++ b/Telegram/SourceFiles/gui/text.h @@ -534,8 +534,6 @@ QString textcmdStartColor(const style::color &color); QString textcmdStopColor(); const QChar *textSkipCommand(const QChar *from, const QChar *end, bool canLink = true); -QString textEmojiString(EmojiPtr emoji); - inline bool chIsSpace(QChar ch, bool rich = false) { return ch.isSpace() || (ch < 32 && !(rich && ch == TextCommand)) || (ch == QChar::ParagraphSeparator) || (ch == QChar::LineSeparator) || (ch == QChar::ObjectReplacementCharacter) || (ch == QChar::SoftHyphen) || (ch == QChar::CarriageReturn) || (ch == QChar::Tabulation); } diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index a380be984..9d31b53aa 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -2900,7 +2900,7 @@ bool HistorySticker::updateStickerEmoji() { } const EmojiStickersMap &stickers(cEmojiStickers()); EmojiStickersMap::const_iterator i = stickers.constFind(data); - QString emoji = (i == stickers.cend()) ? QString() : textEmojiString(i.value()); + QString emoji = (i == stickers.cend()) ? QString() : emojiString(i.value()); if (emoji != _emoji) { _emoji = emoji; return true;