From 8cb9272458dd603fe4656af21d5b418f5acb5b9b Mon Sep 17 00:00:00 2001 From: Paul Kulchenko Date: Wed, 4 Dec 2019 19:26:45 +0100 Subject: [PATCH] Make wxAuiGenericTabArt text readable on dark background Select the appropriate text colour depending on the background to ensure that it remains readable even when using themes/modes using dark background colours -- which wasn't at all the case before. Closes #18601. --- src/aui/dockart.cpp | 36 ++++++++++++++++++++++++++++-------- src/aui/tabart.cpp | 36 +++++++++++------------------------- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/src/aui/dockart.cpp b/src/aui/dockart.cpp index 4ebf227714..ab31a7ab60 100644 --- a/src/aui/dockart.cpp +++ b/src/aui/dockart.cpp @@ -57,14 +57,6 @@ #include -// -- wxAuiDefaultDockArt class implementation -- - -// wxAuiDefaultDockArt is an art provider class which does all of the drawing for -// wxAuiManager. This allows the library caller to customize the dock art -// (probably by deriving from this class), or to completely replace all drawing -// with custom dock art (probably by writing a new stand-alone class derived -// from the wxAuiDockArt base class). The active dock art class can be set via -// wxAuiManager::SetDockArt() wxColor wxAuiLightContrastColour(const wxColour& c) { int amount = 120; @@ -77,6 +69,26 @@ wxColor wxAuiLightContrastColour(const wxColour& c) return c.ChangeLightness(amount); } +inline float wxAuiGetSRGB(float r) { + return r <= 0.03928 ? r/12.92 : pow((r+0.055)/1.055, 2.4); +} + +float wxAuiGetRelativeLuminance(const wxColour& c) +{ + // based on https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef + return 0.2126 * wxAuiGetSRGB(c.Red()/255.0) + + 0.7152 * wxAuiGetSRGB(c.Green()/255.0) + + 0.0722 * wxAuiGetSRGB(c.Blue()/255.0); +} + +float wxAuiGetColourContrast(const wxColour& c1, const wxColour& c2) +{ + // based on https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast7.html + float L1 = wxAuiGetRelativeLuminance(c1); + float L2 = wxAuiGetRelativeLuminance(c2); + return L1 > L2 ? (L1 + 0.05) / (L2 + 0.05) : (L2 + 0.05) / (L1 + 0.05); +} + // wxAuiBitmapFromBits() is a utility function that creates a // masked bitmap from raw bits (XBM format) wxBitmap wxAuiBitmapFromBits(const unsigned char bits[], int w, int h, @@ -174,6 +186,14 @@ wxString wxAuiChopText(wxDC& dc, const wxString& text, int max_size) return ret; } +// -- wxAuiDefaultDockArt class implementation -- + +// wxAuiDefaultDockArt is an art provider class which does all of the drawing for +// wxAuiManager. This allows the library caller to customize the dock art +// (probably by deriving from this class), or to completely replace all drawing +// with custom dock art (probably by writing a new stand-alone class derived +// from the wxAuiDockArt base class). The active dock art class can be set via +// wxAuiManager::SetDockArt() wxAuiDefaultDockArt::wxAuiDefaultDockArt() { UpdateColoursFromSystem(); diff --git a/src/aui/tabart.cpp b/src/aui/tabart.cpp index 7c512f95d7..acab965bac 100644 --- a/src/aui/tabart.cpp +++ b/src/aui/tabart.cpp @@ -74,6 +74,7 @@ wxBitmap wxAuiBitmapFromBits(const unsigned char bits[], int w, int h, // This function is defined in dockart.cpp. void wxAuiScaleBitmap(wxBitmap& bmp, double scale); +float wxAuiGetColourContrast(const wxColour& c1, const wxColour& c2); wxString wxAuiChopText(wxDC& dc, const wxString& text, int max_size); @@ -267,14 +268,6 @@ void wxAuiGenericTabArt::DrawBackground(wxDC& dc, // draw background int topLightness = 90; int bottomLightness = 170; - if ((m_baseColour.Red() < 75) - && (m_baseColour.Green() < 75) - && (m_baseColour.Blue() < 75)) - { - //dark mode, we cannot go very light - topLightness = 90; - bottomLightness = 110; - } wxColor top_color = m_baseColour.ChangeLightness(topLightness); wxColor bottom_color = m_baseColour.ChangeLightness(bottomLightness); @@ -428,7 +421,10 @@ void wxAuiGenericTabArt::DrawTab(wxDC& dc, int drawn_tab_yoff = border_points[1].y; int drawn_tab_height = border_points[0].y - border_points[1].y; - + bool isdark = (m_baseColour.Red() < 75) + && (m_baseColour.Green() < 75) + && (m_baseColour.Blue() < 75); + wxColor back_color = m_baseColour; if (page.active) { // draw active tab @@ -441,13 +437,12 @@ void wxAuiGenericTabArt::DrawTab(wxDC& dc, // this white helps fill out the gradient at the top of the tab wxColor gradient = *wxWHITE; - if ((m_baseColour.Red() < 75) - && (m_baseColour.Green() < 75) - && (m_baseColour.Blue() < 75)) + if (isdark) { //dark mode, we go darker gradient = m_activeColour.ChangeLightness(70); } + back_color = gradient; dc.SetPen(wxPen(gradient)); dc.SetBrush(wxBrush(gradient)); @@ -488,9 +483,7 @@ void wxAuiGenericTabArt::DrawTab(wxDC& dc, // -- draw top gradient fill for glossy look wxColor top_color = m_baseColour; wxColor bottom_color = top_color.ChangeLightness(160); - if ((m_baseColour.Red() < 75) - && (m_baseColour.Green() < 75) - && (m_baseColour.Blue() < 75)) + if (isdark) { //dark mode, we go darker top_color = m_activeColour.ChangeLightness(70); @@ -585,16 +578,9 @@ void wxAuiGenericTabArt::DrawTab(wxDC& dc, tab_width - (text_offset-tab_x) - close_button_width); // draw tab text -#if defined( __WXMAC__ ) - if (page.active) - { - dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_CAPTIONTEXT)); - } - else - { - dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_INACTIVECAPTIONTEXT)); - } -#endif + wxColor font_color = wxAuiGetColourContrast(*wxWHITE, back_color) + > wxAuiGetColourContrast(*wxBLACK, back_color) ? *wxWHITE : *wxBLACK; + dc.SetTextForeground(font_color); dc.DrawText(draw_text, text_offset, drawn_tab_yoff + (drawn_tab_height)/2 - (texty/2) - 1);