From fd8e9dad922ccdbf40332a62bfc1c20f8a7b8b8a Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 29 Jan 2019 13:57:29 +0300 Subject: [PATCH] Fix pattern wallpapers with themes. --- Telegram/SourceFiles/mainwidget.cpp | 2 +- .../SourceFiles/settings/settings_chat.cpp | 2 +- Telegram/SourceFiles/storage/localstorage.cpp | 10 +- .../window/themes/window_theme.cpp | 121 ++++++++++-------- .../SourceFiles/window/themes/window_theme.h | 10 +- 5 files changed, 80 insertions(+), 65 deletions(-) diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 6f53d1ec6..859b2143d 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -1596,7 +1596,7 @@ void MainWidget::setReadyChatBackground( ? Data::DefaultWallPaper() : background; - Background()->setImage(ready, std::move(image)); + Background()->set(ready, std::move(image)); const auto tile = Data::IsLegacy1DefaultWallPaper(ready); Background()->setTile(tile); Ui::ForceFullRepaint(this); diff --git a/Telegram/SourceFiles/settings/settings_chat.cpp b/Telegram/SourceFiles/settings/settings_chat.cpp index 78239487e..5fb0938f9 100644 --- a/Telegram/SourceFiles/settings/settings_chat.cpp +++ b/Telegram/SourceFiles/settings/settings_chat.cpp @@ -409,7 +409,7 @@ void ChooseFromFile(not_null parent) { 4096 * image.width()); } - Window::Theme::Background()->setImage( + Window::Theme::Background()->set( Data::CustomWallPaper(), std::move(image)); Window::Theme::Background()->setTile(false); diff --git a/Telegram/SourceFiles/storage/localstorage.cpp b/Telegram/SourceFiles/storage/localstorage.cpp index 2368346a2..ccff3be78 100644 --- a/Telegram/SourceFiles/storage/localstorage.cpp +++ b/Telegram/SourceFiles/storage/localstorage.cpp @@ -4076,16 +4076,16 @@ bool readBackground() { || Data::IsDefaultWallPaper(*paper)) { _backgroundCanWrite = false; if (isOldEmptyImage || bg.version < 8005) { - Window::Theme::Background()->setImage(Data::DefaultWallPaper()); + Window::Theme::Background()->set(Data::DefaultWallPaper()); Window::Theme::Background()->setTile(false); } else { - Window::Theme::Background()->setImage(*paper); + Window::Theme::Background()->set(*paper); } _backgroundCanWrite = true; return true; } else if (Data::IsThemeWallPaper(*paper) && imageData.isEmpty()) { _backgroundCanWrite = false; - Window::Theme::Background()->setImage(*paper); + Window::Theme::Background()->set(*paper); _backgroundCanWrite = true; return true; } @@ -4132,9 +4132,9 @@ bool readBackground() { image = QImage(); } } - if (!image.isNull()|| paper->backgroundColor()) { + if (!image.isNull() || paper->backgroundColor()) { _backgroundCanWrite = false; - Window::Theme::Background()->setImage(*paper, std::move(image)); + Window::Theme::Background()->set(*paper, std::move(image)); _backgroundCanWrite = true; return true; } diff --git a/Telegram/SourceFiles/window/themes/window_theme.cpp b/Telegram/SourceFiles/window/themes/window_theme.cpp index 54688c1e7..b28da05a5 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme.cpp @@ -788,13 +788,13 @@ bool loadTheme(const QByteArray &content, Cached &cache, Instance *out = nullptr return true; } -QImage prepareBackgroundImage(QImage &&image) { +QImage validateBackgroundImage(QImage image) { if (image.format() != QImage::Format_ARGB32_Premultiplied) { image = std::move(image).convertToFormat( QImage::Format_ARGB32_Premultiplied); } image.setDevicePixelRatio(cRetinaFactor()); - return std::move(image); + return image; } void adjustColor(style::color color, float64 hue, float64 saturation) { @@ -834,21 +834,19 @@ ChatBackground::ChatBackground() : _adjustableColors({ } void ChatBackground::setThemeData(QImage &&themeImage, bool themeTile) { - _themeImage = prepareBackgroundImage(std::move(themeImage)); + _themeImage = validateBackgroundImage(std::move(themeImage)); _themeTile = themeTile; } void ChatBackground::start() { if (Data::details::IsUninitializedWallPaper(_paper)) { if (!Local::readBackground()) { - setImage(Data::ThemeWallPaper()); + set(Data::ThemeWallPaper()); } } } -void ChatBackground::setImage( - const Data::WallPaper &paper, - QImage &&image) { +void ChatBackground::set(const Data::WallPaper &paper, QImage image) { if (image.format() != QImage::Format_ARGB32_Premultiplied) { image = std::move(image).convertToFormat( QImage::Format_ARGB32_Premultiplied); @@ -872,15 +870,17 @@ void ChatBackground::setImage( } if (Data::IsThemeWallPaper(_paper)) { (nightMode() ? _tileNightValue : _tileDayValue) = _themeTile; - setPreparedImage(QImage(_themeImage)); + setPreparedImage(_themeImage, _themeImage); } else if (Data::details::IsTestingThemeWallPaper(_paper) || Data::details::IsTestingDefaultWallPaper(_paper) || Data::details::IsTestingEditorWallPaper(_paper)) { - if (Data::details::IsTestingDefaultWallPaper(_paper) || image.isNull()) { + if (Data::details::IsTestingDefaultWallPaper(_paper) + || image.isNull()) { image.load(qsl(":/gui/art/bg.jpg")); setPaper(Data::details::TestingDefaultWallPaper()); } - setPreparedImage(prepareBackgroundImage(std::move(image))); + image = validateBackgroundImage(std::move(image)); + setPreparedImage(image, image); } else { if (Data::IsLegacy1DefaultWallPaper(_paper)) { image.load(qsl(":/gui/art/bg_initial.jpg")); @@ -903,12 +903,15 @@ void ChatBackground::setImage( : image)); if (const auto fill = _paper.backgroundColor()) { if (_paper.isPattern() && !image.isNull()) { - setPreparedImage(Data::PreparePatternImage( - std::move(image), - *fill, - PatternColor(*fill), - _paper.patternIntensity())); + auto prepared = validateBackgroundImage( + Data::PreparePatternImage( + image, + *fill, + PatternColor(*fill), + _paper.patternIntensity())); + setPreparedImage(std::move(image), std::move(prepared)); } else { + _original = QImage(); _pixmap = QPixmap(); _pixmapForTiled = QPixmap(); if (adjustPaletteRequired()) { @@ -916,11 +919,14 @@ void ChatBackground::setImage( } } } else { - setPreparedImage(prepareBackgroundImage(std::move(image))); + image = validateBackgroundImage(std::move(image)); + setPreparedImage(image, image); } } - Assert((!_pixmap.isNull() && !_pixmapForTiled.isNull()) - || colorForFill()); + Assert(colorForFill() + || (!_original.isNull() + && !_pixmap.isNull() + && !_pixmapForTiled.isNull())); notify(BackgroundUpdate(BackgroundUpdate::Type::New, tile())); if (needResetAdjustable) { @@ -929,23 +935,31 @@ void ChatBackground::setImage( } } -void ChatBackground::setPreparedImage(QImage &&image) { - Expects(image.format() == QImage::Format_ARGB32_Premultiplied); - - image.setDevicePixelRatio(cRetinaFactor()); +void ChatBackground::setPreparedImage(QImage original, QImage prepared) { + Expects(original.format() == QImage::Format_ARGB32_Premultiplied); + Expects(original.width() > 0 && original.height() > 0); + Expects(prepared.format() == QImage::Format_ARGB32_Premultiplied); + Expects(prepared.width() > 0 && prepared.height() > 0); + _original = std::move(original); if (adjustPaletteRequired()) { - adjustPaletteUsingBackground(image); + adjustPaletteUsingBackground(prepared); } + preparePixmaps(std::move(prepared)); +} - auto width = image.width(); - auto height = image.height(); - Assert(width > 0 && height > 0); - auto isSmallForTiled = (width < kMinimumTiledSize || height < kMinimumTiledSize); +void ChatBackground::preparePixmaps(QImage image) { + const auto width = image.width(); + const auto height = image.height(); + const auto isSmallForTiled = (width < kMinimumTiledSize) + || (height < kMinimumTiledSize); if (isSmallForTiled) { - auto repeatTimesX = qCeil(kMinimumTiledSize / float64(width)); - auto repeatTimesY = qCeil(kMinimumTiledSize / float64(height)); - auto imageForTiled = QImage(width * repeatTimesX, height * repeatTimesY, QImage::Format_ARGB32_Premultiplied); + const auto repeatTimesX = qCeil(kMinimumTiledSize / (1. * width)); + const auto repeatTimesY = qCeil(kMinimumTiledSize / (1. * height)); + auto imageForTiled = QImage( + width * repeatTimesX, + height * repeatTimesY, + QImage::Format_ARGB32_Premultiplied); imageForTiled.setDevicePixelRatio(image.devicePixelRatio()); auto imageForTiledBytes = imageForTiled.bits(); auto bytesInLine = width * sizeof(uint32); @@ -996,15 +1010,13 @@ bool ChatBackground::adjustPaletteRequired() { return !usingDefaultBackground(); } -void ChatBackground::adjustPaletteUsingBackground(const QImage &img) { - Assert(img.format() == QImage::Format_ARGB32_Premultiplied); - +void ChatBackground::adjustPaletteUsingBackground(const QImage &image) { 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()) { + const auto w = image.width(); + const auto h = image.height(); + const auto size = w * h; + if (const auto pix = image.constBits()) { for (auto i = 0, l = size * 4; i != l; i += 4) { components[2] += pix[i + 0]; components[1] += pix[i + 1]; @@ -1043,7 +1055,7 @@ QImage ChatBackground::createCurrentImage() const { result.fill(*fill); return result; } - return pixmap().toImage(); // #TODO patterns + return pixmap().toImage(); } bool ChatBackground::tile() const { @@ -1118,15 +1130,15 @@ void ChatBackground::reset() { || Data::details::IsTestingDefaultWallPaper(_paper)) { if (_themeImage.isNull()) { _paperForRevert = Data::DefaultWallPaper(); - _imageForRevert = QImage(); + _originalForRevert = QImage(); _tileForRevert = false; } else { _paperForRevert = Data::ThemeWallPaper(); - _imageForRevert = _themeImage; + _originalForRevert = _themeImage; _tileForRevert = _themeTile; } } else { - setImage(Data::ThemeWallPaper()); + set(Data::ThemeWallPaper()); restoreAdjustableColors(); notify(BackgroundUpdate(BackgroundUpdate::Type::TestingTheme, tile()), true); notify(BackgroundUpdate(BackgroundUpdate::Type::ApplyingTheme, tile()), true); @@ -1138,7 +1150,7 @@ void ChatBackground::saveForRevert() { if (!Data::details::IsTestingThemeWallPaper(_paper) && !Data::details::IsTestingDefaultWallPaper(_paper)) { _paperForRevert = _paper; - _imageForRevert = std::move(_pixmap).toImage(); + _originalForRevert = std::move(_original); _tileForRevert = tile(); } } @@ -1165,24 +1177,26 @@ void ChatBackground::setTestingTheme(Instance &&theme) { || (Data::IsDefaultWallPaper(_paper) && !nightMode() && _themeAbsolutePath.isEmpty()); - if (AreTestingTheme() && IsPaletteTestingPath(GlobalApplying.pathAbsolute)) { + if (AreTestingTheme() + && IsPaletteTestingPath(GlobalApplying.pathAbsolute)) { // Grab current background image if it is not already custom + // Use prepared pixmap, not original image, because we're + // for sure switching to a non-pattern wall-paper (testing editor). if (!Data::IsCustomWallPaper(_paper)) { saveForRevert(); - setImage( + set( Data::details::TestingEditorWallPaper(), std::move(_pixmap).toImage()); } } else if (switchToThemeBackground) { saveForRevert(); - setImage( + set( Data::details::TestingThemeWallPaper(), std::move(theme.background)); setTile(theme.tiled); } else { // Apply current background image so that service bg colors are recounted. - // #TODO patterns - setImage(_paper, std::move(_pixmap).toImage()); + set(_paper, std::move(_original)); } notify(BackgroundUpdate(BackgroundUpdate::Type::TestingTheme, tile()), true); } @@ -1192,7 +1206,7 @@ void ChatBackground::setTestingDefaultTheme() { saveAdjustableColors(); saveForRevert(); - setImage(Data::details::TestingDefaultWallPaper()); + set(Data::details::TestingDefaultWallPaper()); setTile(false); notify(BackgroundUpdate(BackgroundUpdate::Type::TestingTheme, tile()), true); } @@ -1208,7 +1222,7 @@ void ChatBackground::keepApplied(const QString &path, bool write) { } } else if (Data::details::IsTestingThemeWallPaper(_paper)) { setPaper(Data::ThemeWallPaper()); - _themeImage = prepareBackgroundImage(_pixmap.toImage()); + _themeImage = validateBackgroundImage(base::duplicate(_original)); _themeTile = tile(); if (write) { writeNewBackgroundSettings(); @@ -1249,7 +1263,7 @@ void ChatBackground::writeNewBackgroundSettings() { ((Data::IsThemeWallPaper(_paper) || Data::IsDefaultWallPaper(_paper)) ? QImage() - : _pixmap.toImage())); // #TODO patterns + : _original)); } void ChatBackground::revert() { @@ -1257,11 +1271,10 @@ void ChatBackground::revert() { || Data::details::IsTestingDefaultWallPaper(_paper) || Data::details::IsTestingEditorWallPaper(_paper)) { setTile(_tileForRevert); - setImage(_paperForRevert, std::move(_imageForRevert)); + set(_paperForRevert, std::move(_originalForRevert)); } else { // Apply current background image so that service bg colors are recounted. - // #TODO patterns - setImage(_paper, std::move(_pixmap).toImage()); + set(_paper, std::move(_original)); } notify(BackgroundUpdate(BackgroundUpdate::Type::RevertingTheme, tile()), true); } @@ -1329,7 +1342,7 @@ void ChatBackground::toggleNightMode(std::optional themePath) { } Local::writeSettings(); if (!settingDefault && !Local::readBackground()) { - setImage(Data::ThemeWallPaper()); + set(Data::ThemeWallPaper()); } }; } diff --git a/Telegram/SourceFiles/window/themes/window_theme.h b/Telegram/SourceFiles/window/themes/window_theme.h index 4b7646806..b53544ef0 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.h +++ b/Telegram/SourceFiles/window/themes/window_theme.h @@ -177,7 +177,7 @@ public: // This method is setting the default (themed) image if none was set yet. void start(); - void setImage(const Data::WallPaper &paper, QImage &&image = QImage()); + void set(const Data::WallPaper &paper, QImage image = QImage()); void setTile(bool tile); void setTileDayValue(bool tile); void setTileNightValue(bool tile); @@ -215,12 +215,13 @@ private: void ensureStarted(); void saveForRevert(); - void setPreparedImage(QImage &&image); + void setPreparedImage(QImage original, QImage prepared); + void preparePixmaps(QImage image); void writeNewBackgroundSettings(); void setPaper(const Data::WallPaper &paper); [[nodiscard]] bool adjustPaletteRequired(); - void adjustPaletteUsingBackground(const QImage &img); + void adjustPaletteUsingBackground(const QImage &image); void adjustPaletteUsingColor(QColor color); void restoreAdjustableColors(); @@ -240,6 +241,7 @@ private: Data::WallPaper _paper = Data::details::UninitializedWallPaper(); std::optional _paperColor; + QImage _original; QPixmap _pixmap; QPixmap _pixmapForTiled; bool _nightMode = false; @@ -252,7 +254,7 @@ private: Data::WallPaper _paperForRevert = Data::details::UninitializedWallPaper(); - QImage _imageForRevert; + QImage _originalForRevert; bool _tileForRevert = false; std::vector _adjustableColors;