Browse Source

Merge branch 'master' into characterBufferReference

pull/9765/head^2
Benedikt Stebner 4 years ago
committed by GitHub
parent
commit
fe11dfe6e7
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      .editorconfig
  2. 12
      Avalonia.sln
  3. 5
      build/JetBrains.Annotations.props
  4. 1
      nukebuild/DotNetConfigHelper.cs
  5. 3
      samples/ControlCatalog/MainView.xaml
  6. 89
      samples/ControlCatalog/Pages/CompositionPage.axaml
  7. 172
      samples/ControlCatalog/Pages/CompositionPage.axaml.cs
  8. 212
      samples/ControlCatalog/Pages/GesturePage.cs
  9. 117
      samples/ControlCatalog/Pages/GesturePage.xaml
  10. 2
      samples/ControlCatalog/Pages/ImagePage.xaml.cs
  11. 5
      samples/interop/Direct3DInteropSample/App.paml
  12. 21
      samples/interop/Direct3DInteropSample/App.paml.cs
  13. 32
      samples/interop/Direct3DInteropSample/Direct3DInteropSample.csproj
  14. 283
      samples/interop/Direct3DInteropSample/MainWindow.cs
  15. 14
      samples/interop/Direct3DInteropSample/MainWindow.paml
  16. 45
      samples/interop/Direct3DInteropSample/MainWindowViewModel.cs
  17. 47
      samples/interop/Direct3DInteropSample/MiniCube.fx
  18. 16
      samples/interop/Direct3DInteropSample/Program.cs
  19. 2
      src/Android/Avalonia.Android/AndroidInputMethod.cs
  20. 9
      src/Android/Avalonia.Android/AndroidPlatform.cs
  21. 32
      src/Android/Avalonia.Android/OpenGL/GlPlatformSurface.cs
  22. 30
      src/Android/Avalonia.Android/OpenGL/GlRenderTarget.cs
  23. 2
      src/Android/Avalonia.Android/Platform/SkiaPlatform/AndroidFramebuffer.cs
  24. 18
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  25. 1
      src/Avalonia.Base/Animation/AnimationInstance`1.cs
  26. 11
      src/Avalonia.Base/Animation/Cue.cs
  27. 1
      src/Avalonia.Base/Avalonia.Base.csproj
  28. 34
      src/Avalonia.Base/Contract.cs
  29. 9
      src/Avalonia.Base/CornerRadius.cs
  30. 2
      src/Avalonia.Base/Data/BindingValue.cs
  31. 2
      src/Avalonia.Base/Data/Core/ExpressionNode.cs
  32. 2
      src/Avalonia.Base/Data/Core/ExpressionObserver.cs
  33. 4
      src/Avalonia.Base/Data/InstancedBinding.cs
  34. 128
      src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs
  35. 33
      src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs
  36. 22
      src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs
  37. 8
      src/Avalonia.Base/Input/Gestures.cs
  38. 2
      src/Avalonia.Base/Input/KeyEventArgs.cs
  39. 24
      src/Avalonia.Base/Input/PinchEventArgs.cs
  40. 4
      src/Avalonia.Base/Input/PointerPoint.cs
  41. 6
      src/Avalonia.Base/Input/Raw/RawInputEventArgs.cs
  42. 8
      src/Avalonia.Base/Input/Raw/RawPointerEventArgs.cs
  43. 2
      src/Avalonia.Base/Input/TextInput/ITextInputMethodClient.cs
  44. 2
      src/Avalonia.Base/Input/TextInputEventArgs.cs
  45. 2
      src/Avalonia.Base/Logging/ParametrizedLogger.cs
  46. 2
      src/Avalonia.Base/Matrix.cs
  47. 17
      src/Avalonia.Base/Media/BoxShadow.cs
  48. 12
      src/Avalonia.Base/Media/BoxShadows.cs
  49. 5
      src/Avalonia.Base/Media/Brush.cs
  50. 4
      src/Avalonia.Base/Media/BrushExtensions.cs
  51. 282
      src/Avalonia.Base/Media/Brushes.cs
  52. 2
      src/Avalonia.Base/Media/ConicGradientBrush.cs
  53. 8
      src/Avalonia.Base/Media/DashStyle.cs
  54. 2
      src/Avalonia.Base/Media/DrawingContext.cs
  55. 7
      src/Avalonia.Base/Media/DrawingGroup.cs
  56. 2
      src/Avalonia.Base/Media/FontMetrics.cs
  57. 2
      src/Avalonia.Base/Media/FormattedText.cs
  58. 4
      src/Avalonia.Base/Media/Geometry.cs
  59. 2
      src/Avalonia.Base/Media/GeometryDrawing.cs
  60. 2
      src/Avalonia.Base/Media/GlyphMetrics.cs
  61. 2
      src/Avalonia.Base/Media/GlyphRunDrawing.cs
  62. 2
      src/Avalonia.Base/Media/GlyphRunMetrics.cs
  63. 4
      src/Avalonia.Base/Media/GradientBrush.cs
  64. 2
      src/Avalonia.Base/Media/IDashStyle.cs
  65. 9
      src/Avalonia.Base/Media/IImmutableBrush.cs
  66. 4
      src/Avalonia.Base/Media/IMutableBrush.cs
  67. 9
      src/Avalonia.Base/Media/ISolidColorBrush.cs
  68. 4
      src/Avalonia.Base/Media/ImageBrush.cs
  69. 2
      src/Avalonia.Base/Media/ImageDrawing.cs
  70. 4
      src/Avalonia.Base/Media/Imaging/CroppedBitmap.cs
  71. 2
      src/Avalonia.Base/Media/Imaging/RenderTargetBitmap.cs
  72. 373
      src/Avalonia.Base/Media/ImmediateDrawingContext.cs
  73. 4
      src/Avalonia.Base/Media/Immutable/ImmutableDashStyle.cs
  74. 2
      src/Avalonia.Base/Media/Immutable/ImmutableGradientBrush.cs
  75. 4
      src/Avalonia.Base/Media/Immutable/ImmutablePen.cs
  76. 2
      src/Avalonia.Base/Media/Immutable/ImmutableSolidColorBrush.cs
  77. 2
      src/Avalonia.Base/Media/Immutable/ImmutableTileBrush.cs
  78. 6
      src/Avalonia.Base/Media/KnownColors.cs
  79. 2
      src/Avalonia.Base/Media/LinearGradientBrush.cs
  80. 2
      src/Avalonia.Base/Media/RadialGradientBrush.cs
  81. 4
      src/Avalonia.Base/Media/SolidColorBrush.cs
  82. 2
      src/Avalonia.Base/Media/TextCollapsingCreateInfo.cs
  83. 1
      src/Avalonia.Base/Media/TextFormatting/FormattedTextSource.cs
  84. 2
      src/Avalonia.Base/Media/TextFormatting/ShapedBuffer.cs
  85. 2
      src/Avalonia.Base/Media/TextFormatting/SplitResult.cs
  86. 4
      src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs
  87. 2
      src/Avalonia.Base/Media/TextFormatting/TextLineMetrics.cs
  88. 2
      src/Avalonia.Base/Media/TextFormatting/TextMetrics.cs
  89. 2
      src/Avalonia.Base/Media/TextFormatting/TextRange.cs
  90. 2
      src/Avalonia.Base/Media/TextFormatting/TextRunBounds.cs
  91. 2
      src/Avalonia.Base/Media/TextFormatting/TextShaperOptions.cs
  92. 2
      src/Avalonia.Base/Media/TextFormatting/Unicode/Codepoint.cs
  93. 1
      src/Avalonia.Base/Media/TextFormatting/Unicode/CodepointEnumerator.cs
  94. 2
      src/Avalonia.Base/Media/TextFormatting/Unicode/LineBreak.cs
  95. 2
      src/Avalonia.Base/Media/TextHitTestResult.cs
  96. 12
      src/Avalonia.Base/Media/Transformation/TransformOperation.cs
  97. 2
      src/Avalonia.Base/Media/Transformation/TransformOperations.cs
  98. 3
      src/Avalonia.Base/Media/Typeface.cs
  99. 6
      src/Avalonia.Base/Media/UnicodeRange.cs
  100. 4
      src/Avalonia.Base/Media/VisualBrush.cs

6
.editorconfig

@ -140,16 +140,22 @@ dotnet_analyzer_diagnostic.category-Performance.severity = none #error - Uncomme
# CS1591: Missing XML comment for publicly visible type or member
dotnet_diagnostic.CS1591.severity = suggestion
# CS0162: Remove unreachable code
dotnet_diagnostic.CS0162.severity = error
# CA1304: Specify CultureInfo
dotnet_diagnostic.CA1304.severity = warning
# CA1802: Use literals where appropriate
dotnet_diagnostic.CA1802.severity = warning
# CA1815: Override equals and operator equals on value types
dotnet_diagnostic.CA1815.severity = warning
# CA1820: Test for empty strings using string length
dotnet_diagnostic.CA1820.severity = warning
# CA1821: Remove empty finalizers
dotnet_diagnostic.CA1821.severity = warning
# CA1822: Mark members as static
dotnet_diagnostic.CA1822.severity = suggestion
# CA1823: Avoid unused private fields
dotnet_diagnostic.CA1823.severity = warning
dotnet_code_quality.CA1822.api_surface = private, internal
# CA1825: Avoid zero-length array allocations
dotnet_diagnostic.CA1825.severity = warning

12
Avalonia.sln

@ -100,7 +100,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
build\EmbedXaml.props = build\EmbedXaml.props
build\HarfBuzzSharp.props = build\HarfBuzzSharp.props
build\ImageSharp.props = build\ImageSharp.props
build\JetBrains.Annotations.props = build\JetBrains.Annotations.props
build\JetBrains.dotMemoryUnit.props = build\JetBrains.dotMemoryUnit.props
build\Microsoft.CSharp.props = build\Microsoft.CSharp.props
build\Microsoft.Reactive.Testing.props = build\Microsoft.Reactive.Testing.props
@ -136,8 +135,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Linux", "Linux", "{86C53C40
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.LinuxFramebuffer", "src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj", "{854568D5-13D1-4B4F-B50D-534DC7EFD3C9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Direct3DInteropSample", "samples\interop\Direct3DInteropSample\Direct3DInteropSample.csproj", "{638580B0-7910-40EF-B674-DCB34DA308CD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Win32.Interop", "src\Windows\Avalonia.Win32.Interop\Avalonia.Win32.Interop.csproj", "{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia.RenderTests", "tests\Avalonia.Skia.RenderTests\Avalonia.Skia.RenderTests.csproj", "{E1582370-37B3-403C-917F-8209551B1634}"
@ -228,9 +225,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Browser", "src\Bro
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Browser.Blazor", "src\Browser\Avalonia.Browser.Blazor\Avalonia.Browser.Blazor.csproj", "{47F8530C-F19B-4B1A-B4D6-EB231522AE5D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Browser", "samples\ControlCatalog.Browser\ControlCatalog.Browser.csproj", "{15B93A4C-1B46-43F6-B534-7B25B6E99932}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.Browser", "samples\ControlCatalog.Browser\ControlCatalog.Browser.csproj", "{15B93A4C-1B46-43F6-B534-7B25B6E99932}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Browser.Blazor", "samples\ControlCatalog.Browser.Blazor\ControlCatalog.Browser.Blazor.csproj", "{90B08091-9BBD-4362-B712-E9F2CC62B218}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.Browser.Blazor", "samples\ControlCatalog.Browser.Blazor\ControlCatalog.Browser.Blazor.csproj", "{90B08091-9BBD-4362-B712-E9F2CC62B218}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveUIDemo", "samples\ReactiveUIDemo\ReactiveUIDemo.csproj", "{75C47156-C5D8-44BC-A5A7-E8657C2248D6}"
EndProject
@ -366,10 +363,6 @@ Global
{854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|Any CPU.Build.0 = Release|Any CPU
{638580B0-7910-40EF-B674-DCB34DA308CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{638580B0-7910-40EF-B674-DCB34DA308CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{638580B0-7910-40EF-B674-DCB34DA308CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{638580B0-7910-40EF-B674-DCB34DA308CD}.Release|Any CPU.Build.0 = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -580,7 +573,6 @@ Global
{7D2D3083-71DD-4CC9-8907-39A0D86FB322} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
{39D7B147-1A5B-47C2-9D01-21FB7C47C4B3} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{854568D5-13D1-4B4F-B50D-534DC7EFD3C9} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{638580B0-7910-40EF-B674-DCB34DA308CD} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9}
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E} = {B39A8919-9F95-48FE-AD7B-76E08B509888}
{E1582370-37B3-403C-917F-8209551B1634} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{E2999E4A-9086-401F-898C-AEB0AD38E676} = {9B9E3891-2366-4253-A952-D08BCEB71098}

5
build/JetBrains.Annotations.props

@ -1,5 +0,0 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="10.3.0" />
</ItemGroup>
</Project>

1
nukebuild/DotNetConfigHelper.cs

@ -1,5 +1,4 @@
using System.Globalization;
using JetBrains.Annotations;
using Nuke.Common.Tools.DotNet;
// ReSharper disable ReturnValueOfPureMethodIsNotUsed

3
samples/ControlCatalog/MainView.xaml

@ -92,6 +92,9 @@
<TabItem Header="Flyouts">
<pages:FlyoutsPage />
</TabItem>
<TabItem Header="Gestures">
<pages:GesturePage />
</TabItem>
<TabItem Header="Image"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Disabled">

89
samples/ControlCatalog/Pages/CompositionPage.axaml

@ -2,44 +2,57 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:pages="using:ControlCatalog.Pages"
x:Class="ControlCatalog.Pages.CompositionPage">
<StackPanel>
<TextBlock Classes="h1">Implicit animations</TextBlock>
<TabControl>
<TabItem Header="Implicit animations">
<StackPanel>
<Grid ColumnDefinitions="*,10,40" Margin="0 0 40 0">
<ItemsControl x:Name="Items">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.DataTemplates>
<DataTemplate DataType="pages:CompositionPageColorItem">
<Border
pages:CompositionPage.EnableAnimations="True"
Padding="10" BorderBrush="Gray" BorderThickness="2"
Background="{Binding ColorBrush}" Width="100" Height="100" Margin="10">
<TextBlock Text="{Binding ColorHexValue}"/>
</Border>
</DataTemplate>
</ItemsControl.DataTemplates>
</ItemsControl>
<GridSplitter Margin="2" BorderThickness="1" BorderBrush="Gray"
Background="#e0e0e0" Grid.Column="1"
ResizeDirection="Columns" ResizeBehavior="PreviousAndNext"
/>
<Border Grid.Column="2">
<LayoutTransformControl
HorizontalAlignment="Center"
MinWidth="30">
<LayoutTransformControl.LayoutTransform>
<RotateTransform Angle="90"/>
</LayoutTransformControl.LayoutTransform>
<TextBlock>Resize me</TextBlock>
</LayoutTransformControl>
</Border>
<ItemsControl x:Name="Items">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.DataTemplates>
<DataTemplate DataType="pages:CompositionPageColorItem">
<Border
pages:CompositionPage.EnableAnimations="True"
Padding="10" BorderBrush="Gray" BorderThickness="2"
Background="{Binding ColorBrush}" Width="100" Height="100" Margin="10">
<TextBlock Text="{Binding ColorHexValue}"/>
</Border>
</DataTemplate>
</ItemsControl.DataTemplates>
</ItemsControl>
<GridSplitter Margin="2" BorderThickness="1" BorderBrush="Gray"
Background="#e0e0e0" Grid.Column="1"
ResizeDirection="Columns" ResizeBehavior="PreviousAndNext"
/>
<Border Grid.Column="2">
<LayoutTransformControl HorizontalAlignment="Center" MinWidth="30">
<LayoutTransformControl.LayoutTransform>
<RotateTransform Angle="90"/>
</LayoutTransformControl.LayoutTransform>
<TextBlock>Resize me</TextBlock>
</LayoutTransformControl>
</Border>
</Grid>
</StackPanel>
</StackPanel>
</TabItem>
<TabItem Header="Animation">
<DockPanel>
<Button DockPanel.Dock="Top" Margin="10" Click="ButtonThreadSleep">Thread.Sleep(10000);</Button>
<Control x:Name="SolidVisualHost" />
</DockPanel>
</TabItem>
<TabItem Header="Custom">
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Button Margin="10" Click="ButtonThreadSleep">Thread.Sleep(10000);</Button>
<Button Margin="10" Click="ButtonStartCustomVisual">Start</Button>
<Button Margin="10" Click="ButtonStopCustomVisual">Stop</Button>
</StackPanel>
<Control x:Name="CustomVisualHost" />
</DockPanel>
</TabItem>
</TabControl>
</UserControl>

172
samples/ControlCatalog/Pages/CompositionPage.axaml.cs

@ -1,28 +1,39 @@
using System;
using System.Collections.Generic;
using System.Numerics;
using System.Threading;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Media.Immutable;
using Avalonia.Rendering.Composition;
using Avalonia.Rendering.Composition.Animations;
using Avalonia.VisualTree;
using Math = System.Math;
namespace ControlCatalog.Pages;
public partial class CompositionPage : UserControl
{
private ImplicitAnimationCollection? _implicitAnimations;
private CompositionCustomVisual? _customVisual;
private CompositionSolidColorVisual? _solidVisual;
public CompositionPage()
{
AvaloniaXamlLoader.Load(this);
AttachAnimatedSolidVisual(this.FindControl<Control>("SolidVisualHost")!);
AttachCustomVisual(this.FindControl<Control>("CustomVisualHost")!);
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
this.Get<ItemsControl>("Items").Items = CreateColorItems();
}
private static List<CompositionPageColorItem> CreateColorItems()
@ -126,6 +137,167 @@ public partial class CompositionPage : UserControl
compositionVisual.ImplicitAnimations = page._implicitAnimations;
}
}
void AttachAnimatedSolidVisual(Visual v)
{
void Update()
{
if(_solidVisual == null)
return;
_solidVisual.Size = new Vector2((float)v.Bounds.Width / 3, (float)v.Bounds.Height / 3);
_solidVisual.Offset = new Vector3((float)v.Bounds.Width / 3, (float)v.Bounds.Height / 3, 0);
}
v.AttachedToVisualTree += delegate
{
var compositor = ElementComposition.GetElementVisual(v)?.Compositor;
if(compositor == null || _solidVisual?.Compositor == compositor)
return;
_solidVisual = compositor.CreateSolidColorVisual();
ElementComposition.SetElementChildVisual(v, _solidVisual);
_solidVisual.Color = Colors.Red;
var animation = _solidVisual.Compositor.CreateColorKeyFrameAnimation();
animation.InsertKeyFrame(0, Colors.Red);
animation.InsertKeyFrame(0.5f, Colors.Blue);
animation.InsertKeyFrame(1, Colors.Green);
animation.Duration = TimeSpan.FromSeconds(5);
animation.IterationBehavior = AnimationIterationBehavior.Forever;
animation.Direction = PlaybackDirection.Alternate;
_solidVisual.StartAnimation("Color", animation);
_solidVisual.AnchorPoint = new Vector2(0, 0);
var scale = _solidVisual.Compositor.CreateVector3KeyFrameAnimation();
scale.Duration = TimeSpan.FromSeconds(5);
scale.IterationBehavior = AnimationIterationBehavior.Forever;
scale.InsertKeyFrame(0, new Vector3(1, 1, 0));
scale.InsertKeyFrame(0.5f, new Vector3(1.5f, 1.5f, 0));
scale.InsertKeyFrame(1, new Vector3(1, 1, 0));
_solidVisual.StartAnimation("Scale", scale);
var center =
_solidVisual.Compositor.CreateExpressionAnimation(
"Vector3(this.Target.Size.X * 0.5, this.Target.Size.Y * 0.5, 1)");
_solidVisual.StartAnimation("CenterPoint", center);
Update();
};
v.PropertyChanged += (_, a) =>
{
if (a.Property == BoundsProperty)
Update();
};
}
void AttachCustomVisual(Visual v)
{
void Update()
{
if (_customVisual == null)
return;
var h = (float)Math.Min(v.Bounds.Height, v.Bounds.Width / 3);
_customVisual.Size = new Vector2((float)v.Bounds.Width, h);
_customVisual.Offset = new Vector3(0, (float)(v.Bounds.Height - h) / 2, 0);
}
v.AttachedToVisualTree += delegate
{
var compositor = ElementComposition.GetElementVisual(v)?.Compositor;
if(compositor == null || _customVisual?.Compositor == compositor)
return;
_customVisual = compositor.CreateCustomVisual(new CustomVisualHandler());
ElementComposition.SetElementChildVisual(v, _customVisual);
_customVisual.SendHandlerMessage(CustomVisualHandler.StartMessage);
Update();
};
v.PropertyChanged += (_, a) =>
{
if (a.Property == BoundsProperty)
Update();
};
}
class CustomVisualHandler : CompositionCustomVisualHandler
{
private TimeSpan _animationElapsed;
private TimeSpan? _lastServerTime;
private bool _running;
public static readonly object StopMessage = new(), StartMessage = new();
public override void OnRender(ImmediateDrawingContext drawingContext)
{
if (_running)
{
if (_lastServerTime.HasValue) _animationElapsed += (CompositionNow - _lastServerTime.Value);
_lastServerTime = CompositionNow;
}
const int cnt = 20;
var maxPointSizeX = EffectiveSize.X / (cnt * 1.6);
var maxPointSizeY = EffectiveSize.Y / 4;
var pointSize = Math.Min(maxPointSizeX, maxPointSizeY);
var animationLength = TimeSpan.FromSeconds(4);
var animationStage = _animationElapsed.TotalSeconds / animationLength.TotalSeconds;
var sinOffset = Math.Cos(_animationElapsed.TotalSeconds) * 1.5;
for (var c = 0; c < cnt; c++)
{
var stage = (animationStage + (double)c / cnt) % 1;
var colorStage =
(animationStage + (Math.Sin(_animationElapsed.TotalSeconds * 2) + 1) / 2 + (double)c / cnt) % 1;
var posX = (EffectiveSize.X + pointSize * 3) * stage - pointSize;
var posY = (EffectiveSize.Y - pointSize) * (1 + Math.Sin(stage * 3.14 * 3 + sinOffset)) / 2 + pointSize / 2;
var opacity = Math.Sin(stage * 3.14);
drawingContext.DrawEllipse(new ImmutableSolidColorBrush(Color.FromArgb(
255,
(byte)(255 - 255 * colorStage),
(byte)(255 * Math.Abs(0.5 - colorStage) * 2),
(byte)(255 * colorStage)
), opacity), null,
new Point(posX, posY), pointSize / 2, pointSize / 2);
}
}
public override void OnMessage(object message)
{
if (message == StartMessage)
{
_running = true;
_lastServerTime = null;
RegisterForNextAnimationFrameUpdate();
}
else if (message == StopMessage)
_running = false;
}
public override void OnAnimationFrameUpdate()
{
if (_running)
{
Invalidate();
RegisterForNextAnimationFrameUpdate();
}
}
}
private void ButtonThreadSleep(object? sender, RoutedEventArgs e)
{
Thread.Sleep(10000);
}
private void ButtonStartCustomVisual(object? sender, RoutedEventArgs e)
{
_customVisual?.SendHandlerMessage(CustomVisualHandler.StartMessage);
}
private void ButtonStopCustomVisual(object? sender, RoutedEventArgs e)
{
_customVisual?.SendHandlerMessage(CustomVisualHandler.StopMessage);
}
}
public class CompositionPageColorItem

212
samples/ControlCatalog/Pages/GesturePage.cs

@ -0,0 +1,212 @@
using System;
using System.Numerics;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.LogicalTree;
using Avalonia.Markup.Xaml;
using Avalonia.Rendering.Composition;
namespace ControlCatalog.Pages
{
public class GesturePage : UserControl
{
private bool _isInit;
private float _currentScale;
public GesturePage()
{
this.InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
if(_isInit)
{
return;
}
_isInit = true;
SetPullHandlers(this.Find<Border>("TopPullZone"), false);
SetPullHandlers(this.Find<Border>("BottomPullZone"), true);
SetPullHandlers(this.Find<Border>("RightPullZone"), true);
SetPullHandlers(this.Find<Border>("LeftPullZone"), false);
var image = this.Find<Image>("PinchImage");
SetPinchHandlers(image);
var reset = this.Find<Button>("ResetButton");
reset!.Click += (s, e) =>
{
var compositionVisual = ElementComposition.GetElementVisual(image);
if(compositionVisual!= null)
{
_currentScale = 1;
compositionVisual.Scale = new Vector3(1,1,1);
image.InvalidateMeasure();
}
};
}
private void SetPinchHandlers(Control? control)
{
if (control == null)
{
return;
}
_currentScale = 1;
Vector3 currentOffset = default;
bool isZooming = false;
CompositionVisual? compositionVisual = null;
void InitComposition(Control visual)
{
if (compositionVisual != null)
{
return;
}
compositionVisual = ElementComposition.GetElementVisual(visual);
}
control.LayoutUpdated += (s, e) =>
{
InitComposition(control!);
if (compositionVisual != null)
{
compositionVisual.Scale = new(_currentScale, _currentScale, 1);
if(currentOffset == default)
{
currentOffset = compositionVisual.Offset;
}
}
};
control.AddHandler(Gestures.PinchEvent, (s, e) =>
{
InitComposition(control!);
isZooming = true;
if(compositionVisual != null)
{
var scale = _currentScale * (float)e.Scale;
compositionVisual.Scale = new(scale, scale, 1);
}
});
control.AddHandler(Gestures.PinchEndedEvent, (s, e) =>
{
InitComposition(control!);
isZooming = false;
if (compositionVisual != null)
{
_currentScale = compositionVisual.Scale.X;
}
});
control.AddHandler(Gestures.ScrollGestureEvent, (s, e) =>
{
InitComposition(control!);
if (compositionVisual != null && !isZooming)
{
currentOffset -= new Vector3((float)e.Delta.X, (float)e.Delta.Y, 0);
compositionVisual.Offset = currentOffset;
}
});
}
private void SetPullHandlers(Control? control, bool inverse)
{
if (control == null)
{
return;
}
var ball = control.FindLogicalDescendantOfType<Border>();
Vector3 defaultOffset = default;
CompositionVisual? ballCompositionVisual = null;
if (ball != null)
{
InitComposition(ball);
}
else
{
return;
}
control.LayoutUpdated += (s, e) =>
{
InitComposition(ball!);
if (ballCompositionVisual != null)
{
defaultOffset = ballCompositionVisual.Offset;
}
};
control.AddHandler(Gestures.PullGestureEvent, (s, e) =>
{
Vector3 center = new((float)control.Bounds.Center.X, (float)control.Bounds.Center.Y, 0);
InitComposition(ball!);
if (ballCompositionVisual != null)
{
ballCompositionVisual.Offset = defaultOffset + new System.Numerics.Vector3((float)e.Delta.X * 0.4f, (float)e.Delta.Y * 0.4f, 0) * (inverse ? -1 : 1);
}
});
control.AddHandler(Gestures.PullGestureEndedEvent, (s, e) =>
{
InitComposition(ball!);
if (ballCompositionVisual != null)
{
ballCompositionVisual.Offset = defaultOffset;
}
});
void InitComposition(Control control)
{
if (ballCompositionVisual != null)
{
return;
}
ballCompositionVisual = ElementComposition.GetElementVisual(ball);
if (ballCompositionVisual != null)
{
var offsetAnimation = ballCompositionVisual.Compositor.CreateVector3KeyFrameAnimation();
offsetAnimation.Target = "Offset";
offsetAnimation.InsertExpressionKeyFrame(1.0f, "this.FinalValue");
offsetAnimation.Duration = TimeSpan.FromMilliseconds(100);
var implicitAnimations = ballCompositionVisual.Compositor.CreateImplicitAnimationCollection();
implicitAnimations["Offset"] = offsetAnimation;
ballCompositionVisual.ImplicitAnimations = implicitAnimations;
}
}
}
}
}

117
samples/ControlCatalog/Pages/GesturePage.xaml

@ -0,0 +1,117 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
d:DesignHeight="800"
d:DesignWidth="400"
x:Class="ControlCatalog.Pages.GesturePage">
<StackPanel Orientation="Vertical"
Spacing="4">
<TextBlock FontWeight="Bold"
FontSize="18"
Margin="5">Pull Gexture (Touch / Pen)</TextBlock>
<TextBlock Margin="5">Pull from colored rectangles</TextBlock>
<Border>
<DockPanel HorizontalAlignment="Stretch"
ClipToBounds="True"
Margin="5"
Height="200">
<Border DockPanel.Dock="Top"
Margin="2"
Name="TopPullZone"
Background="Transparent"
BorderBrush="Red"
HorizontalAlignment="Stretch"
Height="50"
BorderThickness="1">
<Border.GestureRecognizers>
<PullGestureRecognizer PullDirection="TopToBottom"/>
</Border.GestureRecognizers>
<Border Width="10"
Height="10"
HorizontalAlignment="Center"
VerticalAlignment="Center"
CornerRadius="5"
Name="TopBall"
Background="Green"/>
</Border>
<Border DockPanel.Dock="Bottom"
BorderBrush="Green"
Margin="2"
Background="Transparent"
Name="BottomPullZone"
HorizontalAlignment="Stretch"
Height="50"
BorderThickness="1">
<Border.GestureRecognizers>
<PullGestureRecognizer PullDirection="BottomToTop"/>
</Border.GestureRecognizers>
<Border Width="10"
Name="BottomBall"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Height="10"
CornerRadius="5"
Background="Green"/>
</Border>
<Border DockPanel.Dock="Right"
Margin="2"
Background="Transparent"
Name="RightPullZone"
BorderBrush="Blue"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
Width="50"
BorderThickness="1">
<Border.GestureRecognizers>
<PullGestureRecognizer PullDirection="RightToLeft"/>
</Border.GestureRecognizers>
<Border Width="10"
Height="10"
Name="RightBall"
HorizontalAlignment="Center"
VerticalAlignment="Center"
CornerRadius="5"
Background="Green"/>
</Border>
<Border DockPanel.Dock="Left"
Margin="2"
Background="Transparent"
Name="LeftPullZone"
BorderBrush="Orange"
HorizontalAlignment="Left"
VerticalAlignment="Stretch"
Width="50"
BorderThickness="1">
<Border.GestureRecognizers>
<PullGestureRecognizer PullDirection="LeftToRight"/>
</Border.GestureRecognizers>
<Border Width="10"
Height="10"
Name="LeftBall"
HorizontalAlignment="Center"
VerticalAlignment="Center"
CornerRadius="5"
Background="Green"/>
</Border>
</DockPanel>
</Border>
<TextBlock FontWeight="Bold"
FontSize="18"
Margin="5">Pinch/Zoom Gexture (Multi Touch)</TextBlock>
<Border ClipToBounds="True">
<Image Stretch="UniformToFill"
Margin="5"
Name="PinchImage"
Source="/Assets/delicate-arch-896885_640.jpg">
<Image.GestureRecognizers>
<PinchGestureRecognizer/>
<ScrollGestureRecognizer CanHorizontallyScroll="True" CanVerticallyScroll="True"/>
</Image.GestureRecognizers>
</Image>
</Border>
<Button HorizontalAlignment="Center" Name="ResetButton">Reset</Button>
</StackPanel>
</UserControl>

2
samples/ControlCatalog/Pages/ImagePage.xaml.cs

@ -70,7 +70,7 @@ namespace ControlCatalog.Pages
3 => new PixelRect(new PixelPoint(bitmapWidth - cropSize.Width, 0), cropSize),
4 => new PixelRect(new PixelPoint(0, bitmapHeight - cropSize.Height), cropSize),
5 => new PixelRect(new PixelPoint(bitmapWidth - cropSize.Width, bitmapHeight - cropSize.Height), cropSize),
_ => PixelRect.Empty
_ => default
};
}

5
samples/interop/Direct3DInteropSample/App.paml

@ -1,5 +0,0 @@
<Application xmlns="https://github.com/avaloniaui">
<Application.Styles>
<SimpleTheme Mode="Light" />
</Application.Styles>
</Application>

21
samples/interop/Direct3DInteropSample/App.paml.cs

@ -1,21 +0,0 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
namespace Direct3DInteropSample
{
public class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
desktop.MainWindow = new MainWindow();
base.OnFrameworkInitializationCompleted();
}
}
}

32
samples/interop/Direct3DInteropSample/Direct3DInteropSample.csproj

@ -1,32 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net461</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SharpDX.Mathematics" Version="4.0.1" />
<PackageReference Include="SharpDX.D3DCompiler" Version="4.0.1" />
<Compile Update="**\*.paml.cs">
<DependentUpon>%(Filename)</DependentUpon>
</Compile>
<EmbeddedResource Include="**\*.paml">
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Remove="MiniCube.fx" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="MiniCube.fx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Avalonia.Themes.Simple\Avalonia.Themes.Simple.csproj" />
<ProjectReference Include="..\..\..\src\Windows\Avalonia.Direct2D1\Avalonia.Direct2D1.csproj" />
<ProjectReference Include="..\..\..\src\Windows\Avalonia.Win32\Avalonia.Win32.csproj" />
<ProjectReference Include="..\..\MiniMvvm\MiniMvvm.csproj" />
</ItemGroup>
<Import Project="..\..\..\build\Rx.props" />
<Import Project="..\..\..\build\ReferenceCoreLibraries.props" />
</Project>

283
samples/interop/Direct3DInteropSample/MainWindow.cs

@ -1,283 +0,0 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Direct2D1;
using Avalonia.Direct2D1.Media;
using Avalonia.Markup.Xaml;
using Avalonia.Platform;
using Avalonia.Rendering;
using SharpDX;
using SharpDX.D3DCompiler;
using SharpDX.Direct2D1;
using SharpDX.Direct3D;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using AlphaMode = SharpDX.Direct2D1.AlphaMode;
using Buffer = SharpDX.Direct3D11.Buffer;
using DeviceContext = SharpDX.Direct2D1.DeviceContext;
using Factory2 = SharpDX.DXGI.Factory2;
using InputElement = SharpDX.Direct3D11.InputElement;
using Matrix = SharpDX.Matrix;
using PixelFormat = SharpDX.Direct2D1.PixelFormat;
using Resource = SharpDX.Direct3D11.Resource;
namespace Direct3DInteropSample
{
public class MainWindow : Window
{
Texture2D _backBuffer;
RenderTargetView _renderView;
Texture2D _depthBuffer;
DepthStencilView _depthView;
private readonly SwapChain _swapChain;
private SwapChainDescription1 _desc;
private Matrix _proj = Matrix.Identity;
private readonly Matrix _view;
private Buffer _contantBuffer;
private DeviceContext _deviceContext;
private readonly MainWindowViewModel _model;
public MainWindow()
{
DataContext = _model = new MainWindowViewModel();
_desc = new SwapChainDescription1()
{
BufferCount = 1,
Width = (int)ClientSize.Width,
Height = (int)ClientSize.Height,
Format = Format.R8G8B8A8_UNorm,
SampleDescription = new SampleDescription(1, 0),
SwapEffect = SwapEffect.Discard,
Usage = Usage.RenderTargetOutput
};
using (var factory = Direct2D1Platform.DxgiDevice.Adapter.GetParent<Factory2>())
{
_swapChain = new SwapChain1(factory, Direct2D1Platform.DxgiDevice, PlatformImpl?.Handle.Handle ?? IntPtr.Zero, ref _desc);
}
_deviceContext = new DeviceContext(Direct2D1Platform.Direct2D1Device, DeviceContextOptions.None)
{
DotsPerInch = new Size2F(96, 96)
};
CreateMesh();
_view = Matrix.LookAtLH(new Vector3(0, 0, -5), new Vector3(0, 0, 0), Vector3.UnitY);
this.GetObservable(ClientSizeProperty).Subscribe(Resize);
Resize(ClientSize);
AvaloniaXamlLoader.Load(this);
Background = Avalonia.Media.Brushes.Transparent;
}
protected override void HandlePaint(Rect rect)
{
var viewProj = Matrix.Multiply(_view, _proj);
var context = Direct2D1Platform.Direct3D11Device.ImmediateContext;
// Clear views
context.ClearDepthStencilView(_depthView, DepthStencilClearFlags.Depth, 1.0f, 0);
context.ClearRenderTargetView(_renderView, Color.White);
// Update WorldViewProj Matrix
var worldViewProj = Matrix.RotationX((float)_model.RotationX) * Matrix.RotationY((float)_model.RotationY)
* Matrix.RotationZ((float)_model.RotationZ)
* Matrix.Scaling((float)_model.Zoom)
* viewProj;
worldViewProj.Transpose();
context.UpdateSubresource(ref worldViewProj, _contantBuffer);
// Draw the cube
context.Draw(36, 0);
base.HandlePaint(rect);
// Present!
_swapChain.Present(0, PresentFlags.None);
}
private void CreateMesh()
{
var device = Direct2D1Platform.Direct3D11Device;
// Compile Vertex and Pixel shaders
var vertexShaderByteCode = ShaderBytecode.CompileFromFile("MiniCube.fx", "VS", "vs_4_0");
var vertexShader = new VertexShader(device, vertexShaderByteCode);
var pixelShaderByteCode = ShaderBytecode.CompileFromFile("MiniCube.fx", "PS", "ps_4_0");
var pixelShader = new PixelShader(device, pixelShaderByteCode);
var signature = ShaderSignature.GetInputSignature(vertexShaderByteCode);
var inputElements = new[]
{
new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0)
};
// Layout from VertexShader input signature
var layout = new InputLayout(
device,
signature,
inputElements);
// Instantiate Vertex buffer from vertex data
var vertices = Buffer.Create(
device,
BindFlags.VertexBuffer,
new[]
{
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), // Front
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), // BACK
new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
new Vector4( 1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), // Top
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), // Bottom
new Vector4( 1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
new Vector4( 1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), // Left
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), // Right
new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
new Vector4( 1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
});
// Create Constant Buffer
_contantBuffer = new Buffer(device, Utilities.SizeOf<Matrix>(), ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
var context = Direct2D1Platform.Direct3D11Device.ImmediateContext;
// Prepare All the stages
context.InputAssembler.InputLayout = layout;
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertices, Utilities.SizeOf<Vector4>() * 2, 0));
context.VertexShader.SetConstantBuffer(0, _contantBuffer);
context.VertexShader.Set(vertexShader);
context.PixelShader.Set(pixelShader);
}
private void Resize(Size size)
{
Utilities.Dispose(ref _deviceContext);
Utilities.Dispose(ref _backBuffer);
Utilities.Dispose(ref _renderView);
Utilities.Dispose(ref _depthBuffer);
Utilities.Dispose(ref _depthView);
var context = Direct2D1Platform.Direct3D11Device.ImmediateContext;
// Resize the backbuffer
_swapChain.ResizeBuffers(0, 0, 0, Format.Unknown, SwapChainFlags.None);
// Get the backbuffer from the swapchain
_backBuffer = Resource.FromSwapChain<Texture2D>(_swapChain, 0);
// Renderview on the backbuffer
_renderView = new RenderTargetView(Direct2D1Platform.Direct3D11Device, _backBuffer);
// Create the depth buffer
_depthBuffer = new Texture2D(
Direct2D1Platform.Direct3D11Device,
new Texture2DDescription()
{
Format = Format.D32_Float_S8X24_UInt,
ArraySize = 1,
MipLevels = 1,
Width = (int)size.Width,
Height = (int)size.Height,
SampleDescription = new SampleDescription(1, 0),
Usage = ResourceUsage.Default,
BindFlags = BindFlags.DepthStencil,
CpuAccessFlags = CpuAccessFlags.None,
OptionFlags = ResourceOptionFlags.None
});
// Create the depth buffer view
_depthView = new DepthStencilView(Direct2D1Platform.Direct3D11Device, _depthBuffer);
// Setup targets and viewport for rendering
context.Rasterizer.SetViewport(new Viewport(0, 0, (int)size.Width, (int)size.Height, 0.0f, 1.0f));
context.OutputMerger.SetTargets(_depthView, _renderView);
// Setup new projection matrix with correct aspect ratio
_proj = Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, (float)(size.Width / size.Height), 0.1f, 100.0f);
using (var dxgiBackBuffer = _swapChain.GetBackBuffer<Surface>(0))
{
var renderTarget = new SharpDX.Direct2D1.RenderTarget(
Direct2D1Platform.Direct2D1Factory,
dxgiBackBuffer,
new RenderTargetProperties
{
DpiX = 96,
DpiY = 96,
Type = RenderTargetType.Default,
PixelFormat = new PixelFormat(
Format.Unknown,
AlphaMode.Premultiplied)
});
_deviceContext = renderTarget.QueryInterface<DeviceContext>();
renderTarget.Dispose();
}
}
private class D3DRenderTarget : IRenderTarget
{
private readonly MainWindow _window;
public D3DRenderTarget(MainWindow window)
{
_window = window;
}
public void Dispose()
{
}
public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer)
{
return new DrawingContextImpl(visualBrushRenderer, null, _window._deviceContext);
}
}
protected override IRenderTarget CreateRenderTarget() => new D3DRenderTarget(this);
}
}

14
samples/interop/Direct3DInteropSample/MainWindow.paml

@ -1,14 +0,0 @@
<Window xmlns="https://github.com/avaloniaui" Background="White" Title="Avalonia Direct3D Demo">
<Grid ColumnDefinitions="*,Auto" Margin="20">
<StackPanel Grid.Column="1" MinWidth="200">
<TextBlock>Rotation X</TextBlock>
<Slider Value="{Binding RotationX, Mode=TwoWay}" Maximum="10"/>
<TextBlock>Rotation Y</TextBlock>
<Slider Value="{Binding RotationY, Mode=TwoWay}" Maximum="10"/>
<TextBlock>Rotation Z</TextBlock>
<Slider Value="{Binding RotationZ, Mode=TwoWay}" Maximum="10"/>
<TextBlock>Zoom</TextBlock>
<Slider Value="{Binding Zoom, Mode=TwoWay}" Maximum="3" Minimum="0.5"/>
</StackPanel>
</Grid>
</Window>

45
samples/interop/Direct3DInteropSample/MainWindowViewModel.cs

@ -1,45 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MiniMvvm;
namespace Direct3DInteropSample
{
public class MainWindowViewModel : ViewModelBase
{
private double _rotationX;
public double RotationX
{
get { return _rotationX; }
set { this.RaiseAndSetIfChanged(ref _rotationX, value); }
}
private double _rotationY = 1;
public double RotationY
{
get { return _rotationY; }
set { this.RaiseAndSetIfChanged(ref _rotationY, value); }
}
private double _rotationZ = 2;
public double RotationZ
{
get { return _rotationZ; }
set { this.RaiseAndSetIfChanged(ref _rotationZ, value); }
}
private double _zoom = 1;
public double Zoom
{
get { return _zoom; }
set { this.RaiseAndSetIfChanged(ref _zoom, value); }
}
}
}

47
samples/interop/Direct3DInteropSample/MiniCube.fx

@ -1,47 +0,0 @@
// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
struct VS_IN
{
float4 pos : POSITION;
float4 col : COLOR;
};
struct PS_IN
{
float4 pos : SV_POSITION;
float4 col : COLOR;
};
float4x4 worldViewProj;
PS_IN VS( VS_IN input )
{
PS_IN output = (PS_IN)0;
output.pos = mul(input.pos, worldViewProj);
output.col = input.col;
return output;
}
float4 PS( PS_IN input ) : SV_Target
{
return input.col;
}

16
samples/interop/Direct3DInteropSample/Program.cs

@ -1,16 +0,0 @@
using Avalonia;
namespace Direct3DInteropSample
{
class Program
{
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.With(new Win32PlatformOptions { UseDeferredRendering = false })
.UseWin32()
.UseDirect2D1();
public static int Main(string[] args)
=> BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
}
}

2
src/Android/Avalonia.Android/AndroidInputMethod.cs

@ -167,7 +167,7 @@ namespace Avalonia.Android
}
}
public readonly struct ComposingRegion
public readonly record struct ComposingRegion
{
private readonly int _start = -1;
private readonly int _end = -1;

9
src/Android/Avalonia.Android/AndroidPlatform.cs

@ -32,6 +32,7 @@ namespace Avalonia.Android
public static AndroidPlatformOptions Options { get; private set; }
internal static Compositor Compositor { get; private set; }
internal static PlatformRenderInterfaceContextManager RenderInterface { get; private set; }
public static void Initialize()
{
@ -51,15 +52,19 @@ namespace Avalonia.Android
if (Options.UseGpu)
{
EglPlatformOpenGlInterface.TryInitialize();
EglPlatformGraphics.TryInitialize();
}
if (Options.UseCompositor)
{
Compositor = new Compositor(
AvaloniaLocator.Current.GetRequiredService<IRenderLoop>(),
AvaloniaLocator.Current.GetService<IPlatformOpenGlInterface>());
AvaloniaLocator.Current.GetService<IPlatformGraphics>());
}
else
RenderInterface =
new PlatformRenderInterfaceContextManager(AvaloniaLocator.Current
.GetService<IPlatformGraphics>());
}
}

32
src/Android/Avalonia.Android/OpenGL/GlPlatformSurface.cs

@ -1,32 +0,0 @@
using Avalonia.OpenGL;
using Avalonia.OpenGL.Egl;
using Avalonia.OpenGL.Surfaces;
namespace Avalonia.Android.OpenGL
{
internal sealed class GlPlatformSurface : EglGlPlatformSurfaceBase
{
private readonly EglPlatformOpenGlInterface _egl;
private readonly IEglWindowGlPlatformSurfaceInfo _info;
private GlPlatformSurface(EglPlatformOpenGlInterface egl, IEglWindowGlPlatformSurfaceInfo info)
{
_egl = egl;
_info = info;
}
public override IGlPlatformSurfaceRenderTarget CreateGlRenderTarget() =>
new GlRenderTarget(_egl, _info, _egl.CreateWindowSurface(_info.Handle), _info.Handle);
public static GlPlatformSurface TryCreate(IEglWindowGlPlatformSurfaceInfo info)
{
var feature = AvaloniaLocator.Current.GetService<IPlatformOpenGlInterface>();
if (feature is EglPlatformOpenGlInterface egl)
{
return new GlPlatformSurface(egl, info);
}
return null;
}
}
}

30
src/Android/Avalonia.Android/OpenGL/GlRenderTarget.cs

@ -1,30 +0,0 @@
using System;
using Avalonia.OpenGL.Egl;
using Avalonia.OpenGL.Surfaces;
namespace Avalonia.Android.OpenGL
{
internal sealed class GlRenderTarget : EglPlatformSurfaceRenderTargetBase, IGlPlatformSurfaceRenderTargetWithCorruptionInfo
{
private readonly EglGlPlatformSurfaceBase.IEglWindowGlPlatformSurfaceInfo _info;
private readonly EglSurface _surface;
private readonly IntPtr _handle;
public GlRenderTarget(
EglPlatformOpenGlInterface egl,
EglGlPlatformSurfaceBase.IEglWindowGlPlatformSurfaceInfo info,
EglSurface surface,
IntPtr handle)
: base(egl)
{
_info = info;
_surface = surface;
_handle = handle;
}
public bool IsCorrupted => _handle != _info.Handle;
public override IGlPlatformSurfaceRenderingSession BeginDraw() => BeginDraw(_surface, _info);
}
}

2
src/Android/Avalonia.Android/Platform/SkiaPlatform/AndroidFramebuffer.cs

@ -96,12 +96,14 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public IntPtr bits;
// Do not touch.
#pragma warning disable CA1823 // Avoid unused private fields
uint reserved1;
uint reserved2;
uint reserved3;
uint reserved4;
uint reserved5;
uint reserved6;
#pragma warning restore CA1823 // Avoid unused private fields
}
}
}

18
src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@ -8,7 +8,6 @@ using Android.Runtime;
using Android.Text;
using Android.Views;
using Android.Views.InputMethods;
using Avalonia.Android.OpenGL;
using Avalonia.Android.Platform.Specific;
using Avalonia.Android.Platform.Specific.Helpers;
using Avalonia.Android.Platform.Storage;
@ -30,7 +29,7 @@ using AndroidRect = Android.Graphics.Rect;
namespace Avalonia.Android.Platform.SkiaPlatform
{
class TopLevelImpl : IAndroidView, ITopLevelImpl, EglGlPlatformSurfaceBase.IEglWindowGlPlatformSurfaceInfo,
class TopLevelImpl : IAndroidView, ITopLevelImpl, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo,
ITopLevelImplWithTextInputMethod, ITopLevelImplWithNativeControlHost, ITopLevelImplWithStorageProvider
{
private readonly IGlPlatformSurface _gl;
@ -47,7 +46,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
_textInputMethod = new AndroidInputMethod<ViewImpl>(_view);
_keyboardHelper = new AndroidKeyboardEventsHelper<TopLevelImpl>(this);
_pointerHelper = new AndroidMotionEventsHelper(this);
_gl = GlPlatformSurface.TryCreate(this);
_gl = new EglGlPlatformSurface(this);
_framebuffer = new FramebufferManager(this);
RenderScaling = _view.Scaling;
@ -106,10 +105,15 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public IRenderer CreateRenderer(IRenderRoot root) =>
AndroidPlatform.Options.UseCompositor
? new CompositingRenderer(root, AndroidPlatform.Compositor)
? new CompositingRenderer(root, AndroidPlatform.Compositor, () => Surfaces)
: AndroidPlatform.Options.UseDeferredRendering
? new DeferredRenderer(root, AvaloniaLocator.Current.GetRequiredService<IRenderLoop>()) { RenderOnlyOnRenderThread = true }
: new ImmediateRenderer((Visual)root);
? new DeferredRenderer(root, AvaloniaLocator.Current.GetRequiredService<IRenderLoop>(),
() => AndroidPlatform.RenderInterface.CreateRenderTarget(Surfaces),
AndroidPlatform.RenderInterface)
{ RenderOnlyOnRenderThread = true }
: new ImmediateRenderer((Visual)root,
() => AndroidPlatform.RenderInterface.CreateRenderTarget(Surfaces),
AndroidPlatform.RenderInterface);
public virtual void Hide()
{
@ -283,7 +287,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels => new AcrylicPlatformCompensationLevels(1, 1, 1);
IntPtr EglGlPlatformSurfaceBase.IEglWindowGlPlatformSurfaceInfo.Handle => ((IPlatformHandle)_view).Handle;
IntPtr EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.Handle => ((IPlatformHandle)_view).Handle;
public PixelSize Size => _view.Size;

1
src/Avalonia.Base/Animation/AnimationInstance`1.cs

@ -5,7 +5,6 @@ using Avalonia.Animation.Animators;
using Avalonia.Animation.Utils;
using Avalonia.Data;
using Avalonia.Reactive;
using JetBrains.Annotations;
namespace Avalonia.Animation
{

11
src/Avalonia.Base/Animation/Cue.cs

@ -8,7 +8,7 @@ namespace Avalonia.Animation
/// Determines the time index for a <see cref="KeyFrame"/>.
/// </summary>
[TypeConverter(typeof(CueTypeConverter))]
public readonly struct Cue : IEquatable<Cue>, IEquatable<double>
public readonly record struct Cue : IEquatable<Cue>, IEquatable<double>
{
/// <summary>
/// The normalized percent value, ranging from 0.0 to 1.0
@ -49,15 +49,6 @@ namespace Avalonia.Animation
}
}
/// <summary>
/// Checks for equality between two <see cref="Cue"/>s.
/// </summary>
/// <param name="other">The second cue.</param>
public bool Equals(Cue other)
{
return CueValue == other.CueValue;
}
/// <summary>
/// Checks for equality between a <see cref="Cue"/>
/// and a <see cref="double"/> value.

1
src/Avalonia.Base/Avalonia.Base.csproj

@ -15,7 +15,6 @@
<Import Project="..\..\build\Base.props" />
<Import Project="..\..\build\Binding.props" />
<Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\JetBrains.Annotations.props" />
<Import Project="..\..\build\System.Memory.props" />
<Import Project="..\..\build\ApiDiff.props" />
<Import Project="..\..\build\NullableEnable.props" />

34
src/Avalonia.Base/Contract.cs

@ -1,34 +0,0 @@
using System;
using System.Runtime.CompilerServices;
using JetBrains.Annotations;
namespace Avalonia
{
/// <summary>
/// A stub of Code Contract's Contract class.
/// </summary>
/// <remarks>
/// It would be nice to use Code Contracts on Avalonia but last time I tried it slowed things
/// to a crawl and often crashed. Instead use the same signature for checking preconditions
/// in the hope that it might become usable at some point.
/// </remarks>
public static class Contract
{
/// <summary>
/// Specifies a precondition.
/// </summary>
/// <typeparam name="TException">
/// The exception to throw if <paramref name="condition"/> is false.
/// </typeparam>
/// <param name="condition">The precondition.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[ContractAnnotation("condition:false=>stop")]
public static void Requires<TException>(bool condition) where TException : Exception, new()
{
if (!condition)
{
throw new TException();
}
}
}
}

9
src/Avalonia.Base/CornerRadius.cs

@ -61,9 +61,13 @@ namespace Avalonia
public double BottomLeft { get; }
/// <summary>
/// Gets a value indicating whether all corner radii are set to 0.
/// Gets a value indicating whether the instance has default values (all corner radii are set to 0).
/// </summary>
public bool IsEmpty => TopLeft.Equals(0) && IsUniform;
public bool IsDefault => TopLeft == 0 && TopRight == 0 && BottomLeft == 0 && BottomRight == 0;
/// <inheritdoc cref="IsDefault"/>
[Obsolete("Use IsDefault instead.")]
public bool IsEmpty => IsDefault;
/// <summary>
/// Gets a value indicating whether all corner radii are equal.
@ -79,7 +83,6 @@ namespace Avalonia
{
// ReSharper disable CompareOfFloatsByEqualityOperator
return TopLeft == other.TopLeft &&
TopRight == other.TopRight &&
BottomRight == other.BottomRight &&
BottomLeft == other.BottomLeft;

2
src/Avalonia.Base/Data/BindingValue.cs

@ -80,7 +80,7 @@ namespace Avalonia.Data
/// - For an unset value, use <see cref="Unset"/> or simply `default`
/// - For other types, call one of the static factory methods
/// </remarks>
public readonly struct BindingValue<T>
public readonly record struct BindingValue<T>
{
private readonly T _value;

2
src/Avalonia.Base/Data/Core/ExpressionNode.cs

@ -4,8 +4,6 @@ namespace Avalonia.Data.Core
{
public abstract class ExpressionNode
{
private static readonly object CacheInvalid = new object();
protected static readonly WeakReference<object?> UnsetReference =
new WeakReference<object?>(AvaloniaProperty.UnsetValue);

2
src/Avalonia.Base/Data/Core/ExpressionObserver.cs

@ -49,8 +49,6 @@ namespace Avalonia.Data.Core
new TaskStreamPlugin(),
new ObservableStreamPlugin(),
};
private static readonly object UninitializedValue = new object();
private readonly ExpressionNode _node;
private object? _root;
private Func<object?>? _rootGetter;

4
src/Avalonia.Base/Data/InstancedBinding.cs

@ -28,11 +28,9 @@ namespace Avalonia.Data
/// </remarks>
public InstancedBinding(ISubject<object?> subject, BindingMode mode, BindingPriority priority)
{
Contract.Requires<ArgumentNullException>(subject != null);
Mode = mode;
Priority = priority;
Value = subject;
Value = subject ?? throw new ArgumentNullException(nameof(subject));
}
private InstancedBinding(object? value, BindingMode mode, BindingPriority priority)

128
src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs

@ -0,0 +1,128 @@
using Avalonia.Input.GestureRecognizers;
namespace Avalonia.Input
{
public class PinchGestureRecognizer : StyledElement, IGestureRecognizer
{
private IInputElement? _target;
private IGestureRecognizerActionsDispatcher? _actions;
private float _initialDistance;
private IPointer? _firstContact;
private Point _firstPoint;
private IPointer? _secondContact;
private Point _secondPoint;
private Point _origin;
public void Initialize(IInputElement target, IGestureRecognizerActionsDispatcher actions)
{
_target = target;
_actions = actions;
}
private void OnPointerPressed(object? sender, PointerPressedEventArgs e)
{
PointerPressed(e);
}
private void OnPointerReleased(object? sender, PointerReleasedEventArgs e)
{
PointerReleased(e);
}
public void PointerCaptureLost(IPointer pointer)
{
RemoveContact(pointer);
}
public void PointerMoved(PointerEventArgs e)
{
if (_target != null && _target is Visual visual)
{
if(_firstContact == e.Pointer)
{
_firstPoint = e.GetPosition(visual);
}
else if (_secondContact == e.Pointer)
{
_secondPoint = e.GetPosition(visual);
}
else
{
return;
}
if (_firstContact != null && _secondContact != null)
{
var distance = GetDistance(_firstPoint, _secondPoint);
var scale = distance / _initialDistance;
_target?.RaiseEvent(new PinchEventArgs(scale, _origin));
}
}
}
public void PointerPressed(PointerPressedEventArgs e)
{
if (_target != null && _target is Visual visual && (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen))
{
if (_firstContact == null)
{
_firstContact = e.Pointer;
_firstPoint = e.GetPosition(visual);
return;
}
else if (_secondContact == null && _firstContact != e.Pointer)
{
_secondContact = e.Pointer;
_secondPoint = e.GetPosition(visual);
}
else
{
return;
}
if (_firstContact != null && _secondContact != null)
{
_initialDistance = GetDistance(_firstPoint, _secondPoint);
_origin = new Point((_firstPoint.X + _secondPoint.X) / 2.0f, (_firstPoint.Y + _secondPoint.Y) / 2.0f);
_actions!.Capture(_firstContact, this);
_actions!.Capture(_secondContact, this);
}
}
}
public void PointerReleased(PointerReleasedEventArgs e)
{
RemoveContact(e.Pointer);
}
private void RemoveContact(IPointer pointer)
{
if (_firstContact == pointer || _secondContact == pointer)
{
if (_secondContact == pointer)
{
_secondContact = null;
}
if (_firstContact == pointer)
{
_firstContact = _secondContact;
_secondContact = null;
}
_target?.RaiseEvent(new PinchEndedEventArgs());
}
}
private float GetDistance(Point a, Point b)
{
var length = _secondPoint - _firstPoint;
return (float)new Vector(length.X, length.Y).Length;
}
}
}

33
src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs

@ -1,15 +1,19 @@
using Avalonia.Input.GestureRecognizers;
using System;
using Avalonia.Input.GestureRecognizers;
namespace Avalonia.Input
{
public class PullGestureRecognizer : StyledElement, IGestureRecognizer
{
internal static int MinPullDetectionSize = 50;
private IInputElement? _target;
private IGestureRecognizerActionsDispatcher? _actions;
private Point _initialPosition;
private int _gestureId;
private IPointer? _tracking;
private PullDirection _pullDirection;
private bool _pullInProgress;
/// <summary>
/// Defines the <see cref="PullDirection"/> property.
@ -31,23 +35,12 @@ namespace Avalonia.Input
PullDirection = pullDirection;
}
public PullGestureRecognizer() { }
public void Initialize(IInputElement target, IGestureRecognizerActionsDispatcher actions)
{
_target = target;
_actions = actions;
_target?.AddHandler(InputElement.PointerPressedEvent, OnPointerPressed, Interactivity.RoutingStrategies.Tunnel | Interactivity.RoutingStrategies.Bubble);
_target?.AddHandler(InputElement.PointerReleasedEvent, OnPointerReleased, Interactivity.RoutingStrategies.Tunnel | Interactivity.RoutingStrategies.Bubble);
}
private void OnPointerPressed(object? sender, PointerPressedEventArgs e)
{
PointerPressed(e);
}
private void OnPointerReleased(object? sender, PointerReleasedEventArgs e)
{
PointerReleased(e);
}
public void PointerCaptureLost(IPointer pointer)
@ -94,6 +87,7 @@ namespace Avalonia.Input
break;
}
_pullInProgress = true;
_target?.RaiseEvent(new PullGestureEventArgs(_gestureId, delta, PullDirection));
}
}
@ -111,16 +105,16 @@ namespace Avalonia.Input
switch (PullDirection)
{
case PullDirection.TopToBottom:
canPull = position.Y < bounds.Height * 0.1;
canPull = position.Y < Math.Max(MinPullDetectionSize, bounds.Height * 0.1);
break;
case PullDirection.BottomToTop:
canPull = position.Y > bounds.Height - (bounds.Height * 0.1);
canPull = position.Y > Math.Min(bounds.Height - MinPullDetectionSize, bounds.Height - (bounds.Height * 0.1));
break;
case PullDirection.LeftToRight:
canPull = position.X < bounds.Width * 0.1;
canPull = position.X < Math.Max(MinPullDetectionSize, bounds.Width * 0.1);
break;
case PullDirection.RightToLeft:
canPull = position.X > bounds.Width - (bounds.Width * 0.1);
canPull = position.X > Math.Min(bounds.Width - MinPullDetectionSize, bounds.Width - (bounds.Width * 0.1));
break;
}
@ -135,7 +129,7 @@ namespace Avalonia.Input
public void PointerReleased(PointerReleasedEventArgs e)
{
if (_tracking == e.Pointer)
if (_tracking == e.Pointer && _pullInProgress)
{
EndPull();
}
@ -145,6 +139,7 @@ namespace Avalonia.Input
{
_tracking = null;
_initialPosition = default;
_pullInProgress = false;
_target?.RaiseEvent(new PullGestureEndedEventArgs(_gestureId, PullDirection));
}

22
src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs

@ -16,6 +16,7 @@ namespace Avalonia.Input.GestureRecognizers
private bool _canHorizontallyScroll;
private bool _canVerticallyScroll;
private int _gestureId;
private int _scrollStartDistance = 30;
// Movement per second
private Vector _inertia;
@ -38,6 +39,15 @@ namespace Avalonia.Input.GestureRecognizers
nameof(CanVerticallyScroll),
o => o.CanVerticallyScroll,
(o, v) => o.CanVerticallyScroll = v);
/// <summary>
/// Defines the <see cref="ScrollStartDistance"/> property.
/// </summary>
public static readonly DirectProperty<ScrollGestureRecognizer, int> ScrollStartDistanceProperty =
AvaloniaProperty.RegisterDirect<ScrollGestureRecognizer, int>(
nameof(ScrollStartDistance),
o => o.ScrollStartDistance,
(o, v) => o.ScrollStartDistance = v);
/// <summary>
/// Gets or sets a value indicating whether the content can be scrolled horizontally.
@ -56,6 +66,15 @@ namespace Avalonia.Input.GestureRecognizers
get => _canVerticallyScroll;
set => SetAndRaise(CanVerticallyScrollProperty, ref _canVerticallyScroll, value);
}
/// <summary>
/// Gets or sets a value indicating the distance the pointer moves before scrolling is started
/// </summary>
public int ScrollStartDistance
{
get => _scrollStartDistance;
set => SetAndRaise(ScrollStartDistanceProperty, ref _scrollStartDistance, value);
}
public void Initialize(IInputElement target, IGestureRecognizerActionsDispatcher actions)
@ -75,9 +94,6 @@ namespace Avalonia.Input.GestureRecognizers
_trackedRootPoint = e.GetPosition((Visual?)_target);
}
}
// Arbitrary chosen value, probably need to move that to platform settings or something
private const double ScrollStartDistance = 30;
// Pixels per second speed that is considered to be the stop of inertial scroll
private const double InertialScrollSpeedEnd = 5;

8
src/Avalonia.Base/Input/Gestures.cs

@ -46,6 +46,14 @@ namespace Avalonia.Input
private static readonly WeakReference<object?> s_lastPress = new WeakReference<object?>(null);
private static Point s_lastPressPoint;
public static readonly RoutedEvent<PinchEventArgs> PinchEvent =
RoutedEvent.Register<PinchEventArgs>(
"PinchEvent", RoutingStrategies.Bubble, typeof(Gestures));
public static readonly RoutedEvent<PinchEndedEventArgs> PinchEndedEvent =
RoutedEvent.Register<PinchEndedEventArgs>(
"PinchEndedEvent", RoutingStrategies.Bubble, typeof(Gestures));
public static readonly RoutedEvent<PullGestureEventArgs> PullGestureEvent =
RoutedEvent.Register<PullGestureEventArgs>(
"PullGesture", RoutingStrategies.Bubble, typeof(Gestures));

2
src/Avalonia.Base/Input/KeyEventArgs.cs

@ -5,7 +5,7 @@ namespace Avalonia.Input
{
public class KeyEventArgs : RoutedEventArgs
{
internal KeyEventArgs()
public KeyEventArgs()
{
}

24
src/Avalonia.Base/Input/PinchEventArgs.cs

@ -0,0 +1,24 @@
using Avalonia.Interactivity;
namespace Avalonia.Input
{
public class PinchEventArgs : RoutedEventArgs
{
public PinchEventArgs(double scale, Point scaleOrigin) : base(Gestures.PinchEvent)
{
Scale = scale;
ScaleOrigin = scaleOrigin;
}
public double Scale { get; } = 1;
public Point ScaleOrigin { get; }
}
public class PinchEndedEventArgs : RoutedEventArgs
{
public PinchEndedEventArgs() : base(Gestures.PinchEndedEvent)
{
}
}
}

4
src/Avalonia.Base/Input/PointerPoint.cs

@ -5,7 +5,7 @@ namespace Avalonia.Input
/// <summary>
/// Provides basic properties for the input pointer associated with a single mouse, pen/stylus, or touch contact.
/// </summary>
public struct PointerPoint
public record struct PointerPoint
{
public PointerPoint(IPointer pointer, Point position, PointerPointProperties properties)
{
@ -33,7 +33,7 @@ namespace Avalonia.Input
/// <summary>
/// Provides extended properties for a PointerPoint object.
/// </summary>
public struct PointerPointProperties
public record struct PointerPointProperties
{
/// <summary>
/// Gets a value that indicates whether the pointer input was triggered by the primary action mode of an input device.

6
src/Avalonia.Base/Input/Raw/RawInputEventArgs.cs

@ -21,11 +21,9 @@ namespace Avalonia.Input.Raw
/// <param name="root">The root from which the event originates.</param>
public RawInputEventArgs(IInputDevice device, ulong timestamp, IInputRoot root)
{
device = device ?? throw new ArgumentNullException(nameof(device));
Device = device;
Device = device ?? throw new ArgumentNullException(nameof(device));
Timestamp = timestamp;
Root = root;
Root = root ?? throw new ArgumentNullException(nameof(root));
}
/// <summary>

8
src/Avalonia.Base/Input/Raw/RawPointerEventArgs.cs

@ -53,9 +53,6 @@ namespace Avalonia.Input.Raw
RawInputModifiers inputModifiers)
: base(device, timestamp, root)
{
Contract.Requires<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(root != null);
Point = new RawPointerPoint();
Position = position;
Type = type;
@ -80,9 +77,6 @@ namespace Avalonia.Input.Raw
RawInputModifiers inputModifiers)
: base(device, timestamp, root)
{
Contract.Requires<ArgumentNullException>(device != null);
Contract.Requires<ArgumentNullException>(root != null);
Point = point;
Type = type;
InputModifiers = inputModifiers;
@ -130,7 +124,7 @@ namespace Avalonia.Input.Raw
internal IInputElement? InputHitTestResult { get; set; }
}
public struct RawPointerPoint
public record struct RawPointerPoint
{
/// <summary>
/// Pointer position, in client DIPs.

2
src/Avalonia.Base/Input/TextInput/ITextInputMethodClient.cs

@ -46,7 +46,7 @@ namespace Avalonia.Input.TextInput
void SelectInSurroundingText(int start, int end);
}
public struct TextInputMethodSurroundingText
public record struct TextInputMethodSurroundingText
{
public string Text { get; set; }
public int CursorOffset { get; set; }

2
src/Avalonia.Base/Input/TextInputEventArgs.cs

@ -4,7 +4,7 @@ namespace Avalonia.Input
{
public class TextInputEventArgs : RoutedEventArgs
{
internal TextInputEventArgs()
public TextInputEventArgs()
{
}

2
src/Avalonia.Base/Logging/ParametrizedLogger.cs

@ -5,7 +5,7 @@ namespace Avalonia.Logging
/// <summary>
/// Logger sink parametrized for given logging level.
/// </summary>
public readonly struct ParametrizedLogger
public readonly record struct ParametrizedLogger
{
private readonly ILogSink _sink;
private readonly LogEventLevel _level;

2
src/Avalonia.Base/Matrix.cs

@ -571,7 +571,7 @@ namespace Avalonia
return true;
}
public struct Decomposed
public record struct Decomposed
{
public Vector Translate;
public Vector Scale;

17
src/Avalonia.Base/Media/BoxShadow.cs

@ -45,7 +45,14 @@ namespace Avalonia.Media
}
}
public bool IsEmpty => OffsetX == 0 && OffsetY == 0 && Blur == 0 && Spread == 0;
/// <summary>
/// Gets a value indicating whether the instance has default values.
/// </summary>
public bool IsDefault => OffsetX == 0 && OffsetY == 0 && Blur == 0 && Spread == 0;
/// <inheritdoc cref="IsDefault"/>
[Obsolete("Use IsDefault instead.")]
public bool IsEmpty => IsDefault;
private readonly static char[] s_Separator = new char[] { ' ', '\t' };
@ -82,7 +89,7 @@ namespace Avalonia.Media
{
var sb = StringBuilderCache.Acquire();
if (IsEmpty)
if (IsDefault)
{
return "none";
}
@ -171,5 +178,11 @@ namespace Avalonia.Media
public Rect TransformBounds(in Rect rect)
=> IsInset ? rect : rect.Translate(new Vector(OffsetX, OffsetY)).Inflate(Spread + Blur);
public static bool operator ==(BoxShadow left, BoxShadow right) =>
left.Equals(right);
public static bool operator !=(BoxShadow left, BoxShadow right) =>
!(left == right);
}
}

12
src/Avalonia.Base/Media/BoxShadows.cs

@ -21,7 +21,7 @@ namespace Avalonia.Media
{
_first = shadow;
_list = null;
Count = _first.IsEmpty ? 0 : 1;
Count = _first.IsDefault ? 0 : 1;
}
public BoxShadows(BoxShadow first, BoxShadow[] rest)
@ -62,7 +62,9 @@ namespace Avalonia.Media
}
[EditorBrowsable(EditorBrowsableState.Never)]
#pragma warning disable CA1815 // Override equals and operator equals on value types
public struct BoxShadowsEnumerator
#pragma warning restore CA1815 // Override equals and operator equals on value types
{
private int _index;
private BoxShadows _shadows;
@ -118,7 +120,7 @@ namespace Avalonia.Media
get
{
foreach(var boxShadow in this)
if (!boxShadow.IsEmpty && boxShadow.IsInset)
if (!boxShadow.IsDefault && boxShadow.IsInset)
return true;
return false;
}
@ -149,5 +151,11 @@ namespace Avalonia.Media
return hashCode;
}
}
public static bool operator ==(BoxShadows left, BoxShadows right) =>
left.Equals(right);
public static bool operator !=(BoxShadows left, BoxShadows right) =>
!(left == right);
}
}

5
src/Avalonia.Base/Media/Brush.cs

@ -10,7 +10,7 @@ namespace Avalonia.Media
/// Describes how an area is painted.
/// </summary>
[TypeConverter(typeof(BrushConverter))]
public abstract class Brush : Animatable, IMutableBrush
public abstract class Brush : Animatable
{
/// <summary>
/// Defines the <see cref="Opacity"/> property.
@ -92,9 +92,6 @@ namespace Avalonia.Media
throw new FormatException($"Invalid brush string: '{s}'.");
}
/// <inheritdoc/>
public abstract IBrush ToImmutable();
/// <summary>
/// Marks a property as affecting the brush's visual representation.
/// </summary>

4
src/Avalonia.Base/Media/BrushExtensions.cs

@ -16,11 +16,11 @@ namespace Avalonia.Media
/// The result of calling <see cref="IMutableBrush.ToImmutable"/> if the brush is mutable,
/// otherwise <paramref name="brush"/>.
/// </returns>
public static IBrush ToImmutable(this IBrush brush)
public static IImmutableBrush ToImmutable(this IBrush brush)
{
_ = brush ?? throw new ArgumentNullException(nameof(brush));
return (brush as IMutableBrush)?.ToImmutable() ?? brush;
return (brush as IMutableBrush)?.ToImmutable() ?? (IImmutableBrush)brush;
}
/// <summary>

282
src/Avalonia.Base/Media/Brushes.cs

@ -8,706 +8,706 @@ namespace Avalonia.Media
/// <summary>
/// Gets an <see cref="Colors.AliceBlue"/> colored brush.
/// </summary>
public static ISolidColorBrush AliceBlue => KnownColor.AliceBlue.ToBrush();
public static IImmutableSolidColorBrush AliceBlue => KnownColor.AliceBlue.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.AntiqueWhite"/> colored brush.
/// </summary>
public static ISolidColorBrush AntiqueWhite => KnownColor.AntiqueWhite.ToBrush();
public static IImmutableSolidColorBrush AntiqueWhite => KnownColor.AntiqueWhite.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Aqua"/> colored brush.
/// </summary>
public static ISolidColorBrush Aqua => KnownColor.Aqua.ToBrush();
public static IImmutableSolidColorBrush Aqua => KnownColor.Aqua.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Aquamarine"/> colored brush.
/// </summary>
public static ISolidColorBrush Aquamarine => KnownColor.Aquamarine.ToBrush();
public static IImmutableSolidColorBrush Aquamarine => KnownColor.Aquamarine.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Azure"/> colored brush.
/// </summary>
public static ISolidColorBrush Azure => KnownColor.Azure.ToBrush();
public static IImmutableSolidColorBrush Azure => KnownColor.Azure.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Beige"/> colored brush.
/// </summary>
public static ISolidColorBrush Beige => KnownColor.Beige.ToBrush();
public static IImmutableSolidColorBrush Beige => KnownColor.Beige.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Bisque"/> colored brush.
/// </summary>
public static ISolidColorBrush Bisque => KnownColor.Bisque.ToBrush();
public static IImmutableSolidColorBrush Bisque => KnownColor.Bisque.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Black"/> colored brush.
/// </summary>
public static ISolidColorBrush Black => KnownColor.Black.ToBrush();
public static IImmutableSolidColorBrush Black => KnownColor.Black.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.BlanchedAlmond"/> colored brush.
/// </summary>
public static ISolidColorBrush BlanchedAlmond => KnownColor.BlanchedAlmond.ToBrush();
public static IImmutableSolidColorBrush BlanchedAlmond => KnownColor.BlanchedAlmond.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Blue"/> colored brush.
/// </summary>
public static ISolidColorBrush Blue => KnownColor.Blue.ToBrush();
public static IImmutableSolidColorBrush Blue => KnownColor.Blue.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.BlueViolet"/> colored brush.
/// </summary>
public static ISolidColorBrush BlueViolet => KnownColor.BlueViolet.ToBrush();
public static IImmutableSolidColorBrush BlueViolet => KnownColor.BlueViolet.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Brown"/> colored brush.
/// </summary>
public static ISolidColorBrush Brown => KnownColor.Brown.ToBrush();
public static IImmutableSolidColorBrush Brown => KnownColor.Brown.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.BurlyWood"/> colored brush.
/// </summary>
public static ISolidColorBrush BurlyWood => KnownColor.BurlyWood.ToBrush();
public static IImmutableSolidColorBrush BurlyWood => KnownColor.BurlyWood.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.CadetBlue"/> colored brush.
/// </summary>
public static ISolidColorBrush CadetBlue => KnownColor.CadetBlue.ToBrush();
public static IImmutableSolidColorBrush CadetBlue => KnownColor.CadetBlue.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Chartreuse"/> colored brush.
/// </summary>
public static ISolidColorBrush Chartreuse => KnownColor.Chartreuse.ToBrush();
public static IImmutableSolidColorBrush Chartreuse => KnownColor.Chartreuse.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Chocolate"/> colored brush.
/// </summary>
public static ISolidColorBrush Chocolate => KnownColor.Chocolate.ToBrush();
public static IImmutableSolidColorBrush Chocolate => KnownColor.Chocolate.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Coral"/> colored brush.
/// </summary>
public static ISolidColorBrush Coral => KnownColor.Coral.ToBrush();
public static IImmutableSolidColorBrush Coral => KnownColor.Coral.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.CornflowerBlue"/> colored brush.
/// </summary>
public static ISolidColorBrush CornflowerBlue => KnownColor.CornflowerBlue.ToBrush();
public static IImmutableSolidColorBrush CornflowerBlue => KnownColor.CornflowerBlue.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Cornsilk"/> colored brush.
/// </summary>
public static ISolidColorBrush Cornsilk => KnownColor.Cornsilk.ToBrush();
public static IImmutableSolidColorBrush Cornsilk => KnownColor.Cornsilk.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Crimson"/> colored brush.
/// </summary>
public static ISolidColorBrush Crimson => KnownColor.Crimson.ToBrush();
public static IImmutableSolidColorBrush Crimson => KnownColor.Crimson.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Cyan"/> colored brush.
/// </summary>
public static ISolidColorBrush Cyan => KnownColor.Cyan.ToBrush();
public static IImmutableSolidColorBrush Cyan => KnownColor.Cyan.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DarkBlue"/> colored brush.
/// </summary>
public static ISolidColorBrush DarkBlue => KnownColor.DarkBlue.ToBrush();
public static IImmutableSolidColorBrush DarkBlue => KnownColor.DarkBlue.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DarkCyan"/> colored brush.
/// </summary>
public static ISolidColorBrush DarkCyan => KnownColor.DarkCyan.ToBrush();
public static IImmutableSolidColorBrush DarkCyan => KnownColor.DarkCyan.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DarkGoldenrod"/> colored brush.
/// </summary>
public static ISolidColorBrush DarkGoldenrod => KnownColor.DarkGoldenrod.ToBrush();
public static IImmutableSolidColorBrush DarkGoldenrod => KnownColor.DarkGoldenrod.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DarkGray"/> colored brush.
/// </summary>
public static ISolidColorBrush DarkGray => KnownColor.DarkGray.ToBrush();
public static IImmutableSolidColorBrush DarkGray => KnownColor.DarkGray.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DarkGreen"/> colored brush.
/// </summary>
public static ISolidColorBrush DarkGreen => KnownColor.DarkGreen.ToBrush();
public static IImmutableSolidColorBrush DarkGreen => KnownColor.DarkGreen.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DarkKhaki"/> colored brush.
/// </summary>
public static ISolidColorBrush DarkKhaki => KnownColor.DarkKhaki.ToBrush();
public static IImmutableSolidColorBrush DarkKhaki => KnownColor.DarkKhaki.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DarkMagenta"/> colored brush.
/// </summary>
public static ISolidColorBrush DarkMagenta => KnownColor.DarkMagenta.ToBrush();
public static IImmutableSolidColorBrush DarkMagenta => KnownColor.DarkMagenta.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DarkOliveGreen"/> colored brush.
/// </summary>
public static ISolidColorBrush DarkOliveGreen => KnownColor.DarkOliveGreen.ToBrush();
public static IImmutableSolidColorBrush DarkOliveGreen => KnownColor.DarkOliveGreen.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DarkOrange"/> colored brush.
/// </summary>
public static ISolidColorBrush DarkOrange => KnownColor.DarkOrange.ToBrush();
public static IImmutableSolidColorBrush DarkOrange => KnownColor.DarkOrange.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DarkOrchid"/> colored brush.
/// </summary>
public static ISolidColorBrush DarkOrchid => KnownColor.DarkOrchid.ToBrush();
public static IImmutableSolidColorBrush DarkOrchid => KnownColor.DarkOrchid.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DarkRed"/> colored brush.
/// </summary>
public static ISolidColorBrush DarkRed => KnownColor.DarkRed.ToBrush();
public static IImmutableSolidColorBrush DarkRed => KnownColor.DarkRed.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DarkSalmon"/> colored brush.
/// </summary>
public static ISolidColorBrush DarkSalmon => KnownColor.DarkSalmon.ToBrush();
public static IImmutableSolidColorBrush DarkSalmon => KnownColor.DarkSalmon.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DarkSeaGreen"/> colored brush.
/// </summary>
public static ISolidColorBrush DarkSeaGreen => KnownColor.DarkSeaGreen.ToBrush();
public static IImmutableSolidColorBrush DarkSeaGreen => KnownColor.DarkSeaGreen.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DarkSlateBlue"/> colored brush.
/// </summary>
public static ISolidColorBrush DarkSlateBlue => KnownColor.DarkSlateBlue.ToBrush();
public static IImmutableSolidColorBrush DarkSlateBlue => KnownColor.DarkSlateBlue.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DarkSlateGray"/> colored brush.
/// </summary>
public static ISolidColorBrush DarkSlateGray => KnownColor.DarkSlateGray.ToBrush();
public static IImmutableSolidColorBrush DarkSlateGray => KnownColor.DarkSlateGray.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DarkTurquoise"/> colored brush.
/// </summary>
public static ISolidColorBrush DarkTurquoise => KnownColor.DarkTurquoise.ToBrush();
public static IImmutableSolidColorBrush DarkTurquoise => KnownColor.DarkTurquoise.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DarkViolet"/> colored brush.
/// </summary>
public static ISolidColorBrush DarkViolet => KnownColor.DarkViolet.ToBrush();
public static IImmutableSolidColorBrush DarkViolet => KnownColor.DarkViolet.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DeepPink"/> colored brush.
/// </summary>
public static ISolidColorBrush DeepPink => KnownColor.DeepPink.ToBrush();
public static IImmutableSolidColorBrush DeepPink => KnownColor.DeepPink.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DeepSkyBlue"/> colored brush.
/// </summary>
public static ISolidColorBrush DeepSkyBlue => KnownColor.DeepSkyBlue.ToBrush();
public static IImmutableSolidColorBrush DeepSkyBlue => KnownColor.DeepSkyBlue.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DimGray"/> colored brush.
/// </summary>
public static ISolidColorBrush DimGray => KnownColor.DimGray.ToBrush();
public static IImmutableSolidColorBrush DimGray => KnownColor.DimGray.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.DodgerBlue"/> colored brush.
/// </summary>
public static ISolidColorBrush DodgerBlue => KnownColor.DodgerBlue.ToBrush();
public static IImmutableSolidColorBrush DodgerBlue => KnownColor.DodgerBlue.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Firebrick"/> colored brush.
/// </summary>
public static ISolidColorBrush Firebrick => KnownColor.Firebrick.ToBrush();
public static IImmutableSolidColorBrush Firebrick => KnownColor.Firebrick.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.FloralWhite"/> colored brush.
/// </summary>
public static ISolidColorBrush FloralWhite => KnownColor.FloralWhite.ToBrush();
public static IImmutableSolidColorBrush FloralWhite => KnownColor.FloralWhite.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.ForestGreen"/> colored brush.
/// </summary>
public static ISolidColorBrush ForestGreen => KnownColor.ForestGreen.ToBrush();
public static IImmutableSolidColorBrush ForestGreen => KnownColor.ForestGreen.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Fuchsia"/> colored brush.
/// </summary>
public static ISolidColorBrush Fuchsia => KnownColor.Fuchsia.ToBrush();
public static IImmutableSolidColorBrush Fuchsia => KnownColor.Fuchsia.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Gainsboro"/> colored brush.
/// </summary>
public static ISolidColorBrush Gainsboro => KnownColor.Gainsboro.ToBrush();
public static IImmutableSolidColorBrush Gainsboro => KnownColor.Gainsboro.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.GhostWhite"/> colored brush.
/// </summary>
public static ISolidColorBrush GhostWhite => KnownColor.GhostWhite.ToBrush();
public static IImmutableSolidColorBrush GhostWhite => KnownColor.GhostWhite.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Gold"/> colored brush.
/// </summary>
public static ISolidColorBrush Gold => KnownColor.Gold.ToBrush();
public static IImmutableSolidColorBrush Gold => KnownColor.Gold.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Goldenrod"/> colored brush.
/// </summary>
public static ISolidColorBrush Goldenrod => KnownColor.Goldenrod.ToBrush();
public static IImmutableSolidColorBrush Goldenrod => KnownColor.Goldenrod.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Gray"/> colored brush.
/// </summary>
public static ISolidColorBrush Gray => KnownColor.Gray.ToBrush();
public static IImmutableSolidColorBrush Gray => KnownColor.Gray.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Green"/> colored brush.
/// </summary>
public static ISolidColorBrush Green => KnownColor.Green.ToBrush();
public static IImmutableSolidColorBrush Green => KnownColor.Green.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.GreenYellow"/> colored brush.
/// </summary>
public static ISolidColorBrush GreenYellow => KnownColor.GreenYellow.ToBrush();
public static IImmutableSolidColorBrush GreenYellow => KnownColor.GreenYellow.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Honeydew"/> colored brush.
/// </summary>
public static ISolidColorBrush Honeydew => KnownColor.Honeydew.ToBrush();
public static IImmutableSolidColorBrush Honeydew => KnownColor.Honeydew.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.HotPink"/> colored brush.
/// </summary>
public static ISolidColorBrush HotPink => KnownColor.HotPink.ToBrush();
public static IImmutableSolidColorBrush HotPink => KnownColor.HotPink.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.IndianRed"/> colored brush.
/// </summary>
public static ISolidColorBrush IndianRed => KnownColor.IndianRed.ToBrush();
public static IImmutableSolidColorBrush IndianRed => KnownColor.IndianRed.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Indigo"/> colored brush.
/// </summary>
public static ISolidColorBrush Indigo => KnownColor.Indigo.ToBrush();
public static IImmutableSolidColorBrush Indigo => KnownColor.Indigo.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Ivory"/> colored brush.
/// </summary>
public static ISolidColorBrush Ivory => KnownColor.Ivory.ToBrush();
public static IImmutableSolidColorBrush Ivory => KnownColor.Ivory.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Khaki"/> colored brush.
/// </summary>
public static ISolidColorBrush Khaki => KnownColor.Khaki.ToBrush();
public static IImmutableSolidColorBrush Khaki => KnownColor.Khaki.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Lavender"/> colored brush.
/// </summary>
public static ISolidColorBrush Lavender => KnownColor.Lavender.ToBrush();
public static IImmutableSolidColorBrush Lavender => KnownColor.Lavender.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.LavenderBlush"/> colored brush.
/// </summary>
public static ISolidColorBrush LavenderBlush => KnownColor.LavenderBlush.ToBrush();
public static IImmutableSolidColorBrush LavenderBlush => KnownColor.LavenderBlush.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.LawnGreen"/> colored brush.
/// </summary>
public static ISolidColorBrush LawnGreen => KnownColor.LawnGreen.ToBrush();
public static IImmutableSolidColorBrush LawnGreen => KnownColor.LawnGreen.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.LemonChiffon"/> colored brush.
/// </summary>
public static ISolidColorBrush LemonChiffon => KnownColor.LemonChiffon.ToBrush();
public static IImmutableSolidColorBrush LemonChiffon => KnownColor.LemonChiffon.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.LightBlue"/> colored brush.
/// </summary>
public static ISolidColorBrush LightBlue => KnownColor.LightBlue.ToBrush();
public static IImmutableSolidColorBrush LightBlue => KnownColor.LightBlue.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.LightCoral"/> colored brush.
/// </summary>
public static ISolidColorBrush LightCoral => KnownColor.LightCoral.ToBrush();
public static IImmutableSolidColorBrush LightCoral => KnownColor.LightCoral.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.LightCyan"/> colored brush.
/// </summary>
public static ISolidColorBrush LightCyan => KnownColor.LightCyan.ToBrush();
public static IImmutableSolidColorBrush LightCyan => KnownColor.LightCyan.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.LightGoldenrodYellow"/> colored brush.
/// </summary>
public static ISolidColorBrush LightGoldenrodYellow => KnownColor.LightGoldenrodYellow.ToBrush();
public static IImmutableSolidColorBrush LightGoldenrodYellow => KnownColor.LightGoldenrodYellow.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.LightGray"/> colored brush.
/// </summary>
public static ISolidColorBrush LightGray => KnownColor.LightGray.ToBrush();
public static IImmutableSolidColorBrush LightGray => KnownColor.LightGray.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.LightGreen"/> colored brush.
/// </summary>
public static ISolidColorBrush LightGreen => KnownColor.LightGreen.ToBrush();
public static IImmutableSolidColorBrush LightGreen => KnownColor.LightGreen.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.LightPink"/> colored brush.
/// </summary>
public static ISolidColorBrush LightPink => KnownColor.LightPink.ToBrush();
public static IImmutableSolidColorBrush LightPink => KnownColor.LightPink.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.LightSalmon"/> colored brush.
/// </summary>
public static ISolidColorBrush LightSalmon => KnownColor.LightSalmon.ToBrush();
public static IImmutableSolidColorBrush LightSalmon => KnownColor.LightSalmon.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.LightSeaGreen"/> colored brush.
/// </summary>
public static ISolidColorBrush LightSeaGreen => KnownColor.LightSeaGreen.ToBrush();
public static IImmutableSolidColorBrush LightSeaGreen => KnownColor.LightSeaGreen.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.LightSkyBlue"/> colored brush.
/// </summary>
public static ISolidColorBrush LightSkyBlue => KnownColor.LightSkyBlue.ToBrush();
public static IImmutableSolidColorBrush LightSkyBlue => KnownColor.LightSkyBlue.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.LightSlateGray"/> colored brush.
/// </summary>
public static ISolidColorBrush LightSlateGray => KnownColor.LightSlateGray.ToBrush();
public static IImmutableSolidColorBrush LightSlateGray => KnownColor.LightSlateGray.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.LightSteelBlue"/> colored brush.
/// </summary>
public static ISolidColorBrush LightSteelBlue => KnownColor.LightSteelBlue.ToBrush();
public static IImmutableSolidColorBrush LightSteelBlue => KnownColor.LightSteelBlue.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.LightYellow"/> colored brush.
/// </summary>
public static ISolidColorBrush LightYellow => KnownColor.LightYellow.ToBrush();
public static IImmutableSolidColorBrush LightYellow => KnownColor.LightYellow.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Lime"/> colored brush.
/// </summary>
public static ISolidColorBrush Lime => KnownColor.Lime.ToBrush();
public static IImmutableSolidColorBrush Lime => KnownColor.Lime.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.LimeGreen"/> colored brush.
/// </summary>
public static ISolidColorBrush LimeGreen => KnownColor.LimeGreen.ToBrush();
public static IImmutableSolidColorBrush LimeGreen => KnownColor.LimeGreen.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Linen"/> colored brush.
/// </summary>
public static ISolidColorBrush Linen => KnownColor.Linen.ToBrush();
public static IImmutableSolidColorBrush Linen => KnownColor.Linen.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Magenta"/> colored brush.
/// </summary>
public static ISolidColorBrush Magenta => KnownColor.Magenta.ToBrush();
public static IImmutableSolidColorBrush Magenta => KnownColor.Magenta.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Maroon"/> colored brush.
/// </summary>
public static ISolidColorBrush Maroon => KnownColor.Maroon.ToBrush();
public static IImmutableSolidColorBrush Maroon => KnownColor.Maroon.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.MediumAquamarine"/> colored brush.
/// </summary>
public static ISolidColorBrush MediumAquamarine => KnownColor.MediumAquamarine.ToBrush();
public static IImmutableSolidColorBrush MediumAquamarine => KnownColor.MediumAquamarine.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.MediumBlue"/> colored brush.
/// </summary>
public static ISolidColorBrush MediumBlue => KnownColor.MediumBlue.ToBrush();
public static IImmutableSolidColorBrush MediumBlue => KnownColor.MediumBlue.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.MediumOrchid"/> colored brush.
/// </summary>
public static ISolidColorBrush MediumOrchid => KnownColor.MediumOrchid.ToBrush();
public static IImmutableSolidColorBrush MediumOrchid => KnownColor.MediumOrchid.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.MediumPurple"/> colored brush.
/// </summary>
public static ISolidColorBrush MediumPurple => KnownColor.MediumPurple.ToBrush();
public static IImmutableSolidColorBrush MediumPurple => KnownColor.MediumPurple.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.MediumSeaGreen"/> colored brush.
/// </summary>
public static ISolidColorBrush MediumSeaGreen => KnownColor.MediumSeaGreen.ToBrush();
public static IImmutableSolidColorBrush MediumSeaGreen => KnownColor.MediumSeaGreen.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.MediumSlateBlue"/> colored brush.
/// </summary>
public static ISolidColorBrush MediumSlateBlue => KnownColor.MediumSlateBlue.ToBrush();
public static IImmutableSolidColorBrush MediumSlateBlue => KnownColor.MediumSlateBlue.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.MediumSpringGreen"/> colored brush.
/// </summary>
public static ISolidColorBrush MediumSpringGreen => KnownColor.MediumSpringGreen.ToBrush();
public static IImmutableSolidColorBrush MediumSpringGreen => KnownColor.MediumSpringGreen.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.MediumTurquoise"/> colored brush.
/// </summary>
public static ISolidColorBrush MediumTurquoise => KnownColor.MediumTurquoise.ToBrush();
public static IImmutableSolidColorBrush MediumTurquoise => KnownColor.MediumTurquoise.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.MediumVioletRed"/> colored brush.
/// </summary>
public static ISolidColorBrush MediumVioletRed => KnownColor.MediumVioletRed.ToBrush();
public static IImmutableSolidColorBrush MediumVioletRed => KnownColor.MediumVioletRed.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.MidnightBlue"/> colored brush.
/// </summary>
public static ISolidColorBrush MidnightBlue => KnownColor.MidnightBlue.ToBrush();
public static IImmutableSolidColorBrush MidnightBlue => KnownColor.MidnightBlue.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.MintCream"/> colored brush.
/// </summary>
public static ISolidColorBrush MintCream => KnownColor.MintCream.ToBrush();
public static IImmutableSolidColorBrush MintCream => KnownColor.MintCream.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.MistyRose"/> colored brush.
/// </summary>
public static ISolidColorBrush MistyRose => KnownColor.MistyRose.ToBrush();
public static IImmutableSolidColorBrush MistyRose => KnownColor.MistyRose.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Moccasin"/> colored brush.
/// </summary>
public static ISolidColorBrush Moccasin => KnownColor.Moccasin.ToBrush();
public static IImmutableSolidColorBrush Moccasin => KnownColor.Moccasin.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.NavajoWhite"/> colored brush.
/// </summary>
public static ISolidColorBrush NavajoWhite => KnownColor.NavajoWhite.ToBrush();
public static IImmutableSolidColorBrush NavajoWhite => KnownColor.NavajoWhite.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Navy"/> colored brush.
/// </summary>
public static ISolidColorBrush Navy => KnownColor.Navy.ToBrush();
public static IImmutableSolidColorBrush Navy => KnownColor.Navy.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.OldLace"/> colored brush.
/// </summary>
public static ISolidColorBrush OldLace => KnownColor.OldLace.ToBrush();
public static IImmutableSolidColorBrush OldLace => KnownColor.OldLace.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Olive"/> colored brush.
/// </summary>
public static ISolidColorBrush Olive => KnownColor.Olive.ToBrush();
public static IImmutableSolidColorBrush Olive => KnownColor.Olive.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.OliveDrab"/> colored brush.
/// </summary>
public static ISolidColorBrush OliveDrab => KnownColor.OliveDrab.ToBrush();
public static IImmutableSolidColorBrush OliveDrab => KnownColor.OliveDrab.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Orange"/> colored brush.
/// </summary>
public static ISolidColorBrush Orange => KnownColor.Orange.ToBrush();
public static IImmutableSolidColorBrush Orange => KnownColor.Orange.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.OrangeRed"/> colored brush.
/// </summary>
public static ISolidColorBrush OrangeRed => KnownColor.OrangeRed.ToBrush();
public static IImmutableSolidColorBrush OrangeRed => KnownColor.OrangeRed.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Orchid"/> colored brush.
/// </summary>
public static ISolidColorBrush Orchid => KnownColor.Orchid.ToBrush();
public static IImmutableSolidColorBrush Orchid => KnownColor.Orchid.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.PaleGoldenrod"/> colored brush.
/// </summary>
public static ISolidColorBrush PaleGoldenrod => KnownColor.PaleGoldenrod.ToBrush();
public static IImmutableSolidColorBrush PaleGoldenrod => KnownColor.PaleGoldenrod.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.PaleGreen"/> colored brush.
/// </summary>
public static ISolidColorBrush PaleGreen => KnownColor.PaleGreen.ToBrush();
public static IImmutableSolidColorBrush PaleGreen => KnownColor.PaleGreen.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.PaleTurquoise"/> colored brush.
/// </summary>
public static ISolidColorBrush PaleTurquoise => KnownColor.PaleTurquoise.ToBrush();
public static IImmutableSolidColorBrush PaleTurquoise => KnownColor.PaleTurquoise.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.PaleVioletRed"/> colored brush.
/// </summary>
public static ISolidColorBrush PaleVioletRed => KnownColor.PaleVioletRed.ToBrush();
public static IImmutableSolidColorBrush PaleVioletRed => KnownColor.PaleVioletRed.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.PapayaWhip"/> colored brush.
/// </summary>
public static ISolidColorBrush PapayaWhip => KnownColor.PapayaWhip.ToBrush();
public static IImmutableSolidColorBrush PapayaWhip => KnownColor.PapayaWhip.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.PeachPuff"/> colored brush.
/// </summary>
public static ISolidColorBrush PeachPuff => KnownColor.PeachPuff.ToBrush();
public static IImmutableSolidColorBrush PeachPuff => KnownColor.PeachPuff.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Peru"/> colored brush.
/// </summary>
public static ISolidColorBrush Peru => KnownColor.Peru.ToBrush();
public static IImmutableSolidColorBrush Peru => KnownColor.Peru.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Pink"/> colored brush.
/// </summary>
public static ISolidColorBrush Pink => KnownColor.Pink.ToBrush();
public static IImmutableSolidColorBrush Pink => KnownColor.Pink.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Plum"/> colored brush.
/// </summary>
public static ISolidColorBrush Plum => KnownColor.Plum.ToBrush();
public static IImmutableSolidColorBrush Plum => KnownColor.Plum.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.PowderBlue"/> colored brush.
/// </summary>
public static ISolidColorBrush PowderBlue => KnownColor.PowderBlue.ToBrush();
public static IImmutableSolidColorBrush PowderBlue => KnownColor.PowderBlue.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Purple"/> colored brush.
/// </summary>
public static ISolidColorBrush Purple => KnownColor.Purple.ToBrush();
public static IImmutableSolidColorBrush Purple => KnownColor.Purple.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Red"/> colored brush.
/// </summary>
public static ISolidColorBrush Red => KnownColor.Red.ToBrush();
public static IImmutableSolidColorBrush Red => KnownColor.Red.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.RosyBrown"/> colored brush.
/// </summary>
public static ISolidColorBrush RosyBrown => KnownColor.RosyBrown.ToBrush();
public static IImmutableSolidColorBrush RosyBrown => KnownColor.RosyBrown.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.RoyalBlue"/> colored brush.
/// </summary>
public static ISolidColorBrush RoyalBlue => KnownColor.RoyalBlue.ToBrush();
public static IImmutableSolidColorBrush RoyalBlue => KnownColor.RoyalBlue.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.SaddleBrown"/> colored brush.
/// </summary>
public static ISolidColorBrush SaddleBrown => KnownColor.SaddleBrown.ToBrush();
public static IImmutableSolidColorBrush SaddleBrown => KnownColor.SaddleBrown.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Salmon"/> colored brush.
/// </summary>
public static ISolidColorBrush Salmon => KnownColor.Salmon.ToBrush();
public static IImmutableSolidColorBrush Salmon => KnownColor.Salmon.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.SandyBrown"/> colored brush.
/// </summary>
public static ISolidColorBrush SandyBrown => KnownColor.SandyBrown.ToBrush();
public static IImmutableSolidColorBrush SandyBrown => KnownColor.SandyBrown.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.SeaGreen"/> colored brush.
/// </summary>
public static ISolidColorBrush SeaGreen => KnownColor.SeaGreen.ToBrush();
public static IImmutableSolidColorBrush SeaGreen => KnownColor.SeaGreen.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.SeaShell"/> colored brush.
/// </summary>
public static ISolidColorBrush SeaShell => KnownColor.SeaShell.ToBrush();
public static IImmutableSolidColorBrush SeaShell => KnownColor.SeaShell.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Sienna"/> colored brush.
/// </summary>
public static ISolidColorBrush Sienna => KnownColor.Sienna.ToBrush();
public static IImmutableSolidColorBrush Sienna => KnownColor.Sienna.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Silver"/> colored brush.
/// </summary>
public static ISolidColorBrush Silver => KnownColor.Silver.ToBrush();
public static IImmutableSolidColorBrush Silver => KnownColor.Silver.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.SkyBlue"/> colored brush.
/// </summary>
public static ISolidColorBrush SkyBlue => KnownColor.SkyBlue.ToBrush();
public static IImmutableSolidColorBrush SkyBlue => KnownColor.SkyBlue.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.SlateBlue"/> colored brush.
/// </summary>
public static ISolidColorBrush SlateBlue => KnownColor.SlateBlue.ToBrush();
public static IImmutableSolidColorBrush SlateBlue => KnownColor.SlateBlue.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.SlateGray"/> colored brush.
/// </summary>
public static ISolidColorBrush SlateGray => KnownColor.SlateGray.ToBrush();
public static IImmutableSolidColorBrush SlateGray => KnownColor.SlateGray.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Snow"/> colored brush.
/// </summary>
public static ISolidColorBrush Snow => KnownColor.Snow.ToBrush();
public static IImmutableSolidColorBrush Snow => KnownColor.Snow.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.SpringGreen"/> colored brush.
/// </summary>
public static ISolidColorBrush SpringGreen => KnownColor.SpringGreen.ToBrush();
public static IImmutableSolidColorBrush SpringGreen => KnownColor.SpringGreen.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.SteelBlue"/> colored brush.
/// </summary>
public static ISolidColorBrush SteelBlue => KnownColor.SteelBlue.ToBrush();
public static IImmutableSolidColorBrush SteelBlue => KnownColor.SteelBlue.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Tan"/> colored brush.
/// </summary>
public static ISolidColorBrush Tan => KnownColor.Tan.ToBrush();
public static IImmutableSolidColorBrush Tan => KnownColor.Tan.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Teal"/> colored brush.
/// </summary>
public static ISolidColorBrush Teal => KnownColor.Teal.ToBrush();
public static IImmutableSolidColorBrush Teal => KnownColor.Teal.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Thistle"/> colored brush.
/// </summary>
public static ISolidColorBrush Thistle => KnownColor.Thistle.ToBrush();
public static IImmutableSolidColorBrush Thistle => KnownColor.Thistle.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Tomato"/> colored brush.
/// </summary>
public static ISolidColorBrush Tomato => KnownColor.Tomato.ToBrush();
public static IImmutableSolidColorBrush Tomato => KnownColor.Tomato.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Transparent"/> colored brush.
/// </summary>
public static ISolidColorBrush Transparent => KnownColor.Transparent.ToBrush();
public static IImmutableSolidColorBrush Transparent => KnownColor.Transparent.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Turquoise"/> colored brush.
/// </summary>
public static ISolidColorBrush Turquoise => KnownColor.Turquoise.ToBrush();
public static IImmutableSolidColorBrush Turquoise => KnownColor.Turquoise.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Violet"/> colored brush.
/// </summary>
public static ISolidColorBrush Violet => KnownColor.Violet.ToBrush();
public static IImmutableSolidColorBrush Violet => KnownColor.Violet.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Wheat"/> colored brush.
/// </summary>
public static ISolidColorBrush Wheat => KnownColor.Wheat.ToBrush();
public static IImmutableSolidColorBrush Wheat => KnownColor.Wheat.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.White"/> colored brush.
/// </summary>
public static ISolidColorBrush White => KnownColor.White.ToBrush();
public static IImmutableSolidColorBrush White => KnownColor.White.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.WhiteSmoke"/> colored brush.
/// </summary>
public static ISolidColorBrush WhiteSmoke => KnownColor.WhiteSmoke.ToBrush();
public static IImmutableSolidColorBrush WhiteSmoke => KnownColor.WhiteSmoke.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.Yellow"/> colored brush.
/// </summary>
public static ISolidColorBrush Yellow => KnownColor.Yellow.ToBrush();
public static IImmutableSolidColorBrush Yellow => KnownColor.Yellow.ToBrush();
/// <summary>
/// Gets an <see cref="Colors.YellowGreen"/> colored brush.
/// </summary>
public static ISolidColorBrush YellowGreen => KnownColor.YellowGreen.ToBrush();
public static IImmutableSolidColorBrush YellowGreen => KnownColor.YellowGreen.ToBrush();
}
}

2
src/Avalonia.Base/Media/ConicGradientBrush.cs

@ -47,7 +47,7 @@ namespace Avalonia.Media
}
/// <inheritdoc/>
public override IBrush ToImmutable()
public override IImmutableBrush ToImmutable()
{
return new ImmutableConicGradientBrush(this);
}

8
src/Avalonia.Base/Media/DashStyle.cs

@ -17,8 +17,8 @@ namespace Avalonia.Media
/// <summary>
/// Defines the <see cref="Dashes"/> property.
/// </summary>
public static readonly StyledProperty<AvaloniaList<double>> DashesProperty =
AvaloniaProperty.Register<DashStyle, AvaloniaList<double>>(nameof(Dashes));
public static readonly StyledProperty<AvaloniaList<double>?> DashesProperty =
AvaloniaProperty.Register<DashStyle, AvaloniaList<double>?>(nameof(Dashes));
/// <summary>
/// Defines the <see cref="Offset"/> property.
@ -83,7 +83,7 @@ namespace Avalonia.Media
/// <summary>
/// Gets or sets the length of alternating dashes and gaps.
/// </summary>
public AvaloniaList<double> Dashes
public AvaloniaList<double>? Dashes
{
get => GetValue(DashesProperty);
set => SetValue(DashesProperty, value);
@ -98,7 +98,7 @@ namespace Avalonia.Media
set => SetValue(OffsetProperty, value);
}
IReadOnlyList<double> IDashStyle.Dashes => Dashes;
IReadOnlyList<double>? IDashStyle.Dashes => Dashes;
/// <summary>
/// Raised when the dash style changes.

2
src/Avalonia.Base/Media/DrawingContext.cs

@ -261,7 +261,7 @@ namespace Avalonia.Media
DrawRectangle(brush, null, rect, cornerRadius, cornerRadius);
}
public readonly struct PushedState : IDisposable
public readonly record struct PushedState : IDisposable
{
private readonly int _level;
private readonly DrawingContext _context;

7
src/Avalonia.Base/Media/DrawingGroup.cs

@ -461,9 +461,10 @@ namespace Avalonia.Media
if (_rootDrawing == null)
{
// When a DrawingGroup is set, it should be made the root if
// a root drawing didnt exist.
Contract.Requires<NotSupportedException>(_currentDrawingGroup == null);
if (_currentDrawingGroup != null)
{
throw new NotSupportedException("When a DrawingGroup is set, it should be made the root if a root drawing didnt exist.");
}
// If this is the first Drawing being added, avoid creating a DrawingGroup
// and set this drawing as the root drawing. This optimizes the common

2
src/Avalonia.Base/Media/FontMetrics.cs

@ -3,7 +3,7 @@
/// <summary>
/// The font metrics is holding information about a font's ascent, descent, etc. in design em units.
/// </summary>
public readonly struct FontMetrics
public readonly record struct FontMetrics
{
/// <summary>
/// Gets the font design units per em.

2
src/Avalonia.Base/Media/FormattedText.cs

@ -1379,7 +1379,7 @@ namespace Avalonia.Media
}
}
if (accumulatedBounds?.PlatformImpl == null || accumulatedBounds.PlatformImpl.Bounds.IsEmpty)
if (accumulatedBounds?.PlatformImpl == null || accumulatedBounds.PlatformImpl.Bounds.IsDefault)
{
return null;
}

4
src/Avalonia.Base/Media/Geometry.cs

@ -30,7 +30,7 @@ namespace Avalonia.Media
/// <summary>
/// Gets the geometry's bounding rectangle.
/// </summary>
public Rect Bounds => PlatformImpl?.Bounds ?? Rect.Empty;
public Rect Bounds => PlatformImpl?.Bounds ?? default;
/// <summary>
/// Gets the platform-specific implementation of the geometry.
@ -84,7 +84,7 @@ namespace Avalonia.Media
/// </summary>
/// <param name="pen">The stroke thickness.</param>
/// <returns>The bounding rectangle.</returns>
public Rect GetRenderBounds(IPen pen) => PlatformImpl?.GetRenderBounds(pen) ?? Rect.Empty;
public Rect GetRenderBounds(IPen pen) => PlatformImpl?.GetRenderBounds(pen) ?? default;
/// <summary>
/// Indicates whether the geometry's fill contains the specified point.

2
src/Avalonia.Base/Media/GeometryDrawing.cs

@ -69,7 +69,7 @@ namespace Avalonia.Media
public override Rect GetBounds()
{
IPen pen = Pen ?? s_boundsPen;
return Geometry?.GetRenderBounds(pen) ?? Rect.Empty;
return Geometry?.GetRenderBounds(pen) ?? default;
}
}
}

2
src/Avalonia.Base/Media/GlyphMetrics.cs

@ -1,6 +1,6 @@
namespace Avalonia.Media;
public readonly struct GlyphMetrics
public readonly record struct GlyphMetrics
{
/// <summary>
/// Distance from the x-origin to the left extremum of the glyph.

2
src/Avalonia.Base/Media/GlyphRunDrawing.cs

@ -32,7 +32,7 @@
public override Rect GetBounds()
{
return GlyphRun != null ? new Rect(GlyphRun.Size) : Rect.Empty;
return GlyphRun != null ? new Rect(GlyphRun.Size) : default;
}
}
}

2
src/Avalonia.Base/Media/GlyphRunMetrics.cs

@ -1,6 +1,6 @@
namespace Avalonia.Media
{
public readonly struct GlyphRunMetrics
public readonly record struct GlyphRunMetrics
{
public GlyphRunMetrics(double width, double widthIncludingTrailingWhitespace, double height,
int trailingWhitespaceLength, int newLineLength, int firstCluster, int lastCluster)

4
src/Avalonia.Base/Media/GradientBrush.cs

@ -12,7 +12,7 @@ namespace Avalonia.Media
/// <summary>
/// Base class for brushes that draw with a gradient.
/// </summary>
public abstract class GradientBrush : Brush, IGradientBrush
public abstract class GradientBrush : Brush, IGradientBrush, IMutableBrush
{
/// <summary>
/// Defines the <see cref="SpreadMethod"/> property.
@ -92,5 +92,7 @@ namespace Avalonia.Media
{
RaiseInvalidated(EventArgs.Empty);
}
public abstract IImmutableBrush ToImmutable();
}
}

2
src/Avalonia.Base/Media/IDashStyle.cs

@ -12,7 +12,7 @@ namespace Avalonia.Media
/// <summary>
/// Gets or sets the length of alternating dashes and gaps.
/// </summary>
IReadOnlyList<double> Dashes { get; }
IReadOnlyList<double>? Dashes { get; }
/// <summary>
/// Gets or sets how far in the dash sequence the stroke will start.

9
src/Avalonia.Base/Media/IImmutableBrush.cs

@ -0,0 +1,9 @@
namespace Avalonia.Media;
/// <summary>
/// Represents an immutable brush which can be safely used with various threading contexts
/// </summary>
public interface IImmutableBrush : IBrush
{
}

4
src/Avalonia.Base/Media/IMutableBrush.cs

@ -7,12 +7,12 @@ namespace Avalonia.Media
/// Represents a mutable brush which can return an immutable clone of itself.
/// </summary>
[NotClientImplementable]
public interface IMutableBrush : IBrush, IAffectsRender
internal interface IMutableBrush : IBrush, IAffectsRender
{
/// <summary>
/// Creates an immutable clone of the brush.
/// </summary>
/// <returns>The immutable clone.</returns>
IBrush ToImmutable();
internal IImmutableBrush ToImmutable();
}
}

9
src/Avalonia.Base/Media/ISolidColorBrush.cs

@ -13,4 +13,13 @@ namespace Avalonia.Media
/// </summary>
Color Color { get; }
}
/// <summary>
/// Fills an area with a solid color.
/// </summary>
[NotClientImplementable]
public interface IImmutableSolidColorBrush : ISolidColorBrush, IImmutableBrush
{
}
}

4
src/Avalonia.Base/Media/ImageBrush.cs

@ -6,7 +6,7 @@ namespace Avalonia.Media
/// <summary>
/// Paints an area with an <see cref="IBitmap"/>.
/// </summary>
public class ImageBrush : TileBrush, IImageBrush
public class ImageBrush : TileBrush, IImageBrush, IMutableBrush
{
/// <summary>
/// Defines the <see cref="Visual"/> property.
@ -45,7 +45,7 @@ namespace Avalonia.Media
}
/// <inheritdoc/>
public override IBrush ToImmutable()
public IImmutableBrush ToImmutable()
{
return new ImmutableImageBrush(this);
}

2
src/Avalonia.Base/Media/ImageDrawing.cs

@ -42,7 +42,7 @@ namespace Avalonia.Media
var imageSource = ImageSource;
var rect = Rect;
if (imageSource is object && !rect.IsEmpty)
if (imageSource is object && !rect.IsDefault)
{
context.DrawImage(imageSource, rect);
}

4
src/Avalonia.Base/Media/Imaging/CroppedBitmap.cs

@ -78,8 +78,8 @@ namespace Avalonia.Media.Imaging
get
{
if (Source is not IBitmap bmp)
return Size.Empty;
if (SourceRect.IsEmpty)
return default;
if (SourceRect.IsDefault)
return Source.Size;
return SourceRect.Size.ToSizeWithDpi(bmp.Dpi);
}

2
src/Avalonia.Base/Media/Imaging/RenderTargetBitmap.cs

@ -60,5 +60,7 @@ namespace Avalonia.Media.Imaging
/// <inheritdoc/>
public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer? vbr) => PlatformImpl.Item.CreateDrawingContext(vbr);
bool IRenderTarget.IsCorrupted => false;
}
}

373
src/Avalonia.Base/Media/ImmediateDrawingContext.cs

@ -0,0 +1,373 @@
using System;
using System.Collections.Generic;
using Avalonia.Platform;
using Avalonia.Rendering.SceneGraph;
using Avalonia.Threading;
using Avalonia.Utilities;
using Avalonia.Media.Imaging;
using Avalonia.Media.Immutable;
namespace Avalonia.Media
{
public sealed class ImmediateDrawingContext : IDisposable, IOptionalFeatureProvider
{
private readonly bool _ownsImpl;
private int _currentLevel;
private static ThreadSafeObjectPool<Stack<PushedState>> StateStackPool { get; } =
ThreadSafeObjectPool<Stack<PushedState>>.Default;
private static ThreadSafeObjectPool<Stack<TransformContainer>> TransformStackPool { get; } =
ThreadSafeObjectPool<Stack<TransformContainer>>.Default;
private Stack<PushedState>? _states = StateStackPool.Get();
private Stack<TransformContainer>? _transformContainers = TransformStackPool.Get();
readonly struct TransformContainer
{
public readonly Matrix LocalTransform;
public readonly Matrix ContainerTransform;
public TransformContainer(Matrix localTransform, Matrix containerTransform)
{
LocalTransform = localTransform;
ContainerTransform = containerTransform;
}
}
internal ImmediateDrawingContext(IDrawingContextImpl impl, bool ownsImpl)
{
_ownsImpl = ownsImpl;
PlatformImpl = impl;
_currentContainerTransform = impl.Transform;
}
public IDrawingContextImpl PlatformImpl { get; }
private Matrix _currentTransform = Matrix.Identity;
private Matrix _currentContainerTransform;
/// <summary>
/// Gets the current transform of the drawing context.
/// </summary>
public Matrix CurrentTransform
{
get { return _currentTransform; }
private set
{
_currentTransform = value;
var transform = _currentTransform * _currentContainerTransform;
PlatformImpl.Transform = transform;
}
}
/// <summary>
/// Draws an bitmap.
/// </summary>
/// <param name="source">The bitmap.</param>
/// <param name="rect">The rect in the output to draw to.</param>
public void DrawBitmap(IBitmap source, Rect rect)
{
_ = source ?? throw new ArgumentNullException(nameof(source));
DrawBitmap(source, new Rect(source.Size), rect);
}
/// <summary>
/// Draws an image.
/// </summary>
/// <param name="source">The bitmap.</param>
/// <param name="sourceRect">The rect in the image to draw.</param>
/// <param name="destRect">The rect in the output to draw to.</param>
/// <param name="bitmapInterpolationMode">The bitmap interpolation mode.</param>
public void DrawBitmap(IBitmap source, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode = default)
{
_ = source ?? throw new ArgumentNullException(nameof(source));
PlatformImpl.DrawBitmap(source.PlatformImpl, 1, sourceRect, destRect, bitmapInterpolationMode);
}
/// <summary>
/// Draws a line.
/// </summary>
/// <param name="pen">The stroke pen.</param>
/// <param name="p1">The first point of the line.</param>
/// <param name="p2">The second point of the line.</param>
public void DrawLine(ImmutablePen pen, Point p1, Point p2)
{
if (PenIsVisible(pen))
{
PlatformImpl.DrawLine(pen, p1, p2);
}
}
/// <summary>
/// Draws a rectangle with the specified Brush and Pen.
/// </summary>
/// <param name="brush">The brush used to fill the rectangle, or <c>null</c> for no fill.</param>
/// <param name="pen">The pen used to stroke the rectangle, or <c>null</c> for no stroke.</param>
/// <param name="rect">The rectangle bounds.</param>
/// <param name="radiusX">The radius in the X dimension of the rounded corners.
/// This value will be clamped to the range of 0 to Width/2
/// </param>
/// <param name="radiusY">The radius in the Y dimension of the rounded corners.
/// This value will be clamped to the range of 0 to Height/2
/// </param>
/// <param name="boxShadows">Box shadow effect parameters</param>
/// <remarks>
/// The brush and the pen can both be null. If the brush is null, then no fill is performed.
/// If the pen is null, then no stoke is performed. If both the pen and the brush are null, then the drawing is not visible.
/// </remarks>
public void DrawRectangle(IImmutableBrush? brush, ImmutablePen? pen, Rect rect, double radiusX = 0, double radiusY = 0,
BoxShadows boxShadows = default)
{
if (brush == null && !PenIsVisible(pen))
{
return;
}
if (!MathUtilities.IsZero(radiusX))
{
radiusX = Math.Min(radiusX, rect.Width / 2);
}
if (!MathUtilities.IsZero(radiusY))
{
radiusY = Math.Min(radiusY, rect.Height / 2);
}
PlatformImpl.DrawRectangle(brush, pen, new RoundedRect(rect, radiusX, radiusY), boxShadows);
}
/// <summary>
/// Draws the outline of a rectangle.
/// </summary>
/// <param name="pen">The pen.</param>
/// <param name="rect">The rectangle bounds.</param>
/// <param name="cornerRadius">The corner radius.</param>
public void DrawRectangle(ImmutablePen pen, Rect rect, float cornerRadius = 0.0f)
{
DrawRectangle(null, pen, rect, cornerRadius, cornerRadius);
}
/// <summary>
/// Draws an ellipse with the specified Brush and Pen.
/// </summary>
/// <param name="brush">The brush used to fill the ellipse, or <c>null</c> for no fill.</param>
/// <param name="pen">The pen used to stroke the ellipse, or <c>null</c> for no stroke.</param>
/// <param name="center">The location of the center of the ellipse.</param>
/// <param name="radiusX">The horizontal radius of the ellipse.</param>
/// <param name="radiusY">The vertical radius of the ellipse.</param>
/// <remarks>
/// The brush and the pen can both be null. If the brush is null, then no fill is performed.
/// If the pen is null, then no stoke is performed. If both the pen and the brush are null, then the drawing is not visible.
/// </remarks>
public void DrawEllipse(IImmutableBrush? brush, ImmutablePen? pen, Point center, double radiusX, double radiusY)
{
if (brush == null && !PenIsVisible(pen))
{
return;
}
var originX = center.X - radiusX;
var originY = center.Y - radiusY;
var width = radiusX * 2;
var height = radiusY * 2;
PlatformImpl.DrawEllipse(brush, pen, new Rect(originX, originY, width, height));
}
/// <summary>
/// Draws a glyph run.
/// </summary>
/// <param name="foreground">The foreground brush.</param>
/// <param name="glyphRun">The glyph run.</param>
public void DrawGlyphRun(IImmutableBrush foreground, GlyphRun glyphRun)
{
_ = glyphRun ?? throw new ArgumentNullException(nameof(glyphRun));
PlatformImpl.DrawGlyphRun(foreground, glyphRun);
}
/// <summary>
/// Draws a filled rectangle.
/// </summary>
/// <param name="brush">The brush.</param>
/// <param name="rect">The rectangle bounds.</param>
/// <param name="cornerRadius">The corner radius.</param>
public void FillRectangle(IImmutableBrush brush, Rect rect, float cornerRadius = 0.0f)
{
DrawRectangle(brush, null, rect, cornerRadius, cornerRadius);
}
public readonly record struct PushedState : IDisposable
{
private readonly int _level;
private readonly ImmediateDrawingContext _context;
private readonly Matrix _matrix;
private readonly PushedStateType _type;
public enum PushedStateType
{
None,
Matrix,
Opacity,
Clip,
MatrixContainer,
GeometryClip,
OpacityMask,
}
internal PushedState(ImmediateDrawingContext context, PushedStateType type, Matrix matrix = default(Matrix))
{
if (context._states is null)
throw new ObjectDisposedException(nameof(ImmediateDrawingContext));
_context = context;
_type = type;
_matrix = matrix;
_level = context._currentLevel += 1;
context._states.Push(this);
}
public void Dispose()
{
if (_type == PushedStateType.None)
return;
if (_context._states is null || _context._transformContainers is null)
throw new ObjectDisposedException(nameof(DrawingContext));
if (_context._currentLevel != _level)
throw new InvalidOperationException("Wrong Push/Pop state order");
_context._currentLevel--;
_context._states.Pop();
if (_type == PushedStateType.Matrix)
_context.CurrentTransform = _matrix;
else if (_type == PushedStateType.Clip)
_context.PlatformImpl.PopClip();
else if (_type == PushedStateType.Opacity)
_context.PlatformImpl.PopOpacity();
else if (_type == PushedStateType.GeometryClip)
_context.PlatformImpl.PopGeometryClip();
else if (_type == PushedStateType.OpacityMask)
_context.PlatformImpl.PopOpacityMask();
else if (_type == PushedStateType.MatrixContainer)
{
var cont = _context._transformContainers.Pop();
_context._currentContainerTransform = cont.ContainerTransform;
_context.CurrentTransform = cont.LocalTransform;
}
}
}
public PushedState PushClip(RoundedRect clip)
{
PlatformImpl.PushClip(clip);
return new PushedState(this, PushedState.PushedStateType.Clip);
}
/// <summary>
/// Pushes a clip rectangle.
/// </summary>
/// <param name="clip">The clip rectangle.</param>
/// <returns>A disposable used to undo the clip rectangle.</returns>
public PushedState PushClip(Rect clip)
{
PlatformImpl.PushClip(clip);
return new PushedState(this, PushedState.PushedStateType.Clip);
}
/// <summary>
/// Pushes an opacity value.
/// </summary>
/// <param name="opacity">The opacity.</param>
/// <returns>A disposable used to undo the opacity.</returns>
public PushedState PushOpacity(double opacity)
//TODO: Eliminate platform-specific push opacity call
{
PlatformImpl.PushOpacity(opacity);
return new PushedState(this, PushedState.PushedStateType.Opacity);
}
/// <summary>
/// Pushes an opacity mask.
/// </summary>
/// <param name="mask">The opacity mask.</param>
/// <param name="bounds">
/// The size of the brush's target area. TODO: Are we sure this is needed?
/// </param>
/// <returns>A disposable to undo the opacity mask.</returns>
public PushedState PushOpacityMask(IImmutableBrush mask, Rect bounds)
{
PlatformImpl.PushOpacityMask(mask, bounds);
return new PushedState(this, PushedState.PushedStateType.OpacityMask);
}
/// <summary>
/// Pushes a matrix post-transformation.
/// </summary>
/// <param name="matrix">The matrix</param>
/// <returns>A disposable used to undo the transformation.</returns>
public PushedState PushPostTransform(Matrix matrix) => PushSetTransform(CurrentTransform * matrix);
/// <summary>
/// Pushes a matrix pre-transformation.
/// </summary>
/// <param name="matrix">The matrix</param>
/// <returns>A disposable used to undo the transformation.</returns>
public PushedState PushPreTransform(Matrix matrix) => PushSetTransform(matrix * CurrentTransform);
/// <summary>
/// Sets the current matrix transformation.
/// </summary>
/// <param name="matrix">The matrix</param>
/// <returns>A disposable used to undo the transformation.</returns>
public PushedState PushSetTransform(Matrix matrix)
{
var oldMatrix = CurrentTransform;
CurrentTransform = matrix;
return new PushedState(this, PushedState.PushedStateType.Matrix, oldMatrix);
}
/// <summary>
/// Pushes a new transform context.
/// </summary>
/// <returns>A disposable used to undo the transformation.</returns>
public PushedState PushTransformContainer()
{
if (_transformContainers is null)
throw new ObjectDisposedException(nameof(DrawingContext));
_transformContainers.Push(new TransformContainer(CurrentTransform, _currentContainerTransform));
_currentContainerTransform = CurrentTransform * _currentContainerTransform;
_currentTransform = Matrix.Identity;
return new PushedState(this, PushedState.PushedStateType.MatrixContainer);
}
/// <summary>
/// Disposes of any resources held by the <see cref="DrawingContext"/>.
/// </summary>
public void Dispose()
{
if (_states is null || _transformContainers is null)
throw new ObjectDisposedException(nameof(DrawingContext));
while (_states.Count != 0)
_states.Peek().Dispose();
StateStackPool.Return(_states);
_states = null;
if (_transformContainers.Count != 0)
throw new InvalidOperationException("Transform container stack is non-empty");
TransformStackPool.Return(_transformContainers);
_transformContainers = null;
if (_ownsImpl)
PlatformImpl.Dispose();
}
private static bool PenIsVisible(IPen? pen)
{
return pen?.Brush != null && pen.Thickness > 0;
}
public object? TryGetFeature(Type type) => PlatformImpl.GetFeature(type);
}
}

4
src/Avalonia.Base/Media/Immutable/ImmutableDashStyle.cs

@ -17,7 +17,7 @@ namespace Avalonia.Media.Immutable
/// </summary>
/// <param name="dashes">The dashes collection.</param>
/// <param name="offset">The dash sequence offset.</param>
public ImmutableDashStyle(IEnumerable<double> dashes, double offset)
public ImmutableDashStyle(IEnumerable<double>? dashes, double offset)
{
_dashes = dashes?.ToArray() ?? Array.Empty<double>();
Offset = offset;
@ -69,7 +69,7 @@ namespace Avalonia.Media.Immutable
return hashCode;
}
private static bool SequenceEqual(IReadOnlyList<double> left, IReadOnlyList<double> right)
private static bool SequenceEqual(IReadOnlyList<double> left, IReadOnlyList<double>? right)
{
if (ReferenceEquals(left, right))
{

2
src/Avalonia.Base/Media/Immutable/ImmutableGradientBrush.cs

@ -5,7 +5,7 @@ namespace Avalonia.Media.Immutable
/// <summary>
/// A brush that draws with a gradient.
/// </summary>
public abstract class ImmutableGradientBrush : IGradientBrush
public abstract class ImmutableGradientBrush : IGradientBrush, IImmutableBrush
{
/// <summary>
/// Initializes a new instance of the <see cref="ImmutableGradientBrush"/> class.

4
src/Avalonia.Base/Media/Immutable/ImmutablePen.cs

@ -38,15 +38,13 @@ namespace Avalonia.Media.Immutable
/// <param name="lineJoin">The line join.</param>
/// <param name="miterLimit">The miter limit.</param>
public ImmutablePen(
IBrush? brush,
IImmutableBrush? brush,
double thickness = 1.0,
ImmutableDashStyle? dashStyle = null,
PenLineCap lineCap = PenLineCap.Flat,
PenLineJoin lineJoin = PenLineJoin.Miter,
double miterLimit = 10.0)
{
Debug.Assert(!(brush is IMutableBrush));
Brush = brush;
Thickness = thickness;
LineCap = lineCap;

2
src/Avalonia.Base/Media/Immutable/ImmutableSolidColorBrush.cs

@ -5,7 +5,7 @@ namespace Avalonia.Media.Immutable
/// <summary>
/// Fills an area with a solid color.
/// </summary>
public class ImmutableSolidColorBrush : ISolidColorBrush, IEquatable<ImmutableSolidColorBrush>
public class ImmutableSolidColorBrush : IImmutableSolidColorBrush, IEquatable<ImmutableSolidColorBrush>
{
/// <summary>
/// Initializes a new instance of the <see cref="ImmutableSolidColorBrush"/> class.

2
src/Avalonia.Base/Media/Immutable/ImmutableTileBrush.cs

@ -5,7 +5,7 @@ namespace Avalonia.Media.Immutable
/// <summary>
/// A brush which displays a repeating image.
/// </summary>
public abstract class ImmutableTileBrush : ITileBrush
public abstract class ImmutableTileBrush : ITileBrush, IImmutableBrush
{
/// <summary>
/// Initializes a new instance of the <see cref="ImageBrush"/> class.

6
src/Avalonia.Base/Media/KnownColors.cs

@ -10,7 +10,7 @@ namespace Avalonia.Media
private static readonly IReadOnlyDictionary<string, KnownColor> _knownColorNames;
private static readonly IReadOnlyDictionary<uint, string> _knownColors;
#if !BUILDTASK
private static readonly Dictionary<KnownColor, ISolidColorBrush> _knownBrushes;
private static readonly Dictionary<KnownColor, IImmutableSolidColorBrush> _knownBrushes;
#endif
[GenerateEnumValueDictionary()]
@ -39,7 +39,7 @@ namespace Avalonia.Media
_knownColors = knownColors;
#if !BUILDTASK
_knownBrushes = new Dictionary<KnownColor, ISolidColorBrush>();
_knownBrushes = new ();
#endif
}
@ -72,7 +72,7 @@ namespace Avalonia.Media
}
#if !BUILDTASK
public static ISolidColorBrush ToBrush(this KnownColor color)
public static IImmutableSolidColorBrush ToBrush(this KnownColor color)
{
lock (_knownBrushes)
{

2
src/Avalonia.Base/Media/LinearGradientBrush.cs

@ -47,7 +47,7 @@ namespace Avalonia.Media
}
/// <inheritdoc/>
public override IBrush ToImmutable()
public override IImmutableBrush ToImmutable()
{
return new ImmutableLinearGradientBrush(this);
}

2
src/Avalonia.Base/Media/RadialGradientBrush.cs

@ -67,7 +67,7 @@ namespace Avalonia.Media
}
/// <inheritdoc/>
public override IBrush ToImmutable()
public override IImmutableBrush ToImmutable()
{
return new ImmutableRadialGradientBrush(this);
}

4
src/Avalonia.Base/Media/SolidColorBrush.cs

@ -6,7 +6,7 @@ namespace Avalonia.Media
/// <summary>
/// Fills an area with a solid color.
/// </summary>
public class SolidColorBrush : Brush, ISolidColorBrush
public class SolidColorBrush : Brush, ISolidColorBrush, IMutableBrush
{
/// <summary>
/// Defines the <see cref="Color"/> property.
@ -80,7 +80,7 @@ namespace Avalonia.Media
}
/// <inheritdoc/>
public override IBrush ToImmutable()
public IImmutableBrush ToImmutable()
{
return new ImmutableSolidColorBrush(this);
}

2
src/Avalonia.Base/Media/TextCollapsingCreateInfo.cs

@ -2,7 +2,7 @@
namespace Avalonia.Media
{
public readonly struct TextCollapsingCreateInfo
public readonly record struct TextCollapsingCreateInfo
{
public readonly double Width;
public readonly TextRunProperties TextRunProperties;

1
src/Avalonia.Base/Media/TextFormatting/FormattedTextSource.cs

@ -8,7 +8,6 @@ namespace Avalonia.Media.TextFormatting
internal readonly struct FormattedTextSource : ITextSource
{
private readonly CharacterBufferRange _text;
private readonly int length;
private readonly TextRunProperties _defaultProperties;
private readonly IReadOnlyList<ValueSpan<TextRunProperties>>? _textModifier;

2
src/Avalonia.Base/Media/TextFormatting/ShapedBuffer.cs

@ -262,7 +262,7 @@ namespace Avalonia.Media.TextFormatting
}
}
public readonly struct GlyphInfo
public readonly record struct GlyphInfo
{
public GlyphInfo(ushort glyphIndex, int glyphCluster, double glyphAdvance = 0, Vector glyphOffset = default)
{

2
src/Avalonia.Base/Media/TextFormatting/SplitResult.cs

@ -1,6 +1,8 @@
namespace Avalonia.Media.TextFormatting
{
#pragma warning disable CA1815 // Override equals and operator equals on value types
public readonly struct SplitResult<T>
#pragma warning restore CA1815 // Override equals and operator equals on value types
{
public SplitResult(T first, T? second)
{

4
src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs

@ -576,7 +576,7 @@ namespace Avalonia.Media.TextFormatting
var startX = Start;
double currentWidth = 0;
var currentRect = Rect.Empty;
var currentRect = default(Rect);
TextRunBounds lastRunBounds = default;
@ -792,7 +792,7 @@ namespace Avalonia.Media.TextFormatting
var startX = WidthIncludingTrailingWhitespace;
double currentWidth = 0;
var currentRect = Rect.Empty;
var currentRect = default(Rect);
for (var index = TextRuns.Count - 1; index >= 0; index--)
{

2
src/Avalonia.Base/Media/TextFormatting/TextLineMetrics.cs

@ -4,7 +4,7 @@
/// Represents a metric for a <see cref="TextLine"/> objects,
/// that holds information about ascent, descent, line gap, size and origin of the text line.
/// </summary>
public readonly struct TextLineMetrics
public readonly record struct TextLineMetrics
{
public TextLineMetrics(bool hasOverflowed, double height, int newlineLength, double start, double textBaseline,
int trailingWhitespaceLength, double width,

2
src/Avalonia.Base/Media/TextFormatting/TextMetrics.cs

@ -3,7 +3,7 @@
/// <summary>
/// A metric that holds information about text specific measurements.
/// </summary>
public readonly struct TextMetrics
public readonly record struct TextMetrics
{
public TextMetrics(IGlyphTypeface glyphTypeface, double fontRenderingEmSize)
{

2
src/Avalonia.Base/Media/TextFormatting/TextRange.cs

@ -5,7 +5,7 @@ namespace Avalonia.Media.TextFormatting
/// <summary>
/// References a portion of a text buffer.
/// </summary>
public readonly struct TextRange
public readonly record struct TextRange
{
public TextRange(int start, int length)
{

2
src/Avalonia.Base/Media/TextFormatting/TextRunBounds.cs

@ -3,7 +3,7 @@
/// <summary>
/// The bounding rectangle of text run
/// </summary>
public readonly struct TextRunBounds
public readonly record struct TextRunBounds
{
/// <summary>
/// Constructing TextRunBounds

2
src/Avalonia.Base/Media/TextFormatting/TextShaperOptions.cs

@ -5,7 +5,7 @@ namespace Avalonia.Media.TextFormatting
/// <summary>
/// Options to customize text shaping.
/// </summary>
public readonly struct TextShaperOptions
public readonly record struct TextShaperOptions
{
public TextShaperOptions(
IGlyphTypeface typeface,

2
src/Avalonia.Base/Media/TextFormatting/Unicode/Codepoint.cs

@ -3,7 +3,7 @@ using System.Runtime.CompilerServices;
namespace Avalonia.Media.TextFormatting.Unicode
{
public readonly struct Codepoint
public readonly record struct Codepoint
{
private readonly uint _value;

1
src/Avalonia.Base/Media/TextFormatting/Unicode/CodepointEnumerator.cs

@ -5,7 +5,6 @@ namespace Avalonia.Media.TextFormatting.Unicode
public ref struct CodepointEnumerator
{
private CharacterBufferRange _text;
private int _pos;
public CodepointEnumerator(CharacterBufferRange text)
{

2
src/Avalonia.Base/Media/TextFormatting/Unicode/LineBreak.cs

@ -24,7 +24,7 @@ namespace Avalonia.Media.TextFormatting.Unicode
/// Information about a potential line break position
/// </summary>
[DebuggerDisplay("{PositionMeasure}/{PositionWrap} @ {Required}")]
public readonly struct LineBreak
public readonly record struct LineBreak
{
/// <summary>
/// Constructor

2
src/Avalonia.Base/Media/TextHitTestResult.cs

@ -5,7 +5,7 @@ namespace Avalonia.Media
/// <summary>
/// Holds a hit test result from a <see cref="TextLayout"/>.
/// </summary>
public readonly struct TextHitTestResult
public readonly record struct TextHitTestResult
{
public TextHitTestResult(CharacterHit characterHit, int textPosition, bool isInside, bool isTrailing)
{

12
src/Avalonia.Base/Media/Transformation/TransformOperation.cs

@ -5,7 +5,7 @@ namespace Avalonia.Media.Transformation
/// <summary>
/// Represents a single primitive transform (like translation, rotation, scale, etc.).
/// </summary>
public struct TransformOperation
public record struct TransformOperation
{
public OperationType Type;
public Matrix Matrix;
@ -196,7 +196,7 @@ namespace Avalonia.Media.Transformation
}
[StructLayout(LayoutKind.Explicit)]
public struct DataLayout
public record struct DataLayout
{
[FieldOffset(0)] public SkewLayout Skew;
@ -206,25 +206,25 @@ namespace Avalonia.Media.Transformation
[FieldOffset(0)] public RotateLayout Rotate;
public struct SkewLayout
public record struct SkewLayout
{
public double X;
public double Y;
}
public struct ScaleLayout
public record struct ScaleLayout
{
public double X;
public double Y;
}
public struct TranslateLayout
public record struct TranslateLayout
{
public double X;
public double Y;
}
public struct RotateLayout
public record struct RotateLayout
{
public double Angle;
}

2
src/Avalonia.Base/Media/Transformation/TransformOperations.cs

@ -165,7 +165,7 @@ namespace Avalonia.Media.Transformation
return Math.Max(from._operations.Count, to._operations.Count);
}
public readonly struct Builder
public readonly record struct Builder
{
private readonly List<TransformOperation> _operations;

3
src/Avalonia.Base/Media/Typeface.cs

@ -1,6 +1,5 @@
using System;
using System.Diagnostics;
using JetBrains.Annotations;
namespace Avalonia.Media
{
@ -17,7 +16,7 @@ namespace Avalonia.Media
/// <param name="style">The font style.</param>
/// <param name="weight">The font weight.</param>
/// <param name="stretch">The font stretch.</param>
public Typeface([NotNull] FontFamily fontFamily,
public Typeface(FontFamily fontFamily,
FontStyle style = FontStyle.Normal,
FontWeight weight = FontWeight.Normal,
FontStretch stretch = FontStretch.Normal)

6
src/Avalonia.Base/Media/UnicodeRange.cs

@ -7,7 +7,7 @@ namespace Avalonia.Media
/// <summary>
/// The <see cref="UnicodeRange"/> descripes a set of Unicode characters.
/// </summary>
public readonly struct UnicodeRange
public readonly record struct UnicodeRange
{
public readonly static UnicodeRange Default = Parse("0-10FFFD");
@ -102,9 +102,9 @@ namespace Avalonia.Media
}
}
public readonly struct UnicodeRangeSegment
public readonly record struct UnicodeRangeSegment
{
private static Regex s_regex = new Regex(@"^(?:[uU]\+)?(?:([0-9a-fA-F](?:[0-9a-fA-F?]{1,5})?))$");
private static Regex s_regex = new Regex(@"^(?:[uU]\+)?(?:([0-9a-fA-F](?:[0-9a-fA-F?]{1,5})?))$", RegexOptions.Compiled);
public UnicodeRangeSegment(int start, int end)
{

4
src/Avalonia.Base/Media/VisualBrush.cs

@ -6,7 +6,7 @@ namespace Avalonia.Media
/// <summary>
/// Paints an area with an <see cref="Visual"/>.
/// </summary>
public class VisualBrush : TileBrush, IVisualBrush
public class VisualBrush : TileBrush, IVisualBrush, IMutableBrush
{
/// <summary>
/// Defines the <see cref="Visual"/> property.
@ -45,7 +45,7 @@ namespace Avalonia.Media
}
/// <inheritdoc/>
public override IBrush ToImmutable()
IImmutableBrush IMutableBrush.ToImmutable()
{
return new ImmutableVisualBrush(this);
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save