SKXamlCanvas is now properly DPI aware

This commit is contained in:
Matthew Leibowitz 2016-09-16 00:51:27 +02:00
Родитель e360acc20b
Коммит 85d5e85ec8
1 изменённых файлов: 43 добавлений и 27 удалений

Просмотреть файл

@ -3,9 +3,9 @@ using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.InteropServices.WindowsRuntime; using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel; using Windows.ApplicationModel;
using Windows.Graphics.Display;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging; using Windows.UI.Xaml.Media.Imaging;
@ -18,6 +18,7 @@ namespace SkiaSharp.Views
private byte[] pixels; private byte[] pixels;
private GCHandle buff; private GCHandle buff;
private WriteableBitmap bitmap; private WriteableBitmap bitmap;
private double dpi;
public SKXamlCanvas() public SKXamlCanvas()
{ {
@ -30,14 +31,14 @@ namespace SkiaSharp.Views
return; return;
SizeChanged += OnSizeChanged; SizeChanged += OnSizeChanged;
Tapped += OnTapped;
Unloaded += OnUnloaded; Unloaded += OnUnloaded;
// get the scale from the current display
var display = DisplayInformation.GetForCurrentView();
OnDpiChanged(display);
display.DpiChanged += OnDpiChanged;
} }
public int PixelWidth => (int)ActualWidth;
public int PixelHeight => (int)ActualHeight;
public event EventHandler<SKPaintSurfaceEventArgs> PaintSurface; public event EventHandler<SKPaintSurfaceEventArgs> PaintSurface;
protected virtual void OnPaintSurface(SKPaintSurfaceEventArgs e) protected virtual void OnPaintSurface(SKPaintSurfaceEventArgs e)
@ -45,18 +46,20 @@ namespace SkiaSharp.Views
PaintSurface?.Invoke(this, e); PaintSurface?.Invoke(this, e);
} }
protected virtual void OnSizeChanged(object sender, SizeChangedEventArgs e) private void OnDpiChanged(DisplayInformation sender, object args = null)
{
dpi = sender.LogicalDpi / 96.0f;
Invalidate();
}
private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{ {
Invalidate(); Invalidate();
} }
protected virtual void OnTapped(object sender, TappedRoutedEventArgs e)
{
}
private void OnUnloaded(object sender, RoutedEventArgs e) private void OnUnloaded(object sender, RoutedEventArgs e)
{ {
FreeBitmap(); FreeBitmap(true);
} }
public void Invalidate() public void Invalidate()
@ -64,9 +67,12 @@ namespace SkiaSharp.Views
if (designMode) if (designMode)
return; return;
CreateBitmap(); if (ActualWidth == 0 || ActualHeight == 0)
var info = new SKImageInfo(PixelWidth, PixelHeight, SKImageInfo.PlatformColorType, SKAlphaType.Premul); return;
using (var surface = SKSurface.Create(info, buff.AddrOfPinnedObject(), PixelWidth * 4))
var info = new SKImageInfo((int)(ActualWidth * dpi), (int)(ActualHeight * dpi), SKImageInfo.PlatformColorType, SKAlphaType.Premul);
CreateBitmap(info);
using (var surface = SKSurface.Create(info, buff.AddrOfPinnedObject(), info.RowBytes))
{ {
OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info)); OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info));
} }
@ -78,38 +84,48 @@ namespace SkiaSharp.Views
bitmap.Invalidate(); bitmap.Invalidate();
} }
private void CreateBitmap() private void CreateBitmap(SKImageInfo info)
{ {
if (bitmap == null || bitmap.PixelWidth != PixelWidth || bitmap.PixelHeight != PixelHeight) if (bitmap == null || bitmap.PixelWidth != info.Width || bitmap.PixelHeight != info.Height)
{ {
FreeBitmap(); var recreateArray = pixels == null || pixels.Length != info.BytesSize;
bitmap = new WriteableBitmap(PixelWidth, PixelHeight); FreeBitmap(recreateArray);
pixels = new byte[bitmap.PixelWidth * bitmap.PixelHeight * 4];
buff = GCHandle.Alloc(pixels, GCHandleType.Pinned);
if (recreateArray)
{
pixels = new byte[info.BytesSize];
buff = GCHandle.Alloc(pixels, GCHandleType.Pinned);
}
bitmap = new WriteableBitmap(info.Width, info.Height);
var scale = 1.0 / dpi;
Background = new ImageBrush Background = new ImageBrush
{ {
ImageSource = bitmap, ImageSource = bitmap,
AlignmentX = AlignmentX.Left, AlignmentX = AlignmentX.Left,
AlignmentY = AlignmentY.Top, AlignmentY = AlignmentY.Top,
Stretch = Stretch.None Stretch = Stretch.None,
Transform = new ScaleTransform { ScaleX = scale, ScaleY = scale }
}; };
} }
} }
private void FreeBitmap() private void FreeBitmap(bool freeArray)
{ {
if (bitmap != null) if (bitmap != null)
{ {
bitmap = null; bitmap = null;
} }
if (buff.IsAllocated) if (freeArray)
{ {
buff.Free(); if (buff.IsAllocated)
buff = default(GCHandle); {
buff.Free();
buff = default(GCHandle);
}
pixels = null;
} }
pixels = null;
} }
} }
} }