From 8268e9f8720e40dbeaa35ecc157a3e45c3060013 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 3 Oct 2022 11:35:11 +0400 Subject: [PATCH] Support new rounding for GIFs / videos. --- .../SourceFiles/boxes/premium_preview_box.cpp | 15 ++- .../history/view/media/history_view_gif.cpp | 121 ++++++++++-------- .../history/view/media/history_view_gif.h | 19 +-- .../history/view/media/history_view_media.h | 1 - .../history/view/media/history_view_photo.cpp | 15 ++- .../media/player/media_player_float.cpp | 5 +- .../media/player/media_player_float.h | 1 + .../media/streaming/media_streaming_common.h | 11 +- .../streaming/media_streaming_utility.cpp | 18 +-- .../media/view/media_view_pip_raster.cpp | 90 ++++++------- .../SourceFiles/ui/cached_round_corners.cpp | 4 - .../SourceFiles/ui/cached_round_corners.h | 4 - Telegram/SourceFiles/ui/chat/chat_style.cpp | 39 +----- Telegram/SourceFiles/ui/chat/chat_style.h | 12 +- Telegram/SourceFiles/ui/special_buttons.cpp | 5 +- Telegram/SourceFiles/ui/special_buttons.h | 1 + Telegram/lib_ui | 2 +- 17 files changed, 170 insertions(+), 193 deletions(-) diff --git a/Telegram/SourceFiles/boxes/premium_preview_box.cpp b/Telegram/SourceFiles/boxes/premium_preview_box.cpp index 6daaa778b3..f410495b01 100644 --- a/Telegram/SourceFiles/boxes/premium_preview_box.cpp +++ b/Telegram/SourceFiles/boxes/premium_preview_box.cpp @@ -626,19 +626,24 @@ struct VideoPreviewDocument { }; check(); - const auto corners = alignToBottom - ? (RectPart::TopLeft | RectPart::TopRight) - : (RectPart::BottomLeft | RectPart::BottomRight); const auto ready = state->instance.player().ready() && !state->instance.player().videoSize().isEmpty(); const auto size = QSize(width, height) * style::DevicePixelRatio(); + + using namespace Images; + auto rounding = CornersMaskRef( + Images::CornersMask(ImageRoundRadius::Large)); + if (alignToBottom) { + rounding.p[kBottomLeft] = rounding.p[kBottomRight] = nullptr; + } else { + rounding.p[kTopLeft] = rounding.p[kTopRight] = nullptr; + } const auto frame = !ready ? state->blurred : state->instance.frame({ .resize = size, .outer = size, - .radius = ImageRoundRadius::Large, - .corners = corners, + .rounding = rounding, }); paintFrame(QColor(0, 0, 0, 128), 12.); p.drawImage(QRect(left, top, width, height), frame); diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp index da77d86979..c01fcfdb01 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.cpp @@ -274,6 +274,32 @@ QSize Gif::videoSize() const { } } +void Gif::validateRoundingMask(QSize size) const { + if (_roundingMask.size() != size) { + const auto ratio = style::DevicePixelRatio(); + _roundingMask = Images::EllipseMask(size / ratio); + } +} + +Images::CornersMaskRef Gif::prepareRoundingRef( + std::optional rounding) const { + using namespace Ui; + using namespace Images; + if (!rounding) { + return CornersMaskRef(CachedCornersMasks(CachedCornerRadius::Small)); + } + auto result = CornersMaskRef(); + for (auto i = 0; i != 4; ++i) { + const auto corner = (*rounding)[i]; + result.p[i] = (corner == BubbleCornerRounding::Large) + ? &CachedCornersMasks(CachedCornerRadius::BubbleLarge)[i] + : (corner == BubbleCornerRounding::Small) + ? &CachedCornersMasks(CachedCornerRadius::BubbleSmall)[i] + : nullptr; + } + return result; +} + bool Gif::downloadInCorner() const { return _data->isVideoFile() && (_data->loading() || !autoplayEnabled()) @@ -349,6 +375,9 @@ void Gif::draw(Painter &p, const PaintContext &context) const { const auto radial = isRadialAnimation() || (streamedForWaiting && streamedForWaiting->waitingShown()); + const auto rounding = inWebPage + ? std::optional() + : adjustedBubbleRoundingWithCaption(_caption); if (bubble) { if (!_caption.isEmpty()) { painth -= st::mediaCaptionSkip + _caption.countHeight(captionw); @@ -356,9 +385,6 @@ void Gif::draw(Painter &p, const PaintContext &context) const { painth -= st::msgPadding.bottom(); } } - } else if (!unwrapped) { - // #TODO rounding - Ui::FillRoundShadow(p, 0, 0, paintw, height(), sti->msgShadow, sti->msgShadowCornersSmall); } auto usex = 0, usew = paintw; @@ -381,42 +407,30 @@ void Gif::draw(Painter &p, const PaintContext &context) const { QRect rthumb(style::rtlrect(usex + paintx, painty, usew, painth, width())); - const auto roundRadius = isRound - ? ImageRoundRadius::Ellipse - : unwrapped - ? ImageRoundRadius::None - : inWebPage - ? ImageRoundRadius::Small - : ImageRoundRadius::Large; - const auto roundCorners = isRound - ? RectPart::AllCorners - : unwrapped - ? RectPart::None - : inWebPage - ? RectPart::AllCorners - : ((isBubbleTop() - ? (RectPart::TopLeft | RectPart::TopRight) - : RectPart::None) - | ((isRoundedInBubbleBottom() && _caption.isEmpty()) - ? (RectPart::BottomLeft | RectPart::BottomRight) - : RectPart::None)); + if (!bubble && !unwrapped) { + Assert(rounding.has_value()); + fillImageShadow(p, rthumb, *rounding, context); + } + const auto skipDrawingContent = context.skipDrawingParts == PaintContext::SkipDrawingParts::Content; if (streamed && !skipDrawingContent) { auto paused = context.paused; + auto request = ::Media::Streaming::FrameRequest{ + .outer = QSize(usew, painth) * cIntRetinaFactor(), + .blurredBackground = true, + }; if (isRound) { if (activeRoundStreamed()) { paused = false; } else { displayMute = true; } + validateRoundingMask(request.outer); + request.mask = _roundingMask; + } else { + request.rounding = prepareRoundingRef(rounding); } - auto request = ::Media::Streaming::FrameRequest{ - .outer = QSize(usew, painth) * cIntRetinaFactor(), - .radius = roundRadius, - .corners = roundCorners, - .blurredBackground = true, - }; if (!activeRoundPlaying && activeOwnPlaying->instance.playerLocked()) { if (activeOwnPlaying->frozenFrame.isNull()) { activeOwnPlaying->frozenRequest = request; @@ -465,12 +479,16 @@ void Gif::draw(Painter &p, const PaintContext &context) const { } } else if (!skipDrawingContent) { ensureDataMediaCreated(); - validateThumbCache({ usew, painth }, roundRadius, roundCorners); + validateThumbCache({ usew, painth }, isRound, rounding); p.drawImage(rthumb, _thumbCache); } if (context.selected()) { - Ui::FillComplexOverlayRect(p, st, rthumb, roundRadius, roundCorners); + if (isRound) { + Ui::FillComplexEllipse(p, st, rthumb); + } else { + fillImageOverlay(p, rthumb, rounding, context); + } } if (radial @@ -691,10 +709,8 @@ void Gif::validateVideoThumbnail() const { void Gif::validateThumbCache( QSize outer, - ImageRoundRadius radius, - RectParts corners) const { - const auto intRadius = static_cast(radius); - const auto intCorners = static_cast(corners); + bool isEllipse, + std::optional rounding) const { const auto good = _dataMedia->goodThumbnail(); const auto normal = good ? good : _dataMedia->thumbnail(); if (!normal) { @@ -708,24 +724,18 @@ void Gif::validateThumbCache( && (normal->height() < kUseNonBlurredThreshold)) : !videothumb; const auto ratio = style::DevicePixelRatio(); - const auto shouldBeBlurred = blurred ? 1 : 0; if (_thumbCache.size() == (outer * ratio) - && _thumbCacheRoundRadius == intRadius - && _thumbCacheRoundCorners == intCorners - && _thumbCacheBlurred == shouldBeBlurred) { + && _thumbCacheRounding == rounding + && _thumbCacheBlurred == blurred + && _thumbIsEllipse == isEllipse) { return; } - _thumbCache = prepareThumbCache(outer, radius, corners); - _thumbCacheRoundRadius = intRadius; - _thumbCacheRoundCorners = intCorners; - _thumbCacheBlurred = shouldBeBlurred; -} - -QImage Gif::prepareThumbCache( - QSize outer, - ImageRoundRadius radius, - RectParts corners) const { - return Images::Round(prepareThumbCache(outer), radius, corners); + auto cache = prepareThumbCache(outer); + _thumbCache = isEllipse + ? Images::Circle(std::move(cache)) + : Images::Round(std::move(cache), MediaRoundingMask(rounding)); + _thumbCacheRounding = rounding; + _thumbCacheBlurred = blurred; } QImage Gif::prepareThumbCache(QSize outer) const { @@ -1071,8 +1081,8 @@ void Gif::drawGrouped( auto request = ::Media::Streaming::FrameRequest{ .resize = pixSize * cIntRetinaFactor(), .outer = geometry.size() * cIntRetinaFactor(), - .radius = roundRadius, - .corners = corners, + //.radius = roundRadius, // #TODO rounding + //.corners = corners, }; if (activeOwnPlaying->instance.playerLocked()) { if (activeOwnPlaying->frozenFrame.isNull()) { @@ -1104,10 +1114,11 @@ void Gif::drawGrouped( : highlightOpacity; if (overlayOpacity > 0.) { p.setOpacity(overlayOpacity); - Ui::FillComplexOverlayRect(p, st, geometry, roundRadius, corners); - if (!context.selected()) { - Ui::FillComplexOverlayRect(p, st, geometry, roundRadius, corners); - } + // #TODO rounding + //Ui::FillComplexOverlayRect(p, st, geometry, roundRadius, corners); + //if (!context.selected()) { + // Ui::FillComplexOverlayRect(p, st, geometry, roundRadius, corners); + //} p.setOpacity(1.); } diff --git a/Telegram/SourceFiles/history/view/media/history_view_gif.h b/Telegram/SourceFiles/history/view/media/history_view_gif.h index bdd33e9e68..4f39aab7fa 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_gif.h +++ b/Telegram/SourceFiles/history/view/media/history_view_gif.h @@ -163,12 +163,8 @@ private: void validateThumbCache( QSize outer, - ImageRoundRadius radius, - RectParts corners) const; - [[nodiscard]] QImage prepareThumbCache( - QSize outer, - ImageRoundRadius radius, - RectParts corners) const; + bool isEllipse, + std::optional rounding) const; [[nodiscard]] QImage prepareThumbCache(QSize outer) const; void validateGroupedCache( @@ -180,6 +176,10 @@ private: void updateStatusText() const; [[nodiscard]] QSize sizeForAspectRatio() const; + void validateRoundingMask(QSize size) const; + [[nodiscard]] Images::CornersMaskRef prepareRoundingRef( + std::optional rounding) const; + [[nodiscard]] bool downloadInCorner() const; void drawCornerStatus( Painter &p, @@ -197,9 +197,10 @@ private: mutable std::unique_ptr _videoThumbnailFrame; QString _downloadSize; mutable QImage _thumbCache; - mutable int _thumbCacheRoundRadius : 4 = 0; - mutable int _thumbCacheRoundCorners : 12 = 0; - mutable int _thumbCacheBlurred : 1 = 0; + mutable QImage _roundingMask; + mutable std::optional _thumbCacheRounding; + mutable bool _thumbCacheBlurred = false; + mutable bool _thumbIsEllipse = false; }; diff --git a/Telegram/SourceFiles/history/view/media/history_view_media.h b/Telegram/SourceFiles/history/view/media/history_view_media.h index 4f8a894dba..7bc36e184b 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media.h +++ b/Telegram/SourceFiles/history/view/media/history_view_media.h @@ -32,7 +32,6 @@ struct ColorReplacements; namespace Ui { struct BubbleSelectionInterval; struct ChatPaintContext; -struct CornersMaskRef; } // namespace Ui namespace Images { diff --git a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp index b7e0a42bfc..5effea82ef 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp @@ -44,6 +44,7 @@ using Data::PhotoSize; struct Photo::Streamed { explicit Streamed(std::shared_ptr<::Media::Streaming::Document> shared); ::Media::Streaming::Instance instance; + QImage roundingMask; QImage frozenFrame; }; @@ -410,7 +411,10 @@ void Photo::paintUserpicFrame( auto request = ::Media::Streaming::FrameRequest(); request.outer = size * cIntRetinaFactor(); request.resize = size * cIntRetinaFactor(); - request.radius = ImageRoundRadius::Ellipse; + if (_streamed->roundingMask.size() != request.outer) { + _streamed->roundingMask = Images::EllipseMask(size); + } + request.mask = _streamed->roundingMask; if (_streamed->instance.playerLocked()) { if (_streamed->frozenFrame.isNull()) { _streamed->frozenFrame = _streamed->instance.frame(request); @@ -569,10 +573,11 @@ void Photo::drawGrouped( if (overlayOpacity > 0.) { p.setOpacity(overlayOpacity); const auto roundRadius = ImageRoundRadius::Large; - Ui::FillComplexOverlayRect(p, st, geometry, roundRadius, corners); - if (!context.selected()) { - Ui::FillComplexOverlayRect(p, st, geometry, roundRadius, corners); - } + // #TODO rounding + //Ui::FillComplexOverlayRect(p, st, geometry, roundRadius, corners); + //if (!context.selected()) { + // Ui::FillComplexOverlayRect(p, st, geometry, roundRadius, corners); + //} p.setOpacity(1.); } diff --git a/Telegram/SourceFiles/media/player/media_player_float.cpp b/Telegram/SourceFiles/media/player/media_player_float.cpp index 792861e5e5..2a1ee92e70 100644 --- a/Telegram/SourceFiles/media/player/media_player_float.cpp +++ b/Telegram/SourceFiles/media/player/media_player_float.cpp @@ -244,7 +244,10 @@ bool Float::fillFrame() { if (const auto streamed = getStreamed()) { auto request = Streaming::FrameRequest::NonStrict(); request.outer = request.resize = _frame.size(); - request.radius = ImageRoundRadius::Ellipse; + if (_roundingMask.size() != request.outer) { + _roundingMask = Images::EllipseMask(frameInner().size()); + } + request.mask = _roundingMask; auto frame = streamed->frame(request); if (!frame.isNull()) { _frame.fill(Qt::transparent); diff --git a/Telegram/SourceFiles/media/player/media_player_float.h b/Telegram/SourceFiles/media/player/media_player_float.h index fc7eebf267..236b0bd6c8 100644 --- a/Telegram/SourceFiles/media/player/media_player_float.h +++ b/Telegram/SourceFiles/media/player/media_player_float.h @@ -96,6 +96,7 @@ private: float64 _opacity = 1.; QPixmap _shadow; + QImage _roundingMask; QImage _frame; bool _down = false; QPoint _downPoint; diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_common.h b/Telegram/SourceFiles/media/streaming/media_streaming_common.h index 6baba93c43..d1abf2011e 100644 --- a/Telegram/SourceFiles/media/streaming/media_streaming_common.h +++ b/Telegram/SourceFiles/media/streaming/media_streaming_common.h @@ -8,10 +8,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "data/data_audio_msg_id.h" +#include "ui/image/image_prepare.h" #include "ui/rect_part.h" -enum class ImageRoundRadius; - namespace Media { inline constexpr auto kTimeUnknown = std::numeric_limits::min(); @@ -120,8 +119,8 @@ enum class Error { struct FrameRequest { QSize resize; QSize outer; - ImageRoundRadius radius = ImageRoundRadius(); - RectParts corners = RectPart::AllCorners; + Images::CornersMaskRef rounding; + QImage mask; QColor colored = QColor(0, 0, 0, 0); bool blurredBackground = false; bool requireARGB32 = true; @@ -141,8 +140,8 @@ struct FrameRequest { [[nodiscard]] bool operator==(const FrameRequest &other) const { return (resize == other.resize) && (outer == other.outer) - && (radius == other.radius) - && (corners == other.corners) + && (rounding == other.rounding) + && (mask.constBits() == other.mask.constBits()) && (colored == other.colored) && (keepAlpha == other.keepAlpha) && (requireARGB32 == other.requireARGB32) diff --git a/Telegram/SourceFiles/media/streaming/media_streaming_utility.cpp b/Telegram/SourceFiles/media/streaming/media_streaming_utility.cpp index 42f170498d..cb31ee6b02 100644 --- a/Telegram/SourceFiles/media/streaming/media_streaming_utility.cpp +++ b/Telegram/SourceFiles/media/streaming/media_streaming_utility.cpp @@ -101,8 +101,7 @@ bool GoodForRequest( return true; } else if (rotation != 0) { return false; - } else if ((request.radius != ImageRoundRadius::None) - && ((request.corners & RectPart::AllCorners) != 0)) { + } else if (!request.rounding.empty() || !request.mask.isNull()) { return false; } const auto size = request.blurredBackground @@ -348,14 +347,15 @@ void PaintFrameContent( } void ApplyFrameRounding(QImage &storage, const FrameRequest &request) { - if (!(request.corners & RectPart::AllCorners) - || (request.radius == ImageRoundRadius::None)) { - return; + if (!request.mask.isNull()) { + auto p = QPainter(&storage); + p.setCompositionMode(QPainter::CompositionMode_DestinationIn); + p.drawImage( + QRect(QPoint(), storage.size() / storage.devicePixelRatio()), + request.mask); + } else if (!request.rounding.empty()) { + storage = Images::Round(std::move(storage), request.rounding); } - storage = Images::Round( - std::move(storage), - request.radius, - request.corners); } ExpandDecision DecideFrameResize( diff --git a/Telegram/SourceFiles/media/view/media_view_pip_raster.cpp b/Telegram/SourceFiles/media/view/media_view_pip_raster.cpp index e6f4c2009d..0db759ae84 100644 --- a/Telegram/SourceFiles/media/view/media_view_pip_raster.cpp +++ b/Telegram/SourceFiles/media/view/media_view_pip_raster.cpp @@ -21,45 +21,43 @@ namespace { if (!rotation) { return request; } - const auto unrotatedCorner = [&](RectPart corner) { - if (!(request.corners & corner)) { - return RectPart(0); - } - switch (corner) { - case RectPart::TopLeft: + const auto unrotatedCorner = [&](int index) { + using namespace Images; + switch (index) { + case kTopLeft: return (rotation == 90) - ? RectPart::BottomLeft + ? kBottomLeft : (rotation == 180) - ? RectPart::BottomRight - : RectPart::TopRight; - case RectPart::TopRight: + ? kBottomRight + : kTopRight; + case kTopRight: return (rotation == 90) - ? RectPart::TopLeft + ? kTopLeft : (rotation == 180) - ? RectPart::BottomLeft - : RectPart::BottomRight; - case RectPart::BottomRight: + ? kBottomLeft + : kBottomRight; + case kBottomRight: return (rotation == 90) - ? RectPart::TopRight + ? kTopRight : (rotation == 180) - ? RectPart::TopLeft - : RectPart::BottomLeft; - case RectPart::BottomLeft: + ? kTopLeft + : kBottomLeft; + case kBottomLeft: return (rotation == 90) - ? RectPart::BottomRight + ? kBottomRight : (rotation == 180) - ? RectPart::TopRight - : RectPart::TopLeft; + ? kTopRight + : kTopLeft; } Unexpected("Corner in rotateCorner."); }; auto result = request; result.outer = FlipSizeByRotation(request.outer, rotation); result.resize = FlipSizeByRotation(request.resize, rotation); - result.corners = unrotatedCorner(RectPart::TopLeft) - | unrotatedCorner(RectPart::TopRight) - | unrotatedCorner(RectPart::BottomRight) - | unrotatedCorner(RectPart::BottomLeft); + auto rounding = result.rounding; + for (auto i = 0; i != 4; ++i) { + result.rounding.p[unrotatedCorner(i)] = rounding.p[i]; + } return result; } @@ -137,23 +135,23 @@ void Pip::RendererSW::paintButton( Pip::FrameRequest Pip::RendererSW::frameRequest( ContentGeometry geometry) const { + using namespace Images; auto result = FrameRequest(); result.outer = geometry.inner.size() * style::DevicePixelRatio(); result.resize = result.outer; - result.corners = RectPart(0) - | ((geometry.attached & (RectPart::Left | RectPart::Top)) - ? RectPart(0) - : RectPart::TopLeft) - | ((geometry.attached & (RectPart::Top | RectPart::Right)) - ? RectPart(0) - : RectPart::TopRight) - | ((geometry.attached & (RectPart::Right | RectPart::Bottom)) - ? RectPart(0) - : RectPart::BottomRight) - | ((geometry.attached & (RectPart::Bottom | RectPart::Left)) - ? RectPart(0) - : RectPart::BottomLeft); - result.radius = ImageRoundRadius::Large; + result.rounding = CornersMaskRef(CornersMask(ImageRoundRadius::Large)); + if (geometry.attached & (RectPart::Top | RectPart::Left)) { + result.rounding.p[kTopLeft] = nullptr; + } + if (geometry.attached & (RectPart::Top | RectPart::Right)) { + result.rounding.p[kTopRight] = nullptr; + } + if (geometry.attached & (RectPart::Bottom | RectPart::Left)) { + result.rounding.p[kBottomLeft] = nullptr; + } + if (geometry.attached & (RectPart::Bottom | RectPart::Right)) { + result.rounding.p[kBottomRight] = nullptr; + } return UnrotateRequest(result, geometry.rotation); } @@ -175,19 +173,11 @@ QImage Pip::RendererSW::staticContentByRequest( // _instance.info().video.rotation, // request, // std::move(_preparedCoverStorage)); - using Option = Images::Option; - const auto corner = [&](RectPart part, Option skip) { - return !(request.corners & part) ? skip : Option(); - }; - const auto options = Option::RoundLarge - | corner(RectPart::TopLeft, Option::RoundSkipTopLeft) - | corner(RectPart::TopRight, Option::RoundSkipTopRight) - | corner(RectPart::BottomLeft, Option::RoundSkipBottomLeft) - | corner(RectPart::BottomRight, Option::RoundSkipBottomRight); - _preparedStaticContent = Images::Prepare( + _preparedStaticContent = Images::Round(Images::Prepare( image, request.resize, - { .options = options, .outer = request.outer }); + { .outer = request.outer }), request.rounding); + return _preparedStaticContent; } diff --git a/Telegram/SourceFiles/ui/cached_round_corners.cpp b/Telegram/SourceFiles/ui/cached_round_corners.cpp index 8eda355148..38fd751d18 100644 --- a/Telegram/SourceFiles/ui/cached_round_corners.cpp +++ b/Telegram/SourceFiles/ui/cached_round_corners.cpp @@ -161,10 +161,6 @@ 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) { - 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 &corners) { constexpr auto kLeft = 2; constexpr auto kRight = 3; diff --git a/Telegram/SourceFiles/ui/cached_round_corners.h b/Telegram/SourceFiles/ui/cached_round_corners.h index 86e252eed4..d9d9727154 100644 --- a/Telegram/SourceFiles/ui/cached_round_corners.h +++ b/Telegram/SourceFiles/ui/cached_round_corners.h @@ -40,10 +40,6 @@ 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); -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) { FillRoundRect(p, rect.x(), rect.y(), rect.width(), rect.height(), bg, radius, parts); diff --git a/Telegram/SourceFiles/ui/chat/chat_style.cpp b/Telegram/SourceFiles/ui/chat/chat_style.cpp index 4e9aaa826a..bacd52c832 100644 --- a/Telegram/SourceFiles/ui/chat/chat_style.cpp +++ b/Telegram/SourceFiles/ui/chat/chat_style.cpp @@ -693,10 +693,7 @@ void FillComplexOverlayRect( QRect rect, const style::color &color, const CornersPixmaps &corners) { - constexpr auto kTopLeft = 0; - constexpr auto kTopRight = 1; - constexpr auto kBottomLeft = 2; - constexpr auto kBottomRight = 3; + using namespace Images; const auto pix = corners.p; const auto fillRect = [&](QRect rect) { @@ -795,36 +792,14 @@ void FillComplexOverlayRect( } } -void FillComplexOverlayRect( +void FillComplexEllipse( QPainter &p, not_null st, - QRect rect, - ImageRoundRadius radius, - RectParts roundCorners) { - const auto bg = st->msgSelectOverlay(); - if (radius == ImageRoundRadius::Ellipse) { - PainterHighQualityEnabler hq(p); - p.setPen(Qt::NoPen); - p.setBrush(bg); - p.drawEllipse(rect); - } else { - // #TODO rounding - //const auto &corners = (radius == ImageRoundRadius::Small) - // ? st->msgSelectOverlayCornersSmall() - // : st->msgSelectOverlayCornersLarge(); - //RectWithCorners(p, rect, bg, corners, roundCorners); - } -} - -void FillComplexLocationRect( - QPainter &p, - not_null st, - QRect rect, - ImageRoundRadius radius, - RectParts roundCorners) { - const auto stm = &st->messageStyle(false, false); - // #TODO rounding - RectWithCorners(p, rect, stm->msgBg, stm->msgBgCornersSmall, roundCorners); + QRect rect) { + PainterHighQualityEnabler hq(p); + p.setPen(Qt::NoPen); + p.setBrush(st->msgSelectOverlay()); + p.drawEllipse(rect); } } // namespace Ui diff --git a/Telegram/SourceFiles/ui/chat/chat_style.h b/Telegram/SourceFiles/ui/chat/chat_style.h index fc0ace58f4..443459bde9 100644 --- a/Telegram/SourceFiles/ui/chat/chat_style.h +++ b/Telegram/SourceFiles/ui/chat/chat_style.h @@ -360,17 +360,9 @@ void FillComplexOverlayRect( const style::color &color, const CornersPixmaps &corners); -void FillComplexOverlayRect( +void FillComplexEllipse( QPainter &p, not_null st, - QRect rect, - ImageRoundRadius radius, - RectParts roundCorners); -void FillComplexLocationRect( - QPainter &p, - not_null st, - QRect rect, - ImageRoundRadius radius, - RectParts roundCorners); + QRect rect); } // namespace Ui diff --git a/Telegram/SourceFiles/ui/special_buttons.cpp b/Telegram/SourceFiles/ui/special_buttons.cpp index 7773cb63d2..a9ae3b59ef 100644 --- a/Telegram/SourceFiles/ui/special_buttons.cpp +++ b/Telegram/SourceFiles/ui/special_buttons.cpp @@ -478,7 +478,10 @@ void UserpicButton::paintUserpicFrame(Painter &p, QPoint photoPosition) { auto size = QSize{ _st.photoSize, _st.photoSize }; request.outer = size * cIntRetinaFactor(); request.resize = size * cIntRetinaFactor(); - request.radius = ImageRoundRadius::Ellipse; + if (_ellipseMask.size() != request.outer) { + _ellipseMask = Images::EllipseMask(size); + } + request.mask = _ellipseMask; p.drawImage(QRect(photoPosition, size), _streamed->frame(request)); if (!paused) { _streamed->markFrameShown(); diff --git a/Telegram/SourceFiles/ui/special_buttons.h b/Telegram/SourceFiles/ui/special_buttons.h index d744d07dac..82563e4c56 100644 --- a/Telegram/SourceFiles/ui/special_buttons.h +++ b/Telegram/SourceFiles/ui/special_buttons.h @@ -170,6 +170,7 @@ private: InMemoryKey _userpicUniqueKey; Ui::Animations::Simple _a_appearance; QImage _result; + QImage _ellipseMask; std::unique_ptr _streamed; PhotoData *_streamedPhoto = nullptr; diff --git a/Telegram/lib_ui b/Telegram/lib_ui index cec09b0260..2c2a7887e6 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit cec09b0260ba19639bf9abc7df373569aa1509e7 +Subproject commit 2c2a7887e644dff7130d764c5a7b04aaa0463056