diff --git a/resources/function_help/json/qcolor_cmyk b/resources/function_help/json/qcolor_cmyk new file mode 100644 index 000000000000..f9b9ee8e222c --- /dev/null +++ b/resources/function_help/json/qcolor_cmyk @@ -0,0 +1,29 @@ +{ + "name": "qcolor_cmyk", + "type": "function", + "groups": ["Color"], + "description": "Returns a QColor object based on its cyan, magenta, yellow, black and alpha components.", + "arguments": [{ + "arg": "cyan", + "description": "cyan component as a float value from 0 to 100" + }, { + "arg": "magenta", + "description": "magenta component as a float value from 0 to 100" + }, { + "arg": "yellow", + "description": "yellow component as a float value from 0 to 100" + }, { + "arg": "black", + "description": "black component as a float value from 0 to 100" + }, { + "arg": "alpha", + "optional": true, + "default": "100", + "description": "alpha component as a float value from 0 to 100" + }], + "examples": [{ + "expression": "qcolor_cmyk(100,90,80.15,60.22)", + "returns": "CMYKA: 100.00,90,80.15,60.22" + }], + "tags": ["cyan", "magenta", "yellow", "black", "alpha", "color", "components"] +} diff --git a/src/core/expression/qgsexpressionfunction.cpp b/src/core/expression/qgsexpressionfunction.cpp index 80ecaaf0ded8..5246f21eb5c5 100644 --- a/src/core/expression/qgsexpressionfunction.cpp +++ b/src/core/expression/qgsexpressionfunction.cpp @@ -6047,6 +6047,32 @@ static QVariant fncColorHsva( const QVariantList &values, const QgsExpressionCon return QgsSymbolLayerUtils::encodeColor( color ); } +static QVariant fcnQColorCmyk( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * ) +{ + // Component ranges from 0 - 100 + + const double cyan = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ); + const double magenta = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ); + const double yellow = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ); + const double black = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ); + const double alpha = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent ); + + const float c = static_cast( cyan / 100. ); + const float m = static_cast( magenta / 100. ); + const float y = static_cast( yellow / 100. ); + const float k = static_cast( black / 100. ); + const float a = static_cast( alpha / 100. ); + + QColor color = QColor::fromCmykF( c, m, y, k, a ); + if ( ! color.isValid() ) + { + parent->setEvalErrorString( QObject::tr( "Cannot convert '%1:%2:%3:%4:%5' to color" ).arg( cyan ).arg( magenta ).arg( yellow ).arg( black ).arg( alpha ) ); + color = QColor( 0, 0, 0 ); + } + + return color; +} + static QVariant fcnColorCmyk( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * ) { // Cyan ranges from 0 - 100 @@ -8421,6 +8447,12 @@ const QList &QgsExpression::Functions() << QgsExpressionFunction::Parameter( QStringLiteral( "black" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "alpha" ) ), fncColorCmyka, QStringLiteral( "Color" ) ) + << new QgsStaticExpressionFunction( QStringLiteral( "qcolor_cmyk" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "cyan" ) ) + << QgsExpressionFunction::Parameter( QStringLiteral( "magenta" ) ) + << QgsExpressionFunction::Parameter( QStringLiteral( "yellow" ) ) + << QgsExpressionFunction::Parameter( QStringLiteral( "black" ) ) + << QgsExpressionFunction::Parameter( QStringLiteral( "alpha" ), true, 100. ), + fcnQColorCmyk, QStringLiteral( "Color" ) ) << new QgsStaticExpressionFunction( QStringLiteral( "color_part" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "color" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "component" ) ), fncColorPart, QStringLiteral( "Color" ) ) diff --git a/tests/src/core/testqgsexpression.cpp b/tests/src/core/testqgsexpression.cpp index 9da039d92b29..5f5d2b817e26 100644 --- a/tests/src/core/testqgsexpression.cpp +++ b/tests/src/core/testqgsexpression.cpp @@ -1936,8 +1936,11 @@ class TestQgsExpression: public QObject QTest::newRow( "color lighter" ) << "lighter('200,100,30',150)" << false << QVariant( "255,154,83,255" ); QTest::newRow( "color lighter bad color" ) << "lighter('notacolor',150)" << true << QVariant(); - QTest::newRow( "qcolor rgb" ) << "qcolor_rgb(255,127.23,58.489)" << false << QVariant( QColor::fromRgbF( 1.f, 0.4989, 0.2293 ) ); - QTest::newRow( "qcolor rgba" ) << "qcolor_rgb(255,127.23,58.489,53.55)" << false << QVariant( QColor::fromRgbF( 1.f, 0.4989, 0.2293, 0.21 ) ); + QTest::newRow( "qcolor rgb" ) << "qcolor_rgb(255,127.23,0)" << false << QVariant( QColor::fromRgbF( 1., 0.4989, 0 ) ); + QTest::newRow( "qcolor rgba" ) << "qcolor_rgb(255,127.23,0,53.55)" << false << QVariant( QColor::fromRgbF( 1., 0.4989, 0, 0.21 ) ); + QTest::newRow( "qcolor cmyk" ) << "qcolor_cmyk(100,90.12,0,80.34)" << false << QVariant( QColor::fromCmykF( 1., 0.9012, 0, 0.8034 ) ); + QTest::newRow( "qcolor cmyka" ) << "qcolor_cmyk(100,90.12,0,80.34,50.69)" << false << QVariant( QColor::fromCmykF( 1.f, 0.9012, 0, 0.8034, 0.5069 ) ); + QTest::newRow( "qcolor cmyk invalid" ) << "qcolor_cmyk(150,10,0,0)" << true << QVariant(); // Precedence and associativity QTest::newRow( "multiplication first" ) << "1+2*3" << false << QVariant( 7 ); @@ -2302,10 +2305,21 @@ class TestQgsExpression: public QObject const QColor resultColor = result.value(); const QColor expectedColor = expected.value(); QCOMPARE( resultColor.spec(), expectedColor.spec() ); - QVERIFY( qgsDoubleNear( resultColor.redF(), expectedColor.redF(), 0.001 ) ); - QVERIFY( qgsDoubleNear( resultColor.greenF(), expectedColor.greenF(), 0.001 ) ); - QVERIFY( qgsDoubleNear( resultColor.blueF(), expectedColor.blueF(), 0.001 ) ); - QVERIFY( qgsDoubleNear( resultColor.alphaF(), expectedColor.alphaF(), 0.001 ) ); + if ( resultColor.spec() == QColor::Spec::Cmyk ) + { + QVERIFY( qgsDoubleNear( resultColor.cyanF(), expectedColor.cyanF(), 0.001 ) ); + QVERIFY( qgsDoubleNear( resultColor.magentaF(), expectedColor.magentaF(), 0.001 ) ); + QVERIFY( qgsDoubleNear( resultColor.yellowF(), expectedColor.yellowF(), 0.001 ) ); + QVERIFY( qgsDoubleNear( resultColor.blackF(), expectedColor.blackF(), 0.001 ) ); + QVERIFY( qgsDoubleNear( resultColor.alphaF(), expectedColor.alphaF(), 0.001 ) ); + } + else + { + QVERIFY( qgsDoubleNear( resultColor.redF(), expectedColor.redF(), 0.001 ) ); + QVERIFY( qgsDoubleNear( resultColor.greenF(), expectedColor.greenF(), 0.001 ) ); + QVERIFY( qgsDoubleNear( resultColor.blueF(), expectedColor.blueF(), 0.001 ) ); + QVERIFY( qgsDoubleNear( resultColor.alphaF(), expectedColor.alphaF(), 0.001 ) ); + } break; } default: