Skip to content

Render API

Renderers consume already-paginated Page values. Registry discovery does not import optional rendering backends until selected.

glyphive.render

Named render formats for already-paginated glyphive pages.

DEFAULT_DOCX_FONT = DEFAULT_MONO_FONT module-attribute

DEFAULT_MONO_FONT = 'Consolas' module-attribute

DEFAULT_PAGE_MARGIN_PT = 36.0 module-attribute

DEFAULT_PDF_FONT = 'dejavu-sans-mono' module-attribute

FORMATS = frozenset(RenderFormat.names()) module-attribute

HORIZONTAL_ALIGNMENTS = frozenset({'left', 'center', 'justify'}) module-attribute

MINIMAL_PAGE_MARGIN_PT = 12.0 module-attribute

__all__ = ['FORMATS', 'DEFAULT_MONO_FONT', 'DEFAULT_PDF_FONT', 'DEFAULT_DOCX_FONT', 'DEFAULT_PAGE_MARGIN_PT', 'MINIMAL_PAGE_MARGIN_PT', 'HORIZONTAL_ALIGNMENTS', 'RenderFormat', 'available', 'get', 'lines_per_page_for', 'names', 'render'] module-attribute

RenderFormat

Bases: ABC

Base class for stateless, no-argument render formats.

name class-attribute

__init_subclass__(**kwargs)

Source code in src/glyphive/render/_base.py
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
def __init_subclass__(cls, **kwargs: _ty.Any) -> None:
    super().__init_subclass__(**kwargs)
    if getattr(getattr(cls, "render", None), "__isabstractmethod__", False):
        return
    name = getattr(cls, "name", None)
    if not isinstance(name, str) or not re.fullmatch(r"[a-z][a-z0-9_-]*", name):
        raise ValueError(f"render format {cls.__qualname__} has an invalid name")
    if name in RenderFormat._registry:
        existing = RenderFormat._registry[name]
        raise ValueError(
            f"duplicate render format name {name!r}: "
            f"{existing.__module__}.{existing.__qualname__} and "
            f"{cls.__module__}.{cls.__qualname__}"
        )
    RenderFormat._registry[name] = cls

available() classmethod

Source code in src/glyphive/render/_base.py
46
47
48
49
50
51
52
@classmethod
def available(cls) -> _ty.List[str]:
    return sorted(
        name
        for name, implementation in RenderFormat._registry.items()
        if implementation.is_available()
    )

geometric_payload_capacity(*, font=None, font_size=11.0, page_margin_pt=DEFAULT_PAGE_MARGIN_PT, character_spacing_pt=0.0, nsym_line=2)

Largest payload width that physically fits, ignoring the safety cap.

Unlike :meth:payload_capacity (clamped to the OCR-measured-safe row width), this reports the uncapped geometric fit — used by create --line-width max. Formats without physical font metrics (text/docx/qr) return None, so max is rejected for them. nsym_line is documented on :meth:payload_capacity.

Source code in src/glyphive/render/_base.py
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
def geometric_payload_capacity(
    self,
    *,
    font: _ty.Optional[str] = None,
    font_size: float = 11.0,
    page_margin_pt: float = DEFAULT_PAGE_MARGIN_PT,
    character_spacing_pt: float = 0.0,
    nsym_line: int = 2,
) -> _ty.Optional[int]:
    """Largest payload width that *physically* fits, ignoring the safety cap.

    Unlike :meth:`payload_capacity` (clamped to the OCR-measured-safe row
    width), this reports the uncapped geometric fit — used by
    ``create --line-width max``. Formats without physical font metrics
    (text/docx/qr) return ``None``, so ``max`` is rejected for them.
    ``nsym_line`` is documented on :meth:`payload_capacity`.
    """
    return None

get(name) classmethod

Source code in src/glyphive/render/_base.py
54
55
56
57
58
59
60
61
62
63
@classmethod
def get(cls, name: str) -> "RenderFormat":
    try:
        implementation = RenderFormat._registry[name]
    except (KeyError, TypeError):
        valid = ", ".join(RenderFormat.names()) or "(none)"
        raise ValueError(
            f"unknown render format {name!r}; available formats: {valid}"
        ) from None
    return implementation()

is_available() classmethod

Source code in src/glyphive/render/_base.py
65
66
67
@classmethod
def is_available(cls) -> bool:
    return True

names() classmethod

Source code in src/glyphive/render/_base.py
42
43
44
@classmethod
def names(cls) -> _ty.List[str]:
    return sorted(RenderFormat._registry)

payload_capacity(*, font=None, font_size=11.0, page_margin_pt=DEFAULT_PAGE_MARGIN_PT, character_spacing_pt=0.0, nsym_line=2)

Return the largest fitting codec payload width, if measurable.

Formats without reliable physical font metrics return None and creation retains the conservative 60-character wire row. nsym_line (default 2, matching create's default) is the per-line Reed- Solomon parity budget being encoded with -- a format with physical font metrics must reserve room for that optional field's extra printed characters.

Source code in src/glyphive/render/_base.py
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
def payload_capacity(
    self,
    *,
    font: _ty.Optional[str] = None,
    font_size: float = 11.0,
    page_margin_pt: float = DEFAULT_PAGE_MARGIN_PT,
    character_spacing_pt: float = 0.0,
    nsym_line: int = 2,
) -> _ty.Optional[int]:
    """Return the largest fitting codec payload width, if measurable.

    Formats without reliable physical font metrics return ``None`` and
    creation retains the conservative 60-character wire row. ``nsym_line``
    (default 2, matching ``create``'s default) is the per-line Reed-
    Solomon parity budget being encoded with -- a format with physical
    font metrics must reserve room for that optional field's extra
    printed characters.
    """
    return None

render(pages, out, *, font=None, font_size=11.0, page_margin_pt=DEFAULT_PAGE_MARGIN_PT, horizontal_alignment='left', character_spacing_pt=0.0) abstractmethod

Render already-paginated pages.

Source code in src/glyphive/render/_base.py
128
129
130
131
132
133
134
135
136
137
138
139
140
@abstractmethod
def render(
    self,
    pages: _ty.Iterable[Page],
    out: _ty.Union[str, "_os.PathLike[str]"],
    *,
    font: _ty.Optional[str] = None,
    font_size: float = 11.0,
    page_margin_pt: float = DEFAULT_PAGE_MARGIN_PT,
    horizontal_alignment: str = "left",
    character_spacing_pt: float = 0.0,
) -> None:
    """Render already-paginated pages."""

available()

Source code in src/glyphive/render/__init__.py
52
53
def available() -> _ty.List[str]:
    return RenderFormat.available()

get(name)

Source code in src/glyphive/render/__init__.py
44
45
def get(name: str) -> RenderFormat:
    return RenderFormat.get(name)

lines_per_page_for(font_size, *, page_height_pt=792.0, page_margin_pt=DEFAULT_PAGE_MARGIN_PT)

Source code in src/glyphive/render/__init__.py
56
57
58
59
60
61
62
63
64
65
66
67
68
def lines_per_page_for(
    font_size: float,
    *,
    page_height_pt: float = 792.0,
    page_margin_pt: float = DEFAULT_PAGE_MARGIN_PT,
) -> int:
    if font_size <= 0:
        raise ValueError("font_size must be > 0")
    usable = page_height_pt - 2.0 * page_margin_pt
    leading = font_size * 1.2
    if leading <= 0 or usable <= 0:
        raise ValueError("page geometry leaves no room for any line")
    return max(3, int(usable // leading))

names()

Source code in src/glyphive/render/__init__.py
48
49
def names() -> _ty.List[str]:
    return RenderFormat.names()

render(pages, out, fmt, *, font=None, font_size=11.0, page_margin_pt=DEFAULT_PAGE_MARGIN_PT, horizontal_alignment='left', character_spacing_pt=0.0)

Resolve fmt and delegate one time to its registered implementation.

Source code in src/glyphive/render/__init__.py
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
def render(
    pages: _ty.List["Page"],
    out: _ty.Union[str, "_os.PathLike[str]"],
    fmt: str,
    *,
    font: _ty.Optional[str] = None,
    font_size: float = 11.0,
    page_margin_pt: float = DEFAULT_PAGE_MARGIN_PT,
    horizontal_alignment: str = "left",
    character_spacing_pt: float = 0.0,
) -> None:
    """Resolve ``fmt`` and delegate one time to its registered implementation."""
    get(fmt).render(
        pages,
        out,
        font=font,
        font_size=font_size,
        page_margin_pt=page_margin_pt,
        horizontal_alignment=horizontal_alignment,
        character_spacing_pt=character_spacing_pt,
    )