From 330838275a0fe4225f7fce90eeb240bd4c61077d Mon Sep 17 00:00:00 2001 From: Fatih Uzunoglu <fuzun54@outlook.com> Date: Sat, 15 Feb 2025 21:24:48 +0200 Subject: [PATCH 1/7] qt: move `sdRoundBox()` from `SDFAARoundedTexture.frag` to `SDF.glsl` So that it can be re-used in other shaders. --- modules/gui/qt/Makefile.am | 6 +++- modules/gui/qt/shaders/SDF.glsl | 27 ++++++++++++++ .../gui/qt/shaders/SDFAARoundedTexture.frag | 30 ++-------------- .../SDFAARoundedTexture_cropsupport.frag | 30 ++-------------- modules/gui/qt/shaders/meson.build | 36 ++++++++++--------- 5 files changed, 58 insertions(+), 71 deletions(-) create mode 100644 modules/gui/qt/shaders/SDF.glsl diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am index f6a2a0c29672..a5902404ca9a 100644 --- a/modules/gui/qt/Makefile.am +++ b/modules/gui/qt/Makefile.am @@ -1354,6 +1354,10 @@ libqt_plugin_la_SHADER := shaders/FadingEdge.frag \ shaders/SDFAARoundedTexture.frag \ shaders/SDFAARoundedTexture_cropsupport.frag \ shaders/DitheredTexture.frag + +shaders/SDFAARoundedTexture.frag: shaders/SDF.glsl +shaders/SDFAARoundedTexture_cropsupport.frag: shaders/SDF.glsl + if ENABLE_QT libqt_plugin_la_LIBADD += libqml_module_dialogs.a \ @@ -1407,7 +1411,7 @@ QSB_PARAMS_VERBOSE_ = $(QSB_PARAMS_VERBOSE__$(AM_DEFAULT_VERBOSITY)) QSB_PARAMS_VERBOSE_0 = -s QSB_PARAMS_VERBOSE__0 = $(QSB_PARAMS_VERBOSE_0) -EXTRA_DIST += shaders/Common.glsl +EXTRA_DIST += shaders/Common.glsl shaders/SDF.glsl %.frag.qsb: %.frag shaders/Common.glsl $(qsb_verbose)PATH="$(QSB_EXTRA_PATH)$$PATH" $(QSB) $(QSB_PARAMS) $(QSB_PARAMS_VERBOSE) -o $@ $< diff --git a/modules/gui/qt/shaders/SDF.glsl b/modules/gui/qt/shaders/SDF.glsl new file mode 100644 index 000000000000..e8f69e44aa2f --- /dev/null +++ b/modules/gui/qt/shaders/SDF.glsl @@ -0,0 +1,27 @@ +/***************************************************************************** + * Copyright (C) 2015 Inigo Quilez + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the “Softwareâ€), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + *****************************************************************************/ + +// Signed distance function by Inigo Quilez (https://iquilezles.org/articles/distfunctions2d) +// b.x = width +// b.y = height +// r.x = roundness top-right +// r.y = roundness boottom-right +// r.z = roundness top-left +// r.w = roundness bottom-left +float sdRoundBox( in vec2 p, in vec2 b, in vec4 r ) +{ + r.xy = (p.x>0.0)?r.xy : r.zw; + r.x = (p.y>0.0)?r.x : r.y; + vec2 q = abs(p)-b+r.x; + return min(max(q.x,q.y),0.0) + length(max(q,0.0)) - r.x; +} diff --git a/modules/gui/qt/shaders/SDFAARoundedTexture.frag b/modules/gui/qt/shaders/SDFAARoundedTexture.frag index 88438b601ba2..ae18ef833c4a 100644 --- a/modules/gui/qt/shaders/SDFAARoundedTexture.frag +++ b/modules/gui/qt/shaders/SDFAARoundedTexture.frag @@ -22,18 +22,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ -/***************************************************************************** - * Copyright (C) 2015 Inigo Quilez - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the “Softwareâ€), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is furnished - * to do so, subject to the following conditions: - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - *****************************************************************************/ +#extension GL_GOOGLE_include_directive : enable + +#include "SDF.glsl" layout(location = 0) in vec2 qt_TexCoord0; @@ -62,21 +53,6 @@ layout(std140, binding = 0) uniform buf { layout(binding = 1) uniform sampler2D source; -// Signed distance function by Inigo Quilez (https://iquilezles.org/articles/distfunctions2d) -// b.x = width -// b.y = height -// r.x = roundness top-right -// r.y = roundness boottom-right -// r.z = roundness top-left -// r.w = roundness bottom-left -float sdRoundBox( in vec2 p, in vec2 b, in vec4 r ) -{ - r.xy = (p.x>0.0)?r.xy : r.zw; - r.x = (p.y>0.0)?r.x : r.y; - vec2 q = abs(p)-b+r.x; - return min(max(q.x,q.y),0.0) + length(max(q,0.0)) - r.x; -} - void main() { // The signed distance function works when the primitive is centered. diff --git a/modules/gui/qt/shaders/SDFAARoundedTexture_cropsupport.frag b/modules/gui/qt/shaders/SDFAARoundedTexture_cropsupport.frag index f3ba567bc40b..803e37cdd8fc 100644 --- a/modules/gui/qt/shaders/SDFAARoundedTexture_cropsupport.frag +++ b/modules/gui/qt/shaders/SDFAARoundedTexture_cropsupport.frag @@ -34,18 +34,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ -/***************************************************************************** - * Copyright (C) 2015 Inigo Quilez - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the “Softwareâ€), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is furnished - * to do so, subject to the following conditions: - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - *****************************************************************************/ +#extension GL_GOOGLE_include_directive : enable + +#include "SDF.glsl" layout(location = 0) in vec2 qt_TexCoord0; @@ -74,21 +65,6 @@ layout(std140, binding = 0) uniform buf { layout(binding = 1) uniform sampler2D source; -// Signed distance function by Inigo Quilez (https://iquilezles.org/articles/distfunctions2d) -// b.x = width -// b.y = height -// r.x = roundness top-right -// r.y = roundness boottom-right -// r.z = roundness top-left -// r.w = roundness bottom-left -float sdRoundBox( in vec2 p, in vec2 b, in vec4 r ) -{ - r.xy = (p.x>0.0)?r.xy : r.zw; - r.x = (p.y>0.0)?r.x : r.y; - vec2 q = abs(p)-b+r.x; - return min(max(q.x,q.y),0.0) + length(max(q,0.0)) - r.x; -} - void main() { // The signed distance function works when the primitive is centered. diff --git a/modules/gui/qt/shaders/meson.build b/modules/gui/qt/shaders/meson.build index b23d7fc9d014..0870d76ad1bf 100644 --- a/modules/gui/qt/shaders/meson.build +++ b/modules/gui/qt/shaders/meson.build @@ -7,21 +7,22 @@ env = environment() env.append('PATH', contrib_dir + '/bin') shader_sources = [ - 'FadingEdge.frag', - 'FadingEdgeX.vert', - 'FadingEdgeY.vert', - 'Noise.frag', - 'RectFilter.frag', - 'SubTexture.vert', - 'PlayerBlurredBackground.frag', - 'HollowRectangularGlow.frag', - 'RectangularGlow.frag', - 'SDFAARoundedTexture.frag', - 'SDFAARoundedTexture_cropsupport.frag', - 'DitheredTexture.frag' + {'shader': 'FadingEdge.frag', 'dependencies': []}, + {'shader': 'FadingEdgeX.vert', 'dependencies': []}, + {'shader': 'FadingEdgeY.vert', 'dependencies': []}, + {'shader': 'Noise.frag', 'dependencies': []}, + {'shader': 'RectFilter.frag', 'dependencies': []}, + {'shader': 'SubTexture.vert', 'dependencies': []}, + {'shader': 'PlayerBlurredBackground.frag', 'dependencies': []}, + {'shader': 'HollowRectangularGlow.frag', 'dependencies': []}, + {'shader': 'RectangularGlow.frag', 'dependencies': []}, + {'shader': 'DitheredTexture.frag', 'dependencies': []}, + {'shader': 'SDFAARoundedTexture.frag', 'dependencies': ['SDF.glsl']}, + {'shader': 'SDFAARoundedTexture_cropsupport.frag', 'dependencies': ['SDF.glsl']}, ] -shader_files = files(shader_sources) +# This is populated in the for-each loop below: +shader_files = [] qt_bin_directory = qt6_dep.get_variable(pkgconfig: 'bindir', configtool: 'QT_HOST_BINS') qsb = find_program('qsb', dirs: qt_bin_directory, required: true) @@ -35,11 +36,14 @@ endif shader_targets = [] foreach shader: shader_sources - shader_target_name = shader + '.qsb' + shader_file = shader['shader'] + shader_files += files(shader_file) + + shader_target_name = shader_file + '.qsb' target = custom_target(shader_target_name, - depend_files: ['Common.glsl'], - input: shader, + depend_files: shader['dependencies'] + 'Common.glsl', + input: shader_file, output: shader_target_name, command: [qsb, qsb_params, '--output', '@OUTPUT@', '@INPUT@'] ) -- GitLab From 6c5ce9468b424d9b8253f8ca67198bf0250102c7 Mon Sep 17 00:00:00 2001 From: Fatih Uzunoglu <fuzun54@outlook.com> Date: Sat, 15 Feb 2025 23:02:00 +0200 Subject: [PATCH 2/7] qt: introduce `VideoProgressBar.frag` --- modules/gui/qt/Makefile.am | 4 +- modules/gui/qt/shaders/VideoProgressBar.frag | 75 ++++++++++++++++++++ modules/gui/qt/shaders/meson.build | 1 + modules/gui/qt/shaders/shaders.qrc | 1 + 4 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 modules/gui/qt/shaders/VideoProgressBar.frag diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am index a5902404ca9a..52924bb3c979 100644 --- a/modules/gui/qt/Makefile.am +++ b/modules/gui/qt/Makefile.am @@ -1353,10 +1353,12 @@ libqt_plugin_la_SHADER := shaders/FadingEdge.frag \ shaders/RectangularGlow.frag \ shaders/SDFAARoundedTexture.frag \ shaders/SDFAARoundedTexture_cropsupport.frag \ - shaders/DitheredTexture.frag + shaders/DitheredTexture.frag \ + shaders/VideoProgressBar.frag shaders/SDFAARoundedTexture.frag: shaders/SDF.glsl shaders/SDFAARoundedTexture_cropsupport.frag: shaders/SDF.glsl +shaders/VideoProgressBar.frag: shaders/SDF.glsl if ENABLE_QT diff --git a/modules/gui/qt/shaders/VideoProgressBar.frag b/modules/gui/qt/shaders/VideoProgressBar.frag new file mode 100644 index 000000000000..a256e47cbb1a --- /dev/null +++ b/modules/gui/qt/shaders/VideoProgressBar.frag @@ -0,0 +1,75 @@ +#version 440 + +#define ANTIALIASING + +/***************************************************************************** + * 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 "SDF.glsl" + +layout(location = 0) out vec4 fragColor; + +// NOTE: Even though there is no texture, `qt_TexCoord0` is still provided. +// This is useful, because we don't need to normalize ourselves from +// gl_FragCoord using qt_Matrix and viewport size. As there is no +// texture sampler, this is always in normal form (no need to care +// about the texture atlas): +layout(location = 0) in vec2 qt_TexCoord0; + +layout(std140, binding = 0) uniform buf { + mat4 qt_Matrix; + float qt_Opacity; + + float progress; + float radius; + + vec2 size; + + vec4 elapsedColor; + vec4 remainingColor; +}; + +void main() +{ + vec2 p = (size.xy * ((2.0 * qt_TexCoord0) - 1)) / size.y; + + // Signed distance: + // TODO: Round box distance function may be reducted when radius for top left and top right are always infinite. + float dist = sdRoundBox(p, vec2(size.x / size.y, 1.0), vec4(radius, 999., radius, 999.)); + + vec4 color = (qt_TexCoord0.x <= progress) ? elapsedColor : remainingColor; + +#ifdef ANTIALIASING + float softEdgeMax = fwidth(dist) * 0.75; + float softEdgeMin = -softEdgeMax; + + // Soften the outline, as recommended by the Valve paper, using smoothstep: + // "Improved Alpha-Tested Magnification for Vector Textures and Special Effects" + // NOTE: The whole texel is multiplied, because of premultiplied alpha. + float factor = smoothstep(softEdgeMin, softEdgeMax, dist); +#else + float factor = step(0.0, dist); +#endif + + // NOTE: Colors are in premultiplied alpha format + color *= (1.0 - factor); + + fragColor = color * qt_Opacity; +} diff --git a/modules/gui/qt/shaders/meson.build b/modules/gui/qt/shaders/meson.build index 0870d76ad1bf..714b057cb08f 100644 --- a/modules/gui/qt/shaders/meson.build +++ b/modules/gui/qt/shaders/meson.build @@ -19,6 +19,7 @@ shader_sources = [ {'shader': 'DitheredTexture.frag', 'dependencies': []}, {'shader': 'SDFAARoundedTexture.frag', 'dependencies': ['SDF.glsl']}, {'shader': 'SDFAARoundedTexture_cropsupport.frag', 'dependencies': ['SDF.glsl']}, + {'shader': 'VideoProgressBar.frag', 'dependencies': ['SDF.glsl']}, ] # This is populated in the for-each loop below: diff --git a/modules/gui/qt/shaders/shaders.qrc b/modules/gui/qt/shaders/shaders.qrc index 58f3ff53afec..5412a2b2966b 100644 --- a/modules/gui/qt/shaders/shaders.qrc +++ b/modules/gui/qt/shaders/shaders.qrc @@ -13,5 +13,6 @@ <file alias="SDFAARoundedTexture.frag.qsb">SDFAARoundedTexture.frag.qsb</file> <file alias="SDFAARoundedTexture_cropsupport.frag.qsb">SDFAARoundedTexture_cropsupport.frag.qsb</file> <file alias="DitheredTexture.frag.qsb">DitheredTexture.frag.qsb</file> + <file alias="VideoProgressBar.frag.qsb">VideoProgressBar.frag.qsb</file> </qresource> </RCC> -- GitLab From 6a67d94c90d561c057481917d0de04ae8dd619fd Mon Sep 17 00:00:00 2001 From: Fatih Uzunoglu <fuzun54@outlook.com> Date: Sat, 15 Feb 2025 23:03:04 +0200 Subject: [PATCH 3/7] qml: use `VideoProgressBar.frag` when RHI is in use in `VideoProgressBar` This allows getting rid of the clip node. --- .../gui/qt/widgets/qml/VideoProgressBar.qml | 40 ++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/modules/gui/qt/widgets/qml/VideoProgressBar.qml b/modules/gui/qt/widgets/qml/VideoProgressBar.qml index f10918b3b32a..4dbb62c844ad 100644 --- a/modules/gui/qt/widgets/qml/VideoProgressBar.qml +++ b/modules/gui/qt/widgets/qml/VideoProgressBar.qml @@ -24,9 +24,10 @@ import VLC.Style Item { id: progressBar - implicitHeight: VLCStyle.dp(4, VLCStyle.scale) + // Shader effect needs double height, but it does not paint anything in the upper half: + implicitHeight: VLCStyle.dp(4, VLCStyle.scale) * (shaderEffect.readyForVisibility ? 2.0 : 1.0) - clip :true + clip: !shaderEffect.readyForVisibility property real value: 0 property int radius: implicitHeight @@ -36,9 +37,44 @@ Item { colorSet: ColorContext.Slider } + // WARNING: We can not override QQuickItem's antialiasing + // property as readonly because Qt 6.6 marks it + // as `FINAL`... + // FIXME: The shader can be generated without + // the define that enables antialiasing. + // It should be done when the build system + // starts supporting shader defines. + antialiasing: true + + ShaderEffect { + id: shaderEffect + + anchors.fill: parent + + antialiasing: progressBar.antialiasing + + blending: radius > 0.0 + + cullMode: ShaderEffect.BackFaceCulling + + readonly property double progress: progressBar.value + readonly property double radius: progressBar.radius / (height / 2) + readonly property size size: Qt.size(width, height) + readonly property color elapsedColor: theme.fg.primary + readonly property color remainingColor: "white" + + visible: readyForVisibility + + readonly property bool readyForVisibility: (GraphicsInfo.shaderType === GraphicsInfo.RhiShader) + + fragmentShader: "qrc:///shaders/VideoProgressBar.frag.qsb" + } + Rectangle { id: rectangle + visible: !shaderEffect.readyForVisibility + anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom -- GitLab From 99df2213c17d506b06979e2996e9d8843b162334 Mon Sep 17 00:00:00 2001 From: Fatih Uzunoglu <fuzun54@outlook.com> Date: Sun, 16 Feb 2025 16:44:56 +0200 Subject: [PATCH 4/7] qml: use `effectiveRadius` when forwarding radius to `VideoProgressBar` --- modules/gui/qt/medialibrary/qml/VideoGridItem.qml | 2 +- modules/gui/qt/network/qml/NetworkGridItem.qml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/gui/qt/medialibrary/qml/VideoGridItem.qml b/modules/gui/qt/medialibrary/qml/VideoGridItem.qml index 9730d652a629..e286fd990de5 100644 --- a/modules/gui/qt/medialibrary/qml/VideoGridItem.qml +++ b/modules/gui/qt/medialibrary/qml/VideoGridItem.qml @@ -88,7 +88,7 @@ Widgets.GridItem { visible: (model.progress > 0) - radius: root.pictureRadius + radius: root.effectiveRadius value: Helpers.clamp(model.progress !== undefined ? model.progress : 0, 0, 1) } } diff --git a/modules/gui/qt/network/qml/NetworkGridItem.qml b/modules/gui/qt/network/qml/NetworkGridItem.qml index 1e9fe8ece5d1..1837abc8d67e 100644 --- a/modules/gui/qt/network/qml/NetworkGridItem.qml +++ b/modules/gui/qt/network/qml/NetworkGridItem.qml @@ -85,7 +85,7 @@ Widgets.GridItem { visible: (model.progress ?? - 1) > 0 - radius: root.pictureRadius + radius: root.effectiveRadius value: visible ? Helpers.clamp(model.progress, 0, 1) : 0 -- GitLab From d3b31986af8537db5790164a0631756c8e1f1121 Mon Sep 17 00:00:00 2001 From: Fatih Uzunoglu <fuzun54@outlook.com> Date: Sun, 16 Feb 2025 19:42:25 +0200 Subject: [PATCH 5/7] qml: define the colors in root in `VideoProgressBar` --- modules/gui/qt/widgets/qml/VideoProgressBar.qml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/modules/gui/qt/widgets/qml/VideoProgressBar.qml b/modules/gui/qt/widgets/qml/VideoProgressBar.qml index 4dbb62c844ad..1f88d1a880de 100644 --- a/modules/gui/qt/widgets/qml/VideoProgressBar.qml +++ b/modules/gui/qt/widgets/qml/VideoProgressBar.qml @@ -32,6 +32,10 @@ Item { property real value: 0 property int radius: implicitHeight + property color elapsedColor: theme.fg.primary + //FIXME: do we want it always white or do we want it to change with the theme + property color remainingColor: "white" + readonly property ColorContext colorContext: ColorContext { id: theme colorSet: ColorContext.Slider @@ -60,8 +64,8 @@ Item { readonly property double progress: progressBar.value readonly property double radius: progressBar.radius / (height / 2) readonly property size size: Qt.size(width, height) - readonly property color elapsedColor: theme.fg.primary - readonly property color remainingColor: "white" + readonly property color elapsedColor: progressBar.elapsedColor + readonly property color remainingColor: progressBar.remainingColor visible: readyForVisibility @@ -82,13 +86,12 @@ Item { height: Math.max(progressBar.radius * 2, //to have at least the proper radius applied parent.height + radius) //the top radius section should be always clipped - //FIXME do we want it always white or do we want it to change with the theme - color: "white" + color: progressBar.remainingColor radius: progressBar.radius gradient: Gradient { orientation: Gradient.Horizontal - GradientStop { position: progressBar.value; color: theme.fg.primary } + GradientStop { position: progressBar.value; color: progressBar.elapsedColor } GradientStop { position: progressBar.value + (1. / rectangle.width); color: rectangle.color } } } -- GitLab From 3f872ef8c5fa08ef2e7d465f20282d6ed165319a Mon Sep 17 00:00:00 2001 From: Fatih Uzunoglu <fuzun54@outlook.com> Date: Sun, 16 Feb 2025 19:42:53 +0200 Subject: [PATCH 6/7] qml: use `real` instead of `int` for radius in `VideoProgressBar` --- modules/gui/qt/widgets/qml/VideoProgressBar.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/gui/qt/widgets/qml/VideoProgressBar.qml b/modules/gui/qt/widgets/qml/VideoProgressBar.qml index 1f88d1a880de..51dd9e306c3d 100644 --- a/modules/gui/qt/widgets/qml/VideoProgressBar.qml +++ b/modules/gui/qt/widgets/qml/VideoProgressBar.qml @@ -30,7 +30,7 @@ Item { clip: !shaderEffect.readyForVisibility property real value: 0 - property int radius: implicitHeight + property real radius: implicitHeight property color elapsedColor: theme.fg.primary //FIXME: do we want it always white or do we want it to change with the theme -- GitLab From c9053e15c3314de0e79050fb757299a9527d1df1 Mon Sep 17 00:00:00 2001 From: Fatih Uzunoglu <fuzun54@outlook.com> Date: Sat, 15 Feb 2025 23:03:04 +0200 Subject: [PATCH 7/7] qml: respect antialiasing in `VideoProgressBar` --- modules/gui/qt/widgets/qml/VideoProgressBar.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/gui/qt/widgets/qml/VideoProgressBar.qml b/modules/gui/qt/widgets/qml/VideoProgressBar.qml index 51dd9e306c3d..e94953cf9b33 100644 --- a/modules/gui/qt/widgets/qml/VideoProgressBar.qml +++ b/modules/gui/qt/widgets/qml/VideoProgressBar.qml @@ -89,6 +89,8 @@ Item { color: progressBar.remainingColor radius: progressBar.radius + antialiasing: progressBar.antialiasing + gradient: Gradient { orientation: Gradient.Horizontal GradientStop { position: progressBar.value; color: progressBar.elapsedColor } -- GitLab