mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 22:54:01 +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,
|
documentId,
|
||||||
std::make_unique<Ui::CustomEmoji::Instance>(Loading{
|
std::make_unique<Ui::CustomEmoji::Instance>(Loading{
|
||||||
factory(),
|
factory(),
|
||||||
Ui::CustomEmoji::Preview()
|
prepareNonExactPreview(documentId, tag)
|
||||||
}, std::move(repaint))).first;
|
}, std::move(repaint))).first;
|
||||||
}
|
}
|
||||||
return std::make_unique<Ui::CustomEmoji::Object>(
|
return std::make_unique<Ui::CustomEmoji::Object>(
|
||||||
|
@ -388,6 +388,27 @@ std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
|
||||||
std::move(update));
|
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(
|
std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
|
||||||
QStringView data,
|
QStringView data,
|
||||||
Fn<void()> update,
|
Fn<void()> update,
|
||||||
|
|
|
@ -78,6 +78,9 @@ private:
|
||||||
void invokeRepaints();
|
void invokeRepaints();
|
||||||
void requestSetFor(not_null<DocumentData*> document);
|
void requestSetFor(not_null<DocumentData*> document);
|
||||||
|
|
||||||
|
[[nodiscard]] Ui::CustomEmoji::Preview prepareNonExactPreview(
|
||||||
|
DocumentId documentId,
|
||||||
|
SizeTag tag) const;
|
||||||
template <typename LoaderFactory>
|
template <typename LoaderFactory>
|
||||||
[[nodiscard]] std::unique_ptr<Ui::Text::CustomEmoji> create(
|
[[nodiscard]] std::unique_ptr<Ui::Text::CustomEmoji> create(
|
||||||
DocumentId documentId,
|
DocumentId documentId,
|
||||||
|
|
|
@ -37,22 +37,38 @@ Preview::Preview(QPainterPath path, float64 scale)
|
||||||
: _data(ScaledPath{ std::move(path), 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) {
|
void Preview::paint(QPainter &p, int x, int y, const QColor &preview) {
|
||||||
if (const auto path = std::get_if<ScaledPath>(&_data)) {
|
if (const auto path = std::get_if<ScaledPath>(&_data)) {
|
||||||
paintPath(p, x, y, preview, *path);
|
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 factor = style::DevicePixelRatio();
|
||||||
const auto width = image->width() / factor;
|
const auto width = data.width() / factor;
|
||||||
const auto height = image->height() / factor;
|
const auto height = data.height() / factor;
|
||||||
p.drawImage(QRect(x, y, width, height), *image);
|
p.drawImage(QRect(x, y, width, height), data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Preview::image() const {
|
bool Preview::isImage() const {
|
||||||
return v::is<QImage>(_data);
|
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(
|
void Preview::paintPath(
|
||||||
|
@ -190,7 +206,7 @@ Preview Cache::makePreview() const {
|
||||||
Expects(_frames > 0);
|
Expects(_frames > 0);
|
||||||
|
|
||||||
const auto first = frame(0);
|
const auto first = frame(0);
|
||||||
return { first.image->copy(first.source) };
|
return { first.image->copy(first.source), true };
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cache::reserve(int frames) {
|
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);
|
return _cache.paintCurrentFrame(p, x, y, now);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Preview Cached::makePreview() const {
|
||||||
|
return _cache.makePreview();
|
||||||
|
}
|
||||||
|
|
||||||
Loading Cached::unload() {
|
Loading Cached::unload() {
|
||||||
return Loading(_unloader(), _cache.makePreview());
|
return Loading(_unloader(), makePreview());
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::Renderer(RendererDescriptor &&descriptor)
|
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.paint(p, x, y, preview);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Preview Loading::imagePreview() const {
|
||||||
|
return _preview.isImage() ? _preview : Preview();
|
||||||
|
}
|
||||||
|
|
||||||
void Loading::cancel() {
|
void Loading::cancel() {
|
||||||
_loader->cancel();
|
_loader->cancel();
|
||||||
invalidate_weak_ptrs(this);
|
invalidate_weak_ptrs(this);
|
||||||
|
@ -564,7 +588,7 @@ void Instance::paint(
|
||||||
if (!result.painted) {
|
if (!result.painted) {
|
||||||
caching->preview.paint(p, x, y, preview);
|
caching->preview.paint(p, x, y, preview);
|
||||||
} else {
|
} else {
|
||||||
if (!caching->preview.image()) {
|
if (!caching->preview.isExactImage()) {
|
||||||
caching->preview = caching->renderer->makePreview();
|
caching->preview = caching->renderer->makePreview();
|
||||||
}
|
}
|
||||||
if (result.next > now) {
|
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() {
|
void Instance::repaint() {
|
||||||
for (const auto &object : _usage) {
|
for (const auto &object : _usage) {
|
||||||
object->repaint();
|
object->repaint();
|
||||||
|
|
|
@ -24,11 +24,13 @@ namespace Ui::CustomEmoji {
|
||||||
class Preview final {
|
class Preview final {
|
||||||
public:
|
public:
|
||||||
Preview() = default;
|
Preview() = default;
|
||||||
Preview(QImage image);
|
Preview(QImage image, bool exact);
|
||||||
Preview(QPainterPath path, float64 scale);
|
Preview(QPainterPath path, float64 scale);
|
||||||
|
|
||||||
void paint(QPainter &p, int x, int y, const QColor &preview);
|
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 {
|
[[nodiscard]] explicit operator bool() const {
|
||||||
return !v::is_null(_data);
|
return !v::is_null(_data);
|
||||||
|
@ -39,6 +41,10 @@ private:
|
||||||
QPainterPath path;
|
QPainterPath path;
|
||||||
float64 scale = 1.;
|
float64 scale = 1.;
|
||||||
};
|
};
|
||||||
|
struct Image {
|
||||||
|
QImage data;
|
||||||
|
bool exact = false;
|
||||||
|
};
|
||||||
|
|
||||||
void paintPath(
|
void paintPath(
|
||||||
QPainter &p,
|
QPainter &p,
|
||||||
|
@ -47,7 +53,7 @@ private:
|
||||||
const QColor &preview,
|
const QColor &preview,
|
||||||
const ScaledPath &path);
|
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);
|
Cache cache);
|
||||||
|
|
||||||
[[nodiscard]] QString entityData() const;
|
[[nodiscard]] QString entityData() const;
|
||||||
|
[[nodiscard]] Preview makePreview() const;
|
||||||
PaintFrameResult paint(QPainter &p, int x, int y, crl::time now);
|
PaintFrameResult paint(QPainter &p, int x, int y, crl::time now);
|
||||||
[[nodiscard]] Loading unload();
|
[[nodiscard]] Loading unload();
|
||||||
|
|
||||||
|
@ -194,6 +200,7 @@ public:
|
||||||
void load(Fn<void(Loader::LoadResult)> done);
|
void load(Fn<void(Loader::LoadResult)> done);
|
||||||
[[nodiscard]] bool loading() const;
|
[[nodiscard]] bool loading() const;
|
||||||
void paint(QPainter &p, int x, int y, const QColor &preview);
|
void paint(QPainter &p, int x, int y, const QColor &preview);
|
||||||
|
[[nodiscard]] Preview imagePreview() const;
|
||||||
void cancel();
|
void cancel();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -224,6 +231,7 @@ public:
|
||||||
crl::time now,
|
crl::time now,
|
||||||
const QColor &preview,
|
const QColor &preview,
|
||||||
bool paused);
|
bool paused);
|
||||||
|
[[nodiscard]] Preview imagePreview() const;
|
||||||
|
|
||||||
void incrementUsage(not_null<Object*> object);
|
void incrementUsage(not_null<Object*> object);
|
||||||
void decrementUsage(not_null<Object*> object);
|
void decrementUsage(not_null<Object*> object);
|
||||||
|
|
Loading…
Add table
Reference in a new issue