Browse Source

Merge branch 'master' into SetterTargetType

pull/8572/head
Luis v.d.Eltz 4 years ago
committed by GitHub
parent
commit
d5e3d18184
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      Avalonia.sln
  2. 6
      azure-pipelines.yml
  3. 2
      samples/BindingDemo/App.xaml
  4. 20
      samples/ControlCatalog/App.xaml.cs
  5. 2
      samples/ControlCatalog/ControlCatalog.csproj
  6. 4
      samples/ControlCatalog/MainView.xaml
  7. 20
      samples/ControlCatalog/MainView.xaml.cs
  8. 10
      samples/ControlCatalog/Models/CatalogTheme.cs
  9. 9
      samples/ControlCatalog/Pages/DataGridPage.xaml
  10. 26
      samples/ControlCatalog/Pages/DialogsPage.xaml.cs
  11. 3
      samples/PlatformSanityChecks/App.xaml
  12. 2
      samples/PlatformSanityChecks/PlatformSanityChecks.csproj
  13. 5
      samples/Previewer/App.xaml
  14. 2
      samples/Previewer/Previewer.csproj
  15. 16
      samples/VirtualizationDemo/App.xaml
  16. 2
      samples/VirtualizationDemo/VirtualizationDemo.csproj
  17. 5
      samples/interop/Direct3DInteropSample/App.paml
  18. 2
      samples/interop/Direct3DInteropSample/Direct3DInteropSample.csproj
  19. 33
      src/Android/Avalonia.Android/Platform/Storage/AndroidStorageItem.cs
  20. 56
      src/Avalonia.Base/Controls/ResourceDictionary.cs
  21. 5
      src/Avalonia.Base/Controls/ResourceNodeExtensions.cs
  22. 8
      src/Avalonia.Base/Controls/Templates/ITemplateResult.cs
  23. 3
      src/Avalonia.Base/Controls/Templates/TemplateResult.cs
  24. 2
      src/Avalonia.Base/Media/GlyphRun.cs
  25. 24
      src/Avalonia.Base/Media/TextFormatting/FormattedTextSource.cs
  26. 17
      src/Avalonia.Base/Media/TextFormatting/InterWordJustification.cs
  27. 26
      src/Avalonia.Base/Media/TextFormatting/TextCharacters.cs
  28. 7
      src/Avalonia.Base/Media/TextFormatting/TextLayout.cs
  29. 2
      src/Avalonia.Base/Media/TextFormatting/TextLine.cs
  30. 402
      src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs
  31. 2
      src/Avalonia.Base/Media/TextFormatting/Unicode/Codepoint.cs
  32. 4
      src/Avalonia.Base/Platform/IGeometryImpl.cs
  33. 8
      src/Avalonia.Base/Platform/Storage/FileIO/BclStorageFile.cs
  34. 16
      src/Avalonia.Base/Platform/Storage/FileIO/BclStorageFolder.cs
  35. 2
      src/Avalonia.Base/Platform/Storage/IStorageBookmarkItem.cs
  36. 4
      src/Avalonia.Base/Platform/Storage/IStorageFile.cs
  37. 11
      src/Avalonia.Base/Platform/Storage/IStorageFolder.cs
  38. 2
      src/Avalonia.Base/Platform/Storage/IStorageItem.cs
  39. 5
      src/Avalonia.Base/Rendering/Composition/Animations/AnimationInstanceBase.cs
  40. 11
      src/Avalonia.Base/Rendering/Composition/Animations/CompositionAnimation.cs
  41. 4
      src/Avalonia.Base/Rendering/Composition/Animations/CompositionAnimationGroup.cs
  42. 6
      src/Avalonia.Base/Rendering/Composition/Animations/ExpressionAnimation.cs
  43. 4
      src/Avalonia.Base/Rendering/Composition/Animations/ExpressionAnimationInstance.cs
  44. 4
      src/Avalonia.Base/Rendering/Composition/Animations/IAnimationInstance.cs
  45. 4
      src/Avalonia.Base/Rendering/Composition/Animations/ICompositionAnimationBase.cs
  46. 4
      src/Avalonia.Base/Rendering/Composition/Animations/ImplicitAnimationCollection.cs
  47. 4
      src/Avalonia.Base/Rendering/Composition/Animations/Interpolators.cs
  48. 8
      src/Avalonia.Base/Rendering/Composition/Animations/KeyFrameAnimation.cs
  49. 4
      src/Avalonia.Base/Rendering/Composition/Animations/KeyFrameAnimationInstance.cs
  50. 4
      src/Avalonia.Base/Rendering/Composition/Animations/KeyFrames.cs
  51. 4
      src/Avalonia.Base/Rendering/Composition/Animations/PropertySetSnapshot.cs
  52. 4
      src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs
  53. 4
      src/Avalonia.Base/Rendering/Composition/CompositionDrawListVisual.cs
  54. 4
      src/Avalonia.Base/Rendering/Composition/CompositionObject.cs
  55. 4
      src/Avalonia.Base/Rendering/Composition/CompositionPropertySet.cs
  56. 4
      src/Avalonia.Base/Rendering/Composition/CompositionTarget.cs
  57. 17
      src/Avalonia.Base/Rendering/Composition/Compositor.cs
  58. 4
      src/Avalonia.Base/Rendering/Composition/ContainerVisual.cs
  59. 4
      src/Avalonia.Base/Rendering/Composition/Drawing/CompositionDrawList.cs
  60. 5
      src/Avalonia.Base/Rendering/Composition/Drawing/CompositionDrawingContext.cs
  61. 4
      src/Avalonia.Base/Rendering/Composition/ElementCompositionPreview.cs
  62. 4
      src/Avalonia.Base/Rendering/Composition/Enums.cs
  63. 4
      src/Avalonia.Base/Rendering/Composition/Expressions/BuiltInExpressionFfi.cs
  64. 4
      src/Avalonia.Base/Rendering/Composition/Expressions/DelegateExpressionFfi.cs
  65. 4
      src/Avalonia.Base/Rendering/Composition/Expressions/Expression.cs
  66. 4
      src/Avalonia.Base/Rendering/Composition/Expressions/ExpressionEvaluationContext.cs
  67. 4
      src/Avalonia.Base/Rendering/Composition/Expressions/ExpressionParseException.cs
  68. 4
      src/Avalonia.Base/Rendering/Composition/Expressions/ExpressionParser.cs
  69. 4
      src/Avalonia.Base/Rendering/Composition/Expressions/ExpressionTrackedValues.cs
  70. 4
      src/Avalonia.Base/Rendering/Composition/Expressions/ExpressionVariant.cs
  71. 4
      src/Avalonia.Base/Rendering/Composition/Expressions/TokenParser.cs
  72. 4
      src/Avalonia.Base/Rendering/Composition/ICompositionTargetDebugEvents.cs
  73. 7
      src/Avalonia.Base/Rendering/Composition/License.md
  74. 4
      src/Avalonia.Base/Rendering/Composition/MatrixUtils.cs
  75. 4
      src/Avalonia.Base/Rendering/Composition/Server/CompositionProperty.cs
  76. 4
      src/Avalonia.Base/Rendering/Composition/Server/DrawingContextProxy.cs
  77. 4
      src/Avalonia.Base/Rendering/Composition/Server/FpsCounter.cs
  78. 4
      src/Avalonia.Base/Rendering/Composition/Server/ReadbackIndices.cs
  79. 4
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionContainerVisual.cs
  80. 4
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionDrawListVisual.cs
  81. 4
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionSurface.cs
  82. 4
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
  83. 4
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.DirtyProperties.cs
  84. 4
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs
  85. 7
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositor.cs
  86. 4
      src/Avalonia.Base/Rendering/Composition/Server/ServerList.cs
  87. 4
      src/Avalonia.Base/Rendering/Composition/Server/ServerObject.cs
  88. 4
      src/Avalonia.Base/Rendering/Composition/Transport/Batch.cs
  89. 2
      src/Avalonia.Base/Rendering/Composition/Transport/BatchStream.cs
  90. 4
      src/Avalonia.Base/Rendering/Composition/Transport/BatchStreamArrayPool.cs
  91. 4
      src/Avalonia.Base/Rendering/Composition/Transport/BatchStreamDebugMarker.cs
  92. 4
      src/Avalonia.Base/Rendering/Composition/Transport/ServerListProxyHelper.cs
  93. 4
      src/Avalonia.Base/Rendering/Composition/Visual.cs
  94. 4
      src/Avalonia.Base/Rendering/Composition/VisualCollection.cs
  95. 3
      src/Avalonia.Base/Rendering/Composition/readme.md
  96. 2
      src/Avalonia.Base/Rendering/SceneGraph/ExperimentalAcrylicNode.cs
  97. 4
      src/Avalonia.Base/Rendering/SceneGraph/GeometryNode.cs
  98. 8
      src/Avalonia.Base/Rendering/SceneGraph/GlyphRunNode.cs
  99. 2
      src/Avalonia.Base/Rendering/SceneGraph/ImageNode.cs
  100. 4
      src/Avalonia.Base/Rendering/SceneGraph/LineNode.cs

2
Avalonia.sln

@ -13,7 +13,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Direct2D1", "src\W
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Controls", "src\Avalonia.Controls\Avalonia.Controls.csproj", "{D2221C82-4A25-4583-9B43-D791E3F6820C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Themes.Default", "src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj", "{3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Themes.Simple", "src\Avalonia.Themes.Simple\Avalonia.Themes.Simple.csproj", "{3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Diagnostics", "src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj", "{7062AE20-5DCC-4442-9645-8195BDECE63E}"
EndProject

6
azure-pipelines.yml

@ -59,7 +59,7 @@ jobs:
variables:
SolutionDir: '$(Build.SourcesDirectory)'
pool:
vmImage: 'macOS-10.15'
vmImage: 'macos-12'
steps:
- task: UseDotNet@2
displayName: 'Use .NET Core SDK 3.1.418'
@ -91,10 +91,10 @@ jobs:
inputs:
actions: 'build'
scheme: ''
sdk: 'macosx11.1'
sdk: 'macosx12.3'
configuration: 'Release'
xcWorkspacePath: '**/*.xcodeproj/project.xcworkspace'
xcodeVersion: '12' # Options: 8, 9, default, specifyPath
xcodeVersion: '13' # Options: 8, 9, default, specifyPath
args: '-derivedDataPath ./'
- task: CmdLine@2

2
samples/BindingDemo/App.xaml

@ -4,6 +4,6 @@
x:Class="BindingDemo.App">
<Application.Styles>
<FluentTheme />
<StyleInclude Source="avares://Avalonia.Themes.Default/Accents/BaseLight.xaml"/>
<StyleInclude Source="avares://Avalonia.Themes.Simple/Accents/BaseLight.xaml"/>
</Application.Styles>
</Application>

20
samples/ControlCatalog/App.xaml.cs

@ -5,7 +5,7 @@ using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Avalonia.Markup.Xaml.Styling;
using Avalonia.Styling;
using Avalonia.Themes.Default;
using Avalonia.Themes.Simple;
using Avalonia.Themes.Fluent;
using ControlCatalog.ViewModels;
@ -23,9 +23,9 @@ namespace ControlCatalog
Source = new Uri("avares://Avalonia.Controls.ColorPicker/Themes/Fluent/Fluent.xaml")
};
public static readonly StyleInclude ColorPickerDefault = new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
public static readonly StyleInclude ColorPickerSimple = new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
{
Source = new Uri("avares://Avalonia.Controls.ColorPicker/Themes/Default/Default.xaml")
Source = new Uri("avares://Avalonia.Controls.ColorPicker/Themes/Simple/Simple.xaml")
};
public static readonly StyleInclude DataGridFluent = new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
@ -33,16 +33,16 @@ namespace ControlCatalog
Source = new Uri("avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml")
};
public static readonly StyleInclude DataGridDefault = new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
public static readonly StyleInclude DataGridSimple = new StyleInclude(new Uri("avares://ControlCatalog/Styles"))
{
Source = new Uri("avares://Avalonia.Controls.DataGrid/Themes/Default.xaml")
Source = new Uri("avares://Avalonia.Controls.DataGrid/Themes/Simple.xaml")
};
public static FluentTheme Fluent = new FluentTheme(new Uri("avares://ControlCatalog/Styles"));
public static SimpleTheme Default = new SimpleTheme(new Uri("avares://ControlCatalog/Styles"));
public static SimpleTheme Simple = new SimpleTheme(new Uri("avares://ControlCatalog/Styles"));
public static Styles DefaultLight = new Styles
public static Styles SimpleLight = new Styles
{
new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
{
@ -56,10 +56,10 @@ namespace ControlCatalog
{
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/BaseLight.xaml")
},
Default
Simple
};
public static Styles DefaultDark = new Styles
public static Styles SimpleDark = new Styles
{
new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
{
@ -73,7 +73,7 @@ namespace ControlCatalog
{
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/BaseDark.xaml")
},
Default
Simple
};
public override void Initialize()

2
samples/ControlCatalog/ControlCatalog.csproj

@ -29,7 +29,7 @@
<ProjectReference Include="..\..\packages\Avalonia\Avalonia.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Controls.ColorPicker\Avalonia.Controls.ColorPicker.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Controls.DataGrid\Avalonia.Controls.DataGrid.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Simple\Avalonia.Themes.Simple.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Fluent\Avalonia.Themes.Fluent.csproj" />
<ProjectReference Include="..\MiniMvvm\MiniMvvm.csproj" />
<ProjectReference Include="..\SampleControls\ControlSamples.csproj" />

4
samples/ControlCatalog/MainView.xaml

@ -187,8 +187,8 @@
<ComboBox.Items>
<models:CatalogTheme>FluentLight</models:CatalogTheme>
<models:CatalogTheme>FluentDark</models:CatalogTheme>
<models:CatalogTheme>DefaultLight</models:CatalogTheme>
<models:CatalogTheme>DefaultDark</models:CatalogTheme>
<models:CatalogTheme>SimpleLight</models:CatalogTheme>
<models:CatalogTheme>SimpleDark</models:CatalogTheme>
</ComboBox.Items>
</ComboBox>
<ComboBox x:Name="TransparencyLevels"

20
samples/ControlCatalog/MainView.xaml.cs

@ -58,19 +58,19 @@ namespace ControlCatalog
Application.Current.Styles[1] = App.ColorPickerFluent;
Application.Current.Styles[2] = App.DataGridFluent;
}
else if (theme == CatalogTheme.DefaultLight)
else if (theme == CatalogTheme.SimpleLight)
{
App.Default.Mode = Avalonia.Themes.Default.SimpleThemeMode.Light;
Application.Current.Styles[0] = App.DefaultLight;
Application.Current.Styles[1] = App.ColorPickerDefault;
Application.Current.Styles[2] = App.DataGridDefault;
App.Simple.Mode = Avalonia.Themes.Simple.SimpleThemeMode.Light;
Application.Current.Styles[0] = App.SimpleLight;
Application.Current.Styles[1] = App.ColorPickerSimple;
Application.Current.Styles[2] = App.DataGridSimple;
}
else if (theme == CatalogTheme.DefaultDark)
else if (theme == CatalogTheme.SimpleDark)
{
App.Default.Mode = Avalonia.Themes.Default.SimpleThemeMode.Dark;
Application.Current.Styles[0] = App.DefaultDark;
Application.Current.Styles[1] = App.ColorPickerDefault;
Application.Current.Styles[2] = App.DataGridDefault;
App.Simple.Mode = Avalonia.Themes.Simple.SimpleThemeMode.Dark;
Application.Current.Styles[0] = App.SimpleDark;
Application.Current.Styles[1] = App.ColorPickerSimple;
Application.Current.Styles[2] = App.DataGridSimple;
}
}
};

10
samples/ControlCatalog/Models/CatalogTheme.cs

@ -1,14 +1,10 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ControlCatalog.Models
namespace ControlCatalog.Models
{
public enum CatalogTheme
{
FluentLight,
FluentDark,
DefaultLight,
DefaultDark
SimpleLight,
SimpleDark
}
}

9
samples/ControlCatalog/Pages/DataGridPage.xaml

@ -10,11 +10,11 @@
<TextBlock Text="{Binding}"/>
</StackPanel>
</DataTemplate>
<ControlTheme x:Key="GdpCell" TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
<Setter Property="Background" Value="{Binding Path=GDP, Mode=OneWay, Converter={StaticResource GDPConverter}}" />
</ControlTheme>
</UserControl.Resources>
<UserControl.Styles>
<Style Selector="DataGridCell.gdp">
<Setter Property="Background" Value="{Binding Path=GDP, Mode=OneWay, Converter={StaticResource GDPConverter}}" />
</Style>
<Style Selector="DataGridColumnHeader:nth-last-child(1)">
<Setter Property="FontWeight" Value="Bold" />
</Style>
@ -54,7 +54,8 @@
<DataGridTextColumn Header="Region" Binding="{CompiledBinding Region}" Width="4*" x:DataType="local:Country" />
<DataGridTextColumn Header="Population" Binding="{Binding Population}" Width="3*" />
<DataGridTextColumn Header="Area" Binding="{Binding Area}" Width="3*" />
<DataGridTextColumn Header="GDP" Binding="{Binding GDP}" Width="3*" CellStyleClasses="gdp"
<DataGridTextColumn Header="GDP" Binding="{Binding GDP}" Width="3*"
CellTheme="{StaticResource GdpCell}"
MinWidth="200"
IsVisible="{Binding #ShowGDP.IsChecked}"/>
</DataGrid.Columns>

26
samples/ControlCatalog/Pages/DialogsPage.xaml.cs

@ -195,10 +195,10 @@ namespace ControlCatalog.Pages
{
// Sync disposal of StreamWriter is not supported on WASM
#if NET6_0_OR_GREATER
await using var stream = await file.OpenWrite();
await using var stream = await file.OpenWriteAsync();
await using var reader = new System.IO.StreamWriter(stream);
#else
using var stream = await file.OpenWrite();
using var stream = await file.OpenWriteAsync();
using var reader = new System.IO.StreamWriter(stream);
#endif
await reader.WriteLineAsync(openedFileContent.Text);
@ -243,8 +243,8 @@ namespace ControlCatalog.Pages
async Task SetPickerResult(IReadOnlyCollection<IStorageItem>? items)
{
items ??= Array.Empty<IStorageItem>();
var mappedResults = items.Select(FullPathOrName).ToList();
bookmarkContainer.Text = items.FirstOrDefault(f => f.CanBookmark) is { } f ? await f.SaveBookmark() : "Can't bookmark";
bookmarkContainer.Text = items.FirstOrDefault(f => f.CanBookmark) is { } f ? await f.SaveBookmarkAsync() : "Can't bookmark";
var mappedResults = new List<string>();
if (items.FirstOrDefault() is IStorageItem item)
{
@ -267,9 +267,9 @@ Content:
if (file.CanOpenRead)
{
#if NET6_0_OR_GREATER
await using var stream = await file.OpenRead();
await using var stream = await file.OpenReadAsync();
#else
using var stream = await file.OpenRead();
using var stream = await file.OpenReadAsync();
#endif
using var reader = new System.IO.StreamReader(stream);
@ -293,7 +293,19 @@ Content:
lastSelectedDirectory = await item.GetParentAsync();
if (lastSelectedDirectory is not null)
{
mappedResults.Insert(0, "Parent: " + FullPathOrName(lastSelectedDirectory));
mappedResults.Add(FullPathOrName(lastSelectedDirectory));
}
foreach (var selectedItem in items)
{
mappedResults.Add("+> " + FullPathOrName(selectedItem));
if (selectedItem is IStorageFolder folder)
{
foreach (var innerItems in await folder.GetItemsAsync())
{
mappedResults.Add("++> " + FullPathOrName(innerItems));
}
}
}
}

3
samples/PlatformSanityChecks/App.xaml

@ -1,6 +1,5 @@
<Application xmlns="https://github.com/avaloniaui">
<Application.Styles>
<StyleInclude Source="resm:Avalonia.Themes.Default.DefaultTheme.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"/>
<SimpleTheme Mode="Light" />
</Application.Styles>
</Application>

2
samples/PlatformSanityChecks/PlatformSanityChecks.csproj

@ -7,7 +7,7 @@
<ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.Desktop\Avalonia.Desktop.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Simple\Avalonia.Themes.Simple.csproj" />
<ProjectReference Include="..\..\src\Avalonia.X11\Avalonia.X11.csproj" />
</ItemGroup>

5
samples/Previewer/App.xaml

@ -1,6 +1,5 @@
<Application xmlns="https://github.com/avaloniaui">
<Application.Styles>
<StyleInclude Source="resm:Avalonia.Themes.Default.DefaultTheme.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"/>
<SimpleTheme Mode="Light" />
</Application.Styles>
</Application>
</Application>

2
samples/Previewer/Previewer.csproj

@ -10,7 +10,7 @@
<EmbeddedResource Include="**\*.xaml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Simple\Avalonia.Themes.Simple.csproj" />
</ItemGroup>
<Import Project="..\..\build\SampleApp.props" />

16
samples/VirtualizationDemo/App.xaml

@ -1,9 +1,7 @@
<Application
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="VirtualizationDemo.App">
<Application.Styles>
<StyleInclude Source="avares://Avalonia.Themes.Default/DefaultTheme.xaml"/>
<StyleInclude Source="avares://Avalonia.Themes.Default/Accents/BaseLight.xaml"/>
</Application.Styles>
</Application>
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="VirtualizationDemo.App">
<Application.Styles>
<SimpleTheme />
</Application.Styles>
</Application>

2
samples/VirtualizationDemo/VirtualizationDemo.csproj

@ -5,7 +5,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Simple\Avalonia.Themes.Simple.csproj" />
<ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" />
<ProjectReference Include="..\MiniMvvm\MiniMvvm.csproj" />
</ItemGroup>

5
samples/interop/Direct3DInteropSample/App.paml

@ -1,6 +1,5 @@
<Application xmlns="https://github.com/avaloniaui">
<Application.Styles>
<StyleInclude Source="resm:Avalonia.Themes.Default.DefaultTheme.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"/>
<SimpleTheme Mode="Light" />
</Application.Styles>
</Application>
</Application>

2
samples/interop/Direct3DInteropSample/Direct3DInteropSample.csproj

@ -22,7 +22,7 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
<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" />

33
src/Android/Avalonia.Android/Platform/Storage/AndroidStorageItem.cs

@ -1,6 +1,7 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
@ -35,13 +36,13 @@ internal abstract class AndroidStorageItem : IStorageBookmarkItem
public bool CanBookmark => true;
public Task<string?> SaveBookmark()
public Task<string?> SaveBookmarkAsync()
{
Context.ContentResolver?.TakePersistableUriPermission(Uri, ActivityFlags.GrantWriteUriPermission | ActivityFlags.GrantReadUriPermission);
return Task.FromResult(Uri.ToString());
}
public Task ReleaseBookmark()
public Task ReleaseBookmarkAsync()
{
Context.ContentResolver?.ReleasePersistableUriPermission(Uri, ActivityFlags.GrantWriteUriPermission | ActivityFlags.GrantReadUriPermission);
return Task.CompletedTask;
@ -106,6 +107,30 @@ internal sealed class AndroidStorageFolder : AndroidStorageItem, IStorageBookmar
{
return Task.FromResult(new StorageItemProperties());
}
public async Task<IReadOnlyList<IStorageItem>> GetItemsAsync()
{
using var javaFile = new JavaFile(Uri.Path!);
// Java file represents files AND directories. Don't be confused.
var files = await javaFile.ListFilesAsync().ConfigureAwait(false);
if (files is null)
{
return Array.Empty<IStorageItem>();
}
return files
.Select(f => (file: f, uri: AndroidUri.FromFile(f)))
.Where(t => t.uri is not null)
.Select(t => t.file switch
{
{ IsFile: true } => (IStorageItem)new AndroidStorageFile(Context, t.uri!),
{ IsDirectory: true } => new AndroidStorageFolder(Context, t.uri!),
_ => null
})
.Where(i => i is not null)
.ToArray()!;
}
}
internal sealed class AndroidStorageFile : AndroidStorageItem, IStorageBookmarkFile
@ -118,10 +143,10 @@ internal sealed class AndroidStorageFile : AndroidStorageItem, IStorageBookmarkF
public bool CanOpenWrite => true;
public Task<Stream> OpenRead() => Task.FromResult(OpenContentStream(Context, Uri, false)
public Task<Stream> OpenReadAsync() => Task.FromResult(OpenContentStream(Context, Uri, false)
?? throw new InvalidOperationException("Failed to open content stream"));
public Task<Stream> OpenWrite() => Task.FromResult(OpenContentStream(Context, Uri, true)
public Task<Stream> OpenWriteAsync() => Task.FromResult(OpenContentStream(Context, Uri, true)
?? throw new InvalidOperationException("Failed to open content stream"));
private Stream? OpenContentStream(Context context, AndroidUri uri, bool isOutput)

56
src/Avalonia.Base/Controls/ResourceDictionary.cs

@ -3,6 +3,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Avalonia.Collections;
using Avalonia.Controls.Templates;
namespace Avalonia.Controls
{
@ -29,7 +30,11 @@ namespace Avalonia.Controls
public object? this[object key]
{
get => _inner?[key];
get
{
TryGetValue(key, out var value);
return value;
}
set
{
Inner[key] = value;
@ -119,6 +124,12 @@ namespace Avalonia.Controls
Owner?.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty);
}
public void AddDeferred(object key, Func<IServiceProvider?, object?> factory)
{
Inner.Add(key, new DeferredItem(factory));
Owner?.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty);
}
public void Clear()
{
if (_inner?.Count > 0)
@ -143,10 +154,8 @@ namespace Avalonia.Controls
public bool TryGetResource(object key, out object? value)
{
if (_inner is not null && _inner.TryGetValue(key, out value))
{
if (TryGetValue(key, out value))
return true;
}
if (_mergedDictionaries != null)
{
@ -165,12 +174,28 @@ namespace Avalonia.Controls
public bool TryGetValue(object key, out object? value)
{
if (_inner is not null)
return _inner.TryGetValue(key, out value);
if (_inner is not null && _inner.TryGetValue(key, out value))
{
if (value is DeferredItem deffered)
{
_inner[key] = value = deffered.Factory(null) switch
{
ITemplateResult t => t.Result,
object v => v,
_ => null,
};
}
return true;
}
value = null;
return false;
}
public IEnumerator<KeyValuePair<object, object?>> GetEnumerator()
{
return _inner?.GetEnumerator() ?? Enumerable.Empty<KeyValuePair<object, object?>>().GetEnumerator();
}
void ICollection<KeyValuePair<object, object?>>.Add(KeyValuePair<object, object?> item)
{
@ -198,12 +223,17 @@ namespace Avalonia.Controls
return false;
}
public IEnumerator<KeyValuePair<object, object?>> GetEnumerator()
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
internal bool ContainsDeferredKey(object key)
{
return _inner?.GetEnumerator() ?? Enumerable.Empty<KeyValuePair<object, object?>>().GetEnumerator();
}
if (_inner is not null && _inner.TryGetValue(key, out var result))
{
return result is DeferredItem;
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
return false;
}
void IResourceProvider.AddOwner(IResourceHost owner)
{
@ -258,5 +288,11 @@ namespace Avalonia.Controls
}
}
}
private class DeferredItem
{
public DeferredItem(Func<IServiceProvider?, object?> factory) => Factory = factory;
public Func<IServiceProvider?, object?> Factory { get; }
}
}
}

5
src/Avalonia.Base/Controls/ResourceNodeExtensions.cs

@ -132,6 +132,11 @@ namespace Avalonia.Controls
{
_target.OwnerChanged += OwnerChanged;
_owner = _target.Owner;
if (_owner is object)
{
_owner.ResourcesChanged += ResourcesChanged;
}
}
protected override void Deinitialize()

8
src/Avalonia.Base/Controls/Templates/ITemplateResult.cs

@ -0,0 +1,8 @@
namespace Avalonia.Controls.Templates
{
public interface ITemplateResult
{
public object? Result { get; }
public INameScope NameScope { get; }
}
}

3
src/Avalonia.Controls/Templates/TemplateResult.cs → src/Avalonia.Base/Controls/Templates/TemplateResult.cs

@ -1,9 +1,10 @@
namespace Avalonia.Controls.Templates
{
public class TemplateResult<T>
public class TemplateResult<T> : ITemplateResult
{
public T Result { get; }
public INameScope NameScope { get; }
object? ITemplateResult.Result => Result;
public TemplateResult(T result, INameScope nameScope)
{

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

@ -265,7 +265,7 @@ namespace Avalonia.Media
//RightToLeft
var glyphIndex = FindGlyphIndex(characterIndex);
if (GlyphClusters != null)
if (GlyphClusters != null && GlyphClusters.Count > 0)
{
if (characterIndex > GlyphClusters[0])
{

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

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Avalonia.Media.TextFormatting.Unicode;
using Avalonia.Utilities;
namespace Avalonia.Media.TextFormatting
@ -116,7 +117,30 @@ namespace Avalonia.Media.TextFormatting
length = text.Length;
}
length = CoerceLength(text, length);
return new ValueSpan<TextRunProperties>(firstTextSourceIndex, length, currentProperties);
}
private static int CoerceLength(ReadOnlySlice<char> text, int length)
{
var finalLength = 0;
var graphemeEnumerator = new GraphemeEnumerator(text);
while (graphemeEnumerator.MoveNext())
{
var grapheme = graphemeEnumerator.Current;
finalLength += grapheme.Text.Length;
if (finalLength >= length)
{
return finalLength;
}
}
return length;
}
}
}

17
src/Avalonia.Base/Media/TextFormatting/InterWordJustification.cs

@ -15,6 +15,13 @@ namespace Avalonia.Media.TextFormatting
public override void Justify(TextLine textLine)
{
var lineImpl = textLine as TextLineImpl;
if(lineImpl is null)
{
return;
}
var paragraphWidth = Width;
if (double.IsInfinity(paragraphWidth))
@ -22,12 +29,12 @@ namespace Avalonia.Media.TextFormatting
return;
}
if (textLine.NewLineLength > 0)
if (lineImpl.NewLineLength > 0)
{
return;
}
var textLineBreak = textLine.TextLineBreak;
var textLineBreak = lineImpl.TextLineBreak;
if (textLineBreak is not null && textLineBreak.TextEndOfLine is not null)
{
@ -39,7 +46,7 @@ namespace Avalonia.Media.TextFormatting
var breakOportunities = new Queue<int>();
foreach (var textRun in textLine.TextRuns)
foreach (var textRun in lineImpl.TextRuns)
{
var text = textRun.Text;
@ -68,10 +75,10 @@ namespace Avalonia.Media.TextFormatting
return;
}
var remainingSpace = Math.Max(0, paragraphWidth - textLine.WidthIncludingTrailingWhitespace);
var remainingSpace = Math.Max(0, paragraphWidth - lineImpl.WidthIncludingTrailingWhitespace);
var spacing = remainingSpace / breakOportunities.Count;
foreach (var textRun in textLine.TextRuns)
foreach (var textRun in lineImpl.TextRuns)
{
var text = textRun.Text;

26
src/Avalonia.Base/Media/TextFormatting/TextCharacters.cs

@ -38,7 +38,7 @@ namespace Avalonia.Media.TextFormatting
/// Gets a list of <see cref="ShapeableTextCharacters"/>.
/// </summary>
/// <returns>The shapeable text characters.</returns>
internal IReadOnlyList<ShapeableTextCharacters> GetShapeableCharacters(ReadOnlySlice<char> runText, sbyte biDiLevel,
internal IReadOnlyList<ShapeableTextCharacters> GetShapeableCharacters(ReadOnlySlice<char> runText, sbyte biDiLevel,
ref TextRunProperties? previousProperties)
{
var shapeableCharacters = new List<ShapeableTextCharacters>(2);
@ -65,7 +65,7 @@ namespace Avalonia.Media.TextFormatting
/// <param name="biDiLevel">The bidi level of the run.</param>
/// <param name="previousProperties"></param>
/// <returns>A list of shapeable text runs.</returns>
private static ShapeableTextCharacters CreateShapeableRun(ReadOnlySlice<char> text,
private static ShapeableTextCharacters CreateShapeableRun(ReadOnlySlice<char> text,
TextRunProperties defaultProperties, sbyte biDiLevel, ref TextRunProperties? previousProperties)
{
var defaultTypeface = defaultProperties.Typeface;
@ -76,7 +76,7 @@ namespace Avalonia.Media.TextFormatting
{
if (script == Script.Common && previousTypeface is not null)
{
if(TryGetShapeableLength(text, previousTypeface.Value, defaultTypeface, out var fallbackCount, out _))
if (TryGetShapeableLength(text, previousTypeface.Value, defaultTypeface, out var fallbackCount, out _))
{
return new ShapeableTextCharacters(text.Take(fallbackCount),
defaultProperties.WithTypeface(previousTypeface.Value), biDiLevel);
@ -86,10 +86,10 @@ namespace Avalonia.Media.TextFormatting
return new ShapeableTextCharacters(text.Take(count), defaultProperties.WithTypeface(currentTypeface),
biDiLevel);
}
if (previousTypeface is not null)
{
if(TryGetShapeableLength(text, previousTypeface.Value, defaultTypeface, out count, out _))
if (TryGetShapeableLength(text, previousTypeface.Value, defaultTypeface, out count, out _))
{
return new ShapeableTextCharacters(text.Take(count),
defaultProperties.WithTypeface(previousTypeface.Value), biDiLevel);
@ -106,12 +106,12 @@ namespace Avalonia.Media.TextFormatting
{
continue;
}
codepoint = codepointEnumerator.Current;
break;
}
//ToDo: Fix FontFamily fallback
var matchFound =
FontManager.Current.TryMatchCharacter(codepoint, defaultTypeface.Style, defaultTypeface.Weight,
@ -157,14 +157,14 @@ namespace Avalonia.Media.TextFormatting
/// <param name="script"></param>
/// <returns></returns>
protected static bool TryGetShapeableLength(
ReadOnlySlice<char> text,
Typeface typeface,
ReadOnlySlice<char> text,
Typeface typeface,
Typeface? defaultTypeface,
out int length,
out Script script)
{
length = 0;
script = Script.Unknown;
script = Script.Unknown;
if (text.Length == 0)
{
@ -182,7 +182,7 @@ namespace Avalonia.Media.TextFormatting
var currentScript = currentGrapheme.FirstCodepoint.Script;
if (currentScript != Script.Common && defaultFont != null && defaultFont.TryGetGlyph(currentGrapheme.FirstCodepoint, out _))
if (!currentGrapheme.FirstCodepoint.IsWhiteSpace && defaultFont != null && defaultFont.TryGetGlyph(currentGrapheme.FirstCodepoint, out _))
{
break;
}
@ -192,7 +192,7 @@ namespace Avalonia.Media.TextFormatting
{
break;
}
if (currentScript != script)
{
if (script is Script.Unknown || currentScript != Script.Common &&

7
src/Avalonia.Base/Media/TextFormatting/TextLayout.cs

@ -537,8 +537,13 @@ namespace Avalonia.Media.TextFormatting
/// </summary>
/// <param name="width">The collapsing width.</param>
/// <returns>The <see cref="TextCollapsingProperties"/>.</returns>
private TextCollapsingProperties GetCollapsingProperties(double width)
private TextCollapsingProperties? GetCollapsingProperties(double width)
{
if(_textTrimming == TextTrimming.None)
{
return null;
}
return _textTrimming.CreateCollapsingProperties(new TextCollapsingCreateInfo(width, _paragraphProperties.DefaultTextRunProperties));
}
}

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

@ -153,7 +153,7 @@ namespace Avalonia.Media.TextFormatting
/// <returns>
/// A <see cref="TextLine"/> value that represents a collapsed line that can be displayed.
/// </returns>
public abstract TextLine Collapse(params TextCollapsingProperties[] collapsingPropertiesList);
public abstract TextLine Collapse(params TextCollapsingProperties?[] collapsingPropertiesList);
/// <summary>
/// Create a justified line based on justification text properties.

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

@ -119,7 +119,7 @@ namespace Avalonia.Media.TextFormatting
}
/// <inheritdoc/>
public override TextLine Collapse(params TextCollapsingProperties[] collapsingPropertiesList)
public override TextLine Collapse(params TextCollapsingProperties?[] collapsingPropertiesList)
{
if (collapsingPropertiesList.Length == 0)
{
@ -128,6 +128,11 @@ namespace Avalonia.Media.TextFormatting
var collapsingProperties = collapsingPropertiesList[0];
if(collapsingProperties is null)
{
return this;
}
var collapsedRuns = collapsingProperties.Collapse(this);
if (collapsedRuns is null)
@ -171,7 +176,7 @@ namespace Avalonia.Media.TextFormatting
return GetRunCharacterHit(firstRun, FirstTextSourceIndex, 0);
}
if (distance > WidthIncludingTrailingWhitespace)
if (distance >= WidthIncludingTrailingWhitespace)
{
var lastRun = _textRuns[_textRuns.Count - 1];
@ -183,8 +188,52 @@ namespace Avalonia.Media.TextFormatting
var currentPosition = FirstTextSourceIndex;
var currentDistance = 0.0;
foreach (var currentRun in _textRuns)
for (var i = 0; i < _textRuns.Count; i++)
{
var currentRun = _textRuns[i];
if(currentRun is ShapedTextCharacters shapedRun && !shapedRun.ShapedBuffer.IsLeftToRight)
{
var rightToLeftIndex = i;
currentPosition += currentRun.TextSourceLength;
while (rightToLeftIndex + 1 <= _textRuns.Count - 1)
{
var nextShaped = _textRuns[rightToLeftIndex + 1] as ShapedTextCharacters;
if (nextShaped == null || nextShaped.ShapedBuffer.IsLeftToRight)
{
break;
}
currentPosition += nextShaped.TextSourceLength;
rightToLeftIndex++;
}
for (var j = i; i <= rightToLeftIndex; j++)
{
if(j > _textRuns.Count - 1)
{
break;
}
currentRun = _textRuns[j];
if(currentDistance + currentRun.Size.Width <= distance)
{
currentDistance += currentRun.Size.Width;
currentPosition -= currentRun.TextSourceLength;
continue;
}
characterHit = GetRunCharacterHit(currentRun, currentPosition, distance - currentDistance);
break;
}
}
if (currentDistance + currentRun.Size.Width < distance)
{
currentDistance += currentRun.Size.Width;
@ -211,12 +260,16 @@ namespace Avalonia.Media.TextFormatting
{
characterHit = shapedRun.GlyphRun.GetCharacterHitFromDistance(distance, out _);
var offset = Math.Max(0, currentPosition - shapedRun.Text.Start);
var offset = 0;
if (!shapedRun.GlyphRun.IsLeftToRight)
if (shapedRun.GlyphRun.IsLeftToRight)
{
offset = Math.Max(0, offset - shapedRun.Text.End);
offset = Math.Max(0, currentPosition - shapedRun.Text.Start);
}
//else
//{
// offset = Math.Max(0, currentPosition - shapedRun.Text.Start + shapedRun.Text.Length);
//}
characterHit = new CharacterHit(characterHit.FirstCharacterIndex + offset, characterHit.TrailingLength);
@ -255,10 +308,56 @@ namespace Avalonia.Media.TextFormatting
{
var currentRun = _textRuns[index];
if (TryGetDistanceFromCharacterHit(currentRun, characterHit, currentPosition, remainingLength,
flowDirection, out var distance, out _))
if (currentRun is ShapedTextCharacters shapedRun && !shapedRun.ShapedBuffer.IsLeftToRight)
{
var i = index;
var rightToLeftWidth = currentRun.Size.Width;
while (i + 1 <= _textRuns.Count - 1)
{
var nextRun = _textRuns[i + 1];
if (nextRun is ShapedTextCharacters nextShapedRun && !nextShapedRun.ShapedBuffer.IsLeftToRight)
{
i++;
rightToLeftWidth += nextRun.Size.Width;
continue;
}
break;
}
if(i > index)
{
while (i >= index)
{
currentRun = _textRuns[i];
rightToLeftWidth -= currentRun.Size.Width;
if (currentPosition + currentRun.TextSourceLength >= characterIndex)
{
break;
}
currentPosition += currentRun.TextSourceLength;
remainingLength -= currentRun.TextSourceLength;
i--;
}
currentDistance += rightToLeftWidth;
}
}
if (currentPosition + currentRun.TextSourceLength >= characterIndex &&
TryGetDistanceFromCharacterHit(currentRun, characterHit, currentPosition, remainingLength, flowDirection, out var distance, out _))
{
return currentDistance + distance;
return Math.Max(0, currentDistance + distance);
}
//No hit hit found so we add the full width
@ -283,7 +382,7 @@ namespace Avalonia.Media.TextFormatting
distance = currentGlyphRun.Size.Width - distance;
}
return currentDistance - distance;
return Math.Max(0, currentDistance - distance);
}
//No hit hit found so we add the full width
@ -293,7 +392,7 @@ namespace Avalonia.Media.TextFormatting
}
}
return currentDistance;
return Math.Max(0, currentDistance);
}
private static bool TryGetDistanceFromCharacterHit(
@ -442,92 +541,139 @@ namespace Avalonia.Media.TextFormatting
continue;
}
if (currentPosition + currentRun.TextSourceLength <= firstTextSourceIndex)
{
startX += currentRun.Size.Width;
currentPosition += currentRun.TextSourceLength;
continue;
}
var characterLength = 0;
var endX = startX;
var runWidth = 0.0;
TextRunBounds? currentRunBounds = null;
if (currentRun is ShapedTextCharacters currentShapedRun)
var currentShapedRun = currentRun as ShapedTextCharacters;
if (currentShapedRun != null && !currentShapedRun.ShapedBuffer.IsLeftToRight)
{
var offset = Math.Max(0, firstTextSourceIndex - currentPosition);
var rightToLeftIndex = index;
startX += currentShapedRun.Size.Width;
currentPosition += offset;
while (rightToLeftIndex + 1 <= _textRuns.Count - 1)
{
var nextShapedRun = _textRuns[rightToLeftIndex + 1] as ShapedTextCharacters;
var startIndex = currentRun.Text.Start + offset;
if (nextShapedRun == null || nextShapedRun.ShapedBuffer.IsLeftToRight)
{
break;
}
double startOffset;
double endOffset;
startX += nextShapedRun.Size.Width;
if (currentShapedRun.ShapedBuffer.IsLeftToRight)
rightToLeftIndex++;
}
if (TryGetTextRunBoundsRightToLeft(startX, firstTextSourceIndex, characterIndex, rightToLeftIndex, ref currentPosition, ref remainingLength, out currentRunBounds))
{
startOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex));
startX = currentRunBounds!.Rectangle.Left;
endX = currentRunBounds.Rectangle.Right;
endOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex + remainingLength));
runWidth = currentRunBounds.Rectangle.Width;
}
else
currentDirection = FlowDirection.RightToLeft;
}
else
{
if (currentShapedRun != null)
{
endOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex));
if (currentPosition + currentRun.TextSourceLength <= firstTextSourceIndex)
{
startX += currentRun.Size.Width;
if (currentPosition < startIndex)
currentPosition += currentRun.TextSourceLength;
continue;
}
var offset = Math.Max(0, firstTextSourceIndex - currentPosition);
currentPosition += offset;
var startIndex = currentRun.Text.Start + offset;
double startOffset;
double endOffset;
if (currentShapedRun.ShapedBuffer.IsLeftToRight)
{
startOffset = endOffset;
startOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex));
endOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex + remainingLength));
}
else
{
startOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex + remainingLength));
endOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex));
if (currentPosition < startIndex)
{
startOffset = endOffset;
}
else
{
startOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex + remainingLength));
}
}
}
startX += startOffset;
startX += startOffset;
endX += endOffset;
endX += endOffset;
var endHit = currentShapedRun.GlyphRun.GetCharacterHitFromDistance(endOffset, out _);
var startHit = currentShapedRun.GlyphRun.GetCharacterHitFromDistance(startOffset, out _);
var endHit = currentShapedRun.GlyphRun.GetCharacterHitFromDistance(endOffset, out _);
var startHit = currentShapedRun.GlyphRun.GetCharacterHitFromDistance(startOffset, out _);
characterLength = Math.Abs(endHit.FirstCharacterIndex + endHit.TrailingLength - startHit.FirstCharacterIndex - startHit.TrailingLength);
characterLength = Math.Abs(endHit.FirstCharacterIndex + endHit.TrailingLength - startHit.FirstCharacterIndex - startHit.TrailingLength);
currentDirection = currentShapedRun.ShapedBuffer.IsLeftToRight ?
FlowDirection.LeftToRight :
FlowDirection.RightToLeft;
}
else
{
if (currentPosition < firstTextSourceIndex)
currentDirection = FlowDirection.LeftToRight;
}
else
{
startX += currentRun.Size.Width;
if (currentPosition + currentRun.TextSourceLength <= firstTextSourceIndex)
{
startX += currentRun.Size.Width;
currentPosition += currentRun.TextSourceLength;
continue;
}
if (currentPosition < firstTextSourceIndex)
{
startX += currentRun.Size.Width;
}
if (currentPosition + currentRun.TextSourceLength <= characterIndex)
{
endX += currentRun.Size.Width;
characterLength = currentRun.TextSourceLength;
}
}
if (currentPosition + currentRun.TextSourceLength <= characterIndex)
if (endX < startX)
{
endX += currentRun.Size.Width;
(endX, startX) = (startX, endX);
}
characterLength = currentRun.TextSourceLength;
//Lines that only contain a linebreak need to be covered here
if (characterLength == 0)
{
characterLength = NewLineLength;
}
}
if (endX < startX)
{
(endX, startX) = (startX, endX);
}
runWidth = endX - startX;
currentRunBounds = new TextRunBounds(new Rect(startX, 0, runWidth, Height), currentPosition, characterLength, currentRun);
//Lines that only contain a linebreak need to be covered here
if (characterLength == 0)
{
characterLength = NewLineLength;
}
currentPosition += characterLength;
var runWidth = endX - startX;
var currentRunBounds = new TextRunBounds(new Rect(startX, 0, runWidth, Height), currentPosition, characterLength, currentRun);
remainingLength -= characterLength;
}
if (!MathUtilities.IsZero(runWidth) || NewLineLength > 0)
if (currentRunBounds != null && !MathUtilities.IsZero(runWidth) || NewLineLength > 0)
{
if (lastDirection == currentDirection && result.Count > 0 && MathUtilities.AreClose(currentRect.Right, startX))
{
@ -537,32 +683,26 @@ namespace Avalonia.Media.TextFormatting
textBounds.Rectangle = currentRect;
textBounds.TextRunBounds.Add(currentRunBounds);
textBounds.TextRunBounds.Add(currentRunBounds!);
}
else
{
currentRect = currentRunBounds.Rectangle;
currentRect = currentRunBounds!.Rectangle;
result.Add(new TextBounds(currentRect, currentDirection, new List<TextRunBounds> { currentRunBounds }));
}
}
currentWidth += runWidth;
currentPosition += characterLength;
if (currentPosition > characterIndex)
if (remainingLength <= 0 || currentPosition >= characterIndex)
{
break;
}
startX = endX;
lastDirection = currentDirection;
remainingLength -= characterLength;
if (remainingLength <= 0)
{
break;
}
}
return result;
@ -674,7 +814,7 @@ namespace Avalonia.Media.TextFormatting
var currentRunBounds = new TextRunBounds(new Rect(Start + startX, 0, runWidth, Height), currentPosition, characterLength, currentRun);
if(!MathUtilities.IsZero(runWidth) || NewLineLength > 0)
if (!MathUtilities.IsZero(runWidth) || NewLineLength > 0)
{
if (lastDirection == currentDirection && result.Count > 0 && MathUtilities.AreClose(currentRect.Right, Start + startX))
{
@ -692,7 +832,7 @@ namespace Avalonia.Media.TextFormatting
result.Add(new TextBounds(currentRect, currentDirection, new List<TextRunBounds> { currentRunBounds }));
}
}
}
currentWidth += runWidth;
currentPosition += characterLength;
@ -716,6 +856,107 @@ namespace Avalonia.Media.TextFormatting
return result;
}
private bool TryGetTextRunBoundsRightToLeft(double startX, int firstTextSourceIndex, int characterIndex, int runIndex, ref int currentPosition, ref int remainingLength, out TextRunBounds? textRunBounds)
{
textRunBounds = null;
for (var index = runIndex; index >= 0; index--)
{
if (TextRuns[index] is not DrawableTextRun currentRun)
{
continue;
}
if (currentPosition + currentRun.TextSourceLength <= firstTextSourceIndex)
{
startX -= currentRun.Size.Width;
currentPosition += currentRun.TextSourceLength;
continue;
}
var characterLength = 0;
var endX = startX;
if (currentRun is ShapedTextCharacters currentShapedRun)
{
var offset = Math.Max(0, firstTextSourceIndex - currentPosition);
currentPosition += offset;
var startIndex = currentRun.Text.Start + offset;
double startOffset;
double endOffset;
if (currentShapedRun.ShapedBuffer.IsLeftToRight)
{
if (currentPosition < startIndex)
{
startOffset = endOffset = 0;
}
else
{
endOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex + remainingLength));
startOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex));
}
}
else
{
endOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex));
startOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex + remainingLength));
}
startX -= currentRun.Size.Width - startOffset;
endX -= currentRun.Size.Width - endOffset;
var endHit = currentShapedRun.GlyphRun.GetCharacterHitFromDistance(endOffset, out _);
var startHit = currentShapedRun.GlyphRun.GetCharacterHitFromDistance(startOffset, out _);
characterLength = Math.Abs(startHit.FirstCharacterIndex + startHit.TrailingLength - endHit.FirstCharacterIndex - endHit.TrailingLength);
}
else
{
if (currentPosition + currentRun.TextSourceLength <= characterIndex)
{
endX -= currentRun.Size.Width;
}
if (currentPosition < firstTextSourceIndex)
{
startX -= currentRun.Size.Width;
characterLength = currentRun.TextSourceLength;
}
}
if (endX < startX)
{
(endX, startX) = (startX, endX);
}
//Lines that only contain a linebreak need to be covered here
if (characterLength == 0)
{
characterLength = NewLineLength;
}
var runWidth = endX - startX;
remainingLength -= characterLength;
currentPosition += characterLength;
textRunBounds = new TextRunBounds(new Rect(Start + startX, 0, runWidth, Height), currentPosition, characterLength, currentRun);
return true;
}
return false;
}
public override IReadOnlyList<TextBounds> GetTextBounds(int firstTextSourceIndex, int textLength)
{
if (_paragraphProperties.FlowDirection == FlowDirection.LeftToRight)
@ -1295,6 +1536,11 @@ namespace Avalonia.Media.TextFormatting
var textAlignment = _paragraphProperties.TextAlignment;
var paragraphFlowDirection = _paragraphProperties.FlowDirection;
if(textAlignment == TextAlignment.Justify)
{
textAlignment = TextAlignment.Start;
}
switch (textAlignment)
{
case TextAlignment.Start:
@ -1319,12 +1565,12 @@ namespace Avalonia.Media.TextFormatting
case TextAlignment.Center:
var start = (_paragraphWidth - width) / 2;
if(paragraphFlowDirection == FlowDirection.RightToLeft)
if (paragraphFlowDirection == FlowDirection.RightToLeft)
{
start -= (widthIncludingTrailingWhitespace - width);
}
return Math.Max(0, start);
return Math.Max(0, start);
case TextAlignment.Right:
return Math.Max(0, _paragraphWidth - widthIncludingTrailingWhitespace);

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

@ -224,7 +224,7 @@ namespace Avalonia.Media.TextFormatting.Unicode
}
/// <summary>
/// Returns <see langword="true"/> if <paramref name="value"/> is between
/// Returns <see langword="true"/> if <paramref name="cp"/> is between
/// <paramref name="lowerBound"/> and <paramref name="upperBound"/>, inclusive.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]

4
src/Avalonia.Base/Platform/IGeometryImpl.cs

@ -38,8 +38,8 @@ namespace Avalonia.Platform
/// Intersects the geometry with another geometry.
/// </summary>
/// <param name="geometry">The other geometry.</param>
/// <returns>A new <see cref="IGeometryImpl"/> representing the intersection.</returns>
IGeometryImpl Intersect(IGeometryImpl geometry);
/// <returns>A new <see cref="IGeometryImpl"/> representing the intersection or <c>null</c> when the operation failed.</returns>
IGeometryImpl? Intersect(IGeometryImpl geometry);
/// <summary>
/// Indicates whether the geometry's stroke contains the specified point.

8
src/Avalonia.Base/Platform/Storage/FileIO/BclStorageFile.cs

@ -47,22 +47,22 @@ public class BclStorageFile : IStorageBookmarkFile
return Task.FromResult<IStorageFolder?>(null);
}
public Task<Stream> OpenRead()
public Task<Stream> OpenReadAsync()
{
return Task.FromResult<Stream>(_fileInfo.OpenRead());
}
public Task<Stream> OpenWrite()
public Task<Stream> OpenWriteAsync()
{
return Task.FromResult<Stream>(_fileInfo.OpenWrite());
}
public virtual Task<string?> SaveBookmark()
public virtual Task<string?> SaveBookmarkAsync()
{
return Task.FromResult<string?>(_fileInfo.FullName);
}
public Task ReleaseBookmark()
public Task ReleaseBookmarkAsync()
{
// No-op
return Task.CompletedTask;

16
src/Avalonia.Base/Platform/Storage/FileIO/BclStorageFolder.cs

@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Security;
using System.Threading.Tasks;
using Avalonia.Metadata;
@ -43,12 +45,22 @@ public class BclStorageFolder : IStorageBookmarkFolder
return Task.FromResult<IStorageFolder?>(null);
}
public virtual Task<string?> SaveBookmark()
public Task<IReadOnlyList<IStorageItem>> GetItemsAsync()
{
var items = _directoryInfo.GetDirectories()
.Select(d => (IStorageItem)new BclStorageFolder(d))
.Concat(_directoryInfo.GetFiles().Select(f => new BclStorageFile(f)))
.ToArray();
return Task.FromResult<IReadOnlyList<IStorageItem>>(items);
}
public virtual Task<string?> SaveBookmarkAsync()
{
return Task.FromResult<string?>(_directoryInfo.FullName);
}
public Task ReleaseBookmark()
public Task ReleaseBookmarkAsync()
{
// No-op
return Task.CompletedTask;

2
src/Avalonia.Base/Platform/Storage/IStorageBookmarkItem.cs

@ -6,7 +6,7 @@ namespace Avalonia.Platform.Storage;
[NotClientImplementable]
public interface IStorageBookmarkItem : IStorageItem
{
Task ReleaseBookmark();
Task ReleaseBookmarkAsync();
}
[NotClientImplementable]

4
src/Avalonia.Base/Platform/Storage/IStorageFile.cs

@ -18,7 +18,7 @@ public interface IStorageFile : IStorageItem
/// <summary>
/// Opens a stream for read access.
/// </summary>
Task<Stream> OpenRead();
Task<Stream> OpenReadAsync();
/// <summary>
/// Returns true, if file is writeable.
@ -28,5 +28,5 @@ public interface IStorageFile : IStorageItem
/// <summary>
/// Opens stream for writing to the file.
/// </summary>
Task<Stream> OpenWrite();
Task<Stream> OpenWriteAsync();
}

11
src/Avalonia.Base/Platform/Storage/IStorageFolder.cs

@ -1,4 +1,6 @@
using Avalonia.Metadata;
using System.Collections.Generic;
using System.Threading.Tasks;
using Avalonia.Metadata;
namespace Avalonia.Platform.Storage;
@ -8,4 +10,11 @@ namespace Avalonia.Platform.Storage;
[NotClientImplementable]
public interface IStorageFolder : IStorageItem
{
/// <summary>
/// Gets the files and subfolders in the current folder.
/// </summary>
/// <returns>
/// When this method completes successfully, it returns a list of the files and folders in the current folder. Each item in the list is represented by an <see cref="IStorageItem"/> implementation object.
/// </returns>
Task<IReadOnlyList<IStorageItem>> GetItemsAsync();
}

2
src/Avalonia.Base/Platform/Storage/IStorageItem.cs

@ -44,7 +44,7 @@ public interface IStorageItem : IDisposable
/// <returns>
/// Returns identifier of a bookmark. Can be null if OS denied request.
/// </returns>
Task<string?> SaveBookmark();
Task<string?> SaveBookmarkAsync();
/// <summary>
/// Gets the parent folder of the current storage item.

5
src/Avalonia.Base/Rendering/Composition/Animations/AnimationInstanceBase.cs

@ -3,8 +3,9 @@ using System.Collections.Generic;
using Avalonia.Rendering.Composition.Expressions;
using Avalonia.Rendering.Composition.Server;
namespace Avalonia.Rendering.Composition.Animations;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Animations;
/// <summary>
/// The base class for both key-frame and expression animation instances
@ -79,4 +80,4 @@ internal abstract class AnimationInstanceBase : IAnimationInstance
_invalidated = true;
TargetObject.NotifyAnimatedValueChanged(Property);
}
}
}

11
src/Avalonia.Base/Rendering/Composition/Animations/CompositionAnimation.cs

@ -1,12 +1,11 @@
// ReSharper disable InconsistentNaming
// ReSharper disable CheckNamespace
using System;
using System.Collections.Generic;
using System.Numerics;
using Avalonia.Rendering.Composition.Expressions;
using Avalonia.Rendering.Composition.Server;
using Avalonia.Rendering.Composition.Transport;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Animations
{
@ -14,10 +13,10 @@ namespace Avalonia.Rendering.Composition.Animations
/// This is the base class for ExpressionAnimation and KeyFrameAnimation.
/// </summary>
/// <remarks>
/// Use the <see cref="CompositionObject.StartAnimation"/> method to start the animation.
/// Use the <see cref="CompositionObject.StartAnimation(string , CompositionAnimation)"/> method to start the animation.
/// Value parameters (as opposed to reference parameters which are set using <see cref="SetReferenceParameter"/>)
/// are copied and "embedded" into an expression at the time CompositionObject.StartAnimation is called.
/// Changing the value of the variable after <see cref="CompositionObject.StartAnimation"/> is called will not affect
/// Changing the value of the variable after <see cref="CompositionObject.StartAnimation(string , CompositionAnimation)"/> is called will not affect
/// the value of the ExpressionAnimation.
/// See the remarks section of ExpressionAnimation for additional information.
/// </remarks>
@ -72,4 +71,4 @@ namespace Avalonia.Rendering.Composition.Animations
}
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Animations/CompositionAnimationGroup.cs

@ -3,6 +3,8 @@ using System.Collections.Generic;
using Avalonia.Rendering.Composition.Transport;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Animations
{
public class CompositionAnimationGroup : CompositionObject, ICompositionAnimationBase
@ -21,4 +23,4 @@ namespace Avalonia.Rendering.Composition.Animations
{
}
}
}
}

6
src/Avalonia.Base/Rendering/Composition/Animations/ExpressionAnimation.cs

@ -3,6 +3,8 @@ using System;
using Avalonia.Rendering.Composition.Expressions;
using Avalonia.Rendering.Composition.Server;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Animations
{
/// <summary>
@ -14,7 +16,7 @@ namespace Avalonia.Rendering.Composition.Animations
/// This contrasts <see cref="KeyFrameAnimation"/>s, which use an interpolator to define how the animating
/// property changes over time. The mathematical equation can be defined using references to properties
/// of Composition objects, mathematical functions and operators and Input.
/// Use the <see cref="CompositionObject.StartAnimation"/> method to start the animation.
/// Use the <see cref="CompositionObject.StartAnimation(string , CompositionAnimation)"/> method to start the animation.
/// </remarks>
public class ExpressionAnimation : CompositionAnimation
{
@ -50,4 +52,4 @@ namespace Avalonia.Rendering.Composition.Animations
=> new ExpressionAnimationInstance(ParsedExpression,
targetObject, finalValue, CreateSnapshot());
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Animations/ExpressionAnimationInstance.cs

@ -3,6 +3,8 @@ using System.Collections.Generic;
using Avalonia.Rendering.Composition.Expressions;
using Avalonia.Rendering.Composition.Server;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Animations
{
@ -46,4 +48,4 @@ namespace Avalonia.Rendering.Composition.Animations
_finalValue = finalValue;
}
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Animations/IAnimationInstance.cs

@ -2,6 +2,8 @@ using System;
using Avalonia.Rendering.Composition.Expressions;
using Avalonia.Rendering.Composition.Server;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Animations
{
internal interface IAnimationInstance
@ -13,4 +15,4 @@ namespace Avalonia.Rendering.Composition.Animations
void Deactivate();
void Invalidate();
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Animations/ICompositionAnimationBase.cs

@ -2,6 +2,8 @@
using Avalonia.Rendering.Composition.Server;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Animations
{
/// <summary>
@ -12,4 +14,4 @@ namespace Avalonia.Rendering.Composition.Animations
internal void InternalOnly();
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Animations/ImplicitAnimationCollection.cs

@ -4,6 +4,8 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Avalonia.Rendering.Composition.Transport;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Animations
{
/// <summary>
@ -79,4 +81,4 @@ namespace Avalonia.Rendering.Composition.Animations
return rv;
}
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Animations/Interpolators.cs

@ -1,6 +1,8 @@
using System;
using System.Numerics;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Animations
{
/// <summary>
@ -73,4 +75,4 @@ namespace Avalonia.Rendering.Composition.Animations
public static BooleanInterpolator Instance { get; } = new BooleanInterpolator();
}
}
}

8
src/Avalonia.Base/Rendering/Composition/Animations/KeyFrameAnimation.cs

@ -2,6 +2,8 @@ using System;
using Avalonia.Animation;
using Avalonia.Animation.Easings;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Animations
{
@ -22,9 +24,9 @@ namespace Avalonia.Rendering.Composition.Animations
/// The delay behavior of the key frame animation.
/// </summary>
public AnimationDelayBehavior DelayBehavior { get; set; }
/// <summary>
/// Delay before the animation starts after <see cref="CompositionObject.StartAnimation"/> is called.
/// Delay before the animation starts after <see cref="CompositionObject.StartAnimation(string , CompositionAnimation)"/> is called.
/// </summary>
public System.TimeSpan DelayTime { get; set; }
@ -131,4 +133,4 @@ namespace Avalonia.Rendering.Composition.Animations
/// </summary>
SetToFinalValue
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Animations/KeyFrameAnimationInstance.cs

@ -4,6 +4,8 @@ using Avalonia.Animation;
using Avalonia.Rendering.Composition.Expressions;
using Avalonia.Rendering.Composition.Server;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Animations
{
/// <summary>
@ -175,4 +177,4 @@ namespace Avalonia.Rendering.Composition.Animations
base.Deactivate();
}
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Animations/KeyFrames.cs

@ -3,6 +3,8 @@ using System.Collections.Generic;
using Avalonia.Animation.Easings;
using Avalonia.Rendering.Composition.Expressions;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Animations
{
@ -86,4 +88,4 @@ namespace Avalonia.Rendering.Composition.Animations
{
public void InsertExpressionKeyFrame(float normalizedProgressKey, string value, IEasing easingFunction);
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Animations/PropertySetSnapshot.cs

@ -1,6 +1,8 @@
using System.Collections.Generic;
using Avalonia.Rendering.Composition.Expressions;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Animations
{
/// <summary>
@ -46,4 +48,4 @@ namespace Avalonia.Rendering.Composition.Animations
public ExpressionVariant GetProperty(string name) => GetParameter(name);
}
}
}

4
src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs

@ -11,6 +11,8 @@ using Avalonia.Rendering.Composition.Server;
using Avalonia.Threading;
using Avalonia.VisualTree;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition;
/// <summary>
@ -69,7 +71,7 @@ public class CompositingRenderer : IRendererWithCompositor
if(_queuedUpdate)
return;
_queuedUpdate = true;
Dispatcher.UIThread.Post(_update, DispatcherPriority.Composition);
_compositor.InvokeWhenReadyForNextCommit(_update);
}
/// <inheritdoc/>

4
src/Avalonia.Base/Rendering/Composition/CompositionDrawListVisual.cs

@ -5,6 +5,8 @@ using Avalonia.Rendering.Composition.Server;
using Avalonia.Rendering.Composition.Transport;
using Avalonia.VisualTree;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition;
@ -72,4 +74,4 @@ internal class CompositionDrawListVisual : CompositionContainerVisual
return true;
return false;
}
}
}

4
src/Avalonia.Base/Rendering/Composition/CompositionObject.cs

@ -5,6 +5,8 @@ using Avalonia.Rendering.Composition.Server;
using Avalonia.Rendering.Composition.Transport;
using Avalonia.Utilities;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition
{
/// <summary>
@ -138,4 +140,4 @@ namespace Avalonia.Rendering.Composition
writer.Write((byte)(IsDisposed ? 1 : 0));
}
}
}
}

4
src/Avalonia.Base/Rendering/Composition/CompositionPropertySet.cs

@ -5,6 +5,8 @@ using Avalonia.Rendering.Composition.Animations;
using Avalonia.Rendering.Composition.Expressions;
using Avalonia.Rendering.Composition.Transport;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition
{
/// <summary>
@ -144,4 +146,4 @@ namespace Avalonia.Rendering.Composition
TypeMismatch,
NotFound
}
}
}

4
src/Avalonia.Base/Rendering/Composition/CompositionTarget.cs

@ -4,6 +4,8 @@ using System.Numerics;
using Avalonia.Collections.Pooled;
using Avalonia.VisualTree;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition
{
/// <summary>
@ -127,4 +129,4 @@ namespace Avalonia.Rendering.Composition
Compositor.Server.Render();
}
}
}
}

17
src/Avalonia.Base/Rendering/Composition/Compositor.cs

@ -12,6 +12,8 @@ using Avalonia.Rendering.Composition.Transport;
using Avalonia.Threading;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition
{
/// <summary>
@ -31,6 +33,7 @@ namespace Avalonia.Rendering.Composition
internal IEasing DefaultEasing { get; }
private List<Action>? _invokeOnNextCommit;
private readonly Stack<List<Action>> _invokeListPool = new();
private Task? _lastBatchCompleted;
/// <summary>
/// Creates a new compositor on a specified render loop that would use a particular GPU
@ -84,7 +87,7 @@ namespace Avalonia.Rendering.Composition
if (_invokeOnNextCommit != null)
ScheduleCommitCallbacks(batch.Completed);
return batch.Completed;
return _lastBatchCompleted = batch.Completed;
}
async void ScheduleCommitCallbacks(Task task)
@ -137,5 +140,15 @@ namespace Avalonia.Rendering.Composition
_invokeOnNextCommit ??= _invokeListPool.Count > 0 ? _invokeListPool.Pop() : new();
_invokeOnNextCommit.Add(action);
}
public void InvokeWhenReadyForNextCommit(Action action)
{
if (_lastBatchCompleted == null || _lastBatchCompleted.IsCompleted)
Dispatcher.UIThread.Post(action, DispatcherPriority.Composition);
else
_lastBatchCompleted.ContinueWith(
static (_, state) => Dispatcher.UIThread.Post((Action)state!, DispatcherPriority.Composition),
action);
}
}
}
}

4
src/Avalonia.Base/Rendering/Composition/ContainerVisual.cs

@ -1,5 +1,7 @@
using Avalonia.Rendering.Composition.Server;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition
{
/// <summary>
@ -21,4 +23,4 @@ namespace Avalonia.Rendering.Composition
base.OnRootChangedCore();
}
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Drawing/CompositionDrawList.cs

@ -4,6 +4,8 @@ using Avalonia.Rendering.Composition.Server;
using Avalonia.Rendering.SceneGraph;
using Avalonia.Utilities;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Drawing;
/// <summary>
@ -99,4 +101,4 @@ internal class CompositionDrawListBuilder
if (count < Count)
_operations!.RemoveRange(count, _operations.Count - count);
}
}
}

5
src/Avalonia.Base/Rendering/Composition/Drawing/CompositionDrawingContext.cs

@ -8,6 +8,9 @@ using Avalonia.Rendering.Composition.Drawing;
using Avalonia.Rendering.SceneGraph;
using Avalonia.Utilities;
using Avalonia.VisualTree;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition;
/// <summary>
@ -388,4 +391,4 @@ internal class CompositionDrawingContext : IDrawingContextImpl, IDrawingContextW
}
return null;
}
}
}

4
src/Avalonia.Base/Rendering/Composition/ElementCompositionPreview.cs

@ -1,3 +1,5 @@
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition;
/// <summary>
@ -11,4 +13,4 @@ public static class ElementComposition
/// <param name="visual"></param>
/// <returns></returns>
public static CompositionVisual? GetElementVisual(Visual visual) => visual.CompositionVisual;
}
}

4
src/Avalonia.Base/Rendering/Composition/Enums.cs

@ -1,5 +1,7 @@
using System;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition
{
public enum CompositionBlendMode
@ -117,4 +119,4 @@ namespace Avalonia.Rendering.Composition
Fill = 1,
//TODO: Uniform, UniformToFill
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Expressions/BuiltInExpressionFfi.cs

@ -4,6 +4,8 @@ using System.Numerics;
using Avalonia.Rendering.Composition.Animations;
using Avalonia.Utilities;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Expressions
{
/// <summary>
@ -234,4 +236,4 @@ namespace Avalonia.Rendering.Composition.Expressions
public static BuiltInExpressionFfi Instance { get; } = new BuiltInExpressionFfi();
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Expressions/DelegateExpressionFfi.cs

@ -5,6 +5,8 @@ using System.Linq;
using System.Numerics;
using Avalonia.Media;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Expressions
{
/// <summary>
@ -181,4 +183,4 @@ namespace Avalonia.Rendering.Composition.Expressions
);
}
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Expressions/Expression.cs

@ -4,6 +4,8 @@ using System.Globalization;
using System.Reflection;
using Avalonia.Rendering.Composition.Server;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Expressions
{
/// <summary>
@ -374,4 +376,4 @@ namespace Avalonia.Rendering.Composition.Expressions
}
}

4
src/Avalonia.Base/Rendering/Composition/Expressions/ExpressionEvaluationContext.cs

@ -1,6 +1,8 @@
using System.Collections.Generic;
using Avalonia.Rendering.Composition.Server;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Expressions
{
internal struct ExpressionEvaluationContext
@ -29,4 +31,4 @@ namespace Avalonia.Rendering.Composition.Expressions
{
bool Call(string name, IReadOnlyList<ExpressionVariant> arguments, out ExpressionVariant result);
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Expressions/ExpressionParseException.cs

@ -1,5 +1,7 @@
using System;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Expressions
{
internal class ExpressionParseException : Exception
@ -11,4 +13,4 @@ namespace Avalonia.Rendering.Composition.Expressions
Position = position;
}
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Expressions/ExpressionParser.cs

@ -5,6 +5,8 @@ using System.Linq;
// ReSharper disable StringLiteralTypo
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Expressions
{
internal class ExpressionParser
@ -295,4 +297,4 @@ namespace Avalonia.Rendering.Composition.Expressions
}
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Expressions/ExpressionTrackedValues.cs

@ -2,6 +2,8 @@ using System.Collections;
using System.Collections.Generic;
using Avalonia.Rendering.Composition.Server;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Expressions;
internal class ExpressionTrackedObjects : IEnumerable<IExpressionObject>
@ -54,4 +56,4 @@ internal class ExpressionTrackedObjects : IEnumerable<IExpressionObject>
_stack.Push(obj);
}
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Expressions/ExpressionVariant.cs

@ -4,6 +4,8 @@ using System.Numerics;
using System.Runtime.InteropServices;
using Avalonia.Media;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Expressions
{
internal enum VariantType
@ -727,4 +729,4 @@ namespace Avalonia.Rendering.Composition.Expressions
}
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Expressions/TokenParser.cs

@ -1,6 +1,8 @@
using System;
using System.Globalization;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Expressions
{
/// <summary>
@ -256,4 +258,4 @@ namespace Avalonia.Rendering.Composition.Expressions
public override string ToString() => _s.ToString();
}
}
}

4
src/Avalonia.Base/Rendering/Composition/ICompositionTargetDebugEvents.cs

@ -1,6 +1,8 @@
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition;
internal interface ICompositionTargetDebugEvents
{
void RectInvalidated(Rect rc);
}
}

7
src/Avalonia.Base/Rendering/Composition/License.md

@ -0,0 +1,7 @@
Please note: Any code in this directory is excluded from the normal MIT license.
This code is owned and copyright to Avalonia OU.
This code may be used free of charge by any application that consumes Avalonia binary packages as a direct or indirect dependency.
Explicit permission is required for any other use outside of Avalonia applications.

4
src/Avalonia.Base/Rendering/Composition/MatrixUtils.cs

@ -1,5 +1,7 @@
using System.Numerics;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition
{
static class MatrixUtils
@ -63,4 +65,4 @@ namespace Avalonia.Rendering.Composition
matrix44.M42,
matrix44.M44);
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Server/CompositionProperty.cs

@ -1,6 +1,8 @@
using System.Collections.Generic;
using System.Threading;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Server;
internal class CompositionProperty
@ -12,4 +14,4 @@ internal class CompositionProperty
{
Id = Interlocked.Increment(ref s_NextId)
};
}
}

4
src/Avalonia.Base/Rendering/Composition/Server/DrawingContextProxy.cs

@ -6,6 +6,8 @@ using Avalonia.Rendering.Composition.Drawing;
using Avalonia.Rendering.SceneGraph;
using Avalonia.Utilities;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Server;
/// <summary>
@ -176,4 +178,4 @@ internal class CompositorDrawingContextProxy : IDrawingContextImpl, IDrawingCont
if (_impl is IDrawingContextWithAcrylicLikeSupport acrylic)
acrylic.DrawRectangle(material, rect);
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Server/FpsCounter.cs

@ -6,6 +6,8 @@ using Avalonia.Media.TextFormatting;
using Avalonia.Platform;
using Avalonia.Utilities;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Server;
/// <summary>
@ -73,4 +75,4 @@ internal class FpsCounter
offset += run.Size.Width;
}
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Server/ReadbackIndices.cs

@ -1,3 +1,5 @@
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Server
{
/// <summary>
@ -43,4 +45,4 @@ namespace Avalonia.Rendering.Composition.Server
}
}
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionContainerVisual.cs

@ -1,6 +1,8 @@
using System.Numerics;
using Avalonia.Platform;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Server
{
/// <summary>
@ -41,4 +43,4 @@ namespace Avalonia.Rendering.Composition.Server
Children = new ServerCompositionVisualCollection(Compositor);
}
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionDrawListVisual.cs

@ -7,6 +7,8 @@ using Avalonia.Rendering.Composition.Transport;
using Avalonia.Rendering.SceneGraph;
using Avalonia.Utilities;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Server;
/// <summary>
@ -72,4 +74,4 @@ internal class ServerCompositionDrawListVisual : ServerCompositionContainerVisua
return UiVisual.GetType().ToString();
}
#endif
}
}

4
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionSurface.cs

@ -1,3 +1,5 @@
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Server
{
internal abstract class ServerCompositionSurface : ServerObject
@ -6,4 +8,4 @@ namespace Avalonia.Rendering.Composition.Server
{
}
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs

@ -9,6 +9,8 @@ using Avalonia.Platform;
using Avalonia.Rendering.Composition.Transport;
using Avalonia.Utilities;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Server
{
/// <summary>
@ -218,4 +220,4 @@ namespace Avalonia.Rendering.Composition.Server
public void EnqueueAdornerUpdate(ServerCompositionVisual visual) => _adornerUpdateQueue.Enqueue(visual);
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.DirtyProperties.cs

@ -1,3 +1,5 @@
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Server;
partial class ServerCompositionVisual
@ -73,4 +75,4 @@ partial class ServerCompositionVisual
|| offset == s_IdOfSizeProperty)
_clipSizeDirty = true;
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs

@ -6,6 +6,8 @@ using Avalonia.Rendering.Composition.Animations;
using Avalonia.Rendering.Composition.Transport;
using Avalonia.Utilities;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Server
{
/// <summary>
@ -234,4 +236,4 @@ namespace Avalonia.Rendering.Composition.Server
}
}
}

7
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositor.cs

@ -6,6 +6,8 @@ using Avalonia.Rendering.Composition.Animations;
using Avalonia.Rendering.Composition.Expressions;
using Avalonia.Rendering.Composition.Transport;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Server
{
/// <summary>
@ -106,6 +108,7 @@ namespace Avalonia.Rendering.Composition.Server
private void RenderCore()
{
ApplyPendingBatches();
CompletePendingBatches();
foreach(var animation in _activeAnimations)
_animationsToUpdate.Add(animation);
@ -117,8 +120,6 @@ namespace Avalonia.Rendering.Composition.Server
foreach (var t in _activeTargets)
t.Render();
CompletePendingBatches();
}
public void AddCompositionTarget(ServerCompositionTarget target)
@ -137,4 +138,4 @@ namespace Avalonia.Rendering.Composition.Server
public void RemoveFromClock(IAnimationInstance animationInstance) =>
_activeAnimations.Remove(animationInstance);
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Server/ServerList.cs

@ -2,6 +2,8 @@ using System;
using System.Collections.Generic;
using Avalonia.Rendering.Composition.Transport;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Server
{
/// <summary>
@ -41,4 +43,4 @@ namespace Avalonia.Rendering.Composition.Server
{
}
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Server/ServerObject.cs

@ -7,6 +7,8 @@ using Avalonia.Rendering.Composition.Expressions;
using Avalonia.Rendering.Composition.Transport;
using Avalonia.Utilities;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Server
{
/// <summary>
@ -177,4 +179,4 @@ namespace Avalonia.Rendering.Composition.Server
ItselfLastChangedBy = batch.SequenceId;
}
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Transport/Batch.cs

@ -4,6 +4,8 @@ using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Transport
{
/// <summary>
@ -36,4 +38,4 @@ namespace Avalonia.Rendering.Composition.Transport
public Task Completed => _tcs.Task;
}
}
}

2
src/Avalonia.Base/Rendering/Composition/Transport/BatchStream.cs

@ -5,6 +5,8 @@ using System.Runtime.CompilerServices;
using Avalonia.Rendering.Composition.Animations;
using Avalonia.Rendering.Composition.Server;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Transport;
/// <summary>

4
src/Avalonia.Base/Rendering/Composition/Transport/BatchStreamArrayPool.cs

@ -5,6 +5,8 @@ using System.Runtime.InteropServices;
using Avalonia.Platform;
using Avalonia.Threading;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Transport;
/// <summary>
@ -153,4 +155,4 @@ internal sealed class BatchStreamMemoryPool : BatchStreamPoolBase<IntPtr>
protected override IntPtr CreateItem() => Marshal.AllocHGlobal(BufferSize);
protected override void DestroyItem(IntPtr item) => Marshal.FreeHGlobal(item);
}
}

4
src/Avalonia.Base/Rendering/Composition/Transport/BatchStreamDebugMarker.cs

@ -1,9 +1,11 @@
using System;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Transport;
internal class BatchStreamDebugMarkers
{
public static object ObjectEndMarker = new object();
public static Guid ObjectEndMagic = Guid.NewGuid();
}
}

4
src/Avalonia.Base/Rendering/Composition/Transport/ServerListProxyHelper.cs

@ -2,6 +2,8 @@ using System.Collections;
using System.Collections.Generic;
using Avalonia.Rendering.Composition.Server;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition.Transport
{
/// <summary>
@ -95,4 +97,4 @@ namespace Avalonia.Rendering.Composition.Transport
_changed = false;
}
}
}
}

4
src/Avalonia.Base/Rendering/Composition/Visual.cs

@ -3,6 +3,8 @@ using System.Numerics;
using Avalonia.Media;
using Avalonia.VisualTree;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition
{
/// <summary>
@ -53,4 +55,4 @@ namespace Avalonia.Rendering.Composition
internal virtual bool HitTest(Point point, Func<IVisual, bool>? filter) => true;
}
}
}

4
src/Avalonia.Base/Rendering/Composition/VisualCollection.cs

@ -1,6 +1,8 @@
using System;
using Avalonia.Rendering.Composition.Server;
// Special license applies <see href="https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md">License.md</see>
namespace Avalonia.Rendering.Composition
{
/// <summary>
@ -70,4 +72,4 @@ namespace Avalonia.Rendering.Composition
item.Parent = item;
}
}
}
}

3
src/Avalonia.Base/Rendering/Composition/readme.md

@ -0,0 +1,3 @@
Please note the composition renderer is not subject to the usual MIT license.
Please contact us for more details and see [License.md](https://raw.githubusercontent.com/AvaloniaUI/Avalonia/master/src/Avalonia.Base/Rendering/Composition/License.md)

2
src/Avalonia.Base/Rendering/SceneGraph/ExperimentalAcrylicNode.cs

@ -83,7 +83,7 @@ namespace Avalonia.Rendering.SceneGraph
if (Material != null)
{
var rect = Rect.Rect;
return rect.Contains(p);
return rect.ContainsExclusive(p);
}
}

4
src/Avalonia.Base/Rendering/SceneGraph/GeometryNode.cs

@ -1,9 +1,7 @@
using System;
using System.Collections.Generic;
using Avalonia.Media;
using Avalonia.Media.Immutable;
using Avalonia.Platform;
using Avalonia.VisualTree;
namespace Avalonia.Rendering.SceneGraph
{
@ -19,7 +17,7 @@ namespace Avalonia.Rendering.SceneGraph
/// <param name="brush">The fill brush.</param>
/// <param name="pen">The stroke pen.</param>
/// <param name="geometry">The geometry.</param>
/// <param name="childScenes">Child scenes for drawing visual brushes.</param>
/// <param name="aux">Auxiliary data required to draw the brush.</param>
public GeometryNode(Matrix transform,
IBrush? brush,
IPen? pen,

8
src/Avalonia.Base/Rendering/SceneGraph/GlyphRunNode.cs

@ -1,10 +1,6 @@
using System;
using System.Collections.Generic;
using Avalonia.Media;
using Avalonia.Media.Immutable;
using Avalonia.Platform;
using Avalonia.VisualTree;
namespace Avalonia.Rendering.SceneGraph
{
@ -19,7 +15,7 @@ namespace Avalonia.Rendering.SceneGraph
/// <param name="transform">The transform.</param>
/// <param name="foreground">The foreground brush.</param>
/// <param name="glyphRun">The glyph run to draw.</param>
/// <param name="childScenes">Child scenes for drawing visual brushes.</param>
/// <param name="aux">Auxiliary data required to draw the brush.</param>
public GlyphRunNode(
Matrix transform,
IBrush foreground,
@ -73,6 +69,6 @@ namespace Avalonia.Rendering.SceneGraph
}
/// <inheritdoc/>
public override bool HitTest(Point p) => Bounds.Contains(p);
public override bool HitTest(Point p) => Bounds.ContainsExclusive(p);
}
}

2
src/Avalonia.Base/Rendering/SceneGraph/ImageNode.cs

@ -109,7 +109,7 @@ namespace Avalonia.Rendering.SceneGraph
}
/// <inheritdoc/>
public override bool HitTest(Point p) => Bounds.Contains(p);
public override bool HitTest(Point p) => Bounds.ContainsExclusive(p);
public override void Dispose()
{

4
src/Avalonia.Base/Rendering/SceneGraph/LineNode.cs

@ -1,9 +1,7 @@
using System;
using System.Collections.Generic;
using Avalonia.Media;
using Avalonia.Media.Immutable;
using Avalonia.Platform;
using Avalonia.VisualTree;
namespace Avalonia.Rendering.SceneGraph
{
@ -19,7 +17,7 @@ namespace Avalonia.Rendering.SceneGraph
/// <param name="pen">The stroke pen.</param>
/// <param name="p1">The start point of the line.</param>
/// <param name="p2">The end point of the line.</param>
/// <param name="childScenes">Child scenes for drawing visual brushes.</param>
/// <param name="aux">Auxiliary data required to draw the brush.</param>
public LineNode(
Matrix transform,
IPen pen,

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

Loading…
Cancel
Save