init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
This commit is contained in:
292
Telegram/SourceFiles/ui/chat/chat_theme.h
Normal file
292
Telegram/SourceFiles/ui/chat/chat_theme.h
Normal file
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
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;
|
||||
struct colorizer;
|
||||
} // namespace style
|
||||
|
||||
namespace Ui::Text {
|
||||
class CustomEmoji;
|
||||
} // namespace Ui::Text
|
||||
|
||||
namespace Ui {
|
||||
|
||||
class ChatStyle;
|
||||
struct ChatPaintContext;
|
||||
struct BubblePattern;
|
||||
|
||||
struct ChatThemeGiftSymbol {
|
||||
QRectF area;
|
||||
float64 rotation = 0.;
|
||||
};
|
||||
|
||||
struct ChatThemeBackground {
|
||||
QString key;
|
||||
QImage prepared;
|
||||
QImage preparedForTiled;
|
||||
QImage gradientForFill;
|
||||
std::optional<QColor> colorForFill;
|
||||
std::vector<QColor> colors;
|
||||
std::vector<ChatThemeGiftSymbol> giftSymbols;
|
||||
QImage giftSymbolFrame;
|
||||
uint64_t giftId = 0;
|
||||
float64 patternOpacity = 1.;
|
||||
int gradientRotation = 0;
|
||||
bool isPattern = false;
|
||||
bool tile = false;
|
||||
|
||||
[[nodiscard]] bool waitingForNegativePattern() const {
|
||||
return isPattern && prepared.isNull() && (patternOpacity < 0.);
|
||||
}
|
||||
};
|
||||
|
||||
bool operator==(const ChatThemeBackground &a, const ChatThemeBackground &b);
|
||||
bool operator!=(const ChatThemeBackground &a, const ChatThemeBackground &b);
|
||||
|
||||
struct ChatThemeBackgroundData {
|
||||
QString key;
|
||||
QString path;
|
||||
QByteArray bytes;
|
||||
QImage giftSymbolFrame;
|
||||
uint64 giftId = 0;
|
||||
bool gzipSvg = false;
|
||||
std::vector<QColor> colors;
|
||||
bool isPattern = false;
|
||||
float64 patternOpacity = 0.;
|
||||
int darkModeDimming = 0;
|
||||
bool isBlurred = false;
|
||||
bool forDarkMode = false;
|
||||
bool generateGradient = false;
|
||||
int gradientRotation = 0;
|
||||
};
|
||||
|
||||
struct ChatThemeBubblesData {
|
||||
std::vector<QColor> colors;
|
||||
std::optional<QColor> accent;
|
||||
};
|
||||
|
||||
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;
|
||||
QRect giftArea;
|
||||
float64 giftRotation = 0;
|
||||
bool waitingForNegativePattern = false;
|
||||
};
|
||||
|
||||
[[nodiscard]] CacheBackgroundResult CacheBackground(
|
||||
const CacheBackgroundRequest &request);
|
||||
|
||||
struct CachedBackground {
|
||||
CachedBackground() = default;
|
||||
CachedBackground(CacheBackgroundResult &&result);
|
||||
|
||||
QPixmap pixmap;
|
||||
QSize area;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
QRect giftArea;
|
||||
float64 giftRotation = 0.;
|
||||
mutable std::unique_ptr<Text::CustomEmoji> gift;
|
||||
bool waitingForNegativePattern = false;
|
||||
};
|
||||
|
||||
struct BackgroundState {
|
||||
CachedBackground was;
|
||||
CachedBackground now;
|
||||
float64 shown = 1.;
|
||||
};
|
||||
|
||||
struct ChatThemeKey {
|
||||
uint64 id = 0;
|
||||
bool dark = false;
|
||||
|
||||
explicit operator bool() const {
|
||||
return (id != 0);
|
||||
}
|
||||
|
||||
friend inline auto operator<=>(ChatThemeKey, ChatThemeKey) = default;
|
||||
friend inline bool operator==(ChatThemeKey, ChatThemeKey) = default;
|
||||
};
|
||||
|
||||
struct ChatThemeDescriptor {
|
||||
ChatThemeKey key;
|
||||
Fn<void(style::palette&)> preparePalette;
|
||||
ChatThemeBackgroundData backgroundData;
|
||||
ChatThemeBubblesData bubblesData;
|
||||
bool basedOnDark = false;
|
||||
};
|
||||
|
||||
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]] ChatThemeKey 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();
|
||||
}
|
||||
void finishCreateOnMain(); // Called on_main after setBubblesBackground.
|
||||
|
||||
[[nodiscard]] ChatPaintContext preparePaintContext(
|
||||
not_null<const ChatStyle*> st,
|
||||
QRect viewport,
|
||||
QRect clip,
|
||||
bool paused);
|
||||
[[nodiscard]] const BackgroundState &backgroundState(QSize area);
|
||||
void clearBackgroundState();
|
||||
[[nodiscard]] rpl::producer<> repaintBackgroundRequests() const;
|
||||
void rotateComplexGradientBackground();
|
||||
|
||||
[[nodiscard]] CacheBackgroundRequest cacheBackgroundRequest(
|
||||
QSize area,
|
||||
int addRotation = 0) const;
|
||||
|
||||
private:
|
||||
void cacheBackground();
|
||||
void cacheBackgroundNow();
|
||||
void cacheBackgroundAsync(
|
||||
const CacheBackgroundRequest &request,
|
||||
Fn<void(CacheBackgroundResult&&)> done = nullptr);
|
||||
void setCachedBackground(CacheBackgroundResult &&cached);
|
||||
[[nodiscard]] bool readyForBackgroundRotation() const;
|
||||
void generateNextBackgroundRotation();
|
||||
|
||||
void cacheBubbles();
|
||||
void cacheBubblesNow();
|
||||
void cacheBubblesAsync(
|
||||
const CacheBackgroundRequest &request);
|
||||
[[nodiscard]] CacheBackgroundRequest cacheBubblesRequest(
|
||||
QSize area) const;
|
||||
|
||||
[[nodiscard]] style::colorizer bubblesAccentColorizer(
|
||||
const QColor &accent) const;
|
||||
void adjustPalette(const ChatThemeDescriptor &descriptor);
|
||||
void set(const style::color &my, const QColor &color);
|
||||
void adjust(const style::color &my, const QColor &by);
|
||||
void adjust(const style::color &my, const style::colorizer &by);
|
||||
|
||||
ChatThemeKey _key;
|
||||
std::unique_ptr<style::palette> _palette;
|
||||
ChatThemeBackground _mutableBackground;
|
||||
BackgroundState _backgroundState;
|
||||
Animations::Simple _backgroundFade;
|
||||
CacheBackgroundRequest _backgroundCachingRequest;
|
||||
CacheBackgroundRequest _nextCachingRequest;
|
||||
CacheBackgroundResult _backgroundNext;
|
||||
int _backgroundVersion = 0;
|
||||
QSize _cacheBackgroundArea;
|
||||
crl::time _lastBackgroundAreaChangeTime = 0;
|
||||
std::optional<base::Timer> _cacheBackgroundTimer;
|
||||
|
||||
CachedBackground _bubblesBackground;
|
||||
QImage _bubblesBackgroundPrepared;
|
||||
CacheBackgroundRequest _bubblesCachingRequest;
|
||||
QSize _cacheBubblesArea;
|
||||
crl::time _lastBubblesAreaChangeTime = 0;
|
||||
std::optional<base::Timer> _cacheBubblesTimer;
|
||||
std::unique_ptr<BubblePattern> _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 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);
|
||||
|
||||
struct BackgroundImageFields {
|
||||
QImage image;
|
||||
std::vector<ChatThemeGiftSymbol> giftSymbols;
|
||||
};
|
||||
[[nodiscard]] BackgroundImageFields ReadBackgroundImage(
|
||||
const QString &path,
|
||||
const QByteArray &content,
|
||||
bool gzipSvg,
|
||||
bool findGiftSymbols = false);
|
||||
[[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);
|
||||
[[nodiscard]] QImage PrepareGiftSymbol(
|
||||
const std::unique_ptr<Text::CustomEmoji> &emoji);
|
||||
|
||||
} // namespace Ui
|
||||
Reference in New Issue
Block a user