/* 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 */ #pragma once #include "ui/effects/animations.h" #include "base/timer.h" #include "base/weak_ptr.h" namespace style { class palette; } // namespace style namespace Ui { class ChatStyle; struct ChatPaintContext; struct BubblePattern; struct ChatThemeBackground { QImage prepared; QImage preparedForTiled; QImage gradientForFill; std::optional colorForFill; std::vector colors; float64 patternOpacity = 1.; int gradientRotation = 0; bool isPattern = false; bool tile = false; }; bool operator==(const ChatThemeBackground &a, const ChatThemeBackground &b); bool operator!=(const ChatThemeBackground &a, const ChatThemeBackground &b); struct CacheBackgroundRequest { ChatThemeBackground background; QSize area; int gradientRotationAdd = 0; float64 gradientProgress = 1.; explicit operator bool() const { return !background.prepared.isNull() || !background.gradientForFill.isNull(); } }; bool operator==( const CacheBackgroundRequest &a, const CacheBackgroundRequest &b); bool operator!=( const CacheBackgroundRequest &a, const CacheBackgroundRequest &b); struct CacheBackgroundResult { QImage image; QImage gradient; QSize area; int x = 0; int y = 0; }; struct CachedBackground { CachedBackground() = default; CachedBackground(CacheBackgroundResult &&result); QPixmap pixmap; QSize area; int x = 0; int y = 0; }; struct BackgroundState { CachedBackground was; CachedBackground now; float64 shown = 1.; }; struct ChatThemeDescriptor { uint64 id = 0; Fn preparePalette; Fn prepareBackground; }; class ChatTheme final : public base::has_weak_ptr { public: ChatTheme(); // Expected to be invoked on a background thread. Invokes callbacks there. ChatTheme(ChatThemeDescriptor &&descriptor); ~ChatTheme(); [[nodiscard]] uint64 key() const; [[nodiscard]] const style::palette *palette() const { return _palette.get(); } void setBackground(ChatThemeBackground &&background); void updateBackgroundImageFrom(ChatThemeBackground &&background); [[nodiscard]] const ChatThemeBackground &background() const { return _mutableBackground; } void setBubblesBackground(QImage image); [[nodiscard]] const BubblePattern *bubblesBackgroundPattern() const { return _bubblesBackgroundPattern.get(); } [[nodiscard]] ChatPaintContext preparePaintContext( not_null st, QRect viewport, QRect clip); [[nodiscard]] const BackgroundState &backgroundState(QSize area); [[nodiscard]] rpl::producer<> repaintBackgroundRequests() const; void rotateComplexGradientBackground(); private: void cacheBackground(); void cacheBackgroundNow(); void cacheBackgroundAsync( const CacheBackgroundRequest &request, Fn done = nullptr); void setCachedBackground(CacheBackgroundResult &&cached); [[nodiscard]] CacheBackgroundRequest currentCacheRequest( QSize area, int addRotation = 0) const; [[nodiscard]] bool readyForBackgroundRotation() const; void generateNextBackgroundRotation(); uint64 _id = 0; std::unique_ptr _palette; ChatThemeBackground _mutableBackground; BackgroundState _backgroundState; Animations::Simple _backgroundFade; CacheBackgroundRequest _backgroundCachingRequest; CacheBackgroundResult _backgroundNext; QSize _willCacheForArea; crl::time _lastAreaChangeTime = 0; std::optional _cacheBackgroundTimer; CachedBackground _bubblesBackground; QImage _bubblesBackgroundPrepared; std::unique_ptr _bubblesBackgroundPattern; rpl::event_stream<> _repaintBackgroundRequests; rpl::lifetime _lifetime; }; struct ChatBackgroundRects { QRect from; QRect to; }; [[nodiscard]] ChatBackgroundRects ComputeChatBackgroundRects( QSize fillSize, QSize imageSize); [[nodiscard]] QColor CountAverageColor(const QImage &image); [[nodiscard]] QColor ThemeAdjustedColor(QColor original, QColor background); [[nodiscard]] QImage PreprocessBackgroundImage(QImage image); [[nodiscard]] std::optional CalculateImageMonoColor( const QImage &image); [[nodiscard]] QImage PrepareImageForTiled(const QImage &prepared); [[nodiscard]] QImage ReadBackgroundImage( const QString &path, const QByteArray &content, bool gzipSvg); [[nodiscard]] QImage GenerateBackgroundImage( QSize size, const std::vector &bg, int gradientRotation, float64 patternOpacity = 1., Fn drawPattern = nullptr); [[nodiscard]] QImage PreparePatternImage( QImage pattern, const std::vector &bg, int gradientRotation, float64 patternOpacity); [[nodiscard]] QImage PrepareBlurredBackground(QImage image); [[nodiscard]] QImage GenerateDitheredGradient( const std::vector &colors, int rotation); [[nodiscard]] ChatThemeBackground PrepareBackgroundImage( const QString &path, const QByteArray &bytes, bool gzipSvg, const std::vector &colors, bool isPattern, float64 patternOpacity, bool isBlurred); } // namespace Ui