Move sticker image to DocumentMedia.

This commit is contained in:
John Preston 2020-04-09 12:15:47 +04:00
parent bdd3c51ab8
commit 70c79eb6bd
14 changed files with 156 additions and 122 deletions

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_document.h" #include "data/data_document.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
#include "data/data_document_media.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "chat_helpers/stickers.h" #include "chat_helpers/stickers.h"
#include "boxes/confirm_box.h" #include "boxes/confirm_box.h"
@ -72,6 +73,7 @@ protected:
private: private:
struct Element { struct Element {
not_null<DocumentData*> document; not_null<DocumentData*> document;
std::shared_ptr<Data::DocumentMedia> documentMedia;
Lottie::Animation *animated = nullptr; Lottie::Animation *animated = nullptr;
Ui::Animations::Simple overAnimation; Ui::Animations::Simple overAnimation;
}; };
@ -267,7 +269,7 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
continue; continue;
} }
_pack.push_back(document); _pack.push_back(document);
_elements.push_back({ document }); _elements.push_back({ document, document->createMediaView() });
} }
for (const auto &pack : data.vpacks().v) { for (const auto &pack : data.vpacks().v) {
pack.match([&](const MTPDstickerPack &pack) { pack.match([&](const MTPDstickerPack &pack) {
@ -621,7 +623,8 @@ void StickerSetBox::Inner::paintSticker(
const auto &element = _elements[index]; const auto &element = _elements[index];
const auto document = element.document; const auto document = element.document;
document->checkStickerSmall(); const auto &media = element.documentMedia;
media->checkStickerSmall();
if (document->sticker()->animated if (document->sticker()->animated
&& !element.animated && !element.animated
@ -650,7 +653,7 @@ void StickerSetBox::Inner::paintSticker(
frame); frame);
_lottiePlayer->unpause(element.animated); _lottiePlayer->unpause(element.animated);
} else if (const auto image = document->getStickerSmall()) { } else if (const auto image = media->getStickerSmall()) {
p.drawPixmapLeft( p.drawPixmapLeft(
ppos, ppos,
width(), width(),

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/field_autocomplete.h" #include "chat_helpers/field_autocomplete.h"
#include "data/data_document.h" #include "data/data_document.h"
#include "data/data_document_media.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_chat.h" #include "data/data_chat.h"
#include "data/data_user.h" #include "data/data_user.h"
@ -177,7 +178,10 @@ internal::StickerRows FieldAutocomplete::getStickerSuggestions() {
auto result = ranges::view::all( auto result = ranges::view::all(
list list
) | ranges::view::transform([](not_null<DocumentData*> sticker) { ) | ranges::view::transform([](not_null<DocumentData*> sticker) {
return internal::StickerSuggestion{ sticker }; return internal::StickerSuggestion{
sticker,
sticker->createMediaView()
};
}) | ranges::to_vector; }) | ranges::to_vector;
for (auto &suggestion : _srows) { for (auto &suggestion : _srows) {
if (!suggestion.animated) { if (!suggestion.animated) {
@ -634,6 +638,7 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
auto &sticker = (*_srows)[index]; auto &sticker = (*_srows)[index];
const auto document = sticker.document; const auto document = sticker.document;
const auto &media = sticker.documentMedia;
if (!document->sticker()) continue; if (!document->sticker()) continue;
if (document->sticker()->animated if (document->sticker()->animated
@ -649,7 +654,7 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
App::roundRect(p, QRect(tl, st::stickerPanSize), st::emojiPanHover, StickerHoverCorners); App::roundRect(p, QRect(tl, st::stickerPanSize), st::emojiPanHover, StickerHoverCorners);
} }
document->checkStickerSmall(); media->checkStickerSmall();
auto w = 1; auto w = 1;
auto h = 1; auto h = 1;
if (sticker.animated && !document->dimensions.isEmpty()) { if (sticker.animated && !document->dimensions.isEmpty()) {
@ -680,7 +685,7 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
if (!paused) { if (!paused) {
sticker.animated->markFrameShown(); sticker.animated->markFrameShown();
} }
} else if (const auto image = document->getStickerSmall()) { } else if (const auto image = media->getStickerSmall()) {
QPoint ppos = pos + QPoint((st::stickerPanSize.width() - w) / 2, (st::stickerPanSize.height() - h) / 2); QPoint ppos = pos + QPoint((st::stickerPanSize.width() - w) / 2, (st::stickerPanSize.height() - h) / 2);
p.drawPixmapLeft(ppos, width(), image->pix(document->stickerSetOrigin(), w, h)); p.drawPixmapLeft(ppos, width(), image->pix(document->stickerSetOrigin(), w, h));
} }

View file

@ -26,10 +26,15 @@ namespace Window {
class SessionController; class SessionController;
} // namespace Window } // namespace Window
namespace Data {
class DocumentMedia;
} // namespace Data
namespace internal { namespace internal {
struct StickerSuggestion { struct StickerSuggestion {
not_null<DocumentData*> document; not_null<DocumentData*> document;
std::shared_ptr<Data::DocumentMedia> documentMedia;
std::unique_ptr<Lottie::SinglePlayer> animated; std::unique_ptr<Lottie::SinglePlayer> animated;
}; };

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/stickers_list_widget.h" #include "chat_helpers/stickers_list_widget.h"
#include "data/data_document.h" #include "data/data_document.h"
#include "data/data_document_media.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
@ -184,7 +185,7 @@ auto StickersListWidget::PrepareStickers(const Stickers::Pack &pack)
return ranges::view::all( return ranges::view::all(
pack pack
) | ranges::view::transform([](DocumentData *document) { ) | ranges::view::transform([](DocumentData *document) {
return Sticker{ document }; return Sticker{ document, document->createMediaView() };
}) | ranges::to_vector; }) | ranges::to_vector;
} }
@ -1708,6 +1709,7 @@ QSize StickersListWidget::boundingBoxSize() const {
void StickersListWidget::paintSticker(Painter &p, Set &set, int y, int section, int index, bool selected, bool deleteSelected) { void StickersListWidget::paintSticker(Painter &p, Set &set, int y, int section, int index, bool selected, bool deleteSelected) {
auto &sticker = set.stickers[index]; auto &sticker = set.stickers[index];
const auto document = sticker.document; const auto document = sticker.document;
const auto &media = sticker.documentMedia;
if (!document->sticker()) { if (!document->sticker()) {
return; return;
} }
@ -1727,7 +1729,7 @@ void StickersListWidget::paintSticker(Painter &p, Set &set, int y, int section,
App::roundRect(p, QRect(tl, _singleSize), st::emojiPanHover, StickerHoverCorners); App::roundRect(p, QRect(tl, _singleSize), st::emojiPanHover, StickerHoverCorners);
} }
document->checkStickerSmall(); media->checkStickerSmall();
auto w = 1; auto w = 1;
auto h = 1; auto h = 1;
@ -1752,7 +1754,7 @@ void StickersListWidget::paintSticker(Painter &p, Set &set, int y, int section,
frame); frame);
set.lottiePlayer->unpause(sticker.animated); set.lottiePlayer->unpause(sticker.animated);
} else if (const auto image = document->getStickerSmall()) { } else if (const auto image = media->getStickerSmall()) {
if (image->loaded()) { if (image->loaded()) {
p.drawPixmapLeft( p.drawPixmapLeft(
ppos, ppos,
@ -2301,9 +2303,10 @@ void StickersListWidget::preloadImages() {
if (++k > _columnCount * (_columnCount + 1)) break; if (++k > _columnCount * (_columnCount + 1)) break;
const auto document = sets[i].stickers[j].document; const auto document = sets[i].stickers[j].document;
const auto &media = sets[i].stickers[j].documentMedia;
if (!document || !document->sticker()) continue; if (!document || !document->sticker()) continue;
document->checkStickerSmall(); media->checkStickerSmall();
} }
if (k > _columnCount * (_columnCount + 1)) break; if (k > _columnCount * (_columnCount + 1)) break;
} }
@ -2395,7 +2398,10 @@ auto StickersListWidget::collectRecentStickers() -> std::vector<Sticker> {
_custom[index] = true; _custom[index] = true;
} }
} else if (!_favedStickersMap.contains(document)) { } else if (!_favedStickersMap.contains(document)) {
result.push_back(Sticker{ document }); result.push_back(Sticker{
document,
document->createMediaView()
});
_custom.push_back(custom); _custom.push_back(custom);
} }
}; };

View file

@ -32,6 +32,10 @@ class MultiPlayer;
class FrameRenderer; class FrameRenderer;
} // namespace Lottie } // namespace Lottie
namespace Data {
class DocumentMedia;
} // namespace Data
namespace ChatHelpers { namespace ChatHelpers {
struct StickerIcon; struct StickerIcon;
@ -151,6 +155,7 @@ private:
struct Sticker { struct Sticker {
not_null<DocumentData*> document; not_null<DocumentData*> document;
std::shared_ptr<Data::DocumentMedia> documentMedia;
Lottie::Animation *animated = nullptr; Lottie::Animation *animated = nullptr;
}; };

View file

@ -58,12 +58,6 @@ Core::MediaActiveCache<DocumentData> &ActiveCache() {
return Instance; return Instance;
} }
int64 ComputeUsage(StickerData *sticker) {
return (sticker != nullptr && sticker->image != nullptr)
? sticker->image->width() * sticker->image->height() * 4
: 0;
}
QString JoinStringList(const QStringList &list, const QString &separator) { QString JoinStringList(const QStringList &list, const QString &separator) {
const auto count = list.size(); const auto count = list.size();
if (!count) { if (!count) {
@ -713,7 +707,7 @@ std::shared_ptr<Data::DocumentMedia> DocumentData::createMediaView() {
return result; return result;
} }
std::shared_ptr<Data::DocumentMedia> DocumentData::activeMediaView() { std::shared_ptr<Data::DocumentMedia> DocumentData::activeMediaView() const {
return _media.lock(); return _media.lock();
} }
@ -755,12 +749,6 @@ void DocumentData::unload() {
// from the destructor, because they're already destroyed. // from the destructor, because they're already destroyed.
// //
//_thumbnail->unload(); //_thumbnail->unload();
if (sticker()) {
if (sticker()->image) {
ActiveCache().decrement(ComputeUsage(sticker()));
sticker()->image = nullptr;
}
}
_replyPreview = nullptr; _replyPreview = nullptr;
if (!_data.isEmpty()) { if (!_data.isEmpty()) {
ActiveCache().decrement(_data.size()); ActiveCache().decrement(_data.size());
@ -824,23 +812,14 @@ bool DocumentData::loaded(FilePathResolve resolve) const {
that->_data = _loader->bytes(); that->_data = _loader->bytes();
ActiveCache().increment(that->_data.size()); ActiveCache().increment(that->_data.size());
if (that->sticker()
&& !that->sticker()->image
&& !_loader->imageData().isNull()) {
that->sticker()->image = std::make_unique<Image>(
std::make_unique<Images::LocalFileSource>(
QString(),
_data,
_loader->imageFormat(),
_loader->imageData()));
ActiveCache().increment(ComputeUsage(that->sticker()));
}
that->setGoodThumbnailDataReady(); that->setGoodThumbnailDataReady();
Data::DocumentMedia::CheckGoodThumbnail(that);
if (const auto media = activeMediaView()) {
media->checkStickerLarge(_loader.get());
}
destroyLoader(); destroyLoader();
if (!that->_data.isEmpty() || that->getStickerLarge()) { if (!that->_data.isEmpty()) {
ActiveCache().up(that); ActiveCache().up(that);
} }
} }
@ -1207,66 +1186,6 @@ StickerData *DocumentData::sticker() const {
: nullptr; : nullptr;
} }
void DocumentData::checkStickerLarge() {
const auto data = sticker();
if (!data) return;
automaticLoad(stickerSetOrigin(), nullptr);
if (!data->image && !data->animated && loaded()) {
if (_data.isEmpty()) {
const auto &loc = location(true);
if (loc.accessEnable()) {
data->image = std::make_unique<Image>(
std::make_unique<Images::LocalFileSource>(loc.name()));
loc.accessDisable();
}
} else {
auto format = QByteArray();
auto image = App::readImage(_data, &format, false);
data->image = std::make_unique<Image>(
std::make_unique<Images::LocalFileSource>(
QString(),
_data,
format,
std::move(image)));
}
if (const auto usage = ComputeUsage(data)) {
ActiveCache().increment(usage);
ActiveCache().up(this);
}
}
}
void DocumentData::checkStickerSmall() {
const auto data = sticker();
if ((data && data->animated) || thumbnailEnoughForSticker()) {
_thumbnail->load(stickerSetOrigin());
if (data && data->animated) {
automaticLoad(stickerSetOrigin(), nullptr);
}
} else {
checkStickerLarge();
}
}
Image *DocumentData::getStickerLarge() {
checkStickerLarge();
if (const auto data = sticker()) {
return data->image.get();
}
return nullptr;
}
Image *DocumentData::getStickerSmall() {
const auto data = sticker();
if ((data && data->animated) || thumbnailEnoughForSticker()) {
return _thumbnail->isNull() ? nullptr : _thumbnail.get();
} else if (data) {
return data->image.get();
}
return nullptr;
}
Data::FileOrigin DocumentData::stickerSetOrigin() const { Data::FileOrigin DocumentData::stickerSetOrigin() const {
if (const auto data = sticker()) { if (const auto data = sticker()) {
if (const auto result = data->setOrigin()) { if (const auto result = data->setOrigin()) {

View file

@ -58,7 +58,6 @@ struct DocumentAdditionalData {
struct StickerData : public DocumentAdditionalData { struct StickerData : public DocumentAdditionalData {
Data::FileOrigin setOrigin() const; Data::FileOrigin setOrigin() const;
std::unique_ptr<Image> image;
bool animated = false; bool animated = false;
QString alt; QString alt;
MTPInputStickerSet set = MTP_inputStickerSetEmpty(); MTPInputStickerSet set = MTP_inputStickerSetEmpty();
@ -141,13 +140,10 @@ public:
[[nodiscard]] Image *getReplyPreview(Data::FileOrigin origin); [[nodiscard]] Image *getReplyPreview(Data::FileOrigin origin);
[[nodiscard]] StickerData *sticker() const; [[nodiscard]] StickerData *sticker() const;
void checkStickerLarge();
void checkStickerSmall();
[[nodiscard]] Image *getStickerSmall();
[[nodiscard]] Image *getStickerLarge();
[[nodiscard]] Data::FileOrigin stickerSetOrigin() const; [[nodiscard]] Data::FileOrigin stickerSetOrigin() const;
[[nodiscard]] Data::FileOrigin stickerOrGifOrigin() const; [[nodiscard]] Data::FileOrigin stickerOrGifOrigin() const;
[[nodiscard]] bool isStickerSetInstalled() const; [[nodiscard]] bool isStickerSetInstalled() const;
[[nodiscard]] bool thumbnailEnoughForSticker() const;
[[nodiscard]] SongData *song(); [[nodiscard]] SongData *song();
[[nodiscard]] const SongData *song() const; [[nodiscard]] const SongData *song() const;
[[nodiscard]] VoiceData *voice(); [[nodiscard]] VoiceData *voice();
@ -195,7 +191,8 @@ public:
void setGoodThumbnailChecked(bool hasData); void setGoodThumbnailChecked(bool hasData);
[[nodiscard]] std::shared_ptr<Data::DocumentMedia> createMediaView(); [[nodiscard]] std::shared_ptr<Data::DocumentMedia> createMediaView();
[[nodiscard]] std::shared_ptr<Data::DocumentMedia> activeMediaView(); [[nodiscard]] auto activeMediaView() const
-> std::shared_ptr<Data::DocumentMedia>;
void setGoodThumbnailPhoto(not_null<PhotoData*> photo); void setGoodThumbnailPhoto(not_null<PhotoData*> photo);
[[nodiscard]] PhotoData *goodThumbnailPhoto() const; [[nodiscard]] PhotoData *goodThumbnailPhoto() const;
@ -302,7 +299,6 @@ private:
void destroyLoader() const; void destroyLoader() const;
[[nodiscard]] bool useStreamingLoader() const; [[nodiscard]] bool useStreamingLoader() const;
[[nodiscard]] bool thumbnailEnoughForSticker() const;
// Two types of location: from MTProto by dc+access or from web by url // Two types of location: from MTProto by dc+access or from web by url
int32 _dc = 0; int32 _dc = 0;

View file

@ -11,10 +11,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_document_good_thumbnail.h" #include "data/data_document_good_thumbnail.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_cloud_themes.h" #include "data/data_cloud_themes.h"
#include "data/data_file_origin.h"
#include "media/clip/media_clip_reader.h" #include "media/clip/media_clip_reader.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "lottie/lottie_animation.h" #include "lottie/lottie_animation.h"
#include "window/themes/window_theme_preview.h" #include "window/themes/window_theme_preview.h"
#include "storage/file_download.h"
#include "ui/image/image.h" #include "ui/image/image.h"
#include "app.h" #include "app.h"
@ -121,6 +123,78 @@ Image *DocumentMedia::thumbnailInline() const {
return _inlineThumbnail.get(); return _inlineThumbnail.get();
} }
void DocumentMedia::checkStickerLarge() {
if (_sticker) {
return;
}
const auto data = _owner->sticker();
if (!data) {
return;
}
_owner->automaticLoad(_owner->stickerSetOrigin(), nullptr);
if (data->animated || !_owner->loaded()) {
return;
}
const auto bytes = _owner->data();
if (bytes.isEmpty()) {
const auto &loc = _owner->location(true);
if (loc.accessEnable()) {
_sticker = std::make_unique<Image>(
std::make_unique<Images::LocalFileSource>(loc.name()));
loc.accessDisable();
}
} else {
auto format = QByteArray();
auto image = App::readImage(bytes, &format, false);
_sticker = std::make_unique<Image>(
std::make_unique<Images::LocalFileSource>(
QString(),
bytes,
format,
std::move(image)));
}
}
void DocumentMedia::checkStickerSmall() {
const auto data = _owner->sticker();
if ((data && data->animated) || _owner->thumbnailEnoughForSticker()) {
_owner->loadThumbnail(_owner->stickerSetOrigin());
if (data && data->animated) {
_owner->automaticLoad(_owner->stickerSetOrigin(), nullptr);
}
} else {
checkStickerLarge();
}
}
Image *DocumentMedia::getStickerLarge() {
checkStickerLarge();
return _sticker.get();
}
Image *DocumentMedia::getStickerSmall() {
const auto data = _owner->sticker();
if ((data && data->animated) || _owner->thumbnailEnoughForSticker()) {
return _owner->thumbnail();
}
return _sticker.get();
}
void DocumentMedia::checkStickerLarge(not_null<FileLoader*> loader) {
if (_owner->sticker()
&& !_sticker
&& !loader->imageData().isNull()
&& !_owner->data().isEmpty()) {
_sticker = std::make_unique<Image>(
std::make_unique<Images::LocalFileSource>(
QString(),
_owner->data(),
loader->imageFormat(),
loader->imageData()));
}
}
void DocumentMedia::GenerateGoodThumbnail(not_null<DocumentData*> document) { void DocumentMedia::GenerateGoodThumbnail(not_null<DocumentData*> document) {
const auto data = document->data(); const auto data = document->data();
const auto type = document->isWallPaper() const auto type = document->isWallPaper()

View file

@ -9,6 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/flags.h" #include "base/flags.h"
class FileLoader;
namespace Data { namespace Data {
class DocumentMedia final { class DocumentMedia final {
@ -22,6 +24,12 @@ public:
[[nodiscard]] Image *thumbnailInline() const; [[nodiscard]] Image *thumbnailInline() const;
void checkStickerLarge();
void checkStickerSmall();
[[nodiscard]] Image *getStickerSmall();
[[nodiscard]] Image *getStickerLarge();
void checkStickerLarge(not_null<FileLoader*> loader);
// For DocumentData. // For DocumentData.
static void CheckGoodThumbnail(not_null<DocumentData*> document); static void CheckGoodThumbnail(not_null<DocumentData*> document);
@ -38,6 +46,7 @@ private:
const not_null<DocumentData*> _owner; const not_null<DocumentData*> _owner;
std::unique_ptr<Image> _goodThumbnail; std::unique_ptr<Image> _goodThumbnail;
mutable std::unique_ptr<Image> _inlineThumbnail; mutable std::unique_ptr<Image> _inlineThumbnail;
std::unique_ptr<Image> _sticker;
Flags _flags; Flags _flags;
}; };

View file

@ -100,7 +100,8 @@ bool Sticker::readyToDrawLottie() {
return false; return false;
} }
_data->checkStickerLarge(); ensureDataMediaCreated();
_dataMedia->checkStickerLarge();
const auto loaded = _data->loaded(); const auto loaded = _data->loaded();
if (sticker->animated && !_lottie && loaded) { if (sticker->animated && !_lottie && loaded) {
setupLottie(); setupLottie();
@ -124,6 +125,7 @@ QSize Sticker::GetAnimatedEmojiSize(
} }
void Sticker::draw(Painter &p, const QRect &r, bool selected) { void Sticker::draw(Painter &p, const QRect &r, bool selected) {
ensureDataMediaCreated();
if (readyToDrawLottie()) { if (readyToDrawLottie()) {
paintLottie(p, r, selected); paintLottie(p, r, selected);
} else if (_data->sticker() } else if (_data->sticker()
@ -200,8 +202,6 @@ void Sticker::paintPixmap(Painter &p, const QRect &r, bool selected) {
} }
QPixmap Sticker::paintedPixmap(bool selected) const { QPixmap Sticker::paintedPixmap(bool selected) const {
ensureDataMediaCreated();
const auto o = _parent->data()->fullId(); const auto o = _parent->data()->fullId();
const auto w = _size.width(); const auto w = _size.width();
const auto h = _size.height(); const auto h = _size.height();
@ -210,7 +210,7 @@ QPixmap Sticker::paintedPixmap(bool selected) const {
if (good && !good->loaded()) { if (good && !good->loaded()) {
good->load({}); good->load({});
} }
if (const auto image = _data->getStickerLarge()) { if (const auto image = _dataMedia->getStickerLarge()) {
return selected return selected
? image->pixColored(o, c, w, h) ? image->pixColored(o, c, w, h)
: image->pix(o, w, h); : image->pix(o, w, h);

View file

@ -434,12 +434,20 @@ void Sticker::initDimensions() {
void Sticker::preload() const { void Sticker::preload() const {
if (const auto document = getShownDocument()) { if (const auto document = getShownDocument()) {
document->checkStickerSmall(); ensureDataMediaCreated(document);
_dataMedia->checkStickerSmall();
} else if (const auto thumb = getResultThumb()) { } else if (const auto thumb = getResultThumb()) {
thumb->load(fileOrigin()); thumb->load(fileOrigin());
} }
} }
void Sticker::ensureDataMediaCreated(not_null<DocumentData*> document) const {
if (_dataMedia) {
return;
}
_dataMedia = document->createMediaView();
}
void Sticker::paint(Painter &p, const QRect &clip, const PaintContext *context) const { void Sticker::paint(Painter &p, const QRect &clip, const PaintContext *context) const {
bool loaded = getShownDocument()->loaded(); bool loaded = getShownDocument()->loaded();
@ -517,14 +525,15 @@ void Sticker::setupLottie(not_null<DocumentData*> document) const {
void Sticker::prepareThumbnail() const { void Sticker::prepareThumbnail() const {
if (const auto document = getShownDocument()) { if (const auto document = getShownDocument()) {
ensureDataMediaCreated(document);
if (!_lottie if (!_lottie
&& document->sticker() && document->sticker()
&& document->sticker()->animated && document->sticker()->animated
&& document->loaded()) { && document->loaded()) {
setupLottie(document); setupLottie(document);
} }
document->checkStickerSmall(); _dataMedia->checkStickerSmall();
if (const auto sticker = document->getStickerSmall()) { if (const auto sticker = _dataMedia->getStickerSmall()) {
if (!_lottie && !_thumbLoaded && sticker->loaded()) { if (!_lottie && !_thumbLoaded && sticker->loaded()) {
const auto thumbSize = getThumbSize(); const auto thumbSize = getThumbSize();
_thumb = sticker->pix( _thumb = sticker->pix(

View file

@ -192,6 +192,7 @@ public:
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override; void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
private: private:
void ensureDataMediaCreated(not_null<DocumentData*> document) const;
void setupLottie(not_null<DocumentData*> document) const; void setupLottie(not_null<DocumentData*> document) const;
QSize getThumbSize() const; QSize getThumbSize() const;
void prepareThumbnail() const; void prepareThumbnail() const;
@ -203,6 +204,7 @@ private:
mutable bool _thumbLoaded = false; mutable bool _thumbLoaded = false;
mutable std::unique_ptr<Lottie::SinglePlayer> _lottie; mutable std::unique_ptr<Lottie::SinglePlayer> _lottie;
mutable std::shared_ptr<Data::DocumentMedia> _dataMedia;
mutable rpl::lifetime _lifetime; mutable rpl::lifetime _lifetime;
}; };

View file

@ -1093,6 +1093,7 @@ void OverlayWidget::clearData() {
_fromName = QString(); _fromName = QString();
_photo = nullptr; _photo = nullptr;
_doc = nullptr; _doc = nullptr;
_docMedia = nullptr;
_pip = nullptr; _pip = nullptr;
_fullScreenVideo = false; _fullScreenVideo = false;
_caption.clear(); _caption.clear();
@ -1913,6 +1914,7 @@ void OverlayWidget::displayPhoto(not_null<PhotoData*> photo, HistoryItem *item)
clearStreaming(); clearStreaming();
destroyThemePreview(); destroyThemePreview();
_doc = nullptr; _doc = nullptr;
_docMedia = nullptr;
_fullScreenVideo = false; _fullScreenVideo = false;
_photo = photo; _photo = photo;
_rotation = _photo->owner().mediaRotation().get(_photo); _rotation = _photo->owner().mediaRotation().get(_photo);
@ -1972,6 +1974,9 @@ void OverlayWidget::displayDocument(
clearStreaming(_doc != doc); clearStreaming(_doc != doc);
destroyThemePreview(); destroyThemePreview();
_doc = doc; _doc = doc;
if (_doc) {
_docMedia = _doc->createMediaView();
}
_rotation = _doc ? _doc->owner().mediaRotation().get(_doc) : 0; _rotation = _doc ? _doc->owner().mediaRotation().get(_doc) : 0;
_themeCloudData = cloud; _themeCloudData = cloud;
_photo = nullptr; _photo = nullptr;
@ -1980,7 +1985,7 @@ void OverlayWidget::displayDocument(
refreshMediaViewer(); refreshMediaViewer();
if (_doc) { if (_doc) {
if (_doc->sticker()) { if (_doc->sticker()) {
if (const auto image = _doc->getStickerLarge()) { if (const auto image = _docMedia->getStickerLarge()) {
_staticContent = image->pix(fileOrigin()); _staticContent = image->pix(fileOrigin());
} else if (_doc->hasThumbnail()) { } else if (_doc->hasThumbnail()) {
_staticContent = _doc->thumbnail()->pixBlurred( _staticContent = _doc->thumbnail()->pixBlurred(
@ -3019,7 +3024,7 @@ void OverlayWidget::paintTransformedStaticContent(Painter &p) {
const auto rect = contentRect(); const auto rect = contentRect();
PainterHighQualityEnabler hq(p); PainterHighQualityEnabler hq(p);
if ((!_doc || !_doc->getStickerLarge()) if ((!_doc || !_docMedia->getStickerLarge())
&& (_staticContent.isNull() && (_staticContent.isNull()
|| _staticContent.hasAlpha())) { || _staticContent.hasAlpha())) {
p.fillRect(rect, _transparentBrush); p.fillRect(rect, _transparentBrush);
@ -3482,13 +3487,9 @@ void OverlayWidget::preloadData(int delta) {
if (auto photo = base::get_if<not_null<PhotoData*>>(&entity.data)) { if (auto photo = base::get_if<not_null<PhotoData*>>(&entity.data)) {
(*photo)->download(fileOrigin()); (*photo)->download(fileOrigin());
} else if (auto document = base::get_if<not_null<DocumentData*>>(&entity.data)) { } else if (auto document = base::get_if<not_null<DocumentData*>>(&entity.data)) {
if (const auto image = (*document)->getStickerLarge()) { (*document)->loadThumbnail(fileOrigin());
image->load(fileOrigin()); if (!(*document)->canBePlayed()) {
} else { (*document)->automaticLoad(fileOrigin(), entity.item);
(*document)->loadThumbnail(fileOrigin());
if (!(*document)->canBePlayed()) {
(*document)->automaticLoad(fileOrigin(), entity.item);
}
} }
} }
} }

View file

@ -249,7 +249,7 @@ QPixmap MediaPreviewWidget::currentImage() const {
} }
if (_lottie && _lottie->ready()) { if (_lottie && _lottie->ready()) {
return QPixmap(); return QPixmap();
} else if (const auto image = _document->getStickerLarge()) { } else if (const auto image = _documentMedia->getStickerLarge()) {
QSize s = currentDimensions(); QSize s = currentDimensions();
_cache = image->pix(_origin, s.width(), s.height()); _cache = image->pix(_origin, s.width(), s.height());
_cacheStatus = CacheLoaded; _cacheStatus = CacheLoaded;