#pragma once #include #include #include #include #include #include #include #include #include #include #include #include "common/Aliases.hpp" #include "common/Common.hpp" namespace chatterino { namespace detail { template struct Frame { Image image; int duration; }; class Frames : boost::noncopyable { public: Frames(); Frames(const QVector> &frames); ~Frames(); bool animated() const; void advance(); boost::optional current() const; boost::optional first() const; private: QVector> items_; int index_{0}; int durationOffset_{0}; pajlada::Signals::Connection gifTimerConnection_; }; } // namespace detail class Image; using ImagePtr = std::shared_ptr; /// This class is thread safe. class Image : public std::enable_shared_from_this, boost::noncopyable { public: static ImagePtr fromUrl(const Url &url, qreal scale = 1); static ImagePtr fromPixmap(const QPixmap &pixmap, qreal scale = 1); static ImagePtr getEmpty(); const Url &url() const; bool loaded() const; // either returns the current pixmap, or triggers loading it (lazy loading) boost::optional pixmapOrLoad() const; void load() const; qreal scale() const; bool isEmpty() const; int width() const; int height() const; bool animated() const; bool operator==(const Image &image) const; bool operator!=(const Image &image) const; private: Image(); Image(const Url &url, qreal scale); Image(qreal scale); void setPixmap(const QPixmap &pixmap); void actuallyLoad(); const Url url_{}; const qreal scale_{1}; std::atomic_bool empty_{false}; // gui thread only bool shouldLoad_{false}; std::unique_ptr frames_{}; }; } // namespace chatterino