seedmarkfile
seedmark/src/render.js/

src/render.js raw
1// Internal geometry only: no seed text reaches markup.
2const circle = (x, y, r, fill) => `<circle cx="${x}" cy="${y}" r="${r}" fill="${fill}"/>`;
3const ellipse = (x, y, rx, ry, fill) => `<ellipse cx="${x}" cy="${y}" rx="${rx}" ry="${ry}" fill="${fill}"/>`;
4const rect = (x, y, w, h, rx, fill) => `<rect x="${x}" y="${y}" width="${w}" height="${h}" rx="${rx}" fill="${fill}"/>`;
5const path = (d, fill, stroke = 'none', width = 0) => `<path d="${d}" fill="${fill}" stroke="${stroke}" stroke-width="${width}" stroke-linecap="round" stroke-linejoin="round"/>`;
6const group = (body, transform) => `<g transform="${transform}">${body}</g>`;
7function masks(r) {
8 const [bg, light, hot, cool] = r.palette;
9 const {variant: s, width: w, height: h} = r.silhouette;
10 const {variant: f, accent} = r.features;
11 const x = 32 - w / 2, y = 33 - h / 2;
12 let art = [
13 path('M17 23L10 9L28 19M47 23L54 9L36 19', cool),
14 rect(20, 8, 24, 16, 4, hot),
15 path('M17 23L20 7L32 16L44 7L47 23Z', hot),
16 circle(32, 13, 10, cool) + circle(32, 13, 4, bg)
17 ][r.layout.variant];
18 art += [
19 path(`M${x} ${y}Q32 ${y-6} ${64-x} ${y}L${64-x-2} 43L32 56L${x+2} 43Z`, light),
20 ellipse(32, 33, w / 2, h / 2, light),
21 rect(x, y, w, h, 8, light),
22 path(`M32 ${y-3}L${64-x} 25L${64-x-4} 47L32 54L${x+4} 47L${x} 25Z`, light)
23 ][s];
24 art += path('M32 18L39 25L36 42L32 47Z', accent ? hot : cool);
25 art += [
26 ellipse(24, 31, 5, 6, bg) + ellipse(40, 31, 5, 6, bg),
27 path('M18 28L29 32L19 35ZM35 32L46 28L45 35Z', bg),
28 rect(18, 28, 12, 6, 2, bg) + circle(40, 31, 5, bg),
29 path('M18 33Q24 23 29 33M35 33Q40 23 46 33', 'none', bg, 4)
30 ][f];
31 art += accent ? rect(26, 43, 12, 4, 2, bg) : path('M27 42L32 48L37 42Z', bg);
32 return art;
33}
34function creatures(r) {
35 const [bg, light, hot, cool] = r.palette;
36 const {variant: s, width: w} = r.silhouette;
37 const {variant: f, count, accent} = r.features;
38 let art = [
39 path('M22 27Q4 9 14 9Q24 10 27 26M36 26Q45 4 51 13L43 29', hot),
40 path('M19 29L8 20L13 39M43 28L55 19L51 40', cool),
41 path('M25 25L23 10M39 25L44 12', 'none', light, 5) + circle(23, 10, 5, hot) + circle(44, 12, 5, hot),
42 path('M17 25L15 13L28 22L36 11L40 23L50 18L47 30Z', hot)
43 ][r.layout.variant];
44 art += path('M22 43L17 52L25 52M40 43L47 52L38 52', 'none', cool, 6);
45 art += [
46 ellipse(32, 35, w / 2, 17, cool),
47 path('M15 43Q10 19 32 22Q52 10 50 43Q43 55 32 46Q20 55 15 43Z', cool),
48 rect(32-w/2, 22, w, 27, 10, cool),
49 path('M12 42L23 20Q32 12 42 26L53 43Q33 58 12 42Z', cool)
50 ][s];
51 if (f === 0) art += circle(32, 33, 10, light) + circle(32 + accent * 3, 33, 4, bg);
52 if (f === 1) art += ellipse(24, 32, 6, 8, light) + ellipse(40, 32, 6, 8, light) + circle(25, 33, 3, bg) + circle(41, 33, 3, bg);
53 if (f === 2) art += rect(19, 27, 26, 11, 5, bg) + circle(25, 32, 3, light) + circle(38, 32, 3, light);
54 if (f === 3) for (let i = 0; i < count; i++) art += circle(20 + i * 24 / (count - 1), 31 + i % 2 * 4, 4, light) + circle(20 + i * 24 / (count - 1), 32 + i % 2 * 4, 2, bg);
55 art += accent ? path('M28 43Q32 49 37 42', 'none', bg, 3) : rect(29, 42, 7, 4, 2, bg);
56 return art;
57}
58function botanical(r) {
59 const [bg, light, hot, cool] = r.palette;
60 const {variant: s, width: w} = r.silhouette;
61 const {variant: f, count} = r.features;
62 let art = [
63 path('M23 43L25 55L40 55L43 43Z', hot),
64 ellipse(32, 48, 18, 7, hot),
65 path('M20 52L25 44L39 44L46 52Z', light),
66 path('M25 54L32 45L39 54M20 50L32 45L45 49', 'none', hot, 4)
67 ][r.layout.variant];
68 art += path('M32 46Q28 30 33 14', 'none', light, 4);
69 if (s === 0) art += path(`M31 35Q${32-w/2} 37 12 21Q29 17 31 35ZM32 29Q35 12 51 13Q52 29 32 29Z`, cool);
70 if (s === 1) art += path('M31 41Q11 45 12 34Q15 28 30 34M32 28Q48 33 51 23Q51 14 33 20', cool);
71 if (s === 2) art += path('M31 39Q8 29 22 13Q35 20 31 39ZM33 37Q55 32 46 19Q32 23 33 37Z', cool);
72 if (s === 3) art += path('M30 40L13 29L27 27L15 16L31 23L38 9L40 26L53 19L45 36Z', cool);
73 const bloomX = f % 2 ? 41 : 29, bloomY = f < 2 ? 16 : 24;
74 if (f === 0) {
75 art += circle(bloomX-6, bloomY, 7, hot) + circle(bloomX+6, bloomY, 7, hot) + circle(bloomX, bloomY-6, 7, hot) + circle(bloomX, bloomY+5, 7, hot) + circle(bloomX, bloomY, 4, light);
76 } else if (f === 1) art += path('M29 20L30 9L37 14L42 7L47 15L54 11L51 22Q42 32 29 20Z', hot) + circle(42, 21, 4, light);
77 else if (f === 2) for (let i = 0; i < count; i++) art += circle(19 + i * 6, 16 + i % 2 * 6, 4, hot);
78 else art += ellipse(40, 18, 9, 13, hot) + path('M40 10L40 25', 'none', light, 3);
79 return art;
80}
81function orbital(r) {
82 const [bg, light, hot, cool] = r.palette;
83 const {variant: s, width: w} = r.silhouette;
84 const {variant: f, count} = r.features;
85 const radius = 11 + (w - 26) / 3;
86 let art = [
87 path('M9 39Q1 18 31 12Q58 6 55 30Q49 53 23 52', 'none', cool, 4),
88 path('M12 13L49 50M12 50L49 13', 'none', cool, 4),
89 path('M9 32A23 23 0 1 1 32 55', 'none', cool, 5),
90 rect(12, 12, 40, 40, 12, cool) + rect(17, 17, 30, 30, 8, bg)
91 ][r.layout.variant];
92 art += [circle(32, 32, radius, hot), rect(18, 18, 28, 28, 6, hot), path('M32 14L50 32L32 50L14 32Z', hot), ellipse(32, 32, radius, 19, hot)][s];
93 if (f === 0) art += path('M10 37Q32 46 53 25', 'none', light, 5);
94 if (f === 1) art += circle(29, 29, 7, light) + circle(33, 26, 7, hot);
95 if (f === 2) art += path('M21 25L43 25M21 34L43 34M27 42L37 42', 'none', light, 4);
96 if (f === 3) art += circle(32, 32, 7, bg) + circle(32, 32, 3, light);
97 for (let i = 0; i < count; i++) art += circle([13, 49, 16, 46, 32][i], [16, 46, 47, 13, 7][i], i % 2 ? 3 : 4, light);
98 return art;
99}
100function landscapes(r) {
101 const [bg, light, hot, cool] = r.palette;
102 const {variant: s, height: h} = r.silhouette;
103 const {variant: f, accent} = r.features;
104 const horizon = 31 + (h - 28) / 2;
105 let art = [circle(22, 19, 9, hot), circle(43, 19, 10, hot), rect(14, 12, 34, 9, 4, hot), circle(32, 21, 15, hot)][r.layout.variant];
106 art += [
107 path(`M7 46L21 22L33 37L43 26L57 46V55H7Z`, cool),
108 path(`M7 ${horizon}Q18 21 31 ${horizon}Q46 22 57 35V55H7Z`, cool),
109 path('M8 53V25H20V38H30V19H40V32H55V53Z', cool),
110 path('M7 36L18 28L26 32L39 23L57 33V55H7Z', cool)
111 ][s];
112 if (f === 0) art += path('M31 35L24 45L36 45L28 55H42L45 43L33 43L37 35Z', light);
113 if (f === 1) art += path('M9 45Q21 40 32 46T55 46M13 53Q23 48 35 53', 'none', light, 4);
114 if (f === 2) art += path('M18 48V35M12 42L18 32L24 42ZM42 50V38M36 43L42 33L48 43Z', light, light, 2);
115 if (f === 3) art += rect(26, 36, 15, 17, 2, light) + path('M23 36L33 27L44 36Z', light) + rect(31, 43, 5, 10, 0, bg);
116 art += accent ? path('M9 18Q13 13 17 18Q21 13 25 18', 'none', light, 2) : circle(51, 12, 3, light);
117 return art;
118}
119function glyphs(r) {
120 const [bg, light, hot, cool] = r.palette;
121 const {variant: s, width: w} = r.silhouette;
122 const {variant: f, accent} = r.features;
123 let art = [
124 circle(32, 32, 24, cool) + circle(32, 32, 18, bg),
125 rect(10, 10, 44, 44, 10, cool) + rect(16, 16, 32, 32, 5, bg),
126 path('M10 26L26 10M38 10L54 26M54 38L38 54M26 54L10 38', 'none', cool, 6),
127 path('M10 47V17H24M54 17V47H40', 'none', cool, 6)
128 ][r.layout.variant];
129 const a = 32 - w/2 + 4, b = 64 - a;
130 art += [
131 path(`M${a} 43L32 17L${b} 43M24 35H40`, 'none', light, 7),
132 path(`M${a} 22H${b}L${a} 43H${b}`, 'none', light, 7),
133 path(`M${a} 19V44H${b}V19M32 20V39`, 'none', light, 7),
134 path('M21 18H37Q49 24 37 32Q50 40 38 46H21Z', light) + rect(27, 24, 9, 5, 2, bg) + rect(27, 36, 10, 5, 2, bg)
135 ][s];
136 art += [circle(32, 32, 5, hot), path('M32 24L40 32L32 40L24 32Z', hot), rect(26, 27, 12, 10, 2, hot), path('M22 37L42 27', 'none', hot, 6)][f];
137 art += circle(accent ? 49 : 15, accent ? 15 : 49, 4, light);
138 return art;
139}
140function woven(r) {
141 const [bg, light, hot, cool] = r.palette;
142 const {variant: s, width: w} = r.silhouette;
143 const {variant: f, count} = r.features;
144 let art = '';
145 const gap = 10 + (w - 26) / 6;
146 if (s === 0) {
147 for (let i = 0; i < 3; i++) art += rect(13+i*gap, 10, 7, 44, 3, i%2 ? hot : light);
148 for (let i = 0; i < 3; i++) art += rect(9, 16+i*gap, 45, 6, 2, cool);
149 art += rect(24, 23, 7, 15, 2, hot);
150 }
151 if (s === 1) for (let i = 0; i < 3; i++) art += path(`M${12+i*12} 12L${20+i*12} 25L${12+i*12} 39L${20+i*12} 52`, 'none', [light, hot, cool][i], 8);
152 if (s === 2) {
153 art += path('M12 20Q12 11 22 11H43Q52 11 52 21V43Q52 53 42 53H22Q12 53 12 43Z', 'none', light, 6);
154 art += path('M21 10V44H43V20H10M54 32H32V54', 'none', hot, 7);
155 art += rect(28, 22, 8, 8, 1, cool);
156 }
157 if (s === 3) for (let i = 0; i < 3; i++) art += path(`M10 ${18+i*13}L22 ${10+i*13}L34 ${18+i*13}L46 ${10+i*13}L54 ${18+i*13}L46 ${26+i*13}L34 ${18+i*13}L22 ${26+i*13}Z`, [light, hot, cool][i]);
158 art = group(art, `rotate(${r.layout.variant * 45} 32 32) scale(.88) translate(4.36 4.36)`);
159 art += [circle(32, 32, 5, bg) + circle(32, 32, 2, light), rect(26, 26, 12, 12, 3, hot), path('M32 24L40 32L32 40L24 32Z', cool), path('M27 28L37 36M37 28L27 36', 'none', bg, 4)][f];
160 for (let i = 0; i < count; i++) art += circle(18 + i * 7, 56, 2, hot);
161 return art;
162}
163function machines(r) {
164 const [bg, light, hot, cool] = r.palette;
165 const {variant: s, width: w} = r.silhouette;
166 const {variant: f, count, accent} = r.features;
167 const x = 32-w/2;
168 let art = [
169 path('M22 23L17 11M42 23L49 11', 'none', hot, 4) + circle(17, 11, 4, light),
170 rect(23, 9, 18, 16, 4, hot) + rect(28, 12, 8, 6, 1, bg),
171 path('M12 27L8 39L19 44M51 27L56 39L47 44', 'none', hot, 6),
172 circle(22, 49, 8, hot) + circle(43, 49, 8, hot)
173 ][r.layout.variant];
174 art += [
175 rect(x, 20, w, 30, 5, light),
176 path(`M${x+5} 19H${59-x}L${64-x} 45L41 52H23L${x} 45Z`, light),
177 ellipse(32, 35, w/2, 18, light),
178 path('M23 17H41L52 29V44L41 52H23L12 44V29Z', light)
179 ][s];
180 if (f === 0) art += circle(32, 34, 11, bg) + circle(32, 34, 7, cool) + circle(35, 31, 3, light);
181 if (f === 1) art += rect(20, 26, 24, 17, 3, bg) + path('M24 37L29 30L34 36L40 29', 'none', cool, 3);
182 if (f === 2) {
183 art += rect(19, 25, 26, 15, 2, bg);
184 for (let i = 0; i < count; i++) art += rect(22+i*4, 28, 2, 9, 1, cool);
185 }
186 if (f === 3) art += circle(25, 32, 6, bg) + circle(39, 32, 6, bg) + path('M20 44H44', 'none', hot, 4);
187 art += circle(accent ? 43 : 21, 46, 3, hot);
188 return art;
189}
190
191const renderers = {masks, creatures, botanical, orbital, landscapes, glyphs, woven, machines};
192export function render(r) {
193 let texture = '';
194 for (let i = 0; i < r.texture.marks; i++) {
195 const x = 8 + i * 6;
196 if (r.texture.variant === 1) texture += circle(x, 6, 1.5, r.palette[3]);
197 if (r.texture.variant === 2) texture += rect(x - 1, 5, 3, 3, 0, r.palette[2]);
198 }
199 return texture + group(renderers[r.family](r), `translate(32 32) rotate(${r.layout.tilt}) scale(${r.layout.flip ? -1 : 1} 1) translate(-32 -32)`);
200}

About

ownerba1b5beed5b5
visibilitypublic
headc808a940bc19

Maintainers

  • ba1b5beed5b5 owner

Clone

  • https://012.run/npub1hgd4hmk4kkukjx7yf402adl7msw0ssnmqmt0y6sgz0j8yjjcj9nqh9znde/seedmark.git

Refs