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}