Terminal Presentation
Relevant source files
The following files were used as context for generating this wiki page:
Terminal Presentation refers to the mechanism by which pixel-level graphics, composited within a backend-agnostic buffer, are transmitted and rendered to a physical terminal emulator. This process bridges the gap between the guiltty-core geometry and sprite logic and the specific escape sequences required by terminal protocols like Kitty. Sources: README.md:1-5, crates/guiltty-core/src/lib.rs:88-95
The primary interface for this system is the Backend trait, which defines how a Canvas—containing raw RGBA8 pixel data—is presented to an output stream. The current implementation focus is the KittyBackend, which leverages the Kitty graphics protocol to display images without relying on character-cell grid limitations. Sources: crates/guiltty-core/src/lib.rs:88-95, crates/guiltty-kitty/src/lib.rs:1-6
Architecture and Data Flow
The presentation flow starts with a Canvas populated by shapes, text, or sprites. When present() is called on a backend, the canvas's internal pixel buffer is converted into a format suitable for terminal transmission. Sources: crates/guiltty-core/src/lib.rs:149-155, crates/guiltty-kitty/src/lib.rs:69-75
The diagram shows the transformation of pixel data from the internal Canvas representation to the final terminal escape sequences. Sources: crates/guiltty-core/src/lib.rs:149-155, crates/guiltty-kitty/src/lib.rs:72-76
The Backend Trait
The Backend trait serves as the abstraction layer for different terminal protocols. It requires backends to implement a present method that accepts a reference to a Canvas. Sources: crates/guiltty-core/src/lib.rs:88-95
| Feature | Description | File Path |
|---|---|---|
present() | The primary method to transmit the canvas state to the terminal. | crates/guiltty-core/src/lib.rs:94 |
Error | Associated error type allowing backends to surface protocol-specific failures. | crates/guiltty-core/src/lib.rs:91 |
Kitty Graphics Protocol Implementation
The KittyBackend implements the presentation logic specifically for terminals supporting the Kitty graphics protocol (version 0.20.0+). It transforms the canvas pixel buffer into a series of Application Program Command (APC) sequences. Sources: crates/guiltty-kitty/src/lib.rs:1-12
Encoding and Transmission
To comply with terminal protocol constraints, the backend performs the following steps:
- Format Conversion: The canvas
rgba8_bytes()are extracted. - Base64 Encoding: The raw bytes are Base64 encoded using the
base64crate. - Chunking: The resulting string is split into chunks of 4096 bytes (
MAX_CHUNK_LEN) to avoid exceeding terminal buffer limits. - Escape Sequence Generation: Each chunk is wrapped in
\x1b_G(start) and\x1b\\(stop) sequences. Sources: crates/guiltty-kitty/src/lib.rs:72-80, crates/guiltty-kitty/Cargo.toml:16
Image and Placement Management
To support efficient redrawing and prevent screen flicker or drifting, the backend manages unique IDs for images and placements. Sources: crates/guiltty-kitty/src/lib.rs:15-30
- Image ID (
i): A unique ID assigned to eachKittyBackendinstance using anAtomicU32(NEXT_IMAGE_ID). This prevents different backends from colliding. - Placement ID (
p): Fixed to match the Image ID. This ensures that repeatedpresent()calls update the same on-screen image rather than creating new ones. - Cursor Control (
C=1): The backend sends theC=1key to prevent the terminal cursor from moving after the image is displayed, allowing stable redraws at the same origin. Sources: crates/guiltty-kitty/src/lib.rs:15-20, crates/guiltty-kitty/src/lib.rs:95-105
The sequence shows the interaction between the application, the backend, and the terminal during a frame update. Sources: crates/guiltty-kitty/src/lib.rs:72-115
Protocol Keys Summary
The KittyBackend uses specific control keys within the APC payload to manage rendering behavior. Sources: crates/guiltty-kitty/src/lib.rs:90-105
| Key | Description | Implementation Detail |
|---|---|---|
a=T | Action: Transmit and Display | Combines transmission and placement. |
f=32 | Format: RGBA8 | Indicates 32-bit pixel data. |
i | Image ID | Unique numeric identifier for the image. |
p | Placement ID | Namespaced ID used to update specific placements. |
q=2 | Quiet Mode | Suppresses OK/error responses from the terminal. |
C=1 | Cursor Control | Prevents cursor movement after display. |
m | More Data | 1 if more chunks follow; 0 for the last chunk. |
Implementation Details
The following snippet illustrates the construction of the initial APC chunk header within the KittyBackend.
// crates/guiltty-kitty/src/lib.rs:95-103
write!(
self.writer,
"\x1b_Ga=T,f=32,i={},p={},q=2,C=1,s={},v={},m={};",
self.image_id,
self.image_id,
canvas.width(),
canvas.height(),
more
)
Sources: crates/guiltty-kitty/src/lib.rs:95-103
Error Handling
Terminal presentation involves potentially fallible I/O operations. The system handles these by:
- Mapping
std::io::Errortoguiltty_core::Error::Backendwith a descriptive string. - Returning a
Resultfrompresent(), ensuring the application can recover or log failures. - Treating zero-width/height canvases as no-ops to avoid sending malformed sequences. Sources: crates/guiltty-core/src/lib.rs:73-86, crates/guiltty-kitty/src/lib.rs:82-86
Conclusion
Terminal Presentation in the guiltty project transforms abstract pixel buffers into protocol-specific escape sequences. By using the KittyBackend and the Backend trait, the library achieves pixel-perfect graphics in the terminal while maintaining an architecture that allows for future backend support. The system ensures stable, flicker-free updates by carefully managing Image and Placement IDs within the Kitty graphics protocol. Sources: README.md:16-30, tasks/plan.md:30-45