[LyX/master] Unbreak foreground/background color adaptation with transparent backgrounds
Juergen Spitzmueller <[email protected]> Sun, 05 Jul 2026 11:19:11 +0000
| Newsgroups | gmane.editors.lyx.cvs |
|---|---|
| Message-ID | <[email protected]> |
commit efec7bd2e2b56c24a089c4c4d3188635ae33fdf5 Author: Juergen Spitzmueller <[email protected]> Date: Sun Jul 5 13:18:09 2026 +0200 Unbreak foreground/background color adaptation with transparent backgrounds --- src/RowPainter.cpp | 9 ++++++--- src/frontends/Application.h | 5 +++-- src/frontends/qt/ColorCache.cpp | 27 +++++++++++++++++++++++---- src/frontends/qt/ColorCache.h | 5 ++++- src/frontends/qt/GuiApplication.cpp | 4 ++-- src/frontends/qt/GuiApplication.h | 2 +- src/frontends/qt/GuiWorkArea.cpp | 12 +++++++----- src/insets/Inset.cpp | 21 ++++++++++++++------- 8 files changed, 60 insertions(+), 25 deletions(-) diff --git a/src/RowPainter.cpp b/src/RowPainter.cpp index 0d01ac1bcc..fae564ce3b 100644 --- a/src/RowPainter.cpp +++ b/src/RowPainter.cpp @@ -258,12 +258,15 @@ void RowPainter::paintStringAndSel(Row::Element const & e) const bool invert = false; if (theApp() && theApp()->isInDarkMode()) { + ColorCode cc = pi_.backgroundColor(&pi_.base.bv->buffer().inset()); if (e.font.fontInfo().color() == Color_none - && theApp()->isLightColor(rgbFromHexName(lcolor.getX11HexName(pi_.background_color, true)))) + && theApp()->isLightColor(argbFromHexName(lcolor.get32bitHexName(cc, true)), + argbFromHexName(lcolor.get32bitHexName("background", true)))) invert = true; - else if (pi_.background_color == Color_background + else if (cc == Color_background && lcolor.isStaticColor(e.font.fontInfo().color()) - && !theApp()->isLightColor(rgbFromHexName(lcolor.getX11HexName(e.font.fontInfo().color())))) + && !theApp()->isLightColor(argbFromHexName(lcolor.get32bitHexName(e.font.fontInfo().color())), + argbFromHexName(lcolor.get32bitHexName("background", true)))) invert = true; } diff --git a/src/frontends/Application.h b/src/frontends/Application.h index 3fa4fa4482..931de7849a 100644 --- a/src/frontends/Application.h +++ b/src/frontends/Application.h @@ -220,9 +220,10 @@ public: /** * @return true this is a relatively light color - * depending on relative luminance + * depending on relative luminance. + * Transparent colors are overlayed with the background. */ - virtual bool isLightColor(RGBColor const & rgb) = 0; + virtual bool isLightColor(ARGBColor const & fg, ARGBColor const & bg) = 0; /** Eg, passing Color_black returns "000000", * passing Color_white returns "ffffff". diff --git a/src/frontends/qt/ColorCache.cpp b/src/frontends/qt/ColorCache.cpp index 5cd1207e48..fadaa153c6 100644 --- a/src/frontends/qt/ColorCache.cpp +++ b/src/frontends/qt/ColorCache.cpp @@ -169,20 +169,23 @@ bool ColorCache::isDarkMode() const } -bool ColorCache::isLightColor(RGBColor const & rgb) +bool ColorCache::isLightColor(ARGBColor const & fg, ARGBColor const & bg) { + // Overlay on background (necessary with transparency) + ARGBColor const & argb = colorOverlay(fg, bg); + // RGB to sRGB - double r = rgb.r / 255.0; + double r = argb.r / 255.0; if (r <= 0.04045) r = r / 12.92; else r = pow((r + 0.055) / 1.055, 2.4); - double g = rgb.g / 255.0; + double g = argb.g / 255.0; if (g <= 0.04045) g = g / 12.92; else g = pow((g + 0.055) / 1.055, 2.4); - double b = rgb.b / 255.0; + double b = argb.b / 255.0; if (b <= 0.04045) b = b / 12.92; else @@ -224,6 +227,22 @@ QPixmap ColorCache::mergePixmaps(QPixmap const *fg, QPixmap const *bg) } +ARGBColor ColorCache::colorOverlay(ARGBColor const & fg, ARGBColor const & bg) +{ + int red, green, blue, alpha; + + auto fg_weight = fg.a; + auto bg_weight = 1 - fg.a; + + red = std::round((fg_weight * fg.r + bg_weight * bg.r) * 255); + green = std::round((fg_weight * fg.g + bg_weight * bg.g) * 255); + blue = std::round((fg_weight*fg.b + bg_weight * bg.b) * 255); + alpha = std::round((1 - (1 - fg.a) * (1 - bg.a) * 255)); + + return ARGBColor(red, green, blue, alpha); +} + + QColor const rgb2qcolor(RGBColor const & rgb) { return QColor(rgb.r, rgb.g, rgb.b); diff --git a/src/frontends/qt/ColorCache.h b/src/frontends/qt/ColorCache.h index 617bae8e56..81644f03c0 100644 --- a/src/frontends/qt/ColorCache.h +++ b/src/frontends/qt/ColorCache.h @@ -52,7 +52,7 @@ public: * a dark one as contrast) depending on relative luminance * (cf. https://www.w3.org/TR/WCAG20/#relativeluminancedef) */ - bool isLightColor(RGBColor const & rgb); + bool isLightColor(ARGBColor const & fg, ARGBColor const & bg); /// change the undelying palette void setPalette(QPalette const pal) { pal_ = pal; clear(); } @@ -72,6 +72,9 @@ private: bool initialized_; /// QPalette pal_; + /// Overlay fg color on bg color + /// This is necessary with transparency in fg color + ARGBColor colorOverlay(ARGBColor const & fg, ARGBColor const & bg); }; /// diff --git a/src/frontends/qt/GuiApplication.cpp b/src/frontends/qt/GuiApplication.cpp index 532388a888..e48087bba6 100644 --- a/src/frontends/qt/GuiApplication.cpp +++ b/src/frontends/qt/GuiApplication.cpp @@ -3084,9 +3084,9 @@ bool GuiApplication::isInDarkMode() } -bool GuiApplication::isLightColor(RGBColor const & rgb) +bool GuiApplication::isLightColor(ARGBColor const & fg, ARGBColor const & bg) { - return colorCache().isLightColor(rgb); + return colorCache().isLightColor(fg, bg); } diff --git a/src/frontends/qt/GuiApplication.h b/src/frontends/qt/GuiApplication.h index 3f03ad1458..eff522eb3c 100644 --- a/src/frontends/qt/GuiApplication.h +++ b/src/frontends/qt/GuiApplication.h @@ -76,7 +76,7 @@ public: bool getRgbColor(ColorCode col, RGBColor & rgbcol) override; bool getArgbColor(ColorCode col, ARGBColor & argbcol) override; bool isInDarkMode() override; - bool isLightColor(RGBColor const & rgb) override; + bool isLightColor(ARGBColor const & fg, ARGBColor const & bg) override; std::string const hexName(ColorCode col) override; void registerSocketCallback(int fd, SocketCallback func) override; void unregisterSocketCallback(int fd) override; diff --git a/src/frontends/qt/GuiWorkArea.cpp b/src/frontends/qt/GuiWorkArea.cpp index 3fb3f26e79..b4b4b7e401 100644 --- a/src/frontends/qt/GuiWorkArea.cpp +++ b/src/frontends/qt/GuiWorkArea.cpp @@ -581,12 +581,14 @@ void GuiWorkArea::Private::drawCaret(QPainter & painter, int horiz_offset) const && buffer_view_->getCaretBackground() != "none" && ((guiApp->colorCache().isDarkMode() && guiApp->colorCache().isLightColor( - rgbFromHexName(lcolor.getX11HexName( - buffer_view_->getCaretBackground(), true)))) + argbFromHexName(lcolor.get32bitHexName( + buffer_view_->getCaretBackground(), true)), + argbFromHexName(lcolor.get32bitHexName("background", true)))) || (!guiApp->colorCache().isDarkMode() - && !guiApp->colorCache().isLightColor(rgbFromHexName( - lcolor.getX11HexName( - buffer_view_->getCaretBackground())))))) + && !guiApp->colorCache().isLightColor(argbFromHexName( + lcolor.get32bitHexName( + buffer_view_->getCaretBackground())), + argbFromHexName(lcolor.get32bitHexName("background")))))) ? guiApp->colorCache().get(Color_cursor_inverted) : guiApp->colorCache().get(Color_cursor); painter.setPen(color); diff --git a/src/insets/Inset.cpp b/src/insets/Inset.cpp index 14f93c9d2b..0924136107 100644 --- a/src/insets/Inset.cpp +++ b/src/insets/Inset.cpp @@ -308,12 +308,15 @@ Color Inset::getModeDependentColor(PainterInfo & pi) const FontInfo font = pi.base.font; bool invert = false; if (theApp() && theApp()->isInDarkMode()) { + ColorCode cc = pi.backgroundColor(this); if (font.color() == Color_none - && theApp()->isLightColor(rgbFromHexName(lcolor.getX11HexName(pi.background_color, true)))) + && theApp()->isLightColor(argbFromHexName(lcolor.get32bitHexName(cc, true)), + argbFromHexName(lcolor.get32bitHexName("background", true)))) invert = true; - else if (pi.background_color == Color_background + else if (cc == Color_background && font.color() != Color_none - && !theApp()->isLightColor(rgbFromHexName(lcolor.getX11HexName(font.color())))) + && !theApp()->isLightColor(argbFromHexName(lcolor.get32bitHexName(font.color())), + argbFromHexName(lcolor.get32bitHexName("background", true)))) invert = true; } Color rc = font.realColor(invert); @@ -331,16 +334,20 @@ Color Inset::getModeDependentColor(ColorCode const fgc, ColorCode const bgc) con bool darken = false; if (theApp() && theApp()->isInDarkMode()) { if (fgc == Color_none - && theApp()->isLightColor(rgbFromHexName(lcolor.getX11HexName(bgc, true)))) + && theApp()->isLightColor(argbFromHexName(lcolor.getX11HexName(bgc, true)), + argbFromHexName(lcolor.get32bitHexName("background", true)))) invert = true; else if (bgc == Color_background && fgc != Color_none - && !theApp()->isLightColor(rgbFromHexName(lcolor.getX11HexName(fgc, true)))) + && !theApp()->isLightColor(argbFromHexName(lcolor.getX11HexName(fgc, true)), + argbFromHexName(lcolor.get32bitHexName("background", true)))) invert = true; else if (bgc != Color_background && fgc != Color_none - && theApp()->isLightColor(rgbFromHexName(lcolor.getX11HexName(fgc, true))) - && theApp()->isLightColor(rgbFromHexName(lcolor.getX11HexName(bgc, true)))) + && theApp()->isLightColor(argbFromHexName(lcolor.getX11HexName(fgc, true)), + argbFromHexName(lcolor.get32bitHexName(bgc, true))) + && theApp()->isLightColor(argbFromHexName(lcolor.getX11HexName(bgc, true)), + argbFromHexName(lcolor.get32bitHexName("background", true)))) darken = true; } Color res = fgc; -- lyx-cvs mailing list [email protected] https://lists.lyx.org/mailman/listinfo/lyx-cvs