diff --git a/src/Avalonia.Visuals/Media/Imaging/BitmapScalingMode.cs b/src/Avalonia.Visuals/Media/Imaging/BitmapScalingMode.cs
new file mode 100644
index 0000000000..36d239c9d9
--- /dev/null
+++ b/src/Avalonia.Visuals/Media/Imaging/BitmapScalingMode.cs
@@ -0,0 +1,12 @@
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+namespace Avalonia.Visuals.Media.Imaging
+{
+ public enum BitmapScalingMode
+ {
+ LowQuality,
+ MediumQuality,
+ HighQuality
+ }
+}
diff --git a/src/Avalonia.Visuals/Platform/IDrawingContextImpl.cs b/src/Avalonia.Visuals/Platform/IDrawingContextImpl.cs
index 04bbe713f2..f511daf9b2 100644
--- a/src/Avalonia.Visuals/Platform/IDrawingContextImpl.cs
+++ b/src/Avalonia.Visuals/Platform/IDrawingContextImpl.cs
@@ -7,6 +7,8 @@ using Avalonia.Utilities;
namespace Avalonia.Platform
{
+ using Avalonia.Visuals.Media.Imaging;
+
///
/// Defines the interface through which drawing occurs.
///
@@ -30,7 +32,8 @@ namespace Avalonia.Platform
/// The opacity to draw with.
/// The rect in the image to draw.
/// The rect in the output to draw to.
- void DrawImage(IRef source, double opacity, Rect sourceRect, Rect destRect);
+ /// Controls
+ void DrawImage(IRef source, double opacity, Rect sourceRect, Rect destRect, BitmapScalingMode scalingMode = BitmapScalingMode.LowQuality);
///
/// Draws a bitmap image.
diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs
index f3dbfbd8fb..7172696e81 100644
--- a/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs
+++ b/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs
@@ -10,6 +10,8 @@ using Avalonia.VisualTree;
namespace Avalonia.Rendering.SceneGraph
{
+ using Avalonia.Visuals.Media.Imaging;
+
///
/// A drawing context which builds a scene graph.
///
@@ -114,13 +116,13 @@ namespace Avalonia.Rendering.SceneGraph
}
///
- public void DrawImage(IRef source, double opacity, Rect sourceRect, Rect destRect)
+ public void DrawImage(IRef source, double opacity, Rect sourceRect, Rect destRect, BitmapScalingMode scalingMode = BitmapScalingMode.LowQuality)
{
var next = NextDrawAs();
- if (next == null || !next.Item.Equals(Transform, source, opacity, sourceRect, destRect))
+ if (next == null || !next.Item.Equals(Transform, source, opacity, sourceRect, destRect, scalingMode))
{
- Add(new ImageNode(Transform, source, opacity, sourceRect, destRect));
+ Add(new ImageNode(Transform, source, opacity, sourceRect, destRect, scalingMode));
}
else
{
diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/ImageNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/ImageNode.cs
index 06fdb3f86c..96a8731715 100644
--- a/src/Avalonia.Visuals/Rendering/SceneGraph/ImageNode.cs
+++ b/src/Avalonia.Visuals/Rendering/SceneGraph/ImageNode.cs
@@ -7,6 +7,8 @@ using Avalonia.Utilities;
namespace Avalonia.Rendering.SceneGraph
{
+ using Avalonia.Visuals.Media.Imaging;
+
///
/// A node in the scene graph which represents an image draw.
///
@@ -20,7 +22,8 @@ namespace Avalonia.Rendering.SceneGraph
/// The draw opacity.
/// The source rect.
/// The destination rect.
- public ImageNode(Matrix transform, IRef source, double opacity, Rect sourceRect, Rect destRect)
+ ///
+ public ImageNode(Matrix transform, IRef source, double opacity, Rect sourceRect, Rect destRect, BitmapScalingMode scalingMode)
: base(destRect, transform, null)
{
Transform = transform;
@@ -28,8 +31,11 @@ namespace Avalonia.Rendering.SceneGraph
Opacity = opacity;
SourceRect = sourceRect;
DestRect = destRect;
+ ScalingMode = scalingMode;
}
+
+
///
/// Gets the transform with which the node will be drawn.
///
@@ -55,6 +61,14 @@ namespace Avalonia.Rendering.SceneGraph
///
public Rect DestRect { get; }
+ ///
+ /// Gets or sets the scaling mode.
+ ///
+ ///
+ /// The scaling mode.
+ ///
+ public BitmapScalingMode ScalingMode { get; }
+
///
/// Determines if this draw operation equals another.
///
@@ -63,18 +77,20 @@ namespace Avalonia.Rendering.SceneGraph
/// The opacity of the other draw operation.
/// The source rect of the other draw operation.
/// The dest rect of the other draw operation.
+ ///
/// True if the draw operations are the same, otherwise false.
///
/// The properties of the other draw operation are passed in as arguments to prevent
/// allocation of a not-yet-constructed draw operation object.
///
- public bool Equals(Matrix transform, IRef source, double opacity, Rect sourceRect, Rect destRect)
+ public bool Equals(Matrix transform, IRef source, double opacity, Rect sourceRect, Rect destRect, BitmapScalingMode scalingMode)
{
return transform == Transform &&
Equals(source.Item, Source.Item) &&
opacity == Opacity &&
sourceRect == SourceRect &&
- destRect == DestRect;
+ destRect == DestRect &&
+ scalingMode == ScalingMode;
}
///
@@ -83,7 +99,7 @@ namespace Avalonia.Rendering.SceneGraph
// TODO: Probably need to introduce some kind of locking mechanism in the case of
// WriteableBitmap.
context.Transform = Transform;
- context.DrawImage(Source, Opacity, SourceRect, DestRect);
+ context.DrawImage(Source, Opacity, SourceRect, DestRect, ScalingMode);
}
///
diff --git a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
index bdbbdab2b9..27115e164a 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
@@ -13,6 +13,8 @@ using SharpDX.Mathematics.Interop;
namespace Avalonia.Direct2D1.Media
{
+ using Avalonia.Visuals.Media.Imaging;
+
///
/// Draws using Direct2D1.
///
@@ -100,16 +102,43 @@ namespace Avalonia.Direct2D1.Media
/// The opacity to draw with.
/// The rect in the image to draw.
/// The rect in the output to draw to.
- public void DrawImage(IRef source, double opacity, Rect sourceRect, Rect destRect)
+ ///
+ public void DrawImage(IRef source, double opacity, Rect sourceRect, Rect destRect, BitmapScalingMode scalingMode)
{
using (var d2d = ((BitmapImpl)source.Item).GetDirect2DBitmap(_renderTarget))
{
- _renderTarget.DrawBitmap(
- d2d.Value,
- destRect.ToSharpDX(),
- (float)opacity,
- BitmapInterpolationMode.Linear,
- sourceRect.ToSharpDX());
+ if (_renderTarget is DeviceContext deviceContext)
+ {
+ deviceContext.DrawBitmap(d2d.Value, destRect.ToDirect2D(), (float)opacity, GetInterpolationMode(scalingMode), sourceRect.ToDirect2D(), null);
+ }
+ else
+ {
+ var interpolationMode = scalingMode == BitmapScalingMode.LowQuality
+ ? BitmapInterpolationMode.NearestNeighbor
+ : BitmapInterpolationMode.Linear;
+
+ _renderTarget.DrawBitmap(
+ d2d.Value,
+ destRect.ToSharpDX(),
+ (float)opacity,
+ interpolationMode,
+ sourceRect.ToSharpDX());
+ }
+ }
+ }
+
+ private static InterpolationMode GetInterpolationMode(BitmapScalingMode scalingMode)
+ {
+ switch (scalingMode)
+ {
+ case BitmapScalingMode.LowQuality:
+ return InterpolationMode.NearestNeighbor;
+ case BitmapScalingMode.MediumQuality:
+ return InterpolationMode.Linear;
+ case BitmapScalingMode.HighQuality:
+ return InterpolationMode.HighQualityCubic;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scalingMode), scalingMode, null);
}
}
diff --git a/src/Windows/Avalonia.Direct2D1/Media/Imaging/BitmapImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/Imaging/BitmapImpl.cs
index d58f023391..c792334ec1 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/Imaging/BitmapImpl.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/Imaging/BitmapImpl.cs
@@ -1,11 +1,15 @@
-using System;
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
using System.IO;
using Avalonia.Platform;
using SharpDX.WIC;
-using D2DBitmap = SharpDX.Direct2D1.Bitmap;
namespace Avalonia.Direct2D1.Media
{
+ using SharpDX.Direct2D1;
+
public abstract class BitmapImpl : IBitmapImpl, IDisposable
{
public BitmapImpl(ImagingFactory imagingFactory)
@@ -17,7 +21,7 @@ namespace Avalonia.Direct2D1.Media
public abstract int PixelWidth { get; }
public abstract int PixelHeight { get; }
- public abstract OptionalDispose GetDirect2DBitmap(SharpDX.Direct2D1.RenderTarget target);
+ public abstract OptionalDispose GetDirect2DBitmap(RenderTarget target);
public void Save(string fileName)
{