diff --git a/src/Avalonia.Controls/Image.cs b/src/Avalonia.Controls/Image.cs
index f6f11aa9ad..f146e3571c 100644
--- a/src/Avalonia.Controls/Image.cs
+++ b/src/Avalonia.Controls/Image.cs
@@ -1,12 +1,11 @@
// 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 Avalonia.Media;
using Avalonia.Media.Imaging;
namespace Avalonia.Controls
-{
+{
///
/// Displays a image.
///
@@ -68,7 +67,9 @@ namespace Avalonia.Controls
Rect sourceRect = new Rect(sourceSize)
.CenterRect(new Rect(destRect.Size / scale));
- context.DrawImage(source, 1, sourceRect, destRect);
+ var interpolationMode = RenderOptions.GetBitmapInterpolationMode(this);
+
+ context.DrawImage(source, 1, sourceRect, destRect, interpolationMode);
}
}
@@ -100,4 +101,4 @@ namespace Avalonia.Controls
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Avalonia.Visuals/Media/DrawingContext.cs b/src/Avalonia.Visuals/Media/DrawingContext.cs
index 962f2c1ba8..60a7a2e518 100644
--- a/src/Avalonia.Visuals/Media/DrawingContext.cs
+++ b/src/Avalonia.Visuals/Media/DrawingContext.cs
@@ -2,9 +2,10 @@ using System;
using System.Collections.Generic;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
+using Avalonia.Visuals.Media.Imaging;
namespace Avalonia.Media
-{
+{
public sealed class DrawingContext : IDisposable
{
private int _currentLevel;
@@ -68,11 +69,12 @@ namespace Avalonia.Media
/// The opacity to draw with.
/// The rect in the image to draw.
/// The rect in the output to draw to.
- public void DrawImage(IBitmap source, double opacity, Rect sourceRect, Rect destRect)
+ /// The bitmap interpolation mode.
+ public void DrawImage(IBitmap source, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode = default)
{
Contract.Requires(source != null);
- PlatformImpl.DrawImage(source.PlatformImpl, opacity, sourceRect, destRect);
+ PlatformImpl.DrawImage(source.PlatformImpl, opacity, sourceRect, destRect, bitmapInterpolationMode);
}
///
@@ -309,4 +311,4 @@ namespace Avalonia.Media
return pen?.Brush != null && pen.Thickness > 0;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Avalonia.Visuals/Media/ITileBrush.cs b/src/Avalonia.Visuals/Media/ITileBrush.cs
index 8e2349f506..5cffe02193 100644
--- a/src/Avalonia.Visuals/Media/ITileBrush.cs
+++ b/src/Avalonia.Visuals/Media/ITileBrush.cs
@@ -1,5 +1,10 @@
-namespace Avalonia.Media
-{
+// 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 Avalonia.Visuals.Media.Imaging;
+
+namespace Avalonia.Media
+{
///
/// A brush which displays a repeating image.
///
@@ -35,5 +40,13 @@
/// Gets the brush's tile mode.
///
TileMode TileMode { get; }
+
+ ///
+ /// Gets the bitmap interpolation mode.
+ ///
+ ///
+ /// The bitmap interpolation mode.
+ ///
+ BitmapInterpolationMode BitmapInterpolationMode { get; }
}
-}
\ No newline at end of file
+}
diff --git a/src/Avalonia.Visuals/Media/Imaging/BitmapInterpolationMode.cs b/src/Avalonia.Visuals/Media/Imaging/BitmapInterpolationMode.cs
new file mode 100644
index 0000000000..7e6d330618
--- /dev/null
+++ b/src/Avalonia.Visuals/Media/Imaging/BitmapInterpolationMode.cs
@@ -0,0 +1,31 @@
+// 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
+{
+ ///
+ /// Controls the performance and quality of bitmap scaling.
+ ///
+ public enum BitmapInterpolationMode
+ {
+ ///
+ /// Uses the default behavior of the underling render backend.
+ ///
+ Default,
+
+ ///
+ /// The best performance but worst image quality.
+ ///
+ LowQuality,
+
+ ///
+ /// Good performance and decent image quality.
+ ///
+ MediumQuality,
+
+ ///
+ /// Highest quality but worst performance.
+ ///
+ HighQuality
+ }
+}
diff --git a/src/Avalonia.Visuals/Media/Immutable/ImmutableImageBrush.cs b/src/Avalonia.Visuals/Media/Immutable/ImmutableImageBrush.cs
index 678f99c20d..15da8f8b43 100644
--- a/src/Avalonia.Visuals/Media/Immutable/ImmutableImageBrush.cs
+++ b/src/Avalonia.Visuals/Media/Immutable/ImmutableImageBrush.cs
@@ -1,5 +1,5 @@
-using System;
-using Avalonia.Media.Imaging;
+using Avalonia.Media.Imaging;
+using Avalonia.Visuals.Media.Imaging;
namespace Avalonia.Media.Immutable
{
@@ -21,6 +21,7 @@ namespace Avalonia.Media.Immutable
/// How the source rectangle will be stretched to fill the destination rect.
///
/// The tile mode.
+ /// The bitmap interpolation mode.
public ImmutableImageBrush(
IBitmap source,
AlignmentX alignmentX = AlignmentX.Center,
@@ -29,7 +30,8 @@ namespace Avalonia.Media.Immutable
double opacity = 1,
RelativeRect? sourceRect = null,
Stretch stretch = Stretch.Uniform,
- TileMode tileMode = TileMode.None)
+ TileMode tileMode = TileMode.None,
+ BitmapInterpolationMode bitmapInterpolationMode = BitmapInterpolationMode.Default)
: base(
alignmentX,
alignmentY,
@@ -37,7 +39,8 @@ namespace Avalonia.Media.Immutable
opacity,
sourceRect ?? RelativeRect.Fill,
stretch,
- tileMode)
+ tileMode,
+ bitmapInterpolationMode)
{
Source = source;
}
diff --git a/src/Avalonia.Visuals/Media/Immutable/ImmutableTileBrush.cs b/src/Avalonia.Visuals/Media/Immutable/ImmutableTileBrush.cs
index 37c391040f..c3dd159d04 100644
--- a/src/Avalonia.Visuals/Media/Immutable/ImmutableTileBrush.cs
+++ b/src/Avalonia.Visuals/Media/Immutable/ImmutableTileBrush.cs
@@ -1,4 +1,7 @@
-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 Avalonia.Visuals.Media.Imaging;
namespace Avalonia.Media.Immutable
{
@@ -19,6 +22,7 @@ namespace Avalonia.Media.Immutable
/// How the source rectangle will be stretched to fill the destination rect.
///
/// The tile mode.
+ /// The bitmap interpolation mode.
protected ImmutableTileBrush(
AlignmentX alignmentX,
AlignmentY alignmentY,
@@ -26,7 +30,8 @@ namespace Avalonia.Media.Immutable
double opacity,
RelativeRect sourceRect,
Stretch stretch,
- TileMode tileMode)
+ TileMode tileMode,
+ BitmapInterpolationMode bitmapInterpolationMode)
{
AlignmentX = alignmentX;
AlignmentY = alignmentY;
@@ -35,6 +40,7 @@ namespace Avalonia.Media.Immutable
SourceRect = sourceRect;
Stretch = stretch;
TileMode = tileMode;
+ BitmapInterpolationMode = bitmapInterpolationMode;
}
///
@@ -49,7 +55,8 @@ namespace Avalonia.Media.Immutable
source.Opacity,
source.SourceRect,
source.Stretch,
- source.TileMode)
+ source.TileMode,
+ source.BitmapInterpolationMode)
{
}
@@ -73,5 +80,8 @@ namespace Avalonia.Media.Immutable
///
public TileMode TileMode { get; }
+
+ ///
+ public BitmapInterpolationMode BitmapInterpolationMode { get; }
}
}
diff --git a/src/Avalonia.Visuals/Media/Immutable/ImmutableVisualBrush.cs b/src/Avalonia.Visuals/Media/Immutable/ImmutableVisualBrush.cs
index b07d98867c..f1f61a6e65 100644
--- a/src/Avalonia.Visuals/Media/Immutable/ImmutableVisualBrush.cs
+++ b/src/Avalonia.Visuals/Media/Immutable/ImmutableVisualBrush.cs
@@ -1,4 +1,7 @@
-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 Avalonia.Visuals.Media.Imaging;
using Avalonia.VisualTree;
namespace Avalonia.Media.Immutable
@@ -21,6 +24,7 @@ namespace Avalonia.Media.Immutable
/// How the source rectangle will be stretched to fill the destination rect.
///
/// The tile mode.
+ /// Controls the quality of interpolation.
public ImmutableVisualBrush(
IVisual visual,
AlignmentX alignmentX = AlignmentX.Center,
@@ -29,7 +33,8 @@ namespace Avalonia.Media.Immutable
double opacity = 1,
RelativeRect? sourceRect = null,
Stretch stretch = Stretch.Uniform,
- TileMode tileMode = TileMode.None)
+ TileMode tileMode = TileMode.None,
+ BitmapInterpolationMode bitmapInterpolationMode = BitmapInterpolationMode.Default)
: base(
alignmentX,
alignmentY,
@@ -37,7 +42,8 @@ namespace Avalonia.Media.Immutable
opacity,
sourceRect ?? RelativeRect.Fill,
stretch,
- tileMode)
+ tileMode,
+ bitmapInterpolationMode)
{
Visual = visual;
}
diff --git a/src/Avalonia.Visuals/Media/RenderOptions.cs b/src/Avalonia.Visuals/Media/RenderOptions.cs
new file mode 100644
index 0000000000..180863f9e8
--- /dev/null
+++ b/src/Avalonia.Visuals/Media/RenderOptions.cs
@@ -0,0 +1,39 @@
+// 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 Avalonia.Visuals.Media.Imaging;
+
+namespace Avalonia.Media
+{
+ public class RenderOptions
+ {
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty BitmapInterpolationModeProperty =
+ AvaloniaProperty.RegisterAttached(
+ "BitmapInterpolationMode",
+ BitmapInterpolationMode.MediumQuality,
+ inherits: true);
+
+ ///
+ /// Gets the value of the BitmapInterpolationMode attached property for a control.
+ ///
+ /// The control.
+ /// The control's left coordinate.
+ public static BitmapInterpolationMode GetBitmapInterpolationMode(AvaloniaObject element)
+ {
+ return element.GetValue(BitmapInterpolationModeProperty);
+ }
+
+ ///
+ /// Sets the value of the BitmapInterpolationMode attached property for a control.
+ ///
+ /// The control.
+ /// The left value.
+ public static void SetBitmapInterpolationMode(AvaloniaObject element, BitmapInterpolationMode value)
+ {
+ element.SetValue(BitmapInterpolationModeProperty, value);
+ }
+ }
+}
diff --git a/src/Avalonia.Visuals/Media/TileBrush.cs b/src/Avalonia.Visuals/Media/TileBrush.cs
index 3a7f9d9920..2033754137 100644
--- a/src/Avalonia.Visuals/Media/TileBrush.cs
+++ b/src/Avalonia.Visuals/Media/TileBrush.cs
@@ -1,6 +1,8 @@
// 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 Avalonia.Visuals.Media.Imaging;
+
namespace Avalonia.Media
{
///
@@ -75,6 +77,11 @@ namespace Avalonia.Media
public static readonly StyledProperty TileModeProperty =
AvaloniaProperty.Register(nameof(TileMode));
+ static TileBrush()
+ {
+ RenderOptions.BitmapInterpolationModeProperty.OverrideDefaultValue(BitmapInterpolationMode.Default);
+ }
+
///
/// Gets or sets the horizontal alignment of a tile in the destination.
///
@@ -129,5 +136,17 @@ namespace Avalonia.Media
get { return (TileMode)GetValue(TileModeProperty); }
set { SetValue(TileModeProperty, value); }
}
+
+ ///
+ /// Gets or sets the bitmap interpolation mode.
+ ///
+ ///
+ /// The bitmap interpolation mode.
+ ///
+ public BitmapInterpolationMode BitmapInterpolationMode
+ {
+ get { return RenderOptions.GetBitmapInterpolationMode(this); }
+ set { RenderOptions.SetBitmapInterpolationMode(this, value); }
+ }
}
}
diff --git a/src/Avalonia.Visuals/Platform/IDrawingContextImpl.cs b/src/Avalonia.Visuals/Platform/IDrawingContextImpl.cs
index 04bbe713f2..b11d9f52ab 100644
--- a/src/Avalonia.Visuals/Platform/IDrawingContextImpl.cs
+++ b/src/Avalonia.Visuals/Platform/IDrawingContextImpl.cs
@@ -4,6 +4,7 @@
using System;
using Avalonia.Media;
using Avalonia.Utilities;
+using Avalonia.Visuals.Media.Imaging;
namespace Avalonia.Platform
{
@@ -30,7 +31,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);
+ /// The bitmap interpolation mode.
+ void DrawImage(IRef source, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode = BitmapInterpolationMode.Default);
///
/// Draws a bitmap image.
diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs
index f3dbfbd8fb..42ecde6a6d 100644
--- a/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs
+++ b/src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs
@@ -7,6 +7,7 @@ using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Utilities;
using Avalonia.VisualTree;
+using Avalonia.Visuals.Media.Imaging;
namespace Avalonia.Rendering.SceneGraph
{
@@ -114,13 +115,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, BitmapInterpolationMode bitmapInterpolationMode)
{
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, bitmapInterpolationMode))
{
- Add(new ImageNode(Transform, source, opacity, sourceRect, destRect));
+ Add(new ImageNode(Transform, source, opacity, sourceRect, destRect, bitmapInterpolationMode));
}
else
{
diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/ImageNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/ImageNode.cs
index 06fdb3f86c..9e8fca5f84 100644
--- a/src/Avalonia.Visuals/Rendering/SceneGraph/ImageNode.cs
+++ b/src/Avalonia.Visuals/Rendering/SceneGraph/ImageNode.cs
@@ -4,6 +4,7 @@
using System;
using Avalonia.Platform;
using Avalonia.Utilities;
+using Avalonia.Visuals.Media.Imaging;
namespace Avalonia.Rendering.SceneGraph
{
@@ -20,7 +21,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)
+ /// The bitmap interpolation mode.
+ public ImageNode(Matrix transform, IRef source, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode)
: base(destRect, transform, null)
{
Transform = transform;
@@ -28,7 +30,8 @@ namespace Avalonia.Rendering.SceneGraph
Opacity = opacity;
SourceRect = sourceRect;
DestRect = destRect;
- }
+ BitmapInterpolationMode = bitmapInterpolationMode;
+ }
///
/// Gets the transform with which the node will be drawn.
@@ -55,6 +58,14 @@ namespace Avalonia.Rendering.SceneGraph
///
public Rect DestRect { get; }
+ ///
+ /// Gets the bitmap interpolation mode.
+ ///
+ ///
+ /// The scaling mode.
+ ///
+ public BitmapInterpolationMode BitmapInterpolationMode { get; }
+
///
/// Determines if this draw operation equals another.
///
@@ -63,18 +74,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.
+ /// The bitmap interpolation mode.
/// 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, BitmapInterpolationMode bitmapInterpolationMode)
{
return transform == Transform &&
Equals(source.Item, Source.Item) &&
opacity == Opacity &&
sourceRect == SourceRect &&
- destRect == DestRect;
+ destRect == DestRect &&
+ bitmapInterpolationMode == BitmapInterpolationMode;
}
///
@@ -83,7 +96,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, BitmapInterpolationMode);
}
///
diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
index d2c4bd0aa1..685987ae80 100644
--- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
+++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
@@ -10,6 +10,7 @@ using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Rendering.Utilities;
using Avalonia.Utilities;
+using Avalonia.Visuals.Media.Imaging;
using SkiaSharp;
namespace Avalonia.Skia
@@ -95,24 +96,46 @@ namespace Avalonia.Skia
}
///
- public void DrawImage(IRef source, double opacity, Rect sourceRect, Rect destRect)
+ public void DrawImage(IRef source, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode)
{
- var drawableImage = (IDrawableBitmapImpl) source.Item;
+ var drawableImage = (IDrawableBitmapImpl)source.Item;
var s = sourceRect.ToSKRect();
var d = destRect.ToSKRect();
using (var paint =
- new SKPaint {Color = new SKColor(255, 255, 255, (byte) (255 * opacity * _currentOpacity))})
+ new SKPaint
+ {
+ Color = new SKColor(255, 255, 255, (byte)(255 * opacity * _currentOpacity))
+ })
{
+ paint.FilterQuality = GetInterpolationMode(bitmapInterpolationMode);
+
drawableImage.Draw(this, s, d, paint);
}
}
+ private static SKFilterQuality GetInterpolationMode(BitmapInterpolationMode interpolationMode)
+ {
+ switch (interpolationMode)
+ {
+ case BitmapInterpolationMode.LowQuality:
+ return SKFilterQuality.Low;
+ case BitmapInterpolationMode.MediumQuality:
+ return SKFilterQuality.Medium;
+ case BitmapInterpolationMode.HighQuality:
+ return SKFilterQuality.High;
+ case BitmapInterpolationMode.Default:
+ return SKFilterQuality.None;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(interpolationMode), interpolationMode, null);
+ }
+ }
+
///
public void DrawImage(IRef source, IBrush opacityMask, Rect opacityMaskRect, Rect destRect)
{
PushOpacityMask(opacityMask, opacityMaskRect);
- DrawImage(source, 1, new Rect(0, 0, source.Item.PixelWidth, source.Item.PixelHeight), destRect);
+ DrawImage(source, 1, new Rect(0, 0, source.Item.PixelWidth, source.Item.PixelHeight), destRect, BitmapInterpolationMode.Default);
PopOpacityMask();
}
@@ -357,6 +380,7 @@ namespace Avalonia.Skia
/// Target size.
/// Tile brush to use.
/// Tile brush image.
+ /// The bitmap interpolation mode.
private void ConfigureTileBrush(ref PaintWrapper paintWrapper, Size targetSize, ITileBrush tileBrush, IDrawableBitmapImpl tileBrushImage)
{
var calc = new TileBrushCalculator(tileBrush,
@@ -375,7 +399,7 @@ namespace Avalonia.Skia
context.Clear(Colors.Transparent);
context.PushClip(calc.IntermediateClip);
context.Transform = calc.IntermediateTransform;
- context.DrawImage(RefCountable.CreateUnownedNotClonable(tileBrushImage), 1, rect, rect);
+ context.DrawImage(RefCountable.CreateUnownedNotClonable(tileBrushImage), 1, rect, rect, tileBrush.BitmapInterpolationMode);
context.PopClip();
}
@@ -484,7 +508,7 @@ namespace Avalonia.Skia
}
else
{
- tileBrushImage = (IDrawableBitmapImpl) (tileBrush as IImageBrush)?.Source?.PlatformImpl.Item;
+ tileBrushImage = (IDrawableBitmapImpl)(tileBrush as IImageBrush)?.Source?.PlatformImpl.Item;
}
if (tileBrush != null && tileBrushImage != null)
@@ -690,4 +714,4 @@ namespace Avalonia.Skia
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
index 479db51be4..ae5dd3ae13 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
@@ -10,13 +10,14 @@ using Avalonia.Utilities;
using SharpDX;
using SharpDX.Direct2D1;
using SharpDX.Mathematics.Interop;
+using BitmapInterpolationMode = Avalonia.Visuals.Media.Imaging.BitmapInterpolationMode;
namespace Avalonia.Direct2D1.Media
{
///
/// Draws using Direct2D1.
///
- public class DrawingContextImpl : IDrawingContextImpl, IDisposable
+ public class DrawingContextImpl : IDrawingContextImpl
{
private readonly IVisualBrushRenderer _visualBrushRenderer;
private readonly ILayerFactory _layerFactory;
@@ -100,19 +101,37 @@ 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)
+ /// 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))
{
+ var interpolationMode = GetInterpolationMode(bitmapInterpolationMode);
+
_renderTarget.DrawBitmap(
d2d.Value,
destRect.ToSharpDX(),
(float)opacity,
- BitmapInterpolationMode.Linear,
+ interpolationMode,
sourceRect.ToSharpDX());
}
}
+ private static SharpDX.Direct2D1.BitmapInterpolationMode GetInterpolationMode(BitmapInterpolationMode interpolationMode)
+ {
+ switch (interpolationMode)
+ {
+ case BitmapInterpolationMode.LowQuality:
+ return SharpDX.Direct2D1.BitmapInterpolationMode.NearestNeighbor;
+ case BitmapInterpolationMode.MediumQuality:
+ case BitmapInterpolationMode.HighQuality:
+ case BitmapInterpolationMode.Default:
+ return SharpDX.Direct2D1.BitmapInterpolationMode.Linear;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(interpolationMode), interpolationMode, null);
+ }
+ }
+
///
/// Draws a bitmap image.
///
diff --git a/src/Windows/Avalonia.Direct2D1/Media/ImageBrushImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/ImageBrushImpl.cs
index 75b397edd6..3fc8760a9e 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/ImageBrushImpl.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/ImageBrushImpl.cs
@@ -1,7 +1,6 @@
// 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 Avalonia.Media;
using Avalonia.Rendering.Utilities;
using Avalonia.Utilities;
@@ -11,7 +10,9 @@ namespace Avalonia.Direct2D1.Media
{
public sealed class ImageBrushImpl : BrushImpl
{
- OptionalDispose _bitmap;
+ private readonly OptionalDispose _bitmap;
+
+ private readonly Visuals.Media.Imaging.BitmapInterpolationMode _bitmapInterpolationMode;
public ImageBrushImpl(
ITileBrush brush,
@@ -41,6 +42,8 @@ namespace Avalonia.Direct2D1.Media
GetBrushProperties(brush, calc.DestinationRect));
}
}
+
+ _bitmapInterpolationMode = brush.BitmapInterpolationMode;
}
public override void Dispose()
@@ -102,7 +105,7 @@ namespace Avalonia.Direct2D1.Media
context.PushClip(calc.IntermediateClip);
context.Transform = calc.IntermediateTransform;
- context.DrawImage(RefCountable.CreateUnownedNotClonable(bitmap), 1, rect, rect);
+ context.DrawImage(RefCountable.CreateUnownedNotClonable(bitmap), 1, rect, rect, _bitmapInterpolationMode);
context.PopClip();
}
diff --git a/tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests.cs b/tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests.cs
index 7821f60a51..2350a31d5c 100644
--- a/tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests.cs
+++ b/tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Subjects;
+
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Media;
@@ -10,8 +11,11 @@ using Avalonia.Rendering;
using Avalonia.Rendering.SceneGraph;
using Avalonia.Threading;
using Avalonia.UnitTests;
+using Avalonia.Visuals.Media.Imaging;
using Avalonia.VisualTree;
+
using Moq;
+
using Xunit;
namespace Avalonia.Visuals.UnitTests.Rendering
@@ -336,7 +340,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering
var context = Mock.Get(target.RenderTarget.CreateDrawingContext(null));
var borderLayer = target.Layers[border].Bitmap;
- context.Verify(x => x.DrawImage(borderLayer, 0.5, It.IsAny(), It.IsAny()));
+ context.Verify(x => x.DrawImage(borderLayer, 0.5, It.IsAny(), It.IsAny(), BitmapInterpolationMode.Default));
}
private DeferredRenderer CreateTargetAndRunFrame(
diff --git a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/DrawOperationTests.cs b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/DrawOperationTests.cs
index 8c905dab2f..2060cc7170 100644
--- a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/DrawOperationTests.cs
+++ b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/DrawOperationTests.cs
@@ -1,13 +1,13 @@
-using System;
-using Avalonia.Media;
+using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Rendering.SceneGraph;
using Avalonia.Utilities;
+using Avalonia.Visuals.Media.Imaging;
using Moq;
using Xunit;
namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
-{
+{
public class DrawOperationTests
{
[Fact]
@@ -46,7 +46,13 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
public void Image_Node_Releases_Reference_To_Bitmap_On_Dispose()
{
var bitmap = RefCountable.Create(Mock.Of());
- var imageNode = new ImageNode(Matrix.Identity, bitmap, 1, new Rect(1,1,1,1), new Rect(1,1,1,1));
+ var imageNode = new ImageNode(
+ Matrix.Identity,
+ bitmap,
+ 1,
+ new Rect(1, 1, 1, 1),
+ new Rect(1, 1, 1, 1),
+ BitmapInterpolationMode.Default);
Assert.Equal(2, bitmap.RefCount);