simvx.core.text.bundled¶
The fonts SimVX ships with, and the project keys that choose between them.
Text rendering used to depend on whichever font happened to be installed on the machine: a bare container or a stripped desktop had none, so text silently did not draw at all, and two developers exporting the same game baked two different typefaces. The engine therefore ships fonts of its own and uses them by default.
Three faces, named by the job they do rather than by typeface, so that changing the typeface is a change in one place:
"ui"
Everything a game or the editor draws that is not code: labels, buttons,
menus, dialogs. Noto Sans.
"mono"
Fixed-pitch text, where columns must line up: the code editor, the
terminal, and any tabular readout. Noto Sans Mono.
"fallback"
Not drawn in directly. It is the last face the fallback chain asks for a
character neither the primary face nor the machine’s own fonts can draw,
and it is DejaVu Sans Mono because that face is the widest-covering one
the engine ships: Arabic, Armenian, Georgian, Lao, the box-drawing and
block-element blocks, the mathematical and APL operators. Without it a
bare container would draw missing-glyph boxes for every one of them.
Ask for one by name::
from simvx.core.text import bundled_font_path
ui = bundled_font_path("ui")
code = bundled_font_path("mono")
The "mono" face gives every printable ASCII character a 0.6 em body, and the
outlines say so exactly. That holds for characters, not for all of Unicode:
combining marks advance zero, as they must to stack on the letter before them,
and the digraph and fraction characters advance a whole multiple of 0.6 em.
Anything laying out text it did not choose still has to measure it.
The rasterised advances are a weaker promise than the outlines. Glyphs are
loaded hinted, and hinting rounds each advance to a whole pixel independently,
which this face does not always round the same way: at 48 px its ASCII advances
come out 28, 29 and 30 px rather than a uniform 28.8. A layout that places each
character at a pitch of its own is unaffected, because nothing accumulates, but
one that sums advances along a line drifts. Loading unhinted removes it
entirely, at the cost of crispness at small sizes. "fallback"’s DejaVu Sans
Mono rasterises to a single advance at every size tested, which is why it is
also the face a test of a character grid is written against.
Nothing draws in the "mono" face today, including the code views and the
terminal it is named for. Draw2D holds one glyph atlas at a time and
draw_text takes no face, so every widget on screen draws in the "ui"
face; selecting a second face needs a text path that carries one per draw on
the desktop renderer and a second baked atlas in the web export.
That has a visible cost, not a deferred one, and it arrived with the "ui"
face becoming proportional. A widget on a character grid derives that grid from
the face it is drawn in and takes the pitch from the widest character that face
draws, which is what keeps a wide glyph out of the column beside it. Under a
proportional face the pitch is therefore the width of W for every column,
so the grid is correct but sparse: a terminal’s cell goes from 8.53 px to
13.13 px at the default 14 px size, the same eighty columns take half as much
width again, and a panel that fits its grid to its own width hands the process
about a third fewer columns than it used to. In a code view it shows as
trailing comments at one source column no longer lining up. A game that needs a
tight grid can draw the whole of itself in a fixed-pitch face by passing
bundled_font_path("fallback") to Draw2D.set_font.
The "ui" face is proportional: every widget measures the text it holds
against the font’s own glyph advances, so a menu, dropdown, tooltip or dialog is
as wide as the string inside it rather than as wide as a guess at a fixed
advance per character.
A project chooses fonts in simvx.toml::
[rendering]
font = "assets/fonts/Inter-Regular.ttf"
fallback_fonts = ["assets/fonts/NotoSansArabic-Regular.ttf"]
prefer_system_fonts = false
font replaces the "ui" face. fallback_fonts replaces the chain that
is otherwise auto-detected. prefer_system_fonts searches the machine’s own
fonts ahead of the bundled ones; it is a preference, never an exclusion, so
when the search comes up empty the bundled fonts are still used and no
configuration can leave a game with no font. Paths are resolved against the
directory holding simvx.toml, so they can be written the way the project
writes every other asset path.
Each font ships with the licence it may not be redistributed without: the Noto
faces under the SIL Open Font License (fonts/OFL.txt), DejaVu under the
Bitstream Vera licence (fonts/LICENSE-DejaVu.txt).
Module Contents¶
Functions¶
Filesystem path of the shipped font for face. |
|
Filesystem path of the licence text for face’s font, or None if absent. |
|
Whether the project asked for system fonts ahead of the bundled ones. |
|
The face the project asked every string to be drawn in, or None. |
|
The fallback chain the project named, in order, or an empty list. |
Data¶
API¶
- simvx.core.text.bundled.log¶
‘getLogger(…)’
- simvx.core.text.bundled.__all__¶
[‘BUNDLED_FACES’, ‘BUNDLED_FONT_FILES’, ‘bundled_font_licence_path’, ‘bundled_font_path’, ‘configure…
- simvx.core.text.bundled.BUNDLED_FONT_FILES: dict[str, str]¶
None
- simvx.core.text.bundled.BUNDLED_FACES: dict[str, str]¶
None
- simvx.core.text.bundled.bundled_font_path(face: str) str | None[source]¶
Filesystem path of the shipped font for face.
face is one of the keys of :data:
BUNDLED_FACES; there is no default, because which of them a caller wants is never obvious from the call site.Returns
Noneonly when the package data is missing, which means a damaged or hand-trimmed install; callers fall back to a system font search.
- simvx.core.text.bundled.bundled_font_licence_path(face: str) str | None[source]¶
Filesystem path of the licence text for face’s font, or None if absent.
- simvx.core.text.bundled.prefer_system_fonts(start_dir: str | pathlib.Path | None = None) bool[source]¶
Whether the project asked for system fonts ahead of the bundled ones.
Reads
[rendering] prefer_system_fontsfrom the nearestsimvx.tomlat or above start_dir, or above the working directory when that is None, the same way display settings are read. Defaults toFalse.The value’s type is enforced by the project schema rather than coerced here, because
bool("false")is True and a mistyped switch would otherwise change the typeface of every string in the game without saying so.
- simvx.core.text.bundled.configured_font_path(start_dir: str | pathlib.Path | None = None) str | None[source]¶
The face the project asked every string to be drawn in, or None.
Reads
[rendering] fontfrom the nearestsimvx.tomlat or above start_dir, or above the working directory when that is None. A relative path is resolved against the directory holding that file, so it is written the way the project writes every other asset path. Returns None when the key is absent or names a file that is not there, which leaves the caller on the bundled face.
- simvx.core.text.bundled.configured_fallback_fonts(start_dir: str | pathlib.Path | None = None) list[str][source]¶
The fallback chain the project named, in order, or an empty list.
Reads
[rendering] fallback_fontsfrom the nearestsimvx.tomlat or above start_dir, or above the working directory when that is None. Naming a chain replaces auto-detection: a game that ships its own font for every script it supports draws the same on every machine, which auto-detection cannot promise. Entries that do not resolve are reported and dropped, so one bad path costs one script rather than the whole chain.