From f876d15eedbce39a445b020b92f45d137952ed2a Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 26 Aug 2022 23:51:49 +0400 Subject: [PATCH] Add some helper wrappers for custom emoji. --- CMakeLists.txt | 2 + ui/effects/round_area_with_shadow.cpp | 6 ++- ui/effects/round_area_with_shadow.h | 3 +- ui/text/text_block.cpp | 4 -- ui/text/text_block.h | 26 +-------- ui/text/text_custom_emoji.cpp | 62 +++++++++++++++++++++ ui/text/text_custom_emoji.h | 78 +++++++++++++++++++++++++++ ui/widgets/input_fields.h | 6 +-- 8 files changed, 152 insertions(+), 35 deletions(-) create mode 100644 ui/text/text_custom_emoji.cpp create mode 100644 ui/text/text_custom_emoji.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c473c1..0488eeb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -153,6 +153,8 @@ PRIVATE ui/text/text.h ui/text/text_block.cpp ui/text/text_block.h + ui/text/text_custom_emoji.cpp + ui/text/text_custom_emoji.h ui/text/text_entity.cpp ui/text/text_entity.h ui/text/text_isolated_emoji.h diff --git a/ui/effects/round_area_with_shadow.cpp b/ui/effects/round_area_with_shadow.cpp index 0c056c5..f1bf71a 100644 --- a/ui/effects/round_area_with_shadow.cpp +++ b/ui/effects/round_area_with_shadow.cpp @@ -103,6 +103,7 @@ ImageSubrect RoundAreaWithShadow::validateOverlayMask( p.setCompositionMode(QPainter::CompositionMode_Source); p.fillRect(QRect(position, maskSize), Qt::transparent); + p.setCompositionMode(QPainter::CompositionMode_SourceOver); auto hq = PainterHighQualityEnabler(p); const auto inner = QRect(position + _inner.topLeft(), innerSize); p.setPen(Qt::NoPen); @@ -198,10 +199,13 @@ void RoundAreaWithShadow::overlayExpandedBorder( QPainter &p, QSize size, float64 expandRatio, - float64 radius, + float64 radiusFrom, + float64 radiusTill, float64 scale) { const auto progress = expandRatio; const auto frame = int(base::SafeRound(progress * (kFramesCount - 1))); + const auto cacheRatio = frame / float64(kFramesCount - 1); + const auto radius = radiusFrom + (radiusTill - radiusFrom) * cacheRatio; const auto twiceRadius = int(base::SafeRound(radius * 2)); const auto innerSize = QSize( std::max(_inner.width(), twiceRadius), diff --git a/ui/effects/round_area_with_shadow.h b/ui/effects/round_area_with_shadow.h index 417f6d4..0edd5be 100644 --- a/ui/effects/round_area_with_shadow.h +++ b/ui/effects/round_area_with_shadow.h @@ -59,7 +59,8 @@ public: QPainter &p, QSize size, float64 expandRatio, - float64 radius, + float64 radiusFrom, + float64 radiusTill, float64 scale); private: diff --git a/ui/text/text_block.cpp b/ui/text/text_block.cpp index 7c6c617..f3d2275 100644 --- a/ui/text/text_block.cpp +++ b/ui/text/text_block.cpp @@ -498,10 +498,6 @@ CustomEmojiBlock::CustomEmojiBlock( } } -int AdjustCustomEmojiSize(int emojiSize) { - return base::SafeRound(emojiSize * 1.12); -} - NewlineBlock::NewlineBlock( const style::font &font, const QString &str, diff --git a/ui/text/text_block.h b/ui/text/text_block.h index a974c42..0580146 100644 --- a/ui/text/text_block.h +++ b/ui/text/text_block.h @@ -6,6 +6,7 @@ // #pragma once +#include "ui/text/text_custom_emoji.h" #include "ui/style/style_core.h" #include "ui/emoji_config.h" @@ -166,29 +167,6 @@ private: }; -struct CustomEmojiPaintContext { - QColor preview; - QSize size; // Required only when scaled = true, for path scaling. - crl::time now = 0; - float64 scale = 0.; - QPoint position; - bool paused = false; - bool scaled = false; -}; - -class CustomEmoji { -public: - virtual ~CustomEmoji() = default; - - [[nodiscard]] virtual QString entityData() = 0; - - using Context = CustomEmojiPaintContext; - virtual void paint(QPainter &p, const Context &context) = 0; - virtual void unload() = 0; - [[nodiscard]] virtual bool ready() = 0; - -}; - class CustomEmojiBlock final : public AbstractBlock { public: CustomEmojiBlock( @@ -210,8 +188,6 @@ private: }; -[[nodiscard]] int AdjustCustomEmojiSize(int emojiSize); - class SkipBlock final : public AbstractBlock { public: SkipBlock( diff --git a/ui/text/text_custom_emoji.cpp b/ui/text/text_custom_emoji.cpp new file mode 100644 index 0000000..0157951 --- /dev/null +++ b/ui/text/text_custom_emoji.cpp @@ -0,0 +1,62 @@ +// 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" + +namespace Ui::Text { + +int AdjustCustomEmojiSize(int emojiSize) { + return base::SafeRound(emojiSize * 1.12); +} + +ShiftedEmoji::ShiftedEmoji( + std::unique_ptr wrapped, + QPoint shift) +: _wrapped(std::move(wrapped)) +, _shift(shift) { +} + +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(); +} + +FirstFrameEmoji::FirstFrameEmoji(std::unique_ptr wrapped) +: _wrapped(std::move(wrapped)) { +} + +QString FirstFrameEmoji::entityData() { + return _wrapped->entityData(); +} + +void FirstFrameEmoji::paint(QPainter &p, const Context &context) { + auto copy = context; + copy.firstFrameOnly = true; + _wrapped->paint(p, copy); +} + +void FirstFrameEmoji::unload() { + _wrapped->unload(); +} + +bool FirstFrameEmoji::ready() { + return _wrapped->ready(); +} + +} // namespace Ui::Text diff --git a/ui/text/text_custom_emoji.h b/ui/text/text_custom_emoji.h new file mode 100644 index 0000000..53d134b --- /dev/null +++ b/ui/text/text_custom_emoji.h @@ -0,0 +1,78 @@ +// 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 +// +#pragma once + +#include +#include +#include + +#include + +class QPainter; + +namespace Ui::Text { + +[[nodiscard]] int AdjustCustomEmojiSize(int emojiSize); + +struct CustomEmojiPaintContext { + QColor preview; + QSize size; // Required only when scaled = true, for path scaling. + crl::time now = 0; + float64 scale = 0.; + QPoint position; + bool firstFrameOnly = false; + bool paused = false; + bool scaled = false; +}; + +class CustomEmoji { +public: + virtual ~CustomEmoji() = default; + + [[nodiscard]] virtual QString entityData() = 0; + + using Context = CustomEmojiPaintContext; + virtual void paint(QPainter &p, const Context &context) = 0; + virtual void unload() = 0; + [[nodiscard]] virtual bool ready() = 0; + +}; + +using CustomEmojiFactory = Fn( + QStringView, + Fn)>; + +class ShiftedEmoji final : public CustomEmoji { +public: + ShiftedEmoji(std::unique_ptr wrapped, QPoint shift); + + QString entityData() override; + void paint(QPainter &p, const Context &context) override; + void unload() override; + bool ready() override; + +private: + const std::unique_ptr _wrapped; + const QPoint _shift; + +}; + +class FirstFrameEmoji final : public CustomEmoji { +public: + explicit FirstFrameEmoji(std::unique_ptr wrapped); + + QString entityData() override; + void paint(QPainter &p, const Context &context) override; + void unload() override; + bool ready() override; + +private: + const std::unique_ptr _wrapped; + +}; + +} // namespace Ui::Text diff --git a/ui/widgets/input_fields.h b/ui/widgets/input_fields.h index 1da7845..cfd3440 100644 --- a/ui/widgets/input_fields.h +++ b/ui/widgets/input_fields.h @@ -10,6 +10,7 @@ #include "ui/rp_widget.h" #include "ui/effects/animations.h" #include "ui/text/text_entity.h" +#include "ui/text/text_custom_emoji.h" #include "styles/style_widgets.h" #include @@ -35,10 +36,6 @@ const auto kMonospaceSequence = QKeySequence("ctrl+shift+m"); const auto kEditLinkSequence = QKeySequence("ctrl+k"); const auto kSpoilerSequence = QKeySequence("ctrl+shift+p"); -using CustomEmojiFactory = Fn( - QStringView, - Fn)>; - class PopupMenu; void InsertEmojiAtCursor(QTextCursor cursor, EmojiPtr emoji); @@ -199,6 +196,7 @@ public: MultiLine, }; using TagList = TextWithTags::Tags; + using CustomEmojiFactory = Text::CustomEmojiFactory; struct MarkdownTag { // With each emoji being QChar::ObjectReplacementCharacter.