Support colored custom emoji.
This commit is contained in:
parent
6dc6309269
commit
51657b3c8a
3 changed files with 54 additions and 10 deletions
|
|
@ -37,6 +37,25 @@ void PaintScaledImage(
|
|||
const QRect &target,
|
||||
const Cache::Frame &frame,
|
||||
const Context &context) {
|
||||
const auto colored = context.colored;
|
||||
const auto cache = colored ? &colored->cache : nullptr;
|
||||
auto q = std::optional<QPainter>();
|
||||
if (colored) {
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
if (cache->width() < target.width() * ratio
|
||||
|| cache->height() < target.height() * ratio) {
|
||||
colored->cache = QImage(
|
||||
std::max(cache->width(), target.width() * ratio),
|
||||
std::max(cache->height(), target.height() * ratio),
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
cache->setDevicePixelRatio(ratio);
|
||||
}
|
||||
q.emplace(cache);
|
||||
q->setCompositionMode(QPainter::CompositionMode_Source);
|
||||
q->fillRect(QRect(QPoint(), target.size()), Qt::transparent);
|
||||
q->translate(-target.topLeft());
|
||||
}
|
||||
const auto to = q ? &*q : &p;
|
||||
if (context.scaled) {
|
||||
const auto sx = anim::interpolate(
|
||||
target.width() / 2,
|
||||
|
|
@ -47,14 +66,21 @@ void PaintScaledImage(
|
|||
: anim::interpolate(target.height() / 2, 0, context.scale);
|
||||
const auto scaled = target.marginsRemoved({ sx, sy, sx, sy });
|
||||
if (frame.source.isNull()) {
|
||||
p.drawImage(scaled, *frame.image);
|
||||
to->drawImage(scaled, *frame.image);
|
||||
} else {
|
||||
p.drawImage(scaled, *frame.image, frame.source);
|
||||
to->drawImage(scaled, *frame.image, frame.source);
|
||||
}
|
||||
} else if (frame.source.isNull()) {
|
||||
p.drawImage(target, *frame.image);
|
||||
to->drawImage(target, *frame.image);
|
||||
} else {
|
||||
p.drawImage(target, *frame.image, frame.source);
|
||||
to->drawImage(target, *frame.image, frame.source);
|
||||
}
|
||||
if (q) {
|
||||
q.reset();
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
const auto source = QRect(QPoint(), target.size() * ratio);
|
||||
style::colorizeImage(*cache, colored->color, cache, source);
|
||||
p.drawImage(target, *cache, source);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -631,6 +657,9 @@ QString Instance::entityData() const {
|
|||
}
|
||||
|
||||
void Instance::paint(QPainter &p, const Context &context) {
|
||||
const auto colored = (context.colored && !_colored)
|
||||
? base::take(context.colored)
|
||||
: nullptr;
|
||||
v::match(_state, [&](Loading &state) {
|
||||
state.paint(p, context);
|
||||
load(state);
|
||||
|
|
@ -655,6 +684,9 @@ void Instance::paint(QPainter &p, const Context &context) {
|
|||
_repaintLater(this, { result.next, result.duration });
|
||||
}
|
||||
});
|
||||
if (colored) {
|
||||
context.colored = colored;
|
||||
}
|
||||
}
|
||||
|
||||
bool Instance::ready() {
|
||||
|
|
@ -730,6 +762,15 @@ void Instance::updatePreview(Preview preview) {
|
|||
}, [](const Cached &) {});
|
||||
}
|
||||
|
||||
void Instance::setColored() {
|
||||
if (!_colored) {
|
||||
_colored = true;
|
||||
if (ready()) {
|
||||
_repaintLater(this, { .when = crl::now() + 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Instance::repaint() {
|
||||
for (const auto &object : _usage) {
|
||||
object->repaint();
|
||||
|
|
|
|||
|
|
@ -234,6 +234,7 @@ public:
|
|||
[[nodiscard]] bool hasImagePreview() const;
|
||||
[[nodiscard]] Preview imagePreview() const;
|
||||
void updatePreview(Preview preview);
|
||||
void setColored();
|
||||
|
||||
void incrementUsage(not_null<Object*> object);
|
||||
void decrementUsage(not_null<Object*> object);
|
||||
|
|
@ -246,15 +247,10 @@ private:
|
|||
std::variant<Loading, Caching, Cached> _state;
|
||||
base::flat_set<not_null<Object*>> _usage;
|
||||
Fn<void(not_null<Instance*> that, RepaintRequest)> _repaintLater;
|
||||
bool _colored = false;
|
||||
|
||||
};
|
||||
|
||||
class Delegate {
|
||||
public:
|
||||
[[nodiscard]] virtual bool paused() = 0;
|
||||
virtual ~Delegate() = default;
|
||||
};
|
||||
|
||||
class Object final : public Ui::Text::CustomEmoji {
|
||||
public:
|
||||
Object(not_null<Instance*> instance, Fn<void()> repaint);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <QtGui/QColor>
|
||||
#include <QtGui/QImage>
|
||||
#include <QtCore/QSize>
|
||||
#include <QtCore/QPoint>
|
||||
|
||||
|
|
@ -18,8 +19,14 @@ namespace Ui::Text {
|
|||
|
||||
[[nodiscard]] int AdjustCustomEmojiSize(int emojiSize);
|
||||
|
||||
struct CustomEmojiColored {
|
||||
QColor color;
|
||||
QImage cache;
|
||||
};
|
||||
|
||||
struct CustomEmojiPaintContext {
|
||||
QColor preview;
|
||||
mutable CustomEmojiColored *colored = nullptr;
|
||||
QSize size; // Required only when scaled = true, for path scaling.
|
||||
crl::time now = 0;
|
||||
float64 scale = 0.;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue