init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
This commit is contained in:
235
Telegram/lib_ui/ui/text/text_custom_emoji.cpp
Normal file
235
Telegram/lib_ui/ui/text/text_custom_emoji.cpp
Normal file
@@ -0,0 +1,235 @@
|
||||
// This file is part of Desktop App Toolkit,
|
||||
// a set of libraries for developing nice desktop applications.
|
||||
//
|
||||
// For license and copyright information please follow this link:
|
||||
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
||||
//
|
||||
#include "ui/text/text_custom_emoji.h"
|
||||
|
||||
#include "ui/style/style_core.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/text/text.h"
|
||||
#include "ui/emoji_config.h"
|
||||
|
||||
namespace Ui::Emoji {
|
||||
|
||||
int GetCustomSizeNormal() {
|
||||
const auto full = GetSizeNormal();
|
||||
const auto esize = full / style::DevicePixelRatio();
|
||||
return Ui::Text::AdjustCustomEmojiSize(esize);
|
||||
}
|
||||
|
||||
int GetCustomSizeLarge() {
|
||||
const auto full = GetSizeLarge();
|
||||
const auto esize = full / style::DevicePixelRatio();
|
||||
return Ui::Text::AdjustCustomEmojiSize(esize);
|
||||
}
|
||||
|
||||
int GetCustomSkipNormal() {
|
||||
const auto full = GetSizeNormal();
|
||||
const auto esize = full / style::DevicePixelRatio();
|
||||
return (esize - GetCustomSizeNormal()) / 2;
|
||||
}
|
||||
|
||||
int GetCustomSkipLarge() {
|
||||
const auto full = GetSizeLarge();
|
||||
const auto esize = full / style::DevicePixelRatio();
|
||||
return (esize - GetCustomSizeLarge()) / 2;
|
||||
}
|
||||
|
||||
} // namespace Ui::Emoji
|
||||
|
||||
namespace Ui::Text {
|
||||
|
||||
int AdjustCustomEmojiSize(int emojiSize) {
|
||||
return base::SafeRound(emojiSize * 1.12);
|
||||
}
|
||||
|
||||
ShiftedEmoji::ShiftedEmoji(
|
||||
std::unique_ptr<Ui::Text::CustomEmoji> wrapped,
|
||||
QPoint shift)
|
||||
: _wrapped(std::move(wrapped))
|
||||
, _shift(shift) {
|
||||
}
|
||||
|
||||
int ShiftedEmoji::width() {
|
||||
return _wrapped->width();
|
||||
}
|
||||
|
||||
QString ShiftedEmoji::entityData() {
|
||||
return _wrapped->entityData();
|
||||
}
|
||||
|
||||
void ShiftedEmoji::paint(QPainter &p, const Context &context) {
|
||||
auto copy = context;
|
||||
copy.position += _shift;
|
||||
_wrapped->paint(p, copy);
|
||||
}
|
||||
|
||||
void ShiftedEmoji::unload() {
|
||||
_wrapped->unload();
|
||||
}
|
||||
|
||||
bool ShiftedEmoji::ready() {
|
||||
return _wrapped->ready();
|
||||
}
|
||||
|
||||
bool ShiftedEmoji::readyInDefaultState() {
|
||||
return _wrapped->readyInDefaultState();
|
||||
}
|
||||
|
||||
FirstFrameEmoji::FirstFrameEmoji(std::unique_ptr<CustomEmoji> wrapped)
|
||||
: _wrapped(std::move(wrapped)) {
|
||||
}
|
||||
|
||||
int FirstFrameEmoji::width() {
|
||||
return _wrapped->width();
|
||||
}
|
||||
|
||||
QString FirstFrameEmoji::entityData() {
|
||||
return _wrapped->entityData();
|
||||
}
|
||||
|
||||
void FirstFrameEmoji::paint(QPainter &p, const Context &context) {
|
||||
const auto was = context.internal.forceFirstFrame;
|
||||
context.internal.forceFirstFrame = true;
|
||||
_wrapped->paint(p, context);
|
||||
context.internal.forceFirstFrame = was;
|
||||
}
|
||||
|
||||
void FirstFrameEmoji::unload() {
|
||||
_wrapped->unload();
|
||||
}
|
||||
|
||||
bool FirstFrameEmoji::ready() {
|
||||
return _wrapped->ready();
|
||||
}
|
||||
|
||||
bool FirstFrameEmoji::readyInDefaultState() {
|
||||
return _wrapped->readyInDefaultState();
|
||||
}
|
||||
|
||||
LimitedLoopsEmoji::LimitedLoopsEmoji(
|
||||
std::unique_ptr<CustomEmoji> wrapped,
|
||||
int limit,
|
||||
bool stopOnLast)
|
||||
: _wrapped(std::move(wrapped))
|
||||
, _limit(limit)
|
||||
, _stopOnLast(stopOnLast) {
|
||||
}
|
||||
|
||||
int LimitedLoopsEmoji::width() {
|
||||
return _wrapped->width();
|
||||
}
|
||||
|
||||
QString LimitedLoopsEmoji::entityData() {
|
||||
return _wrapped->entityData();
|
||||
}
|
||||
|
||||
void LimitedLoopsEmoji::paint(QPainter &p, const Context &context) {
|
||||
if (_played < _limit) {
|
||||
if (_wrapped->readyInDefaultState()) {
|
||||
if (_inLoop) {
|
||||
_inLoop = false;
|
||||
++_played;
|
||||
}
|
||||
} else if (_wrapped->ready()) {
|
||||
_inLoop = true;
|
||||
}
|
||||
}
|
||||
if (_played == _limit) {
|
||||
const auto wasFirst = context.internal.forceFirstFrame;
|
||||
const auto wasLast = context.internal.forceLastFrame;
|
||||
(_stopOnLast
|
||||
? context.internal.forceLastFrame
|
||||
: context.internal.forceFirstFrame) = true;
|
||||
_wrapped->paint(p, context);
|
||||
context.internal.forceFirstFrame = wasFirst;
|
||||
context.internal.forceLastFrame = wasLast;
|
||||
} else if (_played + 1 == _limit && _inLoop && _stopOnLast) {
|
||||
const auto wasLast = context.internal.overrideFirstWithLastFrame;
|
||||
context.internal.overrideFirstWithLastFrame = true;
|
||||
_wrapped->paint(p, context);
|
||||
context.internal.overrideFirstWithLastFrame = wasLast;
|
||||
} else {
|
||||
_wrapped->paint(p, context);
|
||||
}
|
||||
}
|
||||
|
||||
void LimitedLoopsEmoji::unload() {
|
||||
_wrapped->unload();
|
||||
_inLoop = false;
|
||||
_played = 0;
|
||||
}
|
||||
|
||||
bool LimitedLoopsEmoji::ready() {
|
||||
return _wrapped->ready();
|
||||
}
|
||||
|
||||
bool LimitedLoopsEmoji::readyInDefaultState() {
|
||||
return _wrapped->readyInDefaultState();
|
||||
}
|
||||
|
||||
std::unique_ptr<CustomEmoji> MakeCustomEmoji(
|
||||
QStringView data,
|
||||
const MarkedContext &context) {
|
||||
if (auto simple = TryMakeSimpleEmoji(data)) {
|
||||
return simple;
|
||||
} else if (const auto &factory = context.customEmojiFactory) {
|
||||
return factory(data, context);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PaletteDependentCustomEmoji::PaletteDependentCustomEmoji(
|
||||
Fn<QImage()> factory,
|
||||
QString entity,
|
||||
QMargins padding)
|
||||
: _factory(std::move(factory))
|
||||
, _entity(std::move(entity))
|
||||
, _padding(padding) {
|
||||
}
|
||||
|
||||
int PaletteDependentCustomEmoji::width() {
|
||||
if (_frame.isNull()) {
|
||||
validateFrame();
|
||||
}
|
||||
return _padding.left()
|
||||
+ (_frame.width() / style::DevicePixelRatio())
|
||||
+ _padding.right();
|
||||
}
|
||||
|
||||
QString PaletteDependentCustomEmoji::entityData() {
|
||||
return _entity;
|
||||
}
|
||||
|
||||
void PaletteDependentCustomEmoji::paint(
|
||||
QPainter &p,
|
||||
const Context &context) {
|
||||
validateFrame();
|
||||
p.drawImage(
|
||||
context.position + QPoint(_padding.left(), _padding.top()),
|
||||
_frame);
|
||||
}
|
||||
|
||||
void PaletteDependentCustomEmoji::unload() {
|
||||
_frame = QImage();
|
||||
}
|
||||
|
||||
bool PaletteDependentCustomEmoji::ready() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PaletteDependentCustomEmoji::readyInDefaultState() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void PaletteDependentCustomEmoji::validateFrame() {
|
||||
const auto version = style::PaletteVersion();
|
||||
if (_frame.isNull() || _paletteVersion != version) {
|
||||
_paletteVersion = version;
|
||||
_frame = _factory();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Ui::Text
|
||||
Reference in New Issue
Block a user