/* All material copyright ESRI, All Rights Reserved, unless otherwise specified. See https://js.arcgis.com/4.24/esri/copyright.txt for details. */ import e from"../../Color.js";import{bidiText as t}from"../../core/BidiText.js";import{packFloatRGBA as r}from"../../core/floatRGBA.js";import{clone as o}from"../../core/lang.js";import a from"../../core/Logger.js";import{nextPowerOfTwo as i}from"../../core/mathUtils.js";import{isSome as s,isNone as n}from"../../core/maybe.js";import l from"../../core/RandomLCG.js";import{pt2px as c,px2pt as m}from"../../core/screenUtils.js";import{create as f,expandPointInPlace as y}from"../../geometry/support/aaBoundingRect.js";import{getBoundsXY as h}from"../../geometry/support/boundsUtils.js";import{Placement as M}from"./CIMPlacements.js";import{lineGapType2LineHeight as p,horizontalAlignment2HAlign as u,verticalAlignment2VAlign as S,EnvDrawHelper as d,Transformation as b,CanvasDrawHelper as g}from"./CIMSymbolDrawHelper.js";import{LineCapStyle as C,LineJoinStyle as I,BlockProgression as k,FontEffects as x,FontEncoding as w,FontType as P,GlyphHinting as L,TextReadingDirection as v,VerticalGlyphOrientation as F,BillBoardMode as D,TextureFilter as T,ExtremityPlacement as z}from"./enums.js";import{getValue as G,isCIMMarkerStrokePlacement as A}from"./utils.js";import{C_INFINITY as N}from"../../views/2d/engine/vectorTiles/GeometryUtils.js";import{GLYPH_SIZE as O,MAGIC_LABEL_LINE_HEIGHT as E,RANDOM_INSIDE_POLYGON_TEXTURE_SIZE as j}from"../../views/2d/engine/webgl/definitions.js";import{shapeGlyphs as R}from"../../views/2d/engine/webgl/mesh/templates/shapingUtils.js";const V=Math.PI,B=V/2,X=4,U=10,_=96/72,H=Math.PI/180,Y=a.getLogger("esri.symbols.cim.CIMSymbolHelper");function q(e){if(!e||!e.type)return null;let t;switch(e.type){case"cim":return e.data;case"web-style":return e;case"simple-marker":t=Z.fromSimpleMarker(e);break;case"picture-marker":t=Z.fromPictureMarker(e);break;case"simple-line":t=Z.fromSimpleLineSymbol(e);break;case"simple-fill":t=Z.fromSimpleFillSymbol(e);break;case"picture-fill":t=Z.fromPictureFillSymbol(e);break;case"text":t=Z.fromTextSymbol(e)}return{type:"CIMSymbolReference",symbol:t}}function W(e,t){switch(t.type){case"CIMSymbolReference":return W(e,t.symbol);case"CIMPointSymbol":{const r={x:0,y:0};e.drawSymbol(t,r);break}case"CIMLineSymbol":{const r={paths:[[[0,0],[0,1]]]};e.drawSymbol(t,r);break}case"CIMPolygonSymbol":{const r={rings:[[[0,0],[0,1],[0,0]]]};e.drawSymbol(t,r);break}case"CIMTextSymbol":{const r={x:0,y:0};e.drawSymbol(t,r);break}case"CIMVectorMarker":{const r=new M;e.drawMarker(t,r);break}}return e.envelope()}function $(e){if(!e)return 0;switch(e.type){case"CIMMarkerPlacementAlongLineSameSize":case"CIMMarkerPlacementAlongLineRandomSize":case"CIMMarkerPlacementAtExtremities":case"CIMMarkerPlacementAtMeasuredUnits":case"CIMMarkerPlacementAtRatioPositions":case"CIMMarkerPlacementOnLine":case"CIMMarkerPlacementOnVertices":return Math.abs(e.offset);default:return 0}}function J(e){if(!e)return 0;switch(e.type){case"CIMGeometricEffectArrow":return Math.abs(.5*e.width);case"CIMGeometricEffectBuffer":return Math.abs(e.size);case"CIMGeometricEffectExtension":case"CIMGeometricEffectRadial":return Math.abs(e.length);case"CIMGeometricEffectJog":return Math.abs(.5*e.length);case"CIMGeometricEffectMove":return Math.max(Math.abs(G(e.offsetX)),Math.abs(G(e.offsetY)));case"CIMGeometricEffectOffset":case"CIMGeometricEffectOffsetTangent":return Math.abs(e.offset);case"CIMGeometricEffectRegularPolygon":return Math.abs(e.radius);case"CIMGeometricEffectRotate":case"CIMGeometricEffectScale":default:return 0;case"CIMGeometricEffectTaperedPolygon":return.5*Math.max(Math.abs(e.fromWidth),Math.abs(e.toWidth));case"CIMGeometricEffectWave":return Math.abs(e.amplitude)}}function K(e){if(!e)return 0;let t=0;for(const r of e)t+=J(r);return t}class Q{getSymbolInflateSize(e,t,r,o,a){return e||(e=[0,0,0,0]),t?this._getInflateSize(e,t,r,o,a):e}static safeSize(e){const t=Math.max(Math.abs(e[0]),Math.abs(e[2])),r=Math.max(Math.abs(e[1]),Math.abs(e[3]));return Math.sqrt(t*t+r*r)}_vectorMarkerBounds(e,t,r,o){let a=!0;const i=f();if(t&&t.markerGraphics)for(const s of t.markerGraphics){const t=[0,0,0,0];s.geometry&&(h(i,s.geometry),t[0]=0,t[1]=0,t[2]=0,t[3]=0,this.getSymbolInflateSize(t,s.symbol,r,0,o),i[0]+=t[0],i[1]+=t[1],i[2]+=t[2],i[3]+=t[3],a?(e[0]=i[0],e[1]=i[1],e[2]=i[2],e[3]=i[3],a=!1):(e[0]=Math.min(e[0],i[0]),e[1]=Math.min(e[1],i[1]),e[2]=Math.max(e[2],i[2]),e[3]=Math.max(e[3],i[3])))}return e}_getInflateSize(e,t,r,o,a){if(fe(t)){const i=this._getLayersInflateSize(e,t.symbolLayers,r,o,a),s=K(t.effects);return s>0&&(i[0]-=s,i[1]-=s,i[2]+=s,i[3]+=s),i}return this._getTextInflatedSize(e,t,a)}_getLayersInflateSize(e,t,r,o,a){let i=!0;if(!t)return e;for(const n of t){if(!n)continue;let t=[0,0,0,0];switch(n.type){case"CIMSolidFill":case"CIMPictureFill":case"CIMHatchFill":case"CIMGradientFill":break;case"CIMSolidStroke":case"CIMPictureStroke":case"CIMGradientStroke":{const e=n;let r=e.width;e.capStyle===C.Square||e.joinStyle===I.Miter?r/=1.4142135623730951:r/=2,t[0]=-r,t[1]=-r,t[2]=r,t[3]=r;break}case"CIMCharacterMarker":case"CIMVectorMarker":case"CIMPictureMarker":{const e=n;if("CIMVectorMarker"===n.type){const e=n;if(t=this._vectorMarkerBounds(t,e,r,a),e.frame){const r=(e.frame.xmin+e.frame.xmax)/2,o=(e.frame.ymin+e.frame.ymax)/2;t[0]-=r,t[1]-=o,t[2]-=r,t[3]-=o;const a=e.size/(e.frame.ymax-e.frame.ymin);t[0]*=a,t[1]*=a,t[2]*=a,t[3]*=a}}else if("CIMPictureMarker"===n.type){const o=n,a=r.getResource(o.url);let i=1;s(a)&&a.height&&(i=a.width/a.height);const l=e.size/2,c=e.size*i*o.scaleX/2;t=[-c,-l,c,l]}else{const r=e.size/2;t=[-r,-r,r,r]}if(e.anchorPoint){let r,o;"Absolute"===e.anchorPointUnits?(r=e.anchorPoint.x,o=e.anchorPoint.y):(r=e.anchorPoint.x*(t[2]-t[0]),o=e.anchorPoint.y*(t[3]-t[1])),t[0]-=r,t[1]-=o,t[2]-=r,t[3]-=o}let i=G(e.rotation);if(e.rotateClockwise&&(i=-i),o&&(i-=o),i){const e=H*i,r=Math.cos(e),o=Math.sin(e),a=f([N,N,-N,-N]);y(a,[t[0]*r-t[1]*o,t[0]*o+t[1]*r]),y(a,[t[0]*r-t[3]*o,t[0]*o+t[3]*r]),y(a,[t[2]*r-t[1]*o,t[2]*o+t[1]*r]),y(a,[t[2]*r-t[3]*o,t[2]*o+t[3]*r]),t=a}let l=G(e.offsetX),c=G(e.offsetY);if(o){const e=H*o,t=Math.cos(e),r=Math.sin(e),a=l*r+c*t;l=l*t-c*r,c=a}t[0]+=l,t[1]+=c,t[2]+=l,t[3]+=c;const m=$(e.markerPlacement);m>0&&(t[0]-=m,t[1]-=m,t[2]+=m,t[3]+=m);break}}const l=K(n.effects);l>0&&(t[0]-=l,t[1]-=l,t[2]+=l,t[3]+=l),i?(e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],i=!1):(e[0]=Math.min(e[0],t[0]),e[1]=Math.min(e[1],t[1]),e[2]=Math.max(e[2],t[2]),e[3]=Math.max(e[3],t[3]))}return e}_getTextInflatedSize(e,r,o){const a=r.height??U;if(e[0]=-a/2,e[1]=-a/2,e[2]=a/2,e[3]=a/2,!o)return e;const i=o.get(r);if(!i)return e;const{text:s,mosaicItem:n}=i;if(!n||0===n.glyphMosaicItems.length)return e;const l=p(r.lineGapType,r.lineGap??0,a),c=t(s)[1],m=n.glyphMosaicItems,f=R(m,c,{scale:a/O,angle:G(r.angle),xOffset:G(r.offsetX),yOffset:G(r.offsetY),hAlign:u(r.horizontalAlignment),vAlign:S(r.verticalAlignment),maxLineWidth:512,lineHeight:E*Math.max(.25,Math.min(l||1,4)),decoration:r.font.decoration||"none",isCIM:!0}).boundsT;return e[0]=f.x-f.halfWidth,e[1]=-f.y-f.halfHeight,e[2]=f.x+f.halfWidth,e[3]=-f.y+f.halfHeight,e}}class Z{static getEnvelope(e,t){const r=new d(t);if(Array.isArray(e)){let t;for(const o of e)t?t.union(W(r,o)):t=W(r,o);return t}return W(r,e)}static getTextureAnchor(e,t){const r=this.getEnvelope(e,t);if(!r)return[0,0,0];const o=(r.x+.5*r.width)*_,a=-(r.y+.5*r.height)*_,i=r.width*_+2,s=r.height*_+2;return[o/i,a/s,s]}static rasterize(e,t,r,o,a=!0){const i=r||this.getEnvelope(t,o);if(!i)return[null,0,0,0,0];const s=(i.x+.5*i.width)*_,n=(i.y+.5*i.height)*_;e.width=i.width*_,e.height=i.height*_,r||(e.width+=2,e.height+=2);const l=e.getContext("2d"),c=b.createScale(_,-_);c.translate(.5*e.width-s,.5*e.height+n);const m=new g(l,o,c);switch(t.type){case"CIMPointSymbol":{const e={type:"point",x:0,y:0};m.drawSymbol(t,e);break}case"CIMVectorMarker":{const e=new M;m.drawMarker(t,e);break}}const f=l.getImageData(0,0,e.width,e.height),y=new Uint8Array(f.data);if(a){let e;for(let t=0;t.667?c(Math.round(m(t.width))):t.width,color:se(t.color)})}else!t||"line-marker"!==e.type||"cross"!==e.style&&"x"!==e.style||r.push({type:"CIMSolidStroke",enable:!0,width:t,color:se(a)});r.push({type:"CIMSolidFill",enable:!0,color:se(a)});const o={type:"CIMPolygonSymbol",symbolLayers:r};n={type:"CIMPointSymbol",symbolLayers:[{type:"CIMVectorMarker",enable:!0,rotation:G(-e.angle),size:G(e.size||6*t),offsetX:G(e.xoffset),offsetY:G(e.yoffset),frame:i,markerGraphics:[{type:"CIMMarkerGraphic",geometry:s,symbol:o}]}]}}return n}static fromCIMHatchFill(e){const t=e.separation??X,r=t/2,o=4,a=e.lineSymbol;let i=this._getLineSymbolPeriod(e.lineSymbol)||o;for(;i({type:"CIMMarkerGraphic",geometry:e,symbol:{type:"CIMPointSymbol",symbolLayers:[r]}}))),size:c}}static getFillColor(e){if(!e)return null;switch(e.type){case"CIMPolygonSymbol":if(e.symbolLayers)for(const t of e.symbolLayers){const e=Z.getFillColor(t);if(null!=e)return e}break;case"CIMTextSymbol":return Z.getFillColor(e.symbol);case"CIMSolidFill":return e.color}}static getStrokeColor(e){if(e)switch(e.type){case"CIMPolygonSymbol":case"CIMLineSymbol":if(e.symbolLayers)for(const t of e.symbolLayers){const e=Z.getStrokeColor(t);if(void 0!==e)return e}break;case"CIMTextSymbol":return Z.getStrokeColor(e.symbol);case"CIMSolidStroke":return e.color}}static getStrokeWidth(e){if(e)switch(e.type){case"CIMPolygonSymbol":case"CIMLineSymbol":if(e.symbolLayers)for(const t of e.symbolLayers){const e=Z.getStrokeWidth(t);if(void 0!==e)return e}break;case"CIMTextSymbol":return Z.getStrokeWidth(e.symbol);case"CIMSolidStroke":case"CIMGradientStroke":case"CIMPictureStroke":return e.width}}static getSize(e){if(e)switch(e.type){case"CIMTextSymbol":return e.height;case"CIMPointSymbol":{let t=0;if(e.symbolLayers)for(const r of e.symbolLayers)if(r)switch(r.type){case"CIMCharacterMarker":case"CIMPictureMarker":case"CIMVectorMarker":case"CIMObjectMarker3D":case"CIMglTFMarker3D":{const e=r.size;e>t&&(t=e);break}}return t}case"CIMLineSymbol":case"CIMPolygonSymbol":{let t=0;if(e.symbolLayers)for(const r of e.symbolLayers)if(r)switch(r.type){case"CIMSolidStroke":case"CIMPictureStroke":case"CIMGradientStroke":{const e=r.width;e>t&&(t=e);break}case"CIMCharacterMarker":case"CIMPictureMarker":case"CIMVectorMarker":case"CIMObjectMarker3D":case"CIMglTFMarker3D":if(A(r.markerPlacement)){const e=r.size;e>t&&(t=e)}}return t}}}static getMarkerScaleRatio(e){if(e&&"CIMVectorMarker"===e.type)if(!1!==e.scaleSymbolsProportionally&&e.frame){const t=e.frame.ymax-e.frame.ymin;return e.size/t}return 1}}class ee{static rasterizeSimpleFill(e,t,r){"solid"!==t&&"none"!==t&&"esriSFSSolid"!==t&&"esriSFSNull"!==t||console.error("Unexpected: style does not require rasterization");const o=i(Math.ceil(r)),a=he(t)?8*o:16*o,s=2*o;e.width=a,e.height=a;const n=e.getContext("2d");n.strokeStyle="#FFFFFF",n.lineWidth=o,n.beginPath(),"vertical"!==t&&"cross"!==t&&"esriSFSCross"!==t&&"esriSFSVertical"!==t||(n.moveTo(a/2,-s),n.lineTo(a/2,a+s)),"horizontal"!==t&&"cross"!==t&&"esriSFSCross"!==t&&"esriSFSHorizontal"!==t||(n.moveTo(-s,a/2),n.lineTo(a+s,a/2)),"forward-diagonal"!==t&&"diagonal-cross"!==t&&"esriSFSDiagonalCross"!==t&&"esriSFSForwardDiagonal"!==t||(n.moveTo(-s,-s),n.lineTo(a+s,a+s),n.moveTo(a-s,-s),n.lineTo(a+s,s),n.moveTo(-s,a-s),n.lineTo(s,a+s)),"backward-diagonal"!==t&&"diagonal-cross"!==t&&"esriSFSBackwardDiagonal"!==t&&"esriSFSDiagonalCross"!==t||(n.moveTo(a+s,-s),n.lineTo(-s,a+s),n.moveTo(s,-s),n.lineTo(-s,s),n.moveTo(a+s,a-s),n.lineTo(a-s,a+s)),n.stroke();const l=n.getImageData(0,0,e.width,e.height),c=new Uint8Array(l.data);let m;for(let i=0;ie?e.charAt(0).toLowerCase()+e.substr(1):e;if(e.primitiveName)for(const i of t)if(i.primitiveName===e.primitiveName){const t=a(i.propertyName);if(o&&o.push({cim:e,nocapPropertyName:t,value:e[t]}),i.expression&&(i.value=te.toValue(i.propertyName,i.expression)),r){let t=!1;for(const o of r)o.primitiveName===e.primitiveName&&(t=!0);t||r.push(i)}e[t]=i.value}switch(e.type){case"CIMPointSymbol":case"CIMLineSymbol":case"CIMPolygonSymbol":if(e.effects)for(const a of e.effects)te.applyOverrides(a,t,r,o);if(e.symbolLayers)for(const a of e.symbolLayers)te.applyOverrides(a,t,r,o);break;case"CIMTextSymbol":break;case"CIMSolidStroke":case"CIMSolidFill":case"CIMVectorMarker":if(e.effects)for(const a of e.effects)te.applyOverrides(a,t,r,o);if("CIMVectorMarker"===e.type&&e.markerGraphics)for(const a of e.markerGraphics)te.applyOverrides(a,t,r,o),te.applyOverrides(a.symbol,t,r,o)}}static restoreOverrides(e){for(const t of e)t.cim[t.nocapPropertyName]=t.value}static buildOverrideKey(e){let t="";for(const r of e)void 0!==r.value&&(t+=`${r.primitiveName}${r.propertyName}${JSON.stringify(r.value)}`);return t}static toValue(t,r){if("DashTemplate"===t)return r.split(" ").map((e=>Number(e)));if("Color"===t){const t=new e(r).toRgba();return t[3]*=255,t}return r}}const re=e=>{if(!e)return C.Butt;switch(e){case"butt":return C.Butt;case"square":return C.Square;case"round":return C.Round}},oe=e=>{if(!e)return I.Miter;switch(e){case"miter":return I.Miter;case"round":return I.Round;case"bevel":return I.Bevel}},ae=e=>{if(n(e))return"Center";switch(e){case"left":return"Left";case"right":return"Right";case"center":return"Center"}},ie=e=>{if(n(e))return"Center";switch(e){case"baseline":return"Baseline";case"top":return"Top";case"middle":return"Center";case"bottom":return"Bottom"}},se=e=>{if(!e)return[0,0,0,0];const{r:t,g:r,b:o,a}=e;return[t,r,o,255*a]},ne=(e,t)=>{const r=le(t),o=ce(e);return r&&o?`${r}-${o}`:`${r}${o}`},le=e=>{if(!e)return"";switch(e.toLowerCase()){case"bold":case"bolder":return"bold"}return""},ce=e=>{if(!e)return"";switch(e.toLowerCase()){case"italic":case"oblique":return"italic"}return""},me=(e,t)=>{const r="butt"===t;switch(e){case"dash":case"esriSLSDash":return r?[4,3]:[3,4];case"dash-dot":case"esriSLSDashDot":return r?[4,3,1,3]:[3,4,0,4];case"dot":case"esriSLSDot":return r?[1,3]:[0,4];case"long-dash":case"esriSLSLongDash":return r?[8,3]:[7,4];case"long-dash-dot":case"esriSLSLongDashDot":return r?[8,3,1,3]:[7,4,0,4];case"long-dash-dot-dot":case"esriSLSDashDotDot":return r?[8,3,1,3,1,3]:[7,4,0,4,0,4];case"short-dash":case"esriSLSShortDash":return r?[4,1]:[3,2];case"short-dash-dot":case"esriSLSShortDashDot":return r?[4,1,1,1]:[3,2,0,2];case"short-dash-dot-dot":case"esriSLSShortDashDotDot":return r?[4,1,1,1,1,1]:[3,2,0,2,0,2];case"short-dot":case"esriSLSShortDot":return r?[1,1]:[0,2];case"solid":case"esriSLSSolid":case"none":return Y.error("Unexpected: style does not require rasterization"),[0,0];default:return Y.error(`Tried to rasterize SLS, but found an unexpected style: ${e}!`),[0,0]}};function fe(e){return void 0!==e.symbolLayers}const ye=e=>{const t=100,r=50;let o,a;const i=e;if("circle"===i||"esriSMSCircle"===i){const e=.25;let t=Math.acos(1-e/r),i=Math.ceil(V/t/4);0===i&&(i=1),t=B/i,i*=4;const s=[];s.push([r,0]);for(let o=1;o"vertical"===e||"horizontal"===e||"cross"===e||"esriSFSCross"===e||"esriSFSVertical"===e||"esriSFSHorizontal"===e;export{Q as CIMSimbolInflatedSizeHelper,Z as CIMSymbolHelper,te as OverrideHelper,ee as SymbolHelper,me as slsDashToTemplateArray,q as symbolToCIM};