diff --git a/Telegram/SourceFiles/boxes/language_box.cpp b/Telegram/SourceFiles/boxes/language_box.cpp index a02667ad2..85e4dacd1 100644 --- a/Telegram/SourceFiles/boxes/language_box.cpp +++ b/Telegram/SourceFiles/boxes/language_box.cpp @@ -373,8 +373,8 @@ void Rows::ensureRippleBySelection(not_null row, Selection selected) { const auto menu = v::is(selected); const auto menuArea = menuToggleArea(row); auto mask = menu - ? Ui::RippleAnimation::ellipseMask(menuArea.size()) - : Ui::RippleAnimation::rectMask({ width(), row->height }); + ? Ui::RippleAnimation::EllipseMask(menuArea.size()) + : Ui::RippleAnimation::RectMask({ width(), row->height }); ripple = std::make_unique( st::defaultRippleAnimation, std::move(mask), diff --git a/Telegram/SourceFiles/boxes/peer_list_box.cpp b/Telegram/SourceFiles/boxes/peer_list_box.cpp index 9459e46a7..409f7d616 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_box.cpp @@ -1410,7 +1410,7 @@ void PeerListContent::mousePressEvent(QMouseEvent *e) { row->addRipple(_st.item, _controller->customRowRippleMaskGenerator(), point, std::move(updateCallback)); } else { const auto maskGenerator = [&] { - return Ui::RippleAnimation::rectMask( + return Ui::RippleAnimation::RectMask( QSize(width(), _rowHeight)); }; row->addRipple(_st.item, maskGenerator, point, std::move(updateCallback)); diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp index 9fac46ddc..134e1b4a2 100644 --- a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp @@ -60,7 +60,7 @@ constexpr auto kSortByOnlineThrottle = 3 * crl::time(1000); //} // //QImage MembersAddButton::prepareRippleMask() const { -// return Ui::RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize)); +// return Ui::RippleAnimation::EllipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize)); //} // //QPoint MembersAddButton::prepareRippleStartPosition() const { diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.cpp index 566351120..928032923 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.cpp @@ -138,7 +138,7 @@ void Row::elementAddRipple( } auto &ripple = *pointer; if (!ripple) { - auto mask = Ui::RippleAnimation::roundRectMask( + auto mask = Ui::RippleAnimation::RoundRectMask( (element == kAcceptButton ? _delegate->rowAcceptButtonSize() : _delegate->rowRejectButtonSize()), diff --git a/Telegram/SourceFiles/boxes/stickers_box.cpp b/Telegram/SourceFiles/boxes/stickers_box.cpp index 057c62117..2a01f8be8 100644 --- a/Telegram/SourceFiles/boxes/stickers_box.cpp +++ b/Telegram/SourceFiles/boxes/stickers_box.cpp @@ -256,7 +256,9 @@ private: const Section _section; const bool _isInstalled; - int32 _rowHeight; + Ui::RoundRect _buttonBgOver, _buttonBg; + + int32 _rowHeight = 0; std::vector> _rows; std::vector> _oldRows; @@ -1126,6 +1128,16 @@ StickersBox::Inner::Inner( , _api(&_controller->session().mtp()) , _section(section) , _isInstalled(_section == Section::Installed || _section == Section::Masks) +, _buttonBgOver( + ImageRoundRadius::Small, + (_isInstalled + ? st::stickersUndoRemove + : st::stickersTrendingAdd).textBgOver) +, _buttonBg( + ImageRoundRadius::Small, + (_isInstalled + ? st::stickersUndoRemove + : st::stickersTrendingAdd).textBg) , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _shiftingAnimation([=](crl::time now) { return shiftingAnimationCallback(now); @@ -1147,6 +1159,16 @@ StickersBox::Inner::Inner( , _api(&_controller->session().mtp()) , _section(StickersBox::Section::Installed) , _isInstalled(_section == Section::Installed || _section == Section::Masks) +, _buttonBgOver( + ImageRoundRadius::Small, + (_isInstalled + ? st::stickersUndoRemove + : st::stickersTrendingAdd).textBgOver) +, _buttonBg( + ImageRoundRadius::Small, + (_isInstalled + ? st::stickersUndoRemove + : st::stickersTrendingAdd).textBg) , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _shiftingAnimation([=](crl::time now) { return shiftingAnimationCallback(now); @@ -1566,8 +1588,7 @@ void StickersBox::Inner::paintFakeButton(Painter &p, not_null row, int ind : st::stickersTrendingAdd; const auto textWidth = _isInstalled ? _undoWidth : _addWidth; const auto &text = _isInstalled ? _undoText : _addText; - const auto &textBg = selected ? st.textBgOver : st.textBg; - Ui::FillRoundRect(p, myrtlrect(rect), textBg, ImageRoundRadius::Small); + (selected ? _buttonBgOver : _buttonBg).paint(p, myrtlrect(rect)); if (row->ripple) { row->ripple->paint(p, rect.x(), rect.y(), width()); if (row->ripple->empty()) { @@ -1618,16 +1639,16 @@ void StickersBox::Inner::setActionDown(int newActionDown) { if (_isInstalled) { if (row->removed) { auto rippleSize = QSize(_undoWidth - st::stickersUndoRemove.width, st::stickersUndoRemove.height); - auto rippleMask = Ui::RippleAnimation::roundRectMask(rippleSize, st::roundRadiusSmall); + auto rippleMask = Ui::RippleAnimation::RoundRectMask(rippleSize, st::roundRadiusSmall); ensureRipple(st::stickersUndoRemove.ripple, std::move(rippleMask), removeButton); } else { auto rippleSize = st::stickersRemove.rippleAreaSize; - auto rippleMask = Ui::RippleAnimation::ellipseMask(QSize(rippleSize, rippleSize)); + auto rippleMask = Ui::RippleAnimation::EllipseMask(QSize(rippleSize, rippleSize)); ensureRipple(st::stickersRemove.ripple, std::move(rippleMask), removeButton); } } else if (!row->isInstalled() || row->isArchived() || row->removed) { auto rippleSize = QSize(_addWidth - st::stickersTrendingAdd.width, st::stickersTrendingAdd.height); - auto rippleMask = Ui::RippleAnimation::roundRectMask(rippleSize, st::roundRadiusSmall); + auto rippleMask = Ui::RippleAnimation::RoundRectMask(rippleSize, st::roundRadiusSmall); ensureRipple(st::stickersTrendingAdd.ripple, std::move(rippleMask), removeButton); } } @@ -1683,7 +1704,7 @@ void StickersBox::Inner::setPressed(SelectedRow pressed) { if (_megagroupSet && pressedIndex >= 0 && pressedIndex < _rows.size()) { update(0, _itemsTop + pressedIndex * _rowHeight, width(), _rowHeight); auto &set = _rows[pressedIndex]; - auto rippleMask = Ui::RippleAnimation::rectMask(QSize(width(), _rowHeight)); + auto rippleMask = Ui::RippleAnimation::RectMask(QSize(width(), _rowHeight)); if (!set->ripple) { set->ripple = std::make_unique(st::defaultRippleAnimation, std::move(rippleMask), [this, pressedIndex] { update(0, _itemsTop + pressedIndex * _rowHeight, width(), _rowHeight); diff --git a/Telegram/SourceFiles/calls/calls_box_controller.cpp b/Telegram/SourceFiles/calls/calls_box_controller.cpp index 67e5de1d9..e5af11c75 100644 --- a/Telegram/SourceFiles/calls/calls_box_controller.cpp +++ b/Telegram/SourceFiles/calls/calls_box_controller.cpp @@ -258,7 +258,7 @@ BoxController::Row::CallType BoxController::Row::ComputeCallType( void BoxController::Row::rightActionAddRipple(QPoint point, Fn updateCallback) { if (!_actionRipple) { - auto mask = Ui::RippleAnimation::ellipseMask( + auto mask = Ui::RippleAnimation::EllipseMask( QSize(_st->rippleAreaSize, _st->rippleAreaSize)); _actionRipple = std::make_unique( _st->ripple, diff --git a/Telegram/SourceFiles/calls/group/calls_group_members_row.cpp b/Telegram/SourceFiles/calls/group/calls_group_members_row.cpp index 9f5e0a4a4..f8e5a8a4c 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_members_row.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_members_row.cpp @@ -747,7 +747,7 @@ void MembersRow::rightActionAddRipple( QPoint point, Fn updateCallback) { if (!_actionRipple) { - auto mask = Ui::RippleAnimation::ellipseMask(QSize( + auto mask = Ui::RippleAnimation::EllipseMask(QSize( st::groupCallActiveButton.rippleAreaSize, st::groupCallActiveButton.rippleAreaSize)); _actionRipple = std::make_unique( diff --git a/Telegram/SourceFiles/calls/group/calls_group_menu.cpp b/Telegram/SourceFiles/calls/group/calls_group_menu.cpp index 0f7c2320e..108441492 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_menu.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_menu.cpp @@ -217,7 +217,7 @@ QPoint JoinAsAction::prepareRippleStartPosition() const { } QImage JoinAsAction::prepareRippleMask() const { - return Ui::RippleAnimation::rectMask(size()); + return Ui::RippleAnimation::RectMask(size()); } int JoinAsAction::contentHeight() const { @@ -365,7 +365,7 @@ QPoint RecordingAction::prepareRippleStartPosition() const { } QImage RecordingAction::prepareRippleMask() const { - return Ui::RippleAnimation::rectMask(size()); + return Ui::RippleAnimation::RectMask(size()); } int RecordingAction::contentHeight() const { diff --git a/Telegram/SourceFiles/calls/group/ui/desktop_capture_choose_source.cpp b/Telegram/SourceFiles/calls/group/ui/desktop_capture_choose_source.cpp index 0c77bbeb1..85fc07502 100644 --- a/Telegram/SourceFiles/calls/group/ui/desktop_capture_choose_source.cpp +++ b/Telegram/SourceFiles/calls/group/ui/desktop_capture_choose_source.cpp @@ -50,7 +50,7 @@ private: }; QImage SourceButton::prepareRippleMask() const { - return RippleAnimation::roundRectMask(size(), st::roundRadiusLarge); + return RippleAnimation::RoundRectMask(size(), st::roundRadiusLarge); } class Source final { diff --git a/Telegram/SourceFiles/chat_helpers/bot_keyboard.cpp b/Telegram/SourceFiles/chat_helpers/bot_keyboard.cpp index b83db33c7..05360cf0f 100644 --- a/Telegram/SourceFiles/chat_helpers/bot_keyboard.cpp +++ b/Telegram/SourceFiles/chat_helpers/bot_keyboard.cpp @@ -28,7 +28,9 @@ public: not_null parent, const style::BotKeyboardButton &st); - int buttonRadius() const override; + Images::CornersMaskRef buttonRounding( + Ui::BubbleRounding outer, + RectParts sides) const override; void startPaint(QPainter &p, const Ui::ChatStyle *st) const override; const style::TextStyle &textStyle() const override; @@ -39,6 +41,7 @@ protected: QPainter &p, const Ui::ChatStyle *st, const QRect &rect, + Ui::BubbleRounding rounding, float64 howMuchOver) const override; void paintButtonIcon( QPainter &p, @@ -76,14 +79,18 @@ void Style::repaint(not_null item) const { _parent->update(); } -int Style::buttonRadius() const { - return st::roundRadiusSmall; +Images::CornersMaskRef Style::buttonRounding( + Ui::BubbleRounding outer, + RectParts sides) const { + using namespace Images; + return CornersMaskRef(CornersMask(ImageRoundRadius::Small)); } void Style::paintButtonBg( QPainter &p, const Ui::ChatStyle *st, const QRect &rect, + Ui::BubbleRounding rounding, float64 howMuchOver) const { Ui::FillRoundRect(p, rect, st::botKbBg, Ui::BotKeyboardCorners); } @@ -131,7 +138,12 @@ void BotKeyboard::paintEvent(QPaintEvent *e) { if (_impl) { int x = rtl() ? st::botKbScroll.width : _st->margin; p.translate(x, st::botKbScroll.deltat); - _impl->paint(p, nullptr, width(), clip.translated(-x, -st::botKbScroll.deltat)); + _impl->paint( + p, + nullptr, + {}, + width(), + clip.translated(-x, -st::botKbScroll.deltat)); } } @@ -237,7 +249,7 @@ void BotKeyboard::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool activ void BotKeyboard::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) { if (!_impl) return; - _impl->clickHandlerPressedChanged(p, pressed); + _impl->clickHandlerPressedChanged(p, pressed, {}); } bool BotKeyboard::updateMarkup(HistoryItem *to, bool force) { diff --git a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp index bd3e142e0..9e75a58d6 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp @@ -1966,7 +1966,7 @@ std::unique_ptr EmojiListWidget::createButtonRipple( ? st::stickerPanRemoveSet.ripple : st::emojiPanButton.ripple; auto mask = remove - ? Ui::RippleAnimation::ellipseMask(QSize( + ? Ui::RippleAnimation::EllipseMask(QSize( st::stickerPanRemoveSet.rippleAreaSize, st::stickerPanRemoveSet.rippleAreaSize)) : rightButton(section).rippleMask; diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp index 43e1f4ef9..9f059c9a9 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp @@ -177,6 +177,16 @@ StickersListWidget::StickersListWidget( , _isMasks(masks) , _updateItemsTimer([=] { updateItems(); }) , _updateSetsTimer([=] { updateSets(); }) +, _trendingAddBgOver( + ImageRoundRadius::Small, + st::stickersTrendingAdd.textBgOver) +, _trendingAddBg(ImageRoundRadius::Small, st::stickersTrendingAdd.textBg) +, _groupCategoryAddBgOver( + ImageRoundRadius::Small, + st::stickerGroupCategoryAdd.textBgOver) +, _groupCategoryAddBg( + ImageRoundRadius::Small, + st::stickerGroupCategoryAdd.textBg) , _pathGradient(std::make_unique( st::windowBgRipple, st::windowBgOver, @@ -840,9 +850,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) { if (featuredHasAddButton(info.section)) { auto add = featuredAddRect(info); auto selected = selectedButton ? (selectedButton->section == info.section) : false; - auto &textBg = selected ? st::stickersTrendingAdd.textBgOver : st::stickersTrendingAdd.textBg; - - Ui::FillRoundRect(p, myrtlrect(add), textBg, ImageRoundRadius::Small); + (selected ? _trendingAddBgOver : _trendingAddBg).paint(p, myrtlrect(add)); if (set.ripple) { set.ripple->paint(p, add.x(), add.y(), width()); if (set.ripple->empty()) { @@ -1068,12 +1076,10 @@ void StickersListWidget::paintMegagroupEmptySet(Painter &p, int y, bool buttonSe auto infoLeft = megagroupSetInfoLeft(); _megagroupSetAbout.drawLeft(p, infoLeft, y, width() - infoLeft, width()); - auto &textBg = buttonSelected - ? st::stickerGroupCategoryAdd.textBgOver - : st::stickerGroupCategoryAdd.textBg; - auto button = _megagroupSetButtonRect.translated(0, y); - Ui::FillRoundRect(p, myrtlrect(button), textBg, ImageRoundRadius::Small); + (buttonSelected ? _groupCategoryAddBgOver : _groupCategoryAddBg).paint( + p, + myrtlrect(button)); if (_megagroupSetButtonRipple) { _megagroupSetButtonRipple->paint(p, button.x(), button.y(), width()); if (_megagroupSetButtonRipple->empty()) { @@ -1486,7 +1492,7 @@ void StickersListWidget::setPressed(OverState newPressed) { } else if (std::get_if(&_pressed)) { if (!_megagroupSetButtonRipple) { auto maskSize = _megagroupSetButtonRect.size(); - auto mask = Ui::RippleAnimation::roundRectMask(maskSize, st::roundRadiusSmall); + auto mask = Ui::RippleAnimation::RoundRectMask(maskSize, st::roundRadiusSmall); _megagroupSetButtonRipple = std::make_unique(st::stickerGroupCategoryAdd.ripple, std::move(mask), [this] { rtlupdate(megagroupSetButtonRectFinal()); }); @@ -1514,14 +1520,14 @@ std::unique_ptr StickersListWidget::createButtonRipple(int if (shownSets()[section].externalLayout) { auto maskSize = QSize(_addWidth - st::stickersTrendingAdd.width, st::stickersTrendingAdd.height); - auto mask = Ui::RippleAnimation::roundRectMask(maskSize, st::roundRadiusSmall); + auto mask = Ui::RippleAnimation::RoundRectMask(maskSize, st::roundRadiusSmall); return std::make_unique( st::stickersTrendingAdd.ripple, std::move(mask), [this, section] { rtlupdate(featuredAddRect(section)); }); } auto maskSize = QSize(st::stickerPanRemoveSet.rippleAreaSize, st::stickerPanRemoveSet.rippleAreaSize); - auto mask = Ui::RippleAnimation::ellipseMask(maskSize); + auto mask = Ui::RippleAnimation::EllipseMask(maskSize); return std::make_unique( st::stickerPanRemoveSet.ripple, std::move(mask), diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h index 3ca5e4b6a..32a7bf49e 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "chat_helpers/tabbed_selector.h" #include "data/stickers/data_stickers.h" +#include "ui/round_rect.h" #include "base/variant.h" #include "base/timer.h" @@ -365,6 +366,9 @@ private: OverState _pressed; QPoint _lastMousePosition; + Ui::RoundRect _trendingAddBgOver, _trendingAddBg; + Ui::RoundRect _groupCategoryAddBgOver, _groupCategoryAddBg; + const std::unique_ptr _pathGradient; Ui::Text::String _megagroupSetAbout; diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp index 2d36ddacf..8110dc962 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp @@ -298,6 +298,12 @@ TabbedSelector::TabbedSelector( , _controller(controller) , _level(level) , _mode(mode) +, _panelRounding(Ui::PrepareCornerPixmaps( + ImageRoundRadius::Small, + st::emojiPanBg)) +, _categoriesRounding(Ui::PrepareCornerPixmaps( + ImageRoundRadius::Small, + st::emojiPanCategories)) , _topShadow(full() ? object_ptr(this) : nullptr) , _bottomShadow(this) , _scroll(this, st::emojiScroll) @@ -410,6 +416,16 @@ TabbedSelector::TabbedSelector( }, lifetime()); } + style::PaletteChanged( + ) | rpl::start_with_next([=] { + _panelRounding = Ui::PrepareCornerPixmaps( + ImageRoundRadius::Small, + st::emojiPanBg); + _categoriesRounding = Ui::PrepareCornerPixmaps( + ImageRoundRadius::Small, + st::emojiPanCategories); + }, lifetime()); + if (hasEmojiTab()) { session().data().stickers().emojiSetInstalled( ) | rpl::start_with_next([=](uint64 setId) { @@ -646,26 +662,19 @@ void TabbedSelector::paintSlideFrame(QPainter &p) { } void TabbedSelector::paintBgRoundedPart(QPainter &p) { - const auto threeRadius = 3 * _roundRadius; - const auto topOrBottomPart = _dropDown - ? QRect(0, height() - threeRadius, width(), threeRadius) - : QRect( - 0, - 0, - width(), - (_tabsSlider - ? _tabsSlider->height() + _roundRadius - : threeRadius)); - Ui::FillRoundRect( - p, - topOrBottomPart, - st::emojiPanBg, - ImageRoundRadius::Small, - (_dropDown - ? RectPart::FullBottom - : tabbed() - ? (RectPart::FullTop | RectPart::NoTopBottom) - : RectPart::FullTop)); + const auto fill = _dropDown + ? QRect(0, height() - _roundRadius, width(), _roundRadius) + : _tabsSlider + ? QRect(0, 0, width(), _tabsSlider->height()) + : QRect(0, 0, width(), _roundRadius); + Ui::FillRoundRect(p, fill, st::emojiPanBg, { + .p = { + _dropDown ? QPixmap() : _panelRounding.p[0], + _dropDown ? QPixmap() : _panelRounding.p[1], + _dropDown ? _panelRounding.p[2] : QPixmap(), + _dropDown ? _panelRounding.p[3] : QPixmap(), + }, + }); } void TabbedSelector::paintContent(QPainter &p) { @@ -675,18 +684,22 @@ void TabbedSelector::paintContent(QPainter &p) { if (_roundRadius > 0) { paintBgRoundedPart(p); + const auto &pixmaps = hasSectionIcons() + ? _categoriesRounding + : _panelRounding; const auto footerPart = QRect( 0, - _footerTop - (_dropDown ? 0 : _roundRadius), + _footerTop, width(), - _st.footer + _roundRadius); - Ui::FillRoundRect( - p, - footerPart, - footerBg, - ImageRoundRadius::Small, - (RectPart::NoTopBottom - | (_dropDown ? RectPart::FullTop : RectPart::FullBottom))); + _st.footer); + Ui::FillRoundRect(p, footerPart, footerBg, { + .p = { + _dropDown ? pixmaps.p[0] : QPixmap(), + _dropDown ? pixmaps.p[1] : QPixmap(), + _dropDown ? QPixmap() : pixmaps.p[2], + _dropDown ? QPixmap() : pixmaps.p[3], + }, + }); } else { if (_tabsSlider) { p.fillRect(0, 0, width(), _tabsSlider->height(), st::emojiPanBg); diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h index c8c0256d7..f9e72cfb3 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h @@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/effects/animations.h" #include "ui/effects/message_sending_animation_common.h" #include "ui/effects/panel_animation.h" +#include "ui/cached_round_corners.h" #include "mtproto/sender.h" #include "base/object_ptr.h" @@ -252,6 +253,8 @@ private: Mode _mode = Mode::Full; int _roundRadius = 0; int _footerTop = 0; + Ui::CornersPixmaps _panelRounding; + Ui::CornersPixmaps _categoriesRounding; PeerData *_currentPeer = nullptr; class SlideAnimation; diff --git a/Telegram/SourceFiles/dialogs/dialogs_row.cpp b/Telegram/SourceFiles/dialogs/dialogs_row.cpp index ed87dd4d5..ea75cd16d 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_row.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_row.cpp @@ -93,7 +93,7 @@ void BasicRow::addRipple( QSize size, Fn updateCallback) { if (!_ripple) { - auto mask = Ui::RippleAnimation::rectMask(size); + auto mask = Ui::RippleAnimation::RectMask(size); _ripple = std::make_unique( st::dialogsRipple, std::move(mask), diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 9348c52d3..a40ad560d 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -922,7 +922,23 @@ void HistoryInner::paintEvent(QPaintEvent *e) { const auto stm = &st->messageStyle(false, false); if (clip.y() < _botAbout->rect.y() + _botAbout->rect.height() && clip.y() + clip.height() > _botAbout->rect.y()) { p.setTextPalette(stm->textPalette); - Ui::FillRoundRect(p, _botAbout->rect, stm->msgBg, stm->msgBgCornersLarge, &stm->msgShadow); + using Corner = Ui::BubbleCornerRounding; + const auto rounding = Ui::BubbleRounding{ + Corner::Large, + Corner::Large, + Corner::Large, + Corner::Large, + }; + Ui::PaintBubble(p, Ui::SimpleBubble{ + .st = st, + .geometry = _botAbout->rect, + .pattern = context.bubblesPattern, + .patternViewport = context.viewport, + .outerWidth = width(), + .selected = false, + .outbg = false, + .rounding = rounding, + }); auto top = _botAbout->rect.top() + st::msgPadding.top(); if (!_history->peer->isRepliesChat()) { diff --git a/Telegram/SourceFiles/history/history_item_components.cpp b/Telegram/SourceFiles/history/history_item_components.cpp index 1224c6f49..6a1e7d7d0 100644 --- a/Telegram/SourceFiles/history/history_item_components.cpp +++ b/Telegram/SourceFiles/history/history_item_components.cpp @@ -724,14 +724,16 @@ int ReplyKeyboard::naturalHeight() const { void ReplyKeyboard::paint( Painter &p, const Ui::ChatStyle *st, + Ui::BubbleRounding rounding, int outerWidth, const QRect &clip) const { Assert(_st != nullptr); Assert(_width > 0); _st->startPaint(p, st); - for (const auto &row : _rows) { - for (const auto &button : row) { + for (auto y = 0, rowsCount = int(_rows.size()); y != rowsCount; ++y) { + for (auto x = 0, count = int(_rows[y].size()); x != count; ++x) { + const auto &button = _rows[y][x]; const auto rect = button.rect; if (rect.y() >= clip.y() + clip.height()) return; if (rect.y() + rect.height() < clip.y()) continue; @@ -739,7 +741,20 @@ void ReplyKeyboard::paint( // just ignore the buttons that didn't layout well if (rect.x() + rect.width() > _width) break; - _st->paintButton(p, st, outerWidth, button); + auto buttonRounding = Ui::BubbleRounding(); + using Corner = Ui::BubbleCornerRounding; + buttonRounding.topLeft = buttonRounding.topRight = Corner::Small; + buttonRounding.bottomLeft = ((y + 1 == rowsCount) + && !x + && (rounding.bottomLeft == Corner::Large)) + ? Corner::Large + : Corner::Small; + buttonRounding.bottomRight = ((y + 1 == rowsCount) + && (x + 1 == count) + && (rounding.bottomRight == Corner::Large)) + ? Corner::Large + : Corner::Small; + _st->paintButton(p, st, outerWidth, button, buttonRounding); } } } @@ -787,7 +802,8 @@ ReplyKeyboard::ButtonCoords ReplyKeyboard::findButtonCoordsByClickHandler(const void ReplyKeyboard::clickHandlerPressedChanged( const ClickHandlerPtr &handler, - bool pressed) { + bool pressed, + Ui::BubbleRounding rounding) { if (!handler) return; _savedPressed = pressed ? handler : ClickHandlerPtr(); @@ -796,13 +812,22 @@ void ReplyKeyboard::clickHandlerPressedChanged( auto &button = _rows[coords.i][coords.j]; if (pressed) { if (!button.ripple) { - auto mask = Ui::RippleAnimation::roundRectMask( + const auto sides = RectPart() + | (!coords.i ? RectPart::Top : RectPart()) + | (!coords.j ? RectPart::Left : RectPart()) + | ((coords.i + 1 == _rows.size()) + ? RectPart::Bottom + : RectPart()) + | ((coords.j + 1 == _rows[coords.i].size()) + ? RectPart::Right + : RectPart()); + auto mask = Ui::RippleAnimation::RoundRectMask( button.rect.size(), - _st->buttonRadius()); + _st->buttonRounding(rounding, sides)); button.ripple = std::make_unique( _st->_st->ripple, std::move(mask), - [this] { _st->repaint(_item); }); + [=] { _st->repaint(_item); }); } button.ripple->add(_savedCoords - button.rect.topLeft()); } else { @@ -877,9 +902,10 @@ void ReplyKeyboard::Style::paintButton( Painter &p, const Ui::ChatStyle *st, int outerWidth, - const ReplyKeyboard::Button &button) const { + const ReplyKeyboard::Button &button, + Ui::BubbleRounding rounding) const { const QRect &rect = button.rect; - paintButtonBg(p, st, rect, button.howMuchOver); + paintButtonBg(p, st, rect, rounding, button.howMuchOver); if (button.ripple) { const auto color = st ? &st->msgBotKbRippleBg()->c : nullptr; button.ripple->paint(p, rect.x(), rect.y(), outerWidth, color); diff --git a/Telegram/SourceFiles/history/history_item_components.h b/Telegram/SourceFiles/history/history_item_components.h index 087f97706..4f78fbeae 100644 --- a/Telegram/SourceFiles/history/history_item_components.h +++ b/Telegram/SourceFiles/history/history_item_components.h @@ -25,6 +25,10 @@ namespace Data { class Session; } // namespace Data +namespace Images { +struct CornersMaskRef; +} // namespace Images + namespace HistoryView { class Element; class Document; @@ -323,7 +327,9 @@ public: int buttonSkip() const; int buttonPadding() const; int buttonHeight() const; - virtual int buttonRadius() const = 0; + [[nodiscard]] virtual Images::CornersMaskRef buttonRounding( + Ui::BubbleRounding outer, + RectParts sides) const = 0; virtual void repaint(not_null item) const = 0; virtual ~Style() { @@ -334,6 +340,7 @@ public: QPainter &p, const Ui::ChatStyle *st, const QRect &rect, + Ui::BubbleRounding rounding, float64 howMuchOver) const = 0; virtual void paintButtonIcon( QPainter &p, @@ -355,7 +362,8 @@ public: Painter &p, const Ui::ChatStyle *st, int outerWidth, - const ReplyKeyboard::Button &button) const; + const ReplyKeyboard::Button &button, + Ui::BubbleRounding rounding) const; friend class ReplyKeyboard; }; @@ -377,12 +385,18 @@ public: void paint( Painter &p, const Ui::ChatStyle *st, + Ui::BubbleRounding rounding, int outerWidth, const QRect &clip) const; ClickHandlerPtr getLink(QPoint point) const; - void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active); - void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed); + void clickHandlerActiveChanged( + const ClickHandlerPtr &p, + bool active); + void clickHandlerPressedChanged( + const ClickHandlerPtr &p, + bool pressed, + Ui::BubbleRounding rounding); void clearSelection(); void updateMessageId(); diff --git a/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.cpp b/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.cpp index e51cf48e5..aeb3ade75 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.cpp @@ -912,7 +912,7 @@ rpl::producer<> RecordLock::locks() const { } QImage RecordLock::prepareRippleMask() const { - return Ui::RippleAnimation::ellipseMask(_rippleRect.size()); + return Ui::RippleAnimation::EllipseMask(_rippleRect.size()); } QPoint RecordLock::prepareRippleStartPosition() const { @@ -976,7 +976,7 @@ void CancelButton::init() { } QImage CancelButton::prepareRippleMask() const { - return Ui::RippleAnimation::ellipseMask(_rippleRect.size()); + return Ui::RippleAnimation::EllipseMask(_rippleRect.size()); } QPoint CancelButton::prepareRippleStartPosition() const { diff --git a/Telegram/SourceFiles/history/view/history_view_element.cpp b/Telegram/SourceFiles/history/view/history_view_element.cpp index 110540f1d..d56231e99 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.cpp +++ b/Telegram/SourceFiles/history/view/history_view_element.cpp @@ -1216,11 +1216,6 @@ void Element::clickHandlerActiveChanged( void Element::clickHandlerPressedChanged( const ClickHandlerPtr &handler, bool pressed) { - if (const auto markup = _data->Get()) { - if (const auto keyboard = markup->inlineKeyboard.get()) { - keyboard->clickHandlerPressedChanged(handler, pressed); - } - } PressedLink(pressed ? this : nullptr); repaint(); if (const auto media = this->media()) { diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index b08dd7c01..7f2db6e68 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -63,7 +63,9 @@ class KeyboardStyle : public ReplyKeyboard::Style { public: using ReplyKeyboard::Style::Style; - int buttonRadius() const override; + Images::CornersMaskRef buttonRounding( + Ui::BubbleRounding outer, + RectParts sides) const override; void startPaint( QPainter &p, @@ -76,6 +78,7 @@ protected: QPainter &p, const Ui::ChatStyle *st, const QRect &rect, + Ui::BubbleRounding rounding, float64 howMuchOver) const override; void paintButtonIcon( QPainter &p, @@ -107,23 +110,54 @@ void KeyboardStyle::repaint(not_null item) const { item->history()->owner().requestItemRepaint(item); } -int KeyboardStyle::buttonRadius() const { - return st::dateRadius; +Images::CornersMaskRef KeyboardStyle::buttonRounding( + Ui::BubbleRounding outer, + RectParts sides) const { + using namespace Images; + using namespace Ui; + using Radius = CachedCornerRadius; + using Corner = BubbleCornerRounding; + auto result = CornersMaskRef(CachedCornersMasks(Radius::BubbleSmall)); + if (sides & RectPart::Bottom) { + const auto &large = CachedCornersMasks(Radius::BubbleLarge); + auto round = [&](RectPart side, int index) { + if ((sides & side) && (outer[index] == Corner::Large)) { + result.p[index] = &large[index]; + } + }; + round(RectPart::Left, kBottomLeft); + round(RectPart::Right, kBottomRight); + } + return result; } void KeyboardStyle::paintButtonBg( QPainter &p, const Ui::ChatStyle *st, const QRect &rect, + Ui::BubbleRounding rounding, float64 howMuchOver) const { Expects(st != nullptr); const auto sti = &st->imageStyle(false); - Ui::FillRoundRect(p, rect, sti->msgServiceBg, sti->msgServiceBgCorners); + const auto &small = sti->msgServiceBgCornersSmall; + const auto &large = sti->msgServiceBgCornersLarge; + auto corners = Ui::CornersPixmaps(); + using Corner = Ui::BubbleCornerRounding; + for (auto i = 0; i != 4; ++i) { + corners.p[i] = (rounding[i] == Corner::Large ? large : small).p[i]; + } + Ui::FillRoundRect(p, rect, sti->msgServiceBg, corners); if (howMuchOver > 0) { auto o = p.opacity(); p.setOpacity(o * howMuchOver); - Ui::FillRoundRect(p, rect, st->msgBotKbOverBgAdd(), st->msgBotKbOverBgAddCorners()); + const auto &small = st->msgBotKbOverBgAddCornersSmall(); + const auto &large = st->msgBotKbOverBgAddCornersLarge(); + auto over = Ui::CornersPixmaps(); + for (auto i = 0; i != 4; ++i) { + over.p[i] = (rounding[i] == Corner::Large ? large : small).p[i]; + } + Ui::FillRoundRect(p, rect, st->msgBotKbOverBgAdd(), over); p.setOpacity(o); } } @@ -354,7 +388,7 @@ void Message::animateReaction(Reactions::AnimationArgs &&args) { const auto bubble = drawBubble(); const auto reactionsInBubble = _reactions && embedReactionsInBubble(); const auto mediaDisplayed = media && media->isDisplayed(); - auto keyboard = item->inlineReplyKeyboard(); + const auto keyboard = item->inlineReplyKeyboard(); auto keyboardHeight = 0; if (keyboard) { keyboardHeight = keyboard->naturalHeight(); @@ -729,13 +763,19 @@ void Message::draw(Painter &p, const PaintContext &context) const { p.setTextPalette(stm->textPalette); - auto keyboard = item->inlineReplyKeyboard(); + const auto keyboard = item->inlineReplyKeyboard(); + const auto messageRounding = countMessageRounding(); if (keyboard) { const auto keyboardHeight = st::msgBotKbButton.margin + keyboard->naturalHeight(); g.setHeight(g.height() - keyboardHeight); const auto keyboardPosition = QPoint(g.left(), g.top() + g.height() + st::msgBotKbButton.margin); p.translate(keyboardPosition); - keyboard->paint(p, context.st, g.width(), context.clip.translated(-keyboardPosition)); + keyboard->paint( + p, + context.st, + messageRounding, + g.width(), + context.clip.translated(-keyboardPosition)); p.translate(-keyboardPosition); } @@ -772,7 +812,7 @@ void Message::draw(Painter &p, const PaintContext &context) const { .outerWidth = width(), .selected = context.selected(), .outbg = context.outbg, - .rounding = countBubbleRounding(), + .rounding = countBubbleRounding(messageRounding), }, .selection = mediaSelectionIntervals, }); @@ -1375,8 +1415,15 @@ bool Message::displayFromPhoto() const { void Message::clickHandlerPressedChanged( const ClickHandlerPtr &handler, bool pressed) { + if (const auto markup = data()->Get()) { + if (const auto keyboard = markup->inlineKeyboard.get()) { + keyboard->clickHandlerPressedChanged( + handler, + pressed, + countMessageRounding()); + } + } Element::clickHandlerPressedChanged(handler, pressed); - if (!handler) { return; } else if (_comments && (handler == _comments->link)) { @@ -1408,7 +1455,7 @@ void Message::toggleCommentsButtonRipple(bool pressed) { radius); p.fillRect(0, 0, linkWidth, radius * 2, Qt::white); }; - auto mask = Ui::RippleAnimation::maskByDrawer( + auto mask = Ui::RippleAnimation::MaskByDrawer( QSize(linkWidth, linkHeight), false, drawMask); @@ -2161,7 +2208,7 @@ void Message::drawInfo( } else if (type == InfoDisplayType::Background) { const auto dateW = size.width() + 2 * st::msgDateImgPadding.x(); const auto dateH = size.height() + 2 * st::msgDateImgPadding.y(); - Ui::FillRoundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, sti->msgServiceBg, sti->msgServiceBgCorners); + Ui::FillRoundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, sti->msgServiceBg, sti->msgServiceBgCornersSmall); } _bottomInfo.paint( p, @@ -2988,7 +3035,7 @@ QRect Message::countGeometry() const { height() - contentTop - marginBottom()); } -Ui::BubbleRounding Message::countBubbleRounding() const { +Ui::BubbleRounding Message::countMessageRounding() const { const auto smallTop = isAttachedToPrevious(); const auto smallBottom = isAttachedToNext(); const auto media = smallBottom ? nullptr : this->media(); @@ -3015,6 +3062,20 @@ Ui::BubbleRounding Message::countBubbleRounding() const { }; } +Ui::BubbleRounding Message::countBubbleRounding( + Ui::BubbleRounding messageRounding) const { + if (const auto keyboard = data()->inlineReplyKeyboard()) { + messageRounding.bottomLeft + = messageRounding.bottomRight + = Ui::BubbleCornerRounding::Small; + } + return messageRounding; +} + +Ui::BubbleRounding Message::countBubbleRounding() const { + return countBubbleRounding(countMessageRounding()); +} + int Message::resizeContentGetHeight(int newWidth) { if (isHidden()) { return marginTop() + marginBottom(); diff --git a/Telegram/SourceFiles/history/view/history_view_message.h b/Telegram/SourceFiles/history/view/history_view_message.h index 28d11272a..a7ce22195 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.h +++ b/Telegram/SourceFiles/history/view/history_view_message.h @@ -225,6 +225,9 @@ private: void updateMediaInBubbleState(); QRect countGeometry() const; + [[nodiscard]] Ui::BubbleRounding countMessageRounding() const; + [[nodiscard]] Ui::BubbleRounding countBubbleRounding( + Ui::BubbleRounding messageRounding) const; [[nodiscard]] Ui::BubbleRounding countBubbleRounding() const; int resizeContentGetHeight(int newWidth); diff --git a/Telegram/SourceFiles/history/view/history_view_view_button.cpp b/Telegram/SourceFiles/history/view/history_view_view_button.cpp index 1d7cba92f..0d6f90c47 100644 --- a/Telegram/SourceFiles/history/view/history_view_view_button.cpp +++ b/Telegram/SourceFiles/history/view/history_view_view_button.cpp @@ -169,7 +169,7 @@ ViewButton::Inner::Inner( void ViewButton::Inner::updateMask(int height) { ripple = std::make_unique( st::defaultRippleAnimation, - Ui::RippleAnimation::roundRectMask( + Ui::RippleAnimation::RoundRectMask( QSize(lastWidth, height - margins.top() - margins.bottom()), st::roundRadiusLarge), updateCallback); diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp index 6366d1f0b..3d5656bfc 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp @@ -564,7 +564,7 @@ void Gif::draw(Painter &p, const PaintContext &context) const { if (mediaUnread) { statusW += st::mediaUnreadSkip + st::mediaUnreadSize; } - Ui::FillRoundRect(p, style::rtlrect(statusX - st::msgDateImgPadding.x(), statusY - st::msgDateImgPadding.y(), statusW, statusH, width()), sti->msgServiceBg, sti->msgServiceBgCorners); + Ui::FillRoundRect(p, style::rtlrect(statusX - st::msgDateImgPadding.x(), statusY - st::msgDateImgPadding.y(), statusW, statusH, width()), sti->msgServiceBg, sti->msgServiceBgCornersSmall); p.setFont(st::normalFont); p.setPen(st->msgServiceFg()); p.drawTextLeft(statusX, statusY, width(), _statusText, statusW - 2 * st::msgDateImgPadding.x()); @@ -596,7 +596,7 @@ void Gif::draw(Painter &p, const PaintContext &context) const { int recty = painty; if (rtl()) rectx = width() - rectx - rectw; - Ui::FillRoundRect(p, rectx, recty, rectw, recth, sti->msgServiceBg, sti->msgServiceBgCorners); + Ui::FillRoundRect(p, rectx, recty, rectw, recth, sti->msgServiceBg, sti->msgServiceBgCornersSmall); p.setPen(st->msgServiceFg()); rectx += st::msgReplyPadding.left(); rectw = innerw; diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp b/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp index b90e5acea..ccd07c1d8 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media_unwrapped.cpp @@ -227,7 +227,7 @@ void UnwrappedMedia::drawSurrounding( int recty = 0; if (rtl()) rectx = width() - rectx - rectw; - Ui::FillRoundRect(p, rectx, recty, rectw, recth, sti->msgServiceBg, sti->msgServiceBgCorners); + Ui::FillRoundRect(p, rectx, recty, rectw, recth, sti->msgServiceBg, sti->msgServiceBgCornersSmall); p.setPen(st->msgServiceFg()); rectx += st::msgReplyPadding.left(); rectw -= st::msgReplyPadding.left() + st::msgReplyPadding.right(); diff --git a/Telegram/SourceFiles/history/view/media/history_view_poll.cpp b/Telegram/SourceFiles/history/view/media/history_view_poll.cpp index ef91615d1..a940b79b7 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_poll.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_poll.cpp @@ -1519,7 +1519,7 @@ void Poll::toggleRipple(Answer &answer, bool pressed) { - st::msgPadding.left() - st::msgPadding.right(); if (!answer.ripple) { - auto mask = Ui::RippleAnimation::rectMask(QSize( + auto mask = Ui::RippleAnimation::RectMask(QSize( outerWidth, countAnswerHeight(answer, innerWidth))); answer.ripple = std::make_unique( @@ -1581,11 +1581,11 @@ void Poll::toggleLinkRipple(bool pressed) { p.fillRect(0, 0, linkWidth, radius * 2, Qt::white); }; auto mask = isRoundedInBubbleBottom() - ? Ui::RippleAnimation::maskByDrawer( + ? Ui::RippleAnimation::MaskByDrawer( QSize(linkWidth, linkHeight), false, drawMask) - : Ui::RippleAnimation::rectMask({ linkWidth, linkHeight }); + : Ui::RippleAnimation::RectMask({ linkWidth, linkHeight }); _linkRipple = std::make_unique( st::defaultRippleAnimation, std::move(mask), diff --git a/Telegram/SourceFiles/history/view/media/history_view_service_media_gift.cpp b/Telegram/SourceFiles/history/view/media/history_view_service_media_gift.cpp index 7431db6cf..589d03b0d 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_service_media_gift.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_service_media_gift.cpp @@ -259,7 +259,7 @@ void MediaGift::Button::toggleRipple(bool pressed) { const auto linkHeight = size.height(); if (!ripple) { const auto drawMask = [&](QPainter &p) { drawBg(p); }; - auto mask = Ui::RippleAnimation::maskByDrawer( + auto mask = Ui::RippleAnimation::MaskByDrawer( QSize(linkWidth, linkHeight), false, drawMask); diff --git a/Telegram/SourceFiles/info/info_layer_widget.cpp b/Telegram/SourceFiles/info/info_layer_widget.cpp index 952c8b767..5b2fb6e5d 100644 --- a/Telegram/SourceFiles/info/info_layer_widget.cpp +++ b/Telegram/SourceFiles/info/info_layer_widget.cpp @@ -326,14 +326,16 @@ void LayerWidget::paintEvent(QPaintEvent *e) { const auto clip = e->rect(); const auto radius = st::boxRadius; - auto parts = RectPart::None | 0; + const auto &corners = Ui::CachedCornerPixmaps(Ui::BoxCorners); if (!_tillBottom) { const auto bottom = QRect{ 0, height() - radius, width(), radius }; if (clip.intersects(bottom)) { if (const auto rounding = _content->bottomSkipRounding()) { rounding->paint(p, rect(), RectPart::FullBottom); } else { - parts |= RectPart::FullBottom; + Ui::FillRoundRect(p, bottom, st::boxBg, { + .p = { QPixmap(), QPixmap(), corners.p[2], corners.p[3] } + }); } } } else if (!_contentTillBottom) { @@ -342,19 +344,13 @@ void LayerWidget::paintEvent(QPaintEvent *e) { p.fillRect(0, height() - radius, width(), radius, color); } if (_content->animatingShow()) { - if (clip.intersects({ 0, 0, width(), radius })) { - parts |= RectPart::FullTop; + const auto top = QRect{ 0, 0, width(), radius }; + if (clip.intersects(top)) { + Ui::FillRoundRect(p, top, st::boxBg, { + .p = { corners.p[0], corners.p[1], QPixmap(), QPixmap() } + }); } - parts |= RectPart::Left | RectPart::Center | RectPart::Right; - } - if (parts) { - Ui::FillRoundRect( - p, - rect(), - st::boxBg, - Ui::BoxCorners, - nullptr, - parts); + p.fillRect(0, radius, width(), height() - 2 * radius, st::boxBg); } } diff --git a/Telegram/SourceFiles/info/info_wrap_widget.cpp b/Telegram/SourceFiles/info/info_wrap_widget.cpp index 895e623f6..5e9414c68 100644 --- a/Telegram/SourceFiles/info/info_wrap_widget.cpp +++ b/Telegram/SourceFiles/info/info_wrap_widget.cpp @@ -18,7 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "settings/settings_chat.h" #include "settings/settings_main.h" #include "settings/settings_premium.h" -#include "ui/effects/ripple_animation.h" // maskByDrawer. +#include "ui/effects/ripple_animation.h" // MaskByDrawer. #include "ui/widgets/discrete_sliders.h" #include "ui/widgets/buttons.h" #include "ui/widgets/shadow.h" @@ -986,7 +986,7 @@ void WrapWidget::showNewContent( const auto s = QSize( newContent->width(), animationParams.topSkip); - auto image = Ui::RippleAnimation::maskByDrawer(s, false, [&]( + auto image = Ui::RippleAnimation::MaskByDrawer(s, false, [&]( QPainter &p) { const auto r = QRect(0, 0, s.width(), s.height() * 2); p.drawRoundedRect(r, st::boxRadius, st::boxRadius); diff --git a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp index d21d55359..67a8769ea 100644 --- a/Telegram/SourceFiles/info/media/info_media_list_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_list_widget.cpp @@ -777,8 +777,7 @@ void ListWidget::paintEvent(QPaintEvent *e) { if (_dateBadge->corners.p[0].isNull()) { _dateBadge->corners = Ui::PrepareCornerPixmaps( Ui::HistoryServiceMsgRadius(), - st::roundedBg, - nullptr); + st::roundedBg); } HistoryView::ServiceMessagePainter::PaintDate( p, diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp index 83f2e0cc4..f71b84116 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp @@ -336,7 +336,7 @@ QPoint BotAction::prepareRippleStartPosition() const { } QImage BotAction::prepareRippleMask() const { - return Ui::RippleAnimation::rectMask(size()); + return Ui::RippleAnimation::RectMask(size()); } int BotAction::contentHeight() const { diff --git a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp index 5465ae22c..37320de40 100644 --- a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp @@ -36,6 +36,9 @@ Widget::Widget( , _contentMaxHeight(st::emojiPanMaxHeight) , _contentHeight(_contentMaxHeight) , _scroll(this, st::inlineBotsScroll) +, _innerRounding(Ui::PrepareCornerPixmaps( + ImageRoundRadius::Small, + st::emojiPanBg)) , _inlineRequestTimer([=] { onInlineRequest(); }) { resize(QRect(0, 0, st::emojiPanWidth, _contentHeight).marginsAdded(innerPadding()).size()); _width = width(); @@ -59,6 +62,13 @@ Widget::Widget( _inner->clearInlineRowsPanel(); }, lifetime()); + style::PaletteChanged( + ) | rpl::start_with_next([=] { + _innerRounding = Ui::PrepareCornerPixmaps( + ImageRoundRadius::Small, + st::emojiPanBg); + }, lifetime()); + macWindowDeactivateEvents( ) | rpl::filter([=] { return !isHidden(); @@ -150,7 +160,17 @@ void Widget::paintEvent(QPaintEvent *e) { void Widget::paintContent(QPainter &p) { auto inner = innerRect(); - Ui::FillRoundRect(p, inner, st::emojiPanBg, ImageRoundRadius::Small, RectPart::FullTop | RectPart::FullBottom); + const auto radius = st::roundRadiusSmall; + + const auto top = Ui::CornersPixmaps{ + .p = { _innerRounding.p[0], _innerRounding.p[1], QPixmap(), QPixmap() }, + }; + Ui::FillRoundRect(p, inner.x(), inner.y(), inner.width(), radius, st::emojiPanBg, top); + + const auto bottom = Ui::CornersPixmaps{ + .p = { QPixmap(), QPixmap(), _innerRounding.p[2], _innerRounding.p[3] }, + }; + Ui::FillRoundRect(p, inner.x(), inner.y() + inner.height() - radius, inner.width(), radius, st::emojiPanBg, bottom); auto horizontal = horizontalRect(); auto sidesTop = horizontal.y(); diff --git a/Telegram/SourceFiles/inline_bots/inline_results_widget.h b/Telegram/SourceFiles/inline_bots/inline_results_widget.h index c46f4f1d9..7f8079680 100644 --- a/Telegram/SourceFiles/inline_bots/inline_results_widget.h +++ b/Telegram/SourceFiles/inline_bots/inline_results_widget.h @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/rp_widget.h" #include "ui/abstract_button.h" +#include "ui/cached_round_corners.h" #include "ui/widgets/tooltip.h" #include "ui/effects/animations.h" #include "ui/effects/panel_animation.h" @@ -144,6 +145,7 @@ private: object_ptr _scroll; QPointer _inner; + Ui::CornersPixmaps _innerRounding; std::map> _inlineCache; base::Timer _inlineRequestTimer; diff --git a/Telegram/SourceFiles/media/player/media_player_dropdown.cpp b/Telegram/SourceFiles/media/player/media_player_dropdown.cpp index 516f71e33..71aa31d11 100644 --- a/Telegram/SourceFiles/media/player/media_player_dropdown.cpp +++ b/Telegram/SourceFiles/media/player/media_player_dropdown.cpp @@ -71,8 +71,18 @@ void Dropdown::paintEvent(QPaintEvent *e) { auto shadowedRect = rect().marginsRemoved(getMargin()); auto shadowedSides = RectPart::Left | RectPart::Right | RectPart::Bottom; Ui::Shadow::paint(p, shadowedRect, width(), st::defaultRoundShadow, shadowedSides); - auto parts = RectPart::NoTopBottom | RectPart::FullBottom; - Ui::FillRoundRect(p, QRect(shadowedRect.x(), -st::roundRadiusSmall, shadowedRect.width(), shadowedRect.y() + shadowedRect.height() + st::roundRadiusSmall), st::menuBg, Ui::MenuCorners, nullptr, parts); + const auto &corners = Ui::CachedCornerPixmaps(Ui::MenuCorners); + const auto fill = Ui::CornersPixmaps{ + .p = { QPixmap(), QPixmap(), corners.p[2], corners.p[3] }, + }; + Ui::FillRoundRect( + p, + shadowedRect.x(), + 0, + shadowedRect.width(), + shadowedRect.y() + shadowedRect.height(), + st::menuBg, + fill); } void Dropdown::enterEventHook(QEnterEvent *e) { diff --git a/Telegram/SourceFiles/media/player/media_player_panel.cpp b/Telegram/SourceFiles/media/player/media_player_panel.cpp index 1a36d1621..23c77b460 100644 --- a/Telegram/SourceFiles/media/player/media_player_panel.cpp +++ b/Telegram/SourceFiles/media/player/media_player_panel.cpp @@ -160,8 +160,7 @@ void Panel::paintEvent(QPaintEvent *e) { | (rtl() ? RectPart::Left : RectPart::Right) | RectPart::Top; Ui::Shadow::paint(p, shadowedRect, width(), st::defaultRoundShadow, shadowedSides); - auto parts = RectPart::Full; - Ui::FillRoundRect(p, shadowedRect, st::menuBg, Ui::MenuCorners, nullptr, parts); + Ui::FillRoundRect(p, shadowedRect, st::menuBg, Ui::MenuCorners); } void Panel::enterEventHook(QEnterEvent *e) { diff --git a/Telegram/SourceFiles/profile/profile_block_peer_list.cpp b/Telegram/SourceFiles/profile/profile_block_peer_list.cpp index fa19b2c9f..130692e47 100644 --- a/Telegram/SourceFiles/profile/profile_block_peer_list.cpp +++ b/Telegram/SourceFiles/profile/profile_block_peer_list.cpp @@ -149,7 +149,7 @@ void PeerListWidget::mousePressEvent(QMouseEvent *e) { const auto item = _items[_pressed]; if (!item->ripple) { auto memberRowWidth = rowWidth(); - auto mask = Ui::RippleAnimation::rectMask(QSize(memberRowWidth, _st.height)); + auto mask = Ui::RippleAnimation::RectMask(QSize(memberRowWidth, _st.height)); item->ripple = std::make_unique(_st.button.ripple, std::move(mask), [this, index = _pressed] { repaintRow(index); }); diff --git a/Telegram/SourceFiles/settings/settings_intro.cpp b/Telegram/SourceFiles/settings/settings_intro.cpp index 17537fbfb..378559045 100644 --- a/Telegram/SourceFiles/settings/settings_intro.cpp +++ b/Telegram/SourceFiles/settings/settings_intro.cpp @@ -515,20 +515,16 @@ void LayerWidget::paintEvent(QPaintEvent *e) { auto clip = e->rect(); auto r = st::boxRadius; auto parts = RectPart::None | 0; + const auto &pixmaps = Ui::CachedCornerPixmaps(Ui::BoxCorners); if (!_tillTop && clip.intersects({ 0, 0, width(), r })) { - parts |= RectPart::FullTop; + Ui::FillRoundRect(p, 0, 0, width(), r, st::boxBg, { + .p = { pixmaps.p[0], pixmaps.p[1], QPixmap(), QPixmap() }, + }); } if (!_tillBottom && clip.intersects({ 0, height() - r, width(), r })) { - parts |= RectPart::FullBottom; - } - if (parts) { - Ui::FillRoundRect( - p, - rect(), - st::boxBg, - Ui::BoxCorners, - nullptr, - parts); + Ui::FillRoundRect(p, 0, height() - r, width(), r, st::boxBg, { + .p = { QPixmap(), QPixmap(), pixmaps.p[2], pixmaps.p[3] }, + }); } if (_tillTop) { p.fillRect(0, 0, width(), r, st::boxBg); diff --git a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp index 4e72afa64..4fc3a7054 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp @@ -277,14 +277,13 @@ struct ForwardedTooltip { { line, line, line, line + arrowSize }); const auto origin = full.topLeft(); + const auto rounded = std::make_shared( + ImageRoundRadius::Large, + st::toastBg); const auto paint = [=](QPainter &p) { p.translate(-origin); - Ui::FillRoundRect( - p, - geometry, - st::toastBg, - ImageRoundRadius::Large); + rounded->paint(p, geometry); p.setFont(font); p.setPen(st::toastFg); diff --git a/Telegram/SourceFiles/ui/boxes/calendar_box.cpp b/Telegram/SourceFiles/ui/boxes/calendar_box.cpp index b6fb9cb00..5c46fbff4 100644 --- a/Telegram/SourceFiles/ui/boxes/calendar_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/calendar_box.cpp @@ -416,8 +416,7 @@ CalendarBox::FloatingDate::FloatingDate( , _corners( PrepareCornerPixmaps( HistoryServiceMsgRadius(), - st::roundedBg, - nullptr)) { + st::roundedBg)) { _context->monthValue( ) | rpl::start_with_next([=](QDate month) { _text = langMonthOfYearFull(month.month(), month.year()); @@ -670,7 +669,7 @@ void CalendarBox::Inner::mousePressEvent(QMouseEvent *e) { auto cell = QRect(rowsLeft() + col * _st.cellSize.width(), rowsTop() + row * _st.cellSize.height(), _st.cellSize.width(), _st.cellSize.height()); auto it = _ripples.find(_selected); if (it == _ripples.cend()) { - auto mask = RippleAnimation::ellipseMask(QSize(_st.cellInner, _st.cellInner)); + auto mask = RippleAnimation::EllipseMask(QSize(_st.cellInner, _st.cellInner)); auto update = [this, cell] { rtlupdate(cell); }; it = _ripples.emplace(_selected, std::make_unique(st::defaultRippleAnimation, std::move(mask), std::move(update))).first; } diff --git a/Telegram/SourceFiles/ui/boxes/country_select_box.cpp b/Telegram/SourceFiles/ui/boxes/country_select_box.cpp index 66ccadbf0..0d21dacdb 100644 --- a/Telegram/SourceFiles/ui/boxes/country_select_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/country_select_box.cpp @@ -347,7 +347,7 @@ void CountrySelectBox::Inner::mousePressEvent(QMouseEvent *e) { } } if (!_ripples[_pressed]) { - auto mask = RippleAnimation::rectMask(QSize(width(), _rowHeight)); + auto mask = RippleAnimation::RectMask(QSize(width(), _rowHeight)); _ripples[_pressed] = std::make_unique(st::countryRipple, std::move(mask), [this, index = _pressed] { updateRow(index); }); diff --git a/Telegram/SourceFiles/ui/cached_round_corners.cpp b/Telegram/SourceFiles/ui/cached_round_corners.cpp index 38fd751d1..ee7bdd55d 100644 --- a/Telegram/SourceFiles/ui/cached_round_corners.cpp +++ b/Telegram/SourceFiles/ui/cached_round_corners.cpp @@ -22,7 +22,6 @@ namespace { constexpr auto kCachedCornerRadiusCount = int(CachedCornerRadius::kCount); std::vector Corners; -base::flat_map CornersMap; QImage CornersMaskLarge[4], CornersMaskSmall[4]; rpl::lifetime PaletteChangedLifetime; @@ -109,56 +108,84 @@ void StartCachedCorners() { void FinishCachedCorners() { Corners.clear(); - CornersMap.clear(); PaletteChangedLifetime.destroy(); } -void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, const CornersPixmaps &corner, const style::color *shadow, RectParts parts) { - auto cornerWidth = corner.p[0].width() / style::DevicePixelRatio(); - auto cornerHeight = corner.p[0].height() / style::DevicePixelRatio(); - if (w < 2 * cornerWidth || h < 2 * cornerHeight) return; - if (w > 2 * cornerWidth) { - if (parts & RectPart::Top) { - p.fillRect(x + cornerWidth, y, w - 2 * cornerWidth, cornerHeight, bg); +void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, const CornersPixmaps &corners) { + using namespace Images; + + const auto fillBg = [&](QRect rect) { + p.fillRect(rect, bg); + }; + const auto fillCorner = [&](int x, int y, int index) { + if (const auto &pix = corners.p[index]; !pix.isNull()) { + p.drawPixmap(x, y, pix); } - if (parts & RectPart::Bottom) { - p.fillRect(x + cornerWidth, y + h - cornerHeight, w - 2 * cornerWidth, cornerHeight, bg); - if (shadow) { - p.fillRect(x + cornerWidth, y + h, w - 2 * cornerWidth, st::msgShadow, *shadow); + }; + + if (corners.p[kTopLeft].isNull() + && corners.p[kTopRight].isNull() + && corners.p[kBottomLeft].isNull() + && corners.p[kBottomRight].isNull()) { + p.fillRect(x, y, w, h, bg); + return; + } + const auto ratio = style::DevicePixelRatio(); + const auto cornerSize = [&](int index) { + return corners.p[index].isNull() + ? 0 + : (corners.p[index].width() / ratio); + }; + const auto verticalSkip = [&](int left, int right) { + return std::max(cornerSize(left), cornerSize(right)); + }; + const auto top = verticalSkip(kTopLeft, kTopRight); + const auto bottom = verticalSkip(kBottomLeft, kBottomRight); + if (top) { + const auto left = cornerSize(kTopLeft); + const auto right = cornerSize(kTopRight); + if (left) { + fillCorner(x, y, kTopLeft); + if (const auto add = top - left) { + fillBg({ x, y + left, left, add }); + } + } + if (const auto fill = w - left - right; fill > 0) { + fillBg({ x + left, y, fill, top }); + } + if (right) { + fillCorner(x + w - right, y, kTopRight); + if (const auto add = top - right) { + fillBg({ x + w - right, y + right, right, add }); } } } - if (h > 2 * cornerHeight) { - if ((parts & RectPart::NoTopBottom) == RectPart::NoTopBottom) { - p.fillRect(x, y + cornerHeight, w, h - 2 * cornerHeight, bg); - } else { - if (parts & RectPart::Left) { - p.fillRect(x, y + cornerHeight, cornerWidth, h - 2 * cornerHeight, bg); - } - if ((parts & RectPart::Center) && w > 2 * cornerWidth) { - p.fillRect(x + cornerWidth, y + cornerHeight, w - 2 * cornerWidth, h - 2 * cornerHeight, bg); - } - if (parts & RectPart::Right) { - p.fillRect(x + w - cornerWidth, y + cornerHeight, cornerWidth, h - 2 * cornerHeight, bg); + if (const auto fill = h - top - bottom; fill > 0) { + fillBg({ x, y + top, w, fill }); + } + if (bottom) { + const auto left = cornerSize(kBottomLeft); + const auto right = cornerSize(kBottomRight); + if (left) { + fillCorner(x, y + h - left, kBottomLeft); + if (const auto add = bottom - left) { + fillBg({ x, y + h - bottom, left, add }); + } + } + if (const auto fill = w - left - right; fill > 0) { + fillBg({ x + left, y + h - bottom, fill, bottom }); + } + if (right) { + fillCorner(x + w - right, y + h - right, kBottomRight); + if (const auto add = bottom - right) { + fillBg({ x + w - right, y + h - bottom, right, add }); } } - } - if (parts & RectPart::TopLeft) { - p.drawPixmap(x, y, corner.p[0]); - } - if (parts & RectPart::TopRight) { - p.drawPixmap(x + w - cornerWidth, y, corner.p[1]); - } - if (parts & RectPart::BottomLeft) { - p.drawPixmap(x, y + h - cornerHeight, corner.p[2]); - } - if (parts & RectPart::BottomRight) { - p.drawPixmap(x + w - cornerWidth, y + h - cornerHeight, corner.p[3]); } } -void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, CachedRoundCorners index, const style::color *shadow, RectParts parts) { - FillRoundRect(p, x, y, w, h, bg, Corners[index], shadow, parts); +void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, CachedRoundCorners index) { + FillRoundRect(p, x, y, w, h, bg, CachedCornerPixmaps(index)); } void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, const CornersPixmaps &corners) { @@ -188,6 +215,12 @@ void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::col fillCorner(x + w - right, y + h + st::msgShadow, kRight); } +const CornersPixmaps &CachedCornerPixmaps(CachedRoundCorners index) { + Expects(index >= 0 && index < RoundCornersCount); + + return Corners[index]; +} + CornersPixmaps PrepareCornerPixmaps(int32 radius, style::color bg, const style::color *sh) { auto images = PrepareCorners(radius, bg, sh); auto result = CornersPixmaps(); @@ -208,24 +241,6 @@ CornersPixmaps PrepareCornerPixmaps(ImageRoundRadius radius, style::color bg, co Unexpected("Image round radius in PrepareCornerPixmaps."); } -void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, ImageRoundRadius radius, RectParts parts) { - if (radius == ImageRoundRadius::None) { - p.fillRect(x, y, w, h, bg); - return; - } - const auto colorKey = ((uint32(bg->c.alpha()) & 0xFF) << 24) - | ((uint32(bg->c.red()) & 0xFF) << 16) - | ((uint32(bg->c.green()) & 0xFF) << 8) - | ((uint32(bg->c.blue()) & 0xFF)); - auto i = CornersMap.find(colorKey); - if (i == end(CornersMap)) { - i = CornersMap.emplace( - colorKey, - PrepareCornerPixmaps(radius, bg, nullptr)).first; - } - FillRoundRect(p, x, y, w, h, bg, i->second, nullptr, parts); -} - [[nodiscard]] int CachedCornerRadiusValue(CachedCornerRadius tag) { using Radius = CachedCornerRadius; switch (tag) { diff --git a/Telegram/SourceFiles/ui/cached_round_corners.h b/Telegram/SourceFiles/ui/cached_round_corners.h index d9d972715..e152e44f9 100644 --- a/Telegram/SourceFiles/ui/cached_round_corners.h +++ b/Telegram/SourceFiles/ui/cached_round_corners.h @@ -36,26 +36,23 @@ enum CachedRoundCorners : int { RoundCornersCount }; -void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, CachedRoundCorners index, const style::color *shadow = nullptr, RectParts parts = RectPart::Full); -inline void FillRoundRect(QPainter &p, const QRect &rect, style::color bg, CachedRoundCorners index, const style::color *shadow = nullptr, RectParts parts = RectPart::Full) { - FillRoundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, index, shadow, parts); -} -void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, ImageRoundRadius radius, RectParts parts = RectPart::Full); -inline void FillRoundRect(QPainter &p, const QRect &rect, style::color bg, ImageRoundRadius radius, RectParts parts = RectPart::Full) { - FillRoundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, radius, parts); +void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, CachedRoundCorners index); +inline void FillRoundRect(QPainter &p, const QRect &rect, style::color bg, CachedRoundCorners index) { + FillRoundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, index); } +[[nodiscard]] const CornersPixmaps &CachedCornerPixmaps(CachedRoundCorners index); [[nodiscard]] CornersPixmaps PrepareCornerPixmaps( int32 radius, style::color bg, - const style::color *sh); + const style::color *sh = nullptr); [[nodiscard]] CornersPixmaps PrepareCornerPixmaps( ImageRoundRadius radius, style::color bg, - const style::color *sh); -void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, const CornersPixmaps &corner, const style::color *shadow = nullptr, RectParts parts = RectPart::Full); -inline void FillRoundRect(QPainter &p, const QRect &rect, style::color bg, const CornersPixmaps &corner, const style::color *shadow = nullptr, RectParts parts = RectPart::Full) { - return FillRoundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, corner, shadow, parts); + const style::color *sh = nullptr); +void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color bg, const CornersPixmaps &corners); +inline void FillRoundRect(QPainter &p, const QRect &rect, style::color bg, const CornersPixmaps &corners) { + return FillRoundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, corners); } void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, const CornersPixmaps &corners); inline void FillRoundShadow(QPainter &p, const QRect &rect, style::color shadow, const CornersPixmaps &corners) { diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp index eda4984a1..40cf7d84b 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp @@ -307,13 +307,12 @@ void Panel::Button::paintEvent(QPaintEvent *e) { } QImage Panel::Button::prepareRippleMask() const { - const auto drawMask = [&](QPainter &p) { + return RippleAnimation::MaskByDrawer(size(), false, [&](QPainter &p) { p.drawRoundedRect( rect().marginsAdded({ 0, st::callRadius * 2, 0, 0 }), st::callRadius, st::callRadius); - }; - return RippleAnimation::maskByDrawer(size(), false, drawMask); + }); } QPoint Panel::Button::prepareRippleStartPosition() const { diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index 8d0b47b6a..2f87b2c2c 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -657,7 +657,7 @@ msgBotKbSwitchPmIcon: icon {{ "inline_button_switch", msgBotKbIconFg }}; msgBotKbPaymentIcon: icon {{ "inline_button_card", msgBotKbIconFg }}; msgBotKbWebviewIcon: icon {{ "inline_button_web", msgBotKbIconFg }}; msgBotKbButton: BotKeyboardButton { - margin: 5px; + margin: 2px; padding: 10px; height: 36px; textTop: 8px; diff --git a/Telegram/SourceFiles/ui/chat/chat_style.cpp b/Telegram/SourceFiles/ui/chat/chat_style.cpp index bacd52c83..a0e0fd3f7 100644 --- a/Telegram/SourceFiles/ui/chat/chat_style.cpp +++ b/Telegram/SourceFiles/ui/chat/chat_style.cpp @@ -28,49 +28,6 @@ void EnsureCorners( } } -void RectWithCorners( - QPainter &p, - QRect rect, - const style::color &bg, - const CornersPixmaps &corners, - RectParts roundCorners) { - const auto parts = RectPart::Top - | RectPart::NoTopBottom - | RectPart::Bottom - | roundCorners; - FillRoundRect(p, rect, bg, corners, nullptr, parts); - if ((roundCorners & RectPart::AllCorners) != RectPart::AllCorners) { - const auto size = corners.p[0].width() / style::DevicePixelRatio(); - if (!(roundCorners & RectPart::TopLeft)) { - p.fillRect(rect.x(), rect.y(), size, size, bg); - } - if (!(roundCorners & RectPart::TopRight)) { - p.fillRect( - rect.x() + rect.width() - size, - rect.y(), - size, - size, - bg); - } - if (!(roundCorners & RectPart::BottomLeft)) { - p.fillRect( - rect.x(), - rect.y() + rect.height() - size, - size, - size, - bg); - } - if (!(roundCorners & RectPart::BottomRight)) { - p.fillRect( - rect.x() + rect.width() - size, - rect.y() + rect.height() - size, - size, - size, - bg); - } - } -} - } // namespace not_null ChatPaintContext::messageStyle() const { @@ -485,13 +442,15 @@ void ChatStyle::assignPalette(not_null palette) { } for (auto &style : _imageStyles) { style.msgDateImgBgCorners = {}; - style.msgServiceBgCorners = {}; + style.msgServiceBgCornersSmall = {}; + style.msgServiceBgCornersLarge = {}; style.msgShadowCornersSmall = {}; style.msgShadowCornersLarge = {}; } _serviceBgCornersNormal = {}; _serviceBgCornersInverted = {}; - _msgBotKbOverBgAddCorners = {}; + _msgBotKbOverBgAddCornersSmall = {}; + _msgBotKbOverBgAddCornersLarge = {}; for (auto &corners : _msgSelectOverlayCorners) { corners = {}; } @@ -555,8 +514,12 @@ const MessageImageStyle &ChatStyle::imageStyle(bool selected) const { (st::msgDateImgPadding.y() * 2 + st::normalFont->height) / 2, result.msgDateImgBg); EnsureCorners( - result.msgServiceBgCorners, - st::dateRadius, + result.msgServiceBgCornersSmall, + st::bubbleRadiusSmall, + result.msgServiceBg); + EnsureCorners( + result.msgServiceBgCornersLarge, + st::bubbleRadiusLarge, result.msgServiceBg); EnsureCorners( result.msgShadowCornersSmall, @@ -569,12 +532,20 @@ const MessageImageStyle &ChatStyle::imageStyle(bool selected) const { return result; } -const CornersPixmaps &ChatStyle::msgBotKbOverBgAddCorners() const { +const CornersPixmaps &ChatStyle::msgBotKbOverBgAddCornersSmall() const { EnsureCorners( - _msgBotKbOverBgAddCorners, - st::dateRadius, + _msgBotKbOverBgAddCornersSmall, + st::bubbleRadiusSmall, msgBotKbOverBgAdd()); - return _msgBotKbOverBgAddCorners; + return _msgBotKbOverBgAddCornersSmall; +} + +const CornersPixmaps &ChatStyle::msgBotKbOverBgAddCornersLarge() const { + EnsureCorners( + _msgBotKbOverBgAddCornersLarge, + st::bubbleRadiusLarge, + msgBotKbOverBgAdd()); + return _msgBotKbOverBgAddCornersLarge; } const CornersPixmaps &ChatStyle::msgSelectOverlayCorners( diff --git a/Telegram/SourceFiles/ui/chat/chat_style.h b/Telegram/SourceFiles/ui/chat/chat_style.h index 443459bde..84935b756 100644 --- a/Telegram/SourceFiles/ui/chat/chat_style.h +++ b/Telegram/SourceFiles/ui/chat/chat_style.h @@ -80,7 +80,8 @@ struct MessageStyle { struct MessageImageStyle { CornersPixmaps msgDateImgBgCorners; - CornersPixmaps msgServiceBgCorners; + CornersPixmaps msgServiceBgCornersSmall; + CornersPixmaps msgServiceBgCornersLarge; CornersPixmaps msgShadowCornersSmall; CornersPixmaps msgShadowCornersLarge; style::color msgServiceBg; @@ -191,7 +192,8 @@ public: bool selected) const; [[nodiscard]] const MessageImageStyle &imageStyle(bool selected) const; - [[nodiscard]] const CornersPixmaps &msgBotKbOverBgAddCorners() const; + [[nodiscard]] const CornersPixmaps &msgBotKbOverBgAddCornersSmall() const; + [[nodiscard]] const CornersPixmaps &msgBotKbOverBgAddCornersLarge() const; [[nodiscard]] const CornersPixmaps &msgSelectOverlayCorners( CachedCornerRadius radius) const; @@ -318,7 +320,8 @@ private: mutable std::array _messageStyles; mutable std::array _imageStyles; - mutable CornersPixmaps _msgBotKbOverBgAddCorners; + mutable CornersPixmaps _msgBotKbOverBgAddCornersSmall; + mutable CornersPixmaps _msgBotKbOverBgAddCornersLarge; mutable CornersPixmaps _msgSelectOverlayCorners[ int(CachedCornerRadius::kCount)]; diff --git a/Telegram/SourceFiles/ui/chat/message_bubble.cpp b/Telegram/SourceFiles/ui/chat/message_bubble.cpp index c02489086..dee9257bd 100644 --- a/Telegram/SourceFiles/ui/chat/message_bubble.cpp +++ b/Telegram/SourceFiles/ui/chat/message_bubble.cpp @@ -28,6 +28,8 @@ void PaintBubbleGeneric( FillSh &&fillSh, FillCorner &&fillCorner, PaintTail &&paintTail) { + using namespace Images; + const auto topLeft = args.rounding.topLeft; const auto topRight = args.rounding.topRight; const auto bottomWithTailLeft = args.rounding.bottomLeft; @@ -64,7 +66,7 @@ void PaintBubbleGeneric( const auto left = cornerSize(topLeft); const auto right = cornerSize(topRight); if (left) { - fillCorner(rect.left(), rect.top(), 0, topLeft); + fillCorner(rect.left(), rect.top(), kTopLeft, topLeft); if (const auto add = top - left) { fillBg({ rect.left(), rect.top() + left, left, add }); } @@ -76,7 +78,7 @@ void PaintBubbleGeneric( fillCorner( rect.left() + rect.width() - right, rect.top(), - 1, + kTopRight, topRight); if (const auto add = top - right) { fillBg({ @@ -88,8 +90,8 @@ void PaintBubbleGeneric( } } } - if (const auto h = rect.height() - top - bottom; h > 0) { - fillBg({ rect.left(), rect.top() + top, rect.width(), h }); + if (const auto fill = rect.height() - top - bottom; fill > 0) { + fillBg({ rect.left(), rect.top() + top, rect.width(), fill }); } if (bottom) { const auto left = cornerSize(bottomLeft); @@ -98,7 +100,7 @@ void PaintBubbleGeneric( fillCorner( rect.left(), rect.top() + rect.height() - left, - 2, + kBottomLeft, bottomLeft); if (const auto add = bottom - left) { fillBg({ @@ -121,7 +123,7 @@ void PaintBubbleGeneric( fillCorner( rect.left() + rect.width() - right, rect.top() + rect.height() - right, - 3, + kBottomRight, bottomRight); if (const auto add = bottom - right) { fillBg({ diff --git a/Telegram/SourceFiles/ui/controls/delete_message_context_action.cpp b/Telegram/SourceFiles/ui/controls/delete_message_context_action.cpp index bbd3e8bc2..e53fcf2d9 100644 --- a/Telegram/SourceFiles/ui/controls/delete_message_context_action.cpp +++ b/Telegram/SourceFiles/ui/controls/delete_message_context_action.cpp @@ -213,7 +213,7 @@ QPoint ActionWithTimer::prepareRippleStartPosition() const { } QImage ActionWithTimer::prepareRippleMask() const { - return Ui::RippleAnimation::rectMask(size()); + return Ui::RippleAnimation::RectMask(size()); } int ActionWithTimer::contentHeight() const { diff --git a/Telegram/SourceFiles/ui/controls/emoji_button.cpp b/Telegram/SourceFiles/ui/controls/emoji_button.cpp index 9f224198e..d500ca7d4 100644 --- a/Telegram/SourceFiles/ui/controls/emoji_button.cpp +++ b/Telegram/SourceFiles/ui/controls/emoji_button.cpp @@ -122,7 +122,7 @@ QPoint EmojiButton::prepareRippleStartPosition() const { } QImage EmojiButton::prepareRippleMask() const { - return RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize)); + return RippleAnimation::EllipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize)); } } // namespace Ui diff --git a/Telegram/SourceFiles/ui/controls/send_button.cpp b/Telegram/SourceFiles/ui/controls/send_button.cpp index 223df4458..fe9f6b115 100644 --- a/Telegram/SourceFiles/ui/controls/send_button.cpp +++ b/Telegram/SourceFiles/ui/controls/send_button.cpp @@ -202,7 +202,7 @@ QImage SendButton::prepareRippleMask() const { auto size = (_type == Type::Record) ? st::historyAttachEmoji.rippleAreaSize : st::historyReplyCancel.rippleAreaSize; - return RippleAnimation::ellipseMask(QSize(size, size)); + return RippleAnimation::EllipseMask(QSize(size, size)); } QPoint SendButton::prepareRippleStartPosition() const { diff --git a/Telegram/SourceFiles/ui/controls/who_reacted_context_action.cpp b/Telegram/SourceFiles/ui/controls/who_reacted_context_action.cpp index ffd645079..03faf1ac7 100644 --- a/Telegram/SourceFiles/ui/controls/who_reacted_context_action.cpp +++ b/Telegram/SourceFiles/ui/controls/who_reacted_context_action.cpp @@ -444,7 +444,7 @@ QPoint Action::prepareRippleStartPosition() const { } QImage Action::prepareRippleMask() const { - return Ui::RippleAnimation::rectMask(size()); + return Ui::RippleAnimation::RectMask(size()); } int Action::contentHeight() const { diff --git a/Telegram/SourceFiles/ui/filter_icon_panel.cpp b/Telegram/SourceFiles/ui/filter_icon_panel.cpp index caa4c79b9..f0de41e3c 100644 --- a/Telegram/SourceFiles/ui/filter_icon_panel.cpp +++ b/Telegram/SourceFiles/ui/filter_icon_panel.cpp @@ -70,7 +70,8 @@ constexpr auto kIcons = std::array{ FilterIconPanel::FilterIconPanel(QWidget *parent) : RpWidget(parent) -, _inner(Ui::CreateChild(this)) { +, _inner(Ui::CreateChild(this)) +, _innerBg(ImageRoundRadius::Small, st::dialogsBg) { setup(); } @@ -117,11 +118,7 @@ void FilterIconPanel::setupInner() { _inner->paintRequest( ) | rpl::start_with_next([=](QRect clip) { auto p = Painter(_inner); - Ui::FillRoundRect( - p, - _inner->rect(), - st::dialogsBg, - ImageRoundRadius::Small); + _innerBg.paint(p, _inner->rect()); p.setFont(st::emojiPanHeaderFont); p.setPen(st::emojiPanHeaderFg); p.drawTextLeft( diff --git a/Telegram/SourceFiles/ui/filter_icon_panel.h b/Telegram/SourceFiles/ui/filter_icon_panel.h index 04a02f936..99caea7a6 100644 --- a/Telegram/SourceFiles/ui/filter_icon_panel.h +++ b/Telegram/SourceFiles/ui/filter_icon_panel.h @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/timer.h" #include "ui/rp_widget.h" #include "ui/effects/animations.h" +#include "ui/round_rect.h" namespace Ui { @@ -69,6 +70,7 @@ private: const not_null _inner; rpl::event_stream _chosen; + Ui::RoundRect _innerBg; int _selected = -1; int _pressed = -1; diff --git a/Telegram/SourceFiles/ui/special_buttons.cpp b/Telegram/SourceFiles/ui/special_buttons.cpp index a9ae3b59e..4489dc6c9 100644 --- a/Telegram/SourceFiles/ui/special_buttons.cpp +++ b/Telegram/SourceFiles/ui/special_buttons.cpp @@ -127,7 +127,7 @@ HistoryDownButton::HistoryDownButton(QWidget *parent, const style::TwoIconButton } QImage HistoryDownButton::prepareRippleMask() const { - return Ui::RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize)); + return Ui::RippleAnimation::EllipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize)); } QPoint HistoryDownButton::prepareRippleStartPosition() const { @@ -502,7 +502,7 @@ QPoint UserpicButton::countPhotoPosition() const { } QImage UserpicButton::prepareRippleMask() const { - return Ui::RippleAnimation::ellipseMask(QSize( + return Ui::RippleAnimation::EllipseMask(QSize( _st.photoSize, _st.photoSize)); } @@ -896,7 +896,7 @@ QPoint SilentToggle::prepareRippleStartPosition() const { } QImage SilentToggle::prepareRippleMask() const { - return RippleAnimation::ellipseMask( + return RippleAnimation::EllipseMask( QSize(_st.rippleAreaSize, _st.rippleAreaSize)); } diff --git a/Telegram/SourceFiles/ui/widgets/discrete_sliders.cpp b/Telegram/SourceFiles/ui/widgets/discrete_sliders.cpp index 734807be9..ff30d88c7 100644 --- a/Telegram/SourceFiles/ui/widgets/discrete_sliders.cpp +++ b/Telegram/SourceFiles/ui/widgets/discrete_sliders.cpp @@ -265,19 +265,32 @@ void SettingsSlider::startRipple(int sectionIndex) { }); } -QImage SettingsSlider::prepareRippleMask(int sectionIndex, const Section §ion) { +QImage SettingsSlider::prepareRippleMask( + int sectionIndex, + const Section §ion) { auto size = QSize(section.width, height() - _st.rippleBottomSkip); - if (!_rippleTopRoundRadius || (sectionIndex > 0 && sectionIndex + 1 < getSectionsCount())) { - return RippleAnimation::rectMask(size); + if (!_rippleTopRoundRadius + || (sectionIndex > 0 && sectionIndex + 1 < getSectionsCount())) { + return RippleAnimation::RectMask(size); } - return RippleAnimation::maskByDrawer(size, false, [this, sectionIndex, width = section.width](QPainter &p) { + return RippleAnimation::MaskByDrawer(size, false, [&](QPainter &p) { auto plusRadius = _rippleTopRoundRadius + 1; - p.drawRoundedRect(0, 0, width, height() + plusRadius, _rippleTopRoundRadius, _rippleTopRoundRadius); + p.drawRoundedRect( + 0, + 0, + section.width, + height() + plusRadius, + _rippleTopRoundRadius, + _rippleTopRoundRadius); if (sectionIndex > 0) { p.fillRect(0, 0, plusRadius, plusRadius, p.brush()); } if (sectionIndex + 1 < getSectionsCount()) { - p.fillRect(width - plusRadius, 0, plusRadius, plusRadius, p.brush()); + p.fillRect( + section.width - plusRadius, + 0, + plusRadius, + plusRadius, p.brush()); } }); } diff --git a/Telegram/SourceFiles/window/themes/window_theme_editor_block.cpp b/Telegram/SourceFiles/window/themes/window_theme_editor_block.cpp index d5c58f342..a7dda1ec1 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_editor_block.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_editor_block.cpp @@ -745,7 +745,7 @@ void EditorBlock::addRowRipple(int index) { auto &row = rowAtIndex(index); auto ripple = row.ripple(); if (!ripple) { - auto mask = Ui::RippleAnimation::rectMask(QSize(width(), row.height())); + auto mask = Ui::RippleAnimation::RectMask(QSize(width(), row.height())); ripple = row.setRipple(std::make_unique(st::defaultRippleAnimation, std::move(mask), [this, index = findRowIndex(&row)] { updateRow(_data[index]); })); diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 2c2a7887e..89ae115a8 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 2c2a7887e644dff7130d764c5a7b04aaa0463056 +Subproject commit 89ae115a878feb9e07fe7423fcf123397eba5966