From 0ed9afe2b4f06c32c765a96bdded9674b36ae7df Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Sat, 4 Jun 2022 17:56:14 +0200 Subject: [PATCH 1/4] QskBoxShadowNode introduced ( from playground/shadows ) - shader code migrated from glsl to vulkan-glsl - #ifdef "Geschnetzel" introduced to support old and rhi graphic APIs - iotdashboard, shadows examples adjusted --- examples/iotdashboard/LightDisplaySkinlet.cpp | 10 +- examples/iotdashboard/ShadowedBox.cpp | 18 +- examples/iotdashboard/iotdashboard.pro | 12 +- examples/iotdashboard/nodes/BoxShadowNode.cpp | 256 ------------ playground/playground.pro | 8 +- playground/shadows/BoxShadowNode.cpp | 261 ------------- playground/shadows/BoxShadowNode.h | 32 -- playground/shadows/ShadowedBox.cpp | 9 +- playground/shadows/shaders.qrc | 7 - playground/shadows/shadows.pro | 6 - src/nodes/QskBoxShadowNode.cpp | 365 ++++++++++++++++++ .../nodes/QskBoxShadowNode.h | 21 +- src/nodes/shaders.qrc | 9 + src/nodes/shaders/boxshadow-vulkan.frag | 49 +++ src/nodes/shaders/boxshadow-vulkan.vert | 24 ++ .../nodes/shaders}/boxshadow.frag | 0 src/nodes/shaders/boxshadow.frag.qsb | Bin 0 -> 2652 bytes .../nodes/shaders}/boxshadow.vert | 0 src/nodes/shaders/boxshadow.vert.qsb | Bin 0 -> 1570 bytes src/nodes/shaders/vulkan2qsb.sh | 4 + src/src.pro | 6 + 21 files changed, 483 insertions(+), 614 deletions(-) delete mode 100644 examples/iotdashboard/nodes/BoxShadowNode.cpp delete mode 100644 playground/shadows/BoxShadowNode.cpp delete mode 100644 playground/shadows/BoxShadowNode.h delete mode 100644 playground/shadows/shaders.qrc create mode 100644 src/nodes/QskBoxShadowNode.cpp rename examples/iotdashboard/nodes/BoxShadowNode.h => src/nodes/QskBoxShadowNode.h (59%) create mode 100644 src/nodes/shaders.qrc create mode 100644 src/nodes/shaders/boxshadow-vulkan.frag create mode 100644 src/nodes/shaders/boxshadow-vulkan.vert rename {playground/shadows => src/nodes/shaders}/boxshadow.frag (100%) create mode 100644 src/nodes/shaders/boxshadow.frag.qsb rename {playground/shadows => src/nodes/shaders}/boxshadow.vert (100%) create mode 100644 src/nodes/shaders/boxshadow.vert.qsb create mode 100755 src/nodes/shaders/vulkan2qsb.sh diff --git a/examples/iotdashboard/LightDisplaySkinlet.cpp b/examples/iotdashboard/LightDisplaySkinlet.cpp index e53b11b0..56b5e154 100644 --- a/examples/iotdashboard/LightDisplaySkinlet.cpp +++ b/examples/iotdashboard/LightDisplaySkinlet.cpp @@ -6,15 +6,13 @@ #include "LightDisplaySkinlet.h" #include "LightDisplay.h" -#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) - #include "nodes/BoxShadowNode.h" -#endif - #include "nodes/RadialTickmarksNode.h" #include #include #include +#include +#include #include #include @@ -144,9 +142,7 @@ QSGNode* LightDisplaySkinlet::updateSubNode( if ( grooveRect.isEmpty() ) return nullptr; - auto shadowNode = static_cast< BoxShadowNode* >( node ); - if ( shadowNode == nullptr ) - shadowNode = new BoxShadowNode(); + auto shadowNode = QskSGNode::ensureNode< QskBoxShadowNode >( node ); const auto& shadowMetrics = display->shadow(); diff --git a/examples/iotdashboard/ShadowedBox.cpp b/examples/iotdashboard/ShadowedBox.cpp index 73ab0957..80d79143 100644 --- a/examples/iotdashboard/ShadowedBox.cpp +++ b/examples/iotdashboard/ShadowedBox.cpp @@ -5,11 +5,10 @@ #include "ShadowedBox.h" -#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) - #include "nodes/BoxShadowNode.h" -#endif #include +#include +#include #include #include #include @@ -50,15 +49,12 @@ namespace switch ( nodeRole ) { -#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) case ShadowRole: { - auto shadowNode = static_cast< BoxShadowNode* >( node ); - if ( shadowNode == nullptr ) - shadowNode = new BoxShadowNode(); - const auto& shadowMetrics = box->shadow(); + auto shadowNode = QskSGNode::ensureNode< QskBoxShadowNode >( node ); + shadowNode->setRect( shadowMetrics.shadowRect( r ) ); shadowNode->setShape( box->shape() ); shadowNode->setBlurRadius( shadowMetrics.blurRadius() ); @@ -69,15 +65,11 @@ namespace return shadowNode; } -#endif case PanelRole: { - auto boxNode = static_cast< QskBoxNode* >( node ); - if ( boxNode == nullptr ) - boxNode = new QskBoxNode(); - const auto r = box->subControlRect( ShadowedBox::Panel ); + auto boxNode = QskSGNode::ensureNode< QskBoxNode >( node ); boxNode->setBoxData( r, box->shape(), box->borderWidth(), box->borderColor(), box->gradient() ); diff --git a/examples/iotdashboard/iotdashboard.pro b/examples/iotdashboard/iotdashboard.pro index cd9036e3..67a0e84e 100644 --- a/examples/iotdashboard/iotdashboard.pro +++ b/examples/iotdashboard/iotdashboard.pro @@ -64,16 +64,6 @@ HEADERS += \ nodes/DiagramSegmentsNode.h \ nodes/RadialTickmarksNode.h -lessThan(QT_MAJOR_VERSION, 6) { - - # the shader for the drop shadows has not yet been migrated - # to work with Qt 6 - - SOURCES += nodes/BoxShadowNode.cpp - HEADERS += nodes/BoxShadowNode.h -} - RESOURCES += \ images.qrc \ - fonts.qrc \ - shaders.qrc + fonts.qrc diff --git a/examples/iotdashboard/nodes/BoxShadowNode.cpp b/examples/iotdashboard/nodes/BoxShadowNode.cpp deleted file mode 100644 index db9ea9fd..00000000 --- a/examples/iotdashboard/nodes/BoxShadowNode.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) 2016 Uwe Rathmann - * This file may be used under the terms of the 3-clause BSD License - *****************************************************************************/ - -#include "BoxShadowNode.h" -#include "QskBoxShapeMetrics.h" - -#include -#include -#include - -#include - -namespace -{ - class Shader final : public QSGMaterialShader - { - public: - Shader(); - - char const* const* attributeNames() const override; - - void initialize() override; - - void updateState( const QSGMaterialShader::RenderState& state, - QSGMaterial* newMaterial, QSGMaterial* oldMaterial) override; - - private: - int m_matrixId = -1; - int m_opacityId = -1; - int m_aspectId = -1; - int m_blurExtentId = -1; - int m_radiusId = -1; - int m_colorId = -1; - }; - - class Material final : public QSGMaterial - { - public: - Material(); - - QSGMaterialShader* createShader() const override; - - QSGMaterialType* type() const override; - - int compare( const QSGMaterial* other ) const override; - - QVector2D aspect = QVector2D{ 1.0, 1.0 }; - float blurExtent = 0.0; - QVector4D radius = QVector4D{ 0.0, 0.0, 0.0, 0.0 }; - QColor color = Qt::black; - }; - - Shader::Shader() - { - const QString root( ":/iotdashboard/shaders/" ); - - setShaderSourceFile( QOpenGLShader::Vertex, root + "boxshadow.vert" ); - setShaderSourceFile( QOpenGLShader::Fragment, root + "boxshadow.frag" ); - } - - char const* const* Shader::attributeNames() const - { - static char const* const names[] = { "in_vertex", "in_coord", nullptr }; - return names; - } - - void Shader::initialize() - { - QSGMaterialShader::initialize(); - - auto p = program(); - - m_matrixId = p->uniformLocation( "matrix" ); - m_aspectId = p->uniformLocation( "aspect" ); - m_opacityId = p->uniformLocation( "opacity" ); - m_blurExtentId = p->uniformLocation( "blurExtent" ); - m_radiusId = p->uniformLocation( "radius" ); - m_colorId = p->uniformLocation( "color" ); - } - - void Shader::updateState( const QSGMaterialShader::RenderState& state, - QSGMaterial* newMaterial, QSGMaterial* oldMaterial ) - { - auto p = program(); - - if ( state.isMatrixDirty() ) - p->setUniformValue( m_matrixId, state.combinedMatrix() ); - - if ( state.isOpacityDirty() ) - p->setUniformValue( m_opacityId, state.opacity() ); - - if ( oldMaterial == nullptr || newMaterial->compare( oldMaterial ) != 0 ) - { - auto material = static_cast< const Material* >( newMaterial ); - - p->setUniformValue( m_aspectId, material->aspect ); - p->setUniformValue( m_blurExtentId, material->blurExtent); - p->setUniformValue( m_radiusId, material->radius ); - p->setUniformValue( m_colorId, material->color ); - } - } - - Material::Material() - { - setFlag( QSGMaterial::Blending, true ); - } - - QSGMaterialShader* Material::createShader() const - { - return new Shader(); - } - - QSGMaterialType* Material::type() const - { - static QSGMaterialType staticType; - return &staticType; - } - - int Material::compare( const QSGMaterial* other ) const - { - auto material = static_cast< const Material* >( other ); - - if ( material->color == color - && material->aspect == aspect - && qFuzzyCompare(material->blurExtent, blurExtent) - && qFuzzyCompare(material->radius, radius) ) - { - return 0; - } - - return QSGMaterial::compare(other); - } -} - -class BoxShadowNodePrivate final : public QSGGeometryNodePrivate -{ - public: - BoxShadowNodePrivate() - : geometry( QSGGeometry::defaultAttributes_TexturedPoint2D(), 4 ) - { - } - - QSGGeometry geometry; - Material material; - - QRectF rect; -}; - -BoxShadowNode::BoxShadowNode() - : QSGGeometryNode( *new BoxShadowNodePrivate ) -{ - Q_D( BoxShadowNode ); - - setGeometry( &d->geometry ); - setMaterial( &d->material ); -} - -BoxShadowNode::~BoxShadowNode() -{ -} - -void BoxShadowNode::setRect( const QRectF& rect ) -{ - Q_D( BoxShadowNode ); - - if ( rect == d->rect ) - return; - - d->rect = rect; - - QVector2D aspect( 1.0, 1.0 ); - - if ( rect.width() >= rect.height() ) - aspect.setX( rect.width() / rect.height() ); - else - aspect.setY( rect.height() / rect.width() ); - - if ( d->material.aspect != aspect ) - { - d->material.aspect = aspect; - markDirty( QSGNode::DirtyMaterial ); - } -} - -void BoxShadowNode::setShape( const QskBoxShapeMetrics& shape ) -{ - Q_D( BoxShadowNode ); - - const float t = std::min( d->rect.width(), d->rect.height() ); - - const float r1 = shape.radius( Qt::BottomRightCorner ).width(); - const float r2 = shape.radius( Qt::TopRightCorner ).width(); - const float r3 = shape.radius( Qt::BottomLeftCorner ).width(); - const float r4 = shape.radius( Qt::TopLeftCorner ).width(); - - const auto uniformRadius = QVector4D( - std::min( r1 / t, 1.0f ), std::min( r2 / t, 1.0f ), - std::min( r3 / t, 1.0f ), std::min( r4 / t, 1.0f ) ); - - if ( d->material.radius != uniformRadius ) - { - d->material.radius = uniformRadius; - - markDirty( QSGNode::DirtyMaterial ); - } -} - -void BoxShadowNode::setColor( const QColor& color ) -{ - Q_D( BoxShadowNode ); - - const auto a = color.alphaF(); - - const auto c = QColor::fromRgbF( - color.redF() * a, color.greenF() * a, color.blueF() * a, a ); - - if ( d->material.color != c ) - { - d->material.color = c; - markDirty( QSGNode::DirtyMaterial ); - } -} - -void BoxShadowNode::setBlurRadius( qreal blurRadius ) -{ - Q_D( BoxShadowNode ); - - if ( blurRadius <= 0.0 ) - blurRadius = 0.0; - - const float t = 0.5 * std::min( d->rect.width(), d->rect.height() ); - const float uniformExtent = blurRadius / t; - - if ( !qFuzzyCompare( d->material.blurExtent, uniformExtent ) ) - { - d->material.blurExtent = uniformExtent; - markDirty( QSGNode::DirtyMaterial ); - } -} - -void BoxShadowNode::setClipRect( const QRectF& rect ) -{ - Q_UNUSED( rect ) -} - -void BoxShadowNode::updateGeometry() -{ - Q_D( BoxShadowNode ); - - QSGGeometry::updateTexturedRectGeometry( - &d->geometry, d->rect, QRectF( -0.5, -0.5, 1.0, 1.0 ) ); - - markDirty( QSGNode::DirtyGeometry ); -} diff --git a/playground/playground.pro b/playground/playground.pro index 86fa8c0c..3f0b5271 100644 --- a/playground/playground.pro +++ b/playground/playground.pro @@ -7,13 +7,7 @@ SUBDIRS += \ inputpanel \ images -lessThan(QT_MAJOR_VERSION, 6) { - - # the shader for the drop shadows has not yet been migrated - # to work with Qt 6 - - SUBDIRS += shadows -} +SUBDIRS += shadows qtHaveModule(webengine) { diff --git a/playground/shadows/BoxShadowNode.cpp b/playground/shadows/BoxShadowNode.cpp deleted file mode 100644 index 5cd25712..00000000 --- a/playground/shadows/BoxShadowNode.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) 2016 Uwe Rathmann - * This file may be used under the terms of the 3-clause BSD License - *****************************************************************************/ - -#include "BoxShadowNode.h" -#include "QskBoxShapeMetrics.h" - -#include -#include -#include - -#include - -namespace -{ - class Shader final : public QSGMaterialShader - { - public: - Shader(); - - char const* const* attributeNames() const override; - - void initialize() override; - - void updateState( const QSGMaterialShader::RenderState& state, - QSGMaterial* newMaterial, QSGMaterial* oldMaterial) override; - - private: - int m_matrixId = -1; - int m_opacityId = -1; - int m_aspectId = -1; - int m_blurExtentId = -1; - int m_radiusId = -1; - int m_colorId = -1; - }; - - class Material final : public QSGMaterial - { - public: - Material(); - - QSGMaterialShader* createShader() const override; - - QSGMaterialType* type() const override; - - int compare( const QSGMaterial* other ) const override; - - QVector2D aspect = QVector2D{ 1.0, 1.0 }; - float blurExtent = 0.0; - QVector4D radius = QVector4D{ 0.0, 0.0, 0.0, 0.0 }; - QColor color = Qt::black; - }; - - Shader::Shader() - { - const QString root( ":/qskinny/shaders/" ); - - setShaderSourceFile( QOpenGLShader::Vertex, root + "boxshadow.vert" ); - setShaderSourceFile( QOpenGLShader::Fragment, root + "boxshadow.frag" ); - } - - char const* const* Shader::attributeNames() const - { - static char const* const names[] = { "in_vertex", "in_coord", nullptr }; - return names; - } - - void Shader::initialize() - { - QSGMaterialShader::initialize(); - - auto p = program(); - - m_matrixId = p->uniformLocation( "matrix" ); - m_aspectId = p->uniformLocation( "aspect" ); - m_opacityId = p->uniformLocation( "opacity" ); - m_blurExtentId = p->uniformLocation( "blurExtent" ); - m_radiusId = p->uniformLocation( "radius" ); - m_colorId = p->uniformLocation( "color" ); - } - - void Shader::updateState( const QSGMaterialShader::RenderState& state, - QSGMaterial* newMaterial, QSGMaterial* oldMaterial ) - { - auto p = program(); - - if ( state.isMatrixDirty() ) - p->setUniformValue( m_matrixId, state.combinedMatrix() ); - - if ( state.isOpacityDirty() ) - p->setUniformValue( m_opacityId, state.opacity() ); - - bool updateMaterial = ( oldMaterial == nullptr ) - || newMaterial->compare( oldMaterial ) != 0; - - updateMaterial |= state.isCachedMaterialDataDirty(); - - if ( updateMaterial ) - { - auto material = static_cast< const Material* >( newMaterial ); - - p->setUniformValue( m_aspectId, material->aspect ); - p->setUniformValue( m_blurExtentId, material->blurExtent); - p->setUniformValue( m_radiusId, material->radius ); - p->setUniformValue( m_colorId, material->color ); - } - } - - Material::Material() - { - setFlag( QSGMaterial::Blending, true ); - } - - QSGMaterialShader* Material::createShader() const - { - return new Shader(); - } - - QSGMaterialType* Material::type() const - { - static QSGMaterialType staticType; - return &staticType; - } - - int Material::compare( const QSGMaterial* other ) const - { - auto material = static_cast< const Material* >( other ); - - if ( material->color == color - && material->aspect == aspect - && qFuzzyCompare(material->blurExtent, blurExtent) - && qFuzzyCompare(material->radius, radius) ) - { - return 0; - } - - return QSGMaterial::compare(other); - } -} - -class BoxShadowNodePrivate final : public QSGGeometryNodePrivate -{ - public: - BoxShadowNodePrivate() - : geometry( QSGGeometry::defaultAttributes_TexturedPoint2D(), 4 ) - { - } - - QSGGeometry geometry; - Material material; - - QRectF rect; -}; - -BoxShadowNode::BoxShadowNode() - : QSGGeometryNode( *new BoxShadowNodePrivate ) -{ - Q_D( BoxShadowNode ); - - setGeometry( &d->geometry ); - setMaterial( &d->material ); -} - -BoxShadowNode::~BoxShadowNode() -{ -} - -void BoxShadowNode::setRect( const QRectF& rect ) -{ - Q_D( BoxShadowNode ); - - if ( rect == d->rect ) - return; - - d->rect = rect; - - QVector2D aspect( 1.0, 1.0 ); - - if ( rect.width() >= rect.height() ) - aspect.setX( rect.width() / rect.height() ); - else - aspect.setY( rect.height() / rect.width() ); - - if ( d->material.aspect != aspect ) - { - d->material.aspect = aspect; - markDirty( QSGNode::DirtyMaterial ); - } -} - -void BoxShadowNode::setShape( const QskBoxShapeMetrics& shape ) -{ - Q_D( BoxShadowNode ); - - const float t = std::min( d->rect.width(), d->rect.height() ); - - const float r1 = shape.radius( Qt::BottomRightCorner ).width(); - const float r2 = shape.radius( Qt::TopRightCorner ).width(); - const float r3 = shape.radius( Qt::BottomLeftCorner ).width(); - const float r4 = shape.radius( Qt::TopLeftCorner ).width(); - - const auto uniformRadius = QVector4D( - std::min( r1 / t, 1.0f ), std::min( r2 / t, 1.0f ), - std::min( r3 / t, 1.0f ), std::min( r4 / t, 1.0f ) ); - - if ( d->material.radius != uniformRadius ) - { - d->material.radius = uniformRadius; - - markDirty( QSGNode::DirtyMaterial ); - } -} - -void BoxShadowNode::setColor( const QColor& color ) -{ - Q_D( BoxShadowNode ); - - const auto a = color.alphaF(); - - const auto c = QColor::fromRgbF( - color.redF() * a, color.greenF() * a, color.blueF() * a, a ); - - if ( d->material.color != c ) - { - d->material.color = c; - markDirty( QSGNode::DirtyMaterial ); - } -} - -void BoxShadowNode::setBlurRadius( qreal blurRadius ) -{ - Q_D( BoxShadowNode ); - - if ( blurRadius <= 0.0 ) - blurRadius = 0.0; - - const float t = 0.5 * std::min( d->rect.width(), d->rect.height() ); - const float uniformExtent = blurRadius / t; - - if ( !qFuzzyCompare( d->material.blurExtent, uniformExtent ) ) - { - d->material.blurExtent = uniformExtent; - markDirty( QSGNode::DirtyMaterial ); - } -} - -void BoxShadowNode::setClipRect( const QRectF& rect ) -{ - Q_UNUSED( rect ) -} - -void BoxShadowNode::updateGeometry() -{ - Q_D( BoxShadowNode ); - - QSGGeometry::updateTexturedRectGeometry( - &d->geometry, d->rect, QRectF( -0.5, -0.5, 1.0, 1.0 ) ); - - markDirty( QSGNode::DirtyGeometry ); -} diff --git a/playground/shadows/BoxShadowNode.h b/playground/shadows/BoxShadowNode.h deleted file mode 100644 index bd84a5eb..00000000 --- a/playground/shadows/BoxShadowNode.h +++ /dev/null @@ -1,32 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) 2016 Uwe Rathmann - * This file may be used under the terms of the 3-clause BSD License - *****************************************************************************/ - -#pragma once - -#include - -class QColor; -class QskBoxShapeMetrics; - -class BoxShadowNodePrivate; - -class BoxShadowNode : public QSGGeometryNode -{ - public: - BoxShadowNode(); - ~BoxShadowNode() override; - - void setRect( const QRectF& ); - void setShape( const QskBoxShapeMetrics& ); - void setColor( const QColor& ); - void setBlurRadius( qreal ); - - void setClipRect( const QRectF& ); - - void updateGeometry(); - - private: - Q_DECLARE_PRIVATE( BoxShadowNode ) -}; diff --git a/playground/shadows/ShadowedBox.cpp b/playground/shadows/ShadowedBox.cpp index a9b9a8cc..ded28d06 100644 --- a/playground/shadows/ShadowedBox.cpp +++ b/playground/shadows/ShadowedBox.cpp @@ -4,9 +4,10 @@ *****************************************************************************/ #include "ShadowedBox.h" -#include "BoxShadowNode.h" #include +#include +#include #include #include #include @@ -49,12 +50,10 @@ namespace { case ShadowRole: { - auto shadowNode = static_cast< BoxShadowNode* >( node ); - if ( shadowNode == nullptr ) - shadowNode = new BoxShadowNode(); - const auto& shadowMetrics = box->shadow(); + auto shadowNode = QskSGNode::ensureNode< QskBoxShadowNode >( node ); + shadowNode->setRect( shadowMetrics.shadowRect( r ) ); shadowNode->setShape( box->shape() ); shadowNode->setBlurRadius( shadowMetrics.blurRadius() ); diff --git a/playground/shadows/shaders.qrc b/playground/shadows/shaders.qrc deleted file mode 100644 index 05ff312f..00000000 --- a/playground/shadows/shaders.qrc +++ /dev/null @@ -1,7 +0,0 @@ - - - - boxshadow.vert - boxshadow.frag - - diff --git a/playground/shadows/shadows.pro b/playground/shadows/shadows.pro index 0f7d9ea4..2d7ca870 100644 --- a/playground/shadows/shadows.pro +++ b/playground/shadows/shadows.pro @@ -1,14 +1,8 @@ CONFIG += qskexample -QT += quick_private - -RESOURCES += \ - shaders.qrc HEADERS += \ ShadowedBox.h \ - BoxShadowNode.h SOURCES += \ ShadowedBox.cpp \ - BoxShadowNode.cpp \ main.cpp diff --git a/src/nodes/QskBoxShadowNode.cpp b/src/nodes/QskBoxShadowNode.cpp new file mode 100644 index 00000000..94e0af65 --- /dev/null +++ b/src/nodes/QskBoxShadowNode.cpp @@ -0,0 +1,365 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * This file may be used under the terms of the QSkinny License, Version 1.0 + *****************************************************************************/ + +#include "QskBoxShadowNode.h" +#include "QskBoxShapeMetrics.h" + +#include +#include +#include + +QSK_QT_PRIVATE_BEGIN +#include +QSK_QT_PRIVATE_END + +// QSGMaterialRhiShader became QSGMaterialShader in Qt6 + +#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) + #include + using RhiShader = QSGMaterialRhiShader; +#else + using RhiShader = QSGMaterialShader; +#endif + +namespace +{ + class Material final : public QSGMaterial + { + public: + Material(); + +#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) + QSGMaterialShader* createShader() const override; +#else + QSGMaterialShader* createShader( QSGRendererInterface::RenderMode ) const override; +#endif + + QSGMaterialType* type() const override; + + int compare( const QSGMaterial* other ) const override; + + QVector2D m_aspect = QVector2D{ 1, 1 }; + QVector4D m_radius = QVector4D{ 0, 0, 0, 0 }; + QVector4D m_color = QVector4D{ 0, 0, 0, 1 }; + float m_blurExtent = 0.0; + }; +} + +namespace +{ + class ShaderRhi final : public RhiShader + { + public: + ShaderRhi() + { + const QString root( ":/qskinny/shaders/" ); + + setShaderFileName( VertexStage, root + "boxshadow.vert.qsb" ); + setShaderFileName( FragmentStage, root + "boxshadow.frag.qsb" ); + } + + bool updateUniformData( RenderState& state, + QSGMaterial* newMaterial, QSGMaterial* oldMaterial ) override + { + const auto matOld = static_cast< Material* >( oldMaterial ); + const auto matNew = static_cast< Material* >( newMaterial ); + + Q_ASSERT( state.uniformData()->size() >= 112 ); + + auto data = state.uniformData()->data(); + bool changed = false; + + if ( state.isMatrixDirty() ) + { + const auto matrix = state.combinedMatrix(); + memcpy( data + 0, matrix.constData(), 64 ); + + changed = true; + } + + if ( matOld == nullptr || matNew->m_color != matOld->m_color ) + { + memcpy( data + 64, &matNew->m_color, 16 ); + changed = true; + } + + if ( matOld == nullptr || matNew->m_radius != matOld->m_radius ) + { + memcpy( data + 80, &matNew->m_radius, 16 ); + changed = true; + } + + if ( matOld == nullptr || matNew->m_aspect != matOld->m_aspect ) + { + memcpy( data + 96, &matNew->m_aspect, 8 ); + changed = true; + } + + if ( matOld == nullptr || matNew->m_blurExtent != matOld->m_blurExtent ) + { + memcpy( data + 104, &matNew->m_blurExtent, 4 ); + changed = true; + } + + if ( state.isOpacityDirty() ) + { + const float opacity = state.opacity(); + memcpy( data + 108, &opacity, 4 ); + + changed = true; + } + + return changed; + } + }; +} + +#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) + +namespace +{ + // the old type of shader - spcific for OpenGL + + class ShaderGL final : public QSGMaterialShader + { + public: + ShaderGL() + { + const QString root( ":/qskinny/shaders/" ); + + setShaderSourceFile( QOpenGLShader::Vertex, root + "boxshadow.vert" ); + setShaderSourceFile( QOpenGLShader::Fragment, root + "boxshadow.frag" ); + } + + char const* const* attributeNames() const override + { + static char const* const names[] = { "in_vertex", "in_coord", nullptr }; + return names; + } + + void initialize() override + { + QSGMaterialShader::initialize(); + + auto p = program(); + + m_matrixId = p->uniformLocation( "matrix" ); + m_aspectId = p->uniformLocation( "aspect" ); + m_opacityId = p->uniformLocation( "opacity" ); + m_blurExtentId = p->uniformLocation( "blurExtent" ); + m_radiusId = p->uniformLocation( "radius" ); + m_colorId = p->uniformLocation( "color" ); + } + + void updateState( const QSGMaterialShader::RenderState& state, + QSGMaterial* newMaterial, QSGMaterial* oldMaterial) override + { + auto p = program(); + + if ( state.isMatrixDirty() ) + p->setUniformValue( m_matrixId, state.combinedMatrix() ); + + if ( state.isOpacityDirty() ) + p->setUniformValue( m_opacityId, state.opacity() ); + + bool updateMaterial = ( oldMaterial == nullptr ) + || newMaterial->compare( oldMaterial ) != 0; + + updateMaterial |= state.isCachedMaterialDataDirty(); + + if ( updateMaterial ) + { + auto material = static_cast< const Material* >( newMaterial ); + + p->setUniformValue( m_aspectId, material->m_aspect ); + p->setUniformValue( m_blurExtentId, material->m_blurExtent); + p->setUniformValue( m_radiusId, material->m_radius ); + p->setUniformValue( m_colorId, material->m_color ); + } + } + + private: + int m_matrixId = -1; + int m_opacityId = -1; + int m_aspectId = -1; + int m_blurExtentId = -1; + int m_radiusId = -1; + int m_colorId = -1; + }; +} + +#endif + +Material::Material() +{ + setFlag( QSGMaterial::Blending, true ); + +#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) + setFlag( QSGMaterial::SupportsRhiShader, true ); +#endif +} + +#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) + +QSGMaterialShader* Material::createShader() const +{ + if ( !( flags() & QSGMaterial::RhiShaderWanted ) ) + return new ShaderGL(); + + return new ShaderRhi(); +} + +#else + +QSGMaterialShader* Material::createShader( QSGRendererInterface::RenderMode ) const +{ + return new ShaderRhi(); +} + +#endif + +QSGMaterialType* Material::type() const +{ + static QSGMaterialType staticType; + return &staticType; +} + +int Material::compare( const QSGMaterial* other ) const +{ + auto material = static_cast< const Material* >( other ); + + if ( material->m_color != m_color + || material->m_aspect != m_aspect + || !qFuzzyCompare(material->m_blurExtent, m_blurExtent) + || !qFuzzyCompare(material->m_radius, m_radius) ) + { + return 1; + } + + return QSGMaterial::compare( other ); +} + +class QskBoxShadowNodePrivate final : public QSGGeometryNodePrivate +{ + public: + QskBoxShadowNodePrivate() + : geometry( QSGGeometry::defaultAttributes_TexturedPoint2D(), 4 ) + { + } + + QSGGeometry geometry; + Material material; + + QRectF rect; +}; + +QskBoxShadowNode::QskBoxShadowNode() + : QSGGeometryNode( *new QskBoxShadowNodePrivate ) +{ + Q_D( QskBoxShadowNode ); + + setGeometry( &d->geometry ); + setMaterial( &d->material ); +} + +QskBoxShadowNode::~QskBoxShadowNode() +{ +} + +void QskBoxShadowNode::setRect( const QRectF& rect ) +{ + Q_D( QskBoxShadowNode ); + + if ( rect == d->rect ) + return; + + d->rect = rect; + + QVector2D aspect( 1.0, 1.0 ); + + if ( rect.width() >= rect.height() ) + aspect.setX( rect.width() / rect.height() ); + else + aspect.setY( rect.height() / rect.width() ); + + if ( d->material.m_aspect != aspect ) + { + d->material.m_aspect = aspect; + markDirty( QSGNode::DirtyMaterial ); + } +} + +void QskBoxShadowNode::setShape( const QskBoxShapeMetrics& shape ) +{ + Q_D( QskBoxShadowNode ); + + const float t = std::min( d->rect.width(), d->rect.height() ); + + const float r1 = shape.radius( Qt::BottomRightCorner ).width(); + const float r2 = shape.radius( Qt::TopRightCorner ).width(); + const float r3 = shape.radius( Qt::BottomLeftCorner ).width(); + const float r4 = shape.radius( Qt::TopLeftCorner ).width(); + + const auto uniformRadius = QVector4D( + std::min( r1 / t, 1.0f ), std::min( r2 / t, 1.0f ), + std::min( r3 / t, 1.0f ), std::min( r4 / t, 1.0f ) ); + + if ( d->material.m_radius != uniformRadius ) + { + d->material.m_radius = uniformRadius; + + markDirty( QSGNode::DirtyMaterial ); + } +} + +void QskBoxShadowNode::setColor( const QColor& color ) +{ + Q_D( QskBoxShadowNode ); + + const auto a = color.alphaF(); + + const QVector4D c( color.redF() * a, color.greenF() * a, color.blueF() * a, a ); + + if ( d->material.m_color != c ) + { + d->material.m_color = c; + markDirty( QSGNode::DirtyMaterial ); + } +} + +void QskBoxShadowNode::setBlurRadius( qreal blurRadius ) +{ + Q_D( QskBoxShadowNode ); + + if ( blurRadius <= 0.0 ) + blurRadius = 0.0; + + const float t = 0.5 * std::min( d->rect.width(), d->rect.height() ); + const float uniformExtent = blurRadius / t; + + if ( !qFuzzyCompare( d->material.m_blurExtent, uniformExtent ) ) + { + d->material.m_blurExtent = uniformExtent; + markDirty( QSGNode::DirtyMaterial ); + } +} + +void QskBoxShadowNode::setClipRect( const QRectF& ) +{ + /* + Usually only the parts, that are not covered by the related rectangle + should be painted. TODO ... + */ +} + +void QskBoxShadowNode::updateGeometry() +{ + Q_D( QskBoxShadowNode ); + + QSGGeometry::updateTexturedRectGeometry( + &d->geometry, d->rect, QRectF( -0.5, -0.5, 1.0, 1.0 ) ); + + markDirty( QSGNode::DirtyGeometry ); +} diff --git a/examples/iotdashboard/nodes/BoxShadowNode.h b/src/nodes/QskBoxShadowNode.h similarity index 59% rename from examples/iotdashboard/nodes/BoxShadowNode.h rename to src/nodes/QskBoxShadowNode.h index bd84a5eb..e3af8aa3 100644 --- a/examples/iotdashboard/nodes/BoxShadowNode.h +++ b/src/nodes/QskBoxShadowNode.h @@ -1,32 +1,35 @@ /****************************************************************************** * QSkinny - Copyright (C) 2016 Uwe Rathmann - * This file may be used under the terms of the 3-clause BSD License + * This file may be used under the terms of the QSkinny License, Version 1.0 *****************************************************************************/ -#pragma once +#ifndef QSK_BOX_SHADOW_NODE_H +#define QSK_BOX_SHADOW_NODE_H +#include "QskGlobal.h" #include class QColor; class QskBoxShapeMetrics; -class BoxShadowNodePrivate; +class QskBoxShadowNodePrivate; -class BoxShadowNode : public QSGGeometryNode +class QSK_EXPORT QskBoxShadowNode : public QSGGeometryNode { public: - BoxShadowNode(); - ~BoxShadowNode() override; + QskBoxShadowNode(); + ~QskBoxShadowNode() override; void setRect( const QRectF& ); void setShape( const QskBoxShapeMetrics& ); void setColor( const QColor& ); void setBlurRadius( qreal ); + void updateGeometry(); void setClipRect( const QRectF& ); - void updateGeometry(); - private: - Q_DECLARE_PRIVATE( BoxShadowNode ) + Q_DECLARE_PRIVATE( QskBoxShadowNode ) }; + +#endif diff --git a/src/nodes/shaders.qrc b/src/nodes/shaders.qrc new file mode 100644 index 00000000..dab52798 --- /dev/null +++ b/src/nodes/shaders.qrc @@ -0,0 +1,9 @@ + + + + shaders/boxshadow.vert.qsb + shaders/boxshadow.frag.qsb + shaders/boxshadow.vert + shaders/boxshadow.frag + + diff --git a/src/nodes/shaders/boxshadow-vulkan.frag b/src/nodes/shaders/boxshadow-vulkan.frag new file mode 100644 index 00000000..06a8df1a --- /dev/null +++ b/src/nodes/shaders/boxshadow-vulkan.frag @@ -0,0 +1,49 @@ +#version 440 + +layout(location = 0) in vec2 coord; +layout(location = 0) out vec4 fragColor; + +layout(std140, binding = 0) uniform buf +{ + mat4 matrix; + vec4 color; + vec4 radius; + vec2 aspect; + float blurExtent; + float opacity; +} ubuf; + +float effectiveRadius( in vec4 radii, in vec2 point ) +{ + if ( point.x > 0.0 ) + return ( point.y > 0.0) ? radii.x : radii.y; + else + return ( point.y > 0.0) ? radii.z : radii.w; +} + +void main() +{ + vec4 col = vec4(0.0); + + if ( ubuf.opacity > 0.0 ) + { + const float minRadius = 0.05; + + float e2 = 0.5 * ubuf.blurExtent; + float r = 2.0 * effectiveRadius( ubuf.radius, coord ); + + float f = minRadius / max( r, minRadius ); + + r += e2 * f; + + vec2 d = r + ubuf.blurExtent - ubuf.aspect * ( 1.0 - abs( 2.0 * coord ) ); + float l = min( max(d.x, d.y), 0.0) + length( max(d, 0.0) ); + + float shadow = l - r; + + float v = smoothstep( -e2, e2, shadow ); + col = mix( ubuf.color, vec4(0.0), v ) * ubuf.opacity; + } + + fragColor = col; +} diff --git a/src/nodes/shaders/boxshadow-vulkan.vert b/src/nodes/shaders/boxshadow-vulkan.vert new file mode 100644 index 00000000..1d802d81 --- /dev/null +++ b/src/nodes/shaders/boxshadow-vulkan.vert @@ -0,0 +1,24 @@ +#version 440 + +layout(location = 0) in vec4 in_vertex; +layout(location = 1) in vec2 in_coord; + +layout(location = 0) out vec2 coord; + +layout(std140, binding = 0) uniform buf +{ + mat4 matrix; + vec4 color; + vec4 radius; + vec2 aspect; + float blurExtent; + float opacity; +} ubuf; + +out gl_PerVertex { vec4 gl_Position; }; + +void main() +{ + coord = in_coord; + gl_Position = ubuf.matrix * in_vertex; +} diff --git a/playground/shadows/boxshadow.frag b/src/nodes/shaders/boxshadow.frag similarity index 100% rename from playground/shadows/boxshadow.frag rename to src/nodes/shaders/boxshadow.frag diff --git a/src/nodes/shaders/boxshadow.frag.qsb b/src/nodes/shaders/boxshadow.frag.qsb new file mode 100644 index 0000000000000000000000000000000000000000..088e7513075afd383e6a572ca77e100fa3da6ee4 GIT binary patch literal 2652 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 Kr~Kb$xenv86?=35 literal 0 HcmV?d00001 diff --git a/playground/shadows/boxshadow.vert b/src/nodes/shaders/boxshadow.vert similarity index 100% rename from playground/shadows/boxshadow.vert rename to src/nodes/shaders/boxshadow.vert diff --git a/src/nodes/shaders/boxshadow.vert.qsb b/src/nodes/shaders/boxshadow.vert.qsb new file mode 100644 index 0000000000000000000000000000000000000000..ae721f89d4deb12b516f3d2c5fedd3c81e252f39 GIT binary patch literal 1570 zcmV+-2Hp7p03kMbob6hBPuxZjU+#{Vc_k1?Thhb{DY+xj^+1qBrJzI!Y9mDgg(|9q zsAGISaO<-#egsH_R8{H+=s*2B{RsU!{ikYYc4yCP`;L~XsDxro9fYty!WxJ)I`rsaBO=f~60r-Gc4-xN?g1aOe!T^_>ARK(8 zvej!CAST%9fZmY68{NSsfLag+3rrENz2b&kCrt}3nMdfENSwtYi#(T z6FI)OoMJ8LmhT7kEYb0d4)jH&zp;bJK3GN#K@5&g)5SEDJmE}4T zGFOy9AXSyMqBmo=+;;Dty3TMCG%atp&UNG>rbCc-ZNtH~G@u=o6_r~}+mi%0hmzBT zFvUGV=wO)`?(>cSsg!Ek^VD+6VWr)Qp@AL6ftOKoq~X4RcF{g@K<_!Udw!S!t3y;b zzffy01qd<4r-^ebqAi`Y7IpsiDt+;mwh0TmcpKH%DS7WyD!pG~jl`bQ@Pj7bb#Rt( z*_gqhluiwn<)ajX-o!Z6h{MWO?Xm;q`DbC?eT&jtqyC?;)F{bf09@&W){Bskf&C%sqns}x-y0>~ zP#aU^v;yasAkPq2FX3f>hMp>|pY%&w58)muv;xsK6k3sJuM}E|XnP8+muN28DdnMG zQ}Dc{_&G%}kp1aQ9Bxt{ZJq!r1&%LrTd+L^EzAscxUT{paec(op+7)&BYm0rgG58V zM*d5_MltRoc_SpR#O)93?E~mfkSrm4fX7MF zM#!c4UG`E`Z#O>+MeU$0Vog8Cnk?h(Rcf0}5>zfQJFf26H_gx6_qddQy{@`sT> z*uSmB@)K(JDf|lAbRSklfh7qn;(h}Pu9X#{}>QgdAx+Ll)yllW^Qla1J6C^dVGRr`Pl{lQK4}YEA4DRO2m6be|IFz@|9%K@iMuspUXP4 zhi5j;&5Yn@D4^71Gz-~JrKi5gN^vLc0_T@lD}$cXRbiKqjW=_)Ea)#+0$7e#Z*qd$oSoiF&g7eUP`0tKTnb_oT1Z z?iaQC>DB6Iy_Wuq+7>-GE^6DeQ`?@0s`YQyp7_<>Ifu0;kk0nU^%Bed9a<(o;{O6z UuEfppGn>e<{M`6I0rl6eQ3;9`g#Z8m literal 0 HcmV?d00001 diff --git a/src/nodes/shaders/vulkan2qsb.sh b/src/nodes/shaders/vulkan2qsb.sh new file mode 100755 index 00000000..032a238d --- /dev/null +++ b/src/nodes/shaders/vulkan2qsb.sh @@ -0,0 +1,4 @@ +#! /bin/sh + +qsb --glsl 100es,120,150 --hlsl 50 --msl 12 -b -o boxshadow.vert.qsb boxshadow-vulkan.vert +qsb --glsl 100es,120,150 --hlsl 50 --msl 12 -b -o boxshadow.frag.qsb boxshadow-vulkan.frag diff --git a/src/src.pro b/src/src.pro index 56a98910..904bf604 100644 --- a/src/src.pro +++ b/src/src.pro @@ -103,6 +103,7 @@ HEADERS += \ nodes/QskBoxClipNode.h \ nodes/QskBoxRenderer.h \ nodes/QskBoxRendererColorMap.h \ + nodes/QskBoxShadowNode.h \ nodes/QskGraphicNode.h \ nodes/QskPaintedNode.h \ nodes/QskPlainTextRenderer.h \ @@ -123,6 +124,7 @@ SOURCES += \ nodes/QskBoxRendererRect.cpp \ nodes/QskBoxRendererEllipse.cpp \ nodes/QskBoxRendererDEllipse.cpp \ + nodes/QskBoxShadowNode.cpp \ nodes/QskGraphicNode.cpp \ nodes/QskPaintedNode.cpp \ nodes/QskPlainTextRenderer.cpp \ @@ -135,6 +137,9 @@ SOURCES += \ nodes/QskTickmarksNode.cpp \ nodes/QskVertex.cpp +RESOURCES += \ + nodes/shaders.qrc + HEADERS += \ controls/QskAbstractButton.h \ controls/QskAnimationHint.h \ @@ -364,6 +369,7 @@ SOURCES += \ inputpanel/QskInputPredictionBar.cpp \ inputpanel/QskVirtualKeyboard.cpp + pinyin { unix { From e954fb8aa1afc19f764e64f21801018a0f7f43cc Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Mon, 6 Jun 2022 07:06:07 +0200 Subject: [PATCH 2/4] CI: Use the native backends on Windows also for Qt 6 (#194) Resolves #164 --- .github/workflows/qmake.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/qmake.yml b/.github/workflows/qmake.yml index 12a9048c..8308be14 100644 --- a/.github/workflows/qmake.yml +++ b/.github/workflows/qmake.yml @@ -244,8 +244,6 @@ jobs: build-windows-qt-lts: name: Windows Qt 6.2 (LTS) build runs-on: windows-latest - env: - QSG_RHI_BACKEND: opengl steps: - uses: actions/checkout@v2 - name: Cache Qt @@ -301,8 +299,6 @@ jobs: build-windows-qt-current: name: Windows Qt 6.3 (current) build runs-on: windows-latest - env: - QSG_RHI_BACKEND: opengl steps: - uses: actions/checkout@v2 - name: Cache Qt From 167965e12c671b81ef347396f86e15b4208cfde4 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Mon, 6 Jun 2022 07:08:33 +0200 Subject: [PATCH 3/4] switch button: Fix size hint (#195) This fixes a case where the Groove is bigger than the Handle, e.g. with the Material 3 switch buttons. --- src/controls/QskSwitchButtonSkinlet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controls/QskSwitchButtonSkinlet.cpp b/src/controls/QskSwitchButtonSkinlet.cpp index f18d45b2..4538b0c8 100644 --- a/src/controls/QskSwitchButtonSkinlet.cpp +++ b/src/controls/QskSwitchButtonSkinlet.cpp @@ -67,7 +67,7 @@ QSizeF QskSwitchButtonSkinlet::sizeHint( const QskSkinnable* skinnable, auto handleHint = skinnable->strutSizeHint( QskSwitchButton::Handle ); auto rippleHint = skinnable->strutSizeHint( QskSwitchButton::Ripple ); - auto hint = grooveHint.expandedTo( grooveHint + rippleHint - handleHint ); + auto hint = grooveHint; hint = hint.expandedTo( rippleHint ); hint = hint.expandedTo( handleHint ); From f03007e7b873b9443e3a0752a930fc6495c856f9 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Mon, 13 Jun 2022 08:43:28 +0200 Subject: [PATCH 4/4] QskShadowMetrics added to QskSkinHintTableEditor --- src/common/QskShadowMetrics.h | 15 +++++++++-- src/controls/QskSkinHintTableEditor.cpp | 35 ++++++++++++++++++++++--- src/controls/QskSkinHintTableEditor.h | 13 +++++++++ 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/src/common/QskShadowMetrics.h b/src/common/QskShadowMetrics.h index 8dd4a5a2..f8a232a4 100644 --- a/src/common/QskShadowMetrics.h +++ b/src/common/QskShadowMetrics.h @@ -27,8 +27,10 @@ class QSK_EXPORT QskShadowMetrics public: constexpr QskShadowMetrics( const QPointF& offset = QPointF() ) noexcept; + constexpr QskShadowMetrics( qreal spreadRadius, qreal blurRadius ) noexcept; + constexpr QskShadowMetrics( qreal spreadRadius, qreal blurRadius, - const QPointF& offset = QPointF() ) noexcept; + const QPointF& offset, Qt::SizeMode = Qt::AbsoluteSize ) noexcept; constexpr bool operator==( const QskShadowMetrics& ) const noexcept; constexpr bool operator!=( const QskShadowMetrics& ) const noexcept; @@ -74,10 +76,19 @@ inline constexpr QskShadowMetrics::QskShadowMetrics( const QPointF& offset ) noe } inline constexpr QskShadowMetrics::QskShadowMetrics( - qreal spreadRadius, qreal blurRadius, const QPointF& offset ) noexcept + qreal spreadRadius, qreal blurRadius ) noexcept + : m_spreadRadius( spreadRadius ) + , m_blurRadius( blurRadius ) +{ +} + +inline constexpr QskShadowMetrics::QskShadowMetrics( + qreal spreadRadius, qreal blurRadius, + const QPointF& offset, Qt::SizeMode sizeMode ) noexcept : m_offset( offset ) , m_spreadRadius( spreadRadius ) , m_blurRadius( blurRadius ) + , m_sizeMode( sizeMode ) { } diff --git a/src/controls/QskSkinHintTableEditor.cpp b/src/controls/QskSkinHintTableEditor.cpp index 91fc8f78..ef2cf17f 100644 --- a/src/controls/QskSkinHintTableEditor.cpp +++ b/src/controls/QskSkinHintTableEditor.cpp @@ -11,6 +11,7 @@ #include "QskBoxShapeMetrics.h" #include "QskBoxBorderMetrics.h" #include "QskBoxBorderColors.h" +#include "QskShadowMetrics.h" #include "QskGradient.h" namespace @@ -114,6 +115,11 @@ namespace { return aspect | QskAspect::Border; } + + inline QskAspect aspectShadow( QskAspect aspect ) + { + return aspect | QskAspect::Shadow; + } } QskSkinHintTableEditor::QskSkinHintTableEditor( QskSkinHintTable* table ) @@ -471,13 +477,12 @@ void QskSkinHintTableEditor::setBoxBorderColors( setColorHint( aspectBorder( aspect ), borderColors, combination ); } -void QskSkinHintTableEditor::setBoxBorderColors(QskAspect aspect, +void QskSkinHintTableEditor::setBoxBorderColors( QskAspect aspect, const QskGradient& left, const QskGradient& top, const QskGradient& right, const QskGradient& bottom, QskStateCombination combination ) { setColorHint( aspectBorder( aspect ), - QskBoxBorderColors( left, top, right, bottom ), - combination ); + QskBoxBorderColors( left, top, right, bottom ), combination ); } bool QskSkinHintTableEditor::removeBoxBorderColors( @@ -491,6 +496,30 @@ QskBoxBorderColors QskSkinHintTableEditor::boxBorderColors( QskAspect aspect ) c return colorHint< QskBoxBorderColors >( aspectBorder( aspect ) ); } +void QskSkinHintTableEditor::setShadowMetrics( QskAspect aspect, + qreal spreadRadius, qreal blurRadius, const QPointF& offset, Qt::SizeMode sizeMode ) +{ + setMetricHint( aspectShadow( aspect ), + QskShadowMetrics( spreadRadius, blurRadius, offset, sizeMode ) ); +} + +void QskSkinHintTableEditor::setShadowMetrics( QskAspect aspect, + const QskShadowMetrics& metrics, QskStateCombination combination ) +{ + setMetricHint( aspectShadow( aspect ), metrics, combination ); +} + +bool QskSkinHintTableEditor::removeShadowMetric( + QskAspect aspect, QskStateCombination combination ) +{ + return removeMetricHint( aspectShadow( aspect ), combination ); +} + +QskShadowMetrics QskSkinHintTableEditor::shadowMetrics( QskAspect aspect ) const +{ + return metricHint< QskShadowMetrics >( aspectShadow( aspect ) ); +} + void QskSkinHintTableEditor::setArcMetrics( QskAspect aspect, qreal width, qreal startAngle, qreal spanAngle, Qt::SizeMode sizeMode ) { diff --git a/src/controls/QskSkinHintTableEditor.h b/src/controls/QskSkinHintTableEditor.h index ce1b25cc..6b45df6d 100644 --- a/src/controls/QskSkinHintTableEditor.h +++ b/src/controls/QskSkinHintTableEditor.h @@ -20,6 +20,7 @@ class QskGradient; class QskBoxShapeMetrics; class QskBoxBorderMetrics; class QskBoxBorderColors; +class QskShadowMetrics; class QSK_EXPORT QskSkinHintTableEditor { @@ -234,6 +235,18 @@ class QSK_EXPORT QskSkinHintTableEditor bool removeBoxBorderColors( QskAspect, QskStateCombination = QskStateCombination() ); QskBoxBorderColors boxBorderColors( QskAspect ) const; + // shadowMetrics + + void setShadowMetrics( QskAspect, qreal, qreal, + const QPointF&, Qt::SizeMode = Qt::AbsoluteSize ); + + void setShadowMetrics( QskAspect, const QskShadowMetrics&, + QskStateCombination = QskStateCombination() ); + + bool removeShadowMetric( QskAspect, QskStateCombination = QskStateCombination() ); + + QskShadowMetrics shadowMetrics( QskAspect ) const; + // arcMetrics void setArcMetrics( QskAspect, qreal, qreal, qreal, Qt::SizeMode = Qt::AbsoluteSize );