@doegis/core
Version:
DOE GIS API
3 lines (1 loc) • 3.54 kB
JavaScript
import has from"../../../../core/has.js";import{throwIfNotAbortError as t}from"../../../../core/promiseUtils.js";import e from"./Rect.js";import i from"./RectangleBinPack.js";import{PixelFormat as h,PixelType as s}from"../../../webgl/enums.js";import{Texture as r}from"../../../webgl/Texture.js";const a=256,n=t=>Math.floor(t/256);function c(t){const e=new Set;for(const i of t)e.add(n(i));return e}function o(e,i,h){return e.has(i)||e.set(i,h().then((()=>{e.delete(i)})).catch((h=>{e.delete(i),t(h)}))),e.get(i)}const l=t=>({rect:new e(0,0,0,0),page:0,metrics:{left:0,width:0,height:0,advance:0,top:0},code:t,sdf:!0});class g{constructor(t,e,h){this.width=0,this.height=0,this._dirties=[],this._glyphData=[],this._currentPage=0,this._glyphCache={},this._textures=[],this._rangePromises=new Map,this.width=t,this.height=e,this._glyphSource=h,this._binPack=new i(t-4,e-4),this._glyphData.push(new Uint8Array(t*e)),this._dirties.push(!0),this._textures.push(null),this._initDecorationGlyph()}dispose(){this._binPack=null;for(const t of this._textures)t&&t.dispose();this._textures.length=0,this._glyphData.length=0}_initDecorationGlyph(){const t=[117,149,181,207,207,181,149,117],e=[];for(let h=0;h<t.length;h++){const i=t[h];for(let t=0;t<11;t++)e.push(i)}const i={metrics:{width:5,height:2,left:0,top:0,advance:0},bitmap:new Uint8Array(e)};this._recordGlyph(i)}async getGlyphItems(t,e,i){const h=this._getGlyphCache(t);return await this._fetchRanges(t,e,i),e.map((e=>this._getMosaicItem(h,t,e)))}bind(t,e,i,h){const s=this._getTexture(t,i);s.setSamplingMode(e),this._dirties[i]&&(s.setData(this._glyphData[i]),this._dirties[i]=!1),t.bindTexture(s,h)}_getGlyphCache(t){return this._glyphCache[t]||(this._glyphCache[t]={}),this._glyphCache[t]}_getTexture(t,e){return this._textures[e]||(this._textures[e]=new r(t,{pixelFormat:h.ALPHA,dataType:s.UNSIGNED_BYTE,width:this.width,height:this.height},new Uint8Array(this.width*this.height))),this._textures[e]}_invalidate(){this._dirties[this._currentPage]=!0}async _fetchRanges(t,e,i){const h=c(e),s=[];h.forEach((e=>{s.push(this._fetchRange(t,e,i))})),await Promise.all(s)}async _fetchRange(t,e,i){if(e>a)return;const h=t+e;return o(this._rangePromises,h,(()=>this._glyphSource.getRange(t,e,i)))}_getMosaicItem(t,e,i){if(!t[i]){const h=this._glyphSource.getGlyph(e,i);if(!h||!h.metrics)return l(i);const s=this._recordGlyph(h),r=this._currentPage,a=h.metrics;t[i]={rect:s,page:r,metrics:a,code:i,sdf:!0},this._invalidate()}return t[i]}_recordGlyph(t){const h=t.metrics;let s;if(0===h.width)s=new e(0,0,0,0);else{const e=3,r=h.width+2*e,a=h.height+2*e;s=this._binPack.allocate(r,a),s.isEmpty&&(this._dirties[this._currentPage]||(this._glyphData[this._currentPage]=null),this._currentPage=this._glyphData.length,this._glyphData.push(new Uint8Array(this.width*this.height)),this._dirties.push(!0),this._textures.push(null),this._initDecorationGlyph(),this._binPack=new i(this.width-4,this.height-4),s=this._binPack.allocate(r,a));const n=this._glyphData[this._currentPage],c=t.bitmap;let o,l;if(c)for(let t=0;t<a;t++){o=r*t,l=this.width*(s.y+t)+s.x;for(let t=0;t<r;t++)n[l+t]=c[o+t]}has("esri-glyph-debug")&&this._showDebugPage(n)}return s}_showDebugPage(t){const e=document.createElement("canvas"),i=e.getContext("2d"),h=new ImageData(this.width,this.height),s=h.data;e.width=this.width,e.height=this.height,e.style.border="1px solid black";for(let r=0;r<t.length;++r)s[4*r+0]=t[r],s[4*r+1]=0,s[4*r+2]=0,s[4*r+3]=255;i.putImageData(h,0,0),document.body.appendChild(e)}}export{g as default};