diff --git a/src/common/QskFunctions.cpp b/src/common/QskFunctions.cpp index 892c9a84..986daa2a 100644 --- a/src/common/QskFunctions.cpp +++ b/src/common/QskFunctions.cpp @@ -233,3 +233,17 @@ float qskConstrainedRadians( float radians ) return radians; } + +// do not export; +bool qskHasEnvironment( const char* env ) +{ + bool ok; + + const int value = qEnvironmentVariableIntValue( env, &ok ); + if ( ok ) + return value != 0; + + // All other strings are true, apart from "false" + auto result = qgetenv( env ); + return !result.isEmpty() && result != "false"; +} diff --git a/src/common/QskRgbValue.h b/src/common/QskRgbValue.h index 163aefd4..f15678ff 100644 --- a/src/common/QskRgbValue.h +++ b/src/common/QskRgbValue.h @@ -209,6 +209,16 @@ namespace QskRgb return toTransparent( rgb, qRound( opacity * 255 ) ); } + inline bool isVisible( QRgb rgb ) + { + return qAlpha( rgb ) > 0; + } + + inline bool isVisible( const QColor& color ) + { + return color.isValid() && color.alpha() > 0; + } + QSK_EXPORT QRgb lighter( QRgb, int factor = 150 ) noexcept; QSK_EXPORT QRgb darker( QRgb, int factor = 200 ) noexcept; } diff --git a/src/controls/QskSetup.cpp b/src/controls/QskSetup.cpp index e0ffb30e..21d98930 100644 --- a/src/controls/QskSetup.cpp +++ b/src/controls/QskSetup.cpp @@ -5,31 +5,19 @@ #include "QskSetup.h" +extern bool qskHasEnvironment( const char* ); extern void qskUpdateItemFlags(); namespace { - inline bool hasEnvironment( const char* env ) - { - bool ok; - - const int value = qEnvironmentVariableIntValue( env, &ok ); - if ( ok ) - return value != 0; - - // All other strings are true, apart from "false" - auto result = qgetenv( env ); - return !result.isEmpty() && result != "false"; - } - inline const QskItem::UpdateFlags environmentUpdateFlags() { QskItem::UpdateFlags flags; - if ( !hasEnvironment( "QSK_PREFER_FBO_PAINTING" ) ) + if ( !qskHasEnvironment( "QSK_PREFER_FBO_PAINTING" ) ) flags |= QskItem::PreferRasterForTextures; - if ( hasEnvironment( "QSK_FORCE_BACKGROUND" ) ) + if ( qskHasEnvironment( "QSK_FORCE_BACKGROUND" ) ) flags |= QskItem::DebugForceBackground; return flags; diff --git a/src/controls/QskSimpleListBox.cpp b/src/controls/QskSimpleListBox.cpp index c94acc47..2fb7e7a6 100644 --- a/src/controls/QskSimpleListBox.cpp +++ b/src/controls/QskSimpleListBox.cpp @@ -173,10 +173,8 @@ void QskSimpleListBox::removeAt( int index ) if ( w >= m_data->maxTextWidth ) m_data->maxTextWidth = qskMaxWidth( effectiveFont( Text ), entries ); } - else - { - entries.removeAt( index ); - } + + entries.removeAt( index ); propagateEntries(); diff --git a/src/nodes/QskArcNode.cpp b/src/nodes/QskArcNode.cpp index d8328bd7..1a6ef00b 100644 --- a/src/nodes/QskArcNode.cpp +++ b/src/nodes/QskArcNode.cpp @@ -12,6 +12,7 @@ #include "QskGradient.h" #include "QskSGNode.h" #include "QskShadowMetrics.h" +#include "QskRgbValue.h" #include @@ -91,12 +92,10 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics const auto metricsArc = arcMetrics.toAbsolute( rect.size() ); const auto hasFilling = gradient.isVisible(); - const auto hasBorder = ( borderWidth > 0.0 ) - && borderColor.isValid() && ( borderColor.alpha() > 0 ); + const auto hasBorder = ( borderWidth > 0.0 ) && QskRgb::isVisible( borderColor ); + const auto hasShadow = hasFilling && QskRgb::isVisible( shadowColor ); - const auto hasShadow = shadowColor.isValid() && ( shadowColor.alpha() > 0 ); - - if ( hasShadow && hasFilling ) + if ( hasShadow ) { /* The shader of the shadow node is for circular arcs and we have some @@ -121,7 +120,10 @@ void QskArcNode::setArcData( const QRectF& rect, const QskArcMetrics& arcMetrics if ( hasBorder && hasFilling ) { - if ( !QskArcRenderer::isGradientSupported( rect, metricsArc, gradient ) ) + const bool doCombine = arcNode->hasHint( QskFillNode::PreferColoredGeometry ) + && QskArcRenderer::isGradientSupported( rect, metricsArc, gradient ); + + if ( !doCombine ) fillNode = qskNode< QskArcRenderNode >( this, FillRole ); } diff --git a/src/nodes/QskArcRenderNode.cpp b/src/nodes/QskArcRenderNode.cpp index 4da98336..2abacb58 100644 --- a/src/nodes/QskArcRenderNode.cpp +++ b/src/nodes/QskArcRenderNode.cpp @@ -9,11 +9,12 @@ #include "QskArcMetrics.h" #include "QskGradient.h" #include "QskSGNode.h" +#include "QskRgbValue.h" #include "QskFillNodePrivate.h" static inline bool qskHasBorder( qreal width, const QColor& color ) { - return ( width > 0.0 ) && color.isValid() && ( color.alpha() > 0 ); + return ( width > 0.0 ) && QskRgb::isVisible( color ); } class QskArcRenderNodePrivate final : public QskFillNodePrivate @@ -42,7 +43,7 @@ class QskArcRenderNodePrivate final : public QskFillNodePrivate { QskHashValue hash = 13000; - if ( borderColor.isValid() && ( borderColor.alpha() > 0 ) ) + if ( QskRgb::isVisible( borderColor ) ) hash = qHashBits( &borderColor, sizeof( borderColor ), hash ); if ( gradient.isVisible() ) diff --git a/src/nodes/QskArcRenderer.cpp b/src/nodes/QskArcRenderer.cpp index 7569939d..48cd0f0e 100644 --- a/src/nodes/QskArcRenderer.cpp +++ b/src/nodes/QskArcRenderer.cpp @@ -489,7 +489,7 @@ void QskArcRenderer::setColoredBorderLines( const QRectF& rect, geometry.setDrawingMode( QSGGeometry::DrawTriangleStrip ); geometry.markVertexDataDirty(); - if ( borderWidth <= 0.0 || !( borderColor.isValid() && borderColor.alpha() > 0 ) ) + if ( borderWidth <= 0.0 || !QskRgb::isVisible( borderColor ) ) { qskAllocateColoredLines( geometry, 0 ); return; diff --git a/src/nodes/QskBoxNode.cpp b/src/nodes/QskBoxNode.cpp index a4ea7f74..1e7363fd 100644 --- a/src/nodes/QskBoxNode.cpp +++ b/src/nodes/QskBoxNode.cpp @@ -13,6 +13,7 @@ #include "QskShadowMetrics.h" #include "QskBoxBorderMetrics.h" #include "QskBoxBorderColors.h" +#include "QskRgbValue.h" namespace { @@ -69,32 +70,41 @@ void QskBoxNode::updateNode( const QRectF& rect, if ( !rect.isEmpty() ) { - if ( !shadowMetrics.isNull() - && shadowColor.isValid() && shadowColor.alpha() != 0 ) + const auto hasFilling = gradient.isVisible(); + const auto hasBorder = !borderMetrics.isNull() && borderColors.isVisible(); + + const auto hasShadow = hasFilling && !shadowMetrics.isNull() + && QskRgb::isVisible( shadowColor ); + + if ( hasShadow ) { shadowNode = qskNode< QskBoxShadowNode >( this, ShadowRole ); shadowNode->setShadowData( shadowMetrics.shadowRect( rect ), shape, shadowMetrics.blurRadius(), shadowColor ); } - if ( QskBoxRectangleNode::isCombinedGeometrySupported( gradient ) ) + if ( hasBorder || hasFilling ) { rectNode = qskNode< QskBoxRectangleNode >( this, BoxRole ); - rectNode->updateBox( rect, shape, borderMetrics, borderColors, gradient ); - } - else - { - if ( !borderMetrics.isNull() && borderColors.isVisible() ) - { - rectNode = qskNode< QskBoxRectangleNode >( this, BoxRole ); - rectNode->updateBorder( rect, shape, borderMetrics, borderColors ); - } - if ( gradient.isVisible() ) + if ( hasBorder && hasFilling ) { - fillNode = qskNode< QskBoxRectangleNode >( this, FillRole ); + const bool doCombine = rectNode->hasHint( QskFillNode::PreferColoredGeometry ) + && QskBoxRectangleNode::isCombinedGeometrySupported( gradient ); + + if ( !doCombine ) + fillNode = qskNode< QskBoxRectangleNode >( this, FillRole ); + } + + if ( fillNode ) + { + rectNode->updateBorder( rect, shape, borderMetrics, borderColors ); fillNode->updateFilling( rect, shape, borderMetrics, gradient ); } + else + { + rectNode->updateBox( rect, shape, borderMetrics, borderColors, gradient ); + } } } diff --git a/src/nodes/QskBoxRectangleNode.cpp b/src/nodes/QskBoxRectangleNode.cpp index b7e519f9..36f31d83 100644 --- a/src/nodes/QskBoxRectangleNode.cpp +++ b/src/nodes/QskBoxRectangleNode.cpp @@ -128,15 +128,7 @@ void QskBoxRectangleNode::updateFilling( const QRectF& rect, } else { - if ( fillGradient.isMonochrome() ) - { - if ( dirtyMaterial ) - setColoring( fillGradient.rgbStart() ); - } - else - { - setColoring( rect, fillGradient ); - } + setColoring( rect, fillGradient ); if ( dirtyGeometry ) { diff --git a/src/nodes/QskFillNode.cpp b/src/nodes/QskFillNode.cpp index 08930df3..99f20332 100644 --- a/src/nodes/QskFillNode.cpp +++ b/src/nodes/QskFillNode.cpp @@ -26,6 +26,17 @@ static inline QskFillNode::Coloring qskColoring( QskGradient::Type type ) return static_cast< QskFillNode::Coloring >( coloring ); } +static inline QskFillNode::Hints qskDefaultFillNodeHints() +{ + extern bool qskHasEnvironment( const char* ); + + QskFillNode::Hints hints; + if ( !qskHasEnvironment( "QSK_PREFER_SHADER_COLORS" ) ) + hints |= QskFillNode::PreferColoredGeometry; + + return hints; +} + QskFillNode::QskFillNode() : QskFillNode( *new QskFillNodePrivate ) { @@ -34,6 +45,9 @@ QskFillNode::QskFillNode() QskFillNode::QskFillNode( QskFillNodePrivate& dd ) : QSGGeometryNode( dd ) { + static const auto hints = qskDefaultFillNodeHints(); + + dd.hints = hints; setGeometry( &dd.geometry ); setMaterial( qskMaterialColorVertex ); diff --git a/src/nodes/QskLinesNode.cpp b/src/nodes/QskLinesNode.cpp index e3dc1671..cd1cacba 100644 --- a/src/nodes/QskLinesNode.cpp +++ b/src/nodes/QskLinesNode.cpp @@ -8,6 +8,7 @@ #include "QskStippleMetrics.h" #include "QskStippledLineRenderer.h" #include "QskSGNode.h" +#include "QskRgbValue.h" #include #include @@ -163,8 +164,7 @@ void QskLinesNode::updateLines( const QColor& color, qreal lineWidth, const QskStippleMetrics& stippleMetrics, const QTransform& transform, int count, const QLineF* lines ) { - if ( !stippleMetrics.isValid() || !color.isValid() - || color.alpha() == 0 || count == 0 ) + if ( !stippleMetrics.isValid() || !QskRgb::isVisible( color ) || count == 0 ) { QskSGNode::resetGeometry( this ); return; @@ -195,7 +195,7 @@ void QskLinesNode::updateGrid( const QColor& color, const QTransform& transform, const QRectF& rect, const QVector< qreal >& xValues, const QVector< qreal >& yValues ) { - if ( !stippleMetrics.isValid() || !color.isValid() || color.alpha() == 0 ) + if ( !stippleMetrics.isValid() || !QskRgb::isVisible( color ) ) { QskSGNode::resetGeometry( this ); return; @@ -409,7 +409,7 @@ QSGGeometry::Point2D* QskLinesNode::setSolidLines( void QskLinesNode::updatePolygon( const QColor& color, qreal lineWidth, const QTransform& transform, const QPolygonF& polygon ) { - if ( polygon.isEmpty() || !color.isValid() || ( color.alpha() == 0 ) ) + if ( polygon.isEmpty() || !QskRgb::isVisible( color ) ) { QskSGNode::resetGeometry( this ); return; diff --git a/src/nodes/QskStrokeNode.cpp b/src/nodes/QskStrokeNode.cpp index fb16c63c..6d1625f7 100644 --- a/src/nodes/QskStrokeNode.cpp +++ b/src/nodes/QskStrokeNode.cpp @@ -6,6 +6,7 @@ #include "QskStrokeNode.h" #include "QskVertex.h" #include "QskGradient.h" +#include "QskRgbValue.h" #include @@ -24,7 +25,7 @@ static inline bool qskIsPenVisible( const QPen& pen ) } else { - if ( !pen.color().isValid() || ( pen.color().alpha() == 0 ) ) + if ( !QskRgb::isVisible( pen.color() ) ) return false; }