using XFESystem.Desktop; using Xunit; namespace XFESystem.Core.Tests; public sealed class ChromeRasterTests { private sealed class BitmapCanvas(int scale, uint background) : IDesktopCoverageCanvas { public int Width => 100; public int Height => 80; public int NativeWidth => Width * scale; public int NativeHeight => Height * scale; public int ScalePercent => scale * 100; public uint[] Pixels { get; } = Enumerable.Repeat(background, 100 * 80 * scale * scale).ToArray(); public void Fill(uint rgb, int x, int y, int width, int height) { for (int py = Math.Max(0, y * scale); py < Math.Min(NativeHeight, (y + height) * scale); py++) for (int px = Math.Max(0, x * scale); px < Math.Min(NativeWidth, (x + width) * scale); px++) Pixels[py * NativeWidth + px] = rgb; } public void BlendCoverage(uint rgb, int x, int y, int width, int height, ReadOnlySpan alpha) { Assert.Equal(width * height, alpha.Length); for (int row = 0; row < height; row++) for (int column = 0; column < width; column++) { int px = x + column, py = y + row; if (px < 0 || py < 0 || px >= NativeWidth || py >= NativeHeight) continue; int index = py * NativeWidth + px, a = alpha[row * width + column]; uint old = Pixels[index], color = 0; foreach (int shift in new[] { 0, 8, 16 }) color |= (uint)(((rgb >> shift & 255) * a + (old >> shift & 255) * (255 - a) + 127) / 255) << shift; Pixels[index] = color; } } public void Line(uint rgb, int x1, int y1, int x2, int y2) => throw new InvalidOperationException("Native coverage must not fall back to aliased lines."); public void Text(string text, uint rgb, int x, int y) { } public void Present() { } } [Theory] [InlineData(1)] [InlineData(2)] public void RoundedCornersContainIntermediateCoverageAndPreserveOutsidePixels(int scale) { const uint background = 0x09121B, foreground = 0xFAFAFE; var bitmap = new BitmapCanvas(scale, background); DesktopChromeRenderer.RoundedFill(bitmap, foreground, 10, 12, 60, 42, 12); Assert.Equal(background, bitmap.Pixels[12 * scale * bitmap.NativeWidth + 10 * scale]); Assert.Equal(foreground, bitmap.Pixels[30 * scale * bitmap.NativeWidth + 35 * scale]); Assert.Contains(bitmap.Pixels, pixel => pixel != foreground && pixel != background); for (int row = 0; row < bitmap.NativeHeight; row++) for (int col = 0; col < bitmap.NativeWidth; col++) if (col < 10 * scale || col >= 70 * scale || row < 12 * scale || row >= 54 * scale) Assert.Equal(background, bitmap.Pixels[row * bitmap.NativeWidth + col]); } [Theory] [InlineData(1)] [InlineData(2)] public void DiagonalCaptionStrokesAreAntialiasedAndBlendWithScene(int scale) { const uint background = 0xEEEFF8, foreground = 0x343C56; var bitmap = new BitmapCanvas(scale, background); DesktopChromeRenderer.Line(bitmap, foreground, 20, 20, 32, 32); Assert.Contains(bitmap.Pixels, pixel => pixel != foreground && pixel != background); Assert.Equal(background, bitmap.Pixels[0]); Assert.Equal(background, bitmap.Pixels[50 * scale * bitmap.NativeWidth + 50 * scale]); Assert.True(bitmap.Pixels.Count(pixel => pixel != background) < 100 * scale * scale); } [Fact] public void NegativeChromeBoundsClipCleanlyAndTinyRadiiDoNotLoseInterior() { var bitmap = new BitmapCanvas(2, 0x102538); DesktopChromeRenderer.RoundedFill(bitmap, 0x75C9F5, -10, -6, 40, 30, 8); Assert.Equal(0x75C9F5u, bitmap.Pixels[0]); DesktopChromeRenderer.RoundedFill(bitmap, 0xFAFAFE, 50, 50, 3, 2, 20); Assert.Equal(0xFAFAFEu, bitmap.Pixels[101 * bitmap.NativeWidth + 102]); DesktopChromeRenderer.Line(bitmap, 0x657DE2, -8, -8, 10, 10); Assert.Contains(bitmap.Pixels, pixel => pixel == 0x102538); } }