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.00 prints as 100, 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 – quoteattr picks whichever one avoids the most escaping.

This exists because xml.sax.saxutils.escape does 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 with innerHTML by 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``