File: Graphics\ShapeDrawable.cs
Web Access
Project: src\src\Core\src\Core.csproj (Microsoft.Maui)
using System;
using System.Numerics;
 
namespace Microsoft.Maui.Graphics
{
	public class ShapeDrawable : IDrawable
	{
		WeakReference<IShapeView>? _shapeView;
		public ShapeDrawable()
		{
 
		}
 
		public ShapeDrawable(IShapeView? shape)
		{
			UpdateShapeView(shape);
		}
 
		internal IShapeView? ShapeView
		{
			get => _shapeView is not null && _shapeView.TryGetTarget(out var d) ? d : null;
			set
			{
				if (value is null)
				{
					_shapeView = null;
					return;
				}
 
				_shapeView = new(value);
			}
		}
 
		internal WindingMode WindingMode { get; set; }
		internal Matrix3x2? RenderTransform { get; set; }
 
		public void UpdateShapeView(IShapeView? shape)
		{
			ShapeView = shape;
		}
 
		public void UpdateWindingMode(WindingMode windingMode)
		{
			WindingMode = windingMode;
		}
 
		public void UpdateRenderTransform(Matrix3x2? renderTransform)
		{
			RenderTransform = renderTransform;
		}
 
		public void Draw(ICanvas canvas, RectF dirtyRect)
		{
			var rect = dirtyRect;
 
			IShape? shape = ShapeView?.Shape;
 
			if (shape == null)
				return;
 
			PathF? path = shape.PathForBounds(rect);
 
			if (path == null)
				return;
 
			ApplyTransform(path);
 
			DrawStrokePath(canvas, rect, path);
			DrawFillPath(canvas, rect, path);
		}
 
		void DrawStrokePath(ICanvas canvas, RectF dirtyRect, PathF path)
		{
			if (ShapeView == null || ShapeView.Shape == null || ShapeView.StrokeThickness <= 0 || ShapeView.Stroke == null)
				return;
 
			canvas.SaveState();
 
			// Set StrokeThickness
			float strokeThickness = (float)ShapeView.StrokeThickness;
			canvas.StrokeSize = strokeThickness;
 
			// Set Stroke
			var stroke = ShapeView.Stroke;
 
			// TODO: Add Paint support for Stroke in Microsoft.Maui.Graphics.
			// For now, only support a solid color.
			canvas.StrokeColor = stroke.ToColor();
 
			// Set StrokeLineCap
			var strokeLineCap = ShapeView.StrokeLineCap;
			canvas.StrokeLineCap = strokeLineCap;
 
			// Set StrokeLineJoin
			var strokeLineJoin = ShapeView.StrokeLineJoin;
			canvas.StrokeLineJoin = strokeLineJoin;
 
			// Set StrokeDashPattern
			var strokeDashPattern = ShapeView.StrokeDashPattern;
			canvas.StrokeDashPattern = strokeDashPattern;
 
			// Set StrokeDashOffset	
			var strokeDashOffset = ShapeView.StrokeDashOffset;
			canvas.StrokeDashOffset = strokeDashOffset;
 
			// Set StrokeMiterLimit
			var strokeMiterLimit = ShapeView.StrokeMiterLimit;
			canvas.MiterLimit = strokeMiterLimit;
 
			canvas.DrawPath(path);
 
			canvas.RestoreState();
		}
 
		void DrawFillPath(ICanvas canvas, RectF dirtyRect, PathF path)
		{
			if (ShapeView == null || ShapeView.Shape == null)
				return;
 
			canvas.SaveState();
 
			canvas.FillColor = Colors.Transparent;
 
			ClipPath(canvas, path);
 
			// Set Fill
			var fillPaint = ShapeView.Fill ?? ShapeView.Background;
 
			if (fillPaint != null)
				canvas.SetFillPaint(fillPaint, dirtyRect);
 
			canvas.FillPath(path);
 
			canvas.RestoreState();
		}
 
		void ClipPath(ICanvas canvas, PathF path)
		{
			canvas.ClipPath(path, WindingMode);
		}
 
		void ApplyTransform(PathF path)
		{
			if (RenderTransform == null)
				return;
 
			path.Transform(RenderTransform.Value);
		}
	}
}