From 3cb645f50704b67537167e14623840a25fbdda7a Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 6 Jan 2023 17:05:24 +0400 Subject: [PATCH] Allow fully custom QImage shadows. --- ui/layers/layer_widget.cpp | 2 +- ui/widgets/shadow.cpp | 107 ++++++++++++++++++++++++++----------- ui/widgets/shadow.h | 10 +++- 3 files changed, 85 insertions(+), 34 deletions(-) diff --git a/ui/layers/layer_widget.cpp b/ui/layers/layer_widget.cpp index 0dac7f4..18aa85d 100644 --- a/ui/layers/layer_widget.cpp +++ b/ui/layers/layer_widget.cpp @@ -259,7 +259,7 @@ void LayerStackWidget::BackgroundWidget::paintEvent(QPaintEvent *e) { if (topCorners || bottomCorners) { p.setClipRegion(QRegion(rect()) - specialLayerBox.marginsRemoved(QMargins(st::boxRadius, 0, st::boxRadius, 0)) - specialLayerBox.marginsRemoved(QMargins(0, st::boxRadius, 0, st::boxRadius))); } - Ui::Shadow::paint(p, specialLayerBox, width(), st::boxRoundShadow, sides, Ui::SpecialLayerShadowCorners()); + Ui::Shadow::paint(p, specialLayerBox, width(), st::boxRoundShadow, Ui::SpecialLayerShadowCorners(), sides); if (topCorners || bottomCorners) { p.setClipping(false); } diff --git a/ui/widgets/shadow.cpp b/ui/widgets/shadow.cpp index 6d790ec..efbedf9 100644 --- a/ui/widgets/shadow.cpp +++ b/ui/widgets/shadow.cpp @@ -16,35 +16,53 @@ namespace Ui { namespace { +struct CustomImage { +public: + explicit CustomImage(const QImage &image) + : _image(image) { + } + void paint(QPainter &p, int x, int y, int outerw) const { + p.drawImage(x, y, _image); + } + void fill(QPainter &p, QRect rect) const { + p.drawImage(rect, _image); + } + [[nodiscard]] bool empty() const { + return _image.isNull(); + } + [[nodiscard]] int width() const { + return _image.width() / style::DevicePixelRatio(); + } + [[nodiscard]] int height() const { + return _image.height() / style::DevicePixelRatio(); + } + +private: + const QImage &_image; + +}; + struct CustomShadowCorners { - struct Image { - public: - Image(const QImage &image) - : _image(image) { - } - void paint(QPainter &p, int x, int y, int outerw) const { - p.drawImage(x, y, _image); - } - [[nodiscard]] bool empty() const { - return _image.isNull(); - } - [[nodiscard]] int width() const { - return _image.width() / style::DevicePixelRatio(); - } - [[nodiscard]] int height() const { - return _image.height() / style::DevicePixelRatio(); - } - private: - const QImage &_image; - }; const style::icon &left; - Image topLeft; + CustomImage topLeft; const style::icon ⊤ - Image topRight; + CustomImage topRight; const style::icon &right; - Image bottomRight; + CustomImage bottomRight; const style::icon ⊥ - Image bottomLeft; + CustomImage bottomLeft; + const style::margins &extend; +}; + +struct CustomShadow { + CustomImage left; + CustomImage topLeft; + CustomImage top; + CustomImage topRight; + CustomImage right; + CustomImage bottomRight; + CustomImage bottom; + CustomImage bottomLeft; const style::margins &extend; }; @@ -121,7 +139,7 @@ void PlainShadow::paintEvent(QPaintEvent *e) { } void Shadow::paint(QPainter &p, const QRect &box, int outerWidth, const style::Shadow &st, RectParts sides) { - ShadowPaint(p, box, outerWidth, st, std::move(sides)); + ShadowPaint(p, box, outerWidth, st, sides); } void Shadow::paint( @@ -129,20 +147,45 @@ void Shadow::paint( const QRect &box, int outerWidth, const style::Shadow &st, - RectParts sides, - const std::array &corners) { + const std::array &corners, + RectParts sides) { const auto shadow = CustomShadowCorners{ .left = st.left, - .topLeft = CustomShadowCorners::Image(corners[0]), + .topLeft = CustomImage(corners[0]), .top = st.top, - .topRight = CustomShadowCorners::Image(corners[2]), + .topRight = CustomImage(corners[2]), .right = st.right, - .bottomRight = CustomShadowCorners::Image(corners[3]), + .bottomRight = CustomImage(corners[3]), .bottom = st.bottom, - .bottomLeft = CustomShadowCorners::Image(corners[1]), + .bottomLeft = CustomImage(corners[1]), .extend = st.extend, }; - ShadowPaint(p, box, outerWidth, shadow, std::move(sides)); + ShadowPaint(p, box, outerWidth, shadow, sides); +} + +void Shadow::paint( + QPainter &p, + const QRect &box, + int outerWidth, + const style::Shadow &st, + const std::array &sides, + const std::array &corners) { + const auto shadow = CustomShadow{ + .left = CustomImage(sides[0]), + .topLeft = CustomImage(corners[0]), + .top = CustomImage(sides[1]), + .topRight = CustomImage(corners[2]), + .right = CustomImage(sides[2]), + .bottomRight = CustomImage(corners[3]), + .bottom = CustomImage(sides[3]), + .bottomLeft = CustomImage(corners[1]), + .extend = st.extend, + }; + ShadowPaint(p, box, outerWidth, shadow, RectPart() + | (sides[0].isNull() ? RectPart() : RectPart::Left) + | (sides[1].isNull() ? RectPart() : RectPart::Top) + | (sides[2].isNull() ? RectPart() : RectPart::Right) + | (sides[3].isNull() ? RectPart() : RectPart::Bottom)); } QPixmap Shadow::grab( diff --git a/ui/widgets/shadow.h b/ui/widgets/shadow.h index b2ee435..0eebab0 100644 --- a/ui/widgets/shadow.h +++ b/ui/widgets/shadow.h @@ -51,7 +51,15 @@ public: const QRect &box, int outerWidth, const style::Shadow &st, - RectParts sides, + const std::array &corners, + RectParts sides = RectPart::AllSides); + + static void paint( + QPainter &p, + const QRect &box, + int outerWidth, + const style::Shadow &st, + const std::array &sides, const std::array &corners); static QPixmap grab(