code wiki / (root) / nx_paint_walk_layout_text_test.nx

nx_paint_walk_layout_text_test.nx source

↩ module page · 140 lines · 5446 B

1// nx_paint_walk_layout_text_test.nx -- smoke for the integrated 2// background + TEXT-box rendering walk. Pairs with 3// nx_paint_walk_layout_test (background-only) which still passes 4// because new text rendering is gated on opt-in via 5// nx_paint_ctx_set_text. 6// 7// Fixture: 1-box tree with a single TEXT box at (3, 2) carrying 8// the byte "1". The walk should rasterize the '1' glyph into the 9// framebuffer at that position. 10 11import "nx_syscalls.nx" 12import "nx_css_tokenize.nx" 13import "nx_css_apply.nx" 14import "nx_css_color_decode.nx" 15import "nx_layout_box.nx" 16import "nx_paint_solid_rect.nx" 17import "nx_paint_text.nx" 18import "nx_font_bitmap_5x7.nx" 19import "nx_paint_walk_layout.nx" 20 21func _put_byte(buf: *u8, i: i64, v: i64) -> i64 { 22 buf[i] = v as u8 23 return 0 24} 25 26func main() -> i64 { 27 // Source buffer hosting (a) the text body "1" at offset 0, and 28 // (b) the paint-table's "background-color" property name at 29 // offset 16 (so the table init writes don't clobber the text 30 // body). We give the paint table its OWN 64-byte buffer to 31 // keep concerns clean. 32 let text_src: *u8 = (sys_mmap(32)) as *u8 33 _put_byte(text_src, 0, 49) // '1' 34 35 // Paint table. 36 let table_buf: *u8 = (sys_mmap(64)) as *u8 37 let table: *PaintPropTable = (sys_mmap(NX_PAINT_PROP_TABLE_BYTES as nx_size)) as *PaintPropTable 38 nx_paint_prop_table_init(table, table_buf) 39 40 // Cascade is empty (no background, no styles). 41 let computed: *CssComputedDecl = (sys_mmap(NX_CSS_COMPUTED_DECL_BYTES as nx_size)) as *CssComputedDecl 42 let n_computed: i64 = 0 43 44 // Build 1-box LayoutTree. 45 let max_boxes: i64 = 4 46 let boxes: *LayoutBox = (sys_mmap((max_boxes * NX_LAYOUT_BOX_BYTES) as nx_size)) as *LayoutBox 47 let tree: *LayoutTree = (sys_mmap(NX_LAYOUT_TREE_BYTES as nx_size)) as *LayoutTree 48 nx_layout_tree_init(tree, boxes, max_boxes) 49 let text_idx: i64 = nx_layout_box_append(tree, NX_LAYOUT_BOX_TEXT, 0) 50 51 // Manually position the text box at (3, 2). Set text body to the 52 // byte at offset 0 of text_src, length 1. 53 let tb: *LayoutBox = boxes 54 tb.x = 3 55 tb.y = 2 56 tb.w = 6 57 tb.h = 7 58 nx_layout_box_set_text(tree, text_idx, 0, 1) 59 60 // Framebuffer. 61 let fb_pixels: *u8 = (sys_mmap((32 * 16 * 4) as nx_size)) as *u8 62 let fb: *Framebuffer = (sys_mmap(NX_FRAMEBUFFER_BYTES as nx_size)) as *Framebuffer 63 nx_framebuffer_init(fb, fb_pixels, 32, 16) 64 nx_framebuffer_clear(fb) 65 66 // PaintCtx + opt-in text rendering with BLACK foreground. 67 let ctx: *PaintCtx = (sys_mmap(NX_PAINT_CTX_BYTES as nx_size)) as *PaintCtx 68 // Cascade-source buffer can be the same as text_src (no cascade 69 // decls exist so byte equality isn't exercised). 70 nx_paint_ctx_init(ctx, fb, tree, computed, n_computed, text_src, table) 71 72 let black: *CssColor = (sys_mmap(NX_CSS_COLOR_BYTES as nx_size)) as *CssColor 73 black.r = 0 74 black.g = 0 75 black.b = 0 76 black.a = 255 77 78 nx_paint_ctx_set_text(ctx, text_src, black) 79 80 // Walk: should paint the '1' glyph. 81 let total: i64 = nx_paint_walk_layout(ctx, text_idx) 82 83 // '1' glyph pixel count (per the font row patterns): 84 // row 0 ..#.. 1 pixel 85 // row 1 .##.. 2 pixels 86 // row 2 ..#.. 1 pixel 87 // row 3 ..#.. 1 pixel 88 // row 4 ..#.. 1 pixel 89 // row 5 ..#.. 1 pixel 90 // row 6 .###. 3 pixels 91 // Total = 10 pixels. 92 if total != 10 { return 1 } 93 94 let probe: *CssColor = (sys_mmap(NX_CSS_COLOR_BYTES as nx_size)) as *CssColor 95 96 // Text painted at (3, 2). '1' has its center stroke at col 2 97 // (relative to cell), so the center column should be at x = 5 98 // (= 3 base + 2 col offset). Row 0..6 span y = 2..8. 99 100 // Center stroke is lit at every row. 101 nx_framebuffer_get_pixel(fb, 5, 2, probe) 102 if probe.r != 0 { return 10 } // black foreground; r,g,b all 0 103 if probe.g != 0 { return 11 } 104 if probe.b != 0 { return 12 } 105 if probe.a != 255 { return 13 } // opaque 106 107 // Row 1 has the .##.. pattern: col 1 also lit, plus center col 2. 108 // (x = 3+1 = 4, y = 2+1 = 3) should be lit. 109 nx_framebuffer_get_pixel(fb, 4, 3, probe) 110 if probe.a != 255 { return 20 } 111 112 // Row 6 (bottom): .###. pattern. cols 1, 2, 3 lit. (x = 4, 5, 6 at y = 8). 113 nx_framebuffer_get_pixel(fb, 4, 8, probe) 114 if probe.a != 255 { return 30 } 115 nx_framebuffer_get_pixel(fb, 6, 8, probe) 116 if probe.a != 255 { return 31 } 117 118 // Pixel that should NOT be lit: col 0 (x = 3) at row 0 (y = 2) 119 // (..#.. -> col 0 is 0, so x = 3 is unlit). 120 nx_framebuffer_get_pixel(fb, 3, 2, probe) 121 if probe.a != 0 { return 40 } // untouched -> transparent zero 122 123 // Pixel below the glyph (y = 10) is untouched. 124 nx_framebuffer_get_pixel(fb, 5, 10, probe) 125 if probe.a != 0 { return 50 } 126 127 // ---- Verify text rendering is OFF by default (without 128 // nx_paint_ctx_set_text). Reset everything. ---- 129 nx_framebuffer_clear(fb) 130 let ctx2: *PaintCtx = (sys_mmap(NX_PAINT_CTX_BYTES as nx_size)) as *PaintCtx 131 nx_paint_ctx_init(ctx2, fb, tree, computed, n_computed, text_src, table) 132 // Do NOT call nx_paint_ctx_set_text -- text rendering should 133 // remain disabled. 134 let total2: i64 = nx_paint_walk_layout(ctx2, text_idx) 135 if total2 != 0 { return 60 } // no background-color, no text -> 0 pixels 136 nx_framebuffer_get_pixel(fb, 5, 2, probe) 137 if probe.a != 0 { return 61 } 138 139 return 0 140}