code wiki / _hdl_build / nx_css_boxmodel_gate.nx

nx_css_boxmodel_gate.nx source

↩ module page · 143 lines · 7816 B

1// nx_css_boxmodel_gate.nx -- PROOF (re-runnable) of the S21 height-axis rung: `padding`/`margin` 2// SHORTHANDS and the `font` shorthand's font-size now shape layout. Real pages set the box model almost 3// entirely through shorthands, which the longhand-only lookups ignored -> we rendered ~40% denser than 4// Chrome. Every test runs the REAL br_layout on an inline fixture and asserts EXACT geometry: 5// T1 padding:8px 12px -> the padded block grows 16px taller AND its text indents 12px 6// T2 margin:10px 0 30px -> vertical rhythm between two paragraphs == 17+10+30 = 57px 7// T3 margin:2em 0 (fs 20) -> em resolves against the INHERITED font-size (40px) 8// T4 font:15px/1.55 ... -> BOTH resolvers (layout inherited + paint br_comp_fontsize_inh) read 15 9// T5 longhand priority -> padding:8px 12px + padding-top:1px -> top is 1 (longhand wins) 10// T6 CAN-FAIL control -> the same fixtures WITHOUT shorthands do NOT move (the deltas are real) 11// license_tier: ORIGINAL expect_exit: 0 12import "nx_syscalls.nx" 13import "nx_browser_render.nx" 14 15func bm_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 16func bm_n(v: i64) -> i64 { let t: *u8=sys_mmap(24); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m} var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} let b: *u8=sys_mmap(24); var j: i64=0; while j<k{b[j]=t[k-1-j];j=j+1} sys_write(1,b,k); return 0 } 17func bm_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 18func bm_box(t: *LayoutTree, i: i64) -> *LayoutBox { 19 return (t.boxes as *u8 + (i as nx_size) * (NX_LAYOUT_BOX_BYTES as nx_size)) as *LayoutBox 20} 21func bm_has(src: *u8, off: i64, len: i64, m: *u8) -> i64 { 22 let ml: i64 = bm_slen(m) 23 if ml == 0 { return 0 } 24 var i: i64 = 0 25 while i + ml <= len { 26 var k: i64 = 0 27 var ok: i64 = 1 28 while k < ml { if (src[off+i+k]&0xff) != (m[k]&0xff) { ok = 0; k = ml } else { k = k + 1 } } 29 if ok == 1 { return 1 } 30 i = i + 1 31 } 32 return 0 33} 34func bm_layout(html: *u8) -> *Page { 35 let page: *Page = sys_mmap(NX_PAGE_BYTES) as *Page 36 page.raw = html 37 page.raw_len = bm_slen(html) 38 page.dark_mode = 0 39 br_layout(page, 1024) 40 return page 41} 42// find the TEXT box containing marker; return it (0 if absent) 43func bm_find(page: *Page, marker: *u8) -> *LayoutBox { 44 let t: *LayoutTree = page.tree 45 var i: i64 = 0 46 while i < t.count { 47 let b: *LayoutBox = bm_box(t, i) 48 if b.text_len > 0 { if bm_has(page.buf, b.text_off, b.text_len, marker) == 1 { return b } } 49 i = i + 1 50 } 51 return 0 as *LayoutBox 52} 53// find the text box's PARENT block 54func bm_parent(page: *Page, marker: *u8) -> *LayoutBox { 55 let tb: *LayoutBox = bm_find(page, marker) 56 if (tb as i64) == 0 { return 0 as *LayoutBox } 57 if tb.parent_idx < 0 { return 0 as *LayoutBox } 58 return bm_box(page.tree, tb.parent_idx) 59} 60 61func main() -> i64 { 62 bm_w("=== nx_css_boxmodel_gate -- padding/margin/font SHORTHANDS shape layout (S21 height axis) ===\n" as *u8) 63 var fails: i64 = 0 64 65 // T1: padding shorthand -- div grows 2x8=16 taller than the control; text indents 12 66 let p1: *Page = bm_layout("<html><head><style>div{padding:8px 12px}</style></head><body><div>alphabeta</div></body></html>\x00" as *u8) 67 let c1: *Page = bm_layout("<html><body><div>alphabeta</div></body></html>\x00" as *u8) 68 let b1: *LayoutBox = bm_parent(p1, "alphabeta\x00" as *u8) 69 let k1: *LayoutBox = bm_parent(c1, "alphabeta\x00" as *u8) 70 let t1t: *LayoutBox = bm_find(p1, "alphabeta\x00" as *u8) 71 let k1t: *LayoutBox = bm_find(c1, "alphabeta\x00" as *u8) 72 bm_w(" T1 padding:8px 12px h=" as *u8) 73 var t1ok: i64 = 0 74 if (b1 as i64) != 0 { if (k1 as i64) != 0 { 75 bm_n(b1.h); bm_w(" (ctl " as *u8); bm_n(k1.h); bm_w(") text-x=" as *u8); bm_n(t1t.x); bm_w(" (ctl " as *u8); bm_n(k1t.x); bm_w(")" as *u8) 76 if b1.h == k1.h + 16 { if t1t.x == k1t.x + 12 { t1ok = 1 } } 77 } } 78 if t1ok == 1 { bm_w(" PASS\n" as *u8) } else { fails=fails+1; bm_w(" FAIL\n" as *u8) } 79 80 // T2: margin shorthand vertical rhythm: y(second) - y(first) == 17 + 10 + 30 = 57 81 let p2: *Page = bm_layout("<html><head><style>p{margin:10px 0 30px}</style></head><body><p>first</p><p>second</p></body></html>\x00" as *u8) 82 let a2: *LayoutBox = bm_find(p2, "first\x00" as *u8) 83 let b2: *LayoutBox = bm_find(p2, "second\x00" as *u8) 84 bm_w(" T2 margin:10px 0 30px dy=" as *u8) 85 var t2ok: i64 = 0 86 if (a2 as i64) != 0 { if (b2 as i64) != 0 { 87 bm_n(b2.y - a2.y); bm_w(" (want 57)" as *u8) 88 if b2.y - a2.y == 57 { t2ok = 1 } 89 } } 90 if t2ok == 1 { bm_w(" PASS\n" as *u8) } else { fails=fails+1; bm_w(" FAIL\n" as *u8) } 91 92 // T3: em margins resolve against the INHERITED font-size (body 20px -> 2em = 40) 93 let p3: *Page = bm_layout("<html><head><style>body{font-size:20px}p{margin:2em 0}</style></head><body><p>first</p><p>second</p></body></html>\x00" as *u8) 94 let a3: *LayoutBox = bm_find(p3, "first\x00" as *u8) 95 let b3: *LayoutBox = bm_find(p3, "second\x00" as *u8) 96 bm_w(" T3 margin:2em 0 @fs20 dy=" as *u8) 97 var t3ok: i64 = 0 98 if (a3 as i64) != 0 { if (b3 as i64) != 0 { 99 let want3: i64 = a3.h + 40 + 40 100 bm_n(b3.y - a3.y); bm_w(" (want " as *u8); bm_n(want3); bm_w(")" as *u8) 101 if b3.y - a3.y == want3 { t3ok = 1 } 102 } } 103 if t3ok == 1 { bm_w(" PASS\n" as *u8) } else { fails=fails+1; bm_w(" FAIL\n" as *u8) } 104 105 // T4: font shorthand -- the paint resolver reads 15 through the inherited walk 106 let p4: *Page = bm_layout("<html><head><style>body{font:15px/1.55 sans-serif}</style></head><body><p>alphabeta</p></body></html>\x00" as *u8) 107 let t4b: *LayoutBox = bm_find(p4, "alphabeta\x00" as *u8) 108 bm_w(" T4 font:15px/1.55 paint-fs=" as *u8) 109 var t4ok: i64 = 0 110 if (t4b as i64) != 0 { 111 let fs4: i64 = br_comp_fontsize_inh(p4.buf, p4.computed, p4.ncomp, p4.tree, t4b.parent_idx, 16) 112 bm_n(fs4); bm_w(" (want 15)" as *u8) 113 if fs4 == 15 { t4ok = 1 } 114 } 115 if t4ok == 1 { bm_w(" PASS\n" as *u8) } else { fails=fails+1; bm_w(" FAIL\n" as *u8) } 116 117 // T5: longhand wins over the shorthand for its side; other sides keep the shorthand 118 let p5: *Page = bm_layout("<html><head><style>div{padding:8px 12px;padding-top:1px}</style></head><body><div>alphabeta</div></body></html>\x00" as *u8) 119 let b5: *LayoutBox = bm_parent(p5, "alphabeta\x00" as *u8) 120 bm_w(" T5 shorthand+longhand-top h=" as *u8) 121 var t5ok: i64 = 0 122 if (b5 as i64) != 0 { if (k1 as i64) != 0 { 123 bm_n(b5.h); bm_w(" (want ctl+1+8=" as *u8); bm_n(k1.h + 9); bm_w(")" as *u8) 124 if b5.h == k1.h + 9 { t5ok = 1 } 125 } } 126 if t5ok == 1 { bm_w(" PASS\n" as *u8) } else { fails=fails+1; bm_w(" FAIL\n" as *u8) } 127 128 // T6 CAN-FAIL control: no-shorthand rhythm is the bare line height (the T2 delta is load-bearing) 129 let p6: *Page = bm_layout("<html><body><p>first</p><p>second</p></body></html>\x00" as *u8) 130 let a6: *LayoutBox = bm_find(p6, "first\x00" as *u8) 131 let b6: *LayoutBox = bm_find(p6, "second\x00" as *u8) 132 bm_w(" T6 control (no shorthand) dy=" as *u8) 133 var t6ok: i64 = 0 134 if (a6 as i64) != 0 { if (b6 as i64) != 0 { 135 bm_n(b6.y - a6.y) 136 if b6.y - a6.y < 57 { t6ok = 1 } 137 } } 138 if t6ok == 1 { bm_w(" PASS (differs from T2 -> the shorthand moved real geometry)\n" as *u8) } else { fails=fails+1; bm_w(" FAIL (vacuous)\n" as *u8) } 139 140 if fails == 0 { bm_w("NX-CSS-BOXMODEL GREEN -- shorthands shape layout; longhand priority + em inheritance + paint parity hold\n" as *u8); sys_exit(0); return 0 } 141 bm_w("NX-CSS-BOXMODEL RED fails=" as *u8); bm_n(fails); bm_w("\n" as *u8) 142 sys_exit(1); return 1 143}