Last active
November 6, 2022 14:54
-
-
Save kant2002/ccda367b8e795f37d25ad735b0531b9a to your computer and use it in GitHub Desktop.
Headless Avalonia
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<OutputType>Exe</OutputType> | |
<TargetFramework>net6.0</TargetFramework> | |
<ImplicitUsings>enable</ImplicitUsings> | |
<Nullable>enable</Nullable> | |
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | |
</PropertyGroup> | |
<ItemGroup> | |
<PackageReference Include="Avalonia.Headless" Version="11.0.0-preview3" /> | |
<PackageReference Include="Avalonia" Version="11.0.0-preview3" /> | |
<PackageReference Include="Avalonia.Skia" Version="11.0.0-preview3" /> | |
<PackageReference Include="SkiaSharp" Version="2.88.3" /> | |
</ItemGroup> | |
</Project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//#r "nuget: Avalonia.Headless, 11.0.0-preview3" | |
//#r "nuget: Avalonia, 11.0.0-preview3" | |
//#r "nuget: Avalonia.Skia, 11.0.0-preview3" | |
//#r "nuget: SkiaSharp, 2.88.3" | |
using Avalonia.Themes.Fluent; | |
using SkiaSharp; | |
var builder = AppBuilder | |
.Configure<App>() | |
.UseSkia() | |
.UseHeadless(new() { UseCompositor = true, UseHeadlessDrawing = false }); | |
// This initialization logic should be part of kernel probably. I canot execute this method just once inside single AppContext | |
builder.SetupWithoutStarting(); | |
var window = CreateWindow(); | |
window.Show(); | |
// Get render target. | |
var renderRoot = (IRenderRoot)window; | |
var renderTarget = renderRoot.CreateRenderTarget(); | |
ImmediateRenderer.Render(window, renderTarget); | |
var headlessWindow = (IHeadlessWindow)window.PlatformImpl!; | |
var lastRenderedFrame = headlessWindow.GetLastRenderedFrame(); | |
var lockedFramebuffer = lastRenderedFrame.Item.Lock(); | |
WriteImage(lockedFramebuffer, "test.png"); | |
void WriteImage(ILockedFramebuffer framebuffer, string fileName) | |
{ | |
var imageInfo = new SKImageInfo(framebuffer.Size.Width, framebuffer.Size.Height, SKColorType.Rgba8888, SKAlphaType.Opaque); | |
var _bitmap = SKImage.FromPixelCopy(imageInfo, framebuffer.Address); | |
var data = _bitmap.Encode(); | |
using var file = File.OpenWrite(fileName); | |
data.SaveTo(file); | |
file.Flush(); | |
} | |
Window CreateWindow() | |
{ | |
var window = new HeadlessWindow(); | |
var grid = new Grid(); | |
grid.HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center; | |
grid.VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center; | |
grid.Children.Add(new Button() { Content = "Hello Headless Avalonia" }); | |
window.Content = grid; | |
window.Resize(new Size(200, 100)); | |
return window; | |
} | |
class HeadlessWindow : Window | |
{ | |
public void Resize(Size newSize) | |
{ | |
ClientSize = newSize; | |
PlatformImpl!.GetType().GetMethod("DoResize", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.InvokeMethod)! | |
.Invoke(PlatformImpl, new object[] { newSize }); | |
} | |
} | |
class App : Application | |
{ | |
public override void Initialize() | |
{ | |
var theme = new FluentTheme(new Uri("avares://AvaloniaHeadlessConsoleApp")); | |
theme.Mode = FluentThemeMode.Light; | |
Styles.Add(theme); | |
base.Initialize(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment