#!/usr/bin/env python3 """Recover share/logo.txt from the oligarchy.fyi logo SVG. The site's logo is not artwork — it is a vectorised
 of block characters,
which the page's own stylesheet says outright ("Vector, not a 
: ... The
geometry is JetBrains Mono's own, so it draws what the 
 was meant to look
like"). Chrome's per-glyph rounding was knocking the rows out of column on
phones, so they shipped the outlines instead.

That means the banner does not have to be re-drawn or rasterised, which is what
loses the letterforms: every rect in the path lands exactly on a 100 x 9
character grid, and each one names the glyph that drew it.

    width  600 + n*557.5   a run of n+1 full-width cells   (557.5 = the advance)
    width  300             one half-width cell             -> left half block
    height 1320            the full character box          -> full block
    height 660 at cell top                                 -> upper half block
    height 660 at cell top + 660                           -> lower half block

Decoding each rect into the four quadrants of its cells and reading them back
out reproduces the original text exactly, glyph for glyph.
"""

import re
import sys
from pathlib import Path

CELL_W = 557.5      # JetBrains Mono advance width in the SVG's units
LINE_H = 1093.75    # line height
TOP = -113.125      # y of the first row
GLYPH_W = 600.0     # block glyphs overdraw the advance slightly, so runs seam-lessly
HALF_H = 660.0
COLS, ROWS = 100, 9

# (top-left, top-right, bottom-left, bottom-right) -> block character
QUADRANTS = {
    (0, 0, 0, 0): " ", (1, 0, 0, 0): "▘", (0, 1, 0, 0): "▝", (0, 0, 1, 0): "▖",
    (0, 0, 0, 1): "▗", (1, 1, 0, 0): "▀", (0, 0, 1, 1): "▄", (1, 0, 1, 0): "▌",
    (0, 1, 0, 1): "▐", (1, 0, 0, 1): "▚", (0, 1, 1, 0): "▞", (1, 1, 1, 0): "▛",
    (1, 1, 0, 1): "▜", (1, 0, 1, 1): "▙", (0, 1, 1, 1): "▟", (1, 1, 1, 1): "█",
}

RECT = re.compile(r"M(-?[\d.]+) (-?[\d.]+)h(-?[\d.]+)v(-?[\d.]+)h(-?[\d.]+)z")


def decode(svg: str) -> str:
    path = re.search(r'\sd="([^"]+)"', svg)
    if not path:
        sys.exit("No path data in the SVG")

    cells = [[[False] * 4 for _ in range(COLS)] for _ in range(ROWS)]

    for match in RECT.finditer(path.group(1)):
        x, y, w, h, _ = (float(v) for v in match.groups())
        col = round(x / CELL_W)

        # A rect either starts at the top of a row or halfway down it; which one
        # is what separates an upper half block from a lower one.
        offset = (y - TOP) / LINE_H
        if abs(offset - round(offset)) < 1e-6:
            row, at_top = round(offset), True
        else:
            row, at_top = round((y - TOP - HALF_H) / LINE_H), False

        if w == GLYPH_W / 2:
            span, parts = 1, (0, 2)                       # ▌
        else:
            span = round((w - GLYPH_W) / CELL_W) + 1
            parts = (0, 1, 2, 3) if h != HALF_H else (0, 1) if at_top else (2, 3)

        for c in range(col, col + span):
            for part in parts:
                cells[row][c][part] = True

    rows = ("".join(QUADRANTS[tuple(int(q) for q in cell)] for cell in row).rstrip()
            for row in cells)
    return "\n".join(rows) + "\n"


def main() -> None:
    here = Path(__file__).resolve().parent.parent
    svg = here / "share" / "oligarchy-logo.svg"
    out = here / "share" / "logo.txt"

    art = decode(svg.read_text())
    out.write_text(art)

    lines = art.splitlines()
    glyphs = "".join(sorted(set(art) - {"\n", " "}))
    print(f"Wrote {out} ({max(map(len, lines))} x {len(lines)}, glyphs: {glyphs})")


if __name__ == "__main__":
    main()