From abdd126dcf2907535c583a4d97802a86fe3f9e82 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 30 Sep 2022 23:03:44 +0400 Subject: [PATCH] Round correctly distinct photos and extended media. --- .../view/media/history_view_document.cpp | 16 ++- .../media/history_view_extended_preview.cpp | 50 +++------ .../media/history_view_extended_preview.h | 15 +-- .../view/media/history_view_location.cpp | 49 +++++---- .../history/view/media/history_view_media.cpp | 104 ++++++++++++++++++ .../history/view/media/history_view_media.h | 23 ++++ .../history/view/media/history_view_photo.cpp | 41 +++---- .../history/view/media/history_view_photo.h | 12 +- .../media/history_view_theme_document.cpp | 2 +- .../view/media/history_view_web_page.cpp | 2 +- .../SourceFiles/ui/cached_round_corners.cpp | 64 +++++++---- .../SourceFiles/ui/cached_round_corners.h | 13 ++- Telegram/SourceFiles/ui/chat/chat_style.cpp | 32 ++---- Telegram/SourceFiles/ui/chat/chat_style.h | 12 +- Telegram/lib_ui | 2 +- 15 files changed, 268 insertions(+), 169 deletions(-) diff --git a/Telegram/SourceFiles/history/view/media/history_view_document.cpp b/Telegram/SourceFiles/history/view/media/history_view_document.cpp index 74e83ef09..fa272149c 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_document.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_document.cpp @@ -424,7 +424,7 @@ void Document::draw(Painter &p, const PaintContext &context) const { const auto corners = (isBubbleTop() ? (RectPart::TopLeft | RectPart::TopRight) : RectParts()) - | ((isBubbleBottom() && !Has()) + | ((isRoundedInBubbleBottom() && !Has()) ? (RectPart::BottomLeft | RectPart::BottomRight) : RectParts()); draw(p, context, width(), LayoutMode::Full, corners); @@ -767,21 +767,19 @@ void Document::fillThumbnailOverlay( Ui::BubbleRounding rounding, const PaintContext &context) const { using Corner = Ui::BubbleCornerRounding; + using Radius = Ui::CachedCornerRadius; auto corners = Ui::CornersPixmaps(); const auto &st = context.st; - const auto set = [&](int index, const Ui::CornersPixmaps &from) { - corners.p[index] = from.p[index]; - }; - const auto lookup = [&](Corner corner) -> const Ui::CornersPixmaps & { + const auto lookup = [&](Corner corner) { switch (corner) { - case Corner::None: return st->msgSelectOverlayCornersSmall(); - case Corner::Small: return st->msgSelectOverlayCornersThumbSmall(); - case Corner::Large: return st->msgSelectOverlayCornersThumbLarge(); + case Corner::None: return Radius::Small; + case Corner::Small: return Radius::ThumbSmall; + case Corner::Large: return Radius::ThumbLarge; } Unexpected("Corner value in Document::fillThumbnailOverlay."); }; for (auto i = 0; i != 4; ++i) { - corners.p[i] = lookup(rounding[i]).p[i]; + corners.p[i] = st->msgSelectOverlayCorners(lookup(rounding[i])).p[i]; } Ui::FillComplexOverlayRect(p, rect, st->msgSelectOverlay(), corners); } diff --git a/Telegram/SourceFiles/history/view/media/history_view_extended_preview.cpp b/Telegram/SourceFiles/history/view/media/history_view_extended_preview.cpp index 90f89fee3..73463ed96 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_extended_preview.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_extended_preview.cpp @@ -90,7 +90,7 @@ void ExtendedPreview::ensureThumbnailRead() const { } _inlineThumbnail = Images::FromInlineBytes(bytes); if (_inlineThumbnail.isNull()) { - _imageCacheInvalid = 1; + _imageCacheInvalid = true; } else { history()->owner().registerHeavyViewPart(_parent); } @@ -202,6 +202,10 @@ void ExtendedPreview::draw(Painter &p, const PaintContext &context) const { auto bubble = _parent->hasBubble(); auto captionw = paintw - st::msgPadding.left() - st::msgPadding.right(); auto rthumb = style::rtlrect(paintx, painty, paintw, painth, width()); + const auto inWebPage = (_parent->media() != this); + const auto rounding = inWebPage + ? std::optional() + : adjustedBubbleRoundingWithCaption(_caption); if (bubble) { if (!_caption.isEmpty()) { painth -= st::mediaCaptionSkip + _caption.countHeight(captionw); @@ -211,21 +215,15 @@ void ExtendedPreview::draw(Painter &p, const PaintContext &context) const { rthumb = style::rtlrect(paintx, painty, paintw, painth, width()); } } else { - // #TODO rounding - Ui::FillRoundShadow(p, 0, 0, paintw, painth, sti->msgShadow, sti->msgShadowCornersSmall); + Assert(rounding.has_value()); + fillImageShadow(p, rthumb, *rounding, context); } - const auto inWebPage = (_parent->media() != this); - const auto roundRadius = inWebPage - ? ImageRoundRadius::Small - : ImageRoundRadius::Large; - const auto roundCorners = inWebPage ? RectPart::AllCorners : ((isBubbleTop() ? (RectPart::TopLeft | RectPart::TopRight) : RectPart::None) - | ((isRoundedInBubbleBottom() && _caption.isEmpty()) ? (RectPart::BottomLeft | RectPart::BottomRight) : RectPart::None)); - validateImageCache(rthumb.size(), roundRadius, roundCorners); + validateImageCache(rthumb.size(), rounding); p.drawImage(rthumb.topLeft(), _imageCache); - fillSpoilerMess(p, rthumb, roundRadius, roundCorners, context); + fillSpoilerMess(p, rthumb, rounding, context); paintButton(p, rthumb, context); if (context.selected()) { - Ui::FillComplexOverlayRect(p, st, rthumb, roundRadius, roundCorners); + fillImageOverlay(p, rthumb, rounding, context); } // date @@ -265,26 +263,16 @@ void ExtendedPreview::draw(Painter &p, const PaintContext &context) const { void ExtendedPreview::validateImageCache( QSize outer, - ImageRoundRadius radius, - RectParts corners) const { - const auto intRadius = static_cast(radius); - const auto intCorners = static_cast(corners); + std::optional rounding) const { const auto ratio = style::DevicePixelRatio(); if (_imageCache.size() == (outer * ratio) - && _imageCacheRoundRadius == intRadius - && _imageCacheRoundCorners == intCorners) { + && _imageCacheRounding == rounding) { return; } - _imageCache = prepareImageCache(outer, radius, corners); - _imageCacheRoundRadius = intRadius; - _imageCacheRoundCorners = intCorners; -} - -QImage ExtendedPreview::prepareImageCache( - QSize outer, - ImageRoundRadius radius, - RectParts corners) const { - return Images::Round(prepareImageCache(outer), radius, corners); + _imageCache = Images::Round( + prepareImageCache(outer), + MediaRoundingMask(rounding)); + _imageCacheRounding = rounding; } QImage ExtendedPreview::prepareImageCache(QSize outer) const { @@ -295,8 +283,7 @@ QImage ExtendedPreview::prepareImageCache(QSize outer) const { void ExtendedPreview::fillSpoilerMess( QPainter &p, QRect rect, - ImageRoundRadius radius, - RectParts corners, + std::optional rounding, const PaintContext &context) const { if (!_animation) { _animation = std::make_unique([=] { @@ -310,8 +297,7 @@ void ExtendedPreview::fillSpoilerMess( Ui::FillSpoilerRect( p, rect, - radius, - corners, + MediaRoundingMask(rounding), spoiler.frame(index), _cornerCache); } diff --git a/Telegram/SourceFiles/history/view/media/history_view_extended_preview.h b/Telegram/SourceFiles/history/view/media/history_view_extended_preview.h index 3607be97b..00e66e959 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_extended_preview.h +++ b/Telegram/SourceFiles/history/view/media/history_view_extended_preview.h @@ -80,12 +80,7 @@ private: bool needInfoDisplay() const; void validateImageCache( QSize outer, - ImageRoundRadius radius, - RectParts corners) const; - [[nodiscard]] QImage prepareImageCache( - QSize outer, - ImageRoundRadius radius, - RectParts corners) const; + std::optional rounding) const; [[nodiscard]] QImage prepareImageCache(QSize outer) const; void paintButton( Painter &p, @@ -95,8 +90,7 @@ private: void fillSpoilerMess( QPainter &p, QRect rect, - ImageRoundRadius radius, - RectParts corners, + std::optional rounding, const PaintContext &context) const; const not_null _invoice; @@ -109,9 +103,8 @@ private: mutable QImage _buttonBackground; mutable QColor _buttonBackgroundOverlay; mutable Ui::Text::String _buttonText; - mutable int _imageCacheRoundRadius : 4 = 0; - mutable int _imageCacheRoundCorners : 12 = 0; - mutable int _imageCacheInvalid : 1 = 0; + mutable std::optional _imageCacheRounding; + mutable bool _imageCacheInvalid = false; }; diff --git a/Telegram/SourceFiles/history/view/media/history_view_location.cpp b/Telegram/SourceFiles/history/view/media/history_view_location.cpp index 848e63e6b..e0300e20f 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_location.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_location.cpp @@ -163,8 +163,11 @@ void Location::draw(Painter &p, const PaintContext &context) const { const auto sti = context.imageStyle(); const auto stm = context.messageStyle(); + const auto hasText = !_title.isEmpty() || !_description.isEmpty(); + const auto rounding = adjustedBubbleRounding( + hasText ? RectPart::FullTop : RectPart()); if (bubble) { - if (!_title.isEmpty() || !_description.isEmpty()) { + if (hasText) { if (isBubbleTop()) { painty += st::msgPadding.top(); } @@ -185,26 +188,34 @@ void Location::draw(Painter &p, const PaintContext &context) const { painty += st::mediaInBubbleSkip; } painth -= painty; - } else { - // #TODO rounding - Ui::FillRoundShadow(p, 0, 0, paintw, painth, sti->msgShadow, sti->msgShadowCornersSmall); + } + auto rthumb = QRect(paintx, painty, paintw, painth); + if (!bubble) { + fillImageShadow(p, rthumb, rounding, context); } - auto roundRadius = ImageRoundRadius::Large; - auto roundCorners = ((isBubbleTop() && _title.isEmpty() && _description.isEmpty()) ? (RectPart::TopLeft | RectPart::TopRight) : RectPart::None) - | (isRoundedInBubbleBottom() ? (RectPart::BottomLeft | RectPart::BottomRight) : RectPart::None); - auto rthumb = QRect(paintx, painty, paintw, painth); ensureMediaCreated(); - if (const auto thumbnail = _media->image()) { - p.drawPixmap(rthumb.topLeft(), thumbnail->pixSingle( - rthumb.size(), - { - .options = Images::RoundOptions(roundRadius, roundCorners), - .outer = rthumb.size(), - })); - } else { - Ui::FillComplexLocationRect(p, st, rthumb, roundRadius, roundCorners); - } + //if (const auto thumbnail = _media->image()) { + // p.drawPixmap(rthumb.topLeft(), thumbnail->pixSingle( + // rthumb.size(), + // { + // .options = Images::RoundOptions(roundRadius, roundCorners), + // .outer = rthumb.size(), + // })); + //} else if (!bubble) { + Ui::PaintBubble( + p, + Ui::SimpleBubble{ + .st = context.st, + .geometry = rthumb, + .pattern = context.bubblesPattern, + .patternViewport = context.viewport, + .outerWidth = width(), + .selected = context.selected(), + .outbg = context.outbg, + .rounding = rounding, + }); + //} const auto paintMarker = [&](const style::icon &icon) { icon.paint( p, @@ -215,7 +226,7 @@ void Location::draw(Painter &p, const PaintContext &context) const { paintMarker(st->historyMapPoint()); paintMarker(st->historyMapPointInner()); if (context.selected()) { - Ui::FillComplexOverlayRect(p, st, rthumb, roundRadius, roundCorners); + fillImageOverlay(p, rthumb, rounding, context); } if (_parent->media() == this) { diff --git a/Telegram/SourceFiles/history/view/media/history_view_media.cpp b/Telegram/SourceFiles/history/view/media/history_view_media.cpp index b7c5960ea..166461afe 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media.cpp @@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/item_text_options.h" #include "ui/chat/chat_style.h" #include "ui/chat/message_bubble.h" +#include "ui/image/image_prepare.h" #include "core/ui_integration.h" #include "styles/style_chat.h" @@ -187,6 +188,60 @@ QSize Media::countCurrentSize(int newWidth) { return QSize(qMin(newWidth, maxWidth()), minHeight()); } +void Media::fillImageShadow( + QPainter &p, + QRect rect, + Ui::BubbleRounding rounding, + const PaintContext &context) const { + const auto sti = context.imageStyle(); + auto corners = Ui::CornersPixmaps(); + const auto choose = [&](int index) -> QPixmap { + using Corner = Ui::BubbleCornerRounding; + switch (rounding[index]) { + case Corner::Large: return sti->msgShadowCornersLarge.p[index]; + case Corner::Small: return sti->msgShadowCornersSmall.p[index]; + } + return QPixmap(); + }; + corners.p[2] = choose(2); + corners.p[3] = choose(3); + Ui::FillRoundShadow(p, rect, sti->msgShadow, corners); +} + +void Media::fillImageOverlay( + QPainter &p, + QRect rect, + std::optional rounding, + const PaintContext &context) const { + using Radius = Ui::CachedCornerRadius; + const auto &st = context.st; + if (!rounding) { + Ui::FillComplexOverlayRect( + p, + rect, + st->msgSelectOverlay(), + st->msgSelectOverlayCorners(Radius::Small)); + return; + } + using Corner = Ui::BubbleCornerRounding; + auto corners = Ui::CornersPixmaps(); + const auto lookup = [&](Corner corner) { + switch (corner) { + case Corner::None: return Radius::kCount; + case Corner::Small: return Radius::BubbleSmall; + case Corner::Large: return Radius::BubbleLarge; + } + Unexpected("Corner value in Document::fillThumbnailOverlay."); + }; + for (auto i = 0; i != 4; ++i) { + const auto radius = lookup((*rounding)[i]); + corners.p[i] = (radius == Radius::kCount) + ? QPixmap() + : st->msgSelectOverlayCorners(radius).p[i]; + } + Ui::FillComplexOverlayRect(p, rect, st->msgSelectOverlay(), corners); +} + void Media::repaint() const { history()->owner().requestViewRepaint(_parent); } @@ -257,10 +312,59 @@ TextState Media::getStateGrouped( Unexpected("Grouping method call."); } +Ui::BubbleRounding Media::adjustedBubbleRounding(RectParts square) const { + auto result = bubbleRounding(); + using Corner = Ui::BubbleCornerRounding; + const auto adjust = [&](bool round, Corner already, RectPart corner) { + return (already == Corner::Tail || !round || (square & corner)) + ? Corner::None + : already; + }; + const auto top = isBubbleTop(); + const auto bottom = isRoundedInBubbleBottom(); + result.topLeft = adjust(top, result.topLeft, RectPart::TopLeft); + result.topRight = adjust(top, result.topRight, RectPart::TopRight); + result.bottomLeft = adjust( + bottom, + result.bottomLeft, + RectPart::BottomLeft); + result.bottomRight = adjust( + bottom, + result.bottomRight, + RectPart::BottomRight); + return result; +} + +Ui::BubbleRounding Media::adjustedBubbleRoundingWithCaption( + const Ui::Text::String &caption) const { + return adjustedBubbleRounding( + caption.isEmpty() ? RectParts() : RectPart::FullBottom); +} + bool Media::isRoundedInBubbleBottom() const { return isBubbleBottom() && !_parent->data()->repliesAreComments() && !_parent->data()->externalReply(); } +Images::CornersMaskRef MediaRoundingMask( + std::optional rounding) { + using Radius = Ui::CachedCornerRadius; + if (!rounding) { + return Images::CornersMaskRef(Ui::CachedCornersMasks(Radius::Small)); + } + using Corner = Ui::BubbleCornerRounding; + auto result = Images::CornersMaskRef(); + const auto &small = Ui::CachedCornersMasks(Radius::BubbleSmall); + const auto &large = Ui::CachedCornersMasks(Radius::BubbleLarge); + for (auto i = 0; i != 4; ++i) { + switch ((*rounding)[i]) { + case Corner::Small: result.p[i] = &small[i]; break; + case Corner::Large: result.p[i] = &large[i]; break; + } + } + return result; + +} + } // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/media/history_view_media.h b/Telegram/SourceFiles/history/view/media/history_view_media.h index 114a9f5d2..4f8a894db 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media.h +++ b/Telegram/SourceFiles/history/view/media/history_view_media.h @@ -32,8 +32,13 @@ struct ColorReplacements; namespace Ui { struct BubbleSelectionInterval; struct ChatPaintContext; +struct CornersMaskRef; } // namespace Ui +namespace Images { +struct CornersMaskRef; +} // namespace Images + namespace HistoryView { enum class PointState : char; @@ -246,6 +251,10 @@ public: [[nodiscard]] Ui::BubbleRounding bubbleRounding() const { return _bubbleRounding; } + [[nodiscard]] Ui::BubbleRounding adjustedBubbleRounding( + RectParts square = {}) const; + [[nodiscard]] Ui::BubbleRounding adjustedBubbleRoundingWithCaption( + const Ui::Text::String &caption) const; [[nodiscard]] bool isBubbleTop() const { return (_inBubbleState == MediaInBubbleState::Top) || (_inBubbleState == MediaInBubbleState::None); @@ -321,6 +330,17 @@ protected: [[nodiscard]] bool usesBubblePattern(const PaintContext &context) const; + void fillImageShadow( + QPainter &p, + QRect rect, + Ui::BubbleRounding rounding, + const PaintContext &context) const; + void fillImageOverlay( + QPainter &p, + QRect rect, + std::optional rounding, // nullopt if in WebPage. + const PaintContext &context) const; + void repaint() const; const not_null _parent; @@ -329,4 +349,7 @@ protected: }; +[[nodiscard]] Images::CornersMaskRef MediaRoundingMask( + std::optional rounding); + } // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp index 130f4ed31..b7e0a42bf 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp @@ -258,6 +258,9 @@ void Photo::draw(Painter &p, const PaintContext &context) const { if (_serviceWidth > 0) { paintUserpicFrame(p, context, rthumb.topLeft()); } else { + const auto rounding = inWebPage + ? std::optional() + : adjustedBubbleRoundingWithCaption(_caption); if (bubble) { if (!_caption.isEmpty()) { painth -= st::mediaCaptionSkip + _caption.countHeight(captionw); @@ -267,19 +270,13 @@ void Photo::draw(Painter &p, const PaintContext &context) const { rthumb = style::rtlrect(paintx, painty, paintw, painth, width()); } } else { - // #TODO rounding - Ui::FillRoundShadow(p, 0, 0, paintw, painth, sti->msgShadow, sti->msgShadowCornersSmall); + Assert(rounding.has_value()); + fillImageShadow(p, rthumb, *rounding, context); } - const auto inWebPage = (_parent->media() != this); - const auto roundRadius = inWebPage - ? ImageRoundRadius::Small - : ImageRoundRadius::Large; - const auto roundCorners = inWebPage ? RectPart::AllCorners : ((isBubbleTop() ? (RectPart::TopLeft | RectPart::TopRight) : RectPart::None) - | ((isRoundedInBubbleBottom() && _caption.isEmpty()) ? (RectPart::BottomLeft | RectPart::BottomRight) : RectPart::None)); - validateImageCache(rthumb.size(), roundRadius, roundCorners); + validateImageCache(rthumb.size(), rounding); p.drawImage(rthumb.topLeft(), _imageCache); if (context.selected()) { - Ui::FillComplexOverlayRect(p, st, rthumb, roundRadius, roundCorners); + fillImageOverlay(p, rthumb, rounding, context); } } if (radial || (!loaded && !_data->loading())) { @@ -355,32 +352,22 @@ void Photo::draw(Painter &p, const PaintContext &context) const { void Photo::validateImageCache( QSize outer, - ImageRoundRadius radius, - RectParts corners) const { - const auto intRadius = static_cast(radius); - const auto intCorners = static_cast(corners); + std::optional rounding) const { const auto large = _dataMedia->image(PhotoSize::Large); const auto ratio = style::DevicePixelRatio(); - const auto shouldBeBlurred = (large != nullptr) ? 0 : 1; + const auto shouldBeBlurred = !large; if (_imageCache.size() == (outer * ratio) - && _imageCacheRoundRadius == intRadius - && _imageCacheRoundCorners == intCorners + && _imageCacheRounding == rounding && _imageCacheBlurred == shouldBeBlurred) { return; } - _imageCache = prepareImageCache(outer, radius, corners); - _imageCacheRoundRadius = intRadius; - _imageCacheRoundCorners = intCorners; + _imageCache = Images::Round( + prepareImageCache(outer), + MediaRoundingMask(rounding)); + _imageCacheRounding = rounding; _imageCacheBlurred = shouldBeBlurred; } -QImage Photo::prepareImageCache( - QSize outer, - ImageRoundRadius radius, - RectParts corners) const { - return Images::Round(prepareImageCache(outer), radius, corners); -} - QImage Photo::prepareImageCache(QSize outer) const { using Size = PhotoSize; const auto large = _dataMedia->image(Size::Large); diff --git a/Telegram/SourceFiles/history/view/media/history_view_photo.h b/Telegram/SourceFiles/history/view/media/history_view_photo.h index 4a350659a..c3e878235 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_photo.h +++ b/Telegram/SourceFiles/history/view/media/history_view_photo.h @@ -128,12 +128,7 @@ private: not_null cache) const; void validateImageCache( QSize outer, - ImageRoundRadius radius, - RectParts corners) const; - [[nodiscard]] QImage prepareImageCache( - QSize outer, - ImageRoundRadius radius, - RectParts corners) const; + std::optional rounding) const; [[nodiscard]] QImage prepareImageCache(QSize outer) const; bool videoAutoplayEnabled() const; @@ -155,9 +150,8 @@ private: mutable std::unique_ptr _streamed; mutable QImage _imageCache; int _serviceWidth = 0; - mutable int _imageCacheRoundRadius : 4 = 0; - mutable int _imageCacheRoundCorners : 12 = 0; - mutable int _imageCacheBlurred : 1 = 0; + mutable std::optional _imageCacheRounding; + mutable bool _imageCacheBlurred = false; }; diff --git a/Telegram/SourceFiles/history/view/media/history_view_theme_document.cpp b/Telegram/SourceFiles/history/view/media/history_view_theme_document.cpp index 45631f819..6eaeac1e2 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_theme_document.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_theme_document.cpp @@ -185,7 +185,7 @@ void ThemeDocument::draw(Painter &p, const PaintContext &context) const { p, rthumb, st->msgSelectOverlay(), - st->msgSelectOverlayCornersSmall()); + st->msgSelectOverlayCorners(Ui::CachedCornerRadius::Small)); } if (_data) { diff --git a/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp b/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp index 357b2580a..08bd8aec4 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp @@ -536,7 +536,7 @@ void WebPage::draw(Painter &p, const PaintContext &context) const { p, style::rtlrect(padding.left() + paintw - pw, tshift, pw, _pixh, width()), st->msgSelectOverlay(), - st->msgSelectOverlayCornersSmall()); + st->msgSelectOverlayCorners(Ui::CachedCornerRadius::Small)); } paintw -= pw + st::webPagePhotoDelta; } diff --git a/Telegram/SourceFiles/ui/cached_round_corners.cpp b/Telegram/SourceFiles/ui/cached_round_corners.cpp index 8e2c4ea5f..8eda35514 100644 --- a/Telegram/SourceFiles/ui/cached_round_corners.cpp +++ b/Telegram/SourceFiles/ui/cached_round_corners.cpp @@ -161,24 +161,35 @@ void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color FillRoundRect(p, x, y, w, h, bg, Corners[index], shadow, parts); } -void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, CachedRoundCorners index, RectParts parts) { - FillRoundShadow(p, x, y, w, h, shadow, Corners[index], parts); +void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, CachedRoundCorners index) { + FillRoundShadow(p, x, y, w, h, shadow, Corners[index]); } -void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, const CornersPixmaps &corner, RectParts parts) { - auto cornerWidth = corner.p[0].width() / style::DevicePixelRatio(); - auto cornerHeight = corner.p[0].height() / style::DevicePixelRatio(); - if (parts & RectPart::Bottom) { - p.fillRect(x + cornerWidth, y + h, w - 2 * cornerWidth, st::msgShadow, shadow); - } - if (parts & RectPart::BottomLeft) { - p.fillRect(x, y + h - cornerHeight, cornerWidth, st::msgShadow, shadow); - p.drawPixmap(x, y + h - cornerHeight + st::msgShadow, corner.p[2]); - } - if (parts & RectPart::BottomRight) { - p.fillRect(x + w - cornerWidth, y + h - cornerHeight, cornerWidth, st::msgShadow, shadow); - p.drawPixmap(x + w - cornerWidth, y + h - cornerHeight + st::msgShadow, corner.p[3]); +void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, const CornersPixmaps &corners) { + constexpr auto kLeft = 2; + constexpr auto kRight = 3; + + const auto ratio = style::DevicePixelRatio(); + const auto size = [&](int index) { + const auto &pix = corners.p[index]; + return pix.isNull() ? 0 : (pix.width() / ratio); + }; + const auto fillCorner = [&](int left, int bottom, int index) { + const auto &pix = corners.p[index]; + if (pix.isNull()) { + return; + } + const auto size = pix.width() / ratio; + p.drawPixmap(left, bottom - size, pix); + }; + const auto left = size(kLeft); + const auto right = size(kRight); + const auto from = x + left; + fillCorner(x, y + h + st::msgShadow, kLeft); + if (const auto width = w - left - right; width > 0) { + p.fillRect(from, y + h, width, st::msgShadow, shadow); } + fillCorner(x + w - right, y + h + st::msgShadow, kRight); } CornersPixmaps PrepareCornerPixmaps(int32 radius, style::color bg, const style::color *sh) { @@ -219,21 +230,26 @@ void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color FillRoundRect(p, x, y, w, h, bg, i->second, nullptr, parts); } +[[nodiscard]] int CachedCornerRadiusValue(CachedCornerRadius tag) { + using Radius = CachedCornerRadius; + switch (tag) { + case Radius::Small: return st::roundRadiusSmall; + case Radius::ThumbSmall: return st::msgFileThumbRadiusSmall; + case Radius::ThumbLarge: return st::msgFileThumbRadiusLarge; + case Radius::BubbleSmall: return st::bubbleRadiusSmall; + case Radius::BubbleLarge: return st::bubbleRadiusLarge; + } + Unexpected("Radius tag in CachedCornerRadiusValue."); +} + [[nodiscard]] const std::array &CachedCornersMasks( CachedCornerRadius radius) { const auto index = static_cast(radius); Assert(index >= 0 && index < kCachedCornerRadiusCount); if (CachedMasks[index][0].isNull()) { - using Radius = CachedCornerRadius; - const auto set = [](Radius key, int radius) { - CachedMasks[static_cast(key)] = Images::CornersMask(radius); - }; - set(Radius::Small, st::roundRadiusSmall); - set(Radius::ThumbSmall, st::msgFileThumbRadiusSmall); - set(Radius::ThumbLarge, st::msgFileThumbRadiusLarge); - set(Radius::BubbleSmall, st::bubbleRadiusSmall); - set(Radius::BubbleLarge, st::bubbleRadiusLarge); + CachedMasks[index] = Images::CornersMask( + CachedCornerRadiusValue(CachedCornerRadius(index))); } return CachedMasks[index]; } diff --git a/Telegram/SourceFiles/ui/cached_round_corners.h b/Telegram/SourceFiles/ui/cached_round_corners.h index e2424f0f5..86e252eed 100644 --- a/Telegram/SourceFiles/ui/cached_round_corners.h +++ b/Telegram/SourceFiles/ui/cached_round_corners.h @@ -40,9 +40,9 @@ void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color 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 FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, CachedRoundCorners index, RectParts parts = RectPart::Full); -inline void FillRoundShadow(QPainter &p, const QRect &rect, style::color shadow, CachedRoundCorners index, RectParts parts = RectPart::Full) { - FillRoundShadow(p, rect.x(), rect.y(), rect.width(), rect.height(), shadow, index, parts); +void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, CachedRoundCorners index); +inline void FillRoundShadow(QPainter &p, const QRect &rect, style::color shadow, CachedRoundCorners index) { + FillRoundShadow(p, rect.x(), rect.y(), rect.width(), rect.height(), shadow, index); } 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) { @@ -61,9 +61,9 @@ void FillRoundRect(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color 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); } -void FillRoundShadow(QPainter &p, int32 x, int32 y, int32 w, int32 h, style::color shadow, const CornersPixmaps &corner, RectParts parts = RectPart::Full); -inline void FillRoundShadow(QPainter &p, const QRect &rect, style::color shadow, const CornersPixmaps &corner, RectParts parts = RectPart::Full) { - FillRoundShadow(p, rect.x(), rect.y(), rect.width(), rect.height(), shadow, corner, parts); +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) { + FillRoundShadow(p, rect.x(), rect.y(), rect.width(), rect.height(), shadow, corners); } enum class CachedCornerRadius { @@ -75,6 +75,7 @@ enum class CachedCornerRadius { kCount, }; +[[nodiscard]] int CachedCornerRadiusValue(CachedCornerRadius tag); [[nodiscard]] const std::array &CachedCornersMasks( CachedCornerRadius radius); diff --git a/Telegram/SourceFiles/ui/chat/chat_style.cpp b/Telegram/SourceFiles/ui/chat/chat_style.cpp index c900497e3..4e9aaa826 100644 --- a/Telegram/SourceFiles/ui/chat/chat_style.cpp +++ b/Telegram/SourceFiles/ui/chat/chat_style.cpp @@ -492,7 +492,9 @@ void ChatStyle::assignPalette(not_null palette) { _serviceBgCornersNormal = {}; _serviceBgCornersInverted = {}; _msgBotKbOverBgAddCorners = {}; - _msgSelectOverlayCornersSmall = {}; + for (auto &corners : _msgSelectOverlayCorners) { + corners = {}; + } for (auto &stm : _messageStyles) { const auto same = (stm.textPalette.linkFg->c == stm.historyTextFg->c); @@ -550,7 +552,7 @@ const MessageImageStyle &ChatStyle::imageStyle(bool selected) const { auto &result = imageStyleRaw(selected); EnsureCorners( result.msgDateImgBgCorners, - st::dateRadius, + (st::msgDateImgPadding.y() * 2 + st::normalFont->height) / 2, result.msgDateImgBg); EnsureCorners( result.msgServiceBgCorners, @@ -575,28 +577,16 @@ const CornersPixmaps &ChatStyle::msgBotKbOverBgAddCorners() const { return _msgBotKbOverBgAddCorners; } -const CornersPixmaps &ChatStyle::msgSelectOverlayCornersSmall() const { - EnsureCorners( - _msgSelectOverlayCornersSmall, - st::roundRadiusSmall, - msgSelectOverlay()); - return _msgSelectOverlayCornersSmall; -} +const CornersPixmaps &ChatStyle::msgSelectOverlayCorners( + CachedCornerRadius radius) const { + const auto index = static_cast(radius); + Assert(index >= 0 && index < int(CachedCornerRadius::kCount)); -const CornersPixmaps &ChatStyle::msgSelectOverlayCornersThumbSmall() const { EnsureCorners( - _msgSelectOverlayCornersThumbSmall, - st::msgFileThumbRadiusSmall, + _msgSelectOverlayCorners[index], + CachedCornerRadiusValue(radius), msgSelectOverlay()); - return _msgSelectOverlayCornersThumbSmall; -} - -const CornersPixmaps &ChatStyle::msgSelectOverlayCornersThumbLarge() const { - EnsureCorners( - _msgSelectOverlayCornersThumbLarge, - st::msgFileThumbRadiusLarge, - msgSelectOverlay()); - return _msgSelectOverlayCornersThumbLarge; + return _msgSelectOverlayCorners[index]; } MessageStyle &ChatStyle::messageStyleRaw(bool outbg, bool selected) const { diff --git a/Telegram/SourceFiles/ui/chat/chat_style.h b/Telegram/SourceFiles/ui/chat/chat_style.h index a9dbbcd26..fc0ace58f 100644 --- a/Telegram/SourceFiles/ui/chat/chat_style.h +++ b/Telegram/SourceFiles/ui/chat/chat_style.h @@ -192,11 +192,8 @@ public: [[nodiscard]] const MessageImageStyle &imageStyle(bool selected) const; [[nodiscard]] const CornersPixmaps &msgBotKbOverBgAddCorners() const; - [[nodiscard]] const CornersPixmaps &msgSelectOverlayCornersSmall() const; - [[nodiscard]] auto msgSelectOverlayCornersThumbSmall() const - -> const CornersPixmaps &; - [[nodiscard]] auto msgSelectOverlayCornersThumbLarge() const - -> const CornersPixmaps &; + [[nodiscard]] const CornersPixmaps &msgSelectOverlayCorners( + CachedCornerRadius radius) const; [[nodiscard]] const style::TextPalette &historyPsaForwardPalette() const { return _historyPsaForwardPalette; @@ -322,9 +319,8 @@ private: mutable std::array _imageStyles; mutable CornersPixmaps _msgBotKbOverBgAddCorners; - mutable CornersPixmaps _msgSelectOverlayCornersSmall; - mutable CornersPixmaps _msgSelectOverlayCornersThumbSmall; - mutable CornersPixmaps _msgSelectOverlayCornersThumbLarge; + mutable CornersPixmaps _msgSelectOverlayCorners[ + int(CachedCornerRadius::kCount)]; style::TextPalette _historyPsaForwardPalette; style::TextPalette _imgReplyTextPalette; diff --git a/Telegram/lib_ui b/Telegram/lib_ui index f49ec866c..cec09b026 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit f49ec866c11fc887d9b16435f67f756d523a9b5b +Subproject commit cec09b0260ba19639bf9abc7df373569aa1509e7