code wiki / _hdl_build / nx_brand_typescale.nx
nx_brand_typescale.nx source
↩ module page · 61 lines · 3283 B
1// nx_brand_typescale.nx -- R9 modular TYPE-SCALE generator. From a base size (milli-rem) + an integer ratio
2// (num/den, e.g. 5/4 = 1.25 "major third"), generate a modular scale of heading sizes as font tokens:
3// font|h1 = base * r^4 , font|h2 = base * r^2 , font|h3 = base * r^1 (rem)
4// NO-FLOAT (integer rational ^n, formatted to 3 decimal places). The generated scale is monotonic-descending and
5// lands inside the R2 type-scale band BY CONSTRUCTION, so bg_type_scale_ok passes. Output is a valid .brand
6// fragment (token|font|... lines) that feeds the token SSOT directly. REUSE: nx_brand_tokens (bt_app).
7// Library, no main. 100% sovereign. license_tier: ORIGINAL
8import "nx_syscalls.nx"
9import "nx_brand_tokens.nx"
10
11func ts_ipow(base: i64, e: i64) -> i64 { var r: i64 = 1; var i: i64 = 0; while i < e { r = r * base; i = i + 1 } return r }
12// base_milli * (num/den)^n (milli-units, integer). n>=0.
13func ts_size_milli(base_milli: i64, num: i64, den: i64, n: i64) -> i64 {
14 let np: i64 = ts_ipow(num, n)
15 let dp: i64 = ts_ipow(den, n)
16 return (base_milli * np) / dp
17}
18// write a decimal integer into out at pos; return new pos.
19func ts_put_int(out: *u8, pos: i64, cap: i64, v: i64) -> i64 {
20 if v == 0 { if pos < cap { out[pos] = 48 as u8 } return pos + 1 }
21 let d: *u8 = sys_mmap(24); var m: i64 = v; var k: i64 = 0
22 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
23 var p: i64 = pos; var i: i64 = k - 1
24 while i >= 0 { if p < cap { out[p] = d[i] } p = p + 1; i = i - 1 }
25 return p
26}
27// format a milli-rem value as "<int>.<3frac>rem" into out (nul-terminated); return length.
28func ts_fmt_rem(milli: i64, out: *u8, cap: i64) -> i64 {
29 var p: i64 = ts_put_int(out, 0, cap, milli / 1000)
30 if p < cap { out[p] = 46 as u8 }; p = p + 1 // '.'
31 let fp: i64 = milli % 1000
32 if p < cap { out[p] = (48 + (fp / 100)) as u8 }; p = p + 1
33 if p < cap { out[p] = (48 + ((fp / 10) % 10)) as u8 }; p = p + 1
34 if p < cap { out[p] = (48 + (fp % 10)) as u8 }; p = p + 1
35 if p < cap { out[p] = 114 as u8 }; p = p + 1 // 'r'
36 if p < cap { out[p] = 101 as u8 }; p = p + 1 // 'e'
37 if p < cap { out[p] = 109 as u8 }; p = p + 1 // 'm'
38 if p < cap { out[p] = 0 as u8 }
39 return p
40}
41// emit one "token|font|<name>|<milli>rem\n" line at pos; return new pos.
42func ts_emit_one(out: *u8, pos: i64, cap: i64, name: *u8, milli: i64) -> i64 {
43 var q: i64 = pos
44 q = bt_app(out, q, cap, "token|font|" as *u8)
45 q = bt_app(out, q, cap, name)
46 q = bt_app(out, q, cap, "|" as *u8)
47 let rem: *u8 = sys_mmap(32)
48 ts_fmt_rem(milli, rem, 32)
49 q = bt_app(out, q, cap, rem)
50 q = bt_app(out, q, cap, "\n" as *u8)
51 return q
52}
53// generate a modular scale (.brand fragment) from base_milli + ratio num/den into out; return length.
54func ts_emit_scale(base_milli: i64, num: i64, den: i64, out: *u8, cap: i64) -> i64 {
55 var p: i64 = 0
56 p = ts_emit_one(out, p, cap, "h1" as *u8, ts_size_milli(base_milli, num, den, 4))
57 p = ts_emit_one(out, p, cap, "h2" as *u8, ts_size_milli(base_milli, num, den, 2))
58 p = ts_emit_one(out, p, cap, "h3" as *u8, ts_size_milli(base_milli, num, den, 1))
59 if p < cap { out[p] = 0 as u8 }
60 return p
61}