diff --git a/Telegram/Resources/icons/menu_shadow.png b/Telegram/Resources/icons/menu_shadow.png new file mode 100644 index 0000000000..fabf8b6e74 Binary files /dev/null and b/Telegram/Resources/icons/menu_shadow.png differ diff --git a/Telegram/Resources/icons/menu_shadow@2x.png b/Telegram/Resources/icons/menu_shadow@2x.png new file mode 100644 index 0000000000..f1f8e9e4cf Binary files /dev/null and b/Telegram/Resources/icons/menu_shadow@2x.png differ diff --git a/Telegram/Resources/icons/menu_shadow@3x.png b/Telegram/Resources/icons/menu_shadow@3x.png new file mode 100644 index 0000000000..15cf662619 Binary files /dev/null and b/Telegram/Resources/icons/menu_shadow@3x.png differ diff --git a/Telegram/SourceFiles/window/window.style b/Telegram/SourceFiles/window/window.style index bb046e10ac..0ffe156e52 100644 --- a/Telegram/SourceFiles/window/window.style +++ b/Telegram/SourceFiles/window/window.style @@ -128,6 +128,7 @@ mainMenu: Menu(defaultMenu) { } itemToggleShift: 11px; } +mainMenuShadow: icon {{ "menu_shadow", windowShadowFg }}; mainMenuNewGroup: icon {{ "menu_new_group", menuIconFg }}; mainMenuNewGroupOver: icon {{ "menu_new_group", menuIconFgOver }}; mainMenuNewChannel: icon {{ "menu_new_channel", menuIconFg }}; diff --git a/Telegram/SourceFiles/window/window_main_menu.cpp b/Telegram/SourceFiles/window/window_main_menu.cpp index b85dbe0517..8add93a948 100644 --- a/Telegram/SourceFiles/window/window_main_menu.cpp +++ b/Telegram/SourceFiles/window/window_main_menu.cpp @@ -33,6 +33,30 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_settings.h" #include "styles/style_boxes.h" +namespace { + +constexpr auto kMinDiffIntensity = 0.25; + +float64 IntensityOfColor(QColor color) { + return (0.299 * color.red() + + 0.587 * color.green() + + 0.114 * color.blue()) / 255.0; +} + +bool IsShadowShown(const QImage &img, const QRect r, float64 intensityText) { + for (auto x = r.x(); x < r.x() + r.width(); x++) { + for (auto y = r.y(); y < r.y() + r.height(); y++) { + const auto intensity = IntensityOfColor(QColor(img.pixel(x, y))); + if ((std::abs(intensity - intensityText)) < kMinDiffIntensity) { + return true; + } + } + } + return false; +} + +} + namespace Window { class MainMenu::ResetScaleButton : public Ui::AbstractButton { @@ -122,6 +146,7 @@ MainMenu::MainMenu( Window::Theme::ToggleNightMode(); Window::Theme::KeepApplied(); } + refreshBackground(); } }); @@ -130,6 +155,7 @@ MainMenu::MainMenu( emit action->triggered(); }); refreshMenu(); + refreshBackground(); _telegram->setRichText(textcmdLink(1, qsl("Telegram Desktop"))); _telegram->setLink(1, std::make_shared(qsl("https://desktop.telegram.org"))); @@ -148,6 +174,7 @@ MainMenu::MainMenu( subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) { if (update.type == Window::Theme::BackgroundUpdate::Type::ApplyingTheme) { refreshMenu(); + refreshBackground(); } }); updatePhone(); @@ -220,6 +247,45 @@ void MainMenu::refreshMenu() { updatePhone(); } +void MainMenu::refreshBackground() { + const auto fill = QRect(0, 0, width(), st::mainMenuCoverHeight); + const auto intensityText = IntensityOfColor(st::mainMenuCoverFg->c); + QImage backgroundImage( + st::mainMenuWidth * cIntRetinaFactor(), + st::mainMenuCoverHeight * cIntRetinaFactor(), + QImage::Format_ARGB32_Premultiplied); + QPainter p(&backgroundImage); + + // Solid color. + if (const auto color = Window::Theme::Background()->colorForFill()) { + const auto intensity = IntensityOfColor(*color); + _isShadowShown = + (std::abs(intensity - intensityText) < kMinDiffIntensity); + p.fillRect(fill, *color); + _background = backgroundImage; + return; + } + + // Background image. + const auto &pixmap = Window::Theme::Background()->pixmap(); + QRect to, from; + Window::Theme::ComputeBackgroundRects(fill, pixmap.size(), to, from); + + p.drawPixmap(to, pixmap, from); + _background = backgroundImage; + + // Cut off the part of the background that is under text. + const QRect underText( + st::mainMenuCoverTextLeft, + st::mainMenuCoverNameTop, + std::max( + st::semiboldFont->width(Auth().user()->nameText.toString()), + st::normalFont->width(_phoneText)), + st::semiboldFont->height * 2); + + _isShadowShown = IsShadowShown(backgroundImage, underText, intensityText); +} + void MainMenu::resizeEvent(QResizeEvent *e) { _menu->setForceWidth(width()); updateControlsGeometry(); @@ -248,25 +314,30 @@ void MainMenu::updatePhone() { void MainMenu::paintEvent(QPaintEvent *e) { Painter p(this); const auto clip = e->rect(); - const auto fill = QRect(0, 0, width(), st::mainMenuCoverHeight); - const auto cover = fill.intersected(clip); + const auto cover = QRect(0, 0, width(), st::mainMenuCoverHeight) + .intersected(e->rect()); - if (const auto color = Window::Theme::Background()->colorForFill()) { - p.fillRect(fill, *color); - } else { + if (!_background.isNull()) { PainterHighQualityEnabler hq(p); - - const auto &pix = Window::Theme::Background()->pixmap(); - QRect to, from; - Window::Theme::ComputeBackgroundRects(fill, pix.size(), to, from); - p.drawPixmap(to, pix, from); + p.drawImage(0, 0, _background); } if (!cover.isEmpty()) { const auto widthText = _cloudButton ? _cloudButton->x() - st::mainMenuCloudSize : width() - 2 * st::mainMenuCoverTextLeft; - p.fillRect(cover, QColor(0, 0, 0, 51)); // 20% opacity. + + if (_isShadowShown) { + st::mainMenuShadow.paint( + p, + 0, + st::mainMenuCoverHeight - st::mainMenuShadow.height(), + st::mainMenuWidth, + IntensityOfColor(st::mainMenuCoverFg->c) < 0.5 + ? Qt::white + : Qt::black); + } + p.setPen(st::mainMenuCoverFg); p.setFont(st::semiboldFont); Auth().user()->nameText.drawLeftElided( diff --git a/Telegram/SourceFiles/window/window_main_menu.h b/Telegram/SourceFiles/window/window_main_menu.h index 8f182e9700..65a1487050 100644 --- a/Telegram/SourceFiles/window/window_main_menu.h +++ b/Telegram/SourceFiles/window/window_main_menu.h @@ -38,6 +38,7 @@ private: void updatePhone(); void initResetScaleButton(); void refreshMenu(); + void refreshBackground(); class ResetScaleButton; not_null _controller; @@ -51,6 +52,8 @@ private: base::Timer _nightThemeSwitch; QString _phoneText; + QImage _background; + bool _isShadowShown = false; };