akarisub 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/dist/akarisub-worker.js +2 -2
- package/dist/akarisub-worker.wasm +0 -0
- package/dist/akarisub.umd.js +5 -5
- package/dist/index.js +5 -5
- package/package.json +1 -1
- package/src/ts/akarisub.ts +148 -71
- package/src/ts/types.ts +4 -13
- package/src/ts/webgl2-renderer.ts +7 -2
- package/src/ts/webgpu-renderer.ts +12 -4
- package/src/ts/worker.ts +31 -78
package/dist/akarisub.umd.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
root.AkariSub = factory();
|
|
8
8
|
}
|
|
9
9
|
}(typeof self !== 'undefined' ? self : this, function() {
|
|
10
|
-
(()=>{var{defineProperty:h,getOwnPropertyNames
|
|
10
|
+
(()=>{var{defineProperty:h,getOwnPropertyNames:$J,getOwnPropertyDescriptor:QJ}=Object,KJ=Object.prototype.hasOwnProperty;function NJ(J){return this[J]}var OJ=(J)=>{var Z=(d??=new WeakMap).get(J),Q;if(Z)return Z;if(Z=h({},"__esModule",{value:!0}),J&&typeof J==="object"||typeof J==="function"){for(var $ of $J(J))if(!KJ.call(Z,$))h(Z,$,{get:NJ.bind(J,$),enumerable:!(Q=QJ(J,$))||Q.enumerable})}return d.set(J,Z),Z},d;var GJ=(J)=>J;function FJ(J,Z){this[J]=GJ.bind(null,Z)}var UJ=(J,Z)=>{for(var Q in Z)h(J,Q,{get:Z[Q],enumerable:!0,configurable:!0,set:FJ.bind(Z,Q)})};var PJ={};UJ(PJ,{webYCbCrMap:()=>u,testImageBugs:()=>l,runFeatureTests:()=>t,parseAss:()=>r,libassYCbCrMap:()=>s,isWebGPUSupported:()=>f,isWebGL2Supported:()=>p,getVideoPosition:()=>c,getColorSpaceFilterUrl:()=>o,getBitmapBug:()=>e,getAlphaBug:()=>a,fixPlayRes:()=>i,fixAlpha:()=>m,dropBlur:()=>n,default:()=>H,computeCanvasSize:()=>w,colorMatrixConversionMap:()=>y,WebGPURenderer:()=>v,WebGL2Renderer:()=>x,AkariSub:()=>H});var u={bt709:"BT709",bt470bg:"BT601",smpte170m:"BT601"},y={BT601:{BT709:"1.0863 -0.0723 -0.014 0 0 0.0965 0.8451 0.0584 0 0 -0.0141 -0.0277 1.0418"},BT709:{BT601:"0.9137 0.0784 0.0079 0 0 -0.1049 1.1722 -0.0671 0 0 0.0096 0.0322 0.9582"},FCC:{BT709:"1.0873 -0.0736 -0.0137 0 0 0.0974 0.8494 0.0531 0 0 -0.0127 -0.0251 1.0378",BT601:"1.001 -0.0008 -0.0002 0 0 0.0009 1.005 -0.006 0 0 0.0013 0.0027 0.996"},SMPTE240M:{BT709:"0.9993 0.0006 0.0001 0 0 -0.0004 0.9812 0.0192 0 0 -0.0034 -0.0114 1.0148",BT601:"0.913 0.0774 0.0096 0 0 -0.1051 1.1508 -0.0456 0 0 0.0063 0.0207 0.973"}},s=[null,"BT601",null,"BT601","BT601","BT709","BT709","SMPTE240M","SMPTE240M","FCC","FCC"];function o(J,Z){if(!J||!Z)return null;if(J===Z)return null;let Q=y[J]?.[Z];if(!Q)return null;return`url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><filter id='f'><feColorMatrix type='matrix' values='${Q} 0 0 0 0 0 1 0'/></filter></svg>#f")`}function w(J,Z,Q,$,N){let O=Q<=0?1:Q,K=globalThis.devicePixelRatio||1;if(Z<=0||J<=0)return{width:0,height:0};let F=O<1?-1:1,G=Z*K;if(F*G*O<=F*$)G*=O;else if(F*G<F*$)G=$;if(N>0&&G>N)G=N;return J*=G/Z,Z=G,{width:J,height:Z}}function c(J,Z=J.videoWidth,Q=J.videoHeight){let $=Z/Q,{offsetWidth:N,offsetHeight:O}=J,K=N/O,F=N,G=O;if(K>$)F=Math.floor(O*$);else G=Math.floor(N/$);let U=(N-F)/2,E=(O-G)/2;return{width:F,height:G,x:U,y:E}}function m(J,Z){if(!Z)return J;let Q=J.length,$=Q-Q%16,N=3;for(;N<$;N+=16){if(J[N]<2)J[N]=1;if(J[N+4]<2)J[N+4]=1;if(J[N+8]<2)J[N+8]=1;if(J[N+12]<2)J[N+12]=1}for(;N<Q;N+=4)if(J[N]<2)J[N]=1;return J}function r(J,Z=!1){let Q=[],$=J.split(/[\r\n]+/g),N=$.length,O=null,K=null;for(let F=0;F<N;F++){let G=$[F];if(!G||/^\s*$/.test(G))continue;let U=G[0];if(U==="["){let E=G.match(/^\[(.*)\]$/);if(E){if(Z&&E[1].toLowerCase()==="events")break;O=null,K={name:E[1],body:[]},Q.push(K);continue}}if(!K)continue;if(U===";")K.body.push({type:"comment",value:G.substring(1)});else{let E=G.indexOf(":");if(E===-1)continue;let M=G.substring(0,E),q=G.substring(E+1).trim();if(O||M==="Format"){let Y=q.split(",");if(O&&Y.length>O.length){let B=Y.slice(O.length-1).join(",");Y=Y.slice(0,O.length-1),Y.push(B)}let L=Y.length;for(let B=0;B<L;B++)Y[B]=Y[B].trim();if(O){let B={},j=Math.min(O.length,L);for(let P=0;P<j;P++)B[O[P]]=Y[P];q=B}else q=Y}if(M==="Format")O=q;K.body.push({key:M,value:q})}}return Q}var XJ=/\\blur(?:[0-9]+\.)?[0-9]+/gm;function n(J){return J.replace(XJ,"")}var qJ=[{w:7680,h:4320},{w:3840,h:2160},{w:2560,h:1440},{w:1920,h:1080},{w:1280,h:720}];function YJ(J,Z){let Q=[...qJ].sort(($,N)=>$.w-N.w);for(let $ of Q)if(J<=$.w&&Z<=$.h)return $;return{w:Math.ceil(J/100)*100,h:Math.ceil(Z/100)*100}}function V(J,Z){return Z&&Z.includes(".")?J.toFixed(2).replace(/\.?0+$/,""):Math.round(J)}function i(J){let Z=J.match(/PlayResX:\s*(\d+)/i),Q=J.match(/PlayResY:\s*(\d+)/i),$=Z?parseInt(Z[1],10):1920,N=Q?parseInt(Q[1],10):1080,O=/\\pos\s*\(\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*\)/g,K=/\\move\s*\(\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)/g,F=/\\org\s*\(\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*\)/g,G=/\\i?clip\s*\(\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*\)/g,U=0,E=0,M=(T,X,k)=>{let R,A=new RegExp(T.source,"g");while((R=A.exec(J))!==null){for(let I of X)if(R[I]){let D=Math.abs(parseFloat(R[I]));if(D>U)U=D}for(let I of k)if(R[I]){let D=Math.abs(parseFloat(R[I]));if(D>E)E=D}}};if(M(O,[1],[2]),M(K,[1,3],[2,4]),M(F,[1],[2]),M(G,[1,3],[2,4]),U<=$&&E<=N)return J;let q=YJ(U,E),Y=$/q.w,L=N/q.h,B=Math.min(Y,L),j=Math.max(Y,L),P=1,z=J,W=z.match(/(\[Events\][\s\S]*)/i);if(!W)return z;let _=W[1];return _=_.replace(O,(T,X,k)=>`\\pos(${V(parseFloat(X)*Y,X)},${V(parseFloat(k)*L,k)})`),_=_.replace(/\\move\s*\(\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)(?:\s*,\s*(-?[\d.]+)\s*,\s*(-?[\d.]+))?\s*\)/g,(T,X,k,R,A,I,D)=>{let g=`\\move(${V(parseFloat(X)*Y,X)},${V(parseFloat(k)*L,k)},${V(parseFloat(R)*Y,R)},${V(parseFloat(A)*L,A)}`;return I?`${g},${I},${D})`:`${g})`}),_=_.replace(F,(T,X,k)=>`\\org(${V(parseFloat(X)*Y,X)},${V(parseFloat(k)*L,k)})`),_=_.replace(/\\(i?clip)\s*\(\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*\)/g,(T,X,k,R,A,I)=>`\\${X}(${V(parseFloat(k)*Y,k)},${V(parseFloat(R)*L,R)},${V(parseFloat(A)*Y,A)},${V(parseFloat(I)*L,I)})`),_=_.replace(/\\fs([\d.]+)/g,(T,X)=>`\\fs${V(parseFloat(X)*j,X)}`),_=_.replace(/\\fscx([\d.]+)/g,(T,X)=>`\\fscx${V(parseFloat(X)*P,X)}`),_=_.replace(/\\xbord([\d.]+)/g,(T,X)=>`\\xbord${V(parseFloat(X)*Y,X)}`),_=_.replace(/\\ybord([\d.]+)/g,(T,X)=>`\\ybord${V(parseFloat(X)*L,X)}`),_=_.replace(/\\xshad(-?[\d.]+)/g,(T,X)=>`\\xshad${V(parseFloat(X)*Y,X)}`),_=_.replace(/\\yshad(-?[\d.]+)/g,(T,X)=>`\\yshad${V(parseFloat(X)*L,X)}`),["fsp","bord","shad","be","blur"].forEach((T)=>{let X=new RegExp(`\\\\${T}(-?[\\d.]+)`,"g");_=_.replace(X,(k,R)=>`\\${T}${V(parseFloat(R)*B,R)}`)}),_=_.replace(/(\\i?clip\s*\([^,)]+m[^)]+\)|\\p[1-9][^}]*?)(?=[\\}]|$)/g,(T)=>{return T.replace(/(-?[\d.]+)\s+(-?[\d.]+)/g,(X,k,R)=>{return`${V(parseFloat(k)*Y,k)} ${V(parseFloat(R)*L,R)}`})}),z.substring(0,W.index)+_}var b=null,S=null;async function l(){if(b!==null&&S!==null)return{hasAlphaBug:b,hasBitmapBug:S};let J=document.createElement("canvas"),Z=J.getContext("2d",{willReadFrequently:!0});if(!Z)throw Error("Canvas rendering not supported");if(typeof ImageData.prototype.constructor==="function")try{new ImageData(new Uint8ClampedArray([0,0,0,0]),1,1)}catch{console.log("Detected that ImageData is not constructable despite browser saying so")}let Q=document.createElement("canvas"),$=Q.getContext("2d",{willReadFrequently:!0});if(!$)throw Error("Canvas rendering not supported");J.width=Q.width=1,J.height=Q.height=1,Z.clearRect(0,0,1,1),$.clearRect(0,0,1,1);let N=$.getImageData(0,0,1,1).data;Z.putImageData(new ImageData(new Uint8ClampedArray([0,255,0,0]),1,1),0,0),$.drawImage(J,0,0);let O=$.getImageData(0,0,1,1).data;if(b=N[1]!==O[1],b)console.log("Detected a browser having issue with transparent pixels, applying workaround");if(typeof createImageBitmap<"u"){let K=new Uint8ClampedArray([255,0,255,0,255]).subarray(1,5);$.drawImage(await createImageBitmap(new ImageData(K,1)),0,0);let{data:F}=$.getImageData(0,0,1,1);S=!1;for(let G=0;G<F.length;G++)if(Math.abs(K[G]-F[G])>15){S=!0,console.log("Detected a browser having issue with partial bitmaps, applying workaround");break}}else S=!1;return J.remove(),Q.remove(),{hasAlphaBug:b,hasBitmapBug:S}}async function t(){return l()}function a(){return b}function e(){return S}function f(){return typeof navigator<"u"&&"gpu"in navigator}function EJ(J){if(J instanceof ArrayBuffer)return new Uint8Array(J);return new Uint8Array(J.buffer,J.byteOffset,J.byteLength)}class v{device=null;context=null;pipeline=null;bindGroupLayout=null;uniformBuffer=null;imageDataBuffer=null;textureArray=null;textureArrayView=null;textureArraySize=0;textureArrayWidth=0;textureArrayHeight=0;pendingDestroyTextures=[];imageDataArray;resolutionArray=new Float32Array(2);conversionBuffer=null;conversionBufferSize=0;bindGroup=null;bindGroupDirty=!0;lastCanvasWidth=0;lastCanvasHeight=0;format="bgra8unorm";_canvas=null;_initPromise=null;_initialized=!1;constructor(){this.imageDataArray=new Float32Array(2048)}async init(){if(this._initPromise)return this._initPromise;return this._initPromise=this._initDevice(),this._initPromise}async _initDevice(){if(!navigator.gpu)throw Error("WebGPU not supported");let J=await navigator.gpu.requestAdapter({powerPreference:"high-performance"});if(!J)throw Error("No WebGPU adapter found");this.device=await J.requestDevice(),this.format=navigator.gpu.getPreferredCanvasFormat();let Z=this.device.createShaderModule({code:`
|
|
11
11
|
struct VertexOutput {
|
|
12
12
|
@builtin(position) position: vec4f,
|
|
13
13
|
@location(0) @interpolate(flat) instanceIndex: u32,
|
|
@@ -62,7 +62,7 @@ fn vertexMain(
|
|
|
62
62
|
|
|
63
63
|
return output;
|
|
64
64
|
}
|
|
65
|
-
`}),
|
|
65
|
+
`}),Q=this.device.createShaderModule({code:`
|
|
66
66
|
@group(0) @binding(2) var texArray: texture_2d_array<f32>;
|
|
67
67
|
|
|
68
68
|
struct ImageData {
|
|
@@ -100,7 +100,7 @@ fn fragmentMain(input: FragmentInput) -> @location(0) vec4f {
|
|
|
100
100
|
// Premultiplied alpha output
|
|
101
101
|
return vec4f(color.rgb * color.a, color.a);
|
|
102
102
|
}
|
|
103
|
-
`});this.uniformBuffer=this.device.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.imageDataBuffer=this.device.createBuffer({size:8192,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),this.createTextureArray(256,256,32),this.bindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"unfilterable-float",viewDimension:"2d-array"}}]});let
|
|
103
|
+
`});this.uniformBuffer=this.device.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.imageDataBuffer=this.device.createBuffer({size:8192,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),this.createTextureArray(256,256,32),this.bindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"unfilterable-float",viewDimension:"2d-array"}}]});let $=this.device.createPipelineLayout({bindGroupLayouts:[this.bindGroupLayout]});this.pipeline=this.device.createRenderPipeline({layout:$,vertex:{module:Z,entryPoint:"vertexMain"},fragment:{module:Q,entryPoint:"fragmentMain",targets:[{format:this.format,blend:{color:{srcFactor:"one",dstFactor:"one-minus-src-alpha",operation:"add"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha",operation:"add"}}}]},primitive:{topology:"triangle-list"}}),this._initialized=!0}nextPowerOf2(J){return J--,J|=J>>1,J|=J>>2,J|=J>>4,J|=J>>8,J|=J>>16,J+1}createTextureArray(J,Z,Q){if(this.textureArray)this.pendingDestroyTextures.push(this.textureArray);let $=this.nextPowerOf2(Math.max(J,64)),N=this.nextPowerOf2(Math.max(Z,64)),O=Math.min(this.nextPowerOf2(Math.max(Q,16)),256);this.textureArray=this.device.createTexture({size:[$,N,O],format:this.format,usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT}),this.textureArrayView=this.textureArray.createView({dimension:"2d-array"}),this.textureArrayWidth=$,this.textureArrayHeight=N,this.textureArraySize=O,this.bindGroupDirty=!0;let K=this.device.createCommandEncoder();for(let F=0;F<O;F++){let G=this.textureArray.createView({dimension:"2d",baseArrayLayer:F,arrayLayerCount:1});K.beginRenderPass({colorAttachments:[{view:G,clearValue:{r:0,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"}]}).end()}this.device.queue.submit([K.finish()])}ensureTextureArray(J,Z,Q){let $=Math.min(Q,256);if(J<=this.textureArrayWidth&&Z<=this.textureArrayHeight&&$<=this.textureArraySize)return!1;let N=this.nextPowerOf2(Math.max(this.textureArrayWidth,J)),O=this.nextPowerOf2(Math.max(this.textureArrayHeight,Z)),K=Math.min(this.nextPowerOf2(Math.max(this.textureArraySize,$,$+16)),256);return this.createTextureArray(N,O,K),!0}updateBindGroup(){if(!this.bindGroupDirty||!this.device||!this.bindGroupLayout)return;this.bindGroup=this.device.createBindGroup({layout:this.bindGroupLayout,entries:[{binding:0,resource:{buffer:this.uniformBuffer}},{binding:1,resource:{buffer:this.imageDataBuffer}},{binding:2,resource:this.textureArrayView}]}),this.bindGroupDirty=!1}ensureConversionBuffer(J){if(this.conversionBufferSize<J)this.conversionBufferSize=Math.max(J,this.conversionBufferSize*1.5|0,65536),this.conversionBuffer=new Uint8Array(this.conversionBufferSize);return this.conversionBuffer}async setCanvas(J,Z,Q){if(await this.init(),!this.device)throw Error("WebGPU device not initialized");if(Z<=0||Q<=0)return;if(this._canvas=J,J.width=Z,J.height=Q,!this.context){if(this.context=J.getContext("webgpu"),!this.context)throw Error("Could not get WebGPU context");this.context.configure({device:this.device,format:this.format,alphaMode:"premultiplied"})}this.resolutionArray[0]=Z,this.resolutionArray[1]=Q,this.device.queue.writeBuffer(this.uniformBuffer,0,this.resolutionArray),this.lastCanvasWidth=Z,this.lastCanvasHeight=Q}updateSize(J,Z){if(!this.device||!this._canvas||J<=0||Z<=0)return;if(J===this.lastCanvasWidth&&Z===this.lastCanvasHeight)return;this._canvas.width=J,this._canvas.height=Z,this.resolutionArray[0]=J,this.resolutionArray[1]=Z,this.device.queue.writeBuffer(this.uniformBuffer,0,this.resolutionArray),this.lastCanvasWidth=J,this.lastCanvasHeight=Z}renderBitmaps(J,Z,Q){if(!this.device||!this.context||!this.pipeline)return;let $=J.length;if($===0){this.clear();return}let N=this.context.getCurrentTexture();if(N.width===0||N.height===0)return;let O=0,K=0,F=0;for(let j=0;j<$;j++){let{image:P}=J[j],z=P.width,W=P.height;if(z>0&&W>0){if(z>O)O=z;if(W>K)K=W;F++}}if(F===0){this.clear();return}let G=Math.min(F,256);this.ensureTextureArray(O,K,G),this.updateBindGroup();let U=this.device,E=U.queue,M=this.textureArray,q=this.imageDataArray,Y=N.createView(),L=0,B=!0;while(L<$){let j=0;while(L<$&&j<256){let W=J[L++],_=W.image,C=_.width,T=_.height;if(C<=0||T<=0)continue;E.copyExternalImageToTexture({source:_,flipY:!1},{texture:M,origin:[0,0,j],premultipliedAlpha:!1},{width:C,height:T});let X=j<<3;q[X]=W.x,q[X+1]=W.y,q[X+2]=C,q[X+3]=T,q[X+4]=C,q[X+5]=T,q[X+6]=j,q[X+7]=0,j++}if(j===0)continue;E.writeBuffer(this.imageDataBuffer,0,q.buffer,0,j<<5);let P=U.createCommandEncoder(),z=P.beginRenderPass({colorAttachments:[{view:Y,clearValue:{r:0,g:0,b:0,a:0},loadOp:B?"clear":"load",storeOp:"store"}]});z.setPipeline(this.pipeline),z.setBindGroup(0,this.bindGroup),z.draw(6,j),z.end(),E.submit([P.finish()]),B=!1}this.cleanupPendingTextures()}render(J,Z,Q){if(!this.device||!this.context||!this.pipeline)return;let $=J.length;if($===0){this.clear();return}let N=this.context.getCurrentTexture();if(N.width===0||N.height===0)return;let O=0,K=0,F=0;for(let P=0;P<$;P++){let{w:z,h:W}=J[P];if(z>0&&W>0){if(z>O)O=z;if(W>K)K=W;F++}}if(F===0){this.clear();return}let G=Math.min(F,256);this.ensureTextureArray(O,K,G),this.updateBindGroup();let U=this.device,E=U.queue,M=this.textureArray,q=this.imageDataArray,Y=this.format==="bgra8unorm",L=N.createView(),B=0,j=!0;while(B<$){let P=0;while(B<$&&P<256){let _=J[B++],C=_.w,T=_.h;if(C<=0||T<=0)continue;let X=_.image;if(X instanceof ImageBitmap)E.copyExternalImageToTexture({source:X,flipY:!1},{texture:M,origin:[0,0,P],premultipliedAlpha:!1},{width:C,height:T});else if(X instanceof ArrayBuffer||X instanceof Uint8Array||X instanceof Uint8ClampedArray)this.uploadTextureData(P,X,C,T,Y);let k=P<<3;q[k]=_.x,q[k+1]=_.y,q[k+2]=C,q[k+3]=T,q[k+4]=C,q[k+5]=T,q[k+6]=P,q[k+7]=0,P++}if(P===0)continue;E.writeBuffer(this.imageDataBuffer,0,q.buffer,0,P<<5);let z=U.createCommandEncoder(),W=z.beginRenderPass({colorAttachments:[{view:L,clearValue:{r:0,g:0,b:0,a:0},loadOp:j?"clear":"load",storeOp:"store"}]});W.setPipeline(this.pipeline),W.setBindGroup(0,this.bindGroup),W.draw(6,P),W.end(),E.submit([z.finish()]),j=!1}this.cleanupPendingTextures()}uploadTextureData(J,Z,Q,$,N){let O=Q*$*4,K=EJ(Z);if(N){let F=this.ensureConversionBuffer(O);for(let G=0;G<O;G+=4)F[G]=K[G+2],F[G+1]=K[G+1],F[G+2]=K[G],F[G+3]=K[G+3];this.device.queue.writeTexture({texture:this.textureArray,origin:[0,0,J]},F.buffer,{bytesPerRow:Q*4},{width:Q,height:$})}else this.device.queue.writeTexture({texture:this.textureArray,origin:[0,0,J]},K,{bytesPerRow:Q*4},{width:Q,height:$})}cleanupPendingTextures(){let J=this.pendingDestroyTextures,Z=J.length;if(Z===0)return;for(let Q=0;Q<Z;Q++)J[Q].destroy();J.length=0}clear(){if(!this.device||!this.context)return;try{let J=this.context.getCurrentTexture();if(J.width===0||J.height===0)return;let Z=this.device.createCommandEncoder();Z.beginRenderPass({colorAttachments:[{view:J.createView(),clearValue:{r:0,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"}]}).end(),this.device.queue.submit([Z.finish()])}catch{}}get initialized(){return this._initialized}destroy(){this.cleanupPendingTextures(),this.textureArray?.destroy(),this.textureArray=null,this.textureArrayView=null,this.uniformBuffer?.destroy(),this.uniformBuffer=null,this.imageDataBuffer?.destroy(),this.imageDataBuffer=null,this.bindGroup=null,this.conversionBuffer=null,this.conversionBufferSize=0,this.device?.destroy(),this.device=null,this.context=null,this._canvas=null,this._initialized=!1,this._initPromise=null}}function p(){if(typeof document>"u")return!1;try{return document.createElement("canvas").getContext("webgl2")!==null}catch{return!1}}function _J(J){return J instanceof Uint8Array||J instanceof Uint8ClampedArray}function JJ(J,Z,Q){let $=J.createShader(Z);if(J.shaderSource($,Q),J.compileShader($),!J.getShaderParameter($,J.COMPILE_STATUS)){let N=J.getShaderInfoLog($);throw J.deleteShader($),Error(`WebGL2 shader compilation failed: ${N}`)}return $}class x{_gl=null;_canvas=null;_program=null;_vao=null;_instanceBuffer=null;_texArray=null;_texWidth=0;_texHeight=0;_texLayers=0;_resolutionLoc=null;_texArraySizeLoc=null;_instanceData;_lastCanvasWidth=0;_lastCanvasHeight=0;_initialized=!1;_initPromise=null;constructor(){this._instanceData=new Float32Array(2048)}async init(){if(this._initPromise)return this._initPromise;return this._initPromise=this._checkSupport(),this._initPromise}async _checkSupport(){if(typeof document>"u")throw Error("WebGL2 requires a DOM environment");if(!document.createElement("canvas").getContext("webgl2"))throw Error("WebGL2 not supported")}_initGL(){if(!this._canvas)throw Error("Canvas not set before _initGL");if(this._gl)return;let J=this._canvas.getContext("webgl2",{alpha:!0,premultipliedAlpha:!0,antialias:!1});if(!J)throw Error("Failed to create WebGL2 context");this._gl=J;let Z=JJ(J,J.VERTEX_SHADER,`#version 300 es
|
|
104
104
|
precision highp float;
|
|
105
105
|
|
|
106
106
|
in vec4 a_destRect;
|
|
@@ -134,7 +134,7 @@ void main() {
|
|
|
134
134
|
v_texIndex = int(a_texInfo.z);
|
|
135
135
|
v_texSize = a_texInfo.xy;
|
|
136
136
|
}
|
|
137
|
-
`),
|
|
137
|
+
`),Q=JJ(J,J.FRAGMENT_SHADER,`#version 300 es
|
|
138
138
|
precision highp float;
|
|
139
139
|
precision highp sampler2DArray;
|
|
140
140
|
|
|
@@ -153,7 +153,7 @@ void main() {
|
|
|
153
153
|
// Premultiplied alpha output (matches WebGPU renderer behaviour)
|
|
154
154
|
fragColor = vec4(color.rgb * color.a, color.a);
|
|
155
155
|
}
|
|
156
|
-
`),N=J.createProgram();if(J.attachShader(N,K),J.attachShader(N,Z),J.linkProgram(N),!J.getProgramParameter(N,J.LINK_STATUS))throw Error(`WebGL2 program link failed: ${J.getProgramInfoLog(N)}`);J.deleteShader(K),J.deleteShader(Z),this._program=N,this._resolutionLoc=J.getUniformLocation(N,"u_resolution"),this._texArraySizeLoc=J.getUniformLocation(N,"u_texArraySize"),this._vao=J.createVertexArray(),J.bindVertexArray(this._vao),this._instanceBuffer=J.createBuffer(),J.bindBuffer(J.ARRAY_BUFFER,this._instanceBuffer),J.bufferData(J.ARRAY_BUFFER,8192,J.DYNAMIC_DRAW);let Q=J.getAttribLocation(N,"a_destRect");J.enableVertexAttribArray(Q),J.vertexAttribPointer(Q,4,J.FLOAT,!1,32,0),J.vertexAttribDivisor(Q,1);let F=J.getAttribLocation(N,"a_texInfo");J.enableVertexAttribArray(F),J.vertexAttribPointer(F,4,J.FLOAT,!1,32,16),J.vertexAttribDivisor(F,1),J.bindVertexArray(null),this._texArray=J.createTexture(),this._allocateTextureArray(256,256,32),J.enable(J.BLEND),J.blendEquation(J.FUNC_ADD),J.blendFunc(J.ONE,J.ONE_MINUS_SRC_ALPHA),this._initialized=!0}_nextPow2(J){return J--,J|=J>>1,J|=J>>2,J|=J>>4,J|=J>>8,J|=J>>16,J+1}_allocateTextureArray(J,K,Z){let N=this._gl,Q=this._nextPow2(Math.max(J,64)),F=this._nextPow2(Math.max(K,64)),$=Math.min(this._nextPow2(Math.max(Z,16)),256);N.bindTexture(N.TEXTURE_2D_ARRAY,this._texArray),N.texImage3D(N.TEXTURE_2D_ARRAY,0,N.RGBA8,Q,F,$,0,N.RGBA,N.UNSIGNED_BYTE,null),N.texParameteri(N.TEXTURE_2D_ARRAY,N.TEXTURE_MIN_FILTER,N.NEAREST),N.texParameteri(N.TEXTURE_2D_ARRAY,N.TEXTURE_MAG_FILTER,N.NEAREST),N.texParameteri(N.TEXTURE_2D_ARRAY,N.TEXTURE_WRAP_S,N.CLAMP_TO_EDGE),N.texParameteri(N.TEXTURE_2D_ARRAY,N.TEXTURE_WRAP_T,N.CLAMP_TO_EDGE),this._texWidth=Q,this._texHeight=F,this._texLayers=$}_ensureTextureArray(J,K,Z){let N=Math.min(Z,256);if(J<=this._texWidth&&K<=this._texHeight&&N<=this._texLayers)return;let Q=this._nextPow2(Math.max(this._texWidth,J)),F=this._nextPow2(Math.max(this._texHeight,K)),$=Math.min(this._nextPow2(Math.max(this._texLayers,N,N+16)),256);this._allocateTextureArray(Q,F,$)}async setCanvas(J,K,Z){if(await this.init(),K<=0||Z<=0)return;this._canvas=J,J.width=K,J.height=Z,this._initGL(),this._gl.viewport(0,0,K,Z),this._lastCanvasWidth=K,this._lastCanvasHeight=Z}updateSize(J,K){if(!this._gl||!this._canvas||J<=0||K<=0)return;if(J===this._lastCanvasWidth&&K===this._lastCanvasHeight)return;this._canvas.width=J,this._canvas.height=K,this._gl.viewport(0,0,J,K),this._lastCanvasWidth=J,this._lastCanvasHeight=K}renderBitmaps(J,K,Z){if(!this._gl||!this._initialized)return;let N=J.length;if(N===0){this.clear();return}let Q=0,F=0;for(let E=0;E<N;E++){let{image:q}=J[E];if(q.width>Q)Q=q.width;if(q.height>F)F=q.height}this._ensureTextureArray(Q,F,Math.min(N,256));let $=this._gl;$.clearColor(0,0,0,0),$.clear($.COLOR_BUFFER_BIT),$.useProgram(this._program),$.uniform2f(this._resolutionLoc,this._lastCanvasWidth,this._lastCanvasHeight),$.uniform2i(this._texArraySizeLoc,this._texWidth,this._texHeight),$.activeTexture($.TEXTURE0),$.bindTexture($.TEXTURE_2D_ARRAY,this._texArray),$.pixelStorei($.UNPACK_FLIP_Y_WEBGL,!1);let U=this._instanceData,O=0;while(O<N){let E=0;while(O<N&&E<256){let q=J[O++],L=q.image.width,_=q.image.height;if(L<=0||_<=0)continue;$.texSubImage3D($.TEXTURE_2D_ARRAY,0,0,0,E,L,_,1,$.RGBA,$.UNSIGNED_BYTE,q.image);let Y=E<<3;U[Y]=q.x,U[Y+1]=q.y,U[Y+2]=L,U[Y+3]=_,U[Y+4]=L,U[Y+5]=_,U[Y+6]=E,U[Y+7]=0,E++}if(E===0)continue;$.bindBuffer($.ARRAY_BUFFER,this._instanceBuffer),$.bufferSubData($.ARRAY_BUFFER,0,U,0,E<<3),$.bindVertexArray(this._vao),$.drawArraysInstanced($.TRIANGLES,0,6,E),$.bindVertexArray(null)}}render(J,K,Z){if(!this._gl||!this._initialized)return;let N=J.length;if(N===0){this.clear();return}let Q=0,F=0;for(let E=0;E<N;E++){let{w:q,h:L}=J[E];if(q>Q)Q=q;if(L>F)F=L}this._ensureTextureArray(Q,F,Math.min(N,256));let $=this._gl;$.clearColor(0,0,0,0),$.clear($.COLOR_BUFFER_BIT),$.useProgram(this._program),$.uniform2f(this._resolutionLoc,this._lastCanvasWidth,this._lastCanvasHeight),$.uniform2i(this._texArraySizeLoc,this._texWidth,this._texHeight),$.activeTexture($.TEXTURE0),$.bindTexture($.TEXTURE_2D_ARRAY,this._texArray),$.pixelStorei($.UNPACK_FLIP_Y_WEBGL,!1);let U=this._instanceData,O=0;while(O<N){let E=0;while(O<N&&E<256){let q=J[O++],L=q.w,_=q.h;if(L<=0||_<=0)continue;let Y=q.image;if(Y instanceof ImageBitmap)$.texSubImage3D($.TEXTURE_2D_ARRAY,0,0,0,E,L,_,1,$.RGBA,$.UNSIGNED_BYTE,Y);else if(Y instanceof ArrayBuffer)$.texSubImage3D($.TEXTURE_2D_ARRAY,0,0,0,E,L,_,1,$.RGBA,$.UNSIGNED_BYTE,new Uint8Array(Y));let T=E<<3;U[T]=q.x,U[T+1]=q.y,U[T+2]=L,U[T+3]=_,U[T+4]=L,U[T+5]=_,U[T+6]=E,U[T+7]=0,E++}if(E===0)continue;$.bindBuffer($.ARRAY_BUFFER,this._instanceBuffer),$.bufferSubData($.ARRAY_BUFFER,0,U,0,E<<3),$.bindVertexArray(this._vao),$.drawArraysInstanced($.TRIANGLES,0,6,E),$.bindVertexArray(null)}}clear(){if(!this._gl)return;this._gl.clearColor(0,0,0,0),this._gl.clear(this._gl.COLOR_BUFFER_BIT)}get initialized(){return this._initialized}destroy(){let J=this._gl;if(J)J.deleteProgram(this._program),J.deleteVertexArray(this._vao),J.deleteBuffer(this._instanceBuffer),J.deleteTexture(this._texArray);this._gl=null,this._program=null,this._vao=null,this._instanceBuffer=null,this._texArray=null,this._canvas=null,this._initialized=!1,this._initPromise=null}}class R extends EventTarget{static MAX_PENDING_DEMANDS=3;static _hasAlphaBug=null;static _hasBitmapBug=null;_loaded;_init;_onDemandRender;_offscreenRender;_video;_videoWidth=0;_videoHeight=0;_videoColorSpace=null;_canvas;_canvasParent;_bufferCanvas;_bufferCtx;_canvasctrl;_ctx=null;_lastRenderTime=0;_playstate=!0;_destroyed=!1;_workerReady=!1;_ro;_worker;_pendingDemandTimes=[];_boundResize;_boundTimeUpdate;_boundSetRate;_boundUpdateColorSpace;_boundHandleRVFC;_gpuRenderer=null;_rendererType="canvas2d";_onCanvasFallback;_lastRenderWidth=0;_lastRenderHeight=0;timeOffset;debug;prescaleFactor;prescaleHeightLimit;maxRenderHeight;busy=!1;renderAhead;constructor(J){super();if(!globalThis.Worker)throw this.destroy(Error("Worker not supported"));if(!J)throw this.destroy(Error("No options provided"));this._loaded=new Promise((Q)=>{this._init=Q});let K=R._test();this._onDemandRender="requestVideoFrameCallback"in HTMLVideoElement.prototype&&(J.onDemandRender??!0),this._onCanvasFallback=J.onCanvasFallback;let Z=!J.canvas&&(f()||p());if(this._offscreenRender="transferControlToOffscreen"in HTMLCanvasElement.prototype&&!J.canvas&&!Z&&(J.offscreenRender??!0),this.timeOffset=J.timeOffset||0,this._video=J.video,this._canvas=J.canvas,this._video&&!this._canvas)this._canvasParent=document.createElement("div"),this._canvasParent.className="AkariSub",this._canvasParent.style.position="relative",this._canvas=this._createCanvas(),this._video.insertAdjacentElement("afterend",this._canvasParent);else if(!this._canvas)throw this.destroy(Error("Don't know where to render: you should give video or canvas in options."));this._bufferCanvas=document.createElement("canvas");let N=this._bufferCanvas.getContext("2d");if(!N)throw this.destroy(Error("Canvas rendering not supported"));if(this._bufferCtx=N,Z)this._initGPURenderer();else if(!this._offscreenRender)this._ctx=this._canvas.getContext("2d");if(this._canvasctrl=this._offscreenRender?this._canvas.transferControlToOffscreen():this._canvas,this._lastRenderTime=0,this.debug=!!J.debug,this.prescaleFactor=J.prescaleFactor||1,this.prescaleHeightLimit=J.prescaleHeightLimit||1080,this.maxRenderHeight=J.maxRenderHeight||0,this.renderAhead=J.renderAhead??0,this._boundResize=this.resize.bind(this),this._boundTimeUpdate=this._timeupdate.bind(this),this._boundSetRate=()=>this.setRate(this._video.playbackRate),this._boundUpdateColorSpace=this._updateColorSpace.bind(this),this._boundHandleRVFC=this._handleRVFC.bind(this),this._video)this.setVideo(this._video);if(this._onDemandRender)this.busy=!1,this._pendingDemandTimes.length=0;this._worker=new Worker(J.workerUrl||"akarisub-worker.js"),this._worker.onmessage=(Q)=>this._onmessage(Q),this._worker.onerror=(Q)=>this._error(Q),K.then(()=>{if(this._worker.postMessage({target:"init",wasmUrl:J.wasmUrl??"akarisub-worker.wasm",asyncRender:typeof createImageBitmap<"u"&&(J.asyncRender??!0),onDemandRender:this._onDemandRender,initialTime:(this._video?.currentTime??0)+this.timeOffset,width:this._canvasctrl.width||0,height:this._canvasctrl.height||0,blendMode:J.blendMode??"wasm",subUrl:J.subUrl,subContent:J.subContent||null,fonts:J.fonts||[],availableFonts:J.availableFonts||{"liberation sans":"./default.woff2"},fallbackFonts:J.fallbackFonts||["liberation sans"],debug:this.debug,targetFps:J.targetFps||24,dropAllAnimations:J.dropAllAnimations,dropAllBlur:J.dropAllBlur,clampPos:J.clampPos,libassMemoryLimit:J.libassMemoryLimit??128,libassGlyphLimit:J.libassGlyphLimit??2048,useLocalFonts:typeof globalThis.queryLocalFonts<"u"&&(J.useLocalFonts??!0),hasBitmapBug:R._hasBitmapBug}),this._offscreenRender)this.sendMessage("offscreenCanvas",{},[this._canvasctrl])})}static async _testImageBugs(){if(R._hasBitmapBug!==null)return;let J=document.createElement("canvas"),K=J.getContext("2d",{willReadFrequently:!0});if(!K)throw Error("Canvas rendering not supported");if(typeof ImageData.prototype.constructor==="function")try{new ImageData(new Uint8ClampedArray([0,0,0,0]),1,1)}catch{console.log("Detected that ImageData is not constructable despite browser saying so")}let Z=document.createElement("canvas"),N=Z.getContext("2d",{willReadFrequently:!0});if(!N)throw Error("Canvas rendering not supported");J.width=Z.width=1,J.height=Z.height=1,K.clearRect(0,0,1,1),N.clearRect(0,0,1,1);let Q=N.getImageData(0,0,1,1).data;K.putImageData(new ImageData(new Uint8ClampedArray([0,255,0,0]),1,1),0,0),N.drawImage(J,0,0);let F=N.getImageData(0,0,1,1).data;if(R._hasAlphaBug=Q[1]!==F[1],R._hasAlphaBug)console.log("Detected a browser having issue with transparent pixels, applying workaround");if(typeof createImageBitmap<"u"){let $=new Uint8ClampedArray([255,0,255,0,255]).subarray(1,5);N.drawImage(await createImageBitmap(new ImageData($,1)),0,0);let{data:U}=N.getImageData(0,0,1,1);R._hasBitmapBug=!1;for(let O=0;O<U.length;O++)if(Math.abs($[O]-U[O])>15){R._hasBitmapBug=!0,console.log("Detected a browser having issue with partial bitmaps, applying workaround");break}}else R._hasBitmapBug=!1;J.remove(),Z.remove()}static async _test(){await R._testImageBugs()}async _initGPURenderer(){if(f())try{let J=new v;if(await J.init(),!this._canvas)return;await J.setCanvas(this._canvas,Math.max(1,this._canvas.width||1),Math.max(1,this._canvas.height||1)),this._gpuRenderer=J,this._rendererType="webgpu",console.log("[AkariSub] Using WebGPU renderer");return}catch(J){console.warn("[AkariSub] WebGPU init failed, trying WebGL2:",J)}if(p())try{let J=new x;if(await J.init(),!this._canvas)return;await J.setCanvas(this._canvas,Math.max(1,this._canvas.width||1),Math.max(1,this._canvas.height||1)),this._gpuRenderer=J,this._rendererType="webgl2",console.log("[AkariSub] Using WebGL2 renderer");return}catch(J){console.warn("[AkariSub] WebGL2 init failed, falling back to Canvas2D:",J)}if(this._rendererType="canvas2d",!this._offscreenRender&&!this._ctx)this._ctx=this._canvas.getContext("2d");this.sendMessage("setAsyncRender",{value:!1}),this._onCanvasFallback?.()}get rendererType(){return this._rendererType}get isUsingWebGPU(){return this._rendererType==="webgpu"}get isUsingGPURenderer(){return this._gpuRenderer!==null}_createCanvas(){return this._canvas=document.createElement("canvas"),this._canvas.style.display="block",this._canvas.style.position="absolute",this._canvas.style.pointerEvents="none",this._canvasParent.appendChild(this._canvas),this._canvas}resize(J=0,K=0,Z=0,N=0,Q=this._video?.paused??!1){if((!J||!K)&&this._video){let F=c(this._video),$;if(this._videoWidth){let U=this._video.videoWidth/this._videoWidth,O=this._video.videoHeight/this._videoHeight;$=w((F.width||0)/U,(F.height||0)/O,this.prescaleFactor,this.prescaleHeightLimit,this.maxRenderHeight)}else $=w(F.width||0,F.height||0,this.prescaleFactor,this.prescaleHeightLimit,this.maxRenderHeight);if(J=$.width,K=$.height,this._canvasParent)Z=F.y-(this._canvasParent.getBoundingClientRect().top-this._video.getBoundingClientRect().top),N=F.x;this._canvas.style.width=F.width+"px",this._canvas.style.height=F.height+"px"}if(this._canvas.style.top=Z+"px",this._canvas.style.left=N+"px",J>0&&K>0)this._canvasctrl.width=J,this._canvasctrl.height=K;if(this._gpuRenderer&&J>0&&K>0)this._gpuRenderer.updateSize(J,K);if(Q&&this.busy===!1)this.busy=!0;else Q=!1;this.sendMessage("canvas",{width:J,height:K,videoWidth:this._videoWidth||this._video?.videoWidth||0,videoHeight:this._videoHeight||this._video?.videoHeight||0,force:Q})}_timeupdate(J){let Z={seeking:!0,waiting:!0,playing:!1}[J.type];if(Z!=null)this._playstate=Z;this.setCurrentTime(this._video.paused||this._playstate,this._video.currentTime+this.timeOffset)}setVideo(J){if(J instanceof HTMLVideoElement){if(this._removeListeners(),this._video=J,this._onDemandRender){if(!this._destroyed&&this._video===J)J.requestVideoFrameCallback(this._boundHandleRVFC)}else this._playstate=J.paused,J.addEventListener("timeupdate",this._boundTimeUpdate,!1),J.addEventListener("progress",this._boundTimeUpdate,!1),J.addEventListener("waiting",this._boundTimeUpdate,!1),J.addEventListener("seeking",this._boundTimeUpdate,!1),J.addEventListener("playing",this._boundTimeUpdate,!1),J.addEventListener("ratechange",this._boundSetRate,!1),J.addEventListener("resize",this._boundResize,!1);if("VideoFrame"in window){if(J.addEventListener("loadedmetadata",this._boundUpdateColorSpace,!1),J.readyState>2)this._updateColorSpace()}if(J.videoWidth>0)this.resize();if(typeof ResizeObserver<"u"){if(!this._ro)this._ro=new ResizeObserver(()=>this.resize());this._ro.observe(J)}}else this._error(Error("Video element invalid!"))}runBenchmark(){this.sendMessage("runBenchmark")}setTrackByUrl(J){if(this.sendMessage("setTrackByUrl",{url:J}),this._reAttachOffscreen(),this._ctx)this._ctx.filter="none"}setTrack(J){if(this.sendMessage("setTrack",{content:J}),this._reAttachOffscreen(),this._ctx)this._ctx.filter="none"}freeTrack(){this.sendMessage("freeTrack")}setIsPaused(J){this.sendMessage("video",{isPaused:J})}setRate(J){this.sendMessage("video",{rate:J})}setCurrentTime(J,K,Z){this.sendMessage("video",{isPaused:J,currentTime:K,rate:Z,colorSpace:this._videoColorSpace})}createEvent(J){this.sendMessage("createEvent",{event:J})}setEvent(J,K){this.sendMessage("setEvent",{event:J,index:K})}removeEvent(J){this.sendMessage("removeEvent",{index:J})}async getEvents(){return(await this._fetchFromWorker({target:"getEvents"})).events??[]}styleOverride(J){this.sendMessage("styleOverride",{style:J})}disableStyleOverride(){this.sendMessage("disableStyleOverride")}createStyle(J){this.sendMessage("createStyle",{style:J})}setStyle(J,K){this.sendMessage("setStyle",{style:J,index:K})}removeStyle(J){this.sendMessage("removeStyle",{index:J})}async getStyles(){return(await this._fetchFromWorker({target:"getStyles"})).styles??[]}addFont(J){this.sendMessage("addFont",{font:J})}setDefaultFont(J){this.sendMessage("defaultFont",{font:J})}async getStats(){let K=(await this._fetchFromWorker({target:"getStats"})).stats;return{framesRendered:K.framesRendered??0,framesDropped:K.framesDropped??0,avgRenderTime:K.avgRenderTime??0,maxRenderTime:K.maxRenderTime??0,minRenderTime:K.minRenderTime??0,lastRenderTime:K.lastRenderTime??0,pendingRenders:K.pendingRenders??0,totalEvents:K.totalEvents??0,cacheHits:K.cacheHits??0,cacheMisses:K.cacheMisses??0,renderFps:K.avgRenderTime&&K.avgRenderTime>0?Math.round(1000/K.avgRenderTime):0,usingWorker:!0,offscreenRender:this._offscreenRender,onDemandRender:this._onDemandRender}}async resetStats(){await this._fetchFromWorker({target:"resetStats"})}async getEventCount(){return(await this._fetchFromWorker({target:"getEventCount"})).count}async getStyleCount(){return(await this._fetchFromWorker({target:"getStyleCount"})).count}_sendLocalFont(J){try{globalThis.queryLocalFonts().then((K)=>{let Z=K?.find((N)=>N.fullName.toLowerCase()===J);if(Z)Z.blob().then((N)=>{N.arrayBuffer().then((Q)=>{this.addFont(new Uint8Array(Q))})})})}catch(K){console.warn("Local fonts API:",K)}}_getLocalFont(J){try{if(navigator?.permissions?.query)navigator.permissions.query({name:"local-fonts"}).then((K)=>{if(K.state==="granted")this._sendLocalFont(J.font)});else this._sendLocalFont(J.font)}catch(K){console.warn("Local fonts API:",K)}}_unbusy(){if(this._pendingDemandTimes.length>0){if(this._pendingDemandTimes.length>1){let K=this._pendingDemandTimes[this._pendingDemandTimes.length-1];this._pendingDemandTimes.length=0,this._pendingDemandTimes.push(K)}let J=this._pendingDemandTimes.shift();if(J){this._demandRender(J);return}}this.busy=!1}_enqueueDemand(J){let K=this._pendingDemandTimes;if(K.length>0){let Z=K[K.length-1];if(Math.abs(Z.mediaTime-J.mediaTime)>0.25)K.length=0}if(K.length>=R.MAX_PENDING_DEMANDS)K.shift();K.push(J)}_handleRVFC(J,K){if(this._destroyed)return;let Z=this._video?.playbackRate??1,Q={mediaTime:K.mediaTime+this.renderAhead*Z,width:K.width,height:K.height};if(!this._workerReady){this._enqueueDemand(Q),this._video.requestVideoFrameCallback(this._boundHandleRVFC);return}if(this.busy)this._enqueueDemand(Q);else this.busy=!0,this._demandRender(Q);this._video.requestVideoFrameCallback(this._boundHandleRVFC)}_demandRender(J){if(J.width!==this._videoWidth||J.height!==this._videoHeight)this._videoWidth=J.width,this._videoHeight=J.height,this.resize();this.sendMessage("demand",{time:J.mediaTime+this.timeOffset})}_detachOffscreen(){if(!this._offscreenRender||this._ctx)return;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas,this._ctx=this._canvasctrl.getContext("2d"),this.sendMessage("detachOffscreen"),this.busy=!1,this._pendingDemandTimes.length=0,this.resize(0,0,0,0,!0)}_reAttachOffscreen(){if(!this._offscreenRender||!this._ctx)return;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas.transferControlToOffscreen(),this._ctx=!1,this.sendMessage("offscreenCanvas",{},[this._canvasctrl]),this.resize(0,0,0,0,!0)}_updateColorSpace(){this._video.requestVideoFrameCallback(()=>{try{let J=new globalThis.VideoFrame(this._video);this._videoColorSpace=u[J.colorSpace.matrix]??null,J.close(),this.sendMessage("getColorSpace")}catch(J){console.warn(J)}})}_verifyColorSpace(J){let{subtitleColorSpace:K,videoColorSpace:Z=this._videoColorSpace}=J;if(!K||!Z)return;if(K===Z)return;this._detachOffscreen();let N=y[K]?.[Z];if(N&&this._ctx)this._ctx.filter=`url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><filter id='f'><feColorMatrix type='matrix' values='${N} 0 0 0 0 0 1 0'/></filter></svg>#f")`}_render(J){this._unbusy();let{width:K,height:Z}=J;if(this.debug)J.times.IPCTime=Date.now()-(J.times.JSRenderTime||0);if(this._canvasctrl.width!==K||this._canvasctrl.height!==Z){if(this._canvasctrl.width=K,this._canvasctrl.height=Z,this._lastRenderWidth=K,this._lastRenderHeight=Z,this._gpuRenderer)this._gpuRenderer.updateSize(K,Z);this._verifyColorSpace({subtitleColorSpace:J.colorSpace})}if(this._gpuRenderer){this._renderGPU(J);return}if(!this._ctx)return;let Q=this._ctx,F=J.images,$=F.length;if(Q.clearRect(0,0,K,Z),J.asyncRender)for(let U=0;U<$;U++){let O=F[U];if(O.image)Q.drawImage(O.image,O.x,O.y),O.image.close()}else{let U=R._hasAlphaBug??!1;for(let O=0;O<$;O++){let E=F[O];if(E.image){let{w:q,h:L}=E,_=new Uint8ClampedArray(E.image),Y=m(_,U);Q.putImageData(new ImageData(Y,q,L),E.x,E.y)}}}if(this.debug){J.times.JSRenderTime=Date.now()-(J.times.JSRenderTime||0)-(J.times.IPCTime||0);let U=0,O=J.times.bitmaps||$;delete J.times.bitmaps;for(let E in J.times)U+=J.times[E]||0;console.log("Bitmaps: "+O+" Total: "+(U|0)+"ms",J.times)}}_renderGPU(J){let K=this._gpuRenderer;if(!K)return;if(J.images.length===0){K.clear();return}if(J.asyncRender){let Z=J.images.filter((N)=>N.image instanceof ImageBitmap).map((N)=>({image:N.image,x:N.x,y:N.y}));K.renderBitmaps(Z,this._canvasctrl.width,this._canvasctrl.height);for(let N of J.images)if(N.image instanceof ImageBitmap)N.image.close()}else K.render(J.images,this._canvasctrl.width,this._canvasctrl.height);if(this.debug){J.times.JSRenderTime=Date.now()-(J.times.JSRenderTime||0)-(J.times.IPCTime||0);let Z=0,N=J.times.bitmaps||J.images.length;delete J.times.bitmaps;for(let Q in J.times)Z+=J.times[Q]||0;console.log(`[${this._rendererType.toUpperCase()}] Bitmaps: `+N+" Total: "+(Z|0)+"ms",J.times)}}_ready(){if(this._workerReady=!0,this._init(),this._onDemandRender&&this._video){this.setCurrentTime(this._video.paused,this._video.currentTime+this.timeOffset,this._video.playbackRate);let J=this._pendingDemandTimes.length>0?this._pendingDemandTimes[this._pendingDemandTimes.length-1]:{mediaTime:this._video.currentTime+this.renderAhead*(this._video.playbackRate||1),width:this._video.videoWidth,height:this._video.videoHeight};this._pendingDemandTimes.length=0,this.busy=!0,this._demandRender(J)}this.dispatchEvent(new CustomEvent("ready"))}_partial_ready(){this.dispatchEvent(new CustomEvent("partial_ready"))}async sendMessage(J,K={},Z){if(await this._loaded,Z)this._worker.postMessage({target:J,transferable:Z,...K},[...Z]);else this._worker.postMessage({target:J,...K})}_fetchFromWorker(J){return new Promise((K,Z)=>{try{let N=J.target,Q=setTimeout(()=>{U(),Z(Error("Error: Timeout while trying to fetch "+N))},5000),F=(O)=>{if(O.data.target===N)U(),K(O.data)},$=(O)=>{U(),Z(O instanceof Error?O:O.error||Error("Worker error"))},U=()=>{this._worker.removeEventListener("message",F),this._worker.removeEventListener("error",$),clearTimeout(Q)};this._worker.addEventListener("message",F),this._worker.addEventListener("error",$),this._worker.postMessage(J)}catch(N){Z(N)}})}_console(J){console[J.command].apply(console,JSON.parse(J.content))}_onmessage(J){let K=J.data.target;if(K==="error"){this._error(J.data.error||"Unknown worker error");return}let Z=this["_"+K];if(Z)Z.call(this,J.data)}_error(J){let K=J instanceof Error?J:J instanceof ErrorEvent?J.error||Error(J.message):Error(String(J)),Z=J instanceof Event?new ErrorEvent(J.type,J):new ErrorEvent("error",{error:K});return this.dispatchEvent(Z),console.error(K),K}_removeListeners(){if(this._video){if(this._ro)this._ro.unobserve(this._video);if(this._ctx)this._ctx.filter="none";this._video.removeEventListener("timeupdate",this._boundTimeUpdate),this._video.removeEventListener("progress",this._boundTimeUpdate),this._video.removeEventListener("waiting",this._boundTimeUpdate),this._video.removeEventListener("seeking",this._boundTimeUpdate),this._video.removeEventListener("playing",this._boundTimeUpdate),this._video.removeEventListener("ratechange",this._boundSetRate),this._video.removeEventListener("resize",this._boundResize),this._video.removeEventListener("loadedmetadata",this._boundUpdateColorSpace)}}destroy(J){let K=J?this._error(J):void 0;if(this._video&&this._canvasParent)this._video.parentNode?.removeChild(this._canvasParent);if(this._gpuRenderer)this._gpuRenderer.destroy(),this._gpuRenderer=null,this._rendererType="canvas2d";return this._destroyed=!0,this._removeListeners(),this.sendMessage("destroy"),this._worker?.terminate(),K}}})();
|
|
156
|
+
`),$=J.createProgram();if(J.attachShader($,Z),J.attachShader($,Q),J.linkProgram($),!J.getProgramParameter($,J.LINK_STATUS))throw Error(`WebGL2 program link failed: ${J.getProgramInfoLog($)}`);J.deleteShader(Z),J.deleteShader(Q),this._program=$,this._resolutionLoc=J.getUniformLocation($,"u_resolution"),this._texArraySizeLoc=J.getUniformLocation($,"u_texArraySize"),this._vao=J.createVertexArray(),J.bindVertexArray(this._vao),this._instanceBuffer=J.createBuffer(),J.bindBuffer(J.ARRAY_BUFFER,this._instanceBuffer),J.bufferData(J.ARRAY_BUFFER,8192,J.DYNAMIC_DRAW);let N=J.getAttribLocation($,"a_destRect");J.enableVertexAttribArray(N),J.vertexAttribPointer(N,4,J.FLOAT,!1,32,0),J.vertexAttribDivisor(N,1);let O=J.getAttribLocation($,"a_texInfo");J.enableVertexAttribArray(O),J.vertexAttribPointer(O,4,J.FLOAT,!1,32,16),J.vertexAttribDivisor(O,1),J.bindVertexArray(null),this._texArray=J.createTexture(),this._allocateTextureArray(256,256,32),J.enable(J.BLEND),J.blendEquation(J.FUNC_ADD),J.blendFunc(J.ONE,J.ONE_MINUS_SRC_ALPHA),this._initialized=!0}_nextPow2(J){return J--,J|=J>>1,J|=J>>2,J|=J>>4,J|=J>>8,J|=J>>16,J+1}_allocateTextureArray(J,Z,Q){let $=this._gl,N=this._nextPow2(Math.max(J,64)),O=this._nextPow2(Math.max(Z,64)),K=Math.min(this._nextPow2(Math.max(Q,16)),256);$.bindTexture($.TEXTURE_2D_ARRAY,this._texArray),$.texImage3D($.TEXTURE_2D_ARRAY,0,$.RGBA8,N,O,K,0,$.RGBA,$.UNSIGNED_BYTE,null),$.texParameteri($.TEXTURE_2D_ARRAY,$.TEXTURE_MIN_FILTER,$.NEAREST),$.texParameteri($.TEXTURE_2D_ARRAY,$.TEXTURE_MAG_FILTER,$.NEAREST),$.texParameteri($.TEXTURE_2D_ARRAY,$.TEXTURE_WRAP_S,$.CLAMP_TO_EDGE),$.texParameteri($.TEXTURE_2D_ARRAY,$.TEXTURE_WRAP_T,$.CLAMP_TO_EDGE),this._texWidth=N,this._texHeight=O,this._texLayers=K}_ensureTextureArray(J,Z,Q){let $=Math.min(Q,256);if(J<=this._texWidth&&Z<=this._texHeight&&$<=this._texLayers)return;let N=this._nextPow2(Math.max(this._texWidth,J)),O=this._nextPow2(Math.max(this._texHeight,Z)),K=Math.min(this._nextPow2(Math.max(this._texLayers,$,$+16)),256);this._allocateTextureArray(N,O,K)}async setCanvas(J,Z,Q){if(await this.init(),Z<=0||Q<=0)return;this._canvas=J,J.width=Z,J.height=Q,this._initGL(),this._gl.viewport(0,0,Z,Q),this._lastCanvasWidth=Z,this._lastCanvasHeight=Q}updateSize(J,Z){if(!this._gl||!this._canvas||J<=0||Z<=0)return;if(J===this._lastCanvasWidth&&Z===this._lastCanvasHeight)return;this._canvas.width=J,this._canvas.height=Z,this._gl.viewport(0,0,J,Z),this._lastCanvasWidth=J,this._lastCanvasHeight=Z}renderBitmaps(J,Z,Q){if(!this._gl||!this._initialized)return;let $=J.length;if($===0){this.clear();return}let N=0,O=0;for(let U=0;U<$;U++){let{image:E}=J[U];if(E.width>N)N=E.width;if(E.height>O)O=E.height}this._ensureTextureArray(N,O,Math.min($,256));let K=this._gl;K.clearColor(0,0,0,0),K.clear(K.COLOR_BUFFER_BIT),K.useProgram(this._program),K.uniform2f(this._resolutionLoc,this._lastCanvasWidth,this._lastCanvasHeight),K.uniform2i(this._texArraySizeLoc,this._texWidth,this._texHeight),K.activeTexture(K.TEXTURE0),K.bindTexture(K.TEXTURE_2D_ARRAY,this._texArray),K.pixelStorei(K.UNPACK_FLIP_Y_WEBGL,!1);let F=this._instanceData,G=0;while(G<$){let U=0;while(G<$&&U<256){let E=J[G++],M=E.image.width,q=E.image.height;if(M<=0||q<=0)continue;K.texSubImage3D(K.TEXTURE_2D_ARRAY,0,0,0,U,M,q,1,K.RGBA,K.UNSIGNED_BYTE,E.image);let Y=U<<3;F[Y]=E.x,F[Y+1]=E.y,F[Y+2]=M,F[Y+3]=q,F[Y+4]=M,F[Y+5]=q,F[Y+6]=U,F[Y+7]=0,U++}if(U===0)continue;K.bindBuffer(K.ARRAY_BUFFER,this._instanceBuffer),K.bufferSubData(K.ARRAY_BUFFER,0,F,0,U<<3),K.bindVertexArray(this._vao),K.drawArraysInstanced(K.TRIANGLES,0,6,U),K.bindVertexArray(null)}}render(J,Z,Q){if(!this._gl||!this._initialized)return;let $=J.length;if($===0){this.clear();return}let N=0,O=0;for(let U=0;U<$;U++){let{w:E,h:M}=J[U];if(E>N)N=E;if(M>O)O=M}this._ensureTextureArray(N,O,Math.min($,256));let K=this._gl;K.clearColor(0,0,0,0),K.clear(K.COLOR_BUFFER_BIT),K.useProgram(this._program),K.uniform2f(this._resolutionLoc,this._lastCanvasWidth,this._lastCanvasHeight),K.uniform2i(this._texArraySizeLoc,this._texWidth,this._texHeight),K.activeTexture(K.TEXTURE0),K.bindTexture(K.TEXTURE_2D_ARRAY,this._texArray),K.pixelStorei(K.UNPACK_FLIP_Y_WEBGL,!1);let F=this._instanceData,G=0;while(G<$){let U=0;while(G<$&&U<256){let E=J[G++],M=E.w,q=E.h;if(M<=0||q<=0)continue;let Y=E.image;if(Y instanceof ImageBitmap)K.texSubImage3D(K.TEXTURE_2D_ARRAY,0,0,0,U,M,q,1,K.RGBA,K.UNSIGNED_BYTE,Y);else if(Y instanceof ArrayBuffer||_J(Y)){let B=Y instanceof ArrayBuffer?new Uint8Array(Y):Y;K.texSubImage3D(K.TEXTURE_2D_ARRAY,0,0,0,U,M,q,1,K.RGBA,K.UNSIGNED_BYTE,B)}let L=U<<3;F[L]=E.x,F[L+1]=E.y,F[L+2]=M,F[L+3]=q,F[L+4]=M,F[L+5]=q,F[L+6]=U,F[L+7]=0,U++}if(U===0)continue;K.bindBuffer(K.ARRAY_BUFFER,this._instanceBuffer),K.bufferSubData(K.ARRAY_BUFFER,0,F,0,U<<3),K.bindVertexArray(this._vao),K.drawArraysInstanced(K.TRIANGLES,0,6,U),K.bindVertexArray(null)}}clear(){if(!this._gl)return;this._gl.clearColor(0,0,0,0),this._gl.clear(this._gl.COLOR_BUFFER_BIT)}get initialized(){return this._initialized}destroy(){let J=this._gl;if(J)J.deleteProgram(this._program),J.deleteVertexArray(this._vao),J.deleteBuffer(this._instanceBuffer),J.deleteTexture(this._texArray);this._gl=null,this._program=null,this._vao=null,this._instanceBuffer=null,this._texArray=null,this._canvas=null,this._initialized=!1,this._initPromise=null}}var ZJ=0.008,LJ=ZJ*1000,MJ=16,TJ=()=>{if(typeof navigator>"u")return!1;let J=navigator.userAgent||"",Z=navigator.vendor||"",Q=/\b(iPhone|iPad|iPod)\b/i.test(J);if(!/AppleWebKit/i.test(J))return!1;if(Q)return!0;if(/\b(Chrome|Chromium|Edg|OPR|SamsungBrowser|Firefox)\b/i.test(J))return!1;return Z.includes("Apple")};class H extends EventTarget{static MAX_PENDING_DEMANDS=3;static _hasAlphaBug=null;static _hasBitmapBug=null;_loaded;_init;_onDemandRender;_offscreenRender;_video;_videoWidth=0;_videoHeight=0;_videoColorSpace=null;_canvas;_canvasParent;_bufferCanvas;_bufferCtx;_canvasctrl;_ctx=null;_lastRenderTime=0;_playstate=!0;_destroyed=!1;_workerReady=!1;_ro;_worker;_pendingDemandTimes=[];_isLikelyWebKit;_activeDemandStartedAt=0;_smoothedDemandLatencyMs;_boundResize;_boundTimeUpdate;_boundSetRate;_boundUpdateColorSpace;_boundHandleRVFC;_gpuRenderer=null;_rendererType="canvas2d";_onCanvasFallback;_lastRenderWidth=0;_lastRenderHeight=0;_gpuBitmapImages=[];timeOffset;debug;prescaleFactor;prescaleHeightLimit;maxRenderHeight;busy=!1;renderAhead;constructor(J){super();if(!globalThis.Worker)throw this.destroy(Error("Worker not supported"));if(!J)throw this.destroy(Error("No options provided"));this._loaded=new Promise((O)=>{this._init=O}),this._isLikelyWebKit=TJ(),this._smoothedDemandLatencyMs=this._isLikelyWebKit?MJ:LJ;let Z=H._test();this._onDemandRender="requestVideoFrameCallback"in HTMLVideoElement.prototype&&(J.onDemandRender??!0),this._onCanvasFallback=J.onCanvasFallback;let Q=!this._isLikelyWebKit&&!J.canvas&&(f()||p()),$=typeof createImageBitmap<"u"&&(J.asyncRender??!this._isLikelyWebKit);if(this._offscreenRender="transferControlToOffscreen"in HTMLCanvasElement.prototype&&!J.canvas&&!Q&&(J.offscreenRender??!0),this.timeOffset=J.timeOffset||0,this._video=J.video,this._canvas=J.canvas,this._video&&!this._canvas)this._canvasParent=document.createElement("div"),this._canvasParent.className="AkariSub",this._canvasParent.style.position="relative",this._canvas=this._createCanvas(),this._video.insertAdjacentElement("afterend",this._canvasParent);else if(!this._canvas)throw this.destroy(Error("Don't know where to render: you should give video or canvas in options."));this._bufferCanvas=document.createElement("canvas");let N=this._bufferCanvas.getContext("2d");if(!N)throw this.destroy(Error("Canvas rendering not supported"));if(this._bufferCtx=N,Q)this._initGPURenderer();else if(!this._offscreenRender)this._ctx=this._canvas.getContext("2d",{alpha:!0,desynchronized:!0});if(this._canvasctrl=this._offscreenRender?this._canvas.transferControlToOffscreen():this._canvas,this._lastRenderTime=0,this.debug=!!J.debug,this.prescaleFactor=J.prescaleFactor||1,this.prescaleHeightLimit=J.prescaleHeightLimit||1080,this.maxRenderHeight=J.maxRenderHeight||0,this.renderAhead=J.renderAhead??ZJ,this._boundResize=this.resize.bind(this),this._boundTimeUpdate=this._timeupdate.bind(this),this._boundSetRate=()=>this.setRate(this._video.playbackRate),this._boundUpdateColorSpace=this._updateColorSpace.bind(this),this._boundHandleRVFC=this._handleRVFC.bind(this),this._video)this.setVideo(this._video);if(this._onDemandRender)this.busy=!1,this._pendingDemandTimes.length=0;this._worker=new Worker(J.workerUrl||"akarisub-worker.js"),this._worker.onmessage=(O)=>this._onmessage(O),this._worker.onerror=(O)=>this._error(O),Z.then(()=>{if(this._worker.postMessage({target:"init",wasmUrl:J.wasmUrl??"akarisub-worker.wasm",asyncRender:$,fullTrackWarmup:J.fullTrackWarmup??!1,onDemandRender:this._onDemandRender,initialTime:(this._video?.currentTime??0)+this.timeOffset,width:this._canvasctrl.width||0,height:this._canvasctrl.height||0,blendMode:J.blendMode??"wasm",subUrl:J.subUrl,subContent:J.subContent||null,fonts:J.fonts||[],availableFonts:J.availableFonts||{"liberation sans":"./default.woff2"},fallbackFonts:J.fallbackFonts||["liberation sans"],debug:this.debug,targetFps:J.targetFps||24,dropAllAnimations:J.dropAllAnimations,dropAllBlur:J.dropAllBlur,clampPos:J.clampPos,libassMemoryLimit:J.libassMemoryLimit??128,libassGlyphLimit:J.libassGlyphLimit??2048,useLocalFonts:typeof globalThis.queryLocalFonts<"u"&&(J.useLocalFonts??!0),hasBitmapBug:H._hasBitmapBug}),this._offscreenRender)this.sendMessage("offscreenCanvas",{},[this._canvasctrl])})}static async _testImageBugs(){if(H._hasBitmapBug!==null)return;let J=document.createElement("canvas"),Z=J.getContext("2d",{willReadFrequently:!0});if(!Z)throw Error("Canvas rendering not supported");if(typeof ImageData.prototype.constructor==="function")try{new ImageData(new Uint8ClampedArray([0,0,0,0]),1,1)}catch{console.log("Detected that ImageData is not constructable despite browser saying so")}let Q=document.createElement("canvas"),$=Q.getContext("2d",{willReadFrequently:!0});if(!$)throw Error("Canvas rendering not supported");J.width=Q.width=1,J.height=Q.height=1,Z.clearRect(0,0,1,1),$.clearRect(0,0,1,1);let N=$.getImageData(0,0,1,1).data;Z.putImageData(new ImageData(new Uint8ClampedArray([0,255,0,0]),1,1),0,0),$.drawImage(J,0,0);let O=$.getImageData(0,0,1,1).data;if(H._hasAlphaBug=N[1]!==O[1],H._hasAlphaBug)console.log("Detected a browser having issue with transparent pixels, applying workaround");if(typeof createImageBitmap<"u"){let K=new Uint8ClampedArray([255,0,255,0,255]).subarray(1,5);$.drawImage(await createImageBitmap(new ImageData(K,1)),0,0);let{data:F}=$.getImageData(0,0,1,1);H._hasBitmapBug=!1;for(let G=0;G<F.length;G++)if(Math.abs(K[G]-F[G])>15){H._hasBitmapBug=!0,console.log("Detected a browser having issue with partial bitmaps, applying workaround");break}}else H._hasBitmapBug=!1;J.remove(),Q.remove()}static async _test(){await H._testImageBugs()}async _initGPURenderer(){if(f())try{let J=new v;if(await J.init(),!this._canvas)return;await J.setCanvas(this._canvas,Math.max(1,this._canvas.width||1),Math.max(1,this._canvas.height||1)),this._gpuRenderer=J,this._rendererType="webgpu",console.log("[AkariSub] Using WebGPU renderer");return}catch(J){console.warn("[AkariSub] WebGPU init failed, trying WebGL2:",J)}if(p())try{let J=new x;if(await J.init(),!this._canvas)return;await J.setCanvas(this._canvas,Math.max(1,this._canvas.width||1),Math.max(1,this._canvas.height||1)),this._gpuRenderer=J,this._rendererType="webgl2",console.log("[AkariSub] Using WebGL2 renderer");return}catch(J){console.warn("[AkariSub] WebGL2 init failed, falling back to Canvas2D:",J)}if(this._rendererType="canvas2d",!this._offscreenRender&&!this._ctx)this._ctx=this._canvas.getContext("2d",{alpha:!0,desynchronized:!0});this.sendMessage("setAsyncRender",{value:!1}),this._onCanvasFallback?.()}get rendererType(){return this._rendererType}get isUsingWebGPU(){return this._rendererType==="webgpu"}get isUsingGPURenderer(){return this._gpuRenderer!==null}_createCanvas(){return this._canvas=document.createElement("canvas"),this._canvas.style.display="block",this._canvas.style.position="absolute",this._canvas.style.pointerEvents="none",this._canvasParent.appendChild(this._canvas),this._canvas}resize(J=0,Z=0,Q=0,$=0,N=this._video?.paused??!1){if((!J||!Z)&&this._video){let O=c(this._video),K;if(this._videoWidth){let F=this._video.videoWidth/this._videoWidth,G=this._video.videoHeight/this._videoHeight;K=w((O.width||0)/F,(O.height||0)/G,this.prescaleFactor,this.prescaleHeightLimit,this.maxRenderHeight)}else K=w(O.width||0,O.height||0,this.prescaleFactor,this.prescaleHeightLimit,this.maxRenderHeight);if(J=K.width,Z=K.height,this._canvasParent)Q=O.y-(this._canvasParent.getBoundingClientRect().top-this._video.getBoundingClientRect().top),$=O.x;this._canvas.style.width=O.width+"px",this._canvas.style.height=O.height+"px"}if(this._canvas.style.top=Q+"px",this._canvas.style.left=$+"px",J>0&&Z>0)this._canvasctrl.width=J,this._canvasctrl.height=Z;if(this._gpuRenderer&&J>0&&Z>0)this._gpuRenderer.updateSize(J,Z);if(N&&this.busy===!1)this.busy=!0;else N=!1;this.sendMessage("canvas",{width:J,height:Z,videoWidth:this._videoWidth||this._video?.videoWidth||0,videoHeight:this._videoHeight||this._video?.videoHeight||0,force:N})}_timeupdate(J){let Q={seeking:!0,waiting:!0,playing:!1}[J.type];if(Q!=null)this._playstate=Q;this.setCurrentTime(this._video.paused||this._playstate,this._video.currentTime+this.timeOffset)}setVideo(J){if(J instanceof HTMLVideoElement){if(this._removeListeners(),this._video=J,this._onDemandRender){if(!this._destroyed&&this._video===J)J.requestVideoFrameCallback(this._boundHandleRVFC)}else this._playstate=J.paused,J.addEventListener("timeupdate",this._boundTimeUpdate,!1),J.addEventListener("progress",this._boundTimeUpdate,!1),J.addEventListener("waiting",this._boundTimeUpdate,!1),J.addEventListener("seeking",this._boundTimeUpdate,!1),J.addEventListener("playing",this._boundTimeUpdate,!1),J.addEventListener("ratechange",this._boundSetRate,!1),J.addEventListener("resize",this._boundResize,!1);if("VideoFrame"in window){if(J.addEventListener("loadedmetadata",this._boundUpdateColorSpace,!1),J.readyState>2)this._updateColorSpace()}if(J.videoWidth>0)this.resize();if(typeof ResizeObserver<"u"){if(!this._ro)this._ro=new ResizeObserver(()=>this.resize());this._ro.observe(J)}}else this._error(Error("Video element invalid!"))}runBenchmark(){this.sendMessage("runBenchmark")}setTrackByUrl(J){if(this.sendMessage("setTrackByUrl",{url:J}),this._reAttachOffscreen(),this._ctx)this._ctx.filter="none"}setTrack(J){if(this.sendMessage("setTrack",{content:J}),this._reAttachOffscreen(),this._ctx)this._ctx.filter="none"}freeTrack(){this.sendMessage("freeTrack")}setIsPaused(J){this.sendMessage("video",{isPaused:J})}setRate(J){this.sendMessage("video",{rate:J})}setCurrentTime(J,Z,Q){this.sendMessage("video",{isPaused:J,currentTime:Z,rate:Q,colorSpace:this._videoColorSpace})}createEvent(J){this.sendMessage("createEvent",{event:J})}setEvent(J,Z){this.sendMessage("setEvent",{event:J,index:Z})}removeEvent(J){this.sendMessage("removeEvent",{index:J})}async getEvents(){return(await this._fetchFromWorker({target:"getEvents"})).events??[]}styleOverride(J){this.sendMessage("styleOverride",{style:J})}disableStyleOverride(){this.sendMessage("disableStyleOverride")}createStyle(J){this.sendMessage("createStyle",{style:J})}setStyle(J,Z){this.sendMessage("setStyle",{style:J,index:Z})}removeStyle(J){this.sendMessage("removeStyle",{index:J})}async getStyles(){return(await this._fetchFromWorker({target:"getStyles"})).styles??[]}addFont(J){this.sendMessage("addFont",{font:J})}setDefaultFont(J){this.sendMessage("defaultFont",{font:J})}async getStats(){let Z=(await this._fetchFromWorker({target:"getStats"})).stats;return{framesRendered:Z.framesRendered??0,framesDropped:Z.framesDropped??0,avgRenderTime:Z.avgRenderTime??0,maxRenderTime:Z.maxRenderTime??0,minRenderTime:Z.minRenderTime??0,lastRenderTime:Z.lastRenderTime??0,pendingRenders:Z.pendingRenders??0,totalEvents:Z.totalEvents??0,cacheHits:Z.cacheHits??0,cacheMisses:Z.cacheMisses??0,renderFps:Z.avgRenderTime&&Z.avgRenderTime>0?Math.round(1000/Z.avgRenderTime):0,usingWorker:!0,offscreenRender:this._offscreenRender,onDemandRender:this._onDemandRender}}async resetStats(){await this._fetchFromWorker({target:"resetStats"})}async getEventCount(){return(await this._fetchFromWorker({target:"getEventCount"})).count}async getStyleCount(){return(await this._fetchFromWorker({target:"getStyleCount"})).count}_sendLocalFont(J){try{globalThis.queryLocalFonts().then((Z)=>{let Q=Z?.find(($)=>$.fullName.toLowerCase()===J);if(Q)Q.blob().then(($)=>{$.arrayBuffer().then((N)=>{this.addFont(new Uint8Array(N))})})})}catch(Z){console.warn("Local fonts API:",Z)}}_getLocalFont(J){try{if(navigator?.permissions?.query)navigator.permissions.query({name:"local-fonts"}).then((Z)=>{if(Z.state==="granted")this._sendLocalFont(J.font)});else this._sendLocalFont(J.font)}catch(Z){console.warn("Local fonts API:",Z)}}_unbusy(){if(this._observeDemandCompletion(),this._pendingDemandTimes.length>0){if(this._pendingDemandTimes.length>1){let Z=this._pendingDemandTimes[this._pendingDemandTimes.length-1];this._pendingDemandTimes.length=0,this._pendingDemandTimes.push(Z)}let J=this._pendingDemandTimes.shift();if(J){this._demandRender(J);return}}this.busy=!1}_markDemandDispatched(){if(!this._onDemandRender)return;this._activeDemandStartedAt=performance.now()}_observeDemandCompletion(){if(!this._onDemandRender||this._activeDemandStartedAt===0)return;let J=performance.now()-this._activeDemandStartedAt;if(this._activeDemandStartedAt=0,!Number.isFinite(J)||J<=0)return;this._smoothedDemandLatencyMs=this._smoothedDemandLatencyMs<=0?J:this._smoothedDemandLatencyMs*0.75+J*0.25}_getDemandPipelineLeadSeconds(J,Z){let Q=Z.expectedDisplayTime??Z.presentationTime??J,$=Math.max(0,Q-J)/1000;return Math.max(0,this._smoothedDemandLatencyMs/1000-$)}_enqueueDemand(J){let Z=this._pendingDemandTimes;if(Z.length>0){let Q=Z[Z.length-1];if(Math.abs(Q.mediaTime-J.mediaTime)>0.25)Z.length=0}if(Z.length>=H.MAX_PENDING_DEMANDS)Z.shift();Z.push(J)}_handleRVFC(J,Z){if(this._destroyed)return;let Q=this._video?.playbackRate??1,$=this._getDemandPipelineLeadSeconds(J,Z),O={mediaTime:Z.mediaTime+($+this.renderAhead)*Q,width:Z.width,height:Z.height};if(!this._workerReady){this._enqueueDemand(O),this._video.requestVideoFrameCallback(this._boundHandleRVFC);return}if(this.busy)this._enqueueDemand(O);else this.busy=!0,this._demandRender(O);this._video.requestVideoFrameCallback(this._boundHandleRVFC)}_demandRender(J){if(J.width!==this._videoWidth||J.height!==this._videoHeight)this._videoWidth=J.width,this._videoHeight=J.height,this.resize();this._markDemandDispatched(),this.sendMessage("demand",{time:J.mediaTime+this.timeOffset})}_detachOffscreen(){if(!this._offscreenRender||this._ctx)return;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas,this._ctx=this._canvasctrl.getContext("2d",{alpha:!0,desynchronized:!0}),this.sendMessage("detachOffscreen"),this.busy=!1,this._activeDemandStartedAt=0,this._pendingDemandTimes.length=0,this.resize(0,0,0,0,!0)}_reAttachOffscreen(){if(!this._offscreenRender||!this._ctx)return;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas.transferControlToOffscreen(),this._ctx=!1,this.sendMessage("offscreenCanvas",{},[this._canvasctrl]),this.resize(0,0,0,0,!0)}_updateColorSpace(){this._video.requestVideoFrameCallback(()=>{try{let J=new globalThis.VideoFrame(this._video);this._videoColorSpace=u[J.colorSpace.matrix]??null,J.close(),this.sendMessage("getColorSpace")}catch(J){console.warn(J)}})}_verifyColorSpace(J){let{subtitleColorSpace:Z,videoColorSpace:Q=this._videoColorSpace}=J;if(!Z||!Q)return;if(Z===Q)return;this._detachOffscreen();let $=y[Z]?.[Q];if($&&this._ctx)this._ctx.filter=`url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><filter id='f'><feColorMatrix type='matrix' values='${$} 0 0 0 0 0 1 0'/></filter></svg>#f")`}_render(J){try{let{width:Z,height:Q}=J;if(this.debug)J.times.IPCTime=Date.now()-(J.times.JSRenderTime||0);if(this._canvasctrl.width!==Z||this._canvasctrl.height!==Q){if(this._canvasctrl.width=Z,this._canvasctrl.height=Q,this._lastRenderWidth=Z,this._lastRenderHeight=Q,this._gpuRenderer)this._gpuRenderer.updateSize(Z,Q);this._verifyColorSpace({subtitleColorSpace:J.colorSpace})}if(this._gpuRenderer){this._renderGPU(J);return}if(!this._ctx)return;let N=this._ctx,O=J.images,K=O.length;if(N.clearRect(0,0,Z,Q),J.asyncRender)for(let F=0;F<K;F++){let G=O[F];if(G.image)N.drawImage(G.image,G.x,G.y),G.image.close()}else{let F=H._hasAlphaBug??!1;for(let G=0;G<K;G++){let U=O[G];if(U.image){let{w:E,h:M,image:q}=U,Y=q instanceof Uint8ClampedArray?q:q instanceof Uint8Array?new Uint8ClampedArray(q.buffer,q.byteOffset,q.byteLength):new Uint8ClampedArray(q),L=m(Y,F);N.putImageData(new ImageData(L,E,M),U.x,U.y)}}}if(this.debug){J.times.JSRenderTime=Date.now()-(J.times.JSRenderTime||0)-(J.times.IPCTime||0);let F=0,G=J.times.bitmaps||K;delete J.times.bitmaps;for(let U in J.times)F+=J.times[U]||0;console.log("Bitmaps: "+G+" Total: "+(F|0)+"ms",J.times)}}finally{this._unbusy()}}_renderGPU(J){let Z=this._gpuRenderer;if(!Z)return;if(J.images.length===0){Z.clear();return}if(J.asyncRender){let Q=this._gpuBitmapImages,$=0;for(let N=0;N<J.images.length;N++){let O=J.images[N];if(!(O.image instanceof ImageBitmap))continue;let K=Q[$]||(Q[$]={image:O.image,x:0,y:0});K.image=O.image,K.x=O.x,K.y=O.y,$++}Q.length=$,Z.renderBitmaps(Q,this._canvasctrl.width,this._canvasctrl.height);for(let N of J.images)if(N.image instanceof ImageBitmap)N.image.close()}else Z.render(J.images,this._canvasctrl.width,this._canvasctrl.height);if(this.debug){J.times.JSRenderTime=Date.now()-(J.times.JSRenderTime||0)-(J.times.IPCTime||0);let Q=0,$=J.times.bitmaps||J.images.length;delete J.times.bitmaps;for(let N in J.times)Q+=J.times[N]||0;console.log(`[${this._rendererType.toUpperCase()}] Bitmaps: `+$+" Total: "+(Q|0)+"ms",J.times)}}_ready(){if(this._workerReady=!0,this._init(),this._onDemandRender&&this._video){this.setCurrentTime(this._video.paused,this._video.currentTime+this.timeOffset,this._video.playbackRate);let J=this._pendingDemandTimes.length>0?this._pendingDemandTimes[this._pendingDemandTimes.length-1]:{mediaTime:this._video.currentTime+this.renderAhead*(this._video.playbackRate||1),width:this._video.videoWidth,height:this._video.videoHeight};this._pendingDemandTimes.length=0,this.busy=!0,this._demandRender(J)}this.dispatchEvent(new CustomEvent("ready"))}_partial_ready(){this.dispatchEvent(new CustomEvent("partial_ready"))}async sendMessage(J,Z={},Q){if(await this._loaded,Q)this._worker.postMessage({target:J,transferable:Q,...Z},[...Q]);else this._worker.postMessage({target:J,...Z})}_fetchFromWorker(J){return new Promise((Z,Q)=>{try{let $=J.target,N=setTimeout(()=>{F(),Q(Error("Error: Timeout while trying to fetch "+$))},5000),O=(G)=>{if(G.data.target===$)F(),Z(G.data)},K=(G)=>{F(),Q(G instanceof Error?G:G.error||Error("Worker error"))},F=()=>{this._worker.removeEventListener("message",O),this._worker.removeEventListener("error",K),clearTimeout(N)};this._worker.addEventListener("message",O),this._worker.addEventListener("error",K),this._worker.postMessage(J)}catch($){Q($)}})}_console(J){console[J.command].apply(console,JSON.parse(J.content))}_onmessage(J){let Z=J.data.target;if(Z==="error"){this._error(J.data.error||"Unknown worker error");return}let Q=this["_"+Z];if(Q)Q.call(this,J.data)}_error(J){let Z=J instanceof Error?J:J instanceof ErrorEvent?J.error||Error(J.message):Error(String(J)),Q=J instanceof Event?new ErrorEvent(J.type,J):new ErrorEvent("error",{error:Z});return this.dispatchEvent(Q),console.error(Z),Z}_removeListeners(){if(this._video){if(this._ro)this._ro.unobserve(this._video);if(this._ctx)this._ctx.filter="none";this._video.removeEventListener("timeupdate",this._boundTimeUpdate),this._video.removeEventListener("progress",this._boundTimeUpdate),this._video.removeEventListener("waiting",this._boundTimeUpdate),this._video.removeEventListener("seeking",this._boundTimeUpdate),this._video.removeEventListener("playing",this._boundTimeUpdate),this._video.removeEventListener("ratechange",this._boundSetRate),this._video.removeEventListener("resize",this._boundResize),this._video.removeEventListener("loadedmetadata",this._boundUpdateColorSpace)}}destroy(J){let Z=J?this._error(J):void 0;if(this._video&&this._canvasParent)this._video.parentNode?.removeChild(this._canvasParent);if(this._gpuRenderer)this._gpuRenderer.destroy(),this._gpuRenderer=null,this._rendererType="canvas2d";return this._destroyed=!0,this._removeListeners(),this.sendMessage("destroy"),this._worker?.terminate(),Z}}})();
|
|
157
157
|
|
|
158
158
|
return AkariSub;
|
|
159
159
|
}));
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var u={bt709:"BT709",bt470bg:"BT601",smpte170m:"BT601"},y={BT601:{BT709:"1.0863 -0.0723 -0.014 0 0 0.0965 0.8451 0.0584 0 0 -0.0141 -0.0277 1.0418"},BT709:{BT601:"0.9137 0.0784 0.0079 0 0 -0.1049 1.1722 -0.0671 0 0 0.0096 0.0322 0.9582"},FCC:{BT709:"1.0873 -0.0736 -0.0137 0 0 0.0974 0.8494 0.0531 0 0 -0.0127 -0.0251 1.0378",BT601:"1.001 -0.0008 -0.0002 0 0 0.0009 1.005 -0.006 0 0 0.0013 0.0027 0.996"},SMPTE240M:{BT709:"0.9993 0.0006 0.0001 0 0 -0.0004 0.9812 0.0192 0 0 -0.0034 -0.0114 1.0148",BT601:"0.913 0.0774 0.0096 0 0 -0.1051 1.1508 -0.0456 0 0 0.0063 0.0207 0.973"}},
|
|
1
|
+
var u={bt709:"BT709",bt470bg:"BT601",smpte170m:"BT601"},y={BT601:{BT709:"1.0863 -0.0723 -0.014 0 0 0.0965 0.8451 0.0584 0 0 -0.0141 -0.0277 1.0418"},BT709:{BT601:"0.9137 0.0784 0.0079 0 0 -0.1049 1.1722 -0.0671 0 0 0.0096 0.0322 0.9582"},FCC:{BT709:"1.0873 -0.0736 -0.0137 0 0 0.0974 0.8494 0.0531 0 0 -0.0127 -0.0251 1.0378",BT601:"1.001 -0.0008 -0.0002 0 0 0.0009 1.005 -0.006 0 0 0.0013 0.0027 0.996"},SMPTE240M:{BT709:"0.9993 0.0006 0.0001 0 0 -0.0004 0.9812 0.0192 0 0 -0.0034 -0.0114 1.0148",BT601:"0.913 0.0774 0.0096 0 0 -0.1051 1.1508 -0.0456 0 0 0.0063 0.0207 0.973"}},s=[null,"BT601",null,"BT601","BT601","BT709","BT709","SMPTE240M","SMPTE240M","FCC","FCC"];function o(J,Z){if(!J||!Z)return null;if(J===Z)return null;let Q=y[J]?.[Z];if(!Q)return null;return`url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><filter id='f'><feColorMatrix type='matrix' values='${Q} 0 0 0 0 0 1 0'/></filter></svg>#f")`}function w(J,Z,Q,$,N){let O=Q<=0?1:Q,K=globalThis.devicePixelRatio||1;if(Z<=0||J<=0)return{width:0,height:0};let F=O<1?-1:1,G=Z*K;if(F*G*O<=F*$)G*=O;else if(F*G<F*$)G=$;if(N>0&&G>N)G=N;return J*=G/Z,Z=G,{width:J,height:Z}}function c(J,Z=J.videoWidth,Q=J.videoHeight){let $=Z/Q,{offsetWidth:N,offsetHeight:O}=J,K=N/O,F=N,G=O;if(K>$)F=Math.floor(O*$);else G=Math.floor(N/$);let U=(N-F)/2,E=(O-G)/2;return{width:F,height:G,x:U,y:E}}function m(J,Z){if(!Z)return J;let Q=J.length,$=Q-Q%16,N=3;for(;N<$;N+=16){if(J[N]<2)J[N]=1;if(J[N+4]<2)J[N+4]=1;if(J[N+8]<2)J[N+8]=1;if(J[N+12]<2)J[N+12]=1}for(;N<Q;N+=4)if(J[N]<2)J[N]=1;return J}function r(J,Z=!1){let Q=[],$=J.split(/[\r\n]+/g),N=$.length,O=null,K=null;for(let F=0;F<N;F++){let G=$[F];if(!G||/^\s*$/.test(G))continue;let U=G[0];if(U==="["){let E=G.match(/^\[(.*)\]$/);if(E){if(Z&&E[1].toLowerCase()==="events")break;O=null,K={name:E[1],body:[]},Q.push(K);continue}}if(!K)continue;if(U===";")K.body.push({type:"comment",value:G.substring(1)});else{let E=G.indexOf(":");if(E===-1)continue;let M=G.substring(0,E),q=G.substring(E+1).trim();if(O||M==="Format"){let Y=q.split(",");if(O&&Y.length>O.length){let B=Y.slice(O.length-1).join(",");Y=Y.slice(0,O.length-1),Y.push(B)}let L=Y.length;for(let B=0;B<L;B++)Y[B]=Y[B].trim();if(O){let B={},j=Math.min(O.length,L);for(let P=0;P<j;P++)B[O[P]]=Y[P];q=B}else q=Y}if(M==="Format")O=q;K.body.push({key:M,value:q})}}return Q}var n=/\\blur(?:[0-9]+\.)?[0-9]+/gm;function i(J){return J.replace(n,"")}var t=[{w:7680,h:4320},{w:3840,h:2160},{w:2560,h:1440},{w:1920,h:1080},{w:1280,h:720}];function a(J,Z){let Q=[...t].sort(($,N)=>$.w-N.w);for(let $ of Q)if(J<=$.w&&Z<=$.h)return $;return{w:Math.ceil(J/100)*100,h:Math.ceil(Z/100)*100}}function V(J,Z){return Z&&Z.includes(".")?J.toFixed(2).replace(/\.?0+$/,""):Math.round(J)}function e(J){let Z=J.match(/PlayResX:\s*(\d+)/i),Q=J.match(/PlayResY:\s*(\d+)/i),$=Z?parseInt(Z[1],10):1920,N=Q?parseInt(Q[1],10):1080,O=/\\pos\s*\(\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*\)/g,K=/\\move\s*\(\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)/g,F=/\\org\s*\(\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*\)/g,G=/\\i?clip\s*\(\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*\)/g,U=0,E=0,M=(T,X,k)=>{let R,A=new RegExp(T.source,"g");while((R=A.exec(J))!==null){for(let I of X)if(R[I]){let D=Math.abs(parseFloat(R[I]));if(D>U)U=D}for(let I of k)if(R[I]){let D=Math.abs(parseFloat(R[I]));if(D>E)E=D}}};if(M(O,[1],[2]),M(K,[1,3],[2,4]),M(F,[1],[2]),M(G,[1,3],[2,4]),U<=$&&E<=N)return J;let q=a(U,E),Y=$/q.w,L=N/q.h,B=Math.min(Y,L),j=Math.max(Y,L),P=1,z=J,W=z.match(/(\[Events\][\s\S]*)/i);if(!W)return z;let _=W[1];return _=_.replace(O,(T,X,k)=>`\\pos(${V(parseFloat(X)*Y,X)},${V(parseFloat(k)*L,k)})`),_=_.replace(/\\move\s*\(\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)(?:\s*,\s*(-?[\d.]+)\s*,\s*(-?[\d.]+))?\s*\)/g,(T,X,k,R,A,I,D)=>{let h=`\\move(${V(parseFloat(X)*Y,X)},${V(parseFloat(k)*L,k)},${V(parseFloat(R)*Y,R)},${V(parseFloat(A)*L,A)}`;return I?`${h},${I},${D})`:`${h})`}),_=_.replace(F,(T,X,k)=>`\\org(${V(parseFloat(X)*Y,X)},${V(parseFloat(k)*L,k)})`),_=_.replace(/\\(i?clip)\s*\(\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*,\s*(-?[\d.]+)\s*\)/g,(T,X,k,R,A,I)=>`\\${X}(${V(parseFloat(k)*Y,k)},${V(parseFloat(R)*L,R)},${V(parseFloat(A)*Y,A)},${V(parseFloat(I)*L,I)})`),_=_.replace(/\\fs([\d.]+)/g,(T,X)=>`\\fs${V(parseFloat(X)*j,X)}`),_=_.replace(/\\fscx([\d.]+)/g,(T,X)=>`\\fscx${V(parseFloat(X)*P,X)}`),_=_.replace(/\\xbord([\d.]+)/g,(T,X)=>`\\xbord${V(parseFloat(X)*Y,X)}`),_=_.replace(/\\ybord([\d.]+)/g,(T,X)=>`\\ybord${V(parseFloat(X)*L,X)}`),_=_.replace(/\\xshad(-?[\d.]+)/g,(T,X)=>`\\xshad${V(parseFloat(X)*Y,X)}`),_=_.replace(/\\yshad(-?[\d.]+)/g,(T,X)=>`\\yshad${V(parseFloat(X)*L,X)}`),["fsp","bord","shad","be","blur"].forEach((T)=>{let X=new RegExp(`\\\\${T}(-?[\\d.]+)`,"g");_=_.replace(X,(k,R)=>`\\${T}${V(parseFloat(R)*B,R)}`)}),_=_.replace(/(\\i?clip\s*\([^,)]+m[^)]+\)|\\p[1-9][^}]*?)(?=[\\}]|$)/g,(T)=>{return T.replace(/(-?[\d.]+)\s+(-?[\d.]+)/g,(X,k,R)=>{return`${V(parseFloat(k)*Y,k)} ${V(parseFloat(R)*L,R)}`})}),z.substring(0,W.index)+_}var b=null,S=null;async function l(){if(b!==null&&S!==null)return{hasAlphaBug:b,hasBitmapBug:S};let J=document.createElement("canvas"),Z=J.getContext("2d",{willReadFrequently:!0});if(!Z)throw Error("Canvas rendering not supported");if(typeof ImageData.prototype.constructor==="function")try{new ImageData(new Uint8ClampedArray([0,0,0,0]),1,1)}catch{console.log("Detected that ImageData is not constructable despite browser saying so")}let Q=document.createElement("canvas"),$=Q.getContext("2d",{willReadFrequently:!0});if(!$)throw Error("Canvas rendering not supported");J.width=Q.width=1,J.height=Q.height=1,Z.clearRect(0,0,1,1),$.clearRect(0,0,1,1);let N=$.getImageData(0,0,1,1).data;Z.putImageData(new ImageData(new Uint8ClampedArray([0,255,0,0]),1,1),0,0),$.drawImage(J,0,0);let O=$.getImageData(0,0,1,1).data;if(b=N[1]!==O[1],b)console.log("Detected a browser having issue with transparent pixels, applying workaround");if(typeof createImageBitmap<"u"){let K=new Uint8ClampedArray([255,0,255,0,255]).subarray(1,5);$.drawImage(await createImageBitmap(new ImageData(K,1)),0,0);let{data:F}=$.getImageData(0,0,1,1);S=!1;for(let G=0;G<F.length;G++)if(Math.abs(K[G]-F[G])>15){S=!0,console.log("Detected a browser having issue with partial bitmaps, applying workaround");break}}else S=!1;return J.remove(),Q.remove(),{hasAlphaBug:b,hasBitmapBug:S}}async function JJ(){return l()}function ZJ(){return b}function $J(){return S}function f(){return typeof navigator<"u"&&"gpu"in navigator}function QJ(J){if(J instanceof ArrayBuffer)return new Uint8Array(J);return new Uint8Array(J.buffer,J.byteOffset,J.byteLength)}class v{device=null;context=null;pipeline=null;bindGroupLayout=null;uniformBuffer=null;imageDataBuffer=null;textureArray=null;textureArrayView=null;textureArraySize=0;textureArrayWidth=0;textureArrayHeight=0;pendingDestroyTextures=[];imageDataArray;resolutionArray=new Float32Array(2);conversionBuffer=null;conversionBufferSize=0;bindGroup=null;bindGroupDirty=!0;lastCanvasWidth=0;lastCanvasHeight=0;format="bgra8unorm";_canvas=null;_initPromise=null;_initialized=!1;constructor(){this.imageDataArray=new Float32Array(2048)}async init(){if(this._initPromise)return this._initPromise;return this._initPromise=this._initDevice(),this._initPromise}async _initDevice(){if(!navigator.gpu)throw Error("WebGPU not supported");let J=await navigator.gpu.requestAdapter({powerPreference:"high-performance"});if(!J)throw Error("No WebGPU adapter found");this.device=await J.requestDevice(),this.format=navigator.gpu.getPreferredCanvasFormat();let Z=this.device.createShaderModule({code:`
|
|
2
2
|
struct VertexOutput {
|
|
3
3
|
@builtin(position) position: vec4f,
|
|
4
4
|
@location(0) @interpolate(flat) instanceIndex: u32,
|
|
@@ -53,7 +53,7 @@ fn vertexMain(
|
|
|
53
53
|
|
|
54
54
|
return output;
|
|
55
55
|
}
|
|
56
|
-
`}),
|
|
56
|
+
`}),Q=this.device.createShaderModule({code:`
|
|
57
57
|
@group(0) @binding(2) var texArray: texture_2d_array<f32>;
|
|
58
58
|
|
|
59
59
|
struct ImageData {
|
|
@@ -91,7 +91,7 @@ fn fragmentMain(input: FragmentInput) -> @location(0) vec4f {
|
|
|
91
91
|
// Premultiplied alpha output
|
|
92
92
|
return vec4f(color.rgb * color.a, color.a);
|
|
93
93
|
}
|
|
94
|
-
`});this.uniformBuffer=this.device.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.imageDataBuffer=this.device.createBuffer({size:8192,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),this.createTextureArray(256,256,32),this.bindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"unfilterable-float",viewDimension:"2d-array"}}]});let
|
|
94
|
+
`});this.uniformBuffer=this.device.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.imageDataBuffer=this.device.createBuffer({size:8192,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),this.createTextureArray(256,256,32),this.bindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"unfilterable-float",viewDimension:"2d-array"}}]});let $=this.device.createPipelineLayout({bindGroupLayouts:[this.bindGroupLayout]});this.pipeline=this.device.createRenderPipeline({layout:$,vertex:{module:Z,entryPoint:"vertexMain"},fragment:{module:Q,entryPoint:"fragmentMain",targets:[{format:this.format,blend:{color:{srcFactor:"one",dstFactor:"one-minus-src-alpha",operation:"add"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha",operation:"add"}}}]},primitive:{topology:"triangle-list"}}),this._initialized=!0}nextPowerOf2(J){return J--,J|=J>>1,J|=J>>2,J|=J>>4,J|=J>>8,J|=J>>16,J+1}createTextureArray(J,Z,Q){if(this.textureArray)this.pendingDestroyTextures.push(this.textureArray);let $=this.nextPowerOf2(Math.max(J,64)),N=this.nextPowerOf2(Math.max(Z,64)),O=Math.min(this.nextPowerOf2(Math.max(Q,16)),256);this.textureArray=this.device.createTexture({size:[$,N,O],format:this.format,usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT}),this.textureArrayView=this.textureArray.createView({dimension:"2d-array"}),this.textureArrayWidth=$,this.textureArrayHeight=N,this.textureArraySize=O,this.bindGroupDirty=!0;let K=this.device.createCommandEncoder();for(let F=0;F<O;F++){let G=this.textureArray.createView({dimension:"2d",baseArrayLayer:F,arrayLayerCount:1});K.beginRenderPass({colorAttachments:[{view:G,clearValue:{r:0,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"}]}).end()}this.device.queue.submit([K.finish()])}ensureTextureArray(J,Z,Q){let $=Math.min(Q,256);if(J<=this.textureArrayWidth&&Z<=this.textureArrayHeight&&$<=this.textureArraySize)return!1;let N=this.nextPowerOf2(Math.max(this.textureArrayWidth,J)),O=this.nextPowerOf2(Math.max(this.textureArrayHeight,Z)),K=Math.min(this.nextPowerOf2(Math.max(this.textureArraySize,$,$+16)),256);return this.createTextureArray(N,O,K),!0}updateBindGroup(){if(!this.bindGroupDirty||!this.device||!this.bindGroupLayout)return;this.bindGroup=this.device.createBindGroup({layout:this.bindGroupLayout,entries:[{binding:0,resource:{buffer:this.uniformBuffer}},{binding:1,resource:{buffer:this.imageDataBuffer}},{binding:2,resource:this.textureArrayView}]}),this.bindGroupDirty=!1}ensureConversionBuffer(J){if(this.conversionBufferSize<J)this.conversionBufferSize=Math.max(J,this.conversionBufferSize*1.5|0,65536),this.conversionBuffer=new Uint8Array(this.conversionBufferSize);return this.conversionBuffer}async setCanvas(J,Z,Q){if(await this.init(),!this.device)throw Error("WebGPU device not initialized");if(Z<=0||Q<=0)return;if(this._canvas=J,J.width=Z,J.height=Q,!this.context){if(this.context=J.getContext("webgpu"),!this.context)throw Error("Could not get WebGPU context");this.context.configure({device:this.device,format:this.format,alphaMode:"premultiplied"})}this.resolutionArray[0]=Z,this.resolutionArray[1]=Q,this.device.queue.writeBuffer(this.uniformBuffer,0,this.resolutionArray),this.lastCanvasWidth=Z,this.lastCanvasHeight=Q}updateSize(J,Z){if(!this.device||!this._canvas||J<=0||Z<=0)return;if(J===this.lastCanvasWidth&&Z===this.lastCanvasHeight)return;this._canvas.width=J,this._canvas.height=Z,this.resolutionArray[0]=J,this.resolutionArray[1]=Z,this.device.queue.writeBuffer(this.uniformBuffer,0,this.resolutionArray),this.lastCanvasWidth=J,this.lastCanvasHeight=Z}renderBitmaps(J,Z,Q){if(!this.device||!this.context||!this.pipeline)return;let $=J.length;if($===0){this.clear();return}let N=this.context.getCurrentTexture();if(N.width===0||N.height===0)return;let O=0,K=0,F=0;for(let j=0;j<$;j++){let{image:P}=J[j],z=P.width,W=P.height;if(z>0&&W>0){if(z>O)O=z;if(W>K)K=W;F++}}if(F===0){this.clear();return}let G=Math.min(F,256);this.ensureTextureArray(O,K,G),this.updateBindGroup();let U=this.device,E=U.queue,M=this.textureArray,q=this.imageDataArray,Y=N.createView(),L=0,B=!0;while(L<$){let j=0;while(L<$&&j<256){let W=J[L++],_=W.image,C=_.width,T=_.height;if(C<=0||T<=0)continue;E.copyExternalImageToTexture({source:_,flipY:!1},{texture:M,origin:[0,0,j],premultipliedAlpha:!1},{width:C,height:T});let X=j<<3;q[X]=W.x,q[X+1]=W.y,q[X+2]=C,q[X+3]=T,q[X+4]=C,q[X+5]=T,q[X+6]=j,q[X+7]=0,j++}if(j===0)continue;E.writeBuffer(this.imageDataBuffer,0,q.buffer,0,j<<5);let P=U.createCommandEncoder(),z=P.beginRenderPass({colorAttachments:[{view:Y,clearValue:{r:0,g:0,b:0,a:0},loadOp:B?"clear":"load",storeOp:"store"}]});z.setPipeline(this.pipeline),z.setBindGroup(0,this.bindGroup),z.draw(6,j),z.end(),E.submit([P.finish()]),B=!1}this.cleanupPendingTextures()}render(J,Z,Q){if(!this.device||!this.context||!this.pipeline)return;let $=J.length;if($===0){this.clear();return}let N=this.context.getCurrentTexture();if(N.width===0||N.height===0)return;let O=0,K=0,F=0;for(let P=0;P<$;P++){let{w:z,h:W}=J[P];if(z>0&&W>0){if(z>O)O=z;if(W>K)K=W;F++}}if(F===0){this.clear();return}let G=Math.min(F,256);this.ensureTextureArray(O,K,G),this.updateBindGroup();let U=this.device,E=U.queue,M=this.textureArray,q=this.imageDataArray,Y=this.format==="bgra8unorm",L=N.createView(),B=0,j=!0;while(B<$){let P=0;while(B<$&&P<256){let _=J[B++],C=_.w,T=_.h;if(C<=0||T<=0)continue;let X=_.image;if(X instanceof ImageBitmap)E.copyExternalImageToTexture({source:X,flipY:!1},{texture:M,origin:[0,0,P],premultipliedAlpha:!1},{width:C,height:T});else if(X instanceof ArrayBuffer||X instanceof Uint8Array||X instanceof Uint8ClampedArray)this.uploadTextureData(P,X,C,T,Y);let k=P<<3;q[k]=_.x,q[k+1]=_.y,q[k+2]=C,q[k+3]=T,q[k+4]=C,q[k+5]=T,q[k+6]=P,q[k+7]=0,P++}if(P===0)continue;E.writeBuffer(this.imageDataBuffer,0,q.buffer,0,P<<5);let z=U.createCommandEncoder(),W=z.beginRenderPass({colorAttachments:[{view:L,clearValue:{r:0,g:0,b:0,a:0},loadOp:j?"clear":"load",storeOp:"store"}]});W.setPipeline(this.pipeline),W.setBindGroup(0,this.bindGroup),W.draw(6,P),W.end(),E.submit([z.finish()]),j=!1}this.cleanupPendingTextures()}uploadTextureData(J,Z,Q,$,N){let O=Q*$*4,K=QJ(Z);if(N){let F=this.ensureConversionBuffer(O);for(let G=0;G<O;G+=4)F[G]=K[G+2],F[G+1]=K[G+1],F[G+2]=K[G],F[G+3]=K[G+3];this.device.queue.writeTexture({texture:this.textureArray,origin:[0,0,J]},F.buffer,{bytesPerRow:Q*4},{width:Q,height:$})}else this.device.queue.writeTexture({texture:this.textureArray,origin:[0,0,J]},K,{bytesPerRow:Q*4},{width:Q,height:$})}cleanupPendingTextures(){let J=this.pendingDestroyTextures,Z=J.length;if(Z===0)return;for(let Q=0;Q<Z;Q++)J[Q].destroy();J.length=0}clear(){if(!this.device||!this.context)return;try{let J=this.context.getCurrentTexture();if(J.width===0||J.height===0)return;let Z=this.device.createCommandEncoder();Z.beginRenderPass({colorAttachments:[{view:J.createView(),clearValue:{r:0,g:0,b:0,a:0},loadOp:"clear",storeOp:"store"}]}).end(),this.device.queue.submit([Z.finish()])}catch{}}get initialized(){return this._initialized}destroy(){this.cleanupPendingTextures(),this.textureArray?.destroy(),this.textureArray=null,this.textureArrayView=null,this.uniformBuffer?.destroy(),this.uniformBuffer=null,this.imageDataBuffer?.destroy(),this.imageDataBuffer=null,this.bindGroup=null,this.conversionBuffer=null,this.conversionBufferSize=0,this.device?.destroy(),this.device=null,this.context=null,this._canvas=null,this._initialized=!1,this._initPromise=null}}function p(){if(typeof document>"u")return!1;try{return document.createElement("canvas").getContext("webgl2")!==null}catch{return!1}}function KJ(J){return J instanceof Uint8Array||J instanceof Uint8ClampedArray}function g(J,Z,Q){let $=J.createShader(Z);if(J.shaderSource($,Q),J.compileShader($),!J.getShaderParameter($,J.COMPILE_STATUS)){let N=J.getShaderInfoLog($);throw J.deleteShader($),Error(`WebGL2 shader compilation failed: ${N}`)}return $}class x{_gl=null;_canvas=null;_program=null;_vao=null;_instanceBuffer=null;_texArray=null;_texWidth=0;_texHeight=0;_texLayers=0;_resolutionLoc=null;_texArraySizeLoc=null;_instanceData;_lastCanvasWidth=0;_lastCanvasHeight=0;_initialized=!1;_initPromise=null;constructor(){this._instanceData=new Float32Array(2048)}async init(){if(this._initPromise)return this._initPromise;return this._initPromise=this._checkSupport(),this._initPromise}async _checkSupport(){if(typeof document>"u")throw Error("WebGL2 requires a DOM environment");if(!document.createElement("canvas").getContext("webgl2"))throw Error("WebGL2 not supported")}_initGL(){if(!this._canvas)throw Error("Canvas not set before _initGL");if(this._gl)return;let J=this._canvas.getContext("webgl2",{alpha:!0,premultipliedAlpha:!0,antialias:!1});if(!J)throw Error("Failed to create WebGL2 context");this._gl=J;let Z=g(J,J.VERTEX_SHADER,`#version 300 es
|
|
95
95
|
precision highp float;
|
|
96
96
|
|
|
97
97
|
in vec4 a_destRect;
|
|
@@ -125,7 +125,7 @@ void main() {
|
|
|
125
125
|
v_texIndex = int(a_texInfo.z);
|
|
126
126
|
v_texSize = a_texInfo.xy;
|
|
127
127
|
}
|
|
128
|
-
`),
|
|
128
|
+
`),Q=g(J,J.FRAGMENT_SHADER,`#version 300 es
|
|
129
129
|
precision highp float;
|
|
130
130
|
precision highp sampler2DArray;
|
|
131
131
|
|
|
@@ -144,4 +144,4 @@ void main() {
|
|
|
144
144
|
// Premultiplied alpha output (matches WebGPU renderer behaviour)
|
|
145
145
|
fragColor = vec4(color.rgb * color.a, color.a);
|
|
146
146
|
}
|
|
147
|
-
`),N=J.createProgram();if(J.attachShader(N,K),J.attachShader(N,Z),J.linkProgram(N),!J.getProgramParameter(N,J.LINK_STATUS))throw Error(`WebGL2 program link failed: ${J.getProgramInfoLog(N)}`);J.deleteShader(K),J.deleteShader(Z),this._program=N,this._resolutionLoc=J.getUniformLocation(N,"u_resolution"),this._texArraySizeLoc=J.getUniformLocation(N,"u_texArraySize"),this._vao=J.createVertexArray(),J.bindVertexArray(this._vao),this._instanceBuffer=J.createBuffer(),J.bindBuffer(J.ARRAY_BUFFER,this._instanceBuffer),J.bufferData(J.ARRAY_BUFFER,8192,J.DYNAMIC_DRAW);let Q=J.getAttribLocation(N,"a_destRect");J.enableVertexAttribArray(Q),J.vertexAttribPointer(Q,4,J.FLOAT,!1,32,0),J.vertexAttribDivisor(Q,1);let F=J.getAttribLocation(N,"a_texInfo");J.enableVertexAttribArray(F),J.vertexAttribPointer(F,4,J.FLOAT,!1,32,16),J.vertexAttribDivisor(F,1),J.bindVertexArray(null),this._texArray=J.createTexture(),this._allocateTextureArray(256,256,32),J.enable(J.BLEND),J.blendEquation(J.FUNC_ADD),J.blendFunc(J.ONE,J.ONE_MINUS_SRC_ALPHA),this._initialized=!0}_nextPow2(J){return J--,J|=J>>1,J|=J>>2,J|=J>>4,J|=J>>8,J|=J>>16,J+1}_allocateTextureArray(J,K,Z){let N=this._gl,Q=this._nextPow2(Math.max(J,64)),F=this._nextPow2(Math.max(K,64)),$=Math.min(this._nextPow2(Math.max(Z,16)),256);N.bindTexture(N.TEXTURE_2D_ARRAY,this._texArray),N.texImage3D(N.TEXTURE_2D_ARRAY,0,N.RGBA8,Q,F,$,0,N.RGBA,N.UNSIGNED_BYTE,null),N.texParameteri(N.TEXTURE_2D_ARRAY,N.TEXTURE_MIN_FILTER,N.NEAREST),N.texParameteri(N.TEXTURE_2D_ARRAY,N.TEXTURE_MAG_FILTER,N.NEAREST),N.texParameteri(N.TEXTURE_2D_ARRAY,N.TEXTURE_WRAP_S,N.CLAMP_TO_EDGE),N.texParameteri(N.TEXTURE_2D_ARRAY,N.TEXTURE_WRAP_T,N.CLAMP_TO_EDGE),this._texWidth=Q,this._texHeight=F,this._texLayers=$}_ensureTextureArray(J,K,Z){let N=Math.min(Z,256);if(J<=this._texWidth&&K<=this._texHeight&&N<=this._texLayers)return;let Q=this._nextPow2(Math.max(this._texWidth,J)),F=this._nextPow2(Math.max(this._texHeight,K)),$=Math.min(this._nextPow2(Math.max(this._texLayers,N,N+16)),256);this._allocateTextureArray(Q,F,$)}async setCanvas(J,K,Z){if(await this.init(),K<=0||Z<=0)return;this._canvas=J,J.width=K,J.height=Z,this._initGL(),this._gl.viewport(0,0,K,Z),this._lastCanvasWidth=K,this._lastCanvasHeight=Z}updateSize(J,K){if(!this._gl||!this._canvas||J<=0||K<=0)return;if(J===this._lastCanvasWidth&&K===this._lastCanvasHeight)return;this._canvas.width=J,this._canvas.height=K,this._gl.viewport(0,0,J,K),this._lastCanvasWidth=J,this._lastCanvasHeight=K}renderBitmaps(J,K,Z){if(!this._gl||!this._initialized)return;let N=J.length;if(N===0){this.clear();return}let Q=0,F=0;for(let E=0;E<N;E++){let{image:q}=J[E];if(q.width>Q)Q=q.width;if(q.height>F)F=q.height}this._ensureTextureArray(Q,F,Math.min(N,256));let $=this._gl;$.clearColor(0,0,0,0),$.clear($.COLOR_BUFFER_BIT),$.useProgram(this._program),$.uniform2f(this._resolutionLoc,this._lastCanvasWidth,this._lastCanvasHeight),$.uniform2i(this._texArraySizeLoc,this._texWidth,this._texHeight),$.activeTexture($.TEXTURE0),$.bindTexture($.TEXTURE_2D_ARRAY,this._texArray),$.pixelStorei($.UNPACK_FLIP_Y_WEBGL,!1);let U=this._instanceData,O=0;while(O<N){let E=0;while(O<N&&E<256){let q=J[O++],L=q.image.width,_=q.image.height;if(L<=0||_<=0)continue;$.texSubImage3D($.TEXTURE_2D_ARRAY,0,0,0,E,L,_,1,$.RGBA,$.UNSIGNED_BYTE,q.image);let Y=E<<3;U[Y]=q.x,U[Y+1]=q.y,U[Y+2]=L,U[Y+3]=_,U[Y+4]=L,U[Y+5]=_,U[Y+6]=E,U[Y+7]=0,E++}if(E===0)continue;$.bindBuffer($.ARRAY_BUFFER,this._instanceBuffer),$.bufferSubData($.ARRAY_BUFFER,0,U,0,E<<3),$.bindVertexArray(this._vao),$.drawArraysInstanced($.TRIANGLES,0,6,E),$.bindVertexArray(null)}}render(J,K,Z){if(!this._gl||!this._initialized)return;let N=J.length;if(N===0){this.clear();return}let Q=0,F=0;for(let E=0;E<N;E++){let{w:q,h:L}=J[E];if(q>Q)Q=q;if(L>F)F=L}this._ensureTextureArray(Q,F,Math.min(N,256));let $=this._gl;$.clearColor(0,0,0,0),$.clear($.COLOR_BUFFER_BIT),$.useProgram(this._program),$.uniform2f(this._resolutionLoc,this._lastCanvasWidth,this._lastCanvasHeight),$.uniform2i(this._texArraySizeLoc,this._texWidth,this._texHeight),$.activeTexture($.TEXTURE0),$.bindTexture($.TEXTURE_2D_ARRAY,this._texArray),$.pixelStorei($.UNPACK_FLIP_Y_WEBGL,!1);let U=this._instanceData,O=0;while(O<N){let E=0;while(O<N&&E<256){let q=J[O++],L=q.w,_=q.h;if(L<=0||_<=0)continue;let Y=q.image;if(Y instanceof ImageBitmap)$.texSubImage3D($.TEXTURE_2D_ARRAY,0,0,0,E,L,_,1,$.RGBA,$.UNSIGNED_BYTE,Y);else if(Y instanceof ArrayBuffer)$.texSubImage3D($.TEXTURE_2D_ARRAY,0,0,0,E,L,_,1,$.RGBA,$.UNSIGNED_BYTE,new Uint8Array(Y));let T=E<<3;U[T]=q.x,U[T+1]=q.y,U[T+2]=L,U[T+3]=_,U[T+4]=L,U[T+5]=_,U[T+6]=E,U[T+7]=0,E++}if(E===0)continue;$.bindBuffer($.ARRAY_BUFFER,this._instanceBuffer),$.bufferSubData($.ARRAY_BUFFER,0,U,0,E<<3),$.bindVertexArray(this._vao),$.drawArraysInstanced($.TRIANGLES,0,6,E),$.bindVertexArray(null)}}clear(){if(!this._gl)return;this._gl.clearColor(0,0,0,0),this._gl.clear(this._gl.COLOR_BUFFER_BIT)}get initialized(){return this._initialized}destroy(){let J=this._gl;if(J)J.deleteProgram(this._program),J.deleteVertexArray(this._vao),J.deleteBuffer(this._instanceBuffer),J.deleteTexture(this._texArray);this._gl=null,this._program=null,this._vao=null,this._instanceBuffer=null,this._texArray=null,this._canvas=null,this._initialized=!1,this._initPromise=null}}class R extends EventTarget{static MAX_PENDING_DEMANDS=3;static _hasAlphaBug=null;static _hasBitmapBug=null;_loaded;_init;_onDemandRender;_offscreenRender;_video;_videoWidth=0;_videoHeight=0;_videoColorSpace=null;_canvas;_canvasParent;_bufferCanvas;_bufferCtx;_canvasctrl;_ctx=null;_lastRenderTime=0;_playstate=!0;_destroyed=!1;_workerReady=!1;_ro;_worker;_pendingDemandTimes=[];_boundResize;_boundTimeUpdate;_boundSetRate;_boundUpdateColorSpace;_boundHandleRVFC;_gpuRenderer=null;_rendererType="canvas2d";_onCanvasFallback;_lastRenderWidth=0;_lastRenderHeight=0;timeOffset;debug;prescaleFactor;prescaleHeightLimit;maxRenderHeight;busy=!1;renderAhead;constructor(J){super();if(!globalThis.Worker)throw this.destroy(Error("Worker not supported"));if(!J)throw this.destroy(Error("No options provided"));this._loaded=new Promise((Q)=>{this._init=Q});let K=R._test();this._onDemandRender="requestVideoFrameCallback"in HTMLVideoElement.prototype&&(J.onDemandRender??!0),this._onCanvasFallback=J.onCanvasFallback;let Z=!J.canvas&&(f()||p());if(this._offscreenRender="transferControlToOffscreen"in HTMLCanvasElement.prototype&&!J.canvas&&!Z&&(J.offscreenRender??!0),this.timeOffset=J.timeOffset||0,this._video=J.video,this._canvas=J.canvas,this._video&&!this._canvas)this._canvasParent=document.createElement("div"),this._canvasParent.className="AkariSub",this._canvasParent.style.position="relative",this._canvas=this._createCanvas(),this._video.insertAdjacentElement("afterend",this._canvasParent);else if(!this._canvas)throw this.destroy(Error("Don't know where to render: you should give video or canvas in options."));this._bufferCanvas=document.createElement("canvas");let N=this._bufferCanvas.getContext("2d");if(!N)throw this.destroy(Error("Canvas rendering not supported"));if(this._bufferCtx=N,Z)this._initGPURenderer();else if(!this._offscreenRender)this._ctx=this._canvas.getContext("2d");if(this._canvasctrl=this._offscreenRender?this._canvas.transferControlToOffscreen():this._canvas,this._lastRenderTime=0,this.debug=!!J.debug,this.prescaleFactor=J.prescaleFactor||1,this.prescaleHeightLimit=J.prescaleHeightLimit||1080,this.maxRenderHeight=J.maxRenderHeight||0,this.renderAhead=J.renderAhead??0,this._boundResize=this.resize.bind(this),this._boundTimeUpdate=this._timeupdate.bind(this),this._boundSetRate=()=>this.setRate(this._video.playbackRate),this._boundUpdateColorSpace=this._updateColorSpace.bind(this),this._boundHandleRVFC=this._handleRVFC.bind(this),this._video)this.setVideo(this._video);if(this._onDemandRender)this.busy=!1,this._pendingDemandTimes.length=0;this._worker=new Worker(J.workerUrl||"akarisub-worker.js"),this._worker.onmessage=(Q)=>this._onmessage(Q),this._worker.onerror=(Q)=>this._error(Q),K.then(()=>{if(this._worker.postMessage({target:"init",wasmUrl:J.wasmUrl??"akarisub-worker.wasm",asyncRender:typeof createImageBitmap<"u"&&(J.asyncRender??!0),onDemandRender:this._onDemandRender,initialTime:(this._video?.currentTime??0)+this.timeOffset,width:this._canvasctrl.width||0,height:this._canvasctrl.height||0,blendMode:J.blendMode??"wasm",subUrl:J.subUrl,subContent:J.subContent||null,fonts:J.fonts||[],availableFonts:J.availableFonts||{"liberation sans":"./default.woff2"},fallbackFonts:J.fallbackFonts||["liberation sans"],debug:this.debug,targetFps:J.targetFps||24,dropAllAnimations:J.dropAllAnimations,dropAllBlur:J.dropAllBlur,clampPos:J.clampPos,libassMemoryLimit:J.libassMemoryLimit??128,libassGlyphLimit:J.libassGlyphLimit??2048,useLocalFonts:typeof globalThis.queryLocalFonts<"u"&&(J.useLocalFonts??!0),hasBitmapBug:R._hasBitmapBug}),this._offscreenRender)this.sendMessage("offscreenCanvas",{},[this._canvasctrl])})}static async _testImageBugs(){if(R._hasBitmapBug!==null)return;let J=document.createElement("canvas"),K=J.getContext("2d",{willReadFrequently:!0});if(!K)throw Error("Canvas rendering not supported");if(typeof ImageData.prototype.constructor==="function")try{new ImageData(new Uint8ClampedArray([0,0,0,0]),1,1)}catch{console.log("Detected that ImageData is not constructable despite browser saying so")}let Z=document.createElement("canvas"),N=Z.getContext("2d",{willReadFrequently:!0});if(!N)throw Error("Canvas rendering not supported");J.width=Z.width=1,J.height=Z.height=1,K.clearRect(0,0,1,1),N.clearRect(0,0,1,1);let Q=N.getImageData(0,0,1,1).data;K.putImageData(new ImageData(new Uint8ClampedArray([0,255,0,0]),1,1),0,0),N.drawImage(J,0,0);let F=N.getImageData(0,0,1,1).data;if(R._hasAlphaBug=Q[1]!==F[1],R._hasAlphaBug)console.log("Detected a browser having issue with transparent pixels, applying workaround");if(typeof createImageBitmap<"u"){let $=new Uint8ClampedArray([255,0,255,0,255]).subarray(1,5);N.drawImage(await createImageBitmap(new ImageData($,1)),0,0);let{data:U}=N.getImageData(0,0,1,1);R._hasBitmapBug=!1;for(let O=0;O<U.length;O++)if(Math.abs($[O]-U[O])>15){R._hasBitmapBug=!0,console.log("Detected a browser having issue with partial bitmaps, applying workaround");break}}else R._hasBitmapBug=!1;J.remove(),Z.remove()}static async _test(){await R._testImageBugs()}async _initGPURenderer(){if(f())try{let J=new v;if(await J.init(),!this._canvas)return;await J.setCanvas(this._canvas,Math.max(1,this._canvas.width||1),Math.max(1,this._canvas.height||1)),this._gpuRenderer=J,this._rendererType="webgpu",console.log("[AkariSub] Using WebGPU renderer");return}catch(J){console.warn("[AkariSub] WebGPU init failed, trying WebGL2:",J)}if(p())try{let J=new x;if(await J.init(),!this._canvas)return;await J.setCanvas(this._canvas,Math.max(1,this._canvas.width||1),Math.max(1,this._canvas.height||1)),this._gpuRenderer=J,this._rendererType="webgl2",console.log("[AkariSub] Using WebGL2 renderer");return}catch(J){console.warn("[AkariSub] WebGL2 init failed, falling back to Canvas2D:",J)}if(this._rendererType="canvas2d",!this._offscreenRender&&!this._ctx)this._ctx=this._canvas.getContext("2d");this.sendMessage("setAsyncRender",{value:!1}),this._onCanvasFallback?.()}get rendererType(){return this._rendererType}get isUsingWebGPU(){return this._rendererType==="webgpu"}get isUsingGPURenderer(){return this._gpuRenderer!==null}_createCanvas(){return this._canvas=document.createElement("canvas"),this._canvas.style.display="block",this._canvas.style.position="absolute",this._canvas.style.pointerEvents="none",this._canvasParent.appendChild(this._canvas),this._canvas}resize(J=0,K=0,Z=0,N=0,Q=this._video?.paused??!1){if((!J||!K)&&this._video){let F=c(this._video),$;if(this._videoWidth){let U=this._video.videoWidth/this._videoWidth,O=this._video.videoHeight/this._videoHeight;$=w((F.width||0)/U,(F.height||0)/O,this.prescaleFactor,this.prescaleHeightLimit,this.maxRenderHeight)}else $=w(F.width||0,F.height||0,this.prescaleFactor,this.prescaleHeightLimit,this.maxRenderHeight);if(J=$.width,K=$.height,this._canvasParent)Z=F.y-(this._canvasParent.getBoundingClientRect().top-this._video.getBoundingClientRect().top),N=F.x;this._canvas.style.width=F.width+"px",this._canvas.style.height=F.height+"px"}if(this._canvas.style.top=Z+"px",this._canvas.style.left=N+"px",J>0&&K>0)this._canvasctrl.width=J,this._canvasctrl.height=K;if(this._gpuRenderer&&J>0&&K>0)this._gpuRenderer.updateSize(J,K);if(Q&&this.busy===!1)this.busy=!0;else Q=!1;this.sendMessage("canvas",{width:J,height:K,videoWidth:this._videoWidth||this._video?.videoWidth||0,videoHeight:this._videoHeight||this._video?.videoHeight||0,force:Q})}_timeupdate(J){let Z={seeking:!0,waiting:!0,playing:!1}[J.type];if(Z!=null)this._playstate=Z;this.setCurrentTime(this._video.paused||this._playstate,this._video.currentTime+this.timeOffset)}setVideo(J){if(J instanceof HTMLVideoElement){if(this._removeListeners(),this._video=J,this._onDemandRender){if(!this._destroyed&&this._video===J)J.requestVideoFrameCallback(this._boundHandleRVFC)}else this._playstate=J.paused,J.addEventListener("timeupdate",this._boundTimeUpdate,!1),J.addEventListener("progress",this._boundTimeUpdate,!1),J.addEventListener("waiting",this._boundTimeUpdate,!1),J.addEventListener("seeking",this._boundTimeUpdate,!1),J.addEventListener("playing",this._boundTimeUpdate,!1),J.addEventListener("ratechange",this._boundSetRate,!1),J.addEventListener("resize",this._boundResize,!1);if("VideoFrame"in window){if(J.addEventListener("loadedmetadata",this._boundUpdateColorSpace,!1),J.readyState>2)this._updateColorSpace()}if(J.videoWidth>0)this.resize();if(typeof ResizeObserver<"u"){if(!this._ro)this._ro=new ResizeObserver(()=>this.resize());this._ro.observe(J)}}else this._error(Error("Video element invalid!"))}runBenchmark(){this.sendMessage("runBenchmark")}setTrackByUrl(J){if(this.sendMessage("setTrackByUrl",{url:J}),this._reAttachOffscreen(),this._ctx)this._ctx.filter="none"}setTrack(J){if(this.sendMessage("setTrack",{content:J}),this._reAttachOffscreen(),this._ctx)this._ctx.filter="none"}freeTrack(){this.sendMessage("freeTrack")}setIsPaused(J){this.sendMessage("video",{isPaused:J})}setRate(J){this.sendMessage("video",{rate:J})}setCurrentTime(J,K,Z){this.sendMessage("video",{isPaused:J,currentTime:K,rate:Z,colorSpace:this._videoColorSpace})}createEvent(J){this.sendMessage("createEvent",{event:J})}setEvent(J,K){this.sendMessage("setEvent",{event:J,index:K})}removeEvent(J){this.sendMessage("removeEvent",{index:J})}async getEvents(){return(await this._fetchFromWorker({target:"getEvents"})).events??[]}styleOverride(J){this.sendMessage("styleOverride",{style:J})}disableStyleOverride(){this.sendMessage("disableStyleOverride")}createStyle(J){this.sendMessage("createStyle",{style:J})}setStyle(J,K){this.sendMessage("setStyle",{style:J,index:K})}removeStyle(J){this.sendMessage("removeStyle",{index:J})}async getStyles(){return(await this._fetchFromWorker({target:"getStyles"})).styles??[]}addFont(J){this.sendMessage("addFont",{font:J})}setDefaultFont(J){this.sendMessage("defaultFont",{font:J})}async getStats(){let K=(await this._fetchFromWorker({target:"getStats"})).stats;return{framesRendered:K.framesRendered??0,framesDropped:K.framesDropped??0,avgRenderTime:K.avgRenderTime??0,maxRenderTime:K.maxRenderTime??0,minRenderTime:K.minRenderTime??0,lastRenderTime:K.lastRenderTime??0,pendingRenders:K.pendingRenders??0,totalEvents:K.totalEvents??0,cacheHits:K.cacheHits??0,cacheMisses:K.cacheMisses??0,renderFps:K.avgRenderTime&&K.avgRenderTime>0?Math.round(1000/K.avgRenderTime):0,usingWorker:!0,offscreenRender:this._offscreenRender,onDemandRender:this._onDemandRender}}async resetStats(){await this._fetchFromWorker({target:"resetStats"})}async getEventCount(){return(await this._fetchFromWorker({target:"getEventCount"})).count}async getStyleCount(){return(await this._fetchFromWorker({target:"getStyleCount"})).count}_sendLocalFont(J){try{globalThis.queryLocalFonts().then((K)=>{let Z=K?.find((N)=>N.fullName.toLowerCase()===J);if(Z)Z.blob().then((N)=>{N.arrayBuffer().then((Q)=>{this.addFont(new Uint8Array(Q))})})})}catch(K){console.warn("Local fonts API:",K)}}_getLocalFont(J){try{if(navigator?.permissions?.query)navigator.permissions.query({name:"local-fonts"}).then((K)=>{if(K.state==="granted")this._sendLocalFont(J.font)});else this._sendLocalFont(J.font)}catch(K){console.warn("Local fonts API:",K)}}_unbusy(){if(this._pendingDemandTimes.length>0){if(this._pendingDemandTimes.length>1){let K=this._pendingDemandTimes[this._pendingDemandTimes.length-1];this._pendingDemandTimes.length=0,this._pendingDemandTimes.push(K)}let J=this._pendingDemandTimes.shift();if(J){this._demandRender(J);return}}this.busy=!1}_enqueueDemand(J){let K=this._pendingDemandTimes;if(K.length>0){let Z=K[K.length-1];if(Math.abs(Z.mediaTime-J.mediaTime)>0.25)K.length=0}if(K.length>=R.MAX_PENDING_DEMANDS)K.shift();K.push(J)}_handleRVFC(J,K){if(this._destroyed)return;let Z=this._video?.playbackRate??1,Q={mediaTime:K.mediaTime+this.renderAhead*Z,width:K.width,height:K.height};if(!this._workerReady){this._enqueueDemand(Q),this._video.requestVideoFrameCallback(this._boundHandleRVFC);return}if(this.busy)this._enqueueDemand(Q);else this.busy=!0,this._demandRender(Q);this._video.requestVideoFrameCallback(this._boundHandleRVFC)}_demandRender(J){if(J.width!==this._videoWidth||J.height!==this._videoHeight)this._videoWidth=J.width,this._videoHeight=J.height,this.resize();this.sendMessage("demand",{time:J.mediaTime+this.timeOffset})}_detachOffscreen(){if(!this._offscreenRender||this._ctx)return;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas,this._ctx=this._canvasctrl.getContext("2d"),this.sendMessage("detachOffscreen"),this.busy=!1,this._pendingDemandTimes.length=0,this.resize(0,0,0,0,!0)}_reAttachOffscreen(){if(!this._offscreenRender||!this._ctx)return;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas.transferControlToOffscreen(),this._ctx=!1,this.sendMessage("offscreenCanvas",{},[this._canvasctrl]),this.resize(0,0,0,0,!0)}_updateColorSpace(){this._video.requestVideoFrameCallback(()=>{try{let J=new globalThis.VideoFrame(this._video);this._videoColorSpace=u[J.colorSpace.matrix]??null,J.close(),this.sendMessage("getColorSpace")}catch(J){console.warn(J)}})}_verifyColorSpace(J){let{subtitleColorSpace:K,videoColorSpace:Z=this._videoColorSpace}=J;if(!K||!Z)return;if(K===Z)return;this._detachOffscreen();let N=y[K]?.[Z];if(N&&this._ctx)this._ctx.filter=`url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><filter id='f'><feColorMatrix type='matrix' values='${N} 0 0 0 0 0 1 0'/></filter></svg>#f")`}_render(J){this._unbusy();let{width:K,height:Z}=J;if(this.debug)J.times.IPCTime=Date.now()-(J.times.JSRenderTime||0);if(this._canvasctrl.width!==K||this._canvasctrl.height!==Z){if(this._canvasctrl.width=K,this._canvasctrl.height=Z,this._lastRenderWidth=K,this._lastRenderHeight=Z,this._gpuRenderer)this._gpuRenderer.updateSize(K,Z);this._verifyColorSpace({subtitleColorSpace:J.colorSpace})}if(this._gpuRenderer){this._renderGPU(J);return}if(!this._ctx)return;let Q=this._ctx,F=J.images,$=F.length;if(Q.clearRect(0,0,K,Z),J.asyncRender)for(let U=0;U<$;U++){let O=F[U];if(O.image)Q.drawImage(O.image,O.x,O.y),O.image.close()}else{let U=R._hasAlphaBug??!1;for(let O=0;O<$;O++){let E=F[O];if(E.image){let{w:q,h:L}=E,_=new Uint8ClampedArray(E.image),Y=m(_,U);Q.putImageData(new ImageData(Y,q,L),E.x,E.y)}}}if(this.debug){J.times.JSRenderTime=Date.now()-(J.times.JSRenderTime||0)-(J.times.IPCTime||0);let U=0,O=J.times.bitmaps||$;delete J.times.bitmaps;for(let E in J.times)U+=J.times[E]||0;console.log("Bitmaps: "+O+" Total: "+(U|0)+"ms",J.times)}}_renderGPU(J){let K=this._gpuRenderer;if(!K)return;if(J.images.length===0){K.clear();return}if(J.asyncRender){let Z=J.images.filter((N)=>N.image instanceof ImageBitmap).map((N)=>({image:N.image,x:N.x,y:N.y}));K.renderBitmaps(Z,this._canvasctrl.width,this._canvasctrl.height);for(let N of J.images)if(N.image instanceof ImageBitmap)N.image.close()}else K.render(J.images,this._canvasctrl.width,this._canvasctrl.height);if(this.debug){J.times.JSRenderTime=Date.now()-(J.times.JSRenderTime||0)-(J.times.IPCTime||0);let Z=0,N=J.times.bitmaps||J.images.length;delete J.times.bitmaps;for(let Q in J.times)Z+=J.times[Q]||0;console.log(`[${this._rendererType.toUpperCase()}] Bitmaps: `+N+" Total: "+(Z|0)+"ms",J.times)}}_ready(){if(this._workerReady=!0,this._init(),this._onDemandRender&&this._video){this.setCurrentTime(this._video.paused,this._video.currentTime+this.timeOffset,this._video.playbackRate);let J=this._pendingDemandTimes.length>0?this._pendingDemandTimes[this._pendingDemandTimes.length-1]:{mediaTime:this._video.currentTime+this.renderAhead*(this._video.playbackRate||1),width:this._video.videoWidth,height:this._video.videoHeight};this._pendingDemandTimes.length=0,this.busy=!0,this._demandRender(J)}this.dispatchEvent(new CustomEvent("ready"))}_partial_ready(){this.dispatchEvent(new CustomEvent("partial_ready"))}async sendMessage(J,K={},Z){if(await this._loaded,Z)this._worker.postMessage({target:J,transferable:Z,...K},[...Z]);else this._worker.postMessage({target:J,...K})}_fetchFromWorker(J){return new Promise((K,Z)=>{try{let N=J.target,Q=setTimeout(()=>{U(),Z(Error("Error: Timeout while trying to fetch "+N))},5000),F=(O)=>{if(O.data.target===N)U(),K(O.data)},$=(O)=>{U(),Z(O instanceof Error?O:O.error||Error("Worker error"))},U=()=>{this._worker.removeEventListener("message",F),this._worker.removeEventListener("error",$),clearTimeout(Q)};this._worker.addEventListener("message",F),this._worker.addEventListener("error",$),this._worker.postMessage(J)}catch(N){Z(N)}})}_console(J){console[J.command].apply(console,JSON.parse(J.content))}_onmessage(J){let K=J.data.target;if(K==="error"){this._error(J.data.error||"Unknown worker error");return}let Z=this["_"+K];if(Z)Z.call(this,J.data)}_error(J){let K=J instanceof Error?J:J instanceof ErrorEvent?J.error||Error(J.message):Error(String(J)),Z=J instanceof Event?new ErrorEvent(J.type,J):new ErrorEvent("error",{error:K});return this.dispatchEvent(Z),console.error(K),K}_removeListeners(){if(this._video){if(this._ro)this._ro.unobserve(this._video);if(this._ctx)this._ctx.filter="none";this._video.removeEventListener("timeupdate",this._boundTimeUpdate),this._video.removeEventListener("progress",this._boundTimeUpdate),this._video.removeEventListener("waiting",this._boundTimeUpdate),this._video.removeEventListener("seeking",this._boundTimeUpdate),this._video.removeEventListener("playing",this._boundTimeUpdate),this._video.removeEventListener("ratechange",this._boundSetRate),this._video.removeEventListener("resize",this._boundResize),this._video.removeEventListener("loadedmetadata",this._boundUpdateColorSpace)}}destroy(J){let K=J?this._error(J):void 0;if(this._video&&this._canvasParent)this._video.parentNode?.removeChild(this._canvasParent);if(this._gpuRenderer)this._gpuRenderer.destroy(),this._gpuRenderer=null,this._rendererType="canvas2d";return this._destroyed=!0,this._removeListeners(),this.sendMessage("destroy"),this._worker?.terminate(),K}}export{u as webYCbCrMap,l as testImageBugs,e as runFeatureTests,o as parseAss,g as libassYCbCrMap,f as isWebGPUSupported,p as isWebGL2Supported,c as getVideoPosition,s as getColorSpaceFilterUrl,KJ as getBitmapBug,JJ as getAlphaBug,t as fixPlayRes,m as fixAlpha,n as dropBlur,R as default,w as computeCanvasSize,y as colorMatrixConversionMap,v as WebGPURenderer,x as WebGL2Renderer,R as AkariSub};
|
|
147
|
+
`),$=J.createProgram();if(J.attachShader($,Z),J.attachShader($,Q),J.linkProgram($),!J.getProgramParameter($,J.LINK_STATUS))throw Error(`WebGL2 program link failed: ${J.getProgramInfoLog($)}`);J.deleteShader(Z),J.deleteShader(Q),this._program=$,this._resolutionLoc=J.getUniformLocation($,"u_resolution"),this._texArraySizeLoc=J.getUniformLocation($,"u_texArraySize"),this._vao=J.createVertexArray(),J.bindVertexArray(this._vao),this._instanceBuffer=J.createBuffer(),J.bindBuffer(J.ARRAY_BUFFER,this._instanceBuffer),J.bufferData(J.ARRAY_BUFFER,8192,J.DYNAMIC_DRAW);let N=J.getAttribLocation($,"a_destRect");J.enableVertexAttribArray(N),J.vertexAttribPointer(N,4,J.FLOAT,!1,32,0),J.vertexAttribDivisor(N,1);let O=J.getAttribLocation($,"a_texInfo");J.enableVertexAttribArray(O),J.vertexAttribPointer(O,4,J.FLOAT,!1,32,16),J.vertexAttribDivisor(O,1),J.bindVertexArray(null),this._texArray=J.createTexture(),this._allocateTextureArray(256,256,32),J.enable(J.BLEND),J.blendEquation(J.FUNC_ADD),J.blendFunc(J.ONE,J.ONE_MINUS_SRC_ALPHA),this._initialized=!0}_nextPow2(J){return J--,J|=J>>1,J|=J>>2,J|=J>>4,J|=J>>8,J|=J>>16,J+1}_allocateTextureArray(J,Z,Q){let $=this._gl,N=this._nextPow2(Math.max(J,64)),O=this._nextPow2(Math.max(Z,64)),K=Math.min(this._nextPow2(Math.max(Q,16)),256);$.bindTexture($.TEXTURE_2D_ARRAY,this._texArray),$.texImage3D($.TEXTURE_2D_ARRAY,0,$.RGBA8,N,O,K,0,$.RGBA,$.UNSIGNED_BYTE,null),$.texParameteri($.TEXTURE_2D_ARRAY,$.TEXTURE_MIN_FILTER,$.NEAREST),$.texParameteri($.TEXTURE_2D_ARRAY,$.TEXTURE_MAG_FILTER,$.NEAREST),$.texParameteri($.TEXTURE_2D_ARRAY,$.TEXTURE_WRAP_S,$.CLAMP_TO_EDGE),$.texParameteri($.TEXTURE_2D_ARRAY,$.TEXTURE_WRAP_T,$.CLAMP_TO_EDGE),this._texWidth=N,this._texHeight=O,this._texLayers=K}_ensureTextureArray(J,Z,Q){let $=Math.min(Q,256);if(J<=this._texWidth&&Z<=this._texHeight&&$<=this._texLayers)return;let N=this._nextPow2(Math.max(this._texWidth,J)),O=this._nextPow2(Math.max(this._texHeight,Z)),K=Math.min(this._nextPow2(Math.max(this._texLayers,$,$+16)),256);this._allocateTextureArray(N,O,K)}async setCanvas(J,Z,Q){if(await this.init(),Z<=0||Q<=0)return;this._canvas=J,J.width=Z,J.height=Q,this._initGL(),this._gl.viewport(0,0,Z,Q),this._lastCanvasWidth=Z,this._lastCanvasHeight=Q}updateSize(J,Z){if(!this._gl||!this._canvas||J<=0||Z<=0)return;if(J===this._lastCanvasWidth&&Z===this._lastCanvasHeight)return;this._canvas.width=J,this._canvas.height=Z,this._gl.viewport(0,0,J,Z),this._lastCanvasWidth=J,this._lastCanvasHeight=Z}renderBitmaps(J,Z,Q){if(!this._gl||!this._initialized)return;let $=J.length;if($===0){this.clear();return}let N=0,O=0;for(let U=0;U<$;U++){let{image:E}=J[U];if(E.width>N)N=E.width;if(E.height>O)O=E.height}this._ensureTextureArray(N,O,Math.min($,256));let K=this._gl;K.clearColor(0,0,0,0),K.clear(K.COLOR_BUFFER_BIT),K.useProgram(this._program),K.uniform2f(this._resolutionLoc,this._lastCanvasWidth,this._lastCanvasHeight),K.uniform2i(this._texArraySizeLoc,this._texWidth,this._texHeight),K.activeTexture(K.TEXTURE0),K.bindTexture(K.TEXTURE_2D_ARRAY,this._texArray),K.pixelStorei(K.UNPACK_FLIP_Y_WEBGL,!1);let F=this._instanceData,G=0;while(G<$){let U=0;while(G<$&&U<256){let E=J[G++],M=E.image.width,q=E.image.height;if(M<=0||q<=0)continue;K.texSubImage3D(K.TEXTURE_2D_ARRAY,0,0,0,U,M,q,1,K.RGBA,K.UNSIGNED_BYTE,E.image);let Y=U<<3;F[Y]=E.x,F[Y+1]=E.y,F[Y+2]=M,F[Y+3]=q,F[Y+4]=M,F[Y+5]=q,F[Y+6]=U,F[Y+7]=0,U++}if(U===0)continue;K.bindBuffer(K.ARRAY_BUFFER,this._instanceBuffer),K.bufferSubData(K.ARRAY_BUFFER,0,F,0,U<<3),K.bindVertexArray(this._vao),K.drawArraysInstanced(K.TRIANGLES,0,6,U),K.bindVertexArray(null)}}render(J,Z,Q){if(!this._gl||!this._initialized)return;let $=J.length;if($===0){this.clear();return}let N=0,O=0;for(let U=0;U<$;U++){let{w:E,h:M}=J[U];if(E>N)N=E;if(M>O)O=M}this._ensureTextureArray(N,O,Math.min($,256));let K=this._gl;K.clearColor(0,0,0,0),K.clear(K.COLOR_BUFFER_BIT),K.useProgram(this._program),K.uniform2f(this._resolutionLoc,this._lastCanvasWidth,this._lastCanvasHeight),K.uniform2i(this._texArraySizeLoc,this._texWidth,this._texHeight),K.activeTexture(K.TEXTURE0),K.bindTexture(K.TEXTURE_2D_ARRAY,this._texArray),K.pixelStorei(K.UNPACK_FLIP_Y_WEBGL,!1);let F=this._instanceData,G=0;while(G<$){let U=0;while(G<$&&U<256){let E=J[G++],M=E.w,q=E.h;if(M<=0||q<=0)continue;let Y=E.image;if(Y instanceof ImageBitmap)K.texSubImage3D(K.TEXTURE_2D_ARRAY,0,0,0,U,M,q,1,K.RGBA,K.UNSIGNED_BYTE,Y);else if(Y instanceof ArrayBuffer||KJ(Y)){let B=Y instanceof ArrayBuffer?new Uint8Array(Y):Y;K.texSubImage3D(K.TEXTURE_2D_ARRAY,0,0,0,U,M,q,1,K.RGBA,K.UNSIGNED_BYTE,B)}let L=U<<3;F[L]=E.x,F[L+1]=E.y,F[L+2]=M,F[L+3]=q,F[L+4]=M,F[L+5]=q,F[L+6]=U,F[L+7]=0,U++}if(U===0)continue;K.bindBuffer(K.ARRAY_BUFFER,this._instanceBuffer),K.bufferSubData(K.ARRAY_BUFFER,0,F,0,U<<3),K.bindVertexArray(this._vao),K.drawArraysInstanced(K.TRIANGLES,0,6,U),K.bindVertexArray(null)}}clear(){if(!this._gl)return;this._gl.clearColor(0,0,0,0),this._gl.clear(this._gl.COLOR_BUFFER_BIT)}get initialized(){return this._initialized}destroy(){let J=this._gl;if(J)J.deleteProgram(this._program),J.deleteVertexArray(this._vao),J.deleteBuffer(this._instanceBuffer),J.deleteTexture(this._texArray);this._gl=null,this._program=null,this._vao=null,this._instanceBuffer=null,this._texArray=null,this._canvas=null,this._initialized=!1,this._initPromise=null}}var d=0.008,NJ=d*1000,OJ=16,GJ=()=>{if(typeof navigator>"u")return!1;let J=navigator.userAgent||"",Z=navigator.vendor||"",Q=/\b(iPhone|iPad|iPod)\b/i.test(J);if(!/AppleWebKit/i.test(J))return!1;if(Q)return!0;if(/\b(Chrome|Chromium|Edg|OPR|SamsungBrowser|Firefox)\b/i.test(J))return!1;return Z.includes("Apple")};class H extends EventTarget{static MAX_PENDING_DEMANDS=3;static _hasAlphaBug=null;static _hasBitmapBug=null;_loaded;_init;_onDemandRender;_offscreenRender;_video;_videoWidth=0;_videoHeight=0;_videoColorSpace=null;_canvas;_canvasParent;_bufferCanvas;_bufferCtx;_canvasctrl;_ctx=null;_lastRenderTime=0;_playstate=!0;_destroyed=!1;_workerReady=!1;_ro;_worker;_pendingDemandTimes=[];_isLikelyWebKit;_activeDemandStartedAt=0;_smoothedDemandLatencyMs;_boundResize;_boundTimeUpdate;_boundSetRate;_boundUpdateColorSpace;_boundHandleRVFC;_gpuRenderer=null;_rendererType="canvas2d";_onCanvasFallback;_lastRenderWidth=0;_lastRenderHeight=0;_gpuBitmapImages=[];timeOffset;debug;prescaleFactor;prescaleHeightLimit;maxRenderHeight;busy=!1;renderAhead;constructor(J){super();if(!globalThis.Worker)throw this.destroy(Error("Worker not supported"));if(!J)throw this.destroy(Error("No options provided"));this._loaded=new Promise((O)=>{this._init=O}),this._isLikelyWebKit=GJ(),this._smoothedDemandLatencyMs=this._isLikelyWebKit?OJ:NJ;let Z=H._test();this._onDemandRender="requestVideoFrameCallback"in HTMLVideoElement.prototype&&(J.onDemandRender??!0),this._onCanvasFallback=J.onCanvasFallback;let Q=!this._isLikelyWebKit&&!J.canvas&&(f()||p()),$=typeof createImageBitmap<"u"&&(J.asyncRender??!this._isLikelyWebKit);if(this._offscreenRender="transferControlToOffscreen"in HTMLCanvasElement.prototype&&!J.canvas&&!Q&&(J.offscreenRender??!0),this.timeOffset=J.timeOffset||0,this._video=J.video,this._canvas=J.canvas,this._video&&!this._canvas)this._canvasParent=document.createElement("div"),this._canvasParent.className="AkariSub",this._canvasParent.style.position="relative",this._canvas=this._createCanvas(),this._video.insertAdjacentElement("afterend",this._canvasParent);else if(!this._canvas)throw this.destroy(Error("Don't know where to render: you should give video or canvas in options."));this._bufferCanvas=document.createElement("canvas");let N=this._bufferCanvas.getContext("2d");if(!N)throw this.destroy(Error("Canvas rendering not supported"));if(this._bufferCtx=N,Q)this._initGPURenderer();else if(!this._offscreenRender)this._ctx=this._canvas.getContext("2d",{alpha:!0,desynchronized:!0});if(this._canvasctrl=this._offscreenRender?this._canvas.transferControlToOffscreen():this._canvas,this._lastRenderTime=0,this.debug=!!J.debug,this.prescaleFactor=J.prescaleFactor||1,this.prescaleHeightLimit=J.prescaleHeightLimit||1080,this.maxRenderHeight=J.maxRenderHeight||0,this.renderAhead=J.renderAhead??d,this._boundResize=this.resize.bind(this),this._boundTimeUpdate=this._timeupdate.bind(this),this._boundSetRate=()=>this.setRate(this._video.playbackRate),this._boundUpdateColorSpace=this._updateColorSpace.bind(this),this._boundHandleRVFC=this._handleRVFC.bind(this),this._video)this.setVideo(this._video);if(this._onDemandRender)this.busy=!1,this._pendingDemandTimes.length=0;this._worker=new Worker(J.workerUrl||"akarisub-worker.js"),this._worker.onmessage=(O)=>this._onmessage(O),this._worker.onerror=(O)=>this._error(O),Z.then(()=>{if(this._worker.postMessage({target:"init",wasmUrl:J.wasmUrl??"akarisub-worker.wasm",asyncRender:$,fullTrackWarmup:J.fullTrackWarmup??!1,onDemandRender:this._onDemandRender,initialTime:(this._video?.currentTime??0)+this.timeOffset,width:this._canvasctrl.width||0,height:this._canvasctrl.height||0,blendMode:J.blendMode??"wasm",subUrl:J.subUrl,subContent:J.subContent||null,fonts:J.fonts||[],availableFonts:J.availableFonts||{"liberation sans":"./default.woff2"},fallbackFonts:J.fallbackFonts||["liberation sans"],debug:this.debug,targetFps:J.targetFps||24,dropAllAnimations:J.dropAllAnimations,dropAllBlur:J.dropAllBlur,clampPos:J.clampPos,libassMemoryLimit:J.libassMemoryLimit??128,libassGlyphLimit:J.libassGlyphLimit??2048,useLocalFonts:typeof globalThis.queryLocalFonts<"u"&&(J.useLocalFonts??!0),hasBitmapBug:H._hasBitmapBug}),this._offscreenRender)this.sendMessage("offscreenCanvas",{},[this._canvasctrl])})}static async _testImageBugs(){if(H._hasBitmapBug!==null)return;let J=document.createElement("canvas"),Z=J.getContext("2d",{willReadFrequently:!0});if(!Z)throw Error("Canvas rendering not supported");if(typeof ImageData.prototype.constructor==="function")try{new ImageData(new Uint8ClampedArray([0,0,0,0]),1,1)}catch{console.log("Detected that ImageData is not constructable despite browser saying so")}let Q=document.createElement("canvas"),$=Q.getContext("2d",{willReadFrequently:!0});if(!$)throw Error("Canvas rendering not supported");J.width=Q.width=1,J.height=Q.height=1,Z.clearRect(0,0,1,1),$.clearRect(0,0,1,1);let N=$.getImageData(0,0,1,1).data;Z.putImageData(new ImageData(new Uint8ClampedArray([0,255,0,0]),1,1),0,0),$.drawImage(J,0,0);let O=$.getImageData(0,0,1,1).data;if(H._hasAlphaBug=N[1]!==O[1],H._hasAlphaBug)console.log("Detected a browser having issue with transparent pixels, applying workaround");if(typeof createImageBitmap<"u"){let K=new Uint8ClampedArray([255,0,255,0,255]).subarray(1,5);$.drawImage(await createImageBitmap(new ImageData(K,1)),0,0);let{data:F}=$.getImageData(0,0,1,1);H._hasBitmapBug=!1;for(let G=0;G<F.length;G++)if(Math.abs(K[G]-F[G])>15){H._hasBitmapBug=!0,console.log("Detected a browser having issue with partial bitmaps, applying workaround");break}}else H._hasBitmapBug=!1;J.remove(),Q.remove()}static async _test(){await H._testImageBugs()}async _initGPURenderer(){if(f())try{let J=new v;if(await J.init(),!this._canvas)return;await J.setCanvas(this._canvas,Math.max(1,this._canvas.width||1),Math.max(1,this._canvas.height||1)),this._gpuRenderer=J,this._rendererType="webgpu",console.log("[AkariSub] Using WebGPU renderer");return}catch(J){console.warn("[AkariSub] WebGPU init failed, trying WebGL2:",J)}if(p())try{let J=new x;if(await J.init(),!this._canvas)return;await J.setCanvas(this._canvas,Math.max(1,this._canvas.width||1),Math.max(1,this._canvas.height||1)),this._gpuRenderer=J,this._rendererType="webgl2",console.log("[AkariSub] Using WebGL2 renderer");return}catch(J){console.warn("[AkariSub] WebGL2 init failed, falling back to Canvas2D:",J)}if(this._rendererType="canvas2d",!this._offscreenRender&&!this._ctx)this._ctx=this._canvas.getContext("2d",{alpha:!0,desynchronized:!0});this.sendMessage("setAsyncRender",{value:!1}),this._onCanvasFallback?.()}get rendererType(){return this._rendererType}get isUsingWebGPU(){return this._rendererType==="webgpu"}get isUsingGPURenderer(){return this._gpuRenderer!==null}_createCanvas(){return this._canvas=document.createElement("canvas"),this._canvas.style.display="block",this._canvas.style.position="absolute",this._canvas.style.pointerEvents="none",this._canvasParent.appendChild(this._canvas),this._canvas}resize(J=0,Z=0,Q=0,$=0,N=this._video?.paused??!1){if((!J||!Z)&&this._video){let O=c(this._video),K;if(this._videoWidth){let F=this._video.videoWidth/this._videoWidth,G=this._video.videoHeight/this._videoHeight;K=w((O.width||0)/F,(O.height||0)/G,this.prescaleFactor,this.prescaleHeightLimit,this.maxRenderHeight)}else K=w(O.width||0,O.height||0,this.prescaleFactor,this.prescaleHeightLimit,this.maxRenderHeight);if(J=K.width,Z=K.height,this._canvasParent)Q=O.y-(this._canvasParent.getBoundingClientRect().top-this._video.getBoundingClientRect().top),$=O.x;this._canvas.style.width=O.width+"px",this._canvas.style.height=O.height+"px"}if(this._canvas.style.top=Q+"px",this._canvas.style.left=$+"px",J>0&&Z>0)this._canvasctrl.width=J,this._canvasctrl.height=Z;if(this._gpuRenderer&&J>0&&Z>0)this._gpuRenderer.updateSize(J,Z);if(N&&this.busy===!1)this.busy=!0;else N=!1;this.sendMessage("canvas",{width:J,height:Z,videoWidth:this._videoWidth||this._video?.videoWidth||0,videoHeight:this._videoHeight||this._video?.videoHeight||0,force:N})}_timeupdate(J){let Q={seeking:!0,waiting:!0,playing:!1}[J.type];if(Q!=null)this._playstate=Q;this.setCurrentTime(this._video.paused||this._playstate,this._video.currentTime+this.timeOffset)}setVideo(J){if(J instanceof HTMLVideoElement){if(this._removeListeners(),this._video=J,this._onDemandRender){if(!this._destroyed&&this._video===J)J.requestVideoFrameCallback(this._boundHandleRVFC)}else this._playstate=J.paused,J.addEventListener("timeupdate",this._boundTimeUpdate,!1),J.addEventListener("progress",this._boundTimeUpdate,!1),J.addEventListener("waiting",this._boundTimeUpdate,!1),J.addEventListener("seeking",this._boundTimeUpdate,!1),J.addEventListener("playing",this._boundTimeUpdate,!1),J.addEventListener("ratechange",this._boundSetRate,!1),J.addEventListener("resize",this._boundResize,!1);if("VideoFrame"in window){if(J.addEventListener("loadedmetadata",this._boundUpdateColorSpace,!1),J.readyState>2)this._updateColorSpace()}if(J.videoWidth>0)this.resize();if(typeof ResizeObserver<"u"){if(!this._ro)this._ro=new ResizeObserver(()=>this.resize());this._ro.observe(J)}}else this._error(Error("Video element invalid!"))}runBenchmark(){this.sendMessage("runBenchmark")}setTrackByUrl(J){if(this.sendMessage("setTrackByUrl",{url:J}),this._reAttachOffscreen(),this._ctx)this._ctx.filter="none"}setTrack(J){if(this.sendMessage("setTrack",{content:J}),this._reAttachOffscreen(),this._ctx)this._ctx.filter="none"}freeTrack(){this.sendMessage("freeTrack")}setIsPaused(J){this.sendMessage("video",{isPaused:J})}setRate(J){this.sendMessage("video",{rate:J})}setCurrentTime(J,Z,Q){this.sendMessage("video",{isPaused:J,currentTime:Z,rate:Q,colorSpace:this._videoColorSpace})}createEvent(J){this.sendMessage("createEvent",{event:J})}setEvent(J,Z){this.sendMessage("setEvent",{event:J,index:Z})}removeEvent(J){this.sendMessage("removeEvent",{index:J})}async getEvents(){return(await this._fetchFromWorker({target:"getEvents"})).events??[]}styleOverride(J){this.sendMessage("styleOverride",{style:J})}disableStyleOverride(){this.sendMessage("disableStyleOverride")}createStyle(J){this.sendMessage("createStyle",{style:J})}setStyle(J,Z){this.sendMessage("setStyle",{style:J,index:Z})}removeStyle(J){this.sendMessage("removeStyle",{index:J})}async getStyles(){return(await this._fetchFromWorker({target:"getStyles"})).styles??[]}addFont(J){this.sendMessage("addFont",{font:J})}setDefaultFont(J){this.sendMessage("defaultFont",{font:J})}async getStats(){let Z=(await this._fetchFromWorker({target:"getStats"})).stats;return{framesRendered:Z.framesRendered??0,framesDropped:Z.framesDropped??0,avgRenderTime:Z.avgRenderTime??0,maxRenderTime:Z.maxRenderTime??0,minRenderTime:Z.minRenderTime??0,lastRenderTime:Z.lastRenderTime??0,pendingRenders:Z.pendingRenders??0,totalEvents:Z.totalEvents??0,cacheHits:Z.cacheHits??0,cacheMisses:Z.cacheMisses??0,renderFps:Z.avgRenderTime&&Z.avgRenderTime>0?Math.round(1000/Z.avgRenderTime):0,usingWorker:!0,offscreenRender:this._offscreenRender,onDemandRender:this._onDemandRender}}async resetStats(){await this._fetchFromWorker({target:"resetStats"})}async getEventCount(){return(await this._fetchFromWorker({target:"getEventCount"})).count}async getStyleCount(){return(await this._fetchFromWorker({target:"getStyleCount"})).count}_sendLocalFont(J){try{globalThis.queryLocalFonts().then((Z)=>{let Q=Z?.find(($)=>$.fullName.toLowerCase()===J);if(Q)Q.blob().then(($)=>{$.arrayBuffer().then((N)=>{this.addFont(new Uint8Array(N))})})})}catch(Z){console.warn("Local fonts API:",Z)}}_getLocalFont(J){try{if(navigator?.permissions?.query)navigator.permissions.query({name:"local-fonts"}).then((Z)=>{if(Z.state==="granted")this._sendLocalFont(J.font)});else this._sendLocalFont(J.font)}catch(Z){console.warn("Local fonts API:",Z)}}_unbusy(){if(this._observeDemandCompletion(),this._pendingDemandTimes.length>0){if(this._pendingDemandTimes.length>1){let Z=this._pendingDemandTimes[this._pendingDemandTimes.length-1];this._pendingDemandTimes.length=0,this._pendingDemandTimes.push(Z)}let J=this._pendingDemandTimes.shift();if(J){this._demandRender(J);return}}this.busy=!1}_markDemandDispatched(){if(!this._onDemandRender)return;this._activeDemandStartedAt=performance.now()}_observeDemandCompletion(){if(!this._onDemandRender||this._activeDemandStartedAt===0)return;let J=performance.now()-this._activeDemandStartedAt;if(this._activeDemandStartedAt=0,!Number.isFinite(J)||J<=0)return;this._smoothedDemandLatencyMs=this._smoothedDemandLatencyMs<=0?J:this._smoothedDemandLatencyMs*0.75+J*0.25}_getDemandPipelineLeadSeconds(J,Z){let Q=Z.expectedDisplayTime??Z.presentationTime??J,$=Math.max(0,Q-J)/1000;return Math.max(0,this._smoothedDemandLatencyMs/1000-$)}_enqueueDemand(J){let Z=this._pendingDemandTimes;if(Z.length>0){let Q=Z[Z.length-1];if(Math.abs(Q.mediaTime-J.mediaTime)>0.25)Z.length=0}if(Z.length>=H.MAX_PENDING_DEMANDS)Z.shift();Z.push(J)}_handleRVFC(J,Z){if(this._destroyed)return;let Q=this._video?.playbackRate??1,$=this._getDemandPipelineLeadSeconds(J,Z),O={mediaTime:Z.mediaTime+($+this.renderAhead)*Q,width:Z.width,height:Z.height};if(!this._workerReady){this._enqueueDemand(O),this._video.requestVideoFrameCallback(this._boundHandleRVFC);return}if(this.busy)this._enqueueDemand(O);else this.busy=!0,this._demandRender(O);this._video.requestVideoFrameCallback(this._boundHandleRVFC)}_demandRender(J){if(J.width!==this._videoWidth||J.height!==this._videoHeight)this._videoWidth=J.width,this._videoHeight=J.height,this.resize();this._markDemandDispatched(),this.sendMessage("demand",{time:J.mediaTime+this.timeOffset})}_detachOffscreen(){if(!this._offscreenRender||this._ctx)return;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas,this._ctx=this._canvasctrl.getContext("2d",{alpha:!0,desynchronized:!0}),this.sendMessage("detachOffscreen"),this.busy=!1,this._activeDemandStartedAt=0,this._pendingDemandTimes.length=0,this.resize(0,0,0,0,!0)}_reAttachOffscreen(){if(!this._offscreenRender||!this._ctx)return;this._canvas.remove(),this._createCanvas(),this._canvasctrl=this._canvas.transferControlToOffscreen(),this._ctx=!1,this.sendMessage("offscreenCanvas",{},[this._canvasctrl]),this.resize(0,0,0,0,!0)}_updateColorSpace(){this._video.requestVideoFrameCallback(()=>{try{let J=new globalThis.VideoFrame(this._video);this._videoColorSpace=u[J.colorSpace.matrix]??null,J.close(),this.sendMessage("getColorSpace")}catch(J){console.warn(J)}})}_verifyColorSpace(J){let{subtitleColorSpace:Z,videoColorSpace:Q=this._videoColorSpace}=J;if(!Z||!Q)return;if(Z===Q)return;this._detachOffscreen();let $=y[Z]?.[Q];if($&&this._ctx)this._ctx.filter=`url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><filter id='f'><feColorMatrix type='matrix' values='${$} 0 0 0 0 0 1 0'/></filter></svg>#f")`}_render(J){try{let{width:Z,height:Q}=J;if(this.debug)J.times.IPCTime=Date.now()-(J.times.JSRenderTime||0);if(this._canvasctrl.width!==Z||this._canvasctrl.height!==Q){if(this._canvasctrl.width=Z,this._canvasctrl.height=Q,this._lastRenderWidth=Z,this._lastRenderHeight=Q,this._gpuRenderer)this._gpuRenderer.updateSize(Z,Q);this._verifyColorSpace({subtitleColorSpace:J.colorSpace})}if(this._gpuRenderer){this._renderGPU(J);return}if(!this._ctx)return;let N=this._ctx,O=J.images,K=O.length;if(N.clearRect(0,0,Z,Q),J.asyncRender)for(let F=0;F<K;F++){let G=O[F];if(G.image)N.drawImage(G.image,G.x,G.y),G.image.close()}else{let F=H._hasAlphaBug??!1;for(let G=0;G<K;G++){let U=O[G];if(U.image){let{w:E,h:M,image:q}=U,Y=q instanceof Uint8ClampedArray?q:q instanceof Uint8Array?new Uint8ClampedArray(q.buffer,q.byteOffset,q.byteLength):new Uint8ClampedArray(q),L=m(Y,F);N.putImageData(new ImageData(L,E,M),U.x,U.y)}}}if(this.debug){J.times.JSRenderTime=Date.now()-(J.times.JSRenderTime||0)-(J.times.IPCTime||0);let F=0,G=J.times.bitmaps||K;delete J.times.bitmaps;for(let U in J.times)F+=J.times[U]||0;console.log("Bitmaps: "+G+" Total: "+(F|0)+"ms",J.times)}}finally{this._unbusy()}}_renderGPU(J){let Z=this._gpuRenderer;if(!Z)return;if(J.images.length===0){Z.clear();return}if(J.asyncRender){let Q=this._gpuBitmapImages,$=0;for(let N=0;N<J.images.length;N++){let O=J.images[N];if(!(O.image instanceof ImageBitmap))continue;let K=Q[$]||(Q[$]={image:O.image,x:0,y:0});K.image=O.image,K.x=O.x,K.y=O.y,$++}Q.length=$,Z.renderBitmaps(Q,this._canvasctrl.width,this._canvasctrl.height);for(let N of J.images)if(N.image instanceof ImageBitmap)N.image.close()}else Z.render(J.images,this._canvasctrl.width,this._canvasctrl.height);if(this.debug){J.times.JSRenderTime=Date.now()-(J.times.JSRenderTime||0)-(J.times.IPCTime||0);let Q=0,$=J.times.bitmaps||J.images.length;delete J.times.bitmaps;for(let N in J.times)Q+=J.times[N]||0;console.log(`[${this._rendererType.toUpperCase()}] Bitmaps: `+$+" Total: "+(Q|0)+"ms",J.times)}}_ready(){if(this._workerReady=!0,this._init(),this._onDemandRender&&this._video){this.setCurrentTime(this._video.paused,this._video.currentTime+this.timeOffset,this._video.playbackRate);let J=this._pendingDemandTimes.length>0?this._pendingDemandTimes[this._pendingDemandTimes.length-1]:{mediaTime:this._video.currentTime+this.renderAhead*(this._video.playbackRate||1),width:this._video.videoWidth,height:this._video.videoHeight};this._pendingDemandTimes.length=0,this.busy=!0,this._demandRender(J)}this.dispatchEvent(new CustomEvent("ready"))}_partial_ready(){this.dispatchEvent(new CustomEvent("partial_ready"))}async sendMessage(J,Z={},Q){if(await this._loaded,Q)this._worker.postMessage({target:J,transferable:Q,...Z},[...Q]);else this._worker.postMessage({target:J,...Z})}_fetchFromWorker(J){return new Promise((Z,Q)=>{try{let $=J.target,N=setTimeout(()=>{F(),Q(Error("Error: Timeout while trying to fetch "+$))},5000),O=(G)=>{if(G.data.target===$)F(),Z(G.data)},K=(G)=>{F(),Q(G instanceof Error?G:G.error||Error("Worker error"))},F=()=>{this._worker.removeEventListener("message",O),this._worker.removeEventListener("error",K),clearTimeout(N)};this._worker.addEventListener("message",O),this._worker.addEventListener("error",K),this._worker.postMessage(J)}catch($){Q($)}})}_console(J){console[J.command].apply(console,JSON.parse(J.content))}_onmessage(J){let Z=J.data.target;if(Z==="error"){this._error(J.data.error||"Unknown worker error");return}let Q=this["_"+Z];if(Q)Q.call(this,J.data)}_error(J){let Z=J instanceof Error?J:J instanceof ErrorEvent?J.error||Error(J.message):Error(String(J)),Q=J instanceof Event?new ErrorEvent(J.type,J):new ErrorEvent("error",{error:Z});return this.dispatchEvent(Q),console.error(Z),Z}_removeListeners(){if(this._video){if(this._ro)this._ro.unobserve(this._video);if(this._ctx)this._ctx.filter="none";this._video.removeEventListener("timeupdate",this._boundTimeUpdate),this._video.removeEventListener("progress",this._boundTimeUpdate),this._video.removeEventListener("waiting",this._boundTimeUpdate),this._video.removeEventListener("seeking",this._boundTimeUpdate),this._video.removeEventListener("playing",this._boundTimeUpdate),this._video.removeEventListener("ratechange",this._boundSetRate),this._video.removeEventListener("resize",this._boundResize),this._video.removeEventListener("loadedmetadata",this._boundUpdateColorSpace)}}destroy(J){let Z=J?this._error(J):void 0;if(this._video&&this._canvasParent)this._video.parentNode?.removeChild(this._canvasParent);if(this._gpuRenderer)this._gpuRenderer.destroy(),this._gpuRenderer=null,this._rendererType="canvas2d";return this._destroyed=!0,this._removeListeners(),this.sendMessage("destroy"),this._worker?.terminate(),Z}}export{u as webYCbCrMap,l as testImageBugs,JJ as runFeatureTests,r as parseAss,s as libassYCbCrMap,f as isWebGPUSupported,p as isWebGL2Supported,c as getVideoPosition,o as getColorSpaceFilterUrl,$J as getBitmapBug,ZJ as getAlphaBug,e as fixPlayRes,m as fixAlpha,i as dropBlur,H as default,w as computeCanvasSize,y as colorMatrixConversionMap,v as WebGPURenderer,x as WebGL2Renderer,H as AkariSub};
|