code wiki / _hdl_build / nx_caption_render_uni.nx

nx_caption_render_uni.nx source

↩ module page · 93 lines · 3796 B

1// nx_caption_render_uni.nx -- UNICODE-aware caption renderer (Latin + Cyrillic) onto a video FRAME (RGBA 2// Framebuffer). Decodes UTF-8 (nx_utf8) per codepoint and dispatches the 8x8 glyph: ASCII printable from 3// nx_font8x8, Cyrillic from nx_font_cyrillic8 (lowercase folded to uppercase). Draws a bottom bar + centered 4// text at integer scale, NO float. This is what makes the Belarus girl's caption render in NATIVE Cyrillic and 5// the Texas boy's in Latin -- the same organ, dispatched by script. license_tier: ORIGINAL 6import "nx_syscalls.nx" 7import "nx_css_color_decode.nx" 8import "nx_paint_solid_rect.nx" 9import "nx_font8x8.nx" 10import "nx_font_cyrillic8.nx" 11import "nx_font_latinext8.nx" 12import "nx_font_cyrillic_ext8.nx" 13import "nx_utf8.nx" 14 15// 8-byte glyph pointer for codepoint cp (0 => blank cell). ascii=font8x8_table(), cyr=cyr8_table(). 16func cr_glyph_ptr(ascii: *u8, cyr: *u8, cp: i64) -> *u8 { 17 if cp == 32 { return 0 as *u8 } 18 if cp >= 0x20 { if cp <= 0x7E { return ((ascii as i64) + (cp - 0x20) * 8) as *u8 } } 19 var u: i64 = cp 20 if u >= 0x430 { if u <= 0x44F { u = u - 0x20 } } // а..я -> А..Я 21 if u == 0x401 { u = 0x415 } // Ё -> Е 22 if u == 0x451 { u = 0x415 } // ё -> Е 23 if u >= 0x410 { if u <= 0x42F { return ((cyr as i64) + (u - 0x410) * 8) as *u8 } } 24 let pl: *u8 = latinext8_glyph(cp) // Polish extended-Latin (ł ą ć ę ń ó ś ź ż) 25 if (pl as i64) != 0 { return pl } 26 let ce: *u8 = cyr_ext_glyph(cp) // Belarusian/Ukrainian Cyrillic (І Ў Є Ї Ґ) 27 if (ce as i64) != 0 { return ce } 28 return 0 as *u8 29} 30// blit one 8x8 glyph (8 bytes, bit0=leftmost) at (x,y) scaled. returns lit pixel count. 31func cr_blit8(fb: *Framebuffer, x: i64, y: i64, g: *u8, scale: i64, color: *CssColor) -> i64 { 32 if (g as i64) == 0 { return 0 } 33 var n: i64 = 0 34 var row: i64 = 0 35 while row < 8 { 36 let bits: i64 = g[row] as i64 37 var col: i64 = 0 38 while col < 8 { 39 if ((bits >> col) & 1) == 1 { 40 nx_paint_solid_rect(fb, x + col*scale, y + row*scale, scale, scale, color) 41 n = n + 1 42 } 43 col = col + 1 44 } 45 row = row + 1 46 } 47 return n 48} 49// count codepoints in a UTF-8 string (for centering) 50func cr_cp_count(text: *u8, len: i64) -> i64 { 51 let pos: *i64 = sys_mmap(8) as *i64 52 *pos = 0 53 var c: i64 = 0 54 while *pos < len { 55 let cp: i64 = utf8_decode_one(text, len, pos) 56 if cp < 0 { *pos = *pos + 1 } else { c = c + 1 } 57 } 58 return c 59} 60// render UTF-8 caption onto fb: bottom bar + centered text at integer scale. returns glyph pixels set. 61func nx_caption_render_uni(fb: *Framebuffer, text: *u8, len: i64, scale: i64, bar: *CssColor, fg: *CssColor) -> i64 { 62 if len <= 0 { return 0 } 63 var sc: i64 = scale 64 if sc < 1 { sc = 1 } 65 let cell_w: i64 = 7 * sc 66 let cell_h: i64 = 8 * sc 67 let pad: i64 = 2 * sc 68 let bar_h: i64 = cell_h + pad + pad 69 var bar_y: i64 = fb.height - bar_h 70 if bar_y < 0 { bar_y = 0 } 71 nx_paint_solid_rect(fb, 0, bar_y, fb.width, bar_h, bar) 72 let ascii: *u8 = font8x8_table() 73 let cyr: *u8 = cyr8_table() 74 let count: i64 = cr_cp_count(text, len) 75 let tw: i64 = count * cell_w 76 var tx: i64 = (fb.width - tw) / 2 77 if tx < 0 { tx = 0 } 78 let ty: i64 = bar_y + pad 79 let pos: *i64 = sys_mmap(8) as *i64 80 *pos = 0 81 var x: i64 = tx 82 var setpx: i64 = 0 83 while *pos < len { 84 let cp: i64 = utf8_decode_one(text, len, pos) 85 if cp < 0 { *pos = *pos + 1 } 86 else { 87 let g: *u8 = cr_glyph_ptr(ascii, cyr, cp) 88 setpx = setpx + cr_blit8(fb, x, ty, g, sc, fg) 89 x = x + cell_w 90 } 91 } 92 return setpx 93}