openlime
Version:
Open Layered IMage Explorer
9 lines • 270 kB
JavaScript
// ##########################################
// OpenLIME - Open Layered IMage Explorer
// Author: CNR ISTI - Visual Computing Lab
// Author: CRS4 Visual and Data-intensive Computing Group
// openlime v1.2.0 - 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,o){for(let l=0;l<e;l++){for(let n=0;n<i;n++)s[n]=t[n*e+l];a(s,n,r,o,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];a(s,n,r,o,e);for(let i=0;i<e;i++)t[l*e+i]=Math.sqrt(n[i])}}function a(t,e,i,s,n){i[0]=0,s[0]=-l,s[1]=+l;for(let e=1,a=0;e<n;e++){for(var r=(t[e]+e*e-(t[i[a]]+i[a]*i[a]))/(2*e-2*i[a]);r<=s[a];)a--,r=(t[e]+e*e-(t[i[a]]+i[a]*i[a]))/(2*e-2*i[a]);a++,i[a]=e,s[a]=r,s[a+1]=+l}for(let r=0,a=0;r<n;r++){for(;s[a+1]<r;)a++;e[r]=(r-i[a])*(r-i[a])+t[i[a]]}}var o=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),g=Array(h);for(let t=0;t<e*i;t++){var f=o[t]/255;c[t]=1===f?0:0===f?l:Math.pow(Math.max(0,.5-f),2),d[t]=1===f?l:0===f?0:Math.pow(Math.max(0,f-.5),2)}r(c,e,i,u,p,g,m),r(d,e,i,u,p,g,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"),a=document.createElement("canvas");a.width=i[0],a.height=i[1],s.setAttributeNS(null,"width","100%"),s.setAttributeNS(null,"height","100%");const o=a.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 a=0,l=0;s<e?(l=i[1],a=l*s):(a=i[0],l=a/s);let d=.5*(i[1]-l),p=.5*(i[0]-a);o.translate(p,d),o.drawImage(c,0,0),h.revokeObjectURL(u);const m=o.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 this.xHigh-this.xLow}height(){return this.yHigh-this.yLow}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 xLow<=t.xHigh&&xHigh>=t.xLow&&yLow<=t.yHigh&&yHigh>=t.yLow}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}static interpolate(t,e,i,n){console.assert(!isNaN(t.x)),console.assert(!isNaN(e.x));const r=new s;let a=e.t-t.t;if(i<t.t)Object.assign(r,t);else if(i>e.t||a<.001)Object.assign(r,e);else{let s=(i-t.t)/a;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 o=1-s;for(let i of["x","y","z","a"])r[i]=o*t[i]+s*e[i]}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,a=Math.PI*this.a/180;return[Math.cos(a)*i*e,Math.sin(a)*s*e,0,0,-Math.sin(a)*i*e,Math.cos(a)*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(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 r;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}mapToScene(t,e,i){t-=this.viewport.w/2,e-=this.viewport.h/2,t-=i.x,e-=i.y,t/=i.z,e/=i.z;let n=s.rotate(t,e,-i.a);return{x:n.x,y:n.y}}sceneToCanvas(t,e,i){let n=s.rotate(t,e,i.a);return{x:t=n.x*i.z+i.x-this.viewport.x+this.viewport.w/2,y:e=n.y*i.z-i.y+this.viewport.y+this.viewport.h/2}}setPosition(t,e,i,n,r,a){if(this.easing=a||this.easing,this.bounded){const t=this.viewport.dx,a=this.viewport.dy;let o=new s({x:e,y:i,z:n,a:r,t:0}).transformBox(this.boundingBox);const l=o.width(),h=o.height(),c=Math.abs(l-t)/2;e=Math.min(Math.max(-c,e),c);const d=Math.abs(h-a)/2;i=Math.min(Math.max(-d,i),d)}let o=performance.now();this.source=this.getCurrentTransform(o),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:o+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(),a=this.getCurrentTransform(r);e*=this.target.z/a.z,this.bounded&&(a.z*e<this.minZoom&&(e=this.minZoom/a.z),a.z*e>this.maxZoom&&(e=this.maxZoom/a.z));let o=s.rotate(i,n,a.a);a.x+=o.x*a.z*(1-e),a.y+=o.y*a.z*(1-e),this.setPosition(t,a.x,a.y,a.z*e,a.a)}getCurrentTransform(t){return t>this.target.t&&(this.easing="linear"),s.interpolate(this.source,this.target,t,this.easing)}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(),a=t.center(),o=Math.min(i/n,s/r);this.setPosition(e,-a.x*o,-a.y*o,o,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(r,"update");class a{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 h{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 a;return e.index=t,e}needed(t,e,i,s,n,r,a=8){let o=r.get(0)||this.newTile(0);return o.time=performance.now(),o.priority=10,null===o.missing?[o]:[]}available(t,e,i,s,n,r){let a={};return r.has(0)&&0==r.get(0).missing&&(a[0]=r.get(0)),a}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})}}h.prototype.types={},n(h,"ready","updateSize");class c{static#t;#e=[];#i;#s=0;#n=0;#r;#a;#o=null;#l;#h;#c=0;constructor(t={}){if(c.#t)return c.#t;const e={capacity:536870912,maxRequest:6,maxRequestsRate:0,maxPrefetch:8388608,...t};this.#i=e.capacity,this.#r=e.maxRequest,this.#a=e.maxRequestsRate,this.#h=e.maxPrefetch,this.#l=performance.now(),c.#t=this}static getInstance(t){if(c.#t){if(t){const e=c.#t;void 0!==t.capacity&&(e.#i=t.capacity),void 0!==t.maxRequest&&(e.#r=t.maxRequest),void 0!==t.maxRequestsRate&&(e.#a=t.maxRequestsRate),void 0!==t.maxPrefetch&&(e.#h=t.maxPrefetch)}}else new c(t);return c.#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.#a)return!1;const t=performance.now(),e=1e3/this.#a,i=t-this.#l;return!(i>e)&&(this.#o||(this.#o=setTimeout((()=>{this.#o=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.#g(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}#g(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 d{constructor(t){if(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)}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 h(null,this.layout,t))}else this.setLayout(this.layout)}setViewport(t){this.viewport=t,this.emit("update")}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.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){if(null==t||null==t){return console.log("ASKING BBOX INFO ON NO LAYERS"),new i}let s=new i;for(let i of Object.values(t))if((!e||i.visible)&&i.layout.width){const t=i.boundingBox();s.mergeBox(t)}return 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,a=(e-i.t)/r;switch(t.easing){case"ease-out":a=1-Math.pow(1-a,2);break;case"ease-in-out":a=a<.5?2*a*a:1-Math.pow(-2*a+2,2)/2}let o=1-a;n.value=[];for(let t=0;t<i.value.length;t++)n.value[t]=o*i.value[t]+a*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,c.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 a=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,a),this.gl.activeTexture(this.gl.TEXTURE0+a),this.gl.bindTexture(this.gl.TEXTURE_2D,t.samplers[e].tex),a++;let o=0;for(let t of Object.values(n))this.drawTile(t,o),++o;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 a=0;for(let e of Object.values(t)){let t=this.layout.tileCoords(e);n.set(t.coords,12*a),r.set(t.tcoords,8*a);const i=4*a;e.indexBufferByteOffset=2*a*6,s.set([i+3,i+2,i+1,i+3,i+1,i+0],6*a),++a}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),c.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]),a=await s.blobToImage(r,this.gl),o=s.loadTexture(this.gl,a),l=a.width*a.height*this.getPixelSize(i.id);t.size+=l,t.tex[i.id]=o,t.w=a.width,t.h=a.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}}d.prototype.types={},n(d,"ready","update","loaded","updateSize"),window.structuredClone="function"==typeof structuredClone?structuredClone:function(t){return JSON.parse(JSON.stringify(t))};class p{constructor(t,e,i,s){Object.assign(this,{canvasElement:null,preserveDrawingBuffer:!1,gl:null,overlayElement:null,camera:i,layers:{},targetfps:30,fps:0,timing:[16],timingLength:5,overBudget:0,signals:{update:[],updateSize:[],ready:[]}}),Object.assign(this,s),this.init(t,e);for(let t in this.layers)this.addLayer(t,new d(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;let i={antialias:!1,depth:!1,preserveDrawingBuffer:this.preserveDrawingBuffer};if(this.gl=this.gl||t.getContext("webgl2",i)||t.getContext("webgl",i)||t.getContext("experimental-webgl",i),!this.gl)throw"Could not create a WebGL context";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()}))}setState(t,e,i="linear"){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,preserveDrawingBuffer:this.preserveDrawingBuffer};this.gl=this.gl||this.canvasElement.getContext("webgl2",t)||this.canvasElement.getContext("webgl",t)||this.canvasElement.getContext("experimental-webgl",t);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.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,this.layers[t]=e,this.prefetch()}removeLayer(t){t.clear(),delete this.layers[t.id],delete c.layers[t],this.prefetch()}updateSize(){const t=!1;let e=d.computeLayersBBox(this.layers,t),i=d.computeLayersMinScale(this.layers,t);null!=e&&this.camera.viewport&&this.camera.updateBounds(e,i),this.emit("updateSize")}draw(t){let e=this.gl,i=this.camera.glViewport();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)),a=!0;for(let t of r)t.visible&&(a=t.draw(n,i)&&a);return a&&n.t>=this.camera.target.t}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())}}}n(p,"update","updateSize","ready");class m{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=m.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])),m.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 a=s;a<i;a++){const i=Math.abs(t[a][n]);i>r&&(e=a,r=i)}if(0===t[e][n])n++;else{m.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 a=n+1;a<=i;a++)t[e][a]-=t[s][a]*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 g{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=g.normalizedRGBA(n>>24),e=g.normalizedRGBA(n>>16),i=g.normalizedRGBA(n>>8),s=g.normalizedRGBA(n)}else if(/^#([A-Fa-f0-9]{4}){1,2}$/.test(t)){let n=t.substring(1).split("");n="0x"+n.join(""),t=g.normalizedRGBA(n>>24),e=g.normalizedRGBA(n>>16),i=g.normalizedRGBA(n>>8),s=g.normalizedRGBA(n)}else if(/^rgb\(/.test(t)){let n=t.split("(")[1].split(")")[0];n=n.split(","),t=g.clamp(n[0]/255),e=g.clamp(n[1]/255),i=g.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=g.clamp(n[0]/255),e=g.clamp(n[1]/255),i=g.clamp(n[2]/255),s=g.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 g.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"#"+g.hex(t)+g.hex(e)+g.hex(i)+g.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]=g.clamp(Math.round(t),0,255)})),t}toHex(){const t=this.toRGB();return g.rgbToHex(t[0],t[1],t[2])}toHexa(){const t=this.toRGBA();return g.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]=g.clamp(Math.round(t),0,255)})),t}}class f{constructor(t){Object.assign(this,{format:"vec3"}),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 callback("Failed loading "+t.url+": "+r.statusText);if(206!=r.status)throw"The server doesn't support partial content requests (206).";let a=await r.blob();i=await this.blobToImage(a,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()}}));return[this.loadTexture(e,i),i.width*i.height*3]}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;switch(this.format){case"vec3":s=t.RGB;break;case"vec4":s=t.RGBA;break;case"float":s=t.LUMINANCE}return t.texImage2D(t.TEXTURE_2D,0,s,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),i}}class v{constructor(t){Object.assign(this,{version:100,debug:!1,samplers:[],uniforms:{},label:null,program:null,modes:[],mode:null,needsUpdate:!0,tileSize:[0,0]}),n(v,"update"),Object.assign(this,t),this.filters=[]}clearFilters(){this.filters=[],this.needsUpdate=!0,this.emit("update")}addFilter(t){t.shader=this,this.filters.push(t),this.needsUpdate=!0,t.needsUpdate=!0,this.emit("update")}removeFilter(t){this.filters=this.filters.filter((e=>e.name!=t)),this.needsUpdate=!0,this.emit("update")}setMode(t){if(-1==this.modes.indexOf(t))throw Error("Unknown mode: "+t);this.mode=t,this.needsUpdate=!0}restoreWebGL(t){this.createProgram(t)}setTileSize(t){this.tileSize=t,this.needsUpdate=!0}setUniform(t,e){let i=this.getUniform(t);if(!i)throw new Error(`Unknown '${t}'. It is not a registered uniform.`);if("number"!=typeof e&&"boolean"!=typeof e||i.value!=e){if(Array.isArray(e)&&Array.isArray(i.value)&&e.length==i.value.length){let t=!0;for(let s=0;s<e.length;s++)if(e[s]!=i.value[s]){t=!1;break}if(t)return}i.value=e,i.needsUpdate=!0,this.emit("update")}}completeFragShaderSrc(t){let e=!(t instanceof WebGLRenderingContext),i=(e?"#version 300 es":"")+"\n";i+="precision highp float;\n",i+="precision highp int;\n",i+=`const vec2 tileSize = vec2(${this.tileSize[0]}.0, ${this.tileSize[1]}.0);\n`,i+=this.fragShaderSrc()+"\n";for(let t of this.filters)i+=`\t\t// Filter: ${t.name}\n`,i+=t.fragModeSrc()+"\n",i+=t.fragSamplerSrc()+"\n",i+=t.fragUniformSrc()+"\n",i+=t.fragDataSrc()+"\n\n";i+=`\n\t\t${e?"out":""} vec4 color;\n\t\tvoid main() { \n\t\t\tcolor = data();\n\t\t\t`;for(let t of this.filters)i+=`color=${t.functionName()}(color);\n`;return i+=(e?"":"gl_FragColor = color;")+"\n\t\t}",i}createProgram(t){let i=t.createShader(t.VERTEX_SHADER);t.shaderSource(i,this.vertShaderSrc(t)),t.compileShader(i);let s=t.getShaderParameter(i,t.COMPILE_STATUS);if(!s)throw e.printSrcCode(this.vertShaderSrc(t)),console.log(t.getShaderInfoLog(i)),Error("Failed vertex shader compilation: see console log and ask for support.");this.debug&&(console.log("here"),e.printSrcCode(this.vertShaderSrc(t)));let n=t.createShader(t.FRAGMENT_SHADER);t.shaderSource(n,this.completeFragShaderSrc(t)),t.compileShader(n),this.program&&t.deleteProgram(this.program);let r=t.createProgram();if(t.getShaderParameter(n,t.COMPILE_STATUS),s=t.getShaderParameter(n,t.COMPILE_STATUS),!s)throw e.printSrcCode(this.completeFragShaderSrc(t)),console.log(t.getShaderInfoLog(n)),Error("Failed fragment shader compilation: see console log and ask for support.");if(this.debug&&e.printSrcCode(this.completeFragShaderSrc(t)),t.attachShader(r,i),t.attachShader(r,n),t.linkProgram(r),!t.getProgramParameter(r,t.LINK_STATUS)){var a=t.getProgramInfoLog(r);throw new Error("Could not compile WebGL program. \n\n"+a)}for(let e of this.samplers)e.location=t.getUniformLocation(r,e.name);for(let e of this.filters)for(let i of e.samplers)i.location=t.getUniformLocation(r,i.name);this.coordattrib=t.getAttribLocation(r,"a_position"),t.vertexAttribPointer(this.coordattrib,3,t.FLOAT,!1,0,0),t.enableVertexAttribArray(this.coordattrib),this.texattrib=t.getAttribLocation(r,"a_texcoord"),t.vertexAttribPointer(this.texattrib,2,t.FLOAT,!1,0,0),t.enableVertexAttribArray(this.texattrib),this.matrixlocation=t.getUniformLocation(r,"u_matrix"),this.program=r,this.needsUpdate=!1;for(let t of Object.values(this.allUniforms()))t.location=null,t.needsUpdate=!0;for(let e of this.filters)e.prepare(t)}getUniform(t){let e=this.uniforms[t];if(e)return e;for(let i of this.filters)if(e=i.uniforms[t],e)return e;return e}allUniforms(){const t=this.uniforms;for(let e of this.filters)Object.assign(t,e.uniforms);return t}updateUniforms(t){for(const[e,i]of Object.entries(this.allUniforms()))if(i.location||(i.location=t.getUniformLocation(this.program,e)),i.location&&i.needsUpdate){let e=i.value;switch(i.type){case"vec4":t.uniform4fv(i.location,e);break;case"vec3":t.uniform3fv(i.location,e);break;case"vec2":t.uniform2fv(i.location,e);break;case"float":t.uniform1f(i.location,e);break;case"int":case"bool":t.uniform1i(i.location,e);break;case"mat3":t.uniformMatrix3fv(i.location,!1,e);break;case"mat4":t.uniformMatrix4fv(i.location,!1,e);break;default:throw Error("Unknown uniform type: "+u.type)}i.needsUpdate=!1}}vertShaderSrc(t){let e=!(t instanceof WebGLRenderingContext);return`${e?"#version 300 es":""}\n\nprecision highp float; \nprecision highp int; \n\nuniform mat4 u_matrix;\n${e?"in":"attribute"} vec4 a_position;\n${e?"in":"attribute"} vec2 a_texcoord;\n\n${e?"out":"varying"} vec2 v_texcoord;\n\n\t\t\tvoid main() {\n\t\t\t\tgl_Position = u_matrix * a_position;\n\t\t\t\tv_texcoord = a_texcoord;\n\t\t\t} `}fragShaderSrc(t){let e=!(t instanceof WebGLRenderingContext);return`\n\nuniform sampler2D kd;\n\n${e?"in":"varying"} vec2 v_texcoord;\n\nvec4 data() {\n\treturn texture${e?"":"2D"}(kd, v_texcoord);\n}\n`}}class y extends d{constructor(t){if(super(t),0!=Object.keys(this.rasters).length)throw"Rasters options should be empty!";if(this.url)this.layout.setUrls([this.url]);else if(0==this.layout.urls.length)throw"Missing options.url parameter";const e=null!=this.format?this.format:"vec4";let i=new f({format:e});this.rasters.push(i);let s=new v({label:"Rgb",samplers:[{id:0,name:"kd",type:e}]});this.shaders={standard:s},this.setShader("standard")}}d.prototype.types.image=t=>new y(t);class x extends d{constructor(t){if(super(t),0!=Object.keys(this.rasters).length)throw"Rasters options should be empty!";this.textures=[],this.framebuffers=[],this.status="ready"}draw(t,e){for(let t of this.layers)if("ready"!=t.status)return;if(!this.shader)throw"Shader not specified!";let i=e.dx,s=e.dy;this.framebuffers.length&&this.layout.width==i&&this.layout.height==s||(this.deleteFramebuffers(),this.layout.width=i,this.layout.height=s,this.createFramebuffers());let n=this.gl;var r=[0,0,0,0];n.clearColor(r[0],r[1],r[2],r[3]);for(let e=0;e<this.layers.length;e++)n.bindFramebuffer(n.FRAMEBUFFER,this.framebuffers[e]),n.clear(n.COLOR_BUFFER_BIT),this.layers[e].draw(t,{x:0,y:0,dx:i,dy:s,w:i,h:s}),n.bindFramebuffer(n.FRAMEBUFFER,null);this.prepareWebGL();for(let t=0;t<this.layers.length;t++)n.uniform1i(this.shader.samplers[t].location,t),n.activeTexture(n.TEXTURE0+t),n.bindTexture(n.TEXTURE_2D,this.textures[t]);this.updateTileBuffers(new Float32Array([-1,-1,0,-1,1,0,1,1,0,1,-1,0]),new Float32Array([0,0,0,1,1,1,1,0])),n.drawElements(n.TRIANGLES,6,n.UNSIGNED_SHORT,0)}createFramebuffers(){let t=this.gl;for(let e=0;e<this.layers.length;e++){const i=t.createTexture();t.bindTexture(t.TEXTURE_2D,i);const s=0,n=t.RGBA,r=0,a=t.RGBA,o=t.UNSIGNED_BYTE;t.texImage2D(t.TEXTURE_2D,s,n,this.layout.width,this.layout.height,r,a,o,null),t.texParameteri(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);const l=t.createFramebuffer();t.bindFramebuffer(t.FRAMEBUFFER,l),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,i,0),t.bindFramebuffer(t.FRAMEBUFFER,null),this.textures[e]=i,this.framebuffers[e]=l}}deleteFramebuffers(){}boundingBox(){let t=d.computeLayersBBox(this.layers,!1);return null!=this.transform&&null!=this.transform&&(t=this.transform.transformBox(t)),t}scale(){let t=d.computeLayersMinScale(this.layers,!1);return t*=this.transform.z,t}}d.prototype.types.combiner=t=>new x(t);class w{constructor(t){Object.assign(this,{id:w.UUID(),code:null,label:null,description:null,class:null,target:null,svg:null,image:null,region:null,data:{},style:null,bbox:null,visible:!0,state:null,ready:!1,needsUpdate:!0,editing:!1},t),this.label||(this.label=""),this.elements=[]}static UUID(){return"axxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(function(t){var e=16*Math.random()|0;return("x"==t?e:3&e|8).toString(16)}))}getBBoxFromElements(){let t=null;if(this.elements.length){let{x:e,y:s,width:n,height:r}=this.elements[0].getBBox();for(let t of this.elements){const{sx:i,sy:a,swidth:o,sheight:l}=t.getBBox();e=Math.min(e,i),s=Math.min(e,a),n=Math.max(n+e,i+o)-e,r=Math.max(r+s,a+l)-s}t=new i({xLow:e,yLow:s,xHigh:e+n,yHigh:s+n})}else if(null==this.region)t=new i;else{const e=this.region;t=new i({xLow:e.x,yLow:e.y,xHigh:e.x+e.w,yHigh:e.y+e.h})}return t}static fromJsonLd(t){if("Annotation"!=t.type)throw"Not a jsonld annotation.";let e={id:t.id},i={identifying:"code",identifying:"label",describing:"description",classifying:"class"};for(let s of t.body){let t=i[s.purpose];t&&(e[t]=s.value)}let s=t.target&&t.target.selector;if(s){if("SvgSelector"!==s.type)throw"Unsupported selector: "+s.type;e.svg=s.value,e.elements=[]}return new w(e)}toJsonLd(){let t=[];(null!==this.code&&t.push({type:"TextualBody",value:this.code,purpose:"indentifying"}),null!==this.class&&t.push({type:"TextualBody",value:this.class,purpose:"classifying"}),null!==this.description&&t.push({type:"TextualBody",value:this.description,purpose:"describing"}),this.id,this.target&&(target.selector.source=this.target),this.element)&&(new XMLSerializer).serializeToString(this.element)}}class b extends d{constructor(t){super(t=Object.assign({style:null,annotations:[],selected:new Set,overlay:!0,annotationsListEntry:null},t)),"string"==typeof this.annotations&&(async()=>{await this.loadAnnotations(this.annotations)})()}async loadAnnotations(t){const e=new Headers;e.append("pragma","no-cache"),e.append("cache-control","no-cache");var i=await fetch(t,{method:"GET",headers:e});if(i.ok)if(this.annotations=await i.json(),"error"!=this.annotations.status){this.annotations=this.annotations.map((t=>new w(t)));for(let t of this.annotations)1!=t.publish&&(t.visible=!1);this.annotationsListEntry&&this.createAnnotationsList(),this.emit("update"),this.status="ready",this.emit("ready"),this.emit("loaded")}else alert("Failed to load annotations: "+this.annotations.msg);else this.status="Failed loading "+this.url+": "+i.statusText}newAnnotation(t){t||(t=new w),this.annotations.push(t);let e=this.createAnnotationEntry(t),i=document.createElement("template");return i.innerHTML=e.trim(),this.annotationsListEntry.element.parentElement.querySelector(".openlime-list").appendChild(i.content.firstChild),this.clearSelected(),t}annotationsEntry(){return this.annotationsListEntry={html:"",list:[],classes:"openlime-annotations",status:()=>"active",oncreate:()=>{Array.isArray(this.annotations)&&this.createAnnotationsList()}}}createAnnotationsList(){let t="";for(let e of this.annotations)t+=this.createAnnotationEntry(e);let e=this.annotationsListEntry.element.parentElement.querySelector(".openlime-list");e.innerHTML=t,e.addEventListener("click",(t=>{let e=t.srcElement.closest("svg");if(e){let t=e.closest("[data-annotation]");t.classList.toggle("hidden");let i=t.getAttribute("data-annotation"),s=this.getAnnotationById(i);s.visible=!s.visible,s.needsUpdate=!0,this.emit("update")}let i=t.srcElement.getAttribute("data-annotation");if(i){this.clearSelected();let t=this.getAnnotationById(i);this.setSelected(t,!0)}}))}createAnnotationEntry(t){return`<a href="#" data-annotation="${t.id}" class="openlime-entry ${0==t.visible?"hidden":""}">${t.label||""}\n\t\t\t<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="openlime-eye"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg>\n\t\t\t<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="openlime-eye-off">