File: Platform\iOS\CoreAnimationExtensions.cs
Web Access
Project: src\src\Core\src\Core.csproj (Microsoft.Maui)
using System;
using System.Collections.Generic;
using System.Numerics;
using CoreAnimation;
using CoreGraphics;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Handlers;
using ObjCRuntime;
using UIKit;
using static Microsoft.Maui.Primitives.Dimension;
 
namespace Microsoft.Maui
{
	internal static class CoreAnimationExtensions
	{
		internal static Matrix4x4 ToViewTransform(this CATransform3D transform) =>
			new Matrix4x4
			{
				M11 = (float)transform.M11,
				M12 = (float)transform.M12,
				M13 = (float)transform.M13,
				M14 = (float)transform.M14,
				M21 = (float)transform.M21,
				M22 = (float)transform.M22,
				M23 = (float)transform.M23,
				M24 = (float)transform.M24,
				M31 = (float)transform.M31,
				M32 = (float)transform.M32,
				M33 = (float)transform.M33,
				M34 = (float)transform.M34,
				Translation = new Vector3((float)transform.M41, (float)transform.M42, (float)transform.M43),
				M44 = (float)transform.M44
			};
 
		internal static Matrix4x4 GetViewTransform(this CALayer layer)
		{
			if (layer == null)
				return new Matrix4x4();
 
			var superTransform = layer.SuperLayer?.GetChildTransform() ?? CATransform3D.Identity;
 
			return layer.GetLocalTransform()
				.Concat(superTransform)
					.ToViewTransform();
		}
 
		internal static CATransform3D Prepend(this CATransform3D a, CATransform3D b) =>
			b.Concat(a);
 
		internal static CATransform3D GetLocalTransform(this CALayer layer)
		{
			return CATransform3D.Identity
				.Translate(
					layer.Position.X,
					layer.Position.Y,
					layer.ZPosition)
				.Prepend(layer.Transform)
				.Translate(
					-layer.AnchorPoint.X * layer.Bounds.Width,
					-layer.AnchorPoint.Y * layer.Bounds.Height,
					-layer.AnchorPointZ);
		}
 
		internal static CATransform3D GetChildTransform(this CALayer layer)
		{
			var childTransform = layer.SublayerTransform;
 
			if (childTransform.IsIdentity)
				return childTransform;
 
			return CATransform3D.Identity
				.Translate(
					layer.AnchorPoint.X * layer.Bounds.Width,
					layer.AnchorPoint.Y * layer.Bounds.Height,
					layer.AnchorPointZ)
				.Prepend(childTransform)
				.Translate(
					-layer.AnchorPoint.X * layer.Bounds.Width,
					-layer.AnchorPoint.Y * layer.Bounds.Height,
					-layer.AnchorPointZ);
		}
 
		internal static CATransform3D TransformToAncestor(this CALayer fromLayer, CALayer toLayer)
		{
			var transform = CATransform3D.Identity;
 
			CALayer? current = fromLayer;
			while (current != toLayer)
			{
				transform = transform.Concat(current.GetLocalTransform());
 
				current = current.SuperLayer;
				if (current == null)
					break;
 
				transform = transform.Concat(current.GetChildTransform());
			}
			return transform;
		}
	}
}