colors: Add HSL conversion and tune colors

When adding colors to length tuner, we depend on the window background
color, which can be set by the user, resulting in an unreadable text.
This uses the HSL conversion to detect which shade it should use for the
coloring.

Also adds test cases for round-trip HSL and HSV conversion

Fixes: lp:1814530
* https://bugs.launchpad.net/kicad/+bug/1814530
This commit is contained in:
Seth Hillbrand 2019-02-11 19:55:03 -08:00
parent f839278597
commit 7b3ef1b7ed
4 changed files with 172 additions and 7 deletions

View File

@ -2,7 +2,7 @@
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright 2012 Torsten Hueter, torstenhtr <at> gmx.de
* Copyright 2017 Kicad Developers, see AUTHORS.txt for contributors.
* Copyright 2017-2019 Kicad Developers, see AUTHORS.txt for contributors.
*
*
* This program is free software; you can redistribute it and/or
@ -283,6 +283,78 @@ std::ostream &operator<<( std::ostream &aStream, COLOR4D const &aColor )
}
void COLOR4D::ToHSL( double& aOutHue, double& aOutSaturation, double& aOutLightness ) const
{
auto min = std::min( r, std::min( g, b ) );
auto max = std::max( r, std::max( g, b ) );
auto diff = max - min;
aOutLightness = ( max + min ) / 2.0;
if( aOutLightness >= 1.0 )
aOutSaturation = 0.0;
else
aOutSaturation = diff / ( 1.0 - std::abs( 2.0 * aOutLightness - 1.0 ) );
double hue;
if( diff <= 0.0 )
hue = 0.0;
else if( max == r )
hue = ( g - b ) / diff;
else if( max == g )
hue = ( b - r ) / diff + 2.0;
else
hue = ( r - g ) / diff + 4.0;
aOutHue = hue > 0.0 ? hue * 60.0 : hue * 60.0 + 360.0;
while( aOutHue < 0.0 )
aOutHue += 360.0;
}
void COLOR4D::FromHSL( double aInHue, double aInSaturation, double aInLightness )
{
const auto P = ( 1.0 - std::abs( 2.0 * aInLightness - 1.0 ) ) * aInSaturation;
const auto scaled_hue = aInHue / 60.0;
const auto Q = P * ( 1.0 - std::abs( std::fmod( scaled_hue, 2.0 ) - 1.0 ) );
r = g = b = aInLightness - P / 2.0;
if (scaled_hue < 1.0)
{
r += P;
g += Q;
}
else if (scaled_hue < 2.0)
{
r += Q;
g += P;
}
else if (scaled_hue < 3.0)
{
g += P;
b += Q;
}
else if (scaled_hue < 4.0)
{
g += Q;
b += P;
}
else if (scaled_hue < 5.0)
{
r += Q;
b += P;
}
else
{
r += P;
b += Q;
}
}
void COLOR4D::ToHSV( double& aOutHue, double& aOutSaturation, double& aOutValue, bool aAlwaysDefineHue ) const
{
double min, max, delta;

View File

@ -139,6 +139,28 @@ public:
static EDA_COLOR_T GetNearestLegacyColor( const COLOR4D &aColor );
#endif /* WX_COMPATIBLITY */
/**
* Function ToHSL()
* Converts current color (stored in RGB) to HSL format.
*
* @param aOutHue is the conversion result for hue component, in degrees 0 ... 360.0
* @param aOutSaturation is the conversion result for saturation component (0 ... 1.0).
* @param aOutLightness is conversion result for value component (0 ... 1.0).
* @note saturation is set to 0.0 for black color if r = g = b,
*/
void ToHSL( double& aOutHue, double& aOutSaturation, double& aOutValue ) const;
/**
* Function FromHSL()
* Changes currently used color to the one given by hue, saturation and lightness parameters.
*
* @param aInHue is hue component, in degrees (0.0 - 360.0)
* @param aInSaturation is saturation component (0.0 - 1.0)
* @param aInLightness is lightness component (0.0 - 1.0)
*/
void FromHSL( double aInHue, double aInSaturation, double aInLightness );
/**
* Function Brighten
* Makes the color brighter by a given factor.

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2014-2015 CERN
* Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2016-2019 KiCad Developers, see AUTHORS.txt for contributors.
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
@ -33,16 +33,33 @@ void PNS_TUNE_STATUS_POPUP::UpdateStatus( PNS::ROUTER* aRouter )
SetText( placer->TuningInfo( m_frame->GetUserUnits() ) );
// Determine the background color first and choose a contrasting value
COLOR4D bg( m_panel->GetBackgroundColour() );
double h, s, l;
bg.ToHSL( h, s, l );
switch( placer->TuningStatus() )
{
case PNS::MEANDER_PLACER::TUNED:
SetTextColor( wxColour( 0, 255, 0 ) );
if( l < 0.5 )
SetTextColor( wxColor( 0, 255, 0 ) );
else
SetTextColor( wxColor( 0, 128, 0 ) );
break;
case PNS::MEANDER_PLACER::TOO_SHORT:
SetTextColor( wxColour( 255, 128, 128 ) );
if( l < 0.5 )
SetTextColor( wxColor( 255, 128, 128 ) );
else
SetTextColor( wxColor( 128, 64, 64 ) );
break;
case PNS::MEANDER_PLACER::TOO_LONG:
SetTextColor( wxColour( 128, 128, 255 ) );
if( l < 0.5 )
SetTextColor( wxColor( 24, 24, 255 ) );
else
SetTextColor( wxColor( 19, 19, 195 ) );
break;
}
}

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018 KiCad Developers, see CHANGELOG.TXT for contributors.
* Copyright (C) 2018-2019 KiCad Developers, see CHANGELOG.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -217,16 +217,70 @@ struct FROM_HSV_TO_HEX_CASE
BOOST_AUTO_TEST_CASE( FromHsv )
{
static const std::vector<FROM_HSV_TO_HEX_CASE> cases = {
{ 90.0, 0.5, 0.5, 96, 128, 64 },
{ 10, 0.71, 0.66, 168, 69, 49 },
{ 15, 0.96, 0.34, 87, 24, 3 },
{ 120, 0.50, 0.50, 64, 128, 64 },
{ 190, 0.32, 0.97, 168, 234, 247 },
{ 240, 0.15, 0.75, 163, 163, 191 },
{ 240, 0.90, 0.75, 19, 19, 191 },
{ 310, 0.71, 0.66, 168, 49, 148 },
{ 331, 0.15, 0.85, 217, 184, 200 },
};
for( const auto& c : cases )
{
auto col = COLOR4D{};
col.FromHSV( c.h, c.s, c.v );
double new_h, new_s, new_v;
col.ToHSV( new_h, new_s, new_v );
const unsigned char alpha = 0xFF;
BOOST_CHECK_PREDICATE( pred_colour_is_near_hex, ( col )( c.r )( c.g )( c.b )( alpha ) );
BOOST_CHECK_CLOSE( c.h, new_h, 0.0001 );
BOOST_CHECK_CLOSE( c.s, new_s, 0.0001 );
BOOST_CHECK_CLOSE( c.v, new_v, 0.0001 );
}
}
struct FROM_HSL_TO_HEX_CASE
{
double h;
double s;
double l;
unsigned char r;
unsigned char g;
unsigned char b;
};
/**
* Check FromHSL
*/
BOOST_AUTO_TEST_CASE( FromHsl )
{
static const std::vector<FROM_HSL_TO_HEX_CASE> cases = {
{ 10, 0.71, 0.66, 230, 127, 107 },
{ 15, 0.96, 0.34, 170, 45, 3 },
{ 120, 0.5, 0.5, 64, 191, 64 },
{ 190, 0.32, 0.97, 245, 249, 250 },
{ 240, 0.15, 0.75, 182, 182, 201 },
{ 240, 0.90, 0.75, 134, 134, 249 },
{ 310, 0.71, 0.66, 230, 107, 209 },
{ 331, 0.15, 0.85, 222, 211, 217 },
};
for( const auto& c : cases )
{
auto col = COLOR4D{};
col.FromHSL( c.h, c.s, c.l );
double new_h, new_s, new_l;
col.ToHSL( new_h, new_s, new_l );
const unsigned char alpha = 0xFF;
BOOST_CHECK_PREDICATE( pred_colour_is_near_hex, ( col )( c.r )( c.g )( c.b )( alpha ) );
BOOST_CHECK_CLOSE( c.h, new_h, 0.0001 );
BOOST_CHECK_CLOSE( c.s, new_s, 0.0001 );
BOOST_CHECK_CLOSE( c.l, new_l, 0.0001 );
}
}