feat(Expression): Add color_cmykf

Contrary to color_cmyk, color_cmykf allows to load a color from float
component (and not int) into a QColor object (and not a string representation).
This commit is contained in:
Julien Cabieces 2024-08-21 18:06:52 +02:00 committed by Nyall Dawson
parent 3203704931
commit 53db863fe2
3 changed files with 71 additions and 7 deletions

View File

@ -0,0 +1,29 @@
{
"name": "color_cmykf",
"type": "function",
"groups": ["Color"],
"description": "Returns a color object based on its cyan, magenta, yellow, black and alpha components.",
"arguments": [{
"arg": "cyan",
"description": "cyan component as a float value from 0.0 to 1.0"
}, {
"arg": "magenta",
"description": "magenta component as a float value from 0.0 to 1.0"
}, {
"arg": "yellow",
"description": "yellow component as a float value from 0.0 to 1.0"
}, {
"arg": "black",
"description": "black component as a float value from 0.0 to 1.0"
}, {
"arg": "alpha",
"optional": true,
"default": "1.0",
"description": "alpha component as a float value from 0.0 to 1.0"
}],
"examples": [{
"expression": "color_cmykf(1,0.9,0.81,0.62)",
"returns": "CMYKA: 1.00,0.90,0.81,0.62,1.00"
}],
"tags": ["cyan", "magenta", "yellow", "black", "alpha", "color", "components"]
}

View File

@ -6043,6 +6043,24 @@ static QVariant fncColorHsva( const QVariantList &values, const QgsExpressionCon
return QgsSymbolLayerUtils::encodeColor( color );
}
static QVariant fcnColorCmykF( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
const float cyan = static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent ) );
const float magenta = static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent ) );
const float yellow = static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ) );
const float black = static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent ) );
const float alpha = static_cast<float>( QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent ) );
QColor color = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
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
@ -8417,6 +8435,12 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
<< QgsExpressionFunction::Parameter( QStringLiteral( "black" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "alpha" ) ),
fncColorCmyka, QStringLiteral( "Color" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "color_cmykf" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "cyan" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "magenta" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "yellow" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "black" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "alpha" ), true, 1. ),
fcnColorCmykF, QStringLiteral( "Color" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "color_part" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "color" ) )
<< QgsExpressionFunction::Parameter( QStringLiteral( "component" ) ),
fncColorPart, QStringLiteral( "Color" ) )

View File

@ -1938,9 +1938,9 @@ class TestQgsExpression: public QObject
QTest::newRow( "color rgb float" ) << "color_rgbf(1,0.4989,0)" << false << QVariant( QColor::fromRgbF( 1., 0.4989, 0 ) );
QTest::newRow( "color rgba float" ) << "color_rgbf(1,0.4989,0,0.21)" << 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();
QTest::newRow( "color cmyk float" ) << "color_cmykf(1,0.9012,0,0.8034)" << false << QVariant( QColor::fromCmykF( 1., 0.9012, 0, 0.8034 ) );
QTest::newRow( "color cmyka float" ) << "color_cmykf(1,0.9012,0,0.8034,0.5069)" << false << QVariant( QColor::fromCmykF( 1.f, 0.9012, 0, 0.8034, 0.5069 ) );
QTest::newRow( "color cmyk invalid float" ) << "color_cmykf(1.5,0.1,0,0)" << true << QVariant();
// Precedence and associativity
QTest::newRow( "multiplication first" ) << "1+2*3" << false << QVariant( 7 );
@ -2305,10 +2305,21 @@ class TestQgsExpression: public QObject
const QColor resultColor = result.value<QColor>();
const QColor expectedColor = expected.value<QColor>();
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: