| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- // Copyright (c) The Avalonia Project. All rights reserved.
- // Licensed under the MIT license. See licence.md file in the project root for full license information.
- using System.IO;
- using System.Runtime.CompilerServices;
- using ImageMagick;
- using Avalonia.Controls;
- using Avalonia.Media.Imaging;
- using Avalonia.Rendering;
- using Xunit;
- using Avalonia.Platform;
- using System.Threading.Tasks;
- using System;
- using System.Threading;
- using Avalonia.Threading;
- #if AVALONIA_SKIA
- using Avalonia.Skia;
- #else
- using Avalonia.Direct2D1;
- #endif
- #if AVALONIA_SKIA
- namespace Avalonia.Skia.RenderTests
- #else
- namespace Avalonia.Direct2D1.RenderTests
- #endif
- {
- public class TestBase
- {
- private static readonly TestThreadingInterface threadingInterface =
- new TestThreadingInterface();
- static TestBase()
- {
- #if AVALONIA_SKIA
- SkiaPlatform.Initialize();
- #else
- Direct2D1Platform.Initialize();
- #endif
- AvaloniaLocator.CurrentMutable
- .Bind<IPlatformThreadingInterface>()
- .ToConstant(threadingInterface);
- }
- public TestBase(string outputPath)
- {
- var testPath = GetTestsDirectory();
- var testFiles = Path.Combine(testPath, "TestFiles");
- #if AVALONIA_SKIA
- var platform = "Skia";
- #else
- var platform = "Direct2D1";
- #endif
- OutputPath = Path.Combine(testFiles, platform, outputPath);
- threadingInterface.MainThread = Thread.CurrentThread;
- }
- public string OutputPath
- {
- get;
- }
- protected async Task RenderToFile(Control target, [CallerMemberName] string testName = "", double dpi = 96)
- {
- if (!Directory.Exists(OutputPath))
- {
- Directory.CreateDirectory(OutputPath);
- }
- var immediatePath = Path.Combine(OutputPath, testName + ".immediate.out.png");
- var deferredPath = Path.Combine(OutputPath, testName + ".deferred.out.png");
- var factory = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>();
- var pixelSize = new PixelSize((int)target.Width, (int)target.Height);
- var size = new Size(target.Width, target.Height);
- var dpiVector = new Vector(dpi, dpi);
- using (RenderTargetBitmap bitmap = new RenderTargetBitmap(pixelSize, dpiVector))
- {
- target.Measure(size);
- target.Arrange(new Rect(size));
- bitmap.Render(target);
- bitmap.Save(immediatePath);
- }
- using (var rtb = factory.CreateRenderTargetBitmap(pixelSize, dpiVector))
- using (var renderer = new DeferredRenderer(target, rtb))
- {
- target.Measure(size);
- target.Arrange(new Rect(size));
- renderer.UnitTestUpdateScene();
- // Do the deferred render on a background thread to expose any threading errors in
- // the deferred rendering path.
- await Task.Run((Action)renderer.UnitTestRender);
- rtb.Save(deferredPath);
- }
- }
- protected void CompareImages([CallerMemberName] string testName = "")
- {
- var expectedPath = Path.Combine(OutputPath, testName + ".expected.png");
- var immediatePath = Path.Combine(OutputPath, testName + ".immediate.out.png");
- var deferredPath = Path.Combine(OutputPath, testName + ".deferred.out.png");
- using (var expected = new MagickImage(expectedPath))
- using (var immediate = new MagickImage(immediatePath))
- using (var deferred = new MagickImage(deferredPath))
- {
- double immediateError = expected.Compare(immediate, ErrorMetric.RootMeanSquared);
- double deferredError = expected.Compare(deferred, ErrorMetric.RootMeanSquared);
- if (immediateError > 0.022)
- {
- Assert.True(false, immediatePath + ": Error = " + immediateError);
- }
- if (deferredError > 0.022)
- {
- Assert.True(false, deferredPath + ": Error = " + deferredError);
- }
- }
- }
- protected void CompareImagesNoRenderer([CallerMemberName] string testName = "")
- {
- var expectedPath = Path.Combine(OutputPath, testName + ".expected.png");
- var actualPath = Path.Combine(OutputPath, testName + ".out.png");
- using (var expected = new MagickImage(expectedPath))
- using (var actual = new MagickImage(actualPath))
- {
- double immediateError = expected.Compare(actual, ErrorMetric.RootMeanSquared);
- if (immediateError > 0.022)
- {
- Assert.True(false, actualPath + ": Error = " + immediateError);
- }
- }
- }
- private string GetTestsDirectory()
- {
- var path = Directory.GetCurrentDirectory();
- while (path.Length > 0 && Path.GetFileName(path) != "tests")
- {
- path = Path.GetDirectoryName(path);
- }
- return path;
- }
- private class TestThreadingInterface : IPlatformThreadingInterface
- {
- public bool CurrentThreadIsLoopThread => MainThread.ManagedThreadId == Thread.CurrentThread.ManagedThreadId;
- public Thread MainThread { get; set; }
- #pragma warning disable 67
- public event Action<DispatcherPriority?> Signaled;
- #pragma warning restore 67
- public void RunLoop(CancellationToken cancellationToken)
- {
- throw new NotImplementedException();
- }
- public void Signal(DispatcherPriority prio)
- {
- throw new NotImplementedException();
- }
- public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
- {
- throw new NotImplementedException();
- }
- }
- }
- }
|