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}