diff --git a/src/common/QskGradient.cpp b/src/common/QskGradient.cpp index 54acf4d9..31e18a0a 100644 --- a/src/common/QskGradient.cpp +++ b/src/common/QskGradient.cpp @@ -171,7 +171,7 @@ QskGradient::QskGradient( const QGradient& qGradient ) QskGradient::QskGradient( const QskGradient& other ) noexcept : m_stops( other.m_stops ) , m_values{ other.m_values[0], other.m_values[1], - other.m_values[2], other.m_values[3], } + other.m_values[2], other.m_values[3], other.m_values[4] } , m_type( other.m_type ) , m_spreadMode( other.m_spreadMode ) , m_stretchMode( other.m_stretchMode ) @@ -197,6 +197,7 @@ QskGradient& QskGradient::operator=( const QskGradient& other ) noexcept m_values[1] = other.m_values[1]; m_values[2] = other.m_values[2]; m_values[3] = other.m_values[3]; + m_values[4] = other.m_values[4]; m_isDirty = other.m_isDirty; m_isValid = other.m_isValid; @@ -215,6 +216,7 @@ bool QskGradient::operator==( const QskGradient& other ) const noexcept && ( m_values[1] == other.m_values[1] ) && ( m_values[2] == other.m_values[2] ) && ( m_values[3] == other.m_values[3] ) + && ( m_values[4] == other.m_values[4] ) && ( m_stops == other.m_stops ); } @@ -439,6 +441,10 @@ void QskGradient::stretchTo( const QRectF& rect ) case Conic: { transform.map( m_values[0], m_values[1], &m_values[0], &m_values[1] ); + + if ( m_values[4] == 0.0 && !rect.isEmpty() ) + m_values[4] = rect.width() / rect.height(); + break; } } @@ -657,6 +663,13 @@ void QskGradient::setConicDirection( qreal x, qreal y, setConicDirection( QskConicDirection( x, y, startAngle, spanAngle ) ); } +void QskGradient::setConicDirection( qreal x, qreal y, + qreal startAngle, qreal spanAngle, qreal aspectRatio ) +{ + const QskConicDirection dir( x, y, startAngle, spanAngle, aspectRatio ); + setConicDirection( dir ); +} + void QskGradient::setConicDirection( const QskConicDirection& direction ) { m_type = Conic; @@ -665,6 +678,7 @@ void QskGradient::setConicDirection( const QskConicDirection& direction ) m_values[1] = direction.center().y(); m_values[2] = direction.startAngle(); m_values[3] = direction.spanAngle(); + m_values[4] = direction.aspectRatio(); } QskConicDirection QskGradient::conicDirection() const @@ -674,7 +688,10 @@ QskConicDirection QskGradient::conicDirection() const if ( m_type != Conic ) return QskConicDirection( 0.5, 0.5, 0.0, 0.0 ); - return QskConicDirection( m_values[0], m_values[1], m_values[2], m_values[3] ); + QskConicDirection dir( m_values[0], m_values[1], m_values[2], m_values[3] ); + dir.setAspectRatio( m_values[4] ); + + return dir; } void QskGradient::setDirection( Type type ) @@ -702,7 +719,7 @@ void QskGradient::setDirection( Type type ) void QskGradient::resetDirection() { m_type = Stops; - m_values[0] = m_values[1] = m_values[2] = m_values[3] = 0.0; + m_values[0] = m_values[1] = m_values[2] = m_values[3] = m_values[4] = 0.0; } QskGradient QskGradient::effectiveGradient() const @@ -803,6 +820,7 @@ QDebug operator<<( QDebug debug, const QskGradient& gradient ) const auto dir = gradient.conicDirection(); debug << dir.center().x() << "," << dir.center().y() + << ",AR:" << dir.aspectRatio() << ",[" << dir.startAngle() << "," << dir.spanAngle() << "])"; break; } diff --git a/src/common/QskGradient.h b/src/common/QskGradient.h index 8fb58ccd..5df88b8c 100644 --- a/src/common/QskGradient.h +++ b/src/common/QskGradient.h @@ -97,8 +97,14 @@ class QSK_EXPORT QskGradient void setRadialDirection( const qreal x, qreal y, qreal radiusX, qreal radiusY ); QskRadialDirection radialDirection() const; - void setConicDirection( qreal, qreal ); - void setConicDirection( qreal, qreal, qreal, qreal = 360.0 ); + void setConicDirection( qreal x, qreal y ); + + void setConicDirection( qreal x, qreal y, + qreal startAngle, qreal spanAngle = 360.0 ); + + void setConicDirection( qreal x, qreal y, + qreal startAngle, qreal spanAngle, qreal aspectRatio ); + void setConicDirection( const QskConicDirection& ); QskConicDirection conicDirection() const; @@ -172,9 +178,9 @@ class QSK_EXPORT QskGradient /* Linear: x1, y1, x2, y2 Radial: centerX, centerY, radiusX, radiusY - Conic: centerX, centerY, startAngle, spanAngle + Conic: centerX, centerY, startAngle, spanAngle, aspectRatio */ - qreal m_values[4] = {}; + qreal m_values[5] = {}; unsigned int m_type : 3; unsigned int m_spreadMode : 3; diff --git a/src/common/QskGradientDirection.cpp b/src/common/QskGradientDirection.cpp index 115edd2b..900377b5 100644 --- a/src/common/QskGradientDirection.cpp +++ b/src/common/QskGradientDirection.cpp @@ -228,6 +228,11 @@ void QskConicDirection::setSpanAngle( qreal degrees ) noexcept m_spanAngle = qBound( -360.0, degrees, 360.0 ); } +void QskConicDirection::setAspectRatio( qreal ratio ) noexcept +{ + m_aspectRatio = qMax( ratio, 0.0 ); +} + // -- QskRadialDirection void QskRadialDirection::setCenter( const QPointF& center ) noexcept diff --git a/src/common/QskGradientDirection.h b/src/common/QskGradientDirection.h index d8a74f52..4ba3e1ad 100644 --- a/src/common/QskGradientDirection.h +++ b/src/common/QskGradientDirection.h @@ -105,16 +105,19 @@ class QSK_EXPORT QskConicDirection Q_PROPERTY( qreal y READ y WRITE setY ) Q_PROPERTY( qreal startAngle READ startAngle WRITE setStartAngle ) Q_PROPERTY( qreal spanAngle READ spanAngle WRITE setSpanAngle ) + Q_PROPERTY( qreal aspectRatio READ aspectRatio WRITE setAspectRatio ) public: // counter-clockwise constexpr QskConicDirection() noexcept = default; constexpr QskConicDirection( qreal x, qreal y, qreal startAngle = 0.0 ) noexcept; - constexpr QskConicDirection( qreal x, qreal y, qreal startAngle, qreal spanAngle ) noexcept; + constexpr QskConicDirection( qreal x, qreal y, + qreal startAngle, qreal spanAngle, qreal aspectRatio = 0.0 ) noexcept; constexpr QskConicDirection( const QPointF&, qreal startAngle = 0.0 ) noexcept; - constexpr QskConicDirection( const QPointF&, qreal startAngle, qreal spanAngle ) noexcept; + constexpr QskConicDirection( const QPointF&, + qreal startAngle, qreal spanAngle, qreal aspectRatio = 0.0 ) noexcept; constexpr QPointF center() const noexcept; void setCenter(const QPointF& center) noexcept; @@ -132,11 +135,15 @@ class QSK_EXPORT QskConicDirection constexpr qreal spanAngle() const noexcept; void setSpanAngle( qreal ) noexcept; + constexpr qreal aspectRatio() const noexcept; + void setAspectRatio( qreal ) noexcept; + private: qreal m_x = 0.5; qreal m_y = 0.5; qreal m_startAngle = 0.0; qreal m_spanAngle = 360.0; + qreal m_aspectRatio = 0.0; }; class QSK_EXPORT QskRadialDirection @@ -299,12 +306,13 @@ inline constexpr QskConicDirection::QskConicDirection( { } -inline constexpr QskConicDirection::QskConicDirection( - qreal x, qreal y, qreal startAngle, qreal spanAngle ) noexcept +inline constexpr QskConicDirection::QskConicDirection( qreal x, qreal y, + qreal startAngle, qreal spanAngle, qreal aspectRatio ) noexcept : m_x( x ) , m_y( y ) , m_startAngle( startAngle ) , m_spanAngle( spanAngle ) + , m_aspectRatio( aspectRatio ) { } @@ -314,9 +322,9 @@ inline constexpr QskConicDirection::QskConicDirection( { } -inline constexpr QskConicDirection::QskConicDirection( - const QPointF& pos, qreal startAngle, qreal spanAngle ) noexcept - : QskConicDirection( pos.x(), pos.y(), startAngle, spanAngle ) +inline constexpr QskConicDirection::QskConicDirection( const QPointF& pos, + qreal startAngle, qreal spanAngle, qreal apectRatio ) noexcept + : QskConicDirection( pos.x(), pos.y(), startAngle, spanAngle, apectRatio ) { } @@ -345,6 +353,11 @@ inline constexpr qreal QskConicDirection::y() const noexcept return m_y; } +inline constexpr qreal QskConicDirection::aspectRatio() const noexcept +{ + return m_aspectRatio; +} + inline constexpr QskRadialDirection::QskRadialDirection( qreal x, qreal y, qreal radius ) noexcept : m_x( x ) diff --git a/src/nodes/QskGradientMaterial.cpp b/src/nodes/QskGradientMaterial.cpp index 164d9f15..7be7d994 100644 --- a/src/nodes/QskGradientMaterial.cpp +++ b/src/nodes/QskGradientMaterial.cpp @@ -510,6 +510,16 @@ namespace const auto dir = gradient.conicDirection(); + float ratio = dir.aspectRatio(); + if ( ratio <= 0.0f ) + ratio = 1.0f; + + if ( ratio != m_aspectRatio ) + { + m_aspectRatio = ratio; + changed = true; + } + const QVector2D center( dir.x(), dir.y() ); if ( center != m_center ) @@ -555,6 +565,7 @@ namespace const auto mat = static_cast< const ConicMaterial* >( other ); if ( ( m_center != mat->m_center ) + || !qskFuzzyCompare( m_aspectRatio, mat->m_aspectRatio ) || !qskFuzzyCompare( m_start, mat->m_start ) || !qskFuzzyCompare( m_span, mat->m_span ) ) { @@ -567,6 +578,7 @@ namespace QSGMaterialShader* createShader() const override; QVector2D m_center; + float m_aspectRatio = 1.0; float m_start = 0.0; float m_span = 1.0; }; @@ -585,6 +597,7 @@ namespace GradientShaderGL::initialize(); m_centerCoordId = program()->uniformLocation( "centerCoord" ); + m_aspectRatioId = program()->uniformLocation( "aspectRatio" ); m_startId = program()->uniformLocation( "start" ); m_spanId = program()->uniformLocation( "span" ); } @@ -594,12 +607,14 @@ namespace auto material = static_cast< const ConicMaterial* >( newMaterial ); program()->setUniformValue( m_centerCoordId, material->m_center ); + program()->setUniformValue( m_aspectRatioId, material->m_aspectRatio ); program()->setUniformValue( m_startId, material->m_start ); program()->setUniformValue( m_spanId, material->m_span ); } private: int m_centerCoordId = -1; + int m_aspectRatioId = -1; int m_startId = -1; int m_spanId = -1; }; @@ -620,7 +635,7 @@ namespace auto matNew = static_cast< ConicMaterial* >( newMaterial ); auto matOld = static_cast< ConicMaterial* >( oldMaterial ); - Q_ASSERT( state.uniformData()->size() >= 84 ); + Q_ASSERT( state.uniformData()->size() >= 88 ); auto data = state.uniformData()->data(); bool changed = false; @@ -639,22 +654,28 @@ namespace changed = true; } + if ( matOld == nullptr || matNew->m_aspectRatio != matOld->m_aspectRatio ) + { + memcpy( data + 72, &matNew->m_aspectRatio, 4 ); + changed = true; + } + if ( matOld == nullptr || matNew->m_start != matOld->m_start ) { - memcpy( data + 72, &matNew->m_start, 4 ); + memcpy( data + 76, &matNew->m_start, 4 ); changed = true; } if ( matOld == nullptr || matNew->m_span != matOld->m_span ) { - memcpy( data + 76, &matNew->m_span, 4 ); + memcpy( data + 80, &matNew->m_span, 4 ); changed = true; } if ( state.isOpacityDirty() ) { const float opacity = state.opacity(); - memcpy( data + 80, &opacity, 4 ); + memcpy( data + 84, &opacity, 4 ); changed = true; } diff --git a/src/nodes/shaders/gradientconic-vulkan.frag b/src/nodes/shaders/gradientconic-vulkan.frag index 526e224d..329d4e4c 100644 --- a/src/nodes/shaders/gradientconic-vulkan.frag +++ b/src/nodes/shaders/gradientconic-vulkan.frag @@ -7,6 +7,7 @@ layout( std140, binding = 0 ) uniform buf { mat4 matrix; vec2 centerCoord; + float aspectRatio; float start; float span; float opacity; diff --git a/src/nodes/shaders/gradientconic-vulkan.vert b/src/nodes/shaders/gradientconic-vulkan.vert index c23fdebb..31c26b26 100644 --- a/src/nodes/shaders/gradientconic-vulkan.vert +++ b/src/nodes/shaders/gradientconic-vulkan.vert @@ -7,6 +7,7 @@ layout( std140, binding = 0 ) uniform buf { mat4 matrix; vec2 centerCoord; + float aspectRatio; float start; float span; float opacity; @@ -17,5 +18,7 @@ out gl_PerVertex { vec4 gl_Position; }; void main() { coord = vertexCoord.xy - ubuf.centerCoord; + coord.y *= ubuf.aspectRatio; + gl_Position = ubuf.matrix * vertexCoord; } diff --git a/src/nodes/shaders/gradientconic.frag.qsb b/src/nodes/shaders/gradientconic.frag.qsb index 3e75c1ac..c2a0848e 100644 Binary files a/src/nodes/shaders/gradientconic.frag.qsb and b/src/nodes/shaders/gradientconic.frag.qsb differ diff --git a/src/nodes/shaders/gradientconic.vert b/src/nodes/shaders/gradientconic.vert index 53b3dbf4..ab2834b8 100644 --- a/src/nodes/shaders/gradientconic.vert +++ b/src/nodes/shaders/gradientconic.vert @@ -1,6 +1,7 @@ attribute vec4 vertexCoord; uniform mat4 matrix; +uniform highp float aspectRatio; uniform vec2 centerCoord; varying vec2 coord; @@ -8,5 +9,7 @@ varying vec2 coord; void main() { coord = vertexCoord.xy - centerCoord; + coord.y *= aspectRatio; + gl_Position = matrix * vertexCoord; } diff --git a/src/nodes/shaders/gradientconic.vert.qsb b/src/nodes/shaders/gradientconic.vert.qsb index abf4cd74..e1b0505c 100644 Binary files a/src/nodes/shaders/gradientconic.vert.qsb and b/src/nodes/shaders/gradientconic.vert.qsb differ