diff --git a/appveyor.yml b/appveyor.yml
index 6b63176a89..7457a1d5bb 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -14,7 +14,7 @@ environment:
secure: OtVfyN3ErqQrDTnWH2HDfJDlCiu/i4/X4wFmK3ZXXP7HmCiXYPSbTjMPwwdOxRaK
MYGET_API_URL: https://www.myget.org/F/avalonia-ci/api/v2/package
init:
-- ps: (New-Object Net.WebClient).DownloadFile('https://raw.githubusercontent.com/appveyor/ci/master/scripts/xamarin-vs2017-151-fixed.targets', "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Microsoft.Common.Targets\ImportAfter\Xamarin.Common.targets")
+- ps: if (Test-Path env:nuget_address) {[System.IO.File]::AppendAllText("C:\Windows\System32\drivers\etc\hosts", "`n$($env:nuget_address)`tapi.nuget.org")}
install:
- if not exist gtk-sharp-2.12.26.msi appveyor DownloadFile http://download.xamarin.com/GTKforWindows/Windows/gtk-sharp-2.12.26.msi
- if not exist dotnet-1.0.1.exe appveyor DownloadFile https://go.microsoft.com/fwlink/?linkid=843448 -FileName "dotnet-1.0.1.exe"
@@ -26,7 +26,6 @@ before_build:
build_script:
- ps: .\build.ps1 -Target "AppVeyor" -Platform "$env:platform" -Configuration "$env:configuration"
after_build:
-- tools\JetBrains.dotMemoryUnit\tools\dotMemoryUnit.exe -targetExecutable="%xunit20%\xunit.console.x86.exe" -returnTargetExitCode --"tests\Avalonia.LeakTests\bin\Release\Avalonia.LeakTests.dll"
- "SET PATH=C:\\Python34;C:\\Python34\\Scripts;%PATH%"
- pip install codecov
- codecov -f "./artifacts/coverage.xml"
diff --git a/build.cake b/build.cake
index b3822271d4..cab2ba9b0a 100644
--- a/build.cake
+++ b/build.cake
@@ -4,8 +4,8 @@
#addin "nuget:?package=Polly&version=4.2.0"
#addin "nuget:?package=NuGet.Core&version=2.12.0"
+#tool "nuget:?package=xunit.runner.console&version=2.2.0"
#tool "nuget:https://dotnet.myget.org/F/nuget-build/?package=NuGet.CommandLine&version=4.3.0-preview1-3980&prerelease"
-#tool "nuget:?package=JetBrains.dotMemoryUnit&version=2.3.20160517.113140"
#tool "JetBrains.ReSharper.CommandLineTools"
///////////////////////////////////////////////////////////////////////////////
// TOOLS
@@ -119,7 +119,6 @@ Task("Restore-NuGet-Packages")
}})
.Execute(()=> {
NuGetRestore(parameters.MSBuildSolution, new NuGetRestoreSettings {
- ToolPath = "./tools/NuGet.CommandLine/tools/NuGet.exe",
ToolTimeout = TimeSpan.FromMinutes(toolTimeout)
});
});
@@ -194,6 +193,7 @@ Task("Run-Net-Core-Unit-Tests")
Task("Run-Unit-Tests")
.IsDependentOn("Run-Net-Core-Unit-Tests")
.IsDependentOn("Build")
+ .IsDependentOn("Run-Leak-Tests")
.WithCriteria(() => !parameters.SkipTests)
.Does(() =>
{
@@ -206,13 +206,6 @@ Task("Run-Unit-Tests")
.Select(name => MakeAbsolute(File("./tests/" + name + "/bin/" + parameters.DirSuffix + "/" + name + ".dll")))
.ToList();
- if (parameters.IsRunningOnWindows)
- {
- var leakTests = GetFiles("./tests/Avalonia.LeakTests/bin/" + parameters.DirSuffix + "/*.LeakTests.dll");
-
- unitTests.AddRange(leakTests);
- }
-
var toolPath = (parameters.IsPlatformAnyCPU || parameters.IsPlatformX86) ?
"./tools/xunit.runner.console/tools/xunit.console.x86.exe" :
"./tools/xunit.runner.console/tools/xunit.console.exe";
@@ -365,6 +358,44 @@ Task("Publish-NuGet")
Information("Publish-NuGet Task failed, but continuing with next Task...");
});
+Task("Run-Leak-Tests")
+ .WithCriteria(parameters.IsRunningOnWindows)
+ .IsDependentOn("Build")
+ .Does(() =>
+ {
+ DotNetCoreRestore("tests\\Avalonia.LeakTests\\toolproject\\tool.csproj");
+ DotNetBuild("tests\\Avalonia.LeakTests\\toolproject\\tool.csproj", settings => settings.SetConfiguration("Release"));
+ var report = "tests\\Avalonia.LeakTests\\bin\\Release\\report.xml";
+ if(System.IO.File.Exists(report))
+ System.IO.File.Delete(report);
+ var proc = System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
+ {
+ FileName="tests\\Avalonia.LeakTests\\toolproject\\bin\\dotMemoryUnit.exe",
+ Arguments="-targetExecutable=\"tools\\xunit.runner.console\\tools\\xunit.console.x86.exe\" -returnTargetExitCode -- tests\\Avalonia.LeakTests\\bin\\Release\\Avalonia.LeakTests.dll -xml tests\\Avalonia.LeakTests\\bin\\Release\\report.xml ",
+ UseShellExecute = false,
+ });
+ var st = System.Diagnostics.Stopwatch.StartNew();
+ while(!proc.HasExited && !System.IO.File.Exists(report))
+ {
+ if(st.Elapsed.TotalSeconds>60)
+ {
+ Error("Timed out, probably a bug in dotMemoryUnit");
+ proc.Kill();
+ throw new Exception("dotMemory issue");
+ }
+ proc.WaitForExit(100);
+ }
+ try{
+ proc.Kill();
+ }catch{}
+ var doc = System.Xml.Linq.XDocument.Load(report);
+ if(doc.Root.Descendants("assembly").Any(x=>x.Attribute("failed").Value.ToString() != "0"))
+ {
+ throw new Exception("Tests failed");
+ }
+
+ });
+
Task("Inspect")
.WithCriteria(parameters.IsRunningOnWindows)
.IsDependentOn("Restore-NuGet-Packages")
diff --git a/build/SharpDX.props b/build/SharpDX.props
index e381bc03e6..0eb910e71e 100644
--- a/build/SharpDX.props
+++ b/build/SharpDX.props
@@ -3,6 +3,7 @@
+
diff --git a/build/UnitTests.NetCore.targets b/build/UnitTests.NetCore.targets
index a8886fe028..13bb4ed230 100644
--- a/build/UnitTests.NetCore.targets
+++ b/build/UnitTests.NetCore.targets
@@ -25,5 +25,4 @@
-
\ No newline at end of file
diff --git a/packages.cake b/packages.cake
index 1a29695d82..07c77f64fd 100644
--- a/packages.cake
+++ b/packages.cake
@@ -81,6 +81,7 @@ public class Packages
var SharpDXVersion = packageVersions["SharpDX"].FirstOrDefault().Item1;
var SharpDXDirect2D1Version = packageVersions["SharpDX.Direct2D1"].FirstOrDefault().Item1;
var SharpDXDirect3D11Version = packageVersions["SharpDX.Direct3D11"].FirstOrDefault().Item1;
+ var SharpDXDirect3D9Version = packageVersions["SharpDX.Direct3D9"].FirstOrDefault().Item1;
var SharpDXDXGIVersion = packageVersions["SharpDX.DXGI"].FirstOrDefault().Item1;
context.Information("Package: Serilog, version: {0}", SerilogVersion);
@@ -93,6 +94,7 @@ public class Packages
context.Information("Package: SharpDX, version: {0}", SharpDXVersion);
context.Information("Package: SharpDX.Direct2D1, version: {0}", SharpDXDirect2D1Version);
context.Information("Package: SharpDX.Direct3D11, version: {0}", SharpDXDirect3D11Version);
+ context.Information("Package: SharpDX.Direct3D9, version: {0}", SharpDXDirect3D9Version);
context.Information("Package: SharpDX.DXGI, version: {0}", SharpDXDXGIVersion);
var nugetPackagesDir = System.Environment.GetEnvironmentVariable("NUGET_HOME")
@@ -476,6 +478,7 @@ public class Packages
{
new NuSpecDependency() { Id = "Avalonia.Win32", Version = parameters.Version },
new NuSpecDependency() { Id = "Avalonia.Direct2D1", Version = parameters.Version },
+ new NuSpecDependency() { Id = "SharpDX.Direct3D9", Version = SharpDXDirect3D9Version },
},
Files = new []
{
diff --git a/samples/BindingTest/BindingTest.csproj b/samples/BindingTest/BindingTest.csproj
index f8964f9fb4..74259a2a4b 100644
--- a/samples/BindingTest/BindingTest.csproj
+++ b/samples/BindingTest/BindingTest.csproj
@@ -174,5 +174,4 @@
-
\ No newline at end of file
diff --git a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
index 4db67a8b60..71e3c4169c 100644
--- a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
+++ b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
@@ -158,5 +158,4 @@
-
\ No newline at end of file
diff --git a/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj b/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
index e215105149..59c8c53137 100644
--- a/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
+++ b/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
@@ -144,5 +144,4 @@
-
\ No newline at end of file
diff --git a/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj b/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj
index 01d287ea83..d0c73b2553 100644
--- a/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj
+++ b/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj
@@ -181,5 +181,4 @@
-
\ No newline at end of file
diff --git a/samples/RenderTest/RenderTest.csproj b/samples/RenderTest/RenderTest.csproj
index cf32316086..ed6194e0e1 100644
--- a/samples/RenderTest/RenderTest.csproj
+++ b/samples/RenderTest/RenderTest.csproj
@@ -183,5 +183,4 @@
-
\ No newline at end of file
diff --git a/samples/VirtualizationTest/VirtualizationTest.csproj b/samples/VirtualizationTest/VirtualizationTest.csproj
index 9b9d8a94c6..89115016bf 100644
--- a/samples/VirtualizationTest/VirtualizationTest.csproj
+++ b/samples/VirtualizationTest/VirtualizationTest.csproj
@@ -158,5 +158,4 @@
-
\ No newline at end of file
diff --git a/samples/interop/Direct3DInteropSample/Direct3DInteropSample.csproj b/samples/interop/Direct3DInteropSample/Direct3DInteropSample.csproj
index d90a251173..55384d787c 100644
--- a/samples/interop/Direct3DInteropSample/Direct3DInteropSample.csproj
+++ b/samples/interop/Direct3DInteropSample/Direct3DInteropSample.csproj
@@ -31,5 +31,4 @@
-
\ No newline at end of file
diff --git a/samples/interop/GtkInteropDemo/GtkInteropDemo.csproj b/samples/interop/GtkInteropDemo/GtkInteropDemo.csproj
index d9a61064f1..8cbaf7a627 100644
--- a/samples/interop/GtkInteropDemo/GtkInteropDemo.csproj
+++ b/samples/interop/GtkInteropDemo/GtkInteropDemo.csproj
@@ -151,5 +151,4 @@
-
\ No newline at end of file
diff --git a/samples/interop/WindowsInteropTest/Program.cs b/samples/interop/WindowsInteropTest/Program.cs
index 4770688ecf..fac06d74b0 100644
--- a/samples/interop/WindowsInteropTest/Program.cs
+++ b/samples/interop/WindowsInteropTest/Program.cs
@@ -15,7 +15,7 @@ namespace WindowsInteropTest
{
System.Windows.Forms.Application.EnableVisualStyles();
System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false);
- AppBuilder.Configure().UseWin32().UseSkia().SetupWithoutStarting();
+ AppBuilder.Configure().UseWin32().UseDirect2D1().SetupWithoutStarting();
System.Windows.Forms.Application.Run(new SelectorForm());
}
}
diff --git a/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj b/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj
index 1aad43a0ea..84bd709f8c 100644
--- a/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj
+++ b/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj
@@ -186,5 +186,4 @@
-
\ No newline at end of file
diff --git a/src/Android/Avalonia.Android/Avalonia.Android.csproj b/src/Android/Avalonia.Android/Avalonia.Android.csproj
index 4babdc8bff..091fdcc4b5 100644
--- a/src/Android/Avalonia.Android/Avalonia.Android.csproj
+++ b/src/Android/Avalonia.Android/Avalonia.Android.csproj
@@ -133,8 +133,4 @@
-
-
- $(MSBuildToolsPath)\Roslyn
-
\ No newline at end of file
diff --git a/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj b/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
index 826f1f0132..87d1f67986 100644
--- a/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
+++ b/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
@@ -157,5 +157,4 @@
-
\ No newline at end of file
diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs
index d2e8085d8c..92ab12f82e 100644
--- a/src/Avalonia.Controls/TextBox.cs
+++ b/src/Avalonia.Controls/TextBox.cs
@@ -236,6 +236,11 @@ namespace Avalonia.Controls
{
_presenter = e.NameScope.Get("PART_TextPresenter");
_presenter.Cursor = new Cursor(StandardCursorType.Ibeam);
+
+ if(IsFocused)
+ {
+ _presenter.ShowCaret();
+ }
}
protected override void OnGotFocus(GotFocusEventArgs e)
@@ -254,7 +259,7 @@ namespace Avalonia.Controls
}
else
{
- _presenter.ShowCaret();
+ _presenter?.ShowCaret();
}
}
@@ -263,7 +268,7 @@ namespace Avalonia.Controls
base.OnLostFocus(e);
SelectionStart = 0;
SelectionEnd = 0;
- _presenter.HideCaret();
+ _presenter?.HideCaret();
}
protected override void OnTextInput(TextInputEventArgs e)
diff --git a/src/Avalonia.Controls/ToolTip.cs b/src/Avalonia.Controls/ToolTip.cs
index 22bc589a36..e1b69637af 100644
--- a/src/Avalonia.Controls/ToolTip.cs
+++ b/src/Avalonia.Controls/ToolTip.cs
@@ -106,24 +106,28 @@ namespace Avalonia.Controls
if (control != null && control.IsVisible && control.GetVisualRoot() != null)
{
var cp = (control.GetVisualRoot() as IInputRoot)?.MouseDevice?.GetPosition(control);
- var position = control.PointToScreen(cp ?? new Point(0, 0)) + new Vector(0, 22);
- if (s_popup == null)
+ if (cp.HasValue && control.IsVisible && new Rect(control.Bounds.Size).Contains(cp.Value))
{
- s_popup = new PopupRoot();
- s_popup.Content = new ToolTip();
- }
- else
- {
- ((ISetLogicalParent)s_popup).SetParent(null);
- }
+ var position = control.PointToScreen(cp.Value) + new Vector(0, 22);
+
+ if (s_popup == null)
+ {
+ s_popup = new PopupRoot();
+ s_popup.Content = new ToolTip();
+ }
+ else
+ {
+ ((ISetLogicalParent)s_popup).SetParent(null);
+ }
((ISetLogicalParent)s_popup).SetParent(control);
- ((ToolTip)s_popup.Content).Content = GetTip(control);
- s_popup.Position = position;
- s_popup.Show();
+ ((ToolTip)s_popup.Content).Content = GetTip(control);
+ s_popup.Position = position;
+ s_popup.Show();
- s_current = control;
+ s_current = control;
+ }
}
}
diff --git a/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj b/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj
index b475c4b3ff..932afbe0e6 100644
--- a/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj
+++ b/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj
@@ -69,5 +69,4 @@
-
\ No newline at end of file
diff --git a/src/Gtk/Avalonia.Cairo/Avalonia.Cairo.csproj b/src/Gtk/Avalonia.Cairo/Avalonia.Cairo.csproj
index cc6684f622..9a59f9e054 100644
--- a/src/Gtk/Avalonia.Cairo/Avalonia.Cairo.csproj
+++ b/src/Gtk/Avalonia.Cairo/Avalonia.Cairo.csproj
@@ -103,5 +103,4 @@
-
\ No newline at end of file
diff --git a/src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj b/src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj
index 837b83bdd7..8aa57293f3 100644
--- a/src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj
+++ b/src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj
@@ -98,5 +98,4 @@
-
\ No newline at end of file
diff --git a/src/Shared/Microsoft.NuGet.Build.Tasks.Patched.dll b/src/Shared/Microsoft.NuGet.Build.Tasks.Patched.dll
deleted file mode 100644
index 33ab0a4af7..0000000000
Binary files a/src/Shared/Microsoft.NuGet.Build.Tasks.Patched.dll and /dev/null differ
diff --git a/src/Shared/nuget.workaround.targets b/src/Shared/nuget.workaround.targets
deleted file mode 100644
index dee700ce08..0000000000
--- a/src/Shared/nuget.workaround.targets
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_ReferencesFromNuGetPackages Remove="%(ReferencePath.FileName)" Condition="'%(ReferencePath.ResolvedFrom)' == 'ImplicitlyExpandTargetFramework'" />
-
-
-
- <_ResolvedProjectReferencePaths Include="@(_ReferencesFromNuGetPackages)" Condition="'%(_ReferencesFromNuGetPackages.NuGetSourceType)' == 'Project'" />
-
-
-
-
-
-
-
-
- true
-
-
-
-
-
-
-
-
- $(MSBuildToolsPath)\..\Roslyn
-
-
\ No newline at end of file
diff --git a/src/Skia/Avalonia.Skia.Android/Avalonia.Skia.Android.csproj b/src/Skia/Avalonia.Skia.Android/Avalonia.Skia.Android.csproj
index aab791cd8f..4cd1f21022 100644
--- a/src/Skia/Avalonia.Skia.Android/Avalonia.Skia.Android.csproj
+++ b/src/Skia/Avalonia.Skia.Android/Avalonia.Skia.Android.csproj
@@ -86,5 +86,4 @@
-
\ No newline at end of file
diff --git a/src/Skia/Avalonia.Skia.Desktop/Avalonia.Skia.Desktop.csproj b/src/Skia/Avalonia.Skia.Desktop/Avalonia.Skia.Desktop.csproj
index e2a2ac6146..f0964680a1 100644
--- a/src/Skia/Avalonia.Skia.Desktop/Avalonia.Skia.Desktop.csproj
+++ b/src/Skia/Avalonia.Skia.Desktop/Avalonia.Skia.Desktop.csproj
@@ -109,5 +109,4 @@
-
diff --git a/src/Skia/Avalonia.Skia.iOS/Avalonia.Skia.iOS.csproj b/src/Skia/Avalonia.Skia.iOS/Avalonia.Skia.iOS.csproj
index 220fb37b81..9ea89704f7 100644
--- a/src/Skia/Avalonia.Skia.iOS/Avalonia.Skia.iOS.csproj
+++ b/src/Skia/Avalonia.Skia.iOS/Avalonia.Skia.iOS.csproj
@@ -88,5 +88,7 @@
-
+
+ $(MSBuildToolsPath)\..\Roslyn
+
\ No newline at end of file
diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
index 4a9f2c6572..3ed0509c0a 100644
--- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
+++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
@@ -141,23 +141,17 @@ namespace Avalonia.Skia
var rv = new PaintWrapper(paint);
paint.IsStroke = false;
- // TODO: SkiaSharp does not contain alpha yet!
+
double opacity = brush.Opacity * _currentOpacity;
- //paint.SetAlpha(paint.GetAlpha() * opacity);
paint.IsAntialias = true;
- SKColor color = new SKColor(255, 255, 255, 255);
-
var solid = brush as ISolidColorBrush;
- if (solid != null)
- color = solid.Color.ToSKColor();
-
- paint.Color = (new SKColor(color.Red, color.Green, color.Blue, (byte)(color.Alpha * opacity)));
-
if (solid != null)
{
+ paint.Color = new SKColor(solid.Color.R, solid.Color.G, solid.Color.B, (byte) (solid.Color.A * opacity));
return rv;
}
+ paint.Color = (new SKColor(255, 255, 255, (byte)(255 * opacity)));
var gradient = brush as IGradientBrush;
if (gradient != null)
diff --git a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs
index 8568c80c04..1d224f97d7 100644
--- a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs
+++ b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs
@@ -42,7 +42,6 @@ namespace Avalonia.Skia
_paint.Typeface = skiaTypeface;
_paint.TextSize = (float)(typeface?.FontSize ?? 12);
_paint.TextAlign = textAlignment.ToSKTextAlign();
- _paint.BlendMode = SKBlendMode.Src;
_wrapping = wrapping;
_constraint = constraint;
@@ -200,66 +199,65 @@ namespace Avalonia.Skia
}
ctx->Canvas->restore();
*/
- SKPaint paint = _paint;
- IDisposable currd = null;
- var currentWrapper = foreground;
-
- try
+ using (var paint = _paint.Clone())
{
- SKPaint currFGPaint = ApplyWrapperTo(ref foreground, ref currd, paint);
- bool hasCusomFGBrushes = _foregroundBrushes.Any();
-
- for (int c = 0; c < _skiaLines.Count; c++)
+ IDisposable currd = null;
+ var currentWrapper = foreground;
+ SKPaint currentPaint = null;
+ try
{
- AvaloniaFormattedTextLine line = _skiaLines[c];
-
- float x = TransformX(origin.X, 0, paint.TextAlign);
+ ApplyWrapperTo(ref currentPaint, foreground, ref currd, paint);
+ bool hasCusomFGBrushes = _foregroundBrushes.Any();
- if (!hasCusomFGBrushes)
- {
- var subString = Text.Substring(line.Start, line.Length);
- canvas.DrawText(subString, x, origin.Y + line.Top + _lineOffset, paint);
- }
- else
+ for (int c = 0; c < _skiaLines.Count; c++)
{
- float currX = x;
- string subStr;
- int len;
+ AvaloniaFormattedTextLine line = _skiaLines[c];
- for (int i = line.Start; i < line.Start + line.Length;)
- {
- var fb = GetNextForegroundBrush(ref line, i, out len);
-
- if (fb != null)
- {
- //TODO: figure out how to get the brush size
- currentWrapper = context.CreatePaint(fb, new Size());
- }
- else
- {
- if (!currentWrapper.Equals(foreground)) currentWrapper.Dispose();
- currentWrapper = foreground;
- }
+ float x = TransformX(origin.X, 0, paint.TextAlign);
- subStr = Text.Substring(i, len);
+ if (!hasCusomFGBrushes)
+ {
+ var subString = Text.Substring(line.Start, line.Length);
+ canvas.DrawText(subString, x, origin.Y + line.Top + _lineOffset, paint);
+ }
+ else
+ {
+ float currX = x;
+ string subStr;
+ int len;
- if (currFGPaint != currentWrapper.Paint)
+ for (int i = line.Start; i < line.Start + line.Length;)
{
- currFGPaint = ApplyWrapperTo(ref currentWrapper, ref currd, paint);
+ var fb = GetNextForegroundBrush(ref line, i, out len);
+
+ if (fb != null)
+ {
+ //TODO: figure out how to get the brush size
+ currentWrapper = context.CreatePaint(fb, new Size());
+ }
+ else
+ {
+ if (!currentWrapper.Equals(foreground)) currentWrapper.Dispose();
+ currentWrapper = foreground;
+ }
+
+ subStr = Text.Substring(i, len);
+
+ ApplyWrapperTo(ref currentPaint, currentWrapper, ref currd, paint);
+
+ canvas.DrawText(subStr, currX, origin.Y + line.Top + _lineOffset, paint);
+
+ i += len;
+ currX += paint.MeasureText(subStr);
}
-
- canvas.DrawText(subStr, currX, origin.Y + line.Top + _lineOffset, paint);
-
- i += len;
- currX += paint.MeasureText(subStr);
}
}
}
- }
- finally
- {
- if (!currentWrapper.Equals(foreground)) currentWrapper.Dispose();
- currd?.Dispose();
+ finally
+ {
+ if (!currentWrapper.Equals(foreground)) currentWrapper.Dispose();
+ currd?.Dispose();
+ }
}
}
@@ -278,12 +276,13 @@ namespace Avalonia.Skia
private Size _size;
private List _skiaLines;
- private static SKPaint ApplyWrapperTo(ref DrawingContextImpl.PaintWrapper wrapper,
+ private static void ApplyWrapperTo(ref SKPaint current, DrawingContextImpl.PaintWrapper wrapper,
ref IDisposable curr, SKPaint paint)
{
+ if (current == wrapper.Paint)
+ return;
curr?.Dispose();
curr = wrapper.ApplyTo(paint);
- return wrapper.Paint;
}
private static bool IsBreakChar(char c)
diff --git a/src/Windows/Avalonia.Designer/Avalonia.Designer.csproj b/src/Windows/Avalonia.Designer/Avalonia.Designer.csproj
index 71fb024d89..4fdd06c9ce 100644
--- a/src/Windows/Avalonia.Designer/Avalonia.Designer.csproj
+++ b/src/Windows/Avalonia.Designer/Avalonia.Designer.csproj
@@ -123,5 +123,4 @@
-
\ No newline at end of file
diff --git a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj
index cf5a055df8..38fd7254dc 100644
--- a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj
+++ b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj
@@ -117,5 +117,4 @@
-
\ No newline at end of file
diff --git a/src/Windows/Avalonia.Direct2D1/ExternalRenderTarget.cs b/src/Windows/Avalonia.Direct2D1/ExternalRenderTarget.cs
index b1c0e7e30a..307048f7b4 100644
--- a/src/Windows/Avalonia.Direct2D1/ExternalRenderTarget.cs
+++ b/src/Windows/Avalonia.Direct2D1/ExternalRenderTarget.cs
@@ -15,7 +15,6 @@ namespace Avalonia.Direct2D1
{
private readonly IExternalDirect2DRenderTargetSurface _externalRenderTargetProvider;
private readonly DirectWriteFactory _dwFactory;
- private SharpDX.Direct2D1.RenderTarget _target;
public ExternalRenderTarget(IExternalDirect2DRenderTargetSurface externalRenderTargetProvider,
DirectWriteFactory dwFactory)
{
@@ -25,15 +24,14 @@ namespace Avalonia.Direct2D1
public void Dispose()
{
- _target?.Dispose();
- _target = null;
+ _externalRenderTargetProvider.DestroyRenderTarget();
}
public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer)
{
- _target = _target ?? _externalRenderTargetProvider.CreateRenderTarget();
+ var target = _externalRenderTargetProvider.GetOrCreateRenderTarget();
_externalRenderTargetProvider.BeforeDrawing();
- return new DrawingContextImpl(visualBrushRenderer, _target, _dwFactory, null, () =>
+ return new DrawingContextImpl(visualBrushRenderer, target, _dwFactory, null, () =>
{
try
{
@@ -41,8 +39,7 @@ namespace Avalonia.Direct2D1
}
catch (SharpDXException ex) when ((uint) ex.HResult == 0x8899000C) // D2DERR_RECREATE_TARGET
{
- _target?.Dispose();
- _target = null;
+ _externalRenderTargetProvider.DestroyRenderTarget();
}
});
}
diff --git a/src/Windows/Avalonia.Direct2D1/IExternalDirect2DRenderTargetSurface.cs b/src/Windows/Avalonia.Direct2D1/IExternalDirect2DRenderTargetSurface.cs
index 0774c25937..aad51f46d5 100644
--- a/src/Windows/Avalonia.Direct2D1/IExternalDirect2DRenderTargetSurface.cs
+++ b/src/Windows/Avalonia.Direct2D1/IExternalDirect2DRenderTargetSurface.cs
@@ -8,7 +8,8 @@ namespace Avalonia.Direct2D1
{
public interface IExternalDirect2DRenderTargetSurface
{
- SharpDX.Direct2D1.RenderTarget CreateRenderTarget();
+ SharpDX.Direct2D1.RenderTarget GetOrCreateRenderTarget();
+ void DestroyRenderTarget();
void BeforeDrawing();
void AfterDrawing();
}
diff --git a/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj b/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj
index c5cd2ab64d..5f1a065028 100644
--- a/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj
+++ b/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj
@@ -49,6 +49,8 @@
+
+
@@ -104,10 +106,18 @@
{6417e941-21bc-467b-a771-0de389353ce6}
Avalonia.Markup
+
+ {3e908f67-5543-4879-a1dc-08eace79b3cd}
+ Avalonia.Direct2D1
+
{811a76cf-1cf6-440f-963b-bbe31bd72a82}
Avalonia.Win32
+
+ true
+
+
\ No newline at end of file
diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs
new file mode 100644
index 0000000000..8fe7275a0f
--- /dev/null
+++ b/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs
@@ -0,0 +1,208 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Interop;
+using Avalonia.Direct2D1;
+using SharpDX;
+using SharpDX.Direct2D1;
+using SharpDX.Direct3D11;
+using SharpDX.Direct3D9;
+using SharpDX.DXGI;
+using AlphaMode = SharpDX.Direct2D1.AlphaMode;
+using Device = SharpDX.Direct3D11.Device;
+using Format = SharpDX.DXGI.Format;
+using MapFlags = SharpDX.Direct3D11.MapFlags;
+using PresentParameters = SharpDX.DXGI.PresentParameters;
+using Query = SharpDX.Direct3D11.Query;
+using QueryType = SharpDX.Direct3D11.QueryType;
+using RenderTarget = SharpDX.Direct2D1.RenderTarget;
+using Surface = SharpDX.DXGI.Surface;
+using SwapEffect = SharpDX.DXGI.SwapEffect;
+using Usage = SharpDX.Direct3D9.Usage;
+
+namespace Avalonia.Win32.Interop.Wpf
+{
+ class Direct2DImageSurface : IExternalDirect2DRenderTargetSurface, IDisposable
+ {
+ class SwapBuffer: IDisposable
+ {
+ private readonly Query _event;
+ private readonly SharpDX.Direct3D11.Resource _resource;
+ private readonly SharpDX.Direct3D11.Resource _sharedResource;
+ public SharpDX.Direct3D9.Surface Texture { get; }
+ public RenderTarget Target { get;}
+ public IntSize Size { get; }
+
+ public SwapBuffer(IntSize size, Vector dpi)
+ {
+ int width = (int) size.Width;
+ int height = (int) size.Height;
+ _event = new Query(s_dxDevice, new QueryDescription {Type = QueryType.Event});
+ using (var texture = new Texture2D(s_dxDevice, new Texture2DDescription
+ {
+ Width = width,
+ Height = height,
+ ArraySize = 1,
+ MipLevels = 1,
+ Format = Format.B8G8R8A8_UNorm,
+ Usage = ResourceUsage.Default,
+ SampleDescription = new SampleDescription(2, 0),
+ BindFlags = BindFlags.RenderTarget,
+ }))
+ using (var surface = texture.QueryInterface())
+
+ {
+ _resource = texture.QueryInterface();
+
+ Target = new RenderTarget(AvaloniaLocator.Current.GetService(), surface,
+ new RenderTargetProperties
+ {
+ DpiX = (float) dpi.X,
+ DpiY = (float) dpi.Y,
+ MinLevel = FeatureLevel.Level_10,
+ PixelFormat = new PixelFormat(Format.B8G8R8A8_UNorm, AlphaMode.Premultiplied),
+
+ });
+ }
+ using (var texture = new Texture2D(s_dxDevice, new Texture2DDescription
+ {
+ Width = width,
+ Height = height,
+ ArraySize = 1,
+ MipLevels = 1,
+ Format = Format.B8G8R8A8_UNorm,
+ Usage = ResourceUsage.Default,
+ SampleDescription = new SampleDescription(1, 0),
+ BindFlags = BindFlags.RenderTarget|BindFlags.ShaderResource,
+ OptionFlags = ResourceOptionFlags.Shared,
+ }))
+ using (var resource = texture.QueryInterface())
+ {
+ _sharedResource = texture.QueryInterface();
+ var handle = resource.SharedHandle;
+ using (var texture9 = new Texture(s_d3DDevice, texture.Description.Width,
+ texture.Description.Height, 1,
+ Usage.RenderTarget, SharpDX.Direct3D9.Format.A8R8G8B8, Pool.Default, ref handle))
+ Texture = texture9.GetSurfaceLevel(0);
+ }
+ Size = size;
+ }
+
+ public void Dispose()
+ {
+ Texture?.Dispose();
+ Target?.Dispose();
+ _resource?.Dispose();
+ _sharedResource?.Dispose();
+ _event?.Dispose();
+ }
+
+ public void Flush()
+ {
+ s_dxDevice.ImmediateContext.ResolveSubresource(_resource, 0, _sharedResource, 0, Format.B8G8R8A8_UNorm);
+ s_dxDevice.ImmediateContext.Flush();
+ s_dxDevice.ImmediateContext.End(_event);
+ s_dxDevice.ImmediateContext.GetData(_event).Dispose();
+ }
+ }
+
+ private D3DImage _image;
+ private SwapBuffer _backBuffer;
+ private readonly WpfTopLevelImpl _impl;
+ private static Device s_dxDevice;
+ private static Direct3DEx s_d3DContext;
+ private static DeviceEx s_d3DDevice;
+ private Vector _oldDpi;
+
+
+ [DllImport("user32.dll", SetLastError = false)]
+ private static extern IntPtr GetDesktopWindow();
+ void EnsureDirectX()
+ {
+ if(s_d3DDevice != null)
+ return;
+ s_d3DContext = new Direct3DEx();
+
+ SharpDX.Direct3D9.PresentParameters presentparams = new SharpDX.Direct3D9.PresentParameters
+ {
+ Windowed = true,
+ SwapEffect = SharpDX.Direct3D9.SwapEffect.Discard,
+ DeviceWindowHandle = GetDesktopWindow(),
+ PresentationInterval = PresentInterval.Default
+ };
+ s_dxDevice = s_dxDevice ?? AvaloniaLocator.Current.GetService()
+ .QueryInterface();
+ s_d3DDevice = new DeviceEx(s_d3DContext, 0, DeviceType.Hardware, IntPtr.Zero, CreateFlags.HardwareVertexProcessing | CreateFlags.Multithreaded | CreateFlags.FpuPreserve, presentparams);
+
+ }
+
+ public Direct2DImageSurface(WpfTopLevelImpl impl)
+ {
+ _impl = impl;
+ }
+
+ public RenderTarget GetOrCreateRenderTarget()
+ {
+ EnsureDirectX();
+ var scale = _impl.GetScaling();
+ var size = new IntSize(_impl.ActualWidth * scale.X, _impl.ActualHeight * scale.Y);
+ var dpi = scale * 96;
+
+ if (_backBuffer!=null && _backBuffer.Size == size)
+ return _backBuffer.Target;
+
+ if (_image == null || _oldDpi.X != dpi.X || _oldDpi.Y != dpi.Y)
+ {
+ _image = new D3DImage(dpi.X, dpi.Y);
+ }
+ _impl.ImageSource = _image;
+
+ RemoveAndDispose(ref _backBuffer);
+ if (size == default(IntSize))
+ {
+ _image.Lock();
+ _image.SetBackBuffer(D3DResourceType.IDirect3DSurface9, IntPtr.Zero);
+ _image.Unlock();
+ return null;
+ }
+ _backBuffer = new SwapBuffer(size, dpi);
+
+ return _backBuffer.Target;
+ }
+
+ void RemoveAndDispose(ref T d) where T : IDisposable
+ {
+ d?.Dispose();
+ d = default(T);
+ }
+
+ void Swap()
+ {
+ _backBuffer.Flush();
+ _image.Lock();
+ _image.SetBackBuffer(D3DResourceType.IDirect3DSurface9, _backBuffer?.Texture?.NativePointer ?? IntPtr.Zero, true);
+ _image.AddDirtyRect(new Int32Rect(0, 0, _image.PixelWidth, _image.PixelHeight));
+ _image.Unlock();
+ }
+
+ public void DestroyRenderTarget()
+ {
+ RemoveAndDispose(ref _backBuffer);
+ }
+
+ public void BeforeDrawing()
+ {
+
+ }
+
+ public void AfterDrawing() => Swap();
+ public void Dispose()
+ {
+ RemoveAndDispose(ref _backBuffer);
+ }
+ }
+}
diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/IntSize.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/IntSize.cs
new file mode 100644
index 0000000000..3fdbdedfd9
--- /dev/null
+++ b/src/Windows/Avalonia.Win32.Interop/Wpf/IntSize.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Win32.Interop.Wpf
+{
+ struct IntSize : IEquatable
+ {
+ public bool Equals(IntSize other)
+ {
+ return Width == other.Width && Height == other.Height;
+ }
+
+ public IntSize(int width, int height)
+ {
+ Width = width;
+ Height = height;
+ }
+
+ public IntSize(double width, double height) : this((int) width, (int) height)
+ {
+
+ }
+
+ public static implicit operator IntSize(System.Windows.Size size)
+ {
+ return new IntSize {Width = (int) size.Width, Height = (int) size.Height};
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ return obj is IntSize && Equals((IntSize) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return (Width * 397) ^ Height;
+ }
+ }
+
+ public static bool operator ==(IntSize left, IntSize right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(IntSize left, IntSize right)
+ {
+ return !left.Equals(right);
+ }
+
+ public int Width { get; set; }
+ public int Height { get; set; }
+ }
+}
diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfAvaloniaHost.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfAvaloniaHost.cs
index e36b53199a..6dc9ba9e09 100644
--- a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfAvaloniaHost.cs
+++ b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfAvaloniaHost.cs
@@ -21,15 +21,32 @@ namespace Avalonia.Win32.Interop.Wpf
{
private WpfTopLevelImpl _impl;
private readonly SynchronizationContext _sync;
+ private bool _hasChildren;
public WpfAvaloniaHost()
{
_sync = SynchronizationContext.Current;
_impl = new WpfTopLevelImpl();
_impl.ControlRoot.Prepare();
_impl.Visibility = Visibility.Visible;
- AddLogicalChild(_impl);
- AddVisualChild(_impl);
SnapsToDevicePixels = true;
+ UseLayoutRounding = true;
+ PresentationSource.AddSourceChangedHandler(this, OnSourceChanged);
+ }
+
+ private void OnSourceChanged(object sender, SourceChangedEventArgs e)
+ {
+ if (e.NewSource != null && !_hasChildren)
+ {
+ AddLogicalChild(_impl);
+ AddVisualChild(_impl);
+ _hasChildren = true;
+ }
+ else
+ {
+ RemoveVisualChild(_impl);
+ RemoveLogicalChild(_impl);
+ _hasChildren = false;
+ }
}
public object Content
diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs
index 0620c6cc57..fbed2f621c 100644
--- a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs
+++ b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs
@@ -60,7 +60,7 @@ namespace Avalonia.Win32.Interop.Wpf
PresentationSource.AddSourceChangedHandler(this, OnSourceChanged);
_hook = WndProc;
_ttl = this;
- _surfaces = new object[] {new WritableBitmapSurface(this)};
+ _surfaces = new object[] {new WritableBitmapSurface(this), new Direct2DImageSurface(this)};
_mouse = new WpfMouseDevice(this);
_keyboard = AvaloniaLocator.Current.GetService();
@@ -88,7 +88,12 @@ namespace Avalonia.Win32.Interop.Wpf
_ttl.ScalingChanged?.Invoke(_ttl.Scaling);
}
- public void Dispose() => _ttl.Closed?.Invoke();
+ public void Dispose()
+ {
+ _ttl.Closed?.Invoke();
+ foreach(var d in _surfaces.OfType())
+ d.Dispose();
+ }
Size ITopLevelImpl.ClientSize => _finalSize;
IMouseDevice ITopLevelImpl.MouseDevice => _mouse;
@@ -224,6 +229,13 @@ namespace Avalonia.Win32.Interop.Wpf
Action ITopLevelImpl.ScalingChanged { get; set; }
Action ITopLevelImpl.Closed { get; set; }
public new event Action LostFocus;
-
+
+ internal Vector GetScaling()
+ {
+ var src = PresentationSource.FromVisual(this)?.CompositionTarget;
+ if (src == null)
+ return new Vector(1, 1);
+ return new Vector(src.TransformToDevice.M11, src.TransformToDevice.M22);
+ }
}
}
diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WritableBitmapSurface.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WritableBitmapSurface.cs
index 1dd1cb983a..0f8752fb8d 100644
--- a/src/Windows/Avalonia.Win32.Interop/Wpf/WritableBitmapSurface.cs
+++ b/src/Windows/Avalonia.Win32.Interop/Wpf/WritableBitmapSurface.cs
@@ -24,7 +24,7 @@ namespace Avalonia.Win32.Interop.Wpf
public ILockedFramebuffer Lock()
{
- var scale = GetScaling();
+ var scale = _impl.GetScaling();
var size = new Size(_impl.ActualWidth * scale.X, _impl.ActualHeight * scale.Y);
var dpi = scale * 96;
if (_bitmap == null || _bitmap.PixelWidth != (int) size.Width || _bitmap.PixelHeight != (int) size.Height)
@@ -69,13 +69,5 @@ namespace Avalonia.Win32.Interop.Wpf
public Vector Dpi { get; }
public PixelFormat Format => PixelFormat.Bgra8888;
}
-
- Vector GetScaling()
- {
- var src = PresentationSource.FromVisual(_impl)?.CompositionTarget;
- if (src == null)
- return new Vector(1, 1);
- return new Vector(src.TransformToDevice.M11, src.TransformToDevice.M22);
- }
}
}
diff --git a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
index 198bb7ce0d..ea742f8911 100644
--- a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
+++ b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
@@ -101,5 +101,4 @@
-
\ No newline at end of file
diff --git a/src/iOS/Avalonia.iOS/Avalonia.iOS.csproj b/src/iOS/Avalonia.iOS/Avalonia.iOS.csproj
index d915b67cd0..a959c0cf72 100644
--- a/src/iOS/Avalonia.iOS/Avalonia.iOS.csproj
+++ b/src/iOS/Avalonia.iOS/Avalonia.iOS.csproj
@@ -105,5 +105,7 @@
-
+
+ $(MSBuildToolsPath)\..\Roslyn
+
\ No newline at end of file
diff --git a/src/iOS/Avalonia.iOSTestApplication/Avalonia.iOSTestApplication.csproj b/src/iOS/Avalonia.iOSTestApplication/Avalonia.iOSTestApplication.csproj
index 050d61376a..92fcf226de 100644
--- a/src/iOS/Avalonia.iOSTestApplication/Avalonia.iOSTestApplication.csproj
+++ b/src/iOS/Avalonia.iOSTestApplication/Avalonia.iOSTestApplication.csproj
@@ -187,5 +187,4 @@
-
\ No newline at end of file
diff --git a/tests/Avalonia.Benchmarks/Avalonia.Benchmarks.csproj b/tests/Avalonia.Benchmarks/Avalonia.Benchmarks.csproj
index 21d7b186b4..1d987e2238 100644
--- a/tests/Avalonia.Benchmarks/Avalonia.Benchmarks.csproj
+++ b/tests/Avalonia.Benchmarks/Avalonia.Benchmarks.csproj
@@ -103,5 +103,4 @@
-
\ No newline at end of file
diff --git a/tests/Avalonia.DesignerSupport.TestApp/Avalonia.DesignerSupport.TestApp.csproj b/tests/Avalonia.DesignerSupport.TestApp/Avalonia.DesignerSupport.TestApp.csproj
index 2bf962bfa5..7945915e8c 100644
--- a/tests/Avalonia.DesignerSupport.TestApp/Avalonia.DesignerSupport.TestApp.csproj
+++ b/tests/Avalonia.DesignerSupport.TestApp/Avalonia.DesignerSupport.TestApp.csproj
@@ -147,5 +147,4 @@
-
\ No newline at end of file
diff --git a/tests/Avalonia.DesignerSupport.Tests/Avalonia.DesignerSupport.Tests.csproj b/tests/Avalonia.DesignerSupport.Tests/Avalonia.DesignerSupport.Tests.csproj
index efca582573..477d44b99d 100644
--- a/tests/Avalonia.DesignerSupport.Tests/Avalonia.DesignerSupport.Tests.csproj
+++ b/tests/Avalonia.DesignerSupport.Tests/Avalonia.DesignerSupport.Tests.csproj
@@ -58,5 +58,4 @@
-
\ No newline at end of file
diff --git a/tests/Avalonia.Direct2D1.UnitTests/Avalonia.Direct2D1.UnitTests.csproj b/tests/Avalonia.Direct2D1.UnitTests/Avalonia.Direct2D1.UnitTests.csproj
index 035d5b6c3e..4b33d14243 100644
--- a/tests/Avalonia.Direct2D1.UnitTests/Avalonia.Direct2D1.UnitTests.csproj
+++ b/tests/Avalonia.Direct2D1.UnitTests/Avalonia.Direct2D1.UnitTests.csproj
@@ -92,5 +92,4 @@
-
\ No newline at end of file
diff --git a/tests/Avalonia.LeakTests/Avalonia.LeakTests.csproj b/tests/Avalonia.LeakTests/Avalonia.LeakTests.csproj
index 83893b9bcd..46bd4ee324 100644
--- a/tests/Avalonia.LeakTests/Avalonia.LeakTests.csproj
+++ b/tests/Avalonia.LeakTests/Avalonia.LeakTests.csproj
@@ -122,5 +122,4 @@
-
\ No newline at end of file
diff --git a/tests/Avalonia.LeakTests/toolproject/tool.csproj b/tests/Avalonia.LeakTests/toolproject/tool.csproj
new file mode 100644
index 0000000000..54dbe6f17e
--- /dev/null
+++ b/tests/Avalonia.LeakTests/toolproject/tool.csproj
@@ -0,0 +1,11 @@
+
+
+ $(MSBuildThisFileDirectory)\bin
+ $(OutputPath)
+ net461
+ Library
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Avalonia.RenderTests/Avalonia.Cairo.RenderTests.csproj b/tests/Avalonia.RenderTests/Avalonia.Cairo.RenderTests.csproj
index b6c573c3c9..98256529bc 100644
--- a/tests/Avalonia.RenderTests/Avalonia.Cairo.RenderTests.csproj
+++ b/tests/Avalonia.RenderTests/Avalonia.Cairo.RenderTests.csproj
@@ -102,5 +102,4 @@
-
\ No newline at end of file
diff --git a/tests/Avalonia.RenderTests/Avalonia.Direct2D1.RenderTests.csproj b/tests/Avalonia.RenderTests/Avalonia.Direct2D1.RenderTests.csproj
index 14fb35202e..370bc04395 100644
--- a/tests/Avalonia.RenderTests/Avalonia.Direct2D1.RenderTests.csproj
+++ b/tests/Avalonia.RenderTests/Avalonia.Direct2D1.RenderTests.csproj
@@ -101,5 +101,4 @@
-
\ No newline at end of file
diff --git a/tests/Avalonia.RenderTests/Avalonia.Skia.RenderTests.csproj b/tests/Avalonia.RenderTests/Avalonia.Skia.RenderTests.csproj
index 9b228a89ee..92111585a7 100644
--- a/tests/Avalonia.RenderTests/Avalonia.Skia.RenderTests.csproj
+++ b/tests/Avalonia.RenderTests/Avalonia.Skia.RenderTests.csproj
@@ -102,5 +102,4 @@
-
\ No newline at end of file
diff --git a/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj b/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj
index 938fca8b4a..40023134fd 100644
--- a/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj
+++ b/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj
@@ -52,5 +52,7 @@
-
+
+
+
\ No newline at end of file