diff options
| author | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-04-05 17:53:13 +1100 |
|---|---|---|
| committer | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-04-05 17:53:13 +1100 |
| commit | f9c60a483d41289c149f52939bfc0e0680077ff4 (patch) | |
| tree | e4fe1ff1a3558af0371b8176a4848180486cabca /scheme/autoadjust.py | |
| parent | install: add dep for app2unit (diff) | |
| download | caelestia-cli-f9c60a483d41289c149f52939bfc0e0680077ff4.tar.gz caelestia-cli-f9c60a483d41289c149f52939bfc0e0680077ff4.tar.bz2 caelestia-cli-f9c60a483d41289c149f52939bfc0e0680077ff4.zip | |
scheme: use material for colour gen
Replaces okolors
Also boost neutral chroma and all chroma
Diffstat (limited to 'scheme/autoadjust.py')
| -rwxr-xr-x | scheme/autoadjust.py | 98 |
1 files changed, 69 insertions, 29 deletions
diff --git a/scheme/autoadjust.py b/scheme/autoadjust.py index 0da2f0b..73deb88 100755 --- a/scheme/autoadjust.py +++ b/scheme/autoadjust.py @@ -72,6 +72,8 @@ colour_names = [ "error", ] +HLS = tuple[float, float, float] + def hex_to_rgb(hex: str) -> tuple[float, float, float]: """Convert a hex string to an RGB tuple in the range [0, 1].""" @@ -91,23 +93,29 @@ def hls_to_hex(h: str, l: str, s: str) -> str: return rgb_to_hex(hls_to_rgb(h, l, s)) -def adjust(hex: str, light: float = 0, sat: float = 0) -> str: - h, l, s = hex_to_hls(hex) - return hls_to_hex(h, max(0, min(1, l + light)), max(0, min(1, s + sat))) +def grayscale(hls: HLS, light: bool) -> HLS: + h, l, s = hls + return h, 0.5 - l / 2 if light else l / 2 + 0.5, 0 + +def mix(a: HLS, b: HLS, w: float) -> HLS: + h1, l1, s1 = a + h2, l2, s2 = b + return h1 * (1 - w) + h2 * w, l1 * (1 - w) + l2 * w, s1 * (1 - w) + s2 * w -def grayscale(hex: str, light: bool) -> str: - h, l, s = hex_to_hls(hex) - return hls_to_hex(h, 0.5 - l / 2 if light else l / 2 + 0.5, 0) +def darken(colour: HLS, amount: float) -> HLS: + h, l, s = colour + return h, max(0, l - amount), s -def distance(colour: str, base: str) -> float: - h1, l1, s1 = hex_to_hls(colour) + +def distance(colour: HLS, base: str) -> float: + h1, l1, s1 = colour h2, l2, s2 = hex_to_hls(base) return abs(h1 - h2) * 0.4 + abs(l1 - l2) * 0.3 + abs(s1 - s2) * 0.3 -def smart_sort(colours: list[str], base: list[str]) -> list[str]: +def smart_sort(colours: list[HLS], base: list[str]) -> dict[str, HLS]: sorted_colours = [None] * len(colours) distances = {} @@ -130,15 +138,7 @@ def smart_sort(colours: list[str], base: list[str]) -> list[str]: distances[colour].pop(0) - return [i[0] for i in sorted_colours] - - -def mix(a: str, b: str, w: float) -> str: - r1, g1, b1 = hex_to_rgb(a) - r2, g2, b2 = hex_to_rgb(b) - return rgb_to_hex( - (r1 * (1 - w) + r2 * w, g1 * (1 - w) + g2 * w, b1 * (1 - w) + b2 * w) - ) + return {colour_names[i]: c[0] for i, c in enumerate(sorted_colours)} def get_scheme(scheme: str) -> DynamicScheme: @@ -167,21 +167,61 @@ if __name__ == "__main__": colours_in = sys.argv[3] base = light_colours if light else dark_colours - MatScheme = get_scheme(scheme) + chroma_mult = 1.5 if light else 1.2 + + # Convert to HLS + colours = [hex_to_hls(c) for c in colours_in.split(" ")] + + # Sort colours and turn into dict + colours = smart_sort(colours, base) - colours = smart_sort(colours_in.split(" "), base) - for i, hex in enumerate(colours): + # Adjust colours + MatScheme = get_scheme(scheme) + for name, hls in colours.items(): if scheme == "monochrome": - colours[i] = grayscale(hex, light) + colours[name] = grayscale(hls, light) else: - argb = argb_from_rgb(int(hex[:2], 16), int(hex[2:4], 16), int(hex[4:], 16)) + argb = int(f"0xFF{hls_to_hex(*hls)}", 16) mat_scheme = MatScheme(Hct.from_int(argb), not light, 0) - primary = MaterialDynamicColors.primary.get_hct(mat_scheme) - colours[i] = "{:02X}{:02X}{:02X}".format(*primary.to_rgba()[:3]) + + colour = MaterialDynamicColors.primary.get_hct(mat_scheme) + + # Boost neutral scheme colours + if scheme == "neutral": + colour.chroma += 10 + + colour.chroma *= chroma_mult + + colours[name] = hex_to_hls("{:02X}{:02X}{:02X}".format(*colour.to_rgba()[:3])) # Success and error colours - colours.append(mix(colours[8], base[8], 0.8)) # Success (green) - colours.append(mix(colours[4], base[4], 0.8)) # Error (red) + colours["success"] = mix(colours["green"], hex_to_hls(base[8]), 0.8) + colours["error"] = mix(colours["red"], hex_to_hls(base[4]), 0.8) + + # Layers and accents + material = {} + primary_scheme = MatScheme(Hct.from_int(int(f"0xFF{colours_in.split(" ")[0]}", 16)), not light, 0) + for colour in vars(MaterialDynamicColors).keys(): + colour_name = getattr(MaterialDynamicColors, colour) + if hasattr(colour_name, "get_hct"): + rgb = colour_name.get_hct(primary_scheme).to_rgba()[:3] + material[colour] = hex_to_hls("{:02X}{:02X}{:02X}".format(*rgb)) + + colours["primary"] = material["primary"] + colours["secondary"] = material["secondary"] + colours["tertiary"] = material["tertiary"] + colours["text"] = material["onBackground"] + colours["subtext1"] = material["onSurfaceVariant"] + colours["subtext0"] = material["outline"] + colours["overlay2"] = mix(material["surface"], material["outline"], 0.86) + colours["overlay1"] = mix(material["surface"], material["outline"], 0.71) + colours["overlay0"] = mix(material["surface"], material["outline"], 0.57) + colours["surface2"] = mix(material["surface"], material["outline"], 0.43) + colours["surface1"] = mix(material["surface"], material["outline"], 0.29) + colours["surface0"] = mix(material["surface"], material["outline"], 0.14) + colours["base"] = material["surface"] + colours["mantle"] = darken(material["surface"], 0.03) + colours["crust"] = darken(material["surface"], 0.05) - for i, colour in enumerate(colours): - print(f"{colour_names[i]} {colour}") + for name, colour in colours.items(): + print(f"{name} {hls_to_hex(*colour)}") |