using RioJoy.Core.Overlay; using SkiaSharp; namespace RioJoy.Overlay; /// /// Generates a profile's cockpit wallpaper: renders a label set onto the overlay /// template's base image and writes a PNG. Resolves the template's /// relative to the template file's /// directory (so a regions.json + sibling riojoy.png work as a unit). /// The runtime calls this on profile activation; an editor can call it for preview. /// public sealed class ProfileWallpaperGenerator { private readonly SkiaOverlayRenderer _renderer; public ProfileWallpaperGenerator(SkiaOverlayRenderer? renderer = null) => _renderer = renderer ?? new SkiaOverlayRenderer(); /// /// Render onto the template's base image and write a /// PNG to ; returns the output path. /// /// /// Directory the template's relative /// is resolved against (normally the folder holding the regions.json). /// public string Generate( OverlayTemplate template, string templateDirectory, IDictionary labels, string outputPath, OverlayLayoutOptions? options = null) { if (template is null) throw new ArgumentNullException(nameof(template)); if (labels is null) throw new ArgumentNullException(nameof(labels)); if (string.IsNullOrWhiteSpace(outputPath)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(outputPath)); if (string.IsNullOrWhiteSpace(template.BaseImagePath)) throw new InvalidOperationException("OverlayTemplate.BaseImagePath is not set."); string basePath = Path.IsPathRooted(template.BaseImagePath) ? template.BaseImagePath : Path.Combine(templateDirectory, template.BaseImagePath); using SKBitmap baseImage = SKBitmap.Decode(basePath) ?? throw new InvalidOperationException($"Could not decode base image: {basePath}"); byte[] png = _renderer.RenderToPng(template, labels, baseImage, options); string? dir = Path.GetDirectoryName(Path.GetFullPath(outputPath)); if (!string.IsNullOrEmpty(dir)) Directory.CreateDirectory(dir); File.WriteAllBytes(outputPath, png); return outputPath; } }