Jelajahi Sumber

InterpolationMode.HighQuality support

Benedikt Schroeder 7 tahun lalu
induk
melakukan
e76b694ebd
1 mengubah file dengan 60 tambahan dan 43 penghapusan
  1. 60 43
      src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs

+ 60 - 43
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>();
+            }
+
+            _deviceContext.BeginDraw();
         }
 
         /// <summary>
@@ -56,14 +67,14 @@ namespace Avalonia.Direct2D1.Media
         /// </summary>
         public Matrix Transform
         {
-            get { return _renderTarget.Transform.ToAvalonia(); }
-            set { _renderTarget.Transform = value.ToDirect2D(); }
+            get { return _deviceContext.Transform.ToAvalonia(); }
+            set { _deviceContext.Transform = value.ToDirect2D(); }
         }
 
         /// <inheritdoc/>
         public void Clear(Color color)
         {
-            _renderTarget.Clear(color.ToDirect2D());
+            _deviceContext.Clear(color.ToDirect2D());
         }
 
         /// <summary>
@@ -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
         /// <param name="bitmapInterpolationMode">The bitmap interpolation mode.</param>
         public void DrawImage(IRef<IBitmapImpl> 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
         /// <param name="destRect">The rect in the output to draw to.</param>
         public void DrawImage(IRef<IBitmapImpl> 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<IPlatformRenderInterface>();
-                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
         /// <returns>A disposable used to undo the clip rectangle.</returns>
         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<Layer> _layers = new Stack<Layer>();
@@ -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);
         }