From b83991fdb6a10c021c6badc5d06cc19357e28c79 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sun, 16 Oct 2016 17:36:37 +0100 Subject: [PATCH] Implemented Skia DPI scaling. Has a workaround for bug in DrawingContext. --- .../Avalonia.Skia.Desktop/RenderTarget.cs | 34 ++++++++++++++++++- src/Skia/Avalonia.Skia/DrawingContextImpl.cs | 20 +++++++---- .../Avalonia.Skia/WindowDrawingContextImpl.cs | 4 +-- 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/src/Skia/Avalonia.Skia.Desktop/RenderTarget.cs b/src/Skia/Avalonia.Skia.Desktop/RenderTarget.cs index 5b61042655..a53f57a968 100644 --- a/src/Skia/Avalonia.Skia.Desktop/RenderTarget.cs +++ b/src/Skia/Avalonia.Skia.Desktop/RenderTarget.cs @@ -79,6 +79,31 @@ namespace Avalonia.Skia #endif } +#if WIN32 + private Size GetWindowDpi() + { + 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); + } +#endif + public override DrawingContext CreateDrawingContext() { FixSize(); @@ -89,9 +114,16 @@ namespace Avalonia.Skia canvas.Clear(SKColors.Red); canvas.ResetMatrix(); + double scale = 1.0; + +#if WIN32 + var dpi = GetWindowDpi(); + scale = dpi.Width / 96.0; +#endif + return new DrawingContext( - new WindowDrawingContextImpl(this)); + new WindowDrawingContextImpl(this, scale)); } public void Present() diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs index 7744e15104..0d8e2a6436 100644 --- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs +++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs @@ -11,13 +11,19 @@ namespace Avalonia.Skia internal class DrawingContextImpl : IDrawingContextImpl { private Stack maskStack = new Stack(); - + private Matrix _dpiScaleMatrix; + private Matrix _currentTransform = Matrix.Identity; + public SKCanvas Canvas { get; private set; } - public DrawingContextImpl(SKCanvas canvas) + public DrawingContextImpl(SKCanvas canvas, double scale = 1.0) { Canvas = canvas; Canvas.Clear(); + + _dpiScaleMatrix = Matrix.CreateScale(scale, scale); + + _currentTransform = Matrix.Identity * _dpiScaleMatrix; } public void DrawImage(IBitmap source, double opacity, Rect sourceRect, Rect destRect) @@ -342,9 +348,7 @@ namespace Avalonia.Skia } Canvas.Restore(); Canvas.Restore(); - } - - private Matrix _currentTransform = Matrix.Identity; + } public Matrix Transform { @@ -355,7 +359,11 @@ namespace Avalonia.Skia return; _currentTransform = value; - Canvas.SetMatrix(value.ToSKMatrix()); + + // TODO this line is a workaround for bug in DrawingContext.cs + _currentTransform *= _dpiScaleMatrix; + + Canvas.SetMatrix(_currentTransform.ToSKMatrix()); } } } diff --git a/src/Skia/Avalonia.Skia/WindowDrawingContextImpl.cs b/src/Skia/Avalonia.Skia/WindowDrawingContextImpl.cs index a4e29fc022..2ab5433063 100644 --- a/src/Skia/Avalonia.Skia/WindowDrawingContextImpl.cs +++ b/src/Skia/Avalonia.Skia/WindowDrawingContextImpl.cs @@ -6,8 +6,8 @@ namespace Avalonia.Skia { WindowRenderTarget _target; - public WindowDrawingContextImpl(WindowRenderTarget target) - : base(target.Surface.Canvas) + public WindowDrawingContextImpl(WindowRenderTarget target, double scale = 1.0) + : base(target.Surface.Canvas, scale) { _target = target; }