mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-22 00:06:12 -05:00
feat(Expression): Add color_mix function
It takes string representation or color object as arguments so the function can work with CMYK color without changing its color type and converting it to RGB.
This commit is contained in:
parent
0b034b7e87
commit
dd41e147f8
25
resources/function_help/json/color_mix
Normal file
25
resources/function_help/json/color_mix
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "color_mix",
|
||||
"type": "function",
|
||||
"groups": ["Color"],
|
||||
"description": "Returns a color mixing the red, green, blue, and alpha values of two provided colors based on a given ratio. Returned type is the same as color arguments, i.e. a color string representation or a color object.",
|
||||
"arguments": [{
|
||||
"arg": "color1",
|
||||
"description": "a color string or a color object"
|
||||
}, {
|
||||
"arg": "color2",
|
||||
"description": "a color string or a color object"
|
||||
}, {
|
||||
"arg": "ratio",
|
||||
"description": "a ratio"
|
||||
}],
|
||||
"examples": [{
|
||||
"expression": "color_mix_rgb('0,0,0','255,255,255',0.5)",
|
||||
"returns": "'127,127,127,255'"
|
||||
},
|
||||
{
|
||||
"expression": "color_mix(color_cmykf(0.9,0.9,0.9,0.9),color_cmykf(0.1,0.1,0.1,0.1),0.5)",
|
||||
"returns": "CMYKA: 0.50,0.50,0.50,0.50,1.00"
|
||||
}],
|
||||
"tags": ["green", "blue", "red", "alpha", "mixing", "color", "colors", "provided", "ratio"]
|
||||
}
|
@ -5864,6 +5864,49 @@ static QVariant fcnColorMixRgb( const QVariantList &values, const QgsExpressionC
|
||||
return QgsSymbolLayerUtils::encodeColor( newColor );
|
||||
}
|
||||
|
||||
static QVariant fcnColorMix( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
const QVariant variant1 = values.at( 0 );
|
||||
const QVariant variant2 = values.at( 1 );
|
||||
|
||||
if ( variant1.userType() != variant2.userType() )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Both color arguments must have the same type (string or color object)" ) );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const bool isQColor = variant1.userType() == QMetaType::Type::QColor;
|
||||
QColor color1 = isQColor ? variant1.value<QColor>() : QgsSymbolLayerUtils::decodeColor( variant1.toString() );
|
||||
QColor color2 = isQColor ? variant2.value<QColor>() : QgsSymbolLayerUtils::decodeColor( variant2.toString() );
|
||||
if ( ( color1.spec() == QColor::Cmyk ) != ( color2.spec() == QColor::Cmyk ) )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Both color arguments must have compatible color type (CMYK or RGB/HSV/HSL)" ) );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const float ratio = static_cast<float>( std::clamp( QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent ), 0., 1. ) );
|
||||
|
||||
QColor newColor;
|
||||
const float alpha = color1.alphaF() * ( 1 - ratio ) + color2.alphaF() * ratio;
|
||||
if ( color1.spec() == QColor::Spec::Cmyk )
|
||||
{
|
||||
float cyan = color1.cyanF() * ( 1 - ratio ) + color2.cyanF() * ratio;
|
||||
float magenta = color1.magentaF() * ( 1 - ratio ) + color2.magentaF() * ratio;
|
||||
float yellow = color1.yellowF() * ( 1 - ratio ) + color2.yellowF() * ratio;
|
||||
float black = color1.blackF() * ( 1 - ratio ) + color2.blackF() * ratio;
|
||||
newColor = QColor::fromCmykF( cyan, magenta, yellow, black, alpha );
|
||||
}
|
||||
else
|
||||
{
|
||||
float red = color1.redF() * ( 1 - ratio ) + color2.redF() * ratio;
|
||||
float green = color1.greenF() * ( 1 - ratio ) + color2.greenF() * ratio;
|
||||
float blue = color1.blueF() * ( 1 - ratio ) + color2.blueF() * ratio;
|
||||
newColor = QColor::fromRgbF( red, green, blue, alpha );
|
||||
}
|
||||
|
||||
return isQColor ? QVariant( newColor ) : QVariant( QgsSymbolLayerUtils::encodeColor( newColor ) );
|
||||
}
|
||||
|
||||
static QVariant fcnColorRgb( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
int red = QgsExpressionUtils::getNativeIntValue( values.at( 0 ), parent );
|
||||
@ -8430,6 +8473,10 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "color2" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "ratio" ) ),
|
||||
fcnColorMixRgb, QStringLiteral( "Color" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "color_mix" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "color1" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "color2" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "ratio" ) ),
|
||||
fcnColorMix, QStringLiteral( "Color" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "color_rgb" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "red" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "green" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "blue" ) ),
|
||||
|
@ -1897,6 +1897,10 @@ class TestQgsExpression: public QObject
|
||||
QTest::newRow( "color grayscale average object" ) << "color_grayscale_average(color_rgbf(0.6,0.5,0.1))" << false << QVariant( QColor::fromRgbF( 0.4, 0.4, 0.4 ) );
|
||||
QTest::newRow( "color grayscale average cmyk" ) << "color_grayscale_average(color_cmykf(0.6,0.5,0.1,0.8))" << false << QVariant( QColor::fromCmykF( 0.4, 0.4, 0.4, 0.8 ) );
|
||||
QTest::newRow( "color mix rgb" ) << "color_mix_rgb('0,0,0,100','255,255,255',0.5)" << false << QVariant( "127,127,127,177" );
|
||||
QTest::newRow( "color mix" ) << "color_mix('0,0,0,100','255,255,255',0.5)" << false << QVariant( "128,128,128,178" );
|
||||
QTest::newRow( "color mix mixed types" ) << "color_mix('0,0,0,100',color_rgbf(1.0,1.0,1.0),0.5)" << true << QVariant();
|
||||
QTest::newRow( "color mix mixed color types" ) << "color_mix(color_cmykf(1.0,1.0,1.0,1.0),color_rgbf(1.0,1.0,1.0),0.5)" << true << QVariant();
|
||||
QTest::newRow( "color mix cmyk" ) << "color_mix(color_cmykf(0.9,0.9,0.9,0.9),color_cmykf(0.1,0.1,0.1,0.1),0.5)" << false << QVariant( QColor::fromCmykF( 0.5, 0.5, 0.5, 0.5 ) );
|
||||
|
||||
QTest::newRow( "color part bad color" ) << "color_part('notacolor','red')" << true << QVariant();
|
||||
QTest::newRow( "color part bad part" ) << "color_part(color_rgb(255,127,0),'bad')" << true << QVariant();
|
||||
|
Loading…
x
Reference in New Issue
Block a user