openlime
Version:
Open Layered IMage Explorer
9 lines • 346 kB
JavaScript
// ##########################################
// OpenLIME - Open Layered IMage Explorer
// Author: CNR ISTI - Visual Computing Lab
// Author: CRS4 Visual and Data-intensive Computing Group
// openlime v1.2.6 - GPL-3.0 License
// Documentation: https://cnr-isti-vclab.github.io/openlime/
// Repository: https://github.com/cnr-isti-vclab/openlime.git
// ##########################################
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).OpenLIME=t.OpenLIME||{})}(this,(function(t){"use strict";window.structuredClone="function"==typeof structuredClone?structuredClone:function(t){return JSON.parse(JSON.stringify(t))};class e{static padZeros(t,e){return t.toString().padStart(e,"0")}static printSrcCode(t){let i="";t.split(/\r\n|\r|\n/).forEach(((t,s)=>{const n=e.padZeros(s+1,5);i+=`${n} ${t}\n`})),console.log(i)}static createSVGElement(t,e){const i=document.createElementNS("http://www.w3.org/2000/svg",t);if(e)for(const[t,s]of Object.entries(e))i.setAttribute(t,s);return i}static SVGFromString(t){return(new DOMParser).parseFromString(t,"image/svg+xml").documentElement}static async loadSVG(t){let i=await fetch(t);if(!i.ok){const t=`An error has occured: ${i.status}`;throw new Error(t)}let s=await i.text(),n=null;if(!e.isSVGString(s)){throw new Error(`${t} is not an SVG file`)}return n=e.SVGFromString(s),n}static async loadHTML(t){let e=await fetch(t);if(!e.ok){const t=`An error has occured: ${e.status}`;throw new Error(t)}return await e.text()}static async loadJSON(t){let e=await fetch(t);if(!e.ok){const t=`An error has occured: ${e.status}`;throw new Error(t)}return await e.json()}static async loadImage(t){return new Promise(((e,i)=>{const s=new Image;s.addEventListener("load",(()=>e(s))),s.addEventListener("error",(t=>i(t))),s.src=t}))}static async appendImg(t,i,s=null){const n=await e.loadImage(i);return s&&n.classList.add(s),t.appendChild(n),n}static async appendImgs(t,i,s=null){for(const n of i){const i=await e.loadImage(n);s&&i.classList.add(s),t.appendChild(i)}}static isSVGString(t){return null!=t&&null!=t&&(t=(t=t.toString().replace(/\s*<!Entity\s+\S*\s*(?:"|')[^"]+(?:"|')\s*>/gim,"")).replace(/<!--([\s\S]*?)-->/g,""),Boolean(t)&&/^\s*(?:<\?xml[^>]*>\s*)?(?:<!doctype svg[^>]*\s*(?:\[?(?:\s*<![^>]*>\s*)*\]?)*[^>]*>\s*)?(?:<svg[^>]*>[^]*<\/svg>|<svg[^/>]*\/\s*>)\s*$/i.test(t))}static computeSDF(t,e,i,s=.25,n=8){function r(t,e,i,s,n,r,a){for(let l=0;l<e;l++){for(let n=0;n<i;n++)s[n]=t[n*e+l];o(s,n,r,a,i);for(let s=0;s<i;s++)t[s*e+l]=n[s]}for(let l=0;l<i;l++){for(let i=0;i<e;i++)s[i]=t[l*e+i];o(s,n,r,a,e);for(let i=0;i<e;i++)t[l*e+i]=Math.sqrt(n[i])}}function o(t,e,i,s,n){i[0]=0,s[0]=-l,s[1]=+l;for(let e=1,o=0;e<n;e++){for(var r=(t[e]+e*e-(t[i[o]]+i[o]*i[o]))/(2*e-2*i[o]);r<=s[o];)o--,r=(t[e]+e*e-(t[i[o]]+i[o]*i[o]))/(2*e-2*i[o]);o++,i[o]=e,s[o]=r,s[o+1]=+l}for(let r=0,o=0;r<n;r++){for(;s[o+1]<r;)o++;e[r]=(r-i[o])*(r-i[o])+t[i[o]]}}var a=new Uint8ClampedArray(t);const l=1e20,h=Math.max(e,i),c=Array(e*i),d=Array(e*i),u=Array(h),p=Array(h),m=Array(h+1),f=Array(h);for(let t=0;t<e*i;t++){var g=a[t]/255;c[t]=1===g?0:0===g?l:Math.pow(Math.max(0,.5-g),2),d[t]=1===g?l:0===g?0:Math.pow(Math.max(0,g-.5),2)}r(c,e,i,u,p,f,m),r(d,e,i,u,p,f,m);const v=window.Float32Array?new Float32Array(e*i):new Array(e*i);for(let t=0;t<e*i;t++)v[t]=Math.min(Math.max(1-((c[t]-d[t])/n+s),0),1);return v}static async rasterizeSVG(t,i=[64,64]){const s=await e.loadSVG(t),n=s.getAttribute("width"),r=s.getAttribute("height"),o=document.createElement("canvas");o.width=i[0],o.height=i[1],s.setAttributeNS(null,"width","100%"),s.setAttributeNS(null,"height","100%");const a=o.getContext("2d"),l=(new XMLSerializer).serializeToString(s),h=window.URL||window.webkitURL||window,c=new Image,d=new Blob([l],{type:"image/svg+xml;charset=utf-8"}),u=h.createObjectURL(d);return c.src=u,new Promise(((t,e)=>{c.onload=()=>{const e=i[0]/i[1],s=n/r;let o=0,l=0;s<e?(l=i[1],o=l*s):(o=i[0],l=o/s);let d=.5*(i[1]-l),p=.5*(i[0]-o);a.translate(p,d),a.drawImage(c,0,0),h.revokeObjectURL(u);const m=a.getImageData(0,0,i[0],i[1]);t(m)},c.onerror=t=>e(t)}))}}class i{constructor(t){Object.assign(this,{xLow:1e20,yLow:1e20,xHigh:-1e20,yHigh:-1e20}),Object.assign(this,t)}fromArray(t){this.xLow=t[0],this.yLow=t[1],this.xHigh=t[2],this.yHigh=t[3]}toEmpty(){this.xLow=1e20,this.yLow=1e20,this.xHigh=-1e20,this.yHigh=-1e20}isEmpty(){return this.xLow>=this.xHigh||this.yLow>=this.yHigh}toArray(){return[this.xLow,this.yLow,this.xHigh,this.yHigh]}toString(){return this.xLow.toString()+" "+this.yLow.toString()+" "+this.xHigh.toString()+" "+this.yHigh.toString()}mergeBox(t){null!=t&&(this.isEmpty()?Object.assign(this,t):(this.xLow=Math.min(this.xLow,t.xLow),this.yLow=Math.min(this.yLow,t.yLow),this.xHigh=Math.max(this.xHigh,t.xHigh),this.yHigh=Math.max(this.yHigh,t.yHigh)))}mergePoint(t){this.xLow=Math.min(this.xLow,t.x),this.yLow=Math.min(this.yLow,t.y),this.xHigh=Math.max(this.xHigh,t.x),this.yHigh=Math.max(this.yHigh,t.y)}shift(t,e){this.xLow+=t,this.yLow+=e,this.xHigh+=t,this.yHigh+=e}quantize(t){this.xLow=Math.floor(this.xLow/t),this.yLow=Math.floor(this.yLow/t),this.xHigh=Math.floor((this.xHigh-1)/t)+1,this.yHigh=Math.floor((this.yHigh-1)/t)+1}width(){return Math.max(0,this.xHigh-this.xLow)}height(){return Math.max(0,this.yHigh-this.yLow)}area(){return this.width()*this.height()}center(){return{x:(this.xLow+this.xHigh)/2,y:(this.yLow+this.yHigh)/2}}corner(t){let e=this.toArray();return{x:e[0+(1&t)<<1],y:e[1+(2&t)]}}intersects(t){return!(!t||t.isEmpty()||this.isEmpty())&&(this.xLow<=t.xHigh&&this.xHigh>=t.xLow&&this.yLow<=t.yHigh&&this.yHigh>=t.yLow)}intersection(t){return this.intersects(t)?new i({xLow:Math.max(this.xLow,t.xLow),yLow:Math.max(this.yLow,t.yLow),xHigh:Math.min(this.xHigh,t.xHigh),yHigh:Math.min(this.yHigh,t.yHigh)}):null}clone(){return new i({xLow:this.xLow,yLow:this.yLow,xHigh:this.xHigh,yHigh:this.yHigh})}containsPoint(t,e=0){return!this.isEmpty()&&(t.x>=this.xLow-e&&t.x<=this.xHigh+e&&t.y>=this.yLow-e&&t.y<=this.yHigh+e)}print(){console.log("BOX="+this.xLow.toFixed(2)+", "+this.yLow.toFixed(2)+", "+this.xHigh.toFixed(2)+", "+this.yHigh.toFixed(2))}}class s{constructor(t){Object.assign(this,{x:0,y:0,z:1,a:0,t:0}),this.t||(this.t=performance.now()),"object"==typeof t&&Object.assign(this,t)}copy(){let t=new s;return Object.assign(t,this),t}apply(t,e){let i=s.rotate(t,e,this.a);return{x:i.x*this.z+this.x,y:i.y*this.z+this.y}}inverse(){let t=s.rotate(this.x/this.z,this.y/this.z,-this.a);return new s({x:-t.x,y:-t.y,z:1/this.z,a:-this.a,t:this.t})}static normalizeAngle(t){for(;t>360;)t-=360;for(;t<0;)t+=360;return t}static rotate(t,e,i){return i=Math.PI*(i/180),{x:Math.cos(i)*t-Math.sin(i)*e,y:Math.sin(i)*t+Math.cos(i)*e}}compose(t){let e=this.copy(),i=t;e.z*=i.z,e.a+=i.a;var n=s.rotate(e.x,e.y,i.a);return e.x=n.x*i.z+i.x,e.y=n.y*i.z+i.y,e}transformBox(t){let e=new i;for(let i=0;i<4;i++){let s=t.corner(i),n=this.apply(s.x,s.y);e.mergePoint(n)}return e}getInverseBox(t){let e=this.inverse(),s=[{x:t.x,y:t.y},{x:t.x+t.dx,y:t.y},{x:t.x,y:t.y+t.dy},{x:t.x+t.dx,y:t.y+t.dy}],n=new i;for(let i of s){let s=e.apply(i.x-t.w/2,-i.y+t.h/2);n.mergePoint(s)}return n}isAtTarget(t){return t>=this.t}static interpolate(t,e,i,n){console.assert(!isNaN(t.x)),console.assert(!isNaN(e.x));const r=new s;let o=e.t-t.t;if(i<t.t)Object.assign(r,t),r.isComplete=!1;else if(i>e.t||o<.001)Object.assign(r,e),r.isComplete=!1;else{let s=(i-t.t)/o;switch(n){case"ease-out":s=1-Math.pow(1-s,2);break;case"ease-in-out":s=s<.5?2*s*s:1-Math.pow(-2*s+2,2)/2}let a=1-s;r.x=a*t.x+s*e.x,r.y=a*t.y+s*e.y,r.z=a*t.z+s*e.z,r.a=a*t.a+s*e.a,r.isComplete=!1}return r.t=i,r}projectionMatrix(t){let e=this.z,i=2/t.dx,s=2/t.dy,n=i*this.x+2/t.dx*(t.w/2-t.x)-1,r=s*this.y+2/t.dy*(t.h/2-t.y)-1,o=Math.PI*this.a/180;return[Math.cos(o)*i*e,Math.sin(o)*s*e,0,0,-Math.sin(o)*i*e,Math.cos(o)*s*e,0,0,0,0,1,0,n,r,0,1]}sceneToViewportCoords(t,e){return[e[0]*this.z+this.x-t.x+t.w/2,e[1]*this.z-this.y+t.y+t.h/2]}viewportToSceneCoords(t,e){return[(e[0]+t.x-t.w/2-this.x)/this.z,(e[1]-t.y-t.h/2+this.y)/this.z]}print(t="",e=0){const i=e;console.log(t+" x:"+this.x.toFixed(i)+", y:"+this.y.toFixed(i)+", z:"+this.z.toFixed(i)+", a:"+this.a.toFixed(i)+", t:"+this.t.toFixed(i))}}function n(t,...e){t.prototype.allSignals??=[],t.prototype.allSignals=[...t.prototype.allSignals,...e],t.prototype.initSignals=function(){this.signals??=Object.fromEntries(this.allSignals.map((t=>[t,[]])))},t.prototype.addEvent=function(t,e){this.signals?.hasOwnProperty(t)||this.initSignals(),this.signals[t].push(e)},t.prototype.once=function(t,e){if(!e||"function"!=typeof e)return void console.error("Callback must be a function");const i=(...s)=>{this.removeEvent(t,i),e.apply(this,s)};this.addEvent(t,i)},t.prototype.removeEvent=function(t,e){if(!this.signals)return this.initSignals(),!1;if(!this.signals[t])return!1;if(void 0===e){const e=this.signals[t].length>0;return this.signals[t]=[],e}const i=this.signals[t].length;return this.signals[t]=this.signals[t].filter((t=>t!==e)),i>this.signals[t].length},t.prototype.emit=function(t,...e){this.signals||this.initSignals();const i=[...this.signals[t]];for(let t of i)t(...e)}}class r{constructor(){Object.assign(this,{index:null,bbox:null,level:null,x:null,y:null,w:null,h:null,start:null,end:null,tex:[],missing:null,time:null,priority:null,size:null})}}class o{static fromViewportToCanvasHtml(t,e,i){const s=this.getViewport(e,i);let n=this.invertY(t,s);return i?this.scale(n,1/window.devicePixelRatio):n}static fromCanvasHtmlToViewport(t,e,i){let s=i?this.scale(t,window.devicePixelRatio):t;const n=this.getViewport(e,i);return this.invertY(s,n)}static fromViewportToLayer(t,e,i,s){const n=this.getCurrentTransform(e,s).inverse(),r=i.inverse();return this.getFromViewportToCenterTransform(e,s).compose(n.compose(r)).apply(t.x,t.y)}static fromLayerToViewport(t,e,i,s){return this.getFromLayerToViewportTransform(e,i,s).apply(t.x,t.y)}static fromLayerToCenter(t,e,i,s){const n=this.getCurrentTransform(e,s);return i.compose(n).apply(t.x,t.y)}static fromLayerToImage(t,e){let i={x:t.x+e.w/2,y:t.y+e.h/2};return this.invertY(i,e)}static fromCanvasHtmlToScene(t,e,i){let s=this.fromCanvasHtmlToViewport(t,e,i);const n=this.getFromViewportToCenterTransform(e,i),r=this.getCurrentTransform(e,i).inverse();return n.compose(r).apply(s.x,s.y)}static fromSceneToCanvasHtml(t,e,i){let s=this.fromSceneToViewport(t,e,i);return this.fromViewportToCanvasHtml(s,e,i)}static fromSceneToViewport(t,e,i){const s=this.getFromViewportToCenterTransform(e,i).inverse();return this.getCurrentTransform(e,i).compose(s).apply(t.x,t.y)}static fromSceneToViewportNoCamera(t,e,i){const s=this.getFromViewportToCenterTransformNoCamera(i).inverse();return e.compose(s).apply(t.x,t.y)}static fromViewportToScene(t,e,i){const s=this.getFromViewportToCenterTransform(e,i),n=this.getCurrentTransform(e,i).inverse();return s.compose(n).apply(t.x,t.y)}static fromViewportToSceneNoCamera(t,e,i){const s=this.getFromViewportToCenterTransformNoCamera(i),n=e.inverse();return s.compose(n).apply(t.x,t.y)}static fromCanvasHtmlToImage(t,e,i,s,n){let r=this.fromCanvasHtmlToScene(t,e,n);return r=i.inverse().apply(r.x,r.y),r=this.fromLayerToImage(r,s),r}static fromViewportBoxToImageBox(t,e,n,r,a){let l=new s({x:-n.w/2,y:-n.h/2}),h=e.inverse(),c=r.inverse(),d=new s({x:a.w/2,y:a.h/2}),u=l.compose(h.compose(c.compose(d))),p=new i;for(let e=0;e<4;++e){let i=t.corner(e);i=u.apply(i.x,i.y),i=o.invertY(i,a),p.mergePoint(i)}return p}static fromLayerBoxToSceneBox(t,e){return e.transformBox(t)}static fromSceneBoxToLayerBox(t,e){return e.inverse().transformBox(t)}static fromLayerBoxToViewportBox(t,e,i,s){return this.getFromLayerToViewportTransform(e,i,s).transformBox(t)}static fromViewportBoxToLayerBox(t,e,i,s){return this.getFromLayerToViewportTransform(e,i,s).inverse().transformBox(t)}static getFromViewportToCenterTransform(t,e){const i=this.getViewport(t,e);return this.getFromViewportToCenterTransformNoCamera(i)}static getFromViewportToCenterTransformNoCamera(t){return new s({x:t.x-t.w/2,y:t.y-t.h/2,z:1,a:0,t:0})}static reflectY(t){return new s({x:t.x,y:-t.y,z:t.z,a:t.a,t:t.t})}static getFromLayerToViewportTransform(t,e,i){const s=this.getCurrentTransform(t,i),n=this.getFromViewportToCenterTransform(t,i).inverse();return e.compose(s.compose(n))}static getFromLayerToViewportTransformNoCamera(t,e,i){const s=this.getFromViewportToCenterTransformNoCamera(e).inverse();return i.compose(t.compose(s))}static scale(t,e){return{x:t.x*e,y:t.y*e}}static invertY(t,e){return{x:t.x,y:e.h-t.y}}static getViewport(t,e){return e?t.glViewport():t.viewport}static getCurrentTransform(t,e){return e?t.getGlCurrentTransform(performance.now()):t.getCurrentTransform(performance.now())}}class a{constructor(t,e,i){if("image"!=e){if(e in this.types)return this.types[e](t,e,i);if(null==e)return;throw"Layout type: "+e+" unknown, or module not loaded"}this.setDefaults(e),this.init(t,e,i)}getTileSize(){return[this.width,this.height]}setDefaults(t){Object.assign(this,{type:t,width:0,height:0,suffix:"jpg",urls:[],status:null,subdomains:"abc"})}init(t,e,i){i&&Object.assign(this,i),"string"==typeof t&&this.setUrls([t])}setUrls(t){this.urls=t,this.getTileURL=(t,e)=>this.urls[t],this.status="ready",this.emit("ready")}imageUrl(t,e){return t.substring(0,t.lastIndexOf("/")+1)+e+".jpg"}getTileURL(t,e){throw Error("Layout not defined or ready.")}boundingBox(){return new i({xLow:-this.width/2,yLow:-this.height/2,xHigh:this.width/2,yHigh:this.height/2})}tileCoords(t){let e=this.width,i=this.height;var s=new Float32Array([0,1,0,0,1,0,1,1]);return{coords:new Float32Array([-e/2,-i/2,0,-e/2,i/2,0,e/2,i/2,0,e/2,-i/2,0]),tcoords:s}}newTile(t){let e=new r;return e.index=t,e}needed(t,e,i,s,n,r,o=8){let a=r.get(0)||this.newTile(0);return a.time=performance.now(),a.priority=10,null===a.missing?[a]:[]}available(t,e,i,s,n,r){let o={};return r.has(0)&&0==r.get(0).missing&&(o[0]=r.get(0)),o}getViewportBox(t,e,s){const n=new i({xLow:t.x,yLow:t.y,xHigh:t.x+t.dx,yHigh:t.y+t.dy});return o.fromViewportBoxToImageBox(n,e,t,s,{w:this.width,h:this.height})}}a.prototype.types={},n(a,"ready","updateSize");class l{static#t;#e=[];#i;#s=0;#n=0;#r;#o;#a=null;#l;#h;#c=0;constructor(t={}){if(l.#t)return l.#t;const e={capacity:536870912,maxRequest:6,maxRequestsRate:0,maxPrefetch:8388608,...t};this.#i=e.capacity,this.#r=e.maxRequest,this.#o=e.maxRequestsRate,this.#h=e.maxPrefetch,this.#l=performance.now(),l.#t=this}static getInstance(t){if(l.#t){if(t){const e=l.#t;void 0!==t.capacity&&(e.#i=t.capacity),void 0!==t.maxRequest&&(e.#r=t.maxRequest),void 0!==t.maxRequestsRate&&(e.#o=t.maxRequestsRate),void 0!==t.maxPrefetch&&(e.#h=t.maxPrefetch)}}else new l(t);return l.#t}setCandidates(t){this.#e.includes(t)||this.#e.push(t),Promise.resolve().then((()=>this.update()))}#d(){if(this.#n>=this.#r)return!0;if(0===this.#o)return!1;const t=performance.now(),e=1e3/this.#o,i=t-this.#l;return!(i>e)&&(this.#a||(this.#a=setTimeout((()=>{this.#a=null,this.update()}),e-i+10)),!0)}update(){if(this.#d())return;const t=this.#u();if(t){for(;this.#s>this.#i;){const e=this.#p();if(!e){console.warn("Cache management issue: No tiles available for removal");break}if(!(e.tile.time<t.tile.time))return;this.#m(e.layer,e.tile)}t.layer.queue.shift(),this.#l=performance.now(),this.#f(t.layer,t.tile)}}#u(){let t=null;for(const e of this.#e){for(;e.queue.length>0&&e.tiles.has(e.queue[0].index);)e.queue.shift();if(!e.queue.length)continue;const i=e.queue[0];(!t||i.time>t.tile.time+1||i.priority>t.tile.priority)&&(t={layer:e,tile:i})}return t}#p(){let t=null;for(const e of this.#e)for(const i of e.tiles.values())0===i.missing&&(!t||i.time<t.tile.time||i.time===t.tile.time&&i.priority<t.tile.priority)&&(t={layer:e,tile:i});return t}#f(t,e){this.#n++,(async()=>{try{await t.loadTile(e,(t=>{this.#s+=t,this.#n--,this.update()}))}catch(t){console.error("Error loading tile:",t),this.#n--,this.update()}})()}#m(t,e){this.#s-=e.size,t.dropTile(e)}flushLayer(t){if(this.#e.includes(t))for(const e of t.tiles.values())this.#m(t,e)}getStats(){return{capacity:this.#i,used:this.#s,usedPercentage:this.#s/this.#i*100,activeRequests:this.#n,layers:this.#e.length}}}class h{constructor(t){if((t=Object.assign({isLinear:!1,isSrgbSimplified:!0},t)).type){let e=t.type;if(delete t.type,e in this.types)return this.types[e](t);throw"Layer type: "+e+" module has not been loaded"}this.init(t)}derive(t={}){const e={layout:this.layout,sourceLayer:this,label:t.label||this.label,zindex:void 0!==t.zindex?t.zindex:this.zindex+1,visible:void 0!==t.visible?t.visible:this.visible,transform:t.transform||this.transform.copy(),shaders:t.shaders||Object.assign({},this.shaders),mipmapBias:t.mipmapBias||this.mipmapBias,pixelSize:t.pixelSize||this.pixelSize,debug:void 0!==t.debug?t.debug:this.debug},i=new h(e);return t.defaultShader&&e.shaders[t.defaultShader]&&i.setShader(t.defaultShader),i}init(t){if(Object.assign(this,{transform:new s,viewport:null,debug:!1,visible:!0,zindex:0,overlay:!1,rasters:[],layers:[],controls:{},controllers:[],shaders:{},layout:"image",shader:null,gl:null,width:0,height:0,prefetchBorder:1,mipmapBias:.4,pixelSize:0,tiles:new Map,queue:[],requested:new Map}),Object.assign(this,t),this.sourceLayer&&(this.tiles=this.sourceLayer.tiles),this.transform=new s(this.transform),"string"==typeof this.layout){let t={width:this.width,height:this.height};this.server&&(t.server=this.server),this.setLayout(new a(null,this.layout,t))}else this.setLayout(this.layout)}setViewport(t){this.viewport=t,this.emit("update")}addShader(t,e){if(t in this.shaders)throw new Error(`Shader with id '${t}' already exists`);return e.isLinear=this.isLinear,e.isSrgbSimplified=this.isSrgbSimplified,this.shaders[t]=e,1!==Object.keys(this.shaders).length||this.shader||this.setShader(t),this}removeShader(t){if(!(t in this.shaders))throw new Error(`Shader with id '${t}' does not exist`);const e=this.shader===this.shaders[t];if(delete this.shaders[t],e){this.shader=null;const t=Object.keys(this.shaders);t.length>0&&this.setShader(t[0]),this.emit("update")}return this}addShaderFilter(t){if(!this.shader)throw"Shader not implemented";this.shader.addFilter(t)}removeShaderFilter(t){if(!this.shader)throw"Shader not implemented";this.shader.removeFilter(t)}clearShaderFilters(){if(!this.shader)throw"Shader not implemented";this.shader.clearFilters()}setState(t,e,i="linear"){if("controls"in t)for(const[s,n]of Object.entries(t.controls))this.setControl(s,n,e,i);"mode"in t&&t.mode&&this.setMode(t.mode)}getState(t=null){const e={controls:{}};for(const[i,s]of Object.entries(this.controls))(!t||"controls"in t&&i in t.controls)&&(e.controls[i]=s.current.value);return t&&!("mode"in t)||this.getMode()&&(e.mode=this.getMode()),e}setLayout(t){this.layout=t;let e=()=>{this.status="ready",this.setupTiles(),this.emit("ready"),this.emit("update")};"ready"==t.status?e():t.addEvent("ready",e),this.layout.addEvent("updateSize",(()=>{this.shader&&this.shader.setTileSize(this.layout.getTileSize()),this.emit("updateSize")}))}setTransform(t){this.transform=t,this.emit("updateSize")}setShader(t){if(!t in this.shaders)throw"Unknown shader: "+t;this.shader=this.shaders[t],this.shader.isLinear=this.isLinear,this.shader.isSrgbSimplified=this.isSrgbSimplified,this.setupTiles(),this.shader.addEvent("update",(()=>{this.emit("update")}))}getMode(){return this.shader?this.shader.mode:null}getModes(){return this.shader?this.shader.modes:[]}setMode(t){this.shader.setMode(t),this.emit("update")}setVisible(t){this.visible=t,this.previouslyNeeded=null,this.emit("update")}setZindex(t){this.zindex=t,this.emit("update")}static computeLayersMinScale(t,e){if(null==t||null==t)return console.log("ASKING SCALE INFO ON NO LAYERS"),1;let i=1;for(let s of Object.values(t))if(!e||s.visible){let t=s.scale();i=Math.min(i,t)}return i}scale(){return this.transform.z}pixelSizePerMM(){return this.pixelSize*this.transform.z}boundingBox(){let t=this.layout.boundingBox();return null!=this.transform&&null!=this.transform&&(t=this.transform.transformBox(t)),t}static computeLayersBBox(t,e=!1){let s=new i,n=0;for(const i in t){const r=t[i];if(!r.visible&&e)continue;const o=r.boundingBox();o&&!o.isEmpty()&&(s.mergeBox(o),n++)}return 0===n||s.isEmpty()?null:s}getControl(t){let e=this.controls[t]?this.controls[t]:null;if(e){let t=performance.now();this.interpolateControl(e,t)}return e}addControl(t,e){if(this.controls[t])throw new Error('Control "$name" already exist!');let i=performance.now();this.controls[t]={source:{value:e,t:i},target:{value:e,t:i},current:{value:e,t:i},easing:"linear"}}setControl(t,e,i,s="linear"){let n=performance.now(),r=this.controls[t];this.interpolateControl(r,n),r.source.value=[...r.current.value],r.source.t=n,r.target.value=[...e],r.target.t=n+i,r.easing=s,this.emit("update")}interpolateControls(){let t=performance.now(),e=!0;for(let i of Object.values(this.controls))e=this.interpolateControl(i,t)&&e;return e}interpolateControl(t,e){let i=t.source,s=t.target,n=t.current;if(n.t=e,e<i.t)return n.value=[...i.value],!1;if(e>s.t-1e-4){let t=n.value.every(((t,e)=>t===s.value[e]));return n.value=[...s.value],t}let r=s.t-i.t,o=(e-i.t)/r;switch(t.easing){case"ease-out":o=1-Math.pow(1-o,2);break;case"ease-in-out":o=o<.5?2*o*o:1-Math.pow(-2*o+2,2)/2}let a=1-o;n.value=[];for(let t=0;t<i.value.length;t++)n.value[t]=a*i.value[t]+o*s.value[t];return!1}dropTile(t){for(let e=0;e<t.tex.length;e++)t.tex[e]&&this.gl.deleteTexture(t.tex[e]);this.tiles.delete(t.index)}clear(){this.ibuffer=this.vbuffer=null,l.flushLayer(this),this.tiles=new Map,this.setupTiles(),this.queue=[],this.previouslyNeeded=!1}draw(t,e){if("ready"!=this.status)return!0;if(!this.shader)throw"Shader not specified!";let i=this.interpolateControls(),s=e;this.viewport&&(e=this.viewport,this.gl.viewport(e.x,e.y,e.dx,e.dy)),this.prepareWebGL();let n=this.layout.available(e,t,this.transform,0,this.mipmapBias,this.tiles),r=(t=this.transform.compose(t)).projectionMatrix(e);this.gl.uniformMatrix4fv(this.shader.matrixlocation,this.gl.FALSE,r),this.updateAllTileBuffers(n);let o=this.shader.samplers.length;for(const t of this.shader.filters)for(let e=0;e<t.samplers.length;e++)this.gl.uniform1i(t.samplers[e].location,o),this.gl.activeTexture(this.gl.TEXTURE0+o),this.gl.bindTexture(this.gl.TEXTURE_2D,t.samplers[e].tex),o++;let a=0;for(let t of Object.values(n))this.drawTile(t,a),++a;return this.vieport&&this.gl.viewport(s.x,s.y,s.dx,s.dy),i}drawTile(t,e){if(0!=t.missing)throw"Attempt to draw tile still missing textures";let i=this.gl;for(var s=0;s<this.shader.samplers.length;s++){let e=this.shader.samplers[s].id;i.uniform1i(this.shader.samplers[s].location,s),i.activeTexture(i.TEXTURE0+s),i.bindTexture(i.TEXTURE_2D,t.tex[e])}const n=this.getTileByteOffset(e);i.drawElements(i.TRIANGLES,6,i.UNSIGNED_SHORT,n)}getTileByteOffset(t){return 6*t*2}updateTileBuffers(t,e){let i=this.gl;i.bindBuffer(i.ARRAY_BUFFER,this.vbuffer),i.bufferData(i.ARRAY_BUFFER,t,i.STATIC_DRAW),i.vertexAttribPointer(this.shader.coordattrib,3,i.FLOAT,!1,0,0),i.enableVertexAttribArray(this.shader.coordattrib),i.bindBuffer(i.ARRAY_BUFFER,this.tbuffer),i.bufferData(i.ARRAY_BUFFER,e,i.STATIC_DRAW),i.vertexAttribPointer(this.shader.texattrib,2,i.FLOAT,!1,0,0),i.enableVertexAttribArray(this.shader.texattrib)}updateAllTileBuffers(t){let e=this.gl,i=Object.values(t).length;if(0==i)return;const s=new Uint16Array(6*i),n=new Float32Array(12*i),r=new Float32Array(8*i);let o=0;for(let e of Object.values(t)){let t=this.layout.tileCoords(e);n.set(t.coords,12*o),r.set(t.tcoords,8*o);const i=4*o;e.indexBufferByteOffset=2*o*6,s.set([i+3,i+2,i+1,i+3,i+1,i+0],6*o),++o}e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.ibuffer),e.bufferData(e.ELEMENT_ARRAY_BUFFER,s,e.STATIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,this.vbuffer),e.bufferData(e.ARRAY_BUFFER,n,e.STATIC_DRAW),e.vertexAttribPointer(this.shader.coordattrib,3,e.FLOAT,!1,0,0),e.enableVertexAttribArray(this.shader.coordattrib),e.bindBuffer(e.ARRAY_BUFFER,this.tbuffer),e.bufferData(e.ARRAY_BUFFER,r,e.STATIC_DRAW),e.vertexAttribPointer(this.shader.texattrib,2,e.FLOAT,!1,0,0),e.enableVertexAttribArray(this.shader.texattrib)}setupTiles(){if(this.shader&&this.layout&&"ready"==this.layout.status)for(let t of this.tiles){t.missing=this.shader.samplers.length;for(let e of this.shader.samplers)t.tex[e.id]&&t.missing--}}prepareWebGL(){let t=this.gl;this.ibuffer||(this.ibuffer=t.createBuffer(),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.ibuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,new Uint16Array([3,2,1,3,1,0]),t.STATIC_DRAW),this.vbuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.vbuffer),t.bufferData(t.ARRAY_BUFFER,new Float32Array([0,0,0,0,1,0,1,1,0,1,0,0]),t.STATIC_DRAW),this.tbuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.tbuffer),t.bufferData(t.ARRAY_BUFFER,new Float32Array([0,0,0,1,1,1,1,0]),t.STATIC_DRAW)),this.shader.needsUpdate&&this.shader.createProgram(t),t.useProgram(this.shader.program),this.shader.updateUniforms(t)}sameNeeded(t,e){if(t.level!=e.level)return!1;for(let i of["xLow","xHigh","yLow","yHigh"])if(t.pyramid[t.level][i]!=e.pyramid[t.level][i])return!1;return!0}prefetch(t,e){if(this.viewport&&(e=this.viewport),0!=this.layers.length)for(let i of this.layers)i.prefetch(t,e);if(0!=this.rasters.length&&"ready"==this.status){if("object"!=typeof this.layout)throw"AH!";this.queue=this.layout.needed(e,t,this.transform,this.prefetchBorder,this.mipmapBias,this.tiles),l.getInstance().setCandidates(this)}}async loadTile(t,e){if(this.tiles.has(t.index)){e(new Error(`Tile with index ${t.index} already exists in cache`))}else{if(this.requested.has(t.index))return console.warn(`Duplicate tile request for index ${t.index}`),void e(new Error("Duplicate tile request"));this.tiles.set(t.index,t),this.requested.set(t.index,!0),t.size=0,t.missing=this.shader.samplers.length,t.tex=[];try{"itarzoom"===this.layout.type?await this._loadInterleaved(t,e):await this._loadParallel(t,e)}catch(i){this.requested.delete(t.index),this.tiles.delete(t.index),console.error(`Error loading tile ${t.index}:`,i),e(i)}}}async _loadInterleaved(t,e){t.url=this.layout.getTileURL(null,t);const i={};t.end&&(i.headers={range:`bytes=${t.start}-${t.end}`,"Accept-Encoding":"identity"});const s=await fetch(t.url,i);if(!s.ok)throw new Error(`Failed loading ${t.url}: ${s.statusText} (${s.status})`);const n=await s.blob();for(let e=0;e<this.shader.samplers.length;e++){const i=this.shader.samplers[e],s=this.rasters[i.id],r=n.slice(t.offsets[e],t.offsets[e+1]),o=await s.blobToImage(r,this.gl),a=s.loadTexture(this.gl,o),l=o.width*o.height*this.getPixelSize(i.id);t.size+=l,t.tex[i.id]=a,t.w=o.width,t.h=o.height}t.missing=0,this.emit("update"),this.requested.delete(t.index),e&&e(null,t.size)}async _loadParallel(t,e){let i=[];const s=this.shader.samplers.map((async e=>{try{const i=this.rasters[e.id];t.url=this.layout.getTileURL(e.id,t);const[s,n]=await i.loadImage(t,this.gl);return"image"===this.layout.type&&(this.layout.width=i.width,this.layout.height=i.height,this.layout.emit("updateSize")),t.size+=n,t.tex[e.id]=s,t.missing--,t.missing<=0&&(this.emit("update"),0===this.requested.size&&this.emit("loaded")),{success:!0,size:n}}catch(t){return i.push(t),{success:!1,error:t}}}));await Promise.allSettled(s),this.requested.delete(t.index),i.length>0?e(i[0]):e(null,t.size)}getPixelSize(t){let e=3;const i=this.rasters[t];if(i&&i.format)switch(i.format){case"vec4":e=4;break;case"vec3":e=3;break;case"float":e=1}return e}getPixelValues(t,e){if(!this.shader)throw new Error("WebGL resources not initialized");if(!this.gl)return console.log("Not a GL Layer"),null;if(t=Math.floor(t),e=Math.floor(e),t<0||t>=this.width||e<0||e>=this.height)return console.warn(`Coordinates (${t}, ${e}) outside image bounds (${this.width}x${this.height})`),[];const i=Array(this.rasters.length).fill(null);try{const s=this.gl.createFramebuffer();if(this.gl.bindFramebuffer(this.gl.FRAMEBUFFER,s),"image"===this.layout.type||"itarzoom"===this.layout.type){const s=this.tiles.get(0);if(s&&0===s.missing)for(let n=0;n<this.rasters.length;n++)if(n<s.tex.length&&s.tex[n]&&(this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER,this.gl.COLOR_ATTACHMENT0,this.gl.TEXTURE_2D,s.tex[n],0),this.gl.checkFramebufferStatus(this.gl.FRAMEBUFFER)===this.gl.FRAMEBUFFER_COMPLETE)){const s=new Uint8Array(4);this.gl.readPixels(t,e,1,1,this.gl.RGBA,this.gl.UNSIGNED_BYTE,s),i[n]=s}}else{let s=!1;for(let n=this.layout.nlevels-1;n>=0;n--){const r=this.layout.getTileSize(),o=Math.pow(2,this.layout.nlevels-1-n),a=r[0]*o,l=r[1]*o,h=Math.floor(t/a),c=Math.floor(e/l),d=this.layout.index(n,h,c);if(this.tiles.has(d)){const n=this.tiles.get(d);if(0===n.missing){const o=t-h*a,d=e-c*l,u=n.w||r[0],p=n.h||r[1],m=Math.min(Math.floor(o*u/a),u-1),f=Math.min(Math.floor(d*p/l),p-1);let g=!1;for(let t=0;t<this.rasters.length;t++)if(null===i[t]&&t<n.tex.length&&n.tex[t]&&(this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER,this.gl.COLOR_ATTACHMENT0,this.gl.TEXTURE_2D,n.tex[t],0),this.gl.checkFramebufferStatus(this.gl.FRAMEBUFFER)===this.gl.FRAMEBUFFER_COMPLETE)){const e=new Uint8Array(4);this.gl.readPixels(m,f,1,1,this.gl.RGBA,this.gl.UNSIGNED_BYTE,e),i[t]=e,g=!0}if(g&&(s=!0,i.every((t=>null!==t))))break}}}s||console.warn(`No suitable tile found for coordinates (${t}, ${e})`)}this.gl.bindFramebuffer(this.gl.FRAMEBUFFER,null),this.gl.deleteFramebuffer(s);for(let t=0;t<i.length;t++)null===i[t]&&(i[t]=new Uint8Array([0,0,0,255]))}catch(t){console.error("Error reading pixel data:",t)}return i}}h.prototype.types={},n(h,"ready","update","loaded","updateSize"),window.structuredClone="function"==typeof structuredClone?structuredClone:function(t){return JSON.parse(JSON.stringify(t))};class c{constructor(t,e,i,s){Object.assign(this,{canvasElement:null,preserveDrawingBuffer:!1,gl:null,overlayElement:null,camera:i,layers:{},ready:!1,targetfps:30,fps:0,timing:[16],timingLength:5,overBudget:0,srgb:!0,isSrgbSimplified:!0,stencil:!1,useOffscreenFramebuffer:!0,offscreenFramebuffer:null,offscreenTexture:null,offscreenRenderbuffer:null,_renderingToOffscreen:!1,signals:{update:[],updateSize:[],ready:[]},splitViewport:!1,leftLayers:[],rightLayers:[]}),Object.assign(this,s),this.init(t,e);for(let t in this.layers)this.addLayer(t,new h(this.layers[t]));this.camera.addEvent("update",(()=>this.emit("update")))}addRenderTiming(t){for(this.timing.push(t);this.timing.length>this.timingLength;)this.timing.shift();this.overBudget=this.timing.filter((t=>t>1e3/this.targetfps)).length/this.timingLength,this.fps=1e3/(this.timing.reduce(((t,e)=>t+e),0)/this.timing.length)}init(t,e){if(!t)throw"Missing element parameter";if("string"==typeof t&&!(t=document.querySelector(t)))throw"Could not find dom element.";if(!e)throw"Missing element parameter";if("string"==typeof e&&!(e=document.querySelector(e)))throw"Could not find dom element.";if(!t.tagName)throw"Element is not a DOM element";if("CANVAS"!=t.tagName)throw"Element is not a canvas element";this.canvasElement=t,this.overlayElement=e;const i={antialias:!1,depth:!1,stencil:this.stencil,preserveDrawingBuffer:this.preserveDrawingBuffer,colorSpace:this.srgb?"srgb":"display-p3"};if(this.gl=this.gl||t.getContext("webgl2",i),!this.gl)throw new Error("Could not create a WebGL 2.0 context");this.useOffscreenFramebuffer&&this.setupOffscreenFramebuffer(),t.addEventListener("webglcontextlost",(t=>{console.log("Context lost."),t.preventDefault()}),!1),t.addEventListener("webglcontextrestored",(()=>{this.restoreWebGL()}),!1),document.addEventListener("visibilitychange",(t=>{this.gl.isContextLost()&&this.restoreWebGL()})),this.hasFloatRender=!!this.gl.getExtension("EXT_color_buffer_float"),this.hasLinearFloat=!!this.gl.getExtension("OES_texture_float_linear"),console.log("Support for rendering to float textures:",this.hasFloatRender),console.log("Support for linear filtering on float textures:",this.hasLinearFloat)}setupOffscreenFramebuffer(){const t=this.gl;this.offscreenFramebuffer=t.createFramebuffer(),t.bindFramebuffer(t.FRAMEBUFFER,this.offscreenFramebuffer),this.offscreenTexture=t.createTexture(),t.bindTexture(t.TEXTURE_2D,this.offscreenTexture);const e=this.canvasElement.width,i=this.canvasElement.height;t.texImage2D(t.TEXTURE_2D,0,t.RGBA,e,i,0,t.RGBA,t.UNSIGNED_BYTE,null),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),this.stencil&&(this.offscreenRenderbuffer=t.createRenderbuffer(),t.bindRenderbuffer(t.RENDERBUFFER,this.offscreenRenderbuffer),t.renderbufferStorage(t.RENDERBUFFER,t.DEPTH_STENCIL,e,i),t.framebufferRenderbuffer(t.FRAMEBUFFER,t.DEPTH_STENCIL_ATTACHMENT,t.RENDERBUFFER,this.offscreenRenderbuffer)),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,this.offscreenTexture,0);const s=t.checkFramebufferStatus(t.FRAMEBUFFER);s!==t.FRAMEBUFFER_COMPLETE&&(console.error("Framebuffer not complete. Status:",s),this.useOffscreenFramebuffer=!1),t.bindFramebuffer(t.FRAMEBUFFER,null),t.bindTexture(t.TEXTURE_2D,null),this.stencil&&t.bindRenderbuffer(t.RENDERBUFFER,null)}resizeOffscreenFramebuffer(){if(!this.useOffscreenFramebuffer||!this.offscreenFramebuffer)return;const t=this.gl,e=this.canvasElement.width,i=this.canvasElement.height;t.bindTexture(t.TEXTURE_2D,this.offscreenTexture),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,e,i,0,t.RGBA,t.UNSIGNED_BYTE,null),this.stencil&&this.offscreenRenderbuffer&&(t.bindRenderbuffer(t.RENDERBUFFER,this.offscreenRenderbuffer),t.renderbufferStorage(t.RENDERBUFFER,t.DEPTH_STENCIL,e,i)),t.bindTexture(t.TEXTURE_2D,null),this.stencil&&t.bindRenderbuffer(t.RENDERBUFFER,null)}getActiveFramebuffer(){return this.useOffscreenFramebuffer&&this._renderingToOffscreen?this.offscreenFramebuffer:null}setActiveFramebuffer(t){this.gl.bindFramebuffer(this.gl.FRAMEBUFFER,t),this._renderingToOffscreen=t===this.offscreenFramebuffer}setState(t,e,i="linear"){if(t&&"object"==typeof t){if("camera"in t){const s=t.camera;this.camera.setPosition(e,s.x,s.y,s.z,s.a,i)}if("layers"in t)for(const[s,n]of Object.entries(t.layers))if(s in this.layers){this.layers[s].setState(n,e,i)}}}getState(t=null){let e={};if(!t||t.camera){let t=performance.now(),i=this.camera.getCurrentTransform(t);e.camera={x:i.x,y:i.y,z:i.z,a:i.a}}e.layers={};for(let i of Object.values(this.layers)){const s=window.structuredClone(t);t&&t.layers&&Object.assign(s,t.layers[i.id]),e.layers[i.id]=i.getState(s)}return e}restoreWebGL(){let t={antialias:!1,depth:!1,stencil:this.stencil,preserveDrawingBuffer:this.preserveDrawingBuffer,colorSpace:this.srgb?"srgb":"display-p3"};this.gl=this.gl||this.canvasElement.getContext("webgl2",t),this.useOffscreenFramebuffer&&(this.offscreenFramebuffer&&this.gl.deleteFramebuffer(this.offscreenFramebuffer),this.offscreenTexture&&this.gl.deleteTexture(this.offscreenTexture),this.offscreenRenderbuffer&&this.gl.deleteRenderbuffer(this.offscreenRenderbuffer),this.setupOffscreenFramebuffer());for(let t of Object.values(this.layers))t.gl=this.gl,t.clear(),t.shader&&t.shader.restoreWebGL(this.gl);this.prefetch(),this.emit("update")}addLayer(t,e){console.assert(!(t in this.layers),"Duplicated layer id"),e.id=t,e.addEvent("ready",(()=>{Object.values(this.layers).every((t=>"ready"==t.status))&&(this.ready=!0,this.emit("ready")),this.prefetch()})),e.addEvent("update",(()=>{this.emit("update")})),e.addEvent("updateSize",(()=>{this.updateSize()})),e.gl=this.gl,e.canvas=this,e.overlayElement=this.overlayElement,e.isSrgbSimplified=this.isSrgbSimplified,this.layers[t]=e,this.prefetch()}removeLayer(t){t.clear(),delete this.layers[t.id],delete l.layers[t],this.prefetch()}updateSize(){const t=!1;let e=h.computeLayersBBox(this.layers,t),i=h.computeLayersMinScale(this.layers,t);e&&this.camera.viewport&&!e.isEmpty()&&this.camera.updateBounds(e,i),this.useOffscreenFramebuffer&&this.resizeOffscreenFramebuffer(),this.emit("updateSize")}setSplitViewport(t,e=[],i=[]){this.splitViewport=t,this.leftLayers=e,this.rightLayers=i,this.emit("update")}draw(t){let e=this.gl,i=this.camera.glViewport();this.useOffscreenFramebuffer?(e.bindFramebuffer(e.FRAMEBUFFER,this.offscreenFramebuffer),this._renderingToOffscreen=!0):this._renderingToOffscreen=!1,e.viewport(i.x,i.y,i.dx,i.dy);var s=[0,0,0,0];e.clearColor(s[0],s[1],s[2],s[3],s[4]),e.clear(e.COLOR_BUFFER_BIT),e.blendFunc(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA),e.enable(e.BLEND);let n=this.camera.getGlCurrentTransform(t);this.prefetch(n);let r=Object.values(this.layers).sort(((t,e)=>t.zindex-e.zindex)),o=!0;if(this.splitViewport){e.enable(e.SCISSOR_TEST);const t=Math.floor(i.dx/2);e.scissor(i.x,i.y,t,i.dy);for(let t of r)this.leftLayers.includes(t.id)&&(o=t.draw(n,i)&&o);e.scissor(i.x+t,i.y,i.dx-t,i.dy);for(let t of r)this.rightLayers.includes(t.id)&&(o=t.draw(n,i)&&o);e.disable(e.SCISSOR_TEST)}else for(let t of r)t.visible&&(o=t.draw(n,i)&&o);return this.useOffscreenFramebuffer&&(e.bindFramebuffer(e.FRAMEBUFFER,null),this._renderingToOffscreen=!1,this.drawOffscreenToCanvas()),o&&n.isComplete}drawOffscreenToCanvas(){const t=this.gl,e=this.camera.glViewport();if(t.viewport(e.x,e.y,e.dx,e.dy),!this._fullscreenQuadProgram){const e="#version 300 es\n\t\t\t\tin vec4 aPosition;\n\t\t\t\tin vec2 aTexCoord;\n\t\t\t\tout vec2 vTexCoord;\n\t\t\t\t\n\t\t\t\tvoid main() {\n\t\t\t\t\tgl_Position = aPosition;\n\t\t\t\t\tvTexCoord = aTexCoord;\n\t\t\t\t}\n\t\t\t";let i="#version 300 es\n\t\t\tprecision highp float;\n\t\t\tin vec2 vTexCoord;\n\t\t\tuniform sampler2D uTexture;\n\t\t\tout vec4 fragColor;";this.isSrgbSimplified?i+="\n\t\t\tvec4 linear2srgb(vec4 linear) {\n\t\t\t\treturn vec4(pow(linear.rgb, vec3(1.0/2.2)), linear.a);\n\t\t\t}":i+="\n\t\t\tvec4 linear2srgb(vec4 linear) {\n\t\t\t\tbvec3 cutoff = lessThan(linear.rgb, vec3(0.0031308));\n\t\t\t\tvec3 higher = vec3(1.055) * pow(linear.rgb, vec3(1.0/2.4)) - vec3(0.055);\n\t\t\t\tvec3 lower = linear.rgb * vec3(12.92);\n\t\t\t\treturn vec4(mix(higher, lower, cutoff), linear.a);\n\t\t\t}",i+="\n\t\tvoid main() {\n\t\t\tfragColor = texture(uTexture, vTexCoord);\n\t\t\tfragColor = linear2srgb(fragColor);\n\t\t\tfragColor = clamp(fragColor, 0.0, 1.0);\n\t\t}";const s=this._createShader(t,t.VERTEX_SHADER,e),n=this._createShader(t,t.FRAGMENT_SHADER,i);this._fullscreenQuadProgram=this._createProgram(t,s,n),this._positionLocation=t.getAttribLocation(this._fullscreenQuadProgram,"aPosition"),this._texCoordLocation=t.getAttribLocation(this._fullscreenQuadProgram,"aTexCoord"),this._textureLocation=t.getUniformLocation(this._fullscreenQuadProgram,"uTexture"),this._quadPositionBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this._quadPositionBuffer),t.bufferData(t.ARRAY_BUFFER,new Float32Array([-1,1,0,-1,-1,0,1,1,0,1,-1,0]),t.STATIC_DRAW),this._quadTexCoordBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this._quadTexCoordBuffer),t.bufferData(t.ARRAY_BUFFER,new Float32Array([0,1,0,0,1,1,1,0]),t.STATIC_DRAW),this._quadVAO=t.createVertexArray(),t.bindVertexArray(this._quadVAO),t.bindBuffer(t.ARRAY_BUFFER,this._quadPositionBuffer),t.enableVertexAttribArray(this._positionLocation),t.vertexAttribPointer(this._positionLocation,3,t.FLOAT,!1,0,0),t.bindBuffer(t.ARRAY_BUFFER,this._quadTexCoordBuffer),t.enableVertexAttribArray(this._texCoordLocation),t.vertexAttribPointer(this._texCoordLocation,2,t.FLOAT,!1,0,0),t.bindVertexArray(null)}t.clearColor(0,0,0,0),t.clear(t.COLOR_BUFFER_BIT),t.useProgram(this._fullscreenQuadProgram),t.bindVertexArray(this._quadVAO),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.offscreenTexture),t.uniform1i(this._textureLocation,0),t.drawArrays(t.TRIANGLE_STRIP,0,4),t.bindVertexArray(null),t.bindTexture(t.TEXTURE_2D,null)}_createShader(t,e,i){const s=t.createShader(e);return t.shaderSource(s,i),t.compileShader(s),t.getShaderParameter(s,t.COMPILE_STATUS)?s:(console.error("Shader compilation error:",t.getShaderInfoLog(s)),t.deleteShader(s),null)}_createProgram(t,e,i){const s=t.createProgram();return t.attachShader(s,e),t.attachShader(s,i),t.linkProgram(s),t.getProgramParameter(s,t.LINK_STATUS)?s:(console.error("Program linking error:",t.getProgramInfoLog(s)),t.deleteProgram(s),null)}prefetch(t){t||(t=this.camera.getGlCurrentTransform(performance.now()));for(let e in this.layers){let i=this.layers[e];i.visible&&"ready"==i.status&&i.prefetch(t,this.camera.glViewport())}}dispose(){const t=this.gl;this.useOffscreenFramebuffer&&(this.offscreenFramebuffer&&(t.deleteFramebuffer(this.offscreenFramebuffer),this.offscreenFramebuffer=null),this.offscreenTexture&&(t.deleteTexture(this.offscreenTexture),this.offscreenTexture=null),this.offscreenRenderbuffer&&(t.deleteRenderbuffer(this.offscreenRenderbuffer),this.offscreenRenderbuffer=null)),this._fullscreenQuadProgram&&(t.deleteProgram(this._fullscreenQuadProgram),this._fullscreenQuadProgram=null),this._quadVAO&&(t.deleteVertexArray(this._quadVAO),this._quadVAO=null),this._quadPositionBuffer&&(t.deleteBuffer(this._quadPositionBuffer),this._quadPositionBuffer=null),this._quadTexCoordBuffer&&(t.deleteBuffer(this._quadTexCoordBuffer),this._quadTexCoordBuffer=null);for(const t in this.layers)this.removeLayer(this.layers[t])}}n(c,"update","updateSize","ready");class d{constructor(t){Object.assign(this,{viewport:null,bounded:!0,minScreenFraction:1,maxFixedZoom:2,maxZoom:2,minZoom:1,boundingBox:new i}),Object.assign(this,t),this.target=new s(this.target),this.source=this.target.copy(),this.easing="linear"}copy(){let t=new d;return Object.assign(t,this),t}setViewport(t){if(this.viewport){let e=Math.sqrt(t.w/this.viewport.w*(t.h/this.viewport.h));this.viewport=t;const{x:i,y:s,z:n,a:r}=this.target;this.setPosition(0,i,s,n*e,r)}else this.viewport=t}glViewport(){let t=window.devicePixelRatio,e={};for(let i in this.viewport)e[i]=this.viewport[i]*t;return e}setPosition(t,e,i,n,r,o){if(this.easing=o||this.easing,this.bounded){const t=this.viewport.dx,o=this.viewport.dy;let a=new s({x:e,y:i,z:n,a:r,t:0}).transformBox(this.boundingBox);const l=a.width(),h=a.height(),c=Math.abs(l-t)/2;e=Math.min(Math.max(-c,e),c);const d=Math.abs(h-o)/2;i=Math.min(Math.max(-d,i),d)}let a=performance.now();this.source=this.getCurrentTransform(a),r=s.normalizeAngle(r),this.source.a=s.normalizeAngle(this.source.a),r-this.source.a>180&&(this.source.a+=360),this.source.a-r>180&&(this.source.a-=360),Object.assign(this.target,{x:e,y:i,z:n,a:r,t:a+t}),console.assert(!isNaN(this.target.x)),this.emit("update")}pan(t,e,i){let s=performance.now(),n=this.getCurrentTransform(s);n.x+=e,n.y+=i,this.setPosition(t,n.x,n.y,n.z,n.a)}zoom(t,e,i,s){i||(i=0),s||(s=0);let n=performance.now(),r=this.getCurrentTransform(n);this.bounded&&(e=Math.min(Math.max(e,this.minZoom),this.maxZoom)),r.x+=(r.x+i)*(r.z-e)/r.z,r.y+=(r.y+s)*(r.z-e)/r.z,this.setPosition(t,r.x,r.y,e,r.a)}rotate(t,e){let i=performance.now(),s=this.getCurrentTransform(i);this.setPosition(t,s.x,s.y,s.z,this.target.a+e)}deltaZoom(t,e,i=0,n=0){let r=performance.now(),o=this.getCurrentTransform(r);e*=this.target.z/o.z,this.bounded&&(o.z*e<this.minZoom&&(e=this.minZoom/o.z),o.z*e>this.maxZoom&&(e=this.maxZoom/o.z));let a=s.rotate(i,n,o.a);o.x+=a.x*o.z*(1-e),o.y+=a.y*o.z*(1-e),this.setPosition(t,o.x,o.y,o.z*e,o.a)}getCurrentTransform(t){return t>this.target.t&&(this.easing="linear"),s.interpolate(this.source,this.target,t,this.easing)}hasReachedTarget(t){return t||(t=this.getCurrentTransform(performance.now())),t.isComplete}getGlCurrentTransform(t){const e=this.getCurrentTransform(t);return e.x*=window.devicePixelRatio,e.y*=window.devicePixelRatio,e.z*=window.devicePixelRatio,e}fit(t,e){if(t.isEmpty())return;e||(e=0);let i=this.viewport.dx,s=this.viewport.dy,n=t.width(),r=t.height(),o=t.center(),a=Math.min(i/n,s/r);this.setPosition(e,-o.x*a,-o.y*a,a,0)}fitCameraBox(t){this.fit(this.boundingBox,t)}updateBounds(t,e){this.boundingBox=t;const i=this.viewport.dx,s=this.viewport.dy;let n=this.boundingBox.width(),r=this.boundingBox.height();this.minZoom=Math.min(i/n,s/r)*this.minScreenFraction,this.maxZoom=e>0?this.maxFixedZoom/e:this.maxFixedZoom,this.maxZoom=Math.max(this.minZoom,this.maxZoom)}}n(d,"update");class p{constructor(t,e){this.xs=t,this.ys=e,this.ks=this.getNaturalKs(new Float64Array(this.xs.length))}getNaturalKs(t){const e=this.xs.length-1,i=p.zerosMat(e+1,e+2);for(let t=1;t<e;t++)i[t][t-1]=1/(this.xs[t]-this.xs[t-1]),i[t][t]=2*(1/(this.xs[t]-this.xs[t-1])+1/(this.xs[t+1]-this.xs[t])),i[t][t+1]=1/(this.xs[t+1]-this.xs[t]),i[t][e+1]=3*((this.ys[t]-this.ys[t-1])/((this.xs[t]-this.xs[t-1])*(this.xs[t]-this.xs[t-1]))+(this.ys[t+1]-this.ys[t])/((this.xs[t+1]-this.xs[t])*(this.xs[t+1]-this.xs[t])));return i[0][0]=2/(this.xs[1]-this.xs[0]),i[0][1]=1/(this.xs[1]-this.xs[0]),i[0][e+1]=3*(this.ys[1]-this.ys[0])/((this.xs[1]-this.xs[0])*(this.xs[1]-this.xs[0])),i[e][e-1]=1/(this.xs[e]-this.xs[e-1]),i[e][e]=2/(this.xs[e]-this.xs[e-1]),i[e][e+1]=3*(this.ys[e]-this.ys[e-1])/((this.xs[e]-this.xs[e-1])*(this.xs[e]-this.xs[e-1])),p.solve(i,t)}getIndexBefore(t){let e=0,i=this.xs.length,s=0;for(;e<i;)s=Math.floor((e+i)/2),this.xs[s]<t&&s!==e?e=s:i=this.xs[s]>=t&&s!==i?s:e;return e===this.xs.length-1?this.xs.length-1:e+1}at(t){let e=this.getIndexBefore(t);const i=(t-this.xs[e-1])/(this.xs[e]-this.xs[e-1]),s=this.ks[e-1]*(this.xs[e]-this.xs[e-1])-(this.ys[e]-this.ys[e-1]),n=-this.ks[e]*(this.xs[e]-this.xs[e-1])+(this.ys[e]-this.ys[e-1]);return(1-i)*this.ys[e-1]+i*this.ys[e]+i*(1-i)*(s*(1-i)+n*i)}static solve(t,e){const i=t.length;let s=0,n=0;for(;s<i&&n<=i;){let e=0,r=-1/0;for(let o=s;o<i;o++){const i=Math.abs(t[o][n]);i>r&&(e=o,r=i)}if(0===t[e][n])n++;else{p.swapRows(t,s,e);for(let e=s+1;e<i;e++){const r=t[e][n]/t[s][n];t[e][n]=0;for(let o=n+1;o<=i;o++)t[e][o]-=t[s][o]*r}s++,n++}}for(let s=i-1;s>=0;s--){var r=0;t[s][s]&&(r=t[s][i]/t[s][s]),e[s]=r;for(let e=s-1;e>=0;e--)t[e][i]-=t[e][s]*r,t[e][s]=0}return e}static zerosMat(t,e){const i=[];for(let s=0;s<t;s++)i.push(new Float64Array(e));return i}static swapRows(t,e,i){let s=t[e];t[e]=t[i],t[i]=s}}class m{constructor(t,e=void 0,i=void 0,s=void 0){if("string"==typeof t)if(/^#([A-Fa-f0-9]{3}){1,2}$/.test(t)){let n=t.substring(1).split("");3==n.length&&(n=[n[0],n[0],n[1],n[1],n[2],n[2]]),n="0x"+n.join("")+"FF",t=m.normalizedRGBA(n>>24),e=m.normalizedRGBA(n>>16),i=m.normalizedRGBA(n>>8),s=m.normalizedRGBA(n)}else if(/^#([A-Fa-f0-9]{4}){1,2}$/.test(t)){let n=t.substring(1).split("");n="0x"+n.join(""),t=m.normalizedRGBA(n>>24),e=m.normalizedRGBA(n>>16),i=m.normalizedRGBA(n>>8),s=m.normalizedRGBA(n)}else if(/^rgb\(/.test(t)){let n=t.split("(")[1].split(")")[0];n=n.split(","),t=m.clamp(n[0]/255),e=m.clamp(n[1]/255),i=m.clamp(n[2]/255),s=1}else{if(!/^rgba\(/.test(t))throw Error("Value is not a color");{let n=t.split("(")[1].split(")")[0];n=n.split(","),t=m.clamp(n[0]/255),e=m.clamp(n[1]/255),i=m.clamp(n[2]/255),s=m.clamp(n[3]/255)}}this.r=t,this.g=e,this.b=i,this.a=s}static clamp=(t,e=0,i=1)=>Math.min(Math.max(t,e),i);static hex(t){var e=t.toString(16).toUpperCase();return 1==e.length?"0"+e:e}static normalizedRGBA(t){return m.clamp((255&t)/255)}static rgbToHex(t,e,i){return"#"+(16777216|(i|e<<8|t<<16)).toString(16).substring(1).toUpperCase()}static rgbToHexa(t,e,i,s){return"#"+m.hex(t)+m.hex(e)+m.hex(i)+m.hex(s)}value(){return[this.r,this.g,this.b,this.a]}toRGB(){const t=[255*this.r,255*this.g,255*this.b];return t.forEach(((t,e,i)=>{i[e]=m.clamp(Math.round(t),0,255)})),t}toHex(){const t=this.toRGB();return m.rgbToHex(t[0],t[1],t[2])}toHexa(){const t=this.toRGBA();return m.rgbToHexa(t[0],t[1],t[2],t[3])}toRGBA(){const t=[255*this.r,255*this.g,255*this.b,255*this.a];return t.forEach(((t,e,i)=>{i[e]=m.clamp(Math.round(t),0,255)})),t}}class f{constructor(t){Object.assign(this,{format:"vec3"}),this._texture=null,Object.assign(this,t)}async loadImage(t,e){let i,s=new URL(t.url,window.location.href).origin!==window.location.origin;if(t.end||"undefined"==typeof createImageBitmap){let n={};n.headers={range:`bytes=${t.start}-${t.end}`,"Accept-Encoding":"indentity",mode:s?"cors":"same-origin"};let r=await fetch(t.url,n);if(!r.ok)return void console.error(`Failed to load ${t.url}: ${r.status} ${r.statusText}`);if(206!=r.status)throw new Error("The server doesn't support partial content requests (206).");let o=await r.blob();i=await this.blobToImage(o,e)}else i=document.createElement("img"),s&&(i.crossOrigin=""),i.onerror=function(t){console.log("Texture loading error!")},i.src=t.url,await new Promise(((t,e)=>{i.onload=()=>{t()}}));const n=this.loadTexture(e,i);const r=i.width*i.height*3;return this.emit("loaded"),[n,r]}async blobToImage(t,e){let i;if("undefined"!=typeof createImageBitmap){var s="undefined"!=typeof InstallTrigger;i=s?await createImageBitmap(t):await createImageBitmap(t,{imageOrientation1:"flipY"})}else{let e=window.URL||window.webkitURL;i=document.createElement("img"),i.onerror=function(t){console.log("Texture loading error!")},i.src=e.createObjectURL(t),await new Promise(((t,e)=>{i.onload=()=>t()})),e.revokeObjectURL(i.src)}return i}loadTexture(t,e){this.width=e.width,this.height=e.height;var i=t.createTexture();t.bindTexture(t.TEXTURE_2D,i);let s=t.RGBA,n=t.RGBA;switch(this.format){case"vec3":s=t.RGB;break;case"vec4":s=t.RGBA;break;case"float":s=t instanceof WebGL2RenderingContext?t.RED:t.LUMINANCE}return n="float"===this.format?t.R8:s===t.RGB?t.RGB:t.RGBA,t.texImage2D(t.TEXTURE_2D,0,n,s,t.UNSIGNED_BYTE,e),t.texParameterf(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),this.width>1024||this.height>1024?(t.generateMipmap(t.TEXTURE_2D),t.texParameterf(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR_MIPMAP_LINEAR)):t.texParameterf(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),this._texture=i,i}}n(f,"loaded");class g{constructor(t){t=Object.assign({isLinear:!1,isSrgbSimplified:!0},t),Object.assign(this,{debug:!1,samplers:[],uniforms:{},label:null,program:null,modes:[],mode:nul