🔧 Font completo + key repeat para navegación

- Font bitmap 8x8 completo (ASCII 32-126)
- navKeyPressed() ahora detecta key repeat de SDL2
- Exportar default_font desde render module

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
reugenio 2025-12-10 00:50:44 +01:00
parent 296939bb65
commit 14d717d7f4
3 changed files with 202 additions and 57 deletions

View file

@ -354,19 +354,17 @@ pub const InputState = struct {
return self.key_events[0..self.key_event_count]; return self.key_events[0..self.key_event_count];
} }
/// Check if any navigation key was pressed /// Check if any navigation key was pressed (includes key repeat)
pub fn navKeyPressed(self: Self) ?Key { pub fn navKeyPressed(self: Self) ?Key {
if (self.keyPressed(.up)) return .up; // Check key events (includes repeats from SDL2)
if (self.keyPressed(.down)) return .down; for (self.key_events[0..self.key_event_count]) |event| {
if (self.keyPressed(.left)) return .left; if (event.pressed) {
if (self.keyPressed(.right)) return .right; switch (event.key) {
if (self.keyPressed(.home)) return .home; .up, .down, .left, .right, .home, .end, .page_up, .page_down, .tab, .enter, .escape => return event.key,
if (self.keyPressed(.end)) return .end; else => {},
if (self.keyPressed(.page_up)) return .page_up; }
if (self.keyPressed(.page_down)) return .page_down; }
if (self.keyPressed(.tab)) return .tab; }
if (self.keyPressed(.enter)) return .enter;
if (self.keyPressed(.escape)) return .escape;
return null; return null;
} }
}; };

View file

@ -131,55 +131,200 @@ pub const default_font = Font{
.num_chars = 95, .num_chars = 95,
}; };
// 8x8 font data for ASCII 32-126 // 8x8 font data for ASCII 32-126 (complete font)
// Each character is 8 bytes (8 rows, 1 byte per row) // Each character is 8 bytes (8 rows, 1 byte per row)
const default_font_data = blk: { // Based on classic PC BIOS font
// This is a minimal font - in production, use a proper font const default_font_data = [95 * 8]u8{
var data: [95 * 8]u8 = undefined;
// Initialize all to zero
for (&data) |*b| {
b.* = 0;
}
// Space (32) // Space (32)
// Already zero 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// ! (33) // ! (33)
const exclaim = [8]u8{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00 }; 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00,
@memcpy(data[1 * 8 ..][0..8], &exclaim); // " (34)
0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00,
// A (65) // # (35)
const a_upper = [8]u8{ 0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00 }; 0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00,
@memcpy(data[33 * 8 ..][0..8], &a_upper); // $ (36)
0x18, 0x7E, 0xC0, 0x7C, 0x06, 0xFC, 0x18, 0x00,
// B (66) // % (37)
const b_upper = [8]u8{ 0x7C, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x7C, 0x00 }; 0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00,
@memcpy(data[34 * 8 ..][0..8], &b_upper); // & (38)
0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00,
// C (67) // ' (39)
const c_upper = [8]u8{ 0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x00 }; 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
@memcpy(data[35 * 8 ..][0..8], &c_upper); // ( (40)
0x0C, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00,
// ... Add more characters as needed // ) (41)
0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00,
// a (97) // * (42)
const a_lower = [8]u8{ 0x00, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3E, 0x00 }; 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00,
@memcpy(data[65 * 8 ..][0..8], &a_lower); // + (43)
0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00,
// b (98) // , (44)
const b_lower = [8]u8{ 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x00 }; 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30,
@memcpy(data[66 * 8 ..][0..8], &b_lower); // - (45)
0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00,
// . (46)
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00,
// / (47)
0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00,
// 0 (48) // 0 (48)
const zero = [8]u8{ 0x3C, 0x66, 0x6E, 0x76, 0x66, 0x66, 0x3C, 0x00 }; 0x7C, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0x7C, 0x00,
@memcpy(data[16 * 8 ..][0..8], &zero);
// 1 (49) // 1 (49)
const one = [8]u8{ 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00 }; 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00,
@memcpy(data[17 * 8 ..][0..8], &one); // 2 (50)
0x7C, 0xC6, 0x06, 0x7C, 0xC0, 0xC0, 0xFE, 0x00,
break :blk data; // 3 (51)
0x7C, 0xC6, 0x06, 0x3C, 0x06, 0xC6, 0x7C, 0x00,
// 4 (52)
0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x0C, 0x00,
// 5 (53)
0xFE, 0xC0, 0xFC, 0x06, 0x06, 0xC6, 0x7C, 0x00,
// 6 (54)
0x7C, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0x7C, 0x00,
// 7 (55)
0xFE, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00,
// 8 (56)
0x7C, 0xC6, 0xC6, 0x7C, 0xC6, 0xC6, 0x7C, 0x00,
// 9 (57)
0x7C, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x7C, 0x00,
// : (58)
0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00,
// ; (59)
0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30,
// < (60)
0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x00,
// = (61)
0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00,
// > (62)
0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x00,
// ? (63)
0x7C, 0xC6, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00,
// @ (64)
0x7C, 0xC6, 0xDE, 0xDE, 0xDE, 0xC0, 0x7C, 0x00,
// A (65)
0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0x00,
// B (66)
0xFC, 0xC6, 0xC6, 0xFC, 0xC6, 0xC6, 0xFC, 0x00,
// C (67)
0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00,
// D (68)
0xF8, 0xCC, 0xC6, 0xC6, 0xC6, 0xCC, 0xF8, 0x00,
// E (69)
0xFE, 0xC0, 0xC0, 0xF8, 0xC0, 0xC0, 0xFE, 0x00,
// F (70)
0xFE, 0xC0, 0xC0, 0xF8, 0xC0, 0xC0, 0xC0, 0x00,
// G (71)
0x7C, 0xC6, 0xC0, 0xCE, 0xC6, 0xC6, 0x7E, 0x00,
// H (72)
0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00,
// I (73)
0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00,
// J (74)
0x06, 0x06, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00,
// K (75)
0xC6, 0xCC, 0xD8, 0xF0, 0xD8, 0xCC, 0xC6, 0x00,
// L (76)
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0x00,
// M (77)
0xC6, 0xEE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0x00,
// N (78)
0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00,
// O (79)
0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00,
// P (80)
0xFC, 0xC6, 0xC6, 0xFC, 0xC0, 0xC0, 0xC0, 0x00,
// Q (81)
0x7C, 0xC6, 0xC6, 0xC6, 0xD6, 0xDE, 0x7C, 0x06,
// R (82)
0xFC, 0xC6, 0xC6, 0xFC, 0xD8, 0xCC, 0xC6, 0x00,
// S (83)
0x7C, 0xC6, 0xC0, 0x7C, 0x06, 0xC6, 0x7C, 0x00,
// T (84)
0xFE, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00,
// U (85)
0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00,
// V (86)
0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x10, 0x00,
// W (87)
0xC6, 0xC6, 0xC6, 0xD6, 0xFE, 0xEE, 0xC6, 0x00,
// X (88)
0xC6, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0xC6, 0x00,
// Y (89)
0xC6, 0xC6, 0x6C, 0x38, 0x18, 0x18, 0x18, 0x00,
// Z (90)
0xFE, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFE, 0x00,
// [ (91)
0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00,
// \ (92)
0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00,
// ] (93)
0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00,
// ^ (94)
0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00,
// _ (95)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
// ` (96)
0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
// a (97)
0x00, 0x00, 0x7C, 0x06, 0x7E, 0xC6, 0x7E, 0x00,
// b (98)
0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xFC, 0x00,
// c (99)
0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC6, 0x7C, 0x00,
// d (100)
0x06, 0x06, 0x7E, 0xC6, 0xC6, 0xC6, 0x7E, 0x00,
// e (101)
0x00, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0x7C, 0x00,
// f (102)
0x1C, 0x36, 0x30, 0x78, 0x30, 0x30, 0x30, 0x00,
// g (103)
0x00, 0x00, 0x7E, 0xC6, 0xC6, 0x7E, 0x06, 0x7C,
// h (104)
0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x00,
// i (105)
0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00,
// j (106)
0x0C, 0x00, 0x0C, 0x0C, 0x0C, 0x0C, 0xCC, 0x78,
// k (107)
0xC0, 0xC0, 0xCC, 0xD8, 0xF0, 0xD8, 0xCC, 0x00,
// l (108)
0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00,
// m (109)
0x00, 0x00, 0xEC, 0xFE, 0xD6, 0xC6, 0xC6, 0x00,
// n (110)
0x00, 0x00, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x00,
// o (111)
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0x00,
// p (112)
0x00, 0x00, 0xFC, 0xC6, 0xC6, 0xFC, 0xC0, 0xC0,
// q (113)
0x00, 0x00, 0x7E, 0xC6, 0xC6, 0x7E, 0x06, 0x06,
// r (114)
0x00, 0x00, 0xDC, 0xE6, 0xC0, 0xC0, 0xC0, 0x00,
// s (115)
0x00, 0x00, 0x7E, 0xC0, 0x7C, 0x06, 0xFC, 0x00,
// t (116)
0x30, 0x30, 0x7C, 0x30, 0x30, 0x36, 0x1C, 0x00,
// u (117)
0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x00,
// v (118)
0x00, 0x00, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00,
// w (119)
0x00, 0x00, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00,
// x (120)
0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00,
// y (121)
0x00, 0x00, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x7C,
// z (122)
0x00, 0x00, 0xFE, 0x0C, 0x38, 0x60, 0xFE, 0x00,
// { (123)
0x0E, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0E, 0x00,
// | (124)
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00,
// } (125)
0x70, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x70, 0x00,
// ~ (126)
0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}; };
// ============================================================================= // =============================================================================

View file

@ -77,7 +77,9 @@ pub const KeyEvent = macro.KeyEvent;
pub const render = struct { pub const render = struct {
pub const Framebuffer = @import("render/framebuffer.zig").Framebuffer; pub const Framebuffer = @import("render/framebuffer.zig").Framebuffer;
pub const SoftwareRenderer = @import("render/software.zig").SoftwareRenderer; pub const SoftwareRenderer = @import("render/software.zig").SoftwareRenderer;
pub const Font = @import("render/font.zig").Font; const font_module = @import("render/font.zig");
pub const Font = font_module.Font;
pub const default_font = font_module.default_font;
pub const ttf = @import("render/ttf.zig"); pub const ttf = @import("render/ttf.zig");
pub const TtfFont = ttf.TtfFont; pub const TtfFont = ttf.TtfFont;
pub const FontRef = ttf.FontRef; pub const FontRef = ttf.FontRef;