XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
using XFESystem.Browser;
using XFESystem.Core;
using XFESystem.Desktop;
using XFESystem.Platform;

namespace XFESystem.Platform.Tests;

public sealed class RenderingTests
{
    [Fact]
    public void NonBreakingSpacesHaveAdvanceAndNoInkAtMonacoSizes()
    {
        var fonts = PlatformFonts.CreateBundled();
        foreach (double size in new[] { 1d, 13d, 16d, 26d })
        {
            Assert.True(fonts.HasGlyph('\u00A0', "Consolas", 400));
            Assert.Equal(fonts.Measure(" ", size, "Consolas", 400), fonts.Measure("\u00A0", size, "Consolas", 400), 5);
            var blank = fonts.Rasterize("\u00A0", size, "Consolas", 400);
            Assert.All(blank.Alpha, value => Assert.Equal((byte)0, value));
            var run = fonts.Rasterize("A\u00A0B", size, "Consolas", 400);
            Assert.Contains(run.Alpha, value => value > 0);
        }
    }

    [Fact]
    public void OfficialMonacoDomPaintsActualTextWithIndependentFonts()
    {
        var output = new ArrayFramebufferPresenter(800, 430); var canvas = new CpuFramebufferCanvas(output);
        var fonts = PlatformFonts.CreateBundled(); var traces = new List<string>();
        var page = new BrowserService { Trace = traces.Add }; page.SetCanvas(canvas); page.ResizeViewport(800, 430);
        try
        {
            page.Navigate("about:Monaco");
            for (int tick = 0; tick < 20; tick++) page.AdvanceTime(tick * 16);
            Assert.Contains("Official Monaco 0.52.2 - ready", page.CurrentPage.Text);
            Assert.Contains("const answer = 6 * 7;", page.ReadEditorText());
            var list = page.Layout(new(800, 430));
            foreach (var item in list.Commands.Where(command => command.Kind == BrowserDrawKind.Text && command.Opacity > 0))
            {
                try { fonts.Rasterize(item.Text, item.Font.Size, item.Font.Family, item.Font.Weight); }
                catch (Exception error)
                {
                    Assert.Fail("Monaco actual text raster failed: " + error.Message + " | " + item.Font + " | " +
                        string.Join(" ", item.Text.Select(character => "U+" + ((int)character).ToString("X4"))));
                }
            }
            page.Paint(canvas, new(0, 0, 800, 430), 0); canvas.Present();
            Assert.DoesNotContain(traces, trace => trace.Contains("PAINT_FAILED", StringComparison.Ordinal));
            Assert.True(page.RasterPaintCount > 0);
            Assert.True(output.Pixels.ToArray().Distinct().Count() > 30);
            EvidencePng.Write("Monaco.png", output.Pixels.Span, output.Width, output.Height);
        }
        finally { page.Release(); }
    }

    [Fact]
    public void OfficialFontsProduceRealProportionalMonoCjkAndIconCoverage()
    {
        var fonts = PlatformFonts.CreateBundled();
        Assert.True(fonts.Measure("WWW", 16, "system-ui", 400) > fonts.Measure("iii", 16, "system-ui", 400) * 2);
        Assert.Equal(fonts.Measure("WWW", 16, "Consolas", 400), fonts.Measure("iii", 16, "Consolas", 400), 5);
        Assert.True(fonts.HasGlyph('中', "system-ui", 400));
        foreach (var text in new[] { "ABC", "中文", "MWig" })
        {
            var mask = fonts.Rasterize(text, 20, "system-ui", 400);
            Assert.Equal(mask.Width * mask.Height, mask.Alpha.Length); Assert.Contains(mask.Alpha, alpha => alpha > 0 && alpha < 255);
        }
        Assert.NotEqual(fonts.Rasterize("Bold", 20, "system-ui", 400).Alpha, fonts.Rasterize("Bold", 20, "system-ui", 700).Alpha);
        // Bootstrap Icons 1.11.3 CSS maps bi-copy to U+F759.
        Assert.True(fonts.HasGlyph('\uF759', "bootstrap-icons", 400));
        Assert.Contains(fonts.Rasterize("\uF759", 20, "bootstrap-icons", 400).Alpha, value => value > 0);
        Assert.True(fonts.CachedGlyphBytes > 0);
    }

    [Fact]
    public void TextMaskReturnedToCallerCannotPoisonCachedRendering()
    {
        var output = new ArrayFramebufferPresenter(120, 40); var canvas = new CpuFramebufferCanvas(output);
        var exposed = canvas.RasterizeWebText("Test", 20, "system-ui", 400);
        Array.Fill(exposed.Alpha, (byte)0);
        canvas.WebText("Test", 0xFFFFFF, 0, 0, 20, "system-ui", 400); canvas.Present();
        Assert.Contains(output.Pixels.ToArray(), pixel => pixel != 0);
    }

    [Fact]
    public void FontPreparationTransfersExclusiveCachesAndRejectsRepeatAndIncompatibleScale()
    {
        var canvas = new CpuFramebufferCanvas(new ArrayFramebufferPresenter(100, 100));
        var preparation = Assert.IsType<CpuFramebufferCanvas>(canvas.CreateEditorPreparationCanvas());
        Assert.Equal(1, preparation.NativeWidth);
        preparation.PrepareEditorText("中文 Mono", 16, "Consolas", 400);
        Assert.True(preparation.CachedTextMaskCount > 0);
        Assert.False(preparation.TryCompleteEditorPreparationHandoff(new CpuFramebufferCanvas(new ArrayFramebufferPresenter(100, 100), scalePercent: 200)));
        Assert.True(preparation.TryCompleteEditorPreparationHandoff(canvas));
        Assert.True(canvas.CachedTextMaskCount > 0); Assert.False(preparation.TryCompleteEditorPreparationHandoff(canvas));
        Assert.Throws<InvalidOperationException>(() => preparation.PrepareEditorText("Late", 16, "Consolas", 400));
    }

    [Fact]
    public void ExistingDesktopRendersWithIndependentCanvasAndPointerPresentation()
    {
        var output = new ArrayFramebufferPresenter(1024, 768); var canvas = new CpuFramebufferCanvas(output);
        var desktop = new DesktopSession(canvas, new MemoryWorkspace());
        desktop.Open(DesktopApplication.Files); desktop.Open(DesktopApplication.Terminal); desktop.Render();
        Assert.True(desktop.LastFrameCompleted); Assert.Equal(1, canvas.FramesPresented);
        Assert.True(output.Pixels.ToArray().Distinct().Count() > 100);
        EvidencePng.Write("Desktop.png", output.Pixels.Span, output.Width, output.Height);
        Assert.True(canvas.TryFingerprintPresentedPixels(new(400, 200, 128, 128), out var before));
        desktop.Pointer(440, 220, false, timestampMs: 1000); desktop.Render();
        Assert.True(desktop.LastFrameCompleted); Assert.Equal(2, canvas.FramesPresented);
        Assert.True(canvas.TryFingerprintPresentedPixels(new(400, 200, 128, 128), out var after));
        Assert.NotEqual(before.Fingerprint, after.Fingerprint);
    }

    [Fact]
    public void RealDomJintCssAndNativeFontBackendRenderChangedBrowserText()
    {
        var output = new ArrayFramebufferPresenter(480, 220); var canvas = new CpuFramebufferCanvas(output);
        var page = new BrowserService(new HtmlTransport()); page.SetCanvas(canvas); page.ResizeViewport(480, 220);
        page.Navigate("http://platform.test/");
        Assert.Contains("JavaScript 中文", page.CurrentPage.Text);
        page.Paint(canvas, new(0, 0, 480, 220), 0); canvas.Present();
        Assert.True(output.Pixels.ToArray().Count(pixel => pixel == 0x112233) > 10000);
        Assert.Contains(output.Pixels.ToArray(), pixel => pixel != 0 && pixel != 0x112233 && pixel != 0xF0F0F0);
        EvidencePng.Write("Browser.png", output.Pixels.Span, output.Width, output.Height);
        page.Release();
    }
    private sealed class HtmlTransport : IWebTransport
    {
        public WebResponse Get(Uri address, BrowserLimits limits) => new(address, 200, "text/html", """
            <html><style>body{margin:0;background:#f0f0f0;font-family:system-ui}#box{width:300px;height:120px;background:#112233;color:#fff;font-size:24px;padding:12px}</style>
            <body><div id='box'>before</div><script>document.getElementById('box').textContent='JavaScript 中文';</script></body></html>
            """);
    }
}