mirror of
git://f0xx.org/ac/ac-be-hub
synced 2026-07-29 05:58:59 +03:00
196 lines
5.7 KiB
Python
196 lines
5.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Generate Quartz-style 7-segment LCD symbol set for hub clock rows."""
|
|
|
|
from __future__ import annotations
|
|
|
|
# Segment indices: 0=top, 1=upper-left, 2=upper-right, 3=mid, 4=lower-left, 5=lower-right, 6=bottom
|
|
PATTERNS: dict[str, list[int]] = {
|
|
" ": [],
|
|
"0": [0, 1, 2, 4, 5, 6],
|
|
"1": [2, 5],
|
|
"2": [0, 1, 3, 4, 6],
|
|
"3": [0, 1, 2, 3, 6],
|
|
"4": [1, 2, 3, 5],
|
|
"5": [0, 2, 3, 5, 6],
|
|
"6": [0, 2, 3, 4, 5, 6],
|
|
"7": [0, 1, 2],
|
|
"8": [0, 1, 2, 3, 4, 5, 6],
|
|
"9": [0, 1, 2, 3, 5, 6],
|
|
"A": [0, 1, 2, 3, 4, 5],
|
|
"B": [0, 1, 2, 3, 5, 6],
|
|
"C": [0, 1, 4, 6],
|
|
"D": [1, 2, 3, 5, 6],
|
|
"E": [0, 3, 4, 5, 6],
|
|
"F": [0, 3, 4, 5],
|
|
"G": [0, 2, 4, 5, 6],
|
|
"H": [1, 2, 3, 4, 5],
|
|
"I": [0, 6],
|
|
"J": [1, 2, 4, 5, 6],
|
|
"K": [1, 3, 4, 5],
|
|
"L": [4, 5, 6],
|
|
"M": [0, 1, 2, 4, 5],
|
|
"N": [1, 2, 4, 5],
|
|
"O": [0, 1, 2, 4, 5, 6],
|
|
"P": [0, 1, 2, 3, 4],
|
|
"Q": [0, 1, 2, 4, 5, 6],
|
|
"R": [0, 1, 2, 3, 4, 5],
|
|
"S": [0, 2, 3, 5, 6],
|
|
"T": [0, 3, 6],
|
|
"U": [1, 2, 4, 5, 6],
|
|
"V": [1, 4, 5],
|
|
"W": [1, 2, 4, 5, 6],
|
|
"X": [1, 2, 4, 5],
|
|
"Y": [2, 3, 5, 6],
|
|
"Z": [0, 1, 4, 6],
|
|
":": [10, 11],
|
|
"+": [12, 13],
|
|
"-": [14],
|
|
"/": [15, 16],
|
|
}
|
|
|
|
EXTRA_RECTS: dict[str, list[tuple]] = {
|
|
"M": [
|
|
("7.1", "5", "2.6", "13.2", 'transform="rotate(28 8.4 11.6)"'),
|
|
("14.3", "5", "2.6", "13.2", 'transform="rotate(-28 15.6 11.6)"'),
|
|
],
|
|
"N": [
|
|
("6.5", "6", "2.4", "12", 'transform="rotate(32 7.7 12)"'),
|
|
("14.8", "14", "2.4", "12", 'transform="rotate(32 16 20)"'),
|
|
],
|
|
"K": [
|
|
("10", "4", "2.2", "11", 'transform="rotate(-30 11.1 9.5)"'),
|
|
("10", "17", "2.2", "11", 'transform="rotate(30 11.1 22.5)"'),
|
|
],
|
|
"V": [
|
|
("7", "17", "2.2", "12", 'transform="rotate(24 8.1 23)"'),
|
|
("12", "17", "2.2", "12", 'transform="rotate(-24 13.1 23)"'),
|
|
],
|
|
"W": [
|
|
("5", "17", "2", "11", 'transform="rotate(18 6 22.5)"'),
|
|
("9.5", "17", "2", "11", 'transform="rotate(-18 10.5 22.5)"'),
|
|
("14", "17", "2", "11", 'transform="rotate(18 15 22.5)"'),
|
|
],
|
|
"X": [
|
|
("7", "5", "2.2", "11", 'transform="rotate(32 8.1 10.5)"'),
|
|
("11", "16", "2.2", "11", 'transform="rotate(-32 12.1 21.5)"'),
|
|
],
|
|
"Q": [
|
|
("14", "18", "2.2", "10", 'transform="rotate(38 15.1 23)"'),
|
|
],
|
|
"R": [
|
|
("12", "17", "2.2", "10", 'transform="rotate(38 13.1 22)"'),
|
|
],
|
|
"/": [
|
|
("13", "4", "2.2", "10", 'transform="rotate(52 14.1 9)"'),
|
|
("5", "18", "2.2", "10", 'transform="rotate(52 6.1 23)"'),
|
|
],
|
|
":": [
|
|
("4", "10", "4", "4"),
|
|
("4", "20", "4", "4"),
|
|
],
|
|
"+": [
|
|
("6", "8", "4", "16"),
|
|
("2", "14", "12", "4"),
|
|
],
|
|
"-": [
|
|
("2", "14", "12", "4"),
|
|
],
|
|
}
|
|
|
|
|
|
def _seg_defs(w: float, h: float) -> list[tuple[float, float, float, float]]:
|
|
h_pad = max(1.0, w * 0.12)
|
|
top_y = max(1.0, h * 0.04)
|
|
mid_y = h * 0.47
|
|
bot_y = h * 0.86
|
|
seg_w = max(6.0, w - h_pad * 2)
|
|
seg_h = max(2.0, h * 0.09)
|
|
v_w = max(2.0, w * 0.14)
|
|
v_h = max(6.0, h * 0.33)
|
|
left_x = max(1.0, h_pad * 0.45)
|
|
right_x = max(left_x + v_w + 1, w - left_x - v_w)
|
|
upper_y = top_y + seg_h
|
|
lower_y = mid_y + seg_h * 0.6
|
|
return [
|
|
(h_pad, top_y, seg_w, seg_h),
|
|
(left_x, upper_y, v_w, v_h),
|
|
(right_x, upper_y, v_w, v_h),
|
|
(h_pad, mid_y, seg_w, seg_h),
|
|
(left_x, lower_y, v_w, v_h),
|
|
(right_x, lower_y, v_w, v_h),
|
|
(h_pad, bot_y, seg_w, seg_h),
|
|
]
|
|
|
|
|
|
def _rect(x, y, width, height, extra: str = "") -> str:
|
|
attrs = f'x="{x}" y="{y}" width="{width}" height="{height}" rx="1"'
|
|
if extra:
|
|
return f"<rect {attrs} {extra}/>"
|
|
return f"<rect {attrs}/>"
|
|
|
|
|
|
def symbol_body(ch: str, width: int = 20) -> str:
|
|
h = 32.0
|
|
w = float(width)
|
|
segs = PATTERNS.get(ch, [])
|
|
parts: list[str] = []
|
|
defs = _seg_defs(w, h)
|
|
for idx in segs:
|
|
if idx < 7:
|
|
x, y, rw, rh = defs[idx]
|
|
parts.append(_rect(f"{x:.2f}", f"{y:.2f}", f"{rw:.2f}", f"{rh:.2f}"))
|
|
for item in EXTRA_RECTS.get(ch, []):
|
|
if len(item) == 4:
|
|
parts.append(_rect(*item))
|
|
else:
|
|
parts.append(_rect(item[0], item[1], item[2], item[3], item[4]))
|
|
return "".join(parts)
|
|
|
|
|
|
def symbol_id(ch: str) -> str:
|
|
if ch == " ":
|
|
return "qz-space"
|
|
if ch == ":":
|
|
return "qz-colon"
|
|
if ch == "+":
|
|
return "qz-plus"
|
|
if ch == "-":
|
|
return "qz-minus"
|
|
if ch == "/":
|
|
return "qz-slash"
|
|
if len(ch) == 1 and "0" <= ch <= "9":
|
|
return f"qz-{ch}"
|
|
if len(ch) == 1 and "A" <= ch <= "Z":
|
|
return f"qz-{ch}"
|
|
return f"qz-u{ord(ch):04x}"
|
|
|
|
|
|
def main() -> None:
|
|
chars = (
|
|
[" "] + [str(d) for d in range(10)] + [chr(c) for c in range(ord("A"), ord("Z") + 1)]
|
|
+ [":", "+", "-", "/"]
|
|
)
|
|
wide = set("MWKNQRX")
|
|
lines = [
|
|
'<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" '
|
|
'style="position:absolute;width:0;height:0;overflow:hidden">',
|
|
" <!-- Quartz (TS) style 7-segment LCD glyphs for hub timezone/date rows -->",
|
|
" <defs>",
|
|
]
|
|
for ch in chars:
|
|
width = 24 if ch in wide else (12 if ch == ":" else (16 if ch in "+-" else (14 if ch == "/" else (8 if ch == " " else 20))))
|
|
sid = symbol_id(ch)
|
|
body = symbol_body(ch, width)
|
|
lines.append(f' <symbol id="{sid}" viewBox="0 0 {width} 32">{body}</symbol>')
|
|
lines.append(" </defs>")
|
|
lines.append("</svg>")
|
|
out = "\n".join(lines) + "\n"
|
|
path = __file__.replace("build_quartz_alphabet.py", "quartz-alphabet.svg")
|
|
with open(path, "w", encoding="utf-8") as fh:
|
|
fh.write(out)
|
|
print(f"Wrote {path} ({len(chars)} symbols)")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|