UNPKG

@arcgis/core

Version:

ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API

6 lines (5 loc) 7.3 kB
/* All material copyright ESRI, All Rights Reserved, unless otherwise specified. See https://js.arcgis.com/4.33/esri/copyright.txt for details. */ import{fromRotation as t,multiply as s,translate as e,rotate as i}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,VAlign as m}from"../../alignmentUtils.js";import d from"../../Rect.js";import g from"../../collisions/BoundingBox.js";const _=22,l=4,u=_+l,x=_-6,p=3,b=Math.PI/180,y=8,w=1.5;class L{constructor(t,s,e,i){this._rotationT=o(),this._xBounds=0,this._yBounds=0,this.minZoom=0,this.maxZoom=255,this._bounds=null;const h=e.rect,n=new Float32Array(8);t*=i,s*=i;const r=e.code?h.width*i:e.metrics.width,a=e.code?h.height*i:e.metrics.height;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=i,this._mosaic=e,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 char(){return String.fromCharCode(this._mosaic.code)}get code(){return this._mosaic.code}get bounds(){if(!this._bounds){const{height:t,width:e}=this._mosaic.metrics,i=e*this._scale,n=Math.abs(t)*this._scale,r=new Float32Array(8);r[0]=this.x,r[1]=this.y,r[2]=this.x+i,r[3]=this.y,r[4]=this.x,r[5]=this.y+n,r[6]=this.x+i,r[7]=this.y+n;const a=s(o(),this._rotationT,this._transform);h(r,r,a);let f=1/0,c=1/0,m=-1/0,d=-1/0;for(let s=0;s<4;s++){const t=r[2*s],e=r[2*s+1];f=Math.min(f,t),c=Math.min(c,e),m=Math.max(m,t),d=Math.max(d,e)}const _=m-f,l=d-c,u=f+_/2,x=c+l/2;this._bounds=new g(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:e,height:i}){this._texcoords={topLeft:[t,s],topRight:[t+e,s],bottomLeft:[t,s+i],bottomRight:[t+e,s+i]}}}const M=(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 R(t,s){return t.forEach((t=>n(t,t,s))),{topLeft:t[0],topRight:t[1],bottomLeft:t[2],bottomRight:t[3]}}class B{constructor(t,s,e){this._rotation=0,this._decorate(t,s,e),this.glyphs=t,this.bounds=this._createBounds(t),this.isMultiline=s.length>1,this._hasRotation=0!==e.angle,this._transform=this._createGlyphTransform(this.bounds,e),this._borderLineSizePx=e.borderLineSizePx,(e.borderLineSizePx||e.hasBackground)&&([this.bounds,this.textBox]=this.shapeBackground(this._transform));for(const i of t)i.setTransform(this._transform)}setRotation(e){if(0===e&&0===this._rotation)return;this._rotation=e;const i=this._transform,h=t(o(),e);s(i,h,i);for(const t of this.glyphs)t.setTransform(this._transform)}_decorate(t,s,e){if(!e.decoration||"none"===e.decoration||!t.length)return;const i=e.scale,o="underline"===e.decoration?u:x,h=t[0].textureBinding;for(const n of s){const s=n.startX*i,e=n.startY*i,r=(n.width+n.glyphWidthEnd)*i;t.push(new L(s,e+o*i,M(r,h),1))}}shapeBackground(t){const s=this._borderLineSizePx||0,e=(w+s)/2,i=this._borderLineSizePx?e:0,{xmin:o,ymin:h,xmax:n,ymax:r,x:a,y:f,width:c,height:m}=this.bounds,d=[o-y,h-y],_=[n+y,h-y],l=[o-y,r+y],u=[n+y,r+y],x=R([[d[0]-e,d[1]-e],[_[0]+e,_[1]-e],[d[0]+i,d[1]+i],[_[0]-i,_[1]+i]],t),p=R([[l[0]+i,l[1]-i],[u[0]-i,u[1]-i],[l[0]-e,l[1]+e],[u[0]+e,u[1]+e]],t),b=R([[d[0]-e,d[1]-e],[d[0]+i,d[1]+i],[l[0]-e,l[1]+e],[l[0]+i,l[1]-i]],t),L=R([[_[0]-i,_[1]+i],[_[0]+e,_[1]-e],[u[0]-i,u[1]-i],[u[0]+e,u[1]+e]],t),M={main:R([d,_,l,u],t),top:x,bot:p,left:b,right:L};return[new g(a,f,c+2*e,m+2*e),M]}get boundsT(){const t=this.bounds,s=r(a(),t.x,t.y);if(n(s,s,this._transform),this._hasRotation){const e=Math.max(t.width,t.height);return new g(s[0],s[1],e,e)}return new g(s[0],s[1],t.width,t.height)}_createBounds(t){let s=1/0,e=1/0,i=0,o=0;for(const r of t)s=Math.min(s,r.xTopLeft),e=Math.min(e,r.yTopLeft),i=Math.max(i,r.xBottomRight),o=Math.max(o,r.yBottomRight);const h=i-s,n=o-e;return new g(s+h/2,e+n/2,h,n)}_createGlyphTransform(t,s){const h=b*s.angle,n=o(),f=a();return e(n,n,r(f,s.xOffset,-s.yOffset)),s.useCIMAngleBehavior?i(n,n,h):(e(n,n,r(f,t.x,t.y)),i(n,n,h),e(n,n,r(f,-t.x,-t.y))),n}}class T{constructor(t,s,e,i,o,h){this.glyphWidthEnd=0,this.startX=0,this.startY=0,this.start=Math.max(0,Math.min(s,e)),this.end=Math.max(0,Math.max(s,e)),this.end<t.length&&(this.glyphWidthEnd=t[this.end].metrics.width),this.width=i,this.yMin=o,this.yMax=h}}const v=t=>10===t,j=t=>32===t;function A(t,s,e){const i=new Array,o=1/e.scale,h=e.maxLineWidth*o,n=s?t.length-1:0,r=s?-1:t.length,a=s?-1:1;let f=n,c=0,m=0,d=f,g=d,_=0,l=1/0,u=0;for(;f!==r;){const{code:s,metrics:e}=t[f],o=Math.abs(e.top);if(v(s)||j(s)||(l=Math.min(l,o),u=Math.max(u,o+e.height)),v(s))f!==n&&(i.push(new T(t,d,f-a,c,l===1/0?0:l,u)),l=1/0,u=0),c=0,d=f+a,g=f+a,m=0;else if(j(s))g=f+a,m=0,_=e.advance,c+=e.advance;else if(c>h){if(g!==d){const s=g-2*a;c-=_,i.push(new T(t,d,s,c-m,l,u)),l=1/0,u=0,d=g,c=m}else i.push(new T(t,d,f-a,c,l,u)),l=1/0,u=0,d=f,g=f,c=0;c+=e.advance,m+=e.advance}else c+=e.advance,m+=e.advance;f+=a}const x=new T(t,d,f-a,c,l,u);return x.start>=0&&x.end<t.length&&i.push(x),i}function z(t,s){let e=0;for(let h=0;h<t.length;h++){const{width:s}=t[h];e=Math.max(s,e)}const i="underline"===s.decoration?l:0,o=t[0].yMin;return{x:0,y:o,height:t[t.length-1].yMax+s.lineHeight*(t.length-1)+i-o,width:e}}function O(t,s){const e=s.scale,i=new Array,{glyphs:o,isRightToLeft:h}=t,n=A(o,h,s),r=n.length?z(n,s):{y:0,height:0},a=f(s.horizontalAlignment),d=c(s.verticalAlignment),g=d===m.Baseline?1:0,_=g?0:d-1,l=(1-g)*-r.y+_*(r.height/2)+-22*(g?1:0);for(let f=0;f<n.length;f++){const{start:h,end:r,width:c}=n[f];let m=-1*(a+1)*(c/2)-p;const d=(t.isRightToLeft?n.length-1-f:f)*s.lineHeight+l-p;n[f].startX=m,n[f].startY=d;for(let t=h;t<=r;t++){const s=o[t];if(v(s.code))continue;const h=new L(m+s.metrics.left,d-s.metrics.top,s,e);m+=s.metrics.advance,i.push(h)}}return new B(i,n,s)}export{L as ShapedGlyph,B as ShapingInfo,O as shapeGlyphs};