UNPKG

@doegis/core

Version:

DOE GIS API

3 lines (1 loc) 9.47 kB
import e from"../../../../../../core/Error.js";import t from"../../../../../../core/Logger.js";import{clamp as i}from"../../../../../../core/mathUtils.js";import{unwrap as o,isNone as r}from"../../../../../../core/maybe.js";import{pt2px as n}from"../../../../../../core/screenUtils.js";import{b as s}from"../../../../../../chunks/mat2d.js";import{c as a}from"../../../../../../chunks/mat2df32.js";import{Alignment as l}from"../../../../../../symbols/cim/enums.js";import{isMapAligned as h,getAlignmentFromPlacement as c,getXDirection as m,getYDirection as _}from"../../alignmentUtils.js";import{premultiplyAlphaRGBAArray as g}from"../../color.js";import{TEXT_PLACEMENT_PADDING as d}from"../../definitions.js";import{WGLGeometryType as f}from"../../enums.js";import{i8888to32 as u}from"../../number.js";import{LabelMaterialKey as p}from"../../materialKey/MaterialKey.js";import{smoothPaths as b,pathDivide as y}from"./segmentUtils.js";import x from"./WGLTextTemplate.js";const L=t.getLogger("esri.views.2d.engine.webgl.WGLLabelTemplate"),S=(t,i="mapview-labeling")=>L.error(new e(i,t)),v=1,P=0,w=4,M=25;function Z(e,t){const o=!!e.minScale&&t.scaleToZoom(e.minScale)||0;return i(o,0,25.5)}function k(e,t){const o=!!e.maxScale&&t.scaleToZoom(e.maxScale)||255;return i(o,0,25.5)}function A(e){const t=new Map;return i=>(t.has(i)||t.set(i,e(i)),t.get(i))}const B=A((e=>{let t=0;if(0===e)return 1/0;for(;!(e%2);)t++,e/=2;return t})),z=e=>Math.floor(127*e+127),C=e=>Math.floor(10*e),W=e=>Math.round(e*(254/360));class G extends x{constructor(e,t,i,o){super(e,i.font?.size,i.haloSize||0,i.font?.size,i.color&&g(i.color)||0,i.haloColor&&g(i.haloColor)||0,i.horizontalAlignment,i.verticalAlignment,h(t.labelPlacement)?l.MAP:l.SCREEN,i.font?.decoration,!1,i.angle||0,i.xoffset,i.yoffset,i.lineWidth,i.lineHeight,null,null,!1,null,null,i.backgroundColor&&g(i.backgroundColor),i.borderLineColor&&g(i.borderLineColor),i.borderLineSize),this._outLineLabelAngle=0,this._refPlacementPadding=0,this._refPlacementDirX=0,this._refPlacementDirY=0,this._refOffsetX=0,this._refOffsetY=0,this._zoomLevel=0,this.geometryType=f.LABEL,this._allowOverrun=t.allowOverrun??!1,this._repeatLabel=t.repeatLabel??!0,this._labelPosition=t.labelPosition??"curved";const r=Z(t,o),s=k(t,o),a=t.labelPlacement,[m,_]=c(a);this._xAlignD=m,this._yAlignD=_,this._minZoom=r,this._maxZoom=s,this._minBackgroundZoom=r,this._maxBackgroundZoom=s,this._refPlacementPadding=n(i.haloSize)+d,this._repeatLabelDistance=t.repeatLabelDistance?n(t.repeatLabelDistance):128;const u=p.load(e);u.sdf=!0,this._materialKey=u.data}static fromLabelClass(e,t){if("esriServerLinePlacementCenterAlong"===e.labelPlacement){const t=e.symbol;t.xoffset=0,t.yoffset=0,t.angle=0,t.font.decoration="none"}return new G(e.materialKey,e,e.symbol,t)}get _shapedBox(){return o(this._shapingInfo).bounds}setZoomLevel(e){this._zoomLevel=e}bindReferenceTemplate(e){let t=m(this._xAlignD),i=_(this._yAlignD);if(this._refOffsetX=0,this._refOffsetY=0,r(e))return void(this._refSymbolAndPlacementOffset=u(0,0,z(t),z(i)));if("circle"===e.boundsType&&(t||i)){const e=Math.sqrt(t*t+i*i);t/=e,i/=e}const o=Math.max(e.height,e.width),n=this._refPlacementPadding*w;this._refSymbolAndPlacementOffset=u(n,o,z(t),z(i)),this._referenceSize=o,this._refPlacementDirX=t,this._refPlacementDirY=i,this._refOffsetX=e.xOffset,this._refOffsetY=e.yOffset}_write(e,t){if(r(this._shapingInfo))return;const i=this._shapingInfo,o=t.getDisplayId(),n="esriGeometryPolygon"===t.geometryType?t.readLegacyCentroid():t.readLegacyGeometry();if(n)switch(this._current={out:e,inId:o,inShaping:i,zoomLevel:this._zoomLevel},"esriGeometryPolyline"===t.geometryType&&"curved"===this._labelPosition&&(this._borderLineColor||this._backgroundColor)&&L.warnOnce("TextSymbol properties 'borderLineColor', 'borderLineSize', and 'backgroundColor' are not supported in curved labels"),t.geometryType){case"esriGeometryPolyline":this._placeLineLabels(n);break;case"esriGeometryPoint":case"esriGeometryPolygon":this._placePointLabels(n);break;default:S(`Geometry of type ${t.geometryType} is not supported`)}}_isVisible(e,t){const i=C(this._current.zoomLevel);return C(e)<=i&&i<=C(t)}_placePointLabels(e){const{out:t,inId:i,inShaping:o}=this._current;this._writeGlyphs(t,i,e,o)}_placeLineLabels(e){const t=b(e.paths,this._current.inShaping.bounds.width),i=this._placeSubdivGlyphs.bind(this),o=(this._shapedBox.width+this._repeatLabelDistance)/(1<<v);for(const r of t)y(r,o,i,this._repeatLabel)}_placeSubdivGlyphs(e,t,i,o){const r=B(t),n=this._shapedBox.width/(1<<v),s=Math.sqrt(this._repeatLabelDistance)/(1<<v),a=Math.min(i,o-i),l=this._current.inShaping.isMultiline?M:Math.log2(a/(s+n/2)),h=0===t?l:Math.min(r,l),c=Math.max(this._minZoom,this._current.zoomLevel+v-h),m=this._current.zoomLevel-c,_=this._shapedBox.width/2*2**m;this._current.inShaping.isMultiline?0===t&&this._placeStraight(e,c):this._allowOverrun&&m<0?this._placeStraightAlong(e,this._minZoom):"parallel"===this._labelPosition?this._placeStraightAlong(e,c):"curved"===this._labelPosition&&this._placeCurved(e,c,_)}_placeStraight(e,t){const{out:i,inId:o,inShaping:r}=this._current,n=Math.ceil(e.angle*(180/Math.PI)%360),s=Math.ceil((e.angle*(180/Math.PI)+180)%360);this._outLineLabelAngle=W(n),this._writeGlyphs(i,o,e,r,t),this._outLineLabelAngle=W(s),this._writeGlyphs(i,o,e,r,t)}_placeCurved(e,t,i){const{out:o,inId:r}=this._current;o.metricStart(r,t,e.x,e.y,0,0,0,0);const n=e.clone(),s=e.angle*(180/Math.PI)%360,a=(e.angle*(180/Math.PI)+180)%360;this._outLineLabelAngle=W(s),this._placeFirst(n,t,1),this._placeBack(e,n,t,i,1),this._placeForward(e,n,t,i,1),this._outLineLabelAngle=W(a),this._placeFirst(n,t,0),this._placeBack(e,n,t,i,0),this._placeForward(e,n,t,i,0),o.metricEnd()}_placeStraightAlong(e,t){const{out:i,inId:o,inShaping:r}=this._current;i.metricStart(o,t,e.x,e.y,0,0,0,0);const n=e.clone(),l=e.angle*(180/Math.PI)%360,h=(e.angle*(180/Math.PI)+180)%360,c=r.glyphs.length>0&&(this._borderLineColor||this._backgroundColor);if(this._maxBackgroundZoom=M,this._minBackgroundZoom=Math.max(t,0),c){const t=p.load(this._materialKey);t.textureBinding=r.glyphs[0].textureBinding;const n=s(a(),-e.angle),[c,m]=r.shapeBackground(n);this._outLineLabelAngle=W(l),i.recordStart(o,t.data,this.geometryType,!0),this._writeBackgroundGeometry(i,o,e,c,m),i.recordEnd(),this._outLineLabelAngle=W(h),i.recordStart(o,t.data,this.geometryType,!0),this._writeBackgroundGeometry(i,o,e,c,m),i.recordEnd()}this._outLineLabelAngle=W(l),this._placeFirst(n,t,1,!0),this._outLineLabelAngle=W(h),this._placeFirst(n,t,0,!0),i.metricEnd()}_placeBack(e,t,i,o,r){const n=e.clone();let s=e.backwardLength+P;for(;n.prev()&&!(s>=o);)this._placeOnSegment(n,t,s,i,-1,r),s+=n.length+P}_placeForward(e,t,i,o,r){const n=e.clone();let s=e.remainingLength+P;for(;n.next()&&!(s>=o);)this._placeOnSegment(n,t,s,i,1,r),s+=n.length+P}_placeFirst(e,t,i,o=!1){const r=e,n=this._current.inShaping,s=n.glyphs,a=this._current.zoomLevel,{out:l,inId:h}=this._current;for(const c of s){const s=c.x>n.bounds.x?i:1-i,m=s*e.remainingLength+(1-s)*e.backwardLength,_=Math.abs(c.x+c.width/2-n.bounds.x),g=Math.max(0,a+Math.log2(_/(m+P))),d=Math.max(t,o?0:g);if(c.maxZoom=M,c.angle=e.angle+(1-i)*Math.PI,c.minZoom=d,this._writeGlyph(l,h,r.x,r.y,c),i&&this._isVisible(c.minZoom,c.maxZoom)){const e=c.bounds;l.metricBoxWrite(e.center[0],e.center[1],e.width,e.height)}}}_placeOnSegment(e,t,i,o,r,n){const s=this._current.inShaping.glyphs,{out:a,inId:l}=this._current,h=this._current.inShaping,c=this._current.zoomLevel,m=e.dx/e.length,_=e.dy/e.length,g={x:e.x+i*-r*m,y:e.y+i*-r*_};for(const d of s){const s=d.x>h.bounds.x?n:1-n;if(!(s&&1===r||!s&&-1===r))continue;const m=Math.abs(d.x+d.width/2-h.bounds.x),_=Math.max(0,c+Math.log2(m/i)-.1),f=Math.max(o,c+Math.log2(m/(i+e.length+P)));if(0!==_&&(d.angle=e.angle+(1-n)*Math.PI,d.minZoom=f,d.maxZoom=_,this._writeGlyph(a,l,g.x,g.y,d),n&&this._isVisible(d.minZoom,d.maxZoom))){const i=d.bounds,o=e.x-t.x,r=e.y-t.y;a.metricBoxWrite(i.center[0]+o,i.center[1]+r,i.width,i.height)}}}_writeGlyphs(e,t,i,o,r=this._minZoom){if(i.x<0||i.x>=512||i.y<0||i.y>=512)return;if(o.glyphs.length>0&&(this._borderLineColor||this._backgroundColor)){const r=p.load(this._materialKey);r.textureBinding=o.glyphs[0].textureBinding,e.recordStart(t,r.data,this.geometryType,!0),this._writeBackgroundGeometry(e,t,i,o.bounds,o.background),e.recordEnd()}const n=i.x+this._refOffsetX,s=i.y-this._refOffsetY;for(const c of o.glyphs)c.minZoom=r,c.maxZoom=this._maxZoom,this._writeGlyph(e,t,n,s,c);const a=this._refPlacementDirX,l=this._refPlacementDirY,h=o.boundsT;e.metricStart(t,r,n,s,a,l,this._referenceSize,this._materialKey),e.metricBoxWrite(h.center[0],h.center[1],h.width,h.height),e.metricEnd()}_writeVertexCommon(e,t,i,o){const r=this._color,n=this._haloColor,s=u(0,0,this._size,this._haloSize),a=Math.max(o.minZoom,this._minZoom),l=Math.min(o.maxZoom,this._maxZoom),h=u(C(a),C(l),this._outLineLabelAngle,0);e.vertexWrite(i),e.vertexWrite(t),e.vertexWrite(r),e.vertexWrite(n),e.vertexWrite(s),e.vertexWrite(this._refSymbolAndPlacementOffset),e.vertexWrite(h)}_writeBackgroundVertex(e,t,i,o,r,n){const s=u(0,0,this._size,this._haloSize),a=u(0,0,0,0),l=u(C(this._minBackgroundZoom),C(this._maxBackgroundZoom),this._outLineLabelAngle,1);e.vertexWrite(i),e.vertexWrite(t),e.vertexWrite(o),e.vertexWrite(a),e.vertexWrite(s),e.vertexWrite(this._refSymbolAndPlacementOffset),e.vertexWrite(l),e.vertexWrite(r),e.vertexWrite(n),e.vertexEnd()}}export{G as default};