# retroglyph - Complete API Documentation > A 2D pseudographic terminal library **Version:** 0.1.0 **Authors:** Matan Lurey **License:** MIT **Repository:** https://github.com/crates-lurey-io/retroglyph **Keywords:** roguelike, terminal, grid, gamedev **Dependencies:** - ixy (0.6.0-alpha.7) - image (0.25) [features: png] - unicode-width (0.2) - bitflags (2.4) - crossterm (0.28) - softbuffer (0.4) - alpha-blend (0.2) [features: std] - winit (0.30) - log (0.4) - grixy (0.6.0-alpha.7) [features: alloc, buffer] - unicode-segmentation (1.13) **Features:** - std: [] - software: [dep:winit, dep:softbuffer, dep:log, std] - software-tilesets: [software, dep:image, dep:alpha-blend, dep:log] - egc: [dep:unicode-segmentation] - default: [std, egc] - crossterm: [dep:crossterm, std] - software-default-font: [software] Generated: 2026-06-22 01:13:48 UTC Created by: [cargo-llms-txt](https://github.com/masinc/cargo-llms-txt) ## Table of Contents ### src/tile.rs - pub struct Tile - impl Default for Tile - impl Tile ### src/event.rs - pub struct KeyModifiers - impl KeyModifiers - impl BitOr for KeyModifiers - impl BitOrAssign for KeyModifiers - impl BitAnd for KeyModifiers - impl BitAndAssign for KeyModifiers - impl Not for KeyModifiers - pub enum KeyCode - pub struct KeyEvent - pub enum MouseButton - pub enum MouseEventKind - pub struct MouseEvent - pub enum Event ### src/color.rs - pub enum AnsiColor - impl AnsiColor - pub struct InvalidAnsiIndex - impl core::fmt::Display for InvalidAnsiIndex - impl TryFrom for AnsiColor - pub enum Color - impl Color ### src/layout.rs - pub enum HAlign - pub enum VAlign - pub struct TextMetrics - pub struct TextLayout - impl TextLayout ### src/terminal.rs - pub struct Terminal - impl Terminal ### src/backend/headless.rs - pub struct Headless - impl Headless - impl Backend for Headless ### src/backend/crossterm.rs - impl From for crossterm::style::Color - impl From for crossterm::style::Attributes - pub struct Crossterm - impl Crossterm - impl Drop for Crossterm - impl Backend for Crossterm - impl TryFrom for crate::event::KeyCode - impl From for crate::event::KeyModifiers - impl From for crate::event::MouseButton - impl TryFrom for crate::event::MouseEventKind - impl TryFrom for crate::event::MouseEvent - impl TryFrom for Event ### src/backend/software/sprite_cache.rs - pub struct Sprite - pub struct SpriteCache - impl SpriteCache - impl Default for SpriteCache - pub fn source_over ### src/backend/software/bitmap_font.rs - pub struct BitmapFont - impl BitmapFont - impl PartialEq for BitmapFont - impl Eq for BitmapFont - pub mod vga8x16 - pub const vga8x16::FONT ### src/backend/software/config.rs - pub enum SoftwareBackendError - impl fmt::Display for SoftwareBackendError - impl std::error::Error for SoftwareBackendError - pub struct SoftwareBackend - impl Default for SoftwareBackend - pub struct SoftwareBackendBuilder - impl SoftwareBackendBuilder - impl Default for SoftwareBackendBuilder ### src/backend/software/windowed.rs - pub trait WindowedBackend ### src/backend/software/mod.rs - pub mod bitmap_font - pub mod config - pub mod sprite_cache - pub mod tileset - pub use bitmap_font::BitmapFont - pub use config::{SoftwareBackend, SoftwareBackendBuilder, SoftwareBackendError} - pub mod windowed - pub use windowed::WindowedBackend - pub struct SoftwareRenderer - pub enum SurfaceError - impl core::fmt::Display for SurfaceError - impl std::error::Error for SurfaceError - impl SoftwareRenderer - impl SoftwareBackend - impl Backend for SoftwareRenderer - impl WindowedBackend for SoftwareRenderer - impl WindowApp - impl ApplicationHandler for WindowApp ### src/backend/software/tileset.rs - pub enum TilesetError - impl fmt::Display for TilesetError - impl std::error::Error for TilesetError - pub enum Codepage - impl Codepage - pub const CP437_TO_UNICODE - pub struct TilesetOptions - impl TilesetOptions - pub struct TilesetBuilder - impl TilesetBuilder ### src/backend/mod.rs - pub mod crossterm - pub mod headless - pub mod software - pub use crossterm::Crossterm - pub use headless::Headless - pub use software::{SoftwareBackend, SoftwareRenderer, WindowedBackend} - pub trait Backend ### src/style.rs - impl core::fmt::Debug for CellModifier - pub struct Style - impl Style ### src/grid.rs - pub struct Size - pub type Pos - pub type Rect - impl From for Size - impl From for Unknown - pub struct Cells - impl Iterator for Cells - pub struct CellsMut - impl Iterator for CellsMut - impl LayerBuf - pub struct Grid - impl Grid - impl Grid - impl Grid - impl Index for Grid - impl IndexMut for Grid - impl fmt::Display for Grid - impl fmt::Debug for Grid ### src/text.rs - pub struct Span - impl Span - impl From for Span - pub struct Line - impl Line - impl From for Line - impl From for Line - impl From for Line - impl From for Line ### src/lib.rs - pub mod backend - pub mod color - pub mod event - pub mod grid - pub mod layout - pub mod style - pub mod terminal - pub mod text - pub mod tile - pub use backend::Crossterm - pub use backend::software::SoftwareBackend - pub use backend::software::tileset::{Codepage, TilesetBuilder, TilesetError, TilesetOptions} - pub use backend::{Backend, Headless} - pub use color::{AnsiColor, Color, InvalidAnsiIndex} - pub use event::{Event, KeyCode, KeyEvent, KeyModifiers, MouseButton, MouseEvent, MouseEventKind} - pub use grid::{Grid, Pos, Rect, Size} - pub use layout::{HAlign, TextLayout, TextMetrics, VAlign} - pub use style::{CellModifier, Style} - pub use terminal::Terminal - pub use text::{Line, Span} - pub use tile::Tile --- ## README.md ### retroglyph A 2D pseudographic terminal library for Rust. ![crossterm demo](tests/snapshots/crossterm_demo.svg) `retroglyph` provides a styled character grid, double-buffered rendering, and pluggable backends. You drive the game loop; `retroglyph` handles drawing efficiently and feeding you input events. #### Features
Grid API — place styled characters on a multi-layer grid with full color support Up to 256 layers. Each cell carries a glyph, foreground/background color, text modifiers (bold, italic, underline, blink, reverse, dim, hidden, strikethrough), and sub-cell pixel offsets. Layer 0 is always allocated; layers 1+ are allocated on first write — single-layer games pay zero overhead. Colors cover the full spectrum: the terminal's default foreground/background, the 16 standard ANSI colors, the 256-color palette, and 24-bit RGB.
Double buffering — diff-based presentation sends only changed cells `Terminal::present()` compares the current frame against the previous one and forwards only the changed cells to the backend. Pixel-based backends (software renderer) request full frames because sub-cell offsets can leave orphaned pixels from the previous frame.
Stateful drawing API — chainable builder for everyday rendering Set the active style with `fg()`, `bg()`, `modifier()`, then place characters with `put()`. Print strings with `print()` (handles newlines and wide characters), render styled spans with `print_styled()`, or lay out text in a bounded rectangle with `print_box()`. Clear the active layer, all layers, or a rectangular region. Switch layers with `layer(id)`. Or bypass the builder and access the grid directly via `grid_mut()`.
Text layout and word wrapping — styled spans with configurable alignment `Span` and `Line` provide styled text primitives. `TextLayout` is a builder that word-wraps a `Line` to a bounded rectangle, then positions it with independent horizontal and vertical alignment (left/center/right, top/middle/bottom). Measure the result before rendering with `TextLayout::measure()`.
Extended grapheme cluster support — combining marks, emoji, and CJK wide chars With the `egc` feature (enabled by default), the library handles full Unicode grapheme clusters: combining marks, ZWJ emoji sequences, and multi-codepoint characters. CJK characters and emoji automatically occupy two grid columns with a transparent spacer in the adjacent cell. Multi-codepoint graphemes are capped at 8 codepoints to prevent combining-mark bombs.
Pluggable backends — swap rendering targets without touching game logic The `Backend` trait has a small surface: draw cells, flush, poll events, resize, cursor control. - **Headless** — in-memory with no I/O. The workhorse for unit and integration tests. Provides `format_view()` for snapshot testing with insta and `push_event()` for synthetic input. - **Crossterm** (feature `crossterm`) — full terminal with raw mode, alternate screen, and mouse capture. Registers a panic hook to safely restore the terminal on crashes. - **Software** (feature `software`) — pixel-based rendering via winit + softbuffer. Uses a 1-bit bitmap font (embedded VGA 8x16 with `software-default-font`), with sub-cell pixel offsets, multi-layer compositing, configurable scale factor, and a headless mode for pixel-level testing. - **Sprite tilesets** (feature `software-tilesets`) — PNG sprite sheets mapped to a codepage (CP437, Unicode range, or custom), rendered with RGBA alpha blending over bitmap font glyphs.
Input handling — keyboard, mouse, resize, and close events `Terminal::poll(timeout)` returns `Option` with support for keyboard (all standard keys + modifier flags), mouse (buttons, movement, scroll), window resize, and close events. `has_input()` checks for events without blocking. Resize events are automatically applied to the grid before the event reaches your code.
no_std compatible — core crate compiles without std Disable the `std` feature (requires an allocator). Useful for embedded or kernel-space roguelikes.
#### Quick start ```toml [dependencies] retroglyph = { version = "0.1", features = ["crossterm"] } ``` ```rust use retroglyph::{Terminal, backend::Crossterm, color::Color, event::{Event, KeyCode}}; fn main() -> std::io::Result<()> { let mut term = Terminal::new(Crossterm::new()?); loop { term.clear(); term.fg(Color::GREEN); term.put(5, 5, '@'); term.present(); if let Some(Event::Key(k)) = term.poll(std::time::Duration::from_secs(1)) { if k.code == KeyCode::Char('q') { break; } } } Ok(()) } ``` Run the interactive demo: ```sh cargo run --example crossterm_demo --features crossterm ``` --- ## src/tile.rs ### Tile ```rust #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Tile { } ``` A single drawable tile in the terminal grid. Each tile occupies one cell on a single layer (see ADR 008 for the layer model). Sub-cell pixel offsets (`dx`, `dy`) are visual only — they do not affect grid logic or hit-testing. Backends that cannot represent pixel offsets (e.g. `CrosstermBackend`) ignore them. ### impl Default for Tile ```rust impl Default for Tile { } ``` ### impl Tile ```rust impl Tile { pub fn new(glyph: char, style: Style) -> Self; pub fn glyph(&self) -> char; pub fn style(&self) -> Style; pub fn flags(&self) -> TileFlags; pub fn extra(&self) -> Option<&str>; pub fn grapheme(&self) -> Option<&str>; pub fn with_glyph(self, glyph: char) -> Self; pub fn with_style(self, style: Style) -> Self; pub fn with_offset(self, dx: i16, dy: i16) -> Self; } ``` ## src/event.rs ### KeyModifiers ```rust #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] pub struct KeyModifiers(); ``` Keyboard modifier flags. Implemented as a manual bitflag over `u8` rather than using the [`bitflags`](https://crates.io/crates/bitflags) crate to keep the dependency surface minimal for `no_std` environments. Combine with `|`. ### impl KeyModifiers ```rust impl KeyModifiers { pub const NONE: Type; pub const SHIFT: Type; pub const CONTROL: Type; pub const ALT: Type; pub fn contains(self, other: Self) -> bool; pub fn is_empty(self) -> bool; } ``` ### impl BitOr for KeyModifiers ```rust impl BitOr for KeyModifiers { } ``` ### impl BitOrAssign for KeyModifiers ```rust impl BitOrAssign for KeyModifiers { } ``` ### impl BitAnd for KeyModifiers ```rust impl BitAnd for KeyModifiers { } ``` ### impl BitAndAssign for KeyModifiers ```rust impl BitAndAssign for KeyModifiers { } ``` ### impl Not for KeyModifiers ```rust impl Not for KeyModifiers { } ``` ### KeyCode ```rust #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum KeyCode { Char(char), F(u8), Backspace, Enter, Left, Right, Up, Down, Home, End, PageUp, PageDown, Tab, BackTab, Delete, Insert, Escape, } ``` Keyboard key codes. ### KeyEvent ```rust #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct KeyEvent { pub code: KeyCode, pub modifiers: KeyModifiers, } ``` Keyboard input event. ### MouseButton ```rust #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum MouseButton { Left, Right, Middle, } ``` Mouse button identifiers. ### MouseEventKind ```rust #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum MouseEventKind { Down(MouseButton), Up(MouseButton), Moved, ScrollUp, ScrollDown, } ``` Kinds of mouse events. ### MouseEvent ```rust #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct MouseEvent { pub kind: MouseEventKind, pub position: Pos, pub modifiers: KeyModifiers, } ``` Mouse input event. ### Event ```rust #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Event { Key(KeyEvent), Mouse(MouseEvent), Resize(u16, u16), Close, } ``` Terminal input event. ## src/color.rs ### AnsiColor ```rust #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] pub enum AnsiColor { Black, Red, Green, Yellow, Blue, Magenta, Cyan, White, BrightBlack, BrightRed, BrightGreen, BrightYellow, BrightBlue, BrightMagenta, BrightCyan, BrightWhite, } ``` Standard 16-color ANSI palette. Prefer `Ansi` colors when you want your game to respect the user's terminal color theme (e.g., Solarized, Nord, or custom themes). Use `Rgb` for fixed colors that must appear identical regardless of the user's terminal configuration. ### impl AnsiColor ```rust impl AnsiColor { pub fn to_index(self) -> u8; } ``` ### InvalidAnsiIndex ```rust #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct InvalidAnsiIndex(pub u8); ``` Error returned when a `u8` value has no corresponding [`AnsiColor`]. ### impl core::fmt::Display for InvalidAnsiIndex ```rust impl core::fmt::Display for InvalidAnsiIndex { } ``` ### impl TryFrom for AnsiColor ```rust impl TryFrom for AnsiColor { } ``` ### Color ```rust #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] pub enum Color { Default, Ansi(AnsiColor), Indexed(u8), Rgb { r: u8, g: u8, b: u8 }, } ``` Represents a color in the terminal grid. ### impl Color ```rust impl Color { pub const BLACK: Type; pub const RED: Type; pub const GREEN: Type; pub const YELLOW: Type; pub const BLUE: Type; pub const MAGENTA: Type; pub const CYAN: Type; pub const WHITE: Type; pub const BRIGHT_BLACK: Type; pub const BRIGHT_RED: Type; pub const BRIGHT_GREEN: Type; pub const BRIGHT_YELLOW: Type; pub const BRIGHT_BLUE: Type; pub const BRIGHT_MAGENTA: Type; pub const BRIGHT_CYAN: Type; pub const BRIGHT_WHITE: Type; } ``` ## src/layout.rs ### HAlign ```rust #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] pub enum HAlign { Left, Center, Right, } ``` Horizontal alignment within a bounded rectangle. ### VAlign ```rust #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] pub enum VAlign { Top, Middle, Bottom, } ``` Vertical alignment within a bounded rectangle. ### TextMetrics ```rust #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] pub struct TextMetrics { pub width: u16, pub height: u16, } ``` The display dimensions of a laid-out block of text. ### TextLayout ```rust pub struct TextLayout<'a> { } ``` Builder for laying out a [`Line`] within a bounded [`Rect`]. Call [`measure`](TextLayout::measure) to get [`TextMetrics`] without touching any terminal, or [`render`](TextLayout::render) to write directly into a [`Terminal`]. #### Example ``` use retroglyph::layout::{TextLayout, HAlign, VAlign}; use retroglyph::grid::Rect; use retroglyph::text::Line; let rect = Rect::new(0, 0, 20, 5); let line = Line::raw("Hello, world!"); let metrics = TextLayout::new(&line) .rect(rect) .h_align(HAlign::Center) .measure(); assert_eq!(metrics.height, 1); ``` ### impl TextLayout ```rust impl<'a> TextLayout { pub fn new(line: &'a Line) -> Self; pub fn rect(self, rect: Rect) -> Self; pub fn h_align(self, align: HAlign) -> Self; pub fn v_align(self, align: VAlign) -> Self; pub fn measure(&self) -> TextMetrics; pub fn render(&self, terminal: &mut Terminal); } ``` ## src/terminal.rs ### Terminal ```rust pub struct Terminal { } ``` The main entry point for `rg`. Generic over the backend. Owns a double-buffered grid and provides a stateful drawing API. ### impl Terminal ```rust impl Terminal { pub fn new(backend: B) -> Self; pub fn layer(&mut self, layer: u8) -> &mut Self; pub fn fg(&mut self, color: Color) -> &mut Self; pub fn bg(&mut self, color: Color) -> &mut Self; pub fn modifier(&mut self, modifier: CellModifier) -> &mut Self; pub fn reset_style(&mut self) -> &mut Self; pub fn style(&self) -> Style; pub fn size(&self) -> Size; pub fn resize(&mut self, width: u16, height: u16); pub fn put(&mut self, x: u16, y: u16, ch: char); pub fn grid(&self) -> &Grid; pub fn grid_mut(&mut self) -> &mut Grid; pub fn backend(&self) -> &B; pub fn backend_mut(&mut self) -> &mut B; pub fn clear(&mut self); pub fn clear_all(&mut self); pub fn clear_region(&mut self, rect: Rect); pub fn put_styled(&mut self, x: u16, y: u16, ch: char, style: Style); pub fn put_offset(&mut self, x: u16, y: u16, dx: i16, dy: i16, ch: char); pub fn print(&mut self, x: u16, y: u16, text: &str); pub fn print_styled(&mut self, x: u16, y: u16, line: &Line); pub fn print_box(&mut self, rect: Rect, line: &Line, h_align: crate::layout::HAlign, v_align: crate::layout::VAlign); pub fn present(&mut self); pub fn poll(&mut self, timeout: Duration) -> Option; pub fn read(&mut self) -> Event; pub fn has_input(&mut self) -> bool; } ``` ## src/backend/headless.rs ### Headless ```rust pub struct Headless { } ``` In-memory backend for testing. Stores presented content and allows injecting synthetic events. ### impl Headless ```rust impl Headless { pub fn new(width: u16, height: u16) -> Self; pub fn grid(&self) -> &Grid; pub fn cursor_visible(&self) -> bool; pub fn cursor_position(&self) -> Pos; pub fn push_event(&mut self, event: Event); pub fn format_view(&self) -> String; } ``` ### impl Backend for Headless ```rust impl Backend for Headless { } ``` ## src/backend/crossterm.rs ### impl From for crossterm::style::Color ```rust impl From for crossterm::style::Color { } ``` ### impl From for crossterm::style::Attributes ```rust impl From for crossterm::style::Attributes { } ``` ### Crossterm ```rust pub struct Crossterm { } ``` A terminal rendering backend powered by `crossterm`. ### impl Crossterm ```rust impl Crossterm { pub fn new() -> Result; } ``` ### impl Drop for Crossterm ```rust impl Drop for Crossterm { } ``` ### impl Backend for Crossterm ```rust impl Backend for Crossterm { } ``` ### impl TryFrom for crate::event::KeyCode ```rust impl TryFrom for crate::event::KeyCode { } ``` ### impl From for crate::event::KeyModifiers ```rust impl From for crate::event::KeyModifiers { } ``` ### impl From for crate::event::MouseButton ```rust impl From for crate::event::MouseButton { } ``` ### impl TryFrom for crate::event::MouseEventKind ```rust impl TryFrom for crate::event::MouseEventKind { } ``` ### impl TryFrom for crate::event::MouseEvent ```rust impl TryFrom for crate::event::MouseEvent { } ``` ### impl TryFrom for Event ```rust impl TryFrom for Event { } ``` ## src/backend/software/sprite_cache.rs ### Sprite ```rust #[derive(Debug, Clone)] pub struct Sprite { pub pixels: Vec, pub pixel_width: u32, pub pixel_height: u32, pub spacing_cells_x: u16, pub spacing_cells_y: u16, } ``` A decoded, ready-to-blit sprite. ### SpriteCache ```rust #[derive(Debug)] pub struct SpriteCache { } ``` Cache of decoded sprites, keyed by Unicode codepoint. ### impl SpriteCache ```rust impl SpriteCache { pub fn new() -> Self; pub fn get(&self, ch: char) -> Option<&Sprite>; pub fn load(&mut self, opts: &TilesetOptions) -> Result<(), TilesetError>; } ``` ### impl Default for SpriteCache ```rust impl Default for SpriteCache { } ``` ### source_over ```rust pub fn source_over(src: U8x4Rgba, dst: U8x4Rgba) -> U8x4Rgba ``` Per-pixel source-over blending with correct integer math. This is the Porter-Duff `SRC_OVER` operator for straight-alpha pixels: `out = src + dst * (1 - src.a)` for each channel, including alpha. Uses the `alpha-blend` crate's `BlendMode::SourceOver.apply` via f32 conversion as the reference implementation. ## src/backend/software/bitmap_font.rs ### BitmapFont ```rust #[derive(Debug, Clone, Copy)] pub struct BitmapFont { pub glyph_width: u8, pub glyph_height: u8, } ``` A 1-bit-per-pixel bitmap glyph font. `Copy` because it is just a static reference plus three small integers. ### impl BitmapFont ```rust impl BitmapFont { pub fn new(data: &'static [u8], glyph_width: u8, glyph_height: u8, glyph_count: u16) -> Self; pub fn rows(&self, index: u8) -> &[u8]; pub fn char_to_index(&self, ch: char) -> u8; } ``` ### impl PartialEq for BitmapFont ```rust impl PartialEq for BitmapFont { } ``` ### impl Eq for BitmapFont ```rust impl Eq for BitmapFont { } ``` ### FONT ```rust pub const FONT: BitmapFont ``` A [`BitmapFont`] backed by the embedded VGA 8×16 glyph data. ## src/backend/software/config.rs ### SoftwareBackendError ```rust #[derive(Debug)] pub enum SoftwareBackendError { WindowCreation(winit::error::OsError), EventLoop(winit::error::EventLoopError), Softbuffer(softbuffer::SoftBufferError), NoFont, #[cfg(feature = "software-tilesets")] Tileset(super::tileset::TilesetError), } ``` Errors that can occur when initializing or running the software backend. ### impl fmt::Display for SoftwareBackendError ```rust impl fmt::Display for SoftwareBackendError { } ``` ### impl std::error::Error for SoftwareBackendError ```rust impl std::error::Error for SoftwareBackendError { } ``` ### SoftwareBackend ```rust #[derive(Debug, Clone, PartialEq, Eq)] pub struct SoftwareBackend { pub window_title: String, pub font: Option, pub cols: u16, pub rows: u16, pub scale: u8, pub tilesets: Vec, } ``` Configuration and entry point for the software rendering backend. Construct this via [`SoftwareBackendBuilder`], then call either [`run`](SoftwareBackend::run) to open a window or [`run_headless`](SoftwareBackend::run_headless) for headless in-memory rendering. Both methods return or run a [`SoftwareRenderer`](crate::backend::software::SoftwareRenderer) that implements [`Backend`](crate::backend::Backend). #### Examples Windowed mode (requires `software-default-font` feature): ```ignore use retroglyph::backend::software::SoftwareBackendBuilder; use retroglyph::event::{Event, KeyCode}; use std::time::Duration; let backend = SoftwareBackendBuilder::new() .title("My Game") .grid_size(80, 25) .scale(2) .build() .expect("backend init failed"); backend.run_windowed(move |term| { term.clear(); term.print(0, 0, "Hello from rg!"); term.present(); if let Some(event) = term.poll(Duration::from_millis(16)) { match event { Event::Key(k) if k.code == KeyCode::Escape => std::process::exit(0), Event::Close => std::process::exit(0), _ => {} } } }).expect("event loop failed"); ``` Headless mode (useful for testing): ```ignore use retroglyph::backend::software::{SoftwareBackendBuilder, SoftwareRenderer}; use retroglyph::style::Style; use retroglyph::grid::Pos; use retroglyph::Color; let opts = SoftwareBackendBuilder::new() .grid_size(1, 1) .scale(1) .build() .unwrap(); let mut renderer: SoftwareRenderer = opts.run_headless(); // Draw a red cell on layer 0. use retroglyph::tile::Tile; renderer.draw_layers( [(0, Pos::new(0, 0), &Tile { glyph: ' ', style: Style::new().bg(Color::Rgb { r: 255, g: 0, b: 0 }), ..Tile::default() })].into_iter(), ); let pixels = renderer.pixels(); assert!(pixels.iter().all(|&p| p == 0x00FF_0000)); ``` See the `software_demo` example for a complete runnable program. ### impl Default for SoftwareBackend ```rust impl Default for SoftwareBackend { } ``` ### SoftwareBackendBuilder ```rust pub struct SoftwareBackendBuilder { } ``` Builder for [`SoftwareBackend`]. #### Examples ```ignore use retroglyph::backend::software::SoftwareBackendBuilder; // With the `software-default-font` feature the embedded VGA 8×16 font is // used automatically. To supply your own 8×16 bitmap font: // // use retroglyph::backend::software::bitmap_font::BitmapFont; // let my_font = BitmapFont::new(include_bytes!("my_font.bin"), 8, 16, 256); // SoftwareBackendBuilder::new().font(my_font)... let backend = SoftwareBackendBuilder::new() .title("My Game") .grid_size(80, 25) .build() .expect("backend init failed"); ``` ### impl SoftwareBackendBuilder ```rust impl SoftwareBackendBuilder { pub fn new() -> Self; pub fn title(self, title: &str) -> Self; pub fn grid_size(self, cols: u16, rows: u16) -> Self; pub fn scale(self, scale: u8) -> Self; pub fn font(self, font: BitmapFont) -> Self; pub fn tileset(self, opts: TilesetOptions) -> Self; pub fn build(self) -> Result; } ``` ### impl Default for SoftwareBackendBuilder ```rust impl Default for SoftwareBackendBuilder { } ``` ## src/backend/software/windowed.rs ### WindowedBackend ```rust pub trait WindowedBackend: Backend { fn present(&mut self) -> Result<(), SurfaceError>; fn init_surface(&mut self, window: &Arc) -> Result<(), SurfaceError>; fn resize_surface(&mut self, width: u32, height: u32); fn cell_size(&self) -> (u32, u32); fn push_window_event(&mut self, event: Event); } ``` A [`Backend`] that can present rendered frames to a winit window surface. #### Backend-specific behavior | Backend | `present()` | `init_surface()` | |---|---|---| | [`SoftwareRenderer`](super::SoftwareRenderer) | Copies pixel buffer to softbuffer surface | Creates `softbuffer::Context` + `Surface` | | `GlowRenderer` (future) | Uploads data textures + draws full-screen quad | Creates WebGL2 context from canvas | | `WgpuRenderer` (future) | Submits render pass + presents swap chain | Creates `wgpu::Surface` + `Device` | ## src/backend/software/mod.rs ### bitmap_font::BitmapFont ```rust pub use bitmap_font::BitmapFont; ``` ### config::{SoftwareBackend, SoftwareBackendBuilder, SoftwareBackendError} ```rust pub use config::{SoftwareBackend, SoftwareBackendBuilder, SoftwareBackendError}; ``` ### windowed::WindowedBackend ```rust pub use windowed::WindowedBackend; ``` ### SoftwareRenderer ```rust pub struct SoftwareRenderer { } ``` The running half of the software backend. A running software renderer, produced by [`SoftwareBackend::run`] or [`SoftwareBackend::run_headless`]. Unlike [`SoftwareBackend`] (which is just configuration), this type always has an active rendering context — its pixel buffer is always available. The `ctx` field is never `None`, so [`Backend`] methods never panic for missing initialisation. Call [`pixels`](Self::pixels) to inspect the rendered output, or use [`Backend::draw`] and [`Backend::draw_layers`] to render into it. ### SurfaceError ```rust #[derive(Debug)] pub enum SurfaceError { Context(softbuffer::SoftBufferError), Surface(softbuffer::SoftBufferError), } ``` Errors that can occur when initializing a window surface. ### impl core::fmt::Display for SurfaceError ```rust impl core::fmt::Display for SurfaceError { } ``` ### impl std::error::Error for SurfaceError ```rust impl std::error::Error for SurfaceError { } ``` ### impl SoftwareRenderer ```rust impl SoftwareRenderer { pub fn pixels(&self) -> &[u32]; pub fn push_event(&mut self, event: Event); pub fn init_surface(&mut self, window: &Arc) -> Result<(), SurfaceError>; pub fn resize_surface(&mut self, width: u32, height: u32); pub fn present(&mut self) -> Result<(), SurfaceError>; } ``` ### impl SoftwareBackend ```rust impl SoftwareBackend { pub fn run_windowed(self, app_loop: F) -> Result<(), SoftwareBackendError> where F: FnMut + 'static; pub fn run_headless(self) -> SoftwareRenderer; } ``` ### impl Backend for SoftwareRenderer ```rust impl Backend for SoftwareRenderer { } ``` ### impl WindowedBackend for SoftwareRenderer ```rust impl WindowedBackend for SoftwareRenderer { } ``` ### impl WindowApp ```rust impl WindowApp { } ``` ### impl ApplicationHandler for WindowApp ```rust impl ApplicationHandler for WindowApp { } ``` ## src/backend/software/tileset.rs ### TilesetError ```rust #[derive(Debug)] pub enum TilesetError { PngDecode(String), InvalidDimensions(u32, u32, u16, u16), EmptyCodepage, UnsupportedPixelFormat(String), ZeroTileSize, ZeroSpacing, } ``` Errors that can occur during tileset validation or decoding. ### impl fmt::Display for TilesetError ```rust impl fmt::Display for TilesetError { } ``` ### impl std::error::Error for TilesetError ```rust impl std::error::Error for TilesetError { } ``` ### Codepage ```rust #[derive(Debug, Clone, PartialEq, Eq)] pub enum Codepage { Cp437, Unicode { start: char }, Custom(Vec), } ``` Maps row-major tile indices in a sprite sheet to Unicode codepoints. `#[non_exhaustive]` allows adding new variants (e.g. `Cp1252`) without a semver break. ### impl Codepage ```rust impl Codepage { pub fn codepoint(&self, i: usize) -> Option; pub fn len(&self) -> Option; pub fn is_empty(&self) -> bool; } ``` ### CP437_TO_UNICODE ```rust pub const CP437_TO_UNICODE: [char; N] ``` Standard IBM CP437 to Unicode mapping, 256 entries. ### TilesetOptions ```rust #[derive(Debug, Clone, PartialEq, Eq)] pub struct TilesetOptions { pub bytes: Vec, pub tile_width: u16, pub tile_height: u16, pub columns: Option, pub codepage: Codepage, pub spacing_cells_x: u16, pub spacing_cells_y: u16, pub transparent_color: Option<(u8, u8, u8)>, } ``` Options for loading a single tileset (sprite sheet). ### impl TilesetOptions ```rust impl TilesetOptions { pub fn from_bytes(bytes: Vec) -> TilesetBuilder; } ``` ### TilesetBuilder ```rust pub struct TilesetBuilder { } ``` Builder for [`TilesetOptions`]. Construct via [`TilesetOptions::from_bytes`]. #### Example ```ignore use retroglyph::backend::software::tileset::{ Codepage, TilesetOptions, }; let png_data: Vec = vec![]; // real PNG data let opts = TilesetOptions::from_bytes(png_data) .tile_size(16, 16) .start_codepoint('\u{E000}') .spacing(2, 2) .build() .unwrap(); ``` ### impl TilesetBuilder ```rust impl TilesetBuilder { pub fn tile_size(self, width: u16, height: u16) -> Self; pub fn columns(self, cols: u16) -> Self; pub fn codepage(self, codepage: Codepage) -> Self; pub fn start_codepoint(self, start: char) -> Self; pub fn spacing(self, x: u16, y: u16) -> Self; pub fn transparent_color(self, r: u8, g: u8, b: u8) -> Self; pub fn build(self) -> Result; } ``` ## src/backend/mod.rs ### crossterm::Crossterm ```rust pub use crossterm::Crossterm; ``` ### headless::Headless ```rust pub use headless::Headless; ``` ### software::{SoftwareBackend, SoftwareRenderer, WindowedBackend} ```rust pub use software::{SoftwareBackend, SoftwareRenderer, WindowedBackend}; ``` ### Backend ```rust pub trait Backend { fn draw<'a, I>(&mut self, content: I) where I: Iterator; fn draw_layers<'a, I>(&mut self, content: I) where I: Iterator; fn needs_full_frame(&self) -> bool; fn flush(&mut self); fn size(&self) -> Size; fn clear(&mut self); fn resize(&mut self, size: Size); fn poll_event(&mut self, timeout: Duration) -> Option; fn is_connected(&self) -> bool; fn set_cursor_visible(&mut self, visible: bool); fn set_cursor_position(&mut self, position: Pos); fn push_event(&mut self, _event: Event); } ``` A rendering backend that presents grid content to a display and provides input events. ## src/style.rs ### impl core::fmt::Debug for CellModifier ```rust impl core::fmt::Debug for CellModifier { } ``` ### Style ```rust #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] pub struct Style { } ``` A style consisting of foreground, background, and text modifiers. ### impl Style ```rust impl Style { pub fn new() -> Self; pub fn fg(self, color: Color) -> Self; pub fn bg(self, color: Color) -> Self; pub fn bold(self) -> Self; pub fn italic(self) -> Self; pub fn foreground(&self) -> Color; pub fn background(&self) -> Color; pub fn modifiers(&self) -> CellModifier; pub fn patch(self, other: Self) -> Self; } ``` ## src/grid.rs ### Size ```rust #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, PartialOrd, Ord)] pub struct Size { pub width: u16, pub height: u16, } ``` Size of the grid. ### Pos ```rust pub type Pos = ixy::Pos ``` Pos in the grid, in (x = column, y = row) order. Implements [`Ord`] in row-major order (y primary, then x), which is the natural ordering for terminal rendering: top-to-bottom, left-to-right within each row. ### Rect ```rust pub type Rect = ixy::Rect ``` Rectangle in the grid. ### impl From<(u16, u16)> for Size ```rust impl From<(u16, u16)> for Size { } ``` ### impl From for Unknown ```rust impl From for Unknown { } ``` ### Cells ```rust pub struct Cells<'a> { } ``` Iterator over all cells with their `(x, y)` coordinates. ### impl Iterator for Cells ```rust impl<'a> Iterator for Cells { } ``` ### CellsMut ```rust pub struct CellsMut<'a> { } ``` Mutable iterator over all cells with their `(x, y)` coordinates. ### impl Iterator for CellsMut ```rust impl<'a> Iterator for CellsMut { } ``` ### impl LayerBuf ```rust impl LayerBuf { } ``` ### Grid ```rust pub struct Grid { } ``` The main grid container for the terminal. Holds up to 256 layers (0–255). Layer 0 is always allocated; higher layers are allocated on first write. Single-layer games pay no overhead — layers 1+ remain `None` until used. Note: This uses `alloc::vec::Vec`, requiring an allocator in `no_std` environments. For strictly static, no-alloc environments, a static-sized grid type may be added in the future. ### impl Grid ```rust impl Grid { } ``` ### impl Grid ```rust impl Grid { pub fn new(width: u16, height: u16) -> Self; pub fn width(&self) -> u16; pub fn height(&self) -> u16; pub fn put(&mut self, x: u16, y: u16, tile: Tile); pub fn get(&self, x: u16, y: u16) -> &Tile; pub fn checked_put(&mut self, x: u16, y: u16, tile: Tile) -> Option<()>; pub fn checked_get(&self, x: u16, y: u16) -> Option<&Tile>; pub fn checked_get_mut(&mut self, x: u16, y: u16) -> Option<&mut Tile>; pub fn cells(&self, layer: u8) -> Option>; pub fn cells_mut(&mut self, layer: u8) -> CellsMut<'_>; pub fn clear(&mut self, layer: u8); pub fn resize(&mut self, width: u16, height: u16); pub fn write_grapheme(&mut self, x: u16, y: u16, grapheme: &str, style: Style); } ``` ### impl Grid ```rust impl Grid { pub fn put_tile(&mut self, layer: u8, x: u16, y: u16, tile: Tile) -> Option<()>; pub fn get_tile(&self, layer: u8, x: u16, y: u16) -> Option<&Tile>; pub fn layers(&self) -> impl Trait; pub fn clear_all(&mut self); pub fn diff<'a>(&self, other: &'a Self) -> impl Trait; } ``` ### impl Index for Grid ```rust impl Index for Grid { } ``` ### impl IndexMut for Grid ```rust impl IndexMut for Grid { } ``` ### impl fmt::Display for Grid ```rust impl fmt::Display for Grid { } ``` ### impl fmt::Debug for Grid ```rust impl fmt::Debug for Grid { } ``` ## src/text.rs ### Span ```rust #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Span { pub content: String, pub style: Style, } ``` A string with an associated [`Style`]. The building block of styled terminal output. A [`Line`] is composed of one or more `Span`s, each with its own style. #### Examples ``` use retroglyph::text::Span; use retroglyph::style::Style; use retroglyph::color::Color; let plain = Span::raw("hello"); let colored = Span::styled("world", Style::new().fg(Color::GREEN)); ``` ### impl Span ```rust impl Span { pub fn raw(content: impl Trait) -> Self; pub fn styled(content: impl Trait, style: Style) -> Self; pub fn width(&self) -> usize; } ``` ### impl From for Span ```rust impl From for Span { } ``` ### Line ```rust #[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct Line { pub spans: Vec, } ``` A horizontal sequence of [`Span`]s rendered as a single line. #### Examples ``` use retroglyph::text::{Line, Span}; use retroglyph::style::Style; use retroglyph::color::Color; let line = Line::from(vec![ Span::raw("HP: "), Span::styled("100", Style::new().fg(Color::GREEN)), ]); assert_eq!(line.width(), 7); ``` ### impl Line ```rust impl Line { pub fn new() -> Self; pub fn raw(content: impl Trait) -> Self; pub fn width(&self) -> usize; } ``` ### impl From<&str> for Line ```rust impl From<&str> for Line { } ``` ### impl From for Line ```rust impl From for Line { } ``` ### impl From for Line ```rust impl From for Line { } ``` ### impl From> for Line ```rust impl From> for Line { } ``` ## src/lib.rs ### backend::Crossterm ```rust pub use backend::Crossterm; ``` ### backend::software::SoftwareBackend ```rust pub use backend::software::SoftwareBackend; ``` ### backend::software::tileset::{Codepage, TilesetBuilder, TilesetError, TilesetOptions} ```rust pub use backend::software::tileset::{Codepage, TilesetBuilder, TilesetError, TilesetOptions}; ``` ### backend::{Backend, Headless} ```rust pub use backend::{Backend, Headless}; ``` ### color::{AnsiColor, Color, InvalidAnsiIndex} ```rust pub use color::{AnsiColor, Color, InvalidAnsiIndex}; ``` ### event::{Event, KeyCode, KeyEvent, KeyModifiers, MouseButton, MouseEvent, MouseEventKind} ```rust pub use event::{Event, KeyCode, KeyEvent, KeyModifiers, MouseButton, MouseEvent, MouseEventKind}; ``` ### grid::{Grid, Pos, Rect, Size} ```rust pub use grid::{Grid, Pos, Rect, Size}; ``` ### layout::{HAlign, TextLayout, TextMetrics, VAlign} ```rust pub use layout::{HAlign, TextLayout, TextMetrics, VAlign}; ``` ### style::{CellModifier, Style} ```rust pub use style::{CellModifier, Style}; ``` ### terminal::Terminal ```rust pub use terminal::Terminal; ``` ### text::{Line, Span} ```rust pub use text::{Line, Span}; ``` ### tile::Tile ```rust pub use tile::Tile; ```