code wiki / _hdl_build / nx_layout_probe.nx

nx_layout_probe.nx source

↩ module page · 162 lines · 6562 B

1// nx_layout_probe.nx -- layout-tree TRUTH probe for the S21 F1 finding (over-tall table rows). Loads a page 2// through the REAL browser layout (br_layout @ vw=1024, the GUI's width), finds the text box holding a 3// marker string, and prints the box GEOMETRY (self, ancestor chain, each ancestor's direct children, and the 4// next row's y for the row pitch). Turns "rows are ~150px, why?" into exact numbers at exact tree levels. 5// usage: nx_layout_probe <file.html> <marker> license_tier: ORIGINAL 6import "nx_syscalls.nx" 7import "nx_browser_render.nx" 8 9func lpw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 10func lpn(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 } 11 12func lp_box(t: *LayoutTree, i: i64) -> *LayoutBox { 13 return (t.boxes as *u8 + (i as nx_size) * (NX_LAYOUT_BOX_BYTES as nx_size)) as *LayoutBox 14} 15 16// print one box line: idx kind x y w h (and up to 40 bytes of text for TEXT boxes) 17func lp_print(src: *u8, t: *LayoutTree, i: i64) -> i64 { 18 let b: *LayoutBox = lp_box(t, i) 19 lpw(" box " as *u8); lpn(i) 20 lpw(" kind=" as *u8); lpn(b.kind) 21 lpw(" x=" as *u8); lpn(b.x) 22 lpw(" y=" as *u8); lpn(b.y) 23 lpw(" w=" as *u8); lpn(b.w) 24 lpw(" h=" as *u8); lpn(b.h) 25 if b.text_len > 0 { 26 lpw(" \"" as *u8) 27 var n: i64 = b.text_len 28 if n > 40 { n = 40 } 29 sys_write(1, ((src as i64) + b.text_off) as *u8, n) 30 lpw("\"" as *u8) 31 } 32 lpw("\n" as *u8) 33 return 0 34} 35 36// does the text box's source slice contain the marker? 37func lp_has(src: *u8, off: i64, len: i64, m: *u8) -> i64 { 38 var ml: i64 = 0 39 while m[ml] != (0 as u8) { ml = ml + 1 } 40 if ml == 0 { return 0 } 41 var i: i64 = 0 42 while i + ml <= len { 43 var k: i64 = 0 44 var ok: i64 = 1 45 while k < ml { if (src[off+i+k]&0xff) != (m[k]&0xff) { ok = 0; k = ml } else { k = k + 1 } } 46 if ok == 1 { return 1 } 47 i = i + 1 48 } 49 return 0 50} 51 52func main(argc: i64, argv: *i64) -> i64 { 53 if argc < 3 { lpw("usage: nx_layout_probe <file.html> <marker>\n" as *u8); sys_exit(2); return 2 } 54 let lb: *i64 = sys_mmap(16) as *i64 55 let html: *u8 = sys_read_file(argv[1] as *u8, lb) 56 if (html as i64) == 0 { lpw("cannot read\n" as *u8); sys_exit(3); return 3 } 57 let page: *Page = sys_mmap(NX_PAGE_BYTES) as *Page 58 page.raw = html 59 page.raw_len = lb[0] 60 page.dark_mode = 0 61 if argc >= 4 { nx_layout_set_vec_measure(1) } // argv[3] present -> vec-measure mode (GUI parity) 62 br_layout(page, 1024) 63 let t: *LayoutTree = page.tree 64 let src: *u8 = page.buf 65 lpw("page_h=" as *u8); lpn(page.page_h); lpw(" boxes=" as *u8); lpn(t.count); lpw("\n" as *u8) 66 67 // TEXT-COLOR SWEEP: the first 14 TEXT boxes with their PAINT-side resolved color + font-size 68 // (google-blank / darkmode-T3 class debugging: is text laid out but painted invisibly?) 69 lpw("== TEXT sweep (idx x y w fs color) ==\n" as *u8) 70 var tc: i64 = 0 71 var ti: i64 = 0 72 while ti < t.count { 73 if tc < 14 { 74 let tb2: *LayoutBox = lp_box(t, ti) 75 if tb2.kind == 4 { if tb2.text_len > 2 { 76 let fs2: i64 = br_comp_fontsize_inh(page.buf, page.computed, page.ncomp, t, tb2.parent_idx, 16) 77 let co2: i64 = br_comp_color_inh(page.buf, page.computed, page.ncomp, t, tb2.parent_idx) 78 lpw(" " as *u8); lpn(ti) 79 lpw(" x=" as *u8); lpn(tb2.x) 80 lpw(" y=" as *u8); lpn(tb2.y) 81 lpw(" w=" as *u8); lpn(tb2.w) 82 lpw(" fs=" as *u8); lpn(fs2) 83 lpw(" col=" as *u8); lpn(co2) 84 lpw(" \"" as *u8) 85 var tn2: i64 = tb2.text_len 86 if tn2 > 24 { tn2 = 24 } 87 sys_write(1, ((page.buf as i64) + tb2.text_off) as *u8, tn2) 88 lpw("\"\n" as *u8) 89 tc = tc + 1 90 } } 91 } 92 ti = ti + 1 93 } 94 95 // BG SWEEP: which of the first 16 boxes carry a computed background (canvas-propagation debugging) 96 lpw("== BG sweep (idx kind parent w h -> bg) ==\n" as *u8) 97 var bi: i64 = 0 98 var bmax: i64 = 16 99 if t.count < 16 { bmax = t.count } 100 while bi < bmax { 101 let bb: *LayoutBox = lp_box(t, bi) 102 let bg: i64 = br_comp_bg(page.buf, page.computed, page.ncomp, bi) 103 lpw(" " as *u8); lpn(bi) 104 lpw(" k=" as *u8); lpn(bb.kind) 105 lpw(" par=" as *u8); lpn(bb.parent_idx) 106 lpw(" w=" as *u8); lpn(bb.w) 107 lpw(" h=" as *u8); lpn(bb.h) 108 lpw(" bg=" as *u8); lpn(bg) 109 lpw("\n" as *u8) 110 bi = bi + 1 111 } 112 113 // find the marker text box 114 var hit: i64 = 0 - 1 115 var i: i64 = 0 116 while i < t.count { 117 if hit < 0 { 118 let b: *LayoutBox = lp_box(t, i) 119 if b.text_len > 0 { if lp_has(src, b.text_off, b.text_len, argv[2] as *u8) == 1 { hit = i } } 120 } 121 i = i + 1 122 } 123 if hit < 0 { lpw("marker not found\n" as *u8); sys_exit(4); return 4 } 124 125 lpw("\n== MARKER text box ==\n" as *u8) 126 lp_print(src, t, hit) 127 128 // ancestor chain with each ancestor's DIRECT children (NB: no fn().field chains -- locals first) 129 lpw("\n== ANCESTORS (each with its direct children) ==\n" as *u8) 130 let hb: *LayoutBox = lp_box(t, hit) 131 var cur: i64 = hb.parent_idx 132 var depth: i64 = 0 133 while cur >= 0 { 134 if depth >= 6 { cur = 0 - 1 } 135 else { 136 lpw("ancestor depth " as *u8); lpn(depth); lpw(":\n" as *u8) 137 lp_print(src, t, cur) 138 lpw(" children:\n" as *u8) 139 let ab: *LayoutBox = lp_box(t, cur) 140 var c: i64 = ab.first_child_idx 141 var nn: i64 = 0 142 while c >= 0 { 143 if nn >= 10 { lpw(" ...(more)\n" as *u8); c = 0 - 1 } 144 else { 145 lpw(" " as *u8); lp_print(src, t, c) 146 let sb: *LayoutBox = lp_box(t, c) 147 c = sb.next_sibling_idx 148 nn = nn + 1 149 } 150 } 151 // row pitch: this ancestor's next sibling y-delta 152 let ns: i64 = ab.next_sibling_idx 153 if ns >= 0 { 154 lpw(" next-sibling: " as *u8); lp_print(src, t, ns) 155 } 156 cur = ab.parent_idx 157 depth = depth + 1 158 } 159 } 160 sys_exit(0) 161 return 0 162}