@energy8platform/golem 0.1.0 → 0.2.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.
package/dist/editor.js CHANGED
@@ -42875,6 +42875,818 @@ var init_TextStyle = __esm({
42875
42875
  }
42876
42876
  });
42877
42877
 
42878
+ // node_modules/gifenc/dist/gifenc.js
42879
+ var require_gifenc = __commonJS({
42880
+ "node_modules/gifenc/dist/gifenc.js"(exports) {
42881
+ var __defProp2 = Object.defineProperty;
42882
+ var __markAsModule = (target) => __defProp2(target, "__esModule", { value: true });
42883
+ var __export2 = (target, all) => {
42884
+ for (var name in all)
42885
+ __defProp2(target, name, { get: all[name], enumerable: true });
42886
+ };
42887
+ __markAsModule(exports);
42888
+ __export2(exports, {
42889
+ GIFEncoder: () => GIFEncoder2,
42890
+ applyPalette: () => applyPalette2,
42891
+ default: () => src_default,
42892
+ nearestColor: () => nearestColor,
42893
+ nearestColorIndex: () => nearestColorIndex,
42894
+ nearestColorIndexWithDistance: () => nearestColorIndexWithDistance,
42895
+ prequantize: () => prequantize,
42896
+ quantize: () => quantize2,
42897
+ snapColorsToPalette: () => snapColorsToPalette
42898
+ });
42899
+ var constants_default = {
42900
+ signature: "GIF",
42901
+ version: "89a",
42902
+ trailer: 59,
42903
+ extensionIntroducer: 33,
42904
+ applicationExtensionLabel: 255,
42905
+ graphicControlExtensionLabel: 249,
42906
+ imageSeparator: 44,
42907
+ signatureSize: 3,
42908
+ versionSize: 3,
42909
+ globalColorTableFlagMask: 128,
42910
+ colorResolutionMask: 112,
42911
+ sortFlagMask: 8,
42912
+ globalColorTableSizeMask: 7,
42913
+ applicationIdentifierSize: 8,
42914
+ applicationAuthCodeSize: 3,
42915
+ disposalMethodMask: 28,
42916
+ userInputFlagMask: 2,
42917
+ transparentColorFlagMask: 1,
42918
+ localColorTableFlagMask: 128,
42919
+ interlaceFlagMask: 64,
42920
+ idSortFlagMask: 32,
42921
+ localColorTableSizeMask: 7
42922
+ };
42923
+ function createStream(initialCapacity = 256) {
42924
+ let cursor2 = 0;
42925
+ let contents = new Uint8Array(initialCapacity);
42926
+ return {
42927
+ get buffer() {
42928
+ return contents.buffer;
42929
+ },
42930
+ reset() {
42931
+ cursor2 = 0;
42932
+ },
42933
+ bytesView() {
42934
+ return contents.subarray(0, cursor2);
42935
+ },
42936
+ bytes() {
42937
+ return contents.slice(0, cursor2);
42938
+ },
42939
+ writeByte(byte) {
42940
+ expand(cursor2 + 1);
42941
+ contents[cursor2] = byte;
42942
+ cursor2++;
42943
+ },
42944
+ writeBytes(data, offset = 0, byteLength = data.length) {
42945
+ expand(cursor2 + byteLength);
42946
+ for (let i6 = 0; i6 < byteLength; i6++) {
42947
+ contents[cursor2++] = data[i6 + offset];
42948
+ }
42949
+ },
42950
+ writeBytesView(data, offset = 0, byteLength = data.byteLength) {
42951
+ expand(cursor2 + byteLength);
42952
+ contents.set(data.subarray(offset, offset + byteLength), cursor2);
42953
+ cursor2 += byteLength;
42954
+ }
42955
+ };
42956
+ function expand(newCapacity) {
42957
+ var prevCapacity = contents.length;
42958
+ if (prevCapacity >= newCapacity)
42959
+ return;
42960
+ var CAPACITY_DOUBLING_MAX = 1024 * 1024;
42961
+ newCapacity = Math.max(newCapacity, prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2 : 1.125) >>> 0);
42962
+ if (prevCapacity != 0)
42963
+ newCapacity = Math.max(newCapacity, 256);
42964
+ const oldContents = contents;
42965
+ contents = new Uint8Array(newCapacity);
42966
+ if (cursor2 > 0)
42967
+ contents.set(oldContents.subarray(0, cursor2), 0);
42968
+ }
42969
+ }
42970
+ var BITS = 12;
42971
+ var DEFAULT_HSIZE = 5003;
42972
+ var MASKS = [
42973
+ 0,
42974
+ 1,
42975
+ 3,
42976
+ 7,
42977
+ 15,
42978
+ 31,
42979
+ 63,
42980
+ 127,
42981
+ 255,
42982
+ 511,
42983
+ 1023,
42984
+ 2047,
42985
+ 4095,
42986
+ 8191,
42987
+ 16383,
42988
+ 32767,
42989
+ 65535
42990
+ ];
42991
+ function lzwEncode(width, height, pixels, colorDepth, outStream = createStream(512), accum = new Uint8Array(256), htab = new Int32Array(DEFAULT_HSIZE), codetab = new Int32Array(DEFAULT_HSIZE)) {
42992
+ const hsize = htab.length;
42993
+ const initCodeSize = Math.max(2, colorDepth);
42994
+ accum.fill(0);
42995
+ codetab.fill(0);
42996
+ htab.fill(-1);
42997
+ let cur_accum = 0;
42998
+ let cur_bits = 0;
42999
+ const init_bits = initCodeSize + 1;
43000
+ const g_init_bits = init_bits;
43001
+ let clear_flg = false;
43002
+ let n_bits = g_init_bits;
43003
+ let maxcode = (1 << n_bits) - 1;
43004
+ const ClearCode = 1 << init_bits - 1;
43005
+ const EOFCode = ClearCode + 1;
43006
+ let free_ent = ClearCode + 2;
43007
+ let a_count = 0;
43008
+ let ent = pixels[0];
43009
+ let hshift = 0;
43010
+ for (let fcode = hsize; fcode < 65536; fcode *= 2) {
43011
+ ++hshift;
43012
+ }
43013
+ hshift = 8 - hshift;
43014
+ outStream.writeByte(initCodeSize);
43015
+ output(ClearCode);
43016
+ const length2 = pixels.length;
43017
+ for (let idx = 1; idx < length2; idx++) {
43018
+ next_block: {
43019
+ const c5 = pixels[idx];
43020
+ const fcode = (c5 << BITS) + ent;
43021
+ let i6 = c5 << hshift ^ ent;
43022
+ if (htab[i6] === fcode) {
43023
+ ent = codetab[i6];
43024
+ break next_block;
43025
+ }
43026
+ const disp = i6 === 0 ? 1 : hsize - i6;
43027
+ while (htab[i6] >= 0) {
43028
+ i6 -= disp;
43029
+ if (i6 < 0)
43030
+ i6 += hsize;
43031
+ if (htab[i6] === fcode) {
43032
+ ent = codetab[i6];
43033
+ break next_block;
43034
+ }
43035
+ }
43036
+ output(ent);
43037
+ ent = c5;
43038
+ if (free_ent < 1 << BITS) {
43039
+ codetab[i6] = free_ent++;
43040
+ htab[i6] = fcode;
43041
+ } else {
43042
+ htab.fill(-1);
43043
+ free_ent = ClearCode + 2;
43044
+ clear_flg = true;
43045
+ output(ClearCode);
43046
+ }
43047
+ }
43048
+ }
43049
+ output(ent);
43050
+ output(EOFCode);
43051
+ outStream.writeByte(0);
43052
+ return outStream.bytesView();
43053
+ function output(code) {
43054
+ cur_accum &= MASKS[cur_bits];
43055
+ if (cur_bits > 0)
43056
+ cur_accum |= code << cur_bits;
43057
+ else
43058
+ cur_accum = code;
43059
+ cur_bits += n_bits;
43060
+ while (cur_bits >= 8) {
43061
+ accum[a_count++] = cur_accum & 255;
43062
+ if (a_count >= 254) {
43063
+ outStream.writeByte(a_count);
43064
+ outStream.writeBytesView(accum, 0, a_count);
43065
+ a_count = 0;
43066
+ }
43067
+ cur_accum >>= 8;
43068
+ cur_bits -= 8;
43069
+ }
43070
+ if (free_ent > maxcode || clear_flg) {
43071
+ if (clear_flg) {
43072
+ n_bits = g_init_bits;
43073
+ maxcode = (1 << n_bits) - 1;
43074
+ clear_flg = false;
43075
+ } else {
43076
+ ++n_bits;
43077
+ maxcode = n_bits === BITS ? 1 << n_bits : (1 << n_bits) - 1;
43078
+ }
43079
+ }
43080
+ if (code == EOFCode) {
43081
+ while (cur_bits > 0) {
43082
+ accum[a_count++] = cur_accum & 255;
43083
+ if (a_count >= 254) {
43084
+ outStream.writeByte(a_count);
43085
+ outStream.writeBytesView(accum, 0, a_count);
43086
+ a_count = 0;
43087
+ }
43088
+ cur_accum >>= 8;
43089
+ cur_bits -= 8;
43090
+ }
43091
+ if (a_count > 0) {
43092
+ outStream.writeByte(a_count);
43093
+ outStream.writeBytesView(accum, 0, a_count);
43094
+ a_count = 0;
43095
+ }
43096
+ }
43097
+ }
43098
+ }
43099
+ var lzwEncode_default = lzwEncode;
43100
+ function rgb888_to_rgb565(r5, g4, b4) {
43101
+ return r5 << 8 & 63488 | g4 << 2 & 992 | b4 >> 3;
43102
+ }
43103
+ function rgba8888_to_rgba4444(r5, g4, b4, a5) {
43104
+ return r5 >> 4 | g4 & 240 | (b4 & 240) << 4 | (a5 & 240) << 8;
43105
+ }
43106
+ function rgb888_to_rgb444(r5, g4, b4) {
43107
+ return r5 >> 4 << 8 | g4 & 240 | b4 >> 4;
43108
+ }
43109
+ function clamp3(value, min, max) {
43110
+ return value < min ? min : value > max ? max : value;
43111
+ }
43112
+ function sqr(value) {
43113
+ return value * value;
43114
+ }
43115
+ function find_nn(bins, idx, hasAlpha) {
43116
+ var nn = 0;
43117
+ var err = 1e100;
43118
+ const bin1 = bins[idx];
43119
+ const n1 = bin1.cnt;
43120
+ const wa = bin1.ac;
43121
+ const wr = bin1.rc;
43122
+ const wg = bin1.gc;
43123
+ const wb = bin1.bc;
43124
+ for (var i6 = bin1.fw; i6 != 0; i6 = bins[i6].fw) {
43125
+ const bin = bins[i6];
43126
+ const n22 = bin.cnt;
43127
+ const nerr2 = n1 * n22 / (n1 + n22);
43128
+ if (nerr2 >= err)
43129
+ continue;
43130
+ var nerr = 0;
43131
+ if (hasAlpha) {
43132
+ nerr += nerr2 * sqr(bin.ac - wa);
43133
+ if (nerr >= err)
43134
+ continue;
43135
+ }
43136
+ nerr += nerr2 * sqr(bin.rc - wr);
43137
+ if (nerr >= err)
43138
+ continue;
43139
+ nerr += nerr2 * sqr(bin.gc - wg);
43140
+ if (nerr >= err)
43141
+ continue;
43142
+ nerr += nerr2 * sqr(bin.bc - wb);
43143
+ if (nerr >= err)
43144
+ continue;
43145
+ err = nerr;
43146
+ nn = i6;
43147
+ }
43148
+ bin1.err = err;
43149
+ bin1.nn = nn;
43150
+ }
43151
+ function create_bin() {
43152
+ return {
43153
+ ac: 0,
43154
+ rc: 0,
43155
+ gc: 0,
43156
+ bc: 0,
43157
+ cnt: 0,
43158
+ nn: 0,
43159
+ fw: 0,
43160
+ bk: 0,
43161
+ tm: 0,
43162
+ mtm: 0,
43163
+ err: 0
43164
+ };
43165
+ }
43166
+ function create_bin_list(data, format) {
43167
+ const bincount = format === "rgb444" ? 4096 : 65536;
43168
+ const bins = new Array(bincount);
43169
+ const size = data.length;
43170
+ if (format === "rgba4444") {
43171
+ for (let i6 = 0; i6 < size; ++i6) {
43172
+ const color = data[i6];
43173
+ const a5 = color >> 24 & 255;
43174
+ const b4 = color >> 16 & 255;
43175
+ const g4 = color >> 8 & 255;
43176
+ const r5 = color & 255;
43177
+ const index = rgba8888_to_rgba4444(r5, g4, b4, a5);
43178
+ let bin = index in bins ? bins[index] : bins[index] = create_bin();
43179
+ bin.rc += r5;
43180
+ bin.gc += g4;
43181
+ bin.bc += b4;
43182
+ bin.ac += a5;
43183
+ bin.cnt++;
43184
+ }
43185
+ } else if (format === "rgb444") {
43186
+ for (let i6 = 0; i6 < size; ++i6) {
43187
+ const color = data[i6];
43188
+ const b4 = color >> 16 & 255;
43189
+ const g4 = color >> 8 & 255;
43190
+ const r5 = color & 255;
43191
+ const index = rgb888_to_rgb444(r5, g4, b4);
43192
+ let bin = index in bins ? bins[index] : bins[index] = create_bin();
43193
+ bin.rc += r5;
43194
+ bin.gc += g4;
43195
+ bin.bc += b4;
43196
+ bin.cnt++;
43197
+ }
43198
+ } else {
43199
+ for (let i6 = 0; i6 < size; ++i6) {
43200
+ const color = data[i6];
43201
+ const b4 = color >> 16 & 255;
43202
+ const g4 = color >> 8 & 255;
43203
+ const r5 = color & 255;
43204
+ const index = rgb888_to_rgb565(r5, g4, b4);
43205
+ let bin = index in bins ? bins[index] : bins[index] = create_bin();
43206
+ bin.rc += r5;
43207
+ bin.gc += g4;
43208
+ bin.bc += b4;
43209
+ bin.cnt++;
43210
+ }
43211
+ }
43212
+ return bins;
43213
+ }
43214
+ function quantize2(rgba, maxColors, opts = {}) {
43215
+ const {
43216
+ format = "rgb565",
43217
+ clearAlpha = true,
43218
+ clearAlphaColor = 0,
43219
+ clearAlphaThreshold = 0,
43220
+ oneBitAlpha = false
43221
+ } = opts;
43222
+ if (!rgba || !rgba.buffer) {
43223
+ throw new Error("quantize() expected RGBA Uint8Array data");
43224
+ }
43225
+ if (!(rgba instanceof Uint8Array) && !(rgba instanceof Uint8ClampedArray)) {
43226
+ throw new Error("quantize() expected RGBA Uint8Array data");
43227
+ }
43228
+ const data = new Uint32Array(rgba.buffer);
43229
+ let useSqrt = opts.useSqrt !== false;
43230
+ const hasAlpha = format === "rgba4444";
43231
+ const bins = create_bin_list(data, format);
43232
+ const bincount = bins.length;
43233
+ const bincountMinusOne = bincount - 1;
43234
+ const heap = new Uint32Array(bincount + 1);
43235
+ var maxbins = 0;
43236
+ for (var i6 = 0; i6 < bincount; ++i6) {
43237
+ const bin = bins[i6];
43238
+ if (bin != null) {
43239
+ var d5 = 1 / bin.cnt;
43240
+ if (hasAlpha)
43241
+ bin.ac *= d5;
43242
+ bin.rc *= d5;
43243
+ bin.gc *= d5;
43244
+ bin.bc *= d5;
43245
+ bins[maxbins++] = bin;
43246
+ }
43247
+ }
43248
+ if (sqr(maxColors) / maxbins < 0.022) {
43249
+ useSqrt = false;
43250
+ }
43251
+ var i6 = 0;
43252
+ for (; i6 < maxbins - 1; ++i6) {
43253
+ bins[i6].fw = i6 + 1;
43254
+ bins[i6 + 1].bk = i6;
43255
+ if (useSqrt)
43256
+ bins[i6].cnt = Math.sqrt(bins[i6].cnt);
43257
+ }
43258
+ if (useSqrt)
43259
+ bins[i6].cnt = Math.sqrt(bins[i6].cnt);
43260
+ var h6, l6, l22;
43261
+ for (i6 = 0; i6 < maxbins; ++i6) {
43262
+ find_nn(bins, i6, false);
43263
+ var err = bins[i6].err;
43264
+ for (l6 = ++heap[0]; l6 > 1; l6 = l22) {
43265
+ l22 = l6 >> 1;
43266
+ if (bins[h6 = heap[l22]].err <= err)
43267
+ break;
43268
+ heap[l6] = h6;
43269
+ }
43270
+ heap[l6] = i6;
43271
+ }
43272
+ var extbins = maxbins - maxColors;
43273
+ for (i6 = 0; i6 < extbins; ) {
43274
+ var tb;
43275
+ for (; ; ) {
43276
+ var b1 = heap[1];
43277
+ tb = bins[b1];
43278
+ if (tb.tm >= tb.mtm && bins[tb.nn].mtm <= tb.tm)
43279
+ break;
43280
+ if (tb.mtm == bincountMinusOne)
43281
+ b1 = heap[1] = heap[heap[0]--];
43282
+ else {
43283
+ find_nn(bins, b1, false);
43284
+ tb.tm = i6;
43285
+ }
43286
+ var err = bins[b1].err;
43287
+ for (l6 = 1; (l22 = l6 + l6) <= heap[0]; l6 = l22) {
43288
+ if (l22 < heap[0] && bins[heap[l22]].err > bins[heap[l22 + 1]].err)
43289
+ l22++;
43290
+ if (err <= bins[h6 = heap[l22]].err)
43291
+ break;
43292
+ heap[l6] = h6;
43293
+ }
43294
+ heap[l6] = b1;
43295
+ }
43296
+ var nb = bins[tb.nn];
43297
+ var n1 = tb.cnt;
43298
+ var n22 = nb.cnt;
43299
+ var d5 = 1 / (n1 + n22);
43300
+ if (hasAlpha)
43301
+ tb.ac = d5 * (n1 * tb.ac + n22 * nb.ac);
43302
+ tb.rc = d5 * (n1 * tb.rc + n22 * nb.rc);
43303
+ tb.gc = d5 * (n1 * tb.gc + n22 * nb.gc);
43304
+ tb.bc = d5 * (n1 * tb.bc + n22 * nb.bc);
43305
+ tb.cnt += nb.cnt;
43306
+ tb.mtm = ++i6;
43307
+ bins[nb.bk].fw = nb.fw;
43308
+ bins[nb.fw].bk = nb.bk;
43309
+ nb.mtm = bincountMinusOne;
43310
+ }
43311
+ let palette = [];
43312
+ var k4 = 0;
43313
+ for (i6 = 0; ; ++k4) {
43314
+ let r5 = clamp3(Math.round(bins[i6].rc), 0, 255);
43315
+ let g4 = clamp3(Math.round(bins[i6].gc), 0, 255);
43316
+ let b4 = clamp3(Math.round(bins[i6].bc), 0, 255);
43317
+ let a5 = 255;
43318
+ if (hasAlpha) {
43319
+ a5 = clamp3(Math.round(bins[i6].ac), 0, 255);
43320
+ if (oneBitAlpha) {
43321
+ const threshold = typeof oneBitAlpha === "number" ? oneBitAlpha : 127;
43322
+ a5 = a5 <= threshold ? 0 : 255;
43323
+ }
43324
+ if (clearAlpha && a5 <= clearAlphaThreshold) {
43325
+ r5 = g4 = b4 = clearAlphaColor;
43326
+ a5 = 0;
43327
+ }
43328
+ }
43329
+ const color = hasAlpha ? [r5, g4, b4, a5] : [r5, g4, b4];
43330
+ const exists = existsInPalette(palette, color);
43331
+ if (!exists)
43332
+ palette.push(color);
43333
+ if ((i6 = bins[i6].fw) == 0)
43334
+ break;
43335
+ }
43336
+ return palette;
43337
+ }
43338
+ function existsInPalette(palette, color) {
43339
+ for (let i6 = 0; i6 < palette.length; i6++) {
43340
+ const p6 = palette[i6];
43341
+ let matchesRGB = p6[0] === color[0] && p6[1] === color[1] && p6[2] === color[2];
43342
+ let matchesAlpha = p6.length >= 4 && color.length >= 4 ? p6[3] === color[3] : true;
43343
+ if (matchesRGB && matchesAlpha)
43344
+ return true;
43345
+ }
43346
+ return false;
43347
+ }
43348
+ function euclideanDistanceSquared(a5, b4) {
43349
+ var sum = 0;
43350
+ var n4;
43351
+ for (n4 = 0; n4 < a5.length; n4++) {
43352
+ const dx = a5[n4] - b4[n4];
43353
+ sum += dx * dx;
43354
+ }
43355
+ return sum;
43356
+ }
43357
+ function roundStep(byte, step) {
43358
+ return step > 1 ? Math.round(byte / step) * step : byte;
43359
+ }
43360
+ function prequantize(rgba, { roundRGB = 5, roundAlpha = 10, oneBitAlpha = null } = {}) {
43361
+ const data = new Uint32Array(rgba.buffer);
43362
+ for (let i6 = 0; i6 < data.length; i6++) {
43363
+ const color = data[i6];
43364
+ let a5 = color >> 24 & 255;
43365
+ let b4 = color >> 16 & 255;
43366
+ let g4 = color >> 8 & 255;
43367
+ let r5 = color & 255;
43368
+ a5 = roundStep(a5, roundAlpha);
43369
+ if (oneBitAlpha) {
43370
+ const threshold = typeof oneBitAlpha === "number" ? oneBitAlpha : 127;
43371
+ a5 = a5 <= threshold ? 0 : 255;
43372
+ }
43373
+ r5 = roundStep(r5, roundRGB);
43374
+ g4 = roundStep(g4, roundRGB);
43375
+ b4 = roundStep(b4, roundRGB);
43376
+ data[i6] = a5 << 24 | b4 << 16 | g4 << 8 | r5 << 0;
43377
+ }
43378
+ }
43379
+ function applyPalette2(rgba, palette, format = "rgb565") {
43380
+ if (!rgba || !rgba.buffer) {
43381
+ throw new Error("quantize() expected RGBA Uint8Array data");
43382
+ }
43383
+ if (!(rgba instanceof Uint8Array) && !(rgba instanceof Uint8ClampedArray)) {
43384
+ throw new Error("quantize() expected RGBA Uint8Array data");
43385
+ }
43386
+ if (palette.length > 256) {
43387
+ throw new Error("applyPalette() only works with 256 colors or less");
43388
+ }
43389
+ const data = new Uint32Array(rgba.buffer);
43390
+ const length2 = data.length;
43391
+ const bincount = format === "rgb444" ? 4096 : 65536;
43392
+ const index = new Uint8Array(length2);
43393
+ const cache = new Array(bincount);
43394
+ const hasAlpha = format === "rgba4444";
43395
+ if (format === "rgba4444") {
43396
+ for (let i6 = 0; i6 < length2; i6++) {
43397
+ const color = data[i6];
43398
+ const a5 = color >> 24 & 255;
43399
+ const b4 = color >> 16 & 255;
43400
+ const g4 = color >> 8 & 255;
43401
+ const r5 = color & 255;
43402
+ const key = rgba8888_to_rgba4444(r5, g4, b4, a5);
43403
+ const idx = key in cache ? cache[key] : cache[key] = nearestColorIndexRGBA(r5, g4, b4, a5, palette);
43404
+ index[i6] = idx;
43405
+ }
43406
+ } else {
43407
+ const rgb888_to_key = format === "rgb444" ? rgb888_to_rgb444 : rgb888_to_rgb565;
43408
+ for (let i6 = 0; i6 < length2; i6++) {
43409
+ const color = data[i6];
43410
+ const b4 = color >> 16 & 255;
43411
+ const g4 = color >> 8 & 255;
43412
+ const r5 = color & 255;
43413
+ const key = rgb888_to_key(r5, g4, b4);
43414
+ const idx = key in cache ? cache[key] : cache[key] = nearestColorIndexRGB(r5, g4, b4, palette);
43415
+ index[i6] = idx;
43416
+ }
43417
+ }
43418
+ return index;
43419
+ }
43420
+ function nearestColorIndexRGBA(r5, g4, b4, a5, palette) {
43421
+ let k4 = 0;
43422
+ let mindist = 1e100;
43423
+ for (let i6 = 0; i6 < palette.length; i6++) {
43424
+ const px2 = palette[i6];
43425
+ const a22 = px2[3];
43426
+ let curdist = sqr2(a22 - a5);
43427
+ if (curdist > mindist)
43428
+ continue;
43429
+ const r22 = px2[0];
43430
+ curdist += sqr2(r22 - r5);
43431
+ if (curdist > mindist)
43432
+ continue;
43433
+ const g22 = px2[1];
43434
+ curdist += sqr2(g22 - g4);
43435
+ if (curdist > mindist)
43436
+ continue;
43437
+ const b22 = px2[2];
43438
+ curdist += sqr2(b22 - b4);
43439
+ if (curdist > mindist)
43440
+ continue;
43441
+ mindist = curdist;
43442
+ k4 = i6;
43443
+ }
43444
+ return k4;
43445
+ }
43446
+ function nearestColorIndexRGB(r5, g4, b4, palette) {
43447
+ let k4 = 0;
43448
+ let mindist = 1e100;
43449
+ for (let i6 = 0; i6 < palette.length; i6++) {
43450
+ const px2 = palette[i6];
43451
+ const r22 = px2[0];
43452
+ let curdist = sqr2(r22 - r5);
43453
+ if (curdist > mindist)
43454
+ continue;
43455
+ const g22 = px2[1];
43456
+ curdist += sqr2(g22 - g4);
43457
+ if (curdist > mindist)
43458
+ continue;
43459
+ const b22 = px2[2];
43460
+ curdist += sqr2(b22 - b4);
43461
+ if (curdist > mindist)
43462
+ continue;
43463
+ mindist = curdist;
43464
+ k4 = i6;
43465
+ }
43466
+ return k4;
43467
+ }
43468
+ function snapColorsToPalette(palette, knownColors, threshold = 5) {
43469
+ if (!palette.length || !knownColors.length)
43470
+ return;
43471
+ const paletteRGB = palette.map((p6) => p6.slice(0, 3));
43472
+ const thresholdSq = threshold * threshold;
43473
+ const dim2 = palette[0].length;
43474
+ for (let i6 = 0; i6 < knownColors.length; i6++) {
43475
+ let color = knownColors[i6];
43476
+ if (color.length < dim2) {
43477
+ color = [color[0], color[1], color[2], 255];
43478
+ } else if (color.length > dim2) {
43479
+ color = color.slice(0, 3);
43480
+ } else {
43481
+ color = color.slice();
43482
+ }
43483
+ const r5 = nearestColorIndexWithDistance(paletteRGB, color.slice(0, 3), euclideanDistanceSquared);
43484
+ const idx = r5[0];
43485
+ const distanceSq = r5[1];
43486
+ if (distanceSq > 0 && distanceSq <= thresholdSq) {
43487
+ palette[idx] = color;
43488
+ }
43489
+ }
43490
+ }
43491
+ function sqr2(a5) {
43492
+ return a5 * a5;
43493
+ }
43494
+ function nearestColorIndex(colors, pixel, distanceFn = euclideanDistanceSquared) {
43495
+ let minDist = Infinity;
43496
+ let minDistIndex = -1;
43497
+ for (let j5 = 0; j5 < colors.length; j5++) {
43498
+ const paletteColor = colors[j5];
43499
+ const dist = distanceFn(pixel, paletteColor);
43500
+ if (dist < minDist) {
43501
+ minDist = dist;
43502
+ minDistIndex = j5;
43503
+ }
43504
+ }
43505
+ return minDistIndex;
43506
+ }
43507
+ function nearestColorIndexWithDistance(colors, pixel, distanceFn = euclideanDistanceSquared) {
43508
+ let minDist = Infinity;
43509
+ let minDistIndex = -1;
43510
+ for (let j5 = 0; j5 < colors.length; j5++) {
43511
+ const paletteColor = colors[j5];
43512
+ const dist = distanceFn(pixel, paletteColor);
43513
+ if (dist < minDist) {
43514
+ minDist = dist;
43515
+ minDistIndex = j5;
43516
+ }
43517
+ }
43518
+ return [minDistIndex, minDist];
43519
+ }
43520
+ function nearestColor(colors, pixel, distanceFn = euclideanDistanceSquared) {
43521
+ return colors[nearestColorIndex(colors, pixel, distanceFn)];
43522
+ }
43523
+ function GIFEncoder2(opt = {}) {
43524
+ const { initialCapacity = 4096, auto = true } = opt;
43525
+ const stream = createStream(initialCapacity);
43526
+ const HSIZE = 5003;
43527
+ const accum = new Uint8Array(256);
43528
+ const htab = new Int32Array(HSIZE);
43529
+ const codetab = new Int32Array(HSIZE);
43530
+ let hasInit = false;
43531
+ return {
43532
+ reset() {
43533
+ stream.reset();
43534
+ hasInit = false;
43535
+ },
43536
+ finish() {
43537
+ stream.writeByte(constants_default.trailer);
43538
+ },
43539
+ bytes() {
43540
+ return stream.bytes();
43541
+ },
43542
+ bytesView() {
43543
+ return stream.bytesView();
43544
+ },
43545
+ get buffer() {
43546
+ return stream.buffer;
43547
+ },
43548
+ get stream() {
43549
+ return stream;
43550
+ },
43551
+ writeHeader,
43552
+ writeFrame(index, width, height, opts = {}) {
43553
+ const {
43554
+ transparent = false,
43555
+ transparentIndex = 0,
43556
+ delay = 0,
43557
+ palette = null,
43558
+ repeat = 0,
43559
+ colorDepth = 8,
43560
+ dispose = -1
43561
+ } = opts;
43562
+ let first = false;
43563
+ if (auto) {
43564
+ if (!hasInit) {
43565
+ first = true;
43566
+ writeHeader();
43567
+ hasInit = true;
43568
+ }
43569
+ } else {
43570
+ first = Boolean(opts.first);
43571
+ }
43572
+ width = Math.max(0, Math.floor(width));
43573
+ height = Math.max(0, Math.floor(height));
43574
+ if (first) {
43575
+ if (!palette) {
43576
+ throw new Error("First frame must include a { palette } option");
43577
+ }
43578
+ encodeLogicalScreenDescriptor(stream, width, height, palette, colorDepth);
43579
+ encodeColorTable(stream, palette);
43580
+ if (repeat >= 0) {
43581
+ encodeNetscapeExt(stream, repeat);
43582
+ }
43583
+ }
43584
+ const delayTime = Math.round(delay / 10);
43585
+ encodeGraphicControlExt(stream, dispose, delayTime, transparent, transparentIndex);
43586
+ const useLocalColorTable = Boolean(palette) && !first;
43587
+ encodeImageDescriptor(stream, width, height, useLocalColorTable ? palette : null);
43588
+ if (useLocalColorTable)
43589
+ encodeColorTable(stream, palette);
43590
+ encodePixels(stream, index, width, height, colorDepth, accum, htab, codetab);
43591
+ }
43592
+ };
43593
+ function writeHeader() {
43594
+ writeUTFBytes(stream, "GIF89a");
43595
+ }
43596
+ }
43597
+ function encodeGraphicControlExt(stream, dispose, delay, transparent, transparentIndex) {
43598
+ stream.writeByte(33);
43599
+ stream.writeByte(249);
43600
+ stream.writeByte(4);
43601
+ if (transparentIndex < 0) {
43602
+ transparentIndex = 0;
43603
+ transparent = false;
43604
+ }
43605
+ var transp, disp;
43606
+ if (!transparent) {
43607
+ transp = 0;
43608
+ disp = 0;
43609
+ } else {
43610
+ transp = 1;
43611
+ disp = 2;
43612
+ }
43613
+ if (dispose >= 0) {
43614
+ disp = dispose & 7;
43615
+ }
43616
+ disp <<= 2;
43617
+ const userInput = 0;
43618
+ stream.writeByte(0 | disp | userInput | transp);
43619
+ writeUInt16(stream, delay);
43620
+ stream.writeByte(transparentIndex || 0);
43621
+ stream.writeByte(0);
43622
+ }
43623
+ function encodeLogicalScreenDescriptor(stream, width, height, palette, colorDepth = 8) {
43624
+ const globalColorTableFlag = 1;
43625
+ const sortFlag = 0;
43626
+ const globalColorTableSize = colorTableSize(palette.length) - 1;
43627
+ const fields = globalColorTableFlag << 7 | colorDepth - 1 << 4 | sortFlag << 3 | globalColorTableSize;
43628
+ const backgroundColorIndex = 0;
43629
+ const pixelAspectRatio = 0;
43630
+ writeUInt16(stream, width);
43631
+ writeUInt16(stream, height);
43632
+ stream.writeBytes([fields, backgroundColorIndex, pixelAspectRatio]);
43633
+ }
43634
+ function encodeNetscapeExt(stream, repeat) {
43635
+ stream.writeByte(33);
43636
+ stream.writeByte(255);
43637
+ stream.writeByte(11);
43638
+ writeUTFBytes(stream, "NETSCAPE2.0");
43639
+ stream.writeByte(3);
43640
+ stream.writeByte(1);
43641
+ writeUInt16(stream, repeat);
43642
+ stream.writeByte(0);
43643
+ }
43644
+ function encodeColorTable(stream, palette) {
43645
+ const colorTableLength = 1 << colorTableSize(palette.length);
43646
+ for (let i6 = 0; i6 < colorTableLength; i6++) {
43647
+ let color = [0, 0, 0];
43648
+ if (i6 < palette.length) {
43649
+ color = palette[i6];
43650
+ }
43651
+ stream.writeByte(color[0]);
43652
+ stream.writeByte(color[1]);
43653
+ stream.writeByte(color[2]);
43654
+ }
43655
+ }
43656
+ function encodeImageDescriptor(stream, width, height, localPalette) {
43657
+ stream.writeByte(44);
43658
+ writeUInt16(stream, 0);
43659
+ writeUInt16(stream, 0);
43660
+ writeUInt16(stream, width);
43661
+ writeUInt16(stream, height);
43662
+ if (localPalette) {
43663
+ const interlace = 0;
43664
+ const sorted = 0;
43665
+ const palSize = colorTableSize(localPalette.length) - 1;
43666
+ stream.writeByte(128 | interlace | sorted | 0 | palSize);
43667
+ } else {
43668
+ stream.writeByte(0);
43669
+ }
43670
+ }
43671
+ function encodePixels(stream, index, width, height, colorDepth = 8, accum, htab, codetab) {
43672
+ lzwEncode_default(width, height, index, colorDepth, stream, accum, htab, codetab);
43673
+ }
43674
+ function writeUInt16(stream, short) {
43675
+ stream.writeByte(short & 255);
43676
+ stream.writeByte(short >> 8 & 255);
43677
+ }
43678
+ function writeUTFBytes(stream, text) {
43679
+ for (var i6 = 0; i6 < text.length; i6++) {
43680
+ stream.writeByte(text.charCodeAt(i6));
43681
+ }
43682
+ }
43683
+ function colorTableSize(length2) {
43684
+ return Math.max(Math.ceil(Math.log2(length2)), 1);
43685
+ }
43686
+ var src_default = GIFEncoder2;
43687
+ }
43688
+ });
43689
+
42878
43690
  // node_modules/preact/dist/preact.module.js
42879
43691
  var n;
42880
43692
  var l;
@@ -50199,6 +51011,7 @@ __export(store_exports, {
50199
51011
  setRect: () => setRect,
50200
51012
  setStatus: () => setStatus,
50201
51013
  setWeightsMode: () => setWeightsMode,
51014
+ showBones: () => showBones,
50202
51015
  shown: () => shown,
50203
51016
  skeleton: () => skeleton,
50204
51017
  snap: () => snap,
@@ -50691,6 +51504,8 @@ var store = (key, v6) => {
50691
51504
  };
50692
51505
  var lockImages = y2(stored("rig-editor.lockImages") === "1");
50693
51506
  j3(() => store("rig-editor.lockImages", lockImages.value ? "1" : "0"));
51507
+ var showBones = y2(stored("rig-editor.showBones") !== "0");
51508
+ j3(() => store("rig-editor.showBones", showBones.value ? "1" : "0"));
50694
51509
  var sections = y2((() => {
50695
51510
  try {
50696
51511
  return JSON.parse(stored("rig-editor.sections") ?? "{}");
@@ -56529,6 +57344,9 @@ init_Sprite();
56529
57344
  init_eventemitter3();
56530
57345
  extensions.add(browserExt, webworkerExt);
56531
57346
 
57347
+ // src/editor/stage.ts
57348
+ var import_gifenc = __toESM(require_gifenc(), 1);
57349
+
56532
57350
  // src/rig-state.ts
56533
57351
  var AnimationState = class {
56534
57352
  constructor(sink, opts = {}) {
@@ -57211,6 +58029,7 @@ var Stage = class {
57211
58029
  }));
57212
58030
  this.dispose.push(j3(() => {
57213
58031
  boneTool.value;
58032
+ showBones.value;
57214
58033
  f3(() => this.drawOverlay());
57215
58034
  }));
57216
58035
  this.dispose.push(j3(() => {
@@ -57374,6 +58193,53 @@ var Stage = class {
57374
58193
  time.value = this.t;
57375
58194
  this.drawOverlay();
57376
58195
  }
58196
+ // ---------- GIF export ----------
58197
+ /** one export at a time: two runs would interleave their seeks into the same player and produce a mixed file */
58198
+ exporting = false;
58199
+ /**
58200
+ * The current animation as GIF bytes — the top bar hands them to a download link, and the tests read them.
58201
+ *
58202
+ * Each frame is the DOCUMENT rectangle rendered on its own: `extract` REPLACES the target's transform with the
58203
+ * frame's, so the file ignores the camera's zoom and pan and comes out at `meta.width` × `meta.height` whatever
58204
+ * is on screen. The overlay (bones, labels, gizmos) is switched off for the duration, so nothing of the editor
58205
+ * ends up in it; the paper stays, which is what makes every pixel opaque — GIF has no partial transparency.
58206
+ */
58207
+ async exportGif(fps = FPS) {
58208
+ const d5 = shown.peek(), anim = currentAnim.peek(), p6 = this.player;
58209
+ if (!p6 || !d5 || !anim || mode.peek() !== "animate") {
58210
+ setStatus("gif: pick an animation in animate mode", "warn");
58211
+ return;
58212
+ }
58213
+ if (this.exporting) return;
58214
+ this.exporting = true;
58215
+ const wasPlaying = playing.peek();
58216
+ playing.value = false;
58217
+ this.overlay.visible = false;
58218
+ try {
58219
+ const w5 = d5.meta.width, h6 = d5.meta.height, n4 = Math.max(1, Math.round(anim.duration * fps));
58220
+ const frame = new Rectangle(0, 0, w5, h6), gif = (0, import_gifenc.GIFEncoder)();
58221
+ for (let i6 = 0; i6 < n4; i6++) {
58222
+ if (this.destroyed) return;
58223
+ void p6.play(anim.id, { loop: false });
58224
+ p6.tick(i6 / fps);
58225
+ const { pixels } = this.app.renderer.extract.pixels({ target: this.camera, frame });
58226
+ const palette = (0, import_gifenc.quantize)(pixels, 256);
58227
+ gif.writeFrame((0, import_gifenc.applyPalette)(pixels, palette), w5, h6, { palette, delay: 1e3 / fps });
58228
+ setStatus(`gif: frame ${i6 + 1}/${n4}`);
58229
+ await new Promise((r5) => setTimeout(r5));
58230
+ }
58231
+ gif.finish();
58232
+ setStatus(`gif: ${anim.id}, ${n4} frames at ${fps} fps`);
58233
+ return gif.bytes();
58234
+ } finally {
58235
+ this.exporting = false;
58236
+ if (!this.destroyed) {
58237
+ this.overlay.visible = true;
58238
+ playing.value = wasPlaying;
58239
+ this.applyPose();
58240
+ }
58241
+ }
58242
+ }
57377
58243
  // ---------- camera ----------
57378
58244
  /** doc px → screen px (canvas client coords); the camera never rotates, so this is exact without a render */
57379
58245
  toScreen(x4, y4) {
@@ -57953,7 +58819,7 @@ var Stage = class {
57953
58819
  this.paper.rect(0, 0, d5.meta.width, d5.meta.height).fill({ color: CANVAS_BG });
57954
58820
  this.gfx.rect(0, 0, d5.meta.width, d5.meta.height).stroke({ color: CANVAS_LINE, width: 1 / z3 });
57955
58821
  const skel = this.skeleton;
57956
- for (const b4 of d5.bones) {
58822
+ if (showBones.value) for (const b4 of d5.bones) {
57957
58823
  const w5 = skel.bones.get(b4.id)?.world;
57958
58824
  if (!w5) continue;
57959
58825
  const parent = b4.parent && skel.bones.get(b4.parent)?.world;
@@ -58670,6 +59536,16 @@ async function history(tool) {
58670
59536
  historyBusy = false;
58671
59537
  }
58672
59538
  }
59539
+ async function exportGif() {
59540
+ const bytes = await stage?.exportGif();
59541
+ if (!bytes) return;
59542
+ const url = URL.createObjectURL(new Blob([bytes], { type: "image/gif" }));
59543
+ const a5 = document.createElement("a");
59544
+ a5.href = url;
59545
+ a5.download = `${shown.peek()?.meta.name ?? "rig"}_${animId.peek() ?? "anim"}.gif`;
59546
+ a5.click();
59547
+ setTimeout(() => URL.revokeObjectURL(url), 1e4);
59548
+ }
58673
59549
  function setMode(m5) {
58674
59550
  if (m5 === "animate" && !shown.value?.animations.length) {
58675
59551
  setStatus("no animations \u2014 create one in the properties panel", "warn");
@@ -58887,7 +59763,25 @@ function TopBar() {
58887
59763
  /* @__PURE__ */ u4("input", { class: "loop", type: "checkbox", checked: loop.value, onChange: (e5) => loop.value = e5.target.checked }),
58888
59764
  "loop"
58889
59765
  ] }),
59766
+ /* @__PURE__ */ u4(
59767
+ "button",
59768
+ {
59769
+ class: "gif",
59770
+ title: "export the current animation as a GIF, at document size, without the overlay",
59771
+ onClick: click(() => void exportGif()),
59772
+ children: "gif"
59773
+ }
59774
+ ),
58890
59775
  /* @__PURE__ */ u4("button", { class: "fit", title: "fit the document to the viewport (F)", onClick: click(() => stage?.fit()), children: "fit" }),
59776
+ /* @__PURE__ */ u4(
59777
+ "button",
59778
+ {
59779
+ class: "bones" + (showBones.value ? " on" : ""),
59780
+ title: "show the bone overlay (H)",
59781
+ onClick: click(() => showBones.value = !showBones.value),
59782
+ children: "bones"
59783
+ }
59784
+ ),
58891
59785
  /* @__PURE__ */ u4(
58892
59786
  "button",
58893
59787
  {
@@ -59115,6 +60009,10 @@ function onKeyDown(e5) {
59115
60009
  setBoneTool(!boneTool.value);
59116
60010
  return;
59117
60011
  }
60012
+ if (e5.key === "h" || e5.key === "H") {
60013
+ showBones.value = !showBones.value;
60014
+ return;
60015
+ }
59118
60016
  if ((e5.key === "[" || e5.key === "]") && weightsMode.value) {
59119
60017
  const b4 = brush.value;
59120
60018
  const radius = Math.min(400, Math.max(4, b4.radius * (e5.key === "]" ? 1.25 : 0.8)));