diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp index f9ea7b520..fb0ff5308 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp @@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_location_manager.h" #include "history/view/history_view_cursor_state.h" #include "history/view/media/history_view_document.h" // DrawThumbnailAsSongCover +#include "history/view/media/history_view_media_common.h" #include "ui/image/image.h" #include "ui/text/format_values.h" #include "ui/cached_round_corners.h" @@ -461,6 +462,7 @@ void Sticker::unloadHeavyPart() { _dataMedia = nullptr; _lifetime.destroy(); _lottie = nullptr; + _webm = nullptr; } void Sticker::paint(Painter &p, const QRect &clip, const PaintContext *context) const { @@ -476,7 +478,6 @@ void Sticker::paint(Painter &p, const QRect &clip, const PaintContext *context) prepareThumbnail(); if (_lottie && _lottie->ready()) { const auto frame = _lottie->frame(); - _lottie->markFrameShown(); const auto size = frame.size() / cIntRetinaFactor(); const auto pos = QPoint( (st::stickerPanSize.width() - size.width()) / 2, @@ -484,6 +485,19 @@ void Sticker::paint(Painter &p, const QRect &clip, const PaintContext *context) p.drawImage( QRect(pos, size), frame); + if (!context->paused) { + _lottie->markFrameShown(); + } + } else if (_webm && _webm->started()) { + const auto size = getThumbSize(); + const auto frame = _webm->current({ + .frame = size, + .keepAlpha = true, + }, context->paused ? 0 : context->ms); + p.drawPixmap( + (st::stickerPanSize.width() - size.width()) / 2, + (st::stickerPanSize.height() - size.width()) / 2, + frame); } else if (!_thumb.isNull()) { int w = _thumb.width() / cIntRetinaFactor(), h = _thumb.height() / cIntRetinaFactor(); QPoint pos = QPoint((st::stickerPanSize.width() - w) / 2, (st::stickerPanSize.height() - h) / 2); @@ -527,13 +541,15 @@ void Sticker::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) { ItemBase::clickHandlerActiveChanged(p, active); } +QSize Sticker::boundingBox() const { + const auto size = st::stickerPanSize.width() - st::roundRadiusSmall * 2; + return { size, size }; +} + QSize Sticker::getThumbSize() const { - int width = qMax(content_width(), 1), height = qMax(content_height(), 1); - float64 coefw = (st::stickerPanSize.width() - st::roundRadiusSmall * 2) / float64(width); - float64 coefh = (st::stickerPanSize.height() - st::roundRadiusSmall * 2) / float64(height); - float64 coef = qMin(qMin(coefw, coefh), 1.); - int w = qRound(coef * content_width()), h = qRound(coef * content_height()); - return QSize(qMax(w, 1), qMax(h, 1)); + const auto width = qMax(content_width(), 1); + const auto height = qMax(content_height(), 1); + return HistoryView::DownscaledSize({ width, height }, boundingBox()); } void Sticker::setupLottie() const { @@ -542,10 +558,7 @@ void Sticker::setupLottie() const { _lottie = ChatHelpers::LottiePlayerFromDocument( _dataMedia.get(), ChatHelpers::StickerLottieSize::InlineResults, - QSize( - st::stickerPanSize.width() - st::roundRadiusSmall * 2, - st::stickerPanSize.height() - st::roundRadiusSmall * 2 - ) * cIntRetinaFactor()); + boundingBox() * cIntRetinaFactor()); _lottie->updates( ) | rpl::start_with_next([=] { @@ -553,27 +566,66 @@ void Sticker::setupLottie() const { }, _lifetime); } +void Sticker::setupWebm() const { + Expects(_dataMedia != nullptr); + + const auto that = const_cast(this); + auto callback = [=](Media::Clip::Notification notification) { + that->clipCallback(notification); + }; + that->_webm = Media::Clip::MakeReader( + _dataMedia->owner()->location(), + _dataMedia->bytes(), + std::move(callback)); +} + void Sticker::prepareThumbnail() const { const auto document = getShownDocument(); Assert(document != nullptr); ensureDataMediaCreated(document); - if (!_lottie - && document->sticker() - && document->sticker()->isLottie() - && _dataMedia->loaded()) { - setupLottie(); + const auto sticker = document->sticker(); + if (sticker && _dataMedia->loaded()) { + if (!_lottie && sticker->isLottie()) { + setupLottie(); + } else if (!_webm && sticker->isWebm()) { + setupWebm(); + } } _dataMedia->checkStickerSmall(); - if (const auto sticker = _dataMedia->getStickerSmall()) { + if (const auto image = _dataMedia->getStickerSmall()) { if (!_lottie && !_thumbLoaded) { const auto thumbSize = getThumbSize(); - _thumb = sticker->pix(thumbSize); + _thumb = image->pix(thumbSize); _thumbLoaded = true; } } } +void Sticker::clipCallback(Media::Clip::Notification notification) { + using namespace Media::Clip; + switch (notification) { + case Notification::Reinit: { + if (!_webm) { + break; + } else if (_webm->state() == State::Error) { + _webm.setBad(); + } else if (_webm->ready() && !_webm->started()) { + _webm->start({ + .frame = getThumbSize(), + .keepAlpha = true, + }); + } else if (_webm->autoPausedGif() + && !context()->inlineItemVisible(this)) { + unloadHeavyPart(); + } + } break; + + case Notification::Repaint: break; + } + update(); +} + Photo::Photo(not_null context, not_null result) : ItemBase(context, result) { Expects(getShownPhoto() != nullptr); diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h index e9ab8b87b..c29d06db7 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h @@ -204,8 +204,11 @@ public: private: void ensureDataMediaCreated(not_null document) const; void setupLottie() const; + void setupWebm() const; QSize getThumbSize() const; + QSize boundingBox() const; void prepareThumbnail() const; + void clipCallback(Media::Clip::Notification notification); mutable Ui::Animations::Simple _a_over; mutable bool _active = false; @@ -214,6 +217,7 @@ private: mutable bool _thumbLoaded = false; mutable std::unique_ptr _lottie; + Media::Clip::ReaderPointer _webm; mutable std::shared_ptr _dataMedia; mutable rpl::lifetime _lifetime;