Fonts and themes¶
Fonts¶
fonts
¶
Font identity and exact advance widths.
Line breaking is only as good as its measurements, so widths come from the font file itself (via Pillow, which shapes with HarfBuzz when available) or from reportlab's built-in metrics for the standard PDF families. An approximate advance model was rejected: the error compounds word by word and reopens the very gaps justification just closed.
Font
dataclass
¶
Font(
family: str,
ascent: float,
descent: float,
advance: Callable[[str], float],
weight: int = 400,
italic: bool = False,
)
A face that can both name itself in SVG and measure its own text.
width
¶
How wide text renders at size, in the figure's units.
TextStyle
dataclass
¶
TextStyle(font: Font, size: float, fill: str = 'ink', tracking: float = 0.0)
How a run of text is set — everything measuring and drawing both need.
load_font
cached
¶
load_font(
path: Path | str,
*,
family: str | None = None,
weight: int = 400,
italic: bool = False,
index: int = 0,
) -> Font
Load a real font file.
family overrides the name written into the SVG; index picks a face out
of a collection (.ttc), where the bold and the regular share one file.
builtin_font
cached
¶
builtin_font(
family: str = "Helvetica", weight: int = 400, *, italic: bool = False
) -> Font
A standard PDF face — no font file needed, works on any machine.
find_font
¶
Locate stem in the usual font directories, e.g. SourceSansPro-Regular.
Themes¶
theme
¶
One object holding the typography, palette and spacing a figure inherits.
Blocks name colours rather than spelling them out — fill="surface" or
accent="red" — so a figure can be restyled by swapping the theme instead
of editing every call. A literal #rrggbb is always accepted too.
ACCENTS
module-attribute
¶
ACCENTS = {
"red": "#a8412f",
"amber": "#a8752a",
"green": "#4f7a4a",
"blue": "#3f6a86",
"grey": "#7a7a7a",
}
Theme
dataclass
¶
Theme(
body: Font = builtin_font(),
bold: Font = (lambda: builtin_font(weight=700))(),
italic: Font = (lambda: builtin_font(italic=True))(),
size: float = 11.0,
leading: float = 1.38,
ink: str = "#1a1a1a",
muted: str = "#5f5f5f",
accent: str = "#1f4e5f",
surface: str = "#f4f3f0",
rule: str = "#e0ded9",
page: str = "#ffffff",
radius: float = 5.0,
pad: float = 14.0,
gap: float = 12.0,
)
bold
class-attribute
instance-attribute
¶
bold: Font = field(default_factory=lambda: builtin_font(weight=700))
italic
class-attribute
instance-attribute
¶
italic: Font = field(default_factory=lambda: builtin_font(italic=True))
font_for
¶
font_for(weight: int, *, italic: bool) -> Font
The face this theme uses for a weight and slant.
tint
¶
Mix color toward white — 0 leaves it alone, 1 returns white.
Images¶
images
¶
Pictures, embedded rather than linked.
A figure has to survive being emailed, so an image becomes a data URI inside the SVG instead of a path to something that will not travel with it. The intrinsic size is read here too: a logo knows its own proportions, and the layout should not have to be told them.