litecanvas 0.201.0 → 0.203.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/dist.dev.js CHANGED
@@ -115,7 +115,7 @@
115
115
  var assert = (condition, message = "Assertion failed") => {
116
116
  if (!condition) throw new Error("[litecanvas] " + message);
117
117
  };
118
- var version = "0.201.0";
118
+ var version = "0.203.0";
119
119
  function litecanvas(settings = {}) {
120
120
  const root = window,
121
121
  math = Math,
@@ -192,11 +192,11 @@
192
192
  return start + t * (end - start);
193
193
  },
194
194
  deg2rad: (degs) => {
195
- DEV: assert(isNumber(degs), "deg2rad: 1st param must be a number");
195
+ DEV: assert(isNumber(degs), "deg2rad() 1st param must be a number");
196
196
  return (math.PI / 180) * degs;
197
197
  },
198
198
  rad2deg: (rads) => {
199
- DEV: assert(isNumber(rads), "rad2deg: 1st param must be a number");
199
+ DEV: assert(isNumber(rads), "rad2deg() 1st param must be a number");
200
200
  return (180 / math.PI) * rads;
201
201
  },
202
202
  round: (n, precision = 0) => {
@@ -646,6 +646,10 @@
646
646
  }
647
647
  },
648
648
  textgap(value) {
649
+ DEV: assert(
650
+ isNumber(value),
651
+ loggerPrefix + "textgap() 1st param must be a number",
652
+ );
649
653
  _fontLineHeight = value;
650
654
  },
651
655
  textfont(family) {
@@ -740,8 +744,10 @@
740
744
  loggerPrefix + "paint() 3rd param must be a function",
741
745
  );
742
746
  DEV: assert(
743
- (options && null == options.scale) || isNumber(options.scale),
744
- loggerPrefix + "paint() 4th param (options.scale) must be a number",
747
+ (options && null == options.scale) ||
748
+ (isNumber(options.scale) && options.scale > 0),
749
+ loggerPrefix +
750
+ "paint() 4th param (options.scale) must be a positive number",
745
751
  );
746
752
  DEV: assert(
747
753
  (options && null == options.canvas) ||
@@ -761,6 +767,13 @@
761
767
  return canvas.transferToImageBitmap();
762
768
  },
763
769
  ctx(context) {
770
+ DEV: assert(
771
+ null == context ||
772
+ context instanceof CanvasRenderingContext2D ||
773
+ context instanceof OffscreenCanvasRenderingContext2D,
774
+ loggerPrefix +
775
+ "ctx() 1st param must be an [Offscreen]CanvasRenderingContext2D",
776
+ );
764
777
  if (context) {
765
778
  _ctx = context;
766
779
  }
@@ -783,16 +796,16 @@
783
796
  );
784
797
  _ctx.translate(~~x, ~~y);
785
798
  },
786
- scale(x, y) {
799
+ scale(x, y = x) {
787
800
  DEV: assert(
788
801
  isNumber(x),
789
802
  loggerPrefix + "scale() 1st param must be a number",
790
803
  );
791
804
  DEV: assert(
792
- null == y || isNumber(y),
805
+ isNumber(y),
793
806
  loggerPrefix + "scale() 2nd param must be a number",
794
807
  );
795
- _ctx.scale(x, y || x);
808
+ _ctx.scale(x, y);
796
809
  },
797
810
  rotate(radians) {
798
811
  DEV: assert(
@@ -827,7 +840,7 @@
827
840
  clip(callback) {
828
841
  DEV: assert(
829
842
  "function" === typeof callback,
830
- loggerPrefix + "clip() 1st param must be a function",
843
+ loggerPrefix + "clip() 1st param must be a function (ctx) => void",
831
844
  );
832
845
  beginPath(_ctx);
833
846
  callback(_ctx);
@@ -872,7 +885,8 @@
872
885
  use(callback, config = {}) {
873
886
  DEV: assert(
874
887
  "function" === typeof callback,
875
- loggerPrefix + "use() 1st param must be a function",
888
+ loggerPrefix +
889
+ "use() 1st param must be a function (instance, config) => any",
876
890
  );
877
891
  DEV: assert(
878
892
  "object" === typeof config,
@@ -921,6 +935,7 @@
921
935
  triggerEvent(eventName, arg1, arg2, arg3, arg4);
922
936
  triggerEvent("after:" + eventName, arg1, arg2, arg3, arg4);
923
937
  }
938
+ return arg1;
924
939
  },
925
940
  pal(colors, textColor = 3) {
926
941
  DEV: assert(
@@ -983,8 +998,8 @@
983
998
  },
984
999
  stat(index) {
985
1000
  DEV: assert(
986
- isNumber(index) || "string" === typeof index,
987
- loggerPrefix + "stat() 1st param must be a number or string",
1001
+ isNumber(index),
1002
+ loggerPrefix + "stat() 1st param must be a number",
988
1003
  );
989
1004
  const internals = [
990
1005
  settings,
@@ -1002,9 +1017,13 @@
1002
1017
  _colorPaletteState,
1003
1018
  _fontLineHeight,
1004
1019
  ];
1005
- const data = { index, value: internals[index] };
1006
- instance.emit("stat", data);
1007
- return data.value;
1020
+ DEV: assert(
1021
+ index >= 0 && index < internals.length,
1022
+ loggerPrefix +
1023
+ "stat() 1st param must be a number between 0 and " +
1024
+ (internals.length - 1),
1025
+ );
1026
+ return internals[index];
1008
1027
  },
1009
1028
  pause() {
1010
1029
  _paused = true;
@@ -1027,7 +1046,7 @@
1027
1046
  return _paused;
1028
1047
  },
1029
1048
  quit() {
1030
- instance.emit("quit");
1049
+ instance.emit("shutdown");
1031
1050
  instance.pause();
1032
1051
  _initialized = false;
1033
1052
  _eventListeners = {};
@@ -1323,11 +1342,7 @@
1323
1342
  instance.listen(eventName, settings.loop[eventName]);
1324
1343
  }
1325
1344
  }
1326
- if ("loading" === document.readyState) {
1327
- on(root, "DOMContentLoaded", () => raf(init));
1328
- } else {
1329
- _rafid = raf(init);
1330
- }
1345
+ _rafid = raf(init);
1331
1346
  return instance;
1332
1347
  }
1333
1348
  window.litecanvas = litecanvas;
package/dist/dist.js CHANGED
@@ -363,8 +363,8 @@
363
363
  translate(x, y) {
364
364
  _ctx.translate(~~x, ~~y);
365
365
  },
366
- scale(x, y) {
367
- _ctx.scale(x, y || x);
366
+ scale(x, y = x) {
367
+ _ctx.scale(x, y);
368
368
  },
369
369
  rotate(radians) {
370
370
  _ctx.rotate(radians);
@@ -429,6 +429,7 @@
429
429
  triggerEvent(eventName, arg1, arg2, arg3, arg4);
430
430
  triggerEvent("after:" + eventName, arg1, arg2, arg3, arg4);
431
431
  }
432
+ return arg1;
432
433
  },
433
434
  pal(colors, textColor = 3) {
434
435
  _colorPalette = colors || defaultPalette;
@@ -471,9 +472,7 @@
471
472
  _colorPaletteState,
472
473
  _fontLineHeight,
473
474
  ];
474
- const data = { index, value: internals[index] };
475
- instance.emit("stat", data);
476
- return data.value;
475
+ return internals[index];
477
476
  },
478
477
  pause() {
479
478
  _paused = true;
@@ -491,7 +490,7 @@
491
490
  return _paused;
492
491
  },
493
492
  quit() {
494
- instance.emit("quit");
493
+ instance.emit("shutdown");
495
494
  instance.pause();
496
495
  _initialized = false;
497
496
  _eventListeners = {};
@@ -734,11 +733,7 @@
734
733
  instance.listen(eventName, settings.loop[eventName]);
735
734
  }
736
735
  }
737
- if ("loading" === document.readyState) {
738
- on(root, "DOMContentLoaded", () => raf(init));
739
- } else {
740
- _rafid = raf(init);
741
- }
736
+ _rafid = raf(init);
742
737
  return instance;
743
738
  }
744
739
  window.litecanvas = litecanvas;
package/dist/dist.min.js CHANGED
@@ -1 +1 @@
1
- (()=>{var e=["#211e20","#555568","#a0a08b","#e9efec"];window.litecanvas=function(t={}){let a,l=window,n=Math,i=performance,o=2*n.PI,r=requestAnimationFrame,s=[],f=(e,t,a)=>{e.addEventListener(t,a,!1),s.push(()=>e.removeEventListener(t,a,!1))},d=(a=new AudioContext,l.zzfxV=1,(e=1,t=.05,n=220,i=0,o=0,r=.1,s=0,f=1,d=0,c=0,u=0,p=0,h=0,m=0,g=0,v=0,w=0,x=1,y=0,b=0,k=0)=>{let E=Math,P=2*E.PI,T=d*=500*P/44100/44100,z=n*=(1-t+2*t*E.random(t=[]))*P/44100,C=0,I=0,L=0,D=1,S=0,A=0,M=0,H=k<0?-1:1,N=P*H*k*2/44100,W=E.cos(N),q=E.sin,B=q(N)/4,O=1+B,V=-2*W/O,R=(1-B)/O,F=(1+H*W)/2/O,G=-(H+W)/O,X=0,Y=0,$=0,j=0;for(i=44100*i+9,y*=44100,o*=44100,r*=44100,w*=44100,c*=500*P/85766121e6,g*=P/44100,u*=P/44100,p*=44100,h=44100*h|0,e*=.3*l.zzfxV,H=i+y+o+r+w|0;L<H;t[L++]=M*e)++A%(100*v|0)||(M=s?1<s?2<s?3<s?q(C*C):E.max(E.min(E.tan(C),1),-1):1-(2*C/P%2+2)%2:1-4*E.abs(E.round(C/P)-C/P):q(C),M=(h?1-b+b*q(P*L/h):1)*(M<0?-1:1)*E.abs(M)**f*(L<i?L/i:L<i+y?1-(L-i)/y*(1-x):L<i+y+o?x:L<H-w?(H-L-w)/r*x:0),M=w?M/2+(w>L?0:(L<H-w?1:(H-L)/w)*t[L-w|0]/2/e):M,k&&(M=j=F*X+G*(X=Y)+F*(Y=M)-R*$-V*($=j))),C+=(N=(n+=d+=c)*E.cos(g*I++))+N*m*q(L**5),D&&++D>p&&(n+=u,z+=u,D=0),!h||++S%h||(n=z,d=T,D=D||1);(e=a.createBuffer(1,H,44100)).getChannelData(0).set(t),(n=a.createBufferSource()).buffer=e,n.connect(a.destination),n.start()});t=Object.assign({width:null,height:null,autoscale:!0,canvas:null,global:!0,loop:null,tapEvents:!0,keyboardEvents:!0},t);let c=!1,u=!0,p,h=1,m,g=.5,v=1,w,x=1e3/60,y,b,k=3,E="sans-serif",P=20,T=1.2,z=Date.now(),C=e,I=[],L=[.5,0,1750,,,.3,1,,,,600,.1],D={},S={W:0,H:0,T:0,MX:-1,MY:-1,TWO_PI:o,HALF_PI:o/4,lerp:(e,t,a)=>e+a*(t-e),deg2rad:e=>n.PI/180*e,rad2deg:e=>180/n.PI*e,round:(e,t=0)=>{if(!t)return n.round(e);let a=10**t;return n.round(e*a)/a},clamp:(e,t,a)=>e<t?t:e>a?a:e,dist:(e,t,a,l)=>n.hypot(a-e,l-t),wrap:(e,t,a)=>e-(a-t)*n.floor((e-t)/(a-t)),map(e,t,a,l,n,i){let o=(e-t)/(a-t)*(n-l)+l;return i?S.clamp(o,l,n):o},norm:(e,t,a)=>S.map(e,t,a,0,1),rand:(e=0,t=1)=>(z=(1664525*z+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>~~S.rand(e,t+1),rseed(e){z=~~e},cls(e){null==e?m.clearRect(0,0,S.W,S.H):S.rectfill(0,0,S.W,S.H,e)},rect(e,t,a,l,n,i){m.beginPath(),m[i?"roundRect":"rect"](~~e-g,~~t-g,~~a+2*g,~~l+2*g,i),S.stroke(n)},rectfill(e,t,a,l,n,i){m.beginPath(),m[i?"roundRect":"rect"](~~e,~~t,~~a,~~l,i),S.fill(n)},circ(e,t,a,l){m.beginPath(),m.arc(~~e,~~t,~~a,0,o),S.stroke(l)},circfill(e,t,a,l){m.beginPath(),m.arc(~~e,~~t,~~a,0,o),S.fill(l)},oval(e,t,a,l,n){m.beginPath(),m.ellipse(~~e,~~t,~~a,~~l,0,0,o),S.stroke(n)},ovalfill(e,t,a,l,n){m.beginPath(),m.ellipse(~~e,~~t,~~a,~~l,0,0,o),S.fill(n)},shape(e){m.beginPath();for(let t=0;t<e.length;t+=2)0===t?m.moveTo(~~e[t],~~e[t+1]):m.lineTo(~~e[t],~~e[t+1]);m.lineTo(~~e[0],~~e[1])},line(e,t,a,l,n){m.beginPath();let i=.5*(0!==g&&~~e==~~a),o=.5*(0!==g&&~~t==~~l);m.moveTo(~~e+i,~~t+o),m.lineTo(~~a+i,~~l+o),S.stroke(n)},linewidth(e){m.lineWidth=~~e,g=.5*(0!=~~e%2)},linedash(e,t=0){m.setLineDash(e),m.lineDashOffset=t},text(e,t,a,l=k,n="normal"){m.font=`${n} ${P}px ${E}`,m.fillStyle=W(l);let i=(""+a).split("\n");for(let a=0;a<i.length;a++)m.fillText(i[a],~~e,~~t+P*T*a)},textgap(e){T=e},textfont(e){E=e},textsize(e){P=e},textalign(e,t){e&&(m.textAlign=e),t&&(m.textBaseline=t)},image(e,t,a){m.drawImage(a,~~e,~~t)},spr(e,t,a){let l=a.trim().split("\n");for(let a=0;a<l.length;a++){let n=l[a].trim();for(let l=0;l<n.length;l++){let i=n[l];"."!==i&&" "!==i&&S.rectfill(e+l,t+a,1,1,parseInt(i,36)||0)}}},paint(e,t,a,l={}){let n=l.canvas||new OffscreenCanvas(1,1),i=l.scale||1,o=m;return n.width=e*i,n.height=t*i,(m=n.getContext("2d")).scale(i,i),a(m),m=o,n.transferToImageBitmap()},ctx:e=>(e&&(m=e),m),push(){m.save()},pop(){m.restore()},translate(e,t){m.translate(~~e,~~t)},scale(e,t){m.scale(e,t||e)},rotate(e){m.rotate(e)},alpha(e){m.globalAlpha=S.clamp(e,0,1)},fill(e){m.fillStyle=W(e),m.fill()},stroke(e){m.strokeStyle=W(e),m.stroke()},clip(e){m.beginPath(),e(m),m.clip()},sfx:(e,t=0,a=1)=>!!l.zzfxV&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e=e||L,(0!==t||1!==a)&&((e=e.slice())[0]=a*(e[0]||1),e[10]=~~e[10]+t),d.apply(0,e),e),volume(e){l.zzfxV=e},canvas:()=>p,use(e,t={}){var a=e,l=t;let n=a(S,l);for(let e in n)S.def(e,n[e])},listen:(e,t)=>{D[e=e.toLowerCase()]=D[e]||new Set,D[e].add(t)},unlisten:(e,t)=>{D[e=e.toLowerCase()]&&D[e].delete(t)},emit(e,a,n,i,o){c&&(N("before:"+(e=e.toLowerCase()),a,n,i,o),t.loop||"function"!=typeof l[e]||l[e](a,n,i,o),N(e,a,n,i,o),N("after:"+e,a,n,i,o))},pal(t,a=3){C=t||e,I=[],k=a},palc(e,t){null==e?I=[]:I[e]=t},def(e,a){S[e]=a,t.global&&(l[e]=a)},timescale(e){v=e},framerate(e){x=1e3/~~e},stat(e){let a={index:e,value:[t,c,x/1e3,h,D,C,L,v,l.zzfxV,z,P,E,I,T][e]};return S.emit("stat",a),a.value},pause(){u=!0,cancelAnimationFrame(b)},resume(){c&&u&&(u=!1,y=x,w=i.now(),b=r(M))},paused:()=>u,quit(){for(let e of(S.emit("quit"),S.pause(),c=!1,D={},s))e();if(t.global){for(let e in S)delete l[e];delete l.ENGINE}}};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp".split(","))S[e]=n[e];function A(){if(t.autoscale&&f(l,"resize",H),t.tapEvents){let e=e=>[(e.pageX-p.offsetLeft)/h,(e.pageY-p.offsetTop)/h],t=new Map,a=(e,a,l)=>{let n={x:a,y:l,xi:a,yi:l,t:i.now()};return t.set(e,n),n},n=(e,l,n)=>{let i=t.get(e)||a(e);i.x=l,i.y=n},o=e=>e&&i.now()-e.t<=300,r=!1;f(p,"mousedown",t=>{if(0===t.button){t.preventDefault();let[l,n]=e(t);S.emit("tap",l,n,0),a(0,l,n),r=!0}}),f(p,"mouseup",a=>{if(0===a.button){a.preventDefault();let l=t.get(0),[n,i]=e(a);o(l)&&S.emit("tapped",l.xi,l.yi,0),S.emit("untap",n,i,0),t.delete(0),r=!1}}),f(l,"mousemove",t=>{t.preventDefault();let[a,l]=e(t);S.def("MX",a),S.def("MY",l),r&&(S.emit("tapping",a,l,0),n(0,a,l))}),f(p,"touchstart",t=>{for(let l of(t.preventDefault(),t.changedTouches)){let[t,n]=e(l);S.emit("tap",t,n,l.identifier+1),a(l.identifier+1,t,n)}}),f(p,"touchmove",t=>{for(let a of(t.preventDefault(),t.changedTouches)){let[t,l]=e(a);S.emit("tapping",t,l,a.identifier+1),n(a.identifier+1,t,l)}});let s=e=>{e.preventDefault();let a=[];if(e.targetTouches.length>0)for(let t of e.targetTouches)a.push(t.identifier+1);for(let[e,l]of t)a.includes(e)||(o(l)&&S.emit("tapped",l.xi,l.yi,e),S.emit("untap",l.x,l.y,e),t.delete(e))};f(p,"touchend",s),f(p,"touchcancel",s),f(l,"blur",()=>{for(let[e,a]of(r=!1,t))S.emit("untap",a.x,a.y,e),t.delete(e)})}if(t.keyboardEvents){let e=new Set,t=new Set,a=(e,t="")=>(t=t.toLowerCase())?e.has("space"===t?" ":t):e.size>0,n="";f(l,"keydown",a=>{let l=a.key.toLowerCase();e.has(l)||(e.add(l),t.add(l),n=" "===l?"space":l)}),f(l,"keyup",t=>{e.delete(t.key.toLowerCase())}),f(l,"blur",()=>e.clear()),S.listen("after:update",()=>t.clear()),S.def("iskeydown",t=>a(e,t)),S.def("iskeypressed",e=>a(t,e)),S.def("lastkey",()=>n)}c=!0,S.resume(),S.emit("init",S)}function M(){b=r(M);let e=i.now(),t=0,a=e-w;for(w=e,y+=a<100?a:x;y>=x;){t++,y-=x;let e=x/1e3*v;S.emit("update",e,t),S.def("T",S.T+e)}t&&(S.emit("draw",m),t>1&&(y=0))}function H(){let e=t.width>0?t.width:innerWidth,a=t.width>0?t.height||t.width:innerHeight;if(S.def("W",e),S.def("H",a),p.width=e,p.height=a,t.autoscale){let l=+t.autoscale;p.style.display||(p.style.display="block",p.style.margin="auto"),h=n.min(innerWidth/e,innerHeight/a),h=l>1&&h>l?l:h,p.style.width=e*h+"px",p.style.height=a*h+"px"}m.imageSmoothingEnabled=!1,S.textalign("start","top"),S.emit("resized",h)}function N(e,t,a,l,n){if(D[e])for(let i of D[e])i(t,a,l,n)}function W(e){return C[~~(I[e]??e)%C.length]}if(t.global){if(l.ENGINE)throw Error("only one global litecanvas is allowed");Object.assign(l,S),l.ENGINE=S}if(m=(p=(p="string"==typeof t.canvas?document.querySelector(t.canvas):t.canvas)||document.createElement("canvas")).getContext("2d"),f(p,"click",()=>focus()),H(),p.parentNode||document.body.appendChild(p),p.style.imageRendering="pixelated",p.oncontextmenu=()=>!1,t.loop)for(let e in t.loop)t.loop[e]&&S.listen(e,t.loop[e]);return"loading"===document.readyState?f(l,"DOMContentLoaded",()=>r(A)):b=r(A),S}})();
1
+ (()=>{var e=["#211e20","#555568","#a0a08b","#e9efec"];window.litecanvas=function(t={}){let l,a=window,n=Math,i=performance,o=2*n.PI,r=requestAnimationFrame,s=[],f=(e,t,l)=>{e.addEventListener(t,l,!1),s.push(()=>e.removeEventListener(t,l,!1))},c=(l=new AudioContext,a.zzfxV=1,(e=1,t=.05,n=220,i=0,o=0,r=.1,s=0,f=1,c=0,d=0,p=0,u=0,h=0,g=0,m=0,w=0,v=0,x=1,y=0,b=0,k=0)=>{let E=Math,P=2*E.PI,T=c*=500*P/44100/44100,z=n*=(1-t+2*t*E.random(t=[]))*P/44100,C=0,I=0,L=0,D=1,A=0,S=0,H=0,M=k<0?-1:1,N=P*M*k*2/44100,W=E.cos(N),B=E.sin,V=B(N)/4,q=1+V,O=-2*W/q,R=(1-V)/q,F=(1+M*W)/2/q,G=-(M+W)/q,X=0,Y=0,$=0,j=0;for(i=44100*i+9,y*=44100,o*=44100,r*=44100,v*=44100,d*=500*P/85766121e6,m*=P/44100,p*=P/44100,u*=44100,h=44100*h|0,e*=.3*a.zzfxV,M=i+y+o+r+v|0;L<M;t[L++]=H*e)++S%(100*w|0)||(H=s?1<s?2<s?3<s?B(C*C):E.max(E.min(E.tan(C),1),-1):1-(2*C/P%2+2)%2:1-4*E.abs(E.round(C/P)-C/P):B(C),H=(h?1-b+b*B(P*L/h):1)*(H<0?-1:1)*E.abs(H)**f*(L<i?L/i:L<i+y?1-(L-i)/y*(1-x):L<i+y+o?x:L<M-v?(M-L-v)/r*x:0),H=v?H/2+(v>L?0:(L<M-v?1:(M-L)/v)*t[L-v|0]/2/e):H,k&&(H=j=F*X+G*(X=Y)+F*(Y=H)-R*$-O*($=j))),C+=(N=(n+=c+=d)*E.cos(m*I++))+N*g*B(L**5),D&&++D>u&&(n+=p,z+=p,D=0),!h||++A%h||(n=z,c=T,D=D||1);(e=l.createBuffer(1,M,44100)).getChannelData(0).set(t),(n=l.createBufferSource()).buffer=e,n.connect(l.destination),n.start()});t=Object.assign({width:null,height:null,autoscale:!0,canvas:null,global:!0,loop:null,tapEvents:!0,keyboardEvents:!0},t);let d=!1,p=!0,u,h=1,g,m=.5,w=1,v,x=1e3/60,y,b,k=3,E="sans-serif",P=20,T=1.2,z=Date.now(),C=e,I=[],L=[.5,0,1750,,,.3,1,,,,600,.1],D={},A={W:0,H:0,T:0,MX:-1,MY:-1,TWO_PI:o,HALF_PI:o/4,lerp:(e,t,l)=>e+l*(t-e),deg2rad:e=>n.PI/180*e,rad2deg:e=>180/n.PI*e,round:(e,t=0)=>{if(!t)return n.round(e);let l=10**t;return n.round(e*l)/l},clamp:(e,t,l)=>e<t?t:e>l?l:e,dist:(e,t,l,a)=>n.hypot(l-e,a-t),wrap:(e,t,l)=>e-(l-t)*n.floor((e-t)/(l-t)),map(e,t,l,a,n,i){let o=(e-t)/(l-t)*(n-a)+a;return i?A.clamp(o,a,n):o},norm:(e,t,l)=>A.map(e,t,l,0,1),rand:(e=0,t=1)=>(z=(1664525*z+0x3c6ef35f)%0x100000000)/0x100000000*(t-e)+e,randi:(e=0,t=1)=>~~A.rand(e,t+1),rseed(e){z=~~e},cls(e){null==e?g.clearRect(0,0,A.W,A.H):A.rectfill(0,0,A.W,A.H,e)},rect(e,t,l,a,n,i){g.beginPath(),g[i?"roundRect":"rect"](~~e-m,~~t-m,~~l+2*m,~~a+2*m,i),A.stroke(n)},rectfill(e,t,l,a,n,i){g.beginPath(),g[i?"roundRect":"rect"](~~e,~~t,~~l,~~a,i),A.fill(n)},circ(e,t,l,a){g.beginPath(),g.arc(~~e,~~t,~~l,0,o),A.stroke(a)},circfill(e,t,l,a){g.beginPath(),g.arc(~~e,~~t,~~l,0,o),A.fill(a)},oval(e,t,l,a,n){g.beginPath(),g.ellipse(~~e,~~t,~~l,~~a,0,0,o),A.stroke(n)},ovalfill(e,t,l,a,n){g.beginPath(),g.ellipse(~~e,~~t,~~l,~~a,0,0,o),A.fill(n)},shape(e){g.beginPath();for(let t=0;t<e.length;t+=2)0===t?g.moveTo(~~e[t],~~e[t+1]):g.lineTo(~~e[t],~~e[t+1]);g.lineTo(~~e[0],~~e[1])},line(e,t,l,a,n){g.beginPath();let i=.5*(0!==m&&~~e==~~l),o=.5*(0!==m&&~~t==~~a);g.moveTo(~~e+i,~~t+o),g.lineTo(~~l+i,~~a+o),A.stroke(n)},linewidth(e){g.lineWidth=~~e,m=.5*(0!=~~e%2)},linedash(e,t=0){g.setLineDash(e),g.lineDashOffset=t},text(e,t,l,a=k,n="normal"){g.font=`${n} ${P}px ${E}`,g.fillStyle=N(a);let i=(""+l).split("\n");for(let l=0;l<i.length;l++)g.fillText(i[l],~~e,~~t+P*T*l)},textgap(e){T=e},textfont(e){E=e},textsize(e){P=e},textalign(e,t){e&&(g.textAlign=e),t&&(g.textBaseline=t)},image(e,t,l){g.drawImage(l,~~e,~~t)},spr(e,t,l){let a=l.trim().split("\n");for(let l=0;l<a.length;l++){let n=a[l].trim();for(let a=0;a<n.length;a++){let i=n[a];"."!==i&&" "!==i&&A.rectfill(e+a,t+l,1,1,parseInt(i,36)||0)}}},paint(e,t,l,a={}){let n=a.canvas||new OffscreenCanvas(1,1),i=a.scale||1,o=g;return n.width=e*i,n.height=t*i,(g=n.getContext("2d")).scale(i,i),l(g),g=o,n.transferToImageBitmap()},ctx:e=>(e&&(g=e),g),push(){g.save()},pop(){g.restore()},translate(e,t){g.translate(~~e,~~t)},scale(e,t=e){g.scale(e,t)},rotate(e){g.rotate(e)},alpha(e){g.globalAlpha=A.clamp(e,0,1)},fill(e){g.fillStyle=N(e),g.fill()},stroke(e){g.strokeStyle=N(e),g.stroke()},clip(e){g.beginPath(),e(g),g.clip()},sfx:(e,t=0,l=1)=>!!a.zzfxV&&(!navigator.userActivation||!!navigator.userActivation.hasBeenActive)&&(e=e||L,(0!==t||1!==l)&&((e=e.slice())[0]=l*(e[0]||1),e[10]=~~e[10]+t),c.apply(0,e),e),volume(e){a.zzfxV=e},canvas:()=>u,use(e,t={}){var l=e,a=t;let n=l(A,a);for(let e in n)A.def(e,n[e])},listen:(e,t)=>{D[e=e.toLowerCase()]=D[e]||new Set,D[e].add(t)},unlisten:(e,t)=>{D[e=e.toLowerCase()]&&D[e].delete(t)},emit:(e,l,n,i,o)=>(d&&(M("before:"+(e=e.toLowerCase()),l,n,i,o),t.loop||"function"!=typeof a[e]||a[e](l,n,i,o),M(e,l,n,i,o),M("after:"+e,l,n,i,o)),l),pal(t,l=3){C=t||e,I=[],k=l},palc(e,t){null==e?I=[]:I[e]=t},def(e,l){A[e]=l,t.global&&(a[e]=l)},timescale(e){w=e},framerate(e){x=1e3/~~e},stat:e=>[t,d,x/1e3,h,D,C,L,w,a.zzfxV,z,P,E,I,T][e],pause(){p=!0,cancelAnimationFrame(b)},resume(){d&&p&&(p=!1,y=x,v=i.now(),b=r(S))},paused:()=>p,quit(){for(let e of(A.emit("shutdown"),A.pause(),d=!1,D={},s))e();if(t.global){for(let e in A)delete a[e];delete a.ENGINE}}};for(let e of"PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp".split(","))A[e]=n[e];function S(){b=r(S);let e=i.now(),t=0,l=e-v;for(v=e,y+=l<100?l:x;y>=x;){t++,y-=x;let e=x/1e3*w;A.emit("update",e,t),A.def("T",A.T+e)}t&&(A.emit("draw",g),t>1&&(y=0))}function H(){let e=t.width>0?t.width:innerWidth,l=t.width>0?t.height||t.width:innerHeight;if(A.def("W",e),A.def("H",l),u.width=e,u.height=l,t.autoscale){let a=+t.autoscale;u.style.display||(u.style.display="block",u.style.margin="auto"),h=n.min(innerWidth/e,innerHeight/l),h=a>1&&h>a?a:h,u.style.width=e*h+"px",u.style.height=l*h+"px"}g.imageSmoothingEnabled=!1,A.textalign("start","top"),A.emit("resized",h)}function M(e,t,l,a,n){if(D[e])for(let i of D[e])i(t,l,a,n)}function N(e){return C[~~(I[e]??e)%C.length]}if(t.global){if(a.ENGINE)throw Error("only one global litecanvas is allowed");Object.assign(a,A),a.ENGINE=A}if(g=(u=(u="string"==typeof t.canvas?document.querySelector(t.canvas):t.canvas)||document.createElement("canvas")).getContext("2d"),f(u,"click",()=>focus()),H(),u.parentNode||document.body.appendChild(u),u.style.imageRendering="pixelated",u.oncontextmenu=()=>!1,t.loop)for(let e in t.loop)t.loop[e]&&A.listen(e,t.loop[e]);return b=r(function(){if(t.autoscale&&f(a,"resize",H),t.tapEvents){let e=e=>[(e.pageX-u.offsetLeft)/h,(e.pageY-u.offsetTop)/h],t=new Map,l=(e,l,a)=>{let n={x:l,y:a,xi:l,yi:a,t:i.now()};return t.set(e,n),n},n=(e,a,n)=>{let i=t.get(e)||l(e);i.x=a,i.y=n},o=e=>e&&i.now()-e.t<=300,r=!1;f(u,"mousedown",t=>{if(0===t.button){t.preventDefault();let[a,n]=e(t);A.emit("tap",a,n,0),l(0,a,n),r=!0}}),f(u,"mouseup",l=>{if(0===l.button){l.preventDefault();let a=t.get(0),[n,i]=e(l);o(a)&&A.emit("tapped",a.xi,a.yi,0),A.emit("untap",n,i,0),t.delete(0),r=!1}}),f(a,"mousemove",t=>{t.preventDefault();let[l,a]=e(t);A.def("MX",l),A.def("MY",a),r&&(A.emit("tapping",l,a,0),n(0,l,a))}),f(u,"touchstart",t=>{for(let a of(t.preventDefault(),t.changedTouches)){let[t,n]=e(a);A.emit("tap",t,n,a.identifier+1),l(a.identifier+1,t,n)}}),f(u,"touchmove",t=>{for(let l of(t.preventDefault(),t.changedTouches)){let[t,a]=e(l);A.emit("tapping",t,a,l.identifier+1),n(l.identifier+1,t,a)}});let s=e=>{e.preventDefault();let l=[];if(e.targetTouches.length>0)for(let t of e.targetTouches)l.push(t.identifier+1);for(let[e,a]of t)l.includes(e)||(o(a)&&A.emit("tapped",a.xi,a.yi,e),A.emit("untap",a.x,a.y,e),t.delete(e))};f(u,"touchend",s),f(u,"touchcancel",s),f(a,"blur",()=>{for(let[e,l]of(r=!1,t))A.emit("untap",l.x,l.y,e),t.delete(e)})}if(t.keyboardEvents){let e=new Set,t=new Set,l=(e,t="")=>(t=t.toLowerCase())?e.has("space"===t?" ":t):e.size>0,n="";f(a,"keydown",l=>{let a=l.key.toLowerCase();e.has(a)||(e.add(a),t.add(a),n=" "===a?"space":a)}),f(a,"keyup",t=>{e.delete(t.key.toLowerCase())}),f(a,"blur",()=>e.clear()),A.listen("after:update",()=>t.clear()),A.def("iskeydown",t=>l(e,t)),A.def("iskeypressed",e=>l(t,e)),A.def("lastkey",()=>n)}d=!0,A.resume(),A.emit("init",A)}),A}})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "litecanvas",
3
- "version": "0.201.0",
3
+ "version": "0.203.0",
4
4
  "description": "Lightweight HTML5 canvas 2D game engine suitable for small projects and creative coding. Inspired by PICO-8 and p5.js/Processing.",
5
5
  "license": "MIT",
6
6
  "author": "Luiz Bills <luizbills@pm.me>",
@@ -32,15 +32,15 @@
32
32
  "creative coding"
33
33
  ],
34
34
  "devDependencies": {
35
- "@happy-dom/global-registrator": "^20.8.4",
35
+ "@happy-dom/global-registrator": "^20.8.9",
36
36
  "@size-limit/preset-small-lib": "^12.0.1",
37
- "@swc/core": "^1.15.18",
37
+ "@swc/core": "^1.15.21",
38
38
  "ava": "^7.0.0",
39
39
  "esbuild": "^0.27.4",
40
40
  "genversion": "^3.2.0",
41
41
  "gzip-size": "^7.0.0",
42
42
  "prettier": "^3.8.1",
43
- "sinon": "^21.0.2",
43
+ "sinon": "^21.0.3",
44
44
  "size-limit": "^12.0.1",
45
45
  "tap-min": "^3.0.0"
46
46
  },
package/src/index.js CHANGED
@@ -86,7 +86,7 @@ export default function litecanvas(settings = {}) {
86
86
  _colorPaletteState = [],
87
87
  /** @type {number[]} */
88
88
  _defaultSound = [0.5, 0, 1750, , , 0.3, 1, , , , 600, 0.1],
89
- /** @type {string} list of functions copied from `Math` module*/
89
+ /** @type {string} list of functions copied from `Math` module */
90
90
  _mathFunctions =
91
91
  'PI,sin,cos,atan2,hypot,tan,abs,ceil,floor,trunc,min,max,pow,sqrt,sign,exp',
92
92
  /**
@@ -155,7 +155,7 @@ export default function litecanvas(settings = {}) {
155
155
  * @returns {number} the value in radians
156
156
  */
157
157
  deg2rad: (degs) => {
158
- DEV: assert(isNumber(degs), 'deg2rad: 1st param must be a number')
158
+ DEV: assert(isNumber(degs), 'deg2rad() 1st param must be a number')
159
159
 
160
160
  return (math.PI / 180) * degs
161
161
  },
@@ -167,7 +167,7 @@ export default function litecanvas(settings = {}) {
167
167
  * @returns {number} the value in degrees
168
168
  */
169
169
  rad2deg: (rads) => {
170
- DEV: assert(isNumber(rads), 'rad2deg: 1st param must be a number')
170
+ DEV: assert(isNumber(rads), 'rad2deg() 1st param must be a number')
171
171
 
172
172
  return (180 / math.PI) * rads
173
173
  },
@@ -706,9 +706,10 @@ export default function litecanvas(settings = {}) {
706
706
  *
707
707
  * Default = `1.2`
708
708
  *
709
- * @param value
709
+ * @param {number} value
710
710
  */
711
711
  textgap(value) {
712
+ DEV: assert(isNumber(value), loggerPrefix + 'textgap() 1st param must be a number')
712
713
  _fontLineHeight = value
713
714
  },
714
715
 
@@ -833,8 +834,9 @@ export default function litecanvas(settings = {}) {
833
834
  loggerPrefix + 'paint() 3rd param must be a function'
834
835
  )
835
836
  DEV: assert(
836
- (options && null == options.scale) || isNumber(options.scale),
837
- loggerPrefix + 'paint() 4th param (options.scale) must be a number'
837
+ (options && null == options.scale) ||
838
+ (isNumber(options.scale) && options.scale > 0),
839
+ loggerPrefix + 'paint() 4th param (options.scale) must be a positive number'
838
840
  )
839
841
  DEV: assert(
840
842
  (options && null == options.canvas) || options.canvas instanceof OffscreenCanvas,
@@ -867,6 +869,13 @@ export default function litecanvas(settings = {}) {
867
869
  * @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
868
870
  */
869
871
  ctx(context) {
872
+ DEV: assert(
873
+ null == context ||
874
+ context instanceof CanvasRenderingContext2D ||
875
+ context instanceof OffscreenCanvasRenderingContext2D,
876
+ loggerPrefix + 'ctx() 1st param must be an [Offscreen]CanvasRenderingContext2D'
877
+ )
878
+
870
879
  if (context) {
871
880
  _ctx = context
872
881
  }
@@ -910,14 +919,11 @@ export default function litecanvas(settings = {}) {
910
919
  * @param {number} x
911
920
  * @param {number} [y]
912
921
  */
913
- scale(x, y) {
922
+ scale(x, y = x) {
914
923
  DEV: assert(isNumber(x), loggerPrefix + 'scale() 1st param must be a number')
915
- DEV: assert(
916
- null == y || isNumber(y),
917
- loggerPrefix + 'scale() 2nd param must be a number'
918
- )
924
+ DEV: assert(isNumber(y), loggerPrefix + 'scale() 2nd param must be a number')
919
925
 
920
- _ctx.scale(x, y || x)
926
+ _ctx.scale(x, y)
921
927
  },
922
928
 
923
929
  /**
@@ -982,7 +988,7 @@ export default function litecanvas(settings = {}) {
982
988
  clip(callback) {
983
989
  DEV: assert(
984
990
  'function' === typeof callback,
985
- loggerPrefix + 'clip() 1st param must be a function'
991
+ loggerPrefix + 'clip() 1st param must be a function (ctx) => void'
986
992
  )
987
993
 
988
994
  beginPath(_ctx)
@@ -1055,14 +1061,15 @@ export default function litecanvas(settings = {}) {
1055
1061
  canvas: () => _canvas,
1056
1062
 
1057
1063
  /**
1058
- * Prepares a plugin to be loaded
1064
+ * Loads a Litecanvas plugin
1059
1065
  *
1060
1066
  * @param {pluginCallback} callback
1067
+ * @param {object} [config]
1061
1068
  */
1062
1069
  use(callback, config = {}) {
1063
1070
  DEV: assert(
1064
1071
  'function' === typeof callback,
1065
- loggerPrefix + 'use() 1st param must be a function'
1072
+ loggerPrefix + 'use() 1st param must be a function (instance, config) => any'
1066
1073
  )
1067
1074
  DEV: assert(
1068
1075
  'object' === typeof config,
@@ -1129,6 +1136,7 @@ export default function litecanvas(settings = {}) {
1129
1136
  * @param {any} [arg2] any data to be passed over the listeners
1130
1137
  * @param {any} [arg3] any data to be passed over the listeners
1131
1138
  * @param {any} [arg4] any data to be passed over the listeners
1139
+ * @returns {any} always returns the second argument
1132
1140
  */
1133
1141
  emit(eventName, arg1, arg2, arg3, arg4) {
1134
1142
  DEV: assert(
@@ -1148,6 +1156,8 @@ export default function litecanvas(settings = {}) {
1148
1156
 
1149
1157
  triggerEvent('after:' + eventName, arg1, arg2, arg3, arg4)
1150
1158
  }
1159
+
1160
+ return arg1
1151
1161
  },
1152
1162
 
1153
1163
  /**
@@ -1202,7 +1212,7 @@ export default function litecanvas(settings = {}) {
1202
1212
  * Define or update a instance property.
1203
1213
  *
1204
1214
  * Note: when the `litecanvas()` option "global" is `true` (default),
1205
- * `def()` with set/update a global property.
1215
+ * `def()` with set/update a window property.
1206
1216
  *
1207
1217
  * E.g: `def('ONE', 1)` do `window.ONE = 1`.
1208
1218
  *
@@ -1257,52 +1267,64 @@ export default function litecanvas(settings = {}) {
1257
1267
  /**
1258
1268
  * Returns information about the engine instance.
1259
1269
  *
1260
- * @param {number|string} index
1270
+ * @param {number} index
1261
1271
  * @returns {any}
1262
1272
  */
1263
1273
  stat(index) {
1264
- DEV: assert(
1265
- isNumber(index) || 'string' === typeof index,
1266
- loggerPrefix + 'stat() 1st param must be a number or string'
1267
- )
1274
+ DEV: assert(isNumber(index), loggerPrefix + 'stat() 1st param must be a number')
1268
1275
 
1269
1276
  const internals = [
1270
1277
  // 0
1271
1278
  settings,
1279
+
1272
1280
  // 1
1273
1281
  _initialized,
1282
+
1274
1283
  // 2
1275
1284
  _fpsInterval / 1000,
1285
+
1276
1286
  // 3
1277
1287
  _canvasScale,
1288
+
1278
1289
  // 4
1279
1290
  _eventListeners,
1291
+
1280
1292
  // 5
1281
1293
  _colorPalette,
1294
+
1282
1295
  // 6
1283
1296
  _defaultSound,
1297
+
1284
1298
  // 7
1285
1299
  _timeScale,
1300
+
1286
1301
  // 8
1287
1302
  root.zzfxV,
1303
+
1288
1304
  // 9
1289
1305
  _rngSeed,
1306
+
1290
1307
  // 10
1291
1308
  _fontSize,
1309
+
1292
1310
  // 11
1293
1311
  _fontFamily,
1312
+
1294
1313
  // 12
1295
1314
  _colorPaletteState,
1315
+
1296
1316
  // 13
1297
1317
  _fontLineHeight,
1298
1318
  ]
1299
1319
 
1300
- const data = { index, value: internals[index] }
1301
-
1302
- // plugins can modify or create new stats
1303
- instance.emit('stat', data)
1320
+ DEV: assert(
1321
+ index >= 0 && index < internals.length,
1322
+ loggerPrefix +
1323
+ 'stat() 1st param must be a number between 0 and ' +
1324
+ (internals.length - 1)
1325
+ )
1304
1326
 
1305
- return data.value
1327
+ return internals[index]
1306
1328
  },
1307
1329
 
1308
1330
  /**
@@ -1343,8 +1365,8 @@ export default function litecanvas(settings = {}) {
1343
1365
  * Shutdown the litecanvas instance and remove all event listeners.
1344
1366
  */
1345
1367
  quit() {
1346
- // emit "quit" event to manual clean ups
1347
- instance.emit('quit')
1368
+ // emit "shutdown" event to manual clean ups
1369
+ instance.emit('shutdown')
1348
1370
 
1349
1371
  // stop the game loop (update & draw)
1350
1372
  instance.pause()
@@ -1827,11 +1849,7 @@ export default function litecanvas(settings = {}) {
1827
1849
  }
1828
1850
 
1829
1851
  // init the engine (async)
1830
- if ('loading' === document.readyState) {
1831
- on(root, 'DOMContentLoaded', () => raf(init))
1832
- } else {
1833
- _rafid = raf(init)
1834
- }
1852
+ _rafid = raf(init)
1835
1853
 
1836
1854
  return instance
1837
1855
  }
package/src/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '0.201.0'
2
+ export const version = '0.203.0'
package/types/global.d.ts CHANGED
@@ -541,11 +541,12 @@ declare global {
541
541
  */
542
542
  function canvas(): HTMLCanvasElement
543
543
  /**
544
- * Prepares a plugin to be loaded
544
+ * Loads a plugin
545
545
  *
546
546
  * @param callback
547
+ * @param config
547
548
  */
548
- function use(callback: pluginCallback): void
549
+ function use(callback: pluginCallback, config: object): void
549
550
  /**
550
551
  * Add a game loop event listener.
551
552
  *
@@ -572,8 +573,9 @@ declare global {
572
573
  * @param [arg2] any data to be passed over the listeners
573
574
  * @param [arg3] any data to be passed over the listeners
574
575
  * @param [arg4] any data to be passed over the listeners
576
+ * @returns always returns the second argument
575
577
  */
576
- function emit(event: string, arg1?: any, arg2?: any, arg3?: any, arg4?: any): void
578
+ function emit(event: string, arg1?: any, arg2?: any, arg3?: any, arg4?: any): any
577
579
  /**
578
580
  * Set new palette colors or restore the default palette.
579
581
  *
@@ -596,7 +598,7 @@ declare global {
596
598
  * Define or update a instance property.
597
599
  *
598
600
  * Note: when the `litecanvas()` option "global" is `true` (default),
599
- * `def()` with set/update a global property.
601
+ * `def()` with set/update a window property.
600
602
  * E.g: `def('ONE', 1)` also do `window.ONE = 1`.
601
603
  *
602
604
  * @param key the property name
@@ -634,11 +636,10 @@ declare global {
634
636
  * - n = 11: the current font family
635
637
  * - n = 12: the current state of the color palette
636
638
  * - n = 13: the current font gap
637
- * - n = *any other value*: probably returns undefined
638
639
  *
639
640
  * @param index
640
641
  */
641
- function stat(index: number | string): any
642
+ function stat(index: number): any
642
643
  /**
643
644
  * Pauses the engine loop (update & draw).
644
645
  */
package/types/types.d.ts CHANGED
@@ -525,11 +525,12 @@ type LitecanvasInstance = {
525
525
  */
526
526
  canvas(): HTMLCanvasElement
527
527
  /**
528
- * Prepares a plugin to be loaded
528
+ * Loads a plugin
529
529
  *
530
530
  * @param callback
531
+ * @param config
531
532
  */
532
- use(callback: pluginCallback): void
533
+ use(callback: pluginCallback, config: object): void
533
534
  /**
534
535
  * Add a game loop event listener.
535
536
  *
@@ -556,13 +557,14 @@ type LitecanvasInstance = {
556
557
  * @param [arg2] any data to be passed over the listeners
557
558
  * @param [arg3] any data to be passed over the listeners
558
559
  * @param [arg4] any data to be passed over the listeners
560
+ * @returns always returns the second argument
559
561
  */
560
- emit(event: string, arg1?: any, arg2?: any, arg3?: any, arg4?: any): void
562
+ emit(event: string, arg1?: any, arg2?: any, arg3?: any, arg4?: any): any
561
563
  /**
562
564
  * Define or update a instance property.
563
565
  *
564
566
  * Note: when the `litecanvas()` option "global" is `true` (default),
565
- * `def()` with set/update a global property.
567
+ * `def()` with set/update a window property.
566
568
  * E.g: `def('ONE', 1)` also do `window.ONE = 1`.
567
569
  *
568
570
  * @param key the property name
@@ -618,11 +620,10 @@ type LitecanvasInstance = {
618
620
  * - n = 11: the current font family
619
621
  * - n = 12: the current state of the color palette
620
622
  * - n = 13: the current font gap
621
- * - n = *any other value*: probably returns undefined
622
623
  *
623
624
  * @param index
624
625
  */
625
- stat(index: number | string): any
626
+ stat(index: number): any
626
627
  /**
627
628
  * Pauses the engine loop (update & draw).
628
629
  */
@@ -704,7 +705,7 @@ type LitecanvasGameLoop = {
704
705
 
705
706
  type drawCallback = (context: OffscreenCanvasRenderingContext2D) => void
706
707
 
707
- type pluginCallback = (instance: LitecanvasInstance, config?: any) => any
708
+ type pluginCallback = (instance: LitecanvasInstance, config?: object) => any
708
709
 
709
710
  type clipCallback = (ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D) => void
710
711