code wiki / _hdl_build / nx_cdmap_export_gate.nx

nx_cdmap_export_gate.nx source

↩ module page · 269 lines · 20725 B

1// nx_cdmap_export_gate.nx -- referee for the position map's EXPORT (datavis DV6, nx_cdmap_raster_lib, 2026-09-15). 2// A planted page carries a :root token block and a small cdmap svg with one of every construct the emitter writes 3// (frame rect with stroke, dashed gridline, momentum polyline with the arrow marker, filled polygon, a bubble with a 4// translucent fill and a momentum ring, a bold haloed label, anchored axis titles, a -90 rotated title, a cdnote group, 5// an uppercase muted quadrant word, a rotation the subset does not draw, and an element outside the subset). The gate 6// composes the library IN-PROCESS and holds the render to the pixels: the token colours land where the elements are, 7// the translucent bubble blends by the declared opacity, the dash is ON where the phase says on and OFF where it says 8// off, the arrow tip is ink, the labels leave dark ink in their boxes, the rotated title leaves ink in a vertical band, 9// and every count on the stats record equals the fixture's census. Both files are then written through rs_export and 10// read back (PNG signature and IHDR dimensions; SVG namespace present and every colour variable resolved). Negative 11// controls drive the named refusals (no figure, no tokens, no font, a scale out of range) and a determinism tooth 12// renders twice. When the live search page is on disk it is exported to /tmp and announced through gv_kv, never 13// gv_need. license_tier: ORIGINAL 14import "nx_cdmap_raster_lib.nx" 15import "nx_syscalls.nx" 16import "nx_gate_verdict.nx" 17 18const G_DIR: *u8 = "/tmp/nx_cdmap_export_gate/" 19const G_PAGE: *u8 = "/tmp/nx_cdmap_export_gate/page.html" 20const G_NOSVG: *u8 = "/tmp/nx_cdmap_export_gate/nosvg.html" 21const G_NOROOT: *u8 = "/tmp/nx_cdmap_export_gate/noroot.html" 22const G_SVG: *u8 = "/tmp/nx_cdmap_export_gate/cdmap.svg" 23const G_PNG: *u8 = "/tmp/nx_cdmap_export_gate/cdmap.png" 24const G_LIVE_SVG: *u8 = "/tmp/nx_cdmap_export_gate/live.svg" 25const G_LIVE_PNG: *u8 = "/tmp/nx_cdmap_export_gate/live.png" 26const G_LIVE_PAGE: *u8 = "sites/nishifamily/compare/search/index.html" 27const G_NOFONT: *u8 = "/tmp/nx_cdmap_export_gate/absent.ttf" 28const G_FONT_NAS: *u8 = "knowledge/fonts/LiberationSans-Regular.ttf" 29const G_FONT_NAS_BOLD: *u8 = "knowledge/fonts/LiberationSans-Bold.ttf" 30const G_FONT_UP: *u8 = "../knowledge/fonts/LiberationSans-Regular.ttf" 31const G_FONT_UP_BOLD: *u8 = "../knowledge/fonts/LiberationSans-Bold.ttf" 32const G_FONT_LAPTOP: *u8 = "web_assets/fonts/LiberationSans-Regular.ttf" 33const G_FONT_LAPTOP_BOLD: *u8 = "web_assets/fonts/LiberationSans-Bold.ttf" 34const G_MODE_644: i64 = 420 35const G_DIR_MODE: i64 = 493 36const G_I64: i64 = 8 37const G_SCALE: i64 = 2 38const G_VB_W: i64 = 200 39const G_VB_H: i64 = 120 40const G_CH_HASH: i64 = 35 41const G_TOL: i64 = 2 // channel tolerance for a blended pixel (integer rounding) 42const G_DARK_MAX_R: i64 = 120 // a label pixel darker than this red channel is ink 43const G_PNG_SIG0: i64 = 137 44const G_PNG_SIG1: i64 = 80 45const G_PNG_W_OFF: i64 = 16 46const G_PNG_H_OFF: i64 = 20 47const G_BYTE: i64 = 256 48// the fixture's declared tokens 49const G_BG_R: i64 = 243 50const G_BG_G: i64 = 241 51const G_BG_B: i64 = 236 52const G_PANEL_R: i64 = 249 53const G_PANEL_G: i64 = 247 54const G_PANEL_B: i64 = 243 55const G_MUT_R: i64 = 92 56const G_MUT_G: i64 = 96 57const G_MUT_B: i64 = 104 58const G_BUB_R: i64 = 86 59const G_BUB_G: i64 = 180 60const G_BUB_B: i64 = 233 61const G_BUB_A: i64 = 820 62const G_RING_R: i64 = 40 63const G_RING_G: i64 = 160 64const G_RING_B: i64 = 90 65const G_POLY_R: i64 = 230 66const G_POLY_G: i64 = 159 67const G_POLY_B: i64 = 0 68const G_PERMIL: i64 = 1000 69 70const G_HEAD: *u8 = "<html><head><style>\n:root{\n --nx-color-bg: rgb(243,241,236);\n --nx-color-fg: rgb(26,26,28);\n --nx-color-panel: rgb(249,247,243);\n --nx-color-line: rgb(219,216,208);\n --nx-color-mut: rgb(92,96,104);\n --nx-color-accent: rgb(88,64,180);\n --nx-font-mono: ui-monospace;\n}\n@media (prefers-color-scheme: dark){:root{--nx-color-bg: rgb(0,0,0);}}\n</style></head><body><p>before</p>\n<figure class='cdfig'><svg class='cdmap' viewBox='0 0 200 120' width='100%' font-family='system-ui'>\n<title id='cdmap-title'>fixture</title><desc id='cdmap-desc'>a planted map</desc>\n<defs><marker id='cdarrow' viewBox='0 0 8 8' refX='7' refY='4'><path d='M0,0 L8,4 L0,8 z' fill='var(--nx-color-mut)'/></marker></defs>\n<rect x='20' y='10' width='160' height='90' rx='6' fill='var(--nx-color-panel)' stroke='var(--nx-color-line)'/>\n<line x1='20' y1='55' x2='180' y2='55' stroke='var(--nx-color-mut)' stroke-dasharray='6 4'/>\n<polygon points='150,70 170,70 170,90 150,90' fill='rgb(230,159,0)' fill-opacity='1'/>\n<polyline data-p='1' points='60,80 90,50' fill='none' stroke='rgb(40,160,90)' stroke-dasharray='4 3' marker-end='url(" 71const G_TAIL: *u8 = "cdarrow)'/>\n<circle cx='100' cy='40' r='10' data-p='1' fill='rgb(86,180,233)' fill-opacity='0.82' stroke='rgb(40,160,90)' stroke-width='2'><title>Nishi 700 300</title></circle>\n<text x='112' y='44' data-p='1' font-size='13' fill='var(--nx-color-fg)' style='paint-order:stroke;stroke:var(--nx-color-bg);stroke-width:3px;stroke-linejoin:round' font-weight='700'>Nishi</text>\n<text x='100' y='114' fill='var(--nx-color-mut)' font-size='12' text-anchor='middle'>Centrality 700&ndash;1000 &middot; up &rarr;</text>\n<text x='8' y='55' fill='var(--nx-color-mut)' font-size='12' text-anchor='middle' transform='rotate(-90 8 55)'>Distinct</text>\n<g class='cdnote'><title>note n1</title><rect x='120' y='12' width='50' height='20' rx='4' fill='var(--nx-color-panel)' stroke='var(--nx-color-mut)' stroke-dasharray='2 2'/>\n<text x='125' y='26' fill='var(--nx-color-fg)' font-size='11'>bright &amp; loud</text>\n</g>\n<text x='30' y='30' fill='var(--nx-color-mut)' font-size='11' text-anchor='middle' opacity='0.75' style='letter-spacing:.12em;text-transform:uppercase'>tail</text>\n<text x='5' y='112' fill='var(--nx-color-fg)' font-size='12' transform='rotate(45 5 112)'>skew</text>\n<ellipse cx='5' cy='5' rx='2' ry='2' fill='var(--nx-color-fg)'/>\n</svg><figcaption>cap</figcaption></figure><p>after</p></body></html>\n" 72const G_NOSVG_BODY: *u8 = "<html><head><style>:root{--nx-color-bg: rgb(1,2,3);}</style></head><body><svg viewBox='0 0 10 10'><rect x='0' y='0' width='1' height='1'/></svg></body></html>\n" 73const G_NOROOT_BODY: *u8 = "<html><body><svg class='cdmap' viewBox='0 0 10 10'><rect x='0' y='0' width='1' height='1' fill='rgb(1,2,3)'/></svg></body></html>\n" 74 75func g_write(path: *u8, a: *u8, b: *u8, hash: i64) -> i64 { 76 let fd: i64 = sys_openat_wr(path, G_MODE_644) 77 if fd < 0 { return 0 - 1 } 78 sys_write(fd, a, rs_slen(a)) 79 if hash == 1 { let t: *u8 = sys_mmap(2); t[0] = G_CH_HASH as u8; sys_write(fd, t, 1) } 80 if (b as i64) != 0 { sys_write(fd, b, rs_slen(b)) } 81 sys_close(fd) 82 return 0 83} 84func g_exists(path: *u8) -> i64 { let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 } sys_close(fd); return 1 } 85func g_px(fb: *i64, W: i64, x: i64, y: i64, rgb: *i64) -> i64 { return rs_fb_get(fb, W, x, y, rgb) } 86func g_near(v: i64, want: i64) -> i64 { if rs_abs(v - want) <= G_TOL { return 1 } return 0 } 87func g_is(fb: *i64, W: i64, x: i64, y: i64, r: i64, g: i64, b: i64) -> i64 { 88 let rgb: *i64 = rs_i64(3) 89 g_px(fb, W, x, y, rgb) 90 let ok: i64 = g_near(rgb[0], r) * g_near(rgb[1], g) * g_near(rgb[2], b) 91 sys_munmap(rgb as *u8, 3 * G_I64) 92 return ok 93} 94// dark pixels (red channel under the ink bar) inside a canvas box, in scaled px 95func g_dark_in(fb: *i64, W: i64, H: i64, x0: i64, y0: i64, x1: i64, y1: i64) -> i64 { 96 let rgb: *i64 = rs_i64(3) 97 var c: i64 = 0 98 var y: i64 = y0 99 while y < y1 { var x: i64 = x0; while x < x1 { if x >= 0 { if y >= 0 { if x < W { if y < H { g_px(fb, W, x, y, rgb); if rgb[0] < G_DARK_MAX_R { c = c + 1 } } } } } x = x + 1 } y = y + 1 } 100 sys_munmap(rgb as *u8, 3 * G_I64) 101 return c 102} 103func g_fb_sum(fb: *i64, n: i64) -> i64 { var s: i64 = 0; var i: i64 = 0; while i < n { s = s + fb[i] % 1000003; i = i + 1 } return s } 104func g_has(buf: *u8, n: i64, needle: *u8) -> i64 { if cr_find(buf, 0, n, needle) != CR_ABSENT { return 1 } return 0 } 105func g_be32(b: *u8, o: i64) -> i64 { return (b[o] as i64) * G_BYTE * G_BYTE * G_BYTE + (b[o + 1] as i64) * G_BYTE * G_BYTE + (b[o + 2] as i64) * G_BYTE + (b[o + 3] as i64) } 106 107func main() -> i64 { 108 let ctr: *i64 = gv_ctr() 109 gv_head("=== NX-CDMAP EXPORT GATE -- the position map's SVG and PNG twins: token colours on the pixels, opacity blends, dash phase, the arrow, label and rotated ink, the census, both files read back, the named refusals ===" as *u8) 110 sys_mkdir(G_DIR, G_DIR_MODE) 111 gv_check("T0-fixture-page-written" as *u8, (g_write(G_PAGE, G_HEAD, G_TAIL, 1) == 0) as i64, ctr) 112 g_write(G_NOSVG, G_NOSVG_BODY, 0 as *u8, 0) 113 g_write(G_NOROOT, G_NOROOT_BODY, 0 as *u8, 0) 114 var freg: *u8 = G_FONT_NAS 115 var fbold: *u8 = G_FONT_NAS_BOLD 116 if g_exists(freg) == 0 { freg = G_FONT_UP; fbold = G_FONT_UP_BOLD } 117 if g_exists(freg) == 0 { freg = G_FONT_LAPTOP; fbold = G_FONT_LAPTOP_BOLD } 118 gv_check("T1-a-liberation-face-opens-at-one-of-its-three-homes" as *u8, g_exists(freg), ctr) 119 // ---- in-process render of the fixture ---- 120 let nb: *i64 = rs_i64(2) 121 nb[0] = 0 122 let h: *u8 = sys_read_file(G_PAGE, nb) 123 let n: i64 = nb[0] 124 let s0: i64 = cr_find(h, 0, n, RS_SVG_OPEN) 125 let s1: i64 = cr_find(h, s0, n, RS_SVG_CLOSE) 126 gv_check("T2-fixture-carries-the-cdmap-figure" as *u8, (s0 != CR_ABSENT) as i64 * (s1 != CR_ABSENT) as i64, ctr) 127 let names: *u8 = sys_mmap(RS_TOK_MAX * RS_TOK_NAME_W) 128 let recs: *i64 = rs_i64(RS_TOK_MAX * RS_TOK_REC) 129 let ntok: i64 = rs_theme_load(h, n, names, recs) 130 gv_check_eq("T3-six-colour-tokens-read-from-the-first-root-block" as *u8, ntok, 6, ctr) 131 let rgb: *i64 = rs_i64(3) 132 gv_check("T3a-panel-token-resolves-to-its-rgb" as *u8, rs_tok_rgb(names, recs, ntok, "panel" as *u8, rgb) * g_near(rgb[0], G_PANEL_R) * g_near(rgb[2], G_PANEL_B), ctr) 133 gv_check("T3b-NEG-dark-theme-bg-does-not-override-the-first-block" as *u8, rs_tok_rgb(names, recs, ntok, "bg" as *u8, rgb) * (rgb[0] == G_BG_R) as i64, ctr) 134 let wh: *i64 = rs_i64(2) 135 gv_check_eq("T4-viewbox-read" as *u8, rs_viewbox(h, s0, s1, wh) * 1000 + wh[0] + wh[1] * 0, 1000 + G_VB_W, ctr) 136 let fhr: *i64 = tf_load(freg) 137 var fhb: *i64 = tf_load(fbold) 138 if (fhb as i64) == 0 { fhb = fhr } 139 gv_check("T5-faces-loaded" as *u8, ((fhr as i64) != 0) as i64, ctr) 140 let W: i64 = G_VB_W * G_SCALE 141 let H: i64 = G_VB_H * G_SCALE 142 let fb: *i64 = rs_i64(W * H) 143 let stats: *i64 = rs_i64(RS_S_SLOTS) 144 rs_render(h, s0, s1, names, recs, ntok, fhr, fhb, G_SCALE, fb, W, H, stats) 145 gv_check_eq("T6-census-rect" as *u8, stats[RS_S_RECT], 2, ctr) 146 gv_check_eq("T6a-census-circle" as *u8, stats[RS_S_CIRCLE], 1, ctr) 147 gv_check_eq("T6b-census-line" as *u8, stats[RS_S_LINE], 1, ctr) 148 gv_check_eq("T6c-census-polyline" as *u8, stats[RS_S_POLYLINE], 1, ctr) 149 gv_check_eq("T6d-census-polygon" as *u8, stats[RS_S_POLYGON], 1, ctr) 150 gv_check_eq("T6e-census-text" as *u8, stats[RS_S_TEXT], 6, ctr) 151 gv_check_eq("T6f-census-notes" as *u8, stats[RS_S_NOTES], 1, ctr) 152 gv_check_eq("T6g-census-arrows" as *u8, stats[RS_S_ARROWS], 1, ctr) 153 gv_check_eq("T6h-census-rotated-drawn" as *u8, stats[RS_S_ROTATED], 1, ctr) 154 gv_check_eq("T6i-census-rotated-skipped-named" as *u8, stats[RS_S_ROTSKIP], 1, ctr) 155 gv_check_eq("T6j-census-skipped-is-the-ellipse-alone" as *u8, stats[RS_S_SKIPPED], 1, ctr) 156 gv_check_eq("T6k-NEG-no-unresolved-colours-on-a-page-that-declares-every-token" as *u8, stats[RS_S_UNRESOLVED], 0, ctr) 157 gv_check("T6l-glyphs-and-ink-are-scale-fields-above-zero" as *u8, (stats[RS_S_GLYPHS] > 0) as i64 * (stats[RS_S_INK] > 0) as i64, ctr) 158 // ---- pixels ---- 159 gv_check("T7-canvas-corner-is-the-bg-token" as *u8, g_is(fb, W, 2, 2, G_BG_R, G_BG_G, G_BG_B), ctr) 160 gv_check("T7a-inside-the-frame-is-the-panel-token" as *u8, g_is(fb, W, 60 * G_SCALE, 20 * G_SCALE, G_PANEL_R, G_PANEL_G, G_PANEL_B), ctr) 161 let br: i64 = (G_PANEL_R * (G_PERMIL - G_BUB_A) + G_BUB_R * G_BUB_A) / G_PERMIL 162 let bg2: i64 = (G_PANEL_G * (G_PERMIL - G_BUB_A) + G_BUB_G * G_BUB_A) / G_PERMIL 163 let bb: i64 = (G_PANEL_B * (G_PERMIL - G_BUB_A) + G_BUB_B * G_BUB_A) / G_PERMIL 164 gv_check("T8-bubble-centre-blends-by-its-fill-opacity-over-the-panel" as *u8, g_is(fb, W, 100 * G_SCALE, 40 * G_SCALE, br, bg2, bb), ctr) 165 gv_check("T8a-bubble-ring-is-the-momentum-stroke" as *u8, g_is(fb, W, 110 * G_SCALE, 40 * G_SCALE, G_RING_R, G_RING_G, G_RING_B), ctr) 166 // the dashed gridline: from x=20 with on 6 off 4 (canvas px) -> len 4 is ON, len 14 is OFF 167 gv_check("T9-dash-phase-on-is-the-muted-stroke" as *u8, g_is(fb, W, 24 * G_SCALE, 55 * G_SCALE, G_MUT_R, G_MUT_G, G_MUT_B), ctr) 168 // the pattern is 6 on 4 off in CANVAS px: canvas x=27 is 7 px along, inside the first off run (6..10) with a 1 px stamp margin either side 169 gv_check("T9a-NEG-dash-phase-off-shows-the-panel-under-it" as *u8, g_is(fb, W, 27 * G_SCALE, 55 * G_SCALE, G_PANEL_R, G_PANEL_G, G_PANEL_B), ctr) 170 gv_check("T10-polygon-interior-is-its-literal-rgb" as *u8, g_is(fb, W, 160 * G_SCALE, 80 * G_SCALE, G_POLY_R, G_POLY_G, G_POLY_B), ctr) 171 gv_check("T11-arrow-tip-is-ink-of-the-path-colour" as *u8, g_is(fb, W, 90 * G_SCALE - 1, 50 * G_SCALE + 1, G_RING_R, G_RING_G, G_RING_B), ctr) 172 let lab_ink: i64 = g_dark_in(fb, W, H, 112 * G_SCALE, 33 * G_SCALE, 150 * G_SCALE, 46 * G_SCALE) 173 gv_check("T12-bold-label-leaves-dark-ink-in-its-box" as *u8, (lab_ink > 0) as i64, ctr) 174 let rot_ink: i64 = g_dark_in(fb, W, H, 1 * G_SCALE, 25 * G_SCALE, 15 * G_SCALE, 85 * G_SCALE) 175 gv_check("T13-rotated-title-leaves-ink-in-a-vertical-band" as *u8, (rot_ink > 0) as i64, ctr) 176 // the band sits above the dashed gridline at y=55 so only a wrongly flat title could leave ink in it 177 let rot_none: i64 = g_dark_in(fb, W, H, 16 * G_SCALE, 44 * G_SCALE, 60 * G_SCALE, 50 * G_SCALE) 178 gv_check("T13a-NEG-rotated-title-leaves-no-horizontal-run-right-of-its-anchor" as *u8, (rot_none == 0) as i64, ctr) 179 let note_ink: i64 = g_dark_in(fb, W, H, 122 * G_SCALE, 14 * G_SCALE, 168 * G_SCALE, 31 * G_SCALE) 180 gv_check("T14-note-line-leaves-ink-inside-its-box" as *u8, (note_ink > 0) as i64, ctr) 181 // the bottom-left corner: left of the centred x-axis title, below the rotated y-axis title's band 182 let skew_ink: i64 = g_dark_in(fb, W, H, 3 * G_SCALE, 100 * G_SCALE, 30 * G_SCALE, 118 * G_SCALE) 183 gv_check("T14a-NEG-a-45-degree-text-is-skipped-not-drawn-flat" as *u8, (skew_ink == 0) as i64, ctr) 184 // ---- unit teeth on the text helpers ---- 185 let t: *u8 = sys_mmap(32) 186 let src: *u8 = "bright &amp; loud &lt;x&gt;" as *u8 187 rs_unescape(src, 0, rs_slen(src), t, 32) 188 gv_check("T15-entities-unescaped" as *u8, cr_streq(t, "bright & loud <x>" as *u8), ctr) 189 let u: *u8 = sys_mmap(8) 190 u[0] = 116 as u8; u[1] = 97 as u8; u[2] = 105 as u8; u[3] = 108 as u8; u[4] = 0 as u8 191 rs_upper(u) 192 gv_check("T15a-uppercase-transform-applied" as *u8, cr_streq(u, "TAIL" as *u8), ctr) 193 // ---- determinism ---- 194 let fb2: *i64 = rs_i64(W * H) 195 let stats2: *i64 = rs_i64(RS_S_SLOTS) 196 rs_render(h, s0, s1, names, recs, ntok, fhr, fhb, G_SCALE, fb2, W, H, stats2) 197 gv_check_eq("T16-two-renders-agree-pixel-for-pixel" as *u8, g_fb_sum(fb2, W * H), g_fb_sum(fb, W * H), ctr) 198 // ---- the one-call export and the files read back ---- 199 let out: *i64 = rs_i64(2) 200 let st3: *i64 = rs_i64(RS_S_SLOTS) 201 let rc: i64 = rs_export(G_PAGE, G_SVG, G_PNG, freg, fbold, G_SCALE, st3, out) 202 gv_check_eq("T17-export-returns-OK" as *u8, rc, RS_OK, ctr) 203 gv_check("T17a-both-files-report-bytes" as *u8, (out[0] > 0) as i64 * (out[1] > 0) as i64, ctr) 204 let pb: *i64 = rs_i64(2) 205 pb[0] = 0 206 let png: *u8 = sys_read_file(G_PNG, pb) 207 gv_check_eq("T18-png-bytes-on-disk-equal-the-receipt" as *u8, pb[0], out[1], ctr) 208 gv_check("T18a-png-signature" as *u8, ((png[0] as i64) == G_PNG_SIG0) as i64 * ((png[1] as i64) == G_PNG_SIG1) as i64, ctr) 209 gv_check_eq("T18b-png-width-is-the-viewbox-times-the-scale" as *u8, g_be32(png, G_PNG_W_OFF), W, ctr) 210 gv_check_eq("T18c-png-height-is-the-viewbox-times-the-scale" as *u8, g_be32(png, G_PNG_H_OFF), H, ctr) 211 let sb: *i64 = rs_i64(2) 212 sb[0] = 0 213 let svg: *u8 = sys_read_file(G_SVG, sb) 214 let sn: i64 = sb[0] 215 gv_check_eq("T19-svg-bytes-on-disk-equal-the-receipt" as *u8, sn, out[0], ctr) 216 gv_check("T19a-svg-starts-with-the-xml-declaration" as *u8, (cr_find(svg, 0, sn, "<?xml" as *u8) == 0) as i64, ctr) 217 gv_check("T19b-svg-declares-its-namespace" as *u8, g_has(svg, sn, RS_SVG_NS), ctr) 218 gv_check("T19c-NEG-no-colour-variable-survives-in-the-standalone-svg" as *u8, (g_has(svg, sn, RS_VAR_OPEN) == 0) as i64, ctr) 219 gv_check("T19d-panel-token-resolved-to-its-rgb-in-the-svg" as *u8, g_has(svg, sn, "rgb(249,247,243)" as *u8), ctr) 220 gv_check("T19e-svg-ends-with-the-closer" as *u8, (cr_rfind(svg, 0, sn, RS_SVG_CLOSE) == sn - rs_slen(RS_SVG_CLOSE) - 1) as i64, ctr) 221 gv_check("T19f-svg-keeps-the-marker-definition" as *u8, g_has(svg, sn, "id='cdarrow'" as *u8), ctr) 222 // the twin is XML: a named HTML entity is a parse error there, so every one the emitter uses is rewritten numerically 223 gv_check("T19g-NEG-no-named-html-entity-survives-in-the-svg" as *u8, ((g_has(svg, sn, "&ndash;" as *u8) + g_has(svg, sn, "&middot;" as *u8) + g_has(svg, sn, "&rarr;" as *u8)) == 0) as i64, ctr) 224 gv_check("T19h-entities-rewritten-as-numeric-references" as *u8, g_has(svg, sn, "&#8211;" as *u8) * g_has(svg, sn, "&#183;" as *u8) * g_has(svg, sn, "&#8594;" as *u8), ctr) 225 gv_check("T19i-the-xml-builtin-amp-is-kept-as-itself" as *u8, g_has(svg, sn, "&amp;" as *u8), ctr) 226 let t2: *u8 = sys_mmap(48) 227 let src2: *u8 = "a&ndash;b&mdash;c&middot;d&rarr;e&nbsp;f" as *u8 228 rs_unescape(src2, 0, rs_slen(src2), t2, 48) 229 gv_check("T15b-typographic-entities-drawn-as-their-nearest-ascii" as *u8, cr_streq(t2, "a-b-c.d->e f" as *u8), ctr) 230 // ---- the named refusals ---- 231 gv_check_eq("T20-NEG-a-page-without-the-cdmap-figure-is-refused-by-name" as *u8, rs_export(G_NOSVG, G_SVG, G_PNG, freg, fbold, G_SCALE, st3, out), RS_E_NOSVG, ctr) 232 gv_check_eq("T20a-NEG-a-page-without-root-tokens-is-refused-by-name" as *u8, rs_export(G_NOROOT, G_SVG, G_PNG, freg, fbold, G_SCALE, st3, out), RS_E_NOTOKENS, ctr) 233 gv_check_eq("T20b-NEG-an-absent-face-is-refused-by-name" as *u8, rs_export(G_PAGE, G_SVG, G_PNG, G_NOFONT, G_NOFONT, G_SCALE, st3, out), RS_E_NOFONT, ctr) 234 gv_check_eq("T20c-NEG-a-zero-scale-is-refused-by-name" as *u8, rs_export(G_PAGE, G_SVG, G_PNG, freg, fbold, 0, st3, out), RS_E_SCALE, ctr) 235 gv_check_eq("T20d-NEG-a-scale-past-the-bound-is-refused-by-name" as *u8, rs_export(G_PAGE, G_SVG, G_PNG, freg, fbold, RS_SCALE_MAX + 1, st3, out), RS_E_SCALE, ctr) 236 gv_check_eq("T20e-NEG-an-absent-page-is-refused-by-name" as *u8, rs_export("/tmp/nx_cdmap_export_gate/nothing.html" as *u8, G_SVG, G_PNG, freg, fbold, G_SCALE, st3, out), RS_E_NOPAGE, ctr) 237 // ---- the live page, when it is on disk: announced, never required ---- 238 var live_present: i64 = 0 239 var live_rc: i64 = 0 - 99 240 var live_circles: i64 = 0 - 1 241 var live_png: i64 = 0 - 1 242 var live_unres: i64 = 0 - 1 243 if g_exists(G_LIVE_PAGE) == 1 { 244 live_present = 1 245 let st4: *i64 = rs_i64(RS_S_SLOTS) 246 let out4: *i64 = rs_i64(2) 247 live_rc = rs_export(G_LIVE_PAGE, G_LIVE_SVG, G_LIVE_PNG, freg, fbold, G_SCALE, st4, out4) 248 live_circles = st4[RS_S_CIRCLE] 249 live_png = out4[1] 250 live_unres = st4[RS_S_UNRESOLVED] 251 gv_check_eq("T21-live-search-page-exports-OK" as *u8, live_rc, RS_OK, ctr) 252 gv_check("T21a-live-page-carries-marks" as *u8, (live_circles > 0) as i64, ctr) 253 gv_check_eq("T21b-live-page-resolves-every-colour" as *u8, live_unres, 0, ctr) 254 } 255 gv_values_head() 256 gv_kv("fixture_glyphs" as *u8, stats[RS_S_GLYPHS]) 257 gv_kv("fixture_ink_px" as *u8, stats[RS_S_INK]) 258 gv_kv("label_ink_px" as *u8, lab_ink) 259 gv_kv("rotated_ink_px" as *u8, rot_ink) 260 gv_kv("note_ink_px" as *u8, note_ink) 261 gv_kv("svg_bytes" as *u8, out[0]) 262 gv_kv("png_bytes" as *u8, out[1]) 263 gv_kv("live_present" as *u8, live_present) 264 gv_kv("live_rc" as *u8, live_rc) 265 gv_kv("live_circles" as *u8, live_circles) 266 gv_kv("live_png_bytes" as *u8, live_png) 267 gv_kv("live_unresolved_colors" as *u8, live_unres) 268 return gv_verdict("nx_cdmap_export_gate" as *u8, ctr, "the position map's SVG and PNG twins: colours, blends, dash phase, arrow, label and rotated ink on the pixels, the census, both files read back, the named refusals, and the live page when on disk" as *u8) 269}