code wiki / (root) / nx_browser_demo_styled.nx

nx_browser_demo_styled.nx source

↩ module page · 150 lines · 5776 B

1// nx_browser_demo_styled.nx -- the closing demo of the day. Renders 2// "NISHI" on a blue background by composing: 3// - HTML "<body>NISHI</body>" via nx_html_tokenizer 4// - LayoutBox tree via nx_layout_from_dom 5// - Manually-populated cascade with body { background-color: #0000ff } 6// so nx_paint_walk_layout fills the body rect blue 7// - nx_paint_ctx_set_text(WHITE) so the text rasterizer paints 8// "NISHI" in white over the blue background 9// - nx_paint_fb_ascii_dump -> stdout 10// 11// Demonstrates that the substrate composes HTML + CSS cascade + 12// layout + background paint + text paint + ASCII output bits-up 13// end-to-end. 14 15import "nx_syscalls.nx" 16import "nx_css_tokenize.nx" 17import "nx_css_apply.nx" 18import "nx_css_color_decode.nx" 19import "nx_html_tokenizer.nx" 20import "nx_layout_box.nx" 21import "nx_layout_default_display.nx" 22import "nx_layout_from_dom.nx" 23import "nx_paint_solid_rect.nx" 24import "nx_paint_text.nx" 25import "nx_paint_walk_layout.nx" 26import "nx_paint_fb_ascii_dump.nx" 27const K_MAGIC_2048: i64 = 2048 28 29func _put_byte(buf: *u8, i: i64, v: i64) -> i64 { 30 buf[i] = v as u8 31 return 0 32} 33 34func main() -> i64 { 35 // HTML source: "<body>NISHI</body>" (18 bytes). 36 let html: *u8 = (sys_mmap(64)) as *u8 37 var p: i64 = 0 38 _put_byte(html, p, 60) p = p + 1 // '<' 39 _put_byte(html, p, 98) p = p + 1 // 'b' 40 _put_byte(html, p, 111) p = p + 1 // 'o' 41 _put_byte(html, p, 100) p = p + 1 // 'd' 42 _put_byte(html, p, 121) p = p + 1 // 'y' 43 _put_byte(html, p, 62) p = p + 1 // '>' 44 _put_byte(html, p, 78) p = p + 1 // 'N' 45 _put_byte(html, p, 73) p = p + 1 // 'I' 46 _put_byte(html, p, 83) p = p + 1 // 'S' 47 _put_byte(html, p, 72) p = p + 1 // 'H' 48 _put_byte(html, p, 73) p = p + 1 // 'I' 49 _put_byte(html, p, 60) p = p + 1 // '<' 50 _put_byte(html, p, 47) p = p + 1 // '/' 51 _put_byte(html, p, 98) p = p + 1 // 'b' 52 _put_byte(html, p, 111) p = p + 1 // 'o' 53 _put_byte(html, p, 100) p = p + 1 // 'd' 54 _put_byte(html, p, 121) p = p + 1 // 'y' 55 _put_byte(html, p, 62) p = p + 1 // '>' 56 let html_len: i64 = p 57 58 // Build LayoutBox tree from HTML. 59 let max_boxes: i64 = 16 60 let boxes: *LayoutBox = (sys_mmap((max_boxes * NX_LAYOUT_BOX_BYTES) as nx_size)) as *LayoutBox 61 let tree: *LayoutTree = (sys_mmap(NX_LAYOUT_TREE_BYTES as nx_size)) as *LayoutTree 62 nx_layout_tree_init(tree, boxes, max_boxes) 63 64 let stk_idx: *i64 = (sys_mmap(64)) as *i64 65 let stk: *LayoutFromDomStack = (sys_mmap(NX_LAYOUT_FROM_DOM_STACK_BYTES as nx_size)) as *LayoutFromDomStack 66 nx_layout_from_dom_stack_init(stk, stk_idx, 8) 67 68 let root: i64 = nx_layout_from_dom(html, html_len, tree, stk) 69 if root != 0 { return 1 } 70 71 // Tree: box 0 = root, box 1 = body, box 2 = text "NISHI". 72 // Position root + body to fill the framebuffer; text inside. 73 let r_box: *LayoutBox = boxes 74 r_box.x = 0 75 r_box.y = 0 76 r_box.w = 48 77 r_box.h = 11 78 79 let body_box: *LayoutBox = (boxes as *u8 + (1 as nx_size) * (NX_LAYOUT_BOX_BYTES as nx_size)) as *LayoutBox 80 body_box.x = 0 81 body_box.y = 0 82 body_box.w = 48 83 body_box.h = 11 84 85 let text_box: *LayoutBox = (boxes as *u8 + (2 as nx_size) * (NX_LAYOUT_BOX_BYTES as nx_size)) as *LayoutBox 86 text_box.x = 2 87 text_box.y = 2 88 89 // Paint table holds the canonical "background-color" property 90 // name at a known offset; for the cascade lookup to byte-equal, 91 // the cascade source buffer's property region must match. We 92 // give the paint table its own buffer and copy the property 93 // bytes into the cascade buffer. 94 let table_buf: *u8 = (sys_mmap(64)) as *u8 95 let table: *PaintPropTable = (sys_mmap(NX_PAINT_PROP_TABLE_BYTES as nx_size)) as *PaintPropTable 96 nx_paint_prop_table_init(table, table_buf) 97 98 // Cascade source: separate buffer with "background-color" at 99 // offset 0, then the blue hex "0000ff" at offset 16. 100 let cascade_buf: *u8 = (sys_mmap(64)) as *u8 101 var i: i64 = 0 102 while i < table.background_color_len { 103 cascade_buf[i] = table_buf[table.background_color_off + i] 104 i = i + 1 105 } 106 // "0000ff" at offset 16 (blue). 107 _put_byte(cascade_buf, 16, 48) // '0' 108 _put_byte(cascade_buf, 17, 48) 109 _put_byte(cascade_buf, 18, 48) 110 _put_byte(cascade_buf, 19, 48) 111 _put_byte(cascade_buf, 20, 102) // 'f' 112 _put_byte(cascade_buf, 21, 102) 113 114 // One CssComputedDecl: body's background-color -> blue. 115 let computed: *CssComputedDecl = (sys_mmap(NX_CSS_COMPUTED_DECL_BYTES as nx_size)) as *CssComputedDecl 116 computed.element_idx = 1 // box 1 is body 117 computed.prop_off = 0 118 computed.prop_len = table.background_color_len 119 computed.val_kind = NX_CSS_VAL_HEXCOLOR 120 computed.val_off = 16 121 computed.val_len = 6 122 computed.unit_off = 0 123 computed.unit_len = 0 124 125 // Framebuffer. 126 let w: i64 = 48 127 let h: i64 = 11 128 let pixels: *u8 = (sys_mmap((w * h * 4) as nx_size)) as *u8 129 let fb: *Framebuffer = (sys_mmap(NX_FRAMEBUFFER_BYTES as nx_size)) as *Framebuffer 130 nx_framebuffer_init(fb, pixels, w, h) 131 nx_framebuffer_clear(fb) 132 133 let ctx: *PaintCtx = (sys_mmap(NX_PAINT_CTX_BYTES as nx_size)) as *PaintCtx 134 nx_paint_ctx_init(ctx, fb, tree, computed, 1, cascade_buf, table) 135 136 let white: *CssColor = (sys_mmap(NX_CSS_COLOR_BYTES as nx_size)) as *CssColor 137 white.r = 255 138 white.g = 255 139 white.b = 255 140 white.a = 255 141 nx_paint_ctx_set_text(ctx, html, white) 142 143 nx_paint_walk_layout(ctx, root) 144 145 let out_buf: *u8 = (sys_mmap(K_MAGIC_2048)) as *u8 146 let n: i64 = nx_paint_fb_ascii_dump(fb, out_buf, K_MAGIC_2048) 147 if n < 0 { return 2 } 148 sys_write(1, out_buf, n) 149 return 0 150}