mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Use non-exact image previews if available.
This commit is contained in:
parent
c51837cfdf
commit
31bb08068b
4 changed files with 82 additions and 15 deletions
|
@ -380,7 +380,7 @@ std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
|
|||
documentId,
|
||||
std::make_unique<Ui::CustomEmoji::Instance>(Loading{
|
||||
factory(),
|
||||
Ui::CustomEmoji::Preview()
|
||||
prepareNonExactPreview(documentId, tag)
|
||||
}, std::move(repaint))).first;
|
||||
}
|
||||
return std::make_unique<Ui::CustomEmoji::Object>(
|
||||
|
@ -388,6 +388,27 @@ std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
|
|||
std::move(update));
|
||||
}
|
||||
|
||||
Ui::CustomEmoji::Preview CustomEmojiManager::prepareNonExactPreview(
|
||||
DocumentId documentId,
|
||||
SizeTag tag) const {
|
||||
const auto &other = _instances[1 - SizeIndex(tag)];
|
||||
const auto j = other.find(documentId);
|
||||
if (j == end(other)) {
|
||||
return {};
|
||||
} else if (const auto nonExact = j->second->imagePreview()) {
|
||||
const auto size = SizeFromTag(tag);
|
||||
return {
|
||||
nonExact.image().scaled(
|
||||
size,
|
||||
size,
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation),
|
||||
false,
|
||||
};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
|
||||
QStringView data,
|
||||
Fn<void()> update,
|
||||
|
|
|
@ -78,6 +78,9 @@ private:
|
|||
void invokeRepaints();
|
||||
void requestSetFor(not_null<DocumentData*> document);
|
||||
|
||||
[[nodiscard]] Ui::CustomEmoji::Preview prepareNonExactPreview(
|
||||
DocumentId documentId,
|
||||
SizeTag tag) const;
|
||||
template <typename LoaderFactory>
|
||||
[[nodiscard]] std::unique_ptr<Ui::Text::CustomEmoji> create(
|
||||
DocumentId documentId,
|
||||
|
|
|
@ -37,22 +37,38 @@ Preview::Preview(QPainterPath path, float64 scale)
|
|||
: _data(ScaledPath{ std::move(path), scale }) {
|
||||
}
|
||||
|
||||
Preview::Preview(QImage image) : _data(std::move(image)) {
|
||||
Preview::Preview(QImage image, bool exact)
|
||||
: _data(Image{ .data = std::move(image), .exact = exact }) {
|
||||
}
|
||||
|
||||
void Preview::paint(QPainter &p, int x, int y, const QColor &preview) {
|
||||
if (const auto path = std::get_if<ScaledPath>(&_data)) {
|
||||
paintPath(p, x, y, preview, *path);
|
||||
} else if (const auto image = std::get_if<QImage>(&_data)) {
|
||||
} else if (const auto image = std::get_if<Image>(&_data)) {
|
||||
const auto &data = image->data;
|
||||
const auto factor = style::DevicePixelRatio();
|
||||
const auto width = image->width() / factor;
|
||||
const auto height = image->height() / factor;
|
||||
p.drawImage(QRect(x, y, width, height), *image);
|
||||
const auto width = data.width() / factor;
|
||||
const auto height = data.height() / factor;
|
||||
p.drawImage(QRect(x, y, width, height), data);
|
||||
}
|
||||
}
|
||||
|
||||
bool Preview::image() const {
|
||||
return v::is<QImage>(_data);
|
||||
bool Preview::isImage() const {
|
||||
return v::is<Image>(_data);
|
||||
}
|
||||
|
||||
bool Preview::isExactImage() const {
|
||||
if (const auto image = std::get_if<Image>(&_data)) {
|
||||
return image->exact;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QImage Preview::image() const {
|
||||
if (const auto image = std::get_if<Image>(&_data)) {
|
||||
return image->data;
|
||||
}
|
||||
return QImage();
|
||||
}
|
||||
|
||||
void Preview::paintPath(
|
||||
|
@ -190,7 +206,7 @@ Preview Cache::makePreview() const {
|
|||
Expects(_frames > 0);
|
||||
|
||||
const auto first = frame(0);
|
||||
return { first.image->copy(first.source) };
|
||||
return { first.image->copy(first.source), true };
|
||||
}
|
||||
|
||||
void Cache::reserve(int frames) {
|
||||
|
@ -349,8 +365,12 @@ PaintFrameResult Cached::paint(QPainter &p, int x, int y, crl::time now) {
|
|||
return _cache.paintCurrentFrame(p, x, y, now);
|
||||
}
|
||||
|
||||
Preview Cached::makePreview() const {
|
||||
return _cache.makePreview();
|
||||
}
|
||||
|
||||
Loading Cached::unload() {
|
||||
return Loading(_unloader(), _cache.makePreview());
|
||||
return Loading(_unloader(), makePreview());
|
||||
}
|
||||
|
||||
Renderer::Renderer(RendererDescriptor &&descriptor)
|
||||
|
@ -516,6 +536,10 @@ void Loading::paint(QPainter &p, int x, int y, const QColor &preview) {
|
|||
_preview.paint(p, x, y, preview);
|
||||
}
|
||||
|
||||
Preview Loading::imagePreview() const {
|
||||
return _preview.isImage() ? _preview : Preview();
|
||||
}
|
||||
|
||||
void Loading::cancel() {
|
||||
_loader->cancel();
|
||||
invalidate_weak_ptrs(this);
|
||||
|
@ -564,7 +588,7 @@ void Instance::paint(
|
|||
if (!result.painted) {
|
||||
caching->preview.paint(p, x, y, preview);
|
||||
} else {
|
||||
if (!caching->preview.image()) {
|
||||
if (!caching->preview.isExactImage()) {
|
||||
caching->preview = caching->renderer->makePreview();
|
||||
}
|
||||
if (result.next > now) {
|
||||
|
@ -582,6 +606,17 @@ void Instance::paint(
|
|||
}
|
||||
}
|
||||
|
||||
Preview Instance::imagePreview() const {
|
||||
if (const auto loading = std::get_if<Loading>(&_state)) {
|
||||
return loading->imagePreview();
|
||||
} else if (const auto caching = std::get_if<Caching>(&_state)) {
|
||||
return caching->preview.isImage() ? caching->preview : Preview();
|
||||
} else if (const auto cached = std::get_if<Cached>(&_state)) {
|
||||
return cached->makePreview();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void Instance::repaint() {
|
||||
for (const auto &object : _usage) {
|
||||
object->repaint();
|
||||
|
|
|
@ -24,11 +24,13 @@ namespace Ui::CustomEmoji {
|
|||
class Preview final {
|
||||
public:
|
||||
Preview() = default;
|
||||
Preview(QImage image);
|
||||
Preview(QImage image, bool exact);
|
||||
Preview(QPainterPath path, float64 scale);
|
||||
|
||||
void paint(QPainter &p, int x, int y, const QColor &preview);
|
||||
[[nodiscard]] bool image() const;
|
||||
[[nodiscard]] bool isImage() const;
|
||||
[[nodiscard]] bool isExactImage() const;
|
||||
[[nodiscard]] QImage image() const;
|
||||
|
||||
[[nodiscard]] explicit operator bool() const {
|
||||
return !v::is_null(_data);
|
||||
|
@ -39,6 +41,10 @@ private:
|
|||
QPainterPath path;
|
||||
float64 scale = 1.;
|
||||
};
|
||||
struct Image {
|
||||
QImage data;
|
||||
bool exact = false;
|
||||
};
|
||||
|
||||
void paintPath(
|
||||
QPainter &p,
|
||||
|
@ -47,7 +53,7 @@ private:
|
|||
const QColor &preview,
|
||||
const ScaledPath &path);
|
||||
|
||||
std::variant<v::null_t, ScaledPath, QImage> _data;
|
||||
std::variant<v::null_t, ScaledPath, Image> _data;
|
||||
|
||||
};
|
||||
|
||||
|
@ -116,7 +122,7 @@ public:
|
|||
Cache cache);
|
||||
|
||||
[[nodiscard]] QString entityData() const;
|
||||
|
||||
[[nodiscard]] Preview makePreview() const;
|
||||
PaintFrameResult paint(QPainter &p, int x, int y, crl::time now);
|
||||
[[nodiscard]] Loading unload();
|
||||
|
||||
|
@ -194,6 +200,7 @@ public:
|
|||
void load(Fn<void(Loader::LoadResult)> done);
|
||||
[[nodiscard]] bool loading() const;
|
||||
void paint(QPainter &p, int x, int y, const QColor &preview);
|
||||
[[nodiscard]] Preview imagePreview() const;
|
||||
void cancel();
|
||||
|
||||
private:
|
||||
|
@ -224,6 +231,7 @@ public:
|
|||
crl::time now,
|
||||
const QColor &preview,
|
||||
bool paused);
|
||||
[[nodiscard]] Preview imagePreview() const;
|
||||
|
||||
void incrementUsage(not_null<Object*> object);
|
||||
void decrementUsage(not_null<Object*> object);
|
||||
|
|
Loading…
Add table
Reference in a new issue