UNPKG

@arcgis/core

Version:

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

6 lines (5 loc) 7.31 kB
/* All material copyright ESRI, All Rights Reserved, unless otherwise specified. See https://js.arcgis.com/4.32/esri/copyright.txt for details. */ 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,VAlign as d}from"../../alignmentUtils.js";import m 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,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=i.code?h.width*e:i.metrics.width,a=i.code?h.height*e:i.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=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 char(){return String.fromCharCode(this._mosaic.code)}get code(){return this._mosaic.code}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,m=-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),m=Math.max(m,i)}const _=d-f,l=m-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:i,height:e}){this._texcoords={topLeft:[t,s],topRight:[t+i,s],bottomLeft:[t,s+e],bottomRight:[t+i,s+e]}}}const M=(t,s)=>({code:0,page:0,sdf:!0,rect:new m(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,i){this._rotation=0,this._decorate(t,s,i),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 e of t)e.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){if(!i.decoration||"none"===i.decoration||!t.length)return;const e=i.scale,o="underline"===i.decoration?u:x,h=t[0].textureBinding;for(const n of s){const s=n.startX*e,i=n.startY*e,r=(n.width+n.glyphWidthEnd)*e;t.push(new L(s,i+o*e,M(r,h),1))}}shapeBackground(t){const s=this._borderLineSizePx||0,i=(w+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,m=[o-y,h-y],_=[n+y,h-y],l=[o-y,r+y],u=[n+y,r+y],x=R([[m[0]-i,m[1]-i],[_[0]+i,_[1]-i],[m[0]+e,m[1]+e],[_[0]-e,_[1]+e]],t),p=R([[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),b=R([[m[0]-i,m[1]-i],[m[0]+e,m[1]+e],[l[0]-i,l[1]+i],[l[0]+e,l[1]-e]],t),L=R([[_[0]-e,_[1]+e],[_[0]+i,_[1]-i],[u[0]-e,u[1]-e],[u[0]+i,u[1]+i]],t),M={main:R([m,_,l,u],t),top:x,bot:p,left:b,right:L};return[new g(a,f,c+2*i,d+2*i),M]}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 g(s[0],s[1],i,i)}return new g(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 g(s+h/2,i+n/2,h,n)}_createGlyphTransform(t,s){const h=b*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 T{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 v=t=>10===t,j=t=>32===t;function A(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(v(s)||j(s)||(l=Math.min(l,o),u=Math.max(u,o+i.height)),v(s))f!==n&&(e.push(new T(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(j(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 T(t,m,s,c-d,l,u)),l=1/0,u=0,m=g,c=d}else e.push(new T(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 T(t,m,f-a,c,l,u);return x.start>=0&&x.end<t.length&&e.push(x),e}function z(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?l: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 O(t,s){const i=s.scale,e=new Array,{glyphs:o,isRightToLeft:h}=t,n=A(o,h,s),r=n.length?z(n,s):{x:0,y:0,height:0,width:0},a=f(s.horizontalAlignment),m=c(s.verticalAlignment),g=m===d.Baseline?1:0,_=g?0:m-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 d=-1*(a+1)*(c/2)-p;const m=(t.isRightToLeft?n.length-1-f:f)*s.lineHeight+l-p;n[f].startX=d,n[f].startY=m;for(let t=h;t<=r;t++){const s=o[t];if(v(s.code))continue;const h=new L(d+s.metrics.left,m-s.metrics.top,s,i);d+=s.metrics.advance,e.push(h)}}return new B(e,n,s)}export{L as ShapedGlyph,B as ShapingInfo,O as shapeGlyphs};