using RioJoy.Core.Overlay; using RioJoy.Overlay; using SkiaSharp; using Xunit; namespace RioJoy.Core.Tests.Overlay; public class SkiaOverlayRendererTests { private static SKBitmap SolidBase(int w, int h, SKColor color) { var bmp = new SKBitmap(w, h); using var canvas = new SKCanvas(bmp); canvas.Clear(color); canvas.Flush(); return bmp; } private static bool HasLightPixel(SKBitmap bmp, int x, int y, int w, int h) { for (int yy = y; yy < y + h; yy++) for (int xx = x; xx < x + w; xx++) { SKColor p = bmp.GetPixel(xx, yy); if (p.Red > 40 || p.Green > 40 || p.Blue > 40) return true; } return false; } private static OverlayRegion Region(string name, int x, int y, int w, int h) => new() { Name = name, X = x, Y = y, Width = w, Height = h, FontFamily = "Arial", FontSizePx = 20, ColorHex = "#FFFFFF" }; [Fact] public void Render_DrawsLabel_AndPreservesDimensions() { using SKBitmap baseImg = SolidBase(200, 100, SKColors.Black); var template = new OverlayTemplate { Width = 200, Height = 100, Regions = { Region("b-00", 10, 10, 150, 50) } }; var labels = new Dictionary { ["b-00"] = "FIRE" }; using SKBitmap output = new SkiaOverlayRenderer().Render(template, labels, baseImg); Assert.Equal(200, output.Width); Assert.Equal(100, output.Height); Assert.True(HasLightPixel(output, 10, 10, 150, 50), "white label text should appear inside the region"); } [Fact] public void Render_DoesNotMutateBaseImage() { using SKBitmap baseImg = SolidBase(120, 60, SKColors.Black); var template = new OverlayTemplate { Regions = { Region("x", 5, 5, 100, 40) } }; using SKBitmap _ = new SkiaOverlayRenderer().Render(template, new Dictionary { ["x"] = "HI" }, baseImg); Assert.False(HasLightPixel(baseImg, 0, 0, 120, 60), "the source bitmap must be left untouched"); } [Fact] public void Render_RegionWithoutLabel_StaysBackground() { using SKBitmap baseImg = SolidBase(120, 60, SKColors.Black); var template = new OverlayTemplate { Regions = { Region("x", 5, 5, 100, 40) } }; // No entry for "x" -> nothing drawn. using SKBitmap output = new SkiaOverlayRenderer().Render(template, new Dictionary(), baseImg); Assert.False(HasLightPixel(output, 0, 0, 120, 60)); } [Fact] public void RenderToPng_ProducesValidPngSignature() { using SKBitmap baseImg = SolidBase(64, 64, SKColors.Black); var template = new OverlayTemplate { Regions = { Region("x", 2, 2, 60, 30) } }; byte[] png = new SkiaOverlayRenderer().RenderToPng(template, new Dictionary { ["x"] = "HI" }, baseImg); Assert.True(png.Length > 8); Assert.Equal(new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }, png[..8]); } }