diff --git a/src/Avalonia.Base/Media/DrawingContext.cs b/src/Avalonia.Base/Media/DrawingContext.cs
index 18d6968168..c38f4d656d 100644
--- a/src/Avalonia.Base/Media/DrawingContext.cs
+++ b/src/Avalonia.Base/Media/DrawingContext.cs
@@ -4,7 +4,6 @@ using Avalonia.Platform;
using Avalonia.Rendering.SceneGraph;
using Avalonia.Threading;
using Avalonia.Utilities;
-using Avalonia.Media.Imaging;
namespace Avalonia.Media
{
@@ -53,12 +52,10 @@ namespace Avalonia.Media
/// The image.
/// The rect in the image to draw.
/// The rect in the output to draw to.
- /// The bitmap interpolation mode.
- public virtual void DrawImage(IImage source, Rect sourceRect, Rect destRect,
- BitmapInterpolationMode bitmapInterpolationMode = default)
+ public virtual void DrawImage(IImage source, Rect sourceRect, Rect destRect)
{
_ = source ?? throw new ArgumentNullException(nameof(source));
- source.Draw(this, sourceRect, destRect, bitmapInterpolationMode);
+ source.Draw(this, sourceRect, destRect);
}
///
@@ -68,8 +65,7 @@ namespace Avalonia.Media
/// The opacity to draw with.
/// The rect in the image to draw.
/// The rect in the output to draw to.
- /// The bitmap interpolation mode.
- internal abstract void DrawBitmap(IRef source, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode = BitmapInterpolationMode.Default);
+ internal abstract void DrawBitmap(IRef source, double opacity, Rect sourceRect, Rect destRect);
///
/// Draws a line.
@@ -286,8 +282,7 @@ namespace Avalonia.Media
Opacity,
Clip,
GeometryClip,
- OpacityMask,
- BitmapBlendMode
+ OpacityMask
}
public RestoreState(DrawingContext context, PushedStateType type)
@@ -312,8 +307,6 @@ namespace Avalonia.Media
_context.PopGeometryClipCore();
else if (_type == PushedStateType.OpacityMask)
_context.PopOpacityMaskCore();
- else if (_type == PushedStateType.BitmapBlendMode)
- _context.PopBitmapBlendModeCore();
}
}
@@ -394,16 +387,6 @@ namespace Avalonia.Media
}
protected abstract void PushOpacityMaskCore(IBrush mask, Rect bounds);
- public PushedState PushBitmapBlendMode(BitmapBlendingMode blendingMode)
- {
- PushBitmapBlendMode(blendingMode);
- _states ??= StateStackPool.Get();
- _states.Push(new RestoreState(this, RestoreState.PushedStateType.BitmapBlendMode));
- return new PushedState(this);
- }
-
- protected abstract void PushBitmapBlendModeCore(BitmapBlendingMode blendingMode);
-
///
/// Pushes a matrix transformation.
///
@@ -431,7 +414,6 @@ namespace Avalonia.Media
protected abstract void PopGeometryClipCore();
protected abstract void PopOpacityCore();
protected abstract void PopOpacityMaskCore();
- protected abstract void PopBitmapBlendModeCore();
protected abstract void PopTransformCore();
private static bool PenIsVisible(IPen? pen)
diff --git a/src/Avalonia.Base/Media/DrawingGroup.cs b/src/Avalonia.Base/Media/DrawingGroup.cs
index c96d2aad57..5a5bd50c7c 100644
--- a/src/Avalonia.Base/Media/DrawingGroup.cs
+++ b/src/Avalonia.Base/Media/DrawingGroup.cs
@@ -196,13 +196,7 @@ namespace Avalonia.Media
throw new NotImplementedException();
}
- protected override void PushBitmapBlendModeCore(BitmapBlendingMode blendingMode)
- {
- throw new NotImplementedException();
- }
-
- internal override void DrawBitmap(IRef source, double opacity, Rect sourceRect, Rect destRect,
- BitmapInterpolationMode bitmapInterpolationMode = BitmapInterpolationMode.Default)
+ internal override void DrawBitmap(IRef source, double opacity, Rect sourceRect, Rect destRect)
{
throw new NotImplementedException();
}
@@ -321,8 +315,6 @@ namespace Avalonia.Media
protected override void PopOpacityMaskCore() => Pop();
- protected override void PopBitmapBlendModeCore() => Pop();
-
protected override void PopTransformCore() => Pop();
///
diff --git a/src/Avalonia.Base/Media/DrawingImage.cs b/src/Avalonia.Base/Media/DrawingImage.cs
index 52fbd87db7..c83e8eb6ee 100644
--- a/src/Avalonia.Base/Media/DrawingImage.cs
+++ b/src/Avalonia.Base/Media/DrawingImage.cs
@@ -1,6 +1,5 @@
using System;
using Avalonia.Metadata;
-using Avalonia.Media.Imaging;
namespace Avalonia.Media
{
@@ -43,8 +42,7 @@ namespace Avalonia.Media
void IImage.Draw(
DrawingContext context,
Rect sourceRect,
- Rect destRect,
- BitmapInterpolationMode bitmapInterpolationMode)
+ Rect destRect)
{
var drawing = Drawing;
diff --git a/src/Avalonia.Base/Media/EdgeMode.cs b/src/Avalonia.Base/Media/EdgeMode.cs
new file mode 100644
index 0000000000..f50a2f7164
--- /dev/null
+++ b/src/Avalonia.Base/Media/EdgeMode.cs
@@ -0,0 +1,10 @@
+namespace Avalonia.Media
+{
+ public enum EdgeMode : byte
+ {
+ Unspecified,
+
+ Antialias,
+ Aliased
+ }
+}
diff --git a/src/Avalonia.Base/Media/GlyphRun.cs b/src/Avalonia.Base/Media/GlyphRun.cs
index d795cca894..20e0f96ff7 100644
--- a/src/Avalonia.Base/Media/GlyphRun.cs
+++ b/src/Avalonia.Base/Media/GlyphRun.cs
@@ -153,7 +153,7 @@ namespace Avalonia.Media
///
/// Gets the conservative bounding box of the .
///
- public Rect Bounds => PlatformImpl.Item.Bounds;
+ public Rect Bounds => new Rect(new Size(Metrics.WidthIncludingTrailingWhitespace, Metrics.Height));
///
///
@@ -166,7 +166,7 @@ namespace Avalonia.Media
///
public Point BaselineOrigin
{
- get => PlatformImpl.Item.BaselineOrigin;
+ get => _baselineOrigin ?? new Point(0, Metrics.Baseline);
set => Set(ref _baselineOrigin, value);
}
@@ -676,13 +676,17 @@ namespace Avalonia.Media
}
}
- return new GlyphRunMetrics(
- width,
- trailingWhitespaceLength,
- newLineLength,
- firstCluster,
- lastCluster
- );
+ return new GlyphRunMetrics
+ {
+ Baseline = -GlyphTypeface.Metrics.Ascent * Scale,
+ Width = width,
+ WidthIncludingTrailingWhitespace = widthIncludingTrailingWhitespace,
+ Height = height,
+ NewLineLength = newLineLength,
+ TrailingWhitespaceLength = trailingWhitespaceLength,
+ FirstCluster = firstCluster,
+ LastCluster = lastCluster
+ };
}
private int GetTrailingWhitespaceLength(bool isReversed, out int newLineLength, out int glyphCount)
@@ -820,10 +824,11 @@ namespace Avalonia.Media
private IRef CreateGlyphRunImpl()
{
var platformImpl = s_renderInterface.CreateGlyphRun(
- GlyphTypeface,
- FontRenderingEmSize,
- GlyphInfos,
- _baselineOrigin ?? new Point(0, -GlyphTypeface.Metrics.Ascent * Scale));
+ GlyphTypeface,
+ FontRenderingEmSize,
+ GlyphInfos,
+ BaselineOrigin,
+ Bounds);
_platformImpl = RefCountable.Create(platformImpl);
@@ -835,5 +840,16 @@ namespace Avalonia.Media
_platformImpl?.Dispose();
_platformImpl = null;
}
+
+ ///
+ /// Gets the intersections of specified upper and lower limit.
+ ///
+ /// Upper limit.
+ /// Lower limit.
+ ///
+ public IReadOnlyList GetIntersections(float lowerLimit, float upperLimit)
+ {
+ return PlatformImpl.Item.GetIntersections(lowerLimit, upperLimit);
+ }
}
}
diff --git a/src/Avalonia.Base/Media/GlyphRunMetrics.cs b/src/Avalonia.Base/Media/GlyphRunMetrics.cs
index 09b183d044..9ca1d5ea12 100644
--- a/src/Avalonia.Base/Media/GlyphRunMetrics.cs
+++ b/src/Avalonia.Base/Media/GlyphRunMetrics.cs
@@ -2,23 +2,20 @@
{
public readonly record struct GlyphRunMetrics
{
- public GlyphRunMetrics(double width, int trailingWhitespaceLength, int newLineLength, int firstCluster, int lastCluster)
- {
- Width = width;
- TrailingWhitespaceLength = trailingWhitespaceLength;
- NewLineLength = newLineLength;
- FirstCluster = firstCluster;
- LastCluster = lastCluster;
- }
+ public double Baseline { get; init; }
- public double Width { get; }
+ public double Width { get; init; }
- public int TrailingWhitespaceLength { get; }
+ public double WidthIncludingTrailingWhitespace { get; init; }
- public int NewLineLength { get; }
+ public double Height { get; init; }
- public int FirstCluster { get; }
+ public int TrailingWhitespaceLength { get; init; }
- public int LastCluster { get; }
+ public int NewLineLength { get; init; }
+
+ public int FirstCluster { get; init; }
+
+ public int LastCluster { get; init; }
}
}
diff --git a/src/Avalonia.Base/Media/IImage.cs b/src/Avalonia.Base/Media/IImage.cs
index cbe25b7b58..4e0b952b88 100644
--- a/src/Avalonia.Base/Media/IImage.cs
+++ b/src/Avalonia.Base/Media/IImage.cs
@@ -18,11 +18,9 @@ namespace Avalonia.Media
/// The drawing context.
/// The rect in the image to draw.
/// The rect in the output to draw to.
- /// The bitmap interpolation mode.
void Draw(
DrawingContext context,
Rect sourceRect,
- Rect destRect,
- BitmapInterpolationMode bitmapInterpolationMode);
+ Rect destRect);
}
}
diff --git a/src/Avalonia.Base/Media/ITileBrush.cs b/src/Avalonia.Base/Media/ITileBrush.cs
index cb5a591003..586f6053a1 100644
--- a/src/Avalonia.Base/Media/ITileBrush.cs
+++ b/src/Avalonia.Base/Media/ITileBrush.cs
@@ -39,13 +39,5 @@ namespace Avalonia.Media
/// Gets the brush's tile mode.
///
TileMode TileMode { get; }
-
- ///
- /// Gets the bitmap interpolation mode.
- ///
- ///
- /// The bitmap interpolation mode.
- ///
- BitmapInterpolationMode BitmapInterpolationMode { get; }
}
}
diff --git a/src/Avalonia.Base/Media/Imaging/Bitmap.cs b/src/Avalonia.Base/Media/Imaging/Bitmap.cs
index c4720d772e..07bb3db100 100644
--- a/src/Avalonia.Base/Media/Imaging/Bitmap.cs
+++ b/src/Avalonia.Base/Media/Imaging/Bitmap.cs
@@ -224,15 +224,13 @@ namespace Avalonia.Media.Imaging
void IImage.Draw(
DrawingContext context,
Rect sourceRect,
- Rect destRect,
- BitmapInterpolationMode bitmapInterpolationMode)
+ Rect destRect)
{
context.DrawBitmap(
PlatformImpl,
1,
sourceRect,
- destRect,
- bitmapInterpolationMode);
+ destRect);
}
private static IPlatformRenderInterface GetFactory()
diff --git a/src/Avalonia.Base/Media/Imaging/BitmapBlendingMode.cs b/src/Avalonia.Base/Media/Imaging/BitmapBlendingMode.cs
index eb39020939..73a3f7b269 100644
--- a/src/Avalonia.Base/Media/Imaging/BitmapBlendingMode.cs
+++ b/src/Avalonia.Base/Media/Imaging/BitmapBlendingMode.cs
@@ -3,8 +3,10 @@ namespace Avalonia.Media.Imaging
///
/// Controls the way the bitmaps are drawn together.
///
- public enum BitmapBlendingMode
+ public enum BitmapBlendingMode : byte
{
+ Unspecified,
+
///
/// Source is placed over the destination.
///
@@ -52,6 +54,6 @@ namespace Avalonia.Media.Imaging
///
/// Display the sum of the source image and destination image.
///
- Plus,
+ Plus
}
}
diff --git a/src/Avalonia.Base/Media/Imaging/BitmapInterpolationMode.cs b/src/Avalonia.Base/Media/Imaging/BitmapInterpolationMode.cs
index 7cdb5d8b9f..eaa64892a4 100644
--- a/src/Avalonia.Base/Media/Imaging/BitmapInterpolationMode.cs
+++ b/src/Avalonia.Base/Media/Imaging/BitmapInterpolationMode.cs
@@ -3,12 +3,14 @@
///
/// Controls the performance and quality of bitmap scaling.
///
- public enum BitmapInterpolationMode
+ public enum BitmapInterpolationMode : byte
{
+ Unspecified,
+
///
- /// Uses the default behavior of the underling render backend.
+ /// Disable interpolation.
///
- Default,
+ None,
///
/// The best performance but worst image quality.
@@ -18,7 +20,7 @@
///
/// Good performance and decent image quality.
///
- MediumQuality,
+ MediumQuality,
///
/// Highest quality but worst performance.
diff --git a/src/Avalonia.Base/Media/Imaging/CroppedBitmap.cs b/src/Avalonia.Base/Media/Imaging/CroppedBitmap.cs
index 8cdf5b592a..93556679e9 100644
--- a/src/Avalonia.Base/Media/Imaging/CroppedBitmap.cs
+++ b/src/Avalonia.Base/Media/Imaging/CroppedBitmap.cs
@@ -83,12 +83,12 @@ namespace Avalonia.Media.Imaging
}
}
- public void Draw(DrawingContext context, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode)
+ public void Draw(DrawingContext context, Rect sourceRect, Rect destRect)
{
if (Source is not IBitmap bmp)
return;
var topLeft = SourceRect.TopLeft.ToPointWithDpi(bmp.Dpi);
- Source.Draw(context, sourceRect.Translate(new Vector(topLeft.X, topLeft.Y)), destRect, bitmapInterpolationMode);
+ Source.Draw(context, sourceRect.Translate(new Vector(topLeft.X, topLeft.Y)), destRect);
}
}
}
diff --git a/src/Avalonia.Base/Media/ImmediateDrawingContext.cs b/src/Avalonia.Base/Media/ImmediateDrawingContext.cs
index 58b153482d..7ddccc80e7 100644
--- a/src/Avalonia.Base/Media/ImmediateDrawingContext.cs
+++ b/src/Avalonia.Base/Media/ImmediateDrawingContext.cs
@@ -80,11 +80,10 @@ namespace Avalonia.Media
/// The bitmap.
/// The rect in the image to draw.
/// The rect in the output to draw to.
- /// The bitmap interpolation mode.
- public void DrawBitmap(IBitmap source, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode = default)
+ public void DrawBitmap(IBitmap source, Rect sourceRect, Rect destRect)
{
_ = source ?? throw new ArgumentNullException(nameof(source));
- PlatformImpl.DrawBitmap(source.PlatformImpl, 1, sourceRect, destRect, bitmapInterpolationMode);
+ PlatformImpl.DrawBitmap(source.PlatformImpl, 1, sourceRect, destRect);
}
///
diff --git a/src/Avalonia.Base/Media/Immutable/ImmutableImageBrush.cs b/src/Avalonia.Base/Media/Immutable/ImmutableImageBrush.cs
index 668a907fdf..175038ba75 100644
--- a/src/Avalonia.Base/Media/Immutable/ImmutableImageBrush.cs
+++ b/src/Avalonia.Base/Media/Immutable/ImmutableImageBrush.cs
@@ -22,7 +22,6 @@ 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,
@@ -33,8 +32,7 @@ namespace Avalonia.Media.Immutable
RelativePoint transformOrigin = default,
RelativeRect? sourceRect = null,
Stretch stretch = Stretch.Uniform,
- TileMode tileMode = TileMode.None,
- BitmapInterpolationMode bitmapInterpolationMode = BitmapInterpolationMode.Default)
+ TileMode tileMode = TileMode.None)
: base(
alignmentX,
alignmentY,
@@ -44,8 +42,7 @@ namespace Avalonia.Media.Immutable
transformOrigin,
sourceRect ?? RelativeRect.Fill,
stretch,
- tileMode,
- bitmapInterpolationMode)
+ tileMode)
{
Source = source;
}
diff --git a/src/Avalonia.Base/Media/Immutable/ImmutableTileBrush.cs b/src/Avalonia.Base/Media/Immutable/ImmutableTileBrush.cs
index 1ee52365e0..7e139af516 100644
--- a/src/Avalonia.Base/Media/Immutable/ImmutableTileBrush.cs
+++ b/src/Avalonia.Base/Media/Immutable/ImmutableTileBrush.cs
@@ -21,7 +21,6 @@ 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,
@@ -31,8 +30,7 @@ namespace Avalonia.Media.Immutable
RelativePoint transformOrigin,
RelativeRect sourceRect,
Stretch stretch,
- TileMode tileMode,
- BitmapInterpolationMode bitmapInterpolationMode)
+ TileMode tileMode)
{
AlignmentX = alignmentX;
AlignmentY = alignmentY;
@@ -43,7 +41,6 @@ namespace Avalonia.Media.Immutable
SourceRect = sourceRect;
Stretch = stretch;
TileMode = tileMode;
- BitmapInterpolationMode = bitmapInterpolationMode;
}
///
@@ -60,8 +57,7 @@ namespace Avalonia.Media.Immutable
source.TransformOrigin,
source.SourceRect,
source.Stretch,
- source.TileMode,
- source.BitmapInterpolationMode)
+ source.TileMode)
{
}
@@ -95,8 +91,5 @@ namespace Avalonia.Media.Immutable
///
public TileMode TileMode { get; }
-
- ///
- public BitmapInterpolationMode BitmapInterpolationMode { get; }
}
}
diff --git a/src/Avalonia.Base/Media/PlatformDrawingContext.cs b/src/Avalonia.Base/Media/PlatformDrawingContext.cs
index eb8a93722c..63cbb3069b 100644
--- a/src/Avalonia.Base/Media/PlatformDrawingContext.cs
+++ b/src/Avalonia.Base/Media/PlatformDrawingContext.cs
@@ -25,6 +25,12 @@ internal sealed class PlatformDrawingContext : DrawingContext, IDrawingContextWi
_ownsImpl = ownsImpl;
}
+ public RenderOptions RenderOptions
+ {
+ get => _impl.RenderOptions;
+ set => _impl.RenderOptions = value;
+ }
+
protected override void DrawLineCore(IPen pen, Point p1, Point p2) =>
_impl.DrawLine(pen, p1, p2);
@@ -37,9 +43,8 @@ internal sealed class PlatformDrawingContext : DrawingContext, IDrawingContextWi
protected override void DrawEllipseCore(IBrush? brush, IPen? pen, Rect rect) => _impl.DrawEllipse(brush, pen, rect);
- internal override void DrawBitmap(IRef source, double opacity, Rect sourceRect, Rect destRect,
- BitmapInterpolationMode bitmapInterpolationMode = BitmapInterpolationMode.Default) =>
- _impl.DrawBitmap(source, opacity, sourceRect, destRect, bitmapInterpolationMode);
+ internal override void DrawBitmap(IRef source, double opacity, Rect sourceRect, Rect destRect) =>
+ _impl.DrawBitmap(source, opacity, sourceRect, destRect);
public override void Custom(ICustomDrawOperation custom) =>
custom.Render(_impl);
@@ -65,9 +70,6 @@ internal sealed class PlatformDrawingContext : DrawingContext, IDrawingContextWi
protected override void PushOpacityMaskCore(IBrush mask, Rect bounds) =>
_impl.PushOpacityMask(mask, bounds);
- protected override void PushBitmapBlendModeCore(BitmapBlendingMode blendingMode) =>
- _impl.PushBitmapBlendMode(blendingMode);
-
protected override void PushTransformCore(Matrix matrix)
{
_transforms ??= TransformStackPool.Get();
@@ -84,8 +86,6 @@ internal sealed class PlatformDrawingContext : DrawingContext, IDrawingContextWi
protected override void PopOpacityMaskCore() => _impl.PopOpacityMask();
- protected override void PopBitmapBlendModeCore() => _impl.PopBitmapBlendMode();
-
protected override void PopTransformCore() =>
_impl.Transform =
(_transforms ?? throw new ObjectDisposedException(nameof(PlatformDrawingContext))).Pop();
diff --git a/src/Avalonia.Base/Media/RenderOptions.cs b/src/Avalonia.Base/Media/RenderOptions.cs
index 5863d0ac58..639498543b 100644
--- a/src/Avalonia.Base/Media/RenderOptions.cs
+++ b/src/Avalonia.Base/Media/RenderOptions.cs
@@ -1,36 +1,131 @@
using Avalonia.Media.Imaging;
namespace Avalonia.Media
-{
- public class RenderOptions
+{
+ public readonly record struct RenderOptions
{
+ public BitmapInterpolationMode BitmapInterpolationMode { get; init; }
+ public EdgeMode EdgeMode { get; init; }
+ public TextRenderingMode TextRenderingMode { get; init; }
+ public BitmapBlendingMode BitmapBlendingMode { get; init; }
+
+ ///
+ /// Gets the value of the BitmapInterpolationMode attached property for a visual.
+ ///
+ /// The control.
+ /// The control's left coordinate.
+ public static BitmapInterpolationMode GetBitmapInterpolationMode(Visual visual)
+ {
+ return visual.RenderOptions.BitmapInterpolationMode;
+ }
+
///
- /// Defines the property.
+ /// Sets the value of the BitmapInterpolationMode attached property for a visual.
///
- public static readonly StyledProperty BitmapInterpolationModeProperty =
- AvaloniaProperty.RegisterAttached(
- "BitmapInterpolationMode",
- BitmapInterpolationMode.MediumQuality,
- inherits: true);
+ /// The control.
+ /// The left value.
+ public static void SetBitmapInterpolationMode(Visual visual, BitmapInterpolationMode value)
+ {
+ visual.RenderOptions = visual.RenderOptions with { BitmapInterpolationMode = value };
+ }
///
- /// Gets the value of the BitmapInterpolationMode attached property for a control.
+ /// Gets the value of the BitmapBlendingMode attached property for a visual.
///
- /// The control.
+ /// The control.
/// The control's left coordinate.
- public static BitmapInterpolationMode GetBitmapInterpolationMode(AvaloniaObject element)
+ public static BitmapBlendingMode GetBitmapBlendingMode(Visual visual)
{
- return element.GetValue(BitmapInterpolationModeProperty);
+ return visual.RenderOptions.BitmapBlendingMode;
}
///
- /// Sets the value of the BitmapInterpolationMode attached property for a control.
+ /// Sets the value of the BitmapBlendingMode attached property for a visual.
///
- /// The control.
+ /// The control.
/// The left value.
- public static void SetBitmapInterpolationMode(AvaloniaObject element, BitmapInterpolationMode value)
+ public static void SetBitmapBlendingMode(Visual visual, BitmapBlendingMode value)
{
- element.SetValue(BitmapInterpolationModeProperty, value);
+ visual.RenderOptions = visual.RenderOptions with { BitmapBlendingMode = value };
+ }
+
+ ///
+ /// Gets the value of the EdgeMode attached property for a visual.
+ ///
+ /// The control.
+ /// The control's left coordinate.
+ public static EdgeMode GetEdgeMode(Visual visual)
+ {
+ return visual.RenderOptions.EdgeMode;
+ }
+
+ ///
+ /// Sets the value of the EdgeMode attached property for a visual.
+ ///
+ /// The control.
+ /// The left value.
+ public static void SetEdgeMode(Visual visual, EdgeMode value)
+ {
+ visual.RenderOptions = visual.RenderOptions with { EdgeMode = value };
+ }
+
+ ///
+ /// Gets the value of the TextRenderingMode attached property for a visual.
+ ///
+ /// The control.
+ /// The control's left coordinate.
+ public static TextRenderingMode GetTextRenderingMode(Visual visual)
+ {
+ return visual.RenderOptions.TextRenderingMode;
+ }
+
+ ///
+ /// Sets the value of the TextRenderingMode attached property for a visual.
+ ///
+ /// The control.
+ /// The left value.
+ public static void SetTextRenderingMode(Visual visual, TextRenderingMode value)
+ {
+ visual.RenderOptions = visual.RenderOptions with { TextRenderingMode = value };
+ }
+
+ public RenderOptions MergeWith(RenderOptions other)
+ {
+ var bitmapInterpolationMode = BitmapInterpolationMode;
+
+ if (bitmapInterpolationMode == BitmapInterpolationMode.Unspecified)
+ {
+ bitmapInterpolationMode = other.BitmapInterpolationMode;
+ }
+
+ var edgeMode = EdgeMode;
+
+ if (edgeMode == EdgeMode.Unspecified)
+ {
+ edgeMode = other.EdgeMode;
+ }
+
+ var textRenderingMode = TextRenderingMode;
+
+ if (textRenderingMode == TextRenderingMode.Unspecified)
+ {
+ textRenderingMode = other.TextRenderingMode;
+ }
+
+ var bitmapBlendingMode = BitmapBlendingMode;
+
+ if (bitmapBlendingMode == BitmapBlendingMode.Unspecified)
+ {
+ bitmapBlendingMode = other.BitmapBlendingMode;
+ }
+
+ return new RenderOptions
+ {
+ BitmapInterpolationMode = bitmapInterpolationMode,
+ EdgeMode = edgeMode,
+ TextRenderingMode = textRenderingMode,
+ BitmapBlendingMode = bitmapBlendingMode
+ };
}
}
}
diff --git a/src/Avalonia.Base/Media/TextDecoration.cs b/src/Avalonia.Base/Media/TextDecoration.cs
index e89a7d8826..8661959aa6 100644
--- a/src/Avalonia.Base/Media/TextDecoration.cs
+++ b/src/Avalonia.Base/Media/TextDecoration.cs
@@ -1,10 +1,6 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using Avalonia.Collections;
-using Avalonia.Collections.Pooled;
using Avalonia.Media.TextFormatting;
-using Avalonia.Platform;
-using Avalonia.Utilities;
namespace Avalonia.Media
{
@@ -218,7 +214,7 @@ namespace Avalonia.Media
{
var offsetY = glyphRun.BaselineOrigin.Y - origin.Y;
- var intersections = glyphRun.PlatformImpl.Item.GetIntersections((float)(thickness * 0.5d - offsetY), (float)(thickness * 1.5d - offsetY));
+ var intersections = glyphRun.GetIntersections((float)(thickness * 0.5d - offsetY), (float)(thickness * 1.5d - offsetY));
if (intersections.Count > 0)
{
diff --git a/src/Avalonia.Base/Media/TextRenderingMode.cs b/src/Avalonia.Base/Media/TextRenderingMode.cs
new file mode 100644
index 0000000000..927d2bce73
--- /dev/null
+++ b/src/Avalonia.Base/Media/TextRenderingMode.cs
@@ -0,0 +1,11 @@
+namespace Avalonia.Media
+{
+ public enum TextRenderingMode : byte
+ {
+ Unspecified,
+
+ SubpixelAntialias,
+ Antialias,
+ Alias
+ }
+}
diff --git a/src/Avalonia.Base/Media/TileBrush.cs b/src/Avalonia.Base/Media/TileBrush.cs
index ab1ee2d604..d7b818a174 100644
--- a/src/Avalonia.Base/Media/TileBrush.cs
+++ b/src/Avalonia.Base/Media/TileBrush.cs
@@ -83,7 +83,6 @@ namespace Avalonia.Media
SourceRectProperty,
StretchProperty,
TileModeProperty);
- RenderOptions.BitmapInterpolationModeProperty.OverrideDefaultValue(BitmapInterpolationMode.Default);
}
///
@@ -140,17 +139,5 @@ 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.Base/Platform/IDrawingContextImpl.cs b/src/Avalonia.Base/Platform/IDrawingContextImpl.cs
index 1359ad6603..cb28ff8d47 100644
--- a/src/Avalonia.Base/Platform/IDrawingContextImpl.cs
+++ b/src/Avalonia.Base/Platform/IDrawingContextImpl.cs
@@ -2,8 +2,8 @@ using System;
using Avalonia.Media;
using Avalonia.Rendering.SceneGraph;
using Avalonia.Utilities;
-using Avalonia.Media.Imaging;
using Avalonia.Metadata;
+using Avalonia.Media.Imaging;
namespace Avalonia.Platform
{
@@ -13,6 +13,11 @@ namespace Avalonia.Platform
[Unstable]
public interface IDrawingContextImpl : IDisposable
{
+ ///
+ /// Gets or sets the current render options used to control the rendering behavior of drawing operations.
+ ///
+ RenderOptions RenderOptions { get; set; }
+
///
/// Gets or sets the current transform of the drawing context.
///
@@ -31,8 +36,7 @@ namespace Avalonia.Platform
/// The opacity to draw with.
/// The rect in the image to draw.
/// The rect in the output to draw to.
- /// The bitmap interpolation mode.
- void DrawBitmap(IRef source, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode = BitmapInterpolationMode.Default);
+ void DrawBitmap(IRef source, double opacity, Rect sourceRect, Rect destRect);
///
/// Draws a bitmap image.
@@ -157,17 +161,6 @@ namespace Avalonia.Platform
///
void PopGeometryClip();
- ///
- /// Pushes a bitmap blending value.
- ///
- /// The bitmap blending mode.
- void PushBitmapBlendMode(BitmapBlendingMode blendingMode);
-
- ///
- /// Pops the latest pushed bitmap blending value.
- ///
- void PopBitmapBlendMode();
-
///
/// Adds a custom draw operation
///
diff --git a/src/Avalonia.Base/Platform/IGlyphRunBuffer.cs b/src/Avalonia.Base/Platform/IGlyphRunBuffer.cs
deleted file mode 100644
index c1fc7a5967..0000000000
--- a/src/Avalonia.Base/Platform/IGlyphRunBuffer.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using System;
-using System.Drawing;
-
-namespace Avalonia.Platform
-{
- public interface IGlyphRunBuffer
- {
- Span GlyphIndices { get; }
-
- IGlyphRunImpl Build();
- }
-
- public interface IHorizontalGlyphRunBuffer : IGlyphRunBuffer
- {
- Span GlyphPositions { get; }
- }
-
- public interface IPositionedGlyphRunBuffer : IGlyphRunBuffer
- {
- Span GlyphPositions { get; }
- }
-}
diff --git a/src/Avalonia.Base/Platform/IGlyphRunImpl.cs b/src/Avalonia.Base/Platform/IGlyphRunImpl.cs
index fccea27c43..2342f32307 100644
--- a/src/Avalonia.Base/Platform/IGlyphRunImpl.cs
+++ b/src/Avalonia.Base/Platform/IGlyphRunImpl.cs
@@ -1,25 +1,36 @@
using System;
using System.Collections.Generic;
+using Avalonia.Media;
using Avalonia.Metadata;
namespace Avalonia.Platform
{
///
- /// Actual implementation of a glyph run that stores platform dependent resources.
+ /// An immutable platform representation of a .
///
[Unstable]
- public interface IGlyphRunImpl : IDisposable
+ public interface IGlyphRunImpl : IDisposable
{
///
- /// Gets the conservative bounding box of the glyph run./>.
+ /// Gets the for the .
///
- Rect Bounds { get; }
+ IGlyphTypeface GlyphTypeface { get; }
+
+ ///
+ /// Gets the em size used for rendering the .
+ ///
+ double FontRenderingEmSize { get; }
///
/// Gets the baseline origin of the glyph run./>.
///
Point BaselineOrigin { get; }
+ ///
+ /// Gets the conservative bounding box of the glyph run./>.
+ ///
+ Rect Bounds { get; }
+
///
/// Gets the intersections of specified upper and lower limit.
///
diff --git a/src/Avalonia.Base/Platform/IPlatformRenderInterface.cs b/src/Avalonia.Base/Platform/IPlatformRenderInterface.cs
index 81fe2c046f..c37233d52c 100644
--- a/src/Avalonia.Base/Platform/IPlatformRenderInterface.cs
+++ b/src/Avalonia.Base/Platform/IPlatformRenderInterface.cs
@@ -169,8 +169,9 @@ namespace Avalonia.Platform
/// The font rendering em size.
/// The list of glyphs.
/// The baseline origin of the run. Can be null.
+ /// the conservative bounding box of the run
/// An .
- IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList glyphInfos, Point baselineOrigin);
+ IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList glyphInfos, Point baselineOrigin, Rect bounds);
///
/// Creates a backend-specific object using a low-level API graphics context
diff --git a/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs b/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs
index 814ecdba29..1bf52729a0 100644
--- a/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs
+++ b/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs
@@ -260,6 +260,8 @@ public class CompositingRenderer : IRendererWithCompositor
if (!comp.Effect.EffectEquals(visual.Effect))
comp.Effect = visual.Effect?.ToImmutable();
+ comp.RenderOptions = visual.RenderOptions;
+
var renderTransform = Matrix.Identity;
if (visual.HasMirrorTransform)
@@ -272,8 +274,6 @@ public class CompositingRenderer : IRendererWithCompositor
renderTransform *= (-offset) * visual.RenderTransform.Value * (offset);
}
-
-
comp.TransformMatrix = MatrixUtils.ToMatrix4x4(renderTransform);
_recorder.BeginUpdate(comp.DrawList);
diff --git a/src/Avalonia.Base/Rendering/Composition/Drawing/CompositionDrawingContext.cs b/src/Avalonia.Base/Rendering/Composition/Drawing/CompositionDrawingContext.cs
index f81cc5a1a0..ec419e6313 100644
--- a/src/Avalonia.Base/Rendering/Composition/Drawing/CompositionDrawingContext.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Drawing/CompositionDrawingContext.cs
@@ -78,15 +78,14 @@ internal sealed class CompositionDrawingContext : DrawingContext, IDrawingContex
}
}
- internal override void DrawBitmap(IRef source, double opacity, Rect sourceRect, Rect destRect,
- BitmapInterpolationMode bitmapInterpolationMode = BitmapInterpolationMode.Default)
+ internal override void DrawBitmap(IRef source, double opacity, Rect sourceRect, Rect destRect)
{
var next = NextDrawAs();
if (next == null ||
- !next.Item.Equals(Transform, source, opacity, sourceRect, destRect, bitmapInterpolationMode))
+ !next.Item.Equals(Transform, source, opacity, sourceRect, destRect))
{
- Add(new ImageNode(Transform, source, opacity, sourceRect, destRect, bitmapInterpolationMode));
+ Add(new ImageNode(Transform, source, opacity, sourceRect, destRect));
}
else
{
@@ -227,20 +226,6 @@ internal sealed class CompositionDrawingContext : DrawingContext, IDrawingContex
}
}
- protected override void PopBitmapBlendModeCore()
- {
- var next = NextDrawAs();
-
- if (next == null || !next.Item.Equals(null))
- {
- Add(new BitmapBlendModeNode());
- }
- else
- {
- ++_drawOperationIndex;
- }
- }
-
protected override void PopOpacityCore()
{
var next = NextDrawAs();
@@ -354,21 +339,6 @@ internal sealed class CompositionDrawingContext : DrawingContext, IDrawingContex
_needsToPopOpacityMask.Push(needsToPop);
}
- ///
- protected override void PushBitmapBlendModeCore(BitmapBlendingMode blendingMode)
- {
- var next = NextDrawAs();
-
- if (next == null || !next.Item.Equals(blendingMode))
- {
- Add(new BitmapBlendModeNode(blendingMode));
- }
- else
- {
- ++_drawOperationIndex;
- }
- }
-
private void Add(T node) where T : class, IDrawOperation
{
if (_drawOperationIndex < _builder.Count)
diff --git a/src/Avalonia.Base/Rendering/Composition/Server/DrawingContextProxy.cs b/src/Avalonia.Base/Rendering/Composition/Server/DrawingContextProxy.cs
index 1ec1362a4c..cdce741020 100644
--- a/src/Avalonia.Base/Rendering/Composition/Server/DrawingContextProxy.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Server/DrawingContextProxy.cs
@@ -42,15 +42,20 @@ internal class CompositorDrawingContextProxy : IDrawingContextImpl,
set => _impl.Transform = (_transform = value) * PostTransform;
}
+ public RenderOptions RenderOptions
+ {
+ get => _impl.RenderOptions;
+ set => _impl.RenderOptions = value;
+ }
+
public void Clear(Color color)
{
_impl.Clear(color);
}
- public void DrawBitmap(IRef source, double opacity, Rect sourceRect, Rect destRect,
- BitmapInterpolationMode bitmapInterpolationMode = BitmapInterpolationMode.Default)
+ public void DrawBitmap(IRef source, double opacity, Rect sourceRect, Rect destRect)
{
- _impl.DrawBitmap(source, opacity, sourceRect, destRect, bitmapInterpolationMode);
+ _impl.DrawBitmap(source, opacity, sourceRect, destRect);
}
public void DrawBitmap(IRef source, IBrush opacityMask, Rect opacityMaskRect, Rect destRect)
@@ -133,16 +138,6 @@ internal class CompositorDrawingContextProxy : IDrawingContextImpl,
_impl.PopGeometryClip();
}
- public void PushBitmapBlendMode(BitmapBlendingMode blendingMode)
- {
- _impl.PushBitmapBlendMode(blendingMode);
- }
-
- public void PopBitmapBlendMode()
- {
- _impl.PopBitmapBlendMode();
- }
-
public void Custom(ICustomDrawOperation custom)
{
_impl.Custom(custom);
diff --git a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
index 3e88b9e77b..45275bdfe1 100644
--- a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
@@ -181,7 +181,7 @@ namespace Avalonia.Rendering.Composition.Server
else
targetContext.DrawBitmap(RefCountable.CreateUnownedNotClonable(_layer), 1,
new Rect(_layerSize),
- new Rect(Size), BitmapInterpolationMode.LowQuality);
+ new Rect(Size));
if (DebugOverlays != RendererDebugOverlays.None)
{
diff --git a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs
index 6e7ef85183..853b90be5e 100644
--- a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs
@@ -66,6 +66,8 @@ namespace Avalonia.Rendering.Composition.Server
if (OpacityMaskBrush != null)
canvas.PushOpacityMask(OpacityMaskBrush, boundsRect);
+ canvas.RenderOptions = RenderOptions;
+
RenderCore(canvas, currentTransformedClip);
// Hack to force invalidation of SKMatrix
@@ -122,6 +124,11 @@ namespace Avalonia.Rendering.Composition.Server
var wasVisible = IsVisibleInFrame;
+ if(Parent != null)
+ {
+ RenderOptions = RenderOptions.MergeWith(Parent.RenderOptions);
+ }
+
// Calculate new parent-relative transform
if (_combinedTransformDirty)
{
diff --git a/src/Avalonia.Base/Rendering/ImmediateRenderer.cs b/src/Avalonia.Base/Rendering/ImmediateRenderer.cs
index 9b7d358b1d..4e264f6951 100644
--- a/src/Avalonia.Base/Rendering/ImmediateRenderer.cs
+++ b/src/Avalonia.Base/Rendering/ImmediateRenderer.cs
@@ -97,7 +97,18 @@ namespace Avalonia.Rendering
using (visual.OpacityMask != null ? context.PushOpacityMask(visual.OpacityMask, bounds) : default)
using (context.PushTransform(Matrix.Identity))
{
- visual.Render(context);
+ var currentRenderOptions = default(RenderOptions);
+
+ var platformContext = context as PlatformDrawingContext;
+
+ if(platformContext != null)
+ {
+ currentRenderOptions = platformContext.RenderOptions;
+
+ platformContext.RenderOptions = visual.RenderOptions.MergeWith(platformContext.RenderOptions);
+ }
+
+ visual.Render(context);
var childrenEnumerable = visual.HasNonUniformZIndexChildren
? visual.VisualChildren.OrderBy(x => x, ZIndexComparer.Instance)
@@ -115,6 +126,11 @@ namespace Avalonia.Rendering
Render(context, child, childClipRect);
}
}
+
+ if(platformContext != null)
+ {
+ platformContext.RenderOptions = currentRenderOptions;
+ }
}
}
}
diff --git a/src/Avalonia.Base/Rendering/SceneGraph/BitmapBlendModeNode.cs b/src/Avalonia.Base/Rendering/SceneGraph/BitmapBlendModeNode.cs
deleted file mode 100644
index b1190a159b..0000000000
--- a/src/Avalonia.Base/Rendering/SceneGraph/BitmapBlendModeNode.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-using Avalonia.Platform;
-using Avalonia.Media.Imaging;
-
-namespace Avalonia.Rendering.SceneGraph
-{
- ///
- /// A node in the scene graph which represents an bitmap blending mode push or pop.
- ///
- internal class BitmapBlendModeNode : IDrawOperation
- {
- ///
- /// Initializes a new instance of the class that represents an
- /// push.
- ///
- /// The to push.
- public BitmapBlendModeNode(BitmapBlendingMode bitmapBlend)
- {
- BlendingMode = bitmapBlend;
- }
-
- ///
- /// Initializes a new instance of the class that represents an
- /// pop.
- ///
- public BitmapBlendModeNode()
- {
- }
-
- ///
- public Rect Bounds => default;
-
- ///
- /// Gets the BitmapBlend to be pushed or null if the operation represents a pop.
- ///
- public BitmapBlendingMode? BlendingMode { get; }
-
- ///
- public bool HitTest(Point p) => false;
-
- ///
- /// Determines if this draw operation equals another.
- ///
- /// the how to compare
- /// 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(BitmapBlendingMode? blendingMode) => BlendingMode == blendingMode;
-
- ///
- public void Render(IDrawingContextImpl context)
- {
- if (BlendingMode.HasValue)
- {
- context.PushBitmapBlendMode(BlendingMode.Value);
- }
- else
- {
- context.PopBitmapBlendMode();
- }
- }
-
- public void Dispose()
- {
- }
- }
-}
diff --git a/src/Avalonia.Base/Rendering/SceneGraph/GlyphRunNode.cs b/src/Avalonia.Base/Rendering/SceneGraph/GlyphRunNode.cs
index 1c4e63b34a..764c5c65f9 100644
--- a/src/Avalonia.Base/Rendering/SceneGraph/GlyphRunNode.cs
+++ b/src/Avalonia.Base/Rendering/SceneGraph/GlyphRunNode.cs
@@ -1,5 +1,4 @@
-using System;
-using Avalonia.Media;
+using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Utilities;
@@ -18,7 +17,7 @@ namespace Avalonia.Rendering.SceneGraph
/// The glyph run to draw.
public GlyphRunNode(
Matrix transform,
- IImmutableBrush foreground,
+ IImmutableBrush? foreground,
IRef glyphRun)
: base(glyphRun.Item.Bounds, transform, foreground)
{
diff --git a/src/Avalonia.Base/Rendering/SceneGraph/ImageNode.cs b/src/Avalonia.Base/Rendering/SceneGraph/ImageNode.cs
index ac946cc8b2..caf0eee175 100644
--- a/src/Avalonia.Base/Rendering/SceneGraph/ImageNode.cs
+++ b/src/Avalonia.Base/Rendering/SceneGraph/ImageNode.cs
@@ -1,6 +1,5 @@
using Avalonia.Platform;
using Avalonia.Utilities;
-using Avalonia.Media.Imaging;
namespace Avalonia.Rendering.SceneGraph
{
@@ -17,15 +16,13 @@ namespace Avalonia.Rendering.SceneGraph
/// The draw opacity.
/// The source rect.
/// The destination rect.
- /// The bitmap interpolation mode.
- public ImageNode(Matrix transform, IRef source, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode)
+ public ImageNode(Matrix transform, IRef source, double opacity, Rect sourceRect, Rect destRect)
: base(destRect, transform)
{
Source = source.Clone();
Opacity = opacity;
SourceRect = sourceRect;
DestRect = destRect;
- BitmapInterpolationMode = bitmapInterpolationMode;
SourceVersion = Source.Item.Version;
}
@@ -53,14 +50,6 @@ namespace Avalonia.Rendering.SceneGraph
/// Gets the destination rect.
///
public Rect DestRect { get; }
-
- ///
- /// Gets the bitmap interpolation mode.
- ///
- ///
- /// The scaling mode.
- ///
- public BitmapInterpolationMode BitmapInterpolationMode { get; }
///
/// Determines if this draw operation equals another.
@@ -70,27 +59,25 @@ 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, BitmapInterpolationMode bitmapInterpolationMode)
+ public bool Equals(Matrix transform, IRef source, double opacity, Rect sourceRect, Rect destRect)
{
return transform == Transform &&
Equals(source.Item, Source.Item) &&
source.Item.Version == SourceVersion &&
opacity == Opacity &&
sourceRect == SourceRect &&
- destRect == DestRect &&
- bitmapInterpolationMode == BitmapInterpolationMode;
+ destRect == DestRect;
}
///
public override void Render(IDrawingContextImpl context)
{
- context.DrawBitmap(Source, Opacity, SourceRect, DestRect, BitmapInterpolationMode);
+ context.DrawBitmap(Source, Opacity, SourceRect, DestRect);
}
///
diff --git a/src/Avalonia.Base/Visual.cs b/src/Avalonia.Base/Visual.cs
index 79cc760fc6..e626dc5249 100644
--- a/src/Avalonia.Base/Visual.cs
+++ b/src/Avalonia.Base/Visual.cs
@@ -318,7 +318,9 @@ namespace Avalonia
internal CompositionDrawListVisual? CompositionVisual { get; private set; }
internal CompositionVisual? ChildCompositionVisual { get; set; }
-
+
+ internal RenderOptions RenderOptions { get; set; }
+
public bool HasNonUniformZIndexChildren { get; private set; }
///
diff --git a/src/Avalonia.Base/composition-schema.xml b/src/Avalonia.Base/composition-schema.xml
index 91d718dfd8..a24c249eed 100644
--- a/src/Avalonia.Base/composition-schema.xml
+++ b/src/Avalonia.Base/composition-schema.xml
@@ -30,6 +30,7 @@
+
internal class D2DBitmapImpl : BitmapImpl
{
- private readonly Bitmap _direct2DBitmap;
+ private readonly Bitmap1 _direct2DBitmap;
///
/// Initialize a new instance of the class
@@ -22,7 +23,7 @@ namespace Avalonia.Direct2D1.Media
/// or if the render target is a ,
/// the device associated with this context, to be renderable.
///
- public D2DBitmapImpl(Bitmap d2DBitmap)
+ public D2DBitmapImpl(Bitmap1 d2DBitmap)
{
_direct2DBitmap = d2DBitmap ?? throw new ArgumentNullException(nameof(d2DBitmap));
}
@@ -36,9 +37,9 @@ namespace Avalonia.Direct2D1.Media
_direct2DBitmap.Dispose();
}
- public override OptionalDispose GetDirect2DBitmap(SharpDX.Direct2D1.RenderTarget target)
+ public override OptionalDispose GetDirect2DBitmap(SharpDX.Direct2D1.RenderTarget target)
{
- return new OptionalDispose(_direct2DBitmap, false);
+ return new OptionalDispose(_direct2DBitmap, false);
}
public override void Save(Stream stream, int? quality = null)
diff --git a/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs
index 6b1ca911fb..2a3bf617f7 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs
@@ -5,7 +5,7 @@ using Avalonia.Rendering;
using Avalonia.Utilities;
using SharpDX;
using SharpDX.Direct2D1;
-using D2DBitmap = SharpDX.Direct2D1.Bitmap;
+using D2DBitmap = SharpDX.Direct2D1.Bitmap1;
namespace Avalonia.Direct2D1.Media.Imaging
{
@@ -14,7 +14,7 @@ namespace Avalonia.Direct2D1.Media.Imaging
private readonly BitmapRenderTarget _renderTarget;
public D2DRenderTargetBitmapImpl(BitmapRenderTarget renderTarget)
- : base(renderTarget.Bitmap)
+ : base(renderTarget.Bitmap.QueryInterface())
{
_renderTarget = renderTarget;
}
@@ -53,7 +53,7 @@ namespace Avalonia.Direct2D1.Media.Imaging
public override OptionalDispose GetDirect2DBitmap(SharpDX.Direct2D1.RenderTarget target)
{
- return new OptionalDispose(_renderTarget.Bitmap, false);
+ return new OptionalDispose(_renderTarget.Bitmap.QueryInterface(), false);
}
public override void Save(Stream stream, int? quality = null)
diff --git a/src/Windows/Avalonia.Direct2D1/Media/Imaging/WicBitmapImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/Imaging/WicBitmapImpl.cs
index 533a29f68c..2fa1e5bd7a 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/Imaging/WicBitmapImpl.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/Imaging/WicBitmapImpl.cs
@@ -1,11 +1,10 @@
using System;
using System.IO;
-using Avalonia.Direct2D1.Media.Imaging;
using Avalonia.Win32.Interop;
using SharpDX.WIC;
using APixelFormat = Avalonia.Platform.PixelFormat;
using AlphaFormat = Avalonia.Platform.AlphaFormat;
-using D2DBitmap = SharpDX.Direct2D1.Bitmap;
+using D2DBitmap = SharpDX.Direct2D1.Bitmap1;
using Avalonia.Platform;
using PixelFormat = SharpDX.WIC.PixelFormat;
@@ -22,7 +21,7 @@ namespace Avalonia.Direct2D1.Media
{
switch (interpolationMode)
{
- case Avalonia.Media.Imaging.BitmapInterpolationMode.Default:
+ case Avalonia.Media.Imaging.BitmapInterpolationMode.Unspecified:
return BitmapInterpolationMode.Fant;
case Avalonia.Media.Imaging.BitmapInterpolationMode.LowQuality:
@@ -184,7 +183,10 @@ namespace Avalonia.Direct2D1.Media
{
using var converter = new FormatConverter(Direct2D1Platform.ImagingFactory);
converter.Initialize(WicImpl, SharpDX.WIC.PixelFormat.Format32bppPBGRA);
- return new OptionalDispose(D2DBitmap.FromWicBitmap(renderTarget, converter), true);
+
+ var d2dBitmap = D2DBitmap.FromWicBitmap(renderTarget, converter).QueryInterface();
+
+ return new OptionalDispose(d2dBitmap, true);
}
public override void Save(Stream stream, int? quality = null)
diff --git a/tests/Avalonia.Base.UnitTests/Rendering/SceneGraph/DrawOperationTests.cs b/tests/Avalonia.Base.UnitTests/Rendering/SceneGraph/DrawOperationTests.cs
index 34878bd08d..86f461673e 100644
--- a/tests/Avalonia.Base.UnitTests/Rendering/SceneGraph/DrawOperationTests.cs
+++ b/tests/Avalonia.Base.UnitTests/Rendering/SceneGraph/DrawOperationTests.cs
@@ -51,8 +51,7 @@ namespace Avalonia.Base.UnitTests.Rendering.SceneGraph
bitmap,
1,
new Rect(1, 1, 1, 1),
- new Rect(1, 1, 1, 1),
- BitmapInterpolationMode.Default);
+ new Rect(1, 1, 1, 1));
Assert.Equal(2, bitmap.RefCount);
diff --git a/tests/Avalonia.Base.UnitTests/VisualTree/MockRenderInterface.cs b/tests/Avalonia.Base.UnitTests/VisualTree/MockRenderInterface.cs
index d494c47a55..37adb03628 100644
--- a/tests/Avalonia.Base.UnitTests/VisualTree/MockRenderInterface.cs
+++ b/tests/Avalonia.Base.UnitTests/VisualTree/MockRenderInterface.cs
@@ -78,7 +78,7 @@ namespace Avalonia.Base.UnitTests.VisualTree
}
public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize,
- IReadOnlyList glyphInfos, Point baselineOrigin)
+ IReadOnlyList glyphInfos, Point baselineOrigin, Rect bounds)
{
throw new NotImplementedException();
}
diff --git a/tests/Avalonia.Benchmarks/NullDrawingContextImpl.cs b/tests/Avalonia.Benchmarks/NullDrawingContextImpl.cs
index 40d504a0ac..3513843367 100644
--- a/tests/Avalonia.Benchmarks/NullDrawingContextImpl.cs
+++ b/tests/Avalonia.Benchmarks/NullDrawingContextImpl.cs
@@ -15,12 +15,13 @@ namespace Avalonia.Benchmarks
public Matrix Transform { get; set; }
+ public RenderOptions RenderOptions { get; set; }
+
public void Clear(Color color)
{
}
- public void DrawBitmap(IRef source, double opacity, Rect sourceRect, Rect destRect,
- BitmapInterpolationMode bitmapInterpolationMode = BitmapInterpolationMode.Default)
+ public void DrawBitmap(IRef source, double opacity, Rect sourceRect, Rect destRect)
{
}
diff --git a/tests/Avalonia.Benchmarks/NullGlyphRun.cs b/tests/Avalonia.Benchmarks/NullGlyphRun.cs
deleted file mode 100644
index 5b584f302d..0000000000
--- a/tests/Avalonia.Benchmarks/NullGlyphRun.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System.Collections.Generic;
-using Avalonia.Platform;
-
-namespace Avalonia.Benchmarks
-{
- internal class NullGlyphRun : IGlyphRunImpl
- {
- public Rect Bounds => default;
-
- public Point BaselineOrigin => default;
-
- public void Dispose()
- {
- }
-
- public IReadOnlyList GetIntersections(float lowerBound, float upperBound)
- {
- return null;
- }
- }
-}
diff --git a/tests/Avalonia.Benchmarks/NullRenderingPlatform.cs b/tests/Avalonia.Benchmarks/NullRenderingPlatform.cs
index d40abd9f47..55cd9e8d4b 100644
--- a/tests/Avalonia.Benchmarks/NullRenderingPlatform.cs
+++ b/tests/Avalonia.Benchmarks/NullRenderingPlatform.cs
@@ -124,9 +124,9 @@ namespace Avalonia.Benchmarks
}
public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize,
- IReadOnlyList glyphInfos, Point baselineOrigin)
+ IReadOnlyList glyphInfos, Point baselineOrigin, Rect bounds)
{
- return new MockGlyphRun(glyphInfos);
+ return new MockGlyphRun(glyphTypeface, fontRenderingEmSize, baselineOrigin, bounds);
}
public IPlatformRenderInterfaceContext CreateBackendContext(IPlatformGraphicsContext graphicsContext)
diff --git a/tests/Avalonia.RenderTests/Media/GlyphRunTests.cs b/tests/Avalonia.RenderTests/Media/GlyphRunTests.cs
index 772d6e1023..1b5083924a 100644
--- a/tests/Avalonia.RenderTests/Media/GlyphRunTests.cs
+++ b/tests/Avalonia.RenderTests/Media/GlyphRunTests.cs
@@ -111,6 +111,29 @@ namespace Avalonia.Direct2D1.RenderTests.Media
CompareImages();
}
+ [Win32Fact("For consistent results")]
+ public async Task Should_Render_GlyphRun_Aliased()
+ {
+ var control = new PositionedGlyphRunControl
+ {
+ [TextElement.ForegroundProperty] = new SolidColorBrush { Color = Colors.Black }
+ };
+
+ RenderOptions.SetTextRenderingMode(control, TextRenderingMode.Alias);
+
+ Decorator target = new Decorator
+ {
+ Padding = new Thickness(8),
+ Width = 190,
+ Height = 120,
+ Child = control
+ };
+
+ await RenderToFile(target);
+
+ CompareImages();
+ }
+
public class GlyphRunGeometryControl : Control
{
public GlyphRunGeometryControl()
diff --git a/tests/Avalonia.RenderTests/Shapes/EllipseTests.cs b/tests/Avalonia.RenderTests/Shapes/EllipseTests.cs
index 43f15e0fad..0851760987 100644
--- a/tests/Avalonia.RenderTests/Shapes/EllipseTests.cs
+++ b/tests/Avalonia.RenderTests/Shapes/EllipseTests.cs
@@ -35,5 +35,49 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes
await RenderToFile(target);
CompareImages();
}
+
+ [Fact]
+ public async Task Should_Render_Circle_Aliased()
+ {
+ var target = new Border
+ {
+ Background = Brushes.White,
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Ellipse
+ {
+ Stroke = Brushes.Black,
+ StrokeThickness = 3.5,
+ }
+ };
+
+ RenderOptions.SetEdgeMode(target, EdgeMode.Aliased);
+
+ await RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public async Task Should_Render_Circle_Antialiased()
+ {
+ var target = new Border
+ {
+ Background = Brushes.White,
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 200,
+ Child = new Ellipse
+ {
+ Stroke = Brushes.Black,
+ StrokeThickness = 3.5,
+ }
+ };
+
+ RenderOptions.SetEdgeMode(target, EdgeMode.Antialias);
+
+ await RenderToFile(target);
+ CompareImages();
+ }
}
}
diff --git a/tests/Avalonia.UnitTests/MockGlyphRun.cs b/tests/Avalonia.UnitTests/MockGlyphRun.cs
index 4561d3b3f2..805c0b6a8a 100644
--- a/tests/Avalonia.UnitTests/MockGlyphRun.cs
+++ b/tests/Avalonia.UnitTests/MockGlyphRun.cs
@@ -1,33 +1,34 @@
using System;
using System.Collections.Generic;
-using Avalonia.Media.TextFormatting;
+using Avalonia.Media;
using Avalonia.Platform;
namespace Avalonia.UnitTests
{
public class MockGlyphRun : IGlyphRunImpl
{
- public MockGlyphRun(IReadOnlyList glyphInfos)
+ public MockGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, Point baselineOrigin, Rect bounds)
{
- var width = 0.0;
+ GlyphTypeface = glyphTypeface;
+ FontRenderingEmSize = fontRenderingEmSize;
+ BaselineOrigin = baselineOrigin;
+ Bounds =bounds;
+ }
- for (var i = 0; i < glyphInfos.Count; ++i)
- {
- width += glyphInfos[i].GlyphAdvance;
- }
+ public IGlyphTypeface GlyphTypeface { get; }
- Bounds = new Rect(new Size(width, 10));
- }
+ public double FontRenderingEmSize { get; }
- public Rect Bounds { get; }
+ public Point BaselineOrigin { get; }
- public Point BaselineOrigin => new Point(0, 8);
+ public Rect Bounds { get; }
public void Dispose()
{
+
}
- public IReadOnlyList GetIntersections(float lowerBound, float upperBound)
+ public IReadOnlyList GetIntersections(float lowerLimit, float upperLimit)
=> Array.Empty();
}
}
diff --git a/tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs b/tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs
index 720755f2b0..8647461c0e 100644
--- a/tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs
+++ b/tests/Avalonia.UnitTests/MockPlatformRenderInterface.cs
@@ -5,7 +5,6 @@ using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Media.Imaging;
using Avalonia.Media.TextFormatting;
-using Avalonia.Rendering;
using Moq;
namespace Avalonia.UnitTests
@@ -149,10 +148,9 @@ namespace Avalonia.UnitTests
throw new NotImplementedException();
}
- public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize,
- IReadOnlyList glyphInfos, Point baselineOrigin)
+ public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList glyphInfos, Point baselineOrigin, Rect bounds)
{
- return new MockGlyphRun(glyphInfos);
+ return new MockGlyphRun(glyphTypeface, fontRenderingEmSize, baselineOrigin, bounds);
}
public IPlatformRenderInterfaceContext CreateBackendContext(IPlatformGraphicsContext graphicsContext) => this;
@@ -162,21 +160,6 @@ namespace Avalonia.UnitTests
return Mock.Of();
}
- public IGlyphRunBuffer AllocateGlyphRun(IGlyphTypeface glyphTypeface, float fontRenderingEmSize, int length)
- {
- return Mock.Of();
- }
-
- public IHorizontalGlyphRunBuffer AllocateHorizontalGlyphRun(IGlyphTypeface glyphTypeface, float fontRenderingEmSize, int length)
- {
- return Mock.Of();
- }
-
- public IPositionedGlyphRunBuffer AllocatePositionedGlyphRun(IGlyphTypeface glyphTypeface, float fontRenderingEmSize, int length)
- {
- return Mock.Of();
- }
-
public bool SupportsIndividualRoundRects { get; set; }
public AlphaFormat DefaultAlphaFormat => AlphaFormat.Premul;
diff --git a/tests/TestFiles/Direct2D1/Media/GlyphRun/Should_Render_GlyphRun_Aliased.expected.png b/tests/TestFiles/Direct2D1/Media/GlyphRun/Should_Render_GlyphRun_Aliased.expected.png
new file mode 100644
index 0000000000..f130809067
Binary files /dev/null and b/tests/TestFiles/Direct2D1/Media/GlyphRun/Should_Render_GlyphRun_Aliased.expected.png differ
diff --git a/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Fill_NoTile.expected.png b/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Fill_NoTile.expected.png
index 73d147bf77..1864f8b214 100644
Binary files a/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Fill_NoTile.expected.png and b/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Fill_NoTile.expected.png differ
diff --git a/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Tile_Fill.expected.png b/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Tile_Fill.expected.png
index c38dcfbcfd..7d54539814 100644
Binary files a/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Tile_Fill.expected.png and b/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Tile_Fill.expected.png differ
diff --git a/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Tile_UniformToFill.expected.png b/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Tile_UniformToFill.expected.png
index 23fc402cd8..8d5c3181f7 100644
Binary files a/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Tile_UniformToFill.expected.png and b/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Tile_UniformToFill.expected.png differ
diff --git a/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_UniformToFill_NoTile.expected.png b/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_UniformToFill_NoTile.expected.png
index e173fa6cee..7c1287d245 100644
Binary files a/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_UniformToFill_NoTile.expected.png and b/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_UniformToFill_NoTile.expected.png differ
diff --git a/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Uniform_NoTile.expected.png b/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Uniform_NoTile.expected.png
index de73af8170..b06a6508fe 100644
Binary files a/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Uniform_NoTile.expected.png and b/tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Uniform_NoTile.expected.png differ
diff --git a/tests/TestFiles/Direct2D1/Media/ImageDrawing/ImageDrawing_Fill.expected.png b/tests/TestFiles/Direct2D1/Media/ImageDrawing/ImageDrawing_Fill.expected.png
index acc8532ff9..8404ce831a 100644
Binary files a/tests/TestFiles/Direct2D1/Media/ImageDrawing/ImageDrawing_Fill.expected.png and b/tests/TestFiles/Direct2D1/Media/ImageDrawing/ImageDrawing_Fill.expected.png differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Fill_NoTile.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Fill_NoTile.expected.png
index 110b44a4c0..86d5e7ccef 100644
Binary files a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Fill_NoTile.expected.png and b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Fill_NoTile.expected.png differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Grip_144_Dpi.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Grip_144_Dpi.expected.png
index 1900ade5e2..28370f3bce 100644
Binary files a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Grip_144_Dpi.expected.png and b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Grip_144_Dpi.expected.png differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_UniformToFill_NoTile.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_UniformToFill_NoTile.expected.png
index 2d7ccac2f7..c1898766aa 100644
Binary files a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_UniformToFill_NoTile.expected.png and b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_UniformToFill_NoTile.expected.png differ
diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Uniform_NoTile.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Uniform_NoTile.expected.png
index d9c62a72a8..6840093b98 100644
Binary files a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Uniform_NoTile.expected.png and b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Uniform_NoTile.expected.png differ
diff --git a/tests/TestFiles/Direct2D1/Shapes/Ellipse/Should_Render_Circle_Aliased.expected.png b/tests/TestFiles/Direct2D1/Shapes/Ellipse/Should_Render_Circle_Aliased.expected.png
new file mode 100644
index 0000000000..d051696d78
Binary files /dev/null and b/tests/TestFiles/Direct2D1/Shapes/Ellipse/Should_Render_Circle_Aliased.expected.png differ
diff --git a/tests/TestFiles/Direct2D1/Shapes/Ellipse/Should_Render_Circle_Antialiased.expected.png b/tests/TestFiles/Direct2D1/Shapes/Ellipse/Should_Render_Circle_Antialiased.expected.png
new file mode 100644
index 0000000000..06dc7f5450
Binary files /dev/null and b/tests/TestFiles/Direct2D1/Shapes/Ellipse/Should_Render_Circle_Antialiased.expected.png differ
diff --git a/tests/TestFiles/Skia/Media/GlyphRun/Should_Render_GlyphRun_Aliased.expected.png b/tests/TestFiles/Skia/Media/GlyphRun/Should_Render_GlyphRun_Aliased.expected.png
new file mode 100644
index 0000000000..0075bfcd3a
Binary files /dev/null and b/tests/TestFiles/Skia/Media/GlyphRun/Should_Render_GlyphRun_Aliased.expected.png differ
diff --git a/tests/TestFiles/Skia/Shapes/Ellipse/Should_Render_Circle_Aliased.expected.png b/tests/TestFiles/Skia/Shapes/Ellipse/Should_Render_Circle_Aliased.expected.png
new file mode 100644
index 0000000000..c8b579f821
Binary files /dev/null and b/tests/TestFiles/Skia/Shapes/Ellipse/Should_Render_Circle_Aliased.expected.png differ
diff --git a/tests/TestFiles/Skia/Shapes/Ellipse/Should_Render_Circle_Antialiased.expected.png b/tests/TestFiles/Skia/Shapes/Ellipse/Should_Render_Circle_Antialiased.expected.png
new file mode 100644
index 0000000000..30df84a194
Binary files /dev/null and b/tests/TestFiles/Skia/Shapes/Ellipse/Should_Render_Circle_Antialiased.expected.png differ