/* All material copyright ESRI, All Rights Reserved, unless otherwise specified. See https://js.arcgis.com/4.24/esri/copyright.txt for details. */ import{bidiText as t}from"../../core/BidiText.js";import e from"../../core/Logger.js";import{isNone as s,isSome as i}from"../../core/maybe.js";import r from"../../core/ObjectPool.js";import{pt2px as n}from"../../core/screenUtils.js";import{create as o,fromValues as a}from"../../geometry/support/aaBoundingRect.js";import{getBoundsXY as h}from"../../geometry/support/boundsUtils.js";import{polygonCentroid as l}from"../../geometry/support/centroid.js";import{isPoint as c,isPolygon as m,isPolyline as f,isExtent as u,isMultipoint as _}from"../../geometry/support/jsonUtils.js";import{SimpleGeometryCursor as d}from"./CIMEffects.js";import{getEffectOperator as p,getPlacementOperator as y}from"./CIMOperators.js";import{Placement as g}from"./CIMPlacements.js";import P from"./CIMResourceManager.js";import{LineCapStyle as x,LineJoinStyle as w}from"./enums.js";import M from"./Rect.js";import b from"./TextRasterizer.js";import{HAlign as S,VAlign as k}from"../../views/2d/engine/webgl/alignmentUtils.js";import{GLYPH_SIZE as C,MAGIC_LABEL_LINE_HEIGHT as R}from"../../views/2d/engine/webgl/definitions.js";import{shapeGlyphs as T}from"../../views/2d/engine/webgl/mesh/templates/shapingUtils.js";const I=Math.PI/180,v=10,L=e.getLogger("esri.symbols.cim.CIMSymbolDrawHelper");class z{constructor(t){this._t=t}static createIdentity(){return new z([1,0,0,0,1,0])}clone(){const t=this._t;return new z(t.slice())}transform(t){const e=this._t;return[e[0]*t[0]+e[1]*t[1]+e[2],e[3]*t[0]+e[4]*t[1]+e[5]]}static createScale(t,e){return new z([t,0,0,0,e,0])}scale(t,e){const s=this._t;return s[0]*=t,s[1]*=t,s[2]*=t,s[3]*=e,s[4]*=e,s[5]*=e,this}scaleRatio(){return Math.sqrt(this._t[0]*this._t[0]+this._t[1]*this._t[1])}static createTranslate(t,e){return new z([0,0,t,0,0,e])}translate(t,e){const s=this._t;return s[2]+=t,s[5]+=e,this}static createRotate(t){const e=Math.cos(t),s=Math.sin(t);return new z([e,-s,0,s,e,0])}rotate(t){return z.multiply(this,z.createRotate(t),this)}static multiply(t,e,s){const i=t._t,r=e._t,n=i[0]*r[0]+i[3]*r[1],o=i[1]*r[0]+i[4]*r[1],a=i[2]*r[0]+i[5]*r[1]+r[2],h=i[0]*r[3]+i[3]*r[4],l=i[1]*r[3]+i[4]*r[4],c=i[2]*r[3]+i[5]*r[4]+r[5],m=s._t;return m[0]=n,m[1]=o,m[2]=a,m[3]=h,m[4]=l,m[5]=c,s}invert(){const t=this._t;let e=t[0]*t[4]-t[1]*t[3];if(0===e)return new z([0,0,0,0,0,0]);e=1/e;const s=(t[1]*t[5]-t[2]*t[4])*e,i=(t[2]*t[3]-t[0]*t[5])*e,r=t[4]*e,n=-t[1]*e,o=-t[3]*e,a=t[0]*e;return new z([r,n,s,o,a,i])}}class F{constructor(t,e){this._transfos=[],this._sizeTransfos=[],this._geomUnitsPerPoint=1,this._placementPool=new r(g,null,null,100),this._earlyReturn=!1,this._mapRotation=0,this._resourceManager=t||new P,this._transfos.push(e||z.createIdentity()),this._sizeTransfos.push(e?e.scaleRatio():1)}setTransform(t,e){this._transfos=[t||z.createIdentity()],this._sizeTransfos=[e||(t?t.scaleRatio():1)]}setGeomUnitsPerPoint(t){this._geomUnitsPerPoint=t}transformPt(t){return this._transfos[this._transfos.length-1].transform(t)}transformSize(t){return t*this._sizeTransfos[this._sizeTransfos.length-1]}reverseTransformPt(t){return this._transfos[this._transfos.length-1].invert().transform(t)}reverseTransformSize(t){return t/this._sizeTransfos[this._sizeTransfos.length-1]}geomUnitsPerPoint(){return this.isEmbedded()?1:this._geomUnitsPerPoint}isEmbedded(){return this._transfos.length>1}back(){return this._transfos[this._transfos.length-1]}push(t,e){const s=e?t.scaleRatio():1;z.multiply(t,this.back(),t),this._transfos.push(t),this._sizeTransfos.push(this._sizeTransfos[this._sizeTransfos.length-1]*s)}pop(){this._transfos.splice(-1,1),this._sizeTransfos.splice(-1,1)}drawSymbol(t,e){if(t)switch(t.type){case"CIMPointSymbol":case"CIMLineSymbol":case"CIMPolygonSymbol":this.drawMultiLayerSymbol(t,e);break;case"CIMTextSymbol":this.drawTextSymbol(t,e)}}drawMultiLayerSymbol(t,e){if(!t)return;const s=t.symbolLayers;if(!s)return;const i=t.effects;if(i&&i.length>0){const t=this.executeEffects(i,e);if(t){let e=t.next();for(;e;)this.drawSymbolLayers(s,e),e=t.next()}}else this.drawSymbolLayers(s,e)}executeEffects(t,e){const s=this._resourceManager.geometryEngine;let i=new d(e);for(const r of t){const t=p(r);t&&(i=t.execute(i,r,this.geomUnitsPerPoint(),s))}return i}drawSymbolLayers(t,e){let s=t.length;for(;s--;){const i=t[s];if(!i||!1===i.enable)continue;const r=i.effects;if(r&&r.length>0){const t=this.executeEffects(r,e);if(t){let e=null;for(;(e=t.next())&&(this.drawSymbolLayer(i,e),!this._earlyReturn););}}else this.drawSymbolLayer(i,e);if(this._earlyReturn)return}}drawSymbolLayer(t,e){switch(t.type){case"CIMSolidFill":this.drawSolidFill(e,t.color);break;case"CIMHatchFill":this.drawHatchFill(e,t);break;case"CIMPictureFill":this.drawPictureFill(e,t);break;case"CIMGradientFill":this.drawGradientFill(e,t);break;case"CIMSolidStroke":this.drawSolidStroke(e,t.color,t.width,t.capStyle,t.joinStyle,t.miterLimit);break;case"CIMPictureStroke":this.drawPictureStroke(e,t);break;case"CIMGradientStroke":this.drawGradientStroke(e,t);break;case"CIMCharacterMarker":case"CIMPictureMarker":case"CIMVectorMarker":this.drawMarkerLayer(t,e)}}drawHatchFill(t,e){const s=this._buildHatchPolyline(e,t,this.geomUnitsPerPoint());s&&(this.pushClipPath(t),this.drawMultiLayerSymbol(e.lineSymbol,s),this.popClipPath())}drawPictureFill(t,e){}drawGradientFill(t,e){}drawPictureStroke(t,e){}drawGradientStroke(t,e){}drawMarkerLayer(t,e){const s=t.markerPlacement;if(s){const i=y(s);if(i){const r="CIMMarkerPlacementInsidePolygon"===s.type;r&&this.pushClipPath(e);const n=i.execute(e,s,this.geomUnitsPerPoint(),this._resourceManager.geometryEngine);if(n){let e=null;for(;(e=n.next())&&(this.drawMarker(t,e),!this._earlyReturn););}r&&this.popClipPath()}}else{const s=this._placementPool.acquire();if(c(e))s.tx=e.x,s.ty=e.y,this.drawMarker(t,s);else if(m(e))[s.tx,s.ty]=l(e),this.drawMarker(t,s);else for(const i of e.points)if(s.tx=i[0],s.ty=i[1],this.drawMarker(t,s),this._earlyReturn)break;this._placementPool.release(s)}}drawMarker(t,e){switch(t.type){case"CIMCharacterMarker":case"CIMPictureMarker":this.drawPictureMarker(t,e);break;case"CIMVectorMarker":this.drawVectorMarker(t,e)}}drawPictureMarker(t,e){if(!t)return;const i=this._resourceManager.getResource(t.url),r=t.size??10;if(s(i)||r<=0)return;const n=i.width,o=i.height;if(!n||!o)return;const a=n/o,h=t.scaleX??1,l=z.createIdentity(),c=t.anchorPoint;if(c){let e=c.x,s=c.y;"Absolute"!==t.anchorPointUnits&&(e*=r*a*h,s*=r),l.translate(-e,-s)}let m=t.rotation??0;t.rotateClockwise&&(m=-m),this._mapRotation&&(m+=this._mapRotation),m&&l.rotate(m*I);let f=t.offsetX??0,u=t.offsetY??0;if(f||u){if(this._mapRotation){const t=I*this._mapRotation,e=Math.cos(t),s=Math.sin(t),i=f*s+u*e;f=f*e-u*s,u=i}l.translate(f,u)}const _=this.geomUnitsPerPoint();1!==_&&l.scale(_,_);const d=e.getAngle();d&&l.rotate(d),l.translate(e.tx,e.ty),this.push(l,!1),this.drawImage(t.url,r,t.scaleX),this.pop()}drawVectorMarker(t,e){if(!t)return;const s=t.markerGraphics;if(!s)return;const i=t.size??10,r=t.frame,n=r?r.ymax-r.ymin:0,o=i&&n?i/n:1,a=z.createIdentity();r&&a.translate(.5*-(r.xmax+r.xmin),.5*-(r.ymax+r.ymin));const h=t.anchorPoint;if(h){let e=h.x,s=h.y;"Absolute"!==t.anchorPointUnits?r&&(e*=r.xmax-r.xmin,s*=r.ymax-r.ymin):(e/=o,s/=o),a.translate(-e,-s)}1!==o&&a.scale(o,o);let l=t.rotation??0;t.rotateClockwise&&(l=-l),this._mapRotation&&(l+=this._mapRotation),l&&a.rotate(l*I);let c=t.offsetX??0,m=t.offsetY??0;if(c||m){if(this._mapRotation){const t=I*this._mapRotation,e=Math.cos(t),s=Math.sin(t),i=c*s+m*e;c=c*e-m*s,m=i}a.translate(c,m)}const f=this.geomUnitsPerPoint();1!==f&&a.scale(f,f);const u=e.getAngle();u&&a.rotate(u),a.translate(e.tx,e.ty),this.push(a,t.scaleSymbolsProportionally);for(const _ of s)if(_&&_.symbol&&_.geometry||L.error("Invalid marker graphic",_),this.drawSymbol(_.symbol,_.geometry),this._earlyReturn)break;this.pop()}drawTextSymbol(t,e){if(!t)return;if(!c(e))return;if((t.height??10)<=0)return;const s=z.createIdentity();let i=t.angle??0;i=-i,i&&s.rotate(i*I);const r=t.offsetX??0,n=t.offsetY??0;(r||n)&&s.translate(r,n);const o=this.geomUnitsPerPoint();1!==o&&s.scale(o,o),s.translate(e.x,e.y),this.push(s,!1),this.drawText(t),this.pop()}_buildHatchPolyline(t,e,s){let i=(void 0!==t.separation?t.separation:4)*s,r=void 0!==t.rotation?t.rotation:0;if(0===i)return null;i<0&&(i=-i);let n=0;const a=.5*i;for(;n>a;)n-=i;for(;n<-a;)n+=i;const l=o();h(l,e),l[0]-=a,l[1]-=a,l[2]+=a,l[3]+=a;const c=[[l[0],l[1]],[l[0],l[3]],[l[2],l[3]],[l[2],l[1]]];for(;r>180;)r-=180;for(;r<0;)r+=180;const m=Math.cos(r*I),f=Math.sin(r*I),u=-i*f,_=i*m;let d,p,y,g;n=(void 0!==t.offsetX?t.offsetX*s:0)*f-(void 0!==t.offsetY?t.offsetY*s:0)*m,d=y=Number.MAX_VALUE,p=g=-Number.MAX_VALUE;for(const o of c){const t=o[0],e=o[1],s=m*t+f*e,i=-f*t+m*e;d=Math.min(d,s),y=Math.min(y,i),p=Math.max(p,s),g=Math.max(g,i)}y=Math.floor(y/i)*i;let P=m*d-f*y-u*n/i,x=f*d+m*y-_*n/i,w=m*p-f*y-u*n/i,M=f*p+m*y-_*n/i;const b=1+Math.round((g-y)/i),S=[];for(let o=0;o0))if(m(t))this._processPath(t.rings,0);else if(f(t))this._processPath(t.paths,0);else if(u(t)){const e=G(t);e&&this._processPath(e.rings,0)}else console.error("drawSolidFill Unexpected geometry type!")}drawSolidStroke(t,e,s){if(!t||this._clipCount>0)return;const i=.5*this.transformSize(s);if(m(t))this._processPath(t.rings,i);else if(f(t))this._processPath(t.paths,i);else if(u(t)){const e=G(t);e&&this._processPath(e.rings,i)}else console.error("drawSolidStroke unexpected geometry type!")}pushClipPath(t){this.drawSolidFill(t),++this._clipCount}popClipPath(){--this._clipCount}drawImage(t,e,s){let r=s*e,n=e;const o=this._resourceManager.getResource(t);!e&&i(o)&&(r=s*o.width,n=o.height),this._merge(this.transformPt([-r/2,-n/2]),0),this._merge(this.transformPt([-r/2,n/2]),0),this._merge(this.transformPt([r/2,-n/2]),0),this._merge(this.transformPt([r/2,n/2]),0)}drawText(t){this._textRasterizer||(this._textRasterizer=new b)}_processPath(t,e){if(t)for(const s of t){const t=s?s.length:0;if(t>1){this._merge(this.transformPt(s[0]),e);for(let i=1;ithis._xmax&&(this._xmax=t[0]+e),t[1]-ethis._ymax&&(this._ymax=t[1]+e)}}class j extends F{constructor(){super(...arguments),this._searchPoint=[0,0],this._searchDistPoint=0}hitTest(t,e,s,i,r,o){const a=o*n(1);this.setTransform(),this.setGeomUnitsPerPoint(a),this._searchPoint=[(t[0]+t[2])/2,(t[1]+t[3])/2],this._searchDistPoint=(t[2]-t[0])/2/a,this._textInfo=i;const h=e&&("CIMPointSymbol"===e.type&&"Map"!==e.angleAlignment||"CIMTextSymbol"===e.type);return this._mapRotation=h?r:0,this._earlyReturn=!1,this.drawSymbol(e,s),this._earlyReturn}drawSolidFill(t,e){this._hitTestFill(t)}drawHatchFill(t,e){this._hitTestFill(t)}drawPictureFill(t,e){this._hitTestFill(t)}drawGradientFill(t,e){this._hitTestFill(t)}drawSolidStroke(t,e,s,i,r,n){this._hitTestStroke(t,s)}drawPictureStroke(t,e){this._hitTestStroke(t,e.width)}drawGradientStroke(t,e){this._hitTestStroke(t,e.width)}drawMarkerLayer(t,e){t.markerPlacement&&"CIMMarkerPlacementInsidePolygon"===t.markerPlacement.type?this._hitTestFill(e):super.drawMarkerLayer(t,e)}pushClipPath(t){}popClipPath(){}drawImage(t,e,i){const r=this._resourceManager.getResource(t);if(s(r)||0===r.height||0===e)return;const n=e*this.geomUnitsPerPoint(),o=n*i*(r.width/r.height),a=this.reverseTransformPt(this._searchPoint),h=this._searchDistPoint;Math.abs(a[0])t.xTopLeft&&f-t.yBottomRight&&u<-t.yTopLeft){this._earlyReturn=!0;break}}_hitTestFill(t){let e=null;if(u(t)){const s=t;e=[[[s.xmin,s.ymin],[s.xmin,s.ymax],[s.xmax,s.ymax],[s.xmax,s.ymin],[s.xmin,s.ymin]]]}else if(m(t))e=t.rings;else{if(!f(t))return;e=t.paths}const s=this.reverseTransformPt(this._searchPoint);if(this._pointInPolygon(s,e)&&(this._earlyReturn=!0),!this._earlyReturn){const t=this.reverseTransformSize(this._searchDistPoint)*this.geomUnitsPerPoint();this._nearLine(s,e,t)&&(this._earlyReturn=!0)}}_hitTestStroke(t,e){let s=null;if(u(t)){const e=t;s=[[[e.xmin,e.ymin],[e.xmin,e.ymax],[e.xmax,e.ymax],[e.xmax,e.ymin],[e.xmin,e.ymin]]]}else if(m(t))s=t.rings;else{if(!f(t))return;s=t.paths}const i=this.reverseTransformPt(this._searchPoint),r=e*this.geomUnitsPerPoint(),n=this.reverseTransformSize(this._searchDistPoint)*this.geomUnitsPerPoint();this._nearLine(i,s,r/2+n)&&(this._earlyReturn=!0)}_pointInPolygon(t,e){let s=0;for(const i of e){const e=i.length;for(let r=1;rt[1]==n[1]>t[1])continue;(n[0]-e[0])*(t[1]-e[1])-(n[1]-e[1])*(t[0]-e[0])>0?s++:s--}}return 0!==s}_nearLine(t,e,s){for(const i of e){const e=i.length;for(let r=1;r-s&&i1){let r=this.transformPt(i[0]);s.moveTo(r[0],r[1]);for(let e=1;et?{spatialReference:t.spatialReference,rings:[[[t.xmin,t.ymin],[t.xmin,t.ymax],[t.xmax,t.ymax],[t.xmax,t.ymin],[t.xmin,t.ymin]]]}:null,E=t=>{switch(t){case"Left":return S.Left;case"Right":return S.Right;case"Center":return S.Center;case"Justify":return L.warnOnce("Horizontal alignment 'justify' is not implemented. Falling back to 'center'."),S.Center}},H=t=>{switch(t){case"Top":return k.Top;case"Center":return k.Center;case"Bottom":return k.Bottom;case"Baseline":return k.Baseline}},B=(t,e,s)=>{switch(t){case"ExtraLeading":return 1+e/s;case"Multiple":return e;case"Exact":return e/s}};export{F as CIMSymbolDrawHelper,I as C_DEG_TO_RAD,A as CanvasDrawHelper,U as EnvDrawHelper,j as HittestDrawHelper,z as Transformation,E as horizontalAlignment2HAlign,B as lineGapType2LineHeight,H as verticalAlignment2VAlign};