Skip to content

Fix dark icon generation

I was working on a PySide6 (Qt for Python) application and noticed that the breeze dark icons weren't always showing up dark. Eventually, looking through /usr/share/icons/breeze-dark I noticed that many of the breeze dark icons were, in fact, not dark.

The issue only happened with images that contained more than 1 ColorScheme CSS rule, like in state-ok.svg:

<style type="text/css" id="current-color-scheme">.ColorScheme-Text{color:#232629;}.ColorScheme-PositiveText { color: #27ae60; } </style>

These are supposed to be parsed individually and then, if it's a Text or Background color, have the color changed.

I found the issue is a simple regex oversight with greedy matching mashing multiple color tags in the svg's stylesheet together, thereby failing to recognize the type of tag, thus not substituting the colors.

Here a print debug of the steps performed in convertStylesheet:

  • Initial stylesheet: "\n .ColorScheme-Text {\n color:#7B7C7E;\n }\n .ColorScheme-Background{\n color:#EFF0F1;\n }\n .ColorScheme-Highlight{\n color:#3DAEE6;\n }\n .ColorScheme-ButtonText {\n color:#7B7C7E;\n }\n"
  • Stylesheet after removing whitespace: ".ColorScheme-Text{color:#7B7C7E;}.ColorScheme-Background{color:#EFF0F1;}.ColorScheme-Highlight{color:#3DAEE6;}.ColorScheme-ButtonText{color:#7B7C7E;}"
  • Matched class: "Text{color:#7B7C7E;}.ColorScheme-Background{color:#EFF0F1;}.ColorScheme-Highlight{color:#3DAEE6;}.ColorScheme-ButtonText" with color: "#7B7C7E"
  • Class-color map: QMap(("Text{color:#7B7C7E;}.ColorScheme-Background{color:#EFF0F1;}.ColorScheme-Highlight{color:#3DAEE6;}.ColorScheme-ButtonText", "#7B7C7E"))
  • Output after adding class "Text{color:#7B7C7E;}.ColorScheme-Background{color:#EFF0F1;}.ColorScheme-Highlight{color:#3DAEE6;}.ColorScheme-ButtonText" with color "#7B7C7E" : ".ColorScheme-Text{color:#7B7C7E;}.ColorScheme-Background{color:#EFF0F1;}.ColorScheme-Highlight{color:#3DAEE6;}.ColorScheme-ButtonText { color: #7B7C7E; } "
  • Final output: ".ColorScheme-Text{color:#7B7C7E;}.ColorScheme-Background{color:#EFF0F1;}.ColorScheme-Highlight{color:#3DAEE6;}.ColorScheme-ButtonText { color: #7B7C7E; } "

We see that it put all 3 tags into a single match.

Simply making the greedy match non-greedy, resulted in the following output:

  • Initial stylesheet: "\n .ColorScheme-Text {\n color:#7B7C7E;\n }\n .ColorScheme-Background{\n color:#EFF0F1;\n }\n .ColorScheme-Highlight{\n color:#3DAEE6;\n }\n .ColorScheme-ButtonText {\n color:#7B7C7E;\n }\n"
  • Stylesheet after removing whitespace: ".ColorScheme-Text{color:#7B7C7E;}.ColorScheme-Background{color:#EFF0F1;}.ColorScheme-Highlight{color:#3DAEE6;}.ColorScheme-ButtonText{color:#7B7C7E;}"
  • Matched class: "Text" with color: "#7B7C7E"
  • Matched class: "Background" with color: "#EFF0F1"
  • Matched class: "Highlight" with color: "#3DAEE6"
  • Matched class: "ButtonText" with color: "#7B7C7E"
  • Class-color map: QMap(("Background", "#2a2e32")("ButtonText", "#7B7C7E")("Highlight", "#3DAEE6")("Text", "#fcfcfc"))
  • Output after adding class "Background" with color "#2a2e32" : ".ColorScheme-Background { color: #2a2e32; } "
  • Output after adding class "ButtonText" with color "#7B7C7E" : ".ColorScheme-Background { color: #2a2e32; } .ColorScheme-ButtonText { color: #7B7C7E; } "
  • Output after adding class "Highlight" with color "#3DAEE6" : ".ColorScheme-Background { color: #2a2e32; } .ColorScheme-ButtonText { color: #7B7C7E; } .ColorScheme-Highlight { color: #3DAEE6; } "
  • Output after adding class "Text" with color "#fcfcfc" : ".ColorScheme-Background { color: #2a2e32; } .ColorScheme-ButtonText { color: #7B7C7E; } .ColorScheme-Highlight { color: #3DAEE6; } .ColorScheme-Text { color: #fcfcfc; } "
  • Final output: ".ColorScheme-Background { color: #2a2e32; } .ColorScheme-ButtonText { color: #7B7C7E; } .ColorScheme-Highlight { color: #3DAEE6; } .ColorScheme-Text { color: #fcfcfc; } "

Now all 4 tags are parsed separately, and the Text and Background classes are successfully color-swapped.

Before After
depression bliss

The Frameworks apparently recolor the icons at runtime, so you didn't end up seeing this issue in programs using the frameworks, but Qt doesn't recolor icons natively, so Qt programs (like those written with PySide, or even generic Qt apps in C++) had broken colors.

Since the breeze-dark export exists to cater to such apps, it is only right that this actually function.

BUG: 487235

Merge request reports