Browse Source

InterpolationMode.HighQuality support

pull/1861/head
Benedikt Schroeder 8 years ago
parent
commit
e76b694ebd
  1. 103
      src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs

103
src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs

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

Loading…
Cancel
Save