diff --git a/appveyor.yml b/appveyor.yml index eaa384fac3..2909da65b7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -23,5 +23,6 @@ after_build: test: off artifacts: - path: artifacts\nuget\*.nupkg + - path: artifacts\zip\*.zip cache: - gtk-sharp-2.12.26.msi diff --git a/build.cake b/build.cake index 9b8604f79f..d128fbcc5e 100644 --- a/build.cake +++ b/build.cake @@ -30,6 +30,7 @@ var target = Argument("target", "Default"); var platform = Argument("platform", "Any CPU"); var configuration = Argument("configuration", "Release"); var skipTests = HasArgument("skip-tests"); + /////////////////////////////////////////////////////////////////////////////// // CONFIGURATION /////////////////////////////////////////////////////////////////////////////// @@ -89,6 +90,8 @@ if (isRunningOnAppVeyor) var artifactsDir = (DirectoryPath)Directory("./artifacts"); var nugetRoot = artifactsDir.Combine("nuget"); +var zipRoot = artifactsDir.Combine("zip"); +var binRoot = artifactsDir.Combine("bin"); var dirSuffix = configuration; var dirSuffixSkia = (isPlatformAnyCPU ? "x86" : platform) + "/" + configuration; @@ -122,6 +125,11 @@ var buildDirs = GetDirectories("./Samples/**/bin/" + dirSuffix) + GetDirectories("./Samples/**/obj/" + dirSuffix); +var fileZipSuffix = version + ".zip"; +var zipCoreArtifacts = zipRoot.CombineWithFilePath("Avalonia-" + fileZipSuffix); +var zipSourceControlCatalogDesktopDirs = (DirectoryPath)Directory("./samples/ControlCatalog.Desktop/bin/" + dirSuffix); +var zipTargetControlCatalogDesktopDirs = zipRoot.CombineWithFilePath("ControlCatalog.Desktop-" + fileZipSuffix); + /////////////////////////////////////////////////////////////////////////////// // NUGET NUSPECS /////////////////////////////////////////////////////////////////////////////// @@ -527,6 +535,12 @@ var nugetPackages = nuspecNuGetSettings.Select(nuspec => { return nuspec.OutputDirectory.CombineWithFilePath(string.Concat(nuspec.Id, ".", nuspec.Version, ".nupkg")); }).ToArray(); +var binFiles = nuspecNuGetSettings.SelectMany(nuspec => { + return nuspec.Files.Select(file => { + return ((DirectoryPath)nuspec.BasePath).CombineWithFilePath(file.Source); + }); +}).GroupBy(f => f.FullPath).Select(g => g.First()); + /////////////////////////////////////////////////////////////////////////////// // INFORMATION /////////////////////////////////////////////////////////////////////////////// @@ -569,6 +583,8 @@ Task("Clean") CleanDirectories(buildDirs); CleanDirectory(artifactsDir); CleanDirectory(nugetRoot); + CleanDirectory(zipRoot); + CleanDirectory(binRoot); }); Task("Restore-NuGet-Packages") @@ -669,6 +685,25 @@ Task("Run-Unit-Tests") } }); +Task("Copy-Files") + .IsDependentOn("Run-Unit-Tests") + .Does(() => +{ + CopyFiles(binFiles, binRoot); +}); + +Task("Zip-Files") + .IsDependentOn("Copy-Files") + .Does(() => +{ + Zip(binRoot, zipCoreArtifacts); + + Zip(zipSourceControlCatalogDesktopDirs, + zipTargetControlCatalogDesktopDirs, + GetFiles(zipSourceControlCatalogDesktopDirs.FullPath + "/*.dll") + + GetFiles(zipSourceControlCatalogDesktopDirs.FullPath + "/*.exe")); +}); + Task("Create-NuGet-Packages") .IsDependentOn("Run-Unit-Tests") .Does(() => @@ -758,6 +793,7 @@ Task("Default") .IsDependentOn("Package"); Task("AppVeyor") + .IsDependentOn("Zip-Files") .IsDependentOn("Publish-MyGet") .IsDependentOn("Publish-NuGet"); diff --git a/readme.md b/readme.md index 6ed2fd55e8..0da6980146 100644 --- a/readme.md +++ b/readme.md @@ -25,6 +25,13 @@ You can find the packages here: ([stable(ish)](https://www.nuget.org/packages/Av You can install the package like this: `Install-Package Avalonia -Pre` +## Bleeding Edge Builds + +Try out the latest build of Avalonia available for download here: +https://ci.appveyor.com/project/AvaloniaUI/Avalonia/branch/master/artifacts + +Try out the ControlCatalog to give it a quick demo. + ## Background Avalonia is a multi-platform windowing toolkit - somewhat like WPF - that is intended to be multi- diff --git a/src/Avalonia.Visuals/Media/DrawingContext.cs b/src/Avalonia.Visuals/Media/DrawingContext.cs index 9fd8761ca5..ddaa681bab 100644 --- a/src/Avalonia.Visuals/Media/DrawingContext.cs +++ b/src/Avalonia.Visuals/Media/DrawingContext.cs @@ -12,6 +12,9 @@ namespace Avalonia.Media { private readonly IDrawingContextImpl _impl; private int _currentLevel; + //Internal tranformation that is applied but not exposed anywhere + //To be used for DPI scaling, etc + private Matrix? _hiddenPostTransform = Matrix.Identity; @@ -36,9 +39,10 @@ namespace Avalonia.Media } } - public DrawingContext(IDrawingContextImpl impl) + public DrawingContext(IDrawingContextImpl impl, Matrix? hiddenPostTransform = null) { _impl = impl; + _hiddenPostTransform = hiddenPostTransform; } @@ -55,11 +59,17 @@ namespace Avalonia.Media private set { _currentTransform = value; - _impl.Transform = _currentTransform*_currentContainerTransform; + var transform = _currentTransform*_currentContainerTransform; + if (_hiddenPostTransform.HasValue) + transform = transform*_hiddenPostTransform.Value; + _impl.Transform = transform; } } - internal Matrix CurrentContainerTransform => _currentContainerTransform; + //HACK: This is a temporary hack that is used in the render loop + //to update TransformedBounds property + [Obsolete("HACK for render loop, don't use")] + internal Matrix CurrentContainerTransform => _currentContainerTransform; /// /// Draws a bitmap image. diff --git a/src/Avalonia.Visuals/Rendering/RendererMixin.cs b/src/Avalonia.Visuals/Rendering/RendererMixin.cs index 6852192bb4..3d13501edd 100644 --- a/src/Avalonia.Visuals/Rendering/RendererMixin.cs +++ b/src/Avalonia.Visuals/Rendering/RendererMixin.cs @@ -124,8 +124,12 @@ namespace Avalonia.Rendering using (context.PushTransformContainer()) { visual.Render(context); + +#pragma warning disable 0618 var transformed = new TransformedBounds(bounds, new Rect(), context.CurrentContainerTransform); +#pragma warning restore 0618 + if (visual is Visual) { BoundsTracker.SetTransformedBounds((Visual)visual, transformed); diff --git a/src/Gtk/Avalonia.Gtk/GtkPlatform.cs b/src/Gtk/Avalonia.Gtk/GtkPlatform.cs index aaeba75b50..38bada2f25 100644 --- a/src/Gtk/Avalonia.Gtk/GtkPlatform.cs +++ b/src/Gtk/Avalonia.Gtk/GtkPlatform.cs @@ -28,7 +28,7 @@ namespace Avalonia.Gtk using Rendering; using Gtk = global::Gtk; - public class GtkPlatform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform, IPlatformIconLoader + public class GtkPlatform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform, IPlatformIconLoader, IRendererFactory { private static readonly GtkPlatform s_instance = new GtkPlatform(); private static Thread _uiThread; @@ -54,6 +54,7 @@ namespace Avalonia.Gtk .Bind().ToConstant(GtkMouseDevice.Instance) .Bind().ToConstant(s_instance) .Bind().ToConstant(s_instance) + .Bind().ToConstant(s_instance) .Bind().ToConstant(new DefaultRenderLoop(60)) .Bind().ToSingleton() .Bind().ToConstant(s_instance); @@ -112,6 +113,11 @@ namespace Avalonia.Gtk return new PopupImpl(); } + public IRenderer CreateRenderer(IRenderRoot root, IRenderLoop renderLoop) + { + return new Renderer(root, renderLoop); + } + public IWindowIconImpl LoadIcon(string fileName) { return new IconImpl(new Gdk.Pixbuf(fileName)); diff --git a/src/Skia/Avalonia.Skia.Desktop/RenderTarget.cs b/src/Skia/Avalonia.Skia.Desktop/RenderTarget.cs index 5b61042655..ef5fb88142 100644 --- a/src/Skia/Avalonia.Skia.Desktop/RenderTarget.cs +++ b/src/Skia/Avalonia.Skia.Desktop/RenderTarget.cs @@ -79,6 +79,29 @@ namespace Avalonia.Skia #endif } + private Size GetWindowDpiWin32() + { + if (UnmanagedMethods.ShCoreAvailable) + { + uint dpix, dpiy; + + var monitor = UnmanagedMethods.MonitorFromWindow( + _hwnd.Handle, + UnmanagedMethods.MONITOR.MONITOR_DEFAULTTONEAREST); + + if (UnmanagedMethods.GetDpiForMonitor( + monitor, + UnmanagedMethods.MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI, + out dpix, + out dpiy) == 0) + { + return new Size(dpix, dpiy); + } + } + + return new Size(96, 96); + } + public override DrawingContext CreateDrawingContext() { FixSize(); @@ -89,9 +112,26 @@ namespace Avalonia.Skia canvas.Clear(SKColors.Red); canvas.ResetMatrix(); - return + double scale = 1.0; + + var runtimeService = AvaloniaLocator.Current.GetService(); + + if (runtimeService != null) + { + switch (runtimeService.GetRuntimeInfo().OperatingSystem) + { + case OperatingSystemType.WinNT: + var dpi = GetWindowDpiWin32(); + scale = dpi.Width / 96.0; + break; + } + } + + var result = new DrawingContext( - new WindowDrawingContextImpl(this)); + new WindowDrawingContextImpl(this), Matrix.CreateScale(scale, scale)); + + return result; } public void Present() diff --git a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs index f37fd7c1c6..f8558c7428 100644 --- a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs +++ b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs @@ -2,11 +2,12 @@ using System; using System.IO; using Avalonia.Media; using Avalonia.Platform; +using Avalonia.Rendering; using SkiaSharp; namespace Avalonia.Skia { - public class PlatformRenderInterface : IPlatformRenderInterface + public class PlatformRenderInterface : IPlatformRenderInterface, IRendererFactory { public IBitmapImpl CreateBitmap(int width, int height) { @@ -48,6 +49,11 @@ namespace Avalonia.Skia } } + public IRenderer CreateRenderer(IRenderRoot root, IRenderLoop renderLoop) + { + return new Renderer(root, renderLoop); + } + public IRenderTargetBitmapImpl CreateRenderTargetBitmap(int width, int height) { if (width < 1) diff --git a/src/Skia/Avalonia.Skia/SkiaPlatform.cs b/src/Skia/Avalonia.Skia/SkiaPlatform.cs index 001970fa36..0751d86bf3 100644 --- a/src/Skia/Avalonia.Skia/SkiaPlatform.cs +++ b/src/Skia/Avalonia.Skia/SkiaPlatform.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using Avalonia.Controls; using Avalonia.Platform; +using Avalonia.Rendering; namespace Avalonia { @@ -23,7 +24,12 @@ namespace Avalonia.Skia private static bool s_forceSoftwareRendering; public static void Initialize() - => AvaloniaLocator.CurrentMutable.Bind().ToConstant(new PlatformRenderInterface()); + { + var renderInterface = new PlatformRenderInterface(); + AvaloniaLocator.CurrentMutable + .Bind().ToConstant(renderInterface) + .Bind().ToConstant(renderInterface); + } public static bool ForceSoftwareRendering { diff --git a/src/Skia/Avalonia.Skia/StreamGeometryImpl.cs b/src/Skia/Avalonia.Skia/StreamGeometryImpl.cs index ddc66e1854..33d4ce10c7 100644 --- a/src/Skia/Avalonia.Skia/StreamGeometryImpl.cs +++ b/src/Skia/Avalonia.Skia/StreamGeometryImpl.cs @@ -72,6 +72,8 @@ namespace Avalonia.Skia public IStreamGeometryContextImpl Open() { _path = new SKPath(); + _path.FillType = SKPathFillType.EvenOdd; + return new StreamContext(this); } diff --git a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj index 6b7e19d3f7..9f9558ff76 100644 --- a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj +++ b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj @@ -37,16 +37,16 @@ true - - ..\..\..\packages\SharpDX.3.0.2\lib\net45\SharpDX.dll + + ..\..\..\packages\SharpDX.3.1.0\lib\net45\SharpDX.dll True - - ..\..\..\packages\SharpDX.Direct2D1.3.0.2\lib\net45\SharpDX.Direct2D1.dll + + ..\..\..\packages\SharpDX.Direct2D1.3.1.0\lib\net45\SharpDX.Direct2D1.dll True - - ..\..\..\packages\SharpDX.DXGI.3.0.2\lib\net45\SharpDX.DXGI.dll + + ..\..\..\packages\SharpDX.DXGI.3.1.0\lib\net45\SharpDX.DXGI.dll True diff --git a/src/Windows/Avalonia.Direct2D1/packages.config b/src/Windows/Avalonia.Direct2D1/packages.config index cd93ea7704..57031c2b9d 100644 --- a/src/Windows/Avalonia.Direct2D1/packages.config +++ b/src/Windows/Avalonia.Direct2D1/packages.config @@ -1,6 +1,6 @@  - - - + + + \ No newline at end of file