|
using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Xml;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using SkiaSharp;
namespace Microsoft.Maui.Resizetizer
{
/// <summary>
/// Generates files relating to the Android splash screen:
/// - Resources/values/maui_colors.xml
/// - Resources/drawable/maui_splash_image.xml
/// - Resources/drawable-v31/maui_splash_image.xml
/// - Resources/[drawable]/[splash].png
/// </summary>
public class GenerateSplashAndroidResources : Task, ILogger
{
[Required]
public string IntermediateOutputPath { get; set; }
[Required]
public ITaskItem[] MauiSplashScreen { get; set; }
public string InputsFile { get; set; }
public override bool Execute()
{
Log.LogMessage(MessageImportance.Low, $"Splash Screen: Intermediate Path " + IntermediateOutputPath);
var splash = MauiSplashScreen?.FirstOrDefault();
if (splash is null)
{
Log.LogMessage(MessageImportance.Low, $"Splash Screen: No images found.");
return true;
}
try
{
var info = ResizeImageInfo.Parse(splash);
var resizer = new Resizer(info, IntermediateOutputPath, this);
WriteImages(resizer);
WriteColors(resizer);
WriteDrawable(resizer);
WriteDrawable_v31(resizer);
return !Log.HasLoggedErrors;
}
catch (Exception ex)
{
Log.LogError(null, "MAUI0000", null, null, 0, 0, 0, 0, ex.ToString());
return false;
}
}
static readonly XmlWriterSettings Settings = new XmlWriterSettings { Indent = true };
const string Namespace = "http://schemas.android.com/apk/res/android";
const string Comment = "This file was auto-generated by .NET MAUI.";
const float PreferredImageSize = 108f;
private void WriteImages(Resizer resizer)
{
if (resizer.Info.Resize)
{
foreach (var dpi in DpiPath.Android.Image)
{
Log.LogMessage(MessageImportance.Low, $"Splash Screen Resize: " + dpi);
resizer.Resize(dpi, InputsFile);
}
}
else
{
var dpi = DpiPath.Android.Original;
Log.LogMessage(MessageImportance.Low, $"Splash Screen Copy: " + dpi);
resizer.CopyFile(dpi, InputsFile);
}
}
void WriteColors(Resizer resizer)
{
var dir = Path.Combine(IntermediateOutputPath, "values");
Directory.CreateDirectory(dir);
var colorsFile = Path.Combine(dir, "maui_colors.xml");
Log.LogMessage(MessageImportance.Low, $"Splash Screen Colors: " + colorsFile);
using var writer = XmlWriter.Create(colorsFile, Settings);
writer.WriteComment(Comment);
writer.WriteStartElement("resources");
if (resizer.Info.Color is not null)
{
writer.WriteStartElement("color");
writer.WriteAttributeString("name", "maui_splash_color");
writer.WriteString(resizer.Info.Color.ToString());
writer.WriteEndElement();
}
writer.WriteEndDocument();
}
void WriteDrawable(Resizer resizer)
{
var dir = Path.Combine(IntermediateOutputPath, "drawable");
Directory.CreateDirectory(dir);
var drawableFile = Path.Combine(dir, "maui_splash_image.xml");
Log.LogMessage(MessageImportance.Low, $"Splash Screen Drawable: " + drawableFile);
using var writer = XmlWriter.Create(drawableFile, Settings);
writer.WriteComment(Comment);
writer.WriteStartElement("layer-list");
writer.WriteAttributeString("xmlns", "android", ns: null, value: Namespace);
writer.WriteStartElement("item");
writer.WriteStartElement("bitmap");
writer.WriteAttributeString("android", "gravity", Namespace, "center");
writer.WriteAttributeString("android", "src", Namespace, "@drawable/" + resizer.Info.OutputName);
writer.WriteAttributeString("android", "mipMap", Namespace, "true");
writer.WriteEndDocument();
}
void WriteDrawable_v31(Resizer resizer)
{
var size = CalculateScaledSize(resizer);
var dir = Path.Combine(IntermediateOutputPath, "drawable-v31");
Directory.CreateDirectory(dir);
var drawableFile = Path.Combine(dir, "maui_splash_image.xml");
Log.LogMessage(MessageImportance.Low, $"Splash Screen Drawable (v31): " + drawableFile);
using var writer = XmlWriter.Create(drawableFile, Settings);
writer.WriteComment(Comment);
writer.WriteStartElement("layer-list");
writer.WriteAttributeString("xmlns", "android", ns: null, value: Namespace);
writer.WriteStartElement("item");
writer.WriteAttributeString("android", "width", Namespace, size.Width.ToString("0", CultureInfo.InvariantCulture) + "dp");
writer.WriteAttributeString("android", "height", Namespace, size.Height.ToString("0", CultureInfo.InvariantCulture) + "dp");
writer.WriteAttributeString("android", "gravity", Namespace, "center");
writer.WriteStartElement("bitmap");
writer.WriteAttributeString("android", "gravity", Namespace, "fill");
writer.WriteAttributeString("android", "src", Namespace, "@drawable/" + resizer.Info.OutputName);
writer.WriteAttributeString("android", "mipMap", Namespace, "true");
writer.WriteEndDocument();
}
void ILogger.Log(string message)
{
Log?.LogMessage(message);
}
static SKSize CalculateScaledSize(Resizer resizer)
{
var size = resizer.BaseSize ?? resizer.GetOriginalSize();
var width = PreferredImageSize;
var height = PreferredImageSize;
if (size.Width > size.Height)
height = size.Height / size.Width * width;
else
width = size.Width / size.Height * height;
return new SKSize(width, height);
}
}
}
|