@tsparticles/shape-image 3.0.3 → 3.1.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.
@@ -4,7 +4,7 @@
4
4
  * Demo / Generator : https://particles.js.org/
5
5
  * GitHub : https://www.github.com/matteobruni/tsparticles
6
6
  * How to use? : Check the GitHub README
7
- * v3.0.3
7
+ * v3.1.0
8
8
  */
9
9
  (function webpackUniversalModuleDefinition(root, factory) {
10
10
  if(typeof exports === 'object' && typeof module === 'object')
@@ -114,32 +114,39 @@ class ByteStream {
114
114
  return this.data[this.pos++];
115
115
  }
116
116
  nextTwoBytes() {
117
- this.pos += 2;
118
- return this.data[this.pos - 2] + (this.data[this.pos - 1] << 8);
117
+ const increment = 2,
118
+ previous = 1,
119
+ shift = 8;
120
+ this.pos += increment;
121
+ return this.data[this.pos - increment] + (this.data[this.pos - previous] << shift);
119
122
  }
120
123
  readSubBlocks() {
121
124
  let blockString = "",
122
125
  size = 0;
126
+ const minCount = 0,
127
+ emptySize = 0;
123
128
  do {
124
129
  size = this.data[this.pos++];
125
- for (let count = size; --count >= 0; blockString += String.fromCharCode(this.data[this.pos++])) {}
126
- } while (size !== 0);
130
+ for (let count = size; --count >= minCount; blockString += String.fromCharCode(this.data[this.pos++])) {}
131
+ } while (size !== emptySize);
127
132
  return blockString;
128
133
  }
129
134
  readSubBlocksBin() {
130
135
  let size = 0,
131
136
  len = 0;
132
- for (let offset = 0; (size = this.data[this.pos + offset]) !== 0; offset += size + 1) {
137
+ const emptySize = 0,
138
+ increment = 1;
139
+ for (let offset = 0; size !== emptySize; offset += size + increment, size = this.data[this.pos + offset]) {
133
140
  len += size;
134
141
  }
135
142
  const blockData = new Uint8Array(len);
136
- for (let i = 0; (size = this.data[this.pos++]) !== 0;) {
137
- for (let count = size; --count >= 0; blockData[i++] = this.data[this.pos++]) {}
143
+ for (let i = 0; size !== emptySize; size = this.data[this.pos++]) {
144
+ for (let count = size; --count >= emptySize; blockData[i++] = this.data[this.pos++]) {}
138
145
  }
139
146
  return blockData;
140
147
  }
141
148
  skipSubBlocks() {
142
- for (; this.data[this.pos] !== 0; this.pos += this.data[this.pos] + 1) {}
149
+ for (const increment = 1, noData = 0; this.data[this.pos] !== noData; this.pos += this.data[this.pos] + increment) {}
143
150
  this.pos++;
144
151
  }
145
152
  }
@@ -158,7 +165,7 @@ function parseColorTable(byteStream, count) {
158
165
  }
159
166
  return colors;
160
167
  }
161
- async function parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex) {
168
+ function parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex) {
162
169
  switch (byteStream.nextByte()) {
163
170
  case 249:
164
171
  {
@@ -240,11 +247,19 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
240
247
  g,
241
248
  b
242
249
  } = (localColorTableFlag ? frame.localColorTable : gif.globalColorTable)[index];
250
+ if (index !== getTransparencyIndex(null)) {
251
+ return {
252
+ r,
253
+ g,
254
+ b,
255
+ a: 255
256
+ };
257
+ }
243
258
  return {
244
259
  r,
245
260
  g,
246
261
  b,
247
- a: index === getTransparencyIndex(null) ? avgAlpha ? ~~((r + g + b) / 3) : 0 : 255
262
+ a: avgAlpha ? ~~((r + g + b) / 3) : 0
248
263
  };
249
264
  };
250
265
  const image = (() => {
@@ -273,7 +288,10 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
273
288
  if (interlacedFlag) {
274
289
  for (let code = 0, size = minCodeSize + 1, pos = 0, dic = [[0]], pass = 0; pass < 4; pass++) {
275
290
  if (InterlaceOffsets[pass] < frame.height) {
276
- for (let pixelPos = 0, lineIndex = 0;;) {
291
+ let pixelPos = 0,
292
+ lineIndex = 0,
293
+ exit = false;
294
+ while (!exit) {
277
295
  const last = code;
278
296
  code = readBits(pos, size);
279
297
  pos += size + 1;
@@ -289,13 +307,13 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
289
307
  } else if (last !== clearCode) {
290
308
  dic.push(dic[last].concat(dic[code][0]));
291
309
  }
292
- for (let i = 0; i < dic[code].length; i++) {
310
+ for (const item of dic[code]) {
293
311
  const {
294
312
  r,
295
313
  g,
296
314
  b,
297
315
  a
298
- } = getColor(dic[code][i]);
316
+ } = getColor(item);
299
317
  image.data.set([r, g, b, a], InterlaceOffsets[pass] * frame.width + InterlaceSteps[pass] * lineIndex + pixelPos % (frame.width * 4));
300
318
  pixelPos += 4;
301
319
  }
@@ -306,7 +324,7 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
306
324
  if (pixelPos === frame.width * 4 * (lineIndex + 1)) {
307
325
  lineIndex++;
308
326
  if (InterlaceOffsets[pass] + InterlaceSteps[pass] * lineIndex >= frame.height) {
309
- break;
327
+ exit = true;
310
328
  }
311
329
  }
312
330
  }
@@ -322,7 +340,13 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
322
340
  frame.image = image;
323
341
  frame.bitmap = await createImageBitmap(image);
324
342
  } else {
325
- for (let code = 0, size = minCodeSize + 1, pos = 0, dic = [[0]], pixelPos = -4;;) {
343
+ let code = 0,
344
+ size = minCodeSize + 1,
345
+ pos = 0,
346
+ pixelPos = -4,
347
+ exit = false;
348
+ const dic = [[0]];
349
+ while (!exit) {
326
350
  const last = code;
327
351
  code = readBits(pos, size);
328
352
  pos += size;
@@ -334,6 +358,7 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
334
358
  }
335
359
  } else {
336
360
  if (code === clearCode + 1) {
361
+ exit = true;
337
362
  break;
338
363
  }
339
364
  if (code >= dic.length) {
@@ -341,13 +366,13 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
341
366
  } else if (last !== clearCode) {
342
367
  dic.push(dic[last].concat(dic[code][0]));
343
368
  }
344
- for (let i = 0; i < dic[code].length; i++) {
369
+ for (const item of dic[code]) {
345
370
  const {
346
371
  r,
347
372
  g,
348
373
  b,
349
374
  a
350
- } = getColor(dic[code][i]);
375
+ } = getColor(item);
351
376
  image.data.set([r, g, b, a], pixelPos += 4);
352
377
  }
353
378
  if (dic.length >= 1 << size && size < 0xc) {
@@ -374,7 +399,7 @@ async function parseBlock(byteStream, gif, avgAlpha, getFrameIndex, getTranspare
374
399
  await parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, progressCallback);
375
400
  break;
376
401
  case 33:
377
- await parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex);
402
+ parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex);
378
403
  break;
379
404
  default:
380
405
  throw new EvalError("undefined block found");
@@ -515,6 +540,9 @@ async function decodeGIF(gifURL, progressCallback, avgAlpha) {
515
540
  ;// CONCATENATED MODULE: ./dist/browser/Utils.js
516
541
 
517
542
 
543
+ const stringStart = 0,
544
+ defaultLoopCount = 0,
545
+ defaultOpacity = 1;
518
546
  const currentColorRegex = /(#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d.]+%?\))|currentcolor/gi;
519
547
  function replaceColorSvg(imageShape, color, opacity) {
520
548
  const {
@@ -528,7 +556,7 @@ function replaceColorSvg(imageShape, color, opacity) {
528
556
  return svgData.replace(currentColorRegex, () => colorStyle);
529
557
  }
530
558
  const preFillIndex = svgData.indexOf(">");
531
- return `${svgData.substring(0, preFillIndex)} fill="${colorStyle}"${svgData.substring(preFillIndex)}`;
559
+ return `${svgData.substring(stringStart, preFillIndex)} fill="${colorStyle}"${svgData.substring(preFillIndex)}`;
532
560
  }
533
561
  async function loadImage(image) {
534
562
  return new Promise(resolve => {
@@ -557,8 +585,8 @@ async function loadGifImage(image) {
557
585
  image.loading = true;
558
586
  try {
559
587
  image.gifData = await decodeGIF(image.source);
560
- image.gifLoopCount = getGIFLoopAmount(image.gifData) ?? 0;
561
- if (image.gifLoopCount === 0) {
588
+ image.gifLoopCount = getGIFLoopAmount(image.gifData) ?? defaultLoopCount;
589
+ if (!image.gifLoopCount) {
562
590
  image.gifLoopCount = Infinity;
563
591
  }
564
592
  } catch {
@@ -582,7 +610,7 @@ async function downloadSvgImage(image) {
582
610
  image.loading = false;
583
611
  }
584
612
  function replaceImageColor(image, imageData, color, particle) {
585
- const svgColoredData = replaceColorSvg(image, color, particle.opacity?.value ?? 1),
613
+ const svgColoredData = replaceColorSvg(image, color, particle.opacity?.value ?? defaultOpacity),
586
614
  imageRes = {
587
615
  color,
588
616
  gif: imageData.gif,
@@ -608,7 +636,7 @@ function replaceImageColor(image, imageData, color, particle) {
608
636
  resolve(imageRes);
609
637
  domUrl.revokeObjectURL(url);
610
638
  });
611
- img.addEventListener("error", async () => {
639
+ const errorHandler = async () => {
612
640
  domUrl.revokeObjectURL(url);
613
641
  const img2 = {
614
642
  ...image,
@@ -619,13 +647,27 @@ function replaceImageColor(image, imageData, color, particle) {
619
647
  imageRes.loaded = true;
620
648
  imageRes.element = img2.element;
621
649
  resolve(imageRes);
622
- });
650
+ };
651
+ img.addEventListener("error", () => void errorHandler());
623
652
  img.src = url;
624
653
  });
625
654
  }
626
655
  ;// CONCATENATED MODULE: ./dist/browser/ImageDrawer.js
627
656
 
628
657
 
658
+ const origin = {
659
+ x: 0,
660
+ y: 0
661
+ },
662
+ ImageDrawer_defaultLoopCount = 0,
663
+ defaultFrame = 0,
664
+ half = 0.5,
665
+ initialTime = 0,
666
+ firstIndex = 0,
667
+ ImageDrawer_double = 2,
668
+ defaultAlpha = 1,
669
+ sides = 12,
670
+ defaultRatio = 1;
629
671
  class ImageDrawer {
630
672
  constructor(engine) {
631
673
  this.loadImageShape = async imageShape => {
@@ -669,18 +711,18 @@ class ImageDrawer {
669
711
  }
670
712
  offscreenContext.imageSmoothingQuality = "low";
671
713
  offscreenContext.imageSmoothingEnabled = false;
672
- offscreenContext.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
714
+ offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
673
715
  if (particle.gifLoopCount === undefined) {
674
- particle.gifLoopCount = image.gifLoopCount ?? 0;
716
+ particle.gifLoopCount = image.gifLoopCount ?? ImageDrawer_defaultLoopCount;
675
717
  }
676
- let frameIndex = particle.gifFrame ?? 0;
718
+ let frameIndex = particle.gifFrame ?? defaultFrame;
677
719
  const pos = {
678
- x: -image.gifData.width * 0.5,
679
- y: -image.gifData.height * 0.5
720
+ x: -image.gifData.width * half,
721
+ y: -image.gifData.height * half
680
722
  },
681
723
  frame = image.gifData.frames[frameIndex];
682
724
  if (particle.gifTime === undefined) {
683
- particle.gifTime = 0;
725
+ particle.gifTime = initialTime;
684
726
  }
685
727
  if (!frame.bitmap) {
686
728
  return;
@@ -694,7 +736,7 @@ class ImageDrawer {
694
736
  case 0:
695
737
  offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
696
738
  context.drawImage(offscreenCanvas, pos.x, pos.y);
697
- offscreenContext.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
739
+ offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
698
740
  break;
699
741
  case 1:
700
742
  offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
@@ -703,20 +745,20 @@ class ImageDrawer {
703
745
  case 2:
704
746
  offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
705
747
  context.drawImage(offscreenCanvas, pos.x, pos.y);
706
- offscreenContext.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
707
- if (image.gifData.globalColorTable.length === 0) {
708
- offscreenContext.putImageData(image.gifData.frames[0].image, pos.x + frame.left, pos.y + frame.top);
748
+ offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
749
+ if (!image.gifData.globalColorTable.length) {
750
+ offscreenContext.putImageData(image.gifData.frames[firstIndex].image, pos.x + frame.left, pos.y + frame.top);
709
751
  } else {
710
752
  offscreenContext.putImageData(image.gifData.backgroundImage, pos.x, pos.y);
711
753
  }
712
754
  break;
713
755
  case 3:
714
756
  {
715
- const previousImageData = offscreenContext.getImageData(0, 0, offscreenCanvas.width, offscreenCanvas.height);
757
+ const previousImageData = offscreenContext.getImageData(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
716
758
  offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
717
759
  context.drawImage(offscreenCanvas, pos.x, pos.y);
718
- offscreenContext.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
719
- offscreenContext.putImageData(previousImageData, 0, 0);
760
+ offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
761
+ offscreenContext.putImageData(previousImageData, origin.x, origin.y);
720
762
  }
721
763
  break;
722
764
  }
@@ -724,11 +766,11 @@ class ImageDrawer {
724
766
  if (particle.gifTime > frame.delayTime) {
725
767
  particle.gifTime -= frame.delayTime;
726
768
  if (++frameIndex >= image.gifData.frames.length) {
727
- if (--particle.gifLoopCount <= 0) {
769
+ if (--particle.gifLoopCount <= ImageDrawer_defaultLoopCount) {
728
770
  return;
729
771
  }
730
- frameIndex = 0;
731
- offscreenContext.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
772
+ frameIndex = firstIndex;
773
+ offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
732
774
  }
733
775
  particle.gifFrame = frameIndex;
734
776
  }
@@ -739,13 +781,13 @@ class ImageDrawer {
739
781
  x: -radius,
740
782
  y: -radius
741
783
  },
742
- diameter = radius * 2;
784
+ diameter = radius * ImageDrawer_double;
743
785
  context.drawImage(element, pos.x, pos.y, diameter, diameter / ratio);
744
786
  }
745
- context.globalAlpha = 1;
787
+ context.globalAlpha = defaultAlpha;
746
788
  }
747
789
  getSidesCount() {
748
- return 12;
790
+ return sides;
749
791
  }
750
792
  async init(container) {
751
793
  const options = container.actualOptions;
@@ -769,7 +811,7 @@ class ImageDrawer {
769
811
  }
770
812
  const image = this._engine.images.find(t => t.name === imageData.name || t.source === imageData.src);
771
813
  if (!image) {
772
- this.loadImageShape(imageData).then(() => {
814
+ void this.loadImageShape(imageData).then(() => {
773
815
  this.loadShape(particle);
774
816
  });
775
817
  }
@@ -798,7 +840,7 @@ class ImageDrawer {
798
840
  });
799
841
  return;
800
842
  }
801
- (async () => {
843
+ void (async () => {
802
844
  let imageRes;
803
845
  if (image.svgData && color) {
804
846
  imageRes = await replaceImageColor(image, imageData, color, particle);
@@ -811,7 +853,7 @@ class ImageDrawer {
811
853
  gifData: image.gifData,
812
854
  gifLoopCount: image.gifLoopCount,
813
855
  loaded: true,
814
- ratio: imageData.width && imageData.height ? imageData.width / imageData.height : image.ratio ?? 1,
856
+ ratio: imageData.width && imageData.height ? imageData.width / imageData.height : image.ratio ?? defaultRatio,
815
857
  replaceColor: replaceColor,
816
858
  source: imageData.src
817
859
  };
@@ -873,7 +915,7 @@ class ImagePreloaderPlugin {
873
915
  return {};
874
916
  }
875
917
  loadOptions(options, source) {
876
- if (!source || !source.preload) {
918
+ if (!source?.preload) {
877
919
  return;
878
920
  }
879
921
  if (!options.preload) {
@@ -900,6 +942,7 @@ class ImagePreloaderPlugin {
900
942
 
901
943
 
902
944
 
945
+ const extLength = 3;
903
946
  function addLoadImageToEngine(engine) {
904
947
  if (engine.loadImage) {
905
948
  return;
@@ -919,14 +962,19 @@ function addLoadImageToEngine(engine) {
919
962
  gif: data.gif ?? false,
920
963
  name: data.name ?? data.src,
921
964
  source: data.src,
922
- type: data.src.substring(data.src.length - 3),
965
+ type: data.src.substring(data.src.length - extLength),
923
966
  error: false,
924
967
  loading: true,
925
968
  replaceColor: data.replaceColor,
926
969
  ratio: data.width && data.height ? data.width / data.height : undefined
927
970
  };
928
971
  engine.images.push(image);
929
- const imageFunc = data.gif ? loadGifImage : data.replaceColor ? downloadSvgImage : loadImage;
972
+ let imageFunc;
973
+ if (data.gif) {
974
+ imageFunc = loadGifImage;
975
+ } else {
976
+ imageFunc = data.replaceColor ? downloadSvgImage : loadImage;
977
+ }
930
978
  await imageFunc(image);
931
979
  } catch {
932
980
  throw new Error(`${engine_root_window_.errorPrefix} ${data.name ?? data.src} not found`);
@@ -1,2 +1,2 @@
1
1
  /*! For license information please see tsparticles.shape.image.min.js.LICENSE.txt */
2
- !function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("@tsparticles/engine"));else if("function"==typeof define&&define.amd)define(["@tsparticles/engine"],t);else{var a="object"==typeof exports?t(require("@tsparticles/engine")):t(e.window);for(var o in a)("object"==typeof exports?exports:e)[o]=a[o]}}(this,(e=>(()=>{"use strict";var t={533:t=>{t.exports=e}},a={};function o(e){var i=a[e];if(void 0!==i)return i.exports;var r=a[e]={exports:{}};return t[e](r,r.exports,o),r.exports}o.d=(e,t)=>{for(var a in t)o.o(t,a)&&!o.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var i={};return(()=>{o.r(i),o.d(i,{loadImageShape:()=>u});var e=o(533);const t=[0,4,2,1],a=[8,8,4,2];class r{constructor(e){this.pos=0,this.data=new Uint8ClampedArray(e)}getString(e){const t=this.data.slice(this.pos,this.pos+e);return this.pos+=t.length,t.reduce(((e,t)=>e+String.fromCharCode(t)),"")}nextByte(){return this.data[this.pos++]}nextTwoBytes(){return this.pos+=2,this.data[this.pos-2]+(this.data[this.pos-1]<<8)}readSubBlocks(){let e="",t=0;do{t=this.data[this.pos++];for(let a=t;--a>=0;e+=String.fromCharCode(this.data[this.pos++]));}while(0!==t);return e}readSubBlocksBin(){let e=0,t=0;for(let a=0;0!==(e=this.data[this.pos+a]);a+=e+1)t+=e;const a=new Uint8Array(t);for(let t=0;0!==(e=this.data[this.pos++]);)for(let o=e;--o>=0;a[t++]=this.data[this.pos++]);return a}skipSubBlocks(){for(;0!==this.data[this.pos];this.pos+=this.data[this.pos]+1);this.pos++}}function n(e,t){const a=[];for(let o=0;o<t;o++)a.push({r:e.data[e.pos],g:e.data[e.pos+1],b:e.data[e.pos+2]}),e.pos+=3;return a}async function s(e,o,i,r,s,l){switch(e.nextByte()){case 59:return!0;case 44:await async function(e,o,i,r,s,l){const c=o.frames[r(!0)];c.left=e.nextTwoBytes(),c.top=e.nextTwoBytes(),c.width=e.nextTwoBytes(),c.height=e.nextTwoBytes();const g=e.nextByte(),h=128==(128&g),d=64==(64&g);c.sortFlag=32==(32&g),c.reserved=(24&g)>>>3;const f=1<<1+(7&g);h&&(c.localColorTable=n(e,f));const p=e=>{const{r:t,g:a,b:r}=(h?c.localColorTable:o.globalColorTable)[e];return{r:t,g:a,b:r,a:e===s(null)?i?~~((t+a+r)/3):0:255}},m=(()=>{try{return new ImageData(c.width,c.height,{colorSpace:"srgb"})}catch(e){if(e instanceof DOMException&&"IndexSizeError"===e.name)return null;throw e}})();if(null==m)throw new EvalError("GIF frame size is to large");const u=e.nextByte(),w=e.readSubBlocksBin(),y=1<<u,b=(e,t)=>{const a=e>>>3,o=7&e;return(w[a]+(w[a+1]<<8)+(w[a+2]<<16)&(1<<t)-1<<o)>>>o};if(d){for(let i=0,n=u+1,s=0,g=[[0]],h=0;h<4;h++){if(t[h]<c.height)for(let e=0,o=0;;){const r=i;if(i=b(s,n),s+=n+1,i===y){n=u+1,g.length=y+2;for(let e=0;e<g.length;e++)g[e]=e<y?[e]:[]}else{i>=g.length?g.push(g[r].concat(g[r][0])):r!==y&&g.push(g[r].concat(g[i][0]));for(let r=0;r<g[i].length;r++){const{r:n,g:s,b:l,a:d}=p(g[i][r]);m.data.set([n,s,l,d],t[h]*c.width+a[h]*o+e%(4*c.width)),e+=4}g.length===1<<n&&n<12&&n++}if(e===4*c.width*(o+1)&&(o++,t[h]+a[h]*o>=c.height))break}l?.(e.pos/(e.data.length-1),r(!1)+1,m,{x:c.left,y:c.top},{width:o.width,height:o.height})}c.image=m,c.bitmap=await createImageBitmap(m)}else{for(let e=0,t=u+1,a=0,o=[[0]],i=-4;;){const r=e;if(e=b(a,t),a+=t,e===y){t=u+1,o.length=y+2;for(let e=0;e<o.length;e++)o[e]=e<y?[e]:[]}else{if(e===y+1)break;e>=o.length?o.push(o[r].concat(o[r][0])):r!==y&&o.push(o[r].concat(o[e][0]));for(let t=0;t<o[e].length;t++){const{r:a,g:r,b:n,a:s}=p(o[e][t]);m.data.set([a,r,n,s],i+=4)}o.length>=1<<t&&t<12&&t++}}c.image=m,c.bitmap=await createImageBitmap(m),l?.((e.pos+1)/e.data.length,r(!1)+1,c.image,{x:c.left,y:c.top},{width:o.width,height:o.height})}}(e,o,i,r,s,l);break;case 33:await async function(e,t,a,o){switch(e.nextByte()){case 249:{const i=t.frames[a(!1)];e.pos++;const r=e.nextByte();i.GCreserved=(224&r)>>>5,i.disposalMethod=(28&r)>>>2,i.userInputDelayFlag=2==(2&r);const n=1==(1&r);i.delayTime=10*e.nextTwoBytes();const s=e.nextByte();n&&o(s),e.pos++;break}case 255:{e.pos++;const a={identifier:e.getString(8),authenticationCode:e.getString(3),data:e.readSubBlocksBin()};t.applicationExtensions.push(a);break}case 254:t.comments.push([a(!1),e.readSubBlocks()]);break;case 1:if(0===t.globalColorTable.length)throw new EvalError("plain text extension without global color table");e.pos++,t.frames[a(!1)].plainTextData={left:e.nextTwoBytes(),top:e.nextTwoBytes(),width:e.nextTwoBytes(),height:e.nextTwoBytes(),charSize:{width:e.nextTwoBytes(),height:e.nextTwoBytes()},foregroundColor:e.nextByte(),backgroundColor:e.nextByte(),text:e.readSubBlocks()};break;default:e.skipSubBlocks()}}(e,o,r,s);break;default:throw new EvalError("undefined block found")}return!1}const l=/(#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d.]+%?\))|currentcolor/gi;async function c(t){return new Promise((a=>{t.loading=!0;const o=new Image;t.element=o,o.addEventListener("load",(()=>{t.loading=!1,a()})),o.addEventListener("error",(()=>{t.element=void 0,t.error=!0,t.loading=!1,(0,e.getLogger)().error(`${e.errorPrefix} loading image: ${t.source}`),a()})),o.src=t.source}))}async function g(e){if("gif"===e.type){e.loading=!0;try{e.gifData=await async function(e,t,a){a||(a=!1);const o=await fetch(e);if(!o.ok&&404===o.status)throw new EvalError("file not found");const i=await o.arrayBuffer(),l={width:0,height:0,totalTime:0,colorRes:0,pixelAspectRatio:0,frames:[],sortFlag:!1,globalColorTable:[],backgroundImage:new ImageData(1,1,{colorSpace:"srgb"}),comments:[],applicationExtensions:[]},c=new r(new Uint8ClampedArray(i));if("GIF89a"!==c.getString(6))throw new Error("not a supported GIF file");l.width=c.nextTwoBytes(),l.height=c.nextTwoBytes();const g=c.nextByte(),h=128==(128&g);l.colorRes=(112&g)>>>4,l.sortFlag=8==(8&g);const d=1<<1+(7&g),f=c.nextByte();l.pixelAspectRatio=c.nextByte(),0!==l.pixelAspectRatio&&(l.pixelAspectRatio=(l.pixelAspectRatio+15)/64),h&&(l.globalColorTable=n(c,d));const p=(()=>{try{return new ImageData(l.width,l.height,{colorSpace:"srgb"})}catch(e){if(e instanceof DOMException&&"IndexSizeError"===e.name)return null;throw e}})();if(null==p)throw new Error("GIF frame size is to large");const{r:m,g:u,b:w}=l.globalColorTable[f];p.data.set(h?[m,u,w,255]:[0,0,0,0]);for(let e=4;e<p.data.length;e*=2)p.data.copyWithin(e,0,e);l.backgroundImage=p;let y=-1,b=!0,x=-1;const C=e=>(e&&(b=!0),y),v=e=>(null!=e&&(x=e),x);try{do{b&&(l.frames.push({left:0,top:0,width:0,height:0,disposalMethod:0,image:new ImageData(1,1,{colorSpace:"srgb"}),plainTextData:null,userInputDelayFlag:!1,delayTime:0,sortFlag:!1,localColorTable:[],reserved:0,GCreserved:0}),y++,x=-1,b=!1)}while(!await s(c,l,a,C,v,t));l.frames.length--;for(const e of l.frames){if(e.userInputDelayFlag&&0===e.delayTime){l.totalTime=1/0;break}l.totalTime+=e.delayTime}return l}catch(e){if(e instanceof EvalError)throw new Error(`error while parsing frame ${y} "${e.message}"`);throw e}}(e.source),e.gifLoopCount=function(e){for(const t of e.applicationExtensions)if(t.identifier+t.authenticationCode==="NETSCAPE2.0")return t.data[1]+(t.data[2]<<8);return NaN}(e.gifData)??0,0===e.gifLoopCount&&(e.gifLoopCount=1/0)}catch{e.error=!0}e.loading=!1}else await c(e)}async function h(t){if("svg"!==t.type)return void await c(t);t.loading=!0;const a=await fetch(t.source);a.ok?t.svgData=await a.text():((0,e.getLogger)().error(`${e.errorPrefix} Image not found`),t.error=!0),t.loading=!1}function d(t,a,o,i){const r=function(t,a,o){const{svgData:i}=t;if(!i)return"";const r=(0,e.getStyleFromHsl)(a,o);if(i.includes("fill"))return i.replace(l,(()=>r));const n=i.indexOf(">");return`${i.substring(0,n)} fill="${r}"${i.substring(n)}`}(t,o,i.opacity?.value??1),n={color:o,gif:a.gif,data:{...t,svgData:r},loaded:!1,ratio:a.width/a.height,replaceColor:a.replaceColor,source:a.src};return new Promise((e=>{const a=new Blob([r],{type:"image/svg+xml"}),o=URL||window.URL||window.webkitURL||window,i=o.createObjectURL(a),s=new Image;s.addEventListener("load",(()=>{n.loaded=!0,n.element=s,e(n),o.revokeObjectURL(i)})),s.addEventListener("error",(async()=>{o.revokeObjectURL(i);const a={...t,error:!1,loading:!0};await c(a),n.loaded=!0,n.element=a.element,e(n)})),s.src=i}))}class f{constructor(t){this.loadImageShape=async t=>{if(!this._engine.loadImage)throw new Error(`${e.errorPrefix} image shape not initialized`);await this._engine.loadImage({gif:t.gif,name:t.name,replaceColor:t.replaceColor??!1,src:t.src})},this._engine=t}addImage(e){this._engine.images||(this._engine.images=[]),this._engine.images.push(e)}draw(e){const{context:t,radius:a,particle:o,opacity:i,delta:r}=e,n=o.image,s=n?.element;if(n){if(t.globalAlpha=i,n.gif&&n.gifData){const e=new OffscreenCanvas(n.gifData.width,n.gifData.height),i=e.getContext("2d");if(!i)throw new Error("could not create offscreen canvas context");i.imageSmoothingQuality="low",i.imageSmoothingEnabled=!1,i.clearRect(0,0,e.width,e.height),void 0===o.gifLoopCount&&(o.gifLoopCount=n.gifLoopCount??0);let s=o.gifFrame??0;const l={x:.5*-n.gifData.width,y:.5*-n.gifData.height},c=n.gifData.frames[s];if(void 0===o.gifTime&&(o.gifTime=0),!c.bitmap)return;switch(t.scale(a/n.gifData.width,a/n.gifData.height),c.disposalMethod){case 4:case 5:case 6:case 7:case 0:i.drawImage(c.bitmap,c.left,c.top),t.drawImage(e,l.x,l.y),i.clearRect(0,0,e.width,e.height);break;case 1:i.drawImage(c.bitmap,c.left,c.top),t.drawImage(e,l.x,l.y);break;case 2:i.drawImage(c.bitmap,c.left,c.top),t.drawImage(e,l.x,l.y),i.clearRect(0,0,e.width,e.height),0===n.gifData.globalColorTable.length?i.putImageData(n.gifData.frames[0].image,l.x+c.left,l.y+c.top):i.putImageData(n.gifData.backgroundImage,l.x,l.y);break;case 3:{const a=i.getImageData(0,0,e.width,e.height);i.drawImage(c.bitmap,c.left,c.top),t.drawImage(e,l.x,l.y),i.clearRect(0,0,e.width,e.height),i.putImageData(a,0,0)}}if(o.gifTime+=r.value,o.gifTime>c.delayTime){if(o.gifTime-=c.delayTime,++s>=n.gifData.frames.length){if(--o.gifLoopCount<=0)return;s=0,i.clearRect(0,0,e.width,e.height)}o.gifFrame=s}t.scale(n.gifData.width/a,n.gifData.height/a)}else if(s){const e=n.ratio,o={x:-a,y:-a},i=2*a;t.drawImage(s,o.x,o.y,i,i/e)}t.globalAlpha=1}}getSidesCount(){return 12}async init(e){const t=e.actualOptions;if(t.preload&&this._engine.loadImage)for(const e of t.preload)await this._engine.loadImage(e)}loadShape(e){if("image"!==e.shape&&"images"!==e.shape)return;this._engine.images||(this._engine.images=[]);const t=e.shapeData;if(!t)return;this._engine.images.find((e=>e.name===t.name||e.source===t.src))||this.loadImageShape(t).then((()=>{this.loadShape(e)}))}particleInit(e,t){if("image"!==t.shape&&"images"!==t.shape)return;this._engine.images||(this._engine.images=[]);const a=this._engine.images,o=t.shapeData;if(!o)return;const i=t.getFillColor(),r=a.find((e=>e.name===o.name||e.source===o.src));if(!r)return;const n=o.replaceColor??r.replaceColor;r.loading?setTimeout((()=>{this.particleInit(e,t)})):(async()=>{let e;e=r.svgData&&i?await d(r,o,i,t):{color:i,data:r,element:r.element,gif:r.gif,gifData:r.gifData,gifLoopCount:r.gifLoopCount,loaded:!0,ratio:o.width&&o.height?o.width/o.height:r.ratio??1,replaceColor:n,source:o.src},e.ratio||(e.ratio=1);const a={image:e,fill:o.fill??t.shapeFill,close:o.close??t.shapeClose};t.image=a.image,t.shapeFill=a.fill,t.shapeClose=a.close})()}}class p{constructor(){this.src="",this.gif=!1}load(e){e&&(void 0!==e.gif&&(this.gif=e.gif),void 0!==e.height&&(this.height=e.height),void 0!==e.name&&(this.name=e.name),void 0!==e.replaceColor&&(this.replaceColor=e.replaceColor),void 0!==e.src&&(this.src=e.src),void 0!==e.width&&(this.width=e.width))}}class m{constructor(e){this.id="imagePreloader",this._engine=e}getPlugin(){return{}}loadOptions(e,t){if(!t||!t.preload)return;e.preload||(e.preload=[]);const a=e.preload;for(const e of t.preload){const t=a.find((t=>t.name===e.name||t.src===e.src));if(t)t.load(e);else{const t=new p;t.load(e),a.push(t)}}}needsPlugin(){return!0}}async function u(t,a=!0){!function(t){t.loadImage||(t.loadImage=async a=>{if(!a.name&&!a.src)throw new Error(`${e.errorPrefix} no image source provided`);if(t.images||(t.images=[]),!t.images.find((e=>e.name===a.name||e.source===a.src)))try{const e={gif:a.gif??!1,name:a.name??a.src,source:a.src,type:a.src.substring(a.src.length-3),error:!1,loading:!0,replaceColor:a.replaceColor,ratio:a.width&&a.height?a.width/a.height:void 0};t.images.push(e);const o=a.gif?g:a.replaceColor?h:c;await o(e)}catch{throw new Error(`${e.errorPrefix} ${a.name??a.src} not found`)}})}(t);const o=new m(t);await t.addPlugin(o,a),await t.addShape(["image","images"],new f(t),a)}})(),i})()));
2
+ !function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("@tsparticles/engine"));else if("function"==typeof define&&define.amd)define(["@tsparticles/engine"],t);else{var a="object"==typeof exports?t(require("@tsparticles/engine")):t(e.window);for(var o in a)("object"==typeof exports?exports:e)[o]=a[o]}}(this,(e=>(()=>{"use strict";var t={533:t=>{t.exports=e}},a={};function o(e){var i=a[e];if(void 0!==i)return i.exports;var r=a[e]={exports:{}};return t[e](r,r.exports,o),r.exports}o.d=(e,t)=>{for(var a in t)o.o(t,a)&&!o.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var i={};return(()=>{o.r(i),o.d(i,{loadImageShape:()=>C});var e=o(533);const t=[0,4,2,1],a=[8,8,4,2];class r{constructor(e){this.pos=0,this.data=new Uint8ClampedArray(e)}getString(e){const t=this.data.slice(this.pos,this.pos+e);return this.pos+=t.length,t.reduce(((e,t)=>e+String.fromCharCode(t)),"")}nextByte(){return this.data[this.pos++]}nextTwoBytes(){return this.pos+=2,this.data[this.pos-2]+(this.data[this.pos-1]<<8)}readSubBlocks(){let e="",t=0;do{t=this.data[this.pos++];for(let a=t;--a>=0;e+=String.fromCharCode(this.data[this.pos++]));}while(0!==t);return e}readSubBlocksBin(){let e=0,t=0;for(let a=0;0!==e;a+=e+1,e=this.data[this.pos+a])t+=e;const a=new Uint8Array(t);for(let t=0;0!==e;e=this.data[this.pos++])for(let o=e;--o>=0;a[t++]=this.data[this.pos++]);return a}skipSubBlocks(){for(const e=1,t=0;this.data[this.pos]!==t;this.pos+=this.data[this.pos]+e);this.pos++}}function n(e,t){const a=[];for(let o=0;o<t;o++)a.push({r:e.data[e.pos],g:e.data[e.pos+1],b:e.data[e.pos+2]}),e.pos+=3;return a}async function s(e,o,i,r,s,l){switch(e.nextByte()){case 59:return!0;case 44:await async function(e,o,i,r,s,l){const c=o.frames[r(!0)];c.left=e.nextTwoBytes(),c.top=e.nextTwoBytes(),c.width=e.nextTwoBytes(),c.height=e.nextTwoBytes();const g=e.nextByte(),h=128==(128&g),d=64==(64&g);c.sortFlag=32==(32&g),c.reserved=(24&g)>>>3;const f=1<<1+(7&g);h&&(c.localColorTable=n(e,f));const p=e=>{const{r:t,g:a,b:r}=(h?c.localColorTable:o.globalColorTable)[e];return e!==s(null)?{r:t,g:a,b:r,a:255}:{r:t,g:a,b:r,a:i?~~((t+a+r)/3):0}},m=(()=>{try{return new ImageData(c.width,c.height,{colorSpace:"srgb"})}catch(e){if(e instanceof DOMException&&"IndexSizeError"===e.name)return null;throw e}})();if(null==m)throw new EvalError("GIF frame size is to large");const u=e.nextByte(),w=e.readSubBlocksBin(),y=1<<u,b=(e,t)=>{const a=e>>>3,o=7&e;return(w[a]+(w[a+1]<<8)+(w[a+2]<<16)&(1<<t)-1<<o)>>>o};if(d){for(let i=0,n=u+1,s=0,g=[[0]],h=0;h<4;h++){if(t[h]<c.height){let e=0,o=0,r=!1;for(;!r;){const l=i;if(i=b(s,n),s+=n+1,i===y){n=u+1,g.length=y+2;for(let e=0;e<g.length;e++)g[e]=e<y?[e]:[]}else{i>=g.length?g.push(g[l].concat(g[l][0])):l!==y&&g.push(g[l].concat(g[i][0]));for(const r of g[i]){const{r:i,g:n,b:s,a:l}=p(r);m.data.set([i,n,s,l],t[h]*c.width+a[h]*o+e%(4*c.width)),e+=4}g.length===1<<n&&n<12&&n++}e===4*c.width*(o+1)&&(o++,t[h]+a[h]*o>=c.height&&(r=!0))}}l?.(e.pos/(e.data.length-1),r(!1)+1,m,{x:c.left,y:c.top},{width:o.width,height:o.height})}c.image=m,c.bitmap=await createImageBitmap(m)}else{let t=0,a=u+1,i=0,n=-4,s=!1;const g=[[0]];for(;!s;){const e=t;if(t=b(i,a),i+=a,t===y){a=u+1,g.length=y+2;for(let e=0;e<g.length;e++)g[e]=e<y?[e]:[]}else{if(t===y+1){s=!0;break}t>=g.length?g.push(g[e].concat(g[e][0])):e!==y&&g.push(g[e].concat(g[t][0]));for(const e of g[t]){const{r:t,g:a,b:o,a:i}=p(e);m.data.set([t,a,o,i],n+=4)}g.length>=1<<a&&a<12&&a++}}c.image=m,c.bitmap=await createImageBitmap(m),l?.((e.pos+1)/e.data.length,r(!1)+1,c.image,{x:c.left,y:c.top},{width:o.width,height:o.height})}}(e,o,i,r,s,l);break;case 33:!function(e,t,a,o){switch(e.nextByte()){case 249:{const i=t.frames[a(!1)];e.pos++;const r=e.nextByte();i.GCreserved=(224&r)>>>5,i.disposalMethod=(28&r)>>>2,i.userInputDelayFlag=2==(2&r);const n=1==(1&r);i.delayTime=10*e.nextTwoBytes();const s=e.nextByte();n&&o(s),e.pos++;break}case 255:{e.pos++;const a={identifier:e.getString(8),authenticationCode:e.getString(3),data:e.readSubBlocksBin()};t.applicationExtensions.push(a);break}case 254:t.comments.push([a(!1),e.readSubBlocks()]);break;case 1:if(0===t.globalColorTable.length)throw new EvalError("plain text extension without global color table");e.pos++,t.frames[a(!1)].plainTextData={left:e.nextTwoBytes(),top:e.nextTwoBytes(),width:e.nextTwoBytes(),height:e.nextTwoBytes(),charSize:{width:e.nextTwoBytes(),height:e.nextTwoBytes()},foregroundColor:e.nextByte(),backgroundColor:e.nextByte(),text:e.readSubBlocks()};break;default:e.skipSubBlocks()}}(e,o,r,s);break;default:throw new EvalError("undefined block found")}return!1}const l=0,c=0,g=/(#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d.]+%?\))|currentcolor/gi;async function h(t){return new Promise((a=>{t.loading=!0;const o=new Image;t.element=o,o.addEventListener("load",(()=>{t.loading=!1,a()})),o.addEventListener("error",(()=>{t.element=void 0,t.error=!0,t.loading=!1,(0,e.getLogger)().error(`${e.errorPrefix} loading image: ${t.source}`),a()})),o.src=t.source}))}async function d(e){if("gif"===e.type){e.loading=!0;try{e.gifData=await async function(e,t,a){a||(a=!1);const o=await fetch(e);if(!o.ok&&404===o.status)throw new EvalError("file not found");const i=await o.arrayBuffer(),l={width:0,height:0,totalTime:0,colorRes:0,pixelAspectRatio:0,frames:[],sortFlag:!1,globalColorTable:[],backgroundImage:new ImageData(1,1,{colorSpace:"srgb"}),comments:[],applicationExtensions:[]},c=new r(new Uint8ClampedArray(i));if("GIF89a"!==c.getString(6))throw new Error("not a supported GIF file");l.width=c.nextTwoBytes(),l.height=c.nextTwoBytes();const g=c.nextByte(),h=128==(128&g);l.colorRes=(112&g)>>>4,l.sortFlag=8==(8&g);const d=1<<1+(7&g),f=c.nextByte();l.pixelAspectRatio=c.nextByte(),0!==l.pixelAspectRatio&&(l.pixelAspectRatio=(l.pixelAspectRatio+15)/64),h&&(l.globalColorTable=n(c,d));const p=(()=>{try{return new ImageData(l.width,l.height,{colorSpace:"srgb"})}catch(e){if(e instanceof DOMException&&"IndexSizeError"===e.name)return null;throw e}})();if(null==p)throw new Error("GIF frame size is to large");const{r:m,g:u,b:w}=l.globalColorTable[f];p.data.set(h?[m,u,w,255]:[0,0,0,0]);for(let e=4;e<p.data.length;e*=2)p.data.copyWithin(e,0,e);l.backgroundImage=p;let y=-1,b=!0,x=-1;const C=e=>(e&&(b=!0),y),v=e=>(null!=e&&(x=e),x);try{do{b&&(l.frames.push({left:0,top:0,width:0,height:0,disposalMethod:0,image:new ImageData(1,1,{colorSpace:"srgb"}),plainTextData:null,userInputDelayFlag:!1,delayTime:0,sortFlag:!1,localColorTable:[],reserved:0,GCreserved:0}),y++,x=-1,b=!1)}while(!await s(c,l,a,C,v,t));l.frames.length--;for(const e of l.frames){if(e.userInputDelayFlag&&0===e.delayTime){l.totalTime=1/0;break}l.totalTime+=e.delayTime}return l}catch(e){if(e instanceof EvalError)throw new Error(`error while parsing frame ${y} "${e.message}"`);throw e}}(e.source),e.gifLoopCount=function(e){for(const t of e.applicationExtensions)if(t.identifier+t.authenticationCode==="NETSCAPE2.0")return t.data[1]+(t.data[2]<<8);return NaN}(e.gifData)??c,e.gifLoopCount||(e.gifLoopCount=1/0)}catch{e.error=!0}e.loading=!1}else await h(e)}async function f(t){if("svg"!==t.type)return void await h(t);t.loading=!0;const a=await fetch(t.source);a.ok?t.svgData=await a.text():((0,e.getLogger)().error(`${e.errorPrefix} Image not found`),t.error=!0),t.loading=!1}function p(t,a,o,i){const r=function(t,a,o){const{svgData:i}=t;if(!i)return"";const r=(0,e.getStyleFromHsl)(a,o);if(i.includes("fill"))return i.replace(g,(()=>r));const n=i.indexOf(">");return`${i.substring(l,n)} fill="${r}"${i.substring(n)}`}(t,o,i.opacity?.value??1),n={color:o,gif:a.gif,data:{...t,svgData:r},loaded:!1,ratio:a.width/a.height,replaceColor:a.replaceColor,source:a.src};return new Promise((e=>{const a=new Blob([r],{type:"image/svg+xml"}),o=URL||window.URL||window.webkitURL||window,i=o.createObjectURL(a),s=new Image;s.addEventListener("load",(()=>{n.loaded=!0,n.element=s,e(n),o.revokeObjectURL(i)}));s.addEventListener("error",(()=>{(async()=>{o.revokeObjectURL(i);const a={...t,error:!1,loading:!0};await h(a),n.loaded=!0,n.element=a.element,e(n)})()})),s.src=i}))}const m=0,u=0;class w{constructor(t){this.loadImageShape=async t=>{if(!this._engine.loadImage)throw new Error(`${e.errorPrefix} image shape not initialized`);await this._engine.loadImage({gif:t.gif,name:t.name,replaceColor:t.replaceColor??!1,src:t.src})},this._engine=t}addImage(e){this._engine.images||(this._engine.images=[]),this._engine.images.push(e)}draw(e){const{context:t,radius:a,particle:o,opacity:i,delta:r}=e,n=o.image,s=n?.element;if(n){if(t.globalAlpha=i,n.gif&&n.gifData){const e=new OffscreenCanvas(n.gifData.width,n.gifData.height),i=e.getContext("2d");if(!i)throw new Error("could not create offscreen canvas context");i.imageSmoothingQuality="low",i.imageSmoothingEnabled=!1,i.clearRect(m,u,e.width,e.height),void 0===o.gifLoopCount&&(o.gifLoopCount=n.gifLoopCount??0);let s=o.gifFrame??0;const l={x:.5*-n.gifData.width,y:.5*-n.gifData.height},c=n.gifData.frames[s];if(void 0===o.gifTime&&(o.gifTime=0),!c.bitmap)return;switch(t.scale(a/n.gifData.width,a/n.gifData.height),c.disposalMethod){case 4:case 5:case 6:case 7:case 0:i.drawImage(c.bitmap,c.left,c.top),t.drawImage(e,l.x,l.y),i.clearRect(m,u,e.width,e.height);break;case 1:i.drawImage(c.bitmap,c.left,c.top),t.drawImage(e,l.x,l.y);break;case 2:i.drawImage(c.bitmap,c.left,c.top),t.drawImage(e,l.x,l.y),i.clearRect(m,u,e.width,e.height),n.gifData.globalColorTable.length?i.putImageData(n.gifData.backgroundImage,l.x,l.y):i.putImageData(n.gifData.frames[0].image,l.x+c.left,l.y+c.top);break;case 3:{const a=i.getImageData(m,u,e.width,e.height);i.drawImage(c.bitmap,c.left,c.top),t.drawImage(e,l.x,l.y),i.clearRect(m,u,e.width,e.height),i.putImageData(a,m,u)}}if(o.gifTime+=r.value,o.gifTime>c.delayTime){if(o.gifTime-=c.delayTime,++s>=n.gifData.frames.length){if(--o.gifLoopCount<=0)return;s=0,i.clearRect(m,u,e.width,e.height)}o.gifFrame=s}t.scale(n.gifData.width/a,n.gifData.height/a)}else if(s){const e=n.ratio,o={x:-a,y:-a},i=2*a;t.drawImage(s,o.x,o.y,i,i/e)}t.globalAlpha=1}}getSidesCount(){return 12}async init(e){const t=e.actualOptions;if(t.preload&&this._engine.loadImage)for(const e of t.preload)await this._engine.loadImage(e)}loadShape(e){if("image"!==e.shape&&"images"!==e.shape)return;this._engine.images||(this._engine.images=[]);const t=e.shapeData;if(!t)return;this._engine.images.find((e=>e.name===t.name||e.source===t.src))||this.loadImageShape(t).then((()=>{this.loadShape(e)}))}particleInit(e,t){if("image"!==t.shape&&"images"!==t.shape)return;this._engine.images||(this._engine.images=[]);const a=this._engine.images,o=t.shapeData;if(!o)return;const i=t.getFillColor(),r=a.find((e=>e.name===o.name||e.source===o.src));if(!r)return;const n=o.replaceColor??r.replaceColor;r.loading?setTimeout((()=>{this.particleInit(e,t)})):(async()=>{let e;e=r.svgData&&i?await p(r,o,i,t):{color:i,data:r,element:r.element,gif:r.gif,gifData:r.gifData,gifLoopCount:r.gifLoopCount,loaded:!0,ratio:o.width&&o.height?o.width/o.height:r.ratio??1,replaceColor:n,source:o.src},e.ratio||(e.ratio=1);const a={image:e,fill:o.fill??t.shapeFill,close:o.close??t.shapeClose};t.image=a.image,t.shapeFill=a.fill,t.shapeClose=a.close})()}}class y{constructor(){this.src="",this.gif=!1}load(e){e&&(void 0!==e.gif&&(this.gif=e.gif),void 0!==e.height&&(this.height=e.height),void 0!==e.name&&(this.name=e.name),void 0!==e.replaceColor&&(this.replaceColor=e.replaceColor),void 0!==e.src&&(this.src=e.src),void 0!==e.width&&(this.width=e.width))}}class b{constructor(e){this.id="imagePreloader",this._engine=e}getPlugin(){return{}}loadOptions(e,t){if(!t?.preload)return;e.preload||(e.preload=[]);const a=e.preload;for(const e of t.preload){const t=a.find((t=>t.name===e.name||t.src===e.src));if(t)t.load(e);else{const t=new y;t.load(e),a.push(t)}}}needsPlugin(){return!0}}const x=3;async function C(t,a=!0){!function(t){t.loadImage||(t.loadImage=async a=>{if(!a.name&&!a.src)throw new Error(`${e.errorPrefix} no image source provided`);if(t.images||(t.images=[]),!t.images.find((e=>e.name===a.name||e.source===a.src)))try{const e={gif:a.gif??!1,name:a.name??a.src,source:a.src,type:a.src.substring(a.src.length-x),error:!1,loading:!0,replaceColor:a.replaceColor,ratio:a.width&&a.height?a.width/a.height:void 0};let o;t.images.push(e),o=a.gif?d:a.replaceColor?f:h,await o(e)}catch{throw new Error(`${e.errorPrefix} ${a.name??a.src} not found`)}})}(t);const o=new b(t);await t.addPlugin(o,a),await t.addShape(["image","images"],new w(t),a)}})(),i})()));
@@ -1 +1 @@
1
- /*! tsParticles Image Shape v3.0.3 by Matteo Bruni */
1
+ /*! tsParticles Image Shape v3.1.0 by Matteo Bruni */
@@ -1,5 +1,5 @@
1
1
  import { type Container, type IShapeDrawData, type IShapeDrawer } from "@tsparticles/engine";
2
- import type { IImage, ImageParticle } from "./Utils.js";
2
+ import { type IImage, type ImageParticle } from "./Utils.js";
3
3
  import type { ImageContainer, ImageEngine } from "./types.js";
4
4
  export declare class ImageDrawer implements IShapeDrawer<ImageParticle> {
5
5
  private readonly _engine;
@@ -24,32 +24,35 @@
24
24
  return this.data[this.pos++];
25
25
  }
26
26
  nextTwoBytes() {
27
- this.pos += 2;
28
- return this.data[this.pos - 2] + (this.data[this.pos - 1] << 8);
27
+ const increment = 2, previous = 1, shift = 8;
28
+ this.pos += increment;
29
+ return this.data[this.pos - increment] + (this.data[this.pos - previous] << shift);
29
30
  }
30
31
  readSubBlocks() {
31
32
  let blockString = "", size = 0;
33
+ const minCount = 0, emptySize = 0;
32
34
  do {
33
35
  size = this.data[this.pos++];
34
- for (let count = size; --count >= 0; blockString += String.fromCharCode(this.data[this.pos++])) {
36
+ for (let count = size; --count >= minCount; blockString += String.fromCharCode(this.data[this.pos++])) {
35
37
  }
36
- } while (size !== 0);
38
+ } while (size !== emptySize);
37
39
  return blockString;
38
40
  }
39
41
  readSubBlocksBin() {
40
42
  let size = 0, len = 0;
41
- for (let offset = 0; (size = this.data[this.pos + offset]) !== 0; offset += size + 1) {
43
+ const emptySize = 0, increment = 1;
44
+ for (let offset = 0; size !== emptySize; offset += size + increment, size = this.data[this.pos + offset]) {
42
45
  len += size;
43
46
  }
44
47
  const blockData = new Uint8Array(len);
45
- for (let i = 0; (size = this.data[this.pos++]) !== 0;) {
46
- for (let count = size; --count >= 0; blockData[i++] = this.data[this.pos++]) {
48
+ for (let i = 0; size !== emptySize; size = this.data[this.pos++]) {
49
+ for (let count = size; --count >= emptySize; blockData[i++] = this.data[this.pos++]) {
47
50
  }
48
51
  }
49
52
  return blockData;
50
53
  }
51
54
  skipSubBlocks() {
52
- for (; this.data[this.pos] !== 0; this.pos += this.data[this.pos] + 1) {
55
+ for (const increment = 1, noData = 0; this.data[this.pos] !== noData; this.pos += this.data[this.pos] + increment) {
53
56
  }
54
57
  this.pos++;
55
58
  }
@@ -24,7 +24,7 @@
24
24
  }
25
25
  return colors;
26
26
  }
27
- async function parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex) {
27
+ function parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex) {
28
28
  switch (byteStream.nextByte()) {
29
29
  case 249: {
30
30
  const frame = gif.frames[getFrameIndex(false)];
@@ -96,7 +96,10 @@
96
96
  }
97
97
  const getColor = (index) => {
98
98
  const { r, g, b } = (localColorTableFlag ? frame.localColorTable : gif.globalColorTable)[index];
99
- return { r, g, b, a: index === getTransparencyIndex(null) ? (avgAlpha ? ~~((r + g + b) / 3) : 0) : 255 };
99
+ if (index !== getTransparencyIndex(null)) {
100
+ return { r, g, b, a: 255 };
101
+ }
102
+ return { r, g, b, a: avgAlpha ? ~~((r + g + b) / 3) : 0 };
100
103
  };
101
104
  const image = (() => {
102
105
  try {
@@ -122,7 +125,8 @@
122
125
  if (interlacedFlag) {
123
126
  for (let code = 0, size = minCodeSize + 1, pos = 0, dic = [[0]], pass = 0; pass < 4; pass++) {
124
127
  if (Constants_js_1.InterlaceOffsets[pass] < frame.height) {
125
- for (let pixelPos = 0, lineIndex = 0;;) {
128
+ let pixelPos = 0, lineIndex = 0, exit = false;
129
+ while (!exit) {
126
130
  const last = code;
127
131
  code = readBits(pos, size);
128
132
  pos += size + 1;
@@ -140,8 +144,8 @@
140
144
  else if (last !== clearCode) {
141
145
  dic.push(dic[last].concat(dic[code][0]));
142
146
  }
143
- for (let i = 0; i < dic[code].length; i++) {
144
- const { r, g, b, a } = getColor(dic[code][i]);
147
+ for (const item of dic[code]) {
148
+ const { r, g, b, a } = getColor(item);
145
149
  image.data.set([r, g, b, a], Constants_js_1.InterlaceOffsets[pass] * frame.width +
146
150
  Constants_js_1.InterlaceSteps[pass] * lineIndex +
147
151
  (pixelPos % (frame.width * 4)));
@@ -154,7 +158,7 @@
154
158
  if (pixelPos === frame.width * 4 * (lineIndex + 1)) {
155
159
  lineIndex++;
156
160
  if (Constants_js_1.InterlaceOffsets[pass] + Constants_js_1.InterlaceSteps[pass] * lineIndex >= frame.height) {
157
- break;
161
+ exit = true;
158
162
  }
159
163
  }
160
164
  }
@@ -165,7 +169,9 @@
165
169
  frame.bitmap = await createImageBitmap(image);
166
170
  }
167
171
  else {
168
- for (let code = 0, size = minCodeSize + 1, pos = 0, dic = [[0]], pixelPos = -4;;) {
172
+ let code = 0, size = minCodeSize + 1, pos = 0, pixelPos = -4, exit = false;
173
+ const dic = [[0]];
174
+ while (!exit) {
169
175
  const last = code;
170
176
  code = readBits(pos, size);
171
177
  pos += size;
@@ -178,6 +184,7 @@
178
184
  }
179
185
  else {
180
186
  if (code === clearCode + 1) {
187
+ exit = true;
181
188
  break;
182
189
  }
183
190
  if (code >= dic.length) {
@@ -186,8 +193,8 @@
186
193
  else if (last !== clearCode) {
187
194
  dic.push(dic[last].concat(dic[code][0]));
188
195
  }
189
- for (let i = 0; i < dic[code].length; i++) {
190
- const { r, g, b, a } = getColor(dic[code][i]);
196
+ for (const item of dic[code]) {
197
+ const { r, g, b, a } = getColor(item);
191
198
  image.data.set([r, g, b, a], (pixelPos += 4));
192
199
  }
193
200
  if (dic.length >= 1 << size && size < 0xc) {
@@ -208,7 +215,7 @@
208
215
  await parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, progressCallback);
209
216
  break;
210
217
  case 33:
211
- await parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex);
218
+ parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex);
212
219
  break;
213
220
  default:
214
221
  throw new EvalError("undefined block found");