| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- // 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 "ui/text/text_custom_emoji.h"
- #include "base/weak_ptr.h"
- #include "base/bytes.h"
- #include "base/timer.h"
- #include <QtGui/QPainterPath>
- class QColor;
- class QPainter;
- namespace style {
- struct IconEmoji;
- } // namespace style
- namespace Ui {
- class DynamicImage;
- class FrameGenerator;
- } // namespace Ui
- namespace Ui::CustomEmoji {
- using Context = Ui::Text::CustomEmoji::Context;
- [[nodiscard]] QColor PreviewColorFromTextColor(QColor color);
- class Preview final {
- public:
- Preview() = default;
- Preview(QImage image, bool exact);
- Preview(QPainterPath path, float64 scale);
- void paint(QPainter &p, const Context &context);
- [[nodiscard]] bool isImage() const;
- [[nodiscard]] bool isExactImage() const;
- [[nodiscard]] QImage image() const;
- [[nodiscard]] explicit operator bool() const {
- return !v::is_null(_data);
- }
- private:
- struct ScaledPath {
- QPainterPath path;
- float64 scale = 1.;
- };
- struct Image {
- QImage data;
- bool exact = false;
- };
- void paintPath(
- QPainter &p,
- const Context &context,
- const ScaledPath &path);
- std::variant<v::null_t, ScaledPath, Image> _data;
- };
- struct PaintFrameResult {
- bool painted = false;
- crl::time next = 0;
- crl::time duration = 0;
- };
- class Cache final {
- public:
- Cache(int size);
- struct Frame {
- not_null<const QImage*> image;
- QRect source;
- };
- [[nodiscard]] static std::optional<Cache> FromSerialized(
- const QByteArray &serialized,
- int requestedSize);
- [[nodiscard]] QByteArray serialize();
- [[nodiscard]] int size() const;
- [[nodiscard]] int frames() const;
- [[nodiscard]] bool readyInDefaultState() const;
- [[nodiscard]] Frame frame(int index) const;
- void reserve(int frames);
- void add(crl::time duration, const QImage &frame);
- void finish();
- [[nodiscard]] Preview makePreview() const;
- PaintFrameResult paintCurrentFrame(QPainter &p, const Context &context);
- [[nodiscard]] int currentFrame() const;
- private:
- static constexpr auto kPerRow = 16;
- [[nodiscard]] int frameRowByteSize() const;
- [[nodiscard]] int frameByteSize() const;
- [[nodiscard]] crl::time currentFrameFinishes() const;
- std::vector<QImage> _images;
- std::vector<uint16> _durations;
- QImage _full;
- crl::time _shown = 0;
- int _frame = 0;
- int _size = 0;
- int _frames = 0;
- bool _finished = false;
- };
- class Loader;
- class Loading;
- class Cached final {
- public:
- Cached(
- const QString &entityData,
- Fn<std::unique_ptr<Loader>()> unloader,
- Cache cache);
- [[nodiscard]] QString entityData() const;
- [[nodiscard]] Preview makePreview() const;
- PaintFrameResult paint(QPainter &p, const Context &context);
- [[nodiscard]] bool inDefaultState() const;
- [[nodiscard]] Loading unload();
- private:
- Fn<std::unique_ptr<Loader>()> _unloader;
- Cache _cache;
- QString _entityData;
- };
- struct RendererDescriptor {
- Fn<std::unique_ptr<Ui::FrameGenerator>()> generator;
- Fn<void(QByteArray)> put;
- Fn<std::unique_ptr<Loader>()> loader;
- int size = 0;
- };
- class Renderer final : public base::has_weak_ptr {
- public:
- explicit Renderer(RendererDescriptor &&descriptor);
- virtual ~Renderer();
- PaintFrameResult paint(QPainter &p, const Context &context);
- [[nodiscard]] std::optional<Cached> ready(const QString &entityData);
- [[nodiscard]] std::unique_ptr<Loader> cancel();
- [[nodiscard]] bool canMakePreview() const;
- [[nodiscard]] Preview makePreview() const;
- [[nodiscard]] bool readyInDefaultState() const;
- void setRepaintCallback(Fn<void()> repaint);
- [[nodiscard]] Cache takeCache();
- private:
- void frameReady(
- std::unique_ptr<Ui::FrameGenerator> generator,
- crl::time duration,
- QImage frame);
- void renderNext(
- std::unique_ptr<Ui::FrameGenerator> generator,
- QImage storage);
- void finish();
- Cache _cache;
- std::unique_ptr<Ui::FrameGenerator> _generator;
- QImage _storage;
- Fn<void(QByteArray)> _put;
- Fn<void()> _repaint;
- Fn<std::unique_ptr<Loader>()> _loader;
- bool _finished = false;
- };
- struct Caching {
- std::unique_ptr<Renderer> renderer;
- QString entityData;
- Preview preview;
- };
- class Loader {
- public:
- using LoadResult = std::variant<Caching, Cached>;
- [[nodiscard]] virtual QString entityData() = 0;
- virtual void load(Fn<void(LoadResult)> loaded) = 0;
- [[nodiscard]] virtual bool loading() = 0;
- virtual void cancel() = 0;
- [[nodiscard]] virtual Preview preview() = 0;
- virtual ~Loader() = default;
- };
- class Loading final : public base::has_weak_ptr {
- public:
- Loading(std::unique_ptr<Loader> loader, Preview preview);
- [[nodiscard]] QString entityData() const;
- void load(Fn<void(Loader::LoadResult)> done);
- [[nodiscard]] bool loading() const;
- void paint(QPainter &p, const Context &context);
- [[nodiscard]] bool hasImagePreview() const;
- [[nodiscard]] Preview imagePreview() const;
- void updatePreview(Preview preview);
- void cancel();
- private:
- std::unique_ptr<Loader> _loader;
- Preview _preview;
- };
- struct RepaintRequest {
- crl::time when = 0;
- crl::time duration = 0;
- };
- class Object;
- class Instance final : public base::has_weak_ptr {
- public:
- Instance(
- Loading loading,
- Fn<void(not_null<Instance*>, RepaintRequest)> repaintLater);
- Instance(const Instance&) = delete;
- Instance &operator=(const Instance&) = delete;
- [[nodiscard]] QString entityData() const;
- void paint(QPainter &p, const Context &context);
- [[nodiscard]] bool ready();
- [[nodiscard]] bool readyInDefaultState();
- [[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);
- void repaint();
- private:
- void load(Loading &state);
- 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 Object final : public Ui::Text::CustomEmoji {
- public:
- Object(not_null<Instance*> instance, Fn<void()> repaint);
- ~Object();
- int width() override;
- QString entityData() override;
- void paint(QPainter &p, const Context &context) override;
- void unload() override;
- bool ready() override;
- bool readyInDefaultState() override;
- void repaint();
- private:
- const not_null<Instance*> _instance;
- Fn<void()> _repaint;
- bool _using = false;
- };
- class Internal final : public Text::CustomEmoji {
- public:
- Internal(
- QString entityData,
- QImage image,
- QMargins padding,
- bool colored);
- int width() override;
- QString entityData() override;
- void paint(QPainter &p, const Context &context) override;
- void unload() override;
- bool ready() override;
- bool readyInDefaultState() override;
- private:
- const QString _entityData;
- const QImage _image;
- const QMargins _padding;
- const bool _colored = false;
- };
- class DynamicImageEmoji final : public Ui::Text::CustomEmoji {
- public:
- DynamicImageEmoji(
- QString entityData,
- std::shared_ptr<DynamicImage> image,
- Fn<void()> repaint,
- QMargins padding,
- int size);
- int width() override;
- QString entityData() override;
- void paint(QPainter &p, const Context &context) override;
- void unload() override;
- bool ready() override;
- bool readyInDefaultState() override;
- private:
- const QString _entityData;
- const std::shared_ptr<DynamicImage> _image;
- const Fn<void()> _repaint;
- const QMargins _padding;
- const int _size = 0;
- bool _subscribed = false;
- };
- struct IconEmojiFrameCache {
- QImage frame;
- int paletteVersion = 0;
- };
- void PaintIconEmoji(
- QPainter &p,
- const Context &context,
- not_null<const style::IconEmoji*> emoji,
- IconEmojiFrameCache &cache);
- } // namespace Ui::CustomEmoji
|