Text
Purpose
Text selects font data, validates/decodes text, shapes Unicode runs and prepares drawable glyphs. Font loading, shaping, rasterization and graphics upload are different stages with different ownership and execution requirements.
Interface
Types below are in CE::Text unless another namespace is shown.
Types and operations
API and purpose |
|---|
|
|
|
|
|
|
|
Sources, direction and raster values
Type |
Choices and details |
|---|---|
Named family sources, selection groups, the application default and common fallback references. Catalogue configuration. |
|
Requested numeric weight/italic state and borrowed retained face bytes/index/style for adapters. Retained handles and style. |
|
File, system family or string source selection; make discovery policy explicit. Font sources and fallback. |
|
|
|
Distinguish source byte/scalar ranges from font-qualified glyph indices. Encoding and source indices. |
|
Raster sizing in |
Usage
For a fixed label, retain a font, lay out the string, prepare CPU glyph data and
upload one immutable generation. Resolve that generation during frame
preparation. For changing text, Rendering::Updater manages replacement work
while the last successful generation remains visible.
---
config:
theme: base
themeVariables:
fontFamily: system-ui, sans-serif
fontSize: 14px
flowchart:
htmlLabels: true
curve: linear
nodeSpacing: 22
rankSpacing: 38
padding: 12
---
flowchart LR
accTitle: Text · simple static label
accDescr: Local names omit Text::; ambiguous nested namespaces remain qualified. Arrows point toward dependencies. Application roles are rounded; named API operations have rounded corners. Dashed arrows mark optional choices.
k0(["Application<br/>init_platform()"]):::app
k1["FontService"]:::focal
k2["Font"]:::focal
k3("layout_text()"):::focal
k4["ShapedText"]:::focal
k5("Text::Rendering::<br/>prepare()"):::focal
k6["Text::Rendering::<br/>Prepared"]:::focal
k7("Text::Rendering::<br/>upload()"):::focal
k8["Rendering::Resources::<br/>Provider"]:::neighbor
k9["Text::Rendering::<br/>Generation"]:::focal
k0 --> k1
k1 --> k2
k3 --> k2
k3 --> k4
k5 --> k4
k5 --> k6
k7 --> k6
k7 --> k8
k7 --> k9
classDef focal fill:#e7f3ef,stroke:#387d6b,color:#153d33,stroke-width:1.2px
classDef neighbor fill:#f0f3f8,stroke:#8c9bb1,color:#35445b,stroke-width:1px
classDef app fill:#fff2df,stroke:#c09452,color:#674515,stroke-dasharray:5 3
classDef system fill:#eaf0fc,stroke:#617fab,color:#263f69,stroke-width:1.2px
linkStyle default stroke:#7e8fa7,stroke-width:1.2px
Local names omit Text:: where unambiguous. Explore this diagram and its other views →
The arrows show dependencies, including the owned result types used by each operation; the stage order is layout, prepare, upload, then draw resolution. See the updater diagram for asynchronous replacement and the engine dependency map for the font and resource relationships.
Choose the text path
Reader task |
Start with |
Work the application owns |
|---|---|---|
Static world label or HUD message |
|
Select the font and layout options; retain and submit the complete generation. Explicit stages. |
Score, dialogue or other changing text |
Construct on platform, request content and call |
|
Editable widget/document text |
Author native toolkit UI and route input/focus. Shared Engine fonts do not replace toolkit layout/editing behavior. |
|
Existing ASCII/bitmap content |
Follow the separate legacy font contract; do not infer Unicode shaping from this compatibility path. |
Uses
Consumer |
Dependency |
Integration boundary |
|---|---|---|
Font selection and layout |
|
Configure the catalogue before consumers. Layout retains the selected font-byte snapshot rather than borrowing the source string or reopening font files. |
Upload complete glyph pages/geometry on graphics and retain a compatible default or explicit material. |
||
Uses a Context-tracked CPU group and saved platform endpoint. Jobs own requests and borrow neither updater nor game. |
||
Glyph draw resolution |
Rendering |
Convert an uploaded generation to packets without repeating layout, rasterization or upload. |
The explicit layout/prepare path does not schedule jobs. Updater supplies
scheduling and nonblocking adoption through the worker group and platform
endpoint above.
Used by
Consumer |
Text value/service |
Responsibility |
|---|---|---|
Application labels, dialogue and HUDs |
Retain the current complete result and submit it from frame preparation. Old frames may retain older generations. |
|
Runtime |
Own the configured catalogue and default font; retained font handles can outlive that service. |
|
GUI TGUI/RmlUi adapters |
Import retained font bytes/metrics while keeping native toolkit layout, mutable atlas and editing state on the UI owner. |
Inspect layout before uploading
Text::ShapedText exposes lines, positioned
glyphs and source mapping, so CPU layout can be inspected without a graphics
provider. Local positions are Y-up pixels; pixel_height is the font em size.
A glyph ID belongs to its retained font collection. Source UTF-8 byte ranges,
Unicode scalar ranges and shaping clusters answer different indexing questions;
use the encoding and source-index guide before
mapping selection or hit-test state back to an application string.
Contracts
The context owns its font catalogue; an unconfigured catalogue supplies the embedded default. Named families and random selection groups use stable application references. Font handles retain CPU snapshots independently of the catalogue and Context. Configure before consumers: publishing another catalogue does not rebind an existing handle or widget. Lookup does not inspect changed source files.
Random selection runs only when requested. Restoring a saved reference reuses it while it is available and remains in the named group; otherwise it selects a replacement, then uses the application default or embedded fallback if no group candidate is available. The application persists the returned reference and owns shared object identity; runtime handles and font bytes are not save data.
Layout positions use local Y-up pixels; pixel_height is the font em size.
Glyph IDs are qualified by their retained font collection. Shaping clusters and
UTF-8 byte/scalar ranges are not interchangeable character indices. Layout
retains the font-byte snapshot used for later preparation, not a borrowed input
string or mutable native face.
Fallback and wrapping operate on the documented Unicode boundaries. Replacing text produces another layout/uploaded generation; it must not mutate a generation already retained by a frame. Upload retains a compatible default material; explicit custom materials must match the generation’s geometry.
FontRasterizer::load() copies font bytes; its copies share synchronized native
face state. Returned metrics/glyph pixels own their values and can survive the
rasterizer. This CPU service neither borrows a graphics provider nor makes a
toolkit’s mutable atlas thread-safe.
Lifecycle
Load selected fonts at a loading boundary, lay out text and prepare its CPU representation. Upload after graphics initialization and retain the generation in the game/HUD. Replace it when content changes, allowing published frames to retain older generations. Settle upload requests and release game handles before backend shutdown. Retained font bytes and native graphics lifetime are separate.
Execution
Font selection/layout/preparation are CPU stages; upload follows graphics affinity. Use owned request data across dispatch boundaries and consume completed futures without blocking simulation. Record positions and immutable generation handles during frame preparation.
Integration
For a static label, run the explicit CPU preparation and upload stages on the platform upload owner after graphics initialization. The configured default needs no application font plumbing:
auto font = engine_.fonts().default_font();
auto layout = CE::Text::layout_text(font, "Score: 0", {.pixel_height = 24});
auto prepared = CE::Text::Rendering::prepare(std::move(layout));
auto score = CE::Text::Rendering::upload(std::move(prepared), engine_.resources());
Retain score and resolve it using its retained material in frame preparation.
For a score or other changing label, use
Rendering::Updater to manage these
stages without adding worker futures or upload/adoption bookkeeping to the game.
It keeps the last successful generation while a replacement is pending or fails.
Limits and further reading
Text rendering is not a full editor/IME service. Do not infer arbitrary toolkit font compatibility or complete script acceptance from a basic label example. Read Unicode layout, encoding and source indices, font discovery, legacy fonts, layout declarations, shared rasterization operations and text rendering declarations.