Skip to content

Commit

Permalink
feat(Expression): Add qcolor_cmyk
Browse files Browse the repository at this point in the history
Contrary to color_cmyk, qcolor_cmyk allows to load a color from float
component (and not int) into a QColor object (and not a string representation).
  • Loading branch information
troopa81 committed Aug 21, 2024
1 parent 71b1d21 commit 0aa9750
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 6 deletions.
29 changes: 29 additions & 0 deletions resources/function_help/json/qcolor_cmyk
Original file line number Diff line number Diff line change
@@ -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"]
}
32 changes: 32 additions & 0 deletions src/core/expression/qgsexpressionfunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<float>( cyan / 100. );
const float m = static_cast<float>( magenta / 100. );
const float y = static_cast<float>( yellow / 100. );
const float k = static_cast<float>( black / 100. );
const float a = static_cast<float>( 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
Expand Down Expand Up @@ -8421,6 +8447,12 @@ const QList<QgsExpressionFunction *> &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" ) )
Expand Down
26 changes: 20 additions & 6 deletions tests/src/core/testqgsexpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand Down Expand Up @@ -2302,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:
Expand Down

0 comments on commit 0aa9750

Please sign in to comment.