nx_garment_twin_gate.nx source
↩ module page · 156 lines · 9334 B
1// nx_garment_twin_gate.nx -- THE GATE FOR THE FLAT-FRONT GARMENT PREVIEW (nx_garment_twin forked for real), 2026-08-24.
2//
3// FIXTURES AT RUNTIME in /tmp/nx_garment_twin_gate/: a 32x32 P6 print (left half pure red, right half pure white) and
4// two confs derived from the estate conf's shape -- one with relief, one with relief_permil=0 (the neg-control: no
5// knit modulation may appear when the relief is zero). Teeth read the DECODED output: canvas dimensions, the fabric
6// outside the chest box reads as (shaded) fabric albedo, the print region is redder than the fabric, ink only darkens
7// (print-region luma below fabric luma), the knit modulation is PRESENT with relief and ABSENT without it (bite).
8// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
9import "nx_syscalls.nx"
10import "nx_gate_verdict.nx"
11import "nx_tool_run.nx"
12import "nx_img_to_rgb.nx"
13
14const GG_SUBJECT_DEFAULT: *u8 = "nx_garment_twin.elf"
15const GG_DIR: *u8 = "/tmp/nx_garment_twin_gate"
16const GG_PRINT: *u8 = "/tmp/nx_garment_twin_gate/print.ppm"
17const GG_CONF: *u8 = "/tmp/nx_garment_twin_gate/relief.conf"
18const GG_CONF_FLAT: *u8 = "/tmp/nx_garment_twin_gate/flat.conf"
19const GG_OUT: *u8 = "/tmp/nx_garment_twin_gate/out.png"
20const GG_OUT_FLAT: *u8 = "/tmp/nx_garment_twin_gate/outflat.png"
21const GG_MODE_DIR: i64 = 493
22const GG_MODE_0644: i64 = 420
23const GG_CAPTURE_CAP: i64 = 65536
24const GG_ARGV_SLOTS: i64 = 8
25const GG_SLOT: i64 = 8
26const GG_CHANNELS: i64 = 3
27const GG_PW: i64 = 32
28const GG_PH: i64 = 32
29const GG_CODE_MAX: i64 = 255
30const GG_PPM_HDR: *u8 = "P6\n32 32\n255\n"
31const GG_W: i64 = 256 // fixture canvas (the conf rows below)
32const GG_H: i64 = 320
33const GG_FAB: i64 = 246 // fixture fabric albedo (one value for all three channels: a neutral)
34const GG_BOX_X: i64 = 51 // 200 permil of 256
35const GG_BOX_Y: i64 = 80 // 250 permil of 320
36const GG_BOX_W: i64 = 153 // 600 permil of 256
37const GG_PROBE_X: i64 = 8 // a fabric pixel well outside the box
38const GG_PROBE_Y: i64 = 8
39const GG_RUN_LEN: i64 = 24 // a run of fabric pixels: the knit must vary along it when relief is on
40const GG_RED_X_OFF: i64 = 10 // inside the red half of the placed print
41const GG_RED_Y_OFF: i64 = 10
42const GG_SHADE_FLOOR: i64 = 700 // ambient_permil of the fixture conf: fabric never darker than this permil of albedo
43const GG_PERMIL: i64 = 1000
44const GG_EXIT_OK: i64 = 0
45
46func gg_write_bytes(path: *u8, b: *u8, n: i64) -> i64 {
47 let fd: i64 = sys_openat_wr(path, GG_MODE_0644)
48 if fd < 0 { return 0 - 1 }
49 let wr: i64 = sys_write(fd, b, n)
50 sys_close(fd)
51 if wr != n { return 0 - 1 }
52 return n
53}
54func gg_write_text(path: *u8, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return gg_write_bytes(path, s, n) }
55func gg_write_print(path: *u8) -> i64 {
56 var hl: i64 = 0
57 while GG_PPM_HDR[hl] != (0 as u8) { hl = hl + 1 }
58 let total: i64 = hl + GG_PW * GG_PH * GG_CHANNELS
59 let b: *u8 = sys_mmap(total)
60 var i: i64 = 0
61 while i < hl { b[i] = GG_PPM_HDR[i]; i = i + 1 }
62 var y: i64 = 0
63 while y < GG_PH {
64 var x: i64 = 0
65 while x < GG_PW {
66 let o: i64 = hl + (y * GG_PW + x) * GG_CHANNELS
67 if x < GG_PW / 2 { b[o] = GG_CODE_MAX as u8; b[o + 1] = 0 as u8; b[o + 2] = 0 as u8 }
68 else { b[o] = GG_CODE_MAX as u8; b[o + 1] = GG_CODE_MAX as u8; b[o + 2] = GG_CODE_MAX as u8 }
69 x = x + 1
70 }
71 y = y + 1
72 }
73 return gg_write_bytes(path, b, total)
74}
75func gg_run(subject: *u8, a1: *u8, a2: *u8, a3: *u8, a4: *u8, out: *u8, outlen: *i64) -> i64 {
76 let av: *i64 = sys_mmap(GG_SLOT * GG_ARGV_SLOTS) as *i64
77 av[0] = subject as i64
78 av[1] = a1 as i64
79 av[2] = a2 as i64
80 av[3] = a3 as i64
81 av[4] = a4 as i64
82 av[5] = 0
83 return tr_run_capture(subject, av, out, GG_CAPTURE_CAP, outlen)
84}
85// decode an output; returns the rgb buffer (0 on failure) and fills wh
86func gg_decode(path: *u8, wh: *i64) -> *u8 {
87 wh[0] = 0
88 wh[1] = 0
89 return nx_img_to_rgb(path, wh)
90}
91func gg_px(rgb: *u8, w: i64, x: i64, y: i64, c: i64) -> i64 { return rgb[(y * w + x) * GG_CHANNELS + c] as i64 }
92// max minus min of channel 0 along a horizontal run: the knit modulation signal
93func gg_run_spread(rgb: *u8, w: i64, x0: i64, y: i64, n: i64) -> i64 {
94 var lo: i64 = GG_CODE_MAX
95 var hi: i64 = 0
96 var i: i64 = 0
97 while i < n { let v: i64 = gg_px(rgb, w, x0 + i, y, 0); if v < lo { lo = v } if v > hi { hi = v } i = i + 1 }
98 return hi - lo
99}
100
101func main(argc: i64, argv: *i64) -> i64 {
102 let ctr: *i64 = gv_ctr()
103 gv_head("nx_garment_twin gate -- ink multiplies the fabric, the knit relief shades it, and a zero relief shades nothing" as *u8)
104 var subject: *u8 = GG_SUBJECT_DEFAULT
105 if argc >= 2 { subject = argv[1] as *u8 }
106 gv_puts(" subject: " as *u8); gv_puts(subject); gv_puts("\n\n" as *u8)
107 sys_mkdir(GG_DIR, GG_MODE_DIR)
108 sys_unlinkat(GG_OUT)
109 sys_unlinkat(GG_OUT_FLAT)
110 let wp: i64 = gg_write_print(GG_PRINT)
111 let wc: i64 = gg_write_text(GG_CONF, "canvas_w=256\ncanvas_h=320\nfabric_r=246\nfabric_g=246\nfabric_b=246\nwale_px=4\ncourse_px=6\nrelief_permil=180\nambient_permil=700\nchest_x_permil=200\nchest_y_permil=250\nchest_w_permil=600\n" as *u8)
112 let wf: i64 = gg_write_text(GG_CONF_FLAT, "canvas_w=256\ncanvas_h=320\nfabric_r=246\nfabric_g=246\nfabric_b=246\nwale_px=4\ncourse_px=6\nrelief_permil=0\nambient_permil=700\nchest_x_permil=200\nchest_y_permil=250\nchest_w_permil=600\n" as *u8)
113 var setup: i64 = 0
114 if wp > 0 { if wc > 0 { if wf > 0 { setup = 1 } } }
115 gv_check("setup-fixtures-written (print, relief conf, flat conf)" as *u8, setup, ctr)
116 let wh0: *i64 = sys_mmap(GG_SLOT * 2) as *i64
117 gv_check("setup-outputs-absent-before-measuring (gate is idempotent)" as *u8, ((gg_decode(GG_OUT, wh0) as i64) == 0) as i64, ctr)
118 let cap: *u8 = sys_mmap(GG_CAPTURE_CAP)
119 let olen: *i64 = sys_mmap(GG_SLOT * 2) as *i64
120 let rc: i64 = gg_run(subject, "place" as *u8, GG_PRINT, GG_OUT, GG_CONF, cap, olen)
121 gv_puts(" [place relief] rc=" as *u8); gv_num(rc); gv_puts("\n" as *u8); sys_write(1, cap, olen[0])
122 gv_check("place-exits-0-and-says-PLACED" as *u8, ((rc == GG_EXIT_OK) as i64) * tr_contains(cap, olen[0], "verdict=PLACED" as *u8), ctr)
123 gv_check("place-declares-its-surface-honestly (FLAT-FRONT-KNIT, mesh drape named as the next rung)" as *u8, tr_contains(cap, olen[0], "surface=FLAT-FRONT-KNIT" as *u8), ctr)
124 let wh: *i64 = sys_mmap(GG_SLOT * 2) as *i64
125 let img: *u8 = gg_decode(GG_OUT, wh)
126 var dims: i64 = 0
127 if (img as i64) != 0 { if wh[0] == GG_W { if wh[1] == GG_H { dims = 1 } } }
128 gv_check("output-decodes-at-the-conf-canvas-size" as *u8, dims, ctr)
129 if dims == 1 {
130 let fr: i64 = gg_px(img, GG_W, GG_PROBE_X, GG_PROBE_Y, 0)
131 let fg: i64 = gg_px(img, GG_W, GG_PROBE_X, GG_PROBE_Y, 1)
132 let fb: i64 = gg_px(img, GG_W, GG_PROBE_X, GG_PROBE_Y, 2)
133 gv_puts(" fabric_probe=" as *u8); gv_num(fr); gv_puts("," as *u8); gv_num(fg); gv_puts("," as *u8); gv_num(fb); gv_puts("\n" as *u8)
134 var fabric_ok: i64 = 0
135 if fr == fg { if fg == fb { if fr <= GG_FAB { if fr >= (GG_FAB * GG_SHADE_FLOOR) / GG_PERMIL { fabric_ok = 1 } } } }
136 gv_check("fabric-outside-the-box-is-neutral-albedo-shaded-no-darker-than-the-ambient-floor" as *u8, fabric_ok, ctr)
137 let rr: i64 = gg_px(img, GG_W, GG_BOX_X + GG_RED_X_OFF, GG_BOX_Y + GG_RED_Y_OFF, 0)
138 let rg: i64 = gg_px(img, GG_W, GG_BOX_X + GG_RED_X_OFF, GG_BOX_Y + GG_RED_Y_OFF, 1)
139 gv_puts(" red_region=" as *u8); gv_num(rr); gv_puts("," as *u8); gv_num(rg); gv_puts("\n" as *u8)
140 gv_check("print-region-shows-the-print (red channel high, green channel ink-suppressed to zero)" as *u8, ((rr > rg) as i64) * ((rg == 0) as i64), ctr)
141 gv_check("ink-only-darkens (red-region red channel never above the fabric albedo)" as *u8, (rr <= GG_FAB) as i64, ctr)
142 let spread_relief: i64 = gg_run_spread(img, GG_W, GG_PROBE_X, GG_PROBE_Y, GG_RUN_LEN)
143 gv_puts(" knit_spread_relief=" as *u8); gv_num(spread_relief); gv_puts("\n" as *u8)
144 gv_check("knit-modulation-present-with-relief (spread along a fabric run > 0)" as *u8, (spread_relief > 0) as i64, ctr)
145 let rc2: i64 = gg_run(subject, "place" as *u8, GG_PRINT, GG_OUT_FLAT, GG_CONF_FLAT, cap, olen)
146 let wh2: *i64 = sys_mmap(GG_SLOT * 2) as *i64
147 let img2: *u8 = gg_decode(GG_OUT_FLAT, wh2)
148 var spread_flat: i64 = 0 - 1
149 if (img2 as i64) != 0 { if wh2[0] == GG_W { spread_flat = gg_run_spread(img2, GG_W, GG_PROBE_X, GG_PROBE_Y, GG_RUN_LEN) } }
150 gv_puts(" knit_spread_flat=" as *u8); gv_num(spread_flat); gv_puts("\n" as *u8)
151 gv_bite("neg-control-zero-relief-shades-nothing (fires with relief, silent without)" as *u8, (spread_relief > 0) as i64, (spread_flat != 0) as i64, ctr)
152 }
153 // luma partition from the subject's own stats line: ink darkens the print region below the fabric
154 gv_check("stats-line-present (fabric_luma_permil and print_luma_permil)" as *u8, tr_contains(cap, olen[0], "print_luma_permil=" as *u8), ctr)
155 return gv_verdict("garment_twin" as *u8, ctr, "the print multiplies white cotton, the knit relief shades it under a light, and a zero relief is a flat composite" as *u8)
156}