Add save screenshot debug tool
ADD
WalletWasabi.Fluent/Screenshot/CanvasRenderTarget.cs
+using Avalonia;
+using Avalonia.Platform;
+using Avalonia.Rendering;
+using Avalonia.Skia.Helpers;
+using SkiaSharp;
+
+namespace WalletWasabi.Fluent.Screenshot;
+
+public class CanvasRenderTarget : IRenderTarget
+{
+ private readonly SKCanvas _canvas;
+ private readonly double _dpi;
+
+ public CanvasRenderTarget(SKCanvas canvas, double dpi)
+ {
+ _canvas = canvas;
+ _dpi = dpi;
+ }
+
+ public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer? visualBrushRenderer)
+ {
+ return DrawingContextHelper.WrapSkiaCanvas(_canvas, new Vector(_dpi, _dpi), visualBrushRenderer);
+ }
+
+ public void Dispose()
+ {
+ }
+}

ADD
WalletWasabi.Fluent/Screenshot/CanvasRenderer.cs
+using Avalonia.Controls;
+using Avalonia.Rendering;
+using SkiaSharp;
+
+namespace WalletWasabi.Fluent.Screenshot;
+
+public static class CanvasRenderer
+{
+ public static void Render(Control target, SKCanvas canvas, double dpi = 96, bool useDeferredRenderer = false)
+ {
+ using var renderTarget = new CanvasRenderTarget(canvas, dpi);
+ if (useDeferredRenderer)
+ {
+ using var renderer = new DeferredRenderer(target, renderTarget);
+ renderer.Start();
+ var renderLoopTask = renderer as IRenderLoopTask;
+ renderLoopTask.Update(TimeSpan.Zero);
+ renderLoopTask.Render();
+ }
+ else
+ {
+ ImmediateRenderer.Render(target, renderTarget);
+ }
+ }
+}

ADD
WalletWasabi.Fluent/Screenshot/Renderers/PdfRenderer.cs
+using System.IO;
+using Avalonia;
+using Avalonia.Controls;
+using SkiaSharp;
+
+namespace WalletWasabi.Fluent.Screenshot.Renderers;
+
+public static class PdfRenderer
+{
+ public static void Render(Control target, Size size, Stream stream, double dpi = 72, bool useDeferredRenderer = false)
+ {
+ using var managedWStream = new SKManagedWStream(stream);
+ using var document = SKDocument.CreatePdf(stream, (float)dpi);
+ using var canvas = document.BeginPage((float)size.Width, (float)size.Height);
+ target.Measure(size);
+ target.Arrange(new Rect(size));
+ CanvasRenderer.Render(target, canvas, dpi, useDeferredRenderer);
+ }
+}

ADD
WalletWasabi.Fluent/Screenshot/Renderers/PngRenderer.cs
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Media.Imaging;
+
+namespace WalletWasabi.Fluent.Screenshot.Renderers;
+
+public static class PngRenderer
+{
+ public static void Render(Control target, Size size, string path, double dpi = 96)
+ {
+ var pixelSize = new PixelSize((int)size.Width, (int)size.Height);
+ var dpiVector = new Vector(dpi, dpi);
+ using var bitmap = new RenderTargetBitmap(pixelSize, dpiVector);
+ target.Measure(size);
+ target.Arrange(new Rect(size));
+ bitmap.Render(target);
+ bitmap.Save(path);
+ }
+}

ADD
WalletWasabi.Fluent/Screenshot/Renderers/SkpRenderer.cs
+using System.IO;
+using Avalonia;
+using Avalonia.Controls;
+using SkiaSharp;
+
+namespace WalletWasabi.Fluent.Screenshot.Renderers;
+
+public static class SkpRenderer
+{
+ public static void Render(Control target, Size size, Stream stream, double dpi = 96, bool useDeferredRenderer = false)
+ {
+ var bounds = SKRect.Create(new SKSize((float)size.Width, (float)size.Height));
+ using var pictureRecorder = new SKPictureRecorder();
+ using var canvas = pictureRecorder.BeginRecording(bounds);
+ target.Measure(size);
+ target.Arrange(new Rect(size));
+ CanvasRenderer.Render(target, canvas, dpi, useDeferredRenderer);
+ using var picture = pictureRecorder.EndRecording();
+ picture.Serialize(stream);
+ }
+}

ADD
WalletWasabi.Fluent/Screenshot/Renderers/SvgRenderer.cs
+using System.IO;
+using Avalonia;
+using Avalonia.Controls;
+using SkiaSharp;
+
+namespace WalletWasabi.Fluent.Screenshot.Renderers;
+
+public static class SvgRenderer
+{
+ public static void Render(Control target, Size size, Stream stream, double dpi = 96, bool useDeferredRenderer = false)
+ {
+ using var managedWStream = new SKManagedWStream(stream);
+ var bounds = SKRect.Create(new SKSize((float)size.Width, (float)size.Height));
+ using var canvas = SKSvgCanvas.Create(bounds, managedWStream);
+ target.Measure(size);
+ target.Arrange(new Rect(size));
+ CanvasRenderer.Render(target, canvas, dpi, useDeferredRenderer);
+ }
+}

ADD
WalletWasabi.Fluent/Screenshot/Renderers/XpsRenderer.cs
+using System.IO;
+using Avalonia;
+using Avalonia.Controls;
+using SkiaSharp;
+
+namespace WalletWasabi.Fluent.Screenshot.Renderers;
+
+public static class XpsRenderer
+{
+ public static void Render(Control target, Size size, Stream stream, double dpi = 72, bool useDeferredRenderer = false)
+ {
+ using var managedWStream = new SKManagedWStream(stream);
+ using var document = SKDocument.CreateXps(stream, (float)dpi);
+ using var canvas = document.BeginPage((float)size.Width, (float)size.Height);
+ target.Measure(size);
+ target.Arrange(new Rect(size));
+ CanvasRenderer.Render(target, canvas, dpi, useDeferredRenderer);
+ }
+}

MODIFY
WalletWasabi.Fluent/Views/MainWindow.axaml.cs
WalletWasabi.Fluent/Views/MainWindow.axaml.cs
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
+using WalletWasabi.Fluent.Screenshot;
namespace WalletWasabi.Fluent.Views;
@@ -16,6 +17,7 @@ public class MainWindow : Window
AvaloniaXamlLoader.Load(this);
#if DEBUG
this.AttachDevTools();
+ this.AttachCapture();
#endif
}
}

Add save screenshot debug tool