@tsparticles/shape-image 3.0.3 → 3.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/21.min.js +2 -0
- package/21.min.js.LICENSE.txt +1 -0
- package/618.min.js +2 -0
- package/618.min.js.LICENSE.txt +1 -0
- package/623.min.js +2 -0
- package/623.min.js.LICENSE.txt +1 -0
- package/browser/GifUtils/ByteStream.js +13 -9
- package/browser/GifUtils/Utils.js +113 -10
- package/browser/ImageDrawer.js +44 -109
- package/browser/ImagePreloader.js +3 -2
- package/browser/Utils.js +6 -23
- package/browser/index.js +12 -5
- package/cjs/GifUtils/ByteStream.js +13 -9
- package/cjs/GifUtils/Utils.js +139 -11
- package/cjs/ImageDrawer.js +67 -109
- package/cjs/ImagePreloader.js +3 -2
- package/cjs/Utils.js +7 -25
- package/cjs/index.js +36 -6
- package/dist_browser_GifUtils_Utils_js.js +50 -0
- package/dist_browser_ImageDrawer_js.js +30 -0
- package/dist_browser_ImagePreloader_js.js +40 -0
- package/esm/GifUtils/ByteStream.js +13 -9
- package/esm/GifUtils/Utils.js +113 -10
- package/esm/ImageDrawer.js +44 -109
- package/esm/ImagePreloader.js +3 -2
- package/esm/Utils.js +6 -23
- package/esm/index.js +12 -5
- package/package.json +2 -2
- package/report.html +3 -3
- package/tsparticles.shape.image.js +251 -862
- package/tsparticles.shape.image.min.js +1 -1
- package/tsparticles.shape.image.min.js.LICENSE.txt +1 -1
- package/types/GifUtils/Utils.d.ts +4 -0
- package/types/ImageDrawer.d.ts +3 -3
- package/types/ImagePreloader.d.ts +1 -1
- package/types/Utils.d.ts +0 -1
- package/umd/GifUtils/ByteStream.js +13 -9
- package/umd/GifUtils/Utils.js +140 -11
- package/umd/ImageDrawer.js +69 -110
- package/umd/ImagePreloader.js +3 -2
- package/umd/Utils.js +8 -26
- package/umd/index.js +38 -7
package/21.min.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! For license information please see 21.min.js.LICENSE.txt */
|
|
2
|
+
(this.webpackChunk_tsparticles_shape_image=this.webpackChunk_tsparticles_shape_image||[]).push([[21],{21:(e,a,i)=>{i.d(a,{ImageDrawer:()=>s});var t=i(533);class s{constructor(e){this.loadImageShape=async e=>{if(!this._engine.loadImage)throw new Error(`${t.errorPrefix} image shape not initialized`);await this._engine.loadImage({gif:e.gif,name:e.name,replaceColor:e.replaceColor??!1,src:e.src})},this._engine=e}addImage(e){this._engine.images||(this._engine.images=[]),this._engine.images.push(e)}async draw(e){const{context:a,radius:t,particle:s,opacity:n}=e,o=s.image,r=o?.element;if(o){if(a.globalAlpha=n,o.gif&&o.gifData){const{drawGif:a}=await i.e(618).then(i.bind(i,618));a(e)}else if(r){const e=o.ratio,i={x:-t,y:-t},s=2*t;a.drawImage(r,i.x,i.y,s,s/e)}a.globalAlpha=1}}getSidesCount(){return 12}async init(e){const a=e.actualOptions;if(a.preload&&this._engine.loadImage)for(const e of a.preload)await this._engine.loadImage(e)}async loadShape(e){if("image"!==e.shape&&"images"!==e.shape)return;this._engine.images||(this._engine.images=[]);const a=e.shapeData;if(!a)return;this._engine.images.find((e=>e.name===a.name||e.source===a.src))||(await this.loadImageShape(a),await this.loadShape(e))}async particleInit(e,a){if("image"!==a.shape&&"images"!==a.shape)return;this._engine.images||(this._engine.images=[]);const t=this._engine.images,s=a.shapeData;if(!s)return;const n=a.getFillColor(),o=t.find((e=>e.name===s.name||e.source===s.src));if(!o)return;const r=s.replaceColor??o.replaceColor;if(o.loading)return void setTimeout((()=>{this.particleInit(e,a)}));let l;if(o.svgData&&n){const{replaceImageColor:e}=await Promise.resolve().then(i.bind(i,103));l=await e(o,s,n,a)}else l={color:n,data:o,element:o.element,gif:o.gif,gifData:o.gifData,gifLoopCount:o.gifLoopCount,loaded:!0,ratio:s.width&&s.height?s.width/s.height:o.ratio??1,replaceColor:r,source:s.src};l.ratio||(l.ratio=1);const g={image:l,fill:s.fill??a.shapeFill,close:s.close??a.shapeClose};a.image=g.image,a.shapeFill=g.fill,a.shapeClose=g.close}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*! tsParticles Image Shape v3.2.0 by Matteo Bruni */
|
package/618.min.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! For license information please see 618.min.js.LICENSE.txt */
|
|
2
|
+
(this.webpackChunk_tsparticles_shape_image=this.webpackChunk_tsparticles_shape_image||[]).push([[618],{618:(t,e,a)=>{a.d(e,{drawGif:()=>p,loadGifImage:()=>w});const o=[0,4,2,1],i=[8,8,4,2];class r{constructor(t){this.pos=0,this.data=new Uint8ClampedArray(t)}getString(t){const e=this.data.slice(this.pos,this.pos+t);return this.pos+=e.length,e.reduce(((t,e)=>t+String.fromCharCode(e)),"")}nextByte(){return this.data[this.pos++]}nextTwoBytes(){return this.pos+=2,this.data[this.pos-2]+(this.data[this.pos-1]<<8)}readSubBlocks(){let t="",e=0;do{e=this.data[this.pos++];for(let a=e;--a>=0;t+=String.fromCharCode(this.data[this.pos++]));}while(0!==e);return t}readSubBlocksBin(){let t=this.data[this.pos],e=0;for(let a=0;0!==t;a+=t+1,t=this.data[this.pos+a])e+=t;const a=new Uint8Array(e);t=this.data[this.pos++];for(let e=0;0!==t;t=this.data[this.pos++])for(let o=t;--o>=0;a[e++]=this.data[this.pos++]);return a}skipSubBlocks(){for(const t=1,e=0;this.data[this.pos]!==e;this.pos+=this.data[this.pos]+t);this.pos++}}const s={x:0,y:0},n=0,l=.5,h=0,c=0,g=0;function f(t,e){const a=[];for(let o=0;o<e;o++)a.push({r:t.data[t.pos],g:t.data[t.pos+1],b:t.data[t.pos+2]}),t.pos+=3;return a}async function d(t,e,a,r,s,n){switch(t.nextByte()){case 59:return!0;case 44:await async function(t,e,a,r,s,n){const l=e.frames[r(!0)];l.left=t.nextTwoBytes(),l.top=t.nextTwoBytes(),l.width=t.nextTwoBytes(),l.height=t.nextTwoBytes();const h=t.nextByte(),c=128==(128&h),g=64==(64&h);l.sortFlag=32==(32&h),l.reserved=(24&h)>>>3;const d=1<<1+(7&h);c&&(l.localColorTable=f(t,d));const p=t=>{const{r:o,g:i,b:r}=(c?l.localColorTable:e.globalColorTable)[t];return t!==s(null)?{r:o,g:i,b:r,a:255}:{r:o,g:i,b:r,a:a?~~((o+i+r)/3):0}},w=(()=>{try{return new ImageData(l.width,l.height,{colorSpace:"srgb"})}catch(t){if(t instanceof DOMException&&"IndexSizeError"===t.name)return null;throw t}})();if(null==w)throw new EvalError("GIF frame size is to large");const u=t.nextByte(),m=t.readSubBlocksBin(),y=1<<u,b=(t,e)=>{const a=t>>>3,o=7&t;return(m[a]+(m[a+1]<<8)+(m[a+2]<<16)&(1<<e)-1<<o)>>>o};if(g){for(let a=0,s=u+1,h=0,c=[[0]],g=0;g<4;g++){if(o[g]<l.height){let t=0,e=0,r=!1;for(;!r;){const n=a;if(a=b(h,s),h+=s+1,a===y){s=u+1,c.length=y+2;for(let t=0;t<c.length;t++)c[t]=t<y?[t]:[]}else{a>=c.length?c.push(c[n].concat(c[n][0])):n!==y&&c.push(c[n].concat(c[a][0]));for(const r of c[a]){const{r:a,g:s,b:n,a:h}=p(r);w.data.set([a,s,n,h],o[g]*l.width+i[g]*e+t%(4*l.width)),t+=4}c.length===1<<s&&s<12&&s++}t===4*l.width*(e+1)&&(e++,o[g]+i[g]*e>=l.height&&(r=!0))}}n?.(t.pos/(t.data.length-1),r(!1)+1,w,{x:l.left,y:l.top},{width:e.width,height:e.height})}l.image=w,l.bitmap=await createImageBitmap(w)}else{let a=0,o=u+1,i=0,s=-4,h=!1;const c=[[0]];for(;!h;){const t=a;if(a=b(i,o),i+=o,a===y){o=u+1,c.length=y+2;for(let t=0;t<c.length;t++)c[t]=t<y?[t]:[]}else{if(a===y+1){h=!0;break}a>=c.length?c.push(c[t].concat(c[t][0])):t!==y&&c.push(c[t].concat(c[a][0]));for(const t of c[a]){const{r:e,g:a,b:o,a:i}=p(t);w.data.set([e,a,o,i],s+=4)}c.length>=1<<o&&o<12&&o++}}l.image=w,l.bitmap=await createImageBitmap(w),n?.((t.pos+1)/t.data.length,r(!1)+1,l.image,{x:l.left,y:l.top},{width:e.width,height:e.height})}}(t,e,a,r,s,n);break;case 33:!function(t,e,a,o){switch(t.nextByte()){case 249:{const i=e.frames[a(!1)];t.pos++;const r=t.nextByte();i.GCreserved=(224&r)>>>5,i.disposalMethod=(28&r)>>>2,i.userInputDelayFlag=2==(2&r);const s=1==(1&r);i.delayTime=10*t.nextTwoBytes();const n=t.nextByte();s&&o(n),t.pos++;break}case 255:{t.pos++;const a={identifier:t.getString(8),authenticationCode:t.getString(3),data:t.readSubBlocksBin()};e.applicationExtensions.push(a);break}case 254:e.comments.push([a(!1),t.readSubBlocks()]);break;case 1:if(0===e.globalColorTable.length)throw new EvalError("plain text extension without global color table");t.pos++,e.frames[a(!1)].plainTextData={left:t.nextTwoBytes(),top:t.nextTwoBytes(),width:t.nextTwoBytes(),height:t.nextTwoBytes(),charSize:{width:t.nextTwoBytes(),height:t.nextTwoBytes()},foregroundColor:t.nextByte(),backgroundColor:t.nextByte(),text:t.readSubBlocks()};break;default:t.skipSubBlocks()}}(t,e,r,s);break;default:throw new EvalError("undefined block found")}return!1}function p(t){const{context:e,radius:a,particle:o,delta:i}=t,r=o.image;if(!r?.gifData||!r.gif)return;const f=new OffscreenCanvas(r.gifData.width,r.gifData.height),d=f.getContext("2d");if(!d)throw new Error("could not create offscreen canvas context");d.imageSmoothingQuality="low",d.imageSmoothingEnabled=!1,d.clearRect(s.x,s.y,f.width,f.height),void 0===o.gifLoopCount&&(o.gifLoopCount=r.gifLoopCount??g);let p=o.gifFrame??n;const w={x:-r.gifData.width*l,y:-r.gifData.height*l},u=r.gifData.frames[p];if(void 0===o.gifTime&&(o.gifTime=h),u.bitmap){switch(e.scale(a/r.gifData.width,a/r.gifData.height),u.disposalMethod){case 4:case 5:case 6:case 7:case 0:d.drawImage(u.bitmap,u.left,u.top),e.drawImage(f,w.x,w.y),d.clearRect(s.x,s.y,f.width,f.height);break;case 1:d.drawImage(u.bitmap,u.left,u.top),e.drawImage(f,w.x,w.y);break;case 2:d.drawImage(u.bitmap,u.left,u.top),e.drawImage(f,w.x,w.y),d.clearRect(s.x,s.y,f.width,f.height),r.gifData.globalColorTable.length?d.putImageData(r.gifData.backgroundImage,w.x,w.y):d.putImageData(r.gifData.frames[c].image,w.x+u.left,w.y+u.top);break;case 3:{const t=d.getImageData(s.x,s.y,f.width,f.height);d.drawImage(u.bitmap,u.left,u.top),e.drawImage(f,w.x,w.y),d.clearRect(s.x,s.y,f.width,f.height),d.putImageData(t,s.x,s.y)}}if(o.gifTime+=i.value,o.gifTime>u.delayTime){if(o.gifTime-=u.delayTime,++p>=r.gifData.frames.length){if(--o.gifLoopCount<=g)return;p=c,d.clearRect(s.x,s.y,f.width,f.height)}o.gifFrame=p}e.scale(r.gifData.width/a,r.gifData.height/a)}}async function w(t){if("gif"===t.type){t.loading=!0;try{t.gifData=await async function(t,e,a){a||(a=!1);const o=await fetch(t);if(!o.ok&&404===o.status)throw new EvalError("file not found");const i=await o.arrayBuffer(),s={width:0,height:0,totalTime:0,colorRes:0,pixelAspectRatio:0,frames:[],sortFlag:!1,globalColorTable:[],backgroundImage:new ImageData(1,1,{colorSpace:"srgb"}),comments:[],applicationExtensions:[]},n=new r(new Uint8ClampedArray(i));if("GIF89a"!==n.getString(6))throw new Error("not a supported GIF file");s.width=n.nextTwoBytes(),s.height=n.nextTwoBytes();const l=n.nextByte(),h=128==(128&l);s.colorRes=(112&l)>>>4,s.sortFlag=8==(8&l);const c=1<<1+(7&l),g=n.nextByte();s.pixelAspectRatio=n.nextByte(),0!==s.pixelAspectRatio&&(s.pixelAspectRatio=(s.pixelAspectRatio+15)/64),h&&(s.globalColorTable=f(n,c));const p=(()=>{try{return new ImageData(s.width,s.height,{colorSpace:"srgb"})}catch(t){if(t instanceof DOMException&&"IndexSizeError"===t.name)return null;throw t}})();if(null==p)throw new Error("GIF frame size is to large");const{r:w,g:u,b:m}=s.globalColorTable[g];p.data.set(h?[w,u,m,255]:[0,0,0,0]);for(let t=4;t<p.data.length;t*=2)p.data.copyWithin(t,0,t);s.backgroundImage=p;let y=-1,b=!0,x=-1;const B=t=>(t&&(b=!0),y),T=t=>(null!=t&&(x=t),x);try{do{b&&(s.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 d(n,s,a,B,T,e));s.frames.length--;for(const t of s.frames){if(t.userInputDelayFlag&&0===t.delayTime){s.totalTime=1/0;break}s.totalTime+=t.delayTime}return s}catch(t){if(t instanceof EvalError)throw new Error(`error while parsing frame ${y} "${t.message}"`);throw t}}(t.source),t.gifLoopCount=function(t){for(const e of t.applicationExtensions)if(e.identifier+e.authenticationCode==="NETSCAPE2.0")return e.data[1]+(e.data[2]<<8);return NaN}(t.gifData)??g,t.gifLoopCount||(t.gifLoopCount=1/0)}catch{t.error=!0}t.loading=!1}else{const{loadImage:e}=await Promise.resolve().then(a.bind(a,103));await e(t)}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*! tsParticles Image Shape v3.2.0 by Matteo Bruni */
|
package/623.min.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! For license information please see 623.min.js.LICENSE.txt */
|
|
2
|
+
(this.webpackChunk_tsparticles_shape_image=this.webpackChunk_tsparticles_shape_image||[]).push([[623],{623:(e,i,s)=>{s.d(i,{ImagePreloaderPlugin:()=>r});class o{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 r{constructor(e){this.id="imagePreloader",this._engine=e}async getPlugin(){return await Promise.resolve(),{}}loadOptions(e,i){if(!i?.preload)return;e.preload||(e.preload=[]);const s=e.preload;for(const e of i.preload){const i=s.find((i=>i.name===e.name||i.src===e.src));if(i)i.load(e);else{const i=new o;i.load(e),s.push(i)}}}needsPlugin(){return!0}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*! tsParticles Image Shape v3.2.0 by Matteo Bruni */
|
|
@@ -12,32 +12,36 @@ export class ByteStream {
|
|
|
12
12
|
return this.data[this.pos++];
|
|
13
13
|
}
|
|
14
14
|
nextTwoBytes() {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
const increment = 2, previous = 1, shift = 8;
|
|
16
|
+
this.pos += increment;
|
|
17
|
+
return this.data[this.pos - increment] + (this.data[this.pos - previous] << shift);
|
|
17
18
|
}
|
|
18
19
|
readSubBlocks() {
|
|
19
20
|
let blockString = "", size = 0;
|
|
21
|
+
const minCount = 0, emptySize = 0;
|
|
20
22
|
do {
|
|
21
23
|
size = this.data[this.pos++];
|
|
22
|
-
for (let count = size; --count >=
|
|
24
|
+
for (let count = size; --count >= minCount; blockString += String.fromCharCode(this.data[this.pos++])) {
|
|
23
25
|
}
|
|
24
|
-
} while (size !==
|
|
26
|
+
} while (size !== emptySize);
|
|
25
27
|
return blockString;
|
|
26
28
|
}
|
|
27
29
|
readSubBlocksBin() {
|
|
28
|
-
let size =
|
|
29
|
-
|
|
30
|
+
let size = this.data[this.pos], len = 0;
|
|
31
|
+
const emptySize = 0, increment = 1;
|
|
32
|
+
for (let offset = 0; size !== emptySize; offset += size + increment, size = this.data[this.pos + offset]) {
|
|
30
33
|
len += size;
|
|
31
34
|
}
|
|
32
35
|
const blockData = new Uint8Array(len);
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
size = this.data[this.pos++];
|
|
37
|
+
for (let i = 0; size !== emptySize; size = this.data[this.pos++]) {
|
|
38
|
+
for (let count = size; --count >= emptySize; blockData[i++] = this.data[this.pos++]) {
|
|
35
39
|
}
|
|
36
40
|
}
|
|
37
41
|
return blockData;
|
|
38
42
|
}
|
|
39
43
|
skipSubBlocks() {
|
|
40
|
-
for (; this.data[this.pos] !==
|
|
44
|
+
for (const increment = 1, noData = 0; this.data[this.pos] !== noData; this.pos += this.data[this.pos] + increment) {
|
|
41
45
|
}
|
|
42
46
|
this.pos++;
|
|
43
47
|
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { InterlaceOffsets, InterlaceSteps } from "./Constants.js";
|
|
2
2
|
import { ByteStream } from "./ByteStream.js";
|
|
3
|
+
const origin = {
|
|
4
|
+
x: 0,
|
|
5
|
+
y: 0,
|
|
6
|
+
}, defaultFrame = 0, half = 0.5, initialTime = 0, firstIndex = 0, defaultLoopCount = 0;
|
|
3
7
|
function parseColorTable(byteStream, count) {
|
|
4
8
|
const colors = [];
|
|
5
9
|
for (let i = 0; i < count; i++) {
|
|
@@ -12,7 +16,7 @@ function parseColorTable(byteStream, count) {
|
|
|
12
16
|
}
|
|
13
17
|
return colors;
|
|
14
18
|
}
|
|
15
|
-
|
|
19
|
+
function parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex) {
|
|
16
20
|
switch (byteStream.nextByte()) {
|
|
17
21
|
case 249: {
|
|
18
22
|
const frame = gif.frames[getFrameIndex(false)];
|
|
@@ -84,7 +88,10 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
84
88
|
}
|
|
85
89
|
const getColor = (index) => {
|
|
86
90
|
const { r, g, b } = (localColorTableFlag ? frame.localColorTable : gif.globalColorTable)[index];
|
|
87
|
-
|
|
91
|
+
if (index !== getTransparencyIndex(null)) {
|
|
92
|
+
return { r, g, b, a: 255 };
|
|
93
|
+
}
|
|
94
|
+
return { r, g, b, a: avgAlpha ? ~~((r + g + b) / 3) : 0 };
|
|
88
95
|
};
|
|
89
96
|
const image = (() => {
|
|
90
97
|
try {
|
|
@@ -110,7 +117,8 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
110
117
|
if (interlacedFlag) {
|
|
111
118
|
for (let code = 0, size = minCodeSize + 1, pos = 0, dic = [[0]], pass = 0; pass < 4; pass++) {
|
|
112
119
|
if (InterlaceOffsets[pass] < frame.height) {
|
|
113
|
-
|
|
120
|
+
let pixelPos = 0, lineIndex = 0, exit = false;
|
|
121
|
+
while (!exit) {
|
|
114
122
|
const last = code;
|
|
115
123
|
code = readBits(pos, size);
|
|
116
124
|
pos += size + 1;
|
|
@@ -128,8 +136,8 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
128
136
|
else if (last !== clearCode) {
|
|
129
137
|
dic.push(dic[last].concat(dic[code][0]));
|
|
130
138
|
}
|
|
131
|
-
for (
|
|
132
|
-
const { r, g, b, a } = getColor(
|
|
139
|
+
for (const item of dic[code]) {
|
|
140
|
+
const { r, g, b, a } = getColor(item);
|
|
133
141
|
image.data.set([r, g, b, a], InterlaceOffsets[pass] * frame.width +
|
|
134
142
|
InterlaceSteps[pass] * lineIndex +
|
|
135
143
|
(pixelPos % (frame.width * 4)));
|
|
@@ -142,7 +150,7 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
142
150
|
if (pixelPos === frame.width * 4 * (lineIndex + 1)) {
|
|
143
151
|
lineIndex++;
|
|
144
152
|
if (InterlaceOffsets[pass] + InterlaceSteps[pass] * lineIndex >= frame.height) {
|
|
145
|
-
|
|
153
|
+
exit = true;
|
|
146
154
|
}
|
|
147
155
|
}
|
|
148
156
|
}
|
|
@@ -153,7 +161,9 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
153
161
|
frame.bitmap = await createImageBitmap(image);
|
|
154
162
|
}
|
|
155
163
|
else {
|
|
156
|
-
|
|
164
|
+
let code = 0, size = minCodeSize + 1, pos = 0, pixelPos = -4, exit = false;
|
|
165
|
+
const dic = [[0]];
|
|
166
|
+
while (!exit) {
|
|
157
167
|
const last = code;
|
|
158
168
|
code = readBits(pos, size);
|
|
159
169
|
pos += size;
|
|
@@ -166,6 +176,7 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
166
176
|
}
|
|
167
177
|
else {
|
|
168
178
|
if (code === clearCode + 1) {
|
|
179
|
+
exit = true;
|
|
169
180
|
break;
|
|
170
181
|
}
|
|
171
182
|
if (code >= dic.length) {
|
|
@@ -174,8 +185,8 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
|
|
|
174
185
|
else if (last !== clearCode) {
|
|
175
186
|
dic.push(dic[last].concat(dic[code][0]));
|
|
176
187
|
}
|
|
177
|
-
for (
|
|
178
|
-
const { r, g, b, a } = getColor(
|
|
188
|
+
for (const item of dic[code]) {
|
|
189
|
+
const { r, g, b, a } = getColor(item);
|
|
179
190
|
image.data.set([r, g, b, a], (pixelPos += 4));
|
|
180
191
|
}
|
|
181
192
|
if (dic.length >= 1 << size && size < 0xc) {
|
|
@@ -196,7 +207,7 @@ async function parseBlock(byteStream, gif, avgAlpha, getFrameIndex, getTranspare
|
|
|
196
207
|
await parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, progressCallback);
|
|
197
208
|
break;
|
|
198
209
|
case 33:
|
|
199
|
-
|
|
210
|
+
parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex);
|
|
200
211
|
break;
|
|
201
212
|
default:
|
|
202
213
|
throw new EvalError("undefined block found");
|
|
@@ -322,3 +333,95 @@ export async function decodeGIF(gifURL, progressCallback, avgAlpha) {
|
|
|
322
333
|
throw error;
|
|
323
334
|
}
|
|
324
335
|
}
|
|
336
|
+
export function drawGif(data) {
|
|
337
|
+
const { context, radius, particle, delta } = data, image = particle.image;
|
|
338
|
+
if (!image?.gifData || !image.gif) {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
const offscreenCanvas = new OffscreenCanvas(image.gifData.width, image.gifData.height), offscreenContext = offscreenCanvas.getContext("2d");
|
|
342
|
+
if (!offscreenContext) {
|
|
343
|
+
throw new Error("could not create offscreen canvas context");
|
|
344
|
+
}
|
|
345
|
+
offscreenContext.imageSmoothingQuality = "low";
|
|
346
|
+
offscreenContext.imageSmoothingEnabled = false;
|
|
347
|
+
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
348
|
+
if (particle.gifLoopCount === undefined) {
|
|
349
|
+
particle.gifLoopCount = image.gifLoopCount ?? defaultLoopCount;
|
|
350
|
+
}
|
|
351
|
+
let frameIndex = particle.gifFrame ?? defaultFrame;
|
|
352
|
+
const pos = { x: -image.gifData.width * half, y: -image.gifData.height * half }, frame = image.gifData.frames[frameIndex];
|
|
353
|
+
if (particle.gifTime === undefined) {
|
|
354
|
+
particle.gifTime = initialTime;
|
|
355
|
+
}
|
|
356
|
+
if (!frame.bitmap) {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
context.scale(radius / image.gifData.width, radius / image.gifData.height);
|
|
360
|
+
switch (frame.disposalMethod) {
|
|
361
|
+
case 4:
|
|
362
|
+
case 5:
|
|
363
|
+
case 6:
|
|
364
|
+
case 7:
|
|
365
|
+
case 0:
|
|
366
|
+
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
367
|
+
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
368
|
+
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
369
|
+
break;
|
|
370
|
+
case 1:
|
|
371
|
+
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
372
|
+
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
373
|
+
break;
|
|
374
|
+
case 2:
|
|
375
|
+
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
376
|
+
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
377
|
+
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
378
|
+
if (!image.gifData.globalColorTable.length) {
|
|
379
|
+
offscreenContext.putImageData(image.gifData.frames[firstIndex].image, pos.x + frame.left, pos.y + frame.top);
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
offscreenContext.putImageData(image.gifData.backgroundImage, pos.x, pos.y);
|
|
383
|
+
}
|
|
384
|
+
break;
|
|
385
|
+
case 3:
|
|
386
|
+
{
|
|
387
|
+
const previousImageData = offscreenContext.getImageData(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
388
|
+
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
389
|
+
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
390
|
+
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
391
|
+
offscreenContext.putImageData(previousImageData, origin.x, origin.y);
|
|
392
|
+
}
|
|
393
|
+
break;
|
|
394
|
+
}
|
|
395
|
+
particle.gifTime += delta.value;
|
|
396
|
+
if (particle.gifTime > frame.delayTime) {
|
|
397
|
+
particle.gifTime -= frame.delayTime;
|
|
398
|
+
if (++frameIndex >= image.gifData.frames.length) {
|
|
399
|
+
if (--particle.gifLoopCount <= defaultLoopCount) {
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
frameIndex = firstIndex;
|
|
403
|
+
offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
|
|
404
|
+
}
|
|
405
|
+
particle.gifFrame = frameIndex;
|
|
406
|
+
}
|
|
407
|
+
context.scale(image.gifData.width / radius, image.gifData.height / radius);
|
|
408
|
+
}
|
|
409
|
+
export async function loadGifImage(image) {
|
|
410
|
+
if (image.type !== "gif") {
|
|
411
|
+
const { loadImage } = await import("../Utils.js");
|
|
412
|
+
await loadImage(image);
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
image.loading = true;
|
|
416
|
+
try {
|
|
417
|
+
image.gifData = await decodeGIF(image.source);
|
|
418
|
+
image.gifLoopCount = getGIFLoopAmount(image.gifData) ?? defaultLoopCount;
|
|
419
|
+
if (!image.gifLoopCount) {
|
|
420
|
+
image.gifLoopCount = Infinity;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
catch {
|
|
424
|
+
image.error = true;
|
|
425
|
+
}
|
|
426
|
+
image.loading = false;
|
|
427
|
+
}
|
package/browser/ImageDrawer.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { errorPrefix } from "@tsparticles/engine";
|
|
2
|
-
|
|
2
|
+
const double = 2, defaultAlpha = 1, sides = 12, defaultRatio = 1;
|
|
3
3
|
export class ImageDrawer {
|
|
4
4
|
constructor(engine) {
|
|
5
5
|
this.loadImageShape = async (imageShape) => {
|
|
@@ -21,92 +21,27 @@ export class ImageDrawer {
|
|
|
21
21
|
}
|
|
22
22
|
this._engine.images.push(image);
|
|
23
23
|
}
|
|
24
|
-
draw(data) {
|
|
25
|
-
const { context, radius, particle, opacity
|
|
24
|
+
async draw(data) {
|
|
25
|
+
const { context, radius, particle, opacity } = data, image = particle.image, element = image?.element;
|
|
26
26
|
if (!image) {
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
29
|
context.globalAlpha = opacity;
|
|
30
30
|
if (image.gif && image.gifData) {
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
throw new Error("could not create offscreen canvas context");
|
|
34
|
-
}
|
|
35
|
-
offscreenContext.imageSmoothingQuality = "low";
|
|
36
|
-
offscreenContext.imageSmoothingEnabled = false;
|
|
37
|
-
offscreenContext.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
|
|
38
|
-
if (particle.gifLoopCount === undefined) {
|
|
39
|
-
particle.gifLoopCount = image.gifLoopCount ?? 0;
|
|
40
|
-
}
|
|
41
|
-
let frameIndex = particle.gifFrame ?? 0;
|
|
42
|
-
const pos = { x: -image.gifData.width * 0.5, y: -image.gifData.height * 0.5 }, frame = image.gifData.frames[frameIndex];
|
|
43
|
-
if (particle.gifTime === undefined) {
|
|
44
|
-
particle.gifTime = 0;
|
|
45
|
-
}
|
|
46
|
-
if (!frame.bitmap) {
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
context.scale(radius / image.gifData.width, radius / image.gifData.height);
|
|
50
|
-
switch (frame.disposalMethod) {
|
|
51
|
-
case 4:
|
|
52
|
-
case 5:
|
|
53
|
-
case 6:
|
|
54
|
-
case 7:
|
|
55
|
-
case 0:
|
|
56
|
-
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
57
|
-
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
58
|
-
offscreenContext.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
|
|
59
|
-
break;
|
|
60
|
-
case 1:
|
|
61
|
-
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
62
|
-
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
63
|
-
break;
|
|
64
|
-
case 2:
|
|
65
|
-
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
66
|
-
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
67
|
-
offscreenContext.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
|
|
68
|
-
if (image.gifData.globalColorTable.length === 0) {
|
|
69
|
-
offscreenContext.putImageData(image.gifData.frames[0].image, pos.x + frame.left, pos.y + frame.top);
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
offscreenContext.putImageData(image.gifData.backgroundImage, pos.x, pos.y);
|
|
73
|
-
}
|
|
74
|
-
break;
|
|
75
|
-
case 3:
|
|
76
|
-
{
|
|
77
|
-
const previousImageData = offscreenContext.getImageData(0, 0, offscreenCanvas.width, offscreenCanvas.height);
|
|
78
|
-
offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
|
|
79
|
-
context.drawImage(offscreenCanvas, pos.x, pos.y);
|
|
80
|
-
offscreenContext.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
|
|
81
|
-
offscreenContext.putImageData(previousImageData, 0, 0);
|
|
82
|
-
}
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
85
|
-
particle.gifTime += delta.value;
|
|
86
|
-
if (particle.gifTime > frame.delayTime) {
|
|
87
|
-
particle.gifTime -= frame.delayTime;
|
|
88
|
-
if (++frameIndex >= image.gifData.frames.length) {
|
|
89
|
-
if (--particle.gifLoopCount <= 0) {
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
frameIndex = 0;
|
|
93
|
-
offscreenContext.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
|
|
94
|
-
}
|
|
95
|
-
particle.gifFrame = frameIndex;
|
|
96
|
-
}
|
|
97
|
-
context.scale(image.gifData.width / radius, image.gifData.height / radius);
|
|
31
|
+
const { drawGif } = await import("./GifUtils/Utils.js");
|
|
32
|
+
drawGif(data);
|
|
98
33
|
}
|
|
99
34
|
else if (element) {
|
|
100
35
|
const ratio = image.ratio, pos = {
|
|
101
36
|
x: -radius,
|
|
102
37
|
y: -radius,
|
|
103
|
-
}, diameter = radius *
|
|
38
|
+
}, diameter = radius * double;
|
|
104
39
|
context.drawImage(element, pos.x, pos.y, diameter, diameter / ratio);
|
|
105
40
|
}
|
|
106
|
-
context.globalAlpha =
|
|
41
|
+
context.globalAlpha = defaultAlpha;
|
|
107
42
|
}
|
|
108
43
|
getSidesCount() {
|
|
109
|
-
return
|
|
44
|
+
return sides;
|
|
110
45
|
}
|
|
111
46
|
async init(container) {
|
|
112
47
|
const options = container.actualOptions;
|
|
@@ -117,7 +52,7 @@ export class ImageDrawer {
|
|
|
117
52
|
await this._engine.loadImage(imageData);
|
|
118
53
|
}
|
|
119
54
|
}
|
|
120
|
-
loadShape(particle) {
|
|
55
|
+
async loadShape(particle) {
|
|
121
56
|
if (particle.shape !== "image" && particle.shape !== "images") {
|
|
122
57
|
return;
|
|
123
58
|
}
|
|
@@ -130,12 +65,11 @@ export class ImageDrawer {
|
|
|
130
65
|
}
|
|
131
66
|
const image = this._engine.images.find((t) => t.name === imageData.name || t.source === imageData.src);
|
|
132
67
|
if (!image) {
|
|
133
|
-
this.loadImageShape(imageData)
|
|
134
|
-
|
|
135
|
-
});
|
|
68
|
+
await this.loadImageShape(imageData);
|
|
69
|
+
await this.loadShape(particle);
|
|
136
70
|
}
|
|
137
71
|
}
|
|
138
|
-
particleInit(container, particle) {
|
|
72
|
+
async particleInit(container, particle) {
|
|
139
73
|
if (particle.shape !== "image" && particle.shape !== "images") {
|
|
140
74
|
return;
|
|
141
75
|
}
|
|
@@ -153,40 +87,41 @@ export class ImageDrawer {
|
|
|
153
87
|
const replaceColor = imageData.replaceColor ?? image.replaceColor;
|
|
154
88
|
if (image.loading) {
|
|
155
89
|
setTimeout(() => {
|
|
156
|
-
this.particleInit(container, particle);
|
|
90
|
+
void this.particleInit(container, particle);
|
|
157
91
|
});
|
|
158
92
|
return;
|
|
159
93
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
if (!imageRes.ratio) {
|
|
180
|
-
imageRes.ratio = 1;
|
|
181
|
-
}
|
|
182
|
-
const fill = imageData.fill ?? particle.shapeFill, close = imageData.close ?? particle.shapeClose, imageShape = {
|
|
183
|
-
image: imageRes,
|
|
184
|
-
fill,
|
|
185
|
-
close,
|
|
94
|
+
let imageRes;
|
|
95
|
+
if (image.svgData && color) {
|
|
96
|
+
const { replaceImageColor } = await import("./Utils.js");
|
|
97
|
+
imageRes = await replaceImageColor(image, imageData, color, particle);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
imageRes = {
|
|
101
|
+
color,
|
|
102
|
+
data: image,
|
|
103
|
+
element: image.element,
|
|
104
|
+
gif: image.gif,
|
|
105
|
+
gifData: image.gifData,
|
|
106
|
+
gifLoopCount: image.gifLoopCount,
|
|
107
|
+
loaded: true,
|
|
108
|
+
ratio: imageData.width && imageData.height
|
|
109
|
+
? imageData.width / imageData.height
|
|
110
|
+
: image.ratio ?? defaultRatio,
|
|
111
|
+
replaceColor: replaceColor,
|
|
112
|
+
source: imageData.src,
|
|
186
113
|
};
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
114
|
+
}
|
|
115
|
+
if (!imageRes.ratio) {
|
|
116
|
+
imageRes.ratio = 1;
|
|
117
|
+
}
|
|
118
|
+
const fill = imageData.fill ?? particle.shapeFill, close = imageData.close ?? particle.shapeClose, imageShape = {
|
|
119
|
+
image: imageRes,
|
|
120
|
+
fill,
|
|
121
|
+
close,
|
|
122
|
+
};
|
|
123
|
+
particle.image = imageShape.image;
|
|
124
|
+
particle.shapeFill = imageShape.fill;
|
|
125
|
+
particle.shapeClose = imageShape.close;
|
|
191
126
|
}
|
|
192
127
|
}
|
|
@@ -4,11 +4,12 @@ export class ImagePreloaderPlugin {
|
|
|
4
4
|
this.id = "imagePreloader";
|
|
5
5
|
this._engine = engine;
|
|
6
6
|
}
|
|
7
|
-
getPlugin() {
|
|
7
|
+
async getPlugin() {
|
|
8
|
+
await Promise.resolve();
|
|
8
9
|
return {};
|
|
9
10
|
}
|
|
10
11
|
loadOptions(options, source) {
|
|
11
|
-
if (!source
|
|
12
|
+
if (!source?.preload) {
|
|
12
13
|
return;
|
|
13
14
|
}
|
|
14
15
|
if (!options.preload) {
|
package/browser/Utils.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { errorPrefix, getLogger, getStyleFromHsl } from "@tsparticles/engine";
|
|
2
|
-
|
|
2
|
+
const stringStart = 0, defaultOpacity = 1;
|
|
3
3
|
const currentColorRegex = /(#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d.]+%?\))|currentcolor/gi;
|
|
4
4
|
function replaceColorSvg(imageShape, color, opacity) {
|
|
5
5
|
const { svgData } = imageShape;
|
|
@@ -11,7 +11,7 @@ function replaceColorSvg(imageShape, color, opacity) {
|
|
|
11
11
|
return svgData.replace(currentColorRegex, () => colorStyle);
|
|
12
12
|
}
|
|
13
13
|
const preFillIndex = svgData.indexOf(">");
|
|
14
|
-
return `${svgData.substring(
|
|
14
|
+
return `${svgData.substring(stringStart, preFillIndex)} fill="${colorStyle}"${svgData.substring(preFillIndex)}`;
|
|
15
15
|
}
|
|
16
16
|
export async function loadImage(image) {
|
|
17
17
|
return new Promise((resolve) => {
|
|
@@ -32,24 +32,6 @@ export async function loadImage(image) {
|
|
|
32
32
|
img.src = image.source;
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
|
-
export async function loadGifImage(image) {
|
|
36
|
-
if (image.type !== "gif") {
|
|
37
|
-
await loadImage(image);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
image.loading = true;
|
|
41
|
-
try {
|
|
42
|
-
image.gifData = await decodeGIF(image.source);
|
|
43
|
-
image.gifLoopCount = getGIFLoopAmount(image.gifData) ?? 0;
|
|
44
|
-
if (image.gifLoopCount === 0) {
|
|
45
|
-
image.gifLoopCount = Infinity;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
catch {
|
|
49
|
-
image.error = true;
|
|
50
|
-
}
|
|
51
|
-
image.loading = false;
|
|
52
|
-
}
|
|
53
35
|
export async function downloadSvgImage(image) {
|
|
54
36
|
if (image.type !== "svg") {
|
|
55
37
|
await loadImage(image);
|
|
@@ -67,7 +49,7 @@ export async function downloadSvgImage(image) {
|
|
|
67
49
|
image.loading = false;
|
|
68
50
|
}
|
|
69
51
|
export function replaceImageColor(image, imageData, color, particle) {
|
|
70
|
-
const svgColoredData = replaceColorSvg(image, color, particle.opacity?.value ??
|
|
52
|
+
const svgColoredData = replaceColorSvg(image, color, particle.opacity?.value ?? defaultOpacity), imageRes = {
|
|
71
53
|
color,
|
|
72
54
|
gif: imageData.gif,
|
|
73
55
|
data: {
|
|
@@ -87,7 +69,7 @@ export function replaceImageColor(image, imageData, color, particle) {
|
|
|
87
69
|
resolve(imageRes);
|
|
88
70
|
domUrl.revokeObjectURL(url);
|
|
89
71
|
});
|
|
90
|
-
|
|
72
|
+
const errorHandler = async () => {
|
|
91
73
|
domUrl.revokeObjectURL(url);
|
|
92
74
|
const img2 = {
|
|
93
75
|
...image,
|
|
@@ -98,7 +80,8 @@ export function replaceImageColor(image, imageData, color, particle) {
|
|
|
98
80
|
imageRes.loaded = true;
|
|
99
81
|
imageRes.element = img2.element;
|
|
100
82
|
resolve(imageRes);
|
|
101
|
-
}
|
|
83
|
+
};
|
|
84
|
+
img.addEventListener("error", () => void errorHandler());
|
|
102
85
|
img.src = url;
|
|
103
86
|
});
|
|
104
87
|
}
|
package/browser/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { downloadSvgImage,
|
|
2
|
-
import { ImageDrawer } from "./ImageDrawer.js";
|
|
3
|
-
import { ImagePreloaderPlugin } from "./ImagePreloader.js";
|
|
1
|
+
import { downloadSvgImage, loadImage } from "./Utils.js";
|
|
4
2
|
import { errorPrefix } from "@tsparticles/engine";
|
|
3
|
+
const extLength = 3;
|
|
5
4
|
function addLoadImageToEngine(engine) {
|
|
6
5
|
if (engine.loadImage) {
|
|
7
6
|
return;
|
|
@@ -21,14 +20,21 @@ function addLoadImageToEngine(engine) {
|
|
|
21
20
|
gif: data.gif ?? false,
|
|
22
21
|
name: data.name ?? data.src,
|
|
23
22
|
source: data.src,
|
|
24
|
-
type: data.src.substring(data.src.length -
|
|
23
|
+
type: data.src.substring(data.src.length - extLength),
|
|
25
24
|
error: false,
|
|
26
25
|
loading: true,
|
|
27
26
|
replaceColor: data.replaceColor,
|
|
28
27
|
ratio: data.width && data.height ? data.width / data.height : undefined,
|
|
29
28
|
};
|
|
30
29
|
engine.images.push(image);
|
|
31
|
-
|
|
30
|
+
let imageFunc;
|
|
31
|
+
if (data.gif) {
|
|
32
|
+
const { loadGifImage } = await import("./GifUtils/Utils.js");
|
|
33
|
+
imageFunc = loadGifImage;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
imageFunc = data.replaceColor ? downloadSvgImage : loadImage;
|
|
37
|
+
}
|
|
32
38
|
await imageFunc(image);
|
|
33
39
|
}
|
|
34
40
|
catch {
|
|
@@ -38,6 +44,7 @@ function addLoadImageToEngine(engine) {
|
|
|
38
44
|
}
|
|
39
45
|
export async function loadImageShape(engine, refresh = true) {
|
|
40
46
|
addLoadImageToEngine(engine);
|
|
47
|
+
const { ImagePreloaderPlugin } = await import("./ImagePreloader.js"), { ImageDrawer } = await import("./ImageDrawer.js");
|
|
41
48
|
const preloader = new ImagePreloaderPlugin(engine);
|
|
42
49
|
await engine.addPlugin(preloader, refresh);
|
|
43
50
|
await engine.addShape(["image", "images"], new ImageDrawer(engine), refresh);
|
|
@@ -15,32 +15,36 @@ class ByteStream {
|
|
|
15
15
|
return this.data[this.pos++];
|
|
16
16
|
}
|
|
17
17
|
nextTwoBytes() {
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
const increment = 2, previous = 1, shift = 8;
|
|
19
|
+
this.pos += increment;
|
|
20
|
+
return this.data[this.pos - increment] + (this.data[this.pos - previous] << shift);
|
|
20
21
|
}
|
|
21
22
|
readSubBlocks() {
|
|
22
23
|
let blockString = "", size = 0;
|
|
24
|
+
const minCount = 0, emptySize = 0;
|
|
23
25
|
do {
|
|
24
26
|
size = this.data[this.pos++];
|
|
25
|
-
for (let count = size; --count >=
|
|
27
|
+
for (let count = size; --count >= minCount; blockString += String.fromCharCode(this.data[this.pos++])) {
|
|
26
28
|
}
|
|
27
|
-
} while (size !==
|
|
29
|
+
} while (size !== emptySize);
|
|
28
30
|
return blockString;
|
|
29
31
|
}
|
|
30
32
|
readSubBlocksBin() {
|
|
31
|
-
let size =
|
|
32
|
-
|
|
33
|
+
let size = this.data[this.pos], len = 0;
|
|
34
|
+
const emptySize = 0, increment = 1;
|
|
35
|
+
for (let offset = 0; size !== emptySize; offset += size + increment, size = this.data[this.pos + offset]) {
|
|
33
36
|
len += size;
|
|
34
37
|
}
|
|
35
38
|
const blockData = new Uint8Array(len);
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
size = this.data[this.pos++];
|
|
40
|
+
for (let i = 0; size !== emptySize; size = this.data[this.pos++]) {
|
|
41
|
+
for (let count = size; --count >= emptySize; blockData[i++] = this.data[this.pos++]) {
|
|
38
42
|
}
|
|
39
43
|
}
|
|
40
44
|
return blockData;
|
|
41
45
|
}
|
|
42
46
|
skipSubBlocks() {
|
|
43
|
-
for (; this.data[this.pos] !==
|
|
47
|
+
for (const increment = 1, noData = 0; this.data[this.pos] !== noData; this.pos += this.data[this.pos] + increment) {
|
|
44
48
|
}
|
|
45
49
|
this.pos++;
|
|
46
50
|
}
|