src/recolor-xfwm4-png.py 2.5 K raw
1
#!/usr/bin/env python3
2
"""Recolour the xfwm4 PNGs that have no SVG source.
3
4
Nine frame pieces -- the thin edge strips and the menu button states -- ship
5
only as PNGs upstream, with no SVG to re-render from. They are flat fills with
6
at most a pixel of antialiasing at the corners, so they are remapped in place:
7
no resampling, no rendering, and nothing to install. Upstream stores them as
8
indexed images at 1x but as RGBA at some of the hidpi sizes, so both are
9
handled. Everything else in xfwm4/ comes from render-xfwm4.sh.
10
"""
11
12
import os
13
import sys
14
15
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "lib"))
16
17
import darkmatter as dm
18
from png import Png
19
from remap import Remapper
20
21
NO_SVG = [
22
    "bottom-inactive", "bottom-left-inactive", "bottom-right-active",
23
    "left-active", "left-inactive", "menu-inactive", "menu-prelight",
24
    "menu-pressed", "right-inactive",
25
]
26
27
# Black and white are anchored to themselves so the corner antialiasing, which
28
# blends the frame colour toward the window's outer outline, follows along.
29
#
30
# The Darkmatter targets are anchored to themselves as well, which makes this
31
# script idempotent: an already-converted file matches those exactly and maps
32
# to itself, instead of being re-read as a Nordic blend and drifting a little
33
# darker on every run. render-xfwm4.sh calls this after rendering, so it does
34
# get run more than once.
35
HOVER_TINT = "#131214"
36
37
ANCHORS = [
38
    (dm.rgb("#353c4a"), dm.rgb(dm.DARK)),
39
    (dm.rgb("#363d4b"), dm.rgb(HOVER_TINT)),   # the menu button's hover tint
40
    (dm.rgb("#000000"), dm.rgb("#000000")),
41
    (dm.rgb("#ffffff"), dm.rgb("#ffffff")),
42
    (dm.rgb(dm.DARK), dm.rgb(dm.DARK)),
43
    (dm.rgb(HOVER_TINT), dm.rgb(HOVER_TINT)),
44
]
45
46
DIRS = [
47
    "xfwm4",
48
    "xfwm4/Darkmatter-hdpi/xfwm4",
49
    "xfwm4/Darkmatter-xhdpi/xfwm4",
50
]
51
52
53
def main():
54
    remap = Remapper(ANCHORS)
55
    done = 0
56
    for d in DIRS:
57
        for name in NO_SVG:
58
            path = os.path.join(d, name + ".png")
59
            if not os.path.exists(path):
60
                continue
61
            img = Png(path)
62
            if img.color_type == 3:
63
                img.set_palette([remap(c) for c in img.palette()])
64
            elif img.color_type == 6:
65
                img.set_rgba([remap(p[:3]) + (p[3],) for p in img.rgba()])
66
            else:
67
                print("  skipped (colour type %d): %s" % (img.color_type, path))
68
                continue
69
            img.save()
70
            done += 1
71
    print("recoloured %d frame PNGs" % done)
72
73
74
if __name__ == "__main__":
75
    main()