Workspace gains a new xenia-ui member that owns the winit/wgpu window, the Xenos display pipeline (xenos_pipeline + render + texture_cache_host), HUD font/blit shaders, and the input-bridge plumbing the app uses to surface guest framebuffers and overlays. Workspace dependencies grow accordingly: rusqlite is replaced with duckdb (analysis pipeline now writes DuckDB stores), and tracing / metrics / pprof / winit / wgpu / gilrs / pollster / crossbeam / bytemuck are added at workspace level so xenia-ui and xenia-app share versions. Cargo.lock regenerated. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
232 lines
6.9 KiB
Rust
232 lines
6.9 KiB
Rust
//! Minimal 8×8 bitmap font for the HUD.
|
||
//!
|
||
//! Only printable ASCII (0x20..0x7E) is populated. Each glyph is 8 bytes, one
|
||
//! byte per row, MSB = leftmost pixel. This is a bespoke hand-drawn font just
|
||
//! wide enough for status-line text ("Swap: 0x1234 Pad: 0x0040 …"); no
|
||
//! international glyphs, no kerning, no anti-aliasing.
|
||
//!
|
||
//! The font is rendered by uploading the 8×(8·N) atlas as an R8 texture and
|
||
//! sampling one cell per character quad from the HUD shader.
|
||
|
||
pub const CELL_W: u32 = 8;
|
||
pub const CELL_H: u32 = 8;
|
||
pub const FIRST: u8 = 0x20;
|
||
pub const LAST: u8 = 0x7E;
|
||
pub const GLYPH_COUNT: u32 = (LAST as u32) - (FIRST as u32) + 1;
|
||
|
||
/// Build the atlas as a linear R8 buffer, `CELL_W × (CELL_H * GLYPH_COUNT)`,
|
||
/// one glyph per 8-row strip stacked top-to-bottom.
|
||
pub fn build_atlas() -> Vec<u8> {
|
||
let mut out = vec![0u8; (CELL_W * CELL_H * GLYPH_COUNT) as usize];
|
||
for ch in FIRST..=LAST {
|
||
let rows = GLYPHS[(ch - FIRST) as usize];
|
||
for (row, byte) in rows.iter().enumerate() {
|
||
for col in 0..8 {
|
||
let bit = (byte >> (7 - col)) & 1;
|
||
if bit != 0 {
|
||
let idx = ((ch - FIRST) as u32 * CELL_H + row as u32) * CELL_W + col as u32;
|
||
out[idx as usize] = 0xFF;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
out
|
||
}
|
||
|
||
/// 95 glyphs (0x20..0x7E). Each entry is 8 bytes of rows.
|
||
/// Hand-crafted for the HUD lines we actually emit. Most punctuation is
|
||
/// covered; unsupported chars fall through to the space glyph.
|
||
#[rustfmt::skip]
|
||
pub const GLYPHS: [[u8; 8]; 95] = [
|
||
// 0x20 ' '
|
||
[0,0,0,0,0,0,0,0],
|
||
// '!'
|
||
[0x18,0x18,0x18,0x18,0x00,0x00,0x18,0x00],
|
||
// '"'
|
||
[0x36,0x36,0x00,0x00,0x00,0x00,0x00,0x00],
|
||
// '#'
|
||
[0x6C,0xFE,0x6C,0x6C,0x6C,0xFE,0x6C,0x00],
|
||
// '$'
|
||
[0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00],
|
||
// '%'
|
||
[0x00,0xC6,0xCC,0x18,0x30,0x66,0xC6,0x00],
|
||
// '&'
|
||
[0x38,0x6C,0x38,0x76,0xDC,0xCC,0x76,0x00],
|
||
// '\''
|
||
[0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00],
|
||
// '('
|
||
[0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00],
|
||
// ')'
|
||
[0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00],
|
||
// '*'
|
||
[0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00],
|
||
// '+'
|
||
[0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00],
|
||
// ','
|
||
[0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30],
|
||
// '-'
|
||
[0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00],
|
||
// '.'
|
||
[0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00],
|
||
// '/'
|
||
[0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00],
|
||
// '0'
|
||
[0x7C,0xC6,0xCE,0xD6,0xE6,0xC6,0x7C,0x00],
|
||
// '1'
|
||
[0x18,0x38,0x18,0x18,0x18,0x18,0x7E,0x00],
|
||
// '2'
|
||
[0x7C,0xC6,0x06,0x1C,0x30,0x66,0xFE,0x00],
|
||
// '3'
|
||
[0x7C,0xC6,0x06,0x3C,0x06,0xC6,0x7C,0x00],
|
||
// '4'
|
||
[0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x1E,0x00],
|
||
// '5'
|
||
[0xFE,0xC0,0xC0,0xFC,0x06,0xC6,0x7C,0x00],
|
||
// '6'
|
||
[0x38,0x60,0xC0,0xFC,0xC6,0xC6,0x7C,0x00],
|
||
// '7'
|
||
[0xFE,0xC6,0x0C,0x18,0x30,0x30,0x30,0x00],
|
||
// '8'
|
||
[0x7C,0xC6,0xC6,0x7C,0xC6,0xC6,0x7C,0x00],
|
||
// '9'
|
||
[0x7C,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00],
|
||
// ':'
|
||
[0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00],
|
||
// ';'
|
||
[0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30],
|
||
// '<'
|
||
[0x06,0x0C,0x18,0x30,0x18,0x0C,0x06,0x00],
|
||
// '='
|
||
[0x00,0x00,0x7E,0x00,0x7E,0x00,0x00,0x00],
|
||
// '>'
|
||
[0x60,0x30,0x18,0x0C,0x18,0x30,0x60,0x00],
|
||
// '?'
|
||
[0x7C,0xC6,0x0C,0x18,0x18,0x00,0x18,0x00],
|
||
// '@'
|
||
[0x7C,0xC6,0xDE,0xDE,0xDE,0xC0,0x78,0x00],
|
||
// 'A'
|
||
[0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x00],
|
||
// 'B'
|
||
[0xFC,0x66,0x66,0x7C,0x66,0x66,0xFC,0x00],
|
||
// 'C'
|
||
[0x3C,0x66,0xC0,0xC0,0xC0,0x66,0x3C,0x00],
|
||
// 'D'
|
||
[0xF8,0x6C,0x66,0x66,0x66,0x6C,0xF8,0x00],
|
||
// 'E'
|
||
[0xFE,0x62,0x68,0x78,0x68,0x62,0xFE,0x00],
|
||
// 'F'
|
||
[0xFE,0x62,0x68,0x78,0x68,0x60,0xF0,0x00],
|
||
// 'G'
|
||
[0x3C,0x66,0xC0,0xC0,0xCE,0x66,0x3E,0x00],
|
||
// 'H'
|
||
[0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00],
|
||
// 'I'
|
||
[0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00],
|
||
// 'J'
|
||
[0x1E,0x0C,0x0C,0x0C,0xCC,0xCC,0x78,0x00],
|
||
// 'K'
|
||
[0xE6,0x66,0x6C,0x78,0x6C,0x66,0xE6,0x00],
|
||
// 'L'
|
||
[0xF0,0x60,0x60,0x60,0x62,0x66,0xFE,0x00],
|
||
// 'M'
|
||
[0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0x00],
|
||
// 'N'
|
||
[0xC6,0xE6,0xF6,0xDE,0xCE,0xC6,0xC6,0x00],
|
||
// 'O'
|
||
[0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x38,0x00],
|
||
// 'P'
|
||
[0xFC,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00],
|
||
// 'Q'
|
||
[0x7C,0xC6,0xC6,0xC6,0xCE,0x7C,0x0E,0x00],
|
||
// 'R'
|
||
[0xFC,0x66,0x66,0x7C,0x6C,0x66,0xE6,0x00],
|
||
// 'S'
|
||
[0x7C,0xC6,0xE0,0x78,0x0E,0xC6,0x7C,0x00],
|
||
// 'T'
|
||
[0x7E,0x7E,0x5A,0x18,0x18,0x18,0x3C,0x00],
|
||
// 'U'
|
||
[0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00],
|
||
// 'V'
|
||
[0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x00],
|
||
// 'W'
|
||
[0xC6,0xC6,0xC6,0xD6,0xFE,0xEE,0xC6,0x00],
|
||
// 'X'
|
||
[0xC6,0xC6,0x6C,0x38,0x6C,0xC6,0xC6,0x00],
|
||
// 'Y'
|
||
[0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00],
|
||
// 'Z'
|
||
[0xFE,0xC6,0x8C,0x18,0x32,0x66,0xFE,0x00],
|
||
// '['
|
||
[0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00],
|
||
// '\\'
|
||
[0xC0,0x60,0x30,0x18,0x0C,0x06,0x02,0x00],
|
||
// ']'
|
||
[0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00],
|
||
// '^'
|
||
[0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00],
|
||
// '_'
|
||
[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF],
|
||
// '`'
|
||
[0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00],
|
||
// 'a'
|
||
[0x00,0x00,0x78,0x0C,0x7C,0xCC,0x76,0x00],
|
||
// 'b'
|
||
[0xE0,0x60,0x7C,0x66,0x66,0x66,0xDC,0x00],
|
||
// 'c'
|
||
[0x00,0x00,0x7C,0xC6,0xC0,0xC6,0x7C,0x00],
|
||
// 'd'
|
||
[0x1C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00],
|
||
// 'e'
|
||
[0x00,0x00,0x7C,0xC6,0xFE,0xC0,0x7C,0x00],
|
||
// 'f'
|
||
[0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00],
|
||
// 'g'
|
||
[0x00,0x00,0x76,0xCC,0xCC,0x7C,0x0C,0xF8],
|
||
// 'h'
|
||
[0xE0,0x60,0x6C,0x76,0x66,0x66,0xE6,0x00],
|
||
// 'i'
|
||
[0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00],
|
||
// 'j'
|
||
[0x06,0x00,0x0E,0x06,0x06,0x66,0x66,0x3C],
|
||
// 'k'
|
||
[0xE0,0x60,0x66,0x6C,0x78,0x6C,0xE6,0x00],
|
||
// 'l'
|
||
[0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00],
|
||
// 'm'
|
||
[0x00,0x00,0xEC,0xFE,0xD6,0xD6,0xD6,0x00],
|
||
// 'n'
|
||
[0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x00],
|
||
// 'o'
|
||
[0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0x00],
|
||
// 'p'
|
||
[0x00,0x00,0xDC,0x66,0x66,0x7C,0x60,0xF0],
|
||
// 'q'
|
||
[0x00,0x00,0x76,0xCC,0xCC,0x7C,0x0C,0x1E],
|
||
// 'r'
|
||
[0x00,0x00,0xDC,0x76,0x60,0x60,0xF0,0x00],
|
||
// 's'
|
||
[0x00,0x00,0x7E,0xC0,0x7C,0x06,0xFC,0x00],
|
||
// 't'
|
||
[0x30,0x30,0x7C,0x30,0x30,0x36,0x1C,0x00],
|
||
// 'u'
|
||
[0x00,0x00,0xCC,0xCC,0xCC,0xCC,0x76,0x00],
|
||
// 'v'
|
||
[0x00,0x00,0xC6,0xC6,0xC6,0x6C,0x38,0x00],
|
||
// 'w'
|
||
[0x00,0x00,0xC6,0xD6,0xD6,0xFE,0x6C,0x00],
|
||
// 'x'
|
||
[0x00,0x00,0xC6,0x6C,0x38,0x6C,0xC6,0x00],
|
||
// 'y'
|
||
[0x00,0x00,0xC6,0xC6,0xC6,0x7E,0x06,0xFC],
|
||
// 'z'
|
||
[0x00,0x00,0xFE,0x4C,0x18,0x32,0xFE,0x00],
|
||
// '{'
|
||
[0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00],
|
||
// '|'
|
||
[0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00],
|
||
// '}'
|
||
[0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00],
|
||
// '~'
|
||
[0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00],
|
||
];
|