code wiki / (root) / nx_font_1bpp.nx

nx_font_1bpp.nx source

↩ module page · 115 lines · 4069 B

1// nx_font_1bpp.nx -- bitmap font (caller-supplied glyph data). 2// 3// Substrate-layer font primitive. Caller supplies the glyph bytes 4// (e.g., a public-domain 5x7 monospace ASCII font), substrate 5// provides the lookup + bounds-checking. Designed for SSD1306-class 6// 1bpp displays where 5x7 = 35 bits = 5 bytes per glyph (with 7// vertical-byte layout matching the framebuffer). 8// 9// Glyph layout: each glyph_width column is one byte (top bit = top 10// pixel for fonts up to height 8). For height > 8, multiple bytes 11// per column (caller arranges). 12// 13// Composes: 14// nx_fb_1bpp -- destination framebuffer 15// nx_text_render -- draws strings using this font primitive 16// 17// V1 ships: 18// - struct NxFont with caller-allocated glyph data 19// - new + glyph_at for lookup 20// - glyph_width / glyph_height getters 21// 22// Gap list: 23// - no variable-width font support yet (monospace V1) 24// - no anti-aliasing (1bpp by design) 25// - no UTF-8 (ASCII only V1) 26 27import "nx_syscalls.nx" 28import "nx_tier.nx" 29 30const NX_FT_OK: nx_int = 0 31const NX_FT_ERR_BAD_CHAR: nx_int = 1 32const NX_FT_ERR_BAD_DIM: nx_int = 2 33 34// ===== Struct: NxFont ============================================= 35 36struct NxFont { 37 glyph_data: *u8, // glyph_count * glyph_bytes_per_glyph 38 glyph_width: nx_size, // column count per glyph 39 glyph_height: nx_size, // row count per glyph 40 glyph_count: nx_int, 41 base_char: nx_int, // first ASCII character in table 42 bytes_per_glyph: nx_size, // = glyph_width * ((glyph_height + 7) / 8) 43} 44 45func nx_font_new(glyph_data: *u8, 46 glyph_width: nx_size, 47 glyph_height: nx_size, 48 glyph_count: nx_int, 49 base_char: nx_int) -> *NxFont { 50 if glyph_width == 0 { return (0 as i64) as *NxFont } 51 if glyph_height == 0 { return (0 as i64) as *NxFont } 52 if glyph_count <= 0 { return (0 as i64) as *NxFont } 53 let f: *NxFont = (sys_mmap(48)) as *NxFont 54 f.glyph_data = glyph_data 55 f.glyph_width = glyph_width 56 f.glyph_height = glyph_height 57 f.glyph_count = glyph_count 58 f.base_char = base_char 59 f.bytes_per_glyph = glyph_width * ((glyph_height + 7) / 8) 60 return f 61} 62 63// ===== nx_font_glyph_at =========================================== 64// 65// Returns pointer to the start of glyph data for character ch. 66// Returns NULL if ch is outside the font's range. Caller iterates 67// the bytes_per_glyph bytes there to render. 68 69func nx_font_glyph_at(f: *NxFont, ch: nx_int) -> *u8 { 70 let idx: nx_int = ch - f.base_char 71 if idx < 0 { return (0 as i64) as *u8 } 72 if idx >= f.glyph_count { return (0 as i64) as *u8 } 73 let off: nx_size = (idx as nx_size) * f.bytes_per_glyph 74 return (f.glyph_data as i64 + off as i64) as *u8 75} 76 77func nx_font_has_char(f: *NxFont, ch: nx_int) -> nx_int { 78 let idx: nx_int = ch - f.base_char 79 if idx < 0 { return 0 } 80 if idx >= f.glyph_count { return 0 } 81 return 1 82} 83 84func nx_font_glyph_width(f: *NxFont) -> nx_size { 85 return f.glyph_width 86} 87 88func nx_font_glyph_height(f: *NxFont) -> nx_size { 89 return f.glyph_height 90} 91 92func nx_font_bytes_per_glyph(f: *NxFont) -> nx_size { 93 return f.bytes_per_glyph 94} 95 96// ===== nx_font_glyph_pixel ======================================== 97// 98// Get the pixel value (0 or 1) at (col, row) within glyph for ch. 99// Layout: vertical bytes — col*ceil(h/8) bytes per column, MSB at 100// bottom of column-group (matching SSD1306 page layout convention). 101 102func nx_font_glyph_pixel(f: *NxFont, ch: nx_int, 103 col: nx_size, row: nx_size) -> nx_int { 104 if col >= f.glyph_width { return 0 } 105 if row >= f.glyph_height { return 0 } 106 let g: *u8 = nx_font_glyph_at(f, ch) 107 if (g as i64) == 0 { return 0 } 108 let page: nx_size = row / 8 109 let bit_in_page: nx_size = row - (page * 8) 110 let bytes_per_col: nx_size = (f.glyph_height + 7) / 8 111 let byte_off: nx_size = col * bytes_per_col + page 112 let b: nx_int = (g[byte_off] as i64) & 255 113 if (b & (1 << bit_in_page)) != 0 { return 1 } 114 return 0 115}