codexcss-mixed-font-line-box.py
css-mixed-font-line-box.py
"""Draw baseline-aligned CSS metric boxes; save a PNG in the working directory."""
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
def measure(ax, x, bottom, top, label, color):
ax.annotate("", xy=(x, bottom), xytext=(x, top),
arrowprops={"arrowstyle": "<->", "linewidth": 1.5,
"color": color})
ax.text(x + 0.15, (bottom + top) / 2, label, va="center",
color=color, fontsize=10)
def main():
fig, ax = plt.subplots(figsize=(8.5, 5.4), dpi=100, facecolor="white")
fig.subplots_adjust(left=0.05, right=0.98, bottom=0.19, top=0.82)
fig.suptitle("Two line heights, a taller line box", y=0.97,
fontsize=16, weight="bold", color="#172330")
fig.text(0.5, 0.9, "Hypothetical font metrics; one common baseline",
ha="center", fontsize=11, color="#45535d")
ax.add_patch(Rectangle((0.8, -8), 8.5, 21, facecolor="#f1f3f5",
edgecolor="#7a8895", linewidth=1.2,
linestyle="--"))
for x, a, d, height, color, name in [
(1.25, 11, 3, 18, "#226a9a", "Run A"),
(5.4, 8, 4, 20, "#26734d", "Run B"),
]:
leading = height - a - d
above, below = a + leading / 2, d + leading / 2
ax.add_patch(Rectangle((x, -below), 2.5, height,
facecolor=color, alpha=0.12, edgecolor="none"))
ax.add_patch(Rectangle((x, -d), 2.5, a + d,
facecolor="white", edgecolor=color,
linewidth=1.2, linestyle=":"))
ax.add_patch(Rectangle((x, -below), 2.5, height,
facecolor="none", edgecolor=color,
linewidth=2))
ax.text(x + 1.25, a / 2, name, ha="center", va="center",
color=color, fontsize=12, weight="bold")
ax.text(x + 1.25, 14.2, f"A = {a}, D = {d}, H = {height}",
ha="center", color=color, fontsize=10)
ax.text(x + 1.25, -10.1,
f"Above baseline: {above:g}; below: {below:g}",
ha="center", va="center", color=color, fontsize=9)
measure(ax, x + 2.75, -below, above, f"{height}", color)
ax.axhline(0, xmin=0.03, xmax=0.8, color="#34495e", linewidth=1.2)
ax.text(0.3, 0.6, "baseline", fontsize=9, color="#34495e")
measure(ax, 10.0, -8, 13, "21", "#9b4928")
ax.text(10.0, 14.2, "Line box", ha="center", fontsize=10,
color="#9b4928")
ax.set_xlim(0, 11.7)
ax.set_ylim(-11.7, 16)
ax.axis("off")
fig.text(0.5, 0.115, "Top comes from A; bottom comes from B: 13 + 8 = 21 CSS pixels.",
ha="center", fontsize=11, color="#172330")
fig.text(0.5, 0.055, "Dotted inner boxes: font metrics. Pale bands: half-leading.",
ha="center", fontsize=10, color="#45535d")
fig.text(0.5, 0.018, "The block's strut is assumed to add no greater extent.",
ha="center", fontsize=9, color="#45535d")
fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), dpi=100,
facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()