"""Canonical project, version, and static-family definitions for Ilta Mono.""" from __future__ import annotations from dataclasses import dataclass import os from pathlib import Path import re ROOT = Path(__file__).resolve().parents[1] VERSION_FILE = ROOT / "VERSION" FAMILY_NAME = "Ilta Mono" NERD_FAMILY_NAME = "Ilta Mono Nerd Font" FONT_AUTHORS = "Samhain (moonwit.ch) and Ilta (ilta.doll.systems)" HOMEPAGE_URL = "https://font.ilta.doll.systems/" REPOSITORY_URL = "https://tangled.org/alignment.removal.surgery/IltaMono" MAC_EPOCH_OFFSET = 2_082_844_800 # The approved release rhythm meets Valley's original 650u advance and the # compact 588u trial halfway: roomy enough to read, still unmistakably mono. CELL_WIDTH = 620 TYPOGRAPHIC_ASCENDER = 980 TYPOGRAPHIC_DESCENDER = -260 TYPOGRAPHIC_LINE_GAP = 0 TYPOGRAPHIC_ROW = TYPOGRAPHIC_ASCENDER - TYPOGRAPHIC_DESCENDER POWERLINE_OVERLAP = 8 @dataclass(frozen=True, slots=True) class ReleaseVersion: """A semantic release version and its OpenType 16.16 representation.""" major: int minor: int patch: int @classmethod def parse(cls, value: str) -> "ReleaseVersion": if re.fullmatch(r"[0-9]+\.[0-9]+\.[0-9]+", value) is None: raise ValueError(f"invalid semantic version: {value!r}") return cls(*(int(part) for part in value.split("."))) @property def semantic(self) -> str: return f"{self.major}.{self.minor}.{self.patch}" @property def opentype(self) -> str: # OpenType stores a 16.16 number rather than semantic components. return f"{self.major}.{self.minor}{self.patch:02d}" @property def revision(self) -> float: return float(self.opentype) def __str__(self) -> str: return self.semantic def load_release_version(path: Path = VERSION_FILE) -> ReleaseVersion: try: value = path.read_text(encoding="utf-8").strip() except OSError as exc: raise RuntimeError(f"cannot read release version: {path}") from exc try: return ReleaseVersion.parse(value) except ValueError as exc: raise RuntimeError(f"invalid release version in {path}: {value!r}") from exc RELEASE = load_release_version() RELEASE_VERSION = RELEASE.semantic FONT_VERSION = RELEASE.opentype FONT_REVISION = RELEASE.revision @dataclass(frozen=True, slots=True) class StyleSpec: """One static face in the public Ilta Mono family.""" name: str display_name: str weight_class: int source_weight: int italic: bool @property def css_style(self) -> str: return "italic" if self.italic else "normal" @dataclass(frozen=True, slots=True) class WeightSpec: """The upright/italic pair for one public CSS weight.""" stem: str display_name: str weight_class: int source_weight: int def style(self, *, italic: bool) -> StyleSpec: if italic: name = "Italic" if self.stem == "Regular" else f"{self.stem}Italic" display_name = ( "Italic" if self.stem == "Regular" else f"{self.display_name} Italic" ) else: name = self.stem display_name = self.display_name return StyleSpec( name=name, display_name=display_name, weight_class=self.weight_class, source_weight=self.source_weight, italic=italic, ) # Public weight classes and the optically rebalanced Valley drawing ladder. WEIGHTS = ( WeightSpec("Thin", "Thin", 100, 175), WeightSpec("ExtraLight", "Extra Light", 200, 270), WeightSpec("Light", "Light", 300, 390), WeightSpec("Regular", "Regular", 400, 510), WeightSpec("Medium", "Medium", 500, 610), WeightSpec("SemiBold", "Semi Bold", 600, 690), WeightSpec("Bold", "Bold", 700, 780), WeightSpec("ExtraBold", "Extra Bold", 800, 835), WeightSpec("Black", "Black", 900, 900), ) STYLE_PAIRS = tuple( (weight.style(italic=False), weight.style(italic=True)) for weight in WEIGHTS ) UPRIGHT_STYLES = tuple(upright for upright, _italic in STYLE_PAIRS) ITALIC_STYLES = tuple(italic for _upright, italic in STYLE_PAIRS) STYLES = UPRIGHT_STYLES + ITALIC_STYLES STYLE_BY_NAME = {style.name: style for style in STYLES} WEIGHT_ROWS = tuple( (weight.stem, weight.weight_class) for weight in WEIGHTS ) # Compatibility-shaped views keep the transformation code declarative while # every release-facing script consumes the same immutable registry. DISPLAY_STYLES = { style.name: style.display_name for style in STYLES } STYLE_SOURCE_WEIGHTS = { style.name: style.source_weight for style in STYLES } NOMINAL_WEIGHT_CLASSES = { style.name: style.weight_class for style in STYLES } RELEASE_STYLES = tuple(style.name for style in STYLES) def style_from_path(path: Path) -> str: prefix = "ValleySans-" if not path.stem.startswith(prefix): raise ValueError(f"unexpected upstream filename: {path.name}") style = path.stem[len(prefix) :] if style not in STYLE_BY_NAME: raise ValueError(f"unknown Valley Sans style in {path.name}") return style def source_epoch() -> int: """Return the deterministic Unix epoch used by external build tools.""" raw = os.environ.get("SOURCE_DATE_EPOCH", "0") try: return int(raw) except ValueError as exc: raise ValueError("SOURCE_DATE_EPOCH must be an integer") from exc def source_timestamp() -> int: """Return a deterministic OpenType longDateTime value.""" return source_epoch() + MAC_EPOCH_OFFSET