From 833a259234505780824396c58e5c69076aae3e0d Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 15 Dec 2022 19:10:51 +0400 Subject: [PATCH] Colorize emoji in text color correctly. --- Telegram/SourceFiles/boxes/peer_list_box.cpp | 1 - .../boxes/peers/edit_forum_topic_box.cpp | 2 +- .../boxes/reactions_settings_box.cpp | 2 +- .../SourceFiles/boxes/sticker_set_box.cpp | 5 +- .../chat_helpers/emoji_list_widget.cpp | 76 +++++++++---------- .../chat_helpers/emoji_list_widget.h | 9 +-- .../chat_helpers/emoji_suggestions_widget.cpp | 13 ++-- .../chat_helpers/stickers_list_footer.cpp | 3 +- Telegram/SourceFiles/data/data_document.cpp | 8 ++ Telegram/SourceFiles/data/data_document.h | 2 + .../SourceFiles/data/data_forum_topic.cpp | 6 +- .../data/stickers/data_custom_emoji.cpp | 41 +++++++--- .../data/stickers/data_custom_emoji.h | 1 + .../dialogs/dialogs_inner_widget.cpp | 5 -- .../SourceFiles/dialogs/ui/dialogs_layout.cpp | 5 -- Telegram/SourceFiles/history/history_item.cpp | 16 ++-- .../history/view/history_view_message.cpp | 5 +- .../view/history_view_sticker_toast.cpp | 2 +- .../view/history_view_top_bar_widget.cpp | 1 - .../view/media/history_view_custom_emoji.cpp | 7 +- .../view/media/history_view_large_emoji.cpp | 7 +- .../view/media/history_view_sticker.cpp | 37 ++++++++- .../view/reactions/history_view_reactions.cpp | 4 +- .../view/reactions/history_view_reactions.h | 2 +- .../reactions/history_view_reactions_list.cpp | 2 +- .../reactions/history_view_reactions_tabs.cpp | 10 +-- .../info/profile/info_profile_badge.cpp | 8 +- .../info/profile/info_profile_badge.h | 1 - .../storage/serialize_document.cpp | 15 +++- .../controls/who_reacted_context_action.cpp | 4 +- .../ui/effects/reaction_fly_animation.cpp | 9 +-- .../ui/effects/reaction_fly_animation.h | 2 - Telegram/SourceFiles/ui/unread_badge.cpp | 7 +- Telegram/SourceFiles/ui/unread_badge.h | 3 - Telegram/lib_ui | 2 +- 35 files changed, 176 insertions(+), 147 deletions(-) diff --git a/Telegram/SourceFiles/boxes/peer_list_box.cpp b/Telegram/SourceFiles/boxes/peer_list_box.cpp index b3db937d8..e6d8613e6 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_box.cpp @@ -735,7 +735,6 @@ int PeerListRow::paintNameIconGetWidth( .premiumFg = &(selected ? st::dialogsVerifiedIconBgOver : st::dialogsVerifiedIconBg), - .preview = st::windowBgOver->c, .customEmojiRepaint = repaint, .now = now, .paused = false, diff --git a/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp index e4052637e..274a55972 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_forum_topic_box.cpp @@ -177,7 +177,7 @@ bool DefaultIconEmoji::readyInDefaultState() { return !paintIconFrame(result); }) | rpl::start_with_next([=](QRect clip) { auto args = Ui::Text::CustomEmoji::Context{ - .preview = st::windowBgOver->c, + .textColor = st::windowFg->c, .now = crl::now(), .paused = controller->isGifPausedAtLeastFor( Window::GifPauseReason::Layer), diff --git a/Telegram/SourceFiles/boxes/reactions_settings_box.cpp b/Telegram/SourceFiles/boxes/reactions_settings_box.cpp index 19b42bb21..e58a1de8e 100644 --- a/Telegram/SourceFiles/boxes/reactions_settings_box.cpp +++ b/Telegram/SourceFiles/boxes/reactions_settings_box.cpp @@ -447,7 +447,7 @@ void AddReactionCustomIcon( const auto ratio = style::DevicePixelRatio(); const auto size = Data::FrameSizeFromTag(tag) / ratio; state->custom->paint(p, { - .preview = st::windowBgRipple->c, + .textColor = st::windowFg->c, .now = crl::now(), .position = QPoint( (widget->width() - size) / 2, diff --git a/Telegram/SourceFiles/boxes/sticker_set_box.cpp b/Telegram/SourceFiles/boxes/sticker_set_box.cpp index fe614f868..ff62368da 100644 --- a/Telegram/SourceFiles/boxes/sticker_set_box.cpp +++ b/Telegram/SourceFiles/boxes/sticker_set_box.cpp @@ -331,7 +331,6 @@ private: std::vector _elements; std::unique_ptr _lottiePlayer; - mutable Ui::Text::CustomEmojiColored _colored; base::flat_map< not_null, std::unique_ptr> _customEmoji; @@ -1335,10 +1334,8 @@ void StickerSetBox::Inner::paintSticker( (_singleSize.height() - size.height()) / 2); auto lottieFrame = QImage(); if (element.emoji) { - _colored.color = st::profileVerifiedCheckBg->c; element.emoji->paint(p, { - .preview = st::windowBgOver->c, - .colored = &_colored, + .textColor = st::windowFg->c, .now = now, .position = ppos, .paused = paused, diff --git a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp index d96cf61eb..eda6bd252 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp @@ -438,9 +438,6 @@ EmojiListWidget::EmojiListWidget( resizeToWidth(width()); }, lifetime()); - if (_mode == Mode::EmojiStatus) { - _emojiStatusColor = std::make_unique(); - } rpl::single( rpl::empty ) | rpl::then( @@ -449,12 +446,6 @@ EmojiListWidget::EmojiListWidget( initButton(_add, tr::lng_stickers_featured_add(tr::now), false); initButton(_unlock, tr::lng_emoji_featured_unlock(tr::now), true); initButton(_restore, tr::lng_emoji_premium_restore(tr::now), true); - if (const auto status = _emojiStatusColor.get()) { - status->color = anim::color( - st::stickerPanPremium1, - st::stickerPanPremium2, - 0.5); - } }, lifetime()); if (!descriptor.customRecentList.empty()) { @@ -842,10 +833,36 @@ void EmojiListWidget::paintEvent(QPaintEvent *e) { paint(p, {}, clip); } +void EmojiListWidget::validateEmojiPaintContext( + const ExpandingContext &context) { + auto value = Ui::Text::CustomEmojiPaintContext{ + .textColor = (_mode == Mode::EmojiStatus + ? anim::color( + st::stickerPanPremium1, + st::stickerPanPremium2, + 0.5) + : st::windowFg->c), + .size = QSize(_customSingleSize, _customSingleSize), + .now = crl::now(), + .scale = context.progress, + .paused = paused(), + .scaled = context.expanding, + }; + if (!_emojiPaintContext) { + _emojiPaintContext = std::make_unique< + Ui::Text::CustomEmojiPaintContext + >(std::move(value)); + } else { + *_emojiPaintContext = std::move(value); + } +} + void EmojiListWidget::paint( QPainter &p, ExpandingContext context, QRect clip) { + validateEmojiPaintContext(context); + auto fromColumn = floorclamp( clip.x() - _rowsLeft, _singleSize.width(), @@ -861,10 +878,7 @@ void EmojiListWidget::paint( fromColumn = _columnCount - fromColumn; toColumn = _columnCount - toColumn; } - const auto expandProgress = context.progress; - const auto paused = this->paused(); - const auto now = crl::now(); auto selectedButton = std::get_if(!v::is_null(_pressed) ? &_pressed : &_selected); @@ -968,12 +982,12 @@ void EmojiListWidget::paint( _overBg.paint(p, QRect(tl, st::emojiPanArea)); } if (info.section == int(Section::Recent)) { - drawRecent(p, context, w, now, paused, index); + drawRecent(p, context, w, index); } else if (info.section < _staticCount) { drawEmoji(p, context, w, _emoji[info.section][index]); } else { const auto set = info.section - _staticCount; - drawCustom(p, context, w, now, paused, set, index); + drawCustom(p, context, w, set, index); } } } @@ -1006,24 +1020,14 @@ void EmojiListWidget::drawRecent( QPainter &p, const ExpandingContext &context, QPoint position, - crl::time now, - bool paused, int index) { _recentPainted = true; auto &recent = _recent[index]; if (const auto custom = recent.custom) { - position += _innerPosition + _customPosition; - const auto paintContext = Ui::Text::CustomEmoji::Context{ - .preview = st::windowBgRipple->c, - .colored = _emojiStatusColor.get(), - .size = QSize(_customSingleSize, _customSingleSize), - .now = now, - .scale = context.progress, - .position = position, - .paused = paused, - .scaled = context.expanding, - }; - custom->paint(p, paintContext); + _emojiPaintContext->position = position + + _innerPosition + + _customPosition; + custom->paint(p, *_emojiPaintContext); } else if (const auto emoji = std::get_if(&recent.id.data)) { if (_mode == Mode::EmojiStatus) { position += QPoint( @@ -1057,24 +1061,16 @@ void EmojiListWidget::drawCustom( QPainter &p, const ExpandingContext &context, QPoint position, - crl::time now, - bool paused, int set, int index) { position += _innerPosition + _customPosition; auto &custom = _custom[set]; custom.painted = true; auto &entry = custom.list[index]; - entry.custom->paint(p, { - .preview = st::windowBgRipple->c, - .colored = _emojiStatusColor.get(), - .size = QSize(_customSingleSize, _customSingleSize), - .now = now, - .scale = context.progress, - .position = position, - .paused = paused, - .scaled = context.expanding, - }); + _emojiPaintContext->position = position + + _innerPosition + + _customPosition; + entry.custom->paint(p, *_emojiPaintContext); } bool EmojiListWidget::checkPickerHide() { diff --git a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h index 5cfbf8a2d..83a4eaa5b 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h @@ -38,7 +38,7 @@ enum class Section; } // namespace Ui::Emoji namespace Ui::Text { -struct CustomEmojiColored; +struct CustomEmojiPaintContext; } // namespace Ui::Text namespace Ui::CustomEmoji { @@ -267,8 +267,6 @@ private: QPainter &p, const ExpandingContext &context, QPoint position, - crl::time now, - bool paused, int index); void drawEmoji( QPainter &p, @@ -279,10 +277,9 @@ private: QPainter &p, const ExpandingContext &context, QPoint position, - crl::time now, - bool paused, int set, int index); + void validateEmojiPaintContext(const ExpandingContext &context); [[nodiscard]] bool hasRemoveButton(int index) const; [[nodiscard]] QRect removeButtonRect(int index) const; [[nodiscard]] QRect removeButtonRect(const SectionInfo &info) const; @@ -345,7 +342,7 @@ private: std::vector _recent; base::flat_set _recentCustomIds; base::flat_set _repaintsScheduled; - std::unique_ptr _emojiStatusColor; + std::unique_ptr _emojiPaintContext; bool _recentPainted = false; bool _grabbingChosen = false; QVector _emoji[kEmojiSectionCount]; diff --git a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp index 42641fbc4..26e40142e 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_suggestions_widget.cpp @@ -341,8 +341,10 @@ void SuggestionsWidget::paintEvent(QPaintEvent *e) { Ui::StickerHoverCorners); } - const auto now = crl::now(); - const auto preview = st::windowBgOver->c; + auto context = Ui::CustomEmoji::Context{ + .textColor = st::windowFg->c, + .now = crl::now(), + }; for (auto i = from; i != till; ++i) { const auto &row = _rows[i]; const auto emoji = row.emoji; @@ -351,11 +353,8 @@ void SuggestionsWidget::paintEvent(QPaintEvent *e) { const auto x = i * _oneWidth + (_oneWidth - size) / 2; const auto y = (_oneWidth - size) / 2; if (row.custom) { - row.custom->paint(p, { - .preview = preview, - .now = now, - .position = { x, y }, - }); + context.position = { x, y }; + row.custom->paint(p, context); } else { Ui::Emoji::Draw(p, emoji, esize, x, y); } diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_footer.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_footer.cpp index 770d52974..7f810ac3b 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_footer.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_footer.cpp @@ -605,6 +605,7 @@ void StickersListFooter::paint( const auto now = crl::now(); const auto paused = _paused(); + p.setPen(st::windowFg); enumerateVisibleIcons([&](const IconInfo &info) { paintSetIcon(p, context, info, now, paused); }); @@ -1251,7 +1252,7 @@ void StickersListFooter::paintSetIcon( const auto y = _iconsTop + (st().footer - icon.pixh) / 2; if (icon.custom) { icon.custom->paint(p, Ui::Text::CustomEmoji::Context{ - .preview = st::windowBgRipple->c, + .textColor = st::windowFg->c, .size = QSize(icon.pixw, icon.pixh), .now = now, .scale = context.progress, diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp index 8676e63f8..b9953da2b 100644 --- a/Telegram/SourceFiles/data/data_document.cpp +++ b/Telegram/SourceFiles/data/data_document.cpp @@ -327,6 +327,7 @@ void DocumentData::setattributes( const QVector &attributes) { _flags &= ~(Flag::ImageType | Flag::HasAttachedStickers + | Flag::UseTextColor | kStreamingSupportedMask); _flags |= kStreamingSupportedUnknown; @@ -375,6 +376,9 @@ void DocumentData::setattributes( } else { _flags |= Flag::PremiumSticker; } + if (data.is_text_color()) { + _flags |= Flag::UseTextColor; + } UpdateStickerSetIdentifier(info->set, data.vstickerset()); } }, [&](const MTPDdocumentAttributeVideo &data) { @@ -555,6 +559,10 @@ bool DocumentData::isPremiumEmoji() const { return info && info->setType == Data::StickersType::Emoji; } +bool DocumentData::emojiUsesTextColor() const { + return (_flags & Flag::UseTextColor); +} + bool DocumentData::hasThumbnail() const { return _thumbnail.location.valid() && !thumbnailFailed() diff --git a/Telegram/SourceFiles/data/data_document.h b/Telegram/SourceFiles/data/data_document.h index b6fcd9477..c66ad024e 100644 --- a/Telegram/SourceFiles/data/data_document.h +++ b/Telegram/SourceFiles/data/data_document.h @@ -181,6 +181,7 @@ public: [[nodiscard]] bool isPatternWallPaperSVG() const; [[nodiscard]] bool isPremiumSticker() const; [[nodiscard]] bool isPremiumEmoji() const; + [[nodiscard]] bool emojiUsesTextColor() const; [[nodiscard]] bool hasThumbnail() const; [[nodiscard]] bool thumbnailLoading() const; @@ -290,6 +291,7 @@ private: ForceToCache = 0x100, PremiumSticker = 0x200, PossibleCoverThumbnail = 0x400, + UseTextColor = 0x800, }; using Flags = base::flags; friend constexpr bool is_flag_type(Flag) { return true; }; diff --git a/Telegram/SourceFiles/data/data_forum_topic.cpp b/Telegram/SourceFiles/data/data_forum_topic.cpp index d8ccd86e8..176d07623 100644 --- a/Telegram/SourceFiles/data/data_forum_topic.cpp +++ b/Telegram/SourceFiles/data/data_forum_topic.cpp @@ -582,7 +582,11 @@ void ForumTopic::paintUserpic( (st->height - size) / 2); } _icon->paint(p, { - .preview = st::windowBgOver->c, + .textColor = (context.active + ? st::dialogsNameFgActive + : context.selected + ? st::dialogsNameFgOver + : st::dialogsNameFg)->c, .now = context.now, .position = position, .paused = context.paused, diff --git a/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp b/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp index c1b047d53..f115937ef 100644 --- a/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp +++ b/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp @@ -447,14 +447,16 @@ std::unique_ptr CustomEmojiManager::create( Ui::CustomEmoji::RepaintRequest request) { repaintLater(instance, request); }; - auto [loader, setId] = factory(); + auto [loader, setId, colored] = factory(); i = instances.emplace( documentId, std::make_unique(Loading{ std::move(loader), prepareNonExactPreview(documentId, tag, sizeOverride) }, std::move(repaint))).first; - if (_coloredSetId) { + if (colored) { + i->second->setColored(); + } else if (_coloredSetId) { if (_coloredSetId == setId) { i->second->setColored(); } @@ -608,6 +610,7 @@ auto CustomEmojiManager::createLoaderWithSetId( return { std::make_unique(document, tag, sizeOverride), sticker->set.id, + document->emojiUsesTextColor(), }; } return createLoaderWithSetId(document->id, tag, sizeOverride); @@ -625,7 +628,11 @@ auto CustomEmojiManager::createLoaderWithSetId( sizeOverride); if (const auto document = result->document()) { if (const auto sticker = document->sticker()) { - return { std::move(result), sticker->set.id }; + return { + std::move(result), + sticker->set.id, + document->emojiUsesTextColor(), + }; } } else { const auto i = SizeIndex(tag); @@ -635,7 +642,7 @@ auto CustomEmojiManager::createLoaderWithSetId( crl::on_main(this, [=] { request(); }); } } - return { std::move(result), uint64() }; + return { std::move(result), uint64(), false }; } QString CustomEmojiManager::lookupSetName(uint64 setId) { @@ -675,17 +682,28 @@ void CustomEmojiManager::request() { void CustomEmojiManager::fillColoredFlags(not_null document) { const auto id = document->id; + const auto setColored = [&] { + for (auto &instances : _instances) { + const auto i = instances.find(id); + if (i != end(instances)) { + i->second->setColored(); + } + } + }; + if (document->emojiUsesTextColor()) { + setColored(); + return; + } const auto sticker = document->sticker(); const auto setId = sticker ? sticker->set.id : uint64(); if (!setId || (_coloredSetId && setId != _coloredSetId)) { return; - } - for (auto &instances : _instances) { - const auto i = instances.find(id); - if (i != end(instances)) { - if (setId == _coloredSetId) { - i->second->setColored(); - } else { + } else if (setId == _coloredSetId) { + setColored(); + } else { + for (auto &instances : _instances) { + const auto i = instances.find(id); + if (i != end(instances)) { _coloredSetPending[setId].emplace(i->second.get()); } } @@ -915,6 +933,7 @@ void InsertCustomEmoji( return; } Ui::InsertCustomEmojiAtCursor( + field, field->textCursor(), sticker->alt, Ui::InputField::CustomEmojiLink(SerializeCustomEmojiId(document))); diff --git a/Telegram/SourceFiles/data/stickers/data_custom_emoji.h b/Telegram/SourceFiles/data/stickers/data_custom_emoji.h index 07c651c3e..15d516671 100644 --- a/Telegram/SourceFiles/data/stickers/data_custom_emoji.h +++ b/Telegram/SourceFiles/data/stickers/data_custom_emoji.h @@ -90,6 +90,7 @@ private: struct LoaderWithSetId { std::unique_ptr loader; uint64 setId = 0; + bool colored = false; }; [[nodiscard]] LoaderWithSetId createLoaderWithSetId( diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 3f498e617..23675eb85 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -1016,11 +1016,6 @@ void InnerWidget::paintPeerSearchResult( : context.selected ? &st::dialogsVerifiedIconBgOver : &st::dialogsVerifiedIconBg), - .preview = (context.active - ? st::dialogsScamFgActive - : context.selected - ? st::windowBgRipple - : st::windowBgOver)->c, .customEmojiRepaint = [=] { updateSearchResult(peer); }, .now = context.now, .paused = context.paused, diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp index 8bb625bf7..9a5fe3a16 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp @@ -656,11 +656,6 @@ void PaintRow( : context.selected ? &st::dialogsVerifiedIconBgOver : &st::dialogsVerifiedIconBg), - .preview = (context.active - ? st::dialogsScamFgActive - : context.selected - ? st::windowBgRipple - : st::windowBgOver)->c, .customEmojiRepaint = customEmojiRepaint, .now = context.now, .paused = context.paused, diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 0894b4423..22abfd5e9 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -2987,12 +2987,12 @@ void HistoryItem::createComponents(const MTPDmessage &data) { config.replyToPeer = 0; } } - const auto id = data.vreply_to_msg_id().v; - config.replyTo = data.is_reply_to_scheduled() - ? _history->owner().scheduledMessages().localMessageId(id) - : id; - config.replyToTop = data.vreply_to_top_id().value_or(id); - config.replyIsTopicPost = data.is_forum_topic(); + const auto id = data.vreply_to_msg_id().v; + config.replyTo = data.is_reply_to_scheduled() + ? _history->owner().scheduledMessages().localMessageId(id) + : id; + config.replyToTop = data.vreply_to_top_id().value_or(id); + config.replyIsTopicPost = data.is_forum_topic(); }); } config.viaBotId = data.vvia_bot_id().value_or_empty(); @@ -3239,7 +3239,9 @@ void HistoryItem::createServiceFromMtp(const MTPDmessageService &message) { if (!updateServiceDependent()) { RequestDependentMessageData( this, - dependent->peerId, + (dependent->peerId + ? dependent->peerId + : _history->peer->id), dependent->msgId); } } diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index c27aeed28..33d58e952 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -289,7 +289,6 @@ struct Message::CommentsButton { struct Message::FromNameStatus { DocumentId id = 0; std::unique_ptr custom; - Ui::Text::CustomEmojiColored colored; int skip = 0; }; @@ -1239,10 +1238,8 @@ void Message::paintFromName( } if (_fromNameStatus->custom) { clearCustomEmojiRepaint(); - _fromNameStatus->colored.color = color; _fromNameStatus->custom->paint(p, { - .preview = color, - .colored = &_fromNameStatus->colored, + .textColor = color, .now = context.now, .position = QPoint( x - 2 * _fromNameStatus->skip, diff --git a/Telegram/SourceFiles/history/view/history_view_sticker_toast.cpp b/Telegram/SourceFiles/history/view/history_view_sticker_toast.cpp index 768435bda..5cf22f446 100644 --- a/Telegram/SourceFiles/history/view/history_view_sticker_toast.cpp +++ b/Telegram/SourceFiles/history/view/history_view_sticker_toast.cpp @@ -311,7 +311,7 @@ void StickerToast::setupEmojiPreview( const auto size = Ui::Emoji::GetSizeLarge() / style::DevicePixelRatio(); instance->object.paint(p, Ui::Text::CustomEmoji::Context{ - .preview = st::toastBg->c, + .textColor = st::toastFg->c, .now = crl::now(), .position = QPoint( (widget->width() - size) / 2, diff --git a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp index 2a62d9c05..7edc6ff8a 100644 --- a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp @@ -562,7 +562,6 @@ void TopBarWidget::paintTopBar(Painter &p) { .premium = &st::dialogsPremiumIcon, .scam = &st::attentionButtonFg, .premiumFg = &st::dialogsVerifiedIconBg, - .preview = st::windowBgOver->c, .customEmojiRepaint = [=] { update(); }, .now = now, .paused = _controller->isGifPausedAtLeastFor( diff --git a/Telegram/SourceFiles/history/view/media/history_view_custom_emoji.cpp b/Telegram/SourceFiles/history/view/media/history_view_custom_emoji.cpp index 63fa634f9..8e628d659 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_custom_emoji.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_custom_emoji.cpp @@ -262,7 +262,8 @@ void CustomEmoji::paintCustom( _hasHeavyPart = true; _parent->history()->owner().registerHeavyViewPart(_parent); } - const auto preview = context.imageStyle()->msgServiceBg->c; + //const auto preview = context.imageStyle()->msgServiceBg->c; + auto &textst = context.st->messageStyle(false, false); if (context.selected()) { const auto factor = style::DevicePixelRatio(); const auto size = QSize(_singleSize, _singleSize) * factor; @@ -275,7 +276,7 @@ void CustomEmoji::paintCustom( _selectedFrame.fill(Qt::transparent); auto q = QPainter(&_selectedFrame); emoji->paint(q, { - .preview = preview, + .textColor = textst.historyTextFg->c, .now = context.now, .paused = context.paused, }); @@ -287,7 +288,7 @@ void CustomEmoji::paintCustom( p.drawImage(x, y, _selectedFrame); } else { emoji->paint(p, { - .preview = preview, + .textColor = textst.historyTextFg->c, .now = context.now, .position = { x, y }, .paused = context.paused, diff --git a/Telegram/SourceFiles/history/view/media/history_view_large_emoji.cpp b/Telegram/SourceFiles/history/view/media/history_view_large_emoji.cpp index ed1e1dce0..320f6e22c 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_large_emoji.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_large_emoji.cpp @@ -135,7 +135,8 @@ void LargeEmoji::paintCustom( const auto inner = st::largeEmojiSize + 2 * st::largeEmojiOutline; const auto outer = Ui::Text::AdjustCustomEmojiSize(inner); const auto skip = (inner - outer) / 2; - const auto preview = context.imageStyle()->msgServiceBg->c; + //const auto preview = context.imageStyle()->msgServiceBg->c; + auto &textst = context.st->messageStyle(false, false); if (context.selected()) { const auto factor = style::DevicePixelRatio(); const auto size = QSize(outer, outer) * factor; @@ -148,7 +149,7 @@ void LargeEmoji::paintCustom( _selectedFrame.fill(Qt::transparent); auto q = QPainter(&_selectedFrame); emoji->paint(q, { - .preview = preview, + .textColor = textst.historyTextFg->c, .now = context.now, .paused = context.paused, }); @@ -160,7 +161,7 @@ void LargeEmoji::paintCustom( p.drawImage(x + skip, y + skip, _selectedFrame); } else { emoji->paint(p, { - .preview = preview, + .textColor = textst.historyTextFg->c, .now = context.now, .position = { x + skip, y + skip }, .paused = context.paused, diff --git a/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp b/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp index 4534a77cd..f5e644637 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp @@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/image/image.h" #include "ui/chat/chat_style.h" #include "ui/effects/path_shift_gradient.h" +#include "ui/text/custom_emoji_instance.h" #include "ui/emoji_config.h" #include "ui/painter.h" #include "core/application.h" @@ -54,6 +55,23 @@ constexpr auto kEmojiMultiplier = 3; return image; } +[[nodiscard]] QColor ComputeEmojiTextColor(const PaintContext &context) { + const auto st = context.st; + const auto result = st->messageStyle(false, false).historyTextFg->c; + if (!context.selected()) { + return result; + } + const auto &add = st->msgStickerOverlay()->c; + + const auto ca = add.alpha(); + const auto ra = 0x100 - ca; + const auto aa = ca + 1; + const auto red = (result.red() * ra + add.red() * aa) >> 8; + const auto green = (result.green() * ra + add.green() * aa) >> 8; + const auto blue = (result.blue() * ra + add.blue() * aa) >> 8; + return QColor(red, green, blue, result.alpha()); +} + } // namespace Sticker::Sticker( @@ -224,7 +242,9 @@ void Sticker::paintAnimationFrame( Painter &p, const PaintContext &context, const QRect &r) { - const auto colored = (context.selected() && !_nextLastDiceFrame) + const auto colored = (customEmojiPart() && _data->emojiUsesTextColor()) + ? ComputeEmojiTextColor(context) + : (context.selected() && !_nextLastDiceFrame) ? context.st->msgStickerOverlay()->c : QColor(0, 0, 0, 0); const auto frame = _player @@ -319,7 +339,12 @@ void Sticker::paintPath( const PaintContext &context, const QRect &r) { const auto pathGradient = _parent->delegate()->elementPathShiftGradient(); - if (context.selected()) { + auto helper = std::optional(); + if (customEmojiPart() && _data->emojiUsesTextColor()) { + helper.emplace(Ui::CustomEmoji::PreviewColorFromTextColor( + ComputeEmojiTextColor(context))); + pathGradient->overrideColors(helper->color(), helper->color()); + } else if (context.selected()) { pathGradient->overrideColors( context.st->msgServiceBgSelected(), context.st->msgServiceBg()); @@ -333,10 +358,16 @@ void Sticker::paintPath( r, pathGradient, mirrorHorizontal()); + if (helper) { + pathGradient->clearOverridenColors(); + } } QPixmap Sticker::paintedPixmap(const PaintContext &context) const { - const auto colored = context.selected() + auto helper = std::optional(); + const auto colored = (customEmojiPart() && _data->emojiUsesTextColor()) + ? &helper.emplace(ComputeEmojiTextColor(context)).color() + : context.selected() ? &context.st->msgStickerOverlay() : nullptr; const auto good = _dataMedia->goodThumbnail(); diff --git a/Telegram/SourceFiles/history/view/reactions/history_view_reactions.cpp b/Telegram/SourceFiles/history/view/reactions/history_view_reactions.cpp index 9c524d643..d6b42d9f0 100644 --- a/Telegram/SourceFiles/history/view/reactions/history_view_reactions.cpp +++ b/Telegram/SourceFiles/history/view/reactions/history_view_reactions.cpp @@ -547,7 +547,7 @@ void InlineList::paintCustomFrame( not_null emoji, QPoint innerTopLeft, crl::time now, - const QColor &preview) const { + const QColor &textColor) const { if (_customCache.isNull()) { using namespace Ui::Text; const auto size = st::emojiSize; @@ -562,7 +562,7 @@ void InlineList::paintCustomFrame( _customCache.fill(Qt::transparent); auto q = QPainter(&_customCache); emoji->paint(q, { - .preview = preview, + .textColor = textColor, .now = now, .paused = p.inactive(), }); diff --git a/Telegram/SourceFiles/history/view/reactions/history_view_reactions.h b/Telegram/SourceFiles/history/view/reactions/history_view_reactions.h index bc6a3c37c..1100aa4af 100644 --- a/Telegram/SourceFiles/history/view/reactions/history_view_reactions.h +++ b/Telegram/SourceFiles/history/view/reactions/history_view_reactions.h @@ -110,7 +110,7 @@ private: not_null emoji, QPoint innerTopLeft, crl::time now, - const QColor &preview) const; + const QColor &textColor) const; QSize countOptimalSize() override; diff --git a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_list.cpp b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_list.cpp index f3613fb8b..d767d3ec7 100644 --- a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_list.cpp +++ b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_list.cpp @@ -158,7 +158,7 @@ void Row::rightActionPaint( const auto size = Ui::Emoji::GetSizeNormal() / style::DevicePixelRatio(); const auto skip = (size - Ui::Text::AdjustCustomEmojiSize(size)) / 2; _custom->paint(p, { - .preview = st::windowBgRipple->c, + .textColor = st::windowFg->c, .now = crl::now(), .position = { x + skip, y + skip }, .paused = _paused(), diff --git a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_tabs.cpp b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_tabs.cpp index b58336dca..c3b5848cc 100644 --- a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_tabs.cpp +++ b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_tabs.cpp @@ -112,13 +112,9 @@ not_null CreateTab( const auto shift = (height - size) / 2; const auto skip = (size - AdjustCustomEmojiSize(size)) / 2; custom->paint(p, { - .preview = (state->selected - ? QColor( - st::activeButtonFg->c.red(), - st::activeButtonFg->c.green(), - st::activeButtonFg->c.blue(), - st::activeButtonFg->c.alpha() / 3) - : st::windowBgRipple->c), + .textColor = (state->selected + ? stm->textActiveFg + : stm->textFg)->c, .now = crl::now(), .position = { icon.x() + shift + skip, shift + skip }, }); diff --git a/Telegram/SourceFiles/info/profile/info_profile_badge.cpp b/Telegram/SourceFiles/info/profile/info_profile_badge.cpp index 0ac67a013..00fb25cad 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_badge.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_badge.cpp @@ -68,7 +68,6 @@ void Badge::setBadge(BadgeType badge, DocumentId emojiStatusId) { _badge = badge; _emojiStatusId = emojiStatusId; _emojiStatus = nullptr; - _emojiStatusColored = nullptr; _view.destroy(); if (_badge == BadgeType::None) { _updated.fire({}); @@ -89,18 +88,13 @@ void Badge::setBadge(BadgeType badge, DocumentId emojiStatusId) { std::move(_emojiStatus), _customStatusLoopsLimit); } - _emojiStatusColored = std::make_unique< - Ui::Text::CustomEmojiColored - >(); const auto emoji = Data::FrameSizeFromTag(sizeTag()) / style::DevicePixelRatio(); _view->resize(emoji, emoji); _view->paintRequest( ) | rpl::start_with_next([=, check = _view.data()]{ - _emojiStatusColored->color = _st.premiumFg->c; auto args = Ui::Text::CustomEmoji::Context{ - .preview = st::windowBgOver->c, - .colored = _emojiStatusColored.get(), + .textColor = _st.premiumFg->c, .now = crl::now(), .paused = _animationPaused && _animationPaused(), }; diff --git a/Telegram/SourceFiles/info/profile/info_profile_badge.h b/Telegram/SourceFiles/info/profile/info_profile_badge.h index 4b3fbbd8d..9e9d01d75 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_badge.h +++ b/Telegram/SourceFiles/info/profile/info_profile_badge.h @@ -65,7 +65,6 @@ private: const int _customStatusLoopsLimit = 0; DocumentId _emojiStatusId = 0; std::unique_ptr _emojiStatus; - std::unique_ptr _emojiStatusColored; base::flags _allowed; BadgeType _badge = BadgeType(); Fn _premiumClickCallback; diff --git a/Telegram/SourceFiles/storage/serialize_document.cpp b/Telegram/SourceFiles/storage/serialize_document.cpp index cd010c847..a44207a52 100644 --- a/Telegram/SourceFiles/storage/serialize_document.cpp +++ b/Telegram/SourceFiles/storage/serialize_document.cpp @@ -18,7 +18,7 @@ namespace Serialize { namespace { constexpr auto kVersionTag = int32(0x7FFFFFFF); -constexpr auto kVersion = 4; +constexpr auto kVersion = 5; enum StickerSetType { StickerSetTypeEmpty = 0, @@ -63,6 +63,7 @@ void Document::writeToStream(QDataStream &stream, DocumentData *document) { const auto premium = document->isPremiumSticker() || document->isPremiumEmoji(); stream << qint32(premium ? 1 : 0); + stream << qint32(document->emojiUsesTextColor() ? 1 : 0); } writeImageLocation(stream, document->thumbnailLocation()); stream << qint32(document->thumbnailByteSize()); @@ -111,6 +112,7 @@ DocumentData *Document::readFromStreamHelper( qint32 duration = -1; qint32 isPremiumSticker = 0; + qint32 useTextColor = 0; if (type == StickerDocument) { QString alt; qint32 typeOfSet; @@ -119,6 +121,9 @@ DocumentData *Document::readFromStreamHelper( stream >> duration; if (version >= 4) { stream >> isPremiumSticker; + if (version >= 5) { + stream >> useTextColor; + } } } if (typeOfSet == StickerSetTypeEmpty) { @@ -140,9 +145,15 @@ DocumentData *Document::readFromStreamHelper( attributes.push_back(MTP_documentAttributeSticker(MTP_flags(MTPDdocumentAttributeSticker::Flag::f_mask), MTP_string(alt), MTP_inputStickerSetID(MTP_long(info->setId), MTP_long(info->accessHash)), MTPMaskCoords())); } break; case StickerSetTypeEmoji: { + if (version < 5) { + // We didn't store useTextColor yet, can't use. + stream.setStatus(QDataStream::ReadCorruptData); + return nullptr; + } using Flag = MTPDdocumentAttributeCustomEmoji::Flag; attributes.push_back(MTP_documentAttributeCustomEmoji( - MTP_flags(isPremiumSticker ? Flag(0) : Flag::f_free), + MTP_flags((isPremiumSticker ? Flag(0) : Flag::f_free) + | (useTextColor ? Flag::f_text_color : Flag(0))), MTP_string(alt), MTP_inputStickerSetID( MTP_long(info->setId), diff --git a/Telegram/SourceFiles/ui/controls/who_reacted_context_action.cpp b/Telegram/SourceFiles/ui/controls/who_reacted_context_action.cpp index 03faf1ac7..98c261e1c 100644 --- a/Telegram/SourceFiles/ui/controls/who_reacted_context_action.cpp +++ b/Telegram/SourceFiles/ui/controls/who_reacted_context_action.cpp @@ -327,7 +327,7 @@ void Action::paint(Painter &p) { + (st::whoReadChecks.width() - adjusted) / 2; const auto y = (_height - adjusted) / 2; _custom->paint(p, { - .preview = _st.ripple.color->c, + .textColor = (selected ? _st.itemFgOver : _st.itemFg)->c, .now = crl::now(), .position = { x, y }, }); @@ -588,7 +588,7 @@ void WhoReactedListMenu::EntryAction::paint(Painter &&p) { const auto size = Emoji::GetSizeNormal() / ratio; const auto skip = (size - _customSize) / 2; _custom->paint(p, { - .preview = _st.ripple.color->c, + .textColor = (selected ? _st.itemFgOver : _st.itemFg)->c, .now = crl::now(), .position = QPoint( width() - _st.itemPadding.right() - (size / ratio) + skip, diff --git a/Telegram/SourceFiles/ui/effects/reaction_fly_animation.cpp b/Telegram/SourceFiles/ui/effects/reaction_fly_animation.cpp index 21938af5f..0366667b3 100644 --- a/Telegram/SourceFiles/ui/effects/reaction_fly_animation.cpp +++ b/Telegram/SourceFiles/ui/effects/reaction_fly_animation.cpp @@ -80,7 +80,6 @@ ReactionFlyAnimation::ReactionFlyAnimation( document, callback(), customSizeTag); - _colored = std::make_unique(); _customSize = esize; _centerSizeMultiplier = _customSize / float64(size); aroundAnimation = owner->chooseGenericAnimation(document); @@ -203,10 +202,8 @@ void ReactionFlyAnimation::paintCenterFrame( p.drawImage(rect, _center->frame()); } else { const auto scaled = (size.width() != _customSize); - _colored->color = colored; _custom->paint(p, { - .preview = QColor(0, 0, 0, 0), - .colored = _colored.get(), + .textColor = colored, .size = { _customSize, _customSize }, .now = now, .scale = (scaled ? (size.width() / float64(_customSize)) : 1.), @@ -237,10 +234,8 @@ void ReactionFlyAnimation::paintMiniCopies( / float64(kMiniCopiesDurationMax); const auto scaleOut = kMiniCopiesScaleOutDuration / float64(kMiniCopiesDurationMax); - _colored->color = colored; auto context = Text::CustomEmoji::Context{ - .preview = preview, - .colored = _colored.get(), + .textColor = colored, .size = size, .now = now, .scaled = true, diff --git a/Telegram/SourceFiles/ui/effects/reaction_fly_animation.h b/Telegram/SourceFiles/ui/effects/reaction_fly_animation.h index 53069db3f..6092d46c1 100644 --- a/Telegram/SourceFiles/ui/effects/reaction_fly_animation.h +++ b/Telegram/SourceFiles/ui/effects/reaction_fly_animation.h @@ -12,7 +12,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Ui::Text { class CustomEmoji; -struct CustomEmojiColored; } // namespace Ui::Text namespace Data { @@ -95,7 +94,6 @@ private: Fn _repaint; QImage _flyIcon; std::unique_ptr _custom; - std::unique_ptr _colored; std::unique_ptr _center; std::unique_ptr _effect; std::vector _miniCopies; diff --git a/Telegram/SourceFiles/ui/unread_badge.cpp b/Telegram/SourceFiles/ui/unread_badge.cpp index 24d6fe7a2..2a5200b35 100644 --- a/Telegram/SourceFiles/ui/unread_badge.cpp +++ b/Telegram/SourceFiles/ui/unread_badge.cpp @@ -178,9 +178,6 @@ int PeerBadge::drawGetWidth( const auto size = st::emojiSize; const auto emoji = Ui::Text::AdjustCustomEmojiSize(size); _emojiStatus->skip = (size - emoji) / 2; - _emojiStatus->colored = std::make_unique< - Ui::Text::CustomEmojiColored - >(); } if (_emojiStatus->id != id) { using namespace Ui::Text; @@ -192,10 +189,8 @@ int PeerBadge::drawGetWidth( descriptor.customEmojiRepaint), kPlayStatusLimit); } - _emojiStatus->colored->color = (*descriptor.premiumFg)->c; _emojiStatus->emoji->paint(p, { - .preview = descriptor.preview, - .colored = _emojiStatus->colored.get(), + .textColor = (*descriptor.premiumFg)->c, .now = descriptor.now, .position = QPoint( iconx - 2 * _emojiStatus->skip, diff --git a/Telegram/SourceFiles/ui/unread_badge.h b/Telegram/SourceFiles/ui/unread_badge.h index 63019b54a..c644ae6d5 100644 --- a/Telegram/SourceFiles/ui/unread_badge.h +++ b/Telegram/SourceFiles/ui/unread_badge.h @@ -11,7 +11,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Ui::Text { class CustomEmoji; -struct CustomEmojiColored; } // namespace Ui::Text namespace Ui { @@ -43,7 +42,6 @@ public: const style::icon *premium = nullptr; const style::color *scam = nullptr; const style::color *premiumFg = nullptr; - QColor preview; Fn customEmojiRepaint; crl::time now = 0; bool paused = false; @@ -60,7 +58,6 @@ private: struct EmojiStatus { DocumentId id = 0; std::unique_ptr emoji; - std::unique_ptr colored; int skip = 0; }; std::unique_ptr _emojiStatus; diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 64d277891..4befce5a2 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 64d277891403ba3275b47d6ccab849322670cf99 +Subproject commit 4befce5a29d247fb17da3faafebb03578c5a989b