This commit is contained in:
Wiesław Šoltés 2022-11-12 21:11:13 +01:00
Родитель cd4e1c8c62
Коммит 738231d32b
10 изменённых файлов: 46 добавлений и 36 удалений

Просмотреть файл

@ -2,6 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:NodeEditorDemo"
xmlns:vm="using:NodeEditorDemo.ViewModels"
xmlns:export="clr-namespace:NodeEditor.Export.Controls;assembly=NodeEditorAvalonia.Export"
x:CompileBindings="True" x:DataType="vm:EditorViewModel"
x:Class="NodeEditorDemo.App">
@ -53,6 +54,10 @@
<Setter Property="Background" Value="{DynamicResource SeparatorBackground}" />
</Style>
<Style Selector="export|ExportRoot">
<Setter Property="(TextElement.FontFamily)" Value="avares://Avalonia.Themes.Fluent/Assets#Inter" />
</Style>
</Application.Styles>
<NativeMenu.Menu>

Просмотреть файл

@ -16,12 +16,14 @@
<Style Selector="Label.node">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="(TextElement.FontFamily)" Value="avares://Avalonia.Themes.Fluent/Assets#Inter" />
</Style>
<Style Selector="CheckBox.node">
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="6,0,0,0" />
<Setter Property="(TextElement.FontFamily)" Value="avares://Avalonia.Themes.Fluent/Assets#Inter" />
</Style>
</Styles>

Просмотреть файл

@ -5,15 +5,13 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Platform.Storage;
using Avalonia.VisualTree;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using NodeEditor.Controls;
using NodeEditor.Export.Controls;
using NodeEditor.Export.Renderers;
using NodeEditor.Model;
using NodeEditor.Serializer;
@ -225,44 +223,61 @@ public partial class EditorViewModel : ViewModelBase, INodeTemplatesHost
};
root.ApplyTemplate();
root.InvalidateMeasure();
root.InvalidateArrange();
root.LayoutManager.ExecuteLayoutPass();
var size = new Size(Drawing.Width, Drawing.Height);
if (file.Name.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
{
using var ms = new MemoryStream();
PngRenderer.Render(root, size, ms);
await using var stream = await file.OpenWriteAsync();
PngRenderer.Render(root, size, stream);
ms.Position = 0;
await stream.WriteAsync(ms.ToArray());
}
if (file.Name.EndsWith(".svg", StringComparison.OrdinalIgnoreCase))
{
using var ms = new MemoryStream();
SvgRenderer.Render(root, size, ms);
await using var stream = await file.OpenWriteAsync();
SvgRenderer.Render(root, size, stream);
ms.Position = 0;
await stream.WriteAsync(ms.ToArray());
}
if (file.Name.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase))
{
using var ms = new MemoryStream();
PdfRenderer.Render(root, size, ms, 96);
await using var stream = await file.OpenWriteAsync();
PdfRenderer.Render(root, size, stream, 96);
ms.Position = 0;
await stream.WriteAsync(ms.ToArray());
}
if (file.Name.EndsWith("xps", StringComparison.OrdinalIgnoreCase))
{
using var ms = new MemoryStream();
XpsRenderer.Render(control, size, ms, 96);
await using var stream = await file.OpenWriteAsync();
XpsRenderer.Render(control, size, stream, 96);
ms.Position = 0;
await stream.WriteAsync(ms.ToArray());
}
if (file.Name.EndsWith("skp", StringComparison.OrdinalIgnoreCase))
{
using var ms = new MemoryStream();
SkpRenderer.Render(control, size, ms);
await using var stream = await file.OpenWriteAsync();
SkpRenderer.Render(control, size, stream);
ms.Position = 0;
await stream.WriteAsync(ms.ToArray());
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
Debug.WriteLine(ex.StackTrace);
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
}
}

Просмотреть файл

@ -20,7 +20,7 @@
</Flyout>
</Panel.ContextFlyout>
<Rectangle Classes="node" />
<Label Classes="node"
Content="{Binding Label}" />
<Label Classes="node"
Content="{Binding Label}" />
</Panel>
</UserControl>

Просмотреть файл

@ -1,4 +1,3 @@
using System;
using Avalonia.Controls;
using Avalonia.Rendering;
using SkiaSharp;
@ -7,20 +6,9 @@ namespace NodeEditor.Export;
public static class CanvasRenderer
{
public static void Render(Control target, SKCanvas canvas, double dpi = 96, bool useDeferredRenderer = false)
public static void Render(Control target, SKCanvas canvas, double dpi = 96)
{
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);
}
ImmediateRenderer.Render(target, renderTarget);
}
}
}

Просмотреть файл

@ -8,7 +8,7 @@ using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Styling;
namespace NodeEditorDemo.Controls;
namespace NodeEditor.Export.Controls;
public class ExportRoot : Decorator, IFocusScope, ILayoutRoot, IInputRoot, IRenderRoot, IStyleHost, ILogicalRoot
{

Просмотреть файл

@ -7,13 +7,13 @@ namespace NodeEditor.Export.Renderers;
public static class PdfRenderer
{
public static void Render(Control target, Size size, Stream stream, double dpi = 72, bool useDeferredRenderer = false)
public static void Render(Control target, Size size, Stream stream, double dpi = 72)
{
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);
CanvasRenderer.Render(target, canvas, dpi);
}
}

Просмотреть файл

@ -7,14 +7,14 @@ namespace NodeEditor.Export.Renderers;
public static class SkpRenderer
{
public static void Render(Control target, Size size, Stream stream, double dpi = 96, bool useDeferredRenderer = false)
public static void Render(Control target, Size size, Stream stream, double dpi = 96)
{
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);
CanvasRenderer.Render(target, canvas, dpi);
using var picture = pictureRecorder.EndRecording();
picture.Serialize(stream);
}

Просмотреть файл

@ -7,13 +7,13 @@ namespace NodeEditor.Export.Renderers;
public static class SvgRenderer
{
public static void Render(Control target, Size size, Stream stream, double dpi = 96, bool useDeferredRenderer = false)
public static void Render(Control target, Size size, Stream stream, double dpi = 96)
{
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);
CanvasRenderer.Render(target, canvas, dpi);
}
}

Просмотреть файл

@ -7,13 +7,13 @@ namespace NodeEditor.Export.Renderers;
public static class XpsRenderer
{
public static void Render(Control target, Size size, Stream stream, double dpi = 72, bool useDeferredRenderer = false)
public static void Render(Control target, Size size, Stream stream, double dpi = 72)
{
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);
CanvasRenderer.Render(target, canvas, dpi);
}
}