diff --git a/.editorconfig b/.editorconfig
index d07618df6c..62a533e468 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -177,7 +177,9 @@ dotnet_diagnostic.CA1828.severity = warning
dotnet_diagnostic.CA1829.severity = warning
#CA1847: Use string.Contains(char) instead of string.Contains(string) with single characters
dotnet_diagnostic.CA1847.severity = warning
-#CACA2211:Non-constant fields should not be visible
+#CA1854: Prefer the IDictionary.TryGetValue(TKey, out TValue) method
+dotnet_diagnostic.CA1854.severity = warning
+#CA2211:Non-constant fields should not be visible
dotnet_diagnostic.CA2211.severity = error
# Wrapping preferences
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/dirs.proj b/dirs.proj
index f1eaae8a4a..d29aa61fcb 100644
--- a/dirs.proj
+++ b/dirs.proj
@@ -9,10 +9,11 @@
-
+
-
+
+
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/Input/FocusManager.cs b/src/Avalonia.Base/Input/FocusManager.cs
index 2bf666af44..c8de7267ca 100644
--- a/src/Avalonia.Base/Input/FocusManager.cs
+++ b/src/Avalonia.Base/Input/FocusManager.cs
@@ -122,6 +122,11 @@ namespace Avalonia.Input
{
scope = scope ?? throw new ArgumentNullException(nameof(scope));
+ if (element is not null && !CanFocus(element))
+ {
+ return;
+ }
+
if (_focusScopes.TryGetValue(scope, out var existingElement))
{
if (element != existingElement)
@@ -242,6 +247,6 @@ namespace Avalonia.Input
}
}
- private static bool IsVisible(IInputElement e) => (e as Visual)?.IsVisible ?? true;
+ private static bool IsVisible(IInputElement e) => (e as Visual)?.IsEffectivelyVisible ?? true;
}
}
diff --git a/src/Avalonia.Base/Input/InputElement.cs b/src/Avalonia.Base/Input/InputElement.cs
index 962c7aa334..33ddbaedf9 100644
--- a/src/Avalonia.Base/Input/InputElement.cs
+++ b/src/Avalonia.Base/Input/InputElement.cs
@@ -647,6 +647,10 @@ namespace Avalonia.Input
{
PseudoClasses.Set(":focus-within", change.GetNewValue());
}
+ else if (change.Property == IsVisibleProperty && !change.GetNewValue() && IsFocused)
+ {
+ FocusManager.Instance?.Focus(null);
+ }
}
///
diff --git a/src/Avalonia.Base/Input/TextInput/InputMethodManager.cs b/src/Avalonia.Base/Input/TextInput/InputMethodManager.cs
index 9b5668bf98..1c61334888 100644
--- a/src/Avalonia.Base/Input/TextInput/InputMethodManager.cs
+++ b/src/Avalonia.Base/Input/TextInput/InputMethodManager.cs
@@ -48,9 +48,9 @@ namespace Avalonia.Input.TextInput
}
_transformTracker.SetVisual(_client?.TextViewVisual);
- UpdateCursorRect();
_im?.SetClient(_client);
+ UpdateCursorRect();
}
else
{
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/Platform/StandardAssetLoader.cs b/src/Avalonia.Base/Platform/StandardAssetLoader.cs
index 118e57c7af..1d9363c70d 100644
--- a/src/Avalonia.Base/Platform/StandardAssetLoader.cs
+++ b/src/Avalonia.Base/Platform/StandardAssetLoader.cs
@@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
+using Avalonia.Metadata;
using Avalonia.Platform.Internal;
using Avalonia.Utilities;
@@ -12,12 +13,13 @@ namespace Avalonia.Platform;
///
/// Loads assets compiled into the application binary.
///
-internal class StandardAssetLoader : IAssetLoader
+[Unstable("StandardAssetLoader is considered unstable. Please use AssetLoader static class instead.")]
+public class StandardAssetLoader : IAssetLoader
{
private readonly IAssemblyDescriptorResolver _assemblyDescriptorResolver;
private AssemblyDescriptor? _defaultResmAssembly;
- public StandardAssetLoader(IAssemblyDescriptorResolver resolver, Assembly? assembly = null)
+ internal StandardAssetLoader(IAssemblyDescriptorResolver resolver, Assembly? assembly = null)
{
if (assembly == null)
assembly = Assembly.GetEntryAssembly();
@@ -153,6 +155,8 @@ internal class StandardAssetLoader : IAssetLoader
return Enumerable.Empty();
}
+ public static void RegisterResUriParsers() => AssetLoader.RegisterResUriParsers();
+
private bool TryGetAsset(Uri uri, Uri? baseUri, [NotNullWhen(true)] out IAssetDescriptor? assetDescriptor)
{
assetDescriptor = null;
diff --git a/src/Avalonia.Base/Platform/Storage/FileIO/StorageProviderHelpers.cs b/src/Avalonia.Base/Platform/Storage/FileIO/StorageProviderHelpers.cs
index 608f924808..55aac6f3fa 100644
--- a/src/Avalonia.Base/Platform/Storage/FileIO/StorageProviderHelpers.cs
+++ b/src/Avalonia.Base/Platform/Storage/FileIO/StorageProviderHelpers.cs
@@ -50,7 +50,8 @@ internal static class StorageProviderHelpers
}
}
- public static string NameWithExtension(string path, string? defaultExtension, FilePickerFileType? filter)
+ [return: NotNullIfNotNull(nameof(path))]
+ public static string? NameWithExtension(string? path, string? defaultExtension, FilePickerFileType? filter)
{
var name = Path.GetFileName(path);
if (name != null && !Path.HasExtension(name))
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 @@
+