virtuality icon indicating copy to clipboard operation
virtuality copied to clipboard

Invert icons in toolbar if toolbar is inverted

Open beojan opened this issue 9 years ago • 7 comments

With KF5, icon themes are using monochrome toolbar icons. Because these icons are also used in the main window in some applications (e.g, kwrite's find bar), when the toolbar is inverted, neither the light background version nor the dark background version of the themes are satisfactory.

Can you invert the icons if the toolbar is inverted, so the light version can be used?

beojan avatar Dec 12 '15 20:12 beojan

With KF5, icon themes "Icon theme" - Breeze in particular. And it's heavily critized for its complete lack of inner contrast.

Can you invert the icons if the toolbar is inverted To a certain degree. You probably noticed the monochromatically tinted hover effect. This can applied with any (the foreground of the toolbar) color, but a) There's nothing such as a perfect monochromatizing. b) It of course implies some CPU overhead.

Assuming (b) is of no major concern, the remaining problem is (a) You might have noticed that not all breeze icons are strictly black/white. Sometimes colored variants will just show up in the toolbar and sometimes the toolbar icon is actually colored (usually red)

This is a qnd hack to do this (it's not configurable and not very efficient either, but you can see the result)

diff --git a/toolbars.cpp b/toolbars.cpp
index a1a75da..7b0f6b4 100644
--- a/toolbars.cpp
+++ b/toolbars.cpp
@@ -169,6 +169,7 @@ Style::drawToolButtonLabel(const QStyleOption *option, QPainter *painter, const
         const int style = config.btn.tool.disabledStyle;
 //         const QIcon::State state = toolbutton->state & State_On ? QIcon::On : QIcon::Off;
         pm = toolbutton->icon.pixmap(RECT.size().boundedTo(pmSize), isEnabled || style ? QIcon::Normal : QIcon::Disabled, QIcon::Off);
+        pm = FX::tintedIcon(pm, 1, 1, text);
 #if 0   // this is -in a way- the way it should be done..., but KIconLoader gives a shit on this or anything else
         if (!isEnabled)
             pm = generatedIconPixmap(QIcon::Disabled, pm, toolbutton);

luebking avatar Dec 12 '15 22:12 luebking

This seems to work with Breeze, but weirdly, not with Papirus (icons in toolbar are completely dark).

beojan avatar Dec 13 '15 09:12 beojan

Papirus With what? Link?

luebking avatar Dec 13 '15 09:12 luebking

https://github.com/varlesh/papirus-pack-kde/tree/master/icons

beojan avatar Dec 13 '15 13:12 beojan

Ah, ok - I figured it would be some icon theme.

As mentione, such as a perfect monochromatizing does not exist, the algorithm I implemented favors bright colors (for tinting, dark colors rather turn translucent - the thing was done for icon highlighting)

The icon theme uses fully back icons with a 50% opacity where this fails miserably - the icons turn entirely transparent.

diff --git a/FX.cpp b/FX.cpp
index 95eed4b..118f727 100644
--- a/FX.cpp
+++ b/FX.cpp
@@ -109,16 +109,40 @@ FX::tintedIcon(QPixmap &pix, int step, int maxSteps, QColor tint)
         int size = img.width() * img.height();
         QRgb *pixel = (QRgb*)img.bits();
         const int r = tint.red(), g = tint.green(), b = tint.blue();
+        int minV = 255, maxV = 0;
+        bool mono = true;
         for (int i = 0; i < size; ++i) {
-            if (int a = qAlpha(*pixel)) {
+            if (qAlpha(*pixel) > 24) {
                 const int v = qGray(*pixel);
-                // stretch alpha
-                a = 255 - v*a/255;
-                a = 255 - a*a/255;
-                *pixel = qRgba(r, g, b, a);
+                maxV = qMax(v, maxV);
+                minV = qMin(v, minV);
+                if (maxV - minV > 10) {
+                    mono = false;
+                    break;
+                }
             }
             ++pixel;
         }
+        pixel = (QRgb*)img.bits();
+        if (mono) {
+            for (int i = 0; i < size; ++i) {
+                if (int a = qAlpha(*pixel)) {
+                    *pixel = qRgba(r, g, b, qAlpha(*pixel));
+                }
+                ++pixel;
+            }
+        } else {
+            for (int i = 0; i < size; ++i) {
+                if (int a = qAlpha(*pixel)) {
+                    const int v = qGray(*pixel);
+                    // stretch alpha
+                    a = 255 - v*a/255;
+                    a = 255 - a*a/255;
+                    *pixel = qRgba(r, g, b, a);
+                }
+                ++pixel;
+            }
+        }
         tintedIcon[1] = QPixmap::fromImage(img);
         lastIconPix[1] = pix.cacheKey();
     }
diff --git a/toolbars.cpp b/toolbars.cpp
index a1a75da..7b0f6b4 100644
--- a/toolbars.cpp
+++ b/toolbars.cpp
@@ -169,6 +169,7 @@ Style::drawToolButtonLabel(const QStyleOption *option, QPainter *painter, const
         const int style = config.btn.tool.disabledStyle;
 //         const QIcon::State state = toolbutton->state & State_On ? QIcon::On : QIcon::Off;
         pm = toolbutton->icon.pixmap(RECT.size().boundedTo(pmSize), isEnabled || style ? QIcon::Normal : QIcon::Disabled, QIcon::Off);
+        pm = FX::tintedIcon(pm, 1, 1, text);
 #if 0   // this is -in a way- the way it should be done..., but KIconLoader gives a shit on this or anything else
         if (!isEnabled)
             pm = generatedIconPixmap(QIcon::Disabled, pm, toolbutton);

luebking avatar Dec 13 '15 21:12 luebking

That works well (though it appears icons need to be inverted everywhere there is an inverted background [e.g. modal dialogs]).

Thanks.

beojan avatar Dec 14 '15 15:12 beojan

Yeah, and especially modal dialogs are pretty much when this approach will reach its limitations.

The style doesn't paint all icons in ann elements that can reside in a modal dialog, nor does it necessarily know "this icon will show up in a modal dialog" when it paints it (and checking that when posible isn't for free either) On top of that, one might not even want to tint the icons which eg. reside in the icon view of a file dialog (one could catch that to a certain degree by tinting monochromatic sources only)

Whenever an icon theme comes with icons w/o inner contrast it pretty much says "use me in a color environment that I was especially designed for or not at all" - that's why breeze is heavily critizised :-(

luebking avatar Dec 14 '15 18:12 luebking