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}