diff --git a/src/cascadia/TerminalApp/ColorHelper.cpp b/src/cascadia/TerminalApp/ColorHelper.cpp deleted file mode 100644 index 2235cc6b37..0000000000 --- a/src/cascadia/TerminalApp/ColorHelper.cpp +++ /dev/null @@ -1,267 +0,0 @@ -#include "ColorHelper.h" - -using namespace winrt::TerminalApp; - -// Method Description: -// Determines whether or not a given color is light -// Arguments: -// - color: this color is going to be examined whether it -// is light or not -// Return Value: -// - true if light, false if dark -bool ColorHelper::IsBrightColor(const winrt::Windows::UI::Color& color) -{ - // https://www.w3.org/TR/AERT#color-contrast - auto brightness = (color.R * 299 + color.G * 587 + color.B * 114) / 1000.f; - return brightness > 128.f; -} - -// Method Description: -// Converts a rgb color to an hsl one -// Arguments: -// - color: the rgb color, which is going to be converted -// Return Value: -// - a hsl color with the following ranges -// - H: [0.f -360.f] -// - L: [0.f - 1.f] (rounded to the third decimal place) -// - S: [0.f - 1.f] (rounded to the third decimal place) -HSL ColorHelper::RgbToHsl(const winrt::Windows::UI::Color& color) -{ - // https://www.rapidtables.com/convert/color/rgb-to-hsl.html - auto epsilon = std::numeric_limits::epsilon(); - auto r = color.R / 255.f; - auto g = color.G / 255.f; - auto b = color.B / 255.f; - - auto max = std::max(r, std::max(g, b)); - auto min = std::min(r, std::min(g, b)); - - auto delta = max - min; - - auto h = 0.f; - auto s = 0.f; - auto l = (max + min) / 2; - - if (delta < epsilon || max < epsilon) /* delta == 0 || max == 0*/ - { - l = std::roundf(l * 1000) / 1000; - return HSL{ h, s, l }; - } - - s = l > 0.5 ? delta / (2 - max - min) : delta / (max + min); - - if (max - r < epsilon) // max == r - { - h = (g - b) / delta + (g < b ? 6 : 0); - } - else if (max - g < epsilon) // max == g - { - h = (b - r) / delta + 2; - } - else if (max - b < epsilon) // max == b - { - h = (r - g) / delta + 4; - } - - // three decimal places after the comma ought - // to be enough for everybody - Bill Gates, 1981 - auto finalH = std::roundf(h * 60); - auto finalS = std::roundf(s * 1000) / 1000; - auto finalL = std::roundf(l * 1000) / 1000; - - return HSL{ finalH, finalS, finalL }; -} - -// Method Description: -// Converts a hsl color to rgb one -// Arguments: -// - color: the hsl color, which is going to be converted -// Return Value: -// - the rgb color (r,g,b - [0, 255] range) -winrt::Windows::UI::Color ColorHelper::HslToRgb(const HSL& color) -{ - auto epsilon = std::numeric_limits::epsilon(); - - auto h = (color.H - 1.f > epsilon) ? color.H / 360.f : color.H; - auto s = (color.S - 1.f > epsilon) ? color.S / 100.f : color.S; - auto l = (color.L - 1.f > epsilon) ? color.L / 100.f : color.L; - - auto r = l; - auto g = l; - auto b = l; - - if (s > epsilon) - { - auto q = l < 0.5 ? l * (1 + s) : l + s - l * s; - auto p = 2 * l - q; - r = HueToRgb(p, q, h + 1.f / 3.f); - g = HueToRgb(p, q, h); - b = HueToRgb(p, q, h - 1.f / 3.f); - } - - auto finalR = static_cast(std::roundf(r * 255)); - auto finalG = static_cast(std::roundf(g * 255)); - auto finalB = static_cast(std::roundf(b * 255)); - uint8_t finalA = 255; //opaque - - return winrt::Windows::UI::ColorHelper::FromArgb(finalA, finalR, finalG, finalB); -} - -float ColorHelper::HueToRgb(float p, float q, float t) -{ - auto epsilon = std::numeric_limits::epsilon(); - - if (t < 0) - t += 1; - if (t > 1) - t -= 1; - if (t - (1.f / 6.f) < epsilon) - return p + (q - p) * 6 * t; - if (t - .5f < epsilon) - return q; - if (t - 2.f / 3.f < epsilon) - return p + (q - p) * (2.f / 3.f - t) * 6; - return p; -} - -// Method Description: -// Lightens a color by a given amount -// Arguments: -// - color: the color which is going to be lightened -// - amount: the lighten amount (0-100) -// Return Value: -// - the lightened color in RGB format -winrt::Windows::UI::Color ColorHelper::Lighten(const winrt::Windows::UI::Color& color, float amount /* = 10.f*/) -{ - auto hsl = RgbToHsl(color); - hsl.L += amount / 100; - hsl.L = std::clamp(hsl.L, 0.f, 1.f); - return HslToRgb(hsl); -} - -// Method Description: -// Darkens a color by a given amount -// Arguments: -// - color: the color which is going to be darkened -// - amount: the darken amount (0-100) -// Return Value: -// - the darkened color in RGB format -winrt::Windows::UI::Color ColorHelper::Darken(const winrt::Windows::UI::Color& color, float amount /* = 10.f*/) -{ - auto hsl = RgbToHsl(color); - hsl.L -= amount / 100; - hsl.L = std::clamp(hsl.L, 0.f, 1.f); - return HslToRgb(hsl); -} - -// Method Description: -// Gets an accent color to a given color. Basically, generates -// 16 shades of the color and finds the first which has a good -// contrast according to https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef (WCAG Version 2) -// Readability ratio of 3.5 seems to look quite nicely -// Arguments: -// - color: the color for which we need an accent -// Return Value: -// - the accent color in RGB format -winrt::Windows::UI::Color ColorHelper::GetAccentColor(const winrt::Windows::UI::Color& color) -{ - auto accentColor = RgbToHsl(color); - - if (accentColor.S < 0.15) - { - accentColor.S = 0.15f; - } - - constexpr auto shadeCount = 16; - constexpr auto shadeStep = 1.f / shadeCount; - auto shades = std::map(); - for (auto i = 0; i < 15; i++) - { - auto shade = HSL{ accentColor.H, accentColor.S, i * shadeStep }; - auto contrast = GetReadability(shade, accentColor); - shades.insert(std::make_pair(contrast, shade)); - } - - // 3f is quite nice if the whole non-client area is painted - constexpr auto readability = 1.75f; - for (auto shade : shades) - { - if (shade.first >= readability) - { - return HslToRgb(shade.second); - } - } - return HslToRgb(shades.end()->second); -} - -// Method Description: -// Gets the readability of two colors according to -// https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef (WCAG Version 2) -// Arguments: -// - firstColor: the first color for the readability check (hsl) -// - secondColor: the second color for the readability check (hsl) -// Return Value: -// - the readability of the colors according to (WCAG Version 2) -float ColorHelper::GetReadability(const HSL& first, const HSL& second) -{ - return GetReadability(HslToRgb(first), HslToRgb(second)); -} - -// Method Description: -// Gets the readability of two colors according to -// https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef (WCAG Version 2) -// Arguments: -// - firstColor: the first color for the readability check (rgb) -// - secondColor: the second color for the readability check (rgb) -// Return Value: -// - the readability of the colors according to (WCAG Version 2) -float ColorHelper::GetReadability(const winrt::Windows::UI::Color& first, const winrt::Windows::UI::Color& second) -{ - auto l1 = GetLuminance(first); - auto l2 = GetLuminance(second); - - return (std::max(l1, l2) + 0.05f) / std::min(l1, l2) + 0.05f; -} - -// Method Description: -// Calculates the luminance of a given color according to -// https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef -// Arguments: -// - color: its luminance is going to be calculated -// Return Value: -// - the luminance of the color -float ColorHelper::GetLuminance(const winrt::Windows::UI::Color& color) -{ - auto epsilon = std::numeric_limits::epsilon(); - float R, G, B; - auto RsRGB = color.R / 255.f; - auto GsRGB = color.G / 255.f; - auto BsRGB = color.B / 255.f; - - if (RsRGB - 0.03928f <= epsilon) - { - R = RsRGB / 12.92f; - } - else - { - R = std::pow(((RsRGB + 0.055f) / 1.055f), 2.4f); - } - if (GsRGB - 0.03928f <= epsilon) - { - G = GsRGB / 12.92f; - } - else - { - G = std::pow(((GsRGB + 0.055f) / 1.055f), 2.4f); - } - if (BsRGB - 0.03928f <= epsilon) - { - B = BsRGB / 12.92f; - } - else - { - B = std::pow(((BsRGB + 0.055f) / 1.055f), 2.4f); - } - auto luminance = (0.2126f * R) + (0.7152f * G) + (0.0722f * B); - return std::roundf(luminance * 10000) / 10000.f; -} diff --git a/src/cascadia/TerminalApp/ColorHelper.h b/src/cascadia/TerminalApp/ColorHelper.h deleted file mode 100644 index e4ab3f42b7..0000000000 --- a/src/cascadia/TerminalApp/ColorHelper.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include - -namespace winrt::TerminalApp -{ - class HSL - { - public: - float H; - float S; - float L; - }; - - class ColorHelper - { - public: - static bool IsBrightColor(const Windows::UI::Color& color); - static HSL RgbToHsl(const Windows::UI::Color& color); - static Windows::UI::Color HslToRgb(const HSL& color); - static Windows::UI::Color Lighten(const Windows::UI::Color& color, float amount = 10.f); - static Windows::UI::Color Darken(const Windows::UI::Color& color, float amount = 10.f); - static Windows::UI::Color GetAccentColor(const Windows::UI::Color& color); - static float GetLuminance(const Windows::UI::Color& color); - static float GetReadability(const Windows::UI::Color& first, const Windows::UI::Color& second); - static float GetReadability(const HSL& first, const HSL& second); - - private: - static float HueToRgb(float p, float q, float t); - }; -} diff --git a/src/cascadia/TerminalApp/Tab.cpp b/src/cascadia/TerminalApp/Tab.cpp index 6c305c66d1..b08842e3f2 100644 --- a/src/cascadia/TerminalApp/Tab.cpp +++ b/src/cascadia/TerminalApp/Tab.cpp @@ -8,8 +8,8 @@ #include "SettingsPaneContent.h" #include "Tab.g.cpp" #include "Utils.h" -#include "ColorHelper.h" #include "AppLogic.h" +#include "../../types/inc/ColorFix.hpp" using namespace winrt; using namespace winrt::Windows::UI::Xaml; @@ -2275,11 +2275,13 @@ namespace winrt::TerminalApp::implementation // the background color // - This method should only be called on the UI thread. // Arguments: - // - color: the color the user picked for their tab + // - uiColor: the color the user picked for their tab // Return Value: // - - void Tab::_ApplyTabColorOnUIThread(const winrt::Windows::UI::Color& color) + void Tab::_ApplyTabColorOnUIThread(const winrt::Windows::UI::Color& uiColor) { + constexpr auto lightnessThreshold = 0.6f; + const til::color color{ uiColor }; Media::SolidColorBrush selectedTabBrush{}; Media::SolidColorBrush deselectedTabBrush{}; Media::SolidColorBrush fontBrush{}; @@ -2292,7 +2294,7 @@ namespace winrt::TerminalApp::implementation // calculate the luminance of the current color and select a font // color based on that // see https://www.w3.org/TR/WCAG20/#relativeluminancedef - if (TerminalApp::ColorHelper::IsBrightColor(color)) + if (ColorFix::GetLightness(color) >= lightnessThreshold) { auto subtleFillColorSecondary = winrt::Windows::UI::Colors::Black(); subtleFillColorSecondary.A = 0x09; @@ -2312,8 +2314,8 @@ namespace winrt::TerminalApp::implementation } // The tab font should be based on the evaluated appearance of the tab color layered on tab row. - const auto layeredTabColor = til::color{ color }.layer_over(_tabRowColor); - if (TerminalApp::ColorHelper::IsBrightColor(layeredTabColor)) + const auto layeredTabColor = color.layer_over(_tabRowColor); + if (ColorFix::GetLightness(layeredTabColor) >= lightnessThreshold) { fontBrush.Color(winrt::Windows::UI::Colors::Black()); auto secondaryFontColor = winrt::Windows::UI::Colors::Black(); @@ -2333,8 +2335,7 @@ namespace winrt::TerminalApp::implementation selectedTabBrush.Color(color); // Start with the current tab color, set to Opacity=.3 - til::color deselectedTabColor{ color }; - deselectedTabColor = deselectedTabColor.with_alpha(77); // 255 * .3 = 77 + auto deselectedTabColor = color.with_alpha(77); // 255 * .3 = 77 // If we DON'T have a color set from the color picker, or the profile's // tabColor, but we do have a unfocused color in the theme, use the @@ -2376,7 +2377,7 @@ namespace winrt::TerminalApp::implementation // We don't want that to result in white text on a white tab row for // inactive tabs. const auto deselectedActualColor = deselectedTabColor.layer_over(_tabRowColor); - if (TerminalApp::ColorHelper::IsBrightColor(deselectedActualColor)) + if (ColorFix::GetLightness(deselectedActualColor) >= lightnessThreshold) { deselectedFontBrush.Color(winrt::Windows::UI::Colors::Black()); } diff --git a/src/cascadia/TerminalApp/TabManagement.cpp b/src/cascadia/TerminalApp/TabManagement.cpp index b7a3e29e5a..bbb42e8b7b 100644 --- a/src/cascadia/TerminalApp/TabManagement.cpp +++ b/src/cascadia/TerminalApp/TabManagement.cpp @@ -18,7 +18,6 @@ #include #include "TabRowControl.h" -#include "ColorHelper.h" #include "DebugTapConnection.h" #include "..\TerminalSettingsModel\FileUtils.h" diff --git a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj index 7e5028167b..3be78cbce0 100644 --- a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj +++ b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj @@ -134,7 +134,6 @@ - ShortcutActionDispatch.idl @@ -247,9 +246,6 @@ - - NotUsing - Create diff --git a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj.filters b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj.filters index 68c7f8c7a3..d082b2a054 100644 --- a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj.filters +++ b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj.filters @@ -20,7 +20,6 @@ - @@ -48,7 +47,6 @@ - commandPalette diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index ce8e8762e4..7ee4649801 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -6,24 +6,24 @@ #include "TerminalPage.h" #include -#include #include +#include -#include "../../types/inc/utils.hpp" #include "App.h" -#include "ColorHelper.h" #include "DebugTapConnection.h" -#include "SettingsPaneContent.h" -#include "ScratchpadContent.h" -#include "SnippetsPaneContent.h" #include "MarkdownPaneContent.h" -#include "TabRowControl.h" #include "Remoting.h" +#include "ScratchpadContent.h" +#include "SettingsPaneContent.h" +#include "SnippetsPaneContent.h" +#include "TabRowControl.h" +#include "../../types/inc/ColorFix.hpp" +#include "../../types/inc/utils.hpp" -#include "TerminalPage.g.cpp" +#include "LaunchPositionRequest.g.cpp" #include "RenameWindowRequestedArgs.g.cpp" #include "RequestMoveContentArgs.g.cpp" -#include "LaunchPositionRequest.g.cpp" +#include "TerminalPage.g.cpp" using namespace winrt; using namespace winrt::Microsoft::Management::Deployment; @@ -3904,36 +3904,18 @@ namespace winrt::TerminalApp::implementation // and the non-client are behind it // Return Value: // - - void TerminalPage::_SetNewTabButtonColor(const Windows::UI::Color& color, const Windows::UI::Color& accentColor) + void TerminalPage::_SetNewTabButtonColor(const til::color color, const til::color accentColor) { + constexpr auto lightnessThreshold = 0.6f; // TODO GH#3327: Look at what to do with the tab button when we have XAML theming - auto IsBrightColor = ColorHelper::IsBrightColor(color); - auto isLightAccentColor = ColorHelper::IsBrightColor(accentColor); - winrt::Windows::UI::Color pressedColor{}; - winrt::Windows::UI::Color hoverColor{}; - winrt::Windows::UI::Color foregroundColor{}; - const auto hoverColorAdjustment = 5.f; - const auto pressedColorAdjustment = 7.f; + const auto IsBrightColor = ColorFix::GetLightness(color) >= lightnessThreshold; + const auto isLightAccentColor = ColorFix::GetLightness(accentColor) >= lightnessThreshold; + const auto hoverColorAdjustment = isLightAccentColor ? -0.05f : 0.05f; + const auto pressedColorAdjustment = isLightAccentColor ? -0.1f : 0.1f; - if (IsBrightColor) - { - foregroundColor = winrt::Windows::UI::Colors::Black(); - } - else - { - foregroundColor = winrt::Windows::UI::Colors::White(); - } - - if (isLightAccentColor) - { - hoverColor = ColorHelper::Darken(accentColor, hoverColorAdjustment); - pressedColor = ColorHelper::Darken(accentColor, pressedColorAdjustment); - } - else - { - hoverColor = ColorHelper::Lighten(accentColor, hoverColorAdjustment); - pressedColor = ColorHelper::Lighten(accentColor, pressedColorAdjustment); - } + const auto foregroundColor = IsBrightColor ? Colors::Black() : Colors::White(); + const auto hoverColor = til::color{ ColorFix::AdjustLightness(accentColor, hoverColorAdjustment) }; + const auto pressedColor = til::color{ ColorFix::AdjustLightness(accentColor, pressedColorAdjustment) }; Media::SolidColorBrush backgroundBrush{ accentColor }; Media::SolidColorBrush backgroundHoverBrush{ hoverColor }; diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index e4bf6efa1e..23def359b2 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -463,7 +463,7 @@ namespace winrt::TerminalApp::implementation void _RefreshUIForSettingsReload(); - void _SetNewTabButtonColor(const Windows::UI::Color& color, const Windows::UI::Color& accentColor); + void _SetNewTabButtonColor(til::color color, til::color accentColor); void _ClearNewTabButtonColor(); safe_void_coroutine _CompleteInitialization(); diff --git a/src/cascadia/TerminalApp/TitlebarControl.cpp b/src/cascadia/TerminalApp/TitlebarControl.cpp index 1ed82f39ca..7ecf34d2c1 100644 --- a/src/cascadia/TerminalApp/TitlebarControl.cpp +++ b/src/cascadia/TerminalApp/TitlebarControl.cpp @@ -7,8 +7,7 @@ #include "pch.h" #include "TitlebarControl.h" - -#include "ColorHelper.h" +#include "../../types/inc/ColorFix.hpp" #include "TitlebarControl.g.cpp" @@ -189,7 +188,8 @@ namespace winrt::TerminalApp::implementation return; } - const auto isBrightColor = ColorHelper::IsBrightColor(c); + constexpr auto lightnessThreshold = 0.6f; + const auto isBrightColor = ColorFix::GetLightness(c) >= lightnessThreshold; MinMaxCloseControl().RequestedTheme(isBrightColor ? winrt::Windows::UI::Xaml::ElementTheme::Light : winrt::Windows::UI::Xaml::ElementTheme::Dark); } diff --git a/src/cascadia/ut_app/ColorHelperTests.cpp b/src/cascadia/ut_app/ColorHelperTests.cpp deleted file mode 100644 index 03ec18d57e..0000000000 --- a/src/cascadia/ut_app/ColorHelperTests.cpp +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#include "precomp.h" - -#include "../TerminalSettingsModel/Profile.h" -#include "../TerminalApp/ColorHelper.h" - -// Import some templates to compare floats using approximate matching. -#include - -using namespace Microsoft::Console; -using namespace winrt::TerminalApp; -using namespace WEX::Logging; -using namespace WEX::TestExecution; -using namespace WEX::Common; - -namespace TerminalAppUnitTests -{ - class ColorHelperTests - { - BEGIN_TEST_CLASS(ColorHelperTests) - TEST_CLASS_PROPERTY(L"ActivationContext", L"TerminalApp.Unit.Tests.manifest") - END_TEST_CLASS() - - TEST_METHOD(ConvertRgbToHsl); - TEST_METHOD(ConvertHslToRgb); - TEST_METHOD(LuminanceTests); - }; - - void ColorHelperTests::ConvertHslToRgb() - { - auto red = winrt::Windows::UI::Colors::Red(); - auto redHsl = ColorHelper::RgbToHsl(red); - VERIFY_ARE_EQUAL(0.f, redHsl.H); - VERIFY_ARE_EQUAL(1.f, redHsl.S); - VERIFY_ARE_EQUAL(0.5f, redHsl.L); - - auto green = winrt::Windows::UI::Colors::Lime(); - auto greenHsl = ColorHelper::RgbToHsl(green); - VERIFY_ARE_EQUAL(120.f, greenHsl.H); - VERIFY_ARE_EQUAL(1.f, greenHsl.S); - VERIFY_ARE_EQUAL(0.5f, greenHsl.L); - - auto blue = winrt::Windows::UI::Colors::Blue(); - auto blueHsl = ColorHelper::RgbToHsl(blue); - VERIFY_ARE_EQUAL(240.f, blueHsl.H); - VERIFY_ARE_EQUAL(1.f, blueHsl.S); - VERIFY_ARE_EQUAL(0.5f, blueHsl.L); - - auto darkTurquoise = winrt::Windows::UI::Colors::DarkTurquoise(); - auto darkTurquoiseHsl = ColorHelper::RgbToHsl(darkTurquoise); - VERIFY_ARE_EQUAL(181.f, darkTurquoiseHsl.H); - VERIFY_ARE_EQUAL(1.f, darkTurquoiseHsl.S); - VERIFY_ARE_EQUAL(0.41f, darkTurquoiseHsl.L); - - auto darkViolet = winrt::Windows::UI::Colors::DarkViolet(); - auto darkVioletHsl = ColorHelper::RgbToHsl(darkViolet); - VERIFY_ARE_EQUAL(282.f, darkVioletHsl.H); - VERIFY_ARE_EQUAL(1.f, darkVioletHsl.S); - VERIFY_ARE_EQUAL(0.414f, darkVioletHsl.L); - - auto white = winrt::Windows::UI::Colors::White(); - auto whiteHsl = ColorHelper::RgbToHsl(white); - VERIFY_ARE_EQUAL(0.f, whiteHsl.H); - VERIFY_ARE_EQUAL(0.f, whiteHsl.S); - VERIFY_ARE_EQUAL(1.f, whiteHsl.L); - - auto black = winrt::Windows::UI::Colors::Black(); - auto blackHsl = ColorHelper::RgbToHsl(black); - VERIFY_ARE_EQUAL(0.f, blackHsl.H); - VERIFY_ARE_EQUAL(0.f, blackHsl.S); - VERIFY_ARE_EQUAL(0.f, blackHsl.L); - } - - void ColorHelperTests::ConvertRgbToHsl() - { - auto redHsl = HSL{ 0.f, 100.f, 50.f }; - auto red = ColorHelper::HslToRgb(redHsl); - VERIFY_ARE_EQUAL(255, red.R); - VERIFY_ARE_EQUAL(0, red.G); - VERIFY_ARE_EQUAL(0, red.B); - - auto greenHsl = HSL{ 120.f, 100.f, 50.f }; - auto green = ColorHelper::HslToRgb(greenHsl); - VERIFY_ARE_EQUAL(0, green.R); - VERIFY_ARE_EQUAL(255, green.G); - VERIFY_ARE_EQUAL(0, green.B); - - auto blueHsl = HSL{ 240.f, 100.f, 50.f }; - auto blue = ColorHelper::HslToRgb(blueHsl); - VERIFY_ARE_EQUAL(0, blue.R); - VERIFY_ARE_EQUAL(0, blue.G); - VERIFY_ARE_EQUAL(255, blue.B); - - auto darkTurquoiseHsl = HSL{ 181.f, 100.f, 41.f }; - auto darkTurquoise = ColorHelper::HslToRgb(darkTurquoiseHsl); - VERIFY_ARE_EQUAL(0, darkTurquoise.R); - VERIFY_ARE_EQUAL(206, darkTurquoise.G); - VERIFY_ARE_EQUAL(209, darkTurquoise.B); - - auto darkVioletHsl = HSL{ 282.f, 100.f, 41.4f }; - auto darkViolet = ColorHelper::HslToRgb(darkVioletHsl); - VERIFY_ARE_EQUAL(148, darkViolet.R); - VERIFY_ARE_EQUAL(0, darkViolet.G); - VERIFY_ARE_EQUAL(211, darkViolet.B); - - auto whiteHsl = HSL{ 360.f, 100.f, 100.f }; - auto white = ColorHelper::HslToRgb(whiteHsl); - VERIFY_ARE_EQUAL(255, white.R); - VERIFY_ARE_EQUAL(255, white.G); - VERIFY_ARE_EQUAL(255, white.B); - - auto blackHsl = HSL{ 0.f, 0.f, 0.f }; - auto black = ColorHelper::HslToRgb(blackHsl); - VERIFY_ARE_EQUAL(0, black.R); - VERIFY_ARE_EQUAL(0, black.G); - VERIFY_ARE_EQUAL(0, black.B); - } - - void ColorHelperTests::LuminanceTests() - { - auto darkTurquoiseLuminance = ColorHelper::GetLuminance(winrt::Windows::UI::Colors::DarkTurquoise()); - VERIFY_ARE_EQUAL(48.75f, darkTurquoiseLuminance * 100); - auto darkVioletLuminance = ColorHelper::GetLuminance(winrt::Windows::UI::Colors::DarkViolet()); - VERIFY_ARE_EQUAL(11.f, darkVioletLuminance * 100); - auto magentaLuminance = ColorHelper::GetLuminance(winrt::Windows::UI::Colors::Magenta()); - VERIFY_ARE_EQUAL(28.48f, magentaLuminance * 100); - } -} diff --git a/src/cascadia/ut_app/TerminalApp.UnitTests.vcxproj b/src/cascadia/ut_app/TerminalApp.UnitTests.vcxproj index 608bce64b6..1eba2400bb 100644 --- a/src/cascadia/ut_app/TerminalApp.UnitTests.vcxproj +++ b/src/cascadia/ut_app/TerminalApp.UnitTests.vcxproj @@ -21,17 +21,11 @@ - - - Create - - NotUsing - diff --git a/src/renderer/atlas/AtlasEngine.cpp b/src/renderer/atlas/AtlasEngine.cpp index 6bebd719e8..af9a92f89a 100644 --- a/src/renderer/atlas/AtlasEngine.cpp +++ b/src/renderer/atlas/AtlasEngine.cpp @@ -322,7 +322,7 @@ CATCH_RETURN() auto misc = _api.s.write()->misc.write(); misc->selectionColor = newSelectionColor; // Select a black or white foreground based on the perceptual lightness of the background. - misc->selectionForeground = ColorFix::GetLuminosity(newSelectionColor) < 0.5f ? 0xffffffff : 0xff000000; + misc->selectionForeground = ColorFix::GetLightness(newSelectionColor) < 0.5f ? 0xffffffff : 0xff000000; // We copied the selection colors into _p during StartPaint, which happened just before PrepareRenderInfo // This keeps their generations in sync. diff --git a/src/types/ColorFix.cpp b/src/types/ColorFix.cpp index 7648de2262..d5a5fd1cd5 100644 --- a/src/types/ColorFix.cpp +++ b/src/types/ColorFix.cpp @@ -209,7 +209,14 @@ COLORREF ColorFix::GetPerceivableColor(COLORREF color, COLORREF reference, float return linearToColorref(oklab::oklab_to_linear_srgb(colorOklab)) | (color & 0xff000000); } -float ColorFix::GetLuminosity(COLORREF color) noexcept +COLORREF ColorFix::AdjustLightness(COLORREF color, float delta) noexcept +{ + auto lab = oklab::linear_srgb_to_oklab(colorrefToLinear(color)); + lab.l = saturate(lab.l + delta); + return linearToColorref(oklab::oklab_to_linear_srgb(lab)) | (color & 0xff000000); +} + +float ColorFix::GetLightness(COLORREF color) noexcept { return oklab::linear_srgb_to_oklab(colorrefToLinear(color)).l; } diff --git a/src/types/inc/ColorFix.hpp b/src/types/inc/ColorFix.hpp index 24c4cf79f3..60a7338731 100644 --- a/src/types/inc/ColorFix.hpp +++ b/src/types/inc/ColorFix.hpp @@ -10,5 +10,6 @@ namespace ColorFix { COLORREF GetPerceivableColor(COLORREF color, COLORREF reference, float minSquaredDistance) noexcept; - float GetLuminosity(COLORREF color) noexcept; + COLORREF AdjustLightness(COLORREF color, float delta) noexcept; + float GetLightness(COLORREF color) noexcept; }