File: DpiPath.cs
Web Access
Project: src\src\SingleProject\Resizetizer\src\Resizetizer.csproj (Microsoft.Maui.Resizetizer)
using System.Linq;
using SkiaSharp;
 
namespace Microsoft.Maui.Resizetizer
{
	internal enum ClipShape
	{
		None,
		// RoundedSquare,
		Circle,
		// Squircle
	}
 
	internal class DpiPath
	{
		public DpiPath(string path, decimal scale, string nameSuffix = null, string scaleSuffix = null, SKSize? size = null, string[] idioms = null, ClipShape clip = ClipShape.None)
		{
			Path = path;
			Scale = scale;
			NameSuffix = nameSuffix;
			ScaleSuffix = scaleSuffix;
			Size = size;
			Idioms = idioms;
			ClipShape = clip;
		}
 
		public string Path { get; set; }
 
		public decimal Scale { get; set; }
 
		public string FileSuffix =>
			string.Concat(NameSuffix, ScaleSuffix);
 
		public string NameSuffix { get; set; }
 
		public string ScaleSuffix { get; set; }
 
		public SKSize? Size { get; set; }
 
		public bool Optimize { get; set; } = true;
 
		public string[] Idioms { get; set; }
 
		public ClipShape ClipShape { get; set; }
 
		public static class Android
		{
			public static DpiPath Original =>
				new DpiPath("drawable", 1.0m);
 
			public static DpiPath[] Image
				=> new[]
				{
					new DpiPath("drawable-mdpi", 1.0m),
					new DpiPath("drawable-hdpi", 1.5m),
					new DpiPath("drawable-xhdpi", 2.0m),
					new DpiPath("drawable-xxhdpi", 3.0m),
					new DpiPath("drawable-xxxhdpi", 4.0m),
				};
 
			public static DpiPath[] AppIcon
				=> new[]
				{
					// legacy square
					new DpiPath("mipmap-mdpi", 1.0m, size: new SKSize(48, 48)),
					new DpiPath("mipmap-hdpi", 1.5m, size: new SKSize(48, 48)),
					new DpiPath("mipmap-xhdpi", 2.0m, size: new SKSize(48, 48)),
					new DpiPath("mipmap-xxhdpi", 3.0m, size: new SKSize(48, 48)),
					new DpiPath("mipmap-xxxhdpi", 4.0m, size: new SKSize(48, 48)),
					// legacy round for Android 7
					new DpiPath("mipmap-mdpi", 1.0m, "_round", size: new SKSize(48, 48), clip: ClipShape.Circle),
					new DpiPath("mipmap-hdpi", 1.5m, "_round", size: new SKSize(48, 48), clip: ClipShape.Circle),
					new DpiPath("mipmap-xhdpi", 2.0m, "_round", size: new SKSize(48, 48), clip: ClipShape.Circle),
					new DpiPath("mipmap-xxhdpi", 3.0m, "_round", size: new SKSize(48, 48), clip: ClipShape.Circle),
					new DpiPath("mipmap-xxxhdpi", 4.0m, "_round", size: new SKSize(48, 48), clip: ClipShape.Circle),
				};
 
			public static DpiPath[] AppIconParts
				=> new[]
				{
					new DpiPath("mipmap-mdpi", 1.0m, size: new SKSize(108, 108)),
					new DpiPath("mipmap-hdpi", 1.5m, size: new SKSize(108, 108)),
					new DpiPath("mipmap-xhdpi", 2.0m, size: new SKSize(108, 108)),
					new DpiPath("mipmap-xxhdpi", 3.0m, size: new SKSize(108, 108)),
					new DpiPath("mipmap-xxxhdpi", 4.0m, size: new SKSize(108, 108)),
				};
		}
 
		public static class Ios
		{
			public const string AppIconPath = "Assets.xcassets/{name}.appiconset";
 
			public static DpiPath Original =>
				new DpiPath("Resources", 1.0m);
 
			public static DpiPath[] Image
				=> new[]
				{
					new DpiPath("", 1.0m),
					new DpiPath("", 2.0m, null,"@2x"),
					new DpiPath("", 3.0m, null,"@3x"),
				};
 
			public static DpiPath[] AppIcon
				=> new[]
				{
					// Notification
					new DpiPath(AppIconPath, 2.0m, "20x20", "@2x", new SKSize(20, 20), new [] { "iphone", "ipad" }),
					new DpiPath(AppIconPath, 3.0m, "20x20", "@3x", new SKSize(20, 20), new [] { "iphone" }),
 
					// Settings
					new DpiPath(AppIconPath, 2.0m, "29x29", "@2x", new SKSize(29, 29), new [] { "iphone", "ipad" }),
					new DpiPath(AppIconPath, 3.0m, "29x29", "@3x", new SKSize(29, 29), new [] { "iphone" }),
 
					// Spotlight
					new DpiPath(AppIconPath, 2.0m, "40x40", "@2x", new SKSize(40, 40), new [] { "iphone", "ipad" }),
					new DpiPath(AppIconPath, 3.0m, "40x40", "@3x", new SKSize(40, 40), new [] { "iphone" }),
 
					// App Icon - iPhone
					new DpiPath(AppIconPath, 2.0m, "60x60", "@2x", new SKSize(60, 60), new [] { "iphone" }),
					new DpiPath(AppIconPath, 3.0m, "60x60", "@3x", new SKSize(60, 60), new [] { "iphone" }),
 
					// App Icon - ipad
					new DpiPath(AppIconPath, 2.0m, "76x76", "@2x", new SKSize(76, 76), new [] { "ipad" }),
					new DpiPath(AppIconPath, 2.0m, "83.5x83.5", "@2x", new SKSize(83.5f, 83.5f), new [] { "ipad" }),
 
					// App Store
					new DpiPath(AppIconPath, 1.0m, "ItunesArtwork", null, new SKSize(1024, 1024), new [] { "ios-marketing" }),
				};
		}
 
		public static class Windows
		{
			public const string OutputPath = "";
 
			public static DpiPath Original =>
				new DpiPath(OutputPath, 1.0m, null, ".scale-100");
 
			public static DpiPath[] Image
				=> new[]
				{
					new DpiPath(OutputPath, 1.00m, null, ".scale-100"),
					new DpiPath(OutputPath, 1.25m, null, ".scale-125"),
					new DpiPath(OutputPath, 1.50m, null, ".scale-150"),
					new DpiPath(OutputPath, 2.00m, null, ".scale-200"),
					new DpiPath(OutputPath, 4.00m, null, ".scale-400"),
				};
 
			public static DpiPath[] SplashScreen
				=> new[]
				{
					new DpiPath(OutputPath, 1.00m, "SplashScreen", ".scale-100", new SKSize(620, 300)),
					new DpiPath(OutputPath, 1.25m, "SplashScreen", ".scale-125", new SKSize(620, 300)),
					new DpiPath(OutputPath, 1.50m, "SplashScreen", ".scale-150", new SKSize(620, 300)),
					new DpiPath(OutputPath, 2.00m, "SplashScreen", ".scale-200", new SKSize(620, 300)),
					new DpiPath(OutputPath, 4.00m, "SplashScreen", ".scale-400", new SKSize(620, 300)),
				};
 
			// App Icon
			public static DpiPath[] Logo
				=> new[]
				{
					// normal
					new DpiPath(OutputPath, 1.00m, "Logo", ".scale-100", new SKSize(44, 44)),
					new DpiPath(OutputPath, 1.25m, "Logo", ".scale-125", new SKSize(44, 44)),
					new DpiPath(OutputPath, 1.50m, "Logo", ".scale-150", new SKSize(44, 44)),
					new DpiPath(OutputPath, 2.00m, "Logo", ".scale-200", new SKSize(44, 44)),
					new DpiPath(OutputPath, 4.00m, "Logo", ".scale-400", new SKSize(44, 44)),
					// targetsize
					new DpiPath(OutputPath, 1.00m, "Logo", ".targetsize-16", new SKSize(16, 16)),
					new DpiPath(OutputPath, 1.00m, "Logo", ".targetsize-24", new SKSize(24, 24)),
					new DpiPath(OutputPath, 1.00m, "Logo", ".targetsize-32", new SKSize(32, 32)),
					new DpiPath(OutputPath, 1.00m, "Logo", ".targetsize-48", new SKSize(48, 48)),
					new DpiPath(OutputPath, 1.00m, "Logo", ".targetsize-256", new SKSize(256, 256)),
					// altform-unplated_targetsize
					new DpiPath(OutputPath, 1.00m, "Logo", ".altform-unplated_targetsize-16", new SKSize(16, 16)),
					new DpiPath(OutputPath, 1.00m, "Logo", ".altform-unplated_targetsize-24", new SKSize(24, 24)),
					new DpiPath(OutputPath, 1.00m, "Logo", ".altform-unplated_targetsize-32", new SKSize(32, 32)),
					new DpiPath(OutputPath, 1.00m, "Logo", ".altform-unplated_targetsize-48", new SKSize(48, 48)),
					new DpiPath(OutputPath, 1.00m, "Logo", ".altform-unplated_targetsize-256", new SKSize(256, 256)),
					// altform-lightunplated_targetsize
					new DpiPath(OutputPath, 1.00m, "Logo", ".altform-lightunplated_targetsize-16", new SKSize(16, 16)),
					new DpiPath(OutputPath, 1.00m, "Logo", ".altform-lightunplated_targetsize-24", new SKSize(24, 24)),
					new DpiPath(OutputPath, 1.00m, "Logo", ".altform-lightunplated_targetsize-32", new SKSize(32, 32)),
					new DpiPath(OutputPath, 1.00m, "Logo", ".altform-lightunplated_targetsize-48", new SKSize(48, 48)),
					new DpiPath(OutputPath, 1.00m, "Logo", ".altform-lightunplated_targetsize-256", new SKSize(256, 256)),
				};
 
			// Store Logo
			public static DpiPath[] StoreLogo
				=> new[]
				{
					new DpiPath(OutputPath, 1.00m, "StoreLogo", ".scale-100", new SKSize(50, 50)),
					new DpiPath(OutputPath, 1.25m, "StoreLogo", ".scale-125", new SKSize(50, 50)),
					new DpiPath(OutputPath, 1.50m, "StoreLogo", ".scale-150", new SKSize(50, 50)),
					new DpiPath(OutputPath, 2.00m, "StoreLogo", ".scale-200", new SKSize(50, 50)),
					new DpiPath(OutputPath, 4.00m, "StoreLogo", ".scale-400", new SKSize(50, 50)),
				};
 
			// Small Tile
			public static DpiPath[] SmallTile
				=> new[]
				{
					new DpiPath(OutputPath, 1.00m, "SmallTile", ".scale-100", new SKSize(71, 71)),
					new DpiPath(OutputPath, 1.25m, "SmallTile", ".scale-125", new SKSize(71, 71)),
					new DpiPath(OutputPath, 1.50m, "SmallTile", ".scale-150", new SKSize(71, 71)),
					new DpiPath(OutputPath, 2.00m, "SmallTile", ".scale-200", new SKSize(71, 71)),
					new DpiPath(OutputPath, 4.00m, "SmallTile", ".scale-400", new SKSize(71, 71)),
				};
 
			// Medium Tile
			public static DpiPath[] MediumTile
				=> new[]
				{
					new DpiPath(OutputPath, 1.00m, "MediumTile", ".scale-100", new SKSize(150, 150)),
					new DpiPath(OutputPath, 1.25m, "MediumTile", ".scale-125", new SKSize(150, 150)),
					new DpiPath(OutputPath, 1.50m, "MediumTile", ".scale-150", new SKSize(150, 150)),
					new DpiPath(OutputPath, 2.00m, "MediumTile", ".scale-200", new SKSize(150, 150)),
					new DpiPath(OutputPath, 4.00m, "MediumTile", ".scale-400", new SKSize(150, 150)),
				};
 
			// Wide Tile
			public static DpiPath[] WideTile
				=> new[]
				{
					new DpiPath(OutputPath, 1.00m, "WideTile", ".scale-100", new SKSize(310, 150)),
					new DpiPath(OutputPath, 1.25m, "WideTile", ".scale-125", new SKSize(310, 150)),
					new DpiPath(OutputPath, 1.50m, "WideTile", ".scale-150", new SKSize(310, 150)),
					new DpiPath(OutputPath, 2.00m, "WideTile", ".scale-200", new SKSize(310, 150)),
					new DpiPath(OutputPath, 4.00m, "WideTile", ".scale-400", new SKSize(310, 150)),
				};
 
			// Large Tile
			public static DpiPath[] LargeTile
				=> new[]
				{
					new DpiPath(OutputPath, 1.00m, "LargeTile", ".scale-100", new SKSize(310, 310)),
					new DpiPath(OutputPath, 1.25m, "LargeTile", ".scale-125", new SKSize(310, 310)),
					new DpiPath(OutputPath, 1.50m, "LargeTile", ".scale-150", new SKSize(310, 310)),
					new DpiPath(OutputPath, 2.00m, "LargeTile", ".scale-200", new SKSize(310, 310)),
					new DpiPath(OutputPath, 4.00m, "LargeTile", ".scale-400", new SKSize(310, 310)),
				};
 
			// Badge
			public static DpiPath[] Badge
				=> new[]
				{
					new DpiPath(OutputPath, 1.00m, "Badge", ".scale-100", new SKSize(24, 24)),
					new DpiPath(OutputPath, 1.25m, "Badge", ".scale-125", new SKSize(24, 24)),
					new DpiPath(OutputPath, 1.50m, "Badge", ".scale-150", new SKSize(24, 24)),
					new DpiPath(OutputPath, 2.00m, "Badge", ".scale-200", new SKSize(24, 24)),
					new DpiPath(OutputPath, 4.00m, "Badge", ".scale-400", new SKSize(24, 24)),
				};
 
			// TODO: logo variants (targetsize, altform-unplated, altform-lightunplated)
 
			public static DpiPath[] AppIcon =>
				Logo.Union(
				StoreLogo).Union(
				SmallTile).Union(
				MediumTile).Union(
				WideTile).Union(
				LargeTile).ToArray();
		}
 
		public static class Wpf
		{
			public static DpiPath Original =>
				new DpiPath("", 4.0m);
 
			public static DpiPath[] Image
				=> new[]
				{
					new DpiPath("", 4.0m),
				};
 
			public static DpiPath[] AppIcon
				=> new[]
				{
					new DpiPath("", 4.0m),
				};
		}
 
 
		public static class Tizen
		{
			public static DpiPath Original => new DpiPath("res", 1.0m);
 
			public static DpiPath[] Image
				=> new[]
				{
				new DpiPath("res/contents/default_All-LDPI", 0.8m),
				new DpiPath("res/contents/default_All-MDPI", 1.0m),
				new DpiPath("res/contents/default_All-HDPI", 1.5m),
				new DpiPath("res/contents/default_All-XHDPI", 2.0m),
				new DpiPath("res/contents/default_All-XXHDPI", 3.0m),
				};
 
			public static DpiPath[] AppIcon
				=> new[]
				{
				new DpiPath("shared/res/hdpi", 1.0m, null, ".high", new SKSize(78, 78)),
				new DpiPath("shared/res/xhdpi", 1.0m, null, ".xhigh", new SKSize(117, 117)),
				};
 
			public static DpiPath[] SplashScreen
				=> new[]
				{
				new DpiPath("res/contents/default_All-MDPI", 1.0m),
				new DpiPath("res/contents/default_All-HDPI", 1.5m),
				};
 
		}
 
		public static DpiPath GetOriginal(string platform)
		{
			switch (platform.ToLowerInvariant())
			{
				case "ios":
					return DpiPath.Ios.Original;
				case "android":
					return DpiPath.Android.Original;
				case "uwp":
					return DpiPath.Windows.Original;
				case "wpf":
					return DpiPath.Wpf.Original;
				case "tizen":
					return DpiPath.Tizen.Original;
			}
 
			return null;
		}
 
		public static DpiPath[] GetDpis(string platform)
		{
			switch (platform.ToLowerInvariant())
			{
				case "ios":
					return DpiPath.Ios.Image;
				case "android":
					return DpiPath.Android.Image;
				case "uwp":
					return DpiPath.Windows.Image;
				case "wpf":
					return DpiPath.Wpf.Image;
				case "tizen":
					return DpiPath.Tizen.Image;
			}
 
			return null;
		}
 
		public static DpiPath[] GetAppIconDpis(string platform, string appIconName)
		{
			DpiPath[] result = null;
 
			switch (platform.ToLowerInvariant())
			{
				case "ios":
					result = DpiPath.Ios.AppIcon;
					break;
				case "android":
					result = DpiPath.Android.AppIcon;
					break;
				case "uwp":
					result = DpiPath.Windows.AppIcon;
					break;
				case "wpf":
					result = DpiPath.Wpf.AppIcon;
					break;
				case "tizen":
					result = DpiPath.Tizen.AppIcon;
					break;
			}
 
			foreach (var r in result)
			{
				if (!string.IsNullOrEmpty(r.Path))
					r.Path = r.Path.Replace("{name}", appIconName);
			}
 
			return result;
		}
	}
}