@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
3 lines (2 loc) • 7.16 kB
JavaScript
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.19/LICENSE.txt */
import{fromRotation as t,multiply as s,translate as i,rotate as e}from"../../../../../../core/libs/gl-matrix-2/math/mat2d.js";import{create as o,transformMany as h}from"../../../../../../core/libs/gl-matrix-2/factories/mat2df32.js";import{transformMat2d as n,set as r}from"../../../../../../core/libs/gl-matrix-2/math/vec2.js";import{create as a}from"../../../../../../core/libs/gl-matrix-2/factories/vec2f32.js";import{getXAnchorDirection as f,getYAnchorDirection as c}from"../../alignmentUtils.js";import d from"../../Rect.js";import m from"../../collisions/BoundingBox.js";const g=22,_=4,l=g+_,u=g-6,x=Math.PI/180,p=8,b=1.5;class y{constructor(t,s,i,e){this._rotationT=o(),this._xBounds=0,this._yBounds=0,this.minZoom=0,this.maxZoom=255,this._bounds=null;const h=i.rect,n=new Float32Array(8);t*=e,s*=e;const r=0===i.code?i.metrics.width:h.width*e,a=0===i.code?i.metrics.height:h.height*e;this.width=r,this.height=a,n[0]=t,n[1]=s,n[2]=t+r,n[3]=s,n[4]=t,n[5]=s+a,n[6]=t+r,n[7]=s+a,this._data=n,this._setTextureCoords(h),this._scale=e,this._mosaic=i,this.x=t,this.y=s,this.maxOffset=Math.max(t+r,s+a)}get mosaic(){return this._mosaic}set angle(s){this._angle=s,t(this._rotationT,-s),this._setOffsets()}get angle(){return this._angle}get xTopLeft(){return this._data[0]}get yTopLeft(){return this._data[1]}get xBottomRight(){return this._data[6]}get yBottomRight(){return this._data[7]}get texcoords(){return this._texcoords}get textureBinding(){return this._mosaic.textureBinding}get offsets(){return this._offsets||this._setOffsets(),this._offsets}get bounds(){if(!this._bounds){const{height:t,width:i}=this._mosaic.metrics,e=i*this._scale,n=Math.abs(t)*this._scale,r=new Float32Array(8);r[0]=this.x,r[1]=this.y,r[2]=this.x+e,r[3]=this.y,r[4]=this.x,r[5]=this.y+n,r[6]=this.x+e,r[7]=this.y+n;const a=s(o(),this._rotationT,this._transform);h(r,r,a);let f=1/0,c=1/0,d=-1/0,g=-1/0;for(let s=0;s<4;s++){const t=r[2*s],i=r[2*s+1];f=Math.min(f,t),c=Math.min(c,i),d=Math.max(d,t),g=Math.max(g,i)}const _=d-f,l=g-c,u=f+_/2,x=c+l/2;this._bounds=new m(u,x,_,l)}return this._bounds}setTransform(t){this._transform=t,this._offsets=null}_setOffsets(){this._offsets||(this._offsets={topLeft:[0,0],topRight:[0,0],bottomLeft:[0,0],bottomRight:[0,0]});const t=s(o(),this._rotationT,this._transform);this._offsets.topLeft[0]=this._data[0],this._offsets.topLeft[1]=this._data[1],this._offsets.topRight[0]=this._data[2],this._offsets.topRight[1]=this._data[3],this._offsets.bottomLeft[0]=this._data[4],this._offsets.bottomLeft[1]=this._data[5],this._offsets.bottomRight[0]=this._data[6],this._offsets.bottomRight[1]=this._data[7],n(this._offsets.topLeft,this._offsets.topLeft,t),n(this._offsets.topRight,this._offsets.topRight,t),n(this._offsets.bottomLeft,this._offsets.bottomLeft,t),n(this._offsets.bottomRight,this._offsets.bottomRight,t)}_setTextureCoords({x:t,y:s,width:i,height:e}){this._texcoords={topLeft:[t,s],topRight:[t+i,s],bottomLeft:[t,s+e],bottomRight:[t+i,s+e]}}}const w=(t,s)=>({code:0,page:0,sdf:!0,rect:new d(0,0,11,8),textureBinding:s,metrics:{advance:0,height:4,width:t,left:0,top:0}});function L(t,s){return t.forEach(t=>n(t,t,s)),{topLeft:t[0],topRight:t[1],bottomLeft:t[2],bottomRight:t[3]}}class M{constructor(t,s,i,e){this._rotation=0,this._decorate(t,s,i,e),this.glyphs=t,this.bounds=this._createBounds(t),this.isMultiline=s.length>1,this._hasRotation=0!==i.angle,this._transform=this._createGlyphTransform(this.bounds,i),this._borderLineSizePx=i.borderLineSizePx,(i.borderLineSizePx||i.hasBackground)&&([this.bounds,this.textBox]=this.shapeBackground(this._transform));for(const o of t)o.setTransform(this._transform)}setRotation(i){if(0===i&&0===this._rotation)return;this._rotation=i;const e=this._transform,h=t(o(),i);s(e,h,e);for(const t of this.glyphs)t.setTransform(this._transform)}_decorate(t,s,i,e){if(!i.decoration||"none"===i.decoration||!t.length)return;const o=i.scale,h="underline"===i.decoration?e?.baseline??l:e?.midline??u,n=t[0].textureBinding;for(const r of s){const s=r.startX*o,i=r.startY*o,e=(r.width+r.glyphWidthEnd)*o;t.push(new y(s,i+h*o,w(e,n),1))}}shapeBackground(t){const s=this._borderLineSizePx||0,i=(b+s)/2,e=this._borderLineSizePx?i:0,{xmin:o,ymin:h,xmax:n,ymax:r,x:a,y:f,width:c,height:d}=this.bounds,g=[o-p,h-p],_=[n+p,h-p],l=[o-p,r+p],u=[n+p,r+p],x=L([[g[0]-i,g[1]-i],[_[0]+i,_[1]-i],[g[0]+e,g[1]+e],[_[0]-e,_[1]+e]],t),y=L([[l[0]+e,l[1]-e],[u[0]-e,u[1]-e],[l[0]-i,l[1]+i],[u[0]+i,u[1]+i]],t),w=L([[g[0]-i,g[1]-i],[g[0]+e,g[1]+e],[l[0]-i,l[1]+i],[l[0]+e,l[1]-e]],t),M=L([[_[0]-e,_[1]+e],[_[0]+i,_[1]-i],[u[0]-e,u[1]-e],[u[0]+i,u[1]+i]],t),R={main:L([g,_,l,u],t),top:x,bot:y,left:w,right:M};return[new m(a,f,c+2*i,d+2*i),R]}get boundsT(){const t=this.bounds,s=r(a(),t.x,t.y);if(n(s,s,this._transform),this._hasRotation){const i=Math.max(t.width,t.height);return new m(s[0],s[1],i,i)}return new m(s[0],s[1],t.width,t.height)}_createBounds(t){let s=1/0,i=1/0,e=0,o=0;for(const r of t)s=Math.min(s,r.xTopLeft),i=Math.min(i,r.yTopLeft),e=Math.max(e,r.xBottomRight),o=Math.max(o,r.yBottomRight);const h=e-s,n=o-i;return new m(s+h/2,i+n/2,h,n)}_createGlyphTransform(t,s){const h=x*s.angle,n=o(),f=a();return i(n,n,r(f,s.xOffset,-s.yOffset)),s.useCIMAngleBehavior?e(n,n,h):(i(n,n,r(f,t.x,t.y)),e(n,n,h),i(n,n,r(f,-t.x,-t.y))),n}}class R{constructor(t,s,i,e,o,h){this.glyphWidthEnd=0,this.startX=0,this.startY=0,this.start=Math.max(0,Math.min(s,i)),this.end=Math.max(0,Math.max(s,i)),this.end<t.length&&(this.glyphWidthEnd=t[this.end].metrics.width),this.width=e,this.yMin=o,this.yMax=h}}const B=t=>10===t,T=t=>32===t;function v(t,s,i){const e=new Array,o=1/i.scale,h=i.maxLineWidth*o,n=s?t.length-1:0,r=s?-1:t.length,a=s?-1:1;let f=n,c=0,d=0,m=f,g=m,_=0,l=1/0,u=0;for(;f!==r;){const{code:s,metrics:i}=t[f],o=Math.abs(i.top);if(B(s)||T(s)||(l=Math.min(l,o),u=Math.max(u,o+i.height)),B(s))f!==n&&(e.push(new R(t,m,f-a,c,l===1/0?0:l,u)),l=1/0,u=0),c=0,m=f+a,g=f+a,d=0;else if(T(s))g=f+a,d=0,_=i.advance,c+=i.advance;else if(c>h){if(g!==m){const s=g-2*a;c-=_,e.push(new R(t,m,s,c-d,l,u)),l=1/0,u=0,m=g,c=d}else e.push(new R(t,m,f-a,c,l,u)),l=1/0,u=0,m=f,g=f,c=0;c+=i.advance,d+=i.advance}else c+=i.advance,d+=i.advance;f+=a}const x=new R(t,m,f-a,c,l,u);return x.start>=0&&x.end<t.length&&e.push(x),e}function j(t,s){let i=0;for(let h=0;h<t.length;h++){const{width:s}=t[h];i=Math.max(s,i)}const e="underline"===s.decoration?_:0,o=t[0].yMin;return{x:0,y:o,height:t[t.length-1].yMax+s.lineHeight*(t.length-1)+e-o,width:i}}function A(t,s){const i=s.scale,e=new Array,o=t.sdfPadding,{faceInfo:h,glyphs:n,isRightToLeft:r}=t,a=v(n,r,s),d=a.length?j(a,s):{y:0,height:0},m=f(s.horizontalAlignment),_=c(s.verticalAlignment),l=2===_?1:0,u=l?0:_-1,x=(1-l)*-d.y+u*(d.height/2)+l*-g;for(let f=0;f<a.length;f++){const{start:h,end:r,width:c}=a[f];let d=-1*(m+1)*(c/2)-o;const g=(t.isRightToLeft?a.length-1-f:f)*s.lineHeight+x-o;a[f].startX=d,a[f].startY=g;for(let t=h;t<=r;t++){const s=n[t];if(B(s.code))continue;const o=new y(d+s.metrics.left,g-s.metrics.top,s,i);d+=s.metrics.advance,e.push(o)}}return new M(e,a,s,h)}export{y as ShapedGlyph,M as ShapingInfo,A as shapeGlyphs};