diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index 487a2555d4..96251b1685 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -10,11 +10,15 @@ on:
- master
- main
+concurrency:
+ group: docs-${{ github.ref }}
+ cancel-in-progress: true
+
permissions:
- contents: write
+ contents: read
jobs:
- deploy:
+ build:
runs-on: ubuntu-latest
steps:
- name: Checkout
@@ -37,8 +41,32 @@ jobs:
chmod +x build-docs.sh
./build-docs.sh
+ - name: Upload docs artifact
+ if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch
+ uses: actions/upload-artifact@v4
+ with:
+ name: docs-site
+ path: ./site/.lunet/build/www
+ include-hidden-files: true
+ if-no-files-found: error
+
+ deploy:
+ if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch
+ needs: build
+ permissions:
+ contents: write
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Download docs artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: docs-site
+ path: ./site/.lunet/build/www
+
- name: Deploy to GitHub Pages
- if: github.event_name == 'push'
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/Directory.Build.props b/Directory.Build.props
index 79a5650e6e..2b622bcb30 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,10 +1,10 @@
- 3.7.0
+ 4.0.0
- 11.3.9.5
+ 12.0.0
$(VersionSuffix)
- 6.5.31
+ 6.5.31.1
$(VersionSuffix)
Wiesław Šoltés
Wiesław Šoltés
diff --git a/Directory.Packages.props b/Directory.Packages.props
index ad6bf1a925..324e188354 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -1,13 +1,12 @@
true
- 11.3.9
+ 12.0.0
-
-
+
@@ -16,7 +15,6 @@
-
@@ -38,6 +36,7 @@
+
diff --git a/README.md b/README.md
index 049b6d4b66..aa1938c8a0 100644
--- a/README.md
+++ b/README.md
@@ -13,6 +13,29 @@
[](https://github.com/wieslawsoltes/svg.skia)
[](https://github.com/wieslawsoltes/svg.skia)
+| Package ID | NuGet | Downloads |
+| --- | --- | --- |
+| `ShimSkiaSharp` | [](https://www.nuget.org/packages/ShimSkiaSharp/) | [](https://www.nuget.org/packages/ShimSkiaSharp/) |
+| `Skia.Controls.Avalonia` | [](https://www.nuget.org/packages/Skia.Controls.Avalonia/) | [](https://www.nuget.org/packages/Skia.Controls.Avalonia/) |
+| `Svg.Animation` | [](https://www.nuget.org/packages/Svg.Animation/) | [](https://www.nuget.org/packages/Svg.Animation/) |
+| `Svg.CodeGen.Skia` | [](https://www.nuget.org/packages/Svg.CodeGen.Skia/) | [](https://www.nuget.org/packages/Svg.CodeGen.Skia/) |
+| `Svg.Controls.Avalonia` | [](https://www.nuget.org/packages/Svg.Controls.Avalonia/) | [](https://www.nuget.org/packages/Svg.Controls.Avalonia/) |
+| `Svg.Controls.Skia.Avalonia` | [](https://www.nuget.org/packages/Svg.Controls.Skia.Avalonia/) | [](https://www.nuget.org/packages/Svg.Controls.Skia.Avalonia/) |
+| `Svg.Controls.Skia.Uno` | [](https://www.nuget.org/packages/Svg.Controls.Skia.Uno/) | [](https://www.nuget.org/packages/Svg.Controls.Skia.Uno/) |
+| `Svg.Custom` | [](https://www.nuget.org/packages/Svg.Custom/) | [](https://www.nuget.org/packages/Svg.Custom/) |
+| `Svg.Editor.Avalonia` | [](https://www.nuget.org/packages/Svg.Editor.Avalonia/) | [](https://www.nuget.org/packages/Svg.Editor.Avalonia/) |
+| `Svg.Editor.Core` | [](https://www.nuget.org/packages/Svg.Editor.Core/) | [](https://www.nuget.org/packages/Svg.Editor.Core/) |
+| `Svg.Editor.Skia` | [](https://www.nuget.org/packages/Svg.Editor.Skia/) | [](https://www.nuget.org/packages/Svg.Editor.Skia/) |
+| `Svg.Editor.Skia.Avalonia` | [](https://www.nuget.org/packages/Svg.Editor.Skia.Avalonia/) | [](https://www.nuget.org/packages/Svg.Editor.Skia.Avalonia/) |
+| `Svg.Editor.Svg` | [](https://www.nuget.org/packages/Svg.Editor.Svg/) | [](https://www.nuget.org/packages/Svg.Editor.Svg/) |
+| `Svg.Model` | [](https://www.nuget.org/packages/Svg.Model/) | [](https://www.nuget.org/packages/Svg.Model/) |
+| `Svg.SceneGraph` | [](https://www.nuget.org/packages/Svg.SceneGraph/) | [](https://www.nuget.org/packages/Svg.SceneGraph/) |
+| `Svg.Skia` | [](https://www.nuget.org/packages/Svg.Skia/) | [](https://www.nuget.org/packages/Svg.Skia/) |
+| `Svg.Skia.Converter` | [](https://www.nuget.org/packages/Svg.Skia.Converter/) | [](https://www.nuget.org/packages/Svg.Skia.Converter/) |
+| `Svg.SourceGenerator.Skia` | [](https://www.nuget.org/packages/Svg.SourceGenerator.Skia/) | [](https://www.nuget.org/packages/Svg.SourceGenerator.Skia/) |
+| `svgc` | [](https://www.nuget.org/packages/svgc/) | [](https://www.nuget.org/packages/svgc/) |
+| `SvgToPng` | [](https://www.nuget.org/packages/SvgToPng/) | [](https://www.nuget.org/packages/SvgToPng/) |
+
*Svg.Skia* is an [SVG](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics) rendering library.
## About
diff --git a/Svg.Skia.slnx b/Svg.Skia.slnx
index 8f5b09614b..035ddfbff0 100644
--- a/Svg.Skia.slnx
+++ b/Svg.Skia.slnx
@@ -30,7 +30,7 @@
-
+
diff --git a/build/Avalonia.Diagnostics.props b/build/Avalonia.Diagnostics.props
index d809e48ed7..dd058c6baa 100644
--- a/build/Avalonia.Diagnostics.props
+++ b/build/Avalonia.Diagnostics.props
@@ -1,6 +1,6 @@
-
+
diff --git a/build/Avalonia.ReactiveUI.props b/build/ReactiveUI.Avalonia.props
similarity index 76%
rename from build/Avalonia.ReactiveUI.props
rename to build/ReactiveUI.Avalonia.props
index e1419432c0..a3e8d07f54 100644
--- a/build/Avalonia.ReactiveUI.props
+++ b/build/ReactiveUI.Avalonia.props
@@ -1,6 +1,6 @@
-
+
diff --git a/build/SkiaSharp.Native.v3.props b/build/SkiaSharp.Native.v3.props
index cdf486fa0f..96cbc5725f 100644
--- a/build/SkiaSharp.Native.v3.props
+++ b/build/SkiaSharp.Native.v3.props
@@ -1,9 +1,9 @@
-
-
-
-
+
+
+
+
diff --git a/build/SkiaSharp.v3.props b/build/SkiaSharp.v3.props
index d9689afb39..cb7734c379 100644
--- a/build/SkiaSharp.v3.props
+++ b/build/SkiaSharp.v3.props
@@ -1,6 +1,6 @@
-
+
diff --git a/build/XUnit.v3.props b/build/XUnit.v3.props
new file mode 100644
index 0000000000..8e0946d9c8
--- /dev/null
+++ b/build/XUnit.v3.props
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/samples/AvalonDraw/App.axaml.cs b/samples/AvalonDraw/App.axaml.cs
index dc10e882f7..93c8c2dfc4 100644
--- a/samples/AvalonDraw/App.axaml.cs
+++ b/samples/AvalonDraw/App.axaml.cs
@@ -1,5 +1,6 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Diagnostics;
using Avalonia.Markup.Xaml;
namespace AvalonDraw;
@@ -19,5 +20,8 @@ public override void OnFrameworkInitializationCompleted()
}
base.OnFrameworkInitializationCompleted();
+#if DEBUG
+ this.AttachDevTools();
+#endif
}
}
diff --git a/samples/AvaloniaControlsSample/App.axaml.cs b/samples/AvaloniaControlsSample/App.axaml.cs
index 06310375c7..e200fda087 100644
--- a/samples/AvaloniaControlsSample/App.axaml.cs
+++ b/samples/AvaloniaControlsSample/App.axaml.cs
@@ -1,5 +1,6 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Diagnostics;
using Avalonia.Markup.Xaml;
namespace AvaloniaControlsSample;
@@ -19,5 +20,8 @@ public override void OnFrameworkInitializationCompleted()
}
base.OnFrameworkInitializationCompleted();
+#if DEBUG
+ this.AttachDevTools();
+#endif
}
}
diff --git a/samples/AvaloniaControlsSample/MainWindow.axaml.cs b/samples/AvaloniaControlsSample/MainWindow.axaml.cs
index 1ae19c5b1e..f4946e555d 100644
--- a/samples/AvaloniaControlsSample/MainWindow.axaml.cs
+++ b/samples/AvaloniaControlsSample/MainWindow.axaml.cs
@@ -9,9 +9,6 @@ public partial class MainWindow : Window
public MainWindow()
{
InitializeComponent();
-#if DEBUG
- this.AttachDevTools();
-#endif
CanvasControl.Draw += (_, e) =>
{
e.Canvas.DrawRect(SKRect.Create(0f, 0f, 100f, 100f), new SKPaint { Color = SKColors.Aqua });
diff --git a/samples/AvaloniaSKPictureImageSample/App.axaml.cs b/samples/AvaloniaSKPictureImageSample/App.axaml.cs
index 2855c249e0..476d5c5590 100644
--- a/samples/AvaloniaSKPictureImageSample/App.axaml.cs
+++ b/samples/AvaloniaSKPictureImageSample/App.axaml.cs
@@ -1,5 +1,6 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Diagnostics;
using Avalonia.Markup.Xaml;
namespace AvaloniaSKPictureImageSample;
@@ -19,5 +20,8 @@ public override void OnFrameworkInitializationCompleted()
}
base.OnFrameworkInitializationCompleted();
+#if DEBUG
+ this.AttachDevTools();
+#endif
}
}
diff --git a/samples/AvaloniaSKPictureImageSample/AvaloniaSKPictureImageSample.csproj b/samples/AvaloniaSKPictureImageSample/AvaloniaSKPictureImageSample.csproj
index b4b2f1dd23..128bee025c 100644
--- a/samples/AvaloniaSKPictureImageSample/AvaloniaSKPictureImageSample.csproj
+++ b/samples/AvaloniaSKPictureImageSample/AvaloniaSKPictureImageSample.csproj
@@ -7,6 +7,7 @@
enable
latest
False
+ false
diff --git a/samples/AvaloniaSKPictureImageSample/MainWindow.axaml.cs b/samples/AvaloniaSKPictureImageSample/MainWindow.axaml.cs
index c314fbea7e..5dd82b5ea7 100644
--- a/samples/AvaloniaSKPictureImageSample/MainWindow.axaml.cs
+++ b/samples/AvaloniaSKPictureImageSample/MainWindow.axaml.cs
@@ -9,9 +9,6 @@ public partial class MainWindow : Window
public MainWindow()
{
InitializeComponent();
-#if DEBUG
- this.AttachDevTools();
-#endif
}
private void InitializeComponent()
diff --git a/samples/AvaloniaSvgSample/App.axaml.cs b/samples/AvaloniaSvgSample/App.axaml.cs
index 81f4980ffd..9122219dfe 100644
--- a/samples/AvaloniaSvgSample/App.axaml.cs
+++ b/samples/AvaloniaSvgSample/App.axaml.cs
@@ -1,5 +1,6 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Diagnostics;
using Avalonia.Markup.Xaml;
namespace AvaloniaSvgSample;
@@ -19,5 +20,8 @@ public override void OnFrameworkInitializationCompleted()
}
base.OnFrameworkInitializationCompleted();
+#if DEBUG
+ this.AttachDevTools();
+#endif
}
}
diff --git a/samples/AvaloniaSvgSample/MainWindow.axaml.cs b/samples/AvaloniaSvgSample/MainWindow.axaml.cs
index e43538d58c..a4b479c216 100644
--- a/samples/AvaloniaSvgSample/MainWindow.axaml.cs
+++ b/samples/AvaloniaSvgSample/MainWindow.axaml.cs
@@ -5,6 +5,7 @@
using Avalonia.Input;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
+using Avalonia.Platform.Storage;
using Avalonia.Svg;
using ShimSkiaSharp;
@@ -15,9 +16,6 @@ public partial class MainWindow : Window
public MainWindow()
{
InitializeComponent();
-#if DEBUG
- this.AttachDevTools();
-#endif
svgSvgDockPanel.AddHandler(DragDrop.DropEvent, Drop);
svgSvgDockPanel.AddHandler(DragDrop.DragOverEvent, DragOver);
@@ -89,7 +87,7 @@ private void DragOver(object sender, DragEventArgs e)
{
e.DragEffects = e.DragEffects & (DragDropEffects.Copy | DragDropEffects.Link);
- if (!e.Data.Contains(DataFormats.Files))
+ if (e.DataTransfer.TryGetFiles() is not { Length: > 0 })
{
e.DragEffects = DragDropEffects.None;
}
@@ -97,41 +95,41 @@ private void DragOver(object sender, DragEventArgs e)
private void Drop(object sender, DragEventArgs e)
{
- if (e.Data.Contains(DataFormats.Files))
+ var fileName = e.DataTransfer.TryGetFiles()?
+ .Select(file => file.TryGetLocalPath())
+ .FirstOrDefault(path => !string.IsNullOrWhiteSpace(path));
+
+ if (!string.IsNullOrWhiteSpace(fileName))
{
- var fileName = e.Data.GetFileNames()?.FirstOrDefault();
- if (!string.IsNullOrWhiteSpace(fileName))
+ if (sender == svgSvgDockPanel)
{
- if (sender == svgSvgDockPanel)
- {
- svgSvg.Path = fileName;
- }
- else if (sender == svgExtensionDockPanel)
- {
- svgExtensionImage.Source = new SvgImage
- {
- Source = SvgSource.Load(fileName, null)
- };
- }
- else if (sender == svgSourceDockPanel)
+ svgSvg.Path = fileName;
+ }
+ else if (sender == svgExtensionDockPanel)
+ {
+ svgExtensionImage.Source = new SvgImage
{
- svgSourceImage.Source = new SvgImage
- {
- Source = SvgSource.Load(fileName, null)
- };
- }
- else if (sender == svgResourceDockPanel)
+ Source = SvgSource.Load(fileName, null)
+ };
+ }
+ else if (sender == svgSourceDockPanel)
+ {
+ svgSourceImage.Source = new SvgImage
{
- svgResourceImage.Source = new SvgImage
- {
- Source = SvgSource.Load(fileName, null)
- };
- }
- else if (sender == stringTextBox || sender == svgString)
+ Source = SvgSource.Load(fileName, null)
+ };
+ }
+ else if (sender == svgResourceDockPanel)
+ {
+ svgResourceImage.Source = new SvgImage
{
- var source = File.ReadAllText(fileName);
- stringTextBox.Text = source;
- }
+ Source = SvgSource.Load(fileName, null)
+ };
+ }
+ else if (sender == stringTextBox || sender == svgString)
+ {
+ var source = File.ReadAllText(fileName);
+ stringTextBox.Text = source;
}
}
}
diff --git a/samples/AvaloniaSvgSkiaSample/App.axaml.cs b/samples/AvaloniaSvgSkiaSample/App.axaml.cs
index c50c7e0b4c..f77ff6ab2d 100644
--- a/samples/AvaloniaSvgSkiaSample/App.axaml.cs
+++ b/samples/AvaloniaSvgSkiaSample/App.axaml.cs
@@ -1,5 +1,6 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Diagnostics;
using Avalonia.Markup.Xaml;
namespace AvaloniaSvgSkiaSample;
@@ -19,5 +20,8 @@ public override void OnFrameworkInitializationCompleted()
}
base.OnFrameworkInitializationCompleted();
+#if DEBUG
+ this.AttachDevTools();
+#endif
}
}
diff --git a/samples/AvaloniaSvgSkiaSample/MainWindow.axaml.cs b/samples/AvaloniaSvgSkiaSample/MainWindow.axaml.cs
index ad72030ba5..b4bd03831c 100644
--- a/samples/AvaloniaSvgSkiaSample/MainWindow.axaml.cs
+++ b/samples/AvaloniaSvgSkiaSample/MainWindow.axaml.cs
@@ -5,6 +5,7 @@
using Avalonia.Input;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
+using Avalonia.Platform.Storage;
using Avalonia.Svg.Skia;
using ShimSkiaSharp;
@@ -15,9 +16,6 @@ public partial class MainWindow : Window
public MainWindow()
{
InitializeComponent();
-#if DEBUG
- this.AttachDevTools();
-#endif
svgSvgDockPanel.AddHandler(DragDrop.DropEvent, Drop);
svgSvgDockPanel.AddHandler(DragDrop.DragOverEvent, DragOver);
@@ -89,7 +87,7 @@ private void DragOver(object sender, DragEventArgs e)
{
e.DragEffects = e.DragEffects & (DragDropEffects.Copy | DragDropEffects.Link);
- if (!e.Data.Contains(DataFormats.Files))
+ if (e.DataTransfer.TryGetFiles() is not { Length: > 0 })
{
e.DragEffects = DragDropEffects.None;
}
@@ -97,54 +95,54 @@ private void DragOver(object sender, DragEventArgs e)
private void Drop(object sender, DragEventArgs e)
{
- if (e.Data.Contains(DataFormats.Files))
+ var fileName = e.DataTransfer.TryGetFiles()?
+ .Select(file => file.TryGetLocalPath())
+ .FirstOrDefault(path => !string.IsNullOrWhiteSpace(path));
+
+ if (!string.IsNullOrWhiteSpace(fileName))
{
- var fileName = e.Data.GetFileNames()?.FirstOrDefault();
- if (!string.IsNullOrWhiteSpace(fileName))
+ if (sender == svgSvgDockPanel)
{
- if (sender == svgSvgDockPanel)
- {
- svgSvg.Path = fileName;
- }
- else if (sender == svgExtensionDockPanel)
+ svgSvg.Path = fileName;
+ }
+ else if (sender == svgExtensionDockPanel)
+ {
+ var svg = SvgSource.Load(fileName);
+ if (svg is { })
{
- var svg = SvgSource.Load(fileName);
- if (svg is { })
+ svgExtensionImage.Source = new SvgImage
{
- svgExtensionImage.Source = new SvgImage
- {
- Source = svg
- };
- }
+ Source = svg
+ };
}
- else if (sender == svgSourceDockPanel)
+ }
+ else if (sender == svgSourceDockPanel)
+ {
+ var svg = SvgSource.Load(fileName);
+ if (svg is { })
{
- var svg = SvgSource.Load(fileName);
- if (svg is { })
+ svgSourceImage.Source = new SvgImage
{
- svgSourceImage.Source = new SvgImage
- {
- Source = svg
- };
- }
+ Source = svg
+ };
}
- else if (sender == svgResourceDockPanel)
+ }
+ else if (sender == svgResourceDockPanel)
+ {
+ var svg = SvgSource.Load(fileName);
+ if (svg is { })
{
- var svg = SvgSource.Load(fileName);
- if (svg is { })
+ svgResourceImage.Source = new SvgImage
{
- svgResourceImage.Source = new SvgImage
- {
- Source = svg
- };
- }
- }
- else if (sender == stringTextBox || sender == svgString)
- {
- var source = File.ReadAllText(fileName);
- stringTextBox.Text = source;
+ Source = svg
+ };
}
}
+ else if (sender == stringTextBox || sender == svgString)
+ {
+ var source = File.ReadAllText(fileName);
+ stringTextBox.Text = source;
+ }
}
}
diff --git a/samples/AvaloniaSvgSkiaStylingSample/App.axaml.cs b/samples/AvaloniaSvgSkiaStylingSample/App.axaml.cs
index 0c33b33fe6..b094a37b67 100644
--- a/samples/AvaloniaSvgSkiaStylingSample/App.axaml.cs
+++ b/samples/AvaloniaSvgSkiaStylingSample/App.axaml.cs
@@ -1,5 +1,6 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Diagnostics;
using Avalonia.Markup.Xaml;
namespace AvaloniaSvgSkiaStylingSample;
@@ -19,5 +20,8 @@ public override void OnFrameworkInitializationCompleted()
}
base.OnFrameworkInitializationCompleted();
+#if DEBUG
+ this.AttachDevTools();
+#endif
}
}
diff --git a/samples/AvaloniaSvgSkiaStylingSample/MainWindow.axaml.cs b/samples/AvaloniaSvgSkiaStylingSample/MainWindow.axaml.cs
index db7b1c4d5e..52f5fc8858 100644
--- a/samples/AvaloniaSvgSkiaStylingSample/MainWindow.axaml.cs
+++ b/samples/AvaloniaSvgSkiaStylingSample/MainWindow.axaml.cs
@@ -12,9 +12,6 @@ public partial class MainWindow : Window
public MainWindow()
{
InitializeComponent();
-#if DEBUG
- this.AttachDevTools();
-#endif
ApplySvgStyleButton.Click += ApplySvgStyleButtonClick;
ApplySvgImageStyleButton.Click += ApplySvgImageStyleButtonClick;
}
diff --git a/samples/TestApp/App.axaml.cs b/samples/TestApp/App.axaml.cs
index 1a4bb0432c..96699bc176 100644
--- a/samples/TestApp/App.axaml.cs
+++ b/samples/TestApp/App.axaml.cs
@@ -3,6 +3,7 @@
using System.IO;
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Diagnostics;
using Avalonia.Markup.Xaml;
using TestApp.Services;
using TestApp.ViewModels;
@@ -79,5 +80,8 @@ public override void OnFrameworkInitializationCompleted()
}
base.OnFrameworkInitializationCompleted();
+#if DEBUG
+ this.AttachDevTools();
+#endif
}
}
diff --git a/samples/TestApp/Services/StorageService.cs b/samples/TestApp/Services/StorageService.cs
index 46a4bd4ab4..73a935f028 100644
--- a/samples/TestApp/Services/StorageService.cs
+++ b/samples/TestApp/Services/StorageService.cs
@@ -159,10 +159,11 @@ public async Task> PickSvgPathsAsync(CancellationToken can
return window.StorageProvider;
}
- if (Application.Current?.ApplicationLifetime is ISingleViewApplicationLifetime { MainView: { } mainView })
+ if (Application.Current?.ApplicationLifetime is ISingleViewApplicationLifetime { MainView: { } mainView } &&
+ mainView is Visual visual)
{
- var visualRoot = mainView.GetVisualRoot();
- if (visualRoot is TopLevel topLevel)
+ var topLevel = TopLevel.GetTopLevel(visual);
+ if (topLevel is not null)
{
return topLevel.StorageProvider;
}
diff --git a/samples/TestApp/TestApp.csproj b/samples/TestApp/TestApp.csproj
index d2f9f32143..7f5a759eaf 100644
--- a/samples/TestApp/TestApp.csproj
+++ b/samples/TestApp/TestApp.csproj
@@ -8,6 +8,9 @@
TestApp
+
+ false
+
@@ -26,5 +29,4 @@
-
diff --git a/samples/TestApp/Views/MainView.axaml b/samples/TestApp/Views/MainView.axaml
index 1f53613e17..8d75ab6210 100644
--- a/samples/TestApp/Views/MainView.axaml
+++ b/samples/TestApp/Views/MainView.axaml
@@ -21,7 +21,7 @@
Grid.Row="0"
Margin="6"
Text="{Binding ItemQuery}"
- Watermark="Filter...">
+ PlaceholderText="Filter...">
diff --git a/samples/TestApp/Views/MainWindow.axaml.cs b/samples/TestApp/Views/MainWindow.axaml.cs
index 8e4025db19..5101667d41 100644
--- a/samples/TestApp/Views/MainWindow.axaml.cs
+++ b/samples/TestApp/Views/MainWindow.axaml.cs
@@ -16,9 +16,6 @@ public partial class MainWindow : Window
public MainWindow()
{
InitializeComponent();
-#if DEBUG
- this.AttachDevTools();
-#endif
}
private void InitializeComponent()
diff --git a/samples/svgc/svgc.csproj b/samples/svgc/svgc.csproj
index 4f16067042..437278f4b6 100644
--- a/samples/svgc/svgc.csproj
+++ b/samples/svgc/svgc.csproj
@@ -28,7 +28,6 @@
-
diff --git a/site/articles/reference/api-coverage-index.md b/site/articles/reference/api-coverage-index.md
index 77a1f03510..1fc03d9612 100644
--- a/site/articles/reference/api-coverage-index.md
+++ b/site/articles/reference/api-coverage-index.md
@@ -26,20 +26,21 @@ The generated API reference under `/api` is built from these projects:
Current API settings:
- configuration: `Release`
-- target framework override: `netstandard2.0`
+- default target framework override: `netstandard2.0`
+- Avalonia 12 project overrides:
+ `Svg.Controls.Avalonia`, `Svg.Controls.Skia.Avalonia`, `Skia.Controls.Avalonia`, `Svg.Editor.Avalonia`, and `Svg.Editor.Skia.Avalonia` build API metadata with `net8.0`
- output path: `/api`
-The Uno control project uses a per-project override of `TargetFramework=net10.0` because it does not target `netstandard2.0`.
-
-## Why `netstandard2.0`
+## Why mixed target frameworks
This repository mixes:
- multi-target runtime packages,
- multi-target editor packages,
+- a `net10.0` Uno control package,
- `netstandard2.0`-only generator packages.
-Using `netstandard2.0` as the documentation build target keeps the API site aligned across the documented assemblies without having to split the API generation into multiple passes.
+The docs build keeps `netstandard2.0` as the default extraction target for the shared runtime and generator-facing packages, while overriding the Avalonia 12 packages to `net8.0`. The Uno control project uses a per-project override of `TargetFramework=net10.0` because it does not target `netstandard2.0`. That keeps a single API site without forcing the Avalonia or Uno projects back onto frameworks they no longer target.
## `Svg.CodeGen.Skia`
diff --git a/site/articles/reference/lunet-docs-pipeline.md b/site/articles/reference/lunet-docs-pipeline.md
index 478bed5896..539124aa93 100644
--- a/site/articles/reference/lunet-docs-pipeline.md
+++ b/site/articles/reference/lunet-docs-pipeline.md
@@ -26,7 +26,8 @@ API docs are generated by Lunet `api.dotnet` from the library projects listed in
Current settings:
- `Release` configuration
-- `TargetFramework: netstandard2.0`
+- default `TargetFramework: netstandard2.0`
+- per-project `TargetFramework: net8.0` overrides for the Avalonia 12 packages
- output under `/api`
- Avalonia xrefs pointed at `https://api-docs.avaloniaui.net/docs`
@@ -82,4 +83,4 @@ All commands operate in `site/` and publish to `site/.lunet/build/www`.
## CI publishing
-`.github/workflows/docs.yml` restores the local Lunet tool, builds the site, and deploys `site/.lunet/build/www` to GitHub Pages on pushes to `main` or `master`.
+`.github/workflows/docs.yml` restores the local Lunet tool, builds the site for pull requests and pushes to `master` or `main`, and deploys `site/.lunet/build/www` to GitHub Pages only from the repository's default branch.
diff --git a/site/config.scriban b/site/config.scriban
index 92eeb8761e..1320b71e63 100644
--- a/site/config.scriban
+++ b/site/config.scriban
@@ -76,15 +76,15 @@ with api.dotnet
{ name: "Svg.Skia", path: "../src/Svg.Skia/Svg.Skia.csproj" },
{ name: "Svg.Model", path: "../src/Svg.Model/Svg.Model.csproj" },
{ name: "Svg.Custom", path: "../src/Svg.Custom/Svg.Custom.csproj" },
- { name: "Svg.Controls.Avalonia", path: "../src/Svg.Controls.Avalonia/Svg.Controls.Avalonia.csproj" },
- { name: "Svg.Controls.Skia.Avalonia", path: "../src/Svg.Controls.Skia.Avalonia/Svg.Controls.Skia.Avalonia.csproj" },
+ { name: "Svg.Controls.Avalonia", path: "../src/Svg.Controls.Avalonia/Svg.Controls.Avalonia.csproj", properties: { TargetFramework: "net8.0" } },
+ { name: "Svg.Controls.Skia.Avalonia", path: "../src/Svg.Controls.Skia.Avalonia/Svg.Controls.Skia.Avalonia.csproj", properties: { TargetFramework: "net8.0" } },
+ { name: "Skia.Controls.Avalonia", path: "../src/Skia.Controls.Avalonia/Skia.Controls.Avalonia.csproj", properties: { TargetFramework: "net8.0" } },
{ name: "Svg.Controls.Skia.Uno", path: "../src/Svg.Controls.Skia.Uno/Svg.Controls.Skia.Uno.csproj", properties: { TargetFramework: "net10.0" } },
- { name: "Skia.Controls.Avalonia", path: "../src/Skia.Controls.Avalonia/Skia.Controls.Avalonia.csproj" },
{ name: "Svg.Editor.Core", path: "../src/Svg.Editor.Core/Svg.Editor.Core.csproj" },
{ name: "Svg.Editor.Svg", path: "../src/Svg.Editor.Svg/Svg.Editor.Svg.csproj" },
{ name: "Svg.Editor.Skia", path: "../src/Svg.Editor.Skia/Svg.Editor.Skia.csproj" },
- { name: "Svg.Editor.Avalonia", path: "../src/Svg.Editor.Avalonia/Svg.Editor.Avalonia.csproj" },
- { name: "Svg.Editor.Skia.Avalonia", path: "../src/Svg.Editor.Skia.Avalonia/Svg.Editor.Skia.Avalonia.csproj" },
+ { name: "Svg.Editor.Avalonia", path: "../src/Svg.Editor.Avalonia/Svg.Editor.Avalonia.csproj", properties: { TargetFramework: "net8.0" } },
+ { name: "Svg.Editor.Skia.Avalonia", path: "../src/Svg.Editor.Skia.Avalonia/Svg.Editor.Skia.Avalonia.csproj", properties: { TargetFramework: "net8.0" } },
{ name: "ShimSkiaSharp", path: "../src/ShimSkiaSharp/ShimSkiaSharp.csproj" },
{ name: "Svg.SourceGenerator.Skia", path: "../src/Svg.SourceGenerator.Skia/Svg.SourceGenerator.Skia.csproj" }
]
diff --git a/src/Skia.Controls.Avalonia/Skia.Controls.Avalonia.csproj b/src/Skia.Controls.Avalonia/Skia.Controls.Avalonia.csproj
index 703d284c07..72e8a7e667 100644
--- a/src/Skia.Controls.Avalonia/Skia.Controls.Avalonia.csproj
+++ b/src/Skia.Controls.Avalonia/Skia.Controls.Avalonia.csproj
@@ -2,7 +2,7 @@
Library
- netstandard2.0;net461;net6.0;net8.0;net10.0
+ net8.0;net10.0
False
False
CS1591
diff --git a/src/Svg.Controls.Avalonia/AvaloniaSvgAssetLoader.cs b/src/Svg.Controls.Avalonia/AvaloniaSvgAssetLoader.cs
index 5519ae4519..c773d026f6 100644
--- a/src/Svg.Controls.Avalonia/AvaloniaSvgAssetLoader.cs
+++ b/src/Svg.Controls.Avalonia/AvaloniaSvgAssetLoader.cs
@@ -14,6 +14,15 @@ namespace Avalonia.Svg;
///
public class AvaloniaSvgAssetLoader : SM.ISvgAssetLoader
{
+ private static float GetGlyphAdvance(GlyphTypeface glyphTypeface, int codepoint)
+ {
+ var glyphId = glyphTypeface.CharacterToGlyphMap.GetGlyph(codepoint);
+
+ return glyphTypeface.TryGetHorizontalGlyphAdvance(glyphId, out var advance)
+ ? advance / (float)glyphTypeface.Metrics.DesignEmHeight
+ : 0f;
+ }
+
///
public bool EnableSvgFonts => true;
@@ -118,7 +127,7 @@ runningTypeface is not { } typeface
}
var glyphTypeface = (typeface ?? Typeface.Default).GlyphTypeface;
- runningAdvance += glyphTypeface.GetGlyphAdvance(glyphTypeface.GetGlyph((uint)codepoint));
+ runningAdvance += GetGlyphAdvance(glyphTypeface, codepoint);
if (char.IsHighSurrogate(text[i]))
{
@@ -162,7 +171,7 @@ public float MeasureText(string? text, SKPaint paint, ref SKRect bounds)
for (int i = 0; i < text.Length; i++)
{
var codepoint = char.ConvertToUtf32(text, i);
- advance += glyphTypeface.GetGlyphAdvance(glyphTypeface.GetGlyph((uint)codepoint));
+ advance += GetGlyphAdvance(glyphTypeface, codepoint);
if (char.IsHighSurrogate(text[i]))
{
i++;
diff --git a/src/Svg.Controls.Avalonia/Svg.Controls.Avalonia.csproj b/src/Svg.Controls.Avalonia/Svg.Controls.Avalonia.csproj
index c869f80d13..3f4e8680ac 100644
--- a/src/Svg.Controls.Avalonia/Svg.Controls.Avalonia.csproj
+++ b/src/Svg.Controls.Avalonia/Svg.Controls.Avalonia.csproj
@@ -2,7 +2,7 @@
Library
- netstandard2.0;net461;net6.0;net8.0;net10.0
+ net8.0;net10.0
False
False
CS1591
diff --git a/src/Svg.Controls.Skia.Avalonia/Svg.Controls.Skia.Avalonia.csproj b/src/Svg.Controls.Skia.Avalonia/Svg.Controls.Skia.Avalonia.csproj
index 64bc2a8830..330ff13f5b 100644
--- a/src/Svg.Controls.Skia.Avalonia/Svg.Controls.Skia.Avalonia.csproj
+++ b/src/Svg.Controls.Skia.Avalonia/Svg.Controls.Skia.Avalonia.csproj
@@ -2,7 +2,7 @@
Library
- netstandard2.0;net461;net6.0;net8.0;net10.0
+ net8.0;net10.0
False
False
CS1591
diff --git a/src/Svg.Editor.Avalonia/Controls/DocumentOutlineView.axaml b/src/Svg.Editor.Avalonia/Controls/DocumentOutlineView.axaml
index 7541a0ef8f..dde2d63f44 100644
--- a/src/Svg.Editor.Avalonia/Controls/DocumentOutlineView.axaml
+++ b/src/Svg.Editor.Avalonia/Controls/DocumentOutlineView.axaml
@@ -13,7 +13,7 @@
+ PlaceholderText="Filter properties" />
Library
- netstandard2.0;net461;net6.0;net8.0;net10.0
+ net8.0;net10.0
+ false
False
False
True
diff --git a/src/Svg.Editor.Avalonia/SymbolNameEditorView.axaml b/src/Svg.Editor.Avalonia/SymbolNameEditorView.axaml
index d86cad5681..d95ccc1318 100644
--- a/src/Svg.Editor.Avalonia/SymbolNameEditorView.axaml
+++ b/src/Svg.Editor.Avalonia/SymbolNameEditorView.axaml
@@ -2,7 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Svg.Editor.Avalonia.SymbolNameEditorView">
-
+
diff --git a/src/Svg.Editor.Avalonia/SymbolPickerView.axaml.cs b/src/Svg.Editor.Avalonia/SymbolPickerView.axaml.cs
index a440eb5892..2e6e5b71d4 100644
--- a/src/Svg.Editor.Avalonia/SymbolPickerView.axaml.cs
+++ b/src/Svg.Editor.Avalonia/SymbolPickerView.axaml.cs
@@ -41,7 +41,7 @@ private void CancelButton_OnClick(object? sender, RoutedEventArgs e)
Cancel();
}
- private void SymbolList_OnGotFocus(object? sender, GotFocusEventArgs e)
+ private void SymbolList_OnGotFocus(object? sender, FocusChangedEventArgs e)
{
_symbolList.IsDropDownOpen = true;
}
diff --git a/src/Svg.Editor.Skia.Avalonia/Svg.Editor.Skia.Avalonia.csproj b/src/Svg.Editor.Skia.Avalonia/Svg.Editor.Skia.Avalonia.csproj
index ef93904356..b97f7abd1f 100644
--- a/src/Svg.Editor.Skia.Avalonia/Svg.Editor.Skia.Avalonia.csproj
+++ b/src/Svg.Editor.Skia.Avalonia/Svg.Editor.Skia.Avalonia.csproj
@@ -2,7 +2,7 @@
Library
- netstandard2.0;net461;net6.0;net8.0;net10.0
+ net8.0;net10.0
False
False
True
diff --git a/src/Svg.Editor.Skia.Avalonia/SvgEditorWorkspace.axaml.cs b/src/Svg.Editor.Skia.Avalonia/SvgEditorWorkspace.axaml.cs
index 1c3f302e8b..50a1018740 100644
--- a/src/Svg.Editor.Skia.Avalonia/SvgEditorWorkspace.axaml.cs
+++ b/src/Svg.Editor.Skia.Avalonia/SvgEditorWorkspace.axaml.cs
@@ -16,6 +16,7 @@
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Platform;
+using Avalonia.Platform.Storage;
using Avalonia.Svg.Skia;
using Avalonia.Threading;
using Svg;
@@ -38,6 +39,7 @@ namespace Svg.Editor.Skia.Avalonia;
public partial class SvgEditorWorkspace : UserControl
{
private const string DefaultWorkspaceTitlePrefix = "SVG Editor";
+ private static readonly DataFormat SvgNodeDragFormat = DataFormat.CreateStringApplicationFormat("SvgNode");
private struct DragInfo
{
@@ -132,6 +134,7 @@ private bool _includeHidden
private ContextMenu? _treeMenu;
private ContextMenu? _pathMenu;
private SvgNode? _dragNode;
+ private PointerPressedEventArgs? _treeDragPressedEventArgs;
private Point _treeDragStart;
private bool _treeDragging;
@@ -692,21 +695,20 @@ private async void PlaceImageMenuItem_Click(object? sender, RoutedEventArgs e)
private void Window_OnDragOver(object? sender, DragEventArgs e)
{
- if (e.Data.Contains(DataFormats.FileNames))
+ if (e.DataTransfer.TryGetFiles()?.Any() == true)
e.DragEffects = DragDropEffects.Copy;
}
private async void Window_OnDrop(object? sender, DragEventArgs e)
{
- if (e.Data.Contains(DataFormats.FileNames))
+ var file = e.DataTransfer.TryGetFiles()?
+ .Select(x => x.TryGetLocalPath())
+ .FirstOrDefault(x => !string.IsNullOrWhiteSpace(x));
+
+ if (!string.IsNullOrWhiteSpace(file))
{
- var files = e.Data.GetFileNames();
- var file = files?.FirstOrDefault();
- if (!string.IsNullOrEmpty(file))
- {
- LoadDocument(file!);
- SvgView.InvalidateVisual();
- }
+ LoadDocument(file!);
+ SvgView.InvalidateVisual();
}
}
@@ -2136,7 +2138,7 @@ private void SaveExpandedNodes(TreeViewItem item, SvgNode node)
ExpandedNodeIds.Add(node.Element.ID);
for (var i = 0; i < node.Children.Count; i++)
{
- if (item.ItemContainerGenerator.ContainerFromIndex(i) is TreeViewItem child)
+ if (item.ContainerFromIndex(i) is TreeViewItem child)
SaveExpandedNodes(child, node.Children[i]);
}
}
@@ -2155,7 +2157,7 @@ private void RestoreExpandedNodes(TreeViewItem item, SvgNode node)
item.IsExpanded = true;
for (var i = 0; i < node.Children.Count; i++)
{
- if (item.ItemContainerGenerator.ContainerFromIndex(i) is TreeViewItem child)
+ if (item.ContainerFromIndex(i) is TreeViewItem child)
RestoreExpandedNodes(child, node.Children[i]);
}
}
@@ -3220,6 +3222,7 @@ private void DocumentTree_OnPointerPressed(object? sender, PointerPressedEventAr
}
_dragNode = DocumentTree.SelectedItem as SvgNode;
+ _treeDragPressedEventArgs = e;
_treeDragStart = e.GetCurrentPoint(DocumentTree).Position;
_treeDragging = false;
}
@@ -3235,10 +3238,16 @@ private async void DocumentTree_OnPointerMoved(object? sender, PointerEventArgs
return;
_treeDragging = true;
}
- var data = new DataObject();
- data.Set("SvgNode", node);
- await DragDrop.DoDragDrop(e, data, DragDropEffects.Move);
+ var data = new DataTransfer();
+ data.Add(DataTransferItem.Create(SvgNodeDragFormat, node.Element.ID ?? string.Empty));
+ if (_treeDragPressedEventArgs is null)
+ {
+ return;
+ }
+
+ await DragDrop.DoDragDropAsync(_treeDragPressedEventArgs, data, DragDropEffects.Move);
_dragNode = null;
+ _treeDragPressedEventArgs = null;
_treeDragging = false;
}
}
@@ -3246,12 +3255,13 @@ private async void DocumentTree_OnPointerMoved(object? sender, PointerEventArgs
private void DocumentTree_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
{
_dragNode = null;
+ _treeDragPressedEventArgs = null;
_treeDragging = false;
}
private void DocumentTree_OnDragOver(object? sender, DragEventArgs e)
{
- if (!e.Data.Contains("SvgNode"))
+ if (!e.DataTransfer.Contains(SvgNodeDragFormat))
{
HideDropIndicator();
return;
@@ -3307,62 +3317,59 @@ private void DocumentTree_OnDragLeave(object? sender, RoutedEventArgs e)
private void DocumentTree_OnDrop(object? sender, DragEventArgs e)
{
- if (!e.Data.Contains("SvgNode") || _dropTarget is null)
+ if (!e.DataTransfer.Contains(SvgNodeDragFormat) || _dropTarget is null || _dragNode is not { } node)
{
HideDropIndicator();
return;
}
- if (e.Data.Get("SvgNode") is SvgNode node)
+ var target = _dropTarget;
+ if (node == target || IsAncestor(node, target) || node.Parent is null)
{
- var target = _dropTarget;
- if (node == target || IsAncestor(node, target) || node.Parent is null)
- {
- HideDropIndicator();
- return;
- }
-
- SaveUndoState();
- SaveExpandedNodes();
- node.Parent.Element.Children.Remove(node.Element);
+ HideDropIndicator();
+ return;
+ }
- switch (_dropPosition)
- {
- case DropPosition.Before:
- if (target.Parent?.Element is SvgElement parentBefore)
- {
- var index = parentBefore.Children.IndexOf(target.Element);
- if (index < 0)
- index = parentBefore.Children.Count;
- if (index >= parentBefore.Children.Count)
- parentBefore.Children.Add(node.Element);
- else
- parentBefore.Children.Insert(index, node.Element);
- }
- break;
- case DropPosition.After:
- if (target.Parent?.Element is SvgElement parentAfter)
- {
- var index = parentAfter.Children.IndexOf(target.Element);
- if (index < 0)
- index = parentAfter.Children.Count - 1;
- if (index + 1 >= parentAfter.Children.Count)
- parentAfter.Children.Add(node.Element);
- else
- parentAfter.Children.Insert(index + 1, node.Element);
- }
- break;
- default:
- target.Element.Children.Add(node.Element);
- break;
- }
+ SaveUndoState();
+ SaveExpandedNodes();
+ node.Parent.Element.Children.Remove(node.Element);
- SvgView.SkSvg!.FromSvgDocument(_document);
- BuildTree();
- SelectNodeFromElement(node.Element);
- SvgView.InvalidateVisual();
+ switch (_dropPosition)
+ {
+ case DropPosition.Before:
+ if (target.Parent?.Element is SvgElement parentBefore)
+ {
+ var index = parentBefore.Children.IndexOf(target.Element);
+ if (index < 0)
+ index = parentBefore.Children.Count;
+ if (index >= parentBefore.Children.Count)
+ parentBefore.Children.Add(node.Element);
+ else
+ parentBefore.Children.Insert(index, node.Element);
+ }
+ break;
+ case DropPosition.After:
+ if (target.Parent?.Element is SvgElement parentAfter)
+ {
+ var index = parentAfter.Children.IndexOf(target.Element);
+ if (index < 0)
+ index = parentAfter.Children.Count - 1;
+ if (index + 1 >= parentAfter.Children.Count)
+ parentAfter.Children.Add(node.Element);
+ else
+ parentAfter.Children.Insert(index + 1, node.Element);
+ }
+ break;
+ default:
+ target.Element.Children.Add(node.Element);
+ break;
}
+ SvgView.SkSvg!.FromSvgDocument(_document);
+ BuildTree();
+ SelectNodeFromElement(node.Element);
+ SvgView.InvalidateVisual();
+
HideDropIndicator();
_dropTarget = null;
_dropPosition = DropPosition.None;
diff --git a/tests/Avalonia.Svg.Skia.UiTests/Avalonia.Svg.Skia.UiTests.csproj b/tests/Avalonia.Svg.Skia.UiTests/Avalonia.Svg.Skia.UiTests.csproj
index 138e87ed8e..d2fc89fd08 100644
--- a/tests/Avalonia.Svg.Skia.UiTests/Avalonia.Svg.Skia.UiTests.csproj
+++ b/tests/Avalonia.Svg.Skia.UiTests/Avalonia.Svg.Skia.UiTests.csproj
@@ -7,13 +7,10 @@
enable
-
-
-
diff --git a/tests/Svg.Controls.Avalonia.UnitTests/Svg.Controls.Avalonia.UnitTests.csproj b/tests/Svg.Controls.Avalonia.UnitTests/Svg.Controls.Avalonia.UnitTests.csproj
index e9cb1962a7..aad3e975c4 100644
--- a/tests/Svg.Controls.Avalonia.UnitTests/Svg.Controls.Avalonia.UnitTests.csproj
+++ b/tests/Svg.Controls.Avalonia.UnitTests/Svg.Controls.Avalonia.UnitTests.csproj
@@ -2,14 +2,14 @@
net10.0
- Library
+ Exe
False
enable
Avalonia.Svg.UnitTests
-
+
diff --git a/tests/Svg.Controls.Skia.Avalonia.UnitTests/Svg.Controls.Skia.Avalonia.UnitTests.csproj b/tests/Svg.Controls.Skia.Avalonia.UnitTests/Svg.Controls.Skia.Avalonia.UnitTests.csproj
index 2cab770448..e57e68c140 100644
--- a/tests/Svg.Controls.Skia.Avalonia.UnitTests/Svg.Controls.Skia.Avalonia.UnitTests.csproj
+++ b/tests/Svg.Controls.Skia.Avalonia.UnitTests/Svg.Controls.Skia.Avalonia.UnitTests.csproj
@@ -2,14 +2,14 @@
net10.0
- Library
+ Exe
False
enable
Avalonia.Svg.Skia.UnitTests
-
+
diff --git a/tests/Svg.Editor.Skia.Avalonia.UnitTests/Svg.Editor.Skia.Avalonia.UnitTests.csproj b/tests/Svg.Editor.Skia.Avalonia.UnitTests/Svg.Editor.Skia.Avalonia.UnitTests.csproj
index 69ed3da87b..eea82096ae 100644
--- a/tests/Svg.Editor.Skia.Avalonia.UnitTests/Svg.Editor.Skia.Avalonia.UnitTests.csproj
+++ b/tests/Svg.Editor.Skia.Avalonia.UnitTests/Svg.Editor.Skia.Avalonia.UnitTests.csproj
@@ -2,14 +2,14 @@
net10.0
- Library
+ Exe
False
enable
Svg.Editor.Skia.Avalonia.UnitTests
-
+