using System.Windows; using System.Windows.Media; using HandyControl.Expression.Drawing; namespace HandyControl.Expression.Media; public abstract class GeometrySource : IGeometrySource where TParameters : IGeometrySourceParameters { private bool _geometryInvalidated; protected Geometry CachedGeometry; public bool InvalidateGeometry(InvalidateGeometryReasons reasons) { if ((reasons & InvalidateGeometryReasons.TemplateChanged) != 0) CachedGeometry = null; if (!_geometryInvalidated) { _geometryInvalidated = true; return true; } return false; } public bool UpdateGeometry(IGeometrySourceParameters parameters, Rect layoutBounds) { var force = false; if (parameters is TParameters parameters1) { var rect = ComputeLogicalBounds(layoutBounds, parameters1); force |= LayoutBounds != layoutBounds || LogicalBounds != rect; if (_geometryInvalidated || force) { LayoutBounds = layoutBounds; LogicalBounds = rect; force |= UpdateCachedGeometry(parameters1); force |= ApplyGeometryEffect(parameters1, force); } } _geometryInvalidated = false; return force; } public Geometry Geometry { get; private set; } public Rect LayoutBounds { get; private set; } public Rect LogicalBounds { get; private set; } private bool ApplyGeometryEffect(IGeometrySourceParameters parameters, bool force) { var flag = false; var cachedGeometry = CachedGeometry; var geometryEffect = parameters.GetGeometryEffect(); if (geometryEffect != null) { if (force) { flag = true; geometryEffect.InvalidateGeometry(InvalidateGeometryReasons.ParentInvalidated); } if (geometryEffect.ProcessGeometry(CachedGeometry)) { flag = true; cachedGeometry = geometryEffect.OutputGeometry; } } if (!Equals(Geometry, cachedGeometry)) { flag = true; Geometry = cachedGeometry; } return flag; } protected virtual Rect ComputeLogicalBounds(Rect layoutBounds, IGeometrySourceParameters parameters) { return GeometryHelper.Inflate(layoutBounds, -parameters.GetHalfStrokeThickness()); } protected abstract bool UpdateCachedGeometry(TParameters parameters); }