tdesktop/Telegram/SourceFiles/ui/chat/chat_theme.h

220 lines
5.8 KiB
C
Raw Normal View History

2021-08-26 13:25:48 +00:00
/*
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"
2021-09-02 10:28:07 +00:00
namespace style {
class palette;
} // namespace style
2021-08-26 13:25:48 +00:00
namespace Ui {
2021-08-26 15:02:21 +00:00
class ChatStyle;
struct ChatPaintContext;
2021-08-26 13:25:48 +00:00
struct BubblePattern;
2021-08-26 15:02:21 +00:00
struct ChatThemeBackground {
2021-08-26 13:25:48 +00:00
QImage prepared;
QImage preparedForTiled;
2021-08-26 15:02:21 +00:00
QImage gradientForFill;
std::optional<QColor> colorForFill;
std::vector<QColor> colors;
float64 patternOpacity = 1.;
2021-08-26 13:25:48 +00:00
int gradientRotation = 0;
bool isPattern = false;
2021-08-26 15:02:21 +00:00
bool tile = false;
};
bool operator==(const ChatThemeBackground &a, const ChatThemeBackground &b);
bool operator!=(const ChatThemeBackground &a, const ChatThemeBackground &b);
struct ChatThemeBackgroundData {
QString path;
QByteArray bytes;
bool gzipSvg = false;
std::vector<QColor> colors;
bool isPattern = false;
float64 patternOpacity = 0.;
bool isBlurred = false;
bool generateGradient = false;
int gradientRotation = 0;
};
struct ChatThemeBubblesData {
std::vector<QColor> colors;
std::optional<QColor> accent;
};
2021-08-26 15:02:21 +00:00
struct CacheBackgroundRequest {
ChatThemeBackground background;
QSize area;
int gradientRotationAdd = 0;
2021-08-26 13:25:48 +00:00
float64 gradientProgress = 1.;
explicit operator bool() const {
2021-08-26 15:02:21 +00:00
return !background.prepared.isNull()
|| !background.gradientForFill.isNull();
2021-08-26 13:25:48 +00:00
}
};
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 {
2021-08-26 15:02:21 +00:00
uint64 id = 0;
2021-08-26 13:25:48 +00:00
Fn<void(style::palette&)> preparePalette;
ChatThemeBackgroundData backgroundData;
ChatThemeBubblesData bubblesData;
bool basedOnDark = false;
2021-08-26 13:25:48 +00:00
};
class ChatTheme final : public base::has_weak_ptr {
public:
ChatTheme();
2021-08-26 15:02:21 +00:00
// Expected to be invoked on a background thread. Invokes callbacks there.
ChatTheme(ChatThemeDescriptor &&descriptor);
2021-08-26 13:25:48 +00:00
2021-09-02 10:28:07 +00:00
~ChatTheme();
2021-08-26 13:25:48 +00:00
[[nodiscard]] uint64 key() const;
[[nodiscard]] const style::palette *palette() const {
2021-08-26 13:25:48 +00:00
return _palette.get();
}
2021-08-26 15:02:21 +00:00
void setBackground(ChatThemeBackground &&background);
void updateBackgroundImageFrom(ChatThemeBackground &&background);
[[nodiscard]] const ChatThemeBackground &background() const {
2021-08-26 15:02:21 +00:00
return _mutableBackground;
}
2021-08-26 13:25:48 +00:00
void setBubblesBackground(QImage image);
[[nodiscard]] const BubblePattern *bubblesBackgroundPattern() const {
2021-08-26 13:25:48 +00:00
return _bubblesBackgroundPattern.get();
}
2021-08-26 15:02:21 +00:00
[[nodiscard]] ChatPaintContext preparePaintContext(
not_null<const ChatStyle*> st,
2021-08-26 13:25:48 +00:00
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<void(CacheBackgroundResult&&)> done = nullptr);
void setCachedBackground(CacheBackgroundResult &&cached);
[[nodiscard]] CacheBackgroundRequest currentCacheRequest(
QSize area,
int addRotation = 0) const;
[[nodiscard]] bool readyForBackgroundRotation() const;
void generateNextBackgroundRotation();
void adjustPalette(const ChatThemeDescriptor &descriptor);
void set(const style::color &my, const QColor &color);
void adjust(const style::color &my, const QColor &by);
2021-08-26 13:25:48 +00:00
uint64 _id = 0;
std::unique_ptr<style::palette> _palette;
2021-08-26 15:02:21 +00:00
ChatThemeBackground _mutableBackground;
2021-08-26 13:25:48 +00:00
BackgroundState _backgroundState;
2021-08-26 15:02:21 +00:00
Animations::Simple _backgroundFade;
2021-08-26 13:25:48 +00:00
CacheBackgroundRequest _backgroundCachingRequest;
CacheBackgroundResult _backgroundNext;
QSize _willCacheForArea;
crl::time _lastAreaChangeTime = 0;
std::optional<base::Timer> _cacheBackgroundTimer;
CachedBackground _bubblesBackground;
QImage _bubblesBackgroundPrepared;
2021-08-26 15:02:21 +00:00
std::unique_ptr<BubblePattern> _bubblesBackgroundPattern;
2021-08-26 13:25:48 +00:00
rpl::event_stream<> _repaintBackgroundRequests;
rpl::lifetime _lifetime;
};
2021-08-26 15:02:21 +00:00
struct ChatBackgroundRects {
QRect from;
QRect to;
};
[[nodiscard]] ChatBackgroundRects ComputeChatBackgroundRects(
QSize fillSize,
QSize imageSize);
[[nodiscard]] QColor CountAverageColor(const QImage &image);
[[nodiscard]] QColor CountAverageColor(const std::vector<QColor> &colors);
[[nodiscard]] bool IsPatternInverted(
const std::vector<QColor> &background,
float64 patternOpacity);
[[nodiscard]] QColor ThemeAdjustedColor(QColor original, QColor background);
[[nodiscard]] QImage PreprocessBackgroundImage(QImage image);
[[nodiscard]] std::optional<QColor> 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<QColor> &bg,
int gradientRotation,
float64 patternOpacity = 1.,
Fn<void(QPainter&,bool)> drawPattern = nullptr);
[[nodiscard]] QImage InvertPatternImage(QImage pattern);
[[nodiscard]] QImage PreparePatternImage(
QImage pattern,
const std::vector<QColor> &bg,
int gradientRotation,
float64 patternOpacity);
[[nodiscard]] QImage PrepareBlurredBackground(QImage image);
[[nodiscard]] QImage GenerateDitheredGradient(
const std::vector<QColor> &colors,
int rotation);
[[nodiscard]] ChatThemeBackground PrepareBackgroundImage(
const ChatThemeBackgroundData &data);
2021-08-26 15:02:21 +00:00
} // namespace Ui