code wiki / (root) / nx_cdmap_raster_lib.nx

nx_cdmap_raster_lib.nx

buildroot/runtime/nx_cdmap_raster_lib.nx

49430 B940 linesdepth 8pulls 14 transitivereach 34 importersview sourcekind librarytopic cdmap
docsdependenciesstructsconstsfunctions

about

nx_cdmap_raster_lib.nx -- THE SOVEREIGN RASTERISER FOR THE POSITION MAP (datavis DV6 export, 2026-09-15). A compare page's position map is an inline SVG the emitter writes from nx_swcompare_lib (cdmap_pass). This library turns that SVG subset into ink: it reads the page's :root colour tokens, walks the figure's elements in document order (rect, circle, line, polyline with the momentum arrow marker, polygon, text incl. the -90 rotated axis title and the note groups), paints them into an i64 framebuffer (r + g*256 + b*65536, the packing nx_png writes) at an integer scale, draws every glyph as coverage through the estate's own TrueType engine (nx_ttf_fontlib, the same engine the pixel referee nx_cdmap_pixjudge already trusts), and writes the PNG through nx_png. It also writes the STANDALONE SVG twin: the figure's bytes with the svg namespace declared and every var(--nx-color-*) resolved to the rgb the page defined, so the file renders identically outside the page's stylesheet. WHY A SUBSET AND NOT A GENERAL SVG ENGINE: the emitter is the ONLY producer of these bytes, so the set of constructs is closed and known (cdp_* in nx_swcompare_lib), and every construct outside it is COUNTED and NAMED in the stats, never silently dropped: a render that cannot say what it skipped is a picture of the renderer's blind spots. SCOPE STATED: the face is Liberation Sans (SIL-OFL data, licence beside the bytes) where the page asks for system-ui, letter-spacing and rounded rect corners are not drawn, and a text rotated by anything but -90 degrees is skipped by name. The pixel referee (DV2) and this rasteriser share the font engine, so a label the referee measures as ink is the same ink this file paints. license_tier: ORIGINAL

dependencies 3 imports · 3 importers

nx_syscalls.nx nx_cdmap_referee_lib.nx nx_png.nx nx_cdmap_raster_lib.nx nx_cdmap_export.nx nx_cdmap_export_gate.nx nx_swcompare_lib.nx

imports: nx_syscalls.nxnx_cdmap_referee_lib.nxnx_png.nx

imported by: nx_cdmap_export.nxnx_cdmap_export_gate.nxnx_swcompare_lib.nx

structs

none

consts

21const RS_I64_BYTES: i64 = 8
22const RS_ABSENT: i64 = 0 - 1
23const RS_SCALE_DEFAULT: i64 = 2
24const RS_SCALE_MAX: i64 = 8 // 760x520 at 8 is a 24 MiB framebuffer; past this the export is refused by name
25const RS_CANVAS_MAX: i64 = 4096 // a viewBox axis past this is refused (the pixel referee's bound)
26const RS_VB_W_DEFAULT: i64 = 760 // the emitter's CDP_SVG_W when the tag carries no viewBox
27const RS_VB_H_DEFAULT: i64 = 520
28const RS_TOK_MAX: i64 = 48 // :root colour tokens read (the page defines under twenty)
29const RS_TOK_NAME_W: i64 = 32
30const RS_TOK_REC: i64 = 4 // r, g, b, name-slot
31const RS_TOK_R: i64 = 0
32const RS_TOK_G: i64 = 1
33const RS_TOK_B: i64 = 2
34const RS_PERMIL: i64 = 1000
35const RS_COV_MAX: i64 = 255
36const RS_INK_MIN: i64 = 8 // coverage below this paints nothing (fringe)
37const RS_STROKE_DEFAULT: i64 = 1 // canvas px when an element carries no stroke-width
38const RS_HALO_PX: i64 = 1 // the label halo (paint-order:stroke, 3px) reads as one canvas px each side of the ink
39const RS_ARROW_LEN: i64 = 7 // the emitter's marker: 7 px, an 8x8 viewBox with its tip at (8,4)
40const RS_ARROW_HALF: i64 = 3
41const RS_WALK_DIV: i64 = 2 // line walk step = scaled px / this
42const RS_DEG_ROT: i64 = 0 - 90 // the one rotation the emitter uses (the y-axis title)
43const RS_VAL_W: i64 = 64 // an attribute value copy (fill='..', transform='..')
44const RS_TEXT_W: i64 = 256 // a text element's content copy
45const RS_PTS_MAX: i64 = 64 // points on one polyline or polygon (a momentum path has two)
46const RS_XS_MAX: i64 = 64 // scanline crossings per row
47const RS_MAX_DASH: i64 = 4096 // scaled px of one dash pattern, bounds the walker
48const RS_STAMP: i64 = 1 // announce on the png publish
49const RS_SVG_HEAD: *u8 = "<?xml version='1.0' encoding='UTF-8'?>\n"
50const RS_SVG_NS: *u8 = " xmlns='http://www.w3.org/2000/svg'"
51const RS_VAR_OPEN: *u8 = "var(--nx-color-"
52const RS_SVG_OPEN: *u8 = "<svg class='cdmap'"
53const RS_SVG_CLOSE: *u8 = "</svg>"
54const RS_ROOT_OPEN: *u8 = ":root{"
55const RS_TOK_PREFIX: *u8 = "--nx-color-"
56const RS_RGB_OPEN: *u8 = "rgb("
57const RS_TAG_TEXT_CLOSE: *u8 = "</text>"
58const RS_TAG_TITLE_CLOSE: *u8 = "</title>"
59const RS_TAG_DESC_CLOSE: *u8 = "</desc>"
60const RS_TAG_DEFS_CLOSE: *u8 = "</defs>"
61const RS_TAG_STYLE_CLOSE: *u8 = "</style>"
62const RS_NOTE_CLASS: *u8 = "class='cdnote'"
63const RS_CH_LT: i64 = 60
64const RS_CH_GT: i64 = 62
65const RS_CH_SLASH: i64 = 47
66const RS_CH_QUOTE: i64 = 39
67const RS_CH_SPACE: i64 = 32
68const RS_CH_COMMA: i64 = 44
69const RS_CH_DOT: i64 = 46
70const RS_CH_MINUS: i64 = 45
71const RS_CH_RPAREN: i64 = 41
72const RS_CH_SEMI: i64 = 59
73const RS_CH_COLON: i64 = 58
74const RS_CH_RBRACE: i64 = 125
75const RS_CH_0: i64 = 48
76const RS_CH_9: i64 = 57
77const RS_CH_A: i64 = 65
78const RS_CH_Z: i64 = 90
79const RS_CH_a: i64 = 97
80const RS_CH_z: i64 = 122
81const RS_CH_AMP: i64 = 38
82const RS_CH_NL: i64 = 10
83const RS_CASE_GAP: i64 = 32
84const RS_BASE10: i64 = 10
85const RS_BYTE: i64 = 256
86const RS_BYTE2: i64 = 65536
87const RS_TWO: i64 = 2
88const RS_MODE_0644: i64 = 420
91const RS_S_RECT: i64 = 0
92const RS_S_CIRCLE: i64 = 1
93const RS_S_LINE: i64 = 2
94const RS_S_POLYLINE: i64 = 3
95const RS_S_POLYGON: i64 = 4
96const RS_S_TEXT: i64 = 5
97const RS_S_SKIPPED: i64 = 6 // elements outside the subset (named on stderr-free stdout by the caller through rs_skip_name)
98const RS_S_UNRESOLVED: i64 = 7 // colour values no token or literal resolved (painted fg)
99const RS_S_GLYPHS: i64 = 8 // glyphs drawn
100const RS_S_ROTATED: i64 = 9 // rotated texts drawn
101const RS_S_ROTSKIP: i64 = 10 // rotated texts skipped (an angle the subset does not draw)
102const RS_S_NOTES: i64 = 11 // cdnote groups seen
103const RS_S_ARROWS: i64 = 12 // marker-end arrows drawn
104const RS_S_INK: i64 = 13 // pixels painted by text ink (a scale field: 0 means no glyph landed)
105const RS_S_W: i64 = 14
106const RS_S_TOKENS: i64 = 15 // colour tokens read from :root
107const RS_S_SLOTS: i64 = 16
110const RS_OK: i64 = 0
111const RS_E_NOPAGE: i64 = 0 - 1
112const RS_E_NOSVG: i64 = 0 - 2
113const RS_E_NOFONT: i64 = 0 - 3
114const RS_E_CANVAS: i64 = 0 - 4
115const RS_E_PNG: i64 = 0 - 5
116const RS_E_SVG: i64 = 0 - 6
117const RS_E_SCALE: i64 = 0 - 7
118const RS_E_NOTOKENS: i64 = 0 - 8
478const RS_ENT_N: i64 = 10
479const RS_ENT_MAX: i64 = 8 // bytes of the longest entity name incl. & and ;

functions

120func rs_i64(n: i64) -> *i64 { return sys_mmap(n * RS_I64_BYTES) as *i64 }
121func rs_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
122func rs_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v }
123func rs_max(a: i64, b: i64) -> i64 { if a > b { return a } return b }
124func rs_min(a: i64, b: i64) -> i64 { if a < b { return a } return b }
125func rs_isqrt(v: i64) -> i64 { if v <= 0 { return 0 } var r: i64 = 1; while r * r <= v { r = r + 1 } return r - 1 }
126func rs_rc_name(rc: i64) -> *u8
140func rs_tok_rec(recs: *i64, i: i64) -> *i64 { return ((recs as i64) + i * RS_TOK_REC * RS_I64_BYTES) as *i64 }
141func rs_tok_name(names: *u8, i: i64) -> *u8 { return ((names as i64) + i * RS_TOK_NAME_W) as *u8 }
142func rs_is_ident(c: i64) -> i64
150func rs_rgb_at(h: *u8, p: i64, to: i64, rgb: *i64) -> i64
170func rs_theme_load(h: *u8, n: i64, names: *u8, recs: *i64) -> i64
called by 1: rs_render
199func rs_tok_find(names: *u8, ntok: i64, want: *u8, wl: i64) -> i64
212func rs_tok_rgb(names: *u8, recs: *i64, ntok: i64, name: *u8, rgb: *i64) -> i64
222func rs_attr_str(h: *u8, t0: i64, t1: i64, needle: *u8, out: *u8, cap: i64) -> i64
232func rs_attr_permil(h: *u8, t0: i64, t1: i64, needle: *u8) -> i64
251func rs_color_value(v: *u8, names: *u8, recs: *i64, ntok: i64, fg: *i64, rgb: *i64, stats: *i64) -> i64
270func rs_attr_color(h: *u8, t0: i64, t1: i64, needle: *u8, names: *u8, recs: *i64, ntok: i64, fg: *i64, rgb: *i64, stats: *i64, present: *i64) -> i64
281func rs_attr_dash(h: *u8, t0: i64, t1: i64, scale: i64, dash: *i64) -> i64
299func rs_attr_points(h: *u8, t0: i64, t1: i64, scale: i64, xs: *i64, ys: *i64) -> i64
330func rs_fb_get(fb: *i64, W: i64, x: i64, y: i64, rgb: *i64) -> i64 { let v: i64 = fb[y * W + x]; rgb[0] = v % RS_BYTE; rgb[1] = (v / RS_BYTE) % RS_BYTE; rgb[2] = (v / RS_BYTE2) % RS_BYTE; return 0 }
331func rs_pack(r: i64, g: i64, b: i64) -> i64 { return r + g * RS_BYTE + b * RS_BYTE2 }
333func rs_px(fb: *i64, W: i64, H: i64, x: i64, y: i64, rgb: *i64, a: i64) -> i64
350func rs_fill_all(fb: *i64, W: i64, H: i64, rgb: *i64) -> i64 { let v: i64 = rs_pack(rgb[0], rgb[1], rgb[2]); var i: i64 = 0; while i < W * H { fb[i] = v; i = i + 1 } return 0 }
351func rs_fill_rect(fb: *i64, W: i64, H: i64, x0: i64, y0: i64, w: i64, h: i64, rgb: *i64, a: i64) -> i64
357func rs_fill_disk(fb: *i64, W: i64, H: i64, cx: i64, cy: i64, r: i64, rgb: *i64, a: i64) -> i64
367func rs_ring(fb: *i64, W: i64, H: i64, cx: i64, cy: i64, r: i64, wd: i64, rgb: *i64, a: i64) -> i64
385func rs_seg(fb: *i64, W: i64, H: i64, x1: i64, y1: i64, x2: i64, y2: i64, wd: i64, rgb: *i64, a: i64, dash: *i64, phase0: i64) -> i64
406func rs_fill_poly(fb: *i64, W: i64, H: i64, xs: *i64, ys: *i64, np: i64, rgb: *i64, a: i64) -> i64
449func rs_arrow(fb: *i64, W: i64, H: i64, x1: i64, y1: i64, x2: i64, y2: i64, scale: i64, rgb: *i64, a: i64) -> i64
480func rs_ent_name(i: i64) -> *u8
493func rs_ent_ascii(i: i64) -> *u8
506func rs_ent_xml(i: i64) -> *u8
519func rs_ent_at(h: *u8, q: i64, to: i64) -> i64
530func rs_unescape(h: *u8, from: i64, to: i64, out: *u8, cap: i64) -> i64
555func rs_text_w(fh: *i64, s: *u8, ph: i64) -> i64 { var i: i64 = 0; var wpx: i64 = 0; while s[i] != (0 as u8) { wpx = wpx + tf_char_adv(fh, s[i] as i64, ph); i = i + 1 } return wpx }
557func rs_rot_x(px: i64, py: i64, cx: i64, cy: i64, rot: i64) -> i64 { if rot == 0 { return px } return cx + (py - cy) }
558func rs_rot_y(px: i64, py: i64, cx: i64, cy: i64, rot: i64) -> i64 { if rot == 0 { return py } return cy - (px - cx) }
561func rs_text(fb: *i64, W: i64, H: i64, fh: *i64, s: *u8, ph: i64, x: i64, ybase: i64, anchor: i64, rgb: *i64, a: i64, halo: i64, halo_rgb: *i64, rot: i64, cx: i64, cy: i64, scale: i64, stats: *i64) -> i64
613func rs_upper(s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { let c: i64 = s[i] as i64; if c >= RS_CH_a { if c <= RS_CH_z { s[i] = (c - RS_CASE_GAP) as u8 } } i = i + 1 } return 0 }
617func rs_tag_name(h: *u8, p: i64, to: i64, name: *u8, cap: i64) -> i64
625func rs_skip_past(h: *u8, p: i64, to: i64, closer: *u8) -> i64 { let e: i64 = cr_find(h, p, to, closer); if e == CR_ABSENT { return to } return e + rs_slen(closer) }
627func rs_viewbox(h: *u8, s0: i64, s1: i64, wh: *i64) -> i64
656func rs_render(h: *u8, s0: i64, s1: i64, names: *u8, recs: *i64, ntok: i64, fhr: *i64, fhb: *i64, scale: i64, fb: *i64, W: i64, H: i64, stats: *i64) -> i64
823func rs_svg_standalone(h: *u8, s0: i64, s1: i64, names: *u8, recs: *i64, ntok: i64, path: *u8) -> i64
885func rs_dec_into(dst: *u8, off: i64, v: i64) -> i64
901func rs_export(page: *u8, svg_path: *u8, png_path: *u8, freg: *u8, fbold: *u8, scale: i64, stats: *i64, out: *i64) -> i64