From e76b694ebdcc4b2ca79532cb30183ea8aa98fc79 Mon Sep 17 00:00:00 2001 From: Benedikt Schroeder Date: Wed, 5 Sep 2018 17:02:22 +0200 Subject: [PATCH] InterpolationMode.HighQuality support --- .../Media/DrawingContextImpl.cs | 103 ++++++++++-------- 1 file changed, 60 insertions(+), 43 deletions(-) diff --git a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs index 3aec6c6eb1..b842f26edb 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs @@ -22,6 +22,7 @@ namespace Avalonia.Direct2D1.Media private readonly IVisualBrushRenderer _visualBrushRenderer; private readonly ILayerFactory _layerFactory; private readonly SharpDX.Direct2D1.RenderTarget _renderTarget; + private readonly DeviceContext _deviceContext; private readonly SharpDX.DXGI.SwapChain1 _swapChain; private readonly Action _finishedCallback; @@ -48,7 +49,17 @@ namespace Avalonia.Direct2D1.Media _renderTarget = renderTarget; _swapChain = swapChain; _finishedCallback = finishedCallback; - _renderTarget.BeginDraw(); + + if (_renderTarget is DeviceContext deviceContext) + { + _deviceContext = deviceContext; + } + else + { + _deviceContext = _renderTarget.QueryInterface(); + } + + _deviceContext.BeginDraw(); } /// @@ -56,14 +67,14 @@ namespace Avalonia.Direct2D1.Media /// public Matrix Transform { - get { return _renderTarget.Transform.ToAvalonia(); } - set { _renderTarget.Transform = value.ToDirect2D(); } + get { return _deviceContext.Transform.ToAvalonia(); } + set { _deviceContext.Transform = value.ToDirect2D(); } } /// public void Clear(Color color) { - _renderTarget.Clear(color.ToDirect2D()); + _deviceContext.Clear(color.ToDirect2D()); } /// @@ -72,10 +83,13 @@ namespace Avalonia.Direct2D1.Media public void Dispose() { foreach (var layer in _layerPool) + { layer.Dispose(); + } + try { - _renderTarget.EndDraw(); + _deviceContext.EndDraw(); _swapChain?.Present(1, SharpDX.DXGI.PresentFlags.None); _finishedCallback?.Invoke(); @@ -96,29 +110,32 @@ namespace Avalonia.Direct2D1.Media /// The bitmap interpolation mode. public void DrawImage(IRef source, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode) { - using (var d2d = ((BitmapImpl)source.Item).GetDirect2DBitmap(_renderTarget)) + using (var d2d = ((BitmapImpl)source.Item).GetDirect2DBitmap(_deviceContext)) { var interpolationMode = GetInterpolationMode(bitmapInterpolationMode); - _renderTarget.DrawBitmap( + _deviceContext.DrawBitmap( d2d.Value, destRect.ToSharpDX(), (float)opacity, interpolationMode, - sourceRect.ToSharpDX()); + sourceRect.ToSharpDX(), + null); } } - private static SharpDX.Direct2D1.BitmapInterpolationMode GetInterpolationMode(BitmapInterpolationMode interpolationMode) + private static InterpolationMode GetInterpolationMode(BitmapInterpolationMode interpolationMode) { switch (interpolationMode) { case BitmapInterpolationMode.LowQuality: - return SharpDX.Direct2D1.BitmapInterpolationMode.NearestNeighbor; + return InterpolationMode.NearestNeighbor; case BitmapInterpolationMode.MediumQuality: + return InterpolationMode.Linear; case BitmapInterpolationMode.HighQuality: + return InterpolationMode.HighQualityCubic; case BitmapInterpolationMode.Default: - return SharpDX.Direct2D1.BitmapInterpolationMode.Linear; + return InterpolationMode.Linear; default: throw new ArgumentOutOfRangeException(nameof(interpolationMode), interpolationMode, null); } @@ -133,17 +150,17 @@ namespace Avalonia.Direct2D1.Media /// The rect in the output to draw to. public void DrawImage(IRef source, IBrush opacityMask, Rect opacityMaskRect, Rect destRect) { - using (var d2dSource = ((BitmapImpl)source.Item).GetDirect2DBitmap(_renderTarget)) - using (var sourceBrush = new BitmapBrush(_renderTarget, d2dSource.Value)) + using (var d2dSource = ((BitmapImpl)source.Item).GetDirect2DBitmap(_deviceContext)) + using (var sourceBrush = new BitmapBrush(_deviceContext, d2dSource.Value)) using (var d2dOpacityMask = CreateBrush(opacityMask, opacityMaskRect.Size)) - using (var geometry = new SharpDX.Direct2D1.RectangleGeometry(_renderTarget.Factory, destRect.ToDirect2D())) + using (var geometry = new SharpDX.Direct2D1.RectangleGeometry(_deviceContext.Factory, destRect.ToDirect2D())) { if (d2dOpacityMask.PlatformBrush != null) { d2dOpacityMask.PlatformBrush.Transform = Matrix.CreateTranslation(opacityMaskRect.Position).ToDirect2D(); } - _renderTarget.FillGeometry( + _deviceContext.FillGeometry( geometry, sourceBrush, d2dOpacityMask.PlatformBrush); @@ -163,11 +180,11 @@ namespace Avalonia.Direct2D1.Media var size = new Rect(p1, p2).Size; using (var d2dBrush = CreateBrush(pen.Brush, size)) - using (var d2dStroke = pen.ToDirect2DStrokeStyle(_renderTarget)) + using (var d2dStroke = pen.ToDirect2DStrokeStyle(_deviceContext)) { if (d2dBrush.PlatformBrush != null) { - _renderTarget.DrawLine( + _deviceContext.DrawLine( p1.ToSharpDX(), p2.ToSharpDX(), d2dBrush.PlatformBrush, @@ -193,7 +210,7 @@ namespace Avalonia.Direct2D1.Media if (d2dBrush.PlatformBrush != null) { var impl = (GeometryImpl)geometry; - _renderTarget.FillGeometry(impl.Geometry, d2dBrush.PlatformBrush); + _deviceContext.FillGeometry(impl.Geometry, d2dBrush.PlatformBrush); } } } @@ -201,12 +218,12 @@ namespace Avalonia.Direct2D1.Media if (pen != null) { using (var d2dBrush = CreateBrush(pen.Brush, geometry.GetRenderBounds(pen).Size)) - using (var d2dStroke = pen.ToDirect2DStrokeStyle(_renderTarget)) + using (var d2dStroke = pen.ToDirect2DStrokeStyle(_deviceContext)) { if (d2dBrush.PlatformBrush != null) { var impl = (GeometryImpl)geometry; - _renderTarget.DrawGeometry(impl.Geometry, d2dBrush.PlatformBrush, (float)pen.Thickness, d2dStroke); + _deviceContext.DrawGeometry(impl.Geometry, d2dBrush.PlatformBrush, (float)pen.Thickness, d2dStroke); } } } @@ -221,13 +238,13 @@ namespace Avalonia.Direct2D1.Media public void DrawRectangle(Pen pen, Rect rect, float cornerRadius) { using (var brush = CreateBrush(pen.Brush, rect.Size)) - using (var d2dStroke = pen.ToDirect2DStrokeStyle(_renderTarget)) + using (var d2dStroke = pen.ToDirect2DStrokeStyle(_deviceContext)) { if (brush.PlatformBrush != null) { if (cornerRadius == 0) { - _renderTarget.DrawRectangle( + _deviceContext.DrawRectangle( rect.ToDirect2D(), brush.PlatformBrush, (float)pen.Thickness, @@ -235,7 +252,7 @@ namespace Avalonia.Direct2D1.Media } else { - _renderTarget.DrawRoundedRectangle( + _deviceContext.DrawRoundedRectangle( new RoundedRectangle { Rect = rect.ToDirect2D(), RadiusX = cornerRadius, RadiusY = cornerRadius }, brush.PlatformBrush, (float)pen.Thickness, @@ -258,7 +275,7 @@ namespace Avalonia.Direct2D1.Media var impl = (FormattedTextImpl)text; using (var brush = CreateBrush(foreground, impl.Size)) - using (var renderer = new AvaloniaTextRenderer(this, _renderTarget, brush.PlatformBrush)) + using (var renderer = new AvaloniaTextRenderer(this, _deviceContext, brush.PlatformBrush)) { if (brush.PlatformBrush != null) { @@ -282,11 +299,11 @@ namespace Avalonia.Direct2D1.Media { if (cornerRadius == 0) { - _renderTarget.FillRectangle(rect.ToDirect2D(), b.PlatformBrush); + _deviceContext.FillRectangle(rect.ToDirect2D(), b.PlatformBrush); } else { - _renderTarget.FillRoundedRectangle( + _deviceContext.FillRoundedRectangle( new RoundedRectangle { Rect = new RawRectangleF( @@ -312,7 +329,7 @@ namespace Avalonia.Direct2D1.Media else { var platform = AvaloniaLocator.Current.GetService(); - var dpi = new Vector(_renderTarget.DotsPerInch.Width, _renderTarget.DotsPerInch.Height); + var dpi = new Vector(_deviceContext.DotsPerInch.Width, _deviceContext.DotsPerInch.Height); var pixelSize = size * (dpi / 96); return platform.CreateRenderTargetBitmap( (int)pixelSize.Width, @@ -329,12 +346,12 @@ namespace Avalonia.Direct2D1.Media /// A disposable used to undo the clip rectangle. public void PushClip(Rect clip) { - _renderTarget.PushAxisAlignedClip(clip.ToSharpDX(), AntialiasMode.PerPrimitive); + _deviceContext.PushAxisAlignedClip(clip.ToSharpDX(), AntialiasMode.PerPrimitive); } public void PopClip() { - _renderTarget.PopAxisAlignedClip(); + _deviceContext.PopAxisAlignedClip(); } readonly Stack _layers = new Stack(); @@ -355,8 +372,8 @@ namespace Avalonia.Direct2D1.Media Opacity = (float)opacity, }; - var layer = _layerPool.Count != 0 ? _layerPool.Pop() : new Layer(_renderTarget); - _renderTarget.PushLayer(ref parameters, layer); + var layer = _layerPool.Count != 0 ? _layerPool.Pop() : new Layer(_deviceContext); + _deviceContext.PushLayer(ref parameters, layer); _layers.Push(layer); } @@ -374,7 +391,7 @@ namespace Avalonia.Direct2D1.Media var layer = _layers.Pop(); if (layer != null) { - _renderTarget.PopLayer(); + _deviceContext.PopLayer(); _layerPool.Push(layer); } } @@ -395,21 +412,21 @@ namespace Avalonia.Direct2D1.Media if (solidColorBrush != null) { - return new SolidColorBrushImpl(solidColorBrush, _renderTarget); + return new SolidColorBrushImpl(solidColorBrush, _deviceContext); } else if (linearGradientBrush != null) { - return new LinearGradientBrushImpl(linearGradientBrush, _renderTarget, destinationSize); + return new LinearGradientBrushImpl(linearGradientBrush, _deviceContext, destinationSize); } else if (radialGradientBrush != null) { - return new RadialGradientBrushImpl(radialGradientBrush, _renderTarget, destinationSize); + return new RadialGradientBrushImpl(radialGradientBrush, _deviceContext, destinationSize); } else if (imageBrush?.Source != null) { return new ImageBrushImpl( imageBrush, - _renderTarget, + _deviceContext, (BitmapImpl)imageBrush.Source.PlatformImpl.Item, destinationSize); } @@ -422,7 +439,7 @@ namespace Avalonia.Direct2D1.Media if (intermediateSize.Width >= 1 && intermediateSize.Height >= 1) { using (var intermediate = new BitmapRenderTarget( - _renderTarget, + _deviceContext, CompatibleRenderTargetOptions.None, intermediateSize.ToSharpDX())) { @@ -434,7 +451,7 @@ namespace Avalonia.Direct2D1.Media return new ImageBrushImpl( visualBrush, - _renderTarget, + _deviceContext, new D2DBitmapImpl(intermediate.Bitmap), destinationSize); } @@ -446,7 +463,7 @@ namespace Avalonia.Direct2D1.Media } } - return new SolidColorBrushImpl(null, _renderTarget); + return new SolidColorBrushImpl(null, _deviceContext); } public void PushGeometryClip(IGeometryImpl clip) @@ -458,8 +475,8 @@ namespace Avalonia.Direct2D1.Media Opacity = 1, GeometricMask = ((GeometryImpl)clip).Geometry }; - var layer = _layerPool.Count != 0 ? _layerPool.Pop() : new Layer(_renderTarget); - _renderTarget.PushLayer(ref parameters, layer); + var layer = _layerPool.Count != 0 ? _layerPool.Pop() : new Layer(_deviceContext); + _deviceContext.PushLayer(ref parameters, layer); _layers.Push(layer); @@ -479,8 +496,8 @@ namespace Avalonia.Direct2D1.Media Opacity = 1, OpacityBrush = CreateBrush(mask, bounds.Size).PlatformBrush }; - var layer = _layerPool.Count != 0 ? _layerPool.Pop() : new Layer(_renderTarget); - _renderTarget.PushLayer(ref parameters, layer); + var layer = _layerPool.Count != 0 ? _layerPool.Pop() : new Layer(_deviceContext); + _deviceContext.PushLayer(ref parameters, layer); _layers.Push(layer); }