[vlc-commits] [Git][videolan/vlc][master] 8 commits: qt: introduce `RoundedRectangleShadow.frag`
Steve Lhomme (@robUx4)
gitlab at videolan.org
Tue May 13 05:07:30 UTC 2025
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
c1acfdb4 by Fatih Uzunoglu at 2025-05-13T04:44:17+00:00
qt: introduce `RoundedRectangleShadow.frag`
- - - - -
ca824ecf by Fatih Uzunoglu at 2025-05-13T04:44:17+00:00
qt: introduce `RoundedRectangleShadow.qml`
- - - - -
871e5655 by Fatih Uzunoglu at 2025-05-13T04:44:17+00:00
qml: use `RoundedRectangleShadow` in `DoubleShadow`
- - - - -
d16e4843 by Fatih Uzunoglu at 2025-05-13T04:44:17+00:00
qml: workaround for `DragItem` images sometimes not getting rendered
This seems to be similar to 089271fd, I assume something is wrong
with QSG batch renderer's optimizations.
- - - - -
e18740cd by Fatih Uzunoglu at 2025-05-13T04:44:17+00:00
qml: use `RoundedRectangleShadow` instead of `DropShadowImage` in `PlayButton.qml`
- - - - -
eb86ceb3 by Fatih Uzunoglu at 2025-05-13T04:44:17+00:00
qml: deprecate `DropShadowImage.qml` in favor of `RoundedRectangleShadow.qml`
- - - - -
b10ba234 by Fatih Uzunoglu at 2025-05-13T04:44:17+00:00
qml: use `RoundedRectangleShadow` instead of `DynamicShadow` in `Player.qml`
- - - - -
ed50b45d by Fatih Uzunoglu at 2025-05-13T04:44:17+00:00
qt: get rid of `DynamicShadow`
- - - - -
21 changed files:
- modules/gui/qt/Makefile.am
- modules/gui/qt/medialibrary/qml/MusicAlbumsGridExpandDelegate.qml
- modules/gui/qt/medialibrary/qml/VideoInfoExpandPanel.qml
- modules/gui/qt/meson.build
- modules/gui/qt/network/qml/NetworkThumbnailItem.qml
- modules/gui/qt/player/qml/Player.qml
- modules/gui/qt/player/qml/controlbarcontrols/ArtworkInfoWidget.qml
- modules/gui/qt/player/qml/controlbarcontrols/PlayButton.qml
- modules/gui/qt/playlist/qml/PlaylistDelegate.qml
- + modules/gui/qt/shaders/RoundedRectangleShadow.frag
- modules/gui/qt/shaders/meson.build
- modules/gui/qt/shaders/shaders.qrc
- modules/gui/qt/widgets/qml/DoubleShadow.qml
- modules/gui/qt/widgets/qml/DragItem.qml
- modules/gui/qt/widgets/qml/DropShadowImage.qml
- modules/gui/qt/widgets/qml/EmptyLabel.qml
- modules/gui/qt/widgets/qml/FloatingNotification.qml
- modules/gui/qt/widgets/qml/GridItem.qml
- modules/gui/qt/widgets/qml/DynamicShadow.qml → modules/gui/qt/widgets/qml/RoundedRectangleShadow.qml
- modules/gui/qt/widgets/qml/TableColumns.qml
- − modules/gui/qt/widgets/qml/compat/DynamicShadow.qml
Changes:
=====================================
modules/gui/qt/Makefile.am
=====================================
@@ -1307,14 +1307,13 @@ libqml_module_widgets_a_QML = \
widgets/qml/ImageExt.qml \
widgets/qml/ScrollBarExt.qml \
widgets/qml/FastBlend.qml \
- widgets/qml/RadioButtonExt.qml
+ widgets/qml/RadioButtonExt.qml \
+ widgets/qml/RoundedRectangleShadow.qml
if HAVE_QT65
libqml_module_widgets_a_QML += \
- widgets/qml/DynamicShadow.qml \
widgets/qml/BlurEffect.qml
else
libqml_module_widgets_a_QML += \
- widgets/qml/compat/DynamicShadow.qml \
widgets/qml/compat/BlurEffect.qml
endif
nodist_libqml_module_widgets_a_SOURCES = widgets_qmlassets.cpp
@@ -1365,7 +1364,8 @@ libqt_plugin_la_SHADER := shaders/FadingEdge.frag \
shaders/FastBlend.frag \
shaders/FastBlend_additive.frag \
shaders/FastBlend_multiply.frag \
- shaders/FastBlend_screen.frag
+ shaders/FastBlend_screen.frag \
+ shaders/RoundedRectangleShadow.frag
if ENABLE_QT
libqt_plugin_la_LIBADD += libqml_module_dialogs.a \
=====================================
modules/gui/qt/medialibrary/qml/MusicAlbumsGridExpandDelegate.qml
=====================================
@@ -133,10 +133,6 @@ FocusScope {
readonly property real eDPR: MainCtx.effectiveDevicePixelRatio(Window.window)
Widgets.DefaultShadow {
- anchors.centerIn: parent
-
- sourceItem: parent
-
visible: (parent.status === Image.Ready)
}
}
=====================================
modules/gui/qt/medialibrary/qml/VideoInfoExpandPanel.qml
=====================================
@@ -120,10 +120,6 @@ FocusScope {
readonly property real eDPR: MainCtx.effectiveDevicePixelRatio(Window.window)
Widgets.DefaultShadow {
- anchors.centerIn: parent
-
- sourceItem: parent
-
visible: (parent.status === Image.Ready)
}
}
=====================================
modules/gui/qt/meson.build
=====================================
@@ -808,10 +808,8 @@ qml_modules += {
}
if qt6_dep.version().version_compare('>=6.5.0')
- qml_dynamicshadow_file = 'widgets/qml/DynamicShadow.qml'
qml_blureffect_file = 'widgets/qml/BlurEffect.qml'
else
- qml_dynamicshadow_file = 'widgets/qml/compat/DynamicShadow.qml'
qml_blureffect_file = 'widgets/qml/compat/BlurEffect.qml'
endif
@@ -901,12 +899,12 @@ qml_modules += {
'widgets/qml/ViewHeader.qml',
'widgets/qml/ProgressIndicator.qml',
'widgets/qml/RectangularGlow.qml',
- qml_dynamicshadow_file,
qml_blureffect_file,
'widgets/qml/ImageExt.qml',
'widgets/qml/ScrollBarExt.qml',
'widgets/qml/FastBlend.qml',
'widgets/qml/RadioButtonExt.qml',
+ 'widgets/qml/RoundedRectangleShadow.qml',
),
}
=====================================
modules/gui/qt/network/qml/NetworkThumbnailItem.qml
=====================================
@@ -80,14 +80,6 @@ Widgets.TableRowDelegate {
width: artwork.width
height: artwork.height
- Widgets.DefaultShadow {
- anchors.centerIn: artwork
-
- // clip shadows to only the painted area of cover
- rectWidth: artwork.paintedWidth
- rectHeight: artwork.paintedHeight
- }
-
//FIXME: implement fillMode in RoundImage and use MediaCover here instead
//or directly TableCollumns.titleHeaderDelegate in place of NetworkThumbnailItem
NetworkCustomCover {
@@ -108,6 +100,10 @@ Widgets.TableRowDelegate {
color1: root.colorContext.fg.primary
accent: root.colorContext.accent
+ Widgets.DefaultShadow {
+
+ }
+
Widgets.PlayCover {
x: Math.round((artwork.width - width) / 2)
y: Math.round((artwork.height - height) / 2)
=====================================
modules/gui/qt/player/qml/Player.qml
=====================================
@@ -358,23 +358,6 @@ FocusScope {
readonly property real sizeConstant: 2.7182
- Widgets.DynamicShadow {
- anchors.centerIn: cover
- sourceItem: cover
-
- color: Qt.rgba(0, 0, 0, .18)
- yOffset: VLCStyle.dp(24)
- blurRadius: VLCStyle.dp(54)
- }
-
- Widgets.DynamicShadow {
- anchors.centerIn: cover
- sourceItem: cover
-
- color: Qt.rgba(0, 0, 0, .22)
- yOffset: VLCStyle.dp(5)
- blurRadius: VLCStyle.dp(14)
- }
Image {
id: cover
@@ -401,6 +384,18 @@ FocusScope {
Accessible.role: Accessible.Graphic
Accessible.name: qsTr("Cover")
+
+ Widgets.RoundedRectangleShadow {
+ color: Qt.rgba(0, 0, 0, .18)
+ yOffset: VLCStyle.dp(24)
+ blurRadius: VLCStyle.dp(54)
+ }
+
+ Widgets.RoundedRectangleShadow {
+ color: Qt.rgba(0, 0, 0, .22)
+ yOffset: VLCStyle.dp(5)
+ blurRadius: VLCStyle.dp(14)
+ }
}
}
=====================================
modules/gui/qt/player/qml/controlbarcontrols/ArtworkInfoWidget.qml
=====================================
@@ -184,9 +184,6 @@ AbstractButton {
}
Widgets.DefaultShadow {
- anchors.centerIn: coverImage
-
- sourceItem: coverImage
}
}
=====================================
modules/gui/qt/player/qml/controlbarcontrols/PlayButton.qml
=====================================
@@ -235,18 +235,13 @@ T.Control {
implicitWidth: height
implicitHeight: VLCStyle.icon_medium
- Widgets.DropShadowImage {
+ Widgets.RoundedRectangleShadow {
id: hoverShadow
- anchors.centerIn: parent
-
visible: opacity > 0
opacity: 0
- rectWidth: parent.width
- rectHeight: parent.height
- xRadius: parent.width
- yRadius: xRadius
+ radius: parent.width
blurRadius: VLCStyle.dp(9)
yOffset: VLCStyle.dp(4)
=====================================
modules/gui/qt/playlist/qml/PlaylistDelegate.qml
=====================================
@@ -193,10 +193,6 @@ T.Control {
}
Widgets.DefaultShadow {
- anchors.centerIn: parent
-
- sourceItem: parent
-
visible: (artwork.status === Image.Ready)
}
}
=====================================
modules/gui/qt/shaders/RoundedRectangleShadow.frag
=====================================
@@ -0,0 +1,121 @@
+#version 440
+
+// TODO: Dithering is not necessary with light colors. It is pretty much
+// necessary with dark colors due to premultiplied alpha to prevent
+// color banding. So, this should ideally be used only when the
+// background color is dark. When the build system starts supporting
+// defines to feed qsb, we can have the non-dithering version as well.
+#define DITHERING
+
+/*****************************************************************************
+ * Copyright (C) 2025 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#extension GL_GOOGLE_include_directive : enable
+
+#include "Common.glsl"
+
+// This is provided by the default vertex shader even when there is no texture:
+layout(location = 0) in vec2 qt_TexCoord0;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 qt_Matrix;
+ float qt_Opacity;
+
+ float blurRadius;
+ float radius;
+ float compensationFactor;
+
+ vec2 size;
+ vec4 color;
+};
+
+// Evan Wallace's Fast Rounded Rectangle Shadows
+// https://madebyevan.com/shaders/fast-rounded-rectangle-shadows/
+// License: CC0 (http://creativecommons.org/publicdomain/zero/1.0/)
+/// <roundedboxshadow>
+
+// A standard gaussian function, used for weighting samples
+float gaussian(float x, float sigma) {
+ const float pi = 3.141592653589793;
+ return exp(-(x * x) / (2.0 * sigma * sigma)) / (sqrt(2.0 * pi) * sigma);
+}
+
+// This approximates the error function, needed for the gaussian integral
+vec2 erf(vec2 x) {
+ vec2 s = sign(x), a = abs(x);
+ x = 1.0 + (0.278393 + (0.230389 + 0.078108 * (a * a)) * a) * a;
+ x *= x;
+ return s - s / (x * x);
+}
+
+// Return the blurred mask along the x dimension
+float roundedBoxShadowX(float x, float y, float sigma, float corner, vec2 halfSize) {
+ float delta = min(halfSize.y - corner - abs(y), 0.0);
+ float curved = halfSize.x - corner + sqrt(max(0.0, corner * corner - delta * delta));
+ vec2 integral = 0.5 + 0.5 * erf((x + vec2(-curved, curved)) * (sqrt(0.5) / sigma));
+ return integral.y - integral.x;
+}
+
+// Return the mask for the shadow of a box from lower to upper
+float roundedBoxShadow(vec2 lower, vec2 upper, vec2 point, float sigma, float corner) {
+ // Center everything to make the math easier
+ vec2 center = (lower + upper) * 0.5;
+ vec2 halfSize = (upper - lower) * 0.5;
+ point -= center;
+
+ // The signal is only non-zero in a limited range, so don't waste samples
+ float low = point.y - halfSize.y;
+ float high = point.y + halfSize.y;
+ float start = clamp(-3.0 * sigma, low, high);
+ float end = clamp(3.0 * sigma, low, high);
+
+ // Accumulate samples (we can get away with surprisingly few samples)
+ float step = (end - start) / 4.0;
+ float y = start + step * 0.5;
+ float value = 0.0;
+ for (int i = 0; i < 4; i++) {
+ value += roundedBoxShadowX(point.x, point.y - y, sigma, corner, halfSize) * gaussian(y, sigma) * step;
+ y += step;
+ }
+
+ return value;
+}
+
+/// </roundedboxshadow>
+
+void main()
+{
+ vec2 compensatedOffset = vec2(blurRadius, blurRadius) * compensationFactor;
+ vec2 denormalCoord = size * qt_TexCoord0;
+
+ float shadow = roundedBoxShadow(compensatedOffset,
+ size - compensatedOffset,
+ denormalCoord,
+ blurRadius,
+ radius / 2.);
+
+ fragColor = color * shadow * qt_Opacity; // premultiplied
+
+#ifdef DITHERING
+ float r = rand(qt_TexCoord0) - 0.5;
+ vec4 noise = vec4(r,r,r,r) * DITHERING_STRENGTH;
+ fragColor += noise * step(DITHERING_CUTOFF, fragColor.a); // additive
+#endif
+}
=====================================
modules/gui/qt/shaders/meson.build
=====================================
@@ -21,7 +21,8 @@ shader_sources = [
'FastBlend.frag',
'FastBlend_additive.frag',
'FastBlend_multiply.frag',
- 'FastBlend_screen.frag'
+ 'FastBlend_screen.frag',
+ 'RoundedRectangleShadow.frag',
]
shader_files = files(shader_sources)
=====================================
modules/gui/qt/shaders/shaders.qrc
=====================================
@@ -16,5 +16,6 @@
<file alias="FastBlend_additive.frag.qsb">FastBlend_additive.frag.qsb</file>
<file alias="FastBlend_multiply.frag.qsb">FastBlend_multiply.frag.qsb</file>
<file alias="FastBlend_screen.frag.qsb">FastBlend_screen.frag.qsb</file>
+ <file alias="RoundedRectangleShadow.frag.qsb">RoundedRectangleShadow.frag.qsb</file>
</qresource>
</RCC>
=====================================
modules/gui/qt/widgets/qml/DoubleShadow.qml
=====================================
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (C) 2022 VLC authors and VideoLAN
+ * Copyright (C) 2025 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,117 +18,44 @@
import QtQuick
-
-import VLC.Style
-import VLC.Util
-
-// A convenience file to encapsulate two drop shadow images stacked on top
-// of each other
+// A convenience file to encapsulate two drop shadow rectangles stacked
Item {
- implicitWidth: image.implicitWidth
- implicitHeight: image.implicitHeight
-
- property Item sourceItem: null
-
- readonly property real viewportHorizontalOffset: (Math.max(Math.abs(primaryHorizontalOffset) + primaryBlurRadius, Math.abs(secondaryHorizontalOffset) + secondaryBlurRadius)) * 2
- readonly property real viewportVerticalOffset: (Math.max(Math.abs(primaryVerticalOffset) + primaryBlurRadius, Math.abs(secondaryVerticalOffset) + secondaryBlurRadius)) * 2
-
- property real viewportWidth: rectWidth + viewportHorizontalOffset
- property real viewportHeight: rectHeight + viewportVerticalOffset
-
- property real rectWidth: sourceItem ? Math.min((sourceItem.paintedWidth ?? Number.MAX_VALUE) - Math.ceil(sourceItem.padding ?? 0) * 2, sourceItem.width) : 0
- property real rectHeight: sourceItem ? Math.min((sourceItem.paintedHeight ?? Number.MAX_VALUE) - Math.ceil(sourceItem.padding ?? 0) * 2, sourceItem.height) : 0
- property real xRadius: (sourceItem ? (sourceItem.effectiveRadius ?? sourceItem.radius) : 0) ?? 0
- property real yRadius: (sourceItem ? (sourceItem.effectiveRadius ?? sourceItem.radius) : 0) ?? 0
-
- property color primaryColor: Qt.rgba(0, 0, 0, .18)
- property real primaryVerticalOffset: 0
- property real primaryHorizontalOffset: 0
- property real primaryBlurRadius: 0
-
- property color secondaryColor: Qt.rgba(0, 0, 0, .22)
- property real secondaryVerticalOffset: 0
- property real secondaryHorizontalOffset: 0
- property real secondaryBlurRadius: 0
-
- property alias sourceSize: image.sourceSize
- property alias cache: image.cache
- property alias asynchronous: image.asynchronous
- property alias fillMode: image.fillMode
-
- z: -1
+ id: root
- visible: (width > 0 && height > 0)
+ property alias radius: primaryShadow.radius
- //by default we request
- sourceSize: Qt.size(viewportWidth, viewportHeight)
+ property alias primaryColor: primaryShadow.color
+ property alias primaryVerticalOffset: primaryShadow.yOffset
+ property alias primaryHorizontalOffset: primaryShadow.xOffset
+ property alias primaryBlurRadius: primaryShadow.blurRadius
- ScaledImage {
- id: image
+ property alias secondaryColor: secondaryShadow.color
+ property alias secondaryVerticalOffset: secondaryShadow.yOffset
+ property alias secondaryHorizontalOffset: secondaryShadow.xOffset
+ property alias secondaryBlurRadius: secondaryShadow.blurRadius
- anchors.fill: parent
+ primaryColor: Qt.rgba(0, 0, 0, .18)
+ secondaryColor: Qt.rgba(0, 0, 0, .22)
- cache: true
- asynchronous: true
+ RoundedRectangleShadow {
+ id: primaryShadow
- visible: !visualDelegate.readyForVisibility
+ parent: root.parent // similar to how Repeater behaves
- fillMode: Image.Stretch
-
- onSourceSizeChanged: {
- // Do not load the image when size is not valid:
- if (sourceSize.width > 0 && sourceSize.height > 0)
- source = Qt.binding(() => {
- return Effects.url(
- Effects.DoubleRoundedRectDropShadow,
- {
- "viewportWidth" : viewportWidth,
- "viewportHeight" :viewportHeight,
-
- "rectWidth": rectWidth,
- "rectHeight": rectHeight,
- "xRadius": xRadius,
- "yRadius": yRadius,
-
- "primaryColor": primaryColor,
- "primaryBlurRadius": primaryBlurRadius,
- "primaryXOffset": primaryHorizontalOffset,
- "primaryYOffset": primaryVerticalOffset,
-
- "secondaryColor": secondaryColor,
- "secondaryBlurRadius": secondaryBlurRadius,
- "secondaryXOffset": secondaryHorizontalOffset,
- "secondaryYOffset": secondaryVerticalOffset,
- })
- })
- else
- source = ""
- }
+ opacity: root.opacity
+ visible: root.visible
+ enabled: root.enabled
}
- ShaderEffect {
- id: visualDelegate
-
- anchors.centerIn: parent
- anchors.alignWhenCentered: true
-
- implicitWidth: image.implicitWidth
- implicitHeight: image.implicitHeight
-
- width: image.paintedWidth
- height: image.paintedHeight
-
- visible: readyForVisibility
-
- readonly property bool readyForVisibility: (GraphicsInfo.shaderType === GraphicsInfo.RhiShader)
+ RoundedRectangleShadow {
+ id: secondaryShadow
- supportsAtlasTextures: true
- blending: true
- // cullMode: ShaderEffect.BackFaceCulling
+ parent: root.parent // similar to how Repeater behaves
- readonly property Image source: image
+ opacity: root.opacity
+ visible: root.visible
+ enabled: root.enabled
- // TODO: Dithered texture is not necessary if theme is not dark.
- fragmentShader: "qrc:///shaders/DitheredTexture.frag.qsb"
+ radius: root.radius
}
}
=====================================
modules/gui/qt/widgets/qml/DragItem.qml
=====================================
@@ -510,9 +510,21 @@ Item {
}
DefaultShadow {
+
+ }
+
+ // FIXME: Qt bug (observed 6.2 and 6.8): The image does not get rendered without this.
+ Rectangle {
+ z: -1
+
anchors.centerIn: parent
- sourceItem: parent
+ width: 1
+ height: 1
+
+ opacity: 0.01
+
+ color: "black"
}
}
}
@@ -544,9 +556,7 @@ Item {
}
DefaultShadow {
- anchors.centerIn: parent
- sourceItem: extraCovers
}
}
=====================================
modules/gui/qt/widgets/qml/DropShadowImage.qml
=====================================
@@ -20,6 +20,8 @@ import QtQuick
import VLC.Util
+
+// WARNING: This is deprecated in favor of RoundedRectangleShadow, and may be removed at any time. Avoid using it.
Item {
implicitWidth: image.implicitWidth
implicitHeight: image.implicitHeight
=====================================
modules/gui/qt/widgets/qml/EmptyLabel.qml
=====================================
@@ -76,9 +76,7 @@ T.Control {
fillMode: Image.PreserveAspectFit
Widgets.DefaultShadow {
- anchors.centerIn: parent
- sourceItem: parent
}
}
=====================================
modules/gui/qt/widgets/qml/FloatingNotification.qml
=====================================
@@ -156,9 +156,7 @@ Column {
}
DefaultShadow {
- anchors.centerIn: parent
- sourceItem: parent
}
SubtitleLabel {
=====================================
modules/gui/qt/widgets/qml/GridItem.qml
=====================================
@@ -297,41 +297,15 @@ T.ItemDelegate {
DefaultShadow {
id: unselectedShadow
- anchors.centerIn: parent
-
visible: opacity > 0
-
- sourceItem: parent
-
- width: picture.paintedWidth + viewportHorizontalOffset - Math.ceil(picture.padding) * 2
- height: picture.paintedHeight + viewportVerticalOffset - Math.ceil(picture.padding) * 2
-
- rectWidth: sourceSize.width
- rectHeight: sourceSize.height
-
- // TODO: Apply painted size's aspect ratio (constant) in source size
- sourceSize: Qt.size(128, 128)
}
DoubleShadow {
id: selectedShadow
- anchors.centerIn: parent
-
visible: opacity > 0
opacity: 0
- sourceItem: parent
-
- width: picture.paintedWidth + viewportHorizontalOffset - Math.ceil(picture.padding) * 2
- height: picture.paintedHeight + viewportVerticalOffset - Math.ceil(picture.padding) * 2
-
- rectWidth: sourceSize.width
- rectHeight: sourceSize.height
-
- // TODO: Apply painted size's aspect ratio (constant) in source size
- sourceSize: Qt.size(128, 128)
-
primaryVerticalOffset: VLCStyle.dp(6, VLCStyle.scale)
primaryBlurRadius: VLCStyle.dp(18, VLCStyle.scale)
=====================================
modules/gui/qt/widgets/qml/DynamicShadow.qml → modules/gui/qt/widgets/qml/RoundedRectangleShadow.qml
=====================================
@@ -1,5 +1,5 @@
/*****************************************************************************
- * Copyright (C) 2024 VLC authors and VideoLAN
+ * Copyright (C) 2025 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,37 +16,46 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
import QtQuick
-import QtQuick.Effects
-MultiEffect {
- id: effect
+// This item uses Evan Wallace's Fast Rounded Rectangle Shadow (CC0).
+// This is considered a better approach than any texture based approach (whether GPU or CPU generated).
+// Regarding non-texture based solutions, it has the advantage over Qt 6.9's `RectangularShadow` or
+// Qt 5's `RectangularGlow` that this uses proper approximation of gaussian blur instead of relying on
+// `smoothstep()`, which I assume is good for glow effect but not for shadows.
+ShaderEffect {
+ implicitWidth: parent ? Math.min((parent.paintedWidth ?? Number.MAX_VALUE) - Math.ceil(parent.padding ?? 0) * 2, parent.width) + (blurRadius * compensationFactor * 2)
+ : 0
+ implicitHeight: parent ? Math.min((parent.paintedHeight ?? Number.MAX_VALUE) - Math.ceil(parent.padding ?? 0) * 2, parent.height) + (blurRadius * compensationFactor * 2)
+ : 0
- implicitWidth: sourceItem ? Math.min(sourceItem.paintedWidth ?? Number.MAX_VALUE, sourceItem.width) : 0
- implicitHeight: sourceItem ? Math.min(sourceItem.paintedHeight ?? Number.MAX_VALUE, sourceItem.height) : 0
+ z: -1
- shadowEnabled: true
- shadowBlur: 1.0
+ anchors.centerIn: parent
+ anchors.horizontalCenterOffset: xOffset
+ anchors.verticalCenterOffset: yOffset
- paddingRect: Qt.rect(xOffset, yOffset, 0, 0)
+ // Any of these properties can be freely animated:
+ property real blurRadius: 0.0
+ property color color
- visible: (GraphicsInfo.shaderType === GraphicsInfo.RhiShader)
+ // These are only respected when anchoring is used to center the item:
+ property real xOffset
+ property real yOffset
- property alias sourceItem: effect.source
+ // Currently different xRadius/yRadius is not supported.
+ property real radius: (parent ? (parent.effectiveRadius ?? parent.radius) : 0) ?? 0
- property alias xOffset: effect.shadowHorizontalOffset
- property alias yOffset: effect.shadowVerticalOffset
+ readonly property size size: Qt.size(width, height)
- property alias blurRadius: effect.blurMax
+ // Increase the compensation factor if clipping occurs, but make it as small as possible
+ // to prevent overlapping shadows (breaks batching) and to decrease the shader coverage:
+ property real compensationFactor: 2.0
- property alias color: effect.shadowColor
+ blending: true
- Binding {
- // Source item should be made invisible
- // since multi effect already renders
- // the source item.
- when: sourceItem && effect.visible
- target: sourceItem
- property: "visible"
- value: false
- }
+ supportsAtlasTextures: true // irrelevant, but nevertheless...
+
+ // cullMode: ShaderEffect.BackFaceCulling // problematic with item layers
+
+ fragmentShader: "qrc:///shaders/RoundedRectangleShadow.frag.qsb"
}
=====================================
modules/gui/qt/widgets/qml/TableColumns.qml
=====================================
@@ -135,9 +135,7 @@ Item {
}
DefaultShadow {
- anchors.centerIn: parent
- sourceItem: parent
}
onPlayIconClicked: root.playClicked(titleDel.rowModel)
=====================================
modules/gui/qt/widgets/qml/compat/DynamicShadow.qml deleted
=====================================
@@ -1,24 +0,0 @@
-/*****************************************************************************
- * Copyright (C) 2024 VLC authors and VideoLAN
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * ( at your option ) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-import QtQuick
-
-import VLC.Widgets
-
-DropShadowImage {
- cache: false
-}
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/3a3d8dd7c2b773a8133e242a5fb52dc82d8c12d5...ed50b45d958a1d46a6272cd6252206be32082619
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/3a3d8dd7c2b773a8133e242a5fb52dc82d8c12d5...ed50b45d958a1d46a6272cd6252206be32082619
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list