code wiki / _hdl_build / nx_lineheight_gate.nx

nx_lineheight_gate.nx source

↩ module page · 109 lines · 5929 B

1// nx_lineheight_gate.nx -- PROOF (re-runnable) of CSS line-height (the S21 height-axis remainder): 2// unitless multiplier, px form, the `font` shorthand's /N part, inheritance-with-recompute, and 3// layout==paint resolver parity -- all through the REAL br_layout on inline fixtures. 4// T1 line-height:2 @fs16 -> single-line text box h == 32 (control: 17) 5// T2 font:15px/1.55 ... -> text box h == 23 (15*1550/1000, integer) 6// T3 line-height:30px -> h == 30 (fixed px, fs-independent) 7// T4 inherit+recompute -> body{line-height:1.5} p{font-size:20px} -> p line h == 30 (1.5x20, NOT 24) 8// T5 paint parity -> br_comp_lineheight_px == the layout-observed height on T2's page 9// T6 CAN-FAIL control -> no decl -> h == 17 (legacy exact; T1's delta is load-bearing) 10// license_tier: ORIGINAL expect_exit: 0 11import "nx_syscalls.nx" 12import "nx_browser_render.nx" 13 14func lg_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 15func lg_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 } 16func lg_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 17func lg_box(t: *LayoutTree, i: i64) -> *LayoutBox { 18 return (t.boxes as *u8 + (i as nx_size) * (NX_LAYOUT_BOX_BYTES as nx_size)) as *LayoutBox 19} 20func lg_has(src: *u8, off: i64, len: i64, m: *u8) -> i64 { 21 let ml: i64 = lg_slen(m) 22 if ml == 0 { return 0 } 23 var i: i64 = 0 24 while i + ml <= len { 25 var k: i64 = 0 26 var ok: i64 = 1 27 while k < ml { if (src[off+i+k]&0xff) != (m[k]&0xff) { ok = 0; k = ml } else { k = k + 1 } } 28 if ok == 1 { return 1 } 29 i = i + 1 30 } 31 return 0 32} 33func lg_layout(html: *u8) -> *Page { 34 let page: *Page = sys_mmap(NX_PAGE_BYTES) as *Page 35 page.raw = html 36 page.raw_len = lg_slen(html) 37 page.dark_mode = 0 38 br_layout(page, 1024) 39 return page 40} 41func lg_find(page: *Page, marker: *u8) -> *LayoutBox { 42 let t: *LayoutTree = page.tree 43 var i: i64 = 0 44 while i < t.count { 45 let b: *LayoutBox = lg_box(t, i) 46 if b.text_len > 0 { if lg_has(page.buf, b.text_off, b.text_len, marker) == 1 { return b } } 47 i = i + 1 48 } 49 return 0 as *LayoutBox 50} 51 52func main() -> i64 { 53 lg_w("=== nx_lineheight_gate -- CSS line-height shapes layout AND paint identically (S21 height axis) ===\n" as *u8) 54 var fails: i64 = 0 55 56 // T1: unitless multiplier vs control 57 let p1: *Page = lg_layout("<html><head><style>body{line-height:2}</style></head><body><p>alphabeta</p></body></html>\x00" as *u8) 58 let b1: *LayoutBox = lg_find(p1, "alphabeta\x00" as *u8) 59 lg_w(" T1 line-height:2 @fs16 h=" as *u8) 60 var t1: i64 = 0 61 if (b1 as i64) != 0 { lg_n(b1.h); lg_w(" (want 32)" as *u8); if b1.h == 32 { t1 = 1 } } 62 if t1 == 1 { lg_w(" PASS\n" as *u8) } else { fails=fails+1; lg_w(" FAIL\n" as *u8) } 63 64 // T2: the font shorthand's /N 65 let p2: *Page = lg_layout("<html><head><style>body{font:15px/1.55 sans-serif}</style></head><body><p>alphabeta</p></body></html>\x00" as *u8) 66 let b2: *LayoutBox = lg_find(p2, "alphabeta\x00" as *u8) 67 lg_w(" T2 font:15px/1.55 h=" as *u8) 68 var t2: i64 = 0 69 if (b2 as i64) != 0 { lg_n(b2.h); lg_w(" (want 23)" as *u8); if b2.h == 23 { t2 = 1 } } 70 if t2 == 1 { lg_w(" PASS\n" as *u8) } else { fails=fails+1; lg_w(" FAIL\n" as *u8) } 71 72 // T3: fixed px form 73 let p3: *Page = lg_layout("<html><head><style>p{line-height:30px}</style></head><body><p>alphabeta</p></body></html>\x00" as *u8) 74 let b3: *LayoutBox = lg_find(p3, "alphabeta\x00" as *u8) 75 lg_w(" T3 line-height:30px h=" as *u8) 76 var t3: i64 = 0 77 if (b3 as i64) != 0 { lg_n(b3.h); lg_w(" (want 30)" as *u8); if b3.h == 30 { t3 = 1 } } 78 if t3 == 1 { lg_w(" PASS\n" as *u8) } else { fails=fails+1; lg_w(" FAIL\n" as *u8) } 79 80 // T4: unitless INHERITS AS THE NUMBER -> recomputes against the descendant's own font-size 81 let p4: *Page = lg_layout("<html><head><style>body{line-height:1.5}p{font-size:20px}</style></head><body><p>alphabeta</p></body></html>\x00" as *u8) 82 let b4: *LayoutBox = lg_find(p4, "alphabeta\x00" as *u8) 83 lg_w(" T4 body lh:1.5 + p fs:20 h=" as *u8) 84 var t4: i64 = 0 85 if (b4 as i64) != 0 { lg_n(b4.h); lg_w(" (want 30 = 1.5x20, NOT 1.5x16=24)" as *u8); if b4.h == 30 { t4 = 1 } } 86 if t4 == 1 { lg_w(" PASS\n" as *u8) } else { fails=fails+1; lg_w(" FAIL\n" as *u8) } 87 88 // T5: the PAINT resolver returns the same value layout used (measure==paint) 89 lg_w(" T5 paint resolver on T2 page lh=" as *u8) 90 var t5: i64 = 0 91 if (b2 as i64) != 0 { 92 let plh: i64 = br_comp_lineheight_px(p2.buf, p2.computed, p2.ncomp, p2.tree, b2.parent_idx, 15) 93 lg_n(plh); lg_w(" (want 23)" as *u8) 94 if plh == 23 { t5 = 1 } 95 } 96 if t5 == 1 { lg_w(" PASS\n" as *u8) } else { fails=fails+1; lg_w(" FAIL\n" as *u8) } 97 98 // T6 CAN-FAIL control: no declaration anywhere -> the legacy 17px line box, exactly 99 let p6: *Page = lg_layout("<html><body><p>alphabeta</p></body></html>\x00" as *u8) 100 let b6: *LayoutBox = lg_find(p6, "alphabeta\x00" as *u8) 101 lg_w(" T6 control (no decl) h=" as *u8) 102 var t6: i64 = 0 103 if (b6 as i64) != 0 { lg_n(b6.h); lg_w(" (want 17)" as *u8); if b6.h == 17 { t6 = 1 } } 104 if t6 == 1 { lg_w(" PASS (legacy exact -> T1/T2 deltas are load-bearing)\n" as *u8) } else { fails=fails+1; lg_w(" FAIL\n" as *u8) } 105 106 if fails == 0 { lg_w("NX-LINEHEIGHT GREEN -- unitless/px/font-shorthand line-height, inherited-with-recompute, layout==paint\n" as *u8); sys_exit(0); return 0 } 107 lg_w("NX-LINEHEIGHT RED fails=" as *u8); lg_n(fails); lg_w("\n" as *u8) 108 sys_exit(1); return 1 109}