@ignaciocabeza/bitface 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1099 @@
1
+ // src/renderer/palette.ts
2
+ var SKIN_PRESETS = {
3
+ light: "#FDDCB5",
4
+ medium: "#E8B88A",
5
+ tan: "#D19A6A",
6
+ brown: "#A0673C",
7
+ dark: "#6B4226",
8
+ pale: "#FFF0E0"
9
+ };
10
+ var SKIN_SHADOW_MAP = {
11
+ "#FDDCB5": "#E5C49D",
12
+ "#E8B88A": "#CFA072",
13
+ "#D19A6A": "#B98252",
14
+ "#A0673C": "#885524",
15
+ "#6B4226": "#533010",
16
+ "#FFF0E0": "#E7D8C8"
17
+ };
18
+ var HAIR_PRESETS = {
19
+ black: "#1A1A2E",
20
+ brown: "#6B3A2A",
21
+ blonde: "#E8C84A",
22
+ red: "#B83A1E",
23
+ gray: "#9E9E9E",
24
+ white: "#E8E8E8",
25
+ auburn: "#8B3A1A",
26
+ strawberry: "#D4713A",
27
+ platinum: "#E8E0D0",
28
+ pink: "#E8559E",
29
+ blue: "#3A6BD5",
30
+ purple: "#6B3A8B",
31
+ teal: "#2A9E8B"
32
+ };
33
+ var EYE_PRESETS = {
34
+ brown: "#5C3A1E",
35
+ blue: "#3A7BD5",
36
+ green: "#3A9D5C",
37
+ gray: "#7A7A7A"
38
+ };
39
+ var HEX_COLOR_RE = /^#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
40
+ function sanitizeColor(value, fallback) {
41
+ if (HEX_COLOR_RE.test(value)) return value;
42
+ return fallback;
43
+ }
44
+ function resolveSkinColor(value) {
45
+ if (!value) return SKIN_PRESETS.medium;
46
+ return SKIN_PRESETS[value] ?? sanitizeColor(value, SKIN_PRESETS.medium);
47
+ }
48
+ function resolveSkinShadow(skinHex) {
49
+ return SKIN_SHADOW_MAP[skinHex] ?? darken(skinHex, 30);
50
+ }
51
+ function resolveHairColor(value) {
52
+ if (!value) return HAIR_PRESETS.black;
53
+ return HAIR_PRESETS[value] ?? sanitizeColor(value, HAIR_PRESETS.black);
54
+ }
55
+ function resolveEyeColor(value) {
56
+ if (!value) return EYE_PRESETS.brown;
57
+ return EYE_PRESETS[value] ?? sanitizeColor(value, EYE_PRESETS.brown);
58
+ }
59
+ function darken(hex, amount) {
60
+ const num = parseInt(hex.replace("#", ""), 16);
61
+ const r = Math.max(0, (num >> 16) - amount);
62
+ const g = Math.max(0, (num >> 8 & 255) - amount);
63
+ const b = Math.max(0, (num & 255) - amount);
64
+ return `#${(r << 16 | g << 8 | b).toString(16).padStart(6, "0").toUpperCase()}`;
65
+ }
66
+
67
+ // src/renderer/parts/face-shapes.ts
68
+ var faceShapes = {
69
+ round: {
70
+ pixels: [
71
+ [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
72
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
73
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
74
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
75
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
76
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
77
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
78
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
79
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
80
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
81
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
82
+ [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
83
+ ],
84
+ slotMap: { 1: "skin", 2: "skinShadow" },
85
+ offsetX: 0,
86
+ offsetY: 3
87
+ },
88
+ oval: {
89
+ pixels: [
90
+ [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
91
+ [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
92
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
93
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
94
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
95
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
96
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
97
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
98
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
99
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
100
+ [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
101
+ [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]
102
+ ],
103
+ slotMap: { 1: "skin", 2: "skinShadow" },
104
+ offsetX: 0,
105
+ offsetY: 3
106
+ },
107
+ square: {
108
+ pixels: [
109
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
110
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
111
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
112
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
113
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
114
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
115
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
116
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
117
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
118
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
119
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
120
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0]
121
+ ],
122
+ slotMap: { 1: "skin", 2: "skinShadow" },
123
+ offsetX: 0,
124
+ offsetY: 3
125
+ },
126
+ heart: {
127
+ pixels: [
128
+ [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
129
+ [0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0],
130
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
131
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
132
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
133
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
134
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
135
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
136
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
137
+ [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
138
+ [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
139
+ [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]
140
+ ],
141
+ slotMap: { 1: "skin", 2: "skinShadow" },
142
+ offsetX: 0,
143
+ offsetY: 3
144
+ },
145
+ long: {
146
+ pixels: [
147
+ [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
148
+ [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
149
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
150
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
151
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
152
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
153
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
154
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
155
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
156
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
157
+ [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
158
+ [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
159
+ [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]
160
+ ],
161
+ slotMap: { 1: "skin", 2: "skinShadow" },
162
+ offsetX: 0,
163
+ offsetY: 2
164
+ },
165
+ diamond: {
166
+ pixels: [
167
+ [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
168
+ [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
169
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
170
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
171
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
172
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
173
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
174
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
175
+ [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
176
+ [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
177
+ [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]
178
+ ],
179
+ slotMap: { 1: "skin", 2: "skinShadow" },
180
+ offsetX: 0,
181
+ offsetY: 3
182
+ },
183
+ wide: {
184
+ pixels: [
185
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
186
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
187
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
188
+ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
189
+ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
190
+ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
191
+ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
192
+ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
193
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
194
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
195
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
196
+ [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
197
+ ],
198
+ slotMap: { 1: "skin", 2: "skinShadow" },
199
+ offsetX: 0,
200
+ offsetY: 3
201
+ }
202
+ };
203
+ var face_shapes_default = faceShapes;
204
+
205
+ // src/renderer/parts/eyes.ts
206
+ var eyes = {
207
+ big: {
208
+ pixels: [
209
+ [1, 1, 0, 0, 0, 0, 1, 1],
210
+ [1, 2, 1, 0, 0, 1, 2, 1],
211
+ [1, 2, 3, 0, 0, 1, 2, 3],
212
+ [1, 1, 0, 0, 0, 0, 1, 1]
213
+ ],
214
+ slotMap: { 1: "white", 2: "eyes", 3: "pupil" },
215
+ offsetX: 4,
216
+ offsetY: 7
217
+ },
218
+ small: {
219
+ pixels: [
220
+ [0, 2, 0, 0, 0, 0, 2, 0],
221
+ [0, 3, 0, 0, 0, 0, 3, 0]
222
+ ],
223
+ slotMap: { 2: "eyes", 3: "pupil" },
224
+ offsetX: 4,
225
+ offsetY: 8
226
+ },
227
+ narrow: {
228
+ pixels: [
229
+ [1, 2, 3, 0, 0, 1, 2, 3]
230
+ ],
231
+ slotMap: { 1: "white", 2: "eyes", 3: "pupil" },
232
+ offsetX: 4,
233
+ offsetY: 8
234
+ },
235
+ round: {
236
+ pixels: [
237
+ [0, 1, 0, 0, 0, 0, 1, 0],
238
+ [1, 2, 1, 0, 0, 1, 2, 1],
239
+ [1, 2, 3, 0, 0, 1, 2, 3],
240
+ [0, 1, 0, 0, 0, 0, 1, 0]
241
+ ],
242
+ slotMap: { 1: "white", 2: "eyes", 3: "pupil" },
243
+ offsetX: 4,
244
+ offsetY: 7
245
+ },
246
+ wink: {
247
+ pixels: [
248
+ [1, 1, 0, 0, 0, 0, 0, 0],
249
+ [1, 2, 1, 0, 0, 0, 0, 0],
250
+ [1, 2, 3, 0, 0, 3, 3, 3],
251
+ [1, 1, 0, 0, 0, 0, 0, 0]
252
+ ],
253
+ slotMap: { 1: "white", 2: "eyes", 3: "pupil" },
254
+ offsetX: 4,
255
+ offsetY: 7
256
+ },
257
+ happy: {
258
+ pixels: [
259
+ [0, 3, 3, 0, 0, 0, 3, 3],
260
+ [3, 0, 0, 0, 0, 3, 0, 0]
261
+ ],
262
+ slotMap: { 3: "pupil" },
263
+ offsetX: 4,
264
+ offsetY: 8
265
+ },
266
+ angry: {
267
+ pixels: [
268
+ [1, 1, 0, 0, 0, 0, 1, 1],
269
+ [1, 2, 3, 0, 0, 3, 2, 1],
270
+ [0, 1, 1, 0, 0, 1, 1, 0]
271
+ ],
272
+ slotMap: { 1: "white", 2: "eyes", 3: "pupil" },
273
+ offsetX: 4,
274
+ offsetY: 7
275
+ },
276
+ dots: {
277
+ pixels: [
278
+ [0, 0, 3, 0, 0, 0, 0, 3]
279
+ ],
280
+ slotMap: { 3: "pupil" },
281
+ offsetX: 4,
282
+ offsetY: 9
283
+ },
284
+ sleepy: {
285
+ pixels: [
286
+ [1, 1, 0, 0, 0, 0, 1, 1],
287
+ [3, 3, 0, 0, 0, 0, 3, 3]
288
+ ],
289
+ slotMap: { 1: "white", 3: "pupil" },
290
+ offsetX: 4,
291
+ offsetY: 8
292
+ },
293
+ cross: {
294
+ pixels: [
295
+ [3, 0, 3, 0, 0, 3, 0, 3],
296
+ [0, 3, 0, 0, 0, 0, 3, 0],
297
+ [3, 0, 3, 0, 0, 3, 0, 3]
298
+ ],
299
+ slotMap: { 3: "pupil" },
300
+ offsetX: 4,
301
+ offsetY: 7
302
+ },
303
+ heart: {
304
+ pixels: [
305
+ [2, 0, 2, 0, 0, 2, 0, 2],
306
+ [2, 2, 2, 0, 0, 2, 2, 2],
307
+ [0, 2, 0, 0, 0, 0, 2, 0]
308
+ ],
309
+ slotMap: { 2: "eyes" },
310
+ offsetX: 4,
311
+ offsetY: 7
312
+ }
313
+ };
314
+ var eyes_default = eyes;
315
+
316
+ // src/renderer/parts/eyebrows.ts
317
+ var eyebrows = {
318
+ thick: {
319
+ pixels: [
320
+ [1, 1, 1, 0, 0, 1, 1, 1],
321
+ [1, 1, 1, 0, 0, 1, 1, 1]
322
+ ],
323
+ slotMap: { 1: "hair" },
324
+ offsetX: 4,
325
+ offsetY: 6
326
+ },
327
+ thin: {
328
+ pixels: [
329
+ [1, 1, 1, 0, 0, 1, 1, 1]
330
+ ],
331
+ slotMap: { 1: "hair" },
332
+ offsetX: 4,
333
+ offsetY: 6
334
+ },
335
+ arched: {
336
+ pixels: [
337
+ [0, 1, 1, 0, 0, 0, 1, 1],
338
+ [1, 0, 0, 0, 0, 1, 0, 0]
339
+ ],
340
+ slotMap: { 1: "hair" },
341
+ offsetX: 4,
342
+ offsetY: 5
343
+ },
344
+ angry: {
345
+ pixels: [
346
+ [1, 0, 0, 0, 0, 0, 0, 1],
347
+ [0, 1, 1, 0, 0, 1, 1, 0]
348
+ ],
349
+ slotMap: { 1: "hair" },
350
+ offsetX: 4,
351
+ offsetY: 5
352
+ },
353
+ worried: {
354
+ pixels: [
355
+ [0, 0, 1, 0, 0, 1, 0, 0],
356
+ [0, 1, 0, 0, 0, 0, 1, 0]
357
+ ],
358
+ slotMap: { 1: "hair" },
359
+ offsetX: 4,
360
+ offsetY: 5
361
+ },
362
+ unibrow: {
363
+ pixels: [
364
+ [1, 1, 1, 1, 1, 1, 1, 1],
365
+ [1, 1, 0, 0, 0, 0, 1, 1]
366
+ ],
367
+ slotMap: { 1: "hair" },
368
+ offsetX: 4,
369
+ offsetY: 5
370
+ },
371
+ none: {
372
+ pixels: [],
373
+ slotMap: {},
374
+ offsetX: 0,
375
+ offsetY: 0
376
+ }
377
+ };
378
+ var eyebrows_default = eyebrows;
379
+
380
+ // src/renderer/parts/mouth.ts
381
+ var mouth = {
382
+ smile: {
383
+ pixels: [
384
+ [1, 0, 0, 0, 0, 1],
385
+ [0, 1, 1, 1, 1, 0]
386
+ ],
387
+ slotMap: { 1: "mouth" },
388
+ offsetX: 5,
389
+ offsetY: 12
390
+ },
391
+ frown: {
392
+ pixels: [
393
+ [0, 1, 1, 1, 1, 0],
394
+ [1, 0, 0, 0, 0, 1]
395
+ ],
396
+ slotMap: { 1: "mouth" },
397
+ offsetX: 5,
398
+ offsetY: 12
399
+ },
400
+ open: {
401
+ pixels: [
402
+ [0, 1, 1, 1, 1, 0],
403
+ [1, 1, 1, 1, 1, 1],
404
+ [0, 1, 1, 1, 1, 0]
405
+ ],
406
+ slotMap: { 1: "mouth" },
407
+ offsetX: 5,
408
+ offsetY: 11
409
+ },
410
+ flat: {
411
+ pixels: [
412
+ [1, 1, 1, 1, 1, 1]
413
+ ],
414
+ slotMap: { 1: "mouth" },
415
+ offsetX: 5,
416
+ offsetY: 12
417
+ },
418
+ teeth: {
419
+ pixels: [
420
+ [0, 1, 1, 1, 1, 0],
421
+ [0, 2, 2, 2, 2, 0],
422
+ [0, 1, 1, 1, 1, 0]
423
+ ],
424
+ slotMap: { 1: "mouth", 2: "white" },
425
+ offsetX: 5,
426
+ offsetY: 11
427
+ },
428
+ smirk: {
429
+ pixels: [
430
+ [0, 0, 0, 0, 1, 0],
431
+ [0, 1, 1, 1, 0, 0]
432
+ ],
433
+ slotMap: { 1: "mouth" },
434
+ offsetX: 5,
435
+ offsetY: 12
436
+ },
437
+ grin: {
438
+ pixels: [
439
+ [0, 1, 1, 1, 1, 1, 1, 0],
440
+ [0, 1, 2, 2, 2, 2, 1, 0],
441
+ [0, 0, 1, 1, 1, 1, 0, 0]
442
+ ],
443
+ slotMap: { 1: "mouth", 2: "white" },
444
+ offsetX: 4,
445
+ offsetY: 11
446
+ },
447
+ tongue: {
448
+ pixels: [
449
+ [0, 1, 1, 1, 1, 0],
450
+ [0, 0, 1, 1, 0, 0],
451
+ [0, 0, 0, 1, 0, 0]
452
+ ],
453
+ slotMap: { 1: "mouth" },
454
+ offsetX: 5,
455
+ offsetY: 12
456
+ },
457
+ oh: {
458
+ pixels: [
459
+ [0, 1, 1, 0],
460
+ [1, 0, 0, 1],
461
+ [0, 1, 1, 0]
462
+ ],
463
+ slotMap: { 1: "mouth" },
464
+ offsetX: 6,
465
+ offsetY: 11
466
+ }
467
+ };
468
+ var mouth_default = mouth;
469
+
470
+ // src/renderer/parts/nose.ts
471
+ var nose = {
472
+ small: {
473
+ pixels: [
474
+ [0, 1, 0],
475
+ [1, 0, 1]
476
+ ],
477
+ slotMap: { 1: "skinShadow" },
478
+ offsetX: 7,
479
+ offsetY: 10
480
+ },
481
+ pointy: {
482
+ pixels: [
483
+ [0, 1, 0],
484
+ [0, 1, 0],
485
+ [1, 0, 1]
486
+ ],
487
+ slotMap: { 1: "skinShadow" },
488
+ offsetX: 7,
489
+ offsetY: 9
490
+ },
491
+ wide: {
492
+ pixels: [
493
+ [0, 1, 1, 0],
494
+ [1, 0, 0, 1],
495
+ [1, 0, 0, 1]
496
+ ],
497
+ slotMap: { 1: "skinShadow" },
498
+ offsetX: 6,
499
+ offsetY: 9
500
+ },
501
+ button: {
502
+ pixels: [
503
+ [1, 1]
504
+ ],
505
+ slotMap: { 1: "skinShadow" },
506
+ offsetX: 7,
507
+ offsetY: 10
508
+ },
509
+ long: {
510
+ pixels: [
511
+ [0, 1, 0],
512
+ [0, 1, 0],
513
+ [0, 1, 0],
514
+ [1, 0, 1]
515
+ ],
516
+ slotMap: { 1: "skinShadow" },
517
+ offsetX: 7,
518
+ offsetY: 8
519
+ },
520
+ snub: {
521
+ pixels: [
522
+ [0, 1],
523
+ [1, 1]
524
+ ],
525
+ slotMap: { 1: "skinShadow" },
526
+ offsetX: 7,
527
+ offsetY: 10
528
+ }
529
+ };
530
+ var nose_default = nose;
531
+
532
+ // src/renderer/parts/ears.ts
533
+ var ears = {
534
+ small: {
535
+ pixels: [
536
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
537
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
538
+ [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]
539
+ ],
540
+ slotMap: { 1: "skin", 2: "skinShadow" },
541
+ offsetX: 0,
542
+ offsetY: 8
543
+ },
544
+ big: {
545
+ pixels: [
546
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
547
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
548
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
549
+ [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
550
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
551
+ ],
552
+ slotMap: { 1: "skin", 2: "skinShadow" },
553
+ offsetX: 0,
554
+ offsetY: 7
555
+ },
556
+ pointed: {
557
+ pixels: [
558
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
559
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
560
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
561
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
562
+ [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]
563
+ ],
564
+ slotMap: { 1: "skin", 2: "skinShadow" },
565
+ offsetX: 0,
566
+ offsetY: 5
567
+ },
568
+ elf: {
569
+ pixels: [
570
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
571
+ [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],
572
+ [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],
573
+ [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],
574
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
575
+ [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]
576
+ ],
577
+ slotMap: { 1: "skin", 2: "skinShadow" },
578
+ offsetX: 0,
579
+ offsetY: 4
580
+ },
581
+ none: {
582
+ pixels: [],
583
+ slotMap: {},
584
+ offsetX: 0,
585
+ offsetY: 0
586
+ }
587
+ };
588
+ var ears_default = ears;
589
+
590
+ // src/renderer/parts/hair.ts
591
+ var hair = {
592
+ short: {
593
+ pixels: [
594
+ [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
595
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
596
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
597
+ [0, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 0]
598
+ ],
599
+ slotMap: { 1: "hair", 2: "hairShadow" },
600
+ offsetX: 0,
601
+ offsetY: 2
602
+ },
603
+ long: {
604
+ pixels: [
605
+ [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
606
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
607
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
608
+ [0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 0],
609
+ [0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0],
610
+ [0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0],
611
+ [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0],
612
+ [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0],
613
+ [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0],
614
+ [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0],
615
+ [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
616
+ [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]
617
+ ],
618
+ slotMap: { 1: "hair", 2: "hairShadow" },
619
+ offsetX: 0,
620
+ offsetY: 2
621
+ },
622
+ curly: {
623
+ pixels: [
624
+ [0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0],
625
+ [0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0],
626
+ [0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0],
627
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
628
+ [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
629
+ [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
630
+ [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
631
+ [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
632
+ [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0]
633
+ ],
634
+ slotMap: { 1: "hair", 2: "hairShadow" },
635
+ offsetX: 0,
636
+ offsetY: 1
637
+ },
638
+ mohawk: {
639
+ pixels: [
640
+ [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
641
+ [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
642
+ [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
643
+ [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
644
+ [0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0]
645
+ ],
646
+ slotMap: { 1: "hair", 2: "hairShadow" },
647
+ offsetX: 0,
648
+ offsetY: 0
649
+ },
650
+ bald: {
651
+ pixels: [],
652
+ slotMap: {},
653
+ offsetX: 0,
654
+ offsetY: 0
655
+ },
656
+ ponytail: {
657
+ pixels: [
658
+ [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
659
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
660
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
661
+ [0, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 0],
662
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],
663
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],
664
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0],
665
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]
666
+ ],
667
+ slotMap: { 1: "hair", 2: "hairShadow" },
668
+ offsetX: 0,
669
+ offsetY: 2
670
+ },
671
+ spiky: {
672
+ pixels: [
673
+ [0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0],
674
+ [0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0],
675
+ [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
676
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
677
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
678
+ [0, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 0]
679
+ ],
680
+ slotMap: { 1: "hair", 2: "hairShadow" },
681
+ offsetX: 0,
682
+ offsetY: 0
683
+ },
684
+ bob: {
685
+ pixels: [
686
+ [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
687
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
688
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
689
+ [0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 0],
690
+ [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0],
691
+ [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0],
692
+ [0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0],
693
+ [0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0]
694
+ ],
695
+ slotMap: { 1: "hair", 2: "hairShadow" },
696
+ offsetX: 0,
697
+ offsetY: 2
698
+ },
699
+ afro: {
700
+ pixels: [
701
+ [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
702
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
703
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
704
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
705
+ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
706
+ [1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1],
707
+ [1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1],
708
+ [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1],
709
+ [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1]
710
+ ],
711
+ slotMap: { 1: "hair", 2: "hairShadow" },
712
+ offsetX: 0,
713
+ offsetY: 0
714
+ },
715
+ bangs: {
716
+ pixels: [
717
+ [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
718
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
719
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
720
+ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
721
+ [0, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 2, 1, 1, 0]
722
+ ],
723
+ slotMap: { 1: "hair", 2: "hairShadow" },
724
+ offsetX: 0,
725
+ offsetY: 2
726
+ }
727
+ };
728
+ var hair_default = hair;
729
+
730
+ // src/renderer/parts/beard.ts
731
+ var beard = {
732
+ stubble: {
733
+ // Sparse dots at chin/jaw edge
734
+ pixels: [
735
+ [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
736
+ [0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0]
737
+ ],
738
+ slotMap: { 1: "hair" },
739
+ offsetX: 0,
740
+ offsetY: 13
741
+ },
742
+ goatee: {
743
+ // Small chin patch below the mouth
744
+ pixels: [
745
+ [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
746
+ [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]
747
+ ],
748
+ slotMap: { 1: "hair" },
749
+ offsetX: 0,
750
+ offsetY: 13
751
+ },
752
+ full: {
753
+ // Jaw outline: sideburns at edges + solid chin, hollow center so mouth shows
754
+ pixels: [
755
+ [0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0],
756
+ [0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0],
757
+ [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
758
+ [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]
759
+ ],
760
+ slotMap: { 1: "hair" },
761
+ offsetX: 0,
762
+ offsetY: 11
763
+ },
764
+ mustache: {
765
+ // Sits just above the mouth line
766
+ pixels: [
767
+ [0, 0, 1, 1, 0, 0, 1, 1, 0, 0],
768
+ [0, 1, 0, 0, 1, 1, 0, 0, 1, 0]
769
+ ],
770
+ slotMap: { 1: "hair" },
771
+ offsetX: 3,
772
+ offsetY: 11
773
+ },
774
+ handlebar: {
775
+ // Wide curling mustache
776
+ pixels: [
777
+ [0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0],
778
+ [0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0],
779
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
780
+ ],
781
+ slotMap: { 1: "hair" },
782
+ offsetX: 2,
783
+ offsetY: 11
784
+ },
785
+ none: {
786
+ pixels: [],
787
+ slotMap: {},
788
+ offsetX: 0,
789
+ offsetY: 0
790
+ }
791
+ };
792
+ var beard_default = beard;
793
+
794
+ // src/renderer/parts/accessories.ts
795
+ var accessories = {
796
+ glasses: {
797
+ pixels: [
798
+ [0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0],
799
+ [1, 1, 1, 3, 3, 1, 1, 1, 1, 3, 3, 1, 1, 1],
800
+ [0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0]
801
+ ],
802
+ slotMap: { 1: "accessoryPrimary", 3: "lens" },
803
+ offsetX: 1,
804
+ offsetY: 7
805
+ },
806
+ sunglasses: {
807
+ pixels: [
808
+ [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
809
+ [1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1],
810
+ [0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0]
811
+ ],
812
+ slotMap: { 1: "accessoryPrimary", 2: "accessorySecondary" },
813
+ offsetX: 1,
814
+ offsetY: 7
815
+ },
816
+ hat: {
817
+ pixels: [
818
+ [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
819
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
820
+ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
821
+ [0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0]
822
+ ],
823
+ slotMap: { 1: "accessoryPrimary", 2: "accessorySecondary" },
824
+ offsetX: 0,
825
+ offsetY: 0
826
+ },
827
+ headband: {
828
+ pixels: [
829
+ [0, 0, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 0, 0]
830
+ ],
831
+ slotMap: { 1: "accessoryPrimary", 2: "accessorySecondary" },
832
+ offsetX: 0,
833
+ offsetY: 5
834
+ },
835
+ earrings: {
836
+ pixels: [
837
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
838
+ [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
839
+ ],
840
+ slotMap: { 1: "accessoryPrimary" },
841
+ offsetX: 0,
842
+ offsetY: 11
843
+ },
844
+ none: {
845
+ pixels: [],
846
+ slotMap: {},
847
+ offsetX: 0,
848
+ offsetY: 0
849
+ }
850
+ };
851
+ var accessories_default = accessories;
852
+
853
+ // src/renderer/parts/index.ts
854
+ var registry = {
855
+ faceShape: face_shapes_default,
856
+ eyes: eyes_default,
857
+ eyebrows: eyebrows_default,
858
+ mouth: mouth_default,
859
+ nose: nose_default,
860
+ ears: ears_default,
861
+ hair: hair_default,
862
+ beard: beard_default,
863
+ accessories: accessories_default
864
+ };
865
+ function getPart(category, name) {
866
+ return registry[category]?.[name];
867
+ }
868
+ function getVariantNames(category) {
869
+ const cat = registry[category];
870
+ return cat ? Object.keys(cat) : [];
871
+ }
872
+ function getAllCategories() {
873
+ return Object.keys(registry);
874
+ }
875
+
876
+ // src/renderer/generator.ts
877
+ var BASE_SIZE = 16;
878
+ function buildColorMap(config) {
879
+ const skin = resolveSkinColor(config.skinColor);
880
+ const skinShadow = resolveSkinShadow(skin);
881
+ const hairColor = resolveHairColor(config.hairColor);
882
+ const eyeColor = resolveEyeColor(config.eyeColor);
883
+ return {
884
+ skin,
885
+ skinShadow,
886
+ hair: hairColor,
887
+ hairShadow: darkenColor(hairColor, 25),
888
+ eyes: eyeColor,
889
+ pupil: "#111111",
890
+ white: "#FFFFFF",
891
+ mouth: "#C75050",
892
+ accessoryPrimary: "#333333",
893
+ accessorySecondary: "#1A1A1A",
894
+ lens: "#87CEEB"
895
+ };
896
+ }
897
+ function darkenColor(hex, amount) {
898
+ const num = parseInt(hex.replace("#", ""), 16);
899
+ const r = Math.max(0, (num >> 16) - amount);
900
+ const g = Math.max(0, (num >> 8 & 255) - amount);
901
+ const b = Math.max(0, (num & 255) - amount);
902
+ return `#${(r << 16 | g << 8 | b).toString(16).padStart(6, "0")}`;
903
+ }
904
+ function stampPart(grid, part, colorMap) {
905
+ for (let py = 0; py < part.pixels.length; py++) {
906
+ const row = part.pixels[py];
907
+ for (let px = 0; px < row.length; px++) {
908
+ const slot = row[px];
909
+ if (slot === 0) continue;
910
+ const role = part.slotMap[slot];
911
+ if (!role) continue;
912
+ const color = colorMap[role];
913
+ if (!color) continue;
914
+ const gx = part.offsetX + px;
915
+ const gy = part.offsetY + py;
916
+ if (gx >= 0 && gx < BASE_SIZE && gy >= 0 && gy < BASE_SIZE) {
917
+ grid[gy][gx] = color;
918
+ }
919
+ }
920
+ }
921
+ }
922
+ var LAYER_ORDER = [
923
+ { category: "faceShape", configKey: "faceShape" },
924
+ { category: "ears", configKey: "ears" },
925
+ { category: "nose", configKey: "nose" },
926
+ { category: "mouth", configKey: "mouth" },
927
+ { category: "eyes", configKey: "eyes" },
928
+ { category: "eyebrows", configKey: "eyebrows" },
929
+ { category: "hair", configKey: "hair" },
930
+ { category: "beard", configKey: "beard" },
931
+ { category: "accessories", configKey: "accessories" }
932
+ ];
933
+ function generateGrid(config) {
934
+ const grid = Array.from(
935
+ { length: BASE_SIZE },
936
+ () => Array.from({ length: BASE_SIZE }, () => null)
937
+ );
938
+ const colorMap = buildColorMap(config);
939
+ for (const layer of LAYER_ORDER) {
940
+ const name = config[layer.configKey];
941
+ if (!name || name === "none") continue;
942
+ const part = getPart(layer.category, name);
943
+ if (!part) continue;
944
+ stampPart(grid, part, colorMap);
945
+ }
946
+ return grid;
947
+ }
948
+ function generatePartThumbnail(category, name, skinColor, hairColor, eyeColor) {
949
+ const grid = Array.from(
950
+ { length: BASE_SIZE },
951
+ () => Array.from({ length: BASE_SIZE }, () => null)
952
+ );
953
+ const skin = resolveSkinColor(skinColor);
954
+ const colorMap = {
955
+ skin,
956
+ skinShadow: resolveSkinShadow(skin),
957
+ hair: resolveHairColor(hairColor),
958
+ hairShadow: darkenColor(resolveHairColor(hairColor), 25),
959
+ eyes: resolveEyeColor(eyeColor),
960
+ pupil: "#111111",
961
+ white: "#FFFFFF",
962
+ mouth: "#C75050",
963
+ accessoryPrimary: "#333333",
964
+ accessorySecondary: "#1A1A1A",
965
+ lens: "#87CEEB"
966
+ };
967
+ const part = getPart(category, name);
968
+ if (part) {
969
+ stampPart(grid, part, colorMap);
970
+ }
971
+ return grid;
972
+ }
973
+
974
+ // src/renderer/svg.ts
975
+ function gridToSvg(grid, backgroundColor) {
976
+ const height = grid.length;
977
+ const width = height > 0 ? grid[0].length : 0;
978
+ const raw = backgroundColor ?? "#87CEEB";
979
+ const bg = raw === "transparent" ? "transparent" : sanitizeColor(raw, "#87CEEB");
980
+ const rects = [];
981
+ if (bg !== "transparent") {
982
+ rects.push(`<rect width="${width}" height="${height}" fill="${bg}"/>`);
983
+ }
984
+ for (let y = 0; y < height; y++) {
985
+ let x = 0;
986
+ while (x < width) {
987
+ const color = grid[y][x];
988
+ if (color === null) {
989
+ x++;
990
+ continue;
991
+ }
992
+ let runLen = 1;
993
+ while (x + runLen < width && grid[y][x + runLen] === color) {
994
+ runLen++;
995
+ }
996
+ rects.push(`<rect x="${x}" y="${y}" width="${runLen}" height="1" fill="${color}"/>`);
997
+ x += runLen;
998
+ }
999
+ }
1000
+ return [
1001
+ `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}" shape-rendering="crispEdges">`,
1002
+ ...rects,
1003
+ "</svg>"
1004
+ ].join("");
1005
+ }
1006
+
1007
+ // src/renderer/index.ts
1008
+ function pickRandom(arr) {
1009
+ return arr[Math.floor(Math.random() * arr.length)];
1010
+ }
1011
+ function generateRandomConfig() {
1012
+ return {
1013
+ faceShape: pickRandom(getVariantNames("faceShape")),
1014
+ eyes: pickRandom(getVariantNames("eyes")),
1015
+ eyebrows: pickRandom(getVariantNames("eyebrows")),
1016
+ mouth: pickRandom(getVariantNames("mouth")),
1017
+ nose: pickRandom(getVariantNames("nose")),
1018
+ ears: pickRandom(getVariantNames("ears")),
1019
+ hair: pickRandom(getVariantNames("hair")),
1020
+ beard: pickRandom(getVariantNames("beard")),
1021
+ accessories: pickRandom(getVariantNames("accessories")),
1022
+ skinColor: pickRandom(Object.keys(SKIN_PRESETS)),
1023
+ hairColor: pickRandom(Object.keys(HAIR_PRESETS)),
1024
+ eyeColor: pickRandom(Object.keys(EYE_PRESETS))
1025
+ };
1026
+ }
1027
+ function generateFace(config) {
1028
+ const resolved = config ?? generateRandomConfig();
1029
+ const grid = generateGrid(resolved);
1030
+ return gridToSvg(grid, resolved.backgroundColor);
1031
+ }
1032
+ function getAvailableParts() {
1033
+ const result = {};
1034
+ for (const category of getAllCategories()) {
1035
+ result[category] = getVariantNames(category);
1036
+ }
1037
+ return result;
1038
+ }
1039
+ function getPartThumbnail(category, name, skinColor, hairColor, eyeColor) {
1040
+ const grid = generatePartThumbnail(category, name, skinColor, hairColor, eyeColor);
1041
+ return gridToSvg(grid);
1042
+ }
1043
+
1044
+ // src/renderer/animations.ts
1045
+ var ANIMATIONS = {
1046
+ idle: {
1047
+ name: "idle",
1048
+ frames: [
1049
+ { duration: 3e3, overrides: {} },
1050
+ { duration: 150, overrides: { eyes: "happy" } },
1051
+ { duration: 150, overrides: {} }
1052
+ ]
1053
+ },
1054
+ talk: {
1055
+ name: "talk",
1056
+ frames: [
1057
+ { duration: 200, overrides: { mouth: "smile" } },
1058
+ { duration: 200, overrides: { mouth: "open" } },
1059
+ { duration: 200, overrides: { mouth: "flat" } },
1060
+ { duration: 200, overrides: { mouth: "open" } },
1061
+ { duration: 300, overrides: { mouth: "smile" } }
1062
+ ]
1063
+ },
1064
+ blink: {
1065
+ name: "blink",
1066
+ frames: [
1067
+ { duration: 2500, overrides: {} },
1068
+ { duration: 100, overrides: { eyes: "narrow" } },
1069
+ { duration: 100, overrides: { eyes: "happy" } },
1070
+ { duration: 100, overrides: { eyes: "narrow" } },
1071
+ { duration: 200, overrides: {} }
1072
+ ]
1073
+ },
1074
+ emote: {
1075
+ name: "emote",
1076
+ frames: [
1077
+ { duration: 500, overrides: {} },
1078
+ { duration: 400, overrides: { eyebrows: "arched", mouth: "open" } },
1079
+ { duration: 400, overrides: { eyebrows: "arched", mouth: "smile" } },
1080
+ { duration: 300, overrides: {} }
1081
+ ]
1082
+ }
1083
+ };
1084
+ function getAnimationNames() {
1085
+ return Object.keys(ANIMATIONS);
1086
+ }
1087
+
1088
+ export {
1089
+ SKIN_PRESETS,
1090
+ HAIR_PRESETS,
1091
+ EYE_PRESETS,
1092
+ generateRandomConfig,
1093
+ generateFace,
1094
+ getAvailableParts,
1095
+ getPartThumbnail,
1096
+ ANIMATIONS,
1097
+ getAnimationNames
1098
+ };
1099
+ //# sourceMappingURL=chunk-SCBE5EEX.js.map