code wiki / _hdl_build / nx_css_boxmap_test.nx
nx_css_boxmap_test.nx source
↩ module page · 154 lines · 7972 B
1// nx_css_boxmap_test.nx -- styling rung 3: map the cascade onto LAYOUT BOXES. nx_layout_block looks up
2// computed style by box-index (cd.element_idx == box_idx), and the tree has a synthetic root + text +
3// anonymous boxes, so we build a CssElement[] indexed BY BOX: each element box (BLOCK/INLINE, not the
4// root, not text/anon) gets the next document-order extracted element's tag/id/class; text/anon blank.
5// Then nx_css_apply -> computed decls keyed by box_idx -> layout/paint lookups hit. Gate proves the h1
6// BOX receives font-size:32px (alignment correct). expect_exit: 0.
7import "nx_syscalls.nx"
8import "nx_html_tokenizer.nx"
9import "nx_dom_query.nx"
10import "nx_css_selector_match.nx"
11import "nx_css_tokenize.nx"
12import "nx_css_parse.nx"
13import "nx_css_apply.nx"
14import "nx_layout_box.nx"
15import "nx_layout_default_display.nx"
16import "nx_layout_from_dom.nx"
17
18func bm_slen(s: *u8) -> i64 { var k: i64=0; while s[k]!=(0 as u8){k=k+1} return k }
19func bm_puts(s: *u8) -> i64 { sys_write(1, s, bm_slen(s)); return 0 }
20func bm_pn(v: i64) -> i64 { let b: *u8=sys_mmap(20); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m}; let t: *u8=sys_mmap(20); var k: i64=0; if m==0{t[0]=48;k=1}; while m>0{t[k]=48+(m%10);m=m/10;k=k+1}; var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1}; sys_write(1,b,k); return 0 }
21func bm_region_is(src: *u8, off: i64, len: i64, lit: *u8) -> i64 {
22 let ll: i64 = bm_slen(lit)
23 if len != ll { return 0 }
24 var i: i64 = 0
25 while i < ll { if (src[off+i] & 0xff) != (lit[i] & 0xff) { return 0 } i = i + 1 }
26 return 1
27}
28// extract elements from HTML (doc order, tags + id/class), like rung 1.
29func bm_extract(html: *u8, hlen: i64, elements: *CssElement, maxn: i64) -> i64 {
30 let c: *HtmlCursor = sys_mmap(24) as *HtmlCursor
31 nx_html_cursor_init(c, html, hlen)
32 let tok: *HtmlToken = sys_mmap(56) as *HtmlToken
33 let ao: *i64=sys_mmap(8) as *i64; let al: *i64=sys_mmap(8) as *i64; let bo: *i64=sys_mmap(8) as *i64; let bl: *i64=sys_mmap(8) as *i64
34 var n: i64 = 0
35 while 1 == 1 {
36 nx_html_next_token(c, tok)
37 if tok.kind == NX_HTML_TOK_EOF { return n }
38 if n >= maxn { return n }
39 var ie: i64 = 0
40 if tok.kind == NX_HTML_TOK_START_TAG { ie = 1 }
41 if tok.kind == NX_HTML_TOK_SELF_CLOSING { ie = 1 }
42 if ie == 1 {
43 let e: *CssElement = ((elements as i64) + n * NX_CSS_ELEMENT_BYTES) as *CssElement
44 e.src = html
45 e.tag_off = tok.name_off; e.tag_len = tok.name_len
46 if nx_dom_find_attr(html, tok.src_off, tok.src_len, "id\x00" as *u8, ao, al) == 1 { e.id_off=ao[0]; e.id_len=al[0] } else { e.id_off=0; e.id_len=0 }
47 if nx_dom_find_attr(html, tok.src_off, tok.src_len, "class\x00" as *u8, bo, bl) == 1 { e.class_off=bo[0]; e.class_len=bl[0] } else { e.class_off=0; e.class_len=0 }
48 n = n + 1
49 }
50 }
51 return n
52}
53func bm_is_elem_kind(k: i64) -> i64 {
54 if k == NX_LAYOUT_BOX_BLOCK { return 1 }
55 if k == NX_LAYOUT_BOX_INLINE { return 1 }
56 if k == NX_LAYOUT_BOX_INLINE_BLOCK { return 1 }
57 return 0
58}
59
60func main() -> i64 {
61 let htmls: *u8 = "<html><body><h1 id='t'>Hi</h1><a href='/y'>L</a><p>x</p></body></html>\x00"
62 let csss: *u8 = "h1{font-size:32px}a{color:#0000ff}\x00"
63 let hlen: i64 = bm_slen(htmls)
64 let clen: i64 = bm_slen(csss)
65 let total: i64 = hlen + clen
66 let buf: *u8 = sys_mmap(total + 16)
67 var i: i64 = 0
68 while i < hlen { buf[i] = htmls[i]; i = i + 1 }
69 i = 0
70 while i < clen { buf[hlen + i] = csss[i]; i = i + 1 }
71
72 // extracted elements (doc order, tags), src = combined buffer
73 let ext: *CssElement = (sys_mmap(NX_CSS_ELEMENT_BYTES * 64) as nx_size) as *CssElement
74 let n_ext: i64 = bm_extract(buf, hlen, ext, 64)
75
76 // layout the HTML part -> box tree
77 let boxes: *LayoutBox = (sys_mmap(NX_LAYOUT_BOX_BYTES * 512 + 16)) as *LayoutBox
78 let tree: *LayoutTree = (sys_mmap(64)) as *LayoutTree
79 nx_layout_tree_init(tree, boxes, 512)
80 let stk: *LayoutFromDomStack = (sys_mmap(NX_LAYOUT_FROM_DOM_STACK_BYTES + 8)) as *LayoutFromDomStack
81 let stk_idx: *i64 = (sys_mmap(8 * 128)) as *i64
82 nx_layout_from_dom_stack_init(stk, stk_idx, 128)
83 nx_layout_from_dom(buf, hlen, tree, stk)
84
85 // build CssElement[] indexed BY BOX INDEX
86 let boxel: *CssElement = (sys_mmap((NX_CSS_ELEMENT_BYTES * (tree.count + 1)) as nx_size)) as *CssElement
87 var k: i64 = 0
88 var h1_box: i64 = 0 - 1
89 i = 0
90 while i < tree.count {
91 let b: *LayoutBox = ((tree.boxes as i64) + i * NX_LAYOUT_BOX_BYTES) as *LayoutBox
92 let e: *CssElement = ((boxel as i64) + i * NX_CSS_ELEMENT_BYTES) as *CssElement
93 e.src = buf
94 var mapped: i64 = 0
95 if bm_is_elem_kind(b.kind) == 1 { if b.parent_idx != (0 - 1) { if k < n_ext {
96 let s: *CssElement = ((ext as i64) + k * NX_CSS_ELEMENT_BYTES) as *CssElement
97 e.tag_off = s.tag_off; e.tag_len = s.tag_len
98 e.id_off = s.id_off; e.id_len = s.id_len
99 e.class_off = s.class_off; e.class_len = s.class_len
100 if bm_region_is(buf, s.tag_off, s.tag_len, "h1\x00" as *u8) == 1 { h1_box = i }
101 k = k + 1
102 mapped = 1
103 } } }
104 if mapped == 0 { e.tag_off=0; e.tag_len=0; e.id_off=0; e.id_len=0; e.class_off=0; e.class_len=0 }
105 i = i + 1
106 }
107
108 // parse the UA CSS region + cascade over boxel (tree.count entries)
109 let cur: *CssCursor = (sys_mmap(NX_CSS_CURSOR_BYTES) as nx_size) as *CssCursor
110 nx_css_cursor_init(cur, buf, total)
111 cur.pos = hlen
112 let tok: *CssToken = (sys_mmap(NX_CSS_TOKEN_BYTES) as nx_size) as *CssToken
113 let rules: *CssRule = (sys_mmap(NX_CSS_RULE_BYTES * 32) as nx_size) as *CssRule
114 let decls: *CssDeclaration = (sys_mmap(NX_CSS_DECLARATION_BYTES * 64) as nx_size) as *CssDeclaration
115 let st: *CssParseState = (sys_mmap(128) as nx_size) as *CssParseState
116 nx_css_parse_state_init(st, cur, tok, rules, 32, decls, 64)
117 nx_css_parse(st)
118 let computed: *CssComputedDecl = (sys_mmap(NX_CSS_COMPUTED_DECL_BYTES * 256) as nx_size) as *CssComputedDecl
119 let cb: *i64 = (sys_mmap(8)) as *i64
120 nx_css_apply(buf, rules, st.rule_count, decls, st.decl_count, boxel, tree.count, computed, 256, cb)
121 let ncomp: i64 = cb[0]
122
123 var pass: i64 = 0
124 var tot: i64 = 0
125 bm_puts("nx_css_boxmap gate (styling rung 3: cascade keyed by BOX index)\n" as *u8)
126
127 // ---- KAT1: every extracted element got mapped to an element box (k == n_ext) ----
128 var r1: i64 = 0
129 if k == n_ext { if n_ext == 5 { r1 = 1 } }
130 if r1 == 1 { bm_puts(" PASS KAT1 element-boxes mapped = extracted elements = 5 (html/body/h1/a/p)\n" as *u8); pass=pass+1 } else { bm_puts(" FAIL KAT1 k=" as *u8); bm_pn(k); bm_puts(" n_ext=" as *u8); bm_pn(n_ext); bm_puts(" boxes=" as *u8); bm_pn(tree.count); bm_puts("\n" as *u8) }
131 tot = tot + 1
132
133 // ---- KAT2: the h1 BOX received computed font-size 32 (alignment correct) ----
134 var r2: i64 = 0
135 if h1_box >= 0 {
136 var j: i64 = 0
137 while j < ncomp {
138 let cd: *CssComputedDecl = ((computed as i64) + j * NX_CSS_COMPUTED_DECL_BYTES) as *CssComputedDecl
139 if cd.element_idx == h1_box {
140 if bm_region_is(buf, cd.prop_off, cd.prop_len, "font-size\x00" as *u8) == 1 {
141 if bm_region_is(buf, cd.val_off, cd.val_len, "32\x00" as *u8) == 1 { r2 = 1 }
142 }
143 }
144 j = j + 1
145 }
146 }
147 if r2 == 1 { bm_puts(" PASS KAT2 the h1 BOX (idx " as *u8); bm_pn(h1_box); bm_puts(") got computed font-size 32 -> cascade aligns to boxes\n" as *u8); pass=pass+1 } else { bm_puts(" FAIL KAT2 h1_box=" as *u8); bm_pn(h1_box); bm_puts(" ncomp=" as *u8); bm_pn(ncomp); bm_puts("\n" as *u8) }
148 tot = tot + 1
149
150 bm_puts("---- nx_css_boxmap gate: passed " as *u8); bm_pn(pass); bm_puts(" / " as *u8); bm_pn(tot); bm_puts("\n" as *u8)
151 if pass == tot { sys_exit(0); return 0 }
152 sys_exit(1)
153 return 1
154}