From b6cd9c2911c2ca77f1918cf58a5e3f93a00158df Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 7 Sep 2021 00:15:38 +0300 Subject: [PATCH] Invert patter image to white for dark colors. --- Telegram/SourceFiles/ui/chat/chat_theme.cpp | 35 +++++++++++++++++-- Telegram/SourceFiles/ui/chat/chat_theme.h | 6 +++- .../window/themes/window_theme.cpp | 3 ++ .../SourceFiles/window/window_main_menu.cpp | 29 ++++++++------- 4 files changed, 56 insertions(+), 17 deletions(-) diff --git a/Telegram/SourceFiles/ui/chat/chat_theme.cpp b/Telegram/SourceFiles/ui/chat/chat_theme.cpp index a03af571ab..03ef319282 100644 --- a/Telegram/SourceFiles/ui/chat/chat_theme.cpp +++ b/Telegram/SourceFiles/ui/chat/chat_theme.cpp @@ -647,6 +647,13 @@ QColor CountAverageColor(const std::vector &colors) { return QColor(components[0], components[1], components[2]); } +bool IsPatternInverted( + const std::vector &background, + float64 patternOpacity) { + return (patternOpacity > 0.) + && (CountAverageColor(background).toHsv().valueF() <= 0.3); +} + QColor ThemeAdjustedColor(QColor original, QColor background) { return QColor::fromHslF( background.hslHueF(), @@ -747,7 +754,7 @@ QImage GenerateBackgroundImage( const std::vector &bg, int gradientRotation, float64 patternOpacity, - Fn drawPattern) { + Fn drawPattern) { auto result = bg.empty() ? Images::GenerateGradient(size, { DefaultBackgroundColor() }) : Images::GenerateGradient(size, bg, gradientRotation); @@ -762,7 +769,7 @@ QImage GenerateBackgroundImage( } else { p.setCompositionMode(QPainter::CompositionMode_DestinationIn); } - drawPattern(p); + drawPattern(p, IsPatternInverted(bg, patternOpacity)); if (patternOpacity < 0. && patternOpacity > -1.) { p.setCompositionMode(QPainter::CompositionMode_SourceOver); p.setOpacity(1. + patternOpacity); @@ -784,7 +791,10 @@ QImage PreparePatternImage( bg, gradientRotation, patternOpacity, - [&](QPainter &p) { + [&](QPainter &p, bool inverted) { + if (inverted) { + pattern = InvertPatternImage(std::move(pattern)); + } p.drawImage(QRect(QPoint(), pattern.size()), pattern); }); @@ -792,6 +802,23 @@ QImage PreparePatternImage( return result; } +QImage InvertPatternImage(QImage pattern) { + pattern = std::move(pattern).convertToFormat( + QImage::Format_ARGB32_Premultiplied); + const auto w = pattern.bytesPerLine() / 4; + auto ints = reinterpret_cast(pattern.bits()); + for (auto y = 0, h = pattern.height(); y != h; ++y) { + for (auto x = 0; x != w; ++x) { + const auto value = (*ints >> 24); + *ints++ = (value << 24) + | (value << 16) + | (value << 8) + | value; + } + } + return pattern; +} + QImage PrepareBlurredBackground(QImage image) { constexpr auto kSize = 900; constexpr auto kRadius = 24; @@ -834,6 +861,8 @@ ChatThemeBackground PrepareBackgroundImage( data.colors, data.gradientRotation, data.patternOpacity); + } else if (IsPatternInverted(data.colors, data.patternOpacity)) { + prepared = InvertPatternImage(std::move(prepared)); } prepared.setDevicePixelRatio(style::DevicePixelRatio()); } else if (data.colors.empty()) { diff --git a/Telegram/SourceFiles/ui/chat/chat_theme.h b/Telegram/SourceFiles/ui/chat/chat_theme.h index 4957086974..25a24cdc91 100644 --- a/Telegram/SourceFiles/ui/chat/chat_theme.h +++ b/Telegram/SourceFiles/ui/chat/chat_theme.h @@ -184,6 +184,9 @@ struct ChatBackgroundRects { [[nodiscard]] QColor CountAverageColor(const QImage &image); [[nodiscard]] QColor CountAverageColor(const std::vector &colors); +[[nodiscard]] bool IsPatternInverted( + const std::vector &background, + float64 patternOpacity); [[nodiscard]] QColor ThemeAdjustedColor(QColor original, QColor background); [[nodiscard]] QImage PreprocessBackgroundImage(QImage image); [[nodiscard]] std::optional CalculateImageMonoColor( @@ -199,7 +202,8 @@ struct ChatBackgroundRects { const std::vector &bg, int gradientRotation, float64 patternOpacity = 1., - Fn drawPattern = nullptr); + Fn drawPattern = nullptr); +[[nodiscard]] QImage InvertPatternImage(QImage pattern); [[nodiscard]] QImage PreparePatternImage( QImage pattern, const std::vector &bg, diff --git a/Telegram/SourceFiles/window/themes/window_theme.cpp b/Telegram/SourceFiles/window/themes/window_theme.cpp index da483f1b52..8a66651956 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme.cpp @@ -722,6 +722,9 @@ void ChatBackground::setPreparedAfterPaper(QImage image) { QImage()); } else { image = postprocessBackgroundImage(std::move(image)); + if (Ui::IsPatternInverted(bgColors, _paper.patternOpacity())) { + image = Ui::InvertPatternImage(std::move(image)); + } setPrepared( image, image, diff --git a/Telegram/SourceFiles/window/window_main_menu.cpp b/Telegram/SourceFiles/window/window_main_menu.cpp index 49bf801407..015089253a 100644 --- a/Telegram/SourceFiles/window/window_main_menu.cpp +++ b/Telegram/SourceFiles/window/window_main_menu.cpp @@ -985,6 +985,9 @@ void MainMenu::refreshMenu() { } void MainMenu::refreshBackground() { + if (IsFilledCover()) { + return; + } const auto fill = QSize(st::mainMenuWidth, st::mainMenuCoverHeight); const auto intensityText = IntensityOfColor(st::mainMenuCoverFg->c); const auto background = Window::Theme::Background(); @@ -995,14 +998,14 @@ void MainMenu::refreshBackground() { fill, prepared.size()); - auto backgroundImage = paper.isPattern() + auto backgroundImage = /*paper.isPattern() ? Ui::GenerateBackgroundImage( fill * cIntRetinaFactor(), paper.backgroundColors(), paper.gradientRotation(), paper.patternOpacity(), [&](QPainter &p) { p.drawImage(rects.to, prepared, rects.from); }) - : QImage( + : */QImage( fill * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied); QPainter p(&backgroundImage); @@ -1019,20 +1022,20 @@ void MainMenu::refreshBackground() { }; // Solid color. - if (const auto color = background->colorForFill()) { - const auto intensity = IntensityOfColor(*color); - p.fillRect(QRect(QPoint(), fill), *color); - if (std::abs(intensity - intensityText) < kMinDiffIntensity) { - drawShadow(p); - } - _background = backgroundImage; - return; - } + //if (const auto color = background->colorForFill()) { + // const auto intensity = IntensityOfColor(*color); + // p.fillRect(QRect(QPoint(), fill), *color); + // if (std::abs(intensity - intensityText) < kMinDiffIntensity) { + // drawShadow(p); + // } + // _background = backgroundImage; + // return; + //} // Background image. - if (!paper.isPattern()) { + //if (!paper.isPattern()) { p.drawImage(rects.to, prepared, rects.from); - } + //} // Cut off the part of the background that is under text. const QRect underText(