@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
6 lines (5 loc) • 3.64 kB
JavaScript
/*
All material copyright ESRI, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/4.32/esri/copyright.txt for details.
*/
import{isLineBreak as t,isWhiteSpace as e,allowsIdeographicBreak as i,hasVerticalOrientation as o}from"./ScriptUtils.js";import s from"../webgl/Rect.js";const c=24,h=17;class l{constructor(t,e,i,o,s,c,h){this._glyphItems=t,this._maxWidth=e,this._lineHeight=i,this._letterSpacing=o,this._hAnchor=s,this._vAnchor=c,this._justify=h}getShaping(s,c,h){const l=this._letterSpacing,n=this._lineHeight,a=this._justify,r=this._maxWidth,m=[];let f=0,p=0;for(const t of s){const e=t.codePointAt(0);if(null==e)continue;const i=h&&o(e);let s;for(const t of this._glyphItems)if(s=t[e],s)break;m.push({codePoint:e,x:f,y:p,vertical:i,glyphMosaicItem:s}),s&&(f+=s.metrics.advance+l)}let g=f;if(r>0){g=f/Math.max(1,Math.ceil(f/r))}const y=s.includes(""),d=[],x=m.length;for(let e=0;e<x-1;e++){const o=m[e].codePoint,s=i(o);if(t(o)||s){let t=0;if(10===o)t-=1e4;else if(s&&y)t+=150;else{40!==o&&65288!==o||(t+=50);const i=m[e+1].codePoint;41!==i&&65289!==i||(t+=50)}d.push(this._buildBreak(e+1,m[e].x,g,d,t,!1))}}const u=this._optimalBreaks(this._buildBreak(x,f,g,d,0,!0));let M=0;const _=c?-n:n;let I=0;for(let t=0;t<u.length;t++){const i=u[t];let o=I;for(;o<i&&e(m[o].codePoint);)m[o].glyphMosaicItem=null,++o;let s=i-1;for(;s>o&&e(m[s].codePoint);)m[s].glyphMosaicItem=null,--s;if(o<=s){const t=m[o].x;for(let i=o;i<=s;i++)m[i].x-=t,m[i].y=p;let e=m[s].x;m[s].glyphMosaicItem&&(e+=m[s].glyphMosaicItem.metrics.advance),M=Math.max(e,M),a&&this._applyJustification(m,o,s)}I=i,p+=_}if(m.length>0){const t=u.length-1,e=(a-this._hAnchor)*M;let i=(-this._vAnchor*(t+1)+.5)*n;c&&t&&(i+=t*n);for(const o of m)o.x+=e,o.y+=i}return m.filter((t=>t.glyphMosaicItem))}static getTextBox(t,e){if(!t.length)return null;let i=1/0,o=1/0,s=0,c=0;for(const l of t){const t=l.glyphMosaicItem.metrics.advance,n=l.x,a=l.y-h,r=n+t,m=a+e;i=Math.min(i,n),s=Math.max(s,r),o=Math.min(o,a),c=Math.max(c,m)}return{x:i,y:o,width:s-i,height:c-o}}static getBox(t){if(!t.length)return null;let e=1/0,i=1/0,o=0,s=0;for(const c of t){const{height:t,left:h,top:l,width:n}=c.glyphMosaicItem.metrics,a=c.x,r=c.y-(t-Math.abs(l)),m=a+n+h,f=r+t;e=Math.min(e,a),o=Math.max(o,m),i=Math.min(i,r),s=Math.max(s,f)}return{x:e,y:i,width:o-e,height:s-i}}static addDecoration(t,e){const i=t.length;if(0===i)return;const o=3;let c=t[0].x+t[0].glyphMosaicItem.metrics.left,h=t[0].y;for(let n=1;n<i;n++){const i=t[n];if(i.y!==h){const l=t[n-1].x+t[n-1].glyphMosaicItem.metrics.left+t[n-1].glyphMosaicItem.metrics.width;t.push({codePoint:0,x:c,y:h+e-o,vertical:!1,glyphMosaicItem:{sdf:!0,rect:new s(4,0,4,8),metrics:{width:l-c,height:2+2*o,left:0,top:0,advance:0},page:0,code:0}}),h=i.y,c=i.x+i.glyphMosaicItem.metrics.left}}const l=t[i-1].x+t[i-1].glyphMosaicItem.metrics.left+t[i-1].glyphMosaicItem.metrics.width;t.push({codePoint:0,x:c,y:h+e-o,vertical:!1,glyphMosaicItem:{sdf:!0,rect:new s(4,0,4,8),metrics:{width:l-c,height:2+2*o,left:0,top:0,advance:0},page:0,code:0}})}_breakScore(t,e,i,o){const s=(t-e)*(t-e);return o?t<e?s/2:2*s:s+Math.abs(i)*i}_buildBreak(t,e,i,o,s,c){let h=null,l=this._breakScore(e,i,s,c);for(const n of o){const t=e-n.x,o=this._breakScore(t,i,s,c)+n.score;o<=l&&(h=n,l=o)}return{index:t,x:e,score:l,previousBreak:h}}_optimalBreaks(t){return t?this._optimalBreaks(t.previousBreak).concat(t.index):[]}_applyJustification(t,e,i){const o=t[i],s=o.vertical?c:o.glyphMosaicItem?o.glyphMosaicItem.metrics.advance:0,h=(o.x+s)*this._justify;for(let c=e;c<=i;c++)t[c].x-=h}}export{l as TextShaping,h as sdfGlyphBaseline,c as sdfGlyphSize};