diff --git a/common/gal/color4d.cpp b/common/gal/color4d.cpp index d4abcf5c01..823232bd50 100644 --- a/common/gal/color4d.cpp +++ b/common/gal/color4d.cpp @@ -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; diff --git a/include/gal/color4d.h b/include/gal/color4d.h index a5bf00c865..cdbf88d542 100644 --- a/include/gal/color4d.h +++ b/include/gal/color4d.h @@ -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. diff --git a/pcbnew/router/pns_tune_status_popup.cpp b/pcbnew/router/pns_tune_status_popup.cpp index 5c4c283d2c..be519a0c9c 100644 --- a/pcbnew/router/pns_tune_status_popup.cpp +++ b/pcbnew/router/pns_tune_status_popup.cpp @@ -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; } } diff --git a/qa/common/test_color4d.cpp b/qa/common/test_color4d.cpp index 9d9354c4a2..0afeb18d76 100644 --- a/qa/common/test_color4d.cpp +++ b/qa/common/test_color4d.cpp @@ -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 ); } }