codex/font-line-metrics.py

font-line-metrics.py
"""Draw hypothetical font metrics and baseline spacing; output PNG in cwd."""
from pathlib import Path

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle, Polygon


def main():
    ascent, descent, gap = 800, 200, 200
    spacing = ascent + descent + gap
    fig, ax = plt.subplots(figsize=(8, 5.2), dpi=100, facecolor="white")
    fig.subplots_adjust(left=0.04, right=0.97, bottom=0.16, top=0.85)
    fig.suptitle("Font metrics and the gap between baselines", y=0.97,
                 fontsize=16, weight="bold", color="#172330")
    for baseline in [0, spacing]:
        ax.add_patch(Rectangle((1.8, baseline - descent), 3.0,
                               ascent + descent, facecolor="#edf3f6",
                               edgecolor="#a4b5c0", linewidth=1,
                               linestyle="--"))
        ax.plot([1.7, 4.9], [baseline, baseline], color="#345d76", linewidth=1)
        # Original schematic ink, with extents smaller than the font metrics.
        ax.add_patch(Polygon([
            (2.1, baseline), (2.22, baseline), (2.4, baseline + 490),
            (2.58, baseline), (2.7, baseline), (2.45, baseline + 650),
            (2.35, baseline + 650),
        ], closed=True, facecolor="#246a91", edgecolor="none"))
        ax.add_patch(Rectangle((3.05, baseline - 150), 0.13, 650,
                               facecolor="#246a91", edgecolor="none"))
        ax.add_patch(Rectangle((3.18, baseline + 250), 0.43, 250,
                               facecolor="#246a91", edgecolor="none"))
        ax.text(4.95, baseline, "baseline", va="center", fontsize=10,
                color="#345d76")
    for start, end, label in [
        (0, ascent, "ascent A = 800"),
        (-descent, 0, "descent D = 200"),
        (ascent, spacing - descent, "gap G = 200"),
    ]:
        ax.annotate("", xy=(1.55, start), xytext=(1.55, end),
                    arrowprops={"arrowstyle": "<->", "color": "#576873"})
        ax.text(1.4, (start + end) / 2, label, ha="right", va="center",
                fontsize=10, color="#45535d")
    ax.annotate("", xy=(6.3, 0), xytext=(6.3, spacing),
                arrowprops={"arrowstyle": "<->", "color": "#9b4928",
                            "linewidth": 1.6})
    ax.text(6.5, spacing / 2, "H = 1200\n= A + D + G",
            va="center", fontsize=12, color="#9b4928")
    ax.set_xlim(-0.25, 8.0)
    ax.set_ylim(-360, spacing + ascent + 150)
    ax.axis("off")
    fig.text(0.5, 0.095,
             "1000 font units per em; 20 pixels per em → 24 pixels between baselines.",
             ha="center", fontsize=10, color="#45535d")
    fig.text(0.5, 0.035,
             "Original schematic ink and hypothetical metrics; a single-font spacing model.",
             ha="center", fontsize=10, color="#45535d")
    fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), dpi=100,
                facecolor="white", transparent=False)
    plt.close(fig)


if __name__ == "__main__":
    main()