Skip to content

Commit

Permalink
fixed issue 206, added tests
Browse files Browse the repository at this point in the history
  • Loading branch information
RomanKalachik authored and wieslawsoltes committed Mar 14, 2024
1 parent 61990af commit 3837ce8
Show file tree
Hide file tree
Showing 9 changed files with 2,252 additions and 30 deletions.
39 changes: 21 additions & 18 deletions src/Avalonia.Svg.Skia/SvgCustomDrawOperation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,28 @@ public void Dispose()

public void Render(ImmediateDrawingContext context)
{
if (_svg?.Picture is null)
lock (_svg.Locker)
{
return;
if (_svg?.Picture is null)
{
return;
}

var leaseFeature = context.TryGetFeature<ISkiaSharpApiLeaseFeature>();
if (leaseFeature is null)
{
return;
}
using var lease = leaseFeature.Lease();
var canvas = lease?.SkCanvas;
if (canvas is null)
{
return;
}

canvas.Save();
canvas.DrawPicture(_svg.Picture);
canvas.Restore();
}

var leaseFeature = context.TryGetFeature<ISkiaSharpApiLeaseFeature>();
if (leaseFeature is null)
{
return;
}
using var lease = leaseFeature.Lease();
var canvas = lease?.SkCanvas;
if (canvas is null)
{
return;
}

canvas.Save();
canvas.DrawPicture(_svg.Picture);
canvas.Restore();
}
}
27 changes: 16 additions & 11 deletions src/Svg.Skia/SKSvg.Model.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ public static void Draw(SkiaSharp.SKCanvas skCanvas, string path, SkiaModel skia

public virtual SkiaSharp.SKPicture? Picture { get; protected set; }

public object Locker { get; } = new object();

public SvgParameters? Parameters => _originalParameters;

public SKSvg()
Expand Down Expand Up @@ -181,23 +183,26 @@ public SKSvg()

public SkiaSharp.SKPicture? ReLoad(SvgParameters? parameters)
{
if (!CacheOriginalStream)
lock (Locker)
{
throw new ArgumentException($"Enable {nameof(CacheOriginalStream)} feature toggle to enable reload feature.");
}
if (!CacheOriginalStream)
{
throw new ArgumentException($"Enable {nameof(CacheOriginalStream)} feature toggle to enable reload feature.");
}

Reset();
Reset();

_originalParameters = parameters;
_originalParameters = parameters;

if (_originalStream == null)
{
return Load(_originalPath, parameters);
}
if (_originalStream == null)
{
return Load(_originalPath, parameters);
}

_originalStream.Position = 0;
_originalStream.Position = 0;

return Load(_originalStream, parameters);
return Load(_originalStream, parameters);
}
}

public SkiaSharp.SKPicture? FromSvg(string svg)
Expand Down
7 changes: 7 additions & 0 deletions tests/Avalonia.Svg.Skia.UnitTests/App.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="UITests.App" RequestedThemeVariant="Light">
<Application.Styles>
<FluentTheme />
</Application.Styles>
</Application>
25 changes: 25 additions & 0 deletions tests/Avalonia.Svg.Skia.UnitTests/App.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls.Primitives;
using Avalonia.Markup.Xaml;

namespace UITests
{
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}

public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new Window();
}
base.OnFrameworkInitializationCompleted();
}
}
}
1,978 changes: 1,978 additions & 0 deletions tests/Avalonia.Svg.Skia.UnitTests/Assets/__tiger.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
<Import Project="..\..\build\SkiaSharp.Linux.props" />
<Import Project="..\..\build\HarfBuzzSharp.NativeAssets.Linux.props" />
<Import Project="..\..\build\Avalonia.props" />
<Import Project="..\..\build\Avalonia.Desktop.props" />
<Import Project="..\..\build\Avalonia.Skia.props" />

<Import Project="..\..\build\Avalonia.Themes.Fluent.props" />

<ItemGroup>
<AvaloniaResource Include="Assets\*" />
</ItemGroup>
Expand Down
33 changes: 33 additions & 0 deletions tests/Avalonia.Svg.Skia.UnitTests/AvaloniaApp.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Threading;

namespace UITests
{
public static class AvaloniaApp
{
public static void Stop()
{
var app = GetApp();
if (app is IDisposable disposable)
{
Dispatcher.UIThread.Post(disposable.Dispose);
}

if (app != null)
Dispatcher.UIThread.Post(() => app.Shutdown());
}

public static Window? GetMainWindow() => GetApp()?.MainWindow;

public static IClassicDesktopStyleApplicationLifetime? GetApp() =>
(IClassicDesktopStyleApplicationLifetime?)Application.Current?.ApplicationLifetime;

public static AppBuilder BuildAvaloniaApp() =>
AppBuilder
.Configure<App>()
.UsePlatformDetect();
}
}
112 changes: 112 additions & 0 deletions tests/Avalonia.Svg.Skia.UnitTests/AvaloniaUiTestFramework.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

using Avalonia;

using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;

[assembly: TestFramework("UITests.AvaloniaUiTestFramework", "Avalonia.Svg.Skia.UnitTests")]
[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly, DisableTestParallelization = true, MaxParallelThreads = 1)]
namespace UITests
{

public class AvaloniaUiTestFramework : XunitTestFramework
{
public AvaloniaUiTestFramework(IMessageSink messageSink)
: base(messageSink)
{
}

protected override ITestFrameworkExecutor CreateExecutor(AssemblyName assemblyName)
=> new Executor(assemblyName, SourceInformationProvider, DiagnosticMessageSink);

private class Executor : XunitTestFrameworkExecutor
{
public Executor(
AssemblyName assemblyName,
ISourceInformationProvider sourceInformationProvider,
IMessageSink diagnosticMessageSink)
: base(
assemblyName,
sourceInformationProvider,
diagnosticMessageSink)
{

}

protected override async void RunTestCases(IEnumerable<IXunitTestCase> testCases,
IMessageSink executionMessageSink,
ITestFrameworkExecutionOptions executionOptions)
{
executionOptions.SetValue("xunit.execution.DisableParallelization", false);
using var assemblyRunner = new Runner(
TestAssembly, testCases, DiagnosticMessageSink, executionMessageSink,
executionOptions);

await assemblyRunner.RunAsync();
}
}

private class Runner : XunitTestAssemblyRunner
{
public Runner(
ITestAssembly testAssembly,
IEnumerable<IXunitTestCase> testCases,
IMessageSink diagnosticMessageSink,
IMessageSink executionMessageSink,
ITestFrameworkExecutionOptions executionOptions)
: base(
testAssembly,
testCases,
diagnosticMessageSink,
executionMessageSink,
executionOptions)
{

}

public override void Dispose()
{
AvaloniaApp.Stop();

base.Dispose();
}

protected override void SetupSyncContext(int maxParallelThreads)
{
var tcs = new TaskCompletionSource<SynchronizationContext>();
var thread = new Thread(() =>
{
try
{
//AvaloniaApp.RegisterDependencies();

AvaloniaApp
.BuildAvaloniaApp()
.AfterSetup(_ =>
{
tcs.SetResult(SynchronizationContext.Current!);
})
.StartWithClassicDesktopLifetime(new string[0]);
}
catch (Exception e)
{
tcs.SetException(e);
}
})
{
IsBackground = true
};

thread.Start();

SynchronizationContext.SetSynchronizationContext(tcs.Task.Result);
}
}
}
}
57 changes: 57 additions & 0 deletions tests/Avalonia.Svg.Skia.UnitTests/SvgImageReloadTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
using Avalonia.Threading;
using Svg.Skia;
using Xunit;

namespace Avalonia.Svg.Skia.UnitTests;

public class SvgImageReloadTests
{
Image test;
private string css = ".Black { fill: #FF0000; }";
Window window;
[Fact]
public async void SvgImage_ReLoad()
{
SKSvg.CacheOriginalStream = true;
var uri = new Uri($"avares://Avalonia.Svg.Skia.UnitTests/Assets/__tiger.svg");
var assetLoader = new StandardAssetLoader(); // AvaloniaLocator.Current.GetService<IAssetLoader>()

var svgFile = assetLoader.Open(uri);

var svgSource = SvgSource.LoadFromStream(svgFile);
var svgImage = new SvgImage() { Source = svgSource };

test = new Image();
test.Source = svgImage;

window = new Window();
window.Content = test;
window.Show();

var timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(10);
timer.Tick += Timer_Tick;
timer.Start();

await Task.Delay(10000);

timer?.Stop();
window?.Close();
}



private void Timer_Tick(object sender, EventArgs e)
{
var image = (SvgImage)test.Source;
(image.CurrentCss, css) = (css, image.CurrentCss);
test.InvalidateVisual();
}
}

0 comments on commit 3837ce8

Please sign in to comment.