2
0
mirror of https://github.com/telegramdesktop/tdesktop synced 2025-08-27 20:57:32 +00:00
tdesktop/Telegram/SourceFiles/ui/text/custom_emoji_instance.cpp

207 lines
4.3 KiB
C++

/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "ui/text/custom_emoji_instance.h"
class QPainter;
namespace Ui::CustomEmoji {
Preview::Preview(QPainterPath path, float64 scale)
: _data(ScaledPath{ std::move(path), scale }) {
}
Preview::Preview(QImage image) : _data(std::move(image)) {
}
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)) {
p.drawImage(x, y, *image);
}
}
void Preview::paintPath(
QPainter &p,
int x,
int y,
const QColor &preview,
const ScaledPath &path) {
auto hq = PainterHighQualityEnabler(p);
p.setBrush(preview);
p.setPen(Qt::NoPen);
const auto scale = path.scale;
const auto required = (scale != 1.);
if (required) {
p.save();
}
p.translate(x, y);
if (required) {
p.scale(scale, scale);
}
p.drawPath(path.path);
if (required) {
p.restore();
} else {
p.translate(-x, -y);
}
}
Cache::Cache(QSize size) : _size(size) {
}
int Cache::frames() const {
return _frames;
}
QImage Cache::frame(int index) const {
return QImage();
}
void Cache::reserve(int frames) {
}
Cached::Cached(std::unique_ptr<Unloader> unloader, Cache cache)
: _unloader(std::move(unloader))
, _cache(cache) {
}
void Cached::paint(QPainter &p, int x, int y) {
p.drawImage(x, y, _cache.frame(0));
}
Loading Cached::unload() {
return Loading(_unloader->unload(), Preview(_cache.frame(0)));
}
void Cacher::reserve(int frames) {
_cache.reserve(frames);
}
void Cacher::add(crl::time duration, QImage frame) {
}
Cache Cacher::takeCache() {
return std::move(_cache);
}
Caching::Caching(std::unique_ptr<Cacher> cacher, Preview preview)
: _cacher(std::move(cacher))
, _preview(std::move(preview)) {
}
void Caching::paint(QPainter &p, int x, int y, const QColor &preview) {
if (!_cacher->paint(p, x, y)) {
_preview.paint(p, x, y, preview);
}
}
std::optional<Cached> Caching::ready() {
return _cacher->ready();
}
Loading Caching::cancel() {
return Loading(_cacher->cancel(), std::move(_preview));
}
Loading::Loading(std::unique_ptr<Loader> loader, Preview preview)
: _loader(std::move(loader))
, _preview(std::move(preview)) {
}
void Loading::load(Fn<void(Caching)> done) {
_loader->load(crl::guard(this, std::move(done)));
}
void Loading::paint(QPainter &p, int x, int y, const QColor &preview) {
if (!_preview) {
if (auto preview = _loader->preview()) {
_preview = std::move(preview);
}
}
_preview.paint(p, x, y, preview);
}
void Loading::cancel() {
_loader->cancel();
invalidate_weak_ptrs(this);
}
Instance::Instance(const QString &entityData, Loading loading)
: _state(std::move(loading))
, _entityData(entityData) {
}
QString Instance::entityData() const {
return _entityData;
}
void Instance::paint(QPainter &p, int x, int y, const QColor &preview) {
if (const auto loading = std::get_if<Loading>(&_state)) {
loading->paint(p, x, y, preview);
loading->load([=](Caching caching) {
_state = std::move(caching);
});
} else if (const auto caching = std::get_if<Caching>(&_state)) {
caching->paint(p, x, y, preview);
if (auto cached = caching->ready()) {
_state = std::move(*cached);
}
} else if (const auto cached = std::get_if<Cached>(&_state)) {
cached->paint(p, x, y);
}
}
void Instance::incrementUsage() {
++_usage;
}
void Instance::decrementUsage() {
Expects(_usage > 0);
if (--_usage > 0) {
return;
}
if (const auto loading = std::get_if<Loading>(&_state)) {
loading->cancel();
} else if (const auto caching = std::get_if<Caching>(&_state)) {
_state = caching->cancel();
} else if (const auto cached = std::get_if<Cached>(&_state)) {
_state = cached->unload();
}
}
Object::Object(not_null<Instance*> instance)
: _instance(instance) {
}
Object::~Object() {
unload();
}
QString Object::entityData() {
return _instance->entityData();
}
void Object::paint(QPainter &p, int x, int y, const QColor &preview) {
if (!_using) {
_using = true;
_instance->incrementUsage();
}
_instance->paint(p, x, y, preview);
}
void Object::unload() {
if (_using) {
_using = false;
_instance->decrementUsage();
}
}
} // namespace Ui::CustomEmoji