Leave only one image source type.

This commit is contained in:
John Preston 2020-05-29 18:29:21 +04:00
parent 6513422e40
commit d0c78eaddd
4 changed files with 60 additions and 84 deletions

View File

@ -117,68 +117,6 @@ constexpr auto kClearSourceTimeout = 10 * crl::time(1000);
return list[index - 1];
}
class ImageSource : public Images::Source {
public:
explicit ImageSource(
EmojiPtr emoji,
not_null<crl::object_on_queue<EmojiImageLoader>*> loader);
void load() override;
QImage takeLoaded() override;
int width() override;
int height() override;
private:
// While HistoryView::Element-s are almost never destroyed
// we make loading of the image lazy.
not_null<crl::object_on_queue<EmojiImageLoader>*> _loader;
EmojiPtr _emoji = nullptr;
QImage _data;
QSize _size;
base::binary_guard _loading;
};
ImageSource::ImageSource(
EmojiPtr emoji,
not_null<crl::object_on_queue<EmojiImageLoader>*> loader)
: _loader(loader)
, _emoji(emoji)
, _size(SingleSize()) {
}
void ImageSource::load() {
if (!_data.isNull() || _loading) {
return;
}
_loader->with([
this,
emoji = _emoji,
guard = _loading.make_guard()
](EmojiImageLoader &loader) mutable {
if (!guard) {
return;
}
crl::on_main(std::move(guard), [this, image = loader.prepare(emoji)]{
_data = image;
Auth().downloaderTaskFinished().notify();
});
});
}
QImage ImageSource::takeLoaded() {
return _data;
}
int ImageSource::width() {
return _size.width();
}
int ImageSource::height() {
return _size.height();
}
} // namespace
EmojiImageLoader::EmojiImageLoader(
@ -264,6 +202,10 @@ std::shared_ptr<UniversalImages> EmojiImageLoader::releaseImages() {
} // namespace details
QSize LargeEmojiImage::Size() {
return details::SingleSize();
}
EmojiPack::EmojiPack(not_null<Main::Session*> session)
: _session(session)
, _imageLoader(prepareSourceImages(), session->settings().largeEmoji())
@ -347,13 +289,38 @@ auto EmojiPack::stickerForEmoji(const IsolatedEmoji &emoji) -> Sticker {
return Sticker();
}
std::shared_ptr<Image> EmojiPack::image(EmojiPtr emoji) {
const auto i = _images.emplace(emoji, std::weak_ptr<Image>()).first;
std::shared_ptr<LargeEmojiImage> EmojiPack::image(EmojiPtr emoji) {
const auto i = _images.emplace(
emoji,
std::weak_ptr<LargeEmojiImage>()).first;
if (const auto result = i->second.lock()) {
return result;
}
auto result = std::make_shared<Image>(
std::make_unique<details::ImageSource>(emoji, &_imageLoader));
auto result = std::make_shared<LargeEmojiImage>();
const auto raw = result.get();
const auto weak = base::make_weak(_session.get());
raw->load = [=] {
_imageLoader.with([=](details::EmojiImageLoader &loader) mutable {
crl::on_main(weak, [
=,
image = loader.prepare(emoji)
]() mutable {
const auto i = _images.find(emoji);
if (i != end(_images)) {
if (const auto strong = i->second.lock()) {
if (!strong->image) {
strong->load = nullptr;
strong->image.emplace(
std::make_unique<Images::ImageSource>(
std::move(image)));
_session->downloaderTaskFinished().notify();
}
}
}
});
});
raw->load = nullptr;
};
i->second = result;
return result;
}

View File

@ -8,11 +8,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "ui/text/text_isolated_emoji.h"
#include "ui/image/image.h"
#include "base/timer.h"
#include <crl/crl_object_on_queue.h>
class Image;
class HistoryItem;
class DocumentData;
@ -40,6 +40,13 @@ class EmojiImageLoader;
using IsolatedEmoji = Ui::Text::IsolatedEmoji;
struct LargeEmojiImage {
std::optional<Image> image;
FnMut<void()> load;
[[nodiscard]] static QSize Size();
};
class EmojiPack final {
public:
struct Sticker {
@ -61,7 +68,7 @@ public:
void remove(not_null<const HistoryItem*> item);
[[nodiscard]] Sticker stickerForEmoji(const IsolatedEmoji &emoji);
[[nodiscard]] std::shared_ptr<Image> image(EmojiPtr emoji);
[[nodiscard]] std::shared_ptr<LargeEmojiImage> image(EmojiPtr emoji);
private:
class ImageLoader;
@ -85,7 +92,7 @@ private:
base::flat_map<
IsolatedEmoji,
base::flat_set<not_null<HistoryItem*>>> _items;
base::flat_map<EmojiPtr, std::weak_ptr<Image>> _images;
base::flat_map<EmojiPtr, std::weak_ptr<LargeEmojiImage>> _images;
mtpRequestId _requestId = 0;
crl::object_on_queue<details::EmojiImageLoader> _imageLoader;

View File

@ -20,10 +20,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace HistoryView {
namespace {
using EmojiImage = Stickers::LargeEmojiImage;
auto ResolveImages(
not_null<Main::Session*> session,
const Ui::Text::IsolatedEmoji &emoji)
-> std::array<std::shared_ptr<Image>, Ui::Text::kIsolatedEmojiLimit> {
-> std::array<std::shared_ptr<EmojiImage>, Ui::Text::kIsolatedEmojiLimit> {
const auto single = [&](EmojiPtr emoji) {
return emoji ? session->emojiStickersPack().image(emoji) : nullptr;
};
@ -33,7 +35,7 @@ auto ResolveImages(
single(emoji.items[2]) } };
}
auto NonEmpty(const std::array<std::shared_ptr<Image>, Ui::Text::kIsolatedEmojiLimit> &images) {
auto NonEmpty(const std::array<std::shared_ptr<EmojiImage>, Ui::Text::kIsolatedEmojiLimit> &images) {
using namespace rpl::mappers;
return images | ranges::view::filter(_1 != nullptr);
@ -54,7 +56,7 @@ QSize LargeEmoji::size() {
const auto count = ranges::distance(NonEmpty(_images));
Assert(count > 0);
const auto single = _images[0]->size() / cIntRetinaFactor();
const auto single = EmojiImage::Size() / cIntRetinaFactor();
const auto skip = st::largeEmojiSkip - 2 * st::largeEmojiOutline;
const auto inner = count * single.width() + (count - 1) * skip;
const auto &padding = st::largeEmojiPadding;
@ -71,16 +73,18 @@ void LargeEmoji::draw(Painter &p, const QRect &r, bool selected) {
const auto y = r.y() + (r.height() - _size.height()) / 2 + padding.top();
const auto o = Data::FileOrigin();
const auto skip = st::largeEmojiSkip - 2 * st::largeEmojiOutline;
const auto size = EmojiImage::Size() / cIntRetinaFactor();
for (const auto &image : images) {
image->load();
const auto w = image->width() / cIntRetinaFactor();
if (image->loaded()) {
const auto h = image->height() / cIntRetinaFactor();
const auto w = size.width();
if (const auto &prepared = image->image) {
const auto h = size.height();
const auto &c = st::msgStickerOverlay;
const auto pixmap = selected
? image->pixColored(o, c, w, h)
: image->pix(o, w, h);
? prepared->pixColored(o, c, w, h)
: prepared->pix(o, w, h);
p.drawPixmap(x, y, pixmap);
} else if (image->load) {
image->load();
}
x += w + skip;
}

View File

@ -10,15 +10,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/media/history_view_media_unwrapped.h"
#include "ui/text/text_isolated_emoji.h"
class Image;
namespace Data {
struct FileOrigin;
} // namespace Data
namespace Lottie {
class SinglePlayer;
} // namespace Lottie
namespace Stickers {
struct LargeEmojiImage;
} // namespace Stickers
namespace HistoryView {
@ -38,7 +36,7 @@ public:
private:
const not_null<Element*> _parent;
const std::array<
std::shared_ptr<Image>,
std::shared_ptr<Stickers::LargeEmojiImage>,
Ui::Text::kIsolatedEmojiLimit> _images;
QSize _size;