Improve theme applying.

This commit is contained in:
John Preston 2018-07-21 16:54:00 +03:00
parent cb338e330f
commit 6429e8b532
4 changed files with 100 additions and 48 deletions

View File

@ -1219,7 +1219,6 @@ void Messenger::loggedOut() {
_mediaView->clearData();
}
Local::reset();
Window::Theme::Background()->reset();
cSetOtherOnline(0);
clearStorageImages();

View File

@ -2689,6 +2689,7 @@ void reset() {
_installedStickersKey = _featuredStickersKey = _recentStickersKey = _favedStickersKey = _archivedStickersKey = 0;
_savedGifsKey = 0;
_backgroundKeyDay = _backgroundKeyNight = 0;
Window::Theme::Background()->reset();
_userSettingsKey = _recentHashtagsAndBotsKey = _savedPeersKey = _exportSettingsKey = 0;
_oldMapVersion = _oldSettingsVersion = 0;
StoredAuthSessionCache.reset();
@ -4299,6 +4300,9 @@ QString loadThemeUsingKey(FileKey key) {
}
void writeTheme(const Window::Theme::Saved &saved) {
if (_themeKeyLegacy) {
return;
}
auto &themeKey = Window::Theme::IsNightMode()
? _themeKeyNight
: _themeKeyDay;

View File

@ -220,6 +220,7 @@ bool loadThemeFromCache(const QByteArray &content, const Cached &cache) {
if (!style::main_palette::load(cache.colors)) {
return false;
}
Background()->saveAdjustableColors();
if (!background.isNull()) {
applyBackground(std::move(background), cache.tiled, nullptr);
}
@ -280,6 +281,7 @@ bool loadTheme(const QByteArray &content, Cached &cache, Instance *out = nullptr
if (!loadColorScheme(schemeContent, out)) {
return false;
}
Background()->saveAdjustableColors();
auto backgroundTiled = false;
auto backgroundContent = QByteArray();
@ -307,6 +309,7 @@ bool loadTheme(const QByteArray &content, Cached &cache, Instance *out = nullptr
if (!loadColorScheme(content, out)) {
return false;
}
Background()->saveAdjustableColors();
}
if (out) {
cache.colors = out->palette.save();
@ -333,39 +336,6 @@ void adjustColor(style::color color, float64 hue, float64 saturation) {
color.set(original.red(), original.green(), original.blue(), original.alpha());
}
void adjustColorsUsingBackground(const QImage &img) {
Assert(img.format() == QImage::Format_ARGB32_Premultiplied);
uint64 components[3] = { 0 };
uint64 componentsScroll[3] = { 0 };
auto w = img.width();
auto h = img.height();
auto size = w * h;
if (auto pix = img.constBits()) {
for (auto i = 0, l = size * 4; i != l; i += 4) {
components[2] += pix[i + 0];
components[1] += pix[i + 1];
components[0] += pix[i + 2];
}
}
if (size) {
for (auto i = 0; i != 3; ++i) {
components[i] /= size;
}
}
auto bgColor = QColor(components[0], components[1], components[2]);
auto hue = bgColor.hslHueF();
auto saturation = bgColor.hslSaturationF();
adjustColor(st::msgServiceBg, hue, saturation);
adjustColor(st::msgServiceBgSelected, hue, saturation);
adjustColor(st::historyScroll.bg, hue, saturation);
adjustColor(st::historyScroll.bgOver, hue, saturation);
adjustColor(st::historyScroll.barBg, hue, saturation);
adjustColor(st::historyScroll.barBgOver, hue, saturation);
}
void ApplyDefaultWithNightMode(bool nightMode) {
if (nightMode) {
if (auto preview = PreviewFromFile(NightThemePath())) {
@ -386,6 +356,21 @@ void ApplyDefaultWithNightMode(bool nightMode) {
} // namespace
ChatBackground::AdjustableColor::AdjustableColor(style::color data)
: item(data)
, original(data->c) {
}
ChatBackground::ChatBackground() : _adjustableColors({
st::msgServiceBg,
st::msgServiceBgSelected,
st::historyScrollBg,
st::historyScrollBgOver,
st::historyScrollBarBg,
st::historyScrollBarBgOver }) {
saveAdjustableColors();
}
void ChatBackground::setThemeData(QImage &&themeImage, bool themeTile) {
_themeImage = prepareBackgroundImage(std::move(themeImage));
_themeTile = themeTile;
@ -400,18 +385,18 @@ void ChatBackground::start() {
}
void ChatBackground::setImage(int32 id, QImage &&image) {
auto resetPalette = (id == kDefaultBackground)
auto needResetAdjustable = (id == kDefaultBackground)
&& (_id != kDefaultBackground)
&& !nightMode()
&& _themeAbsolutePath.isEmpty();
if (id == kThemeBackground && _themeImage.isNull()) {
id = kDefaultBackground;
} else if (resetPalette) {
} else if (needResetAdjustable) {
// If we had a default color theme with non-default background,
// and we switch to default background we must somehow switch from
// adjusted service colors to default (non-adjusted) service colors.
// The only way to do that right now is through full palette reset.
style::main_palette::reset();
restoreAdjustableColors();
}
_id = id;
if (_id == kThemeBackground) {
@ -442,7 +427,7 @@ void ChatBackground::setImage(int32 id, QImage &&image) {
}
Assert(!_pixmap.isNull() && !_pixmapForTiled.isNull());
notify(BackgroundUpdate(BackgroundUpdate::Type::New, tile()));
if (resetPalette) {
if (needResetAdjustable) {
notify(BackgroundUpdate(BackgroundUpdate::Type::TestingTheme, tile()), true);
notify(BackgroundUpdate(BackgroundUpdate::Type::ApplyingTheme, tile()), true);
}
@ -476,7 +461,7 @@ void ChatBackground::setPreparedImage(QImage &&image) {
return !usingDefaultBackground();
}();
if (adjustColors) {
adjustColorsUsingBackground(image);
adjustPaletteUsingBackground(image);
}
auto width = image.width();
@ -509,6 +494,36 @@ void ChatBackground::setPreparedImage(QImage &&image) {
}
}
void ChatBackground::adjustPaletteUsingBackground(const QImage &img) {
Assert(img.format() == QImage::Format_ARGB32_Premultiplied);
uint64 components[3] = { 0 };
uint64 componentsScroll[3] = { 0 };
auto w = img.width();
auto h = img.height();
auto size = w * h;
if (auto pix = img.constBits()) {
for (auto i = 0, l = size * 4; i != l; i += 4) {
components[2] += pix[i + 0];
components[1] += pix[i + 1];
components[0] += pix[i + 2];
}
}
if (size) {
for (auto i = 0; i != 3; ++i) {
components[i] /= size;
}
}
auto bgColor = QColor(components[0], components[1], components[2]);
auto hue = bgColor.hslHueF();
auto saturation = bgColor.hslSaturationF();
for (const auto &color : _adjustableColors) {
adjustColor(color.item, hue, saturation);
}
}
int32 ChatBackground::id() const {
return _id;
}
@ -594,6 +609,9 @@ void ChatBackground::reset() {
}
} else {
setImage(kThemeBackground);
restoreAdjustableColors();
notify(BackgroundUpdate(BackgroundUpdate::Type::TestingTheme, tile()), true);
notify(BackgroundUpdate(BackgroundUpdate::Type::ApplyingTheme, tile()), true);
}
}
@ -607,9 +625,24 @@ void ChatBackground::saveForRevert() {
}
}
void ChatBackground::setTestingTheme(Instance &&theme, ChangeMode mode) {
void ChatBackground::saveAdjustableColors() {
for (auto &color : _adjustableColors) {
color.original = color.item->c;
}
}
void ChatBackground::restoreAdjustableColors() {
for (const auto &color : _adjustableColors) {
const auto value = color.original;
color.item.set(value.red(), value.green(), value.blue(), value.alpha());
}
}
void ChatBackground::setTestingTheme(Instance &&theme) {
style::main_palette::apply(theme.palette);
auto switchToThemeBackground = (mode == ChangeMode::SwitchToThemeBackground && !theme.background.isNull())
saveAdjustableColors();
auto switchToThemeBackground = !theme.background.isNull()
|| (_id == kThemeBackground)
|| (_id == kDefaultBackground
&& !nightMode()
@ -633,6 +666,8 @@ void ChatBackground::setTestingTheme(Instance &&theme, ChangeMode mode) {
void ChatBackground::setTestingDefaultTheme() {
style::main_palette::reset();
saveAdjustableColors();
saveForRevert();
setImage(internal::kTestingDefaultBackground);
setTile(false);
@ -666,7 +701,8 @@ void ChatBackground::keepApplied(const QString &path, bool write) {
notify(BackgroundUpdate(BackgroundUpdate::Type::ApplyingTheme, tile()), true);
}
bool ChatBackground::isNonDefaultThemeOrBackground() const {
bool ChatBackground::isNonDefaultThemeOrBackground() {
start();
return nightMode()
? (_themeAbsolutePath != NightThemePath()
|| _id != kThemeBackground)
@ -865,6 +901,8 @@ void Revert() {
return;
}
style::main_palette::load(instance->applying.paletteForRevert);
Background()->saveAdjustableColors();
instance->applying = Data::Applying();
Background()->revert();
}

View File

@ -91,6 +91,8 @@ struct BackgroundUpdate {
class ChatBackground : public base::Observable<BackgroundUpdate> {
public:
ChatBackground();
// This method is allowed to (and should) be called before start().
void setThemeData(QImage &&themeImage, bool themeTile);
@ -104,11 +106,8 @@ public:
QString themeAbsolutePath() const;
void reset();
enum class ChangeMode {
SwitchToThemeBackground,
LeaveCurrentCustomBackground,
};
void setTestingTheme(Instance &&theme, ChangeMode mode = ChangeMode::SwitchToThemeBackground);
void setTestingTheme(Instance &&theme);
void saveAdjustableColors();
void setTestingDefaultTheme();
void revert();
@ -124,16 +123,26 @@ public:
bool tileNight() const;
private:
struct AdjustableColor {
AdjustableColor(style::color data);
style::color item;
QColor original;
};
void ensureStarted();
void saveForRevert();
void setPreparedImage(QImage &&image);
void writeNewBackgroundSettings();
void adjustPaletteUsingBackground(const QImage &img);
void restoreAdjustableColors();
void setNightModeValue(bool nightMode);
bool nightMode() const;
void toggleNightMode();
void keepApplied(const QString &path, bool write);
bool isNonDefaultThemeOrBackground() const;
bool isNonDefaultThemeOrBackground();
friend bool IsNightMode();
friend void SetNightModeValue(bool nightMode);
@ -156,6 +165,8 @@ private:
QImage _imageForRevert;
bool _tileForRevert = false;
std::vector<AdjustableColor> _adjustableColors;
};
ChatBackground *Background();