Files
tdesktop/Telegram/SourceFiles/ui/text/text_lottie_custom_emoji.cpp
2025-08-30 23:39:36 +03:00

122 lines
2.9 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/text_lottie_custom_emoji.h"
#include "lottie/lottie_icon.h"
#include "ui/text/text_utilities.h"
namespace Ui::Text {
LottieCustomEmoji::LottieCustomEmoji(Lottie::IconDescriptor &&descriptor)
: LottieCustomEmoji(std::move(descriptor), nullptr) {
}
LottieCustomEmoji::LottieCustomEmoji(
Lottie::IconDescriptor &&descriptor,
Fn<void()> repaint)
: _entityData(!descriptor.name.isEmpty()
? descriptor.name
: !descriptor.path.isEmpty()
? descriptor.path
: (Unexpected("LottieCustomEmoji: descriptor.name or descriptor.path"),
QString()))
, _width(descriptor.sizeOverride.width())
, _icon(Lottie::MakeIcon(std::move(descriptor)))
, _repaint(std::move(repaint)) {
if (!_width && _icon && _icon->valid()) {
_width = _icon->width();
startAnimation();
}
}
int LottieCustomEmoji::width() {
return _width;
}
QString LottieCustomEmoji::entityData() {
return _entityData;
}
void LottieCustomEmoji::paint(QPainter &p, const Context &context) {
if (!_icon || !_icon->valid()) {
return;
}
const auto paused = context.paused
|| context.internal.forceFirstFrame
|| context.internal.overrideFirstWithLastFrame;
if (paused) {
const auto frame = context.internal.forceLastFrame
? _icon->framesCount() - 1
: 0;
_icon->jumpTo(frame, _repaint);
} else if (!_icon->animating()) {
startAnimation();
}
_icon->paint(
p,
context.position.x(),
context.position.y(),
context.textColor);
}
void LottieCustomEmoji::unload() {
if (_icon) {
_icon->jumpTo(0, nullptr);
}
}
bool LottieCustomEmoji::ready() {
return _icon && _icon->valid();
}
bool LottieCustomEmoji::readyInDefaultState() {
return _icon && _icon->valid() && _icon->frameIndex() == 0;
}
void LottieCustomEmoji::startAnimation() {
if (!_icon || !_icon->valid() || _icon->framesCount() <= 1) {
return;
}
_icon->animate(
_repaint,
0,
_icon->framesCount() - 1);
}
QString LottieEmojiData(Lottie::IconDescriptor descriptor) {
return !descriptor.name.isEmpty()
? descriptor.name
: !descriptor.path.isEmpty()
? descriptor.path
: QString();
}
TextWithEntities LottieEmoji(Lottie::IconDescriptor descriptor) {
return SingleCustomEmoji(LottieEmojiData(std::move(descriptor)));
}
MarkedContext LottieEmojiContext(Lottie::IconDescriptor descriptor) {
auto customEmojiFactory = [descriptor = std::move(descriptor)](
QStringView data,
const MarkedContext &context
) mutable -> std::unique_ptr<CustomEmoji> {
if (data == LottieEmojiData(descriptor)) {
return std::make_unique<LottieCustomEmoji>(
std::move(descriptor),
context.repaint);
}
return nullptr;
};
return { .customEmojiFactory = std::move(customEmojiFactory) };
}
} // namespace Ui::Text