diff --git a/ui/text/custom_emoji_instance.cpp b/ui/text/custom_emoji_instance.cpp index bac989b..96b8395 100644 --- a/ui/text/custom_emoji_instance.cpp +++ b/ui/text/custom_emoji_instance.cpp @@ -383,20 +383,28 @@ PaintFrameResult Cache::paintCurrentFrame( return {}; } const auto first = context.internal.forceFirstFrame; - if (!first) { + auto last = context.internal.forceLastFrame; + if (!first && !last) { const auto now = context.paused ? 0 : context.now; const auto finishes = now ? currentFrameFinishes() : 0; if (finishes && now >= finishes) { ++_frame; if (_finished && _frame == _frames) { _frame = 0; + if (context.internal.overrideFirstWithLastFrame) { + last = true; + } } _shown = now; } else if (!_shown) { _shown = now; } } - const auto index = first ? 0 : std::min(_frame, _frames - 1); + const auto index = first + ? 0 + : last + ? (_frames - 1) + : std::min(_frame, _frames - 1); const auto info = frame(index); const auto size = _size / style::DevicePixelRatio(); const auto rect = QRect(context.position, QSize(size, size)); diff --git a/ui/text/text_custom_emoji.cpp b/ui/text/text_custom_emoji.cpp index f0da6fd..f767f65 100644 --- a/ui/text/text_custom_emoji.cpp +++ b/ui/text/text_custom_emoji.cpp @@ -70,9 +70,11 @@ bool FirstFrameEmoji::readyInDefaultState() { LimitedLoopsEmoji::LimitedLoopsEmoji( std::unique_ptr wrapped, - int limit) + int limit, + bool stopOnLast) : _wrapped(std::move(wrapped)) -, _limit(limit) { +, _limit(limit) +, _stopOnLast(stopOnLast) { } QString LimitedLoopsEmoji::entityData() { @@ -91,10 +93,18 @@ void LimitedLoopsEmoji::paint(QPainter &p, const Context &context) { } } if (_played == _limit) { - const auto was = context.internal.forceFirstFrame; - context.internal.forceFirstFrame = true; + const auto wasFirst = context.internal.forceFirstFrame; + const auto wasLast = context.internal.forceLastFrame; + (_stopOnLast + ? context.internal.forceLastFrame + : context.internal.forceFirstFrame) = true; _wrapped->paint(p, context); - context.internal.forceFirstFrame = was; + context.internal.forceFirstFrame = wasFirst; + context.internal.forceLastFrame = wasLast; + } else if (_played + 1 == _limit && _inLoop && _stopOnLast) { + const auto wasLast = context.internal.overrideFirstWithLastFrame; + _wrapped->paint(p, context); + context.internal.overrideFirstWithLastFrame = wasLast; } else { _wrapped->paint(p, context); } diff --git a/ui/text/text_custom_emoji.h b/ui/text/text_custom_emoji.h index fb65685..76d525b 100644 --- a/ui/text/text_custom_emoji.h +++ b/ui/text/text_custom_emoji.h @@ -31,6 +31,8 @@ struct CustomEmojiPaintContext { mutable struct { bool colorized = false; bool forceFirstFrame = false; + bool forceLastFrame = false; + bool overrideFirstWithLastFrame = false; } internal; }; @@ -85,7 +87,10 @@ private: class LimitedLoopsEmoji final : public CustomEmoji { public: - LimitedLoopsEmoji(std::unique_ptr wrapped, int limit); + LimitedLoopsEmoji( + std::unique_ptr wrapped, + int limit, + bool stopOnLast = false); QString entityData() override; void paint(QPainter &p, const Context &context) override; @@ -98,6 +103,7 @@ private: const int _limit = 0; int _played = 0; bool _inLoop = false; + bool _stopOnLast = false; };