diff --git a/Avalonia.sln b/Avalonia.sln
index ee3bc05f0e..16de32d661 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -262,9 +262,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SafeAreaDemo.iOS", "samples
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Headless", "Headless", "{FF237916-7150-496B-89ED-6CA3292896E7}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Headless.XUnit", "src\Headless\Avalonia.Headless.XUnit\Avalonia.Headless.XUnit.csproj", "{F47F8316-4D4B-4026-8EF3-16B2CFDA8119}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Headless.XUnit", "src\Headless\Avalonia.Headless.XUnit\Avalonia.Headless.XUnit.csproj", "{F47F8316-4D4B-4026-8EF3-16B2CFDA8119}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Headless.UnitTests", "tests\Avalonia.Headless.UnitTests\Avalonia.Headless.UnitTests.csproj", "{3B2405E8-9E7A-46D1-8E2D-EF9ED124C9F2}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Headless.UnitTests", "tests\Avalonia.Headless.UnitTests\Avalonia.Headless.UnitTests.csproj", "{3B2405E8-9E7A-46D1-8E2D-EF9ED124C9F2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -605,14 +605,6 @@ Global
{13F1135D-BA1A-435C-9C5B-A368D1D63DE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{13F1135D-BA1A-435C-9C5B-A368D1D63DE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{13F1135D-BA1A-435C-9C5B-A368D1D63DE4}.Release|Any CPU.Build.0 = Release|Any CPU
- {F47F8316-4D4B-4026-8EF3-16B2CFDA8119}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {F47F8316-4D4B-4026-8EF3-16B2CFDA8119}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F47F8316-4D4B-4026-8EF3-16B2CFDA8119}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {F47F8316-4D4B-4026-8EF3-16B2CFDA8119}.Release|Any CPU.Build.0 = Release|Any CPU
- {3B2405E8-9E7A-46D1-8E2D-EF9ED124C9F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {3B2405E8-9E7A-46D1-8E2D-EF9ED124C9F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {3B2405E8-9E7A-46D1-8E2D-EF9ED124C9F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {3B2405E8-9E7A-46D1-8E2D-EF9ED124C9F2}.Release|Any CPU.Build.0 = Release|Any CPU
{A82AD1BC-EBE6-4FC3-A13B-D52A50297533}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A82AD1BC-EBE6-4FC3-A13B-D52A50297533}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A82AD1BC-EBE6-4FC3-A13B-D52A50297533}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -637,6 +629,14 @@ Global
{FC956F9A-4C3A-4A1A-ACDD-BB54DCB661DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC956F9A-4C3A-4A1A-ACDD-BB54DCB661DD}.Release|Any CPU.Build.0 = Release|Any CPU
{FC956F9A-4C3A-4A1A-ACDD-BB54DCB661DD}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {F47F8316-4D4B-4026-8EF3-16B2CFDA8119}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F47F8316-4D4B-4026-8EF3-16B2CFDA8119}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F47F8316-4D4B-4026-8EF3-16B2CFDA8119}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F47F8316-4D4B-4026-8EF3-16B2CFDA8119}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3B2405E8-9E7A-46D1-8E2D-EF9ED124C9F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3B2405E8-9E7A-46D1-8E2D-EF9ED124C9F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3B2405E8-9E7A-46D1-8E2D-EF9ED124C9F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3B2405E8-9E7A-46D1-8E2D-EF9ED124C9F2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -681,6 +681,8 @@ Global
{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{351337F5-D66F-461B-A957-4EF60BDB4BA6} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
+ {8C89950F-F5D9-47FC-8066-CBC1EC3DF8FC} = {FF237916-7150-496B-89ED-6CA3292896E7}
+ {B859AE7C-F34F-4A9E-88AE-E0E7229FDE1E} = {FF237916-7150-496B-89ED-6CA3292896E7}
{909A8CBD-7D0E-42FD-B841-022AD8925820} = {8B6A8209-894F-4BA1-B880-965FD453982C}
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{BC594FD5-4AF2-409E-A1E6-04123F54D7C5} = {9B9E3891-2366-4253-A952-D08BCEB71098}
@@ -704,10 +706,6 @@ Global
{C810060E-3809-4B74-A125-F11533AF9C1B} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{C692FE73-43DB-49CE-87FC-F03ED61F25C9} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{F4E36AA8-814E-4704-BC07-291F70F45193} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
- {8C89950F-F5D9-47FC-8066-CBC1EC3DF8FC} = {FF237916-7150-496B-89ED-6CA3292896E7}
- {B859AE7C-F34F-4A9E-88AE-E0E7229FDE1E} = {FF237916-7150-496B-89ED-6CA3292896E7}
- {F47F8316-4D4B-4026-8EF3-16B2CFDA8119} = {FF237916-7150-496B-89ED-6CA3292896E7}
- {3B2405E8-9E7A-46D1-8E2D-EF9ED124C9F2} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{DDA28789-C21A-4654-86CE-D01E81F095C5} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{2D7C812B-7E73-4252-8EFD-BC8A4D5CCB9F} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{A82AD1BC-EBE6-4FC3-A13B-D52A50297533} = {9B9E3891-2366-4253-A952-D08BCEB71098}
@@ -715,6 +713,8 @@ Global
{22E3BC08-EAF7-4889-BDC4-B4D3046C4E2D} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{4CDAD037-34A2-4CCF-A03A-C6C7B988A572} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{FC956F9A-4C3A-4A1A-ACDD-BB54DCB661DD} = {9B9E3891-2366-4253-A952-D08BCEB71098}
+ {F47F8316-4D4B-4026-8EF3-16B2CFDA8119} = {FF237916-7150-496B-89ED-6CA3292896E7}
+ {3B2405E8-9E7A-46D1-8E2D-EF9ED124C9F2} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}
diff --git a/samples/ControlCatalog/Pages/ComboBoxPage.xaml b/samples/ControlCatalog/Pages/ComboBoxPage.xaml
index 748a46c447..f3f6cfe0af 100644
--- a/samples/ControlCatalog/Pages/ComboBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/ComboBoxPage.xaml
@@ -98,6 +98,21 @@
Inline Item 3
Inline Item 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
WrapSelection
diff --git a/samples/ControlCatalog/ViewModels/ComboBoxPageViewModel.cs b/samples/ControlCatalog/ViewModels/ComboBoxPageViewModel.cs
index d3e4ea7c31..6ab7bb02e3 100644
--- a/samples/ControlCatalog/ViewModels/ComboBoxPageViewModel.cs
+++ b/samples/ControlCatalog/ViewModels/ComboBoxPageViewModel.cs
@@ -16,5 +16,20 @@ namespace ControlCatalog.ViewModels
get => _wrapSelection;
set => this.RaiseAndSetIfChanged(ref _wrapSelection, value);
}
+
+ public ObservableCollection Values { get; set; } = new ObservableCollection
+ {
+ new IdAndName(){ Id = "Id 1", Name = "Name 1" },
+ new IdAndName(){ Id = "Id 2", Name = "Name 2" },
+ new IdAndName(){ Id = "Id 3", Name = "Name 3" },
+ new IdAndName(){ Id = "Id 4", Name = "Name 4" },
+ new IdAndName(){ Id = "Id 5", Name = "Name 5" },
+ };
+ }
+
+ public class IdAndName
+ {
+ public string Id { get; set; }
+ public string Name { get; set; }
}
}
diff --git a/samples/Sandbox/MainWindow.axaml.cs b/samples/Sandbox/MainWindow.axaml.cs
index b8e9f0ff42..e3dda25b29 100644
--- a/samples/Sandbox/MainWindow.axaml.cs
+++ b/samples/Sandbox/MainWindow.axaml.cs
@@ -1,6 +1,7 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
+using Avalonia.Input.TextInput;
using Avalonia.Markup.Xaml;
using Avalonia.Win32.WinRT.Composition;
diff --git a/src/Avalonia.Base/Data/Core/Plugins/DataAnnotationsValidationPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/DataAnnotationsValidationPlugin.cs
index ba5f59ea23..bc300386b9 100644
--- a/src/Avalonia.Base/Data/Core/Plugins/DataAnnotationsValidationPlugin.cs
+++ b/src/Avalonia.Base/Data/Core/Plugins/DataAnnotationsValidationPlugin.cs
@@ -10,7 +10,7 @@ namespace Avalonia.Data.Core.Plugins
///
/// Validates properties on that have s.
///
- internal class DataAnnotationsValidationPlugin : IDataValidationPlugin
+ public class DataAnnotationsValidationPlugin : IDataValidationPlugin
{
///
[RequiresUnreferencedCode(TrimmingMessages.DataValidationPluginRequiresUnreferencedCodeMessage)]
diff --git a/src/Avalonia.Base/Data/Core/Plugins/ExceptionValidationPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/ExceptionValidationPlugin.cs
index e60a341309..2bb8da2c74 100644
--- a/src/Avalonia.Base/Data/Core/Plugins/ExceptionValidationPlugin.cs
+++ b/src/Avalonia.Base/Data/Core/Plugins/ExceptionValidationPlugin.cs
@@ -7,7 +7,7 @@ namespace Avalonia.Data.Core.Plugins
///
/// Validates properties that report errors by throwing exceptions.
///
- internal class ExceptionValidationPlugin : IDataValidationPlugin
+ public class ExceptionValidationPlugin : IDataValidationPlugin
{
///
[RequiresUnreferencedCode(TrimmingMessages.DataValidationPluginRequiresUnreferencedCodeMessage)]
diff --git a/src/Avalonia.Base/Data/Core/Plugins/IndeiValidationPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/IndeiValidationPlugin.cs
index 3384a99333..87a2f67ee8 100644
--- a/src/Avalonia.Base/Data/Core/Plugins/IndeiValidationPlugin.cs
+++ b/src/Avalonia.Base/Data/Core/Plugins/IndeiValidationPlugin.cs
@@ -10,7 +10,7 @@ namespace Avalonia.Data.Core.Plugins
///
/// Validates properties on objects that implement .
///
- internal class IndeiValidationPlugin : IDataValidationPlugin
+ public class IndeiValidationPlugin : IDataValidationPlugin
{
private static readonly WeakEvent
ErrorsChangedWeakEvent = WeakEvent.Register(
diff --git a/src/Avalonia.Base/Layout/LayoutManager.cs b/src/Avalonia.Base/Layout/LayoutManager.cs
index f47738f2e4..7873f83edb 100644
--- a/src/Avalonia.Base/Layout/LayoutManager.cs
+++ b/src/Avalonia.Base/Layout/LayoutManager.cs
@@ -21,6 +21,7 @@ namespace Avalonia.Layout
private readonly Layoutable _owner;
private readonly LayoutQueue _toMeasure = new LayoutQueue(v => !v.IsMeasureValid);
private readonly LayoutQueue _toArrange = new LayoutQueue(v => !v.IsArrangeValid);
+ private readonly List _toArrangeAfterMeasure = new();
private readonly Action _executeLayoutPass;
private List? _effectiveViewportChangedListeners;
private bool _disposed;
@@ -266,9 +267,14 @@ namespace Avalonia.Layout
if (!control.IsArrangeValid)
{
- Arrange(control);
+ if (Arrange(control) == ArrangeResult.AncestorMeasureInvalid)
+ _toArrangeAfterMeasure.Add(control);
}
}
+
+ foreach (var i in _toArrangeAfterMeasure)
+ InvalidateArrange(i);
+ _toArrangeAfterMeasure.Clear();
}
private bool Measure(Layoutable control)
@@ -304,19 +310,19 @@ namespace Avalonia.Layout
return true;
}
- private bool Arrange(Layoutable control)
+ private ArrangeResult Arrange(Layoutable control)
{
if (!control.IsVisible || !control.IsAttachedToVisualTree)
- return false;
+ return ArrangeResult.NotVisible;
if (control.VisualParent is Layoutable parent)
{
- if (!Arrange(parent))
- return false;
+ if (Arrange(parent) is var parentResult && parentResult != ArrangeResult.Arranged)
+ return parentResult;
}
if (!control.IsMeasureValid)
- return false;
+ return ArrangeResult.AncestorMeasureInvalid;
if (!control.IsArrangeValid)
{
@@ -332,7 +338,7 @@ namespace Avalonia.Layout
}
}
- return true;
+ return ArrangeResult.Arranged;
}
private void QueueLayoutPass()
@@ -435,5 +441,12 @@ namespace Avalonia.Layout
public Layoutable Listener { get; }
public Rect Viewport { get; set; }
}
+
+ private enum ArrangeResult
+ {
+ Arranged,
+ NotVisible,
+ AncestorMeasureInvalid,
+ }
}
}
diff --git a/src/Avalonia.Base/Media/DrawingContext.cs b/src/Avalonia.Base/Media/DrawingContext.cs
index 3ab946a1db..02294368c5 100644
--- a/src/Avalonia.Base/Media/DrawingContext.cs
+++ b/src/Avalonia.Base/Media/DrawingContext.cs
@@ -1,11 +1,10 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel;
using Avalonia.Platform;
using Avalonia.Rendering.SceneGraph;
using Avalonia.Threading;
using Avalonia.Utilities;
-using Avalonia.Media.Imaging;
-using System.ComponentModel;
namespace Avalonia.Media
{
@@ -54,12 +53,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);
}
///
@@ -69,8 +66,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.
@@ -287,8 +283,7 @@ namespace Avalonia.Media
Opacity,
Clip,
GeometryClip,
- OpacityMask,
- BitmapBlendMode
+ OpacityMask
}
public RestoreState(DrawingContext context, PushedStateType type)
@@ -313,8 +308,6 @@ namespace Avalonia.Media
_context.PopGeometryClipCore();
else if (_type == PushedStateType.OpacityMask)
_context.PopOpacityMaskCore();
- else if (_type == PushedStateType.BitmapBlendMode)
- _context.PopBitmapBlendModeCore();
}
}
@@ -395,16 +388,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.
///
@@ -432,7 +415,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/Imaging/RenderTargetBitmap.cs b/src/Avalonia.Base/Media/Imaging/RenderTargetBitmap.cs
index e77dd9d1ab..4921e9b756 100644
--- a/src/Avalonia.Base/Media/Imaging/RenderTargetBitmap.cs
+++ b/src/Avalonia.Base/Media/Imaging/RenderTargetBitmap.cs
@@ -9,7 +9,7 @@ namespace Avalonia.Media.Imaging
///
/// A bitmap that holds the rendering of a .
///
- public class RenderTargetBitmap : Bitmap, IDisposable
+ public class RenderTargetBitmap : Bitmap
{
///
/// Initializes a new instance of the class.
@@ -68,5 +68,11 @@ namespace Avalonia.Media.Imaging
platform.Clear(Colors.Transparent);
return new PlatformDrawingContext(platform);
}
+
+ public override void Dispose()
+ {
+ PlatformImpl.Dispose();
+ base.Dispose();
+ }
}
}
diff --git a/src/Avalonia.Base/Media/ImmediateDrawingContext.cs b/src/Avalonia.Base/Media/ImmediateDrawingContext.cs
index 17c4560523..fdf10596bb 100644
--- a/src/Avalonia.Base/Media/ImmediateDrawingContext.cs
+++ b/src/Avalonia.Base/Media/ImmediateDrawingContext.cs
@@ -79,11 +79,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 4b683c6acb..09c0cd26ac 100644
--- a/src/Avalonia.Base/Media/PlatformDrawingContext.cs
+++ b/src/Avalonia.Base/Media/PlatformDrawingContext.cs
@@ -26,6 +26,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);
@@ -38,9 +44,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)
{
@@ -77,9 +82,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();
@@ -96,8 +98,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 ef53024508..d86519656c 100644
--- a/src/Avalonia.Base/Platform/IDrawingContextImpl.cs
+++ b/src/Avalonia.Base/Platform/IDrawingContextImpl.cs
@@ -1,8 +1,8 @@
using System;
using Avalonia.Media;
using Avalonia.Utilities;
-using Avalonia.Media.Imaging;
using Avalonia.Metadata;
+using Avalonia.Media.Imaging;
namespace Avalonia.Platform
{
@@ -12,6 +12,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.
///
@@ -30,8 +35,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,15 +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();
///
/// Attempts to get an optional feature from the drawing context implementation
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 6f62c3be1d..b0d17f9c85 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 901bdaae0d..5a4890e568 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 object? GetFeature(Type t) => _impl.GetFeature(t);
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..3462b1008a 100644
--- a/src/Avalonia.Base/Rendering/ImmediateRenderer.cs
+++ b/src/Avalonia.Base/Rendering/ImmediateRenderer.cs
@@ -44,79 +44,99 @@ namespace Avalonia.Rendering
public static void Render(DrawingContext context, Visual visual, Rect clipRect)
{
- var opacity = visual.Opacity;
- var clipToBounds = visual.ClipToBounds;
- var bounds = new Rect(visual.Bounds.Size);
+ var currentRenderOptions = default(RenderOptions);
+ var platformContext = context as PlatformDrawingContext;
- if (visual.IsVisible && opacity > 0)
+ try
{
- var m = Matrix.CreateTranslation(visual.Bounds.Position);
-
- var renderTransform = Matrix.Identity;
-
- // this should be calculated BEFORE renderTransform
- if (visual.HasMirrorTransform)
+ if (platformContext != null)
{
- var mirrorMatrix = new Matrix(-1.0, 0.0, 0.0, 1.0, visual.Bounds.Width, 0);
- renderTransform *= mirrorMatrix;
- }
+ currentRenderOptions = platformContext.RenderOptions;
- if (visual.RenderTransform != null)
- {
- var origin = visual.RenderTransformOrigin.ToPixels(new Size(visual.Bounds.Width, visual.Bounds.Height));
- var offset = Matrix.CreateTranslation(origin);
- var finalTransform = (-offset) * visual.RenderTransform.Value * (offset);
- renderTransform *= finalTransform;
+ platformContext.RenderOptions = visual.RenderOptions.MergeWith(platformContext.RenderOptions);
}
- m = renderTransform * m;
+ var opacity = visual.Opacity;
+ var clipToBounds = visual.ClipToBounds;
+ var bounds = new Rect(visual.Bounds.Size);
- if (clipToBounds)
+ if (visual.IsVisible && opacity > 0)
{
+ var m = Matrix.CreateTranslation(visual.Bounds.Position);
+
+ var renderTransform = Matrix.Identity;
+
+ // this should be calculated BEFORE renderTransform
+ if (visual.HasMirrorTransform)
+ {
+ var mirrorMatrix = new Matrix(-1.0, 0.0, 0.0, 1.0, visual.Bounds.Width, 0);
+ renderTransform *= mirrorMatrix;
+ }
+
if (visual.RenderTransform != null)
{
- clipRect = new Rect(visual.Bounds.Size);
+ var origin = visual.RenderTransformOrigin.ToPixels(new Size(visual.Bounds.Width, visual.Bounds.Height));
+ var offset = Matrix.CreateTranslation(origin);
+ var finalTransform = (-offset) * visual.RenderTransform.Value * (offset);
+ renderTransform *= finalTransform;
}
- else
+
+ m = renderTransform * m;
+
+ if (clipToBounds)
{
- clipRect = clipRect.Intersect(new Rect(visual.Bounds.Size));
+ if (visual.RenderTransform != null)
+ {
+ clipRect = new Rect(visual.Bounds.Size);
+ }
+ else
+ {
+ clipRect = clipRect.Intersect(new Rect(visual.Bounds.Size));
+ }
}
- }
- using (context.PushTransform(m))
- using (context.PushOpacity(opacity, bounds))
- using (clipToBounds
+ using (context.PushTransform(m))
+ using (context.PushOpacity(opacity, bounds))
+ using (clipToBounds
#pragma warning disable CS0618 // Type or member is obsolete
- ? visual is IVisualWithRoundRectClip roundClipVisual
- ? context.PushClip(new RoundedRect(bounds, roundClipVisual.ClipToBoundsRadius))
- : context.PushClip(bounds)
- : default)
+ ? visual is IVisualWithRoundRectClip roundClipVisual
+ ? context.PushClip(new RoundedRect(bounds, roundClipVisual.ClipToBoundsRadius))
+ : context.PushClip(bounds)
+ : default)
#pragma warning restore CS0618 // Type or member is obsolete
- using (visual.Clip != null ? context.PushGeometryClip(visual.Clip) : default)
- using (visual.OpacityMask != null ? context.PushOpacityMask(visual.OpacityMask, bounds) : default)
- using (context.PushTransform(Matrix.Identity))
- {
- visual.Render(context);
-
- var childrenEnumerable = visual.HasNonUniformZIndexChildren
- ? visual.VisualChildren.OrderBy(x => x, ZIndexComparer.Instance)
- : (IEnumerable)visual.VisualChildren;
-
- foreach (var child in childrenEnumerable)
+ using (visual.Clip != null ? context.PushGeometryClip(visual.Clip) : default)
+ using (visual.OpacityMask != null ? context.PushOpacityMask(visual.OpacityMask, bounds) : default)
+ using (context.PushTransform(Matrix.Identity))
{
- var childBounds = GetTransformedBounds(child);
+ visual.Render(context);
+
+ var childrenEnumerable = visual.HasNonUniformZIndexChildren
+ ? visual.VisualChildren.OrderBy(x => x, ZIndexComparer.Instance)
+ : (IEnumerable)visual.VisualChildren;
- if (!child.ClipToBounds || clipRect.Intersects(childBounds))
+ foreach (var child in childrenEnumerable)
{
- var childClipRect = child.RenderTransform == null
- ? clipRect.Translate(-childBounds.Position)
- : clipRect;
- Render(context, child, childClipRect);
- }
+ var childBounds = GetTransformedBounds(child);
+
+ if (!child.ClipToBounds || clipRect.Intersects(childBounds))
+ {
+ var childClipRect = child.RenderTransform == null
+ ? clipRect.Translate(-childBounds.Position)
+ : clipRect;
+ Render(context, child, childClipRect);
+ }
+ }
}
}
}
+ finally
+ {
+ 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/Threading/DispatcherOperation.cs b/src/Avalonia.Base/Threading/DispatcherOperation.cs
index 809c41ff02..8bd6d3bc01 100644
--- a/src/Avalonia.Base/Threading/DispatcherOperation.cs
+++ b/src/Avalonia.Base/Threading/DispatcherOperation.cs
@@ -331,6 +331,8 @@ public class DispatcherOperation : DispatcherOperation
private TaskCompletionSource TaskCompletionSource => (TaskCompletionSource)TaskSource!;
+ public new TaskAwaiter GetAwaiter() => GetTask().GetAwaiter();
+
public new Task GetTask() => TaskCompletionSource!.Task;
protected override Task GetTaskCore() => GetTask();
diff --git a/src/Avalonia.Base/Visual.cs b/src/Avalonia.Base/Visual.cs
index 8717b5340a..30c89d186f 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/src/Windows/Avalonia.Win32/Win32StorageProvider.cs b/src/Windows/Avalonia.Win32/Win32StorageProvider.cs
index 86574f2fa3..c987732768 100644
--- a/src/Windows/Avalonia.Win32/Win32StorageProvider.cs
+++ b/src/Windows/Avalonia.Win32/Win32StorageProvider.cs
@@ -99,12 +99,14 @@ namespace Avalonia.Win32
}
frm.SetOptions(options);
- if (defaultExtension is not null)
+ if (defaultExtension is null)
{
- fixed (char* pExt = defaultExtension)
- {
- frm.SetDefaultExtension(pExt);
- }
+ defaultExtension = String.Empty;
+ }
+
+ fixed (char* pExt = defaultExtension)
+ {
+ frm.SetDefaultExtension(pExt);
}
suggestedFileName ??= "";
diff --git a/tests/Avalonia.Base.UnitTests/Layout/LayoutManagerTests.cs b/tests/Avalonia.Base.UnitTests/Layout/LayoutManagerTests.cs
index 45a6efdd4a..cadf23c754 100644
--- a/tests/Avalonia.Base.UnitTests/Layout/LayoutManagerTests.cs
+++ b/tests/Avalonia.Base.UnitTests/Layout/LayoutManagerTests.cs
@@ -547,5 +547,38 @@ namespace Avalonia.Base.UnitTests.Layout
Assert.True(root.IsMeasureValid);
Assert.True(root.IsArrangeValid);
}
+
+ [Fact]
+ public void GreatGrandparent_Can_Invalidate_Grandparent_Measure_During_Arrange()
+ {
+ // Issue #7706 (second part: scrollbar gets stuck)
+ var child = new LayoutTestControl();
+ var parent = new LayoutTestControl { Child = child };
+ var grandparent = new LayoutTestControl { Child = parent };
+ var greatGrandparent = new LayoutTestControl { Child = grandparent };
+ var root = new LayoutTestRoot { Child = greatGrandparent };
+
+ root.LayoutManager.ExecuteInitialLayoutPass();
+
+ greatGrandparent.DoArrangeOverride = (_, s) =>
+ {
+ grandparent.InvalidateMeasure();
+ return s;
+ };
+
+ child.InvalidateArrange();
+ greatGrandparent.InvalidateArrange();
+
+ root.LayoutManager.ExecuteLayoutPass();
+
+ Assert.True(child.IsMeasureValid);
+ Assert.True(child.IsArrangeValid);
+ Assert.True(parent.IsMeasureValid);
+ Assert.True(parent.IsArrangeValid);
+ Assert.True(greatGrandparent.IsMeasureValid);
+ Assert.True(greatGrandparent.IsArrangeValid);
+ Assert.True(root.IsMeasureValid);
+ Assert.True(root.IsArrangeValid);
+ }
}
}
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