Emitting#
Panel Core to SVG. The emitter makes no layout decisions: everything it draws was already decided.
scenet.emit.svg#
.. py:module:: scenet.emit.svg
Panel Core into SVG.
Purely mechanical: every position here was decided by the solver. The emitter makes no layout decisions, which is what keeps rendering swappable and golden tests meaningful.
Numbers are formatted through one helper at fixed precision so that output is byte-identical across platforms, whose float repr differs in the last digit.
.. py:function:: fmt(value)
- module:
scenet.emit.svg
Format a number for SVG output.
Trailing zeros are stripped so
100.00prints as100, which keeps files small and diffs readable without making them any less exact.- rtype:
- sphinx_autodoc_typehints_type:
\:py\:class\:\str``
.. py:function:: render(core, *, metrics=None, live_text=False)
- module:
scenet.emit.svg
Render a compiled panel as a standalone SVG document.
- rtype:
- sphinx_autodoc_typehints_type:
\:py\:class\:\str``
.. py:function:: attr(value)
- module:
scenet.emit.svg
Quote a string for use as an XML attribute value, delimiters included.
Returns the value with its surrounding quotes, because choosing the quote character is part of escaping correctly –
quoteattrpicks whichever one avoids the most escaping.This exists because
xml.sax.saxutils.escapedoes not escape quotation marks. That is fine for element content and wrong for an attribute: identifiers here come from user documents – a cast key, a panel name – and one containing a double quote would close the attribute early and let the rest of it be read as markup. The output is injected withinnerHTMLby the browser playground, so that is a scripting vector, not merely malformed XML.- type value:
- sphinx_autodoc_typehints_type:
\:py\:class\:\str``
- param value:
Any string, trusted or not.
- rtype:
- sphinx_autodoc_typehints_type:
\:py\:class\:\str``
- returns:
The value, escaped and wrapped in quotes.
.. admonition:: Example
from scenet.emit.svg import attr attr(“alice”) ‘“alice”’ attr(‘a” onload=x’) ‘’a” onload=x’’
scenet.emit.debug_svg#
.. py:module:: scenet.emit.debug_svg
Diagnostic overlay: what the solver was actually looking at.
Building a geometric solver without this is guesswork. When a balloon lands somewhere surprising, the question is always “what did the solver think was there?” – and the answer is invisible in the finished panel. This draws the hidden geometry: silhouette hulls, face exclusion circles, anchors, gaze vectors and tail routes.
.. py:function:: render_debug(core)
- module:
scenet.emit.debug_svg
Render the solver’s working geometry over a faint copy of the panel.
- rtype:
- sphinx_autodoc_typehints_type:
\:py\:class\:\str``
scenet.emit.strip#
.. py:module:: scenet.emit.strip
Several panels laid out as a strip.
Deliberately minimal. Real page composition – tiers, panels of varying size, the page-level reading path, bleeds – is a substantial design problem in its own right and is explicitly out of scope. This is the smallest thing that lets a sequence be read as a sequence: panels in a row, separated by a gutter, in declaration order.
The gutter is not decoration. It is where the reader performs what Scott McCloud calls closure – inferring what happened between two panels – and it is the one formal element that distinguishes comics from a series of illustrations.
.. py:function:: render_strip(panels, *, live_text=False)
- module:
scenet.emit.strip
Lay panels left to right in reading order.
Each panel is rendered independently and then placed, rather than being re-solved: a panel’s composition must not depend on what sits beside it, or the same source would compile differently in isolation.
- rtype:
- sphinx_autodoc_typehints_type:
\:py\:class\:\str``